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

This supplementary file contains the R workflow for processing and analysing the raw data, and creating figures for the manuscript ID: GEB-2022-0268 titled “Open habitats increase vulnerability of amphibian tadpoles to climate warming across latitude”.


1 Pond thermodynamic model

Water temperature is computed based on a heat budget considering longwave radiation, solar heating, and standard bulk aerodynamic flux parameterizations for sensible and latent heat (Mitchell et al., 2012). The budget is driven by fundamental meteorological conditions provided in the microclimate model of NicheMapR (Kearney and Porter, 2017), specific to each site, with the Equation (1.1).

\[\begin{equation} (Lp_w\ c_p)\ \ \frac{dT_w}{dt}=p_w\ c_p\ (I\ T_i-O\ T_w+R\ T_{sky}A_L\ )+(H-E-S+\phi_{LW} +\phi_{SW})\ A_L \tag{1.1} \end{equation}\]

where \(T_w\) is the lake temperature, \(T_i\) is the inflow temperature, \(T_{sky}\) is the air temperature (all in °K), \(p_w\) is the density of water (kg m-3), \(c_p\) is the specific heat capacity of water (J kg-1 K-1), \(L\) is the lake volume (m-3) and \(I\), \(O\), and (\(A_L\ R\)) are the inflow, outflow and rainfall volume fluxes respectively (m-3 d-1), where \(A_L\) is the lake surface area (m-2) used to multiply the rainfall depth (m d-1). \(H\) (1.2), \(E\) (1.3), \(S\) (1.4) are heat fluxes (W m-2) for sensible heat, evaporative and soil heat conduction, respectively, calculated according to:

\[\begin{equation} H=p_a\ c_p\ C_H\ u_2 (T_{sky}-T_w) \tag{1.2} \end{equation}\]

\[\begin{equation} E=p_a\ \lambda\ C_E\ u_2\ (e_s-e_a) \tag{1.3} \end{equation}\]

\[\begin{equation} S=\frac{C_S}{z_s}(T_s-T_w) \tag{1.4} \end{equation}\]

where \(C_H\) and \(C_E\) are bulk transfer coefficients for sensible and latent heat respectively (-), \(\lambda\) is the latent heat of vaporization (J kg-1), \(p_a\) is the density of air (kg m-3), and \(C_S\) is the diffusivity of heat into the soil below the water (W m-1 K-1), and \(z_s\) is the active soil depth over which heat diffusion occurs. \(\phi_{LW}\) (1.5) is the new longwave radiation (W m-2) and \(\phi_{SW}\) (1.6) is the solar insolation (W m-2), calculated from:

\[\begin{equation} \phi_{LW}=\varepsilon_a\ \sigma(T_{sky})^4-\varepsilon_w\ \sigma(T_w)^4 \tag{1.5} \end{equation}\]

\[\begin{equation} \phi_{SW}=(1-\alpha)\ {\hat{\phi}}_{SW}\bigg[\frac{A_L}{A_{MAX}}\ k_s \bigg] \tag{1.6} \end{equation}\]

where \(\varepsilon\) is the emissivity of air or water, \(\sigma\) is the Stefan-Boltzmann constant, \(\alpha\) is the shortwave radiation albedo, \({\hat{\phi}}_{SW}\) is the incident solar radiation above vegetation (W m-2). The last term (1.6) accounts for the effect of wetland vegetation shading on the incident solar intensity, with \(k_s\) defined as a constant to increase the shading effect, and \(A_{MAX}\) is the maximum area of inundation extent (m-2). In NicheMapR, assumed values for \(C_S\), \(C_H\), \(C_E\), \(\varepsilon_a\), \(k_s\) were 0.5, 0.0013, 0.0013, 0.99 and 0.25, respectively.


2 Dataset

2.1 Prepare raw data for analysis

The raw data for analysis is available on GitHub. This section is the import and clean the raw data for analysis.

# Clean raw data
clean_dat <- read.csv("https://raw.githubusercontent.com/nicholaswunz/tadpole-thermal-tolerance/main/data/raw_data.csv", na.strings = c("" , "NA" ), stringsAsFactors = TRUE) %>%
  dplyr::mutate(WT           = CTmax - Tmax,
                region       = factor(region, levels = c('Subtropics', 'Temperate')),
                country      = as.factor(country),
                habitat      = as.factor(collection_habitat),
                species_tree = gsub(" ", "_", species))

# Summarise data by group
summary_dat <- as.data.frame(clean_dat %>%
  dplyr::group_by(region, country, habitat, family, species, sp_abbr, species_tree, breeding_habitat, citation) %>%
  dplyr::summarise(lon        = mean(lon),
                   lat        = mean(lat),
                   CTmax_mean = mean(CTmax),
                   CTmax_SD   = sd(CTmax),
                   Tmax       = mean(Tmax),
                   WT_mean    = mean(WT),
                   WT_SD      = sd(WT),
                   n          = n(),
                   month_start = mean(month_start),
                   month_end   = mean(month_end))) %>%
  dplyr::relocate(c(breeding_habitat, citation), .after = last_col())

2.2 Species data summary

Table S1a

Table S1. List of species included in the study with their sample size (n), mean ± s.d. critical thermal maxima (CTmax), maximum environmental water temperature (Tmax), habitat type based on collection site, and spatial coordinates (latitude and longitude as decimal degree).

Species (abbreviation) n CTmax ± s.d. (°C) Tmax (°C) Collection habitat Latitude Longitude
Bufo bankorensis (BB) 15 37.54±0.40 18.79 Forest 23.919 120.883
Microhyla heymonsi (MH) 15 37.44±0.58 23.90 Forest 23.919 120.883
Odorrana swinhoana (OS) 30 35.85±0.51 23.55 Forest 23.988 121.129
Kurixalus berylliniris (KBE) 16 33.54±0.73 24.74 Forest 22.803 121.051
Kurixalus eiffingeri (KE) 15 31.05±1.60 25.01 Forest 23.690 120.791
Polypedates braueri (PB) 12 40.17±0.32 26.77 Forest 23.889 120.891
Zhangixalus moltrechti (ZM) 15 37.36±0.52 24.17 Forest 23.889 120.891
Duttaphrynus melanostictus (DM) 15 41.41±0.22 35.12 Open 24.181 120.609
Fejervarya limnocharis (FL) 20 41.50±0.93 30.12 Open 24.863 121.550
Hyla chinensis (HC) 12 38.23±0.39 29.14 Open 24.594 120.999
Microhyla fissipes (MF) 19 39.71±0.77 29.34 Open 24.890 121.567
Micryletta steinegeri (MS) 12 37.35±0.45 33.03 Open 23.836 120.748
Hylarana latouchii (HL) 12 37.52±0.37 21.34 Open 23.891 120.884
Rana longicrus (RL) 10 35.79±0.51 19.75 Open 25.191 121.590
Rana sauteri (RS) 14 32.44±1.14 24.89 Open 23.902 120.891
Buergeria choui (BC) 20 41.40±1.03 30.12 Open 24.863 121.550
Buergeria robusta (BR) 13 38.48±1.21 25.28 Open 23.879 120.887
Kurixalus idiootocus (KI) 10 37.40±1.35 30.00 Open 23.914 120.896
Rana pirica (RP) 8 33.91±1.48 14.50 Forest 42.595 141.281
Bufo japonicus formosus (BJF) 7 40.10±0.48 32.50 Open 43.143 141.204
Glandirana rugosa (GR) 10 39.15±0.35 32.50 Open 43.002 141.181
Bombina orientalis (BO) 30 39.93±0.67 23.29 Forest 36.813 128.054
Bufo gargarizans (BG) 48 38.04±0.61 17.95 Forest 36.491 127.197
Rana coreana (RC) 42 36.02±1.63 16.99 Forest 36.718 126.618
Rana uenoi (RU) 12 38.23±0.68 21.95 Forest 36.812 128.052
Dryophytes japonicus (DJ) 36 40.91±1.52 32.50 Open 37.599 126.892
Kaloula borealis (KBO) 6 42.65±0.26 36.84 Open 37.521 126.880
Pelophylax nigromaculatus (PN) 8 39.50±3.61 32.50 Open 36.887 126.936
Glandirana emeljanovi (GE) 30 38.10±1.07 29.05 Open 37.832 127.558

Table S1b

Table S1. Continuation of species summary with additional information on Family, and notes on the species typical breeding habitat based on the associated references. Species grouped as forest primarily breed in forest habitats. Species grouped as forest edge typically breed at the edges of forests (more exposure to sunlight). Species grouped as open primarily breed in open habitats. Species grouped as generalist typically breed in both forest and open habitats.

Family Species Breeding habitat Citation
Bufonidae Bufo bankorensis Generalist Huang et al. 1996
Microhylidae Microhyla heymonsi Generalist Chuang pers. comm.
Ranidae Odorrana swinhoana Forest Lai et al. 2007
Rhacophoridae Kurixalus berylliniris Forest Wu et al. 2016
Rhacophoridae Kurixalus eiffingeri Forest Lin et al. 2008
Rhacophoridae Polypedates braueri Forest Hsu et al. 2012
Rhacophoridae Zhangixalus moltrechti Forest edge Chang et al. 2014
Bufonidae Duttaphrynus melanostictus Open Huang et al. 1997
Dicroglossidae Fejervarya limnocharis Open Kuan et al. 2011
Hylidae Hyla chinensis Generalist Chuang pers. comm.
Microhylidae Microhyla fissipes Open Chuang pers. comm.
Microhylidae Micryletta steinegeri Open Chuang pers. comm.
Ranidae Hylarana latouchii Generalist Huang et al. 2004
Ranidae Rana longicrus Open Kam et al. 1995
Ranidae Rana sauteri Generalist Jang-Liaw et al. 2009
Rhacophoridae Buergeria choui Generalist Tominaga et al. 2015
Rhacophoridae Buergeria robusta Generalist Lin et al. 2012
Rhacophoridae Kurixalus idiootocus Generalist Hou et al. 2008
Ranidae Rana pirica Forest Matsui et al. 2018; Haramura pers. comm.
Bufonidae Bufo japonicus formosus Open Matsui et al. 2018; Haramura pers. comm.
Ranidae Glandirana rugosa Open Matsui et al. 2018; Haramura pers. comm.
Bombinatoridae Bombina orientalis Forest edge Yang et al. 2001
Bufonidae Bufo gargarizans Forest edge Yang et al. 2001; Ambu et al. 2022
Ranidae Rana coreana Generalist Yang et al. 2001; Ambu et al. 2022
Ranidae Rana uenoi Generalist Yang et al. 2001; Ambu et al. 2022
Hylidae Dryophytes japonicus Generalist Yang et al. 2001; Roh et al. 2014
Microhylidae Kaloula borealis Open Yang et al. 2001; Jung et al. 2013
Microhylidae Pelophylax nigromaculatus Open Yang et al. 2001; Yoo et al. 2019
Ranidae Glandirana emeljanovi Generalist Yang et al. 2001
  • Bufo gargarizans was recently renamed to Bufo schalinensis (Othman et al., 2022).
  • Reference list: Ambu et al. (2022), Chang et al. (2014), Hou et al. (2008), Hsu et al. (2012), Huang et al. (1996), Huang et al. (1997), Huang et al. (2004), Jang-Liaw and Lee (2009), Jung et al. (2013), Kam et al. (1995), Kuan and Lin (2011), Lai et al. (2007), Lin et al. (2012), Lin and Kam (2008), Matsui and Maeda (2018), Roh et al. (2014), Tominaga et al. (2015), Wu et al. (2016), Yang et al. (2001), Yoo et al. (2019).

3 Phylogeny

3.1 Species ascension gene number

Table S2. Accession number of genes of all species (ingroups and outgroups) in the analysis from the National Center for Biotechnology Information (NCBI).

Species 12S 16S COI cytb
Ingroup
Bufo gargarizans DQ275350 DQ275350 DQ275350 DQ275350
Bufo japonicus formosus LC061223 LC061223 AB713498
Bombina orientalis AY585338 AY585338 AY585338 AY585338
Buergeria choui DQ283055 DQ283055 MH034165 KC151119
Buergeria robusta AB530075 AF026370 GU244379 JF802879
Bufo bankorensis AF160768 AF160786 HQ650558 AB159260
Dryophytes japonicus AB303949 AB303949 AB303949 AB303949
Duttaphrynus melanostictus AY458592 AY458592 AY458592 AY458592
Fejervarya limnocharis AY158705 AY158705 AY158705 AY158705
Glandirana emeljanovi NC_030211 NC_030211 NC_030211 NC_030211
Glandirana rugosa KF771341 KF771341 JQ844517 KF771341
Hyla chinensis AY458593 AY458593 AY458593 AY458593
Hylarana latouchii KF771284 AB058880 JN700815 EU034751
Kaloula borealis NC_020044 NC_020044 NC_020044 NC_020044
Kurixalus berylliniris DQ468669 DQ468677
Kurixalus eiffingeri AB933305 AF026363 DQ468680
Kurixalus idiootocus AB933306 DQ468674 DQ468682 GQ204503
Microhyla fissipes AB201175 AB201185 KR087802 AB201219
Microhyla heymonsi AY458596 AY458596 AY458596 AY458596
Micryletta steinegeri AB634638 AB634696
Odorrana swinhoana AB200929 KF185045 HQ650557
Pelophylax nigromaculatus KT878718 KT878718 KT878718 KT878718
Polypedates braueri AB728016 AB728003 KR087860
Rana coreana NC_024548 NC_024548 NC_024548 NC_024548
Rana longicrus AB058881 JF939130
Rana pirica KX269184 KX269184 KX024946 KX269331
Rana sauteri AB685767 AB211495 EU034956
Rana uenoi KX269177 KX024885 KX024945 KX024969
Zhangixalus moltrechti AF458145 DQ468676 HQ650556 U00710
Outgroup
Ascaphus truei X86225 DQ283116 AJ871087 AF277330
Batrachuperus pinchonii AY916007 DQ283340 KM201393 AY593142
Gyrinophilus porphyriticus EU336432 DQ283255 NC_006341 NC_006341

3.2 Prepare phylogeny for analysis

This section is the import the phylogenetic tree (see phylogenetic reconstruction in main text) comprising of 29 species, match names with the data set, and create a correlation matrix for subsequent analysis.

# Load phylogeny data
phylo_tree <- ape::read.tree("https://raw.githubusercontent.com/nicholaswunz/tadpole-thermal-tolerance/main/data/tree2021_12.nwk")

tree_tip_label <- phylo_tree$tip.label # extract tree tip names
species_list   <- unique(clean_dat$species_tree) # extract species name from main dataset
missing_sp     <- as.data.frame(setdiff(tree_tip_label, species_list)) # check what names from the dataset not found in phylo_tree
# Three outgroups in tree

pruned_tree    <- ape::drop.tip(phylo_tree, setdiff(phylo_tree$tip.label, species_list)) # prune phylo_tree to keep species from the main dataset

# check if lengths match for both data and tree
sp_n <- length(unique(pruned_tree$tip.label)) # 29
#length(unique(clean_dat$species_tree)) # 29

# Check for polytomies
#ape::is.binary(pruned_tree) # TRUE

# Compute branch lengths
pruned_tree_cal <- ape::compute.brlen(pruned_tree, method = "Grafen", power = 1)
#ape::is.ultrametric(pruned_tree_cal) # TRUE

# Create correlation matrix for analysis
phylo_cor <- vcv(pruned_tree_cal, cor = T)

Fig. S1. Phylogenetic reconstruction of all 29 amphibian species used in this study. Species that were collected from closed-forest habitats shown with filled triangles, while species that were collected from open habitats shown with open circles.


4 Microclimate models and future scenario

4.1 NicheMapR parameters

Table S3. Parameter values used to estimate pond temperature using NicheMapR. Parameters for which settings differ from default values are shown in bold. Default values for other parameters in the model remained.

ID Value Variable name Variable unit
latitude Provided in table S1 latitude coordinate \(^{\circ}\)
longitude Provided in table S1 latitude coordinate \(^{\circ}\)
nyears 2 number of years to run #
soiltype clay (modified*) soil type -
REFL 0.15 soil solar reflectance decimal %
slope 0 slope \(^{\circ}\)
aspect 0 aspect \(^{\circ}\)
DEP 0, 2, 5, 10, 15, 20, 30, 45, 90, 200 soil depth cm
minshade 0 (unshaded) or 90 (shaded) minimum shade level %
maxshade 10 (unshaded) 100 (shaded) maximum shade level %
runshade TRUE run model with shade? -
clearsky FALSE run with clear sky? -
SLE 0.95 substrate longwave IR emissivity decimal %
Thcond 2.5 soil mineral thermal conductivity W m\(\\^{-1}\) K\(\\^{-1}\)
Density 2.56 soil mineral density kg m\(\\^{-3}\)
SpecHeat 870 soil mineral heat capacity J kg\(\\^{-1}\) K\(\\^{-1}\)
BulkDensity 1.4 soil bulk density kg m\(\\^{-3}\)
hori 0 horizon angles \(^{\circ}\)
cap FALSE organic surface layer? -
PE -2.731491 air entry potential J kg\(\\^{-1}\)
KS 6.41E-05 saturated conductivity kg s m\(\\^{-3}\)
BB 16.1914 Campbell\('\)s soil \('\)b\('\) parameter -
BD 1.4 soil bulk density mg m\(\\^{-3}\)
DD 2.56 soil density mg m\(\\^{-3}\)
maxpool 500 maximum pool depth mm
rainmult 10 rainfall multiplier -
LAI 0 leaf area index -
snowmodel FALSE run snow model? -
soilgrids FALSE query soilgrids? -
windfac TRUE wind multiplier -
warm 0 (current) or 4 (warming) warming offset vector \(^{\circ}\)C

* textural soil properties for clay: depth (2.5, 7.5, 22.5, 45, 80, 150), bulk density 1.4 mg m\(\\^3\), 90% clay, 0% silt, 10% sand.

4.2 Define soil parameters

Define soil parameters to enable construction of hypothetical water body in NicheMapR. Parameters modified presented in Table S3.

# Define textural soil properties for clay
soilpro <- matrix(data = 0, nrow = 6, ncol = 5)
colnames(soilpro) <- c('depth', 'blkdens', 'clay', 'silt', 'sand')
soilpro <- as.data.frame(soilpro) %>%
  dplyr::mutate(depth   = c(2.5, 7.5, 22.5, 45, 80, 150),
                blkdens = 1.4, # bulk density (Mg/m3)
                clay    = 90, # % clay
                silt    = 0.0, # % silt
                sand    = 10) # % sand
DEP     <- c(0, 2, 5, 10, 15, 20, 30, 40, 50, 100) # Soil nodes (cm)

# Get hydraulic properties for given soil
soil.hydro  <- NicheMapR::pedotransfer(soilpro = soilpro, DEP = DEP)
PE <- soil.hydro$PE
BB <- soil.hydro$BB
BD <- soil.hydro$BD
KS <- soil.hydro$KS
BulkDensity <- BD[seq(1, 19, 2)]

rainmult  <- 10 # Rainfall multiplier to reflect catchment (1 will result in unadjusted rainfall)
maxpool   <- 500 # maximium pooling depth (mm), i.e. wetland depth
LAI       <- 0 # leaf area index (zero so no transpiration)
cap       <- 0 # do not simulate the organic cap layer
soilgrids <- 0 # don't use SoilGrids soil database for thermal properties

4.3 Simulate pond temperature

Run NichemapR to simulate pond temperatures under four hypothetical scenarios: (a) current climate with open habitat, (b) current climate with shaded habitat, (c) warming climate with open habitat, and (d) warming climate with shaded habitat.

# Simulate dates for 2 years
dates <- NicheMapR::micro_global(nyear = 2)$dates

# Create loop for each coordinates
est_Tmax_open <- NULL
for( i in 1:nrow(summary_dat)){ 
  result <- data.frame(
    NicheMapR::micro_global(loc      = c(summary_dat$lon[i], summary_dat$lat[i]), 
                            runshade = 0, minshade = 0, maxshade = 10, # shade parameters
                            PCTWET   = 100, # model surface soil wetness (%), 
                            PE = PE, BB = BB, BD = BD, KS = KS, rainmult = rainmult, 
                            maxpool = maxpool, LAI = LAI, cap = cap, soilgrids = soilgrids, # soil parameters to simulate pool
                            warm = 0, # current climate
                            nyear = 2,)$soil) %>% # extract soil parameters
    dplyr::mutate(dates = dates) %>%
    dplyr::filter(dates >= summary_dat$month_start[i] & dates <= summary_dat$month_end[i]) %>% 
    dplyr::summarise(est_Tmax_open = max(D0cm))
  print(result)
  results_2 <- cbind(summary_dat$species[i], result)
  est_Tmax_open <- rbind(est_Tmax_open, results_2)
}

est_Tmax_shade <- NULL
for( i in 1:nrow(summary_dat)){ 
  result <- data.frame(
    NicheMapR::micro_global(loc      = c(summary_dat$lon[i], summary_dat$lat[i]), 
                            runshade = 0, minshade = 95, maxshade = 100, # shade parameters
                            PCTWET   = 100, # model surface soil wetness (%), 
                            PE = PE, BB = BB, BD = BD, KS = KS, rainmult = rainmult, maxpool = maxpool, LAI = LAI, cap = cap, soilgrids = soilgrids, # soil parameters to simulate pool
                            warm = 0, # current climate
                            nyear = 2)$soil) %>% # Extract soil parameters
    dplyr::mutate(dates = dates) %>%
    dplyr::filter(dates >= summary_dat$month_start[i] & dates <= summary_dat$month_end[i]) %>% 
    dplyr::summarise(est_Tmax_shade = max(D0cm))
  print(result)
  est_Tmax_shade <- rbind(est_Tmax_shade, result)
}

est_Tmax_open_4C <- NULL
for( i in 1:nrow(summary_dat)){ 
  result <- data.frame(
    NicheMapR::micro_global(loc      = c(summary_dat$lon[i], summary_dat$lat[i]), 
                            runshade = 0, minshade = 0, maxshade = 10, # shade parameters
                            PCTWET   = 100, # model surface soil wetness (%), 
                            PE = PE, BB = BB, BD = BD, KS = KS, rainmult = rainmult, maxpool = maxpool, LAI = LAI, cap = cap, soilgrids = soilgrids, # soil parameters to simulate pool
                            warm = 4, # future climate
                            nyear = 2,)$soil) %>% # extract soil parameters
    dplyr::mutate(dates = dates) %>%
    dplyr::filter(dates >= summary_dat$month_start[i] & dates <= summary_dat$month_end[i]) %>% 
    dplyr::summarise(est_Tmax_open_4C = max(D0cm))
  print(result)
  est_Tmax_open_4C <- rbind(est_Tmax_open_4C, result)
}

est_Tmax_shade_4C <- NULL
for( i in 1:nrow(summary_dat)){ 
  result <- data.frame(
    NicheMapR::micro_global(loc      = c(summary_dat$lon[i], summary_dat$lat[i]), 
                            runshade = 0, minshade = 95, maxshade = 100, # shade parameters
                            PCTWET   = 100, # model surface soil wetness (%), 
                            PE = PE, BB = BB, BD = BD, KS = KS, rainmult = rainmult, maxpool = maxpool, LAI = LAI, cap = cap, soilgrids = soilgrids, # soil parameters to simulate pool
                            warm = 4, # future climate
                            nyear = 2)$soil) %>% # extract soil parameters
    dplyr::mutate(dates = dates) %>%
    dplyr::filter(dates >= summary_dat$month_start[i] & dates <= summary_dat$month_end[i]) %>% 
    dplyr::summarise(est_Tmax_shade_4C = max(D0cm))
  print(result)
  est_Tmax_shade_4C <- rbind(est_Tmax_shade_4C, result)
}

proj_data <- cbind(summary_dat, est_Tmax_shade, est_Tmax_open[,2], est_Tmax_shade_4C, est_Tmax_open_4C) %>% 
  dplyr::rename(est_Tmax_open = "est_Tmax_open[, 2]")

4.4 Verify predicted values

Predicted Tmax from the heat budget models were validated with a linear model (below) and visually in Fig. S2e.

predict_obs_model <- lm(Tmax ~ est_Tmax_shade + habitat, data = proj_data)

verify    <- summary(predict_obs_model)$r.squared
model_mae <- Metrics::mae(proj_data$Tmax, predict(predict_obs_model))

Fig. S2 Maximum water temperature (Tmax as degree Celsius) output from the microclimate model. Example pond temperature output over a one year period for (a) Bombina orientalis, a temperate species in Korea (36.813 °N, 128.054 °E), (b) Pelophylax nigromaculatus, a temperate species in Korea (36.887 °N, 126.936 °E), (c) Kurixalus eiffingeri, a subtropics species in Taiwan (23.914 °N, 120.896 °E), and (d) Duttaphrynus melanostictus, a subtropics species in Taiwan (24.181 °N, 120.608 °E). The solid and dashed line represents the estimated water temperature under shaded conditions (95–100% vegetation shade) and under open conditions (1–10% vegetation shade), respectively. The filled area was the environmental data collection period, and the single dashed horizontal grey line is the observed Tmax from the study. (e) The observed and estimated Tmax for each species, matching the study location and time. Observed temperatures were recorded by HOBO Water Temperature loggers while the estimated Tmax was estimated from NicheMapR under open (filled triangles) and shaded habitats (open circles). Dashed line represents 1:1 scale, and R² = 0.7137031, with a mean absolute error of 2.3863238.


5 Relationship between CTmax, Tmax, and warming tolerance

Run analysis looking at the relationship between (a) CTmax and Tmax (CTmax–Tmax model), (b) warming tolerance (WT) and Tmax (WT–Tmax model), and (c) WT and CTmax (WT–CTmax model).

set.seed(10)

# Set priors
prior <- c(
  brms::prior(normal(0, 5), "b"), # mean of 0 and SD of 10 (wide distribution)
  brms::prior(student_t(3, 0, 10), "sd"), # class of random effect deviation to calculate - has to be positive (no negative SD)
  brms::prior(student_t(3, 0, 10), "sigma")) # residual SD parameter

# Run CTmax_Tmax_model
CTmax_Tmax_model <- brms::brm(CTmax ~ Tmax + habitat + lat + (1 | species) + (1 | gr(species_tree, cov = phylo)),
                              data    = clean_dat,
                              family  = gaussian,
                              data2   = list(phylo = phylo_cor),
                              prior   = prior,
                              iter    = 1e4, warmup = 5e3, cores = 4, chains = 4,
                              control = list(adapt_delta = 0.99, max_treedepth = 18))

# Run WT_Tmax_model
WT_Tmax_model <- brms::brm(WT ~ Tmax + habitat + lat + (1 | species) + (1 | gr(species_tree, cov = phylo)),
                           data    = clean_dat,
                           family  = gaussian,
                           data2   = list(phylo = phylo_cor),
                           prior   = prior,
                           iter    = 1e4, warmup = 5e3, cores = 4, chains = 4,
                           control = list(adapt_delta = 0.99, max_treedepth = 18))

# Run WT_CTmax_model (grouped by species because of co-correlation of Ctmax and WT with Tmax)
WT_CTmax_model <- brms::brm(WT_mean ~ CTmax_mean + habitat + lat + (1 | gr(species_tree, cov = phylo)),
                            data    = summary_dat,
                            family  = gaussian,
                            prior   = prior,
                            data2   = list(phylo = phylo_cor),
                            iter    = 1e4, warmup = 5e3, cores = 4, chains = 4,
                            control = list(adapt_delta = 0.99, max_treedepth = 18))

Fig. S3. Scatterplots of the observed data (y) vs the average simulated data (yrep) from the posterior predictive distribution for the (a) CTmax–Tmax model, (b) WT–Tmax model, and (c) WT–CTmax model. Dashed line represents a slope of 1.


5.1 Model output

Table S4

Table S4. Point estimates and 95% credible intervals (as determined using Bayesian methods) for fitted parameters estimated for the correlation between CTmax and Tmax, which includes fixed-effect parameters for \(\beta_0\), the average across-species intercept; \(\beta_1\), the average across-species slope of Tmax; habitat (closed and open habitat); and latitude. Group-level effects include the standard deviations (sd) for species-level variation in the intercept (\(\Delta_{\beta_0[\zeta]}\)), and phylogenetic variation in the intercept (\(\Delta_{\beta_0[\phi]}\)). Phylogenetic signal was calculated as \(\lambda = \sigma_\phi^2 / (\sigma_\phi^2 + \sigma^2)\), where \(\sigma_\phi^2\) is the estimated phylogenetic variance (i.e. sd\((\Delta_{\beta_0[\phi]})^2\)).

Parameter Estimate Est.Error Q2.5 Q97.5
Fixed effects
\(\beta_0\) 29.388 3.241 23.026 35.762
Tmax, \(\beta_1\) 0.241 0.117 0.009 0.471
Habitat - Open 0.268 1.220 -2.146 2.644
Latitude 0.081 0.065 -0.048 0.210
Group-level effects
sd\((\Delta_{\beta_0[\zeta]})\) 2.086 0.504 1.011 3.064
sd\((\Delta_{\beta_0[\phi]})\) 1.812 1.409 0.066 5.277
Phylogenetic signal
\(\lambda\) 0.580 0.311 0.004 0.961

Table S5

Table S5. Point estimates and 95% credible intervals (as determined using Bayesian methods) for fitted parameters estimated for the correlation between warming tolerance and Tmax, which includes fixed-effect parameters for \(\beta_0\), the average across-species intercept; \(\beta_1\), the average across-species slope of Tmax; habitat (closed and open habitat); and latitude. Group-level effects include the standard deviations (sd) for species-level variation in the intercept (\(\Delta_{\beta_0[\zeta]}\)), and phylogenetic variation in the intercept (\(\Delta_{\beta_0[\phi]}\)). Phylogenetic signal was calculated as \(\lambda = \sigma_\phi^2 / (\sigma_\phi^2 + \sigma^2)\), where \(\sigma_\phi^2\) is the estimated phylogenetic variance (i.e. sd\((\Delta_{\beta_0[\phi]})^2\)).

Parameter Estimate Est.Error Q2.5 Q97.5
Fixed effects
\(\beta_0\) 29.445 3.334 22.853 36.016
Tmax, \(\beta_1\) -0.761 0.117 -0.992 -0.531
Habitat - Open 0.303 1.236 -2.140 2.752
Latitude 0.081 0.065 -0.050 0.209
Group-level effects
sd\((\Delta_{\beta_0[\zeta]})\) 2.088 0.500 1.029 3.071
sd\((\Delta_{\beta_0[\phi]})\) 1.863 1.429 0.081 5.334
Phylogenetic signal
\(\lambda\) 0.589 0.310 0.006 0.963

Table S6

Table S6. Point estimates and 95% credible intervals (as determined using Bayesian methods) for fitted parameters estimated for the correlation between warming tolerance and CTmax at the species level, which includes fixed-effect parameters for \(\beta_0\), the average across-species intercept; \(\beta_1\), the average across-species slope of CTmax; habitat (closed and open habitat); and latitude. Group-level effects include the standard deviations (sd) for phylogenetic variation in the intercept (\(\Delta_{\beta_0[\phi]}\)). Phylogenetic signal was calculated as \(\lambda = \sigma_\phi^2 / (\sigma_\phi^2 + \sigma^2)\), where \(\sigma_\phi^2\) is the estimated phylogenetic variance (i.e. sd\((\Delta_{\beta_0[\phi]})^2\)).

Parameter Estimate Est.Error Q2.5 Q97.5
Fixed effects
\(\beta_0\) 4.957 12.022 -18.649 28.594
CTmax, \(\beta_1\) 0.278 0.336 -0.384 0.933
Habitat - Open -5.589 1.611 -8.700 -2.343
Latitude -0.028 0.120 -0.262 0.213
Group-level effect
sd\((\Delta_{\beta_0[\phi]})\) 3.240 2.162 0.175 8.526
Phylogenetic signal
\(\lambda\) 0.416 0.289 0.002 0.947

6 Habitat and region analysis

Run analysis looking at the relationship between (a) CTmax and (b) warming tolerance (WT) between habitat (closed-forest and open) and region (subtropic and temperate).

CTmax_model <- brms::brm(CTmax ~ habitat + region + (1 | species) + (1 | gr(species_tree, cov = phylo)),
                         data    = clean_dat,
                         family  = gaussian,
                         data2   = list(phylo = phylo_cor),
                         prior   = prior,
                         iter    = 1e4, warmup = 5e3, cores = 4, chains = 4,
                         control = list(adapt_delta = 0.99, max_treedepth = 18))

WT_model <- brms::brm(WT ~ habitat * region + (1 | species) + (1 | gr(species_tree, cov = phylo)),
                      data    = clean_dat,
                      family  = gaussian,
                      data2   = list(phylo = phylo_cor),
                      prior   = prior,
                      iter    = 1e4, warmup = 5e3, cores = 4, chains = 4,
                      control = list(adapt_delta = 0.99, max_treedepth = 18))

WT_lat_model <- brms::brm(WT ~ lat * habitat + (1 | species) + (1 | gr(species_tree, cov = phylo)),
                      data    = clean_dat,
                      family  = gaussian,
                      data2   = list(phylo = phylo_cor),
                      prior   = prior,
                      iter    = 1e4, warmup = 5e3, cores = 4, chains = 4,
                      control = list(adapt_delta = 0.99, max_treedepth = 18))

Fig. S4. Scatterplots of the observed data (y) vs the average simulated data (yrep) from the posterior predictive distribution for the (a) CTmax model, (b) WT model, and (c) WT–latitude model. Dashed line represents a slope of 1.


Model output

Table S7

Table S7. Point estimates and 95% credible intervals (as determined using Bayesian methods) for fitted parameters estimated for the relationship between CTmax with habitat and region, which includes fixed-effect parameters for \(\beta_0\), the average across-species intercept; habitat (closed and open habitat); and region (subtropics, temperate). Group-level effects include the standard deviations (sd) for species-level variation in the intercept (\(\Delta_{\beta_0[\zeta]}\)), and phylogenetic variation in the intercept (\(\Delta_{\beta_0[\phi]}\)). Phylogenetic signal was calculated as \(\lambda = \sigma_\phi^2 / (\sigma_\phi^2 + \sigma^2)\), where \(\sigma_\phi^2\) is the estimated phylogenetic variance (i.e. sd\((\Delta_{\beta_0[\phi]})^2\)).

Parameter Estimate Est.Error Q2.5 Q97.5
Fixed effects
\(\beta_0\) 36.548 1.378 33.888 39.434
Habitat - Open 2.133 0.928 0.321 3.963
Region - Temperate 1.688 0.987 -0.272 3.611
Group-level effects
sd\((\Delta_{\beta_0[\zeta]})\) 2.105 0.519 1.075 3.141
sd\((\Delta_{\beta_0[\phi]})\) 2.264 1.394 0.203 5.527
Phylogenetic signal
\(\lambda\) 0.697 0.258 0.036 0.965

Table S8

Table S8. Point estimates and 95% credible intervals (as determined using Bayesian methods) for fitted parameters estimated for the correlation between warming tolerance and Tmax, which includes fixed-effect parameters for \(\beta_0\), the average across-species intercept; \(\beta_1\), the average across-species slope of Tmax; habitat (closed and open habitat); and latitude. Group-level effects include the standard deviations (sd) for species-level variation in the intercept (\(\Delta_{\beta_0[\zeta]}\)), and phylogenetic variation in the intercept (\(\Delta_{\beta_0[\phi]}\)). Phylogenetic signal was calculated as \(\lambda = \sigma_\phi^2 / (\sigma_\phi^2 + \sigma^2)\), where \(\sigma_\phi^2\) is the estimated phylogenetic variance (i.e. sd\((\Delta_{\beta_0[\phi]})^2\)).

Parameter Estimate Est.Error Q2.5 Q97.5
Fixed effects
\(\beta_0\) 13.087 1.773 9.685 16.783
Habitat - Open -3.005 1.524 -6.064 -0.011
Region - Temperate 3.756 1.920 -0.142 7.410
Habitat - Open: Region - Temperate -6.241 2.349 -10.699 -1.529
Group-level effects
sd\((\Delta_{\beta_0[\zeta]})\) 3.184 0.603 2.072 4.453
sd\((\Delta_{\beta_0[\phi]})\) 2.102 1.644 0.083 6.297
Phylogenetic signal
\(\lambda\) 0.625 0.307 0.006 0.973

7 Warming and deforesation analysis

Run analysis looking at the relationship between climate (current and warming), with the interaction between category (open and shaded simulated habitat), habitat (closed and open habitat - breeding) and region (subtropics, temperate) on warming tolerance.

# Calculate WT
proj_data <- proj_data %>%
  dplyr::mutate(WT_shade_cur = CTmax_mean - est_Tmax_shade,
                WT_open_cur  = CTmax_mean - est_Tmax_open,
                WT_shade_4C  = CTmax_mean - est_Tmax_shade_4C,
                WT_open_4C   = CTmax_mean - est_Tmax_open_4C)

# Convert wide to long format
proj_long <- proj_data %>%
  dplyr::select(region, species, CTmax_mean, habitat, lat, WT_shade_cur, WT_open_cur, WT_shade_4C, WT_open_4C) %>%
  tidyr::pivot_longer(!c(region, species, CTmax_mean, habitat, lat), names_to = "category", values_to = "values") %>%
  dplyr::mutate(climate = case_when(endsWith(category, "cur") ~ "Current",
                                    endsWith(category, "4C")~ "Warming"),
                category = dplyr::recode(category, 
                                         WT_open_cur = "Open habitat",
                                         WT_shade_cur = "Shaded habitat",
                                         WT_open_4C = "Open habitat",
                                         WT_shade_4C = "Shaded habitat"))

# Add phylogeny to dataset
proj_long$species_tree <- summary_dat$species_tree[match(proj_long$species, summary_dat$species)]

# Run brms model
proj_model <- brms::brm(values ~ climate + category * habitat * region + (1 | species) + (1 | gr(species_tree, cov = phylo)),
                        data    = proj_long,
                        family  = gaussian,
                        data2   = list(phylo = phylo_cor),
                        iter    = 1e4, warmup = 5e3, cores = 4, chains = 4,
                        control = list(adapt_delta = 0.99, max_treedepth = 18))

Fig. S5. Scatterplot of the observed data (y) vs the average simulated data (yrep) from the posterior predictive distribution for the climate and deforestation projection model. Dashed line represents a slope of 1.

7.1 Model output

Table S9. Point estimates and 95% credible intervals (as determined using Bayesian methods) for fitted parameters estimated for the relationship between warming tolerance with climate change and deforestation, which includes fixed-effect parameters for \(\beta_0\), the average across-species intercept; climate (current, warming); and the three-way interaction with shaded (open and shaded simulated habitat), habitat (closed and open habitat - breeding) and region (subtropics, temperate). Group-level effects include the standard deviations (sd) for species-level variation in the intercept (\(\Delta_{\beta_0[\zeta]}\)), and phylogenetic variation in the intercept (\(\Delta_{\beta_0[\phi]}\)). Phylogenetic signal was calculated as \(\lambda = \sigma_\phi^2 / (\sigma_\phi^2 + \sigma^2)\), where \(\sigma_\phi^2\) is the estimated phylogenetic variance (i.e. sd\((\Delta_{\beta_0[\phi]})^2\)).

Parameter Estimate Est.Error Q2.5 Q97.5
Fixed effects
\(\beta_0\) 9.097 2.239 4.688 13.798
Climate - Warming -3.266 0.145 -3.554 -2.983
Shaded 6.845 0.292 6.266 7.412
Habitat - Open -0.072 1.863 -3.681 3.610
Region - Temperate -3.538 2.552 -8.637 1.472
Shaded: Habitat - Open 0.068 0.375 -0.656 0.803
Shaded: Region - Temperate 4.977 0.452 4.098 5.856
Habitat - Open: Region - Temperate 2.713 3.232 -3.559 9.076
Shaded: Habitat - Open: Region - Temperate -2.206 0.597 -3.376 -1.036
Group-level effects
sd\((\Delta_{\beta_0[\zeta]})\) 3.333 0.855 1.286 4.901
sd\((\Delta_{\beta_0[\phi]})\) 2.793 2.390 0.091 8.739
Phylogenetic signal
\(\lambda\) 0.735 0.302 0.014 0.992

8 Figures for main text

Raw figures produced were modified in Adobe Illustrator for publication.

8.1 Figure 2 - CTmax, Tmax, warming tolerance relationship

# Extract marginal effects
CTmax_Tmax_me <- as.data.frame(ggeffects::ggpredict(CTmax_Tmax_model, terms = c("Tmax[sample = 25]"))) 
WT_Tmax_me    <- as.data.frame(ggeffects::ggpredict(WT_Tmax_model, terms = c("Tmax[sample = 25]"))) 

# Fig 2
ctmax_tmax_plot <- summary_dat %>%
  ggplot() +
  geom_ribbon(data = CTmax_Tmax_me, aes(x = x, ymin = conf.low, ymax = conf.high), fill = "#FE945C",alpha = 0.1) +
  geom_line(data = CTmax_Tmax_me, aes(x = x, y = conf.low), colour = "#FE945C", linetype = "dashed") +
  geom_line(data = CTmax_Tmax_me, aes(x = x, y = conf.high), colour = "#FE945C", linetype = "dashed") +
  geom_line(data = CTmax_Tmax_me, aes(x = x, y = predicted), colour = "#DD3B24", size = 1) +
  geom_point(aes(x = Tmax, y = CTmax_mean, colour = region, shape = habitat), size = 2, fill = "white") +
  scale_shape_manual(values = c(17, 21)) +
  scale_colour_manual(values = c("#DD3B24", "#FE945C")) +
  xlab(expression(T["max"]~"(°C)")) +
  ylab(expression("CT"["max"]~"(°C)")) +
  mytheme()

wt_tmax_plot <- summary_dat %>%
  ggplot() +
  geom_ribbon(data = WT_Tmax_me, aes(x = x, ymin = conf.low, ymax = conf.high), fill = "#FE945C",alpha = 0.1) +
  geom_line(data = WT_Tmax_me, aes(x = x, y = conf.low), colour = "#FE945C", linetype = "dashed") +
  geom_line(data = WT_Tmax_me, aes(x = x, y = conf.high), colour = "#FE945C", linetype = "dashed") +
  geom_line(data = WT_Tmax_me, aes(x = x, y = predicted), colour = "#DD3B24", size = 1) +
  geom_point(aes(x = Tmax, y = WT_mean, colour = region, shape = habitat), size = 2, fill = "white") +
  scale_shape_manual(values = c(17, 21)) +
  scale_colour_manual(values = c("#DD3B24", "#FE945C")) +
  xlab(expression(T['max']~"(°C)")) +
  ylab("Warming tolerance") +
  mytheme()

wt_ctmax_plot <- summary_dat %>%
  ggplot() +
  geom_point(aes(x = CTmax_mean, y = WT_mean, colour = region, shape = habitat), size = 2, fill = "white") +
  scale_shape_manual(values = c(17, 21)) +
  scale_colour_manual(values = c("#DD3B24", "#FE945C")) +
  xlab(expression(CT['max']~"(°C)")) +
  ylab("Warming tolerance") +
  mytheme()

cowplot::plot_grid(ctmax_tmax_plot + theme(legend.position = "none"), 
                   wt_tmax_plot + theme(legend.position = "none"), 
                   wt_ctmax_plot + theme(legend.position = "none"),
                   ncol = 3, align = "hv", axis = "tblr", labels = c("a", "b", "c"))

8.2 Figure 3 - CTmax and warming tolerance across habitat and region

Latitude as category (Fig. 3a and 3b)

# Fig 3 production
CTmax_plot <- summary_dat %>%
  # regrouping
  dplyr::group_by(region) %>%
  dplyr::arrange(habitat, CTmax_mean) %>%
  mutate(x = row_number()) %>% # change to number to order by habitat and CTmax
  ungroup() %>%
  # plotting
  ggplot(aes(x = x, y = CTmax_mean, colour = region, shape = habitat, label = sp_abbr)) +
  stat_mean_line(aes(linetype = habitat),  alpha = 0.5) +
  geom_pointrange(aes(ymin = CTmax_mean - CTmax_SD, ymax = CTmax_mean + CTmax_SD, linetype = habitat)) +
  geom_point(size = 3, fill = "white") +
  scale_shape_manual(values = c(17, 21)) +
  scale_colour_manual(values = c("#DD3B24", "#FE945C")) +
  geom_text(nudge_y = 1.5, size = 3, show.legend = FALSE) +
  xlab(NULL) +
  ylab(expression("CT"["max"]~"(°C)")) +
  facet_grid(. ~ region, scales = 'free_x') +
  mytheme() +
  theme(axis.title.x = element_blank(),
        axis.text.x  = element_blank(),
        axis.ticks.x = element_blank())

WT_plot <- summary_dat %>%
  # regrouping
  dplyr::group_by(region) %>%
  dplyr::arrange(habitat, WT_mean) %>%
  mutate(x = row_number()) %>% # change to number to order by habitat and WT
  ungroup() %>%
  # plotting
  ggplot(aes(x = x, y = WT_mean, colour = region, shape = habitat, label = sp_abbr)) +
  stat_mean_line(aes(linetype = habitat), alpha = 0.5) +
  geom_pointrange(aes(ymin = WT_mean - WT_SD, ymax = WT_mean + WT_SD, linetype = habitat)) +
  geom_point(size = 3, fill = "white") +
  scale_shape_manual(values = c(17, 21)) +
  scale_colour_manual(values = c("#DD3B24", "#FE945C")) +
  geom_text(nudge_y = 2, size = 3, show.legend = FALSE) +
  ylim(0, 25) +
  xlab("Species") +
  ylab("Warming tolerance") +
  facet_grid(. ~ region, scales = 'free_x') +
  mytheme() +
  theme(axis.title.x = element_blank(),
        axis.text.x  = element_blank(),
        axis.ticks.x = element_blank())

cowplot::plot_grid(CTmax_plot, WT_plot, nrow = 2, align = "hv", axis = "tblr", labels = c("a", "b"))

Latitude as continuous (Fig. 3c)

WT_lat_me <- as.data.frame(ggeffects::ggpredict(WT_lat_model, terms = c("lat [sample = 26]", "habitat")))

summary_dat %>%
  ggplot() +
  geom_ribbon(data = WT_lat_me, aes(x = x, ymin = conf.low, ymax = conf.high, fill = group), alpha = 0.1) +
  geom_line(data = WT_lat_me, aes(x = x, y = conf.low, group = group), colour = "#DD3B24", linetype = "dashed") +
  geom_line(data = WT_lat_me, aes(x = x, y = conf.high, group = group), colour = "#DD3B24", linetype = "dashed") +
  geom_line(data = WT_lat_me, aes(x = x, y = predicted, linetype = group), colour = "#DD3B24", size = 1) +
  geom_point(aes(x = lat, y = WT_mean, shape = habitat), colour = "#DD3B24", size = 2, fill = "white") +
  scale_shape_manual(values = c(17, 21)) +
  scale_fill_manual(values = c("#FE945C", "white")) +
  xlab("Latitude (°)") +
  ylab("Warming tolerance") +
  mytheme()

8.3 Figure 4 - Warming and deforestation projection

# Extract estimate +/- 95% CI
conditions <- make_conditions(proj_model, c("climate", "region"))
predict_me <- brms::conditional_effects(proj_model, "category:habitat", conditions = conditions)
predict_dat <- as.data.frame(predict_me[[1]]) %>% dplyr::rename(estimate = estimate__, ci.lb = lower__, ci.ub = upper__)

proj_long %>%
  dplyr::mutate(category = forcats::fct_relevel(as.factor(category),"Shaded habitat", "Open habitat")) %>%
  ggplot() +
  geom_hline(yintercept = 0, linetype = "dashed", alpha = 0.5) +
  geom_point(aes(x = category, y = values, colour = region, shape = habitat), size = 2, position = position_dodge(0.6), fill = "grey", alpha = 0.5) +
  geom_pointrange(data = predict_dat, aes(x = category, y = estimate, ymin = ci.lb, ymax = ci.ub, colour = region, shape = habitat, linetype = habitat), 
                  position = position_dodge(0.6), size = 0.7, fill = "white") +
  ylab("Warming tolerance") + xlab(NULL) +
  scale_shape_manual(values = c(17, 21)) +
  scale_colour_manual(values = c("#DD3B24", "#FE945C")) +
  scale_fill_manual(values = c("#DD3B24", "#FE945C")) +
  ylim(-10, max(proj_long$values)) +
  facet_grid(. ~ climate) +
  mytheme() +
  theme(legend.position = "bottom")


9 [20/01/2023 CORRECTION] Microclimate models and future scenario

The micro_global function did not have the soil moisture function on by default. After consultation with the NicheMapR developer Michael Kearney, we re-estimated the pond temperatures using the micro_era5 function which provides fine-scale resolution (~1 km weather model forecast.

The model does not confirm that pond drying will ‘not occur’ as stated in the main text. However, the higher rain multiplier (rainmult) reduces the likelihood of pond drying.

The equations from the Pond thermodynamic model do not apply to the NicheMapR models. We followed the methods from Enriquez-Urzelai et al. (2019) to estimate pond temperature.

9.1 Download microclimate spatial map

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)
xmn <- min(summary_dat$lon) - 1 
xmx <- max(summary_dat$lon) + 1 
ymn <- min(summary_dat$lat) - 1
ymx <- max(summary_dat$lat) + 1

# temporal extent
st_time <- lubridate::ymd("2013:01:01") # earliest sampling date
en_time <- lubridate::ymd("2020: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)

9.2 Simulate pond temperature

Run NichemapR to simulate pond temperatures under four hypothetical scenarios: (a) current climate with open habitat, (b) current climate with shaded habitat, (c) warming climate with open habitat, and (d) warming climate with shaded habitat. To ensure the pond does not dry up during the sampling period, we increased rainmult to 20.

sum_dat <- as.data.frame(clean_dat %>%
  dplyr::group_by(region, country, habitat, family, species) %>%
  dplyr::summarise(lon        = mean(lon),
                   lat        = mean(lat),
                   Tmax       = mean(Tmax),
                   year_start = min(year_start),
                   year_end   = min(year_finish),
                   month_start = mean(month_start),
                   month_end   = mean(month_end)))

# Create loop for each coordinates
est_Tmax <- NULL
for( i in 1:nrow(sum_dat)){ 
  micro_out <- 
    NicheMapR::micro_era5(loc = c(sum_dat$lon[i], sum_dat$lat[i]), 
                          runshade = 1, minshade = 0, # shade parameters
                          PE = PE, BB = BB, BD = BD, KS = KS, rainmult = 20, 
                          maxpool = maxpool, LAI = LAI, cap = cap, soilgrids = soilgrids, # soil parameters to simulate pool
                          warm = 0, # current climate
                          DEP = DEP,
                          dstart = paste("01/01/", sum_dat$year_start[i], sep =""), 
                          dfinish = paste("31/12/", sum_dat$year_end[i], sep =""),
                          runmoist = 1, 
                          spatial = '/Users/nicholaswu/Library/CloudStorage/OneDrive-WesternSydneyUniversity/NicheMapR/era5', # change to your location
                          save = 0)
  
  metout <- data.frame(micro_out$metout) %>% # extract soil parameters
  dplyr::mutate(dates = row_number() / 730) %>% # hours to month
  dplyr::filter(dates >= sum_dat$month_start[i] & dates <= sum_dat$month_end[i]) 
  
  # extract water temp in open habitat
    open <- data.frame(micro_out$soil) %>% # extract soil parameters
      dplyr::mutate(dates = row_number() / 730) %>% # hours to month
      merge(metout, by = "dates") %>%
      dplyr::filter(dates >= sum_dat$month_start[i] & dates <= sum_dat$month_end[i] & POOLDEP > 400) %>% 
      dplyr::summarise(est_Tmax_open = max(D50cm))
  print(open)

  # extract water temp in shaded habitat
  closed <- data.frame(micro_out$shadsoil) %>% # extract soil parameters
      dplyr::mutate(dates = row_number() / 730) %>% # hours to month
      merge(metout, by = "dates") %>%
    dplyr::filter(dates >= sum_dat$month_start[i] & dates <= sum_dat$month_end[i] & POOLDEP > 400) %>% 
    dplyr::summarise(est_Tmax_shade = max(D50cm))
  print(closed)
  results <- cbind(sum_dat$species[i], open, closed)
  est_Tmax <- rbind(est_Tmax, results)
}

est_Tmax_4C <- NULL
for( i in 1:nrow(sum_dat)){ 
  micro_out <- 
    NicheMapR::micro_era5(loc = c(sum_dat$lon[i], sum_dat$lat[i]), 
                          runshade = 1, minshade = 0, # shade parameters
                          PE = PE, BB = BB, BD = BD, KS = KS, rainmult = 20, 
                          maxpool = maxpool, LAI = LAI, cap = cap, soilgrids = soilgrids, # soil parameters to simulate pool
                          warm = 4, # future climate
                          DEP = DEP,
                          dstart = paste("01/01/", sum_dat$year_start[i], sep =""), 
                          dfinish = paste("31/12/", sum_dat$year_end[i], sep =""),
                          runmoist = 1, 
                          spatial = '/Users/nicholaswu/Library/CloudStorage/OneDrive-WesternSydneyUniversity/NicheMapR/era5', # change to your location
                          save = 0)
  metout <- data.frame(micro_out$metout) %>% # extract soil parameters
  dplyr::mutate(dates = row_number() / 730) %>% # hours to month
  dplyr::filter(dates >= sum_dat$month_start[i] & dates <= sum_dat$month_end[i]) 
  
  # extract water temp in open habitat
    open <- data.frame(micro_out$soil) %>% # extract soil parameters
      dplyr::mutate(dates = row_number() / 730) %>% # hours to month
      merge(metout, by = "dates") %>%
      dplyr::filter(dates >= sum_dat$month_start[i] & dates <= sum_dat$month_end[i] & POOLDEP > 400) %>% 
      dplyr::summarise(est_Tmax_open_4C = max(D50cm))
  print(open)
  # extract water temp in shaded habitat
  closed <- data.frame(micro_out$shadsoil) %>% # extract soil parameters
      dplyr::mutate(dates = row_number() / 730) %>% # hours to month
      merge(metout, by = "dates") %>%
    dplyr::filter(dates >= sum_dat$month_start[i] & dates <= sum_dat$month_end[i] & POOLDEP > 400) %>% 
    dplyr::summarise(est_Tmax_shade_4C = max(D50cm))
  print(closed)
  results <- cbind(sum_dat$species[i], open, closed)
  est_Tmax_4C <- rbind(est_Tmax_4C, results)
}

proj_data <- cbind(summary_dat, est_Tmax[,2], est_Tmax[,3], est_Tmax_4C[,2], est_Tmax_4C[,3]) %>% 
  dplyr::rename(est_Tmax_open = "est_Tmax[, 2]", 
                est_Tmax_shade = "est_Tmax[, 3]",
                est_Tmax_open_4C = "est_Tmax_4C[, 2]", 
                est_Tmax_shade_4C = "est_Tmax_4C[, 3]")

9.3 Verify predicted values

Predicted Tmax from the heat budget models were validated with a linear model (below) and visually in Updated Fig. S2.

proj_test <- proj_data %>%
  mutate(est_Tmax_test = ifelse(habitat == "Forest", est_Tmax_shade, est_Tmax_open)) %>%
  filter_all(all_vars(!is.infinite(.)))

predict_obs_model <- lm(Tmax ~ est_Tmax_test, data = proj_test)

verify2    <- summary(predict_obs_model)$r.squared
model_mae2 <- Metrics::mae(proj_test$Tmax, predict(predict_obs_model))
## downloading DEM via package elevatr 
## extracting weather data locally from /Users/nicholaswu/Library/CloudStorage/OneDrive-WesternSydneyUniversity/NicheMapR/era5 
## computing radiation and elevation effects with package microclima 
## Downscaling radiation and wind speed 
## Calculating meso-scale terrain effects 
## running microclimate model for  365  days from  2014-01-01  to  2014-12-31 23:00:00  at site  long 121.1295 lat 23.98788 
## Note: the output column `SOLR` in metout and shadmet is for unshaded solar radiation adjusted for slope, aspect and horizon angle 
##    user  system elapsed 
##   5.642   0.075   5.777

Updated Fig. S2 The observed and estimated Tmax for each species, matching the study location and time. Observed temperatures were recorded by HOBO Water Temperature loggers while the estimated Tmax was estimated from NicheMapR under open (filled triangles) and shaded habitats (open circles). Dashed line represents 1:1 scale, and R² = 0.5621393, with a mean absolute error of 2.9461639.

The updated estimated pond temperatures did not differ much relative to the original simulations.


10 References

Ambu, J., Andersen, D. and Borzée, A. (2022). Spawning site selection and segregation at the landscape, habitat and microhabitat scales for five syntopic asian amphibians. Amphibia-Reptilia 43, 169–180.
Chang, Y., Tseng, W., Chen, C., Huang, C., Chen, Y. and Hatch, K. (2014). Winter breeding and high tadpole densities may benefit the growth and development of tadpoles in a subtropical lowland treefrog. Journal of Zoology 294, 154–160.
Hou, W.-S., Chang, Y.-H. and Wang, H.-W. (2008). Climatic effects and impacts of lakeshore bank designs on the activity of Chirixalus idiootocus in Yilan, Taiwan. Ecological Engineering 32, 52–59.
Hsu, J.-L., Kam, Y.-C. and Fellers, G. M. (2012). Overwintering tadpoles and loss of fitness correlates in Polypedates braueri tadpoles that use artificial pools in a lowland agroecosystem. Herpetologica 68, 184–194.
Huang, W.-S., Lin, J.-Y. and Yu, J. Y.-L. (1996). The male reproductive cycle of the toad, Bufo bankorensis, in Taiwan. Zoological Studies 35, 128–137.
Huang, W.-S., Lin, J.-Y. and Yu, J. Y.-L. (1997). Male reproductive cycle of the toad Bufo melanostictus in Taiwan. Zoological Science 14, 497–503.
Huang, W.-S., Cheng, Y.-S. and Tu, H.-Y. (2004). Reproductive patterns of two sympatric ranid frogs, Rana latouchii and R. sauteri, with comments on anuran breeding seasons in Taiwan. Collection and Research 17, 1–10.
Jang-Liaw, N.-H. and Lee, T.-H. (2009). Intraspecific relationships of populations of the brown frog Rana sauteri (Ranidae) on Taiwan, inferred from mitochondrial cytochrome b sequences. Zoological Science 26, 608–616.
Jung, Y. S., Park, M. O. and Koo, B. H. (2013). A substitute habitat planning for Kaloula borealis based on wetlands. Journal of the Korean Society of Environmental Restoration Technology 16, 1–15.
Kam, Y.-C., Wang, C.-S. and Lin, Y.-S. (1995). Reproduction and diet of the brown frog Rana longicrus in Taiwan. Zoological Studies 34, 193–201.
Kearney, M. R. and Porter, W. P. (2017). NicheMapR – an r package for biophysical modelling: The microclimate model. Ecography 40, 664–674.
Kuan, S. and Lin, Y. (2011). Bigger or faster? Spring and summer tadpole cohorts use different life‐history strategies. Journal of Zoology 285, 165–171.
Lai, Y., Shieh, B. and Kam, Y. (2007). Population patterns of a riparian frog (Rana swinhoana) before and after an earthquake in subtropical Taiwan. Biotropica 39, 731–736.
Lin, Y.-S. and Kam, Y.-C. (2008). Nest choice and breeding phenology of an arboreal-breeding frog, Kurixalus eiffingeri (Rhacophoridae), in a bamboo forest. Zoological Studies 47, 129.
Lin, H.-D., Chen, Y.-R. and Lin, S.-M. (2012). Strict consistency between genetic and topographic landscapes of the brown tree frog (Buergeria robusta) in Taiwan. Molecular Phylogenetics and Evolution 62, 251–262.
Matsui, M. and Maeda, N. (2018). Encyclopedia of japanese frogs Japan book. Japan: Bun-ichiSogo Shuppan.
Mitchell, N., Hipsey, M. R., Arnall, S., McGrath, G., Tareque, H. B., Kuchling, G., Vogwill, R., Sivapalan, M., Porter, W. P. and Kearney, M. R. (2012). Linking eco-energetics and eco-hydrology to select sites for the assisted colonization of australia’s rarest reptile. Biology 2, 1–25.
Othman, S. N., Litvinchuk, S. N., Maslova, I., Dahn, H., Messenger, K. R., Andersen, D., Jowers, M. J., Kojima, Y., Skorinov, D. V. and Yasumiba, K. (2022). From Gondwana to the Yellow sea, evolutionary diversifications of true toads Bufo sp. In the Eastern Palearctic and a revisit of species boundaries for Asian lineages. Elife 11, e70494.
Roh, G., Borzée, A. and Jang, Y. (2014). Spatiotemporal distributions and habitat characteristics of the endangered treefrog, Hyla suweonensis, in relation to sympatric H. japonica. Ecological Informatics 24, 78–84.
Tominaga, A., Matsui, M., Eto, K. and Ota, H. (2015). Phylogeny and differentiation of wide-ranging Ryukyu Kajika frog Buergeria japonica (Amphibia: Rhacophoridae): Geographic genetic pattern not simply explained by vicariance through strait formation. Zoological Science 32, 240–247.
Wu, S.-P., Huang, C.-C., Tsai, C.-L., Lin, T.-E., Jhang, J.-J. and Wu, S.-H. (2016). Systematic revision of the Taiwanese genus Kurixalus members with a description of two new endemic species (Anura, Rhacophoridae). ZooKeys 121.
Yang, S. Y., Kim, J. B., Min, M. S., Suh, J. H. and Kang, Y. J. (2001). Monograph of Korean Amphibia. Seoul, Republic of Korea: Academy book Press.
Yoo, N., Do, M. S., Nam, H.-K., Choi, G., Son, S.-J. and Yoo, J.-C. (2019). Habitat characteristics of anuran species inhabiting rice fields of western mid-south Korea - In the case of Daeho reclamation agricultural land by farming practices. Korean Journal of Ecology and Environment 52, 366–377.



10.1 Session Information

R version 4.2.2 (2022-10-31)

Platform: aarch64-apple-darwin20 (64-bit)

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

other attached packages: microclima(v.0.1.0), RNetCDF(v.2.6-1), mcera5(v.0.3.0), raster(v.3.6-13), sp(v.1.5-1), pander(v.0.6.5), NicheMapR(v.3.2.1), diversitree(v.0.9-16), phytools(v.1.2-0), maps(v.3.4.1), ape(v.5.6-2), rstan(v.2.21.7), StanHeaders(v.2.21.0-7), brms(v.2.18.0), Rcpp(v.1.0.9), colorspace(v.2.0-3), forcats(v.0.5.2), stringr(v.1.5.0), dplyr(v.1.0.10), purrr(v.1.0.1), readr(v.2.1.3), tidyr(v.1.2.1), tibble(v.3.1.8), tidyverse(v.1.3.2), Matrix(v.1.5-1), cowplot(v.1.1.1), ggplot2(v.3.4.0) and knitr(v.1.41)

loaded via a namespace (and not attached): utf8(v.1.2.2), tidyselect(v.1.2.0), htmlwidgets(v.1.6.1), hoardr(v.0.5.2), grid(v.4.2.2), combinat(v.0.0-8), munsell(v.0.5.0), units(v.0.8-1), codetools(v.0.2-18), DT(v.0.26), miniUI(v.0.1.1.1), withr(v.2.5.0), Brobdingnag(v.1.2-9), progressr(v.0.13.0), highr(v.0.10), rstudioapi(v.0.14), stats4(v.4.2.2), Metrics(v.0.1.4), bayesplot(v.1.10.0), labeling(v.0.4.2), emmeans(v.1.8.3), mnormt(v.2.1.1), optimParallel(v.1.0-2), farver(v.2.1.1), bridgesampling(v.1.1-2), coda(v.0.19-4), vctrs(v.0.5.1), generics(v.0.1.3), clusterGeneration(v.1.3.7), xfun(v.0.36), timechange(v.0.2.0), slippymath(v.0.3.1), R6(v.2.5.1), markdown(v.1.4), fields(v.14.1), cachem(v.1.0.6), assertthat(v.0.2.1), promises(v.1.2.0.1), scales(v.1.2.1), RNCEP(v.1.0.10), googlesheets4(v.1.0.1), gtable(v.0.3.1), ncmeta(v.0.3.5), processx(v.3.8.0), phangorn(v.2.10.0), spam(v.2.9-1), rlang(v.1.0.6), scatterplot3d(v.0.3-42), rgdal(v.1.6-4), gargle(v.1.2.1), broom(v.1.0.2), checkmate(v.2.1.0), inline(v.0.3.19), yaml(v.2.3.6), reshape2(v.1.4.4), abind(v.1.4-5), modelr(v.0.1.10), threejs(v.0.3.3), crosstalk(v.1.2.0), backports(v.1.4.1), httpuv(v.1.6.8), tensorA(v.0.36.2), tools(v.4.2.2), tcltk(v.4.2.2), bookdown(v.0.31), ellipsis(v.0.3.2), jquerylib(v.0.1.4), posterior(v.1.3.1), RColorBrewer(v.1.1-3), proxy(v.0.4-27), plyr(v.1.8.8), progress(v.1.2.2), base64enc(v.0.1-3), classInt(v.0.4-8), elevatr(v.0.4.2), ps(v.1.7.2), prettyunits(v.1.1.1), rpart(v.4.1.19), tgp(v.2.4-21), viridis(v.0.6.2), deSolve(v.1.34), zoo(v.1.8-11), cluster(v.2.1.4), haven(v.2.5.1), fs(v.1.5.2), crul(v.1.3), magrittr(v.2.0.3), colourpicker(v.1.2.0), reprex(v.2.0.2), googledrive(v.2.0.0), mvtnorm(v.1.1-3), matrixStats(v.0.63.0), hms(v.1.1.2), shinyjs(v.2.1.0), mime(v.0.12), evaluate(v.0.19), xtable(v.1.8-4), XML(v.3.99-0.13), shinystan(v.2.6.0), readxl(v.1.4.1), gridExtra(v.2.3), ggeffects(v.1.1.4), rstantools(v.2.2.0), compiler(v.4.2.2), tidync(v.0.3.0), ncdf4(v.1.21), KernSmooth(v.2.23-20), crayon(v.1.5.2), htmltools(v.0.5.4), later(v.1.3.0), tzdb(v.0.3.0), expm(v.0.999-6), RcppParallel(v.5.1.5), lubridate(v.1.9.0), DBI(v.1.1.3), sjlabelled(v.1.2.0), dbplyr(v.2.2.1), subplex(v.1.8), rappdirs(v.0.3.3), MASS(v.7.3-58.1), sf(v.1.0-9), cli(v.3.6.0), quadprog(v.1.5-8), parallel(v.4.2.2), insight(v.0.18.8), dotCall64(v.1.0-2), igraph(v.1.3.5), pkgconfig(v.2.0.3), numDeriv(v.2016.8-1.1), terra(v.1.6-47), xml2(v.1.3.3), dygraphs(v.1.1.1.6), bslib(v.0.4.2), estimability(v.1.4.1), rvest(v.1.0.3), distributional(v.0.3.1), callr(v.3.7.3), digest(v.0.6.31), httpcode(v.0.3.0), rmarkdown(v.2.19), cellranger(v.1.1.0), fastmatch(v.1.1-3), curl(v.5.0.0), shiny(v.1.7.4), gtools(v.3.9.4), lifecycle(v.1.0.3), nlme(v.3.1-160), jsonlite(v.1.8.4), viridisLite(v.0.4.1), fansi(v.1.0.3), pillar(v.1.8.1), lattice(v.0.20-45), loo(v.2.5.1), fastmap(v.1.1.0), httr(v.1.4.4), plotrix(v.3.8-2), pkgbuild(v.1.4.0), glue(v.1.6.2), xts(v.0.12.2), shinythemes(v.1.2.0), class(v.7.3-20), stringi(v.1.7.12), sass(v.0.4.4), rnoaa(v.1.3.8), e1071(v.1.7-12) and maptree(v.1.4-8)


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

  2. I would like to thank J. Kong (Trinity College Dublin) for showing me the way of Rmarkdown.↩︎

LS0tCnRpdGxlOiAiT3BlbiBoYWJpdGF0cyBpbmNyZWFzZSB2dWxuZXJhYmlsaXR5IG9mIGFtcGhpYmlhbiB0YWRwb2xlcyB0byBjbGltYXRlIHdhcm1pbmcgYWNyb3NzIGxhdGl0dWRlIgpzdWJ0aXRsZTogIlN1cHBsZW1lbnRhcnkgSW5mb3JtYXRpb24iCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVkLyVtLyVZJylgIgphdXRob3I6CiAgLSBOaWNob2xhcyBDLiBXdV5bSGF3a2VzYnVyeSBJbnN0aXR1dGUgZm9yIHRoZSBFbnZpcm9ubWVudCwgV2VzdGVybiBTeWRuZXkgVW5pdmVyc2l0eSwgTlNXIDI3NTMsIEF1c3RyYWxpYSwgbmljaG9sYXMud3UubnpAZ21haWwuY29tXQpvdXRwdXQ6CiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOgogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwplZGl0b3Jfb3B0aW9uczoKICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQpjc2w6IC4vYmliL3RoZS1qb3VybmFsLW9mLWV4cGVyaW1lbnRhbC1iaW9sb2d5LmNzbApiaWJsaW9ncmFwaHk6IC4vYmliL3d0X3JlZi5iaWJ0ZXgKbGluay1jaXRhdGlvbnM6IHRydWUKLS0tCltHaXRIdWIgUmVwb3NpdG9yeV0oaHR0cHM6Ly9naXRodWIuY29tL25pY2hvbGFzd3Vuei90YWRwb2xlLXRoZXJtYWwtdG9sZXJhbmNlKSAgClRoZSBSbWFya2Rvd24gZmlsZSBjYW4gYmUgZG93bmxvYWRlZCBmcm9tIHRoZSAqQ29kZSogZHJvcCBkb3duIG1lbnUgKHRvcCByaWdodCkuXltJIHdvdWxkIGxpa2UgdG8gdGhhbmsgSi4gS29uZyAoVHJpbml0eSBDb2xsZWdlIER1YmxpbikgZm9yIHNob3dpbmcgbWUgdGhlIHdheSBvZiBSbWFya2Rvd24uXQoKVGhpcyBzdXBwbGVtZW50YXJ5IGZpbGUgY29udGFpbnMgdGhlICpSKiB3b3JrZmxvdyBmb3IgcHJvY2Vzc2luZyBhbmQgYW5hbHlzaW5nIHRoZSByYXcgZGF0YSwgYW5kIGNyZWF0aW5nIGZpZ3VyZXMgZm9yIHRoZSBtYW51c2NyaXB0IElEOiBHRUItMjAyMi0wMjY4IHRpdGxlZCAiKipPcGVuIGhhYml0YXRzIGluY3JlYXNlIHZ1bG5lcmFiaWxpdHkgb2YgYW1waGliaWFuIHRhZHBvbGVzIHRvIGNsaW1hdGUgd2FybWluZyBhY3Jvc3MgbGF0aXR1ZGUqKiIuCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKa25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFKQoKbGlicmFyeShnZ3Bsb3QyKSAjIHVzZSBnZ3Bsb3QyIG1ldGhvZCBvZiBwbG90dGluZwpsaWJyYXJ5KGNvd3Bsb3QpICMgb3JnYW5pc2UgZmlndXJlcwpsaWJyYXJ5KE1hdHJpeCkKbGlicmFyeSh0aWR5dmVyc2UpIApsaWJyYXJ5KGNvbG9yc3BhY2UpCmxpYnJhcnkoYnJtcykKbGlicmFyeShyc3RhbikKbGlicmFyeShhcGUpCmxpYnJhcnkocGh5dG9vbHMpCmxpYnJhcnkoZGl2ZXJzaXRyZWUpCmxpYnJhcnkoTmljaGVNYXBSKQpsaWJyYXJ5KHBhbmRlcikKb3B0aW9ucyhkcGx5ci53aWR0aCA9IEluZiwga25pdHIua2FibGUuTkEgPSAiIikKCiMgRnVuY3Rpb25zCm15dGhlbWUgPC0gZnVuY3Rpb24oKSB7CiAgdGhlbWVfYncoKSArIAogICAgdGhlbWUocGFuZWwuYm9yZGVyICAgICAgICAgID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3VyID0gImJsYWNrIiksICMgc2V0IGJvcmRlciBhcm91bmQgcGxvdC4KICAgICAgICAgIHBhbmVsLmdyaWQubWFqb3IgICAgICA9IGVsZW1lbnRfYmxhbmsoKSwgIyByZW1vdmUgbWFqb3IgZ3JpZCBsaW5lcwogICAgICAgICAgcGFuZWwuZ3JpZC5taW5vciAgICAgID0gZWxlbWVudF9ibGFuaygpLCAjIHJlbW92ZSBtaW5vciBncmlkIGxpbmVzCiAgICAgICAgICBheGlzLmxpbmUgICAgICAgICAgICAgPSBlbGVtZW50X2JsYW5rKCksICMgcmVtb3ZlIGF4aXMgbGluZXMKICAgICAgICAgIGF4aXMudGlja3MgICAgICAgICAgICA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICAgIGF4aXMudGV4dCAgICAgICAgICAgICA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ICJibGFjayIpLCAjIGF4aXMgdGV4dCBzaXplCiAgICAgICAgICBheGlzLnRpdGxlICAgICAgICAgICAgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgIyBheGlzIHRpdGxlIHNpemUKICAgICAgICAgIHBsb3Quc3VidGl0bGUgICAgICAgID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksICMgYXhpcyB0aXRsZSBzaXplCiAgICAgICAgICBheGlzLnRpdGxlLnkgICAgICAgICAgPSBlbGVtZW50X3RleHQodmp1c3QgPSAzKSwgIyBpbmNyZWFzZSBkaXN0YW5jZSBmcm9tIHRoZSB5LWF4aXMKICAgICAgICAgIGF4aXMudGl0bGUueCAgICAgICAgICA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IC0xKSwgIyBpbmNyZWFzZSBkaXN0YW5jZSBmcm9tIHRoZSB4LWF4aXMKICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgICAgICA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLAogICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kICAgICAgID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3IgPSBOQSksICMgcmVtb3ZlIGJhY2tncm91bmQgY29sb3VyCiAgICAgICAgICBwbG90Lm1hcmdpbiAgICAgICAgICAgPSB1bml0KGMoMC4yLCAwLjIsIDAuMiwgMC4yKSwgdW5pdHMgPSAsICJjbSIpLCAKICAgICAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kICAgICA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEsIGNvbG9yID0gTkEpLCAjIGdldCByaWQgb2YgbGVnZW5kIGJnCiAgICAgICAgICBsZWdlbmQuYm94LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BLCBjb2xvciA9IE5BKSwgIyBnZXQgcmlkIG9mIGxlZ2VuZCBwYW5lbCBiZwogICAgICAgICAgc3RyaXAudGV4dC54ICAgICAgICAgID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3IgPSAiYmxhY2siLCBmYWNlID0gImJvbGQiKSwgIyBmb3IgZmFjZXQgcGxvdHMKICAgICAgICAgIHN0cmlwLmJhY2tncm91bmQgICAgICA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEsIGNvbG9yID0gTkEpCiAgICApCn0gIyBzZXQgdXAgcGxvdCB0aGVtZQoKU3RhdE1lYW5MaW5lIDwtIGdncHJvdG8oIlN0YXRNZWFuTGluZSIsIFN0YXQsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXB1dGVfZ3JvdXAgPSBmdW5jdGlvbihkYXRhLCBzY2FsZXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0oZGF0YSwgeWludGVyY2VwdCA9IG1lYW4oeSkpCiAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkX2FlcyA9IGMoIngiLCAieSIpKQoKc3RhdF9tZWFuX2xpbmUgPC0gZnVuY3Rpb24obWFwcGluZyAgPSBOVUxMLCBkYXRhID0gTlVMTCwgZ2VvbSA9ICJobGluZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImlkZW50aXR5IiwgbmEucm0gPSBGQUxTRSwgc2hvdy5sZWdlbmQgPSBOQSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gVFJVRSwgLi4uKSB7CiAgbGF5ZXIoCiAgICBzdGF0ID0gU3RhdE1lYW5MaW5lLCBkYXRhID0gZGF0YSwgbWFwcGluZyA9IG1hcHBpbmcsIGdlb20gPSBnZW9tLCAKICAgIHBvc2l0aW9uID0gcG9zaXRpb24sIHNob3cubGVnZW5kID0gc2hvdy5sZWdlbmQsIGluaGVyaXQuYWVzID0gaW5oZXJpdC5hZXMsCiAgICBwYXJhbXMgPSBsaXN0KG5hLnJtID0gbmEucm0sIC4uLikKICApCn0KCmZvcm1hdF9jZWxscyAgIDwtIGZ1bmN0aW9uKGRmLCByb3dzICxjb2xzLCB2YWx1ZSA9IGMoIml0YWxpY3MiLCAiYm9sZCIsICJzdHJpa2V0aHJvdWdoIikpewogICMgc2VsZWN0IHRoZSBjb3JyZWN0IG1hcmt1cAogICMgb25lICogZm9yIGl0YWxpY3MsIHR3byAqKiBmb3IgYm9sZAogIG1hcCA8LSBzZXROYW1lcyhjKCIqIiwgIioqIiwgIn5+IiksIGMoIml0YWxpY3MiLCAiYm9sZCIsICJzdHJpa2V0aHJvdWdoIikpCiAgbWFya3VwIDwtIG1hcFt2YWx1ZV0gIAogIGZvciAociBpbiByb3dzKXsKICAgIGZvcihjIGluIGNvbHMpewogICAgICAjIE1ha2Ugc3VyZSB2YWx1ZXMgYXJlIG5vdCBmYWN0b3JzCiAgICAgIGRmW1tjXV0gPC0gYXMuY2hhcmFjdGVyKCBkZltbY11dKQogICAgICAjIFVwZGF0ZSBmb3JtYXR0aW5nCiAgICAgIGRmW3IsIGNdIDwtIHBhc3RlMChtYXJrdXAsIGRmW3IsIGNdLCBtYXJrdXApCiAgICB9CiAgfQogIHJldHVybihkZikKfQoKYWRkcGFyZW50aGVzZXMgPC0gZnVuY3Rpb24oeCl7cGFzdGUoIigiLCB4LCAiKSIpfQoKIyBTZXQgb3B0aW9ucyBpbiBSc3Rhbgpyc3Rhbl9vcHRpb25zKGF1dG9fd3JpdGUgPSBUUlVFKSAjIHRyYW5zbGF0ZSB0byBTVEFOIHBsYXRmb3JtIGZvciBydW5uaW5nIEJheWVzaWFuIG1vZGVsCm9wdGlvbnMobWMuY29yZXMgPSBwYXJhbGxlbDo6ZGV0ZWN0Q29yZXMoKSkgIyBkZXRlY3RzIGhvdyBtYW55IGNvcmVzIGF2YWlsYWJsZSB0byB1c2UKYGBgCgoqKioKCiMgUG9uZCB0aGVybW9keW5hbWljIG1vZGVsCgpXYXRlciB0ZW1wZXJhdHVyZSBpcyBjb21wdXRlZCBiYXNlZCBvbiBhIGhlYXQgYnVkZ2V0IGNvbnNpZGVyaW5nIGxvbmd3YXZlIHJhZGlhdGlvbiwgc29sYXIgaGVhdGluZywgYW5kIHN0YW5kYXJkIGJ1bGsgYWVyb2R5bmFtaWMgZmx1eCBwYXJhbWV0ZXJpemF0aW9ucyBmb3Igc2Vuc2libGUgYW5kIGxhdGVudCBoZWF0IFtATWl0Y2hlbGwyMDEyXS4gVGhlIGJ1ZGdldCBpcyBkcml2ZW4gYnkgZnVuZGFtZW50YWwgbWV0ZW9yb2xvZ2ljYWwgY29uZGl0aW9ucyBwcm92aWRlZCBpbiB0aGUgbWljcm9jbGltYXRlIG1vZGVsIG9mICpOaWNoZU1hcFIqIFtATmljaGVNYXBSXSwgc3BlY2lmaWMgdG8gZWFjaCBzaXRlLCB3aXRoIHRoZSBFcXVhdGlvbiBcQHJlZihlcTptaWNybykuCgpcYmVnaW57ZXF1YXRpb259CihMcF93XCBjX3ApXCBcIFxmcmFje2RUX3d9e2R0fT1wX3dcIGNfcFwgKElcIFRfaS1PXCBUX3crUlwgVF97c2t5fUFfTFwgKSsoSC1FLVMrXHBoaV97TFd9ICtccGhpX3tTV30pXCBBX0wKKFwjZXE6bWljcm8pClxlbmR7ZXF1YXRpb259Cgp3aGVyZSAkVF93JCBpcyB0aGUgbGFrZSB0ZW1wZXJhdHVyZSwgJFRfaSQgaXMgdGhlIGluZmxvdyB0ZW1wZXJhdHVyZSwgJFRfe3NreX0kIGlzIHRoZSBhaXIgdGVtcGVyYXR1cmUgKGFsbCBpbiDCsEspLCAkcF93JCBpcyB0aGUgZGVuc2l0eSBvZiB3YXRlciAoa2cgbV4tM14pLCAkY19wJCBpcyB0aGUgc3BlY2lmaWMgaGVhdCBjYXBhY2l0eSBvZiB3YXRlciAoSiBrZ14tMV4gS14tMV4pLCAkTCQgaXMgdGhlIGxha2Ugdm9sdW1lIChtXi0zXikgYW5kICRJJCwgJE8kLCBhbmQgKCRBX0xcIFIkKSBhcmUgdGhlIGluZmxvdywgb3V0ZmxvdyBhbmQgcmFpbmZhbGwgdm9sdW1lIGZsdXhlcyByZXNwZWN0aXZlbHkgKG1eLTNeIGReLTFeKSwgd2hlcmUgJEFfTCQgaXMgdGhlIGxha2Ugc3VyZmFjZSBhcmVhIChtXi0yXikgdXNlZCB0byBtdWx0aXBseSB0aGUgcmFpbmZhbGwgZGVwdGggKG0gZF4tMV4pLiAkSCQgXEByZWYoZXE6SCksICRFJCBcQHJlZihlcTpFKSwgJFMkIFxAcmVmKGVxOlMpIGFyZSBoZWF0IGZsdXhlcyAoVyBtXi0yXikgZm9yIHNlbnNpYmxlIGhlYXQsIGV2YXBvcmF0aXZlIGFuZCBzb2lsIGhlYXQgY29uZHVjdGlvbiwgcmVzcGVjdGl2ZWx5LCBjYWxjdWxhdGVkIGFjY29yZGluZyB0bzoKClxiZWdpbntlcXVhdGlvbn0KSD1wX2FcIGNfcFwgQ19IXCB1XzIgKFRfe3NreX0tVF93KQooXCNlcTpIKQpcZW5ke2VxdWF0aW9ufQoKXGJlZ2lue2VxdWF0aW9ufQpFPXBfYVwgXGxhbWJkYVwgQ19FXCB1XzJcIChlX3MtZV9hKQooXCNlcTpFKQpcZW5ke2VxdWF0aW9ufQoKXGJlZ2lue2VxdWF0aW9ufQpTPVxmcmFje0NfU317el9zfShUX3MtVF93KQooXCNlcTpTKQpcZW5ke2VxdWF0aW9ufQoKd2hlcmUgJENfSCQgYW5kICRDX0UkIGFyZSBidWxrIHRyYW5zZmVyIGNvZWZmaWNpZW50cyBmb3Igc2Vuc2libGUgYW5kIGxhdGVudCBoZWF0IHJlc3BlY3RpdmVseSAoLSksICRcbGFtYmRhJCBpcyB0aGUgbGF0ZW50IGhlYXQgb2YgdmFwb3JpemF0aW9uIChKIGtnXi0xXiksICRwX2EkIGlzIHRoZSBkZW5zaXR5IG9mIGFpciAoa2cgbV4tM14pLCBhbmQgJENfUyQgaXMgdGhlIGRpZmZ1c2l2aXR5IG9mIGhlYXQgaW50byB0aGUgc29pbCBiZWxvdyB0aGUgd2F0ZXIgKFcgbV4tMV4gS14tMV4pLCBhbmQgJHpfcyQgaXMgdGhlIGFjdGl2ZSBzb2lsIGRlcHRoIG92ZXIgd2hpY2ggaGVhdCBkaWZmdXNpb24gb2NjdXJzLiAkXHBoaV97TFd9JCBcQHJlZihlcTpsdykgaXMgdGhlIG5ldyBsb25nd2F2ZSByYWRpYXRpb24gKFcgbV4tMl4pIGFuZCAkXHBoaV97U1d9JCBcQHJlZihlcTpzdykgaXMgdGhlIHNvbGFyIGluc29sYXRpb24gKFcgbV4tMl4pLCBjYWxjdWxhdGVkIGZyb206CgpcYmVnaW57ZXF1YXRpb259ClxwaGlfe0xXfT1cdmFyZXBzaWxvbl9hXCBcc2lnbWEoVF97c2t5fSleNC1cdmFyZXBzaWxvbl93XCBcc2lnbWEoVF93KV40CihcI2VxOmx3KQpcZW5ke2VxdWF0aW9ufQoKXGJlZ2lue2VxdWF0aW9ufQpccGhpX3tTV309KDEtXGFscGhhKVwge1xoYXR7XHBoaX19X3tTV31cYmlnZ1tcZnJhY3tBX0x9e0Ffe01BWH19XCBrX3MgXGJpZ2ddCihcI2VxOnN3KQpcZW5ke2VxdWF0aW9ufQoKd2hlcmUgJFx2YXJlcHNpbG9uJCBpcyB0aGUgZW1pc3Npdml0eSBvZiBhaXIgb3Igd2F0ZXIsICRcc2lnbWEkIGlzIHRoZSBTdGVmYW4tQm9sdHptYW5uIGNvbnN0YW50LCAkXGFscGhhJCBpcyB0aGUgc2hvcnR3YXZlIHJhZGlhdGlvbiBhbGJlZG8sICR7XGhhdHtccGhpfX1fe1NXfSQgaXMgdGhlIGluY2lkZW50IHNvbGFyIHJhZGlhdGlvbiBhYm92ZSB2ZWdldGF0aW9uIChXIG1eLTJeKS4gVGhlIGxhc3QgdGVybSBcQHJlZihlcTpzdykgYWNjb3VudHMgZm9yIHRoZSBlZmZlY3Qgb2Ygd2V0bGFuZCB2ZWdldGF0aW9uIHNoYWRpbmcgb24gdGhlIGluY2lkZW50IHNvbGFyIGludGVuc2l0eSwgd2l0aCAka19zJCBkZWZpbmVkIGFzIGEgY29uc3RhbnQgdG8gaW5jcmVhc2UgdGhlIHNoYWRpbmcgZWZmZWN0LCBhbmQgJEFfe01BWH0kIGlzIHRoZSBtYXhpbXVtIGFyZWEgb2YgaW51bmRhdGlvbiBleHRlbnQgKG1eLTJeKS4gSW4gKk5pY2hlTWFwUiosIGFzc3VtZWQgdmFsdWVzIGZvciAkQ19TJCwgJENfSCQsICRDX0UkLCAkXHZhcmVwc2lsb25fYSQsICRrX3MkIHdlcmUgMC41LCAwLjAwMTMsIDAuMDAxMywgMC45OSBhbmQgMC4yNSwgcmVzcGVjdGl2ZWx5LgoKKioqCgojIERhdGFzZXQKCiMjIFByZXBhcmUgcmF3IGRhdGEgZm9yIGFuYWx5c2lzCgpUaGUgcmF3IGRhdGEgZm9yIGFuYWx5c2lzIGlzIGF2YWlsYWJsZSBvbiBbR2l0SHViXShodHRwczovL2dpdGh1Yi5jb20vbmljaG9sYXN3dW56L3RhZHBvbGUtdGhlcm1hbC10b2xlcmFuY2UpLiBUaGlzIHNlY3Rpb24gaXMgdGhlIGltcG9ydCBhbmQgY2xlYW4gdGhlIHJhdyBkYXRhIGZvciBhbmFseXNpcy4KCmBgYHtyIGNsZWFufQojIENsZWFuIHJhdyBkYXRhCmNsZWFuX2RhdCA8LSByZWFkLmNzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL25pY2hvbGFzd3Vuei90YWRwb2xlLXRoZXJtYWwtdG9sZXJhbmNlL21haW4vZGF0YS9yYXdfZGF0YS5jc3YiLCBuYS5zdHJpbmdzID0gYygiIiAsICJOQSIgKSwgc3RyaW5nc0FzRmFjdG9ycyA9IFRSVUUpICU+JQogIGRwbHlyOjptdXRhdGUoV1QgICAgICAgICAgID0gQ1RtYXggLSBUbWF4LAogICAgICAgICAgICAgICAgcmVnaW9uICAgICAgID0gZmFjdG9yKHJlZ2lvbiwgbGV2ZWxzID0gYygnU3VidHJvcGljcycsICdUZW1wZXJhdGUnKSksCiAgICAgICAgICAgICAgICBjb3VudHJ5ICAgICAgPSBhcy5mYWN0b3IoY291bnRyeSksCiAgICAgICAgICAgICAgICBoYWJpdGF0ICAgICAgPSBhcy5mYWN0b3IoY29sbGVjdGlvbl9oYWJpdGF0KSwKICAgICAgICAgICAgICAgIHNwZWNpZXNfdHJlZSA9IGdzdWIoIiAiLCAiXyIsIHNwZWNpZXMpKQoKIyBTdW1tYXJpc2UgZGF0YSBieSBncm91cApzdW1tYXJ5X2RhdCA8LSBhcy5kYXRhLmZyYW1lKGNsZWFuX2RhdCAlPiUKICBkcGx5cjo6Z3JvdXBfYnkocmVnaW9uLCBjb3VudHJ5LCBoYWJpdGF0LCBmYW1pbHksIHNwZWNpZXMsIHNwX2FiYnIsIHNwZWNpZXNfdHJlZSwgYnJlZWRpbmdfaGFiaXRhdCwgY2l0YXRpb24pICU+JQogIGRwbHlyOjpzdW1tYXJpc2UobG9uICAgICAgICA9IG1lYW4obG9uKSwKICAgICAgICAgICAgICAgICAgIGxhdCAgICAgICAgPSBtZWFuKGxhdCksCiAgICAgICAgICAgICAgICAgICBDVG1heF9tZWFuID0gbWVhbihDVG1heCksCiAgICAgICAgICAgICAgICAgICBDVG1heF9TRCAgID0gc2QoQ1RtYXgpLAogICAgICAgICAgICAgICAgICAgVG1heCAgICAgICA9IG1lYW4oVG1heCksCiAgICAgICAgICAgICAgICAgICBXVF9tZWFuICAgID0gbWVhbihXVCksCiAgICAgICAgICAgICAgICAgICBXVF9TRCAgICAgID0gc2QoV1QpLAogICAgICAgICAgICAgICAgICAgbiAgICAgICAgICA9IG4oKSwKICAgICAgICAgICAgICAgICAgIG1vbnRoX3N0YXJ0ID0gbWVhbihtb250aF9zdGFydCksCiAgICAgICAgICAgICAgICAgICBtb250aF9lbmQgICA9IG1lYW4obW9udGhfZW5kKSkpICU+JQogIGRwbHlyOjpyZWxvY2F0ZShjKGJyZWVkaW5nX2hhYml0YXQsIGNpdGF0aW9uKSwgLmFmdGVyID0gbGFzdF9jb2woKSkKYGBgCgojIyBTcGVjaWVzIGRhdGEgc3VtbWFyeSB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30gCgojIyMgVGFibGUgUzFhIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKKipUYWJsZSBTMS4qKiBMaXN0IG9mIHNwZWNpZXMgaW5jbHVkZWQgaW4gdGhlIHN0dWR5IHdpdGggdGhlaXIgc2FtcGxlIHNpemUgKCpuKiksIG1lYW4gwrEgcy5kLiBjcml0aWNhbCB0aGVybWFsIG1heGltYSAoQ1R+bWF4fiksIG1heGltdW0gZW52aXJvbm1lbnRhbCB3YXRlciB0ZW1wZXJhdHVyZSAoVH5tYXh+KSwgaGFiaXRhdCB0eXBlIGJhc2VkIG9uIGNvbGxlY3Rpb24gc2l0ZSwgYW5kIHNwYXRpYWwgY29vcmRpbmF0ZXMgKGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgYXMgZGVjaW1hbCBkZWdyZWUpLgoKYGBge3IgdGFibGVTMWEsIGVjaG89RkFMU0V9CnRhYmxlUzEgPC0gc3VtbWFyeV9kYXQgJT4lCiAgZm9ybWF0X2NlbGxzKDE6MjksIDUsICJpdGFsaWNzIikgJT4lCiAgZHBseXI6Om11dGF0ZShDVG1heF9tZWFuID0gZm9ybWF0KHJvdW5kKENUbWF4X21lYW4sIDIpLCBuc21hbGwgPSAyKSwKICAgICAgICAgICAgICAgIENUbWF4X1NEICAgPSBmb3JtYXQocm91bmQoQ1RtYXhfU0QsIDIpLCBuc21hbGwgPSAyKSwKICAgICAgICAgICAgICAgIFRtYXggICAgICAgPSBmb3JtYXQocm91bmQoVG1heCwgMiksIG5zbWFsbCA9IDIpLAogICAgICAgICAgICAgICAgQ1RtYXggICAgICA9IHBhc3RlKENUbWF4X21lYW4sIENUbWF4X1NELCBzZXAgPSAiwrEiKSwKICAgICAgICAgICAgICAgIHNwX2FiYnIgICAgPSBnc3ViKCIgIiwgIiIsIGFkZHBhcmVudGhlc2VzKHNwX2FiYnIpKSwKICAgICAgICAgICAgICAgIHNwZWNpZXMgICAgPSBwYXN0ZShzcGVjaWVzLCBzcF9hYmJyLCBzZXAgPSAiICIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KHNwZWNpZXMsIG4sIENUbWF4LCBUbWF4LCBoYWJpdGF0LCBsYXQsIGxvbikKCiMgUHJlcGFyZSBjb2x1bW4gbmFtZXMgd2l0aCBMYVRlWAp0YWJsZVMxICU+JQogIGRwbHlyOjpyZW5hbWUoIlNwZWNpZXMgKGFiYnJldmlhdGlvbikiID0gc3BlY2llcywKICAgICAgICAgICAgICAgICJDVH5tYXh+IMKxIHMuZC4gKMKwQykiICAgID0gQ1RtYXgsCiAgICAgICAgICAgICAgICBuICAgICAgICAgICAgICAgICAgICAgICAgPSBuLAogICAgICAgICAgICAgICAgIlR+bWF4fiAowrBDKSIgICAgICAgICAgICA9IFRtYXgsCiAgICAgICAgICAgICAgICAiQ29sbGVjdGlvbiBoYWJpdGF0IiAgICAgPSBoYWJpdGF0LAogICAgICAgICAgICAgICAgTGF0aXR1ZGUgICAgICAgICAgICAgICAgID0gbGF0LAogICAgICAgICAgICAgICAgTG9uZ2l0dWRlICAgICAgICAgICAgICAgID0gbG9uKSAlPiUKICBrbml0cjo6a2FibGUoZGlnaXRzID0gMykgIyAzIGRlY2ltYWwgcGxhY2VzCmBgYAoKKiAqQnVmbyBnYXJnYXJpemFucyogd2FzIHJlY2VudGx5IHJlbmFtZWQgdG8gKkJ1Zm8gc2NoYWxpbmVuc2lzKiBbQE90aG1hbjIwMjJdLgoKCiMjIyBUYWJsZSBTMWIgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHMgLX0gCgoqKlRhYmxlIFMxLioqIENvbnRpbnVhdGlvbiBvZiBzcGVjaWVzIHN1bW1hcnkgd2l0aCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIG9uIEZhbWlseSwgYW5kIG5vdGVzIG9uIHRoZSBzcGVjaWVzIHR5cGljYWwgYnJlZWRpbmcgaGFiaXRhdCBiYXNlZCBvbiB0aGUgYXNzb2NpYXRlZCByZWZlcmVuY2VzLiBTcGVjaWVzIGdyb3VwZWQgYXMgZm9yZXN0IHByaW1hcmlseSBicmVlZCBpbiBmb3Jlc3QgaGFiaXRhdHMuIFNwZWNpZXMgZ3JvdXBlZCBhcyBmb3Jlc3QgZWRnZSB0eXBpY2FsbHkgYnJlZWQgYXQgdGhlIGVkZ2VzIG9mIGZvcmVzdHMgKG1vcmUgZXhwb3N1cmUgdG8gc3VubGlnaHQpLiBTcGVjaWVzIGdyb3VwZWQgYXMgb3BlbiBwcmltYXJpbHkgYnJlZWQgaW4gb3BlbiBoYWJpdGF0cy4gU3BlY2llcyBncm91cGVkIGFzIGdlbmVyYWxpc3QgdHlwaWNhbGx5IGJyZWVkIGluIGJvdGggZm9yZXN0IGFuZCBvcGVuIGhhYml0YXRzLiAKCmBgYHtyIHRhYmxlUzFiLCBlY2hvPUZBTFNFfQpzdW1tYXJ5X2RhdCAlPiUKICBmb3JtYXRfY2VsbHMoMToyOSwgNSwgIml0YWxpY3MiKSAlPiUKICBkcGx5cjo6c2VsZWN0KGZhbWlseSwgc3BlY2llcywgYnJlZWRpbmdfaGFiaXRhdCwgY2l0YXRpb24pICU+JQogIGRwbHlyOjpyZW5hbWUoIkZhbWlseSIgPSBmYW1pbHksCiAgICAgICAgICAgICAgICAiU3BlY2llcyIgPSBzcGVjaWVzLAogICAgICAgICAgICAgICAgIkJyZWVkaW5nIGhhYml0YXQiID0gYnJlZWRpbmdfaGFiaXRhdCwKICAgICAgICAgICAgICAgICJDaXRhdGlvbiIgPSBjaXRhdGlvbikgJT4lCiAga25pdHI6OmthYmxlKCkgIyAzIGRlY2ltYWwgcGxhY2VzCmBgYAoKKiAqQnVmbyBnYXJnYXJpemFucyogd2FzIHJlY2VudGx5IHJlbmFtZWQgdG8gKkJ1Zm8gc2NoYWxpbmVuc2lzKiBbQE90aG1hbjIwMjJdLiAgCiogUmVmZXJlbmNlIGxpc3Q6IEBBbWJ1MjAyMiwgQENoYW5nMjAxNCwgQEhvdTIwMDgsIEBIc3UyMDEyLCBASHVhbmcxOTk2LCBASHVhbmcxOTk3LCBASHVhbmcyMDA0LCBASmFuZy1MaWF3MTAwOSwgQEp1bmcyMDEzLCBAS2FtMTk5NSwgQEt1YW4yMDExLCBATGFpMjAwNywgQExpbjIwMTIsIEBMaW4yMDA4LCBATWF0c3VpMjAxOCwgQFJvaDIwMTQsIEBUb21pbmFnYTIwMTUsIEBXdTIwMTYsIEBZYW5nMjAwMSwgQFlvbzIwMTkuCgoqKioKCiMgUGh5bG9nZW55CgojIyBTcGVjaWVzIGFzY2Vuc2lvbiBnZW5lIG51bWJlcgoKKipUYWJsZSBTMi4qKiBBY2Nlc3Npb24gbnVtYmVyIG9mIGdlbmVzIG9mIGFsbCBzcGVjaWVzIChpbmdyb3VwcyBhbmQgb3V0Z3JvdXBzKSBpbiB0aGUgYW5hbHlzaXMgZnJvbSB0aGUgTmF0aW9uYWwgQ2VudGVyIGZvciBCaW90ZWNobm9sb2d5IEluZm9ybWF0aW9uIChbTkNCSV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi8pKS4KCmBgYHtyIHRhYmxlUzIsIGVjaG89RkFMU0V9CmFuX2RhdCA8LSByZWFkLmNzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL25pY2hvbGFzd3Vuei90YWRwb2xlLXRoZXJtYWwtdG9sZXJhbmNlL21haW4vYWNjZXNzaW9uX251bWJlci5jc3YiLCBuYS5zdHJpbmdzID0gYygiIiAsICJOQSIgKSwgc3RyaW5nc0FzRmFjdG9ycyA9IFRSVUUpCgojIEluZ291cAppbmdyb3VwIDwtIGFuX2RhdCAlPiUgCiAgZHBseXI6OmZpbHRlcihncm91cCA9PSAiSW5ncm91cCIpICU+JQogIGFzLmRhdGEuZnJhbWUoLikgJT4lCiAgdGliYmxlOjphZGRfcm93KFNwZWNpZXMgPSAiKkluZ3JvdXAqIiwgLmJlZm9yZSA9IDEpICU+JQogIGRwbHlyOjpzZWxlY3QoLWdyb3VwKQoKIyBPdXRncm91cApvdXRncm91cCA8LSBhbl9kYXQgJT4lIAogIGRwbHlyOjpmaWx0ZXIoZ3JvdXAgPT0gIk91dGdyb3VwIikgJT4lCiAgYXMuZGF0YS5mcmFtZSguKSAlPiUKICB0aWJibGU6OmFkZF9yb3coU3BlY2llcyA9ICIqT3V0Z3JvdXAqIiwgLmJlZm9yZSA9IDEpICU+JQogIGRwbHlyOjpzZWxlY3QoLWdyb3VwKQoKIyBSZW5kZXIgdGFibGUKYmluZF9yb3dzKGluZ3JvdXAsIG91dGdyb3VwKSAlPiUgCiAgcmVtb3ZlX3Jvd25hbWVzKCkgJT4lCiAgZHBseXI6OnJlbmFtZSgiMTJTIiA9ICJYMTJTIiwKICAgICAgICAgICAgICAgICIxNlMiID0gIlgxNlMiKSAlPiUKICBmb3JtYXRfY2VsbHMoMTozNCwgMSwgIml0YWxpY3MiKSAlPiUKICBrbml0cjo6a2FibGUoKQpgYGAKCiMjIFByZXBhcmUgcGh5bG9nZW55IGZvciBhbmFseXNpcwoKVGhpcyBzZWN0aW9uIGlzIHRoZSBpbXBvcnQgdGhlIHBoeWxvZ2VuZXRpYyB0cmVlIChzZWUgcGh5bG9nZW5ldGljIHJlY29uc3RydWN0aW9uIGluIG1haW4gdGV4dCkgY29tcHJpc2luZyBvZiBgciBucm93KHN1bW1hcnlfZGF0KWAgc3BlY2llcywgbWF0Y2ggbmFtZXMgd2l0aCB0aGUgZGF0YSBzZXQsIGFuZCBjcmVhdGUgYSBjb3JyZWxhdGlvbiBtYXRyaXggZm9yIHN1YnNlcXVlbnQgYW5hbHlzaXMuCgpgYGB7ciBwaHlsb30KIyBMb2FkIHBoeWxvZ2VueSBkYXRhCnBoeWxvX3RyZWUgPC0gYXBlOjpyZWFkLnRyZWUoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9uaWNob2xhc3d1bnovdGFkcG9sZS10aGVybWFsLXRvbGVyYW5jZS9tYWluL2RhdGEvdHJlZTIwMjFfMTIubndrIikKCnRyZWVfdGlwX2xhYmVsIDwtIHBoeWxvX3RyZWUkdGlwLmxhYmVsICMgZXh0cmFjdCB0cmVlIHRpcCBuYW1lcwpzcGVjaWVzX2xpc3QgICA8LSB1bmlxdWUoY2xlYW5fZGF0JHNwZWNpZXNfdHJlZSkgIyBleHRyYWN0IHNwZWNpZXMgbmFtZSBmcm9tIG1haW4gZGF0YXNldAptaXNzaW5nX3NwICAgICA8LSBhcy5kYXRhLmZyYW1lKHNldGRpZmYodHJlZV90aXBfbGFiZWwsIHNwZWNpZXNfbGlzdCkpICMgY2hlY2sgd2hhdCBuYW1lcyBmcm9tIHRoZSBkYXRhc2V0IG5vdCBmb3VuZCBpbiBwaHlsb190cmVlCiMgVGhyZWUgb3V0Z3JvdXBzIGluIHRyZWUKCnBydW5lZF90cmVlICAgIDwtIGFwZTo6ZHJvcC50aXAocGh5bG9fdHJlZSwgc2V0ZGlmZihwaHlsb190cmVlJHRpcC5sYWJlbCwgc3BlY2llc19saXN0KSkgIyBwcnVuZSBwaHlsb190cmVlIHRvIGtlZXAgc3BlY2llcyBmcm9tIHRoZSBtYWluIGRhdGFzZXQKCiMgY2hlY2sgaWYgbGVuZ3RocyBtYXRjaCBmb3IgYm90aCBkYXRhIGFuZCB0cmVlCnNwX24gPC0gbGVuZ3RoKHVuaXF1ZShwcnVuZWRfdHJlZSR0aXAubGFiZWwpKSAjIDI5CiNsZW5ndGgodW5pcXVlKGNsZWFuX2RhdCRzcGVjaWVzX3RyZWUpKSAjIDI5CgojIENoZWNrIGZvciBwb2x5dG9taWVzCiNhcGU6OmlzLmJpbmFyeShwcnVuZWRfdHJlZSkgIyBUUlVFCgojIENvbXB1dGUgYnJhbmNoIGxlbmd0aHMKcHJ1bmVkX3RyZWVfY2FsIDwtIGFwZTo6Y29tcHV0ZS5icmxlbihwcnVuZWRfdHJlZSwgbWV0aG9kID0gIkdyYWZlbiIsIHBvd2VyID0gMSkKI2FwZTo6aXMudWx0cmFtZXRyaWMocHJ1bmVkX3RyZWVfY2FsKSAjIFRSVUUKCiMgQ3JlYXRlIGNvcnJlbGF0aW9uIG1hdHJpeCBmb3IgYW5hbHlzaXMKcGh5bG9fY29yIDwtIHZjdihwcnVuZWRfdHJlZV9jYWwsIGNvciA9IFQpCmBgYAoKCmBgYHtyIEZpZyBTMSwgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD02LCBtZXNzYWdlPUZBTFNFfQpjbGVhbl9kYXQkc3BlY2llc190cmVlIDwtIGZhY3RvcihjbGVhbl9kYXQkc3BlY2llc190cmVlLCBsZXZlbHMgPSBwcnVuZWRfdHJlZSR0aXAubGFiZWwpCnRyYWl0X2RhdCAgICAgICAgICAgICAgPC0gc3VtbWFyeV9kYXQgJT4lIGByb3cubmFtZXM8LWAoLiwgTlVMTCkgJT4lIHRpYmJsZTo6Y29sdW1uX3RvX3Jvd25hbWVzKHZhciA9ICdzcGVjaWVzX3RyZWUnKQoKIyBDVG1heCBwaHlsb2dlbmV0aWMgcmVsYXRpb25zaGlwIApjdG1heF9tZWFuICAgICA8LSBzZXROYW1lcyh0cmFpdF9kYXQkQ1RtYXhfbWVhbiwgcm93bmFtZXModHJhaXRfZGF0KSkKY3RtYXhfbWVhbl9vYmogPC0gcGh5dG9vbHM6OmNvbnRNYXAocHJ1bmVkX3RyZWVfY2FsLCBjdG1heF9tZWFuLCBwbG90ID0gRkFMU0UpICU+JSBwaHl0b29sczo6c2V0TWFwKGMoIiNmYWUwYzMiLCAiI0UzODU2NiIsICIjOGEyOTQ4IikpCmhhYml0YXQgICAgICAgIDwtIHNldE5hbWVzKHRyYWl0X2RhdCRoYWJpdGF0LCByb3duYW1lcyh0cmFpdF9kYXQpKQoKIyBQbG90IHBoeWxvZ25lZXRpYyB0cmVlCnBoeXRvb2xzOjpkb3RUcmVlKHBydW5lZF90cmVlX2NhbCwgaGFiaXRhdCwKICAgICAgICAgICAgICAgICAgY29sb3JzID0gc2V0TmFtZXMoYygiYmxhY2siLCAid2hpdGUiKSwgYygiRm9yZXN0IiwgIk9wZW4iKSksIGZ0eXBlID0gImkiLCBmc2l6ZSA9IDAuNywgbHdkID0gMSkKCiMgYWRkIGNvbnRNYXAgQ3RtYXgKI25hbWVzKGN0bWF4X21lYW5fb2JqKQpwaHl0b29sczo6cGxvdFNpbW1hcChjdG1heF9tZWFuX29iaiR0cmVlLCAKICAgICAgICAgICAgICAgICAgICAgY29sb3JzICA9IGN0bWF4X21lYW5fb2JqJGNvbHMsCiAgICAgICAgICAgICAgICAgICAgIGFkZCAgICAgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgZnR5cGUgICA9ICJvZmYiLCAKICAgICAgICAgICAgICAgICAgICAgbHdkICAgICA9IDMuNSwKICAgICAgICAgICAgICAgICAgICAgb3V0bGluZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHhsaW0gICAgPSBnZXQoImxhc3RfcGxvdC5waHlsbyIsIGVudmlyID0uUGxvdFBoeWxvRW52KSR4LmxpbSwKICAgICAgICAgICAgICAgICAgICAgeWxpbSAgICA9IGdldCgibGFzdF9wbG90LnBoeWxvIiwgZW52aXIgPS5QbG90UGh5bG9FbnYpJHkubGltKSAlPiUKICBwaHl0b29sczo6YWRkLmNvbG9yLmJhcihsZWcgICAgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHMgICA9IGN0bWF4X21lYW5fb2JqJGNvbHMsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlICA9IGV4cHJlc3Npb24oIkNUIlsibWF4Il1+IijCsEMpIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxpbXMgPSBjKG1pbihjdG1heF9tZWFuX29iaiRsaW0pLCBtYXgoY3RtYXhfbWVhbl9vYmokbGltKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvbXB0ID0gRkFMU0UsIHggPSAwLjUsIHkgPSAtMikKYGBgCgoqKkZpZy4gUzEuKiogUGh5bG9nZW5ldGljIHJlY29uc3RydWN0aW9uIG9mIGFsbCBgciBucm93KHN1bW1hcnlfZGF0KWAgYW1waGliaWFuIHNwZWNpZXMgdXNlZCBpbiB0aGlzIHN0dWR5LiBTcGVjaWVzIHRoYXQgd2VyZSBjb2xsZWN0ZWQgZnJvbSBjbG9zZWQtZm9yZXN0IGhhYml0YXRzIHNob3duIHdpdGggZmlsbGVkIHRyaWFuZ2xlcywgd2hpbGUgc3BlY2llcyB0aGF0IHdlcmUgY29sbGVjdGVkIGZyb20gb3BlbiBoYWJpdGF0cyBzaG93biB3aXRoIG9wZW4gY2lyY2xlcy4KCioqKgoKIyBNaWNyb2NsaW1hdGUgbW9kZWxzIGFuZCBmdXR1cmUgc2NlbmFyaW8KCiMjICpOaWNoZU1hcFIqIHBhcmFtZXRlcnMKCioqVGFibGUgUzMuKiogUGFyYW1ldGVyIHZhbHVlcyB1c2VkIHRvIGVzdGltYXRlIHBvbmQgdGVtcGVyYXR1cmUgdXNpbmcgKk5pY2hlTWFwUiouIFBhcmFtZXRlcnMgZm9yIHdoaWNoIHNldHRpbmdzIGRpZmZlciBmcm9tIGRlZmF1bHQgdmFsdWVzIGFyZSBzaG93biBpbiAqKmJvbGQqKi4gRGVmYXVsdCB2YWx1ZXMgZm9yIG90aGVyIHBhcmFtZXRlcnMgaW4gdGhlIG1vZGVsIHJlbWFpbmVkLiAKCmBgYHtyIHRhYmxlUzMsIGVjaG89RkFMU0V9CnNvaWxfcGFyIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vbmljaG9sYXN3dW56L3RhZHBvbGUtdGhlcm1hbC10b2xlcmFuY2UvbWFpbi9wYXJhbWV0ZXJzLmNzdiIsIGhlYWRlcj1GQUxTRSwgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSwgZmlsZUVuY29kaW5nPSJsYXRpbjEiKQpjb2xuYW1lcyhzb2lsX3BhcikgPC0gc29pbF9wYXJbMSxdCnNvaWxfcGFyIDwtIHNvaWxfcGFyWy0xLCBdIAoKIyBSZW5kZXIgdGFibGUKc29pbF9wYXIgJT4lCiAgcmVtb3ZlX3Jvd25hbWVzKCkgJT4lCiAga25pdHI6OmthYmxlKCkKYGBgClwqIHRleHR1cmFsIHNvaWwgcHJvcGVydGllcyBmb3IgY2xheTogZGVwdGggKDIuNSwgNy41LCAyMi41LCA0NSwgODAsIDE1MCksIGJ1bGsgZGVuc2l0eSAxLjQgbWcgbSRcXF4zJCwgOTAlIGNsYXksIDAlIHNpbHQsIDEwJSBzYW5kLgoKIyMgRGVmaW5lIHNvaWwgcGFyYW1ldGVycwoKRGVmaW5lIHNvaWwgcGFyYW1ldGVycyB0byBlbmFibGUgY29uc3RydWN0aW9uIG9mIGh5cG90aGV0aWNhbCB3YXRlciBib2R5IGluICpOaWNoZU1hcFIqLiBQYXJhbWV0ZXJzIG1vZGlmaWVkIHByZXNlbnRlZCBpbiAqKlRhYmxlIFMzKiouCgpgYGB7ciBzb2lsfQojIERlZmluZSB0ZXh0dXJhbCBzb2lsIHByb3BlcnRpZXMgZm9yIGNsYXkKc29pbHBybyA8LSBtYXRyaXgoZGF0YSA9IDAsIG5yb3cgPSA2LCBuY29sID0gNSkKY29sbmFtZXMoc29pbHBybykgPC0gYygnZGVwdGgnLCAnYmxrZGVucycsICdjbGF5JywgJ3NpbHQnLCAnc2FuZCcpCnNvaWxwcm8gPC0gYXMuZGF0YS5mcmFtZShzb2lscHJvKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRlcHRoICAgPSBjKDIuNSwgNy41LCAyMi41LCA0NSwgODAsIDE1MCksCiAgICAgICAgICAgICAgICBibGtkZW5zID0gMS40LCAjIGJ1bGsgZGVuc2l0eSAoTWcvbTMpCiAgICAgICAgICAgICAgICBjbGF5ICAgID0gOTAsICMgJSBjbGF5CiAgICAgICAgICAgICAgICBzaWx0ICAgID0gMC4wLCAjICUgc2lsdAogICAgICAgICAgICAgICAgc2FuZCAgICA9IDEwKSAjICUgc2FuZApERVAgICAgIDwtIGMoMCwgMiwgNSwgMTAsIDE1LCAyMCwgMzAsIDQwLCA1MCwgMTAwKSAjIFNvaWwgbm9kZXMgKGNtKQoKIyBHZXQgaHlkcmF1bGljIHByb3BlcnRpZXMgZm9yIGdpdmVuIHNvaWwKc29pbC5oeWRybyAgPC0gTmljaGVNYXBSOjpwZWRvdHJhbnNmZXIoc29pbHBybyA9IHNvaWxwcm8sIERFUCA9IERFUCkKUEUgPC0gc29pbC5oeWRybyRQRQpCQiA8LSBzb2lsLmh5ZHJvJEJCCkJEIDwtIHNvaWwuaHlkcm8kQkQKS1MgPC0gc29pbC5oeWRybyRLUwpCdWxrRGVuc2l0eSA8LSBCRFtzZXEoMSwgMTksIDIpXQoKcmFpbm11bHQgIDwtIDEwICMgUmFpbmZhbGwgbXVsdGlwbGllciB0byByZWZsZWN0IGNhdGNobWVudCAoMSB3aWxsIHJlc3VsdCBpbiB1bmFkanVzdGVkIHJhaW5mYWxsKQptYXhwb29sICAgPC0gNTAwICMgbWF4aW1pdW0gcG9vbGluZyBkZXB0aCAobW0pLCBpLmUuIHdldGxhbmQgZGVwdGgKTEFJICAgICAgIDwtIDAgIyBsZWFmIGFyZWEgaW5kZXggKHplcm8gc28gbm8gdHJhbnNwaXJhdGlvbikKY2FwICAgICAgIDwtIDAgIyBkbyBub3Qgc2ltdWxhdGUgdGhlIG9yZ2FuaWMgY2FwIGxheWVyCnNvaWxncmlkcyA8LSAwICMgZG9uJ3QgdXNlIFNvaWxHcmlkcyBzb2lsIGRhdGFiYXNlIGZvciB0aGVybWFsIHByb3BlcnRpZXMKYGBgCgojIyBTaW11bGF0ZSBwb25kIHRlbXBlcmF0dXJlCgpSdW4gKk5pY2hlbWFwUiogdG8gc2ltdWxhdGUgcG9uZCB0ZW1wZXJhdHVyZXMgdW5kZXIgZm91ciBoeXBvdGhldGljYWwgc2NlbmFyaW9zOiAoKiphKiopIGN1cnJlbnQgY2xpbWF0ZSB3aXRoIG9wZW4gaGFiaXRhdCwgKCoqYioqKSBjdXJyZW50IGNsaW1hdGUgd2l0aCBzaGFkZWQgaGFiaXRhdCwgKCoqYyoqKSB3YXJtaW5nIGNsaW1hdGUgd2l0aCBvcGVuIGhhYml0YXQsIGFuZCAoKipkKiopIHdhcm1pbmcgY2xpbWF0ZSB3aXRoIHNoYWRlZCBoYWJpdGF0LgoKYGBge3Igc2ltdWxhdGlvbiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9VFJVRSwgcmVzdWx0cz0iaGlkZSJ9CiMgU2ltdWxhdGUgZGF0ZXMgZm9yIDIgeWVhcnMKZGF0ZXMgPC0gTmljaGVNYXBSOjptaWNyb19nbG9iYWwobnllYXIgPSAyKSRkYXRlcwoKIyBDcmVhdGUgbG9vcCBmb3IgZWFjaCBjb29yZGluYXRlcwplc3RfVG1heF9vcGVuIDwtIE5VTEwKZm9yKCBpIGluIDE6bnJvdyhzdW1tYXJ5X2RhdCkpeyAKICByZXN1bHQgPC0gZGF0YS5mcmFtZSgKICAgIE5pY2hlTWFwUjo6bWljcm9fZ2xvYmFsKGxvYyAgICAgID0gYyhzdW1tYXJ5X2RhdCRsb25baV0sIHN1bW1hcnlfZGF0JGxhdFtpXSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuc2hhZGUgPSAwLCBtaW5zaGFkZSA9IDAsIG1heHNoYWRlID0gMTAsICMgc2hhZGUgcGFyYW1ldGVycwogICAgICAgICAgICAgICAgICAgICAgICAgICAgUENUV0VUICAgPSAxMDAsICMgbW9kZWwgc3VyZmFjZSBzb2lsIHdldG5lc3MgKCUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBFID0gUEUsIEJCID0gQkIsIEJEID0gQkQsIEtTID0gS1MsIHJhaW5tdWx0ID0gcmFpbm11bHQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4cG9vbCA9IG1heHBvb2wsIExBSSA9IExBSSwgY2FwID0gY2FwLCBzb2lsZ3JpZHMgPSBzb2lsZ3JpZHMsICMgc29pbCBwYXJhbWV0ZXJzIHRvIHNpbXVsYXRlIHBvb2wKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm0gPSAwLCAjIGN1cnJlbnQgY2xpbWF0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbnllYXIgPSAyLCkkc29pbCkgJT4lICMgZXh0cmFjdCBzb2lsIHBhcmFtZXRlcnMKICAgIGRwbHlyOjptdXRhdGUoZGF0ZXMgPSBkYXRlcykgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKGRhdGVzID49IHN1bW1hcnlfZGF0JG1vbnRoX3N0YXJ0W2ldICYgZGF0ZXMgPD0gc3VtbWFyeV9kYXQkbW9udGhfZW5kW2ldKSAlPiUgCiAgICBkcGx5cjo6c3VtbWFyaXNlKGVzdF9UbWF4X29wZW4gPSBtYXgoRDBjbSkpCiAgcHJpbnQocmVzdWx0KQogIHJlc3VsdHNfMiA8LSBjYmluZChzdW1tYXJ5X2RhdCRzcGVjaWVzW2ldLCByZXN1bHQpCiAgZXN0X1RtYXhfb3BlbiA8LSByYmluZChlc3RfVG1heF9vcGVuLCByZXN1bHRzXzIpCn0KCmVzdF9UbWF4X3NoYWRlIDwtIE5VTEwKZm9yKCBpIGluIDE6bnJvdyhzdW1tYXJ5X2RhdCkpeyAKICByZXN1bHQgPC0gZGF0YS5mcmFtZSgKICAgIE5pY2hlTWFwUjo6bWljcm9fZ2xvYmFsKGxvYyAgICAgID0gYyhzdW1tYXJ5X2RhdCRsb25baV0sIHN1bW1hcnlfZGF0JGxhdFtpXSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuc2hhZGUgPSAwLCBtaW5zaGFkZSA9IDk1LCBtYXhzaGFkZSA9IDEwMCwgIyBzaGFkZSBwYXJhbWV0ZXJzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQQ1RXRVQgICA9IDEwMCwgIyBtb2RlbCBzdXJmYWNlIHNvaWwgd2V0bmVzcyAoJSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUEUgPSBQRSwgQkIgPSBCQiwgQkQgPSBCRCwgS1MgPSBLUywgcmFpbm11bHQgPSByYWlubXVsdCwgbWF4cG9vbCA9IG1heHBvb2wsIExBSSA9IExBSSwgY2FwID0gY2FwLCBzb2lsZ3JpZHMgPSBzb2lsZ3JpZHMsICMgc29pbCBwYXJhbWV0ZXJzIHRvIHNpbXVsYXRlIHBvb2wKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm0gPSAwLCAjIGN1cnJlbnQgY2xpbWF0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbnllYXIgPSAyKSRzb2lsKSAlPiUgIyBFeHRyYWN0IHNvaWwgcGFyYW1ldGVycwogICAgZHBseXI6Om11dGF0ZShkYXRlcyA9IGRhdGVzKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoZGF0ZXMgPj0gc3VtbWFyeV9kYXQkbW9udGhfc3RhcnRbaV0gJiBkYXRlcyA8PSBzdW1tYXJ5X2RhdCRtb250aF9lbmRbaV0pICU+JSAKICAgIGRwbHlyOjpzdW1tYXJpc2UoZXN0X1RtYXhfc2hhZGUgPSBtYXgoRDBjbSkpCiAgcHJpbnQocmVzdWx0KQogIGVzdF9UbWF4X3NoYWRlIDwtIHJiaW5kKGVzdF9UbWF4X3NoYWRlLCByZXN1bHQpCn0KCmVzdF9UbWF4X29wZW5fNEMgPC0gTlVMTApmb3IoIGkgaW4gMTpucm93KHN1bW1hcnlfZGF0KSl7IAogIHJlc3VsdCA8LSBkYXRhLmZyYW1lKAogICAgTmljaGVNYXBSOjptaWNyb19nbG9iYWwobG9jICAgICAgPSBjKHN1bW1hcnlfZGF0JGxvbltpXSwgc3VtbWFyeV9kYXQkbGF0W2ldKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5zaGFkZSA9IDAsIG1pbnNoYWRlID0gMCwgbWF4c2hhZGUgPSAxMCwgIyBzaGFkZSBwYXJhbWV0ZXJzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQQ1RXRVQgICA9IDEwMCwgIyBtb2RlbCBzdXJmYWNlIHNvaWwgd2V0bmVzcyAoJSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUEUgPSBQRSwgQkIgPSBCQiwgQkQgPSBCRCwgS1MgPSBLUywgcmFpbm11bHQgPSByYWlubXVsdCwgbWF4cG9vbCA9IG1heHBvb2wsIExBSSA9IExBSSwgY2FwID0gY2FwLCBzb2lsZ3JpZHMgPSBzb2lsZ3JpZHMsICMgc29pbCBwYXJhbWV0ZXJzIHRvIHNpbXVsYXRlIHBvb2wKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm0gPSA0LCAjIGZ1dHVyZSBjbGltYXRlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBueWVhciA9IDIsKSRzb2lsKSAlPiUgIyBleHRyYWN0IHNvaWwgcGFyYW1ldGVycwogICAgZHBseXI6Om11dGF0ZShkYXRlcyA9IGRhdGVzKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoZGF0ZXMgPj0gc3VtbWFyeV9kYXQkbW9udGhfc3RhcnRbaV0gJiBkYXRlcyA8PSBzdW1tYXJ5X2RhdCRtb250aF9lbmRbaV0pICU+JSAKICAgIGRwbHlyOjpzdW1tYXJpc2UoZXN0X1RtYXhfb3Blbl80QyA9IG1heChEMGNtKSkKICBwcmludChyZXN1bHQpCiAgZXN0X1RtYXhfb3Blbl80QyA8LSByYmluZChlc3RfVG1heF9vcGVuXzRDLCByZXN1bHQpCn0KCmVzdF9UbWF4X3NoYWRlXzRDIDwtIE5VTEwKZm9yKCBpIGluIDE6bnJvdyhzdW1tYXJ5X2RhdCkpeyAKICByZXN1bHQgPC0gZGF0YS5mcmFtZSgKICAgIE5pY2hlTWFwUjo6bWljcm9fZ2xvYmFsKGxvYyAgICAgID0gYyhzdW1tYXJ5X2RhdCRsb25baV0sIHN1bW1hcnlfZGF0JGxhdFtpXSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuc2hhZGUgPSAwLCBtaW5zaGFkZSA9IDk1LCBtYXhzaGFkZSA9IDEwMCwgIyBzaGFkZSBwYXJhbWV0ZXJzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQQ1RXRVQgICA9IDEwMCwgIyBtb2RlbCBzdXJmYWNlIHNvaWwgd2V0bmVzcyAoJSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUEUgPSBQRSwgQkIgPSBCQiwgQkQgPSBCRCwgS1MgPSBLUywgcmFpbm11bHQgPSByYWlubXVsdCwgbWF4cG9vbCA9IG1heHBvb2wsIExBSSA9IExBSSwgY2FwID0gY2FwLCBzb2lsZ3JpZHMgPSBzb2lsZ3JpZHMsICMgc29pbCBwYXJhbWV0ZXJzIHRvIHNpbXVsYXRlIHBvb2wKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm0gPSA0LCAjIGZ1dHVyZSBjbGltYXRlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBueWVhciA9IDIpJHNvaWwpICU+JSAjIGV4dHJhY3Qgc29pbCBwYXJhbWV0ZXJzCiAgICBkcGx5cjo6bXV0YXRlKGRhdGVzID0gZGF0ZXMpICU+JQogICAgZHBseXI6OmZpbHRlcihkYXRlcyA+PSBzdW1tYXJ5X2RhdCRtb250aF9zdGFydFtpXSAmIGRhdGVzIDw9IHN1bW1hcnlfZGF0JG1vbnRoX2VuZFtpXSkgJT4lIAogICAgZHBseXI6OnN1bW1hcmlzZShlc3RfVG1heF9zaGFkZV80QyA9IG1heChEMGNtKSkKICBwcmludChyZXN1bHQpCiAgZXN0X1RtYXhfc2hhZGVfNEMgPC0gcmJpbmQoZXN0X1RtYXhfc2hhZGVfNEMsIHJlc3VsdCkKfQoKcHJval9kYXRhIDwtIGNiaW5kKHN1bW1hcnlfZGF0LCBlc3RfVG1heF9zaGFkZSwgZXN0X1RtYXhfb3BlblssMl0sIGVzdF9UbWF4X3NoYWRlXzRDLCBlc3RfVG1heF9vcGVuXzRDKSAlPiUgCiAgZHBseXI6OnJlbmFtZShlc3RfVG1heF9vcGVuID0gImVzdF9UbWF4X29wZW5bLCAyXSIpCmBgYAoKIyMgVmVyaWZ5IHByZWRpY3RlZCB2YWx1ZXMKClByZWRpY3RlZCBUfm1heH4gZnJvbSB0aGUgaGVhdCBidWRnZXQgbW9kZWxzIHdlcmUgdmFsaWRhdGVkIHdpdGggYSBsaW5lYXIgbW9kZWwgKGJlbG93KSBhbmQgdmlzdWFsbHkgaW4gKipGaWcuIFMyZSoqLgoKYGBge3IgdmVyaWZ5LCBjYWNoZT1UUlVFfQpwcmVkaWN0X29ic19tb2RlbCA8LSBsbShUbWF4IH4gZXN0X1RtYXhfc2hhZGUgKyBoYWJpdGF0LCBkYXRhID0gcHJval9kYXRhKQoKdmVyaWZ5ICAgIDwtIHN1bW1hcnkocHJlZGljdF9vYnNfbW9kZWwpJHIuc3F1YXJlZAptb2RlbF9tYWUgPC0gTWV0cmljczo6bWFlKHByb2pfZGF0YSRUbWF4LCBwcmVkaWN0KHByZWRpY3Rfb2JzX21vZGVsKSkKYGBgCgoKYGBge3IgRmlnIFMyLCBlY2hvPUZBTFNFLCBjYWNoZT1UUlVFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5oZWlnaHQ9OC41LCBmaWcud2lkdGg9OSwgbWVzc2FnZT1GQUxTRX0KZGF0ZSAgIDwtIE5pY2hlTWFwUjo6bWljcm9fZ2xvYmFsKG55ZWFyID0gMSkkZGF0ZXMKY29vcmRzIDwtIHN1bW1hcnlfZGF0ICU+JSBkcGx5cjo6c2VsZWN0KGxvbiwgbGF0KQoKIyBNaWNyb2NsaW1hdGUgc2ltdWxhdGlvbiBmb3IgQm9tYmluYSBvcmllbnRhbGlzIC0gY2xvc2VkIGZvcmVzdCAtIEtvcmVhCkJvX21pY3JvX3NoYWRlIDwtIGRhdGEuZnJhbWUoCiAgTmljaGVNYXBSOjptaWNyb19nbG9iYWwobG9jICAgICAgPSBjb29yZHNbMjIsXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuc2hhZGUgPSAwLCBtaW5zaGFkZSA9IDkwLCBtYXhzaGFkZSA9IDEwMCwgIyBzaGFkZSBwYXJhbWV0ZXJzCiAgICAgICAgICAgICAgICAgICAgICAgICAgUENUV0VUICAgPSAxMDAsICMgbW9kZWwgc3VyZmFjZSBzb2lsIHdldG5lc3MgKCUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBQRSA9IFBFLCBCQiA9IEJCLCBCRCA9IEJELCBLUyA9IEtTLCByYWlubXVsdCA9IHJhaW5tdWx0LCBtYXhwb29sID0gbWF4cG9vbCwgTEFJID0gTEFJLCBjYXAgPSBjYXAsIHNvaWxncmlkcyA9IHNvaWxncmlkcywgIyBzb2lsIHBhcmFtZXRlcnMgdG8gc2ltdWxhdGUgcG9vbAogICAgICAgICAgICAgICAgICAgICAgICAgIG55ZWFyID0gMSkkc29pbCkgJT4lICMgZXh0cmFjdCBzb2lsIHBhcmFtZXRlcnMKICBkcGx5cjo6bXV0YXRlKGRhdGVzID0gZGF0ZSkKCkJvX21pY3JvX29wZW4gPC0gZGF0YS5mcmFtZSgKICBOaWNoZU1hcFI6Om1pY3JvX2dsb2JhbChsb2MgICAgICA9IGNvb3Jkc1syMixdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBydW5zaGFkZSA9IDAsIG1pbnNoYWRlID0gMCwgbWF4c2hhZGUgPSAxMCwgIyBzaGFkZSBwYXJhbWV0ZXJzCiAgICAgICAgICAgICAgICAgICAgICAgICAgUENUV0VUICAgPSAxMDAsICMgbW9kZWwgc3VyZmFjZSBzb2lsIHdldG5lc3MgKCUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBQRSA9IFBFLCBCQiA9IEJCLCBCRCA9IEJELCBLUyA9IEtTLCByYWlubXVsdCA9IHJhaW5tdWx0LCBtYXhwb29sID0gbWF4cG9vbCwgTEFJID0gTEFJLCBjYXAgPSBjYXAsIHNvaWxncmlkcyA9IHNvaWxncmlkcywgIyBzb2lsIHBhcmFtZXRlcnMgdG8gc2ltdWxhdGUgcG9vbAogICAgICAgICAgICAgICAgICAgICAgICAgIG55ZWFyID0gMSkkc29pbCkgJT4lICMgZXh0cmFjdCBzb2lsIHBhcmFtZXRlcnMKICBkcGx5cjo6bXV0YXRlKGRhdGVzID0gZGF0ZSkKCkJvX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IHN1bW1hcnlfZGF0WzIyLDE2XSwgeG1heCA9IHN1bW1hcnlfZGF0WzIyLDE3XSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGFscGhhID0gMC4xLCBmaWxsID0gImJsYWNrIikgKwogIGdlb21faGxpbmUoZGF0YSA9IHN1bW1hcnlfZGF0WzIyLF0sIGFlcyh5aW50ZXJjZXB0ID0gVG1heCksIGxpbmV0eXBlID0gImRhc2hlZCIsIGFscGhhID0gMC41KSArCiAgZ2VvbV9saW5lKGRhdGEgPSBCb19taWNyb19vcGVuLCBhZXMoeCA9IGRhdGVzLCB5ID0gRDBjbSksIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IEJvX21pY3JvX3NoYWRlLCBhZXMoeCA9IGRhdGVzLCB5ID0gRDBjbSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIGxhYnModGl0bGUgPSBwYXN0ZShzdW1tYXJ5X2RhdFsyMiw1XSwgZ3N1YigiICIsICIiLCBhZGRwYXJlbnRoZXNlcyhzdW1tYXJ5X2RhdFsyMiwzXSkpKSwgCiAgICAgICBzdWJ0aXRsZSA9IHBhc3RlKHN1bW1hcnlfZGF0WzIyLDJdLCBnc3ViKCIgIiwgIiIsYWRkcGFyZW50aGVzZXMoc3VtbWFyeV9kYXRbMjIsMV0pKSwgKCItIiksICJsb24iLCBnc3ViKCIgIiwgIiIsIHBhc3RlKChzdW1tYXJ5X2RhdFsyMiw4XSksICIsIikpLCAibGF0IiwgKHN1bW1hcnlfZGF0WzIyLDldKSksIAogICAgICAgeSA9ICJXYXRlciB0ZW1wZXJhdHVyZSAowrBDKSIsIHggPSAiTW9udGggb2YgdGhlIHllYXIiKSArCiAgbXl0aGVtZSgpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gIml0YWxpYyIsIHNpemUgPSAxMCksCiAgICAgICAgICAgICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSkpCgojIE1pY3JvY2xpbWF0ZSBzaW11bGF0aW9uIGZvciBLdXJpeGFsdXMgZWlmZmluZ2VyaSAtIGNsb3NlZCBmb3Jlc3QgLSBUYWl3YW4KS2VfbWljcm9fc2hhZGUgPC0gZGF0YS5mcmFtZSgKICBOaWNoZU1hcFI6Om1pY3JvX2dsb2JhbChsb2MgICAgICA9IGNvb3Jkc1s1LF0sIAogICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnNoYWRlID0gMCwgbWluc2hhZGUgPSA5MCwgbWF4c2hhZGUgPSAxMDAsICMgc2hhZGUgcGFyYW1ldGVycwogICAgICAgICAgICAgICAgICAgICAgICAgIFBDVFdFVCAgID0gMTAwLCAjIG1vZGVsIHN1cmZhY2Ugc29pbCB3ZXRuZXNzICglKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgUEUgPSBQRSwgQkIgPSBCQiwgQkQgPSBCRCwgS1MgPSBLUywgcmFpbm11bHQgPSByYWlubXVsdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4cG9vbCA9IG1heHBvb2wsIExBSSA9IExBSSwgY2FwID0gY2FwLCBzb2lsZ3JpZHMgPSBzb2lsZ3JpZHMsICMgc29pbCBwYXJhbWV0ZXJzIHRvIHNpbXVsYXRlIHBvb2wKICAgICAgICAgICAgICAgICAgICAgICAgICBueWVhciA9IDEpJHNvaWwpICU+JSAjIGV4dHJhY3Qgc29pbCBwYXJhbWV0ZXJzCiAgZHBseXI6Om11dGF0ZShkYXRlcyA9IGRhdGUpCgpLZV9taWNyb19vcGVuIDwtIGRhdGEuZnJhbWUoCiAgTmljaGVNYXBSOjptaWNyb19nbG9iYWwobG9jICAgICAgPSBjb29yZHNbNSxdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBydW5zaGFkZSA9IDAsIG1pbnNoYWRlID0gMCwgbWF4c2hhZGUgPSAxMCwgIyBzaGFkZSBwYXJhbWV0ZXJzCiAgICAgICAgICAgICAgICAgICAgICAgICAgUENUV0VUICAgPSAxMDAsICMgTW9kZWwgc3VyZmFjZSBzb2lsIHdldG5lc3MgKCUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBQRSA9IFBFLCBCQiA9IEJCLCBCRCA9IEJELCBLUyA9IEtTLCByYWlubXVsdCA9IHJhaW5tdWx0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhwb29sID0gbWF4cG9vbCwgTEFJID0gTEFJLCBjYXAgPSBjYXAsIHNvaWxncmlkcyA9IHNvaWxncmlkcywgIyBzb2lsIHBhcmFtZXRlcnMgdG8gc2ltdWxhdGUgcG9vbAogICAgICAgICAgICAgICAgICAgICAgICAgIG55ZWFyID0gMSkkc29pbCkgJT4lICMgZXh0cmFjdCBzb2lsIHBhcmFtZXRlcnMKICBkcGx5cjo6bXV0YXRlKGRhdGVzID0gZGF0ZSkKCktlX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IHN1bW1hcnlfZGF0WzUsMTZdLCB4bWF4ID0gc3VtbWFyeV9kYXRbNSwxN10sIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBhbHBoYSA9IDAuMSwgZmlsbCA9ICJibGFjayIpICsKICBnZW9tX2hsaW5lKGRhdGEgPSBzdW1tYXJ5X2RhdFs1LF0sIGFlcyh5aW50ZXJjZXB0ID0gVG1heCksIGxpbmV0eXBlID0gImRhc2hlZCIsIGFscGhhID0gMC41KSArCiAgZ2VvbV9saW5lKGRhdGEgPSBLZV9taWNyb19vcGVuLCBhZXMoeCA9IGRhdGVzLCB5ID0gRDBjbSksIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IEtlX21pY3JvX3NoYWRlLCBhZXMoeCA9IGRhdGVzLCB5ID0gRDBjbSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIGxhYnModGl0bGUgPSBwYXN0ZShzdW1tYXJ5X2RhdFs1LDVdLCBnc3ViKCIgIiwgIiIsIGFkZHBhcmVudGhlc2VzKHN1bW1hcnlfZGF0WzUsM10pKSksIAogICAgICAgc3VidGl0bGUgPSBwYXN0ZShzdW1tYXJ5X2RhdFs1LDJdLCBnc3ViKCIgIiwgIiIsIGFkZHBhcmVudGhlc2VzKHN1bW1hcnlfZGF0WzUsMV0pKSwgKCItIiksICJsb24iLCBnc3ViKCIgIiwgIiIsIHBhc3RlKChzdW1tYXJ5X2RhdFs1LDhdKSwgIiwiKSksICJsYXQiLCAoc3VtbWFyeV9kYXRbNSw5XSkpLCAKICAgICAgIHkgPSAiV2F0ZXIgdGVtcGVyYXR1cmUgKMKwQykiLCB4ID0gIk1vbnRoIG9mIHRoZSB5ZWFyIikgKwogIG15dGhlbWUoKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiLCBzaXplID0gMTApLAogICAgICAgICAgICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpKQoKIyBNaWNyb2NsaW1hdGUgc2ltdWxhdGlvbiBmb3IgUGVsb3BoeWxheCBuaWdyb21hY3VsYXR1cyAtIE9wZW4gLSBLb3JlYQpQbl9taWNyb19zaGFkZSA8LSBkYXRhLmZyYW1lKAogIE5pY2hlTWFwUjo6bWljcm9fZ2xvYmFsKGxvYyAgICAgID0gY29vcmRzWzI4LF0sIAogICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnNoYWRlID0gMCwgbWluc2hhZGUgPSA5MCwgbWF4c2hhZGUgPSAxMDAsICMgc2hhZGUgcGFyYW1ldGVycwogICAgICAgICAgICAgICAgICAgICAgICAgIFBDVFdFVCAgID0gMTAwLCAjIG1vZGVsIHN1cmZhY2Ugc29pbCB3ZXRuZXNzICglKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgUEUgPSBQRSwgQkIgPSBCQiwgQkQgPSBCRCwgS1MgPSBLUywgcmFpbm11bHQgPSByYWlubXVsdCwgbWF4cG9vbCA9IG1heHBvb2wsIExBSSA9IExBSSwgY2FwID0gY2FwLCBzb2lsZ3JpZHMgPSBzb2lsZ3JpZHMsICMgc29pbCBwYXJhbWV0ZXJzIHRvIHNpbXVsYXRlIHBvb2wKICAgICAgICAgICAgICAgICAgICAgICAgICBueWVhciA9IDEpJHNvaWwpICU+JSAjIGV4dHJhY3Qgc29pbCBwYXJhbWV0ZXJzCiAgZHBseXI6Om11dGF0ZShkYXRlcyA9IGRhdGUpCgpQbl9taWNyb19vcGVuIDwtIGRhdGEuZnJhbWUoCiAgTmljaGVNYXBSOjptaWNyb19nbG9iYWwobG9jICAgICAgPSBjb29yZHNbMjgsXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuc2hhZGUgPSAwLCBtaW5zaGFkZSA9IDAsIG1heHNoYWRlID0gMTAsICMgc2hhZGUgcGFyYW1ldGVycwogICAgICAgICAgICAgICAgICAgICAgICAgIFBDVFdFVCAgID0gMTAwLCAjIG1vZGVsIHN1cmZhY2Ugc29pbCB3ZXRuZXNzICglKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgUEUgPSBQRSwgQkIgPSBCQiwgQkQgPSBCRCwgS1MgPSBLUywgcmFpbm11bHQgPSByYWlubXVsdCwgbWF4cG9vbCA9IG1heHBvb2wsIExBSSA9IExBSSwgY2FwID0gY2FwLCBzb2lsZ3JpZHMgPSBzb2lsZ3JpZHMsICMgc29pbCBwYXJhbWV0ZXJzIHRvIHNpbXVsYXRlIHBvb2wKICAgICAgICAgICAgICAgICAgICAgICAgICBueWVhciA9IDEpJHNvaWwpICU+JSAjIGV4dHJhY3Qgc29pbCBwYXJhbWV0ZXJzCiAgZHBseXI6Om11dGF0ZShkYXRlcyA9IGRhdGUpCgpQbl9wbG90IDwtIGdncGxvdCgpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBzdW1tYXJ5X2RhdFsyOCwxNl0sIHhtYXggPSBzdW1tYXJ5X2RhdFsyOCwxN10sIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBhbHBoYSA9IDAuMSwgZmlsbCA9ICJibGFjayIpICsKICBnZW9tX2hsaW5lKGRhdGEgPSBzdW1tYXJ5X2RhdFsyOCxdLCBhZXMoeWludGVyY2VwdCA9IFRtYXgpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBhbHBoYSA9IDAuNSkgKwogIGdlb21fbGluZShkYXRhID0gUG5fbWljcm9fb3BlbiwgYWVzKHggPSBkYXRlcywgeSA9IEQwY20pLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBQbl9taWNyb19zaGFkZSwgYWVzKHggPSBkYXRlcywgeSA9IEQwY20pKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoc3VtbWFyeV9kYXRbMjgsNV0sIGdzdWIoIiAiLCAiIiwgYWRkcGFyZW50aGVzZXMoc3VtbWFyeV9kYXRbMjgsM10pKSksIAogICAgICAgc3VidGl0bGUgPSBwYXN0ZShzdW1tYXJ5X2RhdFsyOCwyXSwgZ3N1YigiICIsICIiLCBhZGRwYXJlbnRoZXNlcyhzdW1tYXJ5X2RhdFsyOCwxXSkpLCAoIi0iKSwgImxvbiIsIGdzdWIoIiAiLCAiIiwgcGFzdGUoKHN1bW1hcnlfZGF0WzI4LDhdKSwgIiwiKSksICJsYXQiLCAoc3VtbWFyeV9kYXRbMjgsOV0pKSwgCiAgICAgICB5ID0gIldhdGVyIHRlbXBlcmF0dXJlICjCsEMpIiwgeCA9ICJNb250aCBvZiB0aGUgeWVhciIpICsKICBteXRoZW1lKCkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIiwgc2l6ZSA9IDEwKSwKICAgICAgICAgICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSkKCiMgTWljcm9jbGltYXRlIHNpbXVsYXRpb24gZm9yIER1dHRhcGhyeW51cyBtZWxhbm9zdGljdHVzIC0gT3BlbiAtIFRhaXdhbgpEbV9taWNyb19zaGFkZSA8LSBkYXRhLmZyYW1lKAogIE5pY2hlTWFwUjo6bWljcm9fZ2xvYmFsKGxvYyAgICAgID0gY29vcmRzWzgsXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuc2hhZGUgPSAwLCBtaW5zaGFkZSA9IDkwLCAgbWF4c2hhZGUgPSAxMDAsICMgc2hhZGUgcGFyYW1ldGVycwogICAgICAgICAgICAgICAgICAgICAgICAgIFBDVFdFVCAgID0gMTAwLCAjIG1vZGVsIHN1cmZhY2Ugc29pbCB3ZXRuZXNzICglKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgUEUgPSBQRSwgQkIgPSBCQiwgQkQgPSBCRCwgS1MgPSBLUywgcmFpbm11bHQgPSByYWlubXVsdCwgbWF4cG9vbCA9IG1heHBvb2wsIExBSSA9IExBSSwgY2FwID0gY2FwLCBzb2lsZ3JpZHMgPSBzb2lsZ3JpZHMsICMgc29pbCBwYXJhbWV0ZXJzIHRvIHNpbXVsYXRlIHBvb2wKICAgICAgICAgICAgICAgICAgICAgICAgICBueWVhciA9IDEpJHNvaWwpICU+JSAjIGV4dHJhY3Qgc29pbCBwYXJhbWV0ZXJzCiAgZHBseXI6Om11dGF0ZShkYXRlcyA9IGRhdGUpCgpEbV9taWNyb19vcGVuIDwtIGRhdGEuZnJhbWUoCiAgTmljaGVNYXBSOjptaWNyb19nbG9iYWwobG9jICAgICAgPSBjb29yZHNbOCxdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBydW5zaGFkZSA9IDAsIG1pbnNoYWRlID0gMCwgbWF4c2hhZGUgPSAxMCwgIyBzaGFkZSBwYXJhbWV0ZXJzCiAgICAgICAgICAgICAgICAgICAgICAgICAgUENUV0VUICAgPSAxMDAsICMgbW9kZWwgc3VyZmFjZSBzb2lsIHdldG5lc3MgKCUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBQRSA9IFBFLCBCQiA9IEJCLCBCRCA9IEJELCBLUyA9IEtTLCByYWlubXVsdCA9IHJhaW5tdWx0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhwb29sID0gbWF4cG9vbCwgTEFJID0gTEFJLCBjYXAgPSBjYXAsIHNvaWxncmlkcyA9IHNvaWxncmlkcywgIyBzb2lsIHBhcmFtZXRlcnMgdG8gc2ltdWxhdGUgcG9vbAogICAgICAgICAgICAgICAgICAgICAgICAgIG55ZWFyID0gMSkkc29pbCkgJT4lICMgZXh0cmFjdCBzb2lsIHBhcmFtZXRlcnMKICBkcGx5cjo6bXV0YXRlKGRhdGVzID0gZGF0ZSkKCkRtX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IHN1bW1hcnlfZGF0WzgsMTZdLCB4bWF4ID0gc3VtbWFyeV9kYXRbOCwxN10sIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBhbHBoYSA9IDAuMSwgZmlsbCA9ICJibGFjayIpICsKICBnZW9tX2hsaW5lKGRhdGEgPSBzdW1tYXJ5X2RhdFs4LF0sIGFlcyh5aW50ZXJjZXB0ID0gVG1heCksIGxpbmV0eXBlID0gImRhc2hlZCIsIGFscGhhID0gMC41KSArCiAgZ2VvbV9saW5lKGRhdGEgPSBEbV9taWNyb19vcGVuLCBhZXMoeCA9IGRhdGVzLCB5ID0gRDBjbSksIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IERtX21pY3JvX3NoYWRlLCBhZXMoeCA9IGRhdGVzLCB5ID0gRDBjbSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIGxhYnModGl0bGUgPSBwYXN0ZShzdW1tYXJ5X2RhdFs4LDVdLCBnc3ViKCIgIiwgIiIsIGFkZHBhcmVudGhlc2VzKHN1bW1hcnlfZGF0WzgsM10pKSksIAogICAgICAgc3VidGl0bGUgPSBwYXN0ZShzdW1tYXJ5X2RhdFs4LDJdLCBnc3ViKCIgIiwgIiIsIGFkZHBhcmVudGhlc2VzKHN1bW1hcnlfZGF0WzgsMV0pKSwgKCItIiksICJsb24iLCBnc3ViKCIgIiwgIiIsIHBhc3RlKChzdW1tYXJ5X2RhdFs4LDhdKSwgIiwiKSksICJsYXQiLCAoc3VtbWFyeV9kYXRbOCw5XSkpLCAKICAgICAgIHkgPSAiV2F0ZXIgdGVtcGVyYXR1cmUgKMKwQykiLCB4ID0gIk1vbnRoIG9mIHRoZSB5ZWFyIikgKwogIG15dGhlbWUoKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiLCBzaXplID0gMTApLAogICAgICAgICAgICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpKQoKdG9wX3Bsb3QgPC0gY293cGxvdDo6cGxvdF9ncmlkKEJvX3Bsb3QsIFBuX3Bsb3QsIEtlX3Bsb3QsIERtX3Bsb3QsCiAgICAgICAgICAgICAgICAgICBuY29sID0gMiwgYWxpZ24gPSAiaHYiLCBheGlzID0gInRibHIiLCBsYWJlbHMgPSBjKCJhIiwgImIiLCAiYyIsICJkIikpCgpUbWF4X3ByZWRfcGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9wb2ludChkYXRhID0gcHJval9kYXRhICU+JSBkcGx5cjo6ZmlsdGVyKGhhYml0YXQgPT0gIkZvcmVzdCIpLCBhZXMoeCA9IGVzdF9UbWF4X3NoYWRlLCB5ID0gVG1heCksIHNpemUgPSAzLCBzaGFwZSA9IDE3KSArICMgZmlsbGVkIHRyaWFuZ2xlcwogIGdlb21fcG9pbnQoZGF0YSA9IHByb2pfZGF0YSAlPiUgZHBseXI6OmZpbHRlcihoYWJpdGF0ID09ICJPcGVuIiksIGFlcyh4ID0gZXN0X1RtYXhfb3BlbiwgeSA9IFRtYXgpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjIG9wZW4gY2lyY2xlcwogIGxhYnModGl0bGUgPSAiQWxsIHNwZWNpZXMiKSArCiAgeGxhYihleHByZXNzaW9uKCJFc3RpbWF0ZWQgVCJbIm1heCJdfiIowrBDKSIpKSArCiAgeWxhYihleHByZXNzaW9uKCJPYnNlcnZlZCBUIlsibWF4Il1+IijCsEMpIikpICsKICB5bGltKDE1LDM4KSArIHhsaW0oMTUsMzgpICsKICBteXRoZW1lKCkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCgpjb3dwbG90OjpwbG90X2dyaWQodG9wX3Bsb3QsIFRtYXhfcHJlZF9wbG90LAogICAgICAgICAgICAgICAgICAgbmNvbCA9IDEsIHJlbF9oZWlnaHRzID0gYygxLCAwLjYpLCBsYWJlbHMgPSBjKCIiLCAiZSIpKQpgYGAKCioqRmlnLiBTMioqIE1heGltdW0gd2F0ZXIgdGVtcGVyYXR1cmUgKFR+bWF4fiBhcyBkZWdyZWUgQ2Vsc2l1cykgb3V0cHV0IGZyb20gdGhlIG1pY3JvY2xpbWF0ZSBtb2RlbC4gRXhhbXBsZSBwb25kIHRlbXBlcmF0dXJlIG91dHB1dCBvdmVyIGEgb25lIHllYXIgcGVyaW9kIGZvciAoKiphKiopICpCb21iaW5hIG9yaWVudGFsaXMqLCBhIHRlbXBlcmF0ZSBzcGVjaWVzIGluIEtvcmVhICgzNi44MTMgwrBOLCAxMjguMDU0IMKwRSksICgqKmIqKikgKlBlbG9waHlsYXggbmlncm9tYWN1bGF0dXMqLCBhIHRlbXBlcmF0ZSBzcGVjaWVzIGluIEtvcmVhICgzNi44ODcgwrBOLCAxMjYuOTM2IMKwRSksICgqKmMqKikgKkt1cml4YWx1cyBlaWZmaW5nZXJpKiwgYSBzdWJ0cm9waWNzIHNwZWNpZXMgaW4gVGFpd2FuICgyMy45MTQgwrBOLCAxMjAuODk2IMKwRSksIGFuZCAoKipkKiopICpEdXR0YXBocnludXMgbWVsYW5vc3RpY3R1cyosIGEgc3VidHJvcGljcyBzcGVjaWVzIGluIFRhaXdhbiAoMjQuMTgxIMKwTiwgMTIwLjYwOCDCsEUpLiBUaGUgc29saWQgYW5kIGRhc2hlZCBsaW5lIHJlcHJlc2VudHMgdGhlIGVzdGltYXRlZCB3YXRlciB0ZW1wZXJhdHVyZSB1bmRlciBzaGFkZWQgY29uZGl0aW9ucyAoOTXigJMxMDAlIHZlZ2V0YXRpb24gc2hhZGUpIGFuZCB1bmRlciBvcGVuIGNvbmRpdGlvbnMgKDHigJMxMCUgdmVnZXRhdGlvbiBzaGFkZSksIHJlc3BlY3RpdmVseS4gVGhlIGZpbGxlZCBhcmVhIHdhcyB0aGUgZW52aXJvbm1lbnRhbCBkYXRhIGNvbGxlY3Rpb24gcGVyaW9kLCBhbmQgdGhlIHNpbmdsZSBkYXNoZWQgaG9yaXpvbnRhbCBncmV5IGxpbmUgaXMgdGhlIG9ic2VydmVkIFR+bWF4fiBmcm9tIHRoZSBzdHVkeS4gKCoqZSoqKSBUaGUgb2JzZXJ2ZWQgYW5kIGVzdGltYXRlZCBUfm1heH4gZm9yIGVhY2ggc3BlY2llcywgbWF0Y2hpbmcgdGhlIHN0dWR5IGxvY2F0aW9uIGFuZCB0aW1lLiBPYnNlcnZlZCB0ZW1wZXJhdHVyZXMgd2VyZSByZWNvcmRlZCBieSBIT0JPIFdhdGVyIFRlbXBlcmF0dXJlIGxvZ2dlcnMgd2hpbGUgdGhlIGVzdGltYXRlZCBUfm1heH4gd2FzIGVzdGltYXRlZCBmcm9tICpOaWNoZU1hcFIqIHVuZGVyIG9wZW4gKGZpbGxlZCB0cmlhbmdsZXMpIGFuZCBzaGFkZWQgaGFiaXRhdHMgKG9wZW4gY2lyY2xlcykuIERhc2hlZCBsaW5lIHJlcHJlc2VudHMgMToxIHNjYWxlLCBhbmQgUsKyID0gYHIgdmVyaWZ5YCwgd2l0aCBhIG1lYW4gYWJzb2x1dGUgZXJyb3Igb2YgYHIgbW9kZWxfbWFlYC4KCioqKgoKIyBSZWxhdGlvbnNoaXAgYmV0d2VlbiBDVH5tYXh+LCBUfm1heH4sIGFuZCB3YXJtaW5nIHRvbGVyYW5jZQoKUnVuIGFuYWx5c2lzIGxvb2tpbmcgYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICgqKmEqKikgQ1R+bWF4fiBhbmQgVH5tYXh+IChDVH5tYXh+LS1Ufm1heH4gbW9kZWwpLCAoKipiKiopIHdhcm1pbmcgdG9sZXJhbmNlIChXVCkgYW5kIFR+bWF4fiAoV1QtLVR+bWF4fiBtb2RlbCksIGFuZCAoKipjKiopIFdUIGFuZCBDVH5tYXh+IChXVC0tQ1R+bWF4fiBtb2RlbCkuCgpgYGB7ciByZWxhdGlvbnNoaXAsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUUsIHJlc3VsdHM9ImhpZGUifQpzZXQuc2VlZCgxMCkKCiMgU2V0IHByaW9ycwpwcmlvciA8LSBjKAogIGJybXM6OnByaW9yKG5vcm1hbCgwLCA1KSwgImIiKSwgIyBtZWFuIG9mIDAgYW5kIFNEIG9mIDEwICh3aWRlIGRpc3RyaWJ1dGlvbikKICBicm1zOjpwcmlvcihzdHVkZW50X3QoMywgMCwgMTApLCAic2QiKSwgIyBjbGFzcyBvZiByYW5kb20gZWZmZWN0IGRldmlhdGlvbiB0byBjYWxjdWxhdGUgLSBoYXMgdG8gYmUgcG9zaXRpdmUgKG5vIG5lZ2F0aXZlIFNEKQogIGJybXM6OnByaW9yKHN0dWRlbnRfdCgzLCAwLCAxMCksICJzaWdtYSIpKSAjIHJlc2lkdWFsIFNEIHBhcmFtZXRlcgoKIyBSdW4gQ1RtYXhfVG1heF9tb2RlbApDVG1heF9UbWF4X21vZGVsIDwtIGJybXM6OmJybShDVG1heCB+IFRtYXggKyBoYWJpdGF0ICsgbGF0ICsgKDEgfCBzcGVjaWVzKSArICgxIHwgZ3Ioc3BlY2llc190cmVlLCBjb3YgPSBwaHlsbykpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhICAgID0gY2xlYW5fZGF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgID0gZ2F1c3NpYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyICAgPSBsaXN0KHBoeWxvID0gcGh5bG9fY29yKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgICA9IHByaW9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyICAgID0gMWU0LCB3YXJtdXAgPSA1ZTMsIGNvcmVzID0gNCwgY2hhaW5zID0gNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTgpKQoKIyBSdW4gV1RfVG1heF9tb2RlbApXVF9UbWF4X21vZGVsIDwtIGJybXM6OmJybShXVCB+IFRtYXggKyBoYWJpdGF0ICsgbGF0ICsgKDEgfCBzcGVjaWVzKSArICgxIHwgZ3Ioc3BlY2llc190cmVlLCBjb3YgPSBwaHlsbykpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhICAgID0gY2xlYW5fZGF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgID0gZ2F1c3NpYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyICAgPSBsaXN0KHBoeWxvID0gcGh5bG9fY29yKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgICA9IHByaW9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyICAgID0gMWU0LCB3YXJtdXAgPSA1ZTMsIGNvcmVzID0gNCwgY2hhaW5zID0gNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTgpKQoKIyBSdW4gV1RfQ1RtYXhfbW9kZWwgKGdyb3VwZWQgYnkgc3BlY2llcyBiZWNhdXNlIG9mIGNvLWNvcnJlbGF0aW9uIG9mIEN0bWF4IGFuZCBXVCB3aXRoIFRtYXgpCldUX0NUbWF4X21vZGVsIDwtIGJybXM6OmJybShXVF9tZWFuIH4gQ1RtYXhfbWVhbiArIGhhYml0YXQgKyBsYXQgKyAoMSB8IGdyKHNwZWNpZXNfdHJlZSwgY292ID0gcGh5bG8pKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgICAgPSBzdW1tYXJ5X2RhdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSAgPSBnYXVzc2lhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yICAgPSBwcmlvciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyICAgPSBsaXN0KHBoeWxvID0gcGh5bG9fY29yKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgICAgPSAxZTQsIHdhcm11cCA9IDVlMywgY29yZXMgPSA0LCBjaGFpbnMgPSA0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTgpKQpgYGAKCmBgYHtyIEZpZyBTMywgZWNobyA9IEZBTFNFLCBmaWcud2lkdGggPSA3LCBmaWcuaGVpZ2h0ID0gNiwgZmlnLmFsaWduID0nIGNlbnRlcid9CkNUbWF4X1RtYXhfbW9kZWxfcHAgPC0gYnJtczo6cHBfY2hlY2soQ1RtYXhfVG1heF9tb2RlbCwgdHlwZSA9ICJzY2F0dGVyX2F2ZyIpCldUX1RtYXhfbW9kZWxfcHAgICAgPC0gYnJtczo6cHBfY2hlY2soV1RfVG1heF9tb2RlbCwgdHlwZSA9ICJzY2F0dGVyX2F2ZyIpIApXVF9DVG1heF9tb2RlbF9wcCAgIDwtIGJybXM6OnBwX2NoZWNrKFdUX0NUbWF4X21vZGVsLCB0eXBlID0gInNjYXR0ZXJfYXZnIikgCgpjb3dwbG90OjpwbG90X2dyaWQoQ1RtYXhfVG1heF9tb2RlbF9wcCwgV1RfVG1heF9tb2RlbF9wcCwgV1RfQ1RtYXhfbW9kZWxfcHAsIG5jb2wgPSAyLCBsYWJlbHMgPSBjKCdhJywgJ2InLCAnYycpKQpgYGAKCioqRmlnLiBTMy4qKiBTY2F0dGVycGxvdHMgb2YgdGhlIG9ic2VydmVkIGRhdGEgKHkpIHZzIHRoZSBhdmVyYWdlIHNpbXVsYXRlZCBkYXRhICh5fnJlcH4pIGZyb20gdGhlIHBvc3RlcmlvciBwcmVkaWN0aXZlIGRpc3RyaWJ1dGlvbiBmb3IgdGhlICgqKmEqKikgQ1R+bWF4fi0tVH5tYXh+IG1vZGVsLCAoKipiKiopIFdULS1Ufm1heH4gbW9kZWwsIGFuZCAoKipjKiopIFdULS1DVH5tYXh+IG1vZGVsLiBEYXNoZWQgbGluZSByZXByZXNlbnRzIGEgc2xvcGUgb2YgMS4gCgoqKioKCiMjIE1vZGVsIG91dHB1dCB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30gCgojIyMgVGFibGUgUzQgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHMgLX0gCgoqKlRhYmxlIFM0LioqIFBvaW50IGVzdGltYXRlcyBhbmQgOTUlIGNyZWRpYmxlIGludGVydmFscyAoYXMgZGV0ZXJtaW5lZCB1c2luZyBCYXllc2lhbiBtZXRob2RzKSBmb3IgZml0dGVkIHBhcmFtZXRlcnMgZXN0aW1hdGVkIGZvciB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBDVH5tYXh+IGFuZCBUfm1heH4sIHdoaWNoIGluY2x1ZGVzIGZpeGVkLWVmZmVjdCBwYXJhbWV0ZXJzIGZvciAkXGJldGFfMCQsIHRoZSBhdmVyYWdlIGFjcm9zcy1zcGVjaWVzIGludGVyY2VwdDsgJFxiZXRhXzEkLCB0aGUgYXZlcmFnZSBhY3Jvc3Mtc3BlY2llcyBzbG9wZSBvZiBUfm1heH47IGhhYml0YXQgKGNsb3NlZCBhbmQgb3BlbiBoYWJpdGF0KTsgYW5kIGxhdGl0dWRlLiBHcm91cC1sZXZlbCBlZmZlY3RzIGluY2x1ZGUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbnMgKHNkKSBmb3Igc3BlY2llcy1sZXZlbCB2YXJpYXRpb24gaW4gdGhlIGludGVyY2VwdCAoJFxEZWx0YV97XGJldGFfMFtcemV0YV19JCksIGFuZCBwaHlsb2dlbmV0aWMgdmFyaWF0aW9uIGluIHRoZSBpbnRlcmNlcHQgKCRcRGVsdGFfe1xiZXRhXzBbXHBoaV19JCkuIFBoeWxvZ2VuZXRpYyBzaWduYWwgd2FzIGNhbGN1bGF0ZWQgYXMgJFxsYW1iZGEgPSBcc2lnbWFfXHBoaV4yIC8gKFxzaWdtYV9ccGhpXjIgKyBcc2lnbWFeMikkLCB3aGVyZSAkXHNpZ21hX1xwaGleMiQgaXMgdGhlIGVzdGltYXRlZCBwaHlsb2dlbmV0aWMgdmFyaWFuY2UgKGkuZS4gc2QkKFxEZWx0YV97XGJldGFfMFtccGhpXX0pXjIkKS4gCgpgYGB7ciB0YWJsZVM0LCBlY2hvID0gRkFMU0V9CiMgRml4ZWQgZWZmZWN0CmZlZiA8LSBmaXhlZihDVG1heF9UbWF4X21vZGVsKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSguKSAlPiUKICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiUGFyYW1ldGVyIikgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gc3RyX3JlcGxhY2UoUGFyYW1ldGVyLCAiTSIsICItIikpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBhcmFtZXRlciA9IGNhc2Vfd2hlbigKICAgIFBhcmFtZXRlciA9PSAiSW50ZXJjZXB0IiB+ICIkXFxiZXRhXzAkIiwKICAgIFBhcmFtZXRlciA9PSAiVG1heCIgIH4gIlR+bWF4fiwgJFxcYmV0YV8xJCIsCiAgICBQYXJhbWV0ZXIgPT0gImhhYml0YXRPcGVuIiAgfiAiSGFiaXRhdCAtIE9wZW4iLAogICAgUGFyYW1ldGVyID09ICJsYXQiICB+ICJMYXRpdHVkZSIpKSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKkZpeGVkIGVmZmVjdHMqKiIsIC5iZWZvcmUgPSAxKQoKIyBSYW5kb20gZWZmZWN0CnJlZiA8LSBzdW1tYXJ5KENUbWF4X1RtYXhfbW9kZWwpJHJhbmRvbSAlPiUgCiAgYmluZF9yb3dzKCkgJT4lICMgdW5saXN0CiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIlBhcmFtZXRlciIpICU+JSAKICBkcGx5cjo6c2VsZWN0KDE6NSkgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gYygic2QkKFxcRGVsdGFfe1xcYmV0YV8wW1xcemV0YV19KSQiLCAic2QkKFxcRGVsdGFfe1xcYmV0YV8wW1xccGhpXX0pJCIpKSAlPiUgICAKICBkcGx5cjo6cmVuYW1lKFEyLjUgID0gNCwgCiAgICAgICAgICAgICAgICBROTcuNSA9IDUpICU+JSAKICB0aWJibGU6OmFkZF9yb3coUGFyYW1ldGVyID0gIioqR3JvdXAtbGV2ZWwgZWZmZWN0cyoqIiwgLmJlZm9yZSA9IDEpCgojIFBoeWxvZ2VuZXRpYyBzaWduYWwKQ1RtYXhfVG1heF9sYW1iZGEgPC0gaHlwb3RoZXNpcyhDVG1heF9UbWF4X21vZGVsLCAic2Rfc3BlY2llc190cmVlX19JbnRlcmNlcHReMiAvIChzZF9zcGVjaWVzX3RyZWVfX0ludGVyY2VwdF4yICsgc2lnbWFeMikgPSAwIiwgY2xhc3MgPSBOVUxMKSRoeXBvdGhlc2lzICU+JSAKICBkcGx5cjo6c2VsZWN0KC1jKDEsNjo4KSkgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gIiRcXGxhbWJkYSQiKSAlPiUgCiAgZHBseXI6OnJlbmFtZShRMi41ICA9IENJLkxvd2VyLCAKICAgICAgICAgICAgICAgIFE5Ny41ID0gQ0kuVXBwZXIpICU+JSAKICB0aWJibGU6OmFkZF9yb3coUGFyYW1ldGVyID0gIioqUGh5bG9nZW5ldGljIHNpZ25hbCoqIiwgLmJlZm9yZSA9IDEpCgojIFJlbmRlciB0YWJsZQpiaW5kX3Jvd3MoZmVmLCByZWYsIENUbWF4X1RtYXhfbGFtYmRhKSAlPiUgCiAgcmVtb3ZlX3Jvd25hbWVzKCkgJT4lIAogIGtuaXRyOjprYWJsZShkaWdpdHMgPSAzKQpgYGAKCiMjIyBUYWJsZSBTNSB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxscyAtfSAKCioqVGFibGUgUzUuKiogUG9pbnQgZXN0aW1hdGVzIGFuZCA5NSUgY3JlZGlibGUgaW50ZXJ2YWxzIChhcyBkZXRlcm1pbmVkIHVzaW5nIEJheWVzaWFuIG1ldGhvZHMpIGZvciBmaXR0ZWQgcGFyYW1ldGVycyBlc3RpbWF0ZWQgZm9yIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHdhcm1pbmcgdG9sZXJhbmNlIGFuZCBUfm1heH4sIHdoaWNoIGluY2x1ZGVzIGZpeGVkLWVmZmVjdCBwYXJhbWV0ZXJzIGZvciAkXGJldGFfMCQsIHRoZSBhdmVyYWdlIGFjcm9zcy1zcGVjaWVzIGludGVyY2VwdDsgJFxiZXRhXzEkLCB0aGUgYXZlcmFnZSBhY3Jvc3Mtc3BlY2llcyBzbG9wZSBvZiBUfm1heH47IGhhYml0YXQgKGNsb3NlZCBhbmQgb3BlbiBoYWJpdGF0KTsgYW5kIGxhdGl0dWRlLiBHcm91cC1sZXZlbCBlZmZlY3RzIGluY2x1ZGUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbnMgKHNkKSBmb3Igc3BlY2llcy1sZXZlbCB2YXJpYXRpb24gaW4gdGhlIGludGVyY2VwdCAoJFxEZWx0YV97XGJldGFfMFtcemV0YV19JCksIGFuZCBwaHlsb2dlbmV0aWMgdmFyaWF0aW9uIGluIHRoZSBpbnRlcmNlcHQgKCRcRGVsdGFfe1xiZXRhXzBbXHBoaV19JCkuIFBoeWxvZ2VuZXRpYyBzaWduYWwgd2FzIGNhbGN1bGF0ZWQgYXMgJFxsYW1iZGEgPSBcc2lnbWFfXHBoaV4yIC8gKFxzaWdtYV9ccGhpXjIgKyBcc2lnbWFeMikkLCB3aGVyZSAkXHNpZ21hX1xwaGleMiQgaXMgdGhlIGVzdGltYXRlZCBwaHlsb2dlbmV0aWMgdmFyaWFuY2UgKGkuZS4gc2QkKFxEZWx0YV97XGJldGFfMFtccGhpXX0pXjIkKS4gCgpgYGB7ciB0YWJsZVM1LCBlY2hvID0gRkFMU0V9CiMgRml4ZWQgZWZmZWN0CmZlZiA8LSBmaXhlZihXVF9UbWF4X21vZGVsKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSguKSAlPiUKICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiUGFyYW1ldGVyIikgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gc3RyX3JlcGxhY2UoUGFyYW1ldGVyLCAiTSIsICItIikpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBhcmFtZXRlciA9IGNhc2Vfd2hlbigKICAgIFBhcmFtZXRlciA9PSAiSW50ZXJjZXB0IiB+ICIkXFxiZXRhXzAkIiwKICAgIFBhcmFtZXRlciA9PSAiVG1heCIgIH4gIlR+bWF4fiwgJFxcYmV0YV8xJCIsCiAgICBQYXJhbWV0ZXIgPT0gImhhYml0YXRPcGVuIiAgfiAiSGFiaXRhdCAtIE9wZW4iLAogICAgUGFyYW1ldGVyID09ICJsYXQiICB+ICJMYXRpdHVkZSIpKSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKkZpeGVkIGVmZmVjdHMqKiIsIC5iZWZvcmUgPSAxKQoKIyBSYW5kb20gZWZmZWN0CnJlZiA8LSBzdW1tYXJ5KFdUX1RtYXhfbW9kZWwpJHJhbmRvbSAlPiUgCiAgYmluZF9yb3dzKCkgJT4lICMgdW5saXN0CiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIlBhcmFtZXRlciIpICU+JSAKICBkcGx5cjo6c2VsZWN0KDE6NSkgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gYygic2QkKFxcRGVsdGFfe1xcYmV0YV8wW1xcemV0YV19KSQiLCAic2QkKFxcRGVsdGFfe1xcYmV0YV8wW1xccGhpXX0pJCIpKSAlPiUgICAKICBkcGx5cjo6cmVuYW1lKFEyLjUgID0gNCwKICAgICAgICAgICAgICAgIFE5Ny41ID0gNSkgJT4lIAogIHRpYmJsZTo6YWRkX3JvdyhQYXJhbWV0ZXIgPSAiKipHcm91cC1sZXZlbCBlZmZlY3RzKioiLCAuYmVmb3JlID0gMSkKCiMgUGh5bG9nZW5ldGljIHNpZ25hbApXVF9UbWF4X2xhbWJkYSA8LSBoeXBvdGhlc2lzKFdUX1RtYXhfbW9kZWwsICJzZF9zcGVjaWVzX3RyZWVfX0ludGVyY2VwdF4yIC8gKHNkX3NwZWNpZXNfdHJlZV9fSW50ZXJjZXB0XjIgKyBzaWdtYV4yKSA9IDAiLCBjbGFzcyA9IE5VTEwpJGh5cG90aGVzaXMgJT4lIAogIGRwbHlyOjpzZWxlY3QoLWMoMSw2OjgpKSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSAiJFxcbGFtYmRhJCIpICU+JSAKICBkcGx5cjo6cmVuYW1lKFEyLjUgID0gQ0kuTG93ZXIsCiAgICAgICAgICAgICAgICBROTcuNSA9IENJLlVwcGVyKSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKlBoeWxvZ2VuZXRpYyBzaWduYWwqKiIsIC5iZWZvcmUgPSAxKQoKIyBSZW5kZXIgdGFibGUKYmluZF9yb3dzKGZlZiwgcmVmLCBXVF9UbWF4X2xhbWJkYSkgJT4lIAogIHJlbW92ZV9yb3duYW1lcygpICU+JSAKICBrbml0cjo6a2FibGUoZGlnaXRzID0gMykKYGBgCgojIyMgVGFibGUgUzYgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHMgLX0gCgoqKlRhYmxlIFM2LioqIFBvaW50IGVzdGltYXRlcyBhbmQgOTUlIGNyZWRpYmxlIGludGVydmFscyAoYXMgZGV0ZXJtaW5lZCB1c2luZyBCYXllc2lhbiBtZXRob2RzKSBmb3IgZml0dGVkIHBhcmFtZXRlcnMgZXN0aW1hdGVkIGZvciB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB3YXJtaW5nIHRvbGVyYW5jZSBhbmQgQ1R+bWF4fiBhdCB0aGUgc3BlY2llcyBsZXZlbCwgd2hpY2ggaW5jbHVkZXMgZml4ZWQtZWZmZWN0IHBhcmFtZXRlcnMgZm9yICRcYmV0YV8wJCwgdGhlIGF2ZXJhZ2UgYWNyb3NzLXNwZWNpZXMgaW50ZXJjZXB0OyAkXGJldGFfMSQsIHRoZSBhdmVyYWdlIGFjcm9zcy1zcGVjaWVzIHNsb3BlIG9mIENUfm1heH47IGhhYml0YXQgKGNsb3NlZCBhbmQgb3BlbiBoYWJpdGF0KTsgYW5kIGxhdGl0dWRlLiBHcm91cC1sZXZlbCBlZmZlY3RzIGluY2x1ZGUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbnMgKHNkKSBmb3IgcGh5bG9nZW5ldGljIHZhcmlhdGlvbiBpbiB0aGUgaW50ZXJjZXB0ICgkXERlbHRhX3tcYmV0YV8wW1xwaGldfSQpLiBQaHlsb2dlbmV0aWMgc2lnbmFsIHdhcyBjYWxjdWxhdGVkIGFzICRcbGFtYmRhID0gXHNpZ21hX1xwaGleMiAvIChcc2lnbWFfXHBoaV4yICsgXHNpZ21hXjIpJCwgd2hlcmUgJFxzaWdtYV9ccGhpXjIkIGlzIHRoZSBlc3RpbWF0ZWQgcGh5bG9nZW5ldGljIHZhcmlhbmNlIChpLmUuIHNkJChcRGVsdGFfe1xiZXRhXzBbXHBoaV19KV4yJCkuIAoKYGBge3IgdGFibGVTNiwgZWNobyA9IEZBTFNFfQojIEZpeGVkIGVmZmVjdApmZWYgPC0gZml4ZWYoV1RfQ1RtYXhfbW9kZWwpICU+JSAKICBhcy5kYXRhLmZyYW1lKC4pICU+JQogIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKCJQYXJhbWV0ZXIiKSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSBzdHJfcmVwbGFjZShQYXJhbWV0ZXIsICJNIiwgIi0iKSkgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gY2FzZV93aGVuKAogICAgUGFyYW1ldGVyID09ICJJbnRlcmNlcHQiIH4gIiRcXGJldGFfMCQiLAogICAgUGFyYW1ldGVyID09ICJDVG1heF9tZWFuIiAgfiAiQ1R+bWF4fiwgJFxcYmV0YV8xJCIsCiAgICBQYXJhbWV0ZXIgPT0gImhhYml0YXRPcGVuIiAgfiAiSGFiaXRhdCAtIE9wZW4iLAogICAgUGFyYW1ldGVyID09ICJsYXQiICB+ICJMYXRpdHVkZSIpKSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKkZpeGVkIGVmZmVjdHMqKiIsIC5iZWZvcmUgPSAxKQoKIyBSYW5kb20gZWZmZWN0CnJlZiA8LSBzdW1tYXJ5KFdUX0NUbWF4X21vZGVsKSRyYW5kb20gJT4lIAogIGJpbmRfcm93cygpICAlPiUgIyB1bmxpc3QKICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiUGFyYW1ldGVyIikgJT4lIAogIGRwbHlyOjpzZWxlY3QoMTo1KSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSBjKCJzZCQoXFxEZWx0YV97XFxiZXRhXzBbXFxwaGldfSkkIikpICU+JSAgIAogIGRwbHlyOjpyZW5hbWUoUTIuNSAgPSA0LCAgCiAgICAgICAgICAgICAgICBROTcuNSA9IDUpICU+JSAKICB0aWJibGU6OmFkZF9yb3coUGFyYW1ldGVyID0gIioqR3JvdXAtbGV2ZWwgZWZmZWN0KioiLCAuYmVmb3JlID0gMSkKCiMgUGh5bG9nZW5ldGljIHNpZ25hbApXVF9DVG1heF9sYW1iZGEgPC0gaHlwb3RoZXNpcyhXVF9DVG1heF9tb2RlbCwgInNkX3NwZWNpZXNfdHJlZV9fSW50ZXJjZXB0XjIgLyAoc2Rfc3BlY2llc190cmVlX19JbnRlcmNlcHReMiArIHNpZ21hXjIpID0gMCIsIGNsYXNzID0gTlVMTCkkaHlwb3RoZXNpcyAlPiUgCiAgZHBseXI6OnNlbGVjdCgtYygxLDY6OCkpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBhcmFtZXRlciA9ICIkXFxsYW1iZGEkIikgJT4lIAogIGRwbHlyOjpyZW5hbWUoUTIuNSAgPSBDSS5Mb3dlciwKICAgICAgICAgICAgICAgIFE5Ny41ID0gQ0kuVXBwZXIpICU+JSAKICB0aWJibGU6OmFkZF9yb3coUGFyYW1ldGVyID0gIioqUGh5bG9nZW5ldGljIHNpZ25hbCoqIiwgLmJlZm9yZSA9IDEpCgojIFJlbmRlciB0YWJsZQpiaW5kX3Jvd3MoZmVmLCByZWYsIFdUX0NUbWF4X2xhbWJkYSkgJT4lIAogIHJlbW92ZV9yb3duYW1lcygpICU+JSAKICBrbml0cjo6a2FibGUoZGlnaXRzID0gMykKYGBgCgoqKioKCiMgSGFiaXRhdCBhbmQgcmVnaW9uIGFuYWx5c2lzCgpSdW4gYW5hbHlzaXMgbG9va2luZyBhdCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gKCoqYSoqKSBDVH5tYXh+IGFuZCAoKipiKiopIHdhcm1pbmcgdG9sZXJhbmNlIChXVCkgYmV0d2VlbiBoYWJpdGF0IChjbG9zZWQtZm9yZXN0IGFuZCBvcGVuKSBhbmQgcmVnaW9uIChzdWJ0cm9waWMgYW5kIHRlbXBlcmF0ZSkuCgpgYGB7ciByZWdpb24sIGNhY2hlID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCByZXN1bHRzPSJoaWRlIn0KQ1RtYXhfbW9kZWwgPC0gYnJtczo6YnJtKENUbWF4IH4gaGFiaXRhdCArIHJlZ2lvbiArICgxIHwgc3BlY2llcykgKyAoMSB8IGdyKHNwZWNpZXNfdHJlZSwgY292ID0gcGh5bG8pKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgICAgPSBjbGVhbl9kYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgID0gZ2F1c3NpYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiAgID0gbGlzdChwaHlsbyA9IHBoeWxvX2NvciksCiAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciAgID0gcHJpb3IsCiAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyICAgID0gMWU0LCB3YXJtdXAgPSA1ZTMsIGNvcmVzID0gNCwgY2hhaW5zID0gNCwKICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE4KSkKCldUX21vZGVsIDwtIGJybXM6OmJybShXVCB+IGhhYml0YXQgKiByZWdpb24gKyAoMSB8IHNwZWNpZXMpICsgKDEgfCBncihzcGVjaWVzX3RyZWUsIGNvdiA9IHBoeWxvKSksCiAgICAgICAgICAgICAgICAgICAgICBkYXRhICAgID0gY2xlYW5fZGF0LAogICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ICA9IGdhdXNzaWFuLAogICAgICAgICAgICAgICAgICAgICAgZGF0YTIgICA9IGxpc3QocGh5bG8gPSBwaHlsb19jb3IpLAogICAgICAgICAgICAgICAgICAgICAgcHJpb3IgICA9IHByaW9yLAogICAgICAgICAgICAgICAgICAgICAgaXRlciAgICA9IDFlNCwgd2FybXVwID0gNWUzLCBjb3JlcyA9IDQsIGNoYWlucyA9IDQsCiAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxOCkpCgpXVF9sYXRfbW9kZWwgPC0gYnJtczo6YnJtKFdUIH4gbGF0ICogaGFiaXRhdCArICgxIHwgc3BlY2llcykgKyAoMSB8IGdyKHNwZWNpZXNfdHJlZSwgY292ID0gcGh5bG8pKSwKICAgICAgICAgICAgICAgICAgICAgIGRhdGEgICAgPSBjbGVhbl9kYXQsCiAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgID0gZ2F1c3NpYW4sCiAgICAgICAgICAgICAgICAgICAgICBkYXRhMiAgID0gbGlzdChwaHlsbyA9IHBoeWxvX2NvciksCiAgICAgICAgICAgICAgICAgICAgICBwcmlvciAgID0gcHJpb3IsCiAgICAgICAgICAgICAgICAgICAgICBpdGVyICAgID0gMWU0LCB3YXJtdXAgPSA1ZTMsIGNvcmVzID0gNCwgY2hhaW5zID0gNCwKICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE4KSkKYGBgCgpgYGB7ciBGaWcgUzQsIGVjaG8gPSBGQUxTRSwgZmlnLndpZHRoID0gNywgZmlnLmhlaWdodCA9IDYsIGZpZy5hbGlnbiA9JyBjZW50ZXInfQpDVG1heF9tb2RlbF9wcCA8LSBicm1zOjpwcF9jaGVjayhDVG1heF9tb2RlbCwgdHlwZSA9ICJzY2F0dGVyX2F2ZyIpCldUX21vZGVsX3BwICAgIDwtIGJybXM6OnBwX2NoZWNrKFdUX21vZGVsLCB0eXBlID0gInNjYXR0ZXJfYXZnIikgCldUX2xhdF9tb2RlbF9wcCAgICA8LSBicm1zOjpwcF9jaGVjayhXVF9sYXRfbW9kZWwsIHR5cGUgPSAic2NhdHRlcl9hdmciKSAKCmNvd3Bsb3Q6OnBsb3RfZ3JpZChDVG1heF9tb2RlbF9wcCwgV1RfbW9kZWxfcHAsIFdUX2xhdF9tb2RlbF9wcCwgbmNvbCA9IDIsIGxhYmVscyA9IGMoJ2EnLCAnYicsICdjJykpCmBgYAoKKipGaWcuIFM0LioqIFNjYXR0ZXJwbG90cyBvZiB0aGUgb2JzZXJ2ZWQgZGF0YSAoeSkgdnMgdGhlIGF2ZXJhZ2Ugc2ltdWxhdGVkIGRhdGEgKHl+cmVwfikgZnJvbSB0aGUgcG9zdGVyaW9yIHByZWRpY3RpdmUgZGlzdHJpYnV0aW9uIGZvciB0aGUgKCoqYSoqKSBDVH5tYXh+IG1vZGVsLCAoKipiKiopIFdUIG1vZGVsLCBhbmQgKCoqYyoqKSBXVC0tbGF0aXR1ZGUgbW9kZWwuIERhc2hlZCBsaW5lIHJlcHJlc2VudHMgYSBzbG9wZSBvZiAxLiAKCioqKgoKIyMgTW9kZWwgb3V0cHV0IHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKIyMjIFRhYmxlIFM3IHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKKipUYWJsZSBTNy4qKiBQb2ludCBlc3RpbWF0ZXMgYW5kIDk1JSBjcmVkaWJsZSBpbnRlcnZhbHMgKGFzIGRldGVybWluZWQgdXNpbmcgQmF5ZXNpYW4gbWV0aG9kcykgZm9yIGZpdHRlZCBwYXJhbWV0ZXJzIGVzdGltYXRlZCBmb3IgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIENUfm1heH4gd2l0aCBoYWJpdGF0IGFuZCByZWdpb24sIHdoaWNoIGluY2x1ZGVzIGZpeGVkLWVmZmVjdCBwYXJhbWV0ZXJzIGZvciAkXGJldGFfMCQsIHRoZSBhdmVyYWdlIGFjcm9zcy1zcGVjaWVzIGludGVyY2VwdDsgaGFiaXRhdCAoY2xvc2VkIGFuZCBvcGVuIGhhYml0YXQpOyBhbmQgcmVnaW9uIChzdWJ0cm9waWNzLCB0ZW1wZXJhdGUpLiBHcm91cC1sZXZlbCBlZmZlY3RzIGluY2x1ZGUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbnMgKHNkKSBmb3Igc3BlY2llcy1sZXZlbCB2YXJpYXRpb24gaW4gdGhlIGludGVyY2VwdCAoJFxEZWx0YV97XGJldGFfMFtcemV0YV19JCksIGFuZCBwaHlsb2dlbmV0aWMgdmFyaWF0aW9uIGluIHRoZSBpbnRlcmNlcHQgKCRcRGVsdGFfe1xiZXRhXzBbXHBoaV19JCkuIFBoeWxvZ2VuZXRpYyBzaWduYWwgd2FzIGNhbGN1bGF0ZWQgYXMgJFxsYW1iZGEgPSBcc2lnbWFfXHBoaV4yIC8gKFxzaWdtYV9ccGhpXjIgKyBcc2lnbWFeMikkLCB3aGVyZSAkXHNpZ21hX1xwaGleMiQgaXMgdGhlIGVzdGltYXRlZCBwaHlsb2dlbmV0aWMgdmFyaWFuY2UgKGkuZS4gc2QkKFxEZWx0YV97XGJldGFfMFtccGhpXX0pXjIkKS4gCgpgYGB7ciB0YWJsZVM3LCBlY2hvID0gRkFMU0V9CiMgRml4ZWQgZWZmZWN0CmZlZiA8LSBmaXhlZihDVG1heF9tb2RlbCkgJT4lIAogIGFzLmRhdGEuZnJhbWUoLikgJT4lCiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIlBhcmFtZXRlciIpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBhcmFtZXRlciA9IHN0cl9yZXBsYWNlKFBhcmFtZXRlciwgIk0iLCAiLSIpKSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSBjYXNlX3doZW4oCiAgICBQYXJhbWV0ZXIgPT0gIkludGVyY2VwdCIgfiAiJFxcYmV0YV8wJCIsCiAgICBQYXJhbWV0ZXIgPT0gImhhYml0YXRPcGVuIiAgfiAiSGFiaXRhdCAtIE9wZW4iLAogICAgUGFyYW1ldGVyID09ICJyZWdpb25UZW1wZXJhdGUiICB+ICJSZWdpb24gLSBUZW1wZXJhdGUiKSkgJT4lIAogIHRpYmJsZTo6YWRkX3JvdyhQYXJhbWV0ZXIgPSAiKipGaXhlZCBlZmZlY3RzKioiLCAuYmVmb3JlID0gMSkKCiMgUmFuZG9tIGVmZmVjdApyZWYgPC0gc3VtbWFyeShDVG1heF9tb2RlbCkkcmFuZG9tICU+JSAKICBiaW5kX3Jvd3MoKSAlPiUgIyB1bmxpc3QKICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiUGFyYW1ldGVyIikgJT4lIAogIGRwbHlyOjpzZWxlY3QoMTo1KSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSBjKCJzZCQoXFxEZWx0YV97XFxiZXRhXzBbXFx6ZXRhXX0pJCIsICJzZCQoXFxEZWx0YV97XFxiZXRhXzBbXFxwaGldfSkkIikpICU+JSAgIAogIGRwbHlyOjpyZW5hbWUoUTIuNSAgPSA0LCAKICAgICAgICAgICAgICAgIFE5Ny41ID0gNSkgJT4lIAogIHRpYmJsZTo6YWRkX3JvdyhQYXJhbWV0ZXIgPSAiKipHcm91cC1sZXZlbCBlZmZlY3RzKioiLCAuYmVmb3JlID0gMSkKCiMgUGh5bG9nZW5ldGljIHNpZ25hbApDVG1heF9sYW1iZGEgPC0gaHlwb3RoZXNpcyhDVG1heF9tb2RlbCwgInNkX3NwZWNpZXNfdHJlZV9fSW50ZXJjZXB0XjIgLyAoc2Rfc3BlY2llc190cmVlX19JbnRlcmNlcHReMiArIHNpZ21hXjIpID0gMCIsIGNsYXNzID0gTlVMTCkkaHlwb3RoZXNpcyAlPiUgCiAgZHBseXI6OnNlbGVjdCgtYygxLDY6OCkpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBhcmFtZXRlciA9ICIkXFxsYW1iZGEkIikgJT4lIAogIGRwbHlyOjpyZW5hbWUoUTIuNSAgPSBDSS5Mb3dlciwgCiAgICAgICAgICAgICAgICBROTcuNSA9IENJLlVwcGVyKSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKlBoeWxvZ2VuZXRpYyBzaWduYWwqKiIsIC5iZWZvcmUgPSAxKQoKIyBSZW5kZXIgdGFibGUKYmluZF9yb3dzKGZlZiwgcmVmLCBDVG1heF9sYW1iZGEpICU+JSAKICByZW1vdmVfcm93bmFtZXMoKSAlPiUgCiAga25pdHI6OmthYmxlKGRpZ2l0cyA9IDMpCmBgYAoKIyMjIFRhYmxlIFM4IHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzIC19IAoKKipUYWJsZSBTOC4qKiBQb2ludCBlc3RpbWF0ZXMgYW5kIDk1JSBjcmVkaWJsZSBpbnRlcnZhbHMgKGFzIGRldGVybWluZWQgdXNpbmcgQmF5ZXNpYW4gbWV0aG9kcykgZm9yIGZpdHRlZCBwYXJhbWV0ZXJzIGVzdGltYXRlZCBmb3IgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gd2FybWluZyB0b2xlcmFuY2UgYW5kIFR+bWF4fiwgd2hpY2ggaW5jbHVkZXMgZml4ZWQtZWZmZWN0IHBhcmFtZXRlcnMgZm9yICRcYmV0YV8wJCwgdGhlIGF2ZXJhZ2UgYWNyb3NzLXNwZWNpZXMgaW50ZXJjZXB0OyAkXGJldGFfMSQsIHRoZSBhdmVyYWdlIGFjcm9zcy1zcGVjaWVzIHNsb3BlIG9mIFR+bWF4fjsgaGFiaXRhdCAoY2xvc2VkIGFuZCBvcGVuIGhhYml0YXQpOyBhbmQgbGF0aXR1ZGUuIEdyb3VwLWxldmVsIGVmZmVjdHMgaW5jbHVkZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9ucyAoc2QpIGZvciBzcGVjaWVzLWxldmVsIHZhcmlhdGlvbiBpbiB0aGUgaW50ZXJjZXB0ICgkXERlbHRhX3tcYmV0YV8wW1x6ZXRhXX0kKSwgYW5kIHBoeWxvZ2VuZXRpYyB2YXJpYXRpb24gaW4gdGhlIGludGVyY2VwdCAoJFxEZWx0YV97XGJldGFfMFtccGhpXX0kKS4gUGh5bG9nZW5ldGljIHNpZ25hbCB3YXMgY2FsY3VsYXRlZCBhcyAkXGxhbWJkYSA9IFxzaWdtYV9ccGhpXjIgLyAoXHNpZ21hX1xwaGleMiArIFxzaWdtYV4yKSQsIHdoZXJlICRcc2lnbWFfXHBoaV4yJCBpcyB0aGUgZXN0aW1hdGVkIHBoeWxvZ2VuZXRpYyB2YXJpYW5jZSAoaS5lLiBzZCQoXERlbHRhX3tcYmV0YV8wW1xwaGldfSleMiQpLiAKCmBgYHtyIHRhYmxlUzgsIGVjaG8gPSBGQUxTRX0KIyBGaXhlZCBlZmZlY3QKZmVmIDwtIGZpeGVmKFdUX21vZGVsKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSguKSAlPiUKICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiUGFyYW1ldGVyIikgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gc3RyX3JlcGxhY2UoUGFyYW1ldGVyLCAiTSIsICItIikpICU+JSAKICBkcGx5cjo6bXV0YXRlKFBhcmFtZXRlciA9IGNhc2Vfd2hlbigKICAgIFBhcmFtZXRlciA9PSAiSW50ZXJjZXB0IiB+ICIkXFxiZXRhXzAkIiwKICAgIFBhcmFtZXRlciA9PSAiaGFiaXRhdE9wZW4iICB+ICJIYWJpdGF0IC0gT3BlbiIsCiAgICBQYXJhbWV0ZXIgPT0gInJlZ2lvblRlbXBlcmF0ZSIgIH4gIlJlZ2lvbiAtIFRlbXBlcmF0ZSIsCiAgICBQYXJhbWV0ZXIgPT0gImhhYml0YXRPcGVuOnJlZ2lvblRlbXBlcmF0ZSIgIH4gIkhhYml0YXQgLSBPcGVuOiBSZWdpb24gLSBUZW1wZXJhdGUiKSkgJT4lIAogIHRpYmJsZTo6YWRkX3JvdyhQYXJhbWV0ZXIgPSAiKipGaXhlZCBlZmZlY3RzKioiLCAuYmVmb3JlID0gMSkKCiMgUmFuZG9tIGVmZmVjdApyZWYgPC0gc3VtbWFyeShXVF9tb2RlbCkkcmFuZG9tICU+JSAKICBiaW5kX3Jvd3MoKSAlPiUgIyB1bmxpc3QKICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiUGFyYW1ldGVyIikgJT4lIAogIGRwbHlyOjpzZWxlY3QoMTo1KSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSBjKCJzZCQoXFxEZWx0YV97XFxiZXRhXzBbXFx6ZXRhXX0pJCIsICJzZCQoXFxEZWx0YV97XFxiZXRhXzBbXFxwaGldfSkkIikpICU+JSAgIAogIGRwbHlyOjpyZW5hbWUoUTIuNSAgPSA0LAogICAgICAgICAgICAgICAgUTk3LjUgPSA1KSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKkdyb3VwLWxldmVsIGVmZmVjdHMqKiIsIC5iZWZvcmUgPSAxKQoKIyBQaHlsb2dlbmV0aWMgc2lnbmFsCldUX2xhbWJkYSA8LSBoeXBvdGhlc2lzKFdUX21vZGVsLCAic2Rfc3BlY2llc190cmVlX19JbnRlcmNlcHReMiAvIChzZF9zcGVjaWVzX3RyZWVfX0ludGVyY2VwdF4yICsgc2lnbWFeMikgPSAwIiwgY2xhc3MgPSBOVUxMKSRoeXBvdGhlc2lzICU+JSAKICBkcGx5cjo6c2VsZWN0KC1jKDEsNjo4KSkgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gIiRcXGxhbWJkYSQiKSAlPiUgCiAgZHBseXI6OnJlbmFtZShRMi41ICA9IENJLkxvd2VyLAogICAgICAgICAgICAgICAgUTk3LjUgPSBDSS5VcHBlcikgJT4lIAogIHRpYmJsZTo6YWRkX3JvdyhQYXJhbWV0ZXIgPSAiKipQaHlsb2dlbmV0aWMgc2lnbmFsKioiLCAuYmVmb3JlID0gMSkKCiMgUmVuZGVyIHRhYmxlCmJpbmRfcm93cyhmZWYsIHJlZiwgV1RfbGFtYmRhKSAlPiUgCiAgcmVtb3ZlX3Jvd25hbWVzKCkgJT4lIAogIGtuaXRyOjprYWJsZShkaWdpdHMgPSAzKQpgYGAKCiMgV2FybWluZyBhbmQgZGVmb3Jlc2F0aW9uIGFuYWx5c2lzCgpSdW4gYW5hbHlzaXMgbG9va2luZyBhdCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gY2xpbWF0ZSAoY3VycmVudCBhbmQgd2FybWluZyksIHdpdGggdGhlIGludGVyYWN0aW9uIGJldHdlZW4gY2F0ZWdvcnkgKG9wZW4gYW5kIHNoYWRlZCBzaW11bGF0ZWQgaGFiaXRhdCksIGhhYml0YXQgKGNsb3NlZCBhbmQgb3BlbiBoYWJpdGF0IC0gYnJlZWRpbmcpIGFuZCByZWdpb24gKHN1YnRyb3BpY3MsIHRlbXBlcmF0ZSkgb24gd2FybWluZyB0b2xlcmFuY2UuCgpgYGB7ciBwcm9qLCBjYWNoZSA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgcmVzdWx0cz0iaGlkZSJ9CiMgQ2FsY3VsYXRlIFdUCnByb2pfZGF0YSA8LSBwcm9qX2RhdGEgJT4lCiAgZHBseXI6Om11dGF0ZShXVF9zaGFkZV9jdXIgPSBDVG1heF9tZWFuIC0gZXN0X1RtYXhfc2hhZGUsCiAgICAgICAgICAgICAgICBXVF9vcGVuX2N1ciAgPSBDVG1heF9tZWFuIC0gZXN0X1RtYXhfb3BlbiwKICAgICAgICAgICAgICAgIFdUX3NoYWRlXzRDICA9IENUbWF4X21lYW4gLSBlc3RfVG1heF9zaGFkZV80QywKICAgICAgICAgICAgICAgIFdUX29wZW5fNEMgICA9IENUbWF4X21lYW4gLSBlc3RfVG1heF9vcGVuXzRDKQoKIyBDb252ZXJ0IHdpZGUgdG8gbG9uZyBmb3JtYXQKcHJval9sb25nIDwtIHByb2pfZGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KHJlZ2lvbiwgc3BlY2llcywgQ1RtYXhfbWVhbiwgaGFiaXRhdCwgbGF0LCBXVF9zaGFkZV9jdXIsIFdUX29wZW5fY3VyLCBXVF9zaGFkZV80QywgV1Rfb3Blbl80QykgJT4lCiAgdGlkeXI6OnBpdm90X2xvbmdlcighYyhyZWdpb24sIHNwZWNpZXMsIENUbWF4X21lYW4sIGhhYml0YXQsIGxhdCksIG5hbWVzX3RvID0gImNhdGVnb3J5IiwgdmFsdWVzX3RvID0gInZhbHVlcyIpICU+JQogIGRwbHlyOjptdXRhdGUoY2xpbWF0ZSA9IGNhc2Vfd2hlbihlbmRzV2l0aChjYXRlZ29yeSwgImN1ciIpIH4gIkN1cnJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmRzV2l0aChjYXRlZ29yeSwgIjRDIil+ICJXYXJtaW5nIiksCiAgICAgICAgICAgICAgICBjYXRlZ29yeSA9IGRwbHlyOjpyZWNvZGUoY2F0ZWdvcnksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdUX29wZW5fY3VyID0gIk9wZW4gaGFiaXRhdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV1Rfc2hhZGVfY3VyID0gIlNoYWRlZCBoYWJpdGF0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXVF9vcGVuXzRDID0gIk9wZW4gaGFiaXRhdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV1Rfc2hhZGVfNEMgPSAiU2hhZGVkIGhhYml0YXQiKSkKCiMgQWRkIHBoeWxvZ2VueSB0byBkYXRhc2V0CnByb2pfbG9uZyRzcGVjaWVzX3RyZWUgPC0gc3VtbWFyeV9kYXQkc3BlY2llc190cmVlW21hdGNoKHByb2pfbG9uZyRzcGVjaWVzLCBzdW1tYXJ5X2RhdCRzcGVjaWVzKV0KCiMgUnVuIGJybXMgbW9kZWwKcHJval9tb2RlbCA8LSBicm1zOjpicm0odmFsdWVzIH4gY2xpbWF0ZSArIGNhdGVnb3J5ICogaGFiaXRhdCAqIHJlZ2lvbiArICgxIHwgc3BlY2llcykgKyAoMSB8IGdyKHNwZWNpZXNfdHJlZSwgY292ID0gcGh5bG8pKSwKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSAgICA9IHByb2pfbG9uZywKICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ICA9IGdhdXNzaWFuLAogICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiAgID0gbGlzdChwaHlsbyA9IHBoeWxvX2NvciksCiAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgICAgPSAxZTQsIHdhcm11cCA9IDVlMywgY29yZXMgPSA0LCBjaGFpbnMgPSA0LAogICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxOCkpCmBgYAoKYGBge3IgRmlnIFM1LCBlY2hvID0gRkFMU0UsIGZpZy53aWR0aCA9IDQsIGZpZy5oZWlnaHQgPSAzLCBmaWcuYWxpZ24gPSAnY2VudGVyJ30KYnJtczo6cHBfY2hlY2socHJval9tb2RlbCwgdHlwZSA9ICJzY2F0dGVyX2F2ZyIpCmBgYAoKKipGaWcuIFM1LioqIFNjYXR0ZXJwbG90IG9mIHRoZSBvYnNlcnZlZCBkYXRhICh5KSB2cyB0aGUgYXZlcmFnZSBzaW11bGF0ZWQgZGF0YSAoeXJlcCkgZnJvbSB0aGUgcG9zdGVyaW9yIHByZWRpY3RpdmUgZGlzdHJpYnV0aW9uIGZvciB0aGUgY2xpbWF0ZSBhbmQgZGVmb3Jlc3RhdGlvbiBwcm9qZWN0aW9uIG1vZGVsLiBEYXNoZWQgbGluZSByZXByZXNlbnRzIGEgc2xvcGUgb2YgMS4gCgojIyBNb2RlbCBvdXRwdXQKCioqVGFibGUgUzkuKiogUG9pbnQgZXN0aW1hdGVzIGFuZCA5NSUgY3JlZGlibGUgaW50ZXJ2YWxzIChhcyBkZXRlcm1pbmVkIHVzaW5nIEJheWVzaWFuIG1ldGhvZHMpIGZvciBmaXR0ZWQgcGFyYW1ldGVycyBlc3RpbWF0ZWQgZm9yIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB3YXJtaW5nIHRvbGVyYW5jZSB3aXRoIGNsaW1hdGUgY2hhbmdlIGFuZCBkZWZvcmVzdGF0aW9uLCB3aGljaCBpbmNsdWRlcyBmaXhlZC1lZmZlY3QgcGFyYW1ldGVycyBmb3IgJFxiZXRhXzAkLCB0aGUgYXZlcmFnZSBhY3Jvc3Mtc3BlY2llcyBpbnRlcmNlcHQ7IGNsaW1hdGUgKGN1cnJlbnQsIHdhcm1pbmcpOyBhbmQgdGhlIHRocmVlLXdheSBpbnRlcmFjdGlvbiB3aXRoIHNoYWRlZCAob3BlbiBhbmQgc2hhZGVkIHNpbXVsYXRlZCBoYWJpdGF0KSwgaGFiaXRhdCAoY2xvc2VkIGFuZCBvcGVuIGhhYml0YXQgLSBicmVlZGluZykgYW5kIHJlZ2lvbiAoc3VidHJvcGljcywgdGVtcGVyYXRlKS4gR3JvdXAtbGV2ZWwgZWZmZWN0cyBpbmNsdWRlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb25zIChzZCkgZm9yIHNwZWNpZXMtbGV2ZWwgdmFyaWF0aW9uIGluIHRoZSBpbnRlcmNlcHQgKCRcRGVsdGFfe1xiZXRhXzBbXHpldGFdfSQpLCBhbmQgcGh5bG9nZW5ldGljIHZhcmlhdGlvbiBpbiB0aGUgaW50ZXJjZXB0ICgkXERlbHRhX3tcYmV0YV8wW1xwaGldfSQpLiBQaHlsb2dlbmV0aWMgc2lnbmFsIHdhcyBjYWxjdWxhdGVkIGFzICRcbGFtYmRhID0gXHNpZ21hX1xwaGleMiAvIChcc2lnbWFfXHBoaV4yICsgXHNpZ21hXjIpJCwgd2hlcmUgJFxzaWdtYV9ccGhpXjIkIGlzIHRoZSBlc3RpbWF0ZWQgcGh5bG9nZW5ldGljIHZhcmlhbmNlIChpLmUuIHNkJChcRGVsdGFfe1xiZXRhXzBbXHBoaV19KV4yJCkuIAoKYGBge3IgdGFibGVTOSwgZWNobz1GQUxTRX0KIyBGaXhlZCBlZmZlY3QKZmVmIDwtIGZpeGVmKHByb2pfbW9kZWwpICU+JSAKICBhcy5kYXRhLmZyYW1lKC4pICU+JQogIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKCJQYXJhbWV0ZXIiKSAlPiUgCiAgZHBseXI6Om11dGF0ZShQYXJhbWV0ZXIgPSBzdHJfcmVwbGFjZShQYXJhbWV0ZXIsICJNIiwgIi0iKSkgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gY2FzZV93aGVuKAogICAgUGFyYW1ldGVyID09ICJJbnRlcmNlcHQiIH4gIiRcXGJldGFfMCQiLAogICAgUGFyYW1ldGVyID09ICJjbGltYXRlV2FybWluZyIgIH4gIkNsaW1hdGUgLSBXYXJtaW5nIiwKICAgIFBhcmFtZXRlciA9PSAiY2F0ZWdvcnlTaGFkZWRoYWJpdGF0IiAgfiAiU2hhZGVkIiwKICAgIFBhcmFtZXRlciA9PSAiaGFiaXRhdE9wZW4iICB+ICJIYWJpdGF0IC0gT3BlbiIsCiAgICBQYXJhbWV0ZXIgPT0gInJlZ2lvblRlbXBlcmF0ZSIgIH4gIlJlZ2lvbiAtIFRlbXBlcmF0ZSIsCiAgICBQYXJhbWV0ZXIgPT0gImNhdGVnb3J5U2hhZGVkaGFiaXRhdDpoYWJpdGF0T3BlbiIgIH4gIlNoYWRlZDogSGFiaXRhdCAtIE9wZW4iLAogICAgUGFyYW1ldGVyID09ICJjYXRlZ29yeVNoYWRlZGhhYml0YXQ6cmVnaW9uVGVtcGVyYXRlIiAgfiAiU2hhZGVkOiBSZWdpb24gLSBUZW1wZXJhdGUiLAogICAgUGFyYW1ldGVyID09ICJoYWJpdGF0T3BlbjpyZWdpb25UZW1wZXJhdGUiICB+ICJIYWJpdGF0IC0gT3BlbjogUmVnaW9uIC0gVGVtcGVyYXRlIiwKICAgIFBhcmFtZXRlciA9PSAiY2F0ZWdvcnlTaGFkZWRoYWJpdGF0OmhhYml0YXRPcGVuOnJlZ2lvblRlbXBlcmF0ZSIgIH4gIlNoYWRlZDogSGFiaXRhdCAtIE9wZW46IFJlZ2lvbiAtIFRlbXBlcmF0ZSIpKSAlPiUgCiAgdGliYmxlOjphZGRfcm93KFBhcmFtZXRlciA9ICIqKkZpeGVkIGVmZmVjdHMqKiIsIC5iZWZvcmUgPSAxKQoKIyBSYW5kb20gZWZmZWN0CnJlZiA8LSBzdW1tYXJ5KHByb2pfbW9kZWwpJHJhbmRvbSAlPiUgCiAgYmluZF9yb3dzKCkgJT4lICMgdW5saXN0CiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIlBhcmFtZXRlciIpICU+JSAKICBkcGx5cjo6c2VsZWN0KDE6NSkgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gYygic2QkKFxcRGVsdGFfe1xcYmV0YV8wW1xcemV0YV19KSQiLCAic2QkKFxcRGVsdGFfe1xcYmV0YV8wW1xccGhpXX0pJCIpKSAlPiUgICAKICBkcGx5cjo6cmVuYW1lKFEyLjUgID0gNCwgCiAgICAgICAgICAgICAgICBROTcuNSA9IDUpICU+JSAKICB0aWJibGU6OmFkZF9yb3coUGFyYW1ldGVyID0gIioqR3JvdXAtbGV2ZWwgZWZmZWN0cyoqIiwgLmJlZm9yZSA9IDEpCgojIFBoeWxvZ2VuZXRpYyBzaWduYWwKcHJval9sYW1iZGEgPC0gaHlwb3RoZXNpcyhwcm9qX21vZGVsLCAic2Rfc3BlY2llc190cmVlX19JbnRlcmNlcHReMiAvIChzZF9zcGVjaWVzX3RyZWVfX0ludGVyY2VwdF4yICsgc2lnbWFeMikgPSAwIiwgY2xhc3MgPSBOVUxMKSRoeXBvdGhlc2lzICU+JSAKICBkcGx5cjo6c2VsZWN0KC1jKDEsNjo4KSkgJT4lIAogIGRwbHlyOjptdXRhdGUoUGFyYW1ldGVyID0gIiRcXGxhbWJkYSQiKSAlPiUgCiAgZHBseXI6OnJlbmFtZShRMi41ICA9IENJLkxvd2VyLCAKICAgICAgICAgICAgICAgIFE5Ny41ID0gQ0kuVXBwZXIpICU+JSAKICB0aWJibGU6OmFkZF9yb3coUGFyYW1ldGVyID0gIioqUGh5bG9nZW5ldGljIHNpZ25hbCoqIiwgLmJlZm9yZSA9IDEpCgojIFJlbmRlciB0YWJsZQpiaW5kX3Jvd3MoZmVmLCByZWYsIHByb2pfbGFtYmRhKSAlPiUgCiAgcmVtb3ZlX3Jvd25hbWVzKCkgJT4lIAogIGtuaXRyOjprYWJsZShkaWdpdHMgPSAzKQpgYGAKCioqKgoKIyBGaWd1cmVzIGZvciBtYWluIHRleHQKClJhdyBmaWd1cmVzIHByb2R1Y2VkIHdlcmUgbW9kaWZpZWQgaW4gW0Fkb2JlIElsbHVzdHJhdG9yXShodHRwczovL3d3dy5hZG9iZS5jb20vYXUvcHJvZHVjdHMvaWxsdXN0cmF0b3IuaHRtbCkgZm9yIHB1YmxpY2F0aW9uLgoKIyMgRmlndXJlIDIgLSBDVH5tYXh+LCBUfm1heH4sIHdhcm1pbmcgdG9sZXJhbmNlIHJlbGF0aW9uc2hpcAoKYGBge3IgRmlnIDIsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD0yLjUsIGZpZy53aWR0aD05fQojIEV4dHJhY3QgbWFyZ2luYWwgZWZmZWN0cwpDVG1heF9UbWF4X21lIDwtIGFzLmRhdGEuZnJhbWUoZ2dlZmZlY3RzOjpnZ3ByZWRpY3QoQ1RtYXhfVG1heF9tb2RlbCwgdGVybXMgPSBjKCJUbWF4W3NhbXBsZSA9IDI1XSIpKSkgCldUX1RtYXhfbWUgICAgPC0gYXMuZGF0YS5mcmFtZShnZ2VmZmVjdHM6OmdncHJlZGljdChXVF9UbWF4X21vZGVsLCB0ZXJtcyA9IGMoIlRtYXhbc2FtcGxlID0gMjVdIikpKSAKCiMgRmlnIDIKY3RtYXhfdG1heF9wbG90IDwtIHN1bW1hcnlfZGF0ICU+JQogIGdncGxvdCgpICsKICBnZW9tX3JpYmJvbihkYXRhID0gQ1RtYXhfVG1heF9tZSwgYWVzKHggPSB4LCB5bWluID0gY29uZi5sb3csIHltYXggPSBjb25mLmhpZ2gpLCBmaWxsID0gIiNGRTk0NUMiLGFscGhhID0gMC4xKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDVG1heF9UbWF4X21lLCBhZXMoeCA9IHgsIHkgPSBjb25mLmxvdyksIGNvbG91ciA9ICIjRkU5NDVDIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fbGluZShkYXRhID0gQ1RtYXhfVG1heF9tZSwgYWVzKHggPSB4LCB5ID0gY29uZi5oaWdoKSwgY29sb3VyID0gIiNGRTk0NUMiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDVG1heF9UbWF4X21lLCBhZXMoeCA9IHgsIHkgPSBwcmVkaWN0ZWQpLCBjb2xvdXIgPSAiI0REM0IyNCIsIHNpemUgPSAxKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IFRtYXgsIHkgPSBDVG1heF9tZWFuLCBjb2xvdXIgPSByZWdpb24sIHNoYXBlID0gaGFiaXRhdCksIHNpemUgPSAyLCBmaWxsID0gIndoaXRlIikgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDE3LCAyMSkpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIiNERDNCMjQiLCAiI0ZFOTQ1QyIpKSArCiAgeGxhYihleHByZXNzaW9uKFRbIm1heCJdfiIowrBDKSIpKSArCiAgeWxhYihleHByZXNzaW9uKCJDVCJbIm1heCJdfiIowrBDKSIpKSArCiAgbXl0aGVtZSgpCgp3dF90bWF4X3Bsb3QgPC0gc3VtbWFyeV9kYXQgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcmliYm9uKGRhdGEgPSBXVF9UbWF4X21lLCBhZXMoeCA9IHgsIHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCksIGZpbGwgPSAiI0ZFOTQ1QyIsYWxwaGEgPSAwLjEpICsKICBnZW9tX2xpbmUoZGF0YSA9IFdUX1RtYXhfbWUsIGFlcyh4ID0geCwgeSA9IGNvbmYubG93KSwgY29sb3VyID0gIiNGRTk0NUMiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBXVF9UbWF4X21lLCBhZXMoeCA9IHgsIHkgPSBjb25mLmhpZ2gpLCBjb2xvdXIgPSAiI0ZFOTQ1QyIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFdUX1RtYXhfbWUsIGFlcyh4ID0geCwgeSA9IHByZWRpY3RlZCksIGNvbG91ciA9ICIjREQzQjI0Iiwgc2l6ZSA9IDEpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gVG1heCwgeSA9IFdUX21lYW4sIGNvbG91ciA9IHJlZ2lvbiwgc2hhcGUgPSBoYWJpdGF0KSwgc2l6ZSA9IDIsIGZpbGwgPSAid2hpdGUiKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMTcsIDIxKSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiI0REM0IyNCIsICIjRkU5NDVDIikpICsKICB4bGFiKGV4cHJlc3Npb24oVFsnbWF4J11+IijCsEMpIikpICsKICB5bGFiKCJXYXJtaW5nIHRvbGVyYW5jZSIpICsKICBteXRoZW1lKCkKCnd0X2N0bWF4X3Bsb3QgPC0gc3VtbWFyeV9kYXQgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoYWVzKHggPSBDVG1heF9tZWFuLCB5ID0gV1RfbWVhbiwgY29sb3VyID0gcmVnaW9uLCBzaGFwZSA9IGhhYml0YXQpLCBzaXplID0gMiwgZmlsbCA9ICJ3aGl0ZSIpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygxNywgMjEpKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCIjREQzQjI0IiwgIiNGRTk0NUMiKSkgKwogIHhsYWIoZXhwcmVzc2lvbihDVFsnbWF4J11+IijCsEMpIikpICsKICB5bGFiKCJXYXJtaW5nIHRvbGVyYW5jZSIpICsKICBteXRoZW1lKCkKCmNvd3Bsb3Q6OnBsb3RfZ3JpZChjdG1heF90bWF4X3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLCAKICAgICAgICAgICAgICAgICAgIHd0X3RtYXhfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIAogICAgICAgICAgICAgICAgICAgd3RfY3RtYXhfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksCiAgICAgICAgICAgICAgICAgICBuY29sID0gMywgYWxpZ24gPSAiaHYiLCBheGlzID0gInRibHIiLCBsYWJlbHMgPSBjKCJhIiwgImIiLCAiYyIpKQpgYGAKCgojIyBGaWd1cmUgMyAtIENUfm1heH4gYW5kIHdhcm1pbmcgdG9sZXJhbmNlIGFjcm9zcyBoYWJpdGF0IGFuZCByZWdpb24KCkxhdGl0dWRlIGFzIGNhdGVnb3J5ICgqKkZpZy4gM2EgYW5kIDNiKiopCgpgYGB7ciBGaWcgMywgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9OCwgZmlnLmFsaWduPSdjZW50ZXInfQojIEZpZyAzIHByb2R1Y3Rpb24KQ1RtYXhfcGxvdCA8LSBzdW1tYXJ5X2RhdCAlPiUKICAjIHJlZ3JvdXBpbmcKICBkcGx5cjo6Z3JvdXBfYnkocmVnaW9uKSAlPiUKICBkcGx5cjo6YXJyYW5nZShoYWJpdGF0LCBDVG1heF9tZWFuKSAlPiUKICBtdXRhdGUoeCA9IHJvd19udW1iZXIoKSkgJT4lICMgY2hhbmdlIHRvIG51bWJlciB0byBvcmRlciBieSBoYWJpdGF0IGFuZCBDVG1heAogIHVuZ3JvdXAoKSAlPiUKICAjIHBsb3R0aW5nCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IENUbWF4X21lYW4sIGNvbG91ciA9IHJlZ2lvbiwgc2hhcGUgPSBoYWJpdGF0LCBsYWJlbCA9IHNwX2FiYnIpKSArCiAgc3RhdF9tZWFuX2xpbmUoYWVzKGxpbmV0eXBlID0gaGFiaXRhdCksICBhbHBoYSA9IDAuNSkgKwogIGdlb21fcG9pbnRyYW5nZShhZXMoeW1pbiA9IENUbWF4X21lYW4gLSBDVG1heF9TRCwgeW1heCA9IENUbWF4X21lYW4gKyBDVG1heF9TRCwgbGluZXR5cGUgPSBoYWJpdGF0KSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGZpbGwgPSAid2hpdGUiKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMTcsIDIxKSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiI0REM0IyNCIsICIjRkU5NDVDIikpICsKICBnZW9tX3RleHQobnVkZ2VfeSA9IDEuNSwgc2l6ZSA9IDMsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICB4bGFiKE5VTEwpICsKICB5bGFiKGV4cHJlc3Npb24oIkNUIlsibWF4Il1+IijCsEMpIikpICsKICBmYWNldF9ncmlkKC4gfiByZWdpb24sIHNjYWxlcyA9ICdmcmVlX3gnKSArCiAgbXl0aGVtZSgpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSkKCldUX3Bsb3QgPC0gc3VtbWFyeV9kYXQgJT4lCiAgIyByZWdyb3VwaW5nCiAgZHBseXI6Omdyb3VwX2J5KHJlZ2lvbikgJT4lCiAgZHBseXI6OmFycmFuZ2UoaGFiaXRhdCwgV1RfbWVhbikgJT4lCiAgbXV0YXRlKHggPSByb3dfbnVtYmVyKCkpICU+JSAjIGNoYW5nZSB0byBudW1iZXIgdG8gb3JkZXIgYnkgaGFiaXRhdCBhbmQgV1QKICB1bmdyb3VwKCkgJT4lCiAgIyBwbG90dGluZwogIGdncGxvdChhZXMoeCA9IHgsIHkgPSBXVF9tZWFuLCBjb2xvdXIgPSByZWdpb24sIHNoYXBlID0gaGFiaXRhdCwgbGFiZWwgPSBzcF9hYmJyKSkgKwogIHN0YXRfbWVhbl9saW5lKGFlcyhsaW5ldHlwZSA9IGhhYml0YXQpLCBhbHBoYSA9IDAuNSkgKwogIGdlb21fcG9pbnRyYW5nZShhZXMoeW1pbiA9IFdUX21lYW4gLSBXVF9TRCwgeW1heCA9IFdUX21lYW4gKyBXVF9TRCwgbGluZXR5cGUgPSBoYWJpdGF0KSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGZpbGwgPSAid2hpdGUiKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMTcsIDIxKSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiI0REM0IyNCIsICIjRkU5NDVDIikpICsKICBnZW9tX3RleHQobnVkZ2VfeSA9IDIsIHNpemUgPSAzLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgeWxpbSgwLCAyNSkgKwogIHhsYWIoIlNwZWNpZXMiKSArCiAgeWxhYigiV2FybWluZyB0b2xlcmFuY2UiKSArCiAgZmFjZXRfZ3JpZCguIH4gcmVnaW9uLCBzY2FsZXMgPSAnZnJlZV94JykgKwogIG15dGhlbWUoKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ICA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCkpCgpjb3dwbG90OjpwbG90X2dyaWQoQ1RtYXhfcGxvdCwgV1RfcGxvdCwgbnJvdyA9IDIsIGFsaWduID0gImh2IiwgYXhpcyA9ICJ0YmxyIiwgbGFiZWxzID0gYygiYSIsICJiIikpCmBgYAoKTGF0aXR1ZGUgYXMgY29udGludW91cyAoKipGaWcuIDNjKiopCgpgYGB7ciBGaWcgM2IsIGZpZy53aWR0aD01LjUsIGZpZy5oZWlnaHQ9MywgZmlnLmFsaWduPSdjZW50ZXInfQpXVF9sYXRfbWUgPC0gYXMuZGF0YS5mcmFtZShnZ2VmZmVjdHM6OmdncHJlZGljdChXVF9sYXRfbW9kZWwsIHRlcm1zID0gYygibGF0IFtzYW1wbGUgPSAyNl0iLCAiaGFiaXRhdCIpKSkKCnN1bW1hcnlfZGF0ICU+JQogIGdncGxvdCgpICsKICBnZW9tX3JpYmJvbihkYXRhID0gV1RfbGF0X21lLCBhZXMoeCA9IHgsIHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCwgZmlsbCA9IGdyb3VwKSwgYWxwaGEgPSAwLjEpICsKICBnZW9tX2xpbmUoZGF0YSA9IFdUX2xhdF9tZSwgYWVzKHggPSB4LCB5ID0gY29uZi5sb3csIGdyb3VwID0gZ3JvdXApLCBjb2xvdXIgPSAiI0REM0IyNCIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFdUX2xhdF9tZSwgYWVzKHggPSB4LCB5ID0gY29uZi5oaWdoLCBncm91cCA9IGdyb3VwKSwgY29sb3VyID0gIiNERDNCMjQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBXVF9sYXRfbWUsIGFlcyh4ID0geCwgeSA9IHByZWRpY3RlZCwgbGluZXR5cGUgPSBncm91cCksIGNvbG91ciA9ICIjREQzQjI0Iiwgc2l6ZSA9IDEpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gbGF0LCB5ID0gV1RfbWVhbiwgc2hhcGUgPSBoYWJpdGF0KSwgY29sb3VyID0gIiNERDNCMjQiLCBzaXplID0gMiwgZmlsbCA9ICJ3aGl0ZSIpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygxNywgMjEpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0ZFOTQ1QyIsICJ3aGl0ZSIpKSArCiAgeGxhYigiTGF0aXR1ZGUgKMKwKSIpICsKICB5bGFiKCJXYXJtaW5nIHRvbGVyYW5jZSIpICsKICBteXRoZW1lKCkKYGBgCgojIyBGaWd1cmUgNCAtIFdhcm1pbmcgYW5kIGRlZm9yZXN0YXRpb24gcHJvamVjdGlvbgoKYGBge3IgRmlnIDQsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTQsIGZpZy5hbGlnbj0nY2VudGVyJ30KIyBFeHRyYWN0IGVzdGltYXRlICsvLSA5NSUgQ0kKY29uZGl0aW9ucyA8LSBtYWtlX2NvbmRpdGlvbnMocHJval9tb2RlbCwgYygiY2xpbWF0ZSIsICJyZWdpb24iKSkKcHJlZGljdF9tZSA8LSBicm1zOjpjb25kaXRpb25hbF9lZmZlY3RzKHByb2pfbW9kZWwsICJjYXRlZ29yeTpoYWJpdGF0IiwgY29uZGl0aW9ucyA9IGNvbmRpdGlvbnMpCnByZWRpY3RfZGF0IDwtIGFzLmRhdGEuZnJhbWUocHJlZGljdF9tZVtbMV1dKSAlPiUgZHBseXI6OnJlbmFtZShlc3RpbWF0ZSA9IGVzdGltYXRlX18sIGNpLmxiID0gbG93ZXJfXywgY2kudWIgPSB1cHBlcl9fKQoKcHJval9sb25nICU+JQogIGRwbHlyOjptdXRhdGUoY2F0ZWdvcnkgPSBmb3JjYXRzOjpmY3RfcmVsZXZlbChhcy5mYWN0b3IoY2F0ZWdvcnkpLCJTaGFkZWQgaGFiaXRhdCIsICJPcGVuIGhhYml0YXQiKSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGFscGhhID0gMC41KSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGNhdGVnb3J5LCB5ID0gdmFsdWVzLCBjb2xvdXIgPSByZWdpb24sIHNoYXBlID0gaGFiaXRhdCksIHNpemUgPSAyLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNiksIGZpbGwgPSAiZ3JleSIsIGFscGhhID0gMC41KSArCiAgZ2VvbV9wb2ludHJhbmdlKGRhdGEgPSBwcmVkaWN0X2RhdCwgYWVzKHggPSBjYXRlZ29yeSwgeSA9IGVzdGltYXRlLCB5bWluID0gY2kubGIsIHltYXggPSBjaS51YiwgY29sb3VyID0gcmVnaW9uLCBzaGFwZSA9IGhhYml0YXQsIGxpbmV0eXBlID0gaGFiaXRhdCksIAogICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNiksIHNpemUgPSAwLjcsIGZpbGwgPSAid2hpdGUiKSArCiAgeWxhYigiV2FybWluZyB0b2xlcmFuY2UiKSArIHhsYWIoTlVMTCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDE3LCAyMSkpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIiNERDNCMjQiLCAiI0ZFOTQ1QyIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0REM0IyNCIsICIjRkU5NDVDIikpICsKICB5bGltKC0xMCwgbWF4KHByb2pfbG9uZyR2YWx1ZXMpKSArCiAgZmFjZXRfZ3JpZCguIH4gY2xpbWF0ZSkgKwogIG15dGhlbWUoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCmBgYAoKKioqCiMgWzIwLzAxLzIwMjMgQ09SUkVDVElPTl0gTWljcm9jbGltYXRlIG1vZGVscyBhbmQgZnV0dXJlIHNjZW5hcmlvCgpUaGUgYG1pY3JvX2dsb2JhbGAgZnVuY3Rpb24gZGlkIG5vdCBoYXZlIHRoZSBzb2lsIG1vaXN0dXJlIGZ1bmN0aW9uIG9uIGJ5IGRlZmF1bHQuIEFmdGVyIGNvbnN1bHRhdGlvbiB3aXRoIHRoZSAqTmljaGVNYXBSKiBkZXZlbG9wZXIgTWljaGFlbCBLZWFybmV5LCB3ZSByZS1lc3RpbWF0ZWQgdGhlIHBvbmQgdGVtcGVyYXR1cmVzIHVzaW5nIHRoZSBgbWljcm9fZXJhNWAgZnVuY3Rpb24gd2hpY2ggcHJvdmlkZXMgZmluZS1zY2FsZSByZXNvbHV0aW9uICh+MSBrbSB3ZWF0aGVyIG1vZGVsIGZvcmVjYXN0LgoKVGhlIG1vZGVsIGRvZXMgbm90IGNvbmZpcm0gdGhhdCBwb25kIGRyeWluZyB3aWxsICdub3Qgb2NjdXInIGFzIHN0YXRlZCBpbiB0aGUgbWFpbiB0ZXh0LiBIb3dldmVyLCB0aGUgaGlnaGVyIHJhaW4gbXVsdGlwbGllciAoYHJhaW5tdWx0YCkgcmVkdWNlcyB0aGUgbGlrZWxpaG9vZCBvZiBwb25kIGRyeWluZy4KClRoZSBlcXVhdGlvbnMgZnJvbSB0aGUgKipQb25kIHRoZXJtb2R5bmFtaWMgbW9kZWwqKiBkbyBub3QgYXBwbHkgdG8gdGhlICpOaWNoZU1hcFIqIG1vZGVscy4gV2UgZm9sbG93ZWQgdGhlIG1ldGhvZHMgZnJvbSBFbnJpcXVlei1VcnplbGFpIGV0IGFsLiAoMjAxOSkgdG8gZXN0aW1hdGUgcG9uZCB0ZW1wZXJhdHVyZS4KCiMjIERvd25sb2FkIG1pY3JvY2xpbWF0ZSBzcGF0aWFsIG1hcAoKRG93bmxvYWQgdGhlIGBtY2VyYTVgIG1pY3JvY2xpbWF0ZSBkYXRhIHRvIGEgbG9jYWwgZGlyZWN0b3J5IHRvIHJ1biB0aGUgYG1pY3JvX2VyYTVgIGZ1bmN0aW9uIGZhc3Rlci4KCmBgYHtyIG1jZXJhX3NldHVwLCBldmFsPUZBTFNFLCBlY2hvPVR9CiMgZ2V0IEVSQTUgZGF0YSB3aXRoIHBhY2thZ2UgbWNlcmE1IAojIGFzc2lnbiB5b3VyIGNyZWRlbnRpYWxzIChyZWdpc3RlciBoZXJlOiBodHRwczovL2Nkcy5jbGltYXRlLmNvcGVybmljdXMuZXUvdXNlci9yZWdpc3RlcikKdWlkICAgICAgICAgPC0gIiQkJCQkJCIKY2RzX2FwaV9rZXkgPC0gIiQkJCQkJCQkLSQkJCQtJCQkJC0kJCQkLSQkJCQkJCQkJCQkJCIKZWNtd2ZyOjp3Zl9zZXRfa2V5KHVzZXIgPSB1aWQsIGtleSA9IGNkc19hcGlfa2V5LCBzZXJ2aWNlID0gImNkcyIpCgojIGJvdW5kaW5nIGNvb3JkaW5hdGVzIChpbiBXR1M4NCAvIEVQU0c6NDMyNikKeG1uIDwtIG1pbihzdW1tYXJ5X2RhdCRsb24pIC0gMSAKeG14IDwtIG1heChzdW1tYXJ5X2RhdCRsb24pICsgMSAKeW1uIDwtIG1pbihzdW1tYXJ5X2RhdCRsYXQpIC0gMQp5bXggPC0gbWF4KHN1bW1hcnlfZGF0JGxhdCkgKyAxCgojIHRlbXBvcmFsIGV4dGVudApzdF90aW1lIDwtIGx1YnJpZGF0ZTo6eW1kKCIyMDEzOjAxOjAxIikgIyBlYXJsaWVzdCBzYW1wbGluZyBkYXRlCmVuX3RpbWUgPC0gbHVicmlkYXRlOjp5bWQoIjIwMjA6MTI6MzEiKSAjIGxhdGVzdCBzYW1wbGluZyBkYXRlCgojIGZpbGVuYW1lIGFuZCBsb2NhdGlvbiBmb3IgZG93bmxvYWRlZCAubmMgZmlsZXMKZmlsZV9wcmVmaXggPC0gImVyYTUiCm9wIDwtICJZT1VSIERJUkVDVE9SWSIKCiMgYnVpbGQgYSByZXF1ZXN0IChjb3ZlcmluZyBtdWx0aXBsZSB5ZWFycykKcmVxIDwtIG1jZXJhNTo6YnVpbGRfZXJhNV9yZXF1ZXN0KHhtaW4gPSB4bW4sIHhtYXggPSB4bXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IHltbiwgeW1heCA9IHlteCwKICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydF90aW1lICAgPSBzdF90aW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgIGVuZF90aW1lICAgICA9IGVuX3RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0ZmlsZV9uYW1lID0gZmlsZV9wcmVmaXgpCgptY2VyYTU6OnJlcXVlc3RfZXJhNShyZXF1ZXN0ID0gcmVxLCB1aWQgPSB1aWQsIG91dF9wYXRoID0gb3ApCmBgYAoKIyMgU2ltdWxhdGUgcG9uZCB0ZW1wZXJhdHVyZQoKUnVuICpOaWNoZW1hcFIqIHRvIHNpbXVsYXRlIHBvbmQgdGVtcGVyYXR1cmVzIHVuZGVyIGZvdXIgaHlwb3RoZXRpY2FsIHNjZW5hcmlvczogKCoqYSoqKSBjdXJyZW50IGNsaW1hdGUgd2l0aCBvcGVuIGhhYml0YXQsICgqKmIqKikgY3VycmVudCBjbGltYXRlIHdpdGggc2hhZGVkIGhhYml0YXQsICgqKmMqKikgd2FybWluZyBjbGltYXRlIHdpdGggb3BlbiBoYWJpdGF0LCBhbmQgKCoqZCoqKSB3YXJtaW5nIGNsaW1hdGUgd2l0aCBzaGFkZWQgaGFiaXRhdC4gVG8gZW5zdXJlIHRoZSBwb25kIGRvZXMgbm90IGRyeSB1cCBkdXJpbmcgdGhlIHNhbXBsaW5nIHBlcmlvZCwgd2UgaW5jcmVhc2VkIGByYWlubXVsdGAgdG8gMjAuIAoKYGBge3Igc2ltdWxhdGlvbl9jb3JyZWN0LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjYWNoZT1UUlVFLCByZXN1bHRzPSJoaWRlIn0Kc3VtX2RhdCA8LSBhcy5kYXRhLmZyYW1lKGNsZWFuX2RhdCAlPiUKICBkcGx5cjo6Z3JvdXBfYnkocmVnaW9uLCBjb3VudHJ5LCBoYWJpdGF0LCBmYW1pbHksIHNwZWNpZXMpICU+JQogIGRwbHlyOjpzdW1tYXJpc2UobG9uICAgICAgICA9IG1lYW4obG9uKSwKICAgICAgICAgICAgICAgICAgIGxhdCAgICAgICAgPSBtZWFuKGxhdCksCiAgICAgICAgICAgICAgICAgICBUbWF4ICAgICAgID0gbWVhbihUbWF4KSwKICAgICAgICAgICAgICAgICAgIHllYXJfc3RhcnQgPSBtaW4oeWVhcl9zdGFydCksCiAgICAgICAgICAgICAgICAgICB5ZWFyX2VuZCAgID0gbWluKHllYXJfZmluaXNoKSwKICAgICAgICAgICAgICAgICAgIG1vbnRoX3N0YXJ0ID0gbWVhbihtb250aF9zdGFydCksCiAgICAgICAgICAgICAgICAgICBtb250aF9lbmQgICA9IG1lYW4obW9udGhfZW5kKSkpCgojIENyZWF0ZSBsb29wIGZvciBlYWNoIGNvb3JkaW5hdGVzCmVzdF9UbWF4IDwtIE5VTEwKZm9yKCBpIGluIDE6bnJvdyhzdW1fZGF0KSl7IAogIG1pY3JvX291dCA8LSAKICAgIE5pY2hlTWFwUjo6bWljcm9fZXJhNShsb2MgPSBjKHN1bV9kYXQkbG9uW2ldLCBzdW1fZGF0JGxhdFtpXSksIAogICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnNoYWRlID0gMSwgbWluc2hhZGUgPSAwLCAjIHNoYWRlIHBhcmFtZXRlcnMKICAgICAgICAgICAgICAgICAgICAgICAgICBQRSA9IFBFLCBCQiA9IEJCLCBCRCA9IEJELCBLUyA9IEtTLCByYWlubXVsdCA9IDIwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhwb29sID0gbWF4cG9vbCwgTEFJID0gTEFJLCBjYXAgPSBjYXAsIHNvaWxncmlkcyA9IHNvaWxncmlkcywgIyBzb2lsIHBhcmFtZXRlcnMgdG8gc2ltdWxhdGUgcG9vbAogICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm0gPSAwLCAjIGN1cnJlbnQgY2xpbWF0ZQogICAgICAgICAgICAgICAgICAgICAgICAgIERFUCA9IERFUCwKICAgICAgICAgICAgICAgICAgICAgICAgICBkc3RhcnQgPSBwYXN0ZSgiMDEvMDEvIiwgc3VtX2RhdCR5ZWFyX3N0YXJ0W2ldLCBzZXAgPSIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGZpbmlzaCA9IHBhc3RlKCIzMS8xMi8iLCBzdW1fZGF0JHllYXJfZW5kW2ldLCBzZXAgPSIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBydW5tb2lzdCA9IDEsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNwYXRpYWwgPSAnL1VzZXJzL25pY2hvbGFzd3UvTGlicmFyeS9DbG91ZFN0b3JhZ2UvT25lRHJpdmUtV2VzdGVyblN5ZG5leVVuaXZlcnNpdHkvTmljaGVNYXBSL2VyYTUnLCAjIGNoYW5nZSB0byB5b3VyIGxvY2F0aW9uCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZSA9IDApCiAgCiAgbWV0b3V0IDwtIGRhdGEuZnJhbWUobWljcm9fb3V0JG1ldG91dCkgJT4lICMgZXh0cmFjdCBzb2lsIHBhcmFtZXRlcnMKICBkcGx5cjo6bXV0YXRlKGRhdGVzID0gcm93X251bWJlcigpIC8gNzMwKSAlPiUgIyBob3VycyB0byBtb250aAogIGRwbHlyOjpmaWx0ZXIoZGF0ZXMgPj0gc3VtX2RhdCRtb250aF9zdGFydFtpXSAmIGRhdGVzIDw9IHN1bV9kYXQkbW9udGhfZW5kW2ldKSAKICAKICAjIGV4dHJhY3Qgd2F0ZXIgdGVtcCBpbiBvcGVuIGhhYml0YXQKICAgIG9wZW4gPC0gZGF0YS5mcmFtZShtaWNyb19vdXQkc29pbCkgJT4lICMgZXh0cmFjdCBzb2lsIHBhcmFtZXRlcnMKICAgICAgZHBseXI6Om11dGF0ZShkYXRlcyA9IHJvd19udW1iZXIoKSAvIDczMCkgJT4lICMgaG91cnMgdG8gbW9udGgKICAgICAgbWVyZ2UobWV0b3V0LCBieSA9ICJkYXRlcyIpICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKGRhdGVzID49IHN1bV9kYXQkbW9udGhfc3RhcnRbaV0gJiBkYXRlcyA8PSBzdW1fZGF0JG1vbnRoX2VuZFtpXSAmIFBPT0xERVAgPiA0MDApICU+JSAKICAgICAgZHBseXI6OnN1bW1hcmlzZShlc3RfVG1heF9vcGVuID0gbWF4KEQ1MGNtKSkKICBwcmludChvcGVuKQoKICAjIGV4dHJhY3Qgd2F0ZXIgdGVtcCBpbiBzaGFkZWQgaGFiaXRhdAogIGNsb3NlZCA8LSBkYXRhLmZyYW1lKG1pY3JvX291dCRzaGFkc29pbCkgJT4lICMgZXh0cmFjdCBzb2lsIHBhcmFtZXRlcnMKICAgICAgZHBseXI6Om11dGF0ZShkYXRlcyA9IHJvd19udW1iZXIoKSAvIDczMCkgJT4lICMgaG91cnMgdG8gbW9udGgKICAgICAgbWVyZ2UobWV0b3V0LCBieSA9ICJkYXRlcyIpICU+JQogICAgZHBseXI6OmZpbHRlcihkYXRlcyA+PSBzdW1fZGF0JG1vbnRoX3N0YXJ0W2ldICYgZGF0ZXMgPD0gc3VtX2RhdCRtb250aF9lbmRbaV0gJiBQT09MREVQID4gNDAwKSAlPiUgCiAgICBkcGx5cjo6c3VtbWFyaXNlKGVzdF9UbWF4X3NoYWRlID0gbWF4KEQ1MGNtKSkKICBwcmludChjbG9zZWQpCiAgcmVzdWx0cyA8LSBjYmluZChzdW1fZGF0JHNwZWNpZXNbaV0sIG9wZW4sIGNsb3NlZCkKICBlc3RfVG1heCA8LSByYmluZChlc3RfVG1heCwgcmVzdWx0cykKfQoKZXN0X1RtYXhfNEMgPC0gTlVMTApmb3IoIGkgaW4gMTpucm93KHN1bV9kYXQpKXsgCiAgbWljcm9fb3V0IDwtIAogICAgTmljaGVNYXBSOjptaWNyb19lcmE1KGxvYyA9IGMoc3VtX2RhdCRsb25baV0sIHN1bV9kYXQkbGF0W2ldKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuc2hhZGUgPSAxLCBtaW5zaGFkZSA9IDAsICMgc2hhZGUgcGFyYW1ldGVycwogICAgICAgICAgICAgICAgICAgICAgICAgIFBFID0gUEUsIEJCID0gQkIsIEJEID0gQkQsIEtTID0gS1MsIHJhaW5tdWx0ID0gMjAsIAogICAgICAgICAgICAgICAgICAgICAgICAgIG1heHBvb2wgPSBtYXhwb29sLCBMQUkgPSBMQUksIGNhcCA9IGNhcCwgc29pbGdyaWRzID0gc29pbGdyaWRzLCAjIHNvaWwgcGFyYW1ldGVycyB0byBzaW11bGF0ZSBwb29sCiAgICAgICAgICAgICAgICAgICAgICAgICAgd2FybSA9IDQsICMgZnV0dXJlIGNsaW1hdGUKICAgICAgICAgICAgICAgICAgICAgICAgICBERVAgPSBERVAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZHN0YXJ0ID0gcGFzdGUoIjAxLzAxLyIsIHN1bV9kYXQkeWVhcl9zdGFydFtpXSwgc2VwID0iIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgIGRmaW5pc2ggPSBwYXN0ZSgiMzEvMTIvIiwgc3VtX2RhdCR5ZWFyX2VuZFtpXSwgc2VwID0iIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVubW9pc3QgPSAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBzcGF0aWFsID0gJy9Vc2Vycy9uaWNob2xhc3d1L0xpYnJhcnkvQ2xvdWRTdG9yYWdlL09uZURyaXZlLVdlc3Rlcm5TeWRuZXlVbml2ZXJzaXR5L05pY2hlTWFwUi9lcmE1JywgIyBjaGFuZ2UgdG8geW91ciBsb2NhdGlvbgogICAgICAgICAgICAgICAgICAgICAgICAgIHNhdmUgPSAwKQogIG1ldG91dCA8LSBkYXRhLmZyYW1lKG1pY3JvX291dCRtZXRvdXQpICU+JSAjIGV4dHJhY3Qgc29pbCBwYXJhbWV0ZXJzCiAgZHBseXI6Om11dGF0ZShkYXRlcyA9IHJvd19udW1iZXIoKSAvIDczMCkgJT4lICMgaG91cnMgdG8gbW9udGgKICBkcGx5cjo6ZmlsdGVyKGRhdGVzID49IHN1bV9kYXQkbW9udGhfc3RhcnRbaV0gJiBkYXRlcyA8PSBzdW1fZGF0JG1vbnRoX2VuZFtpXSkgCiAgCiAgIyBleHRyYWN0IHdhdGVyIHRlbXAgaW4gb3BlbiBoYWJpdGF0CiAgICBvcGVuIDwtIGRhdGEuZnJhbWUobWljcm9fb3V0JHNvaWwpICU+JSAjIGV4dHJhY3Qgc29pbCBwYXJhbWV0ZXJzCiAgICAgIGRwbHlyOjptdXRhdGUoZGF0ZXMgPSByb3dfbnVtYmVyKCkgLyA3MzApICU+JSAjIGhvdXJzIHRvIG1vbnRoCiAgICAgIG1lcmdlKG1ldG91dCwgYnkgPSAiZGF0ZXMiKSAlPiUKICAgICAgZHBseXI6OmZpbHRlcihkYXRlcyA+PSBzdW1fZGF0JG1vbnRoX3N0YXJ0W2ldICYgZGF0ZXMgPD0gc3VtX2RhdCRtb250aF9lbmRbaV0gJiBQT09MREVQID4gNDAwKSAlPiUgCiAgICAgIGRwbHlyOjpzdW1tYXJpc2UoZXN0X1RtYXhfb3Blbl80QyA9IG1heChENTBjbSkpCiAgcHJpbnQob3BlbikKICAjIGV4dHJhY3Qgd2F0ZXIgdGVtcCBpbiBzaGFkZWQgaGFiaXRhdAogIGNsb3NlZCA8LSBkYXRhLmZyYW1lKG1pY3JvX291dCRzaGFkc29pbCkgJT4lICMgZXh0cmFjdCBzb2lsIHBhcmFtZXRlcnMKICAgICAgZHBseXI6Om11dGF0ZShkYXRlcyA9IHJvd19udW1iZXIoKSAvIDczMCkgJT4lICMgaG91cnMgdG8gbW9udGgKICAgICAgbWVyZ2UobWV0b3V0LCBieSA9ICJkYXRlcyIpICU+JQogICAgZHBseXI6OmZpbHRlcihkYXRlcyA+PSBzdW1fZGF0JG1vbnRoX3N0YXJ0W2ldICYgZGF0ZXMgPD0gc3VtX2RhdCRtb250aF9lbmRbaV0gJiBQT09MREVQID4gNDAwKSAlPiUgCiAgICBkcGx5cjo6c3VtbWFyaXNlKGVzdF9UbWF4X3NoYWRlXzRDID0gbWF4KEQ1MGNtKSkKICBwcmludChjbG9zZWQpCiAgcmVzdWx0cyA8LSBjYmluZChzdW1fZGF0JHNwZWNpZXNbaV0sIG9wZW4sIGNsb3NlZCkKICBlc3RfVG1heF80QyA8LSByYmluZChlc3RfVG1heF80QywgcmVzdWx0cykKfQoKcHJval9kYXRhIDwtIGNiaW5kKHN1bW1hcnlfZGF0LCBlc3RfVG1heFssMl0sIGVzdF9UbWF4WywzXSwgZXN0X1RtYXhfNENbLDJdLCBlc3RfVG1heF80Q1ssM10pICU+JSAKICBkcGx5cjo6cmVuYW1lKGVzdF9UbWF4X29wZW4gPSAiZXN0X1RtYXhbLCAyXSIsIAogICAgICAgICAgICAgICAgZXN0X1RtYXhfc2hhZGUgPSAiZXN0X1RtYXhbLCAzXSIsCiAgICAgICAgICAgICAgICBlc3RfVG1heF9vcGVuXzRDID0gImVzdF9UbWF4XzRDWywgMl0iLCAKICAgICAgICAgICAgICAgIGVzdF9UbWF4X3NoYWRlXzRDID0gImVzdF9UbWF4XzRDWywgM10iKQpgYGAKCiMjIFZlcmlmeSBwcmVkaWN0ZWQgdmFsdWVzCgpQcmVkaWN0ZWQgVH5tYXh+IGZyb20gdGhlIGhlYXQgYnVkZ2V0IG1vZGVscyB3ZXJlIHZhbGlkYXRlZCB3aXRoIGEgbGluZWFyIG1vZGVsIChiZWxvdykgYW5kIHZpc3VhbGx5IGluICoqVXBkYXRlZCBGaWcuIFMyKiouCgpgYGB7ciB2ZXJpZnlfdXBkYXRlfQpwcm9qX3Rlc3QgPC0gcHJval9kYXRhICU+JQogIG11dGF0ZShlc3RfVG1heF90ZXN0ID0gaWZlbHNlKGhhYml0YXQgPT0gIkZvcmVzdCIsIGVzdF9UbWF4X3NoYWRlLCBlc3RfVG1heF9vcGVuKSkgJT4lCiAgZmlsdGVyX2FsbChhbGxfdmFycyghaXMuaW5maW5pdGUoLikpKQoKcHJlZGljdF9vYnNfbW9kZWwgPC0gbG0oVG1heCB+IGVzdF9UbWF4X3Rlc3QsIGRhdGEgPSBwcm9qX3Rlc3QpCgp2ZXJpZnkyICAgIDwtIHN1bW1hcnkocHJlZGljdF9vYnNfbW9kZWwpJHIuc3F1YXJlZAptb2RlbF9tYWUyIDwtIE1ldHJpY3M6Om1hZShwcm9qX3Rlc3QkVG1heCwgcHJlZGljdChwcmVkaWN0X29ic19tb2RlbCkpCmBgYAoKYGBgIHtyIEZpZyBTMl91cGRhdGUsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRX0KIyBFeGFtcGxlIHNwZWNpZXMKZXhfbWljcm8gPC0gCiAgTmljaGVNYXBSOjptaWNyb19lcmE1KGxvYyA9IGMoc3VtX2RhdCRsb25bM10sIHN1bV9kYXQkbGF0WzNdKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnNoYWRlID0gMSwgbWluc2hhZGUgPSAwLCAjIHNoYWRlIHBhcmFtZXRlcnMKICAgICAgICAgICAgICAgICAgICAgICAgUEUgPSBQRSwgQkIgPSBCQiwgQkQgPSBCRCwgS1MgPSBLUywgcmFpbm11bHQgPSAyMCwgCiAgICAgICAgICAgICAgICAgICAgICAgIG1heHBvb2wgPSBtYXhwb29sLCBMQUkgPSBMQUksIGNhcCA9IGNhcCwgc29pbGdyaWRzID0gc29pbGdyaWRzLCAjIHNvaWwgcGFyYW1ldGVycyB0byBzaW11bGF0ZSBwb29sCiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm0gPSAwLCAjIGN1cnJlbnQgY2xpbWF0ZQogICAgICAgICAgICAgICAgICAgICAgICBERVAgPSBERVAsCiAgICAgICAgICAgICAgICAgICAgICAgIGRzdGFydCA9IHBhc3RlKCIwMS8wMS8iLCBzdW1fZGF0JHllYXJfc3RhcnRbM10sIHNlcCA9IiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgZGZpbmlzaCA9IHBhc3RlKCIzMS8xMi8iLCBzdW1fZGF0JHllYXJfZW5kWzNdLCBzZXAgPSIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgcnVubW9pc3QgPSAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgc3BhdGlhbCA9ICcvVXNlcnMvbmljaG9sYXN3dS9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9PbmVEcml2ZS1XZXN0ZXJuU3lkbmV5VW5pdmVyc2l0eS9OaWNoZU1hcFIvZXJhNScsICMgY2hhbmdlIHRvIHlvdXIgbG9jYXRpb24KICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZSA9IDApCgptZXRvdXRfZGYgPC0gZGF0YS5mcmFtZShleF9taWNybyRtZXRvdXQpICU+JSAjIGV4dHJhY3Qgc29pbCBwYXJhbWV0ZXJzCiAgZHBseXI6Om11dGF0ZShkYXRlcyA9IHJvd19udW1iZXIoKSAvIDczMCkKCm1ldG91dF9wbG90IDwtIG1ldG91dF9kZiAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gZGF0ZXMsIHkgPSBQT09MREVQKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoc3VtX2RhdCRtb250aF9zdGFydFszXSwgc3VtX2RhdCRtb250aF9lbmRbM10pLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgbGFicyh4ID0gIk1vbnRocyIsIHkgPSAiUG9vbCBkZXB0aCAobW0pIiwgdGl0bGUgPSBzdW1fZGF0JHNwZWNpZXNbM10sIHN1YnRpdGxlID0gc3VtbWFyeV9kYXQkaGFiaXRhdFszXSkgKwogIG15dGhlbWUoKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKCnBvb2xfZGF0IDwtIGRhdGEuZnJhbWUoZXhfbWljcm8kc2hhZHNvaWwpICU+JSAjIGV4dHJhY3Qgc29pbCBwYXJhbWV0ZXJzCiAgZHBseXI6Om11dGF0ZShkYXRlcyA9IHJvd19udW1iZXIoKSAvIDczMCkgJT4lICMgaG91cnMgdG8gbW9udGgKICBtZXJnZShtZXRvdXRfZGYsIGJ5ID0gImRhdGVzIikgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fbGluZShhZXMoeCA9IGRhdGVzLCB5ID0gVEFSRUYpLCBhbHBoYSA9IDAuMSkgKwogIGdlb21fbGluZShhZXMoeCA9IGRhdGVzLCB5ID0gRDUwY20pKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYyhzdW1fZGF0JG1vbnRoX3N0YXJ0WzNdLCBzdW1fZGF0JG1vbnRoX2VuZFszXSksIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBzdW1fZGF0JFRtYXhbM10sIGNvbG91ciA9ICJyZWQiKSArCiAgbGFicyh4ID0gIk1vbnRocyIsIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiKSArCiAgbXl0aGVtZSgpCgp0b3BfcGxvdCA8LSBjb3dwbG90OjpwbG90X2dyaWQobWV0b3V0X3Bsb3QsIHBvb2xfZGF0LCAKICAgICAgICAgICAgICAgICAgIG5jb2wgPSAyLCBhbGlnbiA9ICJodiIsIGF4aXMgPSAidGJsciIsIGxhYmVscyA9IGMoImEiLCAiYiIpKQogIApUbWF4X3ByZWRfcGxvdDIgPC0gZ2dwbG90KCkgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fcG9pbnQoZGF0YSA9IHByb2pfZGF0YSAlPiUgZHBseXI6OmZpbHRlcihoYWJpdGF0ID09ICJGb3Jlc3QiKSwgYWVzKHggPSBlc3RfVG1heF9zaGFkZSwgeSA9IFRtYXgpLCBzaXplID0gMywgc2hhcGUgPSAxNykgKyAjIGZpbGxlZCB0cmlhbmdsZXMKICBnZW9tX3BvaW50KGRhdGEgPSBwcm9qX2RhdGEgJT4lIGRwbHlyOjpmaWx0ZXIoaGFiaXRhdCA9PSAiT3BlbiIpLCBhZXMoeCA9IGVzdF9UbWF4X29wZW4sIHkgPSBUbWF4KSwgc2l6ZSA9IDMsIHNoYXBlID0gMjEpICsgIyBvcGVuIGNpcmNsZXMKICBsYWJzKHRpdGxlID0gIkFsbCBzcGVjaWVzIikgKwogIHhsYWIoZXhwcmVzc2lvbigiRXN0aW1hdGVkIFQiWyJtYXgiXX4iKMKwQykiKSkgKwogIHlsYWIoZXhwcmVzc2lvbigiT2JzZXJ2ZWQgVCJbIm1heCJdfiIowrBDKSIpKSArCiAgeWxpbSgxNCwgNDApICsgeGxpbSgxNCwgNDApICsKICBteXRoZW1lKCkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCgpjb3dwbG90OjpwbG90X2dyaWQodG9wX3Bsb3QsIFRtYXhfcHJlZF9wbG90MiwKICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLCBsYWJlbHMgPSBjKCIiLCAiYyIpKQpgYGAKCioqVXBkYXRlZCBGaWcuIFMyKiogVGhlIG9ic2VydmVkIGFuZCBlc3RpbWF0ZWQgVH5tYXh+IGZvciBlYWNoIHNwZWNpZXMsIG1hdGNoaW5nIHRoZSBzdHVkeSBsb2NhdGlvbiBhbmQgdGltZS4gT2JzZXJ2ZWQgdGVtcGVyYXR1cmVzIHdlcmUgcmVjb3JkZWQgYnkgSE9CTyBXYXRlciBUZW1wZXJhdHVyZSBsb2dnZXJzIHdoaWxlIHRoZSBlc3RpbWF0ZWQgVH5tYXh+IHdhcyBlc3RpbWF0ZWQgZnJvbSAqTmljaGVNYXBSKiB1bmRlciBvcGVuIChmaWxsZWQgdHJpYW5nbGVzKSBhbmQgc2hhZGVkIGhhYml0YXRzIChvcGVuIGNpcmNsZXMpLiBEYXNoZWQgbGluZSByZXByZXNlbnRzIDE6MSBzY2FsZSwgYW5kIFLCsiA9IGByIHZlcmlmeTJgLCB3aXRoIGEgbWVhbiBhYnNvbHV0ZSBlcnJvciBvZiBgciBtb2RlbF9tYWUyYC4KClRoZSB1cGRhdGVkIGVzdGltYXRlZCBwb25kIHRlbXBlcmF0dXJlcyBkaWQgbm90IGRpZmZlciBtdWNoIHJlbGF0aXZlIHRvIHRoZSBvcmlnaW5hbCBzaW11bGF0aW9ucy4gIAoKKioqCgojIFJlZmVyZW5jZXMKCjxkaXYgaWQ9InJlZnMiPjwvZGl2Pgo8YnI+CgoqKioKCiMjIFNlc3Npb24gSW5mb3JtYXRpb24KCmBgYHtyIHNlc3Npb25pbmZvLCBlY2hvID0gRkFMU0V9CnBhbmRlcihzZXNzaW9uSW5mbygpLCBsb2NhbGUgPSBGQUxTRSkKYGBg