Los votos son contados correctamente
En esta sección se va a usar la variable COUNTFAIR1. Los votos son
contados correcta y justamente. ¿Diría usted que sucede siempre, algunas
veces o nunca? El gráfico 2.5 del reporte el Pulso de la Democracia,
disponible aquí,
presenta los resultados de esta variable por país.
De la misma manera que con las variables nominales, estas variables
tienen que ser declaradas como “factor” en nuevas variables.
library(haven)
lapop21$countfair1r = as.factor(lapop21$countfair1)
Luego, estas variables se tienen que etiquetar y generar las tablas
descriptivas básicas, con el comando table
.
levels(lapop21$countfair1r) = c("Siempre", "Algunas veces", "Nunca")
table(lapop21$countfair1r)
##
## Siempre Algunas veces Nunca
## 3477 5235 1698
Para calcular las tablas con porcentajes, redondeados a un decimal,
usamos prop.table
y round
. Nuevamente, estos
porcentajes no son exactamente iguales a los presentados en el reporte
debido a que estos cálculos no incluyen el factor de expansión.
round(prop.table(table(lapop21$countfair1r)), 3)*100
##
## Siempre Algunas veces Nunca
## 33.4 50.3 16.3
Como se mencionó en la sección anterior, se puede graficar esta
variable usando el comando barplot
.
barplot(prop.table(table(lapop21$countfair1r))*100)
Otra opción es elaborar el gráfico de barras usando la librería
ggplot
. Una primera opción es trabajar directamente de la
base de datos. Sin embargo, producir una tabla con los resultados desde
la base de datos y usar esa tabla para producir un gráfico es una manera
más intuitiva.
Se puede crear una tabla de frecuencias de esta variable con el
comando table
y prop.table
. Esta table se
redondea a un decimal con el comando round
y se guarda como
un dataframe con el comando as.data.frame
en un objeto
“count”. Esta tabla almacena dos columnas, la primera llamada “Var1” con
las etiquetas de la variable y la segunda llamada “Freq” con los
porcentajes.
count = as.data.frame(round(prop.table(table(lapop21$countfair1r)), 3)*100)
count
Podemos usar esta tabla “count” para producir el gráfico de barras
con el comando ggplot
. En la especificación
aes
se define que los valores de la columna “Var1” se
presenten en el eje X y los valores de la columna a “Freq” en el eje Y.
Se define un gráfico de barras simple, usando el comando
geom_bar()
, donde internamente se define el ancho de la
barra. Con la especificación labs
se define las etiquetas
de ejes y el “caption”.
ggplot(data=count, aes(x=Var1, y=Freq))+
geom_bar(stat="identity", width=0.5)+
geom_text(aes(label=paste(Freq, "%", sep="")), color="white",
position=position_stack(vjust=0.5), size=3)+
labs(x="Los votos se cuentan justamente", y="Porcentaje",
caption="Barómetro de las Américas por LAPOP, 2021")
El gráfico 2.5 presenta una barra apilada con los datos por cada
país. Primero presentaremos el gráfico de barras apilado usando los
datos de toda la ronda 2021 del Barómetro de las Américas, es decir de
todos los países. Para producir una barra apilada horizontal, se usará
la variable “Freq” ahora en el eje X. Se usará la opción
fill
para dividir esta barra por los valores de la variable
“Var1”. Como en el eje Y no se mostrará una variable se define como
""
. De la misma manera que se cambiaron las variables en
los ejes, también se cambian las etiquetas en labs
. En esta
especificación se cambia la etiqueta de la leyenda con
fill
.
ggplot(data=count, aes(fill=Var1, x=Freq, y=""))+
geom_bar(stat="identity", width=0.3)+
geom_text(aes(label=paste(Freq, "%", sep="")), color="white",
position=position_stack(vjust=0.5), size=3)+
labs(x="Porcentaje", y="", fill="Los votos se cuentan justamente",
caption="Barómetro de las Américas por LAPOP, 2021")
Para replicar el gráfico comparativo por país se requiere crear la
tabla de contingencia entre la variable “countfair” y “pais”. Esta tabla
cruzada se guarda en un objeto “count_pais”. Se debe notar que el
dataframe que se crea crea una fila por cada valor de “countfair” en
cada país. De esta manera tenemos 3 opciones x 20 países = 60 filas.
count_pais = as.data.frame(round(prop.table(table(lapop21$pais, lapop21$countfair1r), 1), 3)*100)
count_pais
En esta tabla se calculan los datos por cada valor de la variable
“pais”, incluso cuando no se tiene datos de la variable “countfair”,
debido a que la pregunta no se realizó en ese país. Por este motivo se
tienen que eliminar las filas de los países en los que no se recogió
esta información. Esto se hace con la especificación
[-c(filas),]
. Luego se crea un vector con los nombres de
los países. Esta lista se repite 3 veces (15 países restantes x 3
opciones). Este vector se agrega al dataframe en una columna “pais”.
count_pais = count_pais[-c(1:4,18,21:24,38,41:44,58),]
pais = c("Nicaragua","Costa Rica", "Panamá", "Colombia", "Ecuador", "Bolivia", "Perú",
"Paraguay", "Chile", "Uruguay", "Brasil", "Argentina", "Rep. Dom.","Jamaica", "Guyana", "Nicaragua","Costa Rica", "Panamá", "Colombia", "Ecuador", "Bolivia", "Perú",
"Paraguay", "Chile", "Uruguay", "Brasil", "Argentina", "Rep. Dom.","Jamaica", "Guyana","Nicaragua","Costa Rica", "Panamá", "Colombia", "Ecuador", "Bolivia", "Perú",
"Paraguay", "Chile", "Uruguay", "Brasil", "Argentina", "Rep. Dom.","Jamaica", "Guyana")
count_pais$pais = pais
count_pais
Con este dataframe “count_pais” ya tenemos los elementos para
replicar el gráfico de barras apiladas. En la especificación
aes
se define que en el eje X se grafiquen los porcentajes,
en el eje Y los países y cada barra se divida por la columna Var2.
ggplot(data=count_pais, aes(x=Freq, y=pais, fill=Var2))+
geom_bar(stat="identity", width=0.3)+
geom_text(aes(label=paste(Freq, "%", sep="")), color="white",
position=position_stack(vjust=0.5), size=2)+
labs(x="Porcentaje", y="País", fill="Los votos se cuentan justamente",
caption="Barómetro de las Américas por LAPOP, 2021")
Frecuencia de uso de redes sociales
En la ronda 2018/19 se evaluó el uso de redes sociales. De esta
manera, se analizaron las variables SMEDIA2. ¿Con qué frecuencia ve
contenido en Facebook?, SMEDIA5.¿Con qué frecuencia ve contenido en
Twitter? y SMEDIA8.¿Con qué frecuencia usa Whatsapp? Estas variables
tienen como opciones de respuesta:
- Diariamente
- Algunas veces a la semana
- Algunas veces al mes
- Algunas veces al año
- Nunca
De la misma manera que con las variables nominales, estas variables
tienen que ser declaradas como “factor” en nuevas variables.
lapop18$smedia2r = as.factor(lapop18$smedia2)
lapop18$smedia5r = as.factor(lapop18$smedia5)
lapop18$smedia8r = as.factor(lapop18$smedia8)
La nota a pie 15 del reporte indica que “los entrevistados que
reportan nunca ver contenido en Facebook y Twitter, y quienes indican
que nunca usan Whatsapp, son considerados como no usuarios de estas
redes sociales” (p. 64). Por este motivo, el gráfico 3.3 de frecuencia
de uso de redes sociales (pag. 57) solo incluyen las categorías
“Diariamente”, “Algunas veces a la semana”, “Algunas veces al mes” y
“Algunas veces al año”. Se excluya la categoría “Nunca”.
En las nuevas variables vamos a declarar el valor 5, correspondiente
a “nunca”, como “NA”, es decir, como valor perdido en R.
library(car)
lapop18$smedia2r = car::recode(lapop18$smedia2r, "5=NA")
lapop18$smedia5r = car::recode(lapop18$smedia5r, "5=NA")
lapop18$smedia8r = car::recode(lapop18$smedia8r, "5=NA")
Luego, estas variables se tienen que etiquetar y generar las tablas
descriptivas básicas, con el comando table
.
levels(lapop18$smedia2r) = c("Diariamente", "Algunas veces a la semana",
"Algunas veces al mes", "Algunas veces al año")
levels(lapop18$smedia5r) = c("Diariamente", "Algunas veces a la semana",
"Algunas veces al mes", "Algunas veces al año")
levels(lapop18$smedia8r) = c("Diariamente", "Algunas veces a la semana",
"Algunas veces al mes", "Algunas veces al año")
table(lapop18$smedia2r)
##
## Diariamente Algunas veces a la semana Algunas veces al mes
## 8633 4927 1286
## Algunas veces al año
## 282
table(lapop18$smedia5r)
##
## Diariamente Algunas veces a la semana Algunas veces al mes
## 795 728 422
## Algunas veces al año
## 193
table(lapop18$smedia8r)
##
## Diariamente Algunas veces a la semana Algunas veces al mes
## 14151 2646 495
## Algunas veces al año
## 50
Para calcular las tablas con porcentajes, redondeados a un decimal,
usamos prop.table
y round
. Nuevamente, estos
porcentajes no son exactamente iguales a los presentados en el reporte
debido a que estos cálculos no incluyen el factor de expansión.
round(prop.table(table(lapop18$smedia2r)), 3)*100
##
## Diariamente Algunas veces a la semana Algunas veces al mes
## 57.1 32.6 8.5
## Algunas veces al año
## 1.9
round(prop.table(table(lapop18$smedia5r)), 3)*100
##
## Diariamente Algunas veces a la semana Algunas veces al mes
## 37.2 34.1 19.7
## Algunas veces al año
## 9.0
round(prop.table(table(lapop18$smedia8r)), 3)*100
##
## Diariamente Algunas veces a la semana Algunas veces al mes
## 81.6 15.3 2.9
## Algunas veces al año
## 0.3
Para presentar todos los datos en una tabla conjunta, se guarda la
tabla de cada red social en un nuevo objeto de R (llamado como cada red
social). Luego, todas estas tablas parciales, que contienen las mismas
opciones de respuesta, se unen como filas con el comando
rbind
. Esta nueva tabla conjunta se guarda como un nuevo
dataframe “tabla”.
Facebook = round(prop.table(table(lapop18$smedia2r)), 3)*100
Twitter = round(prop.table(table(lapop18$smedia5r)), 3)*100
Whatsapp = round(prop.table(table(lapop18$smedia8r)), 3)*100
tabla = as.data.frame(rbind(Facebook, Twitter, Whatsapp))
tabla
Para tener una mejor presentación de la tabla, se puede usar el
comando kable
del paquete knitr
o el comando
formattable
del paquete del mismo nombre.
library(knitr)
kable(head(tabla), format="markdown", digits=1)
Facebook |
57.1 |
32.6 |
8.5 |
1.9 |
Twitter |
37.2 |
34.1 |
19.7 |
9.0 |
Whatsapp |
81.6 |
15.3 |
2.9 |
0.3 |
library(formattable)
formattable(tabla)
|
Diariamente
|
Algunas veces a la semana
|
Algunas veces al mes
|
Algunas veces al año
|
Facebook
|
57.1
|
32.6
|
8.5
|
1.9
|
Twitter
|
37.2
|
34.1
|
19.7
|
9.0
|
Whatsapp
|
81.6
|
15.3
|
2.9
|
0.3
|
Para graficar esta variable, vamos a trabajar directamente desde la
tabla creada con los porcentajes de las tres redes sociales. Esta tabla
tiene a cada red social en las filas y las opciones de respuesta en las
columnas. Para poder graficar estos datos se requiere que las redes
sociales estén en las columnas y las opciones de respuesta en las filas,
por lo que en primer lugar vamos a transponer esta tabla. Este
procedimiento lo hacemos usando la librería data.table
y el
comando transpose
. Estos datos transpuestos los guardamos
en una nueva tabla “tabla_tr”.
Este comando transpone los datos, pero deja sin nombrar las filas y
columnas. Primero se nombran las columnas con el comando
colnames
usando los nombres de las filas de “tabla”. Luego
se nombran las filas con el comando rownames
usando los
nombres de las columnas de “tabla”.
Finalmente, requerimos una columna dentro de “tabla_tr” que incluya
las etiquetas de respuesta de las preguntas de smedia. Estas etiquetas
están como nombres de filas. Para incluirlas como una variable más, se
agrega una variable “tabla_tr$lab” al que se le asigna los nombres de
las filas con row.names
.
library(data.table)
tabla_tr = data.frame(t(tabla[]))
colnames(tabla_tr) = rownames(tabla)
rownames(tabla_tr) = colnames(tabla)
tabla_tr$lab = rownames(tabla_tr)
tabla_tr
En segundo lugar, se activa la librería ggplot2
para
graficar los datos guardados en “tabla_tr” con el comando
ggplot
. Dentro de este comando se especifica que se
trabajará con el dataframe “tabla_tr” (no con lapop18) y se especifica
la “estética”, es decir que en el eje X no se incluirá una variable, que
en el eje Y se incluirá los datos de “Facebook” del dataframe “tabla_tr”
y que se dividirá por categorías de la variable guardadas en “lab”.
Luego se añade la capa geom_bar
para indicar que se
graficará en barras de ancho (width
) 1 y que la barra
replicará lo especificado en la estética (stat="identity"
).
Con geom_text
se agrega las etiquetas de los datos, con el
símbolo de porcentaje, y se especifica la posición del texto con
position=position_stack(…)
y el tamaño con
size=3
. Con coord_polar
se transforma las
barras en un gráfico circular de sectores. Finalmente, se define el
“tema” con theme_void
indicando un fondo blanco y se
modifica la etiqueta de la leyenda con
scale_fill_discrete
.
library(ggplot2)
ggplot(data=tabla_tr, aes(x="", y=Facebook, fill=lab))+
geom_bar(width=1, stat="identity")+
geom_text(aes(label=paste(Facebook, "%", sep="")), color="white",
position=position_stack(vjust=0.5), size=3)+
coord_polar("y", start=0)+
theme_void()+
scale_fill_discrete(name="Frecuencia de uso de Facebook")
En el gráfico 3.3 del reporte “El Pulso de la Democracia” se presenta
un gráfico circular tipo “dona”. Para reproducir exactamente este tipo
de gráfico, se tiene que acomodar unos detalles de la sintaxis anterior.
Se establece “x=2” en la “estética” y se establece límites en el eje X,
entre 0.5 y 2.5, para que cuando se rote el eje, se cree el “hueco”
dentro del círculo.
ggplot(data=tabla_tr, aes(x=2, y=Facebook, fill=lab))+
geom_bar(stat="identity")+
geom_text(aes(label=paste(Facebook, "%", sep="")), color="white",
position=position_stack(vjust=0.5), size=3)+
coord_polar("y")+
theme_void()+
scale_fill_discrete(name="Frecuencia de uso de Facebook")+
labs(title="Frecuencia con la que ve contenido en Facebbok",
caption="Barómetro de las Américas por LAPOP, 2018/19")+
xlim(0.5, 2.5)
Para replicar el gráfico de barras, se hacen algunas modificaciones
en el código anterior. Por ejemplo, en la “estética”, ahora se indica
que en el eje X va la variable “smedia2r” y en el eje Y el porcentaje
“per”. Se elimina, además, la especificación de las coordenadas polares.
Se agrega un título al gráfico, etiquetas a los ejes y un caption con la
especificación labs
. Finalmente, se define el eje Y entre 0
y 60 con la especificación coord_cartesian
. Un tema
importante es que este gráfico también se puede guardar en un objeto en
R, que llamaremos “graf1”.
graf1 = ggplot(tabla_tr, aes(x=lab, y=Facebook))+
geom_bar(stat="identity", width=0.5)+
geom_text(aes(label=paste(Facebook, "%", sep="")), color="black", vjust=-0.5)+
labs(title="Frecuencia de uso de redes sociales", x="Frecuencia de uso de Facebook", y="Porcentaje", caption="Barómetro de las Américas por LAPOP, 2018/19")+
coord_cartesian(ylim=c(0, 60))
graf1
Guardar un gráfico en un objeto nos permite luego incorporar más
capas o mejoras en el gráfico. El gráfico anterior, por ejemplo, tiene
las etiquetas de “Frecuencia de uso” en una sola línea, por lo se
podrían trasponer. Para mejorar esta visualización se puede inclinar
estas etiquetas, pero si se quisiera mantener la horizontalidad para
facilitar la lectura, lo que se puede hacer es separar las etiquetas
largas en dos o más líneas. Esto se puede hacer, por ejemplo, creando un
vector con las nuevas etiquetas. Las etiquetas largas se pueden partir
en líneas mediante la inclusión de \n
entre los textos que
se quiera separar. Luego, al objeto “graf1” se le puede agregar una
nueva capa para reemplazar las etiquetas con las nuevas divididas en
líneas. Esto se hace con la especificación scale_x_discrete
donde se indica que las etiquetas usen el vector creado.
etiq = c("Diariamente", "Algunas veces\na la semana", "Algunas veces\nal mes",
"Algunas veces\nal año")
graf1 +
scale_x_discrete(labels=etiq)
De esta manera el gráfico queda más legible. Hasta aquí se ha
replicado las tablas y gráficos que se usaron con las variables
nominales, ahora usando variables ordinales. Si se quiere replicar el
gráfico circular de las otras redes sociales, se puede ejecutar el mismo
código, pero cambiando la columna de la red social. Para Twitter, por
ejemplo, se tendría.
graf2 = ggplot(data=tabla_tr, aes(x=2, y=Twitter, fill=lab))+
geom_bar(stat="identity")+
geom_text(aes(label=paste(Twitter, "%", sep="")), color="white",
position=position_stack(vjust=0.5), size=3)+
coord_polar("y")+
theme_void()+
scale_fill_discrete(name="Frecuencia de uso de Twitter")+
labs(title="Frecuencia con la que ve contenido en Twitter",
caption="Barómetro de las Américas por LAPOP, 2018/19")+
xlim(0.5, 2.5)
graf2
Cruce de variables
En la tabla 3.1 (pag. 55) del reporte “El pulso de la democracia” se
presenta los porcentajes de uso de las redes sociales por país. Luego,
en la página 56 se presenta un cuadro con el porcentaje de usuarios de
redes sociales por características sociodemográficas, por ejemplo,
urbano/rural, hombre, edad promedio, riqueza promedio y años de
estudio.
Empezaremos replicando los datos generales del uso de redes sociales
que se reporta en el gráfico 3.1. Para replicar esta tabla primero se
tiene que definir la variable “pais” y las variables de uso de redes
sociales (smedia1, smedia4 y smedia7).
lapop18$smedia1r = as.factor(lapop18$smedia1)
lapop18$smedia4r = as.factor(lapop18$smedia4)
lapop18$smedia7r = as.factor(lapop18$smedia7)
levels(lapop18$smedia1r) = c("Sí", "No")
levels(lapop18$smedia4r) = c("Sí", "No")
levels(lapop18$smedia7r) = c("Sí", "No")
lapop18$pais = as.factor(lapop18$pais)
levels(lapop18$pais) = c("México", "Guatemala", "El Salvador", "Honduras",
"Nicaragua","Costa Rica", "Panamá", "Colombia",
"Ecuador", "Bolivia", "Perú", "Paraguay",
"Chile", "Uruguay", "Brasil", "Argentina",
"Rep. Dom.", "Jamaica")
table(lapop18$pais) #País
##
## México Guatemala El Salvador Honduras Nicaragua Costa Rica
## 1580 1596 1511 1560 1547 1501
## Panamá Colombia Ecuador Bolivia Perú Paraguay
## 1559 1663 1533 1682 1521 1515
## Chile Uruguay Brasil Argentina Rep. Dom. Jamaica
## 1638 1581 1498 1528 1516 1513
table(lapop18$smedia1r) #Facebook
##
## Sí No
## 15389 11573
Sin embargo, la variable “usuario” de cada red social se calcula como
condición de dos variables, como se vio en el documento sobre manejo de
datos, con el siguiente código.
lapop18$fb_user = ifelse(lapop18$smedia1==1 & lapop18$smedia2<=4, 1, 0)
lapop18$tw_user = ifelse(lapop18$smedia4==1 & lapop18$smedia5<=4, 1, 0)
lapop18$wa_user = ifelse(lapop18$smedia7==1 & lapop18$smedia8<=4, 1, 0)
lapop18$fb_user = as.factor(lapop18$fb_user)
lapop18$tw_user = as.factor(lapop18$tw_user)
lapop18$wa_user = as.factor(lapop18$wa_user)
levels(lapop18$fb_user) = c("No usuario", "Usuario")
levels(lapop18$tw_user) = c("No usuario", "Usuario")
levels(lapop18$wa_user) = c("No usuario", "Usuario")
Esta variables son graficadas en el reporte en el Gráfico 3.1. Para
reproducir estos datos, se puede describir estas variables.
prop.table(table(lapop18$fb_user))*100
##
## 0 1
## 43.8289 56.1711
prop.table(table(lapop18$tw_user))*100
##
## 0 1
## 92.056769 7.943231
prop.table(table(lapop18$wa_user))*100
##
## 0 1
## 35.76561 64.23439
Como en gráficos anteriores, con estos datos se puede crear un
dataframe que se utilizaría para hacer los gráficos circulares mostrados
en el reporte.
Para replicar el cuadro de uso de redes sociales por país, primero,
se crean las tablas bivariadas con el porcentaje de los que usan y el
porcentaje de los que no usan cada red social en cada país. Estas tablas
se guardan en objetos de R. Luego se unen estos objetos usando los
comandos cbind
para juntar las columnas y
as.data.frame
para unir las tablas como un dataframe. Esta
tabla presenta también los porcentajes de los que No usan estas redes
sociales. Para presentar una tabla que incluya solo a los que sí usan
las redes sociales, se eliminan estas columnas, usando la especificación
[, c(-1,-3,-5)]
, que indica que se quiere eliminar las
columnas 1, 3 y 5.Finalmente, se cambia el nombre de las columnas del
dataframe.
fbpais = round(prop.table(table(lapop18$pais, lapop18$fb_user), 1), 3)*100
twpais = round(prop.table(table(lapop18$pais, lapop18$tw_user), 1), 3)*100
whpais = round(prop.table(table(lapop18$pais, lapop18$wa_user), 1), 3)*100
tablapais = as.data.frame(cbind(fbpais, twpais, whpais))
tablapais = tablapais[, c(-1,-3,-5)]
varnames = c("Usa Facebook", "Usa Twitter", "Usa Whatsapp")
colnames(tablapais) = varnames
tablapais
Para tener una mejor presentación de la tabla se tienen dos
alternativas: la primera con la librería knitr
y la otra
con la librería formattable
.
library(knitr)
kable(head(tablapais), format="markdown", digits=1)
México |
47.9 |
7.6 |
55.1 |
Guatemala |
43.2 |
6.5 |
47.6 |
El Salvador |
56.2 |
6.7 |
56.0 |
Honduras |
44.6 |
4.8 |
46.9 |
Nicaragua |
48.1 |
5.8 |
47.7 |
Costa Rica |
66.6 |
8.0 |
81.6 |
library(formattable)
formattable(tablapais)
|
Usa Facebook
|
Usa Twitter
|
Usa Whatsapp
|
México
|
47.9
|
7.6
|
55.1
|
Guatemala
|
43.2
|
6.5
|
47.6
|
El Salvador
|
56.2
|
6.7
|
56.0
|
Honduras
|
44.6
|
4.8
|
46.9
|
Nicaragua
|
48.1
|
5.8
|
47.7
|
Costa Rica
|
66.6
|
8.0
|
81.6
|
Panamá
|
34.6
|
5.8
|
56.7
|
Colombia
|
60.0
|
10.7
|
63.5
|
Ecuador
|
66.9
|
11.2
|
60.2
|
Bolivia
|
57.9
|
5.6
|
63.5
|
Perú
|
61.4
|
7.6
|
58.6
|
Paraguay
|
60.5
|
8.0
|
69.2
|
Chile
|
62.9
|
9.2
|
75.5
|
Uruguay
|
66.5
|
9.8
|
80.0
|
Brasil
|
59.2
|
7.9
|
74.9
|
Argentina
|
67.3
|
12.9
|
78.9
|
Rep. Dom.
|
61.9
|
9.5
|
68.2
|
Jamaica
|
45.9
|
4.5
|
68.1
|
Cruce con variables sociodemográficas
En la página 56 del reporte “El pulso de la democracia” se presenta
los resultados del cruce entre las variables uso de redes sociales y
variables sociodemográficas como urbano/rural, sexo, edad, riqueza y
años de educación.
La variable “q1” registra el género del entrevistado. Esta variable
está codificada de la siguiente manera:
- Hombre
- Mujer
Para construir una variable “dummy” llamada “hombre”, de tal manera
que hombre sea 1 y mujer sea 0, una forma de hacerlo es de manera
algebraica (2-variable q1). De esta manera, ahora los hombres mantiene
el valor 1 (2-1) y las mujeres pasar a ser 0 (2-2). En este caso, la
nueva variable “hombre” se crea como una una variable numérica. Vamos a
mantener a la variable como “num” para, más abajo, poder calcular la
media de esta variable (cosa que no se puede hacer de una variable
declarada como factor).
lapop18$hombre = 2-lapop18$q1
lapop18$hombre = as.factor(lapop18$hombre)
levels(lapop18$hombre) = c("Mujer", "Hombre")
table(lapop18$hombre)
##
## Mujer Hombre
## 14084 13943
La variable urbano/rural se llama “ur” en la base de datos y está
codificada de la siguiente manera:
- Urbano
- Rural
De la misma manera que con género, se usa la fórmula 2- variable ur,
pero esta variable sí se convierte en factor y se etiqueta.
lapop18$urban = 2-lapop18$ur
lapop18$urban = as.factor(lapop18$urban)
levels(lapop18$urban) = c("Rural", "Urbano")
table(lapop18$urban)
##
## Rural Urbano
## 8089 19953
Se presentará las tablas cruzadas del uso de redes sociales por
alguno de las variable sociodemográficas, para entender mejor cómo se
construye la tabla general. Por ejemplo, el reporte muestra en la Tabla
3.2, luego de la columna de población general, las columnas para
usuarios y no usuarios de Whatsapp (variable “wa_user”) y en las filas,
la primera corresponde a urbano (variable “urban”, donde 0 es rural y 1
urbano). Se presenta que entre los usuarios de Whatsapp, el 76.7% son
urbanos y entre los no usuarios, el 62% son urbanos. Estos datos se
generan con el comando table
que permite hacer una tabla de
contingencia de 2 variables. En este caso se tiene que notar que cada
variable tiene un título. De esta manera el comando es
table(título1 = var1, título2 = var2)
. Luego, se usa el
comando prop.table
para que no se muestre las
observaciones, sino los porcentajes. Este comando permite calcular los
porcentajes sobre el total (la opción por defecto), sobre las filas y
sobre las columnas. Para calcular sobre las columnas se debe especificar
prop.table(table(...), 2)
. Si se quisiera el porcentaje
sobre las filas, el código sería prop.table(table(...), 1)
.
Esta tabla se pueden guardar como un dataframe con el comando
as.data.frame
en un nuevo objeto “t1”.
t_wa = as.data.frame(round(prop.table(table(Urbano = lapop18$urban, Usuario = lapop18$wa_user), 2)*100, 1))
t_wa
La filas correspondientes a “Urbano” de esta tabla reproducen los
datos de la Tabla 3.2: 62.1% son urbanos entre los no usuarios de
Whatsapp y 76.7% son urbanos entre los usuarios.
El mismo procedimiento se puede realizar para los usuarios de
Facebook, en este caso cruzado con la variable “hombre”.
t_fb = as.data.frame(round(prop.table(table(Urbano = lapop18$hombre, Usuario = lapop18$fb_user), 2)*100, 1))
t_fb
Estos son los porcentajes para los usuarios de Facebook, en la fila
de la variable Hombre de la Tabla 3.2. Es decir, entre los usuarios de
Facebook, 49.9% son hombres y entre los no usuarios este porcentaje es
49.7%. Hasta aquí se ha reconstruido algunos resultados de la Tabla 3.2.
Los demás datos pueden seguir siendo reconstruidos mediante
combinaciones de las variables de usuarios de redes sociales y las
variables sociodemográficas.
Gráfico de barras de dos variables
El cruce entre usuarios de Whatsapp y la variable urbano se puede ver
también en un gráfico de barras agrupadas. Para esto, usaremos la tabla
“t_wa” que contiene estos datos.
ggplot(data=t_wa, aes(x=Usuario, y=Freq, fill=Urbano, ymax=100))+
geom_bar(position="dodge", stat="identity")+
geom_text(aes(label=paste(Freq, "%", sep="")),
position=position_dodge(width=0.9), vjust=-0.25)+
ylab("Porcentaje")+
xlab("Usuario de Whatsapp")
Si quisiéramos hacer el gráfico con barras apiladas, se tiene que
cambiar la especificación de position="stack"
en
geom_bar
y la especificación
position=position_stack()
de geom_text
.
ggplot(data=t_wa, aes(x=Usuario, y=Freq, fill=Urbano, ymax=100))+
geom_bar(position="stack", stat="identity")+
geom_text(aes(label=paste(Freq, "%", sep="")),
position=position_stack(), vjust=2.5)+
ylab("Porcentaje")+
xlab("Usuario de Whatsapp")
En ambos casos las barras celestes indican los porcentajes reportados
en la tabla 3.2 del reporte y corresponden a la proporción de personas
que viven en el ámbito urbano entre los usuarios y los no usuarios.
Cálculos incluyendo el efecto de diseño
Ejemplo con datos de la ronda 2021
Con los datos de la ronda 2021 del Barómetro de las Américas, hemos
calculado los porcentajes de la variable que mide si los votos se han
contado justamente. El gráfico que hemos creado ha sido para el total de
la muestra, es decir, de todos los países. El Gráfico 2.5 del reporte El
Pulso de la Democracia presenta los resultados para cada país.
Si calculáramos los porcentajes con el comando table
y
prop.table
tendríamos resultados diferentes a los mostrados
en el gráfico. Por ejemplo, en el país 5, que es Nicaragua, los
resultados indican que 26% de ciudadanos de ese país indica que los
votos siempre se cuentan justamente, 49% que algunas veces se cuentan
justamente y 24.4% que nunca. Sin embargo, el gráfico indica que en
Nicaragua, 29% indica que nunca de cuenta justamente, 45% indica que
algunas veces y 25% que siempre. Estos porcentajes no corresponden a los
que se encuentran con estos comandos.
round(prop.table(table(lapop21$pais, lapop21$countfair1r), 1), 3)*100
##
## Siempre Algunas veces Nunca
## 1
## 2
## 3
## 4
## 5 26.2 49.4 24.4
## 6 52.3 40.2 7.5
## 7 27.6 57.1 15.4
## 8 18.1 50.4 31.5
## 9 21.5 59.1 19.4
## 10 24.5 59.2 16.3
## 11 25.1 61.1 13.8
## 12 25.9 48.3 25.8
## 13 64.1 30.1 5.8
## 14 80.0 16.9 3.0
## 15 48.1 35.7 16.1
## 17 31.5 51.0 17.5
## 21 25.2 60.1 14.7
## 22
## 23 17.9 67.9 14.2
## 24 17.0 65.1 17.8
Esta diferencia es debido a que los comandos table
y
prop.table
no incluyen el efecto de diseño y el factor de
expansión en los cálculos. Más información sobre estas diferencias se
encuentra aquí.
Para replicar los resultados del Gráfico 2.5 hay algunas opciones. La
primera es mediante la librería especializada survey
. Para
poder usar esta librería, primero debemos preparar la base de datos,
eliminando los valores perdidos de las variables que definen el diseño.
Un paso adicional es transformar las variables del dataframe. Esto es
debido a que cuando se importan, el sistema lee las variables como tipo
“haven_labelled”, es decir, mantiene las etiquetas de las variables, con
lo que se podría producir un libro de códigos. Esto es útil en otras
ocasiones, pero genera problemas con la librería survey
.
Para esto transformamos las variables a otro tipo con el comando
sapply
.
lapop21 = subset(lapop21, !is.na(weight1500))
sapply(lapop21, haven::zap_labels)
Una vez preparada la base de datos, se activa la librería y se define
el diseño. En el módulo anterior, también usamos esta librería para
calcular los resultados con el efecto de diseño en la ronda 2018. A
diferencia de ese código, es que la ronda 2021 del Barómetro de las
Américas utilizó la modalidad telefónica, y no cara a cara, por lo que
ahora la unidad primaria de muestreo es el individuo, y así está
definida en la variable “upm”. La variable que define los estratos es
“strata” (y no “estratopri” como en la ronda 2018). La variable de
ponderación sigue siendo “weight1500”.
Con estos datos calculamos guardamos el diseño en un objeto
“diseno21”.
library(survey)
diseno21 = svydesign(ids = ~upm, strata = ~strata, weights = ~weight1500, nest=TRUE, data=lapop21)
La librería survey
incluye comandos nativos para hacer
múltiples operaciones que incluyan el efecto de diseño. Uno de esos
comandos es svytable
que nos permite hacer la tabla cruzada
entre la variable “countfair1r” y “pais”, especificando el diseño. Este
comando nos devuelve las frecuencias absolutas ponderadas, por lo que se
puede anidar en el comando prop.table
para calcular los
porcentajes desde las frecuencias absolutas ponderadas y dentro del
comando count
para redondear los porcentajes, y dentro del
comando as.data.table
para guardar la tabla en un objeto
“votoxpais” como un dataframe, que nos permita la manipulación con
ggplot
luego.
votoxpais = as.data.frame(round(prop.table(svytable(~pais+countfair1r, design=diseno21), 1)*100, 0))
votoxpais$pais = pais
votoxpais
ggplot(data=votoxpais, aes(fill=countfair1r, x=Freq, y=pais))+
geom_bar(stat="identity", width=0.3)+
geom_text(aes(label=paste(Freq, "%", sep="")), color="white",
position=position_stack(vjust=0.5), size=3)+
labs(x="Porcentaje", y="País", fill="Los votos se cuentan justamente",
caption="Barómetro de las Américas por LAPOP, 2021")
Este gráfico reproduce exactamente los resultados mostrados en el
Gráfico 2.5 del reporte, aunque en un orden diferente.
Ejemplo con los datos de la ronda 2018/19
La pequeña diferencia entre los porcentajes que se muestran en el
Gráfico 3.3 y los mostrados en la sección “Describir las variables”
puede deberse a que en todos las tablas y gráficos anteriores no se
incluye el factor de expansión. Si se incluyera, usando la variable
“weight1500”, se replicarían los porcentajes mostrados en el informe.
Por ejemplo, para el uso de Whatsapp, se puede usar el comando
freq
de la librería descr
que permite incluir
una variable de ponderación.
Esta tabla luego se puede guardar en un dataframe, al que se le
pueden eliminar las filas y columnas que no se requieren, y se les puede
cambiar el nombre a las columnas. y agregar las etiquetas.
tabla2 = as.data.frame(descr::freq(lapop18$smedia8r, lapop18$weight1500, plot=F))
tabla2 = tabla2[-c(5,6), -2]
colnames(tabla2) = c("frec", "per")
tabla2$lab = rownames(tabla2)
tabla2
Con este nuevo dataframe, se puede replicar el gráfico de Whatsapp,
con los datos ponderados, usando el código de ggplot
.
ggplot(data=tabla2, aes(x=2, y=per, fill=lab))+
geom_bar(stat="identity")+
geom_text(aes(label=paste(round(per, 1), "%", sep="")), color="white",
position=position_stack(vjust=0.5), size=3)+
coord_polar("y")+
theme_void()+
scale_fill_discrete(name="Frecuencia de uso de Facebook")+
labs(title="Frecuencia con la que ve contenido en Facebook",
caption="Barómetro de las Américas por LAPOP, 2018/19")+
xlim(0.5, 2.5)
Además del comando freq
, también se puede usar la
librería survey
y el comando nativo
svytable
.
library(survey)
diseno18<-svydesign(ids = ~upm, strata = ~estratopri, weights = ~weight1500, nest=TRUE, data=lapop18)
Los resultados que se obtienen son iguales que con el método anterior
y a los presentados en el reporte. Estos resultados también se pueden
guardar en un “dataframe” para hacer el gráfico.
prop.table(svytable(~smedia8r, design=diseno18))*100
## smedia8r
## Diariamente Algunas veces a la semana Algunas veces al mes
## 81.6626475 15.2056787 2.8473540
## Algunas veces al año
## 0.2843197
La sección “Cruce con variables” presenta los datos de usuarios de
redes sociales por país. Para construir la tabla considerando el efecto
de diseño, también se puede usar el comando nativo svytable
que permite calcular una tabla bivariada. De la misma manera que en caso
no ponderado, las tablas parciales de cada red social se guardan en unos
objetos de tipo lista, los que se juntan como un “dataframe” y se edita
para presentar solo los datos de los usuarios de cada red social por
país.
fbpais_2 = round(prop.table(svytable(~pais+fb_user, design=diseno18), 1), 3)*100
twpais_2 = round(prop.table(svytable(~pais+tw_user, design=diseno18), 1), 3)*100
wapais_2 = round(prop.table(svytable(~pais+wa_user, design=diseno18), 1), 3)*100
tablapais_2 = as.data.frame(cbind(fbpais_2, twpais_2, wapais_2))
tablapais_2 = tablapais_2[, c(-1,-3,-5)]
varnames = c("Usa Facebook", "Usa Twitter", "Usa Whatsapp")
colnames(tablapais_2) = varnames
tablapais_2
Por último, la sección “Cruce con variables sociodemográficas”
reproduce los resultados de la Tabla 3.2 del reporte. De la misma manera
que en el caso anterior, se puede usar el comando nativo
svytable
para realizar el cruce entre las variables de uso
de redes sociales y la variable urbano. Los resultados de la fila Urbano
en cada red social corresponderían a la primera fila de resultados de la
Tabla 3.2.
round(prop.table(svytable(~urban+wa_user, design=diseno18), 2), 3)*100
## wa_user
## urban No usuario Usuario
## Rural 38.0 23.3
## Urbano 62.0 76.7
round(prop.table(svytable(~urban+fb_user, design=diseno18), 2), 3)*100
## fb_user
## urban No usuario Usuario
## Rural 35.6 23.0
## Urbano 64.4 77.0
round(prop.table(svytable(~urban+tw_user, design=diseno18), 2), 3)*100
## tw_user
## urban 0 1
## Rural 29.7 15.3
## Urbano 70.3 84.7
De esta manera se pueden calcular las tablas de distribución de
frecuencias y las tablas bivariadas (o de contingencia) incluyendo el
efecto de diseño o el factor de expansión.
LS0tCnRpdGxlOiAiRXN0YWTDrXN0aWNhIGRlc2NyaXB0aXZhIHVzYW5kbyBlbCBCYXLDs21ldHJvIGRlIGxhcyBBbcOpcmljYXMgKDIpIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICB0b2NfZGVwdGg6IDEKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBmbGF0bHkKICAgIGRmX3ByaW50OiBwYWdlZAogICAgc2VsZl9jb250YWluZWQ6IG5vCiAgICBrZWVwX21kOiB5ZXMKICAgICNjb2RlX2ZvbGRpbmc6IGhpZGUKZWRpdG9yX29wdGlvbnM6IAogIG1hcmtkb3duOiAKICAgIHdyYXA6IHNlbnRlbmNlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUUpCmBgYAoKYGBge2NzcyBjb2xvciwgZWNobz1GQUxTRX0KLmNvbHVtbnMge2Rpc3BsYXk6IGZsZXg7fQpoMSB7Y29sb3I6ICMzMzY2Q0M7fQpgYGAKCiMgSW50cm9kdWNjacOzbgoKRW4gZXN0ZSBkb2N1bWVudG8gdmFtb3MgYSBjb250aW51YXIgdXNhbmRvIGVsIMO6bHRpbW8gaW5mb3JtZSByZWdpb25hbCAiRWwgcHVsc28gZGUgbGEgZGVtb2NyYWNpYSIsIHRhbnRvIGRlIGxhIHJvbmRhIDIwMjEsIGRpc3BvbmlibGUgW2FxdcOtXShodHRwczovL3d3dy52YW5kZXJiaWx0LmVkdS9sYXBvcC9hYjIwMjEvMjAyMV9MQVBPUF9BbWVyaWNhc0Jhcm9tZXRlcl8yMDIxX1B1bHNlX29mX0RlbW9jcmFjeV9TUEEucGRmKSwgeSBkZSBsYSByb25kYSAyMDE4LzE5LCBkaXNwb25pYmxlIFthcXXDrV0oaHR0cHM6Ly93d3cudmFuZGVyYmlsdC5lZHUvbGFwb3AvYWIyMDE4LzIwMTgtMTlfQW1lcmljYXNCYXJvbWV0ZXJfUmVnaW9uYWxfUmVwb3J0X1NwYW5pc2hfV18wMy4yNy4yMC5wZGYpLgpVbmEgZGUgbGFzIHNlY2Npb25lcyBkZSBlc3RlIGluZm9ybWUsIHJlcG9ydGEgbG9zIGRhdG9zIHNvYnJlIHJlZGVzIHNvY2lhbGVzIHkgYWN0aXR1ZGVzIHBvbMOtdGljYXMuCkVuIGVsIHJlcG9ydGUgMjAyMCBzZSBwcmVzZW50YSByZXN1bHRhZG9zIHNvYnJlIHZhcmlhYmxlcyByZWxhY2lvbmFkYXMgY29uIGxhIGludGVncmlkYWQgZWxlY3RvcmFsLCBwb3IgZWplbXBsbywgbGEgcGVyY2VwY2nDs24gZGUgc2kgbG9zIHZvdG9zIHNlIGN1ZW50YW4gY29ycmVjdGFtZW50ZS4KRW4gZWwgcmVwb3J0ZSAyMDE4LzE5LCBzZSBwcmVzZW50YW4gZGF0b3Mgc29icmUgZWwgdXNvIGRlIGludGVybmV0IHkgZWwgdXNvIGRlIHJlZGVzIHNvY2lhbGVzLCBlbiBnZW5lcmFsIHkgcG9yIHBhw61zLgpFbiBlc3RlIGNhc28gdmFtb3MgYSB0cmFiYWphciBjb24gbGEgZnJlY3VlbmNpYSBkZSB1c28gZGUgbGFzIHJlZGVzIHNvY2lhbGVzLgpFbiBlc3RlIGRvY3VtZW50byB2YW1vcyBhIGFuYWxpemFyIGRlc2NyaXB0aXZhbWVudGUgZXN0YXMgdmFyaWFibGVzIHNvYnJlIHNpIGxvcyB2b3RvcyBzZSBjdWVudGFuIGNvcnJlY3RhbWVudGUgeSBzb2JyZSBsYSBmcmVjdWVuY2lhIGRlIHVzbyBkZSByZWRlcyBzb2NpYWxlcywgdmFyaWFibGVzIGRlIHRpcG8gb3JkaW5hbCAobyBkZSBmYWN0b3IsIGVuIGVsIGxlbmd1YWplIGRlIFIpLgoKIyBTb2JyZSBsYSBiYXNlIGRlIGRhdG9zCgpMb3MgZGF0b3MgcXVlIHZhbW9zIGEgdXNhciBkZWJlbiBjaXRhcnNlIGRlIGxhIHNpZ3VpZW50ZSBtYW5lcmE6IEZ1ZW50ZTogQmFyw7NtZXRybyBkZSBsYXMgQW3DqXJpY2FzIHBvciBlbCBQcm95ZWN0byBkZSBPcGluacOzbiBQw7pibGljYSBkZSBBbcOpcmljYSBMYXRpbmEgKExBUE9QKSwgd3d3dy5MYXBvcFN1cnZleXMub3JnLgpFbiBlc3RlIGRvY3VtZW50byBzZSBjYXJnYSBudWV2YW1lbnRlIHVuYSBiYXNlIGRlIGRhdG9zIHJlY29ydGFkYS4KUGFyYSByZXByb2R1Y2lyIGxvcyByZXN1bHRhZG9zIG1vc3RyYWRvcyBlbiBlc3RhIHNlY2Npw7NuIHNlIGRlYmUgbGltcGlhciBlbiBFbnZpcm9ubWVudC4KCkVzdGEgYmFzZSBkZSBkYXRvcyBzZSBlbmN1ZW50cmEgYWxvamFkYSBlbiBlbCByZXBvc2l0b3JpbyAibWF0ZXJpYWxzX2VkdSIgZGUgbGEgY3VlbnRhIGRlIExBUE9QIGVuIEdpdEh1Yi4KTWVkaWFudGUgbGEgbGlicmVyw61hIGByaW9gIHkgZWwgY29tYW5kbyBgaW1wb3J0YCBzZSBwdWVkZSBpbXBvcnRhciBlc3RhIGJhc2UgZGUgZGF0b3MgZGVzZGUgZXN0ZSByZXBvc2l0b3Jpby4KQWRlbcOhcywgc2Ugc2VsZWNjaW9uYW4gbG9zIGRhdG9zIGRlIHBhw61zZXMgY29uIGPDs2RpZ29zIG1lbm9yZXMgbyBpZ3VhbGVzIGEgMzUsIGVzIGRlY2lyLCBzZSBlbGltaW5hIGxhcyBvYnNlcnZhY2lvbmVzIGRlIEVzdGFkb3MgVW5pZG9zIHkgQ2FuYWTDoS4KCmBgYHtyIGJhc2V9CmxpYnJhcnkocmlvKQpsYXBvcDE4ID0gaW1wb3J0KCJodHRwczovL3Jhdy5naXRodWIuY29tL2xhcG9wLWNlbnRyYWwvbWF0ZXJpYWxzX2VkdS9tYWluL0xBUE9QX0FCX01lcmdlXzIwMThfdjEuMC5zYXYiKQpsYXBvcDE4ID0gc3Vic2V0KGxhcG9wMTgsIHBhaXM8PTM1KQpgYGAKClRhbWJpw6luIGNhcmdhbW9zIGxhIGJhc2UgZGUgZGF0b3MgZGUgbGEgcm9uZGEgMjAyMS4KCmBgYHtyIGJhc2UyMX0KbGFwb3AyMSA9IGltcG9ydCgiaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS9sYXBvcC1jZW50cmFsL21hdGVyaWFsc19lZHUvbWFpbi9sYXBvcDIxLlJEYXRhIikKbGFwb3AyMSA9IHN1YnNldChsYXBvcDIxLCBwYWlzPD0zNSkKYGBgCgojIERlc2NyaWJpciB5IGdyYWZpY2FyIGxhcyB2YXJpYWJsZXMKCkVuIGVsIGRvY3VtZW50byBzb2JyZSBlc3RhZMOtc3RpY2EgZGVzY3JpcHRpdmEsIHF1ZSBzZSBwdWVkZSB2ZXIgW2FxdcOtXShodHRwczovL3JwdWJzLmNvbS9hcnR1cm9fbWFsZG9uYWRvLzY5Njc3MCksIHNlIHRyYWJhasOzIGNvbiB2YXJpYWJsZXMgbm9taW5hbGVzLCBjb24gb3BjaW9uZXMgZGUgcmVzcHVlc3RhIGRpY290w7NtaWNhIChTw60vTm8pLgpFbiBlc3RlIGRvY3VtZW50byBzZSB2YSBhIHRyYWJhamFyIGNvbiB2YXJpYWJsZXMgb3JkaW5hbGVzIHBvbGl0w7NtaWNhcy4KCiMgTG9zIHZvdG9zIHNvbiBjb250YWRvcyBjb3JyZWN0YW1lbnRlCgpFbiBlc3RhIHNlY2Npw7NuIHNlIHZhIGEgdXNhciBsYSB2YXJpYWJsZSBDT1VOVEZBSVIxLgpMb3Mgdm90b3Mgc29uIGNvbnRhZG9zIGNvcnJlY3RhIHkganVzdGFtZW50ZS4Kwr9EaXLDrWEgdXN0ZWQgcXVlIHN1Y2VkZSBzaWVtcHJlLCBhbGd1bmFzIHZlY2VzIG8gbnVuY2E/CkVsIGdyw6FmaWNvIDIuNSBkZWwgcmVwb3J0ZSBlbCBQdWxzbyBkZSBsYSBEZW1vY3JhY2lhLCBkaXNwb25pYmxlIFthcXXDrV0oaHR0cHM6Ly93d3cudmFuZGVyYmlsdC5lZHUvbGFwb3AvYWIyMDIxLzIwMjFfTEFQT1BfQW1lcmljYXNCYXJvbWV0ZXJfMjAyMV9QdWxzZV9vZl9EZW1vY3JhY3lfU1BBLnBkZiksIHByZXNlbnRhIGxvcyByZXN1bHRhZG9zIGRlIGVzdGEgdmFyaWFibGUgcG9yIHBhw61zLgoKIVtdKEdyYWZpY28yLjUucG5nKXt3aWR0aD0iNTgwIn0KCkRlIGxhIG1pc21hIG1hbmVyYSBxdWUgY29uIGxhcyB2YXJpYWJsZXMgbm9taW5hbGVzLCBlc3RhcyB2YXJpYWJsZXMgdGllbmVuIHF1ZSBzZXIgZGVjbGFyYWRhcyBjb21vICJmYWN0b3IiIGVuIG51ZXZhcyB2YXJpYWJsZXMuCgpgYGB7ciBmYWN0b3IxfQpsaWJyYXJ5KGhhdmVuKQpsYXBvcDIxJGNvdW50ZmFpcjFyID0gYXMuZmFjdG9yKGxhcG9wMjEkY291bnRmYWlyMSkKYGBgCgpMdWVnbywgZXN0YXMgdmFyaWFibGVzIHNlIHRpZW5lbiBxdWUgZXRpcXVldGFyIHkgZ2VuZXJhciBsYXMgdGFibGFzIGRlc2NyaXB0aXZhcyBiw6FzaWNhcywgY29uIGVsIGNvbWFuZG8gYHRhYmxlYC4KCmBgYHtyIGV0aXF1ZXRhczF9CmxldmVscyhsYXBvcDIxJGNvdW50ZmFpcjFyKSA9IGMoIlNpZW1wcmUiLCAiQWxndW5hcyB2ZWNlcyIsICJOdW5jYSIpCnRhYmxlKGxhcG9wMjEkY291bnRmYWlyMXIpCmBgYAoKUGFyYSBjYWxjdWxhciBsYXMgdGFibGFzIGNvbiBwb3JjZW50YWplcywgcmVkb25kZWFkb3MgYSB1biBkZWNpbWFsLCB1c2Ftb3MgYHByb3AudGFibGVgIHkgYHJvdW5kYC4KTnVldmFtZW50ZSwgZXN0b3MgcG9yY2VudGFqZXMgbm8gc29uIGV4YWN0YW1lbnRlIGlndWFsZXMgYSBsb3MgcHJlc2VudGFkb3MgZW4gZWwgcmVwb3J0ZSBkZWJpZG8gYSBxdWUgZXN0b3MgY8OhbGN1bG9zIG5vIGluY2x1eWVuIGVsIGZhY3RvciBkZSBleHBhbnNpw7NuLgoKYGBge3IgcG9yY2VudGFqZXMxfQpyb3VuZChwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMjEkY291bnRmYWlyMXIpKSwgMykqMTAwCmBgYAoKQ29tbyBzZSBtZW5jaW9uw7MgZW4gbGEgc2VjY2nDs24gYW50ZXJpb3IsIHNlIHB1ZWRlIGdyYWZpY2FyIGVzdGEgdmFyaWFibGUgdXNhbmRvIGVsIGNvbWFuZG8gYGJhcnBsb3RgLgoKYGBge3IgYmFycmFzMX0KYmFycGxvdChwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMjEkY291bnRmYWlyMXIpKSoxMDApCmBgYAoKT3RyYSBvcGNpw7NuIGVzIGVsYWJvcmFyIGVsIGdyw6FmaWNvIGRlIGJhcnJhcyB1c2FuZG8gbGEgbGlicmVyw61hIGBnZ3Bsb3RgLgpVbmEgcHJpbWVyYSBvcGNpw7NuIGVzIHRyYWJhamFyIGRpcmVjdGFtZW50ZSBkZSBsYSBiYXNlIGRlIGRhdG9zLgpTaW4gZW1iYXJnbywgcHJvZHVjaXIgdW5hIHRhYmxhIGNvbiBsb3MgcmVzdWx0YWRvcyBkZXNkZSBsYSBiYXNlIGRlIGRhdG9zIHkgdXNhciBlc2EgdGFibGEgcGFyYSBwcm9kdWNpciB1biBncsOhZmljbyBlcyB1bmEgbWFuZXJhIG3DoXMgaW50dWl0aXZhLgoKU2UgcHVlZGUgY3JlYXIgdW5hIHRhYmxhIGRlIGZyZWN1ZW5jaWFzIGRlIGVzdGEgdmFyaWFibGUgY29uIGVsIGNvbWFuZG8gYHRhYmxlYCB5IGBwcm9wLnRhYmxlYC4KRXN0YSB0YWJsZSBzZSByZWRvbmRlYSBhIHVuIGRlY2ltYWwgY29uIGVsIGNvbWFuZG8gYHJvdW5kYCB5IHNlIGd1YXJkYSBjb21vIHVuIGRhdGFmcmFtZSBjb24gZWwgY29tYW5kbyBgYXMuZGF0YS5mcmFtZWAgZW4gdW4gb2JqZXRvICJjb3VudCIuCkVzdGEgdGFibGEgYWxtYWNlbmEgZG9zIGNvbHVtbmFzLCBsYSBwcmltZXJhIGxsYW1hZGEgIlZhcjEiIGNvbiBsYXMgZXRpcXVldGFzIGRlIGxhIHZhcmlhYmxlIHkgbGEgc2VndW5kYSBsbGFtYWRhICJGcmVxIiBjb24gbG9zIHBvcmNlbnRhamVzLgoKYGBge3IgdGFibGExYX0KY291bnQgPSBhcy5kYXRhLmZyYW1lKHJvdW5kKHByb3AudGFibGUodGFibGUobGFwb3AyMSRjb3VudGZhaXIxcikpLCAzKSoxMDApCmNvdW50CmBgYAoKUG9kZW1vcyB1c2FyIGVzdGEgdGFibGEgImNvdW50IiBwYXJhIHByb2R1Y2lyIGVsIGdyw6FmaWNvIGRlIGJhcnJhcyBjb24gZWwgY29tYW5kbyBgZ2dwbG90YC4KRW4gbGEgZXNwZWNpZmljYWNpw7NuIGBhZXNgIHNlIGRlZmluZSBxdWUgbG9zIHZhbG9yZXMgZGUgbGEgY29sdW1uYSAiVmFyMSIgc2UgcHJlc2VudGVuIGVuIGVsIGVqZSBYIHkgbG9zIHZhbG9yZXMgZGUgbGEgY29sdW1uYSBhICJGcmVxIiBlbiBlbCBlamUgWS4KU2UgZGVmaW5lIHVuIGdyw6FmaWNvIGRlIGJhcnJhcyBzaW1wbGUsIHVzYW5kbyBlbCBjb21hbmRvIGBnZW9tX2JhcigpYCwgZG9uZGUgaW50ZXJuYW1lbnRlIHNlIGRlZmluZSBlbCBhbmNobyBkZSBsYSBiYXJyYS4KQ29uIGxhIGVzcGVjaWZpY2FjacOzbiBgbGFic2Agc2UgZGVmaW5lIGxhcyBldGlxdWV0YXMgZGUgZWplcyB5IGVsICJjYXB0aW9uIi4KCmBgYHtyIGdnYmFycmFzMWN9CmdncGxvdChkYXRhPWNvdW50LCBhZXMoeD1WYXIxLCB5PUZyZXEpKSsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTAuNSkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShGcmVxLCAiJSIsIHNlcD0iIikpLCBjb2xvcj0id2hpdGUiLCAKICAgICAgICAgICAgcG9zaXRpb249cG9zaXRpb25fc3RhY2sodmp1c3Q9MC41KSwgc2l6ZT0zKSsKICBsYWJzKHg9IkxvcyB2b3RvcyBzZSBjdWVudGFuIGp1c3RhbWVudGUiLCB5PSJQb3JjZW50YWplIiwgCiAgICAgICBjYXB0aW9uPSJCYXLDs21ldHJvIGRlIGxhcyBBbcOpcmljYXMgcG9yIExBUE9QLCAyMDIxIikKYGBgCgpFbCBncsOhZmljbyAyLjUgcHJlc2VudGEgdW5hIGJhcnJhIGFwaWxhZGEgY29uIGxvcyBkYXRvcyBwb3IgY2FkYSBwYcOtcy4KUHJpbWVybyBwcmVzZW50YXJlbW9zIGVsIGdyw6FmaWNvIGRlIGJhcnJhcyBhcGlsYWRvIHVzYW5kbyBsb3MgZGF0b3MgZGUgdG9kYSBsYSByb25kYSAyMDIxIGRlbCBCYXLDs21ldHJvIGRlIGxhcyBBbcOpcmljYXMsIGVzIGRlY2lyIGRlIHRvZG9zIGxvcyBwYcOtc2VzLgpQYXJhIHByb2R1Y2lyIHVuYSBiYXJyYSBhcGlsYWRhIGhvcml6b250YWwsIHNlIHVzYXLDoSBsYSB2YXJpYWJsZSAiRnJlcSIgYWhvcmEgZW4gZWwgZWplIFguClNlIHVzYXLDoSBsYSBvcGNpw7NuIGBmaWxsYCBwYXJhIGRpdmlkaXIgZXN0YSBiYXJyYSBwb3IgbG9zIHZhbG9yZXMgZGUgbGEgdmFyaWFibGUgIlZhcjEiLgpDb21vIGVuIGVsIGVqZSBZIG5vIHNlIG1vc3RyYXLDoSB1bmEgdmFyaWFibGUgc2UgZGVmaW5lIGNvbW8gYCIiYC4KRGUgbGEgbWlzbWEgbWFuZXJhIHF1ZSBzZSBjYW1iaWFyb24gbGFzIHZhcmlhYmxlcyBlbiBsb3MgZWplcywgdGFtYmnDqW4gc2UgY2FtYmlhbiBsYXMgZXRpcXVldGFzIGVuIGBsYWJzYC4KRW4gZXN0YSBlc3BlY2lmaWNhY2nDs24gc2UgY2FtYmlhIGxhIGV0aXF1ZXRhIGRlIGxhIGxleWVuZGEgY29uIGBmaWxsYC4KCmBgYHtyIGdnYmFycmFzMWR9CmdncGxvdChkYXRhPWNvdW50LCBhZXMoZmlsbD1WYXIxLCB4PUZyZXEsIHk9IiIpKSsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTAuMykrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShGcmVxLCAiJSIsIHNlcD0iIikpLCBjb2xvcj0id2hpdGUiLCAKICAgICAgICAgICAgcG9zaXRpb249cG9zaXRpb25fc3RhY2sodmp1c3Q9MC41KSwgc2l6ZT0zKSsKICBsYWJzKHg9IlBvcmNlbnRhamUiLCB5PSIiLCBmaWxsPSJMb3Mgdm90b3Mgc2UgY3VlbnRhbiBqdXN0YW1lbnRlIiwKICAgICAgIGNhcHRpb249IkJhcsOzbWV0cm8gZGUgbGFzIEFtw6lyaWNhcyBwb3IgTEFQT1AsIDIwMjEiKQpgYGAKClBhcmEgcmVwbGljYXIgZWwgZ3LDoWZpY28gY29tcGFyYXRpdm8gcG9yIHBhw61zIHNlIHJlcXVpZXJlIGNyZWFyIGxhIHRhYmxhIGRlIGNvbnRpbmdlbmNpYSBlbnRyZSBsYSB2YXJpYWJsZSAiY291bnRmYWlyIiB5ICJwYWlzIi4KRXN0YSB0YWJsYSBjcnV6YWRhIHNlIGd1YXJkYSBlbiB1biBvYmpldG8gImNvdW50X3BhaXMiLgpTZSBkZWJlIG5vdGFyIHF1ZSBlbCBkYXRhZnJhbWUgcXVlIHNlIGNyZWEgY3JlYSB1bmEgZmlsYSBwb3IgY2FkYSB2YWxvciBkZSAiY291bnRmYWlyIiBlbiBjYWRhIHBhw61zLgpEZSBlc3RhIG1hbmVyYSB0ZW5lbW9zIDMgb3BjaW9uZXMgeCAyMCBwYcOtc2VzID0gNjAgZmlsYXMuCgpgYGB7ciB0YWJsYTFifQpjb3VudF9wYWlzID0gYXMuZGF0YS5mcmFtZShyb3VuZChwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMjEkcGFpcywgbGFwb3AyMSRjb3VudGZhaXIxciksIDEpLCAzKSoxMDApCmNvdW50X3BhaXMKYGBgCgpFbiBlc3RhIHRhYmxhIHNlIGNhbGN1bGFuIGxvcyBkYXRvcyBwb3IgY2FkYSB2YWxvciBkZSBsYSB2YXJpYWJsZSAicGFpcyIsIGluY2x1c28gY3VhbmRvIG5vIHNlIHRpZW5lIGRhdG9zIGRlIGxhIHZhcmlhYmxlICJjb3VudGZhaXIiLCBkZWJpZG8gYSBxdWUgbGEgcHJlZ3VudGEgbm8gc2UgcmVhbGl6w7MgZW4gZXNlIHBhw61zLgpQb3IgZXN0ZSBtb3Rpdm8gc2UgdGllbmVuIHF1ZSBlbGltaW5hciBsYXMgZmlsYXMgZGUgbG9zIHBhw61zZXMgZW4gbG9zIHF1ZSBubyBzZSByZWNvZ2nDsyBlc3RhIGluZm9ybWFjacOzbi4KRXN0byBzZSBoYWNlIGNvbiBsYSBlc3BlY2lmaWNhY2nDs24gYFstYyhmaWxhcyksXWAuCkx1ZWdvIHNlIGNyZWEgdW4gdmVjdG9yIGNvbiBsb3Mgbm9tYnJlcyBkZSBsb3MgcGHDrXNlcy4KRXN0YSBsaXN0YSBzZSByZXBpdGUgMyB2ZWNlcyAoMTUgcGHDrXNlcyByZXN0YW50ZXMgeCAzIG9wY2lvbmVzKS4KRXN0ZSB2ZWN0b3Igc2UgYWdyZWdhIGFsIGRhdGFmcmFtZSBlbiB1bmEgY29sdW1uYSAicGFpcyIuCgpgYGB7ciB0YWJsYTFjfQpjb3VudF9wYWlzID0gY291bnRfcGFpc1stYygxOjQsMTgsMjE6MjQsMzgsNDE6NDQsNTgpLF0KcGFpcyA9IGMoIk5pY2FyYWd1YSIsIkNvc3RhIFJpY2EiLCAiUGFuYW3DoSIsICJDb2xvbWJpYSIsICJFY3VhZG9yIiwgIkJvbGl2aWEiLCAiUGVyw7oiLAogICAgICAgICJQYXJhZ3VheSIsICJDaGlsZSIsICJVcnVndWF5IiwgIkJyYXNpbCIsICJBcmdlbnRpbmEiLCAiUmVwLiBEb20uIiwiSmFtYWljYSIsICJHdXlhbmEiLCAiTmljYXJhZ3VhIiwiQ29zdGEgUmljYSIsICJQYW5hbcOhIiwgIkNvbG9tYmlhIiwgIkVjdWFkb3IiLCAiQm9saXZpYSIsICJQZXLDuiIsCiAgICAgICAgIlBhcmFndWF5IiwgIkNoaWxlIiwgIlVydWd1YXkiLCAiQnJhc2lsIiwgIkFyZ2VudGluYSIsICJSZXAuIERvbS4iLCJKYW1haWNhIiwgIkd1eWFuYSIsIk5pY2FyYWd1YSIsIkNvc3RhIFJpY2EiLCAiUGFuYW3DoSIsICJDb2xvbWJpYSIsICJFY3VhZG9yIiwgIkJvbGl2aWEiLCAiUGVyw7oiLAogICAgICAgICJQYXJhZ3VheSIsICJDaGlsZSIsICJVcnVndWF5IiwgIkJyYXNpbCIsICJBcmdlbnRpbmEiLCAiUmVwLiBEb20uIiwiSmFtYWljYSIsICJHdXlhbmEiKQpjb3VudF9wYWlzJHBhaXMgPSBwYWlzCmNvdW50X3BhaXMKYGBgCgpDb24gZXN0ZSBkYXRhZnJhbWUgImNvdW50X3BhaXMiIHlhIHRlbmVtb3MgbG9zIGVsZW1lbnRvcyBwYXJhIHJlcGxpY2FyIGVsIGdyw6FmaWNvIGRlIGJhcnJhcyBhcGlsYWRhcy4KRW4gbGEgZXNwZWNpZmljYWNpw7NuIGBhZXNgIHNlIGRlZmluZSBxdWUgZW4gZWwgZWplIFggc2UgZ3JhZmlxdWVuIGxvcyBwb3JjZW50YWplcywgZW4gZWwgZWplIFkgbG9zIHBhw61zZXMgeSBjYWRhIGJhcnJhIHNlIGRpdmlkYSBwb3IgbGEgY29sdW1uYSBWYXIyLgoKYGBge3IgZ2diYXJyYXMxZX0KZ2dwbG90KGRhdGE9Y291bnRfcGFpcywgYWVzKHg9RnJlcSwgeT1wYWlzLCBmaWxsPVZhcjIpKSsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTAuMykrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShGcmVxLCAiJSIsIHNlcD0iIikpLCBjb2xvcj0id2hpdGUiLCAKICAgICAgICAgICAgcG9zaXRpb249cG9zaXRpb25fc3RhY2sodmp1c3Q9MC41KSwgc2l6ZT0yKSsKICBsYWJzKHg9IlBvcmNlbnRhamUiLCB5PSJQYcOtcyIsIGZpbGw9IkxvcyB2b3RvcyBzZSBjdWVudGFuIGp1c3RhbWVudGUiLAogICAgICAgY2FwdGlvbj0iQmFyw7NtZXRybyBkZSBsYXMgQW3DqXJpY2FzIHBvciBMQVBPUCwgMjAyMSIpCmBgYAoKIyBGcmVjdWVuY2lhIGRlIHVzbyBkZSByZWRlcyBzb2NpYWxlcwoKRW4gbGEgcm9uZGEgMjAxOC8xOSBzZSBldmFsdcOzIGVsIHVzbyBkZSByZWRlcyBzb2NpYWxlcy4KRGUgZXN0YSBtYW5lcmEsIHNlIGFuYWxpemFyb24gbGFzIHZhcmlhYmxlcyBTTUVESUEyLgrCv0NvbiBxdcOpIGZyZWN1ZW5jaWEgdmUgY29udGVuaWRvIGVuIEZhY2Vib29rPywKU01FRElBNS7Cv0NvbiBxdcOpIGZyZWN1ZW5jaWEgdmUgY29udGVuaWRvIGVuIFR3aXR0ZXI/CnkgU01FRElBOC7Cv0NvbiBxdcOpIGZyZWN1ZW5jaWEgdXNhIFdoYXRzYXBwPwpFc3RhcyB2YXJpYWJsZXMgdGllbmVuIGNvbW8gb3BjaW9uZXMgZGUgcmVzcHVlc3RhOgoKMS4gIERpYXJpYW1lbnRlCjIuICBBbGd1bmFzIHZlY2VzIGEgbGEgc2VtYW5hCjMuICBBbGd1bmFzIHZlY2VzIGFsIG1lcwo0LiAgQWxndW5hcyB2ZWNlcyBhbCBhw7FvCjUuICBOdW5jYQoKRGUgbGEgbWlzbWEgbWFuZXJhIHF1ZSBjb24gbGFzIHZhcmlhYmxlcyBub21pbmFsZXMsIGVzdGFzIHZhcmlhYmxlcyB0aWVuZW4gcXVlIHNlciBkZWNsYXJhZGFzIGNvbW8gImZhY3RvciIgZW4gbnVldmFzIHZhcmlhYmxlcy4KCmBgYHtyIGZhY3RvcjJ9CmxhcG9wMTgkc21lZGlhMnIgPSBhcy5mYWN0b3IobGFwb3AxOCRzbWVkaWEyKQpsYXBvcDE4JHNtZWRpYTVyID0gYXMuZmFjdG9yKGxhcG9wMTgkc21lZGlhNSkKbGFwb3AxOCRzbWVkaWE4ciA9IGFzLmZhY3RvcihsYXBvcDE4JHNtZWRpYTgpCmBgYAoKTGEgbm90YSBhIHBpZSAxNSBkZWwgcmVwb3J0ZSBpbmRpY2EgcXVlICJsb3MgZW50cmV2aXN0YWRvcyBxdWUgcmVwb3J0YW4gbnVuY2EgdmVyIGNvbnRlbmlkbyBlbiBGYWNlYm9vayB5IFR3aXR0ZXIsIHkgcXVpZW5lcyBpbmRpY2FuIHF1ZSBudW5jYSB1c2FuIFdoYXRzYXBwLCBzb24gY29uc2lkZXJhZG9zIGNvbW8gbm8gdXN1YXJpb3MgZGUgZXN0YXMgcmVkZXMgc29jaWFsZXMiIChwLiA2NCkuClBvciBlc3RlIG1vdGl2bywgZWwgZ3LDoWZpY28gMy4zIGRlIGZyZWN1ZW5jaWEgZGUgdXNvIGRlIHJlZGVzIHNvY2lhbGVzIChwYWcuIDU3KSBzb2xvIGluY2x1eWVuIGxhcyBjYXRlZ29yw61hcyAiRGlhcmlhbWVudGUiLCAiQWxndW5hcyB2ZWNlcyBhIGxhIHNlbWFuYSIsICJBbGd1bmFzIHZlY2VzIGFsIG1lcyIgeSAiQWxndW5hcyB2ZWNlcyBhbCBhw7FvIi4KU2UgZXhjbHV5YSBsYSBjYXRlZ29yw61hICJOdW5jYSIuCgohW10oR3JhZjMuMy5wbmcpe3dpZHRoPSIzOTgifQoKRW4gbGFzIG51ZXZhcyB2YXJpYWJsZXMgdmFtb3MgYSBkZWNsYXJhciBlbCB2YWxvciA1LCBjb3JyZXNwb25kaWVudGUgYSAibnVuY2EiLCBjb21vICJOQSIsIGVzIGRlY2lyLCBjb21vIHZhbG9yIHBlcmRpZG8gZW4gUi4KCmBgYHtyIGVsaW1pbmFyfQpsaWJyYXJ5KGNhcikKbGFwb3AxOCRzbWVkaWEyciA9IGNhcjo6cmVjb2RlKGxhcG9wMTgkc21lZGlhMnIsICI1PU5BIikKbGFwb3AxOCRzbWVkaWE1ciA9IGNhcjo6cmVjb2RlKGxhcG9wMTgkc21lZGlhNXIsICI1PU5BIikKbGFwb3AxOCRzbWVkaWE4ciA9IGNhcjo6cmVjb2RlKGxhcG9wMTgkc21lZGlhOHIsICI1PU5BIikKYGBgCgpMdWVnbywgZXN0YXMgdmFyaWFibGVzIHNlIHRpZW5lbiBxdWUgZXRpcXVldGFyIHkgZ2VuZXJhciBsYXMgdGFibGFzIGRlc2NyaXB0aXZhcyBiw6FzaWNhcywgY29uIGVsIGNvbWFuZG8gYHRhYmxlYC4KCmBgYHtyIGV0aXF1ZXRhMn0KbGV2ZWxzKGxhcG9wMTgkc21lZGlhMnIpID0gYygiRGlhcmlhbWVudGUiLCAiQWxndW5hcyB2ZWNlcyBhIGxhIHNlbWFuYSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFsZ3VuYXMgdmVjZXMgYWwgbWVzIiwgIkFsZ3VuYXMgdmVjZXMgYWwgYcOxbyIpCmxldmVscyhsYXBvcDE4JHNtZWRpYTVyKSA9IGMoIkRpYXJpYW1lbnRlIiwgIkFsZ3VuYXMgdmVjZXMgYSBsYSBzZW1hbmEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBbGd1bmFzIHZlY2VzIGFsIG1lcyIsICJBbGd1bmFzIHZlY2VzIGFsIGHDsW8iKQpsZXZlbHMobGFwb3AxOCRzbWVkaWE4cikgPSBjKCJEaWFyaWFtZW50ZSIsICJBbGd1bmFzIHZlY2VzIGEgbGEgc2VtYW5hIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWxndW5hcyB2ZWNlcyBhbCBtZXMiLCAiQWxndW5hcyB2ZWNlcyBhbCBhw7FvIikKdGFibGUobGFwb3AxOCRzbWVkaWEycikKdGFibGUobGFwb3AxOCRzbWVkaWE1cikKdGFibGUobGFwb3AxOCRzbWVkaWE4cikKYGBgCgpQYXJhIGNhbGN1bGFyIGxhcyB0YWJsYXMgY29uIHBvcmNlbnRhamVzLCByZWRvbmRlYWRvcyBhIHVuIGRlY2ltYWwsIHVzYW1vcyBgcHJvcC50YWJsZWAgeSBgcm91bmRgLgpOdWV2YW1lbnRlLCBlc3RvcyBwb3JjZW50YWplcyBubyBzb24gZXhhY3RhbWVudGUgaWd1YWxlcyBhIGxvcyBwcmVzZW50YWRvcyBlbiBlbCByZXBvcnRlIGRlYmlkbyBhIHF1ZSBlc3RvcyBjw6FsY3Vsb3Mgbm8gaW5jbHV5ZW4gZWwgZmFjdG9yIGRlIGV4cGFuc2nDs24uCgpgYGB7ciBwb3JjZW50YWplczJ9CnJvdW5kKHByb3AudGFibGUodGFibGUobGFwb3AxOCRzbWVkaWEycikpLCAzKSoxMDAKcm91bmQocHJvcC50YWJsZSh0YWJsZShsYXBvcDE4JHNtZWRpYTVyKSksIDMpKjEwMApyb3VuZChwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMTgkc21lZGlhOHIpKSwgMykqMTAwCmBgYAoKUGFyYSBwcmVzZW50YXIgdG9kb3MgbG9zIGRhdG9zIGVuIHVuYSB0YWJsYSBjb25qdW50YSwgc2UgZ3VhcmRhIGxhIHRhYmxhIGRlIGNhZGEgcmVkIHNvY2lhbCBlbiB1biBudWV2byBvYmpldG8gZGUgUiAobGxhbWFkbyBjb21vIGNhZGEgcmVkIHNvY2lhbCkuCkx1ZWdvLCB0b2RhcyBlc3RhcyB0YWJsYXMgcGFyY2lhbGVzLCBxdWUgY29udGllbmVuIGxhcyBtaXNtYXMgb3BjaW9uZXMgZGUgcmVzcHVlc3RhLCBzZSB1bmVuIGNvbW8gZmlsYXMgY29uIGVsIGNvbWFuZG8gYHJiaW5kYC4KRXN0YSBudWV2YSB0YWJsYSBjb25qdW50YSBzZSBndWFyZGEgY29tbyB1biBudWV2byBkYXRhZnJhbWUgInRhYmxhIi4KCmBgYHtyIHRhYmxhMmF9CkZhY2Vib29rID0gcm91bmQocHJvcC50YWJsZSh0YWJsZShsYXBvcDE4JHNtZWRpYTJyKSksIDMpKjEwMApUd2l0dGVyID0gcm91bmQocHJvcC50YWJsZSh0YWJsZShsYXBvcDE4JHNtZWRpYTVyKSksIDMpKjEwMApXaGF0c2FwcCA9IHJvdW5kKHByb3AudGFibGUodGFibGUobGFwb3AxOCRzbWVkaWE4cikpLCAzKSoxMDAKdGFibGEgPSBhcy5kYXRhLmZyYW1lKHJiaW5kKEZhY2Vib29rLCBUd2l0dGVyLCBXaGF0c2FwcCkpCnRhYmxhCmBgYAoKUGFyYSB0ZW5lciB1bmEgbWVqb3IgcHJlc2VudGFjacOzbiBkZSBsYSB0YWJsYSwgc2UgcHVlZGUgdXNhciBlbCBjb21hbmRvIGBrYWJsZWAgZGVsIHBhcXVldGUgYGtuaXRyYCBvIGVsIGNvbWFuZG8gYGZvcm1hdHRhYmxlYCBkZWwgcGFxdWV0ZSBkZWwgbWlzbW8gbm9tYnJlLgoKYGBge3IgdGFibGEgbWVqb3JhZGF9CmxpYnJhcnkoa25pdHIpCmthYmxlKGhlYWQodGFibGEpLCBmb3JtYXQ9Im1hcmtkb3duIiwgZGlnaXRzPTEpCmxpYnJhcnkoZm9ybWF0dGFibGUpCmZvcm1hdHRhYmxlKHRhYmxhKQpgYGAKClBhcmEgZ3JhZmljYXIgZXN0YSB2YXJpYWJsZSwgdmFtb3MgYSB0cmFiYWphciBkaXJlY3RhbWVudGUgZGVzZGUgbGEgdGFibGEgY3JlYWRhIGNvbiBsb3MgcG9yY2VudGFqZXMgZGUgbGFzIHRyZXMgcmVkZXMgc29jaWFsZXMuCkVzdGEgdGFibGEgdGllbmUgYSBjYWRhIHJlZCBzb2NpYWwgZW4gbGFzIGZpbGFzIHkgbGFzIG9wY2lvbmVzIGRlIHJlc3B1ZXN0YSBlbiBsYXMgY29sdW1uYXMuClBhcmEgcG9kZXIgZ3JhZmljYXIgZXN0b3MgZGF0b3Mgc2UgcmVxdWllcmUgcXVlIGxhcyByZWRlcyBzb2NpYWxlcyBlc3TDqW4gZW4gbGFzIGNvbHVtbmFzIHkgbGFzIG9wY2lvbmVzIGRlIHJlc3B1ZXN0YSBlbiBsYXMgZmlsYXMsIHBvciBsbyBxdWUgZW4gcHJpbWVyIGx1Z2FyIHZhbW9zIGEgdHJhbnNwb25lciBlc3RhIHRhYmxhLgpFc3RlIHByb2NlZGltaWVudG8gbG8gaGFjZW1vcyB1c2FuZG8gbGEgbGlicmVyw61hIGBkYXRhLnRhYmxlYCB5IGVsIGNvbWFuZG8gYHRyYW5zcG9zZWAuCkVzdG9zIGRhdG9zIHRyYW5zcHVlc3RvcyBsb3MgZ3VhcmRhbW9zIGVuIHVuYSBudWV2YSB0YWJsYSAidGFibGFfdHIiLgoKRXN0ZSBjb21hbmRvIHRyYW5zcG9uZSBsb3MgZGF0b3MsIHBlcm8gZGVqYSBzaW4gbm9tYnJhciBsYXMgZmlsYXMgeSBjb2x1bW5hcy4KUHJpbWVybyBzZSBub21icmFuIGxhcyBjb2x1bW5hcyBjb24gZWwgY29tYW5kbyBgY29sbmFtZXNgIHVzYW5kbyBsb3Mgbm9tYnJlcyBkZSBsYXMgZmlsYXMgZGUgInRhYmxhIi4KTHVlZ28gc2Ugbm9tYnJhbiBsYXMgZmlsYXMgY29uIGVsIGNvbWFuZG8gYHJvd25hbWVzYCB1c2FuZG8gbG9zIG5vbWJyZXMgZGUgbGFzIGNvbHVtbmFzIGRlICJ0YWJsYSIuCgpGaW5hbG1lbnRlLCByZXF1ZXJpbW9zIHVuYSBjb2x1bW5hIGRlbnRybyBkZSAidGFibGFfdHIiIHF1ZSBpbmNsdXlhIGxhcyBldGlxdWV0YXMgZGUgcmVzcHVlc3RhIGRlIGxhcyBwcmVndW50YXMgZGUgc21lZGlhLgpFc3RhcyBldGlxdWV0YXMgZXN0w6FuIGNvbW8gbm9tYnJlcyBkZSBmaWxhcy4KUGFyYSBpbmNsdWlybGFzIGNvbW8gdW5hIHZhcmlhYmxlIG3DoXMsIHNlIGFncmVnYSB1bmEgdmFyaWFibGUgInRhYmxhX3RyXCRsYWIiIGFsIHF1ZSBzZSBsZSBhc2lnbmEgbG9zIG5vbWJyZXMgZGUgbGFzIGZpbGFzIGNvbiBgcm93Lm5hbWVzYC4KCmBgYHtyIHRhYmxhIHRyYW5zcHVlc3RhLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGRhdGEudGFibGUpCnRhYmxhX3RyID0gZGF0YS5mcmFtZSh0KHRhYmxhW10pKQpjb2xuYW1lcyh0YWJsYV90cikgPSByb3duYW1lcyh0YWJsYSkKcm93bmFtZXModGFibGFfdHIpID0gY29sbmFtZXModGFibGEpCnRhYmxhX3RyJGxhYiA9IHJvd25hbWVzKHRhYmxhX3RyKQp0YWJsYV90cgpgYGAKCkVuIHNlZ3VuZG8gbHVnYXIsIHNlIGFjdGl2YSBsYSBsaWJyZXLDrWEgYGdncGxvdDJgIHBhcmEgZ3JhZmljYXIgbG9zIGRhdG9zIGd1YXJkYWRvcyBlbiAidGFibGFfdHIiIGNvbiBlbCBjb21hbmRvIGBnZ3Bsb3RgLgpEZW50cm8gZGUgZXN0ZSBjb21hbmRvIHNlIGVzcGVjaWZpY2EgcXVlIHNlIHRyYWJhamFyw6EgY29uIGVsIGRhdGFmcmFtZSAidGFibGFfdHIiIChubyBjb24gbGFwb3AxOCkgeSBzZSBlc3BlY2lmaWNhIGxhICJlc3TDqXRpY2EiLCBlcyBkZWNpciBxdWUgZW4gZWwgZWplIFggbm8gc2UgaW5jbHVpcsOhIHVuYSB2YXJpYWJsZSwgcXVlIGVuIGVsIGVqZSBZIHNlIGluY2x1aXLDoSBsb3MgZGF0b3MgZGUgIkZhY2Vib29rIiBkZWwgZGF0YWZyYW1lICJ0YWJsYV90ciIgeSBxdWUgc2UgZGl2aWRpcsOhIHBvciBjYXRlZ29yw61hcyBkZSBsYSB2YXJpYWJsZSBndWFyZGFkYXMgZW4gImxhYiIuCkx1ZWdvIHNlIGHDsWFkZSBsYSBjYXBhIGBnZW9tX2JhcmAgcGFyYSBpbmRpY2FyIHF1ZSBzZSBncmFmaWNhcsOhIGVuIGJhcnJhcyBkZSBhbmNobyAoYHdpZHRoYCkgMSB5IHF1ZSBsYSBiYXJyYSByZXBsaWNhcsOhIGxvIGVzcGVjaWZpY2FkbyBlbiBsYSBlc3TDqXRpY2EgKGBzdGF0PSJpZGVudGl0eSJgKS4KQ29uIGBnZW9tX3RleHRgIHNlIGFncmVnYSBsYXMgZXRpcXVldGFzIGRlIGxvcyBkYXRvcywgY29uIGVsIHPDrW1ib2xvIGRlIHBvcmNlbnRhamUsIHkgc2UgZXNwZWNpZmljYSBsYSBwb3NpY2nDs24gZGVsIHRleHRvIGNvbiBgcG9zaXRpb249cG9zaXRpb25fc3RhY2so4oCmKWAgeSBlbCB0YW1hw7FvIGNvbiBgc2l6ZT0zYC4KQ29uIGBjb29yZF9wb2xhcmAgc2UgdHJhbnNmb3JtYSBsYXMgYmFycmFzIGVuIHVuIGdyw6FmaWNvIGNpcmN1bGFyIGRlIHNlY3RvcmVzLgpGaW5hbG1lbnRlLCBzZSBkZWZpbmUgZWwgInRlbWEiIGNvbiBgdGhlbWVfdm9pZGAgaW5kaWNhbmRvIHVuIGZvbmRvIGJsYW5jbyB5IHNlIG1vZGlmaWNhIGxhIGV0aXF1ZXRhIGRlIGxhIGxleWVuZGEgY29uIGBzY2FsZV9maWxsX2Rpc2NyZXRlYC4KCmBgYHtyIGdyYWZpY28gcGllfQpsaWJyYXJ5KGdncGxvdDIpCmdncGxvdChkYXRhPXRhYmxhX3RyLCBhZXMoeD0iIiwgeT1GYWNlYm9vaywgZmlsbD1sYWIpKSsKICBnZW9tX2Jhcih3aWR0aD0xLCBzdGF0PSJpZGVudGl0eSIpKwogIGdlb21fdGV4dChhZXMobGFiZWw9cGFzdGUoRmFjZWJvb2ssICIlIiwgc2VwPSIiKSksIGNvbG9yPSJ3aGl0ZSIsIAogICAgICAgICAgICBwb3NpdGlvbj1wb3NpdGlvbl9zdGFjayh2anVzdD0wLjUpLCBzaXplPTMpKwogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQ9MCkrCiAgdGhlbWVfdm9pZCgpKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iRnJlY3VlbmNpYSBkZSB1c28gZGUgRmFjZWJvb2siKQpgYGAKCkVuIGVsIGdyw6FmaWNvIDMuMyBkZWwgcmVwb3J0ZSAiRWwgUHVsc28gZGUgbGEgRGVtb2NyYWNpYSIgc2UgcHJlc2VudGEgdW4gZ3LDoWZpY28gY2lyY3VsYXIgdGlwbyAiZG9uYSIuClBhcmEgcmVwcm9kdWNpciBleGFjdGFtZW50ZSBlc3RlIHRpcG8gZGUgZ3LDoWZpY28sIHNlIHRpZW5lIHF1ZSBhY29tb2RhciB1bm9zIGRldGFsbGVzIGRlIGxhIHNpbnRheGlzIGFudGVyaW9yLgpTZSBlc3RhYmxlY2UgIng9MiIgZW4gbGEgImVzdMOpdGljYSIgeSBzZSBlc3RhYmxlY2UgbMOtbWl0ZXMgZW4gZWwgZWplIFgsIGVudHJlIDAuNSB5IDIuNSwgcGFyYSBxdWUgY3VhbmRvIHNlIHJvdGUgZWwgZWplLCBzZSBjcmVlIGVsICJodWVjbyIgZGVudHJvIGRlbCBjw61yY3Vsby4KCmBgYHtyIGRvbmF9CmdncGxvdChkYXRhPXRhYmxhX3RyLCBhZXMoeD0yLCB5PUZhY2Vib29rLCBmaWxsPWxhYikpKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShGYWNlYm9vaywgIiUiLCBzZXA9IiIpKSwgY29sb3I9IndoaXRlIiwgCiAgICAgICAgICAgIHBvc2l0aW9uPXBvc2l0aW9uX3N0YWNrKHZqdXN0PTAuNSksIHNpemU9MykrCiAgY29vcmRfcG9sYXIoInkiKSsKICB0aGVtZV92b2lkKCkrCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJGcmVjdWVuY2lhIGRlIHVzbyBkZSBGYWNlYm9vayIpKwogICBsYWJzKHRpdGxlPSJGcmVjdWVuY2lhIGNvbiBsYSBxdWUgdmUgY29udGVuaWRvIGVuIEZhY2ViYm9rIiwgCiAgICAgICAgY2FwdGlvbj0iQmFyw7NtZXRybyBkZSBsYXMgQW3DqXJpY2FzIHBvciBMQVBPUCwgMjAxOC8xOSIpKwogIHhsaW0oMC41LCAyLjUpCmBgYAoKUGFyYSByZXBsaWNhciBlbCBncsOhZmljbyBkZSBiYXJyYXMsIHNlIGhhY2VuIGFsZ3VuYXMgbW9kaWZpY2FjaW9uZXMgZW4gZWwgY8OzZGlnbyBhbnRlcmlvci4KUG9yIGVqZW1wbG8sIGVuIGxhICJlc3TDqXRpY2EiLCBhaG9yYSBzZSBpbmRpY2EgcXVlIGVuIGVsIGVqZSBYIHZhIGxhIHZhcmlhYmxlICJzbWVkaWEyciIgeSBlbiBlbCBlamUgWSBlbCBwb3JjZW50YWplICJwZXIiLgpTZSBlbGltaW5hLCBhZGVtw6FzLCBsYSBlc3BlY2lmaWNhY2nDs24gZGUgbGFzIGNvb3JkZW5hZGFzIHBvbGFyZXMuClNlIGFncmVnYSB1biB0w610dWxvIGFsIGdyw6FmaWNvLCBldGlxdWV0YXMgYSBsb3MgZWplcyB5IHVuIGNhcHRpb24gY29uIGxhIGVzcGVjaWZpY2FjacOzbiBgbGFic2AuCkZpbmFsbWVudGUsIHNlIGRlZmluZSBlbCBlamUgWSBlbnRyZSAwIHkgNjAgY29uIGxhIGVzcGVjaWZpY2FjacOzbiBgY29vcmRfY2FydGVzaWFuYC4KVW4gdGVtYSBpbXBvcnRhbnRlIGVzIHF1ZSBlc3RlIGdyw6FmaWNvIHRhbWJpw6luIHNlIHB1ZWRlIGd1YXJkYXIgZW4gdW4gb2JqZXRvIGVuIFIsIHF1ZSBsbGFtYXJlbW9zICJncmFmMSIuCgpgYGB7ciBncmFmaWNvIGRlIGJhcnJhc30KZ3JhZjEgPSBnZ3Bsb3QodGFibGFfdHIsIGFlcyh4PWxhYiwgeT1GYWNlYm9vaykpKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgIHdpZHRoPTAuNSkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShGYWNlYm9vaywgIiUiLCBzZXA9IiIpKSwgY29sb3I9ImJsYWNrIiwgdmp1c3Q9LTAuNSkrCiAgbGFicyh0aXRsZT0iRnJlY3VlbmNpYSBkZSB1c28gZGUgcmVkZXMgc29jaWFsZXMiLCB4PSJGcmVjdWVuY2lhIGRlIHVzbyBkZSBGYWNlYm9vayIsIHk9IlBvcmNlbnRhamUiLCBjYXB0aW9uPSJCYXLDs21ldHJvIGRlIGxhcyBBbcOpcmljYXMgcG9yIExBUE9QLCAyMDE4LzE5IikrCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLCA2MCkpCmdyYWYxCmBgYAoKR3VhcmRhciB1biBncsOhZmljbyBlbiB1biBvYmpldG8gbm9zIHBlcm1pdGUgbHVlZ28gaW5jb3Jwb3JhciBtw6FzIGNhcGFzIG8gbWVqb3JhcyBlbiBlbCBncsOhZmljby4KRWwgZ3LDoWZpY28gYW50ZXJpb3IsIHBvciBlamVtcGxvLCB0aWVuZSBsYXMgZXRpcXVldGFzIGRlICJGcmVjdWVuY2lhIGRlIHVzbyIgZW4gdW5hIHNvbGEgbMOtbmVhLCBwb3IgbG8gc2UgcG9kcsOtYW4gdHJhc3BvbmVyLgpQYXJhIG1lam9yYXIgZXN0YSB2aXN1YWxpemFjacOzbiBzZSBwdWVkZSBpbmNsaW5hciBlc3RhcyBldGlxdWV0YXMsIHBlcm8gc2kgc2UgcXVpc2llcmEgbWFudGVuZXIgbGEgaG9yaXpvbnRhbGlkYWQgcGFyYSBmYWNpbGl0YXIgbGEgbGVjdHVyYSwgbG8gcXVlIHNlIHB1ZWRlIGhhY2VyIGVzIHNlcGFyYXIgbGFzIGV0aXF1ZXRhcyBsYXJnYXMgZW4gZG9zIG8gbcOhcyBsw61uZWFzLgpFc3RvIHNlIHB1ZWRlIGhhY2VyLCBwb3IgZWplbXBsbywgY3JlYW5kbyB1biB2ZWN0b3IgY29uIGxhcyBudWV2YXMgZXRpcXVldGFzLgpMYXMgZXRpcXVldGFzIGxhcmdhcyBzZSBwdWVkZW4gcGFydGlyIGVuIGzDrW5lYXMgbWVkaWFudGUgbGEgaW5jbHVzacOzbiBkZSBgXG5gIGVudHJlIGxvcyB0ZXh0b3MgcXVlIHNlIHF1aWVyYSBzZXBhcmFyLgpMdWVnbywgYWwgb2JqZXRvICJncmFmMSIgc2UgbGUgcHVlZGUgYWdyZWdhciB1bmEgbnVldmEgY2FwYSBwYXJhIHJlZW1wbGF6YXIgbGFzIGV0aXF1ZXRhcyBjb24gbGFzIG51ZXZhcyBkaXZpZGlkYXMgZW4gbMOtbmVhcy4KRXN0byBzZSBoYWNlIGNvbiBsYSBlc3BlY2lmaWNhY2nDs24gYHNjYWxlX3hfZGlzY3JldGVgIGRvbmRlIHNlIGluZGljYSBxdWUgbGFzIGV0aXF1ZXRhcyB1c2VuIGVsIHZlY3RvciBjcmVhZG8uCgpgYGB7ciBldGlxdWV0YXMgc3VwZXJwdWVzdGFzfQpldGlxID0gYygiRGlhcmlhbWVudGUiLCAiQWxndW5hcyB2ZWNlc1xuYSBsYSBzZW1hbmEiLCAiQWxndW5hcyB2ZWNlc1xuYWwgbWVzIiwgCiAgICAgICAgICAiQWxndW5hcyB2ZWNlc1xuYWwgYcOxbyIpCmdyYWYxICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1ldGlxKQpgYGAKCkRlIGVzdGEgbWFuZXJhIGVsIGdyw6FmaWNvIHF1ZWRhIG3DoXMgbGVnaWJsZS4KSGFzdGEgYXF1w60gc2UgaGEgcmVwbGljYWRvIGxhcyB0YWJsYXMgeSBncsOhZmljb3MgcXVlIHNlIHVzYXJvbiBjb24gbGFzIHZhcmlhYmxlcyBub21pbmFsZXMsIGFob3JhIHVzYW5kbyB2YXJpYWJsZXMgb3JkaW5hbGVzLgpTaSBzZSBxdWllcmUgcmVwbGljYXIgZWwgZ3LDoWZpY28gY2lyY3VsYXIgZGUgbGFzIG90cmFzIHJlZGVzIHNvY2lhbGVzLCBzZSBwdWVkZSBlamVjdXRhciBlbCBtaXNtbyBjw7NkaWdvLCBwZXJvIGNhbWJpYW5kbyBsYSBjb2x1bW5hIGRlIGxhIHJlZCBzb2NpYWwuClBhcmEgVHdpdHRlciwgcG9yIGVqZW1wbG8sIHNlIHRlbmRyw61hLgoKYGBge3IgZ3JhZmljbyBUd2l0dGVyfQpncmFmMiA9IGdncGxvdChkYXRhPXRhYmxhX3RyLCBhZXMoeD0yLCB5PVR3aXR0ZXIsIGZpbGw9bGFiKSkrCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXBhc3RlKFR3aXR0ZXIsICIlIiwgc2VwPSIiKSksIGNvbG9yPSJ3aGl0ZSIsIAogICAgICAgICAgICBwb3NpdGlvbj1wb3NpdGlvbl9zdGFjayh2anVzdD0wLjUpLCBzaXplPTMpKwogIGNvb3JkX3BvbGFyKCJ5IikrCiAgdGhlbWVfdm9pZCgpKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iRnJlY3VlbmNpYSBkZSB1c28gZGUgVHdpdHRlciIpKwogICBsYWJzKHRpdGxlPSJGcmVjdWVuY2lhIGNvbiBsYSBxdWUgdmUgY29udGVuaWRvIGVuIFR3aXR0ZXIiLCAKICAgICAgICBjYXB0aW9uPSJCYXLDs21ldHJvIGRlIGxhcyBBbcOpcmljYXMgcG9yIExBUE9QLCAyMDE4LzE5IikrCiAgeGxpbSgwLjUsIDIuNSkKZ3JhZjIKYGBgCgojIyBDcnVjZSBkZSB2YXJpYWJsZXMKCkVuIGxhIHRhYmxhIDMuMSAocGFnLiA1NSkgZGVsIHJlcG9ydGUgIkVsIHB1bHNvIGRlIGxhIGRlbW9jcmFjaWEiIHNlIHByZXNlbnRhIGxvcyBwb3JjZW50YWplcyBkZSB1c28gZGUgbGFzIHJlZGVzIHNvY2lhbGVzIHBvciBwYcOtcy4KTHVlZ28sIGVuIGxhIHDDoWdpbmEgNTYgc2UgcHJlc2VudGEgdW4gY3VhZHJvIGNvbiBlbCBwb3JjZW50YWplIGRlIHVzdWFyaW9zIGRlIHJlZGVzIHNvY2lhbGVzIHBvciBjYXJhY3RlcsOtc3RpY2FzIHNvY2lvZGVtb2dyw6FmaWNhcywgcG9yIGVqZW1wbG8sIHVyYmFuby9ydXJhbCwgaG9tYnJlLCBlZGFkIHByb21lZGlvLCByaXF1ZXphIHByb21lZGlvIHkgYcOxb3MgZGUgZXN0dWRpby4KCiFbXSh0YWJsYTMuMS5wbmcpe3dpZHRoPSI0ODEifQoKRW1wZXphcmVtb3MgcmVwbGljYW5kbyBsb3MgZGF0b3MgZ2VuZXJhbGVzIGRlbCB1c28gZGUgcmVkZXMgc29jaWFsZXMgcXVlIHNlIHJlcG9ydGEgZW4gZWwgZ3LDoWZpY28gMy4xLgpQYXJhIHJlcGxpY2FyIGVzdGEgdGFibGEgcHJpbWVybyBzZSB0aWVuZSBxdWUgZGVmaW5pciBsYSB2YXJpYWJsZSAicGFpcyIgeSBsYXMgdmFyaWFibGVzIGRlIHVzbyBkZSByZWRlcyBzb2NpYWxlcyAoc21lZGlhMSwgc21lZGlhNCB5IHNtZWRpYTcpLgoKYGBge3IgcGHDrXN9CmxhcG9wMTgkc21lZGlhMXIgPSBhcy5mYWN0b3IobGFwb3AxOCRzbWVkaWExKQpsYXBvcDE4JHNtZWRpYTRyID0gYXMuZmFjdG9yKGxhcG9wMTgkc21lZGlhNCkKbGFwb3AxOCRzbWVkaWE3ciA9IGFzLmZhY3RvcihsYXBvcDE4JHNtZWRpYTcpCmxldmVscyhsYXBvcDE4JHNtZWRpYTFyKSA9IGMoIlPDrSIsICJObyIpCmxldmVscyhsYXBvcDE4JHNtZWRpYTRyKSA9IGMoIlPDrSIsICJObyIpCmxldmVscyhsYXBvcDE4JHNtZWRpYTdyKSA9IGMoIlPDrSIsICJObyIpCmxhcG9wMTgkcGFpcyA9IGFzLmZhY3RvcihsYXBvcDE4JHBhaXMpCmxldmVscyhsYXBvcDE4JHBhaXMpID0gYygiTcOpeGljbyIsICJHdWF0ZW1hbGEiLCAiRWwgU2FsdmFkb3IiLCAiSG9uZHVyYXMiLAogICAgICAgICAgICAgICAgICAgICAgICAiTmljYXJhZ3VhIiwiQ29zdGEgUmljYSIsICJQYW5hbcOhIiwgIkNvbG9tYmlhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICJFY3VhZG9yIiwgIkJvbGl2aWEiLCAiUGVyw7oiLCAiUGFyYWd1YXkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIkNoaWxlIiwgIlVydWd1YXkiLCAiQnJhc2lsIiwgIkFyZ2VudGluYSIsIAogICAgICAgICAgICAgICAgICAgICAgICAiUmVwLiBEb20uIiwgIkphbWFpY2EiKQp0YWJsZShsYXBvcDE4JHBhaXMpICNQYcOtcwp0YWJsZShsYXBvcDE4JHNtZWRpYTFyKSAjRmFjZWJvb2sKYGBgCgpTaW4gZW1iYXJnbywgbGEgdmFyaWFibGUgInVzdWFyaW8iIGRlIGNhZGEgcmVkIHNvY2lhbCBzZSBjYWxjdWxhIGNvbW8gY29uZGljacOzbiBkZSBkb3MgdmFyaWFibGVzLCBjb21vIHNlIHZpbyBlbiBlbCBkb2N1bWVudG8gc29icmUgbWFuZWpvIGRlIGRhdG9zLCBjb24gZWwgc2lndWllbnRlIGPDs2RpZ28uCgpgYGB7ciB1c3Vhcmlvc30KbGFwb3AxOCRmYl91c2VyID0gaWZlbHNlKGxhcG9wMTgkc21lZGlhMT09MSAmIGxhcG9wMTgkc21lZGlhMjw9NCwgMSwgMCkKbGFwb3AxOCR0d191c2VyID0gaWZlbHNlKGxhcG9wMTgkc21lZGlhND09MSAmIGxhcG9wMTgkc21lZGlhNTw9NCwgMSwgMCkKbGFwb3AxOCR3YV91c2VyID0gaWZlbHNlKGxhcG9wMTgkc21lZGlhNz09MSAmIGxhcG9wMTgkc21lZGlhODw9NCwgMSwgMCkKCmxhcG9wMTgkZmJfdXNlciA9IGFzLmZhY3RvcihsYXBvcDE4JGZiX3VzZXIpCmxhcG9wMTgkdHdfdXNlciA9IGFzLmZhY3RvcihsYXBvcDE4JHR3X3VzZXIpCmxhcG9wMTgkd2FfdXNlciA9IGFzLmZhY3RvcihsYXBvcDE4JHdhX3VzZXIpCgpsZXZlbHMobGFwb3AxOCRmYl91c2VyKSA9IGMoIk5vIHVzdWFyaW8iLCAiVXN1YXJpbyIpCmxldmVscyhsYXBvcDE4JHR3X3VzZXIpID0gYygiTm8gdXN1YXJpbyIsICJVc3VhcmlvIikKbGV2ZWxzKGxhcG9wMTgkd2FfdXNlcikgPSBjKCJObyB1c3VhcmlvIiwgIlVzdWFyaW8iKQpgYGAKCkVzdGEgdmFyaWFibGVzIHNvbiBncmFmaWNhZGFzIGVuIGVsIHJlcG9ydGUgZW4gZWwgR3LDoWZpY28gMy4xLgpQYXJhIHJlcHJvZHVjaXIgZXN0b3MgZGF0b3MsIHNlIHB1ZWRlIGRlc2NyaWJpciBlc3RhcyB2YXJpYWJsZXMuCgpgYGB7ciB1c2VyfQpwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMTgkZmJfdXNlcikpKjEwMApwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMTgkdHdfdXNlcikpKjEwMApwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMTgkd2FfdXNlcikpKjEwMApgYGAKCkNvbW8gZW4gZ3LDoWZpY29zIGFudGVyaW9yZXMsIGNvbiBlc3RvcyBkYXRvcyBzZSBwdWVkZSBjcmVhciB1biBkYXRhZnJhbWUgcXVlIHNlIHV0aWxpemFyw61hIHBhcmEgaGFjZXIgbG9zIGdyw6FmaWNvcyBjaXJjdWxhcmVzIG1vc3RyYWRvcyBlbiBlbCByZXBvcnRlLgoKUGFyYSByZXBsaWNhciBlbCBjdWFkcm8gZGUgdXNvIGRlIHJlZGVzIHNvY2lhbGVzIHBvciBwYcOtcywgcHJpbWVybywgc2UgY3JlYW4gbGFzIHRhYmxhcyBiaXZhcmlhZGFzIGNvbiBlbCBwb3JjZW50YWplIGRlIGxvcyBxdWUgdXNhbiB5IGVsIHBvcmNlbnRhamUgZGUgbG9zIHF1ZSBubyB1c2FuIGNhZGEgcmVkIHNvY2lhbCBlbiBjYWRhIHBhw61zLgpFc3RhcyB0YWJsYXMgc2UgZ3VhcmRhbiBlbiBvYmpldG9zIGRlIFIuCkx1ZWdvIHNlIHVuZW4gZXN0b3Mgb2JqZXRvcyB1c2FuZG8gbG9zIGNvbWFuZG9zIGBjYmluZGAgcGFyYSBqdW50YXIgbGFzIGNvbHVtbmFzIHkgYGFzLmRhdGEuZnJhbWVgIHBhcmEgdW5pciBsYXMgdGFibGFzIGNvbW8gdW4gZGF0YWZyYW1lLgpFc3RhIHRhYmxhIHByZXNlbnRhIHRhbWJpw6luIGxvcyBwb3JjZW50YWplcyBkZSBsb3MgcXVlIE5vIHVzYW4gZXN0YXMgcmVkZXMgc29jaWFsZXMuClBhcmEgcHJlc2VudGFyIHVuYSB0YWJsYSBxdWUgaW5jbHV5YSBzb2xvIGEgbG9zIHF1ZSBzw60gdXNhbiBsYXMgcmVkZXMgc29jaWFsZXMsIHNlIGVsaW1pbmFuIGVzdGFzIGNvbHVtbmFzLCB1c2FuZG8gbGEgZXNwZWNpZmljYWNpw7NuIGBbLCBjKC0xLC0zLC01KV1gLCBxdWUgaW5kaWNhIHF1ZSBzZSBxdWllcmUgZWxpbWluYXIgbGFzIGNvbHVtbmFzIDEsIDMgeSA1LkZpbmFsbWVudGUsIHNlIGNhbWJpYSBlbCBub21icmUgZGUgbGFzIGNvbHVtbmFzIGRlbCBkYXRhZnJhbWUuCgpgYGB7ciB0YWJsYSBwb3IgcGHDrXN9CmZicGFpcyA9IHJvdW5kKHByb3AudGFibGUodGFibGUobGFwb3AxOCRwYWlzLCBsYXBvcDE4JGZiX3VzZXIpLCAxKSwgMykqMTAwCnR3cGFpcyA9IHJvdW5kKHByb3AudGFibGUodGFibGUobGFwb3AxOCRwYWlzLCBsYXBvcDE4JHR3X3VzZXIpLCAxKSwgMykqMTAwCndocGFpcyA9IHJvdW5kKHByb3AudGFibGUodGFibGUobGFwb3AxOCRwYWlzLCBsYXBvcDE4JHdhX3VzZXIpLCAxKSwgMykqMTAwCnRhYmxhcGFpcyA9IGFzLmRhdGEuZnJhbWUoY2JpbmQoZmJwYWlzLCB0d3BhaXMsIHdocGFpcykpCnRhYmxhcGFpcyA9IHRhYmxhcGFpc1ssIGMoLTEsLTMsLTUpXQp2YXJuYW1lcyA9IGMoIlVzYSBGYWNlYm9vayIsICJVc2EgVHdpdHRlciIsICJVc2EgV2hhdHNhcHAiKQpjb2xuYW1lcyh0YWJsYXBhaXMpID0gdmFybmFtZXMKdGFibGFwYWlzCmBgYAoKUGFyYSB0ZW5lciB1bmEgbWVqb3IgcHJlc2VudGFjacOzbiBkZSBsYSB0YWJsYSBzZSB0aWVuZW4gZG9zIGFsdGVybmF0aXZhczogbGEgcHJpbWVyYSBjb24gbGEgbGlicmVyw61hIGBrbml0cmAgeSBsYSBvdHJhIGNvbiBsYSBsaWJyZXLDrWEgYGZvcm1hdHRhYmxlYC4KCmBgYHtyIHRhYmxhIHBvciBwYcOtcyBtZWpvcmFkYX0KbGlicmFyeShrbml0cikKa2FibGUoaGVhZCh0YWJsYXBhaXMpLCBmb3JtYXQ9Im1hcmtkb3duIiwgZGlnaXRzPTEpCmxpYnJhcnkoZm9ybWF0dGFibGUpCmZvcm1hdHRhYmxlKHRhYmxhcGFpcykKYGBgCgojIyBDcnVjZSBjb24gdmFyaWFibGVzIHNvY2lvZGVtb2dyw6FmaWNhcwoKRW4gbGEgcMOhZ2luYSA1NiBkZWwgcmVwb3J0ZSAiRWwgcHVsc28gZGUgbGEgZGVtb2NyYWNpYSIgc2UgcHJlc2VudGEgbG9zIHJlc3VsdGFkb3MgZGVsIGNydWNlIGVudHJlIGxhcyB2YXJpYWJsZXMgdXNvIGRlIHJlZGVzIHNvY2lhbGVzIHkgdmFyaWFibGVzIHNvY2lvZGVtb2dyw6FmaWNhcyBjb21vIHVyYmFuby9ydXJhbCwgc2V4bywgZWRhZCwgcmlxdWV6YSB5IGHDsW9zIGRlIGVkdWNhY2nDs24uCgohW10oVGFibGEzLjIucG5nKXt3aWR0aD0iNjYzIn0KCkxhIHZhcmlhYmxlICJxMSIgcmVnaXN0cmEgZWwgZ8OpbmVybyBkZWwgZW50cmV2aXN0YWRvLgpFc3RhIHZhcmlhYmxlIGVzdMOhIGNvZGlmaWNhZGEgZGUgbGEgc2lndWllbnRlIG1hbmVyYToKCjEuICBIb21icmUKMi4gIE11amVyCgpQYXJhIGNvbnN0cnVpciB1bmEgdmFyaWFibGUgImR1bW15IiBsbGFtYWRhICJob21icmUiLCBkZSB0YWwgbWFuZXJhIHF1ZSBob21icmUgc2VhIDEgeSBtdWplciBzZWEgMCwgdW5hIGZvcm1hIGRlIGhhY2VybG8gZXMgZGUgbWFuZXJhIGFsZ2VicmFpY2EgKDItdmFyaWFibGUgcTEpLgpEZSBlc3RhIG1hbmVyYSwgYWhvcmEgbG9zIGhvbWJyZXMgbWFudGllbmUgZWwgdmFsb3IgMSAoMi0xKSB5IGxhcyBtdWplcmVzIHBhc2FyIGEgc2VyIDAgKDItMikuCkVuIGVzdGUgY2FzbywgbGEgbnVldmEgdmFyaWFibGUgImhvbWJyZSIgc2UgY3JlYSBjb21vIHVuYSB1bmEgdmFyaWFibGUgbnVtw6lyaWNhLgpWYW1vcyBhIG1hbnRlbmVyIGEgbGEgdmFyaWFibGUgY29tbyAibnVtIiBwYXJhLCBtw6FzIGFiYWpvLCBwb2RlciBjYWxjdWxhciBsYSBtZWRpYSBkZSBlc3RhIHZhcmlhYmxlIChjb3NhIHF1ZSBubyBzZSBwdWVkZSBoYWNlciBkZSB1bmEgdmFyaWFibGUgZGVjbGFyYWRhIGNvbW8gZmFjdG9yKS4KCmBgYHtyIGhvbWJyZX0KbGFwb3AxOCRob21icmUgPSAyLWxhcG9wMTgkcTEKbGFwb3AxOCRob21icmUgPSBhcy5mYWN0b3IobGFwb3AxOCRob21icmUpCmxldmVscyhsYXBvcDE4JGhvbWJyZSkgPSBjKCJNdWplciIsICJIb21icmUiKQp0YWJsZShsYXBvcDE4JGhvbWJyZSkKYGBgCgpMYSB2YXJpYWJsZSB1cmJhbm8vcnVyYWwgc2UgbGxhbWEgInVyIiBlbiBsYSBiYXNlIGRlIGRhdG9zIHkgZXN0w6EgY29kaWZpY2FkYSBkZSBsYSBzaWd1aWVudGUgbWFuZXJhOgoKMS4gIFVyYmFubwoyLiAgUnVyYWwKCkRlIGxhIG1pc21hIG1hbmVyYSBxdWUgY29uIGfDqW5lcm8sIHNlIHVzYSBsYSBmw7NybXVsYSAyLSB2YXJpYWJsZSB1ciwgcGVybyBlc3RhIHZhcmlhYmxlIHPDrSBzZSBjb252aWVydGUgZW4gZmFjdG9yIHkgc2UgZXRpcXVldGEuCgpgYGB7ciB1cmJhbm99CmxhcG9wMTgkdXJiYW4gPSAyLWxhcG9wMTgkdXIKbGFwb3AxOCR1cmJhbiA9IGFzLmZhY3RvcihsYXBvcDE4JHVyYmFuKQpsZXZlbHMobGFwb3AxOCR1cmJhbikgPSBjKCJSdXJhbCIsICJVcmJhbm8iKQp0YWJsZShsYXBvcDE4JHVyYmFuKQpgYGAKClNlIHByZXNlbnRhcsOhIGxhcyB0YWJsYXMgY3J1emFkYXMgZGVsIHVzbyBkZSByZWRlcyBzb2NpYWxlcyBwb3IgYWxndW5vIGRlIGxhcyB2YXJpYWJsZSBzb2Npb2RlbW9ncsOhZmljYXMsIHBhcmEgZW50ZW5kZXIgbWVqb3IgY8OzbW8gc2UgY29uc3RydXllIGxhIHRhYmxhIGdlbmVyYWwuClBvciBlamVtcGxvLCBlbCByZXBvcnRlIG11ZXN0cmEgZW4gbGEgVGFibGEgMy4yLCBsdWVnbyBkZSBsYSBjb2x1bW5hIGRlIHBvYmxhY2nDs24gZ2VuZXJhbCwgbGFzIGNvbHVtbmFzIHBhcmEgdXN1YXJpb3MgeSBubyB1c3VhcmlvcyBkZSBXaGF0c2FwcCAodmFyaWFibGUgIndhX3VzZXIiKSB5IGVuIGxhcyBmaWxhcywgbGEgcHJpbWVyYSBjb3JyZXNwb25kZSBhIHVyYmFubyAodmFyaWFibGUgInVyYmFuIiwgZG9uZGUgMCBlcyBydXJhbCB5IDEgdXJiYW5vKS4KU2UgcHJlc2VudGEgcXVlIGVudHJlIGxvcyB1c3VhcmlvcyBkZSBXaGF0c2FwcCwgZWwgNzYuNyUgc29uIHVyYmFub3MgeSBlbnRyZSBsb3Mgbm8gdXN1YXJpb3MsIGVsIDYyJSBzb24gdXJiYW5vcy4KRXN0b3MgZGF0b3Mgc2UgZ2VuZXJhbiBjb24gZWwgY29tYW5kbyBgdGFibGVgIHF1ZSBwZXJtaXRlIGhhY2VyIHVuYSB0YWJsYSBkZSBjb250aW5nZW5jaWEgZGUgMiB2YXJpYWJsZXMuCkVuIGVzdGUgY2FzbyBzZSB0aWVuZSBxdWUgbm90YXIgcXVlIGNhZGEgdmFyaWFibGUgdGllbmUgdW4gdMOtdHVsby4KRGUgZXN0YSBtYW5lcmEgZWwgY29tYW5kbyBlcyBgdGFibGUodMOtdHVsbzEgPSB2YXIxLCB0w610dWxvMiA9IHZhcjIpYC4KTHVlZ28sIHNlIHVzYSBlbCBjb21hbmRvIGBwcm9wLnRhYmxlYCBwYXJhIHF1ZSBubyBzZSBtdWVzdHJlIGxhcyBvYnNlcnZhY2lvbmVzLCBzaW5vIGxvcyBwb3JjZW50YWplcy4KRXN0ZSBjb21hbmRvIHBlcm1pdGUgY2FsY3VsYXIgbG9zIHBvcmNlbnRhamVzIHNvYnJlIGVsIHRvdGFsIChsYSBvcGNpw7NuIHBvciBkZWZlY3RvKSwgc29icmUgbGFzIGZpbGFzIHkgc29icmUgbGFzIGNvbHVtbmFzLgpQYXJhIGNhbGN1bGFyIHNvYnJlIGxhcyBjb2x1bW5hcyBzZSBkZWJlIGVzcGVjaWZpY2FyIGBwcm9wLnRhYmxlKHRhYmxlKC4uLiksIDIpYC4KU2kgc2UgcXVpc2llcmEgZWwgcG9yY2VudGFqZSBzb2JyZSBsYXMgZmlsYXMsIGVsIGPDs2RpZ28gc2Vyw61hIGBwcm9wLnRhYmxlKHRhYmxlKC4uLiksIDEpYC4KRXN0YSB0YWJsYSBzZSBwdWVkZW4gZ3VhcmRhciBjb21vIHVuIGRhdGFmcmFtZSBjb24gZWwgY29tYW5kbyBgYXMuZGF0YS5mcmFtZWAgZW4gdW4gbnVldm8gb2JqZXRvICJ0MSIuCgpgYGB7ciB0YWJsYSBXaHhVcn0KdF93YSA9IGFzLmRhdGEuZnJhbWUocm91bmQocHJvcC50YWJsZSh0YWJsZShVcmJhbm8gPSBsYXBvcDE4JHVyYmFuLCBVc3VhcmlvID0gbGFwb3AxOCR3YV91c2VyKSwgMikqMTAwLCAxKSkKdF93YQpgYGAKCkxhIGZpbGFzIGNvcnJlc3BvbmRpZW50ZXMgYSAiVXJiYW5vIiBkZSBlc3RhIHRhYmxhIHJlcHJvZHVjZW4gbG9zIGRhdG9zIGRlIGxhIFRhYmxhIDMuMjogNjIuMSUgc29uIHVyYmFub3MgZW50cmUgbG9zIG5vIHVzdWFyaW9zIGRlIFdoYXRzYXBwIHkgNzYuNyUgc29uIHVyYmFub3MgZW50cmUgbG9zIHVzdWFyaW9zLgoKRWwgbWlzbW8gcHJvY2VkaW1pZW50byBzZSBwdWVkZSByZWFsaXphciBwYXJhIGxvcyB1c3VhcmlvcyBkZSBGYWNlYm9vaywgZW4gZXN0ZSBjYXNvIGNydXphZG8gY29uIGxhIHZhcmlhYmxlICJob21icmUiLgoKYGBge3J9CnRfZmIgPSBhcy5kYXRhLmZyYW1lKHJvdW5kKHByb3AudGFibGUodGFibGUoVXJiYW5vID0gbGFwb3AxOCRob21icmUsIFVzdWFyaW8gPSBsYXBvcDE4JGZiX3VzZXIpLCAyKSoxMDAsIDEpKQp0X2ZiCmBgYAoKRXN0b3Mgc29uIGxvcyBwb3JjZW50YWplcyBwYXJhIGxvcyB1c3VhcmlvcyBkZSBGYWNlYm9vaywgZW4gbGEgZmlsYSBkZSBsYSB2YXJpYWJsZSBIb21icmUgZGUgbGEgVGFibGEgMy4yLgpFcyBkZWNpciwgZW50cmUgbG9zIHVzdWFyaW9zIGRlIEZhY2Vib29rLCA0OS45JSBzb24gaG9tYnJlcyB5IGVudHJlIGxvcyBubyB1c3VhcmlvcyBlc3RlIHBvcmNlbnRhamUgZXMgNDkuNyUuCkhhc3RhIGFxdcOtIHNlIGhhIHJlY29uc3RydWlkbyBhbGd1bm9zIHJlc3VsdGFkb3MgZGUgbGEgVGFibGEgMy4yLgpMb3MgZGVtw6FzIGRhdG9zIHB1ZWRlbiBzZWd1aXIgc2llbmRvIHJlY29uc3RydWlkb3MgbWVkaWFudGUgY29tYmluYWNpb25lcyBkZSBsYXMgdmFyaWFibGVzIGRlIHVzdWFyaW9zIGRlIHJlZGVzIHNvY2lhbGVzIHkgbGFzIHZhcmlhYmxlcyBzb2Npb2RlbW9ncsOhZmljYXMuCgojIyBHcsOhZmljbyBkZSBiYXJyYXMgZGUgZG9zIHZhcmlhYmxlcwoKRWwgY3J1Y2UgZW50cmUgdXN1YXJpb3MgZGUgV2hhdHNhcHAgeSBsYSB2YXJpYWJsZSB1cmJhbm8gc2UgcHVlZGUgdmVyIHRhbWJpw6luIGVuIHVuIGdyw6FmaWNvIGRlIGJhcnJhcyBhZ3J1cGFkYXMuClBhcmEgZXN0bywgdXNhcmVtb3MgbGEgdGFibGEgInRfd2EiIHF1ZSBjb250aWVuZSBlc3RvcyBkYXRvcy4KCmBgYHtyIGdyYWZpY28gYWdydXBhZG99CmdncGxvdChkYXRhPXRfd2EsIGFlcyh4PVVzdWFyaW8sIHk9RnJlcSwgZmlsbD1VcmJhbm8sIHltYXg9MTAwKSkrCiAgZ2VvbV9iYXIocG9zaXRpb249ImRvZGdlIiwgc3RhdD0iaWRlbnRpdHkiKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXBhc3RlKEZyZXEsICIlIiwgc2VwPSIiKSksIAogICAgICAgICAgICBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjkpLCB2anVzdD0tMC4yNSkrCiAgeWxhYigiUG9yY2VudGFqZSIpKwogIHhsYWIoIlVzdWFyaW8gZGUgV2hhdHNhcHAiKQpgYGAKClNpIHF1aXNpw6lyYW1vcyBoYWNlciBlbCBncsOhZmljbyBjb24gYmFycmFzIGFwaWxhZGFzLCBzZSB0aWVuZSBxdWUgY2FtYmlhciBsYSBlc3BlY2lmaWNhY2nDs24gZGUgYHBvc2l0aW9uPSJzdGFjayJgIGVuIGBnZW9tX2JhcmAgeSBsYSBlc3BlY2lmaWNhY2nDs24gYHBvc2l0aW9uPXBvc2l0aW9uX3N0YWNrKClgIGRlIGBnZW9tX3RleHRgLgoKYGBge3IgYmFycmFzIGFwaWxhZGFzfQpnZ3Bsb3QoZGF0YT10X3dhLCBhZXMoeD1Vc3VhcmlvLCB5PUZyZXEsIGZpbGw9VXJiYW5vLCB5bWF4PTEwMCkpKwogIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShGcmVxLCAiJSIsIHNlcD0iIikpLCAKICAgICAgICAgICAgcG9zaXRpb249cG9zaXRpb25fc3RhY2soKSwgdmp1c3Q9Mi41KSsKICB5bGFiKCJQb3JjZW50YWplIikrCiAgeGxhYigiVXN1YXJpbyBkZSBXaGF0c2FwcCIpCmBgYAoKRW4gYW1ib3MgY2Fzb3MgbGFzIGJhcnJhcyBjZWxlc3RlcyBpbmRpY2FuIGxvcyBwb3JjZW50YWplcyByZXBvcnRhZG9zIGVuIGxhIHRhYmxhIDMuMiBkZWwgcmVwb3J0ZSB5IGNvcnJlc3BvbmRlbiBhIGxhIHByb3BvcmNpw7NuIGRlIHBlcnNvbmFzIHF1ZSB2aXZlbiBlbiBlbCDDoW1iaXRvIHVyYmFubyBlbnRyZSBsb3MgdXN1YXJpb3MgeSBsb3Mgbm8gdXN1YXJpb3MuCgojIFJlc3VtZW4KCkVuIGVzdGUgZG9jdW1lbnRvIHNlIGhhIHRyYWJhamFkbyBjb24gdmFyaWFibGUgY2F0ZWfDs3JpY2FzIG9yZGluYWxlcywgY29tbyBsYSBmcmVjdWVuY2lhIGRlIHVzbyBkZSByZWRlcyBzb2NpYWxlcy4KVGFtYmnDqW4gc2UgaGEgaW50cm9kdWNpZG8gYWwgdXNvIGRlIHRhYmxhcyBkZSBjb250aW5nZW5jaWEgZGUgZG9zIHZhcmlhYmxlcyBjYXRlZ8OzcmljYXMgeSBsYSBjcmVhY2nDs24gZGUgZ3LDoWZpY29zIGRlIGJhcnJhcyBhZ3J1cGFkYXMgcGFyYSAyIHZhcmlhYmxlcy4KCiMgQ8OhbGN1bG9zIGluY2x1eWVuZG8gZWwgZWZlY3RvIGRlIGRpc2XDsW8KCiMjIEVqZW1wbG8gY29uIGRhdG9zIGRlIGxhIHJvbmRhIDIwMjEKCkNvbiBsb3MgZGF0b3MgZGUgbGEgcm9uZGEgMjAyMSBkZWwgQmFyw7NtZXRybyBkZSBsYXMgQW3DqXJpY2FzLCBoZW1vcyBjYWxjdWxhZG8gbG9zIHBvcmNlbnRhamVzIGRlIGxhIHZhcmlhYmxlIHF1ZSBtaWRlIHNpIGxvcyB2b3RvcyBzZSBoYW4gY29udGFkbyBqdXN0YW1lbnRlLgpFbCBncsOhZmljbyBxdWUgaGVtb3MgY3JlYWRvIGhhIHNpZG8gcGFyYSBlbCB0b3RhbCBkZSBsYSBtdWVzdHJhLCBlcyBkZWNpciwgZGUgdG9kb3MgbG9zIHBhw61zZXMuCkVsIEdyw6FmaWNvIDIuNSBkZWwgcmVwb3J0ZSBFbCBQdWxzbyBkZSBsYSBEZW1vY3JhY2lhIHByZXNlbnRhIGxvcyByZXN1bHRhZG9zIHBhcmEgY2FkYSBwYcOtcy4KClNpIGNhbGN1bMOhcmFtb3MgbG9zIHBvcmNlbnRhamVzIGNvbiBlbCBjb21hbmRvIGB0YWJsZWAgeSBgcHJvcC50YWJsZWAgdGVuZHLDrWFtb3MgcmVzdWx0YWRvcyBkaWZlcmVudGVzIGEgbG9zIG1vc3RyYWRvcyBlbiBlbCBncsOhZmljby4KUG9yIGVqZW1wbG8sIGVuIGVsIHBhw61zIDUsIHF1ZSBlcyBOaWNhcmFndWEsIGxvcyByZXN1bHRhZG9zIGluZGljYW4gcXVlIDI2JSBkZSBjaXVkYWRhbm9zIGRlIGVzZSBwYcOtcyBpbmRpY2EgcXVlIGxvcyB2b3RvcyBzaWVtcHJlIHNlIGN1ZW50YW4ganVzdGFtZW50ZSwgNDklIHF1ZSBhbGd1bmFzIHZlY2VzIHNlIGN1ZW50YW4ganVzdGFtZW50ZSB5IDI0LjQlIHF1ZSBudW5jYS4KU2luIGVtYmFyZ28sIGVsIGdyw6FmaWNvIGluZGljYSBxdWUgZW4gTmljYXJhZ3VhLCAyOSUgaW5kaWNhIHF1ZSBudW5jYSBkZSBjdWVudGEganVzdGFtZW50ZSwgNDUlIGluZGljYSBxdWUgYWxndW5hcyB2ZWNlcyB5IDI1JSBxdWUgc2llbXByZS4KRXN0b3MgcG9yY2VudGFqZXMgbm8gY29ycmVzcG9uZGVuIGEgbG9zIHF1ZSBzZSBlbmN1ZW50cmFuIGNvbiBlc3RvcyBjb21hbmRvcy4KCmBgYHtyIGNydWNlIHNpbiBwb25kZXJhcn0Kcm91bmQocHJvcC50YWJsZSh0YWJsZShsYXBvcDIxJHBhaXMsIGxhcG9wMjEkY291bnRmYWlyMXIpLCAxKSwgMykqMTAwCmBgYAoKRXN0YSBkaWZlcmVuY2lhIGVzIGRlYmlkbyBhIHF1ZSBsb3MgY29tYW5kb3MgYHRhYmxlYCB5IGBwcm9wLnRhYmxlYCBubyBpbmNsdXllbiBlbCBlZmVjdG8gZGUgZGlzZcOxbyB5IGVsIGZhY3RvciBkZSBleHBhbnNpw7NuIGVuIGxvcyBjw6FsY3Vsb3MuCk3DoXMgaW5mb3JtYWNpw7NuIHNvYnJlIGVzdGFzIGRpZmVyZW5jaWFzIHNlIGVuY3VlbnRyYSBbYXF1w61dKGh0dHBzOi8vYXJ0dXJvbWFsZG9uYWRvLmdpdGh1Yi5pby9CYXJvbWV0cm9FZHVfV2ViL0V4cGFuc2lvbi5odG1sKS4KClBhcmEgcmVwbGljYXIgbG9zIHJlc3VsdGFkb3MgZGVsIEdyw6FmaWNvIDIuNSBoYXkgYWxndW5hcyBvcGNpb25lcy4KTGEgcHJpbWVyYSBlcyBtZWRpYW50ZSBsYSBsaWJyZXLDrWEgZXNwZWNpYWxpemFkYSBgc3VydmV5YC4KUGFyYSBwb2RlciB1c2FyIGVzdGEgbGlicmVyw61hLCBwcmltZXJvIGRlYmVtb3MgcHJlcGFyYXIgbGEgYmFzZSBkZSBkYXRvcywgZWxpbWluYW5kbyBsb3MgdmFsb3JlcyBwZXJkaWRvcyBkZSBsYXMgdmFyaWFibGVzIHF1ZSBkZWZpbmVuIGVsIGRpc2XDsW8uClVuIHBhc28gYWRpY2lvbmFsIGVzIHRyYW5zZm9ybWFyIGxhcyB2YXJpYWJsZXMgZGVsIGRhdGFmcmFtZS4KRXN0byBlcyBkZWJpZG8gYSBxdWUgY3VhbmRvIHNlIGltcG9ydGFuLCBlbCBzaXN0ZW1hIGxlZSBsYXMgdmFyaWFibGVzIGNvbW8gdGlwbyAiaGF2ZW5fbGFiZWxsZWQiLCBlcyBkZWNpciwgbWFudGllbmUgbGFzIGV0aXF1ZXRhcyBkZSBsYXMgdmFyaWFibGVzLCBjb24gbG8gcXVlIHNlIHBvZHLDrWEgcHJvZHVjaXIgdW4gbGlicm8gZGUgY8OzZGlnb3MuCkVzdG8gZXMgw7p0aWwgZW4gb3RyYXMgb2Nhc2lvbmVzLCBwZXJvIGdlbmVyYSBwcm9ibGVtYXMgY29uIGxhIGxpYnJlcsOtYSBgc3VydmV5YC4KUGFyYSBlc3RvIHRyYW5zZm9ybWFtb3MgbGFzIHZhcmlhYmxlcyBhIG90cm8gdGlwbyBjb24gZWwgY29tYW5kbyBgc2FwcGx5YC4KCmBgYHtyIHByZXBhcmFjaW9uIGRlIGJhc2UsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmxhcG9wMjEgPSBzdWJzZXQobGFwb3AyMSwgIWlzLm5hKHdlaWdodDE1MDApKQpzYXBwbHkobGFwb3AyMSwgaGF2ZW46OnphcF9sYWJlbHMpCmBgYAoKVW5hIHZleiBwcmVwYXJhZGEgbGEgYmFzZSBkZSBkYXRvcywgc2UgYWN0aXZhIGxhIGxpYnJlcsOtYSB5IHNlIGRlZmluZSBlbCBkaXNlw7FvLgpFbiBlbCBtw7NkdWxvIGFudGVyaW9yLCB0YW1iacOpbiB1c2Ftb3MgZXN0YSBsaWJyZXLDrWEgcGFyYSBjYWxjdWxhciBsb3MgcmVzdWx0YWRvcyBjb24gZWwgZWZlY3RvIGRlIGRpc2XDsW8gZW4gbGEgcm9uZGEgMjAxOC4KQSBkaWZlcmVuY2lhIGRlIGVzZSBjw7NkaWdvLCBlcyBxdWUgbGEgcm9uZGEgMjAyMSBkZWwgQmFyw7NtZXRybyBkZSBsYXMgQW3DqXJpY2FzIHV0aWxpesOzIGxhIG1vZGFsaWRhZCB0ZWxlZsOzbmljYSwgeSBubyBjYXJhIGEgY2FyYSwgcG9yIGxvIHF1ZSBhaG9yYSBsYSB1bmlkYWQgcHJpbWFyaWEgZGUgbXVlc3RyZW8gZXMgZWwgaW5kaXZpZHVvLCB5IGFzw60gZXN0w6EgZGVmaW5pZGEgZW4gbGEgdmFyaWFibGUgInVwbSIuCkxhIHZhcmlhYmxlIHF1ZSBkZWZpbmUgbG9zIGVzdHJhdG9zIGVzICJzdHJhdGEiICh5IG5vICJlc3RyYXRvcHJpIiBjb21vIGVuIGxhIHJvbmRhIDIwMTgpLgpMYSB2YXJpYWJsZSBkZSBwb25kZXJhY2nDs24gc2lndWUgc2llbmRvICJ3ZWlnaHQxNTAwIi4KCkNvbiBlc3RvcyBkYXRvcyBjYWxjdWxhbW9zIGd1YXJkYW1vcyBlbCBkaXNlw7FvIGVuIHVuIG9iamV0byAiZGlzZW5vMjEiLgoKYGBge3IgZGlzZW5vfQpsaWJyYXJ5KHN1cnZleSkKZGlzZW5vMjEgPSBzdnlkZXNpZ24oaWRzID0gfnVwbSwgc3RyYXRhID0gfnN0cmF0YSwgd2VpZ2h0cyA9IH53ZWlnaHQxNTAwLCBuZXN0PVRSVUUsIGRhdGE9bGFwb3AyMSkKYGBgCgpMYSBsaWJyZXLDrWEgYHN1cnZleWAgaW5jbHV5ZSBjb21hbmRvcyBuYXRpdm9zIHBhcmEgaGFjZXIgbcO6bHRpcGxlcyBvcGVyYWNpb25lcyBxdWUgaW5jbHV5YW4gZWwgZWZlY3RvIGRlIGRpc2XDsW8uClVubyBkZSBlc29zIGNvbWFuZG9zIGVzIGBzdnl0YWJsZWAgcXVlIG5vcyBwZXJtaXRlIGhhY2VyIGxhIHRhYmxhIGNydXphZGEgZW50cmUgbGEgdmFyaWFibGUgImNvdW50ZmFpcjFyIiB5ICJwYWlzIiwgZXNwZWNpZmljYW5kbyBlbCBkaXNlw7FvLgpFc3RlIGNvbWFuZG8gbm9zIGRldnVlbHZlIGxhcyBmcmVjdWVuY2lhcyBhYnNvbHV0YXMgcG9uZGVyYWRhcywgcG9yIGxvIHF1ZSBzZSBwdWVkZSBhbmlkYXIgZW4gZWwgY29tYW5kbyBgcHJvcC50YWJsZWAgcGFyYSBjYWxjdWxhciBsb3MgcG9yY2VudGFqZXMgZGVzZGUgbGFzIGZyZWN1ZW5jaWFzIGFic29sdXRhcyBwb25kZXJhZGFzIHkgZGVudHJvIGRlbCBjb21hbmRvIGBjb3VudGAgcGFyYSByZWRvbmRlYXIgbG9zIHBvcmNlbnRhamVzLCB5IGRlbnRybyBkZWwgY29tYW5kbyBgYXMuZGF0YS50YWJsZWAgcGFyYSBndWFyZGFyIGxhIHRhYmxhIGVuIHVuIG9iamV0byAidm90b3hwYWlzIiBjb21vIHVuIGRhdGFmcmFtZSwgcXVlIG5vcyBwZXJtaXRhIGxhIG1hbmlwdWxhY2nDs24gY29uIGBnZ3Bsb3RgIGx1ZWdvLgoKYGBge3IgdGFibGEgcG9uZGVyYWRhfQp2b3RveHBhaXMgPSBhcy5kYXRhLmZyYW1lKHJvdW5kKHByb3AudGFibGUoc3Z5dGFibGUofnBhaXMrY291bnRmYWlyMXIsIGRlc2lnbj1kaXNlbm8yMSksIDEpKjEwMCwgMCkpCnZvdG94cGFpcyRwYWlzID0gcGFpcwp2b3RveHBhaXMKYGBgCgpgYGB7ciBncmFmaWNvIHBvbmRlcmFkb30KZ2dwbG90KGRhdGE9dm90b3hwYWlzLCBhZXMoZmlsbD1jb3VudGZhaXIxciwgeD1GcmVxLCB5PXBhaXMpKSsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTAuMykrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShGcmVxLCAiJSIsIHNlcD0iIikpLCBjb2xvcj0id2hpdGUiLCAKICAgICAgICAgICAgcG9zaXRpb249cG9zaXRpb25fc3RhY2sodmp1c3Q9MC41KSwgc2l6ZT0zKSsKICBsYWJzKHg9IlBvcmNlbnRhamUiLCB5PSJQYcOtcyIsIGZpbGw9IkxvcyB2b3RvcyBzZSBjdWVudGFuIGp1c3RhbWVudGUiLAogICAgICAgY2FwdGlvbj0iQmFyw7NtZXRybyBkZSBsYXMgQW3DqXJpY2FzIHBvciBMQVBPUCwgMjAyMSIpCmBgYAoKRXN0ZSBncsOhZmljbyByZXByb2R1Y2UgZXhhY3RhbWVudGUgbG9zIHJlc3VsdGFkb3MgbW9zdHJhZG9zIGVuIGVsIEdyw6FmaWNvIDIuNSBkZWwgcmVwb3J0ZSwgYXVucXVlIGVuIHVuIG9yZGVuIGRpZmVyZW50ZS4KCiMjIEVqZW1wbG8gY29uIGxvcyBkYXRvcyBkZSBsYSByb25kYSAyMDE4LzE5CgpMYSBwZXF1ZcOxYSBkaWZlcmVuY2lhIGVudHJlIGxvcyBwb3JjZW50YWplcyBxdWUgc2UgbXVlc3RyYW4gZW4gZWwgR3LDoWZpY28gMy4zIHkgbG9zIG1vc3RyYWRvcyBlbiBsYSBzZWNjacOzbiAiRGVzY3JpYmlyIGxhcyB2YXJpYWJsZXMiIHB1ZWRlIGRlYmVyc2UgYSBxdWUgZW4gdG9kb3MgbGFzIHRhYmxhcyB5IGdyw6FmaWNvcyBhbnRlcmlvcmVzIG5vIHNlIGluY2x1eWUgZWwgZmFjdG9yIGRlIGV4cGFuc2nDs24uClNpIHNlIGluY2x1eWVyYSwgdXNhbmRvIGxhIHZhcmlhYmxlICJ3ZWlnaHQxNTAwIiwgc2UgcmVwbGljYXLDrWFuIGxvcyBwb3JjZW50YWplcyBtb3N0cmFkb3MgZW4gZWwgaW5mb3JtZS4KUG9yIGVqZW1wbG8sIHBhcmEgZWwgdXNvIGRlIFdoYXRzYXBwLCBzZSBwdWVkZSB1c2FyIGVsIGNvbWFuZG8gYGZyZXFgIGRlIGxhIGxpYnJlcsOtYSBgZGVzY3JgIHF1ZSBwZXJtaXRlIGluY2x1aXIgdW5hIHZhcmlhYmxlIGRlIHBvbmRlcmFjacOzbi4KCkVzdGEgdGFibGEgbHVlZ28gc2UgcHVlZGUgZ3VhcmRhciBlbiB1biBkYXRhZnJhbWUsIGFsIHF1ZSBzZSBsZSBwdWVkZW4gZWxpbWluYXIgbGFzIGZpbGFzIHkgY29sdW1uYXMgcXVlIG5vIHNlIHJlcXVpZXJlbiwgeSBzZSBsZXMgcHVlZGUgY2FtYmlhciBlbCBub21icmUgYSBsYXMgY29sdW1uYXMuCnkgYWdyZWdhciBsYXMgZXRpcXVldGFzLgoKYGBge3Igd2EgcG9uZGVyYWRvfQp0YWJsYTIgPSBhcy5kYXRhLmZyYW1lKGRlc2NyOjpmcmVxKGxhcG9wMTgkc21lZGlhOHIsIGxhcG9wMTgkd2VpZ2h0MTUwMCwgcGxvdD1GKSkKdGFibGEyID0gdGFibGEyWy1jKDUsNiksIC0yXQpjb2xuYW1lcyh0YWJsYTIpID0gYygiZnJlYyIsICJwZXIiKQp0YWJsYTIkbGFiID0gcm93bmFtZXModGFibGEyKQp0YWJsYTIKYGBgCgpDb24gZXN0ZSBudWV2byBkYXRhZnJhbWUsIHNlIHB1ZWRlIHJlcGxpY2FyIGVsIGdyw6FmaWNvIGRlIFdoYXRzYXBwLCBjb24gbG9zIGRhdG9zIHBvbmRlcmFkb3MsIHVzYW5kbyBlbCBjw7NkaWdvIGRlIGBnZ3Bsb3RgLgoKYGBge3Igd2EgZ3JhZiBwb25kfQpnZ3Bsb3QoZGF0YT10YWJsYTIsIGFlcyh4PTIsIHk9cGVyLCBmaWxsPWxhYikpKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShyb3VuZChwZXIsIDEpLCAiJSIsIHNlcD0iIikpLCBjb2xvcj0id2hpdGUiLCAKICAgICAgICAgICAgcG9zaXRpb249cG9zaXRpb25fc3RhY2sodmp1c3Q9MC41KSwgc2l6ZT0zKSsKICBjb29yZF9wb2xhcigieSIpKwogIHRoZW1lX3ZvaWQoKSsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkZyZWN1ZW5jaWEgZGUgdXNvIGRlIEZhY2Vib29rIikrCiAgIGxhYnModGl0bGU9IkZyZWN1ZW5jaWEgY29uIGxhIHF1ZSB2ZSBjb250ZW5pZG8gZW4gRmFjZWJvb2siLCAKICAgICAgICBjYXB0aW9uPSJCYXLDs21ldHJvIGRlIGxhcyBBbcOpcmljYXMgcG9yIExBUE9QLCAyMDE4LzE5IikrCiAgeGxpbSgwLjUsIDIuNSkKYGBgCgpBZGVtw6FzIGRlbCBjb21hbmRvIGBmcmVxYCwgdGFtYmnDqW4gc2UgcHVlZGUgdXNhciBsYSBsaWJyZXLDrWEgYHN1cnZleWAgeSBlbCBjb21hbmRvIG5hdGl2byBgc3Z5dGFibGVgLgoKYGBge3Igc3VydmV5fQpsaWJyYXJ5KHN1cnZleSkKZGlzZW5vMTg8LXN2eWRlc2lnbihpZHMgPSB+dXBtLCBzdHJhdGEgPSB+ZXN0cmF0b3ByaSwgd2VpZ2h0cyA9IH53ZWlnaHQxNTAwLCBuZXN0PVRSVUUsIGRhdGE9bGFwb3AxOCkKYGBgCgpMb3MgcmVzdWx0YWRvcyBxdWUgc2Ugb2J0aWVuZW4gc29uIGlndWFsZXMgcXVlIGNvbiBlbCBtw6l0b2RvIGFudGVyaW9yIHkgYSBsb3MgcHJlc2VudGFkb3MgZW4gZWwgcmVwb3J0ZS4KRXN0b3MgcmVzdWx0YWRvcyB0YW1iacOpbiBzZSBwdWVkZW4gZ3VhcmRhciBlbiB1biAiZGF0YWZyYW1lIiBwYXJhIGhhY2VyIGVsIGdyw6FmaWNvLgoKYGBge3Igc3Z5dGFibGV9CnByb3AudGFibGUoc3Z5dGFibGUofnNtZWRpYThyLCBkZXNpZ249ZGlzZW5vMTgpKSoxMDAKYGBgCgpMYSBzZWNjacOzbiAiQ3J1Y2UgY29uIHZhcmlhYmxlcyIgcHJlc2VudGEgbG9zIGRhdG9zIGRlIHVzdWFyaW9zIGRlIHJlZGVzIHNvY2lhbGVzIHBvciBwYcOtcy4KUGFyYSBjb25zdHJ1aXIgbGEgdGFibGEgY29uc2lkZXJhbmRvIGVsIGVmZWN0byBkZSBkaXNlw7FvLCB0YW1iacOpbiBzZSBwdWVkZSB1c2FyIGVsIGNvbWFuZG8gbmF0aXZvIGBzdnl0YWJsZWAgcXVlIHBlcm1pdGUgY2FsY3VsYXIgdW5hIHRhYmxhIGJpdmFyaWFkYS4KRGUgbGEgbWlzbWEgbWFuZXJhIHF1ZSBlbiBjYXNvIG5vIHBvbmRlcmFkbywgbGFzIHRhYmxhcyBwYXJjaWFsZXMgZGUgY2FkYSByZWQgc29jaWFsIHNlIGd1YXJkYW4gZW4gdW5vcyBvYmpldG9zIGRlIHRpcG8gbGlzdGEsIGxvcyBxdWUgc2UganVudGFuIGNvbW8gdW4gImRhdGFmcmFtZSIgeSBzZSBlZGl0YSBwYXJhIHByZXNlbnRhciBzb2xvIGxvcyBkYXRvcyBkZSBsb3MgdXN1YXJpb3MgZGUgY2FkYSByZWQgc29jaWFsIHBvciBwYcOtcy4KCmBgYHtyIHN2eXRhYmxlIGJpdmFyaWFkYX0KZmJwYWlzXzIgPSByb3VuZChwcm9wLnRhYmxlKHN2eXRhYmxlKH5wYWlzK2ZiX3VzZXIsIGRlc2lnbj1kaXNlbm8xOCksIDEpLCAzKSoxMDAKdHdwYWlzXzIgPSByb3VuZChwcm9wLnRhYmxlKHN2eXRhYmxlKH5wYWlzK3R3X3VzZXIsIGRlc2lnbj1kaXNlbm8xOCksIDEpLCAzKSoxMDAKd2FwYWlzXzIgPSByb3VuZChwcm9wLnRhYmxlKHN2eXRhYmxlKH5wYWlzK3dhX3VzZXIsIGRlc2lnbj1kaXNlbm8xOCksIDEpLCAzKSoxMDAKdGFibGFwYWlzXzIgPSBhcy5kYXRhLmZyYW1lKGNiaW5kKGZicGFpc18yLCB0d3BhaXNfMiwgd2FwYWlzXzIpKQp0YWJsYXBhaXNfMiA9IHRhYmxhcGFpc18yWywgYygtMSwtMywtNSldCnZhcm5hbWVzID0gYygiVXNhIEZhY2Vib29rIiwgIlVzYSBUd2l0dGVyIiwgIlVzYSBXaGF0c2FwcCIpCmNvbG5hbWVzKHRhYmxhcGFpc18yKSA9IHZhcm5hbWVzCnRhYmxhcGFpc18yCmBgYAoKUG9yIMO6bHRpbW8sIGxhIHNlY2Npw7NuICJDcnVjZSBjb24gdmFyaWFibGVzIHNvY2lvZGVtb2dyw6FmaWNhcyIgcmVwcm9kdWNlIGxvcyByZXN1bHRhZG9zIGRlIGxhIFRhYmxhIDMuMiBkZWwgcmVwb3J0ZS4KRGUgbGEgbWlzbWEgbWFuZXJhIHF1ZSBlbiBlbCBjYXNvIGFudGVyaW9yLCBzZSBwdWVkZSB1c2FyIGVsIGNvbWFuZG8gbmF0aXZvIGBzdnl0YWJsZWAgcGFyYSByZWFsaXphciBlbCBjcnVjZSBlbnRyZSBsYXMgdmFyaWFibGVzIGRlIHVzbyBkZSByZWRlcyBzb2NpYWxlcyB5IGxhIHZhcmlhYmxlIHVyYmFuby4KTG9zIHJlc3VsdGFkb3MgZGUgbGEgZmlsYSBVcmJhbm8gZW4gY2FkYSByZWQgc29jaWFsIGNvcnJlc3BvbmRlcsOtYW4gYSBsYSBwcmltZXJhIGZpbGEgZGUgcmVzdWx0YWRvcyBkZSBsYSBUYWJsYSAzLjIuCgpgYGB7cn0Kcm91bmQocHJvcC50YWJsZShzdnl0YWJsZSh+dXJiYW4rd2FfdXNlciwgZGVzaWduPWRpc2VubzE4KSwgMiksIDMpKjEwMApyb3VuZChwcm9wLnRhYmxlKHN2eXRhYmxlKH51cmJhbitmYl91c2VyLCBkZXNpZ249ZGlzZW5vMTgpLCAyKSwgMykqMTAwCnJvdW5kKHByb3AudGFibGUoc3Z5dGFibGUofnVyYmFuK3R3X3VzZXIsIGRlc2lnbj1kaXNlbm8xOCksIDIpLCAzKSoxMDAKYGBgCgpEZSBlc3RhIG1hbmVyYSBzZSBwdWVkZW4gY2FsY3VsYXIgbGFzIHRhYmxhcyBkZSBkaXN0cmlidWNpw7NuIGRlIGZyZWN1ZW5jaWFzIHkgbGFzIHRhYmxhcyBiaXZhcmlhZGFzIChvIGRlIGNvbnRpbmdlbmNpYSkgaW5jbHV5ZW5kbyBlbCBlZmVjdG8gZGUgZGlzZcOxbyBvIGVsIGZhY3RvciBkZSBleHBhbnNpw7NuLgo=