This document contains the R workflow for processing and analysing the raw data, and generating figures for the manuscript titled “Global exposure risk of frogs to increasing environmental dryness”.

GitHub Repository: The Rmarkdown file can be downloaded from the Code drop down menu (top right).

Abbreviations

  • AI: Aridity Index
  • \(e_a\): actual vapour pressure
  • \(e_s\): saturation vapour pressure
  • EWL: Evaporative water loss
  • IUCN: International Union for Conservation of Nature
  • PDSI: Palmer Drought Severity Index
  • PRISMA: Preferred Reporting Items for Systematic Reviews and Meta-Analyses
  • RH: Relative humidity
  • \(r_i\): Relative skin resistance or resistance to water loss
  • SA: surface-area
  • SPP: Shared Socioeconomic Pathway
  • VPD: Vapour pressure deficit
  • WoS: Web of Science
  • WU: water uptake

Spatial risk

Descriptors

The following series of code is to estimate the risk of anuran amphibians to increasing aridity (Aridity Index; AI) and extreme drought (Palmer Drought Severity Index; PDSI). The AI was categorised to five categories (Humid, Dry sub-humid, Semi-arid, Arid, and Hyper-arid) and the PDSI was categorised to seven categories (Extremely moist, Very moist, Moderate moist, Normal, Moderate drought, Severe drought, Extreme drought) based on descriptions from Budyko (1961) and Palmer (1965), respectively (Table S1).

Generalised ecological types or ‘ecotype’ of each anuran species were classified based on descriptions from Moen and Wiens (2017) focusing on adult behaviour and microhabitat preferences outside the breeding season, given that many anurans breed in water but are not adapted to live in water all year (Table S2).

Table S1

Table S1 Aridity index (Budyko, 1961) and the Palmer Drought Severity Index (Palmer, 1965) categorised.

Aridity index (AI) AI value Palmer Drought Severity Index (PDSI) PDSI Value
Humid ≥ 0.65 Extremely moist ≥ 4
Dry sub-humid 0.50 – ≤ 0.65 Very moist 3 – ≤ 4
Semi-arid 0.20 – ≤ 0.50 Moderate moist 2 – ≤ 3
Arid 0.05 – ≤ 0.20 Normal -2 – ≤ 2
Hyper-arid < 0.05 Moderate drought -3 – ≤ -2
Severe drought -4 – ≤ -3
Extreme drought < -4

Table S2

Table S2 Microhabitat preference or ecotype (Moen and Wiens, 2017).

Ecotype Description
Aquatic Almost always in water.
Arboreal Ability to climb vegetation and spends a substantial amount of time above ground (e.g. forests, on top of vegetations in wetlands).
Semi-aquatic Stay near water bodies, usually permanent water (e.g. ground-level wetlands). Often observed in water and nearby vegetation.
Ground-dwelling Terrestrial only, not always near water bodies, however always in a moist environment (e.g. forest leaf litter, moist soils, scrublands, grassland). Sometimes above ground and sometimes semi-fossorial. Can be classified as broad.
Fossorial The non-breeding season is spent underground in burrows. Capable of burrowing and aestivating.
Stream-dwelling Restricted to near fast-flowing streams usually on rocks or vegetation near streams.

Species richness

Anuran (frogs and toads) distribution shape files were obtained from the International Union for Conservation of Nature’s Red List of Threatened Species (IUCN Red List; extracted on 11/01/2021). Species richness or species assemblages was defined as the sum of species in each grid cell (0.5°), based on the geographic range, and was calculated using the rasterizeIUCN and calcSR function from the from the rasterSp package. Ecotype-specific species richness was also calculated.

filedir <- "rasterSp/"

# Clean raw data
frog_dat <- read.csv(file.path(data_path, "anuran_species_list.csv")) %>%
    dplyr::select(genus:strategy, SVL_cm:binomial_tree_phylo) %>%
    dplyr::mutate(lnSVL = log(SVL_cm), lnMass = log(mass_g), lnArea = log(shape_area),
        IUCN = factor(IUCN, levels = c("Least Concern", "Near Threatened", "Vulnerable",
            "Endangered", "Critically Endangered", "Extinct")), order_name = factor(order_name),
        family_name = factor(family_name), ecotype = factor(ecotype)) %>%
    dplyr::filter(order_name == "ANURA" & ecotype != "" & IUCN != "" & IUCN != "Extinct") %>%
    droplevels()

# Convert shape files into rasters and save to file once (downloaded shape
# files 08/01/2020) only extracted distribution of native range anuran_rast <-
# rasterizeIUCN(dsn = paste0(filedir, 'ANURA/ANURA.shp'), resolution = 0.5,
# seasonal = c(1, 2), origin = 1, presence = c(1,2), save = TRUE, path =
# paste0(rasterSp_path))

# Calculate anuran richness and by ecotype The calcSR function uses a stepwise
# procedure to calculate the sum of species for each grid cell.
anuran_sr <- rasterSp::calcSR(species_names = frog_dat$binomial_IUCN, path = paste0(rasterSp_path))
aquatic_sr <- rasterSp::calcSR(species_names = frog_dat[frog_dat$ecotype == "Aquatic",
    "binomial_IUCN"], path = paste0(rasterSp_path))
arboreal_sr <- rasterSp::calcSR(species_names = frog_dat[frog_dat$ecotype == "Arboreal",
    "binomial_IUCN"], path = paste0(rasterSp_path))
fossorial_sr <- rasterSp::calcSR(species_names = frog_dat[frog_dat$ecotype == "Fossorial",
    "binomial_IUCN"], path = paste0(rasterSp_path))
ground_sr <- rasterSp::calcSR(species_names = frog_dat[frog_dat$ecotype == "Ground-dwelling",
    "binomial_IUCN"], path = paste0(rasterSp_path))
semi_aq_sr <- rasterSp::calcSR(species_names = frog_dat[frog_dat$ecotype == "Semi-aquatic",
    "binomial_IUCN"], path = paste0(rasterSp_path))
stream_sr <- rasterSp::calcSR(species_names = frog_dat[frog_dat$ecotype == "Stream-dwelling",
    "binomial_IUCN"], path = paste0(rasterSp_path))

# Convert raster to matrix then to data frame
anuran_sr_df <- raster::as.data.frame(raster::rasterToPoints(anuran_sr)) %>%
    dplyr::rename(species_n = layer)
aquatic_sr_df <- raster::as.data.frame(raster::rasterToPoints(aquatic_sr)) %>%
    dplyr::rename(aquatic_n = layer)
arboreal_sr_df <- raster::as.data.frame(raster::rasterToPoints(arboreal_sr)) %>%
    dplyr::rename(arboreal_n = layer)
fossorial_sr_df <- raster::as.data.frame(raster::rasterToPoints(fossorial_sr)) %>%
    dplyr::rename(fossorial_n = layer)
ground_sr_df <- raster::as.data.frame(raster::rasterToPoints(ground_sr)) %>%
    dplyr::rename(ground_n = layer)
semi_aq_sr_df <- raster::as.data.frame(raster::rasterToPoints(semi_aq_sr)) %>%
    dplyr::rename(semi_aq_n = layer)
stream_sr_df <- raster::as.data.frame(raster::rasterToPoints(stream_sr)) %>%
    dplyr::rename(stream_n = layer)

There were 5636 anuran species from the IUCN Red List available for the AI and PDSI analysis.

Calculate AI and PDSI

High resolution (~4 km2) global dataset on precipitation (mm/month) and potential evapotranspiration (mm/month) were obtained from Abatzoglou et al. (2018) under 1) the current climate (1970–2000), 2) an intermediate greenhouse gas emission scenario of +2°C (Shared Socioeconomic Pathway 2–4.5; SPP2–4.5), and 3) a high greenhouse gas emission or “business-as-usual” scenario of +4°C (SSP5–8.5) by 2080–2099 (Fig. S1a–f). AI was calculated as the ratio of the total precipitation relative to the potential evapotranspiration under the current climate, SPP2–4.5, and SSP5–8.5 scenario (Fig. S1g–i).

We used a self-calibrated PDSI with Penman–Monteith potential evapotranspiration representing the current climate (1970–2000) and an intermediate and high emission scenario by 2080–2099 (SSP2–4.5 and SSP5-8.5) from Zhao and Dai (2022). The SSP2–4.5 and SSP5–8.5 scenarios were based on the average of 25 CMIP6 models of precipitation, evapotranspiration, soil moisture, and runoff (Eyring et al., 2016), where the mean annual surface temperature is expected to increase by 2.7°C (2.1–3.5°C range) and 4.4°C (3.3–5.7°C range), respectively by 2080–2100 (IPCC, 2021).

# Import the downloaded files
ppt_rast <- raster::projectRaster(raster::stack(x = file.path(spatial_path, "TerraClimate19812010_ppt.nc")),
    anuran_sr)  # Precipitation year 1981-2010 - Pr (mm)
pet_rast <- raster::projectRaster(raster::stack(x = file.path(spatial_path, "TerraClimate19812010_pet.nc")),
    anuran_sr)  # Evapotranspiration 1981-2010 - ET0 (mm)

# +2C and +4C future scenarios
ppt_2C_rast <- raster::projectRaster(raster::stack(x = file.path(spatial_path, "TerraClimate2C_ppt.nc")),
    anuran_sr)
pet_2C_rast <- raster::projectRaster(raster::stack(x = file.path(spatial_path, "TerraClimate2C_pet.nc")),
    anuran_sr)
ppt_4C_rast <- raster::projectRaster(raster::stack(x = file.path(spatial_path, "TerraClimate4C_ppt.nc")),
    anuran_sr)
pet_4C_rast <- raster::projectRaster(raster::stack(x = file.path(spatial_path, "TerraClimate4C_pet.nc")),
    anuran_sr)

# Obtain mean values from 1981-2010
ppt_mean_rast <- raster::calc(ppt_rast, fun = mean, na.rm = TRUE)
pet_mean_rast <- raster::calc(pet_rast, fun = mean, na.rm = TRUE)
ppt_2C_mean_rast <- raster::calc(ppt_2C_rast, fun = mean, na.rm = TRUE)
pet_2C_mean_rast <- raster::calc(pet_2C_rast, fun = mean, na.rm = TRUE)
ppt_4C_mean_rast <- raster::calc(ppt_4C_rast, fun = mean, na.rm = TRUE)
pet_4C_mean_rast <- raster::calc(pet_4C_rast, fun = mean, na.rm = TRUE)

# Obtain mean values from 10-year monthly PDSI
PDSI_ssp245_rast <- raster::stack(x = file.path(spatial_path, "pdsisc.monthly.1900-2100.r2.5x2.5.EnsAvg25Models.TP2.ipe-2.ssp245.nc"))
PDSI_ssp585_rast <- raster::stack(x = file.path(spatial_path, "pdsisc.monthly.1900-2100.r2.5x2.5.EnsAvg25Models.TP2.ipe-2.ssp585.nc"))

PDSI_cur_rast <- raster::subset(PDSI_ssp245_rast, grep("X197.*|X198.*|X199.*", names(PDSI_ssp245_rast),
    value = T))
PDSI_2C_rast <- raster::subset(PDSI_ssp245_rast, grep("X207.*|X208.*|X209.*", names(PDSI_ssp245_rast),
    value = T))
PDSI_4C_rast <- raster::subset(PDSI_ssp585_rast, grep("X207.*|X208.*|X209.*", names(PDSI_ssp585_rast),
    value = T))

PDSI_cur_mean_rast <- raster::calc(PDSI_cur_rast, fun = mean, na.rm = TRUE)
PDSI_2C_mean_rast <- raster::calc(PDSI_2C_rast, fun = mean, na.rm = TRUE)
PDSI_4C_mean_rast <- raster::calc(PDSI_4C_rast, fun = mean, na.rm = TRUE)

# Calculate aridity index [Precipitation (ppt) / Evapotranspiration (pet)]
ai_rast <- raster::overlay(x = ppt_mean_rast, y = pet_mean_rast, fun = function(x,
    y) {
    return(x/y)
})
ai_2C_rast <- raster::overlay(x = ppt_2C_mean_rast, y = pet_2C_mean_rast, fun = function(x,
    y) {
    return(x/y)
})
ai_4C_rast <- raster::overlay(x = ppt_4C_mean_rast, y = pet_4C_mean_rast, fun = function(x,
    y) {
    return(x/y)
})

# Calculate change in PDSI Reproject intensity raster to match anuran_sr
PDSI_cur_mean_rast <- raster::projectRaster(PDSI_cur_mean_rast, anuran_sr)
PDSI_2C_mean_rast <- raster::projectRaster(PDSI_2C_mean_rast, anuran_sr)
PDSI_4C_mean_rast <- raster::projectRaster(PDSI_4C_mean_rast, anuran_sr)

PDSI_2C_diff_rast <- raster::overlay(x = PDSI_cur_mean_rast, y = PDSI_2C_mean_rast,
    fun = function(x, y) {
        return(y - x)
    })
PDSI_4C_diff_rast <- raster::overlay(x = PDSI_cur_mean_rast, y = PDSI_4C_mean_rast,
    fun = function(x, y) {
        return(y - x)
    })

# Convert raster to matrix then to data frame
ai_df <- raster::as.data.frame(raster::rasterToPoints(ai_rast))
ai_2C_df <- raster::as.data.frame(raster::rasterToPoints(ai_2C_rast))
ai_4C_df <- raster::as.data.frame(raster::rasterToPoints(ai_4C_rast))

PDSI_2C_diff_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_2C_diff_rast))
PDSI_4C_diff_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_4C_diff_rast))

# Convert aridity index into category
ai_df <- ai_df %>%
    # Recode
dplyr::mutate(category = case_when(is.infinite(layer) ~ "Humid", layer >= 0.65 ~
    "Humid", layer >= 0.5 & layer < 0.65 ~ "Dry sub-humid", layer >= 0.2 & layer <
    0.5 ~ "Semi-arid", layer >= 0.05 & layer < 0.2 ~ "Arid", layer < 0.05 ~ "Hyper-arid")) %>%
    # Convert to ordered factor
dplyr::mutate(category = factor(category, levels = c("Hyper-arid", "Arid", "Semi-arid",
    "Dry sub-humid", "Humid"), ordered = TRUE))

ai_2C_df <- ai_2C_df %>%
    # Recode
dplyr::mutate(category = case_when(is.infinite(layer) ~ "Humid", layer >= 0.65 ~
    "Humid", layer >= 0.5 & layer < 0.65 ~ "Dry sub-humid", layer >= 0.2 & layer <
    0.5 ~ "Semi-arid", layer >= 0.05 & layer < 0.2 ~ "Arid", layer < 0.05 ~ "Hyper-arid")) %>%
    # Convert to ordered factor
dplyr::mutate(category = factor(category, levels = c("Hyper-arid", "Arid", "Semi-arid",
    "Dry sub-humid", "Humid"), ordered = TRUE))

ai_4C_df <- ai_4C_df %>%
    # Recode
dplyr::mutate(category = case_when(is.infinite(layer) ~ "Humid", layer >= 0.65 ~
    "Humid", layer >= 0.5 & layer < 0.65 ~ "Dry sub-humid", layer >= 0.2 & layer <
    0.5 ~ "Semi-arid", layer >= 0.05 & layer < 0.2 ~ "Arid", layer < 0.05 ~ "Hyper-arid")) %>%
    # Convert to ordered factor
dplyr::mutate(category = factor(category, levels = c("Hyper-arid", "Arid", "Semi-arid",
    "Dry sub-humid", "Humid"), ordered = TRUE))

# Convert PDSI to category
PDSI_2C_diff_df <- PDSI_2C_diff_df %>%
    # Recode
dplyr::mutate(change_2C = case_when(layer >= 4 ~ "4", layer >= 3 & layer < 4 ~ "3",
    layer >= 2 & layer < 3 ~ "2", layer >= 1 & layer < 2 ~ "1", layer >= -1 & layer <
        1 ~ "0", layer >= -2 & layer < -1 ~ "-1", layer >= -3 & layer < -2 ~ "-2",
    layer >= -4 & layer < -3 ~ "-3", layer < -4 ~ "-4")) %>%
    # Convert to ordered factor
dplyr::mutate(change_2C = factor(change_2C, levels = c("-4", "-3", "-2", "-1", "0",
    "1", "2", "3", "4"), ordered = TRUE))

PDSI_4C_diff_df <- PDSI_4C_diff_df %>%
    # Recode
dplyr::mutate(change_4C = case_when(layer >= 4 ~ "4", layer >= 3 & layer < 4 ~ "3",
    layer >= 2 & layer < 3 ~ "2", layer >= 1 & layer < 2 ~ "1", layer >= -1 & layer <
        1 ~ "0", layer >= -2 & layer < -1 ~ "-1", layer >= -3 & layer < -2 ~ "-2",
    layer >= -4 & layer < -3 ~ "-3", layer < -4 ~ "-4")) %>%
    # Convert to ordered factor
dplyr::mutate(change_4C = factor(change_4C, levels = c("-4", "-3", "-2", "-1", "0",
    "1", "2", "3", "4"), ordered = TRUE))
# Crop and mask
world      <- sf::read_sf(file.path(spatial_path, "ne_50m_land/ne_50m_land.shp"))
world_sp   <- sf::as_Spatial(world)
world_spdf <- sp::SpatialPolygonsDataFrame(world_sp, world_sp@data) 

# Precipitation
ppt_curr_plot <- raster::as.data.frame(raster::rasterToPoints(ppt_mean_rast)) %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = layer)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_continuous_sequential(palette = "YlGnBu", lim = c(0, 650), name = "Precipitation (mm)") +
  ggtitle("Precipitation (1981-2010)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  guides(fill = guide_colourbar(barwidth = 10, barheight = 0.3, 
                                label.position = "bottom")) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10),
        legend.title = element_text(size = 8), 
        legend.position = "bottom") +
  coord_fixed(ratio = 1)  

ppt_2C_plot <- raster::as.data.frame(raster::rasterToPoints(ppt_2C_mean_rast)) %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = layer)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_continuous_sequential(palette = "YlGnBu", lim = c(0, 650)) +
  ggtitle("Precipitation (+2°C 2080-2100)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1)

ppt_4C_plot <- raster::as.data.frame(raster::rasterToPoints(ppt_4C_mean_rast)) %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = layer)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_continuous_sequential(palette = "YlGnBu", lim = c(0, 650)) +
  ggtitle("Precipitation (+4°C 2080-2100)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1)  

ppt_legend <- cowplot::get_legend(ppt_curr_plot)

ppt_prow <- cowplot::plot_grid(ppt_curr_plot + theme(legend.position = "none"), 
                   ppt_2C_plot +  theme(legend.position = "none"), 
                   ppt_4C_plot + theme(legend.position = "none"), 
                   align = "v", ncol = 3, labels = c('a', 'b', 'c')) 

ppt_plots <- cowplot::plot_grid(ppt_prow, ppt_legend, ncol = 1, rel_heights = c(1, .1))

# Evapotranspiration
pet_curr_plot <- raster::as.data.frame(raster::rasterToPoints(pet_mean_rast)) %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = layer)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_continuous_sequential(palette = "Rocket", lim = c(0, 300), name = "Evapotranspiration (mm)") +
  ggtitle("Evapotranspiration (1981-2010)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  guides(fill = guide_colourbar(barwidth = 10, barheight = 0.3, 
                                label.position = "bottom")) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10),
        legend.title = element_text(size = 8), 
        legend.position = "bottom") +
  coord_fixed(ratio = 1)  

pet_2C_plot <- raster::as.data.frame(raster::rasterToPoints(pet_2C_mean_rast)) %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = layer)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_continuous_sequential(palette = "Rocket", lim = c(0, 300)) +
  ggtitle("Evapotranspiration (+2°C 2080-2100)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1)

pet_4C_plot <- raster::as.data.frame(raster::rasterToPoints(pet_4C_mean_rast)) %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = layer)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_continuous_sequential(palette = "Rocket", lim = c(0, 300)) +
  ggtitle("Evapotranspiration (+4°C 2080-2100)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1)  

pet_legend <- cowplot::get_legend(pet_curr_plot)

pet_prow <- cowplot::plot_grid(pet_curr_plot + theme(legend.position = "none"), 
                   pet_2C_plot +  theme(legend.position = "none"), 
                   pet_4C_plot + theme(legend.position = "none"), 
                   align = "v", ncol = 3, labels = c('d', 'e', 'f')) 

pet_plots <- cowplot::plot_grid(pet_prow, pet_legend, ncol = 1, rel_heights = c(1, .1))

# Aridity Index
arid_col <- c('#8E063B', '#CB6D53', '#E99A2C', '#F5D579', 'white')
ai_curr_plot <- ggplot() +
  geom_raster(data = ai_df, aes(y = y, x = x, fill = category)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = arid_col,
                    guide = guide_legend(reverse = TRUE),
                    name = "Aridity Index") +
  ggtitle("Aridity Index (1981-2010)") +
  ylab(NULL) + xlab(NULL) +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme_void() + 
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10),
        legend.title = element_text(size = 8), 
        legend.key.size = unit(0.2, 'cm'),
        legend.position = "bottom") +
  coord_fixed(ratio = 1)

ai_2C_plot <- ggplot() +
  geom_raster(data = ai_2C_df, aes(y = y, x = x, fill = category)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = arid_col,
                    guide = guide_legend(reverse = TRUE),
                    name = "Aridity Index") +
  ggtitle("Aridity Index (+2°C 2080-2100)") +
  ylab(NULL) + xlab(NULL) +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme_void() + 
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1)

ai_4C_plot <- ggplot() +
  geom_raster(data = ai_4C_df, aes(y = y, x = x, fill = category)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = arid_col,
                    guide = guide_legend(reverse = TRUE),
                    name = "Aridity Index") +
   ggtitle("Aridity Index (+4°C 2080-2100)") +
  ylab(NULL) + xlab(NULL) +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme_void() + 
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1)

ai_legend <- cowplot::get_legend(ai_curr_plot)

ai_prow <- cowplot::plot_grid(ai_curr_plot + theme(legend.position = "none"), 
                   ai_2C_plot +  theme(legend.position = "none"), 
                   ai_4C_plot + theme(legend.position = "none"), 
                   align = "v", ncol = 3, labels = c('g', 'h', 'i')) 

ai_plots <- cowplot::plot_grid(ai_prow, ai_legend, ncol = 1, rel_heights = c(1, .1))

cowplot::plot_grid(ppt_plots, pet_plots, ai_plots, ncol = 1)

Fig. S1. Climate data used to calculate the aridity index. Mean precipitation (mm) under (a) the current scenario from 1981-2010, (b) an intermediate emission scenario of +2°C (Shared Socioeconomic Pathways 2 - 4.5; SSP2-4.5), and (c) a high emission scenario of +4°C (SSP5-8.5) by 2080-2100. Mean potential evapotranspiration (mm) under (d) the current scenario from 1981-2010, (e) an intermediate emission scenario of +2°C (SSP2-4.5), and (f) a high emission scenario of +4°C (SSP5-8.5) by 2080-2100. Calculated Aridity Index for (g) the current scenario from 1981-2010, (h) an intermediate emission scenario of +2°C (SSP2-4.5), and (i) a high emission scenario of +4°C (SSP5-8.5) by 2080-2100.

AI risk

To examine the relationship of species richness with aridity, the number of species per gird cell was overlapped with the aridity raster layer, where each grid was assigned an AI category. The change in species richness between the current and projected (either +2 or +4 °C warming) AI category was calculated as the change in AI category grids (resolution 0.5° for decimal degree coordinates) occupied by anurans relative to the future projection. A decrease indicates reduced number of species with the assigned AI category and vice versa.

# Merge aridity index, +4C and amphibian species richness
ai_sp_df <- ai_df %>% 
  dplyr::full_join(ai_2C_df, by = c("x" ,"y")) %>%
  dplyr::full_join(ai_4C_df, by = c("x" ,"y")) %>%
  dplyr::full_join(anuran_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(aquatic_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(arboreal_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(fossorial_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(ground_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(semi_aq_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(stream_sr_df, by = c("x" ,"y")) %>% 
  dplyr::rename(aridity = layer.x,
                aridity_2C = layer.y,
                aridity_4C = layer,
                category = category.x,
                category_2C = category.y,
                category_4C = category) %>%
  drop_na(category)

# Calculate grid cells occupied for current climate
ai_sp_sum <- data.frame(ai_sp_df %>% 
                          dplyr::group_by(category) %>% 
                          dplyr::summarise(species_n   = length(species_n[!is.na(species_n)]),
                                           aquatic_n   = length(aquatic_n[!is.na(aquatic_n)]),
                                           arboreal_n  = length(arboreal_n[!is.na(arboreal_n)]),
                                           fossorial_n = length(fossorial_n[!is.na(fossorial_n)]),
                                           ground_n    = length(ground_n[!is.na(ground_n)]),
                                           semi_aq_n   = length(semi_aq_n[!is.na(semi_aq_n)]),
                                           stream_n    = length(stream_n[!is.na(stream_n)]))) %>%
  dplyr::mutate(scenario = "Current",
                all_freq       = species_n / sum(species_n) * 100,
                aquatic_freq   = aquatic_n / sum(aquatic_n) * 100,
                arboreal_freq  = arboreal_n / sum(arboreal_n) * 100,
                fossorial_freq = fossorial_n / sum(fossorial_n) * 100,
                ground_freq    = ground_n / sum(ground_n) * 100,
                semi_aq_freq   = semi_aq_n / sum(semi_aq_n) * 100,
                stream_freq    = stream_n / sum(stream_n) * 100)

# Calculate grid cells occupied for future climate
ai_2C_sp_sum <- data.frame(ai_sp_df %>% 
                             dplyr::group_by(category_2C) %>% 
                             dplyr::summarise(species_n   = length(species_n[!is.na(species_n)]),
                                              aquatic_n   = length(aquatic_n[!is.na(aquatic_n)]),
                                              arboreal_n  = length(arboreal_n[!is.na(arboreal_n)]),
                                              fossorial_n = length(fossorial_n[!is.na(fossorial_n)]),
                                              ground_n    = length(ground_n[!is.na(ground_n)]),
                                              semi_aq_n   = length(semi_aq_n[!is.na(semi_aq_n)]),
                                              stream_n    = length(stream_n[!is.na(stream_n)]))) %>%
  dplyr::mutate(scenario = "SSP245",
                all_freq       = species_n / sum(species_n) * 100,
                aquatic_freq   = aquatic_n / sum(aquatic_n) * 100,
                arboreal_freq  = arboreal_n / sum(arboreal_n) * 100,
                fossorial_freq = fossorial_n / sum(fossorial_n) * 100,
                ground_freq    = ground_n / sum(ground_n) * 100,
                semi_aq_freq   = semi_aq_n / sum(semi_aq_n) * 100,
                stream_freq    = stream_n / sum(stream_n) * 100) %>% 
  dplyr::rename(category = category_2C) 

ai_4C_sp_sum <- data.frame(ai_sp_df %>% 
                             dplyr::group_by(category_4C) %>% 
                             dplyr::summarise(species_n   = length(species_n[!is.na(species_n)]),
                                              aquatic_n   = length(aquatic_n[!is.na(aquatic_n)]),
                                              arboreal_n  = length(arboreal_n[!is.na(arboreal_n)]),
                                              fossorial_n = length(fossorial_n[!is.na(fossorial_n)]),
                                              ground_n    = length(ground_n[!is.na(ground_n)]),
                                              semi_aq_n   = length(semi_aq_n[!is.na(semi_aq_n)]),
                                              stream_n    = length(stream_n[!is.na(stream_n)]))) %>%
  dplyr::mutate(scenario = "SSP585",
                all_freq       = species_n / sum(species_n) * 100,
                aquatic_freq   = aquatic_n / sum(aquatic_n) * 100,
                rboreal_freq   = arboreal_n / sum(arboreal_n) * 100,
                fossorial_freq = fossorial_n / sum(fossorial_n) * 100,
                ground_freq    = ground_n / sum(ground_n) * 100,
                semi_aq_freq   = semi_aq_n / sum(semi_aq_n) * 100,
                stream_freq    = stream_n / sum(stream_n) * 100) %>% 
  dplyr::rename(category = category_4C)

PDSI risk

With a monthly prediction of PDSI from 1950 to 2100 globally available from Zhao and Dai (2022), we categorised future drought risk in three ways: 1) an increase in drought intensity (decrease in PDSI; Fig. S2a–c), 2) an increase in drought frequency (monthly PDSI counts below -2 per year; Fig. S2d–f), and 3) an increase in drought duration (number of consecutive months with PDSI values below -2; Fig. S2g–i). Change in drought intensity (ΔPDSI[intensity]), frequency (ΔPDSI[frequency]), and duration (ΔPDSI[duration]) under a +2 or +4 °C warming scenario (2080–2100) was calculated relative to the 1970–2000 monthly climatology per gird cell (ΔPDSI = PDSI[future] – PDSI[current]). Note, the temporal resolution was limited to monthly variation as the PDSI was developed to monitor long-term meteorological drought.

# Change in PDSI intensity 
PDSI_sp_df <- anuran_sr_df %>% 
  dplyr::full_join(PDSI_2C_diff_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(PDSI_4C_diff_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(aquatic_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(arboreal_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(fossorial_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(ground_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(semi_aq_sr_df, by = c("x" ,"y")) %>% 
  dplyr::full_join(stream_sr_df, by = c("x" ,"y")) %>% 
  dplyr::rename(PDSI_2C = layer.x,
                PDSI_4C = layer.y) %>%
  drop_na(change_2C) %>%
  filter(species_n != "NA")

# Calculate grid cells occupied for current climate
PDSI_sp_2C <- data.frame(PDSI_sp_df %>% 
                           dplyr::group_by(change_2C) %>% 
                           dplyr::summarise(species_n   = length(species_n[!is.na(species_n)]),
                                            aquatic_n   = length(aquatic_n[!is.na(aquatic_n)]),
                                            arboreal_n  = length(arboreal_n[!is.na(arboreal_n)]),
                                            fossorial_n = length(fossorial_n[!is.na(fossorial_n)]),
                                            ground_n    = length(ground_n[!is.na(ground_n)]),
                                            semi_aq_n   = length(semi_aq_n[!is.na(semi_aq_n)]),
                                            stream_n    = length(stream_n[!is.na(stream_n)]))) %>%
  dplyr::mutate(all_freq       = species_n / sum(species_n) * 100,
                aquatic_freq   = aquatic_n / sum(aquatic_n) * 100,
                arboreal_freq  = arboreal_n / sum(arboreal_n) * 100,
                fossorial_freq = fossorial_n / sum(fossorial_n) * 100,
                ground_freq    = ground_n / sum(ground_n) * 100,
                semi_aq_freq   = semi_aq_n / sum(semi_aq_n) * 100,
                stream_freq    = stream_n / sum(stream_n) * 100)

PDSI_sp_4C <- data.frame(PDSI_sp_df %>% 
                           dplyr::group_by(change_4C) %>% 
                           dplyr::summarise(species_n   = length(species_n[!is.na(species_n)]),
                                            aquatic_n   = length(aquatic_n[!is.na(aquatic_n)]),
                                            arboreal_n  = length(arboreal_n[!is.na(arboreal_n)]),
                                            fossorial_n = length(fossorial_n[!is.na(fossorial_n)]),
                                            ground_n    = length(ground_n[!is.na(ground_n)]),
                                            semi_aq_n   = length(semi_aq_n[!is.na(semi_aq_n)]),
                                            stream_n    = length(stream_n[!is.na(stream_n)]))) %>%
  dplyr::mutate(all_freq       = species_n / sum(species_n) * 100,
                aquatic_freq   = aquatic_n / sum(aquatic_n) * 100,
                arboreal_freq  = arboreal_n / sum(arboreal_n) * 100,
                fossorial_freq = fossorial_n / sum(fossorial_n) * 100,
                ground_freq    = ground_n / sum(ground_n) * 100,
                semi_aq_freq   = semi_aq_n / sum(semi_aq_n) * 100,
                stream_freq    = stream_n / sum(stream_n) * 100)
# Calculate frequency of moderate to extreme drought (<-2 PDSI) per year.

# Temporal change in PDSI intensity
PDSI_2C_time_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_ssp245_rast))
PDSI_4C_time_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_ssp585_rast))

# Convert wide to long
freq_2C_df <- PDSI_2C_time_df %>%
  tidyr::pivot_longer(!c("x","y"), names_to = "dates", values_to = "PDSI") %>%
  data.frame() %>%
  tidyr::separate(dates, c("year", 'months')) %>%
  dplyr::mutate(year = as.numeric(substring(year, 2))) %>%
  dplyr::filter(year >= 1950 & year != 2100)

freq_4C_df <- PDSI_4C_time_df %>%
  tidyr::pivot_longer(!c("x","y"), names_to = "dates", values_to = "PDSI") %>%
  data.frame() %>%
  tidyr::separate(dates, c("year", 'months')) %>%
  dplyr::mutate(year = as.numeric(substring(year, 2))) %>%
  dplyr::filter(year >= 1950 & year != 2100)

# Summarise average monthly counts <-2 PDSI from 1970 to 1999 or 2080 to 2100
freq_mean_df <- freq_2C_df %>%
  dplyr::filter(year >= 1970 & year <= 1999) %>%
  dplyr::group_by(x, y, year) %>%
  dplyr::summarise(count = sum(PDSI < -2)) %>%
  dplyr::group_by(x, y) %>%
  dplyr::summarise(mean_curr = mean(count))
  
freq_2C_diff_df <- freq_2C_df %>%
  dplyr::filter(year >= 2080 & year != 2100) %>%
  dplyr::group_by(x, y, year) %>%
  dplyr::summarise(count = sum(PDSI < -2)) %>% 
  dplyr::group_by(x, y) %>%
  dplyr::summarise(mean_2C = mean(count)) %>% 
  dplyr::inner_join(freq_mean_df, by = c("x" = "x", "y" = "y")) %>%
  dplyr::mutate(diff_2C = mean_2C - mean_curr)

freq_4C_diff_df <- freq_4C_df %>%
  dplyr::filter(year >= 2080 & year != 2100) %>%
  dplyr::group_by(x, y, year) %>%
  dplyr::summarise(count = sum(PDSI < -2)) %>% 
  dplyr::group_by(x, y) %>%
  dplyr::summarise(mean_4C = mean(count)) %>% 
  dplyr::inner_join(freq_2C_diff_df, by = c("x" = "x", "y" = "y")) %>%
  dplyr::mutate(diff_4C = mean_4C - mean_curr)
# Calculate duration of moderate to extreme drought (<-2 PDSI) from 1970 to 1999
dur_curr_df <- freq_2C_df %>%
  dplyr::mutate(bin = ifelse(PDSI < -2, 1, 0)) %>%
  dplyr::filter(year >= 1970 & year <= 1999) %>%
  dplyr::group_by(x, y) %>% 
  dplyr::summarise(mean_curr = mean(rle(bin)$lengths[rle(bin)$values==1])) %>%
  replace(is.na(.), 0)

# Calculate duration of moderate to extreme drought (<-2 PDSI) from 2080 to 2100
dur_2C_df <- freq_2C_df %>%
  dplyr::mutate(bin = ifelse(PDSI < -2, 1, 0)) %>% 
  dplyr::filter(year >= 2080 & year != 2100) %>%
  dplyr::group_by(x, y) %>% 
  dplyr::summarise(mean_2C = mean(rle(bin)$lengths[rle(bin)$values==1])) %>%
  replace(is.na(.), 0) %>%
  dplyr::inner_join(dur_curr_df, by = c("x" = "x", "y" = "y")) %>%
  dplyr::mutate(diff_2C = mean_2C - mean_curr)

dur_4C_df <- freq_4C_df %>% 
  dplyr::mutate(bin = ifelse(PDSI < -2, 1, 0)) %>%
  dplyr::group_by(x, y) %>% 
  dplyr::filter(year >= 2080 & year != 2100) %>%
  dplyr::summarise(mean_4C = mean(rle(bin)$lengths[rle(bin)$values==1])) %>%
  replace(is.na(.), 0) %>%
  dplyr::inner_join(dur_2C_df, by = c("x" = "x", "y" = "y")) %>%
  dplyr::mutate(diff_4C = mean_4C - mean_curr)

The simultaneous risk of increasing drought intensity, frequency, and duration within a grid cell that are occupied by anurans (species assemblages) was calculated by converting each risk category as binary. Grid cells with a ΔPDSI[intensity] below -2 (indicating increased drought intensity relative to current scenario) were assigned a ‘1’ binary. Both ΔPDSI[frequency] and ΔPDSI[duration] were assigned a binary of ‘1’ if the grid cell has a value of 1 month or higher (indicating increase in frequency or duration relative to current scenario). The number of overlapping binaries were summed up per grid cell. Therefore, a risk factor of 2 indicate species assemblages in the grid cell are at increasing risk of two drought events. We estimated which species assemblages were at risk of experiencing drought events using an arbitrary risk factor scale (species richness × drought risk), where grid cells with high drought risk and high species richness have higher “assemblage-level risk” than grid cells with high drought risk and low species richness (low assemblage-level risk).

# Intensity
names(PDSI_2C_diff_rast) <- "delta_int_2C"
names(PDSI_4C_diff_rast) <- "delta_int_4C"

# Frequency
freq_diff_rast <- rasterFromXYZ(freq_4C_diff_df) # convert to raster
crs(freq_diff_rast) <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
freq_diff_rast <- projectRaster(freq_diff_rast, anuran_sr) # match anuran extent
freq_diff_df   <- raster::as.data.frame(raster::rasterToPoints(freq_diff_rast))

PDSI_freq_diff <- subset(freq_diff_rast, 4:5)
names(PDSI_freq_diff) <- c("delta_freq_2C", "delta_freq_4C")

# Duration
dur_diff_rast <- raster::rasterFromXYZ(dur_4C_df) # convert to raster
crs(dur_diff_rast) <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
dur_diff_rast <- raster::projectRaster(dur_diff_rast, anuran_sr) # match anuran extent
dur_diff_df <- raster::as.data.frame(raster::rasterToPoints(dur_diff_rast))

PDSI_dur_diff  <- subset(dur_diff_rast, 4:5)
names(PDSI_dur_diff) <- c("delta_dur_2C", "delta_dur_4C")

# Combine relative PDSI metrics
PDSI_risk_comb_rast <- raster::stack(PDSI_2C_diff_rast, PDSI_4C_diff_rast, PDSI_freq_diff, PDSI_dur_diff, resample(anuran_sr, PDSI_4C_diff_rast))
                             
PDSI_risk_comb_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_risk_comb_rast)) %>%
  dplyr::rename("sp_n" = layer) %>%
  dplyr::filter(!is.na(sp_n)) %>%
  dplyr::mutate(delta_int_2C_bin = ifelse(delta_int_2C < -1, 1, 0), # delta_PDSI < -1
         delta_int_4C_bin = ifelse(delta_int_4C < -1, 1, 0), # delta_PDSI < -1
         delta_freq_2C_bin = ifelse(delta_freq_2C >1, 1, 0), # month > 1
         delta_freq_4C_bin = ifelse(delta_freq_4C >1, 1, 0), # month > 1
         delta_dur_2C_bin = ifelse(delta_dur_2C >1, 1, 0), # month > 1
         delta_dur_4C_bin = ifelse(delta_dur_4C >1, 1, 0)) %>% # month > 1 
  dplyr::rowwise() %>%
  dplyr::mutate(count_2C = sum(delta_int_2C_bin, delta_freq_2C_bin, delta_dur_2C_bin, na.rm = T),
         
         count_4C = sum(delta_int_4C_bin, delta_freq_4C_bin, delta_dur_4C_bin, na.rm = T),
         risk_2C  = sp_n * count_2C,
         risk_4C  = sp_n * count_4C,
         count_2C = factor(count_2C, levels = c("3", "2", "1")),
         count_4C = factor(count_4C, levels = c("3", "2", "1"))
         )
# Combine absolute PDSI metrics
PDSI_ab_rast <- raster::stack(PDSI_cur_mean_rast, PDSI_2C_mean_rast, PDSI_4C_mean_rast, freq_diff_rast, dur_diff_rast, resample(anuran_sr, PDSI_4C_mean_rast)) 
PDSI_ab_rast_crop <- raster::mask(crop(PDSI_ab_rast, extent(world)), world) # crop 

PDSI_ab_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_ab_rast_crop)) %>%
  dplyr::rename(PDSI_cur = "layer.1",
                PDSI_2C  = "layer.2",
                PDSI_4C  = "layer.3",
                freq_cur = "mean_curr.1",
                freq_2C  = "mean_2C.1",
                freq_4C  = "mean_4C.1",
                dur_cur  = "mean_curr.2",
                dur_2C   = "mean_2C.2",
                dur_4C   = "mean_4C.2",
                sp_n     = "layer.4") %>%
  filter(sp_n != "NA")

colours_PDSI <- RColorBrewer::brewer.pal(9, "RdBu")

# Intensity
PDSI_cur_plot <- PDSI_ab_df %>%
  dplyr::mutate(PDSI_cur_cat = case_when(
    PDSI_cur >= 2 & PDSI_cur < 3 ~ '2',  
    PDSI_cur >= 1 & PDSI_cur < 2 ~ '1',  
    PDSI_cur >= -1 & PDSI_cur < 1 ~ '0'
  )) %>% 
  dplyr::mutate(PDSI_cur_cat = factor(PDSI_cur_cat,
                                levels = c('0', '1', '2'),
                                ordered = TRUE)) %>%
  filter(PDSI_cur_cat != "NA") %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = PDSI_cur_cat)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#F7F7F7", "#D1E5F0" ,"#92C5DE")) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Mean PDSI intensity (1970–2000)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

PDSI_2C_plot <- PDSI_ab_df %>%
  dplyr::mutate(PDSI_2C_cat = case_when(
    PDSI_2C >= 4 ~ "4", 
    PDSI_2C >= 3 & PDSI_2C < 4 ~ '3',
    PDSI_2C >= 2 & PDSI_2C < 3 ~ '2',  
    PDSI_2C >= 1 & PDSI_2C < 2 ~ '1',  
    PDSI_2C >= -1 & PDSI_2C < 1 ~ '0',
    PDSI_2C >= -2 & PDSI_2C < -1 ~ '-1',
    PDSI_2C >= -3 & PDSI_2C < -2 ~ '-2',
    PDSI_2C >= -4 & PDSI_2C < -3 ~ '-3',   
    PDSI_2C < -4 ~ '-4' 
  )) %>% 
  dplyr::mutate(PDSI_2C_cat = factor(PDSI_2C_cat,
                                levels = c('-4', '-3', '-2', '-1', '0', '1', '2', '3', '4'),
                                ordered = TRUE)) %>%
  filter(PDSI_2C_cat != "NA") %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = PDSI_2C_cat)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = colours_PDSI) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Mean PDSI intensity (+2°C 2080-2100)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

PDSI_4C_plot <- PDSI_ab_df %>%
  dplyr::mutate(PDSI_4C_cat = case_when(
    PDSI_4C >= 4 ~ "4", 
    PDSI_4C >= 3 & PDSI_4C < 4 ~ '3',
    PDSI_4C >= 2 & PDSI_4C < 3 ~ '2',  
    PDSI_4C >= 1 & PDSI_4C < 2 ~ '1',  
    PDSI_4C >= -1 & PDSI_4C < 1 ~ '0',
    PDSI_4C >= -2 & PDSI_4C < -1 ~ '-1',
    PDSI_4C >= -3 & PDSI_4C < -2 ~ '-2',
    PDSI_4C >= -4 & PDSI_4C < -3 ~ '-3',   
    PDSI_4C < -4 ~ '-4' 
  )) %>% 
  dplyr::mutate(PDSI_4C_cat = factor(PDSI_4C_cat,
                                levels = c('-4', '-3', '-2', '-1', '0', '1', '2', '3', '4'),
                                ordered = TRUE)) %>%
  filter(PDSI_4C_cat != "NA") %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = PDSI_4C_cat)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = colours_PDSI, name = "PDSI", guide = guide_legend(reverse = TRUE, nrow = 1)) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Mean PDSI intensity (+4°C 2080-2100)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10),
        legend.title = element_text(size = 8), 
        legend.key.height= unit(0.2, 'cm'),
        legend.key.width= unit(0.2, 'cm'),
        legend.position = "bottom") +
  coord_fixed(ratio = 1) # fixed ratio

int_legend <- cowplot::get_legend(PDSI_4C_plot)

int_prow <- cowplot::plot_grid(PDSI_cur_plot + theme(legend.position = "none"), 
                   PDSI_2C_plot +  theme(legend.position = "none"), 
                   PDSI_4C_plot + theme(legend.position = "none"), 
                   align = "v", ncol = 3, labels = c('a', 'b', 'c')) 

int_plots <- cowplot::plot_grid(int_prow, int_legend, ncol = 1, rel_heights = c(1, .1))

# Frequency
freq_cur_plot <- PDSI_ab_df %>%
  dplyr::mutate(freq_cur_cat = case_when(
    freq_cur > 0.1 & freq_cur < 1 ~ '<1'
  )) %>%
  filter(freq_cur_cat != "NA") %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = freq_cur_cat)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = "#ededed") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Mean drought frequency (1970–2000)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

freq_2C_plot <- PDSI_ab_df %>%
  dplyr::mutate(freq_2C_cat = case_when(
    freq_2C >= 10 ~ "10-12", 
    freq_2C >= 8 & freq_2C < 10 ~ '8-10',
    freq_2C >= 6 & freq_2C < 8 ~ '6-8',  
    freq_2C >= 4 & freq_2C < 6 ~ '4-6',  
    freq_2C >= 2 & freq_2C < 4 ~ '2-4',
    freq_2C >= 1 & freq_2C < 2 ~ '1-2',
    freq_2C > 0.1 & freq_2C < 1 ~ '<1'
  )) %>% 
  dplyr::mutate(freq_2C_cat = factor(freq_2C_cat,
                                     levels = c('10-12', '8-10', '6-8', '4-6', '2-4', '1-2', '<1'),
                                     ordered = TRUE)) %>%
  filter(freq_2C_cat != "NA") %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = freq_2C_cat)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7")) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Mean drought frequency (+2°C 2080-2100)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

freq_4C_plot <- PDSI_ab_df %>%
  dplyr::mutate(freq_4C_cat = case_when(
    freq_4C >= 10 ~ "10-12", 
    freq_4C >= 8 & freq_4C < 10 ~ '8-10',
    freq_4C >= 6 & freq_4C < 8 ~ '6-8',  
    freq_4C >= 4 & freq_4C < 6 ~ '4-6',  
    freq_4C >= 2 & freq_4C < 4 ~ '2-4',
    freq_4C >= 1 & freq_4C < 2 ~ '1-2',
    freq_4C > 0.1 & freq_4C < 1 ~ '<1'
  )) %>% 
  dplyr::mutate(freq_4C_cat = factor(freq_4C_cat,
                                     levels = c('10-12', '8-10', '6-8', '4-6', '2-4', '1-2', '<1'),
                                     ordered = TRUE)) %>%
  filter(freq_4C_cat != "NA") %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = freq_4C_cat)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7"), name = "Months", guide = guide_legend(reverse = TRUE, nrow = 1)) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Mean drought frequency (+4°C 2080-2100)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10),
        legend.title = element_text(size = 8), 
        legend.key.height= unit(0.2, 'cm'),
        legend.key.width= unit(0.2, 'cm'),
        legend.position = "bottom") +
  coord_fixed(ratio = 1) # fixed ratio

freq_legend <- cowplot::get_legend(freq_4C_plot)

freq_prow <- cowplot::plot_grid(freq_cur_plot + theme(legend.position = "none"), 
                   freq_2C_plot +  theme(legend.position = "none"), 
                   freq_4C_plot + theme(legend.position = "none"), 
                   align = "v", ncol = 3, labels = c('d', 'e', 'f')) 

freq_plots <- cowplot::plot_grid(freq_prow, freq_legend, ncol = 1, rel_heights = c(1, .1))


# Duration
dur_cur_plot <- PDSI_ab_df %>%
  dplyr::mutate(dur_cur_cat = case_when(
    dur_cur >= 2 & dur_cur < 4 ~ '2-4',
     dur_cur >= 1 & dur_cur < 2 ~ '1-2',
    dur_cur > 0.1 & dur_cur < 1 ~ '<1'
  )) %>% 
  dplyr::mutate(dur_cur_cat = factor(dur_cur_cat,
                                levels = c('2-4', '1-2', '<1'),
                                ordered = TRUE)) %>%
  filter(dur_cur_cat != "NA") %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = dur_cur_cat)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#FDDBC7", "#FAE9DF", "#F7F7F7")) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Mean drought duration (1970–2000)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

dur_2C_plot <- PDSI_ab_df %>%
  dplyr::mutate(dur_2C_cat = case_when(
    dur_2C >= 10 ~ ">10", 
    dur_2C >= 8 & dur_2C < 10 ~ '8-10',
    dur_2C >= 6 & dur_2C < 8 ~ '6-8',  
    dur_2C >= 4 & dur_2C < 6 ~ '4-6',  
    dur_2C >= 2 & dur_2C < 4 ~ '2-4',
    dur_2C >= 1 & dur_2C < 2 ~ '1-2',
    dur_2C > 0.1 & dur_2C < 1 ~ '<1'
  )) %>% 
  dplyr::mutate(dur_2C_cat = factor(dur_2C_cat,
                                levels = c('>10', '8-10', '6-8', '4-6', '2-4', '1-2', '<1'),
                                ordered = TRUE))%>%
  filter(dur_2C_cat != "NA") %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = dur_2C_cat)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7")) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Mean drought duration (+2°C 2080-2100)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

dur_4C_plot <- PDSI_ab_df %>%
  dplyr::mutate(dur_4C_cat = case_when(
    dur_4C >= 10 ~ ">10", 
    dur_4C >= 8 & dur_4C < 10 ~ '8-10',
    dur_4C >= 6 & dur_4C < 8 ~ '6-8',  
    dur_4C >= 4 & dur_4C < 6 ~ '4-6',  
    dur_4C >= 2 & dur_4C < 4 ~ '2-4',
    dur_4C >= 1 & dur_4C < 4 ~ '1-2',
    dur_4C > 0.1 & dur_4C < 1 ~ '<1'
  )) %>% 
  dplyr::mutate(dur_4C_cat = factor(dur_4C_cat,
                                levels = c('>10', '8-10', '6-8', '4-6', '2-4', '1-2', '<1'),
                                ordered = TRUE)) %>%
  filter(dur_4C_cat != "NA") %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = dur_4C_cat)) +
  geom_polygon(data = world_spdf, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7"), name = "Months", guide = guide_legend(reverse = TRUE, nrow = 1)) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Mean drought duration (+4°C 2080-2100)") +
  scale_y_continuous(limits = c(-60, 90), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-180, 180), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10),
        legend.title = element_text(size = 8), 
        legend.key.size = unit(0.2, 'cm'),
        legend.position = "bottom") +
  coord_fixed(ratio = 1) # fixed ratio

dur_legend <- cowplot::get_legend(dur_4C_plot)

dur_prow <- cowplot::plot_grid(dur_cur_plot + theme(legend.position = "none"), 
                   dur_2C_plot +  theme(legend.position = "none"), 
                   dur_4C_plot + theme(legend.position = "none"), 
                   align = "v", ncol = 3, labels = c('g', 'h', 'i')) 

dur_plots <- cowplot::plot_grid(dur_prow, dur_legend, ncol = 1, rel_heights = c(1, .1))


cowplot::plot_grid(int_plots, freq_plots, dur_plots, ncol = 1)

Fig. S2. Mean monthly Palmer Drought Severity Index (PDSI) self-calibrated with Penman–Monteith potential evapotranspiration from (a) 1970–2000, and from 2080-2100 under (b) under an intermediate emission scenario of +2°C (Shared Socioeconomic Pathways 2 - 4.5; SSP2-4.5), and (c) under a high emission scenario of +4°C (SSP5-8.5). Mean yearly frequency of moderate to extreme drought (PDSI < -2) from (d) 1970–2000, and from 2080-2100 (e) under an intermediate emission scenario of +2°C (SSP2-4.5), and (f) under a high emission scenario of +4°C (SSP5-8.5). Mean duration of moderate to extreme drought (PDSI < -2) from (g) 1970–2000, and from 2080-2100 (h) under an intermediate emission scenario of +2°C (SSP2-4.5), and (i) under a high emission scenario of +4°C (SSP5-8.5).

Summary

Ecotype AI distribution

Mean ± s.d. aridity index occupied by different anuran ecotypes.

Ecotype AI (mean ± s.d.)
Stream-dwelling 1.46 ± 0.62
Arboreal 1.01 ± 0.62
Semi-aquatic 1.01 ± 0.58
Aquatic 0.98 ± 0.61
Ground-dwelling 0.89 ± 0.64
Fossorial 0.80 ± 0.61

2°C AI risk

Percent change in aridity by 2080–2100 (+ 2°C) relative to current climate (1981–2010) for all anurans and also by ecotype.

Ecotype All (%) Aquatic 2°C (%) Arboreal 2°C (%) Fossorial 2°C(%) Ground-dwelling 2°C (%) Semi-aquatic 2°C (%) Stream-dwelling 2°C (%)
Hyper-arid -2.3 13.1 -15.2 -37.25 -2.0 4.7 -18.2
Arid 5.0 10.2 6.3 9.90 4.9 10.0 26.8
Semi-arid 1.4 2.1 1.5 0.75 1.6 1.1 13.9
Dry sub-humid 2.5 11.1 9.5 -3.67 8.4 2.8 10.4
Humid -1.4 -3.2 -2.2 -2.00 -2.4 -1.3 -1.3

4°C AI risk

Percent change in aridity by 2080–2100 (+ 4°C) relative to current climate (1981–2010) for all anurans and also by ecotype.

Ecotype All (%) Aquatic 2°C (%) Arboreal 2°C (%) Fossorial 2°C(%) Ground-dwelling 2°C (%) Semi-aquatic 2°C (%) Stream-dwelling 2°C (%)
Hyper-arid 3.0 28.3 -4.3 -13.7 3.1 11.6 -9.1
Arid 13.2 33.0 20.6 23.1 13.5 27.0 43.7
Semi-arid 8.4 11.6 14.3 4.5 8.8 10.8 53.8
Dry sub-humid 9.0 25.2 16.6 -3.5 16.0 11.6 23.9
Humid -5.8 -9.8 -7.6 -7.5 -7.6 -5.7 -3.8

2°C PDSI risk

Percent change in drought intensity (ΔPDSI), drought frequency (ΔFrequency), and drought duration (ΔDuration) by 2080–2099 (+ 2°C scenario) relative to current climate (1970–2000) in grid cells occupied by anurans and also by ecotype.

ΔPDSI All (%) Aquatic (%) Arboreal (%) Fossorial (%) Ground-dwelling (%) Semi-aquatic (%) Stream-dwelling (%)
-4 0.01 0.00 0.00 0.00 0.00 0.01 0.00
-3 0.15 0.00 0.00 0.00 0.06 0.19 0.00
-2 2.00 4.22 3.35 4.35 2.18 2.46 5.48
-1 18.55 33.52 28.74 27.06 20.99 21.74 26.88
0 71.05 54.90 55.68 54.07 68.60 66.72 60.07
1 6.40 5.19 8.86 9.94 6.05 6.84 6.19
2 1.59 1.83 2.90 3.99 1.84 1.74 1.23
3 0.25 0.34 0.48 0.59 0.29 0.30 0.14
ΔFrequency (months) All (%) Aquatic (%) Arboreal (%) Fossorial (%) Ground-dwelling (%) Semi-aquatic (%) Stream-dwelling (%)
10-12 0.14 0.00 0.00 0.00 0.05 0.17 0.00
8-10 0.22 0.03 0.06 0.03 0.18 0.25 0.20
6-8 0.61 0.78 0.70 0.79 0.60 0.70 0.86
4-6 2.15 3.86 3.40 3.01 2.33 2.26 3.71
2-4 12.25 21.14 19.23 16.82 13.42 13.75 26.57
1-2 16.90 24.28 17.56 18.39 18.51 18.26 10.49
0-1 56.26 42.56 46.21 46.64 53.17 54.34 48.46
-0-1 11.45 7.36 12.84 14.32 11.73 10.27 9.72
ΔDuration (months) All (%) Aquatic (%) Arboreal (%) Fossorial (%) Ground-dwelling (%) Semi-aquatic (%) Stream-dwelling (%)
>10 0.27 0.00 0.00 0.00 0.10 0.34 0.00
8-10 0.06 0.00 0.00 0.00 0.04 0.06 0.01
6-8 0.11 0.00 0.00 0.00 0.09 0.11 0.07
4-6 0.47 0.67 0.61 0.75 0.48 0.55 0.57
2-4 7.79 14.23 11.94 10.29 8.61 9.21 15.78
1-2 38.11 34.96 29.11 23.85 38.14 39.87 27.17
0-1 39.57 41.03 42.90 47.79 38.34 37.31 44.53
-0-1 12.98 8.46 14.49 16.04 13.47 11.90 11.82
-1-2 0.64 0.65 0.95 1.28 0.71 0.64 0.04

4°C PDSI risk

Percent change in drought intensity (ΔPDSI), frequency (ΔFrequency), and duration (ΔDuration) by 2080–2099 (+ 4°C scenario) relative to current climate (1970–2000) in grid cells occupied by anurans and by ecotype.

ΔPDSI All (%) Aquatic (%) Arboreal (%) Fossorial (%) Ground-dwelling (%) Semi-aquatic (%) Stream-dwelling (%)
-4 0.83 1.3 0.96 1.3 0.74 1.0 1.9
-3 4.44 9.9 7.80 9.6 5.04 5.4 15.2
-2 10.88 17.7 16.15 11.0 12.26 12.6 14.4
-1 22.33 26.6 19.04 25.3 24.78 23.6 12.2
0 44.62 31.9 37.41 32.8 42.33 40.2 41.6
1 9.63 4.5 6.79 5.6 6.97 9.5 6.8
2 2.94 2.2 4.17 4.3 2.87 2.9 3.4
3 1.39 1.9 2.30 2.4 1.60 1.4 1.9
4 2.94 3.9 5.38 7.7 3.41 3.4 2.5
ΔFrequency (months) All (%) Aquatic (%) Arboreal (%) Fossorial (%) Ground-dwelling (%) Semi-aquatic (%) Stream-dwelling (%)
10-12 1.6 2.2 1.9 2.0 1.6 1.9 2.9
8-10 4.9 9.3 7.7 7.3 5.4 5.3 11.6
6-8 7.0 10.9 10.0 8.4 7.8 7.5 11.9
4-6 14.0 17.1 13.2 9.9 15.7 15.4 10.7
2-4 22.8 22.8 17.9 25.1 24.1 22.9 12.4
1-2 12.1 11.2 12.9 12.1 11.4 11.4 16.2
0-1 30.1 20.3 26.5 22.8 25.6 28.4 29.4
-0-1 7.6 6.2 9.8 12.3 8.4 7.2 4.8
ΔDuration (months) All (%) Aquatic (%) Arboreal (%) Fossorial (%) Ground-dwelling (%) Semi-aquatic (%) Stream-dwelling (%)
>10 2.53 2.8 2.6 2.6 2.46 2.84 3.90
8-10 1.02 2.0 1.6 1.6 1.14 1.14 2.16
6-8 2.33 4.0 3.7 3.1 2.60 2.50 4.47
4-6 11.07 16.6 13.5 9.0 12.48 12.55 14.75
2-4 24.82 23.0 19.5 18.4 26.38 26.19 17.99
1-2 23.42 22.9 20.5 23.1 20.52 22.95 19.89
0-1 25.18 21.7 26.0 26.7 23.70 22.79 29.51
-0-1 8.83 5.8 11.0 13.5 9.79 8.12 7.27
-1-2 0.81 1.2 1.4 1.9 0.93 0.93 0.05

Dataset

Load and clean the raw dataset raw_data.csv.

# Load and clean raw data
raw_dat <- read.csv(file.path(data_path, "raw_data.csv")) %>%
  dplyr::select(study_ID:unit, r_s_est, calculated) %>%
  dplyr::mutate(ecotype  = factor(ecotype),
         family   = factor(family),
         origin   = factor(origin),
         strategy = factor(case_when(strategy == "" ~ "none", TRUE ~ as.character(strategy))),
         strategy = fct_relevel(strategy, "none", "water-proof", "cocoon", "hollow"),
         trait    = factor(trait),
         response = factor(response),
         lnMass   = log(mean_mass_g),
         lnFlow   = log(airflow_cm_s + 1),
         es_kPa   = ifelse(trait == "water loss", 0.611 * exp(2500000 / 461.5 * (1 / 273 - 1 / (trt_temp + 273.15))), NA), # saturation vapor pressure (kPa) at a given temperature
         ea_kPa   = ifelse(trait == "water loss", RH_perc * es_kPa / 100, NA), # actual vapor pressure (kPa)
         VPD_kPa  = es_kPa - ea_kPa,
         lnVPD    = log(VPD_kPa)) %>%
  dplyr::filter(species_phylo != "") # remove rows with no species

ewl_dat <- raw_dat %>%
  dplyr::filter(response == "evaporative water loss" & !is.na(unit_corrected_mean)) %>%
  dplyr::mutate(mg_h_mean = unit_corrected_mean * dors_SA_cm2,
                mg_h_sd   = unit_corrected_sd * dors_SA_cm2,    
                lnMean    = log(mg_h_mean),
                v         = mg_h_sd^2 / sample_size, # sampling variance (v)
                sei       = sqrt(v), # standard error (SE)
                inv       = 1 / sei, # precision (inverse of SE) )
                w         = 1 / v, # weight (inverse of variance) 
                h_70      = (mean_mass_g - (mean_mass_g * 0.7)) / (mg_h_mean * 0.001)) 

resist_dat <- raw_dat %>%
  dplyr::filter(!is.na(r_s_est)) %>%
  dplyr::mutate(lnMean = log(r_s_est + 1))

wu_dat <- raw_dat %>%
  dplyr::filter(trait == "water gain" & !is.na(unit_corrected_mean)) %>%
  dplyr::mutate(mg_h_mean = unit_corrected_mean * vent_SA_cm2,
                mg_h_sd   = unit_corrected_sd * vent_SA_cm2,
                lnMean    = log(mg_h_mean),
                v         = mg_h_sd^2 / sample_size, # sampling variance (v)
                sei       = sqrt(v), # standard error (SE)
                inv       = 1 / sei) # precision (inverse of SE)

#ewl_dat %>%
  #group_by(strategy) %>%
  #summarise(mean = mean(h_70, na.rm = TRUE))

There are 238 species with data on evaporative water loss (102 studies), 224 species with skin resistance data (81 studies), and 121 species with water uptake data (51 studies). We used the evaporative water loss to analyse differences between ecotype as there are more species represented compared to the skin resistance data. There were three species that were excluded from the analysis because they were not listed in the IUCN Red List and were not present in the phylogenetic tree from Jetz and Pyron (2018): Brachycephalus pitanga, Elachistocleis cesarii, and Leptodactylus luctator.

Geographical bias in hydroregulation studies

Fig. S4. Spatial distribution of hydroregulation studies using wild caught anurans (study n = 113). 19 studies used captive raised anurans. There are large regions around central Africa and Eurasia with high amphibian diversity, but no hydrological studies conducted (Fig. 1b).


Prepare phylogeny for analysis

The phylogeny was obtained from Jetz and Pyron (2018) comprising of 7,238 species. The tree was pruned to match the 256 species extracted for the subsequent analysis.

# Load tree
phylo_tree <- ape::read.tree(file.path(data_path, "amph_shl_new_Consensus_7238.tre"))

# Pruning data and phylogeny
tree_tip_label <- phylo_tree$tip.label # extract tree tip names
sp_list        <- raw_dat$species_phylo # extract species name from mean data
pruned_tree    <- ape::drop.tip(phylo_tree, setdiff(phylo_tree$tip.label, sp_list)) # prune phylo_tree to keep species from the raw data
pruned_tree    <- phytools::force.ultrametric(pruned_tree, method = "extend") # ultrametricize the tree
phylo_cor      <- vcv(pruned_tree, cor = T)

setdiff(raw_dat$species_phylo, rownames(phylo_cor))
setdiff(rownames(phylo_cor), raw_dat$species_phylo)

#ape::is.ultrametric(pruned_tree)

Analysis

The original model incorporated origin (lab-raised or wild-caught) and whether the bladder was void of urine prior to the experiment. However, the model’s bulk effective samples size (ESS) was too low, indicating posterior means and medians may be unreliable. Since origin and whether the bladder was emptied did not influence \(r_i\), they were excluded in the final model. For transparency, on average, wild-caught anurans had, on average, higher \(r_i\) relative to lab-raised anurans (0.08 [-0.47:0.31]), and anurans with their bladder voided of urine had higher \(r_i\) (0.17 [-0.59: 0.25]). However there is substantial variability between the wild-caught and lab-raised groups, and whether anurans with their bladder voided or not.

# options(brms.backend = 'cmdstanr') # Error from using Rstans 'error in
# unserialize(socklist[[n]]) : error reading from connection'. Used cmdstanr
# around it.

priors <- c(prior(normal(0, 3), "b"), prior(normal(0, 3), "Intercept"), prior(student_t(3,
    0, 10), "sd"), prior(student_t(3, 0, 10), "sigma"))

ri_model <- brms::brm(lnMean ~ ecotype + strategy + lnMass + lnVPD + lnFlow + (1 |
    study_ID) + (1 + lnMass | species_iucn) + (1 | gr(species_phylo, cov = phylo)),
    data = resist_dat, family = gaussian(), data2 = list(phylo = phylo_cor), prior = priors,
    chains = 4, cores = 4, iter = 5000, warmup = 2500, control = list(adapt_delta = 0.99,
        max_treedepth = 15))

wu_model <- brms::brm(lnMean ~ ecotype + lnMass + trt_temp + hydration + origin +
    (1 | study_ID) + (1 + lnMass | species_iucn) + (1 | gr(species_phylo, cov = phylo)),
    data = wu_dat %>%
        dplyr::group_by(ecotype) %>%
        dplyr::filter(n() >= 5), family = gaussian(), data2 = list(phylo = phylo_cor),
    prior = priors, chains = 4, cores = 4, iter = 5000, warmup = 2500, control = list(adapt_delta = 0.99,
        max_treedepth = 15))

Fig. S5. Scatterplots of the observed data (y) vs the average simulated data (yrep) from the posterior predictive distribution for the (a) resistance to water loss model, and (b) the water uptake model. Dashed line represents a slope of 1.

Model output

Table S3 - \(r_i\) model

Table S3. Mean parameter estimates, estimate error, and 95% Bayesian credible intervals for the \(r_i\) model, which includes the intercept (\(\beta_0\)), ecotype, strategy, the natural logarithm of body mass (lnMass), the natural logarithm of vapour pressure deficit (lnVPD), and the natural logarithm of the experimental flow rate (lnFlow). Group-level effects include the standard deviations (\(\sigma\)) for study-level observations (\(\sigma_{study}^2\)), phylogenetic relatedness (\(\sigma_{phylogeny}^2\)), and the correlation among species (\(\sigma_{species}^2\)) and body mass (\(\sigma_{lnMass}^2\)). \(R_{marginal}^2\) represents the variance explained by fixed effects, while \(R_{conditional}^2\) represents the variance explained by both fixed effects and group-level effects.

Parameter Estimate Est.Error Q2.5 Q97.5
Fixed effects
ln\(\beta_0\) 1.11 0.55 0.01 2.18
Arboreal 0.73 0.54 -0.36 1.79
Fossorial 0.05 0.55 -1.01 1.13
Ground-dwelling 0.15 0.54 -0.90 1.22
Semi-aquatic -0.02 0.54 -1.08 1.05
Stream-dwelling 0.01 0.58 -1.11 1.16
Water-proof 1.88 0.17 1.54 2.23
Cocoon 3.03 0.14 2.76 3.31
Hollow 1.65 0.44 0.79 2.51
lnMass 0.11 0.03 0.04 0.17
lnVPD -0.01 0.05 -0.11 0.10
lnFlow -0.22 0.06 -0.34 -0.10
Group-level effects
\(\sigma_{species}^2\) 0.35 0.12 0.06 0.57
\(\sigma_{lnMass}^2\) 0.11 0.05 0.01 0.19
cor(\(\sigma_{species}^2\), \(\sigma_{lnMass}^2\)) -0.58 0.42 -0.99 0.65
\(\sigma_{phylogeny}^2\) 0.35 0.13 0.07 0.61
\(\sigma_{study}^2\) 0.82 0.09 0.67 1.01
Phylogenetic signal
\(\lambda\) 0.37 0.17 0.03 0.65
Variance
\(R_{marginal}^2\) 64.18 59.67 67.79
\(R_{conditional}^2\) 88.99 86.95 90.83

Table S4 - WU model

Table S4. Mean parameter estimates, estimate error, and 95% Bayesian credible intervals for the water uptake model, which includes the intercept (\(\beta_0\)), ecotype, the natural logarithm of body mass (lnMass), treatment temperature, initial hydration level, and origin (lab-raised or wild caught). Group-level effects include the standard deviations (\(\sigma\)) for study-level observations (\(\sigma_{study}^2\)), phylogenetic relatedness (\(\sigma_{phylogeny}^2\)), and the correlation among species (\(\sigma_{species}^2\)) and body mass (\(\sigma_{lnMass}^2\)). \(R_{marginal}^2\) represents the variance explained by fixed effects, while \(R_{conditional}^2\) represents the variance explained by both fixed effects and group-level effects.

Parameter Estimate Est.Error Q2.5 Q97.5
Fixed effects
ln\(\beta_0\) 8.90 0.85 7.22 10.56
Fossorial -0.42 0.29 -0.98 0.16
Ground-dwelling -0.19 0.22 -0.62 0.23
Semi-aquatic -0.17 0.29 -0.72 0.41
ecotypeStream-dwelling -0.62 0.30 -1.22 -0.02
lnMass 0.80 0.05 0.70 0.91
Treatment temperature 0.01 0.01 -0.01 0.04
Initial hydration -0.05 0.01 -0.06 -0.04
Origin - Wild 0.02 0.42 -0.83 0.84
Group-level effects
\(\sigma_{species}^2\) 0.24 0.14 0.01 0.52
\(\sigma_{lnMass}^2\) 0.09 0.05 0.01 0.20
cor(\(\sigma_{species}^2\), \(\sigma_{lnMass}^2\)) 0.11 0.52 -0.86 0.95
\(\sigma_{phylogeny}^2\) 0.58 0.19 0.18 0.94
\(\sigma_{study}^2\) 1.03 0.13 0.80 1.31
Phylogenetic signal
\(\lambda\) 0.77 0.16 0.30 0.93
Variance
\(R_{marginal}^2\) 69.65 62.90 75.05
\(R_{conditional}^2\) 97.68 96.51 98.52

Fig. S6 - \(r_i\) model

Fig. S6. Differences in resistance to water loss, \(r_i\) (s cm-1) by (a) ecotype and (b) water-conserving strategies. Note, when plotting by ecotype, the \(r_i\) excludes behavioural water-conserving strategies such as during cocoon-forming and inside hollows. Mean estimates ± 95% CI presented in black points and error bars, while raw values were presented as grey points.


Fig. S7 - WU model

Fig. S7. Differences in cutaneous water uptake (mg H2O h-1) by ecotype. Mean estimates ± 95% CI presented in black points and error bars, while raw values were presented as grey points. The size of the grey points indicates study precision (inverse of standard error).


NicheMapR

To estimate the influence of warming and drought on activity of a hypothetical frog, we simulated a water and heat energy exchange model (Fig. S8a) and its interaction with a simulated local microclimate using the NicheMapR package (Kearney and Porter, 2017; Kearney and Porter, 2020).

Fig. S8. Summary water and energy exchange model from Tracy (1976) integrated into NicheMapR and water conserving strategies. (a) Schematic summary of the exchanges of energy and water between a frog and its environment used to develop the transient-state model of water exchange. In respect to water exchange, the net water loss represents water loss from respiratory, cutaneous, ocular, and cloaca evaporation as well as urinary and faecal water (Pirtle et al., 2019). (b) Behavioural, morphological, and physiological strategies employed by frogs on land to reduce water loss (Hillman et al., 2009).

Simulate water-conserving behaviours

We used the modularized version of NicheMapR’s v3.2.1 ectotherm model (i.e. ectoR_devel) and coded behavioral functions to account for the influence of hydration on activity (behav_functions function) which can be found in the behav_functions.R file on GitHub.

When the animal is not active, it is simulated to go to an underground retreat. It selects the shallowest depth with temperatures between Tmax and Tmin. If water = T, the frog selects the shallowest node with temperatures between Tmax and Tmin and a water potential >= -72.5, which was reported as a soil water potential from which Rana pipiens could absorb water. When the animal is belowground, it re-hydrates if the soil water potential is >= -72.5, at a rate specified in hyd.rate and proportional to the level of dehydration, following:

\[\begin{equation} \frac{Hyd_{max} - Hyd_{i}}{Hyd_{max}} \times hyd.rate, \tag{16} \end{equation}\]

It is important to note that currently frogs are not re-hydrating when active aboveground.

The “skinwet” term (\(p_{wet}\)) determines the proportion of the total surface area used in the calculation of mass transfer of water from the surface. Here, \(p_{wet}\) was calculated from empirically derived skin resistance following Pirtle et al. (2019):

\[\begin{equation} p_{wet} = \frac{1}{h_D \times r_i + (\frac{P_r}{S_c})^\frac{2}{3}}, \tag{17} \end{equation}\]

where \(r_i\) is the skin’s resistance to water vapor transfer (s m-1), \(P_r\) is the Prandtl number (dimensionless), \(S_c\) is the Schmidt number (dimensionless), \(h_D\) is the mass transfer coefficient (m s-1). To calculate \(p_{wet}\), the mass transfer coefficient (\(h_D\)) must be known. Mass transfer refers to the movement of a substance though a fluid interface, driven by changes in the concentration gradient. The mass transfer coefficient controls the rate of diffusion and is dependent on velocity, temperature, and physical properties of the interphase. Similar to the heat transfer coefficient, the mass transfer coefficient also has two components derived from free and forced convection. We consider forced convection only (as free convention should be negligible within a measurement chamber), and this can be calculated from the heat transfer coefficient:

\[\begin{equation} h_D = (\frac{h_C}{C_p \times \rho}) \times (\frac{P_r}{S_c}) ^ \frac{2}{3}, \tag{18} \end{equation}\]

where \(P_r\) is the Prandtl number (dimensionless), \(S_c\) is the Schmidt number (dimensionless), \(h_C\) is the heat transfer coefficient (J s-1 cm-2 K-1), \(\rho\) is the density of dry air (g cm-3), and \(C_p\) is the specific heat of air (1.01 J g-1 K-1).

Simulate drought and warming

Microclimates represent the physical environments experienced by an organism. They are a necessity for mechanistic niche modelling because it is the environment experienced at the scale of the individual that needs to be provided to the equations of energy and mass balance. The microclimate model was implemented as described by Kearney et al. (2014). Specifically, it was driven by historical 0.05° grid (~5 km) daily weather input layers (air temperature, vapor pressure, wind speed, and cloud cover).

We simulated meteorological drought (defined as less than average rainfall) from the micro_era5 function from NicheMapR by decreasing the rainmult function by 0.5 (Fig. S9). A factor of 0.5 means 50% of the original rainfall. To simulate frog activity under drought and warming scenarios, we constructed four climate conditions using the micro_era5 function:

  1. current normal scenario representing the mean annual air temperature and rainfall from 1981–2010,
  2. current drought scenario representing the mean annual air temperature from 1981-2010 and annual rainfall based on 2017-2020 drought in Australia (Fig. S9),
  3. warming normal scenario representing the “business-as-usual” scenario, where the global surface temperature is estimated to increase by 4°C by 2080–2100 with no effect of drought (+4°C only), and
  4. warming drought scenario with a +4°C increasing in air temperature and annual rainfall based on 2017-2020 drought in Australia.

First, download the mcera5 microclimate data to a local directory to run the micro_era5 function faster.

# get ERA5 data with package mcera5 
# assign your credentials (register here: https://cds.climate.copernicus.eu/user/register)
uid         <- "$$$$$$"
cds_api_key <- "$$$$$$$$-$$$$-$$$$-$$$$-$$$$$$$$$$$$"
ecmwfr::wf_set_key(user = uid, key = cds_api_key, service = "cds")

# bounding coordinates (in WGS84 / EPSG:4326)
c(-41.190, -20.186) 
xmn <- -42
xmx <- -41
ymn <- -21
ymx <- -20

xmn <- 152
xmx <- 154
ymn <- -28
ymx <- -26

# temporal extent
st_time <- lubridate::ymd("2016:01:01") # earliest sampling date
en_time <- lubridate::ymd("2018:12:31") # latest sampling date

# filename and location for downloaded .nc files
file_prefix <- "era5"
op <- "YOUR DIRECTORY"

# build a request (covering multiple years)
req <- mcera5::build_era5_request(xmin = xmn, xmax = xmx,
                                  ymin = ymn, ymax = ymx,
                                  start_time   = st_time,
                                  end_time     = en_time,
                                  outfile_name = file_prefix)

mcera5::request_era5(request = req, uid = uid, out_path = op)

Next, run the micro_era5 function for the four scenarios in 2017 (representing typical rainfall year), and one for 2019 to validate the observed rainfall data. Note, we ran the microclimate models from 2016 to 2017 to ‘spin up’ the soil moisture for 2016, and only used the microclimate data for 2017. This also applied to the 2019 microclimate, where we ran the microclimate models from 2018 to 2019, and used the microclimate data for 2019.

# Load microclimates
micro_curr_wet <- readRDS("micro_output/Australia_Current normal.rds")
micro_curr_dry <- readRDS("micro_output/Australia_Current dry.rds")
micro_warm_wet <- readRDS("micro_output/Australia_Warming normal.rds")
micro_warm_dry <- readRDS("micro_output/Australia_Warming dry.rds")

# Simulate rainfall for 2019 drought
act_dry <- micro_era5(loc = c(153.09249, -27.6235), # Karawatha, QLD.
                      runshade = 1, minshade = 0, # shade parameters
                      warm = 0, # current climate
                      dstart = "01/01/2018", 
                      dfinish = "31/12/2019",
                      spatial = '/Users/nicholaswu/Library/CloudStorage/OneDrive-WesternSydneyUniversity/Drought project/Spatial data/karawatha/era5', # change to your location
                      save = 0)

To verify our microclimate models, we plotted the simulated the daily rainfall for 2017 (representing typical rainfall) and 2019 (recent historical drought) with the observed daily rainfall in Australia for the following location: Karawatha, Southeast Queensland, Australia (153.09249, -27.6235). Karawatha provides a good case study because there are many ecotypes found in this location: ground-dwelling (e.g. Rhinella marina), arboreal (e.g. Litoria caerulea), fossorial (e.g. Cyclorana alboguttata), semi-aquatic (e.g. Litoria nasuta), and this area has experienced drought recently (2019). We extracted rainfall data from a weather station next to Karawatha which experienced “very much below average” rainfall from the Australian Bureau of Meteorology.

# Load observed rainfall for 2019
obs_rainfall <- read.csv(file.path(data_path, "obs_rainfall.csv")) %>%
  tibble::rowid_to_column("DOY") %>%
  dplyr::mutate(date = lubridate::make_date(year = 2019, month = month_num, day = day))

# Merge observed and predicted rainfall together
model_rain_wet <- as.data.frame(micro_curr_wet$RAINFALL) %>%
  tail(-366) %>% # remove 2016 simulation
  tibble::rowid_to_column("DOY") %>%
  rename(rainfall_mm = "micro_curr_wet$RAINFALL") %>%
  merge(obs_rainfall, by = "DOY", all.x = TRUE)

model_2019 <- as.data.frame(act_dry$RAINFALL) %>%
  tail(-366) %>% # remove 2018 simulation
  tibble::rowid_to_column("DOY") %>%
  rename(rainfall_mm = "act_dry$RAINFALL") %>%
  merge(obs_rainfall, by = "DOY", all.x = TRUE)

# 2017 normal validate
rain_wet_plot <- model_rain_wet %>%
  ggplot() +
  geom_line(aes(x = DOY, y = karawatha_17), colour = "grey") +
  geom_line(aes(x = DOY, y = rainfall_mm * 1.2), colour = "red", alpha = 0.5) +
  labs(x = "Day of the year", y = expression("Daily rainfall (mm day"^{"-1"}*")")) +
  ggtitle("2017 Normal") +
  scale_y_continuous(lim = c(0, 100), expand = c(0, 0)) +
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom")

# 2019 drought validate
rain_dry_plot <- model_2019 %>%
  ggplot() +
  geom_line(aes(x = DOY, y = karawatha_19), colour = "grey") +
  geom_line(aes(x = DOY, y = rainfall_mm), colour = "red", alpha = 0.5) +
  labs(x = "Day of the year", y = expression("Daily rainfall (mm day"^{"-1"}*")")) +
  ggtitle("2019 Drought") +
  scale_y_continuous(lim = c(0, 100), expand = c(0, 0)) +
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom")

cowplot::plot_grid(rain_wet_plot, rain_dry_plot, ncol = 2)

Fig. S9. Simulated rainfall from the micro_era5 function (red) and the observed rainfall for Karawatha, QLD from the Australian Bureau of Meteorology (grey). The total yearly observed rainfall for 2017 was as 1100 mm, and the total simulated yearly rainfall from NicheMapR was 1097.2 mm. The total yearly observed rainfall for the 2019 drought was 596 mm, and the total simulated yearly rainfall from NicheMapR was 556.22 mm. The average yearly rainfall across 1981-2010 is around 1100 mm per year.

Simulate activity - ecotypes

We simulated the potential number of hours for activity in a year (\(t_{act}\)) which represents the suitable thermal and hydric conditions for the animal to move beyond their retreat to either catch prey or finding mates (Kearney and Porter, 2020). The thermoregulatory and hydroregulatory sequence in the model assumes that frogs will only be ‘active’ (i.e. moving beyond their retreat, catching prey, finding mates) between the minimum and maximum body temperature thresholds for foraging, Tmin and Tmax (°C), and the minimum tolerated hydration, min.hyd (%). In addition, if water.act = T, the frog will only be active if temperatures are within the suitable temp range, and the frog is not expected to go below allowed hydration levels (e.g. if %hydration is not below min.hyd).

To estimate the potential \(t_{act}\) for one year, we simulated the hypothetical frog to be active during the day and night (24 hours). While most frogs are nocturnal, there are some frog species found moving during the day. The water hydric parameters (e.g. skin resistance, water uptake rate, dehydration tolerance) were based on the average values of the dataset collected from the PRISMA search. The thermal parameters (minimum and maximum foraging and critical temperature) were based on Rhinalla marina which has been verified in Kearney et al. (2008).

Three water-saving strategies were constructed to broadly reflect each ecotype that use either behavioural strategies such as microhabitat selection, or physiological strategies such as increased skin resistance or skin thickness (Table S5). For example, many amphibians (especially arid specialist) seek or burrow underground to regulate body temperature and water balance without exhibiting thicker skin or higher skin resistance. This is because underground burrows are generally cooler, less varied temperature fluctuation, and more moist relative to the surface climate.

Table S5. Modified parameters for the sim.ecto function for each hypothetical frog model. The skin resistance values were based on the average empirical measurements for a typical frog and a waterproof frog in the meta-analysis. Seek shade represents microclimate simulated under shaded conditions (0-90% shade). Retreat underground represents the ability for the frog to seek suitable microclimates underground. Can climb represents the ability for the frog to seek suitable microclimates above ground level (e.g. trees, cliffs). Note, frogs are not active when underground, and water uptake only occurs during inactivity.

Water-saving strategy Skin resistance Seek shade? Retreat underground? Can climb? Ecotype
Shade only Low Yes No No Ground-dwelling
Waterproof High Yes No Yes Arboreal
Fossorial Low Yes Yes No Fossorial

It is important to note that we focus only on the direct effects of environmental change on water budgets by predicting changes in EWL rates. The conclusions we draw do not account for the indirect effects of environmental change on water budgets, such as potential changes to thermal tolerance as a result of dehydration, or the thermoregulatory difficulties that may arise as a result of habitat modification.

source("/Users/nicholaswu/Library/CloudStorage/OneDrive-WesternSydneyUniversity/Drought project/code/behav_functions.R")
# Construct frog model
# compute the heat exchange by convection (extract mass transfer coefficient, Prandtl number and Schmidt number)
CONV_out <- NicheMapR::CONV_ENDO(TS     = 19, # skin temperature (°C)
                                 TENV   = 20, # fluid temperature (°C)
                                 SHAPE  = 4, # 4 is ellipsoid
                                 SURFAR = mean(resist_dat$dors_SA_cm2, na.rm = TRUE) / 10000,  # surface area for convection, m2
                                 FLTYPE = 0, # fluid type: 0 = air
                                 FURTST = 0, # test of presence of fur (length x diameter x density x depth) (-)
                                 D      = mean(resist_dat$D, na.rm = TRUE), 
                                 TFA    = 20, # initial fur/air interface temperature
                                 VEL    = mean(resist_dat$airflow_cm_s, na.rm = TRUE) / 100, # wind speed (m/s)
                                 ZFUR   = 0, # fur depth, mean (m)
                                 BP     = 101325, # barometric pressure at sea level
                                 ELEV   = 0) # elevation (m)

# basic parameters for 30 g frog
Ww_g         <- exp(mean(log(raw_dat$mean_mass_g), na.rm = TRUE)) # geometric mean wet weight of animal (g), account for uneven distribution
r_s_low      <- resist_dat %>% dplyr::filter(strategy == "none") %>% dplyr::select(r_s_est) # skin resistance
pct_wet_high <- 1 / (CONV_out[5] * mean(r_s_low$r_s_est, na.rm = TRUE) + (CONV_out[11] / CONV_out[13]) ^ 0.6666666) * 100  # % of surface area acting as a free-water exchanger (Pirtle et al 2017)

# parameters for a water-proof frog
r_s_high    <- resist_dat %>% dplyr::filter(strategy == "water-proof") %>% dplyr::select(r_s_est) # skin resistance
pct_wet_low <- 1 / (CONV_out[5] * max(r_s_high$r_s_est, na.rm = TRUE) + (CONV_out[11] / CONV_out[13]) ^ 0.6666666) * 100 # % of surface area acting as a free-water exchanger (Pirtle et al 2017)

# Thermal traits based on Rhinella marina
Tmin   <- 13.7 # minimum Tb at which activity occurs (Kearney et al 2008)
Tmax   <- 35.4 # maximum Tb at which activity occurs (Kearney et al 2008, Tingley & Shine 2011)
#T_pref <- 24 # preferred Tb (Kearney et al 2008)
CTmax  <- 37 # critical thermal minimum (affects choice of retreat) Tracy et al 2012
CTmin  <- 6 # critical thermal maximum (affects choice of retreat) Kolbe et al 2010, McCann et al 2014

# Water balance traits
min_hyd <- 80 # minimum tolerated hydration before activity declines (% of fully hydrated animals)
hyd.death <- 50 # minimum tolerated hydration before death (% of fully hydrated animals)
wu_rate <- wu_dat %>% dplyr::filter(strategy == "none") %>% dplyr::select(mg_h_mean)
hyd_rate <- exp(mean(log(wu_rate$mg_h_mean), na.rm = TRUE)) / 1000 # geometric mean rehydration rate (g/h), account for uneven distribution
# depends on current and max hydration like this: hyd.rate * ((hyd - hyd.current) / hyd)

# behav = 'diurnal', 'nocturnal' or 'both'
# water; does the frog select depth according to water potential? (TRUE or FALSE)
# water.act; does the activity depend on water loss? (TRUE or FALSE)

# SHADE MODEL
shad_curr_wet_mod <- sim.ecto(micro_curr_wet, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = FALSE, climb = FALSE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_high, 
                              water = FALSE, water.act = TRUE)

shad_curr_dry_mod <- sim.ecto(micro_curr_dry, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = FALSE, climb = FALSE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_high, 
                              water = FALSE, water.act = TRUE)

shad_warm_wet_mod <- sim.ecto(micro_warm_wet, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = FALSE, climb = FALSE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_high, 
                              water = FALSE, water.act = TRUE)

shad_warm_dry_mod <- sim.ecto(micro_warm_dry, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = FALSE, climb = FALSE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_high, 
                              water = FALSE, water.act = TRUE)

# WATER-PROOF MODEL
tree_curr_wet_mod <- sim.ecto(micro_curr_wet, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = FALSE, climb = TRUE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_low, 
                              water = TRUE, water.act = TRUE)

tree_curr_dry_mod <- sim.ecto(micro_curr_dry, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = FALSE, climb = TRUE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_low, 
                              water = TRUE, water.act = TRUE)

tree_warm_wet_mod <- sim.ecto(micro_warm_wet, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = FALSE, climb = TRUE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_low, 
                              water = TRUE, water.act = TRUE)

tree_warm_dry_mod <- sim.ecto(micro_warm_dry, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = FALSE, climb = TRUE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_low, 
                              water = TRUE, water.act = TRUE)

# BURROWING MODEL
burr_curr_wet_mod <- sim.ecto(micro_curr_wet, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = TRUE, climb = FALSE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_high, 
                              water = TRUE, water.act = TRUE)

burr_curr_dry_mod <- sim.ecto(micro_curr_dry, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = TRUE, climb = FALSE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_high, 
                              water = TRUE, water.act = TRUE)

burr_warm_wet_mod <- sim.ecto(micro_warm_wet, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = TRUE, climb = FALSE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_high, 
                              water = TRUE, water.act = TRUE)

burr_warm_dry_mod <- sim.ecto(micro_warm_dry, Ww_g = Ww_g, shape = 4, 
                              Tmax = Tmax, Tmin = Tmin, CTmin = CTmin, CTmax = CTmax,
                              behav = 'both', in.shade = TRUE, burrow = TRUE, climb = FALSE,
                              min.hyd = min_hyd, hyd.death = hyd.death,
                              hyd.rate = hyd_rate, pct_wet = pct_wet_high, 
                              water = TRUE, water.act = TRUE)
# SHADE MODEL
shad_curr_wet_df <- data.frame(shad_curr_wet_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = shad_curr_wet_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_wet = length(active[active == TRUE]))

shad_curr_dry_df <- data.frame(shad_curr_dry_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = shad_curr_dry_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_dry = length(active[active == TRUE]))

shad_warm_wet_df <- data.frame(shad_warm_wet_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = shad_warm_wet_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_wet = length(active[active == TRUE]))

shad_warm_dry_df <- data.frame(shad_warm_dry_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = shad_warm_dry_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_dry = length(active[active == TRUE]))

shad_model <- shad_curr_wet_df %>%
  merge(shad_curr_dry_df, by = "day") %>%
  merge(shad_warm_wet_df, by = "day") %>%
  merge(shad_warm_dry_df, by = "day") %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry", "warm_wet", "curr_dry", "curr_wet")),
                season = case_when(
    day >= 335 ~ "summer",
    day >= 1 & day <= 61 ~ "summer",
    day >= 62 & day <= 153 ~ "autumn",
    day >= 154 & day <= 244 ~ "winter",
    day >= 245 & day <= 334 ~ "spring"
    ))

# TREE MODEL
tree_curr_wet_df <- data.frame(tree_curr_wet_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = tree_curr_wet_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_wet = length(active[active == TRUE]))

tree_curr_dry_df <- data.frame(tree_curr_dry_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = tree_curr_dry_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_dry = length(active[active == TRUE]))

tree_warm_wet_df <- data.frame(tree_warm_wet_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = tree_warm_wet_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_wet = length(active[active == TRUE]))

tree_warm_dry_df <- data.frame(tree_warm_dry_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = tree_warm_dry_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_dry = length(active[active == TRUE]))

tree_model <- tree_curr_wet_df %>%
  merge(tree_curr_dry_df, by = "day") %>%
  merge(tree_warm_wet_df, by = "day") %>%
  merge(tree_warm_dry_df, by = "day") %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry", "warm_wet", "curr_dry", "curr_wet")),
                season = case_when(
    day >= 335 ~ "summer",
    day >= 1 & day <= 61 ~ "summer",
    day >= 62 & day <= 153 ~ "autumn",
    day >= 154 & day <= 244 ~ "winter",
    day >= 245 & day <= 334 ~ "spring"
    ))

# FOSSORIAL MODEL
burr_curr_wet_df <- data.frame(burr_curr_wet_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = burr_curr_wet_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_wet = length(active[active == TRUE]))

burr_curr_dry_df <- data.frame(burr_curr_dry_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = burr_curr_dry_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_dry = length(active[active == TRUE]))

burr_warm_wet_df <- data.frame(burr_warm_wet_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = burr_warm_wet_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_wet = length(active[active == TRUE]))

burr_warm_dry_df <- data.frame(burr_warm_dry_mod$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = burr_warm_dry_mod.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_dry = length(active[active == TRUE]))

burr_model <- burr_curr_wet_df %>%
  merge(burr_curr_dry_df, by = "day") %>%
  merge(burr_warm_wet_df, by = "day") %>%
  merge(burr_warm_dry_df, by = "day") %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry", "warm_wet", "curr_dry", "curr_wet")),
                season = case_when(
    day >= 335 ~ "summer",
    day >= 1 & day <= 61 ~ "summer",
    day >= 62 & day <= 153 ~ "autumn",
    day >= 154 & day <= 244 ~ "winter",
    day >= 245 & day <= 334 ~ "spring"
    ))

Model output - ecotypes

Table S6a - Summary

Table S6a. Total potential activity hours per year (\(t_{act}\)) for a 8.81 g frog under different warming (current or warming) and drought (normal or drought) conditions with different water-saving strategies.

data.frame(strategy = c("Shade only", "Shade only", "Shade only", "Shade only",
                        "Waterproof", "Waterproof", "Waterproof", "Waterproof",
                        "Burrowing", "Burrowing", "Burrowing", "Burrowing"),
           temp = c("current", "current", "warming", "warming"),
           rain = c("normal", "drought"),
           t_act_h = c(sum(shad_curr_wet_df$curr_wet), sum(shad_curr_dry_df$curr_dry), sum(shad_warm_wet_df$warm_wet), sum(shad_warm_dry_df$warm_dry),
                       sum(tree_curr_wet_df$curr_wet), sum(tree_curr_dry_df$curr_dry), sum(tree_warm_wet_df$warm_wet), sum(tree_warm_dry_df$warm_dry),
                       sum(burr_curr_wet_df$curr_wet), sum(burr_curr_dry_df$curr_dry), sum(burr_warm_wet_df$warm_wet), sum(burr_warm_dry_df$warm_dry)),
           t_act_per = c(sum(shad_curr_wet_df$curr_wet) / 8760 * 100, sum(shad_curr_dry_df$curr_dry) / 8760 * 100, sum(shad_warm_wet_df$warm_wet) / 8760 * 100, sum(shad_warm_dry_df$warm_dry) / 8760 * 100,
                       sum(tree_curr_wet_df$curr_wet) / 8760 * 100, sum(tree_curr_dry_df$curr_dry) / 8760 * 100, sum(tree_warm_wet_df$warm_wet) / 8760 * 100, sum(tree_warm_dry_df$warm_dry) / 8760 * 100,
                       sum(burr_curr_wet_df$curr_wet) / 8760 * 100, sum(burr_curr_dry_df$curr_dry) / 8760 * 100, sum(burr_warm_wet_df$warm_wet) / 8760 * 100, sum(burr_warm_dry_df$warm_dry) / 8760 * 100)) %>%
  knitr::kable(col.names = c("Water-saving strategy", "Warming simulation", "Drought simulation", "$t_{act}$ (h)", "$t_{act}$ (%)"))
Water-saving strategy Warming simulation Drought simulation \(t_{act}\) (h) \(t_{act}\) (%)
Shade only current normal 3934 45
Shade only current drought 3729 43
Shade only warming normal 4268 49
Shade only warming drought 4022 46
Waterproof current normal 4724 54
Waterproof current drought 4482 51
Waterproof warming normal 4887 56
Waterproof warming drought 4596 52
Burrowing current normal 4271 49
Burrowing current drought 4152 47
Burrowing warming normal 4652 53
Burrowing warming drought 4535 52

Table S6b - Relative change year

Table S6b. Change in \(t_{act}\) (%) for each water-saving strategy relative to the current normal scenario under warming only, drought only, and warming and drought combined.

data.frame(strategy = c("Shade only","Waterproof", "Burrowing"),
           curr_wet = c(sum(shad_curr_wet_df$curr_wet), sum(tree_curr_wet_df$curr_wet), sum(burr_curr_wet_df$curr_wet)),
           curr_dry = c(sum(shad_curr_dry_df$curr_dry), sum(tree_curr_dry_df$curr_dry), sum(burr_curr_dry_df$curr_dry)),
           warm_wet = c(sum(shad_warm_wet_df$warm_wet), sum(tree_warm_wet_df$warm_wet), sum(burr_warm_wet_df$warm_wet)),
           warm_dry = c(sum(shad_warm_dry_df$warm_dry), sum(tree_warm_dry_df$warm_dry), sum(burr_warm_dry_df$warm_dry))) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet) / curr_wet * 100,
                delta_dry      = (curr_dry - curr_wet) / curr_wet * 100,
                delta_warm_dry = (warm_dry - curr_wet) / curr_wet * 100) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  knitr::kable(col.names = c("Water-saving strategy", "$\\Delta$ warming only (%)", "$\\Delta$ drought only (%)", "$\\Delta$ warming and drought (%)"))
Water-saving strategy \(\Delta\) warming only (%) \(\Delta\) drought only (%) \(\Delta\) warming and drought (%)
Shade only 8.5 -5.2 2.2
Waterproof 3.5 -5.1 -2.7
Burrowing 8.9 -2.8 6.2
data.frame(strategy = c("Shade only","Waterproof", "Burrowing"),
           curr_wet = c(sum(shad_curr_wet_df$curr_wet), sum(tree_curr_wet_df$curr_wet), sum(burr_curr_wet_df$curr_wet)),
           curr_dry = c(sum(shad_curr_dry_df$curr_dry), sum(tree_curr_dry_df$curr_dry), sum(burr_curr_dry_df$curr_dry)),
           warm_wet = c(sum(shad_warm_wet_df$warm_wet), sum(tree_warm_wet_df$warm_wet), sum(burr_warm_wet_df$warm_wet)),
           warm_dry = c(sum(shad_warm_dry_df$warm_dry), sum(tree_warm_dry_df$warm_dry), sum(burr_warm_dry_df$warm_dry))) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet),
                delta_dry      = (curr_dry - curr_wet),
                delta_warm_dry = (warm_dry - curr_wet)) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  knitr::kable(col.names = c("Water-saving strategy", "$\\Delta$ warming only (%)", "$\\Delta$ drought only (%)", "$\\Delta$ warming and drought (%)"))
Water-saving strategy \(\Delta\) warming only (%) \(\Delta\) drought only (%) \(\Delta\) warming and drought (%)
Shade only 334 -205 88
Waterproof 163 -242 -128
Burrowing 381 -119 264

Table S6c - Relative change season

Table S6c. Change in \(t_{act}\) (%) for each water-saving strategy relative to the current normal scenario under warming only, drought only, and warming and drought combined.

# summer
shad_model_summer <- shad_model %>%
  dplyr::filter(season == "summer") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tree_model_summer <- tree_model %>%
  dplyr::filter(season == "summer") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

burr_model_summer <- burr_model %>%
  dplyr::filter(season == "summer") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tab_summer <- data.frame(strategy = c("Shade only","Waterproof", "Burrowing"),
           curr_wet = c(shad_model_summer$hours[4], tree_model_summer$hours[4], burr_model_summer$hours[4]),
           curr_dry = c(shad_model_summer$hours[3], tree_model_summer$hours[3], burr_model_summer$hours[3]),
           warm_wet = c(shad_model_summer$hours[2], tree_model_summer$hours[2], burr_model_summer$hours[2]),
           warm_dry = c(shad_model_summer$hours[1], tree_model_summer$hours[1], burr_model_summer$hours[1])) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet) / curr_wet * 100,
                delta_dry      = (curr_dry - curr_wet) / curr_wet * 100,
                delta_warm_dry = (warm_dry - curr_wet) / curr_wet * 100) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  tibble::add_row(strategy = "**Summer**", .before = 1)

# autumn
shad_model_autumn <- shad_model %>%
  dplyr::filter(season == "autumn") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tree_model_autumn <- tree_model %>%
  dplyr::filter(season == "autumn") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

burr_model_autumn <- burr_model %>%
  dplyr::filter(season == "autumn") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tab_autumn <- data.frame(strategy = c("Shade only","Waterproof", "Burrowing"),
           curr_wet = c(shad_model_autumn$hours[4], tree_model_autumn$hours[4], burr_model_autumn$hours[4]),
           curr_dry = c(shad_model_autumn$hours[3], tree_model_autumn$hours[3], burr_model_autumn$hours[3]),
           warm_wet = c(shad_model_autumn$hours[2], tree_model_autumn$hours[2], burr_model_autumn$hours[2]),
           warm_dry = c(shad_model_autumn$hours[1], tree_model_autumn$hours[1], burr_model_autumn$hours[1])) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet) / curr_wet * 100,
                delta_dry      = (curr_dry - curr_wet) / curr_wet * 100,
                delta_warm_dry = (warm_dry - curr_wet) / curr_wet * 100) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  tibble::add_row(strategy = "**Autumn**", .before = 1)

# winter
shad_model_winter <- shad_model %>%
  dplyr::filter(season == "winter") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tree_model_winter <- tree_model %>%
  dplyr::filter(season == "winter") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

burr_model_winter <- burr_model %>%
  dplyr::filter(season == "winter") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tab_winter <- data.frame(strategy = c("Shade only","Waterproof", "Burrowing"),
           curr_wet = c(shad_model_winter$hours[4], tree_model_winter$hours[4], burr_model_winter$hours[4]),
           curr_dry = c(shad_model_winter$hours[3], tree_model_winter$hours[3], burr_model_winter$hours[3]),
           warm_wet = c(shad_model_winter$hours[2], tree_model_winter$hours[2], burr_model_winter$hours[2]),
           warm_dry = c(shad_model_winter$hours[1], tree_model_winter$hours[1], burr_model_winter$hours[1])) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet) / curr_wet * 100,
                delta_dry      = (curr_dry - curr_wet) / curr_wet * 100,
                delta_warm_dry = (warm_dry - curr_wet) / curr_wet * 100) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  tibble::add_row(strategy = "**Winter**", .before = 1)

# spring
shad_model_spring <- shad_model %>%
  dplyr::filter(season == "spring") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tree_model_spring <- tree_model %>%
  dplyr::filter(season == "spring") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

burr_model_spring <- burr_model %>%
  dplyr::filter(season == "spring") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tab_spring <- data.frame(strategy = c("Shade only","Waterproof", "Burrowing"),
           curr_wet = c(shad_model_spring$hours[4], tree_model_spring$hours[4], burr_model_spring$hours[4]),
           curr_dry = c(shad_model_spring$hours[3], tree_model_spring$hours[3], burr_model_spring$hours[3]),
           warm_wet = c(shad_model_spring$hours[2], tree_model_spring$hours[2], burr_model_spring$hours[2]),
           warm_dry = c(shad_model_spring$hours[1], tree_model_spring$hours[1], burr_model_spring$hours[1])) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet) / curr_wet * 100,
                delta_dry      = (curr_dry - curr_wet) / curr_wet * 100,
                delta_warm_dry = (warm_dry - curr_wet) / curr_wet * 100) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  tibble::add_row(strategy = "**Spring**", .before = 1)

# Render table
bind_rows(tab_summer, tab_autumn, tab_winter, tab_spring) %>% 
  remove_rownames() %>% 
  knitr::kable(col.names = c("Water-saving strategy", "$\\Delta$ warming only (%)", "$\\Delta$ drought only (%)", "$\\Delta$ warming and drought (%)"))
Water-saving strategy \(\Delta\) warming only (%) \(\Delta\) drought only (%) \(\Delta\) warming and drought (%)
Summer
Shade only -8.39 -13.92 -21.82
Waterproof -8.61 -13.39 -22.78
Burrowing -7.16 -6.58 -12.76
Autumn
Shade only 4.75 -1.84 3.26
Waterproof 1.14 -1.99 -0.54
Burrowing 5.87 -1.43 4.99
Winter
Shade only 72.88 -1.91 65.47
Waterproof 38.05 -1.56 33.52
Burrowing 70.55 -0.99 66.60
Spring
Shade only 0.77 -2.80 -4.44
Waterproof -2.15 -3.65 -7.79
Burrowing 2.30 -1.20 0.83

Simulate activity - biomes

To test if changes in activity under different climate scenarios are generalisable, we also ran the shade-only model under three additional representative biome types where anurans typically occupy and are predicted to increase in drought: tropic (Salvador, Brazil), semi-arid (Tankwa Karoo, South Africa), and Mediterranean (Seville, Spain) (Fig. S10). The biome locations were classified based on the Köppen climate classification. All microclimate simulations ran for 2016-2017 and for the same hypothetical frog.

We first downloaded the microclimates locally with the function below (edited by M. Kearney).

source('../micro_era5_local2.R') # a version of micro_era5 that reads from locally downloaded tiles of the whole planet

# Define locations and scenarios
locations <- list(
  list(name = "Brazil", longlat = c(-39.16553, -13.05029)),
  list(name = "South Africa", longlat = c(19.8566, -32.4297)),
  list(name = "Spain", longlat = c(-5.5538, 37.04143)),
  list(name = "Australia", longlat = c(153.09249, -27.6235))
)

scenarios <- list(
  list(name = "Current normal", rainmult = 1.2, warm = 0),
  list(name = "Current dry", rainmult = 0.5, warm = 0),
  list(name = "Warming normal", rainmult = 1.2, warm = 4),
  list(name = "Warming dry", rainmult = 0.5, warm = 4)
)

# Function to run micro_era5 and save output
run_micro_era5 <- function(location=location, scenario=scenario) {
  # Extract parameters
  longlat <- location$longlat
  name <- paste(location$name, scenario$name, sep = "_")
  rainmult <- scenario$rainfact
  warm <- scenario$warm
  cat(name, rainmult, warm, '\n')
  # Run micro_era5
  result <- micro_era5_local(loc = longlat,
                       rainmult = rainmult,
                       warm = warm,
                       dstart = "01/01/2016", 
                       dfinish = "31/12/2017",
                       spatial = "/srv/6300-predecol/data/ERA5/time"
                       )

  # Save output
  output_file <- paste0(name, ".rds")
  saveRDS(result, file = output_file)
}

# Loop over locations and scenarios
for (i in 1:length(locations)) {
  for (j in 1:length(scenarios)) {
    run_micro_era5(locations[i][[1]], scenarios[j][[1]])
  }
}

Due to the long processing time for downloading microclimate for each site, we saved the microclimate locally, and loaded them here.

micro_curr_wet_br <- readRDS("micro_output/Brazil_Current normal.rds")
micro_curr_dry_br <- readRDS("micro_output/Brazil_Current dry.rds")
micro_warm_wet_br <- readRDS("micro_output/Brazil_Warming normal.rds")
micro_warm_dry_br <- readRDS("micro_output/Brazil_Warming dry.rds")

micro_curr_wet_sa <- readRDS("micro_output/South Africa_Current normal.rds")
micro_curr_dry_sa <- readRDS("micro_output/South Africa_Current dry.rds")
micro_warm_wet_sa <- readRDS("micro_output/South Africa_Warming normal.rds")
micro_warm_dry_sa <- readRDS("micro_output/South Africa_Warming dry.rds")

micro_curr_wet_sp <- readRDS("micro_output/Spain_Current normal.rds")
micro_curr_dry_sp <- readRDS("micro_output/Spain_Current dry.rds")
micro_warm_wet_sp <- readRDS("micro_output/Spain_Warming normal.rds")
micro_warm_dry_sp <- readRDS("micro_output/Spain_Warming dry.rds")
model_rain_wet_br <- as.data.frame(micro_curr_wet_br$RAINFALL) %>%
  tail(-366) %>% # remove 2016 simulation
  tibble::rowid_to_column("DOY") %>%
  rename(rainfall_mm = "micro_curr_wet_br$RAINFALL")

model_rain_wet_sa <- as.data.frame(micro_curr_wet_sa$RAINFALL) %>%
  tail(-366) %>% # remove 2016 simulation
  tibble::rowid_to_column("DOY") %>%
  rename(rainfall_mm = "micro_curr_wet_sa$RAINFALL")

model_rain_wet_sp <- as.data.frame(micro_curr_wet_sp$RAINFALL) %>%
  tail(-366) %>% # remove 2016 simulation
  tibble::rowid_to_column("DOY") %>%
  rename(rainfall_mm = "micro_curr_wet_sp$RAINFALL")

p1 <- ggplot() + 
  geom_line(data = model_rain_wet, aes(x = DOY, y = rainfall_mm * 1.2), colour = "darkgrey") +
  ylab("Daily rainfall (mm)") +
  scale_x_continuous(expand = c(0, 0)) + 
  scale_y_continuous(lim = c(0, 100), expand = c(0,0), position = "right") + 
  coord_cartesian(xlim = c(0, 365)) +
  mytheme() +
  theme(legend.position = "bottom")

p2 <- ggplot() + 
  geom_line(data = model_rain_wet_br, aes(x = DOY, y = rainfall_mm * 1.2), colour = "darkgrey") +
  ylab("Daily rainfall (mm)") +
  scale_x_continuous(expand = c(0, 0)) + 
  scale_y_continuous(lim = c(0, 100), expand = c(0,0), position = "right") + 
  coord_cartesian(xlim = c(0, 365)) +
  mytheme() +
  theme(legend.position = "bottom")

p3 <- ggplot() + 
  geom_line(data = model_rain_wet_sa, aes(x = DOY, y = rainfall_mm * 1.2),  colour = "darkgrey") +
  ylab("Daily rainfall (mm)") +
  scale_x_continuous(expand = c(0, 0)) + 
  scale_y_continuous(lim = c(0, 100), expand = c(0,0), position = "right") + 
  coord_cartesian(xlim = c(0, 365)) +
  mytheme() +
  theme(legend.position = "bottom")

p4 <- ggplot() + 
  geom_line(data = model_rain_wet_sp, aes(x = DOY, y = rainfall_mm * 1.2),  colour = "darkgrey") +
  ylab("Daily rainfall (mm)") +
  scale_x_continuous(expand = c(0, 0)) + 
  scale_y_continuous(lim = c(0, 100), expand = c(0,0), position = "right") + 
  coord_cartesian(xlim = c(0, 365)) +
  mytheme() +
  theme(legend.position = "bottom")

t1 <- ggplot() + 
  geom_line(data = data.frame(micro_curr_wet$shadsoil), aes(x = DOY, y = D0cm)) +
  ylab(expression("Shaded"~italic("T")["soil"]*" (°C)")) +
  ggtitle("Subtropic", subtitle = "Brisbane, Australia") +
  scale_x_continuous(expand = c(0, 0)) +
  scale_y_continuous(lim = c(-5, 50), expand = c(0,0)) + 
  coord_cartesian(xlim = c(0, 365)) +
  mytheme() +
  theme(legend.position = "bottom")

t2 <- ggplot() + 
  geom_line(data = data.frame(micro_curr_wet_br$shadsoil), aes(x = DOY, y = D0cm)) +
  ylab(expression("Shaded"~italic("T")["soil"]*" (°C)")) +
  ggtitle("Tropic", subtitle = "Salvador, Brazil") +
  scale_x_continuous(expand = c(0, 0)) + 
  scale_y_continuous(lim = c(-5, 50), expand = c(0,0)) + 
  coord_cartesian(xlim = c(0, 365)) +
  mytheme() +
  theme(legend.position = "bottom")

t3 <- ggplot() + 
  geom_line(data = data.frame(micro_curr_wet_sa$shadsoil), aes(x = DOY, y = D0cm)) +
  ylab(expression("Shaded"~italic("T")["soil"]*" (°C)")) +
  ggtitle("Semi-arid", subtitle = "Tankwa Karoo, South Africa") +
  scale_x_continuous(expand = c(0, 0)) + 
  scale_y_continuous(lim = c(-5, 50), expand = c(0,0)) + 
  coord_cartesian(xlim = c(0, 365)) +
  mytheme() +
  theme(legend.position = "bottom")

t4 <- ggplot() + 
  geom_line(data = data.frame(micro_curr_wet_sp$shadsoil), aes(x = DOY, y = D0cm)) +
  ylab(expression("Shaded"~italic("T")["soil"]*" (°C)")) +
  ggtitle("Mediterranean", subtitle = "Seville, Spain") +
  scale_x_continuous(expand = c(0, 0)) + 
  scale_y_continuous(lim = c(-5, 50), expand = c(0,0)) + 
  coord_cartesian(xlim = c(0, 365)) +
  mytheme() +
  theme(legend.position = "bottom")

aligned_plots <- align_plots(p1, t1, align = "hv", axis = "tblr")
au_plot <- ggdraw(aligned_plots[[1]]) + draw_plot(aligned_plots[[2]])

aligned_plots <- align_plots(p2, t2, align = "hv", axis = "tblr")
br_plot <- ggdraw(aligned_plots[[1]]) + draw_plot(aligned_plots[[2]])

aligned_plots <- align_plots(p3, t3, align = "hv", axis = "tblr")
sa_plot <- ggdraw(aligned_plots[[1]]) + draw_plot(aligned_plots[[2]])

aligned_plots <- align_plots(p4, t4, align = "hv", axis = "tblr")
sp_plot <- ggdraw(aligned_plots[[1]]) + draw_plot(aligned_plots[[2]])

cowplot::plot_grid(au_plot, br_plot, sa_plot, sp_plot, ncol = 2, labels = c('a', 'b', 'c', 'd'))

Fig. S10. Differences in shaded soil temperature (Tskin, °C; black lines) and daily rainfall (mm; grey lines) that anurans are expected to experience under a represenative (a) subtropic biome (total rainfall = 1097.2 mm), (b) tropic biome (total rainfall = 1218.21 mm), (c) semi-arid biome (total rainfall = 83.37 mm), and (d) Mediterranean biome (total rainfall = 385.83 mm).

# BRAZIL MODEL
curr_wet_mod_br <- sim.ecto(micro_curr_wet_br, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

curr_dry_mod_br <- sim.ecto(micro_curr_dry_br, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

warm_wet_mod_br <- sim.ecto(micro_warm_wet_br, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

warm_dry_mod_br <- sim.ecto(micro_warm_dry_br, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

# SOUTH AFRICA MODEL
curr_wet_mod_sa <- sim.ecto(micro_curr_wet_sa, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

curr_dry_mod_sa <- sim.ecto(micro_curr_dry_sa, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

warm_wet_mod_sa <- sim.ecto(micro_warm_wet_sa, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

warm_dry_mod_sa <- sim.ecto(micro_warm_dry_sa, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

# SPAIN MODEL
curr_wet_mod_sp <- sim.ecto(micro_curr_wet_sp, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

curr_dry_mod_sp <- sim.ecto(micro_curr_dry_sp, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

warm_wet_mod_sp <- sim.ecto(micro_warm_wet_sp, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)

warm_dry_mod_sp <- sim.ecto(micro_warm_dry_sp, Ww_g = Ww_g, shape = 4, Tmax = Tmax,
    Tmin = Tmin, CTmin = CTmin, CTmax = CTmax, behav = "both", in.shade = TRUE, burrow = FALSE,
    climb = FALSE, min.hyd = min_hyd, hyd.death = hyd.death, hyd.rate = hyd_rate,
    pct_wet = pct_wet_high, water = FALSE, water.act = TRUE)
# BRAZIL MODEL
curr_wet_br_df <- data.frame(curr_wet_mod_br$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = curr_wet_mod_br.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_wet = length(active[active == TRUE]))

curr_dry_br_df <- data.frame(curr_dry_mod_br$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = curr_dry_mod_br.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_dry = length(active[active == TRUE]))

warm_wet_br_df <- data.frame(warm_wet_mod_br$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = warm_wet_mod_br.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_wet = length(active[active == TRUE]))

warm_dry_br_df <- data.frame(warm_dry_mod_br$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = warm_dry_mod_br.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_dry = length(active[active == TRUE]))

br_model <- curr_wet_br_df %>%
  merge(curr_dry_br_df, by = "day") %>%
  merge(warm_wet_br_df, by = "day") %>%
  merge(warm_dry_br_df, by = "day") %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry", "warm_wet", "curr_dry", "curr_wet")),
                season = case_when(
    day >= 335 ~ "summer",
    day >= 1 & day <= 61 ~ "summer",
    day >= 62 & day <= 153 ~ "autumn",
    day >= 154 & day <= 244 ~ "winter",
    day >= 245 & day <= 334 ~ "spring"
    ))

# SOUTH AFRICA MODEL
curr_wet_sa_df <- data.frame(curr_wet_mod_sa$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = curr_wet_mod_sa.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_wet = length(active[active == TRUE]))

curr_dry_sa_df <- data.frame(curr_dry_mod_sa$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = curr_dry_mod_sa.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_dry = length(active[active == TRUE]))

warm_wet_sa_df <- data.frame(warm_wet_mod_sa$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = warm_wet_mod_sa.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_wet = length(active[active == TRUE]))

warm_dry_sa_df <- data.frame(warm_dry_mod_sa$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = warm_dry_mod_sa.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_dry = length(active[active == TRUE]))

sa_model <- curr_wet_sa_df %>%
  merge(curr_dry_sa_df, by = "day") %>%
  merge(warm_wet_sa_df, by = "day") %>%
  merge(warm_dry_sa_df, by = "day") %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry", "warm_wet", "curr_dry", "curr_wet")),
                season = case_when(
    day >= 335 ~ "summer",
    day >= 1 & day <= 61 ~ "summer",
    day >= 62 & day <= 153 ~ "autumn",
    day >= 154 & day <= 244 ~ "winter",
    day >= 245 & day <= 334 ~ "spring"
    ))

# SPAIN MODEL
curr_wet_sp_df <- data.frame(curr_wet_mod_sp$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = curr_wet_mod_sp.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_wet = length(active[active == TRUE]))

curr_dry_sp_df <- data.frame(curr_dry_mod_sp$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = curr_dry_mod_sp.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(curr_dry = length(active[active == TRUE]))

warm_wet_sp_df <- data.frame(warm_wet_mod_sp$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = warm_wet_mod_sp.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_wet = length(active[active == TRUE]))

warm_dry_sp_df <- data.frame(warm_dry_mod_sp$act) %>%
  tail(-8784) %>% # remove previous year 
  tibble::rowid_to_column("hour") %>%
  dplyr::rename(active = warm_dry_mod_sp.act) %>%
  dplyr::mutate(day = ceiling(1:8760/24)) %>%
  dplyr::group_by(day) %>%
  dplyr::summarise(warm_dry = length(active[active == TRUE]))

sp_model <- curr_wet_sp_df %>%
  merge(curr_dry_sp_df, by = "day") %>%
  merge(warm_wet_sp_df, by = "day") %>%
  merge(warm_dry_sp_df, by = "day") %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry", "warm_wet", "curr_dry", "curr_wet")),
                season = case_when(
    day >= 335 ~ "winter",
    day >= 1 & day <= 61 ~ "winter",
    day >= 62 & day <= 153 ~ "spring",
    day >= 154 & day <= 244 ~ "summer",
    day >= 245 & day <= 334 ~ "autumn"
    ))

Model output - biomes

Table S7a - Summary

Table S7a. Total potential activity hours per year (\(t_{act}\)) for a 8.81 g frog under different warming (current or warming) and drought (normal or drought) conditions across represenative biomes.

data.frame(biome = c("Subtropic", "Subtropic", "Subtropic", "Subtropic",
                     "Tropic", "Tropic", "Tropic", "Tropic",
                     "Semi-arid", "Semi-arid", "Semi-arid", "Semi-arid",
                     "Mediterranean", "Mediterranean", "Mediterranean", "Mediterranean"),
           temp = c("current", "current", "warming", "warming"),
           rain = c("normal", "drought"),
           t_act_h = c(sum(shad_curr_wet_df$curr_wet), sum(shad_curr_dry_df$curr_dry),
                       sum(shad_warm_wet_df$warm_wet), sum(shad_warm_dry_df$warm_dry), 
                       sum(curr_wet_br_df$curr_wet), sum(curr_dry_br_df$curr_dry), 
                       sum(warm_wet_br_df$warm_wet), sum(warm_dry_br_df$warm_dry), 
                       sum(curr_wet_sa_df$curr_wet), sum(curr_dry_sa_df$curr_dry), 
                       sum(warm_wet_sa_df$warm_wet), sum(warm_dry_sa_df$warm_dry), 
                       sum(curr_wet_sp_df$curr_wet), sum(curr_dry_sp_df$curr_dry),
                       sum(warm_wet_sp_df$warm_wet), sum(warm_dry_sp_df$warm_dry)),
           t_act_per = c(sum(shad_curr_wet_df$curr_wet) / 8760 * 100, 
                         sum(shad_curr_dry_df$curr_dry) / 8760 * 100, 
                         sum(shad_warm_wet_df$warm_wet) / 8760 * 100, 
                         sum(shad_warm_dry_df$warm_dry) / 8760 * 100,
                       sum(curr_wet_br_df$curr_wet) / 8760 * 100, 
                       sum(curr_dry_br_df$curr_dry) / 8760 * 100, 
                       sum(warm_wet_br_df$warm_wet) / 8760 * 100, 
                       sum(warm_dry_br_df$warm_dry) / 8760 * 100,
                       sum(curr_wet_sa_df$curr_wet) / 8760 * 100, 
                       sum(curr_dry_sa_df$curr_dry) / 8760 * 100, 
                       sum(warm_wet_sa_df$warm_wet) / 8760 * 100, 
                       sum(warm_dry_sa_df$warm_dry) / 8760 * 100,
                       sum(curr_wet_sp_df$curr_wet) / 8760 * 100, 
                       sum(curr_dry_sp_df$curr_dry) / 8760 * 100, 
                       sum(warm_wet_sp_df$warm_wet) / 8760 * 100, 
                       sum(warm_dry_sp_df$warm_dry) / 8760 * 100)) %>%
  knitr::kable(col.names = c("Biome", "Warming simulation", "Drought simulation", "$t_{act}$ (h)", "$t_{act}$ (%)"))
Biome Warming simulation Drought simulation \(t_{act}\) (h) \(t_{act}\) (%)
Subtropic current normal 3934 44.91
Subtropic current drought 3729 42.57
Subtropic warming normal 4268 48.72
Subtropic warming drought 4022 45.91
Tropic current normal 5561 63.48
Tropic current drought 4355 49.71
Tropic warming normal 5373 61.34
Tropic warming drought 4113 46.95
Semi-arid current normal 42 0.48
Semi-arid current drought 43 0.49
Semi-arid warming normal 79 0.90
Semi-arid warming drought 77 0.88
Mediterranean current normal 372 4.25
Mediterranean current drought 277 3.16
Mediterranean warming normal 907 10.35
Mediterranean warming drought 585 6.68

Table S7b - Relative change year

Table S7b. Change in \(t_{act}\) (%) f to the current normal scenario under warming only, drought only, and warming and drought combined for a hypothetical frog in different biomes.

data.frame(biome = c("Subtropic","Tropic", "Semi-arid", "Mediterranean"),
           curr_wet = c(sum(shad_curr_wet_df$curr_wet), sum(curr_wet_br_df$curr_wet), sum(curr_wet_sa_df$curr_wet), sum(curr_wet_sp_df$curr_wet)),
           curr_dry = c(sum(shad_curr_dry_df$curr_dry), sum(curr_dry_br_df$curr_dry), sum(curr_dry_sa_df$curr_dry), sum(curr_dry_sp_df$curr_dry)),
           warm_wet = c(sum(shad_warm_wet_df$warm_wet), sum(warm_wet_br_df$warm_wet), sum(warm_wet_sa_df$warm_wet), sum(warm_wet_sp_df$warm_wet)),
           warm_dry = c(sum(shad_warm_dry_df$warm_dry), sum(warm_dry_br_df$warm_dry), sum(warm_dry_sa_df$warm_dry), sum(warm_dry_sp_df$warm_dry))) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet) / curr_wet * 100,
                delta_dry      = (curr_dry - curr_wet) / curr_wet * 100,
                delta_warm_dry = (warm_dry - curr_wet) / curr_wet * 100) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  knitr::kable(col.names = c("Biome", "$\\Delta$ warming only (%)", "$\\Delta$ drought only (%)", "$\\Delta$ warming and drought (%)"))
Biome \(\Delta\) warming only (%) \(\Delta\) drought only (%) \(\Delta\) warming and drought (%)
Subtropic 8.5 -5.2 2.2
Tropic -3.4 -21.7 -26.0
Semi-arid 88.1 2.4 83.3
Mediterranean 143.8 -25.5 57.3

Table S7c - Relative change season

Table S7c. Change in \(t_{act}\) (%) relative to the current normal scenario under warming only, drought only, and warming and drought combined for a hypothetical frog in different biomes.

# summer
shad_model_summer <- shad_model %>%
  dplyr::filter(season == "summer") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

br_model_summer <- br_model %>%
  dplyr::filter(season == "summer") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

sa_model_summer <- sa_model %>%
  dplyr::filter(season == "summer") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

sp_model_summer <- sp_model %>%
  dplyr::filter(season == "summer") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tab_summer <- data.frame(biome = c("Subtropic","Tropic", "Semi-arid", "Mediterranean"),
           curr_wet = c(shad_model_summer$hours[4], br_model_summer$hours[4], sa_model_summer$hours[4], sp_model_summer$hours[4]), 
           curr_dry = c(shad_model_summer$hours[3], br_model_summer$hours[3], sa_model_summer$hours[3], sp_model_summer$hours[3]),
           warm_wet = c(shad_model_summer$hours[2], br_model_summer$hours[2], sa_model_summer$hours[2], sp_model_summer$hours[2]),
           warm_dry = c(shad_model_summer$hours[1], br_model_summer$hours[1], sa_model_summer$hours[1], sp_model_summer$hours[1])) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet) / curr_wet * 100,
                delta_dry      = (curr_dry - curr_wet) / curr_wet * 100,
                delta_warm_dry = (warm_dry - curr_wet) / curr_wet * 100) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  tibble::add_row(biome = "**Summer**", .before = 1)

# autumn
shad_model_autumn <- shad_model %>%
  dplyr::filter(season == "autumn") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

br_model_autumn <- br_model %>%
  dplyr::filter(season == "autumn") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

sa_model_autumn <- sa_model %>%
  dplyr::filter(season == "autumn") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

sp_model_autumn <- sp_model %>%
  dplyr::filter(season == "autumn") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tab_autumn <- data.frame(biome = c("Subtropic","Tropic", "Semi-arid", "Mediterranean"),
           curr_wet = c(shad_model_autumn$hours[4], br_model_autumn$hours[4], sa_model_autumn$hours[4], sp_model_autumn$hours[4]), 
           curr_dry = c(shad_model_autumn$hours[3], br_model_autumn$hours[3], sa_model_autumn$hours[3], sp_model_autumn$hours[3]),
           warm_wet = c(shad_model_autumn$hours[2], br_model_autumn$hours[2], sa_model_autumn$hours[2], sp_model_autumn$hours[2]),
           warm_dry = c(shad_model_autumn$hours[1], br_model_autumn$hours[1], sa_model_autumn$hours[1], sp_model_autumn$hours[1])) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet) / curr_wet * 100,
                delta_dry      = (curr_dry - curr_wet) / curr_wet * 100,
                delta_warm_dry = (warm_dry - curr_wet) / curr_wet * 100) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  tibble::add_row(biome = "**Autumn**", .before = 1)

# winter
shad_model_winter <- shad_model %>%
  dplyr::filter(season == "winter") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

br_model_winter <- br_model %>%
  dplyr::filter(season == "winter") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

sa_model_winter <- sa_model %>%
  dplyr::filter(season == "winter") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

sp_model_winter <- sp_model %>%
  dplyr::filter(season == "winter") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tab_winter <- data.frame(biome = c("Subtropic","Tropic", "Semi-arid", "Mediterranean"),
           curr_wet = c(shad_model_winter$hours[4], br_model_winter$hours[4], sa_model_winter$hours[4], sp_model_winter$hours[4]), 
           curr_dry = c(shad_model_winter$hours[3], br_model_winter$hours[3], sa_model_winter$hours[3], sp_model_winter$hours[3]),
           warm_wet = c(shad_model_winter$hours[2], br_model_winter$hours[2], sa_model_winter$hours[2], sp_model_winter$hours[2]),
           warm_dry = c(shad_model_winter$hours[1], br_model_winter$hours[1], sa_model_winter$hours[1], sp_model_winter$hours[1])) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet) / curr_wet * 100,
                delta_dry      = (curr_dry - curr_wet) / curr_wet * 100,
                delta_warm_dry = (warm_dry - curr_wet) / curr_wet * 100) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  tibble::add_row(biome = "**Winter**", .before = 1)

# spring
shad_model_spring <- shad_model %>%
  dplyr::filter(season == "spring") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

br_model_spring <- br_model %>%
  dplyr::filter(season == "spring") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

sa_model_spring <- sa_model %>%
  dplyr::filter(season == "spring") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

sp_model_spring <- sp_model %>%
  dplyr::filter(season == "spring") %>%
  dplyr::group_by(condition) %>%
  dplyr::summarise(hours = sum(hours))

tab_spring <- data.frame(biome = c("Subtropic","Tropic", "Semi-arid", "Mediterranean"),
           curr_wet = c(shad_model_spring$hours[4], br_model_spring$hours[4], sa_model_spring$hours[4], sp_model_spring$hours[4]), 
           curr_dry = c(shad_model_spring$hours[3], br_model_spring$hours[3], sa_model_spring$hours[3], sp_model_spring$hours[3]),
           warm_wet = c(shad_model_spring$hours[2], br_model_spring$hours[2], sa_model_spring$hours[2], sp_model_spring$hours[2]),
           warm_dry = c(shad_model_spring$hours[1], br_model_spring$hours[1], sa_model_spring$hours[1], sp_model_spring$hours[1])) %>%
  dplyr::mutate(delta_warm     = (warm_wet - curr_wet) / curr_wet * 100,
                delta_dry      = (curr_dry - curr_wet) / curr_wet * 100,
                delta_warm_dry = (warm_dry - curr_wet) / curr_wet * 100) %>%
  dplyr::select(-c(curr_wet:warm_dry)) %>%
  tibble::add_row(biome = "**Spring**", .before = 1)

# Render table
bind_rows(tab_summer, tab_autumn, tab_winter, tab_spring) %>% 
  remove_rownames() %>% 
  knitr::kable(col.names = c("Biome", "$\\Delta$ warming only (%)", "$\\Delta$ drought only (%)", "$\\Delta$ warming and drought (%)"))
Biome \(\Delta\) warming only (%) \(\Delta\) drought only (%) \(\Delta\) warming and drought (%)
Summer
Subtropic -8.39 -13.9 -21.8
Tropic -2.06 -13.7 -12.9
Semi-arid -9.09 9.1 0.0
Mediterranean -7.41 -3.7 -11.1
Autumn
Subtropic 4.75 -1.8 3.3
Tropic -3.93 -20.6 -25.9
Semi-arid 46.67 0.0 46.7
Mediterranean -0.81 -35.5 -28.2
Winter
Subtropic 72.88 -1.9 65.5
Tropic -2.37 -21.6 -30.9
Semi-arid 1300.00 0.0 1250.0
Mediterranean 601.47 -16.2 301.5
Spring
Subtropic 0.77 -2.8 -4.4
Tropic -5.02 -28.6 -29.7
Semi-arid 35.71 0.0 21.4
Mediterranean 84.31 -25.5 30.1

Figures

Code to produce the main document figures are detailed below. Figures produced were further modified in Adobe Illustrator for publication.

Figure 1 - AI risk

Create plots for main text figure 1.

# Reproject maps
rob_proj   <- "+proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs" 
world_rob  <- spTransform(world_spdf, CRSobj = rob_proj)

# land
data("land", package = "tmap")
land_raster <- as(land, "Raster") # convert from star to raster
land_df <- raster::as.data.frame(raster::rasterToPoints(land_raster))

elevation_raster <- projectRaster(land_raster$elevation, crs = rob_proj)
slope_raster     <- raster::terrain(elevation_raster, opt = 'slope')
aspect_raster    <- raster::terrain(elevation_raster, opt = 'aspect')
hill_raster      <- hillShade(slope_raster, aspect_raster, 40, 270) #setting the elevation angle (of the sun) to 40 and the direction angle of the light to 270
hill_m           <- rasterToPoints(hill_raster)
hill_df          <-  data.frame(hill_m)
colnames(hill_df) <- c("lon", "lat", "hill")

# Fig 1a - AI current
AI_rob    <- raster::projectRaster(ai_rast, crs = rob_proj)
AI_df_rob <- raster::as.data.frame(raster::rasterToPoints(AI_rob)) 
AI_df_rob <- AI_df_rob %>% 
  # Recode
  dplyr::mutate(category = case_when(
    is.infinite(layer) ~ 'Humid',
    layer >= 0.65 ~ 'Humid',                       
    layer >= 0.5 & layer < 0.65 ~ 'Dry sub-humid', 
    layer >= 0.2 & layer < 0.5 ~ 'Semi-arid',      
    layer >= 0.05 & layer < 0.2 ~ 'Arid',         
    layer < 0.05 ~ 'Hyper-arid'                    
  )) %>% 
  # Convert to ordered factor
  dplyr::mutate(category = factor(category,
                                  levels = c('Hyper-arid', 'Arid', 'Semi-arid',
                                             'Dry sub-humid', 'Humid'),
                                  ordered = TRUE))

AI_2C_rob    <- projectRaster(ai_2C_rast, crs = rob_proj)
AI_2C_df_rob <- raster::as.data.frame(raster::rasterToPoints(AI_2C_rob)) 
AI_2C_df_rob <- AI_2C_df_rob %>% 
  # Recode
  dplyr::mutate(category = case_when(
    is.infinite(layer) ~ 'Humid',
    layer >= 0.65 ~ 'Humid',                       
    layer >= 0.5 & layer < 0.65 ~ 'Dry sub-humid', 
    layer >= 0.2 & layer < 0.5 ~ 'Semi-arid',     
    layer >= 0.05 & layer < 0.2 ~ 'Arid',         
    layer < 0.05 ~ 'Hyper-arid'                
  )) %>% 
  # Convert to ordered factor
  dplyr::mutate(category = factor(category,
                                  levels = c('Hyper-arid', 'Arid', 'Semi-arid',
                                             'Dry sub-humid', 'Humid'),
                                  ordered = TRUE))

AI_4C_rob    <- projectRaster(ai_4C_rast, crs = rob_proj)
AI_4C_df_rob <- raster::as.data.frame(raster::rasterToPoints(AI_4C_rob)) 
AI_4C_df_rob <- AI_4C_df_rob %>% 
  # Recode
  dplyr::mutate(category = case_when(
    is.infinite(layer) ~ 'Humid',
    layer >= 0.65 ~ 'Humid',                       
    layer >= 0.5 & layer < 0.65 ~ 'Dry sub-humid', 
    layer >= 0.2 & layer < 0.5 ~ 'Semi-arid',      
    layer >= 0.05 & layer < 0.2 ~ 'Arid',         
    layer < 0.05 ~ 'Hyper-arid'                    
  )) %>% 
  # Convert to ordered factor
  dplyr::mutate(category = factor(category,
                                  levels = c('Hyper-arid', 'Arid', 'Semi-arid',
                                             'Dry sub-humid', 'Humid'),
                                  ordered = TRUE))

arid_col <- c('#8E063B', '#CB6D53', '#E99A2C', '#F5D579', 'white')
aridity_plot <- ggplot() +
  geom_raster(data = AI_df_rob, aes(y = y, x = x, fill = category)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = arid_col,
                    guide = guide_legend(reverse = TRUE)) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Aridity Index (1981-2010)") +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1)  

# Fig 1b - Species richness
anuran_rob    <- projectRaster(anuran_sr, crs = rob_proj)
anuran_df_rob <- raster::as.data.frame(raster::rasterToPoints(anuran_rob)) %>% dplyr::rename(species_n = layer)

sp_breaks = c(1, 5, 25, 100)
anuran_plot <- ggplot() +
  geom_raster(data = anuran_df_rob, aes(y = y, x = x, fill = species_n)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  colorspace::scale_fill_continuous_sequential(palette = "BluGrn", trans = "log",
                                               breaks = sp_breaks, labels = sp_breaks) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle("Anuran species richness") +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed()

AI_merged <- merge(AI_df_rob, AI_2C_df_rob, by = c("x", "y"), all.x = T) %>%
  merge(AI_4C_df_rob, by = c("x", "y"), all.x = T) %>%
  dplyr::rename(layer_current = layer.x,
                category_current = category.x,
                layer_2C  = layer.y,
                category_2C = category.y,
                layer_4C  = layer,
                category_4C = category) %>%
  dplyr::mutate(change_2C = (layer_2C - layer_current / layer_current) * 100,
                change_2C_AI = case_when(
                  change_2C >= -2 & change_2C <2 ~ 'No change to wetter',
                  change_2C >= -10 & change_2C < -2 ~ '>-2 to -10%',
                  change_2C >= -20 & change_2C < -10 ~ '>-10 to -20%',
                  change_2C >= -40 & change_2C < -20 ~ '>-20 to -40%',
                  change_2C >= -80 & change_2C < -40 ~ '>-40 to -80%',
                  change_2C < -80 ~ '<-80%'),
                  change_4C = (layer_4C - layer_current / layer_current) * 100,
                change_4C_AI = case_when(
                  change_4C >= -2 & change_4C <2 ~ 'No change to wetter',
                  change_4C >= -10 & change_4C < -2 ~ '>-2 to -10%',
                  change_4C >= -20 & change_4C < -10 ~ '>-10 to -20%',
                  change_4C >= -40 & change_4C < -20 ~ '>-20 to -40%',
                  change_4C >= -80 & change_4C < -40 ~ '>-40 to -80%',
                  change_4C < -80 ~ '<-80%'
                )) %>% 
  filter(category_current != "Hyper-arid") %>%
  dplyr::mutate(change_2C_AI = factor(change_2C_AI,
                                   levels = c('<-80%', '>-40 to -80%','>-20 to -40%',
                                              '>-10 to -20%', '>-2 to -10%', 'No change to wetter'),
                                   ordered = TRUE),
                change_4C_AI = factor(change_4C_AI,
                                   levels = c('<-80%', '>-40 to -80%','>-20 to -40%',
                                              '>-10 to -20%', '>-2 to -10%', 'No change to wetter'),
                                   ordered = TRUE))

change_col <- c('#9e5b13', '#bf832e', '#dab367', '#e8ca84', '#f0e0ad', 'white')

# Fig 1C - 2C Difference
change_2C_plot <- ggplot() +
  geom_raster(data = AI_merged, aes(y = y, x = x, fill = change_2C_AI)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = change_col, na.value = "white") +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void()+ ylab(NULL) + xlab(NULL) +
  ggtitle(expression("Change in dryness ("*Delta*"AI +2°C)")) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) 

# Fig 1d - 4C Difference
change_4C_plot <- ggplot() +
  geom_raster(data = AI_merged, aes(y = y, x = x, fill = change_4C_AI)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = change_col, na.value = "white") +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void()+ ylab(NULL) + xlab(NULL) +
  ggtitle(expression("Change in dryness ("*Delta*"AI +4°C)")) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) 

# Fig 1e - Dryness and species richness
arid_col_2 <- c("#8E063B", "#CB6D53", "#E99A2C", "#F5D579", "light grey")
species_ai_plot <- ai_sp_df %>% 
  ggplot(aes(x = aridity, y = species_n, colour = category)) +
  geom_point(size = 2) +
  coord_trans(x = "sqrt") +
  scale_colour_manual(values = arid_col_2,
                    guide = guide_legend(reverse = TRUE)) +
  scale_x_continuous(limits = c(0,3),
                     breaks = c(0, 0.05, 0.2, 0.5, 0.65)) +
  xlab("Precipitation / Evapotranspiration") +
  ylab("Species richness") +
  mytheme() + theme(legend.position = "none", axis.text.x = element_blank(), axis.ticks.x = element_blank())

# Fig 1f - Dryness and species richness by ecotype
ecotype_ai_plot <- ai_sp_df %>%
  dplyr::filter(aridity <=3) %>%
  dplyr::select(aridity, species_n:stream_n) %>%
  tidyr::pivot_longer(!aridity, names_to = "ecotype", values_to = "mean") %>%
  dplyr::filter(ecotype != "species_n") %>%
  drop_na(mean) %>%
  dplyr::mutate(ecotype = factor(ecotype, 
                                 levels = c("fossorial_n", "ground_n", "aquatic_n", 
                                            "arboreal_n", "semi_aq_n", "stream_n"))) %>%
  ggplot(aes(x = aridity, y = ecotype, group = ecotype, fill = ecotype)) +
  ggridges::stat_density_ridges(scale = 1, rel_min_height = 0.01, alpha = 0.5,
                                show.legend = FALSE) +
  scale_fill_viridis_d() +
  scale_x_continuous(trans = "sqrt") +
  labs(x = NULL, y = NULL) +
  mytheme()

# Fig 1g - Change in species AI
# Merge summary data by row
arid_sp_comb          <- data.frame(bind_rows(ai_sp_sum, ai_2C_sp_sum, ai_4C_sp_sum))
arid_sp_comb$scenario <- forcats::fct_relevel(arid_sp_comb$scenario, "Current")

species_occ_plot <- arid_sp_comb %>% 
  ggplot(aes(x = category, y = log(all_freq), group = scenario, colour = scenario, shape = scenario)) +
  geom_point(position = position_dodge(width = .5), size = 1.5) +
  scale_colour_manual(values = c("#F5D579", "#CB6D53", "#8E063B")) +
  scale_y_continuous(breaks = pretty(log(arid_sp_comb$all_freq)), labels = pretty(arid_sp_comb$all_freq)) +
  ylab("% species") + xlab(NULL) +
  mytheme() + theme(legend.position = "none")

# Fig 1
plot_grid(species_ai_plot, ecotype_ai_plot, species_occ_plot, align = "v", ncol = 3) # plot in between.
cowplot::plot_grid(aridity_plot + theme(legend.position = "bottom"), 
                   anuran_plot + theme(legend.position = "bottom"), 
                   change_2C_plot + theme(legend.position = "bottom"),
                   change_4C_plot + theme(legend.position = "bottom"),
                   align = "h", axis = "bt",
                   ncol = 2)

Figure 2 - PDSI risk

Create plots for main text figure 2.

PDSI_risk_rob <- raster::projectRaster(raster::stack(PDSI_2C_diff_rast, PDSI_4C_diff_rast, PDSI_freq_diff, PDSI_dur_diff,
                                                     resample(anuran_sr, PDSI_4C_diff_rast)), 
                                       crs = rob_proj)
                             
PDSI_risk_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_risk_rob)) %>%
  dplyr::rename("sp_n" = layer) %>%
  dplyr::filter(!is.na(sp_n)) %>%
  dplyr::mutate(delta_int_2C_bin = ifelse(delta_int_2C < -1, 1, 0), # delta_PDSI < -1
         delta_int_4C_bin = ifelse(delta_int_4C < -1, 1, 0), # delta_PDSI < -1
         delta_freq_2C_bin = ifelse(delta_freq_2C >1, 1, 0), # month > 1
         delta_freq_4C_bin = ifelse(delta_freq_4C >1, 1, 0), # month > 1
         delta_dur_2C_bin = ifelse(delta_dur_2C >1, 1, 0), # month > 1
         delta_dur_4C_bin = ifelse(delta_dur_4C >1, 1, 0)) %>% # month > 1 
  dplyr::rowwise() %>%
  dplyr::mutate(count_2C = sum(delta_int_2C_bin, delta_freq_2C_bin, delta_dur_2C_bin, na.rm = T),
         
         count_4C = sum(delta_int_4C_bin, delta_freq_4C_bin, delta_dur_4C_bin, na.rm = T),
         risk_2C  = sp_n * count_2C,
         risk_4C  = sp_n * count_4C,
         count_2C = factor(count_2C, levels = c("3", "2", "1")),
         count_4C = factor(count_4C, levels = c("3", "2", "1"))
         ) %>%
  data.frame()

# Plot
PDSI_risk_2C_plot <- ggplot() +
  geom_raster(data = PDSI_risk_df, aes(y = y, x = x, fill = count_2C)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_discrete_sequential(palette = "RedOr", rev = F) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle(expression("+2°C by 2080-2100")) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

PDSI_risk_4C_plot <- ggplot() +
  geom_raster(data = PDSI_risk_df, aes(y = y, x = x, fill = count_4C)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_discrete_sequential(palette = "RedOr", rev = F) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle(expression("+4°C by 2080-2100")) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

sp_2C_plot <- PDSI_risk_df %>%
  dplyr::mutate(risk_2C_cat = case_when(
    risk_2C == 0 ~ '0',
    risk_2C > 0 & risk_2C <=1 ~ '<1',
    risk_2C > 1 & risk_2C < 5 ~ '>1 to 5',
    risk_2C >= 5 & risk_2C < 10 ~ '>5 to 10',
    risk_2C >= 10 & risk_2C < 20 ~ '>10 to 20',
    risk_2C >= 20 & risk_2C < 100 ~ '>20 to 100',
    risk_2C >= 100 & risk_2C < 200 ~ '>100 to 200',
    risk_2C > 200 ~ '>200'),
    risk_2C = na_if(risk_2C, 0),
    risk_2C_cat = factor(risk_2C_cat,
                                   levels = c('>200','>100 to 200', '>20 to 100','>10 to 20', '>5 to 10', '>1 to 5', '<1'))) %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = risk_2C_cat)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_discrete_sequential(palette = "Heat", rev = F) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

sp_4C_plot <- PDSI_risk_df %>%
  dplyr::mutate(risk_4C_cat = case_when(
    risk_4C == 0 ~ '0',
    risk_4C > 0 & risk_4C <=1 ~ '<1',
    risk_4C > 1 & risk_4C < 5 ~ '>1 to 5',
    risk_4C >= 5 & risk_4C < 10 ~ '>5 to 10',
    risk_4C >= 10 & risk_4C < 20 ~ '>10 to 20',
    risk_4C >= 20 & risk_4C < 100 ~ '>20 to 100',
    risk_4C >= 100 & risk_4C < 200 ~ '>100 to 200',
    risk_4C > 200 ~ '>200'),
    risk_4C = na_if(risk_4C, 0),
    risk_4C_cat = factor(risk_4C_cat,
                                   levels = c('>200','>100 to 200', '>20 to 100','>10 to 20', '>5 to 10', '>1 to 5', '<1'))) %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = risk_4C_cat)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_discrete_sequential(palette = "Heat", rev = F) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

cowplot::plot_grid(PDSI_risk_2C_plot + theme(legend.position = "none"),
                   PDSI_risk_4C_plot + theme(legend.position = "none"),
                   sp_2C_plot + theme(legend.position = "none"),
                   sp_4C_plot + theme(legend.position = "none"),
                   ncol = 2,
                   align = "h", axis = "bt", labels = c('a', 'b', 'c', 'd'))
#PDSI_risk_df %>%
  #group_by(count_2C) %>%
  #summarise(length = length(count_2C)) %>%
  #mutate(freq = length / length(PDSI_risk_df$count_2C) * 100)

#PDSI_risk_df %>%
  #group_by(count_4C) %>%
  #summarise(length = length(count_4C)) %>%
  #mutate(freq = length / length(PDSI_risk_df$count_4C) * 100)

Figure 3 - Water loss risk

Run the ectotherm function from NicheMapR for all 12 months from the Terra Climate raster files containing the mean wind speed (m s-1), maximum air temperature (°C), and vapour pressure deficit (VPD; kPa) for the current (1981 to 2010), +2°C and +4°C scenario. From the ecotherm model, we extracted the EWL (g h-1) for each raster pixel to determine the spatial variation in EWL.

## Current ## ---------------------------------------
elev      <- getData("worldclim", var = "alt", res = 2.5)
ws_full   <-  raster::brick(file.path(spatial_path, 'TerraClimate19812010_ws.nc')) # 10m, m/s
tmax_full <- raster::brick(file.path(spatial_path, 'TerraClimate19812010_tmax.nc')) # 2m, deg C
vpd_full  <- raster::brick(file.path(spatial_path, 'TerraClimate19812010_vpd.nc')) # 2m, kpa
Tbs       <- crop(tmax_full, extent(elev))
EWLs      <- Tbs 

# Run ectotherm model for each month and save on local drive (current scenario)
for(month in 1:12){
  # Temperature
  Ta.w   <- crop(tmax_full[[month]], extent(elev))
  esat   <- VAPPRS(Ta.w)
  # RH
  e      <- esat - crop(vpd_full[[month]], extent(elev)) * 1000
  RH.w   <- e / esat * 100
  RH.w[RH.w < 0] <- 0
  # Wind speed
  Wind.w <- crop(ws_full[[month]], extent(elev))
  Vstar  <- 0.4 * Wind.w / log((100 / 0.15) + 1) # friction velocity
  Wind.w <- 2.5 * Vstar * log((1 / 0.15) + 1) # correct for reference height (10 m) to ground level (1 cm) assuming level ground
  # compute atmospheric pressure (kPa)
  P.w <- 101325 * ((1 - (0.0065 * elev / 288)) ^ (1 / 0.190284)) / 1000
  
  # Get raster values
  Ta  <- getValues(Ta.w)
  RH  <- getValues(RH.w)
  P   <- getValues(P.w)
  Pa  <- getValues(e)
  ws  <- getValues(Wind.w)
  P[!is.na(Ta) & is.na(P)] <- 101.325
  Ta2 <- Ta[!is.na(Ta)]
  RH2 <- RH[!is.na(Ta)]
  P2  <- P[!is.na(Ta)]
  ws2 <- ws[!is.na(Ta)]
  Pa2 <- Pa[!is.na(Ta)]
  
  div <- 10
  Twb <- Ta2[1:floor(length(Ta2) / div)]
  micro_base <- micro_global()
  
  for(k in 1:div){
    micro <- micro_base
    if(k == 1){
      extra <- round(24 - (length(Twb) / 24)%%1 * 24, 0)
      Twb4  <- c(Twb, rep(Ta2[1], extra))
      start <- 1
      end   <- length(Twb)
    }
    if(k > 1 & k < div){
      fact  <- (length(Twb) * (k - 1) + k - 1)
      Twb4  <- Ta2[fact:(fact + length(Twb))]
      extra <- round(24 - (length(Twb4) / 24)%%1 * 24, 0)
      Twb4  <- c(Twb4, rep(Ta2[1], extra))
      start <- fact
      end   <- fact + length(Twb)
    }        
    if(k == div){
      fact  <- (length(Twb) * (k - 1) + k - 1)
      Twb4  <- Ta2[fact:length(Ta2)]
      extra <- round(24 - (length(Twb4) / 24)%%1 * 24, 0)
      Twb4  <- c(Twb4, rep(Ta2[1], extra))
      start <- fact
      end   <- length(Ta2)
    } 
    
    soilnames     <- dimnames(micro$soil)
    metoutnames   <- dimnames(micro$metout)
    tcondnames    <- dimnames(micro$tcond)
    specheatnames <- dimnames(micro$specheat)
    densitnames   <- dimnames(micro$densit)
    plantnames    <- dimnames(micro$plant)
    
    micro$metout   <- t(array(micro$metout[1,], dim = c(ncol(micro$metout), length(Twb4))))
    dimnames(micro$metout) <- metoutnames
    micro$soil     <- t(array(micro$soil[1,], dim = c(ncol(micro$soil), length(Twb4))))
    dimnames(micro$soil) <- soilnames
    micro$tcond    <- t(array(micro$tcond[1,], dim = c(ncol(micro$tcond), length(Twb4))))
    dimnames(micro$tcond) <- tcondnames
    micro$specheat <- t(array(micro$specheat[1,], dim = c(ncol(micro$specheat), length(Twb4))))
    dimnames(micro$specheat) <- specheatnames  
    micro$densit   <- t(array(micro$densit[1,], dim = c(ncol(micro$densit), length(Twb4))))
    dimnames(micro$densit) <- densitnames      
    micro$plant    <- t(array(micro$plant[1,], dim = c(ncol(micro$plant), length(Twb4))))
    dimnames(micro$plant) <- plantnames 
    
    micro$shadmet <- micro$metout
    micro$shadsoil <- micro$soil
    micro$humid <- micro$soil
    micro$shadhumid <- micro$soil
    micro$soilpot <- micro$soil
    micro$shadpot <- micro$soil
    micro$soilmoist <- micro$soil
    micro$shadmoist <- micro$soil
    micro$shadtcond <- micro$tcond
    micro$shaddensit <- micro$densit
    micro$shadspecheat <- micro$specheat
    micro$shadplant <- micro$plant
    micro$RAINFALL <- rep(0, length(Twb4)/24)
    micro$minshade <- rep(0, length(Twb4)/24)
    micro$maxshade <- rep(90, length(Twb4)/24)
    micro$nyears <- ceiling(length(Twb4)/24/365)
    
    # replace first line of microclimate input with air temperature and humidity at which to compute Tw
    micro$metout[1:length(Twb4),c(3,4,14)] <- c(Ta2[start:end], rep(Ta2[1], extra)) # set air and sky temperature
    micro$metout[1:length(Twb4),c(5,6)] <- c(RH2[start:end], rep(RH2[1], extra)) # set relative humidity
    # micro$metout[1:length(Twb3),c(7,8)] <- 0.05 # set wind speed to low (sensitive to this)
    micro$soil[1:length(Twb4),3] <- c(Ta2[start:end], rep(Ta2[1], extra)) # set surface soil temperature to air temperature
    micro$metout[1:length(Twb4), 2] <- rep(seq(0, 23 * 60, 60), length(Ta2)/24 + 1)[1:length(Twb4)]
    #micro$metout[1:length(Twb3), 1] <- seq(0, 23 * 60, 60)[1:length(Twb3)]
    preshr <- c(P2[start:end], rep(P2[1], extra))*1000          
    
    micro$metout[1:length(Twb4),c(7,8)] <- c(ws2[start:end], rep(ws2[1], extra)) # set wind speed    
    
    # run the ectotherm model 
    message(paste('running ectotherm simulation for month ',month,' for ', length(Twb4),' sites \n'))
    ptm <- proc.time() # Start timing
    gc()
    ecto <- ectotherm(Ww_g = 8.7,
                      live = 0,
                      pct_wet = 87,
                      shape = 4, # frog
                      preshr = preshr)
    message(paste0('runtime ', (proc.time() - ptm)[3], ' seconds')) # Stop the clock
    gc()
    environ <- as.data.frame(ecto$environ)
    masbal  <- as.data.frame(ecto$masbal)
    if(k == 1){
      Tb.ectotherm  <- environ$TC[1:(nrow(environ) - extra)]
      EWL.ectotherm <- masbal$H2OCut_g[1:(nrow(masbal) - extra)]
    }else{
      Tb.ectotherm  <- c(Tb.ectotherm, environ$TC[1:(nrow(environ) - extra)])
      EWL.ectotherm <- c(EWL.ectotherm, masbal$H2OCut_g[1:(nrow(masbal) - extra)])
    }
  }
  Tb2     <- Ta
  Tb2[!is.na(Ta)] <- Tb.ectotherm
  Tb.grid <- Ta.w
  Tb.grid <- setValues(Tb.grid, Tb2)
  #plot(Tb.grid)
  #map('world', add = TRUE)
  
  EWL2 <- Ta
  EWL2[!is.na(Ta)] <- EWL.ectotherm
  EWL.grid <- Ta.w
  EWL.grid <- setValues(EWL.grid, EWL2)
  #plot(EWL.grid)
  EWL.grid[Tb.grid <= 0] <- NA
  #map('world', add = TRUE)

  writeRaster(EWL.grid, file = paste0('EWL_',month,'.nc'), overwrite = TRUE)
} 

## +2C ## ---------------------------------------
tmax_full_2C <- raster::brick(file.path(spatial_path, 'TerraClimate2C_tmax.nc')) # 2m, deg C
es_kPa_2C    <- tmax_full_2C
values(es_kPa_2C) <- 0.611 * exp(2500000 / 461.5 * ( 1 / 273 - 1 / (values(tmax_full_2C) + 273.15)))

# Actual vapour pressure
ea_kPa <- raster::brick(file.path(spatial_path, 'TerraClimate19812010_vap.nc'))
ea_kPa_2C <- ea_kPa
values(ea_kPa_2C) <- values(ea_kPa_2C) * 0.9

# Calculate VPD (kPa)
vpd_full_2C <- ea_kPa_2C
values(vpd_full_2C) <- values(es_kPa_2C) - values(ea_kPa_2C)

Tbs <- crop(tmax_full_2C, extent(elev))
EWLs <- Tbs 

# Run ectotherm model for each month and save on local drive (+2C scenario)
for(month in 1:12){
  Ta.w   <- crop(tmax_full_2C[[month]], extent(elev))
  esat   <- VAPPRS(Ta.w)
  e      <- esat - crop(vpd_full_2C[[month]], extent(elev)) * 1000
  RH.w   <- e / esat * 100
  RH.w[RH.w < 0] <- 0
  Wind.w <- crop(ws_full[[month]], extent(elev))
  Vstar  <- 0.4 * Wind.w / log((100 / 0.15) + 1) # friction velocity
  Wind.w <- 2.5 * Vstar * log((1 / 0.15) + 1) # correct for reference height (10 m) to ground level (1 cm) assuming level ground
  # compute atmospheric pressure (kPa)
  P.w <- 101325 * ((1 - (0.0065 * elev / 288)) ^ (1 / 0.190284)) / 1000
  
  Ta  <- getValues(Ta.w)
  RH  <- getValues(RH.w)
  P   <- getValues(P.w)
  Pa  <- getValues(e)
  ws  <- getValues(Wind.w)
  P[!is.na(Ta) & is.na(P)] <- 101.325
  Ta2 <- Ta[!is.na(Ta)]
  RH2 <- RH[!is.na(Ta)]
  P2  <- P[!is.na(Ta)]
  ws2 <- ws[!is.na(Ta)]
  Pa2 <- Pa[!is.na(Ta)]
  
  div <- 10
  Twb <- Ta2[1:floor(length(Ta2) / div)]
  micro_base <- micro_global()
  
  for(k in 1:div){
    micro <- micro_base
    if(k == 1){
      extra <- round(24 - (length(Twb) / 24)%%1 * 24, 0)
      Twb4  <- c(Twb, rep(Ta2[1], extra))
      start <- 1
      end   <- length(Twb)
    }
    if(k > 1 & k < div){
      fact  <- (length(Twb) * (k - 1) + k - 1)
      Twb4  <- Ta2[fact:(fact + length(Twb))]
      extra <- round(24 - (length(Twb4) / 24)%%1 * 24, 0)
      Twb4  <- c(Twb4, rep(Ta2[1], extra))
      start <- fact
      end   <- fact + length(Twb)
    }        
    if(k == div){
      fact  <- (length(Twb) * (k - 1) + k - 1)
      Twb4  <- Ta2[fact:length(Ta2)]
      extra <- round(24 - (length(Twb4) / 24)%%1 * 24, 0)
      Twb4  <- c(Twb4, rep(Ta2[1], extra))
      start <- fact
      end   <- length(Ta2)
    } 
    
    soilnames     <- dimnames(micro$soil)
    metoutnames   <- dimnames(micro$metout)
    tcondnames    <- dimnames(micro$tcond)
    specheatnames <- dimnames(micro$specheat)
    densitnames   <- dimnames(micro$densit)
    plantnames    <- dimnames(micro$plant)
    
    micro$metout   <- t(array(micro$metout[1,], dim = c(ncol(micro$metout), length(Twb4))))
    dimnames(micro$metout) <- metoutnames
    micro$soil     <- t(array(micro$soil[1,], dim = c(ncol(micro$soil), length(Twb4))))
    dimnames(micro$soil) <- soilnames
    micro$tcond    <- t(array(micro$tcond[1,], dim = c(ncol(micro$tcond), length(Twb4))))
    dimnames(micro$tcond) <- tcondnames
    micro$specheat <- t(array(micro$specheat[1,], dim = c(ncol(micro$specheat), length(Twb4))))
    dimnames(micro$specheat) <- specheatnames  
    micro$densit   <- t(array(micro$densit[1,], dim = c(ncol(micro$densit), length(Twb4))))
    dimnames(micro$densit) <- densitnames      
    micro$plant    <- t(array(micro$plant[1,], dim = c(ncol(micro$plant), length(Twb4))))
    dimnames(micro$plant) <- plantnames 
    
    micro$shadmet      <- micro$metout
    micro$shadsoil     <- micro$soil
    micro$humid        <- micro$soil
    micro$shadhumid    <- micro$soil
    micro$soilpot      <- micro$soil
    micro$shadpot      <- micro$soil
    micro$soilmoist    <- micro$soil
    micro$shadmoist    <- micro$soil
    micro$shadtcond    <- micro$tcond
    micro$shaddensit   <- micro$densit
    micro$shadspecheat <- micro$specheat
    micro$shadplant    <- micro$plant
    micro$RAINFALL     <- rep(0, length(Twb4)/24)
    micro$minshade     <- rep(0, length(Twb4)/24)
    micro$maxshade     <- rep(90, length(Twb4)/24)
    micro$nyears       <- ceiling(length(Twb4)/24/365)
    
    # replace first line of microclimate input with air temperature and humidity at which to compute Tw
    micro$metout[1:length(Twb4),c(3,4,14)] <- c(Ta2[start:end], rep(Ta2[1], extra)) # set air and sky temperature
    micro$metout[1:length(Twb4),c(5,6)]    <- c(RH2[start:end], rep(RH2[1], extra)) # set relative humidity
    # micro$metout[1:length(Twb3),c(7,8)] <- 0.05 # set wind speed to low (sensitive to this)
    micro$soil[1:length(Twb4),3] <- c(Ta2[start:end], rep(Ta2[1], extra)) # set surface soil temperature to air temperature
    micro$metout[1:length(Twb4), 2] <- rep(seq(0, 23 * 60, 60), length(Ta2)/24 + 1)[1:length(Twb4)]
    #micro$metout[1:length(Twb3), 1] <- seq(0, 23 * 60, 60)[1:length(Twb3)]
    preshr <- c(P2[start:end], rep(P2[1], extra))*1000          
    
    micro$metout[1:length(Twb4),c(7,8)] <- c(ws2[start:end], rep(ws2[1], extra)) # set wind speed    
    
    # run the ectotherm model 
    message(paste('running ectotherm simulation for month ',month,' for ', length(Twb4),' sites \n'))
    ptm <- proc.time() # Start timing
    gc()
    ecto <- ectotherm(Ww_g = 8.7,
                      live = 0,
                      pct_wet = 87,
                      shape = 4, # frog
                      preshr = preshr)
    message(paste0('runtime ', (proc.time() - ptm)[3], ' seconds')) # Stop the clock
    gc()
    environ <- as.data.frame(ecto$environ)
    masbal <- as.data.frame(ecto$masbal)
    if(k == 1){
      Tb.ectotherm <- environ$TC[1:(nrow(environ) - extra)]
      EWL.ectotherm <- masbal$H2OCut_g[1:(nrow(masbal) - extra)]
    }else{
      Tb.ectotherm <- c(Tb.ectotherm, environ$TC[1:(nrow(environ) - extra)])
      EWL.ectotherm <- c(EWL.ectotherm, masbal$H2OCut_g[1:(nrow(masbal) - extra)])
    }
  }
  Tb2 <- Ta
  Tb2[!is.na(Ta)] <- Tb.ectotherm
  Tb.grid <- Ta.w
  Tb.grid <- setValues(Tb.grid, Tb2)
  #plot(Tb.grid)
  #map('world', add = TRUE)
  
  EWL2 <- Ta
  EWL2[!is.na(Ta)] <- EWL.ectotherm
  EWL.grid <- Ta.w
  EWL.grid <- setValues(EWL.grid, EWL2)
  #plot(EWL.grid)
  EWL.grid[Tb.grid <= 0] <- NA
  #map('world', add = TRUE)
  
  writeRaster(EWL.grid, file = paste0('EWL_',month,'_2C.nc'), overwrite=TRUE)
}  

## +4C ## ---------------------------------------
# Saturated vapour pressure
tmax_full_4C <- raster::brick(file.path(spatial_path, 'TerraClimate4C_tmax.nc')) # 2m, deg C
es_kPa_4C    <- tmax_full_4C
values(es_kPa_4C) <- 0.611 * exp(2500000 / 461.5 * ( 1 / 273 - 1 / (values(tmax_full_4C) + 273.15)))

# Actual vapour pressure
ea_kPa      <- raster::brick(file.path(spatial_path, 'TerraClimate19812010_vap.nc'))
ea_kPa_4C   <- ea_kPa
values(ea_kPa_4C) <- values(ea_kPa_4C) * 0.8

# Calculate VPD (kPa)
vpd_full_4C <- ea_kPa_4C
values(vpd_full_4C) <- values(es_kPa_4C) - values(ea_kPa_4C)

Tbs  <- crop(tmax_full_4C, extent(elev))
EWLs <- Tbs 

# Run ectotherm model for each month and save on local drive (+4C scenario)
for(month in 1:12){
  Ta.w   <- crop(tmax_full_4C[[month]], extent(elev))
  esat   <- VAPPRS(Ta.w)
  e      <- esat - crop(vpd_full_4C[[month]], extent(elev)) * 1000
  RH.w   <- e / esat * 100
  RH.w[RH.w < 0] <- 0
  Wind.w <- crop(ws_full[[month]], extent(elev))
  Vstar  <- 0.4 * Wind.w / log((100 / 0.15) + 1) # friction velocity
  Wind.w <- 2.5 * Vstar * log((1 / 0.15) + 1) # correct for reference height (10 m) to ground level (1 cm) assuming level ground
  # compute atmospheric pressure (kPa)
  P.w <- 101325 * ((1 - (0.0065 * elev / 288)) ^ (1 / 0.190284)) / 1000
  
  Ta  <- getValues(Ta.w)
  RH  <- getValues(RH.w)
  P   <- getValues(P.w)
  Pa  <- getValues(e)
  ws  <- getValues(Wind.w)
  P[!is.na(Ta) & is.na(P)] <- 101.325
  Ta2 <- Ta[!is.na(Ta)]
  RH2 <- RH[!is.na(Ta)]
  P2  <- P[!is.na(Ta)]
  ws2 <- ws[!is.na(Ta)]
  Pa2 <- Pa[!is.na(Ta)]
  
  div <- 10
  Twb <- Ta2[1:floor(length(Ta2) / div)]
  micro_base <- micro_global()
  
  for(k in 1:div){
    micro <- micro_base
    if(k == 1){
      extra <- round(24 - (length(Twb) / 24)%%1 * 24, 0)
      Twb4  <- c(Twb, rep(Ta2[1], extra))
      start <- 1
      end   <- length(Twb)
    }
    if(k > 1 & k < div){
      fact  <- (length(Twb) * (k - 1) + k - 1)
      Twb4  <- Ta2[fact:(fact + length(Twb))]
      extra <- round(24 - (length(Twb4) / 24)%%1 * 24, 0)
      Twb4  <- c(Twb4, rep(Ta2[1], extra))
      start <- fact
      end   <- fact + length(Twb)
    }        
    if(k == div){
      fact  <- (length(Twb) * (k - 1) + k - 1)
      Twb4  <- Ta2[fact:length(Ta2)]
      extra <- round(24 - (length(Twb4) / 24)%%1 * 24, 0)
      Twb4  <- c(Twb4, rep(Ta2[1], extra))
      start <- fact
      end   <- length(Ta2)
    } 
    
    soilnames     <- dimnames(micro$soil)
    metoutnames   <- dimnames(micro$metout)
    tcondnames    <- dimnames(micro$tcond)
    specheatnames <- dimnames(micro$specheat)
    densitnames   <- dimnames(micro$densit)
    plantnames    <- dimnames(micro$plant)
    
    micro$metout   <- t(array(micro$metout[1,], dim = c(ncol(micro$metout), length(Twb4))))
    dimnames(micro$metout) <- metoutnames
    micro$soil     <- t(array(micro$soil[1,], dim = c(ncol(micro$soil), length(Twb4))))
    dimnames(micro$soil) <- soilnames
    micro$tcond    <- t(array(micro$tcond[1,], dim = c(ncol(micro$tcond), length(Twb4))))
    dimnames(micro$tcond) <- tcondnames
    micro$specheat <- t(array(micro$specheat[1,], dim = c(ncol(micro$specheat), length(Twb4))))
    dimnames(micro$specheat) <- specheatnames  
    micro$densit   <- t(array(micro$densit[1,], dim = c(ncol(micro$densit), length(Twb4))))
    dimnames(micro$densit) <- densitnames      
    micro$plant    <- t(array(micro$plant[1,], dim = c(ncol(micro$plant), length(Twb4))))
    dimnames(micro$plant) <- plantnames 
    
    micro$shadmet      <- micro$metout
    micro$shadsoil     <- micro$soil
    micro$humid        <- micro$soil
    micro$shadhumid    <- micro$soil
    micro$soilpot      <- micro$soil
    micro$shadpot      <- micro$soil
    micro$soilmoist    <- micro$soil
    micro$shadmoist    <- micro$soil
    micro$shadtcond    <- micro$tcond
    micro$shaddensit   <- micro$densit
    micro$shadspecheat <- micro$specheat
    micro$shadplant    <- micro$plant
    micro$RAINFALL     <- rep(0, length(Twb4)/24)
    micro$minshade     <- rep(0, length(Twb4)/24)
    micro$maxshade     <- rep(90, length(Twb4)/24)
    micro$nyears       <- ceiling(length(Twb4)/24/365)
    
    # replace first line of microclimate input with air temperature and humidity at which to compute Tw
    micro$metout[1:length(Twb4),c(3,4,14)] <- c(Ta2[start:end], rep(Ta2[1], extra)) # set air and sky temperature
    micro$metout[1:length(Twb4),c(5,6)]    <- c(RH2[start:end], rep(RH2[1], extra)) # set relative humidity
    # micro$metout[1:length(Twb3),c(7,8)] <- 0.05 # set wind speed to low (sensitive to this)
    micro$soil[1:length(Twb4),3] <- c(Ta2[start:end], rep(Ta2[1], extra)) # set surface soil temperature to air temperature
    micro$metout[1:length(Twb4), 2] <- rep(seq(0, 23 * 60, 60), length(Ta2)/24 + 1)[1:length(Twb4)]
    #micro$metout[1:length(Twb3), 1] <- seq(0, 23 * 60, 60)[1:length(Twb3)]
    preshr <- c(P2[start:end], rep(P2[1], extra))*1000          
    
    micro$metout[1:length(Twb4),c(7,8)] <- c(ws2[start:end], rep(ws2[1], extra)) # set wind speed    
    
    # run the ectotherm model 
    message(paste('running ectotherm simulation for month ',month,' for ', length(Twb4),' sites \n'))
    ptm <- proc.time() # Start timing
    gc()
    ecto <- ectotherm(Ww_g = 8.7,
                      live = 0,
                      pct_wet = 87,
                      shape = 4, # frog
                      preshr = preshr)
    message(paste0('runtime ', (proc.time() - ptm)[3], ' seconds')) # Stop the clock
    gc()
    environ <- as.data.frame(ecto$environ)
    masbal <- as.data.frame(ecto$masbal)
    if(k == 1){
      Tb.ectotherm <- environ$TC[1:(nrow(environ) - extra)]
      EWL.ectotherm <- masbal$H2OCut_g[1:(nrow(masbal) - extra)]
    }else{
      Tb.ectotherm <- c(Tb.ectotherm, environ$TC[1:(nrow(environ) - extra)])
      EWL.ectotherm <- c(EWL.ectotherm, masbal$H2OCut_g[1:(nrow(masbal) - extra)])
    }
  }
  Tb2 <- Ta
  Tb2[!is.na(Ta)] <- Tb.ectotherm
  Tb.grid <- Ta.w
  Tb.grid <- setValues(Tb.grid, Tb2)
  #plot(Tb.grid)
  #map('world', add = TRUE)
  
  EWL2 <- Ta
  EWL2[!is.na(Ta)] <- EWL.ectotherm
  EWL.grid <- Ta.w
  EWL.grid <- setValues(EWL.grid, EWL2)
  #plot(EWL.grid)
  EWL.grid[Tb.grid <= 0] <- NA
  #map('world', add = TRUE)
  
  writeRaster(EWL.grid, file = paste0('EWL_',month,'_4C.nc'), overwrite=TRUE)
}  

Create plots for main text figure 3.

# Import the downloaded files
EWL_jan <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_1.nc')), anuran_sr)
EWL_feb <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_2.nc')), anuran_sr)
EWL_mar <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_3.nc')), anuran_sr)
EWL_apr <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_4.nc')), anuran_sr)
EWL_may <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_5.nc')), anuran_sr)
EWL_jun <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_6.nc')), anuran_sr)
EWL_jul <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_7.nc')), anuran_sr)
EWL_aug <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_8.nc')), anuran_sr)
EWL_sep <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_9.nc')), anuran_sr)
EWL_oct <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_10.nc')), anuran_sr)
EWL_nov <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_11.nc')), anuran_sr)
EWL_dec <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_12.nc')), anuran_sr)

EWL_jan_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_1_2C.nc')), anuran_sr)
EWL_feb_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_2_2C.nc')), anuran_sr)
EWL_mar_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_3_2C.nc')), anuran_sr)
EWL_apr_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_4_2C.nc')), anuran_sr)
EWL_may_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_5_2C.nc')), anuran_sr)
EWL_jun_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_6_2C.nc')), anuran_sr)
EWL_jul_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_7_2C.nc')), anuran_sr)
EWL_aug_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_8_2C.nc')), anuran_sr)
EWL_sep_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_9_2C.nc')), anuran_sr)
EWL_oct_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_10_2C.nc')), anuran_sr)
EWL_nov_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_11_2C.nc')), anuran_sr)
EWL_dec_2C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_12_2C.nc')), anuran_sr)

EWL_jan_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_1_4C.nc')), anuran_sr)
EWL_feb_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_2_4C.nc')), anuran_sr)
EWL_mar_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_3_4C.nc')), anuran_sr)
EWL_apr_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_4_4C.nc')), anuran_sr)
EWL_may_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_5_4C.nc')), anuran_sr)
EWL_jun_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_6_4C.nc')), anuran_sr)
EWL_jul_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_7_4C.nc')), anuran_sr)
EWL_aug_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_8_4C.nc')), anuran_sr)
EWL_sep_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_9_4C.nc')), anuran_sr)
EWL_oct_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_10_4C.nc')), anuran_sr)
EWL_nov_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_11_4C.nc')), anuran_sr)
EWL_dec_4C <- raster::projectRaster(raster::stack(file.path(spatial_path, 'EWL_12_4C.nc')), anuran_sr)

# Combine all
EWL_all <- raster::stack(EWL_jan, EWL_feb, EWL_mar, EWL_apr, EWL_may, EWL_jun, 
                         EWL_jul, EWL_aug, EWL_sep, EWL_oct, EWL_nov, EWL_dec)

EWL_all_2C <- raster::stack(EWL_jan_2C, EWL_feb_2C, EWL_mar_2C, EWL_apr_2C, EWL_may_2C, EWL_jun_2C, 
                            EWL_jul_2C, EWL_aug_2C, EWL_sep_2C, EWL_oct_2C, EWL_nov_2C, EWL_dec_2C)

EWL_all_4C <- raster::stack(EWL_jan_4C, EWL_feb_4C, EWL_mar_4C, EWL_apr_4C, EWL_may_4C, EWL_jun_4C, 
                            EWL_jul_4C, EWL_aug_4C, EWL_sep_4C, EWL_oct_4C, EWL_nov_4C, EWL_dec_4C)

EWL_all_mean    <- raster::calc(EWL_all, fun = mean, na.rm = TRUE)
EWL_all_mean_2C <- raster::calc(EWL_all_2C, fun = mean, na.rm = TRUE)
EWL_all_mean_4C <- raster::calc(EWL_all_4C, fun = mean, na.rm = TRUE)

EWL_diff_2C <- raster::overlay(x = EWL_all_mean, y = EWL_all_mean_2C, 
                                fun = function(x, y) {return(y - x)}) 

EWL_diff_4C <- raster::overlay(x = EWL_all_mean, y = EWL_all_mean_4C, 
                                fun = function(x, y) {return(y - x)}) 

EWL_risk_rob    <- raster::projectRaster(raster::stack(EWL_all_mean, anuran_sr, aquatic_sr,
                                                       arboreal_sr, fossorial_sr,
                                                       ground_sr, semi_aq_sr,
                                                       stream_sr), crs = rob_proj)
EWL_risk_rob_2C <- raster::projectRaster(raster::stack(EWL_diff_2C, anuran_sr), crs = rob_proj)
EWL_risk_rob_4C <- raster::projectRaster(raster::stack(EWL_diff_4C, anuran_sr), crs = rob_proj)

EWL_sp_df <- raster::as.data.frame(raster::rasterToPoints(EWL_risk_rob)) %>% 
  rename(EWL       = layer.1, 
         species_n = layer.2,
         aqua_sp = layer.3,
         arbo_sp = layer.4,
         foss_sp = layer.5,
         gron_sp = layer.6,
         semi_sp = layer.7,
         strm_sp = layer.8) %>%
  drop_na(species_n)

EWL_sp_2C_df <- raster::as.data.frame(raster::rasterToPoints(EWL_risk_rob_2C)) %>% 
  rename(EWL_diff  = layer.1, 
         species_n = layer.2) %>%
  drop_na(species_n)

EWL_sp_4C_df <- raster::as.data.frame(raster::rasterToPoints(EWL_risk_rob_4C)) %>% 
  rename(EWL_diff  = layer.1, 
         species_n = layer.2) %>%
  drop_na(species_n)

# Fig. 3a
EWL_cur_plot <- EWL_sp_df %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = EWL)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_continuous_sequential(palette = "YlGnBu", rev = T, 
                                   name = expression("EWL"~("g"~H[2]*O~h^{"-1"}))) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  guides(fill = guide_colourbar(barwidth = 20, barheight = 0.2, 
                                label.position = "bottom")) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10),
        legend.title = element_text(size = 8), 
        legend.position = "bottom") +
  coord_fixed(ratio = 1) # fixed ratio

# Fig. 3b - Species richness and EWL
EWL_sp_plot <- EWL_sp_df %>%
  ggplot(aes(x = EWL, y = species_n)) +
  geom_point(colour = "grey") +
  xlab(expression("EWL"~("g"~H[2]*O~h^{"-1"}))) +
  ylab("Species richness") +
  scale_y_continuous(expand = c(0, 0)) +
  scale_x_continuous(breaks = seq(0, 3, 0.5), expand = c(0, 0)) + 
  mytheme()

# Fig. 3c +2C
EWL_2C_plot <- EWL_sp_2C_df %>%
  dplyr::mutate(EWL_diff_cat = case_when(
    EWL_diff == 0 ~ '0',
    EWL_diff > 0 & EWL_diff <=1 ~ '<1',
    EWL_diff >= 1 & EWL_diff < 1.5 ~ '>1 to 1.5',
    EWL_diff >= 1.5 & EWL_diff < 2 ~ '>1.5 to 2',
    EWL_diff >= 2 & EWL_diff < 2.5 ~ '>2 to 2.5',
    EWL_diff >= 2.5 & EWL_diff < 3 ~ '>2.5 to 3',
    EWL_diff > 3 ~ '>3'),
    EWL_diff = na_if(EWL_diff, 0),
    EWL_diffcat = factor(EWL_diff_cat,
                                   levels = c('>3', '<2.5 to 3','>2 to 2.5', '1.5 to 2', '>1 to 1.5', '<1'))) %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = EWL_diff_cat)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#E2E6BD", "#E7CB47", "#EAAB28", "#E78A38", "#DF6753", "#D33F6A"), na.translate = F, name = expression(Delta*"EWL"~("g"~H[2]*O~h^{"-1"}))) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  guides(fill = guide_colourbar(barwidth = 20, barheight = 0.2, 
                                label.position = "bottom")) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10),
        legend.title = element_text(size = 8), 
        legend.position = "bottom") +
  coord_fixed(ratio = 1) # fixed ratio

# Fig. 3d +4C
EWL_4C_plot <- EWL_sp_4C_df %>%
  dplyr::mutate(EWL_diff_cat = case_when(
    EWL_diff == 0 ~ '0',
    EWL_diff > 0 & EWL_diff <=1 ~ '<1',
    EWL_diff >= 1 & EWL_diff < 1.5 ~ '>1 to 1.5',
    EWL_diff >= 1.5 & EWL_diff < 2 ~ '>1.5 to 2',
    EWL_diff >= 2 & EWL_diff < 2.5 ~ '>2 to 2.5',
    EWL_diff >= 2.5 & EWL_diff < 3 ~ '>2.5 to 3',
    EWL_diff > 3 ~ '>3'),
    EWL_diff = na_if(EWL_diff, 0),
    EWL_diffcat = factor(EWL_diff_cat,
                                   levels = c('>3', '<2.5 to 3','>2 to 2.5', '1.5 to 2', '>1 to 1.5', '<1'))) %>%
  ggplot() +
  geom_raster(aes(y = y, x = x, fill = EWL_diff_cat)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#E2E6BD", "#E7CB47", "#EAAB28", "#E78A38", "#DF6753", "#D33F6A"), na.translate = F, name = expression(Delta*"EWL"~("g"~H[2]*O~h^{"-1"}))) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  guides(fill = guide_colourbar(barwidth = 20, barheight = 0.2, 
                                label.position = "bottom")) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10),
        legend.title = element_text(size = 8), 
        legend.position = "bottom") +
  coord_fixed(ratio = 1) # fixed ratio

cowplot::plot_grid(EWL_cur_plot,
                   EWL_sp_plot,
                   EWL_2C_plot,
                   EWL_4C_plot,
                   ncol = 2,
                   align = "h", axis = "bt", labels = c('a', 'b', 'c', 'd'))

Figure 4 - Activity risk - ecotype

Create plots for main text figure 4.

shad_plot <- shad_model %>%
  ggplot(aes(x = day, y = condition, fill = hours)) + 
  geom_tile() +
  viridis::scale_fill_viridis(option = "magma") +
  #scale_fill_continuous_diverging(palette = "Blue-Red 3", mid = 12, rev = TRUE) +
  ylab(NULL) + xlab("Day of the year") + 
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom") +
  guides(fill = guide_colourbar(barheight = 0.5, barwidth = 5, label.position = "bottom")) 

tree_plot <- tree_model %>%
  ggplot(aes(x = day, y = condition, fill = hours)) + 
  geom_tile() +
  viridis::scale_fill_viridis(option = "magma") +
  #scale_fill_continuous_diverging(palette = "Blue-Red 3", mid = 12, rev = TRUE) +
  ylab(NULL) + xlab("Day of the year") + 
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom") +
  guides(fill = guide_colourbar(barheight = 0.5, barwidth = 5, label.position = "bottom")) 

burr_plot <- burr_model %>%
  ggplot(aes(x = day, y = condition, fill = hours)) + 
  geom_tile() +
  viridis::scale_fill_viridis(option = "magma") +
  #scale_fill_continuous_diverging(palette = "Blue-Red 3", mid = 12, rev = TRUE) +
  ylab(NULL) + xlab("Day of the year") +
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom") +
  guides(fill = guide_colourbar(barheight = 0.5, barwidth = 5, label.position = "bottom")) 

prow_2 <- cowplot::plot_grid(
  shad_plot + theme(legend.position ="none"), 
  tree_plot + theme(legend.position ="none"), 
  burr_plot + theme(legend.position ="none"),
  ncol = 1, labels = c('a', 'c', 'e'),
  align = 'v', axis = 'l')

legend_b_2 <- cowplot::get_legend(burr_plot + guides(color = guide_legend(nrow = 1)))
top_graph  <- cowplot::plot_grid(prow_2, legend_b_2, ncol = 1, rel_heights = c(1, .1))

# Relative change
shad_diff_model <- shad_curr_wet_df %>%
  merge(shad_curr_dry_df, by = "day") %>%
  merge(shad_warm_wet_df, by = "day") %>%
  merge(shad_warm_dry_df, by = "day") %>%
  dplyr::mutate(curr_dry_diff = curr_dry - curr_wet,
                warm_wet_diff = warm_wet - curr_wet,
                warm_dry_diff = warm_dry - curr_wet) %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::filter(condition == c("curr_dry_diff", "warm_wet_diff", "warm_dry_diff")) %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry_diff", "warm_wet_diff", "curr_dry_diff"))) %>%
  ggplot(aes(x = day, y = condition, fill = hours)) + 
  geom_tile() +
  scale_fill_continuous_diverging(palette = "Blue-Red 3", mid = 0, rev = TRUE, limits = c(-15, 15)) +
  ylab(NULL) + xlab("Day of the year") + 
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom") +
  guides(fill = guide_colourbar(barheight = 0.5, barwidth = 5, label.position = "bottom")) 

tree_diff_model <- tree_curr_wet_df %>%
  merge(tree_curr_dry_df, by = "day") %>%
  merge(tree_warm_wet_df, by = "day") %>%
  merge(tree_warm_dry_df, by = "day") %>%
  dplyr::mutate(curr_dry_diff = curr_dry - curr_wet,
                warm_wet_diff = warm_wet - curr_wet,
                warm_dry_diff = warm_dry - curr_wet) %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::filter(condition == c("curr_dry_diff", "warm_wet_diff", "warm_dry_diff")) %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry_diff", "warm_wet_diff", "curr_dry_diff"))) %>%
  ggplot(aes(x = day, y = condition, fill = hours)) + 
  geom_tile() +
  scale_fill_continuous_diverging(palette = "Blue-Red 3", mid = 0, rev = TRUE, limits = c(-15, 15)) +
  ylab(NULL) + xlab("Day of the year") + 
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom") +
  guides(fill = guide_colourbar(barheight = 0.5, barwidth = 5, label.position = "bottom")) 

burr_diff_model <- burr_curr_wet_df %>%
  merge(burr_curr_dry_df, by = "day") %>%
  merge(burr_warm_wet_df, by = "day") %>%
  merge(burr_warm_dry_df, by = "day") %>%
  dplyr::mutate(curr_dry_diff = curr_dry - curr_wet,
                warm_wet_diff = warm_wet - curr_wet,
                warm_dry_diff = warm_dry - curr_wet) %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::filter(condition == c("curr_dry_diff", "warm_wet_diff", "warm_dry_diff")) %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry_diff", "warm_wet_diff", "curr_dry_diff"))) %>%
  ggplot(aes(x = day, y = condition, fill = hours)) + 
  geom_tile() +
  scale_fill_continuous_diverging(palette = "Blue-Red 3", mid = 0, rev = TRUE, limits = c(-15, 15)) +
  ylab(NULL) + xlab("Day of the year") + 
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom") +
  guides(fill = guide_colourbar(barheight = 0.5, barwidth = 5, label.position = "bottom")) 

bot_graph <- cowplot::plot_grid(
  shad_diff_model, 
  tree_diff_model, 
  burr_diff_model,
  ncol = 1, labels = c('b', 'd', 'g'),
  align = 'v', axis = 'l')

cowplot::plot_grid(top_graph, bot_graph)

Figure 5 - Activity risk - biome

Create plots for main text figure 5.

au_comb_plot <- cowplot::plot_grid(au_plot, 
                   shad_diff_model + scale_x_continuous(breaks = seq(0, 365, 100), expand = c(0, 0)), 
                   ncol = 1, align = 'v',  rel_heights = c(0.7, 1))

br_diff_plot <- curr_wet_br_df %>%
  merge(curr_dry_br_df, by = "day") %>%
  merge(warm_wet_br_df, by = "day") %>%
  merge(warm_dry_br_df, by = "day") %>%
  dplyr::mutate(curr_dry_diff = curr_dry - curr_wet,
                warm_wet_diff = warm_wet - curr_wet,
                warm_dry_diff = warm_dry - curr_wet) %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::filter(condition == c("curr_dry_diff", "warm_wet_diff", "warm_dry_diff")) %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry_diff", "warm_wet_diff", "curr_dry_diff"))) %>%
  ggplot(aes(x = day, y = condition, fill = hours)) + 
  geom_tile() +
  scale_fill_continuous_diverging(palette = "Blue-Red 3", mid = 0, rev = TRUE, limits = c(-15, 15)) +
  ylab(NULL) + xlab("Day of the year") + 
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom") +
  guides(fill = guide_colourbar(barheight = 0.5, barwidth = 5, label.position = "bottom")) 

br_comb_plot <- cowplot::plot_grid(br_plot, 
                   br_diff_plot + scale_x_continuous(breaks = seq(0, 365, 100), expand = c(0, 0)), 
                   ncol = 1, align = 'v',  rel_heights = c(0.7, 1))

sa_diff_plot <- curr_wet_sa_df %>%
  merge(curr_dry_sa_df, by = "day") %>%
  merge(warm_wet_sa_df, by = "day") %>%
  merge(warm_dry_sa_df, by = "day") %>%
  dplyr::mutate(curr_dry_diff = curr_dry - curr_wet,
                warm_wet_diff = warm_wet - curr_wet,
                warm_dry_diff = warm_dry - curr_wet) %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::filter(condition == c("curr_dry_diff", "warm_wet_diff", "warm_dry_diff")) %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry_diff", "warm_wet_diff", "curr_dry_diff"))) %>%
  ggplot(aes(x = day, y = condition, fill = hours)) + 
  geom_tile() +
  scale_fill_continuous_diverging(palette = "Blue-Red 3", mid = 0, rev = TRUE, limits = c(-15, 15)) +
  ylab(NULL) + xlab("Day of the year") + 
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom") +
  guides(fill = guide_colourbar(barheight = 0.5, barwidth = 5, label.position = "bottom")) 

sa_comb_plot <- cowplot::plot_grid(sa_plot, 
                   sa_diff_plot + scale_x_continuous(breaks = seq(0, 365, 100), expand = c(0, 0)), 
                   ncol = 1, align = 'v',  rel_heights = c(0.7, 1))

sp_diff_plot <- curr_wet_sp_df %>%
  merge(curr_dry_sp_df, by = "day") %>%
  merge(warm_wet_sp_df, by = "day") %>%
  merge(warm_dry_sp_df, by = "day") %>%
  dplyr::mutate(curr_dry_diff = curr_dry - curr_wet,
                warm_wet_diff = warm_wet - curr_wet,
                warm_dry_diff = warm_dry - curr_wet) %>%
  pivot_longer(!day, names_to = "condition", values_to = "hours") %>%
  dplyr::filter(condition == c("curr_dry_diff", "warm_wet_diff", "warm_dry_diff")) %>%
  dplyr::mutate(condition = factor(condition, levels = c("warm_dry_diff", "warm_wet_diff", "curr_dry_diff"))) %>%
  ggplot(aes(x = day, y = condition, fill = hours)) + 
  geom_tile() +
  scale_fill_continuous_diverging(palette = "Blue-Red 3", mid = 0, rev = TRUE, limits = c(-15, 15)) +
  ylab(NULL) + xlab("Day of the year") + 
  scale_x_continuous(breaks = seq(0, 365, 50), expand = c(0, 0)) + 
  mytheme() + theme(legend.position = "bottom") +
  guides(fill = guide_colourbar(barheight = 0.5, barwidth = 5, label.position = "bottom")) 

sp_comb_plot <- cowplot::plot_grid(sp_plot, 
                   sp_diff_plot + scale_x_continuous(breaks = seq(0, 365, 100), expand = c(0, 0)), 
                   ncol = 1, align = 'v',  rel_heights = c(0.7, 1))

# Map
 ggplot() +
   geom_raster(data = PDSI_risk_df %>% dplyr::select(x, y, count_4C) %>% na.omit(), aes(y = y, x = x, fill = "#9e3e3e"), alpha = 0.4) +
  geom_raster(data = PDSI_risk_df %>% dplyr::select(x, y, count_2C) %>% na.omit(), aes(y = y, x = x, fill = "#9e3e3e"), alpha = 0.6) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  theme_void() + ylab(NULL) + xlab(NULL) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

Extended data

Extended Figure 1 - PDSI intensity risk

PDSI_2C_diff_rast_crop <- raster::mask(crop(PDSI_2C_diff_rast, extent(world)), world) # crop 
PDSI_2C_rob <- raster::projectRaster(raster::stack(PDSI_2C_diff_rast_crop, resample(anuran_sr, PDSI_2C_diff_rast_crop)), 
                          crs = rob_proj)

PDSI_4C_diff_rast_crop <- raster::mask(crop(PDSI_4C_diff_rast, extent(world)), world) # crop 
PDSI_4C_rob <- raster::projectRaster(raster::stack(PDSI_4C_diff_rast_crop, resample(anuran_sr, PDSI_4C_diff_rast_crop)), 
                          crs = rob_proj)

PDSI_2C_df_rob <- raster::as.data.frame(raster::rasterToPoints(PDSI_2C_rob)) %>%
  dplyr::rename(layer = delta_int_2C,
                species_n = layer) %>% 
  dplyr::mutate(change = case_when(
    layer >= 4 ~ "4", 
    layer >= 3 & layer < 4 ~ '3',
    layer >= 2 & layer < 3 ~ '2',  
    layer >= 1 & layer < 2 ~ '1',  
    layer >= -1 & layer < 1 ~ '0',
    layer >= -2 & layer < -1 ~ '-1',
    layer >= -3 & layer < -2 ~ '-2',
    layer >= -4 & layer < -3 ~ '-3',   
    layer < -4 ~ '-4' 
  )) %>% 
  dplyr::mutate(change = factor(change,
                                levels = c('-4', '-3', '-2', '-1', '0', '1', '2', '3', '4'),
                                ordered = TRUE)) %>%
  dplyr::filter(change != "NA" & species_n != "NA")

PDSI_4C_df_rob <- raster::as.data.frame(raster::rasterToPoints(PDSI_4C_rob)) %>%
  dplyr::rename(layer = delta_int_4C,
                species_n = layer) %>% 
  dplyr::mutate(change = case_when(
    layer >= 4 ~ "4", 
    layer >= 3 & layer < 4 ~ '3',
    layer >= 2 & layer < 3 ~ '2',  
    layer >= 1 & layer < 2 ~ '1',  
    layer >= -1 & layer < 1 ~ '0',
    layer >= -2 & layer < -1 ~ '-1',
    layer >= -3 & layer < -2 ~ '-2',
    layer >= -4 & layer < -3 ~ '-3',   
    layer < -4 ~ '-4' 
  )) %>% 
  dplyr::mutate(change = factor(change,
                                levels = c('-4', '-3', '-2', '-1', '0', '1', '2', '3', '4'),
                                ordered = TRUE)) %>%
  dplyr::filter(change != "NA" & species_n != "NA")

# Intensity +2C - Ex Fig. 1a
colours_PDSI <- RColorBrewer::brewer.pal(9, "RdBu")
PDSI_2C_plot <- ggplot() +
  geom_raster(data = PDSI_2C_df_rob, aes(y = y, x = x, fill = change)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = colours_PDSI) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle(expression(Delta*"PDSI intensity (+2°C)")) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

# Intensity +4C - Ex Fig. 1c
PDSI_4C_plot <- ggplot() +
  geom_raster(data = PDSI_4C_df_rob, aes(y = y, x = x, fill = change)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = colours_PDSI) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle(expression(Delta*"PDSI intensity (+4°C)")) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

# 2C change - Ex Fig 1b
PDSI_sp_2C_plot <- PDSI_sp_2C %>%
  rows_insert(tibble(change_2C = "4", all_freq = 0), conflict = "ignore") %>%
  filter(change_2C != "NA") %>%
  ggplot(aes(x = change_2C, y = all_freq, fill = change_2C)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = colours_PDSI) +
  geom_text(aes(label = round(all_freq, 1)), vjust = -1, size = 2) +
  ylab("% species") + xlab("PDSI") +
  ylim(0, 80) +
  ggtitle("Grid cell occupied +2°C") +
  mytheme() + 
  theme(plot.title = element_text(size = 10))

# 4C change - Ex Fig 1d
PDSI_sp_4C_plot <- PDSI_sp_4C %>%
  filter(change_4C != "NA") %>%
  ggplot(aes(x = change_4C, y = all_freq, fill = change_4C)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = colours_PDSI) +
  geom_text(aes(label = round(all_freq, 1)), vjust = -1, size = 2) +
  ylab("% species") + xlab("PDSI") +
  ylim(0, 80) +
  ggtitle("Grid cell occupied +4°C") +
  mytheme() + 
  theme(plot.title = element_text(size = 10))

left_plot <- cowplot::plot_grid(
  PDSI_2C_plot + theme(legend.position = "none"),
  PDSI_4C_plot + theme(legend.position = "none"),
  ncol = 1,
  align = "h", axis = "bt", labels = c('a', 'c', 'e'))

right_plot <- cowplot::plot_grid(
  PDSI_sp_2C_plot + theme(legend.position = "none"),
  PDSI_sp_4C_plot + theme(legend.position = "none"),
  ncol = 1,
  align = "h", axis = "bt", labels = c('b', 'd', 'f'))

cowplot::plot_grid(left_plot, right_plot, ncol = 2, rel_widths = c(1, 0.7))

Extended Figure 2 - PDSI frequency risk

freq_diff_rast_crop <- raster::mask(crop(freq_diff_rast, extent(world)), world) # crop

PDSI_freq_rob <- raster::projectRaster(raster::stack(freq_diff_rast_crop, 
                                           resample(anuran_sr, freq_diff_rast_crop)), 
                             crs = rob_proj)
                             
PDSI_freq_2C_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_freq_rob)) %>%
  dplyr::mutate(diff_2C_cat = case_when(
    diff_2C >= 10 ~ "10-12", 
    diff_2C >= 8 & diff_2C < 10 ~ '8-10',
    diff_2C >= 6 & diff_2C < 8 ~ '6-8',  
    diff_2C >= 4 & diff_2C < 6 ~ '4-6',  
    diff_2C >= 2 & diff_2C < 4 ~ '2-4',
    diff_2C >= 1 & diff_2C < 2 ~ '1-2',
    diff_2C > 0 & diff_2C < 1 ~ '0-1',
    diff_2C >= -1 & diff_2C < 0 ~ '-0-1',
    diff_2C >= -2 & diff_2C < -1 ~ '-1-2',
    diff_2C >= -4 & diff_2C < -2 ~ '-2-4'
  )) %>% 
  dplyr::mutate(diff_2C_cat = factor(diff_2C_cat,
                                     levels = c('10-12', '8-10', '6-8', '4-6', '2-4', '1-2', '0-1','-0-1', '-1-2', '-2-4'),
                                ordered = TRUE)) %>%
  dplyr::filter(diff_2C_cat != "NA" & layer != "NA")

PDSI_freq_4C_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_freq_rob)) %>%
  dplyr::mutate(diff_4C_cat = case_when(
    diff_4C >= 10 ~ "10-12", 
    diff_4C >= 8 & diff_4C < 10 ~ '8-10',
    diff_4C >= 6 & diff_4C < 8 ~ '6-8',  
    diff_4C >= 4 & diff_4C < 6 ~ '4-6',  
    diff_4C >= 2 & diff_4C < 4 ~ '2-4',
    diff_4C >= 1 & diff_4C < 2 ~ '1-2',
    diff_4C > 0 & diff_4C < 1 ~ '0-1',
    diff_4C >= -1 & diff_4C < 0 ~ '-0-1',
    diff_4C >= -2 & diff_4C < -1 ~ '-1-2',
    diff_4C >= -4 & diff_4C < -2 ~ '-2-4'
  )) %>% 
  dplyr::mutate(diff_4C_cat = factor(diff_4C_cat,
                                     levels = c('10-12', '8-10', '6-8', '4-6', '2-4', '1-2', '0-1', '-0-1', '-1-2', '-2-4'),
                                     ordered = TRUE)) %>%
  dplyr::filter(diff_4C_cat != "NA" & layer != "NA")

# Freq map 2C - Fig S10a
freq_2C_plot <- ggplot() +
  geom_raster(data = PDSI_freq_2C_df, aes(y = y, x = x, fill = diff_2C_cat)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7", "#dfebf2")) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle(expression("Change in drought frequency ("*Delta*"PDSI +2°C)")) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

# Freq map 4C - Fig S10c
freq_4C_plot <- ggplot() +
  geom_raster(data = PDSI_freq_4C_df, aes(y = y, x = x, fill = diff_4C_cat)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7", "#dfebf2")) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle(expression("Change in drought frequency ("*Delta*"PDSI +4°C)")) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

# 2C change - Fig S10b
freq_sp_2C <- data.frame(PDSI_freq_2C_df %>% 
                           dplyr::group_by(diff_2C_cat) %>% 
                           dplyr::summarise(species_n = length(layer[!is.na(layer)]))) %>%
  dplyr::mutate(all_freq  = species_n / sum(species_n) * 100)

freq_sp_2C_plot <- freq_sp_2C %>%
  ggplot(aes(x = diff_2C_cat, y = all_freq, fill = diff_2C_cat)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7", "#dfebf2")) +
  geom_text(aes(label = round(all_freq, 1)), vjust = -1, size = 2) +
  ylab("% species") + xlab("Months") +
  ylim(0, 60) +
  ggtitle("Grid cell occupied +2°C") +
  mytheme() + 
  theme(plot.title = element_text(size = 10))

# 4C change - Fig S10d
freq_sp_4C <- data.frame(PDSI_freq_4C_df %>% dplyr::group_by(diff_4C_cat) %>%
                           dplyr::summarise(species_n = length(layer[!is.na(layer)]))) %>%
  dplyr::mutate(all_freq  = species_n / sum(species_n) * 100)

freq_sp_4C_plot <- freq_sp_4C %>%
  ggplot(aes(x = diff_4C_cat, y = all_freq, fill = diff_4C_cat)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7", "#dfebf2")) +
  geom_text(aes(label = round(all_freq, 1)), vjust = -1, size = 2) +
  ylab("% species") + xlab("Months") +
  ylim(0, 60) +
  ggtitle("Grid cell occupied +4°C") +
  mytheme() + 
  theme(plot.title = element_text(size = 10))

left_plot2 <- cowplot::plot_grid(
  freq_2C_plot + theme(legend.position = "none"),
  freq_4C_plot + theme(legend.position = "none"),
  ncol = 1,
  align = "h", axis = "bt", labels = c('a', 'c'))

right_plot2 <- cowplot::plot_grid(
  freq_sp_2C_plot + theme(legend.position = "none"),
  freq_sp_4C_plot + theme(legend.position = "none"),
  ncol = 1,
  align = "h", axis = "bt", labels = c('b', 'd'))

cowplot::plot_grid(left_plot2, right_plot2, ncol = 2, rel_widths = c(1, 0.7))

Extended Figure 3 - PDSI duration risk

PDSI_dur_diff_crop <- raster::mask(crop(PDSI_dur_diff, extent(world)), world) # crop

PDSI_dur_rob <- raster::projectRaster(raster::stack(PDSI_dur_diff_crop, 
                                           resample(anuran_sr, PDSI_dur_diff_crop)), 
                             crs = rob_proj)

PDSI_dur_2C_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_dur_rob)) %>%
  dplyr::rename("sp_n" = layer) %>%
  dplyr::filter(!is.na(sp_n)) %>%
  dplyr::mutate(diff_2C_cat = case_when(
    delta_dur_2C >= 10 ~ ">10", 
    delta_dur_2C >= 8 & delta_dur_2C < 10 ~ '8-10',
    delta_dur_2C >= 6 & delta_dur_2C < 8 ~ '6-8',  
    delta_dur_2C >= 4 & delta_dur_2C < 6 ~ '4-6',  
    delta_dur_2C >= 2 & delta_dur_2C < 4 ~ '2-4',
    delta_dur_2C >= 1 & delta_dur_2C < 2 ~ '1-2',
    delta_dur_2C > 0 & delta_dur_2C < 1 ~ '0-1',
    delta_dur_2C >= -1 & delta_dur_2C < 0 ~ '-0-1',
    delta_dur_2C >= -2 & delta_dur_2C < -1 ~ '-1-2',
    delta_dur_2C >= -4 & delta_dur_2C < -2 ~ '-2-4',
    delta_dur_2C >= -8 & delta_dur_2C < -6 ~ '-6-8',
    delta_dur_2C >= -10 & delta_dur_2C < -8 ~ '-8-10',   
    delta_dur_2C < -10 ~ '<-10' 
  )) %>% 
  dplyr::mutate(diff_2C_cat = factor(diff_2C_cat,
                                levels = c('>10', '8-10', '6-8', '4-6', '2-4', '1-2', "0-1", '-0-1', '-1-2', '-2-4', '-4-6', '-6-8', '-8-10', '<-10'),
                                ordered = TRUE)) %>%
  dplyr::filter(diff_2C_cat != "NA")

PDSI_dur_4C_df <- raster::as.data.frame(raster::rasterToPoints(PDSI_dur_rob)) %>%
  dplyr::rename("sp_n" = layer) %>%
  dplyr::filter(!is.na(sp_n)) %>%
  dplyr::mutate(diff_4C_cat = case_when(
    delta_dur_4C >= 10 ~ ">10", 
    delta_dur_4C >= 8 & delta_dur_4C < 10 ~ '8-10',
    delta_dur_4C >= 6 & delta_dur_4C < 8 ~ '6-8',  
    delta_dur_4C >= 4 & delta_dur_4C < 6 ~ '4-6',  
    delta_dur_4C >= 2 & delta_dur_4C < 4 ~ '2-4',
    delta_dur_4C >= 1 & delta_dur_4C < 2 ~ '1-2',
    delta_dur_4C > 0 & delta_dur_4C < 1 ~ '0-1',
    delta_dur_4C >= -1 & delta_dur_4C < 0 ~ '-0-1',
    delta_dur_4C >= -2 & delta_dur_4C < -1 ~ '-1-2',
    delta_dur_4C >= -4 & delta_dur_4C < -2 ~ '-2-4',
    delta_dur_4C >= -6 & delta_dur_4C < -4 ~ '-4-6',
    delta_dur_4C >= -8 & delta_dur_4C < -6 ~ '-6-8',
    delta_dur_4C >= -10 & delta_dur_4C < -8 ~ '-8-10',   
    delta_dur_4C < -10 ~ '<-10' 
  )) %>% 
  dplyr::mutate(diff_4C_cat = factor(diff_4C_cat,
                                levels = c('>10', '8-10', '6-8', '4-6', '2-4', '1-2', "0-1", '-0-1', '-1-2', '-2-4', '-4-6', '-6-8', '-8-10', '<-10'),
                                ordered = TRUE)) %>%
  dplyr::filter(diff_4C_cat != "NA")

dur_2C_plot <- ggplot() +
  geom_raster(data = PDSI_dur_2C_df, aes(y = y, x = x, fill = diff_2C_cat)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7", "#dfebf2", "#D1E5F0")) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle(expression("Change in drought duration ("*Delta*"PDSI +2°C)")) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

dur_4C_plot <- ggplot() +
  geom_raster(data = PDSI_dur_4C_df, aes(y = y, x = x, fill = diff_4C_cat)) +
  geom_polygon(data = world_rob, aes(x = long, y = lat, group = group), colour = "#64686b", fill = NA, size = 0.1) +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7", "#dfebf2", "#D1E5F0")) +
  ggnewscale::new_scale("fill") +
  geom_raster(data = hill_df %>% filter(hill <= 0.645), aes(lon, lat, fill = hill, alpha = hill), show.legend = FALSE) +
  scale_fill_gradient(low = "black", high = "grey") +
  scale_alpha_continuous(trans = "reverse") +
  theme_void() + ylab(NULL) + xlab(NULL) +
  ggtitle(expression("Change in drought duration ("*Delta*"PDSI +4°C)")) +
  scale_y_continuous(limits = c(-61e5, 85e5), expand = c(0, 0)) +
  scale_x_continuous(limits = c(-15e6, 16e6), expand = c(0, 0)) +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        plot.title = element_text(size = 10)) +
  coord_fixed(ratio = 1) # fixed ratio

# 2C change - Fig S11b
dur_sp_2C <- data.frame(PDSI_dur_2C_df %>% dplyr::group_by(diff_2C_cat) %>% 
                            dplyr::summarise(species_n = length(sp_n[!is.na(sp_n)]))) %>%
  dplyr::mutate(all_freq  = species_n / sum(species_n) * 100)

dur_sp_2C_plot <- dur_sp_2C %>%
  ggplot(aes(x = diff_2C_cat, y = all_freq, fill = diff_2C_cat)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7", "#dfebf2", "#D1E5F0")) +
  geom_text(aes(label = round(all_freq, 1)), vjust = -1, size = 2) +
  ylab("% species") + xlab("Months") +
  ylim(0, 50) +
  ggtitle("Grid cell occupied +2°C") +
  mytheme() + 
  theme(plot.title = element_text(size = 10))

# 4C change - Fig S11d
dur_sp_4C <- data.frame(PDSI_dur_4C_df %>% dplyr::group_by(diff_4C_cat) %>%
                           dplyr::summarise(species_n = length(sp_n[!is.na(sp_n)]))) %>%
  dplyr::mutate(all_freq  = species_n / sum(species_n) * 100)

dur_sp_4C_plot <- dur_sp_4C %>%
  ggplot(aes(x = diff_4C_cat, y = all_freq, fill = diff_4C_cat)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = c("#67001F", "#B2182B", "#D6604D", "#F4A582", "#FDDBC7", "#FAE9DF", "#F7F7F7", "#dfebf2", "#D1E5F0")) +
  geom_text(aes(label = round(all_freq, 1)), vjust = -1, size = 2) +
  ylab("% species") + xlab("Months") +
  ylim(0, 50) +
  ggtitle("Grid cell occupied +4°C") +
  mytheme() + 
  theme(plot.title = element_text(size = 10))

left_plot3 <- cowplot::plot_grid(
  dur_2C_plot + theme(legend.position = "none"),
  dur_4C_plot + theme(legend.position = "none"),
  ncol = 1,
  align = "h", axis = "bt", labels = c('a', 'c'))

right_plot3 <- cowplot::plot_grid(
  dur_sp_2C_plot + theme(legend.position = "none"),
  dur_sp_4C_plot + theme(legend.position = "none"),
  ncol = 1,
  align = "h", axis = "bt", labels = c('b', 'd'))

cowplot::plot_grid(left_plot3, right_plot3, ncol = 2, rel_widths = c(1, 0.7))


Supporting figures

temp_dat <- ewl_dat %>% dplyr::filter(!is.na(trt_temp))

temp_dat %>%
  ggplot(aes(x = trt_temp, y = skin_temp)) +
  geom_abline(intercept = 0, slope = 1, linetype = "dashed", size = 0.5) +
  ggpmisc::stat_poly_line(method = "lm", formula = y ~ x + I(x^6), se = F, color = "black") +
  ggpmisc::stat_poly_eq(method = "lm", formula = y ~ x + I(x^6), 
                        ggpmisc::use_label(c("eq", "R2", "n"))) +
  geom_point(size = 2, shape = 21, fill = "white") +
  ylim(5,50) + xlim(5,50) +
  labs(x = "Air temperature (°C)", y = "Skin surface temperature (°C)") +
  mytheme()

Fig. S11. Relationship between exposed air temperature (°C) during the experiment and the observed skin surface temperature (°C) across 238 species. The black line represents the non-linear relationship between air temperature and skin temperature where the skin temperature remains at ~35°C when exposed to air temperatures > 40°C.

raw_dat %>%
  dplyr::filter(trait != "water gain" & !is.na(unit_corrected_mean)) %>%
  ggplot(aes(x = unit_corrected_mean, y = r_s_est, fill = calculated)) +
  geom_point(size = 2, shape = 21, colour = "black") + 
  xlab(expression("EWL"~("mg"~"H"[2]*O~h^{"-1"}))) +
  ylab(expression(italic("r")["i"]~"(s cm"^{-1}*")")) +
  labs(fill = expression("Estimated"~italic("r")["i"])) +
  scale_x_log10(breaks = scales::trans_breaks("log10", function(x) 10^x),
              labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_y_log10(breaks = scales::trans_breaks("log10", function(x) 10^x),
              labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks() +
  scale_fill_manual(values = c("white", "grey")) +
  mytheme() +
  theme(legend.position = "bottom")

Fig. S12. Relationship between evaporative water loss (EWL; mg H2O cm−2 h−1) and resistance to water loss (\(r_i\); s cm-1) on a base-10 logarithmic scale. Measured \(r_i\) from the study presented as white filled points, and the estimated \(r_i\) from EWL in grey filled points.

EWL_sp_long <- EWL_sp_df %>% 
  dplyr::select(-species_n) %>%
  tidyr::pivot_longer(!c(x, y, EWL), names_to = "ecotype", values_to = "count") %>%
  dplyr::mutate(ecotype = factor(ecotype, levels = c("foss_sp", "gron_sp", "aqua_sp", "arbo_sp", "semi_sp", "strm_sp")))

ecotype_labs <- c("Fossorial", "Ground-dwelling", "Aquatic", "Arboreal", "Semi-aquatic", "Stream-dwelling")
names(ecotype_labs) <- c("foss_sp", "gron_sp", "aqua_sp", "arbo_sp", "semi_sp", "strm_sp")

EWL_sp_long %>%
  ggplot(aes(x = EWL, y = count)) + 
  geom_point(data = transform(EWL_sp_long, ecotype = NULL),
             colour = "grey85") + geom_point(aes(colour = ecotype),
                                             alpha = 0.5, show.legend = F) + 
  xlab(expression("EWL" ~ ("g" ~ H[2] * O ~ h^{"-1"}))) + 
  ylab("Species richness") + 
  scale_colour_viridis_d() + 
  scale_y_continuous(expand = c(0, 0)) +
  scale_x_continuous(breaks = seq(0, 3, 0.5), expand = c(0, 0)) + 
  facet_wrap(vars(ecotype), labeller = labeller(ecotype = ecotype_labs)) + 
  mytheme()

Fig. S13. Relationship between EWL and species richness by ecotype. Grey points represent the total dataset as comparison for where each ecotype fits.


References

Abatzoglou, J. T., Dobrowski, S. Z., Parks, S. A. and Hegewisch, K. C. (2018). TerraClimate, a high-resolution global dataset of monthly climate and climatic water balance from 1958–2015. Scientific data 5, 170191.
Anderson, R. C. O., Bovo, R. P., Eismann, C. E., Menegario, A. A. and Andrade, D. V. (2017). Not good, but not all bad: Dehydration effects on body fluids, organ masses, and water flux through the skin of Rhinella schneideri (Amphibia, Bufonidae). Physiological and Biochemical Zoology 90, 170191.
Baldwin, R. A. (1974). The water balance response of the pelvic “patch” of Bufo punctatus and Bufo boreas. Comparative Biochemistry and Physiology Part A: Physiology 47, 1285–1295.
Blaylock, L. A., Ruibal, R. and Kathryn, P.-A. (1976). Skin structure and wiping behavior of phyllomedusine frogs. Copeia 1976, 283–295.
Bovo, R. P., Simon, M. N., Lyra, M. L., Navas, C. A. and Andrade, D. V. (2023). Beyond janzen’s hypothesis: How amphibians that climb tropical mountains respond to climate variation. Integrative Organismal Biology 5, obad009.
Budyko, M. I. (1961). The heat balance of the earth’s surface. Soviet Geography 2, 3–13.
Buttemer, W. A. and Thomas, C. (2003). Influence of temperature on evaporative water loss and cutaneous resistance to water vapour diffusion in the orange-thighed frog (Litoria xanthomera). Australian Journal of Zoology 51, 111–118.
Eyring, V., Bony, S., Meehl, G. A., Senior, C. A., Stevens, B., Stouffer, R. J. and Taylor, K. E. (2016). Overview of the coupled model intercomparison project phase 6 (CMIP6) experimental design and organization. Geoscientific Model Development 9, 1937–1958.
Feder, M. E. and Burggren, W. W. (1992). Environmental physiology of the amphibians. Chicago, USA: University of Chicago Press.
Gomez, N. A., Acosta, M., Zaidan III, F. and Lillywhite, H. B. (2006). Wiping behavior, skin resistance, and the metabolic response to dehydration in the arboreal frog Phyllomedusa hypochondrialis. Current Biology 79, 1058–1068.
Gouveia, S. F., Rafael, R. P., Rubalcaba, J. G., Da Silva, F. R., Maciel, N. M., Andrade, D. V. and Martinez, P. A. (2019). Biophysical modeling of water economy can explain geographic gradient of body size in anurans. The American Naturalist 193, 51–58.
Hillman, S. S., Withers, P. C., Drewes, R. C. and Hillyard, S. D. (2009). Ecological and environmental physiology of amphibians. New York, USA: Oxford University Press.
IPCC (2021). Climate change 2021: The physical science basis, contribution of working group i to the sixth assessment report of the intergovernmental panel on climate change.
Jetz, W. and Pyron, R. A. (2018). The interplay of past diversification and evolutionary isolation with present imperilment across the amphibian tree of life. Nature Ecology & Evolution 2, 850–858.
Kearney, M. R. and Porter, W. P. (2017). NicheMapR–an R package for biophysical modelling: The microclimate model. Ecography 40, 664–674.
Kearney, M. R. and Porter, W. P. (2020). NicheMapR–an R package for biophysical modelling: The ectotherm and dynamic energy budget models. Ecography 43, 85–96.
Kearney, M. R., Phillips, B. L., Tracy, C. R., Christian, K. A., Betts, G. and Porter, W. P. (2008). Modelling species distributions without using species distributions: The cane toad in australia under current and future climates. Ecography 31, 423–434.
Kearney, M. R., Shamakhy, A., Tingley, R., Karoly, D. J., Hoffmann, A. A., Briggs, P. R. and Porter, W. P. (2014). Microclimate modelling at macro scales: A test of a general microclimate model integrated with gridded continental‐scale soil and weather data. Methods in Ecology and Evolution 5, 273–286.
Klein, W., Dabés, L., Bonfim, V. M. G., Magrini, L. and Napoli, M. F. (2016). Allometric relationships between cutaneous surface area and body mass in anuran amphibians. Zoologischer Anzeiger-A Journal of Comparative Zoology 263, 45–54.
Kobelt, F. and Linsenmair, K. E. (1986). Adaptations of the reed frog Hyperolius viridiflavus (amphibia, anura, hyperoliidae) to its arid environment i. The skin of Hyperolius viridiflavus nitidulus in wet and dry season conditions. Oecologia 68, 533–541.
Lillywhite, H. B. (2006). Water relations of tetrapod integument. Journal of Experimental Biology 209, 202–226.
McClanahan Jr, L. and Baldwin, R. (1969). Rate of water uptake through the integument of the desert toad, Bufo punctatus. Comparative Biochemistry and Physiology 28, 381–389.
Moen, D. S. and Wiens, J. J. (2017). Microhabitat and climatic niche change explain patterns of diversification among frog families. The American Naturalist 190, 29–44.
Monteith, John and Unsworth, M. (2013). Principles of environmental physics: Plants, animals, and the atmosphere. Oxford, UK: Academic Press.
Ouzzani, M., Hammady, H., Fedorowicz, Z. and Elmagarmid, A. (2016). Rayyan—a web and mobile app for systematic reviews. Systematic reviews 5, 1–10.
Palmer, W. C. (1965). Meteorological drought. Washington DC, USA: US Department of Commerce, Weather Bureau.
Pirtle, E. I., Tracy, C. R. and Kearney, R., Michael (2019). Hydroregulation: A neglected behavioral response of lizards to climate change? In Behavior of lizards, pp. 343–374. New York, USA: CRC Press.
Riddell, E. A., Apanovitch, E. K., Odom, J. P. and Sears, M. W. (2017). Physical calculations of resistance to water loss improve predictions of species range models. Ecological Monographs 87, 21–33.
Senzano, L. M., Bovo, R. P. and Andrade, D. V. (2022). Empirical estimation of skin resistance to water loss in amphibians: Agar evaluation as a non-resistance model to evaporation. Journal of Experimental Biology 225, jeb243941.
Spotila, J. R. and Berman, E. N. (1976). Determination of skin resistance and the role of the skin in controlling water loss in amphibians and reptiles. Comparative Biochemistry and Physiology Part A: Physiology 55, 407–411.
Stull, R. B. and Ahrens, C. D. (2000). Meteorology for scientists and engineers. Second edition. California, USA: Brooks/Cole.
Titon Jr, B. and Gomes, F. R. (2015). Relation between water balance and climatic variables associated with the geographical distribution of anurans. PLOS One 10, e0140761.
Titon Jr, B., Navas, C. A., Jim, J. and Gomes, F. R. (2010). Water balance and locomotor performance in three species of neotropical toads that differ in geographical distribution. Comparative Biochemistry and Physiology Part A: Molecular & Integrative Physiology 156, 129–135.
Tracy, C. R. (1976). A model of the dynamic exchanges of water and energy between a terrestrial amphibian and its environment. Ecological Monographs 46, 293–326.
Tracy, C. R., Welch, W. R., Pinshow, B., Kearney, M. R. and Porter, W. P. (2019). Properties of air: A manual for use in biophysical ecology.
Willumsen, N. J., Viborg, A. L. and Hillyard, S. D. (2007). Vascular aspects of water uptake mechanisms in the toad skin: Perfusion, diffusion, confusion. Comparative Biochemistry and Physiology Part A: Molecular & Integrative Physiology 148, 55–63.
Withers, P. C., Hillman, S. S., Drewes, R. and Sokol, O. (1982). Water loss and nitrogen excretion in sharp-nosed reed frogs (Hyperolius nasutus: Anura, Hyperoliidae). Journal of Experimental Biology 97, 335–343.
Withers, P. C., Hillman, S. S. and Drewes, R. C. (1984). Evaporative water loss and skin lipids of anuran amphibians. Journal of Experimental Zoology 232, 11–17.
Zhao, T. and Dai, A. (2022). CMIP6 model-projected hydroclimatic and drought changes and their causes in the twenty-first century. Journal of Climate 35, 897–921.



Session Information

R version 4.4.0 (2024-04-24)

Platform: aarch64-apple-darwin20

attached base packages: stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: tmaptools(v.3.1-1), tmap(v.3.3-4), sf(v.1.0-16), raster(v.3.6-26), sp(v.2.1-4), ncdf4(v.1.22), phytools(v.2.1-1), maps(v.3.4.2), ape(v.5.8), performance(v.0.11.0), rstan(v.2.32.6), StanHeaders(v.2.32.7), brms(v.2.21.0), Rcpp(v.1.0.12), kableExtra(v.1.4.0), ggpmisc(v.0.5.5), ggpp(v.0.5.6), ggnewscale(v.0.4.10), cowplot(v.1.1.3), RColorBrewer(v.1.1-3), colorspace(v.2.1-0), lubridate(v.1.9.3), forcats(v.1.0.0), stringr(v.1.5.1), dplyr(v.1.1.4), purrr(v.1.0.2), readr(v.2.1.5), tidyr(v.1.3.1), tibble(v.3.2.1), ggplot2(v.3.5.1), tidyverse(v.2.0.0), Matrix(v.1.7-0), pander(v.0.6.5) and knitr(v.1.46)

loaded via a namespace (and not attached): splines(v.4.4.0), polyclip(v.1.10-6), confintr(v.1.0.2), XML(v.3.99-0.16.1), lifecycle(v.1.0.4), doParallel(v.1.0.17), lattice(v.0.22-6), MASS(v.7.3-60.2), insight(v.0.19.10), crosstalk(v.1.2.1), backports(v.1.4.1), magrittr(v.2.0.3), sass(v.0.4.9), rmarkdown(v.2.26), jquerylib(v.0.1.4), yaml(v.2.3.8), pkgbuild(v.1.4.4), DBI(v.1.2.2), multcomp(v.1.4-25), abind(v.1.4-5), expm(v.0.999-9), quadprog(v.1.5-8), TH.data(v.1.1-2), tensorA(v.0.36.2.1), tweenr(v.2.0.3), sandwich(v.3.1-0), inline(v.0.3.19), terra(v.1.7-71), units(v.0.8-5), MatrixModels(v.0.5-3), bridgesampling(v.1.1-2), svglite(v.2.1.3), codetools(v.0.2-20), xml2(v.1.3.6), ggforce(v.0.4.2), tidyselect(v.1.2.1), bayesplot(v.1.11.1), farver(v.2.1.1), viridis(v.0.6.5), matrixStats(v.1.3.0), stats4(v.4.4.0), base64enc(v.0.1-3), jsonlite(v.1.8.8), e1071(v.1.7-14), ggridges(v.0.5.6), survival(v.3.6-4), iterators(v.1.0.14), emmeans(v.1.10.1), systemfonts(v.1.0.6), foreach(v.1.5.2), tools(v.4.4.0), glue(v.1.7.0), mnormt(v.2.1.1), gridExtra(v.2.3), xfun(v.0.43), distributional(v.0.4.0), loo(v.2.7.0), withr(v.3.0.0), numDeriv(v.2016.8-1.1), combinat(v.0.0-8), fastmap(v.1.1.1), fansi(v.1.0.6), SparseM(v.1.81), digest(v.0.6.35), timechange(v.0.3.0), R6(v.2.5.1), estimability(v.1.5), dichromat(v.2.0-0.1), utf8(v.1.2.4), generics(v.0.1.3), class(v.7.3-22), clusterGeneration(v.1.3.8), htmlwidgets(v.1.6.4), scatterplot3d(v.0.3-44), pkgconfig(v.2.0.3), gtable(v.0.3.5), htmltools(v.0.5.8.1), bookdown(v.0.39), scales(v.1.3.0), png(v.0.1-8), posterior(v.1.5.0), rstudioapi(v.0.16.0), tzdb(v.0.4.0), reshape2(v.1.4.4), coda(v.0.19-4.1), checkmate(v.2.3.1), nlme(v.3.1-164), proxy(v.0.4-27), cachem(v.1.0.8), zoo(v.1.8-12), KernSmooth(v.2.23-22), parallel(v.4.4.0), leafsync(v.0.1.0), pillar(v.1.9.0), grid(v.4.4.0), vctrs(v.0.6.5), xtable(v.1.8-4), evaluate(v.0.23), mvtnorm(v.1.2-4), cli(v.3.6.2), compiler(v.4.4.0), rlang(v.1.1.3), rstantools(v.2.4.0), labeling(v.0.4.3), classInt(v.0.4-10), plyr(v.1.8.9), stringi(v.1.8.3), viridisLite(v.0.4.2), QuickJSR(v.1.1.3), stars(v.0.6-5), munsell(v.0.5.1), leaflet(v.2.2.2), optimParallel(v.1.0-2), Brobdingnag(v.1.2-9), bayestestR(v.0.13.2), pacman(v.0.5.1), quantreg(v.5.97), hms(v.1.1.3), leafem(v.0.2.3), highr(v.0.10), igraph(v.2.0.3), RcppParallel(v.5.1.7), bslib(v.0.7.0), phangorn(v.2.11.1), fastmatch(v.1.1-4), lwgeom(v.0.2-14) and polynom(v.1.4-1)


  1. Hawkesbury Institute for the Environment, Western Sydney University, NSW 2753, Australia, ↩︎

LS0tCnRpdGxlOiAiR2xvYmFsIGV4cG9zdXJlIHJpc2sgb2YgZnJvZ3MgdG8gaW5jcmVhc2luZyBlbnZpcm9ubWVudGFsIGRyeW5lc3MiCnN1YnRpdGxlOiAiU3VwcGxlbWVudGFyeSBJbmZvcm1hdGlvbiIKZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJWQvJW0vJVknKWAiCmF1dGhvcjoKICAtIE5pY2hvbGFzIEMuIFd1XltIYXdrZXNidXJ5IEluc3RpdHV0ZSBmb3IgdGhlIEVudmlyb25tZW50LCBXZXN0ZXJuIFN5ZG5leSBVbml2ZXJzaXR5LCBOU1cgMjc1MywgQXVzdHJhbGlhLCBuaWNob2xhcy53dS5uekBnbWFpbC5jb21dCm91dHB1dDoKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICBoaWdobGlnaHQ6IHRhbmdvCmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCmNzbDogLi9iaWIvdGhlLWpvdXJuYWwtb2YtZXhwZXJpbWVudGFsLWJpb2xvZ3kuY3NsCmJpYmxpb2dyYXBoeTogLi9iaWIvZHJvdWdodF9yZWYuYmliCmxpbmstY2l0YXRpb25zOiB0cnVlCi0tLQoKVGhpcyBkb2N1bWVudCBjb250YWlucyB0aGUgKlIqIHdvcmtmbG93IGZvciBwcm9jZXNzaW5nIGFuZCBhbmFseXNpbmcgdGhlIHJhdyBkYXRhLCBhbmQgZ2VuZXJhdGluZyBmaWd1cmVzIGZvciB0aGUgbWFudXNjcmlwdCB0aXRsZWQgIioqR2xvYmFsIGV4cG9zdXJlIHJpc2sgb2YgZnJvZ3MgdG8gaW5jcmVhc2luZyBlbnZpcm9ubWVudGFsIGRyeW5lc3MqKiIuIAoKW0dpdEh1YiBSZXBvc2l0b3J5XShodHRwczovL2dpdGh1Yi5jb20vbmljaG9sYXN3dW56L2dsb2JhbC1mcm9nLWRyb3VnaHQpOgpUaGUgUm1hcmtkb3duIGZpbGUgY2FuIGJlIGRvd25sb2FkZWQgZnJvbSB0aGUgKkNvZGUqIGRyb3AgZG93biBtZW51ICh0b3AgcmlnaHQpLgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgY2FjaGUgPSBGQUxTRSwgdGlkeSA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFKQpvcHRpb25zKGRwbHlyLndpZHRoID0gSW5mLCBrbml0ci5rYWJsZS5OQSA9ICIiLCBkaWdpdHMgPSAyKQoKIyBMb2FkIGxpYnJhcnkKcGFjbWFuOjpwX2xvYWQocGFuZGVyLCBNYXRyaXgsIHRpZHl2ZXJzZSwgY29sb3JzcGFjZSwgUkNvbG9yQnJld2VyLCBjb3dwbG90LCBnZ25ld3NjYWxlLCBnZ3BtaXNjLCBrYWJsZUV4dHJhLCAKICAgICAgICAgICAgICAgYnJtcywgcnN0YW4sIGNtZHN0YW5yLCBwZXJmb3JtYW5jZSwgYXBlLCBwaHl0b29scywgZ2d0cmVlLCBOaWNoZU1hcFIsCiAgICAgICAgICAgICAgIG5jZGY0LCByYXN0ZXIsIHNmLCBzcCwgdG1hcCwgdG1hcHRvb2xzLCByYXN0ZXJTcCkKCiMgRnVuY3Rpb25zCm15dGhlbWUgPC0gZnVuY3Rpb24oKSB7CiAgdGhlbWVfYncoKSArCiAgICB0aGVtZShwYW5lbC5ib3JkZXIgICAgICAgICAgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BLCBjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICAgIHBhbmVsLmdyaWQubWFqb3IgICAgICA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgICAgICA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMubGluZSAgICAgICAgICAgICA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MgICAgICAgICAgICA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICAgIGF4aXMudGV4dCAgICAgICAgICAgICA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ICJibGFjayIpLAogICAgICAgICAgYXhpcy50aXRsZSAgICAgICAgICAgID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgICBheGlzLnRpdGxlLnkgICAgICAgICAgPSBlbGVtZW50X3RleHQodmp1c3QgPSAzKSwKICAgICAgICAgIGF4aXMudGl0bGUueCAgICAgICAgICA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IC0xKSwKICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgICAgICA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLAogICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kICAgICAgID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3IgPSBOQSksCiAgICAgICAgICBwbG90Lm1hcmdpbiAgICAgICAgICAgPSB1bml0KGMoMC4yLCAwLjIsIDAuMiwgMC4yKSwgdW5pdHMgPSAsICJjbSIpLAogICAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgICAgID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3IgPSBOQSksCiAgICAgICAgICBsZWdlbmQuYm94LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BLCBjb2xvciA9IE5BKSwKICAgICAgICAgIHN0cmlwLnRleHQueCAgICAgICAgICA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kICAgICAgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BLCBjb2xvciA9IE5BKSwKICAgICAgICAgIHBsb3QudGl0bGUgICAgICAgICAgICA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpCiAgICApCn0gIyBzZXQgdXAgcGxvdCB0aGVtZQoKYWRkYnJhY2tldCA8LSBmdW5jdGlvbih4KXtwYXN0ZSgiWyIsIHgsICJdIil9ICMgYWRkIGJyYWNrZXRzIGJldHdlZW4gd29yZHMKCiMgU2V0IG9wdGlvbnMgaW4gUnN0YW4Kc2V0LnNlZWQoMTApCnJzdGFuX29wdGlvbnMoYXV0b193cml0ZSA9IFRSVUUpICMgdHJhbnNsYXRlIHRvIFNUQU4gcGxhdGZvcm0gZm9yIHJ1bm5pbmcgQmF5ZXNpYW4gbW9kZWwKb3B0aW9ucyhtYy5jb3JlcyA9IHBhcmFsbGVsOjpkZXRlY3RDb3JlcygpKSAjIGRldGVjdHMgaG93IG1hbnkgY29yZXMgYXZhaWxhYmxlIHRvIHVzZQoKIyBTZXQgZGlyZWN0b3J5CnNldHdkKCcvVXNlcnMvbmljaG9sYXN3dS9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9PbmVEcml2ZS1XZXN0ZXJuU3lkbmV5VW5pdmVyc2l0eS9Ecm91Z2h0IHByb2plY3QvJykgCgojIFNldCBmaWxlIHBhdGhzCmRhdGFfcGF0aCAgICAgPC0gZmlsZS5wYXRoKCJkYXRhIikKc3BhdGlhbF9wYXRoICA8LSBmaWxlLnBhdGgoIlNwYXRpYWwgZGF0YSIpCnJhc3RlclNwX3BhdGggPC0gInJhc3RlclNwL1NwZWNpZXNEYXRhLyIKYGBgCgoqKkFiYnJldmlhdGlvbnMqKgoKLSBBSTogQXJpZGl0eSBJbmRleAotICRlX2EkOiBhY3R1YWwgdmFwb3VyIHByZXNzdXJlCi0gJGVfcyQ6IHNhdHVyYXRpb24gdmFwb3VyIHByZXNzdXJlCi0gRVdMOiBFdmFwb3JhdGl2ZSB3YXRlciBsb3NzCi0gSVVDTjogSW50ZXJuYXRpb25hbCBVbmlvbiBmb3IgQ29uc2VydmF0aW9uIG9mIE5hdHVyZQotIFBEU0k6IFBhbG1lciBEcm91Z2h0IFNldmVyaXR5IEluZGV4Ci0gUFJJU01BOiBQcmVmZXJyZWQgUmVwb3J0aW5nIEl0ZW1zIGZvciBTeXN0ZW1hdGljIFJldmlld3MgYW5kIE1ldGEtQW5hbHlzZXMKLSBSSDogUmVsYXRpdmUgaHVtaWRpdHkKLSAkcl9pJDogUmVsYXRpdmUgc2tpbiByZXNpc3RhbmNlIG9yIHJlc2lzdGFuY2UgdG8gd2F0ZXIgbG9zcwotIFNBOiBzdXJmYWNlLWFyZWEKLSBTUFA6IFNoYXJlZCBTb2Npb2Vjb25vbWljIFBhdGh3YXkKLSBWUEQ6IFZhcG91ciBwcmVzc3VyZSBkZWZpY2l0Ci0gV29TOiBXZWIgb2YgU2NpZW5jZQotIFdVOiB3YXRlciB1cHRha2UKCioqKgoKIyBTcGF0aWFsIHJpc2sgey19CgojIyBEZXNjcmlwdG9ycyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxscyAtfQoKVGhlIGZvbGxvd2luZyBzZXJpZXMgb2YgY29kZSBpcyB0byBlc3RpbWF0ZSB0aGUgcmlzayBvZiBhbnVyYW4gYW1waGliaWFucyB0byBpbmNyZWFzaW5nIGFyaWRpdHkgKEFyaWRpdHkgSW5kZXg7IEFJKSBhbmQgZXh0cmVtZSBkcm91Z2h0IChQYWxtZXIgRHJvdWdodCBTZXZlcml0eSBJbmRleDsgUERTSSkuIFRoZSBBSSB3YXMgY2F0ZWdvcmlzZWQgdG8gZml2ZSBjYXRlZ29yaWVzIChIdW1pZCwgRHJ5IHN1Yi1odW1pZCwgU2VtaS1hcmlkLCBBcmlkLCBhbmQgSHlwZXItYXJpZCkgYW5kIHRoZSBQRFNJIHdhcyBjYXRlZ29yaXNlZCB0byBzZXZlbiBjYXRlZ29yaWVzIChFeHRyZW1lbHkgbW9pc3QsIFZlcnkgbW9pc3QsIE1vZGVyYXRlIG1vaXN0LCBOb3JtYWwsIE1vZGVyYXRlIGRyb3VnaHQsIFNldmVyZSBkcm91Z2h0LCBFeHRyZW1lIGRyb3VnaHQpIGJhc2VkIG9uIGRlc2NyaXB0aW9ucyBmcm9tIEBCdWR5a28xOTYxIGFuZCBAUGFsbWVyMTk2NSwgcmVzcGVjdGl2ZWx5ICgqKlRhYmxlIFMxKiopLgoKR2VuZXJhbGlzZWQgZWNvbG9naWNhbCB0eXBlcyBvciDigJhlY290eXBl4oCZIG9mIGVhY2ggYW51cmFuIHNwZWNpZXMgd2VyZSBjbGFzc2lmaWVkIGJhc2VkIG9uIGRlc2NyaXB0aW9ucyBmcm9tIEBNb2VuMjAxNyBmb2N1c2luZyBvbiBhZHVsdCBiZWhhdmlvdXIgYW5kIG1pY3JvaGFiaXRhdCBwcmVmZXJlbmNlcyBvdXRzaWRlIHRoZSBicmVlZGluZyBzZWFzb24sIGdpdmVuIHRoYXQgbWFueSBhbnVyYW5zIGJyZWVkIGluIHdhdGVyIGJ1dCBhcmUgbm90IGFkYXB0ZWQgdG8gbGl2ZSBpbiB3YXRlciBhbGwgeWVhciAoKipUYWJsZSBTMioqKS4KCiMjIyBUYWJsZSBTMSB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxscyAtfSAKCioqVGFibGUgUzEqKiBBcmlkaXR5IGluZGV4IFtAQnVkeWtvMTk2MV0gYW5kIHRoZSBQYWxtZXIgRHJvdWdodCBTZXZlcml0eSBJbmRleCBbQFBhbG1lcjE5NjVdIGNhdGVnb3Jpc2VkLgoKYGBge3IgdGFibGUgUzEsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmRhdGEuZnJhbWUoQUkgPSBjKCJIdW1pZCIsICJEcnkgc3ViLWh1bWlkIiwgIlNlbWktYXJpZCIsICJBcmlkIiwiSHlwZXItYXJpZCIsICIiLCAiIiksIAogICAgICAgICAgIFZhbHVlID0gYygi4omlIDAuNjUiLCAiMC41MCDigJMg4omkIDAuNjUiLCAiMC4yMCDigJMg4omkIDAuNTAiLCAiMC4wNSDigJMg4omkIDAuMjAiLCAiPCAwLjA1IiwgIiIsICIiKSwKICAgICAgICAgICBQRFNJID0gYygiRXh0cmVtZWx5IG1vaXN0IiwgIlZlcnkgbW9pc3QiLCAiTW9kZXJhdGUgbW9pc3QiLCAiTm9ybWFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTW9kZXJhdGUgZHJvdWdodCIsICJTZXZlcmUgZHJvdWdodCIsICIgRXh0cmVtZSBkcm91Z2h0IiksCiAgICAgICAgICAgVmFsdWUgPSBjKCLiiaUgNCIsICIzIOKAkyDiiaQgNCIsICIyIOKAkyDiiaQgMyIsICItMiDigJMg4omkIDIiLCAiLTMg4oCTIOKJpCAtMiIsICItNCDigJMg4omkIC0zIiwgIjwgLTQiKSkgJT4lCiAgZHBseXI6OnJlbmFtZSgiQXJpZGl0eSBpbmRleCAoQUkpIiAgICAgICAgICAgICAgICAgICA9IEFJLAogICAgICAgICAgICAgICAgIkFJIHZhbHVlIiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBWYWx1ZSwKICAgICAgICAgICAgICAgICJQYWxtZXIgRHJvdWdodCBTZXZlcml0eSBJbmRleCAoUERTSSkiID0gUERTSSwKICAgICAgICAgICAgICAgICJQRFNJIFZhbHVlIiAgICAgICAgICAgICAgICAgICAgICAgICAgID0gVmFsdWUuMSkgJT4lCiAga25pdHI6OmthYmxlKCkgCmBgYAoKIyMjIFRhYmxlIFMyIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKKipUYWJsZSBTMioqIE1pY3JvaGFiaXRhdCBwcmVmZXJlbmNlIG9yIGVjb3R5cGUgW0BNb2VuMjAxN10uCgpgYGB7ciB0YWJsZSBTMiwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZGF0YS5mcmFtZShFY290eXBlID0gYygiQXF1YXRpYyIsICJBcmJvcmVhbCIsICJTZW1pLWFxdWF0aWMgIiwgIkdyb3VuZC1kd2VsbGluZyIsIkZvc3NvcmlhbCIsICJTdHJlYW0tZHdlbGxpbmciKSwgCiAgICAgICAgICAgRGVzY3JpcHRpb24gPSBjKCJBbG1vc3QgYWx3YXlzIGluIHdhdGVyLiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAiQWJpbGl0eSB0byBjbGltYiB2ZWdldGF0aW9uIGFuZCBzcGVuZHMgYSBzdWJzdGFudGlhbCBhbW91bnQgb2YgdGltZSBhYm92ZSBncm91bmQgKGUuZy4gZm9yZXN0cywgb24gdG9wIG9mIHZlZ2V0YXRpb25zIGluIHdldGxhbmRzKS4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIlN0YXkgbmVhciB3YXRlciBib2RpZXMsIHVzdWFsbHkgcGVybWFuZW50IHdhdGVyIChlLmcuIGdyb3VuZC1sZXZlbCB3ZXRsYW5kcykuIE9mdGVuIG9ic2VydmVkIGluIHdhdGVyIGFuZCBuZWFyYnkgdmVnZXRhdGlvbi4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRlcnJlc3RyaWFsIG9ubHksIG5vdCBhbHdheXMgbmVhciB3YXRlciBib2RpZXMsIGhvd2V2ZXIgYWx3YXlzIGluIGEgbW9pc3QgZW52aXJvbm1lbnQgKGUuZy4gZm9yZXN0IGxlYWYgbGl0dGVyLCBtb2lzdCBzb2lscywgc2NydWJsYW5kcywgZ3Jhc3NsYW5kKS4gU29tZXRpbWVzIGFib3ZlIGdyb3VuZCBhbmQgc29tZXRpbWVzIHNlbWktZm9zc29yaWFsLiBDYW4gYmUgY2xhc3NpZmllZCBhcyBicm9hZC4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRoZSBub24tYnJlZWRpbmcgc2Vhc29uIGlzIHNwZW50IHVuZGVyZ3JvdW5kIGluIGJ1cnJvd3MuIENhcGFibGUgb2YgYnVycm93aW5nIGFuZCBhZXN0aXZhdGluZy4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlc3RyaWN0ZWQgdG8gbmVhciBmYXN0LWZsb3dpbmcgc3RyZWFtcyB1c3VhbGx5IG9uIHJvY2tzIG9yIHZlZ2V0YXRpb24gbmVhciBzdHJlYW1zLiIpKSAlPiUKICBrbml0cjo6a2FibGUoKSAKYGBgCgojIyBTcGVjaWVzIHJpY2huZXNzIHstfQoKQW51cmFuIChmcm9ncyBhbmQgdG9hZHMpICBkaXN0cmlidXRpb24gc2hhcGUgZmlsZXMgd2VyZSBvYnRhaW5lZCBmcm9tIHRoZSBJbnRlcm5hdGlvbmFsIFVuaW9uIGZvciBDb25zZXJ2YXRpb24gb2YgTmF0dXJlJ3MgUmVkIExpc3Qgb2YgVGhyZWF0ZW5lZCBTcGVjaWVzIChbSVVDTiBSZWQgTGlzdF0oaHR0cHM6Ly93d3cuaXVjbnJlZGxpc3Qub3JnL3Jlc291cmNlcy9zcGF0aWFsLWRhdGEtZG93bmxvYWQpOyBleHRyYWN0ZWQgb24gMTEvMDEvMjAyMSkuIFNwZWNpZXMgcmljaG5lc3Mgb3Igc3BlY2llcyBhc3NlbWJsYWdlcyB3YXMgZGVmaW5lZCBhcyB0aGUgc3VtIG9mIHNwZWNpZXMgaW4gZWFjaCBncmlkIGNlbGwgKDAuNcKwKSwgYmFzZWQgb24gdGhlIGdlb2dyYXBoaWMgcmFuZ2UsIGFuZCB3YXMgY2FsY3VsYXRlZCB1c2luZyB0aGUgYHJhc3Rlcml6ZUlVQ05gIGFuZCBgY2FsY1NSYCBmdW5jdGlvbiBmcm9tIHRoZSBmcm9tIHRoZSBbcmFzdGVyU3BdKGh0dHBzOi8vZ2l0aHViLmNvbS9SUy1lY28vcmFzdGVyU3ApIHBhY2thZ2UuIEVjb3R5cGUtc3BlY2lmaWMgc3BlY2llcyByaWNobmVzcyB3YXMgYWxzbyBjYWxjdWxhdGVkLgoKYGBge3Igc3AsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUUsIHJlc3VsdHM9ImhpZGUifQpmaWxlZGlyIDwtICJyYXN0ZXJTcC8iCgojIENsZWFuIHJhdyBkYXRhCmZyb2dfZGF0IDwtIHJlYWQuY3N2KGZpbGUucGF0aChkYXRhX3BhdGgsICJhbnVyYW5fc3BlY2llc19saXN0LmNzdiIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KGdlbnVzOnN0cmF0ZWd5LCBTVkxfY206Ymlub21pYWxfdHJlZV9waHlsbykgJT4lCiAgZHBseXI6Om11dGF0ZShsblNWTCAgICAgICA9IGxvZyhTVkxfY20pLAogICAgICAgICAgICAgICAgbG5NYXNzICAgICAgPSBsb2cobWFzc19nKSwKICAgICAgICAgICAgICAgIGxuQXJlYSAgICAgID0gbG9nKHNoYXBlX2FyZWEpLAogICAgICAgICAgICAgICAgSVVDTiAgICAgICAgPSBmYWN0b3IoSVVDTiwgbGV2ZWxzID0gYygiTGVhc3QgQ29uY2VybiIsICJOZWFyIFRocmVhdGVuZWQiLCAiVnVsbmVyYWJsZSIsICJFbmRhbmdlcmVkIiwgIkNyaXRpY2FsbHkgRW5kYW5nZXJlZCIsICJFeHRpbmN0IikpLAogICAgICAgICAgICAgICAgb3JkZXJfbmFtZSAgPSBmYWN0b3Iob3JkZXJfbmFtZSksCiAgICAgICAgICAgICAgICBmYW1pbHlfbmFtZSA9IGZhY3RvcihmYW1pbHlfbmFtZSksCiAgICAgICAgICAgICAgICBlY290eXBlICAgICA9IGZhY3RvcihlY290eXBlKSkgJT4lCiAgZHBseXI6OmZpbHRlcihvcmRlcl9uYW1lID09ICJBTlVSQSIgJiBlY290eXBlICE9ICIiICYgSVVDTiAhPSAiIiAmIElVQ04gIT0gIkV4dGluY3QiKSAlPiUKICBkcm9wbGV2ZWxzKCkKCiMgQ29udmVydCBzaGFwZSBmaWxlcyBpbnRvIHJhc3RlcnMgYW5kIHNhdmUgdG8gZmlsZSBvbmNlIChkb3dubG9hZGVkIHNoYXBlIGZpbGVzIDA4LzAxLzIwMjApCiMgb25seSBleHRyYWN0ZWQgZGlzdHJpYnV0aW9uIG9mIG5hdGl2ZSByYW5nZQojYW51cmFuX3Jhc3QgPC0gcmFzdGVyaXplSVVDTihkc24gPSBwYXN0ZTAoZmlsZWRpciwgIkFOVVJBL0FOVVJBLnNocCIpLCByZXNvbHV0aW9uID0gMC41LCBzZWFzb25hbCA9IGMoMSwgMiksIG9yaWdpbiA9IDEsIHByZXNlbmNlID0gYygxLDIpLCBzYXZlID0gVFJVRSwgcGF0aCA9IHBhc3RlMChyYXN0ZXJTcF9wYXRoKSkKCiMgQ2FsY3VsYXRlIGFudXJhbiByaWNobmVzcyBhbmQgYnkgZWNvdHlwZSAKIyBUaGUgY2FsY1NSIGZ1bmN0aW9uIHVzZXMgYSBzdGVwd2lzZSBwcm9jZWR1cmUgdG8gY2FsY3VsYXRlIHRoZSBzdW0gb2Ygc3BlY2llcyBmb3IgZWFjaCBncmlkIGNlbGwuCmFudXJhbl9zciAgICA8LSByYXN0ZXJTcDo6Y2FsY1NSKHNwZWNpZXNfbmFtZXMgPSBmcm9nX2RhdCRiaW5vbWlhbF9JVUNOLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9IHBhc3RlMChyYXN0ZXJTcF9wYXRoKSkKYXF1YXRpY19zciAgIDwtIHJhc3RlclNwOjpjYWxjU1Ioc3BlY2llc19uYW1lcyA9IGZyb2dfZGF0W2Zyb2dfZGF0JGVjb3R5cGUgPT0gIkFxdWF0aWMiLCAiYmlub21pYWxfSVVDTiJdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9IHBhc3RlMChyYXN0ZXJTcF9wYXRoKSkKYXJib3JlYWxfc3IgIDwtIHJhc3RlclNwOjpjYWxjU1Ioc3BlY2llc19uYW1lcyA9IGZyb2dfZGF0W2Zyb2dfZGF0JGVjb3R5cGUgPT0gIkFyYm9yZWFsIiwgImJpbm9taWFsX0lVQ04iXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGggPSBwYXN0ZTAocmFzdGVyU3BfcGF0aCkpCmZvc3NvcmlhbF9zciA8LSByYXN0ZXJTcDo6Y2FsY1NSKHNwZWNpZXNfbmFtZXMgPSBmcm9nX2RhdFtmcm9nX2RhdCRlY290eXBlID09ICJGb3Nzb3JpYWwiLCAiYmlub21pYWxfSVVDTiJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gcGFzdGUwKHJhc3RlclNwX3BhdGgpKQpncm91bmRfc3IgICAgPC0gcmFzdGVyU3A6OmNhbGNTUihzcGVjaWVzX25hbWVzID0gZnJvZ19kYXRbZnJvZ19kYXQkZWNvdHlwZSA9PSAiR3JvdW5kLWR3ZWxsaW5nIiwgImJpbm9taWFsX0lVQ04iXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGggPSBwYXN0ZTAocmFzdGVyU3BfcGF0aCkpCnNlbWlfYXFfc3IgICA8LSByYXN0ZXJTcDo6Y2FsY1NSKHNwZWNpZXNfbmFtZXMgPSBmcm9nX2RhdFtmcm9nX2RhdCRlY290eXBlID09ICJTZW1pLWFxdWF0aWMiLCAiYmlub21pYWxfSVVDTiJdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9IHBhc3RlMChyYXN0ZXJTcF9wYXRoKSkKc3RyZWFtX3NyICAgIDwtIHJhc3RlclNwOjpjYWxjU1Ioc3BlY2llc19uYW1lcyA9IGZyb2dfZGF0W2Zyb2dfZGF0JGVjb3R5cGUgPT0gIlN0cmVhbS1kd2VsbGluZyIsICJiaW5vbWlhbF9JVUNOIl0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gcGFzdGUwKHJhc3RlclNwX3BhdGgpKQoKIyBDb252ZXJ0IHJhc3RlciB0byBtYXRyaXggdGhlbiB0byBkYXRhIGZyYW1lCmFudXJhbl9zcl9kZiAgICA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhhbnVyYW5fc3IpKSAlPiUgZHBseXI6OnJlbmFtZShzcGVjaWVzX24gPSBsYXllcikKYXF1YXRpY19zcl9kZiAgIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKGFxdWF0aWNfc3IpKSAlPiUgZHBseXI6OnJlbmFtZShhcXVhdGljX24gPSBsYXllcikKYXJib3JlYWxfc3JfZGYgIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKGFyYm9yZWFsX3NyKSkgJT4lIGRwbHlyOjpyZW5hbWUoYXJib3JlYWxfbiA9IGxheWVyKQpmb3Nzb3JpYWxfc3JfZGYgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMoZm9zc29yaWFsX3NyKSkgJT4lIGRwbHlyOjpyZW5hbWUoZm9zc29yaWFsX24gPSBsYXllcikKZ3JvdW5kX3NyX2RmICAgIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKGdyb3VuZF9zcikpICU+JSBkcGx5cjo6cmVuYW1lKGdyb3VuZF9uID0gbGF5ZXIpCnNlbWlfYXFfc3JfZGYgICA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhzZW1pX2FxX3NyKSkgJT4lIGRwbHlyOjpyZW5hbWUoc2VtaV9hcV9uID0gbGF5ZXIpCnN0cmVhbV9zcl9kZiAgICA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhzdHJlYW1fc3IpKSAlPiUgZHBseXI6OnJlbmFtZShzdHJlYW1fbiA9IGxheWVyKQpgYGAKClRoZXJlIHdlcmUgYHIgbGVuZ3RoKHVuaXF1ZShmcm9nX2RhdCRiaW5vbWlhbF9JVUNOKSlgIGFudXJhbiBzcGVjaWVzIGZyb20gdGhlIElVQ04gUmVkIExpc3QgYXZhaWxhYmxlIGZvciB0aGUgQUkgYW5kIFBEU0kgYW5hbHlzaXMuCgojIyBDYWxjdWxhdGUgQUkgYW5kIFBEU0kgey19CgpIaWdoIHJlc29sdXRpb24gKH40IGttXjJeKSBnbG9iYWwgZGF0YXNldCBvbiBwcmVjaXBpdGF0aW9uIChtbS9tb250aCkgYW5kIHBvdGVudGlhbCBldmFwb3RyYW5zcGlyYXRpb24gKG1tL21vbnRoKSB3ZXJlIG9idGFpbmVkIGZyb20gQEFiYXR6b2dsb3UyMDE4IHVuZGVyIDEpIHRoZSBjdXJyZW50IGNsaW1hdGUgKDE5NzDigJMyMDAwKSwgMikgYW4gaW50ZXJtZWRpYXRlIGdyZWVuaG91c2UgZ2FzIGVtaXNzaW9uIHNjZW5hcmlvIG9mICsywrBDIChTaGFyZWQgU29jaW9lY29ub21pYyBQYXRod2F5IDLigJM0LjU7IFNQUDLigJM0LjUpLCBhbmQgMykgYSBoaWdoIGdyZWVuaG91c2UgZ2FzIGVtaXNzaW9uIG9yIOKAnGJ1c2luZXNzLWFzLXVzdWFs4oCdIHNjZW5hcmlvIG9mICs0wrBDIChTU1A14oCTOC41KSBieSAyMDgw4oCTMjA5OSAoKipGaWcuIFMxYeKAk2YqKikuIEFJIHdhcyBjYWxjdWxhdGVkIGFzIHRoZSByYXRpbyBvZiB0aGUgdG90YWwgcHJlY2lwaXRhdGlvbiByZWxhdGl2ZSB0byB0aGUgcG90ZW50aWFsIGV2YXBvdHJhbnNwaXJhdGlvbiB1bmRlciB0aGUgY3VycmVudCBjbGltYXRlLCBTUFAy4oCTNC41LCBhbmQgU1NQNeKAkzguNSBzY2VuYXJpbyAoKipGaWcuIFMxZ+KAk2kqKikuCgpXZSB1c2VkIGEgc2VsZi1jYWxpYnJhdGVkIFBEU0kgd2l0aCBQZW5tYW7igJNNb250ZWl0aCBwb3RlbnRpYWwgZXZhcG90cmFuc3BpcmF0aW9uIHJlcHJlc2VudGluZyB0aGUgY3VycmVudCBjbGltYXRlICgxOTcw4oCTMjAwMCkgYW5kIGFuIGludGVybWVkaWF0ZSBhbmQgaGlnaCBlbWlzc2lvbiBzY2VuYXJpbyBieSAyMDgw4oCTMjA5OSAoU1NQMuKAkzQuNSBhbmQgU1NQNS04LjUpIGZyb20gQFpoYW8yMDIyLiBUaGUgU1NQMuKAkzQuNSBhbmQgU1NQNeKAkzguNSBzY2VuYXJpb3Mgd2VyZSBiYXNlZCBvbiB0aGUgYXZlcmFnZSBvZiAyNSBDTUlQNiBtb2RlbHMgb2YgcHJlY2lwaXRhdGlvbiwgZXZhcG90cmFuc3BpcmF0aW9uLCBzb2lsIG1vaXN0dXJlLCBhbmQgcnVub2ZmIFtARXlyaW5nMjAxNl0sIHdoZXJlIHRoZSBtZWFuIGFubnVhbCBzdXJmYWNlIHRlbXBlcmF0dXJlIGlzIGV4cGVjdGVkIHRvIGluY3JlYXNlIGJ5IDIuN8KwQyAoMi4x4oCTMy41wrBDIHJhbmdlKSBhbmQgNC40wrBDICgzLjPigJM1LjfCsEMgcmFuZ2UpLCByZXNwZWN0aXZlbHkgYnkgMjA4MOKAkzIxMDAgW0BJUENDMjAyMV0uCgpgYGB7ciBjbGltIGRhdCwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9VFJVRSwgcmVzdWx0cz0iaGlkZSJ9CiMgSW1wb3J0IHRoZSBkb3dubG9hZGVkIGZpbGVzCnBwdF9yYXN0IDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKHggPSBmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnVGVycmFDbGltYXRlMTk4MTIwMTBfcHB0Lm5jJykpLCBhbnVyYW5fc3IpICMgUHJlY2lwaXRhdGlvbiB5ZWFyIDE5ODEtMjAxMCAtIFByIChtbSkKcGV0X3Jhc3QgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soeCA9IGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdUZXJyYUNsaW1hdGUxOTgxMjAxMF9wZXQubmMnKSksIGFudXJhbl9zcikgIyBFdmFwb3RyYW5zcGlyYXRpb24gMTk4MS0yMDEwIC0gRVQwIChtbSkKCiMgKzJDIGFuZCArNEMgZnV0dXJlIHNjZW5hcmlvcyAKcHB0XzJDX3Jhc3QgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soeCA9IGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdUZXJyYUNsaW1hdGUyQ19wcHQubmMnKSksIGFudXJhbl9zcikKcGV0XzJDX3Jhc3QgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soeCA9IGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdUZXJyYUNsaW1hdGUyQ19wZXQubmMnKSksIGFudXJhbl9zcikKcHB0XzRDX3Jhc3QgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soeCA9IGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdUZXJyYUNsaW1hdGU0Q19wcHQubmMnKSksIGFudXJhbl9zcikKcGV0XzRDX3Jhc3QgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soeCA9IGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdUZXJyYUNsaW1hdGU0Q19wZXQubmMnKSksIGFudXJhbl9zcikKCiMgT2J0YWluIG1lYW4gdmFsdWVzIGZyb20gMTk4MS0yMDEwCnBwdF9tZWFuX3Jhc3QgICAgPC0gcmFzdGVyOjpjYWxjKHBwdF9yYXN0LCBmdW4gPSBtZWFuLCBuYS5ybSA9IFRSVUUpCnBldF9tZWFuX3Jhc3QgICAgPC0gcmFzdGVyOjpjYWxjKHBldF9yYXN0LCBmdW4gPSBtZWFuLCBuYS5ybSA9IFRSVUUpIApwcHRfMkNfbWVhbl9yYXN0IDwtIHJhc3Rlcjo6Y2FsYyhwcHRfMkNfcmFzdCwgZnVuID0gbWVhbiwgbmEucm0gPSBUUlVFKSAKcGV0XzJDX21lYW5fcmFzdCA8LSByYXN0ZXI6OmNhbGMocGV0XzJDX3Jhc3QsIGZ1biA9IG1lYW4sIG5hLnJtID0gVFJVRSkKcHB0XzRDX21lYW5fcmFzdCA8LSByYXN0ZXI6OmNhbGMocHB0XzRDX3Jhc3QsIGZ1biA9IG1lYW4sIG5hLnJtID0gVFJVRSkKcGV0XzRDX21lYW5fcmFzdCA8LSByYXN0ZXI6OmNhbGMocGV0XzRDX3Jhc3QsIGZ1biA9IG1lYW4sIG5hLnJtID0gVFJVRSkgCgojIE9idGFpbiBtZWFuIHZhbHVlcyBmcm9tIDEwLXllYXIgbW9udGhseSBQRFNJClBEU0lfc3NwMjQ1X3Jhc3QgPC0gcmFzdGVyOjpzdGFjayh4ID0gZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgICdwZHNpc2MubW9udGhseS4xOTAwLTIxMDAucjIuNXgyLjUuRW5zQXZnMjVNb2RlbHMuVFAyLmlwZS0yLnNzcDI0NS5uYycpKQpQRFNJX3NzcDU4NV9yYXN0IDwtIHJhc3Rlcjo6c3RhY2soeCA9IGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICAncGRzaXNjLm1vbnRobHkuMTkwMC0yMTAwLnIyLjV4Mi41LkVuc0F2ZzI1TW9kZWxzLlRQMi5pcGUtMi5zc3A1ODUubmMnKSkKClBEU0lfY3VyX3Jhc3QgPC0gcmFzdGVyOjpzdWJzZXQoUERTSV9zc3AyNDVfcmFzdCwgZ3JlcCgiWDE5Ny4qfFgxOTguKnxYMTk5LioiLCBuYW1lcyhQRFNJX3NzcDI0NV9yYXN0KSwgdmFsdWUgPSBUKSkKUERTSV8yQ19yYXN0ICA8LSByYXN0ZXI6OnN1YnNldChQRFNJX3NzcDI0NV9yYXN0LCBncmVwKCJYMjA3Lip8WDIwOC4qfFgyMDkuKiIsIG5hbWVzKFBEU0lfc3NwMjQ1X3Jhc3QpLCB2YWx1ZSA9IFQpKQpQRFNJXzRDX3Jhc3QgIDwtIHJhc3Rlcjo6c3Vic2V0KFBEU0lfc3NwNTg1X3Jhc3QsIGdyZXAoIlgyMDcuKnxYMjA4Lip8WDIwOS4qIiwgbmFtZXMoUERTSV9zc3A1ODVfcmFzdCksIHZhbHVlID0gVCkpCgpQRFNJX2N1cl9tZWFuX3Jhc3QgPC0gcmFzdGVyOjpjYWxjKFBEU0lfY3VyX3Jhc3QsIGZ1biA9IG1lYW4sIG5hLnJtID0gVFJVRSkKUERTSV8yQ19tZWFuX3Jhc3QgIDwtIHJhc3Rlcjo6Y2FsYyhQRFNJXzJDX3Jhc3QsIGZ1biA9IG1lYW4sIG5hLnJtID0gVFJVRSkgClBEU0lfNENfbWVhbl9yYXN0ICA8LSByYXN0ZXI6OmNhbGMoUERTSV80Q19yYXN0LCBmdW4gPSBtZWFuLCBuYS5ybSA9IFRSVUUpIAoKIyBDYWxjdWxhdGUgYXJpZGl0eSBpbmRleCBbUHJlY2lwaXRhdGlvbiAocHB0KSAvIEV2YXBvdHJhbnNwaXJhdGlvbiAocGV0KV0KYWlfcmFzdCAgICA8LSByYXN0ZXI6Om92ZXJsYXkoeCA9IHBwdF9tZWFuX3Jhc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gcGV0X21lYW5fcmFzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1biA9IGZ1bmN0aW9uKHgsIHkpIHtyZXR1cm4oeCAvIHkpfSkKYWlfMkNfcmFzdCA8LSByYXN0ZXI6Om92ZXJsYXkoeCA9IHBwdF8yQ19tZWFuX3Jhc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gcGV0XzJDX21lYW5fcmFzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1biA9IGZ1bmN0aW9uKHgsIHkpIHtyZXR1cm4oeCAvIHkpfSkgCmFpXzRDX3Jhc3QgPC0gcmFzdGVyOjpvdmVybGF5KHggPSBwcHRfNENfbWVhbl9yYXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHBldF80Q19tZWFuX3Jhc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW4gPSBmdW5jdGlvbih4LCB5KSB7cmV0dXJuKHggLyB5KX0pIAoKIyBDYWxjdWxhdGUgY2hhbmdlIGluIFBEU0kKIyBSZXByb2plY3QgaW50ZW5zaXR5IHJhc3RlciB0byBtYXRjaCBhbnVyYW5fc3IKUERTSV9jdXJfbWVhbl9yYXN0IDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihQRFNJX2N1cl9tZWFuX3Jhc3QsIGFudXJhbl9zcikKUERTSV8yQ19tZWFuX3Jhc3QgIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihQRFNJXzJDX21lYW5fcmFzdCwgYW51cmFuX3NyKQpQRFNJXzRDX21lYW5fcmFzdCAgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKFBEU0lfNENfbWVhbl9yYXN0LCBhbnVyYW5fc3IpCgpQRFNJXzJDX2RpZmZfcmFzdCA8LSByYXN0ZXI6Om92ZXJsYXkoeCA9IFBEU0lfY3VyX21lYW5fcmFzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gUERTSV8yQ19tZWFuX3Jhc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuID0gZnVuY3Rpb24oeCwgeSkge3JldHVybih5IC0geCl9KSAKUERTSV80Q19kaWZmX3Jhc3QgPC0gcmFzdGVyOjpvdmVybGF5KHggPSBQRFNJX2N1cl9tZWFuX3Jhc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IFBEU0lfNENfbWVhbl9yYXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1biA9IGZ1bmN0aW9uKHgsIHkpIHtyZXR1cm4oeSAtIHgpfSkgCgojIENvbnZlcnQgcmFzdGVyIHRvIG1hdHJpeCB0aGVuIHRvIGRhdGEgZnJhbWUKYWlfZGYgICAgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMoYWlfcmFzdCkpCmFpXzJDX2RmIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKGFpXzJDX3Jhc3QpKQphaV80Q19kZiA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhhaV80Q19yYXN0KSkKClBEU0lfMkNfZGlmZl9kZiA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhQRFNJXzJDX2RpZmZfcmFzdCkpClBEU0lfNENfZGlmZl9kZiA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhQRFNJXzRDX2RpZmZfcmFzdCkpCgojIENvbnZlcnQgYXJpZGl0eSBpbmRleCBpbnRvIGNhdGVnb3J5CmFpX2RmIDwtIGFpX2RmICU+JSAKICAjIFJlY29kZQogIGRwbHlyOjptdXRhdGUoY2F0ZWdvcnkgPSBjYXNlX3doZW4oCiAgICBpcy5pbmZpbml0ZShsYXllcikgfiAnSHVtaWQnLAogICAgbGF5ZXIgPj0gMC42NSB+ICdIdW1pZCcsICAgICAgICAgICAgIAogICAgbGF5ZXIgPj0gMC41ICYgbGF5ZXIgPCAwLjY1IH4gJ0RyeSBzdWItaHVtaWQnLAogICAgbGF5ZXIgPj0gMC4yICYgbGF5ZXIgPCAwLjUgfiAnU2VtaS1hcmlkJywgCiAgICBsYXllciA+PSAwLjA1ICYgbGF5ZXIgPCAwLjIgfiAnQXJpZCcsIAogICAgbGF5ZXIgPCAwLjA1IH4gJ0h5cGVyLWFyaWQnCiAgKSkgJT4lIAogICMgQ29udmVydCB0byBvcmRlcmVkIGZhY3RvcgogIGRwbHlyOjptdXRhdGUoY2F0ZWdvcnkgPSBmYWN0b3IoY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJ0h5cGVyLWFyaWQnLCAnQXJpZCcsICdTZW1pLWFyaWQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdEcnkgc3ViLWh1bWlkJywgJ0h1bWlkJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkKCmFpXzJDX2RmIDwtIGFpXzJDX2RmICU+JSAKICAjIFJlY29kZQogIGRwbHlyOjptdXRhdGUoY2F0ZWdvcnkgPSBjYXNlX3doZW4oCiAgICBpcy5pbmZpbml0ZShsYXllcikgfiAnSHVtaWQnLAogICAgbGF5ZXIgPj0gMC42NSB+ICdIdW1pZCcsICAgICAgICAgICAgICAgICAgICAgICAKICAgIGxheWVyID49IDAuNSAmIGxheWVyIDwgMC42NSB+ICdEcnkgc3ViLWh1bWlkJywgCiAgICBsYXllciA+PSAwLjIgJiBsYXllciA8IDAuNSB+ICdTZW1pLWFyaWQnLCAgICAgIAogICAgbGF5ZXIgPj0gMC4wNSAmIGxheWVyIDwgMC4yIH4gJ0FyaWQnLCAgIAogICAgbGF5ZXIgPCAwLjA1IH4gJ0h5cGVyLWFyaWQnCiAgKSkgJT4lIAogICMgQ29udmVydCB0byBvcmRlcmVkIGZhY3RvcgogIGRwbHlyOjptdXRhdGUoY2F0ZWdvcnkgPSBmYWN0b3IoY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJ0h5cGVyLWFyaWQnLCAnQXJpZCcsICdTZW1pLWFyaWQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdEcnkgc3ViLWh1bWlkJywgJ0h1bWlkJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkKCmFpXzRDX2RmIDwtIGFpXzRDX2RmICU+JSAKICAjIFJlY29kZQogIGRwbHlyOjptdXRhdGUoY2F0ZWdvcnkgPSBjYXNlX3doZW4oCiAgICBpcy5pbmZpbml0ZShsYXllcikgfiAnSHVtaWQnLAogICAgbGF5ZXIgPj0gMC42NSB+ICdIdW1pZCcsICAgICAgICAgICAgICAgICAgICAgICAKICAgIGxheWVyID49IDAuNSAmIGxheWVyIDwgMC42NSB+ICdEcnkgc3ViLWh1bWlkJywgCiAgICBsYXllciA+PSAwLjIgJiBsYXllciA8IDAuNSB+ICdTZW1pLWFyaWQnLCAgICAgIAogICAgbGF5ZXIgPj0gMC4wNSAmIGxheWVyIDwgMC4yIH4gJ0FyaWQnLCAgIAogICAgbGF5ZXIgPCAwLjA1IH4gJ0h5cGVyLWFyaWQnCiAgKSkgJT4lIAogICMgQ29udmVydCB0byBvcmRlcmVkIGZhY3RvcgogIGRwbHlyOjptdXRhdGUoY2F0ZWdvcnkgPSBmYWN0b3IoY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJ0h5cGVyLWFyaWQnLCAnQXJpZCcsICdTZW1pLWFyaWQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdEcnkgc3ViLWh1bWlkJywgJ0h1bWlkJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkKCiMgQ29udmVydCBQRFNJIHRvIGNhdGVnb3J5ClBEU0lfMkNfZGlmZl9kZiA8LSBQRFNJXzJDX2RpZmZfZGYgJT4lIAogICMgUmVjb2RlCiAgZHBseXI6Om11dGF0ZShjaGFuZ2VfMkMgPSBjYXNlX3doZW4oCiAgICBsYXllciA+PSA0IH4gIjQiLCAgICAgICAgICAgICAgICAKICAgIGxheWVyID49IDMgJiBsYXllciA8IDQgfiAnMycsCiAgICBsYXllciA+PSAyICYgbGF5ZXIgPCAzIH4gJzInLCAKICAgIGxheWVyID49IDEgJiBsYXllciA8IDIgfiAnMScsICAKICAgIGxheWVyID49IC0xICYgbGF5ZXIgPCAxIH4gJzAnLCAgCiAgICBsYXllciA+PSAtMiAmIGxheWVyIDwgLTEgfiAnLTEnLCAKICAgIGxheWVyID49IC0zICYgbGF5ZXIgPCAtMiB+ICctMicsIAogICAgbGF5ZXIgPj0gLTQgJiBsYXllciA8IC0zIH4gJy0zJywgCiAgICBsYXllciA8IC00IH4gJy00JwogICkpICU+JSAKICAjIENvbnZlcnQgdG8gb3JkZXJlZCBmYWN0b3IKICBkcGx5cjo6bXV0YXRlKGNoYW5nZV8yQyA9IGZhY3RvcihjaGFuZ2VfMkMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnLTQnLCAnLTMnLCAnLTInLCAnLTEnLCAnMCcsICcxJywgJzInLCAnMycsICc0JyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKQoKUERTSV80Q19kaWZmX2RmIDwtIFBEU0lfNENfZGlmZl9kZiAlPiUgCiAgIyBSZWNvZGUKICBkcGx5cjo6bXV0YXRlKGNoYW5nZV80QyA9IGNhc2Vfd2hlbigKICAgIGxheWVyID49IDQgfiAiNCIsICAgICAgICAgICAgICAgIAogICAgbGF5ZXIgPj0gMyAmIGxheWVyIDwgNCB+ICczJywKICAgIGxheWVyID49IDIgJiBsYXllciA8IDMgfiAnMicsIAogICAgbGF5ZXIgPj0gMSAmIGxheWVyIDwgMiB+ICcxJywgIAogICAgbGF5ZXIgPj0gLTEgJiBsYXllciA8IDEgfiAnMCcsICAKICAgIGxheWVyID49IC0yICYgbGF5ZXIgPCAtMSB+ICctMScsIAogICAgbGF5ZXIgPj0gLTMgJiBsYXllciA8IC0yIH4gJy0yJywgCiAgICBsYXllciA+PSAtNCAmIGxheWVyIDwgLTMgfiAnLTMnLCAKICAgIGxheWVyIDwgLTQgfiAnLTQnCiAgKSkgJT4lIAogICMgQ29udmVydCB0byBvcmRlcmVkIGZhY3RvcgogIGRwbHlyOjptdXRhdGUoY2hhbmdlXzRDID0gZmFjdG9yKGNoYW5nZV80QywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCctNCcsICctMycsICctMicsICctMScsICcwJywgJzEnLCAnMicsICczJywgJzQnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkpCmBgYAoKYGBge3IgRmlnIFMxLCBtZXNzYWdlPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5oZWlnaHQ9Ni41LCBmaWcud2lkdGg9OX0KIyBDcm9wIGFuZCBtYXNrCndvcmxkICAgICAgPC0gc2Y6OnJlYWRfc2YoZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgIm5lXzUwbV9sYW5kL25lXzUwbV9sYW5kLnNocCIpKQp3b3JsZF9zcCAgIDwtIHNmOjphc19TcGF0aWFsKHdvcmxkKQp3b3JsZF9zcGRmIDwtIHNwOjpTcGF0aWFsUG9seWdvbnNEYXRhRnJhbWUod29ybGRfc3AsIHdvcmxkX3NwQGRhdGEpIAoKIyBQcmVjaXBpdGF0aW9uCnBwdF9jdXJyX3Bsb3QgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMocHB0X21lYW5fcmFzdCkpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gbGF5ZXIpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9zcGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiWWxHbkJ1IiwgbGltID0gYygwLCA2NTApLCBuYW1lID0gIlByZWNpcGl0YXRpb24gKG1tKSIpICsKICBnZ3RpdGxlKCJQcmVjaXBpdGF0aW9uICgxOTgxLTIwMTApIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MCwgOTApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE4MCwgMTgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMTAsIGJhcmhlaWdodCA9IDAuMywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwucG9zaXRpb24gPSAiYm90dG9tIikpICsKICB0aGVtZV92b2lkKCkgKyB5bGFiKE5VTEwpICsgeGxhYihOVUxMKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwgCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICAKCnBwdF8yQ19wbG90IDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKHBwdF8yQ19tZWFuX3Jhc3QpKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoYWVzKHkgPSB5LCB4ID0geCwgZmlsbCA9IGxheWVyKSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGRfc3BkZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgY29sb3VyID0gIiM2NDY4NmIiLCBmaWxsID0gTkEsIHNpemUgPSAwLjEpICsKICBzY2FsZV9maWxsX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIllsR25CdSIsIGxpbSA9IGMoMCwgNjUwKSkgKwogIGdndGl0bGUoIlByZWNpcGl0YXRpb24gKCsywrBDIDIwODAtMjEwMCkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTYwLCA5MCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTgwLCAxODApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKQoKcHB0XzRDX3Bsb3QgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMocHB0XzRDX21lYW5fcmFzdCkpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gbGF5ZXIpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9zcGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiWWxHbkJ1IiwgbGltID0gYygwLCA2NTApKSArCiAgZ2d0aXRsZSgiUHJlY2lwaXRhdGlvbiAoKzTCsEMgMjA4MC0yMTAwKSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNjAsIDkwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xODAsIDE4MCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZV92b2lkKCkgKyB5bGFiKE5VTEwpICsgeGxhYihOVUxMKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICAKCnBwdF9sZWdlbmQgPC0gY293cGxvdDo6Z2V0X2xlZ2VuZChwcHRfY3Vycl9wbG90KQoKcHB0X3Byb3cgPC0gY293cGxvdDo6cGxvdF9ncmlkKHBwdF9jdXJyX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLCAKICAgICAgICAgICAgICAgICAgIHBwdF8yQ19wbG90ICsgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIAogICAgICAgICAgICAgICAgICAgcHB0XzRDX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLCAKICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLCBuY29sID0gMywgbGFiZWxzID0gYygnYScsICdiJywgJ2MnKSkgCgpwcHRfcGxvdHMgPC0gY293cGxvdDo6cGxvdF9ncmlkKHBwdF9wcm93LCBwcHRfbGVnZW5kLCBuY29sID0gMSwgcmVsX2hlaWdodHMgPSBjKDEsIC4xKSkKCiMgRXZhcG90cmFuc3BpcmF0aW9uCnBldF9jdXJyX3Bsb3QgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMocGV0X21lYW5fcmFzdCkpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gbGF5ZXIpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9zcGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUm9ja2V0IiwgbGltID0gYygwLCAzMDApLCBuYW1lID0gIkV2YXBvdHJhbnNwaXJhdGlvbiAobW0pIikgKwogIGdndGl0bGUoIkV2YXBvdHJhbnNwaXJhdGlvbiAoMTk4MS0yMDEwKSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNjAsIDkwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xODAsIDE4MCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDEwLCBiYXJoZWlnaHQgPSAwLjMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAgCgpwZXRfMkNfcGxvdCA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhwZXRfMkNfbWVhbl9yYXN0KSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBsYXllcikpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkX3NwZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJSb2NrZXQiLCBsaW0gPSBjKDAsIDMwMCkpICsKICBnZ3RpdGxlKCJFdmFwb3RyYW5zcGlyYXRpb24gKCsywrBDIDIwODAtMjEwMCkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTYwLCA5MCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTgwLCAxODApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKQoKcGV0XzRDX3Bsb3QgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMocGV0XzRDX21lYW5fcmFzdCkpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gbGF5ZXIpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9zcGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUm9ja2V0IiwgbGltID0gYygwLCAzMDApKSArCiAgZ2d0aXRsZSgiRXZhcG90cmFuc3BpcmF0aW9uICgrNMKwQyAyMDgwLTIxMDApIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MCwgOTApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE4MCwgMTgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkgIAoKcGV0X2xlZ2VuZCA8LSBjb3dwbG90OjpnZXRfbGVnZW5kKHBldF9jdXJyX3Bsb3QpCgpwZXRfcHJvdyA8LSBjb3dwbG90OjpwbG90X2dyaWQocGV0X2N1cnJfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIAogICAgICAgICAgICAgICAgICAgcGV0XzJDX3Bsb3QgKyAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwgCiAgICAgICAgICAgICAgICAgICBwZXRfNENfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIAogICAgICAgICAgICAgICAgICAgYWxpZ24gPSAidiIsIG5jb2wgPSAzLCBsYWJlbHMgPSBjKCdkJywgJ2UnLCAnZicpKSAKCnBldF9wbG90cyA8LSBjb3dwbG90OjpwbG90X2dyaWQocGV0X3Byb3csIHBldF9sZWdlbmQsIG5jb2wgPSAxLCByZWxfaGVpZ2h0cyA9IGMoMSwgLjEpKQoKIyBBcmlkaXR5IEluZGV4CmFyaWRfY29sIDwtIGMoJyM4RTA2M0InLCAnI0NCNkQ1MycsICcjRTk5QTJDJywgJyNGNUQ1NzknLCAnd2hpdGUnKQphaV9jdXJyX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBhaV9kZiwgYWVzKHkgPSB5LCB4ID0geCwgZmlsbCA9IGNhdGVnb3J5KSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGRfc3BkZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgY29sb3VyID0gIiM2NDY4NmIiLCBmaWxsID0gTkEsIHNpemUgPSAwLjEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBhcmlkX2NvbCwKICAgICAgICAgICAgICAgICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJBcmlkaXR5IEluZGV4IikgKwogIGdndGl0bGUoIkFyaWRpdHkgSW5kZXggKDE5ODEtMjAxMCkiKSArCiAgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MCwgOTApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE4MCwgMTgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lX3ZvaWQoKSArIAogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIAogICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC4yLCAnY20nKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkKCmFpXzJDX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBhaV8yQ19kZiwgYWVzKHkgPSB5LCB4ID0geCwgZmlsbCA9IGNhdGVnb3J5KSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGRfc3BkZiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgY29sb3VyID0gIiM2NDY4NmIiLCBmaWxsID0gTkEsIHNpemUgPSAwLjEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBhcmlkX2NvbCwKICAgICAgICAgICAgICAgICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJBcmlkaXR5IEluZGV4IikgKwogIGdndGl0bGUoIkFyaWRpdHkgSW5kZXggKCsywrBDIDIwODAtMjEwMCkiKSArCiAgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MCwgOTApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE4MCwgMTgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lX3ZvaWQoKSArIAogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKQoKYWlfNENfcGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoZGF0YSA9IGFpXzRDX2RmLCBhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gY2F0ZWdvcnkpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9zcGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGFyaWRfY29sLAogICAgICAgICAgICAgICAgICAgIGd1aWRlID0gZ3VpZGVfbGVnZW5kKHJldmVyc2UgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkFyaWRpdHkgSW5kZXgiKSArCiAgIGdndGl0bGUoIkFyaWRpdHkgSW5kZXggKCs0wrBDIDIwODAtMjEwMCkiKSArCiAgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MCwgOTApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE4MCwgMTgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lX3ZvaWQoKSArIAogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKQoKYWlfbGVnZW5kIDwtIGNvd3Bsb3Q6OmdldF9sZWdlbmQoYWlfY3Vycl9wbG90KQoKYWlfcHJvdyA8LSBjb3dwbG90OjpwbG90X2dyaWQoYWlfY3Vycl9wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwgCiAgICAgICAgICAgICAgICAgICBhaV8yQ19wbG90ICsgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIAogICAgICAgICAgICAgICAgICAgYWlfNENfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIAogICAgICAgICAgICAgICAgICAgYWxpZ24gPSAidiIsIG5jb2wgPSAzLCBsYWJlbHMgPSBjKCdnJywgJ2gnLCAnaScpKSAKCmFpX3Bsb3RzIDwtIGNvd3Bsb3Q6OnBsb3RfZ3JpZChhaV9wcm93LCBhaV9sZWdlbmQsIG5jb2wgPSAxLCByZWxfaGVpZ2h0cyA9IGMoMSwgLjEpKQoKY293cGxvdDo6cGxvdF9ncmlkKHBwdF9wbG90cywgcGV0X3Bsb3RzLCBhaV9wbG90cywgbmNvbCA9IDEpCmBgYAoKKipGaWcuIFMxLioqIENsaW1hdGUgZGF0YSB1c2VkIHRvIGNhbGN1bGF0ZSB0aGUgYXJpZGl0eSBpbmRleC4gTWVhbiBwcmVjaXBpdGF0aW9uIChtbSkgdW5kZXIgKCoqYSoqKSB0aGUgY3VycmVudCBzY2VuYXJpbyBmcm9tIDE5ODEtMjAxMCwgKCoqYioqKSBhbiBpbnRlcm1lZGlhdGUgZW1pc3Npb24gc2NlbmFyaW8gb2YgKzLCsEMgKFNoYXJlZCBTb2Npb2Vjb25vbWljIFBhdGh3YXlzIDIgLSA0LjU7IFNTUDItNC41KSwgYW5kICgqKmMqKikgYSBoaWdoIGVtaXNzaW9uIHNjZW5hcmlvIG9mICs0wrBDIChTU1A1LTguNSkgYnkgMjA4MC0yMTAwLiBNZWFuIHBvdGVudGlhbCBldmFwb3RyYW5zcGlyYXRpb24gKG1tKSB1bmRlciAoKipkKiopIHRoZSBjdXJyZW50IHNjZW5hcmlvIGZyb20gMTk4MS0yMDEwLCAoKiplKiopIGFuIGludGVybWVkaWF0ZSBlbWlzc2lvbiBzY2VuYXJpbyBvZiArMsKwQyAoU1NQMi00LjUpLCBhbmQgKCoqZioqKSBhIGhpZ2ggZW1pc3Npb24gc2NlbmFyaW8gb2YgKzTCsEMgKFNTUDUtOC41KSBieSAyMDgwLTIxMDAuIENhbGN1bGF0ZWQgQXJpZGl0eSBJbmRleCBmb3IgKCoqZyoqKSB0aGUgY3VycmVudCBzY2VuYXJpbyBmcm9tIDE5ODEtMjAxMCwgKCoqaCoqKSBhbiBpbnRlcm1lZGlhdGUgZW1pc3Npb24gc2NlbmFyaW8gb2YgKzLCsEMgKFNTUDItNC41KSwgYW5kICgqKmkqKikgYSBoaWdoIGVtaXNzaW9uIHNjZW5hcmlvIG9mICs0wrBDIChTU1A1LTguNSkgYnkgMjA4MC0yMTAwLiAKCiMjIEFJIHJpc2sgey19CgpUbyBleGFtaW5lIHRoZSByZWxhdGlvbnNoaXAgb2Ygc3BlY2llcyByaWNobmVzcyB3aXRoIGFyaWRpdHksIHRoZSBudW1iZXIgb2Ygc3BlY2llcyBwZXIgZ2lyZCBjZWxsIHdhcyBvdmVybGFwcGVkIHdpdGggdGhlIGFyaWRpdHkgcmFzdGVyIGxheWVyLCB3aGVyZSBlYWNoIGdyaWQgd2FzIGFzc2lnbmVkIGFuIEFJIGNhdGVnb3J5LiBUaGUgY2hhbmdlIGluIHNwZWNpZXMgcmljaG5lc3MgYmV0d2VlbiB0aGUgY3VycmVudCBhbmQgcHJvamVjdGVkIChlaXRoZXIgKzIgb3IgKzQgwrBDIHdhcm1pbmcpIEFJIGNhdGVnb3J5IHdhcyBjYWxjdWxhdGVkIGFzIHRoZSBjaGFuZ2UgaW4gQUkgY2F0ZWdvcnkgZ3JpZHMgKHJlc29sdXRpb24gMC41wrAgZm9yIGRlY2ltYWwgZGVncmVlIGNvb3JkaW5hdGVzKSBvY2N1cGllZCBieSBhbnVyYW5zIHJlbGF0aXZlIHRvIHRoZSBmdXR1cmUgcHJvamVjdGlvbi4gQSBkZWNyZWFzZSBpbmRpY2F0ZXMgcmVkdWNlZCBudW1iZXIgb2Ygc3BlY2llcyB3aXRoIHRoZSBhc3NpZ25lZCBBSSBjYXRlZ29yeSBhbmQgdmljZSB2ZXJzYS4KCmBgYHtyIEFJfQojIE1lcmdlIGFyaWRpdHkgaW5kZXgsICs0QyBhbmQgYW1waGliaWFuIHNwZWNpZXMgcmljaG5lc3MKYWlfc3BfZGYgPC0gYWlfZGYgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oYWlfMkNfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JQogIGRwbHlyOjpmdWxsX2pvaW4oYWlfNENfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JQogIGRwbHlyOjpmdWxsX2pvaW4oYW51cmFuX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihhcXVhdGljX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihhcmJvcmVhbF9zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oZm9zc29yaWFsX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihncm91bmRfc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKHNlbWlfYXFfc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKHN0cmVhbV9zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoYXJpZGl0eSA9IGxheWVyLngsCiAgICAgICAgICAgICAgICBhcmlkaXR5XzJDID0gbGF5ZXIueSwKICAgICAgICAgICAgICAgIGFyaWRpdHlfNEMgPSBsYXllciwKICAgICAgICAgICAgICAgIGNhdGVnb3J5ID0gY2F0ZWdvcnkueCwKICAgICAgICAgICAgICAgIGNhdGVnb3J5XzJDID0gY2F0ZWdvcnkueSwKICAgICAgICAgICAgICAgIGNhdGVnb3J5XzRDID0gY2F0ZWdvcnkpICU+JQogIGRyb3BfbmEoY2F0ZWdvcnkpCgojIENhbGN1bGF0ZSBncmlkIGNlbGxzIG9jY3VwaWVkIGZvciBjdXJyZW50IGNsaW1hdGUKYWlfc3Bfc3VtIDwtIGRhdGEuZnJhbWUoYWlfc3BfZGYgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpncm91cF9ieShjYXRlZ29yeSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpzdW1tYXJpc2Uoc3BlY2llc19uICAgPSBsZW5ndGgoc3BlY2llc19uWyFpcy5uYShzcGVjaWVzX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcXVhdGljX24gICA9IGxlbmd0aChhcXVhdGljX25bIWlzLm5hKGFxdWF0aWNfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyYm9yZWFsX24gID0gbGVuZ3RoKGFyYm9yZWFsX25bIWlzLm5hKGFyYm9yZWFsX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3Nzb3JpYWxfbiA9IGxlbmd0aChmb3Nzb3JpYWxfblshaXMubmEoZm9zc29yaWFsX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91bmRfbiAgICA9IGxlbmd0aChncm91bmRfblshaXMubmEoZ3JvdW5kX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW1pX2FxX24gICA9IGxlbmd0aChzZW1pX2FxX25bIWlzLm5hKHNlbWlfYXFfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbV9uICAgID0gbGVuZ3RoKHN0cmVhbV9uWyFpcy5uYShzdHJlYW1fbildKSkpICU+JQogIGRwbHlyOjptdXRhdGUoc2NlbmFyaW8gPSAiQ3VycmVudCIsCiAgICAgICAgICAgICAgICBhbGxfZnJlcSAgICAgICA9IHNwZWNpZXNfbiAvIHN1bShzcGVjaWVzX24pICogMTAwLAogICAgICAgICAgICAgICAgYXF1YXRpY19mcmVxICAgPSBhcXVhdGljX24gLyBzdW0oYXF1YXRpY19uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGFyYm9yZWFsX2ZyZXEgID0gYXJib3JlYWxfbiAvIHN1bShhcmJvcmVhbF9uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9mcmVxID0gZm9zc29yaWFsX24gLyBzdW0oZm9zc29yaWFsX24pICogMTAwLAogICAgICAgICAgICAgICAgZ3JvdW5kX2ZyZXEgICAgPSBncm91bmRfbiAvIHN1bShncm91bmRfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBzZW1pX2FxX2ZyZXEgICA9IHNlbWlfYXFfbiAvIHN1bShzZW1pX2FxX24pICogMTAwLAogICAgICAgICAgICAgICAgc3RyZWFtX2ZyZXEgICAgPSBzdHJlYW1fbiAvIHN1bShzdHJlYW1fbikgKiAxMDApCgojIENhbGN1bGF0ZSBncmlkIGNlbGxzIG9jY3VwaWVkIGZvciBmdXR1cmUgY2xpbWF0ZQphaV8yQ19zcF9zdW0gPC0gZGF0YS5mcmFtZShhaV9zcF9kZiAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6Omdyb3VwX2J5KGNhdGVnb3J5XzJDKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnN1bW1hcmlzZShzcGVjaWVzX24gICA9IGxlbmd0aChzcGVjaWVzX25bIWlzLm5hKHNwZWNpZXNfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFxdWF0aWNfbiAgID0gbGVuZ3RoKGFxdWF0aWNfblshaXMubmEoYXF1YXRpY19uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJib3JlYWxfbiAgPSBsZW5ndGgoYXJib3JlYWxfblshaXMubmEoYXJib3JlYWxfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9uID0gbGVuZ3RoKGZvc3NvcmlhbF9uWyFpcy5uYShmb3Nzb3JpYWxfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VuZF9uICAgID0gbGVuZ3RoKGdyb3VuZF9uWyFpcy5uYShncm91bmRfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbWlfYXFfbiAgID0gbGVuZ3RoKHNlbWlfYXFfblshaXMubmEoc2VtaV9hcV9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtX24gICAgPSBsZW5ndGgoc3RyZWFtX25bIWlzLm5hKHN0cmVhbV9uKV0pKSkgJT4lCiAgZHBseXI6Om11dGF0ZShzY2VuYXJpbyA9ICJTU1AyNDUiLAogICAgICAgICAgICAgICAgYWxsX2ZyZXEgICAgICAgPSBzcGVjaWVzX24gLyBzdW0oc3BlY2llc19uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGFxdWF0aWNfZnJlcSAgID0gYXF1YXRpY19uIC8gc3VtKGFxdWF0aWNfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBhcmJvcmVhbF9mcmVxICA9IGFyYm9yZWFsX24gLyBzdW0oYXJib3JlYWxfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBmb3Nzb3JpYWxfZnJlcSA9IGZvc3NvcmlhbF9uIC8gc3VtKGZvc3NvcmlhbF9uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGdyb3VuZF9mcmVxICAgID0gZ3JvdW5kX24gLyBzdW0oZ3JvdW5kX24pICogMTAwLAogICAgICAgICAgICAgICAgc2VtaV9hcV9mcmVxICAgPSBzZW1pX2FxX24gLyBzdW0oc2VtaV9hcV9uKSAqIDEwMCwKICAgICAgICAgICAgICAgIHN0cmVhbV9mcmVxICAgID0gc3RyZWFtX24gLyBzdW0oc3RyZWFtX24pICogMTAwKSAlPiUgCiAgZHBseXI6OnJlbmFtZShjYXRlZ29yeSA9IGNhdGVnb3J5XzJDKSAKCmFpXzRDX3NwX3N1bSA8LSBkYXRhLmZyYW1lKGFpX3NwX2RmICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6Z3JvdXBfYnkoY2F0ZWdvcnlfNEMpICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c3VtbWFyaXNlKHNwZWNpZXNfbiAgID0gbGVuZ3RoKHNwZWNpZXNfblshaXMubmEoc3BlY2llc19uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXF1YXRpY19uICAgPSBsZW5ndGgoYXF1YXRpY19uWyFpcy5uYShhcXVhdGljX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmJvcmVhbF9uICA9IGxlbmd0aChhcmJvcmVhbF9uWyFpcy5uYShhcmJvcmVhbF9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9zc29yaWFsX24gPSBsZW5ndGgoZm9zc29yaWFsX25bIWlzLm5hKGZvc3NvcmlhbF9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdW5kX24gICAgPSBsZW5ndGgoZ3JvdW5kX25bIWlzLm5hKGdyb3VuZF9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VtaV9hcV9uICAgPSBsZW5ndGgoc2VtaV9hcV9uWyFpcy5uYShzZW1pX2FxX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1fbiAgICA9IGxlbmd0aChzdHJlYW1fblshaXMubmEoc3RyZWFtX24pXSkpKSAlPiUKICBkcGx5cjo6bXV0YXRlKHNjZW5hcmlvID0gIlNTUDU4NSIsCiAgICAgICAgICAgICAgICBhbGxfZnJlcSAgICAgICA9IHNwZWNpZXNfbiAvIHN1bShzcGVjaWVzX24pICogMTAwLAogICAgICAgICAgICAgICAgYXF1YXRpY19mcmVxICAgPSBhcXVhdGljX24gLyBzdW0oYXF1YXRpY19uKSAqIDEwMCwKICAgICAgICAgICAgICAgIHJib3JlYWxfZnJlcSAgID0gYXJib3JlYWxfbiAvIHN1bShhcmJvcmVhbF9uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9mcmVxID0gZm9zc29yaWFsX24gLyBzdW0oZm9zc29yaWFsX24pICogMTAwLAogICAgICAgICAgICAgICAgZ3JvdW5kX2ZyZXEgICAgPSBncm91bmRfbiAvIHN1bShncm91bmRfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBzZW1pX2FxX2ZyZXEgICA9IHNlbWlfYXFfbiAvIHN1bShzZW1pX2FxX24pICogMTAwLAogICAgICAgICAgICAgICAgc3RyZWFtX2ZyZXEgICAgPSBzdHJlYW1fbiAvIHN1bShzdHJlYW1fbikgKiAxMDApICU+JSAKICBkcGx5cjo6cmVuYW1lKGNhdGVnb3J5ID0gY2F0ZWdvcnlfNEMpCmBgYAoKIyMgUERTSSByaXNrIHstfQoKV2l0aCBhIG1vbnRobHkgcHJlZGljdGlvbiBvZiBQRFNJIGZyb20gMTk1MCB0byAyMTAwIGdsb2JhbGx5IGF2YWlsYWJsZSBmcm9tIEBaaGFvMjAyMiwgd2UgY2F0ZWdvcmlzZWQgZnV0dXJlIGRyb3VnaHQgcmlzayBpbiB0aHJlZSB3YXlzOiAxKSBhbiBpbmNyZWFzZSBpbiBkcm91Z2h0IGludGVuc2l0eSAoZGVjcmVhc2UgaW4gUERTSTsgKipGaWcuIFMyYeKAk2MqKiksIDIpIGFuIGluY3JlYXNlIGluIGRyb3VnaHQgZnJlcXVlbmN5IChtb250aGx5IFBEU0kgY291bnRzIGJlbG93IC0yIHBlciB5ZWFyOyAqKkZpZy4gUzJk4oCTZioqKSwgYW5kIDMpIGFuIGluY3JlYXNlIGluIGRyb3VnaHQgZHVyYXRpb24gKG51bWJlciBvZiBjb25zZWN1dGl2ZSBtb250aHMgd2l0aCBQRFNJIHZhbHVlcyBiZWxvdyAtMjsgKipGaWcuIFMyZ+KAk2kqKikuIENoYW5nZSBpbiBkcm91Z2h0IGludGVuc2l0eSAozpRQRFNJfltpbnRlbnNpdHldfiksIGZyZXF1ZW5jeSAozpRQRFNJfltmcmVxdWVuY3ldfiksICBhbmQgZHVyYXRpb24gKM6UUERTSX5bZHVyYXRpb25dfikgdW5kZXIgYSArMiBvciArNCDCsEMgd2FybWluZyBzY2VuYXJpbyAoMjA4MOKAkzIxMDApIHdhcyBjYWxjdWxhdGVkIHJlbGF0aXZlIHRvIHRoZSAxOTcw4oCTMjAwMCBtb250aGx5IGNsaW1hdG9sb2d5IHBlciBnaXJkIGNlbGwgKM6UUERTSSA9IFBEU0l+W2Z1dHVyZV1+IOKAkyBQRFNJfltjdXJyZW50XX4pLiBOb3RlLCB0aGUgdGVtcG9yYWwgcmVzb2x1dGlvbiB3YXMgbGltaXRlZCB0byBtb250aGx5IHZhcmlhdGlvbiBhcyB0aGUgUERTSSB3YXMgZGV2ZWxvcGVkIHRvIG1vbml0b3IgbG9uZy10ZXJtIG1ldGVvcm9sb2dpY2FsIGRyb3VnaHQuCgpgYGB7ciBQRFNJIGludH0KIyBDaGFuZ2UgaW4gUERTSSBpbnRlbnNpdHkgClBEU0lfc3BfZGYgPC0gYW51cmFuX3NyX2RmICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKFBEU0lfMkNfZGlmZl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oUERTSV80Q19kaWZmX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihhcXVhdGljX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihhcmJvcmVhbF9zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oZm9zc29yaWFsX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihncm91bmRfc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKHNlbWlfYXFfc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKHN0cmVhbV9zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoUERTSV8yQyA9IGxheWVyLngsCiAgICAgICAgICAgICAgICBQRFNJXzRDID0gbGF5ZXIueSkgJT4lCiAgZHJvcF9uYShjaGFuZ2VfMkMpICU+JQogIGZpbHRlcihzcGVjaWVzX24gIT0gIk5BIikKCiMgQ2FsY3VsYXRlIGdyaWQgY2VsbHMgb2NjdXBpZWQgZm9yIGN1cnJlbnQgY2xpbWF0ZQpQRFNJX3NwXzJDIDwtIGRhdGEuZnJhbWUoUERTSV9zcF9kZiAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpncm91cF9ieShjaGFuZ2VfMkMpICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnN1bW1hcmlzZShzcGVjaWVzX24gICA9IGxlbmd0aChzcGVjaWVzX25bIWlzLm5hKHNwZWNpZXNfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcXVhdGljX24gICA9IGxlbmd0aChhcXVhdGljX25bIWlzLm5hKGFxdWF0aWNfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmJvcmVhbF9uICA9IGxlbmd0aChhcmJvcmVhbF9uWyFpcy5uYShhcmJvcmVhbF9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9uID0gbGVuZ3RoKGZvc3NvcmlhbF9uWyFpcy5uYShmb3Nzb3JpYWxfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91bmRfbiAgICA9IGxlbmd0aChncm91bmRfblshaXMubmEoZ3JvdW5kX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VtaV9hcV9uICAgPSBsZW5ndGgoc2VtaV9hcV9uWyFpcy5uYShzZW1pX2FxX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtX24gICAgPSBsZW5ndGgoc3RyZWFtX25bIWlzLm5hKHN0cmVhbV9uKV0pKSkgJT4lCiAgZHBseXI6Om11dGF0ZShhbGxfZnJlcSAgICAgICA9IHNwZWNpZXNfbiAvIHN1bShzcGVjaWVzX24pICogMTAwLAogICAgICAgICAgICAgICAgYXF1YXRpY19mcmVxICAgPSBhcXVhdGljX24gLyBzdW0oYXF1YXRpY19uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGFyYm9yZWFsX2ZyZXEgID0gYXJib3JlYWxfbiAvIHN1bShhcmJvcmVhbF9uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9mcmVxID0gZm9zc29yaWFsX24gLyBzdW0oZm9zc29yaWFsX24pICogMTAwLAogICAgICAgICAgICAgICAgZ3JvdW5kX2ZyZXEgICAgPSBncm91bmRfbiAvIHN1bShncm91bmRfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBzZW1pX2FxX2ZyZXEgICA9IHNlbWlfYXFfbiAvIHN1bShzZW1pX2FxX24pICogMTAwLAogICAgICAgICAgICAgICAgc3RyZWFtX2ZyZXEgICAgPSBzdHJlYW1fbiAvIHN1bShzdHJlYW1fbikgKiAxMDApCgpQRFNJX3NwXzRDIDwtIGRhdGEuZnJhbWUoUERTSV9zcF9kZiAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpncm91cF9ieShjaGFuZ2VfNEMpICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnN1bW1hcmlzZShzcGVjaWVzX24gICA9IGxlbmd0aChzcGVjaWVzX25bIWlzLm5hKHNwZWNpZXNfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcXVhdGljX24gICA9IGxlbmd0aChhcXVhdGljX25bIWlzLm5hKGFxdWF0aWNfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmJvcmVhbF9uICA9IGxlbmd0aChhcmJvcmVhbF9uWyFpcy5uYShhcmJvcmVhbF9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9uID0gbGVuZ3RoKGZvc3NvcmlhbF9uWyFpcy5uYShmb3Nzb3JpYWxfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91bmRfbiAgICA9IGxlbmd0aChncm91bmRfblshaXMubmEoZ3JvdW5kX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VtaV9hcV9uICAgPSBsZW5ndGgoc2VtaV9hcV9uWyFpcy5uYShzZW1pX2FxX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtX24gICAgPSBsZW5ndGgoc3RyZWFtX25bIWlzLm5hKHN0cmVhbV9uKV0pKSkgJT4lCiAgZHBseXI6Om11dGF0ZShhbGxfZnJlcSAgICAgICA9IHNwZWNpZXNfbiAvIHN1bShzcGVjaWVzX24pICogMTAwLAogICAgICAgICAgICAgICAgYXF1YXRpY19mcmVxICAgPSBhcXVhdGljX24gLyBzdW0oYXF1YXRpY19uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGFyYm9yZWFsX2ZyZXEgID0gYXJib3JlYWxfbiAvIHN1bShhcmJvcmVhbF9uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9mcmVxID0gZm9zc29yaWFsX24gLyBzdW0oZm9zc29yaWFsX24pICogMTAwLAogICAgICAgICAgICAgICAgZ3JvdW5kX2ZyZXEgICAgPSBncm91bmRfbiAvIHN1bShncm91bmRfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBzZW1pX2FxX2ZyZXEgICA9IHNlbWlfYXFfbiAvIHN1bShzZW1pX2FxX24pICogMTAwLAogICAgICAgICAgICAgICAgc3RyZWFtX2ZyZXEgICAgPSBzdHJlYW1fbiAvIHN1bShzdHJlYW1fbikgKiAxMDApCmBgYAoKYGBge3IgUERTSSBmcmVxfQojIENhbGN1bGF0ZSBmcmVxdWVuY3kgb2YgbW9kZXJhdGUgdG8gZXh0cmVtZSBkcm91Z2h0ICg8LTIgUERTSSkgcGVyIHllYXIuCgojIFRlbXBvcmFsIGNoYW5nZSBpbiBQRFNJIGludGVuc2l0eQpQRFNJXzJDX3RpbWVfZGYgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMoUERTSV9zc3AyNDVfcmFzdCkpClBEU0lfNENfdGltZV9kZiA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhQRFNJX3NzcDU4NV9yYXN0KSkKCiMgQ29udmVydCB3aWRlIHRvIGxvbmcKZnJlcV8yQ19kZiA8LSBQRFNJXzJDX3RpbWVfZGYgJT4lCiAgdGlkeXI6OnBpdm90X2xvbmdlcighYygieCIsInkiKSwgbmFtZXNfdG8gPSAiZGF0ZXMiLCB2YWx1ZXNfdG8gPSAiUERTSSIpICU+JQogIGRhdGEuZnJhbWUoKSAlPiUKICB0aWR5cjo6c2VwYXJhdGUoZGF0ZXMsIGMoInllYXIiLCAnbW9udGhzJykpICU+JQogIGRwbHlyOjptdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoc3Vic3RyaW5nKHllYXIsIDIpKSkgJT4lCiAgZHBseXI6OmZpbHRlcih5ZWFyID49IDE5NTAgJiB5ZWFyICE9IDIxMDApCgpmcmVxXzRDX2RmIDwtIFBEU0lfNENfdGltZV9kZiAlPiUKICB0aWR5cjo6cGl2b3RfbG9uZ2VyKCFjKCJ4IiwieSIpLCBuYW1lc190byA9ICJkYXRlcyIsIHZhbHVlc190byA9ICJQRFNJIikgJT4lCiAgZGF0YS5mcmFtZSgpICU+JQogIHRpZHlyOjpzZXBhcmF0ZShkYXRlcywgYygieWVhciIsICdtb250aHMnKSkgJT4lCiAgZHBseXI6Om11dGF0ZSh5ZWFyID0gYXMubnVtZXJpYyhzdWJzdHJpbmcoeWVhciwgMikpKSAlPiUKICBkcGx5cjo6ZmlsdGVyKHllYXIgPj0gMTk1MCAmIHllYXIgIT0gMjEwMCkKCiMgU3VtbWFyaXNlIGF2ZXJhZ2UgbW9udGhseSBjb3VudHMgPC0yIFBEU0kgZnJvbSAxOTcwIHRvIDE5OTkgb3IgMjA4MCB0byAyMTAwCmZyZXFfbWVhbl9kZiA8LSBmcmVxXzJDX2RmICU+JQogIGRwbHlyOjpmaWx0ZXIoeWVhciA+PSAxOTcwICYgeWVhciA8PSAxOTk5KSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoeCwgeSwgeWVhcikgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShjb3VudCA9IHN1bShQRFNJIDwgLTIpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoeCwgeSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShtZWFuX2N1cnIgPSBtZWFuKGNvdW50KSkKICAKZnJlcV8yQ19kaWZmX2RmIDwtIGZyZXFfMkNfZGYgJT4lCiAgZHBseXI6OmZpbHRlcih5ZWFyID49IDIwODAgJiB5ZWFyICE9IDIxMDApICU+JQogIGRwbHlyOjpncm91cF9ieSh4LCB5LCB5ZWFyKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGNvdW50ID0gc3VtKFBEU0kgPCAtMikpICU+JSAKICBkcGx5cjo6Z3JvdXBfYnkoeCwgeSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShtZWFuXzJDID0gbWVhbihjb3VudCkpICU+JSAKICBkcGx5cjo6aW5uZXJfam9pbihmcmVxX21lYW5fZGYsIGJ5ID0gYygieCIgPSAieCIsICJ5IiA9ICJ5IikpICU+JQogIGRwbHlyOjptdXRhdGUoZGlmZl8yQyA9IG1lYW5fMkMgLSBtZWFuX2N1cnIpCgpmcmVxXzRDX2RpZmZfZGYgPC0gZnJlcV80Q19kZiAlPiUKICBkcGx5cjo6ZmlsdGVyKHllYXIgPj0gMjA4MCAmIHllYXIgIT0gMjEwMCkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KHgsIHksIHllYXIpICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoY291bnQgPSBzdW0oUERTSSA8IC0yKSkgJT4lIAogIGRwbHlyOjpncm91cF9ieSh4LCB5KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKG1lYW5fNEMgPSBtZWFuKGNvdW50KSkgJT4lIAogIGRwbHlyOjppbm5lcl9qb2luKGZyZXFfMkNfZGlmZl9kZiwgYnkgPSBjKCJ4IiA9ICJ4IiwgInkiID0gInkiKSkgJT4lCiAgZHBseXI6Om11dGF0ZShkaWZmXzRDID0gbWVhbl80QyAtIG1lYW5fY3VycikKYGBgCgpgYGB7ciBQRFNJIGR1cn0KIyBDYWxjdWxhdGUgZHVyYXRpb24gb2YgbW9kZXJhdGUgdG8gZXh0cmVtZSBkcm91Z2h0ICg8LTIgUERTSSkgZnJvbSAxOTcwIHRvIDE5OTkKZHVyX2N1cnJfZGYgPC0gZnJlcV8yQ19kZiAlPiUKICBkcGx5cjo6bXV0YXRlKGJpbiA9IGlmZWxzZShQRFNJIDwgLTIsIDEsIDApKSAlPiUKICBkcGx5cjo6ZmlsdGVyKHllYXIgPj0gMTk3MCAmIHllYXIgPD0gMTk5OSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KHgsIHkpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKG1lYW5fY3VyciA9IG1lYW4ocmxlKGJpbikkbGVuZ3Roc1tybGUoYmluKSR2YWx1ZXM9PTFdKSkgJT4lCiAgcmVwbGFjZShpcy5uYSguKSwgMCkKCiMgQ2FsY3VsYXRlIGR1cmF0aW9uIG9mIG1vZGVyYXRlIHRvIGV4dHJlbWUgZHJvdWdodCAoPC0yIFBEU0kpIGZyb20gMjA4MCB0byAyMTAwCmR1cl8yQ19kZiA8LSBmcmVxXzJDX2RmICU+JQogIGRwbHlyOjptdXRhdGUoYmluID0gaWZlbHNlKFBEU0kgPCAtMiwgMSwgMCkpICU+JSAKICBkcGx5cjo6ZmlsdGVyKHllYXIgPj0gMjA4MCAmIHllYXIgIT0gMjEwMCkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KHgsIHkpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKG1lYW5fMkMgPSBtZWFuKHJsZShiaW4pJGxlbmd0aHNbcmxlKGJpbikkdmFsdWVzPT0xXSkpICU+JQogIHJlcGxhY2UoaXMubmEoLiksIDApICU+JQogIGRwbHlyOjppbm5lcl9qb2luKGR1cl9jdXJyX2RmLCBieSA9IGMoIngiID0gIngiLCAieSIgPSAieSIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRpZmZfMkMgPSBtZWFuXzJDIC0gbWVhbl9jdXJyKQoKZHVyXzRDX2RmIDwtIGZyZXFfNENfZGYgJT4lIAogIGRwbHlyOjptdXRhdGUoYmluID0gaWZlbHNlKFBEU0kgPCAtMiwgMSwgMCkpICU+JQogIGRwbHlyOjpncm91cF9ieSh4LCB5KSAlPiUgCiAgZHBseXI6OmZpbHRlcih5ZWFyID49IDIwODAgJiB5ZWFyICE9IDIxMDApICU+JQogIGRwbHlyOjpzdW1tYXJpc2UobWVhbl80QyA9IG1lYW4ocmxlKGJpbikkbGVuZ3Roc1tybGUoYmluKSR2YWx1ZXM9PTFdKSkgJT4lCiAgcmVwbGFjZShpcy5uYSguKSwgMCkgJT4lCiAgZHBseXI6OmlubmVyX2pvaW4oZHVyXzJDX2RmLCBieSA9IGMoIngiID0gIngiLCAieSIgPSAieSIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRpZmZfNEMgPSBtZWFuXzRDIC0gbWVhbl9jdXJyKQpgYGAKClRoZSBzaW11bHRhbmVvdXMgcmlzayBvZiBpbmNyZWFzaW5nIGRyb3VnaHQgaW50ZW5zaXR5LCBmcmVxdWVuY3ksIGFuZCBkdXJhdGlvbiB3aXRoaW4gYSBncmlkIGNlbGwgdGhhdCBhcmUgb2NjdXBpZWQgYnkgYW51cmFucyAoc3BlY2llcyBhc3NlbWJsYWdlcykgd2FzIGNhbGN1bGF0ZWQgYnkgY29udmVydGluZyBlYWNoIHJpc2sgY2F0ZWdvcnkgYXMgYmluYXJ5LiBHcmlkIGNlbGxzIHdpdGggYSDOlFBEU0l+W2ludGVuc2l0eV1+IGJlbG93IC0yIChpbmRpY2F0aW5nIGluY3JlYXNlZCBkcm91Z2h0IGludGVuc2l0eSByZWxhdGl2ZSB0byBjdXJyZW50IHNjZW5hcmlvKSB3ZXJlIGFzc2lnbmVkIGEg4oCYMeKAmSBiaW5hcnkuIEJvdGggzpRQRFNJfltmcmVxdWVuY3ldfiBhbmQgzpRQRFNJfltkdXJhdGlvbl1+IHdlcmUgYXNzaWduZWQgYSBiaW5hcnkgb2Yg4oCYMeKAmSBpZiB0aGUgZ3JpZCBjZWxsIGhhcyBhIHZhbHVlIG9mIDEgbW9udGggb3IgaGlnaGVyIChpbmRpY2F0aW5nIGluY3JlYXNlIGluIGZyZXF1ZW5jeSBvciBkdXJhdGlvbiByZWxhdGl2ZSB0byBjdXJyZW50IHNjZW5hcmlvKS4gVGhlIG51bWJlciBvZiBvdmVybGFwcGluZyBiaW5hcmllcyB3ZXJlIHN1bW1lZCB1cCBwZXIgZ3JpZCBjZWxsLiBUaGVyZWZvcmUsIGEgcmlzayBmYWN0b3Igb2YgMiBpbmRpY2F0ZSBzcGVjaWVzIGFzc2VtYmxhZ2VzIGluIHRoZSBncmlkIGNlbGwgYXJlIGF0IGluY3JlYXNpbmcgcmlzayBvZiB0d28gZHJvdWdodCBldmVudHMuIFdlIGVzdGltYXRlZCB3aGljaCBzcGVjaWVzIGFzc2VtYmxhZ2VzIHdlcmUgYXQgcmlzayBvZiBleHBlcmllbmNpbmcgZHJvdWdodCBldmVudHMgdXNpbmcgYW4gYXJiaXRyYXJ5IHJpc2sgZmFjdG9yIHNjYWxlIChzcGVjaWVzIHJpY2huZXNzIMOXIGRyb3VnaHQgcmlzayksIHdoZXJlIGdyaWQgY2VsbHMgd2l0aCBoaWdoIGRyb3VnaHQgcmlzayBhbmQgaGlnaCBzcGVjaWVzIHJpY2huZXNzIGhhdmUgaGlnaGVyIOKAnCphc3NlbWJsYWdlLWxldmVsIHJpc2sq4oCdIHRoYW4gZ3JpZCBjZWxscyB3aXRoIGhpZ2ggZHJvdWdodCByaXNrIGFuZCBsb3cgc3BlY2llcyByaWNobmVzcyAobG93IGFzc2VtYmxhZ2UtbGV2ZWwgcmlzaykuCgpgYGB7ciBQRFNJIGNvbWJ9CiMgSW50ZW5zaXR5Cm5hbWVzKFBEU0lfMkNfZGlmZl9yYXN0KSA8LSAiZGVsdGFfaW50XzJDIgpuYW1lcyhQRFNJXzRDX2RpZmZfcmFzdCkgPC0gImRlbHRhX2ludF80QyIKCiMgRnJlcXVlbmN5CmZyZXFfZGlmZl9yYXN0IDwtIHJhc3RlckZyb21YWVooZnJlcV80Q19kaWZmX2RmKSAjIGNvbnZlcnQgdG8gcmFzdGVyCmNycyhmcmVxX2RpZmZfcmFzdCkgPC0gIitwcm9qPWxvbmdsYXQgK2RhdHVtPVdHUzg0ICtub19kZWZzICtlbGxwcz1XR1M4NCArdG93Z3M4ND0wLDAsMCIKZnJlcV9kaWZmX3Jhc3QgPC0gcHJvamVjdFJhc3RlcihmcmVxX2RpZmZfcmFzdCwgYW51cmFuX3NyKSAjIG1hdGNoIGFudXJhbiBleHRlbnQKZnJlcV9kaWZmX2RmICAgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMoZnJlcV9kaWZmX3Jhc3QpKQoKUERTSV9mcmVxX2RpZmYgPC0gc3Vic2V0KGZyZXFfZGlmZl9yYXN0LCA0OjUpCm5hbWVzKFBEU0lfZnJlcV9kaWZmKSA8LSBjKCJkZWx0YV9mcmVxXzJDIiwgImRlbHRhX2ZyZXFfNEMiKQoKIyBEdXJhdGlvbgpkdXJfZGlmZl9yYXN0IDwtIHJhc3Rlcjo6cmFzdGVyRnJvbVhZWihkdXJfNENfZGYpICMgY29udmVydCB0byByYXN0ZXIKY3JzKGR1cl9kaWZmX3Jhc3QpIDwtICIrcHJvaj1sb25nbGF0ICtkYXR1bT1XR1M4NCArbm9fZGVmcyArZWxscHM9V0dTODQgK3Rvd2dzODQ9MCwwLDAiCmR1cl9kaWZmX3Jhc3QgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKGR1cl9kaWZmX3Jhc3QsIGFudXJhbl9zcikgIyBtYXRjaCBhbnVyYW4gZXh0ZW50CmR1cl9kaWZmX2RmIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKGR1cl9kaWZmX3Jhc3QpKQoKUERTSV9kdXJfZGlmZiAgPC0gc3Vic2V0KGR1cl9kaWZmX3Jhc3QsIDQ6NSkKbmFtZXMoUERTSV9kdXJfZGlmZikgPC0gYygiZGVsdGFfZHVyXzJDIiwgImRlbHRhX2R1cl80QyIpCgojIENvbWJpbmUgcmVsYXRpdmUgUERTSSBtZXRyaWNzClBEU0lfcmlza19jb21iX3Jhc3QgPC0gcmFzdGVyOjpzdGFjayhQRFNJXzJDX2RpZmZfcmFzdCwgUERTSV80Q19kaWZmX3Jhc3QsIFBEU0lfZnJlcV9kaWZmLCBQRFNJX2R1cl9kaWZmLCByZXNhbXBsZShhbnVyYW5fc3IsIFBEU0lfNENfZGlmZl9yYXN0KSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKUERTSV9yaXNrX2NvbWJfZGYgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMoUERTSV9yaXNrX2NvbWJfcmFzdCkpICU+JQogIGRwbHlyOjpyZW5hbWUoInNwX24iID0gbGF5ZXIpICU+JQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKHNwX24pKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRlbHRhX2ludF8yQ19iaW4gPSBpZmVsc2UoZGVsdGFfaW50XzJDIDwgLTEsIDEsIDApLCAjIGRlbHRhX1BEU0kgPCAtMQogICAgICAgICBkZWx0YV9pbnRfNENfYmluID0gaWZlbHNlKGRlbHRhX2ludF80QyA8IC0xLCAxLCAwKSwgIyBkZWx0YV9QRFNJIDwgLTEKICAgICAgICAgZGVsdGFfZnJlcV8yQ19iaW4gPSBpZmVsc2UoZGVsdGFfZnJlcV8yQyA+MSwgMSwgMCksICMgbW9udGggPiAxCiAgICAgICAgIGRlbHRhX2ZyZXFfNENfYmluID0gaWZlbHNlKGRlbHRhX2ZyZXFfNEMgPjEsIDEsIDApLCAjIG1vbnRoID4gMQogICAgICAgICBkZWx0YV9kdXJfMkNfYmluID0gaWZlbHNlKGRlbHRhX2R1cl8yQyA+MSwgMSwgMCksICMgbW9udGggPiAxCiAgICAgICAgIGRlbHRhX2R1cl80Q19iaW4gPSBpZmVsc2UoZGVsdGFfZHVyXzRDID4xLCAxLCAwKSkgJT4lICMgbW9udGggPiAxIAogIGRwbHlyOjpyb3d3aXNlKCkgJT4lCiAgZHBseXI6Om11dGF0ZShjb3VudF8yQyA9IHN1bShkZWx0YV9pbnRfMkNfYmluLCBkZWx0YV9mcmVxXzJDX2JpbiwgZGVsdGFfZHVyXzJDX2JpbiwgbmEucm0gPSBUKSwKICAgICAgICAgCiAgICAgICAgIGNvdW50XzRDID0gc3VtKGRlbHRhX2ludF80Q19iaW4sIGRlbHRhX2ZyZXFfNENfYmluLCBkZWx0YV9kdXJfNENfYmluLCBuYS5ybSA9IFQpLAogICAgICAgICByaXNrXzJDICA9IHNwX24gKiBjb3VudF8yQywKICAgICAgICAgcmlza180QyAgPSBzcF9uICogY291bnRfNEMsCiAgICAgICAgIGNvdW50XzJDID0gZmFjdG9yKGNvdW50XzJDLCBsZXZlbHMgPSBjKCIzIiwgIjIiLCAiMSIpKSwKICAgICAgICAgY291bnRfNEMgPSBmYWN0b3IoY291bnRfNEMsIGxldmVscyA9IGMoIjMiLCAiMiIsICIxIikpCiAgICAgICAgICkKYGBgCgpgYGB7ciBGaWcgUzIsIG1lc3NhZ2U9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD02LjUsIGZpZy53aWR0aD05fQojIENvbWJpbmUgYWJzb2x1dGUgUERTSSBtZXRyaWNzClBEU0lfYWJfcmFzdCA8LSByYXN0ZXI6OnN0YWNrKFBEU0lfY3VyX21lYW5fcmFzdCwgUERTSV8yQ19tZWFuX3Jhc3QsIFBEU0lfNENfbWVhbl9yYXN0LCBmcmVxX2RpZmZfcmFzdCwgZHVyX2RpZmZfcmFzdCwgcmVzYW1wbGUoYW51cmFuX3NyLCBQRFNJXzRDX21lYW5fcmFzdCkpIApQRFNJX2FiX3Jhc3RfY3JvcCA8LSByYXN0ZXI6Om1hc2soY3JvcChQRFNJX2FiX3Jhc3QsIGV4dGVudCh3b3JsZCkpLCB3b3JsZCkgIyBjcm9wIAoKUERTSV9hYl9kZiA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhQRFNJX2FiX3Jhc3RfY3JvcCkpICU+JQogIGRwbHlyOjpyZW5hbWUoUERTSV9jdXIgPSAibGF5ZXIuMSIsCiAgICAgICAgICAgICAgICBQRFNJXzJDICA9ICJsYXllci4yIiwKICAgICAgICAgICAgICAgIFBEU0lfNEMgID0gImxheWVyLjMiLAogICAgICAgICAgICAgICAgZnJlcV9jdXIgPSAibWVhbl9jdXJyLjEiLAogICAgICAgICAgICAgICAgZnJlcV8yQyAgPSAibWVhbl8yQy4xIiwKICAgICAgICAgICAgICAgIGZyZXFfNEMgID0gIm1lYW5fNEMuMSIsCiAgICAgICAgICAgICAgICBkdXJfY3VyICA9ICJtZWFuX2N1cnIuMiIsCiAgICAgICAgICAgICAgICBkdXJfMkMgICA9ICJtZWFuXzJDLjIiLAogICAgICAgICAgICAgICAgZHVyXzRDICAgPSAibWVhbl80Qy4yIiwKICAgICAgICAgICAgICAgIHNwX24gICAgID0gImxheWVyLjQiKSAlPiUKICBmaWx0ZXIoc3BfbiAhPSAiTkEiKQoKY29sb3Vyc19QRFNJIDwtIFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCg5LCAiUmRCdSIpCgojIEludGVuc2l0eQpQRFNJX2N1cl9wbG90IDwtIFBEU0lfYWJfZGYgJT4lCiAgZHBseXI6Om11dGF0ZShQRFNJX2N1cl9jYXQgPSBjYXNlX3doZW4oCiAgICBQRFNJX2N1ciA+PSAyICYgUERTSV9jdXIgPCAzIH4gJzInLCAgCiAgICBQRFNJX2N1ciA+PSAxICYgUERTSV9jdXIgPCAyIH4gJzEnLCAgCiAgICBQRFNJX2N1ciA+PSAtMSAmIFBEU0lfY3VyIDwgMSB+ICcwJwogICkpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBEU0lfY3VyX2NhdCA9IGZhY3RvcihQRFNJX2N1cl9jYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnMCcsICcxJywgJzInKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkpICU+JQogIGZpbHRlcihQRFNJX2N1cl9jYXQgIT0gIk5BIikgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBQRFNJX2N1cl9jYXQpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9zcGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNGN0Y3RjciLCAiI0QxRTVGMCIgLCIjOTJDNURFIikpICsKICB0aGVtZV92b2lkKCkgKyB5bGFiKE5VTEwpICsgeGxhYihOVUxMKSArCiAgZ2d0aXRsZSgiTWVhbiBQRFNJIGludGVuc2l0eSAoMTk3MOKAkzIwMDApIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MCwgOTApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE4MCwgMTgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAjIGZpeGVkIHJhdGlvCgpQRFNJXzJDX3Bsb3QgPC0gUERTSV9hYl9kZiAlPiUKICBkcGx5cjo6bXV0YXRlKFBEU0lfMkNfY2F0ID0gY2FzZV93aGVuKAogICAgUERTSV8yQyA+PSA0IH4gIjQiLCAKICAgIFBEU0lfMkMgPj0gMyAmIFBEU0lfMkMgPCA0IH4gJzMnLAogICAgUERTSV8yQyA+PSAyICYgUERTSV8yQyA8IDMgfiAnMicsICAKICAgIFBEU0lfMkMgPj0gMSAmIFBEU0lfMkMgPCAyIH4gJzEnLCAgCiAgICBQRFNJXzJDID49IC0xICYgUERTSV8yQyA8IDEgfiAnMCcsCiAgICBQRFNJXzJDID49IC0yICYgUERTSV8yQyA8IC0xIH4gJy0xJywKICAgIFBEU0lfMkMgPj0gLTMgJiBQRFNJXzJDIDwgLTIgfiAnLTInLAogICAgUERTSV8yQyA+PSAtNCAmIFBEU0lfMkMgPCAtMyB+ICctMycsICAgCiAgICBQRFNJXzJDIDwgLTQgfiAnLTQnIAogICkpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBEU0lfMkNfY2F0ID0gZmFjdG9yKFBEU0lfMkNfY2F0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJy00JywgJy0zJywgJy0yJywgJy0xJywgJzAnLCAnMScsICcyJywgJzMnLCAnNCcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgZmlsdGVyKFBEU0lfMkNfY2F0ICE9ICJOQSIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gUERTSV8yQ19jYXQpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9zcGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG91cnNfUERTSSkgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICBnZ3RpdGxlKCJNZWFuIFBEU0kgaW50ZW5zaXR5ICgrMsKwQyAyMDgwLTIxMDApIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MCwgOTApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE4MCwgMTgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAjIGZpeGVkIHJhdGlvCgpQRFNJXzRDX3Bsb3QgPC0gUERTSV9hYl9kZiAlPiUKICBkcGx5cjo6bXV0YXRlKFBEU0lfNENfY2F0ID0gY2FzZV93aGVuKAogICAgUERTSV80QyA+PSA0IH4gIjQiLCAKICAgIFBEU0lfNEMgPj0gMyAmIFBEU0lfNEMgPCA0IH4gJzMnLAogICAgUERTSV80QyA+PSAyICYgUERTSV80QyA8IDMgfiAnMicsICAKICAgIFBEU0lfNEMgPj0gMSAmIFBEU0lfNEMgPCAyIH4gJzEnLCAgCiAgICBQRFNJXzRDID49IC0xICYgUERTSV80QyA8IDEgfiAnMCcsCiAgICBQRFNJXzRDID49IC0yICYgUERTSV80QyA8IC0xIH4gJy0xJywKICAgIFBEU0lfNEMgPj0gLTMgJiBQRFNJXzRDIDwgLTIgfiAnLTInLAogICAgUERTSV80QyA+PSAtNCAmIFBEU0lfNEMgPCAtMyB+ICctMycsICAgCiAgICBQRFNJXzRDIDwgLTQgfiAnLTQnIAogICkpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBEU0lfNENfY2F0ID0gZmFjdG9yKFBEU0lfNENfY2F0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJy00JywgJy0zJywgJy0yJywgJy0xJywgJzAnLCAnMScsICcyJywgJzMnLCAnNCcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgZmlsdGVyKFBEU0lfNENfY2F0ICE9ICJOQSIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gUERTSV80Q19jYXQpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9zcGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG91cnNfUERTSSwgbmFtZSA9ICJQRFNJIiwgZ3VpZGUgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUsIG5yb3cgPSAxKSkgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICBnZ3RpdGxlKCJNZWFuIFBEU0kgaW50ZW5zaXR5ICgrNMKwQyAyMDgwLTIxMDApIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MCwgOTApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE4MCwgMTgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIAogICAgICAgIGxlZ2VuZC5rZXkuaGVpZ2h0PSB1bml0KDAuMiwgJ2NtJyksCiAgICAgICAgbGVnZW5kLmtleS53aWR0aD0gdW5pdCgwLjIsICdjbScpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAjIGZpeGVkIHJhdGlvCgppbnRfbGVnZW5kIDwtIGNvd3Bsb3Q6OmdldF9sZWdlbmQoUERTSV80Q19wbG90KQoKaW50X3Byb3cgPC0gY293cGxvdDo6cGxvdF9ncmlkKFBEU0lfY3VyX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLCAKICAgICAgICAgICAgICAgICAgIFBEU0lfMkNfcGxvdCArICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLCAKICAgICAgICAgICAgICAgICAgIFBEU0lfNENfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIAogICAgICAgICAgICAgICAgICAgYWxpZ24gPSAidiIsIG5jb2wgPSAzLCBsYWJlbHMgPSBjKCdhJywgJ2InLCAnYycpKSAKCmludF9wbG90cyA8LSBjb3dwbG90OjpwbG90X2dyaWQoaW50X3Byb3csIGludF9sZWdlbmQsIG5jb2wgPSAxLCByZWxfaGVpZ2h0cyA9IGMoMSwgLjEpKQoKIyBGcmVxdWVuY3kKZnJlcV9jdXJfcGxvdCA8LSBQRFNJX2FiX2RmICU+JQogIGRwbHlyOjptdXRhdGUoZnJlcV9jdXJfY2F0ID0gY2FzZV93aGVuKAogICAgZnJlcV9jdXIgPiAwLjEgJiBmcmVxX2N1ciA8IDEgfiAnPDEnCiAgKSkgJT4lCiAgZmlsdGVyKGZyZXFfY3VyX2NhdCAhPSAiTkEiKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoYWVzKHkgPSB5LCB4ID0geCwgZmlsbCA9IGZyZXFfY3VyX2NhdCkpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkX3NwZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gIiNlZGVkZWQiKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIGdndGl0bGUoIk1lYW4gZHJvdWdodCBmcmVxdWVuY3kgKDE5NzDigJMyMDAwKSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNjAsIDkwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xODAsIDE4MCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkgIyBmaXhlZCByYXRpbwoKZnJlcV8yQ19wbG90IDwtIFBEU0lfYWJfZGYgJT4lCiAgZHBseXI6Om11dGF0ZShmcmVxXzJDX2NhdCA9IGNhc2Vfd2hlbigKICAgIGZyZXFfMkMgPj0gMTAgfiAiMTAtMTIiLCAKICAgIGZyZXFfMkMgPj0gOCAmIGZyZXFfMkMgPCAxMCB+ICc4LTEwJywKICAgIGZyZXFfMkMgPj0gNiAmIGZyZXFfMkMgPCA4IH4gJzYtOCcsICAKICAgIGZyZXFfMkMgPj0gNCAmIGZyZXFfMkMgPCA2IH4gJzQtNicsICAKICAgIGZyZXFfMkMgPj0gMiAmIGZyZXFfMkMgPCA0IH4gJzItNCcsCiAgICBmcmVxXzJDID49IDEgJiBmcmVxXzJDIDwgMiB+ICcxLTInLAogICAgZnJlcV8yQyA+IDAuMSAmIGZyZXFfMkMgPCAxIH4gJzwxJwogICkpICU+JSAKICBkcGx5cjo6bXV0YXRlKGZyZXFfMkNfY2F0ID0gZmFjdG9yKGZyZXFfMkNfY2F0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnMTAtMTInLCAnOC0xMCcsICc2LTgnLCAnNC02JywgJzItNCcsICcxLTInLCAnPDEnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgZmlsdGVyKGZyZXFfMkNfY2F0ICE9ICJOQSIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gZnJlcV8yQ19jYXQpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9zcGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM2NzAwMUYiLCAiI0IyMTgyQiIsICIjRDY2MDREIiwgIiNGNEE1ODIiLCAiI0ZEREJDNyIsICIjRkFFOURGIiwgIiNGN0Y3RjciKSkgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICBnZ3RpdGxlKCJNZWFuIGRyb3VnaHQgZnJlcXVlbmN5ICgrMsKwQyAyMDgwLTIxMDApIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MCwgOTApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE4MCwgMTgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAjIGZpeGVkIHJhdGlvCgpmcmVxXzRDX3Bsb3QgPC0gUERTSV9hYl9kZiAlPiUKICBkcGx5cjo6bXV0YXRlKGZyZXFfNENfY2F0ID0gY2FzZV93aGVuKAogICAgZnJlcV80QyA+PSAxMCB+ICIxMC0xMiIsIAogICAgZnJlcV80QyA+PSA4ICYgZnJlcV80QyA8IDEwIH4gJzgtMTAnLAogICAgZnJlcV80QyA+PSA2ICYgZnJlcV80QyA8IDggfiAnNi04JywgIAogICAgZnJlcV80QyA+PSA0ICYgZnJlcV80QyA8IDYgfiAnNC02JywgIAogICAgZnJlcV80QyA+PSAyICYgZnJlcV80QyA8IDQgfiAnMi00JywKICAgIGZyZXFfNEMgPj0gMSAmIGZyZXFfNEMgPCAyIH4gJzEtMicsCiAgICBmcmVxXzRDID4gMC4xICYgZnJlcV80QyA8IDEgfiAnPDEnCiAgKSkgJT4lIAogIGRwbHlyOjptdXRhdGUoZnJlcV80Q19jYXQgPSBmYWN0b3IoZnJlcV80Q19jYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCcxMC0xMicsICc4LTEwJywgJzYtOCcsICc0LTYnLCAnMi00JywgJzEtMicsICc8MScpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKSAlPiUKICBmaWx0ZXIoZnJlcV80Q19jYXQgIT0gIk5BIikgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBmcmVxXzRDX2NhdCkpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkX3NwZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzY3MDAxRiIsICIjQjIxODJCIiwgIiNENjYwNEQiLCAiI0Y0QTU4MiIsICIjRkREQkM3IiwgIiNGQUU5REYiLCAiI0Y3RjdGNyIpLCBuYW1lID0gIk1vbnRocyIsIGd1aWRlID0gZ3VpZGVfbGVnZW5kKHJldmVyc2UgPSBUUlVFLCBucm93ID0gMSkpICsKICB0aGVtZV92b2lkKCkgKyB5bGFiKE5VTEwpICsgeGxhYihOVUxMKSArCiAgZ2d0aXRsZSgiTWVhbiBkcm91Z2h0IGZyZXF1ZW5jeSAoKzTCsEMgMjA4MC0yMTAwKSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNjAsIDkwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xODAsIDE4MCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCAKICAgICAgICBsZWdlbmQua2V5LmhlaWdodD0gdW5pdCgwLjIsICdjbScpLAogICAgICAgIGxlZ2VuZC5rZXkud2lkdGg9IHVuaXQoMC4yLCAnY20nKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkgIyBmaXhlZCByYXRpbwoKZnJlcV9sZWdlbmQgPC0gY293cGxvdDo6Z2V0X2xlZ2VuZChmcmVxXzRDX3Bsb3QpCgpmcmVxX3Byb3cgPC0gY293cGxvdDo6cGxvdF9ncmlkKGZyZXFfY3VyX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLCAKICAgICAgICAgICAgICAgICAgIGZyZXFfMkNfcGxvdCArICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLCAKICAgICAgICAgICAgICAgICAgIGZyZXFfNENfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIAogICAgICAgICAgICAgICAgICAgYWxpZ24gPSAidiIsIG5jb2wgPSAzLCBsYWJlbHMgPSBjKCdkJywgJ2UnLCAnZicpKSAKCmZyZXFfcGxvdHMgPC0gY293cGxvdDo6cGxvdF9ncmlkKGZyZXFfcHJvdywgZnJlcV9sZWdlbmQsIG5jb2wgPSAxLCByZWxfaGVpZ2h0cyA9IGMoMSwgLjEpKQoKCiMgRHVyYXRpb24KZHVyX2N1cl9wbG90IDwtIFBEU0lfYWJfZGYgJT4lCiAgZHBseXI6Om11dGF0ZShkdXJfY3VyX2NhdCA9IGNhc2Vfd2hlbigKICAgIGR1cl9jdXIgPj0gMiAmIGR1cl9jdXIgPCA0IH4gJzItNCcsCiAgICAgZHVyX2N1ciA+PSAxICYgZHVyX2N1ciA8IDIgfiAnMS0yJywKICAgIGR1cl9jdXIgPiAwLjEgJiBkdXJfY3VyIDwgMSB+ICc8MScKICApKSAlPiUgCiAgZHBseXI6Om11dGF0ZShkdXJfY3VyX2NhdCA9IGZhY3RvcihkdXJfY3VyX2NhdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCcyLTQnLCAnMS0yJywgJzwxJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKSAlPiUKICBmaWx0ZXIoZHVyX2N1cl9jYXQgIT0gIk5BIikgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBkdXJfY3VyX2NhdCkpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkX3NwZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0ZEREJDNyIsICIjRkFFOURGIiwgIiNGN0Y3RjciKSkgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICBnZ3RpdGxlKCJNZWFuIGRyb3VnaHQgZHVyYXRpb24gKDE5NzDigJMyMDAwKSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNjAsIDkwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xODAsIDE4MCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkgIyBmaXhlZCByYXRpbwoKZHVyXzJDX3Bsb3QgPC0gUERTSV9hYl9kZiAlPiUKICBkcGx5cjo6bXV0YXRlKGR1cl8yQ19jYXQgPSBjYXNlX3doZW4oCiAgICBkdXJfMkMgPj0gMTAgfiAiPjEwIiwgCiAgICBkdXJfMkMgPj0gOCAmIGR1cl8yQyA8IDEwIH4gJzgtMTAnLAogICAgZHVyXzJDID49IDYgJiBkdXJfMkMgPCA4IH4gJzYtOCcsICAKICAgIGR1cl8yQyA+PSA0ICYgZHVyXzJDIDwgNiB+ICc0LTYnLCAgCiAgICBkdXJfMkMgPj0gMiAmIGR1cl8yQyA8IDQgfiAnMi00JywKICAgIGR1cl8yQyA+PSAxICYgZHVyXzJDIDwgMiB+ICcxLTInLAogICAgZHVyXzJDID4gMC4xICYgZHVyXzJDIDwgMSB+ICc8MScKICApKSAlPiUgCiAgZHBseXI6Om11dGF0ZShkdXJfMkNfY2F0ID0gZmFjdG9yKGR1cl8yQ19jYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnPjEwJywgJzgtMTAnLCAnNi04JywgJzQtNicsICcyLTQnLCAnMS0yJywgJzwxJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKSU+JQogIGZpbHRlcihkdXJfMkNfY2F0ICE9ICJOQSIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gZHVyXzJDX2NhdCkpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkX3NwZGYsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzY3MDAxRiIsICIjQjIxODJCIiwgIiNENjYwNEQiLCAiI0Y0QTU4MiIsICIjRkREQkM3IiwgIiNGQUU5REYiLCAiI0Y3RjdGNyIpKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIGdndGl0bGUoIk1lYW4gZHJvdWdodCBkdXJhdGlvbiAoKzLCsEMgMjA4MC0yMTAwKSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNjAsIDkwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xODAsIDE4MCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkgIyBmaXhlZCByYXRpbwoKZHVyXzRDX3Bsb3QgPC0gUERTSV9hYl9kZiAlPiUKICBkcGx5cjo6bXV0YXRlKGR1cl80Q19jYXQgPSBjYXNlX3doZW4oCiAgICBkdXJfNEMgPj0gMTAgfiAiPjEwIiwgCiAgICBkdXJfNEMgPj0gOCAmIGR1cl80QyA8IDEwIH4gJzgtMTAnLAogICAgZHVyXzRDID49IDYgJiBkdXJfNEMgPCA4IH4gJzYtOCcsICAKICAgIGR1cl80QyA+PSA0ICYgZHVyXzRDIDwgNiB+ICc0LTYnLCAgCiAgICBkdXJfNEMgPj0gMiAmIGR1cl80QyA8IDQgfiAnMi00JywKICAgIGR1cl80QyA+PSAxICYgZHVyXzRDIDwgNCB+ICcxLTInLAogICAgZHVyXzRDID4gMC4xICYgZHVyXzRDIDwgMSB+ICc8MScKICApKSAlPiUgCiAgZHBseXI6Om11dGF0ZShkdXJfNENfY2F0ID0gZmFjdG9yKGR1cl80Q19jYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnPjEwJywgJzgtMTAnLCAnNi04JywgJzQtNicsICcyLTQnLCAnMS0yJywgJzwxJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKSAlPiUKICBmaWx0ZXIoZHVyXzRDX2NhdCAhPSAiTkEiKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoYWVzKHkgPSB5LCB4ID0geCwgZmlsbCA9IGR1cl80Q19jYXQpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9zcGRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM2NzAwMUYiLCAiI0IyMTgyQiIsICIjRDY2MDREIiwgIiNGNEE1ODIiLCAiI0ZEREJDNyIsICIjRkFFOURGIiwgIiNGN0Y3RjciKSwgbmFtZSA9ICJNb250aHMiLCBndWlkZSA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlID0gVFJVRSwgbnJvdyA9IDEpKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIGdndGl0bGUoIk1lYW4gZHJvdWdodCBkdXJhdGlvbiAoKzTCsEMgMjA4MC0yMTAwKSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNjAsIDkwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xODAsIDE4MCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCAKICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuMiwgJ2NtJyksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICMgZml4ZWQgcmF0aW8KCmR1cl9sZWdlbmQgPC0gY293cGxvdDo6Z2V0X2xlZ2VuZChkdXJfNENfcGxvdCkKCmR1cl9wcm93IDwtIGNvd3Bsb3Q6OnBsb3RfZ3JpZChkdXJfY3VyX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLCAKICAgICAgICAgICAgICAgICAgIGR1cl8yQ19wbG90ICsgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIAogICAgICAgICAgICAgICAgICAgZHVyXzRDX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLCAKICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLCBuY29sID0gMywgbGFiZWxzID0gYygnZycsICdoJywgJ2knKSkgCgpkdXJfcGxvdHMgPC0gY293cGxvdDo6cGxvdF9ncmlkKGR1cl9wcm93LCBkdXJfbGVnZW5kLCBuY29sID0gMSwgcmVsX2hlaWdodHMgPSBjKDEsIC4xKSkKCgpjb3dwbG90OjpwbG90X2dyaWQoaW50X3Bsb3RzLCBmcmVxX3Bsb3RzLCBkdXJfcGxvdHMsIG5jb2wgPSAxKQpgYGAKCioqRmlnLiBTMi4qKiBNZWFuIG1vbnRobHkgUGFsbWVyIERyb3VnaHQgU2V2ZXJpdHkgSW5kZXggKFBEU0kpIHNlbGYtY2FsaWJyYXRlZCB3aXRoIFBlbm1hbuKAk01vbnRlaXRoIHBvdGVudGlhbCBldmFwb3RyYW5zcGlyYXRpb24gZnJvbSAoKiphKiopIDE5NzDigJMyMDAwLCBhbmQgZnJvbSAyMDgwLTIxMDAgdW5kZXIgKCoqYioqKSB1bmRlciBhbiBpbnRlcm1lZGlhdGUgZW1pc3Npb24gc2NlbmFyaW8gb2YgKzLCsEMgKFNoYXJlZCBTb2Npb2Vjb25vbWljIFBhdGh3YXlzIDIgLSA0LjU7IFNTUDItNC41KSwgYW5kICgqKmMqKikgdW5kZXIgYSBoaWdoIGVtaXNzaW9uIHNjZW5hcmlvIG9mICs0wrBDIChTU1A1LTguNSkuIE1lYW4geWVhcmx5IGZyZXF1ZW5jeSBvZiBtb2RlcmF0ZSB0byBleHRyZW1lIGRyb3VnaHQgKFBEU0kgPCAtMikgZnJvbSAoKipkKiopIDE5NzDigJMyMDAwLCBhbmQgZnJvbSAyMDgwLTIxMDAgKCoqZSoqKSB1bmRlciBhbiBpbnRlcm1lZGlhdGUgZW1pc3Npb24gc2NlbmFyaW8gb2YgKzLCsEMgKFNTUDItNC41KSwgYW5kICgqKmYqKikgdW5kZXIgYSBoaWdoIGVtaXNzaW9uIHNjZW5hcmlvIG9mICs0wrBDIChTU1A1LTguNSkuIE1lYW4gZHVyYXRpb24gb2YgbW9kZXJhdGUgdG8gZXh0cmVtZSBkcm91Z2h0IChQRFNJIDwgLTIpIGZyb20gKCoqZyoqKSAxOTcw4oCTMjAwMCwgYW5kIGZyb20gMjA4MC0yMTAwICgqKmgqKikgdW5kZXIgYW4gaW50ZXJtZWRpYXRlIGVtaXNzaW9uIHNjZW5hcmlvIG9mICsywrBDIChTU1AyLTQuNSksIGFuZCAoKippKiopIHVuZGVyIGEgaGlnaCBlbWlzc2lvbiBzY2VuYXJpbyBvZiArNMKwQyAoU1NQNS04LjUpLgoKIyMgU3VtbWFyeSB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxscyAtfQoKIyMjIEVjb3R5cGUgQUkgZGlzdHJpYnV0aW9uIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKTWVhbiDCsSBzLmQuIGFyaWRpdHkgaW5kZXggb2NjdXBpZWQgYnkgZGlmZmVyZW50IGFudXJhbiBlY290eXBlcy4KCmBgYHtyIGVjb3R5cGUsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmFpX3NwX2RmICU+JQogIGRwbHlyOjpmaWx0ZXIoYXJpZGl0eSA8PTMpICU+JQogIGRwbHlyOjpzZWxlY3QoYXJpZGl0eSwgc3BlY2llc19uOnN0cmVhbV9uKSAlPiUKICB0aWR5cjo6cGl2b3RfbG9uZ2VyKCFhcmlkaXR5LCBuYW1lc190byA9ICJlY290eXBlIiwgdmFsdWVzX3RvID0gIm1lYW4iKSAlPiUKICBkcGx5cjo6ZmlsdGVyKGVjb3R5cGUgIT0gInNwZWNpZXNfbiIpICU+JQogIGRyb3BfbmEobWVhbikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGVjb3R5cGUpICU+JQogIGRwbHlyOjpzdW1tYXJpc2UobWVhbiA9IG1lYW4oYXJpZGl0eSksCiAgICAgICAgICAgICAgICAgICBzZCAgID0gc2QoYXJpZGl0eSkpICU+JQogIGRwbHlyOjptdXRhdGUoZWNvdHlwZSA9IHN1YnN0cihlY290eXBlLDEsbmNoYXIoZWNvdHlwZSktMiksCiAgICAgICAgICAgICAgICBtZWFuICAgID0gZm9ybWF0KHJvdW5kKG1lYW4sIDIpLCBuc21hbGwgPSAyKSwKICAgICAgICAgICAgICAgIHNkICAgICAgPSBmb3JtYXQocm91bmQoc2QsIDIpLCBuc21hbGwgPSAyKSwKICAgICAgICAgICAgICAgIGFyaWRpdHkgPSBwYXN0ZShtZWFuLCBzZCwgc2VwID0gIiDCsSAiKSwKICAgICAgICAgICAgICAgIGVjb3R5cGUgPSBjYXNlX3doZW4oCiAgICBlY290eXBlID09ICJzdHJlYW0iICAgIH4gIlN0cmVhbS1kd2VsbGluZyIsCiAgICBlY290eXBlID09ICJhcmJvcmVhbCIgIH4gIkFyYm9yZWFsIiwKICAgIGVjb3R5cGUgPT0gInNlbWlfYXEiICB+ICJTZW1pLWFxdWF0aWMiLAogICAgZWNvdHlwZSA9PSAiYXF1YXRpYyIgIH4gIkFxdWF0aWMiLAogICAgZWNvdHlwZSA9PSAiZ3JvdW5kIiAgfiAiR3JvdW5kLWR3ZWxsaW5nIiwKICAgIGVjb3R5cGUgPT0gImZvc3NvcmlhbCIgfiAiRm9zc29yaWFsIikpICU+JQogIGRwbHlyOjpzZWxlY3QoZWNvdHlwZSwgYXJpZGl0eSkgJT4lCiAgZHBseXI6OmFycmFuZ2UoZGVzYyhhcmlkaXR5KSkgJT4lCiAga25pdHI6OmthYmxlKGNvbC5uYW1lcyA9IGMoIkVjb3R5cGUiLCAiQUkgKG1lYW4gwrEgcy5kLikiKSkKYGBgCgoqKioKCiMjIyAywrBDIEFJIHJpc2sgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHMgLX0gCgpQZXJjZW50IGNoYW5nZSBpbiBhcmlkaXR5IGJ5IDIwODDigJMyMTAwICgrIDLCsEMpIHJlbGF0aXZlIHRvIGN1cnJlbnQgY2xpbWF0ZSAoMTk4MeKAkzIwMTApIGZvciBhbGwgYW51cmFucyBhbmQgYWxzbyBieSBlY290eXBlLgoKYGBge3IgYWkgc3VtIDIsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgY2FsY3VsYXRlIHJlbGF0aXZlIGNoYW5nZSB3aXRoIGZ1dHVyZSBzY2VuYXJpbwphaV9zcF9zdW0gJT4lCiAgZHBseXI6Om11dGF0ZShhbGxfY2hhbmdlICAgICAgID0gKGFpXzJDX3NwX3N1bSRzcGVjaWVzX24gLSBzcGVjaWVzX24pIC8gc3BlY2llc19uICogMTAwLAogICAgICAgICAgICAgICAgYXF1YXRpY19jaGFuZ2UgICA9IChhaV8yQ19zcF9zdW0kYXF1YXRpY19uIC0gYXF1YXRpY19uKSAvIGFxdWF0aWNfbiAqIDEwMCwKICAgICAgICAgICAgICAgIGFyYm9yZWFsX2NoYW5nZSAgPSAoYWlfMkNfc3Bfc3VtJGFyYm9yZWFsX24gLSBhcmJvcmVhbF9uKSAvIGFyYm9yZWFsX24gKiAxMDAsCiAgICAgICAgICAgICAgICBmb3Nzb3JpYWxfY2hhbmdlID0gKGFpXzJDX3NwX3N1bSRmb3Nzb3JpYWxfbiAtIGZvc3NvcmlhbF9uKSAvIGZvc3NvcmlhbF9uICogMTAwLAogICAgICAgICAgICAgICAgZ3JvdW5kX2NoYW5nZSAgICA9IChhaV8yQ19zcF9zdW0kZ3JvdW5kX24gLSBncm91bmRfbikgLyBncm91bmRfbiAqIDEwMCwKICAgICAgICAgICAgICAgIHNlbWlfYXFfY2hhbmdlICAgPSAoYWlfMkNfc3Bfc3VtJHNlbWlfYXFfbiAtIHNlbWlfYXFfbikgLyBzZW1pX2FxX24gKiAxMDAsCiAgICAgICAgICAgICAgICBzdHJlYW1fY2hhbmdlICAgID0gKGFpXzJDX3NwX3N1bSRzdHJlYW1fbiAtIHN0cmVhbV9uKSAvIHN0cmVhbV9uICogMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KGMoY2F0ZWdvcnksIGFsbF9jaGFuZ2U6c3RyZWFtX2NoYW5nZSkpICU+JQogIGtuaXRyOjprYWJsZShjb2wubmFtZXMgPSBjKCJFY290eXBlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFsbCAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBcXVhdGljIDLCsEMgKCUpIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFyYm9yZWFsIDLCsEMgKCUpIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZvc3NvcmlhbCAywrBDKCUpIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VuZC1kd2VsbGluZyAywrBDICglKSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTZW1pLWFxdWF0aWMgMsKwQyAoJSkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3RyZWFtLWR3ZWxsaW5nIDLCsEMgKCUpIiksCiAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKSAjIDIgZGVjaW1hbCBwbGFjZXMKYGBgCgoqKioKCiMjIyA0wrBDIEFJIHJpc2sgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHMgLX0gCgpQZXJjZW50IGNoYW5nZSBpbiBhcmlkaXR5IGJ5IDIwODDigJMyMTAwICgrIDTCsEMpIHJlbGF0aXZlIHRvIGN1cnJlbnQgY2xpbWF0ZSAoMTk4MeKAkzIwMTApIGZvciBhbGwgYW51cmFucyBhbmQgYWxzbyBieSBlY290eXBlLgoKYGBge3IgYWkgc3VtIDQsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgY2FsY3VsYXRlIHJlbGF0aXZlIGNoYW5nZSB3aXRoIGZ1dHVyZSBzY2VuYXJpbwphaV9zcF9zdW0gJT4lCiAgZHBseXI6Om11dGF0ZShhbGxfY2hhbmdlICAgICAgID0gKGFpXzRDX3NwX3N1bSRzcGVjaWVzX24gLSBzcGVjaWVzX24pIC8gc3BlY2llc19uICogMTAwLAogICAgICAgICAgICAgICAgYXF1YXRpY19jaGFuZ2UgICA9IChhaV80Q19zcF9zdW0kYXF1YXRpY19uIC0gYXF1YXRpY19uKSAvIGFxdWF0aWNfbiAqIDEwMCwKICAgICAgICAgICAgICAgIGFyYm9yZWFsX2NoYW5nZSAgPSAoYWlfNENfc3Bfc3VtJGFyYm9yZWFsX24gLSBhcmJvcmVhbF9uKSAvIGFyYm9yZWFsX24gKiAxMDAsCiAgICAgICAgICAgICAgICBmb3Nzb3JpYWxfY2hhbmdlID0gKGFpXzRDX3NwX3N1bSRmb3Nzb3JpYWxfbiAtIGZvc3NvcmlhbF9uKSAvIGZvc3NvcmlhbF9uICogMTAwLAogICAgICAgICAgICAgICAgZ3JvdW5kX2NoYW5nZSAgICA9IChhaV80Q19zcF9zdW0kZ3JvdW5kX24gLSBncm91bmRfbikgLyBncm91bmRfbiAqIDEwMCwKICAgICAgICAgICAgICAgIHNlbWlfYXFfY2hhbmdlICAgPSAoYWlfNENfc3Bfc3VtJHNlbWlfYXFfbiAtIHNlbWlfYXFfbikgLyBzZW1pX2FxX24gKiAxMDAsCiAgICAgICAgICAgICAgICBzdHJlYW1fY2hhbmdlICAgID0gKGFpXzRDX3NwX3N1bSRzdHJlYW1fbiAtIHN0cmVhbV9uKSAvIHN0cmVhbV9uICogMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KGMoY2F0ZWdvcnksIGFsbF9jaGFuZ2U6c3RyZWFtX2NoYW5nZSkpICU+JQogIGtuaXRyOjprYWJsZShjb2wubmFtZXMgPSBjKCJFY290eXBlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFsbCAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBcXVhdGljIDLCsEMgKCUpIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFyYm9yZWFsIDLCsEMgKCUpIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZvc3NvcmlhbCAywrBDKCUpIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VuZC1kd2VsbGluZyAywrBDICglKSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTZW1pLWFxdWF0aWMgMsKwQyAoJSkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3RyZWFtLWR3ZWxsaW5nIDLCsEMgKCUpIiksCiAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKSAjIDIgZGVjaW1hbCBwbGFjZXMKYGBgCgoqKioKCiMjIyAywrBDIFBEU0kgIHJpc2sgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHMgLX0gCgpQZXJjZW50IGNoYW5nZSBpbiBkcm91Z2h0IGludGVuc2l0eSAozpRQRFNJKSwgZHJvdWdodCBmcmVxdWVuY3kgKM6URnJlcXVlbmN5KSwgYW5kIGRyb3VnaHQgZHVyYXRpb24gKM6URHVyYXRpb24pIGJ5IDIwODDigJMyMDk5ICgrIDLCsEMgc2NlbmFyaW8pIHJlbGF0aXZlIHRvIGN1cnJlbnQgY2xpbWF0ZSAoMTk3MOKAkzIwMDApIGluIGdyaWQgY2VsbHMgb2NjdXBpZWQgYnkgYW51cmFucyBhbmQgYWxzbyBieSBlY290eXBlLgoKYGBge3IgUERTSSBzdW0gMiwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KI0ludGVuc2l0eQpQRFNJX3NwXzJDICU+JQogIGRwbHlyOjpzZWxlY3QoYyhjaGFuZ2VfMkMsIGFsbF9mcmVxOnN0cmVhbV9mcmVxKSkgJT4lCiAga25pdHI6OmthYmxlKGNvbC5uYW1lcyA9IGMoIs6UUERTSSIsICJBbGwgKCUpIiwgIkFxdWF0aWMgKCUpIiwgIkFyYm9yZWFsICglKSIsICJGb3Nzb3JpYWwgKCUpIiwgIkdyb3VuZC1kd2VsbGluZyAoJSkiLCAiU2VtaS1hcXVhdGljICglKSIsICJTdHJlYW0tZHdlbGxpbmcgKCUpIiksCiAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKSAjIDIgZGVjaW1hbCBwbGFjZXMKCiMgRnJlcXVlbmN5CmZyZXFfMkNfZGlmZl9kZiA8LSBmcmVxX2RpZmZfZGYgJT4lCiAgZHBseXI6OnNlbGVjdCh4LCB5LCBkaWZmXzJDKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRpZmZfMkNfY2F0ID0gY2FzZV93aGVuKAogICAgZGlmZl8yQyA+PSAxMCB+ICIxMC0xMiIsIAogICAgZGlmZl8yQyA+PSA4ICYgZGlmZl8yQyA8IDEwIH4gJzgtMTAnLAogICAgZGlmZl8yQyA+PSA2ICYgZGlmZl8yQyA8IDggfiAnNi04JywgIAogICAgZGlmZl8yQyA+PSA0ICYgZGlmZl8yQyA8IDYgfiAnNC02JywgIAogICAgZGlmZl8yQyA+PSAyICYgZGlmZl8yQyA8IDQgfiAnMi00JywKICAgIGRpZmZfMkMgPj0gMSAmIGRpZmZfMkMgPCAyIH4gJzEtMicsCiAgICBkaWZmXzJDID4gMCAmIGRpZmZfMkMgPCAxIH4gJzAtMScsCiAgICBkaWZmXzJDID49IC0xICYgZGlmZl8yQyA8IDAgfiAnLTAtMScsCiAgICBkaWZmXzJDID49IC0yICYgZGlmZl8yQyA8IC0xIH4gJy0xLTInLAogICAgZGlmZl8yQyA+PSAtNCAmIGRpZmZfMkMgPCAtMiB+ICctMi00JwogICkpICU+JSAKICBkcGx5cjo6bXV0YXRlKGRpZmZfMkNfY2F0ID0gZmFjdG9yKGRpZmZfMkNfY2F0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJzEwLTEyJywgJzgtMTAnLCAnNi04JywgJzQtNicsICcyLTQnLCAnMS0yJywgJzAtMScsICctMC0xJywgJy0xLTInLCAnLTItNCcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkKCmZyZXFfc3BfMkNfZGYgPC0gYW51cmFuX3NyX2RmICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKGZyZXFfMkNfZGlmZl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oYXF1YXRpY19zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oYXJib3JlYWxfc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKGZvc3NvcmlhbF9zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oZ3JvdW5kX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihzZW1pX2FxX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihzdHJlYW1fc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JQogIGZpbHRlcihkaWZmXzJDX2NhdCAhPSAiTkEiICYgc3BlY2llc19uICE9ICJOQSIpCgpkYXRhLmZyYW1lKGZyZXFfc3BfMkNfZGYgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6Omdyb3VwX2J5KGRpZmZfMkNfY2F0KSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c3VtbWFyaXNlKHNwZWNpZXNfbiAgID0gbGVuZ3RoKHNwZWNpZXNfblshaXMubmEoc3BlY2llc19uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcXVhdGljX24gICA9IGxlbmd0aChhcXVhdGljX25bIWlzLm5hKGFxdWF0aWNfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJib3JlYWxfbiAgPSBsZW5ndGgoYXJib3JlYWxfblshaXMubmEoYXJib3JlYWxfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9zc29yaWFsX24gPSBsZW5ndGgoZm9zc29yaWFsX25bIWlzLm5hKGZvc3NvcmlhbF9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91bmRfbiAgICA9IGxlbmd0aChncm91bmRfblshaXMubmEoZ3JvdW5kX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbWlfYXFfbiAgID0gbGVuZ3RoKHNlbWlfYXFfblshaXMubmEoc2VtaV9hcV9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1fbiAgICA9IGxlbmd0aChzdHJlYW1fblshaXMubmEoc3RyZWFtX24pXSkpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGFsbF9mcmVxICAgICAgID0gc3BlY2llc19uIC8gc3VtKHNwZWNpZXNfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBhcXVhdGljX2ZyZXEgICA9IGFxdWF0aWNfbiAvIHN1bShhcXVhdGljX24pICogMTAwLAogICAgICAgICAgICAgICAgYXJib3JlYWxfZnJlcSAgPSBhcmJvcmVhbF9uIC8gc3VtKGFyYm9yZWFsX24pICogMTAwLAogICAgICAgICAgICAgICAgZm9zc29yaWFsX2ZyZXEgPSBmb3Nzb3JpYWxfbiAvIHN1bShmb3Nzb3JpYWxfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBncm91bmRfZnJlcSAgICA9IGdyb3VuZF9uIC8gc3VtKGdyb3VuZF9uKSAqIDEwMCwKICAgICAgICAgICAgICAgIHNlbWlfYXFfZnJlcSAgID0gc2VtaV9hcV9uIC8gc3VtKHNlbWlfYXFfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBzdHJlYW1fZnJlcSAgICA9IHN0cmVhbV9uIC8gc3VtKHN0cmVhbV9uKSAqIDEwMCkgJT4lCiAgZHBseXI6OnNlbGVjdChjKGRpZmZfMkNfY2F0LCBhbGxfZnJlcTpzdHJlYW1fZnJlcSkpICU+JQogICBrbml0cjo6a2FibGUoY29sLm5hbWVzID0gYygizpRGcmVxdWVuY3kgKG1vbnRocykiLCAiQWxsICglKSIsICJBcXVhdGljICglKSIsICJBcmJvcmVhbCAoJSkiLCAiRm9zc29yaWFsICglKSIsICJHcm91bmQtZHdlbGxpbmcgKCUpIiwgIlNlbWktYXF1YXRpYyAoJSkiLCAiU3RyZWFtLWR3ZWxsaW5nICglKSIpLAogICAgICAgICAgICAgICAgZGlnaXRzID0gMikgIyAyIGRlY2ltYWwgcGxhY2VzCgojIER1cmF0aW9uCmR1cl8yQ19kaWZmX2RmIDwtIGR1cl9kaWZmX2RmICU+JQogIGRwbHlyOjpzZWxlY3QoeCwgeSwgZGlmZl8yQykgJT4lCiAgZHBseXI6Om11dGF0ZShkaWZmXzJDX2NhdCA9IGNhc2Vfd2hlbigKICAgIGRpZmZfMkMgPj0gMTAgfiAiPjEwIiwgCiAgICBkaWZmXzJDID49IDggJiBkaWZmXzJDIDwgMTAgfiAnOC0xMCcsCiAgICBkaWZmXzJDID49IDYgJiBkaWZmXzJDIDwgOCB+ICc2LTgnLCAgCiAgICBkaWZmXzJDID49IDQgJiBkaWZmXzJDIDwgNiB+ICc0LTYnLCAgCiAgICBkaWZmXzJDID49IDIgJiBkaWZmXzJDIDwgNCB+ICcyLTQnLAogICAgZGlmZl8yQyA+PSAxICYgZGlmZl8yQyA8IDIgfiAnMS0yJywKICAgIGRpZmZfMkMgPiAwICYgZGlmZl8yQyA8IDEgfiAnMC0xJywKICAgIGRpZmZfMkMgPj0gLTEgJiBkaWZmXzJDIDwgMCB+ICctMC0xJywKICAgIGRpZmZfMkMgPj0gLTIgJiBkaWZmXzJDIDwgLTEgfiAnLTEtMicsCiAgICBkaWZmXzJDID49IC00ICYgZGlmZl8yQyA8IC0yIH4gJy0yLTQnLAogICAgZGlmZl8yQyA+PSAtNiAmIGRpZmZfMkMgPCAtNCB+ICctNC02JywKICAgIGRpZmZfMkMgPj0gLTggJiBkaWZmXzJDIDwgLTYgfiAnLTYtOCcsCiAgICBkaWZmXzJDID49IC0xMCAmIGRpZmZfMkMgPCAtOCB+ICctOC0xMCcsICAgCiAgICBkaWZmXzJDIDwgLTEwIH4gJzwtMTAnIAogICkpICU+JSAKICBkcGx5cjo6bXV0YXRlKGRpZmZfMkNfY2F0ID0gZmFjdG9yKGRpZmZfMkNfY2F0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJz4xMCcsICc4LTEwJywgJzYtOCcsICc0LTYnLCAnMi00JywgJzEtMicsICcwLTEnLCAnLTAtMScsICctMS0yJywgJy0yLTQnLCAnLTQtNicsICctNi04JywgJy04LTEwJywgJzwtMTAnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkpCgpkdXJfc3BfMkNfZGYgPC0gYW51cmFuX3NyX2RmICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKGR1cl8yQ19kaWZmX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihhcXVhdGljX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihhcmJvcmVhbF9zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oZm9zc29yaWFsX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihncm91bmRfc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKHNlbWlfYXFfc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKHN0cmVhbV9zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lCiAgZmlsdGVyKGRpZmZfMkNfY2F0ICE9ICJOQSIgJiBzcGVjaWVzX24gIT0gIk5BIikKCmRhdGEuZnJhbWUoZHVyX3NwXzJDX2RmICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpncm91cF9ieShkaWZmXzJDX2NhdCkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnN1bW1hcmlzZShzcGVjaWVzX24gICA9IGxlbmd0aChzcGVjaWVzX25bIWlzLm5hKHNwZWNpZXNfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXF1YXRpY19uICAgPSBsZW5ndGgoYXF1YXRpY19uWyFpcy5uYShhcXVhdGljX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyYm9yZWFsX24gID0gbGVuZ3RoKGFyYm9yZWFsX25bIWlzLm5hKGFyYm9yZWFsX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9uID0gbGVuZ3RoKGZvc3NvcmlhbF9uWyFpcy5uYShmb3Nzb3JpYWxfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdW5kX24gICAgPSBsZW5ndGgoZ3JvdW5kX25bIWlzLm5hKGdyb3VuZF9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW1pX2FxX24gICA9IGxlbmd0aChzZW1pX2FxX25bIWlzLm5hKHNlbWlfYXFfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtX24gICAgPSBsZW5ndGgoc3RyZWFtX25bIWlzLm5hKHN0cmVhbV9uKV0pKSkgJT4lCiAgZHBseXI6Om11dGF0ZShhbGxfZnJlcSAgICAgICA9IHNwZWNpZXNfbiAvIHN1bShzcGVjaWVzX24pICogMTAwLAogICAgICAgICAgICAgICAgYXF1YXRpY19mcmVxICAgPSBhcXVhdGljX24gLyBzdW0oYXF1YXRpY19uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGFyYm9yZWFsX2ZyZXEgID0gYXJib3JlYWxfbiAvIHN1bShhcmJvcmVhbF9uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9mcmVxID0gZm9zc29yaWFsX24gLyBzdW0oZm9zc29yaWFsX24pICogMTAwLAogICAgICAgICAgICAgICAgZ3JvdW5kX2ZyZXEgICAgPSBncm91bmRfbiAvIHN1bShncm91bmRfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBzZW1pX2FxX2ZyZXEgICA9IHNlbWlfYXFfbiAvIHN1bShzZW1pX2FxX24pICogMTAwLAogICAgICAgICAgICAgICAgc3RyZWFtX2ZyZXEgICAgPSBzdHJlYW1fbiAvIHN1bShzdHJlYW1fbikgKiAxMDApICU+JQogIGRwbHlyOjpzZWxlY3QoYyhkaWZmXzJDX2NhdCwgYWxsX2ZyZXE6c3RyZWFtX2ZyZXEpKSAlPiUKICAga25pdHI6OmthYmxlKGNvbC5uYW1lcyA9IGMoIs6URHVyYXRpb24gKG1vbnRocykiLCAiQWxsICglKSIsICJBcXVhdGljICglKSIsICJBcmJvcmVhbCAoJSkiLCAiRm9zc29yaWFsICglKSIsICJHcm91bmQtZHdlbGxpbmcgKCUpIiwgIlNlbWktYXF1YXRpYyAoJSkiLCAiU3RyZWFtLWR3ZWxsaW5nICglKSIpLAogICAgICAgICAgICAgICAgZGlnaXRzID0gMikgIyAyIGRlY2ltYWwgcGxhY2VzCmBgYAoKKioqCgojIyMgNMKwQyBQRFNJIHJpc2sgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHMgLX0gCgpQZXJjZW50IGNoYW5nZSBpbiBkcm91Z2h0IGludGVuc2l0eSAozpRQRFNJKSwgZnJlcXVlbmN5ICjOlEZyZXF1ZW5jeSksIGFuZCBkdXJhdGlvbiAozpREdXJhdGlvbikgYnkgMjA4MOKAkzIwOTkgKCsgNMKwQyBzY2VuYXJpbykgcmVsYXRpdmUgdG8gY3VycmVudCBjbGltYXRlICgxOTcw4oCTMjAwMCkgaW4gZ3JpZCBjZWxscyBvY2N1cGllZCBieSBhbnVyYW5zIGFuZCBieSBlY290eXBlLgoKYGBge3IgUERTSSBzdW0gNCwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KI0ludGVuc2l0eQpQRFNJX3NwXzRDICU+JQogIGRwbHlyOjpzZWxlY3QoYyhjaGFuZ2VfNEMsIGFsbF9mcmVxOnN0cmVhbV9mcmVxKSkgJT4lCiAga25pdHI6OmthYmxlKGNvbC5uYW1lcyA9IGMoIs6UUERTSSIsICJBbGwgKCUpIiwgIkFxdWF0aWMgKCUpIiwgIkFyYm9yZWFsICglKSIsICJGb3Nzb3JpYWwgKCUpIiwgIkdyb3VuZC1kd2VsbGluZyAoJSkiLCAiU2VtaS1hcXVhdGljICglKSIsICJTdHJlYW0tZHdlbGxpbmcgKCUpIiksCiAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKSAjIDIgZGVjaW1hbCBwbGFjZXMKCiMgRnJlcXVlbmN5CmZyZXFfNENfZGlmZl9kZiA8LSBmcmVxX2RpZmZfZGYgJT4lCiAgZHBseXI6OnNlbGVjdCh4LCB5LCBkaWZmXzRDKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRpZmZfNENfY2F0ID0gY2FzZV93aGVuKAogICAgZGlmZl80QyA+PSAxMCB+ICIxMC0xMiIsIAogICAgZGlmZl80QyA+PSA4ICYgZGlmZl80QyA8IDEwIH4gJzgtMTAnLAogICAgZGlmZl80QyA+PSA2ICYgZGlmZl80QyA8IDggfiAnNi04JywgIAogICAgZGlmZl80QyA+PSA0ICYgZGlmZl80QyA8IDYgfiAnNC02JywgIAogICAgZGlmZl80QyA+PSAyICYgZGlmZl80QyA8IDQgfiAnMi00JywKICAgIGRpZmZfNEMgPj0gMSAmIGRpZmZfNEMgPCAyIH4gJzEtMicsCiAgICBkaWZmXzRDID4gMCAmIGRpZmZfNEMgPCAxIH4gJzAtMScsCiAgICBkaWZmXzRDID49IC0xICYgZGlmZl80QyA8IDAgfiAnLTAtMScsCiAgICBkaWZmXzRDID49IC0yICYgZGlmZl80QyA8IC0xIH4gJy0xLTInLAogICAgZGlmZl80QyA+PSAtNCAmIGRpZmZfNEMgPCAtMiB+ICctMi00JwogICkpICU+JSAKICBkcGx5cjo6bXV0YXRlKGRpZmZfNENfY2F0ID0gZmFjdG9yKGRpZmZfNENfY2F0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJzEwLTEyJywgJzgtMTAnLCAnNi04JywgJzQtNicsICcyLTQnLCAnMS0yJywgJzAtMScsICctMC0xJywgJy0xLTInLCAnLTItNCcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkKCmZyZXFfc3BfNENfZGYgPC0gYW51cmFuX3NyX2RmICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKGZyZXFfNENfZGlmZl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oYXF1YXRpY19zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oYXJib3JlYWxfc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKGZvc3NvcmlhbF9zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oZ3JvdW5kX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihzZW1pX2FxX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihzdHJlYW1fc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JQogIGZpbHRlcihkaWZmXzRDX2NhdCAhPSAiTkEiICYgc3BlY2llc19uICE9ICJOQSIpCgpkYXRhLmZyYW1lKGZyZXFfc3BfNENfZGYgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6Omdyb3VwX2J5KGRpZmZfNENfY2F0KSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c3VtbWFyaXNlKHNwZWNpZXNfbiAgID0gbGVuZ3RoKHNwZWNpZXNfblshaXMubmEoc3BlY2llc19uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcXVhdGljX24gICA9IGxlbmd0aChhcXVhdGljX25bIWlzLm5hKGFxdWF0aWNfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJib3JlYWxfbiAgPSBsZW5ndGgoYXJib3JlYWxfblshaXMubmEoYXJib3JlYWxfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9zc29yaWFsX24gPSBsZW5ndGgoZm9zc29yaWFsX25bIWlzLm5hKGZvc3NvcmlhbF9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91bmRfbiAgICA9IGxlbmd0aChncm91bmRfblshaXMubmEoZ3JvdW5kX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbWlfYXFfbiAgID0gbGVuZ3RoKHNlbWlfYXFfblshaXMubmEoc2VtaV9hcV9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1fbiAgICA9IGxlbmd0aChzdHJlYW1fblshaXMubmEoc3RyZWFtX24pXSkpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGFsbF9mcmVxICAgICAgID0gc3BlY2llc19uIC8gc3VtKHNwZWNpZXNfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBhcXVhdGljX2ZyZXEgICA9IGFxdWF0aWNfbiAvIHN1bShhcXVhdGljX24pICogMTAwLAogICAgICAgICAgICAgICAgYXJib3JlYWxfZnJlcSAgPSBhcmJvcmVhbF9uIC8gc3VtKGFyYm9yZWFsX24pICogMTAwLAogICAgICAgICAgICAgICAgZm9zc29yaWFsX2ZyZXEgPSBmb3Nzb3JpYWxfbiAvIHN1bShmb3Nzb3JpYWxfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBncm91bmRfZnJlcSAgICA9IGdyb3VuZF9uIC8gc3VtKGdyb3VuZF9uKSAqIDEwMCwKICAgICAgICAgICAgICAgIHNlbWlfYXFfZnJlcSAgID0gc2VtaV9hcV9uIC8gc3VtKHNlbWlfYXFfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBzdHJlYW1fZnJlcSAgICA9IHN0cmVhbV9uIC8gc3VtKHN0cmVhbV9uKSAqIDEwMCkgJT4lCiAgZHBseXI6OnNlbGVjdChjKGRpZmZfNENfY2F0LCBhbGxfZnJlcTpzdHJlYW1fZnJlcSkpICU+JQogICBrbml0cjo6a2FibGUoY29sLm5hbWVzID0gYygizpRGcmVxdWVuY3kgKG1vbnRocykiLCAiQWxsICglKSIsICJBcXVhdGljICglKSIsICJBcmJvcmVhbCAoJSkiLCAiRm9zc29yaWFsICglKSIsICJHcm91bmQtZHdlbGxpbmcgKCUpIiwgIlNlbWktYXF1YXRpYyAoJSkiLCAiU3RyZWFtLWR3ZWxsaW5nICglKSIpLAogICAgICAgICAgICAgICAgZGlnaXRzID0gMikgIyAyIGRlY2ltYWwgcGxhY2VzCgojIER1cmF0aW9uCmR1cl80Q19kaWZmX2RmIDwtIGR1cl9kaWZmX2RmICU+JQogIGRwbHlyOjpzZWxlY3QoeCwgeSwgZGlmZl80QykgJT4lCiAgZHBseXI6Om11dGF0ZShkaWZmXzRDX2NhdCA9IGNhc2Vfd2hlbigKICAgIGRpZmZfNEMgPj0gMTAgfiAiPjEwIiwgCiAgICBkaWZmXzRDID49IDggJiBkaWZmXzRDIDwgMTAgfiAnOC0xMCcsCiAgICBkaWZmXzRDID49IDYgJiBkaWZmXzRDIDwgOCB+ICc2LTgnLCAgCiAgICBkaWZmXzRDID49IDQgJiBkaWZmXzRDIDwgNiB+ICc0LTYnLCAgCiAgICBkaWZmXzRDID49IDIgJiBkaWZmXzRDIDwgNCB+ICcyLTQnLAogICAgZGlmZl80QyA+PSAxICYgZGlmZl80QyA8IDIgfiAnMS0yJywKICAgIGRpZmZfNEMgPiAwICYgZGlmZl80QyA8IDEgfiAnMC0xJywKICAgIGRpZmZfNEMgPj0gLTEgJiBkaWZmXzRDIDwgMCB+ICctMC0xJywKICAgIGRpZmZfNEMgPj0gLTIgJiBkaWZmXzRDIDwgLTEgfiAnLTEtMicsCiAgICBkaWZmXzRDID49IC00ICYgZGlmZl80QyA8IC0yIH4gJy0yLTQnLAogICAgZGlmZl80QyA+PSAtNiAmIGRpZmZfNEMgPCAtNCB+ICctNC02JywKICAgIGRpZmZfNEMgPj0gLTggJiBkaWZmXzRDIDwgLTYgfiAnLTYtOCcsCiAgICBkaWZmXzRDID49IC0xMCAmIGRpZmZfNEMgPCAtOCB+ICctOC0xMCcsICAgCiAgICBkaWZmXzRDIDwgLTEwIH4gJzwtMTAnIAogICkpICU+JSAKICBkcGx5cjo6bXV0YXRlKGRpZmZfNENfY2F0ID0gZmFjdG9yKGRpZmZfNENfY2F0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJz4xMCcsICc4LTEwJywgJzYtOCcsICc0LTYnLCAnMi00JywgJzEtMicsICcwLTEnLCAnLTAtMScsICctMS0yJywgJy0yLTQnLCAnLTQtNicsICctNi04JywgJy04LTEwJywgJzwtMTAnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkpCgpkdXJfc3BfNENfZGYgPC0gYW51cmFuX3NyX2RmICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKGR1cl80Q19kaWZmX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihhcXVhdGljX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihhcmJvcmVhbF9zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lIAogIGRwbHlyOjpmdWxsX2pvaW4oZm9zc29yaWFsX3NyX2RmLCBieSA9IGMoIngiICwieSIpKSAlPiUgCiAgZHBseXI6OmZ1bGxfam9pbihncm91bmRfc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKHNlbWlfYXFfc3JfZGYsIGJ5ID0gYygieCIgLCJ5IikpICU+JSAKICBkcGx5cjo6ZnVsbF9qb2luKHN0cmVhbV9zcl9kZiwgYnkgPSBjKCJ4IiAsInkiKSkgJT4lCiAgZmlsdGVyKGRpZmZfNENfY2F0ICE9ICJOQSIgJiBzcGVjaWVzX24gIT0gIk5BIikKCmRhdGEuZnJhbWUoZHVyX3NwXzRDX2RmICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpncm91cF9ieShkaWZmXzRDX2NhdCkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnN1bW1hcmlzZShzcGVjaWVzX24gICA9IGxlbmd0aChzcGVjaWVzX25bIWlzLm5hKHNwZWNpZXNfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXF1YXRpY19uICAgPSBsZW5ndGgoYXF1YXRpY19uWyFpcy5uYShhcXVhdGljX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyYm9yZWFsX24gID0gbGVuZ3RoKGFyYm9yZWFsX25bIWlzLm5hKGFyYm9yZWFsX24pXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9uID0gbGVuZ3RoKGZvc3NvcmlhbF9uWyFpcy5uYShmb3Nzb3JpYWxfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdW5kX24gICAgPSBsZW5ndGgoZ3JvdW5kX25bIWlzLm5hKGdyb3VuZF9uKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW1pX2FxX24gICA9IGxlbmd0aChzZW1pX2FxX25bIWlzLm5hKHNlbWlfYXFfbildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtX24gICAgPSBsZW5ndGgoc3RyZWFtX25bIWlzLm5hKHN0cmVhbV9uKV0pKSkgJT4lCiAgZHBseXI6Om11dGF0ZShhbGxfZnJlcSAgICAgICA9IHNwZWNpZXNfbiAvIHN1bShzcGVjaWVzX24pICogMTAwLAogICAgICAgICAgICAgICAgYXF1YXRpY19mcmVxICAgPSBhcXVhdGljX24gLyBzdW0oYXF1YXRpY19uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGFyYm9yZWFsX2ZyZXEgID0gYXJib3JlYWxfbiAvIHN1bShhcmJvcmVhbF9uKSAqIDEwMCwKICAgICAgICAgICAgICAgIGZvc3NvcmlhbF9mcmVxID0gZm9zc29yaWFsX24gLyBzdW0oZm9zc29yaWFsX24pICogMTAwLAogICAgICAgICAgICAgICAgZ3JvdW5kX2ZyZXEgICAgPSBncm91bmRfbiAvIHN1bShncm91bmRfbikgKiAxMDAsCiAgICAgICAgICAgICAgICBzZW1pX2FxX2ZyZXEgICA9IHNlbWlfYXFfbiAvIHN1bShzZW1pX2FxX24pICogMTAwLAogICAgICAgICAgICAgICAgc3RyZWFtX2ZyZXEgICAgPSBzdHJlYW1fbiAvIHN1bShzdHJlYW1fbikgKiAxMDApICU+JQogIGRwbHlyOjpzZWxlY3QoYyhkaWZmXzRDX2NhdCwgYWxsX2ZyZXE6c3RyZWFtX2ZyZXEpKSAlPiUKICAga25pdHI6OmthYmxlKGNvbC5uYW1lcyA9IGMoIs6URHVyYXRpb24gKG1vbnRocykiLCAiQWxsICglKSIsICJBcXVhdGljICglKSIsICJBcmJvcmVhbCAoJSkiLCAiRm9zc29yaWFsICglKSIsICJHcm91bmQtZHdlbGxpbmcgKCUpIiwgIlNlbWktYXF1YXRpYyAoJSkiLCAiU3RyZWFtLWR3ZWxsaW5nICglKSIpLAogICAgICAgICAgICAgICAgZGlnaXRzID0gMikgIyAyIGRlY2ltYWwgcGxhY2VzCmBgYAoKKioqCgojIFN5c3RlbWF0aWMgc2VhcmNoIHstfSAKCiMjIEV4Y2x1c2lvbiBjcml0ZXJpYSB7LX0KCi0gU3R1ZGllcyB3aXRoIGxhbmd1YWdlcyB0aGF0IHdlcmUgbm90IHRyYW5zbGF0YWJsZSBvbiBHb29nbGUgVHJhbnNsYXRlLgotIERhdGEgZnJvbSBleHBlcmltZW50YWwgdHJlYXRtZW50cyBzdWNoIGFzIHBhdGhvZ2VuIGluZmVjdGlvbiwgcG9sbHV0YW50cyBvciBwZXN0aWNpZGUgY29udGFtaW5hbnRzLCBhbmQgcGhhcm1hY29sb2dpY2FsIG1hbmlwdWxhdGlvbiAoZS5nLiwgYW50aWRpdXJldGljIGhvcm1vbmVzKS4KLSBEYXRhIHByZXNlbnRlZCBhcyBwZXJjZW50YWdlIGNoYW5nZSBpbiBib2R5IHdlaWdodCB3aXRob3V0IHRoZSBpbml0aWFsIHdlaWdodC4KLSBEYXRhIHByZXNlbnQgd2l0aCBubyB0aW1lIGNvbXBvbmVudC4gRS5nLiBDaGFuZ2UgaW4gYm9keSB3ZWlnaHQgdW50aWwgMjAlIG9mIHdhdGVyIGxvc3Mgd2FzIHJlYWNoZWQgKCUgY2hhbmdlIGluIG1hc3MpLgotIFN0dWRpZXMgd2hlcmUgdW5pdHMgd2VyZSBub3QgcHJlc2VudGVkLgoKIyMgUHJlZmVycmVkIFJlcG9ydGluZyBJdGVtcyBmb3IgU3lzdGVtYXRpYyBSZXZpZXdzIGFuZCBNZXRhLUFuYWx5c2VzIHstfQoKVGhlIGZvbGxvd2luZyBCb29sZWFuIHNlYXJjaCBzdHJpbmcgZm9yIFdlYiBvZiBTY2llbmNlIChXb1MpOiAoZnJvZyBPUiB0b2FkIE9SIGFudXJcKikgQU5EICh3YXRlciBsb3NzIE9SIHdhdGVyIHVwdGFrZSBPUiBldmFwb3JhdGVcKiBPUiBza2luIHJlc2lzdFwqIE9SIGN1dGFuZW91cyBldmFwb1wqKSBBTkQgKGRlaHlkcmF0aW9uIE9SIGRlc2ljY2F0aW9uIE9SIHdhdGVyIE9SIHNvaWwgbW9pc3RcKikgTk9UICh0YWRwb2xlIE9SIGxhcnZhXCogT1IgbWljZSBPUiByYXQgT1IgcGxhbnQsIE9SIHNlZWQgT1IgZmlzaCkgYW5kIGZvciBTY29wdXM6IChUSVRMRS1BQlMtS0VZKGZyb2cgT1IgdG9hZCBPUiBhbnVyXCopICBBTkQgVElUTEUtQUJTLUtFWSh3YXRlciBBTkQgbG9zcyBPUiB3YXRlciBBTkQgdXB0YWtlIE9SIGV2YXBvcmF0ZVwqIE9SIHNraW4gQU5EIHJlc2lzdFwqIE9SIGN1dGFuZW91cyBBTkQgZXZhcG9cKikpIHdlcmUgcGVyZm9ybWVkIG9uIHRoZSAyMSBKdWx5IDIwMjIsIHJlc3VsdGluZyBpbiA0NDkgcmVjb3JkcyBmcm9tIDE5MzggdG8gMjAyMiBmcm9tIHRoZSBXb1MsIGFuZCA1MSByZWNvcmRzIGZyb20gMTk1MSB0byAyMDIyIGZyb20gU2NvcHVzLiBXZSBleGNsdWRlZCB0b3BpY3MgcmVsYXRlZCB0byBjaGVtaXN0cnksIHBoeXNpY2FsLCBtYXRlcmlhbHMgc2NpZW5jZSwgbWVkaWNhbCwgZ2VvbG9neSwgZmlzaGVyaWVzLCBvY2Vhbm9ncmFwaHksIGFuZCBlbmdpbmVlcmluZy4gVGl0bGUgYW5kIGFic3RyYWN0IHNjcmVlbmluZyBvZiB0aGUgc3lzdGVtYXRpYyBzZWFyY2ggd2FzIGNvbmR1Y3RlZCBpbiBbUmF5eWFuXShodHRwczovL3d3dy5yYXl5YW4uYWkvKSBbQE91enphbmkyMDE2XS4gRm9yd2FyZCBhbmQgYmFja3dhcmQgc2VhcmNoZXMgd2VyZSBhbHNvIGNvbmR1Y3RlZCBvbiBHb29nbGUgU2Nob2xhciB1bnRpbCB0aGUgMTV0aCBBdWd1c3QgMjAyMiAoKipGaWcuIFMzKiopIGZvciBhZGRpdGlvbmFsIHBhcGVycywgYW5kIHdlIGFsc28gc2VhcmNoZWQgZm9yIHBhcGVycyBmcm9tIEBGZWRlcjE5OTIsIEBMaWxseXdoaXRlMjAwNiwgYW5kIEBIaWxsbWFuMjAwOS4gTGFzdGx5LCBhZGRpdGlvbmFsIHN0dWRpZXMgKCpuKiA9IDMpIHdlcmUgcHJvdmlkZWQgYnkgdGhlIFN0ZWxsZW5ib3NjaCBVbml2ZXJzaXR5IGxpYnJhcmlhbiAoc2VhcmNoZWQgMXN0IEZlYnJ1YXJ5IDIwMjMpLgoKIVtdKEZpZyBTMyAtIFBSSVNNQSBkaWFncmFtLnBuZykKCioqRmlnLiBTMy4qKiBQUklTTUEgZmxvdyBkaWFncmFtIGZvciB0aGUgc3lzdGVtYXRpYyBkYXRhLWNvbGxlY3Rpb24gcHJvY2Vzcy4gKm4qID0gbnVtYmVyIG9mIHBhcGVycyByZW1haW5pbmcgYWZ0ZXIgZWFjaCBzdGFnZSBvZiBzZWxlY3Rpb24uICprKiBpcyB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucy9yZWNvcmRzLCBhbmQgKm4qIGluIHRoZSBsYXN0IHJvdyBpcyBudW1iZXIgb2Ygc3BlY2llcyBhZnRlciBwcm9jZXNzaW5nIGRhdGEuCgojIyMgRGVmaW5pdGlvbnMgey19CgpXZSBub3RlLCB0aGF0ICJ3YXRlci1wcm9vZiIgaXMgYSBzdWJqZWN0aXZlIHRlcm0sIGFuZCB0aGUgbWVjaGFuaXNtIGlzIG9ubHkgd2VsbCB1bmRlcnN0b29kIGZvciB0aGUgKlBoeWxsb21lZHVzYSogZ2VudXMgd2l0aCB0aGUgcHJlc2VuY2Ugb2Ygd2F4eSBzZWNyZXRpb24gb2YgY3V0YW5lb3VzIGxpcGlkcywgYW5kIHRoZSBzdGVyZW90eXBpY2FsIHdpcGluZyBiZWhhdmlvdXIgW0BCbGF5bG9jazE5NzY7IEBHb21lejIwMDZdLiBPdGhlciBhcmJvcmVhbCBzcGVjaWVzIHNob3cgZHJ5IG11Y3VzIGZpbG0gb24gdGhlIHNraW4gb3IgdGhlIHByZXNlbmNlIG9mIGN1dGFuZW91cyBzdXJmYWNlIGZsdWlkIHRoYXQgbWF5IGNvbnRyaWJ1dGUgdG8gaGlnaCBza2luIHJlc2lzdGFuY2UgW0BLb2JlbHQxOTg2XS4gV2UgbGFiZWxsZWQgZnJvZ3MgYXMgIndhdGVyLXByb29mIiBiYXNlZCBvbiBlYWNoIHN0dWR5J3MgZGVmaW5pdGlvbiwgaS5lLiwgaWYgdGhlIGF1dGhvcnMgZGVzY3JpYmUgdGhlIHNwZWNpZXMgYXMgIndhdGVyLXByb29mIi4gSG93ZXZlciwgbm90IGFsbCAid2F0ZXItcHJvb2YiIGZyb2dzIGV4Y3JldGUgd2F0ZXItcHJvb2Ygc2VjcmV0aW9ucyB0aHJvdWdob3V0IHRoZSB5ZWFyLCBhbmQgbWF5IG9ubHkgc2hvdyB0aGlzIGFkYXB0YXRpb24gZHVyaW5nIGNlcnRhaW4gcGVyaW9kcyBzdWNoIGFzIHRoZSBkcnkgc2Vhc29uIChSLiBQLiBCb3ZvLCBwZXJzLiBjb21tLikuIAoKQW5vdGhlciBwb3N0LWhvYyBkZWZpbml0aW9uIGZvciBjbGFzc2lmeWluZyB3YXRlci1wcm9vZiBpcyB3aGV0aGVyIHRoZSBza2luIHJlc2lzdGFuY2UgaXMgYWJvdmUgYSBjZXJ0YWluIHRocmVzaG9sZC4gQEhpbGxtYW4yMDA5IGRlZmluZWQgYW51cmFucyBhcyBtb2RlcmF0ZWx5IHdhdGVyLXByb29mIHdpdGggc2tpbiByZXNpc3RhbmNlIGJldHdlZW4gMiB0byAyMCBzIGNtXi0xXiwgYW5kIGhpZ2hseSB3YXRlci1wcm9vZiB3aXRoIHNraW4gcmVzaXN0YW5jZSA+MjAgcyBjbV4tMV4uIEhvd2V2ZXIsIGV2ZW4gd2l0aGluIHN0dWRpZXMsIHRoZSBzYW1lIHNwZWNpZXMgd2lsbCBzaG93IGRpZmZlcmVudCBza2luIHJlc2lzdGFuY2UgZGVwZW5kaW5nIG9uIHRoZSBlbnZpcm9ubWVudGFsIGV4cG9zdXJlLiBlLmcuIGxvd2VyIHNraW4gcmVzaXN0YW5jZSBhdCBoaWdoZXIgdGVtcGVyYXR1cmUgW0BCdXR0ZW1lcjIwMDNdLiBXZSBpbmNsdWRlZCBib3RoIGRlZmluaXRpb25zIGluIHRoZSByYXcgZGF0YSBmaWxlLCBidXQgd2UgdXNlZCB0aGUgcHJpb3IgZGVmaW5pdGlvbiBmb3IgYW5hbHlzaXMuCgpFV0wgbWVhc3VyZW1lbnRzIGxhYmVsbGVkIHdpdGggImNvY29vbiIgaXMgc3RyYWlnaHQtZm9yd2FyZC4gQ29jb29uIGlzIHRoZSBwcmVzZW5jZSBvZiBhY2N1bXVsYXRlZCBlcGlkZXJtYWwgbGF5ZXJzIGluIGFlc3RpdmF0aW5nIGFudXJhbnMuIEVXTCBtZWFzdXJlbWVudHMgbGFiZWxsZWQgd2l0aCAiaG9sbG93IiB3ZXJlIGNvbmR1Y3RlZCB3aXRoIGZyb2dzIGluIGFuIGFydGlmaWNpYWwgaG9sbG93IHNoZWx0ZXIgcHJvdGVjdGluZyB0aGUgZnJvZyBmcm9tIHRoZSBleHBvc2VkIGFpci4KCkFudXJhbnMgY2FuIGFsc28gY2hhbmdlIEVXTCBhY3Jvc3MgdGhlIG1lYXN1cmVtZW50IHBlcmlvZCAoaS5lLiBkZWNyZWFzZSBpbiBFV0wgYXMgdGhleSBiZWNvbWUgbW9yZSBkZWh5ZHJhdGVkKS4gSG93ZXZlciwgbW9zdCBzdHVkaWVzIGVpdGhlciB0b29rIGFuIGF2ZXJhZ2UgdmFsdWUgb3ZlciB0aGUgZXhwZXJpbWVudCBkdXJhdGlvbiwgb3IgcHJlc2VudGVkIHRoZSBmaXJzdCBob3VyIG9mIG1lYXN1cmVtZW50cy4gV2hlbiBzdHVkaWVzIHByb3ZpZGVkIGNoYW5nZSBpbiBFV0wgYXQgZGlmZmVyZW50IHRpbWUgcG9pbnRzLCB3ZSB0b29rIHRoZSBmaXJzdCBob3VyIEVXTCBtZWFzdXJlbWVudHMuIE5vdGUsIGFsbW9zdCBhbGwgYW5pbWFscyB3ZXJlIGNvbnNpZGVyZWQgZnVsbHkgaHlkcmF0ZWQgZHVyaW5nIHRoZSBzdGFydCBvZiB0aGUgRVdMIGV4cGVyaW1lbnQsIHdoZXJlIHRoZXkgd2VyZSBzdWJtZXJzZWQgb3IgcHJvdmlkZWQgd2F0ZXIgcHJpb3IgdG8gdGhlIEVXTCBleHBlcmltZW50cy4gCgojIyBVbnB1Ymxpc2hlZCBkYXRhIHstfQoKQWRkaXRpb25hbCBFV0wsICRyX2kkLCBhbmQgV1UgZGF0YSB3ZXJlIG9idGFpbmVkIGZyb20gdW5wdWJsaXNoZWQgc291cmNlcy4gVGhlICpBdGVsb3B1cyBjYXJyaWtlcmkqIGRhdGEgaXMgYXZhaWxhYmxlIG9uIGFuIG9ubGluZSByZXBvc2l0b3J5IChbU29sYW5vICYgQWxiZXJ0LCAyMDAwXShodHRwczovL2RhdGEubWVuZGVsZXkuY29tL2RhdGFzZXRzLzRjNW5rcHJ6Y3kvMSkpLCBhbmQgdGhlICpUaG9yb3BhIG1pbGlhcmlzKiBkYXRhIGNhbiBiZSBvYnRhaW5lZCBmcm9tIEMuIE5hdmFzIChuYXZhc0B1c3AuYnIpIHVwb24gcmVxdWVzdC4KCkJyaWVmbHksIHRoZSBtZXRob2QgZm9yICpBdGVsb3B1cyBjYXJyaWtlcmkqIGlzIGRlc2NyaWJlZCBiZWxvdzoKCjE1ICpBdGVsb3B1cyBjYXJyaWtlcmkqIHdlcmUgY29sbGVjdGVkIG5lYXIgdGhlIGJhc2luIG9mIFBpY28gQ3Jpc3TDsmJhbCBDb2zDsm4gKDEwwrA1NCcwNS44Ik4gNzPCsDU1JzAwLjciVykgYW5kIGJyb3VnaHQgYmFjayB0byB0aGUgVW5pdmVyc2lkYWQgZGVsIE1hZ2RhbGVuYSBjYW1wdXMuIFRvIGVzdGltYXRlIGV2YXBvcmF0aXZlIHdhdGVyIGxvc3MsIGZ1bGx5IGh5ZHJhdGVkIGluZGl2aWR1YWxzIHdlcmUgYnJpZWZseSBkcmllZCB3aXRoIGFic29yYmVudCBwYXBlciBhbmQgdGhlIHVyaW5lIHdhcyByZW1vdmVkIGJ5IGxpZ2h0bHkgcHJlc3NpbmcgdGhlaXIgYWJkb21lbiBhbmQgd2VpZ2hlZCB0byBvYnRhaW4gdGhlIGluaXRpYWwgd2VpZ2h0LiBFYWNoIGluZGl2aWR1YWwgd2FzIHBsYWNlZCBpbiBhIHdpbmQgdHVubmVsIGF0IDIuNCBzIGNtXi0xXiwgYW5kIHdlaWdoZWQgZXZlcnkgZml2ZSBtaW51dGUgdW50aWwgaW5kaXZpZHVhbHMgcmVhY2hlZCA3MC02NSUgb2YgdGhlaXIgaW5pdGlhbCB3ZWlnaHQgW0BUaXRvbjIwMTBdLiBUaGUgcmF0ZSBvZiBFV0wgd2FzIGNhbGN1bGF0ZWQgZnJvbSB0aGUgdmFsdWUgb2YgdGhlIHJlZ3Jlc3Npb24gb2YgdGhlIHdlaWdodCBsb3N0IG92ZXIgdGltZSBhbmQgZXhwcmVzc2VkIGluIG1nIG1pbl4tMV4uIEVXTCBjb3JyZWN0ZWQgZm9yIHN1cmZhY2UgYXJlYSB3YXMgY2FsY3VsYXRlZCBieSBkaXZpZGluZyBieSAyLzMgb2YgdGhlIHRvdGFsIHN1cmZhY2UgYXJlYSB3aGljaCBjb3JyZXNwb25kcyB0byB0aGUgcmVnaW9uIG9mIHRoZSBib2R5IGluIGNvbnRhY3Qgd2l0aCB0aGUgYWlyIGZsb3cgKG1nIGNtXi0yXiBtaW5eLTFeKSBbQFdpdGhlcnMxOTgyOyBAVGl0b24yMDEwOyBAVGl0b24yMDE1XS4gCgpUbyBlc3RpbWF0ZSByYXRlIG9mIFdVLCBJbmRpdmlkdWFscyB3aGVyZSBwbGFjZWQgaW4gY29udGFpbmVycyB3aXRoIGFic29yYmVudCB0b3dlbHMgbW9pc3RlbmVkIHdpdGggZW5vdWdoIHdhdGVyIHRvIGNvdmVyIHRoZSB2ZW50cmFsIHJlZ2lvbiBhZnRlciB0aGUgRVdMIGV4cGVyaW1lbnQuIFRoZSBpbmRpdmlkdWFscyB3ZXJlIGRyaWVkIGFuZCB3ZWlnaGVkIGV2ZXJ5IGZvdXIgbWludXRlcyBmb3Igc2l4IGNvbnNlY3V0aXZlIHRpbWVzIFtAVGl0b24yMDEwOyBAQW5kZXJzb24yMDE3XS4gVGhlIFdVIHJhdGUgcGVyIGFyZWEgd2FzIGNhbGN1bGF0ZWQgZnJvbSB0aGUgdmFsdWUgb2YgdGhlIHJlZ3Jlc3Npb24gb2YgdGhlIGJvZHkgd2VpZ2h0IGdhaW5lZCBhcyBhIGZ1bmN0aW9uIG9mIHRpbWUgKG1nIG1pbl4tMV4pLCBhbmQgaW4gdHVybiBkaXZpZGVkIGJ5IDEvMyBvZiB0aGUgdG90YWwgc3VyZmFjZSBhcmVhIHRoYXQgY29ycmVzcG9uZHMgdG8gdGhlIHZlbnRyYWwgYXJlYSBpbiBjb250YWN0IHdpdGggd2F0ZXIgZHVyaW5nIGFic29ycHRpb24sIHRoZSB2YWx1ZXMgd2VyZSBleHByZXNzZWQgaW4gdW5pdHMgb2YgbWcgY21eLTJeIG1pbl4tMV4uIEFsbCBleHBlcmltZW50cyB3ZXJlIGNvbmR1Y3RlZCBhdCBhbiBhdmVyYWdlIGFpciB0ZW1wZXJhdHVyZSBvZiAyNS41NSDCsSAwLjI4wrBDLiBUaGUgcmVsYXRpdmUgaHVtaWRpdHkgd2FzIG5vdCBtZWFzdXJlZCBidXQgYXBwcm94aW1hdGVkIGJhc2VkIG9uIHRoZSBsb2NhdGlvbiBhbmQgdGltZSBvZiB0aGUgZXhwZXJpbWVudCAoUi4gU29sYW5vIHBlcnMuIGNvbW0uKQoKVGhlIG1ldGhvZCBmb3IgKlRob3JvcGEgbWlsaWFyaXMqIGlzIGRlc2NyaWJlZCBiZWxvdzoKCjE0ICpUaG9yb3BhIG1pbGlhcmlzKiB3ZXJlIGNvbGxlY3RlZCBhcm91bmQgVWJhdHViYSAoYXBwcm94aW1hdGUgbG9jYXRpb24gMjPCsDI24oCyMTPigLNTIDQ1wrAwNOKAsjA44oCzVyksIGFuZCAxNSBpbmRpdmlkdWFscyB3ZXJlIGNvbGxlY3RlZCBpbiB0aGUgU2VycmEgZG8gTWFyIFN0YXRlIFBhcmssIFBpY2luZ3VhYmEgTnVjbGV1cyAoYXBwcm94aW1hdGUgbG9jYXRpb24gMjPCsDI34oCZNTDigJ1TIHRvIDIzwrAxNeKAmTAw4oCdUyBhbmQgNDXCsDE14oCZMDDigJ1XIHRvIDQ0wrA0M+KAmTMw4oCdVykuIEFuaW1hbHMgd2VyZSBicm91Z2h0IGJhY2sgdG8gdGhlIFVuaXZlcnNpdHkgb2YgU8OjbyBQYXVsbyBjYW1wdXMgYW5kIGtlcHQgaW5kaXZpZHVhbGx5IGluIHBsYXN0aWMgZW5jbG9zdXJlcyAoMTcgeCAxOCB4IDEwNyBjbSkgZm9yIDUtNyBkYXlzIHByaW9yIHRvIGVzdGltYXRpbmcgRVdMLiBBbmltYWxzIHdlcmUgZmVkIGNhcHRpdmUgY29ja3JvYWNoZXMgKCpOYXVwaG9ldGEgY2luw6lyZWEqKSB0d2ljZSBhIHdlZWsgYW5kIHdlcmUgcHJvdmlkZWQgZnJlc2ggd2F0ZXIgYWQgbGliaXR1bSAodGFwIHdhdGVyKSBpbiBhIHBsYXN0aWMgY3VwLiBUbyBlc3RpbWF0ZSBFV0wsIGZ1bGx5IGh5ZHJhdGVkIGluZGl2aWR1YWxzIHdlcmUgYnJpZWZseSBkcmllZCB3aXRoIGFic29yYmVudCBwYXBlciBhbmQgdGhlIHVyaW5lIHdhcyByZW1vdmVkIGJ5IGxpZ2h0bHkgcHJlc3NpbmcgdGhlaXIgYWJkb21lbiBhbmQgd2VpZ2hlZCB0byBvYnRhaW4gdGhlIGluaXRpYWwgd2VpZ2h0LiBFYWNoIGluZGl2aWR1YWwgd2FzIHBsYWNlZCBpbiBhIHdpbmQgdHVubmVsIGF0IDIzNSBzIGNtXi0xXiwgYW5kIHdlaWdoZWQgZXZlcnkgZml2ZSBtaW51dGUgdW50aWwgaW5kaXZpZHVhbHMgcmVhY2hlZCA5MCUgb2YgdGhlaXIgaW5pdGlhbCB3ZWlnaHQgb3IgdGhlIGFuaW1hbCBkaWQgbm90IHJlZ2FpbiBwb3N0dXJlIHdoZW4gdHVybmVkIG92ZXIuIEVhY2ggaW5kaXZpZHVhbCBtZWFzdXJlbWVudCB3YXMgcmVwbGljYXRlZCB0d2ljZSBvdmVyIHRoZSAoMyBkYXlzIGluIGJldHdlZW4gbWVhc3VyZW1lbnRzKSBhbmQgYXZlcmFnZWQuIFRoZSByYXRlIG9mIEVXTCBmcm9tIHRoZSBhdmVyYWdlIHZhbHVlcyB3YXMgY2FsY3VsYXRlZCBhbmQgcHJlc2VudGVkIGFzIGluIG1nIGheLTFeLiBFV0wgY29ycmVjdGVkIGZvciBzdXJmYWNlIGFyZWEgd2FzIGNhbGN1bGF0ZWQgYnkgZGl2aWRpbmcgYnkgMi8zIG9mIHRoZSB0b3RhbCBzdXJmYWNlIGFyZWEgd2hpY2ggY29ycmVzcG9uZHMgdG8gdGhlIHJlZ2lvbiBvZiB0aGUgYm9keSBpbiBjb250YWN0IHdpdGggdGhlIGFpciBmbG93IChtZyBjbV4tMl4gbWluXi0xXikuIFRoZSBleHBlcmltZW50IHdhcyBjb25kdWN0ZWQgYXQgYW4gYWlyIHRlbXBlcmF0dXJlIGJldHdlZW4gMjItMjXCsEMgYXQgYSByZWxhdGl2ZSBodW1pZGl0eSBvZiA1MC02MCUuCgpEYXRhIHByb3ZpZGVkIGJ5IFIuIFBhcmVsbGkgQm92byAocnBib3ZvQGdtYWlsLmNvbSkgd2FzIG9yaWdpbmFsbHkgdXNlZCBmb3IgYSBzZXBhcmF0ZSBwYXBlciB3aGljaCBpcyBjdXJyZW50bHkgaW4gZGV2ZWxvcG1lbnQuIEhvd2V2ZXIsIGhlIGhhcyBraW5kbHkgb2ZmZXJlZCB0byBwcm92aWRlIHRoZSBkYXRhIGZvciB0aGlzIHN0dWR5IHByZS1zdWJtaXNzaW9uLiBUaGUgc3BlY2llcyB0aGF0IHdlcmUgY29sbGVjdGVkIGJ5IFIuIFBhcmVsbGkgQm92byBhcmUgcHJvdmlkZWQgYmVsb3c6CgotICpBZGVub21lcmEgbWFybW9yYXRhKgotICpBbWVlcmVnYSBmbGF2b3BpY3RhKgotICpBcGxhc3RvZGlzY3VzIGxldWNvcHlnaXVzKgotICpCb2FuYSBwYXJkYWxpcyoKLSAqQm9hbmEgcmFuaWNlcHMqCi0gKkJva2VybWFubm9oeWxhIGFsdmFyZW5nYWkqCi0gKkJva2VybWFubm9oeWxhIGNpcmN1bWRhdGEqCi0gKkJva2VybWFubm9oeWxhIHNheGljb2xhKgotICpCcmFjaHljZXBoYWx1cyBwaXRhbmdhKgotICpEZW5kcm9wc29waHVzIG1pY3JvcHMqCi0gKkRlbmRyb3Bzb3BodXMgc2FuYm9ybmkqCi0gKkRlcm1hdG9ub3R1cyBtdWVsbGVyaSoKLSAqRWxhY2hpc3RvY2xlaXMgY2VzYXJpaSoKLSAqSGFkZGFkdXMgYmlub3RhdHVzKgotICpJc2Nobm9jbmVtYSBndWVudGhlcmkqCi0gKklzY2hub2NuZW1hIHBhcnZhKgotICpMZXB0b2RhY3R5bHVzIGZ1c2N1cyoKLSAqTGVwdG9kYWN0eWx1cyBzeXBoYXgqCi0gKk9kb250b3BocnludXMgYW1lcmljYW51cyoKLSAqUGh5bGxvbWVkdXNhIG1lZ2FjZXBoYWxhKgotICpQaHlzYWxhZW11cyBhdGxhbnRpY3VzKgotICpQaHlzYWxhZW11cyBvbGZlcnNpaSoKLSAqUGl0aGVjb3B1cyBhenVyZWFlKgotICpQcm9jZXJhdG9waHJ5cyBhcHBlbmRpY3VsYXRhKgotICpQcm9jZXJhdG9waHJ5cyBjdXJ1cnUqCi0gKlJoaW5lbGxhIGRpcHR5Y2hhKgotICpSaGluZWxsYSBvcm5hdGEqCi0gKlJoaW5lbGxhIHJ1YmVzY2VucyoKLSAqU2NpbmF4IGZ1c2NvdmFyaXVzKgotICpUcmFjaHljZXBoYWx1cyBtZXNvcGhhZXVzKgoKQWR1bHRzIHdlcmUgY29sbGVjdGVkIGFsb25nIGVsZXZhdGlvbmFsIGdyYWRpZW50cyBmcm9tIHNlYSBsZXZlbCB0byAxLDYwMCBtIGEucy5sIGluIEJyYXppbOKAmXMgQXRsYW50aWMgRm9yZXN0IGFuZCBDZXJyYWRvIGR1cmluZyB3YXJtL3dldCBzZWFzb25zIChTZXB0ZW1iZXIgdG8gRmVicnVhcnkgb2YgMjAxMeKAkzIwMTcpLiBBbmltYWxzIHdlcmUgdHJhbnNwb3J0ZWQgdG8gdGhlIGxhYm9yYXRvcnkgKDYxMyBtOiAtMjIuMzk3MzMxwrAgUywgNDcuNTQ3Nzk5wrAgVykuIEFsbCBhbmltYWxzIHdlcmUga2VwdCBpbmRpdmlkdWFsbHkgaW4gcGxhc3RpYyB0ZXJyYXJpYSwgd2l0aCBzaGVsdGVyIGFuZCB0YXAgd2F0ZXIgYWQgbGliaXR1bSwgdW5kZXIgbmF0dXJhbCB0aGVybWFsL2h1bWlkaXR5IHJlZ2ltZXMgKGRhaWx5IHRlbXBlcmF0dXJlIHJhbmdlIG9mIDIy4oCTMjcgwrBDLCBhaXIgaHVtaWRpdHkgb2YgNDXigJM2NSUpIGFuZCBwaG90b3BlcmlvZCAobGlnaHQvZGFyayBjeWNsZXMgMTMuNToxMC41KS4KCk1lYXN1cmVtZW50cyB3ZXJlIHRha2VuIG9uY2UgZm9yIGVhY2ggaW5kaXZpZHVhbCwgaW4gdGhlIGZvbGxvd2luZyBzZXF1ZW5jZTogRVdMIGFuZCBXVSB3aXRoaW4gMy01IGRheXMgYWZ0ZXIgZmllbGQgY29sbGVjdGlvbi4gQW5pbWFscyB3ZXJlIG5vdCBmZWQgYXMgdGhlIG1lYXN1cmVtZW50cyB3ZXJlIHRha2VuIGluIGEgZmFzdGVkIHN0YXRlLiBCZWZvcmUgYW5kIGFmdGVyIGFueSBleHBlcmltZW50YWwgcnVuLCBhbmltYWxzIHdlcmUgY2hlY2tlZCBmb3IgbW90b3IgY29vcmRpbmF0aW9uLCBza2luIGNvbG9yLCBwb3N0dXJlLCBhbmQgcmVzcG9uc2l2ZW5lc3MuIFdoZW4gaW5kaXZpZHVhbHMgZmFpbGVkIHRoZXNlIGNoZWNrcywgdGhleSB3ZXJlIG5vdCBpbmNsdWRlIGluIHRoZSBkYXRhc2V0IGFuZCBzdWJzZXF1ZW50IGFuYWx5c2VzLgoKRVdMIGFuZCBXVSBleHBlcmltZW50cyB3ZXJlIGNvbmR1Y3RlZCBmb2xsb3dpbmcgQEFuZGVyc29uMjAxNywgQEdvdXZlaWEyMDE5LCBhbmQgQEJvdm8yMDIzLiBCcmllZmx5LCBhbmltYWxz4oCZIHRlbXBlcmF0dXJlIGFuZCBoeWRyYXRpb24gc3RhdGUgd2VyZSBzdGFuZGFyZGlzZWQgYmVmb3JlIHRoZSB0cmlhbHMgYnkgaG9sZGluZyBlYWNoIGFtcGhpYmlhbiBpbiBpbmRpdmlkdWFsIFBWQyBjb250YWluZXJzLCBmaWxsZWQgd2l0aCAwLjUgY20gKGJvZHkgc2l6ZXMgPCA1IGcpIG9yIDEgY20gb2Ygd2F0ZXIgKGJvZHkgc2l6ZXMgPiA1IGcpLCBhbmQgcGxhY2VkIGluc2lkZSBhIGNsaW1hdGUtY29udHJvbGxlZCBpbmN1YmF0b3IgKDEyMkZDIG1vZGVsIC0gRWxldHJvbGFiKSBhdCAyNSDCsEMgZm9yIDEgaC4gVG8gb2J0YWluIHRoZSBpbml0aWFsIHN0YW5kYXJkaXNlZCBib2R5IG1hc3MgKDEwMCUgaHlkcmF0ZWQpLCBmcm9ncyB3ZXJlIGdlbnRseSBkcmllZCB3aXRoIGFic29yYmVudCBwYXBlciBhbmQgdGhlaXIgYWJkb21lbiB3ZXJlIGxpZ2h0bHkgcHJlc3NlZCB0byByZW1vdmUgdXJpbmUgZnJvbSB0aGVpciB1cmluYXJ5IGJsYWRkZXIuIFRoZW4sIGZyb2dzIHdlcmUgaW5kaXZpZHVhbGx5IHBsYWNlZCBpbiBQVkMgY29udGFpbmVycyAoMSwwMDAgbWwpIGFuZCBFV0wgcmF0ZXMgd2VyZSBtZWFzdXJlZCBpbiBhIHR5cGljYWwgb3Blbi1mbG93IHN5c3RlbSBhdCAyNSDCsEMsIGNvbnRhaW5pbmcgYSBtYXNzIGZsb3cgbWV0ZXIgKFNTLTMgU3Vic2FtcGxlciwgU2FibGUgU3lzdGVtcykgc3VwcGx5aW5nIGEgc3RhYmxlIGFpcmZsb3cgYXQgMjEuNjYgY21eM14gc14tMV4gKDEsMzAwIG1sIG1pbl4tMV4pLCBhIFJIL0Rld3BvaW50IENvbnRyb2xsZXIgKERHLTQsIFNhYmxlIFN5c3RlbXMpIHN0YW5kYXJkaXppbmcgdGhlIGluY3VycmVudCByZWxhdGl2ZSBodW1pZGl0eSBhdCAzMCUsIGFuZCBhIHdhdGVyIHZhcG9yIGFuYWx5emVyIChSSC0zMDAgUkgvRGV3cG9pbnQgQW5hbHl6ZXIsIFNhYmxlIFN5c3RlbXMpIHF1YW50aWZ5aW5nIGluY3VycmVudCBhbmQgZXhjdXJyZW50IGFpci4gQWxsIGVxdWlwbWVudCB3YXMgaW50ZXJmYWNlZCB0byBhIGNvbXB1dGVyIGJ5IGFuIGFuYWxvZy9kaWdpdGFsIHVuaXQgKFVJMiwgU2FibGUgU3lzdGVtcykgdG8gcmVjb3JkIGNoYW5nZXMgaW4gYWlyZmxvdyBhbmQgd2F0ZXIgdmFwb3IgZGVuc2l0eSAoV1ZEKSBldmVyeSAxLjAgc2Vjb25kLiBTa2luIGJvZHkgdGVtcGVyYXR1cmVzIHdlcmUgdGFrZW4gYXQgdGhlIGVuZCBvZiB0aGUgZXhwZXJpbWVudHMsIHR5cGljYWxseSAzMC00MCBtaW4gZm9yIGZyb2dzIDwgNSBnIGFuZCA2MCBtaW4gZm9yIGZyb2dzID4gNSBnLCBmb3IgcXVhbnRpZmljYXRpb24gb2YgdGhlIFdWRCBhdCBzYXR1cmF0aW9uIGF0IHRoZSBldmFwb3JhdGluZyAoc2tpbikgc3VyZmFjZS4gVG8gcXVhbnRpZnkgdGhlIEVXTCByYXRlcywgdGhlIHdhdGVyIHZhcG9yIGRlbnNpdHkgZGVmaWNpdCB3YXMgY2FsY3VsYXRlZCBieSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGFuIGVtcHR5IGNvbnRhaW5lciBhbmQgb25lIGNvbnRhaW5pbmcgdGhlIGFuaW1hbCAoU3BvdGlsYSBhbmQgQmVybWFuIDE5NzYpLiBUaGVuLCB0b3RhbCB0cmFuc2VwaXRoZWxpYWwgRVdMIHdhcyBjb3JyZWN0ZWQgZm9yIHVuaXQgYXJlYSBvZiBleHBvc2VkIHNraW4gc3VyZmFjZSAoMi8zIG9mIHRoZSB0b3RhbCBzdXJmYWNlOyBATWNDbGFuYWhhbjE5NjkpIGFuZCBleHByZXNzZWQgYXMgbWFzcyBvZiB3YXRlciBwZXIgZXhwb3NlZCBzdXJmYWNlIGFyZWEgcGVyIHRpbWUgKGUuZy4gzrxnIEh+Mn5PIGNtXuKIkjJeIHNe4oiSMV4pLiBUbyBtaW5pbWl6ZSB0aGUgYW5pbWFs4oCZcyBhY3Rpdml0eSBkdXJpbmcgRVdMIG1lYXN1cmVtZW50cywgZXhwZXJpbWVudHMgd2VyZSBwZXJmb3JtZWQgZHVyaW5nIHRoZSBkYXkgKG9wcG9zaXRlIHRvIHRoZWlyIG5hdHVyYWwgYWN0aXZlIHBlcmlvZCkgd2l0aCBjaGFtYmVycyBpbiB0aGUgZGFyay4gVG8gZGV0ZWN0IGFueSBzaWduaWZpY2FudCBjaGFuZ2VzIGluIGJlaGF2aW9yIGFuZCBwb3N0dXJlIHRoYXQgY291bGQgYWZmZWN0IHRoZSByZWNvcmRzLCBpbmRpdmlkdWFscyB3ZXJlIG9mdGVuIHZpc3VhbGx5IGluc3BlY3RlZCBkdXJpbmcgdHJpYWxzLiBEYXRhIHdlcmUgZGlzY2FyZGVkIGlmIGFuIGFuaW1hbCB1cmluYXRlZCBkdXJpbmcgdGhlIGV4cGVyaW1lbnQuCgpJbW1lZGlhdGVseSBhZnRlciB0aGUgRVdMIHRyaWFscywgd2hlcmUgYW5pbWFscyB1c3VhbGx5IGxvc3QgOTgtNzAgJSBvZiB0aGVpciBpbml0aWFsIGJvZHkgbWFzc2VzIChzZWUgZGF0YXNldCksIGVhY2ggaW5kaXZpZHVhbCB3YXMgcGxhY2VkIGluIGEgY29udGFpbmVyIChhIFBldHJpIGRpc2ggZm9yIGJvZHkgc2l6ZXMgc21hbGxlciB0aGFuIDUgZywgb3IgYSBjaXJjdWxhciBQVkMgY29udGFpbmVyIGZvciBib2R5IHNpemVzIGxhcmdlciB0aGFuIDUgZykgZmlsbGVkIHdpdGggdGFwIHdhdGVyIGF0IGEgZGVwdGggc3VmZmljaWVudCB0byBjb3ZlciB0aGVpciB2ZW50cmFsIHJlZ2lvbi4gQW5pbWFscyB3ZXJlIHRha2VuIGZyb20gdGhlIGNvbnRhaW5lciBhbmQgY2FyZWZ1bGx5IGJsb3R0ZWQgd2l0aCBwYXBlciB0aXNzdWUgYW5kIHdlaWdoZWQgKMKxIDAuMDAwMSBnIG9yIDAuMDEgZykgZXZlcnkgMiBtaW51dGVzIGZvciBzaXggY29uc2VjdXRpdmUgdGltZXMgaW4gYSByb29tIGF0IDI1IMKwQy4gV1UgcmF0ZXMgd2VyZSBjYWxjdWxhdGVkIGZyb20gdGhlIGxpbmVhciByZWdyZXNzaW9uIGJldHdlZW4gYm9keSBtYXNzIGluY3JlbWVudHMgYWdhaW5zdCB0aW1lLiBUaGVuLCB1c2luZyB0aGUgZXN0aW1hdGVkIHN1cmZhY2UgYXJlYSBpbiBjb250YWN0IHdpdGggd2F0ZXIgKDEvMyBvZiB0aGUgdG90YWwgc3VyZmFjZSwgQE1jQ2xhbmFoYW4xOTY5KSwgdGhlIFdVIHJhdGUgd2FzIGNhbGN1bGF0ZWQgYW5kIGV4cHJlc3NlZCBwZXIgdW5pdCBhcmVhIChlLmcuIM68ZyBIfjJ+TyBjbV7iiJIyXiBzXuKIkjFeKS4KCkRhdGEgZm9yICpCcmV2aWNlcHMgbW9udGFudXMqIHByb3ZpZGVkIGJ5IFMuIENsdXNlbGxhLVRydWxsYXMgKHNjdDMzM0BzdW4uYWMuemEpIHdpbGwgYmUgdXNlZCBmb3IgYSBtYW51c2NyaXB0IHRoYXQgaXMgY3VycmVudGx5IGluIHN1Ym1pc3Npb24uIEhvd2V2ZXIsIHNoZSBoYXMga2luZGx5IG9mZmVyZWQgdG8gcHJvdmlkZSB0aGUgZGF0YSBmb3IgdGhpcyBzdHVkeSBwcmUtc3VibWlzc2lvbi4KClRoZSByYXcgZGF0YSwgaW5jbHVkaW5nIGNvbGxlY3Rpb24gc2l0ZXMsIGFyZSBwcm92aWRlZCBvbiBbR2l0SHViXShodHRwczovL2dpdGh1Yi5jb20vbmljaG9sYXN3dW56L2dsb2JhbC1mcm9nLWRyb3VnaHQvdHJlZS9tYWluL2RhdGEpLgoKKioqCgojIyBDYWxjdWxhdGlvbnMgYW5kIGNvbnZlcnNpb25zIHstfQoKIyMjIEV2YXBvcmF0aXZlIHdhdGVyIGxvc3Mgey19ClRoZSByZWxhdGl2ZSBza2luIHJlc2lzdGFuY2UsICRyX2kkLCBpcyBjYWxjdWxhdGVkIGFzOiAKClxiZWdpbntlcXVhdGlvbn0Kcl9pID0gcl90IC0gcl9iLAooXCNlcTpyZXN0KQpcZW5ke2VxdWF0aW9ufQoKd2hlcmUgJHJfdCQgaXMgdGhlIHRvdGFsIHJlc2lzdGFuY2UgKHMgY21eLTFeKSBhbmQgJHJfYiQgaXMgdGhlIGJvdW5kYXJ5IGxheWVyIHJlc2lzdGFuY2UgYmFzZWQgb24gYW4gZXF1aXZhbGVudCBhZ2FyIG1vZGVsIChzIGNtXi0xXikgb3IgaHlwb3RoZXRpY2FsIGJpb3BoeXNpY2FsIG1vZGVsIFxAcmVmKGVxOnJiKS4gJHJfdCQgaXMgY2FsY3VsYXRlZCBmb2xsb3dpbmcgQFNwb3RpbGExOTc2IGFuZCBASGlsbG1hbjIwMDk6CgpcYmVnaW57ZXF1YXRpb259CnJfdCA9IFxmcmFje1xyaG99e1x0ZXh0cm17Q1dMfX0gPSAoXHJob197dltza2luXX0gLSBccmhvX3YgXHRpbWVzIFx0ZXh0cm17Ukh9X3tbZXhjdXJyZW50XX0pIFx0aW1lcyBcdGV4dHJte0NXTH0sCihcI2VxOnRyZXN0KQpcZW5ke2VxdWF0aW9ufQoKd2hlcmUgJFxyaG8kIGlzIHRoZSB2YXBvdXIgZGVuc2l0eSBncmFkaWVudCBhdCB0aGUgc3VyZmFjZSBvZiB0aGUgYW5pbWFsIChnIGNtXi0zXiksICRcdGV4dHJte0NXTH0kIGlzIHRoZSBjdXRhbmVvdXMgcmF0ZXMgb2YgZXZhcG9yYXRpdmUgd2F0ZXIgbG9zcyAoJFx0ZXh0cm17RVdMfSQpIGJ5IHN1cmZhY2UgYXJlYSAoZyBzXi0xXiBjbV4tMl4pLCAkXHJob192JCBpcyB0aGUgd2F0ZXIgdmFwb3VyIGRlbnNpdHkgb2Ygd2F0ZXItc2F0dXJhdGVkIGFpciAoZyBjbV4tM14pLCAkXHJob197dltza2luXX0kIGlzIHRoZSAkXHJob192JCBhdCB0aGUgc2tpbiBzdXJmYWNlLCBhbmQgJFx0ZXh0cm17Ukh9JCBpcyB0aGUgZnJhY3Rpb25hbCBzYXR1cmF0aW9uICgwLTEpLiAkXHJobyQgaXMgY2FsY3VsYXRlZCBhcyB0aGUgZGlmZmVyZW5jZSBpbiB0aGUgd2F0ZXIgdmFwb3VyIGRlbnNpdHkgYXQgdGhlIHRlbXBlcmF0dXJlIG9mIHRoZSBldmFwb3JhdGluZyBzdXJmYWNlIGJ5IHRoZSB3YXRlciB2YXBvdXIgZGVuc2l0eSBpbiB0aGUgYWlyIGF0ICRcdGV4dHJte1JIfSQgYXMgZnJhY3Rpb25hbCBzYXR1cmF0aW9uIFtARmVkZXIxOTkyXS4KCiRcdGV4dHJte0VXTH0kIChnIHNeLTFeKSBjYW4gYmUgbWVhc3VyZWQgZ3JhdmltZXRyaWNhbGx5IChjaGFuZ2UgaW4gbWFzcyBvdmVyIHRpbWUpIG9yIGNoYW5nZXMgaW4gd2F0ZXIgdmFwb3VyIHByZXNzdXJlLCAkZSQgKGtQYSksIG9yICRcdGV4dHJte1JIfSQgYmV0d2VlbiB0aGUgaW5jdXJyZW50IGFuZCBleGN1cnJlbnQgYWlyIGZvciBhIGZsb3ctdGhyb3VnaCBzeXN0ZW0uIEluIGEgZmxvdy10aHJvdWdoIHN5c3RlbSwgJFx0ZXh0cm17RVdMfSQgY2FuIGJlIGNhbGN1bGF0ZWQgZnJvbSBASGlsbG1hbjIwMDkgYW5kIEBSaWRkZWxsMjAxNzoKClxiZWdpbntlcXVhdGlvbn0KXHRleHRybXtFV0x9ID0gXGZyYWN7ZX17VCBcdGltZXMgUl92fSBcdGltZXMgXHRleHRybXtGUn0gPSBbKFxyaG9fdiBcdGltZXMgXHRleHRybXtSSH1fe1tpbmN1cnJlbnRdfSkgLSAoXHJob192IFx0aW1lcyBcdGV4dHJte1JIfV97W2V4Y3VycmVudF19KV0gXHRpbWVzIFx0ZXh0cm17RlJ9LAooXCNlcTpld2wpClxlbmR7ZXF1YXRpb259Cgp3aGVyZSAkVCQgaXMgdGVtcGVyYXR1cmUgaW4gS2VsdmluIChLKSwgICRSX3YkIGlzIHRoZSBnYXMgY29uc3RhbnQgZm9yIHdhdGVyIHZhcG9yICg0NjEuNSBKIEteLTFeIGtnXi0xXiksIGFuZCAkXHRleHRybXtGUn0kIGlzIHRoZSBmbG93IHJhdGUgKG1sIHNeLTFeKQoKIyMjIEJvdW5kYXJ5IGxheWVyIHJlc2lzdGFuY2Ugey19ClRoZSBib3VuZGFyeSBsYXllciByZXNpc3RhbmNlIGlzIHRoZSBsYXllciBvZiBhaXIgaW4gd2hpY2ggYW4gb2JqZWN0IChvciBvcmdhbmlzbSkgZXhjaGFuZ2VzIGhlYXQgYW5kIG1hc3Mgd2l0aCBpdHMgc3Vycm91bmRpbmcgZW52aXJvbm1lbnQuIFRoZSBib3VuZGFyeSBsYXllciBhZGRzIHRvIHRoZSByZXNpc3RhbmNlIG9mIHdhdGVyIGxvc3MgYnkgY2hhbmdpbmcgdGhlIHBoeXNpY2FsIGNvbmRpdGlvbnMgb2YgdGhlIG1pY3JvY2xpbWF0ZSBhcm91bmQgdGhlIG9yZ2FuaXNtIFtAU2VuemFubzIwMjJdLiBJZiAkcl9iJCB3YXMgbm90IHJlcG9ydGVkIG9yIG5vdCBlc3RpbWF0ZWQgYnkgYSByZXByZXNlbnRhdGl2ZSBhZ2FyIG1vZGVsLCB3ZSB1c2VkIHRoZSB0aGVvcmV0aWNhbCAkcl9iJCB3aXRoIGtub3duIGZvcmNlZCBjb252ZWN0aW9uICgkViQpIGZyb20gQFJpZGRlbGwyMDE3OiAKClxiZWdpbntlcXVhdGlvbn0Kcl9iID0gXGZyYWN7MC45MyBcdGltZXMgXHJobyBcdGltZXMgQ197XHJob319e2hfY30sCihcI2VxOnJiKQpcZW5ke2VxdWF0aW9ufQoKd2hlcmUsICRccmhvJCAgaXMgdGhlIGRlbnNpdHkgb2YgdGhlIGFpciAoa2cgbV4tM14pLCAkQ197XHJob30kIGlzIHRoZSBzcGVjaWZpYyBoZWF0IG9mIGFpciAoa2deLTFeIEteLTFeKSBjYWxjdWxhdGVkIGFzOgoKXGJlZ2lue2VxdWF0aW9ufQpDX3tccmhvfSA9IFxmcmFjezEwMDQuODQgKyAoMTg0Ni40MCBcdGltZXMgcl93KX17MSArIHJfd30sCihcI2VxOmNwKQpcZW5ke2VxdWF0aW9ufQoKd2hlcmUgJHJfdyQgaXMgbWl4aW5nIHJhdGlvIG9mIHdhdGVyIHZhcG91ciBbQFRyYWN5MjAxOV0gZXN0aW1hdGVkIHVzaW5nOgoKXGJlZ2lue2VxdWF0aW9ufQpyX3cgPSBcZnJhY3swLjYyMTk3IFx0aW1lcyAxLjAwNTMgXHRpbWVzIGV9e3AgLSAxLjAwNTMgXHRpbWVzIGV9LAooXCNlcTpydykKXGVuZHtlcXVhdGlvbn0KCndoZXJlICRlJCBpcyB0aGUgdmFwb3VyIHByZXNzdXJlIChrUGEpIGFuZCAkcCQgaXMgdGhlIGF0bW9zcGhlcmljIHByZXNzdXJlIChrUGEpLiAkaF9jJCBcQHJlZihlcTpyYikgaXMgdGhlIGNvZWZmaWNpZW50IG9mIGNvbnZlY3RpdmUtaGVhdCB0cmFuc2ZlciB1bmRlciBmb3JjZWQgY29udmVjdGlvbiBhcHByb3hpbWF0ZWQgYnk6CgpcYmVnaW57ZXF1YXRpb259CmhfYyA9IDAuMDkyMyhWXnswLjAzMzN9IFx0aW1lcyBEXnstMC42NjZ9KSwKKFwjZXE6aGMpClxlbmR7ZXF1YXRpb259Cgp3aGVyZSAkViQgaXMgdGhlIHdpbmQgc3BlZWQgKG0gc14tMV4pIGFuZCAkRCQgaXMgdGhlIGNoYXJhY3RlcmlzdGljIGRpbWVuc2lvbiAobSkuICREJCBpcyB0aGUgY3Jvc3Mtc2VjdGlvbmFsIHJhZGl1cywgYXNzdW1pbmcgdGhlIGRpbWVuc2lvbnMgb2YgYSBzcGhlcmUgZm9yIGEgZnJvZywgYmFzZWQgb24gdGhlIG1hc3MgYW5kIHRoZSB0b3RhbCBzdXJmYWNlIGFyZWEuCgpJZiB0aGUgc3R1ZHkgd2FzIGNvbmR1Y3RlZCB1bmRlciBmcmVlIGNvbnZlY3Rpb24sIHdlIHVzZWQgYSBtb2RpZmllZCBcQHJlZihlcTpoYykgZnJvbSBAUmlkZGVsbDIwMTc6CgpcYmVnaW57ZXF1YXRpb259CmhfYyA9IFxmcmFjezAuNDggXHRpbWVzIFx0ZXh0cm17R3J9XnswLjI1fSBcdGltZXMga317RH0sCihcI2VxOmhjZnJlZSkKXGVuZHtlcXVhdGlvbn0KCndoZXJlICRcdGV4dHJte0dyfSQgaXMgdGhlIEdyYXNob2YgbnVtYmVyLCAkayQgaXMgdGhlIHRoZXJtYWwgY29uZHVjdGl2aXR5IG9mIHRoZSBmbHVpZCAoVyBtXi0xXiBLXi0xXikgJEQkIGlzIHRoZSBjaGFyYWN0ZXJpc3RpYyBkaW1lbnNpb24gKG0pLiAkXHRleHRybXtHcn0kIGRlc2NyaWJlcyB0aGUgcmVsYXRpdmUgc3RyZW5ndGggb2YgdGhlIGJ1b3lhbnQgZm9yY2VzIHRvIHZpc2NvdXMgZm9yY2Ugb2YgdGhlIGFpciBzdXJyb3VuZGluZyB0aGUgb2JqZWN0IGNhbGN1bGF0ZWQgYXM6CgpcYmVnaW57ZXF1YXRpb259Clx0ZXh0cm17R3J9ID0gXGZyYWN7ZyBcdGltZXMgXGJldGEgXHRpbWVzIFxEZWx0YXtUfSBcdGltZXMgRF57M319e3ZeezJ9fSwKKFwjZXE6Z3IpClxlbmR7ZXF1YXRpb259Cgp3aGVyZSAkZyQgaXMgdGhlIGFjY2VsZXJhdGlvbiBieSBncmF2aXR5ICg5LjgwIG0gc14tMl4pLCAkXGJldGEkIGlzIHRoZSBjb2VmZmljaWVudCBvZiB2b2x1bWV0cmljIGV4cGFuc2lvbiAoMy42NyAkXHRpbWVzJCAxMF4tM14gwrBDXi0xXiksICREJCBpcyB0aGUgY2hhcmFjdGVyaXN0aWMgZGltZW5zaW9uLCAkdiQgaXMgdGhlIGtpbmVtYXRpYyB2aXNjb3NpdHkgZnJvbSBAUmlkZGVsbDIwMTcsIGFuZCAkXERlbHRhe1R9JCBpcyBlc3RpbWF0ZWQgYnk6CgpcYmVnaW57ZXF1YXRpb259ClxEZWx0YXtUfSA9IFRfMCgxKzAuMzggXHRpbWVzIGVfMCAvIHApIC0gVCgxKzAuMzggXHRpbWVzIGUvcCksCihcI2VxOmRlbHRhKQpcZW5ke2VxdWF0aW9ufQoKd2hlcmUgJFRfMCQgaXMgdGhlIHRlbXBlcmF0dXJlIChLKSBvZiB0aGUgc3VyZmFjZSwgJGVfMCQgaXMgdGhlIHdhdGVyIHZhcG91ciBwcmVzc3VyZSBkaXJlY3RseSBhYm92ZSB0aGUgc3VyZmFjZSwgYW5kICRwJCBpcyB0aGUgYXRtb3NwaGVyaWMgcHJlc3N1cmUgW0BNb250aWV0aDIwMTNdLiAKCiMjIyBWYXBvdXIgcHJlc3N1cmUgZGVmaWNpdCB7LX0KVGhlIHZhcG91ciBwcmVzc3VyZSBkZWZpY2l0IChWUEQpIHdhcyBjYWxjdWxhdGVkIGFzOgoKXGJlZ2lue2VxdWF0aW9ufQpWUEQgPSBlX3MgLSBlX2EsCihcI2VxOnZwZCkKXGVuZHtlcXVhdGlvbn0KCndoZXJlICRlX3MkIGlzIHRoZSBzYXR1cmF0aW9uIHZhcG91ciBwcmVzc3VyZSAoa1BhKSBhdCBhIGdpdmVuIHRlbXBlcmF0dXJlIGFuZCAkZV9hJCBpcyB0aGUgYWN0dWFsIHZhcG91ciBwcmVzc3VyZSBpbiB0aGUgYWlyIChrUGEpLiAkZV9zJCB3YXMgY2FsY3VsYXRlZCB1c2luZyB0aGUgQ2xhdXNpdXMtQ2xhcGV5cm9uIGVxdWF0aW9uIEBTdHVsbDIwMDA6CgpcYmVnaW57ZXF1YXRpb259CmVfcyA9IGVfMCBcdGltZXMgXGV4cCBcbGVmdFtcZnJhY3tMfXtSX3Z9IFxsZWZ0KCBcZnJhY3sxfXtUXzB9IC0gXGZyYWN7MX17VH0gXHJpZ2h0KSBccmlnaHRdLAooXCNlcTplcykKXGVuZHtlcXVhdGlvbn0KCndoZXJlICRlXzAkID0gMC42MTEga1BhIGFuZCAkVF8wJCDigJMgMjczIEsgYXJlIGNvbnN0YW50IHBhcmFtZXRlcnMsIGFuZCAkUl92JCDigJMgNDYxLjUgSiBLXi0xXiBLZ14tMV4gYW5kICRMJCA9IDIuNSB4IDEwNiBKIGtnXi0xXiBhcmUgZ2FzIGNvbnN0YW50IGZvciB3YXRlciB2YXBvdXIgYW5kIHRoZSBsYXRlbnQgaGVhdCBvZiB2YXBvdXJpemF0aW9uLCByZXNwZWN0aXZlbHkuICAkVCQgKGFzIEspIGlzIHRoZSBhY3R1YWwgdGVtcGVyYXR1cmUgbWVhc3VyZWQuICRlX2EkIHdhcyBhcHByb3hpbWF0ZWQgYXM6CgpcYmVnaW57ZXF1YXRpb259CmVfYSA9IFxmcmFje1x0ZXh0cm17Ukh9IFx0aW1lcyBlX3N9ezEwMH0sCihcI2VxOmVhKQpcZW5ke2VxdWF0aW9ufQoKd2hlcmUgJFx0ZXh0cm17Ukh9JCBpcyB0aGUgbWVhc3VyZWQgcmVsYXRpdmUgaHVtaWRpdHkgKCUpLgoKIyMjIFN1cmZhY2UgYXJlYSB7LX0KRm9yIHN0dWRpZXMgdGhhdCBwcmVzZW50ZWQgRVdMIGFuZCBXVSB3aXRob3V0IGNvcnJlY3RpbmcgZm9yIHN1cmZhY2UgYXJlYSwgd2UgY29ycmVjdGVkIHRvIHN1cmZhY2UgYXJlYSBieSBkaXZpZGluZyB0aGUgYWJzb2x1dGUgcmF0ZXMgYnkgMi8zIG9mIHRoZSB0b3RhbCBzdXJmYWNlIGFyZWEgZm9yIEVXTCwgd2hpY2ggY29ycmVzcG9uZHMgdG8gdGhlIGFyZWEgZXhwb3NlZCB0byBhaXIgd2hlbiBhbnVyYW5zIGtlZXAgdGhlIHdhdGVyIGNvbnNlcnZhdGlvbiBwb3N0dXJlIFtAV2l0aGVyczE5ODI7IEBXaXRoZXJzMTk4NF0uIEZvciBXVSwgd2UgY29ycmVjdGVkIHRvIHN1cmZhY2UgYXJlYSBieSBkaXZpZGluZyB0aGUgYWJzb2x1dGUgcmF0ZXMgYnkgMS8zIG9mIHRoZSB0b3RhbCBzdXJmYWNlIGFyZWEgYmVjYXVzZSBXVSBwcmltYXJpbHkgb2NjdXJzIGluIHRoZSBwZWx2aWMgJ3NlYXQgcGF0Y2gnIHJlZ2lvbiBvZiB0aGUgdmVudHJhbCBza2luIFtAQmFsZHdpbjE5NzQ7IEBNY0NsYW5haGFuMTk2OTsgQFdpbGx1bXNlbjIwMDddLiBUb3RhbCBzdXJmYWNlIGFyZWEgKGNtXjJeKSB3YXMgZXN0aW1hdGVkIHZpYSBmYW1pbHktc3BlY2lmaWMgbWFzcy1zdXJmYWNlIGFyZWEgc2NhbGluZyByZWxhdGlvbnNoaXAgZnJvbSBAS2xlaW4yMDE2OgoKXGJlZ2lue2VxdWF0aW9ufQpTQSA9IFxiZXRhXzAgTV57XGJldGFfMX0sCihcI2VxOnNhKQpcZW5ke2VxdWF0aW9ufQoKd2hlcmUgJFxiZXRhXzAkIGlzIHRoZSBpbnRlcmNlcHQsICRNJCBpcyB0aGUgYW5pbWFsIGJvZHkgbWFzcyAoZyksIGFuZCAkXGJldGFfMSQgaXMgdGhlIHNsb3BlLiBJZiB0aGUgZmFtaWx5LXNwZWNpZmljIG1hc3Mtc3VyZmFjZSBhcmVhIHNjYWxpbmcgcmVsYXRpb25zaGlwIHdhcyBub3QgcHJlc2VudGVkLCB3ZSB1c2VkIHRoZSBwb3dlciBlcXVhdGlvbiBmb3IgYWxsIEFudXJhICg5Ljg1MzckTSReMC42NzQ1XikgYXMgYSBjb25zZXJ2YXRpdmUgZXN0aW1hdGUuCgojIyMgUGVyY2VudGFnZSBtYXNzIGNoYW5nZSB0byBhY3R1YWwgbWFzcyBjaGFuZ2Ugey19CgpGb3Igc3R1ZGllcyB0aGF0IHByZXNlbnRlZCAlIGNoYW5nZSBpbiBtYXNzICgkXERlbHRhIE0kKSB3aXRoIHJhdyBkYXRhIGF2YWlsYWJsZSBvbiBpbml0aWFsIG1hc3MsIHdlIGNvbnZlcnRlZCBwZXJjZW50YWdlIGNoYW5nZSBpbiBtYXNzICglIGheLTFeKSBiYWNrIHRvIGFic29sdXRlIG1hc3MgY2hhbmdlIChnIGheLTFeKSBmb2xsb3dpbmc6IAoKXGJlZ2lue2VxdWF0aW9ufQpcdGV4dHJte0VXTH0gPSBNIFx0aW1lcyBcbGVmdChcZnJhY3tcRGVsdGEgTX17MTAwfVxyaWdodCksCihcI2VxOmV3bHBlcikKXGVuZHtlcXVhdGlvbn0KCndoZXJlICRNJCBpcyB0aGUgaW5pdGlhbCBib2R5IG1hc3MgKGcpLCBhbmQgJFxEZWx0YSBNJCBpcyB0aGUgcGVyY2VudGFnZSBjaGFuZ2UgaW4gbWFzcyAoJSBoXi0xXikuIE5vdGUsIHN0dWRpZXMgd2l0aCAlIGNoYW5nZSBpbiBib2R5IG1hc3Mgd2l0aG91dCB0aGUgaW5pdGlhbCBib2R5IG1hc3MgcHJlc2VudGVkIHdlcmUgbm90IGluY2x1ZGVkIGluIHRoZSBkYXRhIGV4dHJhY3Rpb24uCgoqKioKCiMgRGF0YXNldCB7LX0KCkxvYWQgYW5kIGNsZWFuIHRoZSByYXcgZGF0YXNldCBgcmF3X2RhdGEuY3N2YC4KCmBgYHtyIGNsZWFuLCBtZXNzYWdlPUZBTFNFfQojIExvYWQgYW5kIGNsZWFuIHJhdyBkYXRhCnJhd19kYXQgPC0gcmVhZC5jc3YoZmlsZS5wYXRoKGRhdGFfcGF0aCwgInJhd19kYXRhLmNzdiIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KHN0dWR5X0lEOnVuaXQsIHJfc19lc3QsIGNhbGN1bGF0ZWQpICU+JQogIGRwbHlyOjptdXRhdGUoZWNvdHlwZSAgPSBmYWN0b3IoZWNvdHlwZSksCiAgICAgICAgIGZhbWlseSAgID0gZmFjdG9yKGZhbWlseSksCiAgICAgICAgIG9yaWdpbiAgID0gZmFjdG9yKG9yaWdpbiksCiAgICAgICAgIHN0cmF0ZWd5ID0gZmFjdG9yKGNhc2Vfd2hlbihzdHJhdGVneSA9PSAiIiB+ICJub25lIiwgVFJVRSB+IGFzLmNoYXJhY3RlcihzdHJhdGVneSkpKSwKICAgICAgICAgc3RyYXRlZ3kgPSBmY3RfcmVsZXZlbChzdHJhdGVneSwgIm5vbmUiLCAid2F0ZXItcHJvb2YiLCAiY29jb29uIiwgImhvbGxvdyIpLAogICAgICAgICB0cmFpdCAgICA9IGZhY3Rvcih0cmFpdCksCiAgICAgICAgIHJlc3BvbnNlID0gZmFjdG9yKHJlc3BvbnNlKSwKICAgICAgICAgbG5NYXNzICAgPSBsb2cobWVhbl9tYXNzX2cpLAogICAgICAgICBsbkZsb3cgICA9IGxvZyhhaXJmbG93X2NtX3MgKyAxKSwKICAgICAgICAgZXNfa1BhICAgPSBpZmVsc2UodHJhaXQgPT0gIndhdGVyIGxvc3MiLCAwLjYxMSAqIGV4cCgyNTAwMDAwIC8gNDYxLjUgKiAoMSAvIDI3MyAtIDEgLyAodHJ0X3RlbXAgKyAyNzMuMTUpKSksIE5BKSwgIyBzYXR1cmF0aW9uIHZhcG9yIHByZXNzdXJlIChrUGEpIGF0IGEgZ2l2ZW4gdGVtcGVyYXR1cmUKICAgICAgICAgZWFfa1BhICAgPSBpZmVsc2UodHJhaXQgPT0gIndhdGVyIGxvc3MiLCBSSF9wZXJjICogZXNfa1BhIC8gMTAwLCBOQSksICMgYWN0dWFsIHZhcG9yIHByZXNzdXJlIChrUGEpCiAgICAgICAgIFZQRF9rUGEgID0gZXNfa1BhIC0gZWFfa1BhLAogICAgICAgICBsblZQRCAgICA9IGxvZyhWUERfa1BhKSkgJT4lCiAgZHBseXI6OmZpbHRlcihzcGVjaWVzX3BoeWxvICE9ICIiKSAjIHJlbW92ZSByb3dzIHdpdGggbm8gc3BlY2llcwoKZXdsX2RhdCA8LSByYXdfZGF0ICU+JQogIGRwbHlyOjpmaWx0ZXIocmVzcG9uc2UgPT0gImV2YXBvcmF0aXZlIHdhdGVyIGxvc3MiICYgIWlzLm5hKHVuaXRfY29ycmVjdGVkX21lYW4pKSAlPiUKICBkcGx5cjo6bXV0YXRlKG1nX2hfbWVhbiA9IHVuaXRfY29ycmVjdGVkX21lYW4gKiBkb3JzX1NBX2NtMiwKICAgICAgICAgICAgICAgIG1nX2hfc2QgICA9IHVuaXRfY29ycmVjdGVkX3NkICogZG9yc19TQV9jbTIsICAgIAogICAgICAgICAgICAgICAgbG5NZWFuICAgID0gbG9nKG1nX2hfbWVhbiksCiAgICAgICAgICAgICAgICB2ICAgICAgICAgPSBtZ19oX3NkXjIgLyBzYW1wbGVfc2l6ZSwgIyBzYW1wbGluZyB2YXJpYW5jZSAodikKICAgICAgICAgICAgICAgIHNlaSAgICAgICA9IHNxcnQodiksICMgc3RhbmRhcmQgZXJyb3IgKFNFKQogICAgICAgICAgICAgICAgaW52ICAgICAgID0gMSAvIHNlaSwgIyBwcmVjaXNpb24gKGludmVyc2Ugb2YgU0UpICkKICAgICAgICAgICAgICAgIHcgICAgICAgICA9IDEgLyB2LCAjIHdlaWdodCAoaW52ZXJzZSBvZiB2YXJpYW5jZSkgCiAgICAgICAgICAgICAgICBoXzcwICAgICAgPSAobWVhbl9tYXNzX2cgLSAobWVhbl9tYXNzX2cgKiAwLjcpKSAvIChtZ19oX21lYW4gKiAwLjAwMSkpIAoKcmVzaXN0X2RhdCA8LSByYXdfZGF0ICU+JQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKHJfc19lc3QpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGxuTWVhbiA9IGxvZyhyX3NfZXN0ICsgMSkpCgp3dV9kYXQgPC0gcmF3X2RhdCAlPiUKICBkcGx5cjo6ZmlsdGVyKHRyYWl0ID09ICJ3YXRlciBnYWluIiAmICFpcy5uYSh1bml0X2NvcnJlY3RlZF9tZWFuKSkgJT4lCiAgZHBseXI6Om11dGF0ZShtZ19oX21lYW4gPSB1bml0X2NvcnJlY3RlZF9tZWFuICogdmVudF9TQV9jbTIsCiAgICAgICAgICAgICAgICBtZ19oX3NkICAgPSB1bml0X2NvcnJlY3RlZF9zZCAqIHZlbnRfU0FfY20yLAogICAgICAgICAgICAgICAgbG5NZWFuICAgID0gbG9nKG1nX2hfbWVhbiksCiAgICAgICAgICAgICAgICB2ICAgICAgICAgPSBtZ19oX3NkXjIgLyBzYW1wbGVfc2l6ZSwgIyBzYW1wbGluZyB2YXJpYW5jZSAodikKICAgICAgICAgICAgICAgIHNlaSAgICAgICA9IHNxcnQodiksICMgc3RhbmRhcmQgZXJyb3IgKFNFKQogICAgICAgICAgICAgICAgaW52ICAgICAgID0gMSAvIHNlaSkgIyBwcmVjaXNpb24gKGludmVyc2Ugb2YgU0UpCgojZXdsX2RhdCAlPiUKICAjZ3JvdXBfYnkoc3RyYXRlZ3kpICU+JQogICNzdW1tYXJpc2UobWVhbiA9IG1lYW4oaF83MCwgbmEucm0gPSBUUlVFKSkKYGBgCgpUaGVyZSBhcmUgYHIgbGVuZ3RoKHVuaXF1ZShld2xfZGF0JHNwZWNpZXNfcGh5bG8pKWAgc3BlY2llcyB3aXRoIGRhdGEgb24gZXZhcG9yYXRpdmUgd2F0ZXIgbG9zcyAoYHIgbGVuZ3RoKHVuaXF1ZShld2xfZGF0JHN0dWR5X0lEKSlgIHN0dWRpZXMpLCBgciBsZW5ndGgodW5pcXVlKHJlc2lzdF9kYXQkc3BlY2llc19waHlsbykpYCBzcGVjaWVzIHdpdGggc2tpbiByZXNpc3RhbmNlIGRhdGEgKGByIGxlbmd0aCh1bmlxdWUocmVzaXN0X2RhdCRzdHVkeV9JRCkpYCBzdHVkaWVzKSwgYW5kIGByIGxlbmd0aCh1bmlxdWUod3VfZGF0JHNwZWNpZXNfcGh5bG8pKWAgc3BlY2llcyB3aXRoIHdhdGVyIHVwdGFrZSBkYXRhIChgciBsZW5ndGgodW5pcXVlKHd1X2RhdCRzdHVkeV9JRCkpYCBzdHVkaWVzKS4gV2UgdXNlZCB0aGUgZXZhcG9yYXRpdmUgd2F0ZXIgbG9zcyB0byBhbmFseXNlIGRpZmZlcmVuY2VzIGJldHdlZW4gZWNvdHlwZSBhcyB0aGVyZSBhcmUgbW9yZSBzcGVjaWVzIHJlcHJlc2VudGVkIGNvbXBhcmVkIHRvIHRoZSBza2luIHJlc2lzdGFuY2UgZGF0YS4gVGhlcmUgd2VyZSB0aHJlZSBzcGVjaWVzIHRoYXQgd2VyZSBleGNsdWRlZCBmcm9tIHRoZSBhbmFseXNpcyBiZWNhdXNlIHRoZXkgd2VyZSBub3QgbGlzdGVkIGluIHRoZSBJVUNOIFJlZCBMaXN0IGFuZCB3ZXJlIG5vdCBwcmVzZW50IGluIHRoZSBwaHlsb2dlbmV0aWMgdHJlZSBmcm9tIEBKZXR6MjAxODogKkJyYWNoeWNlcGhhbHVzIHBpdGFuZ2EqLCAqRWxhY2hpc3RvY2xlaXMgY2VzYXJpaSosIGFuZCAqTGVwdG9kYWN0eWx1cyBsdWN0YXRvciouCgojIyBHZW9ncmFwaGljYWwgYmlhcyBpbiBoeWRyb3JlZ3VsYXRpb24gc3R1ZGllcyB7LX0KCmBgYHtyIEZpZyBTNCwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTcsIGVjaG8gPSBGQUxTRX0Kd2lsZF9kYXQgPC0gcmF3X2RhdCAlPiUgZHBseXI6OmZpbHRlcihvcmlnaW4gPT0gIndpbGQiKQpsYWJfZGF0ICA8LSByYXdfZGF0ICU+JSBkcGx5cjo6ZmlsdGVyKG9yaWdpbiA9PSAibGFiIikKCndvcmxkX21hcCA8LSBtYXBfZGF0YSgid29ybGQiKQpyYXdfZGF0ICU+JQogIGdncGxvdCgpICsKICBnZW9tX21hcChkYXRhID0gd29ybGRfbWFwICU+JSBkcGx5cjo6ZmlsdGVyKHJlZ2lvbiAhPSAiQW50YXJjdGljYSIpLCBtYXAgPSB3b3JsZF9tYXAsIGFlcyhsb25nLCBsYXQsIG1hcF9pZCA9IHJlZ2lvbiksIGZpbGwgPSAiI2RlZGVkZSIsIGNvbG91ciA9IE5BKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGxvbiwgeSA9IGxhdCksIHNoYXBlID0gMjEsIGZpbGwgPSAid2hpdGUiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lX3ZvaWQoKSArIAogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQoKQpgYGAKCioqRmlnLiBTNC4qKiBTcGF0aWFsIGRpc3RyaWJ1dGlvbiBvZiBoeWRyb3JlZ3VsYXRpb24gc3R1ZGllcyB1c2luZyB3aWxkIGNhdWdodCBhbnVyYW5zIChzdHVkeSAqbiogPSBgciBsZW5ndGgodW5pcXVlKHdpbGRfZGF0JHN0dWR5X0lEKSlgKS4gYHIgbGVuZ3RoKHVuaXF1ZShsYWJfZGF0JHN0dWR5X0lEKSlgIHN0dWRpZXMgdXNlZCBjYXB0aXZlIHJhaXNlZCBhbnVyYW5zLiBUaGVyZSBhcmUgbGFyZ2UgcmVnaW9ucyBhcm91bmQgY2VudHJhbCBBZnJpY2EgYW5kIEV1cmFzaWEgd2l0aCBoaWdoIGFtcGhpYmlhbiBkaXZlcnNpdHksIGJ1dCBubyBoeWRyb2xvZ2ljYWwgc3R1ZGllcyBjb25kdWN0ZWQgKCoqRmlnLiAxYioqKS4gCgoqKioKCiMjIFByZXBhcmUgcGh5bG9nZW55IGZvciBhbmFseXNpcyB7LX0KClRoZSBwaHlsb2dlbnkgd2FzIG9idGFpbmVkIGZyb20gQEpldHoyMDE4IGNvbXByaXNpbmcgb2YgNywyMzggc3BlY2llcy4gVGhlIHRyZWUgd2FzIHBydW5lZCB0byBtYXRjaCB0aGUgYHIgbGVuZ3RoKHVuaXF1ZShyYXdfZGF0JHNwZWNpZXNfcGh5bG8pKWAgc3BlY2llcyBleHRyYWN0ZWQgZm9yIHRoZSBzdWJzZXF1ZW50IGFuYWx5c2lzLgoKYGBge3IgcGh5bG8sIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9ImhpZGUifQojIExvYWQgdHJlZQpwaHlsb190cmVlIDwtIGFwZTo6cmVhZC50cmVlKGZpbGUucGF0aChkYXRhX3BhdGgsICJhbXBoX3NobF9uZXdfQ29uc2Vuc3VzXzcyMzgudHJlIikpCgojIFBydW5pbmcgZGF0YSBhbmQgcGh5bG9nZW55CnRyZWVfdGlwX2xhYmVsIDwtIHBoeWxvX3RyZWUkdGlwLmxhYmVsICMgZXh0cmFjdCB0cmVlIHRpcCBuYW1lcwpzcF9saXN0ICAgICAgICA8LSByYXdfZGF0JHNwZWNpZXNfcGh5bG8gIyBleHRyYWN0IHNwZWNpZXMgbmFtZSBmcm9tIG1lYW4gZGF0YQpwcnVuZWRfdHJlZSAgICA8LSBhcGU6OmRyb3AudGlwKHBoeWxvX3RyZWUsIHNldGRpZmYocGh5bG9fdHJlZSR0aXAubGFiZWwsIHNwX2xpc3QpKSAjIHBydW5lIHBoeWxvX3RyZWUgdG8ga2VlcCBzcGVjaWVzIGZyb20gdGhlIHJhdyBkYXRhCnBydW5lZF90cmVlICAgIDwtIHBoeXRvb2xzOjpmb3JjZS51bHRyYW1ldHJpYyhwcnVuZWRfdHJlZSwgbWV0aG9kID0gImV4dGVuZCIpICMgdWx0cmFtZXRyaWNpemUgdGhlIHRyZWUKcGh5bG9fY29yICAgICAgPC0gdmN2KHBydW5lZF90cmVlLCBjb3IgPSBUKQoKc2V0ZGlmZihyYXdfZGF0JHNwZWNpZXNfcGh5bG8sIHJvd25hbWVzKHBoeWxvX2NvcikpCnNldGRpZmYocm93bmFtZXMocGh5bG9fY29yKSwgcmF3X2RhdCRzcGVjaWVzX3BoeWxvKQoKI2FwZTo6aXMudWx0cmFtZXRyaWMocHJ1bmVkX3RyZWUpCmBgYAoKIyBBbmFseXNpcyB7LX0KClRoZSBvcmlnaW5hbCBtb2RlbCBpbmNvcnBvcmF0ZWQgb3JpZ2luIChsYWItcmFpc2VkIG9yIHdpbGQtY2F1Z2h0KSBhbmQgd2hldGhlciB0aGUgYmxhZGRlciB3YXMgdm9pZCBvZiB1cmluZSBwcmlvciB0byB0aGUgZXhwZXJpbWVudC4gSG93ZXZlciwgdGhlIG1vZGVsJ3MgYnVsayBlZmZlY3RpdmUgc2FtcGxlcyBzaXplIChFU1MpIHdhcyB0b28gbG93LCBpbmRpY2F0aW5nIHBvc3RlcmlvciBtZWFucyBhbmQgbWVkaWFucyBtYXkgYmUgdW5yZWxpYWJsZS4gU2luY2Ugb3JpZ2luIGFuZCB3aGV0aGVyIHRoZSBibGFkZGVyIHdhcyBlbXB0aWVkIGRpZCBub3QgaW5mbHVlbmNlICRyX2kkLCB0aGV5IHdlcmUgZXhjbHVkZWQgaW4gdGhlIGZpbmFsIG1vZGVsLiBGb3IgdHJhbnNwYXJlbmN5LCBvbiBhdmVyYWdlLCB3aWxkLWNhdWdodCBhbnVyYW5zIGhhZCwgb24gYXZlcmFnZSwgaGlnaGVyICRyX2kkIHJlbGF0aXZlIHRvIGxhYi1yYWlzZWQgYW51cmFucyAoMC4wOCBbLTAuNDc6MC4zMV0pLCBhbmQgYW51cmFucyB3aXRoIHRoZWlyIGJsYWRkZXIgdm9pZGVkIG9mIHVyaW5lIGhhZCBoaWdoZXIgJHJfaSQgKDAuMTcgWy0wLjU5OiAwLjI1XSkuIEhvd2V2ZXIgdGhlcmUgaXMgc3Vic3RhbnRpYWwgdmFyaWFiaWxpdHkgYmV0d2VlbiB0aGUgd2lsZC1jYXVnaHQgYW5kIGxhYi1yYWlzZWQgZ3JvdXBzLCBhbmQgd2hldGhlciBhbnVyYW5zIHdpdGggdGhlaXIgYmxhZGRlciB2b2lkZWQgb3Igbm90LgoKYGBge3IgYW5hbHlzaXMsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUUsIHJlc3VsdHM9ImhpZGUifQojb3B0aW9ucyhicm1zLmJhY2tlbmQgPSAiY21kc3RhbnIiKSAjIEVycm9yIGZyb20gdXNpbmcgUnN0YW5zICJlcnJvciBpbiB1bnNlcmlhbGl6ZShzb2NrbGlzdFtbbl1dKSA6IGVycm9yIHJlYWRpbmcgZnJvbSBjb25uZWN0aW9uIi4gVXNlZCBjbWRzdGFuciBhcm91bmQgaXQuCgpwcmlvcnMgPC0gYyhwcmlvcihub3JtYWwoMCwgMyksICdiJyksIAogICAgICAgICAgICBwcmlvcihub3JtYWwoMCwgMyksICdJbnRlcmNlcHQnKSwKICAgICAgICAgICAgcHJpb3Ioc3R1ZGVudF90KDMsIDAsIDEwKSwgJ3NkJyksIAogICAgICAgICAgICBwcmlvcihzdHVkZW50X3QoMywgMCwgMTApLCAnc2lnbWEnKSkKCnJpX21vZGVsIDwtIGJybXM6OmJybShsbk1lYW4gfiBlY290eXBlICsgc3RyYXRlZ3kgKyBsbk1hc3MgKyBsblZQRCArIGxuRmxvdyArICgxIHwgc3R1ZHlfSUQpICsgKDEgKyBsbk1hc3MgfCBzcGVjaWVzX2l1Y24pICsgKDEgfCBncihzcGVjaWVzX3BoeWxvLCBjb3YgPSBwaHlsbykpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgICAgPSByZXNpc3RfZGF0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSAgPSBnYXVzc2lhbigpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyICAgPSBsaXN0KHBoeWxvID0gcGh5bG9fY29yKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yICAgPSBwcmlvcnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgID0gNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyAgID0gNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyICAgID0gNWUzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCAgPSAyLjVlMywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSkpCgp3dV9tb2RlbCA8LSBicm1zOjpicm0obG5NZWFuIH4gZWNvdHlwZSArIGxuTWFzcyArIHRydF90ZW1wICsgaHlkcmF0aW9uICsgb3JpZ2luICsgKDEgfCBzdHVkeV9JRCkgKyAoMSArIGxuTWFzcyB8IHNwZWNpZXNfaXVjbikgKyAoMSB8IGdyKHNwZWNpZXNfcGh5bG8sIGNvdiA9IHBoeWxvKSksIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgICAgPSB3dV9kYXQgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6Z3JvdXBfYnkoZWNvdHlwZSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKG4oKSA+PSA1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ICA9IGdhdXNzaWFuKCksIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEyICAgPSBsaXN0KHBoeWxvID0gcGh5bG9fY29yKSwKICAgICAgICAgICAgICAgICAgICAgICBwcmlvciAgID0gcHJpb3JzLAogICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyAgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyAgID0gNCwgCiAgICAgICAgICAgICAgICAgICAgICAgaXRlciAgICA9IDVlMywgCiAgICAgICAgICAgICAgICAgICAgICAgd2FybXVwICA9IDIuNWUzLCAKICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSkpCmBgYAoKYGBge3IgRmlnIFM1LCBlY2hvID0gRkFMU0UsIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSAzLCBmaWcuYWxpZ24gPScgY2VudGVyJ30KcmlfbW9kZWxfcHAgPC0gYnJtczo6cHBfY2hlY2socmlfbW9kZWwsIHR5cGUgPSAic2NhdHRlcl9hdmciKSArIG15dGhlbWUoKQp3dV9tb2RlbF9wcCAgPC0gYnJtczo6cHBfY2hlY2sod3VfbW9kZWwsIHR5cGUgPSAic2NhdHRlcl9hdmciKSArIG15dGhlbWUoKQoKY293cGxvdDo6cGxvdF9ncmlkKHJpX21vZGVsX3BwLCB3dV9tb2RlbF9wcCwgbmNvbCA9IDIsIGxhYmVscyA9IGMoJ2EnLCAnYicpKQpgYGAKCioqRmlnLiBTNS4qKiBTY2F0dGVycGxvdHMgb2YgdGhlIG9ic2VydmVkIGRhdGEgKHkpIHZzIHRoZSBhdmVyYWdlIHNpbXVsYXRlZCBkYXRhICh5fnJlcH4pIGZyb20gdGhlIHBvc3RlcmlvciBwcmVkaWN0aXZlIGRpc3RyaWJ1dGlvbiBmb3IgdGhlICgqKmEqKikgcmVzaXN0YW5jZSB0byB3YXRlciBsb3NzIG1vZGVsLCBhbmQgKCoqYioqKSB0aGUgd2F0ZXIgdXB0YWtlIG1vZGVsLiBEYXNoZWQgbGluZSByZXByZXNlbnRzIGEgc2xvcGUgb2YgMS4gCgojIyBNb2RlbCBvdXRwdXQgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHMgLX0KCiMjIyBUYWJsZSBTMyAtICRyX2kkIG1vZGVsIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKKipUYWJsZSBTMy4qKiBNZWFuIHBhcmFtZXRlciBlc3RpbWF0ZXMsIGVzdGltYXRlIGVycm9yLCBhbmQgOTUlIEJheWVzaWFuIGNyZWRpYmxlIGludGVydmFscyBmb3IgdGhlICRyX2kkIG1vZGVsLCB3aGljaCBpbmNsdWRlcyB0aGUgaW50ZXJjZXB0ICgkXGJldGFfMCQpLCBlY290eXBlLCBzdHJhdGVneSwgdGhlIG5hdHVyYWwgbG9nYXJpdGhtIG9mIGJvZHkgbWFzcyAobG5NYXNzKSwgdGhlIG5hdHVyYWwgbG9nYXJpdGhtIG9mIHZhcG91ciBwcmVzc3VyZSBkZWZpY2l0IChsblZQRCksIGFuZCB0aGUgbmF0dXJhbCBsb2dhcml0aG0gb2YgdGhlIGV4cGVyaW1lbnRhbCBmbG93IHJhdGUgKGxuRmxvdykuIEdyb3VwLWxldmVsIGVmZmVjdHMgaW5jbHVkZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9ucyAoJFxzaWdtYSQpIGZvciBzdHVkeS1sZXZlbCBvYnNlcnZhdGlvbnMgKCRcc2lnbWFfe3N0dWR5fV4yJCksIHBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcyAoJFxzaWdtYV97cGh5bG9nZW55fV4yJCksIGFuZCB0aGUgY29ycmVsYXRpb24gYW1vbmcgc3BlY2llcyAoJFxzaWdtYV97c3BlY2llc31eMiQpIGFuZCBib2R5IG1hc3MgKCRcc2lnbWFfe2xuTWFzc31eMiQpLiAkUl97bWFyZ2luYWx9XjIkIHJlcHJlc2VudHMgdGhlIHZhcmlhbmNlIGV4cGxhaW5lZCBieSBmaXhlZCBlZmZlY3RzLCB3aGlsZSAkUl97Y29uZGl0aW9uYWx9XjIkIHJlcHJlc2VudHMgdGhlIHZhcmlhbmNlIGV4cGxhaW5lZCBieSBib3RoIGZpeGVkIGVmZmVjdHMgYW5kIGdyb3VwLWxldmVsIGVmZmVjdHMuCgpgYGB7ciB0YWJsZVMzLCBlY2hvID0gRkFMU0V9CiMgRml4ZWQgZWZmZWN0CmZlZiA8LSBicm1zOjpmaXhlZihyaV9tb2RlbCkgJT4lIAogIGFzLmRhdGEuZnJhbWUoLikgJT4lCiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIlBhcmFtZXRlciIpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBhcmFtZXRlciA9IHN0cl9yZXBsYWNlKFBhcmFtZXRlciwgIk0iLCAiLSIpKSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSBjYXNlX3doZW4oCiAgICBQYXJhbWV0ZXIgPT0gIkludGVyY2VwdCIgfiAibG4kXFxiZXRhXzAkIiwKICAgIFBhcmFtZXRlciA9PSAiZWNvdHlwZUFyYm9yZWFsIiAgfiAiQXJib3JlYWwiLAogICAgUGFyYW1ldGVyID09ICJlY290eXBlRm9zc29yaWFsIiAgfiAiRm9zc29yaWFsIiwKICAgIFBhcmFtZXRlciA9PSAiZWNvdHlwZUdyb3VuZC1kd2VsbGluZyIgIH4gIkdyb3VuZC1kd2VsbGluZyIsCiAgICBQYXJhbWV0ZXIgPT0gImVjb3R5cGVTZW1pLWFxdWF0aWMiICB+ICJTZW1pLWFxdWF0aWMiLAogICAgUGFyYW1ldGVyID09ICJlY290eXBlU3RyZWFtLWR3ZWxsaW5nIiAgfiAiU3RyZWFtLWR3ZWxsaW5nIiwKICAgIFBhcmFtZXRlciA9PSAic3RyYXRlZ3l3YXRlci1wcm9vZiIgIH4gIldhdGVyLXByb29mIiwKICAgIFBhcmFtZXRlciA9PSAic3RyYXRlZ3ljb2Nvb24iICB+ICJDb2Nvb24iLAogICAgUGFyYW1ldGVyID09ICJzdHJhdGVneWhvbGxvdyIgIH4gIkhvbGxvdyIsCiAgICBQYXJhbWV0ZXIgPT0gImxuLWFzcyIgIH4gImxuTWFzcyIsCiAgICBQYXJhbWV0ZXIgPT0gImxuVlBEIiAgfiAibG5WUEQiLAogICAgUGFyYW1ldGVyID09ICJsbkZsb3ciICB+ICJsbkZsb3ciKSwKICAgICkgJT4lIAogIHRpYmJsZTo6YWRkX3JvdyhQYXJhbWV0ZXIgPSAiKipGaXhlZCBlZmZlY3RzKioiLCAuYmVmb3JlID0gMSkKCiMgUmFuZG9tIGVmZmVjdApyZWYgPC0gc3VtbWFyeShyaV9tb2RlbCkkcmFuZG9tICU+JSAKICBiaW5kX3Jvd3MoKSAlPiUgIyB1bmxpc3QKICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiUGFyYW1ldGVyIikgJT4lIAogIGRwbHlyOjpzZWxlY3QoMTo1KSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSBjKCIkXFxzaWdtYV97c3BlY2llc31eMiQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiRcXHNpZ21hX3tsbk1hc3N9XjIkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjb3IoJFxcc2lnbWFfe3NwZWNpZXN9XjIkLCAkXFxzaWdtYV97bG5NYXNzfV4yJCkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiRcXHNpZ21hX3twaHlsb2dlbnl9XjIkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIkXFxzaWdtYV97c3R1ZHl9XjIkIikpICU+JSAgIAogIGRwbHlyOjpyZW5hbWUoUTIuNSAgPSA0LCAKICAgICAgICAgICAgICAgIFE5Ny41ID0gNSkgJT4lIAogIHRpYmJsZTo6YWRkX3JvdyhQYXJhbWV0ZXIgPSAiKipHcm91cC1sZXZlbCBlZmZlY3RzKioiLCAuYmVmb3JlID0gMSkKCnJpX2xhbWJkYSA8LSBoeXBvdGhlc2lzKHJpX21vZGVsLCAic2Rfc3BlY2llc19waHlsb19fSW50ZXJjZXB0XjIgLyAoc2Rfc3BlY2llc19waHlsb19fSW50ZXJjZXB0XjIgKyBzaWdtYV4yKSA9IDAiLCBjbGFzcyA9IE5VTEwpJGh5cG90aGVzaXMgJT4lIAogIGRwbHlyOjpzZWxlY3QoLWMoMSw2OjgpKSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSAiJFxcbGFtYmRhJCIpICU+JSAKICBkcGx5cjo6cmVuYW1lKFEyLjUgID0gQ0kuTG93ZXIsIAogICAgICAgICAgICAgICAgUTk3LjUgPSBDSS5VcHBlcikgJT4lIAogIHRpYmJsZTo6YWRkX3JvdyhQYXJhbWV0ZXIgPSAiKipQaHlsb2dlbmV0aWMgc2lnbmFsKioiLCAuYmVmb3JlID0gMSkKCnJpX3IyIDwtIGRhdGEuZnJhbWUoUGFyYW1ldGVyID0gIiRSX3ttYXJnaW5hbH1eMiQiLAogICAgICAgICAgICAgICAgICAgICBFc3RpbWF0ZSA9IHJvdW5kKGRhdGEuZnJhbWUocGVyZm9ybWFuY2U6OnIyX2JheWVzKHJpX21vZGVsKSlbMiwxXSwgNCkgKiAxMDAsCiAgICAgICAgICAgICAgICAgICAgIFEyLjUgICAgID0gcm91bmQoZGF0YS5mcmFtZShwZXJmb3JtYW5jZTo6cjJfYmF5ZXMocmlfbW9kZWwpKVsyLDRdLCA0KSAqIDEwMCwKICAgICAgICAgICAgICAgICAgICAgUTk3LjUgICAgPSByb3VuZChkYXRhLmZyYW1lKHBlcmZvcm1hbmNlOjpyMl9iYXllcyhyaV9tb2RlbCkpWzIsNV0sIDQpICogMTAwKSAlPiUKICB0aWJibGU6OmFkZF9yb3coUGFyYW1ldGVyID0gIiRSX3tjb25kaXRpb25hbH1eMiQiLAogICAgICAgICAgICAgICAgICAgICBFc3RpbWF0ZSA9IHJvdW5kKGRhdGEuZnJhbWUocGVyZm9ybWFuY2U6OnIyX2JheWVzKHJpX21vZGVsKSlbMSwxXSwgNCkgKiAxMDAsCiAgICAgICAgICAgICAgICAgICAgIFEyLjUgICAgID0gcm91bmQoZGF0YS5mcmFtZShwZXJmb3JtYW5jZTo6cjJfYmF5ZXMocmlfbW9kZWwpKVsxLDRdLCA0KSAqIDEwMCwKICAgICAgICAgICAgICAgICAgICAgUTk3LjUgICAgPSByb3VuZChkYXRhLmZyYW1lKHBlcmZvcm1hbmNlOjpyMl9iYXllcyhyaV9tb2RlbCkpWzEsNV0sIDQpICogMTAwKSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKlZhcmlhbmNlKioiLCAuYmVmb3JlID0gMSkKCiMgUmVuZGVyIHRhYmxlCmJpbmRfcm93cyhmZWYsIHJlZiwgcmlfbGFtYmRhLCByaV9yMikgJT4lIAogIHJlbW92ZV9yb3duYW1lcygpICU+JSAKICBrbml0cjo6a2FibGUoZGlnaXRzID0gMikKYGBgCgoqKioKCiMjIyBUYWJsZSBTNCAtIFdVIG1vZGVsIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKKipUYWJsZSBTNC4qKiBNZWFuIHBhcmFtZXRlciBlc3RpbWF0ZXMsIGVzdGltYXRlIGVycm9yLCBhbmQgOTUlIEJheWVzaWFuIGNyZWRpYmxlIGludGVydmFscyBmb3IgdGhlIHdhdGVyIHVwdGFrZSBtb2RlbCwgd2hpY2ggaW5jbHVkZXMgdGhlIGludGVyY2VwdCAoJFxiZXRhXzAkKSwgZWNvdHlwZSwgdGhlIG5hdHVyYWwgbG9nYXJpdGhtIG9mIGJvZHkgbWFzcyAobG5NYXNzKSwgdHJlYXRtZW50IHRlbXBlcmF0dXJlLCBpbml0aWFsIGh5ZHJhdGlvbiBsZXZlbCwgYW5kIG9yaWdpbiAobGFiLXJhaXNlZCBvciB3aWxkIGNhdWdodCkuIEdyb3VwLWxldmVsIGVmZmVjdHMgaW5jbHVkZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9ucyAoJFxzaWdtYSQpIGZvciBzdHVkeS1sZXZlbCBvYnNlcnZhdGlvbnMgKCRcc2lnbWFfe3N0dWR5fV4yJCksIHBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcyAoJFxzaWdtYV97cGh5bG9nZW55fV4yJCksIGFuZCB0aGUgY29ycmVsYXRpb24gYW1vbmcgc3BlY2llcyAoJFxzaWdtYV97c3BlY2llc31eMiQpIGFuZCBib2R5IG1hc3MgKCRcc2lnbWFfe2xuTWFzc31eMiQpLiAkUl97bWFyZ2luYWx9XjIkIHJlcHJlc2VudHMgdGhlIHZhcmlhbmNlIGV4cGxhaW5lZCBieSBmaXhlZCBlZmZlY3RzLCB3aGlsZSAkUl97Y29uZGl0aW9uYWx9XjIkIHJlcHJlc2VudHMgdGhlIHZhcmlhbmNlIGV4cGxhaW5lZCBieSBib3RoIGZpeGVkIGVmZmVjdHMgYW5kIGdyb3VwLWxldmVsIGVmZmVjdHMuCgpgYGB7ciB0YWJsZVM1LCBlY2hvID0gRkFMU0V9CiMgRml4ZWQgZWZmZWN0CmZlZiA8LSBicm1zOjpmaXhlZih3dV9tb2RlbCkgJT4lIAogIGFzLmRhdGEuZnJhbWUoLikgJT4lCiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIlBhcmFtZXRlciIpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBhcmFtZXRlciA9IHN0cl9yZXBsYWNlKFBhcmFtZXRlciwgIk0iLCAiLSIpKSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSBjYXNlX3doZW4oCiAgICBQYXJhbWV0ZXIgPT0gIkludGVyY2VwdCIgfiAibG4kXFxiZXRhXzAkIiwKICAgIFBhcmFtZXRlciA9PSAiZWNvdHlwZUZvc3NvcmlhbCIgIH4gIkZvc3NvcmlhbCIsCiAgICBQYXJhbWV0ZXIgPT0gImVjb3R5cGVHcm91bmQtZHdlbGxpbmciICB+ICJHcm91bmQtZHdlbGxpbmciLAogICAgUGFyYW1ldGVyID09ICJlY290eXBlU2VtaS1hcXVhdGljIiAgfiAiU2VtaS1hcXVhdGljIiwKICAgIFBhcmFtZXRlciA9PSAibG4tYXNzIiAgfiAibG5NYXNzIiwKICAgIFBhcmFtZXRlciA9PSAidHJ0X3RlbXAiICB+ICJUcmVhdG1lbnQgdGVtcGVyYXR1cmUiLAogICAgUGFyYW1ldGVyID09ICJoeWRyYXRpb24iICB+ICJJbml0aWFsIGh5ZHJhdGlvbiIsCiAgICBQYXJhbWV0ZXIgPT0gIm9yaWdpbndpbGQiICB+ICJPcmlnaW4gLSBXaWxkIiwKICAgICAgICBUUlVFICAgfiBQYXJhbWV0ZXIpKSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKkZpeGVkIGVmZmVjdHMqKiIsIC5iZWZvcmUgPSAxKQoKIyBSYW5kb20gZWZmZWN0CnJlZiA8LSBzdW1tYXJ5KHd1X21vZGVsKSRyYW5kb20gJT4lIAogIGJpbmRfcm93cygpICU+JSAjIHVubGlzdAogIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKCJQYXJhbWV0ZXIiKSAlPiUgCiAgZHBseXI6OnNlbGVjdCgxOjUpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBhcmFtZXRlciA9IGMoIiRcXHNpZ21hX3tzcGVjaWVzfV4yJCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiJFxcc2lnbWFfe2xuTWFzc31eMiQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImNvcigkXFxzaWdtYV97c3BlY2llc31eMiQsICRcXHNpZ21hX3tsbk1hc3N9XjIkKSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiJFxcc2lnbWFfe3BoeWxvZ2VueX1eMiQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiRcXHNpZ21hX3tzdHVkeX1eMiQiKSkgJT4lICAgCiAgZHBseXI6OnJlbmFtZShRMi41ICA9IDQsIAogICAgICAgICAgICAgICAgUTk3LjUgPSA1KSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKkdyb3VwLWxldmVsIGVmZmVjdHMqKiIsIC5iZWZvcmUgPSAxKQoKd3VfbGFtYmRhIDwtIGh5cG90aGVzaXMod3VfbW9kZWwsICJzZF9zcGVjaWVzX3BoeWxvX19JbnRlcmNlcHReMiAvIChzZF9zcGVjaWVzX3BoeWxvX19JbnRlcmNlcHReMiArIHNpZ21hXjIpID0gMCIsIGNsYXNzID0gTlVMTCkkaHlwb3RoZXNpcyAlPiUgCiAgZHBseXI6OnNlbGVjdCgtYygxLDY6OCkpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBhcmFtZXRlciA9ICIkXFxsYW1iZGEkIikgJT4lIAogIGRwbHlyOjpyZW5hbWUoUTIuNSAgPSBDSS5Mb3dlciwgCiAgICAgICAgICAgICAgICBROTcuNSA9IENJLlVwcGVyKSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKlBoeWxvZ2VuZXRpYyBzaWduYWwqKiIsIC5iZWZvcmUgPSAxKQoKd3VfcjIgPC0gZGF0YS5mcmFtZShQYXJhbWV0ZXIgPSAiJFJfe21hcmdpbmFsfV4yJCIsCiAgICAgICAgICAgICAgICAgICAgIEVzdGltYXRlID0gcm91bmQoZGF0YS5mcmFtZShwZXJmb3JtYW5jZTo6cjJfYmF5ZXMod3VfbW9kZWwpKVsyLDFdLCA0KSAqIDEwMCwKICAgICAgICAgICAgICAgICAgICAgUTIuNSAgICAgPSByb3VuZChkYXRhLmZyYW1lKHBlcmZvcm1hbmNlOjpyMl9iYXllcyh3dV9tb2RlbCkpWzIsNF0sIDQpICogMTAwLAogICAgICAgICAgICAgICAgICAgICBROTcuNSAgICA9IHJvdW5kKGRhdGEuZnJhbWUocGVyZm9ybWFuY2U6OnIyX2JheWVzKHd1X21vZGVsKSlbMiw1XSwgNCkgKiAxMDApICU+JQogIHRpYmJsZTo6YWRkX3JvdyhQYXJhbWV0ZXIgPSAiJFJfe2NvbmRpdGlvbmFsfV4yJCIsCiAgICAgICAgICAgICAgICAgICAgIEVzdGltYXRlID0gcm91bmQoZGF0YS5mcmFtZShwZXJmb3JtYW5jZTo6cjJfYmF5ZXMod3VfbW9kZWwpKVsxLDFdLCA0KSAqIDEwMCwKICAgICAgICAgICAgICAgICAgICAgUTIuNSAgICAgPSByb3VuZChkYXRhLmZyYW1lKHBlcmZvcm1hbmNlOjpyMl9iYXllcyh3dV9tb2RlbCkpWzEsNF0sIDQpICogMTAwLAogICAgICAgICAgICAgICAgICAgICBROTcuNSAgICA9IHJvdW5kKGRhdGEuZnJhbWUocGVyZm9ybWFuY2U6OnIyX2JheWVzKHd1X21vZGVsKSlbMSw1XSwgNCkgKiAxMDApICU+JSAKICB0aWJibGU6OmFkZF9yb3coUGFyYW1ldGVyID0gIioqVmFyaWFuY2UqKiIsIC5iZWZvcmUgPSAxKQoKIyBSZW5kZXIgdGFibGUKYmluZF9yb3dzKGZlZiwgcmVmLCB3dV9sYW1iZGEsIHd1X3IyKSAlPiUgCiAgcmVtb3ZlX3Jvd25hbWVzKCkgJT4lIAogIGtuaXRyOjprYWJsZShkaWdpdHMgPSAyKQpgYGAKCioqKgoKIyMjIEZpZy4gUzYgLSAkcl9pJCBtb2RlbCB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxscyAtfSAKCmBgYHtyIEZpZyBTNiwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD03LCBlY2hvID0gRkFMU0V9CnJpX2NlICAgICA8LSBicm1zOjpjb25kaXRpb25hbF9lZmZlY3RzKHJpX21vZGVsLCBjKCJlY290eXBlIiwgInN0cmF0ZWd5IikpCnJpX2Vjb19jZSA8LSBkYXRhLmZyYW1lKHJpX2NlW1sxXV0pICU+JQogIGRwbHlyOjpyZW5hbWUoZXN0aW1hdGUgPSBlc3RpbWF0ZV9fLCBjaS5sYiA9IGxvd2VyX18sIGNpLnViID0gdXBwZXJfXykKCnJpX2Vjb19wbG90IDwtIHJpX2Vjb19jZSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBlY290eXBlLCB5ID0gZXhwKGVzdGltYXRlKSkpICsgCiAgZ2dmb3JjZTo6Z2VvbV9zaW5hKGRhdGEgPSByZXNpc3RfZGF0ICU+JSAKICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKHN0cmF0ZWd5ICVpbiUgYygibm9uZSIsICJ3YXRlci1wcm9vZiIpKSwgCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gZWNvdHlwZSwgeSA9IHJfc19lc3QpLCBjb2xvdXIgPSAiI2RlZGVkZSIsIHNpemUgPSAyKSArIAogIGdlb21fcG9pbnQoYWVzKCksIHNpemUgPSA0LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGV4cChjaS5sYiksIHltYXggPSBleHAoY2kudWIpKSwgc2l6ZSA9IDAuOCwgd2lkdGggPSAwLjEsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSBzY2FsZXM6OmxvZ190cmFucygpLCBicmVha3MgPSBjKDAuMDEsIDAuMSwgMSwgMTAsIDEwMCwgMTAwMCksIGxhYmVscyA9IGMoMC4wMSwgMC4xLCAxLCAxMCwgMTAwLCAiMSwwMDAiKSkgKwogIHhsYWIoTlVMTCkgKwogIHlsYWIoZXhwcmVzc2lvbihpdGFsaWMoInIiKVsiaSJdfiIocyBjbSJeey0xfSoiKSIpKSArCiAgbXl0aGVtZSgpCgpyaV9zdHJhX2NlIDwtIGFzLmRhdGEuZnJhbWUocmlfY2VbWzJdXSkgJT4lCiAgZHBseXI6OnJlbmFtZShlc3RpbWF0ZSA9IGVzdGltYXRlX18sIGNpLmxiID0gbG93ZXJfXywgY2kudWIgPSB1cHBlcl9fKQoKcmlfc3RyYV9wbG90IDwtIHJpX3N0cmFfY2UgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc3RyYXRlZ3ksIHkgPSBleHAoZXN0aW1hdGUpKSkgKyAKICBnZ2ZvcmNlOjpnZW9tX3NpbmEoZGF0YSA9IHJlc2lzdF9kYXQsIGFlcyh4ID0gc3RyYXRlZ3ksIHkgPSByX3NfZXN0KSwgY29sb3VyID0gIiNkZWRlZGUiLCBtYXh3aWR0aCA9IDAuNSwgc2l6ZSA9IDIpICsgCiAgZ2VvbV9wb2ludChhZXMoKSwgc2l6ZSA9IDQsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gZXhwKGNpLmxiKSwgeW1heCA9IGV4cChjaS51YikpLCBzaXplID0gMC44LCB3aWR0aCA9IDAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSBzY2FsZXM6OmxvZ190cmFucygpLCBicmVha3MgPSBjKDAuMDEsIDAuMSwgMSwgMTAsIDEwMCwgMTAwMCksIGxhYmVscyA9IGMoMC4wMSwgMC4xLCAxLCAxMCwgMTAwLCAiMSwwMDAiKSkgKwogIHhsYWIoIlN0cmF0ZWd5IikgKwogIHlsYWIoZXhwcmVzc2lvbihpdGFsaWMoInIiKVsiaSJdfiIocyBjbSJeey0xfSoiKSIpKSArCiAgbXl0aGVtZSgpCgpjb3dwbG90OjpwbG90X2dyaWQocmlfZWNvX3Bsb3QsIHJpX3N0cmFfcGxvdCwgbnJvdyA9IDIsIGFsaWduID0gImgiLCBheGlzID0gImJ0IiwgbGFiZWxzID0gYygnYScsICdiJykpCmBgYAoKKipGaWcuIFM2LioqIERpZmZlcmVuY2VzIGluIHJlc2lzdGFuY2UgdG8gd2F0ZXIgbG9zcywgJHJfaSQgKHMgY21eLTFeKSBieSAoKiphKiopIGVjb3R5cGUgYW5kICgqKmIqKikgd2F0ZXItY29uc2VydmluZyBzdHJhdGVnaWVzLiBOb3RlLCB3aGVuIHBsb3R0aW5nIGJ5IGVjb3R5cGUsIHRoZSAkcl9pJCBleGNsdWRlcyBiZWhhdmlvdXJhbCB3YXRlci1jb25zZXJ2aW5nIHN0cmF0ZWdpZXMgc3VjaCBhcyBkdXJpbmcgY29jb29uLWZvcm1pbmcgYW5kIGluc2lkZSBob2xsb3dzLiBNZWFuIGVzdGltYXRlcyDCsSA5NSUgQ0kgcHJlc2VudGVkIGluIGJsYWNrIHBvaW50cyBhbmQgZXJyb3IgYmFycywgd2hpbGUgcmF3IHZhbHVlcyB3ZXJlIHByZXNlbnRlZCBhcyBncmV5IHBvaW50cy4KCioqKgoKIyMjIEZpZy4gUzcgLSBXVSBtb2RlbCB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxscyAtfSAKCmBgYHtyIEZpZyBTNywgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTcsIGVjaG8gPSBGQUxTRX0Kd3VfY2UgPC0gYnJtczo6Y29uZGl0aW9uYWxfZWZmZWN0cyh3dV9tb2RlbCwgYygiZWNvdHlwZSIsICJsbk1hc3MiLCAiaHlkcmF0aW9uIikpCnd1X2Vjb19jZSA8LSBkYXRhLmZyYW1lKHd1X2NlW1sxXV0pICU+JQogIGRwbHlyOjpyZW5hbWUoZXN0aW1hdGUgPSBlc3RpbWF0ZV9fLCBjaS5sYiA9IGxvd2VyX18sIGNpLnViID0gdXBwZXJfXykKCnd1X2Vjb19jZSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBlY290eXBlLCB5ID0gZXhwKGVzdGltYXRlKSkpICsgCiAgZ2dmb3JjZTo6Z2VvbV9zaW5hKGRhdGEgPSB3dV9kYXQsIGFlcyh4ID0gZWNvdHlwZSwgeSA9IG1nX2hfbWVhbiksIGNvbG91ciA9ICIjZGVkZWRlIiwgc2l6ZSA9IDIpICsgCiAgZ2VvbV9wb2ludChhZXMoKSwgc2l6ZSA9IDQsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gZXhwKGNpLmxiKSwgeW1heCA9IGV4cChjaS51YikpLCBzaXplID0gMC44LCB3aWR0aCA9IDAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9IHNjYWxlczo6bG9nX3RyYW5zKCksIGJyZWFrcyA9IGMoMTAsIDEwMCwgMTAwMCwgMTAwMDAsIDEwMDAwMCksIGxhYmVscyA9IGMoMTAsIDEwMCwgIjEsMDAwIiwgIjEwLDAwMCIsICIxMDAsMDAwIikpICsKICB4bGFiKE5VTEwpICsKICB5bGFiKGV4cHJlc3Npb24oIldVIn4oIm1nIn5IWzJdKk9+aF57Ii0xIn0pKSkgKwogIG15dGhlbWUoKQpgYGAKCioqRmlnLiBTNy4qKiBEaWZmZXJlbmNlcyBpbiBjdXRhbmVvdXMgd2F0ZXIgdXB0YWtlIChtZyBIfjJ+TyBoXi0xXikgYnkgZWNvdHlwZS4gTWVhbiBlc3RpbWF0ZXMgwrEgOTUlIENJIHByZXNlbnRlZCBpbiBibGFjayBwb2ludHMgYW5kIGVycm9yIGJhcnMsIHdoaWxlIHJhdyB2YWx1ZXMgd2VyZSBwcmVzZW50ZWQgYXMgZ3JleSBwb2ludHMuIFRoZSBzaXplIG9mIHRoZSBncmV5IHBvaW50cyBpbmRpY2F0ZXMgc3R1ZHkgcHJlY2lzaW9uIChpbnZlcnNlIG9mIHN0YW5kYXJkIGVycm9yKS4KCioqKgoKIyAqTmljaGVNYXBSKiB7LX0KClRvIGVzdGltYXRlIHRoZSBpbmZsdWVuY2Ugb2Ygd2FybWluZyBhbmQgZHJvdWdodCBvbiBhY3Rpdml0eSBvZiBhIGh5cG90aGV0aWNhbCBmcm9nLCB3ZSBzaW11bGF0ZWQgYSB3YXRlciBhbmQgaGVhdCBlbmVyZ3kgZXhjaGFuZ2UgbW9kZWwgKCoqRmlnLiBTOGEqKikgYW5kIGl0cyBpbnRlcmFjdGlvbiB3aXRoIGEgc2ltdWxhdGVkIGxvY2FsIG1pY3JvY2xpbWF0ZSB1c2luZyB0aGUgKk5pY2hlTWFwUiogcGFja2FnZSBbQEtlYXJuZXkyMDE3OyBAS2Vhcm5leTIwMjBdLgoKIVtdKEZpZyBTOCAtIEVuZXJneSBhbmQgd2F0ZXIgZXhjaGFuZ2UucG5nKQoKKipGaWcuIFM4LioqIFN1bW1hcnkgd2F0ZXIgYW5kIGVuZXJneSBleGNoYW5nZSBtb2RlbCBmcm9tIEBUcmFjeTE5NzYgaW50ZWdyYXRlZCBpbnRvICpOaWNoZU1hcFIqIGFuZCB3YXRlciBjb25zZXJ2aW5nIHN0cmF0ZWdpZXMuICgqKmEqKikgU2NoZW1hdGljIHN1bW1hcnkgb2YgdGhlIGV4Y2hhbmdlcyBvZiBlbmVyZ3kgYW5kIHdhdGVyIGJldHdlZW4gYSBmcm9nIGFuZCBpdHMgZW52aXJvbm1lbnQgdXNlZCB0byBkZXZlbG9wIHRoZSB0cmFuc2llbnQtc3RhdGUgbW9kZWwgb2Ygd2F0ZXIgZXhjaGFuZ2UuIEluIHJlc3BlY3QgdG8gd2F0ZXIgZXhjaGFuZ2UsIHRoZSBuZXQgd2F0ZXIgbG9zcyByZXByZXNlbnRzIHdhdGVyIGxvc3MgZnJvbSByZXNwaXJhdG9yeSwgY3V0YW5lb3VzLCBvY3VsYXIsIGFuZCBjbG9hY2EgZXZhcG9yYXRpb24gYXMgd2VsbCBhcyB1cmluYXJ5IGFuZCBmYWVjYWwgd2F0ZXIgW0BQaXJ0bGUyMDE5XS4gKCoqYioqKSBCZWhhdmlvdXJhbCwgbW9ycGhvbG9naWNhbCwgYW5kIHBoeXNpb2xvZ2ljYWwgc3RyYXRlZ2llcyBlbXBsb3llZCBieSBmcm9ncyBvbiBsYW5kIHRvIHJlZHVjZSB3YXRlciBsb3NzIFtASGlsbG1hbjIwMDldLgoKIyMgU2ltdWxhdGUgd2F0ZXItY29uc2VydmluZyBiZWhhdmlvdXJzIHstfQoKV2UgdXNlZCB0aGUgbW9kdWxhcml6ZWQgdmVyc2lvbiBvZiAqTmljaGVNYXBSKuKAmXMgdjMuMi4xIGVjdG90aGVybSBtb2RlbCAoaS5lLiBgZWN0b1JfZGV2ZWxgKSBhbmQgY29kZWQgYmVoYXZpb3JhbCBmdW5jdGlvbnMgdG8gYWNjb3VudCBmb3IgdGhlIGluZmx1ZW5jZSBvZiBoeWRyYXRpb24gb24gYWN0aXZpdHkgKGBiZWhhdl9mdW5jdGlvbnNgIGZ1bmN0aW9uKSB3aGljaCBjYW4gYmUgZm91bmQgaW4gdGhlIFtiZWhhdl9mdW5jdGlvbnMuUl0oaHR0cHM6Ly9naXRodWIuY29tL25pY2hvbGFzd3Vuei9nbG9iYWwtZnJvZy1kcm91Z2h0L2Jsb2IvbWFpbi9jb2RlL2JlaGF2X2Z1bmN0aW9ucy5SKSBmaWxlIG9uIEdpdEh1Yi4gCgpXaGVuIHRoZSBhbmltYWwgaXMgbm90IGFjdGl2ZSwgaXQgaXMgc2ltdWxhdGVkIHRvIGdvIHRvIGFuIHVuZGVyZ3JvdW5kIHJldHJlYXQuIEl0IHNlbGVjdHMgdGhlIHNoYWxsb3dlc3QgZGVwdGggd2l0aCB0ZW1wZXJhdHVyZXMgYmV0d2VlbiBUbWF4IGFuZCBUbWluLiBJZiB3YXRlciA9IFQsIHRoZSBmcm9nIHNlbGVjdHMgdGhlIHNoYWxsb3dlc3Qgbm9kZSB3aXRoIHRlbXBlcmF0dXJlcyBiZXR3ZWVuIFRtYXggYW5kIFRtaW4gYW5kIGEgd2F0ZXIgcG90ZW50aWFsID49IC03Mi41LCB3aGljaCB3YXMgcmVwb3J0ZWQgYXMgYSBzb2lsIHdhdGVyIHBvdGVudGlhbCBmcm9tIHdoaWNoICpSYW5hIHBpcGllbnMqIGNvdWxkIGFic29yYiB3YXRlci4gV2hlbiB0aGUgYW5pbWFsIGlzIGJlbG93Z3JvdW5kLCBpdCByZS1oeWRyYXRlcyBpZiB0aGUgc29pbCB3YXRlciBwb3RlbnRpYWwgaXMgPj0gLTcyLjUsIGF0IGEgcmF0ZSBzcGVjaWZpZWQgaW4gaHlkLnJhdGUgYW5kIHByb3BvcnRpb25hbCB0byB0aGUgbGV2ZWwgb2YgZGVoeWRyYXRpb24sIGZvbGxvd2luZzoKClxiZWdpbntlcXVhdGlvbn0KXGZyYWN7SHlkX3ttYXh9IC0gSHlkX3tpfX17SHlkX3ttYXh9fSBcdGltZXMgaHlkLnJhdGUsIAooXCNlcTpoeWQpClxlbmR7ZXF1YXRpb259CiAKSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCBjdXJyZW50bHkgZnJvZ3MgYXJlIG5vdCByZS1oeWRyYXRpbmcgd2hlbiBhY3RpdmUgYWJvdmVncm91bmQuCgpUaGUg4oCcc2tpbndldOKAnSB0ZXJtICgkcF97d2V0fSQpIGRldGVybWluZXMgdGhlIHByb3BvcnRpb24gb2YgdGhlIHRvdGFsIHN1cmZhY2UgYXJlYSB1c2VkIGluIHRoZSBjYWxjdWxhdGlvbiBvZiBtYXNzIHRyYW5zZmVyIG9mIHdhdGVyIGZyb20gdGhlIHN1cmZhY2UuIEhlcmUsICRwX3t3ZXR9JCB3YXMgY2FsY3VsYXRlZCBmcm9tIGVtcGlyaWNhbGx5IGRlcml2ZWQgc2tpbiByZXNpc3RhbmNlIGZvbGxvd2luZyBAUGlydGxlMjAxOToKClxiZWdpbntlcXVhdGlvbn0KcF97d2V0fSA9IFxmcmFjezF9e2hfRCBcdGltZXMgcl9pICsgKFxmcmFje1Bfcn17U19jfSleXGZyYWN7Mn17M319LCAKKFwjZXE6cHdldCkKXGVuZHtlcXVhdGlvbn0KCndoZXJlICRyX2kkIGlzIHRoZSBza2lu4oCZcyByZXNpc3RhbmNlIHRvIHdhdGVyIHZhcG9yIHRyYW5zZmVyIChzIG1eLTFeKSwgJFBfciQgaXMgdGhlIFByYW5kdGwgbnVtYmVyIChkaW1lbnNpb25sZXNzKSwgJFNfYyQgaXMgdGhlIFNjaG1pZHQgbnVtYmVyIChkaW1lbnNpb25sZXNzKSwgJGhfRCQgaXMgdGhlIG1hc3MgdHJhbnNmZXIgY29lZmZpY2llbnQgKG0gc14tMV4pLiBUbyBjYWxjdWxhdGUgJHBfe3dldH0kLCB0aGUgbWFzcyB0cmFuc2ZlciBjb2VmZmljaWVudCAoJGhfRCQpIG11c3QgYmUga25vd24uIE1hc3MgdHJhbnNmZXIgcmVmZXJzIHRvIHRoZSBtb3ZlbWVudCBvZiBhIHN1YnN0YW5jZSB0aG91Z2ggYSBmbHVpZCBpbnRlcmZhY2UsIGRyaXZlbiBieSBjaGFuZ2VzIGluIHRoZSBjb25jZW50cmF0aW9uIGdyYWRpZW50LiBUaGUgbWFzcyB0cmFuc2ZlciBjb2VmZmljaWVudCBjb250cm9scyB0aGUgcmF0ZSBvZiBkaWZmdXNpb24gYW5kIGlzIGRlcGVuZGVudCBvbiB2ZWxvY2l0eSwgdGVtcGVyYXR1cmUsIGFuZCBwaHlzaWNhbCBwcm9wZXJ0aWVzIG9mIHRoZSBpbnRlcnBoYXNlLiBTaW1pbGFyIHRvIHRoZSBoZWF0IHRyYW5zZmVyIGNvZWZmaWNpZW50LCB0aGUgbWFzcyB0cmFuc2ZlciBjb2VmZmljaWVudCBhbHNvIGhhcyB0d28gY29tcG9uZW50cyBkZXJpdmVkIGZyb20gZnJlZSBhbmQgZm9yY2VkIGNvbnZlY3Rpb24uIFdlIGNvbnNpZGVyIGZvcmNlZCBjb252ZWN0aW9uIG9ubHkgKGFzIGZyZWUgY29udmVudGlvbiBzaG91bGQgYmUgbmVnbGlnaWJsZSB3aXRoaW4gYSBtZWFzdXJlbWVudCBjaGFtYmVyKSwgYW5kIHRoaXMgY2FuIGJlIGNhbGN1bGF0ZWQgZnJvbSB0aGUgaGVhdCB0cmFuc2ZlciBjb2VmZmljaWVudDoKClxiZWdpbntlcXVhdGlvbn0KaF9EID0gKFxmcmFje2hfQ317Q19wIFx0aW1lcyBccmhvfSkgXHRpbWVzIChcZnJhY3tQX3J9e1NfY30pIF4gXGZyYWN7Mn17M30sIAooXCNlcTpoZCkKXGVuZHtlcXVhdGlvbn0KCndoZXJlICRQX3IkIGlzIHRoZSBQcmFuZHRsIG51bWJlciAoZGltZW5zaW9ubGVzcyksICRTX2MkIGlzIHRoZSBTY2htaWR0IG51bWJlciAoZGltZW5zaW9ubGVzcyksICRoX0MkIGlzIHRoZSBoZWF0IHRyYW5zZmVyIGNvZWZmaWNpZW50IChKIHNeLTFeIGNtXi0yXiBLXi0xXiksICRccmhvJCBpcyB0aGUgZGVuc2l0eSBvZiBkcnkgYWlyIChnIGNtXi0zXiksIGFuZCAkQ19wJCBpcyB0aGUgc3BlY2lmaWMgaGVhdCBvZiBhaXIgKDEuMDEgSiBnXi0xXiBLXi0xXikuCgojIyBTaW11bGF0ZSBkcm91Z2h0IGFuZCB3YXJtaW5nIHstfQoKTWljcm9jbGltYXRlcyByZXByZXNlbnQgdGhlIHBoeXNpY2FsIGVudmlyb25tZW50cyBleHBlcmllbmNlZCBieSBhbiBvcmdhbmlzbS4gVGhleSBhcmUgYSBuZWNlc3NpdHkgZm9yIG1lY2hhbmlzdGljIG5pY2hlIG1vZGVsbGluZyBiZWNhdXNlIGl0IGlzIHRoZSBlbnZpcm9ubWVudCBleHBlcmllbmNlZCBhdCB0aGUgc2NhbGUgb2YgdGhlIGluZGl2aWR1YWwgdGhhdCBuZWVkcyB0byBiZSBwcm92aWRlZCB0byB0aGUgZXF1YXRpb25zIG9mIGVuZXJneSBhbmQgbWFzcyBiYWxhbmNlLiBUaGUgbWljcm9jbGltYXRlIG1vZGVsIHdhcyBpbXBsZW1lbnRlZCBhcyBkZXNjcmliZWQgYnkgQEtlYXJuZXkyMDE0LiBTcGVjaWZpY2FsbHksIGl0IHdhcyBkcml2ZW4gYnkgaGlzdG9yaWNhbCAwLjA1wrAgZ3JpZCAofjUga20pIGRhaWx5IHdlYXRoZXIgaW5wdXQgbGF5ZXJzIChhaXIgdGVtcGVyYXR1cmUsIHZhcG9yIHByZXNzdXJlLCB3aW5kIHNwZWVkLCBhbmQgY2xvdWQgY292ZXIpLgoKV2Ugc2ltdWxhdGVkIG1ldGVvcm9sb2dpY2FsIGRyb3VnaHQgKGRlZmluZWQgYXMgbGVzcyB0aGFuIGF2ZXJhZ2UgcmFpbmZhbGwpIGZyb20gdGhlIGBtaWNyb19lcmE1YCBmdW5jdGlvbiBmcm9tICpOaWNoZU1hcFIqIGJ5IGRlY3JlYXNpbmcgdGhlIGByYWlubXVsdGAgZnVuY3Rpb24gYnkgMC41ICgqKkZpZy4gUzkqKikuIEEgZmFjdG9yIG9mIDAuNSBtZWFucyA1MCUgb2YgdGhlIG9yaWdpbmFsIHJhaW5mYWxsLiBUbyBzaW11bGF0ZSBmcm9nIGFjdGl2aXR5IHVuZGVyIGRyb3VnaHQgYW5kIHdhcm1pbmcgc2NlbmFyaW9zLCB3ZSBjb25zdHJ1Y3RlZCBmb3VyIGNsaW1hdGUgY29uZGl0aW9ucyB1c2luZyB0aGUgYG1pY3JvX2VyYTVgIGZ1bmN0aW9uOiAKCjEuICoqY3VycmVudCBub3JtYWwgc2NlbmFyaW8qKiByZXByZXNlbnRpbmcgdGhlIG1lYW4gYW5udWFsIGFpciB0ZW1wZXJhdHVyZSBhbmQgcmFpbmZhbGwgZnJvbSAxOTgx4oCTMjAxMCwKMi4gKipjdXJyZW50IGRyb3VnaHQgc2NlbmFyaW8qKiByZXByZXNlbnRpbmcgdGhlIG1lYW4gYW5udWFsIGFpciB0ZW1wZXJhdHVyZSBmcm9tIDE5ODEtMjAxMCBhbmQgYW5udWFsIHJhaW5mYWxsIGJhc2VkIG9uIDIwMTctMjAyMCBkcm91Z2h0IGluIEF1c3RyYWxpYSAoKipGaWcuIFM5KiopLAozLiAqKndhcm1pbmcgbm9ybWFsIHNjZW5hcmlvKiogcmVwcmVzZW50aW5nIHRoZSDigJxidXNpbmVzcy1hcy11c3VhbOKAnSBzY2VuYXJpbywgd2hlcmUgdGhlIGdsb2JhbCBzdXJmYWNlIHRlbXBlcmF0dXJlIGlzIGVzdGltYXRlZCB0byBpbmNyZWFzZSBieSA0wrBDIGJ5IDIwODDigJMyMTAwIHdpdGggbm8gZWZmZWN0IG9mIGRyb3VnaHQgKCs0wrBDIG9ubHkpLCBhbmQgCjQuICoqd2FybWluZyBkcm91Z2h0IHNjZW5hcmlvKiogd2l0aCBhICs0wrBDIGluY3JlYXNpbmcgaW4gYWlyIHRlbXBlcmF0dXJlIGFuZCBhbm51YWwgcmFpbmZhbGwgYmFzZWQgb24gMjAxNy0yMDIwIGRyb3VnaHQgaW4gQXVzdHJhbGlhLgoKRmlyc3QsIGRvd25sb2FkIHRoZSBgbWNlcmE1YCBtaWNyb2NsaW1hdGUgZGF0YSB0byBhIGxvY2FsIGRpcmVjdG9yeSB0byBydW4gdGhlIGBtaWNyb19lcmE1YCBmdW5jdGlvbiBmYXN0ZXIuCgpgYGB7ciBtY2VyYV9zZXR1cCwgZXZhbD1GQUxTRSwgZWNobz1UfQojIGdldCBFUkE1IGRhdGEgd2l0aCBwYWNrYWdlIG1jZXJhNSAKIyBhc3NpZ24geW91ciBjcmVkZW50aWFscyAocmVnaXN0ZXIgaGVyZTogaHR0cHM6Ly9jZHMuY2xpbWF0ZS5jb3Blcm5pY3VzLmV1L3VzZXIvcmVnaXN0ZXIpCnVpZCAgICAgICAgIDwtICIkJCQkJCQiCmNkc19hcGlfa2V5IDwtICIkJCQkJCQkJC0kJCQkLSQkJCQtJCQkJC0kJCQkJCQkJCQkJCQiCmVjbXdmcjo6d2Zfc2V0X2tleSh1c2VyID0gdWlkLCBrZXkgPSBjZHNfYXBpX2tleSwgc2VydmljZSA9ICJjZHMiKQoKIyBib3VuZGluZyBjb29yZGluYXRlcyAoaW4gV0dTODQgLyBFUFNHOjQzMjYpCmMoLTQxLjE5MCwgLTIwLjE4NikgCnhtbiA8LSAtNDIKeG14IDwtIC00MQp5bW4gPC0gLTIxCnlteCA8LSAtMjAKCnhtbiA8LSAxNTIKeG14IDwtIDE1NAp5bW4gPC0gLTI4CnlteCA8LSAtMjYKCiMgdGVtcG9yYWwgZXh0ZW50CnN0X3RpbWUgPC0gbHVicmlkYXRlOjp5bWQoIjIwMTY6MDE6MDEiKSAjIGVhcmxpZXN0IHNhbXBsaW5nIGRhdGUKZW5fdGltZSA8LSBsdWJyaWRhdGU6OnltZCgiMjAxODoxMjozMSIpICMgbGF0ZXN0IHNhbXBsaW5nIGRhdGUKCiMgZmlsZW5hbWUgYW5kIGxvY2F0aW9uIGZvciBkb3dubG9hZGVkIC5uYyBmaWxlcwpmaWxlX3ByZWZpeCA8LSAiZXJhNSIKb3AgPC0gIllPVVIgRElSRUNUT1JZIgoKIyBidWlsZCBhIHJlcXVlc3QgKGNvdmVyaW5nIG11bHRpcGxlIHllYXJzKQpyZXEgPC0gbWNlcmE1OjpidWlsZF9lcmE1X3JlcXVlc3QoeG1pbiA9IHhtbiwgeG1heCA9IHhteCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSB5bW4sIHltYXggPSB5bXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydF90aW1lICAgPSBzdF90aW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kX3RpbWUgICAgID0gZW5fdGltZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGZpbGVfbmFtZSA9IGZpbGVfcHJlZml4KQoKbWNlcmE1OjpyZXF1ZXN0X2VyYTUocmVxdWVzdCA9IHJlcSwgdWlkID0gdWlkLCBvdXRfcGF0aCA9IG9wKQpgYGAKCk5leHQsIHJ1biB0aGUgYG1pY3JvX2VyYTVgIGZ1bmN0aW9uIGZvciB0aGUgZm91ciBzY2VuYXJpb3MgaW4gMjAxNyAocmVwcmVzZW50aW5nIHR5cGljYWwgcmFpbmZhbGwgeWVhciksIGFuZCBvbmUgZm9yIDIwMTkgdG8gdmFsaWRhdGUgdGhlIG9ic2VydmVkIHJhaW5mYWxsIGRhdGEuIE5vdGUsIHdlIHJhbiB0aGUgbWljcm9jbGltYXRlIG1vZGVscyBmcm9tIDIwMTYgdG8gMjAxNyB0byAnc3BpbiB1cCcgdGhlIHNvaWwgbW9pc3R1cmUgZm9yIDIwMTYsIGFuZCBvbmx5IHVzZWQgdGhlIG1pY3JvY2xpbWF0ZSBkYXRhIGZvciAyMDE3LiBUaGlzIGFsc28gYXBwbGllZCB0byB0aGUgMjAxOSBtaWNyb2NsaW1hdGUsIHdoZXJlIHdlIHJhbiB0aGUgbWljcm9jbGltYXRlIG1vZGVscyBmcm9tIDIwMTggdG8gMjAxOSwgYW5kIHVzZWQgdGhlIG1pY3JvY2xpbWF0ZSBkYXRhIGZvciAyMDE5LgoKYGBge3IgYXVzX2xvYWQsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUUsIHJlc3VsdHM9ImhpZGUifQojIExvYWQgbWljcm9jbGltYXRlcwptaWNyb19jdXJyX3dldCA8LSByZWFkUkRTKCJtaWNyb19vdXRwdXQvQXVzdHJhbGlhX0N1cnJlbnQgbm9ybWFsLnJkcyIpCm1pY3JvX2N1cnJfZHJ5IDwtIHJlYWRSRFMoIm1pY3JvX291dHB1dC9BdXN0cmFsaWFfQ3VycmVudCBkcnkucmRzIikKbWljcm9fd2FybV93ZXQgPC0gcmVhZFJEUygibWljcm9fb3V0cHV0L0F1c3RyYWxpYV9XYXJtaW5nIG5vcm1hbC5yZHMiKQptaWNyb193YXJtX2RyeSA8LSByZWFkUkRTKCJtaWNyb19vdXRwdXQvQXVzdHJhbGlhX1dhcm1pbmcgZHJ5LnJkcyIpCgojIFNpbXVsYXRlIHJhaW5mYWxsIGZvciAyMDE5IGRyb3VnaHQKYWN0X2RyeSA8LSBtaWNyb19lcmE1KGxvYyA9IGMoMTUzLjA5MjQ5LCAtMjcuNjIzNSksICMgS2FyYXdhdGhhLCBRTEQuCiAgICAgICAgICAgICAgICAgICAgICBydW5zaGFkZSA9IDEsIG1pbnNoYWRlID0gMCwgIyBzaGFkZSBwYXJhbWV0ZXJzCiAgICAgICAgICAgICAgICAgICAgICB3YXJtID0gMCwgIyBjdXJyZW50IGNsaW1hdGUKICAgICAgICAgICAgICAgICAgICAgIGRzdGFydCA9ICIwMS8wMS8yMDE4IiwgCiAgICAgICAgICAgICAgICAgICAgICBkZmluaXNoID0gIjMxLzEyLzIwMTkiLAogICAgICAgICAgICAgICAgICAgICAgc3BhdGlhbCA9ICcvVXNlcnMvbmljaG9sYXN3dS9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9PbmVEcml2ZS1XZXN0ZXJuU3lkbmV5VW5pdmVyc2l0eS9Ecm91Z2h0IHByb2plY3QvU3BhdGlhbCBkYXRhL2thcmF3YXRoYS9lcmE1JywgIyBjaGFuZ2UgdG8geW91ciBsb2NhdGlvbgogICAgICAgICAgICAgICAgICAgICAgc2F2ZSA9IDApCmBgYAoKVG8gdmVyaWZ5IG91ciBtaWNyb2NsaW1hdGUgbW9kZWxzLCB3ZSBwbG90dGVkIHRoZSBzaW11bGF0ZWQgdGhlIGRhaWx5IHJhaW5mYWxsIGZvciAyMDE3IChyZXByZXNlbnRpbmcgdHlwaWNhbCByYWluZmFsbCkgYW5kIDIwMTkgKHJlY2VudCBoaXN0b3JpY2FsIGRyb3VnaHQpIHdpdGggdGhlIFtvYnNlcnZlZCBkYWlseSByYWluZmFsbF0oaHR0cDovL3d3dy5ib20uZ292LmF1L2NsaW1hdGUvZHJvdWdodC9rbm93bGVkZ2UtY2VudHJlL3ByZXZpb3VzLWRyb3VnaHRzLnNodG1sKSBpbiBBdXN0cmFsaWEgZm9yIHRoZSBmb2xsb3dpbmcgbG9jYXRpb246IEthcmF3YXRoYSwgU291dGhlYXN0IFF1ZWVuc2xhbmQsIEF1c3RyYWxpYSAoMTUzLjA5MjQ5LCAtMjcuNjIzNSkuIEthcmF3YXRoYSBwcm92aWRlcyBhIGdvb2QgY2FzZSBzdHVkeSBiZWNhdXNlIHRoZXJlIGFyZSBtYW55IGVjb3R5cGVzIGZvdW5kIGluIHRoaXMgbG9jYXRpb246IGdyb3VuZC1kd2VsbGluZyAoZS5nLiAqUmhpbmVsbGEgbWFyaW5hKiksIGFyYm9yZWFsIChlLmcuICpMaXRvcmlhIGNhZXJ1bGVhKiksIGZvc3NvcmlhbCAoZS5nLiAqQ3ljbG9yYW5hIGFsYm9ndXR0YXRhKiksIHNlbWktYXF1YXRpYyAoZS5nLiAqTGl0b3JpYSBuYXN1dGEqKSwgYW5kIHRoaXMgYXJlYSBoYXMgZXhwZXJpZW5jZWQgZHJvdWdodCByZWNlbnRseSAoMjAxOSkuIFdlIGV4dHJhY3RlZCByYWluZmFsbCBkYXRhIGZyb20gYSB3ZWF0aGVyIHN0YXRpb24gbmV4dCB0byBLYXJhd2F0aGEgd2hpY2ggZXhwZXJpZW5jZWQgInZlcnkgbXVjaCBiZWxvdyBhdmVyYWdlIiByYWluZmFsbCBmcm9tIHRoZSBBdXN0cmFsaWFuIEJ1cmVhdSBvZiBNZXRlb3JvbG9neS4KCmBgYHtyIEZpZyBTOSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTh9CiMgTG9hZCBvYnNlcnZlZCByYWluZmFsbCBmb3IgMjAxOQpvYnNfcmFpbmZhbGwgPC0gcmVhZC5jc3YoZmlsZS5wYXRoKGRhdGFfcGF0aCwgIm9ic19yYWluZmFsbC5jc3YiKSkgJT4lCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oIkRPWSIpICU+JQogIGRwbHlyOjptdXRhdGUoZGF0ZSA9IGx1YnJpZGF0ZTo6bWFrZV9kYXRlKHllYXIgPSAyMDE5LCBtb250aCA9IG1vbnRoX251bSwgZGF5ID0gZGF5KSkKCiMgTWVyZ2Ugb2JzZXJ2ZWQgYW5kIHByZWRpY3RlZCByYWluZmFsbCB0b2dldGhlcgptb2RlbF9yYWluX3dldCA8LSBhcy5kYXRhLmZyYW1lKG1pY3JvX2N1cnJfd2V0JFJBSU5GQUxMKSAlPiUKICB0YWlsKC0zNjYpICU+JSAjIHJlbW92ZSAyMDE2IHNpbXVsYXRpb24KICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiRE9ZIikgJT4lCiAgcmVuYW1lKHJhaW5mYWxsX21tID0gIm1pY3JvX2N1cnJfd2V0JFJBSU5GQUxMIikgJT4lCiAgbWVyZ2Uob2JzX3JhaW5mYWxsLCBieSA9ICJET1kiLCBhbGwueCA9IFRSVUUpCgptb2RlbF8yMDE5IDwtIGFzLmRhdGEuZnJhbWUoYWN0X2RyeSRSQUlORkFMTCkgJT4lCiAgdGFpbCgtMzY2KSAlPiUgIyByZW1vdmUgMjAxOCBzaW11bGF0aW9uCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oIkRPWSIpICU+JQogIHJlbmFtZShyYWluZmFsbF9tbSA9ICJhY3RfZHJ5JFJBSU5GQUxMIikgJT4lCiAgbWVyZ2Uob2JzX3JhaW5mYWxsLCBieSA9ICJET1kiLCBhbGwueCA9IFRSVUUpCgojIDIwMTcgbm9ybWFsIHZhbGlkYXRlCnJhaW5fd2V0X3Bsb3QgPC0gbW9kZWxfcmFpbl93ZXQgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fbGluZShhZXMoeCA9IERPWSwgeSA9IGthcmF3YXRoYV8xNyksIGNvbG91ciA9ICJncmV5IikgKwogIGdlb21fbGluZShhZXMoeCA9IERPWSwgeSA9IHJhaW5mYWxsX21tICogMS4yKSwgY29sb3VyID0gInJlZCIsIGFscGhhID0gMC41KSArCiAgbGFicyh4ID0gIkRheSBvZiB0aGUgeWVhciIsIHkgPSBleHByZXNzaW9uKCJEYWlseSByYWluZmFsbCAobW0gZGF5Il57Ii0xIn0qIikiKSkgKwogIGdndGl0bGUoIjIwMTcgTm9ybWFsIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW0gPSBjKDAsIDEwMCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM2NSwgNTApLCBleHBhbmQgPSBjKDAsIDApKSArIAogIG15dGhlbWUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKIyAyMDE5IGRyb3VnaHQgdmFsaWRhdGUKcmFpbl9kcnlfcGxvdCA8LSBtb2RlbF8yMDE5ICU+JQogIGdncGxvdCgpICsKICBnZW9tX2xpbmUoYWVzKHggPSBET1ksIHkgPSBrYXJhd2F0aGFfMTkpLCBjb2xvdXIgPSAiZ3JleSIpICsKICBnZW9tX2xpbmUoYWVzKHggPSBET1ksIHkgPSByYWluZmFsbF9tbSksIGNvbG91ciA9ICJyZWQiLCBhbHBoYSA9IDAuNSkgKwogIGxhYnMoeCA9ICJEYXkgb2YgdGhlIHllYXIiLCB5ID0gZXhwcmVzc2lvbigiRGFpbHkgcmFpbmZhbGwgKG1tIGRheSJeeyItMSJ9KiIpIikpICsKICBnZ3RpdGxlKCIyMDE5IERyb3VnaHQiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbSA9IGMoMCwgMTAwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMzY1LCA1MCksIGV4cGFuZCA9IGMoMCwgMCkpICsgCiAgbXl0aGVtZSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCgpjb3dwbG90OjpwbG90X2dyaWQocmFpbl93ZXRfcGxvdCwgcmFpbl9kcnlfcGxvdCwgbmNvbCA9IDIpCmBgYAoKKipGaWcuIFM5LioqIFNpbXVsYXRlZCByYWluZmFsbCBmcm9tIHRoZSBgbWljcm9fZXJhNWAgZnVuY3Rpb24gKGByIGthYmxlRXh0cmE6OnRleHRfc3BlYygicmVkIiwgY29sb3IgPSAicmVkIilgKSBhbmQgdGhlIG9ic2VydmVkIHJhaW5mYWxsIGZvciBLYXJhd2F0aGEsIFFMRCBmcm9tIHRoZSBBdXN0cmFsaWFuIEJ1cmVhdSBvZiBNZXRlb3JvbG9neSAoYHIga2FibGVFeHRyYTo6dGV4dF9zcGVjKCJncmV5IiwgY29sb3IgPSAiIzZiNmI2YiIpYCkuIFRoZSB0b3RhbCB5ZWFybHkgb2JzZXJ2ZWQgcmFpbmZhbGwKZm9yIDIwMTcgd2FzIGFzICoqYHIgc3VtKG1vZGVsX3JhaW5fd2V0JGthcmF3YXRoYV8xNylgIG1tKiosIGFuZCB0aGUgdG90YWwgc2ltdWxhdGVkIHllYXJseSByYWluZmFsbCBmcm9tICpOaWNoZU1hcFIqIHdhcyAqKmByIHN1bShtb2RlbF9yYWluX3dldCRyYWluZmFsbF9tbSkgKiAxLjJgIG1tKiouIFRoZSB0b3RhbCB5ZWFybHkgb2JzZXJ2ZWQgcmFpbmZhbGwgZm9yIHRoZSAyMDE5IGRyb3VnaHQgd2FzICoqYHIgc3VtKG1vZGVsXzIwMTkka2FyYXdhdGhhXzE5KWAgbW0qKiwgYW5kIHRoZSB0b3RhbCBzaW11bGF0ZWQgeWVhcmx5IHJhaW5mYWxsIGZyb20gKk5pY2hlTWFwUiogd2FzICoqYHIgc3VtKG1vZGVsXzIwMTkkcmFpbmZhbGxfbW0pYCBtbSoqLiBUaGUgYXZlcmFnZSB5ZWFybHkgcmFpbmZhbGwgYWNyb3NzIDE5ODEtMjAxMCBpcyBhcm91bmQgKioxMTAwIG1tKiogcGVyIHllYXIuCgojIyBTaW11bGF0ZSBhY3Rpdml0eSAtIGVjb3R5cGVzIHstfQoKV2Ugc2ltdWxhdGVkIHRoZSBwb3RlbnRpYWwgbnVtYmVyIG9mIGhvdXJzIGZvciBhY3Rpdml0eSBpbiBhIHllYXIgKCR0X3thY3R9JCkgd2hpY2ggcmVwcmVzZW50cyB0aGUgc3VpdGFibGUgdGhlcm1hbCBhbmQgaHlkcmljIGNvbmRpdGlvbnMgZm9yIHRoZSBhbmltYWwgdG8gbW92ZSBiZXlvbmQgdGhlaXIgcmV0cmVhdCB0byBlaXRoZXIgY2F0Y2ggcHJleSBvciBmaW5kaW5nIG1hdGVzIFtAS2Vhcm5leTIwMjBdLiBUaGUgdGhlcm1vcmVndWxhdG9yeSBhbmQgaHlkcm9yZWd1bGF0b3J5IHNlcXVlbmNlIGluIHRoZSBtb2RlbCBhc3N1bWVzIHRoYXQgZnJvZ3Mgd2lsbCBvbmx5IGJlIOKAmGFjdGl2ZeKAmSAoaS5lLiBtb3ZpbmcgYmV5b25kIHRoZWlyIHJldHJlYXQsIGNhdGNoaW5nIHByZXksIGZpbmRpbmcgbWF0ZXMpIGJldHdlZW4gdGhlIG1pbmltdW0gYW5kIG1heGltdW0gYm9keSB0ZW1wZXJhdHVyZSB0aHJlc2hvbGRzIGZvciBmb3JhZ2luZywgYFRtaW5gIGFuZCBgVG1heGAgKMKwQyksIGFuZCB0aGUgbWluaW11bSB0b2xlcmF0ZWQgaHlkcmF0aW9uLCBgbWluLmh5ZGAgKCUpLiBJbiBhZGRpdGlvbiwgaWYgYHdhdGVyLmFjdCA9IFRgLCB0aGUgZnJvZyB3aWxsIG9ubHkgYmUgYWN0aXZlIGlmIHRlbXBlcmF0dXJlcyBhcmUgd2l0aGluIHRoZSBzdWl0YWJsZSB0ZW1wIHJhbmdlLCBhbmQgdGhlIGZyb2cgaXMgbm90IGV4cGVjdGVkIHRvIGdvIGJlbG93IGFsbG93ZWQgaHlkcmF0aW9uIGxldmVscyAoZS5nLiBpZiAlaHlkcmF0aW9uIGlzIG5vdCBiZWxvdyBgbWluLmh5ZGApLgoKVG8gZXN0aW1hdGUgdGhlIHBvdGVudGlhbCAkdF97YWN0fSQgZm9yIG9uZSB5ZWFyLCB3ZSBzaW11bGF0ZWQgdGhlIGh5cG90aGV0aWNhbCBmcm9nIHRvIGJlIGFjdGl2ZSBkdXJpbmcgdGhlIGRheSBhbmQgbmlnaHQgKDI0IGhvdXJzKS4gV2hpbGUgbW9zdCBmcm9ncyBhcmUgbm9jdHVybmFsLCB0aGVyZSBhcmUgc29tZSBmcm9nIHNwZWNpZXMgZm91bmQgbW92aW5nIGR1cmluZyB0aGUgZGF5LiBUaGUgd2F0ZXIgaHlkcmljIHBhcmFtZXRlcnMgKGUuZy4gc2tpbiByZXNpc3RhbmNlLCB3YXRlciB1cHRha2UgcmF0ZSwgZGVoeWRyYXRpb24gdG9sZXJhbmNlKSB3ZXJlIGJhc2VkIG9uIHRoZSBhdmVyYWdlIHZhbHVlcyBvZiB0aGUgZGF0YXNldCBjb2xsZWN0ZWQgZnJvbSB0aGUgUFJJU01BIHNlYXJjaC4gVGhlIHRoZXJtYWwgcGFyYW1ldGVycyAobWluaW11bSBhbmQgbWF4aW11bSBmb3JhZ2luZyBhbmQgY3JpdGljYWwgdGVtcGVyYXR1cmUpIHdlcmUgYmFzZWQgb24gKlJoaW5hbGxhIG1hcmluYSogd2hpY2ggaGFzIGJlZW4gdmVyaWZpZWQgaW4gQEtlYXJuZXkyMDA4LgoKVGhyZWUgd2F0ZXItc2F2aW5nIHN0cmF0ZWdpZXMgd2VyZSBjb25zdHJ1Y3RlZCB0byBicm9hZGx5IHJlZmxlY3QgZWFjaCBlY290eXBlIHRoYXQgdXNlIGVpdGhlciBiZWhhdmlvdXJhbCBzdHJhdGVnaWVzIHN1Y2ggYXMgbWljcm9oYWJpdGF0IHNlbGVjdGlvbiwgb3IgcGh5c2lvbG9naWNhbCBzdHJhdGVnaWVzIHN1Y2ggYXMgaW5jcmVhc2VkIHNraW4gcmVzaXN0YW5jZSBvciBza2luIHRoaWNrbmVzcyAoKipUYWJsZSBTNSoqKS4gRm9yIGV4YW1wbGUsIG1hbnkgYW1waGliaWFucyAoZXNwZWNpYWxseSBhcmlkIHNwZWNpYWxpc3QpIHNlZWsgb3IgYnVycm93IHVuZGVyZ3JvdW5kIHRvIHJlZ3VsYXRlIGJvZHkgdGVtcGVyYXR1cmUgYW5kIHdhdGVyIGJhbGFuY2Ugd2l0aG91dCBleGhpYml0aW5nIHRoaWNrZXIgc2tpbiBvciBoaWdoZXIgc2tpbiByZXNpc3RhbmNlLiBUaGlzIGlzIGJlY2F1c2UgdW5kZXJncm91bmQgYnVycm93cyBhcmUgZ2VuZXJhbGx5IGNvb2xlciwgbGVzcyB2YXJpZWQgdGVtcGVyYXR1cmUgZmx1Y3R1YXRpb24sIGFuZCBtb3JlIG1vaXN0IHJlbGF0aXZlIHRvIHRoZSBzdXJmYWNlIGNsaW1hdGUuIAoKKipUYWJsZSBTNS4qKiBNb2RpZmllZCBwYXJhbWV0ZXJzIGZvciB0aGUgYHNpbS5lY3RvYCBmdW5jdGlvbiBmb3IgZWFjaCBoeXBvdGhldGljYWwgZnJvZyBtb2RlbC4gVGhlIHNraW4gcmVzaXN0YW5jZSB2YWx1ZXMgd2VyZSBiYXNlZCBvbiB0aGUgYXZlcmFnZSBlbXBpcmljYWwgbWVhc3VyZW1lbnRzIGZvciBhIHR5cGljYWwgZnJvZyBhbmQgYSB3YXRlcnByb29mIGZyb2cgaW4gdGhlIG1ldGEtYW5hbHlzaXMuIFNlZWsgc2hhZGUgcmVwcmVzZW50cyBtaWNyb2NsaW1hdGUgc2ltdWxhdGVkIHVuZGVyIHNoYWRlZCBjb25kaXRpb25zICgwLTkwJSBzaGFkZSkuIFJldHJlYXQgdW5kZXJncm91bmQgcmVwcmVzZW50cyB0aGUgYWJpbGl0eSBmb3IgdGhlIGZyb2cgdG8gc2VlayBzdWl0YWJsZSBtaWNyb2NsaW1hdGVzIHVuZGVyZ3JvdW5kLiBDYW4gY2xpbWIgcmVwcmVzZW50cyB0aGUgYWJpbGl0eSBmb3IgdGhlIGZyb2cgdG8gc2VlayBzdWl0YWJsZSBtaWNyb2NsaW1hdGVzIGFib3ZlIGdyb3VuZCBsZXZlbCAoZS5nLiB0cmVlcywgY2xpZmZzKS4gTm90ZSwgZnJvZ3MgYXJlIG5vdCBhY3RpdmUgd2hlbiB1bmRlcmdyb3VuZCwgYW5kIHdhdGVyIHVwdGFrZSBvbmx5IG9jY3VycyBkdXJpbmcgaW5hY3Rpdml0eS4KCmBgYHtyIHRhYmxlIFM1LCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpkYXRhLmZyYW1lKHN0cmF0ZWd5ID0gYygiU2hhZGUgb25seSIsICJXYXRlcnByb29mIiwiRm9zc29yaWFsIiksIAogICAgICAgICAgIHNraW4gPSBjKCJMb3ciLCAiSGlnaCIsICJMb3ciKSwKICAgICAgICAgICBzaGFkZSA9IGMoIlllcyIsICJZZXMiLCAiWWVzIiksCiAgICAgICAgICAgdW5kZXJncm91bmQgPSBjKCJObyIsICJObyIsICJZZXMiKSwKICAgICAgICAgICBjbGltYiA9IGMoIk5vIiwgIlllcyIsICJObyIpLAogICAgICAgICAgIGVjb3R5cGUgPSBjKCJHcm91bmQtZHdlbGxpbmciLCAiQXJib3JlYWwiLCAiRm9zc29yaWFsIikpICU+JQogIGtuaXRyOjprYWJsZShjb2wubmFtZXMgPSBjKCJXYXRlci1zYXZpbmcgc3RyYXRlZ3kiLCAiU2tpbiByZXNpc3RhbmNlIiwgIlNlZWsgc2hhZGU/IiwgIlJldHJlYXQgdW5kZXJncm91bmQ/IiwgIkNhbiBjbGltYj8iLCAiRWNvdHlwZSIpKSAKYGBgCgpJdCBpcyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHdlIGZvY3VzIG9ubHkgb24gdGhlIGRpcmVjdCBlZmZlY3RzIG9mIGVudmlyb25tZW50YWwgY2hhbmdlIG9uIHdhdGVyIGJ1ZGdldHMgYnkgcHJlZGljdGluZyBjaGFuZ2VzIGluIEVXTCByYXRlcy4gVGhlIGNvbmNsdXNpb25zIHdlIGRyYXcgZG8gbm90IGFjY291bnQgZm9yIHRoZSBpbmRpcmVjdCBlZmZlY3RzIG9mIGVudmlyb25tZW50YWwgY2hhbmdlIG9uIHdhdGVyIGJ1ZGdldHMsIHN1Y2ggYXMgcG90ZW50aWFsIGNoYW5nZXMgdG8gdGhlcm1hbCB0b2xlcmFuY2UgYXMgYSByZXN1bHQgb2YgZGVoeWRyYXRpb24sIG9yIHRoZSB0aGVybW9yZWd1bGF0b3J5IGRpZmZpY3VsdGllcyB0aGF0IG1heSBhcmlzZSBhcyBhIHJlc3VsdCBvZiBoYWJpdGF0IG1vZGlmaWNhdGlvbi4KCmBgYHtyIGZyb2dfc2ltLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFLCByZXN1bHRzPSJoaWRlIn0Kc291cmNlKCIvVXNlcnMvbmljaG9sYXN3dS9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9PbmVEcml2ZS1XZXN0ZXJuU3lkbmV5VW5pdmVyc2l0eS9Ecm91Z2h0IHByb2plY3QvY29kZS9iZWhhdl9mdW5jdGlvbnMuUiIpCiMgQ29uc3RydWN0IGZyb2cgbW9kZWwKIyBjb21wdXRlIHRoZSBoZWF0IGV4Y2hhbmdlIGJ5IGNvbnZlY3Rpb24gKGV4dHJhY3QgbWFzcyB0cmFuc2ZlciBjb2VmZmljaWVudCwgUHJhbmR0bCBudW1iZXIgYW5kIFNjaG1pZHQgbnVtYmVyKQpDT05WX291dCA8LSBOaWNoZU1hcFI6OkNPTlZfRU5ETyhUUyAgICAgPSAxOSwgIyBza2luIHRlbXBlcmF0dXJlICjCsEMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRFTlYgICA9IDIwLCAjIGZsdWlkIHRlbXBlcmF0dXJlICjCsEMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNIQVBFICA9IDQsICMgNCBpcyBlbGxpcHNvaWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1VSRkFSID0gbWVhbihyZXNpc3RfZGF0JGRvcnNfU0FfY20yLCBuYS5ybSA9IFRSVUUpIC8gMTAwMDAsICAjIHN1cmZhY2UgYXJlYSBmb3IgY29udmVjdGlvbiwgbTIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRkxUWVBFID0gMCwgIyBmbHVpZCB0eXBlOiAwID0gYWlyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVUlRTVCA9IDAsICMgdGVzdCBvZiBwcmVzZW5jZSBvZiBmdXIgKGxlbmd0aCB4IGRpYW1ldGVyIHggZGVuc2l0eSB4IGRlcHRoKSAoLSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRCAgICAgID0gbWVhbihyZXNpc3RfZGF0JEQsIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBURkEgICAgPSAyMCwgIyBpbml0aWFsIGZ1ci9haXIgaW50ZXJmYWNlIHRlbXBlcmF0dXJlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZFTCAgICA9IG1lYW4ocmVzaXN0X2RhdCRhaXJmbG93X2NtX3MsIG5hLnJtID0gVFJVRSkgLyAxMDAsICMgd2luZCBzcGVlZCAobS9zKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBaRlVSICAgPSAwLCAjIGZ1ciBkZXB0aCwgbWVhbiAobSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQlAgICAgID0gMTAxMzI1LCAjIGJhcm9tZXRyaWMgcHJlc3N1cmUgYXQgc2VhIGxldmVsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVMRVYgICA9IDApICMgZWxldmF0aW9uIChtKQoKIyBiYXNpYyBwYXJhbWV0ZXJzIGZvciAzMCBnIGZyb2cKV3dfZyAgICAgICAgIDwtIGV4cChtZWFuKGxvZyhyYXdfZGF0JG1lYW5fbWFzc19nKSwgbmEucm0gPSBUUlVFKSkgIyBnZW9tZXRyaWMgbWVhbiB3ZXQgd2VpZ2h0IG9mIGFuaW1hbCAoZyksIGFjY291bnQgZm9yIHVuZXZlbiBkaXN0cmlidXRpb24Kcl9zX2xvdyAgICAgIDwtIHJlc2lzdF9kYXQgJT4lIGRwbHlyOjpmaWx0ZXIoc3RyYXRlZ3kgPT0gIm5vbmUiKSAlPiUgZHBseXI6OnNlbGVjdChyX3NfZXN0KSAjIHNraW4gcmVzaXN0YW5jZQpwY3Rfd2V0X2hpZ2ggPC0gMSAvIChDT05WX291dFs1XSAqIG1lYW4ocl9zX2xvdyRyX3NfZXN0LCBuYS5ybSA9IFRSVUUpICsgKENPTlZfb3V0WzExXSAvIENPTlZfb3V0WzEzXSkgXiAwLjY2NjY2NjYpICogMTAwICAjICUgb2Ygc3VyZmFjZSBhcmVhIGFjdGluZyBhcyBhIGZyZWUtd2F0ZXIgZXhjaGFuZ2VyIChQaXJ0bGUgZXQgYWwgMjAxNykKCiMgcGFyYW1ldGVycyBmb3IgYSB3YXRlci1wcm9vZiBmcm9nCnJfc19oaWdoICAgIDwtIHJlc2lzdF9kYXQgJT4lIGRwbHlyOjpmaWx0ZXIoc3RyYXRlZ3kgPT0gIndhdGVyLXByb29mIikgJT4lIGRwbHlyOjpzZWxlY3Qocl9zX2VzdCkgIyBza2luIHJlc2lzdGFuY2UKcGN0X3dldF9sb3cgPC0gMSAvIChDT05WX291dFs1XSAqIG1heChyX3NfaGlnaCRyX3NfZXN0LCBuYS5ybSA9IFRSVUUpICsgKENPTlZfb3V0WzExXSAvIENPTlZfb3V0WzEzXSkgXiAwLjY2NjY2NjYpICogMTAwICMgJSBvZiBzdXJmYWNlIGFyZWEgYWN0aW5nIGFzIGEgZnJlZS13YXRlciBleGNoYW5nZXIgKFBpcnRsZSBldCBhbCAyMDE3KQoKIyBUaGVybWFsIHRyYWl0cyBiYXNlZCBvbiBSaGluZWxsYSBtYXJpbmEKVG1pbiAgIDwtIDEzLjcgIyBtaW5pbXVtIFRiIGF0IHdoaWNoIGFjdGl2aXR5IG9jY3VycyAoS2Vhcm5leSBldCBhbCAyMDA4KQpUbWF4ICAgPC0gMzUuNCAjIG1heGltdW0gVGIgYXQgd2hpY2ggYWN0aXZpdHkgb2NjdXJzIChLZWFybmV5IGV0IGFsIDIwMDgsIFRpbmdsZXkgJiBTaGluZSAyMDExKQojVF9wcmVmIDwtIDI0ICMgcHJlZmVycmVkIFRiIChLZWFybmV5IGV0IGFsIDIwMDgpCkNUbWF4ICA8LSAzNyAjIGNyaXRpY2FsIHRoZXJtYWwgbWluaW11bSAoYWZmZWN0cyBjaG9pY2Ugb2YgcmV0cmVhdCkgVHJhY3kgZXQgYWwgMjAxMgpDVG1pbiAgPC0gNiAjIGNyaXRpY2FsIHRoZXJtYWwgbWF4aW11bSAoYWZmZWN0cyBjaG9pY2Ugb2YgcmV0cmVhdCkgS29sYmUgZXQgYWwgMjAxMCwgTWNDYW5uIGV0IGFsIDIwMTQKCiMgV2F0ZXIgYmFsYW5jZSB0cmFpdHMKbWluX2h5ZCA8LSA4MCAjIG1pbmltdW0gdG9sZXJhdGVkIGh5ZHJhdGlvbiBiZWZvcmUgYWN0aXZpdHkgZGVjbGluZXMgKCUgb2YgZnVsbHkgaHlkcmF0ZWQgYW5pbWFscykKaHlkLmRlYXRoIDwtIDUwICMgbWluaW11bSB0b2xlcmF0ZWQgaHlkcmF0aW9uIGJlZm9yZSBkZWF0aCAoJSBvZiBmdWxseSBoeWRyYXRlZCBhbmltYWxzKQp3dV9yYXRlIDwtIHd1X2RhdCAlPiUgZHBseXI6OmZpbHRlcihzdHJhdGVneSA9PSAibm9uZSIpICU+JSBkcGx5cjo6c2VsZWN0KG1nX2hfbWVhbikKaHlkX3JhdGUgPC0gZXhwKG1lYW4obG9nKHd1X3JhdGUkbWdfaF9tZWFuKSwgbmEucm0gPSBUUlVFKSkgLyAxMDAwICMgZ2VvbWV0cmljIG1lYW4gcmVoeWRyYXRpb24gcmF0ZSAoZy9oKSwgYWNjb3VudCBmb3IgdW5ldmVuIGRpc3RyaWJ1dGlvbgojIGRlcGVuZHMgb24gY3VycmVudCBhbmQgbWF4IGh5ZHJhdGlvbiBsaWtlIHRoaXM6IGh5ZC5yYXRlICogKChoeWQgLSBoeWQuY3VycmVudCkgLyBoeWQpCgojIGJlaGF2ID0gJ2RpdXJuYWwnLCAnbm9jdHVybmFsJyBvciAnYm90aCcKIyB3YXRlcjsgZG9lcyB0aGUgZnJvZyBzZWxlY3QgZGVwdGggYWNjb3JkaW5nIHRvIHdhdGVyIHBvdGVudGlhbD8gKFRSVUUgb3IgRkFMU0UpCiMgd2F0ZXIuYWN0OyBkb2VzIHRoZSBhY3Rpdml0eSBkZXBlbmQgb24gd2F0ZXIgbG9zcz8gKFRSVUUgb3IgRkFMU0UpCgojIFNIQURFIE1PREVMCnNoYWRfY3Vycl93ZXRfbW9kIDwtIHNpbS5lY3RvKG1pY3JvX2N1cnJfd2V0LCBXd19nID0gV3dfZywgc2hhcGUgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG1heCA9IFRtYXgsIFRtaW4gPSBUbWluLCBDVG1pbiA9IENUbWluLCBDVG1heCA9IENUbWF4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWhhdiA9ICdib3RoJywgaW4uc2hhZGUgPSBUUlVFLCBidXJyb3cgPSBGQUxTRSwgY2xpbWIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmh5ZCA9IG1pbl9oeWQsIGh5ZC5kZWF0aCA9IGh5ZC5kZWF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHlkLnJhdGUgPSBoeWRfcmF0ZSwgcGN0X3dldCA9IHBjdF93ZXRfaGlnaCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID0gRkFMU0UsIHdhdGVyLmFjdCA9IFRSVUUpCgpzaGFkX2N1cnJfZHJ5X21vZCA8LSBzaW0uZWN0byhtaWNyb19jdXJyX2RyeSwgV3dfZyA9IFd3X2csIHNoYXBlID0gNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRtYXggPSBUbWF4LCBUbWluID0gVG1pbiwgQ1RtaW4gPSBDVG1pbiwgQ1RtYXggPSBDVG1heCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVoYXYgPSAnYm90aCcsIGluLnNoYWRlID0gVFJVRSwgYnVycm93ID0gRkFMU0UsIGNsaW1iID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5oeWQgPSBtaW5faHlkLCBoeWQuZGVhdGggPSBoeWQuZGVhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh5ZC5yYXRlID0gaHlkX3JhdGUsIHBjdF93ZXQgPSBwY3Rfd2V0X2hpZ2gsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXRlciA9IEZBTFNFLCB3YXRlci5hY3QgPSBUUlVFKQoKc2hhZF93YXJtX3dldF9tb2QgPC0gc2ltLmVjdG8obWljcm9fd2FybV93ZXQsIFd3X2cgPSBXd19nLCBzaGFwZSA9IDQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUbWF4ID0gVG1heCwgVG1pbiA9IFRtaW4sIENUbWluID0gQ1RtaW4sIENUbWF4ID0gQ1RtYXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlaGF2ID0gJ2JvdGgnLCBpbi5zaGFkZSA9IFRSVUUsIGJ1cnJvdyA9IEZBTFNFLCBjbGltYiA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uaHlkID0gbWluX2h5ZCwgaHlkLmRlYXRoID0gaHlkLmRlYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoeWQucmF0ZSA9IGh5ZF9yYXRlLCBwY3Rfd2V0ID0gcGN0X3dldF9oaWdoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2F0ZXIgPSBGQUxTRSwgd2F0ZXIuYWN0ID0gVFJVRSkKCnNoYWRfd2FybV9kcnlfbW9kIDwtIHNpbS5lY3RvKG1pY3JvX3dhcm1fZHJ5LCBXd19nID0gV3dfZywgc2hhcGUgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG1heCA9IFRtYXgsIFRtaW4gPSBUbWluLCBDVG1pbiA9IENUbWluLCBDVG1heCA9IENUbWF4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWhhdiA9ICdib3RoJywgaW4uc2hhZGUgPSBUUlVFLCBidXJyb3cgPSBGQUxTRSwgY2xpbWIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmh5ZCA9IG1pbl9oeWQsIGh5ZC5kZWF0aCA9IGh5ZC5kZWF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHlkLnJhdGUgPSBoeWRfcmF0ZSwgcGN0X3dldCA9IHBjdF93ZXRfaGlnaCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID0gRkFMU0UsIHdhdGVyLmFjdCA9IFRSVUUpCgojIFdBVEVSLVBST09GIE1PREVMCnRyZWVfY3Vycl93ZXRfbW9kIDwtIHNpbS5lY3RvKG1pY3JvX2N1cnJfd2V0LCBXd19nID0gV3dfZywgc2hhcGUgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG1heCA9IFRtYXgsIFRtaW4gPSBUbWluLCBDVG1pbiA9IENUbWluLCBDVG1heCA9IENUbWF4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWhhdiA9ICdib3RoJywgaW4uc2hhZGUgPSBUUlVFLCBidXJyb3cgPSBGQUxTRSwgY2xpbWIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uaHlkID0gbWluX2h5ZCwgaHlkLmRlYXRoID0gaHlkLmRlYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoeWQucmF0ZSA9IGh5ZF9yYXRlLCBwY3Rfd2V0ID0gcGN0X3dldF9sb3csIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXRlciA9IFRSVUUsIHdhdGVyLmFjdCA9IFRSVUUpCgp0cmVlX2N1cnJfZHJ5X21vZCA8LSBzaW0uZWN0byhtaWNyb19jdXJyX2RyeSwgV3dfZyA9IFd3X2csIHNoYXBlID0gNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRtYXggPSBUbWF4LCBUbWluID0gVG1pbiwgQ1RtaW4gPSBDVG1pbiwgQ1RtYXggPSBDVG1heCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVoYXYgPSAnYm90aCcsIGluLnNoYWRlID0gVFJVRSwgYnVycm93ID0gRkFMU0UsIGNsaW1iID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmh5ZCA9IG1pbl9oeWQsIGh5ZC5kZWF0aCA9IGh5ZC5kZWF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHlkLnJhdGUgPSBoeWRfcmF0ZSwgcGN0X3dldCA9IHBjdF93ZXRfbG93LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2F0ZXIgPSBUUlVFLCB3YXRlci5hY3QgPSBUUlVFKQoKdHJlZV93YXJtX3dldF9tb2QgPC0gc2ltLmVjdG8obWljcm9fd2FybV93ZXQsIFd3X2cgPSBXd19nLCBzaGFwZSA9IDQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUbWF4ID0gVG1heCwgVG1pbiA9IFRtaW4sIENUbWluID0gQ1RtaW4sIENUbWF4ID0gQ1RtYXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlaGF2ID0gJ2JvdGgnLCBpbi5zaGFkZSA9IFRSVUUsIGJ1cnJvdyA9IEZBTFNFLCBjbGltYiA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5oeWQgPSBtaW5faHlkLCBoeWQuZGVhdGggPSBoeWQuZGVhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh5ZC5yYXRlID0gaHlkX3JhdGUsIHBjdF93ZXQgPSBwY3Rfd2V0X2xvdywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID0gVFJVRSwgd2F0ZXIuYWN0ID0gVFJVRSkKCnRyZWVfd2FybV9kcnlfbW9kIDwtIHNpbS5lY3RvKG1pY3JvX3dhcm1fZHJ5LCBXd19nID0gV3dfZywgc2hhcGUgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG1heCA9IFRtYXgsIFRtaW4gPSBUbWluLCBDVG1pbiA9IENUbWluLCBDVG1heCA9IENUbWF4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWhhdiA9ICdib3RoJywgaW4uc2hhZGUgPSBUUlVFLCBidXJyb3cgPSBGQUxTRSwgY2xpbWIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uaHlkID0gbWluX2h5ZCwgaHlkLmRlYXRoID0gaHlkLmRlYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoeWQucmF0ZSA9IGh5ZF9yYXRlLCBwY3Rfd2V0ID0gcGN0X3dldF9sb3csIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXRlciA9IFRSVUUsIHdhdGVyLmFjdCA9IFRSVUUpCgojIEJVUlJPV0lORyBNT0RFTApidXJyX2N1cnJfd2V0X21vZCA8LSBzaW0uZWN0byhtaWNyb19jdXJyX3dldCwgV3dfZyA9IFd3X2csIHNoYXBlID0gNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRtYXggPSBUbWF4LCBUbWluID0gVG1pbiwgQ1RtaW4gPSBDVG1pbiwgQ1RtYXggPSBDVG1heCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVoYXYgPSAnYm90aCcsIGluLnNoYWRlID0gVFJVRSwgYnVycm93ID0gVFJVRSwgY2xpbWIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmh5ZCA9IG1pbl9oeWQsIGh5ZC5kZWF0aCA9IGh5ZC5kZWF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHlkLnJhdGUgPSBoeWRfcmF0ZSwgcGN0X3dldCA9IHBjdF93ZXRfaGlnaCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID0gVFJVRSwgd2F0ZXIuYWN0ID0gVFJVRSkKCmJ1cnJfY3Vycl9kcnlfbW9kIDwtIHNpbS5lY3RvKG1pY3JvX2N1cnJfZHJ5LCBXd19nID0gV3dfZywgc2hhcGUgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG1heCA9IFRtYXgsIFRtaW4gPSBUbWluLCBDVG1pbiA9IENUbWluLCBDVG1heCA9IENUbWF4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWhhdiA9ICdib3RoJywgaW4uc2hhZGUgPSBUUlVFLCBidXJyb3cgPSBUUlVFLCBjbGltYiA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uaHlkID0gbWluX2h5ZCwgaHlkLmRlYXRoID0gaHlkLmRlYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoeWQucmF0ZSA9IGh5ZF9yYXRlLCBwY3Rfd2V0ID0gcGN0X3dldF9oaWdoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2F0ZXIgPSBUUlVFLCB3YXRlci5hY3QgPSBUUlVFKQoKYnVycl93YXJtX3dldF9tb2QgPC0gc2ltLmVjdG8obWljcm9fd2FybV93ZXQsIFd3X2cgPSBXd19nLCBzaGFwZSA9IDQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUbWF4ID0gVG1heCwgVG1pbiA9IFRtaW4sIENUbWluID0gQ1RtaW4sIENUbWF4ID0gQ1RtYXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlaGF2ID0gJ2JvdGgnLCBpbi5zaGFkZSA9IFRSVUUsIGJ1cnJvdyA9IFRSVUUsIGNsaW1iID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5oeWQgPSBtaW5faHlkLCBoeWQuZGVhdGggPSBoeWQuZGVhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh5ZC5yYXRlID0gaHlkX3JhdGUsIHBjdF93ZXQgPSBwY3Rfd2V0X2hpZ2gsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXRlciA9IFRSVUUsIHdhdGVyLmFjdCA9IFRSVUUpCgpidXJyX3dhcm1fZHJ5X21vZCA8LSBzaW0uZWN0byhtaWNyb193YXJtX2RyeSwgV3dfZyA9IFd3X2csIHNoYXBlID0gNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRtYXggPSBUbWF4LCBUbWluID0gVG1pbiwgQ1RtaW4gPSBDVG1pbiwgQ1RtYXggPSBDVG1heCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVoYXYgPSAnYm90aCcsIGluLnNoYWRlID0gVFJVRSwgYnVycm93ID0gVFJVRSwgY2xpbWIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmh5ZCA9IG1pbl9oeWQsIGh5ZC5kZWF0aCA9IGh5ZC5kZWF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHlkLnJhdGUgPSBoeWRfcmF0ZSwgcGN0X3dldCA9IHBjdF93ZXRfaGlnaCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID0gVFJVRSwgd2F0ZXIuYWN0ID0gVFJVRSkKYGBgCgoKYGBgIHtyIGFjdGl2ZX0KIyBTSEFERSBNT0RFTApzaGFkX2N1cnJfd2V0X2RmIDwtIGRhdGEuZnJhbWUoc2hhZF9jdXJyX3dldF9tb2QkYWN0KSAlPiUKICB0YWlsKC04Nzg0KSAlPiUgIyByZW1vdmUgcHJldmlvdXMgeWVhciAKICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiaG91ciIpICU+JQogIGRwbHlyOjpyZW5hbWUoYWN0aXZlID0gc2hhZF9jdXJyX3dldF9tb2QuYWN0KSAlPiUKICBkcGx5cjo6bXV0YXRlKGRheSA9IGNlaWxpbmcoMTo4NzYwLzI0KSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGRheSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShjdXJyX3dldCA9IGxlbmd0aChhY3RpdmVbYWN0aXZlID09IFRSVUVdKSkKCnNoYWRfY3Vycl9kcnlfZGYgPC0gZGF0YS5mcmFtZShzaGFkX2N1cnJfZHJ5X21vZCRhY3QpICU+JQogIHRhaWwoLTg3ODQpICU+JSAjIHJlbW92ZSBwcmV2aW91cyB5ZWFyIAogIHRpYmJsZTo6cm93aWRfdG9fY29sdW1uKCJob3VyIikgJT4lCiAgZHBseXI6OnJlbmFtZShhY3RpdmUgPSBzaGFkX2N1cnJfZHJ5X21vZC5hY3QpICU+JQogIGRwbHlyOjptdXRhdGUoZGF5ID0gY2VpbGluZygxOjg3NjAvMjQpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoZGF5KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGN1cnJfZHJ5ID0gbGVuZ3RoKGFjdGl2ZVthY3RpdmUgPT0gVFJVRV0pKQoKc2hhZF93YXJtX3dldF9kZiA8LSBkYXRhLmZyYW1lKHNoYWRfd2FybV93ZXRfbW9kJGFjdCkgJT4lCiAgdGFpbCgtODc4NCkgJT4lICMgcmVtb3ZlIHByZXZpb3VzIHllYXIgCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oImhvdXIiKSAlPiUKICBkcGx5cjo6cmVuYW1lKGFjdGl2ZSA9IHNoYWRfd2FybV93ZXRfbW9kLmFjdCkgJT4lCiAgZHBseXI6Om11dGF0ZShkYXkgPSBjZWlsaW5nKDE6ODc2MC8yNCkpICU+JQogIGRwbHlyOjpncm91cF9ieShkYXkpICU+JQogIGRwbHlyOjpzdW1tYXJpc2Uod2FybV93ZXQgPSBsZW5ndGgoYWN0aXZlW2FjdGl2ZSA9PSBUUlVFXSkpCgpzaGFkX3dhcm1fZHJ5X2RmIDwtIGRhdGEuZnJhbWUoc2hhZF93YXJtX2RyeV9tb2QkYWN0KSAlPiUKICB0YWlsKC04Nzg0KSAlPiUgIyByZW1vdmUgcHJldmlvdXMgeWVhciAKICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiaG91ciIpICU+JQogIGRwbHlyOjpyZW5hbWUoYWN0aXZlID0gc2hhZF93YXJtX2RyeV9tb2QuYWN0KSAlPiUKICBkcGx5cjo6bXV0YXRlKGRheSA9IGNlaWxpbmcoMTo4NzYwLzI0KSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGRheSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZSh3YXJtX2RyeSA9IGxlbmd0aChhY3RpdmVbYWN0aXZlID09IFRSVUVdKSkKCnNoYWRfbW9kZWwgPC0gc2hhZF9jdXJyX3dldF9kZiAlPiUKICBtZXJnZShzaGFkX2N1cnJfZHJ5X2RmLCBieSA9ICJkYXkiKSAlPiUKICBtZXJnZShzaGFkX3dhcm1fd2V0X2RmLCBieSA9ICJkYXkiKSAlPiUKICBtZXJnZShzaGFkX3dhcm1fZHJ5X2RmLCBieSA9ICJkYXkiKSAlPiUKICBwaXZvdF9sb25nZXIoIWRheSwgbmFtZXNfdG8gPSAiY29uZGl0aW9uIiwgdmFsdWVzX3RvID0gImhvdXJzIikgJT4lCiAgZHBseXI6Om11dGF0ZShjb25kaXRpb24gPSBmYWN0b3IoY29uZGl0aW9uLCBsZXZlbHMgPSBjKCJ3YXJtX2RyeSIsICJ3YXJtX3dldCIsICJjdXJyX2RyeSIsICJjdXJyX3dldCIpKSwKICAgICAgICAgICAgICAgIHNlYXNvbiA9IGNhc2Vfd2hlbigKICAgIGRheSA+PSAzMzUgfiAic3VtbWVyIiwKICAgIGRheSA+PSAxICYgZGF5IDw9IDYxIH4gInN1bW1lciIsCiAgICBkYXkgPj0gNjIgJiBkYXkgPD0gMTUzIH4gImF1dHVtbiIsCiAgICBkYXkgPj0gMTU0ICYgZGF5IDw9IDI0NCB+ICJ3aW50ZXIiLAogICAgZGF5ID49IDI0NSAmIGRheSA8PSAzMzQgfiAic3ByaW5nIgogICAgKSkKCiMgVFJFRSBNT0RFTAp0cmVlX2N1cnJfd2V0X2RmIDwtIGRhdGEuZnJhbWUodHJlZV9jdXJyX3dldF9tb2QkYWN0KSAlPiUKICB0YWlsKC04Nzg0KSAlPiUgIyByZW1vdmUgcHJldmlvdXMgeWVhciAKICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiaG91ciIpICU+JQogIGRwbHlyOjpyZW5hbWUoYWN0aXZlID0gdHJlZV9jdXJyX3dldF9tb2QuYWN0KSAlPiUKICBkcGx5cjo6bXV0YXRlKGRheSA9IGNlaWxpbmcoMTo4NzYwLzI0KSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGRheSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShjdXJyX3dldCA9IGxlbmd0aChhY3RpdmVbYWN0aXZlID09IFRSVUVdKSkKCnRyZWVfY3Vycl9kcnlfZGYgPC0gZGF0YS5mcmFtZSh0cmVlX2N1cnJfZHJ5X21vZCRhY3QpICU+JQogIHRhaWwoLTg3ODQpICU+JSAjIHJlbW92ZSBwcmV2aW91cyB5ZWFyIAogIHRpYmJsZTo6cm93aWRfdG9fY29sdW1uKCJob3VyIikgJT4lCiAgZHBseXI6OnJlbmFtZShhY3RpdmUgPSB0cmVlX2N1cnJfZHJ5X21vZC5hY3QpICU+JQogIGRwbHlyOjptdXRhdGUoZGF5ID0gY2VpbGluZygxOjg3NjAvMjQpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoZGF5KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGN1cnJfZHJ5ID0gbGVuZ3RoKGFjdGl2ZVthY3RpdmUgPT0gVFJVRV0pKQoKdHJlZV93YXJtX3dldF9kZiA8LSBkYXRhLmZyYW1lKHRyZWVfd2FybV93ZXRfbW9kJGFjdCkgJT4lCiAgdGFpbCgtODc4NCkgJT4lICMgcmVtb3ZlIHByZXZpb3VzIHllYXIgCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oImhvdXIiKSAlPiUKICBkcGx5cjo6cmVuYW1lKGFjdGl2ZSA9IHRyZWVfd2FybV93ZXRfbW9kLmFjdCkgJT4lCiAgZHBseXI6Om11dGF0ZShkYXkgPSBjZWlsaW5nKDE6ODc2MC8yNCkpICU+JQogIGRwbHlyOjpncm91cF9ieShkYXkpICU+JQogIGRwbHlyOjpzdW1tYXJpc2Uod2FybV93ZXQgPSBsZW5ndGgoYWN0aXZlW2FjdGl2ZSA9PSBUUlVFXSkpCgp0cmVlX3dhcm1fZHJ5X2RmIDwtIGRhdGEuZnJhbWUodHJlZV93YXJtX2RyeV9tb2QkYWN0KSAlPiUKICB0YWlsKC04Nzg0KSAlPiUgIyByZW1vdmUgcHJldmlvdXMgeWVhciAKICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiaG91ciIpICU+JQogIGRwbHlyOjpyZW5hbWUoYWN0aXZlID0gdHJlZV93YXJtX2RyeV9tb2QuYWN0KSAlPiUKICBkcGx5cjo6bXV0YXRlKGRheSA9IGNlaWxpbmcoMTo4NzYwLzI0KSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGRheSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZSh3YXJtX2RyeSA9IGxlbmd0aChhY3RpdmVbYWN0aXZlID09IFRSVUVdKSkKCnRyZWVfbW9kZWwgPC0gdHJlZV9jdXJyX3dldF9kZiAlPiUKICBtZXJnZSh0cmVlX2N1cnJfZHJ5X2RmLCBieSA9ICJkYXkiKSAlPiUKICBtZXJnZSh0cmVlX3dhcm1fd2V0X2RmLCBieSA9ICJkYXkiKSAlPiUKICBtZXJnZSh0cmVlX3dhcm1fZHJ5X2RmLCBieSA9ICJkYXkiKSAlPiUKICBwaXZvdF9sb25nZXIoIWRheSwgbmFtZXNfdG8gPSAiY29uZGl0aW9uIiwgdmFsdWVzX3RvID0gImhvdXJzIikgJT4lCiAgZHBseXI6Om11dGF0ZShjb25kaXRpb24gPSBmYWN0b3IoY29uZGl0aW9uLCBsZXZlbHMgPSBjKCJ3YXJtX2RyeSIsICJ3YXJtX3dldCIsICJjdXJyX2RyeSIsICJjdXJyX3dldCIpKSwKICAgICAgICAgICAgICAgIHNlYXNvbiA9IGNhc2Vfd2hlbigKICAgIGRheSA+PSAzMzUgfiAic3VtbWVyIiwKICAgIGRheSA+PSAxICYgZGF5IDw9IDYxIH4gInN1bW1lciIsCiAgICBkYXkgPj0gNjIgJiBkYXkgPD0gMTUzIH4gImF1dHVtbiIsCiAgICBkYXkgPj0gMTU0ICYgZGF5IDw9IDI0NCB+ICJ3aW50ZXIiLAogICAgZGF5ID49IDI0NSAmIGRheSA8PSAzMzQgfiAic3ByaW5nIgogICAgKSkKCiMgRk9TU09SSUFMIE1PREVMCmJ1cnJfY3Vycl93ZXRfZGYgPC0gZGF0YS5mcmFtZShidXJyX2N1cnJfd2V0X21vZCRhY3QpICU+JQogIHRhaWwoLTg3ODQpICU+JSAjIHJlbW92ZSBwcmV2aW91cyB5ZWFyIAogIHRpYmJsZTo6cm93aWRfdG9fY29sdW1uKCJob3VyIikgJT4lCiAgZHBseXI6OnJlbmFtZShhY3RpdmUgPSBidXJyX2N1cnJfd2V0X21vZC5hY3QpICU+JQogIGRwbHlyOjptdXRhdGUoZGF5ID0gY2VpbGluZygxOjg3NjAvMjQpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoZGF5KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGN1cnJfd2V0ID0gbGVuZ3RoKGFjdGl2ZVthY3RpdmUgPT0gVFJVRV0pKQoKYnVycl9jdXJyX2RyeV9kZiA8LSBkYXRhLmZyYW1lKGJ1cnJfY3Vycl9kcnlfbW9kJGFjdCkgJT4lCiAgdGFpbCgtODc4NCkgJT4lICMgcmVtb3ZlIHByZXZpb3VzIHllYXIgCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oImhvdXIiKSAlPiUKICBkcGx5cjo6cmVuYW1lKGFjdGl2ZSA9IGJ1cnJfY3Vycl9kcnlfbW9kLmFjdCkgJT4lCiAgZHBseXI6Om11dGF0ZShkYXkgPSBjZWlsaW5nKDE6ODc2MC8yNCkpICU+JQogIGRwbHlyOjpncm91cF9ieShkYXkpICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoY3Vycl9kcnkgPSBsZW5ndGgoYWN0aXZlW2FjdGl2ZSA9PSBUUlVFXSkpCgpidXJyX3dhcm1fd2V0X2RmIDwtIGRhdGEuZnJhbWUoYnVycl93YXJtX3dldF9tb2QkYWN0KSAlPiUKICB0YWlsKC04Nzg0KSAlPiUgIyByZW1vdmUgcHJldmlvdXMgeWVhciAKICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiaG91ciIpICU+JQogIGRwbHlyOjpyZW5hbWUoYWN0aXZlID0gYnVycl93YXJtX3dldF9tb2QuYWN0KSAlPiUKICBkcGx5cjo6bXV0YXRlKGRheSA9IGNlaWxpbmcoMTo4NzYwLzI0KSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGRheSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZSh3YXJtX3dldCA9IGxlbmd0aChhY3RpdmVbYWN0aXZlID09IFRSVUVdKSkKCmJ1cnJfd2FybV9kcnlfZGYgPC0gZGF0YS5mcmFtZShidXJyX3dhcm1fZHJ5X21vZCRhY3QpICU+JQogIHRhaWwoLTg3ODQpICU+JSAjIHJlbW92ZSBwcmV2aW91cyB5ZWFyIAogIHRpYmJsZTo6cm93aWRfdG9fY29sdW1uKCJob3VyIikgJT4lCiAgZHBseXI6OnJlbmFtZShhY3RpdmUgPSBidXJyX3dhcm1fZHJ5X21vZC5hY3QpICU+JQogIGRwbHlyOjptdXRhdGUoZGF5ID0gY2VpbGluZygxOjg3NjAvMjQpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoZGF5KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKHdhcm1fZHJ5ID0gbGVuZ3RoKGFjdGl2ZVthY3RpdmUgPT0gVFJVRV0pKQoKYnVycl9tb2RlbCA8LSBidXJyX2N1cnJfd2V0X2RmICU+JQogIG1lcmdlKGJ1cnJfY3Vycl9kcnlfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKGJ1cnJfd2FybV93ZXRfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKGJ1cnJfd2FybV9kcnlfZGYsIGJ5ID0gImRheSIpICU+JQogIHBpdm90X2xvbmdlcighZGF5LCBuYW1lc190byA9ICJjb25kaXRpb24iLCB2YWx1ZXNfdG8gPSAiaG91cnMiKSAlPiUKICBkcGx5cjo6bXV0YXRlKGNvbmRpdGlvbiA9IGZhY3Rvcihjb25kaXRpb24sIGxldmVscyA9IGMoIndhcm1fZHJ5IiwgIndhcm1fd2V0IiwgImN1cnJfZHJ5IiwgImN1cnJfd2V0IikpLAogICAgICAgICAgICAgICAgc2Vhc29uID0gY2FzZV93aGVuKAogICAgZGF5ID49IDMzNSB+ICJzdW1tZXIiLAogICAgZGF5ID49IDEgJiBkYXkgPD0gNjEgfiAic3VtbWVyIiwKICAgIGRheSA+PSA2MiAmIGRheSA8PSAxNTMgfiAiYXV0dW1uIiwKICAgIGRheSA+PSAxNTQgJiBkYXkgPD0gMjQ0IH4gIndpbnRlciIsCiAgICBkYXkgPj0gMjQ1ICYgZGF5IDw9IDMzNCB+ICJzcHJpbmciCiAgICApKQpgYGAKCiMjIE1vZGVsIG91dHB1dCAtIGVjb3R5cGVzIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19CgojIyMgVGFibGUgUzZhIC0gU3VtbWFyeSB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxscyAtfSAKCioqVGFibGUgUzZhLioqIFRvdGFsIHBvdGVudGlhbCBhY3Rpdml0eSBob3VycyBwZXIgeWVhciAoJHRfe2FjdH0kKSBmb3IgYSBgciBXd19nYCBnIGZyb2cgdW5kZXIgZGlmZmVyZW50IHdhcm1pbmcgKGN1cnJlbnQgb3Igd2FybWluZykgYW5kIGRyb3VnaHQgKG5vcm1hbCBvciBkcm91Z2h0KSBjb25kaXRpb25zIHdpdGggZGlmZmVyZW50IHdhdGVyLXNhdmluZyBzdHJhdGVnaWVzLgoKYGBgIHtyIHRhYmxlIHM2YX0KZGF0YS5mcmFtZShzdHJhdGVneSA9IGMoIlNoYWRlIG9ubHkiLCAiU2hhZGUgb25seSIsICJTaGFkZSBvbmx5IiwgIlNoYWRlIG9ubHkiLAogICAgICAgICAgICAgICAgICAgICAgICAiV2F0ZXJwcm9vZiIsICJXYXRlcnByb29mIiwgIldhdGVycHJvb2YiLCAiV2F0ZXJwcm9vZiIsCiAgICAgICAgICAgICAgICAgICAgICAgICJCdXJyb3dpbmciLCAiQnVycm93aW5nIiwgIkJ1cnJvd2luZyIsICJCdXJyb3dpbmciKSwKICAgICAgICAgICB0ZW1wID0gYygiY3VycmVudCIsICJjdXJyZW50IiwgIndhcm1pbmciLCAid2FybWluZyIpLAogICAgICAgICAgIHJhaW4gPSBjKCJub3JtYWwiLCAiZHJvdWdodCIpLAogICAgICAgICAgIHRfYWN0X2ggPSBjKHN1bShzaGFkX2N1cnJfd2V0X2RmJGN1cnJfd2V0KSwgc3VtKHNoYWRfY3Vycl9kcnlfZGYkY3Vycl9kcnkpLCBzdW0oc2hhZF93YXJtX3dldF9kZiR3YXJtX3dldCksIHN1bShzaGFkX3dhcm1fZHJ5X2RmJHdhcm1fZHJ5KSwKICAgICAgICAgICAgICAgICAgICAgICBzdW0odHJlZV9jdXJyX3dldF9kZiRjdXJyX3dldCksIHN1bSh0cmVlX2N1cnJfZHJ5X2RmJGN1cnJfZHJ5KSwgc3VtKHRyZWVfd2FybV93ZXRfZGYkd2FybV93ZXQpLCBzdW0odHJlZV93YXJtX2RyeV9kZiR3YXJtX2RyeSksCiAgICAgICAgICAgICAgICAgICAgICAgc3VtKGJ1cnJfY3Vycl93ZXRfZGYkY3Vycl93ZXQpLCBzdW0oYnVycl9jdXJyX2RyeV9kZiRjdXJyX2RyeSksIHN1bShidXJyX3dhcm1fd2V0X2RmJHdhcm1fd2V0KSwgc3VtKGJ1cnJfd2FybV9kcnlfZGYkd2FybV9kcnkpKSwKICAgICAgICAgICB0X2FjdF9wZXIgPSBjKHN1bShzaGFkX2N1cnJfd2V0X2RmJGN1cnJfd2V0KSAvIDg3NjAgKiAxMDAsIHN1bShzaGFkX2N1cnJfZHJ5X2RmJGN1cnJfZHJ5KSAvIDg3NjAgKiAxMDAsIHN1bShzaGFkX3dhcm1fd2V0X2RmJHdhcm1fd2V0KSAvIDg3NjAgKiAxMDAsIHN1bShzaGFkX3dhcm1fZHJ5X2RmJHdhcm1fZHJ5KSAvIDg3NjAgKiAxMDAsCiAgICAgICAgICAgICAgICAgICAgICAgc3VtKHRyZWVfY3Vycl93ZXRfZGYkY3Vycl93ZXQpIC8gODc2MCAqIDEwMCwgc3VtKHRyZWVfY3Vycl9kcnlfZGYkY3Vycl9kcnkpIC8gODc2MCAqIDEwMCwgc3VtKHRyZWVfd2FybV93ZXRfZGYkd2FybV93ZXQpIC8gODc2MCAqIDEwMCwgc3VtKHRyZWVfd2FybV9kcnlfZGYkd2FybV9kcnkpIC8gODc2MCAqIDEwMCwKICAgICAgICAgICAgICAgICAgICAgICBzdW0oYnVycl9jdXJyX3dldF9kZiRjdXJyX3dldCkgLyA4NzYwICogMTAwLCBzdW0oYnVycl9jdXJyX2RyeV9kZiRjdXJyX2RyeSkgLyA4NzYwICogMTAwLCBzdW0oYnVycl93YXJtX3dldF9kZiR3YXJtX3dldCkgLyA4NzYwICogMTAwLCBzdW0oYnVycl93YXJtX2RyeV9kZiR3YXJtX2RyeSkgLyA4NzYwICogMTAwKSkgJT4lCiAga25pdHI6OmthYmxlKGNvbC5uYW1lcyA9IGMoIldhdGVyLXNhdmluZyBzdHJhdGVneSIsICJXYXJtaW5nIHNpbXVsYXRpb24iLCAiRHJvdWdodCBzaW11bGF0aW9uIiwgIiR0X3thY3R9JCAoaCkiLCAiJHRfe2FjdH0kICglKSIpKQpgYGAKCioqKgoKIyMjIFRhYmxlIFM2YiAtIFJlbGF0aXZlIGNoYW5nZSB5ZWFyIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKKipUYWJsZSBTNmIuKiogQ2hhbmdlIGluICR0X3thY3R9JCAoJSkgZm9yIGVhY2ggd2F0ZXItc2F2aW5nIHN0cmF0ZWd5IHJlbGF0aXZlIHRvIHRoZSBjdXJyZW50IG5vcm1hbCBzY2VuYXJpbyB1bmRlciB3YXJtaW5nIG9ubHksIGRyb3VnaHQgb25seSwgYW5kIHdhcm1pbmcgYW5kIGRyb3VnaHQgY29tYmluZWQuIAoKYGBgIHtyIHRhYmxlIHM2Yn0KZGF0YS5mcmFtZShzdHJhdGVneSA9IGMoIlNoYWRlIG9ubHkiLCJXYXRlcnByb29mIiwgIkJ1cnJvd2luZyIpLAogICAgICAgICAgIGN1cnJfd2V0ID0gYyhzdW0oc2hhZF9jdXJyX3dldF9kZiRjdXJyX3dldCksIHN1bSh0cmVlX2N1cnJfd2V0X2RmJGN1cnJfd2V0KSwgc3VtKGJ1cnJfY3Vycl93ZXRfZGYkY3Vycl93ZXQpKSwKICAgICAgICAgICBjdXJyX2RyeSA9IGMoc3VtKHNoYWRfY3Vycl9kcnlfZGYkY3Vycl9kcnkpLCBzdW0odHJlZV9jdXJyX2RyeV9kZiRjdXJyX2RyeSksIHN1bShidXJyX2N1cnJfZHJ5X2RmJGN1cnJfZHJ5KSksCiAgICAgICAgICAgd2FybV93ZXQgPSBjKHN1bShzaGFkX3dhcm1fd2V0X2RmJHdhcm1fd2V0KSwgc3VtKHRyZWVfd2FybV93ZXRfZGYkd2FybV93ZXQpLCBzdW0oYnVycl93YXJtX3dldF9kZiR3YXJtX3dldCkpLAogICAgICAgICAgIHdhcm1fZHJ5ID0gYyhzdW0oc2hhZF93YXJtX2RyeV9kZiR3YXJtX2RyeSksIHN1bSh0cmVlX3dhcm1fZHJ5X2RmJHdhcm1fZHJ5KSwgc3VtKGJ1cnJfd2FybV9kcnlfZGYkd2FybV9kcnkpKSkgJT4lCiAgZHBseXI6Om11dGF0ZShkZWx0YV93YXJtICAgICA9ICh3YXJtX3dldCAtIGN1cnJfd2V0KSAvIGN1cnJfd2V0ICogMTAwLAogICAgICAgICAgICAgICAgZGVsdGFfZHJ5ICAgICAgPSAoY3Vycl9kcnkgLSBjdXJyX3dldCkgLyBjdXJyX3dldCAqIDEwMCwKICAgICAgICAgICAgICAgIGRlbHRhX3dhcm1fZHJ5ID0gKHdhcm1fZHJ5IC0gY3Vycl93ZXQpIC8gY3Vycl93ZXQgKiAxMDApICU+JQogIGRwbHlyOjpzZWxlY3QoLWMoY3Vycl93ZXQ6d2FybV9kcnkpKSAlPiUKICBrbml0cjo6a2FibGUoY29sLm5hbWVzID0gYygiV2F0ZXItc2F2aW5nIHN0cmF0ZWd5IiwgIiRcXERlbHRhJCB3YXJtaW5nIG9ubHkgKCUpIiwgIiRcXERlbHRhJCBkcm91Z2h0IG9ubHkgKCUpIiwgIiRcXERlbHRhJCB3YXJtaW5nIGFuZCBkcm91Z2h0ICglKSIpKQoKZGF0YS5mcmFtZShzdHJhdGVneSA9IGMoIlNoYWRlIG9ubHkiLCJXYXRlcnByb29mIiwgIkJ1cnJvd2luZyIpLAogICAgICAgICAgIGN1cnJfd2V0ID0gYyhzdW0oc2hhZF9jdXJyX3dldF9kZiRjdXJyX3dldCksIHN1bSh0cmVlX2N1cnJfd2V0X2RmJGN1cnJfd2V0KSwgc3VtKGJ1cnJfY3Vycl93ZXRfZGYkY3Vycl93ZXQpKSwKICAgICAgICAgICBjdXJyX2RyeSA9IGMoc3VtKHNoYWRfY3Vycl9kcnlfZGYkY3Vycl9kcnkpLCBzdW0odHJlZV9jdXJyX2RyeV9kZiRjdXJyX2RyeSksIHN1bShidXJyX2N1cnJfZHJ5X2RmJGN1cnJfZHJ5KSksCiAgICAgICAgICAgd2FybV93ZXQgPSBjKHN1bShzaGFkX3dhcm1fd2V0X2RmJHdhcm1fd2V0KSwgc3VtKHRyZWVfd2FybV93ZXRfZGYkd2FybV93ZXQpLCBzdW0oYnVycl93YXJtX3dldF9kZiR3YXJtX3dldCkpLAogICAgICAgICAgIHdhcm1fZHJ5ID0gYyhzdW0oc2hhZF93YXJtX2RyeV9kZiR3YXJtX2RyeSksIHN1bSh0cmVlX3dhcm1fZHJ5X2RmJHdhcm1fZHJ5KSwgc3VtKGJ1cnJfd2FybV9kcnlfZGYkd2FybV9kcnkpKSkgJT4lCiAgZHBseXI6Om11dGF0ZShkZWx0YV93YXJtICAgICA9ICh3YXJtX3dldCAtIGN1cnJfd2V0KSwKICAgICAgICAgICAgICAgIGRlbHRhX2RyeSAgICAgID0gKGN1cnJfZHJ5IC0gY3Vycl93ZXQpLAogICAgICAgICAgICAgICAgZGVsdGFfd2FybV9kcnkgPSAod2FybV9kcnkgLSBjdXJyX3dldCkpICU+JQogIGRwbHlyOjpzZWxlY3QoLWMoY3Vycl93ZXQ6d2FybV9kcnkpKSAlPiUKICBrbml0cjo6a2FibGUoY29sLm5hbWVzID0gYygiV2F0ZXItc2F2aW5nIHN0cmF0ZWd5IiwgIiRcXERlbHRhJCB3YXJtaW5nIG9ubHkgKCUpIiwgIiRcXERlbHRhJCBkcm91Z2h0IG9ubHkgKCUpIiwgIiRcXERlbHRhJCB3YXJtaW5nIGFuZCBkcm91Z2h0ICglKSIpKQpgYGAKCioqKgoKIyMjIFRhYmxlIFM2YyAtIFJlbGF0aXZlIGNoYW5nZSBzZWFzb24gey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHMgLX0gCgoqKlRhYmxlIFM2Yy4qKiBDaGFuZ2UgaW4gJHRfe2FjdH0kICglKSBmb3IgZWFjaCB3YXRlci1zYXZpbmcgc3RyYXRlZ3kgcmVsYXRpdmUgdG8gdGhlIGN1cnJlbnQgbm9ybWFsIHNjZW5hcmlvIHVuZGVyIHdhcm1pbmcgb25seSwgZHJvdWdodCBvbmx5LCBhbmQgd2FybWluZyBhbmQgZHJvdWdodCBjb21iaW5lZC4gCgpgYGAge3IgdGFibGUgczZjfQojIHN1bW1lcgpzaGFkX21vZGVsX3N1bW1lciA8LSBzaGFkX21vZGVsICU+JQogIGRwbHlyOjpmaWx0ZXIoc2Vhc29uID09ICJzdW1tZXIiKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGhvdXJzID0gc3VtKGhvdXJzKSkKCnRyZWVfbW9kZWxfc3VtbWVyIDwtIHRyZWVfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gInN1bW1lciIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKYnVycl9tb2RlbF9zdW1tZXIgPC0gYnVycl9tb2RlbCAlPiUKICBkcGx5cjo6ZmlsdGVyKHNlYXNvbiA9PSAic3VtbWVyIikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGNvbmRpdGlvbikgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShob3VycyA9IHN1bShob3VycykpCgp0YWJfc3VtbWVyIDwtIGRhdGEuZnJhbWUoc3RyYXRlZ3kgPSBjKCJTaGFkZSBvbmx5IiwiV2F0ZXJwcm9vZiIsICJCdXJyb3dpbmciKSwKICAgICAgICAgICBjdXJyX3dldCA9IGMoc2hhZF9tb2RlbF9zdW1tZXIkaG91cnNbNF0sIHRyZWVfbW9kZWxfc3VtbWVyJGhvdXJzWzRdLCBidXJyX21vZGVsX3N1bW1lciRob3Vyc1s0XSksCiAgICAgICAgICAgY3Vycl9kcnkgPSBjKHNoYWRfbW9kZWxfc3VtbWVyJGhvdXJzWzNdLCB0cmVlX21vZGVsX3N1bW1lciRob3Vyc1szXSwgYnVycl9tb2RlbF9zdW1tZXIkaG91cnNbM10pLAogICAgICAgICAgIHdhcm1fd2V0ID0gYyhzaGFkX21vZGVsX3N1bW1lciRob3Vyc1syXSwgdHJlZV9tb2RlbF9zdW1tZXIkaG91cnNbMl0sIGJ1cnJfbW9kZWxfc3VtbWVyJGhvdXJzWzJdKSwKICAgICAgICAgICB3YXJtX2RyeSA9IGMoc2hhZF9tb2RlbF9zdW1tZXIkaG91cnNbMV0sIHRyZWVfbW9kZWxfc3VtbWVyJGhvdXJzWzFdLCBidXJyX21vZGVsX3N1bW1lciRob3Vyc1sxXSkpICU+JQogIGRwbHlyOjptdXRhdGUoZGVsdGFfd2FybSAgICAgPSAod2FybV93ZXQgLSBjdXJyX3dldCkgLyBjdXJyX3dldCAqIDEwMCwKICAgICAgICAgICAgICAgIGRlbHRhX2RyeSAgICAgID0gKGN1cnJfZHJ5IC0gY3Vycl93ZXQpIC8gY3Vycl93ZXQgKiAxMDAsCiAgICAgICAgICAgICAgICBkZWx0YV93YXJtX2RyeSA9ICh3YXJtX2RyeSAtIGN1cnJfd2V0KSAvIGN1cnJfd2V0ICogMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1jKGN1cnJfd2V0Ondhcm1fZHJ5KSkgJT4lCiAgdGliYmxlOjphZGRfcm93KHN0cmF0ZWd5ID0gIioqU3VtbWVyKioiLCAuYmVmb3JlID0gMSkKCiMgYXV0dW1uCnNoYWRfbW9kZWxfYXV0dW1uIDwtIHNoYWRfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gImF1dHVtbiIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKdHJlZV9tb2RlbF9hdXR1bW4gPC0gdHJlZV9tb2RlbCAlPiUKICBkcGx5cjo6ZmlsdGVyKHNlYXNvbiA9PSAiYXV0dW1uIikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGNvbmRpdGlvbikgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShob3VycyA9IHN1bShob3VycykpCgpidXJyX21vZGVsX2F1dHVtbiA8LSBidXJyX21vZGVsICU+JQogIGRwbHlyOjpmaWx0ZXIoc2Vhc29uID09ICJhdXR1bW4iKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGhvdXJzID0gc3VtKGhvdXJzKSkKCnRhYl9hdXR1bW4gPC0gZGF0YS5mcmFtZShzdHJhdGVneSA9IGMoIlNoYWRlIG9ubHkiLCJXYXRlcnByb29mIiwgIkJ1cnJvd2luZyIpLAogICAgICAgICAgIGN1cnJfd2V0ID0gYyhzaGFkX21vZGVsX2F1dHVtbiRob3Vyc1s0XSwgdHJlZV9tb2RlbF9hdXR1bW4kaG91cnNbNF0sIGJ1cnJfbW9kZWxfYXV0dW1uJGhvdXJzWzRdKSwKICAgICAgICAgICBjdXJyX2RyeSA9IGMoc2hhZF9tb2RlbF9hdXR1bW4kaG91cnNbM10sIHRyZWVfbW9kZWxfYXV0dW1uJGhvdXJzWzNdLCBidXJyX21vZGVsX2F1dHVtbiRob3Vyc1szXSksCiAgICAgICAgICAgd2FybV93ZXQgPSBjKHNoYWRfbW9kZWxfYXV0dW1uJGhvdXJzWzJdLCB0cmVlX21vZGVsX2F1dHVtbiRob3Vyc1syXSwgYnVycl9tb2RlbF9hdXR1bW4kaG91cnNbMl0pLAogICAgICAgICAgIHdhcm1fZHJ5ID0gYyhzaGFkX21vZGVsX2F1dHVtbiRob3Vyc1sxXSwgdHJlZV9tb2RlbF9hdXR1bW4kaG91cnNbMV0sIGJ1cnJfbW9kZWxfYXV0dW1uJGhvdXJzWzFdKSkgJT4lCiAgZHBseXI6Om11dGF0ZShkZWx0YV93YXJtICAgICA9ICh3YXJtX3dldCAtIGN1cnJfd2V0KSAvIGN1cnJfd2V0ICogMTAwLAogICAgICAgICAgICAgICAgZGVsdGFfZHJ5ICAgICAgPSAoY3Vycl9kcnkgLSBjdXJyX3dldCkgLyBjdXJyX3dldCAqIDEwMCwKICAgICAgICAgICAgICAgIGRlbHRhX3dhcm1fZHJ5ID0gKHdhcm1fZHJ5IC0gY3Vycl93ZXQpIC8gY3Vycl93ZXQgKiAxMDApICU+JQogIGRwbHlyOjpzZWxlY3QoLWMoY3Vycl93ZXQ6d2FybV9kcnkpKSAlPiUKICB0aWJibGU6OmFkZF9yb3coc3RyYXRlZ3kgPSAiKipBdXR1bW4qKiIsIC5iZWZvcmUgPSAxKQoKIyB3aW50ZXIKc2hhZF9tb2RlbF93aW50ZXIgPC0gc2hhZF9tb2RlbCAlPiUKICBkcGx5cjo6ZmlsdGVyKHNlYXNvbiA9PSAid2ludGVyIikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGNvbmRpdGlvbikgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShob3VycyA9IHN1bShob3VycykpCgp0cmVlX21vZGVsX3dpbnRlciA8LSB0cmVlX21vZGVsICU+JQogIGRwbHlyOjpmaWx0ZXIoc2Vhc29uID09ICJ3aW50ZXIiKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGhvdXJzID0gc3VtKGhvdXJzKSkKCmJ1cnJfbW9kZWxfd2ludGVyIDwtIGJ1cnJfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gIndpbnRlciIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKdGFiX3dpbnRlciA8LSBkYXRhLmZyYW1lKHN0cmF0ZWd5ID0gYygiU2hhZGUgb25seSIsIldhdGVycHJvb2YiLCAiQnVycm93aW5nIiksCiAgICAgICAgICAgY3Vycl93ZXQgPSBjKHNoYWRfbW9kZWxfd2ludGVyJGhvdXJzWzRdLCB0cmVlX21vZGVsX3dpbnRlciRob3Vyc1s0XSwgYnVycl9tb2RlbF93aW50ZXIkaG91cnNbNF0pLAogICAgICAgICAgIGN1cnJfZHJ5ID0gYyhzaGFkX21vZGVsX3dpbnRlciRob3Vyc1szXSwgdHJlZV9tb2RlbF93aW50ZXIkaG91cnNbM10sIGJ1cnJfbW9kZWxfd2ludGVyJGhvdXJzWzNdKSwKICAgICAgICAgICB3YXJtX3dldCA9IGMoc2hhZF9tb2RlbF93aW50ZXIkaG91cnNbMl0sIHRyZWVfbW9kZWxfd2ludGVyJGhvdXJzWzJdLCBidXJyX21vZGVsX3dpbnRlciRob3Vyc1syXSksCiAgICAgICAgICAgd2FybV9kcnkgPSBjKHNoYWRfbW9kZWxfd2ludGVyJGhvdXJzWzFdLCB0cmVlX21vZGVsX3dpbnRlciRob3Vyc1sxXSwgYnVycl9tb2RlbF93aW50ZXIkaG91cnNbMV0pKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRlbHRhX3dhcm0gICAgID0gKHdhcm1fd2V0IC0gY3Vycl93ZXQpIC8gY3Vycl93ZXQgKiAxMDAsCiAgICAgICAgICAgICAgICBkZWx0YV9kcnkgICAgICA9IChjdXJyX2RyeSAtIGN1cnJfd2V0KSAvIGN1cnJfd2V0ICogMTAwLAogICAgICAgICAgICAgICAgZGVsdGFfd2FybV9kcnkgPSAod2FybV9kcnkgLSBjdXJyX3dldCkgLyBjdXJyX3dldCAqIDEwMCkgJT4lCiAgZHBseXI6OnNlbGVjdCgtYyhjdXJyX3dldDp3YXJtX2RyeSkpICU+JQogIHRpYmJsZTo6YWRkX3JvdyhzdHJhdGVneSA9ICIqKldpbnRlcioqIiwgLmJlZm9yZSA9IDEpCgojIHNwcmluZwpzaGFkX21vZGVsX3NwcmluZyA8LSBzaGFkX21vZGVsICU+JQogIGRwbHlyOjpmaWx0ZXIoc2Vhc29uID09ICJzcHJpbmciKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGhvdXJzID0gc3VtKGhvdXJzKSkKCnRyZWVfbW9kZWxfc3ByaW5nIDwtIHRyZWVfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gInNwcmluZyIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKYnVycl9tb2RlbF9zcHJpbmcgPC0gYnVycl9tb2RlbCAlPiUKICBkcGx5cjo6ZmlsdGVyKHNlYXNvbiA9PSAic3ByaW5nIikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGNvbmRpdGlvbikgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShob3VycyA9IHN1bShob3VycykpCgp0YWJfc3ByaW5nIDwtIGRhdGEuZnJhbWUoc3RyYXRlZ3kgPSBjKCJTaGFkZSBvbmx5IiwiV2F0ZXJwcm9vZiIsICJCdXJyb3dpbmciKSwKICAgICAgICAgICBjdXJyX3dldCA9IGMoc2hhZF9tb2RlbF9zcHJpbmckaG91cnNbNF0sIHRyZWVfbW9kZWxfc3ByaW5nJGhvdXJzWzRdLCBidXJyX21vZGVsX3NwcmluZyRob3Vyc1s0XSksCiAgICAgICAgICAgY3Vycl9kcnkgPSBjKHNoYWRfbW9kZWxfc3ByaW5nJGhvdXJzWzNdLCB0cmVlX21vZGVsX3NwcmluZyRob3Vyc1szXSwgYnVycl9tb2RlbF9zcHJpbmckaG91cnNbM10pLAogICAgICAgICAgIHdhcm1fd2V0ID0gYyhzaGFkX21vZGVsX3NwcmluZyRob3Vyc1syXSwgdHJlZV9tb2RlbF9zcHJpbmckaG91cnNbMl0sIGJ1cnJfbW9kZWxfc3ByaW5nJGhvdXJzWzJdKSwKICAgICAgICAgICB3YXJtX2RyeSA9IGMoc2hhZF9tb2RlbF9zcHJpbmckaG91cnNbMV0sIHRyZWVfbW9kZWxfc3ByaW5nJGhvdXJzWzFdLCBidXJyX21vZGVsX3NwcmluZyRob3Vyc1sxXSkpICU+JQogIGRwbHlyOjptdXRhdGUoZGVsdGFfd2FybSAgICAgPSAod2FybV93ZXQgLSBjdXJyX3dldCkgLyBjdXJyX3dldCAqIDEwMCwKICAgICAgICAgICAgICAgIGRlbHRhX2RyeSAgICAgID0gKGN1cnJfZHJ5IC0gY3Vycl93ZXQpIC8gY3Vycl93ZXQgKiAxMDAsCiAgICAgICAgICAgICAgICBkZWx0YV93YXJtX2RyeSA9ICh3YXJtX2RyeSAtIGN1cnJfd2V0KSAvIGN1cnJfd2V0ICogMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1jKGN1cnJfd2V0Ondhcm1fZHJ5KSkgJT4lCiAgdGliYmxlOjphZGRfcm93KHN0cmF0ZWd5ID0gIioqU3ByaW5nKioiLCAuYmVmb3JlID0gMSkKCiMgUmVuZGVyIHRhYmxlCmJpbmRfcm93cyh0YWJfc3VtbWVyLCB0YWJfYXV0dW1uLCB0YWJfd2ludGVyLCB0YWJfc3ByaW5nKSAlPiUgCiAgcmVtb3ZlX3Jvd25hbWVzKCkgJT4lIAogIGtuaXRyOjprYWJsZShjb2wubmFtZXMgPSBjKCJXYXRlci1zYXZpbmcgc3RyYXRlZ3kiLCAiJFxcRGVsdGEkIHdhcm1pbmcgb25seSAoJSkiLCAiJFxcRGVsdGEkIGRyb3VnaHQgb25seSAoJSkiLCAiJFxcRGVsdGEkIHdhcm1pbmcgYW5kIGRyb3VnaHQgKCUpIikpCmBgYAoKKioqCgojIyBTaW11bGF0ZSBhY3Rpdml0eSAtIGJpb21lcyB7LX0KClRvIHRlc3QgaWYgY2hhbmdlcyBpbiBhY3Rpdml0eSB1bmRlciBkaWZmZXJlbnQgY2xpbWF0ZSBzY2VuYXJpb3MgYXJlIGdlbmVyYWxpc2FibGUsIHdlIGFsc28gcmFuIHRoZSBzaGFkZS1vbmx5IG1vZGVsIHVuZGVyIHRocmVlIGFkZGl0aW9uYWwgcmVwcmVzZW50YXRpdmUgYmlvbWUgdHlwZXMgd2hlcmUgYW51cmFucyB0eXBpY2FsbHkgb2NjdXB5IGFuZCBhcmUgcHJlZGljdGVkIHRvIGluY3JlYXNlIGluIGRyb3VnaHQ6IHRyb3BpYyAoU2FsdmFkb3IsIEJyYXppbCksIHNlbWktYXJpZCAoVGFua3dhIEthcm9vLCBTb3V0aCBBZnJpY2EpLCBhbmQgTWVkaXRlcnJhbmVhbiAoU2V2aWxsZSwgU3BhaW4pICgqKkZpZy4gUzEwKiopLiBUaGUgYmlvbWUgbG9jYXRpb25zIHdlcmUgY2xhc3NpZmllZCBiYXNlZCBvbiB0aGUgW0vDtnBwZW4gY2xpbWF0ZSBjbGFzc2lmaWNhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSyVDMyVCNnBwZW5fY2xpbWF0ZV9jbGFzc2lmaWNhdGlvbikuIEFsbCBtaWNyb2NsaW1hdGUgc2ltdWxhdGlvbnMgcmFuIGZvciAyMDE2LTIwMTcgYW5kIGZvciB0aGUgc2FtZSBoeXBvdGhldGljYWwgZnJvZy4KCldlIGZpcnN0IGRvd25sb2FkZWQgdGhlIG1pY3JvY2xpbWF0ZXMgbG9jYWxseSB3aXRoIHRoZSBmdW5jdGlvbiBiZWxvdyAoZWRpdGVkIGJ5IE0uIEtlYXJuZXkpLgoKYGBge3IgbWNlcmFfbG9jYWwsIGV2YWw9RkFMU0UsIGVjaG89VH0Kc291cmNlKCcuLi9taWNyb19lcmE1X2xvY2FsMi5SJykgIyBhIHZlcnNpb24gb2YgbWljcm9fZXJhNSB0aGF0IHJlYWRzIGZyb20gbG9jYWxseSBkb3dubG9hZGVkIHRpbGVzIG9mIHRoZSB3aG9sZSBwbGFuZXQKCiMgRGVmaW5lIGxvY2F0aW9ucyBhbmQgc2NlbmFyaW9zCmxvY2F0aW9ucyA8LSBsaXN0KAogIGxpc3QobmFtZSA9ICJCcmF6aWwiLCBsb25nbGF0ID0gYygtMzkuMTY1NTMsIC0xMy4wNTAyOSkpLAogIGxpc3QobmFtZSA9ICJTb3V0aCBBZnJpY2EiLCBsb25nbGF0ID0gYygxOS44NTY2LCAtMzIuNDI5NykpLAogIGxpc3QobmFtZSA9ICJTcGFpbiIsIGxvbmdsYXQgPSBjKC01LjU1MzgsIDM3LjA0MTQzKSksCiAgbGlzdChuYW1lID0gIkF1c3RyYWxpYSIsIGxvbmdsYXQgPSBjKDE1My4wOTI0OSwgLTI3LjYyMzUpKQopCgpzY2VuYXJpb3MgPC0gbGlzdCgKICBsaXN0KG5hbWUgPSAiQ3VycmVudCBub3JtYWwiLCByYWlubXVsdCA9IDEuMiwgd2FybSA9IDApLAogIGxpc3QobmFtZSA9ICJDdXJyZW50IGRyeSIsIHJhaW5tdWx0ID0gMC41LCB3YXJtID0gMCksCiAgbGlzdChuYW1lID0gIldhcm1pbmcgbm9ybWFsIiwgcmFpbm11bHQgPSAxLjIsIHdhcm0gPSA0KSwKICBsaXN0KG5hbWUgPSAiV2FybWluZyBkcnkiLCByYWlubXVsdCA9IDAuNSwgd2FybSA9IDQpCikKCiMgRnVuY3Rpb24gdG8gcnVuIG1pY3JvX2VyYTUgYW5kIHNhdmUgb3V0cHV0CnJ1bl9taWNyb19lcmE1IDwtIGZ1bmN0aW9uKGxvY2F0aW9uPWxvY2F0aW9uLCBzY2VuYXJpbz1zY2VuYXJpbykgewogICMgRXh0cmFjdCBwYXJhbWV0ZXJzCiAgbG9uZ2xhdCA8LSBsb2NhdGlvbiRsb25nbGF0CiAgbmFtZSA8LSBwYXN0ZShsb2NhdGlvbiRuYW1lLCBzY2VuYXJpbyRuYW1lLCBzZXAgPSAiXyIpCiAgcmFpbm11bHQgPC0gc2NlbmFyaW8kcmFpbmZhY3QKICB3YXJtIDwtIHNjZW5hcmlvJHdhcm0KICBjYXQobmFtZSwgcmFpbm11bHQsIHdhcm0sICdcbicpCiAgIyBSdW4gbWljcm9fZXJhNQogIHJlc3VsdCA8LSBtaWNyb19lcmE1X2xvY2FsKGxvYyA9IGxvbmdsYXQsCiAgICAgICAgICAgICAgICAgICAgICAgcmFpbm11bHQgPSByYWlubXVsdCwKICAgICAgICAgICAgICAgICAgICAgICB3YXJtID0gd2FybSwKICAgICAgICAgICAgICAgICAgICAgICBkc3RhcnQgPSAiMDEvMDEvMjAxNiIsIAogICAgICAgICAgICAgICAgICAgICAgIGRmaW5pc2ggPSAiMzEvMTIvMjAxNyIsCiAgICAgICAgICAgICAgICAgICAgICAgc3BhdGlhbCA9ICIvc3J2LzYzMDAtcHJlZGVjb2wvZGF0YS9FUkE1L3RpbWUiCiAgICAgICAgICAgICAgICAgICAgICAgKQoKICAjIFNhdmUgb3V0cHV0CiAgb3V0cHV0X2ZpbGUgPC0gcGFzdGUwKG5hbWUsICIucmRzIikKICBzYXZlUkRTKHJlc3VsdCwgZmlsZSA9IG91dHB1dF9maWxlKQp9CgojIExvb3Agb3ZlciBsb2NhdGlvbnMgYW5kIHNjZW5hcmlvcwpmb3IgKGkgaW4gMTpsZW5ndGgobG9jYXRpb25zKSkgewogIGZvciAoaiBpbiAxOmxlbmd0aChzY2VuYXJpb3MpKSB7CiAgICBydW5fbWljcm9fZXJhNShsb2NhdGlvbnNbaV1bWzFdXSwgc2NlbmFyaW9zW2pdW1sxXV0pCiAgfQp9CmBgYAoKRHVlIHRvIHRoZSBsb25nIHByb2Nlc3NpbmcgdGltZSBmb3IgZG93bmxvYWRpbmcgbWljcm9jbGltYXRlIGZvciBlYWNoIHNpdGUsIHdlIHNhdmVkIHRoZSBtaWNyb2NsaW1hdGUgbG9jYWxseSwgYW5kIGxvYWRlZCB0aGVtIGhlcmUuCgpgYGAge3IgYmlvbWUgbG9hZH0KbWljcm9fY3Vycl93ZXRfYnIgPC0gcmVhZFJEUygibWljcm9fb3V0cHV0L0JyYXppbF9DdXJyZW50IG5vcm1hbC5yZHMiKQptaWNyb19jdXJyX2RyeV9iciA8LSByZWFkUkRTKCJtaWNyb19vdXRwdXQvQnJhemlsX0N1cnJlbnQgZHJ5LnJkcyIpCm1pY3JvX3dhcm1fd2V0X2JyIDwtIHJlYWRSRFMoIm1pY3JvX291dHB1dC9CcmF6aWxfV2FybWluZyBub3JtYWwucmRzIikKbWljcm9fd2FybV9kcnlfYnIgPC0gcmVhZFJEUygibWljcm9fb3V0cHV0L0JyYXppbF9XYXJtaW5nIGRyeS5yZHMiKQoKbWljcm9fY3Vycl93ZXRfc2EgPC0gcmVhZFJEUygibWljcm9fb3V0cHV0L1NvdXRoIEFmcmljYV9DdXJyZW50IG5vcm1hbC5yZHMiKQptaWNyb19jdXJyX2RyeV9zYSA8LSByZWFkUkRTKCJtaWNyb19vdXRwdXQvU291dGggQWZyaWNhX0N1cnJlbnQgZHJ5LnJkcyIpCm1pY3JvX3dhcm1fd2V0X3NhIDwtIHJlYWRSRFMoIm1pY3JvX291dHB1dC9Tb3V0aCBBZnJpY2FfV2FybWluZyBub3JtYWwucmRzIikKbWljcm9fd2FybV9kcnlfc2EgPC0gcmVhZFJEUygibWljcm9fb3V0cHV0L1NvdXRoIEFmcmljYV9XYXJtaW5nIGRyeS5yZHMiKQoKbWljcm9fY3Vycl93ZXRfc3AgPC0gcmVhZFJEUygibWljcm9fb3V0cHV0L1NwYWluX0N1cnJlbnQgbm9ybWFsLnJkcyIpCm1pY3JvX2N1cnJfZHJ5X3NwIDwtIHJlYWRSRFMoIm1pY3JvX291dHB1dC9TcGFpbl9DdXJyZW50IGRyeS5yZHMiKQptaWNyb193YXJtX3dldF9zcCA8LSByZWFkUkRTKCJtaWNyb19vdXRwdXQvU3BhaW5fV2FybWluZyBub3JtYWwucmRzIikKbWljcm9fd2FybV9kcnlfc3AgPC0gcmVhZFJEUygibWljcm9fb3V0cHV0L1NwYWluX1dhcm1pbmcgZHJ5LnJkcyIpCmBgYAoKYGBge3IgRmlnIFMxMCwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD05fQptb2RlbF9yYWluX3dldF9iciA8LSBhcy5kYXRhLmZyYW1lKG1pY3JvX2N1cnJfd2V0X2JyJFJBSU5GQUxMKSAlPiUKICB0YWlsKC0zNjYpICU+JSAjIHJlbW92ZSAyMDE2IHNpbXVsYXRpb24KICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiRE9ZIikgJT4lCiAgcmVuYW1lKHJhaW5mYWxsX21tID0gIm1pY3JvX2N1cnJfd2V0X2JyJFJBSU5GQUxMIikKCm1vZGVsX3JhaW5fd2V0X3NhIDwtIGFzLmRhdGEuZnJhbWUobWljcm9fY3Vycl93ZXRfc2EkUkFJTkZBTEwpICU+JQogIHRhaWwoLTM2NikgJT4lICMgcmVtb3ZlIDIwMTYgc2ltdWxhdGlvbgogIHRpYmJsZTo6cm93aWRfdG9fY29sdW1uKCJET1kiKSAlPiUKICByZW5hbWUocmFpbmZhbGxfbW0gPSAibWljcm9fY3Vycl93ZXRfc2EkUkFJTkZBTEwiKQoKbW9kZWxfcmFpbl93ZXRfc3AgPC0gYXMuZGF0YS5mcmFtZShtaWNyb19jdXJyX3dldF9zcCRSQUlORkFMTCkgJT4lCiAgdGFpbCgtMzY2KSAlPiUgIyByZW1vdmUgMjAxNiBzaW11bGF0aW9uCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oIkRPWSIpICU+JQogIHJlbmFtZShyYWluZmFsbF9tbSA9ICJtaWNyb19jdXJyX3dldF9zcCRSQUlORkFMTCIpCgpwMSA8LSBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShkYXRhID0gbW9kZWxfcmFpbl93ZXQsIGFlcyh4ID0gRE9ZLCB5ID0gcmFpbmZhbGxfbW0gKiAxLjIpLCBjb2xvdXIgPSAiZGFya2dyZXkiKSArCiAgeWxhYigiRGFpbHkgcmFpbmZhbGwgKG1tKSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGltID0gYygwLCAxMDApLCBleHBhbmQgPSBjKDAsMCksIHBvc2l0aW9uID0gInJpZ2h0IikgKyAKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgMzY1KSkgKwogIG15dGhlbWUoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCgpwMiA8LSBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShkYXRhID0gbW9kZWxfcmFpbl93ZXRfYnIsIGFlcyh4ID0gRE9ZLCB5ID0gcmFpbmZhbGxfbW0gKiAxLjIpLCBjb2xvdXIgPSAiZGFya2dyZXkiKSArCiAgeWxhYigiRGFpbHkgcmFpbmZhbGwgKG1tKSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGltID0gYygwLCAxMDApLCBleHBhbmQgPSBjKDAsMCksIHBvc2l0aW9uID0gInJpZ2h0IikgKyAKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgMzY1KSkgKwogIG15dGhlbWUoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCgpwMyA8LSBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShkYXRhID0gbW9kZWxfcmFpbl93ZXRfc2EsIGFlcyh4ID0gRE9ZLCB5ID0gcmFpbmZhbGxfbW0gKiAxLjIpLCAgY29sb3VyID0gImRhcmtncmV5IikgKwogIHlsYWIoIkRhaWx5IHJhaW5mYWxsIChtbSkiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbSA9IGMoMCwgMTAwKSwgZXhwYW5kID0gYygwLDApLCBwb3NpdGlvbiA9ICJyaWdodCIpICsgCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDM2NSkpICsKICBteXRoZW1lKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKcDQgPC0gZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IG1vZGVsX3JhaW5fd2V0X3NwLCBhZXMoeCA9IERPWSwgeSA9IHJhaW5mYWxsX21tICogMS4yKSwgIGNvbG91ciA9ICJkYXJrZ3JleSIpICsKICB5bGFiKCJEYWlseSByYWluZmFsbCAobW0pIikgKwogIHNjYWxlX3hfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArIAogIHNjYWxlX3lfY29udGludW91cyhsaW0gPSBjKDAsIDEwMCksIGV4cGFuZCA9IGMoMCwwKSwgcG9zaXRpb24gPSAicmlnaHQiKSArIAogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCAzNjUpKSArCiAgbXl0aGVtZSgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKCnQxIDwtIGdncGxvdCgpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBkYXRhLmZyYW1lKG1pY3JvX2N1cnJfd2V0JHNoYWRzb2lsKSwgYWVzKHggPSBET1ksIHkgPSBEMGNtKSkgKwogIHlsYWIoZXhwcmVzc2lvbigiU2hhZGVkIn5pdGFsaWMoIlQiKVsic29pbCJdKiIgKMKwQykiKSkgKwogIGdndGl0bGUoIlN1YnRyb3BpYyIsIHN1YnRpdGxlID0gIkJyaXNiYW5lLCBBdXN0cmFsaWEiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltID0gYygtNSwgNTApLCBleHBhbmQgPSBjKDAsMCkpICsgCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDM2NSkpICsKICBteXRoZW1lKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKdDIgPC0gZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGRhdGEuZnJhbWUobWljcm9fY3Vycl93ZXRfYnIkc2hhZHNvaWwpLCBhZXMoeCA9IERPWSwgeSA9IEQwY20pKSArCiAgeWxhYihleHByZXNzaW9uKCJTaGFkZWQifml0YWxpYygiVCIpWyJzb2lsIl0qIiAowrBDKSIpKSArCiAgZ2d0aXRsZSgiVHJvcGljIiwgc3VidGl0bGUgPSAiU2FsdmFkb3IsIEJyYXppbCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGltID0gYygtNSwgNTApLCBleHBhbmQgPSBjKDAsMCkpICsgCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDM2NSkpICsKICBteXRoZW1lKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKdDMgPC0gZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGRhdGEuZnJhbWUobWljcm9fY3Vycl93ZXRfc2Ekc2hhZHNvaWwpLCBhZXMoeCA9IERPWSwgeSA9IEQwY20pKSArCiAgeWxhYihleHByZXNzaW9uKCJTaGFkZWQifml0YWxpYygiVCIpWyJzb2lsIl0qIiAowrBDKSIpKSArCiAgZ2d0aXRsZSgiU2VtaS1hcmlkIiwgc3VidGl0bGUgPSAiVGFua3dhIEthcm9vLCBTb3V0aCBBZnJpY2EiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbSA9IGMoLTUsIDUwKSwgZXhwYW5kID0gYygwLDApKSArIAogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCAzNjUpKSArCiAgbXl0aGVtZSgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKCnQ0IDwtIGdncGxvdCgpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBkYXRhLmZyYW1lKG1pY3JvX2N1cnJfd2V0X3NwJHNoYWRzb2lsKSwgYWVzKHggPSBET1ksIHkgPSBEMGNtKSkgKwogIHlsYWIoZXhwcmVzc2lvbigiU2hhZGVkIn5pdGFsaWMoIlQiKVsic29pbCJdKiIgKMKwQykiKSkgKwogIGdndGl0bGUoIk1lZGl0ZXJyYW5lYW4iLCBzdWJ0aXRsZSA9ICJTZXZpbGxlLCBTcGFpbiIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGltID0gYygtNSwgNTApLCBleHBhbmQgPSBjKDAsMCkpICsgCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDM2NSkpICsKICBteXRoZW1lKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKYWxpZ25lZF9wbG90cyA8LSBhbGlnbl9wbG90cyhwMSwgdDEsIGFsaWduID0gImh2IiwgYXhpcyA9ICJ0YmxyIikKYXVfcGxvdCA8LSBnZ2RyYXcoYWxpZ25lZF9wbG90c1tbMV1dKSArIGRyYXdfcGxvdChhbGlnbmVkX3Bsb3RzW1syXV0pCgphbGlnbmVkX3Bsb3RzIDwtIGFsaWduX3Bsb3RzKHAyLCB0MiwgYWxpZ24gPSAiaHYiLCBheGlzID0gInRibHIiKQpicl9wbG90IDwtIGdnZHJhdyhhbGlnbmVkX3Bsb3RzW1sxXV0pICsgZHJhd19wbG90KGFsaWduZWRfcGxvdHNbWzJdXSkKCmFsaWduZWRfcGxvdHMgPC0gYWxpZ25fcGxvdHMocDMsIHQzLCBhbGlnbiA9ICJodiIsIGF4aXMgPSAidGJsciIpCnNhX3Bsb3QgPC0gZ2dkcmF3KGFsaWduZWRfcGxvdHNbWzFdXSkgKyBkcmF3X3Bsb3QoYWxpZ25lZF9wbG90c1tbMl1dKQoKYWxpZ25lZF9wbG90cyA8LSBhbGlnbl9wbG90cyhwNCwgdDQsIGFsaWduID0gImh2IiwgYXhpcyA9ICJ0YmxyIikKc3BfcGxvdCA8LSBnZ2RyYXcoYWxpZ25lZF9wbG90c1tbMV1dKSArIGRyYXdfcGxvdChhbGlnbmVkX3Bsb3RzW1syXV0pCgpjb3dwbG90OjpwbG90X2dyaWQoYXVfcGxvdCwgYnJfcGxvdCwgc2FfcGxvdCwgc3BfcGxvdCwgbmNvbCA9IDIsIGxhYmVscyA9IGMoJ2EnLCAnYicsICdjJywgJ2QnKSkKYGBgCgoqKkZpZy4gUzEwLioqIERpZmZlcmVuY2VzIGluIHNoYWRlZCBzb2lsIHRlbXBlcmF0dXJlICgqVCp+c2tpbn4sIMKwQzsgYmxhY2sgbGluZXMpIGFuZCBkYWlseSByYWluZmFsbCAobW07IGByIGthYmxlRXh0cmE6OnRleHRfc3BlYygiZ3JleSIsIGNvbG9yID0gIiM2YjZiNmIiKWAgbGluZXMpIHRoYXQgYW51cmFucyBhcmUgZXhwZWN0ZWQgdG8gZXhwZXJpZW5jZSB1bmRlciBhIHJlcHJlc2VuYXRpdmUgKCoqYSoqKSBzdWJ0cm9waWMgYmlvbWUgKHRvdGFsIHJhaW5mYWxsID0gYHIgc3VtKG1vZGVsX3JhaW5fd2V0JHJhaW5mYWxsX21tKSAqIDEuMmAgbW0pLCAoKipiKiopIHRyb3BpYyBiaW9tZSAodG90YWwgcmFpbmZhbGwgPSBgciBzdW0obW9kZWxfcmFpbl93ZXRfYnIkcmFpbmZhbGxfbW0pICogMS4yYCBtbSksICgqKmMqKikgc2VtaS1hcmlkIGJpb21lICh0b3RhbCByYWluZmFsbCA9IGByIHN1bShtb2RlbF9yYWluX3dldF9zYSRyYWluZmFsbF9tbSkgKiAxLjJgIG1tKSwgYW5kICgqKmQqKikgIE1lZGl0ZXJyYW5lYW4gYmlvbWUgKHRvdGFsIHJhaW5mYWxsID0gYHIgc3VtKG1vZGVsX3JhaW5fd2V0X3NwJHJhaW5mYWxsX21tKSAqIDEuMmAgbW0pLgoKYGBge3IgZnJvZ19zaW0yLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFLCByZXN1bHRzPSJoaWRlIn0KIyBCUkFaSUwgTU9ERUwKY3Vycl93ZXRfbW9kX2JyIDwtIHNpbS5lY3RvKG1pY3JvX2N1cnJfd2V0X2JyLCBXd19nID0gV3dfZywgc2hhcGUgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG1heCA9IFRtYXgsIFRtaW4gPSBUbWluLCBDVG1pbiA9IENUbWluLCBDVG1heCA9IENUbWF4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWhhdiA9ICdib3RoJywgaW4uc2hhZGUgPSBUUlVFLCBidXJyb3cgPSBGQUxTRSwgY2xpbWIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmh5ZCA9IG1pbl9oeWQsIGh5ZC5kZWF0aCA9IGh5ZC5kZWF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHlkLnJhdGUgPSBoeWRfcmF0ZSwgcGN0X3dldCA9IHBjdF93ZXRfaGlnaCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID0gRkFMU0UsIHdhdGVyLmFjdCA9IFRSVUUpCgpjdXJyX2RyeV9tb2RfYnIgPC0gc2ltLmVjdG8obWljcm9fY3Vycl9kcnlfYnIsIFd3X2cgPSBXd19nLCBzaGFwZSA9IDQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUbWF4ID0gVG1heCwgVG1pbiA9IFRtaW4sIENUbWluID0gQ1RtaW4sIENUbWF4ID0gQ1RtYXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlaGF2ID0gJ2JvdGgnLCBpbi5zaGFkZSA9IFRSVUUsIGJ1cnJvdyA9IEZBTFNFLCBjbGltYiA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uaHlkID0gbWluX2h5ZCwgaHlkLmRlYXRoID0gaHlkLmRlYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoeWQucmF0ZSA9IGh5ZF9yYXRlLCBwY3Rfd2V0ID0gcGN0X3dldF9oaWdoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2F0ZXIgPSBGQUxTRSwgd2F0ZXIuYWN0ID0gVFJVRSkKCndhcm1fd2V0X21vZF9iciA8LSBzaW0uZWN0byhtaWNyb193YXJtX3dldF9iciwgV3dfZyA9IFd3X2csIHNoYXBlID0gNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRtYXggPSBUbWF4LCBUbWluID0gVG1pbiwgQ1RtaW4gPSBDVG1pbiwgQ1RtYXggPSBDVG1heCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVoYXYgPSAnYm90aCcsIGluLnNoYWRlID0gVFJVRSwgYnVycm93ID0gRkFMU0UsIGNsaW1iID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5oeWQgPSBtaW5faHlkLCBoeWQuZGVhdGggPSBoeWQuZGVhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh5ZC5yYXRlID0gaHlkX3JhdGUsIHBjdF93ZXQgPSBwY3Rfd2V0X2hpZ2gsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXRlciA9IEZBTFNFLCB3YXRlci5hY3QgPSBUUlVFKQoKd2FybV9kcnlfbW9kX2JyIDwtIHNpbS5lY3RvKG1pY3JvX3dhcm1fZHJ5X2JyLCBXd19nID0gV3dfZywgc2hhcGUgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG1heCA9IFRtYXgsIFRtaW4gPSBUbWluLCBDVG1pbiA9IENUbWluLCBDVG1heCA9IENUbWF4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWhhdiA9ICdib3RoJywgaW4uc2hhZGUgPSBUUlVFLCBidXJyb3cgPSBGQUxTRSwgY2xpbWIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmh5ZCA9IG1pbl9oeWQsIGh5ZC5kZWF0aCA9IGh5ZC5kZWF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHlkLnJhdGUgPSBoeWRfcmF0ZSwgcGN0X3dldCA9IHBjdF93ZXRfaGlnaCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID0gRkFMU0UsIHdhdGVyLmFjdCA9IFRSVUUpCgojIFNPVVRIIEFGUklDQSBNT0RFTApjdXJyX3dldF9tb2Rfc2EgPC0gc2ltLmVjdG8obWljcm9fY3Vycl93ZXRfc2EsIFd3X2cgPSBXd19nLCBzaGFwZSA9IDQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUbWF4ID0gVG1heCwgVG1pbiA9IFRtaW4sIENUbWluID0gQ1RtaW4sIENUbWF4ID0gQ1RtYXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlaGF2ID0gJ2JvdGgnLCBpbi5zaGFkZSA9IFRSVUUsIGJ1cnJvdyA9IEZBTFNFLCBjbGltYiA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uaHlkID0gbWluX2h5ZCwgaHlkLmRlYXRoID0gaHlkLmRlYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoeWQucmF0ZSA9IGh5ZF9yYXRlLCBwY3Rfd2V0ID0gcGN0X3dldF9oaWdoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2F0ZXIgPSBGQUxTRSwgd2F0ZXIuYWN0ID0gVFJVRSkKCmN1cnJfZHJ5X21vZF9zYSA8LSBzaW0uZWN0byhtaWNyb19jdXJyX2RyeV9zYSwgV3dfZyA9IFd3X2csIHNoYXBlID0gNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRtYXggPSBUbWF4LCBUbWluID0gVG1pbiwgQ1RtaW4gPSBDVG1pbiwgQ1RtYXggPSBDVG1heCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVoYXYgPSAnYm90aCcsIGluLnNoYWRlID0gVFJVRSwgYnVycm93ID0gRkFMU0UsIGNsaW1iID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5oeWQgPSBtaW5faHlkLCBoeWQuZGVhdGggPSBoeWQuZGVhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh5ZC5yYXRlID0gaHlkX3JhdGUsIHBjdF93ZXQgPSBwY3Rfd2V0X2hpZ2gsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXRlciA9IEZBTFNFLCB3YXRlci5hY3QgPSBUUlVFKQoKd2FybV93ZXRfbW9kX3NhIDwtIHNpbS5lY3RvKG1pY3JvX3dhcm1fd2V0X3NhLCBXd19nID0gV3dfZywgc2hhcGUgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG1heCA9IFRtYXgsIFRtaW4gPSBUbWluLCBDVG1pbiA9IENUbWluLCBDVG1heCA9IENUbWF4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWhhdiA9ICdib3RoJywgaW4uc2hhZGUgPSBUUlVFLCBidXJyb3cgPSBGQUxTRSwgY2xpbWIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmh5ZCA9IG1pbl9oeWQsIGh5ZC5kZWF0aCA9IGh5ZC5kZWF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHlkLnJhdGUgPSBoeWRfcmF0ZSwgcGN0X3dldCA9IHBjdF93ZXRfaGlnaCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID0gRkFMU0UsIHdhdGVyLmFjdCA9IFRSVUUpCgp3YXJtX2RyeV9tb2Rfc2EgPC0gc2ltLmVjdG8obWljcm9fd2FybV9kcnlfc2EsIFd3X2cgPSBXd19nLCBzaGFwZSA9IDQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUbWF4ID0gVG1heCwgVG1pbiA9IFRtaW4sIENUbWluID0gQ1RtaW4sIENUbWF4ID0gQ1RtYXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlaGF2ID0gJ2JvdGgnLCBpbi5zaGFkZSA9IFRSVUUsIGJ1cnJvdyA9IEZBTFNFLCBjbGltYiA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uaHlkID0gbWluX2h5ZCwgaHlkLmRlYXRoID0gaHlkLmRlYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoeWQucmF0ZSA9IGh5ZF9yYXRlLCBwY3Rfd2V0ID0gcGN0X3dldF9oaWdoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2F0ZXIgPSBGQUxTRSwgd2F0ZXIuYWN0ID0gVFJVRSkKCiMgU1BBSU4gTU9ERUwKY3Vycl93ZXRfbW9kX3NwIDwtIHNpbS5lY3RvKG1pY3JvX2N1cnJfd2V0X3NwLCBXd19nID0gV3dfZywgc2hhcGUgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG1heCA9IFRtYXgsIFRtaW4gPSBUbWluLCBDVG1pbiA9IENUbWluLCBDVG1heCA9IENUbWF4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWhhdiA9ICdib3RoJywgaW4uc2hhZGUgPSBUUlVFLCBidXJyb3cgPSBGQUxTRSwgY2xpbWIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmh5ZCA9IG1pbl9oeWQsIGh5ZC5kZWF0aCA9IGh5ZC5kZWF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHlkLnJhdGUgPSBoeWRfcmF0ZSwgcGN0X3dldCA9IHBjdF93ZXRfaGlnaCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID0gRkFMU0UsIHdhdGVyLmFjdCA9IFRSVUUpCgpjdXJyX2RyeV9tb2Rfc3AgPC0gc2ltLmVjdG8obWljcm9fY3Vycl9kcnlfc3AsIFd3X2cgPSBXd19nLCBzaGFwZSA9IDQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUbWF4ID0gVG1heCwgVG1pbiA9IFRtaW4sIENUbWluID0gQ1RtaW4sIENUbWF4ID0gQ1RtYXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlaGF2ID0gJ2JvdGgnLCBpbi5zaGFkZSA9IFRSVUUsIGJ1cnJvdyA9IEZBTFNFLCBjbGltYiA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uaHlkID0gbWluX2h5ZCwgaHlkLmRlYXRoID0gaHlkLmRlYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoeWQucmF0ZSA9IGh5ZF9yYXRlLCBwY3Rfd2V0ID0gcGN0X3dldF9oaWdoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2F0ZXIgPSBGQUxTRSwgd2F0ZXIuYWN0ID0gVFJVRSkKCndhcm1fd2V0X21vZF9zcCA8LSBzaW0uZWN0byhtaWNyb193YXJtX3dldF9zcCwgV3dfZyA9IFd3X2csIHNoYXBlID0gNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRtYXggPSBUbWF4LCBUbWluID0gVG1pbiwgQ1RtaW4gPSBDVG1pbiwgQ1RtYXggPSBDVG1heCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVoYXYgPSAnYm90aCcsIGluLnNoYWRlID0gVFJVRSwgYnVycm93ID0gRkFMU0UsIGNsaW1iID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5oeWQgPSBtaW5faHlkLCBoeWQuZGVhdGggPSBoeWQuZGVhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh5ZC5yYXRlID0gaHlkX3JhdGUsIHBjdF93ZXQgPSBwY3Rfd2V0X2hpZ2gsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXRlciA9IEZBTFNFLCB3YXRlci5hY3QgPSBUUlVFKQoKd2FybV9kcnlfbW9kX3NwIDwtIHNpbS5lY3RvKG1pY3JvX3dhcm1fZHJ5X3NwLCBXd19nID0gV3dfZywgc2hhcGUgPSA0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG1heCA9IFRtYXgsIFRtaW4gPSBUbWluLCBDVG1pbiA9IENUbWluLCBDVG1heCA9IENUbWF4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWhhdiA9ICdib3RoJywgaW4uc2hhZGUgPSBUUlVFLCBidXJyb3cgPSBGQUxTRSwgY2xpbWIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmh5ZCA9IG1pbl9oeWQsIGh5ZC5kZWF0aCA9IGh5ZC5kZWF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHlkLnJhdGUgPSBoeWRfcmF0ZSwgcGN0X3dldCA9IHBjdF93ZXRfaGlnaCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID0gRkFMU0UsIHdhdGVyLmFjdCA9IFRSVUUpCmBgYAoKYGBgIHtyIGFjdGl2ZSBjbGltfQojIEJSQVpJTCBNT0RFTApjdXJyX3dldF9icl9kZiA8LSBkYXRhLmZyYW1lKGN1cnJfd2V0X21vZF9iciRhY3QpICU+JQogIHRhaWwoLTg3ODQpICU+JSAjIHJlbW92ZSBwcmV2aW91cyB5ZWFyIAogIHRpYmJsZTo6cm93aWRfdG9fY29sdW1uKCJob3VyIikgJT4lCiAgZHBseXI6OnJlbmFtZShhY3RpdmUgPSBjdXJyX3dldF9tb2RfYnIuYWN0KSAlPiUKICBkcGx5cjo6bXV0YXRlKGRheSA9IGNlaWxpbmcoMTo4NzYwLzI0KSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGRheSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShjdXJyX3dldCA9IGxlbmd0aChhY3RpdmVbYWN0aXZlID09IFRSVUVdKSkKCmN1cnJfZHJ5X2JyX2RmIDwtIGRhdGEuZnJhbWUoY3Vycl9kcnlfbW9kX2JyJGFjdCkgJT4lCiAgdGFpbCgtODc4NCkgJT4lICMgcmVtb3ZlIHByZXZpb3VzIHllYXIgCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oImhvdXIiKSAlPiUKICBkcGx5cjo6cmVuYW1lKGFjdGl2ZSA9IGN1cnJfZHJ5X21vZF9ici5hY3QpICU+JQogIGRwbHlyOjptdXRhdGUoZGF5ID0gY2VpbGluZygxOjg3NjAvMjQpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoZGF5KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGN1cnJfZHJ5ID0gbGVuZ3RoKGFjdGl2ZVthY3RpdmUgPT0gVFJVRV0pKQoKd2FybV93ZXRfYnJfZGYgPC0gZGF0YS5mcmFtZSh3YXJtX3dldF9tb2RfYnIkYWN0KSAlPiUKICB0YWlsKC04Nzg0KSAlPiUgIyByZW1vdmUgcHJldmlvdXMgeWVhciAKICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiaG91ciIpICU+JQogIGRwbHlyOjpyZW5hbWUoYWN0aXZlID0gd2FybV93ZXRfbW9kX2JyLmFjdCkgJT4lCiAgZHBseXI6Om11dGF0ZShkYXkgPSBjZWlsaW5nKDE6ODc2MC8yNCkpICU+JQogIGRwbHlyOjpncm91cF9ieShkYXkpICU+JQogIGRwbHlyOjpzdW1tYXJpc2Uod2FybV93ZXQgPSBsZW5ndGgoYWN0aXZlW2FjdGl2ZSA9PSBUUlVFXSkpCgp3YXJtX2RyeV9icl9kZiA8LSBkYXRhLmZyYW1lKHdhcm1fZHJ5X21vZF9iciRhY3QpICU+JQogIHRhaWwoLTg3ODQpICU+JSAjIHJlbW92ZSBwcmV2aW91cyB5ZWFyIAogIHRpYmJsZTo6cm93aWRfdG9fY29sdW1uKCJob3VyIikgJT4lCiAgZHBseXI6OnJlbmFtZShhY3RpdmUgPSB3YXJtX2RyeV9tb2RfYnIuYWN0KSAlPiUKICBkcGx5cjo6bXV0YXRlKGRheSA9IGNlaWxpbmcoMTo4NzYwLzI0KSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGRheSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZSh3YXJtX2RyeSA9IGxlbmd0aChhY3RpdmVbYWN0aXZlID09IFRSVUVdKSkKCmJyX21vZGVsIDwtIGN1cnJfd2V0X2JyX2RmICU+JQogIG1lcmdlKGN1cnJfZHJ5X2JyX2RmLCBieSA9ICJkYXkiKSAlPiUKICBtZXJnZSh3YXJtX3dldF9icl9kZiwgYnkgPSAiZGF5IikgJT4lCiAgbWVyZ2Uod2FybV9kcnlfYnJfZGYsIGJ5ID0gImRheSIpICU+JQogIHBpdm90X2xvbmdlcighZGF5LCBuYW1lc190byA9ICJjb25kaXRpb24iLCB2YWx1ZXNfdG8gPSAiaG91cnMiKSAlPiUKICBkcGx5cjo6bXV0YXRlKGNvbmRpdGlvbiA9IGZhY3Rvcihjb25kaXRpb24sIGxldmVscyA9IGMoIndhcm1fZHJ5IiwgIndhcm1fd2V0IiwgImN1cnJfZHJ5IiwgImN1cnJfd2V0IikpLAogICAgICAgICAgICAgICAgc2Vhc29uID0gY2FzZV93aGVuKAogICAgZGF5ID49IDMzNSB+ICJzdW1tZXIiLAogICAgZGF5ID49IDEgJiBkYXkgPD0gNjEgfiAic3VtbWVyIiwKICAgIGRheSA+PSA2MiAmIGRheSA8PSAxNTMgfiAiYXV0dW1uIiwKICAgIGRheSA+PSAxNTQgJiBkYXkgPD0gMjQ0IH4gIndpbnRlciIsCiAgICBkYXkgPj0gMjQ1ICYgZGF5IDw9IDMzNCB+ICJzcHJpbmciCiAgICApKQoKIyBTT1VUSCBBRlJJQ0EgTU9ERUwKY3Vycl93ZXRfc2FfZGYgPC0gZGF0YS5mcmFtZShjdXJyX3dldF9tb2Rfc2EkYWN0KSAlPiUKICB0YWlsKC04Nzg0KSAlPiUgIyByZW1vdmUgcHJldmlvdXMgeWVhciAKICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiaG91ciIpICU+JQogIGRwbHlyOjpyZW5hbWUoYWN0aXZlID0gY3Vycl93ZXRfbW9kX3NhLmFjdCkgJT4lCiAgZHBseXI6Om11dGF0ZShkYXkgPSBjZWlsaW5nKDE6ODc2MC8yNCkpICU+JQogIGRwbHlyOjpncm91cF9ieShkYXkpICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoY3Vycl93ZXQgPSBsZW5ndGgoYWN0aXZlW2FjdGl2ZSA9PSBUUlVFXSkpCgpjdXJyX2RyeV9zYV9kZiA8LSBkYXRhLmZyYW1lKGN1cnJfZHJ5X21vZF9zYSRhY3QpICU+JQogIHRhaWwoLTg3ODQpICU+JSAjIHJlbW92ZSBwcmV2aW91cyB5ZWFyIAogIHRpYmJsZTo6cm93aWRfdG9fY29sdW1uKCJob3VyIikgJT4lCiAgZHBseXI6OnJlbmFtZShhY3RpdmUgPSBjdXJyX2RyeV9tb2Rfc2EuYWN0KSAlPiUKICBkcGx5cjo6bXV0YXRlKGRheSA9IGNlaWxpbmcoMTo4NzYwLzI0KSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGRheSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShjdXJyX2RyeSA9IGxlbmd0aChhY3RpdmVbYWN0aXZlID09IFRSVUVdKSkKCndhcm1fd2V0X3NhX2RmIDwtIGRhdGEuZnJhbWUod2FybV93ZXRfbW9kX3NhJGFjdCkgJT4lCiAgdGFpbCgtODc4NCkgJT4lICMgcmVtb3ZlIHByZXZpb3VzIHllYXIgCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oImhvdXIiKSAlPiUKICBkcGx5cjo6cmVuYW1lKGFjdGl2ZSA9IHdhcm1fd2V0X21vZF9zYS5hY3QpICU+JQogIGRwbHlyOjptdXRhdGUoZGF5ID0gY2VpbGluZygxOjg3NjAvMjQpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoZGF5KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKHdhcm1fd2V0ID0gbGVuZ3RoKGFjdGl2ZVthY3RpdmUgPT0gVFJVRV0pKQoKd2FybV9kcnlfc2FfZGYgPC0gZGF0YS5mcmFtZSh3YXJtX2RyeV9tb2Rfc2EkYWN0KSAlPiUKICB0YWlsKC04Nzg0KSAlPiUgIyByZW1vdmUgcHJldmlvdXMgeWVhciAKICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiaG91ciIpICU+JQogIGRwbHlyOjpyZW5hbWUoYWN0aXZlID0gd2FybV9kcnlfbW9kX3NhLmFjdCkgJT4lCiAgZHBseXI6Om11dGF0ZShkYXkgPSBjZWlsaW5nKDE6ODc2MC8yNCkpICU+JQogIGRwbHlyOjpncm91cF9ieShkYXkpICU+JQogIGRwbHlyOjpzdW1tYXJpc2Uod2FybV9kcnkgPSBsZW5ndGgoYWN0aXZlW2FjdGl2ZSA9PSBUUlVFXSkpCgpzYV9tb2RlbCA8LSBjdXJyX3dldF9zYV9kZiAlPiUKICBtZXJnZShjdXJyX2RyeV9zYV9kZiwgYnkgPSAiZGF5IikgJT4lCiAgbWVyZ2Uod2FybV93ZXRfc2FfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKHdhcm1fZHJ5X3NhX2RmLCBieSA9ICJkYXkiKSAlPiUKICBwaXZvdF9sb25nZXIoIWRheSwgbmFtZXNfdG8gPSAiY29uZGl0aW9uIiwgdmFsdWVzX3RvID0gImhvdXJzIikgJT4lCiAgZHBseXI6Om11dGF0ZShjb25kaXRpb24gPSBmYWN0b3IoY29uZGl0aW9uLCBsZXZlbHMgPSBjKCJ3YXJtX2RyeSIsICJ3YXJtX3dldCIsICJjdXJyX2RyeSIsICJjdXJyX3dldCIpKSwKICAgICAgICAgICAgICAgIHNlYXNvbiA9IGNhc2Vfd2hlbigKICAgIGRheSA+PSAzMzUgfiAic3VtbWVyIiwKICAgIGRheSA+PSAxICYgZGF5IDw9IDYxIH4gInN1bW1lciIsCiAgICBkYXkgPj0gNjIgJiBkYXkgPD0gMTUzIH4gImF1dHVtbiIsCiAgICBkYXkgPj0gMTU0ICYgZGF5IDw9IDI0NCB+ICJ3aW50ZXIiLAogICAgZGF5ID49IDI0NSAmIGRheSA8PSAzMzQgfiAic3ByaW5nIgogICAgKSkKCiMgU1BBSU4gTU9ERUwKY3Vycl93ZXRfc3BfZGYgPC0gZGF0YS5mcmFtZShjdXJyX3dldF9tb2Rfc3AkYWN0KSAlPiUKICB0YWlsKC04Nzg0KSAlPiUgIyByZW1vdmUgcHJldmlvdXMgeWVhciAKICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiaG91ciIpICU+JQogIGRwbHlyOjpyZW5hbWUoYWN0aXZlID0gY3Vycl93ZXRfbW9kX3NwLmFjdCkgJT4lCiAgZHBseXI6Om11dGF0ZShkYXkgPSBjZWlsaW5nKDE6ODc2MC8yNCkpICU+JQogIGRwbHlyOjpncm91cF9ieShkYXkpICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoY3Vycl93ZXQgPSBsZW5ndGgoYWN0aXZlW2FjdGl2ZSA9PSBUUlVFXSkpCgpjdXJyX2RyeV9zcF9kZiA8LSBkYXRhLmZyYW1lKGN1cnJfZHJ5X21vZF9zcCRhY3QpICU+JQogIHRhaWwoLTg3ODQpICU+JSAjIHJlbW92ZSBwcmV2aW91cyB5ZWFyIAogIHRpYmJsZTo6cm93aWRfdG9fY29sdW1uKCJob3VyIikgJT4lCiAgZHBseXI6OnJlbmFtZShhY3RpdmUgPSBjdXJyX2RyeV9tb2Rfc3AuYWN0KSAlPiUKICBkcGx5cjo6bXV0YXRlKGRheSA9IGNlaWxpbmcoMTo4NzYwLzI0KSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGRheSkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShjdXJyX2RyeSA9IGxlbmd0aChhY3RpdmVbYWN0aXZlID09IFRSVUVdKSkKCndhcm1fd2V0X3NwX2RmIDwtIGRhdGEuZnJhbWUod2FybV93ZXRfbW9kX3NwJGFjdCkgJT4lCiAgdGFpbCgtODc4NCkgJT4lICMgcmVtb3ZlIHByZXZpb3VzIHllYXIgCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oImhvdXIiKSAlPiUKICBkcGx5cjo6cmVuYW1lKGFjdGl2ZSA9IHdhcm1fd2V0X21vZF9zcC5hY3QpICU+JQogIGRwbHlyOjptdXRhdGUoZGF5ID0gY2VpbGluZygxOjg3NjAvMjQpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoZGF5KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKHdhcm1fd2V0ID0gbGVuZ3RoKGFjdGl2ZVthY3RpdmUgPT0gVFJVRV0pKQoKd2FybV9kcnlfc3BfZGYgPC0gZGF0YS5mcmFtZSh3YXJtX2RyeV9tb2Rfc3AkYWN0KSAlPiUKICB0YWlsKC04Nzg0KSAlPiUgIyByZW1vdmUgcHJldmlvdXMgeWVhciAKICB0aWJibGU6OnJvd2lkX3RvX2NvbHVtbigiaG91ciIpICU+JQogIGRwbHlyOjpyZW5hbWUoYWN0aXZlID0gd2FybV9kcnlfbW9kX3NwLmFjdCkgJT4lCiAgZHBseXI6Om11dGF0ZShkYXkgPSBjZWlsaW5nKDE6ODc2MC8yNCkpICU+JQogIGRwbHlyOjpncm91cF9ieShkYXkpICU+JQogIGRwbHlyOjpzdW1tYXJpc2Uod2FybV9kcnkgPSBsZW5ndGgoYWN0aXZlW2FjdGl2ZSA9PSBUUlVFXSkpCgpzcF9tb2RlbCA8LSBjdXJyX3dldF9zcF9kZiAlPiUKICBtZXJnZShjdXJyX2RyeV9zcF9kZiwgYnkgPSAiZGF5IikgJT4lCiAgbWVyZ2Uod2FybV93ZXRfc3BfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKHdhcm1fZHJ5X3NwX2RmLCBieSA9ICJkYXkiKSAlPiUKICBwaXZvdF9sb25nZXIoIWRheSwgbmFtZXNfdG8gPSAiY29uZGl0aW9uIiwgdmFsdWVzX3RvID0gImhvdXJzIikgJT4lCiAgZHBseXI6Om11dGF0ZShjb25kaXRpb24gPSBmYWN0b3IoY29uZGl0aW9uLCBsZXZlbHMgPSBjKCJ3YXJtX2RyeSIsICJ3YXJtX3dldCIsICJjdXJyX2RyeSIsICJjdXJyX3dldCIpKSwKICAgICAgICAgICAgICAgIHNlYXNvbiA9IGNhc2Vfd2hlbigKICAgIGRheSA+PSAzMzUgfiAid2ludGVyIiwKICAgIGRheSA+PSAxICYgZGF5IDw9IDYxIH4gIndpbnRlciIsCiAgICBkYXkgPj0gNjIgJiBkYXkgPD0gMTUzIH4gInNwcmluZyIsCiAgICBkYXkgPj0gMTU0ICYgZGF5IDw9IDI0NCB+ICJzdW1tZXIiLAogICAgZGF5ID49IDI0NSAmIGRheSA8PSAzMzQgfiAiYXV0dW1uIgogICAgKSkKYGBgCgojIyBNb2RlbCBvdXRwdXQgLSBiaW9tZXMgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHMgLX0KCiMjIyBUYWJsZSBTN2EgLSBTdW1tYXJ5IHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKKipUYWJsZSBTN2EuKiogVG90YWwgcG90ZW50aWFsIGFjdGl2aXR5IGhvdXJzIHBlciB5ZWFyICgkdF97YWN0fSQpIGZvciBhIGByIFd3X2dgIGcgZnJvZyB1bmRlciBkaWZmZXJlbnQgd2FybWluZyAoY3VycmVudCBvciB3YXJtaW5nKSBhbmQgZHJvdWdodCAobm9ybWFsIG9yIGRyb3VnaHQpIGNvbmRpdGlvbnMgYWNyb3NzIHJlcHJlc2VuYXRpdmUgYmlvbWVzLgoKYGBgIHtyIHRhYmxlIHM3YX0KZGF0YS5mcmFtZShiaW9tZSA9IGMoIlN1YnRyb3BpYyIsICJTdWJ0cm9waWMiLCAiU3VidHJvcGljIiwgIlN1YnRyb3BpYyIsCiAgICAgICAgICAgICAgICAgICAgICJUcm9waWMiLCAiVHJvcGljIiwgIlRyb3BpYyIsICJUcm9waWMiLAogICAgICAgICAgICAgICAgICAgICAiU2VtaS1hcmlkIiwgIlNlbWktYXJpZCIsICJTZW1pLWFyaWQiLCAiU2VtaS1hcmlkIiwKICAgICAgICAgICAgICAgICAgICAgIk1lZGl0ZXJyYW5lYW4iLCAiTWVkaXRlcnJhbmVhbiIsICJNZWRpdGVycmFuZWFuIiwgIk1lZGl0ZXJyYW5lYW4iKSwKICAgICAgICAgICB0ZW1wID0gYygiY3VycmVudCIsICJjdXJyZW50IiwgIndhcm1pbmciLCAid2FybWluZyIpLAogICAgICAgICAgIHJhaW4gPSBjKCJub3JtYWwiLCAiZHJvdWdodCIpLAogICAgICAgICAgIHRfYWN0X2ggPSBjKHN1bShzaGFkX2N1cnJfd2V0X2RmJGN1cnJfd2V0KSwgc3VtKHNoYWRfY3Vycl9kcnlfZGYkY3Vycl9kcnkpLAogICAgICAgICAgICAgICAgICAgICAgIHN1bShzaGFkX3dhcm1fd2V0X2RmJHdhcm1fd2V0KSwgc3VtKHNoYWRfd2FybV9kcnlfZGYkd2FybV9kcnkpLCAKICAgICAgICAgICAgICAgICAgICAgICBzdW0oY3Vycl93ZXRfYnJfZGYkY3Vycl93ZXQpLCBzdW0oY3Vycl9kcnlfYnJfZGYkY3Vycl9kcnkpLCAKICAgICAgICAgICAgICAgICAgICAgICBzdW0od2FybV93ZXRfYnJfZGYkd2FybV93ZXQpLCBzdW0od2FybV9kcnlfYnJfZGYkd2FybV9kcnkpLCAKICAgICAgICAgICAgICAgICAgICAgICBzdW0oY3Vycl93ZXRfc2FfZGYkY3Vycl93ZXQpLCBzdW0oY3Vycl9kcnlfc2FfZGYkY3Vycl9kcnkpLCAKICAgICAgICAgICAgICAgICAgICAgICBzdW0od2FybV93ZXRfc2FfZGYkd2FybV93ZXQpLCBzdW0od2FybV9kcnlfc2FfZGYkd2FybV9kcnkpLCAKICAgICAgICAgICAgICAgICAgICAgICBzdW0oY3Vycl93ZXRfc3BfZGYkY3Vycl93ZXQpLCBzdW0oY3Vycl9kcnlfc3BfZGYkY3Vycl9kcnkpLAogICAgICAgICAgICAgICAgICAgICAgIHN1bSh3YXJtX3dldF9zcF9kZiR3YXJtX3dldCksIHN1bSh3YXJtX2RyeV9zcF9kZiR3YXJtX2RyeSkpLAogICAgICAgICAgIHRfYWN0X3BlciA9IGMoc3VtKHNoYWRfY3Vycl93ZXRfZGYkY3Vycl93ZXQpIC8gODc2MCAqIDEwMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBzdW0oc2hhZF9jdXJyX2RyeV9kZiRjdXJyX2RyeSkgLyA4NzYwICogMTAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHN1bShzaGFkX3dhcm1fd2V0X2RmJHdhcm1fd2V0KSAvIDg3NjAgKiAxMDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgc3VtKHNoYWRfd2FybV9kcnlfZGYkd2FybV9kcnkpIC8gODc2MCAqIDEwMCwKICAgICAgICAgICAgICAgICAgICAgICBzdW0oY3Vycl93ZXRfYnJfZGYkY3Vycl93ZXQpIC8gODc2MCAqIDEwMCwgCiAgICAgICAgICAgICAgICAgICAgICAgc3VtKGN1cnJfZHJ5X2JyX2RmJGN1cnJfZHJ5KSAvIDg3NjAgKiAxMDAsIAogICAgICAgICAgICAgICAgICAgICAgIHN1bSh3YXJtX3dldF9icl9kZiR3YXJtX3dldCkgLyA4NzYwICogMTAwLCAKICAgICAgICAgICAgICAgICAgICAgICBzdW0od2FybV9kcnlfYnJfZGYkd2FybV9kcnkpIC8gODc2MCAqIDEwMCwKICAgICAgICAgICAgICAgICAgICAgICBzdW0oY3Vycl93ZXRfc2FfZGYkY3Vycl93ZXQpIC8gODc2MCAqIDEwMCwgCiAgICAgICAgICAgICAgICAgICAgICAgc3VtKGN1cnJfZHJ5X3NhX2RmJGN1cnJfZHJ5KSAvIDg3NjAgKiAxMDAsIAogICAgICAgICAgICAgICAgICAgICAgIHN1bSh3YXJtX3dldF9zYV9kZiR3YXJtX3dldCkgLyA4NzYwICogMTAwLCAKICAgICAgICAgICAgICAgICAgICAgICBzdW0od2FybV9kcnlfc2FfZGYkd2FybV9kcnkpIC8gODc2MCAqIDEwMCwKICAgICAgICAgICAgICAgICAgICAgICBzdW0oY3Vycl93ZXRfc3BfZGYkY3Vycl93ZXQpIC8gODc2MCAqIDEwMCwgCiAgICAgICAgICAgICAgICAgICAgICAgc3VtKGN1cnJfZHJ5X3NwX2RmJGN1cnJfZHJ5KSAvIDg3NjAgKiAxMDAsIAogICAgICAgICAgICAgICAgICAgICAgIHN1bSh3YXJtX3dldF9zcF9kZiR3YXJtX3dldCkgLyA4NzYwICogMTAwLCAKICAgICAgICAgICAgICAgICAgICAgICBzdW0od2FybV9kcnlfc3BfZGYkd2FybV9kcnkpIC8gODc2MCAqIDEwMCkpICU+JQogIGtuaXRyOjprYWJsZShjb2wubmFtZXMgPSBjKCJCaW9tZSIsICJXYXJtaW5nIHNpbXVsYXRpb24iLCAiRHJvdWdodCBzaW11bGF0aW9uIiwgIiR0X3thY3R9JCAoaCkiLCAiJHRfe2FjdH0kICglKSIpKQpgYGAKCioqKgoKIyMjIFRhYmxlIFM3YiAtIFJlbGF0aXZlIGNoYW5nZSB5ZWFyIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKKipUYWJsZSBTN2IuKiogQ2hhbmdlIGluICR0X3thY3R9JCAoJSkgZiB0byB0aGUgY3VycmVudCBub3JtYWwgc2NlbmFyaW8gdW5kZXIgd2FybWluZyBvbmx5LCBkcm91Z2h0IG9ubHksIGFuZCB3YXJtaW5nIGFuZCBkcm91Z2h0IGNvbWJpbmVkIGZvciBhIGh5cG90aGV0aWNhbCBmcm9nIGluIGRpZmZlcmVudCBiaW9tZXMuIAoKYGBgIHtyIHRhYmxlIHM3Yn0KZGF0YS5mcmFtZShiaW9tZSA9IGMoIlN1YnRyb3BpYyIsIlRyb3BpYyIsICJTZW1pLWFyaWQiLCAiTWVkaXRlcnJhbmVhbiIpLAogICAgICAgICAgIGN1cnJfd2V0ID0gYyhzdW0oc2hhZF9jdXJyX3dldF9kZiRjdXJyX3dldCksIHN1bShjdXJyX3dldF9icl9kZiRjdXJyX3dldCksIHN1bShjdXJyX3dldF9zYV9kZiRjdXJyX3dldCksIHN1bShjdXJyX3dldF9zcF9kZiRjdXJyX3dldCkpLAogICAgICAgICAgIGN1cnJfZHJ5ID0gYyhzdW0oc2hhZF9jdXJyX2RyeV9kZiRjdXJyX2RyeSksIHN1bShjdXJyX2RyeV9icl9kZiRjdXJyX2RyeSksIHN1bShjdXJyX2RyeV9zYV9kZiRjdXJyX2RyeSksIHN1bShjdXJyX2RyeV9zcF9kZiRjdXJyX2RyeSkpLAogICAgICAgICAgIHdhcm1fd2V0ID0gYyhzdW0oc2hhZF93YXJtX3dldF9kZiR3YXJtX3dldCksIHN1bSh3YXJtX3dldF9icl9kZiR3YXJtX3dldCksIHN1bSh3YXJtX3dldF9zYV9kZiR3YXJtX3dldCksIHN1bSh3YXJtX3dldF9zcF9kZiR3YXJtX3dldCkpLAogICAgICAgICAgIHdhcm1fZHJ5ID0gYyhzdW0oc2hhZF93YXJtX2RyeV9kZiR3YXJtX2RyeSksIHN1bSh3YXJtX2RyeV9icl9kZiR3YXJtX2RyeSksIHN1bSh3YXJtX2RyeV9zYV9kZiR3YXJtX2RyeSksIHN1bSh3YXJtX2RyeV9zcF9kZiR3YXJtX2RyeSkpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRlbHRhX3dhcm0gICAgID0gKHdhcm1fd2V0IC0gY3Vycl93ZXQpIC8gY3Vycl93ZXQgKiAxMDAsCiAgICAgICAgICAgICAgICBkZWx0YV9kcnkgICAgICA9IChjdXJyX2RyeSAtIGN1cnJfd2V0KSAvIGN1cnJfd2V0ICogMTAwLAogICAgICAgICAgICAgICAgZGVsdGFfd2FybV9kcnkgPSAod2FybV9kcnkgLSBjdXJyX3dldCkgLyBjdXJyX3dldCAqIDEwMCkgJT4lCiAgZHBseXI6OnNlbGVjdCgtYyhjdXJyX3dldDp3YXJtX2RyeSkpICU+JQogIGtuaXRyOjprYWJsZShjb2wubmFtZXMgPSBjKCJCaW9tZSIsICIkXFxEZWx0YSQgd2FybWluZyBvbmx5ICglKSIsICIkXFxEZWx0YSQgZHJvdWdodCBvbmx5ICglKSIsICIkXFxEZWx0YSQgd2FybWluZyBhbmQgZHJvdWdodCAoJSkiKSkKYGBgCgoqKioKCiMjIyBUYWJsZSBTN2MgLSBSZWxhdGl2ZSBjaGFuZ2Ugc2Vhc29uIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKKipUYWJsZSBTN2MuKiogQ2hhbmdlIGluICR0X3thY3R9JCAoJSkgcmVsYXRpdmUgdG8gdGhlIGN1cnJlbnQgbm9ybWFsIHNjZW5hcmlvIHVuZGVyIHdhcm1pbmcgb25seSwgZHJvdWdodCBvbmx5LCBhbmQgd2FybWluZyBhbmQgZHJvdWdodCBjb21iaW5lZCBmb3IgYSBoeXBvdGhldGljYWwgZnJvZyBpbiBkaWZmZXJlbnQgYmlvbWVzLiAKCmBgYCB7ciB0YWJsZSBzN2N9CiMgc3VtbWVyCnNoYWRfbW9kZWxfc3VtbWVyIDwtIHNoYWRfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gInN1bW1lciIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKYnJfbW9kZWxfc3VtbWVyIDwtIGJyX21vZGVsICU+JQogIGRwbHlyOjpmaWx0ZXIoc2Vhc29uID09ICJzdW1tZXIiKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGhvdXJzID0gc3VtKGhvdXJzKSkKCnNhX21vZGVsX3N1bW1lciA8LSBzYV9tb2RlbCAlPiUKICBkcGx5cjo6ZmlsdGVyKHNlYXNvbiA9PSAic3VtbWVyIikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGNvbmRpdGlvbikgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShob3VycyA9IHN1bShob3VycykpCgpzcF9tb2RlbF9zdW1tZXIgPC0gc3BfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gInN1bW1lciIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKdGFiX3N1bW1lciA8LSBkYXRhLmZyYW1lKGJpb21lID0gYygiU3VidHJvcGljIiwiVHJvcGljIiwgIlNlbWktYXJpZCIsICJNZWRpdGVycmFuZWFuIiksCiAgICAgICAgICAgY3Vycl93ZXQgPSBjKHNoYWRfbW9kZWxfc3VtbWVyJGhvdXJzWzRdLCBicl9tb2RlbF9zdW1tZXIkaG91cnNbNF0sIHNhX21vZGVsX3N1bW1lciRob3Vyc1s0XSwgc3BfbW9kZWxfc3VtbWVyJGhvdXJzWzRdKSwgCiAgICAgICAgICAgY3Vycl9kcnkgPSBjKHNoYWRfbW9kZWxfc3VtbWVyJGhvdXJzWzNdLCBicl9tb2RlbF9zdW1tZXIkaG91cnNbM10sIHNhX21vZGVsX3N1bW1lciRob3Vyc1szXSwgc3BfbW9kZWxfc3VtbWVyJGhvdXJzWzNdKSwKICAgICAgICAgICB3YXJtX3dldCA9IGMoc2hhZF9tb2RlbF9zdW1tZXIkaG91cnNbMl0sIGJyX21vZGVsX3N1bW1lciRob3Vyc1syXSwgc2FfbW9kZWxfc3VtbWVyJGhvdXJzWzJdLCBzcF9tb2RlbF9zdW1tZXIkaG91cnNbMl0pLAogICAgICAgICAgIHdhcm1fZHJ5ID0gYyhzaGFkX21vZGVsX3N1bW1lciRob3Vyc1sxXSwgYnJfbW9kZWxfc3VtbWVyJGhvdXJzWzFdLCBzYV9tb2RlbF9zdW1tZXIkaG91cnNbMV0sIHNwX21vZGVsX3N1bW1lciRob3Vyc1sxXSkpICU+JQogIGRwbHlyOjptdXRhdGUoZGVsdGFfd2FybSAgICAgPSAod2FybV93ZXQgLSBjdXJyX3dldCkgLyBjdXJyX3dldCAqIDEwMCwKICAgICAgICAgICAgICAgIGRlbHRhX2RyeSAgICAgID0gKGN1cnJfZHJ5IC0gY3Vycl93ZXQpIC8gY3Vycl93ZXQgKiAxMDAsCiAgICAgICAgICAgICAgICBkZWx0YV93YXJtX2RyeSA9ICh3YXJtX2RyeSAtIGN1cnJfd2V0KSAvIGN1cnJfd2V0ICogMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1jKGN1cnJfd2V0Ondhcm1fZHJ5KSkgJT4lCiAgdGliYmxlOjphZGRfcm93KGJpb21lID0gIioqU3VtbWVyKioiLCAuYmVmb3JlID0gMSkKCiMgYXV0dW1uCnNoYWRfbW9kZWxfYXV0dW1uIDwtIHNoYWRfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gImF1dHVtbiIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKYnJfbW9kZWxfYXV0dW1uIDwtIGJyX21vZGVsICU+JQogIGRwbHlyOjpmaWx0ZXIoc2Vhc29uID09ICJhdXR1bW4iKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGhvdXJzID0gc3VtKGhvdXJzKSkKCnNhX21vZGVsX2F1dHVtbiA8LSBzYV9tb2RlbCAlPiUKICBkcGx5cjo6ZmlsdGVyKHNlYXNvbiA9PSAiYXV0dW1uIikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGNvbmRpdGlvbikgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShob3VycyA9IHN1bShob3VycykpCgpzcF9tb2RlbF9hdXR1bW4gPC0gc3BfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gImF1dHVtbiIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKdGFiX2F1dHVtbiA8LSBkYXRhLmZyYW1lKGJpb21lID0gYygiU3VidHJvcGljIiwiVHJvcGljIiwgIlNlbWktYXJpZCIsICJNZWRpdGVycmFuZWFuIiksCiAgICAgICAgICAgY3Vycl93ZXQgPSBjKHNoYWRfbW9kZWxfYXV0dW1uJGhvdXJzWzRdLCBicl9tb2RlbF9hdXR1bW4kaG91cnNbNF0sIHNhX21vZGVsX2F1dHVtbiRob3Vyc1s0XSwgc3BfbW9kZWxfYXV0dW1uJGhvdXJzWzRdKSwgCiAgICAgICAgICAgY3Vycl9kcnkgPSBjKHNoYWRfbW9kZWxfYXV0dW1uJGhvdXJzWzNdLCBicl9tb2RlbF9hdXR1bW4kaG91cnNbM10sIHNhX21vZGVsX2F1dHVtbiRob3Vyc1szXSwgc3BfbW9kZWxfYXV0dW1uJGhvdXJzWzNdKSwKICAgICAgICAgICB3YXJtX3dldCA9IGMoc2hhZF9tb2RlbF9hdXR1bW4kaG91cnNbMl0sIGJyX21vZGVsX2F1dHVtbiRob3Vyc1syXSwgc2FfbW9kZWxfYXV0dW1uJGhvdXJzWzJdLCBzcF9tb2RlbF9hdXR1bW4kaG91cnNbMl0pLAogICAgICAgICAgIHdhcm1fZHJ5ID0gYyhzaGFkX21vZGVsX2F1dHVtbiRob3Vyc1sxXSwgYnJfbW9kZWxfYXV0dW1uJGhvdXJzWzFdLCBzYV9tb2RlbF9hdXR1bW4kaG91cnNbMV0sIHNwX21vZGVsX2F1dHVtbiRob3Vyc1sxXSkpICU+JQogIGRwbHlyOjptdXRhdGUoZGVsdGFfd2FybSAgICAgPSAod2FybV93ZXQgLSBjdXJyX3dldCkgLyBjdXJyX3dldCAqIDEwMCwKICAgICAgICAgICAgICAgIGRlbHRhX2RyeSAgICAgID0gKGN1cnJfZHJ5IC0gY3Vycl93ZXQpIC8gY3Vycl93ZXQgKiAxMDAsCiAgICAgICAgICAgICAgICBkZWx0YV93YXJtX2RyeSA9ICh3YXJtX2RyeSAtIGN1cnJfd2V0KSAvIGN1cnJfd2V0ICogMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1jKGN1cnJfd2V0Ondhcm1fZHJ5KSkgJT4lCiAgdGliYmxlOjphZGRfcm93KGJpb21lID0gIioqQXV0dW1uKioiLCAuYmVmb3JlID0gMSkKCiMgd2ludGVyCnNoYWRfbW9kZWxfd2ludGVyIDwtIHNoYWRfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gIndpbnRlciIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKYnJfbW9kZWxfd2ludGVyIDwtIGJyX21vZGVsICU+JQogIGRwbHlyOjpmaWx0ZXIoc2Vhc29uID09ICJ3aW50ZXIiKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGhvdXJzID0gc3VtKGhvdXJzKSkKCnNhX21vZGVsX3dpbnRlciA8LSBzYV9tb2RlbCAlPiUKICBkcGx5cjo6ZmlsdGVyKHNlYXNvbiA9PSAid2ludGVyIikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGNvbmRpdGlvbikgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShob3VycyA9IHN1bShob3VycykpCgpzcF9tb2RlbF93aW50ZXIgPC0gc3BfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gIndpbnRlciIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKdGFiX3dpbnRlciA8LSBkYXRhLmZyYW1lKGJpb21lID0gYygiU3VidHJvcGljIiwiVHJvcGljIiwgIlNlbWktYXJpZCIsICJNZWRpdGVycmFuZWFuIiksCiAgICAgICAgICAgY3Vycl93ZXQgPSBjKHNoYWRfbW9kZWxfd2ludGVyJGhvdXJzWzRdLCBicl9tb2RlbF93aW50ZXIkaG91cnNbNF0sIHNhX21vZGVsX3dpbnRlciRob3Vyc1s0XSwgc3BfbW9kZWxfd2ludGVyJGhvdXJzWzRdKSwgCiAgICAgICAgICAgY3Vycl9kcnkgPSBjKHNoYWRfbW9kZWxfd2ludGVyJGhvdXJzWzNdLCBicl9tb2RlbF93aW50ZXIkaG91cnNbM10sIHNhX21vZGVsX3dpbnRlciRob3Vyc1szXSwgc3BfbW9kZWxfd2ludGVyJGhvdXJzWzNdKSwKICAgICAgICAgICB3YXJtX3dldCA9IGMoc2hhZF9tb2RlbF93aW50ZXIkaG91cnNbMl0sIGJyX21vZGVsX3dpbnRlciRob3Vyc1syXSwgc2FfbW9kZWxfd2ludGVyJGhvdXJzWzJdLCBzcF9tb2RlbF93aW50ZXIkaG91cnNbMl0pLAogICAgICAgICAgIHdhcm1fZHJ5ID0gYyhzaGFkX21vZGVsX3dpbnRlciRob3Vyc1sxXSwgYnJfbW9kZWxfd2ludGVyJGhvdXJzWzFdLCBzYV9tb2RlbF93aW50ZXIkaG91cnNbMV0sIHNwX21vZGVsX3dpbnRlciRob3Vyc1sxXSkpICU+JQogIGRwbHlyOjptdXRhdGUoZGVsdGFfd2FybSAgICAgPSAod2FybV93ZXQgLSBjdXJyX3dldCkgLyBjdXJyX3dldCAqIDEwMCwKICAgICAgICAgICAgICAgIGRlbHRhX2RyeSAgICAgID0gKGN1cnJfZHJ5IC0gY3Vycl93ZXQpIC8gY3Vycl93ZXQgKiAxMDAsCiAgICAgICAgICAgICAgICBkZWx0YV93YXJtX2RyeSA9ICh3YXJtX2RyeSAtIGN1cnJfd2V0KSAvIGN1cnJfd2V0ICogMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1jKGN1cnJfd2V0Ondhcm1fZHJ5KSkgJT4lCiAgdGliYmxlOjphZGRfcm93KGJpb21lID0gIioqV2ludGVyKioiLCAuYmVmb3JlID0gMSkKCiMgc3ByaW5nCnNoYWRfbW9kZWxfc3ByaW5nIDwtIHNoYWRfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gInNwcmluZyIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKYnJfbW9kZWxfc3ByaW5nIDwtIGJyX21vZGVsICU+JQogIGRwbHlyOjpmaWx0ZXIoc2Vhc29uID09ICJzcHJpbmciKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGhvdXJzID0gc3VtKGhvdXJzKSkKCnNhX21vZGVsX3NwcmluZyA8LSBzYV9tb2RlbCAlPiUKICBkcGx5cjo6ZmlsdGVyKHNlYXNvbiA9PSAic3ByaW5nIikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGNvbmRpdGlvbikgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShob3VycyA9IHN1bShob3VycykpCgpzcF9tb2RlbF9zcHJpbmcgPC0gc3BfbW9kZWwgJT4lCiAgZHBseXI6OmZpbHRlcihzZWFzb24gPT0gInNwcmluZyIpICU+JQogIGRwbHlyOjpncm91cF9ieShjb25kaXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoaG91cnMgPSBzdW0oaG91cnMpKQoKdGFiX3NwcmluZyA8LSBkYXRhLmZyYW1lKGJpb21lID0gYygiU3VidHJvcGljIiwiVHJvcGljIiwgIlNlbWktYXJpZCIsICJNZWRpdGVycmFuZWFuIiksCiAgICAgICAgICAgY3Vycl93ZXQgPSBjKHNoYWRfbW9kZWxfc3ByaW5nJGhvdXJzWzRdLCBicl9tb2RlbF9zcHJpbmckaG91cnNbNF0sIHNhX21vZGVsX3NwcmluZyRob3Vyc1s0XSwgc3BfbW9kZWxfc3ByaW5nJGhvdXJzWzRdKSwgCiAgICAgICAgICAgY3Vycl9kcnkgPSBjKHNoYWRfbW9kZWxfc3ByaW5nJGhvdXJzWzNdLCBicl9tb2RlbF9zcHJpbmckaG91cnNbM10sIHNhX21vZGVsX3NwcmluZyRob3Vyc1szXSwgc3BfbW9kZWxfc3ByaW5nJGhvdXJzWzNdKSwKICAgICAgICAgICB3YXJtX3dldCA9IGMoc2hhZF9tb2RlbF9zcHJpbmckaG91cnNbMl0sIGJyX21vZGVsX3NwcmluZyRob3Vyc1syXSwgc2FfbW9kZWxfc3ByaW5nJGhvdXJzWzJdLCBzcF9tb2RlbF9zcHJpbmckaG91cnNbMl0pLAogICAgICAgICAgIHdhcm1fZHJ5ID0gYyhzaGFkX21vZGVsX3NwcmluZyRob3Vyc1sxXSwgYnJfbW9kZWxfc3ByaW5nJGhvdXJzWzFdLCBzYV9tb2RlbF9zcHJpbmckaG91cnNbMV0sIHNwX21vZGVsX3NwcmluZyRob3Vyc1sxXSkpICU+JQogIGRwbHlyOjptdXRhdGUoZGVsdGFfd2FybSAgICAgPSAod2FybV93ZXQgLSBjdXJyX3dldCkgLyBjdXJyX3dldCAqIDEwMCwKICAgICAgICAgICAgICAgIGRlbHRhX2RyeSAgICAgID0gKGN1cnJfZHJ5IC0gY3Vycl93ZXQpIC8gY3Vycl93ZXQgKiAxMDAsCiAgICAgICAgICAgICAgICBkZWx0YV93YXJtX2RyeSA9ICh3YXJtX2RyeSAtIGN1cnJfd2V0KSAvIGN1cnJfd2V0ICogMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1jKGN1cnJfd2V0Ondhcm1fZHJ5KSkgJT4lCiAgdGliYmxlOjphZGRfcm93KGJpb21lID0gIioqU3ByaW5nKioiLCAuYmVmb3JlID0gMSkKCiMgUmVuZGVyIHRhYmxlCmJpbmRfcm93cyh0YWJfc3VtbWVyLCB0YWJfYXV0dW1uLCB0YWJfd2ludGVyLCB0YWJfc3ByaW5nKSAlPiUgCiAgcmVtb3ZlX3Jvd25hbWVzKCkgJT4lIAogIGtuaXRyOjprYWJsZShjb2wubmFtZXMgPSBjKCJCaW9tZSIsICIkXFxEZWx0YSQgd2FybWluZyBvbmx5ICglKSIsICIkXFxEZWx0YSQgZHJvdWdodCBvbmx5ICglKSIsICIkXFxEZWx0YSQgd2FybWluZyBhbmQgZHJvdWdodCAoJSkiKSkKYGBgCgoqKioKCiMgRmlndXJlcyB7LX0KCkNvZGUgdG8gcHJvZHVjZSB0aGUgbWFpbiBkb2N1bWVudCBmaWd1cmVzIGFyZSBkZXRhaWxlZCBiZWxvdy4gRmlndXJlcyBwcm9kdWNlZCB3ZXJlIGZ1cnRoZXIgbW9kaWZpZWQgaW4gW0Fkb2JlIElsbHVzdHJhdG9yXShodHRwczovL3d3dy5hZG9iZS5jb20vYXUvcHJvZHVjdHMvaWxsdXN0cmF0b3IuaHRtbCkgZm9yIHB1YmxpY2F0aW9uLgoKIyMgRmlndXJlIDEgLSBBSSByaXNrIHstfQoKQ3JlYXRlIHBsb3RzIGZvciBtYWluIHRleHQgZmlndXJlIDEuCgpgYGB7ciBGaWcgMSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD05LCBmaWcuc2hvdz0naGlkZSd9CiMgUmVwcm9qZWN0IG1hcHMKcm9iX3Byb2ogICA8LSAiK3Byb2o9cm9iaW4gK2xvbl8wPTAgK3hfMD0wICt5XzA9MCArZWxscHM9V0dTODQgK2RhdHVtPVdHUzg0ICt1bml0cz1tICtub19kZWZzIiAKd29ybGRfcm9iICA8LSBzcFRyYW5zZm9ybSh3b3JsZF9zcGRmLCBDUlNvYmogPSByb2JfcHJvaikKCiMgbGFuZApkYXRhKCJsYW5kIiwgcGFja2FnZSA9ICJ0bWFwIikKbGFuZF9yYXN0ZXIgPC0gYXMobGFuZCwgIlJhc3RlciIpICMgY29udmVydCBmcm9tIHN0YXIgdG8gcmFzdGVyCmxhbmRfZGYgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMobGFuZF9yYXN0ZXIpKQoKZWxldmF0aW9uX3Jhc3RlciA8LSBwcm9qZWN0UmFzdGVyKGxhbmRfcmFzdGVyJGVsZXZhdGlvbiwgY3JzID0gcm9iX3Byb2opCnNsb3BlX3Jhc3RlciAgICAgPC0gcmFzdGVyOjp0ZXJyYWluKGVsZXZhdGlvbl9yYXN0ZXIsIG9wdCA9ICdzbG9wZScpCmFzcGVjdF9yYXN0ZXIgICAgPC0gcmFzdGVyOjp0ZXJyYWluKGVsZXZhdGlvbl9yYXN0ZXIsIG9wdCA9ICdhc3BlY3QnKQpoaWxsX3Jhc3RlciAgICAgIDwtIGhpbGxTaGFkZShzbG9wZV9yYXN0ZXIsIGFzcGVjdF9yYXN0ZXIsIDQwLCAyNzApICNzZXR0aW5nIHRoZSBlbGV2YXRpb24gYW5nbGUgKG9mIHRoZSBzdW4pIHRvIDQwIGFuZCB0aGUgZGlyZWN0aW9uIGFuZ2xlIG9mIHRoZSBsaWdodCB0byAyNzAKaGlsbF9tICAgICAgICAgICA8LSByYXN0ZXJUb1BvaW50cyhoaWxsX3Jhc3RlcikKaGlsbF9kZiAgICAgICAgICA8LSAgZGF0YS5mcmFtZShoaWxsX20pCmNvbG5hbWVzKGhpbGxfZGYpIDwtIGMoImxvbiIsICJsYXQiLCAiaGlsbCIpCgojIEZpZyAxYSAtIEFJIGN1cnJlbnQKQUlfcm9iICAgIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihhaV9yYXN0LCBjcnMgPSByb2JfcHJvaikKQUlfZGZfcm9iIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKEFJX3JvYikpIApBSV9kZl9yb2IgPC0gQUlfZGZfcm9iICU+JSAKICAjIFJlY29kZQogIGRwbHlyOjptdXRhdGUoY2F0ZWdvcnkgPSBjYXNlX3doZW4oCiAgICBpcy5pbmZpbml0ZShsYXllcikgfiAnSHVtaWQnLAogICAgbGF5ZXIgPj0gMC42NSB+ICdIdW1pZCcsICAgICAgICAgICAgICAgICAgICAgICAKICAgIGxheWVyID49IDAuNSAmIGxheWVyIDwgMC42NSB+ICdEcnkgc3ViLWh1bWlkJywgCiAgICBsYXllciA+PSAwLjIgJiBsYXllciA8IDAuNSB+ICdTZW1pLWFyaWQnLCAgICAgIAogICAgbGF5ZXIgPj0gMC4wNSAmIGxheWVyIDwgMC4yIH4gJ0FyaWQnLCAgICAgICAgIAogICAgbGF5ZXIgPCAwLjA1IH4gJ0h5cGVyLWFyaWQnICAgICAgICAgICAgICAgICAgICAKICApKSAlPiUgCiAgIyBDb252ZXJ0IHRvIG9yZGVyZWQgZmFjdG9yCiAgZHBseXI6Om11dGF0ZShjYXRlZ29yeSA9IGZhY3RvcihjYXRlZ29yeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJ0h5cGVyLWFyaWQnLCAnQXJpZCcsICdTZW1pLWFyaWQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnRHJ5IHN1Yi1odW1pZCcsICdIdW1pZCcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKQoKQUlfMkNfcm9iICAgIDwtIHByb2plY3RSYXN0ZXIoYWlfMkNfcmFzdCwgY3JzID0gcm9iX3Byb2opCkFJXzJDX2RmX3JvYiA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhBSV8yQ19yb2IpKSAKQUlfMkNfZGZfcm9iIDwtIEFJXzJDX2RmX3JvYiAlPiUgCiAgIyBSZWNvZGUKICBkcGx5cjo6bXV0YXRlKGNhdGVnb3J5ID0gY2FzZV93aGVuKAogICAgaXMuaW5maW5pdGUobGF5ZXIpIH4gJ0h1bWlkJywKICAgIGxheWVyID49IDAuNjUgfiAnSHVtaWQnLCAgICAgICAgICAgICAgICAgICAgICAgCiAgICBsYXllciA+PSAwLjUgJiBsYXllciA8IDAuNjUgfiAnRHJ5IHN1Yi1odW1pZCcsIAogICAgbGF5ZXIgPj0gMC4yICYgbGF5ZXIgPCAwLjUgfiAnU2VtaS1hcmlkJywgICAgIAogICAgbGF5ZXIgPj0gMC4wNSAmIGxheWVyIDwgMC4yIH4gJ0FyaWQnLCAgICAgICAgIAogICAgbGF5ZXIgPCAwLjA1IH4gJ0h5cGVyLWFyaWQnICAgICAgICAgICAgICAgIAogICkpICU+JSAKICAjIENvbnZlcnQgdG8gb3JkZXJlZCBmYWN0b3IKICBkcGx5cjo6bXV0YXRlKGNhdGVnb3J5ID0gZmFjdG9yKGNhdGVnb3J5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnSHlwZXItYXJpZCcsICdBcmlkJywgJ1NlbWktYXJpZCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdEcnkgc3ViLWh1bWlkJywgJ0h1bWlkJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkpCgpBSV80Q19yb2IgICAgPC0gcHJvamVjdFJhc3RlcihhaV80Q19yYXN0LCBjcnMgPSByb2JfcHJvaikKQUlfNENfZGZfcm9iIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKEFJXzRDX3JvYikpIApBSV80Q19kZl9yb2IgPC0gQUlfNENfZGZfcm9iICU+JSAKICAjIFJlY29kZQogIGRwbHlyOjptdXRhdGUoY2F0ZWdvcnkgPSBjYXNlX3doZW4oCiAgICBpcy5pbmZpbml0ZShsYXllcikgfiAnSHVtaWQnLAogICAgbGF5ZXIgPj0gMC42NSB+ICdIdW1pZCcsICAgICAgICAgICAgICAgICAgICAgICAKICAgIGxheWVyID49IDAuNSAmIGxheWVyIDwgMC42NSB+ICdEcnkgc3ViLWh1bWlkJywgCiAgICBsYXllciA+PSAwLjIgJiBsYXllciA8IDAuNSB+ICdTZW1pLWFyaWQnLCAgICAgIAogICAgbGF5ZXIgPj0gMC4wNSAmIGxheWVyIDwgMC4yIH4gJ0FyaWQnLCAgICAgICAgIAogICAgbGF5ZXIgPCAwLjA1IH4gJ0h5cGVyLWFyaWQnICAgICAgICAgICAgICAgICAgICAKICApKSAlPiUgCiAgIyBDb252ZXJ0IHRvIG9yZGVyZWQgZmFjdG9yCiAgZHBseXI6Om11dGF0ZShjYXRlZ29yeSA9IGZhY3RvcihjYXRlZ29yeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJ0h5cGVyLWFyaWQnLCAnQXJpZCcsICdTZW1pLWFyaWQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnRHJ5IHN1Yi1odW1pZCcsICdIdW1pZCcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKQoKYXJpZF9jb2wgPC0gYygnIzhFMDYzQicsICcjQ0I2RDUzJywgJyNFOTlBMkMnLCAnI0Y1RDU3OScsICd3aGl0ZScpCmFyaWRpdHlfcGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoZGF0YSA9IEFJX2RmX3JvYiwgYWVzKHkgPSB5LCB4ID0geCwgZmlsbCA9IGNhdGVnb3J5KSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGRfcm9iLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGFyaWRfY29sLAogICAgICAgICAgICAgICAgICAgIGd1aWRlID0gZ3VpZGVfbGVnZW5kKHJldmVyc2UgPSBUUlVFKSkgKwogIGdnbmV3c2NhbGU6Om5ld19zY2FsZSgiZmlsbCIpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gaGlsbF9kZiAlPiUgZmlsdGVyKGhpbGwgPD0gMC42NDUpLCBhZXMobG9uLCBsYXQsIGZpbGwgPSBoaWxsLCBhbHBoYSA9IGhpbGwpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gImdyZXkiKSArCiAgc2NhbGVfYWxwaGFfY29udGludW91cyh0cmFucyA9ICJyZXZlcnNlIikgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICBnZ3RpdGxlKCJBcmlkaXR5IEluZGV4ICgxOTgxLTIwMTApIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MWU1LCA4NWU1KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xNWU2LCAxNmU2KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAgCgojIEZpZyAxYiAtIFNwZWNpZXMgcmljaG5lc3MKYW51cmFuX3JvYiAgICA8LSBwcm9qZWN0UmFzdGVyKGFudXJhbl9zciwgY3JzID0gcm9iX3Byb2opCmFudXJhbl9kZl9yb2IgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMoYW51cmFuX3JvYikpICU+JSBkcGx5cjo6cmVuYW1lKHNwZWNpZXNfbiA9IGxheWVyKQoKc3BfYnJlYWtzID0gYygxLCA1LCAyNSwgMTAwKQphbnVyYW5fcGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoZGF0YSA9IGFudXJhbl9kZl9yb2IsIGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBzcGVjaWVzX24pKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9yb2IsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgY29sb3JzcGFjZTo6c2NhbGVfZmlsbF9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJCbHVHcm4iLCB0cmFucyA9ICJsb2ciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNwX2JyZWFrcywgbGFiZWxzID0gc3BfYnJlYWtzKSArCiAgZ2duZXdzY2FsZTo6bmV3X3NjYWxlKCJmaWxsIikgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBoaWxsX2RmICU+JSBmaWx0ZXIoaGlsbCA8PSAwLjY0NSksIGFlcyhsb24sIGxhdCwgZmlsbCA9IGhpbGwsIGFscGhhID0gaGlsbCksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAiZ3JleSIpICsKICBzY2FsZV9hbHBoYV9jb250aW51b3VzKHRyYW5zID0gInJldmVyc2UiKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIGdndGl0bGUoIkFudXJhbiBzcGVjaWVzIHJpY2huZXNzIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MWU1LCA4NWU1KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xNWU2LCAxNmU2KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQoKQoKQUlfbWVyZ2VkIDwtIG1lcmdlKEFJX2RmX3JvYiwgQUlfMkNfZGZfcm9iLCBieSA9IGMoIngiLCAieSIpLCBhbGwueCA9IFQpICU+JQogIG1lcmdlKEFJXzRDX2RmX3JvYiwgYnkgPSBjKCJ4IiwgInkiKSwgYWxsLnggPSBUKSAlPiUKICBkcGx5cjo6cmVuYW1lKGxheWVyX2N1cnJlbnQgPSBsYXllci54LAogICAgICAgICAgICAgICAgY2F0ZWdvcnlfY3VycmVudCA9IGNhdGVnb3J5LngsCiAgICAgICAgICAgICAgICBsYXllcl8yQyAgPSBsYXllci55LAogICAgICAgICAgICAgICAgY2F0ZWdvcnlfMkMgPSBjYXRlZ29yeS55LAogICAgICAgICAgICAgICAgbGF5ZXJfNEMgID0gbGF5ZXIsCiAgICAgICAgICAgICAgICBjYXRlZ29yeV80QyA9IGNhdGVnb3J5KSAlPiUKICBkcGx5cjo6bXV0YXRlKGNoYW5nZV8yQyA9IChsYXllcl8yQyAtIGxheWVyX2N1cnJlbnQgLyBsYXllcl9jdXJyZW50KSAqIDEwMCwKICAgICAgICAgICAgICAgIGNoYW5nZV8yQ19BSSA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgY2hhbmdlXzJDID49IC0yICYgY2hhbmdlXzJDIDwyIH4gJ05vIGNoYW5nZSB0byB3ZXR0ZXInLAogICAgICAgICAgICAgICAgICBjaGFuZ2VfMkMgPj0gLTEwICYgY2hhbmdlXzJDIDwgLTIgfiAnPi0yIHRvIC0xMCUnLAogICAgICAgICAgICAgICAgICBjaGFuZ2VfMkMgPj0gLTIwICYgY2hhbmdlXzJDIDwgLTEwIH4gJz4tMTAgdG8gLTIwJScsCiAgICAgICAgICAgICAgICAgIGNoYW5nZV8yQyA+PSAtNDAgJiBjaGFuZ2VfMkMgPCAtMjAgfiAnPi0yMCB0byAtNDAlJywKICAgICAgICAgICAgICAgICAgY2hhbmdlXzJDID49IC04MCAmIGNoYW5nZV8yQyA8IC00MCB+ICc+LTQwIHRvIC04MCUnLAogICAgICAgICAgICAgICAgICBjaGFuZ2VfMkMgPCAtODAgfiAnPC04MCUnKSwKICAgICAgICAgICAgICAgICAgY2hhbmdlXzRDID0gKGxheWVyXzRDIC0gbGF5ZXJfY3VycmVudCAvIGxheWVyX2N1cnJlbnQpICogMTAwLAogICAgICAgICAgICAgICAgY2hhbmdlXzRDX0FJID0gY2FzZV93aGVuKAogICAgICAgICAgICAgICAgICBjaGFuZ2VfNEMgPj0gLTIgJiBjaGFuZ2VfNEMgPDIgfiAnTm8gY2hhbmdlIHRvIHdldHRlcicsCiAgICAgICAgICAgICAgICAgIGNoYW5nZV80QyA+PSAtMTAgJiBjaGFuZ2VfNEMgPCAtMiB+ICc+LTIgdG8gLTEwJScsCiAgICAgICAgICAgICAgICAgIGNoYW5nZV80QyA+PSAtMjAgJiBjaGFuZ2VfNEMgPCAtMTAgfiAnPi0xMCB0byAtMjAlJywKICAgICAgICAgICAgICAgICAgY2hhbmdlXzRDID49IC00MCAmIGNoYW5nZV80QyA8IC0yMCB+ICc+LTIwIHRvIC00MCUnLAogICAgICAgICAgICAgICAgICBjaGFuZ2VfNEMgPj0gLTgwICYgY2hhbmdlXzRDIDwgLTQwIH4gJz4tNDAgdG8gLTgwJScsCiAgICAgICAgICAgICAgICAgIGNoYW5nZV80QyA8IC04MCB+ICc8LTgwJScKICAgICAgICAgICAgICAgICkpICU+JSAKICBmaWx0ZXIoY2F0ZWdvcnlfY3VycmVudCAhPSAiSHlwZXItYXJpZCIpICU+JQogIGRwbHlyOjptdXRhdGUoY2hhbmdlXzJDX0FJID0gZmFjdG9yKGNoYW5nZV8yQ19BSSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCc8LTgwJScsICc+LTQwIHRvIC04MCUnLCc+LTIwIHRvIC00MCUnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJz4tMTAgdG8gLTIwJScsICc+LTIgdG8gLTEwJScsICdObyBjaGFuZ2UgdG8gd2V0dGVyJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpLAogICAgICAgICAgICAgICAgY2hhbmdlXzRDX0FJID0gZmFjdG9yKGNoYW5nZV80Q19BSSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCc8LTgwJScsICc+LTQwIHRvIC04MCUnLCc+LTIwIHRvIC00MCUnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJz4tMTAgdG8gLTIwJScsICc+LTIgdG8gLTEwJScsICdObyBjaGFuZ2UgdG8gd2V0dGVyJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKQoKY2hhbmdlX2NvbCA8LSBjKCcjOWU1YjEzJywgJyNiZjgzMmUnLCAnI2RhYjM2NycsICcjZThjYTg0JywgJyNmMGUwYWQnLCAnd2hpdGUnKQoKIyBGaWcgMUMgLSAyQyBEaWZmZXJlbmNlCmNoYW5nZV8yQ19wbG90IDwtIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gQUlfbWVyZ2VkLCBhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gY2hhbmdlXzJDX0FJKSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGRfcm9iLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoYW5nZV9jb2wsIG5hLnZhbHVlID0gIndoaXRlIikgKwogIGdnbmV3c2NhbGU6Om5ld19zY2FsZSgiZmlsbCIpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gaGlsbF9kZiAlPiUgZmlsdGVyKGhpbGwgPD0gMC42NDUpLCBhZXMobG9uLCBsYXQsIGZpbGwgPSBoaWxsLCBhbHBoYSA9IGhpbGwpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gImdyZXkiKSArCiAgc2NhbGVfYWxwaGFfY29udGludW91cyh0cmFucyA9ICJyZXZlcnNlIikgKwogIHRoZW1lX3ZvaWQoKSsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIGdndGl0bGUoZXhwcmVzc2lvbigiQ2hhbmdlIGluIGRyeW5lc3MgKCIqRGVsdGEqIkFJICsywrBDKSIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTYxZTUsIDg1ZTUpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE1ZTYsIDE2ZTYpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpIAoKIyBGaWcgMWQgLSA0QyBEaWZmZXJlbmNlCmNoYW5nZV80Q19wbG90IDwtIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gQUlfbWVyZ2VkLCBhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gY2hhbmdlXzRDX0FJKSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGRfcm9iLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoYW5nZV9jb2wsIG5hLnZhbHVlID0gIndoaXRlIikgKwogIGdnbmV3c2NhbGU6Om5ld19zY2FsZSgiZmlsbCIpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gaGlsbF9kZiAlPiUgZmlsdGVyKGhpbGwgPD0gMC42NDUpLCBhZXMobG9uLCBsYXQsIGZpbGwgPSBoaWxsLCBhbHBoYSA9IGhpbGwpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gImdyZXkiKSArCiAgc2NhbGVfYWxwaGFfY29udGludW91cyh0cmFucyA9ICJyZXZlcnNlIikgKwogIHRoZW1lX3ZvaWQoKSsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIGdndGl0bGUoZXhwcmVzc2lvbigiQ2hhbmdlIGluIGRyeW5lc3MgKCIqRGVsdGEqIkFJICs0wrBDKSIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTYxZTUsIDg1ZTUpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE1ZTYsIDE2ZTYpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpIAoKIyBGaWcgMWUgLSBEcnluZXNzIGFuZCBzcGVjaWVzIHJpY2huZXNzCmFyaWRfY29sXzIgPC0gYygiIzhFMDYzQiIsICIjQ0I2RDUzIiwgIiNFOTlBMkMiLCAiI0Y1RDU3OSIsICJsaWdodCBncmV5IikKc3BlY2llc19haV9wbG90IDwtIGFpX3NwX2RmICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhcmlkaXR5LCB5ID0gc3BlY2llc19uLCBjb2xvdXIgPSBjYXRlZ29yeSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgY29vcmRfdHJhbnMoeCA9ICJzcXJ0IikgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYXJpZF9jb2xfMiwKICAgICAgICAgICAgICAgICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlID0gVFJVRSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDMpLAogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKDAsIDAuMDUsIDAuMiwgMC41LCAwLjY1KSkgKwogIHhsYWIoIlByZWNpcGl0YXRpb24gLyBFdmFwb3RyYW5zcGlyYXRpb24iKSArCiAgeWxhYigiU3BlY2llcyByaWNobmVzcyIpICsKICBteXRoZW1lKCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCkpCgojIEZpZyAxZiAtIERyeW5lc3MgYW5kIHNwZWNpZXMgcmljaG5lc3MgYnkgZWNvdHlwZQplY290eXBlX2FpX3Bsb3QgPC0gYWlfc3BfZGYgJT4lCiAgZHBseXI6OmZpbHRlcihhcmlkaXR5IDw9MykgJT4lCiAgZHBseXI6OnNlbGVjdChhcmlkaXR5LCBzcGVjaWVzX246c3RyZWFtX24pICU+JQogIHRpZHlyOjpwaXZvdF9sb25nZXIoIWFyaWRpdHksIG5hbWVzX3RvID0gImVjb3R5cGUiLCB2YWx1ZXNfdG8gPSAibWVhbiIpICU+JQogIGRwbHlyOjpmaWx0ZXIoZWNvdHlwZSAhPSAic3BlY2llc19uIikgJT4lCiAgZHJvcF9uYShtZWFuKSAlPiUKICBkcGx5cjo6bXV0YXRlKGVjb3R5cGUgPSBmYWN0b3IoZWNvdHlwZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImZvc3NvcmlhbF9uIiwgImdyb3VuZF9uIiwgImFxdWF0aWNfbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJhcmJvcmVhbF9uIiwgInNlbWlfYXFfbiIsICJzdHJlYW1fbiIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYXJpZGl0eSwgeSA9IGVjb3R5cGUsIGdyb3VwID0gZWNvdHlwZSwgZmlsbCA9IGVjb3R5cGUpKSArCiAgZ2dyaWRnZXM6OnN0YXRfZGVuc2l0eV9yaWRnZXMoc2NhbGUgPSAxLCByZWxfbWluX2hlaWdodCA9IDAuMDEsIGFscGhhID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9maWxsX3ZpcmlkaXNfZCgpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAic3FydCIpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCkgKwogIG15dGhlbWUoKQoKIyBGaWcgMWcgLSBDaGFuZ2UgaW4gc3BlY2llcyBBSQojIE1lcmdlIHN1bW1hcnkgZGF0YSBieSByb3cKYXJpZF9zcF9jb21iICAgICAgICAgIDwtIGRhdGEuZnJhbWUoYmluZF9yb3dzKGFpX3NwX3N1bSwgYWlfMkNfc3Bfc3VtLCBhaV80Q19zcF9zdW0pKQphcmlkX3NwX2NvbWIkc2NlbmFyaW8gPC0gZm9yY2F0czo6ZmN0X3JlbGV2ZWwoYXJpZF9zcF9jb21iJHNjZW5hcmlvLCAiQ3VycmVudCIpCgpzcGVjaWVzX29jY19wbG90IDwtIGFyaWRfc3BfY29tYiAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY2F0ZWdvcnksIHkgPSBsb2coYWxsX2ZyZXEpLCBncm91cCA9IHNjZW5hcmlvLCBjb2xvdXIgPSBzY2VuYXJpbywgc2hhcGUgPSBzY2VuYXJpbykpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAuNSksIHNpemUgPSAxLjUpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIiNGNUQ1NzkiLCAiI0NCNkQ1MyIsICIjOEUwNjNCIikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gcHJldHR5KGxvZyhhcmlkX3NwX2NvbWIkYWxsX2ZyZXEpKSwgbGFiZWxzID0gcHJldHR5KGFyaWRfc3BfY29tYiRhbGxfZnJlcSkpICsKICB5bGFiKCIlIHNwZWNpZXMiKSArIHhsYWIoTlVMTCkgKwogIG15dGhlbWUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCiMgRmlnIDEKcGxvdF9ncmlkKHNwZWNpZXNfYWlfcGxvdCwgZWNvdHlwZV9haV9wbG90LCBzcGVjaWVzX29jY19wbG90LCBhbGlnbiA9ICJ2IiwgbmNvbCA9IDMpICMgcGxvdCBpbiBiZXR3ZWVuLgoKY293cGxvdDo6cGxvdF9ncmlkKGFyaWRpdHlfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSwgCiAgICAgICAgICAgICAgICAgICBhbnVyYW5fcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSwgCiAgICAgICAgICAgICAgICAgICBjaGFuZ2VfMkNfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSwKICAgICAgICAgICAgICAgICAgIGNoYW5nZV80Q19wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpLAogICAgICAgICAgICAgICAgICAgYWxpZ24gPSAiaCIsIGF4aXMgPSAiYnQiLAogICAgICAgICAgICAgICAgICAgbmNvbCA9IDIpCmBgYAoKIyMgRmlndXJlIDIgLSBQRFNJIHJpc2sgey19CgpDcmVhdGUgcGxvdHMgZm9yIG1haW4gdGV4dCBmaWd1cmUgMi4KCmBgYHtyIEZpZyAyLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTksIGZpZy5zaG93PSdoaWRlJ30KUERTSV9yaXNrX3JvYiA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhQRFNJXzJDX2RpZmZfcmFzdCwgUERTSV80Q19kaWZmX3Jhc3QsIFBEU0lfZnJlcV9kaWZmLCBQRFNJX2R1cl9kaWZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2FtcGxlKGFudXJhbl9zciwgUERTSV80Q19kaWZmX3Jhc3QpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNycyA9IHJvYl9wcm9qKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIApQRFNJX3Jpc2tfZGYgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMoUERTSV9yaXNrX3JvYikpICU+JQogIGRwbHlyOjpyZW5hbWUoInNwX24iID0gbGF5ZXIpICU+JQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKHNwX24pKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRlbHRhX2ludF8yQ19iaW4gPSBpZmVsc2UoZGVsdGFfaW50XzJDIDwgLTEsIDEsIDApLCAjIGRlbHRhX1BEU0kgPCAtMQogICAgICAgICBkZWx0YV9pbnRfNENfYmluID0gaWZlbHNlKGRlbHRhX2ludF80QyA8IC0xLCAxLCAwKSwgIyBkZWx0YV9QRFNJIDwgLTEKICAgICAgICAgZGVsdGFfZnJlcV8yQ19iaW4gPSBpZmVsc2UoZGVsdGFfZnJlcV8yQyA+MSwgMSwgMCksICMgbW9udGggPiAxCiAgICAgICAgIGRlbHRhX2ZyZXFfNENfYmluID0gaWZlbHNlKGRlbHRhX2ZyZXFfNEMgPjEsIDEsIDApLCAjIG1vbnRoID4gMQogICAgICAgICBkZWx0YV9kdXJfMkNfYmluID0gaWZlbHNlKGRlbHRhX2R1cl8yQyA+MSwgMSwgMCksICMgbW9udGggPiAxCiAgICAgICAgIGRlbHRhX2R1cl80Q19iaW4gPSBpZmVsc2UoZGVsdGFfZHVyXzRDID4xLCAxLCAwKSkgJT4lICMgbW9udGggPiAxIAogIGRwbHlyOjpyb3d3aXNlKCkgJT4lCiAgZHBseXI6Om11dGF0ZShjb3VudF8yQyA9IHN1bShkZWx0YV9pbnRfMkNfYmluLCBkZWx0YV9mcmVxXzJDX2JpbiwgZGVsdGFfZHVyXzJDX2JpbiwgbmEucm0gPSBUKSwKICAgICAgICAgCiAgICAgICAgIGNvdW50XzRDID0gc3VtKGRlbHRhX2ludF80Q19iaW4sIGRlbHRhX2ZyZXFfNENfYmluLCBkZWx0YV9kdXJfNENfYmluLCBuYS5ybSA9IFQpLAogICAgICAgICByaXNrXzJDICA9IHNwX24gKiBjb3VudF8yQywKICAgICAgICAgcmlza180QyAgPSBzcF9uICogY291bnRfNEMsCiAgICAgICAgIGNvdW50XzJDID0gZmFjdG9yKGNvdW50XzJDLCBsZXZlbHMgPSBjKCIzIiwgIjIiLCAiMSIpKSwKICAgICAgICAgY291bnRfNEMgPSBmYWN0b3IoY291bnRfNEMsIGxldmVscyA9IGMoIjMiLCAiMiIsICIxIikpCiAgICAgICAgICkgJT4lCiAgZGF0YS5mcmFtZSgpCgojIFBsb3QKUERTSV9yaXNrXzJDX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBQRFNJX3Jpc2tfZGYsIGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBjb3VudF8yQykpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkX3JvYiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgY29sb3VyID0gIiM2NDY4NmIiLCBmaWxsID0gTkEsIHNpemUgPSAwLjEpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJSZWRPciIsIHJldiA9IEYpICsKICBnZ25ld3NjYWxlOjpuZXdfc2NhbGUoImZpbGwiKSArCiAgZ2VvbV9yYXN0ZXIoZGF0YSA9IGhpbGxfZGYgJT4lIGZpbHRlcihoaWxsIDw9IDAuNjQ1KSwgYWVzKGxvbiwgbGF0LCBmaWxsID0gaGlsbCwgYWxwaGEgPSBoaWxsKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJncmV5IikgKwogIHNjYWxlX2FscGhhX2NvbnRpbnVvdXModHJhbnMgPSAicmV2ZXJzZSIpICsKICB0aGVtZV92b2lkKCkgKyB5bGFiKE5VTEwpICsgeGxhYihOVUxMKSArCiAgZ2d0aXRsZShleHByZXNzaW9uKCIrMsKwQyBieSAyMDgwLTIxMDAiKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MWU1LCA4NWU1KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xNWU2LCAxNmU2KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAjIGZpeGVkIHJhdGlvCgpQRFNJX3Jpc2tfNENfcGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoZGF0YSA9IFBEU0lfcmlza19kZiwgYWVzKHkgPSB5LCB4ID0geCwgZmlsbCA9IGNvdW50XzRDKSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGRfcm9iLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGVfc2VxdWVudGlhbChwYWxldHRlID0gIlJlZE9yIiwgcmV2ID0gRikgKwogIGdnbmV3c2NhbGU6Om5ld19zY2FsZSgiZmlsbCIpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gaGlsbF9kZiAlPiUgZmlsdGVyKGhpbGwgPD0gMC42NDUpLCBhZXMobG9uLCBsYXQsIGZpbGwgPSBoaWxsLCBhbHBoYSA9IGhpbGwpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gImdyZXkiKSArCiAgc2NhbGVfYWxwaGFfY29udGludW91cyh0cmFucyA9ICJyZXZlcnNlIikgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICBnZ3RpdGxlKGV4cHJlc3Npb24oIis0wrBDIGJ5IDIwODAtMjEwMCIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTYxZTUsIDg1ZTUpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE1ZTYsIDE2ZTYpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICMgZml4ZWQgcmF0aW8KCnNwXzJDX3Bsb3QgPC0gUERTSV9yaXNrX2RmICU+JQogIGRwbHlyOjptdXRhdGUocmlza18yQ19jYXQgPSBjYXNlX3doZW4oCiAgICByaXNrXzJDID09IDAgfiAnMCcsCiAgICByaXNrXzJDID4gMCAmIHJpc2tfMkMgPD0xIH4gJzwxJywKICAgIHJpc2tfMkMgPiAxICYgcmlza18yQyA8IDUgfiAnPjEgdG8gNScsCiAgICByaXNrXzJDID49IDUgJiByaXNrXzJDIDwgMTAgfiAnPjUgdG8gMTAnLAogICAgcmlza18yQyA+PSAxMCAmIHJpc2tfMkMgPCAyMCB+ICc+MTAgdG8gMjAnLAogICAgcmlza18yQyA+PSAyMCAmIHJpc2tfMkMgPCAxMDAgfiAnPjIwIHRvIDEwMCcsCiAgICByaXNrXzJDID49IDEwMCAmIHJpc2tfMkMgPCAyMDAgfiAnPjEwMCB0byAyMDAnLAogICAgcmlza18yQyA+IDIwMCB+ICc+MjAwJyksCiAgICByaXNrXzJDID0gbmFfaWYocmlza18yQywgMCksCiAgICByaXNrXzJDX2NhdCA9IGZhY3RvcihyaXNrXzJDX2NhdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCc+MjAwJywnPjEwMCB0byAyMDAnLCAnPjIwIHRvIDEwMCcsJz4xMCB0byAyMCcsICc+NSB0byAxMCcsICc+MSB0byA1JywgJzwxJykpKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoYWVzKHkgPSB5LCB4ID0geCwgZmlsbCA9IHJpc2tfMkNfY2F0KSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGRfcm9iLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGVfc2VxdWVudGlhbChwYWxldHRlID0gIkhlYXQiLCByZXYgPSBGKSArCiAgZ2duZXdzY2FsZTo6bmV3X3NjYWxlKCJmaWxsIikgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBoaWxsX2RmICU+JSBmaWx0ZXIoaGlsbCA8PSAwLjY0NSksIGFlcyhsb24sIGxhdCwgZmlsbCA9IGhpbGwsIGFscGhhID0gaGlsbCksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAiZ3JleSIpICsKICBzY2FsZV9hbHBoYV9jb250aW51b3VzKHRyYW5zID0gInJldmVyc2UiKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MWU1LCA4NWU1KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xNWU2LCAxNmU2KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAjIGZpeGVkIHJhdGlvCgpzcF80Q19wbG90IDwtIFBEU0lfcmlza19kZiAlPiUKICBkcGx5cjo6bXV0YXRlKHJpc2tfNENfY2F0ID0gY2FzZV93aGVuKAogICAgcmlza180QyA9PSAwIH4gJzAnLAogICAgcmlza180QyA+IDAgJiByaXNrXzRDIDw9MSB+ICc8MScsCiAgICByaXNrXzRDID4gMSAmIHJpc2tfNEMgPCA1IH4gJz4xIHRvIDUnLAogICAgcmlza180QyA+PSA1ICYgcmlza180QyA8IDEwIH4gJz41IHRvIDEwJywKICAgIHJpc2tfNEMgPj0gMTAgJiByaXNrXzRDIDwgMjAgfiAnPjEwIHRvIDIwJywKICAgIHJpc2tfNEMgPj0gMjAgJiByaXNrXzRDIDwgMTAwIH4gJz4yMCB0byAxMDAnLAogICAgcmlza180QyA+PSAxMDAgJiByaXNrXzRDIDwgMjAwIH4gJz4xMDAgdG8gMjAwJywKICAgIHJpc2tfNEMgPiAyMDAgfiAnPjIwMCcpLAogICAgcmlza180QyA9IG5hX2lmKHJpc2tfNEMsIDApLAogICAgcmlza180Q19jYXQgPSBmYWN0b3Iocmlza180Q19jYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnPjIwMCcsJz4xMDAgdG8gMjAwJywgJz4yMCB0byAxMDAnLCc+MTAgdG8gMjAnLCAnPjUgdG8gMTAnLCAnPjEgdG8gNScsICc8MScpKSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSByaXNrXzRDX2NhdCkpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkX3JvYiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgY29sb3VyID0gIiM2NDY4NmIiLCBmaWxsID0gTkEsIHNpemUgPSAwLjEpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJIZWF0IiwgcmV2ID0gRikgKwogIGdnbmV3c2NhbGU6Om5ld19zY2FsZSgiZmlsbCIpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gaGlsbF9kZiAlPiUgZmlsdGVyKGhpbGwgPD0gMC42NDUpLCBhZXMobG9uLCBsYXQsIGZpbGwgPSBoaWxsLCBhbHBoYSA9IGhpbGwpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gImdyZXkiKSArCiAgc2NhbGVfYWxwaGFfY29udGludW91cyh0cmFucyA9ICJyZXZlcnNlIikgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNjFlNSwgODVlNSksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTVlNiwgMTZlNiksIGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkgIyBmaXhlZCByYXRpbwoKY293cGxvdDo6cGxvdF9ncmlkKFBEU0lfcmlza18yQ19wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwKICAgICAgICAgICAgICAgICAgIFBEU0lfcmlza180Q19wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwKICAgICAgICAgICAgICAgICAgIHNwXzJDX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLAogICAgICAgICAgICAgICAgICAgc3BfNENfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksCiAgICAgICAgICAgICAgICAgICBuY29sID0gMiwKICAgICAgICAgICAgICAgICAgIGFsaWduID0gImgiLCBheGlzID0gImJ0IiwgbGFiZWxzID0gYygnYScsICdiJywgJ2MnLCAnZCcpKQoKI1BEU0lfcmlza19kZiAlPiUKICAjZ3JvdXBfYnkoY291bnRfMkMpICU+JQogICNzdW1tYXJpc2UobGVuZ3RoID0gbGVuZ3RoKGNvdW50XzJDKSkgJT4lCiAgI211dGF0ZShmcmVxID0gbGVuZ3RoIC8gbGVuZ3RoKFBEU0lfcmlza19kZiRjb3VudF8yQykgKiAxMDApCgojUERTSV9yaXNrX2RmICU+JQogICNncm91cF9ieShjb3VudF80QykgJT4lCiAgI3N1bW1hcmlzZShsZW5ndGggPSBsZW5ndGgoY291bnRfNEMpKSAlPiUKICAjbXV0YXRlKGZyZXEgPSBsZW5ndGggLyBsZW5ndGgoUERTSV9yaXNrX2RmJGNvdW50XzRDKSAqIDEwMCkKYGBgIAoKIyMgRmlndXJlIDMgLSBXYXRlciBsb3NzIHJpc2sgey19CgpSdW4gdGhlIGBlY3RvdGhlcm1gIGZ1bmN0aW9uIGZyb20gKk5pY2hlTWFwUiogZm9yIGFsbCAxMiBtb250aHMgZnJvbSB0aGUgVGVycmEgQ2xpbWF0ZSByYXN0ZXIgZmlsZXMgY29udGFpbmluZyB0aGUgbWVhbiB3aW5kIHNwZWVkIChtIHNeLTFeKSwgbWF4aW11bSBhaXIgdGVtcGVyYXR1cmUgKMKwQyksIGFuZCB2YXBvdXIgcHJlc3N1cmUgZGVmaWNpdCAoVlBEOyBrUGEpIGZvciB0aGUgY3VycmVudCAoMTk4MSB0byAyMDEwKSwgKzLCsEMgYW5kICs0wrBDIHNjZW5hcmlvLiBGcm9tIHRoZSBlY290aGVybSBtb2RlbCwgd2UgZXh0cmFjdGVkIHRoZSBFV0wgKGcgaF4tMV4pIGZvciBlYWNoIHJhc3RlciBwaXhlbCB0byBkZXRlcm1pbmUgdGhlIHNwYXRpYWwgdmFyaWF0aW9uIGluIEVXTC4KCmBgYHtyIGdsb2JfZXdsLCBldmFsPUZBTFNFLCBlY2hvPVR9CiMjIEN1cnJlbnQgIyMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmVsZXYgICAgICA8LSBnZXREYXRhKCJ3b3JsZGNsaW0iLCB2YXIgPSAiYWx0IiwgcmVzID0gMi41KQp3c19mdWxsICAgPC0gIHJhc3Rlcjo6YnJpY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ1RlcnJhQ2xpbWF0ZTE5ODEyMDEwX3dzLm5jJykpICMgMTBtLCBtL3MKdG1heF9mdWxsIDwtIHJhc3Rlcjo6YnJpY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ1RlcnJhQ2xpbWF0ZTE5ODEyMDEwX3RtYXgubmMnKSkgIyAybSwgZGVnIEMKdnBkX2Z1bGwgIDwtIHJhc3Rlcjo6YnJpY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ1RlcnJhQ2xpbWF0ZTE5ODEyMDEwX3ZwZC5uYycpKSAjIDJtLCBrcGEKVGJzICAgICAgIDwtIGNyb3AodG1heF9mdWxsLCBleHRlbnQoZWxldikpCkVXTHMgICAgICA8LSBUYnMgCgojIFJ1biBlY3RvdGhlcm0gbW9kZWwgZm9yIGVhY2ggbW9udGggYW5kIHNhdmUgb24gbG9jYWwgZHJpdmUgKGN1cnJlbnQgc2NlbmFyaW8pCmZvcihtb250aCBpbiAxOjEyKXsKICAjIFRlbXBlcmF0dXJlCiAgVGEudyAgIDwtIGNyb3AodG1heF9mdWxsW1ttb250aF1dLCBleHRlbnQoZWxldikpCiAgZXNhdCAgIDwtIFZBUFBSUyhUYS53KQogICMgUkgKICBlICAgICAgPC0gZXNhdCAtIGNyb3AodnBkX2Z1bGxbW21vbnRoXV0sIGV4dGVudChlbGV2KSkgKiAxMDAwCiAgUkgudyAgIDwtIGUgLyBlc2F0ICogMTAwCiAgUkgud1tSSC53IDwgMF0gPC0gMAogICMgV2luZCBzcGVlZAogIFdpbmQudyA8LSBjcm9wKHdzX2Z1bGxbW21vbnRoXV0sIGV4dGVudChlbGV2KSkKICBWc3RhciAgPC0gMC40ICogV2luZC53IC8gbG9nKCgxMDAgLyAwLjE1KSArIDEpICMgZnJpY3Rpb24gdmVsb2NpdHkKICBXaW5kLncgPC0gMi41ICogVnN0YXIgKiBsb2coKDEgLyAwLjE1KSArIDEpICMgY29ycmVjdCBmb3IgcmVmZXJlbmNlIGhlaWdodCAoMTAgbSkgdG8gZ3JvdW5kIGxldmVsICgxIGNtKSBhc3N1bWluZyBsZXZlbCBncm91bmQKICAjIGNvbXB1dGUgYXRtb3NwaGVyaWMgcHJlc3N1cmUgKGtQYSkKICBQLncgPC0gMTAxMzI1ICogKCgxIC0gKDAuMDA2NSAqIGVsZXYgLyAyODgpKSBeICgxIC8gMC4xOTAyODQpKSAvIDEwMDAKICAKICAjIEdldCByYXN0ZXIgdmFsdWVzCiAgVGEgIDwtIGdldFZhbHVlcyhUYS53KQogIFJIICA8LSBnZXRWYWx1ZXMoUkgudykKICBQICAgPC0gZ2V0VmFsdWVzKFAudykKICBQYSAgPC0gZ2V0VmFsdWVzKGUpCiAgd3MgIDwtIGdldFZhbHVlcyhXaW5kLncpCiAgUFshaXMubmEoVGEpICYgaXMubmEoUCldIDwtIDEwMS4zMjUKICBUYTIgPC0gVGFbIWlzLm5hKFRhKV0KICBSSDIgPC0gUkhbIWlzLm5hKFRhKV0KICBQMiAgPC0gUFshaXMubmEoVGEpXQogIHdzMiA8LSB3c1shaXMubmEoVGEpXQogIFBhMiA8LSBQYVshaXMubmEoVGEpXQogIAogIGRpdiA8LSAxMAogIFR3YiA8LSBUYTJbMTpmbG9vcihsZW5ndGgoVGEyKSAvIGRpdildCiAgbWljcm9fYmFzZSA8LSBtaWNyb19nbG9iYWwoKQogIAogIGZvcihrIGluIDE6ZGl2KXsKICAgIG1pY3JvIDwtIG1pY3JvX2Jhc2UKICAgIGlmKGsgPT0gMSl7CiAgICAgIGV4dHJhIDwtIHJvdW5kKDI0IC0gKGxlbmd0aChUd2IpIC8gMjQpJSUxICogMjQsIDApCiAgICAgIFR3YjQgIDwtIGMoVHdiLCByZXAoVGEyWzFdLCBleHRyYSkpCiAgICAgIHN0YXJ0IDwtIDEKICAgICAgZW5kICAgPC0gbGVuZ3RoKFR3YikKICAgIH0KICAgIGlmKGsgPiAxICYgayA8IGRpdil7CiAgICAgIGZhY3QgIDwtIChsZW5ndGgoVHdiKSAqIChrIC0gMSkgKyBrIC0gMSkKICAgICAgVHdiNCAgPC0gVGEyW2ZhY3Q6KGZhY3QgKyBsZW5ndGgoVHdiKSldCiAgICAgIGV4dHJhIDwtIHJvdW5kKDI0IC0gKGxlbmd0aChUd2I0KSAvIDI0KSUlMSAqIDI0LCAwKQogICAgICBUd2I0ICA8LSBjKFR3YjQsIHJlcChUYTJbMV0sIGV4dHJhKSkKICAgICAgc3RhcnQgPC0gZmFjdAogICAgICBlbmQgICA8LSBmYWN0ICsgbGVuZ3RoKFR3YikKICAgIH0gICAgICAgIAogICAgaWYoayA9PSBkaXYpewogICAgICBmYWN0ICA8LSAobGVuZ3RoKFR3YikgKiAoayAtIDEpICsgayAtIDEpCiAgICAgIFR3YjQgIDwtIFRhMltmYWN0Omxlbmd0aChUYTIpXQogICAgICBleHRyYSA8LSByb3VuZCgyNCAtIChsZW5ndGgoVHdiNCkgLyAyNCklJTEgKiAyNCwgMCkKICAgICAgVHdiNCAgPC0gYyhUd2I0LCByZXAoVGEyWzFdLCBleHRyYSkpCiAgICAgIHN0YXJ0IDwtIGZhY3QKICAgICAgZW5kICAgPC0gbGVuZ3RoKFRhMikKICAgIH0gCiAgICAKICAgIHNvaWxuYW1lcyAgICAgPC0gZGltbmFtZXMobWljcm8kc29pbCkKICAgIG1ldG91dG5hbWVzICAgPC0gZGltbmFtZXMobWljcm8kbWV0b3V0KQogICAgdGNvbmRuYW1lcyAgICA8LSBkaW1uYW1lcyhtaWNybyR0Y29uZCkKICAgIHNwZWNoZWF0bmFtZXMgPC0gZGltbmFtZXMobWljcm8kc3BlY2hlYXQpCiAgICBkZW5zaXRuYW1lcyAgIDwtIGRpbW5hbWVzKG1pY3JvJGRlbnNpdCkKICAgIHBsYW50bmFtZXMgICAgPC0gZGltbmFtZXMobWljcm8kcGxhbnQpCiAgICAKICAgIG1pY3JvJG1ldG91dCAgIDwtIHQoYXJyYXkobWljcm8kbWV0b3V0WzEsXSwgZGltID0gYyhuY29sKG1pY3JvJG1ldG91dCksIGxlbmd0aChUd2I0KSkpKQogICAgZGltbmFtZXMobWljcm8kbWV0b3V0KSA8LSBtZXRvdXRuYW1lcwogICAgbWljcm8kc29pbCAgICAgPC0gdChhcnJheShtaWNybyRzb2lsWzEsXSwgZGltID0gYyhuY29sKG1pY3JvJHNvaWwpLCBsZW5ndGgoVHdiNCkpKSkKICAgIGRpbW5hbWVzKG1pY3JvJHNvaWwpIDwtIHNvaWxuYW1lcwogICAgbWljcm8kdGNvbmQgICAgPC0gdChhcnJheShtaWNybyR0Y29uZFsxLF0sIGRpbSA9IGMobmNvbChtaWNybyR0Y29uZCksIGxlbmd0aChUd2I0KSkpKQogICAgZGltbmFtZXMobWljcm8kdGNvbmQpIDwtIHRjb25kbmFtZXMKICAgIG1pY3JvJHNwZWNoZWF0IDwtIHQoYXJyYXkobWljcm8kc3BlY2hlYXRbMSxdLCBkaW0gPSBjKG5jb2wobWljcm8kc3BlY2hlYXQpLCBsZW5ndGgoVHdiNCkpKSkKICAgIGRpbW5hbWVzKG1pY3JvJHNwZWNoZWF0KSA8LSBzcGVjaGVhdG5hbWVzICAKICAgIG1pY3JvJGRlbnNpdCAgIDwtIHQoYXJyYXkobWljcm8kZGVuc2l0WzEsXSwgZGltID0gYyhuY29sKG1pY3JvJGRlbnNpdCksIGxlbmd0aChUd2I0KSkpKQogICAgZGltbmFtZXMobWljcm8kZGVuc2l0KSA8LSBkZW5zaXRuYW1lcyAgICAgIAogICAgbWljcm8kcGxhbnQgICAgPC0gdChhcnJheShtaWNybyRwbGFudFsxLF0sIGRpbSA9IGMobmNvbChtaWNybyRwbGFudCksIGxlbmd0aChUd2I0KSkpKQogICAgZGltbmFtZXMobWljcm8kcGxhbnQpIDwtIHBsYW50bmFtZXMgCiAgICAKICAgIG1pY3JvJHNoYWRtZXQgPC0gbWljcm8kbWV0b3V0CiAgICBtaWNybyRzaGFkc29pbCA8LSBtaWNybyRzb2lsCiAgICBtaWNybyRodW1pZCA8LSBtaWNybyRzb2lsCiAgICBtaWNybyRzaGFkaHVtaWQgPC0gbWljcm8kc29pbAogICAgbWljcm8kc29pbHBvdCA8LSBtaWNybyRzb2lsCiAgICBtaWNybyRzaGFkcG90IDwtIG1pY3JvJHNvaWwKICAgIG1pY3JvJHNvaWxtb2lzdCA8LSBtaWNybyRzb2lsCiAgICBtaWNybyRzaGFkbW9pc3QgPC0gbWljcm8kc29pbAogICAgbWljcm8kc2hhZHRjb25kIDwtIG1pY3JvJHRjb25kCiAgICBtaWNybyRzaGFkZGVuc2l0IDwtIG1pY3JvJGRlbnNpdAogICAgbWljcm8kc2hhZHNwZWNoZWF0IDwtIG1pY3JvJHNwZWNoZWF0CiAgICBtaWNybyRzaGFkcGxhbnQgPC0gbWljcm8kcGxhbnQKICAgIG1pY3JvJFJBSU5GQUxMIDwtIHJlcCgwLCBsZW5ndGgoVHdiNCkvMjQpCiAgICBtaWNybyRtaW5zaGFkZSA8LSByZXAoMCwgbGVuZ3RoKFR3YjQpLzI0KQogICAgbWljcm8kbWF4c2hhZGUgPC0gcmVwKDkwLCBsZW5ndGgoVHdiNCkvMjQpCiAgICBtaWNybyRueWVhcnMgPC0gY2VpbGluZyhsZW5ndGgoVHdiNCkvMjQvMzY1KQogICAgCiAgICAjIHJlcGxhY2UgZmlyc3QgbGluZSBvZiBtaWNyb2NsaW1hdGUgaW5wdXQgd2l0aCBhaXIgdGVtcGVyYXR1cmUgYW5kIGh1bWlkaXR5IGF0IHdoaWNoIHRvIGNvbXB1dGUgVHcKICAgIG1pY3JvJG1ldG91dFsxOmxlbmd0aChUd2I0KSxjKDMsNCwxNCldIDwtIGMoVGEyW3N0YXJ0OmVuZF0sIHJlcChUYTJbMV0sIGV4dHJhKSkgIyBzZXQgYWlyIGFuZCBza3kgdGVtcGVyYXR1cmUKICAgIG1pY3JvJG1ldG91dFsxOmxlbmd0aChUd2I0KSxjKDUsNildIDwtIGMoUkgyW3N0YXJ0OmVuZF0sIHJlcChSSDJbMV0sIGV4dHJhKSkgIyBzZXQgcmVsYXRpdmUgaHVtaWRpdHkKICAgICMgbWljcm8kbWV0b3V0WzE6bGVuZ3RoKFR3YjMpLGMoNyw4KV0gPC0gMC4wNSAjIHNldCB3aW5kIHNwZWVkIHRvIGxvdyAoc2Vuc2l0aXZlIHRvIHRoaXMpCiAgICBtaWNybyRzb2lsWzE6bGVuZ3RoKFR3YjQpLDNdIDwtIGMoVGEyW3N0YXJ0OmVuZF0sIHJlcChUYTJbMV0sIGV4dHJhKSkgIyBzZXQgc3VyZmFjZSBzb2lsIHRlbXBlcmF0dXJlIHRvIGFpciB0ZW1wZXJhdHVyZQogICAgbWljcm8kbWV0b3V0WzE6bGVuZ3RoKFR3YjQpLCAyXSA8LSByZXAoc2VxKDAsIDIzICogNjAsIDYwKSwgbGVuZ3RoKFRhMikvMjQgKyAxKVsxOmxlbmd0aChUd2I0KV0KICAgICNtaWNybyRtZXRvdXRbMTpsZW5ndGgoVHdiMyksIDFdIDwtIHNlcSgwLCAyMyAqIDYwLCA2MClbMTpsZW5ndGgoVHdiMyldCiAgICBwcmVzaHIgPC0gYyhQMltzdGFydDplbmRdLCByZXAoUDJbMV0sIGV4dHJhKSkqMTAwMCAgICAgICAgICAKICAgIAogICAgbWljcm8kbWV0b3V0WzE6bGVuZ3RoKFR3YjQpLGMoNyw4KV0gPC0gYyh3czJbc3RhcnQ6ZW5kXSwgcmVwKHdzMlsxXSwgZXh0cmEpKSAjIHNldCB3aW5kIHNwZWVkICAgIAogICAgCiAgICAjIHJ1biB0aGUgZWN0b3RoZXJtIG1vZGVsIAogICAgbWVzc2FnZShwYXN0ZSgncnVubmluZyBlY3RvdGhlcm0gc2ltdWxhdGlvbiBmb3IgbW9udGggJyxtb250aCwnIGZvciAnLCBsZW5ndGgoVHdiNCksJyBzaXRlcyBcbicpKQogICAgcHRtIDwtIHByb2MudGltZSgpICMgU3RhcnQgdGltaW5nCiAgICBnYygpCiAgICBlY3RvIDwtIGVjdG90aGVybShXd19nID0gOC43LAogICAgICAgICAgICAgICAgICAgICAgbGl2ZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICBwY3Rfd2V0ID0gODcsCiAgICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IDQsICMgZnJvZwogICAgICAgICAgICAgICAgICAgICAgcHJlc2hyID0gcHJlc2hyKQogICAgbWVzc2FnZShwYXN0ZTAoJ3J1bnRpbWUgJywgKHByb2MudGltZSgpIC0gcHRtKVszXSwgJyBzZWNvbmRzJykpICMgU3RvcCB0aGUgY2xvY2sKICAgIGdjKCkKICAgIGVudmlyb24gPC0gYXMuZGF0YS5mcmFtZShlY3RvJGVudmlyb24pCiAgICBtYXNiYWwgIDwtIGFzLmRhdGEuZnJhbWUoZWN0byRtYXNiYWwpCiAgICBpZihrID09IDEpewogICAgICBUYi5lY3RvdGhlcm0gIDwtIGVudmlyb24kVENbMToobnJvdyhlbnZpcm9uKSAtIGV4dHJhKV0KICAgICAgRVdMLmVjdG90aGVybSA8LSBtYXNiYWwkSDJPQ3V0X2dbMToobnJvdyhtYXNiYWwpIC0gZXh0cmEpXQogICAgfWVsc2V7CiAgICAgIFRiLmVjdG90aGVybSAgPC0gYyhUYi5lY3RvdGhlcm0sIGVudmlyb24kVENbMToobnJvdyhlbnZpcm9uKSAtIGV4dHJhKV0pCiAgICAgIEVXTC5lY3RvdGhlcm0gPC0gYyhFV0wuZWN0b3RoZXJtLCBtYXNiYWwkSDJPQ3V0X2dbMToobnJvdyhtYXNiYWwpIC0gZXh0cmEpXSkKICAgIH0KICB9CiAgVGIyICAgICA8LSBUYQogIFRiMlshaXMubmEoVGEpXSA8LSBUYi5lY3RvdGhlcm0KICBUYi5ncmlkIDwtIFRhLncKICBUYi5ncmlkIDwtIHNldFZhbHVlcyhUYi5ncmlkLCBUYjIpCiAgI3Bsb3QoVGIuZ3JpZCkKICAjbWFwKCd3b3JsZCcsIGFkZCA9IFRSVUUpCiAgCiAgRVdMMiA8LSBUYQogIEVXTDJbIWlzLm5hKFRhKV0gPC0gRVdMLmVjdG90aGVybQogIEVXTC5ncmlkIDwtIFRhLncKICBFV0wuZ3JpZCA8LSBzZXRWYWx1ZXMoRVdMLmdyaWQsIEVXTDIpCiAgI3Bsb3QoRVdMLmdyaWQpCiAgRVdMLmdyaWRbVGIuZ3JpZCA8PSAwXSA8LSBOQQogICNtYXAoJ3dvcmxkJywgYWRkID0gVFJVRSkKCiAgd3JpdGVSYXN0ZXIoRVdMLmdyaWQsIGZpbGUgPSBwYXN0ZTAoJ0VXTF8nLG1vbnRoLCcubmMnKSwgb3ZlcndyaXRlID0gVFJVRSkKfSAKCiMjICsyQyAjIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KdG1heF9mdWxsXzJDIDwtIHJhc3Rlcjo6YnJpY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ1RlcnJhQ2xpbWF0ZTJDX3RtYXgubmMnKSkgIyAybSwgZGVnIEMKZXNfa1BhXzJDICAgIDwtIHRtYXhfZnVsbF8yQwp2YWx1ZXMoZXNfa1BhXzJDKSA8LSAwLjYxMSAqIGV4cCgyNTAwMDAwIC8gNDYxLjUgKiAoIDEgLyAyNzMgLSAxIC8gKHZhbHVlcyh0bWF4X2Z1bGxfMkMpICsgMjczLjE1KSkpCgojIEFjdHVhbCB2YXBvdXIgcHJlc3N1cmUKZWFfa1BhIDwtIHJhc3Rlcjo6YnJpY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ1RlcnJhQ2xpbWF0ZTE5ODEyMDEwX3ZhcC5uYycpKQplYV9rUGFfMkMgPC0gZWFfa1BhCnZhbHVlcyhlYV9rUGFfMkMpIDwtIHZhbHVlcyhlYV9rUGFfMkMpICogMC45CgojIENhbGN1bGF0ZSBWUEQgKGtQYSkKdnBkX2Z1bGxfMkMgPC0gZWFfa1BhXzJDCnZhbHVlcyh2cGRfZnVsbF8yQykgPC0gdmFsdWVzKGVzX2tQYV8yQykgLSB2YWx1ZXMoZWFfa1BhXzJDKQoKVGJzIDwtIGNyb3AodG1heF9mdWxsXzJDLCBleHRlbnQoZWxldikpCkVXTHMgPC0gVGJzIAoKIyBSdW4gZWN0b3RoZXJtIG1vZGVsIGZvciBlYWNoIG1vbnRoIGFuZCBzYXZlIG9uIGxvY2FsIGRyaXZlICgrMkMgc2NlbmFyaW8pCmZvcihtb250aCBpbiAxOjEyKXsKICBUYS53ICAgPC0gY3JvcCh0bWF4X2Z1bGxfMkNbW21vbnRoXV0sIGV4dGVudChlbGV2KSkKICBlc2F0ICAgPC0gVkFQUFJTKFRhLncpCiAgZSAgICAgIDwtIGVzYXQgLSBjcm9wKHZwZF9mdWxsXzJDW1ttb250aF1dLCBleHRlbnQoZWxldikpICogMTAwMAogIFJILncgICA8LSBlIC8gZXNhdCAqIDEwMAogIFJILndbUkgudyA8IDBdIDwtIDAKICBXaW5kLncgPC0gY3JvcCh3c19mdWxsW1ttb250aF1dLCBleHRlbnQoZWxldikpCiAgVnN0YXIgIDwtIDAuNCAqIFdpbmQudyAvIGxvZygoMTAwIC8gMC4xNSkgKyAxKSAjIGZyaWN0aW9uIHZlbG9jaXR5CiAgV2luZC53IDwtIDIuNSAqIFZzdGFyICogbG9nKCgxIC8gMC4xNSkgKyAxKSAjIGNvcnJlY3QgZm9yIHJlZmVyZW5jZSBoZWlnaHQgKDEwIG0pIHRvIGdyb3VuZCBsZXZlbCAoMSBjbSkgYXNzdW1pbmcgbGV2ZWwgZ3JvdW5kCiAgIyBjb21wdXRlIGF0bW9zcGhlcmljIHByZXNzdXJlIChrUGEpCiAgUC53IDwtIDEwMTMyNSAqICgoMSAtICgwLjAwNjUgKiBlbGV2IC8gMjg4KSkgXiAoMSAvIDAuMTkwMjg0KSkgLyAxMDAwCiAgCiAgVGEgIDwtIGdldFZhbHVlcyhUYS53KQogIFJIICA8LSBnZXRWYWx1ZXMoUkgudykKICBQICAgPC0gZ2V0VmFsdWVzKFAudykKICBQYSAgPC0gZ2V0VmFsdWVzKGUpCiAgd3MgIDwtIGdldFZhbHVlcyhXaW5kLncpCiAgUFshaXMubmEoVGEpICYgaXMubmEoUCldIDwtIDEwMS4zMjUKICBUYTIgPC0gVGFbIWlzLm5hKFRhKV0KICBSSDIgPC0gUkhbIWlzLm5hKFRhKV0KICBQMiAgPC0gUFshaXMubmEoVGEpXQogIHdzMiA8LSB3c1shaXMubmEoVGEpXQogIFBhMiA8LSBQYVshaXMubmEoVGEpXQogIAogIGRpdiA8LSAxMAogIFR3YiA8LSBUYTJbMTpmbG9vcihsZW5ndGgoVGEyKSAvIGRpdildCiAgbWljcm9fYmFzZSA8LSBtaWNyb19nbG9iYWwoKQogIAogIGZvcihrIGluIDE6ZGl2KXsKICAgIG1pY3JvIDwtIG1pY3JvX2Jhc2UKICAgIGlmKGsgPT0gMSl7CiAgICAgIGV4dHJhIDwtIHJvdW5kKDI0IC0gKGxlbmd0aChUd2IpIC8gMjQpJSUxICogMjQsIDApCiAgICAgIFR3YjQgIDwtIGMoVHdiLCByZXAoVGEyWzFdLCBleHRyYSkpCiAgICAgIHN0YXJ0IDwtIDEKICAgICAgZW5kICAgPC0gbGVuZ3RoKFR3YikKICAgIH0KICAgIGlmKGsgPiAxICYgayA8IGRpdil7CiAgICAgIGZhY3QgIDwtIChsZW5ndGgoVHdiKSAqIChrIC0gMSkgKyBrIC0gMSkKICAgICAgVHdiNCAgPC0gVGEyW2ZhY3Q6KGZhY3QgKyBsZW5ndGgoVHdiKSldCiAgICAgIGV4dHJhIDwtIHJvdW5kKDI0IC0gKGxlbmd0aChUd2I0KSAvIDI0KSUlMSAqIDI0LCAwKQogICAgICBUd2I0ICA8LSBjKFR3YjQsIHJlcChUYTJbMV0sIGV4dHJhKSkKICAgICAgc3RhcnQgPC0gZmFjdAogICAgICBlbmQgICA8LSBmYWN0ICsgbGVuZ3RoKFR3YikKICAgIH0gICAgICAgIAogICAgaWYoayA9PSBkaXYpewogICAgICBmYWN0ICA8LSAobGVuZ3RoKFR3YikgKiAoayAtIDEpICsgayAtIDEpCiAgICAgIFR3YjQgIDwtIFRhMltmYWN0Omxlbmd0aChUYTIpXQogICAgICBleHRyYSA8LSByb3VuZCgyNCAtIChsZW5ndGgoVHdiNCkgLyAyNCklJTEgKiAyNCwgMCkKICAgICAgVHdiNCAgPC0gYyhUd2I0LCByZXAoVGEyWzFdLCBleHRyYSkpCiAgICAgIHN0YXJ0IDwtIGZhY3QKICAgICAgZW5kICAgPC0gbGVuZ3RoKFRhMikKICAgIH0gCiAgICAKICAgIHNvaWxuYW1lcyAgICAgPC0gZGltbmFtZXMobWljcm8kc29pbCkKICAgIG1ldG91dG5hbWVzICAgPC0gZGltbmFtZXMobWljcm8kbWV0b3V0KQogICAgdGNvbmRuYW1lcyAgICA8LSBkaW1uYW1lcyhtaWNybyR0Y29uZCkKICAgIHNwZWNoZWF0bmFtZXMgPC0gZGltbmFtZXMobWljcm8kc3BlY2hlYXQpCiAgICBkZW5zaXRuYW1lcyAgIDwtIGRpbW5hbWVzKG1pY3JvJGRlbnNpdCkKICAgIHBsYW50bmFtZXMgICAgPC0gZGltbmFtZXMobWljcm8kcGxhbnQpCiAgICAKICAgIG1pY3JvJG1ldG91dCAgIDwtIHQoYXJyYXkobWljcm8kbWV0b3V0WzEsXSwgZGltID0gYyhuY29sKG1pY3JvJG1ldG91dCksIGxlbmd0aChUd2I0KSkpKQogICAgZGltbmFtZXMobWljcm8kbWV0b3V0KSA8LSBtZXRvdXRuYW1lcwogICAgbWljcm8kc29pbCAgICAgPC0gdChhcnJheShtaWNybyRzb2lsWzEsXSwgZGltID0gYyhuY29sKG1pY3JvJHNvaWwpLCBsZW5ndGgoVHdiNCkpKSkKICAgIGRpbW5hbWVzKG1pY3JvJHNvaWwpIDwtIHNvaWxuYW1lcwogICAgbWljcm8kdGNvbmQgICAgPC0gdChhcnJheShtaWNybyR0Y29uZFsxLF0sIGRpbSA9IGMobmNvbChtaWNybyR0Y29uZCksIGxlbmd0aChUd2I0KSkpKQogICAgZGltbmFtZXMobWljcm8kdGNvbmQpIDwtIHRjb25kbmFtZXMKICAgIG1pY3JvJHNwZWNoZWF0IDwtIHQoYXJyYXkobWljcm8kc3BlY2hlYXRbMSxdLCBkaW0gPSBjKG5jb2wobWljcm8kc3BlY2hlYXQpLCBsZW5ndGgoVHdiNCkpKSkKICAgIGRpbW5hbWVzKG1pY3JvJHNwZWNoZWF0KSA8LSBzcGVjaGVhdG5hbWVzICAKICAgIG1pY3JvJGRlbnNpdCAgIDwtIHQoYXJyYXkobWljcm8kZGVuc2l0WzEsXSwgZGltID0gYyhuY29sKG1pY3JvJGRlbnNpdCksIGxlbmd0aChUd2I0KSkpKQogICAgZGltbmFtZXMobWljcm8kZGVuc2l0KSA8LSBkZW5zaXRuYW1lcyAgICAgIAogICAgbWljcm8kcGxhbnQgICAgPC0gdChhcnJheShtaWNybyRwbGFudFsxLF0sIGRpbSA9IGMobmNvbChtaWNybyRwbGFudCksIGxlbmd0aChUd2I0KSkpKQogICAgZGltbmFtZXMobWljcm8kcGxhbnQpIDwtIHBsYW50bmFtZXMgCiAgICAKICAgIG1pY3JvJHNoYWRtZXQgICAgICA8LSBtaWNybyRtZXRvdXQKICAgIG1pY3JvJHNoYWRzb2lsICAgICA8LSBtaWNybyRzb2lsCiAgICBtaWNybyRodW1pZCAgICAgICAgPC0gbWljcm8kc29pbAogICAgbWljcm8kc2hhZGh1bWlkICAgIDwtIG1pY3JvJHNvaWwKICAgIG1pY3JvJHNvaWxwb3QgICAgICA8LSBtaWNybyRzb2lsCiAgICBtaWNybyRzaGFkcG90ICAgICAgPC0gbWljcm8kc29pbAogICAgbWljcm8kc29pbG1vaXN0ICAgIDwtIG1pY3JvJHNvaWwKICAgIG1pY3JvJHNoYWRtb2lzdCAgICA8LSBtaWNybyRzb2lsCiAgICBtaWNybyRzaGFkdGNvbmQgICAgPC0gbWljcm8kdGNvbmQKICAgIG1pY3JvJHNoYWRkZW5zaXQgICA8LSBtaWNybyRkZW5zaXQKICAgIG1pY3JvJHNoYWRzcGVjaGVhdCA8LSBtaWNybyRzcGVjaGVhdAogICAgbWljcm8kc2hhZHBsYW50ICAgIDwtIG1pY3JvJHBsYW50CiAgICBtaWNybyRSQUlORkFMTCAgICAgPC0gcmVwKDAsIGxlbmd0aChUd2I0KS8yNCkKICAgIG1pY3JvJG1pbnNoYWRlICAgICA8LSByZXAoMCwgbGVuZ3RoKFR3YjQpLzI0KQogICAgbWljcm8kbWF4c2hhZGUgICAgIDwtIHJlcCg5MCwgbGVuZ3RoKFR3YjQpLzI0KQogICAgbWljcm8kbnllYXJzICAgICAgIDwtIGNlaWxpbmcobGVuZ3RoKFR3YjQpLzI0LzM2NSkKICAgIAogICAgIyByZXBsYWNlIGZpcnN0IGxpbmUgb2YgbWljcm9jbGltYXRlIGlucHV0IHdpdGggYWlyIHRlbXBlcmF0dXJlIGFuZCBodW1pZGl0eSBhdCB3aGljaCB0byBjb21wdXRlIFR3CiAgICBtaWNybyRtZXRvdXRbMTpsZW5ndGgoVHdiNCksYygzLDQsMTQpXSA8LSBjKFRhMltzdGFydDplbmRdLCByZXAoVGEyWzFdLCBleHRyYSkpICMgc2V0IGFpciBhbmQgc2t5IHRlbXBlcmF0dXJlCiAgICBtaWNybyRtZXRvdXRbMTpsZW5ndGgoVHdiNCksYyg1LDYpXSAgICA8LSBjKFJIMltzdGFydDplbmRdLCByZXAoUkgyWzFdLCBleHRyYSkpICMgc2V0IHJlbGF0aXZlIGh1bWlkaXR5CiAgICAjIG1pY3JvJG1ldG91dFsxOmxlbmd0aChUd2IzKSxjKDcsOCldIDwtIDAuMDUgIyBzZXQgd2luZCBzcGVlZCB0byBsb3cgKHNlbnNpdGl2ZSB0byB0aGlzKQogICAgbWljcm8kc29pbFsxOmxlbmd0aChUd2I0KSwzXSA8LSBjKFRhMltzdGFydDplbmRdLCByZXAoVGEyWzFdLCBleHRyYSkpICMgc2V0IHN1cmZhY2Ugc29pbCB0ZW1wZXJhdHVyZSB0byBhaXIgdGVtcGVyYXR1cmUKICAgIG1pY3JvJG1ldG91dFsxOmxlbmd0aChUd2I0KSwgMl0gPC0gcmVwKHNlcSgwLCAyMyAqIDYwLCA2MCksIGxlbmd0aChUYTIpLzI0ICsgMSlbMTpsZW5ndGgoVHdiNCldCiAgICAjbWljcm8kbWV0b3V0WzE6bGVuZ3RoKFR3YjMpLCAxXSA8LSBzZXEoMCwgMjMgKiA2MCwgNjApWzE6bGVuZ3RoKFR3YjMpXQogICAgcHJlc2hyIDwtIGMoUDJbc3RhcnQ6ZW5kXSwgcmVwKFAyWzFdLCBleHRyYSkpKjEwMDAgICAgICAgICAgCiAgICAKICAgIG1pY3JvJG1ldG91dFsxOmxlbmd0aChUd2I0KSxjKDcsOCldIDwtIGMod3MyW3N0YXJ0OmVuZF0sIHJlcCh3czJbMV0sIGV4dHJhKSkgIyBzZXQgd2luZCBzcGVlZCAgICAKICAgIAogICAgIyBydW4gdGhlIGVjdG90aGVybSBtb2RlbCAKICAgIG1lc3NhZ2UocGFzdGUoJ3J1bm5pbmcgZWN0b3RoZXJtIHNpbXVsYXRpb24gZm9yIG1vbnRoICcsbW9udGgsJyBmb3IgJywgbGVuZ3RoKFR3YjQpLCcgc2l0ZXMgXG4nKSkKICAgIHB0bSA8LSBwcm9jLnRpbWUoKSAjIFN0YXJ0IHRpbWluZwogICAgZ2MoKQogICAgZWN0byA8LSBlY3RvdGhlcm0oV3dfZyA9IDguNywKICAgICAgICAgICAgICAgICAgICAgIGxpdmUgPSAwLAogICAgICAgICAgICAgICAgICAgICAgcGN0X3dldCA9IDg3LAogICAgICAgICAgICAgICAgICAgICAgc2hhcGUgPSA0LCAjIGZyb2cKICAgICAgICAgICAgICAgICAgICAgIHByZXNociA9IHByZXNocikKICAgIG1lc3NhZ2UocGFzdGUwKCdydW50aW1lICcsIChwcm9jLnRpbWUoKSAtIHB0bSlbM10sICcgc2Vjb25kcycpKSAjIFN0b3AgdGhlIGNsb2NrCiAgICBnYygpCiAgICBlbnZpcm9uIDwtIGFzLmRhdGEuZnJhbWUoZWN0byRlbnZpcm9uKQogICAgbWFzYmFsIDwtIGFzLmRhdGEuZnJhbWUoZWN0byRtYXNiYWwpCiAgICBpZihrID09IDEpewogICAgICBUYi5lY3RvdGhlcm0gPC0gZW52aXJvbiRUQ1sxOihucm93KGVudmlyb24pIC0gZXh0cmEpXQogICAgICBFV0wuZWN0b3RoZXJtIDwtIG1hc2JhbCRIMk9DdXRfZ1sxOihucm93KG1hc2JhbCkgLSBleHRyYSldCiAgICB9ZWxzZXsKICAgICAgVGIuZWN0b3RoZXJtIDwtIGMoVGIuZWN0b3RoZXJtLCBlbnZpcm9uJFRDWzE6KG5yb3coZW52aXJvbikgLSBleHRyYSldKQogICAgICBFV0wuZWN0b3RoZXJtIDwtIGMoRVdMLmVjdG90aGVybSwgbWFzYmFsJEgyT0N1dF9nWzE6KG5yb3cobWFzYmFsKSAtIGV4dHJhKV0pCiAgICB9CiAgfQogIFRiMiA8LSBUYQogIFRiMlshaXMubmEoVGEpXSA8LSBUYi5lY3RvdGhlcm0KICBUYi5ncmlkIDwtIFRhLncKICBUYi5ncmlkIDwtIHNldFZhbHVlcyhUYi5ncmlkLCBUYjIpCiAgI3Bsb3QoVGIuZ3JpZCkKICAjbWFwKCd3b3JsZCcsIGFkZCA9IFRSVUUpCiAgCiAgRVdMMiA8LSBUYQogIEVXTDJbIWlzLm5hKFRhKV0gPC0gRVdMLmVjdG90aGVybQogIEVXTC5ncmlkIDwtIFRhLncKICBFV0wuZ3JpZCA8LSBzZXRWYWx1ZXMoRVdMLmdyaWQsIEVXTDIpCiAgI3Bsb3QoRVdMLmdyaWQpCiAgRVdMLmdyaWRbVGIuZ3JpZCA8PSAwXSA8LSBOQQogICNtYXAoJ3dvcmxkJywgYWRkID0gVFJVRSkKICAKICB3cml0ZVJhc3RlcihFV0wuZ3JpZCwgZmlsZSA9IHBhc3RlMCgnRVdMXycsbW9udGgsJ18yQy5uYycpLCBvdmVyd3JpdGU9VFJVRSkKfSAgCgojIyArNEMgIyMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgU2F0dXJhdGVkIHZhcG91ciBwcmVzc3VyZQp0bWF4X2Z1bGxfNEMgPC0gcmFzdGVyOjpicmljayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnVGVycmFDbGltYXRlNENfdG1heC5uYycpKSAjIDJtLCBkZWcgQwplc19rUGFfNEMgICAgPC0gdG1heF9mdWxsXzRDCnZhbHVlcyhlc19rUGFfNEMpIDwtIDAuNjExICogZXhwKDI1MDAwMDAgLyA0NjEuNSAqICggMSAvIDI3MyAtIDEgLyAodmFsdWVzKHRtYXhfZnVsbF80QykgKyAyNzMuMTUpKSkKCiMgQWN0dWFsIHZhcG91ciBwcmVzc3VyZQplYV9rUGEgICAgICA8LSByYXN0ZXI6OmJyaWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdUZXJyYUNsaW1hdGUxOTgxMjAxMF92YXAubmMnKSkKZWFfa1BhXzRDICAgPC0gZWFfa1BhCnZhbHVlcyhlYV9rUGFfNEMpIDwtIHZhbHVlcyhlYV9rUGFfNEMpICogMC44CgojIENhbGN1bGF0ZSBWUEQgKGtQYSkKdnBkX2Z1bGxfNEMgPC0gZWFfa1BhXzRDCnZhbHVlcyh2cGRfZnVsbF80QykgPC0gdmFsdWVzKGVzX2tQYV80QykgLSB2YWx1ZXMoZWFfa1BhXzRDKQoKVGJzICA8LSBjcm9wKHRtYXhfZnVsbF80QywgZXh0ZW50KGVsZXYpKQpFV0xzIDwtIFRicyAKCiMgUnVuIGVjdG90aGVybSBtb2RlbCBmb3IgZWFjaCBtb250aCBhbmQgc2F2ZSBvbiBsb2NhbCBkcml2ZSAoKzRDIHNjZW5hcmlvKQpmb3IobW9udGggaW4gMToxMil7CiAgVGEudyAgIDwtIGNyb3AodG1heF9mdWxsXzRDW1ttb250aF1dLCBleHRlbnQoZWxldikpCiAgZXNhdCAgIDwtIFZBUFBSUyhUYS53KQogIGUgICAgICA8LSBlc2F0IC0gY3JvcCh2cGRfZnVsbF80Q1tbbW9udGhdXSwgZXh0ZW50KGVsZXYpKSAqIDEwMDAKICBSSC53ICAgPC0gZSAvIGVzYXQgKiAxMDAKICBSSC53W1JILncgPCAwXSA8LSAwCiAgV2luZC53IDwtIGNyb3Aod3NfZnVsbFtbbW9udGhdXSwgZXh0ZW50KGVsZXYpKQogIFZzdGFyICA8LSAwLjQgKiBXaW5kLncgLyBsb2coKDEwMCAvIDAuMTUpICsgMSkgIyBmcmljdGlvbiB2ZWxvY2l0eQogIFdpbmQudyA8LSAyLjUgKiBWc3RhciAqIGxvZygoMSAvIDAuMTUpICsgMSkgIyBjb3JyZWN0IGZvciByZWZlcmVuY2UgaGVpZ2h0ICgxMCBtKSB0byBncm91bmQgbGV2ZWwgKDEgY20pIGFzc3VtaW5nIGxldmVsIGdyb3VuZAogICMgY29tcHV0ZSBhdG1vc3BoZXJpYyBwcmVzc3VyZSAoa1BhKQogIFAudyA8LSAxMDEzMjUgKiAoKDEgLSAoMC4wMDY1ICogZWxldiAvIDI4OCkpIF4gKDEgLyAwLjE5MDI4NCkpIC8gMTAwMAogIAogIFRhICA8LSBnZXRWYWx1ZXMoVGEudykKICBSSCAgPC0gZ2V0VmFsdWVzKFJILncpCiAgUCAgIDwtIGdldFZhbHVlcyhQLncpCiAgUGEgIDwtIGdldFZhbHVlcyhlKQogIHdzICA8LSBnZXRWYWx1ZXMoV2luZC53KQogIFBbIWlzLm5hKFRhKSAmIGlzLm5hKFApXSA8LSAxMDEuMzI1CiAgVGEyIDwtIFRhWyFpcy5uYShUYSldCiAgUkgyIDwtIFJIWyFpcy5uYShUYSldCiAgUDIgIDwtIFBbIWlzLm5hKFRhKV0KICB3czIgPC0gd3NbIWlzLm5hKFRhKV0KICBQYTIgPC0gUGFbIWlzLm5hKFRhKV0KICAKICBkaXYgPC0gMTAKICBUd2IgPC0gVGEyWzE6Zmxvb3IobGVuZ3RoKFRhMikgLyBkaXYpXQogIG1pY3JvX2Jhc2UgPC0gbWljcm9fZ2xvYmFsKCkKICAKICBmb3IoayBpbiAxOmRpdil7CiAgICBtaWNybyA8LSBtaWNyb19iYXNlCiAgICBpZihrID09IDEpewogICAgICBleHRyYSA8LSByb3VuZCgyNCAtIChsZW5ndGgoVHdiKSAvIDI0KSUlMSAqIDI0LCAwKQogICAgICBUd2I0ICA8LSBjKFR3YiwgcmVwKFRhMlsxXSwgZXh0cmEpKQogICAgICBzdGFydCA8LSAxCiAgICAgIGVuZCAgIDwtIGxlbmd0aChUd2IpCiAgICB9CiAgICBpZihrID4gMSAmIGsgPCBkaXYpewogICAgICBmYWN0ICA8LSAobGVuZ3RoKFR3YikgKiAoayAtIDEpICsgayAtIDEpCiAgICAgIFR3YjQgIDwtIFRhMltmYWN0OihmYWN0ICsgbGVuZ3RoKFR3YikpXQogICAgICBleHRyYSA8LSByb3VuZCgyNCAtIChsZW5ndGgoVHdiNCkgLyAyNCklJTEgKiAyNCwgMCkKICAgICAgVHdiNCAgPC0gYyhUd2I0LCByZXAoVGEyWzFdLCBleHRyYSkpCiAgICAgIHN0YXJ0IDwtIGZhY3QKICAgICAgZW5kICAgPC0gZmFjdCArIGxlbmd0aChUd2IpCiAgICB9ICAgICAgICAKICAgIGlmKGsgPT0gZGl2KXsKICAgICAgZmFjdCAgPC0gKGxlbmd0aChUd2IpICogKGsgLSAxKSArIGsgLSAxKQogICAgICBUd2I0ICA8LSBUYTJbZmFjdDpsZW5ndGgoVGEyKV0KICAgICAgZXh0cmEgPC0gcm91bmQoMjQgLSAobGVuZ3RoKFR3YjQpIC8gMjQpJSUxICogMjQsIDApCiAgICAgIFR3YjQgIDwtIGMoVHdiNCwgcmVwKFRhMlsxXSwgZXh0cmEpKQogICAgICBzdGFydCA8LSBmYWN0CiAgICAgIGVuZCAgIDwtIGxlbmd0aChUYTIpCiAgICB9IAogICAgCiAgICBzb2lsbmFtZXMgICAgIDwtIGRpbW5hbWVzKG1pY3JvJHNvaWwpCiAgICBtZXRvdXRuYW1lcyAgIDwtIGRpbW5hbWVzKG1pY3JvJG1ldG91dCkKICAgIHRjb25kbmFtZXMgICAgPC0gZGltbmFtZXMobWljcm8kdGNvbmQpCiAgICBzcGVjaGVhdG5hbWVzIDwtIGRpbW5hbWVzKG1pY3JvJHNwZWNoZWF0KQogICAgZGVuc2l0bmFtZXMgICA8LSBkaW1uYW1lcyhtaWNybyRkZW5zaXQpCiAgICBwbGFudG5hbWVzICAgIDwtIGRpbW5hbWVzKG1pY3JvJHBsYW50KQogICAgCiAgICBtaWNybyRtZXRvdXQgICA8LSB0KGFycmF5KG1pY3JvJG1ldG91dFsxLF0sIGRpbSA9IGMobmNvbChtaWNybyRtZXRvdXQpLCBsZW5ndGgoVHdiNCkpKSkKICAgIGRpbW5hbWVzKG1pY3JvJG1ldG91dCkgPC0gbWV0b3V0bmFtZXMKICAgIG1pY3JvJHNvaWwgICAgIDwtIHQoYXJyYXkobWljcm8kc29pbFsxLF0sIGRpbSA9IGMobmNvbChtaWNybyRzb2lsKSwgbGVuZ3RoKFR3YjQpKSkpCiAgICBkaW1uYW1lcyhtaWNybyRzb2lsKSA8LSBzb2lsbmFtZXMKICAgIG1pY3JvJHRjb25kICAgIDwtIHQoYXJyYXkobWljcm8kdGNvbmRbMSxdLCBkaW0gPSBjKG5jb2wobWljcm8kdGNvbmQpLCBsZW5ndGgoVHdiNCkpKSkKICAgIGRpbW5hbWVzKG1pY3JvJHRjb25kKSA8LSB0Y29uZG5hbWVzCiAgICBtaWNybyRzcGVjaGVhdCA8LSB0KGFycmF5KG1pY3JvJHNwZWNoZWF0WzEsXSwgZGltID0gYyhuY29sKG1pY3JvJHNwZWNoZWF0KSwgbGVuZ3RoKFR3YjQpKSkpCiAgICBkaW1uYW1lcyhtaWNybyRzcGVjaGVhdCkgPC0gc3BlY2hlYXRuYW1lcyAgCiAgICBtaWNybyRkZW5zaXQgICA8LSB0KGFycmF5KG1pY3JvJGRlbnNpdFsxLF0sIGRpbSA9IGMobmNvbChtaWNybyRkZW5zaXQpLCBsZW5ndGgoVHdiNCkpKSkKICAgIGRpbW5hbWVzKG1pY3JvJGRlbnNpdCkgPC0gZGVuc2l0bmFtZXMgICAgICAKICAgIG1pY3JvJHBsYW50ICAgIDwtIHQoYXJyYXkobWljcm8kcGxhbnRbMSxdLCBkaW0gPSBjKG5jb2wobWljcm8kcGxhbnQpLCBsZW5ndGgoVHdiNCkpKSkKICAgIGRpbW5hbWVzKG1pY3JvJHBsYW50KSA8LSBwbGFudG5hbWVzIAogICAgCiAgICBtaWNybyRzaGFkbWV0ICAgICAgPC0gbWljcm8kbWV0b3V0CiAgICBtaWNybyRzaGFkc29pbCAgICAgPC0gbWljcm8kc29pbAogICAgbWljcm8kaHVtaWQgICAgICAgIDwtIG1pY3JvJHNvaWwKICAgIG1pY3JvJHNoYWRodW1pZCAgICA8LSBtaWNybyRzb2lsCiAgICBtaWNybyRzb2lscG90ICAgICAgPC0gbWljcm8kc29pbAogICAgbWljcm8kc2hhZHBvdCAgICAgIDwtIG1pY3JvJHNvaWwKICAgIG1pY3JvJHNvaWxtb2lzdCAgICA8LSBtaWNybyRzb2lsCiAgICBtaWNybyRzaGFkbW9pc3QgICAgPC0gbWljcm8kc29pbAogICAgbWljcm8kc2hhZHRjb25kICAgIDwtIG1pY3JvJHRjb25kCiAgICBtaWNybyRzaGFkZGVuc2l0ICAgPC0gbWljcm8kZGVuc2l0CiAgICBtaWNybyRzaGFkc3BlY2hlYXQgPC0gbWljcm8kc3BlY2hlYXQKICAgIG1pY3JvJHNoYWRwbGFudCAgICA8LSBtaWNybyRwbGFudAogICAgbWljcm8kUkFJTkZBTEwgICAgIDwtIHJlcCgwLCBsZW5ndGgoVHdiNCkvMjQpCiAgICBtaWNybyRtaW5zaGFkZSAgICAgPC0gcmVwKDAsIGxlbmd0aChUd2I0KS8yNCkKICAgIG1pY3JvJG1heHNoYWRlICAgICA8LSByZXAoOTAsIGxlbmd0aChUd2I0KS8yNCkKICAgIG1pY3JvJG55ZWFycyAgICAgICA8LSBjZWlsaW5nKGxlbmd0aChUd2I0KS8yNC8zNjUpCiAgICAKICAgICMgcmVwbGFjZSBmaXJzdCBsaW5lIG9mIG1pY3JvY2xpbWF0ZSBpbnB1dCB3aXRoIGFpciB0ZW1wZXJhdHVyZSBhbmQgaHVtaWRpdHkgYXQgd2hpY2ggdG8gY29tcHV0ZSBUdwogICAgbWljcm8kbWV0b3V0WzE6bGVuZ3RoKFR3YjQpLGMoMyw0LDE0KV0gPC0gYyhUYTJbc3RhcnQ6ZW5kXSwgcmVwKFRhMlsxXSwgZXh0cmEpKSAjIHNldCBhaXIgYW5kIHNreSB0ZW1wZXJhdHVyZQogICAgbWljcm8kbWV0b3V0WzE6bGVuZ3RoKFR3YjQpLGMoNSw2KV0gICAgPC0gYyhSSDJbc3RhcnQ6ZW5kXSwgcmVwKFJIMlsxXSwgZXh0cmEpKSAjIHNldCByZWxhdGl2ZSBodW1pZGl0eQogICAgIyBtaWNybyRtZXRvdXRbMTpsZW5ndGgoVHdiMyksYyg3LDgpXSA8LSAwLjA1ICMgc2V0IHdpbmQgc3BlZWQgdG8gbG93IChzZW5zaXRpdmUgdG8gdGhpcykKICAgIG1pY3JvJHNvaWxbMTpsZW5ndGgoVHdiNCksM10gPC0gYyhUYTJbc3RhcnQ6ZW5kXSwgcmVwKFRhMlsxXSwgZXh0cmEpKSAjIHNldCBzdXJmYWNlIHNvaWwgdGVtcGVyYXR1cmUgdG8gYWlyIHRlbXBlcmF0dXJlCiAgICBtaWNybyRtZXRvdXRbMTpsZW5ndGgoVHdiNCksIDJdIDwtIHJlcChzZXEoMCwgMjMgKiA2MCwgNjApLCBsZW5ndGgoVGEyKS8yNCArIDEpWzE6bGVuZ3RoKFR3YjQpXQogICAgI21pY3JvJG1ldG91dFsxOmxlbmd0aChUd2IzKSwgMV0gPC0gc2VxKDAsIDIzICogNjAsIDYwKVsxOmxlbmd0aChUd2IzKV0KICAgIHByZXNociA8LSBjKFAyW3N0YXJ0OmVuZF0sIHJlcChQMlsxXSwgZXh0cmEpKSoxMDAwICAgICAgICAgIAogICAgCiAgICBtaWNybyRtZXRvdXRbMTpsZW5ndGgoVHdiNCksYyg3LDgpXSA8LSBjKHdzMltzdGFydDplbmRdLCByZXAod3MyWzFdLCBleHRyYSkpICMgc2V0IHdpbmQgc3BlZWQgICAgCiAgICAKICAgICMgcnVuIHRoZSBlY3RvdGhlcm0gbW9kZWwgCiAgICBtZXNzYWdlKHBhc3RlKCdydW5uaW5nIGVjdG90aGVybSBzaW11bGF0aW9uIGZvciBtb250aCAnLG1vbnRoLCcgZm9yICcsIGxlbmd0aChUd2I0KSwnIHNpdGVzIFxuJykpCiAgICBwdG0gPC0gcHJvYy50aW1lKCkgIyBTdGFydCB0aW1pbmcKICAgIGdjKCkKICAgIGVjdG8gPC0gZWN0b3RoZXJtKFd3X2cgPSA4LjcsCiAgICAgICAgICAgICAgICAgICAgICBsaXZlID0gMCwKICAgICAgICAgICAgICAgICAgICAgIHBjdF93ZXQgPSA4NywKICAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gNCwgIyBmcm9nCiAgICAgICAgICAgICAgICAgICAgICBwcmVzaHIgPSBwcmVzaHIpCiAgICBtZXNzYWdlKHBhc3RlMCgncnVudGltZSAnLCAocHJvYy50aW1lKCkgLSBwdG0pWzNdLCAnIHNlY29uZHMnKSkgIyBTdG9wIHRoZSBjbG9jawogICAgZ2MoKQogICAgZW52aXJvbiA8LSBhcy5kYXRhLmZyYW1lKGVjdG8kZW52aXJvbikKICAgIG1hc2JhbCA8LSBhcy5kYXRhLmZyYW1lKGVjdG8kbWFzYmFsKQogICAgaWYoayA9PSAxKXsKICAgICAgVGIuZWN0b3RoZXJtIDwtIGVudmlyb24kVENbMToobnJvdyhlbnZpcm9uKSAtIGV4dHJhKV0KICAgICAgRVdMLmVjdG90aGVybSA8LSBtYXNiYWwkSDJPQ3V0X2dbMToobnJvdyhtYXNiYWwpIC0gZXh0cmEpXQogICAgfWVsc2V7CiAgICAgIFRiLmVjdG90aGVybSA8LSBjKFRiLmVjdG90aGVybSwgZW52aXJvbiRUQ1sxOihucm93KGVudmlyb24pIC0gZXh0cmEpXSkKICAgICAgRVdMLmVjdG90aGVybSA8LSBjKEVXTC5lY3RvdGhlcm0sIG1hc2JhbCRIMk9DdXRfZ1sxOihucm93KG1hc2JhbCkgLSBleHRyYSldKQogICAgfQogIH0KICBUYjIgPC0gVGEKICBUYjJbIWlzLm5hKFRhKV0gPC0gVGIuZWN0b3RoZXJtCiAgVGIuZ3JpZCA8LSBUYS53CiAgVGIuZ3JpZCA8LSBzZXRWYWx1ZXMoVGIuZ3JpZCwgVGIyKQogICNwbG90KFRiLmdyaWQpCiAgI21hcCgnd29ybGQnLCBhZGQgPSBUUlVFKQogIAogIEVXTDIgPC0gVGEKICBFV0wyWyFpcy5uYShUYSldIDwtIEVXTC5lY3RvdGhlcm0KICBFV0wuZ3JpZCA8LSBUYS53CiAgRVdMLmdyaWQgPC0gc2V0VmFsdWVzKEVXTC5ncmlkLCBFV0wyKQogICNwbG90KEVXTC5ncmlkKQogIEVXTC5ncmlkW1RiLmdyaWQgPD0gMF0gPC0gTkEKICAjbWFwKCd3b3JsZCcsIGFkZCA9IFRSVUUpCiAgCiAgd3JpdGVSYXN0ZXIoRVdMLmdyaWQsIGZpbGUgPSBwYXN0ZTAoJ0VXTF8nLG1vbnRoLCdfNEMubmMnKSwgb3ZlcndyaXRlPVRSVUUpCn0gIApgYGAKCkNyZWF0ZSBwbG90cyBmb3IgbWFpbiB0ZXh0IGZpZ3VyZSAzLgoKYGBge3IgRmlnIDMsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9NywgZmlnLnNob3c9J2hpZGUnfQojIEltcG9ydCB0aGUgZG93bmxvYWRlZCBmaWxlcwpFV0xfamFuIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfMS5uYycpKSwgYW51cmFuX3NyKQpFV0xfZmViIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfMi5uYycpKSwgYW51cmFuX3NyKQpFV0xfbWFyIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfMy5uYycpKSwgYW51cmFuX3NyKQpFV0xfYXByIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfNC5uYycpKSwgYW51cmFuX3NyKQpFV0xfbWF5IDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfNS5uYycpKSwgYW51cmFuX3NyKQpFV0xfanVuIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfNi5uYycpKSwgYW51cmFuX3NyKQpFV0xfanVsIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfNy5uYycpKSwgYW51cmFuX3NyKQpFV0xfYXVnIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfOC5uYycpKSwgYW51cmFuX3NyKQpFV0xfc2VwIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfOS5uYycpKSwgYW51cmFuX3NyKQpFV0xfb2N0IDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfMTAubmMnKSksIGFudXJhbl9zcikKRVdMX25vdiA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzExLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9kZWMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF8xMi5uYycpKSwgYW51cmFuX3NyKQoKRVdMX2phbl8yQyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzFfMkMubmMnKSksIGFudXJhbl9zcikKRVdMX2ZlYl8yQyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzJfMkMubmMnKSksIGFudXJhbl9zcikKRVdMX21hcl8yQyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzNfMkMubmMnKSksIGFudXJhbl9zcikKRVdMX2Fwcl8yQyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzRfMkMubmMnKSksIGFudXJhbl9zcikKRVdMX21heV8yQyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzVfMkMubmMnKSksIGFudXJhbl9zcikKRVdMX2p1bl8yQyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzZfMkMubmMnKSksIGFudXJhbl9zcikKRVdMX2p1bF8yQyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzdfMkMubmMnKSksIGFudXJhbl9zcikKRVdMX2F1Z18yQyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzhfMkMubmMnKSksIGFudXJhbl9zcikKRVdMX3NlcF8yQyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzlfMkMubmMnKSksIGFudXJhbl9zcikKRVdMX29jdF8yQyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzEwXzJDLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9ub3ZfMkMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF8xMV8yQy5uYycpKSwgYW51cmFuX3NyKQpFV0xfZGVjXzJDIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfMTJfMkMubmMnKSksIGFudXJhbl9zcikKCkVXTF9qYW5fNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF8xXzRDLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9mZWJfNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF8yXzRDLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9tYXJfNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF8zXzRDLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9hcHJfNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF80XzRDLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9tYXlfNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF81XzRDLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9qdW5fNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF82XzRDLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9qdWxfNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF83XzRDLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9hdWdfNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF84XzRDLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9zZXBfNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF85XzRDLm5jJykpLCBhbnVyYW5fc3IpCkVXTF9vY3RfNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soZmlsZS5wYXRoKHNwYXRpYWxfcGF0aCwgJ0VXTF8xMF80Qy5uYycpKSwgYW51cmFuX3NyKQpFV0xfbm92XzRDIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKGZpbGUucGF0aChzcGF0aWFsX3BhdGgsICdFV0xfMTFfNEMubmMnKSksIGFudXJhbl9zcikKRVdMX2RlY180QyA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmaWxlLnBhdGgoc3BhdGlhbF9wYXRoLCAnRVdMXzEyXzRDLm5jJykpLCBhbnVyYW5fc3IpCgojIENvbWJpbmUgYWxsCkVXTF9hbGwgPC0gcmFzdGVyOjpzdGFjayhFV0xfamFuLCBFV0xfZmViLCBFV0xfbWFyLCBFV0xfYXByLCBFV0xfbWF5LCBFV0xfanVuLCAKICAgICAgICAgICAgICAgICAgICAgICAgIEVXTF9qdWwsIEVXTF9hdWcsIEVXTF9zZXAsIEVXTF9vY3QsIEVXTF9ub3YsIEVXTF9kZWMpCgpFV0xfYWxsXzJDIDwtIHJhc3Rlcjo6c3RhY2soRVdMX2phbl8yQywgRVdMX2ZlYl8yQywgRVdMX21hcl8yQywgRVdMX2Fwcl8yQywgRVdMX21heV8yQywgRVdMX2p1bl8yQywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFV0xfanVsXzJDLCBFV0xfYXVnXzJDLCBFV0xfc2VwXzJDLCBFV0xfb2N0XzJDLCBFV0xfbm92XzJDLCBFV0xfZGVjXzJDKQoKRVdMX2FsbF80QyA8LSByYXN0ZXI6OnN0YWNrKEVXTF9qYW5fNEMsIEVXTF9mZWJfNEMsIEVXTF9tYXJfNEMsIEVXTF9hcHJfNEMsIEVXTF9tYXlfNEMsIEVXTF9qdW5fNEMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRVdMX2p1bF80QywgRVdMX2F1Z180QywgRVdMX3NlcF80QywgRVdMX29jdF80QywgRVdMX25vdl80QywgRVdMX2RlY180QykKCkVXTF9hbGxfbWVhbiAgICA8LSByYXN0ZXI6OmNhbGMoRVdMX2FsbCwgZnVuID0gbWVhbiwgbmEucm0gPSBUUlVFKQpFV0xfYWxsX21lYW5fMkMgPC0gcmFzdGVyOjpjYWxjKEVXTF9hbGxfMkMsIGZ1biA9IG1lYW4sIG5hLnJtID0gVFJVRSkKRVdMX2FsbF9tZWFuXzRDIDwtIHJhc3Rlcjo6Y2FsYyhFV0xfYWxsXzRDLCBmdW4gPSBtZWFuLCBuYS5ybSA9IFRSVUUpCgpFV0xfZGlmZl8yQyA8LSByYXN0ZXI6Om92ZXJsYXkoeCA9IEVXTF9hbGxfbWVhbiwgeSA9IEVXTF9hbGxfbWVhbl8yQywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuID0gZnVuY3Rpb24oeCwgeSkge3JldHVybih5IC0geCl9KSAKCkVXTF9kaWZmXzRDIDwtIHJhc3Rlcjo6b3ZlcmxheSh4ID0gRVdMX2FsbF9tZWFuLCB5ID0gRVdMX2FsbF9tZWFuXzRDLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW4gPSBmdW5jdGlvbih4LCB5KSB7cmV0dXJuKHkgLSB4KX0pIAoKRVdMX3Jpc2tfcm9iICAgIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKEVXTF9hbGxfbWVhbiwgYW51cmFuX3NyLCBhcXVhdGljX3NyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJib3JlYWxfc3IsIGZvc3NvcmlhbF9zciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VuZF9zciwgc2VtaV9hcV9zciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbV9zciksIGNycyA9IHJvYl9wcm9qKQpFV0xfcmlza19yb2JfMkMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soRVdMX2RpZmZfMkMsIGFudXJhbl9zciksIGNycyA9IHJvYl9wcm9qKQpFV0xfcmlza19yb2JfNEMgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soRVdMX2RpZmZfNEMsIGFudXJhbl9zciksIGNycyA9IHJvYl9wcm9qKQoKRVdMX3NwX2RmIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKEVXTF9yaXNrX3JvYikpICU+JSAKICByZW5hbWUoRVdMICAgICAgID0gbGF5ZXIuMSwgCiAgICAgICAgIHNwZWNpZXNfbiA9IGxheWVyLjIsCiAgICAgICAgIGFxdWFfc3AgPSBsYXllci4zLAogICAgICAgICBhcmJvX3NwID0gbGF5ZXIuNCwKICAgICAgICAgZm9zc19zcCA9IGxheWVyLjUsCiAgICAgICAgIGdyb25fc3AgPSBsYXllci42LAogICAgICAgICBzZW1pX3NwID0gbGF5ZXIuNywKICAgICAgICAgc3RybV9zcCA9IGxheWVyLjgpICU+JQogIGRyb3BfbmEoc3BlY2llc19uKQoKRVdMX3NwXzJDX2RmIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKEVXTF9yaXNrX3JvYl8yQykpICU+JSAKICByZW5hbWUoRVdMX2RpZmYgID0gbGF5ZXIuMSwgCiAgICAgICAgIHNwZWNpZXNfbiA9IGxheWVyLjIpICU+JQogIGRyb3BfbmEoc3BlY2llc19uKQoKRVdMX3NwXzRDX2RmIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKEVXTF9yaXNrX3JvYl80QykpICU+JSAKICByZW5hbWUoRVdMX2RpZmYgID0gbGF5ZXIuMSwgCiAgICAgICAgIHNwZWNpZXNfbiA9IGxheWVyLjIpICU+JQogIGRyb3BfbmEoc3BlY2llc19uKQoKIyBGaWcuIDNhCkVXTF9jdXJfcGxvdCA8LSBFV0xfc3BfZGYgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBFV0wpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9yb2IsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJZbEduQnUiLCByZXYgPSBULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gZXhwcmVzc2lvbigiRVdMIn4oImcifkhbMl0qT35oXnsiLTEifSkpKSArCiAgZ2duZXdzY2FsZTo6bmV3X3NjYWxlKCJmaWxsIikgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBoaWxsX2RmICU+JSBmaWx0ZXIoaGlsbCA8PSAwLjY0NSksIGFlcyhsb24sIGxhdCwgZmlsbCA9IGhpbGwsIGFscGhhID0gaGlsbCksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAiZ3JleSIpICsKICBzY2FsZV9hbHBoYV9jb250aW51b3VzKHRyYW5zID0gInJldmVyc2UiKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MWU1LCA4NWU1KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xNWU2LCAxNmU2KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMjAsIGJhcmhlaWdodCA9IDAuMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwucG9zaXRpb24gPSAiYm90dG9tIikpICsKICB0aGVtZV92b2lkKCkgKyB5bGFiKE5VTEwpICsgeGxhYihOVUxMKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwgCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICMgZml4ZWQgcmF0aW8KCiMgRmlnLiAzYiAtIFNwZWNpZXMgcmljaG5lc3MgYW5kIEVXTApFV0xfc3BfcGxvdCA8LSBFV0xfc3BfZGYgJT4lCiAgZ2dwbG90KGFlcyh4ID0gRVdMLCB5ID0gc3BlY2llc19uKSkgKwogIGdlb21fcG9pbnQoY29sb3VyID0gImdyZXkiKSArCiAgeGxhYihleHByZXNzaW9uKCJFV0wifigiZyJ+SFsyXSpPfmheeyItMSJ9KSkpICsKICB5bGFiKCJTcGVjaWVzIHJpY2huZXNzIikgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAzLCAwLjUpLCBleHBhbmQgPSBjKDAsIDApKSArIAogIG15dGhlbWUoKQoKIyBGaWcuIDNjICsyQwpFV0xfMkNfcGxvdCA8LSBFV0xfc3BfMkNfZGYgJT4lCiAgZHBseXI6Om11dGF0ZShFV0xfZGlmZl9jYXQgPSBjYXNlX3doZW4oCiAgICBFV0xfZGlmZiA9PSAwIH4gJzAnLAogICAgRVdMX2RpZmYgPiAwICYgRVdMX2RpZmYgPD0xIH4gJzwxJywKICAgIEVXTF9kaWZmID49IDEgJiBFV0xfZGlmZiA8IDEuNSB+ICc+MSB0byAxLjUnLAogICAgRVdMX2RpZmYgPj0gMS41ICYgRVdMX2RpZmYgPCAyIH4gJz4xLjUgdG8gMicsCiAgICBFV0xfZGlmZiA+PSAyICYgRVdMX2RpZmYgPCAyLjUgfiAnPjIgdG8gMi41JywKICAgIEVXTF9kaWZmID49IDIuNSAmIEVXTF9kaWZmIDwgMyB+ICc+Mi41IHRvIDMnLAogICAgRVdMX2RpZmYgPiAzIH4gJz4zJyksCiAgICBFV0xfZGlmZiA9IG5hX2lmKEVXTF9kaWZmLCAwKSwKICAgIEVXTF9kaWZmY2F0ID0gZmFjdG9yKEVXTF9kaWZmX2NhdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCc+MycsICc8Mi41IHRvIDMnLCc+MiB0byAyLjUnLCAnMS41IHRvIDInLCAnPjEgdG8gMS41JywgJzwxJykpKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoYWVzKHkgPSB5LCB4ID0geCwgZmlsbCA9IEVXTF9kaWZmX2NhdCkpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkX3JvYiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgY29sb3VyID0gIiM2NDY4NmIiLCBmaWxsID0gTkEsIHNpemUgPSAwLjEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjRTJFNkJEIiwgIiNFN0NCNDciLCAiI0VBQUIyOCIsICIjRTc4QTM4IiwgIiNERjY3NTMiLCAiI0QzM0Y2QSIpLCBuYS50cmFuc2xhdGUgPSBGLCBuYW1lID0gZXhwcmVzc2lvbihEZWx0YSoiRVdMIn4oImcifkhbMl0qT35oXnsiLTEifSkpKSArCiAgZ2duZXdzY2FsZTo6bmV3X3NjYWxlKCJmaWxsIikgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBoaWxsX2RmICU+JSBmaWx0ZXIoaGlsbCA8PSAwLjY0NSksIGFlcyhsb24sIGxhdCwgZmlsbCA9IGhpbGwsIGFscGhhID0gaGlsbCksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAiZ3JleSIpICsKICBzY2FsZV9hbHBoYV9jb250aW51b3VzKHRyYW5zID0gInJldmVyc2UiKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MWU1LCA4NWU1KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xNWU2LCAxNmU2KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMjAsIGJhcmhlaWdodCA9IDAuMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwucG9zaXRpb24gPSAiYm90dG9tIikpICsKICB0aGVtZV92b2lkKCkgKyB5bGFiKE5VTEwpICsgeGxhYihOVUxMKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwgCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICMgZml4ZWQgcmF0aW8KCiMgRmlnLiAzZCArNEMKRVdMXzRDX3Bsb3QgPC0gRVdMX3NwXzRDX2RmICU+JQogIGRwbHlyOjptdXRhdGUoRVdMX2RpZmZfY2F0ID0gY2FzZV93aGVuKAogICAgRVdMX2RpZmYgPT0gMCB+ICcwJywKICAgIEVXTF9kaWZmID4gMCAmIEVXTF9kaWZmIDw9MSB+ICc8MScsCiAgICBFV0xfZGlmZiA+PSAxICYgRVdMX2RpZmYgPCAxLjUgfiAnPjEgdG8gMS41JywKICAgIEVXTF9kaWZmID49IDEuNSAmIEVXTF9kaWZmIDwgMiB+ICc+MS41IHRvIDInLAogICAgRVdMX2RpZmYgPj0gMiAmIEVXTF9kaWZmIDwgMi41IH4gJz4yIHRvIDIuNScsCiAgICBFV0xfZGlmZiA+PSAyLjUgJiBFV0xfZGlmZiA8IDMgfiAnPjIuNSB0byAzJywKICAgIEVXTF9kaWZmID4gMyB+ICc+MycpLAogICAgRVdMX2RpZmYgPSBuYV9pZihFV0xfZGlmZiwgMCksCiAgICBFV0xfZGlmZmNhdCA9IGZhY3RvcihFV0xfZGlmZl9jYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnPjMnLCAnPDIuNSB0byAzJywnPjIgdG8gMi41JywgJzEuNSB0byAyJywgJz4xIHRvIDEuNScsICc8MScpKSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBFV0xfZGlmZl9jYXQpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9yb2IsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0UyRTZCRCIsICIjRTdDQjQ3IiwgIiNFQUFCMjgiLCAiI0U3OEEzOCIsICIjREY2NzUzIiwgIiNEMzNGNkEiKSwgbmEudHJhbnNsYXRlID0gRiwgbmFtZSA9IGV4cHJlc3Npb24oRGVsdGEqIkVXTCJ+KCJnIn5IWzJdKk9+aF57Ii0xIn0pKSkgKwogIGdnbmV3c2NhbGU6Om5ld19zY2FsZSgiZmlsbCIpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gaGlsbF9kZiAlPiUgZmlsdGVyKGhpbGwgPD0gMC42NDUpLCBhZXMobG9uLCBsYXQsIGZpbGwgPSBoaWxsLCBhbHBoYSA9IGhpbGwpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gImdyZXkiKSArCiAgc2NhbGVfYWxwaGFfY29udGludW91cyh0cmFucyA9ICJyZXZlcnNlIikgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNjFlNSwgODVlNSksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTVlNiwgMTZlNiksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDIwLCBiYXJoZWlnaHQgPSAwLjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAjIGZpeGVkIHJhdGlvCgpjb3dwbG90OjpwbG90X2dyaWQoRVdMX2N1cl9wbG90LAogICAgICAgICAgICAgICAgICAgRVdMX3NwX3Bsb3QsCiAgICAgICAgICAgICAgICAgICBFV0xfMkNfcGxvdCwKICAgICAgICAgICAgICAgICAgIEVXTF80Q19wbG90LAogICAgICAgICAgICAgICAgICAgbmNvbCA9IDIsCiAgICAgICAgICAgICAgICAgICBhbGlnbiA9ICJoIiwgYXhpcyA9ICJidCIsIGxhYmVscyA9IGMoJ2EnLCAnYicsICdjJywgJ2QnKSkKYGBgCgojIyBGaWd1cmUgNCAtIEFjdGl2aXR5IHJpc2sgLSBlY290eXBlIHstfQoKQ3JlYXRlIHBsb3RzIGZvciBtYWluIHRleHQgZmlndXJlIDQuCgpgYGAge3IgRmlnIDQsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OCwgZmlnLnNob3c9J2hpZGUnfQpzaGFkX3Bsb3QgPC0gc2hhZF9tb2RlbCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXksIHkgPSBjb25kaXRpb24sIGZpbGwgPSBob3VycykpICsgCiAgZ2VvbV90aWxlKCkgKwogIHZpcmlkaXM6OnNjYWxlX2ZpbGxfdmlyaWRpcyhvcHRpb24gPSAibWFnbWEiKSArCiAgI3NjYWxlX2ZpbGxfY29udGludW91c19kaXZlcmdpbmcocGFsZXR0ZSA9ICJCbHVlLVJlZCAzIiwgbWlkID0gMTIsIHJldiA9IFRSVUUpICsKICB5bGFiKE5VTEwpICsgeGxhYigiRGF5IG9mIHRoZSB5ZWFyIikgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM2NSwgNTApLCBleHBhbmQgPSBjKDAsIDApKSArIAogIG15dGhlbWUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9jb2xvdXJiYXIoYmFyaGVpZ2h0ID0gMC41LCBiYXJ3aWR0aCA9IDUsIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpKSAKCnRyZWVfcGxvdCA8LSB0cmVlX21vZGVsICU+JQogIGdncGxvdChhZXMoeCA9IGRheSwgeSA9IGNvbmRpdGlvbiwgZmlsbCA9IGhvdXJzKSkgKyAKICBnZW9tX3RpbGUoKSArCiAgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKG9wdGlvbiA9ICJtYWdtYSIpICsKICAjc2NhbGVfZmlsbF9jb250aW51b3VzX2RpdmVyZ2luZyhwYWxldHRlID0gIkJsdWUtUmVkIDMiLCBtaWQgPSAxMiwgcmV2ID0gVFJVRSkgKwogIHlsYWIoTlVMTCkgKyB4bGFiKCJEYXkgb2YgdGhlIHllYXIiKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMzY1LCA1MCksIGV4cGFuZCA9IGMoMCwgMCkpICsgCiAgbXl0aGVtZSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG91cmJhcihiYXJoZWlnaHQgPSAwLjUsIGJhcndpZHRoID0gNSwgbGFiZWwucG9zaXRpb24gPSAiYm90dG9tIikpIAoKYnVycl9wbG90IDwtIGJ1cnJfbW9kZWwgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5LCB5ID0gY29uZGl0aW9uLCBmaWxsID0gaG91cnMpKSArIAogIGdlb21fdGlsZSgpICsKICB2aXJpZGlzOjpzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uID0gIm1hZ21hIikgKwogICNzY2FsZV9maWxsX2NvbnRpbnVvdXNfZGl2ZXJnaW5nKHBhbGV0dGUgPSAiQmx1ZS1SZWQgMyIsIG1pZCA9IDEyLCByZXYgPSBUUlVFKSArCiAgeWxhYihOVUxMKSArIHhsYWIoIkRheSBvZiB0aGUgeWVhciIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM2NSwgNTApLCBleHBhbmQgPSBjKDAsIDApKSArIAogIG15dGhlbWUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9jb2xvdXJiYXIoYmFyaGVpZ2h0ID0gMC41LCBiYXJ3aWR0aCA9IDUsIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpKSAKCnByb3dfMiA8LSBjb3dwbG90OjpwbG90X2dyaWQoCiAgc2hhZF9wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0ibm9uZSIpLCAKICB0cmVlX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSJub25lIiksIAogIGJ1cnJfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9Im5vbmUiKSwKICBuY29sID0gMSwgbGFiZWxzID0gYygnYScsICdjJywgJ2UnKSwKICBhbGlnbiA9ICd2JywgYXhpcyA9ICdsJykKCmxlZ2VuZF9iXzIgPC0gY293cGxvdDo6Z2V0X2xlZ2VuZChidXJyX3Bsb3QgKyBndWlkZXMoY29sb3IgPSBndWlkZV9sZWdlbmQobnJvdyA9IDEpKSkKdG9wX2dyYXBoICA8LSBjb3dwbG90OjpwbG90X2dyaWQocHJvd18yLCBsZWdlbmRfYl8yLCBuY29sID0gMSwgcmVsX2hlaWdodHMgPSBjKDEsIC4xKSkKCiMgUmVsYXRpdmUgY2hhbmdlCnNoYWRfZGlmZl9tb2RlbCA8LSBzaGFkX2N1cnJfd2V0X2RmICU+JQogIG1lcmdlKHNoYWRfY3Vycl9kcnlfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKHNoYWRfd2FybV93ZXRfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKHNoYWRfd2FybV9kcnlfZGYsIGJ5ID0gImRheSIpICU+JQogIGRwbHlyOjptdXRhdGUoY3Vycl9kcnlfZGlmZiA9IGN1cnJfZHJ5IC0gY3Vycl93ZXQsCiAgICAgICAgICAgICAgICB3YXJtX3dldF9kaWZmID0gd2FybV93ZXQgLSBjdXJyX3dldCwKICAgICAgICAgICAgICAgIHdhcm1fZHJ5X2RpZmYgPSB3YXJtX2RyeSAtIGN1cnJfd2V0KSAlPiUKICBwaXZvdF9sb25nZXIoIWRheSwgbmFtZXNfdG8gPSAiY29uZGl0aW9uIiwgdmFsdWVzX3RvID0gImhvdXJzIikgJT4lCiAgZHBseXI6OmZpbHRlcihjb25kaXRpb24gPT0gYygiY3Vycl9kcnlfZGlmZiIsICJ3YXJtX3dldF9kaWZmIiwgIndhcm1fZHJ5X2RpZmYiKSkgJT4lCiAgZHBseXI6Om11dGF0ZShjb25kaXRpb24gPSBmYWN0b3IoY29uZGl0aW9uLCBsZXZlbHMgPSBjKCJ3YXJtX2RyeV9kaWZmIiwgIndhcm1fd2V0X2RpZmYiLCAiY3Vycl9kcnlfZGlmZiIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5LCB5ID0gY29uZGl0aW9uLCBmaWxsID0gaG91cnMpKSArIAogIGdlb21fdGlsZSgpICsKICBzY2FsZV9maWxsX2NvbnRpbnVvdXNfZGl2ZXJnaW5nKHBhbGV0dGUgPSAiQmx1ZS1SZWQgMyIsIG1pZCA9IDAsIHJldiA9IFRSVUUsIGxpbWl0cyA9IGMoLTE1LCAxNSkpICsKICB5bGFiKE5VTEwpICsgeGxhYigiRGF5IG9mIHRoZSB5ZWFyIikgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM2NSwgNTApLCBleHBhbmQgPSBjKDAsIDApKSArIAogIG15dGhlbWUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9jb2xvdXJiYXIoYmFyaGVpZ2h0ID0gMC41LCBiYXJ3aWR0aCA9IDUsIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpKSAKCnRyZWVfZGlmZl9tb2RlbCA8LSB0cmVlX2N1cnJfd2V0X2RmICU+JQogIG1lcmdlKHRyZWVfY3Vycl9kcnlfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKHRyZWVfd2FybV93ZXRfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKHRyZWVfd2FybV9kcnlfZGYsIGJ5ID0gImRheSIpICU+JQogIGRwbHlyOjptdXRhdGUoY3Vycl9kcnlfZGlmZiA9IGN1cnJfZHJ5IC0gY3Vycl93ZXQsCiAgICAgICAgICAgICAgICB3YXJtX3dldF9kaWZmID0gd2FybV93ZXQgLSBjdXJyX3dldCwKICAgICAgICAgICAgICAgIHdhcm1fZHJ5X2RpZmYgPSB3YXJtX2RyeSAtIGN1cnJfd2V0KSAlPiUKICBwaXZvdF9sb25nZXIoIWRheSwgbmFtZXNfdG8gPSAiY29uZGl0aW9uIiwgdmFsdWVzX3RvID0gImhvdXJzIikgJT4lCiAgZHBseXI6OmZpbHRlcihjb25kaXRpb24gPT0gYygiY3Vycl9kcnlfZGlmZiIsICJ3YXJtX3dldF9kaWZmIiwgIndhcm1fZHJ5X2RpZmYiKSkgJT4lCiAgZHBseXI6Om11dGF0ZShjb25kaXRpb24gPSBmYWN0b3IoY29uZGl0aW9uLCBsZXZlbHMgPSBjKCJ3YXJtX2RyeV9kaWZmIiwgIndhcm1fd2V0X2RpZmYiLCAiY3Vycl9kcnlfZGlmZiIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5LCB5ID0gY29uZGl0aW9uLCBmaWxsID0gaG91cnMpKSArIAogIGdlb21fdGlsZSgpICsKICBzY2FsZV9maWxsX2NvbnRpbnVvdXNfZGl2ZXJnaW5nKHBhbGV0dGUgPSAiQmx1ZS1SZWQgMyIsIG1pZCA9IDAsIHJldiA9IFRSVUUsIGxpbWl0cyA9IGMoLTE1LCAxNSkpICsKICB5bGFiKE5VTEwpICsgeGxhYigiRGF5IG9mIHRoZSB5ZWFyIikgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM2NSwgNTApLCBleHBhbmQgPSBjKDAsIDApKSArIAogIG15dGhlbWUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9jb2xvdXJiYXIoYmFyaGVpZ2h0ID0gMC41LCBiYXJ3aWR0aCA9IDUsIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpKSAKCmJ1cnJfZGlmZl9tb2RlbCA8LSBidXJyX2N1cnJfd2V0X2RmICU+JQogIG1lcmdlKGJ1cnJfY3Vycl9kcnlfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKGJ1cnJfd2FybV93ZXRfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKGJ1cnJfd2FybV9kcnlfZGYsIGJ5ID0gImRheSIpICU+JQogIGRwbHlyOjptdXRhdGUoY3Vycl9kcnlfZGlmZiA9IGN1cnJfZHJ5IC0gY3Vycl93ZXQsCiAgICAgICAgICAgICAgICB3YXJtX3dldF9kaWZmID0gd2FybV93ZXQgLSBjdXJyX3dldCwKICAgICAgICAgICAgICAgIHdhcm1fZHJ5X2RpZmYgPSB3YXJtX2RyeSAtIGN1cnJfd2V0KSAlPiUKICBwaXZvdF9sb25nZXIoIWRheSwgbmFtZXNfdG8gPSAiY29uZGl0aW9uIiwgdmFsdWVzX3RvID0gImhvdXJzIikgJT4lCiAgZHBseXI6OmZpbHRlcihjb25kaXRpb24gPT0gYygiY3Vycl9kcnlfZGlmZiIsICJ3YXJtX3dldF9kaWZmIiwgIndhcm1fZHJ5X2RpZmYiKSkgJT4lCiAgZHBseXI6Om11dGF0ZShjb25kaXRpb24gPSBmYWN0b3IoY29uZGl0aW9uLCBsZXZlbHMgPSBjKCJ3YXJtX2RyeV9kaWZmIiwgIndhcm1fd2V0X2RpZmYiLCAiY3Vycl9kcnlfZGlmZiIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5LCB5ID0gY29uZGl0aW9uLCBmaWxsID0gaG91cnMpKSArIAogIGdlb21fdGlsZSgpICsKICBzY2FsZV9maWxsX2NvbnRpbnVvdXNfZGl2ZXJnaW5nKHBhbGV0dGUgPSAiQmx1ZS1SZWQgMyIsIG1pZCA9IDAsIHJldiA9IFRSVUUsIGxpbWl0cyA9IGMoLTE1LCAxNSkpICsKICB5bGFiKE5VTEwpICsgeGxhYigiRGF5IG9mIHRoZSB5ZWFyIikgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM2NSwgNTApLCBleHBhbmQgPSBjKDAsIDApKSArIAogIG15dGhlbWUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9jb2xvdXJiYXIoYmFyaGVpZ2h0ID0gMC41LCBiYXJ3aWR0aCA9IDUsIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpKSAKCmJvdF9ncmFwaCA8LSBjb3dwbG90OjpwbG90X2dyaWQoCiAgc2hhZF9kaWZmX21vZGVsLCAKICB0cmVlX2RpZmZfbW9kZWwsIAogIGJ1cnJfZGlmZl9tb2RlbCwKICBuY29sID0gMSwgbGFiZWxzID0gYygnYicsICdkJywgJ2cnKSwKICBhbGlnbiA9ICd2JywgYXhpcyA9ICdsJykKCmNvd3Bsb3Q6OnBsb3RfZ3JpZCh0b3BfZ3JhcGgsIGJvdF9ncmFwaCkKCmBgYAoKIyMgRmlndXJlIDUgLSBBY3Rpdml0eSByaXNrIC0gYmlvbWUgey19CgpDcmVhdGUgcGxvdHMgZm9yIG1haW4gdGV4dCBmaWd1cmUgNS4KCmBgYCB7ciBGaWcgNSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD05LCBmaWcuc2hvdz0naGlkZSd9CmF1X2NvbWJfcGxvdCA8LSBjb3dwbG90OjpwbG90X2dyaWQoYXVfcGxvdCwgCiAgICAgICAgICAgICAgICAgICBzaGFkX2RpZmZfbW9kZWwgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM2NSwgMTAwKSwgZXhwYW5kID0gYygwLCAwKSksIAogICAgICAgICAgICAgICAgICAgbmNvbCA9IDEsIGFsaWduID0gJ3YnLCAgcmVsX2hlaWdodHMgPSBjKDAuNywgMSkpCgpicl9kaWZmX3Bsb3QgPC0gY3Vycl93ZXRfYnJfZGYgJT4lCiAgbWVyZ2UoY3Vycl9kcnlfYnJfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKHdhcm1fd2V0X2JyX2RmLCBieSA9ICJkYXkiKSAlPiUKICBtZXJnZSh3YXJtX2RyeV9icl9kZiwgYnkgPSAiZGF5IikgJT4lCiAgZHBseXI6Om11dGF0ZShjdXJyX2RyeV9kaWZmID0gY3Vycl9kcnkgLSBjdXJyX3dldCwKICAgICAgICAgICAgICAgIHdhcm1fd2V0X2RpZmYgPSB3YXJtX3dldCAtIGN1cnJfd2V0LAogICAgICAgICAgICAgICAgd2FybV9kcnlfZGlmZiA9IHdhcm1fZHJ5IC0gY3Vycl93ZXQpICU+JQogIHBpdm90X2xvbmdlcighZGF5LCBuYW1lc190byA9ICJjb25kaXRpb24iLCB2YWx1ZXNfdG8gPSAiaG91cnMiKSAlPiUKICBkcGx5cjo6ZmlsdGVyKGNvbmRpdGlvbiA9PSBjKCJjdXJyX2RyeV9kaWZmIiwgIndhcm1fd2V0X2RpZmYiLCAid2FybV9kcnlfZGlmZiIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGNvbmRpdGlvbiA9IGZhY3Rvcihjb25kaXRpb24sIGxldmVscyA9IGMoIndhcm1fZHJ5X2RpZmYiLCAid2FybV93ZXRfZGlmZiIsICJjdXJyX2RyeV9kaWZmIikpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXksIHkgPSBjb25kaXRpb24sIGZpbGwgPSBob3VycykpICsgCiAgZ2VvbV90aWxlKCkgKwogIHNjYWxlX2ZpbGxfY29udGludW91c19kaXZlcmdpbmcocGFsZXR0ZSA9ICJCbHVlLVJlZCAzIiwgbWlkID0gMCwgcmV2ID0gVFJVRSwgbGltaXRzID0gYygtMTUsIDE1KSkgKwogIHlsYWIoTlVMTCkgKyB4bGFiKCJEYXkgb2YgdGhlIHllYXIiKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMzY1LCA1MCksIGV4cGFuZCA9IGMoMCwgMCkpICsgCiAgbXl0aGVtZSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG91cmJhcihiYXJoZWlnaHQgPSAwLjUsIGJhcndpZHRoID0gNSwgbGFiZWwucG9zaXRpb24gPSAiYm90dG9tIikpIAoKYnJfY29tYl9wbG90IDwtIGNvd3Bsb3Q6OnBsb3RfZ3JpZChicl9wbG90LCAKICAgICAgICAgICAgICAgICAgIGJyX2RpZmZfcGxvdCArIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMzY1LCAxMDApLCBleHBhbmQgPSBjKDAsIDApKSwgCiAgICAgICAgICAgICAgICAgICBuY29sID0gMSwgYWxpZ24gPSAndicsICByZWxfaGVpZ2h0cyA9IGMoMC43LCAxKSkKCnNhX2RpZmZfcGxvdCA8LSBjdXJyX3dldF9zYV9kZiAlPiUKICBtZXJnZShjdXJyX2RyeV9zYV9kZiwgYnkgPSAiZGF5IikgJT4lCiAgbWVyZ2Uod2FybV93ZXRfc2FfZGYsIGJ5ID0gImRheSIpICU+JQogIG1lcmdlKHdhcm1fZHJ5X3NhX2RmLCBieSA9ICJkYXkiKSAlPiUKICBkcGx5cjo6bXV0YXRlKGN1cnJfZHJ5X2RpZmYgPSBjdXJyX2RyeSAtIGN1cnJfd2V0LAogICAgICAgICAgICAgICAgd2FybV93ZXRfZGlmZiA9IHdhcm1fd2V0IC0gY3Vycl93ZXQsCiAgICAgICAgICAgICAgICB3YXJtX2RyeV9kaWZmID0gd2FybV9kcnkgLSBjdXJyX3dldCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCFkYXksIG5hbWVzX3RvID0gImNvbmRpdGlvbiIsIHZhbHVlc190byA9ICJob3VycyIpICU+JQogIGRwbHlyOjpmaWx0ZXIoY29uZGl0aW9uID09IGMoImN1cnJfZHJ5X2RpZmYiLCAid2FybV93ZXRfZGlmZiIsICJ3YXJtX2RyeV9kaWZmIikpICU+JQogIGRwbHlyOjptdXRhdGUoY29uZGl0aW9uID0gZmFjdG9yKGNvbmRpdGlvbiwgbGV2ZWxzID0gYygid2FybV9kcnlfZGlmZiIsICJ3YXJtX3dldF9kaWZmIiwgImN1cnJfZHJ5X2RpZmYiKSkpICU+JQogIGdncGxvdChhZXMoeCA9IGRheSwgeSA9IGNvbmRpdGlvbiwgZmlsbCA9IGhvdXJzKSkgKyAKICBnZW9tX3RpbGUoKSArCiAgc2NhbGVfZmlsbF9jb250aW51b3VzX2RpdmVyZ2luZyhwYWxldHRlID0gIkJsdWUtUmVkIDMiLCBtaWQgPSAwLCByZXYgPSBUUlVFLCBsaW1pdHMgPSBjKC0xNSwgMTUpKSArCiAgeWxhYihOVUxMKSArIHhsYWIoIkRheSBvZiB0aGUgeWVhciIpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAzNjUsIDUwKSwgZXhwYW5kID0gYygwLCAwKSkgKyAKICBteXRoZW1lKCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3VyYmFyKGJhcmhlaWdodCA9IDAuNSwgYmFyd2lkdGggPSA1LCBsYWJlbC5wb3NpdGlvbiA9ICJib3R0b20iKSkgCgpzYV9jb21iX3Bsb3QgPC0gY293cGxvdDo6cGxvdF9ncmlkKHNhX3Bsb3QsIAogICAgICAgICAgICAgICAgICAgc2FfZGlmZl9wbG90ICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAzNjUsIDEwMCksIGV4cGFuZCA9IGMoMCwgMCkpLCAKICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLCBhbGlnbiA9ICd2JywgIHJlbF9oZWlnaHRzID0gYygwLjcsIDEpKQoKc3BfZGlmZl9wbG90IDwtIGN1cnJfd2V0X3NwX2RmICU+JQogIG1lcmdlKGN1cnJfZHJ5X3NwX2RmLCBieSA9ICJkYXkiKSAlPiUKICBtZXJnZSh3YXJtX3dldF9zcF9kZiwgYnkgPSAiZGF5IikgJT4lCiAgbWVyZ2Uod2FybV9kcnlfc3BfZGYsIGJ5ID0gImRheSIpICU+JQogIGRwbHlyOjptdXRhdGUoY3Vycl9kcnlfZGlmZiA9IGN1cnJfZHJ5IC0gY3Vycl93ZXQsCiAgICAgICAgICAgICAgICB3YXJtX3dldF9kaWZmID0gd2FybV93ZXQgLSBjdXJyX3dldCwKICAgICAgICAgICAgICAgIHdhcm1fZHJ5X2RpZmYgPSB3YXJtX2RyeSAtIGN1cnJfd2V0KSAlPiUKICBwaXZvdF9sb25nZXIoIWRheSwgbmFtZXNfdG8gPSAiY29uZGl0aW9uIiwgdmFsdWVzX3RvID0gImhvdXJzIikgJT4lCiAgZHBseXI6OmZpbHRlcihjb25kaXRpb24gPT0gYygiY3Vycl9kcnlfZGlmZiIsICJ3YXJtX3dldF9kaWZmIiwgIndhcm1fZHJ5X2RpZmYiKSkgJT4lCiAgZHBseXI6Om11dGF0ZShjb25kaXRpb24gPSBmYWN0b3IoY29uZGl0aW9uLCBsZXZlbHMgPSBjKCJ3YXJtX2RyeV9kaWZmIiwgIndhcm1fd2V0X2RpZmYiLCAiY3Vycl9kcnlfZGlmZiIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5LCB5ID0gY29uZGl0aW9uLCBmaWxsID0gaG91cnMpKSArIAogIGdlb21fdGlsZSgpICsKICBzY2FsZV9maWxsX2NvbnRpbnVvdXNfZGl2ZXJnaW5nKHBhbGV0dGUgPSAiQmx1ZS1SZWQgMyIsIG1pZCA9IDAsIHJldiA9IFRSVUUsIGxpbWl0cyA9IGMoLTE1LCAxNSkpICsKICB5bGFiKE5VTEwpICsgeGxhYigiRGF5IG9mIHRoZSB5ZWFyIikgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM2NSwgNTApLCBleHBhbmQgPSBjKDAsIDApKSArIAogIG15dGhlbWUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9jb2xvdXJiYXIoYmFyaGVpZ2h0ID0gMC41LCBiYXJ3aWR0aCA9IDUsIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpKSAKCnNwX2NvbWJfcGxvdCA8LSBjb3dwbG90OjpwbG90X2dyaWQoc3BfcGxvdCwgCiAgICAgICAgICAgICAgICAgICBzcF9kaWZmX3Bsb3QgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM2NSwgMTAwKSwgZXhwYW5kID0gYygwLCAwKSksIAogICAgICAgICAgICAgICAgICAgbmNvbCA9IDEsIGFsaWduID0gJ3YnLCAgcmVsX2hlaWdodHMgPSBjKDAuNywgMSkpCgojIE1hcAogZ2dwbG90KCkgKwogICBnZW9tX3Jhc3RlcihkYXRhID0gUERTSV9yaXNrX2RmICU+JSBkcGx5cjo6c2VsZWN0KHgsIHksIGNvdW50XzRDKSAlPiUgbmEub21pdCgpLCBhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gIiM5ZTNlM2UiKSwgYWxwaGEgPSAwLjQpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gUERTSV9yaXNrX2RmICU+JSBkcGx5cjo6c2VsZWN0KHgsIHksIGNvdW50XzJDKSAlPiUgbmEub21pdCgpLCBhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gIiM5ZTNlM2UiKSwgYWxwaGEgPSAwLjYpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkX3JvYiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgY29sb3VyID0gIiM2NDY4NmIiLCBmaWxsID0gTkEsIHNpemUgPSAwLjEpICsKICB0aGVtZV92b2lkKCkgKyB5bGFiKE5VTEwpICsgeGxhYihOVUxMKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTYxZTUsIDg1ZTUpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE1ZTYsIDE2ZTYpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICMgZml4ZWQgcmF0aW8KYGBgCgoqKioKCiMgRXh0ZW5kZWQgZGF0YSB7LX0KCiMjIEV4dGVuZGVkIEZpZ3VyZSAxIC0gUERTSSBpbnRlbnNpdHkgcmlzayB7LX0KCmBgYHtyIEZpZyBFMSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD05fQpQRFNJXzJDX2RpZmZfcmFzdF9jcm9wIDwtIHJhc3Rlcjo6bWFzayhjcm9wKFBEU0lfMkNfZGlmZl9yYXN0LCBleHRlbnQod29ybGQpKSwgd29ybGQpICMgY3JvcCAKUERTSV8yQ19yb2IgPC0gcmFzdGVyOjpwcm9qZWN0UmFzdGVyKHJhc3Rlcjo6c3RhY2soUERTSV8yQ19kaWZmX3Jhc3RfY3JvcCwgcmVzYW1wbGUoYW51cmFuX3NyLCBQRFNJXzJDX2RpZmZfcmFzdF9jcm9wKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgIGNycyA9IHJvYl9wcm9qKQoKUERTSV80Q19kaWZmX3Jhc3RfY3JvcCA8LSByYXN0ZXI6Om1hc2soY3JvcChQRFNJXzRDX2RpZmZfcmFzdCwgZXh0ZW50KHdvcmxkKSksIHdvcmxkKSAjIGNyb3AgClBEU0lfNENfcm9iIDwtIHJhc3Rlcjo6cHJvamVjdFJhc3RlcihyYXN0ZXI6OnN0YWNrKFBEU0lfNENfZGlmZl9yYXN0X2Nyb3AsIHJlc2FtcGxlKGFudXJhbl9zciwgUERTSV80Q19kaWZmX3Jhc3RfY3JvcCkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBjcnMgPSByb2JfcHJvaikKClBEU0lfMkNfZGZfcm9iIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKFBEU0lfMkNfcm9iKSkgJT4lCiAgZHBseXI6OnJlbmFtZShsYXllciA9IGRlbHRhX2ludF8yQywKICAgICAgICAgICAgICAgIHNwZWNpZXNfbiA9IGxheWVyKSAlPiUgCiAgZHBseXI6Om11dGF0ZShjaGFuZ2UgPSBjYXNlX3doZW4oCiAgICBsYXllciA+PSA0IH4gIjQiLCAKICAgIGxheWVyID49IDMgJiBsYXllciA8IDQgfiAnMycsCiAgICBsYXllciA+PSAyICYgbGF5ZXIgPCAzIH4gJzInLCAgCiAgICBsYXllciA+PSAxICYgbGF5ZXIgPCAyIH4gJzEnLCAgCiAgICBsYXllciA+PSAtMSAmIGxheWVyIDwgMSB+ICcwJywKICAgIGxheWVyID49IC0yICYgbGF5ZXIgPCAtMSB+ICctMScsCiAgICBsYXllciA+PSAtMyAmIGxheWVyIDwgLTIgfiAnLTInLAogICAgbGF5ZXIgPj0gLTQgJiBsYXllciA8IC0zIH4gJy0zJywgICAKICAgIGxheWVyIDwgLTQgfiAnLTQnIAogICkpICU+JSAKICBkcGx5cjo6bXV0YXRlKGNoYW5nZSA9IGZhY3RvcihjaGFuZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnLTQnLCAnLTMnLCAnLTInLCAnLTEnLCAnMCcsICcxJywgJzInLCAnMycsICc0JyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKSAlPiUKICBkcGx5cjo6ZmlsdGVyKGNoYW5nZSAhPSAiTkEiICYgc3BlY2llc19uICE9ICJOQSIpCgpQRFNJXzRDX2RmX3JvYiA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhQRFNJXzRDX3JvYikpICU+JQogIGRwbHlyOjpyZW5hbWUobGF5ZXIgPSBkZWx0YV9pbnRfNEMsCiAgICAgICAgICAgICAgICBzcGVjaWVzX24gPSBsYXllcikgJT4lIAogIGRwbHlyOjptdXRhdGUoY2hhbmdlID0gY2FzZV93aGVuKAogICAgbGF5ZXIgPj0gNCB+ICI0IiwgCiAgICBsYXllciA+PSAzICYgbGF5ZXIgPCA0IH4gJzMnLAogICAgbGF5ZXIgPj0gMiAmIGxheWVyIDwgMyB+ICcyJywgIAogICAgbGF5ZXIgPj0gMSAmIGxheWVyIDwgMiB+ICcxJywgIAogICAgbGF5ZXIgPj0gLTEgJiBsYXllciA8IDEgfiAnMCcsCiAgICBsYXllciA+PSAtMiAmIGxheWVyIDwgLTEgfiAnLTEnLAogICAgbGF5ZXIgPj0gLTMgJiBsYXllciA8IC0yIH4gJy0yJywKICAgIGxheWVyID49IC00ICYgbGF5ZXIgPCAtMyB+ICctMycsICAgCiAgICBsYXllciA8IC00IH4gJy00JyAKICApKSAlPiUgCiAgZHBseXI6Om11dGF0ZShjaGFuZ2UgPSBmYWN0b3IoY2hhbmdlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoJy00JywgJy0zJywgJy0yJywgJy0xJywgJzAnLCAnMScsICcyJywgJzMnLCAnNCcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgZHBseXI6OmZpbHRlcihjaGFuZ2UgIT0gIk5BIiAmIHNwZWNpZXNfbiAhPSAiTkEiKQoKIyBJbnRlbnNpdHkgKzJDIC0gRXggRmlnLiAxYQpjb2xvdXJzX1BEU0kgPC0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDksICJSZEJ1IikKUERTSV8yQ19wbG90IDwtIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gUERTSV8yQ19kZl9yb2IsIGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBjaGFuZ2UpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9yb2IsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3Vyc19QRFNJKSArCiAgZ2duZXdzY2FsZTo6bmV3X3NjYWxlKCJmaWxsIikgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBoaWxsX2RmICU+JSBmaWx0ZXIoaGlsbCA8PSAwLjY0NSksIGFlcyhsb24sIGxhdCwgZmlsbCA9IGhpbGwsIGFscGhhID0gaGlsbCksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAiZ3JleSIpICsKICBzY2FsZV9hbHBoYV9jb250aW51b3VzKHRyYW5zID0gInJldmVyc2UiKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIGdndGl0bGUoZXhwcmVzc2lvbihEZWx0YSoiUERTSSBpbnRlbnNpdHkgKCsywrBDKSIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTYxZTUsIDg1ZTUpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE1ZTYsIDE2ZTYpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICMgZml4ZWQgcmF0aW8KCiMgSW50ZW5zaXR5ICs0QyAtIEV4IEZpZy4gMWMKUERTSV80Q19wbG90IDwtIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gUERTSV80Q19kZl9yb2IsIGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBjaGFuZ2UpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9yb2IsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3Vyc19QRFNJKSArCiAgZ2duZXdzY2FsZTo6bmV3X3NjYWxlKCJmaWxsIikgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBoaWxsX2RmICU+JSBmaWx0ZXIoaGlsbCA8PSAwLjY0NSksIGFlcyhsb24sIGxhdCwgZmlsbCA9IGhpbGwsIGFscGhhID0gaGlsbCksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAiZ3JleSIpICsKICBzY2FsZV9hbHBoYV9jb250aW51b3VzKHRyYW5zID0gInJldmVyc2UiKSArCiAgdGhlbWVfdm9pZCgpICsgeWxhYihOVUxMKSArIHhsYWIoTlVMTCkgKwogIGdndGl0bGUoZXhwcmVzc2lvbihEZWx0YSoiUERTSSBpbnRlbnNpdHkgKCs0wrBDKSIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTYxZTUsIDg1ZTUpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE1ZTYsIDE2ZTYpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICMgZml4ZWQgcmF0aW8KCiMgMkMgY2hhbmdlIC0gRXggRmlnIDFiClBEU0lfc3BfMkNfcGxvdCA8LSBQRFNJX3NwXzJDICU+JQogIHJvd3NfaW5zZXJ0KHRpYmJsZShjaGFuZ2VfMkMgPSAiNCIsIGFsbF9mcmVxID0gMCksIGNvbmZsaWN0ID0gImlnbm9yZSIpICU+JQogIGZpbHRlcihjaGFuZ2VfMkMgIT0gIk5BIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gY2hhbmdlXzJDLCB5ID0gYWxsX2ZyZXEsIGZpbGwgPSBjaGFuZ2VfMkMpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvdXJzX1BEU0kpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoYWxsX2ZyZXEsIDEpKSwgdmp1c3QgPSAtMSwgc2l6ZSA9IDIpICsKICB5bGFiKCIlIHNwZWNpZXMiKSArIHhsYWIoIlBEU0kiKSArCiAgeWxpbSgwLCA4MCkgKwogIGdndGl0bGUoIkdyaWQgY2VsbCBvY2N1cGllZCArMsKwQyIpICsKICBteXRoZW1lKCkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCgojIDRDIGNoYW5nZSAtIEV4IEZpZyAxZApQRFNJX3NwXzRDX3Bsb3QgPC0gUERTSV9zcF80QyAlPiUKICBmaWx0ZXIoY2hhbmdlXzRDICE9ICJOQSIpICU+JQogIGdncGxvdChhZXMoeCA9IGNoYW5nZV80QywgeSA9IGFsbF9mcmVxLCBmaWxsID0gY2hhbmdlXzRDKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3Vyc19QRFNJKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKGFsbF9mcmVxLCAxKSksIHZqdXN0ID0gLTEsIHNpemUgPSAyKSArCiAgeWxhYigiJSBzcGVjaWVzIikgKyB4bGFiKCJQRFNJIikgKwogIHlsaW0oMCwgODApICsKICBnZ3RpdGxlKCJHcmlkIGNlbGwgb2NjdXBpZWQgKzTCsEMiKSArCiAgbXl0aGVtZSgpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQoKbGVmdF9wbG90IDwtIGNvd3Bsb3Q6OnBsb3RfZ3JpZCgKICBQRFNJXzJDX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLAogIFBEU0lfNENfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksCiAgbmNvbCA9IDEsCiAgYWxpZ24gPSAiaCIsIGF4aXMgPSAiYnQiLCBsYWJlbHMgPSBjKCdhJywgJ2MnLCAnZScpKQoKcmlnaHRfcGxvdCA8LSBjb3dwbG90OjpwbG90X2dyaWQoCiAgUERTSV9zcF8yQ19wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwKICBQRFNJX3NwXzRDX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLAogIG5jb2wgPSAxLAogIGFsaWduID0gImgiLCBheGlzID0gImJ0IiwgbGFiZWxzID0gYygnYicsICdkJywgJ2YnKSkKCmNvd3Bsb3Q6OnBsb3RfZ3JpZChsZWZ0X3Bsb3QsIHJpZ2h0X3Bsb3QsIG5jb2wgPSAyLCByZWxfd2lkdGhzID0gYygxLCAwLjcpKQpgYGAKCiMjIEV4dGVuZGVkIEZpZ3VyZSAyIC0gUERTSSBmcmVxdWVuY3kgcmlzayB7LX0KCmBgYHtyIEZpZyBFMiwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD05fQpmcmVxX2RpZmZfcmFzdF9jcm9wIDwtIHJhc3Rlcjo6bWFzayhjcm9wKGZyZXFfZGlmZl9yYXN0LCBleHRlbnQod29ybGQpKSwgd29ybGQpICMgY3JvcAoKUERTSV9mcmVxX3JvYiA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhmcmVxX2RpZmZfcmFzdF9jcm9wLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2FtcGxlKGFudXJhbl9zciwgZnJlcV9kaWZmX3Jhc3RfY3JvcCkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcnMgPSByb2JfcHJvaikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKUERTSV9mcmVxXzJDX2RmIDwtIHJhc3Rlcjo6YXMuZGF0YS5mcmFtZShyYXN0ZXI6OnJhc3RlclRvUG9pbnRzKFBEU0lfZnJlcV9yb2IpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRpZmZfMkNfY2F0ID0gY2FzZV93aGVuKAogICAgZGlmZl8yQyA+PSAxMCB+ICIxMC0xMiIsIAogICAgZGlmZl8yQyA+PSA4ICYgZGlmZl8yQyA8IDEwIH4gJzgtMTAnLAogICAgZGlmZl8yQyA+PSA2ICYgZGlmZl8yQyA8IDggfiAnNi04JywgIAogICAgZGlmZl8yQyA+PSA0ICYgZGlmZl8yQyA8IDYgfiAnNC02JywgIAogICAgZGlmZl8yQyA+PSAyICYgZGlmZl8yQyA8IDQgfiAnMi00JywKICAgIGRpZmZfMkMgPj0gMSAmIGRpZmZfMkMgPCAyIH4gJzEtMicsCiAgICBkaWZmXzJDID4gMCAmIGRpZmZfMkMgPCAxIH4gJzAtMScsCiAgICBkaWZmXzJDID49IC0xICYgZGlmZl8yQyA8IDAgfiAnLTAtMScsCiAgICBkaWZmXzJDID49IC0yICYgZGlmZl8yQyA8IC0xIH4gJy0xLTInLAogICAgZGlmZl8yQyA+PSAtNCAmIGRpZmZfMkMgPCAtMiB+ICctMi00JwogICkpICU+JSAKICBkcGx5cjo6bXV0YXRlKGRpZmZfMkNfY2F0ID0gZmFjdG9yKGRpZmZfMkNfY2F0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnMTAtMTInLCAnOC0xMCcsICc2LTgnLCAnNC02JywgJzItNCcsICcxLTInLCAnMC0xJywnLTAtMScsICctMS0yJywgJy0yLTQnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkpICU+JQogIGRwbHlyOjpmaWx0ZXIoZGlmZl8yQ19jYXQgIT0gIk5BIiAmIGxheWVyICE9ICJOQSIpCgpQRFNJX2ZyZXFfNENfZGYgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMoUERTSV9mcmVxX3JvYikpICU+JQogIGRwbHlyOjptdXRhdGUoZGlmZl80Q19jYXQgPSBjYXNlX3doZW4oCiAgICBkaWZmXzRDID49IDEwIH4gIjEwLTEyIiwgCiAgICBkaWZmXzRDID49IDggJiBkaWZmXzRDIDwgMTAgfiAnOC0xMCcsCiAgICBkaWZmXzRDID49IDYgJiBkaWZmXzRDIDwgOCB+ICc2LTgnLCAgCiAgICBkaWZmXzRDID49IDQgJiBkaWZmXzRDIDwgNiB+ICc0LTYnLCAgCiAgICBkaWZmXzRDID49IDIgJiBkaWZmXzRDIDwgNCB+ICcyLTQnLAogICAgZGlmZl80QyA+PSAxICYgZGlmZl80QyA8IDIgfiAnMS0yJywKICAgIGRpZmZfNEMgPiAwICYgZGlmZl80QyA8IDEgfiAnMC0xJywKICAgIGRpZmZfNEMgPj0gLTEgJiBkaWZmXzRDIDwgMCB+ICctMC0xJywKICAgIGRpZmZfNEMgPj0gLTIgJiBkaWZmXzRDIDwgLTEgfiAnLTEtMicsCiAgICBkaWZmXzRDID49IC00ICYgZGlmZl80QyA8IC0yIH4gJy0yLTQnCiAgKSkgJT4lIAogIGRwbHlyOjptdXRhdGUoZGlmZl80Q19jYXQgPSBmYWN0b3IoZGlmZl80Q19jYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCcxMC0xMicsICc4LTEwJywgJzYtOCcsICc0LTYnLCAnMi00JywgJzEtMicsICcwLTEnLCAnLTAtMScsICctMS0yJywgJy0yLTQnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgZHBseXI6OmZpbHRlcihkaWZmXzRDX2NhdCAhPSAiTkEiICYgbGF5ZXIgIT0gIk5BIikKCiMgRnJlcSBtYXAgMkMgLSBGaWcgUzEwYQpmcmVxXzJDX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBQRFNJX2ZyZXFfMkNfZGYsIGFlcyh5ID0geSwgeCA9IHgsIGZpbGwgPSBkaWZmXzJDX2NhdCkpICsKICBnZW9tX3BvbHlnb24oZGF0YSA9IHdvcmxkX3JvYiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgY29sb3VyID0gIiM2NDY4NmIiLCBmaWxsID0gTkEsIHNpemUgPSAwLjEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjNjcwMDFGIiwgIiNCMjE4MkIiLCAiI0Q2NjA0RCIsICIjRjRBNTgyIiwgIiNGRERCQzciLCAiI0ZBRTlERiIsICIjRjdGN0Y3IiwgIiNkZmViZjIiKSkgKwogIGdnbmV3c2NhbGU6Om5ld19zY2FsZSgiZmlsbCIpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gaGlsbF9kZiAlPiUgZmlsdGVyKGhpbGwgPD0gMC42NDUpLCBhZXMobG9uLCBsYXQsIGZpbGwgPSBoaWxsLCBhbHBoYSA9IGhpbGwpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gImdyZXkiKSArCiAgc2NhbGVfYWxwaGFfY29udGludW91cyh0cmFucyA9ICJyZXZlcnNlIikgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICBnZ3RpdGxlKGV4cHJlc3Npb24oIkNoYW5nZSBpbiBkcm91Z2h0IGZyZXF1ZW5jeSAoIipEZWx0YSoiUERTSSArMsKwQykiKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MWU1LCA4NWU1KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xNWU2LCAxNmU2KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAjIGZpeGVkIHJhdGlvCgojIEZyZXEgbWFwIDRDIC0gRmlnIFMxMGMKZnJlcV80Q19wbG90IDwtIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gUERTSV9mcmVxXzRDX2RmLCBhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gZGlmZl80Q19jYXQpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9yb2IsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzY3MDAxRiIsICIjQjIxODJCIiwgIiNENjYwNEQiLCAiI0Y0QTU4MiIsICIjRkREQkM3IiwgIiNGQUU5REYiLCAiI0Y3RjdGNyIsICIjZGZlYmYyIikpICsKICBnZ25ld3NjYWxlOjpuZXdfc2NhbGUoImZpbGwiKSArCiAgZ2VvbV9yYXN0ZXIoZGF0YSA9IGhpbGxfZGYgJT4lIGZpbHRlcihoaWxsIDw9IDAuNjQ1KSwgYWVzKGxvbiwgbGF0LCBmaWxsID0gaGlsbCwgYWxwaGEgPSBoaWxsKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJncmV5IikgKwogIHNjYWxlX2FscGhhX2NvbnRpbnVvdXModHJhbnMgPSAicmV2ZXJzZSIpICsKICB0aGVtZV92b2lkKCkgKyB5bGFiKE5VTEwpICsgeGxhYihOVUxMKSArCiAgZ2d0aXRsZShleHByZXNzaW9uKCJDaGFuZ2UgaW4gZHJvdWdodCBmcmVxdWVuY3kgKCIqRGVsdGEqIlBEU0kgKzTCsEMpIikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNjFlNSwgODVlNSksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTVlNiwgMTZlNiksIGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkgIyBmaXhlZCByYXRpbwoKIyAyQyBjaGFuZ2UgLSBGaWcgUzEwYgpmcmVxX3NwXzJDIDwtIGRhdGEuZnJhbWUoUERTSV9mcmVxXzJDX2RmICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6Omdyb3VwX2J5KGRpZmZfMkNfY2F0KSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpzdW1tYXJpc2Uoc3BlY2llc19uID0gbGVuZ3RoKGxheWVyWyFpcy5uYShsYXllcildKSkpICU+JQogIGRwbHlyOjptdXRhdGUoYWxsX2ZyZXEgID0gc3BlY2llc19uIC8gc3VtKHNwZWNpZXNfbikgKiAxMDApCgpmcmVxX3NwXzJDX3Bsb3QgPC0gZnJlcV9zcF8yQyAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkaWZmXzJDX2NhdCwgeSA9IGFsbF9mcmVxLCBmaWxsID0gZGlmZl8yQ19jYXQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjNjcwMDFGIiwgIiNCMjE4MkIiLCAiI0Q2NjA0RCIsICIjRjRBNTgyIiwgIiNGRERCQzciLCAiI0ZBRTlERiIsICIjRjdGN0Y3IiwgIiNkZmViZjIiKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChhbGxfZnJlcSwgMSkpLCB2anVzdCA9IC0xLCBzaXplID0gMikgKwogIHlsYWIoIiUgc3BlY2llcyIpICsgeGxhYigiTW9udGhzIikgKwogIHlsaW0oMCwgNjApICsKICBnZ3RpdGxlKCJHcmlkIGNlbGwgb2NjdXBpZWQgKzLCsEMiKSArCiAgbXl0aGVtZSgpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQoKIyA0QyBjaGFuZ2UgLSBGaWcgUzEwZApmcmVxX3NwXzRDIDwtIGRhdGEuZnJhbWUoUERTSV9mcmVxXzRDX2RmICU+JSBkcGx5cjo6Z3JvdXBfYnkoZGlmZl80Q19jYXQpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c3VtbWFyaXNlKHNwZWNpZXNfbiA9IGxlbmd0aChsYXllclshaXMubmEobGF5ZXIpXSkpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGFsbF9mcmVxICA9IHNwZWNpZXNfbiAvIHN1bShzcGVjaWVzX24pICogMTAwKQoKZnJlcV9zcF80Q19wbG90IDwtIGZyZXFfc3BfNEMgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGlmZl80Q19jYXQsIHkgPSBhbGxfZnJlcSwgZmlsbCA9IGRpZmZfNENfY2F0KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzY3MDAxRiIsICIjQjIxODJCIiwgIiNENjYwNEQiLCAiI0Y0QTU4MiIsICIjRkREQkM3IiwgIiNGQUU5REYiLCAiI0Y3RjdGNyIsICIjZGZlYmYyIikpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoYWxsX2ZyZXEsIDEpKSwgdmp1c3QgPSAtMSwgc2l6ZSA9IDIpICsKICB5bGFiKCIlIHNwZWNpZXMiKSArIHhsYWIoIk1vbnRocyIpICsKICB5bGltKDAsIDYwKSArCiAgZ2d0aXRsZSgiR3JpZCBjZWxsIG9jY3VwaWVkICs0wrBDIikgKwogIG15dGhlbWUoKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKCmxlZnRfcGxvdDIgPC0gY293cGxvdDo6cGxvdF9ncmlkKAogIGZyZXFfMkNfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksCiAgZnJlcV80Q19wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwKICBuY29sID0gMSwKICBhbGlnbiA9ICJoIiwgYXhpcyA9ICJidCIsIGxhYmVscyA9IGMoJ2EnLCAnYycpKQoKcmlnaHRfcGxvdDIgPC0gY293cGxvdDo6cGxvdF9ncmlkKAogIGZyZXFfc3BfMkNfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksCiAgZnJlcV9zcF80Q19wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwKICBuY29sID0gMSwKICBhbGlnbiA9ICJoIiwgYXhpcyA9ICJidCIsIGxhYmVscyA9IGMoJ2InLCAnZCcpKQoKY293cGxvdDo6cGxvdF9ncmlkKGxlZnRfcGxvdDIsIHJpZ2h0X3Bsb3QyLCBuY29sID0gMiwgcmVsX3dpZHRocyA9IGMoMSwgMC43KSkKYGBgCgojIyBFeHRlbmRlZCBGaWd1cmUgMyAtIFBEU0kgZHVyYXRpb24gcmlzayB7LX0KCmBgYHtyIEZpZyBFMywgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD05fQpQRFNJX2R1cl9kaWZmX2Nyb3AgPC0gcmFzdGVyOjptYXNrKGNyb3AoUERTSV9kdXJfZGlmZiwgZXh0ZW50KHdvcmxkKSksIHdvcmxkKSAjIGNyb3AKClBEU0lfZHVyX3JvYiA8LSByYXN0ZXI6OnByb2plY3RSYXN0ZXIocmFzdGVyOjpzdGFjayhQRFNJX2R1cl9kaWZmX2Nyb3AsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzYW1wbGUoYW51cmFuX3NyLCBQRFNJX2R1cl9kaWZmX2Nyb3ApKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JzID0gcm9iX3Byb2opCgpQRFNJX2R1cl8yQ19kZiA8LSByYXN0ZXI6OmFzLmRhdGEuZnJhbWUocmFzdGVyOjpyYXN0ZXJUb1BvaW50cyhQRFNJX2R1cl9yb2IpKSAlPiUKICBkcGx5cjo6cmVuYW1lKCJzcF9uIiA9IGxheWVyKSAlPiUKICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShzcF9uKSkgJT4lCiAgZHBseXI6Om11dGF0ZShkaWZmXzJDX2NhdCA9IGNhc2Vfd2hlbigKICAgIGRlbHRhX2R1cl8yQyA+PSAxMCB+ICI+MTAiLCAKICAgIGRlbHRhX2R1cl8yQyA+PSA4ICYgZGVsdGFfZHVyXzJDIDwgMTAgfiAnOC0xMCcsCiAgICBkZWx0YV9kdXJfMkMgPj0gNiAmIGRlbHRhX2R1cl8yQyA8IDggfiAnNi04JywgIAogICAgZGVsdGFfZHVyXzJDID49IDQgJiBkZWx0YV9kdXJfMkMgPCA2IH4gJzQtNicsICAKICAgIGRlbHRhX2R1cl8yQyA+PSAyICYgZGVsdGFfZHVyXzJDIDwgNCB+ICcyLTQnLAogICAgZGVsdGFfZHVyXzJDID49IDEgJiBkZWx0YV9kdXJfMkMgPCAyIH4gJzEtMicsCiAgICBkZWx0YV9kdXJfMkMgPiAwICYgZGVsdGFfZHVyXzJDIDwgMSB+ICcwLTEnLAogICAgZGVsdGFfZHVyXzJDID49IC0xICYgZGVsdGFfZHVyXzJDIDwgMCB+ICctMC0xJywKICAgIGRlbHRhX2R1cl8yQyA+PSAtMiAmIGRlbHRhX2R1cl8yQyA8IC0xIH4gJy0xLTInLAogICAgZGVsdGFfZHVyXzJDID49IC00ICYgZGVsdGFfZHVyXzJDIDwgLTIgfiAnLTItNCcsCiAgICBkZWx0YV9kdXJfMkMgPj0gLTggJiBkZWx0YV9kdXJfMkMgPCAtNiB+ICctNi04JywKICAgIGRlbHRhX2R1cl8yQyA+PSAtMTAgJiBkZWx0YV9kdXJfMkMgPCAtOCB+ICctOC0xMCcsICAgCiAgICBkZWx0YV9kdXJfMkMgPCAtMTAgfiAnPC0xMCcgCiAgKSkgJT4lIAogIGRwbHlyOjptdXRhdGUoZGlmZl8yQ19jYXQgPSBmYWN0b3IoZGlmZl8yQ19jYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnPjEwJywgJzgtMTAnLCAnNi04JywgJzQtNicsICcyLTQnLCAnMS0yJywgIjAtMSIsICctMC0xJywgJy0xLTInLCAnLTItNCcsICctNC02JywgJy02LTgnLCAnLTgtMTAnLCAnPC0xMCcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgZHBseXI6OmZpbHRlcihkaWZmXzJDX2NhdCAhPSAiTkEiKQoKUERTSV9kdXJfNENfZGYgPC0gcmFzdGVyOjphcy5kYXRhLmZyYW1lKHJhc3Rlcjo6cmFzdGVyVG9Qb2ludHMoUERTSV9kdXJfcm9iKSkgJT4lCiAgZHBseXI6OnJlbmFtZSgic3BfbiIgPSBsYXllcikgJT4lCiAgZHBseXI6OmZpbHRlcighaXMubmEoc3BfbikpICU+JQogIGRwbHlyOjptdXRhdGUoZGlmZl80Q19jYXQgPSBjYXNlX3doZW4oCiAgICBkZWx0YV9kdXJfNEMgPj0gMTAgfiAiPjEwIiwgCiAgICBkZWx0YV9kdXJfNEMgPj0gOCAmIGRlbHRhX2R1cl80QyA8IDEwIH4gJzgtMTAnLAogICAgZGVsdGFfZHVyXzRDID49IDYgJiBkZWx0YV9kdXJfNEMgPCA4IH4gJzYtOCcsICAKICAgIGRlbHRhX2R1cl80QyA+PSA0ICYgZGVsdGFfZHVyXzRDIDwgNiB+ICc0LTYnLCAgCiAgICBkZWx0YV9kdXJfNEMgPj0gMiAmIGRlbHRhX2R1cl80QyA8IDQgfiAnMi00JywKICAgIGRlbHRhX2R1cl80QyA+PSAxICYgZGVsdGFfZHVyXzRDIDwgMiB+ICcxLTInLAogICAgZGVsdGFfZHVyXzRDID4gMCAmIGRlbHRhX2R1cl80QyA8IDEgfiAnMC0xJywKICAgIGRlbHRhX2R1cl80QyA+PSAtMSAmIGRlbHRhX2R1cl80QyA8IDAgfiAnLTAtMScsCiAgICBkZWx0YV9kdXJfNEMgPj0gLTIgJiBkZWx0YV9kdXJfNEMgPCAtMSB+ICctMS0yJywKICAgIGRlbHRhX2R1cl80QyA+PSAtNCAmIGRlbHRhX2R1cl80QyA8IC0yIH4gJy0yLTQnLAogICAgZGVsdGFfZHVyXzRDID49IC02ICYgZGVsdGFfZHVyXzRDIDwgLTQgfiAnLTQtNicsCiAgICBkZWx0YV9kdXJfNEMgPj0gLTggJiBkZWx0YV9kdXJfNEMgPCAtNiB+ICctNi04JywKICAgIGRlbHRhX2R1cl80QyA+PSAtMTAgJiBkZWx0YV9kdXJfNEMgPCAtOCB+ICctOC0xMCcsICAgCiAgICBkZWx0YV9kdXJfNEMgPCAtMTAgfiAnPC0xMCcgCiAgKSkgJT4lIAogIGRwbHlyOjptdXRhdGUoZGlmZl80Q19jYXQgPSBmYWN0b3IoZGlmZl80Q19jYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygnPjEwJywgJzgtMTAnLCAnNi04JywgJzQtNicsICcyLTQnLCAnMS0yJywgIjAtMSIsICctMC0xJywgJy0xLTInLCAnLTItNCcsICctNC02JywgJy02LTgnLCAnLTgtMTAnLCAnPC0xMCcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgZHBseXI6OmZpbHRlcihkaWZmXzRDX2NhdCAhPSAiTkEiKQoKZHVyXzJDX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fcmFzdGVyKGRhdGEgPSBQRFNJX2R1cl8yQ19kZiwgYWVzKHkgPSB5LCB4ID0geCwgZmlsbCA9IGRpZmZfMkNfY2F0KSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGRfcm9iLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiIzY0Njg2YiIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuMSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM2NzAwMUYiLCAiI0IyMTgyQiIsICIjRDY2MDREIiwgIiNGNEE1ODIiLCAiI0ZEREJDNyIsICIjRkFFOURGIiwgIiNGN0Y3RjciLCAiI2RmZWJmMiIsICIjRDFFNUYwIikpICsKICBnZ25ld3NjYWxlOjpuZXdfc2NhbGUoImZpbGwiKSArCiAgZ2VvbV9yYXN0ZXIoZGF0YSA9IGhpbGxfZGYgJT4lIGZpbHRlcihoaWxsIDw9IDAuNjQ1KSwgYWVzKGxvbiwgbGF0LCBmaWxsID0gaGlsbCwgYWxwaGEgPSBoaWxsKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJncmV5IikgKwogIHNjYWxlX2FscGhhX2NvbnRpbnVvdXModHJhbnMgPSAicmV2ZXJzZSIpICsKICB0aGVtZV92b2lkKCkgKyB5bGFiKE5VTEwpICsgeGxhYihOVUxMKSArCiAgZ2d0aXRsZShleHByZXNzaW9uKCJDaGFuZ2UgaW4gZHJvdWdodCBkdXJhdGlvbiAoIipEZWx0YSoiUERTSSArMsKwQykiKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC02MWU1LCA4NWU1KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xNWU2LCAxNmU2KSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSAjIGZpeGVkIHJhdGlvCgpkdXJfNENfcGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoZGF0YSA9IFBEU0lfZHVyXzRDX2RmLCBhZXMoeSA9IHksIHggPSB4LCBmaWxsID0gZGlmZl80Q19jYXQpKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZF9yb2IsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICIjNjQ2ODZiIiwgZmlsbCA9IE5BLCBzaXplID0gMC4xKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzY3MDAxRiIsICIjQjIxODJCIiwgIiNENjYwNEQiLCAiI0Y0QTU4MiIsICIjRkREQkM3IiwgIiNGQUU5REYiLCAiI0Y3RjdGNyIsICIjZGZlYmYyIiwgIiNEMUU1RjAiKSkgKwogIGdnbmV3c2NhbGU6Om5ld19zY2FsZSgiZmlsbCIpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gaGlsbF9kZiAlPiUgZmlsdGVyKGhpbGwgPD0gMC42NDUpLCBhZXMobG9uLCBsYXQsIGZpbGwgPSBoaWxsLCBhbHBoYSA9IGhpbGwpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gImdyZXkiKSArCiAgc2NhbGVfYWxwaGFfY29udGludW91cyh0cmFucyA9ICJyZXZlcnNlIikgKwogIHRoZW1lX3ZvaWQoKSArIHlsYWIoTlVMTCkgKyB4bGFiKE5VTEwpICsKICBnZ3RpdGxlKGV4cHJlc3Npb24oIkNoYW5nZSBpbiBkcm91Z2h0IGR1cmF0aW9uICgiKkRlbHRhKiJQRFNJICs0wrBDKSIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTYxZTUsIDg1ZTUpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE1ZTYsIDE2ZTYpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICMgZml4ZWQgcmF0aW8KCiMgMkMgY2hhbmdlIC0gRmlnIFMxMWIKZHVyX3NwXzJDIDwtIGRhdGEuZnJhbWUoUERTSV9kdXJfMkNfZGYgJT4lIGRwbHlyOjpncm91cF9ieShkaWZmXzJDX2NhdCkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnN1bW1hcmlzZShzcGVjaWVzX24gPSBsZW5ndGgoc3BfblshaXMubmEoc3BfbildKSkpICU+JQogIGRwbHlyOjptdXRhdGUoYWxsX2ZyZXEgID0gc3BlY2llc19uIC8gc3VtKHNwZWNpZXNfbikgKiAxMDApCgpkdXJfc3BfMkNfcGxvdCA8LSBkdXJfc3BfMkMgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGlmZl8yQ19jYXQsIHkgPSBhbGxfZnJlcSwgZmlsbCA9IGRpZmZfMkNfY2F0KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzY3MDAxRiIsICIjQjIxODJCIiwgIiNENjYwNEQiLCAiI0Y0QTU4MiIsICIjRkREQkM3IiwgIiNGQUU5REYiLCAiI0Y3RjdGNyIsICIjZGZlYmYyIiwgIiNEMUU1RjAiKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChhbGxfZnJlcSwgMSkpLCB2anVzdCA9IC0xLCBzaXplID0gMikgKwogIHlsYWIoIiUgc3BlY2llcyIpICsgeGxhYigiTW9udGhzIikgKwogIHlsaW0oMCwgNTApICsKICBnZ3RpdGxlKCJHcmlkIGNlbGwgb2NjdXBpZWQgKzLCsEMiKSArCiAgbXl0aGVtZSgpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQoKIyA0QyBjaGFuZ2UgLSBGaWcgUzExZApkdXJfc3BfNEMgPC0gZGF0YS5mcmFtZShQRFNJX2R1cl80Q19kZiAlPiUgZHBseXI6Omdyb3VwX2J5KGRpZmZfNENfY2F0KSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnN1bW1hcmlzZShzcGVjaWVzX24gPSBsZW5ndGgoc3BfblshaXMubmEoc3BfbildKSkpICU+JQogIGRwbHlyOjptdXRhdGUoYWxsX2ZyZXEgID0gc3BlY2llc19uIC8gc3VtKHNwZWNpZXNfbikgKiAxMDApCgpkdXJfc3BfNENfcGxvdCA8LSBkdXJfc3BfNEMgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGlmZl80Q19jYXQsIHkgPSBhbGxfZnJlcSwgZmlsbCA9IGRpZmZfNENfY2F0KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzY3MDAxRiIsICIjQjIxODJCIiwgIiNENjYwNEQiLCAiI0Y0QTU4MiIsICIjRkREQkM3IiwgIiNGQUU5REYiLCAiI0Y3RjdGNyIsICIjZGZlYmYyIiwgIiNEMUU1RjAiKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChhbGxfZnJlcSwgMSkpLCB2anVzdCA9IC0xLCBzaXplID0gMikgKwogIHlsYWIoIiUgc3BlY2llcyIpICsgeGxhYigiTW9udGhzIikgKwogIHlsaW0oMCwgNTApICsKICBnZ3RpdGxlKCJHcmlkIGNlbGwgb2NjdXBpZWQgKzTCsEMiKSArCiAgbXl0aGVtZSgpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQoKbGVmdF9wbG90MyA8LSBjb3dwbG90OjpwbG90X2dyaWQoCiAgZHVyXzJDX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLAogIGR1cl80Q19wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwKICBuY29sID0gMSwKICBhbGlnbiA9ICJoIiwgYXhpcyA9ICJidCIsIGxhYmVscyA9IGMoJ2EnLCAnYycpKQoKcmlnaHRfcGxvdDMgPC0gY293cGxvdDo6cGxvdF9ncmlkKAogIGR1cl9zcF8yQ19wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwKICBkdXJfc3BfNENfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksCiAgbmNvbCA9IDEsCiAgYWxpZ24gPSAiaCIsIGF4aXMgPSAiYnQiLCBsYWJlbHMgPSBjKCdiJywgJ2QnKSkKCmNvd3Bsb3Q6OnBsb3RfZ3JpZChsZWZ0X3Bsb3QzLCByaWdodF9wbG90MywgbmNvbCA9IDIsIHJlbF93aWR0aHMgPSBjKDEsIDAuNykpCmBgYAoKKioqCgojIFN1cHBvcnRpbmcgZmlndXJlcyB7LX0KCmBgYHtyIGZpZyBTMTEsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9Nn0KdGVtcF9kYXQgPC0gZXdsX2RhdCAlPiUgZHBseXI6OmZpbHRlcighaXMubmEodHJ0X3RlbXApKQoKdGVtcF9kYXQgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdHJ0X3RlbXAsIHkgPSBza2luX3RlbXApKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMC41KSArCiAgZ2dwbWlzYzo6c3RhdF9wb2x5X2xpbmUobWV0aG9kID0gImxtIiwgZm9ybXVsYSA9IHkgfiB4ICsgSSh4XjYpLCBzZSA9IEYsIGNvbG9yID0gImJsYWNrIikgKwogIGdncG1pc2M6OnN0YXRfcG9seV9lcShtZXRob2QgPSAibG0iLCBmb3JtdWxhID0geSB+IHggKyBJKHheNiksIAogICAgICAgICAgICAgICAgICAgICAgICBnZ3BtaXNjOjp1c2VfbGFiZWwoYygiZXEiLCAiUjIiLCAibiIpKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIsIHNoYXBlID0gMjEsIGZpbGwgPSAid2hpdGUiKSArCiAgeWxpbSg1LDUwKSArIHhsaW0oNSw1MCkgKwogIGxhYnMoeCA9ICJBaXIgdGVtcGVyYXR1cmUgKMKwQykiLCB5ID0gIlNraW4gc3VyZmFjZSB0ZW1wZXJhdHVyZSAowrBDKSIpICsKICBteXRoZW1lKCkKYGBgCgoqKkZpZy4gUzExLioqIFJlbGF0aW9uc2hpcCBiZXR3ZWVuIGV4cG9zZWQgYWlyIHRlbXBlcmF0dXJlICjCsEMpIGR1cmluZyB0aGUgZXhwZXJpbWVudCBhbmQgdGhlIG9ic2VydmVkIHNraW4gc3VyZmFjZSB0ZW1wZXJhdHVyZSAowrBDKSBhY3Jvc3MgYHIgbGVuZ3RoKHVuaXF1ZSh0ZW1wX2RhdCRzcGVjaWVzX3BoeWxvKSlgIHNwZWNpZXMuIFRoZSBibGFjayBsaW5lIHJlcHJlc2VudHMgdGhlIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gYWlyIHRlbXBlcmF0dXJlIGFuZCBza2luIHRlbXBlcmF0dXJlIHdoZXJlIHRoZSBza2luIHRlbXBlcmF0dXJlIHJlbWFpbnMgYXQgfjM1wrBDIHdoZW4gZXhwb3NlZCB0byBhaXIgdGVtcGVyYXR1cmVzID4gNDDCsEMuCgpgYGB7ciBmaWcgUzEyLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5oZWlnaHQ9My42LCBmaWcud2lkdGg9Nn0KcmF3X2RhdCAlPiUKICBkcGx5cjo6ZmlsdGVyKHRyYWl0ICE9ICJ3YXRlciBnYWluIiAmICFpcy5uYSh1bml0X2NvcnJlY3RlZF9tZWFuKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdW5pdF9jb3JyZWN0ZWRfbWVhbiwgeSA9IHJfc19lc3QsIGZpbGwgPSBjYWxjdWxhdGVkKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIsIHNoYXBlID0gMjEsIGNvbG91ciA9ICJibGFjayIpICsgCiAgeGxhYihleHByZXNzaW9uKCJFV0wifigibWcifiJIIlsyXSpPfmheeyItMSJ9KSkpICsKICB5bGFiKGV4cHJlc3Npb24oaXRhbGljKCJyIilbImkiXX4iKHMgY20iXnstMX0qIikiKSkgKwogIGxhYnMoZmlsbCA9IGV4cHJlc3Npb24oIkVzdGltYXRlZCJ+aXRhbGljKCJyIilbImkiXSkpICsKICBzY2FsZV94X2xvZzEwKGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngpLAogICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKwogIHNjYWxlX3lfbG9nMTAoYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCksCiAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArCiAgYW5ub3RhdGlvbl9sb2d0aWNrcygpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJ3aGl0ZSIsICJncmV5IikpICsKICBteXRoZW1lKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQpgYGAKCioqRmlnLiBTMTIuKiogUmVsYXRpb25zaGlwIGJldHdlZW4gZXZhcG9yYXRpdmUgd2F0ZXIgbG9zcyAoRVdMOyBtZyBIfjJ+TyBjbV7iiJIyXiBoXuKIkjFeKSBhbmQgcmVzaXN0YW5jZSB0byB3YXRlciBsb3NzICgkcl9pJDsgcyBjbV4tMV4pIG9uIGEgYmFzZS0xMCBsb2dhcml0aG1pYyBzY2FsZS4gTWVhc3VyZWQgJHJfaSQgZnJvbSB0aGUgc3R1ZHkgcHJlc2VudGVkIGFzIHdoaXRlIGZpbGxlZCBwb2ludHMsIGFuZCB0aGUgZXN0aW1hdGVkICRyX2kkIGZyb20gRVdMIGluIGdyZXkgZmlsbGVkIHBvaW50cy4KCmBgYHtyIEZpZyBzMTMsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9OH0KRVdMX3NwX2xvbmcgPC0gRVdMX3NwX2RmICU+JSAKICBkcGx5cjo6c2VsZWN0KC1zcGVjaWVzX24pICU+JQogIHRpZHlyOjpwaXZvdF9sb25nZXIoIWMoeCwgeSwgRVdMKSwgbmFtZXNfdG8gPSAiZWNvdHlwZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JQogIGRwbHlyOjptdXRhdGUoZWNvdHlwZSA9IGZhY3RvcihlY290eXBlLCBsZXZlbHMgPSBjKCJmb3NzX3NwIiwgImdyb25fc3AiLCAiYXF1YV9zcCIsICJhcmJvX3NwIiwgInNlbWlfc3AiLCAic3RybV9zcCIpKSkKCmVjb3R5cGVfbGFicyA8LSBjKCJGb3Nzb3JpYWwiLCAiR3JvdW5kLWR3ZWxsaW5nIiwgIkFxdWF0aWMiLCAiQXJib3JlYWwiLCAiU2VtaS1hcXVhdGljIiwgIlN0cmVhbS1kd2VsbGluZyIpCm5hbWVzKGVjb3R5cGVfbGFicykgPC0gYygiZm9zc19zcCIsICJncm9uX3NwIiwgImFxdWFfc3AiLCAiYXJib19zcCIsICJzZW1pX3NwIiwgInN0cm1fc3AiKQoKRVdMX3NwX2xvbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gRVdMLCB5ID0gY291bnQpKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IHRyYW5zZm9ybShFV0xfc3BfbG9uZywgZWNvdHlwZSA9IE5VTEwpLAogICAgICAgICAgICAgY29sb3VyID0gImdyZXk4NSIpICsgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gZWNvdHlwZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMC41LCBzaG93LmxlZ2VuZCA9IEYpICsgCiAgeGxhYihleHByZXNzaW9uKCJFV0wiIH4gKCJnIiB+IEhbMl0gKiBPIH4gaF57Ii0xIn0pKSkgKyAKICB5bGFiKCJTcGVjaWVzIHJpY2huZXNzIikgKyAKICBzY2FsZV9jb2xvdXJfdmlyaWRpc19kKCkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMywgMC41KSwgZXhwYW5kID0gYygwLCAwKSkgKyAKICBmYWNldF93cmFwKHZhcnMoZWNvdHlwZSksIGxhYmVsbGVyID0gbGFiZWxsZXIoZWNvdHlwZSA9IGVjb3R5cGVfbGFicykpICsgCiAgbXl0aGVtZSgpCmBgYAoKKipGaWcuIFMxMy4qKiBSZWxhdGlvbnNoaXAgYmV0d2VlbiBFV0wgYW5kIHNwZWNpZXMgcmljaG5lc3MgYnkgZWNvdHlwZS4gR3JleSBwb2ludHMgcmVwcmVzZW50IHRoZSB0b3RhbCBkYXRhc2V0IGFzIGNvbXBhcmlzb24gZm9yIHdoZXJlIGVhY2ggZWNvdHlwZSBmaXRzLgoKKioqCgojIFJlZmVyZW5jZXMgey19Cgo8ZGl2IGlkPSJyZWZzIj48L2Rpdj4KPGJyPgoKKioqCgojIyBTZXNzaW9uIEluZm9ybWF0aW9uIHstfQoKYGBge3Igc2Vzc2lvbmluZm8sIGVjaG8gPSBGQUxTRX0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSwgbG9jYWxlID0gRkFMU0UpCmBgYA==