Required packages

library("readr")
library("dplyr")
library("tidyr")
library("deductive")
library("deducorrect")
library("editrules")
library("validate")
library("Hmisc")
library("forecast")
library("stringr")
library("lubridate")
library("car")
library("outliers")
library("mvoutlier")
library("MVN")
library("infotheo")
library("MASS")
library("mlr")
library("mlr3")
library("ggplot2")
library("knitr")
library ("rmarkdown")

Executive Summary

The aim of this assignment is to demonstrate the concepts and techniques in Data Preprocessing or also known as Data Wrangling. Data Preprocessing in data mining can be summarised as a data mining technique that involves transforming raw (and complex) data into an understable format ready for statistical analysis.

Major Tasks in Data Preprocessing are as follow:

Three datasets are used in demonstrating the major tasks in data preprocessing in this assignment; i.e. the Human Freedom Index 2018 and World Happiness Report 2016 and 2017.

This exercise is aimed to prepare a dataset that will be used for analysing whether higher degree of freedom means higher level of happiness.

Data

Human Freedom Index

The Human Freedom Index (‘HFI’) present the degree of human freedom in the world based on 79 indicators of personal and economic freedom grouped into 12 categories as follow (pf = personal freedom, ef = economic freedom):

  1. Rule of Law (pf_rol):
    • pf_rol_procedural (Procedural justice)
    • pf_rol_civil (Civil justice)
    • pf_rol_criminal (Criminal Justice)
  2. Security and Safety (pf_ss):
    • pf_ss_homicide (Homicide)
    • pf_ss_disappearances_disap (Disappearances)
    • pf_ss_disappearances_violent (Violent conflicts)
    • pf_ss_disappearances_organized (Organized conflicts)
    • pf_ss_disappearances_fatalities (Terrorism fatalities)
    • pf_ss_disappearances_injuries (Terrorism injuries)
    • pf_ss_disappearances (Disappearances, conflict, and terrorism)
    • pf_ss_women_fgm (Female genital mutilation)
    • pf_ss_women_missing (Missing women)
    • pf_ss_women_inheritance_widows (Inheritance rights for widows)
    • pf_ss_women_inheritance_daughters (Inheritance rights for daughters)
    • pf_ss_women_inheritance (Inheritance)
    • pf_ss_women (Women’s security)
  3. Movement (pf_movement):
    • pf_movement_domestic (Freedom of domestic movement)
    • pf_movement_foreign (Freedom of foreign movement)
    • pf_movement_women (Women’s movement)
  4. Religion (pf_religion):
    • pf_religion_estop_establish (Freedom to establish religious organizations)
    • pf_religion_estop_operate (Freedom to operate religious organizations)
    • pf_religion_estop (Freedom to establish and operate religious organizations)
    • pf_religion_harassment (Harassment and physical hostilities)
    • pf_religion_restrictions (Legal and regulatory restrictions)
  5. Association, Assembly, and Civil Society (pf_association):
    • pf_association_association (Freedom of association)
    • pf_association_assembly (Freedom of assembly)
    • pf_association_political_establish (Freedom to establish political parties)
    • pf_association_political_operate (Freedom to operate political parties)
    • pf_association_political (Freedom to establish and operate political parties)
    • pf_association_prof_establish (Freedom to establish professional organizations)
    • pf_association_prof_operate (Freedom to operate professional organizations)
    • pf_association_prof (Freedom to establish and operate professional organizations)
    • pf_association_sport_establish (Freedom to establish educational, sporting, and cultural organizations)
    • pf_association_sport_operate (Freedom to operate educational, sporting, and cultural organizations)
    • pf_association_sport (Freedom to establish and operate educational, sporting, and cultural organizations)
  6. Expression and Information (pf_expression):
    • pf_expression_killed (Press killed)
    • pf_expression_jailed (Press jailed)
    • pf_expression_influence (Laws and regulations that influence media content)
    • pf_expression_control (Political pressures and controls on media content)
    • pf_expression_cable (Access to cable/satellite)
    • pf_expression_newspapers (Access to foreign newspapers)
    • pf_expression_internet (State control over Internet access)
  7. Identity and Relationships (pf_identity):
    • pf_identity_legal (Legal gender)
    • pf_identity_parental_marriage (Parental rights in marriage)
    • pf_identity_parental_divorce (Parental rights after divorce)
    • pf_identity_parental (Parental rights)
    • pf_identity_sex_male (Male-to-male relationships)
    • pf_identity_sex_female (Female-to-female relationships)
    • pf_identity_sex (Same-sex ralitionships)
    • pf_identity_divorce (Divorce)
  8. Size of Government (ef_government):
    • ef_government_consumption (Government consumption)
    • ef_government_transfers (Transfers and subsidies)
    • ef_government_enterprises (Government enterprises and investments)
    • ef_government_tax_income (Top marginal income tax rate)
    • ef_government_tax_payroll (Top marginal income and payroll tax rate)
    • ef_government_tax (Top marginal tax rate)
  9. Legal System and Property Rights (ef_legal):
    • ef_legal_judicial (Judicial independence)
    • ef_legal_courts (Impartial courts)
    • ef_legal_protection (Protection of property rights)
    • ef_legal_military (Military interference in rule of law and politics)
    • ef_legal_integrity (Integrity of the legal system)
    • ef_legal_enforcement (Legal enforcement of contracts)
    • ef_legal_restrictions (Regulatory restrictions on the sale of real property)
    • ef_legal_police (Reliability of police)
    • ef_legal_crime (Business costs of crime)
    • ef_legal_gender (Gender adjustment)
  10. Access to Sound Money (ef_money):
    • ef_money_growth (Money growth)
    • ef_money_sd (Standard deviation of inflation)
    • ef_money_inflation (Inflation: most recent year)
    • ef_money_currency (Freedom to own foreign currency bank account)
  11. Freedom to Trade Internationally (ef_trade)
    • ef_trade_tariffs_revenue (Revenue from trade taxes (% of trade sector))
    • ef_trade_tariffs_mean (Mean tariff rate)
    • ef_trade_tariffs_sd (Standard deviation of tariffs rates)
    • ef_trade_tariffs (Tariffs)
    • ef_trade_regulatory_nontariff (Nontariff trade barriers)
    • ef_trade_regulatory_compliance (Compliance costs of importing and exporting)
    • ef_trade_regulatory (Regulatory trade barriers)
    • ef_trade_black (Black-market exchange rates)
    • ef_trade_movement_foreign (Foreign ownership/investment restrictions)
    • ef_trade_movement_capital (Capital controls) ` + ef_trade_movement_visit (Freedom of foreigners to visit)
    • ef_trade_movement (Controls of the movement of capital and people)
  12. Regulation of Credit, Labor, and Business (ef_regulation_credit_ownership)

The HFI 2018 report is co-published by the Cato Institute, the Fraser Institute, and the Liberales Institut at the Friedrich Naumann Foundation for Freedom, which can be found at this link: https://www.cato.org/human-freedom-index-new

The HFI 2018 dataset covers the HFI from year 2008 up to 2016 and 162 countries. It can also be retireved from Kaggle: https://www.kaggle.com/chchloe29/gdp-per-capita

The World Happinness Report

The World Happiness Report is a landmark survey of the state of global happiness that ranks 155-157 countries by how happy their citizens perceive themselves to be. The report is produced by the United Nations Sustainable Development Solutions Network in partnership with the Ernesto Illy Foundation. The original World Happinness Report 2018 can be found at this link: https://worldhappiness.report/ed/2018/

However, for the purpose of the data prepocessing exercise, the dataset has been sourced from Kaggle:

+ https://www.kaggle.com/unsdsn/world-happiness#2016.csv
+ https://www.kaggle.com/unsdsn/world-happiness#2017.csv

The report ranks 156 countries by their happiness level from year 2026 and 2017. The happiness score are based on answers to the main life evaluation question asked in the Gallup World Poll (Gallup is US data analytic firm). In the survey, people were asked to rate their happiness on a scare from 0 to 10 with 0 being the worst possible life and 10 being the best possible life. The report then determined six key factors that contribute to happiness score:

+ economic production (*GDP per capita*)
+ social support (*Family*)
+ life expectancy (*Health*)
+ freedom to make life choices (*Freedom*)*
+ absence of corruption (*Trust - Goverment Corruption*), and 
+ generosity (*Generosity*).

Note: the Freedom variable in the World Happiness Report is different measure to Freedom in Human Freedom Index. The Freedom level is determined based on the survey result of the Gallup World Poll where applicants were asked this question: “Are you satisfied or dissatisfied with your freedom to choose what you do with your life?”

In order to make the happiness score for each country more meaningful, a hypothetical country where that has the lowest happiness level is established; it is called ‘Dystopia’ which is the opposite of Utopia. The purpose in establishing Dystopia is to have a benchmark against which all countries can be favorably compared (no country performs more poorly than Dystopia) in terms of each of the six key variables, thus allowing each sub-bar to be of positive width.

The residuals, or unexplained components, differ for each country, reflecting the extent to which the six variables either over- or under-explain average 2014-2016 life evaluations. These residuals have an average value of approximately zero over the whole set of countries.

The whiskers or upper lower levels of confidence indicate 95% confidence intervals for the estimated means.

setwd("~/Desktop/RMIT/MATH2349 – Data Preprocessing/Assignments/Assignment3/Data")
The working directory was changed to /Users/Meilda/Desktop/RMIT/MATH2349 – Data Preprocessing/Assignments/Assignment3/Data inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
library(readr)
hfi_raw <- read_csv("hfi_cc_2018.csv")
Parsed with column specification:
cols(
  .default = col_double(),
  ISO_code = col_character(),
  countries = col_character(),
  region = col_character()
)
See spec(...) for full column specifications.
head(hfi_raw)
happy16 <- read_csv("2016.csv")
Parsed with column specification:
cols(
  Country = col_character(),
  Region = col_character(),
  `Happiness Rank` = col_double(),
  `Happiness Score` = col_double(),
  `Lower Confidence Interval` = col_double(),
  `Upper Confidence Interval` = 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(happy16)
happy17 <- read_csv("2017.csv")
Parsed with column specification:
cols(
  Country = col_character(),
  Happiness.Rank = col_double(),
  Happiness.Score = col_double(),
  Whisker.high = col_double(),
  Whisker.low = col_double(),
  Economy..GDP.per.Capita. = col_double(),
  Family = col_double(),
  Health..Life.Expectancy. = col_double(),
  Freedom = col_double(),
  Generosity = col_double(),
  Trust..Government.Corruption. = col_double(),
  Dystopia.Residual = col_double()
)
head(happy17)

Understand

Differences between happy16 & happy17 dataframes are the results of inconsistency in naming variables and difference in the number of countries being surveyed. In order to avoid duplicates of the common columns in the two dataframes being joined, consistency in naming variables. Suitably, columns in happy16 are renamed in accordance to their corresponding variables in happy17 by using names() function.

#To keep data each year:
happy16$year <- 2016
happy17$year <- 2017
#Remove redundant variables in 'happy16' and 'happy17'
happy16a <- happy16[-c(2,5:6)]
head(happy16a)
happy17a <- happy17[-c(4:5)]
head(happy17a)
#Check each dataframe structure before joining happy16 & happy17 dataframes to see if there is any difference in regards to the data dimension and variables.
str(happy16a)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   157 obs. of  11 variables:
 $ Country                      : chr  "Denmark" "Switzerland" "Iceland" "Norway" ...
 $ Happiness Rank               : num  1 2 3 4 5 6 7 8 9 10 ...
 $ Happiness Score              : num  7.53 7.51 7.5 7.5 7.41 ...
 $ Economy (GDP per Capita)     : num  1.44 1.53 1.43 1.58 1.41 ...
 $ Family                       : num  1.16 1.15 1.18 1.13 1.13 ...
 $ Health (Life Expectancy)     : num  0.795 0.863 0.867 0.796 0.811 ...
 $ Freedom                      : num  0.579 0.586 0.566 0.596 0.571 ...
 $ Trust (Government Corruption): num  0.445 0.412 0.15 0.358 0.41 ...
 $ Generosity                   : num  0.362 0.281 0.477 0.379 0.255 ...
 $ Dystopia Residual            : num  2.74 2.69 2.83 2.66 2.83 ...
 $ year                         : num  2016 2016 2016 2016 2016 ...
str(happy17a)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   155 obs. of  11 variables:
 $ Country                      : chr  "Norway" "Denmark" "Iceland" "Switzerland" ...
 $ Happiness.Rank               : num  1 2 3 4 5 6 7 8 9 10 ...
 $ Happiness.Score              : num  7.54 7.52 7.5 7.49 7.47 ...
 $ Economy..GDP.per.Capita.     : num  1.62 1.48 1.48 1.56 1.44 ...
 $ Family                       : num  1.53 1.55 1.61 1.52 1.54 ...
 $ Health..Life.Expectancy.     : num  0.797 0.793 0.834 0.858 0.809 ...
 $ Freedom                      : num  0.635 0.626 0.627 0.62 0.618 ...
 $ Generosity                   : num  0.362 0.355 0.476 0.291 0.245 ...
 $ Trust..Government.Corruption.: num  0.316 0.401 0.154 0.367 0.383 ...
 $ Dystopia.Residual            : num  2.28 2.31 2.32 2.28 2.43 ...
 $ year                         : num  2017 2017 2017 2017 2017 ...
#Check mismatches between happy16a and happy17a
anti_join(happy16a,happy17a)
Joining, by = c("Country", "Family", "Freedom", "Generosity", "year")
#Rename columns in happy16a dataframe to be consistent with happy17a columns:
names(happy16a)[2] <- "Happiness.Rank"
names(happy16a)[3] <- "Happiness.Score"
names(happy16a)[4] <- "Economy..GDP.per.Capita."
names(happy16a)[6] <- "Health..Life.Expectancy."
names(happy16a)[8] <- "Trust..Government.Corruption."
names(happy16a)[10] <- "Dystopia.Residual"
head(happy16a)
#Merge 'happy16a' with 'happy17a'
joined_happy <- bind_rows(happy16a,happy17a)
names(joined_happy) <- c("Country","Happiness_Rank",
                         "Happiness_Score","GDP_per_Capita", 
                         "Family","Health","Freedom","Trust_Govt_Corruption", 
                         "Generosity","Dystopia_Residual","year")
head(joined_happy)
str(joined_happy)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   312 obs. of  11 variables:
 $ Country              : chr  "Denmark" "Switzerland" "Iceland" "Norway" ...
 $ Happiness_Rank       : num  1 2 3 4 5 6 7 8 9 10 ...
 $ Happiness_Score      : num  7.53 7.51 7.5 7.5 7.41 ...
 $ GDP_per_Capita       : num  1.44 1.53 1.43 1.58 1.41 ...
 $ Family               : num  1.16 1.15 1.18 1.13 1.13 ...
 $ Health               : num  0.795 0.863 0.867 0.796 0.811 ...
 $ Freedom              : num  0.579 0.586 0.566 0.596 0.571 ...
 $ Trust_Govt_Corruption: num  0.445 0.412 0.15 0.358 0.41 ...
 $ Generosity           : num  0.362 0.281 0.477 0.379 0.255 ...
 $ Dystopia_Residual    : num  2.74 2.69 2.83 2.66 2.83 ...
 $ year                 : num  2016 2016 2016 2016 2016 ...
#Check structure of human freedom index 'hfi_raw
str(hfi_raw)
Classes ‘spec_tbl_df’, ‘tbl_df’, ‘tbl’ and 'data.frame':    1458 obs. of  123 variables:
 $ year                              : num  2016 2016 2016 2016 2016 ...
 $ ISO_code                          : chr  "ALB" "DZA" "AGO" "ARG" ...
 $ countries                         : chr  "Albania" "Algeria" "Angola" "Argentina" ...
 $ region                            : chr  "Eastern Europe" "Middle East & North Africa" "Sub-Saharan Africa" "Latin America & the Caribbean" ...
 $ pf_rol_procedural                 : num  6.66 NA NA 7.1 NA ...
 $ pf_rol_civil                      : num  4.55 NA NA 5.79 NA ...
 $ pf_rol_criminal                   : num  4.67 NA NA 4.34 NA ...
 $ pf_rol                            : num  5.29 3.82 3.45 5.74 5 ...
 $ pf_ss_homicide                    : num  8.92 9.46 8.06 7.62 8.81 ...
 $ pf_ss_disappearances_disap        : num  10 10 5 10 10 10 10 10 10 10 ...
 $ pf_ss_disappearances_violent      : num  10 9.29 10 10 10 ...
 $ pf_ss_disappearances_organized    : num  10 5 7.5 7.5 7.5 10 10 7.5 NA 2.5 ...
 $ pf_ss_disappearances_fatalities   : num  10 9.93 10 10 9.32 ...
 $ pf_ss_disappearances_injuries     : num  10 9.99 10 9.99 9.93 ...
 $ pf_ss_disappearances              : num  10 8.84 8.5 9.5 9.35 ...
 $ pf_ss_women_fgm                   : num  10 10 10 10 10 10 10 10 NA 10 ...
 $ pf_ss_women_missing               : num  7.5 7.5 10 10 5 10 10 7.5 NA 7.5 ...
 $ pf_ss_women_inheritance_widows    : num  5 0 5 10 10 10 10 5 NA 0 ...
 $ pf_ss_women_inheritance_daughters : num  5 0 5 10 10 10 10 10 NA 0 ...
 $ pf_ss_women_inheritance           : num  5 0 5 10 10 10 10 7.5 NA 0 ...
 $ pf_ss_women                       : num  7.5 5.83 8.33 10 8.33 ...
 $ pf_ss                             : num  8.81 8.04 8.3 9.04 8.83 ...
 $ pf_movement_domestic              : num  5 5 0 10 5 10 10 5 10 10 ...
 $ pf_movement_foreign               : num  10 5 5 10 5 10 10 5 10 5 ...
 $ pf_movement_women                 : num  5 5 10 10 10 10 10 5 NA 5 ...
 $ pf_movement                       : num  6.67 5 5 10 6.67 ...
 $ pf_religion_estop_establish       : num  NA NA NA NA NA NA NA NA NA NA ...
 $ pf_religion_estop_operate         : num  NA NA NA NA NA NA NA NA NA NA ...
 $ pf_religion_estop                 : num  10 5 10 7.5 5 10 10 2.5 NA 10 ...
 $ pf_religion_harassment            : num  9.57 6.87 8.9 9.04 8.58 ...
 $ pf_religion_restrictions          : num  8.01 2.96 7.46 6.85 5.09 ...
 $ pf_religion                       : num  9.19 4.94 8.79 7.8 6.22 ...
 $ pf_association_association        : num  10 5 2.5 7.5 7.5 10 10 2.5 NA 5 ...
 $ pf_association_assembly           : num  10 5 2.5 10 7.5 10 10 5 NA 0 ...
 $ pf_association_political_establish: num  NA NA NA NA NA NA NA NA NA NA ...
 $ pf_association_political_operate  : num  NA NA NA NA NA NA NA NA NA NA ...
 $ pf_association_political          : num  10 5 2.5 5 5 10 10 2.5 NA 0 ...
 $ pf_association_prof_establish     : num  NA NA NA NA NA NA NA NA NA NA ...
 $ pf_association_prof_operate       : num  NA NA NA NA NA NA NA NA NA NA ...
 $ pf_association_prof               : num  10 5 5 7.5 5 10 10 2.5 NA 10 ...
 $ pf_association_sport_establish    : num  NA NA NA NA NA NA NA NA NA NA ...
 $ pf_association_sport_operate      : num  NA NA NA NA NA NA NA NA NA NA ...
 $ pf_association_sport              : num  10 5 7.5 7.5 7.5 10 10 2.5 NA 10 ...
 $ pf_association                    : num  10 5 4 7.5 6.5 10 10 3 NA 5 ...
 $ pf_expression_killed              : num  10 10 10 10 10 10 10 10 10 10 ...
 $ pf_expression_jailed              : num  10 10 10 10 10 ...
 $ pf_expression_influence           : num  5 2.67 2.67 5.67 3.33 ...
 $ pf_expression_control             : num  5.25 4 2.5 5.5 4.25 7.75 8 0.25 7.25 0.75 ...
 $ pf_expression_cable               : num  10 10 7.5 10 7.5 10 10 10 NA 7.5 ...
 $ pf_expression_newspapers          : num  10 7.5 5 10 7.5 10 10 0 NA 7.5 ...
 $ pf_expression_internet            : num  10 7.5 7.5 10 7.5 10 10 7.5 NA 2.5 ...
 $ pf_expression                     : num  8.61 7.38 6.45 8.74 7.15 ...
 $ pf_identity_legal                 : num  0 NA 10 10 7 7 10 0 NA NA ...
 $ pf_identity_parental_marriage     : num  10 0 10 10 10 10 10 10 10 0 ...
 $ pf_identity_parental_divorce      : num  10 5 10 10 10 10 10 10 10 0 ...
 $ pf_identity_parental              : num  10 2.5 10 10 10 10 10 10 10 0 ...
 $ pf_identity_sex_male              : num  10 0 0 10 10 10 10 10 10 10 ...
 $ pf_identity_sex_female            : num  10 0 0 10 10 10 10 10 10 10 ...
 $ pf_identity_sex                   : num  10 0 0 10 10 10 10 10 10 10 ...
 $ pf_identity_divorce               : num  5 0 10 10 5 10 10 5 NA 0 ...
 $ pf_identity                       : num  6.25 0.833 7.5 10 8 ...
 $ pf_score                          : num  7.6 5.28 6.11 8.1 6.91 ...
 $ pf_rank                           : num  57 147 117 42 84 11 8 131 64 114 ...
 $ ef_government_consumption         : num  8.23 2.15 7.6 5.34 7.26 ...
 $ ef_government_transfers           : num  7.51 7.82 8.89 6.05 7.75 ...
 $ ef_government_enterprises         : num  8 0 0 6 8 10 10 0 7 10 ...
 $ ef_government_tax_income          : num  9 7 10 7 5 5 4 9 10 10 ...
 $ ef_government_tax_payroll         : num  7 2 9 1 5 5 3 4 10 10 ...
 $ ef_government_tax                 : num  8 4.5 9.5 4 5 5 3.5 6.5 10 10 ...
 $ ef_government                     : num  7.94 3.62 6.5 5.35 7 ...
 $ ef_legal_judicial                 : num  2.67 4.19 1.84 3.69 3.87 ...
 $ ef_legal_courts                   : num  3.15 4.33 1.97 2.93 4.2 ...
 $ ef_legal_protection               : num  4.51 4.69 2.51 4.26 5.66 ...
 $ ef_legal_military                 : num  8.33 4.17 3.33 7.5 5.83 ...
 $ ef_legal_integrity                : num  4.17 5 4.17 3.33 5 ...
 $ ef_legal_enforcement              : num  4.39 4.51 2.3 3.63 5.2 ...
 $ ef_legal_restrictions             : num  6.49 6.63 5.46 6.86 9.8 ...
 $ ef_legal_police                   : num  6.93 6.14 3.02 3.39 5.71 ...
 $ ef_legal_crime                    : num  6.22 6.74 4.29 4.13 7.01 ...
 $ ef_legal_gender                   : num  0.949 0.821 0.846 0.769 1 ...
 $ ef_legal                          : num  5.07 4.69 2.96 3.9 5.81 ...
 $ ef_money_growth                   : num  8.99 6.96 9.39 5.23 9.08 ...
 $ ef_money_sd                       : num  9.48 8.34 4.99 5.22 9.26 ...
 $ ef_money_inflation                : num  9.74 8.72 3.05 2 9.75 ...
 $ ef_money_currency                 : num  10 5 5 10 10 10 10 5 0 10 ...
 $ ef_money                          : num  9.55 7.25 5.61 5.61 9.52 ...
 $ ef_trade_tariffs_revenue          : num  9.63 8.48 8.99 6.06 8.87 ...
 $ ef_trade_tariffs_mean             : num  9.24 6.22 7.72 7.26 8.76 9.5 8.96 8.2 3.36 9.06 ...
 $ ef_trade_tariffs_sd               : num  8.02 5.92 4.25 5.94 8.02 ...
 $ ef_trade_tariffs                  : num  8.96 6.87 6.99 6.42 8.55 ...
 $ ef_trade_regulatory_nontariff     : num  5.57 4.96 3.13 4.47 5.92 ...
 $ ef_trade_regulatory_compliance    : num  9.405 0 0.917 5.156 8.466 ...
 $ ef_trade_regulatory               : num  7.49 2.48 2.02 4.81 7.19 ...
 $ ef_trade_black                    : num  10 5.56 10 0 10 ...
 $ ef_trade_movement_foreign         : num  6.31 3.66 2.95 5.36 5.11 ...
 $ ef_trade_movement_capital         : num  4.615 0 3.077 0.769 5.385 ...
 $ ef_trade_movement_visit           : num  8.297 1.106 0.111 7.965 10 ...
 $ ef_trade_movement                 : num  6.41 1.59 2.04 4.7 6.83 ...
 $ ef_trade                          : num  8.21 4.13 5.26 3.98 8.14 ...
  [list output truncated]
 - attr(*, "spec")=
  .. cols(
  ..   year = col_double(),
  ..   ISO_code = col_character(),
  ..   countries = col_character(),
  ..   region = col_character(),
  ..   pf_rol_procedural = col_double(),
  ..   pf_rol_civil = col_double(),
  ..   pf_rol_criminal = col_double(),
  ..   pf_rol = col_double(),
  ..   pf_ss_homicide = col_double(),
  ..   pf_ss_disappearances_disap = col_double(),
  ..   pf_ss_disappearances_violent = col_double(),
  ..   pf_ss_disappearances_organized = col_double(),
  ..   pf_ss_disappearances_fatalities = col_double(),
  ..   pf_ss_disappearances_injuries = col_double(),
  ..   pf_ss_disappearances = col_double(),
  ..   pf_ss_women_fgm = col_double(),
  ..   pf_ss_women_missing = col_double(),
  ..   pf_ss_women_inheritance_widows = col_double(),
  ..   pf_ss_women_inheritance_daughters = col_double(),
  ..   pf_ss_women_inheritance = col_double(),
  ..   pf_ss_women = col_double(),
  ..   pf_ss = col_double(),
  ..   pf_movement_domestic = col_double(),
  ..   pf_movement_foreign = col_double(),
  ..   pf_movement_women = col_double(),
  ..   pf_movement = col_double(),
  ..   pf_religion_estop_establish = col_double(),
  ..   pf_religion_estop_operate = col_double(),
  ..   pf_religion_estop = col_double(),
  ..   pf_religion_harassment = col_double(),
  ..   pf_religion_restrictions = col_double(),
  ..   pf_religion = col_double(),
  ..   pf_association_association = col_double(),
  ..   pf_association_assembly = col_double(),
  ..   pf_association_political_establish = col_double(),
  ..   pf_association_political_operate = col_double(),
  ..   pf_association_political = col_double(),
  ..   pf_association_prof_establish = col_double(),
  ..   pf_association_prof_operate = col_double(),
  ..   pf_association_prof = col_double(),
  ..   pf_association_sport_establish = col_double(),
  ..   pf_association_sport_operate = col_double(),
  ..   pf_association_sport = col_double(),
  ..   pf_association = col_double(),
  ..   pf_expression_killed = col_double(),
  ..   pf_expression_jailed = col_double(),
  ..   pf_expression_influence = col_double(),
  ..   pf_expression_control = col_double(),
  ..   pf_expression_cable = col_double(),
  ..   pf_expression_newspapers = col_double(),
  ..   pf_expression_internet = col_double(),
  ..   pf_expression = col_double(),
  ..   pf_identity_legal = col_double(),
  ..   pf_identity_parental_marriage = col_double(),
  ..   pf_identity_parental_divorce = col_double(),
  ..   pf_identity_parental = col_double(),
  ..   pf_identity_sex_male = col_double(),
  ..   pf_identity_sex_female = col_double(),
  ..   pf_identity_sex = col_double(),
  ..   pf_identity_divorce = col_double(),
  ..   pf_identity = col_double(),
  ..   pf_score = col_double(),
  ..   pf_rank = col_double(),
  ..   ef_government_consumption = col_double(),
  ..   ef_government_transfers = col_double(),
  ..   ef_government_enterprises = col_double(),
  ..   ef_government_tax_income = col_double(),
  ..   ef_government_tax_payroll = col_double(),
  ..   ef_government_tax = col_double(),
  ..   ef_government = col_double(),
  ..   ef_legal_judicial = col_double(),
  ..   ef_legal_courts = col_double(),
  ..   ef_legal_protection = col_double(),
  ..   ef_legal_military = col_double(),
  ..   ef_legal_integrity = col_double(),
  ..   ef_legal_enforcement = col_double(),
  ..   ef_legal_restrictions = col_double(),
  ..   ef_legal_police = col_double(),
  ..   ef_legal_crime = col_double(),
  ..   ef_legal_gender = col_double(),
  ..   ef_legal = col_double(),
  ..   ef_money_growth = col_double(),
  ..   ef_money_sd = col_double(),
  ..   ef_money_inflation = col_double(),
  ..   ef_money_currency = col_double(),
  ..   ef_money = col_double(),
  ..   ef_trade_tariffs_revenue = col_double(),
  ..   ef_trade_tariffs_mean = col_double(),
  ..   ef_trade_tariffs_sd = col_double(),
  ..   ef_trade_tariffs = col_double(),
  ..   ef_trade_regulatory_nontariff = col_double(),
  ..   ef_trade_regulatory_compliance = col_double(),
  ..   ef_trade_regulatory = col_double(),
  ..   ef_trade_black = col_double(),
  ..   ef_trade_movement_foreign = col_double(),
  ..   ef_trade_movement_capital = col_double(),
  ..   ef_trade_movement_visit = col_double(),
  ..   ef_trade_movement = col_double(),
  ..   ef_trade = col_double(),
  ..   ef_regulation_credit_ownership = col_double(),
  ..   ef_regulation_credit_private = col_double(),
  ..   ef_regulation_credit_interest = col_double(),
  ..   ef_regulation_credit = col_double(),
  ..   ef_regulation_labor_minwage = col_double(),
  ..   ef_regulation_labor_firing = col_double(),
  ..   ef_regulation_labor_bargain = col_double(),
  ..   ef_regulation_labor_hours = col_double(),
  ..   ef_regulation_labor_dismissal = col_double(),
  ..   ef_regulation_labor_conscription = col_double(),
  ..   ef_regulation_labor = col_double(),
  ..   ef_regulation_business_adm = col_double(),
  ..   ef_regulation_business_bureaucracy = col_double(),
  ..   ef_regulation_business_start = col_double(),
  ..   ef_regulation_business_bribes = col_double(),
  ..   ef_regulation_business_licensing = col_double(),
  ..   ef_regulation_business_compliance = col_double(),
  ..   ef_regulation_business = col_double(),
  ..   ef_regulation = col_double(),
  ..   ef_score = col_double(),
  ..   ef_rank = col_double(),
  ..   hf_score = col_double(),
  ..   hf_rank = col_double(),
  ..   hf_quartile = col_double()
  .. )
#Simplify hfi_raw by subsetting
hfi <- subset(hfi_raw, select = c((1:4), hf_score, hf_rank, pf_rol, pf_ss, pf_movement, pf_religion, pf_association, pf_expression, pf_identity, pf_score, pf_rank, ef_government, ef_legal, ef_money, ef_trade, ef_regulation, ef_score, ef_rank))
#Rename variable 'countries' to match 'Country' in joined_happy
names(hfi)[3] <- "Country"
head(hfi)
dim(hfi)
[1] 1458   22
#Join human freedom index 'hfi' & world happiness index 'joined_happy'
hfi_happy <- hfi %>% left_join(joined_happy)
Joining, by = c("year", "Country")
#Transform column 2-4 into factor
hfi_happy[,2:4] <- lapply(hfi_happy[,2:4], as.factor)
str(hfi_happy)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   1458 obs. of  31 variables:
 $ year                 : num  2016 2016 2016 2016 2016 ...
 $ ISO_code             : Factor w/ 162 levels "AGO","ALB","ARE",..: 2 43 1 4 5 6 7 8 16 15 ...
 $ Country              : Factor w/ 162 levels "Albania","Algeria",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ region               : Factor w/ 10 levels "Caucasus & Central Asia",..: 3 5 9 4 1 7 10 1 4 5 ...
 $ hf_score             : num  7.57 5.14 5.64 6.47 7.24 ...
 $ hf_rank              : num  48 155 142 107 57 4 16 130 50 75 ...
 $ pf_rol               : num  5.29 3.82 3.45 5.74 5 ...
 $ pf_ss                : num  8.81 8.04 8.3 9.04 8.83 ...
 $ pf_movement          : num  6.67 5 5 10 6.67 ...
 $ pf_religion          : num  9.19 4.94 8.79 7.8 6.22 ...
 $ pf_association       : num  10 5 4 7.5 6.5 10 10 3 NA 5 ...
 $ pf_expression        : num  8.61 7.38 6.45 8.74 7.15 ...
 $ pf_identity          : num  6.25 0.833 7.5 10 8 ...
 $ pf_score             : num  7.6 5.28 6.11 8.1 6.91 ...
 $ pf_rank              : num  57 147 117 42 84 11 8 131 64 114 ...
 $ ef_government        : num  7.94 3.62 6.5 5.35 7 ...
 $ ef_legal             : num  5.07 4.69 2.96 3.9 5.81 ...
 $ ef_money             : num  9.55 7.25 5.61 5.61 9.52 ...
 $ ef_trade             : num  8.21 4.13 5.26 3.98 8.14 ...
 $ ef_regulation        : num  6.91 5.27 5.52 5.37 7.38 ...
 $ ef_score             : num  7.54 4.99 5.17 4.84 7.57 7.98 7.58 6.49 7.34 7.56 ...
 $ ef_rank              : num  34 159 155 160 29 10 27 106 49 30 ...
 $ Happiness_Rank       : num  109 38 141 26 121 9 12 81 NA 42 ...
 $ Happiness_Score      : num  4.66 6.36 3.87 6.65 4.36 ...
 $ GDP_per_Capita       : num  0.955 1.053 0.847 1.151 0.861 ...
 $ Family               : num  0.502 0.833 0.664 1.066 0.625 ...
 $ Health               : num  0.7301 0.618 0.0499 0.6971 0.6408 ...
 $ Freedom              : num  0.31866 0.21006 0.00589 0.42284 0.14037 ...
 $ Trust_Govt_Corruption: num  0.053 0.1616 0.0843 0.073 0.0362 ...
 $ Generosity           : num  0.1684 0.0704 0.1207 0.1099 0.0779 ...
 $ Dystopia_Residual    : num  1.93 3.41 2.09 3.13 1.98 ...

Tidy & Manipulate Data I

The combined dataset is tidy in a way that it meets the three requirements which make a dataset tidy: + Each variable must have its own column. + Each observation must have its own row. + Each value must have its own cell.

head(hfi_happy)

Tidy & Manipulate Data II

df<-merge(happy16a[,c(1,3)],
           happy17a[,c(1,3)],
           by.x = "Country",
           by.y = "Country")
colnames(df)<-c("Country","Happiness_Rank16","Happiness_Rank17")
df1<-df%>%
  mutate(HappinessRank_Change = Happiness_Rank17 - Happiness_Rank16) 
df1

Scan I

#scan for missing values
sum(is.na(hfi_happy))
[1] 13591
#Select data from year 2016 & 2017
hfi_happy_nomiss <- hfi_happy %>% filter(year==2016 | year == 2017)
sum(is.na(hfi_happy_nomiss))
[1] 252
#Delete countries that are not covered in World Happiness Index
hfi_happy_nomiss1 <- hfi_happy_nomiss %>% filter(!is.na(Happiness_Score),
                      !is.na(Happiness_Score),
                      !is.na(GDP_per_Capita),
                      !is.na(Family),
                      !is.na(Health),
                      !is.na(Freedom),
                      !is.na(Trust_Govt_Corruption),
                      !is.na(Generosity),
                      !is.na(Dystopia_Residual)
                      )
sum(is.na(hfi_happy_nomiss1))
[1] 11
summary(hfi_happy_nomiss1)
      year         ISO_code        Country                              region      hf_score    
 Min.   :2016   AGO    :  1   Albania  :  1   Sub-Saharan Africa           :31   Min.   :3.766  
 1st Qu.:2016   ALB    :  1   Algeria  :  1   Latin America & the Caribbean:22   1st Qu.:6.275  
 Median :2016   ARE    :  1   Angola   :  1   Eastern Europe               :20   Median :6.848  
 Mean   :2016   ARG    :  1   Argentina:  1   Western Europe               :18   Mean   :6.945  
 3rd Qu.:2016   ARM    :  1   Armenia  :  1   Middle East & North Africa   :17   3rd Qu.:7.858  
 Max.   :2016   AUS    :  1   Australia:  1   South Asia                   :15   Max.   :8.887  
                (Other):131   (Other)  :131   (Other)                      :14                  
    hf_rank           pf_rol          pf_ss        pf_movement      pf_religion   
 Min.   :  1.00   Min.   :1.980   Min.   :3.964   Min.   : 0.000   Min.   :3.215  
 1st Qu.: 37.00   1st Qu.:3.988   1st Qu.:7.383   1st Qu.: 6.667   1st Qu.:6.346  
 Median : 75.00   Median :4.861   Median :8.413   Median : 8.333   Median :7.893  
 Mean   : 78.51   Mean   :5.183   Mean   :8.220   Mean   : 7.701   Mean   :7.389  
 3rd Qu.:119.00   3rd Qu.:6.451   3rd Qu.:9.370   3rd Qu.:10.000   3rd Qu.:8.540  
 Max.   :162.00   Max.   :8.687   Max.   :9.960   Max.   :10.000   Max.   :9.731  
                                                                                  
 pf_association   pf_expression    pf_identity        pf_score        pf_rank     
 Min.   : 0.500   Min.   :1.759   Min.   : 0.000   Min.   :2.512   Min.   :  1.0  
 1st Qu.: 5.000   1st Qu.:6.964   1st Qu.: 4.375   1st Qu.:6.041   1st Qu.: 38.0  
 Median : 7.500   Median :8.018   Median : 8.000   Median :6.975   Median : 80.0  
 Mean   : 7.127   Mean   :7.745   Mean   : 6.969   Mean   :7.044   Mean   : 79.9  
 3rd Qu.: 9.500   3rd Qu.:9.000   3rd Qu.: 9.250   3rd Qu.:8.259   3rd Qu.:121.0  
 Max.   :10.000   Max.   :9.798   Max.   :10.000   Max.   :9.399   Max.   :161.0  
 NA's   :11                                                                       
 ef_government      ef_legal        ef_money        ef_trade     ef_regulation      ef_score    
 Min.   :3.617   Min.   :2.003   Min.   :1.942   Min.   :2.877   Min.   :2.484   Min.   :2.880  
 1st Qu.:5.664   1st Qu.:4.127   1st Qu.:7.217   1st Qu.:6.356   1st Qu.:6.475   1st Qu.:6.290  
 Median :6.576   Median :5.125   Median :8.680   Median :7.217   Median :7.098   Median :6.950  
 Mean   :6.534   Mean   :5.300   Mean   :8.304   Mean   :7.056   Mean   :7.038   Mean   :6.846  
 3rd Qu.:7.462   3rd Qu.:6.218   3rd Qu.:9.433   3rd Qu.:8.050   3rd Qu.:7.733   3rd Qu.:7.500  
 Max.   :9.528   Max.   :8.798   Max.   :9.922   Max.   :9.324   Max.   :9.440   Max.   :8.970  
                                                                                                
    ef_rank       Happiness_Rank   Happiness_Score GDP_per_Capita        Family      
 Min.   :  1.00   Min.   :  1.00   Min.   :2.905   Min.   :0.06831   Min.   :0.0000  
 1st Qu.: 37.00   1st Qu.: 37.00   1st Qu.:4.459   1st Qu.:0.69429   1st Qu.:0.6450  
 Median : 76.00   Median : 78.00   Median :5.389   Median :1.05266   Median :0.8597  
 Mean   : 78.23   Mean   : 77.19   Mean   :5.429   Mean   :0.98463   Mean   :0.8031  
 3rd Qu.:121.00   3rd Qu.:116.00   3rd Qu.:6.361   3rd Qu.:1.27964   3rd Qu.:1.0217  
 Max.   :162.00   Max.   :157.00   Max.   :7.526   Max.   :1.82427   Max.   :1.1833  
                                                                                     
     Health          Freedom       Trust_Govt_Corruption   Generosity     Dystopia_Residual
 Min.   :0.0000   Min.   :0.0000   Min.   :0.00000       Min.   :0.0000   Min.   :0.8179   
 1st Qu.:0.4249   1st Qu.:0.2767   1st Qu.:0.06126       1st Qu.:0.1546   1st Qu.:1.9982   
 Median :0.6201   Median :0.4027   Median :0.10398       Median :0.2225   Median :2.2809   
 Mean   :0.5729   Mean   :0.3764   Mean   :0.13739       Mean   :0.2438   Mean   :2.3105   
 3rd Qu.:0.7301   3rd Qu.:0.4877   3rd Qu.:0.17554       3rd Qu.:0.3147   3rd Qu.:2.6646   
 Max.   :0.9528   Max.   :0.5961   Max.   :0.50521       Max.   :0.8197   Max.   :3.5591   
                                                                                           
 
hfi_happy_imp <- hfi_happy_nomiss1 %>% mutate_at(vars(pf_association),~ifelse(is.na(.x), mean(.x, na.rm = TRUE), .x))
sum(is.na(hfi_happy_imp))
[1] 0

Scan II

The presence of the two outliers can dramatically affected mean and variance estimates of our data, thus can lead to inaccurate result or prediction. The outliers may occur as a result of recording error, limitations on measuring techniques, skewed population, samples are taken from not entirely the same population, among others. However, we can not be sure what caused the outliers in our dataset as we extracted the data from a publicly available data source.

We use the Mahalanobis distance computing in the MVN package to detect any outliers in our data. The Mahalanobis distance detects an outlier by measuring how far each observation is to the center of joint chi-square distribution.

The result of the multivariate normality (‘mvn’) test are as follow:

#Choose only numerical variables (excl. 'year')
happy_nums <- dplyr::select_if((hfi_happy_imp[ , -1]), is.numeric) 
dim(happy_nums)
[1] 137  27
head(happy_nums)
#check for outliers and multivariate normality
result <- mvn(happy_nums, multivariateOutlierMethod = "quan", showOutliers = TRUE)
The covariance matrix of the data is singular.
There are 137 observations (in the entire dataset of 137 obs.) lying on the hyperplane
with equation a_1*(x_i1 - m_1) + ... + a_p*(x_ip - m_p) = 0 with (m_1, ..., m_p) the
mean of these observations and coefficients a_i from the vector a <- c(0.8164966, 0,
0, 0, 0, 0, 0, 0, 0, -0.4082483, 0, 0, 0, 0, 0, 0, -0.4082483, 0, 0, -4e-07, 4e-07,
4e-07, 4e-07, 4e-07, 4e-07, 4e-07, 4e-07)

result
$multivariateNormality

$univariateNormality

$Descriptives

$multivariateOutliers
# remove outliers from dataset.
result_clean <- mvn(happy_nums, multivariateOutlierMethod = "quan", showOutliers = TRUE, showNewData = TRUE)
The covariance matrix of the data is singular.
There are 137 observations (in the entire dataset of 137 obs.) lying on the hyperplane
with equation a_1*(x_i1 - m_1) + ... + a_p*(x_ip - m_p) = 0 with (m_1, ..., m_p) the
mean of these observations and coefficients a_i from the vector a <- c(0.8164966, 0,
0, 0, 0, 0, 0, 0, 0, -0.4082483, 0, 0, 0, 0, 0, 0, -0.4082483, 0, 0, -4e-07, 4e-07,
4e-07, 4e-07, 4e-07, 4e-07, 4e-07, 4e-07)

dim(result_clean$newData)
[1] 135  27

Transform

Basically, there are two methods used in dealing with outliers, i.e. removing them from data set and data transformation.

As the outliers in our data count only 1% of the sample, it can be dealt by simply removing them from our dataset. The result (result_clean) shows new data with a dimension of 135 observation with 27 variables.

We also tried data tranformation method that is immune to the presence of outliers to see how . We chose one variable for this - the Human Freedom Index - and observed that it has a left-skewed distribution. We applied a square transformation on the variable and found that after the transformation its distribution becomes more symmetrical or normally distributed as shown in the histograms below.

#Data transformation using square transformation:
freedomsquare <- (hfi_happy_imp$hf_score)^2
#Before transformation:
#histogram
qplot(hfi_happy_imp$hf_score,
      geom = "histogram",
      bindwith = 1,
      main = "Human Freedom Index Histogram",
      xlab = "Human Freedom Score",
      fill = I("light blue"),
      col = I("turquoise"),
      alpha=I(1))
Ignoring unknown parameters: bindwith

#QQ plot
qqnorm(hfi_happy_imp$hf_score, main = "Human Freedom Index Score before data transformation")
qqline(hfi_happy_imp$hf_score, col = "deeppink")

#after data transformation
#histogram
qplot (freedomsquare, geom = "histogram",
      bindwith = 1,
      main = "Normalised Human Freedom Index Histogram",
      xlab = "Human Freedom Score",
      fill = I("palegreen"),
      col = I("deepskyblue"),
      alpha=I(1))
Ignoring unknown parameters: bindwith

#QQ plot
qqnorm(freedomsquare, main = "Normalised Human Freedom Index Score")
qqline(freedomsquare, col = "lime green")



LS0tCnRpdGxlOiAiTUFUSDIzNDkgU2VtZXN0ZXIgMiwgMjAxOSIKYXV0aG9yOiAiTWVpbGRhIFJhc3NpYXMgKHMzNzczMDY3KSIKc3VidGl0bGU6IEFzc2lnbm1lbnQgMwpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKLS0tCgoKCiMjIFJlcXVpcmVkIHBhY2thZ2VzIAoKCmBgYHtyfQpsaWJyYXJ5KCJyZWFkciIpCmxpYnJhcnkoImRwbHlyIikKbGlicmFyeSgidGlkeXIiKQpsaWJyYXJ5KCJkZWR1Y3RpdmUiKQpsaWJyYXJ5KCJkZWR1Y29ycmVjdCIpCmxpYnJhcnkoImVkaXRydWxlcyIpCmxpYnJhcnkoInZhbGlkYXRlIikKbGlicmFyeSgiSG1pc2MiKQpsaWJyYXJ5KCJmb3JlY2FzdCIpCmxpYnJhcnkoInN0cmluZ3IiKQpsaWJyYXJ5KCJsdWJyaWRhdGUiKQpsaWJyYXJ5KCJjYXIiKQpsaWJyYXJ5KCJvdXRsaWVycyIpCmxpYnJhcnkoIm12b3V0bGllciIpCmxpYnJhcnkoIk1WTiIpCmxpYnJhcnkoImluZm90aGVvIikKbGlicmFyeSgiTUFTUyIpCmxpYnJhcnkoIm1sciIpCmxpYnJhcnkoIm1scjMiKQpsaWJyYXJ5KCJnZ3Bsb3QyIikKbGlicmFyeSgia25pdHIiKQpsaWJyYXJ5ICgicm1hcmtkb3duIikKCgpgYGAKCgojIyBFeGVjdXRpdmUgU3VtbWFyeSAKClRoZSBhaW0gb2YgdGhpcyBhc3NpZ25tZW50IGlzIHRvIGRlbW9uc3RyYXRlIHRoZSBjb25jZXB0cyBhbmQgdGVjaG5pcXVlcyBpbiBEYXRhIFByZXByb2Nlc3Npbmcgb3IgYWxzbyBrbm93biBhcyBEYXRhIFdyYW5nbGluZy4gCkRhdGEgUHJlcHJvY2Vzc2luZyBpbiBkYXRhIG1pbmluZyBjYW4gYmUgc3VtbWFyaXNlZCBhcyBhIGRhdGEgbWluaW5nIHRlY2huaXF1ZSB0aGF0IGludm9sdmVzIHRyYW5zZm9ybWluZyByYXcgKGFuZCBjb21wbGV4KSBkYXRhIGludG8gYW4gdW5kZXJzdGFibGUgZm9ybWF0IHJlYWR5IGZvciBzdGF0aXN0aWNhbCBhbmFseXNpcy4gCgoqTWFqb3IgVGFza3MgaW4gRGF0YSBQcmVwcm9jZXNzaW5nIGFyZSBhcyBmb2xsb3cqOgoKKiAqKkRhdGEgY2xlYW5pbmcqKjogZmlsbCBpbiBtaXNzaW5nIHZhbHVlcywgc21vb3RoIG5vaXN5IGRhdGEsIGlkZW50aWZ5IG9yIHJlbW92ZSBvdXRsaWVycyBhbmQgbm9pc3kgZGF0YSwgYW5kIHJlc29sdmUgaW5jb25zaXN0ZW5jaWUuCiogKipEYXRhIGludGVncmF0aW9uKio6IGludGVncmF0aW9uIG9mIG11bHRpcGxlIGRhdGFiYXNlcywgZGF0YSBjdWJlcyBvciBmaWxlcy4KKiAqKkRhdGEgdHJhbnNmb3JtYXRpb24qKjogdGhlIHRhc2sgb2YgZGF0YSBub3JtYWxpc2F0aW9uIGFuZCBhZ2dyZWdhdGlvbiAoY29tYmluaW5nIHR3byBvciBtb3JlIG9iamVjdHMgaW50byBvbmUgb2JqZWN0KS4KKiAqKkRhdGEgcmVkdWN0aW9uKio6IHJlZHVjZXMgdGhlIGRhdGEgc2V0IGFuZCBwcm92aWRlcyBhIHNtYWxsZXIgdm9sdW1lIGRhdGEgc2V0LCB3aGljaCBwcm9kdWNlcyB0aGUgc2FtZSBvciBzaW1pbGFyIGFuYWx5dGljYWwgcmVzdWx0cyBhcyB0aGUgY29tcGxldGUgZGF0YSBzZXRzLgoqICoqRGF0YSBkaXNjcmV0aXNhdGlvbioqOiB0cmFuc2Zvcm1zIHF1YW50aXRhdGl2ZSBkYXRhIGludG8gcXVhbGl0YXRpdmUgZGF0YS4KClRocmVlIGRhdGFzZXRzIGFyZSB1c2VkIGluIGRlbW9uc3RyYXRpbmcgdGhlIG1ham9yIHRhc2tzIGluIGRhdGEgcHJlcHJvY2Vzc2luZyBpbiB0aGlzIGFzc2lnbm1lbnQ7IGkuZS4gdGhlIEh1bWFuIEZyZWVkb20gSW5kZXggMjAxOCBhbmQgV29ybGQgSGFwcGluZXNzIFJlcG9ydCAyMDE2IGFuZCAyMDE3LgoKVGhpcyBleGVyY2lzZSBpcyBhaW1lZCB0byBwcmVwYXJlIGEgZGF0YXNldCB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgYW5hbHlzaW5nIHdoZXRoZXIgaGlnaGVyIGRlZ3JlZSBvZiBmcmVlZG9tIG1lYW5zIGhpZ2hlciBsZXZlbCBvZiBoYXBwaW5lc3MuIAoKCgojIyBEYXRhIAoKCioqSHVtYW4gRnJlZWRvbSBJbmRleCoqCgpUaGUgSHVtYW4gRnJlZWRvbSBJbmRleCAoJ0hGSScpIHByZXNlbnQgdGhlIGRlZ3JlZSBvZiBodW1hbiBmcmVlZG9tIGluIHRoZSB3b3JsZCBiYXNlZCBvbiA3OSBpbmRpY2F0b3JzIG9mIHBlcnNvbmFsIGFuZCBlY29ub21pYyBmcmVlZG9tIGdyb3VwZWQgaW50byAxMiBjYXRlZ29yaWVzIGFzIGZvbGxvdyAocGYgPSBwZXJzb25hbCBmcmVlZG9tLCBlZiA9IGVjb25vbWljIGZyZWVkb20pOiAKCgoxLiBSdWxlIG9mIExhdyAocGZfcm9sKToKICAgICsgcGZfcm9sX3Byb2NlZHVyYWwgKFByb2NlZHVyYWwganVzdGljZSkKICAgICsgcGZfcm9sX2NpdmlsIChDaXZpbCBqdXN0aWNlKQogICAgKyBwZl9yb2xfY3JpbWluYWwgKENyaW1pbmFsIEp1c3RpY2UpCiAgICAKICAgIAogICAgCjIuIFNlY3VyaXR5IGFuZCBTYWZldHkgKHBmX3NzKToKICAgICsgcGZfc3NfaG9taWNpZGUgKEhvbWljaWRlKQogICAgKyBwZl9zc19kaXNhcHBlYXJhbmNlc19kaXNhcCAoRGlzYXBwZWFyYW5jZXMpCiAgICArIHBmX3NzX2Rpc2FwcGVhcmFuY2VzX3Zpb2xlbnQgKFZpb2xlbnQgICBjb25mbGljdHMpCiAgICArIHBmX3NzX2Rpc2FwcGVhcmFuY2VzX29yZ2FuaXplZCAoT3JnYW5pemVkIGNvbmZsaWN0cykKICAgICsgcGZfc3NfZGlzYXBwZWFyYW5jZXNfZmF0YWxpdGllcyAoVGVycm9yaXNtIGZhdGFsaXRpZXMpCiAgICArIHBmX3NzX2Rpc2FwcGVhcmFuY2VzX2luanVyaWVzIChUZXJyb3Jpc20gaW5qdXJpZXMpCiAgICArIHBmX3NzX2Rpc2FwcGVhcmFuY2VzIChEaXNhcHBlYXJhbmNlcywgY29uZmxpY3QsIGFuZCB0ZXJyb3Jpc20pCiAgICArIHBmX3NzX3dvbWVuX2ZnbSAoRmVtYWxlIGdlbml0YWwgbXV0aWxhdGlvbikKICAgICsgcGZfc3Nfd29tZW5fbWlzc2luZyAoTWlzc2luZyB3b21lbikKICAgICsgcGZfc3Nfd29tZW5faW5oZXJpdGFuY2Vfd2lkb3dzIChJbmhlcml0YW5jZSByaWdodHMgZm9yIHdpZG93cykKICAgICsgcGZfc3Nfd29tZW5faW5oZXJpdGFuY2VfZGF1Z2h0ZXJzIChJbmhlcml0YW5jZSByaWdodHMgZm9yIGRhdWdodGVycykKICAgICsgcGZfc3Nfd29tZW5faW5oZXJpdGFuY2UgKEluaGVyaXRhbmNlKQogICAgKyBwZl9zc193b21lbiAoV29tZW4ncyBzZWN1cml0eSkKCgoKMy4gTW92ZW1lbnQgKHBmX21vdmVtZW50KToKICAgICsgcGZfbW92ZW1lbnRfZG9tZXN0aWMgKEZyZWVkb20gb2YgZG9tZXN0aWMgbW92ZW1lbnQpCiAgICArIHBmX21vdmVtZW50X2ZvcmVpZ24gKEZyZWVkb20gb2YgZm9yZWlnbiBtb3ZlbWVudCkKICAgICsgcGZfbW92ZW1lbnRfd29tZW4gKFdvbWVuJ3MgbW92ZW1lbnQpCiAgCiAgCgo0LiBSZWxpZ2lvbiAocGZfcmVsaWdpb24pOgogICAgKyBwZl9yZWxpZ2lvbl9lc3RvcF9lc3RhYmxpc2ggKEZyZWVkb20gdG8gZXN0YWJsaXNoIHJlbGlnaW91cyBvcmdhbml6YXRpb25zKQogICAgKyBwZl9yZWxpZ2lvbl9lc3RvcF9vcGVyYXRlIChGcmVlZG9tIHRvIG9wZXJhdGUgcmVsaWdpb3VzIG9yZ2FuaXphdGlvbnMpCiAgICArIHBmX3JlbGlnaW9uX2VzdG9wIChGcmVlZG9tIHRvIGVzdGFibGlzaCBhbmQgb3BlcmF0ZSByZWxpZ2lvdXMgb3JnYW5pemF0aW9ucykKICAgICsgcGZfcmVsaWdpb25faGFyYXNzbWVudCAoSGFyYXNzbWVudCBhbmQgcGh5c2ljYWwgaG9zdGlsaXRpZXMpCiAgICArIHBmX3JlbGlnaW9uX3Jlc3RyaWN0aW9ucyAoTGVnYWwgYW5kIHJlZ3VsYXRvcnkgcmVzdHJpY3Rpb25zKQoKCgo1LiBBc3NvY2lhdGlvbiwgQXNzZW1ibHksIGFuZCBDaXZpbCBTb2NpZXR5IChwZl9hc3NvY2lhdGlvbik6CiAgICArIHBmX2Fzc29jaWF0aW9uX2Fzc29jaWF0aW9uIChGcmVlZG9tIG9mIGFzc29jaWF0aW9uKQogICAgKyBwZl9hc3NvY2lhdGlvbl9hc3NlbWJseSAoRnJlZWRvbSBvZiBhc3NlbWJseSkKICAgICsgcGZfYXNzb2NpYXRpb25fcG9saXRpY2FsX2VzdGFibGlzaCAoRnJlZWRvbSB0byBlc3RhYmxpc2ggcG9saXRpY2FsIHBhcnRpZXMpCiAgICArIHBmX2Fzc29jaWF0aW9uX3BvbGl0aWNhbF9vcGVyYXRlIChGcmVlZG9tIHRvIG9wZXJhdGUgcG9saXRpY2FsIHBhcnRpZXMpCiAgICArIHBmX2Fzc29jaWF0aW9uX3BvbGl0aWNhbCAoRnJlZWRvbSB0byBlc3RhYmxpc2ggYW5kIG9wZXJhdGUgcG9saXRpY2FsIHBhcnRpZXMpCiAgICArIHBmX2Fzc29jaWF0aW9uX3Byb2ZfZXN0YWJsaXNoIChGcmVlZG9tIHRvIGVzdGFibGlzaCBwcm9mZXNzaW9uYWwgb3JnYW5pemF0aW9ucykKICAgICsgcGZfYXNzb2NpYXRpb25fcHJvZl9vcGVyYXRlIChGcmVlZG9tIHRvIG9wZXJhdGUgcHJvZmVzc2lvbmFsIG9yZ2FuaXphdGlvbnMpCiAgICArIHBmX2Fzc29jaWF0aW9uX3Byb2YgKEZyZWVkb20gdG8gZXN0YWJsaXNoIGFuZCBvcGVyYXRlIHByb2Zlc3Npb25hbCBvcmdhbml6YXRpb25zKQogICAgKyBwZl9hc3NvY2lhdGlvbl9zcG9ydF9lc3RhYmxpc2ggKEZyZWVkb20gdG8gZXN0YWJsaXNoIGVkdWNhdGlvbmFsLCBzcG9ydGluZywgYW5kIGN1bHR1cmFsIG9yZ2FuaXphdGlvbnMpCiAgICArIHBmX2Fzc29jaWF0aW9uX3Nwb3J0X29wZXJhdGUgKEZyZWVkb20gdG8gb3BlcmF0ZSBlZHVjYXRpb25hbCwgc3BvcnRpbmcsIGFuZCBjdWx0dXJhbCBvcmdhbml6YXRpb25zKQogICAgKyBwZl9hc3NvY2lhdGlvbl9zcG9ydCAoRnJlZWRvbSB0byBlc3RhYmxpc2ggYW5kIG9wZXJhdGUgZWR1Y2F0aW9uYWwsIHNwb3J0aW5nLCBhbmQgY3VsdHVyYWwgb3JnYW5pemF0aW9ucykKCgoKNi4gRXhwcmVzc2lvbiBhbmQgSW5mb3JtYXRpb24gKHBmX2V4cHJlc3Npb24pOgogICAgKyBwZl9leHByZXNzaW9uX2tpbGxlZCAoUHJlc3Mga2lsbGVkKQogICAgKyBwZl9leHByZXNzaW9uX2phaWxlZCAoUHJlc3MgamFpbGVkKQogICAgKyBwZl9leHByZXNzaW9uX2luZmx1ZW5jZSAoTGF3cyBhbmQgcmVndWxhdGlvbnMgdGhhdCBpbmZsdWVuY2UgbWVkaWEgY29udGVudCkKICAgICsgcGZfZXhwcmVzc2lvbl9jb250cm9sIChQb2xpdGljYWwgcHJlc3N1cmVzIGFuZCBjb250cm9scyBvbiBtZWRpYSBjb250ZW50KQogICAgKyBwZl9leHByZXNzaW9uX2NhYmxlIChBY2Nlc3MgdG8gY2FibGUvc2F0ZWxsaXRlKQogICAgKyBwZl9leHByZXNzaW9uX25ld3NwYXBlcnMgKEFjY2VzcyB0byBmb3JlaWduIG5ld3NwYXBlcnMpCiAgICArIHBmX2V4cHJlc3Npb25faW50ZXJuZXQgKFN0YXRlIGNvbnRyb2wgb3ZlciBJbnRlcm5ldCBhY2Nlc3MpCiAgCgoKNy4gSWRlbnRpdHkgYW5kIFJlbGF0aW9uc2hpcHMgKHBmX2lkZW50aXR5KToKICAgICsgcGZfaWRlbnRpdHlfbGVnYWwgKExlZ2FsIGdlbmRlcikKICAgICsgcGZfaWRlbnRpdHlfcGFyZW50YWxfbWFycmlhZ2UgKFBhcmVudGFsIHJpZ2h0cyBpbiBtYXJyaWFnZSkKICAgICsgcGZfaWRlbnRpdHlfcGFyZW50YWxfZGl2b3JjZSAoUGFyZW50YWwgcmlnaHRzIGFmdGVyIGRpdm9yY2UpCiAgICArIHBmX2lkZW50aXR5X3BhcmVudGFsIChQYXJlbnRhbCByaWdodHMpCiAgICArIHBmX2lkZW50aXR5X3NleF9tYWxlIChNYWxlLXRvLW1hbGUgcmVsYXRpb25zaGlwcykKICAgICsgcGZfaWRlbnRpdHlfc2V4X2ZlbWFsZSAoRmVtYWxlLXRvLWZlbWFsZSByZWxhdGlvbnNoaXBzKQogICAgKyBwZl9pZGVudGl0eV9zZXggKFNhbWUtc2V4IHJhbGl0aW9uc2hpcHMpCiAgICArIHBmX2lkZW50aXR5X2Rpdm9yY2UgKERpdm9yY2UpCgoKCjguIFNpemUgb2YgR292ZXJubWVudCAoZWZfZ292ZXJubWVudCk6CiAgICArIGVmX2dvdmVybm1lbnRfY29uc3VtcHRpb24gKEdvdmVybm1lbnQgY29uc3VtcHRpb24pCiAgICArIGVmX2dvdmVybm1lbnRfdHJhbnNmZXJzIChUcmFuc2ZlcnMgYW5kIHN1YnNpZGllcykKICAgICsgZWZfZ292ZXJubWVudF9lbnRlcnByaXNlcyAoR292ZXJubWVudCBlbnRlcnByaXNlcyBhbmQgaW52ZXN0bWVudHMpCiAgICArIGVmX2dvdmVybm1lbnRfdGF4X2luY29tZSAoVG9wIG1hcmdpbmFsIGluY29tZSB0YXggcmF0ZSkKICAgICsgZWZfZ292ZXJubWVudF90YXhfcGF5cm9sbCAoVG9wIG1hcmdpbmFsIGluY29tZSBhbmQgcGF5cm9sbCB0YXggcmF0ZSkKICAgICsgZWZfZ292ZXJubWVudF90YXggKFRvcCBtYXJnaW5hbCB0YXggcmF0ZSkKCgoKOS4gTGVnYWwgU3lzdGVtIGFuZCBQcm9wZXJ0eSBSaWdodHMgKGVmX2xlZ2FsKToKICAgICsgZWZfbGVnYWxfanVkaWNpYWwgKEp1ZGljaWFsIGluZGVwZW5kZW5jZSkKICAgICsgZWZfbGVnYWxfY291cnRzIChJbXBhcnRpYWwgY291cnRzKQogICAgKyBlZl9sZWdhbF9wcm90ZWN0aW9uIChQcm90ZWN0aW9uIG9mIHByb3BlcnR5IHJpZ2h0cykKICAgICsgZWZfbGVnYWxfbWlsaXRhcnkgKE1pbGl0YXJ5IGludGVyZmVyZW5jZSBpbiBydWxlIG9mIGxhdyBhbmQgcG9saXRpY3MpCiAgICArIGVmX2xlZ2FsX2ludGVncml0eSAoSW50ZWdyaXR5IG9mIHRoZSBsZWdhbCBzeXN0ZW0pCiAgICArIGVmX2xlZ2FsX2VuZm9yY2VtZW50IChMZWdhbCBlbmZvcmNlbWVudCBvZiBjb250cmFjdHMpCiAgICArIGVmX2xlZ2FsX3Jlc3RyaWN0aW9ucyAoUmVndWxhdG9yeSByZXN0cmljdGlvbnMgb24gdGhlIHNhbGUgb2YgcmVhbCBwcm9wZXJ0eSkKICAgICsgZWZfbGVnYWxfcG9saWNlIChSZWxpYWJpbGl0eSBvZiBwb2xpY2UpCiAgICArIGVmX2xlZ2FsX2NyaW1lIChCdXNpbmVzcyBjb3N0cyBvZiBjcmltZSkKICAgICsgZWZfbGVnYWxfZ2VuZGVyIChHZW5kZXIgYWRqdXN0bWVudCkKCgoKMTAuIEFjY2VzcyB0byBTb3VuZCBNb25leSAoZWZfbW9uZXkpOgogICAgKyBlZl9tb25leV9ncm93dGggKE1vbmV5IGdyb3d0aCkKICAgICsgZWZfbW9uZXlfc2QgKFN0YW5kYXJkIGRldmlhdGlvbiBvZiBpbmZsYXRpb24pCiAgICArIGVmX21vbmV5X2luZmxhdGlvbiAoSW5mbGF0aW9uOiBtb3N0IHJlY2VudCB5ZWFyKQogICAgKyBlZl9tb25leV9jdXJyZW5jeSAoRnJlZWRvbSB0byBvd24gZm9yZWlnbiBjdXJyZW5jeSBiYW5rIGFjY291bnQpCiAKIAogICAgCjExLiBGcmVlZG9tIHRvIFRyYWRlIEludGVybmF0aW9uYWxseSAgKGVmX3RyYWRlKQogICAgKyBlZl90cmFkZV90YXJpZmZzX3JldmVudWUgKFJldmVudWUgZnJvbSB0cmFkZSB0YXhlcyAoJSBvZiB0cmFkZSBzZWN0b3IpKQogICAgKyBlZl90cmFkZV90YXJpZmZzX21lYW4gKE1lYW4gdGFyaWZmIHJhdGUpCiAgICArIGVmX3RyYWRlX3RhcmlmZnNfc2QgKFN0YW5kYXJkIGRldmlhdGlvbiBvZiB0YXJpZmZzIHJhdGVzKQogICAgKyBlZl90cmFkZV90YXJpZmZzIChUYXJpZmZzKQogICAgKyBlZl90cmFkZV9yZWd1bGF0b3J5X25vbnRhcmlmZiAoTm9udGFyaWZmIHRyYWRlIGJhcnJpZXJzKQogICAgKyBlZl90cmFkZV9yZWd1bGF0b3J5X2NvbXBsaWFuY2UgKENvbXBsaWFuY2UgY29zdHMgb2YgaW1wb3J0aW5nIGFuZCBleHBvcnRpbmcpCiAgICArIGVmX3RyYWRlX3JlZ3VsYXRvcnkgKFJlZ3VsYXRvcnkgdHJhZGUgYmFycmllcnMpCiAgICArIGVmX3RyYWRlX2JsYWNrIChCbGFjay1tYXJrZXQgZXhjaGFuZ2UgcmF0ZXMpCiAgICArIGVmX3RyYWRlX21vdmVtZW50X2ZvcmVpZ24gKEZvcmVpZ24gb3duZXJzaGlwL2ludmVzdG1lbnQgcmVzdHJpY3Rpb25zKQogICAgKyBlZl90cmFkZV9tb3ZlbWVudF9jYXBpdGFsIChDYXBpdGFsIGNvbnRyb2xzKQogIGAgKyBlZl90cmFkZV9tb3ZlbWVudF92aXNpdCAoRnJlZWRvbSBvZiBmb3JlaWduZXJzIHRvIHZpc2l0KQogICAgKyBlZl90cmFkZV9tb3ZlbWVudCAoQ29udHJvbHMgb2YgdGhlIG1vdmVtZW50IG9mIGNhcGl0YWwgYW5kIHBlb3BsZSkKCgoKMTIuIFJlZ3VsYXRpb24gb2YgQ3JlZGl0LCBMYWJvciwgYW5kIEJ1c2luZXNzIChlZl9yZWd1bGF0aW9uX2NyZWRpdF9vd25lcnNoaXApCgoKVGhlIEhGSSAyMDE4IHJlcG9ydCBpcyBjby1wdWJsaXNoZWQgYnkgdGhlIENhdG8gSW5zdGl0dXRlLCB0aGUgRnJhc2VyIEluc3RpdHV0ZSwgYW5kIHRoZSBMaWJlcmFsZXMgSW5zdGl0dXQgYXQgdGhlIEZyaWVkcmljaCBOYXVtYW5uIEZvdW5kYXRpb24gZm9yIEZyZWVkb20sIHdoaWNoIGNhbiBiZSBmb3VuZCBhdCB0aGlzIGxpbms6IGh0dHBzOi8vd3d3LmNhdG8ub3JnL2h1bWFuLWZyZWVkb20taW5kZXgtbmV3CgoKVGhlIEhGSSAyMDE4IGRhdGFzZXQgY292ZXJzIHRoZSBIRkkgZnJvbSB5ZWFyIDIwMDggdXAgdG8gMjAxNiBhbmQgMTYyIGNvdW50cmllcy4gSXQgY2FuIGFsc28gYmUgcmV0aXJldmVkIGZyb20gS2FnZ2xlOiBodHRwczovL3d3dy5rYWdnbGUuY29tL2NoY2hsb2UyOS9nZHAtcGVyLWNhcGl0YQoKCgoKCioqVGhlIFdvcmxkIEhhcHBpbm5lc3MgUmVwb3J0KioKClRoZSBXb3JsZCBIYXBwaW5lc3MgUmVwb3J0IGlzIGEgbGFuZG1hcmsgc3VydmV5IG9mIHRoZSBzdGF0ZSBvZiBnbG9iYWwgaGFwcGluZXNzIHRoYXQgcmFua3MgMTU1LTE1NyBjb3VudHJpZXMgYnkgaG93IGhhcHB5IHRoZWlyIGNpdGl6ZW5zIHBlcmNlaXZlIHRoZW1zZWx2ZXMgdG8gYmUuIFRoZSByZXBvcnQgaXMgcHJvZHVjZWQgYnkgdGhlIFVuaXRlZCBOYXRpb25zIFN1c3RhaW5hYmxlIERldmVsb3BtZW50IFNvbHV0aW9ucyBOZXR3b3JrIGluIHBhcnRuZXJzaGlwIHdpdGggdGhlIEVybmVzdG8gSWxseSBGb3VuZGF0aW9uLgpUaGUgb3JpZ2luYWwgV29ybGQgSGFwcGlubmVzcyBSZXBvcnQgMjAxOCBjYW4gYmUgZm91bmQgYXQgdGhpcyBsaW5rOiBodHRwczovL3dvcmxkaGFwcGluZXNzLnJlcG9ydC9lZC8yMDE4LwoKSG93ZXZlciwgZm9yIHRoZSBwdXJwb3NlIG9mIHRoZSBkYXRhIHByZXBvY2Vzc2luZyBleGVyY2lzZSwgdGhlIGRhdGFzZXQgaGFzIGJlZW4gc291cmNlZCBmcm9tIEthZ2dsZToKCiAgICArIGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vdW5zZHNuL3dvcmxkLWhhcHBpbmVzcyMyMDE2LmNzdgogICAgKyBodHRwczovL3d3dy5rYWdnbGUuY29tL3Vuc2Rzbi93b3JsZC1oYXBwaW5lc3MjMjAxNy5jc3YKClRoZSByZXBvcnQgcmFua3MgMTU2IGNvdW50cmllcyBieSB0aGVpciBoYXBwaW5lc3MgbGV2ZWwgZnJvbSB5ZWFyIDIwMjYgYW5kIDIwMTcuIFRoZSBoYXBwaW5lc3Mgc2NvcmUgYXJlIGJhc2VkIG9uIGFuc3dlcnMgdG8gdGhlIG1haW4gbGlmZSBldmFsdWF0aW9uIHF1ZXN0aW9uIGFza2VkIGluIHRoZSBHYWxsdXAgV29ybGQgUG9sbCAoR2FsbHVwIGlzIFVTIGRhdGEgYW5hbHl0aWMgZmlybSkuIEluIHRoZSBzdXJ2ZXksIHBlb3BsZSB3ZXJlIGFza2VkIHRvIHJhdGUgdGhlaXIgaGFwcGluZXNzIG9uIGEgc2NhcmUgZnJvbSAwIHRvIDEwIHdpdGggMCBiZWluZyB0aGUgd29yc3QgcG9zc2libGUgbGlmZSBhbmQgMTAgYmVpbmcgdGhlIGJlc3QgcG9zc2libGUgbGlmZS4gClRoZSByZXBvcnQgdGhlbiBkZXRlcm1pbmVkIHNpeCBrZXkgZmFjdG9ycyB0aGF0IGNvbnRyaWJ1dGUgdG8gaGFwcGluZXNzIHNjb3JlOgoKICAgICsgZWNvbm9taWMgcHJvZHVjdGlvbiAoKkdEUCBwZXIgY2FwaXRhKikKICAgICsgc29jaWFsIHN1cHBvcnQgKCpGYW1pbHkqKQogICAgKyBsaWZlIGV4cGVjdGFuY3kgKCpIZWFsdGgqKQogICAgKyBmcmVlZG9tIHRvIG1ha2UgbGlmZSBjaG9pY2VzICgqRnJlZWRvbSopKgogICAgKyBhYnNlbmNlIG9mIGNvcnJ1cHRpb24gKCpUcnVzdCAtIEdvdmVybWVudCBDb3JydXB0aW9uKiksIGFuZCAKICAgICsgZ2VuZXJvc2l0eSAoKkdlbmVyb3NpdHkqKS4KCioqTm90ZSoqOiB0aGUgRnJlZWRvbSB2YXJpYWJsZSBpbiB0aGUgV29ybGQgSGFwcGluZXNzIFJlcG9ydCBpcyBkaWZmZXJlbnQgbWVhc3VyZSB0byBGcmVlZG9tIGluIEh1bWFuIEZyZWVkb20gSW5kZXguIApUaGUgRnJlZWRvbSBsZXZlbCBpcyBkZXRlcm1pbmVkIGJhc2VkIG9uIHRoZSBzdXJ2ZXkgcmVzdWx0IG9mIHRoZSBHYWxsdXAgV29ybGQgUG9sbCB3aGVyZSBhcHBsaWNhbnRzIHdlcmUgYXNrZWQgdGhpcyBxdWVzdGlvbjoKIkFyZSB5b3Ugc2F0aXNmaWVkIG9yIGRpc3NhdGlzZmllZCB3aXRoIHlvdXIgZnJlZWRvbSB0byBjaG9vc2Ugd2hhdCB5b3UgZG8gd2l0aCB5b3VyIGxpZmU/IgoKCkluIG9yZGVyIHRvIG1ha2UgdGhlIGhhcHBpbmVzcyBzY29yZSBmb3IgZWFjaCBjb3VudHJ5IG1vcmUgbWVhbmluZ2Z1bCwgYSBoeXBvdGhldGljYWwgY291bnRyeSB3aGVyZSB0aGF0IGhhcyB0aGUgbG93ZXN0IGhhcHBpbmVzcyBsZXZlbCBpcyBlc3RhYmxpc2hlZDsgaXQgaXMgY2FsbGVkICcqRHlzdG9waWEqJyB3aGljaCBpcyB0aGUgb3Bwb3NpdGUgb2YgVXRvcGlhLiBUaGUgcHVycG9zZSBpbiBlc3RhYmxpc2hpbmcgRHlzdG9waWEgaXMgdG8gaGF2ZSBhIGJlbmNobWFyayBhZ2FpbnN0IHdoaWNoIGFsbCBjb3VudHJpZXMgY2FuIGJlIGZhdm9yYWJseSBjb21wYXJlZCAobm8gY291bnRyeSBwZXJmb3JtcyBtb3JlIHBvb3JseSB0aGFuIER5c3RvcGlhKSBpbiB0ZXJtcyBvZiBlYWNoIG9mIHRoZSBzaXgga2V5IHZhcmlhYmxlcywgdGh1cyBhbGxvd2luZyBlYWNoIHN1Yi1iYXIgdG8gYmUgb2YgcG9zaXRpdmUgd2lkdGguIAoKClRoZSByZXNpZHVhbHMsIG9yIHVuZXhwbGFpbmVkIGNvbXBvbmVudHMsIGRpZmZlciBmb3IgZWFjaCBjb3VudHJ5LCByZWZsZWN0aW5nIHRoZSBleHRlbnQgdG8gd2hpY2ggdGhlIHNpeCB2YXJpYWJsZXMgZWl0aGVyIG92ZXItIG9yIHVuZGVyLWV4cGxhaW4gYXZlcmFnZSAyMDE0LTIwMTYgbGlmZSBldmFsdWF0aW9ucy4gVGhlc2UgcmVzaWR1YWxzIGhhdmUgYW4gYXZlcmFnZSB2YWx1ZSBvZiBhcHByb3hpbWF0ZWx5IHplcm8gb3ZlciB0aGUgd2hvbGUgc2V0IG9mIGNvdW50cmllcy4KCgpUaGUgd2hpc2tlcnMgb3IgdXBwZXIgbG93ZXIgbGV2ZWxzIG9mIGNvbmZpZGVuY2UgaW5kaWNhdGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciB0aGUgZXN0aW1hdGVkIG1lYW5zLiAKCgpgYGB7cn0Kc2V0d2QoIn4vRGVza3RvcC9STUlUL01BVEgyMzQ5IOKAkyBEYXRhIFByZXByb2Nlc3NpbmcvQXNzaWdubWVudHMvQXNzaWdubWVudDMvRGF0YSIpCgpsaWJyYXJ5KHJlYWRyKQpoZmlfcmF3IDwtIHJlYWRfY3N2KCJoZmlfY2NfMjAxOC5jc3YiKQpoZWFkKGhmaV9yYXcpCgpoYXBweTE2IDwtIHJlYWRfY3N2KCIyMDE2LmNzdiIpCmhlYWQoaGFwcHkxNikKCmhhcHB5MTcgPC0gcmVhZF9jc3YoIjIwMTcuY3N2IikKaGVhZChoYXBweTE3KQoKCgoKYGBgCgojIyBVbmRlcnN0YW5kIAoKCiogQXMgYm90aCAqaGFwcHkxNiogJiAqaGFwcHkxNyogc2hhcmVzIGFsbW9zdCBpZGVudGljYWwgdmFyaWFibGVzLCB0byBvYnNlcnZhdGlvbnMgZnJvbSBlYWNoIHllYXIsIGFuIGFkZGl0aW9uYWwgY29sdW1uICd5ZWFyJyBpcyBhZGRlZCBpbnRvIGVhY2ggZGF0YWZyYW1lLgoKCgoqIFRoZSBwdXJwb3NlIG9mIHRha2luZyBkYXRhIHByZXBhcmF0aW9uIGluIHRoaXMgZXhlcmNpc2UgaXMgdG8gcHJvZHVjZSBhbiBlZmZpY2llbnQgYW5kIHVuZGVyc3RhYmxlIGRhdGFzZXQgZm9yIGFuYWx5c2luZyB3aGV0aGVyIGZyZWVkb20gbWVhbnMgaGFwcGluZXNzLiBIZW5jZSwgc29tZSB2YXJpYWJsZXMgaW4gKmhhcHB5MTYqIGFuZCAqaGFwcHkxNyogdGhhdCBkbyBub3QgaGF2ZSBncmVhdCBpbXBhY3QgdG8gdGhlIGVuZCByZXN1bHQgb2YgdGhlIGV4ZXJjaXNlIGFyZSByZW1vdmVkLCBlLmcuOiB0aGUgbGV2ZWxzIG9mIGNvbmZpZGVuY2UgYW5kIHdoaXNrZXJzIHZhcnJpYWJsZXMuIENvbHVtbiAnUmVnaW9uJyBpcyBhbHNvIGRyb3BwZWQgdG8gYXZvaWQgY3JlYXRpbmcgbWlzc2luZyB2YWx1ZXMgZm9yIGRhdGFmcmFtZSAqaGFwcHkxNyogdGhhdCBkb2Vzbid0IGhhdmUgY29sdW1uICdSZWdpb24nLiBEcm9wcGluZyB2YXJpYWJsZXMgYXJlIGRvbmUgYnkgbWFraW5nIGEgc3Vic2V0IG91dCBvZiB0aGUgZGF0YXNldCB1c2luZyBhIHZlY3RvciBvZiBjb2x1bW4gbmFtZXMgZXhjZXB0IHRoZSBuYW1lcyBvZiB0aGUgdW53YW50ZWQgY29sdW1ucy4KCgoKKiBDaGVjayBlYWNoIGRhdGFmcmFtZXMnIHN0cnVjdHVyZSB1c2luZyAqc3RyKCkqIGZ1bmN0aW9uICBiZWZvcmUgbWVyZ2luZyB0aGUgdHdvIGRhdGFmcmFtZXMgaW4gb3JkZXIgdG8gc2VlIGlmIHRoZXJlIGlzIGFueSBkaWZmZXJlbmNlIGluIHJlZ2FyZHMgdG8gdGhlIGRhdGEgZGltZW5zaW9uIGFuZCB2YXJpYWJsZXMgdXNpbmcgKmFudGlfam9pbigpKiBmdW5jdGlvbi4gVGhlIHJlc3VsdCBzaG93aW5nIHRoYXQgdGhleSBhcmUgam9pbmVkIGJ5IDQgdmFyaWFibGVzIG9ubHksIGkuZS4gYnkgIkNvdW50cnkiLCAiRmFtaWx5IiwgIkZyZWVkb20iLCAiR2VuZXJvc2l0eSJhbmQgInllYXIiLgoKRGlmZmVyZW5jZXMgYmV0d2VlbiAqaGFwcHkxNiogJiAqaGFwcHkxNyogZGF0YWZyYW1lcyBhcmUgdGhlIHJlc3VsdHMgb2YgaW5jb25zaXN0ZW5jeSBpbiBuYW1pbmcgdmFyaWFibGVzIGFuZCBkaWZmZXJlbmNlIGluIHRoZSBudW1iZXIgb2YgY291bnRyaWVzIGJlaW5nIHN1cnZleWVkLgpJbiBvcmRlciB0byBhdm9pZCBkdXBsaWNhdGVzIG9mIHRoZSBjb21tb24gY29sdW1ucyBpbiB0aGUgdHdvIGRhdGFmcmFtZXMgYmVpbmcgam9pbmVkLCBjb25zaXN0ZW5jeSBpbiBuYW1pbmcgdmFyaWFibGVzLiBTdWl0YWJseSwgY29sdW1ucyBpbiAqaGFwcHkxNiogYXJlIHJlbmFtZWQgaW4gYWNjb3JkYW5jZSB0byB0aGVpciBjb3JyZXNwb25kaW5nIHZhcmlhYmxlcyBpbiAqaGFwcHkxNyogYnkgdXNpbmcgKm5hbWVzKCkqIGZ1bmN0aW9uLiAKCgoKKiBNZXJnaW5nIGluc3RlYWQgb2Ygam9pbmluZyBpcyB1c2VkIGJlY2F1c2UgYm90aCBkYXRhIHNoYXJlcyBzYW1lIHZhcmlhYmxlcy4gTWVyZ2luZyBpcyBkb25lIGJ5IHVzaW5nICpiaW5kX3Jvd3MoeCx5KSouCgoKKiBGb3IgYSBwdXJwb3NlIG9mIGRlbW9uc3RyYXRpbmcgdGFza3MgaW4gZGF0YSBwcmVwb2Nlc3NpbmcsIG5vdCBhbGwgdmFyaWFibGVzIGluIGh1bWFuIGZyZWVkb20gaW5kZXggYXJlIHVzZWQuIEEgc2ltcGxpZmllZCBkYXRhZnJhbWUgaXMgY3JlYXRlZCBieSBzdWJzZXR0aW5nIHZhcmlhYmxlcyBmcm9tIGhmaV9yYXcgZGF0YWZyYW1lIHdoZXJlIG9ubHkgdmFyaWFibGVzIHRoYXQgcmVwcmVzZW50IHRoZSB0d2VsdmUgZmFjdG9ycyB0aGF0IGRldGVybWluZSB0aGUgaHVtYW4gZnJlZWRvbSBpbmRleCBwcmV2aW91c2x5IGRlc2NyaWJlZCBpbiB0aGUgKipEYXRhKiogc2VjdGlvbiBhcmUgY2hvc2VuIGFsb25nIHdpdGggJ3llYXInLCAncmVnaW9uJywgSVNPX2NvZGUsICdjb3VudHJ5JywgdG90YWwgZnJlZWRvbSBzY29yZXMgJiByYW5rcy4gVGhlIHZhbHVlIG9mIHRoZSB0d2VsdmUgZGV0ZXJtaW5hbnRzID0gbWVhbiBvZiBjb21wb25lbnRzIHdpdGhpbiBlYWNoIGRldGVybWluYW50cykuIAoKKiBDb2x1bW4gJ2NvdW50cmllcycgaW4gdGhlIG5ldyBkYXRhZnJhbWUgKmhmaSogaXMgcmVuYW1lZCB0byBiZSAnQ291bnRyeScgdG8gbWF0Y2ggY29ycmVzcG9uZGluZyBjb2x1bW4gaW4gKmpvaW5lZF9oYXBweSogdXNpbmcgZnVuY3Rpb24gKm5hbWVzKCkqCgoqIEpvaW4gdGhlIGh1bWFuIGZyZWVkb20gaW5kZXggZGF0YWZyYW1lIGFuZCB0aGUgd29ybGQgaGFwcGluZXNzIGluZGV4IGRhdGFmcmFtZSAqam9pbl9oYXBweSogdXNpbmcgYSB1c2luZyBhbGwgdmFyaWFibGVzIHRoYXQgYXBwZWFyIGluIGJvdGggdGFibGVzIHRvIGpvaW4gdGhlbSAobmF0dXJhbCBqb2luKS4gSm9pbmluZyB0aGUgdHdvIHRhYmxlIGJhc2VkIG9uIHRoZWlyIGNvbW1vbiB2YXJpYWJsZXMgY2FuIGJlIGRvbmUgYnkgKmxlZnRfam9pbigpKiBvcGVyYXRpb24uCgoqIExhc3RseSwgdHJhbnNmb3JtIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBpbiB0aGUgY29tYmluZWQgdGFibGUgaW50byBmYWN0b3IuIEluIHN0YXRpc3RpY2FsIG1vZGVsbGluZywgc3RvcmluZyBjYXRlZ29yaWNhbCBkYXRhIGFzIGZhY3RvciBlbnN1cmVzIHRoYXQgdGhlIG1vZGVsbGluZyBmdW5jdGlvbnMgd2lsbCB0cmVhdCB0aGUgZGF0YSBjb3JyZWN0bHkuIFRyYW5zZm9ybWF0aW9uIGlzIGRvbmUgYnkgdXNpbmcgKmxhcHBseSgpKiBhbmQgKmFzLiogZnVuY3Rpb25zLgoKCmBgYHtyfQojVG8ga2VlcCBkYXRhIGVhY2ggeWVhcjoKaGFwcHkxNiR5ZWFyIDwtIDIwMTYKaGFwcHkxNyR5ZWFyIDwtIDIwMTcKCgoKCiNSZW1vdmUgcmVkdW5kYW50IHZhcmlhYmxlcyBpbiAnaGFwcHkxNicgYW5kICdoYXBweTE3JwpoYXBweTE2YSA8LSBoYXBweTE2Wy1jKDIsNTo2KV0KaGVhZChoYXBweTE2YSkKCgoKaGFwcHkxN2EgPC0gaGFwcHkxN1stYyg0OjUpXQpoZWFkKGhhcHB5MTdhKQoKCiNDaGVjayBlYWNoIGRhdGFmcmFtZSBzdHJ1Y3R1cmUgYmVmb3JlIGpvaW5pbmcgaGFwcHkxNiAmIGhhcHB5MTcgZGF0YWZyYW1lcyB0byBzZWUgaWYgdGhlcmUgaXMgYW55IGRpZmZlcmVuY2UgaW4gcmVnYXJkcyB0byB0aGUgZGF0YSBkaW1lbnNpb24gYW5kIHZhcmlhYmxlcy4Kc3RyKGhhcHB5MTZhKQpzdHIoaGFwcHkxN2EpCgoKCiNDaGVjayBtaXNtYXRjaGVzIGJldHdlZW4gaGFwcHkxNmEgYW5kIGhhcHB5MTdhCmFudGlfam9pbihoYXBweTE2YSxoYXBweTE3YSkKCgoKI1JlbmFtZSBjb2x1bW5zIGluIGhhcHB5MTZhIGRhdGFmcmFtZSB0byBiZSBjb25zaXN0ZW50IHdpdGggaGFwcHkxN2EgY29sdW1uczoKCm5hbWVzKGhhcHB5MTZhKVsyXSA8LSAiSGFwcGluZXNzLlJhbmsiCgpuYW1lcyhoYXBweTE2YSlbM10gPC0gIkhhcHBpbmVzcy5TY29yZSIKCm5hbWVzKGhhcHB5MTZhKVs0XSA8LSAiRWNvbm9teS4uR0RQLnBlci5DYXBpdGEuIgoKbmFtZXMoaGFwcHkxNmEpWzZdIDwtICJIZWFsdGguLkxpZmUuRXhwZWN0YW5jeS4iCgpuYW1lcyhoYXBweTE2YSlbOF0gPC0gIlRydXN0Li5Hb3Zlcm5tZW50LkNvcnJ1cHRpb24uIgoKbmFtZXMoaGFwcHkxNmEpWzEwXSA8LSAiRHlzdG9waWEuUmVzaWR1YWwiCgpoZWFkKGhhcHB5MTZhKQoKCiNNZXJnZSAnaGFwcHkxNmEnIHdpdGggJ2hhcHB5MTdhJwpqb2luZWRfaGFwcHkgPC0gYmluZF9yb3dzKGhhcHB5MTZhLGhhcHB5MTdhKQoKbmFtZXMoam9pbmVkX2hhcHB5KSA8LSBjKCJDb3VudHJ5IiwiSGFwcGluZXNzX1JhbmsiLAogICAgICAgICAgICAgICAgICAgICAgICAgIkhhcHBpbmVzc19TY29yZSIsIkdEUF9wZXJfQ2FwaXRhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAiRmFtaWx5IiwiSGVhbHRoIiwiRnJlZWRvbSIsIlRydXN0X0dvdnRfQ29ycnVwdGlvbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIkdlbmVyb3NpdHkiLCJEeXN0b3BpYV9SZXNpZHVhbCIsInllYXIiKQpoZWFkKGpvaW5lZF9oYXBweSkKc3RyKGpvaW5lZF9oYXBweSkKCgoKI0NoZWNrIHN0cnVjdHVyZSBvZiBodW1hbiBmcmVlZG9tIGluZGV4ICdoZmlfcmF3CnN0cihoZmlfcmF3KQoKCgojU2ltcGxpZnkgaGZpX3JhdyBieSBzdWJzZXR0aW5nCmhmaSA8LSBzdWJzZXQoaGZpX3Jhdywgc2VsZWN0ID0gYygoMTo0KSwgaGZfc2NvcmUsIGhmX3JhbmssIHBmX3JvbCwgcGZfc3MsIHBmX21vdmVtZW50LCBwZl9yZWxpZ2lvbiwgcGZfYXNzb2NpYXRpb24sIHBmX2V4cHJlc3Npb24sIHBmX2lkZW50aXR5LCBwZl9zY29yZSwgcGZfcmFuaywgZWZfZ292ZXJubWVudCwgZWZfbGVnYWwsIGVmX21vbmV5LCBlZl90cmFkZSwgZWZfcmVndWxhdGlvbiwgZWZfc2NvcmUsIGVmX3JhbmspKQoKCgojUmVuYW1lIHZhcmlhYmxlICdjb3VudHJpZXMnIHRvIG1hdGNoICdDb3VudHJ5JyBpbiBqb2luZWRfaGFwcHkKbmFtZXMoaGZpKVszXSA8LSAiQ291bnRyeSIKCmhlYWQoaGZpKQpkaW0oaGZpKQoKCgojSm9pbiBodW1hbiBmcmVlZG9tIGluZGV4ICdoZmknICYgd29ybGQgaGFwcGluZXNzIGluZGV4ICdqb2luZWRfaGFwcHknCmhmaV9oYXBweSA8LSBoZmkgJT4lIGxlZnRfam9pbihqb2luZWRfaGFwcHkpCgojVHJhbnNmb3JtIGNvbHVtbiAyLTQgaW50byBmYWN0b3IKaGZpX2hhcHB5WywyOjRdIDwtIGxhcHBseShoZmlfaGFwcHlbLDI6NF0sIGFzLmZhY3RvcikKCnN0cihoZmlfaGFwcHkpCgoKCgoKCmBgYAoKCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSSAKClRoZSBjb21iaW5lZCBkYXRhc2V0IGlzIHRpZHkgaW4gYSB3YXkgdGhhdCBpdCBtZWV0cyB0aGUgdGhyZWUgcmVxdWlyZW1lbnRzIHdoaWNoIG1ha2UgYSBkYXRhc2V0IHRpZHk6CiAgICArIEVhY2ggdmFyaWFibGUgbXVzdCBoYXZlIGl0cyBvd24gY29sdW1uLgogICAgKyBFYWNoIG9ic2VydmF0aW9uIG11c3QgaGF2ZSBpdHMgb3duIHJvdy4KICAgICsgRWFjaCB2YWx1ZSBtdXN0IGhhdmUgaXRzIG93biBjZWxsLgogICAgCiAgICAKCmBgYHtyfQpoZWFkKGhmaV9oYXBweSkKCmBgYAoKIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJSSAKCiogICBBIG5ldyB2YXJpYWJsZSAiSGFwcGluZXNSYW5rX0NoYW5nZSIgaXMgY3JlYXRlZCB0byBzZWUgaWYgdGhlcmUgaXMgYW55IGNoYW5nZSBpbiB0aGUgbGV2ZWwgb2YgaGFwcGluZXNzIHNpbmNlIDIwMTYgYnkgdXNpbmcgKm11dGF0ZSgpKiBmdW5jdGlvbi4KCgoKYGBge3J9CgpkZjwtbWVyZ2UoaGFwcHkxNmFbLGMoMSwzKV0sCiAgICAgICAgICAgaGFwcHkxN2FbLGMoMSwzKV0sCiAgICAgICAgICAgYnkueCA9ICJDb3VudHJ5IiwKICAgICAgICAgICBieS55ID0gIkNvdW50cnkiKQpjb2xuYW1lcyhkZik8LWMoIkNvdW50cnkiLCJIYXBwaW5lc3NfUmFuazE2IiwiSGFwcGluZXNzX1JhbmsxNyIpCgpkZjE8LWRmJT4lCiAgbXV0YXRlKEhhcHBpbmVzc1JhbmtfQ2hhbmdlID0gSGFwcGluZXNzX1JhbmsxNyAtIEhhcHBpbmVzc19SYW5rMTYpIApkZjEKCmBgYAoKCiMjCVNjYW4gSSAKICAqIE1vc3Qgb2YgdGhlIG1pc3NpbmcgdmFsdWVzIGFyZSByZXN1bHRlZCBmcm9tIHdvcmxkLWhhcHBpbmVzcy1pbmRleCB2YXJpYWJsZXMgdGhhdCBzdGFydCBmcm9tIHllYXIgMjAxNiB3aGlsc3QgdGhlIGh1bWFuLWZyZWVkb20taW5kZXggc3RhcnRlZCBmcm9tIDIwMDguCkFzIGl0IGlzIGltcG9zc2libGUgdG8gcmVwbGFjZSB0aG9zZSBtaXNzaW5nIHZhbHVlcyB3aXRoIG1lYW5pbmdmdWwgdmFsdWVzLCBvYnNlcnZhdGlvbnMgZnJvbSB5ZWFyIDIwMDggLSAyMDE1IGFyZSBkZWxldGVkIGJ5IHN1YnNldHRpbmcgdGhlIHllYXIgMjAxNiAmIDIwMTcgZGF0YS4KCiAgKiBGdXJ0aGVyIGludmVzdGlnYXRpb24gZm91bmQgdGhhdCB0aGVyZSBhcmUgMTU3IGNvdW50cmllcyBjb3ZlcmVkIGluIHRoZSBXb3JsZCBIYXBwaW5lc3MgSW5kZXggd2hpbHN0IGNvdW50cmllcyBjb3ZlcmVkIGluIHRoZSBIdW1hbiBGcmVlZG9tIEluZGV4IGFyZSAxNjIgaW4gdG90YWwuIFRoaXMgbWlzbWF0Y2ggaW4gbnVtYmVyIG9mIGNvdW50cnkgcmVzdWx0cyBpbiBtaXNzaW5nIHZhbHVlcyAoJ05BJykuIFRoZSByb3dzIHdpdGggbWlzc2luZyB2YWx1ZXMgaW4gdGhlIGhhcHBpbmVzcyB2YXJpYWJsZXMgYXJlIGFsc28gZGVsZXRlZCBieSB1c2luZyAqZmlsdGVyKCkqIGZ1bmN0aW9uLgoKICAqIEFmdGVyIGRlbGV0aW5nIHRoZSBtaXNzaW5nIHZhbHVlcywgdGhlcmUgYXJlIHN0aWxsIHRvdGFsIG1pc3NpbmcgdmFsdWVzIG9mIG1vcmUgdGhhbiA1JSBvZiB0aGUgdG90YWwgb2JzZXJ2YXRpb25zICgxMSBtaXNzaW5nIHZhbHVlcyBvdXQgb2YgMTM3IG9ic2VydmF0aW9ucyksIHdlIGNhbm5vdCBmdXJ0aGVyIGRlbGV0aW5nIHRoZSBtaXNzaW5nIHZhbHVlcy4gSW5zdGVhZCwgYW5vdGhlciBhcHByb2FjaCB0byBtaXNzaW5nIHZhbHVlcyBpcyBhcHBsaWVkLCBpLmUuIHRoZSBpbXB1dGF0aW9uIG1ldGhvZCB3aGVyZSB0aGUgbWlzc2luZyB2YWx1ZXMgYXJlIHJlcGxhY2VkIHdpdGggdGhlIG1lYW4sIG1lZGlhbiBvciBtb2RlIG9mIHRoZSB2YXJpYWJlIHdpdGggbWlzc2luZyB2YWx1ZXMuIApGcm9tIHRoZSBkYXRhIHN1bW1hcnksIGl0IGlzIGZvdW5kIHRoYXQgYWxsIHRoZSBtaXNzaW5nIHZhbHVlcyBhcmUgd2l0aGluIHZhcmlhYmxlICpwZl9hc3NvY2lhdGlvbiogd2hpY2ggd2lsbCBiZSByZXBsYWNlZCB3aXRoIHRoZSBtZWFuIHZhbHVlIG9mICpwZl9hc3NvY2lhdGlvbiouCgoKYGBge3J9CiNzY2FuIGZvciBtaXNzaW5nIHZhbHVlcwoKc3VtKGlzLm5hKGhmaV9oYXBweSkpCgoKI1NlbGVjdCBkYXRhIGZyb20geWVhciAyMDE2ICYgMjAxNwpoZmlfaGFwcHlfbm9taXNzIDwtIGhmaV9oYXBweSAlPiUgZmlsdGVyKHllYXI9PTIwMTYgfCB5ZWFyID09IDIwMTcpCnN1bShpcy5uYShoZmlfaGFwcHlfbm9taXNzKSkKCgojRGVsZXRlIGNvdW50cmllcyB0aGF0IGFyZSBub3QgY292ZXJlZCBpbiBXb3JsZCBIYXBwaW5lc3MgSW5kZXgKCmhmaV9oYXBweV9ub21pc3MxIDwtIGhmaV9oYXBweV9ub21pc3MgJT4lIGZpbHRlcighaXMubmEoSGFwcGluZXNzX1Njb3JlKSwKICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShIYXBwaW5lc3NfU2NvcmUpLAogICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKEdEUF9wZXJfQ2FwaXRhKSwKICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShGYW1pbHkpLAogICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKEhlYWx0aCksCiAgICAgICAgICAgICAgICAgICAgICAhaXMubmEoRnJlZWRvbSksCiAgICAgICAgICAgICAgICAgICAgICAhaXMubmEoVHJ1c3RfR292dF9Db3JydXB0aW9uKSwKICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShHZW5lcm9zaXR5KSwKICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShEeXN0b3BpYV9SZXNpZHVhbCkKICAgICAgICAgICAgICAgICAgICAgICkKCgoKc3VtKGlzLm5hKGhmaV9oYXBweV9ub21pc3MxKSkKCgpzdW1tYXJ5KGhmaV9oYXBweV9ub21pc3MxKQoKIAoKaGZpX2hhcHB5X2ltcCA8LSBoZmlfaGFwcHlfbm9taXNzMSAlPiUgbXV0YXRlX2F0KHZhcnMocGZfYXNzb2NpYXRpb24pLH5pZmVsc2UoaXMubmEoLngpLCBtZWFuKC54LCBuYS5ybSA9IFRSVUUpLCAueCkpCgoKCnN1bShpcy5uYShoZmlfaGFwcHlfaW1wKSkKCgoKCgoKCmBgYAoKCiMjCVNjYW4gSUkKClRoZSBwcmVzZW5jZSBvZiB0aGUgdHdvIG91dGxpZXJzIGNhbiBkcmFtYXRpY2FsbHkgYWZmZWN0ZWQgbWVhbiBhbmQgdmFyaWFuY2UgZXN0aW1hdGVzIG9mIG91ciBkYXRhLCB0aHVzIGNhbiBsZWFkIHRvIGluYWNjdXJhdGUgcmVzdWx0IG9yIHByZWRpY3Rpb24uICBUaGUgb3V0bGllcnMgbWF5IG9jY3VyIGFzIGEgcmVzdWx0IG9mIHJlY29yZGluZyBlcnJvciwgbGltaXRhdGlvbnMgb24gbWVhc3VyaW5nIHRlY2huaXF1ZXMsIHNrZXdlZCBwb3B1bGF0aW9uLCBzYW1wbGVzIGFyZSB0YWtlbiBmcm9tIG5vdCBlbnRpcmVseSB0aGUgc2FtZSBwb3B1bGF0aW9uLCBhbW9uZyBvdGhlcnMuIEhvd2V2ZXIsIHdlIGNhbiBub3QgYmUgc3VyZSB3aGF0IGNhdXNlZCB0aGUgb3V0bGllcnMgaW4gb3VyIGRhdGFzZXQgYXMgd2UgZXh0cmFjdGVkIHRoZSBkYXRhIGZyb20gYSBwdWJsaWNseSBhdmFpbGFibGUgZGF0YSBzb3VyY2UuCgoKV2UgdXNlIHRoZSBNYWhhbGFub2JpcyBkaXN0YW5jZSBjb21wdXRpbmcgaW4gdGhlIE1WTiBwYWNrYWdlIHRvIGRldGVjdCBhbnkgb3V0bGllcnMgaW4gb3VyIGRhdGEuIFRoZSBNYWhhbGFub2JpcyBkaXN0YW5jZSBkZXRlY3RzIGFuIG91dGxpZXIgYnkgbWVhc3VyaW5nIGhvdyBmYXIgZWFjaCBvYnNlcnZhdGlvbiBpcyB0byB0aGUgY2VudGVyIG9mIGpvaW50IGNoaS1zcXVhcmUgZGlzdHJpYnV0aW9uLgoKVGhlIHJlc3VsdCBvZiB0aGUgbXVsdGl2YXJpYXRlIG5vcm1hbGl0eSAoJ212bicpIHRlc3QgYXJlIGFzIGZvbGxvdzoKIAogICogdGhlIHJlc3VsdCBvZiBNYXJkaWEncyBtdWx0aXZhcmlhdGUgbm9ybWFsaXR5ICgnTVZOJykgdGVzdCwgd2hpY2ggbWVhc3VyZXMgdGhlIHNrZXduZXNzIGFuZCBrdXJ0b3NpcyBjb2VmZmljaWVudHMgYXMgd2VsbCBhcyB0aGVpciBjb3JyZXNwb25kaW5nIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSwgc2hvd3MgdGhhdCB0aGUgc2tld25lc3MgdGVzdCBwLXZhbHVlIHJlc3VsdCBpcyBsZXNzIHRoYW4gMC4wNSB3aGlsc3QgdGhlIGt1cnRvc2lzIHRlc3QgcmVzdWx0IGlzIGFib3ZlIDAuMDUuIE1hcmRpYSBNVk4gdGVzdCByZXF1aXJlcyB0aGUgcC12YWx1ZSByZXN1bHRzIG9mIGJvdGggdGVzdHMgbXVzdCBiZSBhdCBsZWFzdCAwLjA1IGZvciB0aGUgZGF0YSBmb2xsb3dzIGEgbXVsdGl2YXJpYXRlIG5vcm1hbGl0eSBkaXN0cmlidXRpb24gYXQgdGhlIDAuMDUgc2lnbmlmaWNhbmNlIGxldmVsLiBCYXNlZCBvbiB0aGUgcmVzdWx0IG9mIHRoZSBNYXJkaWEgdGVzdCwgb3VyIGRhdGEgZG9lcyBub3QgaGF2ZSBhIG11bHRpdmFyaWF0ZSBub3JtYWwgZGlzdHJpYnV0aW9uOwogIAogICogdGhlIFNoYXBpcm8tV2lsayB0ZXN0LCB3aGljaCBtZWFzdXJlIG5vcm1hbGl0eSBvbiBlYWNoIHZhcmlhYmxlLCBzaG93cyB0aGF0IG9ubHkgdHdvIHZhcmlhYmxlcyBpbiBvdXIgZGF0YSB0aGF0IGhhdmUgbm9ybWFsIGRpc3RyaWJ1dGlvbiwgaS5lLiBlZl9nb3Zlcm5tZW50ICh0aGUgc2l6ZSBvIGYgZ292ZXJubWVudCkgJiBEeXN0b3BpYV9SZXNpZHVhbCAodW5leHBsYWluZWQgY29tcG9uZW50cyBpbiBsZXZlbCBvZiBoYXBwaW5lc3Mgb2YgZWFjaCBjb3VudHJ5KS4KICAKICAqIHRoZSBNYWhhbGFub2JpcyBkaXN0YW5jZSB0ZXN0IHNob3dzIHRoYXQgdGhlIGRhdGEgaGFzIHR3byBvdXRsaWVycyB3aGljaCBsaWUgaW4gdGhlIGZpcnN0IGFuZCBzZWNvbmQgb2JzZXJ2YXRpb25zIG9mIHRoZSBkYXRhc2V0LgogIAogICogdGhlIE1WTiB0ZXN0IHJlc3VsdCBhbHNvIHBvaW50cyBvdXQgdGhhdCAidGhlIGNvdmFyaWFuY2UgbWF0cml4IG9mIHRoZSBkYXRhIGlzIHNpbmd1bGFyIiwgd2hpY2ggbWF5IGJlIGNhdXNlZCBieSBsaW5lYXIgaW50ZXJkZXBlbmRhbmNlcyBhbW9uZyB0aGUgdmFyaWFibGVzIG9mIHRoZSBkYXRhIGFuZCB0d28gb3IgbW9yZSB2YXJpYWJsZXMgc3VtIHVwIHRvIGEgY29uc3RhbnQgc3VjaCBhcyBIYXBwaW5lc3MgU2NvcmUgJiBEeXN0b3BpYSBSZXNpZHVhbC4gVGhlIHNpbmd1bGFyaXR5IGlzc3VlIGlzIG91dHNpZGUgb2Ygb3VyIHByb2plY3QncyBzY29wZSBhbmQgdGh1cywgd2lsbCBiZSBsZWZ0IHVudHJlYXRlZCBpbiB0aGlzIHByb2plY3QuCgoKCmBgYHtyfQojQ2hvb3NlIG9ubHkgbnVtZXJpY2FsIHZhcmlhYmxlcyAoZXhjbC4gJ3llYXInKQpoYXBweV9udW1zIDwtIGRwbHlyOjpzZWxlY3RfaWYoKGhmaV9oYXBweV9pbXBbICwgLTFdKSwgaXMubnVtZXJpYykgCmRpbShoYXBweV9udW1zKQpoZWFkKGhhcHB5X251bXMpCgojY2hlY2sgZm9yIG91dGxpZXJzIGFuZCBtdWx0aXZhcmlhdGUgbm9ybWFsaXR5CgpyZXN1bHQgPC0gbXZuKGhhcHB5X251bXMsIG11bHRpdmFyaWF0ZU91dGxpZXJNZXRob2QgPSAicXVhbiIsIHNob3dPdXRsaWVycyA9IFRSVUUpCnJlc3VsdAoKIyByZW1vdmUgb3V0bGllcnMgZnJvbSBkYXRhc2V0LgpyZXN1bHRfY2xlYW4gPC0gbXZuKGhhcHB5X251bXMsIG11bHRpdmFyaWF0ZU91dGxpZXJNZXRob2QgPSAicXVhbiIsIHNob3dPdXRsaWVycyA9IFRSVUUsIHNob3dOZXdEYXRhID0gVFJVRSkKZGltKHJlc3VsdF9jbGVhbiRuZXdEYXRhKQoKCgoKYGBgCgoKIyMJVHJhbnNmb3JtIApCYXNpY2FsbHksIHRoZXJlIGFyZSB0d28gbWV0aG9kcyB1c2VkIGluIGRlYWxpbmcgd2l0aCBvdXRsaWVycywgaS5lLiByZW1vdmluZyB0aGVtIGZyb20gZGF0YSBzZXQgYW5kIGRhdGEgdHJhbnNmb3JtYXRpb24uCgpBcyB0aGUgb3V0bGllcnMgaW4gb3VyIGRhdGEgY291bnQgb25seSAxJSBvZiB0aGUgc2FtcGxlLCBpdCBjYW4gYmUgZGVhbHQgYnkgc2ltcGx5IHJlbW92aW5nIHRoZW0gZnJvbSBvdXIgZGF0YXNldC4gVGhlIHJlc3VsdCAocmVzdWx0X2NsZWFuKSBzaG93cyBuZXcgZGF0YSB3aXRoIGEgZGltZW5zaW9uIG9mIDEzNSBvYnNlcnZhdGlvbiB3aXRoIDI3IHZhcmlhYmxlcy4KCldlIGFsc28gdHJpZWQgZGF0YSB0cmFuZm9ybWF0aW9uIG1ldGhvZCB0aGF0IGlzIGltbXVuZSB0byB0aGUgcHJlc2VuY2Ugb2Ygb3V0bGllcnMgdG8gc2VlIGhvdyAuIFdlIGNob3NlIG9uZSB2YXJpYWJsZSBmb3IgdGhpcyAtIHRoZSBIdW1hbiBGcmVlZG9tIEluZGV4IC0gYW5kIG9ic2VydmVkIHRoYXQgIGl0IGhhcyBhIGxlZnQtc2tld2VkIGRpc3RyaWJ1dGlvbi4gV2UgYXBwbGllZCBhIHNxdWFyZSB0cmFuc2Zvcm1hdGlvbiBvbiB0aGUgdmFyaWFibGUgYW5kIGZvdW5kIHRoYXQgYWZ0ZXIgdGhlIHRyYW5zZm9ybWF0aW9uIGl0cyBkaXN0cmlidXRpb24gYmVjb21lcyBtb3JlIHN5bW1ldHJpY2FsIG9yIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGFzIHNob3duIGluIHRoZSBoaXN0b2dyYW1zIGJlbG93LgoKCgpgYGB7cn0KI0RhdGEgdHJhbnNmb3JtYXRpb24gdXNpbmcgc3F1YXJlIHRyYW5zZm9ybWF0aW9uOgpmcmVlZG9tc3F1YXJlIDwtIChoZmlfaGFwcHlfaW1wJGhmX3Njb3JlKV4yCgojQmVmb3JlIHRyYW5zZm9ybWF0aW9uOgojaGlzdG9ncmFtCnFwbG90KGhmaV9oYXBweV9pbXAkaGZfc2NvcmUsCiAgICAgIGdlb20gPSAiaGlzdG9ncmFtIiwKICAgICAgYmluZHdpdGggPSAxLAogICAgICBtYWluID0gIkh1bWFuIEZyZWVkb20gSW5kZXggSGlzdG9ncmFtIiwKICAgICAgeGxhYiA9ICJIdW1hbiBGcmVlZG9tIFNjb3JlIiwKICAgICAgZmlsbCA9IEkoImxpZ2h0IGJsdWUiKSwKICAgICAgY29sID0gSSgidHVycXVvaXNlIiksCiAgICAgIGFscGhhPUkoMSkpCgojUVEgcGxvdApxcW5vcm0oaGZpX2hhcHB5X2ltcCRoZl9zY29yZSwgbWFpbiA9ICJIdW1hbiBGcmVlZG9tIEluZGV4IFNjb3JlIGJlZm9yZSBkYXRhIHRyYW5zZm9ybWF0aW9uIikKcXFsaW5lKGhmaV9oYXBweV9pbXAkaGZfc2NvcmUsIGNvbCA9ICJkZWVwcGluayIpCgoKI2FmdGVyIGRhdGEgdHJhbnNmb3JtYXRpb24KI2hpc3RvZ3JhbQpxcGxvdCAoZnJlZWRvbXNxdWFyZSwgZ2VvbSA9ICJoaXN0b2dyYW0iLAogICAgICBiaW5kd2l0aCA9IDEsCiAgICAgIG1haW4gPSAiTm9ybWFsaXNlZCBIdW1hbiBGcmVlZG9tIEluZGV4IEhpc3RvZ3JhbSIsCiAgICAgIHhsYWIgPSAiSHVtYW4gRnJlZWRvbSBTY29yZSIsCiAgICAgIGZpbGwgPSBJKCJwYWxlZ3JlZW4iKSwKICAgICAgY29sID0gSSgiZGVlcHNreWJsdWUiKSwKICAgICAgYWxwaGE9SSgxKSkKCgojUVEgcGxvdApxcW5vcm0oZnJlZWRvbXNxdWFyZSwgbWFpbiA9ICJOb3JtYWxpc2VkIEh1bWFuIEZyZWVkb20gSW5kZXggU2NvcmUiKQpxcWxpbmUoZnJlZWRvbXNxdWFyZSwgY29sID0gImxpbWUgZ3JlZW4iKQoKCmBgYAoKCgoKPGJyPgo8YnI+Cg==