Executive Summary

In this analysis I will utilise the OECD dataset on Goverment Expenditure on Education for the years 2010-2015. I will join this dataset with the World Bank Cuntry classification and apply suitable Data Preprocessing techniques to reveal patterns in spending in the combined data.

The World Bank data is processed first. This dataset classifies 211 countries by region and income group. It is originally in excel format with multiple sheets and headers. After loading using the readxl library, I filter and subset this dataset and use the mutate function to create factors of “Income Group” and “Region”. A scan and treatment for erroneous data and missing values is perfromed and the results provided.

Next, the OECD dataset containing Education spending data for Years 2010-2015 is processed. This dataset is not in tidy format as variables are stored as observations. The dataset is loaded, columns re-named, to align with the world bank data, and the dplyr spread function is used to create new variables for the year 2015. A scan and treatment for erroneous data and missing values is performed and the results provided. Additionally, I utilise the rowMeans function and the mutate function to impute the average spend value for that country where a spend value is missing for a particular country-year.

Finally, both datasets are joined. A scan for missing values and outliers is made. Lastly the distribution of produce distributions for the indicators used and transform one of the indicator variables to produce a more normal distribution.

Data Sources:

World Bank

https://datahelpdesk.worldbank.org/knowledgebase/articles/906519-world-bank-country-and-lending-groups, download date “25/10/2019”, license: https://datacatalog.worldbank.org/public-licenses#cc-other

OECD

Source: Education at a glance: Educational finance indicators, https://data.oecd.org/eduresource/public-spending-on-education.htm, download date “25/10/2019”

Required packages

# clean the environment
rm(list=ls())
library(readr)
library(dplyr)
library(tidyr)
library(Hmisc) 
library(ggplot2) 
library(knitr) 
library(readxl)
library(outliers)

Data

Load the World Bank country classifications.

country_worldbank <- read_excel("data/country_class_worldbank.xls", sheet = "List of economies", skip = 3)

-
/
                                                                                                                                
New names:
* x -> x..1
* x -> x..2
cat(" Dimensions: " , dim(country_worldbank))
 Dimensions:  275 9
head(country_worldbank)

Relevant Columns in world bankdataset: Economy, Code, Region, Income group

DATA - continued

Load the OECD Eduaction Expenditure dataset

# read in OECD eduaction expenditure data
education  <- read_csv("data/OECD_ED_Spend_1.csv")
Parsed with column specification:
cols(
  LOCATION = col_character(),
  INDICATOR = col_character(),
  SUBJECT = col_character(),
  MEASURE = col_character(),
  FREQUENCY = col_character(),
  TIME = col_double(),
  Value = col_double(),
  `Flag Codes` = col_character()
)
cat(" Dimensions: " , dim(education))
 Dimensions:  5401 8
head(education)

Relevant Columns in OECD Education dataset: LOCATION, INDICATOR, TIME, Value

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.

World Bank Country classifications dataset.

Verify Data types - all character columns Columns of interst: “Economy” rename -> “CountryName” “Code” rename -> “CountryCode” “Income group” reaname -> “IncomeGroup” to remove space. Alter to be a factor - ordered. “Region” column to remain unchanged. Alter to be a factor - ordered. All other columns to be removed,

cat("############## country_worldbank  ##################\n")
############## country_worldbank  ##################
str(country_worldbank)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   275 obs. of  9 variables:
 $ x..1            : chr  "x" "1" "2" "3" ...
 $ x..2            : chr  "x" NA NA NA ...
 $ Economy         : chr  "x" "Afghanistan" "Albania" "Algeria" ...
 $ Code            : chr  "x" "AFG" "ALB" "DZA" ...
 $ X               : chr  "x" NA NA NA ...
 $ Region          : chr  "x" "South Asia" "Europe & Central Asia" "Middle East & North Africa" ...
 $ Income group    : chr  "x" "Low income" "Upper middle income" "Upper middle income" ...
 $ Lending category: chr  "x" "IDA" "IBRD" "IBRD" ...
 $ Other           : chr  "x" "HIPC" NA NA ...
describe(country_worldbank)
country_worldbank 

 9  Variables      275  Observations
----------------------------------------------------------------------------------------------------------------------------------
x..1 
       n  missing distinct 
     269        6      223 

lowest : 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         10                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        100                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       101                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       102                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
highest: Geographic classifications in this table cover all income levels.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         IDA countries are those that lack the financial ability to borrow from IBRD. IDA credits are deeply concessional—interest-free loans and grants for programs aimed at boosting economic growth and improving living conditions. IBRD loans are noncessional. Blend countries are eligible for IDA credits because of their low per capita incomes but are also eligible for IBRD because they are financially creditworthy.                                                                                                                                                                                                                                                                                                                                                                                                                                                               Note: The term country, used interchangeably with economy, does not imply political independence but refers to any territory for which authorities report separate social or economic statistics. Income classifications set on 1 July 2019 remain in effect until 1 July 2020. Argentina, which was temporarily unclassified in July 2016 pending release of revised national accounts statistics, was classified as upper middle income for FY17 as of 29 September 2016 based on alternative conversion factors. Also effective 29 September 2016, Syrian Arab Republic is reclassified from IBRD lending category to IDA-only. On 29 March 2017, new country codes were introduced to align World Bank 3-letter codes with ISO 3-letter codes: Andorra (AND), Dem. Rep. Congo (COD), Isle of Man (IMN), Kosovo (XKX), Romania (ROU), Timor-Leste (TLS), and West Bank and Gaza (PSE). This table classifies all World Bank member countries (189), and all other economies with populations of more than 30,000. For operational and analytical purposes, economies are divided among income groups according to 2018 gross national income (GNI) per capita, calculated using the World Bank Atlas method. The groups are: low income, $1,025 or less; lower middle income, $1,026 - 3,995; upper middle income, $3,996 - 12,375; and high income, $12,375 or more. The effective operational cutoff for IDA eligibility is $1,175 or less.                                                                                                                                                                                                                                                                                                                                    x                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
----------------------------------------------------------------------------------------------------------------------------------
x..2 
       n  missing distinct    value 
       1      274        1        x 
            
Value      x
Frequency  1
Proportion 1
----------------------------------------------------------------------------------------------------------------------------------
Economy 
       n  missing distinct 
     265       10      265 

lowest : Afghanistan    Albania        Algeria        American Samoa Andorra       
highest: World          x              Yemen, Rep.    Zambia         Zimbabwe      
----------------------------------------------------------------------------------------------------------------------------------
Code 
       n  missing distinct 
     265       10      265 

lowest : ABW AFG AGO ALB AND, highest: XKX YEM ZAF ZMB ZWE
----------------------------------------------------------------------------------------------------------------------------------
X 
       n  missing distinct    value 
       1      274        1        x 
            
Value      x
Frequency  1
Proportion 1
----------------------------------------------------------------------------------------------------------------------------------
Region 
       n  missing distinct 
     219       56        8 
                                                                                                                      
Value             East Asia & Pacific      Europe & Central Asia  Latin America & Caribbean Middle East & North Africa
Frequency                          38                         58                         42                         21
Proportion                      0.174                      0.265                      0.192                      0.096
                                                                                                                      
Value                   North America                 South Asia         Sub-Saharan Africa                          x
Frequency                           3                          8                         48                          1
Proportion                      0.014                      0.037                      0.219                      0.005
----------------------------------------------------------------------------------------------------------------------------------
Income group 
       n  missing distinct 
     219       56        5 
                                                                                                              
Value              High income          Low income Lower middle income Upper middle income                   x
Frequency                   80                  31                  47                  60                   1
Proportion               0.365               0.142               0.215               0.274               0.005
----------------------------------------------------------------------------------------------------------------------------------
Lending category 
       n  missing distinct 
     219       56        5 
                                        
Value         .. Blend  IBRD   IDA     x
Frequency     74    17    68    59     1
Proportion 0.338 0.078 0.311 0.269 0.005
----------------------------------------------------------------------------------------------------------------------------------
Other 
       n  missing distinct 
      59      216        3 
                            
Value        EMU  HIPC     x
Frequency     19    39     1
Proportion 0.322 0.661 0.017
----------------------------------------------------------------------------------------------------------------------------------
# select, rename and filter.
country_worldbank <- country_worldbank %>% 
  select("Economy", "Code", "Region", "Income group") %>% 
  rename("CountryName" = "Economy", "CountryCode" = "Code","IncomeGroup" =  "Income group") %>% 
  filter(!is.na(Region) & !is.na(`IncomeGroup`) & nchar(CountryCode) ==3  )
# Set region and Income Group as factors.  Order by Region.
country_worldbank <- country_worldbank %>% 
  mutate(Region = factor(as.character(Region), 
                            labels = c("E.Asia", "EUR.Cen.Asia", "Lat.Amer.Carr", "M.East.N.Africa", 
                                       "N.Amer", "Sth.Asia", "Sub.S.Africa" ),
                            levels = c("East Asia & Pacific", "Europe & Central Asia",
                                       "Latin America & Caribbean","Middle East & North Africa",
                                       "North America", "South Asia", "Sub-Saharan Africa")),
         IncomeGroup = factor(IncomeGroup, 
                              labels = c("High","Upper.Mid", "Low.Mid", "Low"), 
                              levels = c("High income","Upper middle income", "Lower middle income", "Low income")))        
# dispaly and verify factors
cat("Regions:")
Regions:
levels(country_worldbank$Region)
[1] "E.Asia"          "EUR.Cen.Asia"    "Lat.Amer.Carr"   "M.East.N.Africa" "N.Amer"          "Sth.Asia"        "Sub.S.Africa"   
cat("Income Groups: ")
Income Groups: 
levels(country_worldbank$IncomeGroup)
[1] "High"      "Upper.Mid" "Low.Mid"   "Low"      
head(country_worldbank)
cat(" Dimensions: " , dim(country_worldbank))
 Dimensions:  218 4

worldbank dataset now has four columns and 218 observations Two factors have been created.

OECD Education dataset.

Verify Data types - all character columns Columns of interst: “LOCATON” rename -> “CountryCode” “MEASURE” filter to only include -> PC_GDP “SUBJECT” rename -> IndicatorCode. filter to only include ->“PRY_NTRY”, “TRY”" “TIME” column to remain unchanged for now.

cat("\n\n################# oecd education   #####################\n")


################# oecd education   #####################
str(education)
Classes ‘spec_tbl_df’, ‘tbl_df’, ‘tbl’ and 'data.frame':    5401 obs. of  8 variables:
 $ LOCATION  : chr  "AUT" "AUT" "AUT" "AUT" ...
 $ INDICATOR : chr  "EDUEXP" "EDUEXP" "EDUEXP" "EDUEXP" ...
 $ SUBJECT   : chr  "TRY" "TRY" "TRY" "TRY" ...
 $ MEASURE   : chr  "USD_STUDENT" "USD_STUDENT" "USD_STUDENT" "USD_STUDENT" ...
 $ FREQUENCY : chr  "A" "A" "A" "A" ...
 $ TIME      : num  1995 2000 2005 2008 2009 ...
 $ Value     : num  NA NA NA NA NA ...
 $ Flag Codes: chr  "M" "M" "M" "M" ...
 - attr(*, "spec")=
  .. cols(
  ..   LOCATION = col_character(),
  ..   INDICATOR = col_character(),
  ..   SUBJECT = col_character(),
  ..   MEASURE = col_character(),
  ..   FREQUENCY = col_character(),
  ..   TIME = col_double(),
  ..   Value = col_double(),
  ..   `Flag Codes` = col_character()
  .. )
head(education) 
describe(education)
education 

 8  Variables      5401  Observations
----------------------------------------------------------------------------------------------------------------------------------
LOCATION 
       n  missing distinct 
    5401        0       46 

lowest : ARG AUS AUT BEL BRA, highest: SVN SWE TUR USA ZAF
----------------------------------------------------------------------------------------------------------------------------------
INDICATOR 
       n  missing distinct    value 
    5401        0        1   EDUEXP 
                 
Value      EDUEXP
Frequency    5401
Proportion      1
----------------------------------------------------------------------------------------------------------------------------------
SUBJECT 
       n  missing distinct 
    5401        0        5 
                                                                                
Value      EARLYCHILDEDU           PRY      PRY_NTRY           SRY           TRY
Frequency           1077          1068          1100          1052          1104
Proportion         0.199         0.198         0.204         0.195         0.204
----------------------------------------------------------------------------------------------------------------------------------
MEASURE 
       n  missing distinct 
    5401        0        2 
                                  
Value           PC_GDP USD_STUDENT
Frequency         2715        2686
Proportion       0.503       0.497
----------------------------------------------------------------------------------------------------------------------------------
FREQUENCY 
       n  missing distinct    value 
    5401        0        1        A 
               
Value         A
Frequency  5401
Proportion    1
----------------------------------------------------------------------------------------------------------------------------------
TIME 
       n  missing distinct     Info     Mean      Gmd      .05      .10      .25      .50      .75      .90      .95 
    5401        0       12    0.993     2009    6.421     1995     2000     2008     2011     2014     2015     2016 
                                                                                  
Value       1995  2000  2005  2008  2009  2010  2011  2012  2013  2014  2015  2016
Frequency    443   444   452   452   450   452   450   444   450   452   452   460
Proportion 0.082 0.082 0.084 0.084 0.083 0.084 0.083 0.082 0.083 0.084 0.084 0.085
----------------------------------------------------------------------------------------------------------------------------------
Value 
        n   missing  distinct      Info      Mean       Gmd       .05       .10       .25       .50       .75       .90       .95 
     2487      2914      2251         1      4247      5653 6.763e-01 9.816e-01 1.692e+00 4.200e+00 8.131e+03 1.163e+04 1.538e+04 

lowest :     0.000     0.072     0.073     0.074     0.086, highest: 27578.869 29328.235 30003.244 45800.558 48906.889
----------------------------------------------------------------------------------------------------------------------------------
Flag Codes 
       n  missing distinct    value 
    2914     2487        1        M 
               
Value         M
Frequency  2914
Proportion    1
----------------------------------------------------------------------------------------------------------------------------------
# rename character columns and subset charcater columns plus numeric values for years 2010-2015 
keep_cols_education = c("CountryName", "CountryCode", "IndicatorCode")
years <- paste(2010:2015)
keep_cols_education = c(keep_cols_education, years)
# rename coumns and filte to include only the indicator codes for  
#  "primary to post secondary non-tertiary" and "Tertiary". 
education <- education %>% 
  rename(Measure = MEASURE, IndicatorCode = SUBJECT, CountryCode = LOCATION, Time = TIME) %>%
  select(CountryCode, Measure, IndicatorCode, Time, Value) %>% 
  filter(Measure == "PC_GDP" & IndicatorCode %in% c("PRY_NTRY", "TRY") & Time %in% years)
head(education)
cat(" Dimensions: " , dim(education))
 Dimensions:  552 5

education datset now has five columns and 552 observations

Tidy & Manipulate Data I

Check if data is tidy: Exah variable in its own column. Ecah observation in its own row. Check observation for Australia and USA

country_worldbank %>% filter(CountryCode %in% c("AUS", "USA") )

Data is in tidy format. One observation, no variables in columns

education %>% filter(CountryCode %in% c("AUS", "USA")  & Time > 2013)

Data is NOT in tidy format. Time column needs to be spread out. Indicator codes to be summed inot one value fr each country/year

# Checking the number of NA values for each variable.  
colSums(is.na(education))
  CountryCode       Measure IndicatorCode          Time         Value 
            0             0             0             0           112 
# we see 112 missing values that can be dropped
education <-  education[complete.cases(education), ]
# sum the percentage spent on education  for each country, year
# count the number of records the sum to filter when 
education <- education  %>% group_by(CountryCode, Measure, Time) %>% 
  summarise(code_count = n(), ED_PCG = sum(Value)) %>% 
  filter(code_count == 2) %>% 
  select(-code_count ) 
# now spread the data to 
education  <- education  %>% 
  spread(Time, value =ED_PCG, drop = TRUE, fill = NA)
head(education) 

Now data is in tidy format.

Tidy & Manipulate Data II

In OECD Education dataset.. Create / mutate the average of all Education expenditure values for row. Thsn aerage is used to impute missing values for years with no value for pecentage spent on education.

# Checking the number of NA values for each variable. 
colSums(is.na(education))
CountryCode     Measure        2010        2011        2012        2013        2014        2015 
          0           0          12          11           4           1           3           4 
# imputation of means where NAs exist for value in years 
education$col_avg = rowMeans(education[, years], na.rm = TRUE)
education <- education %>% mutate(`2010` = coalesce(`2010`,col_avg ), 
                              `2011` = coalesce(`2011`,col_avg ), 
                              `2012` = coalesce(`2012`,col_avg ), 
                              `2013` = coalesce(`2013`,col_avg ), 
                              `2014` = coalesce(`2014`,col_avg ), 
                              `2015` = coalesce(`2015`,col_avg ))
# we still ahve some NAs that can be dropped later.
colSums(is.na(education))
CountryCode     Measure        2010        2011        2012        2013        2014        2015     col_avg 
          0           0           0           0           0           0           0           0           0 

join the datasets

data <- left_join(country_worldbank, education, by = c("CountryCode"), suffix = c("", ".EDUCATION") )
head(data)

Scan I

Scan the data for missing values, inconsistencies and obvious errors. In this step, you should fulfil the minimum requirement #7. In addition to the R codes and outputs, explain your methodology (i.e. explain why you have chosen that methodology and the actions that you have taken to handle these values) and communicate your results clearly.

  1. Key columns are“CountryName” and “CountryCode”. verify NAs do not exist in these columns
  2. SCAN for empty values in year columns
  3. remove observatins with any empty values for years 2010-2015
# verify dimensions and NAs
dim(data)
[1] 218  12
colSums(is.na(data))
CountryName CountryCode      Region IncomeGroup     Measure        2010        2011        2012        2013        2014 
          0           0           0           0         176         176         176         176         176         176 
       2015     col_avg 
        176         176 
# key columns are "CountryName" and "CountryCode".
# verify NAs do not exist in these columns 
colSums(is.na(data[,0:4]))
CountryName CountryCode      Region IncomeGroup 
          0           0           0           0 
# SCAN for  empty values in year columns
data %>% filter(is.na(`2010`) & is.na(`2011`)& is.na(`2012`)& is.na(`2013`)& is.na(`2014`) & is.na(`2015`)  )
#drop these out of the datset
data <- data %>% filter(!is.na(`2010`) | !is.na(`2011`) | !is.na(`2012`) | !is.na(`2013`) | !is.na(`2014`) | !is.na(`2015`)  )
colSums(is.na(data))
CountryName CountryCode      Region IncomeGroup     Measure        2010        2011        2012        2013        2014 
          0           0           0           0           0           0           0           0           0           0 
       2015     col_avg 
          0           0 

Scan II

  1. produce bioxplots of all values for years 2010-2015
  2. visually determin 211 has an outlier
  3. utilise outliers package
# plot a 
boxplot(data$`2010`)

boxplot(data$`2011`)

boxplot(data$`2012`)

boxplot(data$`2013`)

boxplot(data$`2014`)

boxplot(data$`2015`)

y = data$`2011`

Transform

  1. produce histogarm of 2011 data for education spend
  2. log 2011 data an dproduce histogram.
# his of 2011 data 
hist(data$`2011`)

# transform with log and plot hist.
hist(log(data$`2011`))

LS0tCnRpdGxlOiAiRGF0YSBQcmVwcm9jZXNzaW5nIFRlY2huaXF1ZXMiCnN1YnRpdGxlOiAiV29ybGQgQmFuayBhbmQgT0VDRCBkYXRhIGZvciAyMDEwLTIwMTUiCmF1dGhvcjogIk1BVEggMjM0OSAtIFBhdWwgTWNLaWUgKHMzNzY3MTMwKSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgojIyMjRXhlY3V0aXZlIFN1bW1hcnkgCkluIHRoaXMgYW5hbHlzaXMgSSB3aWxsIHV0aWxpc2UgdGhlIE9FQ0QgZGF0YXNldCBvbiBHb3Zlcm1lbnQgRXhwZW5kaXR1cmUgb24gRWR1Y2F0aW9uIGZvciB0aGUgeWVhcnMgMjAxMC0yMDE1LiBJIHdpbGwgam9pbiB0aGlzIGRhdGFzZXQgd2l0aCB0aGUgV29ybGQgQmFuayBDdW50cnkgY2xhc3NpZmljYXRpb24gYW5kIGFwcGx5IHN1aXRhYmxlIERhdGEgUHJlcHJvY2Vzc2luZyB0ZWNobmlxdWVzIHRvIHJldmVhbCBwYXR0ZXJucyBpbiBzcGVuZGluZyAgaW4gdGhlIGNvbWJpbmVkIGRhdGEuCgpUaGUgIFdvcmxkIEJhbmsgZGF0YSBpcyBwcm9jZXNzZWQgZmlyc3QuICBUaGlzIGRhdGFzZXQgY2xhc3NpZmllcyAyMTEgY291bnRyaWVzIGJ5IHJlZ2lvbiBhbmQgaW5jb21lIGdyb3VwLiBJdCBpcyBvcmlnaW5hbGx5IGluIGV4Y2VsIGZvcm1hdCB3aXRoIG11bHRpcGxlIHNoZWV0cyBhbmQgaGVhZGVycy4gQWZ0ZXIgbG9hZGluZyB1c2luZyB0aGUgcmVhZHhsIGxpYnJhcnksICBJIGZpbHRlciBhbmQgc3Vic2V0IHRoaXMgZGF0YXNldCBhbmQgdXNlIHRoZSBtdXRhdGUgZnVuY3Rpb24gdG8gY3JlYXRlIGZhY3RvcnMgb2YgIkluY29tZSBHcm91cCIgYW5kICJSZWdpb24iLiAgQSBzY2FuIGFuZCB0cmVhdG1lbnQgZm9yIGVycm9uZW91cyBkYXRhIGFuZCBtaXNzaW5nIHZhbHVlcyBpcyBwZXJmcm9tZWQgYW5kIHRoZSByZXN1bHRzIHByb3ZpZGVkLgoKTmV4dCwgdGhlIE9FQ0QgZGF0YXNldCBjb250YWluaW5nIEVkdWNhdGlvbiBzcGVuZGluZyBkYXRhIGZvciBZZWFycyAyMDEwLTIwMTUgaXMgcHJvY2Vzc2VkLiAgVGhpcyBkYXRhc2V0IGlzIG5vdCBpbiB0aWR5IGZvcm1hdCBhcyB2YXJpYWJsZXMgYXJlIHN0b3JlZCBhcyBvYnNlcnZhdGlvbnMuICBUaGUgZGF0YXNldCBpcyBsb2FkZWQsIGNvbHVtbnMgcmUtbmFtZWQsIHRvIGFsaWduIHdpdGggdGhlIHdvcmxkIGJhbmsgZGF0YSwgYW5kIHRoZSBkcGx5ciBzcHJlYWQgZnVuY3Rpb24gaXMgdXNlZCB0byBjcmVhdGUgbmV3IHZhcmlhYmxlcyBmb3IgdGhlIHllYXIgMjAxNS4gIEEgc2NhbiBhbmQgdHJlYXRtZW50IGZvciBlcnJvbmVvdXMgZGF0YSBhbmQgbWlzc2luZyB2YWx1ZXMgaXMgcGVyZm9ybWVkIGFuZCB0aGUgcmVzdWx0cyBwcm92aWRlZC4gIEFkZGl0aW9uYWxseSwgIEkgdXRpbGlzZSB0aGUgcm93TWVhbnMgZnVuY3Rpb24gYW5kIHRoZSBtdXRhdGUgZnVuY3Rpb24gdG8gaW1wdXRlIHRoZSBhdmVyYWdlIHNwZW5kIHZhbHVlIGZvciB0aGF0IGNvdW50cnkgd2hlcmUgYSBzcGVuZCB2YWx1ZSBpcyBtaXNzaW5nIGZvciBhIHBhcnRpY3VsYXIgY291bnRyeS15ZWFyLgoKRmluYWxseSwgYm90aCBkYXRhc2V0cyBhcmUgam9pbmVkLiBBIHNjYW4gZm9yIG1pc3NpbmcgdmFsdWVzIGFuZCBvdXRsaWVycyBpcyBtYWRlLiBMYXN0bHkgdGhlIGRpc3RyaWJ1dGlvbiBvZiBwcm9kdWNlIGRpc3RyaWJ1dGlvbnMgZm9yIHRoZSBpbmRpY2F0b3JzIHVzZWQgYW5kIHRyYW5zZm9ybSBvbmUgb2YgdGhlIGluZGljYXRvciB2YXJpYWJsZXMgdG8gcHJvZHVjZSBhIG1vcmUgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gIAoKIyMjIERhdGEgU291cmNlczoKIyMjIFdvcmxkIEJhbmsgCmh0dHBzOi8vZGF0YWhlbHBkZXNrLndvcmxkYmFuay5vcmcva25vd2xlZGdlYmFzZS9hcnRpY2xlcy85MDY1MTktd29ybGQtYmFuay1jb3VudHJ5LWFuZC1sZW5kaW5nLWdyb3VwcywgZG93bmxvYWQgZGF0ZSAiMjUvMTAvMjAxOSIsCmxpY2Vuc2U6IGh0dHBzOi8vZGF0YWNhdGFsb2cud29ybGRiYW5rLm9yZy9wdWJsaWMtbGljZW5zZXMjY2Mtb3RoZXIKCiMjIyBPRUNEICAKU291cmNlOiBFZHVjYXRpb24gYXQgYSBnbGFuY2U6IEVkdWNhdGlvbmFsIGZpbmFuY2UgaW5kaWNhdG9ycywgaHR0cHM6Ly9kYXRhLm9lY2Qub3JnL2VkdXJlc291cmNlL3B1YmxpYy1zcGVuZGluZy1vbi1lZHVjYXRpb24uaHRtLCAKZG93bmxvYWQgZGF0ZSAiMjUvMTAvMjAxOSIKCiMjIyMgUmVxdWlyZWQgcGFja2FnZXMgCmBgYHtyLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRX0KIyBjbGVhbiB0aGUgZW52aXJvbm1lbnQKcm0obGlzdD1scygpKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KEhtaXNjKSAKbGlicmFyeShnZ3Bsb3QyKSAKbGlicmFyeShrbml0cikgCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KG91dGxpZXJzKQpgYGAKCiMjIERhdGEKIyMjIyBMb2FkIHRoZSBXb3JsZCBCYW5rIGNvdW50cnkgY2xhc3NpZmljYXRpb25zLgoKYGBge3J9CmNvdW50cnlfd29ybGRiYW5rIDwtIHJlYWRfZXhjZWwoImRhdGEvY291bnRyeV9jbGFzc193b3JsZGJhbmsueGxzIiwgc2hlZXQgPSAiTGlzdCBvZiBlY29ub21pZXMiLCBza2lwID0gMykKY2F0KCIgRGltZW5zaW9uczogIiAsIGRpbShjb3VudHJ5X3dvcmxkYmFuaykpCmBgYAoKYGBge3J9CmhlYWQoY291bnRyeV93b3JsZGJhbmspCmBgYApSZWxldmFudCBDb2x1bW5zIGluIHdvcmxkIGJhbmtkYXRhc2V0OiBFY29ub215LCBDb2RlLCBSZWdpb24sIEluY29tZSBncm91cAoKCiMjIyBEQVRBIC0gY29udGludWVkCiMjIyMgTG9hZCB0aGUgT0VDRCBFZHVhY3Rpb24gRXhwZW5kaXR1cmUgZGF0YXNldApgYGB7cn0KIyByZWFkIGluIE9FQ0QgZWR1YWN0aW9uIGV4cGVuZGl0dXJlIGRhdGEKZWR1Y2F0aW9uICA8LSByZWFkX2NzdigiZGF0YS9PRUNEX0VEX1NwZW5kXzEuY3N2IikKY2F0KCIgRGltZW5zaW9uczogIiAsIGRpbShlZHVjYXRpb24pKQpgYGAKCgpgYGB7cn0KaGVhZChlZHVjYXRpb24pCmBgYApSZWxldmFudCBDb2x1bW5zIGluIE9FQ0QgRWR1Y2F0aW9uIGRhdGFzZXQ6IExPQ0FUSU9OLCBJTkRJQ0FUT1IsIFRJTUUsIFZhbHVlIAoKCiMjIyBVTkRFUlNUQU5EClN1bW1hcmlzZSB0aGUgdHlwZXMgb2YgdmFyaWFibGVzIGFuZCBkYXRhIHN0cnVjdHVyZXMsIGNoZWNrIHRoZSBhdHRyaWJ1dGVzIGluIHRoZSBkYXRhIGFuZCBhcHBseSBwcm9wZXIgZGF0YSB0eXBlIGNvbnZlcnNpb25zLiBJbiBhZGRpdGlvbiB0byB0aGUgUiBjb2RlcyBhbmQgb3V0cHV0cywgZXhwbGFpbiBicmllZmx5IHRoZSBzdGVwcyB0aGF0IHlvdSBoYXZlIHRha2VuLiBJbiB0aGlzIHNlY3Rpb24sIHNob3cgdGhhdCB5b3UgaGF2ZSBmdWxmaWxsZWQgbWluaW11bSByZXF1aXJlbWVudHMgMi00LgoKIyMjIyBXb3JsZCBCYW5rIENvdW50cnkgY2xhc3NpZmljYXRpb25zIGRhdGFzZXQuClZlcmlmeSBEYXRhIHR5cGVzIC0gYWxsIGNoYXJhY3RlciBjb2x1bW5zCkNvbHVtbnMgb2YgaW50ZXJzdDoKIkVjb25vbXkiIHJlbmFtZSAtPiAiQ291bnRyeU5hbWUiCiJDb2RlIiByZW5hbWUgLT4gIkNvdW50cnlDb2RlIiAKIkluY29tZSBncm91cCIgcmVhbmFtZSAtPiAiSW5jb21lR3JvdXAiIHRvIHJlbW92ZSBzcGFjZS4gIEFsdGVyIHRvIGJlIGEgZmFjdG9yIC0gb3JkZXJlZC4KIlJlZ2lvbiIgY29sdW1uIHRvIHJlbWFpbiB1bmNoYW5nZWQuICBBbHRlciB0byBiZSBhIGZhY3RvciAtIG9yZGVyZWQuCiAgQWxsIG90aGVyIGNvbHVtbnMgdG8gYmUgcmVtb3ZlZCwKCmBgYHtyLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRX0KY2F0KCIjIyMjIyMjIyMjIyMjIyBjb3VudHJ5X3dvcmxkYmFuayAgIyMjIyMjIyMjIyMjIyMjIyMjXG4iKQpzdHIoY291bnRyeV93b3JsZGJhbmspCmRlc2NyaWJlKGNvdW50cnlfd29ybGRiYW5rKQoKIyBzZWxlY3QsIHJlbmFtZSBhbmQgZmlsdGVyLgpjb3VudHJ5X3dvcmxkYmFuayA8LSBjb3VudHJ5X3dvcmxkYmFuayAlPiUgCiAgc2VsZWN0KCJFY29ub215IiwgIkNvZGUiLCAiUmVnaW9uIiwgIkluY29tZSBncm91cCIpICU+JSAKICByZW5hbWUoIkNvdW50cnlOYW1lIiA9ICJFY29ub215IiwgIkNvdW50cnlDb2RlIiA9ICJDb2RlIiwiSW5jb21lR3JvdXAiID0gICJJbmNvbWUgZ3JvdXAiKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShSZWdpb24pICYgIWlzLm5hKGBJbmNvbWVHcm91cGApICYgbmNoYXIoQ291bnRyeUNvZGUpID09MyAgKQoKIyBTZXQgcmVnaW9uIGFuZCBJbmNvbWUgR3JvdXAgYXMgZmFjdG9ycy4gIE9yZGVyIGJ5IFJlZ2lvbi4KY291bnRyeV93b3JsZGJhbmsgPC0gY291bnRyeV93b3JsZGJhbmsgJT4lIAogIG11dGF0ZShSZWdpb24gPSBmYWN0b3IoYXMuY2hhcmFjdGVyKFJlZ2lvbiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiRS5Bc2lhIiwgIkVVUi5DZW4uQXNpYSIsICJMYXQuQW1lci5DYXJyIiwgIk0uRWFzdC5OLkFmcmljYSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTi5BbWVyIiwgIlN0aC5Bc2lhIiwgIlN1Yi5TLkFmcmljYSIgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkVhc3QgQXNpYSAmIFBhY2lmaWMiLCAiRXVyb3BlICYgQ2VudHJhbCBBc2lhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxhdGluIEFtZXJpY2EgJiBDYXJpYmJlYW4iLCJNaWRkbGUgRWFzdCAmIE5vcnRoIEFmcmljYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOb3J0aCBBbWVyaWNhIiwgIlNvdXRoIEFzaWEiLCAiU3ViLVNhaGFyYW4gQWZyaWNhIikpLAogICAgICAgICBJbmNvbWVHcm91cCA9IGZhY3RvcihJbmNvbWVHcm91cCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkhpZ2giLCJVcHBlci5NaWQiLCAiTG93Lk1pZCIsICJMb3ciKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkhpZ2ggaW5jb21lIiwiVXBwZXIgbWlkZGxlIGluY29tZSIsICJMb3dlciBtaWRkbGUgaW5jb21lIiwgIkxvdyBpbmNvbWUiKSkpICAgICAgICAKCiMgZGlzcGFseSBhbmQgdmVyaWZ5IGZhY3RvcnMKY2F0KCJSZWdpb25zOiIpCmxldmVscyhjb3VudHJ5X3dvcmxkYmFuayRSZWdpb24pCmNhdCgiSW5jb21lIEdyb3VwczogIikKbGV2ZWxzKGNvdW50cnlfd29ybGRiYW5rJEluY29tZUdyb3VwKQoKaGVhZChjb3VudHJ5X3dvcmxkYmFuaykKY2F0KCIgRGltZW5zaW9uczogIiAsIGRpbShjb3VudHJ5X3dvcmxkYmFuaykpCmBgYAp3b3JsZGJhbmsgZGF0YXNldCBub3cgaGFzIGZvdXIgY29sdW1ucyBhbmQgMjE4IG9ic2VydmF0aW9ucwpUd28gZmFjdG9ycyBoYXZlIGJlZW4gY3JlYXRlZC4KCiMjIyMgT0VDRCBFZHVjYXRpb24gZGF0YXNldC4KVmVyaWZ5IERhdGEgdHlwZXMgLSBhbGwgY2hhcmFjdGVyIGNvbHVtbnMKQ29sdW1ucyBvZiBpbnRlcnN0OgoiTE9DQVRPTiIgcmVuYW1lIC0+ICJDb3VudHJ5Q29kZSIgCiJNRUFTVVJFIiBmaWx0ZXIgdG8gb25seSBpbmNsdWRlIC0+IFBDX0dEUAoiU1VCSkVDVCIgcmVuYW1lIC0+IEluZGljYXRvckNvZGUuIGZpbHRlciB0byBvbmx5IGluY2x1ZGUgLT4iUFJZX05UUlkiLCAiVFJZIiIKIlRJTUUiIGNvbHVtbiB0byByZW1haW4gdW5jaGFuZ2VkIGZvciBub3cuCgpgYGB7ciwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0V9CmNhdCgiXG5cbiMjIyMjIyMjIyMjIyMjIyMjIG9lY2QgZWR1Y2F0aW9uICAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjXG4iKQpzdHIoZWR1Y2F0aW9uKQpoZWFkKGVkdWNhdGlvbikgCmRlc2NyaWJlKGVkdWNhdGlvbikKCiMgcmVuYW1lIGNoYXJhY3RlciBjb2x1bW5zIGFuZCBzdWJzZXQgY2hhcmNhdGVyIGNvbHVtbnMgcGx1cyBudW1lcmljIHZhbHVlcyBmb3IgeWVhcnMgMjAxMC0yMDE1IAprZWVwX2NvbHNfZWR1Y2F0aW9uID0gYygiQ291bnRyeU5hbWUiLCAiQ291bnRyeUNvZGUiLCAiSW5kaWNhdG9yQ29kZSIpCnllYXJzIDwtIHBhc3RlKDIwMTA6MjAxNSkKa2VlcF9jb2xzX2VkdWNhdGlvbiA9IGMoa2VlcF9jb2xzX2VkdWNhdGlvbiwgeWVhcnMpCgojIHJlbmFtZSBjb3VtbnMgYW5kIGZpbHRlIHRvIGluY2x1ZGUgb25seSB0aGUgaW5kaWNhdG9yIGNvZGVzIGZvciAgCiMgICJwcmltYXJ5IHRvIHBvc3Qgc2Vjb25kYXJ5IG5vbi10ZXJ0aWFyeSIgYW5kICJUZXJ0aWFyeSIuIAplZHVjYXRpb24gPC0gZWR1Y2F0aW9uICU+JSAKICByZW5hbWUoTWVhc3VyZSA9IE1FQVNVUkUsIEluZGljYXRvckNvZGUgPSBTVUJKRUNULCBDb3VudHJ5Q29kZSA9IExPQ0FUSU9OLCBUaW1lID0gVElNRSkgJT4lCiAgc2VsZWN0KENvdW50cnlDb2RlLCBNZWFzdXJlLCBJbmRpY2F0b3JDb2RlLCBUaW1lLCBWYWx1ZSkgJT4lIAogIGZpbHRlcihNZWFzdXJlID09ICJQQ19HRFAiICYgSW5kaWNhdG9yQ29kZSAlaW4lIGMoIlBSWV9OVFJZIiwgIlRSWSIpICYgVGltZSAlaW4lIHllYXJzKQoKaGVhZChlZHVjYXRpb24pCmNhdCgiIERpbWVuc2lvbnM6ICIgLCBkaW0oZWR1Y2F0aW9uKSkKYGBgCmVkdWNhdGlvbiBkYXRzZXQgbm93IGhhcyBmaXZlIGNvbHVtbnMgYW5kIDU1MiBvYnNlcnZhdGlvbnMKCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSSAKQ2hlY2sgaWYgZGF0YSBpcyB0aWR5OiBFeGFoIHZhcmlhYmxlIGluIGl0cyBvd24gY29sdW1uLiAgRWNhaCBvYnNlcnZhdGlvbiBpbiBpdHMgb3duIHJvdy4KQ2hlY2sgb2JzZXJ2YXRpb24gZm9yIEF1c3RyYWxpYSBhbmQgVVNBCmBgYHtyfQpjb3VudHJ5X3dvcmxkYmFuayAlPiUgZmlsdGVyKENvdW50cnlDb2RlICVpbiUgYygiQVVTIiwgIlVTQSIpICkKYGBgCkRhdGEgaXMgaW4gdGlkeSBmb3JtYXQuIE9uZSBvYnNlcnZhdGlvbiwgbm8gdmFyaWFibGVzIGluIGNvbHVtbnMgCgoKYGBge3J9CmVkdWNhdGlvbiAlPiUgZmlsdGVyKENvdW50cnlDb2RlICVpbiUgYygiQVVTIiwgIlVTQSIpICAmIFRpbWUgPiAyMDEzKQpgYGAKRGF0YSBpcyBOT1QgaW4gdGlkeSBmb3JtYXQuIApUaW1lIGNvbHVtbiBuZWVkcyB0byBiZSBzcHJlYWQgb3V0LiAKSW5kaWNhdG9yIGNvZGVzIHRvIGJlIHN1bW1lZCBpbm90IG9uZSB2YWx1ZSBmciBlYWNoIGNvdW50cnkveWVhcgoKCmBgYHtyfQojIENoZWNraW5nIHRoZSBudW1iZXIgb2YgTkEgdmFsdWVzIGZvciBlYWNoIHZhcmlhYmxlLiAgCmNvbFN1bXMoaXMubmEoZWR1Y2F0aW9uKSkKCiMgd2Ugc2VlIDExMiBtaXNzaW5nIHZhbHVlcyB0aGF0IGNhbiBiZSBkcm9wcGVkCmVkdWNhdGlvbiA8LSAgZWR1Y2F0aW9uW2NvbXBsZXRlLmNhc2VzKGVkdWNhdGlvbiksIF0KCiMgc3VtIHRoZSBwZXJjZW50YWdlIHNwZW50IG9uIGVkdWNhdGlvbiAgZm9yIGVhY2ggY291bnRyeSwgeWVhcgojIGNvdW50IHRoZSBudW1iZXIgb2YgcmVjb3JkcyB0aGUgc3VtIHRvIGZpbHRlciB3aGVuIAplZHVjYXRpb24gPC0gZWR1Y2F0aW9uICAlPiUgZ3JvdXBfYnkoQ291bnRyeUNvZGUsIE1lYXN1cmUsIFRpbWUpICU+JSAKICBzdW1tYXJpc2UoY29kZV9jb3VudCA9IG4oKSwgRURfUENHID0gc3VtKFZhbHVlKSkgJT4lIAogIGZpbHRlcihjb2RlX2NvdW50ID09IDIpICU+JSAKICBzZWxlY3QoLWNvZGVfY291bnQgKSAKCiMgbm93IHNwcmVhZCB0aGUgZGF0YSB0byAKZWR1Y2F0aW9uICA8LSBlZHVjYXRpb24gICU+JSAKICBzcHJlYWQoVGltZSwgdmFsdWUgPUVEX1BDRywgZHJvcCA9IFRSVUUsIGZpbGwgPSBOQSkKCmhlYWQoZWR1Y2F0aW9uKSAKYGBgCk5vdyBkYXRhIGlzIGluIHRpZHkgZm9ybWF0LgoKCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSUkgCkluIE9FQ0QgRWR1Y2F0aW9uIGRhdGFzZXQuLiAKQ3JlYXRlIC8gbXV0YXRlICB0aGUgYXZlcmFnZSBvZiBhbGwgRWR1Y2F0aW9uIGV4cGVuZGl0dXJlIHZhbHVlcyBmb3Igcm93LgpUaHNuIGFlcmFnZSBpcyB1c2VkIHRvIGltcHV0ZSBtaXNzaW5nIHZhbHVlcyBmb3IgeWVhcnMgd2l0aCBubyB2YWx1ZSBmb3IgcGVjZW50YWdlIHNwZW50IG9uIGVkdWNhdGlvbi4KCmBgYHtyfQojIENoZWNraW5nIHRoZSBudW1iZXIgb2YgTkEgdmFsdWVzIGZvciBlYWNoIHZhcmlhYmxlLiAKY29sU3Vtcyhpcy5uYShlZHVjYXRpb24pKQoKIyBpbXB1dGF0aW9uIG9mIG1lYW5zIHdoZXJlIE5BcyBleGlzdCBmb3IgdmFsdWUgaW4geWVhcnMgCmVkdWNhdGlvbiRjb2xfYXZnID0gcm93TWVhbnMoZWR1Y2F0aW9uWywgeWVhcnNdLCBuYS5ybSA9IFRSVUUpCgplZHVjYXRpb24gPC0gZWR1Y2F0aW9uICU+JSBtdXRhdGUoYDIwMTBgID0gY29hbGVzY2UoYDIwMTBgLGNvbF9hdmcgKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGAyMDExYCA9IGNvYWxlc2NlKGAyMDExYCxjb2xfYXZnICksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgMjAxMmAgPSBjb2FsZXNjZShgMjAxMmAsY29sX2F2ZyApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYDIwMTNgID0gY29hbGVzY2UoYDIwMTNgLGNvbF9hdmcgKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGAyMDE0YCA9IGNvYWxlc2NlKGAyMDE0YCxjb2xfYXZnICksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgMjAxNWAgPSBjb2FsZXNjZShgMjAxNWAsY29sX2F2ZyApKQoKCiMgd2Ugc3RpbGwgYWh2ZSBzb21lIE5BcyB0aGF0IGNhbiBiZSBkcm9wcGVkIGxhdGVyLgpjb2xTdW1zKGlzLm5hKGVkdWNhdGlvbikpCmBgYAoKCiMjIyBqb2luIHRoZSBkYXRhc2V0cwpgYGB7cn0KZGF0YSA8LSBsZWZ0X2pvaW4oY291bnRyeV93b3JsZGJhbmssIGVkdWNhdGlvbiwgYnkgPSBjKCJDb3VudHJ5Q29kZSIpLCBzdWZmaXggPSBjKCIiLCAiLkVEVUNBVElPTiIpICkKCmhlYWQoZGF0YSkKYGBgCgoKIyMJU2NhbiBJIAoKU2NhbiB0aGUgZGF0YSBmb3IgbWlzc2luZyB2YWx1ZXMsIGluY29uc2lzdGVuY2llcyBhbmQgb2J2aW91cyBlcnJvcnMuIEluIHRoaXMgc3RlcCwgeW91IHNob3VsZCBmdWxmaWwgdGhlIG1pbmltdW0gcmVxdWlyZW1lbnQgIzcuIEluIGFkZGl0aW9uIHRvIHRoZSBSIGNvZGVzIGFuZCBvdXRwdXRzLCBleHBsYWluIHlvdXIgbWV0aG9kb2xvZ3kgKGkuZS4gZXhwbGFpbiB3aHkgeW91IGhhdmUgY2hvc2VuIHRoYXQgbWV0aG9kb2xvZ3kgYW5kIHRoZSBhY3Rpb25zIHRoYXQgeW91IGhhdmUgdGFrZW4gdG8gaGFuZGxlIHRoZXNlIHZhbHVlcykgYW5kIGNvbW11bmljYXRlIHlvdXIgcmVzdWx0cyBjbGVhcmx5LgoKMS4gS2V5IGNvbHVtbnMgYXJlIkNvdW50cnlOYW1lIiBhbmQgIkNvdW50cnlDb2RlIi4KIHZlcmlmeSBOQXMgZG8gbm90IGV4aXN0IGluIHRoZXNlIGNvbHVtbnMgCjIuIFNDQU4gZm9yICBlbXB0eSB2YWx1ZXMgaW4geWVhciBjb2x1bW5zIAozLiByZW1vdmUgb2JzZXJ2YXRpbnMgd2l0aCBhbnkgZW1wdHkgdmFsdWVzIGZvciB5ZWFycyAyMDEwLTIwMTUKCmBgYHtyfQojIHZlcmlmeSBkaW1lbnNpb25zIGFuZCBOQXMKZGltKGRhdGEpCmNvbFN1bXMoaXMubmEoZGF0YSkpCgojIGtleSBjb2x1bW5zIGFyZSAiQ291bnRyeU5hbWUiIGFuZCAiQ291bnRyeUNvZGUiLgojIHZlcmlmeSBOQXMgZG8gbm90IGV4aXN0IGluIHRoZXNlIGNvbHVtbnMgCmNvbFN1bXMoaXMubmEoZGF0YVssMDo0XSkpCgojIFNDQU4gZm9yICBlbXB0eSB2YWx1ZXMgaW4geWVhciBjb2x1bW5zCmRhdGEgJT4lIGZpbHRlcihpcy5uYShgMjAxMGApICYgaXMubmEoYDIwMTFgKSYgaXMubmEoYDIwMTJgKSYgaXMubmEoYDIwMTNgKSYgaXMubmEoYDIwMTRgKSAmIGlzLm5hKGAyMDE1YCkgICkKCiNkcm9wIHRoZXNlIG91dCBvZiB0aGUgZGF0c2V0CmRhdGEgPC0gZGF0YSAlPiUgZmlsdGVyKCFpcy5uYShgMjAxMGApIHwgIWlzLm5hKGAyMDExYCkgfCAhaXMubmEoYDIwMTJgKSB8ICFpcy5uYShgMjAxM2ApIHwgIWlzLm5hKGAyMDE0YCkgfCAhaXMubmEoYDIwMTVgKSAgKQoKY29sU3Vtcyhpcy5uYShkYXRhKSkKCmBgYAoKCiMjCVNjYW4gSUkKCjEuIHByb2R1Y2UgYmlveHBsb3RzIG9mIGFsbCB2YWx1ZXMgZm9yIHllYXJzIDIwMTAtMjAxNQoyLiB2aXN1YWxseSBkZXRlcm1pbiAyMTEgaGFzIGFuIG91dGxpZXIKMy4gdXRpbGlzZSBvdXRsaWVycyBwYWNrYWdlCgoKYGBge3J9CiMgcGxvdCBhIApib3hwbG90KGRhdGEkYDIwMTBgKQpib3hwbG90KGRhdGEkYDIwMTFgKQpib3hwbG90KGRhdGEkYDIwMTJgKQpib3hwbG90KGRhdGEkYDIwMTNgKQpib3hwbG90KGRhdGEkYDIwMTRgKQpib3hwbG90KGRhdGEkYDIwMTVgKQoKeSA9IGRhdGEkYDIwMTFgCgoKYGBgCgoKIyMJVHJhbnNmb3JtIAoKMS4gcHJvZHVjZSBoaXN0b2dhcm0gb2YgMjAxMSBkYXRhIGZvciBlZHVjYXRpb24gc3BlbmQKMi4gbG9nIDIwMTEgZGF0YSBhbiBkcHJvZHVjZSBoaXN0b2dyYW0uCgpgYGB7cn0KIyBoaXMgb2YgMjAxMSBkYXRhIApoaXN0KGRhdGEkYDIwMTFgKQoKIyB0cmFuc2Zvcm0gd2l0aCBsb2cgYW5kIHBsb3QgaGlzdC4KaGlzdChsb2coZGF0YSRgMjAxMWApKQoKCgpgYGAKCgoK