Setup


# Load packages 

library(readr)
library(kableExtra)
library(tidyr)
library(dplyr)
#install.packages("tidyverse")
library(tidyverse)
#install.packages("Hmisc")
library(Hmisc)
library(ggplot2)
#install.packages("DescTools")
library(DescTools)
library(magrittr)

Student Name, Student Number and Percentage of Contribution

Individual Details
Student name Student Number Percentage of contribution
Chamudi Abeysinghe s4150303 100%

Executive Summary

Data

The data sets were sourced from the World Bank Data repository. One of them, Urban Population.csv, contains information on people living in urban areas, based on definitions provided by each country’s national statistical office. The data is organized by country and covers the years from 1960 to 2023.

The second data set is ‘Urban Development.csv’ which lists urban development indicators by country for the same period of time.

In Urban Development (2023) mentions, data on urbanization, traffic and congestion, and air pollution are from the United Nations Population Division, World Health Organization, International Road Federation, World Resources Institute, and other sources.

Both sets contain ‘Country Name’ and ‘Country Code’ variables.

More variable descriptions will be provided later on this report.

After loading the data sets, I chose to focus only on the most recent six years (2018 to 2023) to keep things concise. This doesn’t affect the data wrangling methods used later, as they remain the same.

Source of Data

Urban population (2023) Worldbank.org, Retrieved May 25, 2025, https://data.worldbank.org/indicator/SP.URB.TOTL?end=2023&start=2000 Released under a Creative Commons Attribution BY-4.0 license.

This was sourced by World Bank staff estimates based on the United Nations Population Division’s World Urbanization Prospects: 2018 Revision.

Urban Development (2023) Worldbank.org, Retrieved May 25, 2025, https://data.worldbank.org/topic/urban-development. Released under a Creative Commons Attribution BY-4.0 license.

This was sourced by World Bank staff estimates based on the United Nations Population Division’s World Urbanization Prospects: 2018 Revision.

Data set I

In ‘Urban Population.csv’, there are 266 observations and 10 variables.

Variable Description for ‘Urban Population.csv’ as below:

Column Name Description
Country Name Name of the country.
Country Code Country code (ex: “USA” - United States)
Indicator Name The name of the indicator (ex: “Urban population”)
Indicator Code Code used to represent the indicator (ex: “SP.URB.TOTL”)
1960 to 2024 Urban population data for each corresponding year
# Import the urban population data, skip the first 4 metadata rows while importing

urban_population <- read_csv("/Users/chamudi/Desktop/RMIT/1st Year 1st Semester/Data Wrangling/Assignments/Assignment 2/Dataset/1/Urban Population.csv", skip = 4) 
New names:Rows: 266 Columns: 70── Column specification ──────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (4): Country Name, Country Code, Indicator Name, Indicator Code
dbl (64): 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 19...
lgl  (2): 2024, ...70
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#select columns 1 to 4 and 63 to 68 - reason is mentioned in 'Data' section.
urban_population <- urban_population %>%
  select(c(1:4, 63:68))

#display the first few rows
knitr::kable(head(urban_population))
Country Name Country Code Indicator Name Indicator Code 2018 2019 2020 2021 2022 2023
Aruba ABW Urban population SP.URB.TOTL 47278 47554 47449 47244 47272 47511
Africa Eastern and Southern AFE Urban population SP.URB.TOTL 236107161 245939557 256139740 266650602 277426261 288380305
Afghanistan AFG Urban population SP.URB.TOTL 9367638 9749465 10168092 10525708 10800465 11165011
Africa Western and Central AFW Urban population SP.URB.TOTL 211219592 219276647 227465935 235827038 244365364 253228069
Angola AGO Urban population SP.URB.TOTL 20504018 21425222 22353719 23295577 24260684 25242775
Albania ALB Urban population SP.URB.TOTL 1728969 1747593 1762645 1770478 1772138 1773980
NA
NA
NA

Data set II

In the ‘Urban Development.csv’, there are 4522 observations and 10 variables.

Variable Description for ‘Urban Development.csv’ as below:

Column Name Description
Country Name Name of the country (ex: “India”, “Brazil”).
Country Code Country code (ex: “USA” for United States).
Indicator Name The name of the development indicator, likely all “Urban population”.
Indicator Code The official code for the indicator.
1960 to 2024 Annual values for the indicator from 1960 to 2024. Each year is a separate column.
# Import the urban development data, skip the first 4 metadata rows while importing

urban_development <- read_csv("/Users/chamudi/Desktop/RMIT/1st Year 1st Semester/Data Wrangling/Assignments/Assignment 2/Dataset/2/Urban Development.csv", skip = 4) 
New names:Rows: 4522 Columns: 70── Column specification ──────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (4): Country Name, Country Code, Indicator Name, Indicator Code
dbl (65): 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 19...
lgl  (1): ...70
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#select columns 1 to 4 and 63 to 68 - reason is mentioned in 'Data' section.
urban_development <- urban_development %>%
  select(c(1:4, 63:68))

#display the first few rows
knitr::kable(head(urban_development))
Country Name Country Code Indicator Name Indicator Code 2018 2019 2020 2021 2022 2023
Aruba ABW Urban population (% of total population) SP.URB.TOTL.IN.ZS 4.341100e+01 4.354600e+01 43.6970000 43.8660000 4.40520e+01 4.425400e+01
Aruba ABW Urban population SP.URB.TOTL 4.727800e+04 4.755400e+04 47449.0000000 47244.0000000 4.72720e+04 4.751100e+04
Aruba ABW Urban population growth (annual %) SP.URB.GROW 4.302996e-01 5.820836e-01 -0.2210457 -0.4329788 5.92492e-02 5.043109e-01
Aruba ABW Mortality caused by road traffic injury (per 100,000 population) SH.STA.TRAF.P5 NA NA NA NA NA NA
Aruba ABW Population in urban agglomerations of more than 1 million (% of total population) EN.URB.MCTY.TL.ZS NA NA NA NA NA NA
Aruba ABW Population in urban agglomerations of more than 1 million EN.URB.MCTY NA NA NA NA NA NA
NA

Sub-setting: Now I am creating random subsets using my student number s4150303. Since set.seed() only accepts numeric values, I need to extract the numeric part of my student number: 4150303.

In the urban_population_subset, there are 212 observations and 10 variables.

In the urban_development_subset, there are 3617 observations and 10 variables.

# Set seed using numeric part of your student number
set.seed(4150303)

# Calculate desired number of rows (at least 80% as in the specification)
urban_population_rows <- floor(0.8 * nrow(urban_population))
urban_development_rows <- floor(0.8 * nrow(urban_development))

# Randomly select 80% of rows for each data set
urban_population_subset <- urban_population[sample(nrow(urban_population), urban_population_rows), ]
urban_development_subset <- urban_development[sample(nrow(urban_development), urban_development_rows), ]

# Display first few rows of the subsets
knitr::kable(head(urban_population_subset))
Country Name Country Code Indicator Name Indicator Code 2018 2019 2020 2021 2022 2023
Tajikistan TJK Urban population SP.URB.TOTL 2525452 2602538 2681645 2763425 2847764 2933456
Guam GUM Urban population SP.URB.TOTL 154187 153489 153950 155568 157071 158457
Tonga TON Urban population SP.URB.TOTL 24419 24417 24417 24372 24291 24225
Togo TGO Urban population SP.URB.TOTL 3444076 3575477 3710640 3849488 3992304 4139500
Cambodia KHM Urban population SP.URB.TOTL 3806285 3923374 4052917 4187222 4320041 4455286
Liechtenstein LIE Urban population SP.URB.TOTL 5484 5542 5608 5670 5741 5825
knitr::kable(head(urban_development_subset))
Country Name Country Code Indicator Name Indicator Code 2018 2019 2020 2021 2022 2023
Malawi MWI Population in largest city EN.URB.LCTY 1029639 1074695 1121720 1170870 1222325 1276316
Georgia GEO Urban population living in areas where elevation is below 5 meters (% of total population) EN.POP.EL5M.UR.ZS NA NA NA NA NA NA
Puerto Rico PRI Urban population living in areas where elevation is below 5 meters (% of total population) EN.POP.EL5M.UR.ZS NA NA NA NA NA NA
Central Europe and the Baltics CEB Population in urban agglomerations of more than 1 million (% of total population) EN.URB.MCTY.TL.ZS NA NA NA NA NA NA
Qatar QAT Population living in slums (% of urban population) EN.POP.SLUM.UR.ZS NA NA NA NA NA NA
Curacao CUW Urban land area where elevation is below 5 meters (sq. km) AG.LND.EL5M.UR.K2 NA NA NA NA NA NA
NA

Understand I

To get an understand about the subset data set, I first checked the data types.

The data set contains 212 observations and 10 variables.

All columns are stored as character data, while the columns for the years 2018 to 2023 are numeric. I decided to convert the character variables into factors because, in later sections involving statistical modeling, it’s important to treat these as categorical groups rather than plain text. This also helps improve both efficiency and performance during analysis.

# Check initial structure
str(urban_population_subset)
tibble [212 × 10] (S3: tbl_df/tbl/data.frame)
 $ Country Name  : chr [1:212] "Tajikistan" "Guam" "Tonga" "Togo" ...
 $ Country Code  : chr [1:212] "TJK" "GUM" "TON" "TGO" ...
 $ Indicator Name: chr [1:212] "Urban population" "Urban population" "Urban population" "Urban population" ...
 $ Indicator Code: chr [1:212] "SP.URB.TOTL" "SP.URB.TOTL" "SP.URB.TOTL" "SP.URB.TOTL" ...
 $ 2018          : num [1:212] 2525452 154187 24419 3444076 3806285 ...
 $ 2019          : num [1:212] 2602538 153489 24417 3575477 3923374 ...
 $ 2020          : num [1:212] 2681645 153950 24417 3710640 4052917 ...
 $ 2021          : num [1:212] 2763425 155568 24372 3849488 4187222 ...
 $ 2022          : num [1:212] 2847764 157071 24291 3992304 4320041 ...
 $ 2023          : num [1:212] 2933456 158457 24225 4139500 4455286 ...
# Convert categorical variables to factors
urban_population_subset <- urban_population_subset %>%
  mutate(
    `Country Name` = as.factor(`Country Name`),
    `Country Code` = as.factor(`Country Code`),
    `Indicator Name` = as.factor(`Indicator Name`),
    `Indicator Code` = as.factor(`Indicator Code`)
  )

# View structure after conversion
glimpse(urban_population_subset)
Rows: 212
Columns: 10
$ `Country Name`   <fct> "Tajikistan", "Guam", "Tonga", "Togo", "Cambodia", "Liechtenstein",…
$ `Country Code`   <fct> TJK, GUM, TON, TGO, KHM, LIE, TUR, JOR, PSS, PYF, RWA, DEU, MRT, AB…
$ `Indicator Name` <fct> Urban population, Urban population, Urban population, Urban populat…
$ `Indicator Code` <fct> SP.URB.TOTL, SP.URB.TOTL, SP.URB.TOTL, SP.URB.TOTL, SP.URB.TOTL, SP…
$ `2018`           <dbl> 2525452, 154187, 24419, 3444076, 3806285, 5484, 61171815, 9518501, …
$ `2019`           <dbl> 2602538, 153489, 24417, 3575477, 3923374, 5542, 62454830, 9733085, …
$ `2020`           <dbl> 2681645, 153950, 24417, 3710640, 4052917, 5608, 63459911, 9932774, …
$ `2021`           <dbl> 2763425, 155568, 24372, 3849488, 4187222, 5670, 64430760, 10139659,…
$ `2022`           <dbl> 2847764, 157071, 24291, 3992304, 4320041, 5741, 65453229, 10336289,…
$ `2023`           <dbl> 2933456, 158457, 24225, 4139500, 4455286, 5825, 66096052, 10526364,…
# View summary statistics
summary(urban_population_subset)
                      Country Name  Country Code          Indicator Name     Indicator Code
 Afghanistan                :  1   ABW    :  1   Urban population:212    SP.URB.TOTL:212   
 Africa Eastern and Southern:  1   AFE    :  1                                             
 Africa Western and Central :  1   AFG    :  1                                             
 Albania                    :  1   AFW    :  1                                             
 Algeria                    :  1   AGO    :  1                                             
 American Samoa             :  1   ALB    :  1                                             
 (Other)                    :206   (Other):206                                             
      2018                2019                2020                2021          
 Min.   :5.484e+03   Min.   :5.542e+03   Min.   :5.608e+03   Min.   :5.670e+03  
 1st Qu.:8.644e+05   1st Qu.:8.737e+05   1st Qu.:8.827e+05   1st Qu.:8.915e+05  
 Median :5.559e+06   Median :5.715e+06   Median :5.799e+06   Median :5.924e+06  
 Mean   :1.714e+08   Mean   :1.751e+08   Mean   :1.788e+08   Mean   :1.822e+08  
 3rd Qu.:3.857e+07   3rd Qu.:3.937e+07   3rd Qu.:4.016e+07   3rd Qu.:4.090e+07  
 Max.   :4.239e+09   Max.   :4.317e+09   Max.   :4.396e+09   Max.   :4.465e+09  
 NA's   :2           NA's   :2           NA's   :2           NA's   :2          
      2022                2023          
 Min.   :5.741e+03   Min.   :5.825e+03  
 1st Qu.:9.032e+05   1st Qu.:9.184e+05  
 Median :6.055e+06   Median :6.186e+06  
 Mean   :1.857e+08   Mean   :1.894e+08  
 3rd Qu.:4.126e+07   3rd Qu.:4.150e+07  
 Max.   :4.538e+09   Max.   :4.614e+09  
 NA's   :2           NA's   :2          
str(urban_population_subset)
tibble [212 × 10] (S3: tbl_df/tbl/data.frame)
 $ Country Name  : Factor w/ 212 levels "Afghanistan",..: 186 71 191 190 30 109 194 93 145 62 ...
 $ Country Code  : Factor w/ 212 levels "ABW","AFE","AFG",..: 184 71 189 182 97 108 193 93 155 156 ...
 $ Indicator Name: Factor w/ 1 level "Urban population": 1 1 1 1 1 1 1 1 1 1 ...
 $ Indicator Code: Factor w/ 1 level "SP.URB.TOTL": 1 1 1 1 1 1 1 1 1 1 ...
 $ 2018          : num [1:212] 2525452 154187 24419 3444076 3806285 ...
 $ 2019          : num [1:212] 2602538 153489 24417 3575477 3923374 ...
 $ 2020          : num [1:212] 2681645 153950 24417 3710640 4052917 ...
 $ 2021          : num [1:212] 2763425 155568 24372 3849488 4187222 ...
 $ 2022          : num [1:212] 2847764 157071 24291 3992304 4320041 ...
 $ 2023          : num [1:212] 2933456 158457 24225 4139500 4455286 ...

Understand the Urban Development subset dataset.

I followed the same thing for this dataset as well.

# View structure of the data set
str(urban_development_subset)
tibble [3,617 × 10] (S3: tbl_df/tbl/data.frame)
 $ Country Name  : chr [1:3617] "Malawi" "Georgia" "Puerto Rico" "Central Europe and the Baltics" ...
 $ Country Code  : chr [1:3617] "MWI" "GEO" "PRI" "CEB" ...
 $ Indicator Name: chr [1:3617] "Population in largest city" "Urban population living in areas where elevation is below 5 meters (% of total population)" "Urban population living in areas where elevation is below 5 meters (% of total population)" "Population in urban agglomerations of more than 1 million (% of total population)" ...
 $ Indicator Code: chr [1:3617] "EN.URB.LCTY" "EN.POP.EL5M.UR.ZS" "EN.POP.EL5M.UR.ZS" "EN.URB.MCTY.TL.ZS" ...
 $ 2018          : num [1:3617] 1029639 NA NA NA NA ...
 $ 2019          : num [1:3617] 1074695 NA NA NA NA ...
 $ 2020          : num [1:3617] 1121720 NA NA NA NA ...
 $ 2021          : num [1:3617] 1170870 NA NA NA NA ...
 $ 2022          : num [1:3617] 1222325 NA NA NA NA ...
 $ 2023          : num [1:3617] 1276316 NA NA NA NA ...
# Convert categorical variables to factor type
urban_development_subset <- urban_development_subset %>%
  mutate(
    `Country Name` = as.factor(`Country Name`),
    `Country Code` = as.factor(`Country Code`),
    `Indicator Name` = as.factor(`Indicator Name`),
    `Indicator Code` = as.factor(`Indicator Code`)
  )

# Re-check structure after type conversion
glimpse(urban_development_subset)
Rows: 3,617
Columns: 10
$ `Country Name`   <fct> "Malawi", "Georgia", "Puerto Rico", "Central Europe and the Baltics…
$ `Country Code`   <fct> MWI, GEO, PRI, CEB, QAT, CUW, BEN, VEN, BWA, ESP, CEB, BEN, CHE, KH…
$ `Indicator Name` <fct> "Population in largest city", "Urban population living in areas whe…
$ `Indicator Code` <fct> EN.URB.LCTY, EN.POP.EL5M.UR.ZS, EN.POP.EL5M.UR.ZS, EN.URB.MCTY.TL.Z…
$ `2018`           <dbl> 1.029639e+06, NA, NA, NA, NA, NA, 4.731200e+01, 3.820000e+01, 6.944…
$ `2019`           <dbl> 1.074695e+06, NA, NA, NA, NA, NA, 4.786100e+01, 3.900000e+01, 7.017…
$ `2020`           <dbl> 1.121720e+06, NA, NA, NA, NA, NA, 4.841500e+01, NA, 7.087700e+01, N…
$ `2021`           <dbl> 1.170870e+06, NA, NA, NA, NA, NA, 4.897200e+01, NA, 7.156000e+01, N…
$ `2022`           <dbl> 1.222325e+06, NA, NA, NA, NA, NA, 4.953400e+01, NA, 7.222400e+01, N…
$ `2023`           <dbl> 1.276316e+06, NA, NA, NA, NA, NA, 5.010000e+01, NA, 7.286700e+01, N…
# View summary statistics
summary(urban_development_subset)
       Country Name   Country Code 
 Cuba        :  17   CUB    :  17  
 Gabon       :  17   GAB    :  17  
 Kiribati    :  17   KIR    :  17  
 Sierra Leone:  17   SLE    :  17  
 Bulgaria    :  16   ARE    :  16  
 Canada      :  16   BGR    :  16  
 (Other)     :3517   (Other):3517  
                                                                                    Indicator Name
 Population density (people per sq. km of land area)                                       : 223  
 Urban land area where elevation is below 5 meters (sq. km)                                : 220  
 Access to electricity, urban (% of urban population)                                      : 218  
 Mortality caused by road traffic injury (per 100,000 population)                          : 218  
 Population in the largest city (% of urban population)                                    : 218  
 Urban population living in areas where elevation is below 5 meters (% of total population): 218  
 (Other)                                                                                   :2302  
           Indicator Code      2018                 2019                 2020           
 EN.POP.DNST      : 223   Min.   :        -4   Min.   :        -3   Min.   :        -3  
 AG.LND.EL5M.UR.K2: 220   1st Qu.:        17   1st Qu.:        17   1st Qu.:        20  
 EG.ELC.ACCS.UR.ZS: 218   Median :        46   Median :        46   Median :        55  
 EN.POP.EL5M.UR.ZS: 218   Mean   :  18496456   Mean   :  19784247   Mean   :  21371607  
 EN.URB.LCTY.UR.ZS: 218   3rd Qu.:       100   3rd Qu.:       139   3rd Qu.:       264  
 SH.STA.TRAF.P5   : 218   Max.   :4238877472   Max.   :4317201037   Max.   :4395641624  
 (Other)          :2302   NA's   :1596         NA's   :1688         NA's   :1795        
      2021                 2022                 2023           
 Min.   :       -11   Min.   :        -7   Min.   :        -8  
 1st Qu.:        23   1st Qu.:        23   1st Qu.:        21  
 Median :        78   Median :        79   Median :        79  
 Mean   :  25669620   Mean   :  26263438   Mean   :  31214010  
 3rd Qu.:    173656   3rd Qu.:    205704   3rd Qu.:   1113224  
 Max.   :4464635019   Max.   :4538431007   Max.   :4614425176  
 NA's   :2072         NA's   :2079         NA's   :2299        
str(urban_development_subset)
tibble [3,617 × 10] (S3: tbl_df/tbl/data.frame)
 $ Country Name  : Factor w/ 266 levels "Afghanistan",..: 150 88 200 43 201 56 24 259 29 224 ...
 $ Country Code  : Factor w/ 266 levels "ABW","AFE","AFG",..: 169 83 193 37 201 52 19 255 34 71 ...
 $ Indicator Name: Factor w/ 17 levels "Access to electricity, urban (% of urban population)",..: 6 17 17 9 10 13 15 2 15 12 ...
 $ Indicator Code: Factor w/ 17 levels "AG.LND.EL5M.UR.K2",..: 10 8 8 13 9 1 17 14 17 2 ...
 $ 2018          : num [1:3617] 1029639 NA NA NA NA ...
 $ 2019          : num [1:3617] 1074695 NA NA NA NA ...
 $ 2020          : num [1:3617] 1121720 NA NA NA NA ...
 $ 2021          : num [1:3617] 1170870 NA NA NA NA ...
 $ 2022          : num [1:3617] 1222325 NA NA NA NA ...
 $ 2023          : num [1:3617] 1276316 NA NA NA NA ...

Tidy & Manipulate Data I

The original data sets aren’t in a tidy format, as mainly the ‘Year’ column doesn’t represent a single variable which goes against the principles of tidy data.

Repeating ‘Urban population’ cell data in ‘indicator Name’ doesn’t mean the data set untidy. Therefore, I am only dealing with urban population only it’s okay and safe to drop the column to make the data set more concise.

Additionally, in the urban development the ‘Indicator Name’ column contains multiple types of information, which should be separated into distinct variables.

To fix this, I’ll start by using gather(). This will turn the separate year columns into a single ‘Year’ column, with the corresponding values in another column as ‘Population’

#I combined all the year columns into one using the gather() function. I also removed unnecessary columns like "Country Code" and "Indicator Code" to keep the data cleaner and more focused.

population_gather <- urban_population_subset %>% gather(5:10, key = "Year", value = "Population") %>%  select(c(1, 3, 5, 6)) 

#Repeating 'Urban population' cell data in "indicator Name" doesn't mean the data set untidy. Therefore, I am only dealing with urban population only it's okay and safe to drop the column to make the data set more concise.

population_new_gather <- population_gather %>%
  select(-`Indicator Name`)

head(population_new_gather)
NA

Looking at the modified urban population data set, we can now see that it contains only three remaining variables.

Next, the “Indicator Name” column in the urban development.csv will be separated into individual variables using the spread() function.

#Same as before
development_gather <- urban_development_subset %>% gather(5:10, key = "Year", value = "Development") %>%  select(c(1, 3, 5, 6)) 

#Split the "Indicator Name" into multiple columns using spread()
development_spread <- spread(development_gather, key = "Indicator Name", value = "Development")

head(development_spread)
NA

Understand II

Converting the “Year” variable to an ordered factor is important especially in the context of data analysis and visualization.


#The “Year” variable should be a ordered factor variable.

population_new_gather$Year <- population_new_gather$Year %>% factor(levels = c("2018", "2019", "2020", "2021", "2022", "2023"), ordered = TRUE)

levels(population_new_gather$Year)
[1] "2018" "2019" "2020" "2021" "2022" "2023"
str(population_new_gather)
tibble [1,272 × 3] (S3: tbl_df/tbl/data.frame)
 $ Country Name: Factor w/ 212 levels "Afghanistan",..: 186 71 191 190 30 109 194 93 145 62 ...
 $ Year        : Ord.factor w/ 6 levels "2018"<"2019"<..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Population  : num [1:1272] 2525452 154187 24419 3444076 3806285 ...

#The “Year” variable should be a ordered factor variable.

development_spread$Year <- development_spread$Year %>% factor(levels = c("2018", "2019", "2020", "2021", "2022", "2023"), ordered = TRUE)

levels(development_spread$Year)
[1] "2018" "2019" "2020" "2021" "2022" "2023"
str(development_spread)
tibble [1,596 × 19] (S3: tbl_df/tbl/data.frame)
 $ Country Name                                                                                : Factor w/ 266 levels "Afghanistan",..: 1 1 1 1 1 1 2 2 2 2 ...
 $ Year                                                                                        : Ord.factor w/ 6 levels "2018"<"2019"<..: 1 2 3 4 5 6 1 2 3 4 ...
 $ Access to electricity, urban (% of urban population)                                        : num [1:1596] 98.8 99.5 99.5 99.5 95.9 ...
 $ Mortality caused by road traffic injury (per 100,000 population)                            : num [1:1596] 14.2 15.9 NA NA NA ...
 $ PM2.5 air pollution, mean annual exposure (micrograms per cubic meter)                      : num [1:1596] 67.2 58.3 46.1 NA NA ...
 $ PM2.5 air pollution, population exposed to levels exceeding WHO guideline value (% of total): num [1:1596] NA NA NA NA NA NA NA NA NA NA ...
 $ Population density (people per sq. km of land area)                                         : num [1:1596] 56.3 58 59.9 61.3 62.2 ...
 $ Population in largest city                                                                  : num [1:1596] NA NA NA NA NA NA NA NA NA NA ...
 $ Population in the largest city (% of urban population)                                      : num [1:1596] 42.8 42.2 41.5 41.2 41.3 ...
 $ Population in urban agglomerations of more than 1 million                                   : num [1:1596] 4011770 4114030 4221532 4335770 4457882 ...
 $ Population in urban agglomerations of more than 1 million (% of total population)           : num [1:1596] NA NA NA NA NA NA NA NA NA NA ...
 $ Population living in slums (% of urban population)                                          : num [1:1596] 73.3 NA 73.3 NA NA ...
 $ Urban land area (sq. km)                                                                    : num [1:1596] NA NA NA NA NA NA NA NA NA NA ...
 $ Urban land area where elevation is below 5 meters (% of total land area)                    : num [1:1596] NA NA NA NA NA NA NA NA NA NA ...
 $ Urban land area where elevation is below 5 meters (sq. km)                                  : num [1:1596] NA NA NA NA NA NA NA NA NA NA ...
 $ Urban population                                                                            : num [1:1596] 9367638 9749465 10168092 10525708 10800465 ...
 $ Urban population (% of total population)                                                    : num [1:1596] 25.5 25.8 26 26.3 26.6 ...
 $ Urban population growth (annual %)                                                          : num [1:1596] 3.88 4 4.2 3.46 2.58 ...
 $ Urban population living in areas where elevation is below 5 meters (% of total population)  : num [1:1596] NA NA NA NA NA NA NA NA NA NA ...

Tidy & Manipulate Data I Cont.

Now as both data sets are in a tidy format, it will be merged using a left join based on the common variables “Country Name” and “Year”. A left join ensures that all observations from the population data set are retained, while matching values from the development data set are added wherever available.


#Merge using natural join
population_development <- population_new_gather %>%
  left_join(development_spread, by = c("Country Name", "Year"))

head(population_development)

#choosing the columns 
population_development2 <- population_development %>% select(c(1, 2, 3, 4))

str(population_development2)
tibble [1,272 × 4] (S3: tbl_df/tbl/data.frame)
 $ Country Name                                        : Factor w/ 266 levels "Afghanistan",..: 186 71 191 190 30 109 194 93 145 62 ...
 $ Year                                                : Ord.factor w/ 6 levels "2018"<"2019"<..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Population                                          : num [1:1272] 2525452 154187 24419 3444076 3806285 ...
 $ Access to electricity, urban (% of urban population): num [1:1272] NA 100 99.8 83.1 NA ...

Variable Description: In the data frame there are only 4 remaining variables it has 1272 observations:

Column Name Description
Country Name There are 266 countries.
Year. An ordered factor variable to show the order in which the data was collected, from the oldest year to the most recent
Population Total population of a country in any given year
Access to electricity, urban (% of urban population) The percentage of population with access to electricity in any given year.

Tidy & Manipulate Data II

In this section, I’ll calculate the total number of people with access to electricity in each country for the year 2020.

Calculation is as below.


# Create a new column for total number with access to electricity in 2020
electricity_2020 <- population_development2 %>%
  filter(Year == 2020) %>% select(1,3,4) %>%
  mutate(
    Population_with_electricity = Population * `Access to electricity, urban (% of urban population)` / 100
  )

# View the result
head(electricity_2020)

str(electricity_2020)
tibble [212 × 4] (S3: tbl_df/tbl/data.frame)
 $ Country Name                                        : Factor w/ 266 levels "Afghanistan",..: 186 71 191 190 30 109 194 93 145 62 ...
 $ Population                                          : num [1:212] 2681645 153950 24417 3710640 4052917 ...
 $ Access to electricity, urban (% of urban population): num [1:212] NA 100 100 94 NA ...
 $ Population_with_electricity                         : num [1:212] NA 153950 24417 3488002 NA ...

Scan I

In this section, I checked the data for any missing values, unusual entries, or inconsistencies.

#missing values
sum(is.na(electricity_2020))
[1] 84
colSums(is.na(electricity_2020))
                                        Country Name 
                                                   0 
                                          Population 
                                                   2 
Access to electricity, urban (% of urban population) 
                                                  41 
                         Population_with_electricity 
                                                  41 

#special values
sapply(electricity_2020, function(x) sum(is.infinite(x) | is.nan(x)))
                                        Country Name 
                                                   0 
                                          Population 
                                                   0 
Access to electricity, urban (% of urban population) 
                                                   0 
                         Population_with_electricity 
                                                   0 

There are no infinite or NaN values in the data set.

But there are a few missing values (NAs). Since all columns except Country Name are numeric, any missing entries in those columns are automatically treated as NA. From the data scan, we can see a total of 84 missing values across the three main variables.

#Countries which are missing population data
electricity_2020[which(is.na(electricity_2020$'Population')), "Country Name"]
#Countries which are missing 'Access to electricity' data
electricity_2020[which(is.na(electricity_2020$`Access to electricity, urban (% of urban population)`)), "Country Name"]
#Countries which are missing 'Population_with_electricity' data
electricity_2020[which(is.na(electricity_2020$Population_with_electricity)), "Country Name"]



An obvious error can be seen in the country name ‘Not classified’. So, it appears to be no data for this. Therefore, I decided to remove that row. It will not affect for my analysis.

For the remaining NA values which includes numerical values are replaced with the mean.

electricity_2020_clean <- electricity_2020 %>%
  filter(`Country Name` != "Not classified")

#Replace the missing value(s) of population with the mean
electricity_2020_clean$Population <- impute(electricity_2020_clean$Population, fun = mean) 

#Replace the missing value(s) of Access to electricity with the mean
electricity_2020_clean$`Access to electricity, urban (% of urban population)` <- impute(electricity_2020_clean$`Access to electricity, urban (% of urban population)`, fun = mean) 

#Replace the missing value(s) of population with electricity, with the mean
electricity_2020_clean$Population_with_electricity <- impute(electricity_2020_clean$Population_with_electricity, fun = mean) 

#Remaining missing values
colSums(is.na(electricity_2020_clean))
                                        Country Name 
                                                   0 
                                          Population 
                                                   0 
Access to electricity, urban (% of urban population) 
                                                   0 
                         Population_with_electricity 
                                                   0 

Now seems to be okay with the NA values.

Scan II

Before handling the outliers, it is important to understand the distribution of your variables. The best first step is to use Histogram to visually inspect whether the data is normally distributed or skewed.


# Histogram for Population
ggplot(electricity_2020_clean, aes(x = Population)) +
  geom_histogram(binwidth = 1000000, fill = "blue", color = "black") +
  labs(title = "Distribution of Urban Population", x = "Population", y = "Frequency")


# Histogram for Access to Electricity (%)
ggplot(electricity_2020_clean, aes(x = `Access to electricity, urban (% of urban population)`)) +
  geom_histogram(binwidth = 5, fill = "green", color = "black") +
  labs(title = "Distribution of Urban Electricity Access", x = "Percentage", y = "Frequency")


# Histogram for Computed Variable: Population with Electricity
ggplot(electricity_2020_clean, aes(x = Population_with_electricity)) +
  geom_histogram(binwidth = 1000000, fill = "purple", color = "black") +
  labs(title = "Distribution of People with Electricity", x = "Population with Access", y = "Frequency")

NA
NA
  1. Distribution of Urban Population The histogram is highly right-skewed (positively skewed). Most countries have a relatively small urban population, concentrated near the left side of the graph. A few countries have very large urban populations, extending the distribution to the right with long, low-frequency bars.

  2. Distribution of Urban Electricity Access The histogram is left-skewed (negatively skewed), with the tail extending toward lower percentages. A large number of countries have very high access rates (close to 100%). Very few countries have low access rates (below 50%), shown as smaller bars on the left.

  3. Distribution of People with Electricity The histogram is highly right-skewed, with a long tail stretching toward higher values. The majority of countries have low to moderate values of urban population with electricity access. A small number of countries have extremely large values, driving the skew.

Since the observation clearly displays all the three types are heavily skewed.

To detect outliers in this task, the best way is Turkey’s method (IQR).


#Plots variables using box plots

electricity_2020_clean$Population %>% boxplot(ylab="Population")


electricity_2020_clean$`Access to electricity, urban (% of urban population)` %>% boxplot(ylab="Access to electricity (% of population)")


electricity_2020_clean$Population_with_electricity%>% boxplot(ylab="No of people with access to electricity")

From the box plots, each contains multiple outliers. Classical statistics are sensitive to extreme values.

I have chosen to apply capping/Winsorising. This method limits extreme values by replacing them with a specified percentile (ex: the 5th and 95th percentiles).

#stakoverflow: https://stackoverflow.com/questions/13339685/how-to-replace-outliers-with-the-5th-and-95th-percentile-values-in-r?utm_medium=organic&utm_sourcegoogle_rich_qa&utm_campaign=google_rich_qa

# Define a function to cap the values outside the limits

cap <- function(x){
    quantiles <- quantile( x, c(.05, 0.25, 0.75, .95 ) )
    x[ x < quantiles[2] - 1.5*IQR(x) ] <- quantiles[1]
    x[ x > quantiles[3] + 1.5*IQR(x) ] <- quantiles[4]
    x}
#capping function

population_capped <- electricity_2020_clean$Population %>% cap()
boxplot(population_capped, ylab="Population")


electricity_capped <- electricity_2020_clean$`Access to electricity, urban (% of urban population)` %>% cap()
boxplot(electricity_capped, ylab="Access to electricity (% of population)")


people_electricity_capped <- electricity_2020_clean$Population_with_electricity %>% cap()
boxplot(people_electricity_capped, ylab="No of people with access to electricity")

Transform

Histograms and box plots created during the “Scan II” section, I observed that the variable ‘No of people with access to electricity’ is heavily right-skewed, meaning most of the data is concentrated on the left, with a few extreme values on the right.


hist(electricity_2020_clean$Population, main = "Histogram of non-transformed data")


hist(electricity_2020_clean$`Access to electricity, urban (% of urban population)`, main = "Histogram of non-transformed data")


hist(electricity_2020_clean$Population_with_electricity, main = "Histogram of non-transformed data")

Apply the method of logarithmic transformation to changing the Population into a normal distribution.


Norm_Population<-log10(electricity_2020_clean$Population)
hist(Norm_Population)

The data now follows as a normal distribution much more closely than earlier.

Reflection on Challenges and Ease

References

  1. Dr. Sona (2025) ‘Module 1’, [Module 1 Notes, MATH2349], RMIT University, Melbourne, accessed May 25 https://data-wrangling.stem.melbourne/module_01
  2. Dr. Sona (2025) ‘Module 2’, [Module 1 Notes, MATH2349], RMIT University, Melbourne, accessed May 25 https://data-wrangling.stem.melbourne/module_02
  3. Dr. Sona (2025) ‘Module 3’, [Module 1 Notes, MATH2349], RMIT University, Melbourne, accessed May 25 https://data-wrangling.stem.melbourne/module_03
  4. Dr. Sona (2025) ‘Module 4’, [Module 1 Notes, MATH2349], RMIT University, Melbourne, accessed May 26 https://data-wrangling.stem.melbourne/module_04
  5. Dr. Sona (2025) ‘Module 5’, [Module 1 Notes, MATH2349], RMIT University, Melbourne, accessed May 26 https://data-wrangling.stem.melbourne/module_05
  6. Dr. Sona (2025) ‘Module 6’, [Module 1 Notes, MATH2349], RMIT University, Melbourne, accessed May 26 https://data-wrangling.stem.melbourne/module_06
  7. Dr. Sona (2025) ‘Module 7’, [Module 1 Notes, MATH2349], RMIT University, Melbourne, accessed May 26 https://data-wrangling.stem.melbourne/module_07
  8. Stack overflow (2025), Stack overflow website, accessed 26 May 2025 https://stackoverflow.com/questions/13339685/how-to-replace-outliers-with-the-5th-and-95th-percentile-values-in-r?utm_medium=organic&utm_sourcegoogle_rich_qa&utm_campaign=google_rich_qa
  9. Urban population (2023) Worldbank.org, accessed May 25, 2025, https://data.worldbank.org/indicator/SP.URB.TOTL?end=2023&start=2000 Released under a Creative Commons Attribution BY-4.0 license.
  10. Urban Development | Data (2023) Worldbank.org, accessed May 25, 2025, https://data.worldbank.org/topic/urban-development. Released under a Creative Commons Attribution BY-4.0 license.
  11. R Core Team (2021). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria, accessed 27 May 2025 https://www.R-project.org/.

Presentation

[Data Wrangling Assignment 2 - s4150303]

Link: https://rmit-arc.instructuremedia.com/embed/40201e92-ab45-41b5-96d7-3b7e9dba84d8

LS0tCnRpdGxlOiAiTUFUSDIzNDkgRGF0YSBXcmFuZ2xpbmciCmF1dGhvcjogIkNoYW11ZGkgQWJleXNpbmdoZSAoczQxNTAzMDMpIgpzdWJ0aXRsZTogUHJhY3RpY2FsIEFzc2Vzc21lbnQgMgpkYXRlOiAiIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCgoKIyMgKipTZXR1cCoqCgpgYGB7cn0KCiMgTG9hZCBwYWNrYWdlcyAKCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeSh0aWR5cikKbGlicmFyeShkcGx5cikKI2luc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpCmxpYnJhcnkodGlkeXZlcnNlKQojaW5zdGFsbC5wYWNrYWdlcygiSG1pc2MiKQpsaWJyYXJ5KEhtaXNjKQpsaWJyYXJ5KGdncGxvdDIpCiNpbnN0YWxsLnBhY2thZ2VzKCJEZXNjVG9vbHMiKQpsaWJyYXJ5KERlc2NUb29scykKbGlicmFyeShtYWdyaXR0cikKCmBgYAoKCiMjICoqU3R1ZGVudCBOYW1lLCBTdHVkZW50IE51bWJlciBhbmQgUGVyY2VudGFnZSBvZiBDb250cmlidXRpb24qKgpgYGB7ciwgZWNobz1GQUxTRX0KCiMgQWRkIHlvdXIgbmFtZXMsIG51bWJlcnMgYW5kIHBlcmNlbnRhZ2Ugb2YgeW91ciBjb250cmlidXRpb24gaGVyZS4KCm5hPC0gYygiQ2hhbXVkaSBBYmV5c2luZ2hlIikKc248LSBjKCdzNDE1MDMwMycpCnBjPC0gYygiMTAwJSIpCgpzPC0gZGF0YS5mcmFtZShjYmluZChuYSxzbiwgcGMpKQpjb2xuYW1lcyhzKTwtIGMoIlN0dWRlbnQgbmFtZSIsICJTdHVkZW50IE51bWJlciIsICJQZXJjZW50YWdlIG9mIGNvbnRyaWJ1dGlvbiIpCgpzICU+JSBrYmwoY2FwdGlvbiA9ICJJbmRpdmlkdWFsIERldGFpbHMiKSAlPiUKICBrYWJsZV9jbGFzc2ljKGZ1bGxfd2lkdGggPSBGLCBodG1sX2ZvbnQgPSAiQ2FtYnJpYSIpCgpgYGAKCgojIyAqKkV4ZWN1dGl2ZSBTdW1tYXJ5KioKCi0gSWRlbnRpZmllZCB0d28gZGF0YSBzZXRzIHdoaWNoIGhhZCBtdWx0aXBsZSB5ZWFycyBhcyBzZXBhcmF0ZSBjb2x1bW5zLCB2aW9sYXRpbmcgdGlkeSBkYXRhIHByaW5jaXBsZXMgaW4gYm90aCBkYXRhIHNldHMuIEJvdGggZGF0YSBzZXRzIGluY2x1ZGVkIGEgY29tbW9uIHZhcmlhYmxlcywgIkNvdW50cnkgTmFtZSIsIGFuZCAiWWVhciIgd2hpY2ggd2FzIHVzZWQgZm9yIG1lcmdpbmcuCgotIENhdGVnb3JpY2FsIHZhcmlhYmxlcyBzdWNoIGFzICJDb3VudHJ5IE5hbWUiLCAiQ291bnRyeSBDb2RlIiwgIkluZGljYXRvciBDb2RlIiBhbmQgIkluZGljYXRvciBOYW1lIiB3ZXJlIGNvbnZlcnRlZCB0byBmYWN0b3IgdHlwZXMgdG8gb3B0aW1pemUgbWVtb3J5IHVzYWdlIGFuZCBpbXByb3ZlIGNsYXJpdHkgaW4gYW5hbHlzaXMuCgotIEkgdHJhbnNmb3JtZWQgdGhlIHdpZGUgZm9ybWF0ICh5ZWFycyBhcyBjb2x1bW5zKSBpbnRvIGEgbG9uZyBmb3JtYXQgdXNpbmcgZ2F0aGVyKCkuIFRoaXMgc3RlcCBjcmVhdGVkIGEgc2luZ2xlICJZZWFyIiBjb2x1bW4gYW5kIGEgY29ycmVzcG9uZGluZyAiVmFsdWUiIGNvbHVtbiwgbWFraW5nIHRoZSBkYXRhIHRpZHkgYW5kIGVhc2llciB0byB3b3JrIHdpdGguCgotIEkgdXNlZCBzcHJlYWQoKSB0byBzZXBhcmF0ZSB2YWx1ZXMgaW4gdGhlICJJbmRpY2F0b3IgTmFtZSIgY29sdW1uIGludG8gZGlzdGluY3QgdmFyaWFibGVzIChlLmcuLCBwb3B1bGF0aW9uLCBlbGVjdHJpY2l0eSBhY2Nlc3MpLiBUaGlzIGFsbG93ZWQgZWFjaCBpbmRpY2F0b3IgdG8gaGF2ZSBpdHMgb3duIGNvbHVtbi4KCi0gVGhlICJZZWFyIiB2YXJpYWJsZSB3YXMgY2hhbmdlZCBpbnRvIGFuIG9yZGVyZWQgZmFjdG9yIHRvIGVuc3VyZSBjb3JyZWN0IHNvcnRpbmcgaW4gdmlzdWFsaXphdGlvbnMuCgotIE1lcmdlZCBEYXRhc2V0cyB3aXRoIGxlZnRfam9pbigpLiBDb21iaW5lZCB0aGUgdHdvIHRpZHkgZGF0YSBzZXRzIHVzaW5nIGEgbmF0dXJhbCBqb2luIG9uICJDb3VudHJ5IE5hbWUiIGFuZCAiWWVhciIuIFRoaXMgcmV0YWluZWQgYWxsIHJlY29yZHMgZnJvbSB0aGUgcG9wdWxhdGlvbiBkYXRhIHNldCBhbmQgYWRkZWQgbWF0Y2hpbmcgdmFsdWVzIGZyb20gdGhlIGRldmVsb3BtZW50IGRhdGEgc2V0LgoKLSBTZWxlY3RlZCBSZWxldmFudCBWYXJpYWJsZXMuIEkgbmFycm93ZWQgZG93biB0byBmb3VyIGtleSB2YXJpYWJsZXM6ICJDb3VudHJ5IE5hbWUiLCAiWWVhciIsICJQb3B1bGF0aW9uIiwgYW5kICJBY2Nlc3MgdG8gZWxlY3RyaWNpdHksIHVyYmFuICglIG9mIHVyYmFuIHBvcHVsYXRpb24pIiwgZm9jdXNpbmcgdGhlIGRhdGEgc2V0IG9uIHZhcmlhYmxlcyBjcml0aWNhbCB0byB0aGUgYW5hbHlzaXMuCgotIFNjYW5uZWQgYW5kIENsZWFuZWQgRGF0YS4gQ2hlY2tlZCBhbmQgcmVtb3ZlZCBtaXNzaW5nIHZhbHVlcyAoTkEpLCBzcGVjaWFsIHZhbHVlcyAoSW5mLCBOYU4pLCBhbmQgaW5jb25zaXN0ZW5jaWVzLgoKCiMjICoqRGF0YSoqCgpUaGUgZGF0YSBzZXRzIHdlcmUgc291cmNlZCBmcm9tIHRoZSBXb3JsZCBCYW5rIERhdGEgcmVwb3NpdG9yeS4gT25lIG9mIHRoZW0sIFVyYmFuIFBvcHVsYXRpb24uY3N2LCBjb250YWlucyBpbmZvcm1hdGlvbiBvbiBwZW9wbGUgbGl2aW5nIGluIHVyYmFuIGFyZWFzLCBiYXNlZCBvbiBkZWZpbml0aW9ucyBwcm92aWRlZCBieSBlYWNoIGNvdW50cnkncyBuYXRpb25hbCBzdGF0aXN0aWNhbCBvZmZpY2UuIFRoZSBkYXRhIGlzIG9yZ2FuaXplZCBieSBjb3VudHJ5IGFuZCBjb3ZlcnMgdGhlIHllYXJzIGZyb20gMTk2MCB0byAyMDIzLgoKVGhlIHNlY29uZCBkYXRhIHNldCBpcyAnVXJiYW4gRGV2ZWxvcG1lbnQuY3N2JyB3aGljaCBsaXN0cyB1cmJhbiBkZXZlbG9wbWVudCBpbmRpY2F0b3JzIGJ5IGNvdW50cnkgZm9yIHRoZSBzYW1lIHBlcmlvZCBvZiB0aW1lLiAKCkluIFVyYmFuIERldmVsb3BtZW50ICgyMDIzKSBtZW50aW9ucywgZGF0YSBvbiB1cmJhbml6YXRpb24sIHRyYWZmaWMgYW5kIGNvbmdlc3Rpb24sIGFuZCBhaXIgcG9sbHV0aW9uIGFyZSBmcm9tIHRoZSBVbml0ZWQgTmF0aW9ucyBQb3B1bGF0aW9uIERpdmlzaW9uLCBXb3JsZCBIZWFsdGggT3JnYW5pemF0aW9uLCBJbnRlcm5hdGlvbmFsIFJvYWQgRmVkZXJhdGlvbiwgV29ybGQgUmVzb3VyY2VzIEluc3RpdHV0ZSwgYW5kIG90aGVyIHNvdXJjZXMuCgpCb3RoIHNldHMgY29udGFpbiDigJhDb3VudHJ5IE5hbWXigJkgYW5kICdDb3VudHJ5IENvZGUnIHZhcmlhYmxlcy4KCk1vcmUgdmFyaWFibGUgZGVzY3JpcHRpb25zIHdpbGwgYmUgcHJvdmlkZWQgbGF0ZXIgb24gdGhpcyByZXBvcnQuIAoKQWZ0ZXIgbG9hZGluZyB0aGUgZGF0YSBzZXRzLCBJIGNob3NlIHRvIGZvY3VzIG9ubHkgb24gdGhlIG1vc3QgcmVjZW50IHNpeCB5ZWFycyAoMjAxOCB0byAyMDIzKSB0byBrZWVwIHRoaW5ncyBjb25jaXNlLiBUaGlzIGRvZXNu4oCZdCBhZmZlY3QgdGhlIGRhdGEgd3JhbmdsaW5nIG1ldGhvZHMgdXNlZCBsYXRlciwgYXMgdGhleSByZW1haW4gdGhlIHNhbWUuCgoKIyMgKipTb3VyY2Ugb2YgRGF0YSoqCgpVcmJhbiBwb3B1bGF0aW9uICgyMDIzKSBXb3JsZGJhbmsub3JnLCBSZXRyaWV2ZWQgTWF5IDI1LCAyMDI1LApodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy9pbmRpY2F0b3IvU1AuVVJCLlRPVEw/ZW5kPTIwMjMmc3RhcnQ9MjAwMCBSZWxlYXNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24gQlktNC4wIGxpY2Vuc2UuCgpUaGlzIHdhcyBzb3VyY2VkIGJ5IFdvcmxkIEJhbmsgc3RhZmYgZXN0aW1hdGVzIGJhc2VkIG9uIHRoZSBVbml0ZWQgTmF0aW9ucyBQb3B1bGF0aW9uIERpdmlzaW9uJ3MgV29ybGQgVXJiYW5pemF0aW9uIFByb3NwZWN0czogMjAxOCBSZXZpc2lvbi4KClVyYmFuIERldmVsb3BtZW50ICgyMDIzKSBXb3JsZGJhbmsub3JnLCBSZXRyaWV2ZWQgTWF5IDI1LCAyMDI1LCBodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy90b3BpYy91cmJhbi1kZXZlbG9wbWVudC4gUmVsZWFzZWQgdW5kZXIgYSBDcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uIEJZLTQuMCBsaWNlbnNlLgoKVGhpcyB3YXMgc291cmNlZCBieSBXb3JsZCBCYW5rIHN0YWZmIGVzdGltYXRlcyBiYXNlZCBvbiB0aGUgVW5pdGVkIE5hdGlvbnMgUG9wdWxhdGlvbiBEaXZpc2lvbidzIFdvcmxkIFVyYmFuaXphdGlvbiBQcm9zcGVjdHM6IDIwMTggUmV2aXNpb24uCgojIyAqKkRhdGEgc2V0IEkqKgoKSW4gJ1VyYmFuIFBvcHVsYXRpb24uY3N2JywgdGhlcmUgYXJlIDI2NiBvYnNlcnZhdGlvbnMgYW5kIDEwIHZhcmlhYmxlcy4KClZhcmlhYmxlIERlc2NyaXB0aW9uIGZvciAnVXJiYW4gUG9wdWxhdGlvbi5jc3YnIGFzIGJlbG93OiAKCnwgKipDb2x1bW4gTmFtZSoqICB8ICoqRGVzY3JpcHRpb24qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IC0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwKfCBgQ291bnRyeSBOYW1lYCAgIHwgTmFtZSBvZiB0aGUgY291bnRyeS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgYENvdW50cnkgQ29kZWAgICB8IENvdW50cnkgY29kZSAoZXg6ICJVU0EiIC0gVW5pdGVkIFN0YXRlcykgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IGBJbmRpY2F0b3IgTmFtZWAgfCBUaGUgbmFtZSBvZiB0aGUgaW5kaWNhdG9yIChleDogIlVyYmFuIHBvcHVsYXRpb24iKSAgICAgICAgICAgICAgIHwKfCBgSW5kaWNhdG9yIENvZGVgIHwgQ29kZSB1c2VkIHRvIHJlcHJlc2VudCB0aGUgaW5kaWNhdG9yIChleDogIlNQLlVSQi5UT1RMIikgICAgICAgICB8CnwgYDE5NjBgIHRvIGAyMDI0YCB8IFVyYmFuIHBvcHVsYXRpb24gZGF0YSBmb3IgZWFjaCBjb3JyZXNwb25kaW5nIHllYXIgICAgICAgICAgICAgICAgfAoKYGBge3J9CiMgSW1wb3J0IHRoZSB1cmJhbiBwb3B1bGF0aW9uIGRhdGEsIHNraXAgdGhlIGZpcnN0IDQgbWV0YWRhdGEgcm93cyB3aGlsZSBpbXBvcnRpbmcKCnVyYmFuX3BvcHVsYXRpb24gPC0gcmVhZF9jc3YoIi9Vc2Vycy9jaGFtdWRpL0Rlc2t0b3AvUk1JVC8xc3QgWWVhciAxc3QgU2VtZXN0ZXIvRGF0YSBXcmFuZ2xpbmcvQXNzaWdubWVudHMvQXNzaWdubWVudCAyL0RhdGFzZXQvMS9VcmJhbiBQb3B1bGF0aW9uLmNzdiIsIHNraXAgPSA0KSAKCiNzZWxlY3QgY29sdW1ucyAxIHRvIDQgYW5kIDYzIHRvIDY4IC0gcmVhc29uIGlzIG1lbnRpb25lZCBpbiAnRGF0YScgc2VjdGlvbi4KdXJiYW5fcG9wdWxhdGlvbiA8LSB1cmJhbl9wb3B1bGF0aW9uICU+JQogIHNlbGVjdChjKDE6NCwgNjM6NjgpKQoKI2Rpc3BsYXkgdGhlIGZpcnN0IGZldyByb3dzCmtuaXRyOjprYWJsZShoZWFkKHVyYmFuX3BvcHVsYXRpb24pKQoKCgpgYGAKCiMjICoqRGF0YSBzZXQgSUkqKgoKSW4gdGhlICdVcmJhbiBEZXZlbG9wbWVudC5jc3YnLCB0aGVyZSBhcmUgNDUyMiBvYnNlcnZhdGlvbnMgYW5kIDEwIHZhcmlhYmxlcy4KClZhcmlhYmxlIERlc2NyaXB0aW9uIGZvciAnVXJiYW4gRGV2ZWxvcG1lbnQuY3N2JyBhcyBiZWxvdzogCgp8ICoqQ29sdW1uIE5hbWUqKiAgfCAqKkRlc2NyaXB0aW9uKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwKfCBgQ291bnRyeSBOYW1lYCAgIHwgTmFtZSBvZiB0aGUgY291bnRyeSAoZXg6ICJJbmRpYSIsICJCcmF6aWwiKS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IGBDb3VudHJ5IENvZGVgICAgfCBDb3VudHJ5IGNvZGUgKGV4OiAiVVNBIiBmb3IgVW5pdGVkIFN0YXRlcykuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgYEluZGljYXRvciBOYW1lYCB8IFRoZSBuYW1lIG9mIHRoZSBkZXZlbG9wbWVudCBpbmRpY2F0b3IsIGxpa2VseSBhbGwgIlVyYmFuIHBvcHVsYXRpb24iLiAgICAgICAgICAgICAgIHwKfCBgSW5kaWNhdG9yIENvZGVgIHwgVGhlIG9mZmljaWFsIGNvZGUgZm9yIHRoZSBpbmRpY2F0b3IuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IGAxOTYwYCB0byBgMjAyNGAgfCBBbm51YWwgdmFsdWVzIGZvciB0aGUgaW5kaWNhdG9yIGZyb20gMTk2MCB0byAyMDI0LiBFYWNoIHllYXIgaXMgYSBzZXBhcmF0ZSBjb2x1bW4uICB8CgoKYGBge3J9CiMgSW1wb3J0IHRoZSB1cmJhbiBkZXZlbG9wbWVudCBkYXRhLCBza2lwIHRoZSBmaXJzdCA0IG1ldGFkYXRhIHJvd3Mgd2hpbGUgaW1wb3J0aW5nCgp1cmJhbl9kZXZlbG9wbWVudCA8LSByZWFkX2NzdigiL1VzZXJzL2NoYW11ZGkvRGVza3RvcC9STUlULzFzdCBZZWFyIDFzdCBTZW1lc3Rlci9EYXRhIFdyYW5nbGluZy9Bc3NpZ25tZW50cy9Bc3NpZ25tZW50IDIvRGF0YXNldC8yL1VyYmFuIERldmVsb3BtZW50LmNzdiIsIHNraXAgPSA0KSAKCiNzZWxlY3QgY29sdW1ucyAxIHRvIDQgYW5kIDYzIHRvIDY4IC0gcmVhc29uIGlzIG1lbnRpb25lZCBpbiAnRGF0YScgc2VjdGlvbi4KdXJiYW5fZGV2ZWxvcG1lbnQgPC0gdXJiYW5fZGV2ZWxvcG1lbnQgJT4lCiAgc2VsZWN0KGMoMTo0LCA2Mzo2OCkpCgojZGlzcGxheSB0aGUgZmlyc3QgZmV3IHJvd3MKa25pdHI6OmthYmxlKGhlYWQodXJiYW5fZGV2ZWxvcG1lbnQpKQoKYGBgCgpTdWItc2V0dGluZzogTm93IEkgYW0gY3JlYXRpbmcgcmFuZG9tIHN1YnNldHMgdXNpbmcgbXkgc3R1ZGVudCBudW1iZXIgczQxNTAzMDMuIFNpbmNlIHNldC5zZWVkKCkgb25seSBhY2NlcHRzIG51bWVyaWMgdmFsdWVzLCBJIG5lZWQgdG8gZXh0cmFjdCB0aGUgbnVtZXJpYyBwYXJ0IG9mIG15IHN0dWRlbnQgbnVtYmVyOiA0MTUwMzAzLgoKSW4gdGhlIHVyYmFuX3BvcHVsYXRpb25fc3Vic2V0LCB0aGVyZSBhcmUgMjEyIG9ic2VydmF0aW9ucyBhbmQgMTAgdmFyaWFibGVzLgoKSW4gdGhlIHVyYmFuX2RldmVsb3BtZW50X3N1YnNldCwgdGhlcmUgYXJlIDM2MTcgb2JzZXJ2YXRpb25zIGFuZCAxMCB2YXJpYWJsZXMuCgpgYGB7cn0KIyBTZXQgc2VlZCB1c2luZyBudW1lcmljIHBhcnQgb2YgeW91ciBzdHVkZW50IG51bWJlcgpzZXQuc2VlZCg0MTUwMzAzKQoKIyBDYWxjdWxhdGUgZGVzaXJlZCBudW1iZXIgb2Ygcm93cyAoYXQgbGVhc3QgODAlIGFzIGluIHRoZSBzcGVjaWZpY2F0aW9uKQp1cmJhbl9wb3B1bGF0aW9uX3Jvd3MgPC0gZmxvb3IoMC44ICogbnJvdyh1cmJhbl9wb3B1bGF0aW9uKSkKdXJiYW5fZGV2ZWxvcG1lbnRfcm93cyA8LSBmbG9vcigwLjggKiBucm93KHVyYmFuX2RldmVsb3BtZW50KSkKCiMgUmFuZG9tbHkgc2VsZWN0IDgwJSBvZiByb3dzIGZvciBlYWNoIGRhdGEgc2V0CnVyYmFuX3BvcHVsYXRpb25fc3Vic2V0IDwtIHVyYmFuX3BvcHVsYXRpb25bc2FtcGxlKG5yb3codXJiYW5fcG9wdWxhdGlvbiksIHVyYmFuX3BvcHVsYXRpb25fcm93cyksIF0KdXJiYW5fZGV2ZWxvcG1lbnRfc3Vic2V0IDwtIHVyYmFuX2RldmVsb3BtZW50W3NhbXBsZShucm93KHVyYmFuX2RldmVsb3BtZW50KSwgdXJiYW5fZGV2ZWxvcG1lbnRfcm93cyksIF0KCiMgRGlzcGxheSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgc3Vic2V0cwprbml0cjo6a2FibGUoaGVhZCh1cmJhbl9wb3B1bGF0aW9uX3N1YnNldCkpCmtuaXRyOjprYWJsZShoZWFkKHVyYmFuX2RldmVsb3BtZW50X3N1YnNldCkpCgpgYGAKCiMjICoqVW5kZXJzdGFuZCBJKiogCgpUbyBnZXQgYW4gdW5kZXJzdGFuZCBhYm91dCB0aGUgc3Vic2V0IGRhdGEgc2V0LCBJIGZpcnN0IGNoZWNrZWQgdGhlIGRhdGEgdHlwZXMuIAoKVGhlIGRhdGEgc2V0IGNvbnRhaW5zIDIxMiBvYnNlcnZhdGlvbnMgYW5kIDEwIHZhcmlhYmxlcy4gCgpBbGwgY29sdW1ucyBhcmUgc3RvcmVkIGFzIGNoYXJhY3RlciBkYXRhLCB3aGlsZSB0aGUgY29sdW1ucyBmb3IgdGhlIHllYXJzIDIwMTggdG8gMjAyMyBhcmUgbnVtZXJpYy4gSSBkZWNpZGVkIHRvIGNvbnZlcnQgdGhlIGNoYXJhY3RlciB2YXJpYWJsZXMgaW50byBmYWN0b3JzIGJlY2F1c2UsIGluIGxhdGVyIHNlY3Rpb25zIGludm9sdmluZyBzdGF0aXN0aWNhbCBtb2RlbGluZywgaXQncyBpbXBvcnRhbnQgdG8gdHJlYXQgdGhlc2UgYXMgY2F0ZWdvcmljYWwgZ3JvdXBzIHJhdGhlciB0aGFuIHBsYWluIHRleHQuIFRoaXMgYWxzbyBoZWxwcyBpbXByb3ZlIGJvdGggZWZmaWNpZW5jeSBhbmQgcGVyZm9ybWFuY2UgZHVyaW5nIGFuYWx5c2lzLgoKCmBgYHtyfQojIENoZWNrIGluaXRpYWwgc3RydWN0dXJlCnN0cih1cmJhbl9wb3B1bGF0aW9uX3N1YnNldCkKCiMgQ29udmVydCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgdG8gZmFjdG9ycwp1cmJhbl9wb3B1bGF0aW9uX3N1YnNldCA8LSB1cmJhbl9wb3B1bGF0aW9uX3N1YnNldCAlPiUKICBtdXRhdGUoCiAgICBgQ291bnRyeSBOYW1lYCA9IGFzLmZhY3RvcihgQ291bnRyeSBOYW1lYCksCiAgICBgQ291bnRyeSBDb2RlYCA9IGFzLmZhY3RvcihgQ291bnRyeSBDb2RlYCksCiAgICBgSW5kaWNhdG9yIE5hbWVgID0gYXMuZmFjdG9yKGBJbmRpY2F0b3IgTmFtZWApLAogICAgYEluZGljYXRvciBDb2RlYCA9IGFzLmZhY3RvcihgSW5kaWNhdG9yIENvZGVgKQogICkKCiMgVmlldyBzdHJ1Y3R1cmUgYWZ0ZXIgY29udmVyc2lvbgpnbGltcHNlKHVyYmFuX3BvcHVsYXRpb25fc3Vic2V0KQoKIyBWaWV3IHN1bW1hcnkgc3RhdGlzdGljcwpzdW1tYXJ5KHVyYmFuX3BvcHVsYXRpb25fc3Vic2V0KQoKc3RyKHVyYmFuX3BvcHVsYXRpb25fc3Vic2V0KQoKYGBgClVuZGVyc3RhbmQgdGhlIFVyYmFuIERldmVsb3BtZW50IHN1YnNldCBkYXRhc2V0LgoKSSBmb2xsb3dlZCB0aGUgc2FtZSB0aGluZyBmb3IgdGhpcyBkYXRhc2V0IGFzIHdlbGwuCgpgYGB7cn0KIyBWaWV3IHN0cnVjdHVyZSBvZiB0aGUgZGF0YSBzZXQKc3RyKHVyYmFuX2RldmVsb3BtZW50X3N1YnNldCkKCiMgQ29udmVydCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgdG8gZmFjdG9yIHR5cGUKdXJiYW5fZGV2ZWxvcG1lbnRfc3Vic2V0IDwtIHVyYmFuX2RldmVsb3BtZW50X3N1YnNldCAlPiUKICBtdXRhdGUoCiAgICBgQ291bnRyeSBOYW1lYCA9IGFzLmZhY3RvcihgQ291bnRyeSBOYW1lYCksCiAgICBgQ291bnRyeSBDb2RlYCA9IGFzLmZhY3RvcihgQ291bnRyeSBDb2RlYCksCiAgICBgSW5kaWNhdG9yIE5hbWVgID0gYXMuZmFjdG9yKGBJbmRpY2F0b3IgTmFtZWApLAogICAgYEluZGljYXRvciBDb2RlYCA9IGFzLmZhY3RvcihgSW5kaWNhdG9yIENvZGVgKQogICkKCiMgUmUtY2hlY2sgc3RydWN0dXJlIGFmdGVyIHR5cGUgY29udmVyc2lvbgpnbGltcHNlKHVyYmFuX2RldmVsb3BtZW50X3N1YnNldCkKCiMgVmlldyBzdW1tYXJ5IHN0YXRpc3RpY3MKc3VtbWFyeSh1cmJhbl9kZXZlbG9wbWVudF9zdWJzZXQpCgpzdHIodXJiYW5fZGV2ZWxvcG1lbnRfc3Vic2V0KQoKYGBgCgojIwkqKlRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSSAqKgoKVGhlIG9yaWdpbmFsIGRhdGEgc2V0cyBhcmVu4oCZdCBpbiBhIHRpZHkgZm9ybWF0LCBhcyBtYWlubHkgdGhlICdZZWFyJyBjb2x1bW4gZG9lc27igJl0IHJlcHJlc2VudCBhIHNpbmdsZSB2YXJpYWJsZSB3aGljaCBnb2VzIGFnYWluc3QgdGhlIHByaW5jaXBsZXMgb2YgdGlkeSBkYXRhLgoKUmVwZWF0aW5nICdVcmJhbiBwb3B1bGF0aW9uJyBjZWxsIGRhdGEgaW4gJ2luZGljYXRvciBOYW1lJyBkb2Vzbid0IG1lYW4gdGhlIGRhdGEgc2V0IHVudGlkeS4gVGhlcmVmb3JlLCBJIGFtIG9ubHkgZGVhbGluZyB3aXRoIHVyYmFuIHBvcHVsYXRpb24gb25seSBpdCdzIG9rYXkgYW5kIHNhZmUgdG8gZHJvcCB0aGUgY29sdW1uIHRvIG1ha2UgdGhlIGRhdGEgc2V0IG1vcmUgY29uY2lzZS4KCkFkZGl0aW9uYWxseSwgaW4gdGhlIHVyYmFuIGRldmVsb3BtZW50IHRoZSAnSW5kaWNhdG9yIE5hbWUnIGNvbHVtbiBjb250YWlucyBtdWx0aXBsZSB0eXBlcyBvZiBpbmZvcm1hdGlvbiwgd2hpY2ggc2hvdWxkIGJlIHNlcGFyYXRlZCBpbnRvIGRpc3RpbmN0IHZhcmlhYmxlcy4gCgpUbyBmaXggdGhpcywgSSdsbCBzdGFydCBieSB1c2luZyBnYXRoZXIoKS4gVGhpcyB3aWxsIHR1cm4gdGhlIHNlcGFyYXRlIHllYXIgY29sdW1ucyBpbnRvIGEgc2luZ2xlICdZZWFyJyBjb2x1bW4sIHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgdmFsdWVzIGluIGFub3RoZXIgY29sdW1uIGFzICdQb3B1bGF0aW9uJwoKCmBgYHtyfQojSSBjb21iaW5lZCBhbGwgdGhlIHllYXIgY29sdW1ucyBpbnRvIG9uZSB1c2luZyB0aGUgZ2F0aGVyKCkgZnVuY3Rpb24uIEkgYWxzbyByZW1vdmVkIHVubmVjZXNzYXJ5IGNvbHVtbnMgbGlrZSAiQ291bnRyeSBDb2RlIiBhbmQgIkluZGljYXRvciBDb2RlIiB0byBrZWVwIHRoZSBkYXRhIGNsZWFuZXIgYW5kIG1vcmUgZm9jdXNlZC4KCnBvcHVsYXRpb25fZ2F0aGVyIDwtIHVyYmFuX3BvcHVsYXRpb25fc3Vic2V0ICU+JSBnYXRoZXIoNToxMCwga2V5ID0gIlllYXIiLCB2YWx1ZSA9ICJQb3B1bGF0aW9uIikgJT4lICBzZWxlY3QoYygxLCAzLCA1LCA2KSkgCgojUmVwZWF0aW5nICdVcmJhbiBwb3B1bGF0aW9uJyBjZWxsIGRhdGEgaW4gImluZGljYXRvciBOYW1lIiBkb2Vzbid0IG1lYW4gdGhlIGRhdGEgc2V0IHVudGlkeS4gVGhlcmVmb3JlLCBJIGFtIG9ubHkgZGVhbGluZyB3aXRoIHVyYmFuIHBvcHVsYXRpb24gb25seSBpdCdzIG9rYXkgYW5kIHNhZmUgdG8gZHJvcCB0aGUgY29sdW1uIHRvIG1ha2UgdGhlIGRhdGEgc2V0IG1vcmUgY29uY2lzZS4KCnBvcHVsYXRpb25fbmV3X2dhdGhlciA8LSBwb3B1bGF0aW9uX2dhdGhlciAlPiUKICBzZWxlY3QoLWBJbmRpY2F0b3IgTmFtZWApCgpoZWFkKHBvcHVsYXRpb25fbmV3X2dhdGhlcikKCmBgYAoKTG9va2luZyBhdCB0aGUgbW9kaWZpZWQgdXJiYW4gcG9wdWxhdGlvbiBkYXRhIHNldCwgd2UgY2FuIG5vdyBzZWUgdGhhdCBpdCBjb250YWlucyBvbmx5IHRocmVlIHJlbWFpbmluZyB2YXJpYWJsZXMuCgpOZXh0LCB0aGUgIkluZGljYXRvciBOYW1lIiBjb2x1bW4gaW4gdGhlIHVyYmFuIGRldmVsb3BtZW50LmNzdiB3aWxsIGJlIHNlcGFyYXRlZCBpbnRvIGluZGl2aWR1YWwgdmFyaWFibGVzIHVzaW5nIHRoZSBzcHJlYWQoKSBmdW5jdGlvbi4gCgpgYGB7cn0KI1NhbWUgYXMgYmVmb3JlCmRldmVsb3BtZW50X2dhdGhlciA8LSB1cmJhbl9kZXZlbG9wbWVudF9zdWJzZXQgJT4lIGdhdGhlcig1OjEwLCBrZXkgPSAiWWVhciIsIHZhbHVlID0gIkRldmVsb3BtZW50IikgJT4lICBzZWxlY3QoYygxLCAzLCA1LCA2KSkgCgojU3BsaXQgdGhlICJJbmRpY2F0b3IgTmFtZSIgaW50byBtdWx0aXBsZSBjb2x1bW5zIHVzaW5nIHNwcmVhZCgpCmRldmVsb3BtZW50X3NwcmVhZCA8LSBzcHJlYWQoZGV2ZWxvcG1lbnRfZ2F0aGVyLCBrZXkgPSAiSW5kaWNhdG9yIE5hbWUiLCB2YWx1ZSA9ICJEZXZlbG9wbWVudCIpCgpoZWFkKGRldmVsb3BtZW50X3NwcmVhZCkKCmBgYAoKCiMjCSoqVW5kZXJzdGFuZCBJSSAqKgoKQ29udmVydGluZyB0aGUgIlllYXIiIHZhcmlhYmxlIHRvIGFuIG9yZGVyZWQgZmFjdG9yIGlzIGltcG9ydGFudCBlc3BlY2lhbGx5IGluIHRoZSBjb250ZXh0IG9mIGRhdGEgYW5hbHlzaXMgYW5kIHZpc3VhbGl6YXRpb24uIAoKYGBge3J9CgojVGhlIOKAnFllYXLigJ0gdmFyaWFibGUgc2hvdWxkIGJlIGEgb3JkZXJlZCBmYWN0b3IgdmFyaWFibGUuCgpwb3B1bGF0aW9uX25ld19nYXRoZXIkWWVhciA8LSBwb3B1bGF0aW9uX25ld19nYXRoZXIkWWVhciAlPiUgZmFjdG9yKGxldmVscyA9IGMoIjIwMTgiLCAiMjAxOSIsICIyMDIwIiwgIjIwMjEiLCAiMjAyMiIsICIyMDIzIiksIG9yZGVyZWQgPSBUUlVFKQoKbGV2ZWxzKHBvcHVsYXRpb25fbmV3X2dhdGhlciRZZWFyKQoKc3RyKHBvcHVsYXRpb25fbmV3X2dhdGhlcikKCmBgYAogCgpgYGB7cn0KCiNUaGUg4oCcWWVhcuKAnSB2YXJpYWJsZSBzaG91bGQgYmUgYSBvcmRlcmVkIGZhY3RvciB2YXJpYWJsZS4KCmRldmVsb3BtZW50X3NwcmVhZCRZZWFyIDwtIGRldmVsb3BtZW50X3NwcmVhZCRZZWFyICU+JSBmYWN0b3IobGV2ZWxzID0gYygiMjAxOCIsICIyMDE5IiwgIjIwMjAiLCAiMjAyMSIsICIyMDIyIiwgIjIwMjMiKSwgb3JkZXJlZCA9IFRSVUUpCgpsZXZlbHMoZGV2ZWxvcG1lbnRfc3ByZWFkJFllYXIpCgpzdHIoZGV2ZWxvcG1lbnRfc3ByZWFkKQoKYGBgCgoKIyMgKipUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIEkgQ29udC4qKiAKCk5vdyBhcyBib3RoIGRhdGEgc2V0cyBhcmUgaW4gYSB0aWR5IGZvcm1hdCwgaXQgd2lsbCBiZSBtZXJnZWQgdXNpbmcgYSBsZWZ0IGpvaW4gYmFzZWQgb24gdGhlIGNvbW1vbiB2YXJpYWJsZXMgIkNvdW50cnkgTmFtZSIgYW5kICJZZWFyIi4gQSBsZWZ0IGpvaW4gZW5zdXJlcyB0aGF0IGFsbCBvYnNlcnZhdGlvbnMgZnJvbSB0aGUgcG9wdWxhdGlvbiBkYXRhIHNldCBhcmUgcmV0YWluZWQsIHdoaWxlIG1hdGNoaW5nIHZhbHVlcyBmcm9tIHRoZSBkZXZlbG9wbWVudCBkYXRhIHNldCBhcmUgYWRkZWQgd2hlcmV2ZXIgYXZhaWxhYmxlLgoKYGBge3J9CgojTWVyZ2UgdXNpbmcgbmF0dXJhbCBqb2luCnBvcHVsYXRpb25fZGV2ZWxvcG1lbnQgPC0gcG9wdWxhdGlvbl9uZXdfZ2F0aGVyICU+JQogIGxlZnRfam9pbihkZXZlbG9wbWVudF9zcHJlYWQsIGJ5ID0gYygiQ291bnRyeSBOYW1lIiwgIlllYXIiKSkKCmhlYWQocG9wdWxhdGlvbl9kZXZlbG9wbWVudCkKCiNjaG9vc2luZyB0aGUgY29sdW1ucyAKcG9wdWxhdGlvbl9kZXZlbG9wbWVudDIgPC0gcG9wdWxhdGlvbl9kZXZlbG9wbWVudCAlPiUgc2VsZWN0KGMoMSwgMiwgMywgNCkpCgpzdHIocG9wdWxhdGlvbl9kZXZlbG9wbWVudDIpCgoKYGBgClZhcmlhYmxlIERlc2NyaXB0aW9uOgogIEluIHRoZSBkYXRhIGZyYW1lIHRoZXJlIGFyZSBvbmx5IDQgcmVtYWluaW5nIHZhcmlhYmxlcyBpdCBoYXMgMTI3MiBvYnNlcnZhdGlvbnM6CiAgCgp8ICoqQ29sdW1uIE5hbWUqKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICoqRGVzY3JpcHRpb24qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgLS0tLS0tLS0tLS0tLS0tLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgICAgIHwKfCBgQ291bnRyeSBOYW1lYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBUaGVyZSBhcmUgMjY2IGNvdW50cmllcy4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IGBZZWFyYC4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IEFuIG9yZGVyZWQgZmFjdG9yIHZhcmlhYmxlIHRvIHNob3cgdGhlIG9yZGVyIGluIHdoaWNoIHRoZSBkYXRhIHdhcyBjb2xsZWN0ZWQsIGZyb20gdGhlIG9sZGVzdCB5ZWFyIHRvIHRoZSBtb3N0IHJlY2VudCB8CnwgYFBvcHVsYXRpb25gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgVG90YWwgcG9wdWxhdGlvbiBvZiBhIGNvdW50cnkgaW4gYW55IGdpdmVuIHllYXIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCBgQWNjZXNzIHRvIGVsZWN0cmljaXR5LCB1cmJhbiAoJSBvZiB1cmJhbiBwb3B1bGF0aW9uKWAgfCBUaGUgcGVyY2VudGFnZSBvZiBwb3B1bGF0aW9uIHdpdGggYWNjZXNzIHRvIGVsZWN0cmljaXR5IGluIGFueSBnaXZlbiB5ZWFyLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAogCgojIyAqKlRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSUkqKiAKCkluIHRoaXMgc2VjdGlvbiwgSeKAmWxsIGNhbGN1bGF0ZSB0aGUgdG90YWwgbnVtYmVyIG9mIHBlb3BsZSB3aXRoIGFjY2VzcyB0byBlbGVjdHJpY2l0eSBpbiBlYWNoIGNvdW50cnkgZm9yIHRoZSB5ZWFyIDIwMjAuIAoKQ2FsY3VsYXRpb24gaXMgYXMgYmVsb3cuCgpgYGB7cn0KCiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiBmb3IgdG90YWwgbnVtYmVyIHdpdGggYWNjZXNzIHRvIGVsZWN0cmljaXR5IGluIDIwMjAKZWxlY3RyaWNpdHlfMjAyMCA8LSBwb3B1bGF0aW9uX2RldmVsb3BtZW50MiAlPiUKICBmaWx0ZXIoWWVhciA9PSAyMDIwKSAlPiUgc2VsZWN0KDEsMyw0KSAlPiUKICBtdXRhdGUoCiAgICBQb3B1bGF0aW9uX3dpdGhfZWxlY3RyaWNpdHkgPSBQb3B1bGF0aW9uICogYEFjY2VzcyB0byBlbGVjdHJpY2l0eSwgdXJiYW4gKCUgb2YgdXJiYW4gcG9wdWxhdGlvbilgIC8gMTAwCiAgKQoKIyBWaWV3IHRoZSByZXN1bHQKaGVhZChlbGVjdHJpY2l0eV8yMDIwKQoKc3RyKGVsZWN0cmljaXR5XzIwMjApCgoKYGBgCgoKIyMJKipTY2FuIEkgKioKCkluIHRoaXMgc2VjdGlvbiwgSSBjaGVja2VkIHRoZSBkYXRhIGZvciBhbnkgbWlzc2luZyB2YWx1ZXMsIHVudXN1YWwgZW50cmllcywgb3IgaW5jb25zaXN0ZW5jaWVzLgoKYGBge3J9CiNtaXNzaW5nIHZhbHVlcwpzdW0oaXMubmEoZWxlY3RyaWNpdHlfMjAyMCkpCmNvbFN1bXMoaXMubmEoZWxlY3RyaWNpdHlfMjAyMCkpCgpgYGAKCmBgYHtyfQoKI3NwZWNpYWwgdmFsdWVzCnNhcHBseShlbGVjdHJpY2l0eV8yMDIwLCBmdW5jdGlvbih4KSBzdW0oaXMuaW5maW5pdGUoeCkgfCBpcy5uYW4oeCkpKQoKYGBgCgpUaGVyZSBhcmUgbm8gaW5maW5pdGUgb3IgTmFOIHZhbHVlcyBpbiB0aGUgZGF0YSBzZXQuCgpCdXQgdGhlcmUgYXJlIGEgZmV3IG1pc3NpbmcgdmFsdWVzIChOQXMpLiBTaW5jZSBhbGwgY29sdW1ucyBleGNlcHQgQ291bnRyeSBOYW1lIGFyZSBudW1lcmljLCBhbnkgbWlzc2luZyBlbnRyaWVzIGluIHRob3NlIGNvbHVtbnMgYXJlIGF1dG9tYXRpY2FsbHkgdHJlYXRlZCBhcyBOQS4gRnJvbSB0aGUgZGF0YSBzY2FuLCB3ZSBjYW4gc2VlIGEgdG90YWwgb2YgODQgbWlzc2luZyB2YWx1ZXMgYWNyb3NzIHRoZSB0aHJlZSBtYWluIHZhcmlhYmxlcy4KCmBgYHtyfQojQ291bnRyaWVzIHdoaWNoIGFyZSBtaXNzaW5nIHBvcHVsYXRpb24gZGF0YQplbGVjdHJpY2l0eV8yMDIwW3doaWNoKGlzLm5hKGVsZWN0cmljaXR5XzIwMjAkJ1BvcHVsYXRpb24nKSksICJDb3VudHJ5IE5hbWUiXQpgYGAKYGBge3J9CiNDb3VudHJpZXMgd2hpY2ggYXJlIG1pc3NpbmcgJ0FjY2VzcyB0byBlbGVjdHJpY2l0eScgZGF0YQplbGVjdHJpY2l0eV8yMDIwW3doaWNoKGlzLm5hKGVsZWN0cmljaXR5XzIwMjAkYEFjY2VzcyB0byBlbGVjdHJpY2l0eSwgdXJiYW4gKCUgb2YgdXJiYW4gcG9wdWxhdGlvbilgKSksICJDb3VudHJ5IE5hbWUiXQpgYGAKYGBge3J9CiNDb3VudHJpZXMgd2hpY2ggYXJlIG1pc3NpbmcgJ1BvcHVsYXRpb25fd2l0aF9lbGVjdHJpY2l0eScgZGF0YQplbGVjdHJpY2l0eV8yMDIwW3doaWNoKGlzLm5hKGVsZWN0cmljaXR5XzIwMjAkUG9wdWxhdGlvbl93aXRoX2VsZWN0cmljaXR5KSksICJDb3VudHJ5IE5hbWUiXQpgYGAKPGJyPgo8YnI+CgpBbiBvYnZpb3VzIGVycm9yIGNhbiBiZSBzZWVuIGluIHRoZSBjb3VudHJ5IG5hbWUg4oCYTm90IGNsYXNzaWZpZWTigJkuIFNvLCBpdCBhcHBlYXJzIHRvIGJlIG5vIGRhdGEgZm9yIHRoaXMuIFRoZXJlZm9yZSwgSSBkZWNpZGVkIHRvIHJlbW92ZSB0aGF0IHJvdy4gSXQgd2lsbCBub3QgYWZmZWN0IGZvciBteSBhbmFseXNpcy4gCgpGb3IgdGhlIHJlbWFpbmluZyBOQSB2YWx1ZXMgd2hpY2ggaW5jbHVkZXMgbnVtZXJpY2FsIHZhbHVlcyBhcmUgcmVwbGFjZWQgd2l0aCB0aGUgbWVhbi4KCmBgYHtyfQplbGVjdHJpY2l0eV8yMDIwX2NsZWFuIDwtIGVsZWN0cmljaXR5XzIwMjAgJT4lCiAgZmlsdGVyKGBDb3VudHJ5IE5hbWVgICE9ICJOb3QgY2xhc3NpZmllZCIpCgojUmVwbGFjZSB0aGUgbWlzc2luZyB2YWx1ZShzKSBvZiBwb3B1bGF0aW9uIHdpdGggdGhlIG1lYW4KZWxlY3RyaWNpdHlfMjAyMF9jbGVhbiRQb3B1bGF0aW9uIDwtIGltcHV0ZShlbGVjdHJpY2l0eV8yMDIwX2NsZWFuJFBvcHVsYXRpb24sIGZ1biA9IG1lYW4pIAoKI1JlcGxhY2UgdGhlIG1pc3NpbmcgdmFsdWUocykgb2YgQWNjZXNzIHRvIGVsZWN0cmljaXR5IHdpdGggdGhlIG1lYW4KZWxlY3RyaWNpdHlfMjAyMF9jbGVhbiRgQWNjZXNzIHRvIGVsZWN0cmljaXR5LCB1cmJhbiAoJSBvZiB1cmJhbiBwb3B1bGF0aW9uKWAgPC0gaW1wdXRlKGVsZWN0cmljaXR5XzIwMjBfY2xlYW4kYEFjY2VzcyB0byBlbGVjdHJpY2l0eSwgdXJiYW4gKCUgb2YgdXJiYW4gcG9wdWxhdGlvbilgLCBmdW4gPSBtZWFuKSAKCiNSZXBsYWNlIHRoZSBtaXNzaW5nIHZhbHVlKHMpIG9mIHBvcHVsYXRpb24gd2l0aCBlbGVjdHJpY2l0eSwgd2l0aCB0aGUgbWVhbgplbGVjdHJpY2l0eV8yMDIwX2NsZWFuJFBvcHVsYXRpb25fd2l0aF9lbGVjdHJpY2l0eSA8LSBpbXB1dGUoZWxlY3RyaWNpdHlfMjAyMF9jbGVhbiRQb3B1bGF0aW9uX3dpdGhfZWxlY3RyaWNpdHksIGZ1biA9IG1lYW4pIAoKYGBgCgpgYGB7cn0KCiNSZW1haW5pbmcgbWlzc2luZyB2YWx1ZXMKY29sU3Vtcyhpcy5uYShlbGVjdHJpY2l0eV8yMDIwX2NsZWFuKSkKCmBgYApOb3cgc2VlbXMgdG8gYmUgb2theSB3aXRoIHRoZSBOQSB2YWx1ZXMuIAoKIyMJKipTY2FuIElJKioKCkJlZm9yZSBoYW5kbGluZyB0aGUgb3V0bGllcnMsIGl0IGlzIGltcG9ydGFudCB0byB1bmRlcnN0YW5kIHRoZSBkaXN0cmlidXRpb24gb2YgeW91ciB2YXJpYWJsZXMuIFRoZSBiZXN0IGZpcnN0IHN0ZXAgaXMgdG8gdXNlIEhpc3RvZ3JhbSB0byB2aXN1YWxseSBpbnNwZWN0IHdoZXRoZXIgdGhlIGRhdGEgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgb3Igc2tld2VkLgoKYGBge3J9CgojIEhpc3RvZ3JhbSBmb3IgUG9wdWxhdGlvbgpnZ3Bsb3QoZWxlY3RyaWNpdHlfMjAyMF9jbGVhbiwgYWVzKHggPSBQb3B1bGF0aW9uKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAwMDAwMCwgZmlsbCA9ICJibHVlIiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgVXJiYW4gUG9wdWxhdGlvbiIsIHggPSAiUG9wdWxhdGlvbiIsIHkgPSAiRnJlcXVlbmN5IikKCiMgSGlzdG9ncmFtIGZvciBBY2Nlc3MgdG8gRWxlY3RyaWNpdHkgKCUpCmdncGxvdChlbGVjdHJpY2l0eV8yMDIwX2NsZWFuLCBhZXMoeCA9IGBBY2Nlc3MgdG8gZWxlY3RyaWNpdHksIHVyYmFuICglIG9mIHVyYmFuIHBvcHVsYXRpb24pYCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGZpbGwgPSAiZ3JlZW4iLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBVcmJhbiBFbGVjdHJpY2l0eSBBY2Nlc3MiLCB4ID0gIlBlcmNlbnRhZ2UiLCB5ID0gIkZyZXF1ZW5jeSIpCgojIEhpc3RvZ3JhbSBmb3IgQ29tcHV0ZWQgVmFyaWFibGU6IFBvcHVsYXRpb24gd2l0aCBFbGVjdHJpY2l0eQpnZ3Bsb3QoZWxlY3RyaWNpdHlfMjAyMF9jbGVhbiwgYWVzKHggPSBQb3B1bGF0aW9uX3dpdGhfZWxlY3RyaWNpdHkpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMDAwMDAwLCBmaWxsID0gInB1cnBsZSIsIGNvbG9yID0gImJsYWNrIikgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFBlb3BsZSB3aXRoIEVsZWN0cmljaXR5IiwgeCA9ICJQb3B1bGF0aW9uIHdpdGggQWNjZXNzIiwgeSA9ICJGcmVxdWVuY3kiKQoKCmBgYAogIDEuIERpc3RyaWJ1dGlvbiBvZiBVcmJhbiBQb3B1bGF0aW9uCiAgICAgIFRoZSBoaXN0b2dyYW0gaXMgaGlnaGx5IHJpZ2h0LXNrZXdlZCAocG9zaXRpdmVseSBza2V3ZWQpLgogICAgICBNb3N0IGNvdW50cmllcyBoYXZlIGEgcmVsYXRpdmVseSBzbWFsbCB1cmJhbiBwb3B1bGF0aW9uLCBjb25jZW50cmF0ZWQgbmVhciB0aGUgbGVmdCBzaWRlIG9mIHRoZSBncmFwaC4KICAgICAgQSBmZXcgY291bnRyaWVzIGhhdmUgdmVyeSBsYXJnZSB1cmJhbiBwb3B1bGF0aW9ucywgZXh0ZW5kaW5nIHRoZSBkaXN0cmlidXRpb24gdG8gdGhlIHJpZ2h0IHdpdGggbG9uZywgbG93LWZyZXF1ZW5jeSBiYXJzLgogICAgICAKICAyLiBEaXN0cmlidXRpb24gb2YgVXJiYW4gRWxlY3RyaWNpdHkgQWNjZXNzCiAgICAgIFRoZSBoaXN0b2dyYW0gaXMgbGVmdC1za2V3ZWQgKG5lZ2F0aXZlbHkgc2tld2VkKSwgd2l0aCB0aGUgdGFpbCBleHRlbmRpbmcgdG93YXJkIGxvd2VyIHBlcmNlbnRhZ2VzLgogICAgICBBIGxhcmdlIG51bWJlciBvZiBjb3VudHJpZXMgaGF2ZSB2ZXJ5IGhpZ2ggYWNjZXNzIHJhdGVzIChjbG9zZSB0byAxMDAlKS4KICAgICAgVmVyeSBmZXcgY291bnRyaWVzIGhhdmUgbG93IGFjY2VzcyByYXRlcyAoYmVsb3cgNTAlKSwgc2hvd24gYXMgc21hbGxlciBiYXJzIG9uIHRoZSBsZWZ0LgogICAgICAKICAzLiBEaXN0cmlidXRpb24gb2YgUGVvcGxlIHdpdGggRWxlY3RyaWNpdHkKICAgICAgVGhlIGhpc3RvZ3JhbSBpcyBoaWdobHkgcmlnaHQtc2tld2VkLCB3aXRoIGEgbG9uZyB0YWlsIHN0cmV0Y2hpbmcgdG93YXJkIGhpZ2hlciB2YWx1ZXMuCiAgICAgIFRoZSBtYWpvcml0eSBvZiBjb3VudHJpZXMgaGF2ZSBsb3cgdG8gbW9kZXJhdGUgdmFsdWVzIG9mIHVyYmFuIHBvcHVsYXRpb24gd2l0aCBlbGVjdHJpY2l0eSBhY2Nlc3MuCiAgICAgIEEgc21hbGwgbnVtYmVyIG9mIGNvdW50cmllcyBoYXZlIGV4dHJlbWVseSBsYXJnZSB2YWx1ZXMsIGRyaXZpbmcgdGhlIHNrZXcuCiAgICAgIApTaW5jZSB0aGUgb2JzZXJ2YXRpb24gY2xlYXJseSBkaXNwbGF5cyBhbGwgdGhlIHRocmVlIHR5cGVzIGFyZSBoZWF2aWx5IHNrZXdlZC4gCgpUbyBkZXRlY3Qgb3V0bGllcnMgaW4gdGhpcyB0YXNrLCB0aGUgYmVzdCB3YXkgaXMgVHVya2V5J3MgbWV0aG9kIChJUVIpLgoKYGBge3J9CgojUGxvdHMgdmFyaWFibGVzIHVzaW5nIGJveCBwbG90cwoKZWxlY3RyaWNpdHlfMjAyMF9jbGVhbiRQb3B1bGF0aW9uICU+JSBib3hwbG90KHlsYWI9IlBvcHVsYXRpb24iKQoKZWxlY3RyaWNpdHlfMjAyMF9jbGVhbiRgQWNjZXNzIHRvIGVsZWN0cmljaXR5LCB1cmJhbiAoJSBvZiB1cmJhbiBwb3B1bGF0aW9uKWAgJT4lIGJveHBsb3QoeWxhYj0iQWNjZXNzIHRvIGVsZWN0cmljaXR5ICglIG9mIHBvcHVsYXRpb24pIikKCmVsZWN0cmljaXR5XzIwMjBfY2xlYW4kUG9wdWxhdGlvbl93aXRoX2VsZWN0cmljaXR5JT4lIGJveHBsb3QoeWxhYj0iTm8gb2YgcGVvcGxlIHdpdGggYWNjZXNzIHRvIGVsZWN0cmljaXR5IikKCmBgYApGcm9tIHRoZSBib3ggcGxvdHMsIGVhY2ggY29udGFpbnMgbXVsdGlwbGUgb3V0bGllcnMuIENsYXNzaWNhbCBzdGF0aXN0aWNzIGFyZSBzZW5zaXRpdmUgdG8gZXh0cmVtZSB2YWx1ZXMuCgpJIGhhdmUgY2hvc2VuIHRvIGFwcGx5IGNhcHBpbmcvV2luc29yaXNpbmcuIFRoaXMgbWV0aG9kIGxpbWl0cyBleHRyZW1lIHZhbHVlcyBieSByZXBsYWNpbmcgdGhlbSB3aXRoIGEgc3BlY2lmaWVkIHBlcmNlbnRpbGUgKGV4OiB0aGUgNXRoIGFuZCA5NXRoIHBlcmNlbnRpbGVzKS4gCgpgYGB7cn0KI3N0YWtvdmVyZmxvdzogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTMzMzk2ODUvaG93LXRvLXJlcGxhY2Utb3V0bGllcnMtd2l0aC10aGUtNXRoLWFuZC05NXRoLXBlcmNlbnRpbGUtdmFsdWVzLWluLXI/dXRtX21lZGl1bT1vcmdhbmljJnV0bV9zb3VyY2Vnb29nbGVfcmljaF9xYSZ1dG1fY2FtcGFpZ249Z29vZ2xlX3JpY2hfcWEKCiMgRGVmaW5lIGEgZnVuY3Rpb24gdG8gY2FwIHRoZSB2YWx1ZXMgb3V0c2lkZSB0aGUgbGltaXRzCgpjYXAgPC0gZnVuY3Rpb24oeCl7CiAgICBxdWFudGlsZXMgPC0gcXVhbnRpbGUoIHgsIGMoLjA1LCAwLjI1LCAwLjc1LCAuOTUgKSApCiAgICB4WyB4IDwgcXVhbnRpbGVzWzJdIC0gMS41KklRUih4KSBdIDwtIHF1YW50aWxlc1sxXQogICAgeFsgeCA+IHF1YW50aWxlc1szXSArIDEuNSpJUVIoeCkgXSA8LSBxdWFudGlsZXNbNF0KICAgIHh9CmBgYAoKYGBge3J9CiNjYXBwaW5nIGZ1bmN0aW9uCgpwb3B1bGF0aW9uX2NhcHBlZCA8LSBlbGVjdHJpY2l0eV8yMDIwX2NsZWFuJFBvcHVsYXRpb24gJT4lIGNhcCgpCmJveHBsb3QocG9wdWxhdGlvbl9jYXBwZWQsIHlsYWI9IlBvcHVsYXRpb24iKQoKZWxlY3RyaWNpdHlfY2FwcGVkIDwtIGVsZWN0cmljaXR5XzIwMjBfY2xlYW4kYEFjY2VzcyB0byBlbGVjdHJpY2l0eSwgdXJiYW4gKCUgb2YgdXJiYW4gcG9wdWxhdGlvbilgICU+JSBjYXAoKQpib3hwbG90KGVsZWN0cmljaXR5X2NhcHBlZCwgeWxhYj0iQWNjZXNzIHRvIGVsZWN0cmljaXR5ICglIG9mIHBvcHVsYXRpb24pIikKCnBlb3BsZV9lbGVjdHJpY2l0eV9jYXBwZWQgPC0gZWxlY3RyaWNpdHlfMjAyMF9jbGVhbiRQb3B1bGF0aW9uX3dpdGhfZWxlY3RyaWNpdHkgJT4lIGNhcCgpCmJveHBsb3QocGVvcGxlX2VsZWN0cmljaXR5X2NhcHBlZCwgeWxhYj0iTm8gb2YgcGVvcGxlIHdpdGggYWNjZXNzIHRvIGVsZWN0cmljaXR5IikKYGBgCgojIwkqKlRyYW5zZm9ybSAqKgoKSGlzdG9ncmFtcyBhbmQgYm94IHBsb3RzIGNyZWF0ZWQgZHVyaW5nIHRoZSAiU2NhbiBJSSIgc2VjdGlvbiwgSSBvYnNlcnZlZCB0aGF0IHRoZSB2YXJpYWJsZSAnTm8gb2YgcGVvcGxlIHdpdGggYWNjZXNzIHRvIGVsZWN0cmljaXR5JyBpcyBoZWF2aWx5IHJpZ2h0LXNrZXdlZCwgbWVhbmluZyBtb3N0IG9mIHRoZSBkYXRhIGlzIGNvbmNlbnRyYXRlZCBvbiB0aGUgbGVmdCwgd2l0aCBhIGZldyBleHRyZW1lIHZhbHVlcyBvbiB0aGUgcmlnaHQuCgoKYGBge3J9CgpoaXN0KGVsZWN0cmljaXR5XzIwMjBfY2xlYW4kUG9wdWxhdGlvbiwgbWFpbiA9ICJIaXN0b2dyYW0gb2Ygbm9uLXRyYW5zZm9ybWVkIGRhdGEiKQoKaGlzdChlbGVjdHJpY2l0eV8yMDIwX2NsZWFuJGBBY2Nlc3MgdG8gZWxlY3RyaWNpdHksIHVyYmFuICglIG9mIHVyYmFuIHBvcHVsYXRpb24pYCwgbWFpbiA9ICJIaXN0b2dyYW0gb2Ygbm9uLXRyYW5zZm9ybWVkIGRhdGEiKQoKaGlzdChlbGVjdHJpY2l0eV8yMDIwX2NsZWFuJFBvcHVsYXRpb25fd2l0aF9lbGVjdHJpY2l0eSwgbWFpbiA9ICJIaXN0b2dyYW0gb2Ygbm9uLXRyYW5zZm9ybWVkIGRhdGEiKQoKYGBgCkFwcGx5IHRoZSBtZXRob2Qgb2YgbG9nYXJpdGhtaWMgdHJhbnNmb3JtYXRpb24gdG8gY2hhbmdpbmcgdGhlIFBvcHVsYXRpb24gaW50byBhIG5vcm1hbCBkaXN0cmlidXRpb24uCgpgYGB7cn0KCk5vcm1fUG9wdWxhdGlvbjwtbG9nMTAoZWxlY3RyaWNpdHlfMjAyMF9jbGVhbiRQb3B1bGF0aW9uKQpoaXN0KE5vcm1fUG9wdWxhdGlvbikKCmBgYApUaGUgZGF0YSBub3cgZm9sbG93cyBhcyBhIG5vcm1hbCBkaXN0cmlidXRpb24gbXVjaCBtb3JlIGNsb3NlbHkgdGhhbiBlYXJsaWVyLgoKCiMjICoqUmVmbGVjdGlvbiBvbiBDaGFsbGVuZ2VzIGFuZCBFYXNlKioKCi0gQ2hhbGxlbmdlcyBGYWNlZAoKICAgIDEuIEluaXRpYWxseSwgaWRlbnRpZnlpbmcgdHdvIGRhdGFzZXRzIHRoYXQgd2VyZSBib3RoIHVudGlkeSBhbmQgaGFkIGEgY29tbW9uIHZhcmlhYmxlIGZvciBqb2luaW5nIHdhcyBjaGFsbGVuZ2luZy4gVGhpcyBzdGVwIHJlcXVpcmVkIGNhcmVmdWwgY29uc2lkZXJhdGlvbiBvZiB0aGUgc3RydWN0dXJlIGFuZCBjb250ZW50IG9mIHBvdGVudGlhbCBkYXRhc2V0cy4KICAgIDIuIEkgdG9vayBndWlkYW5jZSBmcm9tIG15IGxlY3R1cmVyIChEci4gU29uYSksIHdobyBwcm92aWRlZCB2YWx1YWJsZSBmZWVkYmFjayBvbiBhcHByb3ByaWF0ZSBkYXRhc2V0IGNoYXJhY3RlcmlzdGljcy4gVGhpcyBoZWxwZWQgbWUgbWFrZSBhIG1vcmUgY29uZmlkZW50IG9uIG15IHNlbGVjdGlvbi4KICAgIDMuIFdoaWxlIHRoZSBjb25jZXB0IG9mIHVuLXRpZHkgZGF0YSB3YXMgZXhwbGFpbmVkIGluIHRoZSBjb3Vyc2UsIGFwcGx5aW5nIGl0IHByYWN0aWNhbGx5LCBlc3BlY2lhbGx5IHRyYW5zZm9ybWluZyBkYXRhIHVzaW5nIGdhdGhlcigpLCBzcHJlYWQoKSwgYW5kIGpvaW5pbmcgdGVjaG5pcXVlcyB0b29rIHNvbWUgZXhwZXJpbWVudGF0aW9uIGFuZCByZXZpZXcgb2YgdGhlIGNvdXJzZSBtYXRlcmlhbHMuCiAgICAKLSBFYXNlIGFuZCBTdHJlbmd0aHMKCiAgICAxLiBPbmNlIHRoZSBkYXRhc2V0cyB3ZXJlIHNlbGVjdGVkIGFuZCB0aGUgaW5pdGlhbCB0cmFuc2Zvcm1hdGlvbiB1bmRlcnN0b29kLCB0aGUgcmVzdCBvZiB0aGUgdGFzayBiZWNhbWUgZWFzaWVyLiBUaGUgc3RlcCBieSBzdGVwIHN0cnVjdHVyZSB0YXVnaHQgaW4gdGhlIGNvdXJzZSBhbGlnbmVkIHdlbGwgd2l0aCB3aGF0IHdhcyByZXF1aXJlZCBpbiB0aGUgYXNzaWdubWVudC4KICAgIDIuIENyZWF0aW5nIGhpc3RvZ3JhbXMgdXNpbmcgZ2dwbG90MiB3YXMgb25lIG9mIHRoZSBlYXNpZXIgdGFza3MsIGFuZCBpdCBoZWxwZWQgbWUgYmV0dGVyIHVuZGVyc3RhbmQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBteSB2YXJpYWJsZXMuCiAgICAzLiBJIGZvdW5kIHVzaW5nIFIsIHBhcnRpY3VsYXJseSBmdW5jdGlvbnMgZnJvbSB0aGUgdGlkeXZlcnNlIGxpa2UgbXV0YXRlKCksIHNlbGVjdCgpLCBhbmQgbGVmdF9qb2luKCksIHJlbGF0aXZlbHkgc3RyYWlnaHRmb3J3YXJkIHRoYW5rcyB0byBjb25zaXN0ZW50IHByYWN0aWNlIGR1cmluZyBsZWN0b3JpYWxzIGFuZCB0dXRvcmFpbHMuCiAgICAKLSBJbnNpZ2h0cyBhbmQgTGVhcm5pbmcKCiAgICAxLiBJIGxlYXJuZWQgdGhhdCBjYXJlZnVsIGRhdGFzZXQgc2VsZWN0aW9uIGFuZCBjbGVhciBwbGFubmluZyBhcmUgY3J1Y2lhbCBiZWZvcmUgYmVnaW5uaW5nIGRhdGEgdHJhbnNmb3JtYXRpb24uCiAgICAyLiBUaGlzIHRhc2sgc3RyZW5ndGhlbmVkIG15IHVuZGVyc3RhbmRpbmcgb2YgdGlkeSBkYXRhIHByaW5jaXBsZXMgYW5kIGVuaGFuY2VkIG15IGFiaWxpdHkgdG8gYXBwbHkgdGhlbSBjb25maWRlbnRseSB1c2luZyBSLgoKIyMJKipSZWZlcmVuY2VzICoqCgoxLiBEci4gU29uYSAoMjAyNSkg4oCYTW9kdWxlIDHigJksIFtNb2R1bGUgMSBOb3RlcywgTUFUSDIzNDldLCBSTUlUIFVuaXZlcnNpdHksIE1lbGJvdXJuZSwgYWNjZXNzZWQgTWF5IDI1IGh0dHBzOi8vZGF0YS13cmFuZ2xpbmcuc3RlbS5tZWxib3VybmUvbW9kdWxlXzAxCjIuIERyLiBTb25hICgyMDI1KSDigJhNb2R1bGUgMuKAmSwgW01vZHVsZSAxIE5vdGVzLCBNQVRIMjM0OV0sIFJNSVQgVW5pdmVyc2l0eSwgTWVsYm91cm5lLCBhY2Nlc3NlZCBNYXkgMjUgaHR0cHM6Ly9kYXRhLXdyYW5nbGluZy5zdGVtLm1lbGJvdXJuZS9tb2R1bGVfMDIKMy4gRHIuIFNvbmEgKDIwMjUpIOKAmE1vZHVsZSAz4oCZLCBbTW9kdWxlIDEgTm90ZXMsIE1BVEgyMzQ5XSwgUk1JVCBVbml2ZXJzaXR5LCBNZWxib3VybmUsIGFjY2Vzc2VkIE1heSAyNSBodHRwczovL2RhdGEtd3JhbmdsaW5nLnN0ZW0ubWVsYm91cm5lL21vZHVsZV8wMwo0LiBEci4gU29uYSAoMjAyNSkg4oCYTW9kdWxlIDTigJksIFtNb2R1bGUgMSBOb3RlcywgTUFUSDIzNDldLCBSTUlUIFVuaXZlcnNpdHksIE1lbGJvdXJuZSwgYWNjZXNzZWQgTWF5IDI2IGh0dHBzOi8vZGF0YS13cmFuZ2xpbmcuc3RlbS5tZWxib3VybmUvbW9kdWxlXzA0CjUuIERyLiBTb25hICgyMDI1KSDigJhNb2R1bGUgNeKAmSwgW01vZHVsZSAxIE5vdGVzLCBNQVRIMjM0OV0sIFJNSVQgVW5pdmVyc2l0eSwgTWVsYm91cm5lLCBhY2Nlc3NlZCBNYXkgMjYgaHR0cHM6Ly9kYXRhLXdyYW5nbGluZy5zdGVtLm1lbGJvdXJuZS9tb2R1bGVfMDUKNi4gRHIuIFNvbmEgKDIwMjUpIOKAmE1vZHVsZSA24oCZLCBbTW9kdWxlIDEgTm90ZXMsIE1BVEgyMzQ5XSwgUk1JVCBVbml2ZXJzaXR5LCBNZWxib3VybmUsIGFjY2Vzc2VkIE1heSAyNiBodHRwczovL2RhdGEtd3JhbmdsaW5nLnN0ZW0ubWVsYm91cm5lL21vZHVsZV8wNgo3LiBEci4gU29uYSAoMjAyNSkg4oCYTW9kdWxlIDfigJksIFtNb2R1bGUgMSBOb3RlcywgTUFUSDIzNDldLCBSTUlUIFVuaXZlcnNpdHksIE1lbGJvdXJuZSwgYWNjZXNzZWQgTWF5IDI2IGh0dHBzOi8vZGF0YS13cmFuZ2xpbmcuc3RlbS5tZWxib3VybmUvbW9kdWxlXzA3CjguIFN0YWNrIG92ZXJmbG93ICgyMDI1KSwgU3RhY2sgb3ZlcmZsb3cgd2Vic2l0ZSwgYWNjZXNzZWQgMjYgTWF5IDIwMjUgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTMzMzk2ODUvaG93LXRvLXJlcGxhY2Utb3V0bGllcnMtd2l0aC10aGUtNXRoLWFuZC05NXRoLXBlcmNlbnRpbGUtdmFsdWVzLWluLXI/dXRtX21lZGl1bT1vcmdhbmljJnV0bV9zb3VyY2Vnb29nbGVfcmljaF9xYSZ1dG1fY2FtcGFpZ249Z29vZ2xlX3JpY2hfcWEKOS4gVXJiYW4gcG9wdWxhdGlvbiAoMjAyMykgV29ybGRiYW5rLm9yZywgYWNjZXNzZWQgTWF5IDI1LCAyMDI1LApodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy9pbmRpY2F0b3IvU1AuVVJCLlRPVEw/ZW5kPTIwMjMmc3RhcnQ9MjAwMCBSZWxlYXNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24gQlktNC4wIGxpY2Vuc2UuCjEwLiBVcmJhbiBEZXZlbG9wbWVudCB8IERhdGEgKDIwMjMpIFdvcmxkYmFuay5vcmcsIGFjY2Vzc2VkIE1heSAyNSwgMjAyNSwgaHR0cHM6Ly9kYXRhLndvcmxkYmFuay5vcmcvdG9waWMvdXJiYW4tZGV2ZWxvcG1lbnQuIFJlbGVhc2VkIHVuZGVyIGEgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbiBCWS00LjAgbGljZW5zZS4KMTEuIFIgQ29yZSBUZWFtICgyMDIxKS4gUjogQSBsYW5ndWFnZSBhbmQgZW52aXJvbm1lbnQgZm9yIHN0YXRpc3RpY2FsIGNvbXB1dGluZy4gUiBGb3VuZGF0aW9uIGZvciBTdGF0aXN0aWNhbCBDb21wdXRpbmcsIFZpZW5uYSwgQXVzdHJpYSwgYWNjZXNzZWQgMjcgTWF5IDIwMjUgaHR0cHM6Ly93d3cuUi1wcm9qZWN0Lm9yZy8uCgoKCiMjCSoqUHJlc2VudGF0aW9uICoqCgoKW0RhdGEgV3JhbmdsaW5nIEFzc2lnbm1lbnQgMiAtIHM0MTUwMzAzXSAKCkxpbms6IGh0dHBzOi8vcm1pdC1hcmMuaW5zdHJ1Y3R1cmVtZWRpYS5jb20vZW1iZWQvNDAyMDFlOTItYWI0NS00MWI1LTk2ZDctM2I3ZTlkYmE4NGQ4CgoKCg==