Required packages
# This is the R chunk for the required packages
library(readr)
library(tidyr)
library(dplyr)
library(magrittr)
library(outliers)
library(forecast)
Executive Summary
Data preprocessing was performed on a dataset containing information on the happiness score and unemployment rate in different countries in 2016, in an attempt to investigate their correlations with a range of factors including income groups, regions and country’s GDP per Capita.
The data wraggling process started was commenced by importing the dataset of world happiness report in 2016, as well as the world bank unemployment rate (1960-2019) dataset. Then these datasets were prefiltered by selecting the relevant variables, mering and forming of a new, tidy dataframe for further manipulation.
Then the new dataframe structure was checked for a better understanding of the variables, with the proper data type conversions performed. Further scanning of the numeric variables (unemployment rate, happy score, GDP per Capita) in the dataset was performed to check missing values, special values and outliers. Finally, data transformation was perfromed to transform non-symetrically distributed varaiables to normally distributed ones.
Data
The frist data is the World Happiness Report in 2016 downloaded from https://www.kaggle.com/unsdsn/world-happiness?select=2016.csv, with a license of CC0: Public Domain. The report ranks 155 countries by their happiness levels based on a range of factors including their economy (GDP per Capita), freedom, health etc. The data is a tidy data set since each variable has its own column, each observation has its own row and each value has its own cell.
The second data and the third datasets were World Bank Unemployment Data (1960-2019) downloaded from https://data.worldbank.org/indicator/SL.UEM.TOTL.NE.ZS with a World Bank Dataset license. The second dataset was the unemployment rate% reported in countries over years. The third dataset was information on the countries included in dataset2, such as the country’s code, name, region and income groups.The data set was untidy because a number of varaiables from “1960” to “2019” representing the year should be values of a new variable “year”, rather than being column names themselved. Data manipulation was not performed here since only the result in 2016 was the interest of this invesitgation. However, if this dataset was to be used for other purposed, this dataset needed to be reshaped using the dyplr gather() function using the follwoing command: gather (dataset, key = “year”, value = “unemployment rate”, ‘1960’:‘2019’)
# This is the R chunk for the Data Section
happy_2016<-read_csv("Happiness_world.csv")
Parsed with column specification:
cols(
Country = [31mcol_character()[39m,
Region = [31mcol_character()[39m,
`Happiness Rank` = [32mcol_double()[39m,
`Happiness Score` = [32mcol_double()[39m,
`Lower Confidence Interval` = [32mcol_double()[39m,
`Upper Confidence Interval` = [32mcol_double()[39m,
`Economy (GDP per Capita)` = [32mcol_double()[39m,
Family = [32mcol_double()[39m,
`Health (Life Expectancy)` = [32mcol_double()[39m,
Freedom = [32mcol_double()[39m,
`Trust (Government Corruption)` = [32mcol_double()[39m,
Generosity = [32mcol_double()[39m,
`Dystopia Residual` = [32mcol_double()[39m
)
dfunemploy<-read_csv("Unemployment_world.csv")
Parsed with column specification:
cols(
.default = col_logical(),
`Country Name` = [31mcol_character()[39m,
`Country Code` = [31mcol_character()[39m,
`Indicator Name` = [31mcol_character()[39m,
`Indicator Code` = [31mcol_character()[39m,
`1991` = [32mcol_double()[39m,
`1992` = [32mcol_double()[39m,
`1993` = [32mcol_double()[39m,
`1994` = [32mcol_double()[39m,
`1995` = [32mcol_double()[39m,
`1996` = [32mcol_double()[39m,
`1997` = [32mcol_double()[39m,
`1998` = [32mcol_double()[39m,
`1999` = [32mcol_double()[39m,
`2000` = [32mcol_double()[39m,
`2001` = [32mcol_double()[39m,
`2002` = [32mcol_double()[39m,
`2003` = [32mcol_double()[39m,
`2004` = [32mcol_double()[39m,
`2005` = [32mcol_double()[39m,
`2006` = [32mcol_double()[39m
# ... with 13 more columns
)
See spec(...) for full column specifications.
dfcountry <- read_csv("Country_world.csv")
Parsed with column specification:
cols(
`Country Code` = [31mcol_character()[39m,
Region = [31mcol_character()[39m,
IncomeGroup = [31mcol_character()[39m,
SpecialNotes = [31mcol_character()[39m,
TableName = [31mcol_character()[39m
)
head(happy_2016)
head(dfunemploy)
head(dfcountry)
Tidy & Manipulate Data I
Select relevant columns from each dataset. Only the variables required for further analysis will be selected to form a new dataset.
Mutate join is used to merge the datasets to form a new one.
# This is the R chunk for the Tidy & Manipulate Data I
#select data for 2016 from the datasets for further analysis
happy_2016 <- happy_2016 %>% select(c("Country", "Happiness Score", "Happiness Rank", "Economy (GDP per Capita)"))
unemploy_2016 <- dfunemploy %>% select(c("Country Name", "Country Code", "2016"))
dfcountry <- dfcountry %>% select(c("Country Code", "Region", "IncomeGroup"))
#perform inner join on these three datasets by country name;
df <- unemploy_2016 %>% left_join(dfcountry, by = "Country Code") %>% inner_join(happy_2016, by = c("Country Name" = "Country"))
head(df)
Tidy & Manipulate Data II
Assign new column names to the formed dataset; Arrange the unemployment rate of all countries and find their ranking - create a new column called unemployment_rank; This will be used for further analysis along with the happiness score ranking of countries
colnames(df) <- c("Country", "Country_code", "Unemployment_rate", "Region","Income_group", "Happy_rank", "Happy_score", "GDPperCapita")
df <- df %>% arrange(Unemployment_rate) %>% mutate(Unemployment_rank =row_number ())
df <- df %>% select(c("Country", "Region","Income_group","GDPperCapita", "Happy_score", "Happy_rank","Unemployment_rate", "Unemployment_rank"))
head(df)
NA
Understand
To understand the formed dataset, the dataframe structure has been examined. Several categorical values need to be converted to factor. Also, the ranking numbers need to be converted to ordered factor.
After type conversion, the strucutre of the dataframe was checked again, ensuring that the desired data types were used.
# This is the R chunk for the Understand Section
#structure before type conversion
glimpse(df)
Observations: 138
Variables: 8
$ Country [3m[38;5;246m<chr>[39m[23m "Qatar", "Niger", "Thailand", ...
$ Region [3m[38;5;246m<chr>[39m[23m "Middle East & North Africa", ...
$ Income_group [3m[38;5;246m<chr>[39m[23m "High income", "Low income", "...
$ GDPperCapita [3m[38;5;246m<dbl>[39m[23m 1.82427, 0.13270, 1.08930, 0.5...
$ Happy_score [3m[38;5;246m<dbl>[39m[23m 36, 142, 33, 140, 42, 152, 119...
$ Happy_rank [3m[38;5;246m<dbl>[39m[23m 6.375, 3.856, 6.474, 3.907, 6....
$ Unemployment_rate [3m[38;5;246m<dbl>[39m[23m 0.150, 0.505, 0.688, 0.716, 0....
$ Unemployment_rank [3m[38;5;246m<int>[39m[23m 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,...
# Type conversion
df$Region <- as.factor(df$Region)
levels(df$Income_group)
NULL
df$Happy_rank <- factor(df$Happy_rank, ordered = TRUE)
df$Unemployment_rank <- factor (df$Unemployment_rank, ordered = TRUE)
df$Income_group <- factor(df$Income_group, levels = c("Low income", "Lower middle income", "Upper middle income", "High income"), ordered = TRUE)
#structure after type conversion
glimpse(df)
Observations: 138
Variables: 8
$ Country [3m[38;5;246m<chr>[39m[23m "Qatar", "Niger", "Thailand", ...
$ Region [3m[38;5;246m<fct>[39m[23m Middle East & North Africa, Su...
$ Income_group [3m[38;5;246m<ord>[39m[23m High income, Low income, Upper...
$ GDPperCapita [3m[38;5;246m<dbl>[39m[23m 1.82427, 0.13270, 1.08930, 0.5...
$ Happy_score [3m[38;5;246m<dbl>[39m[23m 36, 142, 33, 140, 42, 152, 119...
$ Happy_rank [3m[38;5;246m<ord>[39m[23m 6.375, 3.856, 6.474, 3.907, 6....
$ Unemployment_rate [3m[38;5;246m<dbl>[39m[23m 0.150, 0.505, 0.688, 0.716, 0....
$ Unemployment_rank [3m[38;5;246m<ord>[39m[23m 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,...
Scan I
The dataframe was then scanned for missing values.
# Scan for missing values:
colSums(is.na(df))
Country Region Income_group
0 0 0
GDPperCapita Happy_score Happy_rank
0 0 0
Unemployment_rate Unemployment_rank
1 0
Results indicated that there is a missing value in unemployment rate; By examining, this missing value could be recoded by using the mean value of unemployment rate
# Handle missing values
df$Unemployment_rate[is.na(df$Unemployment_rate)] <- mean(df$Unemployment_rate, na.rm = TRUE)
Furthermore, the dataset was checked for special values since calculations invovling special values can result in special values which need to be scanned and handled.
A function has been created to scan several special values; sapply() will be used to apply this function on the dataframe.
# Scan for special values:
check_special <- function(x){if (is.numeric(x)) (is.infinite(x) | is.nan(x))}
df %>% select('GDPperCapita','Happy_score', 'Unemployment_rate') %>% sapply(function(x) sum(check_special(x)))
GDPperCapita Happy_score Unemployment_rate
0 0 0
Resutls showed that there were no special values in the dataframe.
Scan II
The next step was to scan the numerical variables (unemployment rate, happy score and GDP) of the dataframe for outliers. Two approaches were used.
- The first approach was to check the descriptive statistics (summary) of each numeric variable, screening for abnormal values.
# Scan for outliers using descriptive statistics:
df %>% select("Happy_score", "Unemployment_rate", "GDPperCapita") %>% summary()
Happy_score Unemployment_rate GDPperCapita
Min. : 1.00 Min. : 0.150 Min. :0.0000
1st Qu.: 36.25 1st Qu.: 3.905 1st Qu.:0.6891
Median : 76.50 Median : 5.954 Median :1.0291
Mean : 76.96 Mean : 7.372 Mean :0.9606
3rd Qu.:116.75 3rd Qu.: 9.570 3rd Qu.:1.2787
Max. :157.00 Max. :26.551 Max. :1.8243
The results showed that the maximum value of the unemploymen rate was about 3 times of its 3rd quartile value, and is much higher than 1.5 * IQR, which seems an outlier. Also, the GDP data has a minimum value of 0, which could be an outlier worth further exploration.
- To further support these hypotheses, a second approach, Tukey’s method - boxplot was used to scan for outliersin happy score and unemployment rate.
# Scan for outliers using boxplot:
unemploy_out <- boxplot(df$Unemployment_rate,main ="Unemployment Rate Box Plot", ylab="Unemployment Rate", col = "grey")

happy_out <- boxplot(df$Happy_score,main ="Happy Score Box Plot", ylab="Unemployment Rate", col = "pink")

GDP_out <- boxplot(df$GDPperCapita,main ="GDP Box Plot", ylab="Unemployment Rate", col = "light blue")

NA
NA
The boxplots indicate that there are no outliers in the happiness score data and GDP data, but there are some outliers in the unemployment rate data, which need to be handled using Turkey’s method: outlier fences: Q1 - 1.5 IQR ~ Q3 + 1.5 IQR Only the higher fence was calculated based on the boxplot and outlier were removed using subset function.
#Handle the outliers:
HighFence <- quantile(df$Unemployment_rate, .75) + 1.5 * IQR(df$Unemployment_rate)
df <- subset(df, df$Unemployment_rate < HighFence)
Transform
Data transformation is often used to process data for further statistical analysis. It can be used to enhance the understanding of the data by rescaling/standardising the values. It can also be used to reduce the skewness of data to achieve symmetric distribution which is preferred in many statistical analysis.
- histogram is used to display the distribution of the unemployment_rate data:
# Histogram of unemployment rate and happy score
hist(df$Unemployment_rate, main="Unemployment Rate Distribution", xlab = "Unemployment Rate %",breaks = 10)

Results showed that both the unemployment rate and happy score are right skewed.
To reduce right skewness, taking logarithms was attempted and histogram was checked:
# Logarithm:
log_unemploy <- log10 (df$Unemployment_rate)
# Histogram
hist(log_unemploy, main="Unemployment Rate Distribution - log transformed", xlab = "Unemployment Rate %",breaks = 10)

Results showed that the data was left_skewed. Which means taking logarithm was too powerful and both data were over-transformed.
Another approach, the square root transformation method was used:
# Taking square root:
sqrt_unemploy <- sqrt(df$Unemployment_rate)
# Histogram
hist(sqrt_unemploy, main="Unemployment Rate Distribution - sqrt transformed", xlab = "Unemployment Rate %",breaks = 10)

Results showed that the unemployment rate distribution was approximately symmetric, which means the data transformation was successful. The dataframe was updated with the transformed data:
# Update the employment rate variable
df$Unemployment_rate <- sqrt(df$Unemployment_rate)
- The histogram of happy_score data is shown below:
# Histogram
hist(df$Happy_score , main="Happy Score Distribution", xlab = "Happy Score",breaks = 10)

The data did not show clear distribution. Different transformation method were used:
@1). Logarithm:
# logarithm transformation:
log_happy <- log10(df$Happy_score)
# Histogram
hist(log_happy , main="Happy Score Distribution - log transformed", xlab = "Happy Score",breaks = 10)

@2). Square:
# logarithm transformation:
square_happy <- df$Happy_score^2
# Histogram
hist(square_happy , main="Happy Score Distribution - square transformed", xlab = "Happy Score",breaks = 10)

@3). Square root:
# square root transformation:
sqrt_happy <- sqrt(df$Happy_score)
# Histogram
hist(sqrt_happy , main="Happy Score Distribution - sqrt transformed", xlab = "Happy Score",breaks = 10)

@4). box-Cox:
# Box-Cox transformation
bc_happy <- BoxCox(df$Happy_score, lambda = "auto")
# Histogram
hist(bc_happy , main="Happy Score Distribution - BoxCox Transformed", xlab = "Happy Score",breaks = 10)

The happy score data was showed clearer distribution with data transformation applied.
However, each transformation led to either right skewed or left skewed data. The square root transformed data led to moderately left skewed data, so it was choosen as the transformation method.
# Update the happy score variable
df$Happy_score <- sqrt(df$Happy_score)
- The histogram of GDP data is shown below:
# Histogram
hist(df$GDPperCapita , main="GDP per Capita Distribution", xlab = "GDP per Capita",breaks = 10)

It was shown that the GDP per Captita data was appriximately normally distributed. So data transformation was not performed.
Summary
The information on unemployment rate and happiness report in 2016 among countries was gathered. Data cleasing and transformation were performed. The dataset was ready for further explorary analysis.
LS0tDQp0aXRsZTogIk1BVEgyMzQ5IFNlbWVzdGVyIDEsIDIwMjAiDQphdXRob3I6ICJTdHVkZW50IG5hbWUgYW5kIG51bWJlciBjb21lIGhlcmUiDQpzdWJ0aXRsZTogQXNzaWdubWVudCAyDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCi0tLQ0KDQojIyBSZXF1aXJlZCBwYWNrYWdlcyANCg0KYGBge3J9DQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSByZXF1aXJlZCBwYWNrYWdlcw0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkob3V0bGllcnMpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KYGBgDQoNCg0KIyMgRXhlY3V0aXZlIFN1bW1hcnkgDQpEYXRhIHByZXByb2Nlc3Npbmcgd2FzIHBlcmZvcm1lZCBvbiBhIGRhdGFzZXQgY29udGFpbmluZyBpbmZvcm1hdGlvbiBvbiB0aGUgaGFwcGluZXNzIHNjb3JlIGFuZCB1bmVtcGxveW1lbnQgcmF0ZSBpbiBkaWZmZXJlbnQgY291bnRyaWVzIGluIDIwMTYsIGluIGFuIGF0dGVtcHQgdG8gaW52ZXN0aWdhdGUgdGhlaXIgY29ycmVsYXRpb25zIHdpdGggYSByYW5nZSBvZiBmYWN0b3JzIGluY2x1ZGluZyBpbmNvbWUgZ3JvdXBzLCByZWdpb25zIGFuZCBjb3VudHJ5J3MgR0RQIHBlciBDYXBpdGEuIA0KDQpUaGUgZGF0YSB3cmFnZ2xpbmcgcHJvY2VzcyBzdGFydGVkIHdhcyBjb21tZW5jZWQgYnkgaW1wb3J0aW5nIHRoZSBkYXRhc2V0IG9mIHdvcmxkIGhhcHBpbmVzcyByZXBvcnQgaW4gMjAxNiwgYXMgd2VsbCBhcyB0aGUgd29ybGQgYmFuayB1bmVtcGxveW1lbnQgcmF0ZSAoMTk2MC0yMDE5KSBkYXRhc2V0LiBUaGVuIHRoZXNlIGRhdGFzZXRzIHdlcmUgcHJlZmlsdGVyZWQgYnkgc2VsZWN0aW5nIHRoZSByZWxldmFudCB2YXJpYWJsZXMsIG1lcmluZyBhbmQgZm9ybWluZyBvZiBhIG5ldywgdGlkeSBkYXRhZnJhbWUgZm9yIGZ1cnRoZXIgbWFuaXB1bGF0aW9uLiANCg0KVGhlbiB0aGUgbmV3IGRhdGFmcmFtZSBzdHJ1Y3R1cmUgd2FzIGNoZWNrZWQgZm9yIGEgYmV0dGVyIHVuZGVyc3RhbmRpbmcgb2YgdGhlIHZhcmlhYmxlcywgd2l0aCB0aGUgcHJvcGVyIGRhdGEgdHlwZSBjb252ZXJzaW9ucyBwZXJmb3JtZWQuIEZ1cnRoZXIgc2Nhbm5pbmcgb2YgdGhlIG51bWVyaWMgdmFyaWFibGVzICh1bmVtcGxveW1lbnQgcmF0ZSwgaGFwcHkgc2NvcmUsIEdEUCBwZXIgQ2FwaXRhKSBpbiB0aGUgZGF0YXNldCB3YXMgcGVyZm9ybWVkIHRvIGNoZWNrIG1pc3NpbmcgdmFsdWVzLCBzcGVjaWFsIHZhbHVlcyBhbmQgb3V0bGllcnMuIEZpbmFsbHksIGRhdGEgdHJhbnNmb3JtYXRpb24gd2FzIHBlcmZyb21lZCB0byB0cmFuc2Zvcm0gbm9uLXN5bWV0cmljYWxseSBkaXN0cmlidXRlZCB2YXJhaWFibGVzIHRvIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIG9uZXMuIA0KDQojIyBEYXRhIA0KVGhlIGZyaXN0IGRhdGEgaXMgdGhlIFdvcmxkIEhhcHBpbmVzcyBSZXBvcnQgaW4gMjAxNiBkb3dubG9hZGVkIGZyb20gaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS91bnNkc24vd29ybGQtaGFwcGluZXNzP3NlbGVjdD0yMDE2LmNzdiwgd2l0aCBhIGxpY2Vuc2Ugb2YgQ0MwOiBQdWJsaWMgRG9tYWluLiBUaGUgcmVwb3J0IHJhbmtzIDE1NSBjb3VudHJpZXMgYnkgdGhlaXIgaGFwcGluZXNzIGxldmVscyBiYXNlZCBvbiBhIHJhbmdlIG9mIGZhY3RvcnMgaW5jbHVkaW5nIHRoZWlyIGVjb25vbXkgKEdEUCBwZXIgQ2FwaXRhKSwgZnJlZWRvbSwgaGVhbHRoIGV0Yy4gDQpUaGUgZGF0YSBpcyBhIHRpZHkgZGF0YSBzZXQgc2luY2UgZWFjaCB2YXJpYWJsZSBoYXMgaXRzIG93biBjb2x1bW4sIGVhY2ggb2JzZXJ2YXRpb24gaGFzIGl0cyBvd24gcm93IGFuZCBlYWNoIHZhbHVlIGhhcyBpdHMgb3duIGNlbGwuDQoNClRoZSBzZWNvbmQgZGF0YSBhbmQgdGhlIHRoaXJkIGRhdGFzZXRzIHdlcmUgV29ybGQgQmFuayBVbmVtcGxveW1lbnQgRGF0YSAoMTk2MC0yMDE5KSBkb3dubG9hZGVkIGZyb20gaHR0cHM6Ly9kYXRhLndvcmxkYmFuay5vcmcvaW5kaWNhdG9yL1NMLlVFTS5UT1RMLk5FLlpTIHdpdGggYSBXb3JsZCBCYW5rIERhdGFzZXQgbGljZW5zZS4gVGhlIHNlY29uZCBkYXRhc2V0IHdhcyB0aGUgdW5lbXBsb3ltZW50IHJhdGUlIHJlcG9ydGVkIGluIGNvdW50cmllcyBvdmVyIHllYXJzLiBUaGUgdGhpcmQgZGF0YXNldCB3YXMgaW5mb3JtYXRpb24gb24gdGhlIGNvdW50cmllcyBpbmNsdWRlZCBpbiBkYXRhc2V0Miwgc3VjaCBhcyB0aGUgY291bnRyeSdzIGNvZGUsIG5hbWUsIHJlZ2lvbiBhbmQgaW5jb21lIGdyb3Vwcy5UaGUgZGF0YSBzZXQgd2FzIHVudGlkeSBiZWNhdXNlIGEgbnVtYmVyIG9mIHZhcmFpYWJsZXMgZnJvbSDigJwxOTYw4oCdIHRvIOKAnDIwMTnigJ0gcmVwcmVzZW50aW5nIHRoZSB5ZWFyIHNob3VsZCBiZSB2YWx1ZXMgb2YgYSBuZXcgdmFyaWFibGUgInllYXIiLCByYXRoZXIgdGhhbiBiZWluZyBjb2x1bW4gbmFtZXMgdGhlbXNlbHZlZC4gRGF0YSBtYW5pcHVsYXRpb24gd2FzIG5vdCBwZXJmb3JtZWQgaGVyZSBzaW5jZSBvbmx5IHRoZSByZXN1bHQgaW4gMjAxNiB3YXMgdGhlIGludGVyZXN0IG9mIHRoaXMgaW52ZXNpdGdhdGlvbi4gSG93ZXZlciwgaWYgdGhpcyBkYXRhc2V0IHdhcyB0byBiZSB1c2VkIGZvciBvdGhlciBwdXJwb3NlZCwgdGhpcyBkYXRhc2V0IG5lZWRlZCB0byBiZSByZXNoYXBlZCB1c2luZyB0aGUgZHlwbHIgZ2F0aGVyKCkgZnVuY3Rpb24gdXNpbmcgdGhlIGZvbGx3b2luZyBjb21tYW5kOiBnYXRoZXIgKGRhdGFzZXQsIGtleSA9ICJ5ZWFyIiwgdmFsdWUgPSAidW5lbXBsb3ltZW50IHJhdGUiLCAnMTk2MCc6JzIwMTknKQ0KDQpgYGB7cn0NCiMgVGhpcyBpcyB0aGUgUiBjaHVuayBmb3IgdGhlIERhdGEgU2VjdGlvbg0KaGFwcHlfMjAxNjwtcmVhZF9jc3YoIkhhcHBpbmVzc193b3JsZC5jc3YiKQ0KZGZ1bmVtcGxveTwtcmVhZF9jc3YoIlVuZW1wbG95bWVudF93b3JsZC5jc3YiKQ0KZGZjb3VudHJ5IDwtIHJlYWRfY3N2KCJDb3VudHJ5X3dvcmxkLmNzdiIpDQoNCmhlYWQoaGFwcHlfMjAxNikNCmhlYWQoZGZ1bmVtcGxveSkNCmhlYWQoZGZjb3VudHJ5KQ0KYGBgDQoNCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSSANClNlbGVjdCByZWxldmFudCBjb2x1bW5zIGZyb20gZWFjaCBkYXRhc2V0LiBPbmx5IHRoZSB2YXJpYWJsZXMgcmVxdWlyZWQgZm9yIGZ1cnRoZXIgYW5hbHlzaXMgd2lsbCBiZSBzZWxlY3RlZCB0byBmb3JtIGEgbmV3IGRhdGFzZXQuIA0KDQpNdXRhdGUgam9pbiBpcyB1c2VkIHRvIG1lcmdlIHRoZSBkYXRhc2V0cyB0byBmb3JtIGEgbmV3IG9uZS4NCg0KYGBge3J9DQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIEkgDQojc2VsZWN0IGRhdGEgZm9yIDIwMTYgZnJvbSB0aGUgZGF0YXNldHMgZm9yIGZ1cnRoZXIgYW5hbHlzaXMNCg0KaGFwcHlfMjAxNiA8LSBoYXBweV8yMDE2ICU+JSBzZWxlY3QoYygiQ291bnRyeSIsICJIYXBwaW5lc3MgU2NvcmUiLCAiSGFwcGluZXNzIFJhbmsiLCAiRWNvbm9teSAoR0RQIHBlciBDYXBpdGEpIikpDQp1bmVtcGxveV8yMDE2IDwtIGRmdW5lbXBsb3kgJT4lIHNlbGVjdChjKCJDb3VudHJ5IE5hbWUiLCAiQ291bnRyeSBDb2RlIiwgIjIwMTYiKSkNCmRmY291bnRyeSA8LSBkZmNvdW50cnkgJT4lIHNlbGVjdChjKCJDb3VudHJ5IENvZGUiLCAiUmVnaW9uIiwgIkluY29tZUdyb3VwIikpDQoNCiNwZXJmb3JtIGlubmVyIGpvaW4gb24gdGhlc2UgdGhyZWUgZGF0YXNldHMgYnkgY291bnRyeSBuYW1lOyANCmRmIDwtIHVuZW1wbG95XzIwMTYgJT4lIGxlZnRfam9pbihkZmNvdW50cnksIGJ5ID0gIkNvdW50cnkgQ29kZSIpICU+JSBpbm5lcl9qb2luKGhhcHB5XzIwMTYsIGJ5ID0gYygiQ291bnRyeSBOYW1lIiA9ICJDb3VudHJ5IikpDQoNCmhlYWQoZGYpDQpgYGANCg0KIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJSSANCkFzc2lnbiBuZXcgY29sdW1uIG5hbWVzIHRvIHRoZSBmb3JtZWQgZGF0YXNldDsNCkFycmFuZ2UgdGhlIHVuZW1wbG95bWVudCByYXRlIG9mIGFsbCBjb3VudHJpZXMgYW5kIGZpbmQgdGhlaXIgcmFua2luZyAtIGNyZWF0ZSBhIG5ldyBjb2x1bW4gY2FsbGVkIHVuZW1wbG95bWVudF9yYW5rOyBUaGlzIHdpbGwgYmUgdXNlZCBmb3IgZnVydGhlciBhbmFseXNpcyBhbG9uZyB3aXRoIHRoZSBoYXBwaW5lc3Mgc2NvcmUgcmFua2luZyBvZiBjb3VudHJpZXMNCmBgYHtyfQ0KDQpjb2xuYW1lcyhkZikgPC0gYygiQ291bnRyeSIsICJDb3VudHJ5X2NvZGUiLCAiVW5lbXBsb3ltZW50X3JhdGUiLCAiUmVnaW9uIiwiSW5jb21lX2dyb3VwIiwgIkhhcHB5X3JhbmsiLCAiSGFwcHlfc2NvcmUiLCAiR0RQcGVyQ2FwaXRhIikNCg0KZGYgPC0gZGYgJT4lIGFycmFuZ2UoVW5lbXBsb3ltZW50X3JhdGUpICU+JSBtdXRhdGUoVW5lbXBsb3ltZW50X3JhbmsgPXJvd19udW1iZXIgKCkpDQoNCmRmIDwtIGRmICU+JSBzZWxlY3QoYygiQ291bnRyeSIsICJSZWdpb24iLCJJbmNvbWVfZ3JvdXAiLCJHRFBwZXJDYXBpdGEiLCAiSGFwcHlfc2NvcmUiLCAiSGFwcHlfcmFuayIsIlVuZW1wbG95bWVudF9yYXRlIiwgIlVuZW1wbG95bWVudF9yYW5rIikpDQoNCmhlYWQoZGYpDQoNCmBgYA0KDQoNCiMjIFVuZGVyc3RhbmQgDQpUbyB1bmRlcnN0YW5kIHRoZSBmb3JtZWQgZGF0YXNldCwgdGhlIGRhdGFmcmFtZSBzdHJ1Y3R1cmUgaGFzIGJlZW4gZXhhbWluZWQuIFNldmVyYWwgY2F0ZWdvcmljYWwgdmFsdWVzIG5lZWQgdG8gYmUgY29udmVydGVkIHRvIGZhY3Rvci4gQWxzbywgdGhlIHJhbmtpbmcgbnVtYmVycyBuZWVkIHRvIGJlIGNvbnZlcnRlZCB0byBvcmRlcmVkIGZhY3Rvci4NCg0KQWZ0ZXIgdHlwZSBjb252ZXJzaW9uLCB0aGUgc3RydWN1dHJlIG9mIHRoZSBkYXRhZnJhbWUgd2FzIGNoZWNrZWQgYWdhaW4sIGVuc3VyaW5nIHRoYXQgdGhlIGRlc2lyZWQgZGF0YSB0eXBlcyB3ZXJlIHVzZWQuIA0KYGBge3J9DQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBVbmRlcnN0YW5kIFNlY3Rpb24NCiNzdHJ1Y3R1cmUgYmVmb3JlIHR5cGUgY29udmVyc2lvbg0KZ2xpbXBzZShkZikNCg0KIyBUeXBlIGNvbnZlcnNpb24NCmRmJFJlZ2lvbiA8LSBhcy5mYWN0b3IoZGYkUmVnaW9uKQ0KbGV2ZWxzKGRmJEluY29tZV9ncm91cCkNCg0KZGYkSGFwcHlfcmFuayA8LSBmYWN0b3IoZGYkSGFwcHlfcmFuaywgb3JkZXJlZCA9IFRSVUUpDQpkZiRVbmVtcGxveW1lbnRfcmFuayA8LSBmYWN0b3IgKGRmJFVuZW1wbG95bWVudF9yYW5rLCBvcmRlcmVkID0gVFJVRSkNCg0KZGYkSW5jb21lX2dyb3VwIDwtIGZhY3RvcihkZiRJbmNvbWVfZ3JvdXAsIGxldmVscyA9IGMoIkxvdyBpbmNvbWUiLCAiTG93ZXIgbWlkZGxlIGluY29tZSIsICJVcHBlciBtaWRkbGUgaW5jb21lIiwgIkhpZ2ggaW5jb21lIiksICBvcmRlcmVkID0gVFJVRSkNCg0KI3N0cnVjdHVyZSBhZnRlciB0eXBlIGNvbnZlcnNpb24NCmdsaW1wc2UoZGYpDQpgYGANCg0KDQojIwlTY2FuIEkgDQpUaGUgZGF0YWZyYW1lIHdhcyB0aGVuIHNjYW5uZWQgZm9yIG1pc3NpbmcgdmFsdWVzLg0KYGBge3J9DQojIFNjYW4gZm9yIG1pc3NpbmcgdmFsdWVzOg0KY29sU3Vtcyhpcy5uYShkZikpDQoNCmBgYA0KUmVzdWx0cyBpbmRpY2F0ZWQgdGhhdCB0aGVyZSBpcyBhIG1pc3NpbmcgdmFsdWUgaW4gdW5lbXBsb3ltZW50IHJhdGU7DQpCeSBleGFtaW5pbmcsIHRoaXMgbWlzc2luZyB2YWx1ZSBjb3VsZCBiZSByZWNvZGVkIGJ5IHVzaW5nIHRoZSBtZWFuIHZhbHVlIG9mIHVuZW1wbG95bWVudCByYXRlDQoNCmBgYHtyfQ0KIyBIYW5kbGUgbWlzc2luZyB2YWx1ZXMNCmRmJFVuZW1wbG95bWVudF9yYXRlW2lzLm5hKGRmJFVuZW1wbG95bWVudF9yYXRlKV0gPC0gbWVhbihkZiRVbmVtcGxveW1lbnRfcmF0ZSwgbmEucm0gPSBUUlVFKQ0KYGBgDQoNCkZ1cnRoZXJtb3JlLCB0aGUgZGF0YXNldCB3YXMgY2hlY2tlZCBmb3Igc3BlY2lhbCB2YWx1ZXMgc2luY2UgY2FsY3VsYXRpb25zIGludm92bGluZyBzcGVjaWFsIHZhbHVlcyBjYW4gcmVzdWx0IGluIHNwZWNpYWwgdmFsdWVzIHdoaWNoIG5lZWQgdG8gYmUgc2Nhbm5lZCBhbmQgaGFuZGxlZC4NCg0KQSBmdW5jdGlvbiBoYXMgYmVlbiBjcmVhdGVkIHRvIHNjYW4gc2V2ZXJhbCBzcGVjaWFsIHZhbHVlczsNCnNhcHBseSgpIHdpbGwgYmUgdXNlZCB0byBhcHBseSB0aGlzIGZ1bmN0aW9uIG9uIHRoZSBkYXRhZnJhbWUuDQpgYGB7cn0NCiMgU2NhbiBmb3Igc3BlY2lhbCB2YWx1ZXM6DQpjaGVja19zcGVjaWFsIDwtIGZ1bmN0aW9uKHgpe2lmIChpcy5udW1lcmljKHgpKSAoaXMuaW5maW5pdGUoeCkgfCBpcy5uYW4oeCkpfQ0KZGYgJT4lIHNlbGVjdCgnR0RQcGVyQ2FwaXRhJywnSGFwcHlfc2NvcmUnLCAnVW5lbXBsb3ltZW50X3JhdGUnKSAlPiUgc2FwcGx5KGZ1bmN0aW9uKHgpIHN1bShjaGVja19zcGVjaWFsKHgpKSkNCg0KYGBgDQpSZXN1dGxzIHNob3dlZCB0aGF0IHRoZXJlIHdlcmUgbm8gc3BlY2lhbCB2YWx1ZXMgaW4gdGhlIGRhdGFmcmFtZS4NCg0KIyMJU2NhbiBJSQ0KVGhlIG5leHQgc3RlcCB3YXMgdG8gc2NhbiB0aGUgbnVtZXJpY2FsIHZhcmlhYmxlcyAodW5lbXBsb3ltZW50IHJhdGUsIGhhcHB5IHNjb3JlIGFuZCBHRFApIG9mIHRoZSBkYXRhZnJhbWUgZm9yIG91dGxpZXJzLiBUd28gYXBwcm9hY2hlcyB3ZXJlIHVzZWQuIA0KDQoxLg0KVGhlIGZpcnN0IGFwcHJvYWNoIHdhcyB0byBjaGVjayB0aGUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyAoc3VtbWFyeSkgb2YgZWFjaCBudW1lcmljIHZhcmlhYmxlLCBzY3JlZW5pbmcgZm9yIGFibm9ybWFsIHZhbHVlcy4gDQpgYGB7cn0NCiMgU2NhbiBmb3Igb3V0bGllcnMgdXNpbmcgZGVzY3JpcHRpdmUgc3RhdGlzdGljczoNCmRmICU+JSBzZWxlY3QoIkhhcHB5X3Njb3JlIiwgIlVuZW1wbG95bWVudF9yYXRlIiwgIkdEUHBlckNhcGl0YSIpICU+JSBzdW1tYXJ5KCkNCmBgYA0KVGhlIHJlc3VsdHMgc2hvd2VkIHRoYXQgdGhlIG1heGltdW0gdmFsdWUgb2YgdGhlIHVuZW1wbG95bWVuIHJhdGUgd2FzIGFib3V0IDMgdGltZXMgb2YgaXRzIDNyZCBxdWFydGlsZSB2YWx1ZSwgYW5kIGlzIG11Y2ggaGlnaGVyIHRoYW4gMS41ICogSVFSLCB3aGljaCBzZWVtcyBhbiBvdXRsaWVyLiBBbHNvLCB0aGUgR0RQIGRhdGEgaGFzIGEgbWluaW11bSB2YWx1ZSBvZiAwLCB3aGljaCBjb3VsZCBiZSBhbiBvdXRsaWVyIHdvcnRoIGZ1cnRoZXIgZXhwbG9yYXRpb24uDQoNCjIuIA0KVG8gZnVydGhlciBzdXBwb3J0IHRoZXNlIGh5cG90aGVzZXMsIGEgc2Vjb25kIGFwcHJvYWNoLCBUdWtleSdzIG1ldGhvZCAtIGJveHBsb3Qgd2FzIHVzZWQgdG8gc2NhbiBmb3Igb3V0bGllcnNpbiBoYXBweSBzY29yZSBhbmQgdW5lbXBsb3ltZW50IHJhdGUuIA0KYGBge3J9DQojIFNjYW4gZm9yIG91dGxpZXJzIHVzaW5nIGJveHBsb3Q6DQp1bmVtcGxveV9vdXQgPC0gYm94cGxvdChkZiRVbmVtcGxveW1lbnRfcmF0ZSxtYWluID0iVW5lbXBsb3ltZW50IFJhdGUgQm94IFBsb3QiLCB5bGFiPSJVbmVtcGxveW1lbnQgUmF0ZSIsIGNvbCA9ICJncmV5IikNCmhhcHB5X291dCA8LSBib3hwbG90KGRmJEhhcHB5X3Njb3JlLG1haW4gPSJIYXBweSBTY29yZSBCb3ggUGxvdCIsIHlsYWI9IlVuZW1wbG95bWVudCBSYXRlIiwgY29sID0gInBpbmsiKQ0KR0RQX291dCA8LSBib3hwbG90KGRmJEdEUHBlckNhcGl0YSxtYWluID0iR0RQIEJveCBQbG90IiwgeWxhYj0iVW5lbXBsb3ltZW50IFJhdGUiLCBjb2wgPSAibGlnaHQgYmx1ZSIpDQpgYGANClRoZSBib3hwbG90cyBpbmRpY2F0ZSB0aGF0IHRoZXJlIGFyZSBubyBvdXRsaWVycyBpbiB0aGUgaGFwcGluZXNzIHNjb3JlIGRhdGEgYW5kIEdEUCBkYXRhLCBidXQgdGhlcmUgYXJlIHNvbWUgb3V0bGllcnMgaW4gdGhlIHVuZW1wbG95bWVudCByYXRlIGRhdGEsIHdoaWNoIG5lZWQgdG8gYmUgaGFuZGxlZCB1c2luZyBUdXJrZXkncyBtZXRob2Q6DQpvdXRsaWVyIGZlbmNlczogUTEgLSAxLjUgSVFSIH4gUTMgKyAxLjUgSVFSDQpPbmx5IHRoZSBoaWdoZXIgZmVuY2Ugd2FzIGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlIGJveHBsb3QgYW5kIG91dGxpZXIgd2VyZSByZW1vdmVkIHVzaW5nIHN1YnNldCBmdW5jdGlvbi4NCg0KYGBge3J9DQojSGFuZGxlIHRoZSBvdXRsaWVyczoNCkhpZ2hGZW5jZSA8LSBxdWFudGlsZShkZiRVbmVtcGxveW1lbnRfcmF0ZSwgLjc1KSArIDEuNSAqIElRUihkZiRVbmVtcGxveW1lbnRfcmF0ZSkgDQoNCmRmIDwtIHN1YnNldChkZiwgZGYkVW5lbXBsb3ltZW50X3JhdGUgPCBIaWdoRmVuY2UpDQoNCmBgYA0KDQojIwlUcmFuc2Zvcm0gDQpEYXRhIHRyYW5zZm9ybWF0aW9uIGlzIG9mdGVuIHVzZWQgdG8gcHJvY2VzcyBkYXRhIGZvciBmdXJ0aGVyIHN0YXRpc3RpY2FsIGFuYWx5c2lzLiBJdCBjYW4gYmUgdXNlZCB0byBlbmhhbmNlIHRoZSB1bmRlcnN0YW5kaW5nIG9mIHRoZSBkYXRhIGJ5IHJlc2NhbGluZy9zdGFuZGFyZGlzaW5nIHRoZSB2YWx1ZXMuIEl0IGNhbiBhbHNvIGJlIHVzZWQgdG8gcmVkdWNlIHRoZSBza2V3bmVzcyBvZiBkYXRhIHRvIGFjaGlldmUgc3ltbWV0cmljIGRpc3RyaWJ1dGlvbiB3aGljaCBpcyBwcmVmZXJyZWQgaW4gbWFueSBzdGF0aXN0aWNhbCBhbmFseXNpcy4NCg0KMS4gaGlzdG9ncmFtIGlzIHVzZWQgdG8gZGlzcGxheSB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSB1bmVtcGxveW1lbnRfcmF0ZSBkYXRhOg0KDQpgYGB7cn0NCiMgSGlzdG9ncmFtIG9mIHVuZW1wbG95bWVudCByYXRlIGFuZCBoYXBweSBzY29yZQ0KaGlzdChkZiRVbmVtcGxveW1lbnRfcmF0ZSwgbWFpbj0iVW5lbXBsb3ltZW50IFJhdGUgRGlzdHJpYnV0aW9uIiwgeGxhYiA9ICJVbmVtcGxveW1lbnQgUmF0ZSAlIixicmVha3MgPSAxMCkNCmBgYA0KDQpSZXN1bHRzIHNob3dlZCB0aGF0IGJvdGggdGhlIHVuZW1wbG95bWVudCByYXRlIGFuZCBoYXBweSBzY29yZSBhcmUgcmlnaHQgc2tld2VkLg0KDQpUbyByZWR1Y2UgcmlnaHQgc2tld25lc3MsIHRha2luZyBsb2dhcml0aG1zIHdhcyBhdHRlbXB0ZWQgYW5kIGhpc3RvZ3JhbSB3YXMgY2hlY2tlZDoNCg0KYGBge3J9DQojIExvZ2FyaXRobToNCmxvZ191bmVtcGxveSA8LSBsb2cxMCAoZGYkVW5lbXBsb3ltZW50X3JhdGUpDQojIEhpc3RvZ3JhbQ0KaGlzdChsb2dfdW5lbXBsb3ksIG1haW49IlVuZW1wbG95bWVudCBSYXRlIERpc3RyaWJ1dGlvbiAtIGxvZyB0cmFuc2Zvcm1lZCIsIHhsYWIgPSAiVW5lbXBsb3ltZW50IFJhdGUgJSIsYnJlYWtzID0gMTApDQpgYGANCg0KUmVzdWx0cyBzaG93ZWQgdGhhdCB0aGUgZGF0YSB3YXMgbGVmdF9za2V3ZWQuIFdoaWNoIG1lYW5zIHRha2luZyBsb2dhcml0aG0gd2FzIHRvbyBwb3dlcmZ1bCBhbmQgYm90aCBkYXRhIHdlcmUgb3Zlci10cmFuc2Zvcm1lZC4NCg0KQW5vdGhlciBhcHByb2FjaCwgdGhlIHNxdWFyZSByb290IHRyYW5zZm9ybWF0aW9uIG1ldGhvZCB3YXMgdXNlZDoNCmBgYHtyfQ0KIyBUYWtpbmcgc3F1YXJlIHJvb3Q6DQpzcXJ0X3VuZW1wbG95IDwtIHNxcnQoZGYkVW5lbXBsb3ltZW50X3JhdGUpDQojIEhpc3RvZ3JhbQ0KaGlzdChzcXJ0X3VuZW1wbG95LCBtYWluPSJVbmVtcGxveW1lbnQgUmF0ZSBEaXN0cmlidXRpb24gLSBzcXJ0IHRyYW5zZm9ybWVkIiwgeGxhYiA9ICJVbmVtcGxveW1lbnQgUmF0ZSAlIixicmVha3MgPSAxMCkNCmBgYA0KDQpSZXN1bHRzIHNob3dlZCB0aGF0IHRoZSB1bmVtcGxveW1lbnQgcmF0ZSBkaXN0cmlidXRpb24gd2FzIGFwcHJveGltYXRlbHkgc3ltbWV0cmljLCB3aGljaCBtZWFucyB0aGUgZGF0YSB0cmFuc2Zvcm1hdGlvbiB3YXMgc3VjY2Vzc2Z1bC4gVGhlIGRhdGFmcmFtZSB3YXMgdXBkYXRlZCB3aXRoIHRoZSB0cmFuc2Zvcm1lZCBkYXRhOg0KDQpgYGB7cn0NCiMgVXBkYXRlIHRoZSBlbXBsb3ltZW50IHJhdGUgdmFyaWFibGUgDQpkZiRVbmVtcGxveW1lbnRfcmF0ZSA8LSBzcXJ0KGRmJFVuZW1wbG95bWVudF9yYXRlKQ0KYGBgDQoNCjIuIFRoZSBoaXN0b2dyYW0gb2YgaGFwcHlfc2NvcmUgZGF0YSBpcyBzaG93biBiZWxvdzoNCmBgYHtyfQ0KIyBIaXN0b2dyYW0NCmhpc3QoZGYkSGFwcHlfc2NvcmUgLCBtYWluPSJIYXBweSBTY29yZSBEaXN0cmlidXRpb24iLCB4bGFiID0gIkhhcHB5IFNjb3JlIixicmVha3MgPSAxMCkNCmBgYA0KDQpUaGUgZGF0YSBkaWQgbm90IHNob3cgY2xlYXIgZGlzdHJpYnV0aW9uLiBEaWZmZXJlbnQgdHJhbnNmb3JtYXRpb24gbWV0aG9kIHdlcmUgdXNlZDoNCg0KQDEpLiBMb2dhcml0aG06DQpgYGB7cn0NCiMgbG9nYXJpdGhtIHRyYW5zZm9ybWF0aW9uOg0KbG9nX2hhcHB5IDwtIGxvZzEwKGRmJEhhcHB5X3Njb3JlKQ0KDQojIEhpc3RvZ3JhbQ0KaGlzdChsb2dfaGFwcHkgLCBtYWluPSJIYXBweSBTY29yZSBEaXN0cmlidXRpb24gLSBsb2cgdHJhbnNmb3JtZWQiLCB4bGFiID0gIkhhcHB5IFNjb3JlIixicmVha3MgPSAxMCkNCmBgYA0KDQpAMikuIFNxdWFyZToNCmBgYHtyfQ0KIyBsb2dhcml0aG0gdHJhbnNmb3JtYXRpb246DQpzcXVhcmVfaGFwcHkgPC0gZGYkSGFwcHlfc2NvcmVeMg0KDQojIEhpc3RvZ3JhbQ0KaGlzdChzcXVhcmVfaGFwcHkgLCBtYWluPSJIYXBweSBTY29yZSBEaXN0cmlidXRpb24gLSBzcXVhcmUgdHJhbnNmb3JtZWQiLCB4bGFiID0gIkhhcHB5IFNjb3JlIixicmVha3MgPSAxMCkNCmBgYA0KDQpAMykuIFNxdWFyZSByb290Og0KYGBge3J9DQojIHNxdWFyZSByb290IHRyYW5zZm9ybWF0aW9uOg0Kc3FydF9oYXBweSA8LSBzcXJ0KGRmJEhhcHB5X3Njb3JlKQ0KDQojIEhpc3RvZ3JhbQ0KaGlzdChzcXJ0X2hhcHB5ICwgbWFpbj0iSGFwcHkgU2NvcmUgRGlzdHJpYnV0aW9uIC0gc3FydCB0cmFuc2Zvcm1lZCIsIHhsYWIgPSAiSGFwcHkgU2NvcmUiLGJyZWFrcyA9IDEwKQ0KYGBgDQoNCkA0KS4gYm94LUNveDogDQpgYGB7cn0NCiMgQm94LUNveCB0cmFuc2Zvcm1hdGlvbg0KYmNfaGFwcHkgPC0gQm94Q294KGRmJEhhcHB5X3Njb3JlLCBsYW1iZGEgPSAiYXV0byIpDQoNCiMgSGlzdG9ncmFtDQpoaXN0KGJjX2hhcHB5ICwgbWFpbj0iSGFwcHkgU2NvcmUgRGlzdHJpYnV0aW9uIC0gQm94Q294IFRyYW5zZm9ybWVkIiwgeGxhYiA9ICJIYXBweSBTY29yZSIsYnJlYWtzID0gMTApDQpgYGANCg0KVGhlIGhhcHB5IHNjb3JlIGRhdGEgd2FzIHNob3dlZCBjbGVhcmVyIGRpc3RyaWJ1dGlvbiB3aXRoIGRhdGEgdHJhbnNmb3JtYXRpb24gYXBwbGllZC4NCg0KSG93ZXZlciwgZWFjaCB0cmFuc2Zvcm1hdGlvbiBsZWQgdG8gZWl0aGVyIHJpZ2h0IHNrZXdlZCBvciBsZWZ0IHNrZXdlZCBkYXRhLiBUaGUgc3F1YXJlIHJvb3QgdHJhbnNmb3JtZWQgZGF0YSBsZWQgdG8gbW9kZXJhdGVseSBsZWZ0IHNrZXdlZCBkYXRhLCBzbyBpdCB3YXMgY2hvb3NlbiBhcyB0aGUgdHJhbnNmb3JtYXRpb24gbWV0aG9kLg0KDQpgYGB7cn0NCiMgVXBkYXRlIHRoZSBoYXBweSBzY29yZSB2YXJpYWJsZSANCmRmJEhhcHB5X3Njb3JlIDwtIHNxcnQoZGYkSGFwcHlfc2NvcmUpDQpgYGANCg0KMy4gVGhlIGhpc3RvZ3JhbSBvZiBHRFAgZGF0YSBpcyBzaG93biBiZWxvdzoNCmBgYHtyfQ0KIyBIaXN0b2dyYW0NCmhpc3QoZGYkR0RQcGVyQ2FwaXRhICwgbWFpbj0iR0RQIHBlciBDYXBpdGEgRGlzdHJpYnV0aW9uIiwgeGxhYiA9ICJHRFAgcGVyIENhcGl0YSIsYnJlYWtzID0gMTApDQpgYGANCkl0IHdhcyBzaG93biB0aGF0IHRoZSBHRFAgcGVyIENhcHRpdGEgZGF0YSB3YXMgYXBwcml4aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZC4gU28gZGF0YSB0cmFuc2Zvcm1hdGlvbiB3YXMgbm90IHBlcmZvcm1lZC4gDQoNCiMjCVN1bW1hcnkNClRoZSBpbmZvcm1hdGlvbiBvbiB1bmVtcGxveW1lbnQgcmF0ZSBhbmQgaGFwcGluZXNzIHJlcG9ydCBpbiAyMDE2IGFtb25nIGNvdW50cmllcyB3YXMgZ2F0aGVyZWQuIERhdGEgY2xlYXNpbmcgYW5kIHRyYW5zZm9ybWF0aW9uIHdlcmUgcGVyZm9ybWVkLiBUaGUgZGF0YXNldCB3YXMgcmVhZHkgZm9yIGZ1cnRoZXIgZXhwbG9yYXJ5IGFuYWx5c2lzLiA=