Suggested citation: > Miranti, Ragdad Cani.(2020). Regional Poverty Convergence across Districts in Indonesia: A Distribution Dynamics Approach https://rpubs.com/canimiranti/distribution_dynamics_poverty514districts

This work is licensed under the Creative Commons Attribution-Non Commercial-Share Alike 4.0 International License.

1 Original data source

Data of Headcount Index (Poverty Rate) are derived from the Indonesia Central Bureau of Statistics (Badan Pusat Statistik Republik of Indonesia). https://www.bps.go.id/

Acknowledgment:

Material adapted from multiple sources, in particular from Magrini (2007).

2 Libraries

knitr::opts_chunk$set(echo = TRUE)

library(tidyverse)
library(skimr)
library(kableExtra)    # html tables 
library(pdfCluster)    # density based clusters
library(hdrcde)        # conditional density estimation 
library(plotly)

library(intoo)
library(barsurf)
library(bivariate)

library(np)
library(quantreg)

library(basetheme)
basetheme("minimal")

library(viridis)
library(ggpointdensity)
library(isoband)

#library(MASS)
library(KernSmooth)


# Change the presentation of decimal numbers to 4 and avoid scientific notation
options(prompt="R> ", digits=4, scipen=7)

3 Tutorial objectives

  • Study the dynamics of univariate densities

  • Compute the bandwidth of a density

  • Study mobility plots

  • Study bi-variate densities

  • Study density-based clustering methods

  • Study conditional bi-variate densities

4 Import data

dat <- read_csv("poverty.csv")
dat <- as.data.frame(dat)

5 Transform data

Since the data is in relative terms, let us rename the variables and add new variables.

dat <- dat %>% 
  mutate(
    rel_pov2010 = pov2010/mean(pov2010),
    rel_pov2018 = pov2010/mean(pov2018)
  )
dat

6 Descriptive statistics

skim(dat)
Data summary
Name dat
Number of rows 514
Number of columns 13
_______________________
Column type frequency:
character 1
numeric 12
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
District 0 1 4 26 0 514 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
Code 0 1 4558.30 2678.26 911.00 1803.25 3550.00 7173.75 9471.00 ▇▆▂▇▃
pov2010 0 1 15.62 9.42 1.67 9.01 13.34 19.56 49.58 ▇▇▂▁▁
pov2011 0 1 14.64 8.92 1.50 8.14 12.44 18.91 47.44 ▇▇▂▁▁
pov2012 0 1 13.92 8.55 1.33 7.79 11.77 17.78 45.92 ▇▇▂▁▁
pov2013 0 1 13.83 8.59 1.75 7.76 11.74 17.41 47.52 ▇▆▂▁▁
pov2014 0 1 13.12 7.93 1.68 7.38 11.18 16.60 44.49 ▇▆▂▁▁
pov2015 0 1 13.51 8.25 1.69 7.59 11.58 16.87 45.74 ▇▇▂▁▁
pov2016 0 1 13.18 8.20 1.67 7.40 11.25 16.29 45.11 ▇▇▂▁▁
pov2017 0 1 12.97 7.98 1.76 7.35 11.14 16.04 43.63 ▇▇▂▁▁
pov2018 0 1 12.34 7.84 1.68 6.99 10.21 15.08 43.49 ▇▆▂▁▁
rel_pov2010 0 1 1.00 0.60 0.11 0.58 0.85 1.25 3.18 ▇▇▂▁▁
rel_pov2018 0 1 1.27 0.76 0.14 0.73 1.08 1.59 4.02 ▇▇▂▁▁
xy <- dat %>% 
select(
pov2010,
pov2018,
  ) %>% 
  mutate(
    x = pov2010,
    y = pov2018
  ) %>% 
  select(
    x,
    y
  )

7 Univariate dynamics

7.1 Select bandwiths

Select bandwidth based on function dpik from the package KernSmooth

h_rel_pov2010<- dpik(dat$rel_pov2010)
h_rel_pov2010
## [1] 0.1026
h_rel_pov2018 <- dpik(dat$rel_pov2018)
h_rel_pov2018
## [1] 0.1299

7.2 Plot each density

dis_rel_pov2010 <- bkde(dat$rel_pov2010, bandwidth = h_rel_pov2010)
dis_rel_pov2010 <- as.data.frame(dis_rel_pov2010)
ggplot(dis_rel_pov2010, aes(x, y)) + geom_line() + 
  theme_minimal() 

dis_rel_pov2018 <- bkde(dat$rel_pov2018, bandwidth = h_rel_pov2018)
dis_rel_pov2018 <- as.data.frame(dis_rel_pov2018)
ggplot(dis_rel_pov2018, aes(x, y)) + geom_line() + 
  theme_minimal() 

7.3 Plot both densities

There are two methods for plot both densities,i.e. Kernsmooth and bandwith default of ggplot. I prefer using the gglot ( Method 2).

8 Method 2 (ggplot)

Using the bandwidth default of ggplot Manual labels are not yet implemented in the ggplotly function

rel_pov2010 <- dat %>% 
  select(rel_pov2010) %>% 
  rename(rel_var = rel_pov2010) %>% 
  mutate(year = 2010)
rel_pov2018 <- dat %>% 
  select(rel_pov2018) %>% 
  rename(rel_var = rel_pov2018) %>% 
  mutate(year = 2018)
rel_pov2010pov2018 <- bind_rows(rel_pov2010, rel_pov2018)
rel_pov2010pov2018 <- rel_pov2010pov2018 %>% 
  mutate(year = as.factor(year))
head(rel_pov2010pov2018)
dis_rel_pov2010pov2018 <- ggplot(rel_pov2010pov2018,aes(x=rel_var, color=year)) +
  geom_density() + 
  theme_minimal() 
dis_rel_pov2010pov2018

Using plotly

ggplotly(dis_rel_pov2010pov2018)

9 Bivariate density

9.1 Using Mobility scatterplot

dat %>% 
  ggplot(aes(x = rel_pov2010, y = rel_pov2018)) +
  geom_point(alpha=0.5) +
  geom_abline(aes(intercept = 0, slope = 1)) +
  geom_hline(yintercept = 1, linetype="dashed") + 
  geom_vline(xintercept = 1, linetype="dashed") +
  theme_minimal() +
  labs(subtitle = "Relative Pov2018",
       x = "Relative Pov2010",
       y = "") +
  theme(text=element_text(family="Palatino")) 

Fit a non-linear function

dat %>% 
  ggplot(aes(x = rel_pov2010, y = rel_pov2018)) +
  geom_point(alpha=0.5) + 
  geom_smooth() + 
  geom_abline(aes(intercept = 0, slope = 1)) +
  geom_hline(yintercept = 1, linetype="dashed") + 
  geom_vline(xintercept = 1, linetype="dashed") +
  theme_minimal() +
  labs(subtitle = "Relative pov2018",
       x = "Relative pov2010",
       y = "") +
  theme(text=element_text(family="Palatino")) 
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Not that the nonlinear fit crosses the 45-degree line two times from above.

9.2 Using the Bivariate package

bivariate <- kbvpdf(dat$rel_pov2010, dat$rel_pov2018, h_rel_pov2010, h_rel_pov2018) 
plot(bivariate,
      xlab="Relative Poverty 2010", 
      ylab="Relative Poverty 2018")
abline(a=0, b=1)
abline(h=1, v=1)

plot(bivariate,
      TRUE,
      xlab="Relative Poverty 2010", 
      ylab="Relative Poverty 2018")

9.3 Using ggplot (stat_density_2d)

dat %>% 
  ggplot(aes(x = rel_pov2010, y = rel_pov2018)) +
  geom_point(color = "lightgray") + 
  geom_smooth() + 
  #geom_smooth(method=lm, se=FALSE) + 
  stat_density_2d() +
  geom_abline(aes(intercept = 0, slope = 1)) +
  geom_hline(yintercept = 1, linetype="dashed") + 
  geom_vline(xintercept = 1, linetype="dashed") +
  theme_minimal() +
  labs(subtitle = "Relative pov2018",
       x = "Relative pov2010",
       y = "") +
  theme(text=element_text(family="Palatino")) 
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

dat %>% 
  ggplot(aes(x = rel_pov2010, y = rel_pov2018)) +
        stat_density_2d(aes(fill = stat(nlevel)), geom = "polygon") + 
  scale_fill_viridis_c() +
        geom_abline(aes(intercept = 0, slope = 1)) +
        geom_hline(yintercept = 1, linetype="dashed") + 
        geom_vline(xintercept = 1, linetype="dashed") + 
  theme_minimal() +
        labs(x = "Relative Poverty Rate 2010",
             y = "Relative Poverty Rate 2018") +
        theme(text=element_text(size=8, family="Palatino"))

9.4 Using Stochastic Kernel Package

There are two ways of analyzing the use of stochastic kernel package: 1. Contour Plots and 2. Surface Plots

9.4.1 Contour Plots

pov2010pov2018 <- cbind(dat$rel_pov2010, dat$rel_pov2018)
pov2010pov2018_dis <- bkde2D(pov2010pov2018, bandwidth = c(h_rel_pov2010, h_rel_pov2018)) 
contour(pov2010pov2018_dis$x1,pov2010pov2018_dis$x2,pov2010pov2018_dis$fhat)
abline(a=0, b=1)

9.4.2 Surface Plots

plot_ly(x=pov2010pov2018_dis$x1, y=pov2010pov2018_dis$x2, z=pov2010pov2018_dis$fhat) %>% add_surface()
plot_ly(x=pov2010pov2018_dis$x1, y=pov2010pov2018_dis$x2, z=pov2010pov2018_dis$fhat, type = "contour", contours = list(showlabels = TRUE))  %>%
  colorbar(title = "Density")

10 Conditional density analysis

10.1 Using the hdrcde package

pov2010pov2018_cde <- cde(dat$rel_pov2010, dat$rel_pov2018)

Increase the number of intervals to 60

pov2010pov2018_cde2 <- cde(dat$rel_pov2010, dat$rel_pov2018, nxmargin = 20)
plot(pov2010pov2018_cde)

plot(pov2010pov2018_cde2)

High density regions

plot(pov2010pov2018_cde, plot.fn="hdr")
abline(a=0, b=1)
abline(h=1, v=1)

plot(pov2010pov2018_cde2, plot.fn="hdr")
abline(a=0, b=1)
abline(h=1, v=1)

10.2 Using the np package

Compute adaptive bandwith based on cross-validation

bw_c_ad_cv <- npcdensbw(
  formula = dat$rel_pov2018 ~ dat$rel_pov2010, 
  bwtype = "adaptive_nn") 
## 
Multistart 1 of 2 |
Multistart 1 of 2 |
Multistart 1 of 2 |
Multistart 1 of 2 /
Multistart 1 of 2 |
Multistart 1 of 2 |
Multistart 2 of 2 |
Multistart 2 of 2 |
Multistart 2 of 2 /
Multistart 2 of 2 -
Multistart 2 of 2 |
Multistart 2 of 2 |
                   
summary(bw_c_ad_cv)
## 
## Conditional density data (514 observations, 2 variable(s))
## (1 dependent variable(s), and 1 explanatory variable(s))
## 
## Bandwidth Selection Method: Maximum Likelihood Cross-Validation
## Formula: dat$rel_pov2018 ~ dat$rel_pov2010
## Bandwidth Type: Adaptive Nearest Neighbour
## Objective Function Value: 2166 (achieved on multistart 1)
## 
## Exp. Var. Name: dat$rel_pov2010 Bandwidth: 1  
## 
## Dep. Var. Name: dat$rel_pov2018 Bandwidth: 1 
## 
## Continuous Kernel Type: Second-Order Gaussian
## No. Continuous Explanatory Vars.: 1
## No. Continuous Dependent Vars.: 1
## Estimation Time: 13.48 seconds

Compute conditional density object

cdist_bwCV <- npcdens(bws = bw_c_ad_cv)
summary(cdist_bwCV)
## 
## Conditional Density Data: 514 training points, in 2 variable(s)
## (1 dependent variable(s), and 1 explanatory variable(s))
## 
##                         dat$rel_pov2018
## Dep. Var. Bandwidth(s):               1
##                         dat$rel_pov2010
## Exp. Var. Bandwidth(s):               1
## 
## Bandwidth Type: Adaptive Nearest Neighbour
## Log Likelihood: 2534
## 
## Continuous Kernel Type: Second-Order Gaussian
## No. Continuous Explanatory Vars.: 1
## No. Continuous Dependent Vars.: 1
pov <- dat[,c(3, 11)]
pov
cl.pov <- pdfCluster(pov)
summary(cl.pov)
## An S4 object of class "pdfCluster"
## 
## Call: pdfCluster(x = pov)
## 
## Initial groupings: 
##  label    1   2   3   4  NA 
##  count  458  15   7   4  30 
## 
## Final groupings: 
##  label    1   2   3   4 
##  count  461  28  16   9 
## 
## Groups tree (here 'h' denotes 'height'):
## --[dendrogram w/ 1 branches and 4 members at h = 1]
##   `--[dendrogram w/ 3 branches and 4 members at h = 0.955]
##      |--[dendrogram w/ 2 branches and 2 members at h = 0.927]
##      |  |--leaf "1 " 
##      |  `--leaf "2 " (h= 0.882  )
##      |--leaf "4 " (h= 0.945  )
##      `--leaf "3 " (h= 0.918  )
fig1 <- cde(dat$pov2010, dat$pov2018, 
            x.name="Poverty Rate in 2010",
            y.name="Poverty Rate in 2018")
plot(fig1)

# 1. Create the plot
plot(fig1)

# 2. Close the file
dev.off()
## null device 
##           1
plot_sc_pov <- plot(cl.pov, 
                 stage = 0,
                 which = 3,
                 frame = FALSE)
# 1. Create the plot
plot(cl.pov, 
      stage = 0,
      which = 3,
      frame = FALSE)

# 2. Close the file
dev.off()
## null device 
##           1
plot(fig1, plot.fn="hdr")

# 1. Create the plot
plot(fig1, plot.fn="hdr")

# 2. Close the file
dev.off()
## null device 
##           1
LS0tCnRpdGxlOiAiUmVnaW9uYWwgUG92ZXJ0eSBDb252ZXJnZW5jZSBhY3Jvc3MgRGlzdHJpY3RzIGluIEluZG9uZXNpYTpBIERpc3RyaWJ1dGlvbiBEeW5hbWljcyBBcHByb2FjaCIKYXV0aG9yOiAiUmFnZGFkIENhbmkgTWlyYW50aSIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQogICAgdG9jX2RlcHRoOiA0CiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogInNob3ciCiAgICB0aGVtZTogImNvc21vIgogICAgaGlnaGxpZ2h0OiAibW9ub2Nocm9tZSIKICBnaXRodWJfZG9jdW1lbnQ6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCiAgICB0b2NfZGVwdGg6IDQKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiAiaGlkZSIKICAgIHRoZW1lOiAiY29zbW8iCiAgICBoaWdobGlnaHQ6ICJtb25vY2hyb21lIgogICAgZGZfcHJpbnQ6ICJrYWJsZSIKLS0tCgo8c3R5bGU+CmgxLnRpdGxlIHtmb250LXNpemU6IDE4cHQ7IGNvbG9yOiBEYXJrQmx1ZTt9IApib2R5LCBoMSwgaDIsIGgzLCBoNCB7Zm9udC1mYW1pbHk6ICJQYWxhdGlubyIsIHNlcmlmO30KYm9keSB7Zm9udC1zaXplOiAxMnB0O30KLyogSGVhZGVycyAqLwpoMSxoMixoMyxoNCxoNSxoNntmb250LXNpemU6IDE0cHQ7IGNvbG9yOiAjMDAwMDhCO30KYm9keSB7Y29sb3I6ICMzMzMzMzM7fQphLCBhOmhvdmVyIHtjb2xvcjogIzhCM0E2Mjt9CnByZSB7Zm9udC1zaXplOiAxMnB4O30KPC9zdHlsZT4KClN1Z2dlc3RlZCBjaXRhdGlvbjogCj4gTWlyYW50aSwgUmFnZGFkIENhbmkuKDIwMjApLiBSZWdpb25hbCBQb3ZlcnR5IENvbnZlcmdlbmNlIGFjcm9zcyBEaXN0cmljdHMgaW4gSW5kb25lc2lhOiBBIERpc3RyaWJ1dGlvbiBEeW5hbWljcyBBcHByb2FjaCA8aHR0cHM6Ly9ycHVicy5jb20vY2FuaW1pcmFudGkvZGlzdHJpYnV0aW9uX2R5bmFtaWNzX3BvdmVydHk1MTRkaXN0cmljdHM+CgoKVGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBDcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uLU5vbiBDb21tZXJjaWFsLVNoYXJlIEFsaWtlIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2UuIAoKIyBPcmlnaW5hbCBkYXRhIHNvdXJjZQoKRGF0YSBvZiBIZWFkY291bnQgSW5kZXggKFBvdmVydHkgUmF0ZSkgYXJlIGRlcml2ZWQgZnJvbSB0aGUgSW5kb25lc2lhIENlbnRyYWwgQnVyZWF1IG9mIFN0YXRpc3RpY3MgKEJhZGFuIFB1c2F0IFN0YXRpc3RpayBSZXB1YmxpayBvZiBJbmRvbmVzaWEpLiA8aHR0cHM6Ly93d3cuYnBzLmdvLmlkLz4KCkFja25vd2xlZGdtZW50OgoKTWF0ZXJpYWwgYWRhcHRlZCBmcm9tIG11bHRpcGxlIHNvdXJjZXMsIGluIHBhcnRpY3VsYXIgZnJvbSBbTWFncmluaSAoMjAwNykuXShodHRwczovL3BkZnMuc2VtYW50aWNzY2hvbGFyLm9yZy9lYWIxL2NiODlkZGUwYzkwOTg5OGIwYTQzMjczMzc3YzVkZmE3M2ViYy5wZGYpCgojIExpYnJhcmllcwoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2tpbXIpCmxpYnJhcnkoa2FibGVFeHRyYSkgICAgIyBodG1sIHRhYmxlcyAKbGlicmFyeShwZGZDbHVzdGVyKSAgICAjIGRlbnNpdHkgYmFzZWQgY2x1c3RlcnMKbGlicmFyeShoZHJjZGUpICAgICAgICAjIGNvbmRpdGlvbmFsIGRlbnNpdHkgZXN0aW1hdGlvbiAKbGlicmFyeShwbG90bHkpCgpsaWJyYXJ5KGludG9vKQpsaWJyYXJ5KGJhcnN1cmYpCmxpYnJhcnkoYml2YXJpYXRlKQoKbGlicmFyeShucCkKbGlicmFyeShxdWFudHJlZykKCmxpYnJhcnkoYmFzZXRoZW1lKQpiYXNldGhlbWUoIm1pbmltYWwiKQoKbGlicmFyeSh2aXJpZGlzKQpsaWJyYXJ5KGdncG9pbnRkZW5zaXR5KQpsaWJyYXJ5KGlzb2JhbmQpCgojbGlicmFyeShNQVNTKQpsaWJyYXJ5KEtlcm5TbW9vdGgpCgoKIyBDaGFuZ2UgdGhlIHByZXNlbnRhdGlvbiBvZiBkZWNpbWFsIG51bWJlcnMgdG8gNCBhbmQgYXZvaWQgc2NpZW50aWZpYyBub3RhdGlvbgpvcHRpb25zKHByb21wdD0iUj4gIiwgZGlnaXRzPTQsIHNjaXBlbj03KQoKYGBgCgojIFR1dG9yaWFsIG9iamVjdGl2ZXMKCi0gU3R1ZHkgdGhlIGR5bmFtaWNzIG9mIHVuaXZhcmlhdGUgZGVuc2l0aWVzCgotIENvbXB1dGUgdGhlIGJhbmR3aWR0aCBvZiBhIGRlbnNpdHkKCi0gU3R1ZHkgbW9iaWxpdHkgcGxvdHMKCi0gU3R1ZHkgYmktdmFyaWF0ZSBkZW5zaXRpZXMKCi0gU3R1ZHkgZGVuc2l0eS1iYXNlZCBjbHVzdGVyaW5nIG1ldGhvZHMKCi0gU3R1ZHkgY29uZGl0aW9uYWwgYmktdmFyaWF0ZSBkZW5zaXRpZXMKCgoKIyBJbXBvcnQgZGF0YQoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1UUlVFfQpkYXQgPC0gcmVhZF9jc3YoInBvdmVydHkuY3N2IikKZGF0IDwtIGFzLmRhdGEuZnJhbWUoZGF0KQpgYGAKCgojIFRyYW5zZm9ybSBkYXRhCgoKU2luY2UgdGhlIGRhdGEgaXMgaW4gcmVsYXRpdmUgdGVybXMsIGxldCB1cyByZW5hbWUgdGhlIHZhcmlhYmxlcyBhbmQgYWRkIG5ldyB2YXJpYWJsZXMuCgoKYGBge3J9CmRhdCA8LSBkYXQgJT4lIAogIG11dGF0ZSgKICAgIHJlbF9wb3YyMDEwID0gcG92MjAxMC9tZWFuKHBvdjIwMTApLAogICAgcmVsX3BvdjIwMTggPSBwb3YyMDEwL21lYW4ocG92MjAxOCkKICApCmRhdApgYGAKCgoKIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzCgpgYGB7cn0Kc2tpbShkYXQpCmBgYAoKCmBgYHtyfQp4eSA8LSBkYXQgJT4lIApzZWxlY3QoCnBvdjIwMTAsCnBvdjIwMTgsCiAgKSAlPiUgCiAgbXV0YXRlKAogICAgeCA9IHBvdjIwMTAsCiAgICB5ID0gcG92MjAxOAogICkgJT4lIAogIHNlbGVjdCgKICAgIHgsCiAgICB5CiAgKQoKYGBgCgoKIyBVbml2YXJpYXRlIGR5bmFtaWNzCgojIyBTZWxlY3QgYmFuZHdpdGhzCgpTZWxlY3QgYmFuZHdpZHRoIGJhc2VkIG9uIGZ1bmN0aW9uIGBkcGlrYCBmcm9tIHRoZSBwYWNrYWdlIGBLZXJuU21vb3RoYAoKYGBge3J9CmhfcmVsX3BvdjIwMTA8LSBkcGlrKGRhdCRyZWxfcG92MjAxMCkKaF9yZWxfcG92MjAxMApgYGAKCgpgYGB7cn0KaF9yZWxfcG92MjAxOCA8LSBkcGlrKGRhdCRyZWxfcG92MjAxOCkKaF9yZWxfcG92MjAxOApgYGAKCiMjIFBsb3QgZWFjaCBkZW5zaXR5CgpgYGB7cn0KZGlzX3JlbF9wb3YyMDEwIDwtIGJrZGUoZGF0JHJlbF9wb3YyMDEwLCBiYW5kd2lkdGggPSBoX3JlbF9wb3YyMDEwKQpkaXNfcmVsX3BvdjIwMTAgPC0gYXMuZGF0YS5mcmFtZShkaXNfcmVsX3BvdjIwMTApCmdncGxvdChkaXNfcmVsX3BvdjIwMTAsIGFlcyh4LCB5KSkgKyBnZW9tX2xpbmUoKSArIAogIHRoZW1lX21pbmltYWwoKSAKYGBgCgoKYGBge3J9CmRpc19yZWxfcG92MjAxOCA8LSBia2RlKGRhdCRyZWxfcG92MjAxOCwgYmFuZHdpZHRoID0gaF9yZWxfcG92MjAxOCkKZGlzX3JlbF9wb3YyMDE4IDwtIGFzLmRhdGEuZnJhbWUoZGlzX3JlbF9wb3YyMDE4KQpnZ3Bsb3QoZGlzX3JlbF9wb3YyMDE4LCBhZXMoeCwgeSkpICsgZ2VvbV9saW5lKCkgKyAKICB0aGVtZV9taW5pbWFsKCkgCmBgYAoKCiMjIFBsb3QgYm90aCBkZW5zaXRpZXMKClRoZXJlIGFyZSB0d28gbWV0aG9kcyBmb3IgcGxvdCBib3RoIGRlbnNpdGllcyxpLmUuIEtlcm5zbW9vdGggYW5kIGJhbmR3aXRoIGRlZmF1bHQgb2YgZ2dwbG90LiBJIHByZWZlciB1c2luZyB0aGUgZ2dsb3QgKCBNZXRob2QgMikuCgojIE1ldGhvZCAyIChnZ3Bsb3QpCgpVc2luZyB0aGUgYmFuZHdpZHRoIGRlZmF1bHQgb2YgZ2dwbG90IApNYW51YWwgbGFiZWxzIGFyZSBub3QgeWV0IGltcGxlbWVudGVkIGluIHRoZSBgZ2dwbG90bHlgIGZ1bmN0aW9uCgpgYGB7cn0KcmVsX3BvdjIwMTAgPC0gZGF0ICU+JSAKICBzZWxlY3QocmVsX3BvdjIwMTApICU+JSAKICByZW5hbWUocmVsX3ZhciA9IHJlbF9wb3YyMDEwKSAlPiUgCiAgbXV0YXRlKHllYXIgPSAyMDEwKQpgYGAKCmBgYHtyfQpyZWxfcG92MjAxOCA8LSBkYXQgJT4lIAogIHNlbGVjdChyZWxfcG92MjAxOCkgJT4lIAogIHJlbmFtZShyZWxfdmFyID0gcmVsX3BvdjIwMTgpICU+JSAKICBtdXRhdGUoeWVhciA9IDIwMTgpCmBgYAoKYGBge3J9CnJlbF9wb3YyMDEwcG92MjAxOCA8LSBiaW5kX3Jvd3MocmVsX3BvdjIwMTAsIHJlbF9wb3YyMDE4KQpgYGAKIApgYGB7cn0KcmVsX3BvdjIwMTBwb3YyMDE4IDwtIHJlbF9wb3YyMDEwcG92MjAxOCAlPiUgCiAgbXV0YXRlKHllYXIgPSBhcy5mYWN0b3IoeWVhcikpCmhlYWQocmVsX3BvdjIwMTBwb3YyMDE4KQpgYGAKIAogCgpgYGB7cn0KZGlzX3JlbF9wb3YyMDEwcG92MjAxOCA8LSBnZ3Bsb3QocmVsX3BvdjIwMTBwb3YyMDE4LGFlcyh4PXJlbF92YXIsIGNvbG9yPXllYXIpKSArCiAgZ2VvbV9kZW5zaXR5KCkgKyAKICB0aGVtZV9taW5pbWFsKCkgCmRpc19yZWxfcG92MjAxMHBvdjIwMTgKYGBgCgoKVXNpbmcgcGxvdGx5CgpgYGB7cn0KZ2dwbG90bHkoZGlzX3JlbF9wb3YyMDEwcG92MjAxOCkKYGBgCgoKCiMgQml2YXJpYXRlIGRlbnNpdHkKCiMjIFVzaW5nIE1vYmlsaXR5IHNjYXR0ZXJwbG90CgpgYGB7cn0KZGF0ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSByZWxfcG92MjAxMCwgeSA9IHJlbF9wb3YyMDE4KSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArCiAgZ2VvbV9hYmxpbmUoYWVzKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZT0iZGFzaGVkIikgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyhzdWJ0aXRsZSA9ICJSZWxhdGl2ZSBQb3YyMDE4IiwKICAgICAgIHggPSAiUmVsYXRpdmUgUG92MjAxMCIsCiAgICAgICB5ID0gIiIpICsKICB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChmYW1pbHk9IlBhbGF0aW5vIikpIApgYGAKCgpGaXQgYSBub24tbGluZWFyIGZ1bmN0aW9uCgpgYGB7cn0KZGF0ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSByZWxfcG92MjAxMCwgeSA9IHJlbF9wb3YyMDE4KSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArIAogIGdlb21fc21vb3RoKCkgKyAKICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEsIGxpbmV0eXBlPSJkYXNoZWQiKSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHN1YnRpdGxlID0gIlJlbGF0aXZlIHBvdjIwMTgiLAogICAgICAgeCA9ICJSZWxhdGl2ZSBwb3YyMDEwIiwKICAgICAgIHkgPSAiIikgKwogIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KGZhbWlseT0iUGFsYXRpbm8iKSkgCmBgYAoKTm90IHRoYXQgdGhlIG5vbmxpbmVhciBmaXQgY3Jvc3NlcyB0aGUgNDUtZGVncmVlIGxpbmUgdHdvIHRpbWVzIGZyb20gYWJvdmUuCgojIyBVc2luZyB0aGUgQml2YXJpYXRlIHBhY2thZ2UKCmBgYHtyfQpiaXZhcmlhdGUgPC0ga2J2cGRmKGRhdCRyZWxfcG92MjAxMCwgZGF0JHJlbF9wb3YyMDE4LCBoX3JlbF9wb3YyMDEwLCBoX3JlbF9wb3YyMDE4KSAKYGBgCgoKYGBge3J9CnBsb3QoYml2YXJpYXRlLAogICAgICB4bGFiPSJSZWxhdGl2ZSBQb3ZlcnR5IDIwMTAiLCAKICAgICAgeWxhYj0iUmVsYXRpdmUgUG92ZXJ0eSAyMDE4IikKYWJsaW5lKGE9MCwgYj0xKQphYmxpbmUoaD0xLCB2PTEpCmBgYAoKCmBgYHtyfQpwbG90KGJpdmFyaWF0ZSwKICAgICAgVFJVRSwKICAgICAgeGxhYj0iUmVsYXRpdmUgUG92ZXJ0eSAyMDEwIiwgCiAgICAgIHlsYWI9IlJlbGF0aXZlIFBvdmVydHkgMjAxOCIpCmBgYAoKCiMjIFVzaW5nIGdncGxvdCAoc3RhdF9kZW5zaXR5XzJkKQoKYGBge3J9CmRhdCAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gcmVsX3BvdjIwMTAsIHkgPSByZWxfcG92MjAxOCkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImxpZ2h0Z3JheSIpICsgCiAgZ2VvbV9zbW9vdGgoKSArIAogICNnZW9tX3Ntb290aChtZXRob2Q9bG0sIHNlPUZBTFNFKSArIAogIHN0YXRfZGVuc2l0eV8yZCgpICsKICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEsIGxpbmV0eXBlPSJkYXNoZWQiKSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHN1YnRpdGxlID0gIlJlbGF0aXZlIHBvdjIwMTgiLAogICAgICAgeCA9ICJSZWxhdGl2ZSBwb3YyMDEwIiwKICAgICAgIHkgPSAiIikgKwogIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KGZhbWlseT0iUGFsYXRpbm8iKSkgCmBgYAoKCgpgYGB7cn0KZGF0ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSByZWxfcG92MjAxMCwgeSA9IHJlbF9wb3YyMDE4KSkgKwogICAgICAgIHN0YXRfZGVuc2l0eV8yZChhZXMoZmlsbCA9IHN0YXQobmxldmVsKSksIGdlb20gPSAicG9seWdvbiIpICsgCiAgc2NhbGVfZmlsbF92aXJpZGlzX2MoKSArCiAgICAgICAgZ2VvbV9hYmxpbmUoYWVzKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkpICsKICAgICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZT0iZGFzaGVkIikgKyAKICAgICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZT0iZGFzaGVkIikgKyAKICB0aGVtZV9taW5pbWFsKCkgKwogICAgICAgIGxhYnMoeCA9ICJSZWxhdGl2ZSBQb3ZlcnR5IFJhdGUgMjAxMCIsCiAgICAgICAgICAgICB5ID0gIlJlbGF0aXZlIFBvdmVydHkgUmF0ZSAyMDE4IikgKwogICAgICAgIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9OCwgZmFtaWx5PSJQYWxhdGlubyIpKQpgYGAKCgojIyBVc2luZyBTdG9jaGFzdGljIEtlcm5lbCBQYWNrYWdlCgpUaGVyZSBhcmUgdHdvIHdheXMgb2YgYW5hbHl6aW5nIHRoZSB1c2Ugb2Ygc3RvY2hhc3RpYyBrZXJuZWwgcGFja2FnZTogMS4gQ29udG91ciBQbG90cwphbmQgMi4gU3VyZmFjZSBQbG90cwoKIyMjIENvbnRvdXIgUGxvdHMKCmBgYHtyfQpwb3YyMDEwcG92MjAxOCA8LSBjYmluZChkYXQkcmVsX3BvdjIwMTAsIGRhdCRyZWxfcG92MjAxOCkKcG92MjAxMHBvdjIwMThfZGlzIDwtIGJrZGUyRChwb3YyMDEwcG92MjAxOCwgYmFuZHdpZHRoID0gYyhoX3JlbF9wb3YyMDEwLCBoX3JlbF9wb3YyMDE4KSkgCmBgYAoKYGBge3J9CmNvbnRvdXIocG92MjAxMHBvdjIwMThfZGlzJHgxLHBvdjIwMTBwb3YyMDE4X2RpcyR4Mixwb3YyMDEwcG92MjAxOF9kaXMkZmhhdCkKYWJsaW5lKGE9MCwgYj0xKQpgYGAKCiMjIyBTdXJmYWNlIFBsb3RzCgpgYGB7cn0KcGxvdF9seSh4PXBvdjIwMTBwb3YyMDE4X2RpcyR4MSwgeT1wb3YyMDEwcG92MjAxOF9kaXMkeDIsIHo9cG92MjAxMHBvdjIwMThfZGlzJGZoYXQpICU+JSBhZGRfc3VyZmFjZSgpCmBgYApgYGB7cn0KcGxvdF9seSh4PXBvdjIwMTBwb3YyMDE4X2RpcyR4MSwgeT1wb3YyMDEwcG92MjAxOF9kaXMkeDIsIHo9cG92MjAxMHBvdjIwMThfZGlzJGZoYXQsIHR5cGUgPSAiY29udG91ciIsIGNvbnRvdXJzID0gbGlzdChzaG93bGFiZWxzID0gVFJVRSkpICAlPiUKICBjb2xvcmJhcih0aXRsZSA9ICJEZW5zaXR5IikKYGBgCgojIENvbmRpdGlvbmFsIGRlbnNpdHkgYW5hbHlzaXMKCiMjIFVzaW5nIHRoZSBgaGRyY2RlYCBwYWNrYWdlCgpgYGB7cn0KcG92MjAxMHBvdjIwMThfY2RlIDwtIGNkZShkYXQkcmVsX3BvdjIwMTAsIGRhdCRyZWxfcG92MjAxOCkKYGBgCgpJbmNyZWFzZSB0aGUgbnVtYmVyIG9mIGludGVydmFscyB0byA2MAoKYGBge3J9CnBvdjIwMTBwb3YyMDE4X2NkZTIgPC0gY2RlKGRhdCRyZWxfcG92MjAxMCwgZGF0JHJlbF9wb3YyMDE4LCBueG1hcmdpbiA9IDIwKQpgYGAKCgpgYGB7cn0KcGxvdChwb3YyMDEwcG92MjAxOF9jZGUpCmBgYAoKCmBgYHtyfQpwbG90KHBvdjIwMTBwb3YyMDE4X2NkZTIpCmBgYAoKCkhpZ2ggZGVuc2l0eSByZWdpb25zCgoKYGBge3J9CnBsb3QocG92MjAxMHBvdjIwMThfY2RlLCBwbG90LmZuPSJoZHIiKQphYmxpbmUoYT0wLCBiPTEpCmFibGluZShoPTEsIHY9MSkKYGBgCgoKCmBgYHtyfQpwbG90KHBvdjIwMTBwb3YyMDE4X2NkZTIsIHBsb3QuZm49ImhkciIpCmFibGluZShhPTAsIGI9MSkKYWJsaW5lKGg9MSwgdj0xKQpgYGAKCgojIyBVc2luZyB0aGUgYG5wYCBwYWNrYWdlCgpDb21wdXRlIGFkYXB0aXZlIGJhbmR3aXRoIGJhc2VkIG9uIGNyb3NzLXZhbGlkYXRpb24KCmBgYHtyfQpid19jX2FkX2N2IDwtIG5wY2RlbnNidygKICBmb3JtdWxhID0gZGF0JHJlbF9wb3YyMDE4IH4gZGF0JHJlbF9wb3YyMDEwLCAKICBid3R5cGUgPSAiYWRhcHRpdmVfbm4iKSAKYGBgCgpgYGB7cn0Kc3VtbWFyeShid19jX2FkX2N2KQpgYGAKCkNvbXB1dGUgY29uZGl0aW9uYWwgZGVuc2l0eSBvYmplY3QKCmBgYHtyfQpjZGlzdF9id0NWIDwtIG5wY2RlbnMoYndzID0gYndfY19hZF9jdikKc3VtbWFyeShjZGlzdF9id0NWKQpgYGAKCgoKCmBgYHtyfQpwb3YgPC0gZGF0WyxjKDMsIDExKV0KcG92CmBgYAoKCmBgYHtyfQpjbC5wb3YgPC0gcGRmQ2x1c3Rlcihwb3YpCnN1bW1hcnkoY2wucG92KQpgYGAKYGBge3J9CmZpZzEgPC0gY2RlKGRhdCRwb3YyMDEwLCBkYXQkcG92MjAxOCwgCiAgICAgICAgICAgIHgubmFtZT0iUG92ZXJ0eSBSYXRlIGluIDIwMTAiLAogICAgICAgICAgICB5Lm5hbWU9IlBvdmVydHkgUmF0ZSBpbiAyMDE4IikKcGxvdChmaWcxKQoKIyAxLiBDcmVhdGUgdGhlIHBsb3QKcGxvdChmaWcxKQojIDIuIENsb3NlIHRoZSBmaWxlCmRldi5vZmYoKQpgYGAKCgpgYGB7cn0KcGxvdF9zY19wb3YgPC0gcGxvdChjbC5wb3YsIAogICAgICAgICAgICAgICAgIHN0YWdlID0gMCwKICAgICAgICAgICAgICAgICB3aGljaCA9IDMsCiAgICAgICAgICAgICAgICAgZnJhbWUgPSBGQUxTRSkKIyAxLiBDcmVhdGUgdGhlIHBsb3QKcGxvdChjbC5wb3YsIAogICAgICBzdGFnZSA9IDAsCiAgICAgIHdoaWNoID0gMywKICAgICAgZnJhbWUgPSBGQUxTRSkKIyAyLiBDbG9zZSB0aGUgZmlsZQpkZXYub2ZmKCkKYGBgCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CnBsb3QoZmlnMSwgcGxvdC5mbj0iaGRyIikKCiMgMS4gQ3JlYXRlIHRoZSBwbG90CnBsb3QoZmlnMSwgcGxvdC5mbj0iaGRyIikKIyAyLiBDbG9zZSB0aGUgZmlsZQpkZXYub2ZmKCkKYGBgCgojIFJlZmVyZW5jZXMKCi0gW01hZ3JpbmksIFMuICgyMDA3KS4gQW5hbHlzaW5nIGNvbnZlcmdlbmNlIHRocm91Z2ggdGhlIGRpc3RyaWJ1dGlvbiBkeW5hbWljcyBhcHByb2FjaDogd2h5IGFuZCBob3c/LiBVbml2ZXJzaXR5IENhJ0Zvc2Nhcmkgb2YgVmVuaWNlLCBEZXB0LiBvZiBFY29ub21pY3MgUmVzZWFyY2ggUGFwZXIgU2VyaWVzIE5vLCAxMy4gXShodHRwczovL3BkZnMuc2VtYW50aWNzY2hvbGFyLm9yZy9lYWIxL2NiODlkZGUwYzkwOTg5OGIwYTQzMjczMzc3YzVkZmE3M2ViYy5wZGYpCgotIE1lbmRleiBDLiAoMjAyMCkuIENsYXNzaWNhbCBzaWdtYSBhbmQgYmV0YSBjb252ZXJnZW5jZSBhbmFseXNpcyBpbiBSOiBVc2luZyB0aGUgUkVBVCAyLjEgUGFja2FnZS4gUiBTdHVkaW8vUlB1YnMuIEF2YWlsYWJsZSBhdCBodHRwczovL3JwdWJzLmNvbS9xdWFyY3MtbGFiL2NsYXNzaWNhbC1jb252ZXJnZW5jZS1yZWF0MjEKCi0gTWVuZGV6IEMuICgyMDIwKS4gVW5pdmFyaWF0ZSBkaXN0cmlidXRpb24gZHluYW1pY3MgaW4gUjogVXNpbmcgdGhlIGdncmlkZ2VzIHBhY2thZ2UuIFIgU3R1ZGlvL1JQdWJzLiBBdmFpbGFibGUgYXQgaHR0cHM6Ly9ycHVicy5jb20vcXVhcmNzLWxhYi91bml2YXJpYXRlLWRpc3RyaWJ1dGlvbi1keW5hbWljcwoKLSBbTWVuZGV6LCBDLiAoMjAyMCkgUmVnaW9uYWwgZWZmaWNpZW5jeSBjb252ZXJnZW5jZSBhbmQgZWZmaWNpZW5jeSBjbHVzdGVycy4gQXNpYS1QYWNpZmljIEpvdXJuYWwgb2YgUmVnaW9uYWwgU2NpZW5jZSwgMS0yMS5dKGh0dHA6Ly9lbS5yZGN1LmJlL3dmL2NsaWNrP3Vwbj1sTVp5MWxlcm5TSjdhcGM1RGdZTThZVGhTSTViS1cwNnpuVzNCYW5PLTJGUnMtM0RfdTZhMlBxRjN2c2xOTnRTUmJoeEpQY0pLeE81RUt6T3NmMC0yRldpaXpONTdkNGNzRjdSZU11cjVlNDBUYlg0OERiU2U5a0VNQ3dGcHZ2RnBMY3VhVkItMkJwZEMzZkxDYnNQMGlLY3N4SXMxZHYxeXJQc0dEQ05oNWJoZ3ZJOC0yRi0yQnh3ejd1cGpEZ3ljcVBiaE9iTnFrVDQxdXFZM2RQaVhyNXZCb1kxeHdUODhNQTMtMkZiZEpnd29CbDFHbnpsaTEzbWttbEpqMGtxVHMtMkJsbFZmQ1RCMzU2bUxqaktSMlZCWkNVZ0tieVZwWWd1MXZYandUd2RPeXpkNUZUYlU4ZWFSc1d5T1JqZTdXQ1BwR0VLQ1VBdmJlVENTUGEycmZka21ua1FJcnNtWUJTcWZTWjhhYVd6SHdJa01VM2h4YklVNm5IR1EpIAoKLSBbTWVuZGV6LCBDLiAoMjAxOSkuIExhY2sgb2YgR2xvYmFsIENvbnZlcmdlbmNlIGFuZCB0aGUgRm9ybWF0aW9uIG9mIE11bHRpcGxlIFdlbGZhcmUgQ2x1YnMgYWNyb3NzIENvdW50cmllczogQW4gVW5zdXBlcnZpc2VkIE1hY2hpbmUgTGVhcm5pbmcgQXBwcm9hY2guIEVjb25vbWllcywgNygzKSwgNzQuXShodHRwczovL3d3dy5tZHBpLmNvbS8yMjI3LTcwOTkvNy8zLzc0L3BkZikKCi0gTWVuZGV6LCBDLiAoMjAxOSkuIE92ZXJhbGwgZWZmaWNpZW5jeSwgcHVyZSB0ZWNobmljYWwgZWZmaWNpZW5jeSwgYW5kIHNjYWxlIGVmZmljaWVuY3kgYWNyb3NzIHByb3ZpbmNlcyBpbiBJbmRvbmVzaWEgMTk5MCBhbmQgMjAxMC4gUiBTdHVkaW8vUlB1YnMuIEF2YWlsYWJsZSBhdCBodHRwczovL3JwdWJzLmNvbS9xdWFyY3MtbGFiL2VmZmljaWVuY3ktY2x1c3RlcnMtaW5kb25lc2lhLTE5OTAtMjAxMAoKLSBbTWVuZGV6LUd1ZXJyYSwgQy4gKDIwMTgpLiBPbiB0aGUgZGlzdHJpYnV0aW9uIGR5bmFtaWNzIG9mIGh1bWFuIGRldmVsb3BtZW50OiBFdmlkZW5jZSBmcm9tIHRoZSBtZXRyb3BvbGl0YW4gcmVnaW9ucyBvZiBCb2xpdmlhJycuIEVjb25vbWljcyBCdWxsZXRpbiwgMzgoNCksIDI0NjctMjQ3NS5dKGh0dHA6Ly93d3cuYWNjZXNzZWNvbi5jb20vUHVicy9FQi8yMDE4L1ZvbHVtZTM4L0VCLTE4LVYzOC1JNC1QMjIzLnBkZikKCgpFTkQK