Required packages

library(readr)
library(tidyr)
library(dplyr)
library(Hmisc)
library(outliers)
library(lubridate)
library(stringr)
library(deductive)
library(validate)
library(forecast)

Executive Summary

Main objective of this report is to apply the functions that we have learnt throughout Data Preprocessing course to a real world dataset in order to fulfill Assignment 3 requirements. A dataset was collected from world bank dataset which contained 5 .csv files, but two were enough for our investigation. Dataset contained character, numeric and factor variables which is a major requirement for the assignment. Both the selected datasets had to be cleaned priior to joining. Renaming, Gather and Spread functions were used to tidy up the datasets which were joined later. Joined dataset was amalyzed using the structure of the variables and necessary transformations were performed such as character -> numeric, character -> factor, charactor -> ordered factor in order to maintain a relaiable dataset to perform any statistical analysis. Dataset was a tidy dataset after all and created a new variable using mutate function. All the NAs in all the columns were identified and performed imputation for required variables by getting the mean value of the variable with the group by function. Possible outliers were detected using z-scores function for all the numeric variables and imputation was performed by replacing the mean value. Finally, log transformation was performed to make the distibution of the selected variable to be normal which was acutually right skewed when inpecting histogram.

Data

Poverty Dataset was extracted from World Bank website which contains different countries across globe.

Data Source: https://datacatalog.worldbank.org/dataset/poverty-and-equity-database

There were 5 .csv files but we Selected two of the datasets which we thought are more important perform data preprocessing.

  1. PovStatsCountry.csv contains 30 columns including Country_code, SHORT_NAME, ALPHA_CODE, Currency_Unit,Region, Income_Group. Dimensional Data with country code, short name of the country, cureency unit of the country, Region of the country in the world, Income group suggests whether it is Low, Medium or High income group can be understood from those columns. Data types of major columns in the dataset can be identified as follow.

Country_code -> Character SHORT_NAME -> Character ALPHA_CODE -> Character Currency_Unit -> Character Region -> Character (Supposed to be a factor) Income_Group -> Character (Supposed to be an ordered factor)

  1. PovStatsData.csv contains 48 columns including Country_code, Indicator_code, and year column from 1974 - 2018. Measure or Fact data with country code, country name, Indicator code as measure type and 1974 to 2017 measures can be identified from these columns.

country code -> Character country name -> Character Indicator code -> Character Year column from 1974 - 2018 -> Numeric

#Import Data from PovStatsCountry.csv
POV_COUNTRY <- read_csv("PovStatsCountry.csv")
Missing column names filled in: 'X31' [31]Parsed with column specification:
cols(
  .default = col_character(),
  `National accounts reference year` = col_integer(),
  `Latest industrial data` = col_integer(),
  `Latest trade data` = col_integer()
)
See spec(...) for full column specifications.
head(POV_COUNTRY)
#Selection of required variables from the dataset and Renaming variables
POV_COUNTRY_RENAME <- POV_COUNTRY %>% select(Country_code = "Country Code", SHORT_NAME = "Short Name" ,ALPHA_CODE = "2-alpha code" , Currency_Unit = "Currency Unit",Region = "Region" , Income_Group = "Income Group" )
head(POV_COUNTRY_RENAME)
#Import Data from PovStatsData.csv
POV_STATS_DATA <- read_csv("PovStatsData.csv")
Missing column names filled in: 'X49' [49]Parsed with column specification:
cols(
  .default = col_double(),
  `Country Name` = col_character(),
  `Country Code` = col_character(),
  `Indicator Name` = col_character(),
  `Indicator Code` = col_character(),
  X49 = col_character()
)
See spec(...) for full column specifications.
head(POV_STATS_DATA)
#Selection of required variables from the dataset
POV_STATS_SELECT <- POV_STATS_DATA %>% select (2, 4, 41:44)
head(POV_STATS_SELECT)
#Renaming of some of the selected variables
POV_STATS_RENAME <- POV_STATS_SELECT %>% rename(Country_code = 'Country Code', Indicator_code = 'Indicator Code' )
head(POV_STATS_RENAME)
#Filteration to select only observations based on the Income.
POV_STATS_FILTER = POV_STATS_RENAME %>% filter(Indicator_code %in% c("SI.POV.NOP1" , "SI.POV.LMIC.NO", "SI.POV.UMIC.NO" , "SP.POP.TOTL" ))
head(POV_STATS_FILTER)
#Implemented data tidy techniques like Gather, Spread to tidy up data
POV_STATS_GATHER <- POV_STATS_FILTER %>% gather ('2010','2011','2012','2013', key = year, value = 'value' )
head(POV_STATS_GATHER)
POV_STATS_SPREAD <- POV_STATS_GATHER %>% spread(key = Indicator_code, value = 'value') 
head(POV_STATS_SPREAD)
#Renaming of some of the selected variables
POV_SPREAD_RENAME <- POV_STATS_SPREAD %>% rename(POOR_199c_DAY=SI.POV.NOP1,POOR_320c_DAY = SI.POV.LMIC.NO, POOR_550c_DAY=SI.POV.UMIC.NO, POP_TOTL = SP.POP.TOTL )
head(POV_SPREAD_RENAME)
#Joining of both the data sets using Country code to create final data set.
POV_COUNTRY_STATS_JOIN <- POV_COUNTRY_RENAME %>% inner_join (POV_SPREAD_RENAME, by = 'Country_code')
head(POV_COUNTRY_STATS_JOIN)

Understand

#Description of the joined data set
str(POV_COUNTRY_STATS_JOIN)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   736 obs. of  11 variables:
 $ Country_code : chr  "AFG" "AFG" "AFG" "AFG" ...
 $ SHORT_NAME   : chr  "Afghanistan" "Afghanistan" "Afghanistan" "Afghanistan" ...
 $ ALPHA_CODE   : chr  "AF" "AF" "AF" "AF" ...
 $ Currency_Unit: chr  "Afghan afghani" "Afghan afghani" "Afghan afghani" "Afghan afghani" ...
 $ Region       : chr  "South Asia" "South Asia" "South Asia" "South Asia" ...
 $ Income_Group : chr  "Low income" "Low income" "Low income" "Low income" ...
 $ year         : chr  "2010" "2011" "2012" "2013" ...
 $ POOR_320c_DAY: num  NA NA NA NA NA NA NA NA NA NA ...
 $ POOR_199c_DAY: num  NA NA NA NA NA NA NA NA NA NA ...
 $ POOR_550c_DAY: num  NA NA NA NA NA NA NA NA NA NA ...
 $ POP_TOTL     : num  28803167 29708599 30696958 31731688 23369131 ...
#Converting year to numeric
POV_COUNTRY_STATS_JOIN$year = as.numeric(POV_COUNTRY_STATS_JOIN$year)
#Converting Region, Income Group to factor
POV_COUNTRY_STATS_JOIN$Region = as.factor(POV_COUNTRY_STATS_JOIN$Region)
POV_COUNTRY_STATS_JOIN$Income_Group = as.factor(POV_COUNTRY_STATS_JOIN$Income_Group)
#Converting Income Group factor variable to ordered factor variable
POV_COUNTRY_STATS_JOIN$Income_Group<- factor(POV_COUNTRY_STATS_JOIN$Income_Group,levels=c("High income","Upper middle income","Lower middle income","Low income"),labels=c("High income","Upper middle income","Lower middle income","Low income"),ordered=TRUE)
# The final structure of the dataset
str(POV_COUNTRY_STATS_JOIN) 
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   736 obs. of  11 variables:
 $ Country_code : chr  "AFG" "AFG" "AFG" "AFG" ...
 $ SHORT_NAME   : chr  "Afghanistan" "Afghanistan" "Afghanistan" "Afghanistan" ...
 $ ALPHA_CODE   : chr  "AF" "AF" "AF" "AF" ...
 $ Currency_Unit: chr  "Afghan afghani" "Afghan afghani" "Afghan afghani" "Afghan afghani" ...
 $ Region       : Factor w/ 7 levels "East Asia & Pacific",..: 6 6 6 6 7 7 7 7 2 2 ...
 $ Income_Group : Ord.factor w/ 4 levels "High income"<..: 4 4 4 4 3 3 3 3 2 2 ...
 $ year         : num  2010 2011 2012 2013 2010 ...
 $ POOR_320c_DAY: num  NA NA NA NA NA NA NA NA NA NA ...
 $ POOR_199c_DAY: num  NA NA NA NA NA NA NA NA NA NA ...
 $ POOR_550c_DAY: num  NA NA NA NA NA NA NA NA NA NA ...
 $ POP_TOTL     : num  28803167 29708599 30696958 31731688 23369131 ...

Tidy & Manipulate Data I

This part have been done in The first section of the assignment (Data). Therefore, the POV_COUNTRY_STATS_JOIN is in tidy format because of the following reasons:

1)Every variable in its own column.

2)Every observation in its own row.

3)Every value have its own cell for easy understanding and further analysis.

Tidy & Manipulate Data II

#Creation of a new column to represent country wise population earning more than 550 cents per day.
POV_STATS_MUTATE = POV_COUNTRY_STATS_JOIN %>% mutate( POP_ABOVE_550c_DAY = POP_TOTL - (POOR_550c_DAY)*1000000)
head(POV_STATS_MUTATE) 

Scan I

#Checking for  total values existing in each column in the above data set
colSums(is.na(POV_STATS_MUTATE))
      Country_code         SHORT_NAME         ALPHA_CODE      Currency_Unit             Region 
                 0                  0                  4                 60                 60 
      Income_Group               year      POOR_320c_DAY      POOR_199c_DAY      POOR_550c_DAY 
                60                  0                372                372                372 
          POP_TOTL POP_ABOVE_550c_DAY 
                 2                372 
#Checking for  inconsistencies in numeric columns
sum(is.nan(POV_STATS_MUTATE$year))
[1] 0
sum(is.nan(POV_STATS_MUTATE$POOR_199c_DAY))
[1] 0
sum(is.nan(POV_STATS_MUTATE$POOR_320c_DAY))
[1] 0
sum(is.nan(POV_STATS_MUTATE$POOR_550c_DAY))
[1] 0
sum(is.nan(POV_STATS_MUTATE$POP_TOTL))
[1] 0
#Convertion of NA values with mean of the measure group by year and Income  to get the most appropriate mean value of similar contries.
POV_STATS_IMPUTE <- POV_STATS_MUTATE %>% group_by(Income_Group, year) %>% mutate(POOR_199c_DAY =  ifelse(is.na(POOR_199c_DAY) ,mean(POOR_199c_DAY,na.rm = TRUE), POOR_199c_DAY ), POOR_320c_DAY =  ifelse(is.na(POOR_320c_DAY) ,mean(POOR_320c_DAY,na.rm = TRUE), POOR_320c_DAY ), POOR_550c_DAY =  ifelse(is.na(POOR_550c_DAY) ,mean(POOR_550c_DAY,na.rm = TRUE), POOR_550c_DAY ), POP_ABOVE_550c_DAY =  ifelse(is.na(POP_ABOVE_550c_DAY) ,mean(POP_ABOVE_550c_DAY,na.rm = TRUE), POP_ABOVE_550c_DAY )) 
# Convertion of NA values with mean of the measure group by year Country_code to get the most appropriate mean value of same country
POV_STATS_IMPUTE_FINAL <- POV_STATS_IMPUTE %>% group_by(Country_code) %>% mutate(POP_TOTL =  ifelse(is.na(POP_TOTL) ,mean(POP_TOTL,na.rm = TRUE), POP_TOTL ))
head(POV_STATS_IMPUTE_FINAL)
#Checking the NAs after Imputation
colSums(is.na(POV_STATS_IMPUTE_FINAL))
      Country_code         SHORT_NAME         ALPHA_CODE      Currency_Unit             Region 
                 0                  0                  4                 60                 60 
      Income_Group               year      POOR_320c_DAY      POOR_199c_DAY      POOR_550c_DAY 
                60                  0                  0                  0                  0 
          POP_TOTL POP_ABOVE_550c_DAY 
                 0                  0 

Scan II

#Finding the locations of outliers in the POOR_320c_DAY variable
POOR_320c_DAY_outliers <- POV_STATS_IMPUTE_FINAL$POOR_320c_DAY%>% scores(type = "z")
which( abs(POOR_320c_DAY_outliers) >3 )
 [1] 381 382 383 384 385 386 387 388 557 558 559 709 710 711 712
length (which( abs(POOR_320c_DAY_outliers) >3 ))
[1] 15
#Finding the locations of outliers in the POOR_199c_DAY variable
POOR_199c_DAY_outliers <- POV_STATS_IMPUTE_FINAL$POOR_199c_DAY%>% scores(type = "z")
which( abs(POOR_199c_DAY_outliers) >3 )
 [1] 281 282 283 284 381 382 383 384 385 386 387 388 557 589 590 591 592 709 710 711 712
length (which( abs(POOR_199c_DAY_outliers) >3 ))
[1] 21
#Finding the locations of outliers in the POOR_550c_DAY variable
POOR_550c_DAY_outliers <- POV_STATS_IMPUTE_FINAL$POOR_550c_DAY%>% scores(type = "z")
which( abs(POOR_550c_DAY_outliers) >3 )
 [1] 381 382 383 384 385 386 387 388 709 710 711 712
length (which( abs(POOR_550c_DAY_outliers) >3 ))
[1] 12
#Finding the locations of outliers in the POP_TOTL variable
POP_TOTL_outliers <- POV_STATS_IMPUTE_FINAL$POP_TOTL%>% scores(type = "z")
which( abs(POP_TOTL_outliers) >3 )
 [1] 384 385 386 387 388 429 430 431 432 709 710 711 712
length (which( abs(POP_TOTL_outliers) >3 ))
[1] 13
#Finding the locations of outliers in the POP_ABOVE_550c_DAY  variable
POP_ABOVE_550c_DAY_outliers <- POV_STATS_IMPUTE_FINAL$POP_ABOVE_550c_DAY%>% scores(type = "z")
which( abs(POP_ABOVE_550c_DAY_outliers) >3 )
 [1] 170 171 172 385 386 387 388 681 682 683 684 709 710 711 712
length (which( abs(POP_ABOVE_550c_DAY_outliers) >3 ))
[1] 15
#Imputing Outliers of numeric variables with mean assuming that outliers are a result of data entry/processing error.
POV_STATS_IMPUTE_FINAL$POOR_320c_DAY [which(abs(POOR_320c_DAY_outliers) >3 )] <- mean(POV_STATS_IMPUTE_FINAL$POOR_320c_DAY, na.rm = TRUE)
POOR_320c_DAY_outliers_imputed <- POV_STATS_IMPUTE_FINAL$POOR_320c_DAY%>% scores(type = "z")
length (which( abs(POOR_320c_DAY_outliers_imputed) >3 ))
[1] 23
#Imputing Outliers of numeric variables with mean assuming that outliers are a result of data entry/processing error.
POV_STATS_IMPUTE_FINAL$POOR_199c_DAY [which(abs(POOR_199c_DAY_outliers) >3 )] <- mean(POV_STATS_IMPUTE_FINAL$POOR_199c_DAY, na.rm = TRUE)
POOR_199c_DAY_outliers_imputed <- POV_STATS_IMPUTE_FINAL$POOR_199c_DAY%>% scores(type = "z")
length (which( abs(POOR_199c_DAY_outliers_imputed) >3 ))
[1] 24
#Imputing Outliers of numeric variables with mean assuming that outliers are a result of data entry/processing error.
POV_STATS_IMPUTE_FINAL$POOR_550c_DAY [which(abs(POOR_550c_DAY_outliers) >3 )] <- mean(POV_STATS_IMPUTE_FINAL$POOR_550c_DAY, na.rm = TRUE)
POOR_550c_DAY_outliers_imputed <- POV_STATS_IMPUTE_FINAL$POOR_550c_DAY%>% scores(type = "z")
length (which( abs(POOR_550c_DAY_outliers_imputed) >3 ))
[1] 26
#Imputing Outliers of numeric variables with mean assuming that outliers are a result of data entry/processing error.
POV_STATS_IMPUTE_FINAL$POP_TOTL [which(abs(POP_TOTL_outliers) >3 )] <- mean(POV_STATS_IMPUTE_FINAL$POP_TOTL, na.rm = TRUE)
POP_TOTL_outliers_imputed <- POV_STATS_IMPUTE_FINAL$POP_TOTL%>% scores(type = "z")
length (which( abs(POP_TOTL_outliers_imputed) >3 ))
[1] 26
#Imputing Outliers of numeric variables with mean assuming that outliers are a result of data entry/processing error.
POV_STATS_IMPUTE_FINAL$POP_ABOVE_550c_DAY [which(abs(POP_ABOVE_550c_DAY_outliers) >3 )] <- mean(POV_STATS_IMPUTE_FINAL$POP_ABOVE_550c_DAY, na.rm = TRUE)
POP_ABOVE_550c_DAY_outliers_imputed <- POV_STATS_IMPUTE_FINAL$POP_ABOVE_550c_DAY %>% scores(type = "z")
length (which( abs(POP_ABOVE_550c_DAY_outliers_imputed) >3 ))
[1] 20

Transform

#Displaying histogram of 'total population' coulumn
hist(POV_STATS_IMPUTE_FINAL$POP_TOTL, main = "Histogram of POOR_320c_DAY")

#Application of log transformation for 'total population' coulumn
log_total_population <- log10(POV_STATS_IMPUTE_FINAL$POP_TOTL)
hist(log_total_population)



LS0tDQp0aXRsZTogIk1BVEgyMzQ5IFNlbWVzdGVyIDIsIDIwMTgiDQphdXRob3I6ICJIZXdheWFsYWdlIFZpc2h2YSBMYWhpcnUgS2FudGhhIEFiZXlyYXRobmUgKFMzNzM1MTk1KSwgVmlzaHdhbmFkaGFtIEtvZHVrdWxhIChTMzc0OTg1NSksIEtvZGl0aHV3YWtrdSBBcmFjaGNoaWdlIElyZXNoIFVkYXJhIEthdXNoYWx5YSAoUzM3MDQ3NjkpICIgDQpzdWJ0aXRsZTogQXNzaWdubWVudCAzDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCi0tLQ0KDQojIyBSZXF1aXJlZCBwYWNrYWdlcyANCg0KYGBge3J9DQoNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoSG1pc2MpDQpsaWJyYXJ5KG91dGxpZXJzKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KGRlZHVjdGl2ZSkNCmxpYnJhcnkodmFsaWRhdGUpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KYGBgDQoNCg0KIyMgRXhlY3V0aXZlIFN1bW1hcnkgDQoNCk1haW4gb2JqZWN0aXZlIG9mIHRoaXMgcmVwb3J0IGlzIHRvIGFwcGx5IHRoZSBmdW5jdGlvbnMgdGhhdCB3ZSBoYXZlIGxlYXJudCB0aHJvdWdob3V0IERhdGEgUHJlcHJvY2Vzc2luZyBjb3Vyc2UgdG8gYSByZWFsIHdvcmxkIGRhdGFzZXQgaW4gb3JkZXIgdG8gZnVsZmlsbCBBc3NpZ25tZW50IDMgcmVxdWlyZW1lbnRzLiBBIGRhdGFzZXQgd2FzIGNvbGxlY3RlZCBmcm9tIHdvcmxkIGJhbmsgZGF0YXNldCB3aGljaCBjb250YWluZWQgNSAuY3N2IGZpbGVzLCBidXQgdHdvIHdlcmUgZW5vdWdoIGZvciBvdXIgaW52ZXN0aWdhdGlvbi4gRGF0YXNldCBjb250YWluZWQgY2hhcmFjdGVyLCBudW1lcmljIGFuZCBmYWN0b3IgdmFyaWFibGVzIHdoaWNoIGlzIGEgbWFqb3IgcmVxdWlyZW1lbnQgZm9yIHRoZSBhc3NpZ25tZW50LiBCb3RoIHRoZSBzZWxlY3RlZCBkYXRhc2V0cyBoYWQgdG8gYmUgY2xlYW5lZCBwcmlpb3IgdG8gam9pbmluZy4gUmVuYW1pbmcsIEdhdGhlciBhbmQgU3ByZWFkIGZ1bmN0aW9ucyB3ZXJlIHVzZWQgdG8gdGlkeSB1cCB0aGUgZGF0YXNldHMgd2hpY2ggd2VyZSBqb2luZWQgbGF0ZXIuIEpvaW5lZCBkYXRhc2V0IHdhcyBhbWFseXplZCB1c2luZyB0aGUgc3RydWN0dXJlIG9mIHRoZSB2YXJpYWJsZXMgYW5kIG5lY2Vzc2FyeSB0cmFuc2Zvcm1hdGlvbnMgd2VyZSBwZXJmb3JtZWQgc3VjaCBhcyBjaGFyYWN0ZXIgLT4gbnVtZXJpYywgY2hhcmFjdGVyIC0+IGZhY3RvciwgY2hhcmFjdG9yIC0+IG9yZGVyZWQgZmFjdG9yIGluIG9yZGVyIHRvIG1haW50YWluIGEgcmVsYWlhYmxlIGRhdGFzZXQgdG8gcGVyZm9ybSBhbnkgc3RhdGlzdGljYWwgYW5hbHlzaXMuIERhdGFzZXQgd2FzIGEgdGlkeSBkYXRhc2V0IGFmdGVyIGFsbCBhbmQgY3JlYXRlZCBhIG5ldyB2YXJpYWJsZSB1c2luZyBtdXRhdGUgZnVuY3Rpb24uIEFsbCB0aGUgTkFzIGluIGFsbCB0aGUgY29sdW1ucyB3ZXJlIGlkZW50aWZpZWQgYW5kIHBlcmZvcm1lZCBpbXB1dGF0aW9uIGZvciByZXF1aXJlZCB2YXJpYWJsZXMgYnkgZ2V0dGluZyB0aGUgbWVhbiB2YWx1ZSBvZiB0aGUgdmFyaWFibGUgd2l0aCB0aGUgZ3JvdXAgYnkgZnVuY3Rpb24uIFBvc3NpYmxlIG91dGxpZXJzIHdlcmUgZGV0ZWN0ZWQgdXNpbmcgei1zY29yZXMgZnVuY3Rpb24gZm9yIGFsbCB0aGUgbnVtZXJpYyB2YXJpYWJsZXMgYW5kIGltcHV0YXRpb24gd2FzIHBlcmZvcm1lZCBieSByZXBsYWNpbmcgdGhlIG1lYW4gdmFsdWUuIEZpbmFsbHksIGxvZyB0cmFuc2Zvcm1hdGlvbiB3YXMgcGVyZm9ybWVkIHRvIG1ha2UgdGhlIGRpc3RpYnV0aW9uIG9mIHRoZSBzZWxlY3RlZCB2YXJpYWJsZSB0byBiZSBub3JtYWwgd2hpY2ggd2FzIGFjdXR1YWxseSByaWdodCBza2V3ZWQgd2hlbiBpbnBlY3RpbmcgaGlzdG9ncmFtLg0KDQoNCg0KIyMgRGF0YSANCg0KDQpQb3ZlcnR5IERhdGFzZXQgd2FzIGV4dHJhY3RlZCBmcm9tIFdvcmxkIEJhbmsgd2Vic2l0ZSB3aGljaCBjb250YWlucyBkaWZmZXJlbnQgY291bnRyaWVzIGFjcm9zcyBnbG9iZS4NCg0KRGF0YSBTb3VyY2U6IGh0dHBzOi8vZGF0YWNhdGFsb2cud29ybGRiYW5rLm9yZy9kYXRhc2V0L3BvdmVydHktYW5kLWVxdWl0eS1kYXRhYmFzZQ0KDQpUaGVyZSB3ZXJlIDUgLmNzdiBmaWxlcyBidXQgd2UgU2VsZWN0ZWQgdHdvIG9mIHRoZSBkYXRhc2V0cyB3aGljaCB3ZSB0aG91Z2h0IGFyZSBtb3JlIGltcG9ydGFudCBwZXJmb3JtIGRhdGEgcHJlcHJvY2Vzc2luZy4NCg0KICAxKSBQb3ZTdGF0c0NvdW50cnkuY3N2IGNvbnRhaW5zIDMwIGNvbHVtbnMgaW5jbHVkaW5nIENvdW50cnlfY29kZSwgU0hPUlRfTkFNRSwgQUxQSEFfQ09ERSwgQ3VycmVuY3lfVW5pdCxSZWdpb24sIEluY29tZV9Hcm91cC4gRGltZW5zaW9uYWwgRGF0YSB3aXRoIGNvdW50cnkgY29kZSwgc2hvcnQgbmFtZSBvZiB0aGUgY291bnRyeSwgY3VyZWVuY3kgdW5pdCBvZiB0aGUgY291bnRyeSwgIFJlZ2lvbiBvZiB0aGUgY291bnRyeSBpbiB0aGUgd29ybGQsIEluY29tZSBncm91cCBzdWdnZXN0cyB3aGV0aGVyIGl0IGlzIExvdywgTWVkaXVtIG9yIEhpZ2ggaW5jb21lIGdyb3VwIGNhbiBiZSB1bmRlcnN0b29kIGZyb20gdGhvc2UgY29sdW1ucy4gRGF0YSB0eXBlcyBvZiBtYWpvciBjb2x1bW5zIGluIHRoZSBkYXRhc2V0IGNhbiBiZSBpZGVudGlmaWVkIGFzIGZvbGxvdy4NCiAgDQogIENvdW50cnlfY29kZSAtPiBDaGFyYWN0ZXINCiAgU0hPUlRfTkFNRSAgLT4gQ2hhcmFjdGVyDQogIEFMUEhBX0NPREUgIC0+IENoYXJhY3Rlcg0KICBDdXJyZW5jeV9Vbml0ICAtPiBDaGFyYWN0ZXINCiAgUmVnaW9uICAtPiBDaGFyYWN0ZXIgKFN1cHBvc2VkIHRvIGJlIGEgZmFjdG9yKQ0KICBJbmNvbWVfR3JvdXAgIC0+IENoYXJhY3RlciAoU3VwcG9zZWQgdG8gYmUgYW4gb3JkZXJlZCBmYWN0b3IpDQogIA0KICAyKSBQb3ZTdGF0c0RhdGEuY3N2IGNvbnRhaW5zIDQ4IGNvbHVtbnMgaW5jbHVkaW5nIENvdW50cnlfY29kZSwgSW5kaWNhdG9yX2NvZGUsIGFuZCB5ZWFyIGNvbHVtbiBmcm9tIDE5NzQgLSAyMDE4LiBNZWFzdXJlIG9yIEZhY3QgZGF0YSB3aXRoIGNvdW50cnkgY29kZSwgY291bnRyeSBuYW1lLCBJbmRpY2F0b3IgY29kZSBhcyBtZWFzdXJlIHR5cGUgYW5kIDE5NzQgdG8gMjAxNyBtZWFzdXJlcyBjYW4gYmUgaWRlbnRpZmllZCBmcm9tIHRoZXNlIGNvbHVtbnMuDQogIA0KICBjb3VudHJ5IGNvZGUgLT4gQ2hhcmFjdGVyDQogIGNvdW50cnkgbmFtZSAtPiBDaGFyYWN0ZXINCiAgSW5kaWNhdG9yIGNvZGUgLT4gQ2hhcmFjdGVyDQogIFllYXIgY29sdW1uIGZyb20gMTk3NCAtIDIwMTggLT4gTnVtZXJpYw0KDQoNCmBgYHtyfQ0KDQojSW1wb3J0IERhdGEgZnJvbSBQb3ZTdGF0c0NvdW50cnkuY3N2DQpQT1ZfQ09VTlRSWSA8LSByZWFkX2NzdigiUG92U3RhdHNDb3VudHJ5LmNzdiIpDQpoZWFkKFBPVl9DT1VOVFJZKQ0KDQojU2VsZWN0aW9uIG9mIHJlcXVpcmVkIHZhcmlhYmxlcyBmcm9tIHRoZSBkYXRhc2V0IGFuZCBSZW5hbWluZyB2YXJpYWJsZXMNClBPVl9DT1VOVFJZX1JFTkFNRSA8LSBQT1ZfQ09VTlRSWSAlPiUgc2VsZWN0KENvdW50cnlfY29kZSA9ICJDb3VudHJ5IENvZGUiLCBTSE9SVF9OQU1FID0gIlNob3J0IE5hbWUiICxBTFBIQV9DT0RFID0gIjItYWxwaGEgY29kZSIgLCBDdXJyZW5jeV9Vbml0ID0gIkN1cnJlbmN5IFVuaXQiLFJlZ2lvbiA9ICJSZWdpb24iICwgSW5jb21lX0dyb3VwID0gIkluY29tZSBHcm91cCIgKQ0KaGVhZChQT1ZfQ09VTlRSWV9SRU5BTUUpDQoNCiNJbXBvcnQgRGF0YSBmcm9tIFBvdlN0YXRzRGF0YS5jc3YNClBPVl9TVEFUU19EQVRBIDwtIHJlYWRfY3N2KCJQb3ZTdGF0c0RhdGEuY3N2IikNCmhlYWQoUE9WX1NUQVRTX0RBVEEpDQoNCiNTZWxlY3Rpb24gb2YgcmVxdWlyZWQgdmFyaWFibGVzIGZyb20gdGhlIGRhdGFzZXQNClBPVl9TVEFUU19TRUxFQ1QgPC0gUE9WX1NUQVRTX0RBVEEgJT4lIHNlbGVjdCAoMiwgNCwgNDE6NDQpDQpoZWFkKFBPVl9TVEFUU19TRUxFQ1QpDQoNCiNSZW5hbWluZyBvZiBzb21lIG9mIHRoZSBzZWxlY3RlZCB2YXJpYWJsZXMNClBPVl9TVEFUU19SRU5BTUUgPC0gUE9WX1NUQVRTX1NFTEVDVCAlPiUgcmVuYW1lKENvdW50cnlfY29kZSA9ICdDb3VudHJ5IENvZGUnLCBJbmRpY2F0b3JfY29kZSA9ICdJbmRpY2F0b3IgQ29kZScgKQ0KaGVhZChQT1ZfU1RBVFNfUkVOQU1FKQ0KDQojRmlsdGVyYXRpb24gdG8gc2VsZWN0IG9ubHkgb2JzZXJ2YXRpb25zIGJhc2VkIG9uIHRoZSBJbmNvbWUuDQpQT1ZfU1RBVFNfRklMVEVSID0gUE9WX1NUQVRTX1JFTkFNRSAlPiUgZmlsdGVyKEluZGljYXRvcl9jb2RlICVpbiUgYygiU0kuUE9WLk5PUDEiICwgIlNJLlBPVi5MTUlDLk5PIiwgIlNJLlBPVi5VTUlDLk5PIiAsICJTUC5QT1AuVE9UTCIgKSkNCmhlYWQoUE9WX1NUQVRTX0ZJTFRFUikNCg0KI0ltcGxlbWVudGVkIGRhdGEgdGlkeSB0ZWNobmlxdWVzIGxpa2UgR2F0aGVyLCBTcHJlYWQgdG8gdGlkeSB1cCBkYXRhDQpQT1ZfU1RBVFNfR0FUSEVSIDwtIFBPVl9TVEFUU19GSUxURVIgJT4lIGdhdGhlciAoJzIwMTAnLCcyMDExJywnMjAxMicsJzIwMTMnLCBrZXkgPSB5ZWFyLCB2YWx1ZSA9ICd2YWx1ZScgKQ0KaGVhZChQT1ZfU1RBVFNfR0FUSEVSKQ0KDQpQT1ZfU1RBVFNfU1BSRUFEIDwtIFBPVl9TVEFUU19HQVRIRVIgJT4lIHNwcmVhZChrZXkgPSBJbmRpY2F0b3JfY29kZSwgdmFsdWUgPSAndmFsdWUnKSANCmhlYWQoUE9WX1NUQVRTX1NQUkVBRCkNCg0KI1JlbmFtaW5nIG9mIHNvbWUgb2YgdGhlIHNlbGVjdGVkIHZhcmlhYmxlcw0KUE9WX1NQUkVBRF9SRU5BTUUgPC0gUE9WX1NUQVRTX1NQUkVBRCAlPiUgcmVuYW1lKFBPT1JfMTk5Y19EQVk9U0kuUE9WLk5PUDEsUE9PUl8zMjBjX0RBWSA9IFNJLlBPVi5MTUlDLk5PLCBQT09SXzU1MGNfREFZPVNJLlBPVi5VTUlDLk5PLCBQT1BfVE9UTCA9IFNQLlBPUC5UT1RMICkNCmhlYWQoUE9WX1NQUkVBRF9SRU5BTUUpDQoNCiNKb2luaW5nIG9mIGJvdGggdGhlIGRhdGEgc2V0cyB1c2luZyBDb3VudHJ5IGNvZGUgdG8gY3JlYXRlIGZpbmFsIGRhdGEgc2V0Lg0KUE9WX0NPVU5UUllfU1RBVFNfSk9JTiA8LSBQT1ZfQ09VTlRSWV9SRU5BTUUgJT4lIGlubmVyX2pvaW4gKFBPVl9TUFJFQURfUkVOQU1FLCBieSA9ICdDb3VudHJ5X2NvZGUnKQ0KaGVhZChQT1ZfQ09VTlRSWV9TVEFUU19KT0lOKQ0KDQpgYGANCiogQm90aCBQb3ZTdGF0c0NvdW50cnkuY3N2IGFuZCBQb3ZTdGF0c0RhdGEuY3N2IGRhdGFzZXRzIHdlcmUgaW1wb3J0ZWQgYW5kIG9ubHkgc2VsZWN0ZWQgY29sdW1ucyB3aGljaCBhcmUgcmVxdWlyZWQgICB0byBwZXJmb3JtIGFuIGFuYWx5c2lzLg0KDQoqIFNvbWUgb2YgdGhlIHNlbGVjdGVkIGNvbHVtbnMgZnJvbSBib3RoIHRoZSBkYXRhc2V0cyB3ZXJlIHJlbmFtZWQgZm9yIGJldHRlciBpZGVudGlmaWNhdGlvbi4NCg0KKiBGaWx0ZXJhdGlvbiB3YXMgcGVyZm9ybWVkIHRvIHNlbGVjdCB2YWx1ZXMgb2YgJ0luZGljYXRvciBDb2RlJyB0byBiZSBpbmNsdWRlZCBhcyBjb2x1bW5zLg0KDQoqIEdhdGhlciwgU3ByZWFkIGZ1bmN0aW9ucyB3ZXJlIHVzZWQgdG8gdGlkeSB1cCB0aGUgdW50aWR5IGRhdGEgaW4gYm90aCB0aGUgZGF0YXNldHMuDQoNCiogUmVuYW1pbmcgb2Ygc29tZSBvZiB0aGUgY29sdW1ucyB3YXMgcGVyZm9ybWVkIGFmdGVyIHR5ZGluZyB1cCBkYWF0YXNldHMuDQoNCiogRmluYWxseSBib3RoIHRoZSBkYXRhc2V0cyB3ZXJlIGpvaW5lZCB1c2luZyBpbm5lciBqb2luLg0KDQoNCiMjIFVuZGVyc3RhbmQgDQoNCmBgYHtyfQ0KDQojRGVzY3JpcHRpb24gb2YgdGhlIGpvaW5lZCBkYXRhIHNldA0Kc3RyKFBPVl9DT1VOVFJZX1NUQVRTX0pPSU4pDQoNCiNDb252ZXJ0aW5nIHllYXIgdG8gbnVtZXJpYw0KUE9WX0NPVU5UUllfU1RBVFNfSk9JTiR5ZWFyID0gYXMubnVtZXJpYyhQT1ZfQ09VTlRSWV9TVEFUU19KT0lOJHllYXIpDQoNCiNDb252ZXJ0aW5nIFJlZ2lvbiwgSW5jb21lIEdyb3VwIHRvIGZhY3Rvcg0KUE9WX0NPVU5UUllfU1RBVFNfSk9JTiRSZWdpb24gPSBhcy5mYWN0b3IoUE9WX0NPVU5UUllfU1RBVFNfSk9JTiRSZWdpb24pDQpQT1ZfQ09VTlRSWV9TVEFUU19KT0lOJEluY29tZV9Hcm91cCA9IGFzLmZhY3RvcihQT1ZfQ09VTlRSWV9TVEFUU19KT0lOJEluY29tZV9Hcm91cCkNCg0KI0NvbnZlcnRpbmcgSW5jb21lIEdyb3VwIGZhY3RvciB2YXJpYWJsZSB0byBvcmRlcmVkIGZhY3RvciB2YXJpYWJsZQ0KUE9WX0NPVU5UUllfU1RBVFNfSk9JTiRJbmNvbWVfR3JvdXA8LSBmYWN0b3IoUE9WX0NPVU5UUllfU1RBVFNfSk9JTiRJbmNvbWVfR3JvdXAsbGV2ZWxzPWMoIkhpZ2ggaW5jb21lIiwiVXBwZXIgbWlkZGxlIGluY29tZSIsIkxvd2VyIG1pZGRsZSBpbmNvbWUiLCJMb3cgaW5jb21lIiksbGFiZWxzPWMoIkhpZ2ggaW5jb21lIiwiVXBwZXIgbWlkZGxlIGluY29tZSIsIkxvd2VyIG1pZGRsZSBpbmNvbWUiLCJMb3cgaW5jb21lIiksb3JkZXJlZD1UUlVFKQ0KDQojIFRoZSBmaW5hbCBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGFzZXQNCnN0cihQT1ZfQ09VTlRSWV9TVEFUU19KT0lOKSANCg0KYGBgDQoqIFN0cnVjdHVyZSBvZiB0aGUgam9pbmVkIGRhdGFzZXQgd2FzIHJldmlld2VkLg0KDQoqIFllYXIgY29sdW1uIHdhcyBjb252ZXJ0ZWQgdG8gYSBudW1lcmljIGNvbHVtbiB3aGljaCB3YXMgYSBjaGFyYWN0ZXIgY29sdW1uIGJlZm9yZS4NCg0KKiBSZWdpb24gY29sdW1uIGFuZCBJbmNvbWVfR3JvdXAgY29sdW1ucyB3ZXJlIGNvbnZlcnRlZCB0byBmYWN0b3IgdmFyaWFibGVzIHdoaWNoIHdlcmUgaW4gY2hhcmFjdGVyIGZvcm1hdC4NCg0KKiBBdCB0aGUgZW5kLCBJbmNvbWVfR3JvdXAgZmFjdG9yIHZhcmlhYmxlIHdhcyBjb252ZXJldGVkIHRvIGFuIG9yZGVyZWQgZmFjdG9yLiANCg0KIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJIA0KDQoNClRoaXMgcGFydCBoYXZlIGJlZW4gZG9uZSBpbiBUaGUgZmlyc3Qgc2VjdGlvbiBvZiB0aGUgYXNzaWdubWVudCAoRGF0YSkuIFRoZXJlZm9yZSwgdGhlIFBPVl9DT1VOVFJZX1NUQVRTX0pPSU4gaXMgaW4gdGlkeSBmb3JtYXQgYmVjYXVzZSBvZiB0aGUgZm9sbG93aW5nIHJlYXNvbnM6DQoNCjEpRXZlcnkgdmFyaWFibGUgaW4gaXRzIG93biBjb2x1bW4uDQoNCjIpRXZlcnkgb2JzZXJ2YXRpb24gaW4gaXRzIG93biByb3cuDQoNCjMpRXZlcnkgdmFsdWUgaGF2ZSBpdHMgb3duIGNlbGwgZm9yIGVhc3kgdW5kZXJzdGFuZGluZyBhbmQgZnVydGhlciBhbmFseXNpcy4NCg0KYGBge3J9DQoNCmBgYA0KDQojIwlUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIElJIA0KDQoNCmBgYHtyfQ0KI0NyZWF0aW9uIG9mIGEgbmV3IGNvbHVtbiB0byByZXByZXNlbnQgY291bnRyeSB3aXNlIHBvcHVsYXRpb24gZWFybmluZyBtb3JlIHRoYW4gNTUwIGNlbnRzIHBlciBkYXkuDQpQT1ZfU1RBVFNfTVVUQVRFID0gUE9WX0NPVU5UUllfU1RBVFNfSk9JTiAlPiUgbXV0YXRlKCBQT1BfQUJPVkVfNTUwY19EQVkgPSBQT1BfVE9UTCAtIChQT09SXzU1MGNfREFZKSoxMDAwMDAwKQ0KaGVhZChQT1ZfU1RBVFNfTVVUQVRFKSANCg0KYGBgDQoNCiogUE9PUl81NTBjX0RBWSByZXByZXNlbnRzIGN1bXVsYXRpdmUgc3VtIG9mIHBvcHVsYXRpb24gd2hvIGFyZSBlYXJuaW5nIGxlc3MgdGhhbiAgICBhcmUgZXF1YWwgdG8gNTUwIGNlbnRzIChpLmUuICAgICBUaGlzIHZhcmlhYmxlIGluY2x1ZGVkIHdobyBhcmUgZWFybmluZyAxOTljIHBlciBkYXkgICBhbmQgMzIwIGNlbnRzIHBlciBkYXkpIGluIG1pbGxpb25zLg0KDQoqIFdlIGNhbGN1bGF0ZWQgYSBuZXcgdmFyaWFibGUgdG8gaWRlbnRpZnkgd2hvIGFyZSBlYXJuaW5nIG1vcmUgdGhhbiA1NTAgY2VudHMgcGVyICAgZGF5IGJ5IHN1YnJhY3RpbmcgUE9PUl81NTBjX0RBWSAgIG11bHRpcGxpZWQgYnkgYSBtaWxsaW9uIGZyb20gdG90YWwgcG9wdWxhdGlvbi4NCg0KKiBVc2VkIG11dGF0ZSB0byBpbmNsdWRlIG5ldyB2YXJpYWJsZSAiUE9QX0FCT1ZFXzU1MGNfREFZIiINCg0KIyMJU2NhbiBJIA0KDQoNCmBgYHtyfQ0KDQojQ2hlY2tpbmcgZm9yICB0b3RhbCB2YWx1ZXMgZXhpc3RpbmcgaW4gZWFjaCBjb2x1bW4gaW4gdGhlIGFib3ZlIGRhdGEgc2V0DQpjb2xTdW1zKGlzLm5hKFBPVl9TVEFUU19NVVRBVEUpKQ0KDQojQ2hlY2tpbmcgZm9yICBpbmNvbnNpc3RlbmNpZXMgaW4gbnVtZXJpYyBjb2x1bW5zDQpzdW0oaXMubmFuKFBPVl9TVEFUU19NVVRBVEUkeWVhcikpDQpzdW0oaXMubmFuKFBPVl9TVEFUU19NVVRBVEUkUE9PUl8xOTljX0RBWSkpDQpzdW0oaXMubmFuKFBPVl9TVEFUU19NVVRBVEUkUE9PUl8zMjBjX0RBWSkpDQpzdW0oaXMubmFuKFBPVl9TVEFUU19NVVRBVEUkUE9PUl81NTBjX0RBWSkpDQpzdW0oaXMubmFuKFBPVl9TVEFUU19NVVRBVEUkUE9QX1RPVEwpKQ0KDQojQ29udmVydGlvbiBvZiBOQSB2YWx1ZXMgd2l0aCBtZWFuIG9mIHRoZSBtZWFzdXJlIGdyb3VwIGJ5IHllYXIgYW5kIEluY29tZSAgdG8gZ2V0IHRoZSBtb3N0IGFwcHJvcHJpYXRlIG1lYW4gdmFsdWUgb2Ygc2ltaWxhciBjb250cmllcy4NClBPVl9TVEFUU19JTVBVVEUgPC0gUE9WX1NUQVRTX01VVEFURSAlPiUgZ3JvdXBfYnkoSW5jb21lX0dyb3VwLCB5ZWFyKSAlPiUgbXV0YXRlKFBPT1JfMTk5Y19EQVkgPSAgaWZlbHNlKGlzLm5hKFBPT1JfMTk5Y19EQVkpICxtZWFuKFBPT1JfMTk5Y19EQVksbmEucm0gPSBUUlVFKSwgUE9PUl8xOTljX0RBWSApLCBQT09SXzMyMGNfREFZID0gIGlmZWxzZShpcy5uYShQT09SXzMyMGNfREFZKSAsbWVhbihQT09SXzMyMGNfREFZLG5hLnJtID0gVFJVRSksIFBPT1JfMzIwY19EQVkgKSwgUE9PUl81NTBjX0RBWSA9ICBpZmVsc2UoaXMubmEoUE9PUl81NTBjX0RBWSkgLG1lYW4oUE9PUl81NTBjX0RBWSxuYS5ybSA9IFRSVUUpLCBQT09SXzU1MGNfREFZICksIFBPUF9BQk9WRV81NTBjX0RBWSA9ICBpZmVsc2UoaXMubmEoUE9QX0FCT1ZFXzU1MGNfREFZKSAsbWVhbihQT1BfQUJPVkVfNTUwY19EQVksbmEucm0gPSBUUlVFKSwgUE9QX0FCT1ZFXzU1MGNfREFZICkpIA0KDQojIENvbnZlcnRpb24gb2YgTkEgdmFsdWVzIHdpdGggbWVhbiBvZiB0aGUgbWVhc3VyZSBncm91cCBieSB5ZWFyIENvdW50cnlfY29kZSB0byBnZXQgdGhlIG1vc3QgYXBwcm9wcmlhdGUgbWVhbiB2YWx1ZSBvZiBzYW1lIGNvdW50cnkNClBPVl9TVEFUU19JTVBVVEVfRklOQUwgPC0gUE9WX1NUQVRTX0lNUFVURSAlPiUgZ3JvdXBfYnkoQ291bnRyeV9jb2RlKSAlPiUgbXV0YXRlKFBPUF9UT1RMID0gIGlmZWxzZShpcy5uYShQT1BfVE9UTCkgLG1lYW4oUE9QX1RPVEwsbmEucm0gPSBUUlVFKSwgUE9QX1RPVEwgKSkNCmhlYWQoUE9WX1NUQVRTX0lNUFVURV9GSU5BTCkNCg0KI0NoZWNraW5nIHRoZSBOQXMgYWZ0ZXIgSW1wdXRhdGlvbg0KY29sU3Vtcyhpcy5uYShQT1ZfU1RBVFNfSU1QVVRFX0ZJTkFMKSkNCg0KYGBgDQogDQoqIFNjYW5uZWQgZGF0YSBzZXQgZm9yIE5BLCBpbmNvbnNpc3RlbmNpZXMgYW5kIGVycm9ycyB1c2luZyBpcy5uYSwgaXMubmFuIGZ1bmN0aW9ucy4NCg0KKiBJbXB1dGVkIG5hIHZhbHVlcyB3aXRoIG1lYW4gb2YgdmFyaWFibGUgZ3JvdXAgYnkgeWVhciwgSW5jb21lIEdyb3VwIGZvciBQT09SXzE5OWNfREFZLCBQT09SXzMyMGNfREFZLCBQT09SXzU1MGNfREFZLCBQT1BfQUJPVkVfNTUwY19EQVkgdmFyaWFibGVzLiAgICAgICAgIEJlY2F1c2UgaXQgaXMgYmV0dGVyIHRvIGdldCB2YWx1ZXMgYWNjb3JkaW5nIHRvIHRoZSB5ZWFyIGFuZCBJbmNvbWUgR3JvdXAgcmF0aGVyICAgdGhhbiBSZWdpb24gd2hpY2ggZG9lcyBub3QgbWFrZSBhbnkgc2Vuc2UgYW5kIG5vdCBhZGVxdWF0ZS4NCg0KKiBJbXB1dGVkIG5hIHZhbHVlcyB3aXRoIG1lYW4gb2YgdmFyaWFibGUgZ3JvdXAgYnkgQ291bnRyeV9jb2RlIGZvciBQT1BfVE9UTCB2YXJpYWJsZS4gQmVjYXVzZSBpbXB1dGluZyB2YWx1ZXMgd2l0aCBvdGhlciB2YXJpYWJsZXMgaXMgbm90IGdvaW5nIHRvIGJlIGFjY3VyYXRlLg0KDQoqIE5lZ2xlY3RlZCBpbXB1dGF0aW9uIG9mIG90aGVyIGNvbHVtbiB3aGljaCBhcmUgbm90IGhhdmluZyBhIHN0YXRpc3RpY2FsIGltcGFjdCBhY2NvcmRpbmcgdG8gdGhlIHNjZW5hcmlvLg0KDQojIwlTY2FuIElJDQoNCmBgYHtyfQ0KDQojRmluZGluZyB0aGUgbG9jYXRpb25zIG9mIG91dGxpZXJzIGluIHRoZSBQT09SXzMyMGNfREFZIHZhcmlhYmxlDQpQT09SXzMyMGNfREFZX291dGxpZXJzIDwtIFBPVl9TVEFUU19JTVBVVEVfRklOQUwkUE9PUl8zMjBjX0RBWSU+JSBzY29yZXModHlwZSA9ICJ6IikNCg0Kd2hpY2goIGFicyhQT09SXzMyMGNfREFZX291dGxpZXJzKSA+MyApDQoNCmxlbmd0aCAod2hpY2goIGFicyhQT09SXzMyMGNfREFZX291dGxpZXJzKSA+MyApKQ0KDQojRmluZGluZyB0aGUgbG9jYXRpb25zIG9mIG91dGxpZXJzIGluIHRoZSBQT09SXzE5OWNfREFZIHZhcmlhYmxlDQpQT09SXzE5OWNfREFZX291dGxpZXJzIDwtIFBPVl9TVEFUU19JTVBVVEVfRklOQUwkUE9PUl8xOTljX0RBWSU+JSBzY29yZXModHlwZSA9ICJ6IikNCg0Kd2hpY2goIGFicyhQT09SXzE5OWNfREFZX291dGxpZXJzKSA+MyApDQoNCmxlbmd0aCAod2hpY2goIGFicyhQT09SXzE5OWNfREFZX291dGxpZXJzKSA+MyApKQ0KDQojRmluZGluZyB0aGUgbG9jYXRpb25zIG9mIG91dGxpZXJzIGluIHRoZSBQT09SXzU1MGNfREFZIHZhcmlhYmxlDQpQT09SXzU1MGNfREFZX291dGxpZXJzIDwtIFBPVl9TVEFUU19JTVBVVEVfRklOQUwkUE9PUl81NTBjX0RBWSU+JSBzY29yZXModHlwZSA9ICJ6IikNCg0Kd2hpY2goIGFicyhQT09SXzU1MGNfREFZX291dGxpZXJzKSA+MyApDQoNCmxlbmd0aCAod2hpY2goIGFicyhQT09SXzU1MGNfREFZX291dGxpZXJzKSA+MyApKQ0KDQojRmluZGluZyB0aGUgbG9jYXRpb25zIG9mIG91dGxpZXJzIGluIHRoZSBQT1BfVE9UTCB2YXJpYWJsZQ0KUE9QX1RPVExfb3V0bGllcnMgPC0gUE9WX1NUQVRTX0lNUFVURV9GSU5BTCRQT1BfVE9UTCU+JSBzY29yZXModHlwZSA9ICJ6IikNCg0Kd2hpY2goIGFicyhQT1BfVE9UTF9vdXRsaWVycykgPjMgKQ0KDQpsZW5ndGggKHdoaWNoKCBhYnMoUE9QX1RPVExfb3V0bGllcnMpID4zICkpDQoNCiNGaW5kaW5nIHRoZSBsb2NhdGlvbnMgb2Ygb3V0bGllcnMgaW4gdGhlIFBPUF9BQk9WRV81NTBjX0RBWSAgdmFyaWFibGUNClBPUF9BQk9WRV81NTBjX0RBWV9vdXRsaWVycyA8LSBQT1ZfU1RBVFNfSU1QVVRFX0ZJTkFMJFBPUF9BQk9WRV81NTBjX0RBWSU+JSBzY29yZXModHlwZSA9ICJ6IikNCg0Kd2hpY2goIGFicyhQT1BfQUJPVkVfNTUwY19EQVlfb3V0bGllcnMpID4zICkNCg0KbGVuZ3RoICh3aGljaCggYWJzKFBPUF9BQk9WRV81NTBjX0RBWV9vdXRsaWVycykgPjMgKSkNCg0KDQojSW1wdXRpbmcgT3V0bGllcnMgb2YgbnVtZXJpYyB2YXJpYWJsZXMgd2l0aCBtZWFuIGFzc3VtaW5nIHRoYXQgb3V0bGllcnMgYXJlIGEgcmVzdWx0IG9mIGRhdGEgZW50cnkvcHJvY2Vzc2luZyBlcnJvci4NClBPVl9TVEFUU19JTVBVVEVfRklOQUwkUE9PUl8zMjBjX0RBWSBbd2hpY2goYWJzKFBPT1JfMzIwY19EQVlfb3V0bGllcnMpID4zICldIDwtIG1lYW4oUE9WX1NUQVRTX0lNUFVURV9GSU5BTCRQT09SXzMyMGNfREFZLCBuYS5ybSA9IFRSVUUpDQoNClBPT1JfMzIwY19EQVlfb3V0bGllcnNfaW1wdXRlZCA8LSBQT1ZfU1RBVFNfSU1QVVRFX0ZJTkFMJFBPT1JfMzIwY19EQVklPiUgc2NvcmVzKHR5cGUgPSAieiIpDQoNCmxlbmd0aCAod2hpY2goIGFicyhQT09SXzMyMGNfREFZX291dGxpZXJzX2ltcHV0ZWQpID4zICkpDQoNCiNJbXB1dGluZyBPdXRsaWVycyBvZiBudW1lcmljIHZhcmlhYmxlcyB3aXRoIG1lYW4gYXNzdW1pbmcgdGhhdCBvdXRsaWVycyBhcmUgYSByZXN1bHQgb2YgZGF0YSBlbnRyeS9wcm9jZXNzaW5nIGVycm9yLg0KUE9WX1NUQVRTX0lNUFVURV9GSU5BTCRQT09SXzE5OWNfREFZIFt3aGljaChhYnMoUE9PUl8xOTljX0RBWV9vdXRsaWVycykgPjMgKV0gPC0gbWVhbihQT1ZfU1RBVFNfSU1QVVRFX0ZJTkFMJFBPT1JfMTk5Y19EQVksIG5hLnJtID0gVFJVRSkNCg0KUE9PUl8xOTljX0RBWV9vdXRsaWVyc19pbXB1dGVkIDwtIFBPVl9TVEFUU19JTVBVVEVfRklOQUwkUE9PUl8xOTljX0RBWSU+JSBzY29yZXModHlwZSA9ICJ6IikNCg0KbGVuZ3RoICh3aGljaCggYWJzKFBPT1JfMTk5Y19EQVlfb3V0bGllcnNfaW1wdXRlZCkgPjMgKSkNCg0KI0ltcHV0aW5nIE91dGxpZXJzIG9mIG51bWVyaWMgdmFyaWFibGVzIHdpdGggbWVhbiBhc3N1bWluZyB0aGF0IG91dGxpZXJzIGFyZSBhIHJlc3VsdCBvZiBkYXRhIGVudHJ5L3Byb2Nlc3NpbmcgZXJyb3IuDQpQT1ZfU1RBVFNfSU1QVVRFX0ZJTkFMJFBPT1JfNTUwY19EQVkgW3doaWNoKGFicyhQT09SXzU1MGNfREFZX291dGxpZXJzKSA+MyApXSA8LSBtZWFuKFBPVl9TVEFUU19JTVBVVEVfRklOQUwkUE9PUl81NTBjX0RBWSwgbmEucm0gPSBUUlVFKQ0KDQpQT09SXzU1MGNfREFZX291dGxpZXJzX2ltcHV0ZWQgPC0gUE9WX1NUQVRTX0lNUFVURV9GSU5BTCRQT09SXzU1MGNfREFZJT4lIHNjb3Jlcyh0eXBlID0gInoiKQ0KDQpsZW5ndGggKHdoaWNoKCBhYnMoUE9PUl81NTBjX0RBWV9vdXRsaWVyc19pbXB1dGVkKSA+MyApKQ0KDQojSW1wdXRpbmcgT3V0bGllcnMgb2YgbnVtZXJpYyB2YXJpYWJsZXMgd2l0aCBtZWFuIGFzc3VtaW5nIHRoYXQgb3V0bGllcnMgYXJlIGEgcmVzdWx0IG9mIGRhdGEgZW50cnkvcHJvY2Vzc2luZyBlcnJvci4NClBPVl9TVEFUU19JTVBVVEVfRklOQUwkUE9QX1RPVEwgW3doaWNoKGFicyhQT1BfVE9UTF9vdXRsaWVycykgPjMgKV0gPC0gbWVhbihQT1ZfU1RBVFNfSU1QVVRFX0ZJTkFMJFBPUF9UT1RMLCBuYS5ybSA9IFRSVUUpDQoNClBPUF9UT1RMX291dGxpZXJzX2ltcHV0ZWQgPC0gUE9WX1NUQVRTX0lNUFVURV9GSU5BTCRQT1BfVE9UTCU+JSBzY29yZXModHlwZSA9ICJ6IikNCg0KbGVuZ3RoICh3aGljaCggYWJzKFBPUF9UT1RMX291dGxpZXJzX2ltcHV0ZWQpID4zICkpDQoNCiNJbXB1dGluZyBPdXRsaWVycyBvZiBudW1lcmljIHZhcmlhYmxlcyB3aXRoIG1lYW4gYXNzdW1pbmcgdGhhdCBvdXRsaWVycyBhcmUgYSByZXN1bHQgb2YgZGF0YSBlbnRyeS9wcm9jZXNzaW5nIGVycm9yLg0KUE9WX1NUQVRTX0lNUFVURV9GSU5BTCRQT1BfQUJPVkVfNTUwY19EQVkgW3doaWNoKGFicyhQT1BfQUJPVkVfNTUwY19EQVlfb3V0bGllcnMpID4zICldIDwtIG1lYW4oUE9WX1NUQVRTX0lNUFVURV9GSU5BTCRQT1BfQUJPVkVfNTUwY19EQVksIG5hLnJtID0gVFJVRSkNCg0KUE9QX0FCT1ZFXzU1MGNfREFZX291dGxpZXJzX2ltcHV0ZWQgPC0gUE9WX1NUQVRTX0lNUFVURV9GSU5BTCRQT1BfQUJPVkVfNTUwY19EQVkgJT4lIHNjb3Jlcyh0eXBlID0gInoiKQ0KDQpsZW5ndGggKHdoaWNoKCBhYnMoUE9QX0FCT1ZFXzU1MGNfREFZX291dGxpZXJzX2ltcHV0ZWQpID4zICkpDQoNCg0KDQoNCg0KDQoNCg0KDQpgYGANCiogRm91bmQgdGhlIG91dGxpZXJzIG9mIGFsbCB0aGUgbnVtZXJpYyB2YXJpYWJsZXMgdXNpbmcgei1zY29yZXMgbWV0aG9kIGV4Y2VwdCAneWVhcicgY29sdW1uIHdoaWNoIGlzIG5vdCByZXF1cmlyZWQgICB0byBiZSBjb25zaWRlcmVkIGZvciBzZWFyY2hpbmcgb3V0bGllcnMuDQoNCiogVGhlcmUgd2VyZSBzb21lIG91bGllcnMgd2hpY2ggbWlnaHQgaGFkIGJlZW4gZHVlIHRvIGRhdGEgZW50ZXJpbmcuDQoNCiogaW1wdXRhdGlvbiB3YXMgdXNlZCB0byByZW1vdmUgdGhlIG91dGxpZXJzIG9mIGFsbCB0aGUgbnVtZXJpYyB2YXRpYWJsZXMgYnkgcmVzcGVjdGl2ZSBtZWFuIHZhbHVlcy4NCg0KKiBIb3dldmVyLCBmb3Igc29tZSByZWFzb24gb3V0bGllciBjb3VudCBnb3QgaW5jcmVhc2VkIGFmdGVyIHRoZSBpbXB1dGF0aW9uLiBJdCBtaWdodCBiZSBkdWUgdG8gdGhlIGZhY3QgdGhhdCBkYXRhICAgIGVudHJ5IGVycm9yIG1pZ2h0IGNvbnRhaW4gZmFyIGxhcmdlciB2YWx1ZXMgdGhhbiBleGlzdGluZyB2YWx1ZXMuDQoNCg0KIyMJVHJhbnNmb3JtIA0KDQoNCmBgYHtyfQ0KI0Rpc3BsYXlpbmcgaGlzdG9ncmFtIG9mICd0b3RhbCBwb3B1bGF0aW9uJyBjb3VsdW1uDQpoaXN0KFBPVl9TVEFUU19JTVBVVEVfRklOQUwkUE9QX1RPVEwsIG1haW4gPSAiSGlzdG9ncmFtIG9mIFBPT1JfMzIwY19EQVkiKQ0KDQojQXBwbGljYXRpb24gb2YgbG9nIHRyYW5zZm9ybWF0aW9uIGZvciAndG90YWwgcG9wdWxhdGlvbicgY291bHVtbg0KbG9nX3RvdGFsX3BvcHVsYXRpb24gPC0gbG9nMTAoUE9WX1NUQVRTX0lNUFVURV9GSU5BTCRQT1BfVE9UTCkNCg0KaGlzdChsb2dfdG90YWxfcG9wdWxhdGlvbikNCg0KDQoNCg0KDQpgYGANCg0KKiBIaXN0b2dyYW0gb2YgdGhlIHNlbGVjdGVkIHZhcmlhYmxlICdQT1BfVE9UTCcgd2FzIGRpc3BsYXllZCB0byB2aWV3IHRoZSBkaXN0cmlidXRpb24uDQoNCiogSXQgd2FzIG1vcmUgb2YgYSByaWdodCBza2V3ZWQgZGlzdHJpYnV0aW9uIGFuZCBsb2cgdHJhbnNmb3JtYXRpb24gd2FzIHVzZWQgdG8gcmVtb3ZlIHRoZSByaWdodCBza2V3bmVzcyBzaW5jZSBsb2cgdHJuYXNmb3JtYXRpb24gaXMgaWRlYWwgZm9yIHJlbW92aW5nIHJpZ2h0IHNrZXduZXNzLg0KDQoNCg0KDQoNCjxicj4NCjxicj4NCg==