Contextualización de la encuesta
Las encuestas dirigidas a los distintos hogares constituyen una de las principales fuentes de datos socioeconómicos con las que cuentan los países. A partir de la información obtenida de ellas, es posible calcular indicadores para la medición de variados aspectos económicos y sociales; además, facilitan el conocimiento y explicación de los determinantes o factores causales del comportamiento de dichos aspectos, lo cual es de gran importancia para el diseño, monitoreo y medición de resultados de las políticas públicas.” DANE, 2018.
La Encuesta de Calidad de Vida (ECV) es un instrumento diseñado para realizar el seguimiento y la medición de las condiciones de vida de los colombianos, incluyendo variables relacionadas con la vivienda, educación, salud, cuidado de los niños, fuerza de trabajo, gastos e ingresos, etc.
Análisis descriptivo
El conjunto de datos está compuesto por 93993 observaciones y 14 variables, de las cuales fue necesario transformar los valores numéricos y variables categóricas, además de realizar un proceso de imputación de valores faltantes para garantizar la calidad de los datos. Una visualización de los datos se muestra a continuación:
load("C:/Users/ASUS/Desktop/a/seminario/datos.RData")
paged_table(datos, options = list(rows.print = 6, cols.print=6))
Con el fin de realizar una imputación de valores faltantes, se presenta un gráfico que permite visualizar el porcentaje de valores faltantes dentro del conjunto de datos.
# dim(datos) # 93993 observaciones, 14 variables
# conversión del ingreso
datos$Ingreso <- gsub(",",".",datos$Ingreso)
datos$Ingreso_percapita <- gsub(",",".",datos$Ingreso_percapita)
datos$Ingreso <- round(as.double(datos$Ingreso), 2)
datos$Ingreso_percapita <- round(as.double(datos$Ingreso_percapita), 2)
# imputacion de valores faltantes
# para ver cuantos valores faltantes hay por columna
# datos %>%
# summarise_all(funs(sum(is.na(.))))
missmap(datos)

#' la mayoria de los hogares tienen un inodoro así que con este valor se imputan NA's para
#' esta variable
datos$Inodoros[is.na(datos$Inodoros)] <- 1
#' la mayoria de los hogares tienen una cocina así que con este valor se imputan NA's para
#' esta variable
datos$Cocina[is.na(datos$Cocina)] <- 2
datos$Cocina <- ifelse(1, "Sí", "No")
#' la mayoria de los hogares son estrato 1 así que con este valor se imputan NA's para
#' esta variable
datos$Estrato[is.na(datos$Estrato)] <- 1
#' las personas con valores faltantes en el arriendo debe ser porque no pagan,
#' se reemplazan por 0
datos$Arriendo[is.na(datos$Arriendo)] <- 0
# se eliminan los valores de identificación
datos <- datos %>% select(!c("DIRECTORIO", "SECUENCIA_ENCUESTA"))
Análisis de variables individuales
Lo siguiente entonces es realizar un análisis de los datos por medio de visualizaciones. Inicialmente se presentan histogramas para variables numéricas continuas.
a <- datos %>% ggplot(aes(x = Ingreso)) +
geom_histogram(bins = 30, col ='black', fill = "#FF6A6A",
alpha = 0.4) +
ggtitle("Ingreso del hogar") +
theme_bw()
b <- datos %>% ggplot(aes(x = Ingreso_percapita)) +
geom_histogram(bins = 30, col ='black', fill = "#00BFFF",
alpha = 0.4) +
ggtitle("Ingreso del hogar per capita") +
theme_bw()
c <- datos %>% ggplot(aes(x = Superficie)) +
geom_histogram(bins = 30, col='black', fill= "lightgoldenrod1",
alpha=0.4) +
ggtitle("Superficie de la región") +
theme_bw()
d <- datos %>% ggplot(aes(x = Arriendo)) +
geom_histogram(bins = 30, col='black', fill= "springgreen2",
alpha=0.4) +
ggtitle("Valor de Arriendo") +
theme_bw()
grid.arrange(a,b, ncol = 2)

grid.arrange(c,d, ncol = 2)

Se observa una clara asimetría hacia la derecha para cada una de las variables numéricas en el conjunto de datos, además de que la mayoría de las observaciones parecen estar acumuladas en un rango muy cercano al mínimo de cada variable.
Ahora, se presentan diagramas de barras con la cantidad de hogares para cada una de las categorías de las distintas variables categóricas, además del mismo tipo de gráficos para variables numéricas de tipo discreto, tales como el estrato, el número de cuartos, etc.
mis.colores.3 <- colorRampPalette(c("#ff9999", "#99ff99", "#9999ff"))
datos %>%
group_by(Region) %>%
summarise(Frecuencia = n()) %>%
ggplot(aes(x = Region, y = Frecuencia)) +
geom_bar(stat = "identity", width = 0.5, fill = mis.colores.3(9)) +
theme_bw() +
geom_text(size = 3,aes(label = Frecuencia), col = "#696969",
vjust = -0.5) +
ggtitle("Número de hogares por región") +
labs(x = "Región") +
coord_flip()

Es posible apreciar que Caribe y central, sin considerar Bogotá, son las regiones con mayor número de hogares registrados en el conjunto de datos, mientras que regiones como San Andrés y Bogotá (tomada como región por parte del DANE), presentan menor número de hogares registrados.
num_cuartos <- datos %>%
group_by(Cuartos) %>%
summarise(Frecuencia = n())
num_cuartos <- data.frame(num_cuartos)
num_cuartos1 <- num_cuartos[1:8,]
num_cuartos1$Cuartos <- as.character(num_cuartos1$Cuartos)
a <- num_cuartos1 %>%
ggplot(aes(x = Cuartos, y = Frecuencia)) +
geom_bar(stat = "identity", width = 0.5, fill = mis.colores.3(8)) +
theme_bw() +
geom_text(size = 3,aes(label = Frecuencia), col = "#696969",
vjust = -0.5) +
ggtitle("Número de cuartos")
num_dormitorios <- datos %>%
group_by(Dormitorios) %>%
summarise(Frecuencia = n())
num_dormitorios <- data.frame(num_dormitorios)
num_dormitorios1 <- num_dormitorios[1:8,]
num_dormitorios1$Dormitorios <- as.character(num_dormitorios1$Dormitorios)
b <- num_dormitorios1 %>%
ggplot(aes(x = Dormitorios, y = Frecuencia)) +
geom_bar(stat = "identity", width = 0.5, fill = mis.colores.3(8)) +
theme_bw() +
geom_text(size = 3,aes(label = Frecuencia), col = "#696969",
vjust = -0.5) +
ggtitle("Número de Dormitorios")
num_inodoros <- datos %>%
group_by(Inodoros) %>%
summarise(Frecuencia = n())
num_inodoros <- num_inodoros
num_inodoros1 <- num_inodoros[1:8,]
num_inodoros1$Inodoros <- as.character(num_inodoros1$Inodoros)
c <- num_inodoros1 %>%
ggplot(aes(x = Inodoros, y = Frecuencia)) +
geom_bar(stat = "identity", width = 0.5, fill = mis.colores.3(8)) +
theme_bw() +
geom_text(size = 3,aes(label = Frecuencia), col = "#696969",
vjust = -0.5) +
ggtitle("Número de Inodoros")
num_personas <- datos %>%
group_by(Personas) %>%
summarise(Frecuencia = n())
num_personas <- data.frame(num_personas)
num_personas1 <- num_personas[1:8,]
num_personas1$Personas <- as.character(num_personas1$Personas)
d <- num_personas1 %>%
ggplot(aes(x = Personas, y = Frecuencia)) +
geom_bar(stat = "identity", width = 0.5, fill = mis.colores.3(8)) +
theme_bw() +
geom_text(size = 3,aes(label = Frecuencia), col = "#696969",
vjust = -0.5) +
ggtitle("Número de Personas")
grid.arrange(a, b, nrow = 1)

grid.arrange(c, d, nrow = 1)

num_estrato <- datos %>%
group_by(Estrato) %>%
summarise(Frecuencia = n())
num_estrato <- data.frame(num_estrato)
num_estrato1 <- num_estrato[1:8,]
num_estrato1$Estrato <- as.character(num_estrato1$Estrato)
num_estrato1 %>%
ggplot(aes(x = Estrato, y = Frecuencia)) +
geom_bar(stat = "identity", width = 0.5, fill = mis.colores.3(8)) +
theme_bw() +
geom_text(size = 3,aes(label = Frecuencia), col = "#696969",
vjust = -0.5) +
ggtitle("Estrato del hogar")

datos %>%
group_by(Tipo_vivienda) %>%
summarise(Frecuencia = n()) %>%
ggplot(aes(x = Tipo_vivienda, y = Frecuencia)) +
geom_bar(stat = "identity", width = 0.5, fill = mis.colores.3(5)) +
theme_bw() +
geom_text(size = 3,aes(label = Frecuencia), col = "#696969",
vjust = -0.5) +
ggtitle("Tipo de vivienda de los hogares") +
labs(x = "") +
coord_flip()

datos %>%
group_by(Posesion_vivienda) %>%
summarise(Frecuencia = n()) %>%
ggplot(aes(x = Posesion_vivienda, y = Frecuencia)) +
geom_bar(stat = "identity", width = 0.5, fill = mis.colores.3(6)) +
theme_bw() +
geom_text(size = 3,aes(label = Frecuencia), col = "#696969",
vjust = -0.5) +
ggtitle("Tipo de vivienda de los hogares") +
labs(x = "") +
coord_flip()

La mayoría de los hogares ocupan un espacio que tiene entre 2 y 5 cuartos, aunque hubo aproximadamente 50 hogares que tenían registro de ocupación de más de 10 cuartos.
El número de dormitorios de un hogar puede estar entre 1 y 8, aunque la mayoría de los hogares no tienen más de 3 dormitorios; además, es esperable que el número de dormitorios esté incluido en el número de cuartos que ocupa el hogar, por lo que el número de dormitorios siempre es menor o igual al número de cuartos del hogar.
Se puede apreciar que gran parte de los hogares tienen entre 1 y 2 inodoros.
Los hogares colombianos tenden en su mayoría a estar compuestos por una cantidad de personas entre 1 y 7, aunque se encontraron unos pocos hogares en donde el número de personas podía llegar a ser entre 10 y 19.
La mayoría de los hogares colombianos son estrato 1, 2 o 3, aunque hay registro de casi 4000 hogares colombianos en donde no tienen estratificación o el acceso a servicios públicos es pirateado, los cuales corresponden a valores de 0 visibles en el gráfico.
La mayoría de los hogares colombianos registrados viven en casas o apartamentos, aunque hay casos en los cuales ocupan un solo cuarto o unos pocos cuartos de la vivieda, una vivienda tradicional indígena, u otro tipo de vivienda tales como carpas, contenedores, vagones, entre otros.
Los hogares colombianos tienden en su mayoría vivienda propia, aunque también hay bastantes registros de hogares que han usufructuado un sitio; también es apreciable una poca cantidad de hogares que comparte vivienda, ya sea como propiedad colectiva o con la modalidad de propia parcialmente.
Para la variable cocina, se encontró que todos los hogares colombianos tomados en la muestra poseen cocina, por lo que al no brindar información relevante, esta variable fue descartada para el resto del análisis.
Análisis de relaciones entre variables
A continuación se considera la matriz de correlación para variables numéricas, utilizando el coeficiente de correlación de Spearman que permite analizar el grado de asociación entre variables numéricas, ya sean de tipo discreto o continuo:
mis.colores.4 <- colorRampPalette(c("#99ff99", "#9999ff", "#ff9999"))
numericas <- datos %>% select(hijos, Cuartos, Dormitorios, Inodoros, Ingreso, Ingreso_percapita,
Superficie, Estrato, Arriendo)
cor_matrix <- round(cor(numericas, method = "spearman"), 2)
corrplot(cor_matrix, method = "shade", shade.col = NA, tl.col = "black", tl.srt = 45,
addCoef.col = "black", col = mis.colores.4(200), type = "upper")

Es posible apreciar correlaciones altas entre el valor del ingreso, con el valor del ingreso percapita en el hogar y entre el número de cuartos con el número de dormitorios, por lo que sería viable considerar solo una de las dos variables que presentan alta correlación entre sí en la construcción de un modelo. Según esto, las variables Ingreso percapita y número de dormitorios, no serán consideradas en el ajuste de modelos. Son apreciables también algunas correlaciones positivas mayores a 0.3 en el conjunto de datos.
Para ver la relación entre variables numéricas y el número de hijos del hogar, se consideran los siguientes gráficos boxplot:
require(ggplot2)
a <- datos %>%
ggplot(aes(x = as.factor(hijos),y = Ingreso)) +
geom_boxplot() +
theme_bw() +
ggtitle("Hijos vs. Ingreso") +
labs(x = "Hijos")
b <- datos %>%
ggplot(aes(x = as.factor(hijos),y = Arriendo)) +
geom_boxplot() +
theme_bw() +
ggtitle("Hijos vs. Arriendo") +
labs(x = "Hijos")
c <- datos %>%
ggplot(aes(x = as.factor(hijos),y = Superficie)) +
geom_boxplot() +
theme_bw() +
ggtitle("Hijos vs. Superficie") +
labs(x = "Hijos")
grid.arrange(a,b,c, ncol = 3)

Aunque no se observan diferencias significativas entre el número de hijos del hogar de acuerdo al Ingreso o el Arriendo que pagan, se aprecia gra cantidad de valores atípicos. Además, se observan diferencias para el número de hijos del hogar de acuedo a la superficie en \(km^2\) de la región en la que está ubicado.
Modelos a considerar
Para el ajuste de los modelos se tiene presentes las siguientes consideraciones:
- Se denota como \(y_{ij}\) el número de hijos del hogar j en la región i de colombia, el cual será modelado por medio de una regresión Poisson:
\[y_{ij} \sim Poisson(\lambda_{ij})\]
La regresión tendrá en cuenta solo algunas de las variables analizadas con anterioridad, las cuales representan información de los hogares, o de la región en la cual están ubicados.
Modelo 1
Modelo lineal generalizado de distribución Poisson e intercepto aleatorio, con variable predictora Ingreso del hogar.
\[\lambda_{ij} = \beta_0 + \beta_1Ingreso_{ij} + b_{0i}\]
\[b_0 \sim N(0, \sigma^2_{b0})\]
Modelo 2
Modelo lineal generalizado de distribución Poisson e intercepto aleatorio, tomando como variables predictoras Ingreso del hogar y Tipo de vivienda.
\[\lambda_{ij} = \beta_0 + \beta_1Ingreso_{ij} + \beta_2Apartamento_{ij} + \beta_3Casa_{ij} + \beta_4Cuarto_{ij} + \beta_5Otro_{ij} + b_{0i}\]
\[b_0 \sim N(0, \sigma^2_{b0})\]
Modelo 3
Modelo lineal generalizado de distribución Poisson, con intercepto y pendiente aleatorios, tomando como variables predictoras Ingreso del hogar y Tipo de vivienda.
\[\lambda_{ij} = \beta_0 + \beta_1Ingreso_{ij} + \beta_2Apartamento_{ij} + \beta_3Casa_{ij} + \beta_4Cuarto_{ij} + \beta_5Otro_{ij} + b_{0i} + b_{1}Region_{ij}\]
\[X = \begin{pmatrix}b_0\\
b_1
\end{pmatrix} \sim N \left[ \begin{pmatrix}0\\
0
\end{pmatrix}, \begin{bmatrix}\sigma_{b0}^2 & \sigma_{b01}^2\\
\sigma_{b01}^2 & \sigma_{b1}^2
\end{bmatrix}\right]\]
Comparación de modelos
En esta sección se elegirá uno de los modelos mostrados con anterioridad, por medio de la puerba de razón de verosimilitud. A continuación se presenta el vector de parámetros estimados para cada uno de los modelos:
Modelo 1
\[\Theta_1 = (\beta_0, \beta_1, \sigma_{b_0})^T\]
\[\hat{\Theta_1} = (0.033646, 0.024726, 0.1466)^T\]
Modelo 2
\[\Theta_2 = (\beta_0, \beta_1, \beta_2, \beta_3, \beta_4, \beta_5, \sigma_{b_0})^T\]
\[\hat{\Theta_2} = (0.499416, 0.028018, -0.564548, -0.415342, -1.025895, -0.587986, 0.1234)^T\]
Modelo 3
\[\Theta_3 = (\beta_0, \beta_1, \beta_2, \beta_3, \beta_4, \beta_5, \sigma_{b_0}, \sigma_{b_1}, \sigma_{b_{01}})^T\]
\[\hat{\Theta_3} = (0.499416, 0.028018, -0.564548, -0.415342, -1.025895, -0.587986, 0.1234, 0.11596, 0.05426)^T\] La prueba de razón de verosimilitud se plantea de la siguiente manera:
Al considerar dos modelos \(fit_x\) y \(fit_y\) con vectores de parámetros estimados \(\Theta_x\), \(\Theta_y\) respectivamente, tales que \(\Theta_x \subset \Theta_y\), siendo \(\Theta^c_p\) aquellos parámetros que están en \(fit_y\) y no en \(fit_x\). La prueba de gipótesis asociada a la significacia de este vector de parámetros será:
\[H_0: \Theta^c = 0_{1\times p} \quad v.s \quad H_1: \Theta^c \not= 0_{1\times p}\]
Donde el estadístico de prueba está dado por:
\[LR = -2 \times (loglikelihood(fit_x)- loglikelihood(fit_y))\] Para un nivel de significancia \(\alpha\), se rechaza \(H_0\) si \(VP =P(\chi^2_p > LR) < \alpha\).
A continuación se presentan las comparaciones entre modelos, hechas por medio de la función anova().
LS0tDQp0aXRsZTogJ0FwbGljYWNpw7NuIGRlIG1vZGVsb3MgbWl4dG9zIHBhcmEgZXN0aW1hciBlbCBuw7ptZXJvIGRlIGhpam9zIGRlIHVuIGhvZ2FyIGNvbG9tYmlhbm8nDQpzdWJ0aXRsZTogJ1NlbWluYXJpbyBkZSBhcGxpY2FjacOzbiAtIE1vZGVsb3MgbWl4dG9zJw0KYXV0aG9yOiAiU3RlcGhhbnkgTWljaGVsbCBMb2JvIExhZ3VhZG8gPGJyPiBVbml2ZXJzaWRhZCBOYWNpb25hbCBkZSBDb2xvbWJpYSA8YnI+IFNlZGUgTWVkZWxsw61uIg0KZGF0ZTogXHRvZGF5DQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMw0KICAgIHRoZW1lOiBmbGF0bHkNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KEFtZWxpYSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ3JpZEV4dHJhKQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkocm1hcmtkb3duKQ0KbGlicmFyeShsbWU0KQ0KYGBgDQoNCiMgQ29udGV4dHVhbGl6YWNpw7NuIGRlIGxhIGVuY3Vlc3RhDQoNCkxhcyBlbmN1ZXN0YXMgZGlyaWdpZGFzIGEgbG9zIGRpc3RpbnRvcyBob2dhcmVzIGNvbnN0aXR1eWVuIHVuYSBkZSBsYXMgcHJpbmNpcGFsZXMgZnVlbnRlcyBkZSBkYXRvcyBzb2Npb2Vjb27Ds21pY29zIGNvbiBsYXMgcXVlIGN1ZW50YW4gbG9zIHBhw61zZXMuIEEgcGFydGlyIGRlIGxhIGluZm9ybWFjacOzbiBvYnRlbmlkYSBkZSBlbGxhcywgZXMgcG9zaWJsZSBjYWxjdWxhciBpbmRpY2Fkb3JlcyBwYXJhIGxhIG1lZGljacOzbiBkZSB2YXJpYWRvcyBhc3BlY3RvcyBlY29uw7NtaWNvcyB5IHNvY2lhbGVzOyBhZGVtw6FzLCBmYWNpbGl0YW4gZWwgY29ub2NpbWllbnRvIHkgZXhwbGljYWNpw7NuIGRlIGxvcyBkZXRlcm1pbmFudGVzIG8gZmFjdG9yZXMgY2F1c2FsZXMgZGVsIGNvbXBvcnRhbWllbnRvIGRlIGRpY2hvcyBhc3BlY3RvcywgbG8gY3VhbCBlcyBkZSBncmFuIGltcG9ydGFuY2lhIHBhcmEgZWwgZGlzZcOxbywgbW9uaXRvcmVvIHkgbWVkaWNpw7NuIGRlIHJlc3VsdGFkb3MgZGUgbGFzIHBvbMOtdGljYXMgcMO6YmxpY2FzLuKAnSBbREFORSwgMjAxOF0oaHR0cHM6Ly93d3cuZGF0b3MuZ292LmNvL0VzdGFkLXN0aWNhcy1OYWNpb25hbGVzL0VuY3Vlc3RhLU5hY2lvbmFsLWRlLUNhbGlkYWQtZGUtVmlkYS1FQ1YtL216OXktM3g5aykuDQoNCkxhIEVuY3Vlc3RhIGRlIENhbGlkYWQgZGUgVmlkYSAoRUNWKSBlcyB1biBpbnN0cnVtZW50byBkaXNlw7FhZG8gcGFyYSByZWFsaXphciBlbCBzZWd1aW1pZW50byB5IGxhIG1lZGljacOzbiBkZSBsYXMgY29uZGljaW9uZXMgZGUgdmlkYSBkZSBsb3MgY29sb21iaWFub3MsIGluY2x1eWVuZG8gdmFyaWFibGVzIHJlbGFjaW9uYWRhcyBjb24gbGEgdml2aWVuZGEsIGVkdWNhY2nDs24sIHNhbHVkLCBjdWlkYWRvIGRlIGxvcyBuacOxb3MsIGZ1ZXJ6YSBkZSB0cmFiYWpvLCBnYXN0b3MgZSBpbmdyZXNvcywgZXRjLg0KDQojIERlc2NyaXBjacOzbiBkZSBsYSBiYXNlIGRlIGRhdG9zIHkgc3VzIHZhcmlhYmxlcw0KDQpQYXJhIGxhIG9idGVuY2nDs24gZGUgdW4gY29uanVudG8gZGUgZGF0b3MgYSBzZXIgYW5hbGl6YWRvLCBmdWUgbmVjZXNhcmlvIHRvbWFyIHkgZXN0cnVjdHVyYXIgYWxndW5vcyBjYW1wb3MgZGUgaW5mb3JtYWNpw7NuIG9idGVuaWRhIGVuIGxhIFtFbmN1ZXN0YSBOYWNpb25hbCBkZSBDYWxpZGFkIGRlIFZpZGEgLSBFQ1YgMjAxOV0oaHR0cHM6Ly9taWNyb2RhdG9zLmRhbmUuZ292LmNvL2luZGV4LnBocC9jYXRhbG9nLzY3OC9zdHVkeS1kZXNjcmlwdGlvbikuIA0KDQpTZSBlc3RydWN0dXLDsyBlbnRvbmNlcywgdW4gY29uanVudG8gZGUgZGF0b3MgY29uIGxhIHNpZ3VpZW50ZSBpbmZvcm1hY2nDs246IA0KDQoqICoqRElSRUNUT1JJTy9TRUNVRU5DSUEgRU5DVUVTVEE6ICoqIFZhcmlhYmxlcyBjbGF2ZXMgcXVlIHBlcm1pdGVuIHVuaXIgZGlzdGludGFzIGJhc2VzIGRlIGRhdG9zLiAgDQoNCiogKipDdWFydG9zOiAqKiBuw7ptZXJvIGRlIGN1YXJ0b3MgcXVlIG9jdXBhIGVsIGhvZ2FyLiAgDQoNCiogKipEb3JtaXRvcmlvczogKiogbsO6bWVybyBkZSBkb3JtaXRvcmlvcyBxdWUgb2N1cGEgZWwgaG9nYXIuICANCg0KKiAqKklub2Rvcm9zOiAqKiBuw7ptZXJvIGRlIGlub2Rvcm9zIHF1ZSBoYXkgZW4gZWwgaG9nYXIuICANCg0KKiAqKkNvY2luYTogKiogc2kgZWwgaG9nYXIgdGllbmUgbyBubyBjb2NpbmEuICANCiANCiogKipJbmdyZXNvOiAqKiBWYWxvciBkZWwgdG90YWwgZGUgaW5ncmVzb3MgZW4gZWwgaG9nYXIuICANCg0KKiAqKkluZ3Jlc28gcGVyY2FwaXRhOiAqKiB2YWxvciBkZWwgaW5ncmVzbyBwZXIgY2FwaXRhIGVuIGVsIGhvZ2FyLiAgDQoNCiogKipQZXJzb25hczogKiogVG90YWwgZGUgcGVyc29uYXMgcXVlIGhheSBlbiBlbCBob2dhci4gIA0KDQoqICoqUmVnaW9uOiAqKiBSZWdpw7NuIGRlIENvbG9tYmlhIGVuIGxhIGN1YWwgZXN0w6EgdWJpY2FkbyBlbCBob2dhci4gRWwgRGFuZSBjb25zaWRlcmEgbGFzIHNpZ3VpZW50ZXMgOSByZWdpb25lczogQW50aW9xdWlhLCBCb2dvdMOhLCBDYXJpYmUsIENlbnRyYWwsIE9yaWVudGFsLCBPcmlub3F1w61hIC0gQW1hem9uw61hLCBQYWPDrWZpY2EsIFNhbiBBbmRyw6lzIHkgVmFsbGUgZGVsIENhdWNhLiAgDQoNCiogKipTdXBlcmZpY2llOiAqKiBzdXBlcmZpY2llIGVuICRrbV4yJCBkZWwgw6FyZWEgZW4gbGEgY3VhbCBlc3TDoSB1YmljYWRvIGVsIGhvZ2FyLiANCg0KKiAqKkVzdHJhdG86ICoqIGVzdHJhdG8gZGVsIGhvZ2FyLiAgDQoNCiogKipUaXBvX3ZpdmllbmRhOiAqKiBUaXBvIGRlIHZpdmllbmRhIHF1ZSBvY3VwYSBlbCBob2dhci4gIA0KDQoqICoqQXJyaWVuZG86ICoqIHZhbG9yIGRlIGFycmllbmRvIHF1ZSBwYWdhbiBlbiBlbCBob2dhdC4gIA0KDQoqICoqVml2aWVuZGFfcHJvcGlhOiAqKiBzaSBsYSB2aXZpZW5kYSBxdWUgb2N1cGEgZWwgaG9nYXIgZXMgcHJvcGlhIG8gZGUgb3RybyB0aXBvLg0KDQojIE9iamV0aXZvIGRlbCBlc3R1ZGlvDQoNCkVsIG9iamV0aXZvIGRlbCBhbsOhbGlzaXMgZXMgYWp1c3RhciB5IGNvbXBhcmFyIGRpc3RpbnRhcyB0w6ljbmljYXMgZGUgbW9kZWxhY2nDs24gcXVlIHBlcm1pdGFuIG9idGVuZXIgbGEgZXN0aW1hY2nDs24gZGVsIG7Dum1lcm8gZGUgaGlqb3MgZGUgdW4gaG9nYXIgY29sb21iaWFubyBwb3IgbWVkaW8gZGUgdW4gY29uanVudG8gZGUgY292YXJpYmxlcyBvIHZhcmlhYmxlcyBwcmVkaWN0b3Jhcy4NCg0KIyBBbsOhbGlzaXMgZGVzY3JpcHRpdm8gIA0KDQpFbCBjb25qdW50byBkZSBkYXRvcyBlc3TDoSBjb21wdWVzdG8gIHBvciA5Mzk5MyBvYnNlcnZhY2lvbmVzIHkgMTQgdmFyaWFibGVzLCBkZSBsYXMgY3VhbGVzIGZ1ZSBuZWNlc2FyaW8gdHJhbnNmb3JtYXIgbG9zIHZhbG9yZXMgbnVtw6lyaWNvcyB5IHZhcmlhYmxlcyBjYXRlZ8OzcmljYXMsIGFkZW3DoXMgZGUgcmVhbGl6YXIgdW4gcHJvY2VzbyBkZSBpbXB1dGFjacOzbiBkZSB2YWxvcmVzIGZhbHRhbnRlcyBwYXJhIGdhcmFudGl6YXIgbGEgY2FsaWRhZCBkZSBsb3MgZGF0b3MuIFVuYSB2aXN1YWxpemFjacOzbiBkZSBsb3MgZGF0b3Mgc2UgbXVlc3RyYSBhIGNvbnRpbnVhY2nDs246DQoNCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSc3MCUnfQ0KbG9hZCgiQzovVXNlcnMvQVNVUy9EZXNrdG9wL2Evc2VtaW5hcmlvL2RhdG9zLlJEYXRhIikNCg0KcGFnZWRfdGFibGUoZGF0b3MsIG9wdGlvbnMgPSBsaXN0KHJvd3MucHJpbnQgPSA2LCBjb2xzLnByaW50PTYpKQ0KYGBgDQoNCkNvbiBlbCBmaW4gZGUgcmVhbGl6YXIgdW5hIGltcHV0YWNpw7NuIGRlIHZhbG9yZXMgZmFsdGFudGVzLCBzZSBwcmVzZW50YSB1biBncsOhZmljbyBxdWUgcGVybWl0ZSB2aXN1YWxpemFyIGVsIHBvcmNlbnRhamUgZGUgdmFsb3JlcyBmYWx0YW50ZXMgZGVudHJvIGRlbCBjb25qdW50byBkZSBkYXRvcy4NCiANCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSc3MCUnfQ0KIyBkaW0oZGF0b3MpICMgOTM5OTMgb2JzZXJ2YWNpb25lcywgMTQgdmFyaWFibGVzDQoNCiMgY29udmVyc2nDs24gZGVsIGluZ3Jlc28NCmRhdG9zJEluZ3Jlc28gPC0gZ3N1YigiLCIsIi4iLGRhdG9zJEluZ3Jlc28pDQpkYXRvcyRJbmdyZXNvX3BlcmNhcGl0YSA8LSBnc3ViKCIsIiwiLiIsZGF0b3MkSW5ncmVzb19wZXJjYXBpdGEpDQpkYXRvcyRJbmdyZXNvIDwtIHJvdW5kKGFzLmRvdWJsZShkYXRvcyRJbmdyZXNvKSwgMikNCmRhdG9zJEluZ3Jlc29fcGVyY2FwaXRhIDwtIHJvdW5kKGFzLmRvdWJsZShkYXRvcyRJbmdyZXNvX3BlcmNhcGl0YSksIDIpDQoNCiMgaW1wdXRhY2lvbiBkZSB2YWxvcmVzIGZhbHRhbnRlcw0KDQojIHBhcmEgdmVyIGN1YW50b3MgdmFsb3JlcyBmYWx0YW50ZXMgaGF5IHBvciBjb2x1bW5hDQojIGRhdG9zICU+JSANCiMgICBzdW1tYXJpc2VfYWxsKGZ1bnMoc3VtKGlzLm5hKC4pKSkpDQoNCm1pc3NtYXAoZGF0b3MpDQoNCiMnIGxhIG1heW9yaWEgZGUgbG9zIGhvZ2FyZXMgdGllbmVuIHVuIGlub2Rvcm8gYXPDrSBxdWUgY29uIGVzdGUgdmFsb3Igc2UgaW1wdXRhbiBOQSdzIHBhcmENCiMnIGVzdGEgdmFyaWFibGUNCmRhdG9zJElub2Rvcm9zW2lzLm5hKGRhdG9zJElub2Rvcm9zKV0gPC0gMQ0KDQojJyBsYSBtYXlvcmlhIGRlIGxvcyBob2dhcmVzIHRpZW5lbiB1bmEgY29jaW5hIGFzw60gcXVlIGNvbiBlc3RlIHZhbG9yIHNlIGltcHV0YW4gTkEncyBwYXJhDQojJyBlc3RhIHZhcmlhYmxlDQpkYXRvcyRDb2NpbmFbaXMubmEoZGF0b3MkQ29jaW5hKV0gPC0gMg0KZGF0b3MkQ29jaW5hIDwtIGlmZWxzZSgxLCAiU8OtIiwgIk5vIikNCg0KIycgbGEgbWF5b3JpYSBkZSBsb3MgaG9nYXJlcyBzb24gZXN0cmF0byAxIGFzw60gcXVlIGNvbiBlc3RlIHZhbG9yIHNlIGltcHV0YW4gTkEncyBwYXJhDQojJyBlc3RhIHZhcmlhYmxlDQpkYXRvcyRFc3RyYXRvW2lzLm5hKGRhdG9zJEVzdHJhdG8pXSA8LSAxDQoNCiMnIGxhcyBwZXJzb25hcyBjb24gdmFsb3JlcyBmYWx0YW50ZXMgZW4gZWwgYXJyaWVuZG8gZGViZSBzZXIgcG9ycXVlIG5vIHBhZ2FuLA0KIycgIHNlIHJlZW1wbGF6YW4gcG9yIDANCmRhdG9zJEFycmllbmRvW2lzLm5hKGRhdG9zJEFycmllbmRvKV0gPC0gMA0KDQojIHNlIGVsaW1pbmFuIGxvcyB2YWxvcmVzIGRlIGlkZW50aWZpY2FjacOzbg0KZGF0b3MgPC0gZGF0b3MgJT4lICBzZWxlY3QoIWMoIkRJUkVDVE9SSU8iLCAiU0VDVUVOQ0lBX0VOQ1VFU1RBIikpDQoNCmBgYA0KDQojIyBBbsOhbGlzaXMgZGUgdmFyaWFibGVzIGluZGl2aWR1YWxlcw0KDQpMbyBzaWd1aWVudGUgZW50b25jZXMgZXMgcmVhbGl6YXIgdW4gYW7DoWxpc2lzIGRlIGxvcyBkYXRvcyBwb3IgbWVkaW8gZGUgdmlzdWFsaXphY2lvbmVzLiBJbmljaWFsbWVudGUgc2UgcHJlc2VudGFuIGhpc3RvZ3JhbWFzIHBhcmEgdmFyaWFibGVzIG51bcOpcmljYXMgY29udGludWFzLg0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIHdhcm5pbmc9RkFMU0UsIG91dC53aWR0aD0nNzAlJ30NCmEgPC0gZGF0b3MgJT4lICBnZ3Bsb3QoYWVzKHggPSBJbmdyZXNvKSkgKyANCiAgICAgICAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwLCBjb2wgPSdibGFjaycsIGZpbGwgPSAiI0ZGNkE2QSIsDQogICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMC40KSArDQogICAgICAgIGdndGl0bGUoIkluZ3Jlc28gZGVsIGhvZ2FyIikgKw0KICAgICAgICB0aGVtZV9idygpDQoNCmIgPC0gZGF0b3MgJT4lICBnZ3Bsb3QoYWVzKHggPSBJbmdyZXNvX3BlcmNhcGl0YSkpICsgDQogICAgICAgIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgY29sID0nYmxhY2snLCBmaWxsID0gIiMwMEJGRkYiLA0KICAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNCkgKw0KICAgICAgICBnZ3RpdGxlKCJJbmdyZXNvIGRlbCBob2dhciBwZXIgY2FwaXRhIikgKw0KICAgICAgICB0aGVtZV9idygpDQoNCmMgPC0gZGF0b3MgJT4lICBnZ3Bsb3QoYWVzKHggPSBTdXBlcmZpY2llKSkgKyANCiAgICAgICAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwLCBjb2w9J2JsYWNrJywgZmlsbD0gImxpZ2h0Z29sZGVucm9kMSIsDQogICAgICAgICAgICAgICAgICAgICAgIGFscGhhPTAuNCkgKw0KICAgICAgICBnZ3RpdGxlKCJTdXBlcmZpY2llIGRlIGxhIHJlZ2nDs24iKSArIA0KICAgICAgICB0aGVtZV9idygpDQoNCmQgPC0gZGF0b3MgJT4lICBnZ3Bsb3QoYWVzKHggPSBBcnJpZW5kbykpICsgDQogICAgICAgIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgY29sPSdibGFjaycsIGZpbGw9ICJzcHJpbmdncmVlbjIiLA0KICAgICAgICAgICAgICAgICAgICAgICBhbHBoYT0wLjQpICsNCiAgICAgICAgZ2d0aXRsZSgiVmFsb3IgZGUgQXJyaWVuZG8iKSArDQogICAgICAgIHRoZW1lX2J3KCkNCg0KZ3JpZC5hcnJhbmdlKGEsYiwgbmNvbCA9IDIpDQpncmlkLmFycmFuZ2UoYyxkLCBuY29sID0gMikNCiAgICAgIA0KYGBgDQoNClNlIG9ic2VydmEgdW5hIGNsYXJhIGFzaW1ldHLDrWEgaGFjaWEgbGEgZGVyZWNoYSBwYXJhIGNhZGEgdW5hIGRlIGxhcyB2YXJpYWJsZXMgbnVtw6lyaWNhcyBlbiBlbCBjb25qdW50byBkZSBkYXRvcywgYWRlbcOhcyBkZSBxdWUgbGEgbWF5b3LDrWEgZGUgbGFzIG9ic2VydmFjaW9uZXMgcGFyZWNlbiBlc3RhciBhY3VtdWxhZGFzIGVuIHVuIHJhbmdvIG11eSBjZXJjYW5vIGFsIG3DrW5pbW8gZGUgY2FkYSB2YXJpYWJsZS4NCg0KQWhvcmEsIHNlIHByZXNlbnRhbiBkaWFncmFtYXMgZGUgYmFycmFzIGNvbiBsYSBjYW50aWRhZCBkZSBob2dhcmVzIHBhcmEgY2FkYSB1bmEgZGUgbGFzIGNhdGVnb3LDrWFzIGRlIGxhcyBkaXN0aW50YXMgdmFyaWFibGVzIGNhdGVnw7NyaWNhcywgYWRlbcOhcyBkZWwgbWlzbW8gdGlwbyBkZSBncsOhZmljb3MgcGFyYSB2YXJpYWJsZXMgbnVtw6lyaWNhcyBkZSB0aXBvIGRpc2NyZXRvLCB0YWxlcyBjb21vIGVsIGVzdHJhdG8sIGVsIG7Dum1lcm8gZGUgY3VhcnRvcywgZXRjLg0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIHdhcm5pbmc9RkFMU0UsIG91dC53aWR0aD0nODAlJ30NCm1pcy5jb2xvcmVzLjMgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCIjZmY5OTk5IiwgIiM5OWZmOTkiLCAiIzk5OTlmZiIpKQ0KZGF0b3MgJT4lIA0KICBncm91cF9ieShSZWdpb24pICU+JSANCiAgc3VtbWFyaXNlKEZyZWN1ZW5jaWEgPSBuKCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gUmVnaW9uLCB5ID0gRnJlY3VlbmNpYSkpICsgDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNSwgZmlsbCA9IG1pcy5jb2xvcmVzLjMoOSkpICsNCiAgdGhlbWVfYncoKSArIA0KICAgICAgICBnZW9tX3RleHQoc2l6ZSA9IDMsYWVzKGxhYmVsID0gIEZyZWN1ZW5jaWEpLCBjb2wgPSAiIzY5Njk2OSIsDQogICAgICAgICAgICAgICAgICB2anVzdCA9IC0wLjUpICsgDQogIGdndGl0bGUoIk7Dum1lcm8gZGUgaG9nYXJlcyBwb3IgcmVnacOzbiIpICsNCiAgbGFicyh4ID0gIlJlZ2nDs24iKSArDQogIGNvb3JkX2ZsaXAoKQ0KDQpgYGANCg0KRXMgcG9zaWJsZSBhcHJlY2lhciBxdWUgQ2FyaWJlIHkgY2VudHJhbCwgc2luIGNvbnNpZGVyYXIgQm9nb3TDoSwgc29uIGxhcyByZWdpb25lcyBjb24gbWF5b3IgbsO6bWVybyBkZSBob2dhcmVzIHJlZ2lzdHJhZG9zIGVuIGVsIGNvbmp1bnRvIGRlIGRhdG9zLCBtaWVudHJhcyBxdWUgcmVnaW9uZXMgY29tbyBTYW4gQW5kcsOpcyB5IEJvZ290w6EgKHRvbWFkYSBjb21vIHJlZ2nDs24gcG9yIHBhcnRlIGRlbCBEQU5FKSwgcHJlc2VudGFuIG1lbm9yIG7Dum1lcm8gZGUgaG9nYXJlcyByZWdpc3RyYWRvcy4NCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCB3YXJuaW5nPUZBTFNFLCBvdXQud2lkdGg9JzcwJSd9DQpudW1fY3VhcnRvcyA8LSBkYXRvcyAlPiUgDQogICAgICAgIGdyb3VwX2J5KEN1YXJ0b3MpICU+JSANCiAgICAgICAgc3VtbWFyaXNlKEZyZWN1ZW5jaWEgPSBuKCkpIA0KbnVtX2N1YXJ0b3MgPC0gZGF0YS5mcmFtZShudW1fY3VhcnRvcykNCg0KbnVtX2N1YXJ0b3MxIDwtIG51bV9jdWFydG9zWzE6OCxdDQpudW1fY3VhcnRvczEkQ3VhcnRvcyA8LSBhcy5jaGFyYWN0ZXIobnVtX2N1YXJ0b3MxJEN1YXJ0b3MpDQoNCiBhIDwtIG51bV9jdWFydG9zMSAlPiUgDQogICAgICAgIGdncGxvdChhZXMoeCA9IEN1YXJ0b3MsIHkgPSBGcmVjdWVuY2lhKSkgKyANCiAgICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC41LCBmaWxsID0gbWlzLmNvbG9yZXMuMyg4KSkgKw0KICAgICAgICB0aGVtZV9idygpICsgDQogICAgICAgIGdlb21fdGV4dChzaXplID0gMyxhZXMobGFiZWwgPSAgRnJlY3VlbmNpYSksIGNvbCA9ICIjNjk2OTY5IiwNCiAgICAgICAgICAgICAgICAgIHZqdXN0ID0gLTAuNSkgKyANCiAgICAgICAgZ2d0aXRsZSgiTsO6bWVybyBkZSBjdWFydG9zIikgDQoNCm51bV9kb3JtaXRvcmlvcyA8LSBkYXRvcyAlPiUgDQogICAgICAgIGdyb3VwX2J5KERvcm1pdG9yaW9zKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZShGcmVjdWVuY2lhID0gbigpKSANCm51bV9kb3JtaXRvcmlvcyA8LSBkYXRhLmZyYW1lKG51bV9kb3JtaXRvcmlvcykNCg0KbnVtX2Rvcm1pdG9yaW9zMSA8LSBudW1fZG9ybWl0b3Jpb3NbMTo4LF0NCm51bV9kb3JtaXRvcmlvczEkRG9ybWl0b3Jpb3MgPC0gYXMuY2hhcmFjdGVyKG51bV9kb3JtaXRvcmlvczEkRG9ybWl0b3Jpb3MpDQoNCmIgPC0gbnVtX2Rvcm1pdG9yaW9zMSAlPiUgDQogICAgICAgIGdncGxvdChhZXMoeCA9IERvcm1pdG9yaW9zLCB5ID0gRnJlY3VlbmNpYSkpICsgDQogICAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNSwgZmlsbCA9IG1pcy5jb2xvcmVzLjMoOCkpICsNCiAgICAgICAgdGhlbWVfYncoKSArIA0KICAgICAgICBnZW9tX3RleHQoc2l6ZSA9IDMsYWVzKGxhYmVsID0gIEZyZWN1ZW5jaWEpLCBjb2wgPSAiIzY5Njk2OSIsDQogICAgICAgICAgICAgICAgICB2anVzdCA9IC0wLjUpICsgDQogICAgICAgIGdndGl0bGUoIk7Dum1lcm8gZGUgRG9ybWl0b3Jpb3MiKSANCg0KbnVtX2lub2Rvcm9zIDwtIGRhdG9zICU+JSANCiAgICAgICAgZ3JvdXBfYnkoSW5vZG9yb3MpICU+JSANCiAgICAgICAgc3VtbWFyaXNlKEZyZWN1ZW5jaWEgPSBuKCkpIA0KbnVtX2lub2Rvcm9zIDwtIG51bV9pbm9kb3Jvcw0KDQpudW1faW5vZG9yb3MxIDwtIG51bV9pbm9kb3Jvc1sxOjgsXQ0KbnVtX2lub2Rvcm9zMSRJbm9kb3JvcyA8LSBhcy5jaGFyYWN0ZXIobnVtX2lub2Rvcm9zMSRJbm9kb3JvcykNCg0KYyA8LSBudW1faW5vZG9yb3MxICU+JSANCiAgICAgICAgZ2dwbG90KGFlcyh4ID0gSW5vZG9yb3MsIHkgPSBGcmVjdWVuY2lhKSkgKyANCiAgICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC41LCBmaWxsID0gbWlzLmNvbG9yZXMuMyg4KSkgKw0KICAgICAgICB0aGVtZV9idygpICsgDQogICAgICAgIGdlb21fdGV4dChzaXplID0gMyxhZXMobGFiZWwgPSAgRnJlY3VlbmNpYSksIGNvbCA9ICIjNjk2OTY5IiwNCiAgICAgICAgICAgICAgICAgIHZqdXN0ID0gLTAuNSkgKyANCiAgICAgICAgZ2d0aXRsZSgiTsO6bWVybyBkZSBJbm9kb3JvcyIpIA0KDQoNCm51bV9wZXJzb25hcyA8LSBkYXRvcyAlPiUgDQogICAgICAgIGdyb3VwX2J5KFBlcnNvbmFzKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZShGcmVjdWVuY2lhID0gbigpKSANCm51bV9wZXJzb25hcyA8LSBkYXRhLmZyYW1lKG51bV9wZXJzb25hcykNCg0KbnVtX3BlcnNvbmFzMSA8LSBudW1fcGVyc29uYXNbMTo4LF0NCm51bV9wZXJzb25hczEkUGVyc29uYXMgPC0gYXMuY2hhcmFjdGVyKG51bV9wZXJzb25hczEkUGVyc29uYXMpDQoNCmQgPC0gbnVtX3BlcnNvbmFzMSAlPiUgDQogICAgICAgIGdncGxvdChhZXMoeCA9IFBlcnNvbmFzLCB5ID0gRnJlY3VlbmNpYSkpICsgDQogICAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNSwgZmlsbCA9IG1pcy5jb2xvcmVzLjMoOCkpICsNCiAgICAgICAgdGhlbWVfYncoKSArIA0KICAgICAgICBnZW9tX3RleHQoc2l6ZSA9IDMsYWVzKGxhYmVsID0gIEZyZWN1ZW5jaWEpLCBjb2wgPSAiIzY5Njk2OSIsDQogICAgICAgICAgICAgICAgICB2anVzdCA9IC0wLjUpICsgDQogICAgICAgIGdndGl0bGUoIk7Dum1lcm8gZGUgUGVyc29uYXMiKSANCg0KZ3JpZC5hcnJhbmdlKGEsIGIsIG5yb3cgPSAxKQ0KZ3JpZC5hcnJhbmdlKGMsIGQsIG5yb3cgPSAxKQ0KDQpgYGANCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCB3YXJuaW5nPUZBTFNFLCBvdXQud2lkdGg9JzcwJSd9DQpudW1fZXN0cmF0byA8LSBkYXRvcyAlPiUgDQogICAgICAgIGdyb3VwX2J5KEVzdHJhdG8pICU+JSANCiAgICAgICAgc3VtbWFyaXNlKEZyZWN1ZW5jaWEgPSBuKCkpIA0KbnVtX2VzdHJhdG8gPC0gZGF0YS5mcmFtZShudW1fZXN0cmF0bykNCg0KbnVtX2VzdHJhdG8xIDwtIG51bV9lc3RyYXRvWzE6OCxdDQpudW1fZXN0cmF0bzEkRXN0cmF0byA8LSBhcy5jaGFyYWN0ZXIobnVtX2VzdHJhdG8xJEVzdHJhdG8pDQoNCm51bV9lc3RyYXRvMSAlPiUgDQogICAgICAgIGdncGxvdChhZXMoeCA9IEVzdHJhdG8sIHkgPSBGcmVjdWVuY2lhKSkgKyANCiAgICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC41LCBmaWxsID0gbWlzLmNvbG9yZXMuMyg4KSkgKw0KICAgICAgICB0aGVtZV9idygpICsgDQogICAgICAgIGdlb21fdGV4dChzaXplID0gMyxhZXMobGFiZWwgPSAgRnJlY3VlbmNpYSksIGNvbCA9ICIjNjk2OTY5IiwNCiAgICAgICAgICAgICAgICAgIHZqdXN0ID0gLTAuNSkgKyANCiAgICAgICAgZ2d0aXRsZSgiRXN0cmF0byBkZWwgaG9nYXIiKSANCg0KZGF0b3MgJT4lIA0KICBncm91cF9ieShUaXBvX3ZpdmllbmRhKSAlPiUgDQogIHN1bW1hcmlzZShGcmVjdWVuY2lhID0gbigpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IFRpcG9fdml2aWVuZGEsIHkgPSBGcmVjdWVuY2lhKSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC41LCBmaWxsID0gbWlzLmNvbG9yZXMuMyg1KSkgKw0KICB0aGVtZV9idygpICsgDQogICAgICAgIGdlb21fdGV4dChzaXplID0gMyxhZXMobGFiZWwgPSAgRnJlY3VlbmNpYSksIGNvbCA9ICIjNjk2OTY5IiwNCiAgICAgICAgICAgICAgICAgIHZqdXN0ID0gLTAuNSkgKyANCiAgZ2d0aXRsZSgiVGlwbyBkZSB2aXZpZW5kYSBkZSBsb3MgaG9nYXJlcyIpICsNCiAgbGFicyh4ID0gIiIpICsNCiAgY29vcmRfZmxpcCgpDQoNCmRhdG9zICU+JSANCiAgZ3JvdXBfYnkoUG9zZXNpb25fdml2aWVuZGEpICU+JSANCiAgc3VtbWFyaXNlKEZyZWN1ZW5jaWEgPSBuKCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gUG9zZXNpb25fdml2aWVuZGEsIHkgPSBGcmVjdWVuY2lhKSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC41LCBmaWxsID0gbWlzLmNvbG9yZXMuMyg2KSkgKw0KICB0aGVtZV9idygpICsgDQogICAgICAgIGdlb21fdGV4dChzaXplID0gMyxhZXMobGFiZWwgPSAgRnJlY3VlbmNpYSksIGNvbCA9ICIjNjk2OTY5IiwNCiAgICAgICAgICAgICAgICAgIHZqdXN0ID0gLTAuNSkgKyANCiAgZ2d0aXRsZSgiVGlwbyBkZSB2aXZpZW5kYSBkZSBsb3MgaG9nYXJlcyIpICsNCiAgbGFicyh4ID0gIiIpICsNCiAgY29vcmRfZmxpcCgpDQpgYGANCg0KKiBMYSBtYXlvcsOtYSBkZSBsb3MgaG9nYXJlcyBvY3VwYW4gdW4gZXNwYWNpbyBxdWUgdGllbmUgZW50cmUgMiB5IDUgY3VhcnRvcywgYXVucXVlIGh1Ym8gYXByb3hpbWFkYW1lbnRlIDUwIGhvZ2FyZXMgcXVlIHRlbsOtYW4gcmVnaXN0cm8gZGUgb2N1cGFjacOzbiBkZSBtw6FzIGRlIDEwIGN1YXJ0b3MuICANCg0KKiBFbCBuw7ptZXJvIGRlIGRvcm1pdG9yaW9zIGRlIHVuIGhvZ2FyIHB1ZWRlIGVzdGFyIGVudHJlIDEgeSA4LCBhdW5xdWUgbGEgbWF5b3LDrWEgZGUgbG9zIGhvZ2FyZXMgbm8gdGllbmVuIG3DoXMgZGUgMyBkb3JtaXRvcmlvczsgYWRlbcOhcywgZXMgZXNwZXJhYmxlIHF1ZSBlbCBuw7ptZXJvIGRlIGRvcm1pdG9yaW9zIGVzdMOpIGluY2x1aWRvIGVuIGVsIG7Dum1lcm8gZGUgY3VhcnRvcyBxdWUgb2N1cGEgZWwgaG9nYXIsIHBvciBsbyBxdWUgZWwgbsO6bWVybyBkZSBkb3JtaXRvcmlvcyBzaWVtcHJlIGVzIG1lbm9yIG8gaWd1YWwgYWwgbsO6bWVybyBkZSBjdWFydG9zIGRlbCBob2dhci4NCg0KKiBTZSBwdWVkZSBhcHJlY2lhciBxdWUgZ3JhbiBwYXJ0ZSBkZSBsb3MgaG9nYXJlcyB0aWVuZW4gZW50cmUgMSB5IDIgaW5vZG9yb3MuDQoNCiogTG9zIGhvZ2FyZXMgY29sb21iaWFub3MgdGVuZGVuIGVuIHN1IG1heW9yw61hIGEgZXN0YXIgY29tcHVlc3RvcyBwb3IgdW5hIGNhbnRpZGFkIGRlIHBlcnNvbmFzIGVudHJlIDEgeSA3LCBhdW5xdWUgc2UgZW5jb250cmFyb24gdW5vcyBwb2NvcyBob2dhcmVzIGVuIGRvbmRlIGVsIG7Dum1lcm8gZGUgcGVyc29uYXMgcG9kw61hIGxsZWdhciBhIHNlciBlbnRyZSAxMCB5IDE5LiANCg0KKiBMYSBtYXlvcsOtYSBkZSBsb3MgaG9nYXJlcyBjb2xvbWJpYW5vcyBzb24gZXN0cmF0byAxLCAyIG8gMywgYXVucXVlIGhheSByZWdpc3RybyBkZSBjYXNpIDQwMDAgaG9nYXJlcyBjb2xvbWJpYW5vcyBlbiBkb25kZSBubyB0aWVuZW4gZXN0cmF0aWZpY2FjacOzbiBvIGVsIGFjY2VzbyBhIHNlcnZpY2lvcyBww7pibGljb3MgZXMgcGlyYXRlYWRvLCBsb3MgY3VhbGVzIGNvcnJlc3BvbmRlbiBhIHZhbG9yZXMgZGUgMCB2aXNpYmxlcyBlbiBlbCBncsOhZmljby4NCg0KKiBMYSBtYXlvcsOtYSBkZSBsb3MgaG9nYXJlcyBjb2xvbWJpYW5vcyByZWdpc3RyYWRvcyB2aXZlbiBlbiBjYXNhcyBvIGFwYXJ0YW1lbnRvcywgYXVucXVlIGhheSBjYXNvcyBlbiBsb3MgY3VhbGVzIG9jdXBhbiB1biBzb2xvIGN1YXJ0byBvIHVub3MgcG9jb3MgY3VhcnRvcyBkZSBsYSB2aXZpZWRhLCB1bmEgdml2aWVuZGEgdHJhZGljaW9uYWwgaW5kw61nZW5hLCB1IG90cm8gdGlwbyBkZSB2aXZpZW5kYSB0YWxlcyBjb21vIGNhcnBhcywgY29udGVuZWRvcmVzLCB2YWdvbmVzLCBlbnRyZSBvdHJvcy4NCg0KKiBMb3MgaG9nYXJlcyBjb2xvbWJpYW5vcyB0aWVuZGVuIGVuIHN1IG1heW9yw61hIHZpdmllbmRhIHByb3BpYSwgYXVucXVlIHRhbWJpw6luIGhheSBiYXN0YW50ZXMgcmVnaXN0cm9zIGRlIGhvZ2FyZXMgcXVlIGhhbiB1c3VmcnVjdHVhZG8gdW4gc2l0aW87IHRhbWJpw6luIGVzIGFwcmVjaWFibGUgdW5hIHBvY2EgY2FudGlkYWQgZGUgaG9nYXJlcyBxdWUgY29tcGFydGUgdml2aWVuZGEsIHlhIHNlYSBjb21vIHByb3BpZWRhZCBjb2xlY3RpdmEgbyBjb24gbGEgbW9kYWxpZGFkIGRlIHByb3BpYSBwYXJjaWFsbWVudGUuDQoNCiogUGFyYSBsYSB2YXJpYWJsZSBjb2NpbmEsIHNlIGVuY29udHLDsyBxdWUgdG9kb3MgbG9zIGhvZ2FyZXMgY29sb21iaWFub3MgdG9tYWRvcyBlbiBsYSBtdWVzdHJhIHBvc2VlbiBjb2NpbmEsIHBvciBsbyBxdWUgYWwgbm8gYnJpbmRhciBpbmZvcm1hY2nDs24gcmVsZXZhbnRlLCBlc3RhIHZhcmlhYmxlIGZ1ZSBkZXNjYXJ0YWRhIHBhcmEgZWwgcmVzdG8gZGVsIGFuw6FsaXNpcy4NCg0KIyMgQW7DoWxpc2lzIGRlIHJlbGFjaW9uZXMgZW50cmUgdmFyaWFibGVzDQoNCkEgY29udGludWFjacOzbiBzZSBjb25zaWRlcmEgbGEgbWF0cml6IGRlIGNvcnJlbGFjacOzbiBwYXJhIHZhcmlhYmxlcyBudW3DqXJpY2FzLCB1dGlsaXphbmRvIGVsIGNvZWZpY2llbnRlIGRlIGNvcnJlbGFjacOzbiBkZSBTcGVhcm1hbiBxdWUgcGVybWl0ZSBhbmFsaXphciBlbCBncmFkbyBkZSBhc29jaWFjacOzbiBlbnRyZSB2YXJpYWJsZXMgbnVtw6lyaWNhcywgeWEgc2VhbiBkZSB0aXBvIGRpc2NyZXRvIG8gY29udGludW86IA0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIHdhcm5pbmc9RkFMU0UsIG91dC53aWR0aD0nODAlJ30NCm1pcy5jb2xvcmVzLjQgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCIjOTlmZjk5IiwgIiM5OTk5ZmYiLCAiI2ZmOTk5OSIpKQ0KbnVtZXJpY2FzIDwtIGRhdG9zICU+JSAgc2VsZWN0KGhpam9zLCBDdWFydG9zLCBEb3JtaXRvcmlvcywgSW5vZG9yb3MsIEluZ3Jlc28sIEluZ3Jlc29fcGVyY2FwaXRhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdXBlcmZpY2llLCBFc3RyYXRvLCBBcnJpZW5kbykNCmNvcl9tYXRyaXggPC0gcm91bmQoY29yKG51bWVyaWNhcywgbWV0aG9kID0gInNwZWFybWFuIiksIDIpDQoNCmNvcnJwbG90KGNvcl9tYXRyaXgsIG1ldGhvZCA9ICAic2hhZGUiLCBzaGFkZS5jb2wgPSBOQSwgdGwuY29sID0gImJsYWNrIiwgdGwuc3J0ID0gNDUsIA0KICAgICAgICAgYWRkQ29lZi5jb2wgPSAiYmxhY2siLCBjb2wgPSBtaXMuY29sb3Jlcy40KDIwMCksIHR5cGUgPSAidXBwZXIiKQ0KYGBgDQoNCkVzIHBvc2libGUgYXByZWNpYXIgY29ycmVsYWNpb25lcyBhbHRhcyBlbnRyZSBlbCB2YWxvciBkZWwgaW5ncmVzbywgY29uIGVsIHZhbG9yIGRlbCBpbmdyZXNvIHBlcmNhcGl0YSBlbiBlbCBob2dhciB5IGVudHJlIGVsIG7Dum1lcm8gZGUgY3VhcnRvcyBjb24gZWwgbsO6bWVybyBkZSBkb3JtaXRvcmlvcywgcG9yIGxvIHF1ZSBzZXLDrWEgdmlhYmxlIGNvbnNpZGVyYXIgc29sbyB1bmEgZGUgbGFzIGRvcyB2YXJpYWJsZXMgcXVlIHByZXNlbnRhbiBhbHRhIGNvcnJlbGFjacOzbiBlbnRyZSBzw60gZW4gbGEgY29uc3RydWNjacOzbiBkZSB1biBtb2RlbG8uIFNlZ8O6biBlc3RvLCBsYXMgdmFyaWFibGVzIEluZ3Jlc28gcGVyY2FwaXRhIHkgbsO6bWVybyBkZSBkb3JtaXRvcmlvcywgbm8gc2Vyw6FuIGNvbnNpZGVyYWRhcyBlbiBlbCBhanVzdGUgZGUgbW9kZWxvcy4gU29uIGFwcmVjaWFibGVzIHRhbWJpw6luIGFsZ3VuYXMgY29ycmVsYWNpb25lcyBwb3NpdGl2YXMgbWF5b3JlcyBhIDAuMyBlbiBlbCBjb25qdW50byBkZSBkYXRvcy4NCg0KUGFyYSB2ZXIgbGEgcmVsYWNpw7NuIGVudHJlIHZhcmlhYmxlcyBudW3DqXJpY2FzIHkgZWwgbsO6bWVybyBkZSBoaWpvcyBkZWwgaG9nYXIsIHNlIGNvbnNpZGVyYW4gbG9zIHNpZ3VpZW50ZXMgZ3LDoWZpY29zIGJveHBsb3Q6IA0KDQpgYGB7cn0NCnJlcXVpcmUoZ2dwbG90MikNCg0KYSA8LSBkYXRvcyAlPiUgDQogIGdncGxvdChhZXMoeCA9IGFzLmZhY3RvcihoaWpvcykseSA9IEluZ3Jlc28pKSArIA0KICBnZW9tX2JveHBsb3QoKSArIA0KICB0aGVtZV9idygpICsgDQogIGdndGl0bGUoIkhpam9zIHZzLiBJbmdyZXNvIikgKyANCiAgbGFicyh4ID0gIkhpam9zIikNCg0KYiA8LSBkYXRvcyAlPiUgDQogIGdncGxvdChhZXMoeCA9IGFzLmZhY3RvcihoaWpvcykseSA9IEFycmllbmRvKSkgKyANCiAgZ2VvbV9ib3hwbG90KCkgKyANCiAgdGhlbWVfYncoKSArIA0KICBnZ3RpdGxlKCJIaWpvcyB2cy4gQXJyaWVuZG8iKSArIA0KICBsYWJzKHggPSAiSGlqb3MiKQ0KDQpjIDwtIGRhdG9zICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gYXMuZmFjdG9yKGhpam9zKSx5ID0gU3VwZXJmaWNpZSkpICsgDQogIGdlb21fYm94cGxvdCgpICsgDQogIHRoZW1lX2J3KCkgKyAgDQogIGdndGl0bGUoIkhpam9zIHZzLiBTdXBlcmZpY2llIikgKyANCiAgbGFicyh4ID0gIkhpam9zIikNCg0KZ3JpZC5hcnJhbmdlKGEsYixjLCBuY29sID0gMykNCmBgYA0KDQoNCkF1bnF1ZSBubyBzZSBvYnNlcnZhbiBkaWZlcmVuY2lhcyBzaWduaWZpY2F0aXZhcyBlbnRyZSBlbCBuw7ptZXJvIGRlIGhpam9zIGRlbCBob2dhciBkZSBhY3VlcmRvIGFsIEluZ3Jlc28gbyBlbCBBcnJpZW5kbyBxdWUgcGFnYW4sIHNlIGFwcmVjaWEgZ3JhIGNhbnRpZGFkIGRlIHZhbG9yZXMgYXTDrXBpY29zLiBBZGVtw6FzLCBzZSBvYnNlcnZhbiBkaWZlcmVuY2lhcyBwYXJhIGVsIG7Dum1lcm8gZGUgaGlqb3MgZGVsIGhvZ2FyIGRlIGFjdWVkbyBhIGxhIHN1cGVyZmljaWUgZW4gJGttXjIkIGRlIGxhIHJlZ2nDs24gZW4gbGEgcXVlIGVzdMOhIHViaWNhZG8uDQoNCiMgTW9kZWxvcyBhIGNvbnNpZGVyYXIgey50YWJzZXR9DQoNClBhcmEgZWwgYWp1c3RlIGRlIGxvcyBtb2RlbG9zIHNlIHRpZW5lIHByZXNlbnRlcyBsYXMgc2lndWllbnRlcyBjb25zaWRlcmFjaW9uZXM6DQoNCiogU2UgZGVub3RhIGNvbW8gJHlfe2lqfSQgZWwgbsO6bWVybyBkZSBoaWpvcyBkZWwgaG9nYXIgaiBlbiBsYSByZWdpw7NuIGkgZGUgY29sb21iaWEsIGVsIGN1YWwgc2Vyw6EgbW9kZWxhZG8gcG9yIG1lZGlvIGRlIHVuYSByZWdyZXNpw7NuIFBvaXNzb246IA0KDQokJHlfe2lqfSBcc2ltIFBvaXNzb24oXGxhbWJkYV97aWp9KSQkDQoNCkxhIHJlZ3Jlc2nDs24gdGVuZHLDoSBlbiBjdWVudGEgc29sbyBhbGd1bmFzIGRlIGxhcyB2YXJpYWJsZXMgYW5hbGl6YWRhcyBjb24gYW50ZXJpb3JpZGFkLCBsYXMgY3VhbGVzIHJlcHJlc2VudGFuIGluZm9ybWFjacOzbiBkZSBsb3MgaG9nYXJlcywgbyBkZSBsYSByZWdpw7NuIGVuIGxhIGN1YWwgZXN0w6FuIHViaWNhZG9zLg0KDQojIyBNb2RlbG8gMQ0KDQpNb2RlbG8gbGluZWFsIGdlbmVyYWxpemFkbyBkZSBkaXN0cmlidWNpw7NuIFBvaXNzb24gZSBpbnRlcmNlcHRvIGFsZWF0b3JpbywgY29uIHZhcmlhYmxlIHByZWRpY3RvcmEgSW5ncmVzbyBkZWwgaG9nYXIuIA0KDQokJFxsYW1iZGFfe2lqfSA9IFxiZXRhXzAgKyBcYmV0YV8xSW5ncmVzb197aWp9ICsgYl97MGl9JCQNCg0KJCRiXzAgXHNpbSBOKDAsIFxzaWdtYV4yX3tiMH0pJCQNCg0KIyMgTW9kZWxvIDIgDQoNCk1vZGVsbyBsaW5lYWwgZ2VuZXJhbGl6YWRvIGRlIGRpc3RyaWJ1Y2nDs24gUG9pc3NvbiBlIGludGVyY2VwdG8gYWxlYXRvcmlvLCB0b21hbmRvIGNvbW8gdmFyaWFibGVzIHByZWRpY3RvcmFzIEluZ3Jlc28gZGVsIGhvZ2FyIHkgVGlwbyBkZSB2aXZpZW5kYS4NCg0KJCRcbGFtYmRhX3tpan0gPSBcYmV0YV8wICsgXGJldGFfMUluZ3Jlc29fe2lqfSArIFxiZXRhXzJBcGFydGFtZW50b197aWp9ICsgXGJldGFfM0Nhc2Ffe2lqfSArIFxiZXRhXzRDdWFydG9fe2lqfSArIFxiZXRhXzVPdHJvX3tpan0gKyAgYl97MGl9JCQNCg0KJCRiXzAgXHNpbSBOKDAsIFxzaWdtYV4yX3tiMH0pJCQNCg0KIyMgTW9kZWxvIDMgIA0KDQpNb2RlbG8gbGluZWFsIGdlbmVyYWxpemFkbyBkZSBkaXN0cmlidWNpw7NuIFBvaXNzb24sIGNvbiBpbnRlcmNlcHRvIHkgcGVuZGllbnRlIGFsZWF0b3Jpb3MsIHRvbWFuZG8gY29tbyB2YXJpYWJsZXMgcHJlZGljdG9yYXMgSW5ncmVzbyBkZWwgaG9nYXIgeSBUaXBvIGRlIHZpdmllbmRhLg0KDQokJFxsYW1iZGFfe2lqfSA9IFxiZXRhXzAgKyBcYmV0YV8xSW5ncmVzb197aWp9ICsgXGJldGFfMkFwYXJ0YW1lbnRvX3tpan0gKyBcYmV0YV8zQ2FzYV97aWp9ICsgXGJldGFfNEN1YXJ0b197aWp9ICsgXGJldGFfNU90cm9fe2lqfSArICBiX3swaX0gKyBiX3sxfVJlZ2lvbl97aWp9JCQNCg0KJCRYID0gXGJlZ2lue3BtYXRyaXh9Yl8wXFwNCmJfMQ0KXGVuZHtwbWF0cml4fSBcc2ltIE4gXGxlZnRbIFxiZWdpbntwbWF0cml4fTBcXA0KMA0KXGVuZHtwbWF0cml4fSwgXGJlZ2lue2JtYXRyaXh9XHNpZ21hX3tiMH1eMiAmIFxzaWdtYV97YjAxfV4yXFwNClxzaWdtYV97YjAxfV4yICYgXHNpZ21hX3tiMX1eMg0KXGVuZHtibWF0cml4fVxyaWdodF0kJA0KDQojIENvbnN0cnVjY2nDs24gZGUgbW9kZWxvcyANCg0KTG9zIG1vZGVsb3MgYW50ZXJpb3JtZW50ZSBjb25zaWRlcmFkb3MgZnVlcm9uIGFqdXN0YWRvcyBwb3IgbWVkaW8gZGUgbGEgZnVuY2nDs24gIGBnbG1lcigpYCBkZWwgcGFxdWV0ZSBgbG1lNGAsIG5vIHNpbiBhbnRlcyBjb25zaWRlcmFyIGxhcyByZXNwZWN0aXZhcyB0cmFuc2Zvcm1hY2lvbmVzIHkgcmVlc2NhbGFtaWVudG8gZGUgdmFyaWFibGVzLg0KDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpkYXRvcyRJbmdyZXNvIDwtIHNjYWxlKGRhdG9zJEluZ3Jlc28pDQpkYXRvcyRTdXBlcmZpY2llIDwtIHNjYWxlKGRhdG9zJFN1cGVyZmljaWUpDQpkYXRvcyRBcnJpZW5kbyA8LSBzY2FsZShkYXRvcyRBcnJpZW5kbykNCmRhdG9zJFRpcG9fdml2aWVuZGEgPC0gYXMuZmFjdG9yKGRhdG9zJFRpcG9fdml2aWVuZGEpDQpkYXRvcyRUaXBvX3ZpdmllbmRhIDwtIHJlbGV2ZWwoZGF0b3MkVGlwb192aXZpZW5kYSwgIlZpdmllbmRhIEluZMOtZ2VuYSIpDQpkYXRvcyRFc3RyYXRvIDwtIGFzLmZhY3RvcihkYXRvcyRFc3RyYXRvKQ0KDQojIE1vZGVsbyAxDQpmaXQxIDwtIGdsbWVyKGhpam9zIH4gSW5ncmVzbyArICgxIHwgUmVnaW9uKSwNCiAgICAgICAgICAgICAgZGF0YSA9IGRhdG9zLA0KICAgICAgICAgICAgICBmYW1pbHkgPSBwb2lzc29uKGxpbmsgPSAibG9nIikpDQoNCiMgTW9kZWxvIDINCmZpdDIgPC0gZ2xtZXIoaGlqb3MgfiBJbmdyZXNvICsgVGlwb192aXZpZW5kYSArICgxIHwgUmVnaW9uKSwNCiAgICAgICAgICAgICAgZGF0YSA9IGRhdG9zLA0KICAgICAgICAgICAgICBmYW1pbHkgPSBwb2lzc29uKGxpbmsgPSAibG9nIikpDQoNCiMgTW9kZWxvIDMNCmZpdDMgPC0gZ2xtZXIoaGlqb3MgfiBJbmdyZXNvICsgVGlwb192aXZpZW5kYSArICgxICsgU3VwZXJmaWNpZSB8IFJlZ2lvbiksDQogICAgICAgICAgICAgIGRhdGEgPSBkYXRvcywNCiAgICAgICAgICAgICAgZmFtaWx5ID0gcG9pc3NvbihsaW5rID0gImxvZyIpKQ0KDQojIEd1YXJkYWRvIGRlIGxvcyBtb2RlbG9zDQpzYXZlKGZpdDEsIGZpdDIsIGZpdDMsIGZpbGUgPSAiTW9kZWxvcy5SRGF0YSIpDQpgYGANCg0KIyBDb21wYXJhY2nDs24gZGUgbW9kZWxvcyB7LnRhYnNldH0NCg0KRW4gZXN0YSBzZWNjacOzbiBzZSBlbGVnaXLDoSB1bm8gZGUgbG9zIG1vZGVsb3MgbW9zdHJhZG9zIGNvbiBhbnRlcmlvcmlkYWQsIHBvciBtZWRpbyBkZSBsYSBwdWVyYmEgZGUgcmF6w7NuIGRlIHZlcm9zaW1pbGl0dWQuIEEgY29udGludWFjacOzbiBzZSBwcmVzZW50YSBlbCB2ZWN0b3IgZGUgcGFyw6FtZXRyb3MgZXN0aW1hZG9zIHBhcmEgY2FkYSB1bm8gZGUgbG9zIG1vZGVsb3M6DQoNCiMjIE1vZGVsbyAxDQoNCiQkXFRoZXRhXzEgPSAoXGJldGFfMCwgXGJldGFfMSwgXHNpZ21hX3tiXzB9KV5UJCQgIA0KDQokJFxoYXR7XFRoZXRhXzF9ID0gKDAuMDMzNjQ2LCAwLjAyNDcyNiwgMC4xNDY2KV5UJCQNCg0KIyMgTW9kZWxvIDINCg0KJCRcVGhldGFfMiA9IChcYmV0YV8wLCBcYmV0YV8xLCBcYmV0YV8yLCBcYmV0YV8zLCBcYmV0YV80LCBcYmV0YV81LCBcc2lnbWFfe2JfMH0pXlQkJCAgDQoNCiQkXGhhdHtcVGhldGFfMn0gPSAoMC40OTk0MTYsIDAuMDI4MDE4LCAtMC41NjQ1NDgsIC0wLjQxNTM0MiwgLTEuMDI1ODk1LCAtMC41ODc5ODYsIDAuMTIzNCleVCQkDQoNCiMjIE1vZGVsbyAzDQoNCiQkXFRoZXRhXzMgPSAoXGJldGFfMCwgXGJldGFfMSwgXGJldGFfMiwgXGJldGFfMywgXGJldGFfNCwgXGJldGFfNSwgXHNpZ21hX3tiXzB9LCBcc2lnbWFfe2JfMX0sIFxzaWdtYV97Yl97MDF9fSleVCQkICANCg0KJCRcaGF0e1xUaGV0YV8zfSA9ICgwLjQ5OTQxNiwgMC4wMjgwMTgsIC0wLjU2NDU0OCwgLTAuNDE1MzQyLCAtMS4wMjU4OTUsIC0wLjU4Nzk4NiwgMC4xMjM0LCAwLjExNTk2LCAwLjA1NDI2KV5UJCQNCkxhIHBydWViYSBkZSByYXrDs24gZGUgdmVyb3NpbWlsaXR1ZCBzZSBwbGFudGVhIGRlIGxhIHNpZ3VpZW50ZSBtYW5lcmE6DQoNCkFsIGNvbnNpZGVyYXIgZG9zIG1vZGVsb3MgJGZpdF94JCB5ICRmaXRfeSQgY29uIHZlY3RvcmVzIGRlIHBhcsOhbWV0cm9zIGVzdGltYWRvcyAkXFRoZXRhX3gkLCANCiRcVGhldGFfeSQgcmVzcGVjdGl2YW1lbnRlLCB0YWxlcyBxdWUgJFxUaGV0YV94IFxzdWJzZXQgXFRoZXRhX3kkLCBzaWVuZG8gJFxUaGV0YV5jX3AkIGFxdWVsbG9zIHBhcsOhbWV0cm9zIHF1ZSBlc3TDoW4gZW4gJGZpdF95JCB5IG5vIGVuICRmaXRfeCQuIExhIHBydWViYSBkZSBnaXDDs3Rlc2lzIGFzb2NpYWRhIGEgbGEgc2lnbmlmaWNhY2lhIGRlIGVzdGUgdmVjdG9yIGRlIHBhcsOhbWV0cm9zIHNlcsOhOiAgDQoNCiQkSF8wOiBcVGhldGFeYyA9IDBfezFcdGltZXMgcH0gXHF1YWQgdi5zIFxxdWFkIEhfMTogXFRoZXRhXmMgXG5vdD0gMF97MVx0aW1lcyBwfSQkDQoNCkRvbmRlIGVsIGVzdGFkw61zdGljbyBkZSBwcnVlYmEgZXN0w6EgZGFkbyBwb3I6IA0KDQokJExSID0gLTIgXHRpbWVzIChsb2dsaWtlbGlob29kKGZpdF94KS0gbG9nbGlrZWxpaG9vZChmaXRfeSkpJCQNClBhcmEgdW4gbml2ZWwgZGUgc2lnbmlmaWNhbmNpYSAkXGFscGhhJCwgc2UgcmVjaGF6YSAkSF8wJCBzaSAkVlAgPVAoXGNoaV4yX3AgPiBMUikgPCBcYWxwaGEkLg0KDQpBIGNvbnRpbnVhY2nDs24gc2UgcHJlc2VudGFuIGxhcyBjb21wYXJhY2lvbmVzIGVudHJlIG1vZGVsb3MsIGhlY2hhcyBwb3IgbWVkaW8gZGUgbGEgZnVuY2nDs24gYGFub3ZhKClgLg0KDQojIEFqdXN0ZSBkZSBsYSBwcnVlYmEgZGUgcmF6w7NuIGRlIHZlcm9zaW1pbGl0dWQgey50YWJzZXR9DQoNCiMjIE1vZGVsb3MgMSB5IDINCg0KYGBge3J9DQpsb2FkKCJDOi9Vc2Vycy9BU1VTL0Rlc2t0b3AvYS9zZW1pbmFyaW8vTW9kZWxvcy5SRGF0YSIpDQoNCmFub3ZhKGZpdDEsIGZpdDIpDQpgYGANCg0KIyMgTW9kZWxvcyAxIHkgMw0KDQpgYGB7cn0NCmFub3ZhKGZpdDEsIGZpdDMpDQpgYGANCg0KIyMgTW9kZWxvcyAyIHkgwr8zDQoNCmBgYHtyfQ0KYW5vdmEoZml0MiwgZml0MykNCmBgYA0KDQpMb3MgcmVzdWx0YWRvcyBkZSBsYSBwcnVlYmEgbXVlc3RyYW4gcXVlIGxhIGluY2x1c2nDs24gZGVsIHRpcG8gZGUgdml2aWVuZGEgZXMgc2lnbmlmaWNhdGl2YSBlbiBlbCBtb2RlbG8sIHBlcm8gbGEgaW5jbHVzacOzbiBkZSB1biBudWV2byB0w6lybWlubyBwYXJhIGxhIHBlbmRpZW50ZSBhbGVhdG9yaWEgcG9yIGVsIGNvbnRyYXRpbyBubyByZXByZXNlbnRhIHVuYSBtZWpvcsOtYSBlbiBlbCBhanVzdGUsIHBvciBsbyBxdWUgc2UgaGFyw6FuIGRpYWduw7NzdGljb3Mgc29icmUgZWwgbW9kZWxvIDIuDQoNCiMgQW7DoWxpc2lzIGRlIHJlc2lkdWFsZXMgIHsudGFic2V0fQ0KDQojIyBNb2RlbG8gMQ0KDQpgYGB7cn0NCnBhcihtZnJvdyA9IGMgKDEsMikpDQpwbG90KGZpdHRlZChmaXQxKSB+IGRhdG9zJGhpam9zLCB5bGltID0gYygwLDQpLCBwY2ggPSAxOSwgY29sID0gImxpZ2h0c3RlZWxibHVlMyIsDQogICAgIHhsYWIgPSAiVmFsb3JlcyByZWFsZXMiLCB5bGFiID0gIlZhbG9yZXMgQWp1c3RhZG9zIikNCmdyaWQoKQ0KDQoNCnFxbm9ybShyZXNpZHVhbHMoZml0MSksIGNvbCA9ICJsaWdodHN0ZWVsYmx1ZTMiKQ0KcXFsaW5lKHJlc2lkdWFscyhmaXQxKSkNCmBgYA0KDQojIyBNb2RlbG8gMg0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFfQ0KcGFyKG1mcm93ID0gYyAoMSwyKSkNCnBsb3QoZml0dGVkKGZpdDIpIH4gZGF0b3MkaGlqb3MsIHlsaW0gPSBjKDAsNCksIHBjaCA9IDE5LCBjb2wgPSAibGlnaHRzdGVlbGJsdWUzIiwNCiAgICAgeGxhYiA9ICJWYWxvcmVzIHJlYWxlcyIsIHlsYWIgPSAiVmFsb3JlcyBBanVzdGFkb3MiKQ0KZ3JpZCgpDQoNCg0KcXFub3JtKHJlc2lkdWFscyhmaXQyKSwgY29sID0gImxpZ2h0c3RlZWxibHVlMyIpDQpxcWxpbmUocmVzaWR1YWxzKGZpdDIpKQ0KYGBgDQoNCg0KIyMgTW9kZWxvIDMNCg0KYGBge3J9DQpwYXIobWZyb3cgPSBjICgxLDIpKQ0KcGxvdChmaXR0ZWQoZml0MykgfiBkYXRvcyRoaWpvcywgeWxpbSA9IGMoMCw0KSwgcGNoID0gMTksIGNvbCA9ICJsaWdodHN0ZWVsYmx1ZTMiLA0KICAgICB4bGFiID0gIlZhbG9yZXMgcmVhbGVzIiwgeWxhYiA9ICJWYWxvcmVzIEFqdXN0YWRvcyIpDQpncmlkKCkNCg0KDQpxcW5vcm0ocmVzaWR1YWxzKGZpdDMpLCBjb2wgPSAibGlnaHRzdGVlbGJsdWUzIikNCnFxbGluZShyZXNpZHVhbHMoZml0MykpDQpgYGANCg0KDQoNCg0KRWwgbW9kZWxvIHBhcmVjZSBwcmVzZW50YXIgcHJvYmxlbWFzIGRlIGhvbW9nZW5laWRhZCBkZSB2YXJpYW56YSwgYXPDrSBjb21vIHRhbWJpw6luIHVuIGluY3VtcGxpbWllbnRvIGFsIHN1cHVlc3RvIGRlIG5vcm1hbGlkYWQgZGUgbG9zIGVycm9yZXMsIGF1bnF1ZSBwYXJhIGVsIG1vZGVsbyAyLCBlbCBjdWFsIGVzIGNhbmRpZGF0byBhIHNlciBlbCBtZWpvciBtb2RlbG8gbm8gcGFyZWNlIHRlbmVyIHByb2JsZW1hcyB0YW4gZnVlcnRlcyBkZSBob21vZ2VuZWlkYWQgZGUgdmFyaWFuemEuIEVsIHByb2JsZW1hIGRlIG5vcm1hbGlkYWQgZGUgdmFyaWFuemEsIGRlYmlkbyBhIHByb2JsZW1hcyBkZSBjb3N0byBjb21wdXRhY2lvbmFsLCBzZSBkZWphIGNvbW8gdW5hIHByb3B1ZXN0YSBkZSBtZWpvciBhbCBlc3R1ZGlvLg0KDQojIFByZXNlbnRhY2nDs24gZGVsIG1lam9yIG1vZGVsbw0KDQpEZSBhY3VlcmRvIGFsIGFuw6FsaXNpcyBwbGFudGVhZG8gY29uIGFudGVyaW9yaWRhZCwgZWwgbWVqb3IgbW9kZWxvIGVzIGVsICoqbW9kZWxvIGxpbmVhbCBnZW5lcmFsaXphZG8gZGUgZGlzdHJpYnVjacOzbiBQb2lzc29uIGUgaW50ZXJjZXB0byBhbGVhdG9yaW8sIHRvbWFuZG8gY29tbyB2YXJpYWJsZXMgcHJlZGljdG9yYXMgSW5ncmVzbyBkZWwgaG9nYXIgeSBUaXBvIGRlIHZpdmllbmRhKiogY3V5YSBlY3VhY2nDs24gdmllbmUgZGVmaW5pZGEgZGUgbGEgc2lndWllbnRlIG1hbmVyYTogDQoNClNlYSAkeV97aWp9JCBlbCBuw7ptZXJvIGRlIGhpam9zIGRlbCBob2dhciBqIGVuIGxhIHJlZ2nDs24gaSBkZSBjb2xvbWJpYSwgc2UgdGllbmUgcXVlOg0KDQokJHlfe2lqfSBcc2ltIFBvaXNzb24oXGxhbWJkYV97aWp9KSQkDQoNCiQkXGxhbWJkYV97aWp9ID0gXGJldGFfMCArIFxiZXRhXzFJbmdyZXNvX3tpan0gKyBcYmV0YV8yQXBhcnRhbWVudG9fe2lqfSArIFxiZXRhXzNDYXNhX3tpan0gKyBcYmV0YV80Q3VhcnRvX3tpan0gKyBcYmV0YV81T3Ryb197aWp9ICsgIGJfezBpfSQkDQoNCiQkYl8wIFxzaW0gTigwLCBcc2lnbWFeMl97YjB9KSQkDQoNCiMgQ29tZW50YXJpb3MgZ2VuZXJhbGVzDQoNCiogIExvcyBtb2RlbG9zIG1peHRvcyBwZXJtaXRpZXJvbiBlc3R1ZGlhciBlbCBuw7ptZXJvIGRlIGhpam9zIGRlIHVuIGhvZ2FyLCBlbiBmdW5jacOzbiBkZSB2YXJpYWJsZXMgcXVlIHJlcHJlc2VudGFiYW4gaW5mb3JtYWNpw7NuIGRlIGxhIHJlZ2nDs24gZW4gbGEgY3VhbCBzZSB1YmljYWJhIGVsIGhvZ2FyLCB5IG5vIHNvbG8gcG9yIG1lZGlvIGRlIGluZm9ybWFjacOzbiBkZWwgaG9nYXIgZXNwZWPDrWZpY2FtZW50ZSwgbG8gY3VhbCByZXByZXNlbnRhIHVuIG1ldG9kb2xvZ8OtYSBpbnRlcmVzYW50ZSBwYXJhIGxhIGFwbGljYWNpw7NuIGRlIG1vZGVsb3MgY29uIGVsIGZpbiBkZSBlc3RpbWFyIHVuIHBhcsOhbWV0cm8gZGUgaW50ZXLDqXMuDQoNCiogQXVucXVlIGxhIG1ldG9kb2xvZ8OtYSBkZSBhbsOhbGlzaXMgZGVzZGUgbGEgY29uc3RydWNjacOzbiBkZWwgY29uanVudG8gZGUgZGF0b3MgdG9tw7MgY2llcnRhIGluZm9ybWFjacOzbiBlbiBwYXJ0aWN1bGFyLCBlcyBwb3NpYmxlIHJlZXN0cnVjdHVyYXIgbG9zIGRhdG9zIGRlIGxhIGVuY3Vlc3RhIGNvbiBlbCBmaW4gZGUgY29uc2lkZXJhciBpbmZvcm1hY2nDs24gZGUgb3RyYSDDrW5kb2xlIHBhcmEgbGEgZXN0aW1hY2nDs24gZGVsIG7Dum1lcm8gZGUgaGlqb3MgZGUgdW4gaG9nYXIgY29sb21iaWFuby4NCg0KKiBBdW5xdWUgc2UgaW50ZW50w7MgYXBsaWNhciB0cmFuc2Zvcm1hY2lvbmVzIHBhcmEgY29ycmVnaXIgZWwgcHJvYmxlbWEgZGUgdmlvbGFjacOzbiBkZSBsb3Mgc3VwdWVzdG9zIGRlbCBtb2RlbG8sIGVsIHByb2JsZW1hIG5vIG1lam9yw7MgeSBnZW5lcsOzIHByb2JsZW1hcyBkZSBjb3N0byBjb21wdXRhY2lvbmFsLCBwb3IgbG8gcXVlIGJham8gbG9zIG1vZGVsb3MgY29uc2lkZXJhZG9zLCBlbCBtb2RlbG8gMiBzaWd1ZSBzaWVuZG8gZWwgbWVqb3IgY29uc2lkZXJhZG8gZW4gZWwgYW7DoWxpc2lzLg0KDQoqIEFsIHRvbWFyIG90cmFzIHZhcmlhYmxlcyBwcmVkaWN0b3JhcywgZWwgY29zdG8gY29tcHV0YWNpb25hbCBkZWwgYWp1c3RlIGZ1ZSBleGNlc2l2bywgbG8gY3VhbCBpbXBpZGnDsyBsYSBjb25zaWRlcmFjacOzbiBkZSBlc3RhcyBlbiBsYSBjb25zdHJ1Y2Npw7NuIHkgZXZhbHVhY2nDs24gZGUgbG9zIG1vZGVsb3MuDQoNCiogRGViaWRvIGEgcXVlIGxhIGFwbGljYWNpw7NuIGRlIHRyYW5zZm9ybWFjaW9uZXMgYWwgbW9kZWxvIDIgdGFtYmnDqW4gZ2VuZXLDsyBwcm9ibGVtYXMgY29tcHV0YWNpb25hbG1lbnRlIGhhYmxhbmRvLCBlc3RvIHNlIGRlamEgw7puaWNhbWVudGUgY29tbyBwcm9wdWVzdGEgZGUgbWVqb3JhIGEgbGEgbWV0b2RvbG9nw61hIGNvbnNpZGVyYWRhIGVuIGVsIGFuw6FsaXNpcy4NCg0KKiBFbCBhanVzdGUgeSBldmFsdWFjacOzbiBkZSBtb2RlbG9zIHRvbcOzIGVuIGN1ZW50YSBncmFuIHBhcnRlIGRlbCBtYXRlcmlhbCB2aXN0byBlbiBjbGFzZSwgYWRlbcOhcyBkZSBxdWUgdG9kb3MgbG9zIGFyY2hpdm9zIHJlZmVyZW50ZXMgYWwgZXN0dWRpbyBzZSBwdWVkZW4gY29uc3VsdGFyIGVuIGVsIHNpZ3VpZW50ZSBbbGlua10oaHR0cHM6Ly9naXRodWIuY29tL1N0ZXBobDk5L01vZGVsb3NKZXJhcnF1aWNvcy90cmVlL21haW4vU2VtaW5hcmlvKS4NCg0KIyBCaWJsaW9ncmFmw61hLCByZWZlcmVuY2lhcyB5IGd1w61hcw0KDQoqIEVzdGFkw61zdGljYSwgRC4gQS4gTi4gRS4gKDIwMTksIERlY2VtYmVyIDEzKS4gRW5jdWVzdGEgTmFjaW9uYWwgZGUgQ2FsaWRhZCBkZSBWaWRhIC0gRUNWLTogRGF0b3MgQWJpZXJ0b3MgQ29sb21iaWEuIEVuY3Vlc3RhIE5hY2lvbmFsIGRlIENhbGlkYWQgZGUgVmlkYSAtIEVDVi0gfCBEYXRvcyBBYmllcnRvcyBDb2xvbWJpYS4gUmV0cmlldmVkIEphbnVhcnkgMjIsIDIwMjIsIGZyb20gaHR0cHM6Ly93d3cuZGF0b3MuZ292LmNvL0VzdGFkLXN0aWNhcy1OYWNpb25hbGVzL0VuY3Vlc3RhLU5hY2lvbmFsLWRlLUNhbGlkYWQtZGUtVmlkYS1FQ1YtL216OXktM3g5ayAgIA0KDQoqIFNjcmliZC4gKG4uZC4pLiBFbmN1ZXN0YSBOYWNpb25hbCBkZSBDYWxpZGFkIGRlIFZpZGEgLSBFQ1YgMjAxOC4gU2NyaWJkLiBSZXRyaWV2ZWQgSmFudWFyeSAyMiwgMjAyMiwgZnJvbSBodHRwczovL2VzLnNjcmliZC5jb20vZG9jdW1lbnQvNDc2NTc4MjA2L0VuY3Vlc3RhLU5hY2lvbmFsLWRlLUNhbGlkYWQtZGUtVmlkYS1FQ1YtMjAxOC1wZGYgDQoNCiogV2lraW1lZGlhIEZvdW5kYXRpb24uICgyMDIwLCBGZWJydWFyeSA0KS4gUmVnacOzbiBPcmllbnRhbCBkZSBDb2xvbWJpYS4gV2lraXBlZGlhLiBSZXRyaWV2ZWQgSmFudWFyeSAyMiwgMjAyMiwgZnJvbSBodHRwczovL2VzLndpa2lwZWRpYS5vcmcvd2lraS9SZWdpJUMzJUIzbl9PcmllbnRhbF9kZV9Db2xvbWJpYSANCg0KKiBIZXJuw6FuZGV6LCBGLiwgJmFtcDsgTWF6bywgTS4gKDIwMjAsIE9jdG9iZXIgMzApLiBNb2RlbG9zIGRlIFJlZ3Jlc2nDs24gQ29uIFIuIGluZGV4LmtuaXQuIFJldHJpZXZlZCBKYW51YXJ5IDMxLCAyMDIyLCBmcm9tIGh0dHBzOi8vZmhlcm5hbmIuZ2l0aHViLmlvL2xpYnJvX3JlZ3Jlc2lvbi8gDQoNCiogQmFyYWphcywgRi4gSC4sICZhbXA7IE1hcnTDrW5leiwgSi4gTC4gTC4gKDIwMjIsIEphbnVhcnkgMjYpLiBNb2RlbG9zIE1peHRvcyBDb24gUi4gaW5kZXgua25pdC4gUmV0cmlldmVkIEphbnVhcnkgMzEsIDIwMjIsIGZyb20gaHR0cHM6Ly9maGVybmFuYi5naXRodWIuaW8vbGlicm9fbW9kZWxvc19taXh0b3MvDQoNCiogR2VsbWFuLCBBLiwgJmFtcDsgSGlsbCwgSi4gKDIwMDkpLiBEYXRhIGFuYWx5c2lzIHVzaW5nIHJlZ3Jlc3Npb24gYW5kIG11bHRpbGV2ZWwvaGllcmFyY2hpY2FsIG1vZGVscy4gQ2FtYnJpZGdlIFVuaXZlcnNpdHkgUHJlc3MuDQoNCiogUjogQSBMYW5ndWFnZSBhbmQgRW52aXJvbm1lbnQgZm9yIFN0YXRpc3RpY2FsIENvbXB1dGluZyxhdXRob3IgPSBSIENvcmUgVGVhbSwgb3JnYW5pemF0aW9uID0gUiBGb3VuZGF0aW9uIGZvciBTdGF0aXN0aWNhbCBDb21wdXRpbmcsYWRkcmVzcyA9IFZpZW5uYSwgQXVzdHJpYSwgeWVhciA9IDIwMjAsIHVybCA9IGh0dHBzOi8vd3d3LlItcHJvamVjdC5vcmcvDQoNCg0K