0.1 Introduction:

Be sure to toggle the code buttons located on the far right of the page as you read along! you can also download the RMD by clicking the code button at the very top of the page.

The analysis demonstrated in this tutorial is part of a two part study in which data was initially extracted from satellite imagery in a remote sensing analysis.The initial study hypothesized that the acceleration of sea level rise and increased storm frequency are influencing the disappearance of marsh vegetation in Long Island’s South Shore Estuary. The extracted satellite imagery data will be used to evaluate the relationship between Long Island’s vegetation density (NDVI), mean local sea level rise, and storm events frequency over time. Basic statistical tests will be used to evaluate these relationships by doing the following analysis:

  1. Normality testing
  2. Plotting the data in a dual axis time series plot
  3. Correlation testing using Spearman’s Rho
  4. A basic multiple linear regression analysis

0.2 Background on remote sensing analysis

Click the tabs below to review the results of a remote sensing color image analysis.

Shown below, is the composite satellite image that was created to extract the Long Island vegetation density data used in the statistical analysis in this tutorial. This single color image is composed of three normalized difference vegetation index images (NDVI) created in the initial study.This color image displays the vegetation density in an area for a given year. Specifically,each primary color represents a single year containing vegetation. A secondary color represents the presences of vegetation throughout multiple years. For example red spots show where vegetation only grew in 2019, blue spots show only where vegetation grew in 1995, and cyan spots show only where vegetation grew through out the years 1995 and 2000.

For more information on the methods and out come of the entire study feel free to read the executive study.

0.2.1 Jamaica Bay Color Image

0.2.2 South Oyster Bay Color Image

0.2.3 Great South Bay Color Image

0.3 About the data

The storm event data used in this tutorial are available on NOAA’s storm event database. Mean Local see level rise data can be found on NOAA’s tides and currents webpage.The NDVI data used in this tutorial was extracted from satellite imagery. Satellite imagery data are accessible on Google Earth Engine’s data catalog.To learn how to use Google Earth Engine’s python api to extract NDVI data from satellite images please visit this tutorial.

0.4 Reading in libraries and organizing data

Let’s begin our analysis with reading in some necessary libraries as well as reading in and organizing mean local sea level rise (MLSLR) data.

library(tidyverse)
library(lubridate)
library(janitor)
library(readr)
library(ggplot2)
library(hrbrthemes)
library(tidyquant)

meanL_SLR <-read_csv("TheBattery_meanSLtrend_trim2.csv")
#organize and clean MLSLR data
meanL_SLR<- clean_names(meanL_SLR)
meanL_SLR<- rename(meanL_SLR, month = slr_month)

Now lets read in the NDVI (satellite obtained vegetation density data) and organize it. Data from nine region of interests (ROI sites) were extracted from the color image in GEE. Therefore, we will need to read in nine CSV file. To read the files in more efficiently, a function that reads in all files and merges them all into one data frame will be created. The date column will then be converted to yyyy-mm-dd and the year, month and day will be extracted from the new date column to a new columns.

multi_merge2 = function(mypath){
  filenames=list.files(path=mypath,full.names=TRUE)
  datalist = lapply(filenames, read_csv)
  Reduce(full_join, datalist)}

NDVI_data <- multi_merge2("SR_timeseries_Final")

#organize/ clean/ reclassify and rename columns NDVI the data

NDVI_data <- clean_names(NDVI_data)

NDVI_data <- rename(NDVI_data, date = system_time_start)

NDVI_data$date<- lubridate::mdy(NDVI_data$date) 

NDVI_data <- NDVI_data %>%
  dplyr::mutate(year = lubridate::year(date),
                month = lubridate::month(date),
                day = lubridate::day(date))

0.5 Data exploration and normality testing

Now let’s inspect the data. Note how there are 26 observations in the MLSLR data and there are 72 observation in the NDVI data.

length(!is.na(meanL_SLR$monthly_msl)) 
## [1] 26
length(!is.na(NDVI_data$gsb95_ndvi))
## [1] 72

Before we run normality testing on the MLSLR and NDVI data, we will join the data together. This is because we want to correctly assess the distribution of all the data to choose the correct correlation test when analyzing for the relationship between vegetation density and MLSLR. Normality testing can be conducted using the Wilk Shapiro test. We can analyze the normality of the NDVI data for each ROI site and visualize the data in a histogram one by one as shown below.

NDVI_ML_SLR <- NDVI_data %>%
  left_join(meanL_SLR,
            by = c("year" = "year", "month" = "month")) %>%
  arrange(year)

Click the tabs below to see the results of the normality test.

0.5.1 Plot_

hist(NDVI_ML_SLR$gsb_95_00_ndvi, 
     main ="Histogram of Vegetation Density Values (NDVI) in Great South bay 1995",
     xlab = "NDVI values",
     ylab = "Frequency")

0.5.2 Result Summary Values

shapiro.test(NDVI_ML_SLR$gsb_95_00_ndvi) #meanL_SLR$monthly_msl
## 
##  Shapiro-Wilk normality test
## 
## data:  NDVI_ML_SLR$gsb_95_00_ndvi
## W = 0.90965, p-value = 0.005525

0.5.3 Table

NDVI_ML_SLR
## # A tibble: 72 x 14
##    date       gsb95_ndvi gsb19_ndvi gsb_95_00_ndvi jb95_ndvi jb19_ndvi
##    <date>          <dbl>      <dbl>          <dbl>     <dbl>     <dbl>
##  1 1995-08-12      0.499      0.054          0.466     0.046     0.045
##  2 1995-08-28      0.572      0.332          0.536     0.348     0.104
##  3 1996-08-14      0.476      0.309          0.21      0.205     0.085
##  4 1996-08-30      0.589      0.29           0.528     0.443     0.145
##  5 1996-08-05     NA         NA             NA         0.364     0.22 
##  6 1997-08-17      0.543      0.266          0.456     0.494     0.4  
##  7 1997-08-24     NA         NA             NA         0.449     0.228
##  8 1998-08-20      0.417      0.271          0.5       0.406     0.367
##  9 1998-08-27     NA         NA             NA         0.023     0.024
## 10 1999-08-23      0.395      0.29           0.523     0.35      0.303
## # ... with 62 more rows, and 8 more variables: jb_95_00_ndvi <dbl>,
## #   sob95_ndvi <dbl>, sob19_ndvi <dbl>, sob_95_00_ndvi <dbl>, year <dbl>,
## #   month <dbl>, day <int>, monthly_msl <dbl>

HOWEVER, this would take along time. Instead we will organize the data so that we can loop the test over the data set. Our current table has some columns that we don’t want to apply the shapiro test on. To fix this, we will create a new variable and drop the columns we don’t want from the original table then apply the shapiro test to the new table. Then we will have a list of test results showing how some data are skewed.

Normallity_tests <- NDVI_ML_SLR %>%
  select(c(jb19_ndvi,jb_95_00_ndvi, jb95_ndvi))%>%
  apply(2,shapiro.test)

Normallity_tests 
## $jb19_ndvi
## 
##  Shapiro-Wilk normality test
## 
## data:  newX[, i]
## W = 0.93742, p-value = 0.001408
## 
## 
## $jb_95_00_ndvi
## 
##  Shapiro-Wilk normality test
## 
## data:  newX[, i]
## W = 0.92965, p-value = 0.000593
## 
## 
## $jb95_ndvi
## 
##  Shapiro-Wilk normality test
## 
## data:  newX[, i]
## W = 0.96114, p-value = 0.02562

0.6 Correlation between NDVI and MLSLR

As we saw, some of the data in the data frame are not normally distributed. We can choose Spearman’s Rho because it is a robust analysis and doesn’t require normally distributed data. We can now create a function that will loop over the data set and run the correlation test.

Lets begin the process by subsetting the data using the select function. This will remove any columns you don’t need to include in your correlation. In this section we will create a function that compares mean local sea level rise data (y) to all x’s (other_var) by using the apply function to run Spearman’s Rho over all the data.

0.6.1 Code

SubNDVI_mlsr <- NDVI_ML_SLR %>%
  select(c(gsb_95_00_ndvi, gsb95_ndvi, monthly_msl))

cor_test_loop <- function(data, y) {
  return(apply(
    data,
    2,
    FUN = function (other_var) {
      return(cor.test(other_var, data[[y]], data = data, method = "spearman"))
    }
  ))
}

#cor_test_loop(SubNDVI_mlsr,"monthly_msl")

0.6.2 Result Summary Values

cor_test_loop(SubNDVI_mlsr,"monthly_msl")
## $gsb_95_00_ndvi
## 
##  Spearman's rank correlation rho
## 
## data:  other_var and data[[y]]
## S = 12764, p-value = 0.001165
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##        rho 
## -0.5130808 
## 
## 
## $gsb95_ndvi
## 
##  Spearman's rank correlation rho
## 
## data:  other_var and data[[y]]
## S = 13187, p-value = 0.000285
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##        rho 
## -0.5631231 
## 
## 
## $monthly_msl
## 
##  Spearman's rank correlation rho
## 
## data:  other_var and data[[y]]
## S = 0, p-value < 2.2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
## rho 
##   1

0.7 Plotting NDVI vs MLSLR

The correlation analysis reveled that there is a relationship between the vegetation density (NDVI values) in Queens, Long Island South Bay, and MLSLR. In this section we will see if the vegetation in each location has kept growing over time despite the rise in sea level. To show this, we will compare the NDVI values to MLSLR data by creating a dual axis box plot and line graph time series analysis.This will help us visualize the correlation results. To start, lets take the joined NDVI and MLSLR data frame and make it long.

NDVI_ML_SLR_long <- NDVI_ML_SLR  %>%
  pivot_longer(cols = contains("ndvi"),
               names_to = "roi_marsh",
               values_to = "NDVI_val")%>%
  filter(!is.na("roi_marsh")&
           !is.na("NDVI_val"))

To see the code for the plots select the code button on your right.

0.7.1 Boxplot 1

Plot of vegetation that grew in the blue sites on the map in 1995 blue site.


# Create custom colors for your boxplot graph

ndvicolor <- "#17c1d4"
MLSLRcolor <- "#d49817"
ndviTXTcolor95 <- "#0c5970"
MLSLRtxtColor95 <- "#4f280a"

# New facet label names for dose variable
roi_marsh.labs <- c("Great South Bay", "Jamaica Bay", "South Oyster Bay")
names(roi_marsh.labs) <- c("gsb95_ndvi", "jb95_ndvi", "sob95_ndvi")


##Create boxplots of Blue NDVI data distribution V.S. Mean Local Sea Level Rise


MLSLR_NDVI_95_bp <- NDVI_ML_SLR_long %>%
  filter(roi_marsh %in% c("jb95_ndvi", "sob95_ndvi", "gsb95_ndvi")) %>%
  ggplot(aes(x = year)) +
  geom_boxplot(aes(y = NDVI_val, group = year),
               size = 1,
               color = ndvicolor) +
  geom_line(aes(y = monthly_msl), size = 1.5, color = MLSLRcolor) +
  scale_y_continuous(# Features of the first axis
    name = "NDVI Values from Marshes Exsisting in 1995",
    
    # Add a second axis and specify its features
    sec.axis = sec_axis(trans =  ~ . * 1, name = "Mean Local SLR")) +
  ggtitle("Mean Local SLR Compared to NDVI Times Series") +
  theme_test(
    base_size = 15,
    base_family = "",
    base_rect_size = 0.5
  ) + #this changes the text size of the numbers on the xy scale and the facet names
  theme(
    strip.text = element_text(size = 10, face = "bold"),
    axis.title.y = element_text(
      color = ndviTXTcolor95 ,
      size = 13,
      margin = margin(
        t = 5,
        r = 10,
        b = 10,
        l = 10
      )
    ),
    axis.title.y.right = element_text(size = 13,
      color = MLSLRtxtColor95 ,
      margin = margin(
        t = 5,
        r = 10,
        b = 10,
        l = 10
      )
    ),
    axis.title.x = element_text(size = 13, margin = margin(
      t = 5,
      r = 10,
      b = 10,
      l = 10
    )),
    plot.title = element_text(size = 15, margin = margin(
      t = 5,
      r = 10,
      b = 10,
      l = 10
    ))
  ) +
  facet_wrap( ~ roi_marsh,
              labeller = labeller(roi_marsh = roi_marsh.labs),
              nrow = 3)

MLSLR_NDVI_95_bp

0.7.2 Boxplot 2

Plot of vegetation that grew in the cyan sites through out the years 1995 to 2000.Click the code button to see how to change the colors and variable names

ndvicolor <- "#008080"
MLSLRcolor <- "#d49817"
ndviTXTcolor95_00 <- "#1e3321"
MLSLRtxtColor95_00 <- "#4f280a"

# New facet label names for dose variable
roi_marsh.labs2 <-
  c("Great South Bay", "Jamaica Bay", "South Oyster Bay")
names(roi_marsh.labs2) <-
  c("gsb_95_00_ndvi", "jb_95_00_ndvi", "sob_95_00_ndvi")

#filter and plot
MLSLR_NDVI_95_00_bp <- NDVI_ML_SLR_long %>%
  filter(roi_marsh %in% c("gsb_95_00_ndvi", "jb_95_00_ndvi", "sob_95_00_ndvi")) %>%
  ggplot(aes(x = year)) +
  geom_boxplot(aes(y = NDVI_val, group = year),
               size = 1,
               color = ndvicolor) +
  geom_line(aes(y = monthly_msl), size = 1.5, color = MLSLRcolor) +
  scale_y_continuous(
    name = "NDVI Values from Marshes Exsisting in 1995 to 2000",
    sec.axis = sec_axis(trans =  ~ . * 1, name = "Mean Local SLR")) +
  ggtitle("Mean Local SLR Compared to NDVI Times Series") +
  theme_test(
    base_size = 15,
    base_family = "",
    base_rect_size = 0.5
  ) + 
  theme(
    strip.text = element_text(size = 10, face = "bold"),
    axis.title.y = element_text(
      color = ndviTXTcolor95_00 ,
      size = 13,
      margin = margin(
        t = 5,
        r = 10,
        b = 10,
        l = 10
      )
    ),
    axis.title.y.right = element_text(
      size = 13,
      color = MLSLRtxtColor95_00 ,
      margin = margin(
        t = 5,
        r = 10,
        b = 10,
        l = 10
      )
    ),
    axis.title.x = element_text(size = 13, margin = margin(
      t = 5,
      r = 10,
      b = 10,
      l = 10
    )),
    plot.title = element_text(size = 15, margin = margin(
      t = 5,
      r = 10,
      b = 10,
      l = 10
    ))
  ) +
  facet_wrap( ~ roi_marsh,
              labeller = labeller(roi_marsh = roi_marsh.labs2),
              nrow = 3)

MLSLR_NDVI_95_00_bp

0.7.3 Boxplot 3

Plot of vegetation that grew in the red sites in 2019. Click the code button to see how to change the colors and variable names.

ndvicolor19 <- "#d11e0a"
MLSLRcolor19 <- "#d49817"
ndviTXTcolor19 <- "#6b1207"
MLSLRtxtColor19 <- "#4f280a"


# New facet label names for dose variable
roi_marsh.labs3 <- c("Great South Bay", "Jamaica Bay", "South Oyster Bay")
names(roi_marsh.labs3) <- c("gsb19_ndvi", "jb19_ndvi", "sob19_ndvi")



# Create boxplots of Red NDVI distribution V.S. Sea Level Rise 

MLSLR_NDVI_19_bp <- NDVI_ML_SLR_long %>%
  filter(roi_marsh %in% c("gsb19_ndvi", "jb19_ndvi", "sob19_ndvi")) %>%
  ggplot(aes(x = year)) +
  geom_boxplot(aes(y = NDVI_val, group = year),
               size = 1,
               color = ndviTXTcolor19) +
  geom_line(aes(y = monthly_msl), size = 1.5, color = MLSLRcolor) + # Divide by 10 to
  scale_y_continuous(name = "NDVI Values from Marshes Exsisting in 2019",
                     sec.axis = sec_axis(trans =  ~ . * 1, name = "Mean Local SLR")) +
  ggtitle("Mean Local SLR Compared to NDVI Times Series") +
  theme_test(
    base_size = 15,
    base_family = "",
    base_rect_size = 0.5
  ) +
  theme(
    strip.text = element_text(size = 10, face = "bold"),
    axis.title.y = element_text(
      color = ndviTXTcolor19 ,
      size = 13,
      margin =     margin(
        t = 5,
        r = 10,
        b = 10,
        l = 10
      )
    ),
    axis.title.y.right = element_text(
      size = 13,
      color = MLSLRtxtColor19 ,
      margin = margin(
        t = 5,
        r = 10,
        b = 10,
        l = 10
      )
    ),
    axis.title.x = element_text(size = 13, margin = margin(
      t = 5,
      r = 10,
      b = 10,
      l = 10
    )),
    plot.title = element_text(size = 15, margin = margin(
      t = 5,
      r = 10,
      b = 10,
      l = 10
    ))
  ) +
  facet_wrap( ~ roi_marsh,
              labeller = labeller(roi_marsh = roi_marsh.labs3),
              nrow = 3)
MLSLR_NDVI_19_bp

0.8 Exploring storm frequency data

The plots show how MLSLR increased overtime as the NDVI data decreased in the blue and cyan ROI sites. These results are consistent with the results of the correlation analysis. However, the last time series plot shows the opposite out come. This indicates that the marshes in the red ROI sites maybe resilient to sea level rise. Still, not all blue and cyan ROI sites had a significant negative correlation between NDVI values and MLSLR.

In this section we will further look into these sites and investigate the impact of storm frequency on marsh island vegetation. Lets start by reading in some storm frequency data acquired from NOAA’s storm event database. Then lets evaluate the frequency of storm events over time in a smoothed time series analysis plot.

subset_storms <- read.csv("Subset_storm_data.csv") 
subset_storms <-clean_names(subset_storms) 


Stormplot <-  subset_storms%>% 
  filter(event_type_coarse %in% c("Heavy Rain", "Thunderstorm", "Flood"))%>%
  group_by(event_type_coarse, begin_year)%>%
  summarise(freq= n())

The plot below shows that there was a high frequency of thunderstorms in 2009 and a high frequency of floods 2011. There also seemed to have been some small storm event peaks in heavy rain and thunderstorms in 1997. With this information we can now continue with a regression analysis to see if the relationship between NDVI and MLSLR changes after adding storm frequency data to the analysis.

To see the code for the plots select the code button on your right.

0.8.1 Time Series Plot

Stormplot %>%
  ggplot( aes(x=begin_year, y=freq, 
              group=event_type_coarse, 
              color= event_type_coarse)) +
  #geom_line() +
  geom_smooth(se=FALSE, size = 1.5)+
  theme_minimal()+
  theme(plot.title = element_text(size=15),
        plot.subtitle = element_text(size = 13),
        axis.title = element_text(size = 12), 
        axis.text = element_text(size = 10, face="bold"),
        strip.text = element_text(size = 112, face="bold"),
        legend.text = element_text(size = 9),
        legend.title = element_text(size = 9)) +
  geom_vline(xintercept = 2009)+
  geom_vline(xintercept = 2011)+
  geom_vline(xintercept = 1997)+
  labs(colour = "Reported Event Type")+  
  ylab("Number of Reported Storm Events")+
  xlab( "Year")

0.8.2 Table

## # A tibble: 42 x 3
## # Groups:   event_type_coarse [3]
##    event_type_coarse begin_year  freq
##    <chr>                  <int> <int>
##  1 Flood                   1997     2
##  2 Flood                   1998     2
##  3 Flood                   1999     3
##  4 Flood                   2000     6
##  5 Flood                   2001     5
##  6 Flood                   2002     4
##  7 Flood                   2003     6
##  8 Flood                   2004     4
##  9 Flood                   2005     1
## 10 Flood                   2007     2
## # ... with 32 more rows

0.9 NDVI, MLSLR, storm frequency regression analysis

When comparing MLSLR data to NDVI values derived from cyan ROI sites specifically in Jamaica bay and South Oyster Bay no significant correlations was found. In this section we will continue with a regression analysis to find out if the frequency of storm events impacts the relationship between vegetation density and MLSLR data.

First lets read in storm event data that has been joined to both MLSLR and NDVI data. We will then convert the storm data from character to factor and run the linear model function on both site locations.

Storm_SLR_NDVI<- read_csv("Storm_SLR_NDVI_cyan.csv")

Storm_SLR_NDVI$event_type_coarse <- as.factor(Storm_SLR_NDVI$event_type_coarse)
class(Storm_SLR_NDVI$event_type_coarse)
## [1] "factor"
levels(Storm_SLR_NDVI$event_type_coarse)
## [1] "Flood"        "Heavy Rain"   "Thunderstorm"

To see the code for the plots select the code button on your right.

0.9.1 Jamaica Bay Summary Stats

This summary compares the NDVI values extracted from the Jamaica Bay cyan ROI site to MLSLR and storm event type frequency.

MLR_jb_95_00_ndvi <-lm(jb_95_00_ndvi ~ monthly_msl + event_type_coarse, data = Storm_SLR_NDVI)

summary(MLR_jb_95_00_ndvi)
## 
## Call:
## lm(formula = jb_95_00_ndvi ~ monthly_msl + event_type_coarse, 
##     data = Storm_SLR_NDVI)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.47603 -0.07626  0.03490  0.10515  0.43025 
## 
## Coefficients:
##                               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                   -0.09526    0.01247  -7.641 4.28e-14 ***
## monthly_msl                    0.48790    0.11076   4.405 1.15e-05 ***
## event_type_coarseHeavy Rain    0.03428    0.05388   0.636    0.525    
## event_type_coarseThunderstorm -0.04767    0.01077  -4.425 1.05e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.1839 on 1252 degrees of freedom
##   (25 observations deleted due to missingness)
## Multiple R-squared:  0.02866,    Adjusted R-squared:  0.02634 
## F-statistic: 12.32 on 3 and 1252 DF,  p-value: 6.085e-08

0.9.2 South Oyster Bay Summary Stats

This summary compares the NDVI values extracted from the South Oyster Bay cyan ROI site to MLSLR and storm event type frequency.

MLR_sob_95_00_ndvi <-lm(sob_95_00_ndvi ~ monthly_msl + event_type_coarse, data = Storm_SLR_NDVI)

summary(MLR_sob_95_00_ndvi)
## 
## Call:
## lm(formula = sob_95_00_ndvi ~ monthly_msl + event_type_coarse, 
##     data = Storm_SLR_NDVI)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.40599 -0.12049  0.03499  0.12451  0.46352 
## 
## Coefficients:
##                               Estimate Std. Error t value Pr(>|t|)   
## (Intercept)                   -0.02748    0.01528  -1.799  0.07254 . 
## monthly_msl                    0.36096    0.13358   2.702  0.00707 **
## event_type_coarseHeavy Rain    0.12287    0.06564   1.872  0.06167 . 
## event_type_coarseThunderstorm -0.03413    0.01282  -2.662  0.00796 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.1585 on 646 degrees of freedom
##   (631 observations deleted due to missingness)
## Multiple R-squared:  0.02659,    Adjusted R-squared:  0.02207 
## F-statistic: 5.882 on 3 and 646 DF,  p-value: 0.0005783

0.10 Regression analysis discussion

Notice that both analyses have significant p-values but R-squared values that are < than 0.5. This means that there is no relationship between vegetation density, MLSLR, and storm event type frequency at these specific sites. Other environmental or anthropogenic factors could be impacting the relationship between MLSLR and marsh island vegetation density at specific locations and sites throughout Queens and Long Islands South bay. Still, the analyses conducted through out this notebook show how tidal wetlands are losing vegetation at accelerating rates at other sites through out Long Island and are not keeping up with climate change-derived MLSLR.

LS0tDQp0aXRsZTogImByIGh0bWx0b29sczo6SFRNTCgnPGgxPkRhdGEgQW5hbHlzaXMgb2YgTkRWSSAoVmVnZXRhdGlvbiBkZW5zaXR5IGRhdGEgZXh0cmFjdGVkIGZyb20gUk9JIHNhdGVsaXRlIGltYWdlcyksIG1lYW4gbG9jYWwgc2VhIGxldmVsIHJpc2UgZGF0YSBmcm9tIHRoZSBiYXR0ZXJ5IE4uWS4sIGFuZCBzdG9ybSBldmVudCBmcmVxdWVuY3kgZGF0YS4gPC9oMT4nKWAiDQphdXRob3I6ICJIZWxlbiBQb2xhbmNvIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgdG9jOiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgdGhlbWU6IHBhcGVyDQogICAgaGlnaGxpZ2h0OiBlc3ByZXNzbw0KICAgICNjc3M6ICJzdHlsZXMuY3NzIiB0aGlzIGlzIGFuIG9wdGlvbiBpZiB5b3UgZG9uJ3Qgd2FudCB0byBoYXZlIGEgY3NzIGNvZGUgICAgIGNodW5rIGluIHlvdXIgbm90ZWJvb2suDQotLS0NCmBgYHtjc3MgZm9ybWF0dGluZywgZWNobz1GQUxTRX0NCg0KaDEgew0KICAgICBmb250LXNpemU6IDI1cHg7DQogICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgICBmb250LWZhbWlseTogSGVsdmV0aWNhOw0KICAgICBjb2xvcjogIzM0MzQzNDsNCiB9DQogaDIgew0KICAgICBmb250LXNpemU6IDE1cHg7DQogICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgICBmb250LWZhbWlseTogSGVsdmV0aWNhOw0KICAgICBjb2xvcjogIzM0MzQzNDsNCg0KIH0NCmBgYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Ka25pdHI6Om9wdHNfa25pdCRzZXQoIkM6L1VzZXJzL0hlbGVuIFBvbGFuY28vT25lRHJpdmUvRG9jdW1lbnRzL21hcnNoX21hcmtkb3duIikNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQotLS0NCmtuaXQ6ICAoZnVuY3Rpb24oaW5wdXRGaWxlLCBlbmNvZGluZykgeyBvdXRfZGlyIDwtICdkb2NzJzsgcm1hcmtkb3duOjpyZW5kZXIoaW5wdXRGaWxlLCBlbmNvZGluZz1lbmNvZGluZywgb3V0cHV0X2ZpbGU9ZmlsZS5wYXRoKGRpcm5hbWUoaW5wdXRGaWxlKSwgb3V0X2RpciwgJ2luZGV4Lmh0bWwnKSkgfSkNCi0tLQ0KIyMgX19JbnRyb2R1Y3Rpb246X18NCg0KX19fQmUgc3VyZSB0byB0b2dnbGUgdGhlIGNvZGUgYnV0dG9ucyBsb2NhdGVkIG9uIHRoZSBmYXIgcmlnaHQgb2YgdGhlIHBhZ2UgYXMgeW91IHJlYWQgYWxvbmchIHlvdSBjYW4gYWxzbyBkb3dubG9hZCB0aGUgUk1EIGJ5IGNsaWNraW5nIHRoZSBjb2RlIGJ1dHRvbiBhdCB0aGUgdmVyeSB0b3Agb2YgdGhlIHBhZ2UuX19fICANCg0KVGhlIGFuYWx5c2lzIGRlbW9uc3RyYXRlZCBpbiB0aGlzIHR1dG9yaWFsIGlzIHBhcnQgb2YgYSBbdHdvIHBhcnQgc3R1ZHldKGh0dHBzOi8vZ2l0aHViLmNvbS9wb2xhbmNoMTkwL0dFRS1TcGF0aWFsLVRlbXBvcmFsLUFuYWx5c2lzLW9mLUNoYW5nZXMtaW4tTWFyc2gtVmVnZXRhdGlvbi1EZW5zaXR5LS9ibG9iL21haW4vQ29sb3JfY29tcG9zaXRlX0ltYWdlX05CLmlweW5iKSBpbiB3aGljaCBkYXRhIHdhcyBpbml0aWFsbHkgZXh0cmFjdGVkIGZyb20gc2F0ZWxsaXRlIGltYWdlcnkgaW4gYSByZW1vdGUgc2Vuc2luZyBhbmFseXNpcy5UaGUgaW5pdGlhbCBzdHVkeSBoeXBvdGhlc2l6ZWQgdGhhdCB0aGUgYWNjZWxlcmF0aW9uIG9mIHNlYSBsZXZlbCByaXNlIGFuZCBpbmNyZWFzZWQgc3Rvcm0gZnJlcXVlbmN5IGFyZSBpbmZsdWVuY2luZyB0aGUgZGlzYXBwZWFyYW5jZSBvZiBtYXJzaCB2ZWdldGF0aW9uIGluIExvbmcgSXNsYW5k4oCZcyBTb3V0aCBTaG9yZSBFc3R1YXJ5LiBUaGUgZXh0cmFjdGVkIHNhdGVsbGl0ZSBpbWFnZXJ5IGRhdGEgd2lsbCBiZSB1c2VkIHRvIGV2YWx1YXRlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBMb25nIElzbGFuZCdzIHZlZ2V0YXRpb24gZGVuc2l0eSAoTkRWSSksIG1lYW4gbG9jYWwgc2VhIGxldmVsIHJpc2UsIGFuZCBzdG9ybSBldmVudHMgZnJlcXVlbmN5IG92ZXIgdGltZS4gQmFzaWMgc3RhdGlzdGljYWwgdGVzdHMgd2lsbCBiZSB1c2VkIHRvIGV2YWx1YXRlIHRoZXNlIHJlbGF0aW9uc2hpcHMgYnkgZG9pbmcgdGhlIGZvbGxvd2luZyBhbmFseXNpczoNCg0KMS4gTm9ybWFsaXR5IHRlc3RpbmcNCjMuIFBsb3R0aW5nIHRoZSBkYXRhIGluIGEgZHVhbCBheGlzIHRpbWUgc2VyaWVzIHBsb3QgDQo0LiBDb3JyZWxhdGlvbiB0ZXN0aW5nIHVzaW5nIFNwZWFybWFuJ3MgUmhvIA0KNi4gQSBiYXNpYyBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcw0KDQojIyBfX0JhY2tncm91bmQgb24gcmVtb3RlIHNlbnNpbmcgYW5hbHlzaXNfXyB7LnRhYnNldH0NCg0KX19fQ2xpY2sgdGhlIHRhYnMgYmVsb3cgdG8gcmV2aWV3IHRoZSByZXN1bHRzIG9mIGEgcmVtb3RlIHNlbnNpbmcgY29sb3IgaW1hZ2UgYW5hbHlzaXMuX19fIA0KDQoNClNob3duIGJlbG93LCBpcyB0aGUgY29tcG9zaXRlIHNhdGVsbGl0ZSBpbWFnZSB0aGF0IHdhcyBjcmVhdGVkIHRvIGV4dHJhY3QgdGhlIExvbmcgSXNsYW5kIHZlZ2V0YXRpb24gZGVuc2l0eSBkYXRhIHVzZWQgaW4gdGhlIHN0YXRpc3RpY2FsIGFuYWx5c2lzIGluIHRoaXMgdHV0b3JpYWwuIFRoaXMgc2luZ2xlIGNvbG9yIGltYWdlIGlzIGNvbXBvc2VkIG9mIHRocmVlIG5vcm1hbGl6ZWQgZGlmZmVyZW5jZSB2ZWdldGF0aW9uIGluZGV4IGltYWdlcyAoTkRWSSkgY3JlYXRlZCBpbiB0aGUgaW5pdGlhbCBzdHVkeS5UaGlzIGNvbG9yIGltYWdlIGRpc3BsYXlzIHRoZSB2ZWdldGF0aW9uIGRlbnNpdHkgaW4gYW4gYXJlYSBmb3IgYSBnaXZlbiB5ZWFyLiBTcGVjaWZpY2FsbHksZWFjaCBwcmltYXJ5IGNvbG9yIHJlcHJlc2VudHMgYSBzaW5nbGUgeWVhciBjb250YWluaW5nIHZlZ2V0YXRpb24uIEEgc2Vjb25kYXJ5IGNvbG9yIHJlcHJlc2VudHMgdGhlIHByZXNlbmNlcyBvZiB2ZWdldGF0aW9uIHRocm91Z2hvdXQgbXVsdGlwbGUgeWVhcnMuIEZvciBleGFtcGxlIHJlZCBzcG90cyBzaG93IHdoZXJlIHZlZ2V0YXRpb24gb25seSBncmV3IGluIDIwMTksIGJsdWUgc3BvdHMgc2hvdyBvbmx5IHdoZXJlIHZlZ2V0YXRpb24gZ3JldyBpbiAxOTk1LCBhbmQgY3lhbiBzcG90cyBzaG93IG9ubHkgd2hlcmUgdmVnZXRhdGlvbiBncmV3IHRocm91Z2ggb3V0IHRoZSB5ZWFycyAxOTk1IGFuZCAyMDAwLg0KDQpGb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiB0aGUgbWV0aG9kcyBhbmQgb3V0IGNvbWUgb2YgdGhlIGVudGlyZSBzdHVkeSBmZWVsIGZyZWUgdG8gcmVhZCB0aGUgW2V4ZWN1dGl2ZSBzdHVkeV0oaHR0cHM6Ly9naXRodWIuY29tL3BvbGFuY2gxOTAvR0VFLVNwYXRpYWwtVGVtcG9yYWwtQW5hbHlzaXMtb2YtQ2hhbmdlcy1pbi1NYXJzaC1WZWdldGF0aW9uLURlbnNpdHktL2Jsb2IvbWFpbi9UaGVzaXNFeGVjdXRpdmVTdW1tYXJ5X1VwZGF0ZWRBbmFseXNpcy5wZGYpLg0KDQoNCiMjIyBfX0phbWFpY2EgQmF5IENvbG9yIEltYWdlX18NCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9JzEwMCUnLCBpbmNsdWRlPVRSVUV9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnLi9ST0lzX2luX0pCYXkuUE5HJykNCmBgYA0KDQojIyMgX19Tb3V0aCBPeXN0ZXIgQmF5IENvbG9yIEltYWdlX18NCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9JzEwMCUnLCBpbmNsdWRlPVRSVUV9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnLi9ST0lzX2luX1NPQi5QTkcnKQ0KYGBgDQoNCiMjIyBfX0dyZWF0IFNvdXRoIEJheSBDb2xvciBJbWFnZV9fDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPScxMDAlJywgaW5jbHVkZT1UUlVFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJy4vUk9Jc19pbl9HU0IuUE5HJykNCmBgYA0KDQoNCiMjIF9fQWJvdXQgdGhlIGRhdGFfXw0KDQpUaGUgc3Rvcm0gZXZlbnQgZGF0YSB1c2VkIGluIHRoaXMgdHV0b3JpYWwgYXJlIGF2YWlsYWJsZSBvbiBbTk9BQSdzIHN0b3JtIGV2ZW50IGRhdGFiYXNlXShodHRwczovL3d3dy5uY2RjLm5vYWEuZ292L3N0b3JtZXZlbnRzL2Z0cC5qc3ApLiBNZWFuIExvY2FsIHNlZSBsZXZlbCByaXNlIGRhdGEgY2FuIGJlIGZvdW5kIG9uIA0KW05PQUEncyB0aWRlcyBhbmQgY3VycmVudHMgd2VicGFnZV0oaHR0cHM6Ly90aWRlc2FuZGN1cnJlbnRzLm5vYWEuZ292L3NsdHJlbmRzL3NsdHJlbmRzX3N0YXRpb24uc2h0bWw/aWQ9ODUxODc1MCkuVGhlIE5EVkkgZGF0YSB1c2VkIGluIHRoaXMgdHV0b3JpYWwgd2FzIGV4dHJhY3RlZCBmcm9tIHNhdGVsbGl0ZSBpbWFnZXJ5LiBTYXRlbGxpdGUgaW1hZ2VyeSBkYXRhIGFyZSBhY2Nlc3NpYmxlIG9uIFtHb29nbGUgRWFydGggRW5naW5lJ3MgZGF0YSBjYXRhbG9nXShodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS9lYXJ0aC1lbmdpbmUvZGF0YXNldHMvY2F0YWxvZy9sYW5kc2F0KS5UbyBsZWFybiBob3cgdG8gdXNlIEdvb2dsZSBFYXJ0aCBFbmdpbmUncyBweXRob24gYXBpIHRvIGV4dHJhY3QgTkRWSSBkYXRhIGZyb20gc2F0ZWxsaXRlIGltYWdlcyBwbGVhc2UgdmlzaXQgW3RoaXNdKGh0dHBzOi8vZ2l0aHViLmNvbS9wb2xhbmNoMTkwL0dFRS1TcGF0aWFsLVRlbXBvcmFsLUFuYWx5c2lzLW9mLUNoYW5nZXMtaW4tTWFyc2gtVmVnZXRhdGlvbi1EZW5zaXR5LS9ibG9iL21haW4vQ29sb3JfY29tcG9zaXRlX0ltYWdlX05CLmlweW5iKSB0dXRvcmlhbC4gDQoNCg0KIyMgX19SZWFkaW5nIGluIGxpYnJhcmllcyBhbmQgb3JnYW5pemluZyBkYXRhX18NCg0KTGV0J3MgYmVnaW4gb3VyIGFuYWx5c2lzIHdpdGggcmVhZGluZyBpbiBzb21lIG5lY2Vzc2FyeSBsaWJyYXJpZXMgYXMgd2VsbCBhcyByZWFkaW5nIGluIGFuZCBvcmdhbml6aW5nIG1lYW4gbG9jYWwgc2VhIGxldmVsIHJpc2UgKE1MU0xSKSBkYXRhLg0KYGBge3IgY2xhc3Muc291cmNlID0gJ2ZvbGQtc2hvdycsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgaW5jbHVkZT1UUlVFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGhyYnJ0aGVtZXMpDQpsaWJyYXJ5KHRpZHlxdWFudCkNCg0KbWVhbkxfU0xSIDwtcmVhZF9jc3YoIlRoZUJhdHRlcnlfbWVhblNMdHJlbmRfdHJpbTIuY3N2IikNCiNvcmdhbml6ZSBhbmQgY2xlYW4gTUxTTFIgZGF0YQ0KbWVhbkxfU0xSPC0gY2xlYW5fbmFtZXMobWVhbkxfU0xSKQ0KbWVhbkxfU0xSPC0gcmVuYW1lKG1lYW5MX1NMUiwgbW9udGggPSBzbHJfbW9udGgpDQpgYGANCg0KTm93IGxldHMgcmVhZCBpbiB0aGUgTkRWSSAoc2F0ZWxsaXRlIG9idGFpbmVkIHZlZ2V0YXRpb24gZGVuc2l0eSBkYXRhKSBhbmQgb3JnYW5pemUgaXQuIERhdGEgZnJvbSBuaW5lIHJlZ2lvbiBvZiBpbnRlcmVzdHMgKFJPSSBzaXRlcykgd2VyZSBleHRyYWN0ZWQgZnJvbSB0aGUgY29sb3IgaW1hZ2UgaW4gR0VFLiBUaGVyZWZvcmUsIHdlIHdpbGwgbmVlZCB0byByZWFkIGluIG5pbmUgQ1NWIGZpbGUuIFRvIHJlYWQgdGhlIGZpbGVzIGluIG1vcmUgZWZmaWNpZW50bHksIGEgZnVuY3Rpb24gdGhhdCByZWFkcyBpbiBhbGwgZmlsZXMgYW5kIG1lcmdlcyB0aGVtIGFsbCBpbnRvIG9uZSBkYXRhIGZyYW1lIHdpbGwgYmUgY3JlYXRlZC4gVGhlIGRhdGUgY29sdW1uIHdpbGwgdGhlbiBiZSBjb252ZXJ0ZWQgdG8geXl5eS1tbS1kZCBhbmQgdGhlIHllYXIsIG1vbnRoIGFuZCBkYXkgd2lsbCBiZSBleHRyYWN0ZWQgZnJvbSB0aGUgbmV3IGRhdGUgY29sdW1uIHRvIGEgbmV3IGNvbHVtbnMuICANCmBgYHtyLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1zaG93JywgZWNobz1UUlVFLCBpbmNsdWRlPVRSVUUsIG1lc3NhZ2U9IEZBTFNFfQ0KDQptdWx0aV9tZXJnZTIgPSBmdW5jdGlvbihteXBhdGgpew0KICBmaWxlbmFtZXM9bGlzdC5maWxlcyhwYXRoPW15cGF0aCxmdWxsLm5hbWVzPVRSVUUpDQogIGRhdGFsaXN0ID0gbGFwcGx5KGZpbGVuYW1lcywgcmVhZF9jc3YpDQogIFJlZHVjZShmdWxsX2pvaW4sIGRhdGFsaXN0KX0NCg0KTkRWSV9kYXRhIDwtIG11bHRpX21lcmdlMigiU1JfdGltZXNlcmllc19GaW5hbCIpDQoNCiNvcmdhbml6ZS8gY2xlYW4vIHJlY2xhc3NpZnkgYW5kIHJlbmFtZSBjb2x1bW5zIE5EVkkgdGhlIGRhdGENCg0KTkRWSV9kYXRhIDwtIGNsZWFuX25hbWVzKE5EVklfZGF0YSkNCg0KTkRWSV9kYXRhIDwtIHJlbmFtZShORFZJX2RhdGEsIGRhdGUgPSBzeXN0ZW1fdGltZV9zdGFydCkNCg0KTkRWSV9kYXRhJGRhdGU8LSBsdWJyaWRhdGU6Om1keShORFZJX2RhdGEkZGF0ZSkgDQoNCk5EVklfZGF0YSA8LSBORFZJX2RhdGEgJT4lDQogIGRwbHlyOjptdXRhdGUoeWVhciA9IGx1YnJpZGF0ZTo6eWVhcihkYXRlKSwNCiAgICAgICAgICAgICAgICBtb250aCA9IGx1YnJpZGF0ZTo6bW9udGgoZGF0ZSksDQogICAgICAgICAgICAgICAgZGF5ID0gbHVicmlkYXRlOjpkYXkoZGF0ZSkpDQoNCmBgYA0KDQojIyBfX0RhdGEgZXhwbG9yYXRpb24gYW5kIG5vcm1hbGl0eSB0ZXN0aW5nX18gey50YWJzZXR9IA0KDQpOb3cgbGV0J3MgaW5zcGVjdCB0aGUgZGF0YS4gTm90ZSBob3cgdGhlcmUgYXJlIDI2IG9ic2VydmF0aW9ucyBpbiB0aGUgTUxTTFIgZGF0YSBhbmQgdGhlcmUgYXJlIDcyIG9ic2VydmF0aW9uIGluIHRoZSBORFZJIGRhdGEuDQoNCmBgYHtyLGNsYXNzLnNvdXJjZSA9ICdmb2xkLXNob3cnLGVjaG89VFJVRSwgaW5jbHVkZT1UUlVFfQ0KbGVuZ3RoKCFpcy5uYShtZWFuTF9TTFIkbW9udGhseV9tc2wpKSANCg0KbGVuZ3RoKCFpcy5uYShORFZJX2RhdGEkZ3NiOTVfbmR2aSkpDQpgYGANCg0KQmVmb3JlIHdlIHJ1biBub3JtYWxpdHkgdGVzdGluZyBvbiB0aGUgTUxTTFIgYW5kIE5EVkkgZGF0YSwgd2Ugd2lsbCBqb2luIHRoZSBkYXRhIHRvZ2V0aGVyLiBUaGlzIGlzIGJlY2F1c2Ugd2Ugd2FudCB0byBjb3JyZWN0bHkgYXNzZXNzIHRoZSBkaXN0cmlidXRpb24gb2YgYWxsIHRoZSBkYXRhIHRvIGNob29zZSB0aGUgY29ycmVjdCBjb3JyZWxhdGlvbiB0ZXN0IHdoZW4gYW5hbHl6aW5nIGZvciB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdmVnZXRhdGlvbiBkZW5zaXR5IGFuZCBNTFNMUi4gTm9ybWFsaXR5IHRlc3RpbmcgY2FuIGJlIGNvbmR1Y3RlZCB1c2luZyB0aGUgV2lsayBTaGFwaXJvIHRlc3QuIFdlIGNhbiBhbmFseXplIHRoZSBub3JtYWxpdHkgb2YgdGhlIE5EVkkgZGF0YSBmb3IgZWFjaCBST0kgc2l0ZSBhbmQgdmlzdWFsaXplIHRoZSBkYXRhIGluIGEgaGlzdG9ncmFtIG9uZSBieSBvbmUgYXMgc2hvd24gYmVsb3cuICAgDQoNCmBgYHtyLGNsYXNzLnNvdXJjZSA9ICdmb2xkLXNob3cnLGVjaG89VFJVRSwgaW5jbHVkZT1UUlVFfQ0KTkRWSV9NTF9TTFIgPC0gTkRWSV9kYXRhICU+JQ0KICBsZWZ0X2pvaW4obWVhbkxfU0xSLA0KICAgICAgICAgICAgYnkgPSBjKCJ5ZWFyIiA9ICJ5ZWFyIiwgIm1vbnRoIiA9ICJtb250aCIpKSAlPiUNCiAgYXJyYW5nZSh5ZWFyKQ0KYGBgDQpfX19DbGljayB0aGUgdGFicyBiZWxvdyB0byBzZWUgdGhlIHJlc3VsdHMgb2YgdGhlIG5vcm1hbGl0eSB0ZXN0Ll9fXw0KDQojIyMgX19QbG90X19fDQpgYGB7cn0NCmhpc3QoTkRWSV9NTF9TTFIkZ3NiXzk1XzAwX25kdmksIA0KICAgICBtYWluID0iSGlzdG9ncmFtIG9mIFZlZ2V0YXRpb24gRGVuc2l0eSBWYWx1ZXMgKE5EVkkpIGluIEdyZWF0IFNvdXRoIGJheSAxOTk1IiwNCiAgICAgeGxhYiA9ICJORFZJIHZhbHVlcyIsDQogICAgIHlsYWIgPSAiRnJlcXVlbmN5IikNCg0KYGBgDQoNCiMjIyBfX1Jlc3VsdCBTdW1tYXJ5IFZhbHVlc19fDQpgYGB7cn0NCnNoYXBpcm8udGVzdChORFZJX01MX1NMUiRnc2JfOTVfMDBfbmR2aSkgI21lYW5MX1NMUiRtb250aGx5X21zbA0KYGBgDQoNCiMjIyBfX1RhYmxlX18NCmBgYHtyfQ0KTkRWSV9NTF9TTFINCmBgYA0KDQpIT1dFVkVSLCB0aGlzIHdvdWxkIHRha2UgYWxvbmcgdGltZS4gSW5zdGVhZCB3ZSB3aWxsIG9yZ2FuaXplIHRoZSBkYXRhIHNvIHRoYXQgd2UgY2FuIGxvb3AgdGhlIHRlc3Qgb3ZlciB0aGUgZGF0YSBzZXQuIE91ciBjdXJyZW50IHRhYmxlIGhhcyBzb21lIGNvbHVtbnMgdGhhdCB3ZSBkb24ndCB3YW50IHRvIGFwcGx5IHRoZSBzaGFwaXJvIHRlc3Qgb24uIFRvIGZpeCB0aGlzLCB3ZSB3aWxsIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSBhbmQgZHJvcCB0aGUgY29sdW1ucyB3ZSBkb24ndCB3YW50IGZyb20gdGhlIG9yaWdpbmFsIHRhYmxlIHRoZW4gYXBwbHkgdGhlIHNoYXBpcm8gdGVzdCB0byB0aGUgbmV3IHRhYmxlLiBUaGVuIHdlIHdpbGwgaGF2ZSBhIGxpc3Qgb2YgdGVzdCByZXN1bHRzIHNob3dpbmcgaG93IHNvbWUgZGF0YSBhcmUgc2tld2VkLg0KDQpgYGB7ciwgZWNobz1UUlVFLCBpbmNsdWRlPVRSVUV9DQoNCk5vcm1hbGxpdHlfdGVzdHMgPC0gTkRWSV9NTF9TTFIgJT4lDQogIHNlbGVjdChjKGpiMTlfbmR2aSxqYl85NV8wMF9uZHZpLCBqYjk1X25kdmkpKSU+JQ0KICBhcHBseSgyLHNoYXBpcm8udGVzdCkNCg0KTm9ybWFsbGl0eV90ZXN0cyANCg0KYGBgDQoNCg0KIyMgX19Db3JyZWxhdGlvbiBiZXR3ZWVuIE5EVkkgYW5kIE1MU0xSX18gey50YWJzZXR9DQoNCkFzIHdlIHNhdywgc29tZSBvZiB0aGUgZGF0YSBpbiB0aGUgZGF0YSBmcmFtZSBhcmUgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBXZSBjYW4gY2hvb3NlIFNwZWFybWFuJ3MgUmhvIGJlY2F1c2UgaXQgaXMgYSByb2J1c3QgYW5hbHlzaXMgYW5kIGRvZXNuJ3QgcmVxdWlyZSBub3JtYWxseSBkaXN0cmlidXRlZCBkYXRhLiBXZSBjYW4gbm93IGNyZWF0ZSBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBsb29wIG92ZXIgdGhlIGRhdGEgc2V0IGFuZCBydW4gdGhlIGNvcnJlbGF0aW9uIHRlc3QuIA0KDQoNCkxldHMgYmVnaW4gdGhlIHByb2Nlc3MgYnkgc3Vic2V0dGluZyB0aGUgZGF0YSB1c2luZyB0aGUgc2VsZWN0IGZ1bmN0aW9uLiBUaGlzIHdpbGwgcmVtb3ZlIGFueSBjb2x1bW5zIHlvdSBkb24ndCBuZWVkIHRvIGluY2x1ZGUgaW4geW91ciBjb3JyZWxhdGlvbi4gSW4gdGhpcyBzZWN0aW9uIHdlIHdpbGwgY3JlYXRlIGEgZnVuY3Rpb24gdGhhdCBjb21wYXJlcyBtZWFuIGxvY2FsIHNlYSBsZXZlbCByaXNlIGRhdGEgKHkpIHRvIGFsbCB4J3MgKG90aGVyX3ZhcikgYnkgdXNpbmcgdGhlIGFwcGx5IGZ1bmN0aW9uIHRvIHJ1biBTcGVhcm1hbidzIFJobyBvdmVyIGFsbCB0aGUgZGF0YS4NCg0KIyMjIF9fQ29kZV9fDQpgYGB7ciwgY2xhc3Muc291cmNlID0gJ2ZvbGQtc2hvdycgLGVjaG89VFJVRSwgaW5jbHVkZT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9DQpTdWJORFZJX21sc3IgPC0gTkRWSV9NTF9TTFIgJT4lDQogIHNlbGVjdChjKGdzYl85NV8wMF9uZHZpLCBnc2I5NV9uZHZpLCBtb250aGx5X21zbCkpDQoNCmNvcl90ZXN0X2xvb3AgPC0gZnVuY3Rpb24oZGF0YSwgeSkgew0KICByZXR1cm4oYXBwbHkoDQogICAgZGF0YSwNCiAgICAyLA0KICAgIEZVTiA9IGZ1bmN0aW9uIChvdGhlcl92YXIpIHsNCiAgICAgIHJldHVybihjb3IudGVzdChvdGhlcl92YXIsIGRhdGFbW3ldXSwgZGF0YSA9IGRhdGEsIG1ldGhvZCA9ICJzcGVhcm1hbiIpKQ0KICAgIH0NCiAgKSkNCn0NCg0KI2Nvcl90ZXN0X2xvb3AoU3ViTkRWSV9tbHNyLCJtb250aGx5X21zbCIpDQoNCmBgYA0KDQojIyMgX19SZXN1bHQgU3VtbWFyeSBWYWx1ZXNfXw0KYGBge3IsIGVjaG89VFJVRSwgaW5jbHVkZT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0NCmNvcl90ZXN0X2xvb3AoU3ViTkRWSV9tbHNyLCJtb250aGx5X21zbCIpDQoNCmBgYA0KDQoNCg0KIyMgX19QbG90dGluZyBORFZJIHZzIE1MU0xSX18gey50YWJzZXR9DQoNClRoZSBjb3JyZWxhdGlvbiBhbmFseXNpcyByZXZlbGVkIHRoYXQgdGhlcmUgaXMgYSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdmVnZXRhdGlvbiBkZW5zaXR5IChORFZJIHZhbHVlcykgaW4gUXVlZW5zLCBMb25nIElzbGFuZCBTb3V0aCBCYXksIGFuZCBNTFNMUi4gSW4gdGhpcyBzZWN0aW9uIHdlIHdpbGwgc2VlIGlmIHRoZSB2ZWdldGF0aW9uIGluIGVhY2ggbG9jYXRpb24gaGFzIGtlcHQgZ3Jvd2luZyBvdmVyIHRpbWUgZGVzcGl0ZSB0aGUgcmlzZSBpbiBzZWEgbGV2ZWwuIFRvIHNob3cgdGhpcywgd2Ugd2lsbCBjb21wYXJlIHRoZSBORFZJIHZhbHVlcyB0byBNTFNMUiBkYXRhIGJ5IGNyZWF0aW5nIGEgZHVhbCBheGlzIGJveCBwbG90IGFuZCBsaW5lIGdyYXBoIHRpbWUgc2VyaWVzIGFuYWx5c2lzLlRoaXMgd2lsbCBoZWxwIHVzIHZpc3VhbGl6ZSB0aGUgY29ycmVsYXRpb24gcmVzdWx0cy4gVG8gc3RhcnQsIGxldHMgdGFrZSB0aGUgam9pbmVkIE5EVkkgYW5kIE1MU0xSIGRhdGEgZnJhbWUgYW5kIG1ha2UgaXQgbG9uZy4gDQoNCg0KDQpgYGB7cixlY2hvPVRSVUUsIGluY2x1ZGU9VFJVRSwgY2xhc3Muc291cmNlID0gJ2ZvbGQtc2hvdyd9DQoNCk5EVklfTUxfU0xSX2xvbmcgPC0gTkRWSV9NTF9TTFIgICU+JQ0KICBwaXZvdF9sb25nZXIoY29scyA9IGNvbnRhaW5zKCJuZHZpIiksDQogICAgICAgICAgICAgICBuYW1lc190byA9ICJyb2lfbWFyc2giLA0KICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIk5EVklfdmFsIiklPiUNCiAgZmlsdGVyKCFpcy5uYSgicm9pX21hcnNoIikmDQogICAgICAgICAgICFpcy5uYSgiTkRWSV92YWwiKSkNCmBgYA0KDQpfX19UbyBzZWUgdGhlIGNvZGUgZm9yIHRoZSBwbG90cyBzZWxlY3QgdGhlIGNvZGUgYnV0dG9uIG9uIHlvdXIgcmlnaHQuX19fDQoNCiMjIyBfX0JveHBsb3QgMV9fDQpQbG90IG9mIHZlZ2V0YXRpb24gdGhhdCBncmV3IGluIHRoZSBibHVlIHNpdGVzIG9uIHRoZSBtYXAgaW4gMTk5NSBibHVlIHNpdGUuIA0KYGBge3IsIGVjaG89IFRSVUUsIGNvbGxhcHNlID0gVFJVRSwgaW5jbHVkZT1UUlVFLHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gOH0NCg0KIyBDcmVhdGUgY3VzdG9tIGNvbG9ycyBmb3IgeW91ciBib3hwbG90IGdyYXBoDQoNCm5kdmljb2xvciA8LSAiIzE3YzFkNCINCk1MU0xSY29sb3IgPC0gIiNkNDk4MTciDQpuZHZpVFhUY29sb3I5NSA8LSAiIzBjNTk3MCINCk1MU0xSdHh0Q29sb3I5NSA8LSAiIzRmMjgwYSINCg0KIyBOZXcgZmFjZXQgbGFiZWwgbmFtZXMgZm9yIGRvc2UgdmFyaWFibGUNCnJvaV9tYXJzaC5sYWJzIDwtIGMoIkdyZWF0IFNvdXRoIEJheSIsICJKYW1haWNhIEJheSIsICJTb3V0aCBPeXN0ZXIgQmF5IikNCm5hbWVzKHJvaV9tYXJzaC5sYWJzKSA8LSBjKCJnc2I5NV9uZHZpIiwgImpiOTVfbmR2aSIsICJzb2I5NV9uZHZpIikNCg0KDQojI0NyZWF0ZSBib3hwbG90cyBvZiBCbHVlIE5EVkkgZGF0YSBkaXN0cmlidXRpb24gVi5TLiBNZWFuIExvY2FsIFNlYSBMZXZlbCBSaXNlDQoNCg0KTUxTTFJfTkRWSV85NV9icCA8LSBORFZJX01MX1NMUl9sb25nICU+JQ0KICBmaWx0ZXIocm9pX21hcnNoICVpbiUgYygiamI5NV9uZHZpIiwgInNvYjk1X25kdmkiLCAiZ3NiOTVfbmR2aSIpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geWVhcikpICsNCiAgZ2VvbV9ib3hwbG90KGFlcyh5ID0gTkRWSV92YWwsIGdyb3VwID0geWVhciksDQogICAgICAgICAgICAgICBzaXplID0gMSwNCiAgICAgICAgICAgICAgIGNvbG9yID0gbmR2aWNvbG9yKSArDQogIGdlb21fbGluZShhZXMoeSA9IG1vbnRobHlfbXNsKSwgc2l6ZSA9IDEuNSwgY29sb3IgPSBNTFNMUmNvbG9yKSArDQogIHNjYWxlX3lfY29udGludW91cygjIEZlYXR1cmVzIG9mIHRoZSBmaXJzdCBheGlzDQogICAgbmFtZSA9ICJORFZJIFZhbHVlcyBmcm9tIE1hcnNoZXMgRXhzaXN0aW5nIGluIDE5OTUiLA0KICAgIA0KICAgICMgQWRkIGEgc2Vjb25kIGF4aXMgYW5kIHNwZWNpZnkgaXRzIGZlYXR1cmVzDQogICAgc2VjLmF4aXMgPSBzZWNfYXhpcyh0cmFucyA9ICB+IC4gKiAxLCBuYW1lID0gIk1lYW4gTG9jYWwgU0xSIikpICsNCiAgZ2d0aXRsZSgiTWVhbiBMb2NhbCBTTFIgQ29tcGFyZWQgdG8gTkRWSSBUaW1lcyBTZXJpZXMiKSArDQogIHRoZW1lX3Rlc3QoDQogICAgYmFzZV9zaXplID0gMTUsDQogICAgYmFzZV9mYW1pbHkgPSAiIiwNCiAgICBiYXNlX3JlY3Rfc2l6ZSA9IDAuNQ0KICApICsgI3RoaXMgY2hhbmdlcyB0aGUgdGV4dCBzaXplIG9mIHRoZSBudW1iZXJzIG9uIHRoZSB4eSBzY2FsZSBhbmQgdGhlIGZhY2V0IG5hbWVzDQogIHRoZW1lKA0KICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoDQogICAgICBjb2xvciA9IG5kdmlUWFRjb2xvcjk1ICwNCiAgICAgIHNpemUgPSAxMywNCiAgICAgIG1hcmdpbiA9IG1hcmdpbigNCiAgICAgICAgdCA9IDUsDQogICAgICAgIHIgPSAxMCwNCiAgICAgICAgYiA9IDEwLA0KICAgICAgICBsID0gMTANCiAgICAgICkNCiAgICApLA0KICAgIGF4aXMudGl0bGUueS5yaWdodCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMsDQogICAgICBjb2xvciA9IE1MU0xSdHh0Q29sb3I5NSAsDQogICAgICBtYXJnaW4gPSBtYXJnaW4oDQogICAgICAgIHQgPSA1LA0KICAgICAgICByID0gMTAsDQogICAgICAgIGIgPSAxMCwNCiAgICAgICAgbCA9IDEwDQogICAgICApDQogICAgKSwNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzLCBtYXJnaW4gPSBtYXJnaW4oDQogICAgICB0ID0gNSwNCiAgICAgIHIgPSAxMCwNCiAgICAgIGIgPSAxMCwNCiAgICAgIGwgPSAxMA0KICAgICkpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LCBtYXJnaW4gPSBtYXJnaW4oDQogICAgICB0ID0gNSwNCiAgICAgIHIgPSAxMCwNCiAgICAgIGIgPSAxMCwNCiAgICAgIGwgPSAxMA0KICAgICkpDQogICkgKw0KICBmYWNldF93cmFwKCB+IHJvaV9tYXJzaCwNCiAgICAgICAgICAgICAgbGFiZWxsZXIgPSBsYWJlbGxlcihyb2lfbWFyc2ggPSByb2lfbWFyc2gubGFicyksDQogICAgICAgICAgICAgIG5yb3cgPSAzKQ0KDQpNTFNMUl9ORFZJXzk1X2JwDQpgYGANCg0KIyMjIF9fQm94cGxvdCAyX18NCg0KUGxvdCBvZiB2ZWdldGF0aW9uIHRoYXQgZ3JldyBpbiB0aGUgY3lhbiBzaXRlcyB0aHJvdWdoIG91dCB0aGUgeWVhcnMgMTk5NSB0byAyMDAwLkNsaWNrIHRoZSBjb2RlIGJ1dHRvbiB0byBzZWUgaG93IHRvIGNoYW5nZSB0aGUgY29sb3JzIGFuZCB2YXJpYWJsZSBuYW1lcw0KYGBgYGBge3IsIGVjaG89IFRSVUUsIGluY2x1ZGUgPSBUUlVFLGNvbGxhcHNlID0gVFJVRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSA4fQ0KbmR2aWNvbG9yIDwtICIjMDA4MDgwIg0KTUxTTFJjb2xvciA8LSAiI2Q0OTgxNyINCm5kdmlUWFRjb2xvcjk1XzAwIDwtICIjMWUzMzIxIg0KTUxTTFJ0eHRDb2xvcjk1XzAwIDwtICIjNGYyODBhIg0KDQojIE5ldyBmYWNldCBsYWJlbCBuYW1lcyBmb3IgZG9zZSB2YXJpYWJsZQ0Kcm9pX21hcnNoLmxhYnMyIDwtDQogIGMoIkdyZWF0IFNvdXRoIEJheSIsICJKYW1haWNhIEJheSIsICJTb3V0aCBPeXN0ZXIgQmF5IikNCm5hbWVzKHJvaV9tYXJzaC5sYWJzMikgPC0NCiAgYygiZ3NiXzk1XzAwX25kdmkiLCAiamJfOTVfMDBfbmR2aSIsICJzb2JfOTVfMDBfbmR2aSIpDQoNCiNmaWx0ZXIgYW5kIHBsb3QNCk1MU0xSX05EVklfOTVfMDBfYnAgPC0gTkRWSV9NTF9TTFJfbG9uZyAlPiUNCiAgZmlsdGVyKHJvaV9tYXJzaCAlaW4lIGMoImdzYl85NV8wMF9uZHZpIiwgImpiXzk1XzAwX25kdmkiLCAic29iXzk1XzAwX25kdmkiKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IHllYXIpKSArDQogIGdlb21fYm94cGxvdChhZXMoeSA9IE5EVklfdmFsLCBncm91cCA9IHllYXIpLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEsDQogICAgICAgICAgICAgICBjb2xvciA9IG5kdmljb2xvcikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBtb250aGx5X21zbCksIHNpemUgPSAxLjUsIGNvbG9yID0gTUxTTFJjb2xvcikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbmFtZSA9ICJORFZJIFZhbHVlcyBmcm9tIE1hcnNoZXMgRXhzaXN0aW5nIGluIDE5OTUgdG8gMjAwMCIsDQogICAgc2VjLmF4aXMgPSBzZWNfYXhpcyh0cmFucyA9ICB+IC4gKiAxLCBuYW1lID0gIk1lYW4gTG9jYWwgU0xSIikpICsNCiAgZ2d0aXRsZSgiTWVhbiBMb2NhbCBTTFIgQ29tcGFyZWQgdG8gTkRWSSBUaW1lcyBTZXJpZXMiKSArDQogIHRoZW1lX3Rlc3QoDQogICAgYmFzZV9zaXplID0gMTUsDQogICAgYmFzZV9mYW1pbHkgPSAiIiwNCiAgICBiYXNlX3JlY3Rfc2l6ZSA9IDAuNQ0KICApICsgDQogIHRoZW1lKA0KICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoDQogICAgICBjb2xvciA9IG5kdmlUWFRjb2xvcjk1XzAwICwNCiAgICAgIHNpemUgPSAxMywNCiAgICAgIG1hcmdpbiA9IG1hcmdpbigNCiAgICAgICAgdCA9IDUsDQogICAgICAgIHIgPSAxMCwNCiAgICAgICAgYiA9IDEwLA0KICAgICAgICBsID0gMTANCiAgICAgICkNCiAgICApLA0KICAgIGF4aXMudGl0bGUueS5yaWdodCA9IGVsZW1lbnRfdGV4dCgNCiAgICAgIHNpemUgPSAxMywNCiAgICAgIGNvbG9yID0gTUxTTFJ0eHRDb2xvcjk1XzAwICwNCiAgICAgIG1hcmdpbiA9IG1hcmdpbigNCiAgICAgICAgdCA9IDUsDQogICAgICAgIHIgPSAxMCwNCiAgICAgICAgYiA9IDEwLA0KICAgICAgICBsID0gMTANCiAgICAgICkNCiAgICApLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMsIG1hcmdpbiA9IG1hcmdpbigNCiAgICAgIHQgPSA1LA0KICAgICAgciA9IDEwLA0KICAgICAgYiA9IDEwLA0KICAgICAgbCA9IDEwDQogICAgKSksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIG1hcmdpbiA9IG1hcmdpbigNCiAgICAgIHQgPSA1LA0KICAgICAgciA9IDEwLA0KICAgICAgYiA9IDEwLA0KICAgICAgbCA9IDEwDQogICAgKSkNCiAgKSArDQogIGZhY2V0X3dyYXAoIH4gcm9pX21hcnNoLA0KICAgICAgICAgICAgICBsYWJlbGxlciA9IGxhYmVsbGVyKHJvaV9tYXJzaCA9IHJvaV9tYXJzaC5sYWJzMiksDQogICAgICAgICAgICAgIG5yb3cgPSAzKQ0KDQpNTFNMUl9ORFZJXzk1XzAwX2JwDQpgYGANCg0KIyMjIF9fQm94cGxvdCAzX18NClBsb3Qgb2YgdmVnZXRhdGlvbiB0aGF0IGdyZXcgaW4gdGhlIHJlZCBzaXRlcyBpbiAyMDE5LiBDbGljayB0aGUgY29kZSBidXR0b24gdG8gc2VlIGhvdyB0byBjaGFuZ2UgdGhlIGNvbG9ycyBhbmQgdmFyaWFibGUgbmFtZXMuDQpgYGB7ciwgZWNobz0gVFJVRSwgaW5jbHVkZSA9IFRSVUUsY29sbGFwc2UgPSBUUlVFLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRSxmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDh9DQpuZHZpY29sb3IxOSA8LSAiI2QxMWUwYSINCk1MU0xSY29sb3IxOSA8LSAiI2Q0OTgxNyINCm5kdmlUWFRjb2xvcjE5IDwtICIjNmIxMjA3Ig0KTUxTTFJ0eHRDb2xvcjE5IDwtICIjNGYyODBhIg0KDQoNCiMgTmV3IGZhY2V0IGxhYmVsIG5hbWVzIGZvciBkb3NlIHZhcmlhYmxlDQpyb2lfbWFyc2gubGFiczMgPC0gYygiR3JlYXQgU291dGggQmF5IiwgIkphbWFpY2EgQmF5IiwgIlNvdXRoIE95c3RlciBCYXkiKQ0KbmFtZXMocm9pX21hcnNoLmxhYnMzKSA8LSBjKCJnc2IxOV9uZHZpIiwgImpiMTlfbmR2aSIsICJzb2IxOV9uZHZpIikNCg0KDQoNCiMgQ3JlYXRlIGJveHBsb3RzIG9mIFJlZCBORFZJIGRpc3RyaWJ1dGlvbiBWLlMuIFNlYSBMZXZlbCBSaXNlIA0KDQpNTFNMUl9ORFZJXzE5X2JwIDwtIE5EVklfTUxfU0xSX2xvbmcgJT4lDQogIGZpbHRlcihyb2lfbWFyc2ggJWluJSBjKCJnc2IxOV9uZHZpIiwgImpiMTlfbmR2aSIsICJzb2IxOV9uZHZpIikpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5ZWFyKSkgKw0KICBnZW9tX2JveHBsb3QoYWVzKHkgPSBORFZJX3ZhbCwgZ3JvdXAgPSB5ZWFyKSwNCiAgICAgICAgICAgICAgIHNpemUgPSAxLA0KICAgICAgICAgICAgICAgY29sb3IgPSBuZHZpVFhUY29sb3IxOSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBtb250aGx5X21zbCksIHNpemUgPSAxLjUsIGNvbG9yID0gTUxTTFJjb2xvcikgKyAjIERpdmlkZSBieSAxMCB0bw0KICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJORFZJIFZhbHVlcyBmcm9tIE1hcnNoZXMgRXhzaXN0aW5nIGluIDIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgc2VjLmF4aXMgPSBzZWNfYXhpcyh0cmFucyA9ICB+IC4gKiAxLCBuYW1lID0gIk1lYW4gTG9jYWwgU0xSIikpICsNCiAgZ2d0aXRsZSgiTWVhbiBMb2NhbCBTTFIgQ29tcGFyZWQgdG8gTkRWSSBUaW1lcyBTZXJpZXMiKSArDQogIHRoZW1lX3Rlc3QoDQogICAgYmFzZV9zaXplID0gMTUsDQogICAgYmFzZV9mYW1pbHkgPSAiIiwNCiAgICBiYXNlX3JlY3Rfc2l6ZSA9IDAuNQ0KICApICsNCiAgdGhlbWUoDQogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgIGNvbG9yID0gbmR2aVRYVGNvbG9yMTkgLA0KICAgICAgc2l6ZSA9IDEzLA0KICAgICAgbWFyZ2luID0gICAgIG1hcmdpbigNCiAgICAgICAgdCA9IDUsDQogICAgICAgIHIgPSAxMCwNCiAgICAgICAgYiA9IDEwLA0KICAgICAgICBsID0gMTANCiAgICAgICkNCiAgICApLA0KICAgIGF4aXMudGl0bGUueS5yaWdodCA9IGVsZW1lbnRfdGV4dCgNCiAgICAgIHNpemUgPSAxMywNCiAgICAgIGNvbG9yID0gTUxTTFJ0eHRDb2xvcjE5ICwNCiAgICAgIG1hcmdpbiA9IG1hcmdpbigNCiAgICAgICAgdCA9IDUsDQogICAgICAgIHIgPSAxMCwNCiAgICAgICAgYiA9IDEwLA0KICAgICAgICBsID0gMTANCiAgICAgICkNCiAgICApLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMsIG1hcmdpbiA9IG1hcmdpbigNCiAgICAgIHQgPSA1LA0KICAgICAgciA9IDEwLA0KICAgICAgYiA9IDEwLA0KICAgICAgbCA9IDEwDQogICAgKSksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIG1hcmdpbiA9IG1hcmdpbigNCiAgICAgIHQgPSA1LA0KICAgICAgciA9IDEwLA0KICAgICAgYiA9IDEwLA0KICAgICAgbCA9IDEwDQogICAgKSkNCiAgKSArDQogIGZhY2V0X3dyYXAoIH4gcm9pX21hcnNoLA0KICAgICAgICAgICAgICBsYWJlbGxlciA9IGxhYmVsbGVyKHJvaV9tYXJzaCA9IHJvaV9tYXJzaC5sYWJzMyksDQogICAgICAgICAgICAgIG5yb3cgPSAzKQ0KTUxTTFJfTkRWSV8xOV9icA0KYGBgDQoNCiMjIF9fRXhwbG9yaW5nIHN0b3JtIGZyZXF1ZW5jeSBkYXRhX197LnRhYnNldH0NCg0KVGhlIHBsb3RzIHNob3cgaG93IE1MU0xSIGluY3JlYXNlZCBvdmVydGltZSBhcyB0aGUgTkRWSSBkYXRhIGRlY3JlYXNlZCBpbiB0aGUgYmx1ZSBhbmQgY3lhbiBST0kgc2l0ZXMuIFRoZXNlIHJlc3VsdHMgYXJlIGNvbnNpc3RlbnQgd2l0aCB0aGUgcmVzdWx0cyBvZiB0aGUgY29ycmVsYXRpb24gYW5hbHlzaXMuIEhvd2V2ZXIsIHRoZSBsYXN0IHRpbWUgc2VyaWVzIHBsb3Qgc2hvd3MgdGhlIG9wcG9zaXRlIG91dCBjb21lLiBUaGlzIGluZGljYXRlcyB0aGF0IHRoZSBtYXJzaGVzIGluIHRoZSByZWQgUk9JIHNpdGVzIG1heWJlIHJlc2lsaWVudCB0byBzZWEgbGV2ZWwgcmlzZS4gU3RpbGwsIG5vdCBhbGwgYmx1ZSBhbmQgY3lhbiBST0kgc2l0ZXMgaGFkIGEgc2lnbmlmaWNhbnQgbmVnYXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBORFZJIHZhbHVlcyBhbmQgTUxTTFIuIA0KDQpJbiB0aGlzIHNlY3Rpb24gd2Ugd2lsbCBmdXJ0aGVyIGxvb2sgaW50byB0aGVzZSBzaXRlcyBhbmQgaW52ZXN0aWdhdGUgdGhlIGltcGFjdCBvZiBzdG9ybSBmcmVxdWVuY3kgb24gbWFyc2ggaXNsYW5kIHZlZ2V0YXRpb24uIExldHMgc3RhcnQgYnkgcmVhZGluZyBpbiBzb21lIHN0b3JtIGZyZXF1ZW5jeSBkYXRhIGFjcXVpcmVkIGZyb20gTk9BQSdzIHN0b3JtIGV2ZW50IGRhdGFiYXNlLiBUaGVuIGxldHMgZXZhbHVhdGUgdGhlIGZyZXF1ZW5jeSBvZiBzdG9ybSBldmVudHMgb3ZlciB0aW1lIGluIGEgc21vb3RoZWQgdGltZSBzZXJpZXMgYW5hbHlzaXMgcGxvdC4NCg0KDQpgYGB7cixlY2hvPVRSVUUsaW5jbHVlID1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1zaG93J30NCnN1YnNldF9zdG9ybXMgPC0gcmVhZC5jc3YoIlN1YnNldF9zdG9ybV9kYXRhLmNzdiIpIA0Kc3Vic2V0X3N0b3JtcyA8LWNsZWFuX25hbWVzKHN1YnNldF9zdG9ybXMpIA0KDQoNClN0b3JtcGxvdCA8LSAgc3Vic2V0X3N0b3JtcyU+JSANCiAgZmlsdGVyKGV2ZW50X3R5cGVfY29hcnNlICVpbiUgYygiSGVhdnkgUmFpbiIsICJUaHVuZGVyc3Rvcm0iLCAiRmxvb2QiKSklPiUNCiAgZ3JvdXBfYnkoZXZlbnRfdHlwZV9jb2Fyc2UsIGJlZ2luX3llYXIpJT4lDQogIHN1bW1hcmlzZShmcmVxPSBuKCkpDQoNCg0KYGBgDQoNClRoZSBwbG90IGJlbG93IHNob3dzIHRoYXQgdGhlcmUgd2FzIGEgaGlnaCBmcmVxdWVuY3kgb2YgdGh1bmRlcnN0b3JtcyBpbiAyMDA5IGFuZCBhIGhpZ2ggZnJlcXVlbmN5IG9mIGZsb29kcyAyMDExLiBUaGVyZSBhbHNvIHNlZW1lZCB0byBoYXZlIGJlZW4gc29tZSBzbWFsbCBzdG9ybSBldmVudCBwZWFrcyBpbiBoZWF2eSByYWluIGFuZCB0aHVuZGVyc3Rvcm1zIGluIDE5OTcuIFdpdGggdGhpcyBpbmZvcm1hdGlvbiB3ZSBjYW4gbm93IGNvbnRpbnVlIHdpdGggYSByZWdyZXNzaW9uIGFuYWx5c2lzIHRvIHNlZSBpZiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gTkRWSSBhbmQgTUxTTFIgY2hhbmdlcyBhZnRlciBhZGRpbmcgc3Rvcm0gZnJlcXVlbmN5IGRhdGEgdG8gdGhlIGFuYWx5c2lzLg0KDQpfX19UbyBzZWUgdGhlIGNvZGUgZm9yIHRoZSBwbG90cyBzZWxlY3QgdGhlIGNvZGUgYnV0dG9uIG9uIHlvdXIgcmlnaHQuX19fDQoNCiMjIyBfX1RpbWUgU2VyaWVzIFBsb3RfXw0KYGBge3IsZWNobz1UUlVFLCBpbmNsdWRlPVRSVUUsd2FybmluZz1GQUxTRSxlcnJvcj1GQUxTRSxtZXNzYWdlPUZBTFNFLCBvdXQud2lkdGg9JzEwMCUnfQ0KDQpTdG9ybXBsb3QgJT4lDQogIGdncGxvdCggYWVzKHg9YmVnaW5feWVhciwgeT1mcmVxLCANCiAgICAgICAgICAgICAgZ3JvdXA9ZXZlbnRfdHlwZV9jb2Fyc2UsIA0KICAgICAgICAgICAgICBjb2xvcj0gZXZlbnRfdHlwZV9jb2Fyc2UpKSArDQogICNnZW9tX2xpbmUoKSArDQogIGdlb21fc21vb3RoKHNlPUZBTFNFLCBzaXplID0gMS41KSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTUpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwgDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGZhY2U9ImJvbGQiKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEyLCBmYWNlPSJib2xkIiksDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSkgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyMDA5KSsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMjAxMSkrDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDE5OTcpKw0KICBsYWJzKGNvbG91ciA9ICJSZXBvcnRlZCBFdmVudCBUeXBlIikrICANCiAgeWxhYigiTnVtYmVyIG9mIFJlcG9ydGVkIFN0b3JtIEV2ZW50cyIpKw0KICB4bGFiKCAiWWVhciIpDQoNCmBgYA0KDQojIyMgX19UYWJsZV9fDQpgYGB7cixlY2hvPUZBTFNFLGluY2x1ZSA9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQpTdG9ybXBsb3QNCmBgYA0KDQoNCiMjIF9fTkRWSSwgTUxTTFIsIHN0b3JtIGZyZXF1ZW5jeSByZWdyZXNzaW9uIGFuYWx5c2lzX18gey50YWJzZXR9DQoNCldoZW4gY29tcGFyaW5nIE1MU0xSIGRhdGEgdG8gTkRWSSB2YWx1ZXMgZGVyaXZlZCBmcm9tIGN5YW4gUk9JIHNpdGVzIHNwZWNpZmljYWxseSBpbiBKYW1haWNhIGJheSBhbmQgU291dGggT3lzdGVyIEJheSBubyBzaWduaWZpY2FudCBjb3JyZWxhdGlvbnMgd2FzIGZvdW5kLiBJbiB0aGlzIHNlY3Rpb24gd2Ugd2lsbCBjb250aW51ZSB3aXRoIGEgcmVncmVzc2lvbiBhbmFseXNpcyB0byBmaW5kIG91dCBpZiB0aGUgZnJlcXVlbmN5IG9mIHN0b3JtIGV2ZW50cyBpbXBhY3RzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB2ZWdldGF0aW9uIGRlbnNpdHkgYW5kIE1MU0xSIGRhdGEuIA0KDQpGaXJzdCBsZXRzIHJlYWQgaW4gc3Rvcm0gZXZlbnQgZGF0YSB0aGF0IGhhcyBiZWVuIGpvaW5lZCB0byBib3RoIE1MU0xSIGFuZCBORFZJIGRhdGEuIFdlIHdpbGwgdGhlbiBjb252ZXJ0IHRoZSBzdG9ybSBkYXRhIGZyb20gY2hhcmFjdGVyIHRvIGZhY3RvciBhbmQgcnVuIHRoZSBsaW5lYXIgbW9kZWwgZnVuY3Rpb24gb24gYm90aCBzaXRlIGxvY2F0aW9ucy4gDQoNCg0KYGBge3IsY2xhc3Muc291cmNlID0gJ2ZvbGQtc2hvdycsZWNobz1UUlVFLGluY2x1ZGU9VFJVRSwgbWVzc2FnZT1GQUxTRX0NClN0b3JtX1NMUl9ORFZJPC0gcmVhZF9jc3YoIlN0b3JtX1NMUl9ORFZJX2N5YW4uY3N2IikNCg0KU3Rvcm1fU0xSX05EVkkkZXZlbnRfdHlwZV9jb2Fyc2UgPC0gYXMuZmFjdG9yKFN0b3JtX1NMUl9ORFZJJGV2ZW50X3R5cGVfY29hcnNlKQ0KY2xhc3MoU3Rvcm1fU0xSX05EVkkkZXZlbnRfdHlwZV9jb2Fyc2UpDQpsZXZlbHMoU3Rvcm1fU0xSX05EVkkkZXZlbnRfdHlwZV9jb2Fyc2UpDQpgYGANCg0KX19fVG8gc2VlIHRoZSBjb2RlIGZvciB0aGUgcGxvdHMgc2VsZWN0IHRoZSBjb2RlIGJ1dHRvbiBvbiB5b3VyIHJpZ2h0Ll9fXw0KDQojIyMgX19KYW1haWNhIEJheSBTdW1tYXJ5IFN0YXRzX18NCg0KVGhpcyBzdW1tYXJ5IGNvbXBhcmVzIHRoZSBORFZJIHZhbHVlcyBleHRyYWN0ZWQgZnJvbSB0aGUgSmFtYWljYSBCYXkgY3lhbiBST0kgc2l0ZSB0byBNTFNMUiBhbmQgc3Rvcm0gZXZlbnQgdHlwZSBmcmVxdWVuY3kuDQpgYGB7ciwgZWNobz0gVFJVRSxpbmNsdWRlID0gVFJVRX0NCk1MUl9qYl85NV8wMF9uZHZpIDwtbG0oamJfOTVfMDBfbmR2aSB+IG1vbnRobHlfbXNsICsgZXZlbnRfdHlwZV9jb2Fyc2UsIGRhdGEgPSBTdG9ybV9TTFJfTkRWSSkNCg0Kc3VtbWFyeShNTFJfamJfOTVfMDBfbmR2aSkNCmBgYA0KDQojIyMgX19Tb3V0aCBPeXN0ZXIgQmF5IFN1bW1hcnkgU3RhdHNfXw0KDQpUaGlzIHN1bW1hcnkgY29tcGFyZXMgdGhlIE5EVkkgdmFsdWVzIGV4dHJhY3RlZCBmcm9tIHRoZSBTb3V0aCBPeXN0ZXIgQmF5IGN5YW4gUk9JIHNpdGUgdG8gTUxTTFIgYW5kIHN0b3JtIGV2ZW50IHR5cGUgZnJlcXVlbmN5Lg0KYGBge3IsIGVjaG89VFJVRSxpbmNsdWRlPVRSVUV9DQpNTFJfc29iXzk1XzAwX25kdmkgPC1sbShzb2JfOTVfMDBfbmR2aSB+IG1vbnRobHlfbXNsICsgZXZlbnRfdHlwZV9jb2Fyc2UsIGRhdGEgPSBTdG9ybV9TTFJfTkRWSSkNCg0Kc3VtbWFyeShNTFJfc29iXzk1XzAwX25kdmkpDQpgYGANCg0KDQojIyBfX1JlZ3Jlc3Npb24gYW5hbHlzaXMgZGlzY3Vzc2lvbl9fDQpOb3RpY2UgdGhhdCBib3RoIGFuYWx5c2VzIGhhdmUgc2lnbmlmaWNhbnQgcC12YWx1ZXMgYnV0IFItc3F1YXJlZCB2YWx1ZXMgdGhhdCBhcmUgPCB0aGFuIDAuNS4gVGhpcyBtZWFucyB0aGF0IHRoZXJlIGlzIG5vIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHZlZ2V0YXRpb24gZGVuc2l0eSwgTUxTTFIsIGFuZCBzdG9ybSBldmVudCB0eXBlIGZyZXF1ZW5jeSBhdCB0aGVzZSBzcGVjaWZpYyBzaXRlcy4gT3RoZXIgZW52aXJvbm1lbnRhbCBvciBhbnRocm9wb2dlbmljIGZhY3RvcnMgY291bGQgYmUgaW1wYWN0aW5nIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBNTFNMUiBhbmQgbWFyc2ggaXNsYW5kIHZlZ2V0YXRpb24gZGVuc2l0eSBhdCBzcGVjaWZpYyBsb2NhdGlvbnMgYW5kIHNpdGVzIHRocm91Z2hvdXQgUXVlZW5zIGFuZCBMb25nIElzbGFuZHMgU291dGggYmF5LiBTdGlsbCwgdGhlIGFuYWx5c2VzIGNvbmR1Y3RlZCB0aHJvdWdoIG91dCB0aGlzIG5vdGVib29rIHNob3cgaG93IHRpZGFsIHdldGxhbmRzIGFyZSBsb3NpbmcgdmVnZXRhdGlvbiBhdCBhY2NlbGVyYXRpbmcgcmF0ZXMgYXQgb3RoZXIgc2l0ZXMgdGhyb3VnaCBvdXQgTG9uZyBJc2xhbmQgYW5kIGFyZSBub3Qga2VlcGluZyB1cCB3aXRoIGNsaW1hdGUgY2hhbmdlLWRlcml2ZWQgTUxTTFIuIA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=