Introducción

En este documento veremos aspectos básicos de cómo describir una variable numérica. Para eso, vamos a seguir usando el último informe regional “El pulso de la democracia”, disponible aquí, donde se presentan los principales hallazgos de la ronda 2018/19 del Barómetro de las Américas. Una de las secciones de este informe, reporta los datos sobre redes sociales y actitudes políticas. En esta sección, se presentan datos sobre el uso de internet y el uso de redes sociales, en general, por país y por ciertas características sociodemográficas.

Sobre la base de datos

Los datos que vamos a usar deben citarse de la siguiente manera: Fuente: Barómetro de las Américas por el Proyecto de Opinión Pública de América Latina (LAPOP), wwww.LapopSurveys.org. En este documento se carga una base de datos recortada. Esta base de datos se encuentra alojada en el repositorio “materials_edu” de la cuenta de LAPOP en GitHub. Se recomienda limpiar el Environment antes de comenzar este módulo.

Mediante la librería rio y el comando import se puede importar esta base de datos desde este repositorio. Además, se seleccionan los datos de países con códigos menores o iguales a 35, es decir, se elimina las observaciones de Estados Unidos y Canadá.

library(rio)
lapop18 = import("https://raw.github.com/lapop-central/materials_edu/main/LAPOP_AB_Merge_2018_v1.0.sav")
lapop18 = subset(lapop18, pais<=35)

Descriptivos para una variable numérica

En la tabla 3.2 del reporte “El pulso de la democracia” se presentan los promedios generales de las variables edad (“q2” en la base de datos) y años de estudio (“ed” en la base de datos) para la población general.

Se usa el comando mean para calcular el promedio y se usa na.rm=T debido a que estas variables cuentan con valores perdidos.

mean(lapop18$q2, na.rm=T)
## [1] 39.99204
mean(lapop18$ed, na.rm=T)
## [1] 9.934748

En la sección donde trabajamos con variables cualitativas (o de factor, en el lenguaje de R), vimos que se podía describir las variables “hombre” y “urbano” definiendo estas variables como factor, etiquetándolas y haciendo una tabla de frecuencias de estas variables. Otra manera de encontrar el porcentaje de personas que son hombres o que viven en el área urbana es trabajar con estas variables, pero no definirlas como factor. Cuando se crean las variables, ambas son definidas por defecto como numéricas. En este caso, además se ser numéricas, son variables de tipo dummy, es decir con valores 0 y 1. En el caso de la variable “hombre” se ha definido 0=Mujer y 1=Hombre; y en el caso de la variable “urbano” se ha definido 0=Rural y 1=Urbano. Es una buena práctica nombrar a la variable dummy con un nombre que refiere a la categoría 1. Con variables dummy, cuando se calcula el promedio, el resultado es el mismo que el porcentaje de la categoría 1. Entonces, si se calcula mean(lapop$hombre, na.rm=T), esta operación nos arroja el porcentaje de la categoría 1, es decir de hombres. Se multiplica por 100 para ponerlo en formato de 0 a 100.

lapop18$hombre = 2-lapop18$q1
lapop18$urban = 2-lapop18$ur
mean(lapop18$hombre, na.rm=T)*100
## [1] 49.74846
mean(lapop18$urban, na.rm=T)*100
## [1] 71.15398

Estos son los datos que se presentan en la primera columna de resultados de la población general, excepto para la variable riqueza (“quintall”) que no está disponible en esta versión recortada de la base de datos.

Gráficos descriptivos

Luego de describir una variable numérica, también puede incluir algunas gráficas básicas, por ejemplo, usando el comando hist, que es parte del paquete de base de R, se puede producir el histograma de la variable “años de educación” (ed).

hist(lapop18$ed)

Este mismo gráfico se puede reproducir usando el comando ggplot. Con este comando se tiene más flexibilidad con las opciones gráficas. En primer lugar, se define el dataframe que se usará y la variable “ed” en el eje X. Luego con la especificación geom_histogram() se define usar un histograma. Se define el ancho de la barra del histograma con banwidth=1. Finalmente, este código permite etiquetar el eje X e Y e incluir un tema en blanco y negro, con theme_bw().

library(ggplot2)
ggplot(lapop18, aes(x=ed))+
  geom_histogram(binwidth = 1)+
  xlab("Años de educación")+
  ylab("Frecuencia")+
  theme_bw()

Media por grupos

En la Tabla 3.2 del reporte se presentan la media de estas variables numéricas por grupos de las variables relacionadas a las redes sociales. Es decir, por ejemplo, el promedio de años de estudio para los usuarios de Facebook y para los no usuarios de Facebook. Si queremos calcular el promedio de años de estudio para los usuarios de Facebook, primero se calcula esta variable, de la misma manera que en secciones anteriores, con el comando ifelse.

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)

El cálculo del promedio de años para los usuarios y no usuarios de Facebook se puede hacer de muchas maneras. Una primera es usando los corchetes [...]. En este caso, calcularemos el promedio de años de estudio por grupos de usuarios [lapop18$fb_user==1] y no usuarios de Facebook [lapop18$fb_user==0].

mean(lapop18$ed[lapop18$fb_user==0], na.rm=T)
## [1] 8.064905
mean(lapop18$ed[lapop18$fb_user==1], na.rm=T)
## [1] 11.44839

Descriptivos de una variable numérica por grupos

Otra manera de describir una variable numérica es usando el comando summary. Este comando reporta los estadísticos descriptivos más usados para una variable numérica: mínimo, máximo, cuartiles, media y mediana. Todos estos estadísticos permiten una comparación mejor entre ambos grupos, de usuarios y no usuarios de Facebook. Dentro de este comando se puede incluir la especificación digits=3 para redondear los resultados, lo que evita tener que usar round, por ejemplo.

summary(lapop18$ed[lapop18$fb_user==0], na.rm=T, digits=3)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    0.00    5.00    8.00    8.06   11.00   18.00    1374
summary(lapop18$ed[lapop18$fb_user==1], na.rm=T, digits=3)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##     0.0     9.0    12.0    11.4    14.0    18.0    1240

Sin embargo, el comando summary no brinda un estadístico importante como la desviación estándar, una medida de dispersión o heterogeneidad. Para poder tener los estadísticos anteriores y que se incluya la desviación estándar, entre otras medidas adicionales, se puede usar el comando describeBy, que es parte de la librería psych. Este comando pide la variable a describir (“ed”) y la variable que forma los grupos (“fb_user”) y brinda la media, la desviación estándar, la mediana, la media recortada, la desviación absoluta de la mediana, el mínimo y máximo.

library(psych)
describeBy(lapop18$ed, lapop18$fb_user)
## 
##  Descriptive statistics by group 
## group: 0
##    vars     n mean  sd median trimmed  mad min max range skew kurtosis   se
## X1    1 11540 8.06 4.3      8    7.99 4.45   0  18    18 0.13    -0.52 0.04
## ------------------------------------------------------------ 
## group: 1
##    vars     n  mean   sd median trimmed  mad min max range  skew kurtosis   se
## X1    1 14998 11.45 3.59     12   11.52 2.97   0  18    18 -0.24        0 0.03

Gráficos descriptivos por grupos

El reporte no lo muestra, pero se pueden presentar gráficos para cada grupo para facilitar la comparación de una variable. Para hacer estos gráficos comparativos por grupo, vamos a seguir usando la librería tidyverse y el comando ggplot para graficar variables. Igual que en la tabla anterior, se define el dataframe “lapop18” y se indica que no se tome en cuenta los valores perdidos de la variable “wa_user” con el comando subset(lapop18, wa_use!="NA". Si no se incluyera esta especificación, se crearía un histograma de edad para el grupo de observaciones con NAs en un tercer panel.

Luego, se indica que se haga un gráfico, con ggplot que tenga la variable “q2” en el eje X. Se define que este gráfico sea un histograma con geom_histogram(). Una novedad es que, con la especificación facet_wrap(~wa_user) se puede indicar que se hagan gráficos por cada grupo de esa variable. Finalmente, se etiquetan los ejes.

library(tidyverse)
ggplot(subset(lapop18, wa_user!="NA"), aes(x=q2))+
  geom_histogram()+
  facet_wrap(~wa_user)+
  xlab("Edad")+
  ylab("Frecuencia")

Este gráfico, sin embargo, muestra los valores 0 y 1 de la variable “wa_user” en el encabezado de ambos gráficos. Esto es debido a que esta variable, cuando se creó, se definió por defecto como numérica. Para que aparezcan las etiquetas de la variable, se tiene que transformar “wa_user” en factor y etiquetarla.

lapop18$wa_user = as.factor(lapop18$wa_user)
levels(lapop18$wa_user) = c("No usuario", "Usuario")

Otra forma de comparar la distribución de edad por grupos de usuarios o no usuarios de Whatsapp es mediante un gráfico de cajas o boxplot. Con el comando boxplot, que es parte de los comandos de base de R, se puede hacer estos gráficos. El comando pide primero la variable en el eje Y, luego la variable que define los grupos y el dataframe. Se puede etiquetar el eje X y Y con los nombres de las variables. Como la variable “wa_user” ha sido transformada a factor y etiquetada, ahora aparecen las etiquetas.

boxplot(q2 ~ wa_user, data=lapop18, xlab ="Usuario de Whatsapp", ylab="Edad")

Este gráfico también lo podemos reproducir con la librería ggplot.

ggplot(subset(lapop18, wa_user!="NA"), aes(x=wa_user, y=q2))+
  geom_boxplot()+
  ylab("Edad")+
  xlab("Usuario de Whatsapp")

Resumen

En este documento se ha trabajado con variables numéricas, como edad o años de estudio. Se ha calculado estadísticos descriptivos, como la media o la desviación estándar para toda la población o por grupos. Finalmente, se ha presentado formas de graficar estas variables, mediante histogramas o boxplots.

Cálculos incluyendo el efecto de diseño

Los resultados anteriores no incluyen el factor de expansión. Para incluirlo en los cálculos se puede usar el comando weighted.mean, que es parte de la librería stats, que viene precargada con R, por lo que no hay que instalarla.

weighted.mean(lapop18$q2, lapop18$weight1500, na.rm=T)
## [1] 39.98095
weighted.mean(lapop18$ed, lapop18$weight1500, na.rm=T)
## [1] 9.931417
weighted.mean(lapop18$hombre, lapop18$weight1500, na.rm=T)*100
## [1] 49.74826
weighted.mean(lapop18$urban, lapop18$weight1500, na.rm=T)*100
## [1] 71.11895

Otra forma de calcular la media incluyendo el factor de expansión es mediante de el uso de la librería survey y el comando nativo svymean. Para esto se tiene que definir el diseño muestral con el comando svydesign y guardar este diseño en un objeto, aquí llamado “lapop.design”.

library(survey)
diseno18 = svydesign(ids = ~upm, strata = ~estratopri, weights = ~weight1500, nest=TRUE, data=lapop18)

Para calcular el promedio, se usa el comando svymean y se usa la especificación na.rm=T debido a que estas variables cuentan con valores perdidos.

svymean(~q2, diseno18, na.rm=T)
##      mean     SE
## q2 39.981 0.0535
svymean(~ed, diseno18, na.rm=T)
##      mean   SE
## ed 9.9314 0.04

Para las variables dummies el procedimiento es el mismo, salvo que se le multiplica por 100 para presentarlo en formato de porcentaje

svymean(~hombre, diseno18, na.rm =T)*100
##          mean    SE
## hombre 49.748 8e-04
svymean(~urban, diseno18, na.rm=T)*100
##         mean     SE
## urban 71.119 0.0076

El paquete survey también tiene comandos para replicar gráficos. Por ejemplo, para calcular un histograma simple.

svyhist(~ed, diseno18, freq = T)

Para calcular estadísticos descriptivos por grupos, se puede usar el comando svyby, que permite definir la variable numérica que se quiere describir, la variable que define los grupos y el estadístico ponderado que se quiere calcular.

svyby(~ed, ~fb_user, diseno18, svymean, na.rm=T)

Para reproducir un gráfico descriptivo por grupos, se puede usar el comando svyboxplot para comparar la distribución de la variable edad entre grupos de una variable de tipo factor, como usuarios de Whatsapp.

svyboxplot(~q2~factor(wa_user), diseno18, all.outliers = T)

LS0tCnRpdGxlOiAiRXN0YWTDrXN0aWNhIGRlc2NyaXB0aXZhIHVzYW5kbyBlbCBCYXLDs21ldHJvIGRlIGxhcyBBbcOpcmljYXMgKDMpIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICB0b2NfZGVwdGg6IDEKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBmbGF0bHkKICAgIGRmX3ByaW50OiBwYWdlZAogICAgc2VsZl9jb250YWluZWQ6IG5vCiAgICBrZWVwX21kOiB5ZXMKICAgICNjb2RlX2ZvbGRpbmc6IGhpZGUKZWRpdG9yX29wdGlvbnM6IAogIG1hcmtkb3duOiAKICAgIHdyYXA6IHNlbnRlbmNlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUUpCmBgYAoKYGBge2NzcyBjb2xvciwgZWNobz1GQUxTRX0KLmNvbHVtbnMge2Rpc3BsYXk6IGZsZXg7fQpoMSB7Y29sb3I6ICMzMzY2Q0M7fQpgYGAKCiMgSW50cm9kdWNjacOzbgoKRW4gZXN0ZSBkb2N1bWVudG8gdmVyZW1vcyBhc3BlY3RvcyBiw6FzaWNvcyBkZSBjw7NtbyBkZXNjcmliaXIgdW5hIHZhcmlhYmxlIG51bcOpcmljYS4KUGFyYSBlc28sIHZhbW9zIGEgc2VndWlyIHVzYW5kbyBlbCDDumx0aW1vIGluZm9ybWUgcmVnaW9uYWwgIkVsIHB1bHNvIGRlIGxhIGRlbW9jcmFjaWEiLCBkaXNwb25pYmxlIFthcXXDrV0oaHR0cHM6Ly93d3cudmFuZGVyYmlsdC5lZHUvbGFwb3AvYWIyMDE4LzIwMTgtMTlfQW1lcmljYXNCYXJvbWV0ZXJfUmVnaW9uYWxfUmVwb3J0X1NwYW5pc2hfV18wMy4yNy4yMC5wZGYpLCBkb25kZSBzZSBwcmVzZW50YW4gbG9zIHByaW5jaXBhbGVzIGhhbGxhemdvcyBkZSBsYSByb25kYSAyMDE4LzE5IGRlbCBCYXLDs21ldHJvIGRlIGxhcyBBbcOpcmljYXMuClVuYSBkZSBsYXMgc2VjY2lvbmVzIGRlIGVzdGUgaW5mb3JtZSwgcmVwb3J0YSBsb3MgZGF0b3Mgc29icmUgcmVkZXMgc29jaWFsZXMgeSBhY3RpdHVkZXMgcG9sw610aWNhcy4KRW4gZXN0YSBzZWNjacOzbiwgc2UgcHJlc2VudGFuIGRhdG9zIHNvYnJlIGVsIHVzbyBkZSBpbnRlcm5ldCB5IGVsIHVzbyBkZSByZWRlcyBzb2NpYWxlcywgZW4gZ2VuZXJhbCwgcG9yIHBhw61zIHkgcG9yIGNpZXJ0YXMgY2FyYWN0ZXLDrXN0aWNhcyBzb2Npb2RlbW9ncsOhZmljYXMuCgojIFNvYnJlIGxhIGJhc2UgZGUgZGF0b3MKCkxvcyBkYXRvcyBxdWUgdmFtb3MgYSB1c2FyIGRlYmVuIGNpdGFyc2UgZGUgbGEgc2lndWllbnRlIG1hbmVyYTogRnVlbnRlOiBCYXLDs21ldHJvIGRlIGxhcyBBbcOpcmljYXMgcG9yIGVsIFByb3llY3RvIGRlIE9waW5pw7NuIFDDumJsaWNhIGRlIEFtw6lyaWNhIExhdGluYSAoTEFQT1ApLCB3d3d3LkxhcG9wU3VydmV5cy5vcmcuCkVuIGVzdGUgZG9jdW1lbnRvIHNlIGNhcmdhIHVuYSBiYXNlIGRlIGRhdG9zIHJlY29ydGFkYS4KRXN0YSBiYXNlIGRlIGRhdG9zIHNlIGVuY3VlbnRyYSBhbG9qYWRhIGVuIGVsIHJlcG9zaXRvcmlvICJtYXRlcmlhbHNfZWR1IiBkZSBsYSBjdWVudGEgZGUgTEFQT1AgZW4gR2l0SHViLgpTZSByZWNvbWllbmRhIGxpbXBpYXIgZWwgRW52aXJvbm1lbnQgYW50ZXMgZGUgY29tZW56YXIgZXN0ZSBtw7NkdWxvLgoKTWVkaWFudGUgbGEgbGlicmVyw61hIGByaW9gIHkgZWwgY29tYW5kbyBgaW1wb3J0YCBzZSBwdWVkZSBpbXBvcnRhciBlc3RhIGJhc2UgZGUgZGF0b3MgZGVzZGUgZXN0ZSByZXBvc2l0b3Jpby4KQWRlbcOhcywgc2Ugc2VsZWNjaW9uYW4gbG9zIGRhdG9zIGRlIHBhw61zZXMgY29uIGPDs2RpZ29zIG1lbm9yZXMgbyBpZ3VhbGVzIGEgMzUsIGVzIGRlY2lyLCBzZSBlbGltaW5hIGxhcyBvYnNlcnZhY2lvbmVzIGRlIEVzdGFkb3MgVW5pZG9zIHkgQ2FuYWTDoS4KCmBgYHtyIGJhc2UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkocmlvKQpsYXBvcDE4ID0gaW1wb3J0KCJodHRwczovL3Jhdy5naXRodWIuY29tL2xhcG9wLWNlbnRyYWwvbWF0ZXJpYWxzX2VkdS9tYWluL0xBUE9QX0FCX01lcmdlXzIwMThfdjEuMC5zYXYiKQpsYXBvcDE4ID0gc3Vic2V0KGxhcG9wMTgsIHBhaXM8PTM1KQpgYGAKCiMgRGVzY3JpcHRpdm9zIHBhcmEgdW5hIHZhcmlhYmxlIG51bcOpcmljYQoKRW4gbGEgdGFibGEgMy4yIGRlbCByZXBvcnRlICJFbCBwdWxzbyBkZSBsYSBkZW1vY3JhY2lhIiBzZSBwcmVzZW50YW4gbG9zIHByb21lZGlvcyBnZW5lcmFsZXMgZGUgbGFzIHZhcmlhYmxlcyBlZGFkICgicTIiIGVuIGxhIGJhc2UgZGUgZGF0b3MpIHkgYcOxb3MgZGUgZXN0dWRpbyAoImVkIiBlbiBsYSBiYXNlIGRlIGRhdG9zKSBwYXJhIGxhIHBvYmxhY2nDs24gZ2VuZXJhbC4KCiFbXShUYWJsYTMuMi5wbmcpe3dpZHRoPSI2OTEifQoKU2UgdXNhIGVsIGNvbWFuZG8gYG1lYW5gIHBhcmEgY2FsY3VsYXIgZWwgcHJvbWVkaW8geSBzZSB1c2EgYG5hLnJtPVRgIGRlYmlkbyBhIHF1ZSBlc3RhcyB2YXJpYWJsZXMgY3VlbnRhbiBjb24gdmFsb3JlcyBwZXJkaWRvcy4KCmBgYHtyIG1lZGlhfQptZWFuKGxhcG9wMTgkcTIsIG5hLnJtPVQpCm1lYW4obGFwb3AxOCRlZCwgbmEucm09VCkKYGBgCgpFbiBsYSBzZWNjacOzbiBkb25kZSB0cmFiYWphbW9zIGNvbiB2YXJpYWJsZXMgY3VhbGl0YXRpdmFzIChvIGRlIGZhY3RvciwgZW4gZWwgbGVuZ3VhamUgZGUgUiksIHZpbW9zIHF1ZSBzZSBwb2TDrWEgZGVzY3JpYmlyIGxhcyB2YXJpYWJsZXMgImhvbWJyZSIgeSAidXJiYW5vIiBkZWZpbmllbmRvIGVzdGFzIHZhcmlhYmxlcyBjb21vIGZhY3RvciwgZXRpcXVldMOhbmRvbGFzIHkgaGFjaWVuZG8gdW5hIHRhYmxhIGRlIGZyZWN1ZW5jaWFzIGRlIGVzdGFzIHZhcmlhYmxlcy4KT3RyYSBtYW5lcmEgZGUgZW5jb250cmFyIGVsIHBvcmNlbnRhamUgZGUgcGVyc29uYXMgcXVlIHNvbiBob21icmVzIG8gcXVlIHZpdmVuIGVuIGVsIMOhcmVhIHVyYmFuYSBlcyB0cmFiYWphciBjb24gZXN0YXMgdmFyaWFibGVzLCBwZXJvIG5vIGRlZmluaXJsYXMgY29tbyBmYWN0b3IuCkN1YW5kbyBzZSBjcmVhbiBsYXMgdmFyaWFibGVzLCBhbWJhcyBzb24gZGVmaW5pZGFzIHBvciBkZWZlY3RvIGNvbW8gbnVtw6lyaWNhcy4KRW4gZXN0ZSBjYXNvLCBhZGVtw6FzIHNlIHNlciBudW3DqXJpY2FzLCBzb24gdmFyaWFibGVzIGRlIHRpcG8gZHVtbXksIGVzIGRlY2lyIGNvbiB2YWxvcmVzIDAgeSAxLgpFbiBlbCBjYXNvIGRlIGxhIHZhcmlhYmxlICJob21icmUiIHNlIGhhIGRlZmluaWRvIDA9TXVqZXIgeSAxPUhvbWJyZTsgeSBlbiBlbCBjYXNvIGRlIGxhIHZhcmlhYmxlICJ1cmJhbm8iIHNlIGhhIGRlZmluaWRvIDA9UnVyYWwgeSAxPVVyYmFuby4KRXMgdW5hIGJ1ZW5hIHByw6FjdGljYSBub21icmFyIGEgbGEgdmFyaWFibGUgZHVtbXkgY29uIHVuIG5vbWJyZSBxdWUgcmVmaWVyZSBhIGxhIGNhdGVnb3LDrWEgMS4KQ29uIHZhcmlhYmxlcyBkdW1teSwgY3VhbmRvIHNlIGNhbGN1bGEgZWwgcHJvbWVkaW8sIGVsIHJlc3VsdGFkbyBlcyBlbCBtaXNtbyBxdWUgZWwgcG9yY2VudGFqZSBkZSBsYSBjYXRlZ29yw61hIDEuCkVudG9uY2VzLCBzaSBzZSBjYWxjdWxhIGBtZWFuKGxhcG9wJGhvbWJyZSwgbmEucm09VClgLCBlc3RhIG9wZXJhY2nDs24gbm9zIGFycm9qYSBlbCBwb3JjZW50YWplIGRlIGxhIGNhdGVnb3LDrWEgMSwgZXMgZGVjaXIgZGUgaG9tYnJlcy4KU2UgbXVsdGlwbGljYSBwb3IgMTAwIHBhcmEgcG9uZXJsbyBlbiBmb3JtYXRvIGRlIDAgYSAxMDAuCgpgYGB7ciBwcm9tZWRpbyBkdW1teX0KbGFwb3AxOCRob21icmUgPSAyLWxhcG9wMTgkcTEKbGFwb3AxOCR1cmJhbiA9IDItbGFwb3AxOCR1cgptZWFuKGxhcG9wMTgkaG9tYnJlLCBuYS5ybT1UKSoxMDAKbWVhbihsYXBvcDE4JHVyYmFuLCBuYS5ybT1UKSoxMDAKYGBgCgpFc3RvcyBzb24gbG9zIGRhdG9zIHF1ZSBzZSBwcmVzZW50YW4gZW4gbGEgcHJpbWVyYSBjb2x1bW5hIGRlIHJlc3VsdGFkb3MgZGUgbGEgcG9ibGFjacOzbiBnZW5lcmFsLCBleGNlcHRvIHBhcmEgbGEgdmFyaWFibGUgcmlxdWV6YSAoInF1aW50YWxsIikgcXVlIG5vIGVzdMOhIGRpc3BvbmlibGUgZW4gZXN0YSB2ZXJzacOzbiByZWNvcnRhZGEgZGUgbGEgYmFzZSBkZSBkYXRvcy4KCiMgR3LDoWZpY29zIGRlc2NyaXB0aXZvcwoKTHVlZ28gZGUgZGVzY3JpYmlyIHVuYSB2YXJpYWJsZSBudW3DqXJpY2EsIHRhbWJpw6luIHB1ZWRlIGluY2x1aXIgYWxndW5hcyBncsOhZmljYXMgYsOhc2ljYXMsIHBvciBlamVtcGxvLCB1c2FuZG8gZWwgY29tYW5kbyBgaGlzdGAsIHF1ZSBlcyBwYXJ0ZSBkZWwgcGFxdWV0ZSBkZSBiYXNlIGRlIFIsIHNlIHB1ZWRlIHByb2R1Y2lyIGVsIGhpc3RvZ3JhbWEgZGUgbGEgdmFyaWFibGUgImHDsW9zIGRlIGVkdWNhY2nDs24iIChlZCkuCgpgYGB7ciBoaXN0b2dyYW1hIHNpbXBsZX0KaGlzdChsYXBvcDE4JGVkKQpgYGAKCkVzdGUgbWlzbW8gZ3LDoWZpY28gc2UgcHVlZGUgcmVwcm9kdWNpciB1c2FuZG8gZWwgY29tYW5kbyBgZ2dwbG90YC4KQ29uIGVzdGUgY29tYW5kbyBzZSB0aWVuZSBtw6FzIGZsZXhpYmlsaWRhZCBjb24gbGFzIG9wY2lvbmVzIGdyw6FmaWNhcy4KRW4gcHJpbWVyIGx1Z2FyLCBzZSBkZWZpbmUgZWwgZGF0YWZyYW1lIHF1ZSBzZSB1c2Fyw6EgeSBsYSB2YXJpYWJsZSAiZWQiIGVuIGVsIGVqZSBYLgpMdWVnbyBjb24gbGEgZXNwZWNpZmljYWNpw7NuIGBnZW9tX2hpc3RvZ3JhbSgpYCBzZSBkZWZpbmUgdXNhciB1biBoaXN0b2dyYW1hLgpTZSBkZWZpbmUgZWwgYW5jaG8gZGUgbGEgYmFycmEgZGVsIGhpc3RvZ3JhbWEgY29uIGBiYW53aWR0aD0xYC4KRmluYWxtZW50ZSwgZXN0ZSBjw7NkaWdvIHBlcm1pdGUgZXRpcXVldGFyIGVsIGVqZSBYIGUgWSBlIGluY2x1aXIgdW4gdGVtYSBlbiBibGFuY28geSBuZWdybywgY29uIGB0aGVtZV9idygpYC4KCmBgYHtyIGdnaGlzdCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShnZ3Bsb3QyKQpnZ3Bsb3QobGFwb3AxOCwgYWVzKHg9ZWQpKSsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpKwogIHhsYWIoIkHDsW9zIGRlIGVkdWNhY2nDs24iKSsKICB5bGFiKCJGcmVjdWVuY2lhIikrCiAgdGhlbWVfYncoKQpgYGAKCiMgTWVkaWEgcG9yIGdydXBvcwoKRW4gbGEgVGFibGEgMy4yIGRlbCByZXBvcnRlIHNlIHByZXNlbnRhbiBsYSBtZWRpYSBkZSBlc3RhcyB2YXJpYWJsZXMgbnVtw6lyaWNhcyBwb3IgZ3J1cG9zIGRlIGxhcyB2YXJpYWJsZXMgcmVsYWNpb25hZGFzIGEgbGFzIHJlZGVzIHNvY2lhbGVzLgpFcyBkZWNpciwgcG9yIGVqZW1wbG8sIGVsIHByb21lZGlvIGRlIGHDsW9zIGRlIGVzdHVkaW8gcGFyYSBsb3MgdXN1YXJpb3MgZGUgRmFjZWJvb2sgeSBwYXJhIGxvcyBubyB1c3VhcmlvcyBkZSBGYWNlYm9vay4KU2kgcXVlcmVtb3MgY2FsY3VsYXIgZWwgcHJvbWVkaW8gZGUgYcOxb3MgZGUgZXN0dWRpbyBwYXJhIGxvcyB1c3VhcmlvcyBkZSBGYWNlYm9vaywgcHJpbWVybyBzZSBjYWxjdWxhIGVzdGEgdmFyaWFibGUsIGRlIGxhIG1pc21hIG1hbmVyYSBxdWUgZW4gc2VjY2lvbmVzIGFudGVyaW9yZXMsIGNvbiBlbCBjb21hbmRvIGBpZmVsc2VgLgoKYGBge3IgdXN1YXJpb3N9CmxhcG9wMTgkZmJfdXNlciA9IGlmZWxzZShsYXBvcDE4JHNtZWRpYTE9PTEgJiBsYXBvcDE4JHNtZWRpYTI8PTQsIDEsIDApCmxhcG9wMTgkdHdfdXNlciA9IGlmZWxzZShsYXBvcDE4JHNtZWRpYTQ9PTEgJiBsYXBvcDE4JHNtZWRpYTU8PTQsIDEsIDApCmxhcG9wMTgkd2FfdXNlciA9IGlmZWxzZShsYXBvcDE4JHNtZWRpYTc9PTEgJiBsYXBvcDE4JHNtZWRpYTg8PTQsIDEsIDApCmBgYAoKRWwgY8OhbGN1bG8gZGVsIHByb21lZGlvIGRlIGHDsW9zIHBhcmEgbG9zIHVzdWFyaW9zIHkgbm8gdXN1YXJpb3MgZGUgRmFjZWJvb2sgc2UgcHVlZGUgaGFjZXIgZGUgbXVjaGFzIG1hbmVyYXMuClVuYSBwcmltZXJhIGVzIHVzYW5kbyBsb3MgY29yY2hldGVzIGBbLi4uXWAuCkVuIGVzdGUgY2FzbywgY2FsY3VsYXJlbW9zIGVsIHByb21lZGlvIGRlIGHDsW9zIGRlIGVzdHVkaW8gcG9yIGdydXBvcyBkZSB1c3VhcmlvcyBgW2xhcG9wMTgkZmJfdXNlcj09MV1gIHkgbm8gdXN1YXJpb3MgZGUgRmFjZWJvb2sgYFtsYXBvcDE4JGZiX3VzZXI9PTBdYC4KCmBgYHtyIGHDsW9zIGRlIGVzdHVkaW8gZGUgRmJ9Cm1lYW4obGFwb3AxOCRlZFtsYXBvcDE4JGZiX3VzZXI9PTBdLCBuYS5ybT1UKQptZWFuKGxhcG9wMTgkZWRbbGFwb3AxOCRmYl91c2VyPT0xXSwgbmEucm09VCkKYGBgCgojIERlc2NyaXB0aXZvcyBkZSB1bmEgdmFyaWFibGUgbnVtw6lyaWNhIHBvciBncnVwb3MKCk90cmEgbWFuZXJhIGRlIGRlc2NyaWJpciB1bmEgdmFyaWFibGUgbnVtw6lyaWNhIGVzIHVzYW5kbyBlbCBjb21hbmRvIGBzdW1tYXJ5YC4KRXN0ZSBjb21hbmRvIHJlcG9ydGEgbG9zIGVzdGFkw61zdGljb3MgZGVzY3JpcHRpdm9zIG3DoXMgdXNhZG9zIHBhcmEgdW5hIHZhcmlhYmxlIG51bcOpcmljYTogbcOtbmltbywgbcOheGltbywgY3VhcnRpbGVzLCBtZWRpYSB5IG1lZGlhbmEuClRvZG9zIGVzdG9zIGVzdGFkw61zdGljb3MgcGVybWl0ZW4gdW5hIGNvbXBhcmFjacOzbiBtZWpvciBlbnRyZSBhbWJvcyBncnVwb3MsIGRlIHVzdWFyaW9zIHkgbm8gdXN1YXJpb3MgZGUgRmFjZWJvb2suCkRlbnRybyBkZSBlc3RlIGNvbWFuZG8gc2UgcHVlZGUgaW5jbHVpciBsYSBlc3BlY2lmaWNhY2nDs24gYGRpZ2l0cz0zYCBwYXJhIHJlZG9uZGVhciBsb3MgcmVzdWx0YWRvcywgbG8gcXVlIGV2aXRhIHRlbmVyIHF1ZSB1c2FyIGByb3VuZGAsIHBvciBlamVtcGxvLgoKYGBge3J9CnN1bW1hcnkobGFwb3AxOCRlZFtsYXBvcDE4JGZiX3VzZXI9PTBdLCBuYS5ybT1ULCBkaWdpdHM9MykKc3VtbWFyeShsYXBvcDE4JGVkW2xhcG9wMTgkZmJfdXNlcj09MV0sIG5hLnJtPVQsIGRpZ2l0cz0zKQpgYGAKClNpbiBlbWJhcmdvLCBlbCBjb21hbmRvIGBzdW1tYXJ5YCBubyBicmluZGEgdW4gZXN0YWTDrXN0aWNvIGltcG9ydGFudGUgY29tbyBsYSBkZXN2aWFjacOzbiBlc3TDoW5kYXIsIHVuYSBtZWRpZGEgZGUgZGlzcGVyc2nDs24gbyBoZXRlcm9nZW5laWRhZC4KUGFyYSBwb2RlciB0ZW5lciBsb3MgZXN0YWTDrXN0aWNvcyBhbnRlcmlvcmVzIHkgcXVlIHNlIGluY2x1eWEgbGEgZGVzdmlhY2nDs24gZXN0w6FuZGFyLCBlbnRyZSBvdHJhcyBtZWRpZGFzIGFkaWNpb25hbGVzLCBzZSBwdWVkZSB1c2FyIGVsIGNvbWFuZG8gYGRlc2NyaWJlQnlgLCBxdWUgZXMgcGFydGUgZGUgbGEgbGlicmVyw61hIGBwc3ljaGAuCkVzdGUgY29tYW5kbyBwaWRlIGxhIHZhcmlhYmxlIGEgZGVzY3JpYmlyICgiZWQiKSB5IGxhIHZhcmlhYmxlIHF1ZSBmb3JtYSBsb3MgZ3J1cG9zICgiZmJfdXNlciIpIHkgYnJpbmRhIGxhIG1lZGlhLCBsYSBkZXN2aWFjacOzbiBlc3TDoW5kYXIsIGxhIG1lZGlhbmEsIGxhIG1lZGlhIHJlY29ydGFkYSwgbGEgZGVzdmlhY2nDs24gYWJzb2x1dGEgZGUgbGEgbWVkaWFuYSwgZWwgbcOtbmltbyB5IG3DoXhpbW8uCgpgYGB7ciBtZWRpYSBhw7FvcyBkZSBlc3R1ZGlvIHBvciBGQiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShwc3ljaCkKZGVzY3JpYmVCeShsYXBvcDE4JGVkLCBsYXBvcDE4JGZiX3VzZXIpCmBgYAoKIyBHcsOhZmljb3MgZGVzY3JpcHRpdm9zIHBvciBncnVwb3MKCkVsIHJlcG9ydGUgbm8gbG8gbXVlc3RyYSwgcGVybyBzZSBwdWVkZW4gcHJlc2VudGFyIGdyw6FmaWNvcyBwYXJhIGNhZGEgZ3J1cG8gcGFyYSBmYWNpbGl0YXIgbGEgY29tcGFyYWNpw7NuIGRlIHVuYSB2YXJpYWJsZS4KUGFyYSBoYWNlciBlc3RvcyBncsOhZmljb3MgY29tcGFyYXRpdm9zIHBvciBncnVwbywgdmFtb3MgYSBzZWd1aXIgdXNhbmRvIGxhIGxpYnJlcsOtYSBgdGlkeXZlcnNlYCB5IGVsIGNvbWFuZG8gYGdncGxvdGAgcGFyYSBncmFmaWNhciB2YXJpYWJsZXMuCklndWFsIHF1ZSBlbiBsYSB0YWJsYSBhbnRlcmlvciwgc2UgZGVmaW5lIGVsIGRhdGFmcmFtZSAibGFwb3AxOCIgeSBzZSBpbmRpY2EgcXVlIG5vIHNlIHRvbWUgZW4gY3VlbnRhIGxvcyB2YWxvcmVzIHBlcmRpZG9zIGRlIGxhIHZhcmlhYmxlICJ3YV91c2VyIiBjb24gZWwgY29tYW5kbyBgc3Vic2V0KGxhcG9wMTgsIHdhX3VzZSE9Ik5BImAuIFNpIG5vIHNlIGluY2x1eWVyYSBlc3RhIGVzcGVjaWZpY2FjacOzbiwgc2UgY3JlYXLDrWEgdW4gaGlzdG9ncmFtYSBkZSBlZGFkIHBhcmEgZWwgZ3J1cG8gZGUgb2JzZXJ2YWNpb25lcyBjb24gTkFzIGVuIHVuIHRlcmNlciBwYW5lbC4KCkx1ZWdvLCBzZSBpbmRpY2EgcXVlIHNlIGhhZ2EgdW4gZ3LDoWZpY28sIGNvbiBgZ2dwbG90YCBxdWUgdGVuZ2EgbGEgdmFyaWFibGUgInEyIiBlbiBlbCBlamUgWC4KU2UgZGVmaW5lIHF1ZSBlc3RlIGdyw6FmaWNvIHNlYSB1biBoaXN0b2dyYW1hIGNvbiBgZ2VvbV9oaXN0b2dyYW0oKWAuClVuYSBub3ZlZGFkIGVzIHF1ZSwgY29uIGxhIGVzcGVjaWZpY2FjacOzbiBgZmFjZXRfd3JhcCh+d2FfdXNlcilgIHNlIHB1ZWRlIGluZGljYXIgcXVlIHNlIGhhZ2FuIGdyw6FmaWNvcyBwb3IgY2FkYSBncnVwbyBkZSBlc2EgdmFyaWFibGUuCkZpbmFsbWVudGUsIHNlIGV0aXF1ZXRhbiBsb3MgZWplcy4KCmBgYHtyIGhpc3QgZWRhZHh3aGF0LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKZ2dwbG90KHN1YnNldChsYXBvcDE4LCB3YV91c2VyIT0iTkEiKSwgYWVzKHg9cTIpKSsKICBnZW9tX2hpc3RvZ3JhbSgpKwogIGZhY2V0X3dyYXAofndhX3VzZXIpKwogIHhsYWIoIkVkYWQiKSsKICB5bGFiKCJGcmVjdWVuY2lhIikKYGBgCgpFc3RlIGdyw6FmaWNvLCBzaW4gZW1iYXJnbywgbXVlc3RyYSBsb3MgdmFsb3JlcyAwIHkgMSBkZSBsYSB2YXJpYWJsZSAid2FfdXNlciIgZW4gZWwgZW5jYWJlemFkbyBkZSBhbWJvcyBncsOhZmljb3MuCkVzdG8gZXMgZGViaWRvIGEgcXVlIGVzdGEgdmFyaWFibGUsIGN1YW5kbyBzZSBjcmXDsywgc2UgZGVmaW5pw7MgcG9yIGRlZmVjdG8gY29tbyBudW3DqXJpY2EuClBhcmEgcXVlIGFwYXJlemNhbiBsYXMgZXRpcXVldGFzIGRlIGxhIHZhcmlhYmxlLCBzZSB0aWVuZSBxdWUgdHJhbnNmb3JtYXIgIndhX3VzZXIiIGVuIGZhY3RvciB5IGV0aXF1ZXRhcmxhLgoKYGBge3Igd2EgZmFjdG9yfQpsYXBvcDE4JHdhX3VzZXIgPSBhcy5mYWN0b3IobGFwb3AxOCR3YV91c2VyKQpsZXZlbHMobGFwb3AxOCR3YV91c2VyKSA9IGMoIk5vIHVzdWFyaW8iLCAiVXN1YXJpbyIpCmBgYAoKT3RyYSBmb3JtYSBkZSBjb21wYXJhciBsYSBkaXN0cmlidWNpw7NuIGRlIGVkYWQgcG9yIGdydXBvcyBkZSB1c3VhcmlvcyBvIG5vIHVzdWFyaW9zIGRlIFdoYXRzYXBwIGVzIG1lZGlhbnRlIHVuIGdyw6FmaWNvIGRlIGNhamFzIG8gYm94cGxvdC4KQ29uIGVsIGNvbWFuZG8gYGJveHBsb3RgLCBxdWUgZXMgcGFydGUgZGUgbG9zIGNvbWFuZG9zIGRlIGJhc2UgZGUgUiwgc2UgcHVlZGUgaGFjZXIgZXN0b3MgZ3LDoWZpY29zLgpFbCBjb21hbmRvIHBpZGUgcHJpbWVybyBsYSB2YXJpYWJsZSBlbiBlbCBlamUgWSwgbHVlZ28gbGEgdmFyaWFibGUgcXVlIGRlZmluZSBsb3MgZ3J1cG9zIHkgZWwgZGF0YWZyYW1lLgpTZSBwdWVkZSBldGlxdWV0YXIgZWwgZWplIFggeSBZIGNvbiBsb3Mgbm9tYnJlcyBkZSBsYXMgdmFyaWFibGVzLgpDb21vIGxhIHZhcmlhYmxlICJ3YV91c2VyIiBoYSBzaWRvIHRyYW5zZm9ybWFkYSBhIGZhY3RvciB5IGV0aXF1ZXRhZGEsIGFob3JhIGFwYXJlY2VuIGxhcyBldGlxdWV0YXMuCgpgYGB7ciBib3hwbG90IGVkYWR4V2hhLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpib3hwbG90KHEyIH4gd2FfdXNlciwgZGF0YT1sYXBvcDE4LCB4bGFiID0iVXN1YXJpbyBkZSBXaGF0c2FwcCIsIHlsYWI9IkVkYWQiKQpgYGAKCkVzdGUgZ3LDoWZpY28gdGFtYmnDqW4gbG8gcG9kZW1vcyByZXByb2R1Y2lyIGNvbiBsYSBsaWJyZXLDrWEgYGdncGxvdGAuCgpgYGB7cn0KZ2dwbG90KHN1YnNldChsYXBvcDE4LCB3YV91c2VyIT0iTkEiKSwgYWVzKHg9d2FfdXNlciwgeT1xMikpKwogIGdlb21fYm94cGxvdCgpKwogIHlsYWIoIkVkYWQiKSsKICB4bGFiKCJVc3VhcmlvIGRlIFdoYXRzYXBwIikKYGBgCgojIFJlc3VtZW4KCkVuIGVzdGUgZG9jdW1lbnRvIHNlIGhhIHRyYWJhamFkbyBjb24gdmFyaWFibGVzIG51bcOpcmljYXMsIGNvbW8gZWRhZCBvIGHDsW9zIGRlIGVzdHVkaW8uClNlIGhhIGNhbGN1bGFkbyBlc3RhZMOtc3RpY29zIGRlc2NyaXB0aXZvcywgY29tbyBsYSBtZWRpYSBvIGxhIGRlc3ZpYWNpw7NuIGVzdMOhbmRhciBwYXJhIHRvZGEgbGEgcG9ibGFjacOzbiBvIHBvciBncnVwb3MuCkZpbmFsbWVudGUsIHNlIGhhIHByZXNlbnRhZG8gZm9ybWFzIGRlIGdyYWZpY2FyIGVzdGFzIHZhcmlhYmxlcywgbWVkaWFudGUgaGlzdG9ncmFtYXMgbyBib3hwbG90cy4KCiMgQ8OhbGN1bG9zIGluY2x1eWVuZG8gZWwgZWZlY3RvIGRlIGRpc2XDsW8KCkxvcyByZXN1bHRhZG9zIGFudGVyaW9yZXMgbm8gaW5jbHV5ZW4gZWwgZmFjdG9yIGRlIGV4cGFuc2nDs24uClBhcmEgaW5jbHVpcmxvIGVuIGxvcyBjw6FsY3Vsb3Mgc2UgcHVlZGUgdXNhciBlbCBjb21hbmRvIGB3ZWlnaHRlZC5tZWFuYCwgcXVlIGVzIHBhcnRlIGRlIGxhIGxpYnJlcsOtYSBgc3RhdHNgLCBxdWUgdmllbmUgcHJlY2FyZ2FkYSBjb24gUiwgcG9yIGxvIHF1ZSBubyBoYXkgcXVlIGluc3RhbGFybGEuCgpgYGB7ciBjb21hbmRvIHdlaWdodGVkfQp3ZWlnaHRlZC5tZWFuKGxhcG9wMTgkcTIsIGxhcG9wMTgkd2VpZ2h0MTUwMCwgbmEucm09VCkKd2VpZ2h0ZWQubWVhbihsYXBvcDE4JGVkLCBsYXBvcDE4JHdlaWdodDE1MDAsIG5hLnJtPVQpCndlaWdodGVkLm1lYW4obGFwb3AxOCRob21icmUsIGxhcG9wMTgkd2VpZ2h0MTUwMCwgbmEucm09VCkqMTAwCndlaWdodGVkLm1lYW4obGFwb3AxOCR1cmJhbiwgbGFwb3AxOCR3ZWlnaHQxNTAwLCBuYS5ybT1UKSoxMDAKYGBgCgpPdHJhIGZvcm1hIGRlIGNhbGN1bGFyIGxhIG1lZGlhIGluY2x1eWVuZG8gZWwgZmFjdG9yIGRlIGV4cGFuc2nDs24gZXMgbWVkaWFudGUgZGUgZWwgdXNvIGRlIGxhIGxpYnJlcsOtYSBgc3VydmV5YCB5IGVsIGNvbWFuZG8gbmF0aXZvIGBzdnltZWFuYC4KUGFyYSBlc3RvIHNlIHRpZW5lIHF1ZSBkZWZpbmlyIGVsIGRpc2XDsW8gbXVlc3RyYWwgY29uIGVsIGNvbWFuZG8gYHN2eWRlc2lnbmAgeSBndWFyZGFyIGVzdGUgZGlzZcOxbyBlbiB1biBvYmpldG8sIGFxdcOtIGxsYW1hZG8gImxhcG9wLmRlc2lnbiIuCgpgYGB7ciBzdXJ2ZXksIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoc3VydmV5KQpkaXNlbm8xOCA9IHN2eWRlc2lnbihpZHMgPSB+dXBtLCBzdHJhdGEgPSB+ZXN0cmF0b3ByaSwgd2VpZ2h0cyA9IH53ZWlnaHQxNTAwLCBuZXN0PVRSVUUsIGRhdGE9bGFwb3AxOCkKYGBgCgpQYXJhIGNhbGN1bGFyIGVsIHByb21lZGlvLCBzZSB1c2EgZWwgY29tYW5kbyBgc3Z5bWVhbmAgeSBzZSB1c2EgbGEgZXNwZWNpZmljYWNpw7NuIGBuYS5ybT1UYCBkZWJpZG8gYSBxdWUgZXN0YXMgdmFyaWFibGVzIGN1ZW50YW4gY29uIHZhbG9yZXMgcGVyZGlkb3MuCgpgYGB7ciB3ZWlnaHRlZCBtZWFuIGVkYWQgeSBlc3R1ZGlvc30Kc3Z5bWVhbih+cTIsIGRpc2VubzE4LCBuYS5ybT1UKQpzdnltZWFuKH5lZCwgZGlzZW5vMTgsIG5hLnJtPVQpCmBgYAoKUGFyYSBsYXMgdmFyaWFibGVzIGR1bW1pZXMgZWwgcHJvY2VkaW1pZW50byBlcyBlbCBtaXNtbywgc2Fsdm8gcXVlIHNlIGxlIG11bHRpcGxpY2EgcG9yIDEwMCBwYXJhIHByZXNlbnRhcmxvIGVuIGZvcm1hdG8gZGUgcG9yY2VudGFqZQoKYGBge3Igd2VpZ2h0ZWQgbWVhbiBob21icmUgeSB1cmJhbm99CnN2eW1lYW4ofmhvbWJyZSwgZGlzZW5vMTgsIG5hLnJtID1UKSoxMDAKc3Z5bWVhbih+dXJiYW4sIGRpc2VubzE4LCBuYS5ybT1UKSoxMDAKYGBgCgpFbCBwYXF1ZXRlIGBzdXJ2ZXlgIHRhbWJpw6luIHRpZW5lIGNvbWFuZG9zIHBhcmEgcmVwbGljYXIgZ3LDoWZpY29zLgpQb3IgZWplbXBsbywgcGFyYSBjYWxjdWxhciB1biBoaXN0b2dyYW1hIHNpbXBsZS4KCmBgYHtyIHdlaWdodGVkIGhpc3R9CnN2eWhpc3QofmVkLCBkaXNlbm8xOCwgZnJlcSA9IFQpCmBgYAoKUGFyYSBjYWxjdWxhciBlc3RhZMOtc3RpY29zIGRlc2NyaXB0aXZvcyBwb3IgZ3J1cG9zLCBzZSBwdWVkZSB1c2FyIGVsIGNvbWFuZG8gYHN2eWJ5YCwgcXVlIHBlcm1pdGUgZGVmaW5pciBsYSB2YXJpYWJsZSBudW3DqXJpY2EgcXVlIHNlIHF1aWVyZSBkZXNjcmliaXIsIGxhIHZhcmlhYmxlIHF1ZSBkZWZpbmUgbG9zIGdydXBvcyB5IGVsIGVzdGFkw61zdGljbyBwb25kZXJhZG8gcXVlIHNlIHF1aWVyZSBjYWxjdWxhci4KCmBgYHtyIHdlaWdodGVkIGVkIHBvciBncnVwb3N9CnN2eWJ5KH5lZCwgfmZiX3VzZXIsIGRpc2VubzE4LCBzdnltZWFuLCBuYS5ybT1UKQpgYGAKClBhcmEgcmVwcm9kdWNpciB1biBncsOhZmljbyBkZXNjcmlwdGl2byBwb3IgZ3J1cG9zLCBzZSBwdWVkZSB1c2FyIGVsIGNvbWFuZG8gYHN2eWJveHBsb3RgIHBhcmEgY29tcGFyYXIgbGEgZGlzdHJpYnVjacOzbiBkZSBsYSB2YXJpYWJsZSBlZGFkIGVudHJlIGdydXBvcyBkZSB1bmEgdmFyaWFibGUgZGUgdGlwbyBmYWN0b3IsIGNvbW8gdXN1YXJpb3MgZGUgV2hhdHNhcHAuCgpgYGB7ciB3ZWlnaHRlZCBib3hwbG90IHBvciBncnVwb3N9CnN2eWJveHBsb3QofnEyfmZhY3Rvcih3YV91c2VyKSwgZGlzZW5vMTgsIGFsbC5vdXRsaWVycyA9IFQpCmBgYAo=