Required packages

All required packages for the preprocessing steps are loaded.

library(dplyr)
library(readxl)
library(tidyr)
library(ggplot2)

Executive Summary

This report outlines the steps taken to pre-process two relational dataset downloaded from the World Bank website. The final dataset contains information about the GDP and net inflow of Foreign Direct Investment (FDI) for ASEAN countries, which will be used for the next step of analysis in investigating the relationship between GDP and FDI.

Firstly, each table was reshaped individually according to tidy data principles, before they were merged. It is important to note that the countries in the GDP table were prioritised during merging as net inflow of FDI was expressed in percentage of the country’s GDP. The next step was to apply data type conversions, where Country Name and year was converted from character into factor and ordered factor types respectively. The tidy dataset was then filtered to only include observations from ten ASEAN countries from the year 2000 onwards as the last member of ASEAN joined in 1999.

The filtered dataset was scanned for missing values and special values (Infinity and NaNs). One observation had missing values in them, which was removed as it is below the 5% threshold. Outliers were also observed upon examining the dataset. However, the decision was to leave it as is as these were considered to be valid points which can be explained by the varying strengths of each country’s economy.

The final step involves checking the distribution of GDP and net inflow of FDI. Mathematical data transformation technique was applied in an attempt of getting the variables to match a normal distribution. Even though the transformed variables are not perfectly normal, the mean and median of each variable are close, which means that they are close to a normal distribution. Furthermore, the sample size is large enough (n > 30) where Central Limit Theorem can be invoked.

Data

There are two datasets in this report, which has been downloaded from the worldbank website. The first dataset contains information about a country’s GDP from 1960 to 2018 in US dollars. There are 63 variables in this dataset:
- Country Name
- Country Code (Unique country code given by World Bank)
- Indicator Name (The name of the indicator depending on the dataset found on World Bank’s website)
- Indicator Code (Unique indicator code)
- Column 5 to 63 contains the recorded GDP of each country for that year, labelled as the year.

# Import function
  import <- function(file){
    read_xlsx(file, sheet = 1, skip = 3)
}

# Import FDI and GDP tables
  file <- "Country FDI.xlsx"
  FDI <- import(file)

head(FDI)

The second dataset includes information about net inflow of Foreign Direct Investment (FDI) into different countries worldwide, expressed as the percentage of GDP. FDI net inflows are the value of inward direct investment made by non-resident investors in the reporting economy. It is calculated as new investment inflows less disinvestments from foreign investors in each economy, which is finally divided by GDP to be represented as a percentage of GDP. More information on FDI can be found in the link provided in the References section below.

There are also 63 variables in this dataset, with the same structure outlined above. The two datasets can be connected by Country Name or Country Code. The net inflow of FDI can be a negative number when new foreign investment is less than disinvestment for that year.

file <- "Country GDP.xlsx"
GDP <- import(file)
head(GDP)

Tidy & Manipulate Data I

According to tidy data principles, each variable should have its own column and the current dataset violates that principle as the years are spread across column 5 to 63 (column headers as variables). We will first reshape the dataset individually before merging them together by gathering column 5 to 63 into a year column.

FDI_clean <- FDI %>% gather(key = "year", value = "FDI_percent", 5:63)
GDP_clean <- GDP %>% gather(key = "year", value = "GDP", 5:63)

head(FDI_clean)
head(GDP_clean)

With two tables in a tidy format, we will merge the two together using the left_join() function, with the GDP_clean table on the left. The reason for using left_join() is because we only want to retain countries that has its GDP recorded. Since net FDI inflow is expressed in percentage of the country’s GDP, we exclude observations where a country’s net FDI inflow is recorded, but without the corresponding GDP information in the first table.

The tables will be joined by Country Name, Country Code and year to avoid duplications of these columns in the merged dataset. We will also drop redundant columns after merging.

economy <- left_join(GDP_clean, FDI_clean, by = c("Country Name", "Country Code", "year")) 
   
head(economy)
economy <- economy[,-c(2,3,4,7,8)]

head(economy)

Understand

Now that the dataset is in a tidy format, we will continue with data type conversions. The variables that has gone through data type conversions are:
1. Country Name: Changed from character to factor.
2. year: Changed from character to ordered factor

# Check the data structure of economy table before conversion
  str(economy)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   15576 obs. of  4 variables:
 $ Country Name: chr  "Aruba" "Afghanistan" "Angola" "Albania" ...
 $ year        : chr  "1960" "1960" "1960" "1960" ...
 $ GDP         : num  NA 5.38e+08 NA NA NA ...
 $ FDI_percent : num  NA NA NA NA NA NA NA NA NA NA ...
# Apply data conversions
  country_level <- unique(economy$`Country Name`)
  economy$`Country Name` <- factor(economy$`Country Name`, 
                                     levels = country_level,
                                     labels = country_level)

  year <- seq(1960,2018, by = 1)
  economy$year <- factor(economy$year,
                         levels = year,
                         labels = year,
                         ordered = TRUE)

# Check the data structure of economy table after conversion
  str(economy)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   15576 obs. of  4 variables:
 $ Country Name: Factor w/ 264 levels "Aruba","Afghanistan",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ year        : Ord.factor w/ 59 levels "1960"<"1961"<..: 1 1 1 1 1 1 1 1 1 1 ...
 $ GDP         : num  NA 5.38e+08 NA NA NA ...
 $ FDI_percent : num  NA NA NA NA NA NA NA NA NA NA ...

Tidy & Manipulate Data II

Since we are only interested in countries that are members of ASEAN, we will subset the merged economy table to include only the observations of the 10 countries. The dataset is also filtered to the year 2000 onwards as the last member of ASEAN, Cambodia, joined on \(30^{th}\) April 1999.

economy_ASEAN<- economy %>% filter(`Country Name` == "Cambodia" |
                                       `Country Name` == "Philippines" |
                                       `Country Name` == "Indonesia" |
                                       `Country Name` == "Thailand" |
                                       `Country Name` == "Vietnam" |
                                       `Country Name` == "Singapore" |
                                       `Country Name` == "Malaysia" |
                                       `Country Name` == "Lao PDR" |
                                       `Country Name` == "Brunei Darussalam" |
                                       `Country Name` == "Myanmar", year >=2000)
# Check dimension of subset
  dim(economy_ASEAN)
[1] 190   4

After subsetting the dataset, we will create two new variables:
1. FDI_value_InBillions: Each country’s net inflow FDI expressed in billions US\(\$\) (FDI_percent \(\times\) GDP)
2. GDP_value_InBillions: Each country’s GDP expressed in billions US\(\$\) (in order to simplify the reading of the numbers)

# Mutate a new variable and convert the actual values in billions
  economy_ASEAN <- mutate(economy_ASEAN, FDI_value_InBillions =
                            (economy_ASEAN$FDI_percent*economy_ASEAN$GDP)/1000000000)
  economy_ASEAN <- mutate(economy_ASEAN, GDP_value_InBillions = economy_ASEAN$GDP/1000000000)
  head(economy_ASEAN)

Scan I

The next step will be to scan for obvious errors, missing values and special values within the dataset. The total number of missing values were tallied for each column and one observation with missing values has been identified.

# Scan for missing values
  colSums(is.na(economy_ASEAN))
        Country Name                 year                  GDP          FDI_percent FDI_value_InBillions 
                   0                    0                    0                    1                    1 
GDP_value_InBillions 
                   0 
  which(is.na(economy_ASEAN), arr.ind = TRUE)
     row col
[1,]   1   4
[2,]   1   5
  economy_ASEAN[1,]

Since the missing value is less than 5% of the data, we can safely remove the observation.

  (sum(is.na(economy_ASEAN$FDI_percent)) / length(economy_ASEAN$FDI_percent))*100
[1] 0.5263158
  (sum(is.na(economy_ASEAN$FDI_value_InBillions)) / length(economy_ASEAN$FDI_value_InBillions))*100
[1] 0.5263158
  economy_ASEAN_cleaned <- economy_ASEAN[complete.cases(economy_ASEAN),]
  dim(economy_ASEAN_cleaned)
[1] 189   6

Special values (Infinity, NaNs) and inconsistencies were also checked and none were found in the dataset. As mentioned in previous sections, net inflow of FDI can be a negative number, which is why it is not considered to be an inconsistency in this dataset. Therefore, we will check if there is any zero in the dataset as FDI and GDP cannot be zero in value.

# Scan for special values
  is.special <- function(x){ if (is.numeric(x)) (is.infinite(x) | is.nan(x)) }
  sapply(economy_ASEAN_cleaned, function(x) sum( is.special(x) ))
        Country Name                 year                  GDP          FDI_percent FDI_value_InBillions 
                   0                    0                    0                    0                    0 
GDP_value_InBillions 
                   0 

The result show there is no zero value observed in the dataset.

# check for inconsistencies in the dataset
  zero <- function(x){if (is.numeric(x)) (x = 0)}
  sapply(economy_ASEAN_cleaned, function(x) sum(zero(x)))
        Country Name                 year                  GDP          FDI_percent FDI_value_InBillions 
                   0                    0                    0                    0                    0 
GDP_value_InBillions 
                   0 

Scan II

After examining and handling the missing values, special values, and inconsistencies, the next step will be to check for outliers in the dataset using boxplot.

GDP_A <- economy_ASEAN_cleaned$GDP_value_InBillions
FDI_A <- economy_ASEAN_cleaned$FDI_value_InBillions
FDI_percent_A <- economy_ASEAN_cleaned$FDI_percent
  
boxplot(GDP_A, main = "Boxplot of GDP (In Billions)", xlab = "GDP (In Billions)")

boxplot(FDI_A, main = "Boxplot of FDI (In Billions)", xlab = "FDI (In Billions)")

boxplot(FDI_percent_A, main = "Boxplot of FDI (In Percent)", xlab = "FDI (In Percent)")

From the boxplots above, we can see that there are many univariate outliers in the dataset. However, we will leave these values as is as these are mainly caused by the GDP and net inflow of FDI disparity between ASEAN countries, wherein economies of some of these countries performed better (as shown in the bar chart below). Hence, the oultiers are not driven by any potential errors in the data.

  plot1 <- ggplot(economy_ASEAN_cleaned, aes(x = reorder(`Country Name`, GDP_value_InBillions), y = GDP_value_InBillions, fill = `Country Name`))

plot1 + geom_histogram(stat = "identity") +
  coord_flip() +
  theme(legend.position = "none",
        plot.title = element_text(hjust = 0.5)) +
  ggtitle("ASEAN Countries' Total GDP (2000-2005)") +
  xlab("Countries") +
  ylab("GDP (US Billions)")


  plot2 <- ggplot(economy_ASEAN_cleaned, aes(x = reorder(`Country Name`, GDP_value_InBillions), y = FDI_value_InBillions, fill = `Country Name`))

plot2 + geom_histogram(stat = "identity") +
  coord_flip() +
  theme(legend.position = "none",
        plot.title = element_text(hjust = 0.5)) +
  ggtitle("ASEAN Countries' Total FDI net inflow (2000-2005)") +
  xlab("Countries") +
  ylab("Net FDI inflow (US Billions)")

Transform

Since we are pre-processing the data with the intent of performing a simple linear regression between the GDP and FDI, the normality of both variables will be checked using a histogram. The countries’ GDP will be checked first before moving on to the net inflow of FDI.

GDP Transformation

hist(GDP_A, main = "Histrogram of GDP (in billions)")

Upon first inspection, we can see that the distribution of GDP for ASEAN countries is right skewed. Mathematical data transformation techniques has been applied in the attempt of transforming the data to have a normal distribution.

logGDP <- log10(GDP_A)
hist(logGDP)

summary(logGDP)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.2383  1.1581  1.9962  1.8205  2.4199  3.0179 

After applying data transformation, the histogram of logGDP shows a better shape. Although it is not perfectly symmetric, the GDP’s mean and median being very close together indicates that it can be considered close to an approximately normal distribution. Furthermore, the sample size for this dataset is greater than 30, which means that Central Limit Theorem can be invoked in the analysis.

FDI Transformation

Similar to the GDP, shape of the distribution of the FDI is right-skewed. Mathematical data transformation has been applied to transform the data to approximate a normal distribution. Since there are negative values observed in the FDI as explained earlier, first step is to transform FDI raised to the power of 4 to address the negative values. Then, log10 transformation is applied.

hist(FDI_A)

FDI_power4 <- FDI_A^4
logFDI <- log10(FDI_power4)
hist(logFDI)

summary(logFDI)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 -1.406   7.163   9.781   9.393  11.803  15.907 

The histogram of logFDI does not show a perfectly symmetrical distribution. However same as the explanation on the GDP’s transformation, FDI can be considered close to a normal distribution with the mean and median being fairly close to each other and the sample size being large enough for the Central Limit Theorem to be applied.

References

Foreign direct investment, net inflows (% of GDP). (2019). Retrieved from https://data.worldbank.org/indicator/BX.KLT.DINV.WD.GD.ZS?view=chart

GDP (current US$). (2019). Retrieved from https://data.worldbank.org/indicator/NY.GDP.MKTP.CD?name_desc=false&view=chart

Kramer, L. (2019). What is GDP and Why is It So Important to Economists and Investors?. Retrieved from https://www.investopedia.com/ask/answers/what-is-gdp-why-its-important-to-economists-investors/

Te Velde, D. W. (2006). Foreign Direct Investment and Development: An Historical Perspective. Retrieved from https://www.odi.org/publications/594-foreign-direct-investment-development-historical-perspective

LS0tDQp0aXRsZTogIk1BVEgyMzQ5IFNlbWVzdGVyIDIsIDIwMTkiDQphdXRob3I6ICJIYXJkaSBXaW5hdGEgMzc5NDkwNSwgTWEuIENoYXJyaXogQW5uZSBSaW9mbG9yaWRvIDM3ODkxMTQsIEtlYXZhdGV5IFNydW4gMzc2NzYxNSINCnN1YnRpdGxlOiBBc3NpZ25tZW50IDMNCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KLS0tDQoNCiMjIFJlcXVpcmVkIHBhY2thZ2VzIA0KDQpBbGwgcmVxdWlyZWQgcGFja2FnZXMgZm9yIHRoZSBwcmVwcm9jZXNzaW5nIHN0ZXBzIGFyZSBsb2FkZWQuDQoNCmBgYHtyIH0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KDQojIyBFeGVjdXRpdmUgU3VtbWFyeSANCg0KVGhpcyByZXBvcnQgb3V0bGluZXMgdGhlIHN0ZXBzIHRha2VuIHRvIHByZS1wcm9jZXNzIHR3byByZWxhdGlvbmFsIGRhdGFzZXQgZG93bmxvYWRlZCBmcm9tIHRoZSBXb3JsZCBCYW5rIHdlYnNpdGUuIFRoZSBmaW5hbCBkYXRhc2V0IGNvbnRhaW5zIGluZm9ybWF0aW9uIGFib3V0IHRoZSBHRFAgYW5kIG5ldCBpbmZsb3cgb2YgRm9yZWlnbiBEaXJlY3QgSW52ZXN0bWVudCAoRkRJKSBmb3IgQVNFQU4gY291bnRyaWVzLCB3aGljaCB3aWxsIGJlIHVzZWQgZm9yIHRoZSBuZXh0IHN0ZXAgb2YgYW5hbHlzaXMgaW4gaW52ZXN0aWdhdGluZyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gR0RQIGFuZCBGREkuICANCiAgDQpGaXJzdGx5LCBlYWNoIHRhYmxlIHdhcyByZXNoYXBlZCBpbmRpdmlkdWFsbHkgYWNjb3JkaW5nIHRvIHRpZHkgZGF0YSBwcmluY2lwbGVzLCBiZWZvcmUgdGhleSB3ZXJlIG1lcmdlZC4gSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCB0aGUgY291bnRyaWVzIGluIHRoZSBHRFAgdGFibGUgd2VyZSBwcmlvcml0aXNlZCBkdXJpbmcgbWVyZ2luZyBhcyBuZXQgaW5mbG93IG9mIEZESSB3YXMgZXhwcmVzc2VkIGluIHBlcmNlbnRhZ2Ugb2YgdGhlIGNvdW50cnnigJlzIEdEUC4gVGhlIG5leHQgc3RlcCB3YXMgdG8gYXBwbHkgZGF0YSB0eXBlIGNvbnZlcnNpb25zLCB3aGVyZSBgQ291bnRyeSBOYW1lYCBhbmQgYHllYXJgIHdhcyBjb252ZXJ0ZWQgZnJvbSBgY2hhcmFjdGVyYCBpbnRvIGBmYWN0b3JgIGFuZCBvcmRlcmVkIGBmYWN0b3JgIHR5cGVzIHJlc3BlY3RpdmVseS4gVGhlIHRpZHkgZGF0YXNldCB3YXMgdGhlbiBmaWx0ZXJlZCB0byBvbmx5IGluY2x1ZGUgb2JzZXJ2YXRpb25zIGZyb20gdGVuIEFTRUFOIGNvdW50cmllcyBmcm9tIHRoZSB5ZWFyIDIwMDAgb253YXJkcyBhcyB0aGUgbGFzdCBtZW1iZXIgb2YgQVNFQU4gam9pbmVkIGluIDE5OTkuICANCiAgDQpUaGUgZmlsdGVyZWQgZGF0YXNldCB3YXMgc2Nhbm5lZCBmb3IgbWlzc2luZyB2YWx1ZXMgYW5kIHNwZWNpYWwgdmFsdWVzIChJbmZpbml0eSBhbmQgTmFOcykuIE9uZSBvYnNlcnZhdGlvbiBoYWQgbWlzc2luZyB2YWx1ZXMgaW4gdGhlbSwgd2hpY2ggd2FzIHJlbW92ZWQgYXMgaXQgaXMgYmVsb3cgdGhlIDUlIHRocmVzaG9sZC4gT3V0bGllcnMgd2VyZSBhbHNvIG9ic2VydmVkIHVwb24gZXhhbWluaW5nIHRoZSBkYXRhc2V0LiBIb3dldmVyLCB0aGUgZGVjaXNpb24gd2FzIHRvIGxlYXZlIGl0IGFzIGlzIGFzIHRoZXNlIHdlcmUgY29uc2lkZXJlZCB0byBiZSB2YWxpZCBwb2ludHMgd2hpY2ggY2FuIGJlIGV4cGxhaW5lZCBieSB0aGUgdmFyeWluZyBzdHJlbmd0aHMgb2YgZWFjaCBjb3VudHJ54oCZcyBlY29ub215Lg0KDQpUaGUgZmluYWwgc3RlcCBpbnZvbHZlcyBjaGVja2luZyB0aGUgZGlzdHJpYnV0aW9uIG9mIEdEUCBhbmQgbmV0IGluZmxvdyBvZiBGREkuIE1hdGhlbWF0aWNhbCBkYXRhIHRyYW5zZm9ybWF0aW9uIHRlY2huaXF1ZSB3YXMgYXBwbGllZCBpbiBhbiBhdHRlbXB0IG9mIGdldHRpbmcgdGhlIHZhcmlhYmxlcyB0byBtYXRjaCBhIG5vcm1hbCBkaXN0cmlidXRpb24uIEV2ZW4gdGhvdWdoIHRoZSB0cmFuc2Zvcm1lZCB2YXJpYWJsZXMgYXJlIG5vdCBwZXJmZWN0bHkgbm9ybWFsLCB0aGUgbWVhbiBhbmQgbWVkaWFuIG9mIGVhY2ggdmFyaWFibGUgYXJlIGNsb3NlLCB3aGljaCBtZWFucyB0aGF0IHRoZXkgYXJlIGNsb3NlIHRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gRnVydGhlcm1vcmUsIHRoZSBzYW1wbGUgc2l6ZSBpcyBsYXJnZSBlbm91Z2ggKG4gPiAzMCkgd2hlcmUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtIGNhbiBiZSBpbnZva2VkLiANCg0KIyMgRGF0YSANCg0KVGhlcmUgYXJlIHR3byBkYXRhc2V0cyBpbiB0aGlzIHJlcG9ydCwgd2hpY2ggaGFzIGJlZW4gZG93bmxvYWRlZCBmcm9tIHRoZSB3b3JsZGJhbmsgd2Vic2l0ZS4gVGhlIGZpcnN0IGRhdGFzZXQgY29udGFpbnMgaW5mb3JtYXRpb24gYWJvdXQgYSBjb3VudHJ5J3MgR0RQIGZyb20gMTk2MCB0byAyMDE4IGluIFVTIGRvbGxhcnMuIFRoZXJlIGFyZSA2MyB2YXJpYWJsZXMgaW4gdGhpcyBkYXRhc2V0OiAgDQogIC0gKipDb3VudHJ5IE5hbWUqKiAgDQogIC0gKipDb3VudHJ5IENvZGUqKiAoVW5pcXVlIGNvdW50cnkgY29kZSBnaXZlbiBieSBXb3JsZCBCYW5rKSAgDQogIC0gKipJbmRpY2F0b3IgTmFtZSoqIChUaGUgbmFtZSBvZiB0aGUgaW5kaWNhdG9yIGRlcGVuZGluZyBvbiB0aGUgZGF0YXNldCBmb3VuZCBvbiBXb3JsZCBCYW5rJ3Mgd2Vic2l0ZSkgIA0KICAtICoqSW5kaWNhdG9yIENvZGUqKiAoVW5pcXVlIGluZGljYXRvciBjb2RlKSAgDQogIC0gKipDb2x1bW4gNSB0byA2MyoqIGNvbnRhaW5zIHRoZSByZWNvcmRlZCBHRFAgb2YgZWFjaCBjb3VudHJ5IGZvciB0aGF0IHllYXIsIGxhYmVsbGVkIGFzIHRoZSB5ZWFyLiAgDQpgYGB7cn0NCiMgSW1wb3J0IGZ1bmN0aW9uDQogIGltcG9ydCA8LSBmdW5jdGlvbihmaWxlKXsNCiAgICByZWFkX3hsc3goZmlsZSwgc2hlZXQgPSAxLCBza2lwID0gMykNCn0NCg0KIyBJbXBvcnQgRkRJIGFuZCBHRFAgdGFibGVzDQogIGZpbGUgPC0gIkNvdW50cnkgRkRJLnhsc3giDQogIEZESSA8LSBpbXBvcnQoZmlsZSkNCg0KaGVhZChGREkpDQpgYGANCg0KVGhlIHNlY29uZCBkYXRhc2V0IGluY2x1ZGVzIGluZm9ybWF0aW9uIGFib3V0IG5ldCBpbmZsb3cgb2YgRm9yZWlnbiBEaXJlY3QgSW52ZXN0bWVudCAoRkRJKSBpbnRvIGRpZmZlcmVudCBjb3VudHJpZXMgd29ybGR3aWRlLCBleHByZXNzZWQgYXMgdGhlIHBlcmNlbnRhZ2Ugb2YgR0RQLiBGREkgbmV0IGluZmxvd3MgYXJlIHRoZSB2YWx1ZSBvZiBpbndhcmQgZGlyZWN0IGludmVzdG1lbnQgbWFkZSBieSBub24tcmVzaWRlbnQgaW52ZXN0b3JzIGluIHRoZSByZXBvcnRpbmcgZWNvbm9teS4gSXQgaXMgY2FsY3VsYXRlZCBhcyBuZXcgaW52ZXN0bWVudCBpbmZsb3dzIGxlc3MgZGlzaW52ZXN0bWVudHMgZnJvbSBmb3JlaWduIGludmVzdG9ycyBpbiBlYWNoIGVjb25vbXksIHdoaWNoIGlzIGZpbmFsbHkgZGl2aWRlZCBieSBHRFAgdG8gYmUgcmVwcmVzZW50ZWQgYXMgYSBwZXJjZW50YWdlIG9mIEdEUC4gTW9yZSBpbmZvcm1hdGlvbiBvbiBGREkgY2FuIGJlIGZvdW5kIGluIHRoZSBsaW5rIHByb3ZpZGVkIGluIHRoZSBSZWZlcmVuY2VzIHNlY3Rpb24gYmVsb3cuDQoNClRoZXJlIGFyZSBhbHNvIDYzIHZhcmlhYmxlcyBpbiB0aGlzIGRhdGFzZXQsIHdpdGggdGhlIHNhbWUgc3RydWN0dXJlIG91dGxpbmVkIGFib3ZlLiBUaGUgdHdvIGRhdGFzZXRzIGNhbiBiZSBjb25uZWN0ZWQgYnkgQ291bnRyeSBOYW1lIG9yIENvdW50cnkgQ29kZS4gVGhlIG5ldCBpbmZsb3cgb2YgRkRJIGNhbiBiZSBhIG5lZ2F0aXZlIG51bWJlciB3aGVuIG5ldyBmb3JlaWduIGludmVzdG1lbnQgaXMgbGVzcyB0aGFuIGRpc2ludmVzdG1lbnQgZm9yIHRoYXQgeWVhci4NCmBgYHtyfQ0KZmlsZSA8LSAiQ291bnRyeSBHRFAueGxzeCINCkdEUCA8LSBpbXBvcnQoZmlsZSkNCmhlYWQoR0RQKQ0KYGBgDQoNCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSSANCg0KQWNjb3JkaW5nIHRvIHRpZHkgZGF0YSBwcmluY2lwbGVzLCBlYWNoIHZhcmlhYmxlIHNob3VsZCBoYXZlIGl0cyBvd24gY29sdW1uIGFuZCB0aGUgY3VycmVudCBkYXRhc2V0IHZpb2xhdGVzIHRoYXQgcHJpbmNpcGxlIGFzIHRoZSB5ZWFycyBhcmUgc3ByZWFkIGFjcm9zcyBjb2x1bW4gNSB0byA2MyAoY29sdW1uIGhlYWRlcnMgYXMgdmFyaWFibGVzKS4gV2Ugd2lsbCBmaXJzdCByZXNoYXBlIHRoZSBkYXRhc2V0IGluZGl2aWR1YWxseSBiZWZvcmUgbWVyZ2luZyB0aGVtIHRvZ2V0aGVyIGJ5IGdhdGhlcmluZyBjb2x1bW4gNSB0byA2MyBpbnRvIGEgYHllYXJgIGNvbHVtbi4gDQpgYGB7cn0NCkZESV9jbGVhbiA8LSBGREkgJT4lIGdhdGhlcihrZXkgPSAieWVhciIsIHZhbHVlID0gIkZESV9wZXJjZW50IiwgNTo2MykNCkdEUF9jbGVhbiA8LSBHRFAgJT4lIGdhdGhlcihrZXkgPSAieWVhciIsIHZhbHVlID0gIkdEUCIsIDU6NjMpDQoNCmhlYWQoRkRJX2NsZWFuKQ0KaGVhZChHRFBfY2xlYW4pDQpgYGANCldpdGggdHdvIHRhYmxlcyBpbiBhIHRpZHkgZm9ybWF0LCB3ZSB3aWxsIG1lcmdlIHRoZSB0d28gdG9nZXRoZXIgdXNpbmcgdGhlIGBsZWZ0X2pvaW4oKWAgZnVuY3Rpb24sIHdpdGggdGhlIGBHRFBfY2xlYW5gIHRhYmxlIG9uIHRoZSBsZWZ0LiBUaGUgcmVhc29uIGZvciB1c2luZyBgbGVmdF9qb2luKClgIGlzIGJlY2F1c2Ugd2Ugb25seSB3YW50IHRvIHJldGFpbiBjb3VudHJpZXMgdGhhdCBoYXMgaXRzIEdEUCByZWNvcmRlZC4gU2luY2UgbmV0IEZESSBpbmZsb3cgaXMgZXhwcmVzc2VkIGluIHBlcmNlbnRhZ2Ugb2YgdGhlIGNvdW50cnkncyBHRFAsIHdlIGV4Y2x1ZGUgb2JzZXJ2YXRpb25zIHdoZXJlIGEgY291bnRyeSdzIG5ldCBGREkgaW5mbG93IGlzIHJlY29yZGVkLCBidXQgd2l0aG91dCB0aGUgY29ycmVzcG9uZGluZyBHRFAgaW5mb3JtYXRpb24gaW4gdGhlIGZpcnN0IHRhYmxlLiAgDQogIA0KVGhlIHRhYmxlcyB3aWxsIGJlIGpvaW5lZCBieSBgQ291bnRyeSBOYW1lYCwgYENvdW50cnkgQ29kZWAgYW5kIGB5ZWFyYCB0byBhdm9pZCBkdXBsaWNhdGlvbnMgb2YgdGhlc2UgY29sdW1ucyBpbiB0aGUgbWVyZ2VkIGRhdGFzZXQuIFdlIHdpbGwgYWxzbyBkcm9wIHJlZHVuZGFudCBjb2x1bW5zIGFmdGVyIG1lcmdpbmcuIA0KYGBge3J9DQplY29ub215IDwtIGxlZnRfam9pbihHRFBfY2xlYW4sIEZESV9jbGVhbiwgYnkgPSBjKCJDb3VudHJ5IE5hbWUiLCAiQ291bnRyeSBDb2RlIiwgInllYXIiKSkgDQogICANCmhlYWQoZWNvbm9teSkNCmVjb25vbXkgPC0gZWNvbm9teVssLWMoMiwzLDQsNyw4KV0NCg0KaGVhZChlY29ub215KQ0KYGBgDQoNCiMjIFVuZGVyc3RhbmQgDQoNCk5vdyB0aGF0IHRoZSBkYXRhc2V0IGlzIGluIGEgdGlkeSBmb3JtYXQsIHdlIHdpbGwgY29udGludWUgd2l0aCBkYXRhIHR5cGUgY29udmVyc2lvbnMuIFRoZSB2YXJpYWJsZXMgdGhhdCBoYXMgZ29uZSB0aHJvdWdoIGRhdGEgdHlwZSBjb252ZXJzaW9ucyBhcmU6ICANCiAgMS4gYENvdW50cnkgTmFtZWA6IENoYW5nZWQgZnJvbSBgY2hhcmFjdGVyYCB0byBgZmFjdG9yYC4gIA0KICAyLiBgeWVhcmA6IENoYW5nZWQgZnJvbSBgY2hhcmFjdGVyYCB0byBvcmRlcmVkIGBmYWN0b3JgICANCmBgYHtyfQ0KIyBDaGVjayB0aGUgZGF0YSBzdHJ1Y3R1cmUgb2YgZWNvbm9teSB0YWJsZSBiZWZvcmUgY29udmVyc2lvbg0KICBzdHIoZWNvbm9teSkNCg0KIyBBcHBseSBkYXRhIGNvbnZlcnNpb25zDQogIGNvdW50cnlfbGV2ZWwgPC0gdW5pcXVlKGVjb25vbXkkYENvdW50cnkgTmFtZWApDQogIGVjb25vbXkkYENvdW50cnkgTmFtZWAgPC0gZmFjdG9yKGVjb25vbXkkYENvdW50cnkgTmFtZWAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGNvdW50cnlfbGV2ZWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gY291bnRyeV9sZXZlbCkNCg0KICB5ZWFyIDwtIHNlcSgxOTYwLDIwMTgsIGJ5ID0gMSkNCiAgZWNvbm9teSR5ZWFyIDwtIGZhY3RvcihlY29ub215JHllYXIsDQogICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0geWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSB5ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKQ0KDQojIENoZWNrIHRoZSBkYXRhIHN0cnVjdHVyZSBvZiBlY29ub215IHRhYmxlIGFmdGVyIGNvbnZlcnNpb24NCiAgc3RyKGVjb25vbXkpDQpgYGANCg0KIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJSSANCg0KU2luY2Ugd2UgYXJlIG9ubHkgaW50ZXJlc3RlZCBpbiBjb3VudHJpZXMgdGhhdCBhcmUgbWVtYmVycyBvZiBBU0VBTiwgd2Ugd2lsbCBzdWJzZXQgdGhlIG1lcmdlZCBgZWNvbm9teWAgdGFibGUgdG8gaW5jbHVkZSBvbmx5IHRoZSBvYnNlcnZhdGlvbnMgb2YgdGhlIDEwIGNvdW50cmllcy4gVGhlIGRhdGFzZXQgaXMgYWxzbyBmaWx0ZXJlZCB0byB0aGUgeWVhciAyMDAwIG9ud2FyZHMgYXMgdGhlIGxhc3QgbWVtYmVyIG9mIEFTRUFOLCBDYW1ib2RpYSwgam9pbmVkIG9uICQzMF57dGh9JCBBcHJpbCAxOTk5Lg0KYGBge3J9DQplY29ub215X0FTRUFOPC0gZWNvbm9teSAlPiUgZmlsdGVyKGBDb3VudHJ5IE5hbWVgID09ICJDYW1ib2RpYSIgfA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYENvdW50cnkgTmFtZWAgPT0gIlBoaWxpcHBpbmVzIiB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQ291bnRyeSBOYW1lYCA9PSAiSW5kb25lc2lhIiB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQ291bnRyeSBOYW1lYCA9PSAiVGhhaWxhbmQiIHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBDb3VudHJ5IE5hbWVgID09ICJWaWV0bmFtIiB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQ291bnRyeSBOYW1lYCA9PSAiU2luZ2Fwb3JlIiB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQ291bnRyeSBOYW1lYCA9PSAiTWFsYXlzaWEiIHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBDb3VudHJ5IE5hbWVgID09ICJMYW8gUERSIiB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQ291bnRyeSBOYW1lYCA9PSAiQnJ1bmVpIERhcnVzc2FsYW0iIHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBDb3VudHJ5IE5hbWVgID09ICJNeWFubWFyIiwgeWVhciA+PTIwMDApDQojIENoZWNrIGRpbWVuc2lvbiBvZiBzdWJzZXQNCiAgZGltKGVjb25vbXlfQVNFQU4pDQpgYGANCg0KQWZ0ZXIgc3Vic2V0dGluZyB0aGUgZGF0YXNldCwgd2Ugd2lsbCBjcmVhdGUgdHdvIG5ldyB2YXJpYWJsZXM6ICANCiAgMS4gYEZESV92YWx1ZV9JbkJpbGxpb25zYDogRWFjaCBjb3VudHJ5J3MgbmV0IGluZmxvdyBGREkgZXhwcmVzc2VkIGluIGJpbGxpb25zIFVTJFwkJCAoYEZESV9wZXJjZW50YCAkXHRpbWVzJCBgR0RQYCkgIA0KICAyLiBgR0RQX3ZhbHVlX0luQmlsbGlvbnNgOiBFYWNoIGNvdW50cnkncyBHRFAgZXhwcmVzc2VkIGluIGJpbGxpb25zIFVTJFwkJCAoaW4gb3JkZXIgdG8gc2ltcGxpZnkgdGhlIHJlYWRpbmcgb2YgdGhlIG51bWJlcnMpICANCmBgYHtyfQ0KIyBNdXRhdGUgYSBuZXcgdmFyaWFibGUgYW5kIGNvbnZlcnQgdGhlIGFjdHVhbCB2YWx1ZXMgaW4gYmlsbGlvbnMNCiAgZWNvbm9teV9BU0VBTiA8LSBtdXRhdGUoZWNvbm9teV9BU0VBTiwgRkRJX3ZhbHVlX0luQmlsbGlvbnMgPQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIChlY29ub215X0FTRUFOJEZESV9wZXJjZW50KmVjb25vbXlfQVNFQU4kR0RQKS8xMDAwMDAwMDAwKQ0KICBlY29ub215X0FTRUFOIDwtIG11dGF0ZShlY29ub215X0FTRUFOLCBHRFBfdmFsdWVfSW5CaWxsaW9ucyA9IGVjb25vbXlfQVNFQU4kR0RQLzEwMDAwMDAwMDApDQogIGhlYWQoZWNvbm9teV9BU0VBTikNCmBgYA0KDQojIwlTY2FuIEkgDQoNClRoZSBuZXh0IHN0ZXAgd2lsbCBiZSB0byBzY2FuIGZvciBvYnZpb3VzIGVycm9ycywgbWlzc2luZyB2YWx1ZXMgYW5kIHNwZWNpYWwgdmFsdWVzIHdpdGhpbiB0aGUgZGF0YXNldC4gVGhlIHRvdGFsIG51bWJlciBvZiBtaXNzaW5nIHZhbHVlcyB3ZXJlIHRhbGxpZWQgZm9yIGVhY2ggY29sdW1uIGFuZCBvbmUgb2JzZXJ2YXRpb24gd2l0aCBtaXNzaW5nIHZhbHVlcyBoYXMgYmVlbiBpZGVudGlmaWVkLiAgDQpgYGB7cn0NCiMgU2NhbiBmb3IgbWlzc2luZyB2YWx1ZXMNCiAgY29sU3Vtcyhpcy5uYShlY29ub215X0FTRUFOKSkNCiAgd2hpY2goaXMubmEoZWNvbm9teV9BU0VBTiksIGFyci5pbmQgPSBUUlVFKQ0KICBlY29ub215X0FTRUFOWzEsXQ0KYGBgDQoNClNpbmNlIHRoZSBtaXNzaW5nIHZhbHVlIGlzIGxlc3MgdGhhbiA1JSBvZiB0aGUgZGF0YSwgd2UgY2FuIHNhZmVseSByZW1vdmUgdGhlIG9ic2VydmF0aW9uLg0KYGBge3J9DQogIChzdW0oaXMubmEoZWNvbm9teV9BU0VBTiRGRElfcGVyY2VudCkpIC8gbGVuZ3RoKGVjb25vbXlfQVNFQU4kRkRJX3BlcmNlbnQpKSoxMDANCiAgKHN1bShpcy5uYShlY29ub215X0FTRUFOJEZESV92YWx1ZV9JbkJpbGxpb25zKSkgLyBsZW5ndGgoZWNvbm9teV9BU0VBTiRGRElfdmFsdWVfSW5CaWxsaW9ucykpKjEwMA0KDQogIGVjb25vbXlfQVNFQU5fY2xlYW5lZCA8LSBlY29ub215X0FTRUFOW2NvbXBsZXRlLmNhc2VzKGVjb25vbXlfQVNFQU4pLF0NCiAgZGltKGVjb25vbXlfQVNFQU5fY2xlYW5lZCkNCmBgYA0KDQpTcGVjaWFsIHZhbHVlcyAoSW5maW5pdHksIE5hTnMpIGFuZCBpbmNvbnNpc3RlbmNpZXMgd2VyZSBhbHNvIGNoZWNrZWQgYW5kIG5vbmUgd2VyZSBmb3VuZCBpbiB0aGUgZGF0YXNldC4gQXMgbWVudGlvbmVkIGluIHByZXZpb3VzIHNlY3Rpb25zLCBuZXQgaW5mbG93IG9mIEZESSBjYW4gYmUgYSBuZWdhdGl2ZSBudW1iZXIsIHdoaWNoIGlzIHdoeSBpdCBpcyBub3QgY29uc2lkZXJlZCB0byBiZSBhbiBpbmNvbnNpc3RlbmN5IGluIHRoaXMgZGF0YXNldC4gVGhlcmVmb3JlLCB3ZSB3aWxsIGNoZWNrIGlmIHRoZXJlIGlzIGFueSB6ZXJvIGluIHRoZSBkYXRhc2V0IGFzIEZESSBhbmQgR0RQIGNhbm5vdCBiZSB6ZXJvIGluIHZhbHVlLg0KYGBge3J9DQojIFNjYW4gZm9yIHNwZWNpYWwgdmFsdWVzDQogIGlzLnNwZWNpYWwgPC0gZnVuY3Rpb24oeCl7IGlmIChpcy5udW1lcmljKHgpKSAoaXMuaW5maW5pdGUoeCkgfCBpcy5uYW4oeCkpIH0NCiAgc2FwcGx5KGVjb25vbXlfQVNFQU5fY2xlYW5lZCwgZnVuY3Rpb24oeCkgc3VtKCBpcy5zcGVjaWFsKHgpICkpDQpgYGANCg0KVGhlIHJlc3VsdCBzaG93IHRoZXJlIGlzIG5vIHplcm8gdmFsdWUgb2JzZXJ2ZWQgaW4gdGhlIGRhdGFzZXQuDQpgYGB7cn0NCiMgY2hlY2sgZm9yIGluY29uc2lzdGVuY2llcyBpbiB0aGUgZGF0YXNldA0KICB6ZXJvIDwtIGZ1bmN0aW9uKHgpe2lmIChpcy5udW1lcmljKHgpKSAoeCA9IDApfQ0KICBzYXBwbHkoZWNvbm9teV9BU0VBTl9jbGVhbmVkLCBmdW5jdGlvbih4KSBzdW0oemVybyh4KSkpDQpgYGANCg0KIyMJU2NhbiBJSQ0KDQpBZnRlciBleGFtaW5pbmcgYW5kIGhhbmRsaW5nIHRoZSBtaXNzaW5nIHZhbHVlcywgc3BlY2lhbCB2YWx1ZXMsIGFuZCBpbmNvbnNpc3RlbmNpZXMsIHRoZSBuZXh0IHN0ZXAgd2lsbCBiZSB0byBjaGVjayBmb3Igb3V0bGllcnMgaW4gdGhlIGRhdGFzZXQgdXNpbmcgYm94cGxvdC4NCmBgYHtyfQ0KR0RQX0EgPC0gZWNvbm9teV9BU0VBTl9jbGVhbmVkJEdEUF92YWx1ZV9JbkJpbGxpb25zDQpGRElfQSA8LSBlY29ub215X0FTRUFOX2NsZWFuZWQkRkRJX3ZhbHVlX0luQmlsbGlvbnMNCkZESV9wZXJjZW50X0EgPC0gZWNvbm9teV9BU0VBTl9jbGVhbmVkJEZESV9wZXJjZW50DQogIA0KYm94cGxvdChHRFBfQSwgbWFpbiA9ICJCb3hwbG90IG9mIEdEUCAoSW4gQmlsbGlvbnMpIiwgeGxhYiA9ICJHRFAgKEluIEJpbGxpb25zKSIpDQpib3hwbG90KEZESV9BLCBtYWluID0gIkJveHBsb3Qgb2YgRkRJIChJbiBCaWxsaW9ucykiLCB4bGFiID0gIkZESSAoSW4gQmlsbGlvbnMpIikNCmJveHBsb3QoRkRJX3BlcmNlbnRfQSwgbWFpbiA9ICJCb3hwbG90IG9mIEZESSAoSW4gUGVyY2VudCkiLCB4bGFiID0gIkZESSAoSW4gUGVyY2VudCkiKQ0KYGBgDQoNCkZyb20gdGhlIGJveHBsb3RzIGFib3ZlLCB3ZSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIG1hbnkgdW5pdmFyaWF0ZSBvdXRsaWVycyBpbiB0aGUgZGF0YXNldC4gSG93ZXZlciwgd2Ugd2lsbCBsZWF2ZSB0aGVzZSB2YWx1ZXMgYXMgaXMgYXMgdGhlc2UgYXJlIG1haW5seSBjYXVzZWQgYnkgdGhlIEdEUCBhbmQgbmV0IGluZmxvdyBvZiBGREkgZGlzcGFyaXR5IGJldHdlZW4gQVNFQU4gY291bnRyaWVzLCB3aGVyZWluIGVjb25vbWllcyBvZiBzb21lIG9mIHRoZXNlIGNvdW50cmllcyBwZXJmb3JtZWQgYmV0dGVyIChhcyBzaG93biBpbiB0aGUgYmFyIGNoYXJ0IGJlbG93KS4gSGVuY2UsIHRoZSBvdWx0aWVycyBhcmUgbm90IGRyaXZlbiBieSBhbnkgcG90ZW50aWFsIGVycm9ycyBpbiB0aGUgZGF0YS4NCmBgYHtyIHdhcm5pbmc9RkFMU0V9DQogIHBsb3QxIDwtIGdncGxvdChlY29ub215X0FTRUFOX2NsZWFuZWQsIGFlcyh4ID0gcmVvcmRlcihgQ291bnRyeSBOYW1lYCwgR0RQX3ZhbHVlX0luQmlsbGlvbnMpLCB5ID0gR0RQX3ZhbHVlX0luQmlsbGlvbnMsIGZpbGwgPSBgQ291bnRyeSBOYW1lYCkpDQoNCnBsb3QxICsgZ2VvbV9oaXN0b2dyYW0oc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICBnZ3RpdGxlKCJBU0VBTiBDb3VudHJpZXMnIFRvdGFsIEdEUCAoMjAwMC0yMDA1KSIpICsNCiAgeGxhYigiQ291bnRyaWVzIikgKw0KICB5bGFiKCJHRFAgKFVTIEJpbGxpb25zKSIpDQoNCiAgcGxvdDIgPC0gZ2dwbG90KGVjb25vbXlfQVNFQU5fY2xlYW5lZCwgYWVzKHggPSByZW9yZGVyKGBDb3VudHJ5IE5hbWVgLCBHRFBfdmFsdWVfSW5CaWxsaW9ucyksIHkgPSBGRElfdmFsdWVfSW5CaWxsaW9ucywgZmlsbCA9IGBDb3VudHJ5IE5hbWVgKSkNCg0KcGxvdDIgKyBnZW9tX2hpc3RvZ3JhbShzdGF0ID0gImlkZW50aXR5IikgKw0KICBjb29yZF9mbGlwKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArDQogIGdndGl0bGUoIkFTRUFOIENvdW50cmllcycgVG90YWwgRkRJIG5ldCBpbmZsb3cgKDIwMDAtMjAwNSkiKSArDQogIHhsYWIoIkNvdW50cmllcyIpICsNCiAgeWxhYigiTmV0IEZESSBpbmZsb3cgKFVTIEJpbGxpb25zKSIpDQpgYGANCg0KIyMJVHJhbnNmb3JtIA0KDQpTaW5jZSB3ZSBhcmUgcHJlLXByb2Nlc3NpbmcgdGhlIGRhdGEgd2l0aCB0aGUgaW50ZW50IG9mIHBlcmZvcm1pbmcgYSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gYmV0d2VlbiB0aGUgR0RQIGFuZCBGREksIHRoZSBub3JtYWxpdHkgb2YgYm90aCB2YXJpYWJsZXMgd2lsbCBiZSBjaGVja2VkIHVzaW5nIGEgaGlzdG9ncmFtLiBUaGUgY291bnRyaWVzJyBHRFAgd2lsbCBiZSBjaGVja2VkIGZpcnN0IGJlZm9yZSBtb3Zpbmcgb24gdG8gdGhlIG5ldCBpbmZsb3cgb2YgRkRJLg0KDQojIyMgR0RQIFRyYW5zZm9ybWF0aW9uDQoNCmBgYHtyfQ0KaGlzdChHRFBfQSwgbWFpbiA9ICJIaXN0cm9ncmFtIG9mIEdEUCAoaW4gYmlsbGlvbnMpIikNCmBgYA0KDQpVcG9uIGZpcnN0IGluc3BlY3Rpb24sIHdlIGNhbiBzZWUgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIEdEUCBmb3IgQVNFQU4gY291bnRyaWVzIGlzIHJpZ2h0IHNrZXdlZC4gTWF0aGVtYXRpY2FsIGRhdGEgdHJhbnNmb3JtYXRpb24gdGVjaG5pcXVlcyBoYXMgYmVlbiBhcHBsaWVkIGluIHRoZSBhdHRlbXB0IG9mIHRyYW5zZm9ybWluZyB0aGUgZGF0YSB0byBoYXZlIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4NCmBgYHtyfQ0KbG9nR0RQIDwtIGxvZzEwKEdEUF9BKQ0KaGlzdChsb2dHRFApDQpzdW1tYXJ5KGxvZ0dEUCkNCmBgYA0KDQpBZnRlciBhcHBseWluZyBkYXRhIHRyYW5zZm9ybWF0aW9uLCB0aGUgaGlzdG9ncmFtIG9mIGBsb2dHRFBgIHNob3dzIGEgYmV0dGVyIHNoYXBlLiBBbHRob3VnaCBpdCBpcyBub3QgcGVyZmVjdGx5IHN5bW1ldHJpYywgdGhlIEdEUCdzIG1lYW4gYW5kIG1lZGlhbiBiZWluZyB2ZXJ5IGNsb3NlIHRvZ2V0aGVyIGluZGljYXRlcyB0aGF0IGl0IGNhbiBiZSBjb25zaWRlcmVkIGNsb3NlIHRvIGFuIGFwcHJveGltYXRlbHkgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gRnVydGhlcm1vcmUsIHRoZSBzYW1wbGUgc2l6ZSBmb3IgdGhpcyBkYXRhc2V0IGlzIGdyZWF0ZXIgdGhhbiAzMCwgd2hpY2ggbWVhbnMgdGhhdCBDZW50cmFsIExpbWl0IFRoZW9yZW0gY2FuIGJlIGludm9rZWQgaW4gdGhlIGFuYWx5c2lzLiANCg0KIyMjIEZESSBUcmFuc2Zvcm1hdGlvbg0KDQpTaW1pbGFyIHRvIHRoZSBHRFAsIHNoYXBlIG9mIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIEZESSBpcyByaWdodC1za2V3ZWQuIE1hdGhlbWF0aWNhbCBkYXRhIHRyYW5zZm9ybWF0aW9uIGhhcyBiZWVuIGFwcGxpZWQgdG8gdHJhbnNmb3JtIHRoZSBkYXRhIHRvIGFwcHJveGltYXRlIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gU2luY2UgdGhlcmUgYXJlIG5lZ2F0aXZlIHZhbHVlcyBvYnNlcnZlZCBpbiB0aGUgRkRJIGFzIGV4cGxhaW5lZCBlYXJsaWVyLCBmaXJzdCBzdGVwIGlzIHRvIHRyYW5zZm9ybSBGREkgcmFpc2VkIHRvIHRoZSBwb3dlciBvZiA0IHRvIGFkZHJlc3MgdGhlIG5lZ2F0aXZlIHZhbHVlcy4gVGhlbiwgYGxvZzEwYCB0cmFuc2Zvcm1hdGlvbiBpcyBhcHBsaWVkLg0KDQpgYGB7cn0NCmhpc3QoRkRJX0EpDQpGRElfcG93ZXI0IDwtIEZESV9BXjQNCmxvZ0ZESSA8LSBsb2cxMChGRElfcG93ZXI0KQ0KaGlzdChsb2dGREkpDQpzdW1tYXJ5KGxvZ0ZESSkNCmBgYA0KDQpUaGUgaGlzdG9ncmFtIG9mIGBsb2dGRElgIGRvZXMgbm90IHNob3cgYSBwZXJmZWN0bHkgc3ltbWV0cmljYWwgZGlzdHJpYnV0aW9uLiBIb3dldmVyIHNhbWUgYXMgdGhlIGV4cGxhbmF0aW9uIG9uIHRoZSBHRFAncyB0cmFuc2Zvcm1hdGlvbiwgRkRJIGNhbiBiZSBjb25zaWRlcmVkIGNsb3NlIHRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiB3aXRoIHRoZSBtZWFuIGFuZCBtZWRpYW4gYmVpbmcgZmFpcmx5IGNsb3NlIHRvIGVhY2ggb3RoZXIgYW5kIHRoZSBzYW1wbGUgc2l6ZSBiZWluZyBsYXJnZSBlbm91Z2ggZm9yIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gdG8gYmUgYXBwbGllZC4NCg0KIyMJUmVmZXJlbmNlcw0KDQpGb3JlaWduIGRpcmVjdCBpbnZlc3RtZW50LCBuZXQgaW5mbG93cyAoJSBvZiBHRFApLiAoMjAxOSkuDQogICAgUmV0cmlldmVkIGZyb20gaHR0cHM6Ly9kYXRhLndvcmxkYmFuay5vcmcvaW5kaWNhdG9yL0JYLktMVC5ESU5WLldELkdELlpTP3ZpZXc9Y2hhcnQNCiAgICANCkdEUCAoY3VycmVudCBVUyQpLiAoMjAxOSkuIFJldHJpZXZlZCBmcm9tIA0KICAgIGh0dHBzOi8vZGF0YS53b3JsZGJhbmsub3JnL2luZGljYXRvci9OWS5HRFAuTUtUUC5DRD9uYW1lX2Rlc2M9ZmFsc2Umdmlldz1jaGFydA0KDQpLcmFtZXIsIEwuICgyMDE5KS4gV2hhdCBpcyBHRFAgYW5kIFdoeSBpcyBJdCBTbyBJbXBvcnRhbnQgdG8gRWNvbm9taXN0cyBhbmQgSW52ZXN0b3JzPy4gUmV0cmlldmVkIGZyb20gDQogICAgaHR0cHM6Ly93d3cuaW52ZXN0b3BlZGlhLmNvbS9hc2svYW5zd2Vycy93aGF0LWlzLWdkcC13aHktaXRzLWltcG9ydGFudC10by1lY29ub21pc3RzLWludmVzdG9ycy8NCg0KVGUgVmVsZGUsIEQuIFcuICgyMDA2KS4gRm9yZWlnbiBEaXJlY3QgSW52ZXN0bWVudCBhbmQgRGV2ZWxvcG1lbnQ6IEFuIEhpc3RvcmljYWwgUGVyc3BlY3RpdmUuIFJldHJpZXZlZCBmcm9tDQogICAgaHR0cHM6Ly93d3cub2RpLm9yZy9wdWJsaWNhdGlvbnMvNTk0LWZvcmVpZ24tZGlyZWN0LWludmVzdG1lbnQtZGV2ZWxvcG1lbnQtaGlzdG9yaWNhbC1wZXJzcGVjdGl2ZQ0KDQo=