
Rpubs link : http://rpubs.com/beancounter/430586
Motion Chart link: http://jasonperez.learningnomad.com/2018/10/suicide-rate-vs-gdp-motion-chart.html (only works with Internet Explorer browser)
Geomap link: http://jasonperez.learningnomad.com/2018/10/suicide-rate-per-country-geomap.html
Packages used
library(dplyr)
library(readr)
library(ggplot2)
library(tidyr)
library(MVN)
library(googleVis)
library(gridExtra)
Executive Summary
In order to come up with an understanding on whether suicide rates have a dependence on the country’s GDP, we have taken two sets of data from various sources. Prior to arriving to a conclusion, several data pre-processing have been done to come up with a clean data and be able to use it for visualisation and further analysis. Steps taken are identified below:
- Once the data are imported to R, it was initially checked and inspected the data by checking the structure, type, etc.
- Selected and filtered those variables that are only needed since not all of it are required for analysis and final results.
- Organised the data and transform it from wide to long format.
- Mutated or added new variable in the data frame.
- Merged the two data sets to come up with one data frame.
- The missing values were dropped and identified the outliers.
- Transformed the country’s GDP per capita using the \(log10\) function to normalise the values.
After doing the data pre-processing tasks, several visual representations have been shown. We can see on the graphics that there is a non-linear relationship between suicide cases/rates and the country’s GDP per capita. Several plots were presented and added statistical methods for analysis. On the other hand, there are some confounding variables why persons are committing suicide such as geographical weather (winter, summer, etc.), mental health issues or in a more contextual level such as cultural or spiritual aspects. Economic factor is one of the drivers also such as GDP. However, GDP is one of the many factors affecting suicide.
Lastly, it is good to note though that the suicide rate per country have been decreasing since people are becoming aware of the issue and the regular campaigns promoted by the charitable institutions plays a big role. If we know someone who needs help, talk to them. It may take a big difference, it may save someone’s lives.
Data
Suicide remains one of the leading causes of death in Australia aged between 15 and 44.\(^1\) This remains to be a problem in every country and considered to be a world phenomenon. Regardless of whether the country is rich or poor or how high or low the country’s living standards which all can be measured through GDP, no one is exempted on this global problem. Based on studies, about 90% of people who commit suicide have mental illness where depression is one of the top factors, however there are other mental health disorders that contribute to individual’s suicidal tendencies such as bipolar or schizophrenia.\(^2\).
In order to have an insights between suicide and GDP per country, two sets of data have been taken from various websites. The global data on suicide cases have been collected per country as well as the data about every country’s GDP. Suicide data cases included country, year (from 2000 to 2015), gender, age, number of suicide cases and population. The data about GDP per country included country and their GDP per year.
The suicide data have been taken from Kaggle, a public data platform which was originally sourced from WHO (World Health Organisation)\(^3\). On the other hand, the GDP data have been taken from World Bank Open Data \(^4\).
Limitations and Assumptions:
- The data included from 2000 to 2015 excluding years prior to 2000.
- Countries with complete data from year 2000 to 2015 with suicide cases and GDP data were only accounted and included on this analysis. There are countries that have missing data on a particular year or years. Missing values were identified but these are ignored in the analysis. However, there is a code used below in order to handle the missing values.
- Screenshots of the charts in googlevis are presented but you can see the interactive graphics in rpubs using the link. Make sure this is open in Internet Explorer as googlevis package works on Internet Explorer and NOT on Chrome or Microsoft Edge.
- Suicide cases are assumed to be normal and represented as the number of cases for every 100,000 population. However, the GDP per capita is calculated as the GDP amount divided by the population and then normalised using \(log10\) function.
- Age groups and genders are ignored in the summary for purposes of simplicity but these variables were used to show for tidying up the data, i.e., formatting, variable ordering, etc.
- Outliers are identified but remained to be included on the report as these are the actual reported statistics from the source. However, there are codes used in order to handle these outliers as shown below.
- The significance level is set to 0.05 and is assumed that there is a homogenity of variance in the selected countries taken.
- There are several functions that are created which can be useful in repetitive tasks for reporting/visualisation.
Understand
After importing the two data sets onto R, following are the steps taken to inspect, show the data structure and merge the data sets:
- Inspect the data structure and show the first 6 lines in the data frame.
- On the suicide data set, it selected those years from 2000 to 2015 and dropping the information prior to 2000.
- On the GDP data set, selected variables were taken only such as Country and the Year from 2000 to 2015.
- The \(gather\) function was used to create the selected year and used GDP as the value.
- Merged the two data set using \(left join\) using the Country Name/country as their primary key.
setwd("C:/Users/JP/Desktop/Analytics/Data Preprocessing/Assignment 3")
suicide_stats <- read.csv("who_suicide_statistics.csv") # Import the suicide statistics per country
head(suicide_stats) # Show the first 6 data information
str(suicide_stats) #Inspect the data structure
'data.frame': 40368 obs. of 6 variables:
$ country : Factor w/ 127 levels "Albania","Anguilla",..: 1 1 1 1 1 1 1 1 1 1 ...
$ year : int 1985 1985 1985 1985 1985 1985 1985 1985 1985 1985 ...
$ sex : int 2 2 2 2 2 2 1 1 1 1 ...
$ age : Factor w/ 6 levels "15-24 years",..: 1 2 3 4 5 6 1 2 3 4 ...
$ suicides_no: int NA NA NA NA NA NA NA NA NA NA ...
$ population : int 277900 246800 267500 298300 138700 34200 301400 264200 296700 325800 ...
suicide_stats_2000_to_2015 <- subset(suicide_stats, suicide_stats$year >= 2000) # Filter out data earlier than year 2000
gdp <- read.csv("w_gdp2.csv", header = TRUE, skip = 3, check.names = FALSE) # Import the world GDP
gdp1 <- gdp %>% select(`Country Name`, c("2000":"2015")) # Select only information needed
str(gdp1) # Inspect the data structure
'data.frame': 219 obs. of 17 variables:
$ Country Name: Factor w/ 219 levels "Afghanistan",..: 1 2 3 4 5 6 7 8 9 10 ...
$ 2000 : num NA 3.63e+09 5.48e+10 NA 1.43e+09 ...
$ 2001 : num 2.46e+09 4.06e+09 5.47e+10 NA 1.50e+09 ...
$ 2002 : num 4.13e+09 4.44e+09 5.68e+10 5.14e+08 1.73e+09 ...
$ 2003 : num 4.58e+09 5.75e+09 6.79e+10 5.27e+08 2.40e+09 ...
$ 2004 : num 5.29e+09 7.31e+09 8.53e+10 5.12e+08 2.94e+09 ...
$ 2005 : num 6.28e+09 8.16e+09 1.03e+11 5.03e+08 3.26e+09 ...
$ 2006 : num 7.06e+09 8.99e+09 1.17e+11 4.96e+08 3.54e+09 ...
$ 2007 : num 9.84e+09 1.07e+10 1.35e+11 5.20e+08 4.02e+09 ...
$ 2008 : num 1.02e+10 1.29e+10 1.71e+11 5.63e+08 4.01e+09 ...
$ 2009 : num 1.25e+10 1.20e+10 1.37e+11 6.78e+08 3.66e+09 ...
$ 2010 : num 1.59e+10 1.19e+10 1.61e+11 5.76e+08 3.36e+09 ...
$ 2011 : num 1.79e+10 1.29e+10 2.00e+11 5.74e+08 3.44e+09 ...
$ 2012 : num 2.05e+10 1.23e+10 2.09e+11 6.44e+08 3.16e+09 ...
$ 2013 : num 2.00e+10 1.28e+10 2.10e+11 6.41e+08 3.28e+09 ...
$ 2014 : num 2.01e+10 1.32e+10 2.14e+11 6.43e+08 3.35e+09 ...
$ 2015 : num 1.92e+10 1.13e+10 1.66e+11 6.59e+08 2.81e+09 ...
gdp2<- gdp1 %>% gather(c("2000":"2015"), key = "Year", value = "GDP") # Create a year column
suicide_gdp_country <- suicide_stats2000to2015_country %>%
left_join(gdp2, ., by = c("Country Name" = "country", "Year" = "year")) # Merged two datasets
Column `Country Name`/`country` joining factors with different levels, coercing to character vectorColumn `Year`/`year` joining character vector and factor, coercing into character vector
Tidy & Manipulate Data I
Following are some of the steps for tidying and manipulating data:
- Filtered the rows that are not missing or non zero values.
- Converted the year variable to factor.
- Factored the gender variable and labelled it accordingly.
suicide_stats_2000_to_2015_clean <- suicide_stats_2000_to_2015 %>%
filter(suicides_no != "NA" & suicides_no!=0) # Filter the rows that are not NA or zeroes
suicide_stats_2000_to_2015_clean[,"year"] <- as.factor(suicide_stats_2000_to_2015_clean[,"year"]) # Convert the year (int) to factor
levels(suicide_stats_2000_to_2015_clean$year)
[1] "2000" "2001" "2002" "2003" "2004" "2005" "2006" "2007" "2008" "2009" "2010"
[12] "2011" "2012" "2013" "2014" "2015" "2016"
suicide_stats_2000_to_2015_clean$sex <- suicide_stats_2000_to_2015_clean$sex %>% factor(c(1,2), labels = c("Male", "Female")) # Factor the gender
Tidy & Manipulate Data II
Some of the steps in tidying up and manipulating data are shown on the following:
- Aggregated the suicide cases and population per country per year.
- Added new variables using \(mutate\) function. The new variables are called Suicide_Rate, GDP_per_capita and the normalised GDP_per_capita_log.
- Selected variables to use on the analysis.
- Converted the year variable to numeric and rename the Country Name variable.
suicide_stats2000to2015_country <- aggregate(. ~country+year, data=suicide_stats_2000_to_2015_clean1, sum, na.rm=TRUE) # Aggregate the suicide cases and population
suicide_gdp_country_clean1 <- mutate(suicide_gdp_country_clean, Suicide_Rate = (suicides_no/population*100000), GDP_per_capita = (GDP/population), GDP_per_capita_log = log10(GDP/population) ) # Add Mortality rate, GDP per capita, GDP per capita log as new columns
suicide_stats_2000_to_2015_clean1 <- suicide_stats_2000_to_2015_clean %>% select(country, year, suicides_no, population) # Selected variables
suicide_gdp_country_clean1$Year <- as.numeric(as.character(suicide_gdp_country_clean1$Year)) # Converted year to numeric
colnames(suicide_gdp_country_clean1)[colnames(suicide_gdp_country_clean1)=="Country Name"] <- "Country" # Rename the variable
Scan I (Missing Values)
On the data frame, we have found out few missing values. We can identify the location of NAs but since there are a lot of items on the data frame, only the code has been shown. The sum of the total missing values in the data frame including on the columns have been identified.
All missing values have been intentionally omitted in the data frame as it was mentioned on the Limitations and Assumptions area that we are including only those countries that have full data of suicide cases and GDP data. Countries with incomplete data have been totally excluded. Although there are several methods of handling missing data such as imputation, it was opted to just exclude it due to its high sensitivity of the nature of data.
#which(is.na(suicide_gdp_country)) # Identify the location of NAs
sum(is.na(suicide_gdp_country)) # Sum up the total of NAs
[1] 4645
colSums(is.na(suicide_gdp_country)) # Identify the nuber of NAs in columns
Country Name Year GDP suicides_no population
0 0 253 2196 2196
suicide_gdp_country_clean <- na.omit(suicide_gdp_country) # Omit NAs in the data frame
Scan II (Outliers)
Several visual graphs have been shown below to show the presence of outliers. Even though one variable have been transformed, outliers are still present. Due to sensitivity of data and would like to present the actual data, countries with the full suicide and GDP data were presented. Although, there are several methods of handling outliers like imputing, capping or totally excluding it, those outliers identified were intentionally included since this report is heavily reliant on the data source. In real life though, this poses further investigation prior to any suggested action in handling outliers. This was also shown as one of the items in the Limitations and Assumptions of the study.
suicide_gdp_country_clean1 %>% boxplot(Suicide_Rate ~ Year, data = ., main="Boxplot of Suicide Rate", ylab = "Suicide Rate per 100,000", xlab = "Year", col="lightblue")
grid()

suicide_gdp_out <- suicide_gdp_country_clean1 %>% select(GDP_per_capita_log, Suicide_Rate)
suicide_gdp_out_Contour <- mvn(data = suicide_gdp_out, multivariateOutlierMethod = "quan", multivariatePlot = "contour")

grid()

Visualisation Part I
suicide_gdp_year <- suicide_gdp_country_clean1 %>% select(Year, Suicide_Rate, GDP_per_capita_log)
suicide_gdp_year1<- aggregate(. ~`Year`, data=suicide_gdp_year, sum)
plot(suicide_gdp_year1, col = "darkblue")

ggplot(suicide_gdp_country_clean1, aes(x = GDP_per_capita_log, y = Suicide_Rate)) + geom_jitter(alpha = 0.3) + geom_smooth(lwd = 0.85, alpha = 0.15) + ggtitle("Scatter Plot of Suicide Rate and GDP per Capita") # Scatter plot

ggplot(suicide_gdp_country_clean1, aes(x = GDP_per_capita_log, y = Suicide_Rate, colour = factor(Year))) + geom_line(alpha=0.5) + ggtitle("Plot of Yearly Suicide Rate and GDP per Capital") # Scatter plot

yearly_suicide <- ggplot(suicide_gdp_country_clean1, aes(x = Year, y = Suicide_Rate)) + geom_jitter() + geom_smooth(lwd = 2, se = FALSE, method = "lm") + ggtitle("Scatter Plot per Year") # Scatter plot per year
yearly_GDP <- ggplot(suicide_gdp_country_clean1, aes(x = Year, y = GDP_per_capita_log)) +geom_jitter() +geom_smooth(lwd = 2, se = FALSE, method = "lm") + ggtitle("Scatter Plot per Year") # Scatter plot per year
grid.arrange(yearly_suicide, yearly_GDP, ncol=2)

Visualisation part II (including the Functions created)
A couple of functions were created to either randomly select or specifically select a country. Few plots were shown to see the trend on suicide cases per year and also suicide and GDP per year. Lastly, the top 4 countries were presented alongside with some graphical presentations.
countries <- c("Argentina","Aruba","Austria","Belgium","Belize","Brazil","Brunei Darussalam","Chile","Colombia","Croatia","Cuba","Czech Republic","Denmark","Ecuador","Egypt, Arab Rep.","Estonia","Finland","Germany","Greece","Guatemala","Hong Kong SAR, China","Hungary","Iceland","Israel","Italy","Japan","Kazakhstan","Korea, Rep.","Kyrgyz Republic","Latvia","Lithuania","Luxembourg","Malta","Mauritius","Mexico","Moldova","Netherlands","Norway","Panama","Poland","Puerto Rico","Romania","Russian Federation","Serbia","Singapore","Slovenia","South Africa","Spain","Sweden","Switzerland","Turkmenistan","United Kingdom","United States")
selected_countries <- suicide_gdp_country_clean1 %>% filter(`Country`%in% countries)
plot_per_country <- function(i) {selected_countries %>% filter(`Country`== i) %>% ggplot(aes(Year,Suicide_Rate)) + geom_line(alpha=0.5)+ ggtitle(i)} # Function to check the suicide rate per country per country
plot_per_country("Brazil")

for(i in selected_countries$'Country'[c(800,816)]){
print(ggplot(filter(selected_countries, selected_countries$`Country`== i), aes(x = Year, y = Suicide_Rate)) + geom_line(alpha=0.5) + ggtitle(i)) # Function to check the suicide rate for multiple country per year
}


for(i in selected_countries$'Country'[c(814,832)]){
print(ggplot(filter(selected_countries, selected_countries$`Country`== i), aes(x = GDP_per_capita_log, y = Suicide_Rate)) + geom_line(alpha=0.5) + ggtitle(i)) # Function to check the suicide rate and GDP for multiple country per year
}


four_countries <- c("Korea, Rep.","Latvia","Lithuania","Slovenia") # Select the top 4 countries of suicide rate
top4_countries <- suicide_gdp_country_clean1 %>% filter(`Country`%in% four_countries) # Select the data for top 4 countries of suicide rate
top4_suicide <- ggplot(top4_countries, aes(x = Year, y = Suicide_Rate, colour = Country)) + geom_line(alpha=1) # Visualise top 4
top4_GDP <- ggplot(top4_countries, aes(x = Year, y = GDP_per_capita_log, colour = Country)) + geom_line(alpha=1) # Visualise top 4
grid.arrange(top4_suicide,top4_GDP, nrow = 2, ncol = 1)

top4_Suicide_GDP <- ggplot(top4_countries, aes(x = GDP_per_capita_log, y = Suicide_Rate, colour = Year)) + geom_line(alpha=1) + ggtitle("Suicide_GDP_Top4_countries")#
top4_Suicide_GDP # Visualise top 4

Visualisation using Motion Chart and Maps
In order to view the interactive charts particularly the motion chart using the googlevis package, you need to use the Internet Explorer browser. Take note that if you use Google Chrome, Firefox or Edge browsers, the motion chart would not work.
The codes used to create the visuals are shown below including the screenshots of the output of the reports.
The motion chart presents the suicide cases and GDP per year where the size of the circle/bubble represents the population. Alternatively, the map shows the geographical suicide cases per country which highlights the intensity level based on the number of cases. Links to view the interactive charts are shown below :
http://jasonperez.learningnomad.com/2018/10/suicide-rate-vs-gdp-motion-chart.html (Use Internet Explorer to view this)
http://jasonperez.learningnomad.com/2018/10/suicide-rate-per-country-geomap.html
data_motion <- gvisMotionChart(suicide_gdp_country_clean1, idvar = "Country", timevar = "Year", xvar = "GDP_per_capita_log", yvar = "Suicide_Rate", sizevar = "population")
plot(data_motion)
data_geomap <- gvisGeoChart(suicide_gdp_country_clean1, "Country", "Suicide_Rate",options=list(width=600, height=400))
suicide_gdp_country_clean2 <- suicide_gdp_country_clean1 %>% select(Country, Suicide_Rate) # Select the variable
data_table <- gvisTable(suicide_gdp_country_clean2, options=list(width=300, height=200)) # Show the data table
geomap_table <- gvisMerge(data_geomap, data_table, horizontal=TRUE) # Merged two data set
plot(geomap_table) # Plot



Statistical Conclusion
Using statistical tools, we can identify the average number of suicide cases based from the sampled countries. We can also run the regression using the \(lm\) function and the results are presented below. It was shown on the previous graphs that there is a non-linear relationship between the Suicide Rates and the Country’s GDP per capita. Based on the selected countries which we used as samples, it can be concluded that since p value (0.2412) is > 0.05, this means that the data used do not fit the linear regression model and can be assumed that there is no relationship between the Country’s Suicide Cases and the GDP per capita.
Although GDP does not in any way directly impact the suicide cases, this could be one of the many contextual reasons as it relates to economic aspects. However, based on this analysis, it is not statistically significant to support that GDP per capita of one’s country contributes to the suicide cases. There are a lot of confounding factors why people are taking suicide which are mentioned in the Executive Summary. If we take our part to resolve the issue, we could be saving the life of our friends, family, relatives or even a stranger.
summary(suicide_gdp_country_clean1$Suicide_Rate) # Summay statistics for Suicide Rate
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.05183 6.24922 11.81422 12.95302 18.29047 53.23583
summary(suicide_gdp_country_clean1$GDP_per_capita_log) # Summary statistics for normalised GDP
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.496 3.717 4.180 4.132 4.612 5.824
summary(suicide_gdp_country_clean1$GDP_per_capita) # Summary statistics for normalised GDP
Min. 1st Qu. Median Mean 3rd Qu. Max.
313.5 5216.9 15123.6 27267.4 40900.4 666228.4
summary(lm(suicide_gdp_country_clean1$GDP_per_capita_log~suicide_gdp_country_clean1$Suicide_Rate,data=suicide_gdp_country_clean1))
Call:
lm(formula = suicide_gdp_country_clean1$GDP_per_capita_log ~
suicide_gdp_country_clean1$Suicide_Rate, data = suicide_gdp_country_clean1)
Residuals:
Min 1Q Median 3Q Max
-1.63348 -0.41355 0.03416 0.48038 1.64644
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.104898 0.028251 145.300 <2e-16 ***
suicide_gdp_country_clean1$Suicide_Rate 0.002125 0.001813 1.173 0.241
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 0.567 on 1300 degrees of freedom
Multiple R-squared: 0.001056, Adjusted R-squared: 0.000288
F-statistic: 1.375 on 1 and 1300 DF, p-value: 0.2412
cor.test(suicide_gdp_country_clean1$GDP_per_capita_log, suicide_gdp_country_clean1$Suicide_Rate, method = "pearson")
Pearson's product-moment correlation
data: suicide_gdp_country_clean1$GDP_per_capita_log and suicide_gdp_country_clean1$Suicide_Rate
t = 1.1725, df = 1300, p-value = 0.2412
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
-0.02186329 0.08667626
sample estimates:
cor
0.03250232
LS0tDQp0aXRsZTogIk1BVEgyMzQ5IFNlbWVzdGVyIDIsIDIwMTgiDQphdXRob3I6ICJKYXNvbiBQZXJleiAtIFMzNzQ3OTQ2Ig0Kc3VidGl0bGU6IEFzc2lnbm1lbnQgMyAtIFN1aWNpZGUgYW5kIEdEUCBpbiBhIGdsb2JhbCB3b3JsZCAtIGlzIHRoZXJlIGEgY29ycmVsYXRpb24/DQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCi0tLQ0KDQohW10oQzovVXNlcnMvSlAvRGVza3RvcC9BbmFseXRpY3MvRGF0YSBQcmVwcm9jZXNzaW5nL0Fzc2lnbm1lbnQgMy9pbWFnZXMvc3VpY2lkZV9waWMuanBnKXsgd2lkdGg9MjAlIH0NCiFbXShDOi9Vc2Vycy9KUC9EZXNrdG9wL0FuYWx5dGljcy9EYXRhIFByZXByb2Nlc3NpbmcvQXNzaWdubWVudCAzL2ltYWdlcy9HRFBfcGljLmpwZyl7IHdpZHRoPTI0JSB9DQoNCg0KDQpScHVicyBsaW5rIDogaHR0cDovL3JwdWJzLmNvbS9iZWFuY291bnRlci80MzA1ODYgPGJyPg0KDQpNb3Rpb24gQ2hhcnQgbGluazogaHR0cDovL2phc29ucGVyZXoubGVhcm5pbmdub21hZC5jb20vMjAxOC8xMC9zdWljaWRlLXJhdGUtdnMtZ2RwLW1vdGlvbi1jaGFydC5odG1sIChvbmx5IHdvcmtzIHdpdGggSW50ZXJuZXQgRXhwbG9yZXIgYnJvd3NlcikgPGJyPg0KDQpHZW9tYXAgbGluazogaHR0cDovL2phc29ucGVyZXoubGVhcm5pbmdub21hZC5jb20vMjAxOC8xMC9zdWljaWRlLXJhdGUtcGVyLWNvdW50cnktZ2VvbWFwLmh0bWwgPGJyPg0KDQoNCiMjIFBhY2thZ2VzIHVzZWQgDQoNCg0KYGBge3J9DQoNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoTVZOKQ0KbGlicmFyeShnb29nbGVWaXMpDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCg0KYGBgDQoNCg0KIyMgRXhlY3V0aXZlIFN1bW1hcnkgDQoNCkluIG9yZGVyIHRvIGNvbWUgdXAgd2l0aCBhbiB1bmRlcnN0YW5kaW5nIG9uIHdoZXRoZXIgc3VpY2lkZSByYXRlcyBoYXZlIGEgZGVwZW5kZW5jZSBvbiB0aGUgY291bnRyeSdzIEdEUCwgd2UgaGF2ZSB0YWtlbiB0d28gc2V0cyBvZiBkYXRhIGZyb20gdmFyaW91cyBzb3VyY2VzLiBQcmlvciB0byBhcnJpdmluZyB0byBhIGNvbmNsdXNpb24sIHNldmVyYWwgZGF0YSBwcmUtcHJvY2Vzc2luZyBoYXZlIGJlZW4gZG9uZSB0byBjb21lIHVwIHdpdGggYSBjbGVhbiBkYXRhIGFuZCBiZSBhYmxlIHRvIHVzZSBpdCBmb3IgdmlzdWFsaXNhdGlvbiBhbmQgZnVydGhlciBhbmFseXNpcy4gU3RlcHMgdGFrZW4gYXJlIGlkZW50aWZpZWQgYmVsb3c6DQoNCjEuIE9uY2UgdGhlIGRhdGEgYXJlIGltcG9ydGVkIHRvIFIsIGl0IHdhcyBpbml0aWFsbHkgY2hlY2tlZCBhbmQgaW5zcGVjdGVkIHRoZSBkYXRhIGJ5IGNoZWNraW5nIHRoZSBzdHJ1Y3R1cmUsIHR5cGUsIGV0Yy4gPGJyPg0KMi4gU2VsZWN0ZWQgYW5kIGZpbHRlcmVkIHRob3NlIHZhcmlhYmxlcyB0aGF0IGFyZSBvbmx5IG5lZWRlZCBzaW5jZSBub3QgYWxsIG9mIGl0IGFyZSByZXF1aXJlZCBmb3IgYW5hbHlzaXMgYW5kIGZpbmFsIHJlc3VsdHMuICA8YnI+DQozLiBPcmdhbmlzZWQgdGhlIGRhdGEgYW5kIHRyYW5zZm9ybSBpdCBmcm9tIHdpZGUgdG8gbG9uZyBmb3JtYXQuIDxicj4NCjQuIE11dGF0ZWQgb3IgYWRkZWQgbmV3IHZhcmlhYmxlIGluIHRoZSBkYXRhIGZyYW1lLiA8YnI+DQo1LiBNZXJnZWQgdGhlIHR3byBkYXRhIHNldHMgdG8gY29tZSB1cCB3aXRoIG9uZSBkYXRhIGZyYW1lLiA8YnI+DQo2LiBUaGUgbWlzc2luZyB2YWx1ZXMgd2VyZSBkcm9wcGVkIGFuZCBpZGVudGlmaWVkIHRoZSBvdXRsaWVycy4gPGJyPg0KNy4gVHJhbnNmb3JtZWQgdGhlIGNvdW50cnkncyBHRFAgcGVyIGNhcGl0YSB1c2luZyB0aGUgJGxvZzEwJCBmdW5jdGlvbiB0byBub3JtYWxpc2UgdGhlIHZhbHVlcy4gPGJyPg0KDQpBZnRlciBkb2luZyB0aGUgZGF0YSBwcmUtcHJvY2Vzc2luZyB0YXNrcywgc2V2ZXJhbCB2aXN1YWwgcmVwcmVzZW50YXRpb25zIGhhdmUgYmVlbiBzaG93bi4gV2UgY2FuIHNlZSBvbiB0aGUgZ3JhcGhpY3MgdGhhdCB0aGVyZSBpcyBhIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gc3VpY2lkZSBjYXNlcy9yYXRlcyBhbmQgdGhlIGNvdW50cnkncyBHRFAgcGVyIGNhcGl0YS4gU2V2ZXJhbCBwbG90cyB3ZXJlIHByZXNlbnRlZCBhbmQgYWRkZWQgc3RhdGlzdGljYWwgbWV0aG9kcyBmb3IgYW5hbHlzaXMuIE9uIHRoZSBvdGhlciBoYW5kLCB0aGVyZSBhcmUgc29tZSBjb25mb3VuZGluZyB2YXJpYWJsZXMgd2h5IHBlcnNvbnMgYXJlIGNvbW1pdHRpbmcgc3VpY2lkZSBzdWNoIGFzIGdlb2dyYXBoaWNhbCB3ZWF0aGVyICh3aW50ZXIsIHN1bW1lciwgZXRjLiksIG1lbnRhbCBoZWFsdGggaXNzdWVzIG9yIGluIGEgbW9yZSBjb250ZXh0dWFsIGxldmVsIHN1Y2ggYXMgY3VsdHVyYWwgb3Igc3Bpcml0dWFsIGFzcGVjdHMuIEVjb25vbWljIGZhY3RvciBpcyBvbmUgb2YgdGhlIGRyaXZlcnMgYWxzbyBzdWNoIGFzIEdEUC4gSG93ZXZlciwgR0RQIGlzIG9uZSBvZiB0aGUgbWFueSBmYWN0b3JzIGFmZmVjdGluZyBzdWljaWRlLg0KDQpMYXN0bHksIGl0IGlzIGdvb2QgdG8gbm90ZSB0aG91Z2ggdGhhdCB0aGUgc3VpY2lkZSByYXRlIHBlciBjb3VudHJ5IGhhdmUgYmVlbiBkZWNyZWFzaW5nIHNpbmNlIHBlb3BsZSBhcmUgYmVjb21pbmcgYXdhcmUgb2YgdGhlIGlzc3VlIGFuZCB0aGUgcmVndWxhciBjYW1wYWlnbnMgcHJvbW90ZWQgYnkgdGhlIGNoYXJpdGFibGUgaW5zdGl0dXRpb25zIHBsYXlzIGEgYmlnIHJvbGUuIElmIHdlIGtub3cgc29tZW9uZSB3aG8gbmVlZHMgaGVscCwgdGFsayB0byB0aGVtLiBJdCBtYXkgdGFrZSBhIGJpZyBkaWZmZXJlbmNlLCBpdCBtYXkgc2F2ZSBzb21lb25lJ3MgbGl2ZXMuDQoNCg0KDQojIyBEYXRhIA0KDQpTdWljaWRlIHJlbWFpbnMgb25lIG9mIHRoZSBsZWFkaW5nIGNhdXNlcyBvZiBkZWF0aCBpbiBBdXN0cmFsaWEgYWdlZCBiZXR3ZWVuIDE1IGFuZCA0NC4kXjEkIFRoaXMgcmVtYWlucyB0byBiZSBhIHByb2JsZW0gaW4gZXZlcnkgY291bnRyeSBhbmQgY29uc2lkZXJlZCB0byBiZSBhIHdvcmxkIHBoZW5vbWVub24uIFJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGUgY291bnRyeSBpcyByaWNoIG9yIHBvb3Igb3IgaG93IGhpZ2ggb3IgbG93IHRoZSBjb3VudHJ5J3MgbGl2aW5nIHN0YW5kYXJkcyB3aGljaCBhbGwgY2FuIGJlIG1lYXN1cmVkIHRocm91Z2ggR0RQLCBubyBvbmUgaXMgZXhlbXB0ZWQgb24gdGhpcyBnbG9iYWwgcHJvYmxlbS4gQmFzZWQgb24gc3R1ZGllcywgYWJvdXQgOTAlIG9mIHBlb3BsZSB3aG8gY29tbWl0IHN1aWNpZGUgaGF2ZSBtZW50YWwgaWxsbmVzcyB3aGVyZSBkZXByZXNzaW9uIGlzIG9uZSBvZiB0aGUgdG9wIGZhY3RvcnMsIGhvd2V2ZXIgdGhlcmUgYXJlIG90aGVyIG1lbnRhbCBoZWFsdGggZGlzb3JkZXJzIHRoYXQgY29udHJpYnV0ZSB0byBpbmRpdmlkdWFsJ3Mgc3VpY2lkYWwgdGVuZGVuY2llcyBzdWNoIGFzIGJpcG9sYXIgIG9yIHNjaGl6b3BocmVuaWEuJF4yJC4gDQoNCkluIG9yZGVyIHRvIGhhdmUgYW4gaW5zaWdodHMgYmV0d2VlbiBzdWljaWRlIGFuZCBHRFAgcGVyIGNvdW50cnksIHR3byBzZXRzIG9mIGRhdGEgaGF2ZSBiZWVuIHRha2VuIGZyb20gdmFyaW91cyB3ZWJzaXRlcy4gVGhlIGdsb2JhbCBkYXRhIG9uIHN1aWNpZGUgY2FzZXMgaGF2ZSBiZWVuIGNvbGxlY3RlZCBwZXIgY291bnRyeSBhcyB3ZWxsIGFzIHRoZSBkYXRhIGFib3V0IGV2ZXJ5IGNvdW50cnkncyBHRFAuIFN1aWNpZGUgZGF0YSBjYXNlcyBpbmNsdWRlZCBjb3VudHJ5LCB5ZWFyIChmcm9tIDIwMDAgdG8gMjAxNSksIGdlbmRlciwgYWdlLCBudW1iZXIgb2Ygc3VpY2lkZSBjYXNlcyBhbmQgcG9wdWxhdGlvbi4gVGhlIGRhdGEgYWJvdXQgR0RQIHBlciBjb3VudHJ5IGluY2x1ZGVkIGNvdW50cnkgYW5kIHRoZWlyIEdEUCBwZXIgeWVhci4NCg0KVGhlIHN1aWNpZGUgZGF0YSBoYXZlIGJlZW4gdGFrZW4gZnJvbSBLYWdnbGUsIGEgcHVibGljIGRhdGEgcGxhdGZvcm0gd2hpY2ggd2FzIG9yaWdpbmFsbHkgc291cmNlZCBmcm9tIFdITyAoV29ybGQgSGVhbHRoIE9yZ2FuaXNhdGlvbikkXjMkLiBPbiB0aGUgb3RoZXIgaGFuZCwgdGhlIEdEUCBkYXRhIGhhdmUgYmVlbiB0YWtlbiBmcm9tIFdvcmxkIEJhbmsgT3BlbiBEYXRhICReNCQuDQoNCiMjIyNMaW1pdGF0aW9ucyBhbmQgQXNzdW1wdGlvbnM6IyMjIw0KDQoxLiBUaGUgZGF0YSBpbmNsdWRlZCBmcm9tIDIwMDAgdG8gMjAxNSBleGNsdWRpbmcgeWVhcnMgcHJpb3IgdG8gMjAwMC4NCjIuIENvdW50cmllcyB3aXRoIGNvbXBsZXRlIGRhdGEgZnJvbSB5ZWFyIDIwMDAgdG8gMjAxNSB3aXRoIHN1aWNpZGUgY2FzZXMgYW5kIEdEUCBkYXRhIHdlcmUgb25seSBhY2NvdW50ZWQgYW5kIGluY2x1ZGVkIG9uIHRoaXMgYW5hbHlzaXMuIFRoZXJlIGFyZSBjb3VudHJpZXMgdGhhdCBoYXZlIG1pc3NpbmcgZGF0YSBvbiBhIHBhcnRpY3VsYXIgeWVhciBvciB5ZWFycy4gTWlzc2luZyB2YWx1ZXMgd2VyZSBpZGVudGlmaWVkIGJ1dCB0aGVzZSBhcmUgaWdub3JlZCBpbiB0aGUgYW5hbHlzaXMuIEhvd2V2ZXIsIHRoZXJlIGlzIGEgY29kZSB1c2VkIGJlbG93IGluIG9yZGVyIHRvIGhhbmRsZSB0aGUgbWlzc2luZyB2YWx1ZXMuDQozLiBTY3JlZW5zaG90cyBvZiB0aGUgY2hhcnRzIGluIGdvb2dsZXZpcyBhcmUgcHJlc2VudGVkIGJ1dCB5b3UgY2FuIHNlZSB0aGUgaW50ZXJhY3RpdmUgZ3JhcGhpY3MgaW4gcnB1YnMgdXNpbmcgdGhlIGxpbmsuIE1ha2Ugc3VyZSB0aGlzIGlzIG9wZW4gaW4gSW50ZXJuZXQgRXhwbG9yZXIgYXMgZ29vZ2xldmlzIHBhY2thZ2Ugd29ya3Mgb24gSW50ZXJuZXQgRXhwbG9yZXIgYW5kIE5PVCBvbiBDaHJvbWUgb3IgTWljcm9zb2Z0IEVkZ2UuDQo0LiBTdWljaWRlIGNhc2VzIGFyZSBhc3N1bWVkIHRvIGJlIG5vcm1hbCBhbmQgcmVwcmVzZW50ZWQgYXMgdGhlIG51bWJlciBvZiBjYXNlcyBmb3IgZXZlcnkgMTAwLDAwMCBwb3B1bGF0aW9uLiBIb3dldmVyLCB0aGUgR0RQIHBlciBjYXBpdGEgaXMgY2FsY3VsYXRlZCBhcyB0aGUgR0RQIGFtb3VudCBkaXZpZGVkIGJ5IHRoZSBwb3B1bGF0aW9uIGFuZCB0aGVuIG5vcm1hbGlzZWQgdXNpbmcgJGxvZzEwJCBmdW5jdGlvbi4NCjUuIEFnZSBncm91cHMgYW5kIGdlbmRlcnMgYXJlIGlnbm9yZWQgaW4gdGhlIHN1bW1hcnkgZm9yIHB1cnBvc2VzIG9mIHNpbXBsaWNpdHkgYnV0IHRoZXNlIHZhcmlhYmxlcyB3ZXJlIHVzZWQgdG8gc2hvdyBmb3IgdGlkeWluZyB1cCB0aGUgZGF0YSwgaS5lLiwgZm9ybWF0dGluZywgdmFyaWFibGUgb3JkZXJpbmcsIGV0Yy4NCjYuIE91dGxpZXJzIGFyZSBpZGVudGlmaWVkIGJ1dCByZW1haW5lZCB0byBiZSBpbmNsdWRlZCBvbiB0aGUgcmVwb3J0IGFzIHRoZXNlIGFyZSB0aGUgYWN0dWFsIHJlcG9ydGVkIHN0YXRpc3RpY3MgZnJvbSB0aGUgc291cmNlLiBIb3dldmVyLCB0aGVyZSBhcmUgY29kZXMgdXNlZCBpbiBvcmRlciB0byBoYW5kbGUgdGhlc2Ugb3V0bGllcnMgYXMgc2hvd24gYmVsb3cuDQo3LiBUaGUgc2lnbmlmaWNhbmNlIGxldmVsIGlzIHNldCB0byAwLjA1IGFuZCBpcyBhc3N1bWVkIHRoYXQgdGhlcmUgaXMgYSBob21vZ2VuaXR5IG9mIHZhcmlhbmNlIGluIHRoZSBzZWxlY3RlZCBjb3VudHJpZXMgdGFrZW4uDQo4LiBUaGVyZSBhcmUgc2V2ZXJhbCBmdW5jdGlvbnMgdGhhdCBhcmUgY3JlYXRlZCB3aGljaCBjYW4gYmUgdXNlZnVsIGluIHJlcGV0aXRpdmUgdGFza3MgZm9yIHJlcG9ydGluZy92aXN1YWxpc2F0aW9uLg0KDQoNCg0KIyMgVW5kZXJzdGFuZCANCg0KQWZ0ZXIgaW1wb3J0aW5nIHRoZSB0d28gZGF0YSBzZXRzIG9udG8gUiwgZm9sbG93aW5nIGFyZSB0aGUgc3RlcHMgdGFrZW4gdG8gaW5zcGVjdCwgc2hvdyB0aGUgZGF0YSBzdHJ1Y3R1cmUgYW5kIG1lcmdlIHRoZSBkYXRhIHNldHM6DQoNCjEuIEluc3BlY3QgdGhlIGRhdGEgc3RydWN0dXJlIGFuZCBzaG93IHRoZSBmaXJzdCA2IGxpbmVzIGluIHRoZSBkYXRhIGZyYW1lLg0KMi4gT24gdGhlIHN1aWNpZGUgZGF0YSBzZXQsIGl0IHNlbGVjdGVkIHRob3NlIHllYXJzIGZyb20gMjAwMCB0byAyMDE1IGFuZCBkcm9wcGluZyB0aGUgaW5mb3JtYXRpb24gcHJpb3IgdG8gMjAwMC4NCjMuIE9uIHRoZSBHRFAgZGF0YSBzZXQsIHNlbGVjdGVkIHZhcmlhYmxlcyB3ZXJlIHRha2VuIG9ubHkgc3VjaCBhcyBDb3VudHJ5IGFuZCB0aGUgWWVhciBmcm9tIDIwMDAgdG8gMjAxNS4NCjQuIFRoZSAkZ2F0aGVyJCBmdW5jdGlvbiB3YXMgdXNlZCB0byBjcmVhdGUgdGhlIHNlbGVjdGVkIHllYXIgYW5kIHVzZWQgR0RQIGFzIHRoZSB2YWx1ZS4NCjUuIE1lcmdlZCB0aGUgdHdvIGRhdGEgc2V0IHVzaW5nICRsZWZ0IGpvaW4kIHVzaW5nIHRoZSBDb3VudHJ5IE5hbWUvY291bnRyeSBhcyB0aGVpciBwcmltYXJ5IGtleS4NCg0KDQoNCmBgYHtyfQ0Kc2V0d2QoIkM6L1VzZXJzL0pQL0Rlc2t0b3AvQW5hbHl0aWNzL0RhdGEgUHJlcHJvY2Vzc2luZy9Bc3NpZ25tZW50IDMiKQ0Kc3VpY2lkZV9zdGF0cyA8LSByZWFkLmNzdigid2hvX3N1aWNpZGVfc3RhdGlzdGljcy5jc3YiKSAjIEltcG9ydCB0aGUgc3VpY2lkZSBzdGF0aXN0aWNzIHBlciBjb3VudHJ5DQpoZWFkKHN1aWNpZGVfc3RhdHMpICMgU2hvdyB0aGUgZmlyc3QgNiBkYXRhIGluZm9ybWF0aW9uDQpzdHIoc3VpY2lkZV9zdGF0cykgI0luc3BlY3QgdGhlIGRhdGEgc3RydWN0dXJlDQpzdWljaWRlX3N0YXRzXzIwMDBfdG9fMjAxNSA8LSBzdWJzZXQoc3VpY2lkZV9zdGF0cywgc3VpY2lkZV9zdGF0cyR5ZWFyID49IDIwMDApICMgRmlsdGVyIG91dCBkYXRhIGVhcmxpZXIgdGhhbiB5ZWFyIDIwMDANCg0KZ2RwIDwtIHJlYWQuY3N2KCJ3X2dkcDIuY3N2IiwgaGVhZGVyID0gVFJVRSwgc2tpcCA9IDMsIGNoZWNrLm5hbWVzID0gRkFMU0UpICMgSW1wb3J0IHRoZSB3b3JsZCBHRFANCmdkcDEgPC0gZ2RwICU+JSBzZWxlY3QoYENvdW50cnkgTmFtZWAsIGMoIjIwMDAiOiIyMDE1IikpICMgU2VsZWN0IG9ubHkgaW5mb3JtYXRpb24gbmVlZGVkDQpzdHIoZ2RwMSkgIyBJbnNwZWN0IHRoZSBkYXRhIHN0cnVjdHVyZQ0KZ2RwMjwtIGdkcDEgJT4lIGdhdGhlcihjKCIyMDAwIjoiMjAxNSIpLCBrZXkgPSAiWWVhciIsIHZhbHVlID0gIkdEUCIpICMgQ3JlYXRlIGEgeWVhciBjb2x1bW4NCnN1aWNpZGVfZ2RwX2NvdW50cnkgPC0gc3VpY2lkZV9zdGF0czIwMDB0bzIwMTVfY291bnRyeSAlPiUgDQogIGxlZnRfam9pbihnZHAyLCAuLCBieSA9IGMoIkNvdW50cnkgTmFtZSIgPSAiY291bnRyeSIsICJZZWFyIiA9ICJ5ZWFyIikpICMgTWVyZ2VkIHR3byBkYXRhc2V0cw0KDQoNCmBgYA0KDQoNCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSSANCg0KRm9sbG93aW5nIGFyZSBzb21lIG9mIHRoZSBzdGVwcyBmb3IgdGlkeWluZyBhbmQgbWFuaXB1bGF0aW5nIGRhdGE6DQoNCjEuIEZpbHRlcmVkIHRoZSByb3dzIHRoYXQgYXJlIG5vdCBtaXNzaW5nIG9yIG5vbiB6ZXJvIHZhbHVlcy4NCjIuIENvbnZlcnRlZCB0aGUgeWVhciB2YXJpYWJsZSB0byBmYWN0b3IuDQozLiBGYWN0b3JlZCB0aGUgZ2VuZGVyIHZhcmlhYmxlIGFuZCBsYWJlbGxlZCBpdCBhY2NvcmRpbmdseS4NCg0KDQpgYGB7cn0NCg0Kc3VpY2lkZV9zdGF0c18yMDAwX3RvXzIwMTVfY2xlYW4gPC0gc3VpY2lkZV9zdGF0c18yMDAwX3RvXzIwMTUgJT4lIA0KICBmaWx0ZXIoc3VpY2lkZXNfbm8gIT0gIk5BIiAmIHN1aWNpZGVzX25vIT0wKSAjIEZpbHRlciB0aGUgcm93cyB0aGF0IGFyZSBub3QgTkEgb3IgemVyb2VzDQpzdWljaWRlX3N0YXRzXzIwMDBfdG9fMjAxNV9jbGVhblssInllYXIiXSA8LSBhcy5mYWN0b3Ioc3VpY2lkZV9zdGF0c18yMDAwX3RvXzIwMTVfY2xlYW5bLCJ5ZWFyIl0pICMgQ29udmVydCB0aGUgeWVhciAoaW50KSB0byBmYWN0b3INCmxldmVscyhzdWljaWRlX3N0YXRzXzIwMDBfdG9fMjAxNV9jbGVhbiR5ZWFyKQ0Kc3VpY2lkZV9zdGF0c18yMDAwX3RvXzIwMTVfY2xlYW4kc2V4IDwtIHN1aWNpZGVfc3RhdHNfMjAwMF90b18yMDE1X2NsZWFuJHNleCAlPiUgZmFjdG9yKGMoMSwyKSwgbGFiZWxzID0gYygiTWFsZSIsICJGZW1hbGUiKSkgIyBGYWN0b3IgdGhlIGdlbmRlcg0KDQoNCg0KYGBgDQoNCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSUkgDQoNClNvbWUgb2YgdGhlIHN0ZXBzIGluIHRpZHlpbmcgdXAgYW5kIG1hbmlwdWxhdGluZyBkYXRhIGFyZSBzaG93biBvbiB0aGUgZm9sbG93aW5nOg0KDQoxLiBBZ2dyZWdhdGVkIHRoZSBzdWljaWRlIGNhc2VzIGFuZCBwb3B1bGF0aW9uIHBlciBjb3VudHJ5IHBlciB5ZWFyLg0KMi4gQWRkZWQgbmV3IHZhcmlhYmxlcyB1c2luZyAkbXV0YXRlJCBmdW5jdGlvbi4gVGhlIG5ldyB2YXJpYWJsZXMgYXJlIGNhbGxlZCBTdWljaWRlX1JhdGUsIEdEUF9wZXJfY2FwaXRhIGFuZCB0aGUgbm9ybWFsaXNlZCBHRFBfcGVyX2NhcGl0YV9sb2cuDQozLiBTZWxlY3RlZCB2YXJpYWJsZXMgdG8gdXNlIG9uIHRoZSBhbmFseXNpcy4NCjQuIENvbnZlcnRlZCB0aGUgeWVhciB2YXJpYWJsZSB0byBudW1lcmljIGFuZCByZW5hbWUgdGhlIENvdW50cnkgTmFtZSB2YXJpYWJsZS4NCg0KDQoNCmBgYHtyfQ0Kc3VpY2lkZV9zdGF0czIwMDB0bzIwMTVfY291bnRyeSA8LSBhZ2dyZWdhdGUoLiB+Y291bnRyeSt5ZWFyLCBkYXRhPXN1aWNpZGVfc3RhdHNfMjAwMF90b18yMDE1X2NsZWFuMSwgc3VtLCBuYS5ybT1UUlVFKSAjIEFnZ3JlZ2F0ZSB0aGUgc3VpY2lkZSBjYXNlcyBhbmQgcG9wdWxhdGlvbg0Kc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjEgPC0gbXV0YXRlKHN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4sIFN1aWNpZGVfUmF0ZSA9IChzdWljaWRlc19uby9wb3B1bGF0aW9uKjEwMDAwMCksIEdEUF9wZXJfY2FwaXRhID0gKEdEUC9wb3B1bGF0aW9uKSwgR0RQX3Blcl9jYXBpdGFfbG9nID0gbG9nMTAoR0RQL3BvcHVsYXRpb24pICkgIyBBZGQgTW9ydGFsaXR5IHJhdGUsIEdEUCBwZXIgY2FwaXRhLCBHRFAgcGVyIGNhcGl0YSBsb2cgYXMgbmV3IGNvbHVtbnMNCnN1aWNpZGVfc3RhdHNfMjAwMF90b18yMDE1X2NsZWFuMSA8LSBzdWljaWRlX3N0YXRzXzIwMDBfdG9fMjAxNV9jbGVhbiAlPiUgc2VsZWN0KGNvdW50cnksIHllYXIsIHN1aWNpZGVzX25vLCBwb3B1bGF0aW9uKSAjIFNlbGVjdGVkIHZhcmlhYmxlcw0Kc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjEkWWVhciA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihzdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuMSRZZWFyKSkgIyBDb252ZXJ0ZWQgeWVhciB0byBudW1lcmljDQpjb2xuYW1lcyhzdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuMSlbY29sbmFtZXMoc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjEpPT0iQ291bnRyeSBOYW1lIl0gPC0gIkNvdW50cnkiICMgUmVuYW1lIHRoZSB2YXJpYWJsZQ0KDQpgYGANCg0KDQojIwlTY2FuIEkgKE1pc3NpbmcgVmFsdWVzKQ0KDQpPbiB0aGUgZGF0YSBmcmFtZSwgd2UgaGF2ZSBmb3VuZCBvdXQgZmV3IG1pc3NpbmcgdmFsdWVzLiBXZSBjYW4gaWRlbnRpZnkgdGhlIGxvY2F0aW9uIG9mIE5BcyBidXQgc2luY2UgdGhlcmUgYXJlIGEgbG90IG9mIGl0ZW1zIG9uIHRoZSBkYXRhIGZyYW1lLCBvbmx5IHRoZSBjb2RlIGhhcyBiZWVuIHNob3duLiBUaGUgc3VtIG9mIHRoZSB0b3RhbCBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgZGF0YSBmcmFtZSBpbmNsdWRpbmcgb24gdGhlIGNvbHVtbnMgaGF2ZSBiZWVuIGlkZW50aWZpZWQuIA0KDQpBbGwgbWlzc2luZyB2YWx1ZXMgaGF2ZSBiZWVuIGludGVudGlvbmFsbHkgb21pdHRlZCBpbiB0aGUgZGF0YSBmcmFtZSBhcyBpdCB3YXMgbWVudGlvbmVkIG9uIHRoZSBMaW1pdGF0aW9ucyBhbmQgQXNzdW1wdGlvbnMgYXJlYSB0aGF0IHdlIGFyZSBpbmNsdWRpbmcgb25seSB0aG9zZSBjb3VudHJpZXMgdGhhdCBoYXZlIGZ1bGwgZGF0YSBvZiBzdWljaWRlIGNhc2VzIGFuZCBHRFAgZGF0YS4gQ291bnRyaWVzIHdpdGggaW5jb21wbGV0ZSBkYXRhIGhhdmUgYmVlbiB0b3RhbGx5IGV4Y2x1ZGVkLiBBbHRob3VnaCB0aGVyZSBhcmUgc2V2ZXJhbCBtZXRob2RzIG9mIGhhbmRsaW5nIG1pc3NpbmcgZGF0YSBzdWNoIGFzIGltcHV0YXRpb24sIGl0IHdhcyBvcHRlZCB0byBqdXN0IGV4Y2x1ZGUgaXQgZHVlIHRvIGl0cyBoaWdoIHNlbnNpdGl2aXR5IG9mIHRoZSBuYXR1cmUgb2YgZGF0YS4NCg0KDQpgYGB7cn0NCiN3aGljaChpcy5uYShzdWljaWRlX2dkcF9jb3VudHJ5KSkgIyBJZGVudGlmeSB0aGUgbG9jYXRpb24gb2YgTkFzDQpzdW0oaXMubmEoc3VpY2lkZV9nZHBfY291bnRyeSkpICMgU3VtIHVwIHRoZSB0b3RhbCBvZiBOQXMNCmNvbFN1bXMoaXMubmEoc3VpY2lkZV9nZHBfY291bnRyeSkpICMgSWRlbnRpZnkgdGhlIG51YmVyIG9mIE5BcyBpbiBjb2x1bW5zDQpzdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuIDwtICBuYS5vbWl0KHN1aWNpZGVfZ2RwX2NvdW50cnkpICMgT21pdCBOQXMgaW4gdGhlIGRhdGEgZnJhbWUNCg0KDQpgYGANCg0KDQojIwlTY2FuIElJIChPdXRsaWVycykNCg0KU2V2ZXJhbCB2aXN1YWwgZ3JhcGhzIGhhdmUgYmVlbiBzaG93biBiZWxvdyB0byBzaG93IHRoZSBwcmVzZW5jZSBvZiBvdXRsaWVycy4gRXZlbiB0aG91Z2ggb25lIHZhcmlhYmxlIGhhdmUgYmVlbiB0cmFuc2Zvcm1lZCwgb3V0bGllcnMgYXJlIHN0aWxsIHByZXNlbnQuIER1ZSB0byBzZW5zaXRpdml0eSBvZiBkYXRhIGFuZCB3b3VsZCBsaWtlIHRvIHByZXNlbnQgdGhlIGFjdHVhbCBkYXRhLCBjb3VudHJpZXMgd2l0aCB0aGUgZnVsbCBzdWljaWRlIGFuZCBHRFAgZGF0YSB3ZXJlIHByZXNlbnRlZC4gQWx0aG91Z2gsIHRoZXJlIGFyZSBzZXZlcmFsIG1ldGhvZHMgb2YgaGFuZGxpbmcgb3V0bGllcnMgbGlrZSBpbXB1dGluZywgY2FwcGluZyBvciB0b3RhbGx5IGV4Y2x1ZGluZyBpdCwgdGhvc2Ugb3V0bGllcnMgaWRlbnRpZmllZCB3ZXJlIGludGVudGlvbmFsbHkgaW5jbHVkZWQgc2luY2UgdGhpcyByZXBvcnQgaXMgaGVhdmlseSByZWxpYW50IG9uIHRoZSBkYXRhIHNvdXJjZS4gSW4gcmVhbCBsaWZlIHRob3VnaCwgdGhpcyBwb3NlcyBmdXJ0aGVyIGludmVzdGlnYXRpb24gcHJpb3IgdG8gYW55IHN1Z2dlc3RlZCBhY3Rpb24gaW4gaGFuZGxpbmcgb3V0bGllcnMuIFRoaXMgd2FzIGFsc28gc2hvd24gYXMgb25lIG9mIHRoZSBpdGVtcyBpbiB0aGUgTGltaXRhdGlvbnMgYW5kIEFzc3VtcHRpb25zIG9mIHRoZSBzdHVkeS4NCg0KDQpgYGB7cn0NCnN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4xICU+JSBib3hwbG90KFN1aWNpZGVfUmF0ZSB+IFllYXIsIGRhdGEgPSAuLCBtYWluPSJCb3hwbG90IG9mIFN1aWNpZGUgUmF0ZSIsIHlsYWIgPSAiU3VpY2lkZSBSYXRlIHBlciAxMDAsMDAwIiwgeGxhYiA9ICJZZWFyIiwgY29sPSJsaWdodGJsdWUiKQ0KZ3JpZCgpDQoNCnN1aWNpZGVfZ2RwX291dCA8LSBzdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuMSAlPiUgc2VsZWN0KEdEUF9wZXJfY2FwaXRhX2xvZywgU3VpY2lkZV9SYXRlKQ0Kc3VpY2lkZV9nZHBfb3V0X0NvbnRvdXIgPC0gbXZuKGRhdGEgPSBzdWljaWRlX2dkcF9vdXQsIG11bHRpdmFyaWF0ZU91dGxpZXJNZXRob2QgPSAicXVhbiIsIG11bHRpdmFyaWF0ZVBsb3QgPSAgImNvbnRvdXIiKQ0KZ3JpZCgpDQoNCg0KYGBgDQoNCg0KIyMJVHJhbnNmb3JtIA0KDQpUaGUgR0RQIHBlciBjYXBpdGEgaXMgdHJhbnNmb3JtZWQgYnkgdXNpbmcgdGhlICRsb2cxMCQgZnVuY3Rpb24uIFRoZSBoaXN0b2dyYW0gYW5kIFFRIHBsb3QgYmVmb3JlIGFuZCBhZnRlciB0aGUgdHJhbnNmb3JtYXRpb24gaGF2ZSBiZWVuIHNob3duLg0KDQoNCmBgYHtyfQ0KcGFyKG1mcm93ID1jKDIsMikpDQpoaXN0KHN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4xJEdEUF9wZXJfY2FwaXRhLCBtYWluID0gIkdEUCBwZXIgQ2FwaXRhIiwgY29sID0gInJlZCIpDQpoaXN0KGxvZzEwKHN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4xJEdEUF9wZXJfY2FwaXRhKSwgbWFpbiA9ICJHRFAgcGVyIENhcGl0YSBOb3JtYWwiLCBjb2w9ImxpZ2h0Ymx1ZSIpDQpxcW5vcm0oc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjEkR0RQX3Blcl9jYXBpdGEsIG1haW4gPSAiUVEgUGxvdCBvZiBHRFAgcGVyIENhcGl0YSIpDQpxcW5vcm0oc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjEkR0RQX3Blcl9jYXBpdGFfbG9nLCBtYWluID0gIlFRIFBsb3Qgb2YgR0RQIHBlciBDYXBpdGEgTm9ybWFsIikNCg0KYGBgDQoNCiMjVmlzdWFsaXNhdGlvbiBQYXJ0IEkNCg0KYGBge3J9DQpzdWljaWRlX2dkcF95ZWFyIDwtIHN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4xICU+JSBzZWxlY3QoWWVhciwgU3VpY2lkZV9SYXRlLCBHRFBfcGVyX2NhcGl0YV9sb2cpDQpzdWljaWRlX2dkcF95ZWFyMTwtIGFnZ3JlZ2F0ZSguIH5gWWVhcmAsIGRhdGE9c3VpY2lkZV9nZHBfeWVhciwgc3VtKQ0KcGxvdChzdWljaWRlX2dkcF95ZWFyMSwgY29sID0gImRhcmtibHVlIikNCg0KDQpnZ3Bsb3Qoc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjEsIGFlcyh4ID0gR0RQX3Blcl9jYXBpdGFfbG9nLCB5ID0gU3VpY2lkZV9SYXRlKSkgKyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuMykgKyBnZW9tX3Ntb290aChsd2QgPSAwLjg1LCBhbHBoYSA9IDAuMTUpICsgZ2d0aXRsZSgiU2NhdHRlciBQbG90IG9mIFN1aWNpZGUgUmF0ZSBhbmQgR0RQIHBlciBDYXBpdGEiKSAjIFNjYXR0ZXIgcGxvdA0KZ2dwbG90KHN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4xLCBhZXMoeCA9IEdEUF9wZXJfY2FwaXRhX2xvZywgeSA9IFN1aWNpZGVfUmF0ZSwgY29sb3VyID0gZmFjdG9yKFllYXIpKSkgKyBnZW9tX2xpbmUoYWxwaGE9MC41KSArIGdndGl0bGUoIlBsb3Qgb2YgWWVhcmx5IFN1aWNpZGUgUmF0ZSBhbmQgR0RQIHBlciBDYXBpdGFsIikgIyBTY2F0dGVyIHBsb3QNCnllYXJseV9zdWljaWRlIDwtIGdncGxvdChzdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuMSwgYWVzKHggPSBZZWFyLCB5ID0gU3VpY2lkZV9SYXRlKSkgKyBnZW9tX2ppdHRlcigpICsgZ2VvbV9zbW9vdGgobHdkID0gMiwgc2UgPSBGQUxTRSwgbWV0aG9kID0gImxtIikgKyBnZ3RpdGxlKCJTY2F0dGVyIFBsb3QgcGVyIFllYXIiKSAjIFNjYXR0ZXIgcGxvdCBwZXIgeWVhcg0KeWVhcmx5X0dEUCA8LSBnZ3Bsb3Qoc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjEsIGFlcyh4ID0gWWVhciwgeSA9IEdEUF9wZXJfY2FwaXRhX2xvZykpICtnZW9tX2ppdHRlcigpICtnZW9tX3Ntb290aChsd2QgPSAyLCBzZSA9IEZBTFNFLCBtZXRob2QgPSAibG0iKSArIGdndGl0bGUoIlNjYXR0ZXIgUGxvdCBwZXIgWWVhciIpICMgU2NhdHRlciBwbG90IHBlciB5ZWFyDQpncmlkLmFycmFuZ2UoeWVhcmx5X3N1aWNpZGUsIHllYXJseV9HRFAsIG5jb2w9MikNCg0KDQoNCmBgYA0KIyMgVmlzdWFsaXNhdGlvbiBwYXJ0IElJIChpbmNsdWRpbmcgdGhlIEZ1bmN0aW9ucyBjcmVhdGVkKQ0KDQpBIGNvdXBsZSBvZiBmdW5jdGlvbnMgd2VyZSBjcmVhdGVkIHRvIGVpdGhlciByYW5kb21seSBzZWxlY3Qgb3Igc3BlY2lmaWNhbGx5IHNlbGVjdCBhIGNvdW50cnkuIEZldyBwbG90cyB3ZXJlIHNob3duIHRvIHNlZSB0aGUgdHJlbmQgb24gc3VpY2lkZSBjYXNlcyBwZXIgeWVhciBhbmQgYWxzbyBzdWljaWRlIGFuZCBHRFAgcGVyIHllYXIuIExhc3RseSwgdGhlIHRvcCA0IGNvdW50cmllcyB3ZXJlIHByZXNlbnRlZCBhbG9uZ3NpZGUgd2l0aCBzb21lIGdyYXBoaWNhbCBwcmVzZW50YXRpb25zLg0KDQpgYGB7cn0NCg0KY291bnRyaWVzIDwtIGMoIkFyZ2VudGluYSIsIkFydWJhIiwiQXVzdHJpYSIsIkJlbGdpdW0iLCJCZWxpemUiLCJCcmF6aWwiLCJCcnVuZWkgRGFydXNzYWxhbSIsIkNoaWxlIiwiQ29sb21iaWEiLCJDcm9hdGlhIiwiQ3ViYSIsIkN6ZWNoIFJlcHVibGljIiwiRGVubWFyayIsIkVjdWFkb3IiLCJFZ3lwdCwgQXJhYiBSZXAuIiwiRXN0b25pYSIsIkZpbmxhbmQiLCJHZXJtYW55IiwiR3JlZWNlIiwiR3VhdGVtYWxhIiwiSG9uZyBLb25nIFNBUiwgQ2hpbmEiLCJIdW5nYXJ5IiwiSWNlbGFuZCIsIklzcmFlbCIsIkl0YWx5IiwiSmFwYW4iLCJLYXpha2hzdGFuIiwiS29yZWEsIFJlcC4iLCJLeXJneXogUmVwdWJsaWMiLCJMYXR2aWEiLCJMaXRodWFuaWEiLCJMdXhlbWJvdXJnIiwiTWFsdGEiLCJNYXVyaXRpdXMiLCJNZXhpY28iLCJNb2xkb3ZhIiwiTmV0aGVybGFuZHMiLCJOb3J3YXkiLCJQYW5hbWEiLCJQb2xhbmQiLCJQdWVydG8gUmljbyIsIlJvbWFuaWEiLCJSdXNzaWFuIEZlZGVyYXRpb24iLCJTZXJiaWEiLCJTaW5nYXBvcmUiLCJTbG92ZW5pYSIsIlNvdXRoIEFmcmljYSIsIlNwYWluIiwiU3dlZGVuIiwiU3dpdHplcmxhbmQiLCJUdXJrbWVuaXN0YW4iLCJVbml0ZWQgS2luZ2RvbSIsIlVuaXRlZCBTdGF0ZXMiKQ0Kc2VsZWN0ZWRfY291bnRyaWVzIDwtIHN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4xICU+JSBmaWx0ZXIoYENvdW50cnlgJWluJSBjb3VudHJpZXMpDQpwbG90X3Blcl9jb3VudHJ5IDwtIGZ1bmN0aW9uKGkpIHtzZWxlY3RlZF9jb3VudHJpZXMgJT4lIGZpbHRlcihgQ291bnRyeWA9PSBpKSAlPiUgZ2dwbG90KGFlcyhZZWFyLFN1aWNpZGVfUmF0ZSkpICsgZ2VvbV9saW5lKGFscGhhPTAuNSkrIGdndGl0bGUoaSl9ICMgRnVuY3Rpb24gdG8gY2hlY2sgdGhlIHN1aWNpZGUgcmF0ZSBwZXIgY291bnRyeSBwZXIgY291bnRyeQ0KcGxvdF9wZXJfY291bnRyeSgiQnJhemlsIikNCg0KZm9yKGkgaW4gc2VsZWN0ZWRfY291bnRyaWVzJCdDb3VudHJ5J1tjKDgwMCw4MTYpXSl7DQogICAgcHJpbnQoZ2dwbG90KGZpbHRlcihzZWxlY3RlZF9jb3VudHJpZXMsIHNlbGVjdGVkX2NvdW50cmllcyRgQ291bnRyeWA9PSBpKSwgYWVzKHggPSBZZWFyLCB5ID0gU3VpY2lkZV9SYXRlKSkgKyBnZW9tX2xpbmUoYWxwaGE9MC41KSArIGdndGl0bGUoaSkpICMgRnVuY3Rpb24gdG8gY2hlY2sgdGhlIHN1aWNpZGUgcmF0ZSBmb3IgbXVsdGlwbGUgY291bnRyeSBwZXIgeWVhcg0KfQ0KZm9yKGkgaW4gc2VsZWN0ZWRfY291bnRyaWVzJCdDb3VudHJ5J1tjKDgxNCw4MzIpXSl7DQogICAgcHJpbnQoZ2dwbG90KGZpbHRlcihzZWxlY3RlZF9jb3VudHJpZXMsIHNlbGVjdGVkX2NvdW50cmllcyRgQ291bnRyeWA9PSBpKSwgYWVzKHggPSBHRFBfcGVyX2NhcGl0YV9sb2csIHkgPSBTdWljaWRlX1JhdGUpKSArIGdlb21fbGluZShhbHBoYT0wLjUpICsgZ2d0aXRsZShpKSkgIyBGdW5jdGlvbiB0byBjaGVjayB0aGUgc3VpY2lkZSByYXRlIGFuZCBHRFAgZm9yIG11bHRpcGxlIGNvdW50cnkgcGVyIHllYXINCn0NCmZvdXJfY291bnRyaWVzIDwtIGMoIktvcmVhLCBSZXAuIiwiTGF0dmlhIiwiTGl0aHVhbmlhIiwiU2xvdmVuaWEiKSAjIFNlbGVjdCB0aGUgdG9wIDQgIGNvdW50cmllcyBvZiBzdWljaWRlIHJhdGUNCnRvcDRfY291bnRyaWVzIDwtIHN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4xICU+JSBmaWx0ZXIoYENvdW50cnlgJWluJSBmb3VyX2NvdW50cmllcykgIyBTZWxlY3QgdGhlIGRhdGEgZm9yIHRvcCA0IGNvdW50cmllcyBvZiBzdWljaWRlIHJhdGUNCnRvcDRfc3VpY2lkZSA8LSBnZ3Bsb3QodG9wNF9jb3VudHJpZXMsIGFlcyh4ID0gWWVhciwgeSA9IFN1aWNpZGVfUmF0ZSwgY29sb3VyID0gQ291bnRyeSkpICsgZ2VvbV9saW5lKGFscGhhPTEpICMgVmlzdWFsaXNlIHRvcCA0DQp0b3A0X0dEUCA8LSBnZ3Bsb3QodG9wNF9jb3VudHJpZXMsIGFlcyh4ID0gWWVhciwgeSA9IEdEUF9wZXJfY2FwaXRhX2xvZywgY29sb3VyID0gQ291bnRyeSkpICsgZ2VvbV9saW5lKGFscGhhPTEpICMgVmlzdWFsaXNlIHRvcCA0DQpncmlkLmFycmFuZ2UodG9wNF9zdWljaWRlLHRvcDRfR0RQLCBucm93ID0gMiwgbmNvbCA9IDEpDQp0b3A0X1N1aWNpZGVfR0RQIDwtIGdncGxvdCh0b3A0X2NvdW50cmllcywgYWVzKHggPSBHRFBfcGVyX2NhcGl0YV9sb2csIHkgPSBTdWljaWRlX1JhdGUsIGNvbG91ciA9IFllYXIpKSArIGdlb21fbGluZShhbHBoYT0xKSArIGdndGl0bGUoIlN1aWNpZGVfR0RQX1RvcDRfY291bnRyaWVzIikjIA0KdG9wNF9TdWljaWRlX0dEUCAjIFZpc3VhbGlzZSB0b3AgNA0KDQoNCg0KYGBgDQoNCiMjVmlzdWFsaXNhdGlvbiB1c2luZyBNb3Rpb24gQ2hhcnQgYW5kIE1hcHMNCg0KSW4gb3JkZXIgdG8gdmlldyB0aGUgaW50ZXJhY3RpdmUgY2hhcnRzIHBhcnRpY3VsYXJseSB0aGUgbW90aW9uIGNoYXJ0IHVzaW5nIHRoZSBnb29nbGV2aXMgcGFja2FnZSwgeW91IG5lZWQgdG8gdXNlIHRoZSBJbnRlcm5ldCBFeHBsb3JlciBicm93c2VyLiBUYWtlIG5vdGUgdGhhdCBpZiB5b3UgdXNlIEdvb2dsZSBDaHJvbWUsIEZpcmVmb3ggb3IgRWRnZSBicm93c2VycywgdGhlIG1vdGlvbiBjaGFydCB3b3VsZCBub3Qgd29yay4gDQoNClRoZSBjb2RlcyB1c2VkIHRvIGNyZWF0ZSB0aGUgdmlzdWFscyBhcmUgc2hvd24gYmVsb3cgaW5jbHVkaW5nIHRoZSBzY3JlZW5zaG90cyBvZiB0aGUgb3V0cHV0IG9mIHRoZSByZXBvcnRzLg0KDQpUaGUgbW90aW9uIGNoYXJ0IHByZXNlbnRzIHRoZSBzdWljaWRlIGNhc2VzIGFuZCBHRFAgcGVyIHllYXIgd2hlcmUgdGhlIHNpemUgb2YgdGhlIGNpcmNsZS9idWJibGUgcmVwcmVzZW50cyB0aGUgcG9wdWxhdGlvbi4gQWx0ZXJuYXRpdmVseSwgdGhlIG1hcCBzaG93cyB0aGUgZ2VvZ3JhcGhpY2FsIHN1aWNpZGUgY2FzZXMgcGVyIGNvdW50cnkgd2hpY2ggaGlnaGxpZ2h0cyB0aGUgaW50ZW5zaXR5IGxldmVsIGJhc2VkIG9uIHRoZSBudW1iZXIgb2YgY2FzZXMuIExpbmtzIHRvIHZpZXcgdGhlIGludGVyYWN0aXZlIGNoYXJ0cyBhcmUgc2hvd24gYmVsb3cgOg0KDQpodHRwOi8vamFzb25wZXJlei5sZWFybmluZ25vbWFkLmNvbS8yMDE4LzEwL3N1aWNpZGUtcmF0ZS12cy1nZHAtbW90aW9uLWNoYXJ0Lmh0bWwgKFVzZSBJbnRlcm5ldCBFeHBsb3JlciB0byB2aWV3IHRoaXMpDQoNCmh0dHA6Ly9qYXNvbnBlcmV6LmxlYXJuaW5nbm9tYWQuY29tLzIwMTgvMTAvc3VpY2lkZS1yYXRlLXBlci1jb3VudHJ5LWdlb21hcC5odG1sIA0KDQoNCg0KYGBge3J9DQpkYXRhX21vdGlvbiA8LSBndmlzTW90aW9uQ2hhcnQoc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjEsIGlkdmFyID0gIkNvdW50cnkiLCB0aW1ldmFyID0gIlllYXIiLCB4dmFyID0gIkdEUF9wZXJfY2FwaXRhX2xvZyIsIHl2YXIgPSAiU3VpY2lkZV9SYXRlIiwgc2l6ZXZhciA9ICJwb3B1bGF0aW9uIikNCnBsb3QoZGF0YV9tb3Rpb24pDQoNCg0KZGF0YV9nZW9tYXAgPC0gZ3Zpc0dlb0NoYXJ0KHN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4xLCAiQ291bnRyeSIsICJTdWljaWRlX1JhdGUiLG9wdGlvbnM9bGlzdCh3aWR0aD02MDAsIGhlaWdodD00MDApKQ0Kc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjIgPC0gc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjEgJT4lIHNlbGVjdChDb3VudHJ5LCBTdWljaWRlX1JhdGUpICMgU2VsZWN0IHRoZSB2YXJpYWJsZQ0KZGF0YV90YWJsZSA8LSBndmlzVGFibGUoc3VpY2lkZV9nZHBfY291bnRyeV9jbGVhbjIsIG9wdGlvbnM9bGlzdCh3aWR0aD0zMDAsIGhlaWdodD0yMDApKSAjIFNob3cgdGhlIGRhdGEgdGFibGUNCmdlb21hcF90YWJsZSA8LSBndmlzTWVyZ2UoZGF0YV9nZW9tYXAsIGRhdGFfdGFibGUsIGhvcml6b250YWw9VFJVRSkgIyBNZXJnZWQgdHdvIGRhdGEgc2V0DQpwbG90KGdlb21hcF90YWJsZSkgIyBQbG90DQoNCmBgYA0KDQoNCg0KIVtdKEM6L1VzZXJzL0pQL0Rlc2t0b3AvQW5hbHl0aWNzL0RhdGEgUHJlcHJvY2Vzc2luZy9Bc3NpZ25tZW50IDMvaW1hZ2VzLzIwMDBfbW90aW9uLmpwZyl7IHdpZHRoPTQ1JSB9DQohW10oQzovVXNlcnMvSlAvRGVza3RvcC9BbmFseXRpY3MvRGF0YSBQcmVwcm9jZXNzaW5nL0Fzc2lnbm1lbnQgMy9pbWFnZXMvMjAwM19tb3Rpb24uanBnKXsgd2lkdGg9NDUlIH0NCg0KDQohW10oQzovVXNlcnMvSlAvRGVza3RvcC9BbmFseXRpY3MvRGF0YSBQcmVwcm9jZXNzaW5nL0Fzc2lnbm1lbnQgMy9pbWFnZXMvMjAwNl9tb3Rpb24uanBnKXsgd2lkdGg9NDUlIH0NCiFbXShDOi9Vc2Vycy9KUC9EZXNrdG9wL0FuYWx5dGljcy9EYXRhIFByZXByb2Nlc3NpbmcvQXNzaWdubWVudCAzL2ltYWdlcy8yMDA5X21vdGlvbi5qcGcpeyB3aWR0aD00NSUgfQ0KDQoNCg0KIVtdKEM6L1VzZXJzL0pQL0Rlc2t0b3AvQW5hbHl0aWNzL0RhdGEgUHJlcHJvY2Vzc2luZy9Bc3NpZ25tZW50IDMvaW1hZ2VzLzIwMTJfbW90aW9uLmpwZyl7IHdpZHRoPTQ1JSB9DQohW10oQzovVXNlcnMvSlAvRGVza3RvcC9BbmFseXRpY3MvRGF0YSBQcmVwcm9jZXNzaW5nL0Fzc2lnbm1lbnQgMy9pbWFnZXMvMjAxNV9tb3Rpb24uanBnKXsgd2lkdGg9NDUlIH0NCg0KDQohW10oQzovVXNlcnMvSlAvRGVza3RvcC9BbmFseXRpY3MvRGF0YSBQcmVwcm9jZXNzaW5nL0Fzc2lnbm1lbnQgMy9pbWFnZXMvbWFwX3RhYmxlLmpwZyl7IHdpZHRoPTEwMCUgfQ0KDQo8YnI+DQoNCiMjIFN0YXRpc3RpY2FsIENvbmNsdXNpb24NCg0KVXNpbmcgc3RhdGlzdGljYWwgdG9vbHMsIHdlIGNhbiBpZGVudGlmeSB0aGUgYXZlcmFnZSBudW1iZXIgb2Ygc3VpY2lkZSBjYXNlcyBiYXNlZCBmcm9tIHRoZSBzYW1wbGVkIGNvdW50cmllcy4gV2UgY2FuIGFsc28gcnVuIHRoZSByZWdyZXNzaW9uIHVzaW5nIHRoZSAkbG0kIGZ1bmN0aW9uIGFuZCB0aGUgcmVzdWx0cyBhcmUgcHJlc2VudGVkIGJlbG93LiBJdCB3YXMgc2hvd24gb24gdGhlIHByZXZpb3VzIGdyYXBocyB0aGF0IHRoZXJlIGlzIGEgbm9uLWxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgU3VpY2lkZSBSYXRlcyBhbmQgdGhlIENvdW50cnkncyBHRFAgcGVyIGNhcGl0YS4gQmFzZWQgb24gdGhlIHNlbGVjdGVkIGNvdW50cmllcyB3aGljaCB3ZSB1c2VkIGFzIHNhbXBsZXMsIGl0IGNhbiBiZSBjb25jbHVkZWQgdGhhdCBzaW5jZSBwIHZhbHVlICgwLjI0MTIpIGlzID4gMC4wNSwgdGhpcyBtZWFucyB0aGF0IHRoZSBkYXRhIHVzZWQgZG8gbm90IGZpdCB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgYW5kIGNhbiBiZSBhc3N1bWVkIHRoYXQgdGhlcmUgaXMgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIENvdW50cnkncyBTdWljaWRlIENhc2VzIGFuZCB0aGUgR0RQIHBlciBjYXBpdGEuIA0KDQpBbHRob3VnaCBHRFAgZG9lcyBub3QgaW4gYW55IHdheSBkaXJlY3RseSBpbXBhY3QgdGhlIHN1aWNpZGUgY2FzZXMsIHRoaXMgY291bGQgYmUgb25lIG9mIHRoZSBtYW55IGNvbnRleHR1YWwgcmVhc29ucyBhcyBpdCByZWxhdGVzIHRvIGVjb25vbWljIGFzcGVjdHMuIEhvd2V2ZXIsIGJhc2VkIG9uIHRoaXMgYW5hbHlzaXMsIGl0IGlzIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IHRvIHN1cHBvcnQgdGhhdCBHRFAgcGVyIGNhcGl0YSBvZiBvbmUncyBjb3VudHJ5IGNvbnRyaWJ1dGVzIHRvIHRoZSBzdWljaWRlIGNhc2VzLiBUaGVyZSBhcmUgYSBsb3Qgb2YgY29uZm91bmRpbmcgZmFjdG9ycyB3aHkgcGVvcGxlIGFyZSB0YWtpbmcgc3VpY2lkZSB3aGljaCBhcmUgbWVudGlvbmVkIGluIHRoZSBFeGVjdXRpdmUgU3VtbWFyeS4gSWYgd2UgdGFrZSBvdXIgcGFydCB0byByZXNvbHZlIHRoZSBpc3N1ZSwgd2UgY291bGQgYmUgc2F2aW5nIHRoZSBsaWZlIG9mIG91ciBmcmllbmRzLCBmYW1pbHksIHJlbGF0aXZlcyBvciBldmVuIGEgc3RyYW5nZXIuDQoNCmBgYHtyfQ0Kc3VtbWFyeShzdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuMSRTdWljaWRlX1JhdGUpICMgU3VtbWF5IHN0YXRpc3RpY3MgZm9yIFN1aWNpZGUgUmF0ZQ0Kc3VtbWFyeShzdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuMSRHRFBfcGVyX2NhcGl0YV9sb2cpICMgU3VtbWFyeSBzdGF0aXN0aWNzIGZvciBub3JtYWxpc2VkIEdEUA0Kc3VtbWFyeShzdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuMSRHRFBfcGVyX2NhcGl0YSkgIyBTdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIG5vcm1hbGlzZWQgR0RQDQpzdW1tYXJ5KGxtKHN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4xJEdEUF9wZXJfY2FwaXRhX2xvZ35zdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuMSRTdWljaWRlX1JhdGUsZGF0YT1zdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuMSkpDQpjb3IudGVzdChzdWljaWRlX2dkcF9jb3VudHJ5X2NsZWFuMSRHRFBfcGVyX2NhcGl0YV9sb2csIHN1aWNpZGVfZ2RwX2NvdW50cnlfY2xlYW4xJFN1aWNpZGVfUmF0ZSwgbWV0aG9kID0gInBlYXJzb24iKQ0KDQpgYGANCg0KIyMgUmVmZXJlbmNlcw0KDQokXjEkIEF1c3RyYWxpYW4gQnVyZWF1IG9mIFN0YXRpc3RpY3MuICgyMDE2KS4gQ2F1c2VzIG9mIERlYXRoLCBBdXN0cmFsaWEgMjAxNSwgcHJlbGltaW5hcnkgZGF0YS4sIENhdC4gbm8uICgzMzAzLjApLiBDYW5iZXJyYTogQUJTLiA8YnI+DQokXjIkIGh0dHBzOi8vd3d3LmhlYWx0aGxpbmUuY29tL2hlYWx0aC9zdWljaWRlLWFuZC1zdWljaWRhbC1iZWhhdmlvciA8YnI+DQokXjMkIGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vc3phbWlsL3doby1zdWljaWRlLXN0YXRpc3RpY3MgPGJyPg0KJF40JCBodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy9pbmRpY2F0b3IvTlkuR0RQLlBDQVAuQ04/bG9jYXRpb25zPTFXIDxicj4NClN1aWNpZGUgSW1hZ2UgaHR0cDovL2VuLnJlYWwtc2NpZW5jZXMuY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDE2LzA2L21heHJlc2RlZmF1bHQtMi5qcGcgPGJyPg0KR0RQIEltYWdlIGh0dHA6Ly9iYW9jaGluaHBodS52bi8vVXBsb2FkZWQvYnVpdGh1aHVvbmcvMjAxOF8wMl8xNi9nZHBfanBnMl9TRUNZLmpwZyA8YnI+DQoNCg0KDQoNCjxicj4NCjxicj4=