Required packages
# This is the R chunk for the required packages
library(readr)
library(tidyr)
library(readxl)
library(stringr)
library(lubridate)
library(dplyr)
library(forecast)
Executive Summary
The World Bank Development Indicators are able to provide significant insight into the economics and demographics of countries around the world. However this data is split into multiple files, with inconsistent formatting and much missing data. For combining the dataset of Country Information with Population and Health data and then preparing it for analysis, the following steps were used.
* The datasets were joined using the unique country codes
* The data was tidied by creating a new observation for each year, and placing each variable measured each year into its own column
* Variables which were originally stored as a single string were split into their own variables
* Fields containing no data were formatted as NA
* Fields containing a range of multiple years were changed to only show the latest year in the range
* Other obviously incorrect data was manually corrected
* Columns containing no data at all were removed
* Columns containing data with ordinal data were formatted as ordered factors
* Years and other numeric data were converted from character to string to allow mathematical manipulation
* New variables were calculated to indicate the population change over 5 year periods, and the contribution of the net migration to this number
* The contribution of net migration to population change was used to create a new categorical variable
* Numerical data was re-scanned for outlier values, however the only outliers found were actually correct and significant
* To allow for linear regression using the population totals, a Box-Cox transformation was applied to it to ensure it was normally distributed
Data
A clear description of data sets, their sources, and variable descriptions should be provided. In this section, you must also provide the R codes with outputs (head of data sets) that you used to import/read/scrape the data set. You need to fulfil the minimum requirement #1 and merge at least two data sets to create the one you are going to work on. In addition to the R codes and outputs, you need to explain the steps that you have taken.
This investigation is combining two different datasets obtained from the World Bank Open Data repository.
The first dataset is a list of economic information about each country of the world, as well as aggregate information for certain groups of countries. The details of each variable are as below:
- Country Code Character This is a 3 character alphabetical unique identifier for the country or group
- Short Name Character This is an informal shortening of the full country name or group
- Table Name Character This is the name of the country or group used when referred to elsewhere in World Bank Data, and is typically similar to the Short Name
- Long Name Character This is the formal, full name of the country or group which has been chosen by the country itself
- 2-alpha code Character This is a 2 character code which can also function as a unique country identifier as per ISO 3166
- Currency Unit Character This indicates the unit of currency used by the country
- Special Notes Character This contains a variety of notes about the entry, such as the timings of its fiscal year and historical notes
- Region Character This indicates which broader region of the world the country or group is located in
- Income Group Character This indicates the rough level of income for the country, and is divided into four different levels. This is left blank for groups.
- WB-2 Code Character This is identical to the 2-alpha code except for instances where a 2-alpha code does not exist
- National Accounts Base Year Character This is the year used as the starting point for price calculations in the country’s national accounts if these calculations have never been rescaled for a later year.
- National Accounts Reference Year Character Is the year used for price calculations in the country’s national accounts if these calculations have been rescaled from a different year previously.
- SNA Price Valuation Character This is the method by which the prices of goods in the country is calculated
- Lending Category Character This indicates which types of loans the country is eligible for
- Other Groups Character This indicates which other significant groupings of countries the country may belong to
- System of National Accounts Character This indicates which system the country uses for its national financial reporting, typically referring to the system of a particular year
- Alternative Conversion Factor Character This indicates which period’s exchange rates are used when converting the country’s GDP into USD
- PPP Survey Year Untyped This would indicate the year in which the survey data regarding Purchasing Power Parity was obtained for the country, however this entire column is blank in the dataset
- Balance of Payments Manual in use Character This indicates which edition of the IMF’s Balance of Payments Manual is being used as the standard for compiling statisistics on the country
- External Debt Reporting Status Character This indicates whether the debt data for the country is what was actually reported by the country, if World Bank staff needed to estimate part of the data, or if the data is wholly estimated by the World Bank
- System of Trade Character This indicates what system of international trade is used by the country
- Government Accounting concept Character This indicates if the country’s finance data captures all of the central government’s fiscal activities (Consolidated), or if it is incomplete (Budgetary)
- IMF Data Dissemination Standard Character This indicates which of the IMF’s data dissemination standard’s the country meets
- Latest Population Census Character This contains the year of the latest population census for the country, as well as notes regarding the census
- Latest Household Survey Character This contains the year and name of the latest household survey for the country
- Source of Most Recent Income and Expenditure Data Character This contains the year and name of the source of the latest income and expenditure data for the country
- Vital Registration Complete Character This indicates whether or not the country has systems which record vital events regarding the population, and whether the registries of this are complete. This is yes if true, and blank otherwise
- Latest Agricultural Census Character This indicates the year of the latest agricultural census for the country, as well as the name of the census in some instances
- Latest Industrial Data Numeric This indicates the year from which the latest industrial data is available for the country
- Latest Trade Data Numeric This indicates the year from which the latest trade data is available for the country
The second dataset contains information regarding the population, net migration and Universal Health Coverage Index for all countries starting at the year 1960. The details of each variable are as below:
- Series Name Character This indicates the piece of data which is being measured, which for this dataset can be one of: UHC Service Coverage Index, Total Population or Net Migration
- Series Code Character This is a unique identifier for which piece of data is being measured, and functions as a unique key for the series within the broader World Bank databases
- Country Name Character This is the name of the country which the observations are from
- Country Code Character This is the 3 character unique identifier for each country/group, and these identifiers are identical to those from the first dataset
- Subsequent columns Numeric This is the value for the observation, with each column representing the year the observation was made. These are all numeric values, with blanks being filled with ‘..’
The two datasets are joined using a left join with the Country Code as a key. This allows for all information about each country to be shown for each observation.
# This is the R chunk for the Data Section
setwd("C:/Users/Alex D'Souza/Documents/Uni/RMIT/MATH2349/Assignment 2")
country<-read_csv("WDI_csv/WDICountry.csv")
Parsed with column specification:
cols(
.default = col_character(),
`PPP survey year` = [33mcol_logical()[39m,
`Latest industrial data` = [32mcol_double()[39m,
`Latest trade data` = [32mcol_double()[39m
)
See spec(...) for full column specifications.
head(country)
migpop<-read_csv("Data_Extract_From_Health_Nutrition_and_Population_Statistics/World Net Migration Data.csv")
Parsed with column specification:
cols(
.default = col_character()
)
See spec(...) for full column specifications.
head(migpop)
countmig<-migpop %>% left_join(country, by="Country Code")
head(countmig)
NA
Tidy & Manipulate Data I
According to tidy data principles, each instance of observation should have its own row in the dataframe. As such, the observations for each year should be in their own row. Additionally, the variables observed each year should all be shown in the same row, since they will be compared at the same point in time after tidying.
The tidying is being performed at this stage due to type manipulation and sanitisation needing to be performed on the new variables created from tidying the data set. Additionally, the Series Key is synonymous with the Series Name, and as such these two fields are being combined before being used as new column names when spreading the data to make it tidy.
# This is the R chunk for the Tidy & Manipulate Data I
countmigt1<-countmig %>% gather(colnames(countmig)[5:64],key="Observation Year", value = "Observation Value")
countmigt1$`Observation Year` <-as.numeric(str_sub(countmigt1$`Observation Year`,1,4))
countmigt1<-countmigt1[!is.na(countmigt1$`Series Code`),]
countmigt1<-countmigt1 %>% unite(`Series`, `Series Name`, `Series Code`)
countmigtf<-spread(countmigt1,key="Series",value="Observation Value")
countmigtf<-countmigtf %>% separate(`Latest population census`, into=c("Latest Population Census Year", "Census Notes"), sep=". " , extra = "merge")
Expected 2 pieces. Missing pieces filled with `NA` in 11040 rows [1, 2, 3, 4, 6, 7, 9, 10, 11, 12, 14, 15, 17, 18, 19, 21, 22, 23, 24, 25, ...].
countmigtf<-countmigtf %>% separate(`Latest household survey`, into=c("Latest household survey name", "Latest household survey year"), sep = ", ")
Expected 2 pieces. Additional pieces discarded in 60 rows [235, 494, 753, 1012, 1271, 1530, 1789, 2048, 2307, 2566, 2825, 3084, 3343, 3602, 3861, 4120, 4379, 4638, 4897, 5156, ...].Expected 2 pieces. Missing pieces filled with `NA` in 60 rows [27, 286, 545, 804, 1063, 1322, 1581, 1840, 2099, 2358, 2617, 2876, 3135, 3394, 3653, 3912, 4171, 4430, 4689, 4948, ...].
countmigtf<-countmigtf %>% separate(`Source of most recent Income and expenditure data`, into=c("Source of most recent Income and expenditure data", "Year of most recent Income and expenditure data"), sep = ", ")
countmigtf<-countmigtf %>% separate(`Latest agricultural census`, into=c("Latest Agricultural Census Year", "Latest Agricultural Census Name"), sep = ". ", extra = "merge")
Expected 2 pieces. Missing pieces filled with `NA` in 7320 rows [2, 4, 7, 9, 10, 12, 13, 14, 16, 17, 20, 21, 25, 27, 28, 31, 32, 34, 35, 37, ...].
Scan I
Due to the use of ‘..’ to indicate missing values for certain fields, as well as many fields containing a year occasionally containing non-numeric data, the data must have missing values and inconsistencies removed prior to the appropriate data type conversions being made.
Since the purpose of using this data is to model the percentage change in population due to migration and how it correlates with the UHC index, and migration data is only gathered over 5 year periods, we do not require the population data from the years where migration data is not recorded. As such, any observations from years which do not have migration data recorded are discarded.
The column X31 which was created during data import is also removed during this step, as it contains no data. The PPP Survey Year column is also empty for all observations, and as such will also be removed.
The National Accounts Base Year column contains the text “Original chained constant price data are rescaled.” as a place-holder if the year is not available. As such this text will be replaced by NA values to allow the year (when present) to be treated as a number.
Numerous columns contain two consecutive years to indicate a year long period spanning two calendar years. These years are separated by a ‘/’, or occasionally another character such as “-”. These values will be replaced by the latest of the two years, as this would necessarily be the year in which the data was completed and presumably released. The second year value in these instances is often stored as the last two digits of the year, and as such the full year must be inferred from the context of the data. Since all data is from the years 1960-2020, we can safely assume that if the last two digits are from 0-20, the first two are 20, and otherwise the first two are 19.
For the Channel Islands (code CHI), the data format for the Census Year, and Vital Registration Completion is different, and as such this will need to be manually corrected.
# This is the R chunk for the Scan I
countmigtf$`Population, total_SP.POP.TOTL`[countmigtf$`Population, total_SP.POP.TOTL`==".."]<-NA
countmigtf$`UHC service coverage index_SH.UHC.SRVS.CV.XD`[countmigtf$`UHC service coverage index_SH.UHC.SRVS.CV.XD`==".."]<-NA
countmigtf$`Net migration_SM.POP.NETM`[countmigtf$`Net migration_SM.POP.NETM`==".."]<-NA
countmigtf<-subset(countmigtf[!is.na(countmigtf$`Net migration_SM.POP.NETM`),], select=-c(`PPP survey year`))
countmigtf$`National accounts base year`[countmigtf$`National accounts base year`=="Original chained constant price data are rescaled."]<-NA
deslash<-function(yearstr,delim = "/"){
if (is.na(yearstr)){
return (NA)
}else{
delimvec<-c(1:length(delim))
matched<-FALSE
for (i in delimvec){
if(str_detect(yearstr,delim[i])) {
slashloc<-str_locate(yearstr,delim[i])[1]
matched<-TRUE
returnstr<-as.numeric(str_sub(yearstr,slashloc+1,str_length(yearstr)))
if (returnstr <100){
if (returnstr <21){
returnstr = returnstr+2000
}else{
returnstr = returnstr+1900
}
}
return(returnstr)
} else {
}
}
if (matched){
} else {
return (yearstr)
}
}
}
countmigtf$`National accounts base year`<-as.numeric(lapply(countmigtf$`National accounts base year`,deslash,c("/","-")))
countmigtf$`National accounts reference year`<-as.numeric(lapply(countmigtf$`National accounts reference year`,deslash,c("/","-")))
countmigtf$`Year of most recent Income and expenditure data`<-as.numeric(lapply(countmigtf$`Year of most recent Income and expenditure data`,deslash,c("/","-")))
countmigtf$`Latest household survey year`<-as.numeric(lapply(countmigtf$`Latest household survey year`,deslash,c("/","-")))
NAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercion
countmigtf$`Latest Agricultural Census Year`<-as.numeric(lapply(countmigtf$`Latest Agricultural Census Year`,deslash,c("/","-")))
countmigtf$`Latest Population Census Year`<-as.numeric(lapply(countmigtf$`Latest Population Census Year`,deslash,c("/","-")))
NAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercion
countmigtf$`Latest Population Census Year`[countmigtf$`Country Code`=="CHI"] <- 2015
countmigtf$`Vital registration complete`[countmigtf$`Country Code`=="CHI"] <- "Yes"
Understand
Summarise the types of variables and data structures, check the attributes in the data and apply proper data type conversions. In addition to the R codes and outputs, explain briefly the steps that you have taken. In this section, show that you have fulfilled minimum requirements 2-4.
Due to originally being stored as a string, the columns which store a year value will need to be coerced to a numeric type. additionally, some variables have a clear order as per the data inspection section, and as such can be coerced to a factor with levels.
# This is the R chunk for the Understand Section
str(countmigtf)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 2808 obs. of 38 variables:
$ Country Name : chr "Afghanistan" "Albania" "Algeria" "Angola" ...
$ Country Code : chr "AFG" "ALB" "DZA" "AGO" ...
$ Short Name : chr "Afghanistan" "Albania" "Algeria" "Angola" ...
$ Table Name : chr "Afghanistan" "Albania" "Algeria" "Angola" ...
$ Long Name : chr "Islamic State of Afghanistan" "Republic of Albania" "People's Democratic Republic of Algeria" "People's Republic of Angola" ...
$ 2-alpha code : chr "AF" "AL" "DZ" "AO" ...
$ Currency Unit : chr "Afghan afghani" "Albanian lek" "Algerian dinar" "Angolan kwanza" ...
$ Special Notes : chr NA NA NA NA ...
$ Region : chr "South Asia" "Europe & Central Asia" "Middle East & North Africa" "Sub-Saharan Africa" ...
$ Income Group : chr "Low income" "Upper middle income" "Upper middle income" "Lower middle income" ...
$ WB-2 code : chr "AF" "AL" "DZ" "AO" ...
$ National accounts base year : num 2003 NA NA 2002 2006 ...
$ National accounts reference year : num NA 2010 1999 NA NA ...
$ SNA price valuation : chr "Value added at basic prices (VAB)" "Value added at basic prices (VAB)" "Value added at basic prices (VAB)" "Value added at basic prices (VAB)" ...
$ Lending category : chr "IDA" "IBRD" "IBRD" "IBRD" ...
$ Other groups : chr "HIPC" NA NA NA ...
$ System of National Accounts : chr "Country uses the 1993 System of National Accounts methodology" "Country uses the 2008 System of National Accounts methodology" "Country uses the 1993 System of National Accounts methodology" "Country uses the 1993 System of National Accounts methodology" ...
$ Alternative conversion factor : chr NA NA NA "1991–96" ...
$ Balance of Payments Manual in use : chr "BPM6" "BPM6" "BPM6" "BPM6" ...
$ External debt Reporting status : chr "Actual" "Actual" "Actual" "Actual" ...
$ System of trade : chr "General trade system" "Special trade system" "Special trade system" "Special trade system" ...
$ Government Accounting concept : chr "Consolidated central government" "Consolidated central government" "Consolidated central government" "Budgetary central government" ...
$ IMF data dissemination standard : chr "Enhanced General Data Dissemination System (e-GDDS)" "Enhanced General Data Dissemination System (e-GDDS)" "Enhanced General Data Dissemination System (e-GDDS)" "Enhanced General Data Dissemination System (e-GDDS)" ...
$ Latest Population Census Year : num 1979 2011 2008 2014 2011 ...
$ Census Notes : chr NA NA NA NA ...
$ Latest household survey name : chr "Demographic and Health Survey" "Demographic and Health Survey" "Multiple Indicator Cluster Survey" "Demographic and Health Survey" ...
$ Latest household survey year : num 2015 2018 2019 2016 NA ...
$ Source of most recent Income and expenditure data: chr "Integrated household survey (IHS)" "Living Standards Measurement Study Survey (LSMS)" "Integrated household survey (IHS)" "Integrated household survey (IHS)" ...
$ Year of most recent Income and expenditure data : num 2017 2012 2011 2009 NA ...
$ Vital registration complete : chr NA "Yes" NA NA ...
$ Latest Agricultural Census Year : num NA 2012 NA NA 2007 ...
$ Latest Agricultural Census Name : chr NA NA NA NA ...
$ Latest industrial data : num NA 2013 2010 NA NA ...
$ Latest trade data : num 2017 2017 2017 2017 2017 ...
$ Observation Year : num 1962 1962 1962 1962 1962 ...
$ Net migration_SM.POP.NETM : chr "-20000" "-99" "-282941" "-296717" ...
$ Population, total_SP.POP.TOTL : chr "9351441" "1711319" "11619828" "5608539" ...
$ UHC service coverage index_SH.UHC.SRVS.CV.XD : chr NA NA NA NA ...
countmigtf$`External debt Reporting status`<-factor(countmigtf$`External debt Reporting status`, levels=addNA(c(NA,"Estimate","Preliminary","Actual")), exclude=NULL)
countmigtf$`Income Group`<-factor(countmigtf$`Income Group`,levels=c(NA,"Low income", "Lower middle income","Upper middle income","High income"), exclude=NULL)
countmigtf$`Vital registration complete`[is.na(countmigtf$`Vital registration complete`)]<-"No"
countmigtf$`Vital registration complete`<-factor(countmigtf$`Vital registration complete`, levels=c("Yes","No"), exclude=NULL)
countmigtf$`System of National Accounts`<- as.numeric(str_sub(countmigtf$`System of National Accounts`,18,21))
countmigtf$`Net migration_SM.POP.NETM`<-as.numeric(countmigtf$`Net migration_SM.POP.NETM`)
countmigtf$`Population, total_SP.POP.TOTL`<-as.numeric(countmigtf$`Population, total_SP.POP.TOTL`)
countmigtf$`UHC service coverage index_SH.UHC.SRVS.CV.XD`<-as.numeric(countmigtf$`UHC service coverage index_SH.UHC.SRVS.CV.XD`)
str(countmigtf)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 2808 obs. of 38 variables:
$ Country Name : chr "Afghanistan" "Albania" "Algeria" "Angola" ...
$ Country Code : chr "AFG" "ALB" "DZA" "AGO" ...
$ Short Name : chr "Afghanistan" "Albania" "Algeria" "Angola" ...
$ Table Name : chr "Afghanistan" "Albania" "Algeria" "Angola" ...
$ Long Name : chr "Islamic State of Afghanistan" "Republic of Albania" "People's Democratic Republic of Algeria" "People's Republic of Angola" ...
$ 2-alpha code : chr "AF" "AL" "DZ" "AO" ...
$ Currency Unit : chr "Afghan afghani" "Albanian lek" "Algerian dinar" "Angolan kwanza" ...
$ Special Notes : chr NA NA NA NA ...
$ Region : chr "South Asia" "Europe & Central Asia" "Middle East & North Africa" "Sub-Saharan Africa" ...
$ Income Group : Factor w/ 5 levels NA,"Low income",..: 2 4 4 3 5 1 4 4 5 5 ...
$ WB-2 code : chr "AF" "AL" "DZ" "AO" ...
$ National accounts base year : num 2003 NA NA 2002 2006 ...
$ National accounts reference year : num NA 2010 1999 NA NA ...
$ SNA price valuation : chr "Value added at basic prices (VAB)" "Value added at basic prices (VAB)" "Value added at basic prices (VAB)" "Value added at basic prices (VAB)" ...
$ Lending category : chr "IDA" "IBRD" "IBRD" "IBRD" ...
$ Other groups : chr "HIPC" NA NA NA ...
$ System of National Accounts : num 1993 2008 1993 1993 2008 ...
$ Alternative conversion factor : chr NA NA NA "1991–96" ...
$ Balance of Payments Manual in use : chr "BPM6" "BPM6" "BPM6" "BPM6" ...
$ External debt Reporting status : Factor w/ 4 levels NA,"Estimate",..: 4 4 4 4 1 1 4 4 1 1 ...
$ System of trade : chr "General trade system" "Special trade system" "Special trade system" "Special trade system" ...
$ Government Accounting concept : chr "Consolidated central government" "Consolidated central government" "Consolidated central government" "Budgetary central government" ...
$ IMF data dissemination standard : chr "Enhanced General Data Dissemination System (e-GDDS)" "Enhanced General Data Dissemination System (e-GDDS)" "Enhanced General Data Dissemination System (e-GDDS)" "Enhanced General Data Dissemination System (e-GDDS)" ...
$ Latest Population Census Year : num 1979 2011 2008 2014 2011 ...
$ Census Notes : chr NA NA NA NA ...
$ Latest household survey name : chr "Demographic and Health Survey" "Demographic and Health Survey" "Multiple Indicator Cluster Survey" "Demographic and Health Survey" ...
$ Latest household survey year : num 2015 2018 2019 2016 NA ...
$ Source of most recent Income and expenditure data: chr "Integrated household survey (IHS)" "Living Standards Measurement Study Survey (LSMS)" "Integrated household survey (IHS)" "Integrated household survey (IHS)" ...
$ Year of most recent Income and expenditure data : num 2017 2012 2011 2009 NA ...
$ Vital registration complete : Factor w/ 2 levels "Yes","No": 2 1 2 2 1 2 1 1 1 1 ...
$ Latest Agricultural Census Year : num NA 2012 NA NA 2007 ...
$ Latest Agricultural Census Name : chr NA NA NA NA ...
$ Latest industrial data : num NA 2013 2010 NA NA ...
$ Latest trade data : num 2017 2017 2017 2017 2017 ...
$ Observation Year : num 1962 1962 1962 1962 1962 ...
$ Net migration_SM.POP.NETM : num -20000 -99 -282941 -296717 -1880 ...
$ Population, total_SP.POP.TOTL : num 9351441 1711319 11619828 5608539 55841 ...
$ UHC service coverage index_SH.UHC.SRVS.CV.XD : num NA NA NA NA NA NA NA NA NA NA ...
Tidy & Manipulate Data II
For the purposes of having a unique identifier for each observation, a key will be created by combining the country code with the year of the observation. This will be useful for future indexing and using this data in a Database Management Schema.
The 5-year migration numbers for each country are currently absolute values. This number could be more useful if represented as either a proportion of the total population of the country, or as a proportion of the total change in population over that period.
As such, these proportions will be calculated for each entry in the dataset.
For instances where the data from 5 years prior is unavailable, this field will be left blank (NA).
It will also be useful to create a categorical variable to indicate whether migration comprises the entirety or just a portion of the net population change, and in which direction the population is changing.
# This is the R chunk for the Tidy & Manipulate Data II
countmigtf$Key<-paste0(countmigtf$`Country Code`,countmigtf$`Observation Year`)
#Verify the keys are unique
sum(duplicated(countmigtf$Key))==0
[1] TRUE
countmig5<-subset(countmigtf,select=c(`Country Code`, `Observation Year`, `Population, total_SP.POP.TOTL`))
countmig5$`Observation Year`<-countmig5$`Observation Year`+5
countmig5<- countmig5 %>% unite(Key, `Country Code`, `Observation Year`,sep="")
countmigtf<-left_join(countmigtf, countmig5, by="Key", suffix=c(""," 5YA"))
countmigtf$`5 Year Population Change`<-countmigtf$`Population, total_SP.POP.TOTL`-countmigtf$`Population, total_SP.POP.TOTL 5YA`
countmigtf$`Migration Proportion of Total Population`<-countmigtf$`Net migration_SM.POP.NETM`/countmigtf$`Population, total_SP.POP.TOTL`
countmigtf$`Migration Proportion of Population Change`<-countmigtf$`Net migration_SM.POP.NETM`/countmigtf$`5 Year Population Change`
migpopstatus<-c("Insufficient Data", "Decrease Exclusively Due to Migration", "Decrease Partially Due to Migration", "Increase Exclusively Due to Migration", "Increase Partially Due to Migration", "Decrease Despite Positive Migration", "Increase Despite Negative Migration", "No Net Migration")
#Function to categorise the impact of migration upon the change in population
migcat<-function(migprop, changeprop){
if (is.na(migprop)|is.na(changeprop)){
#If insufficient data is available about migration or population
return (1)
} else {
#If there is no net migration
if (changeprop==0) {
return (8)
}else {
#If the net migration is in the same direction as the population change
if (changeprop>0){
#If the change in population is exclusively due to migration
if (changeprop>=1){
#If the net migration is positive
if (migprop >0) {
return (4)
#If the net migration is negative
} else {
return (2)
}
#If the change in population is partially due to migration
} else {
#If the net migration is positive
if (migprop >0) {
return (5)
#If the net migration is negative
} else {
return (3)
}
}
#If the net migration is in the opposite direction to the population change
} else {
#If the net migration is negative
if (migprop<0){
return (7)
#If the net migration is positive
} else{
return (6)
}
}
}
}
}
countmigtf$`Change in Population Due to Migration`<-factor(mapply(migcat, countmigtf$`Migration Proportion of Total Population`, countmigtf$`Migration Proportion of Population Change`), ordered=TRUE, labels=migpopstatus)
Scan II
For all variables which store a year, this value should generally be between 1960 and 2020, since this is the time period which the data covers. As such, our outlier checks here will be looking for any year value which is outside of this range.
The UHC service coverage index is by definition a value between 0 and 100. As such, it will be scanned for values lying outside of this range.
The only other numeric data in this data set is the population and migration data. One of the common reasons for removing or modifying outliers is sampling error, with the outliers being unrepresentative of the population due to the low number of observations. However due to the dataset containing the entire population (every country), every single data point would be representative of the population, and as such we cannot remove or modify any observations due to sampling error.
Instead, the scanning for outliers will focus upon those which were due to data entry, or data processing errors; and this will be done by searching for logically impossible values. For the population totals it will only be checked that these are above 0 and for net migration it will be checked that the absolute value is not greater than the population total.
Since the 5 year ago population and the 5 year population change are derived from the population data which is already being scanned, if there are no outliers in the population totals, then this data will be free of outliers too.
The calculated proportions from Tidy & Manipulate Data II will be checked for both impossible, and non-useful values. The migration proportion of the total population must be in the range from -1 to 1, since otherwise would indicate a greater proportion than the total country’s population leaving or entering the country.
However, the migration proportion of the population change is useful regardless of what value it takes, and due to being calculated from variables which are already being scanned, there will be no outliers here beyond those identified in other variables.
# This is the R chunk for the Scan II
yearvarlist<-c("National accounts base year", "National accounts reference year", "System of National Accounts", "Latest Population Census Year", "Latest household survey year", "Year of most recent Income and expenditure data", "Latest Agricultural Census Year", "Latest industrial data", "Latest trade data", "Observation Year")
outliervarlist<-append(yearvarlist,c("Population, total_SP.POP.TOTL","Net migration_SM.POP.NETM","UHC service coverage index_SH.UHC.SRVS.CV.XD", "Migration Proportion of Total Population"))
outliercount<-rep(0,14)
outliervals<-rep(NA,14)
varlength<-c(1:length(yearvarlist))
for (i in varlength){
thisoutlier<-as.data.frame(countmigtf[yearvarlist[i]])[(countmigtf[yearvarlist[i]]<1960|countmigtf[yearvarlist[i]]>2020)& !is.na(countmigtf[yearvarlist[i]])]
outliercount[i]<-length(thisoutlier)
if (outliercount[i] >0){
outliervals[i]<-paste(unique(thisoutlier))}
}
popoutlier<-as.data.frame(countmigtf["Population, total_SP.POP.TOTL"])[!countmigtf["Population, total_SP.POP.TOTL"]>0 & !is.na(countmigtf["Population, total_SP.POP.TOTL"])]
outliercount[11]<-length(popoutlier)
if (outliercount[11] >0){
outliervals[12]<-paste(unique(popoutlier))}
netmigoutlier<-as.data.frame(countmigtf["Net migration_SM.POP.NETM"])[(abs(countmigtf["Net migration_SM.POP.NETM"])>countmigtf["Population, total_SP.POP.TOTL"])& !is.na(countmigtf["Net migration_SM.POP.NETM"]) & !is.na(countmigtf["Population, total_SP.POP.TOTL"])]
outliercount[12]<-length(netmigoutlier)
if (outliercount[12] >0){
outliervals[12]<-paste(unique(netmigoutlier))}
UHCoutlier<-as.data.frame(countmigtf["UHC service coverage index_SH.UHC.SRVS.CV.XD"])[(countmigtf["UHC service coverage index_SH.UHC.SRVS.CV.XD"]>100|countmigtf["UHC service coverage index_SH.UHC.SRVS.CV.XD"]<0) & !is.na(countmigtf["UHC service coverage index_SH.UHC.SRVS.CV.XD"])]
outliercount[13]<-length(UHCoutlier)
if (outliercount[13] >0){
outliervals[13]<-paste(unique(UHCoutlier))}
migtotoutlier<-as.data.frame(countmigtf["Migration Proportion of Total Population"])[(countmigtf["Migration Proportion of Total Population"]>1|countmigtf["Migration Proportion of Total Population"]<(-1)) & !is.na(countmigtf["Migration Proportion of Total Population"])]
outliercount[14]<-length(migtotoutlier)
if (outliercount[14] >0){
outliervals[14]<-paste(unique(migtotoutlier))}
yearoutliersummary<-data.frame(outliercount, outliervals)
rownames(yearoutliersummary)<-outliervarlist
colnames(yearoutliersummary)<-c("Number of Outliers", "Outlier Value(s)")
as.table(as.matrix(yearoutliersummary))
Number of Outliers Outlier Value(s)
National accounts base year 12 1954
National accounts reference year 0
System of National Accounts 0
Latest Population Census Year 12 1943
Latest household survey year 0
Year of most recent Income and expenditure data 0
Latest Agricultural Census Year 0
Latest industrial data 0
Latest trade data 0
Observation Year 0
Population, total_SP.POP.TOTL 0
Net migration_SM.POP.NETM 0
UHC service coverage index_SH.UHC.SRVS.CV.XD 0
Migration Proportion of Total Population 0
As can be seen from this summary of outliers, there are only outliers present in the national accounts base year, and the latest population census year. These values of 1954 and 1943 however, still appear to be reasonable years for data to have been obtained from for the World Bank.
For the national accounts base year, it is quite possible for the accounts to be calculated using values from as far back as 1954.
Similarly, the latest population census being in 1943 is also possible for a country, especially one which may be undergoing some conflict.
As such, these outliers will be left in the data, as they still appear to be accurate and useful.
Transform
One might want to perform a linear regression to investigate if there is a linear relationship between the population of a country and the UHC service coverage index. However a key requirement for linear regression is that the data is normally distributed. As such, it will need to be checked whether these two variables are normally distributed; and if they are not, then an appropriate transformation will need to be applied.
Their normality can be checked by a visual inspection of a histogram of the data, and it’s quickly clear that the Population data is heavily right skewed. The UHC index however does appear to be roughly normally distributed, and as such will require no transformation.
Fortunately, the Box-Cox transformation can be applied to the data here to ensure it is normally distributed to allow for linear regression. The lambda value for this transformation will be automatically calculated through the use of the forecast package.


hist(countmigtf$`Population, total_SP.POP.TOTL`, main="Histogram of Total Population", xlab="Population")
hist(countmigtf$`UHC service coverage index_SH.UHC.SRVS.CV.XD`, main="Histogram of UHC Service Coverage Index", xlab="UHC Service Coverage Index")
countmigtf$`Box-Cox Population`<-BoxCox(countmigtf$`Population, total_SP.POP.TOTL`, lambda="auto")
hist(countmigtf$`Box-Cox Population`, main="Histogram of Box-Cox Normalised Population", xlab = "Box-Cox Normalised Population")

NOTE: Note that sometimes the order of the tasks may be different than the order given here. For example, you may need to tidy the data sets first to be able to create the common key to merge. Therefore, for such cases you may have a different ordering of the sections.
Any further or optional pre-processing tasks can be added to the template using an additional section in the R Markdown file. Make sure your code is visible (within the margin of the page). Do not use View() to show your data, instead give headers (using head() )
References
RStudio 2020, R Markdown Reference Guide, RStudio, viewed 27 March 2020, <link>
Dolgun, A 2020, Module 4, RMIT University, viewed 6 June 2020, <link>
Dolgun, A 2020, Module 5, RMIT University, viewed 6 June 2020, <link>
Dolgun, A 2020, Module 6, RMIT University, viewed 6 June 2020, <link>
Dolgun, A 2020, Module 7, RMIT University, viewed 6 June 2020, <link>
Dolgun, A 2020, Module 8, RMIT University, viewed 6 June 2020, <link>
World Bank Group 2020, Health Nutrition and Population Statistics, World Bank Group, viewed 4 June 2020, <link>
World Bank Group 2020, World Development Indicators, World Bank Group, viewed 30 May 2020, <link>
Baglin, J 2019, Module 9, RMIT University, viewed 6 June 2020, <link>
IBAN 2020, List of country codes, IBAN, viewed 7 June 2020, <link>
World Bank Group 2020, National Accounts Base Year, World Bank Data Catalog, viewed 6 June 2020, <link>
OECD 2020, Market Prices - SNA, Glossary of Statistical Terms, viewed 7 June 2020, <link>
World Bank Group 2020, How Does the World Bank Classify Countries, World Bank Data Helpdesk, viewed 7 June 2020, <link>
World Bank Group 2020, What is the DEC conversion factor?, World Bank Data Helpdesk, viewed 7 June 2020, <link>
World Bank Group 2020, Balance of Payments Manual In Use, World Bank Data Catalog, viewed 6 June 2020, <link>
World Bank Group 2020, External Debt Reporting Status, World Bank Data Catalog, viewed 6 June 2020, <link>
World Bank Group 2020, Government Finance Accounting, World Bank Data Catalog, viewed 6 June 2020, <link>
World Bank Group 2020, Special Data Dissemination Standard, World Bank Data Catalog, viewed 6 June 2020, <link>
World Bank Group 2020, Vital Registration System Coverage, World Bank Data Catalog, viewed 6 June 2020, <link>
Scholer, F 2020, Database Concepts: The Relational Model 1, ISYS1055 Week 2 Learning Materials/Activities, viewed 6 June 2020, <link>
LS0tDQp0aXRsZTogIk1BVEgyMzQ5IFNlbWVzdGVyIDEsIDIwMjAiDQphdXRob3I6ICJBbGV4YW5kZXIgRCdTb3V6YSBTMzgyODAwNiINCnN1YnRpdGxlOiBBc3NpZ25tZW50IDINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KLS0tDQoNCg0KIyMgUmVxdWlyZWQgcGFja2FnZXMgDQoNCg0KYGBge3J9DQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSByZXF1aXJlZCBwYWNrYWdlcw0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KDQpgYGANCg0KDQojIyBFeGVjdXRpdmUgU3VtbWFyeSANCg0KDQpUaGUgV29ybGQgQmFuayBEZXZlbG9wbWVudCBJbmRpY2F0b3JzIGFyZSBhYmxlIHRvIHByb3ZpZGUgc2lnbmlmaWNhbnQgaW5zaWdodCBpbnRvIHRoZSBlY29ub21pY3MgYW5kIGRlbW9ncmFwaGljcyBvZiBjb3VudHJpZXMgYXJvdW5kIHRoZSB3b3JsZC4gSG93ZXZlciB0aGlzIGRhdGEgaXMgc3BsaXQgaW50byBtdWx0aXBsZSBmaWxlcywgd2l0aCBpbmNvbnNpc3RlbnQgZm9ybWF0dGluZyBhbmQgbXVjaCBtaXNzaW5nIGRhdGEuIEZvciBjb21iaW5pbmcgdGhlIGRhdGFzZXQgb2YgQ291bnRyeSBJbmZvcm1hdGlvbiB3aXRoIFBvcHVsYXRpb24gYW5kIEhlYWx0aCBkYXRhIGFuZCB0aGVuIHByZXBhcmluZyBpdCBmb3IgYW5hbHlzaXMsIHRoZSBmb2xsb3dpbmcgc3RlcHMgd2VyZSB1c2VkLiAgDQoqIFRoZSBkYXRhc2V0cyB3ZXJlIGpvaW5lZCB1c2luZyB0aGUgdW5pcXVlIGNvdW50cnkgY29kZXMgIA0KKiBUaGUgZGF0YSB3YXMgdGlkaWVkIGJ5IGNyZWF0aW5nIGEgbmV3IG9ic2VydmF0aW9uIGZvciBlYWNoIHllYXIsIGFuZCBwbGFjaW5nIGVhY2ggdmFyaWFibGUgbWVhc3VyZWQgZWFjaCB5ZWFyIGludG8gaXRzIG93biBjb2x1bW4gIA0KKiBWYXJpYWJsZXMgd2hpY2ggd2VyZSBvcmlnaW5hbGx5IHN0b3JlZCBhcyBhIHNpbmdsZSBzdHJpbmcgd2VyZSBzcGxpdCBpbnRvIHRoZWlyIG93biB2YXJpYWJsZXMgIA0KKiBGaWVsZHMgY29udGFpbmluZyBubyBkYXRhIHdlcmUgZm9ybWF0dGVkIGFzIE5BICANCiogRmllbGRzIGNvbnRhaW5pbmcgYSByYW5nZSBvZiBtdWx0aXBsZSB5ZWFycyB3ZXJlIGNoYW5nZWQgdG8gb25seSBzaG93IHRoZSBsYXRlc3QgeWVhciBpbiB0aGUgcmFuZ2UgIA0KKiBPdGhlciBvYnZpb3VzbHkgaW5jb3JyZWN0IGRhdGEgd2FzIG1hbnVhbGx5IGNvcnJlY3RlZCAgDQoqIENvbHVtbnMgY29udGFpbmluZyBubyBkYXRhIGF0IGFsbCB3ZXJlIHJlbW92ZWQgIA0KKiBDb2x1bW5zIGNvbnRhaW5pbmcgZGF0YSB3aXRoIG9yZGluYWwgZGF0YSB3ZXJlIGZvcm1hdHRlZCBhcyBvcmRlcmVkIGZhY3RvcnMgIA0KKiBZZWFycyBhbmQgb3RoZXIgbnVtZXJpYyBkYXRhIHdlcmUgY29udmVydGVkIGZyb20gY2hhcmFjdGVyIHRvIHN0cmluZyB0byBhbGxvdyBtYXRoZW1hdGljYWwgbWFuaXB1bGF0aW9uICANCiogTmV3IHZhcmlhYmxlcyB3ZXJlIGNhbGN1bGF0ZWQgdG8gaW5kaWNhdGUgdGhlIHBvcHVsYXRpb24gY2hhbmdlIG92ZXIgNSB5ZWFyIHBlcmlvZHMsIGFuZCB0aGUgY29udHJpYnV0aW9uIG9mIHRoZSBuZXQgbWlncmF0aW9uIHRvIHRoaXMgbnVtYmVyICANCiogVGhlIGNvbnRyaWJ1dGlvbiBvZiBuZXQgbWlncmF0aW9uIHRvIHBvcHVsYXRpb24gY2hhbmdlIHdhcyB1c2VkIHRvIGNyZWF0ZSBhIG5ldyBjYXRlZ29yaWNhbCB2YXJpYWJsZSAgDQoqIE51bWVyaWNhbCBkYXRhIHdhcyByZS1zY2FubmVkIGZvciBvdXRsaWVyIHZhbHVlcywgaG93ZXZlciB0aGUgb25seSBvdXRsaWVycyBmb3VuZCB3ZXJlIGFjdHVhbGx5IGNvcnJlY3QgYW5kIHNpZ25pZmljYW50ICANCiogVG8gYWxsb3cgZm9yIGxpbmVhciByZWdyZXNzaW9uIHVzaW5nIHRoZSBwb3B1bGF0aW9uIHRvdGFscywgYSBCb3gtQ294IHRyYW5zZm9ybWF0aW9uIHdhcyBhcHBsaWVkIHRvIGl0IHRvIGVuc3VyZSBpdCB3YXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgIA0KDQoNCg0KDQoNCiMjIERhdGEgDQoNCkEgY2xlYXIgZGVzY3JpcHRpb24gb2YgZGF0YSBzZXRzLCB0aGVpciBzb3VyY2VzLCBhbmQgdmFyaWFibGUgZGVzY3JpcHRpb25zIHNob3VsZCBiZSBwcm92aWRlZC4gSW4gdGhpcyBzZWN0aW9uLCB5b3UgbXVzdCBhbHNvIHByb3ZpZGUgdGhlIFIgY29kZXMgd2l0aCBvdXRwdXRzIChoZWFkIG9mIGRhdGEgc2V0cykgdGhhdCB5b3UgdXNlZCB0byBpbXBvcnQvcmVhZC9zY3JhcGUgdGhlIGRhdGEgc2V0LiBZb3UgbmVlZCB0byBmdWxmaWwgdGhlIG1pbmltdW0gcmVxdWlyZW1lbnQgIzEgYW5kIG1lcmdlIGF0IGxlYXN0IHR3byBkYXRhIHNldHMgdG8gY3JlYXRlIHRoZSBvbmUgeW91IGFyZSBnb2luZyB0byB3b3JrIG9uLiBJbiBhZGRpdGlvbiB0byB0aGUgUiBjb2RlcyBhbmQgb3V0cHV0cywgeW91IG5lZWQgdG8gZXhwbGFpbiB0aGUgc3RlcHMgdGhhdCB5b3UgaGF2ZSB0YWtlbi4gIA0KDQpUaGlzIGludmVzdGlnYXRpb24gaXMgY29tYmluaW5nIHR3byBkaWZmZXJlbnQgZGF0YXNldHMgb2J0YWluZWQgZnJvbSB0aGUgV29ybGQgQmFuayBPcGVuIERhdGEgcmVwb3NpdG9yeS4gIA0KDQpUaGUgZmlyc3QgZGF0YXNldCBpcyBhIGxpc3Qgb2YgZWNvbm9taWMgaW5mb3JtYXRpb24gYWJvdXQgZWFjaCBjb3VudHJ5IG9mIHRoZSB3b3JsZCwgYXMgd2VsbCBhcyBhZ2dyZWdhdGUgaW5mb3JtYXRpb24gZm9yIGNlcnRhaW4gZ3JvdXBzIG9mIGNvdW50cmllcy4gVGhlIGRldGFpbHMgb2YgZWFjaCB2YXJpYWJsZSBhcmUgYXMgYmVsb3c6ICANCg0KKiAqKkNvdW50cnkgQ29kZSoqICpDaGFyYWN0ZXIqIFRoaXMgaXMgYSAzIGNoYXJhY3RlciBhbHBoYWJldGljYWwgdW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBjb3VudHJ5IG9yIGdyb3VwICANCiogKipTaG9ydCBOYW1lKiogKkNoYXJhY3RlciogVGhpcyBpcyBhbiBpbmZvcm1hbCBzaG9ydGVuaW5nIG9mIHRoZSBmdWxsIGNvdW50cnkgbmFtZSBvciBncm91cCAgDQoqICoqVGFibGUgTmFtZSoqICpDaGFyYWN0ZXIqIFRoaXMgaXMgdGhlIG5hbWUgb2YgdGhlIGNvdW50cnkgb3IgZ3JvdXAgdXNlZCB3aGVuIHJlZmVycmVkIHRvIGVsc2V3aGVyZSBpbiBXb3JsZCBCYW5rIERhdGEsIGFuZCBpcyB0eXBpY2FsbHkgc2ltaWxhciB0byB0aGUgU2hvcnQgTmFtZSAgDQoqICoqTG9uZyBOYW1lKiogKkNoYXJhY3RlciogVGhpcyBpcyB0aGUgZm9ybWFsLCBmdWxsIG5hbWUgb2YgdGhlIGNvdW50cnkgb3IgZ3JvdXAgd2hpY2ggaGFzIGJlZW4gY2hvc2VuIGJ5IHRoZSBjb3VudHJ5IGl0c2VsZiAgDQoqICoqMi1hbHBoYSBjb2RlKiogKkNoYXJhY3RlciogVGhpcyBpcyBhIDIgY2hhcmFjdGVyIGNvZGUgd2hpY2ggY2FuIGFsc28gZnVuY3Rpb24gYXMgYSB1bmlxdWUgY291bnRyeSBpZGVudGlmaWVyIGFzIHBlciBJU08gMzE2NiAgDQoqICoqQ3VycmVuY3kgVW5pdCoqICpDaGFyYWN0ZXIqIFRoaXMgaW5kaWNhdGVzIHRoZSB1bml0IG9mIGN1cnJlbmN5IHVzZWQgYnkgdGhlIGNvdW50cnkgIA0KKiAqKlNwZWNpYWwgTm90ZXMqKiAqQ2hhcmFjdGVyKiBUaGlzIGNvbnRhaW5zIGEgdmFyaWV0eSBvZiBub3RlcyBhYm91dCB0aGUgZW50cnksIHN1Y2ggYXMgdGhlIHRpbWluZ3Mgb2YgaXRzIGZpc2NhbCB5ZWFyIGFuZCBoaXN0b3JpY2FsIG5vdGVzICANCiogKipSZWdpb24qKiAqQ2hhcmFjdGVyKiBUaGlzIGluZGljYXRlcyB3aGljaCBicm9hZGVyIHJlZ2lvbiBvZiB0aGUgd29ybGQgdGhlIGNvdW50cnkgb3IgZ3JvdXAgaXMgbG9jYXRlZCBpbiAgDQoqICoqSW5jb21lIEdyb3VwKiogKkNoYXJhY3RlciogVGhpcyBpbmRpY2F0ZXMgdGhlIHJvdWdoIGxldmVsIG9mIGluY29tZSBmb3IgdGhlIGNvdW50cnksIGFuZCBpcyBkaXZpZGVkIGludG8gZm91ciBkaWZmZXJlbnQgbGV2ZWxzLiBUaGlzIGlzIGxlZnQgYmxhbmsgZm9yIGdyb3Vwcy4gIA0KKiAqKldCLTIgQ29kZSoqICpDaGFyYWN0ZXIqIFRoaXMgaXMgaWRlbnRpY2FsIHRvIHRoZSAyLWFscGhhIGNvZGUgZXhjZXB0IGZvciBpbnN0YW5jZXMgd2hlcmUgYSAyLWFscGhhIGNvZGUgZG9lcyBub3QgZXhpc3QNCiogKipOYXRpb25hbCBBY2NvdW50cyBCYXNlIFllYXIqKiAqQ2hhcmFjdGVyKiBUaGlzIGlzIHRoZSB5ZWFyIHVzZWQgYXMgdGhlIHN0YXJ0aW5nIHBvaW50IGZvciBwcmljZSBjYWxjdWxhdGlvbnMgaW4gdGhlIGNvdW50cnkncyBuYXRpb25hbCBhY2NvdW50cyBpZiB0aGVzZSBjYWxjdWxhdGlvbnMgaGF2ZSBuZXZlciBiZWVuIHJlc2NhbGVkIGZvciBhIGxhdGVyIHllYXIuICAgIA0KKiAqKk5hdGlvbmFsIEFjY291bnRzIFJlZmVyZW5jZSBZZWFyKiogKkNoYXJhY3RlciogSXMgdGhlIHllYXIgdXNlZCBmb3IgcHJpY2UgY2FsY3VsYXRpb25zIGluIHRoZSBjb3VudHJ5J3MgbmF0aW9uYWwgYWNjb3VudHMgaWYgdGhlc2UgY2FsY3VsYXRpb25zIGhhdmUgYmVlbiByZXNjYWxlZCBmcm9tIGEgZGlmZmVyZW50IHllYXIgcHJldmlvdXNseS4gIA0KKiAqKlNOQSBQcmljZSBWYWx1YXRpb24qKiAqQ2hhcmFjdGVyKiBUaGlzIGlzIHRoZSBtZXRob2QgYnkgd2hpY2ggdGhlIHByaWNlcyBvZiBnb29kcyBpbiB0aGUgY291bnRyeSBpcyBjYWxjdWxhdGVkICANCiogKipMZW5kaW5nIENhdGVnb3J5KiogKkNoYXJhY3RlciogVGhpcyBpbmRpY2F0ZXMgd2hpY2ggdHlwZXMgb2YgbG9hbnMgdGhlIGNvdW50cnkgaXMgZWxpZ2libGUgZm9yICANCiogKipPdGhlciBHcm91cHMqKiAqQ2hhcmFjdGVyKiBUaGlzIGluZGljYXRlcyB3aGljaCBvdGhlciBzaWduaWZpY2FudCBncm91cGluZ3Mgb2YgY291bnRyaWVzIHRoZSBjb3VudHJ5IG1heSBiZWxvbmcgdG8gIA0KKiAqKlN5c3RlbSBvZiBOYXRpb25hbCBBY2NvdW50cyoqICpDaGFyYWN0ZXIqIFRoaXMgaW5kaWNhdGVzIHdoaWNoIHN5c3RlbSB0aGUgY291bnRyeSB1c2VzIGZvciBpdHMgbmF0aW9uYWwgZmluYW5jaWFsIHJlcG9ydGluZywgdHlwaWNhbGx5IHJlZmVycmluZyB0byB0aGUgc3lzdGVtIG9mIGEgcGFydGljdWxhciB5ZWFyICANCiogKipBbHRlcm5hdGl2ZSBDb252ZXJzaW9uIEZhY3RvcioqICpDaGFyYWN0ZXIqIFRoaXMgaW5kaWNhdGVzIHdoaWNoIHBlcmlvZCdzIGV4Y2hhbmdlIHJhdGVzIGFyZSB1c2VkIHdoZW4gY29udmVydGluZyB0aGUgY291bnRyeSdzIEdEUCBpbnRvIFVTRCAgDQoqICoqUFBQIFN1cnZleSBZZWFyKiogKlVudHlwZWQqIFRoaXMgd291bGQgaW5kaWNhdGUgdGhlIHllYXIgaW4gd2hpY2ggdGhlIHN1cnZleSBkYXRhIHJlZ2FyZGluZyBQdXJjaGFzaW5nIFBvd2VyIFBhcml0eSB3YXMgb2J0YWluZWQgZm9yIHRoZSBjb3VudHJ5LCBob3dldmVyIHRoaXMgZW50aXJlIGNvbHVtbiBpcyBibGFuayBpbiB0aGUgZGF0YXNldCAgDQoqICoqQmFsYW5jZSBvZiBQYXltZW50cyBNYW51YWwgaW4gdXNlKiogKkNoYXJhY3RlciogVGhpcyBpbmRpY2F0ZXMgd2hpY2ggZWRpdGlvbiBvZiB0aGUgSU1GJ3MgQmFsYW5jZSBvZiBQYXltZW50cyBNYW51YWwgaXMgYmVpbmcgdXNlZCBhcyB0aGUgc3RhbmRhcmQgZm9yIGNvbXBpbGluZyBzdGF0aXNpc3RpY3Mgb24gdGhlIGNvdW50cnkgIA0KKiAqKkV4dGVybmFsIERlYnQgUmVwb3J0aW5nIFN0YXR1cyoqICpDaGFyYWN0ZXIqIFRoaXMgaW5kaWNhdGVzIHdoZXRoZXIgdGhlIGRlYnQgZGF0YSBmb3IgdGhlIGNvdW50cnkgaXMgd2hhdCB3YXMgYWN0dWFsbHkgcmVwb3J0ZWQgYnkgdGhlIGNvdW50cnksIGlmIFdvcmxkIEJhbmsgc3RhZmYgbmVlZGVkIHRvIGVzdGltYXRlIHBhcnQgb2YgdGhlIGRhdGEsIG9yIGlmIHRoZSBkYXRhIGlzIHdob2xseSBlc3RpbWF0ZWQgYnkgdGhlIFdvcmxkIEJhbmsgIA0KKiAqKlN5c3RlbSBvZiBUcmFkZSoqICpDaGFyYWN0ZXIqIFRoaXMgaW5kaWNhdGVzIHdoYXQgc3lzdGVtIG9mIGludGVybmF0aW9uYWwgdHJhZGUgaXMgdXNlZCBieSB0aGUgY291bnRyeSAgDQoqICoqR292ZXJubWVudCBBY2NvdW50aW5nIGNvbmNlcHQqKiAqQ2hhcmFjdGVyKiBUaGlzIGluZGljYXRlcyBpZiB0aGUgY291bnRyeSdzIGZpbmFuY2UgZGF0YSBjYXB0dXJlcyBhbGwgb2YgdGhlIGNlbnRyYWwgZ292ZXJubWVudCdzIGZpc2NhbCBhY3Rpdml0aWVzIChDb25zb2xpZGF0ZWQpLCBvciBpZiBpdCBpcyBpbmNvbXBsZXRlIChCdWRnZXRhcnkpICANCiogKipJTUYgRGF0YSBEaXNzZW1pbmF0aW9uIFN0YW5kYXJkKiogKkNoYXJhY3RlciogVGhpcyBpbmRpY2F0ZXMgd2hpY2ggb2YgdGhlIElNRidzIGRhdGEgZGlzc2VtaW5hdGlvbiBzdGFuZGFyZCdzIHRoZSBjb3VudHJ5IG1lZXRzICANCiogKipMYXRlc3QgUG9wdWxhdGlvbiBDZW5zdXMqKiAqQ2hhcmFjdGVyKiBUaGlzIGNvbnRhaW5zIHRoZSB5ZWFyIG9mIHRoZSBsYXRlc3QgcG9wdWxhdGlvbiBjZW5zdXMgZm9yIHRoZSBjb3VudHJ5LCBhcyB3ZWxsIGFzIG5vdGVzIHJlZ2FyZGluZyB0aGUgY2Vuc3VzICANCiogKipMYXRlc3QgSG91c2Vob2xkIFN1cnZleSoqICpDaGFyYWN0ZXIqIFRoaXMgY29udGFpbnMgdGhlIHllYXIgYW5kIG5hbWUgb2YgdGhlIGxhdGVzdCBob3VzZWhvbGQgc3VydmV5IGZvciB0aGUgY291bnRyeSAgDQoqICoqU291cmNlIG9mIE1vc3QgUmVjZW50IEluY29tZSBhbmQgRXhwZW5kaXR1cmUgRGF0YSoqICpDaGFyYWN0ZXIqIFRoaXMgY29udGFpbnMgdGhlIHllYXIgYW5kIG5hbWUgb2YgdGhlIHNvdXJjZSBvZiB0aGUgbGF0ZXN0IGluY29tZSBhbmQgZXhwZW5kaXR1cmUgZGF0YSBmb3IgdGhlIGNvdW50cnkgIA0KKiAqKlZpdGFsIFJlZ2lzdHJhdGlvbiBDb21wbGV0ZSoqICpDaGFyYWN0ZXIqIFRoaXMgaW5kaWNhdGVzIHdoZXRoZXIgb3Igbm90IHRoZSBjb3VudHJ5IGhhcyBzeXN0ZW1zIHdoaWNoIHJlY29yZCB2aXRhbCBldmVudHMgcmVnYXJkaW5nIHRoZSBwb3B1bGF0aW9uLCBhbmQgd2hldGhlciB0aGUgcmVnaXN0cmllcyBvZiB0aGlzIGFyZSBjb21wbGV0ZS4gVGhpcyBpcyB5ZXMgaWYgdHJ1ZSwgYW5kIGJsYW5rIG90aGVyd2lzZSAgDQoqICoqTGF0ZXN0IEFncmljdWx0dXJhbCBDZW5zdXMqKiAqQ2hhcmFjdGVyKiBUaGlzIGluZGljYXRlcyB0aGUgeWVhciBvZiB0aGUgbGF0ZXN0IGFncmljdWx0dXJhbCBjZW5zdXMgZm9yIHRoZSBjb3VudHJ5LCBhcyB3ZWxsIGFzIHRoZSBuYW1lIG9mIHRoZSBjZW5zdXMgaW4gc29tZSBpbnN0YW5jZXMgIA0KKiAqKkxhdGVzdCBJbmR1c3RyaWFsIERhdGEqKiAqTnVtZXJpYyogVGhpcyBpbmRpY2F0ZXMgdGhlIHllYXIgZnJvbSB3aGljaCB0aGUgbGF0ZXN0IGluZHVzdHJpYWwgZGF0YSBpcyBhdmFpbGFibGUgZm9yIHRoZSBjb3VudHJ5ICANCiogKipMYXRlc3QgVHJhZGUgRGF0YSoqICpOdW1lcmljKiBUaGlzIGluZGljYXRlcyB0aGUgeWVhciBmcm9tIHdoaWNoIHRoZSBsYXRlc3QgdHJhZGUgZGF0YSBpcyBhdmFpbGFibGUgZm9yIHRoZSBjb3VudHJ5ICANCg0KICAgIA0KDQpUaGUgc2Vjb25kIGRhdGFzZXQgY29udGFpbnMgaW5mb3JtYXRpb24gcmVnYXJkaW5nIHRoZSBwb3B1bGF0aW9uLCBuZXQgbWlncmF0aW9uIGFuZCBVbml2ZXJzYWwgSGVhbHRoIENvdmVyYWdlIEluZGV4IGZvciBhbGwgY291bnRyaWVzIHN0YXJ0aW5nIGF0IHRoZSB5ZWFyIDE5NjAuIFRoZSBkZXRhaWxzIG9mIGVhY2ggdmFyaWFibGUgYXJlIGFzIGJlbG93OiAgDQogIA0KKiAqKlNlcmllcyBOYW1lKiogKkNoYXJhY3RlciogVGhpcyBpbmRpY2F0ZXMgdGhlIHBpZWNlIG9mIGRhdGEgd2hpY2ggaXMgYmVpbmcgbWVhc3VyZWQsIHdoaWNoIGZvciB0aGlzIGRhdGFzZXQgY2FuIGJlIG9uZSBvZjogVUhDIFNlcnZpY2UgQ292ZXJhZ2UgSW5kZXgsIFRvdGFsIFBvcHVsYXRpb24gb3IgTmV0IE1pZ3JhdGlvbiAgDQoqICoqU2VyaWVzIENvZGUqKiAqQ2hhcmFjdGVyKiBUaGlzIGlzIGEgdW5pcXVlIGlkZW50aWZpZXIgZm9yIHdoaWNoIHBpZWNlIG9mIGRhdGEgaXMgYmVpbmcgbWVhc3VyZWQsIGFuZCBmdW5jdGlvbnMgYXMgYSB1bmlxdWUga2V5IGZvciB0aGUgc2VyaWVzIHdpdGhpbiB0aGUgYnJvYWRlciBXb3JsZCBCYW5rIGRhdGFiYXNlcyAgDQoqICoqQ291bnRyeSBOYW1lKiogKkNoYXJhY3RlciogVGhpcyBpcyB0aGUgbmFtZSBvZiB0aGUgY291bnRyeSB3aGljaCB0aGUgb2JzZXJ2YXRpb25zIGFyZSBmcm9tICANCiogKipDb3VudHJ5IENvZGUqKiAqQ2hhcmFjdGVyKiBUaGlzIGlzIHRoZSAzIGNoYXJhY3RlciB1bmlxdWUgaWRlbnRpZmllciBmb3IgZWFjaCBjb3VudHJ5L2dyb3VwLCBhbmQgdGhlc2UgaWRlbnRpZmllcnMgYXJlIGlkZW50aWNhbCB0byB0aG9zZSBmcm9tIHRoZSBmaXJzdCBkYXRhc2V0ICANCiogKipTdWJzZXF1ZW50IGNvbHVtbnMqKiAqTnVtZXJpYyogVGhpcyBpcyB0aGUgdmFsdWUgZm9yIHRoZSBvYnNlcnZhdGlvbiwgd2l0aCBlYWNoIGNvbHVtbiByZXByZXNlbnRpbmcgdGhlIHllYXIgdGhlIG9ic2VydmF0aW9uIHdhcyBtYWRlLiBUaGVzZSBhcmUgYWxsIG51bWVyaWMgdmFsdWVzLCB3aXRoIGJsYW5rcyBiZWluZyBmaWxsZWQgd2l0aCAnLi4nICANCg0KVGhlIHR3byBkYXRhc2V0cyBhcmUgam9pbmVkIHVzaW5nIGEgbGVmdCBqb2luIHdpdGggdGhlIENvdW50cnkgQ29kZSBhcyBhIGtleS4gVGhpcyBhbGxvd3MgZm9yIGFsbCBpbmZvcm1hdGlvbiBhYm91dCBlYWNoIGNvdW50cnkgdG8gYmUgc2hvd24gZm9yIGVhY2ggb2JzZXJ2YXRpb24uICANCg0KDQoNCg0KYGBge3J9DQojQ2hhbmdlIHdvcmtpbmcgZGlyZWN0b3J5IHRvIGxvY2F0aW9uIG9mIGRvY3VtZW50cw0Kc2V0d2QoIkM6L1VzZXJzL0FsZXggRCdTb3V6YS9Eb2N1bWVudHMvVW5pL1JNSVQvTUFUSDIzNDkvQXNzaWdubWVudCAyIikNCiNSZWFkIGluIENvdW50cnkgZGF0YQ0KY291bnRyeTwtcmVhZF9jc3YoIldESV9jc3YvV0RJQ291bnRyeS5jc3YiKQ0KI1N1bW1hcmlzZSBDb3VudHJ5IGRhdGENCmhlYWQoY291bnRyeSkNCiNSZWFkIGluIGhlYWx0aCBhbmQgcG9wdWxhdGlvbiBkYXRhDQptaWdwb3A8LXJlYWRfY3N2KCJEYXRhX0V4dHJhY3RfRnJvbV9IZWFsdGhfTnV0cml0aW9uX2FuZF9Qb3B1bGF0aW9uX1N0YXRpc3RpY3MvV29ybGQgTmV0IE1pZ3JhdGlvbiBEYXRhLmNzdiIpDQojU3VtbWFyaXNlIGhlYWx0aCBhbmQgcG9wdWxhdGlvbiBkYXRhDQpoZWFkKG1pZ3BvcCkNCiNKb2luIGRhdGFzZXRzIHVzaW5nIENvdW50cnkgQ29kZSBhcyBhIGtleQ0KY291bnRtaWc8LW1pZ3BvcCAlPiUgbGVmdF9qb2luKGNvdW50cnksIGJ5PSJDb3VudHJ5IENvZGUiKQ0KI1N1bW1hcmlzZSBuZXcgbWVyZ2VkIGRhdGFzZXQNCmhlYWQoY291bnRtaWcpDQoNCmBgYA0KDQojIwlUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIEkgDQoNCg0KDQpBY2NvcmRpbmcgdG8gdGlkeSBkYXRhIHByaW5jaXBsZXMsIGVhY2ggaW5zdGFuY2Ugb2Ygb2JzZXJ2YXRpb24gc2hvdWxkIGhhdmUgaXRzIG93biByb3cgaW4gdGhlIGRhdGFmcmFtZS4gQXMgc3VjaCwgdGhlIG9ic2VydmF0aW9ucyBmb3IgZWFjaCB5ZWFyIHNob3VsZCBiZSBpbiB0aGVpciBvd24gcm93LiBBZGRpdGlvbmFsbHksIHRoZSB2YXJpYWJsZXMgb2JzZXJ2ZWQgZWFjaCB5ZWFyIHNob3VsZCBhbGwgYmUgc2hvd24gaW4gdGhlIHNhbWUgcm93LCBzaW5jZSB0aGV5IHdpbGwgYmUgY29tcGFyZWQgYXQgdGhlIHNhbWUgcG9pbnQgaW4gdGltZSBhZnRlciB0aWR5aW5nLiAgDQogIA0KVGhlIHRpZHlpbmcgaXMgYmVpbmcgcGVyZm9ybWVkIGF0IHRoaXMgc3RhZ2UgZHVlIHRvIHR5cGUgbWFuaXB1bGF0aW9uIGFuZCBzYW5pdGlzYXRpb24gbmVlZGluZyB0byBiZSBwZXJmb3JtZWQgb24gdGhlIG5ldyB2YXJpYWJsZXMgY3JlYXRlZCBmcm9tIHRpZHlpbmcgdGhlIGRhdGEgc2V0LiBBZGRpdGlvbmFsbHksIHRoZSBTZXJpZXMgS2V5IGlzIHN5bm9ueW1vdXMgd2l0aCB0aGUgU2VyaWVzIE5hbWUsIGFuZCBhcyBzdWNoIHRoZXNlIHR3byBmaWVsZHMgYXJlIGJlaW5nIGNvbWJpbmVkIGJlZm9yZSBiZWluZyB1c2VkIGFzIG5ldyBjb2x1bW4gbmFtZXMgd2hlbiBzcHJlYWRpbmcgdGhlIGRhdGEgdG8gbWFrZSBpdCB0aWR5LiAgDQogIA0KYGBge3J9DQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIEkgDQojVGlkeSBkYXRhIGJ5IGNyZWF0aW5nIGEgbmV3IG9ic2VydmF0aW9uIGZvciBlYWNoIHllYXINCmNvdW50bWlndDE8LWNvdW50bWlnICU+JSBnYXRoZXIoY29sbmFtZXMoY291bnRtaWcpWzU6NjRdLGtleT0iT2JzZXJ2YXRpb24gWWVhciIsIHZhbHVlID0gIk9ic2VydmF0aW9uIFZhbHVlIikNCiNDb252ZXJ0IHRoZSBvYnNlcnZhdGlvbiB5ZWFyIHRvIGEgbnVtZXJpYyB2YWx1ZSBieSBrZWVwaW5nIG9ubHkgdGhlIGZpcnN0IDQgY2hhcmFjdGVycw0KY291bnRtaWd0MSRgT2JzZXJ2YXRpb24gWWVhcmAgPC1hcy5udW1lcmljKHN0cl9zdWIoY291bnRtaWd0MSRgT2JzZXJ2YXRpb24gWWVhcmAsMSw0KSkNCiNSZW1vdmUgYmxhbmsgb2JzZXJ2YXRpb25zIHdoaWNoIGRvIG5vdCBiZWxvbmcgdG8gYW55IHNlcmllcyBvZiBkYXRhDQpjb3VudG1pZ3QxPC1jb3VudG1pZ3QxWyFpcy5uYShjb3VudG1pZ3QxJGBTZXJpZXMgQ29kZWApLF0NCiNDcmVhdGUgYSBzaW5nbGUgdmFyaWFibGUgY29udGFpbmluZyBib3RoIHRoZSBzZXJpZXMgbmFtZSBhbmQgY29kZSwgc2luY2UgdGhleSBhcmUgaW50ZXJjaGFuZ2VhYmxlDQpjb3VudG1pZ3QxPC1jb3VudG1pZ3QxICU+JSB1bml0ZShgU2VyaWVzYCwgYFNlcmllcyBOYW1lYCwgYFNlcmllcyBDb2RlYCkNCiNDcmVhdGUgYSBuZXcgY29sdW1uIGZvciBlYWNoIHZhcmlhYmxlLCBjb21wbGV0aW5nIHRoZSB0aWR5aW5nIG9mIHRoZSBkYXRhDQpjb3VudG1pZ3RmPC1zcHJlYWQoY291bnRtaWd0MSxrZXk9IlNlcmllcyIsdmFsdWU9Ik9ic2VydmF0aW9uIFZhbHVlIikNCiNTZXBhcmF0ZSB5ZWFycyBhbmQgbm90ZXMgZnJvbSBjb2x1bW5zIHdoaWNoIGNvbWJpbmUgeWVhciBhbmQgbm90ZXMuDQpjb3VudG1pZ3RmPC1jb3VudG1pZ3RmICU+JSBzZXBhcmF0ZShgTGF0ZXN0IHBvcHVsYXRpb24gY2Vuc3VzYCwgaW50bz1jKCJMYXRlc3QgUG9wdWxhdGlvbiBDZW5zdXMgWWVhciIsICJDZW5zdXMgTm90ZXMiKSwgc2VwPSIuICIgLCBleHRyYSA9ICJtZXJnZSIpDQpjb3VudG1pZ3RmPC1jb3VudG1pZ3RmICU+JSBzZXBhcmF0ZShgTGF0ZXN0IGhvdXNlaG9sZCBzdXJ2ZXlgLCBpbnRvPWMoIkxhdGVzdCBob3VzZWhvbGQgc3VydmV5IG5hbWUiLCAiTGF0ZXN0IGhvdXNlaG9sZCBzdXJ2ZXkgeWVhciIpLCBzZXAgPSAiLCAiKQ0KY291bnRtaWd0ZjwtY291bnRtaWd0ZiAlPiUgc2VwYXJhdGUoYFNvdXJjZSBvZiBtb3N0IHJlY2VudCBJbmNvbWUgYW5kIGV4cGVuZGl0dXJlIGRhdGFgLCBpbnRvPWMoIlNvdXJjZSBvZiBtb3N0IHJlY2VudCBJbmNvbWUgYW5kIGV4cGVuZGl0dXJlIGRhdGEiLCAiWWVhciBvZiBtb3N0IHJlY2VudCBJbmNvbWUgYW5kIGV4cGVuZGl0dXJlIGRhdGEiKSwgc2VwID0gIiwgIikNCmNvdW50bWlndGY8LWNvdW50bWlndGYgJT4lIHNlcGFyYXRlKGBMYXRlc3QgYWdyaWN1bHR1cmFsIGNlbnN1c2AsIGludG89YygiTGF0ZXN0IEFncmljdWx0dXJhbCBDZW5zdXMgWWVhciIsICJMYXRlc3QgQWdyaWN1bHR1cmFsIENlbnN1cyBOYW1lIiksIHNlcCA9ICIuICIsIGV4dHJhID0gIm1lcmdlIikNCmBgYA0KDQoNCg0KDQojIwlTY2FuIEkNCg0KDQoNCkR1ZSB0byB0aGUgdXNlIG9mICcuLicgdG8gaW5kaWNhdGUgbWlzc2luZyB2YWx1ZXMgZm9yIGNlcnRhaW4gZmllbGRzLCBhcyB3ZWxsIGFzIG1hbnkgZmllbGRzIGNvbnRhaW5pbmcgYSB5ZWFyIG9jY2FzaW9uYWxseSBjb250YWluaW5nIG5vbi1udW1lcmljIGRhdGEsIHRoZSBkYXRhIG11c3QgaGF2ZSBtaXNzaW5nIHZhbHVlcyBhbmQgaW5jb25zaXN0ZW5jaWVzIHJlbW92ZWQgcHJpb3IgdG8gdGhlIGFwcHJvcHJpYXRlIGRhdGEgdHlwZSBjb252ZXJzaW9ucyBiZWluZyBtYWRlLiAgDQogIA0KU2luY2UgdGhlIHB1cnBvc2Ugb2YgdXNpbmcgdGhpcyBkYXRhIGlzIHRvIG1vZGVsIHRoZSBwZXJjZW50YWdlIGNoYW5nZSBpbiBwb3B1bGF0aW9uIGR1ZSB0byBtaWdyYXRpb24gYW5kIGhvdyBpdCBjb3JyZWxhdGVzIHdpdGggdGhlIFVIQyBpbmRleCwgYW5kIG1pZ3JhdGlvbiBkYXRhIGlzIG9ubHkgZ2F0aGVyZWQgb3ZlciA1IHllYXIgcGVyaW9kcywgd2UgZG8gbm90IHJlcXVpcmUgdGhlIHBvcHVsYXRpb24gZGF0YSBmcm9tIHRoZSB5ZWFycyB3aGVyZSBtaWdyYXRpb24gZGF0YSBpcyBub3QgcmVjb3JkZWQuIEFzIHN1Y2gsIGFueSBvYnNlcnZhdGlvbnMgZnJvbSB5ZWFycyB3aGljaCBkbyBub3QgaGF2ZSBtaWdyYXRpb24gZGF0YSByZWNvcmRlZCBhcmUgZGlzY2FyZGVkLiAgDQogIA0KVGhlIGNvbHVtbiBYMzEgd2hpY2ggd2FzIGNyZWF0ZWQgZHVyaW5nIGRhdGEgaW1wb3J0IGlzIGFsc28gcmVtb3ZlZCBkdXJpbmcgdGhpcyBzdGVwLCBhcyBpdCBjb250YWlucyBubyBkYXRhLiBUaGUgKlBQUCBTdXJ2ZXkgWWVhciogY29sdW1uIGlzIGFsc28gZW1wdHkgZm9yIGFsbCBvYnNlcnZhdGlvbnMsIGFuZCBhcyBzdWNoIHdpbGwgYWxzbyBiZSByZW1vdmVkLiAgDQogIA0KVGhlICpOYXRpb25hbCBBY2NvdW50cyBCYXNlIFllYXIqIGNvbHVtbiBjb250YWlucyB0aGUgdGV4dCAiT3JpZ2luYWwgY2hhaW5lZCBjb25zdGFudCBwcmljZSBkYXRhIGFyZSByZXNjYWxlZC4iIGFzIGEgcGxhY2UtaG9sZGVyIGlmIHRoZSB5ZWFyIGlzIG5vdCBhdmFpbGFibGUuIEFzIHN1Y2ggdGhpcyB0ZXh0IHdpbGwgYmUgcmVwbGFjZWQgYnkgTkEgdmFsdWVzIHRvIGFsbG93IHRoZSB5ZWFyICh3aGVuIHByZXNlbnQpIHRvIGJlIHRyZWF0ZWQgYXMgYSBudW1iZXIuICANCiAgDQpOdW1lcm91cyBjb2x1bW5zIGNvbnRhaW4gdHdvIGNvbnNlY3V0aXZlIHllYXJzIHRvIGluZGljYXRlIGEgeWVhciBsb25nIHBlcmlvZCBzcGFubmluZyB0d28gY2FsZW5kYXIgeWVhcnMuIFRoZXNlIHllYXJzIGFyZSBzZXBhcmF0ZWQgYnkgYSAnLycsIG9yIG9jY2FzaW9uYWxseSBhbm90aGVyIGNoYXJhY3RlciBzdWNoIGFzICItIi4gVGhlc2UgdmFsdWVzIHdpbGwgYmUgcmVwbGFjZWQgYnkgdGhlIGxhdGVzdCBvZiB0aGUgdHdvIHllYXJzLCBhcyB0aGlzIHdvdWxkIG5lY2Vzc2FyaWx5IGJlIHRoZSB5ZWFyIGluIHdoaWNoIHRoZSBkYXRhIHdhcyBjb21wbGV0ZWQgYW5kIHByZXN1bWFibHkgcmVsZWFzZWQuIFRoZSBzZWNvbmQgeWVhciB2YWx1ZSBpbiB0aGVzZSBpbnN0YW5jZXMgaXMgb2Z0ZW4gc3RvcmVkIGFzIHRoZSBsYXN0IHR3byBkaWdpdHMgb2YgdGhlIHllYXIsIGFuZCBhcyBzdWNoIHRoZSBmdWxsIHllYXIgbXVzdCBiZSBpbmZlcnJlZCBmcm9tIHRoZSBjb250ZXh0IG9mIHRoZSBkYXRhLiBTaW5jZSBhbGwgZGF0YSBpcyBmcm9tIHRoZSB5ZWFycyAxOTYwLTIwMjAsIHdlIGNhbiBzYWZlbHkgYXNzdW1lIHRoYXQgaWYgdGhlIGxhc3QgdHdvIGRpZ2l0cyBhcmUgZnJvbSAwLTIwLCB0aGUgZmlyc3QgdHdvIGFyZSAyMCwgYW5kIG90aGVyd2lzZSB0aGUgZmlyc3QgdHdvIGFyZSAxOS4gIA0KICANCkZvciB0aGUgQ2hhbm5lbCBJc2xhbmRzIChjb2RlIENISSksIHRoZSBkYXRhIGZvcm1hdCBmb3IgdGhlIENlbnN1cyBZZWFyLCBhbmQgVml0YWwgUmVnaXN0cmF0aW9uIENvbXBsZXRpb24gaXMgZGlmZmVyZW50LCBhbmQgYXMgc3VjaCB0aGlzIHdpbGwgbmVlZCB0byBiZSBtYW51YWxseSBjb3JyZWN0ZWQuICANCiAgDQoNCmBgYHtyfQ0KIyBUaGlzIGlzIHRoZSBSIGNodW5rIGZvciB0aGUgU2NhbiBJDQojUmVwbGFjZSBhbGwgLi4gdmFsdWVzIHdpdGggYmxhbmtzDQpjb3VudG1pZ3RmJGBQb3B1bGF0aW9uLCB0b3RhbF9TUC5QT1AuVE9UTGBbY291bnRtaWd0ZiRgUG9wdWxhdGlvbiwgdG90YWxfU1AuUE9QLlRPVExgPT0iLi4iXTwtTkENCmNvdW50bWlndGYkYFVIQyBzZXJ2aWNlIGNvdmVyYWdlIGluZGV4X1NILlVIQy5TUlZTLkNWLlhEYFtjb3VudG1pZ3RmJGBVSEMgc2VydmljZSBjb3ZlcmFnZSBpbmRleF9TSC5VSEMuU1JWUy5DVi5YRGA9PSIuLiJdPC1OQQ0KY291bnRtaWd0ZiRgTmV0IG1pZ3JhdGlvbl9TTS5QT1AuTkVUTWBbY291bnRtaWd0ZiRgTmV0IG1pZ3JhdGlvbl9TTS5QT1AuTkVUTWA9PSIuLiJdPC1OQQ0KI1JlbW92ZSB0aGUgUFBQIHN1cnZleSB5ZWFyIGNvbHVtbiwgc2luY2UgaXQgaXMgZW1wdHkNCmNvdW50bWlndGY8LXN1YnNldChjb3VudG1pZ3RmWyFpcy5uYShjb3VudG1pZ3RmJGBOZXQgbWlncmF0aW9uX1NNLlBPUC5ORVRNYCksXSwgc2VsZWN0PS1jKGBQUFAgc3VydmV5IHllYXJgKSkNCiNSZW1vdmUgdGV4dCBpbmRpY2F0aW5nIHRoYXQgdGhlIGJhc2UgeWVhciBpcyBubyBsb25nZXIgcmVsZXZhbnQgZm9yIHRoZSBjb3VudHJ5DQpjb3VudG1pZ3RmJGBOYXRpb25hbCBhY2NvdW50cyBiYXNlIHllYXJgW2NvdW50bWlndGYkYE5hdGlvbmFsIGFjY291bnRzIGJhc2UgeWVhcmA9PSJPcmlnaW5hbCBjaGFpbmVkIGNvbnN0YW50IHByaWNlIGRhdGEgYXJlIHJlc2NhbGVkLiJdPC1OQQ0KDQojRnVuY3Rpb24gdG8gcmV0dXJuIHRoZSBsYXN0IHllYXIgaWYgZ2l2ZW4gYSBwZXJpb2Qgb2YgdHdvIHllYXJzIGFzIGEgc3RyaW5nDQpkZXNsYXNoPC1mdW5jdGlvbih5ZWFyc3RyLGRlbGltID0gIi8iKXsNCiAgI1JldHVybnMgTkEgaWYgdGhlIHN0cmluZyBpcyBhbHJlYWR5IE5BDQogIGlmIChpcy5uYSh5ZWFyc3RyKSl7DQogICAgcmV0dXJuIChOQSkNCiAgfWVsc2V7DQogIGRlbGltdmVjPC1jKDE6bGVuZ3RoKGRlbGltKSkNCiAgbWF0Y2hlZDwtRkFMU0UNCiAgI0ZvciBlYWNoIGRlbGltaXRlciBiZXR3ZWVuIHRoZSB0d28geWVhcnMsIGFzIHNwZWNpZmllZCBieSB0aGUgdXNlcg0KICBmb3IgKGkgaW4gZGVsaW12ZWMpew0KICAgICNJZiB0aGUgZGVsaW1pdGVyIGlzIGZvdW5kIGluIHRoZSBzdHJpbmcNCiAgICBpZihzdHJfZGV0ZWN0KHllYXJzdHIsZGVsaW1baV0pKSB7DQogICAgc2xhc2hsb2M8LXN0cl9sb2NhdGUoeWVhcnN0cixkZWxpbVtpXSlbMV0NCiAgICBtYXRjaGVkPC1UUlVFDQogICAgcmV0dXJuc3RyPC1hcy5udW1lcmljKHN0cl9zdWIoeWVhcnN0cixzbGFzaGxvYysxLHN0cl9sZW5ndGgoeWVhcnN0cikpKQ0KICAgICNJZiB0aGUgbGFzdCB5ZWFyIGluIHRoZSBzdHJpbmcgaXMgb25seSBnaXZlbiBhcyB0aGUgbGFzdCB0d28gZGlnaXRzIG9mIHRoZSB5ZWFyDQogICAgaWYgKHJldHVybnN0ciA8MTAwKXsNCiAgICAgIGlmIChyZXR1cm5zdHIgPDIxKXsNCiAgICAgICAgcmV0dXJuc3RyID0gcmV0dXJuc3RyKzIwMDANCiAgICAgIH1lbHNlew0KICAgICAgICByZXR1cm5zdHIgPSByZXR1cm5zdHIrMTkwMA0KICAgICAgfQ0KICAgIH0NCiAgICANCiAgICByZXR1cm4ocmV0dXJuc3RyKQ0KICB9IGVsc2Ugew0KICB9DQogICAgfQ0KaWYgKG1hdGNoZWQpew0KICAgIA0KICB9IGVsc2Ugew0KICAgIHJldHVybiAoeWVhcnN0cikNCiAgfQ0KICB9DQp9DQojUmVwbGFjZXMgbXVsdGkteWVhciBwZXJpb2RzIGluIHZhcmlvdXMgdmFyaWFibGVzIHdpdGggdGhlIGxhc3QgeWVhciBpbiB0aGUgcGVyaW9kDQpjb3VudG1pZ3RmJGBOYXRpb25hbCBhY2NvdW50cyBiYXNlIHllYXJgPC1hcy5udW1lcmljKGxhcHBseShjb3VudG1pZ3RmJGBOYXRpb25hbCBhY2NvdW50cyBiYXNlIHllYXJgLGRlc2xhc2gsYygiLyIsIi0iKSkpDQpjb3VudG1pZ3RmJGBOYXRpb25hbCBhY2NvdW50cyByZWZlcmVuY2UgeWVhcmA8LWFzLm51bWVyaWMobGFwcGx5KGNvdW50bWlndGYkYE5hdGlvbmFsIGFjY291bnRzIHJlZmVyZW5jZSB5ZWFyYCxkZXNsYXNoLGMoIi8iLCItIikpKQ0KY291bnRtaWd0ZiRgWWVhciBvZiBtb3N0IHJlY2VudCBJbmNvbWUgYW5kIGV4cGVuZGl0dXJlIGRhdGFgPC1hcy5udW1lcmljKGxhcHBseShjb3VudG1pZ3RmJGBZZWFyIG9mIG1vc3QgcmVjZW50IEluY29tZSBhbmQgZXhwZW5kaXR1cmUgZGF0YWAsZGVzbGFzaCxjKCIvIiwiLSIpKSkNCmNvdW50bWlndGYkYExhdGVzdCBob3VzZWhvbGQgc3VydmV5IHllYXJgPC1hcy5udW1lcmljKGxhcHBseShjb3VudG1pZ3RmJGBMYXRlc3QgaG91c2Vob2xkIHN1cnZleSB5ZWFyYCxkZXNsYXNoLGMoIi8iLCItIikpKQ0KY291bnRtaWd0ZiRgTGF0ZXN0IEFncmljdWx0dXJhbCBDZW5zdXMgWWVhcmA8LWFzLm51bWVyaWMobGFwcGx5KGNvdW50bWlndGYkYExhdGVzdCBBZ3JpY3VsdHVyYWwgQ2Vuc3VzIFllYXJgLGRlc2xhc2gsYygiLyIsIi0iKSkpDQpjb3VudG1pZ3RmJGBMYXRlc3QgUG9wdWxhdGlvbiBDZW5zdXMgWWVhcmA8LWFzLm51bWVyaWMobGFwcGx5KGNvdW50bWlndGYkYExhdGVzdCBQb3B1bGF0aW9uIENlbnN1cyBZZWFyYCxkZXNsYXNoLGMoIi8iLCItIikpKQ0KDQojTWFudWFsbHkgY29ycmVjdCBkYXRhIGZvciBDaGFubmVsIElzbGFuZHMNCmNvdW50bWlndGYkYExhdGVzdCBQb3B1bGF0aW9uIENlbnN1cyBZZWFyYFtjb3VudG1pZ3RmJGBDb3VudHJ5IENvZGVgPT0iQ0hJIl0gPC0gMjAxNQ0KY291bnRtaWd0ZiRgVml0YWwgcmVnaXN0cmF0aW9uIGNvbXBsZXRlYFtjb3VudG1pZ3RmJGBDb3VudHJ5IENvZGVgPT0iQ0hJIl0gPC0gIlllcyINCg0KICANCg0KYGBgDQoNCg0KDQoNCg0KIyMgVW5kZXJzdGFuZCANCg0KU3VtbWFyaXNlIHRoZSB0eXBlcyBvZiB2YXJpYWJsZXMgYW5kIGRhdGEgc3RydWN0dXJlcywgY2hlY2sgdGhlIGF0dHJpYnV0ZXMgaW4gdGhlIGRhdGEgYW5kIGFwcGx5IHByb3BlciBkYXRhIHR5cGUgY29udmVyc2lvbnMuIEluIGFkZGl0aW9uIHRvIHRoZSBSIGNvZGVzIGFuZCBvdXRwdXRzLCBleHBsYWluIGJyaWVmbHkgdGhlIHN0ZXBzIHRoYXQgeW91IGhhdmUgdGFrZW4uIEluIHRoaXMgc2VjdGlvbiwgc2hvdyB0aGF0IHlvdSBoYXZlIGZ1bGZpbGxlZCBtaW5pbXVtIHJlcXVpcmVtZW50cyAyLTQuICANCiAgDQpEdWUgdG8gb3JpZ2luYWxseSBiZWluZyBzdG9yZWQgYXMgYSBzdHJpbmcsIHRoZSBjb2x1bW5zIHdoaWNoIHN0b3JlIGEgeWVhciB2YWx1ZSB3aWxsIG5lZWQgdG8gYmUgY29lcmNlZCB0byBhIG51bWVyaWMgdHlwZS4gYWRkaXRpb25hbGx5LCBzb21lIHZhcmlhYmxlcyBoYXZlIGEgY2xlYXIgb3JkZXIgYXMgcGVyIHRoZSBkYXRhIGluc3BlY3Rpb24gc2VjdGlvbiwgYW5kIGFzIHN1Y2ggY2FuIGJlIGNvZXJjZWQgdG8gYSBmYWN0b3Igd2l0aCBsZXZlbHMuICANCg0KDQoNCg0KYGBge3J9DQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBVbmRlcnN0YW5kIFNlY3Rpb24NCiNTaG93IHRoZSBvcmlnaW5hbCBkYXRhIHR5cGVzIGZvciBlYWNoIHZhcmlhYmxlDQpzdHIoY291bnRtaWd0ZikNCiNDb252ZXJ0IHRvIGxldmVsbGVkIGZhY3RvcnMgZm9yIHJlbGV2YW50IHZhcmlhYmxlcw0KY291bnRtaWd0ZiRgRXh0ZXJuYWwgZGVidCBSZXBvcnRpbmcgc3RhdHVzYDwtZmFjdG9yKGNvdW50bWlndGYkYEV4dGVybmFsIGRlYnQgUmVwb3J0aW5nIHN0YXR1c2AsIGxldmVscz1hZGROQShjKE5BLCJFc3RpbWF0ZSIsIlByZWxpbWluYXJ5IiwiQWN0dWFsIikpLCBleGNsdWRlPU5VTEwpDQpjb3VudG1pZ3RmJGBJbmNvbWUgR3JvdXBgPC1mYWN0b3IoY291bnRtaWd0ZiRgSW5jb21lIEdyb3VwYCxsZXZlbHM9YyhOQSwiTG93IGluY29tZSIsICJMb3dlciBtaWRkbGUgaW5jb21lIiwiVXBwZXIgbWlkZGxlIGluY29tZSIsIkhpZ2ggaW5jb21lIiksIGV4Y2x1ZGU9TlVMTCkNCiNyZXBsYWNlIGJsYW5rcyB3aXRoIE5vIGZvciB2aXRhbCByZWdpc3RyYXRpb24sIHRoZW4gY29udmVydCB0byBsZXZlbHMNCmNvdW50bWlndGYkYFZpdGFsIHJlZ2lzdHJhdGlvbiBjb21wbGV0ZWBbaXMubmEoY291bnRtaWd0ZiRgVml0YWwgcmVnaXN0cmF0aW9uIGNvbXBsZXRlYCldPC0iTm8iDQpjb3VudG1pZ3RmJGBWaXRhbCByZWdpc3RyYXRpb24gY29tcGxldGVgPC1mYWN0b3IoY291bnRtaWd0ZiRgVml0YWwgcmVnaXN0cmF0aW9uIGNvbXBsZXRlYCwgbGV2ZWxzPWMoIlllcyIsIk5vIiksIGV4Y2x1ZGU9TlVMTCkNCiNDb252ZXJ0IHllYXJzIHRvIG51bWVyaWMgdHlwZQ0KY291bnRtaWd0ZiRgU3lzdGVtIG9mIE5hdGlvbmFsIEFjY291bnRzYDwtICBhcy5udW1lcmljKHN0cl9zdWIoY291bnRtaWd0ZiRgU3lzdGVtIG9mIE5hdGlvbmFsIEFjY291bnRzYCwxOCwyMSkpDQpjb3VudG1pZ3RmJGBOZXQgbWlncmF0aW9uX1NNLlBPUC5ORVRNYDwtYXMubnVtZXJpYyhjb3VudG1pZ3RmJGBOZXQgbWlncmF0aW9uX1NNLlBPUC5ORVRNYCkNCmNvdW50bWlndGYkYFBvcHVsYXRpb24sIHRvdGFsX1NQLlBPUC5UT1RMYDwtYXMubnVtZXJpYyhjb3VudG1pZ3RmJGBQb3B1bGF0aW9uLCB0b3RhbF9TUC5QT1AuVE9UTGApDQpjb3VudG1pZ3RmJGBVSEMgc2VydmljZSBjb3ZlcmFnZSBpbmRleF9TSC5VSEMuU1JWUy5DVi5YRGA8LWFzLm51bWVyaWMoY291bnRtaWd0ZiRgVUhDIHNlcnZpY2UgY292ZXJhZ2UgaW5kZXhfU0guVUhDLlNSVlMuQ1YuWERgKQ0KI1Nob3cgdXBkYXRlZCBkYXRhIHR5cGVzIGZvciBlYWNoIHZhcmlhYmxlDQpzdHIoY291bnRtaWd0ZikNCmBgYA0KDQoNCg0KIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJSSANCg0KRm9yIHRoZSBwdXJwb3NlcyBvZiBoYXZpbmcgYSB1bmlxdWUgaWRlbnRpZmllciBmb3IgZWFjaCBvYnNlcnZhdGlvbiwgYSBrZXkgd2lsbCBiZSBjcmVhdGVkIGJ5IGNvbWJpbmluZyB0aGUgY291bnRyeSBjb2RlIHdpdGggdGhlIHllYXIgb2YgdGhlIG9ic2VydmF0aW9uLiBUaGlzIHdpbGwgYmUgdXNlZnVsIGZvciBmdXR1cmUgaW5kZXhpbmcgYW5kIHVzaW5nIHRoaXMgZGF0YSBpbiBhIERhdGFiYXNlIE1hbmFnZW1lbnQgU2NoZW1hLiAgDQogIA0KVGhlIDUteWVhciBtaWdyYXRpb24gbnVtYmVycyBmb3IgZWFjaCBjb3VudHJ5IGFyZSBjdXJyZW50bHkgYWJzb2x1dGUgdmFsdWVzLiBUaGlzIG51bWJlciBjb3VsZCBiZSBtb3JlIHVzZWZ1bCBpZiByZXByZXNlbnRlZCBhcyBlaXRoZXIgYSBwcm9wb3J0aW9uIG9mIHRoZSB0b3RhbCBwb3B1bGF0aW9uIG9mIHRoZSBjb3VudHJ5LCBvciBhcyBhIHByb3BvcnRpb24gb2YgdGhlIHRvdGFsIGNoYW5nZSBpbiBwb3B1bGF0aW9uIG92ZXIgdGhhdCBwZXJpb2QuICANCiAgDQpBcyBzdWNoLCB0aGVzZSBwcm9wb3J0aW9ucyB3aWxsIGJlIGNhbGN1bGF0ZWQgZm9yIGVhY2ggZW50cnkgaW4gdGhlIGRhdGFzZXQuICANCiAgDQpGb3IgaW5zdGFuY2VzIHdoZXJlIHRoZSBkYXRhIGZyb20gNSB5ZWFycyBwcmlvciBpcyB1bmF2YWlsYWJsZSwgdGhpcyBmaWVsZCB3aWxsIGJlIGxlZnQgYmxhbmsgKE5BKS4gIA0KICANCkl0IHdpbGwgYWxzbyBiZSB1c2VmdWwgdG8gY3JlYXRlIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgdG8gaW5kaWNhdGUgd2hldGhlciBtaWdyYXRpb24gY29tcHJpc2VzIHRoZSBlbnRpcmV0eSBvciBqdXN0IGEgcG9ydGlvbiBvZiB0aGUgbmV0IHBvcHVsYXRpb24gY2hhbmdlLCBhbmQgaW4gd2hpY2ggZGlyZWN0aW9uIHRoZSBwb3B1bGF0aW9uIGlzIGNoYW5naW5nLiAgDQoNCmBgYHtyfQ0KIyBUaGlzIGlzIHRoZSBSIGNodW5rIGZvciB0aGUgVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJSSANCmNvdW50bWlndGYkS2V5PC1wYXN0ZTAoY291bnRtaWd0ZiRgQ291bnRyeSBDb2RlYCxjb3VudG1pZ3RmJGBPYnNlcnZhdGlvbiBZZWFyYCkNCg0KI1ZlcmlmeSB0aGUga2V5cyBhcmUgdW5pcXVlDQpzdW0oZHVwbGljYXRlZChjb3VudG1pZ3RmJEtleSkpPT0wDQoNCiNDcmVhdGUgYSBzdWJzZXQgb2YgdGhlIGRhdGEsIHdpdGggdGhlIE9ic2VydmF0aW9uIFllYXIgdmFsdWUgc2hpZnRlZCBieSA1DQpjb3VudG1pZzU8LXN1YnNldChjb3VudG1pZ3RmLHNlbGVjdD1jKGBDb3VudHJ5IENvZGVgLCBgT2JzZXJ2YXRpb24gWWVhcmAsIGBQb3B1bGF0aW9uLCB0b3RhbF9TUC5QT1AuVE9UTGApKQ0KY291bnRtaWc1JGBPYnNlcnZhdGlvbiBZZWFyYDwtY291bnRtaWc1JGBPYnNlcnZhdGlvbiBZZWFyYCs1DQpjb3VudG1pZzU8LSBjb3VudG1pZzUgJT4lIHVuaXRlKEtleSwgYENvdW50cnkgQ29kZWAsIGBPYnNlcnZhdGlvbiBZZWFyYCxzZXA9IiIpDQojSm9pbiB0aGUgc3Vic2V0dGVkIGRhdGEgYmFjayBvbnRvIHRoZSBvcmlnaW5hbCwgc2hvd2luZyB0aGUgcG9wdWxhdGlvbiA1IHllYXJzIGFnbw0KY291bnRtaWd0ZjwtbGVmdF9qb2luKGNvdW50bWlndGYsIGNvdW50bWlnNSwgYnk9IktleSIsIHN1ZmZpeD1jKCIiLCIgNVlBIikpDQojQ2FsY3VsYXRlIHRoZSBkaWZmZXJlbmNlIGluIHBvcHVsYXRpb24gb3ZlciA1IHllYXJzDQpjb3VudG1pZ3RmJGA1IFllYXIgUG9wdWxhdGlvbiBDaGFuZ2VgPC1jb3VudG1pZ3RmJGBQb3B1bGF0aW9uLCB0b3RhbF9TUC5QT1AuVE9UTGAtY291bnRtaWd0ZiRgUG9wdWxhdGlvbiwgdG90YWxfU1AuUE9QLlRPVEwgNVlBYA0KI0NhbGN1bGF0ZSB3aGF0IHByb3BvcnRpb24gb2YgdGhlIHRvdGFsIHBvcHVsYXRpb24gbWlncmF0ZWQgdG8vZnJvbSB0aGUgY291bnRyeS9yZWdpb24NCmNvdW50bWlndGYkYE1pZ3JhdGlvbiBQcm9wb3J0aW9uIG9mIFRvdGFsIFBvcHVsYXRpb25gPC1jb3VudG1pZ3RmJGBOZXQgbWlncmF0aW9uX1NNLlBPUC5ORVRNYC9jb3VudG1pZ3RmJGBQb3B1bGF0aW9uLCB0b3RhbF9TUC5QT1AuVE9UTGANCiNDYWxjdWxhdGUgd2hhdCBwcm9wb3J0aW9uIG9mIHRoZSBwb3B1bGF0aW9uIGNoYW5nZSB3YXMgZHVlIHRvIG1pZ3JhdGlvbg0KY291bnRtaWd0ZiRgTWlncmF0aW9uIFByb3BvcnRpb24gb2YgUG9wdWxhdGlvbiBDaGFuZ2VgPC1jb3VudG1pZ3RmJGBOZXQgbWlncmF0aW9uX1NNLlBPUC5ORVRNYC9jb3VudG1pZ3RmJGA1IFllYXIgUG9wdWxhdGlvbiBDaGFuZ2VgDQptaWdwb3BzdGF0dXM8LWMoIkluc3VmZmljaWVudCBEYXRhIiwgIkRlY3JlYXNlIEV4Y2x1c2l2ZWx5IER1ZSB0byBNaWdyYXRpb24iLCAiRGVjcmVhc2UgUGFydGlhbGx5IER1ZSB0byBNaWdyYXRpb24iLCAiSW5jcmVhc2UgRXhjbHVzaXZlbHkgRHVlIHRvIE1pZ3JhdGlvbiIsICJJbmNyZWFzZSBQYXJ0aWFsbHkgRHVlIHRvIE1pZ3JhdGlvbiIsICJEZWNyZWFzZSBEZXNwaXRlIFBvc2l0aXZlIE1pZ3JhdGlvbiIsICJJbmNyZWFzZSBEZXNwaXRlIE5lZ2F0aXZlIE1pZ3JhdGlvbiIsICJObyBOZXQgTWlncmF0aW9uIikNCiNGdW5jdGlvbiB0byBjYXRlZ29yaXNlIHRoZSBpbXBhY3Qgb2YgbWlncmF0aW9uIHVwb24gdGhlIGNoYW5nZSBpbiBwb3B1bGF0aW9uDQptaWdjYXQ8LWZ1bmN0aW9uKG1pZ3Byb3AsIGNoYW5nZXByb3Apew0KICBpZiAoaXMubmEobWlncHJvcCl8aXMubmEoY2hhbmdlcHJvcCkpew0KICAgICNJZiBpbnN1ZmZpY2llbnQgZGF0YSBpcyBhdmFpbGFibGUgYWJvdXQgbWlncmF0aW9uIG9yIHBvcHVsYXRpb24NCiAgICByZXR1cm4gKDEpDQogIH0gZWxzZSB7DQogICAgI0lmIHRoZXJlIGlzIG5vIG5ldCBtaWdyYXRpb24NCiAgICBpZiAoY2hhbmdlcHJvcD09MCkgew0KICAgICAgcmV0dXJuICg4KQ0KICAgIH1lbHNlIHsNCiAgICAjSWYgdGhlIG5ldCBtaWdyYXRpb24gaXMgaW4gdGhlIHNhbWUgZGlyZWN0aW9uIGFzIHRoZSBwb3B1bGF0aW9uIGNoYW5nZQ0KICAgICAgaWYgKGNoYW5nZXByb3A+MCl7DQogICAgICAgICNJZiB0aGUgY2hhbmdlIGluIHBvcHVsYXRpb24gaXMgZXhjbHVzaXZlbHkgZHVlIHRvIG1pZ3JhdGlvbg0KICAgICAgICBpZiAoY2hhbmdlcHJvcD49MSl7DQogICAgICAgICAgI0lmIHRoZSBuZXQgbWlncmF0aW9uIGlzIHBvc2l0aXZlDQogICAgICAgICAgaWYgKG1pZ3Byb3AgPjApIHsNCiAgICAgICAgICAgcmV0dXJuICg0KQ0KICAgICAgICAgICNJZiB0aGUgbmV0IG1pZ3JhdGlvbiBpcyBuZWdhdGl2ZSAgDQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICByZXR1cm4gKDIpICANCiAgICAgICAgICB9DQogICAgICAgICNJZiB0aGUgY2hhbmdlIGluIHBvcHVsYXRpb24gaXMgcGFydGlhbGx5IGR1ZSB0byBtaWdyYXRpb24gIA0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICNJZiB0aGUgbmV0IG1pZ3JhdGlvbiBpcyBwb3NpdGl2ZQ0KICAgICAgICAgIGlmIChtaWdwcm9wID4wKSB7DQogICAgICAgICAgcmV0dXJuICg1KQ0KICAgICAgICAgICNJZiB0aGUgbmV0IG1pZ3JhdGlvbiBpcyBuZWdhdGl2ZSAgICAgIA0KICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgcmV0dXJuICgzKSAgDQogICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICAjSWYgdGhlIG5ldCBtaWdyYXRpb24gaXMgaW4gdGhlIG9wcG9zaXRlIGRpcmVjdGlvbiB0byB0aGUgcG9wdWxhdGlvbiBjaGFuZ2UNCiAgICAgIH0gZWxzZSB7DQogICAgICAgICNJZiB0aGUgbmV0IG1pZ3JhdGlvbiBpcyBuZWdhdGl2ZQ0KICAgICAgICAgIGlmIChtaWdwcm9wPDApew0KICAgICAgICAgICAgcmV0dXJuICg3KQ0KICAgICAgICAjSWYgdGhlIG5ldCBtaWdyYXRpb24gaXMgcG9zaXRpdmUgICAgDQogICAgICAgICAgfSBlbHNlew0KICAgICAgICAgICAgcmV0dXJuICg2KQ0KICAgICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQogIH0NCn0NCiNDcmVhdGUgYSBmYWN0b3IgdG8gY2F0ZWdvcmlzZSB0aGUgbGV2ZWwgb2YgaW1wYWN0IG9mIG1pZ3JhdGlvbiBvbiB0aGUgcG9wdWxhdGlvbiBjaGFuZ2UsIGFuZCB3aGF0IGRpcmVjdGlvbiB0aGUgcG9wdWxhdGlvbiB3YXMgY2hhbmdpbmcgaW4NCmNvdW50bWlndGYkYENoYW5nZSBpbiBQb3B1bGF0aW9uIER1ZSB0byBNaWdyYXRpb25gPC1mYWN0b3IobWFwcGx5KG1pZ2NhdCwgY291bnRtaWd0ZiRgTWlncmF0aW9uIFByb3BvcnRpb24gb2YgVG90YWwgUG9wdWxhdGlvbmAsIGNvdW50bWlndGYkYE1pZ3JhdGlvbiBQcm9wb3J0aW9uIG9mIFBvcHVsYXRpb24gQ2hhbmdlYCksIG9yZGVyZWQ9VFJVRSwgbGFiZWxzPW1pZ3BvcHN0YXR1cykNCg0KYGBgDQoNCg0KIyMJU2NhbiBJSQ0KDQoNCkZvciBhbGwgdmFyaWFibGVzIHdoaWNoIHN0b3JlIGEgeWVhciwgdGhpcyB2YWx1ZSBzaG91bGQgZ2VuZXJhbGx5IGJlIGJldHdlZW4gMTk2MCBhbmQgMjAyMCwgc2luY2UgdGhpcyBpcyB0aGUgdGltZSBwZXJpb2Qgd2hpY2ggdGhlIGRhdGEgY292ZXJzLiBBcyBzdWNoLCBvdXIgb3V0bGllciBjaGVja3MgaGVyZSB3aWxsIGJlIGxvb2tpbmcgZm9yIGFueSB5ZWFyIHZhbHVlIHdoaWNoIGlzIG91dHNpZGUgb2YgdGhpcyByYW5nZS4gIA0KICANClRoZSBVSEMgc2VydmljZSBjb3ZlcmFnZSBpbmRleCBpcyBieSBkZWZpbml0aW9uIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxMDAuIEFzIHN1Y2gsIGl0IHdpbGwgYmUgc2Nhbm5lZCBmb3IgdmFsdWVzIGx5aW5nIG91dHNpZGUgb2YgdGhpcyByYW5nZS4gIA0KICANClRoZSBvbmx5IG90aGVyIG51bWVyaWMgZGF0YSBpbiB0aGlzIGRhdGEgc2V0IGlzIHRoZSBwb3B1bGF0aW9uIGFuZCBtaWdyYXRpb24gZGF0YS4gT25lIG9mIHRoZSBjb21tb24gcmVhc29ucyBmb3IgcmVtb3Zpbmcgb3IgbW9kaWZ5aW5nIG91dGxpZXJzIGlzIHNhbXBsaW5nIGVycm9yLCB3aXRoIHRoZSBvdXRsaWVycyBiZWluZyB1bnJlcHJlc2VudGF0aXZlIG9mIHRoZSBwb3B1bGF0aW9uIGR1ZSB0byB0aGUgbG93IG51bWJlciBvZiBvYnNlcnZhdGlvbnMuIEhvd2V2ZXIgZHVlIHRvIHRoZSBkYXRhc2V0IGNvbnRhaW5pbmcgdGhlIGVudGlyZSBwb3B1bGF0aW9uIChldmVyeSBjb3VudHJ5KSwgZXZlcnkgc2luZ2xlIGRhdGEgcG9pbnQgd291bGQgYmUgcmVwcmVzZW50YXRpdmUgb2YgdGhlIHBvcHVsYXRpb24sIGFuZCBhcyBzdWNoIHdlIGNhbm5vdCByZW1vdmUgb3IgbW9kaWZ5IGFueSBvYnNlcnZhdGlvbnMgZHVlIHRvIHNhbXBsaW5nIGVycm9yLiANCiAgDQpJbnN0ZWFkLCB0aGUgc2Nhbm5pbmcgZm9yIG91dGxpZXJzIHdpbGwgZm9jdXMgdXBvbiB0aG9zZSB3aGljaCB3ZXJlIGR1ZSB0byBkYXRhIGVudHJ5LCBvciBkYXRhIHByb2Nlc3NpbmcgZXJyb3JzOyBhbmQgdGhpcyB3aWxsIGJlIGRvbmUgYnkgc2VhcmNoaW5nIGZvciBsb2dpY2FsbHkgaW1wb3NzaWJsZSB2YWx1ZXMuIEZvciB0aGUgcG9wdWxhdGlvbiB0b3RhbHMgaXQgd2lsbCBvbmx5IGJlIGNoZWNrZWQgdGhhdCB0aGVzZSBhcmUgYWJvdmUgMCBhbmQgZm9yIG5ldCBtaWdyYXRpb24gaXQgd2lsbCBiZSBjaGVja2VkIHRoYXQgdGhlIGFic29sdXRlIHZhbHVlIGlzIG5vdCBncmVhdGVyIHRoYW4gdGhlIHBvcHVsYXRpb24gdG90YWwuICANCiAgDQpTaW5jZSB0aGUgNSB5ZWFyIGFnbyBwb3B1bGF0aW9uIGFuZCB0aGUgNSB5ZWFyIHBvcHVsYXRpb24gY2hhbmdlIGFyZSBkZXJpdmVkIGZyb20gdGhlIHBvcHVsYXRpb24gZGF0YSB3aGljaCBpcyBhbHJlYWR5IGJlaW5nIHNjYW5uZWQsIGlmIHRoZXJlIGFyZSBubyBvdXRsaWVycyBpbiB0aGUgcG9wdWxhdGlvbiB0b3RhbHMsIHRoZW4gdGhpcyBkYXRhIHdpbGwgYmUgZnJlZSBvZiBvdXRsaWVycyB0b28uICANCiAgDQpUaGUgY2FsY3VsYXRlZCBwcm9wb3J0aW9ucyBmcm9tICpUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIElJKiB3aWxsIGJlIGNoZWNrZWQgZm9yIGJvdGggaW1wb3NzaWJsZSwgYW5kIG5vbi11c2VmdWwgdmFsdWVzLiBUaGUgbWlncmF0aW9uIHByb3BvcnRpb24gb2YgdGhlIHRvdGFsIHBvcHVsYXRpb24gbXVzdCBiZSBpbiB0aGUgcmFuZ2UgZnJvbSAtMSB0byAxLCBzaW5jZSBvdGhlcndpc2Ugd291bGQgaW5kaWNhdGUgYSBncmVhdGVyIHByb3BvcnRpb24gdGhhbiB0aGUgdG90YWwgY291bnRyeSdzIHBvcHVsYXRpb24gbGVhdmluZyBvciBlbnRlcmluZyB0aGUgY291bnRyeS4gIA0KICANCkhvd2V2ZXIsIHRoZSBtaWdyYXRpb24gcHJvcG9ydGlvbiBvZiB0aGUgcG9wdWxhdGlvbiBjaGFuZ2UgaXMgdXNlZnVsIHJlZ2FyZGxlc3Mgb2Ygd2hhdCB2YWx1ZSBpdCB0YWtlcywgYW5kIGR1ZSB0byBiZWluZyBjYWxjdWxhdGVkIGZyb20gdmFyaWFibGVzIHdoaWNoIGFyZSBhbHJlYWR5IGJlaW5nIHNjYW5uZWQsIHRoZXJlIHdpbGwgYmUgbm8gb3V0bGllcnMgaGVyZSBiZXlvbmQgdGhvc2UgaWRlbnRpZmllZCBpbiBvdGhlciB2YXJpYWJsZXMuICANCg0KDQoNCmBgYHtyfQ0KIyBUaGlzIGlzIHRoZSBSIGNodW5rIGZvciB0aGUgU2NhbiBJSQ0KI0NyZWF0ZSBhIGxpc3Qgb2YgZWFjaCB2YXJpYWJsZSBjb250YWluaW5nIGEgeWVhciB3aGljaCBtdXN0IGJlIHNjYW5uZWQgZm9yIG91dGxpZXJzDQp5ZWFydmFybGlzdDwtYygiTmF0aW9uYWwgYWNjb3VudHMgYmFzZSB5ZWFyIiwgIk5hdGlvbmFsIGFjY291bnRzIHJlZmVyZW5jZSB5ZWFyIiwgIlN5c3RlbSBvZiBOYXRpb25hbCBBY2NvdW50cyIsICJMYXRlc3QgUG9wdWxhdGlvbiBDZW5zdXMgWWVhciIsICJMYXRlc3QgaG91c2Vob2xkIHN1cnZleSB5ZWFyIiwgIlllYXIgb2YgbW9zdCByZWNlbnQgSW5jb21lIGFuZCBleHBlbmRpdHVyZSBkYXRhIiwgIkxhdGVzdCBBZ3JpY3VsdHVyYWwgQ2Vuc3VzIFllYXIiLCAiTGF0ZXN0IGluZHVzdHJpYWwgZGF0YSIsICJMYXRlc3QgdHJhZGUgZGF0YSIsICJPYnNlcnZhdGlvbiBZZWFyIikNCiNDcmVhdGUgYSBsaXN0IG9mIGFsbCBub24teWVhciB2YXJpYWJsZXMgd2hpY2ggbXVzdCBiZSBzY2FubmVkIGZvciBvdXRsaWVycw0Kb3V0bGllcnZhcmxpc3Q8LWFwcGVuZCh5ZWFydmFybGlzdCxjKCJQb3B1bGF0aW9uLCB0b3RhbF9TUC5QT1AuVE9UTCIsIk5ldCBtaWdyYXRpb25fU00uUE9QLk5FVE0iLCJVSEMgc2VydmljZSBjb3ZlcmFnZSBpbmRleF9TSC5VSEMuU1JWUy5DVi5YRCIsICJNaWdyYXRpb24gUHJvcG9ydGlvbiBvZiBUb3RhbCBQb3B1bGF0aW9uIikpDQoNCiNJbml0aWFsaXNlIHZlY3RvcnMgZm9yIHN0b3Jpbmcgb3V0bGllciBkYXRhDQpvdXRsaWVyY291bnQ8LXJlcCgwLDE0KQ0Kb3V0bGllcnZhbHM8LXJlcChOQSwxNCkNCnZhcmxlbmd0aDwtYygxOmxlbmd0aCh5ZWFydmFybGlzdCkpDQoNCiNPYnRhaW4gb3V0bGllciBkYXRhIGZvciBlYWNoIHllYXIgdmFyaWFibGUsIHdpdGggTkEgYmVpbmcgaWdub3JlZA0KZm9yIChpIGluIHZhcmxlbmd0aCl7DQogIHRoaXNvdXRsaWVyPC1hcy5kYXRhLmZyYW1lKGNvdW50bWlndGZbeWVhcnZhcmxpc3RbaV1dKVsoY291bnRtaWd0Zlt5ZWFydmFybGlzdFtpXV08MTk2MHxjb3VudG1pZ3RmW3llYXJ2YXJsaXN0W2ldXT4yMDIwKSYgIWlzLm5hKGNvdW50bWlndGZbeWVhcnZhcmxpc3RbaV1dKV0NCiAgb3V0bGllcmNvdW50W2ldPC1sZW5ndGgodGhpc291dGxpZXIpDQogIGlmIChvdXRsaWVyY291bnRbaV0gPjApew0KICBvdXRsaWVydmFsc1tpXTwtcGFzdGUodW5pcXVlKHRoaXNvdXRsaWVyKSl9DQp9DQojT2J0YWluIG91dGxpZXIgZGF0YSBmb3IgcG9wdWxhdGlvbiB0b3RhbA0KcG9wb3V0bGllcjwtYXMuZGF0YS5mcmFtZShjb3VudG1pZ3RmWyJQb3B1bGF0aW9uLCB0b3RhbF9TUC5QT1AuVE9UTCJdKVshY291bnRtaWd0ZlsiUG9wdWxhdGlvbiwgdG90YWxfU1AuUE9QLlRPVEwiXT4wICYgIWlzLm5hKGNvdW50bWlndGZbIlBvcHVsYXRpb24sIHRvdGFsX1NQLlBPUC5UT1RMIl0pXQ0Kb3V0bGllcmNvdW50WzExXTwtbGVuZ3RoKHBvcG91dGxpZXIpDQppZiAob3V0bGllcmNvdW50WzExXSA+MCl7DQogIG91dGxpZXJ2YWxzWzEyXTwtcGFzdGUodW5pcXVlKHBvcG91dGxpZXIpKX0NCg0KI09idGFpbiBvdXRsaWVyIGRhdGEgZm9yIG5ldCBtaWdyYXRpb24NCm5ldG1pZ291dGxpZXI8LWFzLmRhdGEuZnJhbWUoY291bnRtaWd0ZlsiTmV0IG1pZ3JhdGlvbl9TTS5QT1AuTkVUTSJdKVsoYWJzKGNvdW50bWlndGZbIk5ldCBtaWdyYXRpb25fU00uUE9QLk5FVE0iXSk+Y291bnRtaWd0ZlsiUG9wdWxhdGlvbiwgdG90YWxfU1AuUE9QLlRPVEwiXSkmICFpcy5uYShjb3VudG1pZ3RmWyJOZXQgbWlncmF0aW9uX1NNLlBPUC5ORVRNIl0pICYgIWlzLm5hKGNvdW50bWlndGZbIlBvcHVsYXRpb24sIHRvdGFsX1NQLlBPUC5UT1RMIl0pXQ0Kb3V0bGllcmNvdW50WzEyXTwtbGVuZ3RoKG5ldG1pZ291dGxpZXIpDQppZiAob3V0bGllcmNvdW50WzEyXSA+MCl7DQogIG91dGxpZXJ2YWxzWzEyXTwtcGFzdGUodW5pcXVlKG5ldG1pZ291dGxpZXIpKX0NCg0KI09idGFpbiBvdXRsaWVyIGRhdGEgZm9yIFVIQyBpbmRleA0KVUhDb3V0bGllcjwtYXMuZGF0YS5mcmFtZShjb3VudG1pZ3RmWyJVSEMgc2VydmljZSBjb3ZlcmFnZSBpbmRleF9TSC5VSEMuU1JWUy5DVi5YRCJdKVsoY291bnRtaWd0ZlsiVUhDIHNlcnZpY2UgY292ZXJhZ2UgaW5kZXhfU0guVUhDLlNSVlMuQ1YuWEQiXT4xMDB8Y291bnRtaWd0ZlsiVUhDIHNlcnZpY2UgY292ZXJhZ2UgaW5kZXhfU0guVUhDLlNSVlMuQ1YuWEQiXTwwKSAmICFpcy5uYShjb3VudG1pZ3RmWyJVSEMgc2VydmljZSBjb3ZlcmFnZSBpbmRleF9TSC5VSEMuU1JWUy5DVi5YRCJdKV0NCm91dGxpZXJjb3VudFsxM108LWxlbmd0aChVSENvdXRsaWVyKQ0KaWYgKG91dGxpZXJjb3VudFsxM10gPjApew0KICBvdXRsaWVydmFsc1sxM108LXBhc3RlKHVuaXF1ZShVSENvdXRsaWVyKSl9DQoNCiNPYnRhaW4gb3V0bGllciBkYXRhIGZvciBtaWdyYXRpb24gYXMgYSBwcm9wb3J0aW9uIG9mIHRoZSB0b3RhbCBwb3B1bGF0aW9uDQptaWd0b3RvdXRsaWVyPC1hcy5kYXRhLmZyYW1lKGNvdW50bWlndGZbIk1pZ3JhdGlvbiBQcm9wb3J0aW9uIG9mIFRvdGFsIFBvcHVsYXRpb24iXSlbKGNvdW50bWlndGZbIk1pZ3JhdGlvbiBQcm9wb3J0aW9uIG9mIFRvdGFsIFBvcHVsYXRpb24iXT4xfGNvdW50bWlndGZbIk1pZ3JhdGlvbiBQcm9wb3J0aW9uIG9mIFRvdGFsIFBvcHVsYXRpb24iXTwoLTEpKSAmICFpcy5uYShjb3VudG1pZ3RmWyJNaWdyYXRpb24gUHJvcG9ydGlvbiBvZiBUb3RhbCBQb3B1bGF0aW9uIl0pXQ0Kb3V0bGllcmNvdW50WzE0XTwtbGVuZ3RoKG1pZ3RvdG91dGxpZXIpDQppZiAob3V0bGllcmNvdW50WzE0XSA+MCl7DQogIG91dGxpZXJ2YWxzWzE0XTwtcGFzdGUodW5pcXVlKG1pZ3RvdG91dGxpZXIpKX0NCg0KI1N1bW1hcmlzZSB0aGUgb3V0bGllciBkYXRhDQp5ZWFyb3V0bGllcnN1bW1hcnk8LWRhdGEuZnJhbWUob3V0bGllcmNvdW50LCBvdXRsaWVydmFscykNCnJvd25hbWVzKHllYXJvdXRsaWVyc3VtbWFyeSk8LW91dGxpZXJ2YXJsaXN0DQpjb2xuYW1lcyh5ZWFyb3V0bGllcnN1bW1hcnkpPC1jKCJOdW1iZXIgb2YgT3V0bGllcnMiLCAiT3V0bGllciBWYWx1ZShzKSIpDQphcy50YWJsZShhcy5tYXRyaXgoeWVhcm91dGxpZXJzdW1tYXJ5KSkNCg0KDQpgYGANCg0KQXMgY2FuIGJlIHNlZW4gZnJvbSB0aGlzIHN1bW1hcnkgb2Ygb3V0bGllcnMsIHRoZXJlIGFyZSBvbmx5IG91dGxpZXJzIHByZXNlbnQgaW4gdGhlIG5hdGlvbmFsIGFjY291bnRzIGJhc2UgeWVhciwgYW5kIHRoZSBsYXRlc3QgcG9wdWxhdGlvbiBjZW5zdXMgeWVhci4gVGhlc2UgdmFsdWVzIG9mIDE5NTQgYW5kIDE5NDMgaG93ZXZlciwgc3RpbGwgYXBwZWFyIHRvIGJlIHJlYXNvbmFibGUgeWVhcnMgZm9yIGRhdGEgdG8gaGF2ZSBiZWVuIG9idGFpbmVkIGZyb20gZm9yIHRoZSBXb3JsZCBCYW5rLiANCg0KRm9yIHRoZSBuYXRpb25hbCBhY2NvdW50cyBiYXNlIHllYXIsIGl0IGlzIHF1aXRlIHBvc3NpYmxlIGZvciB0aGUgYWNjb3VudHMgdG8gYmUgY2FsY3VsYXRlZCB1c2luZyB2YWx1ZXMgZnJvbSBhcyBmYXIgYmFjayBhcyAxOTU0LiANCg0KU2ltaWxhcmx5LCB0aGUgbGF0ZXN0IHBvcHVsYXRpb24gY2Vuc3VzIGJlaW5nIGluIDE5NDMgaXMgYWxzbyBwb3NzaWJsZSBmb3IgYSBjb3VudHJ5LCBlc3BlY2lhbGx5IG9uZSB3aGljaCBtYXkgYmUgdW5kZXJnb2luZyBzb21lIGNvbmZsaWN0LiAgDQoNCkFzIHN1Y2gsIHRoZXNlIG91dGxpZXJzIHdpbGwgYmUgbGVmdCBpbiB0aGUgZGF0YSwgYXMgdGhleSBzdGlsbCBhcHBlYXIgdG8gYmUgYWNjdXJhdGUgYW5kIHVzZWZ1bC4gIA0KDQoNCg0KIyMJVHJhbnNmb3JtIA0KDQoNCk9uZSBtaWdodCB3YW50IHRvIHBlcmZvcm0gYSBsaW5lYXIgcmVncmVzc2lvbiB0byBpbnZlc3RpZ2F0ZSBpZiB0aGVyZSBpcyBhIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgcG9wdWxhdGlvbiBvZiBhIGNvdW50cnkgYW5kIHRoZSBVSEMgc2VydmljZSBjb3ZlcmFnZSBpbmRleC4gSG93ZXZlciBhIGtleSByZXF1aXJlbWVudCBmb3IgbGluZWFyIHJlZ3Jlc3Npb24gaXMgdGhhdCB0aGUgZGF0YSBpcyBub3JtYWxseSBkaXN0cmlidXRlZC4gQXMgc3VjaCwgaXQgd2lsbCBuZWVkIHRvIGJlIGNoZWNrZWQgd2hldGhlciB0aGVzZSB0d28gdmFyaWFibGVzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZDsgYW5kIGlmIHRoZXkgYXJlIG5vdCwgdGhlbiBhbiBhcHByb3ByaWF0ZSB0cmFuc2Zvcm1hdGlvbiB3aWxsIG5lZWQgdG8gYmUgYXBwbGllZC4gIA0KDQpUaGVpciBub3JtYWxpdHkgY2FuIGJlIGNoZWNrZWQgYnkgYSB2aXN1YWwgaW5zcGVjdGlvbiBvZiBhIGhpc3RvZ3JhbSBvZiB0aGUgZGF0YSwgYW5kIGl0J3MgcXVpY2tseSBjbGVhciB0aGF0IHRoZSBQb3B1bGF0aW9uIGRhdGEgaXMgaGVhdmlseSByaWdodCBza2V3ZWQuIFRoZSBVSEMgaW5kZXggaG93ZXZlciBkb2VzIGFwcGVhciB0byBiZSByb3VnaGx5IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCBhbmQgYXMgc3VjaCB3aWxsIHJlcXVpcmUgbm8gdHJhbnNmb3JtYXRpb24uICANCg0KRm9ydHVuYXRlbHksIHRoZSBCb3gtQ294IHRyYW5zZm9ybWF0aW9uIGNhbiBiZSBhcHBsaWVkIHRvIHRoZSBkYXRhIGhlcmUgdG8gZW5zdXJlIGl0IGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIHRvIGFsbG93IGZvciBsaW5lYXIgcmVncmVzc2lvbi4gVGhlIGxhbWJkYSB2YWx1ZSBmb3IgdGhpcyB0cmFuc2Zvcm1hdGlvbiB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgY2FsY3VsYXRlZCB0aHJvdWdoIHRoZSB1c2Ugb2YgdGhlICpmb3JlY2FzdCogcGFja2FnZS4gIA0KDQoNCg0KYGBge3J9DQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBUcmFuc2Zvcm0gU2VjdGlvbg0KI0NyZWF0ZSBoaXN0b2dyYW1zIHRvIGNoZWNrIHRoZSBwb3B1bGF0aW9uIHRvdGFsIGFuZCBVSEMgaW5kZXggZm9yIG5vcm1hbGl0eQ0KaGlzdChjb3VudG1pZ3RmJGBQb3B1bGF0aW9uLCB0b3RhbF9TUC5QT1AuVE9UTGAsIG1haW49Ikhpc3RvZ3JhbSBvZiBUb3RhbCBQb3B1bGF0aW9uIiwgeGxhYj0iUG9wdWxhdGlvbiIpDQpoaXN0KGNvdW50bWlndGYkYFVIQyBzZXJ2aWNlIGNvdmVyYWdlIGluZGV4X1NILlVIQy5TUlZTLkNWLlhEYCwgbWFpbj0iSGlzdG9ncmFtIG9mIFVIQyBTZXJ2aWNlIENvdmVyYWdlIEluZGV4IiwgeGxhYj0iVUhDIFNlcnZpY2UgQ292ZXJhZ2UgSW5kZXgiKQ0KI0NyZWF0ZSBhIEJveC1Db3ggdHJhbnNmb3JtYXRpb24gb2YgdGhlIHBvcHVsYXRpb24gdmFyaWFibGUgdG8gZW5zdXJlIGl0IGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGZvciBsaW5lYXIgcmVncmVzc2lvbg0KY291bnRtaWd0ZiRgQm94LUNveCBQb3B1bGF0aW9uYDwtQm94Q294KGNvdW50bWlndGYkYFBvcHVsYXRpb24sIHRvdGFsX1NQLlBPUC5UT1RMYCwgbGFtYmRhPSJhdXRvIikNCiNDcmVhdGUgaGlzdG9ncmFtIG9mIEJveC1Db3ggbm9ybWFsaXNlZCBwb3B1bGF0aW9uDQpoaXN0KGNvdW50bWlndGYkYEJveC1Db3ggUG9wdWxhdGlvbmAsIG1haW49Ikhpc3RvZ3JhbSBvZiBCb3gtQ294IE5vcm1hbGlzZWQgUG9wdWxhdGlvbiIsIHhsYWIgPSAiQm94LUNveCBOb3JtYWxpc2VkIFBvcHVsYXRpb24iKQ0KDQoNCmBgYA0KDQoNCk5PVEU6IE5vdGUgdGhhdCBzb21ldGltZXMgdGhlIG9yZGVyIG9mIHRoZSB0YXNrcyBtYXkgYmUgZGlmZmVyZW50IHRoYW4gdGhlIG9yZGVyIGdpdmVuIGhlcmUuIEZvciBleGFtcGxlLCB5b3UgbWF5IG5lZWQgdG8gdGlkeSB0aGUgZGF0YSBzZXRzIGZpcnN0IHRvIGJlIGFibGUgdG8gY3JlYXRlIHRoZSBjb21tb24ga2V5IHRvIG1lcmdlLiBUaGVyZWZvcmUsIGZvciBzdWNoIGNhc2VzIHlvdSBtYXkgaGF2ZSBhIGRpZmZlcmVudCBvcmRlcmluZyBvZiB0aGUgc2VjdGlvbnMuICANCg0KQW55IGZ1cnRoZXIgb3Igb3B0aW9uYWwgcHJlLXByb2Nlc3NpbmcgdGFza3MgY2FuIGJlIGFkZGVkIHRvIHRoZSB0ZW1wbGF0ZSB1c2luZyBhbiBhZGRpdGlvbmFsIHNlY3Rpb24gaW4gdGhlIFIgTWFya2Rvd24gZmlsZS4gTWFrZSBzdXJlIHlvdXIgY29kZSBpcyB2aXNpYmxlICh3aXRoaW4gdGhlIG1hcmdpbiBvZiB0aGUgcGFnZSkuIERvIG5vdCB1c2UgVmlldygpIHRvIHNob3cgeW91ciBkYXRhLCBpbnN0ZWFkIGdpdmUgaGVhZGVycyAodXNpbmcgaGVhZCgpICkNCg0KIyMgUmVmZXJlbmNlcw0KDQpSU3R1ZGlvIDIwMjAsICpSIE1hcmtkb3duIFJlZmVyZW5jZSBHdWlkZSosIFJTdHVkaW8sIHZpZXdlZCAyNyBNYXJjaCAyMDIwLCA8W2xpbmtdKGh0dHBzOi8vcnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTUvMDMvcm1hcmtkb3duLXJlZmVyZW5jZS5wZGYpPiAgDQpEb2xndW4sIEEgMjAyMCwgKk1vZHVsZSA0KiwgUk1JVCBVbml2ZXJzaXR5LCB2aWV3ZWQgNiBKdW5lIDIwMjAsIDxbbGlua10oaHR0cDovL3JhcmUtcGhvZW5peC0xNjE2MTAuYXBwc3BvdC5jb20vc2VjdXJlZC9Nb2R1bGVfMDQuaHRtbCk+ICANCkRvbGd1biwgQSAyMDIwLCAqTW9kdWxlIDUqLCBSTUlUIFVuaXZlcnNpdHksIHZpZXdlZCA2IEp1bmUgMjAyMCwgPFtsaW5rXShodHRwOi8vcmFyZS1waG9lbml4LTE2MTYxMC5hcHBzcG90LmNvbS9zZWN1cmVkL01vZHVsZV8wNS5odG1sKT4gIA0KRG9sZ3VuLCBBIDIwMjAsICpNb2R1bGUgNiosIFJNSVQgVW5pdmVyc2l0eSwgdmlld2VkIDYgSnVuZSAyMDIwLCA8W2xpbmtdKGh0dHA6Ly9yYXJlLXBob2VuaXgtMTYxNjEwLmFwcHNwb3QuY29tL3NlY3VyZWQvTW9kdWxlXzA2Lmh0bWwpPiAgDQpEb2xndW4sIEEgMjAyMCwgKk1vZHVsZSA3KiwgUk1JVCBVbml2ZXJzaXR5LCB2aWV3ZWQgNiBKdW5lIDIwMjAsIDxbbGlua10oaHR0cDovL3JhcmUtcGhvZW5peC0xNjE2MTAuYXBwc3BvdC5jb20vc2VjdXJlZC9Nb2R1bGVfMDcuaHRtbCk+ICANCkRvbGd1biwgQSAyMDIwLCAqTW9kdWxlIDgqLCBSTUlUIFVuaXZlcnNpdHksIHZpZXdlZCA2IEp1bmUgMjAyMCwgPFtsaW5rXShodHRwOi8vcmFyZS1waG9lbml4LTE2MTYxMC5hcHBzcG90LmNvbS9zZWN1cmVkL01vZHVsZV8wOC5odG1sKT4gIA0KV29ybGQgQmFuayBHcm91cCAyMDIwLCAqSGVhbHRoIE51dHJpdGlvbiBhbmQgUG9wdWxhdGlvbiBTdGF0aXN0aWNzKiwgV29ybGQgQmFuayBHcm91cCwgdmlld2VkIDQgSnVuZSAyMDIwLCA8W2xpbmtdKGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9zb3VyY2UvaGVhbHRoLW51dHJpdGlvbi1hbmQtcG9wdWxhdGlvbi1zdGF0aXN0aWNzIyk+ICANCldvcmxkIEJhbmsgR3JvdXAgMjAyMCwgKldvcmxkIERldmVsb3BtZW50IEluZGljYXRvcnMqLCBXb3JsZCBCYW5rIEdyb3VwLCB2aWV3ZWQgMzAgTWF5IDIwMjAsIDxbbGlua10oaHR0cDovL2RhdGFiYW5rLndvcmxkYmFuay5vcmcvZGF0YS9kb3dubG9hZC9XRElfY3N2LnppcCk+ICANCkJhZ2xpbiwgSiAyMDE5LCAqTW9kdWxlIDkqLCBSTUlUIFVuaXZlcnNpdHksIHZpZXdlZCA2IEp1bmUgMjAyMCwgPFtsaW5rXShodHRwczovL2FzdHJhbC10aGVvcnktMTU3NTEwLmFwcHNwb3QuY29tL3NlY3VyZWQvTUFUSDEzMjRfTW9kdWxlXzA5Lmh0bWwpPiAgDQpJQkFOIDIwMjAsICpMaXN0IG9mIGNvdW50cnkgY29kZXMqLCBJQkFOLCB2aWV3ZWQgNyBKdW5lIDIwMjAsIDxbbGlua10oaHR0cHM6Ly93d3cuaWJhbi5jb20vY291bnRyeS1jb2Rlcyk+ICANCldvcmxkIEJhbmsgR3JvdXAgMjAyMCwgKk5hdGlvbmFsIEFjY291bnRzIEJhc2UgWWVhciosIFdvcmxkIEJhbmsgRGF0YSBDYXRhbG9nLCB2aWV3ZWQgNiBKdW5lIDIwMjAsIDxbbGlua10oaHR0cHM6Ly9kYXRhY2F0YWxvZy53b3JsZGJhbmsub3JnL25hdGlvbmFsLWFjY291bnRzLWJhc2UteWVhcik+ICANCk9FQ0QgMjAyMCwgKk1hcmtldCBQcmljZXMgLSBTTkEqLCBHbG9zc2FyeSBvZiBTdGF0aXN0aWNhbCBUZXJtcywgdmlld2VkIDcgSnVuZSAyMDIwLCA8W2xpbmtdKGh0dHBzOi8vc3RhdHMub2VjZC5vcmcvZ2xvc3NhcnkvZGV0YWlsLmFzcD9JRD0xNjA4KT4gIA0KV29ybGQgQmFuayBHcm91cCAyMDIwLCAqSG93IERvZXMgdGhlIFdvcmxkIEJhbmsgQ2xhc3NpZnkgQ291bnRyaWVzKiwgV29ybGQgQmFuayBEYXRhIEhlbHBkZXNrLCB2aWV3ZWQgNyBKdW5lIDIwMjAsIDxbbGlua10oaHR0cHM6Ly9kYXRhaGVscGRlc2sud29ybGRiYW5rLm9yZy9rbm93bGVkZ2ViYXNlL2FydGljbGVzLzM3ODgzNC1ob3ctZG9lcy10aGUtd29ybGQtYmFuay1jbGFzc2lmeS1jb3VudHJpZXMpPiAgDQpXb3JsZCBCYW5rIEdyb3VwIDIwMjAsICpXaGF0IGlzIHRoZSBERUMgY29udmVyc2lvbiBmYWN0b3I/KiwgV29ybGQgQmFuayBEYXRhIEhlbHBkZXNrLCB2aWV3ZWQgNyBKdW5lIDIwMjAsIDxbbGlua10oaHR0cHM6Ly9kYXRhaGVscGRlc2sud29ybGRiYW5rLm9yZy9rbm93bGVkZ2ViYXNlL2FydGljbGVzLzc3OTM1LXdoYXQtaXMtdGhlLWRlYy1jb252ZXJzaW9uLWZhY3Rvcik+ICANCldvcmxkIEJhbmsgR3JvdXAgMjAyMCwgKkJhbGFuY2Ugb2YgUGF5bWVudHMgTWFudWFsIEluIFVzZSosIFdvcmxkIEJhbmsgRGF0YSBDYXRhbG9nLCB2aWV3ZWQgNiBKdW5lIDIwMjAsIDxbbGlua10oaHR0cHM6Ly9kYXRhY2F0YWxvZy53b3JsZGJhbmsub3JnL2JhbGFuY2UtcGF5bWVudHMtbWFudWFsLXVzZSk+ICANCldvcmxkIEJhbmsgR3JvdXAgMjAyMCwgKkV4dGVybmFsIERlYnQgUmVwb3J0aW5nIFN0YXR1cyosIFdvcmxkIEJhbmsgRGF0YSBDYXRhbG9nLCB2aWV3ZWQgNiBKdW5lIDIwMjAsIDxbbGlua10oaHR0cHM6Ly9kYXRhY2F0YWxvZy53b3JsZGJhbmsub3JnL2V4dGVybmFsLWRlYnQtcmVwb3J0aW5nLXN0YXR1cyk+ICANCldvcmxkIEJhbmsgR3JvdXAgMjAyMCwgKkdvdmVybm1lbnQgRmluYW5jZSBBY2NvdW50aW5nKiwgV29ybGQgQmFuayBEYXRhIENhdGFsb2csIHZpZXdlZCA2IEp1bmUgMjAyMCwgPFtsaW5rXShodHRwczovL2RhdGFjYXRhbG9nLndvcmxkYmFuay5vcmcvZ292ZXJubWVudC1maW5hbmNlLWFjY291bnRpbmcpPiAgDQpXb3JsZCBCYW5rIEdyb3VwIDIwMjAsICpTcGVjaWFsIERhdGEgRGlzc2VtaW5hdGlvbiBTdGFuZGFyZCosIFdvcmxkIEJhbmsgRGF0YSBDYXRhbG9nLCB2aWV3ZWQgNiBKdW5lIDIwMjAsIDxbbGlua10oaHR0cHM6Ly9kYXRhY2F0YWxvZy53b3JsZGJhbmsub3JnL3NwZWNpYWwtZGF0YS1kaXNzZW1pbmF0aW9uLXN0YW5kYXJkKT4gIA0KV29ybGQgQmFuayBHcm91cCAyMDIwLCAqVml0YWwgUmVnaXN0cmF0aW9uIFN5c3RlbSBDb3ZlcmFnZSosIFdvcmxkIEJhbmsgRGF0YSBDYXRhbG9nLCB2aWV3ZWQgNiBKdW5lIDIwMjAsIDxbbGlua10oaHR0cHM6Ly9kYXRhY2F0YWxvZy53b3JsZGJhbmsub3JnL3ZpdGFsLXJlZ2lzdHJhdGlvbi1zeXN0ZW0tY292ZXJhZ2UpPiAgDQpTY2hvbGVyLCBGIDIwMjAsICpEYXRhYmFzZSBDb25jZXB0czogVGhlIFJlbGF0aW9uYWwgTW9kZWwgMSosIElTWVMxMDU1IFdlZWsgMiBMZWFybmluZyBNYXRlcmlhbHMvQWN0aXZpdGllcywgdmlld2VkIDYgSnVuZSAyMDIwLCA8W2xpbmtdKGh0dHBzOi8vcm1pdC5pbnN0cnVjdHVyZS5jb20vY291cnNlcy82NzA0Ny9maWxlcy8xMTI0OTk0OC9kb3dubG9hZD93cmFwPTEpPg0KDQoNCjxicj4NCjxicj4NCg==