Required packages

The below packages have been used for this analysis:

library(readr)
library(dplyr)
library(tidyr)
library(knitr)
library(hms)
library(outliers)
library(ggplot2)
library(forecast)



Executive Summary



Data

The first dataset used is “World Happiness Report” from the year 2015. This report is a landmark survey of the state of global happiness of various countries across the globe. The data consist of a happiness score which is calculated on a scale of 0 to 10 where 10 is the happiest and the respective countries ranking amongst others. Switzerland is currently ranking 1st with a happiness score of 7.59. The different columns are described as below:

  1. Country – Name of the country
  2. Region – Region the country belongs to
  3. Happiness Rank – Country’s rank based on happiness score
  4. Happiness Score – Score measured by asking sampled people how they would rate their happiness.
  5. Standard Error – The standard error of the happiness score
  6. Economy (GDP per Capita) – The extent to which GDP contributes to the calculation of happiness score
  7. Family - The extent to which Family contributes to the calculation of happiness score
  8. Health (Life Expectancy) - The extent to which health contributes to the calculation of happiness score
  9. Freedom - The extent to which Freedom contributes to the calculation of happiness score
  10. Trust (Government Corruption) - The extent to which perception of corruption contributes to the calculation of happiness score
  11. Generosity – The extent to which Generosity contributes to the calculation of happiness score
  12. Dystopia Residual – It is the sum of the dystopia happiness score (1.85) ie score of a hypothetical country having rank lower than the lowest ranking country in the report, plus the residual value of each country which is a number left over from the normalization of the variables which cannot be explained).

By adding up all these factors including the Dystopia Residual, we get the happiness score for each country.
The second dataset used here is “Countries Longitude and Latitude” which gives the latitude and longitude details of each country which is used as a reference in several cases. The latitude and longitude of each country is given in Simple Decimal Standard in separate columns. The columns in the dataset can be explained as below:

  1. (Blank column title) – Gives the serial number of countries
  2. Latitude – Gives the respective country’s latitudinal coordinates
  3. Longitude – Gives the respective country’s longitudinal coordinates
  4. Country – Name of the country

The datasets used were obtained from an open source website: “World Happiness Report” (https://www.kaggle.com/unsdsn/world-happiness) and “Countries Longitude and Latitude” (https://www.kaggle.com/folaraz/world-countries-and-continents-details?select=Countries+Longitude+and+Latitude.csv).

#Setting the working directory
setwd("C:/Users/User/Desktop/RMIT class/Data Wrangling/Assignment 2")
getwd()
[1] "C:/Users/User/Desktop/RMIT class/Data Wrangling/Assignment 2"
#Reading the datasets
Happy <- read_csv("2015.csv")
Parsed with column specification:
cols(
  Country = col_character(),
  Region = col_character(),
  `Happiness Rank` = col_double(),
  `Happiness Score` = col_double(),
  `Standard Error` = col_double(),
  `Economy (GDP per Capita)` = col_double(),
  Family = col_double(),
  `Health (Life Expectancy)` = col_double(),
  Freedom = col_double(),
  `Trust (Government Corruption)` = col_double(),
  Generosity = col_double(),
  `Dystopia Residual` = col_double()
)
head(Happy)

Country1 <- read_csv("Countries.csv")
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
  X1 = col_double(),
  latitude = col_double(),
  longitude = col_double(),
  Country = col_character()
)
Country <- Country1[,c(2,3,4)]
head(Country)

#Joining the 2 datasets
join <- inner_join(Happy, Country, by = "Country")
head(join)
NA



Understand

str(join)
Classes ‘spec_tbl_df’, ‘tbl_df’, ‘tbl’ and 'data.frame':    147 obs. of  14 variables:
 $ Country                      : chr  "Switzerland" "Iceland" "Denmark" "Norway" ...
 $ Region                       : chr  "Western Europe" "Western Europe" "Western Europe" "Western Europe" ...
 $ Happiness Rank               : num  1 2 3 4 5 6 7 8 9 10 ...
 $ Happiness Score              : num  7.59 7.56 7.53 7.52 7.43 ...
 $ Standard Error               : num  0.0341 0.0488 0.0333 0.0388 0.0355 ...
 $ Economy (GDP per Capita)     : num  1.4 1.3 1.33 1.46 1.33 ...
 $ Family                       : num  1.35 1.4 1.36 1.33 1.32 ...
 $ Health (Life Expectancy)     : num  0.941 0.948 0.875 0.885 0.906 ...
 $ Freedom                      : num  0.666 0.629 0.649 0.67 0.633 ...
 $ Trust (Government Corruption): num  0.42 0.141 0.484 0.365 0.33 ...
 $ Generosity                   : num  0.297 0.436 0.341 0.347 0.458 ...
 $ Dystopia Residual            : num  2.52 2.7 2.49 2.47 2.45 ...
 $ latitude                     : num  46.8 65 56.3 60.5 56.1 ...
 $ longitude                    : num  8.23 -19.02 9.5 8.47 -106.35 ...
#Data type conversion

join$Region <- factor(join$Region, order = FALSE, levels = c("Australia and New Zealand", "Central and Eastern Europe", "Eastern Asia", "Latin America and Caribbean", "Middle East and Northern Africa", "North America", "Southeastern Asia", "Southern Asia", "Sub-Saharan Africa", "Western Europe"))

join$`Happiness Rank` <- factor(join$`Happiness Rank`, order = TRUE, levels = c(1:158))

str(join)
Classes ‘spec_tbl_df’, ‘tbl_df’, ‘tbl’ and 'data.frame':    147 obs. of  14 variables:
 $ Country                      : chr  "Switzerland" "Iceland" "Denmark" "Norway" ...
 $ Region                       : Factor w/ 10 levels "Australia and New Zealand",..: 10 10 10 10 6 10 10 10 1 1 ...
 $ Happiness Rank               : Ord.factor w/ 158 levels "1"<"2"<"3"<"4"<..: 1 2 3 4 5 6 7 8 9 10 ...
 $ Happiness Score              : num  7.59 7.56 7.53 7.52 7.43 ...
 $ Standard Error               : num  0.0341 0.0488 0.0333 0.0388 0.0355 ...
 $ Economy (GDP per Capita)     : num  1.4 1.3 1.33 1.46 1.33 ...
 $ Family                       : num  1.35 1.4 1.36 1.33 1.32 ...
 $ Health (Life Expectancy)     : num  0.941 0.948 0.875 0.885 0.906 ...
 $ Freedom                      : num  0.666 0.629 0.649 0.67 0.633 ...
 $ Trust (Government Corruption): num  0.42 0.141 0.484 0.365 0.33 ...
 $ Generosity                   : num  0.297 0.436 0.341 0.347 0.458 ...
 $ Dystopia Residual            : num  2.52 2.7 2.49 2.47 2.45 ...
 $ latitude                     : num  46.8 65 56.3 60.5 56.1 ...
 $ longitude                    : num  8.23 -19.02 9.5 8.47 -106.35 ...



Tidy & Manipulate Data I

join1 <- join %>% unite(`Country Coordinates`, latitude, longitude, sep = ", ")
join2 <- join1[, c(1,13,2:12)]



Tidy & Manipulate Data II

join3 <- join2 %>% mutate(`Residual Value` = (join$`Dystopia Residual` - 1.85))



Scan I

#Checking for NA values
colSums(is.na(join3))
                      Country           Country Coordinates                        Region 
                            0                             0                             0 
               Happiness Rank               Happiness Score                Standard Error 
                            0                             0                             0 
     Economy (GDP per Capita)                        Family      Health (Life Expectancy) 
                            0                             0                             0 
                      Freedom Trust (Government Corruption)                    Generosity 
                            0                             0                             0 
            Dystopia Residual                Residual Value 
                            0                             0 
#Checking for special values
special <- function(x){
  if (is.numeric(x)) (is.infinite(x) | is.nan(x))}

#Sum of special values in each column
sapply(join3, function(x){if (is.numeric(x)) sum(special(x))})
$Country
NULL

$`Country Coordinates`
NULL

$Region
NULL

$`Happiness Rank`
NULL

$`Happiness Score`
[1] 0

$`Standard Error`
[1] 0

$`Economy (GDP per Capita)`
[1] 0

$Family
[1] 0

$`Health (Life Expectancy)`
[1] 0

$Freedom
[1] 0

$`Trust (Government Corruption)`
[1] 0

$Generosity
[1] 0

$`Dystopia Residual`
[1] 0

$`Residual Value`
[1] 0



Scan II

#Boxplots before handling outliers
box_1 <- boxplot(join3$`Happiness Score`, join3$Family, join3$`Dystopia Residual`, 
                 join3$`Residual Value`, join3$`Economy (GDP per Capita)`,
                 names = c("Happiness", "Family", "Dys Residual", "Res Value", "Economy"), 
                 main = "Boxplot to detect outliers")


box_2 <- boxplot(join3$`Health (Life Expectancy)`, join3$Freedom, join3$`Standard Error`, 
                 join3$`Trust (Government Corruption)`, join3$Generosity,
                 names = c("Health", "Freedom", "Standard Err", "Trust", "Generosity"),
                 main = "Boxplot to detect outliers")


#Capping function
cap <- function(x){
  quantiles <- quantile(x, c(.05, .25, .75, .95) )
  x[ x < quantiles[2] - 1.5*IQR(x)] <- quantiles[1]
  x[ x > quantiles[3] + 1.5*IQR(x)] <- quantiles[4]
  x}

join3$`Standard Error` <- join3$`Standard Error` %>% cap()
join3$Family <- join3$Family %>% cap()
join3$`Trust (Government Corruption)` <- join3$`Trust (Government Corruption)` %>% cap()
join3$Generosity <- join3$Generosity %>% cap()
join3$`Dystopia Residual` <- join3$`Dystopia Residual` %>% cap()
join3$`Residual Value` <- join3$`Residual Value` %>% cap()

#Boxplots after removing outliers
box_3 <- boxplot(join3$`Happiness Score`, join3$Family, join3$`Dystopia Residual`, 
                 join3$`Residual Value`, join3$`Economy (GDP per Capita)`,
                 names = c("Happiness", "Family", "Dys Residual", "Res Value", "Economy"), 
                 main = "Boxplot to detect outliers")


box_4<- boxplot(join3$`Health (Life Expectancy)`, join3$Freedom, join3$`Standard Error`, 
                join3$`Trust (Government Corruption)`, join3$Generosity,
                names = c("Health", "Freedom", "Standard Err", "Trust", "Generosity"),
                main = "Boxplot to detect outliers")


boxplot(join3$`Standard Error`, main = "Boxplot of Standard Error")$out
 [1] 0.078768 0.078768 0.078768 0.078768 0.078768 0.078768 0.078768 0.078768 0.078768 0.078768 0.078768
[12] 0.078768

boxplot(join3$`Trust (Government Corruption)`, main = "Boxplot of Trust")$out
 [1] 0.405353 0.405353 0.405353 0.405353 0.405353 0.405353 0.405353 0.405353 0.405353 0.405353 0.405353
[12] 0.405353 0.405353



Transform

#Trust (Government Corruption)
hist(join3$`Trust (Government Corruption)`, main = "Histogram of Trust",
     xlab = "Trust (Government Corruption)")

sqrt_trust<- sqrt(join3$`Trust (Government Corruption)`)
hist(sqrt_trust, main = "Trust (after Transformation)",
     xlab = "Trust (Government Corruption)")


# Residual value
hist(join3$`Residual Value`, main = "Histogram of Residual Value", 
     xlab = "Residual Value")

box_residual <- BoxCox(join3$`Residual Value`, lambda = "auto")
hist(box_residual, main = "Residual Value (after Transformation)",
     xlab = "Residual Value")


# Dystopia residual
hist(join3$`Dystopia Residual`, main = "Histogram of Dystopia Residual",
     xlab = "Dystopia Residual")

box_dystopia <- BoxCox(join3$`Dystopia Residual`, lambda = "auto")
hist(box_dystopia, main = "Dystopia Residual (after Transformation)",
     xlab = "Dystopia Residual")



References



LS0tDQp0aXRsZTogIk1BVEgyMzQ5IFNlbWVzdGVyIDEsIDIwMjAiDQphdXRob3I6ICJTaWRkaGFydGggSmFjb2IgKFMzODI1MjM0KSINCnN1YnRpdGxlOiBBc3NpZ25tZW50IDINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KLS0tDQoNCg0KDQojIyBSZXF1aXJlZCBwYWNrYWdlcyANCg0KVGhlIGJlbG93IHBhY2thZ2VzIGhhdmUgYmVlbiB1c2VkIGZvciB0aGlzIGFuYWx5c2lzOg0KYGBge3J9DQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShobXMpDQpsaWJyYXJ5KG91dGxpZXJzKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShmb3JlY2FzdCkNCg0KYGBgDQo8YnI+DQo8YnI+DQoNCiMjIEV4ZWN1dGl2ZSBTdW1tYXJ5IA0KDQoqIERhdGEgcHJlcHJvY2Vzc2luZyBpcyBhIHByb2Nlc3MgYW5kIHRoZSBjb2xsZWN0aW9uIG9mIG9wZXJhdGlvbnMgbmVlZGVkIHRvIHByZXBhcmUgYWxsIGZvcm1zIG9mIHVudGlkeSBkYXRhIGZvciBzdGF0aXN0aWNhbCBhbmFseXNpcy4gDQoqIFRoZXJlIGFyZSA1IG1ham9yIHRhc2tzIGZvciBkYXRhIHByZXByb2Nlc3NpbmcgZnJhbWV3b3JrLCBuYW1lbHk6IEdldCwgVW5kZXJzdGFuZCwgVGlkeSAmIE1hbmlwdWxhdGUsIFNjYW4gYW5kIFRyYW5zZm9ybS4NCiogV2UgbG9hZCB0aGUgbmVjZXNzYXJ5IHBhY2thZ2VzIGludG8gUiByZXF1aXJlZCBmb3Igb3VyIHByb2Nlc3Nlcy4NCiogVGhlIGRhdGEgc2V0cyB3aGljaCB3YXMgZG93bmxvYWRlZCBmcm9tIGFuIG9wZW4gc291cmNlIHdlYnNpdGUgaXMgbG9hZGVkIGludG8gUiB1c2luZyByZWFkX2NzdigpIGFzIHRoZXkgd2VyZSBpbiBjc3YgZm9ybWF0LiBUaGUgaGVhZCBvZiB0aGUgZGF0YXNldHMgYXJlIGFsc28gZGlzcGxheWVkLg0KKiBOZXh0LCB3ZSBqb2luIHRoZSAyIGRhdGFzZXRzIHVzaW5nIGlubmVyX2pvaW4oKSBmdW5jdGlvbiB3aXRoIHRoZSBjb21tb24gdmFyaWFibGUgYmVpbmcg4oCcQ291bnRyeeKAnSBhbmQgZGlzcGxheSB0aGUgaGVhZCBvZiB0aGUgbmV3bHkgam9pbmVkIGRhdGEgZnJhbWUuDQoqIFdlIGNoZWNrIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGEgZnJhbWUgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIHRoZSBkYXRhIHN0cnVjdHVyZXMgYW5kIHZhcmlhYmxlIHR5cGVzLiBXZSBtYWtlIG5lY2Vzc2FyeSBkYXRhIHR5cGUgY29udmVyc2lvbnMgb24gdGhlIGRhdGEgc2V0Lg0KKiBXaGlsZSBvYnNlcnZpbmcgdGhlIGRhdGFzZXQsIHdlIHJlYWxpc2VkIHRoYXQgdGhlIHdheSBjb3VudHJ5IGNvb3JkaW5hdGVzIHdlcmUgcmVwcmVzZW50ZWQgd2FzIGluY29ycmVjdCBhbmQgdGlkeWluZyB3YXMgbmVjZXNzYXJ5IHRvIGpvaW4gdGhlIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgdmFsdWVzIGludG8gYSBzaW5nbGUgY29sdW1uLiBXZSB1c2UgdW5pdGUoKSBmdW5jdGlvbiB0byBqb2luIHRoZSBjb2x1bW5zIGdpdmluZyBjb3VudHJ5IGNvb3JkaW5hdGVzIGluIHRoZSBjb3JyZWN0IGZvcm1hdC4NCiogQSBuZXcgY29sdW1uIGlzIG11dGF0ZWQgZnJvbSBEeXN0b3BpYSBSZXNpZHVhbCBjb2x1bW4gdG8gZ2V0IHRoZSBSZXNpZHVhbCB2YWx1ZSBvZiBlYWNoIGNvbHVtbiAoUmVzaWR1YWwgVmFsdWUgPSBEeXN0b3BpYSBSZXNpZHVhbCAtMS44NSkuDQoqIE9uY2Ugd2UgYXJlIGRvbmUgd2l0aCB0aGUgdGlkeWluZyBhbmQgbWFuaXB1bGF0aW5nIHRoZSBkYXRhc2V0LCB3ZSBzY2FuIGZvciBtaXNzaW5nIHZhbHVlcy4gSXQgaXMgc2VlbiB0aGF0IHRoZXJlIGFyZSBubyBtaXNzaW5nIHZhbHVlcyBoZW5jZSB3ZSBtb3ZlIG9uIHRvIHNjYW4gZm9yIG91dGxpZXJzLg0KKiBXZSB1c2UgYm94cGxvdCBtZXRob2QgdG8gc2NhbiBmb3Igb3V0bGllcnMgb24gbnVtZXJpYyB2YXJpYWJsZXMgYW5kIHVzZSBjYXBwaW5nIGZ1bmN0aW9uIHRvIGNhcCB0aG9zZSB2YWx1ZXMgdG8gNXRoIGFuZCA5NXRoIHBlcmNlbnRpbGUgdmFsdWVzIG9mIHRoZSBkYXRhLiANCiogTGFzdGx5LCBkYXRhIHRyYW5zZm9ybWF0aW9uIGlzIHBlcmZvcm1lZCBvbiAzIHZhcmlhYmxlcyBoYXZpbmcgbm9uLW5vcm1hbCBkaXN0cmlidXRpb24uIFRoZSB0cmFuc2Zvcm1hdGlvbnMgd2VyZSBkb25lIHVzaW5nIFNxdWFyZSByb290IG1ldGhvZCBhbmQgQm94Q294IG1ldGhvZCBpbm9yZGVyIHRvIHJlZHVjZSB0aGUgc2tld25lc3MgYW5kIHRyYW5zZm9ybWluZyB0aGUgZGF0YSBpbnRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4NCg0KPGJyPg0KPGJyPg0KDQojIyBEYXRhIA0KDQpUaGUgZmlyc3QgZGF0YXNldCB1c2VkIGlzIOKAnFdvcmxkIEhhcHBpbmVzcyBSZXBvcnTigJ0gZnJvbSB0aGUgeWVhciAyMDE1LiBUaGlzIHJlcG9ydCBpcyBhIGxhbmRtYXJrIHN1cnZleSBvZiB0aGUgc3RhdGUgb2YgZ2xvYmFsIGhhcHBpbmVzcyBvZiB2YXJpb3VzIGNvdW50cmllcyBhY3Jvc3MgdGhlIGdsb2JlLiBUaGUgZGF0YSBjb25zaXN0IG9mIGEgaGFwcGluZXNzIHNjb3JlIHdoaWNoIGlzIGNhbGN1bGF0ZWQgb24gYSBzY2FsZSBvZiAwIHRvIDEwIHdoZXJlIDEwIGlzIHRoZSBoYXBwaWVzdCBhbmQgdGhlIHJlc3BlY3RpdmUgY291bnRyaWVzIHJhbmtpbmcgYW1vbmdzdCBvdGhlcnMuIFN3aXR6ZXJsYW5kIGlzIGN1cnJlbnRseSByYW5raW5nIDFzdCB3aXRoIGEgaGFwcGluZXNzIHNjb3JlIG9mIDcuNTkuIFRoZSBkaWZmZXJlbnQgY29sdW1ucyBhcmUgZGVzY3JpYmVkIGFzIGJlbG93Og0KDQoxLglDb3VudHJ5IOKAkyBOYW1lIG9mIHRoZSBjb3VudHJ5DQoyLglSZWdpb24g4oCTIFJlZ2lvbiB0aGUgY291bnRyeSBiZWxvbmdzIHRvDQozLglIYXBwaW5lc3MgUmFuayDigJMgQ291bnRyeeKAmXMgcmFuayBiYXNlZCBvbiBoYXBwaW5lc3Mgc2NvcmUNCjQuCUhhcHBpbmVzcyBTY29yZSDigJMgU2NvcmUgbWVhc3VyZWQgYnkgYXNraW5nIHNhbXBsZWQgcGVvcGxlIGhvdyB0aGV5IHdvdWxkIHJhdGUgdGhlaXIgaGFwcGluZXNzLg0KNS4JU3RhbmRhcmQgRXJyb3Ig4oCTIFRoZSBzdGFuZGFyZCBlcnJvciBvZiB0aGUgaGFwcGluZXNzIHNjb3JlDQo2LglFY29ub215IChHRFAgcGVyIENhcGl0YSkg4oCTIFRoZSBleHRlbnQgdG8gd2hpY2ggR0RQIGNvbnRyaWJ1dGVzIHRvIHRoZSBjYWxjdWxhdGlvbiBvZiBoYXBwaW5lc3MgICAgIHNjb3JlDQo3LglGYW1pbHkgLSBUaGUgZXh0ZW50IHRvIHdoaWNoIEZhbWlseSBjb250cmlidXRlcyB0byB0aGUgY2FsY3VsYXRpb24gb2YgaGFwcGluZXNzIHNjb3JlDQo4LglIZWFsdGggKExpZmUgRXhwZWN0YW5jeSkgLSBUaGUgZXh0ZW50IHRvIHdoaWNoIGhlYWx0aCBjb250cmlidXRlcyB0byB0aGUgY2FsY3VsYXRpb24gb2YgICAgICAgICAgIGhhcHBpbmVzcyBzY29yZQ0KOS4JRnJlZWRvbSAtIFRoZSBleHRlbnQgdG8gd2hpY2ggRnJlZWRvbSBjb250cmlidXRlcyB0byB0aGUgY2FsY3VsYXRpb24gb2YgaGFwcGluZXNzIHNjb3JlDQoxMC4JVHJ1c3QgKEdvdmVybm1lbnQgQ29ycnVwdGlvbikgLSBUaGUgZXh0ZW50IHRvIHdoaWNoIHBlcmNlcHRpb24gb2YgY29ycnVwdGlvbiBjb250cmlidXRlcyB0byAgICAgICB0aGUgY2FsY3VsYXRpb24gb2YgaGFwcGluZXNzIHNjb3JlDQoxMS4JR2VuZXJvc2l0eSDigJMgVGhlIGV4dGVudCB0byB3aGljaCBHZW5lcm9zaXR5IGNvbnRyaWJ1dGVzIHRvIHRoZSBjYWxjdWxhdGlvbiBvZiBoYXBwaW5lc3Mgc2NvcmUNCjEyLglEeXN0b3BpYSBSZXNpZHVhbCDigJMgSXQgaXMgdGhlIHN1bSBvZiB0aGUgZHlzdG9waWEgaGFwcGluZXNzIHNjb3JlICgxLjg1KSBpZSBzY29yZSBvZiBhICAgICAgICAgICAgaHlwb3RoZXRpY2FsIGNvdW50cnkgaGF2aW5nIHJhbmsgbG93ZXIgdGhhbiB0aGUgbG93ZXN0IHJhbmtpbmcgY291bnRyeSBpbiB0aGUgcmVwb3J0LCBwbHVzIHRoZSAgICAgcmVzaWR1YWwgdmFsdWUgb2YgZWFjaCBjb3VudHJ5IHdoaWNoIGlzIGEgbnVtYmVyIGxlZnQgb3ZlciBmcm9tIHRoZSBub3JtYWxpemF0aW9uIG9mIHRoZSAgICAgICAgICB2YXJpYWJsZXMgd2hpY2ggY2Fubm90IGJlIGV4cGxhaW5lZCkuDQoNCkJ5IGFkZGluZyB1cCBhbGwgdGhlc2UgZmFjdG9ycyBpbmNsdWRpbmcgdGhlIER5c3RvcGlhIFJlc2lkdWFsLCB3ZSBnZXQgdGhlIGhhcHBpbmVzcyBzY29yZSBmb3IgZWFjaCBjb3VudHJ5LiANCjxicj4NClRoZSBzZWNvbmQgZGF0YXNldCB1c2VkIGhlcmUgaXMg4oCcQ291bnRyaWVzIExvbmdpdHVkZSBhbmQgTGF0aXR1ZGXigJ0gd2hpY2ggZ2l2ZXMgdGhlIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgZGV0YWlscyBvZiBlYWNoIGNvdW50cnkgd2hpY2ggaXMgdXNlZCBhcyBhIHJlZmVyZW5jZSBpbiBzZXZlcmFsIGNhc2VzLiBUaGUgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSBvZiBlYWNoIGNvdW50cnkgaXMgZ2l2ZW4gaW4gU2ltcGxlIERlY2ltYWwgU3RhbmRhcmQgaW4gc2VwYXJhdGUgY29sdW1ucy4gVGhlIGNvbHVtbnMgaW4gdGhlIGRhdGFzZXQgY2FuIGJlIGV4cGxhaW5lZCBhcyBiZWxvdzoNCg0KMS4JKEJsYW5rIGNvbHVtbiB0aXRsZSkg4oCTIEdpdmVzIHRoZSBzZXJpYWwgbnVtYmVyIG9mIGNvdW50cmllcw0KMi4JTGF0aXR1ZGUg4oCTIEdpdmVzIHRoZSByZXNwZWN0aXZlIGNvdW50cnnigJlzIGxhdGl0dWRpbmFsIGNvb3JkaW5hdGVzDQozLglMb25naXR1ZGUg4oCTIEdpdmVzIHRoZSByZXNwZWN0aXZlIGNvdW50cnnigJlzIGxvbmdpdHVkaW5hbCBjb29yZGluYXRlcw0KNC4JQ291bnRyeSDigJMgTmFtZSBvZiB0aGUgY291bnRyeQ0KDQpUaGUgZGF0YXNldHMgdXNlZCB3ZXJlIG9idGFpbmVkIGZyb20gYW4gb3BlbiBzb3VyY2Ugd2Vic2l0ZTog4oCcV29ybGQgSGFwcGluZXNzIFJlcG9ydOKAnSAoaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS91bnNkc24vd29ybGQtaGFwcGluZXNzKSBhbmQg4oCcQ291bnRyaWVzIExvbmdpdHVkZSBhbmQgTGF0aXR1ZGXigJ0gKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZm9sYXJhei93b3JsZC1jb3VudHJpZXMtYW5kLWNvbnRpbmVudHMtZGV0YWlscz9zZWxlY3Q9Q291bnRyaWVzK0xvbmdpdHVkZSthbmQrTGF0aXR1ZGUuY3N2KS4NCg0KKiBGaXJzdCB0aGUgd29ya2luZyBkaXJlY3Rvcnkgd2FzIHNldCB0byBteSBwcmVmZXJlbmNlIHVzaW5nIHNldHdkKCkgZnVuY3Rpb24uDQoqIFRoZSB0d28gZGF0YXNldHMgd2hpY2ggd2VyZSBpbiBjc3YgZm9ybWF0IHdhcyByZWFkIGludG8gUiB1c2luZyByZWFkX2NzdigpLiBUaGUgaGFwcGluZXNzIHJlcG9ydCBkYXRhc2V0IGlzIHN0b3JlZCBpbiBkYXRhIGZyYW1lIOKAnEhhcHB54oCdIGFuZCBjb3VudHJpZXMgY29vcmRpbmF0ZXMgaW4g4oCcQ291bnRyeeKAnSAoY29sdW1uIHdpdGggbm8gdGl0bGUgY29uc2lzdGluZyBvZiBzZXJpYWwgbnVtYmVyIHdhcyBleGNsdWRlZCBhcyBpdCBwb3NzZXNzZWQgbm8gcmVsZXZhbmNlIHRvIG91ciBhbmFseXNpcykuDQoqIFRoZSBoZWFkIG9mIGRhdGFzZXRzIGlzIGRpc3BsYXllZCB1c2luZyBoZWFkKCkuVGhlIHR3byBkYXRhIHNldHMgaGF2ZSBDb3VudHJ5IG5hbWVzIGFzIHRoZSBjb21tb24gdmFyaWFibGUuDQoqIEFsdGhvdWdoIHRoZXJlIHdlcmUgZGlmZmVyZW50IGFwcHJvYWNoZXMgaW4gam9pbmluZyB0aGUgMiBkYXRhc2V0cywgSSB3ZW50IGFoZWFkIHVzaW5nIGlubmVyX2pvaW4oKS4gVGhlIHJlYXNvbiBiZWluZyB0aGF0IGRhdGFzZXQg4oCcSGFwcHnigJ0gY29uc2lzdGVkIG9mIDE1OCBvYnNlcnZhdGlvbnMgYW5kIGFmdGVyIHVzaW5nIGlubmVyIGpvaW4sIHRoZSByZXN1bHRhbnQgZGF0YXNldCBoYWQgMTQ3IG9ic2VydmF0aW9ucyBtZWFuaW5nIHRoYXQgMTEgY291bnRyaWVzIGluIHRoZSBmaXJzdCBkYXRhc2V0IGRpZCBub3QgaGF2ZSBjb29yZGluYXRlcyBkZXRhaWxzIGZyb20gdGhlIHNlY29uZCBkYXRhc2V0LiBBcyB0aGlzIGlzIG9ubHkgYSBzbWFsbCBwZXJjZW50YWdlIG9mIHRoZSBkYXRhc2V0LCBJIGRlY2lkZWQgdG8gb21pdCB0aG9zZSBvYnNlcnZhdGlvbiwgaGVuY2UgdXNpbmcgaW5uZXIgam9pbiB0byBqb2luIHRoZSBkYXRhc2V0cy4NCg0KYGBge3J9DQojU2V0dGluZyB0aGUgd29ya2luZyBkaXJlY3RvcnkNCnNldHdkKCJDOi9Vc2Vycy9Vc2VyL0Rlc2t0b3AvUk1JVCBjbGFzcy9EYXRhIFdyYW5nbGluZy9Bc3NpZ25tZW50IDIiKQ0KZ2V0d2QoKQ0KDQojUmVhZGluZyB0aGUgZGF0YXNldHMNCkhhcHB5IDwtIHJlYWRfY3N2KCIyMDE1LmNzdiIpDQpoZWFkKEhhcHB5KQ0KDQpDb3VudHJ5MSA8LSByZWFkX2NzdigiQ291bnRyaWVzLmNzdiIpDQpDb3VudHJ5IDwtIENvdW50cnkxWyxjKDIsMyw0KV0NCmhlYWQoQ291bnRyeSkNCg0KI0pvaW5pbmcgdGhlIDIgZGF0YXNldHMNCmpvaW4gPC0gaW5uZXJfam9pbihIYXBweSwgQ291bnRyeSwgYnkgPSAiQ291bnRyeSIpDQpoZWFkKGpvaW4pDQoNCmBgYA0KPGJyPg0KPGJyPg0KDQojIyBVbmRlcnN0YW5kIA0KDQoqIFRoZSBkYXRhIHR5cGVzIG9mIHRoZSBkYXRhIGZyYW1lIHdlcmUgY2hlY2tlZCB1c2luZyBzdHIoKSBmdW5jdGlvbi4gDQoqIFRoZSB2YXJpYWJsZSAnUmVnaW9uJyB3YXMgZmFjdG9yaXNlZCBhbmQgbGV2ZWxzIHdlcmUgc2V0IHdpdGggcmVnaW9uIG5hbWVzLiBBbHNvIHRoZSB2YXJpYWJsZSAnUmFuaycgd2FzIGNvbnZlcnRlZCB0byBvcmRlcmVkIGZhY3Rvci4NCiogVGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YSBmcmFtZSB3YXMgY2hlY2tlZCBhZnRlciB0aGUgZGF0YSB0eXBlIGNvbnZlcnNpb25zIGFuZCBhbGwgdGhlIHZhcmlhYmxlcyB3ZXJlIGluIHRoZSBjb3JyZWN0IGZvcm1hdC4NCg0KYGBge3J9DQpzdHIoam9pbikNCg0KI0RhdGEgdHlwZSBjb252ZXJzaW9uDQoNCmpvaW4kUmVnaW9uIDwtIGZhY3Rvcihqb2luJFJlZ2lvbiwgb3JkZXIgPSBGQUxTRSwgbGV2ZWxzID0gYygiQXVzdHJhbGlhIGFuZCBOZXcgWmVhbGFuZCIsICJDZW50cmFsIGFuZCBFYXN0ZXJuIEV1cm9wZSIsICJFYXN0ZXJuIEFzaWEiLCAiTGF0aW4gQW1lcmljYSBhbmQgQ2FyaWJiZWFuIiwgIk1pZGRsZSBFYXN0IGFuZCBOb3J0aGVybiBBZnJpY2EiLCAiTm9ydGggQW1lcmljYSIsICJTb3V0aGVhc3Rlcm4gQXNpYSIsICJTb3V0aGVybiBBc2lhIiwgIlN1Yi1TYWhhcmFuIEFmcmljYSIsICJXZXN0ZXJuIEV1cm9wZSIpKQ0KDQpqb2luJGBIYXBwaW5lc3MgUmFua2AgPC0gZmFjdG9yKGpvaW4kYEhhcHBpbmVzcyBSYW5rYCwgb3JkZXIgPSBUUlVFLCBsZXZlbHMgPSBjKDE6MTU4KSkNCg0Kc3RyKGpvaW4pDQpgYGANCjxicj4NCjxicj4NCg0KIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJIA0KDQoqIEluIG15IGRhdGEgZnJhbWUgKGpvaW4pIHRoZSBjb2x1bW5zIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgYXJlIHVudGlkeS4NCiogTG9jYXRpb24gY29vcmRpbmF0ZXMgYXJlIHJlcHJlc2VudGVkIGluIHZhcmlvdXMgZm9ybWF0cy4gRm9yIGV4YW1wbGUgRGVjaW1hbCBjb29yZGluYXRlcyAoMjAuNTkzNjgzMiwgNzguOTYyODgzKSwgRGVjaW1hbCBEZWdyZWVzIENvb3JkaW5hdGVzICgyMC41OTM3wrAgTiA3OC45NjI5wrAgRSkgYW5kIERNUyAoRGVncmVlcywgTWludXRlcyBhbmQgU2Vjb25kcykgQ29vcmRpbmF0ZXMgKDIwwrAzNSczNy4zJycgTiA3OMKwNTcnNDYuNCcnIEUpLiBXaGVuIHlvdSBsb29rIHVwIGFueSBsb2NhdGlvbiBvbiBnb29nbGUgbWFwcywgdGhlIGFkZHJlc3Mgb2YgdGhhdCBsb2NhdGlvbiB3b3VsZCBhbHNvIGdpdmUgdGhlIGNvb3JkaW5hdGVzIHdyaXR0ZW4gaW4gRGVjaW1hbCBEZWdyZWVzIGZvcm1hdC4gDQoqIExvY2F0aW9uIGNvb3JkaW5hdGVzIGJ5IGRlZmF1bHQgaXMgd3JpdHRlbiB3aXRoIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgdG9nZXRoZXIgYW5kIG5vdCBzZXBlcmF0ZWx5LiBUaGlzIGxpbmsgc2hvd3MgdGhlIGZvcm1hdHMgaW4gd2hpY2ggbG9jYXRpb24gY29vcmRpbmF0ZXMgYXJlIHdyaXR0ZW4gKGh0dHBzOi8vd3d3Lndpa2lob3cuY29tL1dyaXRlLUxhdGl0dWRlLWFuZC1Mb25naXR1ZGUjOn46dGV4dD1TdGFydCUyMHdpdGglMjB5b3VyJTIwbGluZSUyMG9mLG9yJTIwV2VzdCUyMGFzJTIwdGhlJTIwZGlyZWN0aW9uLikNCiogSWYgdGhlIGNvb3JkaW5hdGVzIGFyZSB3cml0dGVuIGluIHRoZSBjb3JyZWN0IGZvcm1hdCwgaXQgd291bGQgYmUgaGVscGZ1bCB3aGlsZSBleHBvcnRpbmcgdGhlIGRhdGEgaW50byBhIEdQUyBzb2Z0d2FyZSBmb3IgcGxvdHRpbmcgdGhlbSBvbiB0aGUgbWFwLg0KKiBJbiBteSBkYXRhIGZyYW1lLCB0aGUgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSBpcyB3cml0dGVuIHNlcGVyYXRlbHkuIFRoZXJlZm9yZSwgSSB1bml0ZSB0aG9zZSB0d28gY29sdW1ucyB1c2luZyB1bml0ZSgpIHdpdGggc2VwPSIsICIuDQoqIFRoZSBuZXcgY29sdW1uIGNyZWF0ZWQgYnkgdW5pdGluZyB0aGUgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSBpcyBjYWxsZWQgIkNvdW50cnkgQ29vcmRpbmF0ZXMiLg0KKiBUaGUgY29sdW1ucyBoYXZlIGJlZW4gcmUtYXJyYW5nZWQgdG8gcGxhY2UgdGhlIG5ldyBjb2x1bW4gbmV4dCB0byB0aGUgY291bnRyeSBuYW1lcy4NCg0KYGBge3J9DQpqb2luMSA8LSBqb2luICU+JSB1bml0ZShgQ291bnRyeSBDb29yZGluYXRlc2AsIGxhdGl0dWRlLCBsb25naXR1ZGUsIHNlcCA9ICIsICIpDQpqb2luMiA8LSBqb2luMVssIGMoMSwxMywyOjEyKV0NCg0KYGBgDQo8YnI+DQo8YnI+DQoNCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSUkgDQoNCiogSW4gb3VyIGRhdGFzZXQsIER5c3RvcGlhIFJlc2lkdWFsIGlzIG1lYXN1cmVkIGFzIHRoZSBzdW0gb2YgRHlzdG9waWEgaGFwcGluZXNzIHNjb3JlIGFuZCByZXNpZHVhbCB2YWx1ZSBvZiBlYWNoIGNvdW50cnkuDQoqIFRoZSBEeXN0b3BpYSBoYXBwaW5lc3Mgc2NvcmUgYXMgbWVudGlvbmVkIGVhcmxpZXIgaXMgYSBjb25zdGFudCB2YWx1ZSAoMS44NSkgd2hpY2ggaXMgc2FtZSBmb3IgYWxsIGNvdW50cmllcy4NCiogSW5vcmRlciB0byBjaGVjayB0aGUgcmVzaWR1YWwgdmFsdWUgb2YgZWFjaCBjb3VucnksIHdlIHVzZSBtdXRhdGUoKSBmdW5jdGlvbiB0byBjcmVhdGUgYSBuZXcgdmFyaWFibGUgYnkgcHJlc2VydmluZyB0aGUgZXhpc3RpbmcgdmFyaWFibGUuIA0KKiBXZSBuYW1lIHRoZSBuZXcgdmFyaWFibGUgIlJlc2lkdWFsIFZhbHVlIiBhbmQgaXQgaXMgY2FsY3VsYXRlZCBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIER5c3RvcGlhIHJlc2lkdWFsIG9mIGVhY2ggY291bnRyeSBhbmQgMS44NS4NCiogVGhlIHJlc2lkdWFsIHZhbHVlIGlzIGRpcmVjdGx5IHByb3BvcnRpb25hbCB0byB0aGUgZHlzdG9waWEgcmVzaWR1YWwgbWVhbmluZyBhcyB0aGUgcmVzaWR1YWwgdmFsdWUgaW5jcmVhc2VzLCBkeXN0b3BpYSByZXNpZHVhbCBpbmNyZWFzZXMuDQoNCg0KYGBge3J9DQpqb2luMyA8LSBqb2luMiAlPiUgbXV0YXRlKGBSZXNpZHVhbCBWYWx1ZWAgPSAoam9pbiRgRHlzdG9waWEgUmVzaWR1YWxgIC0gMS44NSkpDQoNCmBgYA0KPGJyPg0KPGJyPg0KDQojIwlTY2FuIEkgDQoNCiogV2UgY2hlY2sgZm9yIE5BIHZhbHVlcyBpbiBvdXIgZGF0YXNldCBieSBpbmNvcnBvcmF0aW5nIGlzLm5hKCkgd2l0aGluIGNvbFN1bXMoKSBzbyBhcyB0byBnZXQgdGhlIHN1bSBvZiBOQSB2YWx1ZXMgaW4gZWFjaCBjb2x1bW4uIA0KKiBCeSBydW5uaW5nIHRoZSBjb2RlLCB3ZSBzZWUgdGhhdCB0aGVyZSBhcmUgbm8gTkEgdmFsdWVzIGluIG91ciBkYXRhc2V0Lg0KKiBUaGUgbmV4dCBzdGVwIGlzIHRvIGNoZWNrIGZvciBzcGVjaWFsIHZhbHVlcyAoLUluZiwgSW5mLCBOYW4pLg0KKiBJbm9yZGVyIHRvIGNoZWNrIGFsbCBudW1lcmljIGNvbHVtbnMgZm9yIHRoZSBwcmVzZW5jZSBvZiBzcGVjaWFsIHZhbHVlcywgd2UgY3JlYXRlIGEgZnVuY3Rpb24gY2FsbGVkICJzcGVjaWFsIi4gVGhlIGZ1bmN0aW9uIGNoZWNrcyBhbGwgb2JlcnZhdGlvbnMgd2hldGhlciBpZiBpdHMgYSBzcGVjaWFsIHZhbHVlIGFuZCB0aGUgcmVzdWx0IGlzIGluIGxvZ2ljYWwgZm9ybSAoVFJVRSBpZiBzcGVjaWFsIHZhbHVlcyBhcmUgZGV0ZWN0ZWQsIEZBTFNFIGlmIG5vdCBhIHNwZWNpYWwgdmFsdWUpLg0KKiBUbyBnZXQgdGhlIHN1bSBvZiBzcGVjaWFsIHZhbHVlcyBpbiBlYWNoIGNvbHVtbiwgd2UgdXNlIHNhcHBseSgpIGZ1bmN0aW9uIGFzIGdpdmVuIGJlbG93LiBUaGlzIHdvdWxkIGdpdmUgdGhlIGNvdW50IG9mIHNwZWNpYWwgdmFsdWVzIGluIGVhY2ggY29sdW1uIG9mIG91ciBkYXRhc2V0Lg0KDQoNCmBgYHtyfQ0KI0NoZWNraW5nIGZvciBOQSB2YWx1ZXMNCmNvbFN1bXMoaXMubmEoam9pbjMpKQ0KDQojQ2hlY2tpbmcgZm9yIHNwZWNpYWwgdmFsdWVzDQpzcGVjaWFsIDwtIGZ1bmN0aW9uKHgpew0KICBpZiAoaXMubnVtZXJpYyh4KSkgKGlzLmluZmluaXRlKHgpIHwgaXMubmFuKHgpKX0NCg0KI1N1bSBvZiBzcGVjaWFsIHZhbHVlcyBpbiBlYWNoIGNvbHVtbg0Kc2FwcGx5KGpvaW4zLCBmdW5jdGlvbih4KXtpZiAoaXMubnVtZXJpYyh4KSkgc3VtKHNwZWNpYWwoeCkpfSkNCg0KYGBgDQo8YnI+DQo8YnI+DQoNCiMjCVNjYW4gSUkNCg0KKiBPbmNlIHdlIGhhdmUgc2Nhbm5lZCBmb3IgTkEgdmFsdWVzIGFuZCBzcGVjaWFsIHZhbHVlcywgdGhlIG5leHQgc3RlcCBpcyB0byBoYW5kbGUgdGhlIG91dGxpZXJzIHByZXNlbnQgaW4gb3VyIGRhdGFzZXQuDQoqIFdlIHVzZSBib3hwbG90IG1ldGhvZCB0byBkZXRlY3QgdGhlIHVuaXZhcmlhdGUgdmFyaWFibGVzIChhcyBvdXIgdmFyaWFibGVzIGFyZSBub3QgZGVwZW5kZW50IG9uIGVhY2ggb3RoZXIpDQoqIEJ5IG9ic2VydmluZyB0aGUgYm94cGxvdHMsIHdlIHNlZSB0aGF0IDYgb3V0IG9mIDEwIHZhcmlhYmxlcyBhcmUgaGF2aW5nIG91dGxpZXJzLiBXZSB1c2UgY2FwcGluZyBtZXRob2QgdG8gaGFuZGxlIHRoZSBvdXRsaWVycy4NCiogQ2FwcGluZyBwcm9jZXNzIGludm9sdmVzIGluIHJlcGxhY2luZyB0aGUgb3V0bGllcnMgd2l0aCB0aGUgbmVhcmVzdCBuZWlnaGJvdXJpbmcgdmFsdWVzIHRoYXQgYXJlIG5vdCBvdXRsaWVycy4gQXMgYW4gZXhhbXBsZSwgZm9yIG91dGxpZXJzIHRoYXQgbGllIG91dHNpZGUgdGhlIG91dGxpZXIgZmVuY2Ugd2UgY2FwIGl0IGJ5IHJlcGxhY2luZyB0aG9zZSB2YWx1ZXMgb3V0c2lkZSB0aGUgbG93ZXIgbGltaXQgd2l0aCB0aGUgdmFsdWUgb2YgNSB0aCBwZXJjZW50aWxlIGFuZCBmb3IgdGhvc2UgdGhhdCBsaWUgYWJvdmUgdGhlIHVwcGVyIGxpbWl0IHdpdGggdGhlIDk1IHRoIHBlcmNlbnRpbGUgdmFsdWUuDQoqIFdlIGNoZWNrIHRoZSBib3hwbG90cyBvbmNlIGFnYWluIGFmdGVyIGFwcGx5aW5nIGNhcHBpbmcgZnVuY3Rpb24gb24gdGhlIHZhcmlhYmxlcyBoYXZpbmcgb3V0bGllcnMuIA0KKiBXaGlsZSBvYnNlcnZpbmcgdGhlIGJveHBsb3RzLCB3ZSBzZWUgdGhhdCB0aGUgJ1N0YW5kYXJkIEVycm9yJyBhbmQgJ1RydXN0IChHb3Zlcm5tZW50IENvcnJ1cHRpb24pJyBhcmUgc2hvd2luZyB0aGUgcHJlc2VuY2Ugb2Ygb3V0bGllcnMgb24gdGhlIGJveHBsb3QuIFRoZXkgYXJlIGFjdHVhbGx5IHRoZSBvdXRsaWVyIGZlbmNlIHZhbHVlIHdoaWNoIGFjdHMgYXMgYSBiYXJyaWVyIGJldHdlZW4gb3V0bGllcnMgYW5kIG5vbiBvdXRsaWVyIHZhbHVlcy4gSW4gb3JkZXIgdG8gY29uZmlybSB0aGlzLCB3ZSB1c2UgbGVuZ3RoKCkgb24gdGhlIGJveHBsb3RzIG9mIHRob3NlIHR3byB2YXJpYWJsZXMuIA0KDQpgYGB7cn0NCiNCb3hwbG90cyBiZWZvcmUgaGFuZGxpbmcgb3V0bGllcnMNCmJveF8xIDwtIGJveHBsb3Qoam9pbjMkYEhhcHBpbmVzcyBTY29yZWAsIGpvaW4zJEZhbWlseSwgam9pbjMkYER5c3RvcGlhIFJlc2lkdWFsYCwgDQogICAgICAgICAgICAgICAgIGpvaW4zJGBSZXNpZHVhbCBWYWx1ZWAsIGpvaW4zJGBFY29ub215IChHRFAgcGVyIENhcGl0YSlgLA0KICAgICAgICAgICAgICAgICBuYW1lcyA9IGMoIkhhcHBpbmVzcyIsICJGYW1pbHkiLCAiRHlzIFJlc2lkdWFsIiwgIlJlcyBWYWx1ZSIsICJFY29ub215IiksIA0KICAgICAgICAgICAgICAgICBtYWluID0gIkJveHBsb3QgdG8gZGV0ZWN0IG91dGxpZXJzIikNCg0KYm94XzIgPC0gYm94cGxvdChqb2luMyRgSGVhbHRoIChMaWZlIEV4cGVjdGFuY3kpYCwgam9pbjMkRnJlZWRvbSwgam9pbjMkYFN0YW5kYXJkIEVycm9yYCwgDQogICAgICAgICAgICAgICAgIGpvaW4zJGBUcnVzdCAoR292ZXJubWVudCBDb3JydXB0aW9uKWAsIGpvaW4zJEdlbmVyb3NpdHksDQogICAgICAgICAgICAgICAgIG5hbWVzID0gYygiSGVhbHRoIiwgIkZyZWVkb20iLCAiU3RhbmRhcmQgRXJyIiwgIlRydXN0IiwgIkdlbmVyb3NpdHkiKSwNCiAgICAgICAgICAgICAgICAgbWFpbiA9ICJCb3hwbG90IHRvIGRldGVjdCBvdXRsaWVycyIpDQoNCiNDYXBwaW5nIGZ1bmN0aW9uDQpjYXAgPC0gZnVuY3Rpb24oeCl7DQogIHF1YW50aWxlcyA8LSBxdWFudGlsZSh4LCBjKC4wNSwgLjI1LCAuNzUsIC45NSkgKQ0KICB4WyB4IDwgcXVhbnRpbGVzWzJdIC0gMS41KklRUih4KV0gPC0gcXVhbnRpbGVzWzFdDQogIHhbIHggPiBxdWFudGlsZXNbM10gKyAxLjUqSVFSKHgpXSA8LSBxdWFudGlsZXNbNF0NCiAgeH0NCg0Kam9pbjMkYFN0YW5kYXJkIEVycm9yYCA8LSBqb2luMyRgU3RhbmRhcmQgRXJyb3JgICU+JSBjYXAoKQ0Kam9pbjMkRmFtaWx5IDwtIGpvaW4zJEZhbWlseSAlPiUgY2FwKCkNCmpvaW4zJGBUcnVzdCAoR292ZXJubWVudCBDb3JydXB0aW9uKWAgPC0gam9pbjMkYFRydXN0IChHb3Zlcm5tZW50IENvcnJ1cHRpb24pYCAlPiUgY2FwKCkNCmpvaW4zJEdlbmVyb3NpdHkgPC0gam9pbjMkR2VuZXJvc2l0eSAlPiUgY2FwKCkNCmpvaW4zJGBEeXN0b3BpYSBSZXNpZHVhbGAgPC0gam9pbjMkYER5c3RvcGlhIFJlc2lkdWFsYCAlPiUgY2FwKCkNCmpvaW4zJGBSZXNpZHVhbCBWYWx1ZWAgPC0gam9pbjMkYFJlc2lkdWFsIFZhbHVlYCAlPiUgY2FwKCkNCg0KI0JveHBsb3RzIGFmdGVyIHJlbW92aW5nIG91dGxpZXJzDQpib3hfMyA8LSBib3hwbG90KGpvaW4zJGBIYXBwaW5lc3MgU2NvcmVgLCBqb2luMyRGYW1pbHksIGpvaW4zJGBEeXN0b3BpYSBSZXNpZHVhbGAsIA0KICAgICAgICAgICAgICAgICBqb2luMyRgUmVzaWR1YWwgVmFsdWVgLCBqb2luMyRgRWNvbm9teSAoR0RQIHBlciBDYXBpdGEpYCwNCiAgICAgICAgICAgICAgICAgbmFtZXMgPSBjKCJIYXBwaW5lc3MiLCAiRmFtaWx5IiwgIkR5cyBSZXNpZHVhbCIsICJSZXMgVmFsdWUiLCAiRWNvbm9teSIpLCANCiAgICAgICAgICAgICAgICAgbWFpbiA9ICJCb3hwbG90IHRvIGRldGVjdCBvdXRsaWVycyIpDQoNCmJveF80PC0gYm94cGxvdChqb2luMyRgSGVhbHRoIChMaWZlIEV4cGVjdGFuY3kpYCwgam9pbjMkRnJlZWRvbSwgam9pbjMkYFN0YW5kYXJkIEVycm9yYCwgDQogICAgICAgICAgICAgICAgam9pbjMkYFRydXN0IChHb3Zlcm5tZW50IENvcnJ1cHRpb24pYCwgam9pbjMkR2VuZXJvc2l0eSwNCiAgICAgICAgICAgICAgICBuYW1lcyA9IGMoIkhlYWx0aCIsICJGcmVlZG9tIiwgIlN0YW5kYXJkIEVyciIsICJUcnVzdCIsICJHZW5lcm9zaXR5IiksDQogICAgICAgICAgICAgICAgbWFpbiA9ICJCb3hwbG90IHRvIGRldGVjdCBvdXRsaWVycyIpDQoNCmJveHBsb3Qoam9pbjMkYFN0YW5kYXJkIEVycm9yYCwgbWFpbiA9ICJCb3hwbG90IG9mIFN0YW5kYXJkIEVycm9yIikkb3V0DQpib3hwbG90KGpvaW4zJGBUcnVzdCAoR292ZXJubWVudCBDb3JydXB0aW9uKWAsIG1haW4gPSAiQm94cGxvdCBvZiBUcnVzdCIpJG91dA0KDQpgYGANCjxicj4NCjxicj4NCg0KIyMJVHJhbnNmb3JtIA0KDQoqIFRoZSBsYXN0IHN0ZXAgaW4gb3VyIGFuYWx5c2lzIGlzIHRvIHBlcmZvcm0gdHJhbnNmb3JtYXRpb24uIFdlIHBlcmZvcm0gZGF0YSB0cmFuc2Zvcm1hdGlvbiB0byBzdGFuZGFyZGlzZSB0aGUgdmFyaWFibGVzLCB0byBtYWtlIHRoZSByZWxhdGlvbnNoaXBzIGxpbmVhciBhbmQgZXZlbiB0byBtYWtlIHRoZSBkaXN0cmlidXRpb24gbGVzcyBza2V3ZWQuDQoqIFdlIHBlcmZvcm0gZGF0YSB0cmFuc2Zvcm1hdGlvbiBvbiAzIHZhcmlhYmxlcyBoZXJlOiBSZXNpZHVhbCBWYWx1ZSwgRHlzdG9waWEgUmVzaWR1YWwgYW5kIFRydXN0IChHb3Zlcm5tZW50IENvcnJ1cHRpb24pLg0KKiBPbiBjaGVja2luZyB0aGUgaGlzdG9ncmFtIGZvciBUcnVzdCwgd2Ugc2VlIHRoYXQgaXQgaXMgc2tld2VkIHRvd2FyZHMgdGhlIHJpZ2h0LiBXZSB1c2Ugc3F1YXJlIHJvb3QgdHJhbnNmb3JtYXRpb24gbWV0aG9kIGFzIGl0IGNhbiByZWR1Y2UgcmlnaHQgc2tld25lc3MgYW5kIGNhbiBhbHNvIGJlIGFwcGxpZWQgdG8gemVybyB2YWx1ZXMuIFRoZSBmdW5jdGlvbiBzcXJ0KCkgd2lsbCBhcHBseSBzcXVhcmUgcm9vdCB0cmFuZm9ybWF0aW9uIGFuZCBhIGhpc3RvZ3JhbSBpcyBwbG90dGVkIHBvc3QgdHJhbnNmb3JtYXRpb24gd2hlcmUgdGhlIGRpc3RyaWJ1dGlvbiBpcyBzZWVuIGJlIG5vcm1hbC4NCiogTmV4dCB3ZSBjaGVjayB0aGUgaGlzdG9ncmFtIGZvciBSZXNpZHVhbCBWYWx1ZS4gQWx0aG91Z2ggdGhlIGRpc3RyaWJ1dGlvbiBzZWVtcyB0byBiZSBub3JtYWwsIGl0IGlzIG5vdCBwZXJmZWN0LiBCb3gtQ294IG1ldGhvZCBpcyBhIHR5cGUgb2YgcG93ZXIgdHJhbnNmb3JtYXRpb24gdXNlZCB0byB0cmFuc2Zvcm0gbm9uLW5vcm1hbCBkYXRhIGludG8gbm9ybWFsIGRpc3RyaWJ1dGlvbi4gV2UgdXNlIHRoZSBwYWNrYWdlICJmb3JlY2FzdCIgdG8gcGVyZm9ybSB0aGlzIGZ1bmN0aW9uLiBUbyBnZXQgdGhlIGJlc3QgQm94LUNveCB0cmFuc2Zvcm1hdGlvbiwgd2UgdXNlIEJveENveCgpIGZ1bmN0aW9uIHVzaW5nIGxhbWJkYT0iYXV0byIgYXJndW1lbnQuIFVwb24gcGxvdHRpbmcgdGhlIGhpc3RvZ3JhbSBhZnRlciB0aGUgdHJhbnNmb3JtYXRpb24sIHdlIHNlZSB0aGF0IHRoZSBkaXN0cmlidXRpb24gaXMgcGVyZmVjdGx5IG5vcm1hbC4NCiogV2UgY2hlY2sgdGhlIGhpc3RvZ3JhbSBmb3IgRHlzdG9waWEgUmVzaWR1YWwuIFRoaXMgYWxzbyBhcHBlYXJzIHRvIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGJ1dCBub3QgcGVyZmVjdGx5IHN5bW1ldHJpYy4gSGVyZSBhbHNvIHdlIHBlcmZvcm0gQm94Q294KCkgZnVuY3Rpb24gd2l0aCBsYWJtZGE9ImF1dG8iLiBUaGUgaGlzdG9ncmFtIGFmdGVyIHRyYW5zZm9ybWF0aW9uIGdpdmVzIGEgbXVjaCBiZXR0ZXIgc3ltbWV0cmljIGxvb2tpbmcgZGlzdHJpYnV0aW9uLg0KDQpgYGB7cn0NCiNUcnVzdCAoR292ZXJubWVudCBDb3JydXB0aW9uKQ0KaGlzdChqb2luMyRgVHJ1c3QgKEdvdmVybm1lbnQgQ29ycnVwdGlvbilgLCBtYWluID0gIkhpc3RvZ3JhbSBvZiBUcnVzdCIsDQogICAgIHhsYWIgPSAiVHJ1c3QgKEdvdmVybm1lbnQgQ29ycnVwdGlvbikiKQ0Kc3FydF90cnVzdDwtIHNxcnQoam9pbjMkYFRydXN0IChHb3Zlcm5tZW50IENvcnJ1cHRpb24pYCkNCmhpc3Qoc3FydF90cnVzdCwgbWFpbiA9ICJUcnVzdCAoYWZ0ZXIgVHJhbnNmb3JtYXRpb24pIiwNCiAgICAgeGxhYiA9ICJUcnVzdCAoR292ZXJubWVudCBDb3JydXB0aW9uKSIpDQoNCiMgUmVzaWR1YWwgdmFsdWUNCmhpc3Qoam9pbjMkYFJlc2lkdWFsIFZhbHVlYCwgbWFpbiA9ICJIaXN0b2dyYW0gb2YgUmVzaWR1YWwgVmFsdWUiLCANCiAgICAgeGxhYiA9ICJSZXNpZHVhbCBWYWx1ZSIpDQpib3hfcmVzaWR1YWwgPC0gQm94Q294KGpvaW4zJGBSZXNpZHVhbCBWYWx1ZWAsIGxhbWJkYSA9ICJhdXRvIikNCmhpc3QoYm94X3Jlc2lkdWFsLCBtYWluID0gIlJlc2lkdWFsIFZhbHVlIChhZnRlciBUcmFuc2Zvcm1hdGlvbikiLA0KICAgICB4bGFiID0gIlJlc2lkdWFsIFZhbHVlIikNCg0KIyBEeXN0b3BpYSByZXNpZHVhbA0KaGlzdChqb2luMyRgRHlzdG9waWEgUmVzaWR1YWxgLCBtYWluID0gIkhpc3RvZ3JhbSBvZiBEeXN0b3BpYSBSZXNpZHVhbCIsDQogICAgIHhsYWIgPSAiRHlzdG9waWEgUmVzaWR1YWwiKQ0KYm94X2R5c3RvcGlhIDwtIEJveENveChqb2luMyRgRHlzdG9waWEgUmVzaWR1YWxgLCBsYW1iZGEgPSAiYXV0byIpDQpoaXN0KGJveF9keXN0b3BpYSwgbWFpbiA9ICJEeXN0b3BpYSBSZXNpZHVhbCAoYWZ0ZXIgVHJhbnNmb3JtYXRpb24pIiwNCiAgICAgeGxhYiA9ICJEeXN0b3BpYSBSZXNpZHVhbCIpDQoNCmBgYA0KPGJyPg0KPGJyPg0KDQojIyBSZWZlcmVuY2VzDQoNCiogS2FnZ2xlLmNvbS4gMjAxOS4gV29ybGQgSGFwcGluZXNzIFJlcG9ydC4gW29ubGluZV0gQXZhaWxhYmxlIGF0OiA8aHR0cHM6Ly93d3cua2FnZ2xlLmNvbS91bnNkc24vd29ybGQtaGFwcGluZXNzPg0KDQoqIEthZ2dsZS5jb20uIDIwMTcuIFdvcmxkIENvdW50cmllcyBBbmQgQ29udGluZW50cyBEZXRhaWxzLiBbb25saW5lXSBBdmFpbGFibGUgYXQ6IDxodHRwczovL3d3dy5rYWdnbGUuY29tL2ZvbGFyYXovd29ybGQtY291bnRyaWVzLWFuZC1jb250aW5lbnRzLWRldGFpbHM/c2VsZWN0PUNvdW50cmllcytMb25naXR1ZGUrYW5kK0xhdGl0dWRlLmNzdj4NCg0KKiBEb2xndW4sIEFuaWwgMjAxMCwg4oCYRGF0YSBXcmFuZ2xpbmfigJksIGxlY3R1cmUgbm90ZXMsIE1BVEgyMzQ5LCBSTUlUIFVuaXZlcnNpdHksIDxodHRwOi8vcmFyZS1waG9lbml4LTE2MTYxMC5hcHBzcG90LmNvbS9zZWN1cmVkL2luZGV4Lmh0bWw+DQoNCiogQmFnbGluLCBKYW1lcyAyMDEwLCDigJhBcHBsaWVkIEFuYWx5dGljc+KAmSwgbGVjdHVyZSBub3RlcywgTUFUSDEzMjQsIFJNSVQgVW5pdmVyc2l0eSwgPGh0dHBzOi8vYXN0cmFsLXRoZW9yeS0xNTc1MTAuYXBwc3BvdC5jb20vc2VjdXJlZC9pbmRleC5odG1sPg0KDQoqIHdpa2lIb3cuIDIwMjAuIEhvdyBUbyBXcml0ZSBMYXRpdHVkZSBBbmQgTG9uZ2l0dWRlLiBbb25saW5lXSBBdmFpbGFibGUgYXQ6IDxodHRwczovL3d3dy53aWtpaG93LmNvbS9Xcml0ZS1MYXRpdHVkZS1hbmQtTG9uZ2l0dWRlIzp+OnRleHQ9U3RhcnQlMjB3aXRoJTIweW91ciUyMGxpbmUlMjBvZixvciUyMFdlc3QlMjBhcyUyMHRoZSUyMGRpcmVjdGlvbi4+DQoNCjxicj4NCjxicj4NCg==