wHappiness_Df <- read.csv("C:/Users/PC/Documents/R_4DS/WorldHappinessReport/world-happiness-report-2021.csv")
glimpse(wHappiness_Df)
Rows: 149
Columns: 20
$ ï..Country.name                            <fct> Finland, Denmark, Switzerland, Iceland, Netherlands, Norway, Sweden, Luxembourg, ~
$ Regional.indicator                         <fct> Western Europe, Western Europe, Western Europe, Western Europe, Western Europe, W~
$ Ladder.score                               <dbl> 7.842, 7.620, 7.571, 7.554, 7.464, 7.392, 7.363, 7.324, 7.277, 7.268, 7.183, 7.15~
$ Standard.error.of.ladder.score             <dbl> 0.032, 0.035, 0.036, 0.059, 0.027, 0.035, 0.036, 0.037, 0.040, 0.036, 0.041, 0.03~
$ upperwhisker                               <dbl> 7.904, 7.687, 7.643, 7.670, 7.518, 7.462, 7.433, 7.396, 7.355, 7.337, 7.265, 7.22~
$ lowerwhisker                               <dbl> 7.780, 7.552, 7.500, 7.438, 7.410, 7.323, 7.293, 7.252, 7.198, 7.198, 7.102, 7.09~
$ Logged.GDP.per.capita                      <dbl> 10.775, 10.933, 11.117, 10.878, 10.932, 11.053, 10.867, 11.647, 10.643, 10.906, 1~
$ Social.support                             <dbl> 0.954, 0.954, 0.942, 0.983, 0.942, 0.954, 0.934, 0.908, 0.948, 0.934, 0.940, 0.93~
$ Healthy.life.expectancy                    <dbl> 72.000, 72.700, 74.400, 73.000, 72.400, 73.300, 72.700, 72.600, 73.400, 73.300, 7~
$ Freedom.to.make.life.choices               <dbl> 0.949, 0.946, 0.919, 0.955, 0.913, 0.960, 0.945, 0.907, 0.929, 0.908, 0.914, 0.80~
$ Generosity                                 <dbl> -0.098, 0.030, 0.025, 0.160, 0.175, 0.093, 0.086, -0.034, 0.134, 0.042, 0.159, 0.~
$ Perceptions.of.corruption                  <dbl> 0.186, 0.179, 0.292, 0.673, 0.338, 0.270, 0.237, 0.386, 0.242, 0.481, 0.442, 0.75~
$ Ladder.score.in.Dystopia                   <dbl> 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.4~
$ Explained.by..Log.GDP.per.capita           <dbl> 1.446, 1.502, 1.566, 1.482, 1.501, 1.543, 1.478, 1.751, 1.400, 1.492, 1.453, 1.37~
$ Explained.by..Social.support               <dbl> 1.106, 1.108, 1.079, 1.172, 1.079, 1.108, 1.062, 1.003, 1.094, 1.062, 1.076, 1.07~
$ Explained.by..Healthy.life.expectancy      <dbl> 0.741, 0.763, 0.816, 0.772, 0.753, 0.782, 0.763, 0.760, 0.785, 0.782, 0.801, 0.78~
$ Explained.by..Freedom.to.make.life.choices <dbl> 0.691, 0.686, 0.653, 0.698, 0.647, 0.703, 0.685, 0.639, 0.665, 0.640, 0.647, 0.50~
$ Explained.by..Generosity                   <dbl> 0.124, 0.208, 0.204, 0.293, 0.302, 0.249, 0.244, 0.166, 0.276, 0.215, 0.291, 0.20~
$ Explained.by..Perceptions.of.corruption    <dbl> 0.481, 0.485, 0.413, 0.170, 0.384, 0.427, 0.448, 0.353, 0.445, 0.292, 0.317, 0.11~
$ Dystopia...residual                        <dbl> 3.253, 2.868, 2.839, 2.967, 2.798, 2.580, 2.683, 2.653, 2.612, 2.784, 2.598, 3.08~

Data Inspection and Cleaning

## Check for missing values
null_vars <- (sapply(wHappiness_Df, function(x) sum(is.na(x))))
t(data.frame(null_vars))
          ï..Country.name Regional.indicator Ladder.score Standard.error.of.ladder.score upperwhisker lowerwhisker
null_vars               0                  0            0                              0            0            0
          Logged.GDP.per.capita Social.support Healthy.life.expectancy Freedom.to.make.life.choices Generosity
null_vars                     0              0                       0                            0          0
          Perceptions.of.corruption Ladder.score.in.Dystopia Explained.by..Log.GDP.per.capita Explained.by..Social.support
null_vars                         0                        0                                0                            0
          Explained.by..Healthy.life.expectancy Explained.by..Freedom.to.make.life.choices Explained.by..Generosity
null_vars                                     0                                          0                        0
          Explained.by..Perceptions.of.corruption Dystopia...residual
null_vars                                       0                   0
## Checking for Blank Values
wHappiness_Df[wHappiness_Df == "",]

No missing or empty values, go-to-go.

names(wHappiness_Df)
 [1] "ï..Country.name"                            "Regional.indicator"                        
 [3] "Ladder.score"                               "Standard.error.of.ladder.score"            
 [5] "upperwhisker"                               "lowerwhisker"                              
 [7] "Logged.GDP.per.capita"                      "Social.support"                            
 [9] "Healthy.life.expectancy"                    "Freedom.to.make.life.choices"              
[11] "Generosity"                                 "Perceptions.of.corruption"                 
[13] "Ladder.score.in.Dystopia"                   "Explained.by..Log.GDP.per.capita"          
[15] "Explained.by..Social.support"               "Explained.by..Healthy.life.expectancy"     
[17] "Explained.by..Freedom.to.make.life.choices" "Explained.by..Generosity"                  
[19] "Explained.by..Perceptions.of.corruption"    "Dystopia...residual"                       
## Tidying the Column Name
colClean <- function(x){
  colnames(x) <- gsub("\\.\\.+",".", colnames(x));
  x
}

wHappiness_Df <- colClean(wHappiness_Df) %>% 
  rename(Country = ï.Country.name)
names(wHappiness_Df)
 [1] "Country"                                   "Regional.indicator"                       
 [3] "Ladder.score"                              "Standard.error.of.ladder.score"           
 [5] "upperwhisker"                              "lowerwhisker"                             
 [7] "Logged.GDP.per.capita"                     "Social.support"                           
 [9] "Healthy.life.expectancy"                   "Freedom.to.make.life.choices"             
[11] "Generosity"                                "Perceptions.of.corruption"                
[13] "Ladder.score.in.Dystopia"                  "Explained.by.Log.GDP.per.capita"          
[15] "Explained.by.Social.support"               "Explained.by.Healthy.life.expectancy"     
[17] "Explained.by.Freedom.to.make.life.choices" "Explained.by.Generosity"                  
[19] "Explained.by.Perceptions.of.corruption"    "Dystopia.residual"                        
# colnames(wHappiness_Df) <- gsub("Explained.by.", "", colnames(wHappiness_Df))
# names(wHappiness_Df)

Exploratory Data Analysis

wHappiness_Df %>% 
  count(Regional.indicator) %>% 
  ggplot(aes(x = reorder(Regional.indicator, n), y = n)) +
  geom_bar(stat = "identity") +
  coord_flip()

Regions by LifeExpectancy

# plotdata <- function(xx, y){
#   if(is.integer(y) == TRUE){
#     wHappiness_Df %>% 
#     group_by(xx) %>% 
#     summarise(mean_ = mean(y))
#   } else {
#     print("Enter Integer")
#   }
# }
# 
# plotdata(Regional.indicator, Healthy.life.expectancy)

plotdata <- wHappiness_Df %>%
  group_by(Regional.indicator) %>%
  summarise(n = n(),
            mean_ = mean(Healthy.life.expectancy),
            sd = sd(Healthy.life.expectancy),
            se = sd/sqrt(n),
            ci = qt(0.0975, df = n - 1) * sd/sqrt(n))
`summarise()` ungrouping output (override with `.groups` argument)
plotdata %>% 
  ggplot(aes(x = reorder(Regional.indicator, mean_), y = mean_, group = 1)) +
  geom_point() +
  geom_line() +
  geom_errorbar(aes(ymin = mean_ - se,
                    ymax = mean_ + se),
                width = .1) +
  coord_flip()

Cluster Analysis

cluster_x <- wHappiness_Df %>% 
  select(-c("Regional.indicator", "Country"))

##
cluster_x <- cluster_x[ , which(apply(cluster_x, 2, var) != 0)]
which(apply(cluster_x, 2, var)==0)
named integer(0)
## Checking for clusters
library(factoextra)
library(gridExtra)

set.seed(234)

## Initiate clusters with k = (3,4,5,6)
k0 <- kmeans(cluster_x, centers = 2, nstart = 25)
k1 <- kmeans(cluster_x, centers = 3, nstart = 25)
k2 <- kmeans(cluster_x, centers = 4, nstart = 25)
k3 <- kmeans(cluster_x, centers = 5, nstart = 25)
k4 <- kmeans(cluster_x, centers = 6, nstart = 25)

##Visualize cluster results
p0 <- fviz_cluster(k0, geom = "point", data = cluster_x) + ggtitle("K means k=3")
p1 <- fviz_cluster(k1, geom = "point", data = cluster_x) + ggtitle("K means k=3")
p2 <- fviz_cluster(k2, geom = "point", data = cluster_x) + ggtitle("K means k=4")
p3 <- fviz_cluster(k3, geom = "point", data = cluster_x) + ggtitle("K means k=5")
p4 <- fviz_cluster(k4, geom = "point", data = cluster_x) + ggtitle("K means k=6")


## Concanate grids
grid.arrange(p0, p1, p2, p3, p4)

## Determine n of cluster, plot Elbow method
fviz_nbclust(cluster_x, kmeans, method = "wss") +
  geom_vline(xintercept = 2, linetype = 2) 

k = 2 forms the perfect elbow

Evaluation

## Applying n = 4 clusters on dataset.
cluster_Df <- data.frame(wHappiness_Df, Cluster = k0$cluster) %>% 
  mutate(Cluster = as.factor(Cluster))

cluster_Df %>% 
  group_by(Cluster) %>% 
  ggplot(aes(x = Regional.indicator, y = Healthy.life.expectancy, colour = Cluster)) +
  geom_jitter()  +
  facet_wrap(~Cluster) +
  coord_flip()

NA

Ladder score of Happiness

cluster_Df %>% 
  group_by(Cluster) %>% 
  ggplot(aes(x = Regional.indicator, y = Ladder.score, colour = Cluster)) +
  geom_jitter()  +
  facet_wrap(~Cluster) +
  coord_flip()

Logged GDP/Capita

cluster_Df %>% 
  group_by(Cluster) %>% 
  ggplot(aes(x = Regional.indicator, y = Logged.GDP.per.capita, colour = Cluster)) +
  geom_jitter()  +
  facet_wrap(~Cluster) +
  coord_flip()

Perception of Corruption

cluster_Df %>% 
  group_by(Cluster) %>% 
  ggplot(aes(x = Regional.indicator, y = Perceptions.of.corruption, colour = Cluster)) +
  geom_jitter()  +
  facet_wrap(~Cluster) +
  coord_flip()

Perception of corruption in the Second Cluster is more generalized, unlike the first cluster who have a more defined and uniform perception of corruption, however provided by the survey’s scale.

At this junction our evaluation of our cluster analysis gives to define the clusters in pre-concieved real world ideas of (k = 1)Developed and (k =2) Developing Clusters/Countries, which are found, ironically, to rate higher on the scale of happiness. Indicatively more has to be done to attenuate the real reasons behind these metrics.

cluster_Df <- cluster_Df %>% 
  mutate(Cluster = if_else(Cluster == 1, "Developed_Region", "Developing_Region"))
LS0tDQp0aXRsZTogIihHZW50bGUpIENsdXN0ZXIgQW5hbHlzaXMgb2YgdGhlIFdvcmxkIGJ5IEhhcHBpbmVzcyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyIGVjaG8gPSBGLCBtZXNzYWdlID0gRn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShEVCkNCmBgYA0KDQpgYGB7cn0NCndIYXBwaW5lc3NfRGYgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL1BDL0RvY3VtZW50cy9SXzREUy9Xb3JsZEhhcHBpbmVzc1JlcG9ydC93b3JsZC1oYXBwaW5lc3MtcmVwb3J0LTIwMjEuY3N2IikNCmdsaW1wc2Uod0hhcHBpbmVzc19EZikNCmBgYA0KDQojIyBEYXRhIEluc3BlY3Rpb24gYW5kIENsZWFuaW5nDQoNCmBgYHtyfQ0KIyMgQ2hlY2sgZm9yIG1pc3NpbmcgdmFsdWVzDQpudWxsX3ZhcnMgPC0gKHNhcHBseSh3SGFwcGluZXNzX0RmLCBmdW5jdGlvbih4KSBzdW0oaXMubmEoeCkpKSkNCnQoZGF0YS5mcmFtZShudWxsX3ZhcnMpKQ0KDQojIyBDaGVja2luZyBmb3IgQmxhbmsgVmFsdWVzDQp3SGFwcGluZXNzX0RmW3dIYXBwaW5lc3NfRGYgPT0gIiIsXQ0KYGBgDQoNCk5vIG1pc3Npbmcgb3IgZW1wdHkgdmFsdWVzLCBnby10by1nby4NCg0KYGBge3J9DQpuYW1lcyh3SGFwcGluZXNzX0RmKQ0KYGBgDQoNCg0KYGBge3J9DQojIyBUaWR5aW5nIHRoZSBDb2x1bW4gTmFtZQ0KY29sQ2xlYW4gPC0gZnVuY3Rpb24oeCl7DQogIGNvbG5hbWVzKHgpIDwtIGdzdWIoIlxcLlxcLisiLCIuIiwgY29sbmFtZXMoeCkpOw0KICB4DQp9DQoNCndIYXBwaW5lc3NfRGYgPC0gY29sQ2xlYW4od0hhcHBpbmVzc19EZikgJT4lIA0KICByZW5hbWUoQ291bnRyeSA9IMOvLkNvdW50cnkubmFtZSkNCm5hbWVzKHdIYXBwaW5lc3NfRGYpDQpgYGANCg0KYGBge3J9DQojIGNvbG5hbWVzKHdIYXBwaW5lc3NfRGYpIDwtIGdzdWIoIkV4cGxhaW5lZC5ieS4iLCAiIiwgY29sbmFtZXMod0hhcHBpbmVzc19EZikpDQojIG5hbWVzKHdIYXBwaW5lc3NfRGYpDQpgYGANCg0KDQojIyBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzDQoNCmBgYHtyfQ0Kd0hhcHBpbmVzc19EZiAlPiUgDQogIGNvdW50KFJlZ2lvbmFsLmluZGljYXRvcikgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKFJlZ2lvbmFsLmluZGljYXRvciwgbiksIHkgPSBuKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBjb29yZF9mbGlwKCkNCmBgYA0KDQojIyMjIFJlZ2lvbnMgYnkgTGlmZUV4cGVjdGFuY3kNCmBgYHtyfQ0KIyBwbG90ZGF0YSA8LSBmdW5jdGlvbih4eCwgeSl7DQojICAgaWYoaXMuaW50ZWdlcih5KSA9PSBUUlVFKXsNCiMgICAgIHdIYXBwaW5lc3NfRGYgJT4lIA0KIyAgICAgZ3JvdXBfYnkoeHgpICU+JSANCiMgICAgIHN1bW1hcmlzZShtZWFuXyA9IG1lYW4oeSkpDQojICAgfSBlbHNlIHsNCiMgICAgIHByaW50KCJFbnRlciBJbnRlZ2VyIikNCiMgICB9DQojIH0NCiMgDQojIHBsb3RkYXRhKFJlZ2lvbmFsLmluZGljYXRvciwgSGVhbHRoeS5saWZlLmV4cGVjdGFuY3kpDQoNCnBsb3RkYXRhIDwtIHdIYXBwaW5lc3NfRGYgJT4lDQogIGdyb3VwX2J5KFJlZ2lvbmFsLmluZGljYXRvcikgJT4lDQogIHN1bW1hcmlzZShuID0gbigpLA0KICAgICAgICAgICAgbWVhbl8gPSBtZWFuKEhlYWx0aHkubGlmZS5leHBlY3RhbmN5KSwNCiAgICAgICAgICAgIHNkID0gc2QoSGVhbHRoeS5saWZlLmV4cGVjdGFuY3kpLA0KICAgICAgICAgICAgc2UgPSBzZC9zcXJ0KG4pLA0KICAgICAgICAgICAgY2kgPSBxdCgwLjA5NzUsIGRmID0gbiAtIDEpICogc2Qvc3FydChuKSkNCg0KcGxvdGRhdGEgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKFJlZ2lvbmFsLmluZGljYXRvciwgbWVhbl8pLCB5ID0gbWVhbl8sIGdyb3VwID0gMSkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbl8gLSBzZSwNCiAgICAgICAgICAgICAgICAgICAgeW1heCA9IG1lYW5fICsgc2UpLA0KICAgICAgICAgICAgICAgIHdpZHRoID0gLjEpICsNCiAgY29vcmRfZmxpcCgpDQpgYGANCg0KDQojIyBDbHVzdGVyIEFuYWx5c2lzDQoNCmBgYHtyfQ0KY2x1c3Rlcl94IDwtIHdIYXBwaW5lc3NfRGYgJT4lIA0KICBzZWxlY3QoLWMoIlJlZ2lvbmFsLmluZGljYXRvciIsICJDb3VudHJ5IikpDQoNCiMjDQpjbHVzdGVyX3ggPC0gY2x1c3Rlcl94WyAsIHdoaWNoKGFwcGx5KGNsdXN0ZXJfeCwgMiwgdmFyKSAhPSAwKV0NCndoaWNoKGFwcGx5KGNsdXN0ZXJfeCwgMiwgdmFyKT09MCkNCg0KIyMgQ2hlY2tpbmcgZm9yIGNsdXN0ZXJzDQpsaWJyYXJ5KGZhY3RvZXh0cmEpDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCg0Kc2V0LnNlZWQoMjM0KQ0KDQojIyBJbml0aWF0ZSBjbHVzdGVycyB3aXRoIGsgPSAoMyw0LDUsNikNCmswIDwtIGttZWFucyhjbHVzdGVyX3gsIGNlbnRlcnMgPSAyLCBuc3RhcnQgPSAyNSkNCmsxIDwtIGttZWFucyhjbHVzdGVyX3gsIGNlbnRlcnMgPSAzLCBuc3RhcnQgPSAyNSkNCmsyIDwtIGttZWFucyhjbHVzdGVyX3gsIGNlbnRlcnMgPSA0LCBuc3RhcnQgPSAyNSkNCmszIDwtIGttZWFucyhjbHVzdGVyX3gsIGNlbnRlcnMgPSA1LCBuc3RhcnQgPSAyNSkNCms0IDwtIGttZWFucyhjbHVzdGVyX3gsIGNlbnRlcnMgPSA2LCBuc3RhcnQgPSAyNSkNCg0KIyNWaXN1YWxpemUgY2x1c3RlciByZXN1bHRzDQpwMCA8LSBmdml6X2NsdXN0ZXIoazAsIGdlb20gPSAicG9pbnQiLCBkYXRhID0gY2x1c3Rlcl94KSArIGdndGl0bGUoIksgbWVhbnMgaz0zIikNCnAxIDwtIGZ2aXpfY2x1c3RlcihrMSwgZ2VvbSA9ICJwb2ludCIsIGRhdGEgPSBjbHVzdGVyX3gpICsgZ2d0aXRsZSgiSyBtZWFucyBrPTMiKQ0KcDIgPC0gZnZpel9jbHVzdGVyKGsyLCBnZW9tID0gInBvaW50IiwgZGF0YSA9IGNsdXN0ZXJfeCkgKyBnZ3RpdGxlKCJLIG1lYW5zIGs9NCIpDQpwMyA8LSBmdml6X2NsdXN0ZXIoazMsIGdlb20gPSAicG9pbnQiLCBkYXRhID0gY2x1c3Rlcl94KSArIGdndGl0bGUoIksgbWVhbnMgaz01IikNCnA0IDwtIGZ2aXpfY2x1c3RlcihrNCwgZ2VvbSA9ICJwb2ludCIsIGRhdGEgPSBjbHVzdGVyX3gpICsgZ2d0aXRsZSgiSyBtZWFucyBrPTYiKQ0KDQoNCiMjIENvbmNhbmF0ZSBncmlkcw0KZ3JpZC5hcnJhbmdlKHAwLCBwMSwgcDIsIHAzLCBwNCkNCmBgYA0KDQpgYGB7cn0NCiMjIERldGVybWluZSBuIG9mIGNsdXN0ZXIsIHBsb3QgRWxib3cgbWV0aG9kDQpmdml6X25iY2x1c3QoY2x1c3Rlcl94LCBrbWVhbnMsIG1ldGhvZCA9ICJ3c3MiKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDIsIGxpbmV0eXBlID0gMikgDQpgYGANCg0KayA9IDIgZm9ybXMgdGhlIHBlcmZlY3QgZWxib3cNCg0KDQojIyBFdmFsdWF0aW9uDQoNCmBgYHtyfQ0KIyMgQXBwbHlpbmcgbiA9IDQgY2x1c3RlcnMgb24gZGF0YXNldC4NCmNsdXN0ZXJfRGYgPC0gZGF0YS5mcmFtZSh3SGFwcGluZXNzX0RmLCBDbHVzdGVyID0gazAkY2x1c3RlcikgJT4lIA0KICBtdXRhdGUoQ2x1c3RlciA9IGFzLmZhY3RvcihDbHVzdGVyKSkNCg0KY2x1c3Rlcl9EZiAlPiUgDQogIGdyb3VwX2J5KENsdXN0ZXIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gUmVnaW9uYWwuaW5kaWNhdG9yLCB5ID0gSGVhbHRoeS5saWZlLmV4cGVjdGFuY3ksIGNvbG91ciA9IENsdXN0ZXIpKSArDQogIGdlb21faml0dGVyKCkgICsNCiAgZmFjZXRfd3JhcCh+Q2x1c3RlcikgKw0KICBjb29yZF9mbGlwKCkNCiAgDQpgYGANCg0KIyMjIyBMYWRkZXIgc2NvcmUgb2YgSGFwcGluZXNzDQoNCmBgYHtyfQ0KY2x1c3Rlcl9EZiAlPiUgDQogIGdyb3VwX2J5KENsdXN0ZXIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gUmVnaW9uYWwuaW5kaWNhdG9yLCB5ID0gTGFkZGVyLnNjb3JlLCBjb2xvdXIgPSBDbHVzdGVyKSkgKw0KICBnZW9tX2ppdHRlcigpICArDQogIGZhY2V0X3dyYXAofkNsdXN0ZXIpICsNCiAgY29vcmRfZmxpcCgpDQpgYGANCg0KDQoNCiMjIyMgTG9nZ2VkIEdEUC9DYXBpdGENCg0KYGBge3J9DQpjbHVzdGVyX0RmICU+JSANCiAgZ3JvdXBfYnkoQ2x1c3RlcikgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBSZWdpb25hbC5pbmRpY2F0b3IsIHkgPSBMb2dnZWQuR0RQLnBlci5jYXBpdGEsIGNvbG91ciA9IENsdXN0ZXIpKSArDQogIGdlb21faml0dGVyKCkgICsNCiAgZmFjZXRfd3JhcCh+Q2x1c3RlcikgKw0KICBjb29yZF9mbGlwKCkNCmBgYA0KDQojIyMjIFBlcmNlcHRpb24gb2YgQ29ycnVwdGlvbg0KYGBge3J9DQpjbHVzdGVyX0RmICU+JSANCiAgZ3JvdXBfYnkoQ2x1c3RlcikgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBSZWdpb25hbC5pbmRpY2F0b3IsIHkgPSBQZXJjZXB0aW9ucy5vZi5jb3JydXB0aW9uLCBjb2xvdXIgPSBDbHVzdGVyKSkgKw0KICBnZW9tX2ppdHRlcigpICArDQogIGZhY2V0X3dyYXAofkNsdXN0ZXIpICsNCiAgY29vcmRfZmxpcCgpDQpgYGANCg0KDQpQZXJjZXB0aW9uIG9mIGNvcnJ1cHRpb24gaW4gdGhlIFNlY29uZCBDbHVzdGVyIGlzIG1vcmUgZ2VuZXJhbGl6ZWQsIHVubGlrZSB0aGUgZmlyc3QgY2x1c3RlciB3aG8gaGF2ZSBhIG1vcmUgZGVmaW5lZCBhbmQgdW5pZm9ybSBwZXJjZXB0aW9uIG9mIGNvcnJ1cHRpb24sIGhvd2V2ZXIgcHJvdmlkZWQgYnkgdGhlIHN1cnZleSdzIHNjYWxlLg0KDQpBdCB0aGlzIGp1bmN0aW9uIG91ciBldmFsdWF0aW9uIG9mIG91ciBjbHVzdGVyIGFuYWx5c2lzIGdpdmVzIHRvIGRlZmluZSB0aGUgY2x1c3RlcnMgaW4gcHJlLWNvbmNpZXZlZCByZWFsIHdvcmxkIGlkZWFzIG9mIChrID0gMSlEZXZlbG9wZWQgYW5kIChrID0yKSBEZXZlbG9waW5nIENsdXN0ZXJzL0NvdW50cmllcywgd2hpY2ggYXJlIGZvdW5kLCBpcm9uaWNhbGx5LCB0byByYXRlIGhpZ2hlciBvbiB0aGUgc2NhbGUgb2YgaGFwcGluZXNzLiBJbmRpY2F0aXZlbHkgbW9yZSBoYXMgdG8gYmUgZG9uZSB0byBhdHRlbnVhdGUgdGhlIHJlYWwgcmVhc29ucyBiZWhpbmQgdGhlc2UgbWV0cmljcy4NCg0KYGBge3J9DQpjbHVzdGVyX0RmIDwtIGNsdXN0ZXJfRGYgJT4lIA0KICBtdXRhdGUoQ2x1c3RlciA9IGlmX2Vsc2UoQ2x1c3RlciA9PSAxLCAiRGV2ZWxvcGVkX1JlZ2lvbiIsICJEZXZlbG9waW5nX1JlZ2lvbiIpKQ0KYGBgDQoNCg==