Required packages

library(dplyr)
library(readr)
library(tidyr)
library(ggplot2)

Executive Summary

Two datasets “Imports of Goods” & “Exports of Goods” were taken with country wise Gross values for Imported and Exported goods for different years and different SNA series methods.

We have taken a subset of country column to filter out 7 countries -“United Kingdom”, “United States”, “Japan”, “Germany”, “Australia”, “Canada” and “France” and year column to filter records from 1970 to 2010 & used Join operation to merge these two datasets to combine them in a single dataset. Also, Column names were changed to more meaningful names after joining them.

For better Understanding of data, “Country”, “SNA_Series”, “SNA_System” & “Currency” are converted into unordered Factor and “Year” is converted into ordered Factor.

As merged dataset satisfies the tidy data condition, there was no need to perform any operation to tidy the dataset. We have merged two columns “SNA_Series”" & “SNA_Numbers” and mutated one column named “Terms_Of_Trade”.

We have scanned the data to identify potential NAs/missing values and Outliers in the dataset. There were no missing values or NAs found in the combined dataset. Possible outliers are identified but given the context of the Numeric Column on which outliers are identified, there is no significance of considering them as outliers. Detailed Explanation is given in the the relevant “Scan” section of this document.

Since the dataset contains Gross values for different countries in their own currency values and different countries having different currency values, we have transformed the variables “Gross_Imports” & “Gross_Exports” by scaling the values, to express them in terms of Standard Deviations, giving resulting values on a same scale so that they can be compared with other values.

Data

Data for this Data Preprocessing study is acquired from “www.data.un.org”, which is mainly a product of United Nations Statistics Division which brings UN Stats Databases in reach of users through internet. Initially we are referring two datasets, both falling under same category and sub-category, which is “National Accounts Official Country Data”/“table 1.1 Gross domestic product by expenditures at current prices”. Datasets are “Imports of Goods” & “Exports of Goods”. Data descriptions for both of them are follows.

  1. Imports of Goods

    Source - http://data.un.org/Data.aspx?d=SNA&f=group_code%3a101%3bitem_code%3a21

  2. Exports of Goods

    Source - http://data.un.org/Data.aspx?d=SNA&f=group_code%3a101%3bitem_code%3a18

Variables - a. Country or Area - Name of territory being observed b. SNA93 Table Code - category table reference number c. Sub Group - Sub Category reference number d. Item - Item that current database represents in the provided category/sub-category e. SNA93 Item Code - “System of National Accounts - 1993” - item number for particular dataset f. Year - Year of observation g. Series - SNA 93 Observation Series h. Currency - Currency for the mentioned value for Import / Export i. Fiscal Year Type - Fiscal Year specification for the observation j. value - Reported gross value of Import/Export for country or Area for given year

However, For this task, we will only consider following columns.

i.   Country or Area
ii.  Year
iii. Series
iv.  Currency
v.   SNA System
vi.  Value
  

Both of the datasets, contain identical variable sets. First dataset contains the gross value for Imported Goods and second contains gross value for Exported Goods, for multiple years measured by multiple SNA Series methods. We will consider a subset of countries to carry out the preprocessing task, which includes “Japan”, “United Kingdom”, “Germany”, “United States”, “France”, “Canada” & “Australia”. We will consider data from years 1970 to 2010. So for each country we will have Import & Export Records for 41 years.

We will merge the datasets with an inner join on columns “Country or Area”, “Year”, “Series”, “SNA System”, “Currency”. This will give us a combined dataset, records of which, describes the Gross Import & Gross Export Values for a country, for a year measured in the same SNA Series.

We will rename the columns to more readable names.

It is important to note that for a given year, Import & Export values can be measured in multiple SNA Systems. For this task we will use only the highest SNA System(Series) in which data is recorded. We will do that by taking a slice which has maximum SNA System year out of all 3 SNA Systems that are used to measure Goods Trading, i.e. “1968”, “1993”, “2008”.

cat("Subsetting Import of Goods Dataset before merging (Below)")
Subsetting Import of Goods Dataset before merging (Below)
ImportGoods <- ImportGoods[0:9506,]
ImportGoods <- ImportGoods %>% select(`Country or Area`,Year,Series,Currency,`SNA System`,Value)
ImportGoods <- ImportGoods %>% subset(ImportGoods$`Country or Area` %in% c("United Kingdom","United States","Japan","Germany","Australia","Canada","France") & ImportGoods$Year %in% c(seq(1970,2010)))
cat("Subsetting Export of Goods Dataset before merging (Below)")
Subsetting Export of Goods Dataset before merging (Below)
ExportGoods <- ExportGoods[0:9506,]
ExportGoods <- ExportGoods %>% select(`Country or Area`,Year,Series,Currency,`SNA System`,Value)
ExportGoods <- ExportGoods %>% subset(ExportGoods$`Country or Area` %in% c("United Kingdom","United States","Japan","Germany","Australia","Canada","France") & ExportGoods$Year %in% c(seq(1970,2010)))
cat("Merging datasets (Below)")
Merging datasets (Below)
TradeStatistics <- ImportGoods %>% inner_join(ExportGoods,by = c("Country or Area","Year","Series","SNA System","Currency"))
cat("Renaming Columns (Below)")
Renaming Columns (Below)
colnames(TradeStatistics) <- c("Country","Year","SNA_Series","Currency","SNA_System","Gross_Imports","Gross_Exports")
head(ImportGoods)
head(ExportGoods)
head(TradeStatistics)
TradeStatistics <- TradeStatistics %>% group_by(Country,Year) %>% slice(which.max(SNA_System))
TradeStatistics$Country %>%  table()
.
     Australia         Canada         France        Germany          Japan United Kingdom  United States 
            41             41             41             41             41             41             41 

Understand

Following is the Summary of variable types. 1. Country - Character 2. Year - int 3. SNA_Series - int 4. Currency - Character 5. SNA_System - int 6. Gross_Imports - double 7. Gross_Exports - double

TradeStatistics$Country <- TradeStatistics$Country %>% as.factor()
attributes(TradeStatistics$Country)
$levels
[1] "Australia"      "Canada"         "France"         "Germany"        "Japan"          "United Kingdom"
[7] "United States" 

$class
[1] "factor"
TradeStatistics$SNA_Series <- TradeStatistics$SNA_Series %>% as.factor()
attributes(TradeStatistics$SNA_Series)
$levels
[1] "20"   "200"  "300"  "400"  "1000"

$class
[1] "factor"
TradeStatistics$SNA_System <- TradeStatistics$SNA_System %>% as.factor()
attributes(TradeStatistics$SNA_System)
$levels
[1] "1968" "1993" "2008"

$class
[1] "factor"
TradeStatistics$Year <- TradeStatistics$Year %>% factor(levels = c(seq(1970,2010)),labels = c(seq(1970,2010)), ordered = TRUE) 
attributes(TradeStatistics$Year)
$levels
 [1] "1970" "1971" "1972" "1973" "1974" "1975" "1976" "1977" "1978" "1979" "1980" "1981" "1982" "1983" "1984" "1985"
[17] "1986" "1987" "1988" "1989" "1990" "1991" "1992" "1993" "1994" "1995" "1996" "1997" "1998" "1999" "2000" "2001"
[33] "2002" "2003" "2004" "2005" "2006" "2007" "2008" "2009" "2010"

$class
[1] "ordered" "factor" 
str(TradeStatistics$Year)
 Ord.factor w/ 41 levels "1970"<"1971"<..: 1 2 3 4 5 6 7 8 9 10 ...
TradeStatistics$Currency <- TradeStatistics$Currency %>% factor(levels = c("1999 FRF euro / euro","1999 DEM euro / euro","Euro","Australian dollar","Canadian dollar","yen","pound sterling","US dollar"),labels = c("EUR","EUR","EUR","AUD","CAD","JPY","GBP","USD"),ordered = FALSE) 
duplicated levels in factors are deprecated
attributes(TradeStatistics$Currency)
$levels
[1] "EUR" "EUR" "EUR" "AUD" "CAD" "JPY" "GBP" "USD"

$class
[1] "factor"
TradeStatistics$Gross_Imports %>%  class()
[1] "numeric"
TradeStatistics$Gross_Exports %>%  class()
[1] "numeric"

Tidy & Manipulate Data I

Following characteristics are observable in the current data.

That suggests that data is readily in a tidy format.

However, there is a possibility to merge two columns - SNA_Series & SNA_Numbers,as they have contextual binding with each other, and also, we don’t need these values separately in further preprocessing tasks. So these two columns are merged together with unite() operation. The resulting column will contain both values joined with a “/”. Altered dataset can be seen in the table-output below.

TradeStatistics <-  TradeStatistics %>% unite(col = "SNA-Series/System",SNA_Series , SNA_System,sep = "/")
TradeStatistics$`SNA-Series/System` <- as.factor(TradeStatistics$`SNA-Series/System`)
TradeStatistics %>% head()

Tidy & Manipulate Data II

We will create a new variable called “Terms_Of_Trade”. Terms of trade is a trading term, which is essentially a ratio of Gross Exports to Gross Imports multiplied by 100. Terms of trade, in fact, describes the amount of export good a country can purchase per unit of import good. So if the Terms of Trade is more than 100%, that indicates a country has an healthy economy with good trade. But that is a blunt and abstract statement to indicate the meaning of ToT.

We will add the new column named “Terms_Of_Trade” in our dataset by using a mutate() operation.

TradeStatistics <- TradeStatistics %>% mutate(Terms_Of_Trade = (Gross_Exports * 100)/ Gross_Imports)
TradeStatistics %>% head()

Scan I

In this section, We have checked Gross_Imports, Gross_Exports & newly added Terms_Of_Trade variables for null values, Infinite values and NaN values.

As per the results, there are no null/inconsistent values in the numeric variables of dataset.

na_Count_Gross_Imports <- sum(is.na(TradeStatistics$Gross_Imports) | is.infinite(TradeStatistics$Gross_Imports) | is.nan(TradeStatistics$Gross_Imports))
na_Count_Gross_Exports <- sum(is.na(TradeStatistics$Gross_Exports) | is.infinite(TradeStatistics$Gross_Exports) | is.nan(TradeStatistics$Gross_Exports))
na_Count_TOT <- sum(is.na(TradeStatistics$Terms_Of_Trade) | is.infinite(TradeStatistics$Terms_Of_Trade) | is.nan(TradeStatistics$Terms_Of_Trade))
cat(" Number of Nulls/inconsistencies in Gross_Imports -",na_Count_Gross_Imports,"\n","Number of Nulls/inconsistencies in Gross_Imports -",na_Count_Gross_Exports,"\n","Number of Nulls/inconsistencies in Terms_Of_Trade -",na_Count_TOT,"\n")
 Number of Nulls/inconsistencies in Gross_Imports - 0 
 Number of Nulls/inconsistencies in Gross_Imports - 0 
 Number of Nulls/inconsistencies in Terms_Of_Trade - 0 

Scan II

We will scan all 3 numeric columns for potential outliers in them using box-plots.

It is important to note that we will scan for outliers, considering each country, for variables Gross_Imports & Gross_Exports. We do so to accommodate the effect of different currencies on the value of Imports & Exports, we will need look for outliers in the data of particular groups.

For example, we cannot directly compare, United States’ import value in 1970, which is “40900000000” USD, to Japan’s import value in 1970, which is “5484100000000” JPY. Simply because a USD and JPY cannot be directly compared.

That’s why we can look for outliers in particular country’s data, where all observations are made in same currency. Outliers in table 1 & 2 represent, Significantly high or low, Import or Export of Goods by a country in a particular year than it did in other years.

However, for Terms of Trade, we can consider entire variable to scan for outliers, simply because of the fact that ToT is not dependent on any currency, and can be used to compare absolute trade performances of countries.

For example, if United States has a ToT of 110 for any given year & Japan has ToT of 140 for the same or different year, we can say that Japan performed better than united states particularly in “Terms of Trade”.

Outliers in table 3 represent, Significantly high or low performance of a country in “Terms of Trade” as compared to all other countries for entire observation period.

These outliers, are not due to any error in measurement, but are extreme occurrences of events in the observation period so we do not need to impute them, as they possess actual statistical values.

NOTE > Box-plots for Gross_Imports & Gross_Exports may seem unrealistic or faulty at first! but the irregular shape for countries other than “Japan”, is because of the fact that all the values are represented in different currencies.Value of Japanese being smaller than rest of the countries, the magnitude of numbers representing Import & Export is large. > We need to scale the variables Gross_Imports & Gross_Exports, to suppress the effect of different currencies. Which is done in the next section

par(ps = 12, cex = 2, cex.main = 1)
imports_boxplot <- boxplot(Gross_Imports ~ as.factor(x = unite(col = "Country-Currency",Country , Currency,sep = " - ",data = TradeStatistics)$`Country-Currency`),
                          data = TradeStatistics,main="Gross Import value for countries (Different Currencies)",
                          xlab="Country - Currency",
                          ylab="Import Value")

exports_boxplot <- boxplot(Gross_Exports ~ as.factor(x = unite(col = "Country-Currency",Country , Currency,sep = " - ",data = TradeStatistics)$`Country-Currency`),
                      data = TradeStatistics,
                      main="Gross Export value for countries (Different Currencies)",
                      xlab="Country - Currency",
                      ylab="Export Value")

 
  tot_boxplot <- boxplot(TradeStatistics$Terms_Of_Trade,
                      main="Term of Trade for countries ",
                      ylab="Term o Trade")

  
  
Import_Outliers <- TradeStatistics %>% subset(Gross_Imports %in% imports_boxplot$out)
Export_Outliers <- TradeStatistics %>% subset(Gross_Exports %in% exports_boxplot$out)
Tot_Outliers <- TradeStatistics %>% subset((Terms_Of_Trade) %in% tot_boxplot$out)
print(Import_Outliers)
print(Export_Outliers)
print(Tot_Outliers)

Transform

The difference in values of different currencies creates a major problem while trying to understand nature of variables Gross_Imports & Gross_Exports. As can be seen in the plots on the left hand side in the grid below. Japan’s currency JPY has a relatively low value compared to others. So the number representing, even a small trade, in JPY will be a significantly large number. (As on 21 October, 2018, 1 JPY = 0.0089 USD).

This creates a problem when we try to interpret the data which has values expressed in multiple currencies. Smaller currencies tend to overshadow the larger currencies.

To remedy the effects of different currencies, we will scale the values, and express them in terms of Standard Deviations.

Here also, we will group the data by country, and apply scaling to each of the group independently. If we apply the scaling on entire variables, the output will be the same, smaller JPY overshadowing all the other larger currencies as can be seen in left side plots.

Grouped scaling will expose true nature of the values, by abstracting the effect of currency on the data.

As can be observed from the plots on the right hand side, data is more interpretable, as the values are scaled and now expressed in terms of Standard deviations of that group.

By comparing both graphs we can see that Japan’s values in scatterplot & shapes in boxplots have not changed. It is because scaling has not changed the values in its absolution, but only represented them in a more suitable and narrow scale, without affecting the true nature of the data.

cat("Plot A1")
Plot A1
scatter_plot_before_scale <- 
                            ggplot(TradeStatistics, aes(x=Gross_Imports, y=Gross_Exports, color=Country,shape = Country))+
                             scale_shape_manual(values=1:nlevels(TradeStatistics$Country)) +
                             geom_point(size=8) + 
                             theme_grey(base_size = 25) +
                             labs(x = "Gross Imports",y = "Gross Exports",title = "Scatter plot - Gross Imports vs. Gross Exports (Before Scaling)",tag = "A1")
cat("Plot A2")
Plot A2
boxplot_Import_before_scale <- ggplot(data = TradeStatistics,aes(x = Country, y = Gross_Imports, color = Country)) +
                                geom_boxplot(size = 1,outlier.color = "black",outlier.size = 3) +
                                theme(axis.text.x = element_text(angle = 45, hjust = 2,size = 25)) +
                                theme_grey(base_size = 25) +
                                labs(x = "Country",y = "Gross Imports",title = "Box plot - Gross Imports By Country (Before Scaling)",tag = "A2") 
cat("Plot A3")
Plot A3
boxplot_Export_before_scale <- ggplot(data = TradeStatistics,aes(x = Country, y = Gross_Exports, color = Country)) +
                                geom_boxplot(size = 1,outlier.color = "black",outlier.size = 3) +
                                theme(axis.text.x = element_text(angle = 45, hjust = 1,size = 25)) +
                                theme_grey(base_size = 25) +
                                labs(x = "Country",y = "Gross Exports",title = "Box plot - Gross Exports By Country (Before Scaling)",tag = "A3") 
cat("Scaling Gross_Imports")
Scaling Gross_Imports
TradeStatistics <- TradeStatistics %>%  group_by(Country) %>% mutate(Gross_Imports_Scaled = (Gross_Imports /(sd(Gross_Imports))))
cat("Scaling Gross_Exports")
Scaling Gross_Exports
TradeStatistics <- TradeStatistics %>%  group_by(Country) %>% mutate(Gross_Exports_Scaled = (Gross_Exports /(sd(Gross_Exports))))
cat("Plot B1")
Plot B1
scatter_plot_after_scale <- ggplot(TradeStatistics, aes(x=Gross_Imports_Scaled, y=Gross_Exports_Scaled, color=Country,shape = Country)) +
                             scale_shape_manual(values=1:nlevels(TradeStatistics$Country)) +
                             geom_point(size = 8) +
                             theme_grey(base_size = 25) +
                             labs(x = "Gross Imports",y = "Gross Exports",title = "Scatter plot - Gross Imports vs. Gross Exports (After Scaling)",tag = "B1") 
cat("Plot B2")
Plot B2
boxplot_Import_after_scale <- ggplot(data = TradeStatistics,aes(x = Country, y = Gross_Imports_Scaled, color = Country)) +
                               geom_boxplot(size = 1,outlier.color = "black",outlier.size = 3) +
                               theme(axis.text.x = element_text(angle = 45, hjust = 1,size = 25)) +
                               theme_grey(base_size = 25) +
                               labs(x = "Country",y = "Gross Imports",title = "Box plot - Gross Imports By Country (After Scaling)",tag = "B2") 
cat("Plot B3")
Plot B3
boxplot_Export_after_scale <- ggplot(data = TradeStatistics,aes(x = Country, y = Gross_Exports_Scaled, color = Country)) +
                               geom_boxplot(size = 1,outlier.color = "black",outlier.size = 3) +
                               theme(axis.text.x = element_text(angle = 45, hjust = 1,size = 25)) +
                               theme_grey(base_size = 25) +
                               labs(x = "Country",y = "Gross Exports",title = "Box plot - Gross Exports By Country (After Scaling)",tag = "B3")
gridExtra::grid.arrange(
  scatter_plot_before_scale,
  scatter_plot_after_scale,
  boxplot_Import_before_scale,
  boxplot_Import_after_scale,
  boxplot_Export_before_scale,
  boxplot_Export_after_scale,
  ncol=2
  )



LS0tDQp0aXRsZTogIk1BVEgyMzQ5IC0gUHJlcHJvY2Vzc2luZyBVTiBHb29kcyBUcmFkaW5nIERhdGFzZXRzIg0KYXV0aG9yOiAiSmlnYXIgTWFuZ3VraXlhIChTMzcxNTgwNyksIFZpa2FzIFZpcmFuaSAoUzM3MTU1NTUpLCBWaXNod2EgR2FuZGhpIChTMzcxNDgwNSkiDQpzdWJ0aXRsZTogQXNzaWdubWVudCAzDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCi0tLQ0KDQoNCiMjIFJlcXVpcmVkIHBhY2thZ2VzIA0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KDQojIyBFeGVjdXRpdmUgU3VtbWFyeSANCg0KICBUd28gZGF0YXNldHMgIkltcG9ydHMgb2YgR29vZHMiICYgIkV4cG9ydHMgb2YgR29vZHMiIHdlcmUgdGFrZW4gd2l0aCBjb3VudHJ5IHdpc2UgR3Jvc3MgdmFsdWVzIGZvciBJbXBvcnRlZCBhbmQgRXhwb3J0ZWQgZ29vZHMgZm9yIGRpZmZlcmVudCB5ZWFycyBhbmQgZGlmZmVyZW50IFNOQSBzZXJpZXMgbWV0aG9kcy4NCiAgICAgIA0KICBXZSBoYXZlIHRha2VuIGEgc3Vic2V0IG9mIGNvdW50cnkgY29sdW1uIHRvIGZpbHRlciBvdXQgNyBjb3VudHJpZXMgLSJVbml0ZWQgS2luZ2RvbSIsICJVbml0ZWQgU3RhdGVzIiwgIkphcGFuIiwgIkdlcm1hbnkiLCAiQXVzdHJhbGlhIiwgIkNhbmFkYSIgYW5kICJGcmFuY2UiIGFuZCB5ZWFyIGNvbHVtbiB0byBmaWx0ZXIgcmVjb3JkcyBmcm9tIDE5NzAgdG8gMjAxMCAmIHVzZWQgSm9pbiBvcGVyYXRpb24gdG8gbWVyZ2UgdGhlc2UgdHdvIGRhdGFzZXRzIHRvIGNvbWJpbmUgdGhlbSBpbiBhIHNpbmdsZSBkYXRhc2V0LiBBbHNvLCBDb2x1bW4gbmFtZXMgd2VyZSBjaGFuZ2VkIHRvIG1vcmUgbWVhbmluZ2Z1bCBuYW1lcyBhZnRlciBqb2luaW5nIHRoZW0uDQoNCiAgRm9yIGJldHRlciBVbmRlcnN0YW5kaW5nIG9mIGRhdGEsICJDb3VudHJ5IiwgIlNOQV9TZXJpZXMiLCAiU05BX1N5c3RlbSIgJiAiQ3VycmVuY3kiIGFyZSBjb252ZXJ0ZWQgaW50byB1bm9yZGVyZWQgRmFjdG9yIGFuZCAiWWVhciIgaXMgY29udmVydGVkIGludG8gb3JkZXJlZCBGYWN0b3IuDQogIA0KICBBcyBtZXJnZWQgZGF0YXNldCBzYXRpc2ZpZXMgdGhlIHRpZHkgZGF0YSBjb25kaXRpb24sIHRoZXJlIHdhcyBubyBuZWVkIHRvIHBlcmZvcm0gYW55IG9wZXJhdGlvbiB0byB0aWR5IHRoZSBkYXRhc2V0LiBXZSBoYXZlIG1lcmdlZCB0d28gY29sdW1ucyAiU05BX1NlcmllcyIiICYgIlNOQV9OdW1iZXJzIiBhbmQgbXV0YXRlZCBvbmUgY29sdW1uIG5hbWVkICJUZXJtc19PZl9UcmFkZSIuDQogIA0KICBXZSBoYXZlIHNjYW5uZWQgdGhlIGRhdGEgdG8gaWRlbnRpZnkgcG90ZW50aWFsIE5Bcy9taXNzaW5nIHZhbHVlcyBhbmQgT3V0bGllcnMgaW4gdGhlIGRhdGFzZXQuIFRoZXJlIHdlcmUgbm8gbWlzc2luZyB2YWx1ZXMgb3IgTkFzIGZvdW5kIGluIHRoZSBjb21iaW5lZCBkYXRhc2V0LiBQb3NzaWJsZSBvdXRsaWVycyBhcmUgaWRlbnRpZmllZCBidXQgZ2l2ZW4gdGhlIGNvbnRleHQgb2YgdGhlIE51bWVyaWMgQ29sdW1uIG9uIHdoaWNoIG91dGxpZXJzIGFyZSBpZGVudGlmaWVkLCB0aGVyZSBpcyBubyBzaWduaWZpY2FuY2Ugb2YgY29uc2lkZXJpbmcgdGhlbSBhcyBvdXRsaWVycy4gRGV0YWlsZWQgRXhwbGFuYXRpb24gaXMgZ2l2ZW4gaW4gdGhlIHRoZSByZWxldmFudCAiU2NhbiIgc2VjdGlvbiBvZiB0aGlzIGRvY3VtZW50Lg0KICANCiAgU2luY2UgdGhlIGRhdGFzZXQgY29udGFpbnMgR3Jvc3MgdmFsdWVzIGZvciBkaWZmZXJlbnQgY291bnRyaWVzIGluIHRoZWlyIG93biBjdXJyZW5jeSB2YWx1ZXMgYW5kIGRpZmZlcmVudCBjb3VudHJpZXMgaGF2aW5nIGRpZmZlcmVudCBjdXJyZW5jeSB2YWx1ZXMsIHdlIGhhdmUgdHJhbnNmb3JtZWQgdGhlIHZhcmlhYmxlcyAiR3Jvc3NfSW1wb3J0cyIgJiAiR3Jvc3NfRXhwb3J0cyIgYnkgc2NhbGluZyB0aGUgdmFsdWVzLCB0byBleHByZXNzIHRoZW0gaW4gdGVybXMgb2YgU3RhbmRhcmQgRGV2aWF0aW9ucywgZ2l2aW5nIHJlc3VsdGluZyB2YWx1ZXMgb24gYSBzYW1lIHNjYWxlIHNvIHRoYXQgdGhleSBjYW4gYmUgY29tcGFyZWQgd2l0aCBvdGhlciB2YWx1ZXMuDQoNCiMjIERhdGEgDQoNCiAgRGF0YSBmb3IgdGhpcyBEYXRhIFByZXByb2Nlc3Npbmcgc3R1ZHkgaXMgYWNxdWlyZWQgZnJvbSAid3d3LmRhdGEudW4ub3JnIiwgd2hpY2ggaXMgbWFpbmx5IGEgcHJvZHVjdCBvZiBVbml0ZWQgTmF0aW9ucyBTdGF0aXN0aWNzIERpdmlzaW9uIHdoaWNoIGJyaW5ncyBVTiBTdGF0cyBEYXRhYmFzZXMgaW4gcmVhY2ggb2YgdXNlcnMgdGhyb3VnaCBpbnRlcm5ldC4gSW5pdGlhbGx5IHdlIGFyZSByZWZlcnJpbmcgdHdvIGRhdGFzZXRzLCBib3RoIGZhbGxpbmcgdW5kZXIgc2FtZSBjYXRlZ29yeSBhbmQgc3ViLWNhdGVnb3J5LCB3aGljaCBpcyAiTmF0aW9uYWwgQWNjb3VudHMgT2ZmaWNpYWwgQ291bnRyeSBEYXRhIi8idGFibGUgMS4xIEdyb3NzIGRvbWVzdGljIHByb2R1Y3QgYnkgZXhwZW5kaXR1cmVzIGF0IGN1cnJlbnQgcHJpY2VzIi4gRGF0YXNldHMgYXJlICJJbXBvcnRzIG9mIEdvb2RzIiAmICJFeHBvcnRzIG9mIEdvb2RzIi4gRGF0YSBkZXNjcmlwdGlvbnMgZm9yIGJvdGggb2YgdGhlbSBhcmUgZm9sbG93cy4NCiAgDQogIDEuIEltcG9ydHMgb2YgR29vZHMNCiAgICAgIA0KICAgICAgU291cmNlIC0gaHR0cDovL2RhdGEudW4ub3JnL0RhdGEuYXNweD9kPVNOQSZmPWdyb3VwX2NvZGUlM2ExMDElM2JpdGVtX2NvZGUlM2EyMQ0KICAgICAgDQogIDIuIEV4cG9ydHMgb2YgR29vZHMNCiAgDQogICAgICBTb3VyY2UgLSBodHRwOi8vZGF0YS51bi5vcmcvRGF0YS5hc3B4P2Q9U05BJmY9Z3JvdXBfY29kZSUzYTEwMSUzYml0ZW1fY29kZSUzYTE4DQogICAgICANCiAgVmFyaWFibGVzIC0NCiAgYS4gQ291bnRyeSBvciBBcmVhIC0gTmFtZSBvZiB0ZXJyaXRvcnkgYmVpbmcgb2JzZXJ2ZWQNCiAgYi4gU05BOTMgVGFibGUgQ29kZSAtIGNhdGVnb3J5IHRhYmxlIHJlZmVyZW5jZSBudW1iZXINCiAgYy4gU3ViIEdyb3VwIC0gU3ViIENhdGVnb3J5IHJlZmVyZW5jZSBudW1iZXIgDQogIGQuIEl0ZW0gLSBJdGVtIHRoYXQgY3VycmVudCBkYXRhYmFzZSByZXByZXNlbnRzIGluIHRoZSBwcm92aWRlZCBjYXRlZ29yeS9zdWItY2F0ZWdvcnkNCiAgZS4gU05BOTMgSXRlbSBDb2RlIC0gIlN5c3RlbSBvZiBOYXRpb25hbCBBY2NvdW50cyAtIDE5OTMiIC0gaXRlbSBudW1iZXIgZm9yIHBhcnRpY3VsYXIgZGF0YXNldA0KICBmLiBZZWFyIC0gWWVhciBvZiBvYnNlcnZhdGlvbg0KICBnLiBTZXJpZXMgLSBTTkEgOTMgT2JzZXJ2YXRpb24gU2VyaWVzDQogIGguIEN1cnJlbmN5IC0gQ3VycmVuY3kgZm9yIHRoZSBtZW50aW9uZWQgdmFsdWUgZm9yIEltcG9ydCAvIEV4cG9ydA0KICBpLiBGaXNjYWwgWWVhciBUeXBlIC0gRmlzY2FsIFllYXIgc3BlY2lmaWNhdGlvbiBmb3IgdGhlIG9ic2VydmF0aW9uDQogIGouIHZhbHVlIC0gUmVwb3J0ZWQgZ3Jvc3MgdmFsdWUgb2YgSW1wb3J0L0V4cG9ydCBmb3IgY291bnRyeSBvciBBcmVhIGZvciBnaXZlbiB5ZWFyDQoNCiAgIEhvd2V2ZXIsIEZvciB0aGlzIHRhc2ssIHdlIHdpbGwgb25seSBjb25zaWRlciBmb2xsb3dpbmcgY29sdW1ucy4NCg0KICAgIGkuICAgQ291bnRyeSBvciBBcmVhDQogICAgaWkuICBZZWFyDQogICAgaWlpLiBTZXJpZXMNCiAgICBpdi4gIEN1cnJlbmN5DQogICAgdi4gICBTTkEgU3lzdGVtDQogICAgdmkuICBWYWx1ZQ0KICAgICAgDQoNCiAgQm90aCBvZiB0aGUgZGF0YXNldHMsIGNvbnRhaW4gaWRlbnRpY2FsIHZhcmlhYmxlIHNldHMuIEZpcnN0IGRhdGFzZXQgY29udGFpbnMgdGhlIGdyb3NzIHZhbHVlIGZvciBJbXBvcnRlZCBHb29kcyBhbmQgc2Vjb25kIGNvbnRhaW5zIGdyb3NzIHZhbHVlIGZvciBFeHBvcnRlZCBHb29kcywgZm9yIG11bHRpcGxlIHllYXJzIG1lYXN1cmVkIGJ5IG11bHRpcGxlIFNOQSBTZXJpZXMgbWV0aG9kcy4gV2Ugd2lsbCBjb25zaWRlciBhIHN1YnNldCBvZiBjb3VudHJpZXMgdG8gY2Fycnkgb3V0IHRoZSBwcmVwcm9jZXNzaW5nIHRhc2ssIHdoaWNoIGluY2x1ZGVzICJKYXBhbiIsICJVbml0ZWQgS2luZ2RvbSIsICJHZXJtYW55IiwgIlVuaXRlZCBTdGF0ZXMiLCAiRnJhbmNlIiwgIkNhbmFkYSIgJiAiQXVzdHJhbGlhIi4gV2Ugd2lsbCBjb25zaWRlciBkYXRhIGZyb20geWVhcnMgMTk3MCB0byAyMDEwLiBTbyBmb3IgZWFjaCBjb3VudHJ5IHdlIHdpbGwgaGF2ZSBJbXBvcnQgJiBFeHBvcnQgUmVjb3JkcyBmb3IgNDEgeWVhcnMuDQogIA0KICBXZSB3aWxsIG1lcmdlIHRoZSBkYXRhc2V0cyB3aXRoIGFuIGlubmVyIGpvaW4gb24gY29sdW1ucyAiQ291bnRyeSBvciBBcmVhIiwgIlllYXIiLCAiU2VyaWVzIiwgIlNOQSBTeXN0ZW0iLCAiQ3VycmVuY3kiLiBUaGlzIHdpbGwgZ2l2ZSB1cyBhIGNvbWJpbmVkIGRhdGFzZXQsIHJlY29yZHMgb2Ygd2hpY2gsIGRlc2NyaWJlcyB0aGUgR3Jvc3MgSW1wb3J0ICYgR3Jvc3MgRXhwb3J0IFZhbHVlcyBmb3IgYSBjb3VudHJ5LCBmb3IgYSB5ZWFyIG1lYXN1cmVkIGluIHRoZSBzYW1lIFNOQSBTZXJpZXMuDQogIA0KICBXZSB3aWxsIHJlbmFtZSB0aGUgY29sdW1ucyB0byBtb3JlIHJlYWRhYmxlIG5hbWVzLiANCiAgDQogIEl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoYXQgZm9yIGEgZ2l2ZW4geWVhciwgSW1wb3J0ICYgRXhwb3J0IHZhbHVlcyBjYW4gYmUgbWVhc3VyZWQgaW4gbXVsdGlwbGUgU05BIFN5c3RlbXMuIEZvciB0aGlzIHRhc2sgd2Ugd2lsbCB1c2Ugb25seSB0aGUgaGlnaGVzdCBTTkEgU3lzdGVtKFNlcmllcykgaW4gd2hpY2ggZGF0YSBpcyByZWNvcmRlZC4gV2Ugd2lsbCBkbyB0aGF0IGJ5IHRha2luZyBhIHNsaWNlIHdoaWNoIGhhcyBtYXhpbXVtIFNOQSBTeXN0ZW0geWVhciBvdXQgb2YgYWxsIDMgU05BIFN5c3RlbXMgdGhhdCBhcmUgdXNlZCB0byBtZWFzdXJlIEdvb2RzIFRyYWRpbmcsIGkuZS4gIjE5NjgiLCAiMTk5MyIsICIyMDA4Ii4NCg0KDQoNCmBgYHtyfQ0KDQpJbXBvcnRHb29kcyA8LSByZWFkX2NzdigiSW1wb3J0IG9mIGdvb2RzLmNzdiIpDQpFeHBvcnRHb29kcyA8LSByZWFkX2NzdigiRXhwb3J0IG9mIGdvb2RzLmNzdiIpDQoNCmNhdCgiU3Vic2V0dGluZyBJbXBvcnQgb2YgR29vZHMgRGF0YXNldCBiZWZvcmUgbWVyZ2luZyAoQmVsb3cpIikNCkltcG9ydEdvb2RzIDwtIEltcG9ydEdvb2RzWzA6OTUwNixdDQpJbXBvcnRHb29kcyA8LSBJbXBvcnRHb29kcyAlPiUgc2VsZWN0KGBDb3VudHJ5IG9yIEFyZWFgLFllYXIsU2VyaWVzLEN1cnJlbmN5LGBTTkEgU3lzdGVtYCxWYWx1ZSkNCkltcG9ydEdvb2RzIDwtIEltcG9ydEdvb2RzICU+JSBzdWJzZXQoSW1wb3J0R29vZHMkYENvdW50cnkgb3IgQXJlYWAgJWluJSBjKCJVbml0ZWQgS2luZ2RvbSIsIlVuaXRlZCBTdGF0ZXMiLCJKYXBhbiIsIkdlcm1hbnkiLCJBdXN0cmFsaWEiLCJDYW5hZGEiLCJGcmFuY2UiKSAmIEltcG9ydEdvb2RzJFllYXIgJWluJSBjKHNlcSgxOTcwLDIwMTApKSkNCg0KDQoNCmNhdCgiU3Vic2V0dGluZyBFeHBvcnQgb2YgR29vZHMgRGF0YXNldCBiZWZvcmUgbWVyZ2luZyAoQmVsb3cpIikNCkV4cG9ydEdvb2RzIDwtIEV4cG9ydEdvb2RzWzA6OTUwNixdDQpFeHBvcnRHb29kcyA8LSBFeHBvcnRHb29kcyAlPiUgc2VsZWN0KGBDb3VudHJ5IG9yIEFyZWFgLFllYXIsU2VyaWVzLEN1cnJlbmN5LGBTTkEgU3lzdGVtYCxWYWx1ZSkNCkV4cG9ydEdvb2RzIDwtIEV4cG9ydEdvb2RzICU+JSBzdWJzZXQoRXhwb3J0R29vZHMkYENvdW50cnkgb3IgQXJlYWAgJWluJSBjKCJVbml0ZWQgS2luZ2RvbSIsIlVuaXRlZCBTdGF0ZXMiLCJKYXBhbiIsIkdlcm1hbnkiLCJBdXN0cmFsaWEiLCJDYW5hZGEiLCJGcmFuY2UiKSAmIEV4cG9ydEdvb2RzJFllYXIgJWluJSBjKHNlcSgxOTcwLDIwMTApKSkNCg0KDQoNCmNhdCgiTWVyZ2luZyBkYXRhc2V0cyAoQmVsb3cpIikNClRyYWRlU3RhdGlzdGljcyA8LSBJbXBvcnRHb29kcyAlPiUgaW5uZXJfam9pbihFeHBvcnRHb29kcyxieSA9IGMoIkNvdW50cnkgb3IgQXJlYSIsIlllYXIiLCJTZXJpZXMiLCJTTkEgU3lzdGVtIiwiQ3VycmVuY3kiKSkNCg0KY2F0KCJSZW5hbWluZyBDb2x1bW5zIChCZWxvdykiKQ0KY29sbmFtZXMoVHJhZGVTdGF0aXN0aWNzKSA8LSBjKCJDb3VudHJ5IiwiWWVhciIsIlNOQV9TZXJpZXMiLCJDdXJyZW5jeSIsIlNOQV9TeXN0ZW0iLCJHcm9zc19JbXBvcnRzIiwiR3Jvc3NfRXhwb3J0cyIpDQoNCg0KDQpoZWFkKEltcG9ydEdvb2RzKQ0KaGVhZChFeHBvcnRHb29kcykNCmhlYWQoVHJhZGVTdGF0aXN0aWNzKQ0KDQoNClRyYWRlU3RhdGlzdGljcyA8LSBUcmFkZVN0YXRpc3RpY3MgJT4lIGdyb3VwX2J5KENvdW50cnksWWVhcikgJT4lIHNsaWNlKHdoaWNoLm1heChTTkFfU3lzdGVtKSkNCg0KVHJhZGVTdGF0aXN0aWNzJENvdW50cnkgJT4lICB0YWJsZSgpDQoNCg0KDQpgYGANCg0KIyMgVW5kZXJzdGFuZCANCg0KICBGb2xsb3dpbmcgaXMgdGhlIFN1bW1hcnkgb2YgdmFyaWFibGUgdHlwZXMuIA0KICAgIDEuIENvdW50cnkgLSAgICAgICAgQ2hhcmFjdGVyDQogICAgMi4gWWVhciAtICAgICAgICAgICBpbnQNCiAgICAzLiBTTkFfU2VyaWVzIC0gICAgIGludA0KICAgIDQuIEN1cnJlbmN5IC0gICAgICAgQ2hhcmFjdGVyDQogICAgNS4gU05BX1N5c3RlbSAtICAgICBpbnQNCiAgICA2LiBHcm9zc19JbXBvcnRzIC0gIGRvdWJsZQ0KICAgIDcuIEdyb3NzX0V4cG9ydHMgLSAgZG91YmxlDQogICAgDQogIC0gIkNvdW50cnkiLCAiU05BX1NlcmllcyIgJiAiU05BX1N5c3RlbSIgYXJlIGNvbnZlcnRlZCBpbnRvIHVub3JkZXJlZCBmYWN0b3JzLg0KICAtIEN1cnJ1ZW5jeSBpcyBjb252ZXJ0ZWQgaW50byB1bm9yZGVyZWQgbGFiZWxlZCBmYWN0b3IgdmFyaWFibGUuIFdlIHdpbGwgY2hhbmdlIHRoZSBsYWJlbHMgdG8gSW50ZXJuYXRpb25hbCBjdXJyZW5jeSBjb2RlcyBmb3IgZWFzZSBvZiB1c2FnZS4NCiAgLSBZZWFyIGlzIGNvbnZlcnRlZCBpbnRvIGEgb3JkZXJlZCBmYWN0b3IgdmFyaWFibGUNCiAgLSBHcm9zc19JbXBvcnRzICYgR3Jvc3NfRXhwb3J0cyBhcmUgbnVtZXJpYyB2YXJpYWJsZXMNCg0KYGBge3J9DQoNClRyYWRlU3RhdGlzdGljcyRDb3VudHJ5IDwtIFRyYWRlU3RhdGlzdGljcyRDb3VudHJ5ICU+JSBhcy5mYWN0b3IoKQ0KYXR0cmlidXRlcyhUcmFkZVN0YXRpc3RpY3MkQ291bnRyeSkNCg0KVHJhZGVTdGF0aXN0aWNzJFNOQV9TZXJpZXMgPC0gVHJhZGVTdGF0aXN0aWNzJFNOQV9TZXJpZXMgJT4lIGFzLmZhY3RvcigpDQphdHRyaWJ1dGVzKFRyYWRlU3RhdGlzdGljcyRTTkFfU2VyaWVzKQ0KDQpUcmFkZVN0YXRpc3RpY3MkU05BX1N5c3RlbSA8LSBUcmFkZVN0YXRpc3RpY3MkU05BX1N5c3RlbSAlPiUgYXMuZmFjdG9yKCkNCmF0dHJpYnV0ZXMoVHJhZGVTdGF0aXN0aWNzJFNOQV9TeXN0ZW0pDQoNClRyYWRlU3RhdGlzdGljcyRZZWFyIDwtIFRyYWRlU3RhdGlzdGljcyRZZWFyICU+JSBmYWN0b3IobGV2ZWxzID0gYyhzZXEoMTk3MCwyMDEwKSksbGFiZWxzID0gYyhzZXEoMTk3MCwyMDEwKSksIG9yZGVyZWQgPSBUUlVFKSANCmF0dHJpYnV0ZXMoVHJhZGVTdGF0aXN0aWNzJFllYXIpDQpzdHIoVHJhZGVTdGF0aXN0aWNzJFllYXIpDQoNClRyYWRlU3RhdGlzdGljcyRDdXJyZW5jeSA8LSBUcmFkZVN0YXRpc3RpY3MkQ3VycmVuY3kgJT4lIGZhY3RvcihsZXZlbHMgPSBjKCIxOTk5IEZSRiBldXJvIC8gZXVybyIsIjE5OTkgREVNIGV1cm8gLyBldXJvIiwiRXVybyIsIkF1c3RyYWxpYW4gZG9sbGFyIiwiQ2FuYWRpYW4gZG9sbGFyIiwieWVuIiwicG91bmQgc3RlcmxpbmciLCJVUyBkb2xsYXIiKSxsYWJlbHMgPSBjKCJFVVIiLCJFVVIiLCJFVVIiLCJBVUQiLCJDQUQiLCJKUFkiLCJHQlAiLCJVU0QiKSxvcmRlcmVkID0gRkFMU0UpIA0KYXR0cmlidXRlcyhUcmFkZVN0YXRpc3RpY3MkQ3VycmVuY3kpDQoNCg0KVHJhZGVTdGF0aXN0aWNzJEdyb3NzX0ltcG9ydHMgJT4lICBjbGFzcygpDQpUcmFkZVN0YXRpc3RpY3MkR3Jvc3NfRXhwb3J0cyAlPiUgIGNsYXNzKCkNCg0KYGBgDQoNCg0KIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJIA0KDQogIEZvbGxvd2luZyBjaGFyYWN0ZXJpc3RpY3MgYXJlIG9ic2VydmFibGUgaW4gdGhlIGN1cnJlbnQgZGF0YS4NCiAgDQogICogRWFjaCB2YXJpYWJsZSBoYXMgaXRzIG93biBjb2x1bW4sIGFzIHRoZXJlIGFyZSB2YXJpYWJsZXMgZXhwcmVzc2VkIGFzIHZhbHVlcy4NCiAgKiBBbGwgdGhlIHZhbHVlcyBpbiB0aGUgcmVjb3JkcyB0aGF0IGFyZSB1bmlxdWUgYW5kIGhhdmUgdGhlaXIgb3duIHJvdyBkdWUgdG8gaW5uZXIgam9pbiBvcGVyYXRpb24gd2UgcGVyZm9ybWVkLiBvbmx5IG1hdGNoaW5nIHJvd3MgYXJlIGNvcGllZCB0byB0aGUgbmV3IGRhdGFzZXQuDQogICogQWxsIHRoZSB2YWx1ZXMgaGF2ZSB0aGVpciBvd24gY2VsbC4NCiAgDQogIFRoYXQgc3VnZ2VzdHMgdGhhdCBkYXRhIGlzIHJlYWRpbHkgaW4gYSB0aWR5IGZvcm1hdC4gDQogIA0KICBIb3dldmVyLCB0aGVyZSBpcyBhIHBvc3NpYmlsaXR5IHRvIG1lcmdlIHR3byBjb2x1bW5zIC0gU05BX1NlcmllcyAmIFNOQV9OdW1iZXJzLGFzIHRoZXkgaGF2ZSBjb250ZXh0dWFsIGJpbmRpbmcgd2l0aCBlYWNoIG90aGVyLCBhbmQgYWxzbywgd2UgZG9uJ3QgbmVlZCB0aGVzZSB2YWx1ZXMgc2VwYXJhdGVseSBpbiBmdXJ0aGVyIHByZXByb2Nlc3NpbmcgdGFza3MuIFNvIHRoZXNlIHR3byBjb2x1bW5zIGFyZSBtZXJnZWQgdG9nZXRoZXIgd2l0aCB1bml0ZSgpIG9wZXJhdGlvbi4gVGhlIHJlc3VsdGluZyBjb2x1bW4gd2lsbCBjb250YWluIGJvdGggdmFsdWVzIGpvaW5lZCB3aXRoIGEgIi8iLiBBbHRlcmVkIGRhdGFzZXQgY2FuIGJlIHNlZW4gaW4gdGhlIHRhYmxlLW91dHB1dCBiZWxvdy4NCg0KDQpgYGB7cn0NCg0KVHJhZGVTdGF0aXN0aWNzIDwtICBUcmFkZVN0YXRpc3RpY3MgJT4lIHVuaXRlKGNvbCA9ICJTTkEtU2VyaWVzL1N5c3RlbSIsU05BX1NlcmllcyAsIFNOQV9TeXN0ZW0sc2VwID0gIi8iKQ0KVHJhZGVTdGF0aXN0aWNzJGBTTkEtU2VyaWVzL1N5c3RlbWAgPC0gYXMuZmFjdG9yKFRyYWRlU3RhdGlzdGljcyRgU05BLVNlcmllcy9TeXN0ZW1gKQ0KDQpUcmFkZVN0YXRpc3RpY3MgJT4lIGhlYWQoKQ0KDQpgYGANCg0KIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJSSANCg0KICBXZSB3aWxsIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSBjYWxsZWQgIlRlcm1zX09mX1RyYWRlIi4gVGVybXMgb2YgdHJhZGUgaXMgYSB0cmFkaW5nIHRlcm0sIHdoaWNoIGlzIGVzc2VudGlhbGx5IGEgcmF0aW8gb2YgR3Jvc3MgRXhwb3J0cyB0byBHcm9zcyBJbXBvcnRzIG11bHRpcGxpZWQgYnkgMTAwLiBUZXJtcyBvZiB0cmFkZSwgaW4gZmFjdCwgZGVzY3JpYmVzIHRoZSBhbW91bnQgb2YgZXhwb3J0IGdvb2QgYSBjb3VudHJ5IGNhbiBwdXJjaGFzZSBwZXIgdW5pdCBvZiBpbXBvcnQgZ29vZC4gU28gaWYgdGhlIFRlcm1zIG9mIFRyYWRlIGlzIG1vcmUgdGhhbiAxMDAlLCB0aGF0IGluZGljYXRlcyBhIGNvdW50cnkgaGFzIGFuIGhlYWx0aHkgZWNvbm9teSB3aXRoIGdvb2QgdHJhZGUuIEJ1dCB0aGF0IGlzIGEgYmx1bnQgYW5kIGFic3RyYWN0IHN0YXRlbWVudCB0byBpbmRpY2F0ZSB0aGUgbWVhbmluZyBvZiBUb1QuDQogIA0KICBXZSB3aWxsIGFkZCB0aGUgbmV3IGNvbHVtbiBuYW1lZCAiVGVybXNfT2ZfVHJhZGUiIGluIG91ciBkYXRhc2V0IGJ5IHVzaW5nIGEgbXV0YXRlKCkgb3BlcmF0aW9uLg0KDQpgYGB7cn0NCg0KVHJhZGVTdGF0aXN0aWNzIDwtIFRyYWRlU3RhdGlzdGljcyAlPiUgbXV0YXRlKFRlcm1zX09mX1RyYWRlID0gKEdyb3NzX0V4cG9ydHMgKiAxMDApLyBHcm9zc19JbXBvcnRzKQ0KDQpUcmFkZVN0YXRpc3RpY3MgJT4lIGhlYWQoKQ0KDQpgYGANCg0KDQojIwlTY2FuIEkgDQoNCiAgSW4gdGhpcyBzZWN0aW9uLCBXZSBoYXZlIGNoZWNrZWQgR3Jvc3NfSW1wb3J0cywgR3Jvc3NfRXhwb3J0cyAmIG5ld2x5IGFkZGVkIFRlcm1zX09mX1RyYWRlIHZhcmlhYmxlcyBmb3IgbnVsbCB2YWx1ZXMsIEluZmluaXRlIHZhbHVlcyBhbmQgTmFOIHZhbHVlcy4NCiAgDQogIEFzIHBlciB0aGUgcmVzdWx0cywgdGhlcmUgYXJlIG5vIG51bGwvaW5jb25zaXN0ZW50IHZhbHVlcyBpbiB0aGUgbnVtZXJpYyB2YXJpYWJsZXMgb2YgZGF0YXNldC4gDQoNCmBgYHtyfQ0KDQpuYV9Db3VudF9Hcm9zc19JbXBvcnRzIDwtIHN1bShpcy5uYShUcmFkZVN0YXRpc3RpY3MkR3Jvc3NfSW1wb3J0cykgfCBpcy5pbmZpbml0ZShUcmFkZVN0YXRpc3RpY3MkR3Jvc3NfSW1wb3J0cykgfCBpcy5uYW4oVHJhZGVTdGF0aXN0aWNzJEdyb3NzX0ltcG9ydHMpKQ0KDQpuYV9Db3VudF9Hcm9zc19FeHBvcnRzIDwtIHN1bShpcy5uYShUcmFkZVN0YXRpc3RpY3MkR3Jvc3NfRXhwb3J0cykgfCBpcy5pbmZpbml0ZShUcmFkZVN0YXRpc3RpY3MkR3Jvc3NfRXhwb3J0cykgfCBpcy5uYW4oVHJhZGVTdGF0aXN0aWNzJEdyb3NzX0V4cG9ydHMpKQ0KDQpuYV9Db3VudF9UT1QgPC0gc3VtKGlzLm5hKFRyYWRlU3RhdGlzdGljcyRUZXJtc19PZl9UcmFkZSkgfCBpcy5pbmZpbml0ZShUcmFkZVN0YXRpc3RpY3MkVGVybXNfT2ZfVHJhZGUpIHwgaXMubmFuKFRyYWRlU3RhdGlzdGljcyRUZXJtc19PZl9UcmFkZSkpDQoNCmNhdCgiIE51bWJlciBvZiBOdWxscy9pbmNvbnNpc3RlbmNpZXMgaW4gR3Jvc3NfSW1wb3J0cyAtIixuYV9Db3VudF9Hcm9zc19JbXBvcnRzLCJcbiIsIk51bWJlciBvZiBOdWxscy9pbmNvbnNpc3RlbmNpZXMgaW4gR3Jvc3NfSW1wb3J0cyAtIixuYV9Db3VudF9Hcm9zc19FeHBvcnRzLCJcbiIsIk51bWJlciBvZiBOdWxscy9pbmNvbnNpc3RlbmNpZXMgaW4gVGVybXNfT2ZfVHJhZGUgLSIsbmFfQ291bnRfVE9ULCJcbiIpDQoNCmBgYA0KDQoNCiMjCVNjYW4gSUkNCg0KICBXZSB3aWxsIHNjYW4gYWxsIDMgbnVtZXJpYyBjb2x1bW5zIGZvciBwb3RlbnRpYWwgb3V0bGllcnMgaW4gdGhlbSB1c2luZyBib3gtcGxvdHMuIA0KIA0KICBJdCBpcyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHdlIHdpbGwgc2NhbiBmb3Igb3V0bGllcnMsIGNvbnNpZGVyaW5nIGVhY2ggY291bnRyeSwgZm9yIHZhcmlhYmxlcyBHcm9zc19JbXBvcnRzICYgR3Jvc3NfRXhwb3J0cy4gV2UgZG8gc28gdG8gYWNjb21tb2RhdGUgdGhlIGVmZmVjdCBvZiBkaWZmZXJlbnQgY3VycmVuY2llcyBvbiB0aGUgdmFsdWUgb2YgSW1wb3J0cyAmIEV4cG9ydHMsIHdlIHdpbGwgbmVlZCBsb29rIGZvciBvdXRsaWVycyBpbiB0aGUgZGF0YSBvZiBwYXJ0aWN1bGFyIGdyb3Vwcy4NCiAgDQogIEZvciBleGFtcGxlLCB3ZSBjYW5ub3QgZGlyZWN0bHkgY29tcGFyZSwgVW5pdGVkIFN0YXRlcycgaW1wb3J0IHZhbHVlIGluIDE5NzAsIHdoaWNoIGlzICI0MDkwMDAwMDAwMCIgVVNELCB0byBKYXBhbidzIGltcG9ydCB2YWx1ZSBpbiAxOTcwLCB3aGljaCBpcyAiNTQ4NDEwMDAwMDAwMCIgSlBZLiBTaW1wbHkgYmVjYXVzZSBhIFVTRCBhbmQgSlBZIGNhbm5vdCBiZSBkaXJlY3RseSBjb21wYXJlZC4NCiAgDQogIFRoYXQncyB3aHkgd2UgY2FuIGxvb2sgZm9yIG91dGxpZXJzIGluIHBhcnRpY3VsYXIgY291bnRyeSdzIGRhdGEsIHdoZXJlIGFsbCBvYnNlcnZhdGlvbnMgYXJlIG1hZGUgaW4gc2FtZSBjdXJyZW5jeS4NCiAgT3V0bGllcnMgaW4gdGFibGUgMSAmIDIgcmVwcmVzZW50LCBTaWduaWZpY2FudGx5IGhpZ2ggb3IgbG93LCBJbXBvcnQgb3IgRXhwb3J0IG9mIEdvb2RzIGJ5IGEgY291bnRyeSBpbiBhIHBhcnRpY3VsYXIgeWVhciB0aGFuIGl0IGRpZCBpbiBvdGhlciB5ZWFycy4gDQogIA0KICBIb3dldmVyLCBmb3IgVGVybXMgb2YgVHJhZGUsIHdlIGNhbiBjb25zaWRlciBlbnRpcmUgdmFyaWFibGUgdG8gc2NhbiBmb3Igb3V0bGllcnMsIHNpbXBseSBiZWNhdXNlIG9mIHRoZSBmYWN0IHRoYXQgVG9UIGlzIG5vdCBkZXBlbmRlbnQgb24gYW55IGN1cnJlbmN5LCBhbmQgY2FuIGJlIHVzZWQgdG8gY29tcGFyZSBhYnNvbHV0ZSB0cmFkZSBwZXJmb3JtYW5jZXMgb2YgY291bnRyaWVzLiANCiAgDQogIEZvciBleGFtcGxlLCBpZiBVbml0ZWQgU3RhdGVzIGhhcyBhIFRvVCBvZiAxMTAgZm9yIGFueSBnaXZlbiB5ZWFyICYgSmFwYW4gaGFzIFRvVCBvZiAxNDAgZm9yIHRoZSBzYW1lIG9yIGRpZmZlcmVudCB5ZWFyLCB3ZSBjYW4gc2F5IHRoYXQgSmFwYW4gcGVyZm9ybWVkIGJldHRlciB0aGFuIHVuaXRlZCBzdGF0ZXMgcGFydGljdWxhcmx5IGluICJUZXJtcyBvZiBUcmFkZSIuDQogIA0KICBPdXRsaWVycyBpbiB0YWJsZSAzIHJlcHJlc2VudCwgU2lnbmlmaWNhbnRseSBoaWdoIG9yIGxvdyBwZXJmb3JtYW5jZSBvZiBhIGNvdW50cnkgaW4gIlRlcm1zIG9mIFRyYWRlIiBhcyBjb21wYXJlZCB0byBhbGwgb3RoZXIgY291bnRyaWVzIGZvciBlbnRpcmUgb2JzZXJ2YXRpb24gcGVyaW9kLg0KICANCiAgVGhlc2Ugb3V0bGllcnMsIGFyZSBub3QgZHVlIHRvIGFueSBlcnJvciBpbiBtZWFzdXJlbWVudCwgYnV0IGFyZSBleHRyZW1lIG9jY3VycmVuY2VzIG9mIGV2ZW50cyBpbiB0aGUgb2JzZXJ2YXRpb24gcGVyaW9kIHNvIHdlIGRvIG5vdCBuZWVkIHRvIGltcHV0ZSB0aGVtLCBhcyB0aGV5IHBvc3Nlc3MgYWN0dWFsIHN0YXRpc3RpY2FsIHZhbHVlcy4NCiAgDQogIE5PVEUgDQogICAgPiBCb3gtcGxvdHMgZm9yIEdyb3NzX0ltcG9ydHMgJiBHcm9zc19FeHBvcnRzIG1heSBzZWVtIHVucmVhbGlzdGljIG9yIGZhdWx0eSBhdCBmaXJzdCEgYnV0IHRoZSBpcnJlZ3VsYXIgc2hhcGUgZm9yICBjb3VudHJpZXMgb3RoZXIgdGhhbiAiSmFwYW4iLCBpcyBiZWNhdXNlIG9mIHRoZSBmYWN0IHRoYXQgYWxsIHRoZSB2YWx1ZXMgYXJlIHJlcHJlc2VudGVkIGluIGRpZmZlcmVudCBjdXJyZW5jaWVzLlZhbHVlIG9mIEphcGFuZXNlIGJlaW5nIHNtYWxsZXIgdGhhbiByZXN0IG9mIHRoZSBjb3VudHJpZXMsIHRoZSBtYWduaXR1ZGUgb2YgbnVtYmVycyByZXByZXNlbnRpbmcgSW1wb3J0ICYgRXhwb3J0IGlzIGxhcmdlLiANCiAgICA+IFdlIG5lZWQgdG8gc2NhbGUgdGhlIHZhcmlhYmxlcyBHcm9zc19JbXBvcnRzICYgR3Jvc3NfRXhwb3J0cywgdG8gc3VwcHJlc3MgdGhlIGVmZmVjdCBvZiBkaWZmZXJlbnQgY3VycmVuY2llcy4gV2hpY2ggaXMgZG9uZSBpbiB0aGUgbmV4dCBzZWN0aW9uDQogICAgICAgDQogIA0KDQpgYGB7ciwgZmlnLndpZHRoPTMwLCBmaWcuaGVpZ2h0PTE1LGZpZy5zaG93PSdob2xkJyxmaWcuYWxpZ249J2NlbnRlcid9DQoNCnBhcihwcyA9IDEyLCBjZXggPSAyLCBjZXgubWFpbiA9IDEpDQoNCg0KaW1wb3J0c19ib3hwbG90IDwtIGJveHBsb3QoR3Jvc3NfSW1wb3J0cyB+IGFzLmZhY3Rvcih4ID0gdW5pdGUoY29sID0gIkNvdW50cnktQ3VycmVuY3kiLENvdW50cnkgLCBDdXJyZW5jeSxzZXAgPSAiIC0gIixkYXRhID0gVHJhZGVTdGF0aXN0aWNzKSRgQ291bnRyeS1DdXJyZW5jeWApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gVHJhZGVTdGF0aXN0aWNzLG1haW49Ikdyb3NzIEltcG9ydCB2YWx1ZSBmb3IgY291bnRyaWVzIChEaWZmZXJlbnQgQ3VycmVuY2llcykiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB4bGFiPSJDb3VudHJ5IC0gQ3VycmVuY3kiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB5bGFiPSJJbXBvcnQgVmFsdWUiKQ0KDQoNCmV4cG9ydHNfYm94cGxvdCA8LSBib3hwbG90KEdyb3NzX0V4cG9ydHMgfiBhcy5mYWN0b3IoeCA9IHVuaXRlKGNvbCA9ICJDb3VudHJ5LUN1cnJlbmN5IixDb3VudHJ5ICwgQ3VycmVuY3ksc2VwID0gIiAtICIsZGF0YSA9IFRyYWRlU3RhdGlzdGljcykkYENvdW50cnktQ3VycmVuY3lgKSwNCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gVHJhZGVTdGF0aXN0aWNzLA0KICAgICAgICAgICAgICAgICAgICAgIG1haW49Ikdyb3NzIEV4cG9ydCB2YWx1ZSBmb3IgY291bnRyaWVzIChEaWZmZXJlbnQgQ3VycmVuY2llcykiLA0KICAgICAgICAgICAgICAgICAgICAgIHhsYWI9IkNvdW50cnkgLSBDdXJyZW5jeSIsDQogICAgICAgICAgICAgICAgICAgICAgeWxhYj0iRXhwb3J0IFZhbHVlIikNCg0KIA0KICB0b3RfYm94cGxvdCA8LSBib3hwbG90KFRyYWRlU3RhdGlzdGljcyRUZXJtc19PZl9UcmFkZSwNCiAgICAgICAgICAgICAgICAgICAgICBtYWluPSJUZXJtIG9mIFRyYWRlIGZvciBjb3VudHJpZXMgIiwNCiAgICAgICAgICAgICAgICAgICAgICB5bGFiPSJUZXJtIG8gVHJhZGUiKQ0KICANCiAgDQpJbXBvcnRfT3V0bGllcnMgPC0gVHJhZGVTdGF0aXN0aWNzICU+JSBzdWJzZXQoR3Jvc3NfSW1wb3J0cyAlaW4lIGltcG9ydHNfYm94cGxvdCRvdXQpDQpFeHBvcnRfT3V0bGllcnMgPC0gVHJhZGVTdGF0aXN0aWNzICU+JSBzdWJzZXQoR3Jvc3NfRXhwb3J0cyAlaW4lIGV4cG9ydHNfYm94cGxvdCRvdXQpDQpUb3RfT3V0bGllcnMgPC0gVHJhZGVTdGF0aXN0aWNzICU+JSBzdWJzZXQoKFRlcm1zX09mX1RyYWRlKSAlaW4lIHRvdF9ib3hwbG90JG91dCkNCg0KDQoNCnByaW50KEltcG9ydF9PdXRsaWVycykNCg0KcHJpbnQoRXhwb3J0X091dGxpZXJzKQ0KDQpwcmludChUb3RfT3V0bGllcnMpDQoNCmBgYA0KDQoNCiMjCVRyYW5zZm9ybSANCg0KICBUaGUgZGlmZmVyZW5jZSBpbiB2YWx1ZXMgb2YgZGlmZmVyZW50IGN1cnJlbmNpZXMgY3JlYXRlcyBhIG1ham9yIHByb2JsZW0gd2hpbGUgdHJ5aW5nIHRvIHVuZGVyc3RhbmQgbmF0dXJlIG9mIHZhcmlhYmxlcyBHcm9zc19JbXBvcnRzICYgR3Jvc3NfRXhwb3J0cy4gQXMgY2FuIGJlIHNlZW4gaW4gdGhlIHBsb3RzIG9uIHRoZSBsZWZ0IGhhbmQgc2lkZSBpbiB0aGUgZ3JpZCBiZWxvdy4gSmFwYW4ncyBjdXJyZW5jeSBKUFkgaGFzIGEgcmVsYXRpdmVseSBsb3cgdmFsdWUgY29tcGFyZWQgdG8gb3RoZXJzLiBTbyB0aGUgbnVtYmVyIHJlcHJlc2VudGluZywgZXZlbiBhIHNtYWxsIHRyYWRlLCBpbiBKUFkgd2lsbCBiZSBhIHNpZ25pZmljYW50bHkgbGFyZ2UgbnVtYmVyLiAoQXMgb24gMjEgT2N0b2JlciwgMjAxOCwgMSBKUFkgPSAwLjAwODkgVVNEKS4NCiAgDQogIFRoaXMgY3JlYXRlcyBhIHByb2JsZW0gd2hlbiB3ZSB0cnkgdG8gaW50ZXJwcmV0IHRoZSBkYXRhIHdoaWNoIGhhcyB2YWx1ZXMgZXhwcmVzc2VkIGluIG11bHRpcGxlIGN1cnJlbmNpZXMuIFNtYWxsZXIgY3VycmVuY2llcyB0ZW5kIHRvIG92ZXJzaGFkb3cgdGhlIGxhcmdlciBjdXJyZW5jaWVzLg0KICANCiAgVG8gcmVtZWR5IHRoZSBlZmZlY3RzIG9mIGRpZmZlcmVudCBjdXJyZW5jaWVzLCB3ZSB3aWxsIHNjYWxlIHRoZSB2YWx1ZXMsIGFuZCBleHByZXNzIHRoZW0gaW4gdGVybXMgb2YgU3RhbmRhcmQgRGV2aWF0aW9ucy4gDQogIA0KICBIZXJlIGFsc28sIHdlIHdpbGwgZ3JvdXAgdGhlIGRhdGEgYnkgY291bnRyeSwgYW5kIGFwcGx5IHNjYWxpbmcgdG8gZWFjaCBvZiB0aGUgZ3JvdXAgaW5kZXBlbmRlbnRseS4gSWYgd2UgYXBwbHkgdGhlIHNjYWxpbmcgb24gZW50aXJlIHZhcmlhYmxlcywgdGhlIG91dHB1dCB3aWxsIGJlIHRoZSBzYW1lLCBzbWFsbGVyIEpQWSBvdmVyc2hhZG93aW5nIGFsbCB0aGUgb3RoZXIgbGFyZ2VyIGN1cnJlbmNpZXMgYXMgY2FuIGJlIHNlZW4gaW4gbGVmdCBzaWRlIHBsb3RzLg0KICANCiAgR3JvdXBlZCBzY2FsaW5nIHdpbGwgZXhwb3NlIHRydWUgbmF0dXJlIG9mIHRoZSB2YWx1ZXMsIGJ5IGFic3RyYWN0aW5nIHRoZSBlZmZlY3Qgb2YgY3VycmVuY3kgb24gdGhlIGRhdGEuIA0KICANCiAgQXMgY2FuIGJlIG9ic2VydmVkIGZyb20gdGhlIHBsb3RzIG9uIHRoZSByaWdodCBoYW5kIHNpZGUsIGRhdGEgaXMgbW9yZSBpbnRlcnByZXRhYmxlLCBhcyB0aGUgdmFsdWVzIGFyZSBzY2FsZWQgYW5kIG5vdyBleHByZXNzZWQgaW4gdGVybXMgb2YgU3RhbmRhcmQgZGV2aWF0aW9ucyBvZiB0aGF0IGdyb3VwLg0KICANCiAgQnkgY29tcGFyaW5nIGJvdGggZ3JhcGhzIHdlIGNhbiBzZWUgdGhhdCBKYXBhbidzIHZhbHVlcyBpbiBzY2F0dGVycGxvdCAmIHNoYXBlcyBpbiBib3hwbG90cyBoYXZlIG5vdCBjaGFuZ2VkLiBJdCBpcyBiZWNhdXNlIHNjYWxpbmcgaGFzIG5vdCBjaGFuZ2VkIHRoZSB2YWx1ZXMgaW4gaXRzIGFic29sdXRpb24sIGJ1dCBvbmx5IHJlcHJlc2VudGVkIHRoZW0gaW4gYSBtb3JlIHN1aXRhYmxlIGFuZCBuYXJyb3cgc2NhbGUsIHdpdGhvdXQgYWZmZWN0aW5nIHRoZSB0cnVlIG5hdHVyZSBvZiB0aGUgZGF0YS4NCg0KDQoNCmBgYHtyLCBvdXQud2lkdGg9JzFcXGxpbmV3aWR0aCcsIGZpZy53aWR0aD0zMCwgZmlnLmhlaWdodD0zMCxmaWcuc2hvdz0naG9sZCcsZmlnLmFsaWduPSdjZW50ZXInfQ0KDQpjYXQoIlBsb3QgQTEiKQ0Kc2NhdHRlcl9wbG90X2JlZm9yZV9zY2FsZSA8LSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3Bsb3QoVHJhZGVTdGF0aXN0aWNzLCBhZXMoeD1Hcm9zc19JbXBvcnRzLCB5PUdyb3NzX0V4cG9ydHMsIGNvbG9yPUNvdW50cnksc2hhcGUgPSBDb3VudHJ5KSkrDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9MTpubGV2ZWxzKFRyYWRlU3RhdGlzdGljcyRDb3VudHJ5KSkgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KHNpemU9OCkgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfZ3JleShiYXNlX3NpemUgPSAyNSkgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHggPSAiR3Jvc3MgSW1wb3J0cyIseSA9ICJHcm9zcyBFeHBvcnRzIix0aXRsZSA9ICJTY2F0dGVyIHBsb3QgLSBHcm9zcyBJbXBvcnRzIHZzLiBHcm9zcyBFeHBvcnRzIChCZWZvcmUgU2NhbGluZykiLHRhZyA9ICJBMSIpDQoNCmNhdCgiUGxvdCBBMiIpDQpib3hwbG90X0ltcG9ydF9iZWZvcmVfc2NhbGUgPC0gZ2dwbG90KGRhdGEgPSBUcmFkZVN0YXRpc3RpY3MsYWVzKHggPSBDb3VudHJ5LCB5ID0gR3Jvc3NfSW1wb3J0cywgY29sb3IgPSBDb3VudHJ5KSkgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2JveHBsb3Qoc2l6ZSA9IDEsb3V0bGllci5jb2xvciA9ICJibGFjayIsb3V0bGllci5zaXplID0gMykgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDIsc2l6ZSA9IDI1KSkgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV9ncmV5KGJhc2Vfc2l6ZSA9IDI1KSArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnMoeCA9ICJDb3VudHJ5Iix5ID0gIkdyb3NzIEltcG9ydHMiLHRpdGxlID0gIkJveCBwbG90IC0gR3Jvc3MgSW1wb3J0cyBCeSBDb3VudHJ5IChCZWZvcmUgU2NhbGluZykiLHRhZyA9ICJBMiIpIA0KDQpjYXQoIlBsb3QgQTMiKQ0KYm94cGxvdF9FeHBvcnRfYmVmb3JlX3NjYWxlIDwtIGdncGxvdChkYXRhID0gVHJhZGVTdGF0aXN0aWNzLGFlcyh4ID0gQ291bnRyeSwgeSA9IEdyb3NzX0V4cG9ydHMsIGNvbG9yID0gQ291bnRyeSkpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9ib3hwbG90KHNpemUgPSAxLG91dGxpZXIuY29sb3IgPSAiYmxhY2siLG91dGxpZXIuc2l6ZSA9IDMpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLHNpemUgPSAyNSkpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfZ3JleShiYXNlX3NpemUgPSAyNSkgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHggPSAiQ291bnRyeSIseSA9ICJHcm9zcyBFeHBvcnRzIix0aXRsZSA9ICJCb3ggcGxvdCAtIEdyb3NzIEV4cG9ydHMgQnkgQ291bnRyeSAoQmVmb3JlIFNjYWxpbmcpIix0YWcgPSAiQTMiKSANCg0KDQoNCmNhdCgiU2NhbGluZyBHcm9zc19JbXBvcnRzIikNClRyYWRlU3RhdGlzdGljcyA8LSBUcmFkZVN0YXRpc3RpY3MgJT4lICBncm91cF9ieShDb3VudHJ5KSAlPiUgbXV0YXRlKEdyb3NzX0ltcG9ydHNfU2NhbGVkID0gKEdyb3NzX0ltcG9ydHMgLyhzZChHcm9zc19JbXBvcnRzKSkpKQ0KDQpjYXQoIlNjYWxpbmcgR3Jvc3NfRXhwb3J0cyIpDQpUcmFkZVN0YXRpc3RpY3MgPC0gVHJhZGVTdGF0aXN0aWNzICU+JSAgZ3JvdXBfYnkoQ291bnRyeSkgJT4lIG11dGF0ZShHcm9zc19FeHBvcnRzX1NjYWxlZCA9IChHcm9zc19FeHBvcnRzIC8oc2QoR3Jvc3NfRXhwb3J0cykpKSkNCg0KDQpjYXQoIlBsb3QgQjEiKQ0Kc2NhdHRlcl9wbG90X2FmdGVyX3NjYWxlIDwtIGdncGxvdChUcmFkZVN0YXRpc3RpY3MsIGFlcyh4PUdyb3NzX0ltcG9ydHNfU2NhbGVkLCB5PUdyb3NzX0V4cG9ydHNfU2NhbGVkLCBjb2xvcj1Db3VudHJ5LHNoYXBlID0gQ291bnRyeSkpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz0xOm5sZXZlbHMoVHJhZGVTdGF0aXN0aWNzJENvdW50cnkpKSArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoc2l6ZSA9IDgpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfZ3JleShiYXNlX3NpemUgPSAyNSkgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHggPSAiR3Jvc3MgSW1wb3J0cyIseSA9ICJHcm9zcyBFeHBvcnRzIix0aXRsZSA9ICJTY2F0dGVyIHBsb3QgLSBHcm9zcyBJbXBvcnRzIHZzLiBHcm9zcyBFeHBvcnRzIChBZnRlciBTY2FsaW5nKSIsdGFnID0gIkIxIikgDQoNCg0KY2F0KCJQbG90IEIyIikNCmJveHBsb3RfSW1wb3J0X2FmdGVyX3NjYWxlIDwtIGdncGxvdChkYXRhID0gVHJhZGVTdGF0aXN0aWNzLGFlcyh4ID0gQ291bnRyeSwgeSA9IEdyb3NzX0ltcG9ydHNfU2NhbGVkLCBjb2xvciA9IENvdW50cnkpKSArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9ib3hwbG90KHNpemUgPSAxLG91dGxpZXIuY29sb3IgPSAiYmxhY2siLG91dGxpZXIuc2l6ZSA9IDMpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsc2l6ZSA9IDI1KSkgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX2dyZXkoYmFzZV9zaXplID0gMjUpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHggPSAiQ291bnRyeSIseSA9ICJHcm9zcyBJbXBvcnRzIix0aXRsZSA9ICJCb3ggcGxvdCAtIEdyb3NzIEltcG9ydHMgQnkgQ291bnRyeSAoQWZ0ZXIgU2NhbGluZykiLHRhZyA9ICJCMiIpIA0KDQpjYXQoIlBsb3QgQjMiKQ0KYm94cGxvdF9FeHBvcnRfYWZ0ZXJfc2NhbGUgPC0gZ2dwbG90KGRhdGEgPSBUcmFkZVN0YXRpc3RpY3MsYWVzKHggPSBDb3VudHJ5LCB5ID0gR3Jvc3NfRXhwb3J0c19TY2FsZWQsIGNvbG9yID0gQ291bnRyeSkpICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2JveHBsb3Qoc2l6ZSA9IDEsb3V0bGllci5jb2xvciA9ICJibGFjayIsb3V0bGllci5zaXplID0gMykgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSxzaXplID0gMjUpKSArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfZ3JleShiYXNlX3NpemUgPSAyNSkgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnMoeCA9ICJDb3VudHJ5Iix5ID0gIkdyb3NzIEV4cG9ydHMiLHRpdGxlID0gIkJveCBwbG90IC0gR3Jvc3MgRXhwb3J0cyBCeSBDb3VudHJ5IChBZnRlciBTY2FsaW5nKSIsdGFnID0gIkIzIikNCg0KZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UoDQogIHNjYXR0ZXJfcGxvdF9iZWZvcmVfc2NhbGUsDQogIHNjYXR0ZXJfcGxvdF9hZnRlcl9zY2FsZSwNCiAgYm94cGxvdF9JbXBvcnRfYmVmb3JlX3NjYWxlLA0KICBib3hwbG90X0ltcG9ydF9hZnRlcl9zY2FsZSwNCiAgYm94cGxvdF9FeHBvcnRfYmVmb3JlX3NjYWxlLA0KICBib3hwbG90X0V4cG9ydF9hZnRlcl9zY2FsZSwNCiAgbmNvbD0yDQogICkNCg0KYGBgDQoNCjxicj4NCjxicj4NCg==