Group/Individual Details

Executive Statement

Data was collected online (www.frugl.com.au) for 489 manufactured food / drink products from Coles and Woolworths at sale and full price. These data were split into four categories, Beauty (n = 205), Sugary Snack (n = 128), Diet/ Gym Food (n = 68) & Supplement (n = 88). After data exploration, visualization and data preprocessing, paired sample t-tests were used to test for a significant mean difference between Woolworths Sale and Coles Sale prices. For all categories (n = 489) the mean difference was found to be 1.69 (SD = 8.68), with t(df=488) = 4.30, p < 0.001, 95% [0.91, 2.46], Woolworths sale items were statistically significantly lower than Coles sale in price. For Beauty (n = 205) the mean difference was found to be 0.16 (SD = 3.78), with t(df=204) = 0.62, p < 0.54, 95% [-0.36, 068], no statistically significantly difference was found between Woolworths Sale and Coles sale in price. For Sugary Snack, per 1000 g, (n = 128) the mean difference was found to be 3.08 (SD = 10.60), with t(df=127) = 3.29, p < 0.001, 95% [1.23, 4.93], Woolworths sale items were statistically significantly lower than Coles sale in price. For Diet/ Gym Food (n = 68) the mean difference was found to be 2.17 (SD = 15.06), with t(df=67) = 1.19, p < 0.23, 95% [-1.47, 5.82], no statistically significantly difference was found between Woolworths Sale and Coles sale in price. For Supplement (n = 88) the mean difference was found to be 2.83 (SD = 6.36), with t(df=87) = 4.18, p < 0.001, 95% [1.48, 4.18], Woolworths sale items were statistically significantly lower than Coles sale in price. QQ plots were not used due to all sample and subsample sizes (n > 30, normality assumed). The granovo.ds() function was used to provide for all Sale data to provide dependent sample assessment plots and summary stats (modulus values were taken as order was not relevant).

Hypothesis

As both Coles and Woolworths heavily market themselves to be “low cost”, over a sample of identical goods (identical being defined as manufactured goods that are stocked at both Coles and Woolworths), they will have the same mean cost.

The statistical hypotheses for the paired-samples t-test are as follows:

Introduction

Coles Supermarkets Australia Pty Ltd (trading as Coles) and Woolworths Supermarkets (colloquially known as “Woolworths” or “Woolies”) were founded in Australia in 1914 and 1924, respectively 1,2. Together, they make up more than 80% of the Australian market. Both Coles and Woolworths market themselves as extremely price competitive, whilst maintaining high quality products and a wide range 3. Over the course of this investigation, we will attempt to prove or disprove our null hypothesis (as outlined above).

Data Collection

The price comparison website www.frugl.com.au4 was used for data collection. Data was collected over three days (7 Sep, 17 Sep & 18 Sep 2017) within the postcode 3054 (Carlton North, Victoria, Australia). Date was noted as sale items will change with time (and thus collection was performed within an 11 day window). Postcode was kept constant as different regions will presumably have specials and full priced products based on geographies (for example shops in Queensland may sell mangos at much cheaper prices than in Victoria). Such assumption could be evaluated, however are outside the scope of this investigation.

Frugl allows filtering of products into a selection of distinct native categories, for example HEALTH & BEAUTY or BAKING. Categories were chosen based on the likelyhood of containing identical products. For example ‘Nivea Moisturiser 200g’ is manufactured and thus identical between Coles and Woolworths stores, whereas Coles may stock ‘Fresh Celery 250g’ while Woolworths may stock ‘Farm Fresh Celery 225g’. These subtle differences make comparison harder, and so products like the latter were ignored. For the products sampled, the native categories and their respective item counts will be explored below.

For each item four prices were recorded; i. Coles Full Price, ii. Coles Sale Price, iii. Woolworths Full Price & iv. Woolworths Sale Price. If the item was not on sale, the full price was simply recorded into both the full price and the sale column. This was done to for ease of data processing, as delta = 0 between the full price and sale column (within either the Coles or Woolworths categories) will indicate the item is not presently on sale.

Data was collated into a Google Sheet, which was pulled directly into the R Markdown environment. See below for data structure and importation methology.

Load Packages and Data

library(car)
library(ggplot2)
library(dplyr)
library(gsheet)
library(gridExtra)
library("htmltools")
library(reshape2)
library(granova)
ds <- gsheet2tbl('https://drive.google.com/open?id=1_6RZ0HXg7VbgO78oyFfUyZaFOUHYWijy8XH1_jw5tA4')

Summary Statistics, Data Checking and Initial Visualization

The importation of the data set from Google Sheets as ‘ds’ was checked with summary, and the attribute names were also checked using sapply. During data collection, identical items available at both Coles and Woolworths were chosen. These items came from the following native categories on the Frugl website - BAKING, DAIRY & EGGS DIETARY, HEALTH & LIFESTYLE, DRINKS, FROZEN FOOD, HEALTH & BEAUTY, PACKAGED & READY MEALS and PANTRY, value counts can be seen below.

During data collection, these items were re-categorized into the following categories - Beauty, Diet/ Gym Food, Sugary Snack and Supplement, value counts can also be seen below. For this investigation the allocated categories will be used, as they contain the same number of products but spread over fewer groupings. In many cases the allocated categories more accuratly group the products. For example table(ds$"Allocated Category") see four items that can be accurately categorized together as sugary snacks.

## Summary
summary(ds)
 Date Tabulated       Allocated Category Native Category    Description            Coles         Coles Sale      Woolworths   
 Min.   :2017-09-07   Length:489         Length:489         Length:489         Min.   : 1.16   Min.   : 1.00   Min.   : 1.00  
 1st Qu.:2017-09-07   Class :character   Class :character   Class :character   1st Qu.: 4.95   1st Qu.: 4.39   1st Qu.: 4.50  
 Median :2017-09-17   Mode  :character   Mode  :character   Mode  :character   Median :12.65   Median : 9.90   Median :11.50  
 Mean   :2017-09-14                                                            Mean   :12.93   Mean   :10.94   Mean   :11.61  
 3rd Qu.:2017-09-18                                                            3rd Qu.:18.10   3rd Qu.:16.28   3rd Qu.:16.50  
 Max.   :2017-09-18                                                            Max.   :51.70   Max.   :51.70   Max.   :47.00  
 Woolworths Sale     Unit               Amount      
 Min.   : 0.50   Length:489         Min.   :   1.0  
 1st Qu.: 3.50   Class :character   1st Qu.:   1.0  
 Median : 9.40   Mode  :character   Median :  60.0  
 Mean   :10.16                      Mean   : 142.4  
 3rd Qu.:14.00                      3rd Qu.: 200.0  
 Max.   :40.70                      Max.   :2000.0  
## Checking the column names and corresponding data types
sapply(ds, typeof)
    Date Tabulated Allocated Category    Native Category        Description              Coles         Coles Sale         Woolworths 
          "double"        "character"        "character"        "character"           "double"           "double"           "double" 
   Woolworths Sale               Unit             Amount 
          "double"        "character"          "integer" 
## Value counts for the native categories
table(ds$`Native Category`)

                     BAKING                DAIRY & EGGS DIETARY, HEALTH & LIFESTYLE                      DRINKS                 FROZEN FOOD 
                          6                           4                         152                           4                          10 
            HEALTH & BEAUTY      PACKAGED & READY MEALS                      PANTRY 
                        205                           4                         104 
## Value counts for the allocated categories
table(ds$`Allocated Category`)

        Beauty Diet/ Gym Food   Sugary Snack     Supplement 
           205             68            128             88 
## Exploring the Allocated Categories
ds[c(281,286,291,300),c(2,3,4)]
#Exploring Unit and Amount - Data Selection
ds[c(9,47,17,234,283,409),c(2,4,9,10)]
#Value Counts for Unit
table(ds$`Unit`)

   g   mL pack 
 200   55  234 

The attributes “Unit” and “Amount” refer to the unit of measurement the product comes in and the amount, respectively (see exploration code blocks below). Value counts were used to check the categorical attribute Unit.

A scatter plot and a stacked histogram were used explore amount.

The exploration up until this point has highlighted numerous challenges working with the data set. The products are distributed between three units, grams (g), milli litres (mL) & pack. Pack has a different meaning in the context of the products. For example ds[c(9,47,17,234,283,409),c(2,4,9,10)] shows Tresemme Extra Hold Hair Spray (75g) has units g, with an amount of 75. John Frieda Medium Ash Blonde Hair Colour (1 pack) has the unit pack (not volume or mass) and a quantity of one. In the Supplement category Ostelin Vitamin D & Calcium Tablets (180 pack) has unit pack and quantity 180. The data will be explored further and preprocessed, as described below.

Exploring the Native Continuous Data with Scatter Plots

Prior to any transformations, the data was also explored in a qualitative fashion with scatterplots (see below).

The scatter show (qualitively), that the full price between Woolworhts and Coles is quite well correlated, while the sale price between Woolworths and Coles is poorly correlated by comparison (R squared of 0.988 and 0.735, respectively). This indicates that Coles and Woolworths employ different sale pricing stratergy.

Bar Charts of Native Data

These data were plotted into bar charts for Woolworths (denoted WW), Woolworths Sale (denoted WW Sale), Coles and Coles Sale.

As mentioned prior, these data contain a variety of volumes / units / quantites. The plot below shows the “Beauty” allocated category gives no outliers accrross the four plots, and has well distributed bounds. “Beauty” will be left as is for the subsequent analysis. “Sugary Snack” & “Diet/ Gym Food” will be converted all into price per unit 1000 g. For this exercise we will assume 1 g = 1 mL (a reasonable assumption as any liquids from these categories will be mostly water, and 1 mL water has 1 g of mass). “Supplement” has minimal outliers and well distributed bounds, and will be left as is for the subsequent analysis.

Restructuring the Data

These data were broken into their respective categories.

beauty_filter <- ds$`Allocated Category` == "Beauty"
beauty_data <- ds[beauty_filter,]
sugarySnack_filter <- ds$`Allocated Category` == "Sugary Snack"
sugarySnack_data <- ds[sugarySnack_filter,]
dietGymFood_filter <- ds$`Allocated Category` == "Diet/ Gym Food"
dietGymFood_data <- ds[dietGymFood_filter,]
supplement_filter <- ds$`Allocated Category` == "Supplement"
supplement_data <- ds[supplement_filter,]

Resultant units were breifly checked.

#Value Counts for Unit
table(sugarySnack_data$`Unit`)

  g  mL 
116  12 
#Value Counts for Unit
table(dietGymFood_data$`Unit`)

 g mL 
63  5 

Price per 1000g was generated for “Sugary Snack”.

sugarySnack_data$PriceMass <- 1000 / sugarySnack_data$Amount
sugarySnack_data$Per1000gPrice_Coles <- sugarySnack_data$PriceMass*sugarySnack_data$Coles
sugarySnack_data$Per1000gPrice_WW <- sugarySnack_data$PriceMass*sugarySnack_data$Woolworths
sugarySnack_data$Per1000gPrice_ColesSale <- sugarySnack_data$PriceMass*sugarySnack_data$'Coles Sale'
sugarySnack_data$Per1000gPrice_WWSale <- sugarySnack_data$PriceMass*sugarySnack_data$'Woolworths Sale'

Price per 1000g was generated for “Diet/ Gym Food”.

dietGymFood_data$PriceMass <- 1000 / dietGymFood_data$Amount
dietGymFood_data$Per1000gPrice_Coles <- dietGymFood_data$PriceMass * dietGymFood_data$Coles
dietGymFood_data$Per1000gPrice_WW <- dietGymFood_data$PriceMass * dietGymFood_data$Woolworths
dietGymFood_data$Per1000gPrice_ColesSale <- dietGymFood_data$PriceMass * dietGymFood_data$'Coles Sale'
dietGymFood_data$Per1000gPrice_WWSale <- dietGymFood_data$PriceMass * dietGymFood_data$'Woolworths Sale'

These data were exported to .csv and recombined with the Beauty and Supplment data to give dsAdjusted.

write.csv(dietGymFood_data, file = "DietGymFood.csv")
write.csv(sugarySnack_data, file = "SugarySnack.csv")
dsAdjusted <- gsheet2tbl('https://docs.google.com/spreadsheets/d/1VQh07x0OQaaADhflcZ5YY17bB0Ho9kUsPycBsRFYsIk/edit?usp=sharing')

Box Plot of dsAdjusted

Outlier identification was then performed.

summary(sugarySnack_dataAdjusted$ColesAdjusted)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1.90   20.39   27.45   31.46   44.00   83.33 

The items above were filled with the mean of each category in their respective columns, and data was imported once more as dsAdjusted (name was kept constant for simplicities sake).

Box Plot of dsAdjusted with Outliers removed

Scaled Box Plot of dsAdjusted with Outliers removed

These data will now be prepared for paired sample hypothesis testing, through the introduction of a difference attribute (d) in the dsAdjusted data set. Only Coles SALE and Woolworths SALE data will be considered moving forward. Analysis of full price versus sale price is outside the scope of this investigation.

These data are considered to be sufficiently preprocessed for analysis. Paired sample t-testing will be performed on the data set dsAdjusted, on the attribute ‘d’. Due to the nature of the metholodgy (t-test of difference) the remaining outliers will not interfere with the analysis. Due to the size of the data set and the constituent allocated categories (n > 30), we will assume normality. QQ plots were breifly explored, however were deemed to be unesscesary. These data were broken into their constituent categories for processing also.

beauty_filter_d <- dsAdjusted$`Allocated Category` == "Beauty"
beauty_data_d <- dsAdjusted[beauty_filter_d,]
sugarySnack_filter_d <- dsAdjusted$`Allocated Category` == "Sugary Snack"
sugarySnack_data_d <- dsAdjusted[sugarySnack_filter_d,]
dietGymFood_filter_d <- dsAdjusted$`Allocated Category` == "Diet/ Gym Food"
dietGymFood_data_d <- dsAdjusted[dietGymFood_filter_d,]
supplement_filter_d <- dsAdjusted$`Allocated Category` == "Supplement"
supplement_data_d <- dsAdjusted[supplement_filter_d,]

Descriptive Statistics of Mean Difference - All Categories

Descriptive Statistics of Mean Difference - Beauty Category

Descriptive Statistics of Mean Difference - Sugary Snack Category (per 1000 g)

Descriptive Statistics of Mean Difference - Diet/ Gym Food Category (per 1000 g)

Descriptive Statistics of Mean Difference - Supplement Category

Hypothesis Test

We will now perform paired sample t-tests.

Paired Sample t-test - All Categories


    Paired t-test

data:  dsAdjusted$ColesSaleAdjusted and dsAdjusted$WoolworthsSaleAdjusted
t = 4.2968, df = 488, p-value = 2.093e-05
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.914826 2.456462
sample estimates:
mean of the differences 
               1.685644 

Paired Sample t-test - Beauty Category


    Paired t-test

data:  beauty_data_d$ColesSaleAdjusted and beauty_data_d$WoolworthsSaleAdjusted
t = 0.61836, df = 204, p-value = 0.537
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.3575356  0.6842673
sample estimates:
mean of the differences 
              0.1633659 

Paired Sample t-test - Sugary Snack Category (per 1000 g)


    Paired t-test

data:  sugarySnack_data_d$ColesSaleAdjusted and sugarySnack_data_d$WoolworthsSaleAdjusted
t = 3.288, df = 127, p-value = 0.001306
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 1.225281 4.929407
sample estimates:
mean of the differences 
               3.077344 

Paired Sample t-test - Diet/ Gym Food Category (per 1000 g)


    Paired t-test

data:  dietGymFood_data_d$ColesSaleAdjusted and dietGymFood_data_d$WoolworthsSaleAdjusted
t = 1.1899, df = 67, p-value = 0.2383
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.472253  5.818430
sample estimates:
mean of the differences 
               2.173088 

Paired Sample t-test - Supplement Category


    Paired t-test

data:  supplement_data_d$ColesSaleAdjusted and supplement_data_d$WoolworthsSaleAdjusted
t = 4.177, df = 87, p-value = 6.998e-05
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 1.483825 4.177993
sample estimates:
mean of the differences 
               2.830909 

The critical value, t∗ for the paired-sample t-test (assuming a two-tailed test with α=0.05) was then calculated.

Critical Value - All Categories

[1] -1.964837

Critical Value - Beauty Category

[1] -1.971661

Critical Value - Sugary Snack Category (per 1000 g)

[1] -1.97882

Critical Value - Diet/ Gym Food Category (per 1000 g)

[1] -1.996008

Critical Value - Supplement Category

[1] -1.987608

Hypothesis Testing Results & Interpretation

All Categories

The t* values are ± 1.96. As t = 4.3 is more extreme than + 1.96, H0 should be rejected (additionally the 95% CI of the mean difference is found to be [0.91 2.46], which does not contain capture H0). There was a statistically significant mean difference between the Woolworths Sale and Coles Sale prices accross all categories.

Beauty Category

The t* values are ± 1.97. As t = 0.62, t is less extreme than than +1.97, H0 cannot be rejected on critical value. The 95% CI of the mean difference is found to be [-0.36 0.68], H0 cannot be rejected on 95% CI. As p > 0.05, we fail to reject H0. There was not a statistically significant mean difference between the Woolworths Sale and Coles Sale prices in the beauty category.

Sugary Snack Category (per 1000 g)

The t* values are ± 1.98. As t = 3.28 is more extreme than + 1.98, H0 should be rejected (additionally the 95% CI of the mean difference is found to be [1.23 4.93], which does not contain capture H0). There was a statistically significant mean difference between the Woolworths Sale and Coles Sale prices in the Sugary Snack category (price per 1000 g).

Diet/ Gym Food Category (per 1000 g)

The t* values are ± 2.0. As t = 1.19, t is less extreme than than +2.0, H0 cannot be rejected on critical value. The 95% CI of the mean difference is found to be [-1.47 5.82], H0 cannot be rejected on 95% CI. As p > 0.05, we fail to reject H0. There was not a statistically significant mean difference between the Woolworths Sale and Coles Sale prices in the diet/ gym food category.

Supplement Category

The t* values are ± 1.99. As t = 4.18 is more extreme than + 1.99, H0 should be rejected (additionally the 95% CI of the mean difference is found to be [1.48 4.18], which does not contain capture H0). There was a statistically significant mean difference between the Woolworths Sale and Coles Sale prices in the supplement category.

Mean Difference Scatter Plots

All Categories

            Summary Stats
n                 489.000
mean(x)            20.756
mean(y)            22.441
mean(D=x-y)        -1.686
SD(D)               8.675
ES(D)              -0.194
r(x,y)              0.884
r(x+y,d)           -0.200
LL 95%CI           -2.456
UL 95%CI           -0.915
t(D-bar)           -4.297
df.t              488.000
pval.t              0.000

Beauty Category

            Summary Stats
n                 205.000
mean(x)            12.292
mean(y)            12.456
mean(D=x-y)        -0.163
SD(D)               3.783
ES(D)              -0.043
r(x,y)              0.671
r(x+y,d)           -0.018
LL 95%CI           -0.684
UL 95%CI            0.358
t(D-bar)           -0.618
df.t              204.000
pval.t              0.537

Sugary Snack Category (per 1000 g)

            Summary Stats
n                 128.000
mean(x)            20.425
mean(y)            23.502
mean(D=x-y)        -3.077
SD(D)              10.589
ES(D)              -0.291
r(x,y)              0.596
r(x+y,d)           -0.442
LL 95%CI           -4.929
UL 95%CI           -1.225
t(D-bar)           -3.288
df.t              127.000
pval.t              0.001

Diet/ Gym Food Category (per 1000 g)

            Summary Stats
n                  68.000
mean(x)            51.898
mean(y)            54.071
mean(D=x-y)        -2.173
SD(D)              15.060
ES(D)              -0.144
r(x,y)              0.817
r(x+y,d)           -0.149
LL 95%CI           -5.818
UL 95%CI            1.472
t(D-bar)           -1.190
df.t               67.000
pval.t              0.238

Supplement Category

            Summary Stats
n                  88.000
mean(x)            16.888
mean(y)            19.719
mean(D=x-y)        -2.831
SD(D)               6.358
ES(D)              -0.445
r(x,y)              0.757
r(x+y,d)           -0.318
LL 95%CI           -4.178
UL 95%CI           -1.484
t(D-bar)           -4.177
df.t               87.000
pval.t              0.000

Discussion

The following was determined over the duration of the investigation,

The strengths of the investigation included high sample size (overall and in sub-categories), controls of sampling in one postcode over a period of only 11 days and choosing manufactured items that were identical. Limitations include working with the sale data (as full price items not on sale were included here). Full prices overall may be more stable with time, and thus a better representation of the price of the supermarket overall. For future studies, sampling at time intervals (t = 1 month, over 24 months) could be performed at full price in one postcode.

Conclusion

Data of almost 500 points was collected from Coles, Coles Sale, Woolworths and Woolworths Sale (postcode 3054, Carlton North, Victoria, Australia, 7 Sep 2017 till 18 Sep 2017) accross the categories BAKING, DAIRY & EGGS DIETARY, HEALTH & LIFESTYLE, DRINKS, FROZEN FOOD, HEALTH & BEAUTY, PACKAGED & READY MEALS and PANTRY (generalized as Beauty, Diet/ Gym Food, Sugary Snack and Supplement). It was determined that Woolworths Sale had statistically significant lower prices overall, in the sugary snack category and in the supplement category.


  1. http://www.wesfarmers.com.au/util/news-media/article/2017/06/22/coles-creates-115-jobs-at-its-milestone-800th-supermarket

  2. http://www.smh.com.au/business/supermarket-duopoly-blamed-for-soaring-food-prices-20091108-i3tn.html

  3. http://www.smh.com.au/business/retail/coles-deepens-price-war-after-slicing-bread-prices-20170712-gxa33p.html

  4. https://www.frugl.com.au/

LS0tCnRpdGxlOiAiTUFUSDEzMjQgQXNzaWdubWVudCAzIgpzdWJ0aXRsZTogU3VwZXJtYXJrZXQgUHJpY2UgV2FycwpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgojIyMgR3JvdXAvSW5kaXZpZHVhbCBEZXRhaWxzCgoqIEFsaXN0YWlyIEdyZXZpcy1KYW1lcyAoczM2NDQxMTkpCgojIyMgRXhlY3V0aXZlIFN0YXRlbWVudApEYXRhIHdhcyBjb2xsZWN0ZWQgb25saW5lICh3d3cuZnJ1Z2wuY29tLmF1KSBmb3IgNDg5IG1hbnVmYWN0dXJlZCBmb29kIC8gZHJpbmsgcHJvZHVjdHMgZnJvbSBDb2xlcyBhbmQgV29vbHdvcnRocyBhdCBzYWxlIGFuZCBmdWxsIHByaWNlLiBUaGVzZSBkYXRhIHdlcmUgc3BsaXQgaW50byBmb3VyIGNhdGVnb3JpZXMsIEJlYXV0eSAobiA9IDIwNSksIFN1Z2FyeSBTbmFjayAobiA9IDEyOCksIERpZXQvIEd5bSBGb29kIChuID0gNjgpICYgU3VwcGxlbWVudCAobiA9IDg4KS4gQWZ0ZXIgZGF0YSBleHBsb3JhdGlvbiwgdmlzdWFsaXphdGlvbiBhbmQgZGF0YSBwcmVwcm9jZXNzaW5nLCBwYWlyZWQgc2FtcGxlIHQtdGVzdHMgd2VyZSB1c2VkIHRvIHRlc3QgZm9yIGEgc2lnbmlmaWNhbnQgbWVhbiBkaWZmZXJlbmNlIGJldHdlZW4gV29vbHdvcnRocyBTYWxlIGFuZCBDb2xlcyBTYWxlIHByaWNlcy4gRm9yIGFsbCBjYXRlZ29yaWVzIChuID0gNDg5KSB0aGUgbWVhbiBkaWZmZXJlbmNlIHdhcyBmb3VuZCB0byBiZSAxLjY5IChTRCA9IDguNjgpLCB3aXRoIHQoZGY9NDg4KSA9IDQuMzAsIHAgPCAwLjAwMSwgOTUlIFswLjkxLCAyLjQ2XSwgV29vbHdvcnRocyBzYWxlIGl0ZW1zIHdlcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudGx5IGxvd2VyIHRoYW4gQ29sZXMgc2FsZSBpbiBwcmljZS4gRm9yIEJlYXV0eSAobiA9IDIwNSkgdGhlIG1lYW4gZGlmZmVyZW5jZSB3YXMgZm91bmQgdG8gYmUgMC4xNiAoU0QgPSAzLjc4KSwgd2l0aCB0KGRmPTIwNCkgPSAwLjYyLCBwIDwgMC41NCwgOTUlIFstMC4zNiwgMDY4XSwgbm8gc3RhdGlzdGljYWxseSBzaWduaWZpY2FudGx5IGRpZmZlcmVuY2Ugd2FzIGZvdW5kIGJldHdlZW4gV29vbHdvcnRocyBTYWxlIGFuZCBDb2xlcyBzYWxlIGluIHByaWNlLiBGb3IgU3VnYXJ5IFNuYWNrLCBwZXIgMTAwMCBnLCAobiA9IDEyOCkgdGhlIG1lYW4gZGlmZmVyZW5jZSB3YXMgZm91bmQgdG8gYmUgMy4wOCAoU0QgPSAxMC42MCksIHdpdGggdChkZj0xMjcpID0gMy4yOSwgcCA8IDAuMDAxLCA5NSUgWzEuMjMsIDQuOTNdLCBXb29sd29ydGhzIHNhbGUgaXRlbXMgd2VyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50bHkgbG93ZXIgdGhhbiBDb2xlcyBzYWxlIGluIHByaWNlLiBGb3IgRGlldC8gR3ltIEZvb2QgKG4gPSA2OCkgdGhlIG1lYW4gZGlmZmVyZW5jZSB3YXMgZm91bmQgdG8gYmUgMi4xNyAoU0QgPSAxNS4wNiksIHdpdGggdChkZj02NykgPSAxLjE5LCBwIDwgMC4yMywgOTUlIFstMS40NywgNS44Ml0sIG5vIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnRseSBkaWZmZXJlbmNlIHdhcyBmb3VuZCBiZXR3ZWVuIFdvb2x3b3J0aHMgU2FsZSBhbmQgQ29sZXMgc2FsZSBpbiBwcmljZS4gRm9yIFN1cHBsZW1lbnQgKG4gPSA4OCkgdGhlIG1lYW4gZGlmZmVyZW5jZSB3YXMgZm91bmQgdG8gYmUgMi44MyAoU0QgPSA2LjM2KSwgd2l0aCB0KGRmPTg3KSA9IDQuMTgsIHAgPCAwLjAwMSwgOTUlIFsxLjQ4LCA0LjE4XSwgV29vbHdvcnRocyBzYWxlIGl0ZW1zIHdlcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudGx5IGxvd2VyIHRoYW4gQ29sZXMgc2FsZSBpbiBwcmljZS4gUVEgcGxvdHMgd2VyZSBub3QgdXNlZCBkdWUgdG8gYWxsIHNhbXBsZSBhbmQgc3Vic2FtcGxlIHNpemVzIChuID4gMzAsIG5vcm1hbGl0eSBhc3N1bWVkKS4gVGhlIGBncmFub3ZvLmRzKClgIGZ1bmN0aW9uIHdhcyB1c2VkIHRvIHByb3ZpZGUgZm9yIGFsbCBTYWxlIGRhdGEgdG8gcHJvdmlkZSBkZXBlbmRlbnQgc2FtcGxlIGFzc2Vzc21lbnQgcGxvdHMgYW5kIHN1bW1hcnkgc3RhdHMgKG1vZHVsdXMgdmFsdWVzIHdlcmUgdGFrZW4gYXMgb3JkZXIgd2FzIG5vdCByZWxldmFudCkuICAKCgojIyMgSHlwb3RoZXNpcwpBcyBib3RoIENvbGVzIGFuZCBXb29sd29ydGhzIGhlYXZpbHkgbWFya2V0IHRoZW1zZWx2ZXMgdG8gYmUgImxvdyBjb3N0Iiwgb3ZlciBhIHNhbXBsZSBvZiBpZGVudGljYWwgZ29vZHMgKGlkZW50aWNhbCBiZWluZyBkZWZpbmVkIGFzIG1hbnVmYWN0dXJlZCBnb29kcyB0aGF0IGFyZSBzdG9ja2VkIGF0IGJvdGggQ29sZXMgYW5kIFdvb2x3b3J0aHMpLCB0aGV5IHdpbGwgaGF2ZSB0aGUgc2FtZSBtZWFuIGNvc3QuICAKClRoZSBzdGF0aXN0aWNhbCBoeXBvdGhlc2VzIGZvciB0aGUgcGFpcmVkLXNhbXBsZXMgdC10ZXN0IGFyZSBhcyBmb2xsb3dzOiAgCgoqIEgwOs68zpQ9MAoqIEhBOs68zpTiiaAwCgojIyMgSW50cm9kdWN0aW9uCkNvbGVzIFN1cGVybWFya2V0cyBBdXN0cmFsaWEgUHR5IEx0ZCAodHJhZGluZyBhcyBDb2xlcykgYW5kIFdvb2x3b3J0aHMgU3VwZXJtYXJrZXRzIChjb2xsb3F1aWFsbHkga25vd24gYXMgIldvb2x3b3J0aHMiIG9yICJXb29saWVzIikgd2VyZSBmb3VuZGVkIGluIEF1c3RyYWxpYSBpbiAxOTE0IGFuZCAxOTI0LCByZXNwZWN0aXZlbHkgW14xXSxbXjJdLiBUb2dldGhlciwgdGhleSBtYWtlIHVwIG1vcmUgdGhhbiA4MCUgb2YgdGhlIEF1c3RyYWxpYW4gbWFya2V0LiBCb3RoIENvbGVzIGFuZCBXb29sd29ydGhzIG1hcmtldCB0aGVtc2VsdmVzIGFzIGV4dHJlbWVseSBwcmljZSBjb21wZXRpdGl2ZSwgd2hpbHN0IG1haW50YWluaW5nIGhpZ2ggcXVhbGl0eSBwcm9kdWN0cyBhbmQgYSB3aWRlIHJhbmdlIFteM10uIE92ZXIgdGhlIGNvdXJzZSBvZiB0aGlzIGludmVzdGlnYXRpb24sIHdlIHdpbGwgYXR0ZW1wdCB0byBwcm92ZSBvciBkaXNwcm92ZSBvdXIgbnVsbCBoeXBvdGhlc2lzIChhcyBvdXRsaW5lZCBhYm92ZSkuCgojIyMgRGF0YSBDb2xsZWN0aW9uClRoZSBwcmljZSBjb21wYXJpc29uIHdlYnNpdGUgd3d3LmZydWdsLmNvbS5hdVteNF0gd2FzIHVzZWQgZm9yIGRhdGEgY29sbGVjdGlvbi4gRGF0YSB3YXMgY29sbGVjdGVkIG92ZXIgdGhyZWUgZGF5cyAoNyBTZXAsIDE3IFNlcCAmIDE4IFNlcCAyMDE3KSB3aXRoaW4gdGhlIHBvc3Rjb2RlIDMwNTQgKENhcmx0b24gTm9ydGgsIFZpY3RvcmlhLCBBdXN0cmFsaWEpLiBEYXRlIHdhcyBub3RlZCBhcyBzYWxlIGl0ZW1zIHdpbGwgY2hhbmdlIHdpdGggdGltZSAoYW5kIHRodXMgY29sbGVjdGlvbiB3YXMgcGVyZm9ybWVkIHdpdGhpbiBhbiAxMSBkYXkgd2luZG93KS4gUG9zdGNvZGUgd2FzIGtlcHQgY29uc3RhbnQgYXMgZGlmZmVyZW50IHJlZ2lvbnMgd2lsbCBwcmVzdW1hYmx5IGhhdmUgc3BlY2lhbHMgYW5kIGZ1bGwgcHJpY2VkIHByb2R1Y3RzIGJhc2VkIG9uIGdlb2dyYXBoaWVzIChmb3IgZXhhbXBsZSBzaG9wcyBpbiBRdWVlbnNsYW5kIG1heSBzZWxsIG1hbmdvcyBhdCBtdWNoIGNoZWFwZXIgcHJpY2VzIHRoYW4gaW4gVmljdG9yaWEpLiBTdWNoIGFzc3VtcHRpb24gY291bGQgYmUgZXZhbHVhdGVkLCBob3dldmVyIGFyZSBvdXRzaWRlIHRoZSBzY29wZSBvZiB0aGlzIGludmVzdGlnYXRpb24uICAKCkZydWdsIGFsbG93cyBmaWx0ZXJpbmcgb2YgcHJvZHVjdHMgaW50byBhIHNlbGVjdGlvbiBvZiBkaXN0aW5jdCBuYXRpdmUgY2F0ZWdvcmllcywgZm9yIGV4YW1wbGUgSEVBTFRIICYgQkVBVVRZIG9yIEJBS0lORy4gQ2F0ZWdvcmllcyB3ZXJlIGNob3NlbiBiYXNlZCBvbiB0aGUgbGlrZWx5aG9vZCBvZiBjb250YWluaW5nIGlkZW50aWNhbCBwcm9kdWN0cy4gRm9yIGV4YW1wbGUgJ05pdmVhIE1vaXN0dXJpc2VyIDIwMGcnIGlzIG1hbnVmYWN0dXJlZCBhbmQgdGh1cyBpZGVudGljYWwgYmV0d2VlbiBDb2xlcyBhbmQgV29vbHdvcnRocyBzdG9yZXMsIHdoZXJlYXMgQ29sZXMgbWF5IHN0b2NrICdGcmVzaCBDZWxlcnkgMjUwZycgd2hpbGUgV29vbHdvcnRocyBtYXkgc3RvY2sgJ0Zhcm0gRnJlc2ggQ2VsZXJ5IDIyNWcnLiBUaGVzZSBzdWJ0bGUgZGlmZmVyZW5jZXMgbWFrZSBjb21wYXJpc29uIGhhcmRlciwgYW5kIHNvIHByb2R1Y3RzIGxpa2UgdGhlIGxhdHRlciB3ZXJlIGlnbm9yZWQuIEZvciB0aGUgcHJvZHVjdHMgc2FtcGxlZCwgdGhlIG5hdGl2ZSBjYXRlZ29yaWVzIGFuZCB0aGVpciByZXNwZWN0aXZlIGl0ZW0gY291bnRzIHdpbGwgYmUgZXhwbG9yZWQgYmVsb3cuICAKCkZvciBlYWNoIGl0ZW0gZm91ciBwcmljZXMgd2VyZSByZWNvcmRlZDsgaS4gQ29sZXMgRnVsbCBQcmljZSwgaWkuIENvbGVzIFNhbGUgUHJpY2UsIGlpaS4gV29vbHdvcnRocyBGdWxsIFByaWNlICYgaXYuIFdvb2x3b3J0aHMgU2FsZSBQcmljZS4gSWYgdGhlIGl0ZW0gd2FzIG5vdCBvbiBzYWxlLCB0aGUgZnVsbCBwcmljZSB3YXMgc2ltcGx5IHJlY29yZGVkIGludG8gYm90aCB0aGUgZnVsbCBwcmljZSBhbmQgdGhlIHNhbGUgY29sdW1uLiBUaGlzIHdhcyBkb25lIHRvIGZvciBlYXNlIG9mIGRhdGEgcHJvY2Vzc2luZywgYXMgZGVsdGEgPSAwIGJldHdlZW4gdGhlIGZ1bGwgcHJpY2UgYW5kIHNhbGUgY29sdW1uICh3aXRoaW4gZWl0aGVyIHRoZSBDb2xlcyBvciBXb29sd29ydGhzIGNhdGVnb3JpZXMpIHdpbGwgaW5kaWNhdGUgdGhlIGl0ZW0gaXMgbm90IHByZXNlbnRseSBvbiBzYWxlLiAgCgpEYXRhIHdhcyBjb2xsYXRlZCBpbnRvIGEgR29vZ2xlIFNoZWV0LCB3aGljaCB3YXMgcHVsbGVkIGRpcmVjdGx5IGludG8gdGhlIFIgTWFya2Rvd24gZW52aXJvbm1lbnQuIFNlZSBiZWxvdyBmb3IgZGF0YSBzdHJ1Y3R1cmUgYW5kIGltcG9ydGF0aW9uIG1ldGhvbG9neS4KCiMjIyBMb2FkIFBhY2thZ2VzIGFuZCBEYXRhCmBgYHtyLCBldmFsPUZBTFNFfQpsaWJyYXJ5KGNhcikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdzaGVldCkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoImh0bWx0b29scyIpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkoZ3Jhbm92YSkKZHMgPC0gZ3NoZWV0MnRibCgnaHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL29wZW4/aWQ9MV82UlowSFhnN1ZiZ083OG95RmZVeVphRk9VSFlXaWp5OFhIMV9qdzV0QTQnKQpgYGAKIyMjIFN1bW1hcnkgU3RhdGlzdGljcywgRGF0YSBDaGVja2luZyBhbmQgSW5pdGlhbCBWaXN1YWxpemF0aW9uClRoZSBpbXBvcnRhdGlvbiBvZiB0aGUgZGF0YSBzZXQgZnJvbSBHb29nbGUgU2hlZXRzIGFzICdkcycgd2FzIGNoZWNrZWQgd2l0aCBzdW1tYXJ5LCBhbmQgdGhlIGF0dHJpYnV0ZSBuYW1lcyB3ZXJlIGFsc28gY2hlY2tlZCB1c2luZyBzYXBwbHkuIER1cmluZyBkYXRhIGNvbGxlY3Rpb24sIGlkZW50aWNhbCBpdGVtcyBhdmFpbGFibGUgYXQgYm90aCBDb2xlcyBhbmQgV29vbHdvcnRocyB3ZXJlIGNob3Nlbi4gVGhlc2UgaXRlbXMgY2FtZSBmcm9tIHRoZSBmb2xsb3dpbmcgbmF0aXZlIGNhdGVnb3JpZXMgb24gdGhlIEZydWdsIHdlYnNpdGUgLSBCQUtJTkcsIERBSVJZICYgRUdHUyBESUVUQVJZLCBIRUFMVEggJiBMSUZFU1RZTEUsIERSSU5LUywgRlJPWkVOIEZPT0QsIEhFQUxUSCAmIEJFQVVUWSwgUEFDS0FHRUQgJiBSRUFEWSBNRUFMUyBhbmQgUEFOVFJZLCB2YWx1ZSBjb3VudHMgY2FuIGJlIHNlZW4gYmVsb3cuICAKCkR1cmluZyBkYXRhIGNvbGxlY3Rpb24sIHRoZXNlIGl0ZW1zIHdlcmUgcmUtY2F0ZWdvcml6ZWQgaW50byB0aGUgZm9sbG93aW5nIGNhdGVnb3JpZXMgLSBCZWF1dHksIERpZXQvIEd5bSBGb29kLCBTdWdhcnkgU25hY2sgYW5kIFN1cHBsZW1lbnQsIHZhbHVlIGNvdW50cyBjYW4gYWxzbyBiZSBzZWVuIGJlbG93LiBGb3IgdGhpcyBpbnZlc3RpZ2F0aW9uIHRoZSBhbGxvY2F0ZWQgY2F0ZWdvcmllcyB3aWxsIGJlIHVzZWQsIGFzIHRoZXkgY29udGFpbiB0aGUgc2FtZSBudW1iZXIgb2YgcHJvZHVjdHMgYnV0IHNwcmVhZCBvdmVyIGZld2VyIGdyb3VwaW5ncy4gSW4gbWFueSBjYXNlcyB0aGUgYWxsb2NhdGVkIGNhdGVnb3JpZXMgbW9yZSBhY2N1cmF0bHkgZ3JvdXAgdGhlIHByb2R1Y3RzLiBGb3IgZXhhbXBsZSBgdGFibGUoZHMkIkFsbG9jYXRlZCBDYXRlZ29yeSIpYCBzZWUgZm91ciBpdGVtcyB0aGF0IGNhbiBiZSBhY2N1cmF0ZWx5IGNhdGVnb3JpemVkIHRvZ2V0aGVyIGFzIHN1Z2FyeSBzbmFja3MuCgpgYGB7cn0KIyMgU3VtbWFyeQpzdW1tYXJ5KGRzKQpgYGAKYGBge3J9CiMjIENoZWNraW5nIHRoZSBjb2x1bW4gbmFtZXMgYW5kIGNvcnJlc3BvbmRpbmcgZGF0YSB0eXBlcwpzYXBwbHkoZHMsIHR5cGVvZikKYGBgCmBgYHtyfQojIyBWYWx1ZSBjb3VudHMgZm9yIHRoZSBuYXRpdmUgY2F0ZWdvcmllcwp0YWJsZShkcyRgTmF0aXZlIENhdGVnb3J5YCkKYGBgCmBgYHtyfQojIyBWYWx1ZSBjb3VudHMgZm9yIHRoZSBhbGxvY2F0ZWQgY2F0ZWdvcmllcwp0YWJsZShkcyRgQWxsb2NhdGVkIENhdGVnb3J5YCkKYGBgCmBgYHtyfQojIyBFeHBsb3JpbmcgdGhlIEFsbG9jYXRlZCBDYXRlZ29yaWVzCmRzW2MoMjgxLDI4NiwyOTEsMzAwKSxjKDIsMyw0KV0KYGBgCmBgYHtyfQojRXhwbG9yaW5nIFVuaXQgYW5kIEFtb3VudCAtIERhdGEgU2VsZWN0aW9uCmRzW2MoOSw0NywxNywyMzQsMjgzLDQwOSksYygyLDQsOSwxMCldCmBgYApgYGB7cn0KI1ZhbHVlIENvdW50cyBmb3IgVW5pdAp0YWJsZShkcyRgVW5pdGApCmBgYApUaGUgYXR0cmlidXRlcyAiVW5pdCIgYW5kICJBbW91bnQiIHJlZmVyIHRvIHRoZSB1bml0IG9mIG1lYXN1cmVtZW50IHRoZSBwcm9kdWN0IGNvbWVzIGluIGFuZCB0aGUgYW1vdW50LCByZXNwZWN0aXZlbHkgKHNlZSBleHBsb3JhdGlvbiBjb2RlIGJsb2NrcyBiZWxvdykuIFZhbHVlIGNvdW50cyB3ZXJlIHVzZWQgdG8gY2hlY2sgdGhlIGNhdGVnb3JpY2FsIGF0dHJpYnV0ZSBVbml0LiAgCgpBIHNjYXR0ZXIgcGxvdCBhbmQgYSBzdGFja2VkIGhpc3RvZ3JhbSB3ZXJlIHVzZWQgZXhwbG9yZSBhbW91bnQuCmBgYHtyLCBlY2hvID0gRkFMU0V9CiNFeHBsb3JpbmcgVW5pdCBhbmQgQW1vdW50IC0gRG90IFBsb3QKcXBsb3QoZGF0YT1kcywgeD1BbW91bnQsIHk9ZHMkYEFsbG9jYXRlZCBDYXRlZ29yeWAsIGNvbG91ciA9IGRzJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgLCBtYWluID0gJ0RvdCBQbG90IG9mIEFsbG9jYXRlZCBDYXRlZ29yeSB2cyBBbW91bnQnLCAgeWxhYiA9ICdBbGxvY2F0ZWQgQ2F0ZWdvcnknLCB4bGFiID0gJ0Ftb3VudCAoZywgbUwsIHBhY2spJykgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKQpgYGAKYGBge3IsIGVjaG8gPSBGQUxTRX0KI0V4cGxvcmluZyBVbml0IGFuZCBBbW91bnQgLSBTdGFja2VkIEhpc3RvZ3JhbQpxcGxvdChkYXRhPWRzLCB4PUFtb3VudCwgZmlsbCA9IGRzJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgLCBjb2xvdXIgPSBJKCJCbGFjayIpLCBtYWluID0gJ1N0YWNrZWQgSGlzdG9ncmFtIG9mIEFsbG9jYXRlZCBDYXRlZ29yeSB2cyBBbW91bnQnLCB4bGFiID0gJ0Ftb3VudCAoZywgbUwsIHBhY2spJykgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKQpgYGAKVGhlIGV4cGxvcmF0aW9uIHVwIHVudGlsIHRoaXMgcG9pbnQgaGFzIGhpZ2hsaWdodGVkIG51bWVyb3VzIGNoYWxsZW5nZXMgd29ya2luZyB3aXRoIHRoZSBkYXRhIHNldC4gVGhlIHByb2R1Y3RzIGFyZSBkaXN0cmlidXRlZCBiZXR3ZWVuIHRocmVlIHVuaXRzLCBncmFtcyAoZyksIG1pbGxpIGxpdHJlcyAobUwpICYgcGFjay4gUGFjayBoYXMgYSBkaWZmZXJlbnQgbWVhbmluZyBpbiB0aGUgY29udGV4dCBvZiB0aGUgcHJvZHVjdHMuIEZvciBleGFtcGxlIGBkc1tjKDksNDcsMTcsMjM0LDI4Myw0MDkpLGMoMiw0LDksMTApXWAgc2hvd3MgVHJlc2VtbWUgRXh0cmEgSG9sZCBIYWlyIFNwcmF5ICg3NWcpIGhhcyB1bml0cyBnLCB3aXRoIGFuIGFtb3VudCBvZiA3NS4gSm9obiBGcmllZGEgTWVkaXVtIEFzaCBCbG9uZGUgSGFpciBDb2xvdXIgKDEgcGFjaykgaGFzIHRoZSB1bml0IHBhY2sgKG5vdCB2b2x1bWUgb3IgbWFzcykgYW5kIGEgcXVhbnRpdHkgb2Ygb25lLiBJbiB0aGUgU3VwcGxlbWVudCBjYXRlZ29yeSBPc3RlbGluIFZpdGFtaW4gRCAmIENhbGNpdW0gVGFibGV0cyAoMTgwIHBhY2spIGhhcyB1bml0IHBhY2sgYW5kIHF1YW50aXR5IDE4MC4gVGhlIGRhdGEgd2lsbCBiZSBleHBsb3JlZCBmdXJ0aGVyIGFuZCBwcmVwcm9jZXNzZWQsIGFzIGRlc2NyaWJlZCBiZWxvdy4KCiMjIyBFeHBsb3JpbmcgdGhlIE5hdGl2ZSBDb250aW51b3VzIERhdGEgd2l0aCBTY2F0dGVyIFBsb3RzClByaW9yIHRvIGFueSB0cmFuc2Zvcm1hdGlvbnMsIHRoZSBkYXRhIHdhcyBhbHNvIGV4cGxvcmVkIGluIGEgcXVhbGl0YXRpdmUgZmFzaGlvbiB3aXRoIHNjYXR0ZXJwbG90cyAoc2VlIGJlbG93KS4gIApgYGB7ciwgZWNobyA9IEZBTFNFfQp3d1Zjb2xlcyA8LSBnZ3Bsb3QoZGF0YT1kcywgYWVzKHg9Q29sZXMsIHk9V29vbHdvcnRocywgY29sb3VyID0gZHMkYEFsbG9jYXRlZCBDYXRlZ29yeWApKSArCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fcG9pbnQoKSArIAogIGxhYnModGl0bGUgPSAnV29vbHdvcnRocyB2ZXJzdXMgQ29sZXMgRnVsbCBQcmljZSBTY2F0dGVyIFBsb3QnLCAgCiAgICAgICB5ID0gJ1dvb2x3b3J0aHMgRnVsbCBQcmljZSBJdGVtcyAoQVVEKScsIAogICAgICAgeCA9ICdDb2xlcyBGdWxsIFByaWNlIEl0ZW1zIChBVUQpJykgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE1LCB5ID0gNCwgbGFiZWwgPSAiUiBTcXVhcmVkIikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxNSwgeSA9IDEsIGxhYmVsID0gZm9ybWF0KHN1bW1hcnkobG0oV29vbHdvcnRocyB+IENvbGVzLCBkYXRhID0gZHMpKSRyLnNxdWFyZWQsIGRpZ2l0cyA9IDMpKQp3d1Zjb2xlcwpgYGAKCmBgYHtyLCBlY2hvID0gRkFMU0V9Cnd3U2FsZVZjb2xlc1NhbGUgPC0gZ2dwbG90KGRhdGE9ZHMsIGFlcyh4PWRzJCdDb2xlcyBTYWxlJywgeT1kcyQnV29vbHdvcnRocyBTYWxlJywgY29sb3VyID0gZHMkYEFsbG9jYXRlZCBDYXRlZ29yeWApKSArCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fcG9pbnQoKSArIAogIGxhYnModGl0bGUgPSAnV29vbHdvcnRocyBTYWxlIHZlcnN1cyBDb2xlcyBTYWxlIFByaWNlIFNjYXR0ZXIgUGxvdCcsICAKICAgICAgIHkgPSAnV29vbHdvcnRocyBTYWxlIEl0ZW1zIChBVUQpJywgCiAgICAgICB4ID0gJ0NvbGVzIFNhbGUgSXRlbXMgKEFVRCknKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTUsIHkgPSA0LCBsYWJlbCA9ICJSIFNxdWFyZWQiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE1LCB5ID0gMSwgbGFiZWwgPSBmb3JtYXQoc3VtbWFyeShsbShkcyQnV29vbHdvcnRocyBTYWxlJyB+IGRzJCdDb2xlcyBTYWxlJywgZGF0YSA9IGRzKSkkci5zcXVhcmVkLCBkaWdpdHMgPSAzKSkKd3dTYWxlVmNvbGVzU2FsZQpgYGAKVGhlIHNjYXR0ZXIgc2hvdyAocXVhbGl0aXZlbHkpLCB0aGF0IHRoZSBmdWxsIHByaWNlIGJldHdlZW4gV29vbHdvcmh0cyBhbmQgQ29sZXMgaXMgcXVpdGUgd2VsbCBjb3JyZWxhdGVkLCB3aGlsZSB0aGUgc2FsZSBwcmljZSBiZXR3ZWVuIFdvb2x3b3J0aHMgYW5kIENvbGVzIGlzIHBvb3JseSBjb3JyZWxhdGVkIGJ5IGNvbXBhcmlzb24gKFIgc3F1YXJlZCBvZiAwLjk4OCBhbmQgMC43MzUsIHJlc3BlY3RpdmVseSkuIFRoaXMgaW5kaWNhdGVzIHRoYXQgQ29sZXMgYW5kIFdvb2x3b3J0aHMgZW1wbG95IGRpZmZlcmVudCBzYWxlIHByaWNpbmcgc3RyYXRlcmd5LgoKIyMjIEJhciBDaGFydHMgb2YgTmF0aXZlIERhdGEKVGhlc2UgZGF0YSB3ZXJlIHBsb3R0ZWQgaW50byBiYXIgY2hhcnRzIGZvciBXb29sd29ydGhzIChkZW5vdGVkIFdXKSwgV29vbHdvcnRocyBTYWxlIChkZW5vdGVkIFdXIFNhbGUpLCBDb2xlcyBhbmQgQ29sZXMgU2FsZS4gIAoKQXMgbWVudGlvbmVkIHByaW9yLCB0aGVzZSBkYXRhIGNvbnRhaW4gYSB2YXJpZXR5IG9mIHZvbHVtZXMgLyB1bml0cyAvIHF1YW50aXRlcy4gVGhlIHBsb3QgYmVsb3cgc2hvd3MgdGhlICJCZWF1dHkiIGFsbG9jYXRlZCBjYXRlZ29yeSBnaXZlcyBubyBvdXRsaWVycyBhY2Nycm9zcyB0aGUgZm91ciBwbG90cywgYW5kIGhhcyB3ZWxsIGRpc3RyaWJ1dGVkIGJvdW5kcy4gIkJlYXV0eSIgd2lsbCBiZSBsZWZ0IGFzIGlzIGZvciB0aGUgc3Vic2VxdWVudCBhbmFseXNpcy4gIlN1Z2FyeSBTbmFjayIgJiAiRGlldC8gR3ltIEZvb2QiIHdpbGwgYmUgY29udmVydGVkIGFsbCBpbnRvIHByaWNlIHBlciB1bml0IDEwMDAgZy4gRm9yIHRoaXMgZXhlcmNpc2Ugd2Ugd2lsbCBhc3N1bWUgMSBnID0gMSBtTCAoYSByZWFzb25hYmxlIGFzc3VtcHRpb24gYXMgYW55IGxpcXVpZHMgZnJvbSB0aGVzZSBjYXRlZ29yaWVzIHdpbGwgYmUgbW9zdGx5IHdhdGVyLCBhbmQgMSBtTCB3YXRlciBoYXMgMSBnIG9mIG1hc3MpLiAiU3VwcGxlbWVudCIgaGFzIG1pbmltYWwgb3V0bGllcnMgYW5kIHdlbGwgZGlzdHJpYnV0ZWQgYm91bmRzLCBhbmQgd2lsbCBiZSBsZWZ0IGFzIGlzIGZvciB0aGUgc3Vic2VxdWVudCBhbmFseXNpcy4KYGBge3IsIGVjaG8gPSBGQUxTRX0KY29sZXNIaXN0IDwtIGdncGxvdChkYXRhPWRzLCBhZXMoeD1kcyQnQWxsb2NhdGVkIENhdGVnb3J5JywgeT1Db2xlcywgZmlsbCA9IGRzJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsgbGFicyh0aXRsZSA9IE5VTEwsICB4ID0gIkNvbGVzIiwgeSA9IE5VTEwpICsgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKyBjb29yZF9mbGlwKCkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDU1KSwgZXhwYW5kID0gYygwLCAwKSkKY29sZXNTYWxlSGlzdCA8LSBnZ3Bsb3QoZGF0YT1kcywgYWVzKHg9ZHMkJ0FsbG9jYXRlZCBDYXRlZ29yeScsIHk9ZHMkYENvbGVzIFNhbGVgLCBmaWxsID0gZHMkYEFsbG9jYXRlZCBDYXRlZ29yeWApKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKyBsYWJzKHRpdGxlID0gTlVMTCwgIHggPSAiQ29sZXMgU2FsZSIsIHkgPSBOVUxMKSArIGd1aWRlcyhmaWxsID0gRkFMU0UpICsgY29vcmRfZmxpcCgpICsgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCw1NSksIGV4cGFuZCA9IGMoMCwgMCkpCnd3SGlzdCA8LSBnZ3Bsb3QoZGF0YT1kcywgYWVzKHg9ZHMkJ0FsbG9jYXRlZCBDYXRlZ29yeScsIHk9V29vbHdvcnRocywgZmlsbCA9IGRzJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsgbGFicyh0aXRsZSA9IE5VTEwsICB4ID0gIldXIiwgeSA9IE5VTEwpICsgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKyBjb29yZF9mbGlwKCkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDU1KSwgZXhwYW5kID0gYygwLCAwKSkKd3dTYWxlSGlzdCA8LSBnZ3Bsb3QoZGF0YT1kcywgYWVzKHg9ZHMkJ0FsbG9jYXRlZCBDYXRlZ29yeScsIHk9ZHMkYFdvb2x3b3J0aHMgU2FsZWAsIGZpbGwgPSBkcyRgQWxsb2NhdGVkIENhdGVnb3J5YCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArIGxhYnModGl0bGUgPSBOVUxMLCB4ID0gIldXIFNhbGUiLCB5ID0gTlVMTCkgKyBndWlkZXMoZmlsbCA9IEZBTFNFKSArIGNvb3JkX2ZsaXAoKSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsNTUpLCBleHBhbmQgPSBjKDAsIDApKQpgYGAKYGBge3IsIGVjaG8gPSBGQUxTRX0KZ3JpZC5hcnJhbmdlKGNvbGVzSGlzdCwgY29sZXNTYWxlSGlzdCwgd3dIaXN0LCB3d1NhbGVIaXN0LCBucm93ID0gNCkKYGBgCgojIyMgUmVzdHJ1Y3R1cmluZyB0aGUgRGF0YQpUaGVzZSBkYXRhIHdlcmUgYnJva2VuIGludG8gdGhlaXIgcmVzcGVjdGl2ZSBjYXRlZ29yaWVzLgpgYGB7ciBicmVha2luZyB1cCBjYXRlZ29yaWVzLCBlY2hvPVRSVUV9CmJlYXV0eV9maWx0ZXIgPC0gZHMkYEFsbG9jYXRlZCBDYXRlZ29yeWAgPT0gIkJlYXV0eSIKYmVhdXR5X2RhdGEgPC0gZHNbYmVhdXR5X2ZpbHRlcixdCnN1Z2FyeVNuYWNrX2ZpbHRlciA8LSBkcyRgQWxsb2NhdGVkIENhdGVnb3J5YCA9PSAiU3VnYXJ5IFNuYWNrIgpzdWdhcnlTbmFja19kYXRhIDwtIGRzW3N1Z2FyeVNuYWNrX2ZpbHRlcixdCmRpZXRHeW1Gb29kX2ZpbHRlciA8LSBkcyRgQWxsb2NhdGVkIENhdGVnb3J5YCA9PSAiRGlldC8gR3ltIEZvb2QiCmRpZXRHeW1Gb29kX2RhdGEgPC0gZHNbZGlldEd5bUZvb2RfZmlsdGVyLF0Kc3VwcGxlbWVudF9maWx0ZXIgPC0gZHMkYEFsbG9jYXRlZCBDYXRlZ29yeWAgPT0gIlN1cHBsZW1lbnQiCnN1cHBsZW1lbnRfZGF0YSA8LSBkc1tzdXBwbGVtZW50X2ZpbHRlcixdCmBgYApSZXN1bHRhbnQgdW5pdHMgd2VyZSBicmVpZmx5IGNoZWNrZWQuCmBgYHtyfQojVmFsdWUgQ291bnRzIGZvciBVbml0CnRhYmxlKHN1Z2FyeVNuYWNrX2RhdGEkYFVuaXRgKQpgYGAKYGBge3J9CiNWYWx1ZSBDb3VudHMgZm9yIFVuaXQKdGFibGUoZGlldEd5bUZvb2RfZGF0YSRgVW5pdGApCmBgYApQcmljZSBwZXIgMTAwMGcgd2FzIGdlbmVyYXRlZCBmb3IgIlN1Z2FyeSBTbmFjayIuCmBgYHtyIFByaWNlIHBlciAxMDAwZyBmb3IgU3VnYXJ5IFNuYWNrICwgZWNobz1UUlVFfQpzdWdhcnlTbmFja19kYXRhJFByaWNlTWFzcyA8LSAxMDAwIC8gc3VnYXJ5U25hY2tfZGF0YSRBbW91bnQKc3VnYXJ5U25hY2tfZGF0YSRQZXIxMDAwZ1ByaWNlX0NvbGVzIDwtIHN1Z2FyeVNuYWNrX2RhdGEkUHJpY2VNYXNzKnN1Z2FyeVNuYWNrX2RhdGEkQ29sZXMKc3VnYXJ5U25hY2tfZGF0YSRQZXIxMDAwZ1ByaWNlX1dXIDwtIHN1Z2FyeVNuYWNrX2RhdGEkUHJpY2VNYXNzKnN1Z2FyeVNuYWNrX2RhdGEkV29vbHdvcnRocwpzdWdhcnlTbmFja19kYXRhJFBlcjEwMDBnUHJpY2VfQ29sZXNTYWxlIDwtIHN1Z2FyeVNuYWNrX2RhdGEkUHJpY2VNYXNzKnN1Z2FyeVNuYWNrX2RhdGEkJ0NvbGVzIFNhbGUnCnN1Z2FyeVNuYWNrX2RhdGEkUGVyMTAwMGdQcmljZV9XV1NhbGUgPC0gc3VnYXJ5U25hY2tfZGF0YSRQcmljZU1hc3Mqc3VnYXJ5U25hY2tfZGF0YSQnV29vbHdvcnRocyBTYWxlJwpgYGAKUHJpY2UgcGVyIDEwMDBnIHdhcyBnZW5lcmF0ZWQgZm9yICJEaWV0LyBHeW0gRm9vZCIuCmBgYHtyIFByaWNlIHBlciAxMDAwZyBmb3IgRGlldCBHeW0gRm9vZCwgZWNobz1UUlVFfQpkaWV0R3ltRm9vZF9kYXRhJFByaWNlTWFzcyA8LSAxMDAwIC8gZGlldEd5bUZvb2RfZGF0YSRBbW91bnQKZGlldEd5bUZvb2RfZGF0YSRQZXIxMDAwZ1ByaWNlX0NvbGVzIDwtIGRpZXRHeW1Gb29kX2RhdGEkUHJpY2VNYXNzICogZGlldEd5bUZvb2RfZGF0YSRDb2xlcwpkaWV0R3ltRm9vZF9kYXRhJFBlcjEwMDBnUHJpY2VfV1cgPC0gZGlldEd5bUZvb2RfZGF0YSRQcmljZU1hc3MgKiBkaWV0R3ltRm9vZF9kYXRhJFdvb2x3b3J0aHMKZGlldEd5bUZvb2RfZGF0YSRQZXIxMDAwZ1ByaWNlX0NvbGVzU2FsZSA8LSBkaWV0R3ltRm9vZF9kYXRhJFByaWNlTWFzcyAqIGRpZXRHeW1Gb29kX2RhdGEkJ0NvbGVzIFNhbGUnCmRpZXRHeW1Gb29kX2RhdGEkUGVyMTAwMGdQcmljZV9XV1NhbGUgPC0gZGlldEd5bUZvb2RfZGF0YSRQcmljZU1hc3MgKiBkaWV0R3ltRm9vZF9kYXRhJCdXb29sd29ydGhzIFNhbGUnCmBgYApUaGVzZSBkYXRhIHdlcmUgZXhwb3J0ZWQgdG8gLmNzdiBhbmQgcmVjb21iaW5lZCB3aXRoIHRoZSBCZWF1dHkgYW5kIFN1cHBsbWVudCBkYXRhIHRvIGdpdmUgZHNBZGp1c3RlZC4KYGBge3J9CndyaXRlLmNzdihkaWV0R3ltRm9vZF9kYXRhLCBmaWxlID0gIkRpZXRHeW1Gb29kLmNzdiIpCndyaXRlLmNzdihzdWdhcnlTbmFja19kYXRhLCBmaWxlID0gIlN1Z2FyeVNuYWNrLmNzdiIpCmRzQWRqdXN0ZWQgPC0gZ3NoZWV0MnRibCgnaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMVZRaDA3eDBPUWFhQURoZmxjWjVZWTE3YkIwSG85a1VzUHljQnNSRllzSWsvZWRpdD91c3A9c2hhcmluZycpCmBgYAojIyMjIEJveCBQbG90IG9mIGRzQWRqdXN0ZWQKYGBge3IsIGVjaG8gPSBGQUxTRX0KY29sZXNIaXN0QWRqdXN0ZWQgPC0gZ2dwbG90KGRhdGE9ZHNBZGp1c3RlZCwgYWVzKHg9ZHNBZGp1c3RlZCQnQWxsb2NhdGVkIENhdGVnb3J5JywgeT1Db2xlc0FkanVzdGVkLCBmaWxsID0gZHNBZGp1c3RlZCRgQWxsb2NhdGVkIENhdGVnb3J5YCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArIGxhYnModGl0bGUgPSBOVUxMLCAgeCA9ICJDb2xlcyBBZGouIiwgeSA9IE5VTEwpICsgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKyBjb29yZF9mbGlwKCkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDQxMCksIGV4cGFuZCA9IGMoMCwgMCkpCmNvbGVzU2FsZUhpc3RBZGp1c3RlZCA8LSBnZ3Bsb3QoZGF0YT1kc0FkanVzdGVkLCBhZXMoeD1kc0FkanVzdGVkJCdBbGxvY2F0ZWQgQ2F0ZWdvcnknLCB5PUNvbGVzU2FsZUFkanVzdGVkLCBmaWxsID0gZHNBZGp1c3RlZCRgQWxsb2NhdGVkIENhdGVnb3J5YCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArIGxhYnModGl0bGUgPSBOVUxMLCAgeCA9ICJDb2xlcyBTYWxlIEFkai4iLCB5ID0gTlVMTCkgKyBndWlkZXMoZmlsbCA9IEZBTFNFKSArIGNvb3JkX2ZsaXAoKSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsNDEwKSwgZXhwYW5kID0gYygwLCAwKSkKd3dIaXN0QWRqdXN0ZWQgPC0gZ2dwbG90KGRhdGE9ZHNBZGp1c3RlZCwgYWVzKHg9ZHNBZGp1c3RlZCQnQWxsb2NhdGVkIENhdGVnb3J5JywgeT1Xb29sd29ydGhzQWRqdXN0ZWQsIGZpbGwgPSBkc0FkanVzdGVkJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsgbGFicyh0aXRsZSA9IE5VTEwsICB4ID0gIldXIEFkai4iLCB5ID0gTlVMTCkgKyBndWlkZXMoZmlsbCA9IEZBTFNFKSArIGNvb3JkX2ZsaXAoKSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsNDEwKSwgZXhwYW5kID0gYygwLCAwKSkKd3dTYWxlSGlzdEFkanVzdGVkIDwtIGdncGxvdChkYXRhPWRzQWRqdXN0ZWQsIGFlcyh4PWRzQWRqdXN0ZWQkJ0FsbG9jYXRlZCBDYXRlZ29yeScsIHk9V29vbHdvcnRoc1NhbGVBZGp1c3RlZCwgZmlsbCA9IGRzQWRqdXN0ZWQkYEFsbG9jYXRlZCBDYXRlZ29yeWApKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKyBsYWJzKHRpdGxlID0gTlVMTCwgeCA9ICJXVyBTYWxlIEFkai4iLCB5ID0gTlVMTCkgKyBndWlkZXMoZmlsbCA9IEZBTFNFKSArIGNvb3JkX2ZsaXAoKSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsNDEwKSwgZXhwYW5kID0gYygwLCAwKSkKYGBgCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpncmlkLmFycmFuZ2UoY29sZXNIaXN0QWRqdXN0ZWQsIGNvbGVzU2FsZUhpc3RBZGp1c3RlZCwgd3dIaXN0QWRqdXN0ZWQsIHd3U2FsZUhpc3RBZGp1c3RlZCwgbnJvdyA9IDQpCmBgYApPdXRsaWVyIGlkZW50aWZpY2F0aW9uIHdhcyB0aGVuIHBlcmZvcm1lZC4KYGBge3Igc3Vic2V0dGluZyBmb3Igb3V0bGllcnMsIGVjaG89VFJVRX0Kc3VnYXJ5U25hY2tfZmlsdGVyQWRqdXN0ZWQgPC0gZHNBZGp1c3RlZCRgQWxsb2NhdGVkIENhdGVnb3J5YCA9PSAiU3VnYXJ5IFNuYWNrIgpzdWdhcnlTbmFja19kYXRhQWRqdXN0ZWQgPC0gZHNBZGp1c3RlZFtzdWdhcnlTbmFja19maWx0ZXJBZGp1c3RlZCxdCmRpZXRHeW1Gb29kX2ZpbHRlckFkanVzdGVkIDwtIGRzQWRqdXN0ZWQkYEFsbG9jYXRlZCBDYXRlZ29yeWAgPT0gIkRpZXQvIEd5bSBGb29kIgpkaWV0R3ltRm9vZF9kYXRhQWRqdXN0ZWQgPC0gZHNBZGp1c3RlZFtkaWV0R3ltRm9vZF9maWx0ZXIsXQpgYGAKCmBgYHtyfQpzdW1tYXJ5KHN1Z2FyeVNuYWNrX2RhdGFBZGp1c3RlZCRDb2xlc0FkanVzdGVkKQpgYGAKYGBge3J9CmRzQWRqdXN0ZWRbZHNBZGp1c3RlZCRDb2xlc0FkanVzdGVkID09IDgzLjMzLF0KYGBgCmBgYHtyfQpzdWdhcnlTbmFja19kYXRhQWRqdXN0ZWRbc3VnYXJ5U25hY2tfZGF0YUFkanVzdGVkJFdvb2x3b3J0aHNTYWxlQWRqdXN0ZWQgPiA1MCxdCmBgYApgYGB7cn0Kc3VnYXJ5U25hY2tfZGF0YUFkanVzdGVkW3N1Z2FyeVNuYWNrX2RhdGFBZGp1c3RlZCRXb29sd29ydGhzU2FsZUFkanVzdGVkID09IDU2LjAwLF0KYGBgCgpgYGB7cn0KZHNBZGp1c3RlZFtkc0FkanVzdGVkJENvbGVzQWRqdXN0ZWQgPiAxMTAsXQpgYGAKVGhlIGl0ZW1zIGFib3ZlIHdlcmUgZmlsbGVkIHdpdGggdGhlIG1lYW4gb2YgZWFjaCBjYXRlZ29yeSBpbiB0aGVpciByZXNwZWN0aXZlIGNvbHVtbnMsIGFuZCBkYXRhIHdhcyBpbXBvcnRlZCBvbmNlIG1vcmUgYXMgZHNBZGp1c3RlZCAobmFtZSB3YXMga2VwdCBjb25zdGFudCBmb3Igc2ltcGxpY2l0aWVzIHNha2UpLgpgYGB7cn0KZHNBZGp1c3RlZCA8LSBnc2hlZXQydGJsKCdodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9zcHJlYWRzaGVldHMvZC8xQzAxRkhFNlkwZ25rRWQtZ092YlY1N0NtZDhCWFlzMGNoMXBHRGE5YUtLcy9lZGl0P3VzcD1zaGFyaW5nJykKYGBgCiMjIyMgQm94IFBsb3Qgb2YgZHNBZGp1c3RlZCB3aXRoIE91dGxpZXJzIHJlbW92ZWQKYGBge3IsIGVjaG8gPSBGQUxTRX0KY29sZXNIaXN0QWRqdXN0ZWQgPC0gZ2dwbG90KGRhdGE9ZHNBZGp1c3RlZCwgYWVzKHg9ZHNBZGp1c3RlZCQnQWxsb2NhdGVkIENhdGVnb3J5JywgeT1Db2xlc0FkanVzdGVkLCBmaWxsID0gZHNBZGp1c3RlZCRgQWxsb2NhdGVkIENhdGVnb3J5YCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArIGxhYnModGl0bGUgPSBOVUxMLCAgeCA9ICJDb2xlcyBBZGouIiwgeSA9IE5VTEwpICsgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKyBjb29yZF9mbGlwKCkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDQxMCksIGV4cGFuZCA9IGMoMCwgMCkpCmNvbGVzU2FsZUhpc3RBZGp1c3RlZCA8LSBnZ3Bsb3QoZGF0YT1kc0FkanVzdGVkLCBhZXMoeD1kc0FkanVzdGVkJCdBbGxvY2F0ZWQgQ2F0ZWdvcnknLCB5PUNvbGVzU2FsZUFkanVzdGVkLCBmaWxsID0gZHNBZGp1c3RlZCRgQWxsb2NhdGVkIENhdGVnb3J5YCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArIGxhYnModGl0bGUgPSBOVUxMLCAgeCA9ICJDb2xlcyBTYWxlIEFkai4iLCB5ID0gTlVMTCkgKyBndWlkZXMoZmlsbCA9IEZBTFNFKSArIGNvb3JkX2ZsaXAoKSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsNDEwKSwgZXhwYW5kID0gYygwLCAwKSkKd3dIaXN0QWRqdXN0ZWQgPC0gZ2dwbG90KGRhdGE9ZHNBZGp1c3RlZCwgYWVzKHg9ZHNBZGp1c3RlZCQnQWxsb2NhdGVkIENhdGVnb3J5JywgeT1Xb29sd29ydGhzQWRqdXN0ZWQsIGZpbGwgPSBkc0FkanVzdGVkJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsgbGFicyh0aXRsZSA9IE5VTEwsICB4ID0gIldXIEFkai4iLCB5ID0gTlVMTCkgKyBndWlkZXMoZmlsbCA9IEZBTFNFKSArIGNvb3JkX2ZsaXAoKSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsNDEwKSwgZXhwYW5kID0gYygwLCAwKSkKd3dTYWxlSGlzdEFkanVzdGVkIDwtIGdncGxvdChkYXRhPWRzQWRqdXN0ZWQsIGFlcyh4PWRzQWRqdXN0ZWQkJ0FsbG9jYXRlZCBDYXRlZ29yeScsIHk9V29vbHdvcnRoc1NhbGVBZGp1c3RlZCwgZmlsbCA9IGRzQWRqdXN0ZWQkYEFsbG9jYXRlZCBDYXRlZ29yeWApKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKyBsYWJzKHRpdGxlID0gTlVMTCwgeCA9ICJXVyBTYWxlIEFkai4iLCB5ID0gTlVMTCkgKyBndWlkZXMoZmlsbCA9IEZBTFNFKSArIGNvb3JkX2ZsaXAoKSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsNDEwKSwgZXhwYW5kID0gYygwLCAwKSkKYGBgCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpncmlkLmFycmFuZ2UoY29sZXNIaXN0QWRqdXN0ZWQsIGNvbGVzU2FsZUhpc3RBZGp1c3RlZCwgd3dIaXN0QWRqdXN0ZWQsIHd3U2FsZUhpc3RBZGp1c3RlZCwgbnJvdyA9IDQpCmBgYAojIyMjIFNjYWxlZCBCb3ggUGxvdCBvZiBkc0FkanVzdGVkIHdpdGggT3V0bGllcnMgcmVtb3ZlZApgYGB7ciwgZWNobyA9IEZBTFNFfQpjb2xlc0hpc3RBZGp1c3RlZCA8LSBnZ3Bsb3QoZGF0YT1kc0FkanVzdGVkLCBhZXMoeD1kc0FkanVzdGVkJCdBbGxvY2F0ZWQgQ2F0ZWdvcnknLCB5PUNvbGVzQWRqdXN0ZWQsIGZpbGwgPSBkc0FkanVzdGVkJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsgbGFicyh0aXRsZSA9IE5VTEwsICB4ID0gIkNvbGVzIEFkai4iLCB5ID0gTlVMTCkgKyBndWlkZXMoZmlsbCA9IEZBTFNFKSArIGNvb3JkX2ZsaXAoKSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsMTMwKSwgZXhwYW5kID0gYygwLCAwKSkKY29sZXNTYWxlSGlzdEFkanVzdGVkIDwtIGdncGxvdChkYXRhPWRzQWRqdXN0ZWQsIGFlcyh4PWRzQWRqdXN0ZWQkJ0FsbG9jYXRlZCBDYXRlZ29yeScsIHk9Q29sZXNTYWxlQWRqdXN0ZWQsIGZpbGwgPSBkc0FkanVzdGVkJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsgbGFicyh0aXRsZSA9IE5VTEwsICB4ID0gIkNvbGVzIFNhbGUgQWRqLiIsIHkgPSBOVUxMKSArIGd1aWRlcyhmaWxsID0gRkFMU0UpICsgY29vcmRfZmxpcCgpICsgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwxMzApLCBleHBhbmQgPSBjKDAsIDApKQp3d0hpc3RBZGp1c3RlZCA8LSBnZ3Bsb3QoZGF0YT1kc0FkanVzdGVkLCBhZXMoeD1kc0FkanVzdGVkJCdBbGxvY2F0ZWQgQ2F0ZWdvcnknLCB5PVdvb2x3b3J0aHNBZGp1c3RlZCwgZmlsbCA9IGRzQWRqdXN0ZWQkYEFsbG9jYXRlZCBDYXRlZ29yeWApKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKyBsYWJzKHRpdGxlID0gTlVMTCwgIHggPSAiV1cgQWRqLiIsIHkgPSBOVUxMKSArIGd1aWRlcyhmaWxsID0gRkFMU0UpICsgY29vcmRfZmxpcCgpICsgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwxMzApLCBleHBhbmQgPSBjKDAsIDApKQp3d1NhbGVIaXN0QWRqdXN0ZWQgPC0gZ2dwbG90KGRhdGE9ZHNBZGp1c3RlZCwgYWVzKHg9ZHNBZGp1c3RlZCQnQWxsb2NhdGVkIENhdGVnb3J5JywgeT1Xb29sd29ydGhzU2FsZUFkanVzdGVkLCBmaWxsID0gZHNBZGp1c3RlZCRgQWxsb2NhdGVkIENhdGVnb3J5YCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArIGxhYnModGl0bGUgPSBOVUxMLCB4ID0gIldXIFNhbGUgQWRqLiIsIHkgPSBOVUxMKSArIGd1aWRlcyhmaWxsID0gRkFMU0UpICsgY29vcmRfZmxpcCgpICsgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwxMzApLCBleHBhbmQgPSBjKDAsIDApKQpgYGAKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmdyaWQuYXJyYW5nZShjb2xlc0hpc3RBZGp1c3RlZCwgY29sZXNTYWxlSGlzdEFkanVzdGVkLCB3d0hpc3RBZGp1c3RlZCwgd3dTYWxlSGlzdEFkanVzdGVkLCBucm93ID0gNCkKYGBgClRoZXNlIGRhdGEgd2lsbCBub3cgYmUgcHJlcGFyZWQgZm9yIHBhaXJlZCBzYW1wbGUgaHlwb3RoZXNpcyB0ZXN0aW5nLCB0aHJvdWdoIHRoZSBpbnRyb2R1Y3Rpb24gb2YgYSBkaWZmZXJlbmNlIGF0dHJpYnV0ZSAoZCkgaW4gdGhlIGBkc0FkanVzdGVkYCBkYXRhIHNldC4gT25seSBDb2xlcyBTQUxFIGFuZCBXb29sd29ydGhzIFNBTEUgZGF0YSB3aWxsIGJlIGNvbnNpZGVyZWQgbW92aW5nIGZvcndhcmQuIEFuYWx5c2lzIG9mIGZ1bGwgcHJpY2UgdmVyc3VzIHNhbGUgcHJpY2UgaXMgb3V0c2lkZSB0aGUgc2NvcGUgb2YgdGhpcyBpbnZlc3RpZ2F0aW9uLgpgYGB7cn0KZHNBZGp1c3RlZCA8LSBkc0FkanVzdGVkICU+JSBtdXRhdGUoZCA9IENvbGVzU2FsZUFkanVzdGVkIC0gV29vbHdvcnRoc1NhbGVBZGp1c3RlZCkKYGBgClRoZXNlIGRhdGEgYXJlIGNvbnNpZGVyZWQgdG8gYmUgc3VmZmljaWVudGx5IHByZXByb2Nlc3NlZCBmb3IgYW5hbHlzaXMuIFBhaXJlZCBzYW1wbGUgdC10ZXN0aW5nIHdpbGwgYmUgcGVyZm9ybWVkIG9uIHRoZSBkYXRhIHNldCBgZHNBZGp1c3RlZGAsIG9uIHRoZSBhdHRyaWJ1dGUgJ2QnLiBEdWUgdG8gdGhlIG5hdHVyZSBvZiB0aGUgbWV0aG9sb2RneSAodC10ZXN0IG9mIGRpZmZlcmVuY2UpIHRoZSByZW1haW5pbmcgb3V0bGllcnMgd2lsbCBub3QgaW50ZXJmZXJlIHdpdGggdGhlIGFuYWx5c2lzLiBEdWUgdG8gdGhlIHNpemUgb2YgdGhlIGRhdGEgc2V0IGFuZCB0aGUgY29uc3RpdHVlbnQgYWxsb2NhdGVkIGNhdGVnb3JpZXMgKG4gPiAzMCksIHdlIHdpbGwgYXNzdW1lIG5vcm1hbGl0eS4gUVEgcGxvdHMgd2VyZSBicmVpZmx5IGV4cGxvcmVkLCBob3dldmVyIHdlcmUgZGVlbWVkIHRvIGJlIHVuZXNzY2VzYXJ5LiBUaGVzZSBkYXRhIHdlcmUgYnJva2VuIGludG8gdGhlaXIgY29uc3RpdHVlbnQgY2F0ZWdvcmllcyBmb3IgcHJvY2Vzc2luZyBhbHNvLgpgYGB7ciBicmVha2luZyB1cCBjYXRlZ29yaWVzIGZvciBkaWZmZXJlbmNlLCBlY2hvPVRSVUV9CmJlYXV0eV9maWx0ZXJfZCA8LSBkc0FkanVzdGVkJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgID09ICJCZWF1dHkiCmJlYXV0eV9kYXRhX2QgPC0gZHNBZGp1c3RlZFtiZWF1dHlfZmlsdGVyX2QsXQpzdWdhcnlTbmFja19maWx0ZXJfZCA8LSBkc0FkanVzdGVkJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgID09ICJTdWdhcnkgU25hY2siCnN1Z2FyeVNuYWNrX2RhdGFfZCA8LSBkc0FkanVzdGVkW3N1Z2FyeVNuYWNrX2ZpbHRlcl9kLF0KZGlldEd5bUZvb2RfZmlsdGVyX2QgPC0gZHNBZGp1c3RlZCRgQWxsb2NhdGVkIENhdGVnb3J5YCA9PSAiRGlldC8gR3ltIEZvb2QiCmRpZXRHeW1Gb29kX2RhdGFfZCA8LSBkc0FkanVzdGVkW2RpZXRHeW1Gb29kX2ZpbHRlcl9kLF0Kc3VwcGxlbWVudF9maWx0ZXJfZCA8LSBkc0FkanVzdGVkJGBBbGxvY2F0ZWQgQ2F0ZWdvcnlgID09ICJTdXBwbGVtZW50IgpzdXBwbGVtZW50X2RhdGFfZCA8LSBkc0FkanVzdGVkW3N1cHBsZW1lbnRfZmlsdGVyX2QsXQpgYGAKCiMjIyMgRGVzY3JpcHRpdmUgU3RhdGlzdGljcyBvZiBNZWFuIERpZmZlcmVuY2UgLSBBbGwgQ2F0ZWdvcmllcwpgYGB7cn0KZHNBZGp1c3RlZCAlPiUKICBzdW1tYXJpc2UoCiAgTWluID0gbWluKGQsIG5hLnJtID0gVFJVRSksCiAgUTEgPSBxdWFudGlsZShkLCBwcm9icyA9IC4yNSwgbmEucm0gPSBUUlVFKSwKICBNZWRpYW4gPSBtZWRpYW4oZCwgbmEucm0gPSBUUlVFKSwKICBRMyA9IHF1YW50aWxlKGQsIHByb2JzID0gLjc1LCBuYS5ybSA9IFRSVUUpLAogIE1heCA9IG1heChkLCBuYS5ybSA9IFRSVUUpLAogIE1lYW4gPSBtZWFuKGQsIG5hLnJtID0gVFJVRSksCiAgU0QgPSBzZChkLCBuYS5ybSA9IFRSVUUpLAogIG4gPSBuKCksCiAgTWlzc2luZyA9IHN1bShpcy5uYShkKSkKICApCmBgYAojIyMjIERlc2NyaXB0aXZlIFN0YXRpc3RpY3Mgb2YgTWVhbiBEaWZmZXJlbmNlIC0gQmVhdXR5IENhdGVnb3J5CmBgYHtyfQpiZWF1dHlfZGF0YV9kICU+JQogIHN1bW1hcmlzZSgKICBNaW4gPSBtaW4oZCwgbmEucm0gPSBUUlVFKSwKICBRMSA9IHF1YW50aWxlKGQsIHByb2JzID0gLjI1LCBuYS5ybSA9IFRSVUUpLAogIE1lZGlhbiA9IG1lZGlhbihkLCBuYS5ybSA9IFRSVUUpLAogIFEzID0gcXVhbnRpbGUoZCwgcHJvYnMgPSAuNzUsIG5hLnJtID0gVFJVRSksCiAgTWF4ID0gbWF4KGQsIG5hLnJtID0gVFJVRSksCiAgTWVhbiA9IG1lYW4oZCwgbmEucm0gPSBUUlVFKSwKICBTRCA9IHNkKGQsIG5hLnJtID0gVFJVRSksCiAgbiA9IG4oKSwKICBNaXNzaW5nID0gc3VtKGlzLm5hKGQpKQogICkKYGBgCiMjIyMgRGVzY3JpcHRpdmUgU3RhdGlzdGljcyBvZiBNZWFuIERpZmZlcmVuY2UgLSBTdWdhcnkgU25hY2sgQ2F0ZWdvcnkgKHBlciAxMDAwIGcpCmBgYHtyfQpzdWdhcnlTbmFja19kYXRhX2QgJT4lCiAgc3VtbWFyaXNlKAogIE1pbiA9IG1pbihkLCBuYS5ybSA9IFRSVUUpLAogIFExID0gcXVhbnRpbGUoZCwgcHJvYnMgPSAuMjUsIG5hLnJtID0gVFJVRSksCiAgTWVkaWFuID0gbWVkaWFuKGQsIG5hLnJtID0gVFJVRSksCiAgUTMgPSBxdWFudGlsZShkLCBwcm9icyA9IC43NSwgbmEucm0gPSBUUlVFKSwKICBNYXggPSBtYXgoZCwgbmEucm0gPSBUUlVFKSwKICBNZWFuID0gbWVhbihkLCBuYS5ybSA9IFRSVUUpLAogIFNEID0gc2QoZCwgbmEucm0gPSBUUlVFKSwKICBuID0gbigpLAogIE1pc3NpbmcgPSBzdW0oaXMubmEoZCkpCiAgKQpgYGAKIyMjIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzIG9mIE1lYW4gRGlmZmVyZW5jZSAtIERpZXQvIEd5bSBGb29kIENhdGVnb3J5IChwZXIgMTAwMCBnKQpgYGB7cn0KZGlldEd5bUZvb2RfZGF0YV9kICU+JQogIHN1bW1hcmlzZSgKICBNaW4gPSBtaW4oZCwgbmEucm0gPSBUUlVFKSwKICBRMSA9IHF1YW50aWxlKGQsIHByb2JzID0gLjI1LCBuYS5ybSA9IFRSVUUpLAogIE1lZGlhbiA9IG1lZGlhbihkLCBuYS5ybSA9IFRSVUUpLAogIFEzID0gcXVhbnRpbGUoZCwgcHJvYnMgPSAuNzUsIG5hLnJtID0gVFJVRSksCiAgTWF4ID0gbWF4KGQsIG5hLnJtID0gVFJVRSksCiAgTWVhbiA9IG1lYW4oZCwgbmEucm0gPSBUUlVFKSwKICBTRCA9IHNkKGQsIG5hLnJtID0gVFJVRSksCiAgbiA9IG4oKSwKICBNaXNzaW5nID0gc3VtKGlzLm5hKGQpKQogICkKYGBgCiMjIyMgRGVzY3JpcHRpdmUgU3RhdGlzdGljcyBvZiBNZWFuIERpZmZlcmVuY2UgLSBTdXBwbGVtZW50IENhdGVnb3J5CmBgYHtyfQpzdXBwbGVtZW50X2RhdGFfZCAlPiUKICBzdW1tYXJpc2UoCiAgTWluID0gbWluKGQsIG5hLnJtID0gVFJVRSksCiAgUTEgPSBxdWFudGlsZShkLCBwcm9icyA9IC4yNSwgbmEucm0gPSBUUlVFKSwKICBNZWRpYW4gPSBtZWRpYW4oZCwgbmEucm0gPSBUUlVFKSwKICBRMyA9IHF1YW50aWxlKGQsIHByb2JzID0gLjc1LCBuYS5ybSA9IFRSVUUpLAogIE1heCA9IG1heChkLCBuYS5ybSA9IFRSVUUpLAogIE1lYW4gPSBtZWFuKGQsIG5hLnJtID0gVFJVRSksCiAgU0QgPSBzZChkLCBuYS5ybSA9IFRSVUUpLAogIG4gPSBuKCksCiAgTWlzc2luZyA9IHN1bShpcy5uYShkKSkKICApCmBgYAoKIyMjIEh5cG90aGVzaXMgVGVzdApXZSB3aWxsIG5vdyBwZXJmb3JtIHBhaXJlZCBzYW1wbGUgdC10ZXN0cy4gIAoKIyMjIyBQYWlyZWQgU2FtcGxlIHQtdGVzdCAtIEFsbCBDYXRlZ29yaWVzCmBgYHtyLCBlY2hvID0gRkFMU0V9CnQudGVzdChkc0FkanVzdGVkJENvbGVzU2FsZUFkanVzdGVkLCBkc0FkanVzdGVkJFdvb2x3b3J0aHNTYWxlQWRqdXN0ZWQsIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpCmBgYAojIyMjIFBhaXJlZCBTYW1wbGUgdC10ZXN0IC0gQmVhdXR5IENhdGVnb3J5CmBgYHtyLCBlY2hvID0gRkFMU0V9CnQudGVzdChiZWF1dHlfZGF0YV9kJENvbGVzU2FsZUFkanVzdGVkLCBiZWF1dHlfZGF0YV9kJFdvb2x3b3J0aHNTYWxlQWRqdXN0ZWQsIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpCmBgYAojIyMjIFBhaXJlZCBTYW1wbGUgdC10ZXN0IC0gU3VnYXJ5IFNuYWNrIENhdGVnb3J5IChwZXIgMTAwMCBnKQpgYGB7ciwgZWNobyA9IEZBTFNFfQp0LnRlc3Qoc3VnYXJ5U25hY2tfZGF0YV9kJENvbGVzU2FsZUFkanVzdGVkLCBzdWdhcnlTbmFja19kYXRhX2QkV29vbHdvcnRoc1NhbGVBZGp1c3RlZCwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikKYGBgCiMjIyMgUGFpcmVkIFNhbXBsZSB0LXRlc3QgLSBEaWV0LyBHeW0gRm9vZCBDYXRlZ29yeSAocGVyIDEwMDAgZykKYGBge3IsIGVjaG8gPSBGQUxTRX0KdC50ZXN0KGRpZXRHeW1Gb29kX2RhdGFfZCRDb2xlc1NhbGVBZGp1c3RlZCwgZGlldEd5bUZvb2RfZGF0YV9kJFdvb2x3b3J0aHNTYWxlQWRqdXN0ZWQsIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpCmBgYAojIyMjIFBhaXJlZCBTYW1wbGUgdC10ZXN0IC0gU3VwcGxlbWVudCBDYXRlZ29yeQpgYGB7ciwgZWNobyA9IEZBTFNFfQp0LnRlc3Qoc3VwcGxlbWVudF9kYXRhX2QkQ29sZXNTYWxlQWRqdXN0ZWQsIHN1cHBsZW1lbnRfZGF0YV9kJFdvb2x3b3J0aHNTYWxlQWRqdXN0ZWQsIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpCmBgYApUaGUgY3JpdGljYWwgdmFsdWUsIHTiiJcgZm9yIHRoZSBwYWlyZWQtc2FtcGxlIHQtdGVzdCAoYXNzdW1pbmcgYSB0d28tdGFpbGVkIHRlc3Qgd2l0aCDOsT0wLjA1KSB3YXMgdGhlbiBjYWxjdWxhdGVkLgoKIyMjIyBDcml0aWNhbCBWYWx1ZSAtIEFsbCBDYXRlZ29yaWVzCmBgYHtyLCBlY2hvID0gRkFMU0V9CnF0KHAgPSAwLjAyNSwgZGYgPSA0ODgpCmBgYAoKIyMjIyBDcml0aWNhbCBWYWx1ZSAtIEJlYXV0eSBDYXRlZ29yeQpgYGB7ciwgZWNobyA9IEZBTFNFfQpxdChwID0gMC4wMjUsIGRmID0gMjA0KQpgYGAKCiMjIyMgQ3JpdGljYWwgVmFsdWUgLSBTdWdhcnkgU25hY2sgQ2F0ZWdvcnkgKHBlciAxMDAwIGcpCmBgYHtyLCBlY2hvID0gRkFMU0V9CnF0KHAgPSAwLjAyNSwgZGYgPSAxMjcpCmBgYAoKIyMjIyBDcml0aWNhbCBWYWx1ZSAtIERpZXQvIEd5bSBGb29kIENhdGVnb3J5IChwZXIgMTAwMCBnKQpgYGB7ciwgZWNobyA9IEZBTFNFfQpxdChwID0gMC4wMjUsIGRmID0gNjcpCmBgYAoKIyMjIyBDcml0aWNhbCBWYWx1ZSAtIFN1cHBsZW1lbnQgQ2F0ZWdvcnkKYGBge3IsIGVjaG8gPSBGQUxTRX0KcXQocCA9IDAuMDI1LCBkZiA9IDg3KQpgYGAKCiMjIyBIeXBvdGhlc2lzIFRlc3RpbmcgUmVzdWx0cyAmIEludGVycHJldGF0aW9uCgojIyMjIEFsbCBDYXRlZ29yaWVzClRoZSB0KiB2YWx1ZXMgYXJlIMKxIDEuOTYuIEFzIHQgPSA0LjMgaXMgbW9yZSBleHRyZW1lIHRoYW4gKyAxLjk2LCBIMCBzaG91bGQgYmUgcmVqZWN0ZWQgKGFkZGl0aW9uYWxseSB0aGUgOTUlIENJIG9mIHRoZSBtZWFuIGRpZmZlcmVuY2UgaXMgZm91bmQgdG8gYmUgWzAuOTEgMi40Nl0sIHdoaWNoIGRvZXMgbm90IGNvbnRhaW4gY2FwdHVyZSBIMCkuIFRoZXJlIHdhcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgbWVhbiBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIFdvb2x3b3J0aHMgU2FsZSBhbmQgQ29sZXMgU2FsZSBwcmljZXMgYWNjcm9zcyBhbGwgY2F0ZWdvcmllcy4KCiMjIyMgQmVhdXR5IENhdGVnb3J5ClRoZSB0KiB2YWx1ZXMgYXJlIMKxIDEuOTcuIEFzIHQgPSAwLjYyLCB0IGlzIGxlc3MgZXh0cmVtZSB0aGFuIHRoYW4gKzEuOTcsIEgwIGNhbm5vdCBiZSByZWplY3RlZCBvbiBjcml0aWNhbCB2YWx1ZS4gVGhlIDk1JSBDSSBvZiB0aGUgbWVhbiBkaWZmZXJlbmNlIGlzIGZvdW5kIHRvIGJlIFstMC4zNiAwLjY4XSwgSDAgY2Fubm90IGJlIHJlamVjdGVkIG9uIDk1JSBDSS4gQXMgcCA+IDAuMDUsIHdlIGZhaWwgdG8gcmVqZWN0IEgwLiBUaGVyZSB3YXMgbm90IGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBtZWFuIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgV29vbHdvcnRocyBTYWxlIGFuZCBDb2xlcyBTYWxlIHByaWNlcyBpbiB0aGUgYmVhdXR5IGNhdGVnb3J5LgoKIyMjIyBTdWdhcnkgU25hY2sgQ2F0ZWdvcnkgKHBlciAxMDAwIGcpClRoZSB0KiB2YWx1ZXMgYXJlIMKxIDEuOTguIEFzIHQgPSAzLjI4IGlzIG1vcmUgZXh0cmVtZSB0aGFuICsgMS45OCwgSDAgc2hvdWxkIGJlIHJlamVjdGVkIChhZGRpdGlvbmFsbHkgdGhlIDk1JSBDSSBvZiB0aGUgbWVhbiBkaWZmZXJlbmNlIGlzIGZvdW5kIHRvIGJlIFsxLjIzIDQuOTNdLCB3aGljaCBkb2VzIG5vdCBjb250YWluIGNhcHR1cmUgSDApLiBUaGVyZSB3YXMgYSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IG1lYW4gZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBXb29sd29ydGhzIFNhbGUgYW5kIENvbGVzIFNhbGUgcHJpY2VzIGluIHRoZSBTdWdhcnkgU25hY2sgY2F0ZWdvcnkgKHByaWNlIHBlciAxMDAwIGcpLgoKIyMjIyBEaWV0LyBHeW0gRm9vZCBDYXRlZ29yeSAocGVyIDEwMDAgZykKVGhlIHQqIHZhbHVlcyBhcmUgwrEgMi4wLiBBcyB0ID0gMS4xOSwgdCBpcyBsZXNzIGV4dHJlbWUgdGhhbiB0aGFuICsyLjAsIEgwIGNhbm5vdCBiZSByZWplY3RlZCBvbiBjcml0aWNhbCB2YWx1ZS4gVGhlIDk1JSBDSSBvZiB0aGUgbWVhbiBkaWZmZXJlbmNlIGlzIGZvdW5kIHRvIGJlIFstMS40NyA1LjgyXSwgSDAgY2Fubm90IGJlIHJlamVjdGVkIG9uIDk1JSBDSS4gQXMgcCA+IDAuMDUsIHdlIGZhaWwgdG8gcmVqZWN0IEgwLiBUaGVyZSB3YXMgbm90IGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBtZWFuIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgV29vbHdvcnRocyBTYWxlIGFuZCBDb2xlcyBTYWxlIHByaWNlcyBpbiB0aGUgZGlldC8gZ3ltIGZvb2QgY2F0ZWdvcnkuCgojIyMjIFN1cHBsZW1lbnQgQ2F0ZWdvcnkKVGhlIHQqIHZhbHVlcyBhcmUgwrEgMS45OS4gQXMgdCA9IDQuMTggaXMgbW9yZSBleHRyZW1lIHRoYW4gKyAxLjk5LCBIMCBzaG91bGQgYmUgcmVqZWN0ZWQgKGFkZGl0aW9uYWxseSB0aGUgOTUlIENJIG9mIHRoZSBtZWFuIGRpZmZlcmVuY2UgaXMgZm91bmQgdG8gYmUgWzEuNDggNC4xOF0sIHdoaWNoIGRvZXMgbm90IGNvbnRhaW4gY2FwdHVyZSBIMCkuIFRoZXJlIHdhcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgbWVhbiBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIFdvb2x3b3J0aHMgU2FsZSBhbmQgQ29sZXMgU2FsZSBwcmljZXMgaW4gdGhlIHN1cHBsZW1lbnQgY2F0ZWdvcnkuCgojIyMgTWVhbiBEaWZmZXJlbmNlIFNjYXR0ZXIgUGxvdHMKCiMjIyMgQWxsIENhdGVnb3JpZXMKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmdyYW5vdmEuZHMoCiAgZGF0YS5mcmFtZShkc0FkanVzdGVkJFdvb2x3b3J0aHNTYWxlQWRqdXN0ZWQsIGRzQWRqdXN0ZWQkQ29sZXNTYWxlQWRqdXN0ZWQpLAogIHhsYWIgPSAiV29vbHdvcnRocyBTYWxlIEFkanVzdGVkIiwKICB5bGFiID0gIkNvbGVzIFNhbGUgQWRqdXN0ZWQiCiAgKQpgYGAKCiMjIyMgQmVhdXR5IENhdGVnb3J5CgpgYGB7ciwgZWNobyA9IEZBTFNFfQpncmFub3ZhLmRzKAogIGRhdGEuZnJhbWUoYmVhdXR5X2RhdGFfZCRXb29sd29ydGhzU2FsZUFkanVzdGVkLCBiZWF1dHlfZGF0YV9kJENvbGVzU2FsZUFkanVzdGVkKSwKICB4bGFiID0gIkJlYXV0eSAtIFdvb2x3b3J0aHMgU2FsZSBBZGp1c3RlZCIsCiAgeWxhYiA9ICJCZWF1dHkgLSBDb2xlcyBTYWxlIEFkanVzdGVkIgogICkKYGBgCgojIyMjIFN1Z2FyeSBTbmFjayBDYXRlZ29yeSAocGVyIDEwMDAgZykKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmdyYW5vdmEuZHMoCiAgZGF0YS5mcmFtZShzdWdhcnlTbmFja19kYXRhX2QkV29vbHdvcnRoc1NhbGVBZGp1c3RlZCwgc3VnYXJ5U25hY2tfZGF0YV9kJENvbGVzU2FsZUFkanVzdGVkKSwKICB4bGFiID0gIlN1Z2FyeSBTbmFjayAoMTAwMCBnKSAtIFdvb2x3b3J0aHMgU2FsZSBBZGp1c3RlZCIsCiAgeWxhYiA9ICJTdWdhcnkgU25hY2sgKDEwMDAgZykgLSBDb2xlcyBTYWxlIEFkanVzdGVkIgogICkKYGBgCgojIyMjIERpZXQvIEd5bSBGb29kIENhdGVnb3J5IChwZXIgMTAwMCBnKQoKYGBge3IsIGVjaG8gPSBGQUxTRX0KZ3Jhbm92YS5kcygKICBkYXRhLmZyYW1lKGRpZXRHeW1Gb29kX2RhdGFfZCRXb29sd29ydGhzU2FsZUFkanVzdGVkLCBkaWV0R3ltRm9vZF9kYXRhX2QkQ29sZXNTYWxlQWRqdXN0ZWQpLAogIHhsYWIgPSAiRGlldC8gR3ltIEZvb2QgKDEwMDAgZykgLSBXb29sd29ydGhzIFNhbGUgQWRqdXN0ZWQiLAogIHlsYWIgPSAiRGlldC8gR3ltIEZvb2QgKDEwMDAgZykgLSBDb2xlcyBTYWxlIEFkanVzdGVkIgogICkKYGBgCgojIyMjIFN1cHBsZW1lbnQgQ2F0ZWdvcnkKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmdyYW5vdmEuZHMoCiAgZGF0YS5mcmFtZShzdXBwbGVtZW50X2RhdGFfZCRXb29sd29ydGhzU2FsZUFkanVzdGVkLCBzdXBwbGVtZW50X2RhdGFfZCRDb2xlc1NhbGVBZGp1c3RlZCksCiAgeGxhYiA9ICJTdXBwbGVtZW50IC0gV29vbHdvcnRocyBTYWxlIEFkanVzdGVkIiwKICB5bGFiID0gIlN1cHBsZW1lbnQgLSBDb2xlcyBTYWxlIEFkanVzdGVkIgogICkKYGBgCgojIyMgRGlzY3Vzc2lvbiAKClRoZSBmb2xsb3dpbmcgd2FzIGRldGVybWluZWQgb3ZlciB0aGUgZHVyYXRpb24gb2YgdGhlIGludmVzdGlnYXRpb24sCgoqIFRoZXJlIHdhcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgbWVhbiBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIFdvb2x3b3J0aHMgU2FsZSBhbmQgQ29sZXMgU2FsZSBwcmljZXMgYWNjcm9zcyBhbGwgY2F0ZWdvcmllcy4gVGhlIGBncmFub3ZvLmRzKClgIGZ1bmN0aW9uIHN1bW1hcnkgc3RhdHMgc2hvdyBXVyBTYWxlIHRvIGhhdmUgYSBtZWFuIHZhbHVlIG9mIEFVRCAyMC43Niwgd2hpbGUgQ29sZXMgU2FsZSBoYXMgYSBtZWFuIHZhbHVlIG9mIEFVRCAyMi40NC4gV29vbHdvcnRocyBTYWxlIGlzIGNoZWFwZXIgb3ZlcmFsbCAob3ZlciB0aGUgZm91ciBjYXRlZ29yaWVzIG9mIGdvb2RzKS4KCiogVGhlcmUgd2FzIG5vdCBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgbWVhbiBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIFdvb2x3b3J0aHMgU2FsZSBhbmQgQ29sZXMgU2FsZSBwcmljZXMgaW4gdGhlIGJlYXV0eSBjYXRlZ29yeS4gVGhlIGBncmFub3ZvLmRzKClgIGZ1bmN0aW9uIHN1bW1hcnkgc3RhdHMgc2hvdyBXVyBTYWxlIHRvIGhhdmUgYSBtZWFuIHZhbHVlIG9mIEFVRCAxMi4yOSwgd2hpbGUgQ29sZXMgU2FsZSBoYXMgYSBtZWFuIHZhbHVlIG9mIEFVRCAxMi40Ni4gV2hpbGUgdGhlIG1lYW4gb2YgV29vbHdvcnRocyBTYWxlIGlzIGxvd2VyLCB0aGlzIGlzIHN0YXRpc3RpY2FsbHkgaW5zaWduaWZpY2FudCBvdmVyIHRoZSBiZWF1dHkgZ29vZHMuCgoqIFRoZXJlIHdhcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgbWVhbiBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIFdvb2x3b3J0aHMgU2FsZSBhbmQgQ29sZXMgU2FsZSBwcmljZXMgaW4gdGhlIFN1Z2FyeSBTbmFjayBjYXRlZ29yeSAocHJpY2UgcGVyIDEwMDAgZykuIFRoZSBgZ3Jhbm92by5kcygpYCBmdW5jdGlvbiBzdW1tYXJ5IHN0YXRzIHNob3cgV1cgU2FsZSB0byBoYXZlIGEgbWVhbiB2YWx1ZSBvZiBBVUQgMjAuNDMsIHdoaWxlIENvbGVzIFNhbGUgaGFzIGEgbWVhbiB2YWx1ZSBvZiBBVUQgMjMuNTAuIFdvb2x3b3J0aHMgU2FsZSBpcyBjaGVhcGVyIG92ZXIgdGhlIHN1Z2FyeSBzbmFjayBjYXRlZ29yeSBwZXIgMTAwMCBnLgoKKiBUaGVyZSB3YXMgbm90IGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBtZWFuIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgV29vbHdvcnRocyBTYWxlIGFuZCBDb2xlcyBTYWxlIHByaWNlcyBpbiB0aGUgZGlldC8gZ3ltIGZvb2QgY2F0ZWdvcnkgKHByaWNlIHBlciAxMDAwIGcpLiBUaGUgYGdyYW5vdm8uZHMoKWAgZnVuY3Rpb24gc3VtbWFyeSBzdGF0cyBzaG93IFdXIFNhbGUgdG8gaGF2ZSBhIG1lYW4gdmFsdWUgb2YgQVVEIDUxLjkwLCB3aGlsZSBDb2xlcyBTYWxlIGhhcyBhIG1lYW4gdmFsdWUgb2YgQVVEIDU0LjA3LiBXaGlsZSB0aGUgbWVhbiBvZiBXb29sd29ydGhzIFNhbGUgaXMgbG93ZXIsIHRoaXMgaXMgc3RhdGlzdGljYWxseSBpbnNpZ25pZmljYW50IG92ZXIgdGhlIGRpZXQvIGd5bSBmb29kIGdvb2RzLgoKKiBUaGVyZSB3YXMgYSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IG1lYW4gZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBXb29sd29ydGhzIFNhbGUgYW5kIENvbGVzIFNhbGUgcHJpY2VzIGluIHRoZSBzdXBwbGVtZW50IGNhdGVnb3J5LiBUaGUgYGdyYW5vdm8uZHMoKWAgZnVuY3Rpb24gc3VtbWFyeSBzdGF0cyBzaG93IFdXIFNhbGUgdG8gaGF2ZSBhIG1lYW4gdmFsdWUgb2YgQVVEIDE2Ljg5LCB3aGlsZSBDb2xlcyBTYWxlIGhhcyBhIG1lYW4gdmFsdWUgb2YgQVVEIDE5LjcyLiBXb29sd29ydGhzIFNhbGUgaXMgY2hlYXBlciBvdmVyIHRoZSBzdXBwbG1lbnQgY2F0ZWdvcnkuCgpUaGUgc3RyZW5ndGhzIG9mIHRoZSBpbnZlc3RpZ2F0aW9uIGluY2x1ZGVkIGhpZ2ggc2FtcGxlIHNpemUgKG92ZXJhbGwgYW5kIGluIHN1Yi1jYXRlZ29yaWVzKSwgY29udHJvbHMgb2Ygc2FtcGxpbmcgaW4gb25lIHBvc3Rjb2RlIG92ZXIgYSBwZXJpb2Qgb2Ygb25seSAxMSBkYXlzIGFuZCBjaG9vc2luZyBtYW51ZmFjdHVyZWQgaXRlbXMgdGhhdCB3ZXJlIGlkZW50aWNhbC4gTGltaXRhdGlvbnMgaW5jbHVkZSB3b3JraW5nIHdpdGggdGhlIHNhbGUgZGF0YSAoYXMgZnVsbCBwcmljZSBpdGVtcyBub3Qgb24gc2FsZSB3ZXJlIGluY2x1ZGVkIGhlcmUpLiBGdWxsIHByaWNlcyBvdmVyYWxsIG1heSBiZSBtb3JlIHN0YWJsZSB3aXRoIHRpbWUsIGFuZCB0aHVzIGEgYmV0dGVyIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwcmljZSBvZiB0aGUgc3VwZXJtYXJrZXQgb3ZlcmFsbC4gRm9yIGZ1dHVyZSBzdHVkaWVzLCBzYW1wbGluZyBhdCB0aW1lIGludGVydmFscyAodCA9IDEgbW9udGgsIG92ZXIgMjQgbW9udGhzKSBjb3VsZCBiZSBwZXJmb3JtZWQgYXQgZnVsbCBwcmljZSBpbiBvbmUgcG9zdGNvZGUuCgojIyMgQ29uY2x1c2lvbgpEYXRhIG9mIGFsbW9zdCA1MDAgcG9pbnRzIHdhcyBjb2xsZWN0ZWQgZnJvbSBDb2xlcywgQ29sZXMgU2FsZSwgV29vbHdvcnRocyBhbmQgV29vbHdvcnRocyBTYWxlIChwb3N0Y29kZSAzMDU0LCBDYXJsdG9uIE5vcnRoLCBWaWN0b3JpYSwgQXVzdHJhbGlhLCA3IFNlcCAyMDE3IHRpbGwgMTggU2VwIDIwMTcpIGFjY3Jvc3MgdGhlIGNhdGVnb3JpZXMgQkFLSU5HLCBEQUlSWSAmIEVHR1MgRElFVEFSWSwgSEVBTFRIICYgTElGRVNUWUxFLCBEUklOS1MsIEZST1pFTiBGT09ELCBIRUFMVEggJiBCRUFVVFksIFBBQ0tBR0VEICYgUkVBRFkgTUVBTFMgYW5kIFBBTlRSWSAoZ2VuZXJhbGl6ZWQgYXMgQmVhdXR5LCBEaWV0LyBHeW0gRm9vZCwgU3VnYXJ5IFNuYWNrIGFuZCBTdXBwbGVtZW50KS4gSXQgd2FzIGRldGVybWluZWQgdGhhdCBXb29sd29ydGhzIFNhbGUgaGFkIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgbG93ZXIgcHJpY2VzIG92ZXJhbGwsIGluIHRoZSBzdWdhcnkgc25hY2sgY2F0ZWdvcnkgYW5kIGluIHRoZSBzdXBwbGVtZW50IGNhdGVnb3J5LgoKW14xXTogaHR0cDovL3d3dy53ZXNmYXJtZXJzLmNvbS5hdS91dGlsL25ld3MtbWVkaWEvYXJ0aWNsZS8yMDE3LzA2LzIyL2NvbGVzLWNyZWF0ZXMtMTE1LWpvYnMtYXQtaXRzLW1pbGVzdG9uZS04MDB0aC1zdXBlcm1hcmtldApbXjJdOiBodHRwOi8vd3d3LnNtaC5jb20uYXUvYnVzaW5lc3Mvc3VwZXJtYXJrZXQtZHVvcG9seS1ibGFtZWQtZm9yLXNvYXJpbmctZm9vZC1wcmljZXMtMjAwOTExMDgtaTN0bi5odG1sClteM106IGh0dHA6Ly93d3cuc21oLmNvbS5hdS9idXNpbmVzcy9yZXRhaWwvY29sZXMtZGVlcGVucy1wcmljZS13YXItYWZ0ZXItc2xpY2luZy1icmVhZC1wcmljZXMtMjAxNzA3MTItZ3hhMzNwLmh0bWwKW140XTogaHR0cHM6Ly93d3cuZnJ1Z2wuY29tLmF1LyA=