Efectivos en las Comisarias del Perú

Pregunta: ¿los policías en el Perú están distribuidos equitativamente entre las comisarías del Perú?

¿Cómo cree que es esta distribución de datos?

Para responder a esta pregunta se usa la base de datos de comisarías del Perú de 2017. Esta base de datos está disponible en la sección Microdatos del INEI.

library(rio) 
comi17 = import("bases/comi2017.sav")

Esta base de datos incluye la pregunta sobre el número total de efectivos en cada comisaría. Esta variable se importa en R como una variable numérica, y efectivamente es el tipo de variable correcto.

class(comi17$INF110_TOT)
## [1] "numeric"

Como esta es una variable numérica, se puede describir mediante la media y la mediana.

¿Qué nos indican estos resultados?

library(tidyverse)
comi17 %>%
  summarise(Mínimo = min(INF110_TOT), 
            Mediana = median(INF110_TOT), 
            Promedio = mean(INF110_TOT),
            Máximo = max(INF110_TOT))
##   Mínimo Mediana Promedio Máximo
## 1      3      19 31.61538    259

Se puede graficar la distribución del número de efectivos por comisarias mediante un histograma. ¿Qué nos indica el gráfico?

library(ggplot2)
ggplot(comi17, aes(x=INF110_TOT))+
  geom_histogram()+
  xlab("Número de efectivos") +
  ylab("Frecuencia")+
  theme_light()
## `stat_bin()` using `bins = 30`.
## Pick better value with
## `binwidth`.

Se puede incluir el dato de la media y la mediana en este gráfico. ¿Cómo se interpreta la posición relativa de ambas medidas?

ggplot(comi17, aes(x=INF110_TOT))+
  geom_histogram()+
  geom_vline(xintercept = 19, color = "red")+
  geom_vline(xintercept = 31.6, color = "green")+
  xlab("Número de efectivos") +
  ylab("Frecuencia")+
  theme_light()
## `stat_bin()` using `bins = 30`.
## Pick better value with
## `binwidth`.

Ahora se quiere ver si existen diferencias en el número promedio de efectivos policiales en las comisarías del Perú entre departamentos o entre regiones. A pesar que en formulario se recoge el dato de Departamento, Provincia y Distrito, en la base de datos no se cuenta con esa información. Lo que se tiene es una variable llamada “ubigeo”. Esta variable está estandarizada de tal manera que los dos primeros dígitos corresponden al departamento, los segundos dos dígitos a las provincias y los últimos dos dígitos al distrito. Por lo tanto, para saber en qué departamento está la comisaría se requiere separar los primeros dos dígitos y guardarlos en una nueva variable.

comi17 = comi17 %>%
  mutate(dpto = str_sub(UBIGEO, 1, 2))

Copiamos el código usado para el voto 2016 y lo adaptamos a las necesidades de esta base de datos. La variable “dpto” es una variable de tipo “character” y sabemos que va desde el “01” al “25”, representando cada “número” un departamento del Perú, que hemos asociado a Costa = 1, Sierra = 2 o Selva = 3.

Entonces lo que tenemos que hallar es el código ubigeo de cada departamento y reemplazarlo por el nombre del departamento en el código original. La clasificación la guardamos en otra variable “region”.

comi17 = comi17 %>%
  mutate(region = case_when(
    dpto=="01"~3,
    dpto=="02"~2,
    dpto=="03"~2,
    dpto=="04"~2,
    dpto=="05"~2,
    dpto=="06"~2,
    dpto=="08"~2,
    dpto=="07"~1,
    dpto=="09"~2,
    dpto=="10"~3,
    dpto=="11"~1,
    dpto=="12"~2,
    dpto=="13"~1,
    dpto=="14"~1,
    dpto=="15"~1,
    dpto=="16"~3,
    dpto=="17"~3,
    dpto=="18"~1,
    dpto=="19"~2,
    dpto=="20"~1,
    dpto=="21"~2,
    dpto=="22"~3,
    dpto=="23"~1,
    dpto=="24"~1,
    dpto=="25"~3
  )) 

Esta variable “region” es de tipo numérico, pero los códigos (1, 2 y 3) no son números, sino códigos para Costa, Sierra y Selva, por lo que tenemos que crear otra variable, “region2” que sea de tipo “factor” con las etiquetas correspondientes.

library(forcats)
comi17 = comi17 %>%
  mutate(region2 = factor(region, labels=c("Costa", "Sierra", "Selva")))

Podemos usar esta variable para calcular los descriptivos del número de efectivos por región. ¿Qué conclusión saca de la tabla?

tabla1 = comi17 %>%
  group_by(region2) %>%
  summarise(Mínimo = min(INF110_TOT), 
            Mediana = median(INF110_TOT), 
            Promedio = mean(INF110_TOT),
            Desv = sd(INF110_TOT),
            Máximo = max(INF110_TOT))
tabla1
## # A tibble: 3 × 6
##   region2 Mínimo Mediana Promedio  Desv Máximo
##   <fct>    <dbl>   <dbl>    <dbl> <dbl>  <dbl>
## 1 Costa        4      28     44.3  38.3    259
## 2 Sierra       3      16     24.2  24.8    190
## 3 Selva        4      16     24.0  26.5    165

Esta tabla sirve para comparar los datos descriptivos por grupos de otra variable. Algo similar se puede hacer con el gráfico de cajas, pero comparando medianas y rangos intercuartiles.

ggplot(comi17, aes(y=INF110_TOT, x=region2))+
  geom_boxplot()+
  ylab("Número de efectivos")+
  xlab("Región")+
  theme_get()

Servicios básicos en las comisarías del Perú

Pregunta: ¿Las comisarías del Perú cuentan con servicios básicos?

Para responder estas preguntas, la Encuesta Nacional de Comisarías de 2017 tiene otro módulo sobre infraestructura. Cargamos esa base de datos.

library(rio)
comi17_2 = import("bases/comi2017_2.sav")

Esta base incluye la pregunta INF216 sobre luz eléctrica, la pregunta INF225 sobre agua potable, la pregunta INF230 sobre desagüe y la pregunta INF264_E sobre el servicio de internet.

En primer lugar verificamos cómo se importan las variables. Vemos que se importan como variables numéricas. La variable sobre luz tiene opciones Si = 1 y No = 2. Esta variable es en realidad una de tipo factor.

class(comi17_2$INF216)
## [1] "numeric"
table(comi17_2$INF216)
## 
##    1    2 
## 1485    9

Se procede a crear otra variable “luz”, como la factorización de INF216 con etiquetas Sí y No.

library(tidyverse)
comi17_2 = comi17_2 %>%
  mutate(luz = factor(INF216, labels=c("Sí", "No")))

Esta variable incluye algunas comisarías donde no se tiene el dato, por lo que cuando se calcula la tabla, se filtra solo las respuestas Sí y No. Se guarda los resultados en un objeto “tabla2”.

tabla2 = comi17_2 %>%
  filter(luz == "Sí" | luz == "No") %>%
  count(Luz = luz, name="Frecuencia")
tabla2
##   Luz Frecuencia
## 1  Sí       1485
## 2  No          9

Se añade a este mismo objeto los porcentajes. ¿Qué conclusiones saca de estos resultados?

tabla2 = tabla2 %>%
  mutate(Porcentaje = (Frecuencia / sum(Frecuencia)*100 ))
tabla2
##   Luz Frecuencia Porcentaje
## 1  Sí       1485 99.3975904
## 2  No          9  0.6024096

Se hace el mismo procedimiento con la variable sobre agua potable. En este caso, la variable tiene cinco valores.

class(comi17_2$INF225)
## [1] "numeric"
table(comi17_2$INF225)
## 
##    1    3    4    5    6 
## 1424   28   30   12    1
comi17_2 = comi17_2 %>%
  mutate(agua = factor(INF225, labels=c("Red pública dentro del local", 
                                        "Camión cisterna",
                                        "Pozo",
                                        "Río, acequia o manantial",
                                        "Otro")))
table(comi17_2$agua)
## 
## Red pública dentro del local              Camión cisterna 
##                         1424                           28 
##                         Pozo     Río, acequia o manantial 
##                           30                           12 
##                         Otro 
##                            1

Se calcula la tabla de distribución de frecuencias, con el cálculo de los porcentajes en el mismo código. ¿Qué conclusiones saca de estos resultados?

tabla3 = comi17_2 %>%
  count(Agua = agua, name="Frecuencia") %>%
  mutate(Porcentaje = (Frecuencia / sum(Frecuencia)*100 ))
tabla3
##                           Agua Frecuencia  Porcentaje
## 1 Red pública dentro del local       1424 95.25083612
## 2              Camión cisterna         28  1.87290970
## 3                         Pozo         30  2.00668896
## 4     Río, acequia o manantial         12  0.80267559
## 5                         Otro          1  0.06688963

¿Qué conclusiones saca de estos resultados?

Finalmente, se hace lo mismo para la pregunta sobre internet.

class(comi17_2$INF264_E)
## [1] "numeric"
table(comi17_2$INF264_E)
## 
##   1   2   3   4 
## 127 950 132 286
comi17_2 = comi17_2 %>%
  mutate(internet = factor(INF264_E, labels=c("Sí, pago pendiente", 
                                        "Sí, pago al día",
                                        "Sí, no sabe del pago",
                                        "No cuenta con el servicio")))
table(comi17_2$internet)
## 
##        Sí, pago pendiente           Sí, pago al día      Sí, no sabe del pago 
##                       127                       950                       132 
## No cuenta con el servicio 
##                       286

¿Qué conclusiones saca sobre estos resultados?

tabla5 = comi17_2 %>%
  count(Internet = internet, name="Frecuencia") %>%
  mutate(Porcentaje = (Frecuencia / sum(Frecuencia)*100 ))
tabla5
##                    Internet Frecuencia Porcentaje
## 1        Sí, pago pendiente        127   8.494983
## 2           Sí, pago al día        950  63.545151
## 3      Sí, no sabe del pago        132   8.829431
## 4 No cuenta con el servicio        286  19.130435

Este tipo de variables, de tipo factor, se puede visualizar con gráficos de barras.

graf1 = ggplot(tabla5, aes(x=Internet, y=Porcentaje))+
  geom_bar(stat="identity")+
   geom_text(aes(label=paste(round(Porcentaje, 1))), vjust=-1, size=3)+
  labs(x="Internet", y="Porcentaje")+
  theme_classic()
graf1

Tarea

Calcule las tablas de distribución de frecuencias de luz y de internet por regiones. Grafique.

Pruebas de significancia

Es una de las técnicas más usadas para el análisis en ciencias sociales. Sirve, por ejemplo, para comparar entre grupos:

  • Comparar la media de ingresos de hombres y mujeres

  • Comparar la proporción de personas que votarán a candidato X en Lima y en Regiones

  • Comparar los ingresos de profesores en la gestión pública y en la gestión privada

La idea es comparar las estimaciones puntuales entre ambos grupos y también poder extrapolar estas diferencias a la población.

Vamos a comenzar por comparaciones entre solo 2 grupos (por el momento), que corresponde a una variable binaria o dicotómica, como sexo (hombres/mujeres), ámbito (urbano/rural), gestión educativa (pública/privada).

Para mostrar un ejemplo, vamos a usar el trabajo de (Galarza, Kogan, and Yamada 2012) que evalúa la discriminación en el mercado laborar entre hombres y mujeres. Estos autores enviaron CVs con exactas cualificaciones a ofertas reales de trabajo, variando solo el nombre del aplicante, con nombres de hombres y mujeres. La variable de respuesta es la tasa de respuesta a estos CVs, es decir, de cuántos CVs enviados se recibió una llamada para una entrevista.

En cualquier prueba de significancia se tiene que presentar una hipótesis nula, que generalmente es la hipótesis de no diferencias o de no efectos. Este trabajo parte de una idea que existe una discriminación de género en el mercado laboral, por lo que la hipótesis nula indicaría lo contrario. En el caso de este trabajo se tendría:

H0: Tasa de respuesta a CVs de hombres = Tasa de respuesta a CVs de mujeres

o lo que es lo mismo

H0: Tasa de respuesta a CVs de hombres - Tasa de respuesta a CVs de mujeres = 0

En ese trabajo se presenta el siguiente cuadro de resultados:

En la muestra total de 2,228 CVs enviados, mitad de CVs con nombres de hombres y la otra mitad con nombres de mujeres, todos con las mismas cualificaciones, se tiene que la tasa de respuesta para los CVs de hombres es 13.4% y para los CVs de mujeres es 11.1%.

De acuerdo a las estimaciones puntuales, efectivamente, los hombres tienen una mayor tasa de respuesta a sus CVs que las mujeres, a iguales cualificaciones. Esta conclusión, sin embargo, es solo para las 2,228 observaciones de la muestra. ¿Cómo extrapolar esta conclusión a la población? ¿Toda diferencia puntual se validaría en la población?

Comparación de intervalos de confianza por grupos

Una primera forma “informal” para extrapolar las diferencias en las estimaciones puntuales de la muestra a la población es construyendo los intervalos de confianza para la media o para la proporción por cada uno de los subgrupos.

En este caso, por ejemplo, significaría construir el IC de la tasa de respuesta para hombre y mujeres.

Pregunta: ¿Se pueden construir los IC de cada grupo con los datos de la tabla?

Cada IC sería una extrapolación del parámetro, es decir, el rango de valores de la tasa de respuesta a los CVs de hombres para todo el mercado laboral al 95% de confianza. Lo mismo para la tasa de respuesta de las mujeres.

Una vez construidos los IC, se analiza si estos intervalos se cruzan o no se cruzan. La regla de decisión “informal” es:

  • Si los IC de ambos grupos se cruzan, entonces no se puede afirmar que el parámetro de un grupo sea mayor o menos que el parámetro del otro grupo.

  • Si los IC de ambos grupos NO se cruzan, entonces se puede afirmar, al 95% de confianza, que el parámetro de un grupo es mayor/menor al parámetro del otro grupo.

Ejemplo 1 para una variable numérica: ENL

Pregunta: ¿existen diferencia en la cantidad de libros que leen hombres y mujeres? ¿y entre diferentes niveles socioeconómicos?

La hipótesis cero sería:

Ho: Promedio de libros que lee un hombre = Promedio de libros que lee una mujer.

library(rio)
enl = import("/Users/Arturo/Library/CloudStorage/GoogleDrive-arturo.maldonado@pucp.pe/My Drive/A Cursos/Estadistica_1/Data/ENL2022/ENL2022.sav")
library(tidyverse)
enl = enl %>%
  mutate(sexo = factor(P209, labels=c("Hombre", "Mujer")))
enl = enl %>%
  mutate(nse1 = factor(nse, labels=c("Rural", "Bajo", "Medio", "Alto")))
library(tidyverse)
enl = enl %>%
  mutate(libros = P412_1 + P412_2)
enl %>%
  summarize(mean(P412_1, na.rm=T), 
            mean(P412_2, na.rm=T), 
            mean(libros, na.rm=T))
##   mean(P412_1, na.rm = T) mean(P412_2, na.rm = T) mean(libros, na.rm = T)
## 1                2.468012                1.376829                3.844841
tabla1 = enl %>%
  group_by(sexo) %>%
  summarize(media = mean(libros, na.rm=T), 
            mediana = median(libros, na.rm=T),
            desviacion = sd(libros, na.rm=T))
tabla1
## # A tibble: 2 × 4
##   sexo   media mediana desviacion
##   <fct>  <dbl>   <dbl>      <dbl>
## 1 Hombre  3.93       3       5.65
## 2 Mujer   3.78       3       4.86
ggplot(enl, aes(y= libros, x= sexo))+
  geom_boxplot()+
  scale_y_continuous(limits = c(0, 20))+
  ylab("Total libros leídos")+
  xlab("Sexo")+
  theme_get()
## Warning: Removed 25176 rows containing
## non-finite outside the scale
## range (`stat_boxplot()`).

El cálculo del intervalo de confianza de una media es:

\[ IC = \bar{X} \pm 1.96 * \frac{s} {\sqrt{n}} \]

Para una comparación usando los intervalos de confianza, se puede usar el comando ciMean de la librería lsr. Este comando regresa el límite inferior y el límite superior del intervalo de confianza. Por lo tanto, para guardar solo el mínimo se tiene que especificar lsr::ciMean(P1_6, na.rm=T)[1] y para el máximo cambiaría a [2].

library(lsr)
tabla2 = enl %>%
  summarise(media = mean(libros, na.rm=T),
            desv = sd(libros, na.rm = T),
            liminf = ciMean(libros, na.rm=T)[1],
            limsup = ciMean(libros, na.rm=T)[2]
            )
tabla2
##      media    desv   liminf   limsup
## 1 3.844841 5.22275 3.770435 3.919248
tabla2xsexo = enl %>%
  group_by(sexo) %>%
  summarise(media = mean(libros, na.rm=T),
            desv = sd(libros, na.rm = T),
            liminf = ciMean(libros, na.rm=T)[1],
            limsup = ciMean(libros, na.rm=T)[2]
            )
tabla2xsexo
## # A tibble: 2 × 5
##   sexo   media  desv liminf limsup
##   <fct>  <dbl> <dbl>  <dbl>  <dbl>
## 1 Hombre  3.93  5.65   3.80   4.05
## 2 Mujer   3.78  4.86   3.69   3.87
  • El IC al 95% de confianza, el promedio de libros que lee un hombre está en el siguiente intervalo \[3.80 - 4.05\]

  • El IC al 95% de confianza el libros que lee una mujer está en el siguiente intervalo \[3.69 - 3.87\]

Como ambos intervalos SÍ se traslapan, entonces NO se puede afirmar que esas diferencias se pueden extrapolar la población. NO se puede afirmar que existan diferencias entre hombres y mujeres en el número de libros que leen (sería un “empate técnico”).

Gráfico de IC para comparar medias

library(ggplot2)
graf = ggplot(tabla2xsexo, aes(x=sexo, y=media))+
  geom_bar(stat="identity")+
  geom_errorbar(aes(ymin=liminf, ymax=limsup), width=0.2)+
  geom_text(aes(label=round(media, 1)), vjust=-1, size=4)+
  xlab("Sexo") + ylab("Promedio de libros que lee")+
  ylim(0, 5)
graf

Ejemplo 2 para una variable numérica: ENDO

Pregunta: ¿a cuántos alumnos en promedio atiende un profesor peruano? ¿Existen diferencias de género?

Usando el ejemplo de la ENDO 2020, la hipótesis que se puede evaluar es si los profesores atienden a diferente número de alumnos de acuerdo a su sexo. Como vimos antes, las comparaciones puntuales sugieren diferencias, donde los docentes hombres atienden a más alumnos que las docentes mujeres.

La hipótesis cero sería:

Ho: Promedio de alumnos que acompaña un docente hombre = Promedio de alumnos que acompaña una docente mujer.

library(rio)
endo2020 = import("bases/ENDO_REMOTO_2020.dta")

La variable P1_1 (sexo del docente) está definida originalmente como una variable numérica (esto se puede comprobar con el código str(endo2020$P1_1). Esta variable, sin embargo es de tipo factor.

Se puede crear una nueva variable “sexo” con la variable transformada y etiquetada.

library(dplyr)
library(tidyverse)
endo2020 = endo2020 %>%
  mutate(sexo = factor(P1_1, labels=c("Hombre", "Mujer")))
endo2020 %>%
  summarize(Media = mean(P1_6, na.rm = T), 
            Desv.Std = sd(P1_6, na.rm = T))
##      Media Desv.Std
## 1 39.98644 50.76707
alumxsexo = endo2020 %>%
  group_by(sexo) %>%
  summarize(Media = mean(P1_6, na.rm = T), 
            Desv.Std = sd(P1_6, na.rm = T))
alumxsexo
## # A tibble: 3 × 3
##   sexo   Media Desv.Std
##   <fct>  <dbl>    <dbl>
## 1 Hombre  52.2     60.4
## 2 Mujer   34.1     44.2
## 3 <NA>   NaN       NA

Se encuentra que los docentes hombres acompañan a 52 alumnos en promedio, en comparación con las docentes mujeres que acompañan a 34 alumnos en promedio, es decir 18 alumnos menos en promedio.

Recordemos que el cálculo del intervalo de confianza de una media es:

\[ IC = \bar{X} \pm 1.96 * \frac{s} {\sqrt{n}} \]

Para una comparación usando los intervalos de confianza, se puede usar el comando ciMean de la librería lsr. Este comando regresa el límite inferior y el límite superior del intervalo de confianza. Por lo tanto, para guardar solo el mínimo se tiene que especificar lsr::ciMean(P1_6, na.rm=T)[1] y para el máximo cambiaría a [2].

library(lsr)
endo2020 %>%
  summarise(media = mean(P1_6, na.rm=T),
            desv = sd(P1_6, na.rm = T),
            liminf = ciMean(P1_6, na.rm=T)[1],
            limsup = ciMean(P1_6, na.rm=T)[2]
            )
##      media     desv   liminf  limsup
## 1 39.98644 50.76707 39.26358 40.7093
alumxsexo = endo2020 %>%
  group_by(sexo) %>%
  summarise(media = mean(P1_6, na.rm=T),
            desv = sd(P1_6, na.rm = T),
            liminf = ciMean(P1_6, na.rm=T)[1],
            limsup = ciMean(P1_6, na.rm=T)[2]
            )
alumxsexo
## # A tibble: 3 × 5
##   sexo   media  desv liminf limsup
##   <fct>  <dbl> <dbl>  <dbl>  <dbl>
## 1 Hombre  52.2  60.4   50.7   53.8
## 2 Mujer   34.1  44.2   33.3   34.8
## 3 <NA>   NaN    NA     NA     NA
  • El IC al 95% de confianza, el promedio de alumnos que acompañan los docentes hombre está en el siguiente intervalo \[50.7 - 53.8\]

  • El IC al 95% de confianza el promedio de alumnos que acompañan las docentes mujeres está en el siguiente intervalo \[33.3 - 34.8\]

Como ambos intervalos NO se traslapan (el mayor valor del segundo IC, 34.8 , es menor al mejor valor del primer IC, 50.7), entonces se puede afirmar que esas diferencias se pueden extrapolar la población.

Si los IC se traslapan, entonces, no se puede afirmar que existan diferencias en el número de alumnos que acompañan docentes hombres o mujeres (sería un “empate técnico”).

Gráfico de IC para comparar medias

Se puede graficar ambos intervalos de confianza. Para hacer esto, usaremos la tabla que guarda los datos de los intervalos de confianza.

Esta tabla, sin embargo, tiene una fila de resultados para los valores perdidos. Esta fila no tiene datos por graficar, por lo que tenemos que eliminarla.

Los dataframes se organizan en filas y columnas. La table “ci_alumxsexo” tiene 3 filas y 3 columnas. La tercera fila es la que no tiene datos que graficar. Para eliminar se tiene que especificar la tabla y con los brackets [filas, columnas] definir los datos a eliminar [-3, ]. Se elimina con el signo “-” y como no hay datos luego de la “,”, se indica que no se cambia ninguna columna.

alumxsexo = alumxsexo[-3,]
alumxsexo
## # A tibble: 2 × 5
##   sexo   media  desv liminf limsup
##   <fct>  <dbl> <dbl>  <dbl>  <dbl>
## 1 Hombre  52.2  60.4   50.7   53.8
## 2 Mujer   34.1  44.2   33.3   34.8

Esta tabla se puede usar para crear un gráfico que compare ambos IC con la librería ggplot2 y con la geometría geom_errorbar. Se agrega geom_text para incluir el “texto” con los valores promedio de ambos grupos.

library(ggplot2)
graf1 = ggplot(alumxsexo, aes(x=sexo, y=media))+
  geom_bar(stat="identity")+
  geom_errorbar(aes(ymin=liminf, ymax=limsup), width=0.2)+
  geom_text(aes(label=round(media, 1)), vjust=-1, size=4)+
  xlab("Sexo del docente") + ylab("Promedio de alumnos")+
  ylim(0, 60)
graf1

En este gráfico queda más claro que ambos IC no se traslapan por lo que se puede decir que sí existen diferencias entre docentes hombre y mujeres en el número de alumnos que acompañan en el Perú.

Este tipo de gráfico es bastante usual en los reportes estadísticos. Por ejemplo, se pueden ver este tipo de gráficos en los reportes de El Pulso de la Democracia del proyecto LAPOP. En el último reporte para Perú se presenta el siguiente gráfico que muestra los niveles de satisfacción con la democracia entre grupos de satisfacción con los servicios públicos. Estos gráficos son construidos de la misma manera que se ha construido el gráfico de arriba.

¿Por qué?. .. Aquí viene la interpretación del politólogo .

OJO: no se debe confundir este gráfico con un gráfico de cajas.

TAREA: Analizar si existen diferencias en el número de alumnos entre docentes con diferentes condiciones laborales (P1_7).

Ejemplo 3 para una variable numérica: LAPOP

library(rio)
lapop = import("bases/PER_2023_LAPOP_AmericasBarometer_v1.0_w.sav")

Ejemplo para variable numérica con índice aditivo

El cuestionario de LAPOP incluye dos preguntas sobre las fuerzas del orden. B12. ¿Hasta qué punto tiene usted confianza en las Fuerzas Armadas? y B18. ¿Hasta qué punto tiene usted confianza en la policía nacional?

Ambas preguntas están medidas en una escala de 1 a 7, donde 1 significa “Nada” y 7 significa “Mucho”. Una persona que tenga desconfianza de las fuerzas del orden en general, seguramente reportará puntajes bajos en ambas preguntas. Por el contrario, una persona que tenga alta confianza en las fuerzas del orden en general, puede reportar puntajes altos en ambas preguntas.

Se pueden combinar ambas preguntas para generar un índice aditivo de confianza general en las fuerzas del orden, como la suma de ambas. Como cada pregunta puede ser respondida entre 1 y 7, la suma puede variar entre 2 y 14. Un puntaje de 2 expresará la más baja confianza en las fuerzas del orden. Un puntaje de 14, la más alta confianza en las fuerzas del orden. Cualquier puntaje intermedio, expresará una confianza intermedia.

Como NO es intuitivo tener un índice que varíe entre 2 y 14, se puede restar dos a la suma para que el índice varíe entre 0 y 12. Como esta variación tampoco es intuitiva, se puede dividir todo entre 12 para que el índice varíe entre 0 y 1.

Confianza en FFAA Confianza en policía Confianza general Confianza general - 2 (Confianza general - 2) / 12 (Confianza general - 2) / 12*100
Persona con mucha desconfianza en las fuerzas del orden 1 1 2 0 0 0
Persona con mucha confianza en las fuerzas del orden 7 7 14 12 1 100
Persona con confianza media en las fuerzas del orden 4 5 9 7 0.58 58
Persona con confianza media en las fuerzas del orden 6 4 10 8 0.66 66

De esta manera cada persona tiene un puntaje que puede variar entre 0 y 1, dependiendo de las respuestas que dio a cada una de las preguntas individuales.

Esto se puede calcular en R.

library(tidyverse)
lapop = lapop %>%
  mutate(indice = (b12+b18-2)/12*100)

Podemos asumir que este índice es una variable cuantitativa, por lo que podemos calcular la media y el intervalo de confianza de la media.

library(lsr)
lapop %>%
  summarise(media = mean(indice, na.rm=T),
            liminf = ciMean(indice, na.rm=T)[1],
            limsup = ciMean(indice, na.rm=T)[2]
            )
##      media   liminf  limsup
## 1 47.81916 46.42952 49.2088

Mejor aún, podemos calcular el índice de confianza en las fuerzas del orden por año de la encuesta.

indicexwave = lapop %>%
  group_by(wave) %>%
  summarise(media = mean(indice, na.rm=T),
            liminf = ciMean(indice, na.rm=T)[1],
            limsup = ciMean(indice, na.rm=T)[2]
            )
indicexwave
## # A tibble: 1 × 4
##    wave media liminf limsup
##   <dbl> <dbl>  <dbl>  <dbl>
## 1  2023  47.8   46.4   49.2

Con lo que podemos comparar el índice de apoyo a las fuerzas del orden por año para sacar conclusiones acerca de diferencias.

library(ggplot2)
graf3 = ggplot(indicexwave, aes(x=wave, y=media))+
  geom_bar(stat="identity")+
  geom_errorbar(aes(ymin=liminf, ymax=limsup), width=0.2)+
  geom_text(aes(label=paste(round(media, 1))), vjust=-1, size=4)+
  xlab("Año de encuestas") + ylab("Índice de confianza en las fuerzas del orden")+
  ylim(0, 60)
graf3

Ejemplo 1 para una variable categórica: ENDO

Siguiendo con el ejemplo de la ENDO 2020, la hipótesis que se puede evaluar es si existen diferencias en si los docentes han recibido apoyo psicológico o emocional por sexo (P1_13).

La hipótesis cero sería: La proporción de docentes que han recibido apoyo psicológico entre docentes hombres = Proporción de docentes que han recibido apoyo psicológico entre docentes mujeres.

Lo primero es transformar la variable P1_13 que es importada como numérica, como una variable de factor y con sus etiquetas.

endo2020 = endo2020 %>%
  mutate(apoyo = factor(P1_13, labels=c("Sí", "No")))

Ahora tenemos que producir la tabla de distribución de frecuencias. Si calculamos las frecuencias con count directamente, esta tabla incluiría una fila de los NAs y luego calculará los porcentajes incluyendo a este grupo. Es por esto que antes de calcular las frecuencias, tenemos que filtrar para que solo cuente los “Sí” y “No”. Luego de las frecuencias, incluimos el porcentaje con mutate.

tabla = endo2020 %>%
  filter(apoyo =="Sí" | apoyo == "No") %>%
  count(Apoyo = apoyo, name="N") %>%
  mutate(total = sum(N), 
         Porcentaje = N / total * 100)
tabla
##   Apoyo    N total Porcentaje
## 1    Sí 9476 18930   50.05811
## 2    No 9454 18930   49.94189

Por ejemplo, para hallar el IC de la proporción de aquellos docentes que reportaron haber recibido apoyo psicológico, podemos usar el comando prop.test. Este comando requiere el n de la opción “Sí” de la tabla y el total de casos. Por defecto nos calcula el IC al 95% de confianza.

prop.test(9476,18930)
## 
##  1-sample proportions test with continuity correction
## 
## data:  9476 out of 18930, null probability 0.5
## X-squared = 0.023296, df = 1, p-value = 0.8787
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
##  0.4934326 0.5077293
## sample estimates:
##         p 
## 0.5005811

Se estima que el la proporción de docentes que recibieron apoyo psicológico está entre 49.3% y 50.8%.

Luego, para responder a la pregunta de si esta proporción varía entre docentes hombres y mujeres, tenemos que crear otra tabla con las frecuencias y porcentajes por cada grupo de la variable “sexo”. Para esto, al código anterior le agregamos el comando group_by.

tabla2 = endo2020 %>%
  filter(apoyo =="Sí" | apoyo == "No") %>%
  group_by(sexo) %>%
  count(Apoyo = apoyo, name="N") %>%
  mutate(total = sum(N), 
         Por = N / total * 100,
         err = sqrt(Por*(100-Por)/N), 
         liminf = Por - 1.96*err, 
         limsup = Por + 1.96*err)
tabla2
## # A tibble: 4 × 8
## # Groups:   sexo [2]
##   sexo   Apoyo     N total   Por   err liminf limsup
##   <fct>  <fct> <int> <int> <dbl> <dbl>  <dbl>  <dbl>
## 1 Hombre Sí     2777  6163  45.1 0.944   43.2   46.9
## 2 Hombre No     3386  6163  54.9 0.855   53.3   56.6
## 3 Mujer  Sí     6699 12767  52.5 0.610   51.3   53.7
## 4 Mujer  No     6068 12767  47.5 0.641   46.3   48.8

El mismo comando prop.test permite hacer la prueba para la diferencia de proporciones. Para esto, los valores tanto de hombres, como de mujeres, se concatenan con la especificación c(…), tanto para el n de “Sí” de cada grupo, como para el total de casos de cada grupo.

prop.test(c(2777, 6699), c(6163,12767))
## 
##  2-sample test for equality of proportions with continuity correction
## 
## data:  c(2777, 6699) out of c(6163, 12767)
## X-squared = 91.044, df = 1, p-value < 2.2e-16
## alternative hypothesis: two.sided
## 95 percent confidence interval:
##  -0.08938432 -0.05885549
## sample estimates:
##    prop 1    prop 2 
## 0.4505922 0.5247121

Según los resultados, se encuentra que el 52.5% de docentes mujeres recibieron apoyo psicológico versus el 45.1% de docentes hombres. Este comando no nos brinda directamente los límites inferior y superior de los IC de cada grupo, pero nos brinda el IC de la diferencia de proporciones al 95% de confianza. Este IC de la diferencia de proporciones varía entre -8.9% y -5.9%.

Como este IC va solo entre valores negativos; es decir, como el IC no incluye al cero, se puede concluir que la diferencia de proporciones no puede ser cero, por lo tanto, que existe una diferencia estadísticamente significativa en las proporciones entre ambos grupos.

La tabla 2 se puede usar para graficar. Como nos interesa comparar los porcentajes de docentes que reportaron haber recibido atención psicológica por sexo, se puede eliminar las filas de aquellos que no recibieron atención psicológica en la tabla 2.

tabla2 = tabla2[-c(2,4),]

Luego, con esta tabla podemos seguir el mismo procedimiento que con el cálculo de las barras de error para la media, pero esta vez para los porcentajes.

library(ggplot2)
graf2 = ggplot(tabla2, aes(x=sexo, y=Por))+
  geom_bar(stat="identity")+
  geom_errorbar(aes(ymin=liminf, ymax=limsup), width=0.2)+
  geom_text(aes(label=paste(round(Por, 1))), vjust=-1, size=4)+
  xlab("Sexo del docente") + ylab("Porcentaje que recibió atención psicológica")+
  ylim(0, 60)
graf2

De este gráfico se puede concluir que existen diferencias estadísticamente significativas en el porcentaje de docentes que buscaron atención psicológica entre hombres y mujeres, debido a que los intervalos de confianza no se traslapan.

De manera más específica, se puede afirmar que las docentes peruanas reciben más atención psicológica que los docentes hombres.

Ejemplo 2 para una variable categórica: LAPOP

En la página 21 del reporte Cultura política de la democracia en Perú y en las Américas 2021: Tomándole el pulso a la democracia se presenta el gráfico que muestra el porcentaje de apoyo a la democracia en Perú (línea magenta) a lo largo del tiempo, en comparación con América Latina (línea morada).

El apoyo a la democracia, variable “ING4”, está medida en una escala del 1 al 7, donde 1 significa “muy en desacuerdo” y 7 significa “muy de acuerdo”. Esta variable se tiene que recodificar. De acuerdo al reporte “Las respuestas van de 1 (muy en desacuerdo) a 7 (muy de acuerdo). Para este análisis, se codificaron las respuestas en el extremo”de acuerdo” de la escala (valores que van de 5 a 7) como apoyo a la democracia.” (p.7).

Para recodificar la variable se usa el siguiente código. El resultado es una variable dicotómica (0=No, 1=Sí), que es una variable categórica, aunque incluye un grupo que no tiene respuesta en esta variable y está como NAs.

library(dplyr)
lapop = lapop %>%
  mutate(ing4rec= case_when(
    ing4 >= 1 & ing4 <= 4 ~ 0,
    ing4 >= 5 & ing4 <= 7 ~ 1,
    ))

Se verifica la recodificación.

lapop %>%
  count(ing4, name="Frecuencia")
##   ing4 Frecuencia
## 1    1        113
## 2    2        109
## 3    3        191
## 4    4        335
## 5    5        337
## 6    6        200
## 7    7        236
## 8   NA         14

Lo que queremos es encontrar el intervalo de confianza de la proporción (o porcentaje) de aquellos que responden “Sí” (las 7754 personas con un 1). Ojo que la tabla muestra a 393 personas con NAs.

lapop %>%
  count(ing4rec, name="Frecuencia")
##   ing4rec Frecuencia
## 1       0        748
## 2       1        773
## 3      NA         14

Y queremos calcular el porcentaje de aquellos que responden “Sí” por año de la encuesta. La variable que registra el año de la encuesta es “wave”. Esta variable se carga como una numérica (por este motivo, en el gráfico anterior el eje X del gráfico aparece como una variable continua) y se tiene que transformar a una de factor llamada “ronda”.

lapop = lapop %>%
  mutate(ronda = factor(wave))

Se calcula el apoyo a la democracia por años. Para el cálculo de esta tabla queremos excluir a aquellos que no tienen respuesta en la variable apoyo a la democracia (los 393 NAs anteriores). Esto lo podemos hacer con el comando filter, donde especificamos que solo queremos calcular los porcentajes de aquellos que respondieron No (o 0 en la variable) y aquellos que respondieron Sí (o 1 en la variable).

En cada grupo se quiere calcular el intervalo de confianza de la proporción. Recuerden que la fórmula que se tiene que usar es la de intervalos de confianza de la proporción.

Dentro del comando mutate calculamos el total en cada grupo (total), la proporción (Por), el error estándar (err que es igual a la raíz cuadrada del porcentaje por 100-porcentaje entre N) y el límite inferior y superior del intervalo de confianza.

tabla3 = lapop %>%
  filter(ing4rec ==0 | ing4rec == 1) %>%
  group_by(ronda) %>%
  count(Apoyo = ing4rec, name="N") %>%
  mutate(total = sum(N), 
         Por = N / total * 100, 
         err = sqrt(Por*(100-Por)/N), 
         liminf = Por - 1.96*err, 
         limsup = Por + 1.96*err)
tabla3
## # A tibble: 2 × 8
## # Groups:   ronda [1]
##   ronda Apoyo     N total   Por   err liminf limsup
##   <fct> <dbl> <int> <int> <dbl> <dbl>  <dbl>  <dbl>
## 1 2023      0   748  1521  49.2  1.83   45.6   52.8
## 2 2023      1   773  1521  50.8  1.80   47.3   54.3

La tabla muestra los datos de los que no apoyan a la democracia (filas donde Apoyo=0) y de los que sí apoyan a la democracia (filas donde Apoyo=1) por cada ronda.

Como solo se quiere graficar a los que sí apoyan a la democracia, se deben eliminar todas las filas impares.

tabla3 = tabla3[-c(1,3,5,7,9,11,13,15),]
tabla3
## # A tibble: 1 × 8
## # Groups:   ronda [1]
##   ronda Apoyo     N total   Por   err liminf limsup
##   <fct> <dbl> <int> <int> <dbl> <dbl>  <dbl>  <dbl>
## 1 2023      1   773  1521  50.8  1.80   47.3   54.3

Ahora, tenemos los datos para graficar.

graf4 = ggplot(tabla3, aes(x=ronda, y=Por))+
  geom_bar(stat="identity")+
  geom_errorbar(aes(ymin=liminf, ymax=limsup), width=0.2)+
  geom_text(aes(label=paste(round(Por, 1))), vjust=-1, size=4)+
  xlab("Ronda") + ylab("Porcentaje que apoya a la democracia")+
  ylim(0, 70)
graf4

Nota final

La comparación de IC, ya sea calculando los valores para cada grupo o ya sea de manera gráfica, es una primera manera de analizar si las diferencias entre grupos se pueden extrapolar a la población.

Pero esta es una manera “informal” de hacer esta comparación. Para formalizar esta comparación existe una prueba estadística llamada prueba t de diferencias de medias o la prueba de proporciones, que se verán en la siguiente sesión.

Bibliografía

Galarza, Francisco, Liuba Kogan, and Gustavo Yamada. 2012. “Detectando Discriminación Sexual y Racial En El Mercado Laboral de Lima.” In Chapters of Books, 1:103–35. Fondo Editorial, Universidad del Pacífico.
LS0tCnRpdGxlOiAiQ2xhc2UgNDogRWplbXBsb3MgZSBJbnRlcnZhbG9zIGRlIENvbmZpYW56YSIKYXV0aG9yOiAiQXJ0dXJvIE1hbGRvbmFkbyIKZGF0ZTogIjEwLTE3LzA5LzIwMjQiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvbGxhcHNlZDogZmFsc2UKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgIHRvY19kZXB0aDogMQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IGNvc21vCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlCmVkaXRvcl9vcHRpb25zOgogIG1hcmtkb3duOgogICAgd3JhcDogc2VudGVuY2UKYmlibGlvZ3JhcGh5OiByZWZlcmVuY2VzLmJpYgotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKIyBFZmVjdGl2b3MgZW4gbGFzIENvbWlzYXJpYXMgZGVsIFBlcsO6CgoqUHJlZ3VudGE6IMK/bG9zIHBvbGljw61hcyBlbiBlbCBQZXLDuiBlc3TDoW4gZGlzdHJpYnVpZG9zIGVxdWl0YXRpdmFtZW50ZSBlbnRyZSBsYXMgY29taXNhcsOtYXMgZGVsIFBlcsO6PyoKCirCv0PDs21vIGNyZWUgcXVlIGVzIGVzdGEgZGlzdHJpYnVjacOzbiBkZSBkYXRvcz8qCgpQYXJhIHJlc3BvbmRlciBhIGVzdGEgcHJlZ3VudGEgc2UgdXNhIGxhIGJhc2UgZGUgZGF0b3MgZGUgY29taXNhcsOtYXMgZGVsIFBlcsO6IGRlIDIwMTcuCkVzdGEgYmFzZSBkZSBkYXRvcyBlc3TDoSBkaXNwb25pYmxlIGVuIGxhIHNlY2Npw7NuIFtNaWNyb2RhdG9zXShodHRwczovL3Byb3llY3Rvcy5pbmVpLmdvYi5wZS9taWNyb2RhdG9zLykgZGVsIElORUkuCgpgYGB7cn0KbGlicmFyeShyaW8pIApjb21pMTcgPSBpbXBvcnQoImJhc2VzL2NvbWkyMDE3LnNhdiIpCmBgYAoKRXN0YSBiYXNlIGRlIGRhdG9zIGluY2x1eWUgbGEgcHJlZ3VudGEgc29icmUgZWwgbsO6bWVybyB0b3RhbCBkZSBlZmVjdGl2b3MgZW4gY2FkYSBjb21pc2Fyw61hLgpFc3RhIHZhcmlhYmxlIHNlIGltcG9ydGEgZW4gUiBjb21vIHVuYSB2YXJpYWJsZSBudW3DqXJpY2EsIHkgZWZlY3RpdmFtZW50ZSBlcyBlbCB0aXBvIGRlIHZhcmlhYmxlIGNvcnJlY3RvLgoKYGBge3J9CmNsYXNzKGNvbWkxNyRJTkYxMTBfVE9UKQpgYGAKCkNvbW8gZXN0YSBlcyB1bmEgdmFyaWFibGUgbnVtw6lyaWNhLCBzZSBwdWVkZSBkZXNjcmliaXIgbWVkaWFudGUgbGEgbWVkaWEgeSBsYSBtZWRpYW5hLgoKwr9RdcOpIG5vcyBpbmRpY2FuIGVzdG9zIHJlc3VsdGFkb3M/CgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmNvbWkxNyAlPiUKICBzdW1tYXJpc2UoTcOtbmltbyA9IG1pbihJTkYxMTBfVE9UKSwgCiAgICAgICAgICAgIE1lZGlhbmEgPSBtZWRpYW4oSU5GMTEwX1RPVCksIAogICAgICAgICAgICBQcm9tZWRpbyA9IG1lYW4oSU5GMTEwX1RPVCksCiAgICAgICAgICAgIE3DoXhpbW8gPSBtYXgoSU5GMTEwX1RPVCkpCmBgYAoKU2UgcHVlZGUgZ3JhZmljYXIgbGEgZGlzdHJpYnVjacOzbiBkZWwgbsO6bWVybyBkZSBlZmVjdGl2b3MgcG9yIGNvbWlzYXJpYXMgbWVkaWFudGUgdW4gaGlzdG9ncmFtYS4Kwr9RdcOpIG5vcyBpbmRpY2EgZWwgZ3LDoWZpY28/CgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpnZ3Bsb3QoY29taTE3LCBhZXMoeD1JTkYxMTBfVE9UKSkrCiAgZ2VvbV9oaXN0b2dyYW0oKSsKICB4bGFiKCJOw7ptZXJvIGRlIGVmZWN0aXZvcyIpICsKICB5bGFiKCJGcmVjdWVuY2lhIikrCiAgdGhlbWVfbGlnaHQoKQpgYGAKClNlIHB1ZWRlIGluY2x1aXIgZWwgZGF0byBkZSBsYSBtZWRpYSB5IGxhIG1lZGlhbmEgZW4gZXN0ZSBncsOhZmljby4Kwr9Dw7NtbyBzZSBpbnRlcnByZXRhIGxhIHBvc2ljacOzbiByZWxhdGl2YSBkZSBhbWJhcyBtZWRpZGFzPwoKYGBge3J9CmdncGxvdChjb21pMTcsIGFlcyh4PUlORjExMF9UT1QpKSsKICBnZW9tX2hpc3RvZ3JhbSgpKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDE5LCBjb2xvciA9ICJyZWQiKSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAzMS42LCBjb2xvciA9ICJncmVlbiIpKwogIHhsYWIoIk7Dum1lcm8gZGUgZWZlY3Rpdm9zIikgKwogIHlsYWIoIkZyZWN1ZW5jaWEiKSsKICB0aGVtZV9saWdodCgpCmBgYAoKQWhvcmEgc2UgcXVpZXJlIHZlciBzaSBleGlzdGVuIGRpZmVyZW5jaWFzIGVuIGVsIG7Dum1lcm8gcHJvbWVkaW8gZGUgZWZlY3Rpdm9zIHBvbGljaWFsZXMgZW4gbGFzIGNvbWlzYXLDrWFzIGRlbCBQZXLDuiBlbnRyZSBkZXBhcnRhbWVudG9zIG8gZW50cmUgcmVnaW9uZXMuCkEgcGVzYXIgcXVlIGVuIGZvcm11bGFyaW8gc2UgcmVjb2dlIGVsIGRhdG8gZGUgRGVwYXJ0YW1lbnRvLCBQcm92aW5jaWEgeSBEaXN0cml0bywgZW4gbGEgYmFzZSBkZSBkYXRvcyBubyBzZSBjdWVudGEgY29uIGVzYSBpbmZvcm1hY2nDs24uCkxvIHF1ZSBzZSB0aWVuZSBlcyB1bmEgdmFyaWFibGUgbGxhbWFkYSAidWJpZ2VvIi4KRXN0YSB2YXJpYWJsZSBlc3TDoSBlc3RhbmRhcml6YWRhIGRlIHRhbCBtYW5lcmEgcXVlIGxvcyBkb3MgcHJpbWVyb3MgZMOtZ2l0b3MgY29ycmVzcG9uZGVuIGFsIGRlcGFydGFtZW50bywgbG9zIHNlZ3VuZG9zIGRvcyBkw61naXRvcyBhIGxhcyBwcm92aW5jaWFzIHkgbG9zIMO6bHRpbW9zIGRvcyBkw61naXRvcyBhbCBkaXN0cml0by4KUG9yIGxvIHRhbnRvLCBwYXJhIHNhYmVyIGVuIHF1w6kgZGVwYXJ0YW1lbnRvIGVzdMOhIGxhIGNvbWlzYXLDrWEgc2UgcmVxdWllcmUgc2VwYXJhciBsb3MgcHJpbWVyb3MgZG9zIGTDrWdpdG9zIHkgZ3VhcmRhcmxvcyBlbiB1bmEgbnVldmEgdmFyaWFibGUuCgpgYGB7cn0KY29taTE3ID0gY29taTE3ICU+JQogIG11dGF0ZShkcHRvID0gc3RyX3N1YihVQklHRU8sIDEsIDIpKQpgYGAKCkNvcGlhbW9zIGVsIGPDs2RpZ28gdXNhZG8gcGFyYSBlbCB2b3RvIDIwMTYgeSBsbyBhZGFwdGFtb3MgYSBsYXMgbmVjZXNpZGFkZXMgZGUgZXN0YSBiYXNlIGRlIGRhdG9zLgpMYSB2YXJpYWJsZSAiZHB0byIgZXMgdW5hIHZhcmlhYmxlIGRlIHRpcG8gImNoYXJhY3RlciIgeSBzYWJlbW9zIHF1ZSB2YSBkZXNkZSBlbCAiMDEiIGFsICIyNSIsIHJlcHJlc2VudGFuZG8gY2FkYSAibsO6bWVybyIgdW4gZGVwYXJ0YW1lbnRvIGRlbCBQZXLDuiwgcXVlIGhlbW9zIGFzb2NpYWRvIGEgQ29zdGEgPSAxLCBTaWVycmEgPSAyIG8gU2VsdmEgPSAzLgoKRW50b25jZXMgbG8gcXVlIHRlbmVtb3MgcXVlIGhhbGxhciBlcyBlbCBjw7NkaWdvIHViaWdlbyBkZSBjYWRhIGRlcGFydGFtZW50byB5IHJlZW1wbGF6YXJsbyBwb3IgZWwgbm9tYnJlIGRlbCBkZXBhcnRhbWVudG8gZW4gZWwgY8OzZGlnbyBvcmlnaW5hbC4KTGEgY2xhc2lmaWNhY2nDs24gbGEgZ3VhcmRhbW9zIGVuIG90cmEgdmFyaWFibGUgInJlZ2lvbiIuCgpgYGB7cn0KY29taTE3ID0gY29taTE3ICU+JQogIG11dGF0ZShyZWdpb24gPSBjYXNlX3doZW4oCiAgICBkcHRvPT0iMDEifjMsCiAgICBkcHRvPT0iMDIifjIsCiAgICBkcHRvPT0iMDMifjIsCiAgICBkcHRvPT0iMDQifjIsCiAgICBkcHRvPT0iMDUifjIsCiAgICBkcHRvPT0iMDYifjIsCiAgICBkcHRvPT0iMDgifjIsCiAgICBkcHRvPT0iMDcifjEsCiAgICBkcHRvPT0iMDkifjIsCiAgICBkcHRvPT0iMTAifjMsCiAgICBkcHRvPT0iMTEifjEsCiAgICBkcHRvPT0iMTIifjIsCiAgICBkcHRvPT0iMTMifjEsCiAgICBkcHRvPT0iMTQifjEsCiAgICBkcHRvPT0iMTUifjEsCiAgICBkcHRvPT0iMTYifjMsCiAgICBkcHRvPT0iMTcifjMsCiAgICBkcHRvPT0iMTgifjEsCiAgICBkcHRvPT0iMTkifjIsCiAgICBkcHRvPT0iMjAifjEsCiAgICBkcHRvPT0iMjEifjIsCiAgICBkcHRvPT0iMjIifjMsCiAgICBkcHRvPT0iMjMifjEsCiAgICBkcHRvPT0iMjQifjEsCiAgICBkcHRvPT0iMjUifjMKICApKSAKYGBgCgpFc3RhIHZhcmlhYmxlICJyZWdpb24iIGVzIGRlIHRpcG8gbnVtw6lyaWNvLCBwZXJvIGxvcyBjw7NkaWdvcyAoMSwgMiB5IDMpIG5vIHNvbiBuw7ptZXJvcywgc2lubyBjw7NkaWdvcyBwYXJhIENvc3RhLCBTaWVycmEgeSBTZWx2YSwgcG9yIGxvIHF1ZSB0ZW5lbW9zIHF1ZSBjcmVhciBvdHJhIHZhcmlhYmxlLCAicmVnaW9uMiIgcXVlIHNlYSBkZSB0aXBvICJmYWN0b3IiIGNvbiBsYXMgZXRpcXVldGFzIGNvcnJlc3BvbmRpZW50ZXMuCgpgYGB7cn0KbGlicmFyeShmb3JjYXRzKQpjb21pMTcgPSBjb21pMTcgJT4lCiAgbXV0YXRlKHJlZ2lvbjIgPSBmYWN0b3IocmVnaW9uLCBsYWJlbHM9YygiQ29zdGEiLCAiU2llcnJhIiwgIlNlbHZhIikpKQpgYGAKClBvZGVtb3MgdXNhciBlc3RhIHZhcmlhYmxlIHBhcmEgY2FsY3VsYXIgbG9zIGRlc2NyaXB0aXZvcyBkZWwgbsO6bWVybyBkZSBlZmVjdGl2b3MgcG9yIHJlZ2nDs24uCsK/UXXDqSBjb25jbHVzacOzbiBzYWNhIGRlIGxhIHRhYmxhPwoKYGBge3J9CnRhYmxhMSA9IGNvbWkxNyAlPiUKICBncm91cF9ieShyZWdpb24yKSAlPiUKICBzdW1tYXJpc2UoTcOtbmltbyA9IG1pbihJTkYxMTBfVE9UKSwgCiAgICAgICAgICAgIE1lZGlhbmEgPSBtZWRpYW4oSU5GMTEwX1RPVCksIAogICAgICAgICAgICBQcm9tZWRpbyA9IG1lYW4oSU5GMTEwX1RPVCksCiAgICAgICAgICAgIERlc3YgPSBzZChJTkYxMTBfVE9UKSwKICAgICAgICAgICAgTcOheGltbyA9IG1heChJTkYxMTBfVE9UKSkKdGFibGExCmBgYAoKRXN0YSB0YWJsYSBzaXJ2ZSBwYXJhIGNvbXBhcmFyIGxvcyBkYXRvcyBkZXNjcmlwdGl2b3MgcG9yIGdydXBvcyBkZSBvdHJhIHZhcmlhYmxlLgpBbGdvIHNpbWlsYXIgc2UgcHVlZGUgaGFjZXIgY29uIGVsIGdyw6FmaWNvIGRlIGNhamFzLCBwZXJvIGNvbXBhcmFuZG8gbWVkaWFuYXMgeSByYW5nb3MgaW50ZXJjdWFydGlsZXMuCgpgYGB7cn0KZ2dwbG90KGNvbWkxNywgYWVzKHk9SU5GMTEwX1RPVCwgeD1yZWdpb24yKSkrCiAgZ2VvbV9ib3hwbG90KCkrCiAgeWxhYigiTsO6bWVybyBkZSBlZmVjdGl2b3MiKSsKICB4bGFiKCJSZWdpw7NuIikrCiAgdGhlbWVfZ2V0KCkKYGBgCgojIFNlcnZpY2lvcyBiw6FzaWNvcyBlbiBsYXMgY29taXNhcsOtYXMgZGVsIFBlcsO6CgoqUHJlZ3VudGE6IMK/TGFzIGNvbWlzYXLDrWFzIGRlbCBQZXLDuiBjdWVudGFuIGNvbiBzZXJ2aWNpb3MgYsOhc2ljb3M/KgoKUGFyYSByZXNwb25kZXIgZXN0YXMgcHJlZ3VudGFzLCBsYSBFbmN1ZXN0YSBOYWNpb25hbCBkZSBDb21pc2Fyw61hcyBkZSAyMDE3IHRpZW5lIG90cm8gbcOzZHVsbyBzb2JyZSBpbmZyYWVzdHJ1Y3R1cmEuCkNhcmdhbW9zIGVzYSBiYXNlIGRlIGRhdG9zLgoKYGBge3J9CmxpYnJhcnkocmlvKQpjb21pMTdfMiA9IGltcG9ydCgiYmFzZXMvY29taTIwMTdfMi5zYXYiKQpgYGAKCkVzdGEgYmFzZSBpbmNsdXllIGxhIHByZWd1bnRhIElORjIxNiBzb2JyZSBsdXogZWzDqWN0cmljYSwgbGEgcHJlZ3VudGEgSU5GMjI1IHNvYnJlIGFndWEgcG90YWJsZSwgbGEgcHJlZ3VudGEgSU5GMjMwIHNvYnJlIGRlc2Fnw7xlIHkgbGEgcHJlZ3VudGEgSU5GMjY0X0Ugc29icmUgZWwgc2VydmljaW8gZGUgaW50ZXJuZXQuCgpFbiBwcmltZXIgbHVnYXIgdmVyaWZpY2Ftb3MgY8OzbW8gc2UgaW1wb3J0YW4gbGFzIHZhcmlhYmxlcy4KVmVtb3MgcXVlIHNlIGltcG9ydGFuIGNvbW8gdmFyaWFibGVzIG51bcOpcmljYXMuCkxhIHZhcmlhYmxlIHNvYnJlIGx1eiB0aWVuZSBvcGNpb25lcyBTaSA9IDEgeSBObyA9IDIuCkVzdGEgdmFyaWFibGUgZXMgZW4gcmVhbGlkYWQgdW5hIGRlIHRpcG8gZmFjdG9yLgoKYGBge3J9CmNsYXNzKGNvbWkxN18yJElORjIxNikKdGFibGUoY29taTE3XzIkSU5GMjE2KQpgYGAKClNlIHByb2NlZGUgYSBjcmVhciBvdHJhIHZhcmlhYmxlICJsdXoiLCBjb21vIGxhIGZhY3Rvcml6YWNpw7NuIGRlIElORjIxNiBjb24gZXRpcXVldGFzIFPDrSB5IE5vLgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpjb21pMTdfMiA9IGNvbWkxN18yICU+JQogIG11dGF0ZShsdXogPSBmYWN0b3IoSU5GMjE2LCBsYWJlbHM9YygiU8OtIiwgIk5vIikpKQpgYGAKCkVzdGEgdmFyaWFibGUgaW5jbHV5ZSBhbGd1bmFzIGNvbWlzYXLDrWFzIGRvbmRlIG5vIHNlIHRpZW5lIGVsIGRhdG8sIHBvciBsbyBxdWUgY3VhbmRvIHNlIGNhbGN1bGEgbGEgdGFibGEsIHNlIGZpbHRyYSBzb2xvIGxhcyByZXNwdWVzdGFzIFPDrSB5IE5vLgpTZSBndWFyZGEgbG9zIHJlc3VsdGFkb3MgZW4gdW4gb2JqZXRvICJ0YWJsYTIiLgoKYGBge3J9CnRhYmxhMiA9IGNvbWkxN18yICU+JQogIGZpbHRlcihsdXogPT0gIlPDrSIgfCBsdXogPT0gIk5vIikgJT4lCiAgY291bnQoTHV6ID0gbHV6LCBuYW1lPSJGcmVjdWVuY2lhIikKdGFibGEyCmBgYAoKU2UgYcOxYWRlIGEgZXN0ZSBtaXNtbyBvYmpldG8gbG9zIHBvcmNlbnRhamVzLgrCv1F1w6kgY29uY2x1c2lvbmVzIHNhY2EgZGUgZXN0b3MgcmVzdWx0YWRvcz8KCmBgYHtyfQp0YWJsYTIgPSB0YWJsYTIgJT4lCiAgbXV0YXRlKFBvcmNlbnRhamUgPSAoRnJlY3VlbmNpYSAvIHN1bShGcmVjdWVuY2lhKSoxMDAgKSkKdGFibGEyCmBgYAoKU2UgaGFjZSBlbCBtaXNtbyBwcm9jZWRpbWllbnRvIGNvbiBsYSB2YXJpYWJsZSBzb2JyZSBhZ3VhIHBvdGFibGUuCkVuIGVzdGUgY2FzbywgbGEgdmFyaWFibGUgdGllbmUgY2luY28gdmFsb3Jlcy4KCmBgYHtyfQpjbGFzcyhjb21pMTdfMiRJTkYyMjUpCnRhYmxlKGNvbWkxN18yJElORjIyNSkKYGBgCgpgYGB7cn0KY29taTE3XzIgPSBjb21pMTdfMiAlPiUKICBtdXRhdGUoYWd1YSA9IGZhY3RvcihJTkYyMjUsIGxhYmVscz1jKCJSZWQgcMO6YmxpY2EgZGVudHJvIGRlbCBsb2NhbCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNhbWnDs24gY2lzdGVybmEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBvem8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlLDrW8sIGFjZXF1aWEgbyBtYW5hbnRpYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk90cm8iKSkpCnRhYmxlKGNvbWkxN18yJGFndWEpCmBgYAoKU2UgY2FsY3VsYSBsYSB0YWJsYSBkZSBkaXN0cmlidWNpw7NuIGRlIGZyZWN1ZW5jaWFzLCBjb24gZWwgY8OhbGN1bG8gZGUgbG9zIHBvcmNlbnRhamVzIGVuIGVsIG1pc21vIGPDs2RpZ28uCsK/UXXDqSBjb25jbHVzaW9uZXMgc2FjYSBkZSBlc3RvcyByZXN1bHRhZG9zPwoKYGBge3J9CnRhYmxhMyA9IGNvbWkxN18yICU+JQogIGNvdW50KEFndWEgPSBhZ3VhLCBuYW1lPSJGcmVjdWVuY2lhIikgJT4lCiAgbXV0YXRlKFBvcmNlbnRhamUgPSAoRnJlY3VlbmNpYSAvIHN1bShGcmVjdWVuY2lhKSoxMDAgKSkKdGFibGEzCmBgYAoKwr9RdcOpIGNvbmNsdXNpb25lcyBzYWNhIGRlIGVzdG9zIHJlc3VsdGFkb3M/CgpGaW5hbG1lbnRlLCBzZSBoYWNlIGxvIG1pc21vIHBhcmEgbGEgcHJlZ3VudGEgc29icmUgaW50ZXJuZXQuCgpgYGB7cn0KY2xhc3MoY29taTE3XzIkSU5GMjY0X0UpCnRhYmxlKGNvbWkxN18yJElORjI2NF9FKQpgYGAKCmBgYHtyfQpjb21pMTdfMiA9IGNvbWkxN18yICU+JQogIG11dGF0ZShpbnRlcm5ldCA9IGZhY3RvcihJTkYyNjRfRSwgbGFiZWxzPWMoIlPDrSwgcGFnbyBwZW5kaWVudGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTw60sIHBhZ28gYWwgZMOtYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU8OtLCBubyBzYWJlIGRlbCBwYWdvIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJObyBjdWVudGEgY29uIGVsIHNlcnZpY2lvIikpKQp0YWJsZShjb21pMTdfMiRpbnRlcm5ldCkKYGBgCgrCv1F1w6kgY29uY2x1c2lvbmVzIHNhY2Egc29icmUgZXN0b3MgcmVzdWx0YWRvcz8KCmBgYHtyfQp0YWJsYTUgPSBjb21pMTdfMiAlPiUKICBjb3VudChJbnRlcm5ldCA9IGludGVybmV0LCBuYW1lPSJGcmVjdWVuY2lhIikgJT4lCiAgbXV0YXRlKFBvcmNlbnRhamUgPSAoRnJlY3VlbmNpYSAvIHN1bShGcmVjdWVuY2lhKSoxMDAgKSkKdGFibGE1CmBgYAoKRXN0ZSB0aXBvIGRlIHZhcmlhYmxlcywgZGUgdGlwbyBmYWN0b3IsIHNlIHB1ZWRlIHZpc3VhbGl6YXIgY29uIGdyw6FmaWNvcyBkZSBiYXJyYXMuCgpgYGB7cn0KZ3JhZjEgPSBnZ3Bsb3QodGFibGE1LCBhZXMoeD1JbnRlcm5ldCwgeT1Qb3JjZW50YWplKSkrCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsKICAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShyb3VuZChQb3JjZW50YWplLCAxKSkpLCB2anVzdD0tMSwgc2l6ZT0zKSsKICBsYWJzKHg9IkludGVybmV0IiwgeT0iUG9yY2VudGFqZSIpKwogIHRoZW1lX2NsYXNzaWMoKQpncmFmMQpgYGAKCiMjIFRhcmVhCgpDYWxjdWxlIGxhcyB0YWJsYXMgZGUgZGlzdHJpYnVjacOzbiBkZSBmcmVjdWVuY2lhcyBkZSBsdXogeSBkZSBpbnRlcm5ldCBwb3IgcmVnaW9uZXMuCkdyYWZpcXVlLgoKIyBQcnVlYmFzIGRlIHNpZ25pZmljYW5jaWEKCkVzIHVuYSBkZSBsYXMgdMOpY25pY2FzIG3DoXMgdXNhZGFzIHBhcmEgZWwgYW7DoWxpc2lzIGVuIGNpZW5jaWFzIHNvY2lhbGVzLgpTaXJ2ZSwgcG9yIGVqZW1wbG8sIHBhcmEgY29tcGFyYXIgZW50cmUgZ3J1cG9zOgoKLSAgIENvbXBhcmFyIGxhIG1lZGlhIGRlIGluZ3Jlc29zIGRlIGhvbWJyZXMgeSBtdWplcmVzCgotICAgQ29tcGFyYXIgbGEgcHJvcG9yY2nDs24gZGUgcGVyc29uYXMgcXVlIHZvdGFyw6FuIGEgY2FuZGlkYXRvIFggZW4gTGltYSB5IGVuIFJlZ2lvbmVzCgotICAgQ29tcGFyYXIgbG9zIGluZ3Jlc29zIGRlIHByb2Zlc29yZXMgZW4gbGEgZ2VzdGnDs24gcMO6YmxpY2EgeSBlbiBsYSBnZXN0acOzbiBwcml2YWRhCgpMYSBpZGVhIGVzIGNvbXBhcmFyIGxhcyBlc3RpbWFjaW9uZXMgcHVudHVhbGVzIGVudHJlIGFtYm9zIGdydXBvcyB5IHRhbWJpw6luIHBvZGVyIGV4dHJhcG9sYXIgZXN0YXMgZGlmZXJlbmNpYXMgYSBsYSBwb2JsYWNpw7NuLgoKVmFtb3MgYSBjb21lbnphciBwb3IgY29tcGFyYWNpb25lcyBlbnRyZSBzb2xvIDIgZ3J1cG9zIChwb3IgZWwgbW9tZW50byksIHF1ZSBjb3JyZXNwb25kZSBhIHVuYSB2YXJpYWJsZSBiaW5hcmlhIG8gZGljb3TDs21pY2EsIGNvbW8gc2V4byAoaG9tYnJlcy9tdWplcmVzKSwgw6FtYml0byAodXJiYW5vL3J1cmFsKSwgZ2VzdGnDs24gZWR1Y2F0aXZhIChww7pibGljYS9wcml2YWRhKS4KClBhcmEgbW9zdHJhciB1biBlamVtcGxvLCB2YW1vcyBhIHVzYXIgZWwgdHJhYmFqbyBkZSBbQGdhbGFyemFEZXRlY3RhbmRvRGlzY3JpbWluYWNpb25TZXh1YWwyMDEyXSBxdWUgZXZhbMO6YSBsYSBkaXNjcmltaW5hY2nDs24gZW4gZWwgbWVyY2FkbyBsYWJvcmFyIGVudHJlIGhvbWJyZXMgeSBtdWplcmVzLgpFc3RvcyBhdXRvcmVzIGVudmlhcm9uIENWcyBjb24gZXhhY3RhcyBjdWFsaWZpY2FjaW9uZXMgYSBvZmVydGFzIHJlYWxlcyBkZSB0cmFiYWpvLCB2YXJpYW5kbyBzb2xvIGVsIG5vbWJyZSBkZWwgYXBsaWNhbnRlLCBjb24gbm9tYnJlcyBkZSBob21icmVzIHkgbXVqZXJlcy4KTGEgdmFyaWFibGUgZGUgcmVzcHVlc3RhIGVzIGxhIHRhc2EgZGUgcmVzcHVlc3RhIGEgZXN0b3MgQ1ZzLCBlcyBkZWNpciwgZGUgY3XDoW50b3MgQ1ZzIGVudmlhZG9zIHNlIHJlY2liacOzIHVuYSBsbGFtYWRhIHBhcmEgdW5hIGVudHJldmlzdGEuCgpFbiBjdWFscXVpZXIgcHJ1ZWJhIGRlIHNpZ25pZmljYW5jaWEgc2UgdGllbmUgcXVlIHByZXNlbnRhciB1bmEgaGlww7N0ZXNpcyBudWxhLCBxdWUgZ2VuZXJhbG1lbnRlIGVzIGxhIGhpcMOzdGVzaXMgZGUgbm8gZGlmZXJlbmNpYXMgbyBkZSBubyBlZmVjdG9zLgpFc3RlIHRyYWJham8gcGFydGUgZGUgdW5hIGlkZWEgcXVlIGV4aXN0ZSB1bmEgZGlzY3JpbWluYWNpw7NuIGRlIGfDqW5lcm8gZW4gZWwgbWVyY2FkbyBsYWJvcmFsLCBwb3IgbG8gcXVlIGxhIGhpcMOzdGVzaXMgbnVsYSBpbmRpY2Fyw61hIGxvIGNvbnRyYXJpby4KRW4gZWwgY2FzbyBkZSBlc3RlIHRyYWJham8gc2UgdGVuZHLDrWE6CgpIMDogVGFzYSBkZSByZXNwdWVzdGEgYSBDVnMgZGUgaG9tYnJlcyA9IFRhc2EgZGUgcmVzcHVlc3RhIGEgQ1ZzIGRlIG11amVyZXMKCm8gbG8gcXVlIGVzIGxvIG1pc21vCgpIMDogVGFzYSBkZSByZXNwdWVzdGEgYSBDVnMgZGUgaG9tYnJlcyAtIFRhc2EgZGUgcmVzcHVlc3RhIGEgQ1ZzIGRlIG11amVyZXMgPSAwCgpFbiBlc2UgdHJhYmFqbyBzZSBwcmVzZW50YSBlbCBzaWd1aWVudGUgY3VhZHJvIGRlIHJlc3VsdGFkb3M6CgohW10oR2FsYXJ6YS5wbmcpe3dpZHRoPSI0MzUifQoKRW4gbGEgbXVlc3RyYSB0b3RhbCBkZSAyLDIyOCBDVnMgZW52aWFkb3MsIG1pdGFkIGRlIENWcyBjb24gbm9tYnJlcyBkZSBob21icmVzIHkgbGEgb3RyYSBtaXRhZCBjb24gbm9tYnJlcyBkZSBtdWplcmVzLCB0b2RvcyBjb24gbGFzIG1pc21hcyBjdWFsaWZpY2FjaW9uZXMsIHNlIHRpZW5lIHF1ZSBsYSB0YXNhIGRlIHJlc3B1ZXN0YSBwYXJhIGxvcyBDVnMgZGUgaG9tYnJlcyBlcyAxMy40JSB5IHBhcmEgbG9zIENWcyBkZSBtdWplcmVzIGVzIDExLjElLgoKRGUgYWN1ZXJkbyBhIGxhcyBlc3RpbWFjaW9uZXMgcHVudHVhbGVzLCBlZmVjdGl2YW1lbnRlLCBsb3MgaG9tYnJlcyB0aWVuZW4gdW5hIG1heW9yIHRhc2EgZGUgcmVzcHVlc3RhIGEgc3VzIENWcyBxdWUgbGFzIG11amVyZXMsIGEgaWd1YWxlcyBjdWFsaWZpY2FjaW9uZXMuCkVzdGEgY29uY2x1c2nDs24sIHNpbiBlbWJhcmdvLCBlcyBzb2xvIHBhcmEgbGFzIDIsMjI4IG9ic2VydmFjaW9uZXMgZGUgbGEgbXVlc3RyYS4Kwr9Dw7NtbyBleHRyYXBvbGFyIGVzdGEgY29uY2x1c2nDs24gYSBsYSBwb2JsYWNpw7NuPwrCv1RvZGEgZGlmZXJlbmNpYSBwdW50dWFsIHNlIHZhbGlkYXLDrWEgZW4gbGEgcG9ibGFjacOzbj8KCiMgQ29tcGFyYWNpw7NuIGRlIGludGVydmFsb3MgZGUgY29uZmlhbnphIHBvciBncnVwb3MKClVuYSBwcmltZXJhIGZvcm1hICJpbmZvcm1hbCIgcGFyYSBleHRyYXBvbGFyIGxhcyBkaWZlcmVuY2lhcyBlbiBsYXMgZXN0aW1hY2lvbmVzIHB1bnR1YWxlcyBkZSBsYSBtdWVzdHJhIGEgbGEgcG9ibGFjacOzbiBlcyBjb25zdHJ1eWVuZG8gbG9zIGludGVydmFsb3MgZGUgY29uZmlhbnphIHBhcmEgbGEgbWVkaWEgbyBwYXJhIGxhIHByb3BvcmNpw7NuIHBvciBjYWRhIHVubyBkZSBsb3Mgc3ViZ3J1cG9zLgoKRW4gZXN0ZSBjYXNvLCBwb3IgZWplbXBsbywgc2lnbmlmaWNhcsOtYSBjb25zdHJ1aXIgZWwgSUMgZGUgbGEgdGFzYSBkZSByZXNwdWVzdGEgcGFyYSBob21icmUgeSBtdWplcmVzLgoKUHJlZ3VudGE6IMK/U2UgcHVlZGVuIGNvbnN0cnVpciBsb3MgSUMgZGUgY2FkYSBncnVwbyBjb24gbG9zIGRhdG9zIGRlIGxhIHRhYmxhPwoKQ2FkYSBJQyBzZXLDrWEgdW5hIGV4dHJhcG9sYWNpw7NuIGRlbCBwYXLDoW1ldHJvLCBlcyBkZWNpciwgZWwgcmFuZ28gZGUgdmFsb3JlcyBkZSBsYSB0YXNhIGRlIHJlc3B1ZXN0YSBhIGxvcyBDVnMgZGUgaG9tYnJlcyBwYXJhIHRvZG8gZWwgbWVyY2FkbyBsYWJvcmFsIGFsIDk1JSBkZSBjb25maWFuemEuCkxvIG1pc21vIHBhcmEgbGEgdGFzYSBkZSByZXNwdWVzdGEgZGUgbGFzIG11amVyZXMuCgpVbmEgdmV6IGNvbnN0cnVpZG9zIGxvcyBJQywgc2UgYW5hbGl6YSBzaSBlc3RvcyBpbnRlcnZhbG9zIHNlIGNydXphbiBvIG5vIHNlIGNydXphbi4KTGEgcmVnbGEgZGUgZGVjaXNpw7NuICJpbmZvcm1hbCIgZXM6CgotICAgU2kgbG9zIElDIGRlIGFtYm9zIGdydXBvcyBzZSBjcnV6YW4sIGVudG9uY2VzIG5vIHNlIHB1ZWRlIGFmaXJtYXIgcXVlIGVsIHBhcsOhbWV0cm8gZGUgdW4gZ3J1cG8gc2VhIG1heW9yIG8gbWVub3MgcXVlIGVsIHBhcsOhbWV0cm8gZGVsIG90cm8gZ3J1cG8uCgotICAgU2kgbG9zIElDIGRlIGFtYm9zIGdydXBvcyBOTyBzZSBjcnV6YW4sIGVudG9uY2VzIHNlIHB1ZWRlIGFmaXJtYXIsIGFsIDk1JSBkZSBjb25maWFuemEsIHF1ZSBlbCBwYXLDoW1ldHJvIGRlIHVuIGdydXBvIGVzIG1heW9yL21lbm9yIGFsIHBhcsOhbWV0cm8gZGVsIG90cm8gZ3J1cG8uCgojIEVqZW1wbG8gMSBwYXJhIHVuYSB2YXJpYWJsZSBudW3DqXJpY2E6IEVOTAoKKlByZWd1bnRhOiDCv2V4aXN0ZW4gZGlmZXJlbmNpYSBlbiBsYSBjYW50aWRhZCBkZSBsaWJyb3MgcXVlIGxlZW4gaG9tYnJlcyB5IG11amVyZXM/KiDCv3kgZW50cmUgZGlmZXJlbnRlcyBuaXZlbGVzIHNvY2lvZWNvbsOzbWljb3M/CgpMYSBoaXDDs3Rlc2lzIGNlcm8gc2Vyw61hOgoKSG86IFByb21lZGlvIGRlIGxpYnJvcyBxdWUgbGVlIHVuIGhvbWJyZSA9IFByb21lZGlvIGRlIGxpYnJvcyBxdWUgbGVlIHVuYSBtdWplci4KCmBgYHtyfQpsaWJyYXJ5KHJpbykKZW5sID0gaW1wb3J0KCIvVXNlcnMvQXJ0dXJvL0xpYnJhcnkvQ2xvdWRTdG9yYWdlL0dvb2dsZURyaXZlLWFydHVyby5tYWxkb25hZG9AcHVjcC5wZS9NeSBEcml2ZS9BIEN1cnNvcy9Fc3RhZGlzdGljYV8xL0RhdGEvRU5MMjAyMi9FTkwyMDIyLnNhdiIpCmBgYAoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQplbmwgPSBlbmwgJT4lCiAgbXV0YXRlKHNleG8gPSBmYWN0b3IoUDIwOSwgbGFiZWxzPWMoIkhvbWJyZSIsICJNdWplciIpKSkKYGBgCgpgYGB7cn0KZW5sID0gZW5sICU+JQogIG11dGF0ZShuc2UxID0gZmFjdG9yKG5zZSwgbGFiZWxzPWMoIlJ1cmFsIiwgIkJham8iLCAiTWVkaW8iLCAiQWx0byIpKSkKYGBgCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmVubCA9IGVubCAlPiUKICBtdXRhdGUobGlicm9zID0gUDQxMl8xICsgUDQxMl8yKQpgYGAKCmBgYHtyfQplbmwgJT4lCiAgc3VtbWFyaXplKG1lYW4oUDQxMl8xLCBuYS5ybT1UKSwgCiAgICAgICAgICAgIG1lYW4oUDQxMl8yLCBuYS5ybT1UKSwgCiAgICAgICAgICAgIG1lYW4obGlicm9zLCBuYS5ybT1UKSkKYGBgCgpgYGB7cn0KdGFibGExID0gZW5sICU+JQogIGdyb3VwX2J5KHNleG8pICU+JQogIHN1bW1hcml6ZShtZWRpYSA9IG1lYW4obGlicm9zLCBuYS5ybT1UKSwgCiAgICAgICAgICAgIG1lZGlhbmEgPSBtZWRpYW4obGlicm9zLCBuYS5ybT1UKSwKICAgICAgICAgICAgZGVzdmlhY2lvbiA9IHNkKGxpYnJvcywgbmEucm09VCkpCnRhYmxhMQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZW5sLCBhZXMoeT0gbGlicm9zLCB4PSBzZXhvKSkrCiAgZ2VvbV9ib3hwbG90KCkrCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMjApKSsKICB5bGFiKCJUb3RhbCBsaWJyb3MgbGXDrWRvcyIpKwogIHhsYWIoIlNleG8iKSsKICB0aGVtZV9nZXQoKQpgYGAKCkVsIGPDoWxjdWxvIGRlbCBpbnRlcnZhbG8gZGUgY29uZmlhbnphIGRlIHVuYSBtZWRpYSBlczoKCiQkCklDID0gIFxiYXJ7WH0gXHBtIDEuOTYgKiBcZnJhY3tzfSB7XHNxcnR7bn19CiQkCgpQYXJhIHVuYSBjb21wYXJhY2nDs24gdXNhbmRvIGxvcyBpbnRlcnZhbG9zIGRlIGNvbmZpYW56YSwgc2UgcHVlZGUgdXNhciBlbCBjb21hbmRvIGBjaU1lYW5gIGRlIGxhIGxpYnJlcsOtYSBgbHNyYC4KRXN0ZSBjb21hbmRvIHJlZ3Jlc2EgZWwgbMOtbWl0ZSBpbmZlcmlvciB5IGVsIGzDrW1pdGUgc3VwZXJpb3IgZGVsIGludGVydmFsbyBkZSBjb25maWFuemEuClBvciBsbyB0YW50bywgcGFyYSBndWFyZGFyIHNvbG8gZWwgbcOtbmltbyBzZSB0aWVuZSBxdWUgZXNwZWNpZmljYXIgYGxzcjo6Y2lNZWFuKFAxXzYsIG5hLnJtPVQpWzFdYCB5IHBhcmEgZWwgbcOheGltbyBjYW1iaWFyw61hIGEgYFsyXWAuCgpgYGB7cn0KbGlicmFyeShsc3IpCnRhYmxhMiA9IGVubCAlPiUKICBzdW1tYXJpc2UobWVkaWEgPSBtZWFuKGxpYnJvcywgbmEucm09VCksCiAgICAgICAgICAgIGRlc3YgPSBzZChsaWJyb3MsIG5hLnJtID0gVCksCiAgICAgICAgICAgIGxpbWluZiA9IGNpTWVhbihsaWJyb3MsIG5hLnJtPVQpWzFdLAogICAgICAgICAgICBsaW1zdXAgPSBjaU1lYW4obGlicm9zLCBuYS5ybT1UKVsyXQogICAgICAgICAgICApCnRhYmxhMgpgYGAKCmBgYHtyfQp0YWJsYTJ4c2V4byA9IGVubCAlPiUKICBncm91cF9ieShzZXhvKSAlPiUKICBzdW1tYXJpc2UobWVkaWEgPSBtZWFuKGxpYnJvcywgbmEucm09VCksCiAgICAgICAgICAgIGRlc3YgPSBzZChsaWJyb3MsIG5hLnJtID0gVCksCiAgICAgICAgICAgIGxpbWluZiA9IGNpTWVhbihsaWJyb3MsIG5hLnJtPVQpWzFdLAogICAgICAgICAgICBsaW1zdXAgPSBjaU1lYW4obGlicm9zLCBuYS5ybT1UKVsyXQogICAgICAgICAgICApCnRhYmxhMnhzZXhvCmBgYAoKLSAgIEVsIElDIGFsIDk1JSBkZSBjb25maWFuemEsIGVsIHByb21lZGlvIGRlIGxpYnJvcyBxdWUgbGVlIHVuIGhvbWJyZSBlc3TDoSBlbiBlbCBzaWd1aWVudGUgaW50ZXJ2YWxvICQkMy44MCAtIDQuMDUkJAoKLSAgIEVsIElDIGFsIDk1JSBkZSBjb25maWFuemEgZWwgbGlicm9zIHF1ZSBsZWUgdW5hIG11amVyIGVzdMOhIGVuIGVsIHNpZ3VpZW50ZSBpbnRlcnZhbG8gJCQzLjY5IC0gMy44NyQkCgpDb21vIGFtYm9zIGludGVydmFsb3MgU8ONIHNlIHRyYXNsYXBhbiwgZW50b25jZXMgTk8gc2UgcHVlZGUgYWZpcm1hciBxdWUgZXNhcyBkaWZlcmVuY2lhcyBzZSBwdWVkZW4gZXh0cmFwb2xhciBsYSBwb2JsYWNpw7NuLgpOTyBzZSBwdWVkZSBhZmlybWFyIHF1ZSBleGlzdGFuIGRpZmVyZW5jaWFzIGVudHJlIGhvbWJyZXMgeSBtdWplcmVzIGVuIGVsIG7Dum1lcm8gZGUgbGlicm9zIHF1ZSBsZWVuIChzZXLDrWEgdW4gImVtcGF0ZSB0w6ljbmljbyIpLgoKIyMgR3LDoWZpY28gZGUgSUMgcGFyYSBjb21wYXJhciBtZWRpYXMKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmdyYWYgPSBnZ3Bsb3QodGFibGEyeHNleG8sIGFlcyh4PXNleG8sIHk9bWVkaWEpKSsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49bGltaW5mLCB5bWF4PWxpbXN1cCksIHdpZHRoPTAuMikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZChtZWRpYSwgMSkpLCB2anVzdD0tMSwgc2l6ZT00KSsKICB4bGFiKCJTZXhvIikgKyB5bGFiKCJQcm9tZWRpbyBkZSBsaWJyb3MgcXVlIGxlZSIpKwogIHlsaW0oMCwgNSkKZ3JhZgpgYGAKCiMgRWplbXBsbyAyIHBhcmEgdW5hIHZhcmlhYmxlIG51bcOpcmljYTogRU5ETwoKKlByZWd1bnRhOiDCv2EgY3XDoW50b3MgYWx1bW5vcyBlbiBwcm9tZWRpbyBhdGllbmRlIHVuIHByb2Zlc29yIHBlcnVhbm8/IMK/RXhpc3RlbiBkaWZlcmVuY2lhcyBkZSBnw6luZXJvPyoKClVzYW5kbyBlbCBlamVtcGxvIGRlIGxhIEVORE8gMjAyMCwgbGEgaGlww7N0ZXNpcyBxdWUgc2UgcHVlZGUgZXZhbHVhciBlcyBzaSBsb3MgcHJvZmVzb3JlcyBhdGllbmRlbiBhIGRpZmVyZW50ZSBuw7ptZXJvIGRlIGFsdW1ub3MgZGUgYWN1ZXJkbyBhIHN1IHNleG8uCkNvbW8gdmltb3MgYW50ZXMsIGxhcyBjb21wYXJhY2lvbmVzIHB1bnR1YWxlcyBzdWdpZXJlbiBkaWZlcmVuY2lhcywgZG9uZGUgbG9zIGRvY2VudGVzIGhvbWJyZXMgYXRpZW5kZW4gYSBtw6FzIGFsdW1ub3MgcXVlIGxhcyBkb2NlbnRlcyBtdWplcmVzLgoKTGEgaGlww7N0ZXNpcyBjZXJvIHNlcsOtYToKCkhvOiBQcm9tZWRpbyBkZSBhbHVtbm9zIHF1ZSBhY29tcGHDsWEgdW4gZG9jZW50ZSBob21icmUgPSBQcm9tZWRpbyBkZSBhbHVtbm9zIHF1ZSBhY29tcGHDsWEgdW5hIGRvY2VudGUgbXVqZXIuCgpgYGB7ciBlbmRvLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHJpbykKZW5kbzIwMjAgPSBpbXBvcnQoImJhc2VzL0VORE9fUkVNT1RPXzIwMjAuZHRhIikKYGBgCgpMYSB2YXJpYWJsZSBQMV8xIChzZXhvIGRlbCBkb2NlbnRlKSBlc3TDoSBkZWZpbmlkYSBvcmlnaW5hbG1lbnRlIGNvbW8gdW5hIHZhcmlhYmxlIG51bcOpcmljYSAoZXN0byBzZSBwdWVkZSBjb21wcm9iYXIgY29uIGVsIGPDs2RpZ28gYHN0cihlbmRvMjAyMCRQMV8xKWAuCkVzdGEgdmFyaWFibGUsIHNpbiBlbWJhcmdvIGVzIGRlIHRpcG8gZmFjdG9yLgoKU2UgcHVlZGUgY3JlYXIgdW5hIG51ZXZhIHZhcmlhYmxlICJzZXhvIiBjb24gbGEgdmFyaWFibGUgdHJhbnNmb3JtYWRhIHkgZXRpcXVldGFkYS4KCmBgYHtyIG1lZGlhcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmVuZG8yMDIwID0gZW5kbzIwMjAgJT4lCiAgbXV0YXRlKHNleG8gPSBmYWN0b3IoUDFfMSwgbGFiZWxzPWMoIkhvbWJyZSIsICJNdWplciIpKSkKYGBgCgpgYGB7cn0KZW5kbzIwMjAgJT4lCiAgc3VtbWFyaXplKE1lZGlhID0gbWVhbihQMV82LCBuYS5ybSA9IFQpLCAKICAgICAgICAgICAgRGVzdi5TdGQgPSBzZChQMV82LCBuYS5ybSA9IFQpKQpgYGAKCmBgYHtyfQphbHVteHNleG8gPSBlbmRvMjAyMCAlPiUKICBncm91cF9ieShzZXhvKSAlPiUKICBzdW1tYXJpemUoTWVkaWEgPSBtZWFuKFAxXzYsIG5hLnJtID0gVCksIAogICAgICAgICAgICBEZXN2LlN0ZCA9IHNkKFAxXzYsIG5hLnJtID0gVCkpCmFsdW14c2V4bwpgYGAKClNlIGVuY3VlbnRyYSBxdWUgbG9zIGRvY2VudGVzIGhvbWJyZXMgYWNvbXBhw7FhbiBhIDUyIGFsdW1ub3MgZW4gcHJvbWVkaW8sIGVuIGNvbXBhcmFjacOzbiBjb24gbGFzIGRvY2VudGVzIG11amVyZXMgcXVlIGFjb21wYcOxYW4gYSAzNCBhbHVtbm9zIGVuIHByb21lZGlvLCBlcyBkZWNpciAxOCBhbHVtbm9zIG1lbm9zIGVuIHByb21lZGlvLgoKUmVjb3JkZW1vcyBxdWUgZWwgY8OhbGN1bG8gZGVsIGludGVydmFsbyBkZSBjb25maWFuemEgZGUgdW5hIG1lZGlhIGVzOgoKJCQKSUMgPSAgXGJhcntYfSBccG0gMS45NiAqIFxmcmFje3N9IHtcc3FydHtufX0KJCQKClBhcmEgdW5hIGNvbXBhcmFjacOzbiB1c2FuZG8gbG9zIGludGVydmFsb3MgZGUgY29uZmlhbnphLCBzZSBwdWVkZSB1c2FyIGVsIGNvbWFuZG8gYGNpTWVhbmAgZGUgbGEgbGlicmVyw61hIGBsc3JgLgpFc3RlIGNvbWFuZG8gcmVncmVzYSBlbCBsw61taXRlIGluZmVyaW9yIHkgZWwgbMOtbWl0ZSBzdXBlcmlvciBkZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YS4KUG9yIGxvIHRhbnRvLCBwYXJhIGd1YXJkYXIgc29sbyBlbCBtw61uaW1vIHNlIHRpZW5lIHF1ZSBlc3BlY2lmaWNhciBgbHNyOjpjaU1lYW4oUDFfNiwgbmEucm09VClbMV1gIHkgcGFyYSBlbCBtw6F4aW1vIGNhbWJpYXLDrWEgYSBgWzJdYC4KCmBgYHtyfQpsaWJyYXJ5KGxzcikKZW5kbzIwMjAgJT4lCiAgc3VtbWFyaXNlKG1lZGlhID0gbWVhbihQMV82LCBuYS5ybT1UKSwKICAgICAgICAgICAgZGVzdiA9IHNkKFAxXzYsIG5hLnJtID0gVCksCiAgICAgICAgICAgIGxpbWluZiA9IGNpTWVhbihQMV82LCBuYS5ybT1UKVsxXSwKICAgICAgICAgICAgbGltc3VwID0gY2lNZWFuKFAxXzYsIG5hLnJtPVQpWzJdCiAgICAgICAgICAgICkKYGBgCgpgYGB7cn0KYWx1bXhzZXhvID0gZW5kbzIwMjAgJT4lCiAgZ3JvdXBfYnkoc2V4bykgJT4lCiAgc3VtbWFyaXNlKG1lZGlhID0gbWVhbihQMV82LCBuYS5ybT1UKSwKICAgICAgICAgICAgZGVzdiA9IHNkKFAxXzYsIG5hLnJtID0gVCksCiAgICAgICAgICAgIGxpbWluZiA9IGNpTWVhbihQMV82LCBuYS5ybT1UKVsxXSwKICAgICAgICAgICAgbGltc3VwID0gY2lNZWFuKFAxXzYsIG5hLnJtPVQpWzJdCiAgICAgICAgICAgICkKYWx1bXhzZXhvCmBgYAoKLSAgIEVsIElDIGFsIDk1JSBkZSBjb25maWFuemEsIGVsIHByb21lZGlvIGRlIGFsdW1ub3MgcXVlIGFjb21wYcOxYW4gbG9zIGRvY2VudGVzIGhvbWJyZSBlc3TDoSBlbiBlbCBzaWd1aWVudGUgaW50ZXJ2YWxvICQkNTAuNyAtIDUzLjgkJAoKLSAgIEVsIElDIGFsIDk1JSBkZSBjb25maWFuemEgZWwgcHJvbWVkaW8gZGUgYWx1bW5vcyBxdWUgYWNvbXBhw7FhbiBsYXMgZG9jZW50ZXMgbXVqZXJlcyBlc3TDoSBlbiBlbCBzaWd1aWVudGUgaW50ZXJ2YWxvICQkMzMuMyAtIDM0LjgkJAoKQ29tbyBhbWJvcyBpbnRlcnZhbG9zIE5PIHNlIHRyYXNsYXBhbiAoZWwgbWF5b3IgdmFsb3IgZGVsIHNlZ3VuZG8gSUMsIDM0LjggLCBlcyBtZW5vciBhbCBtZWpvciB2YWxvciBkZWwgcHJpbWVyIElDLCA1MC43KSwgZW50b25jZXMgc2UgcHVlZGUgYWZpcm1hciBxdWUgZXNhcyBkaWZlcmVuY2lhcyBzZSBwdWVkZW4gZXh0cmFwb2xhciBsYSBwb2JsYWNpw7NuLgoKU2kgbG9zIElDIHNlIHRyYXNsYXBhbiwgZW50b25jZXMsIG5vIHNlIHB1ZWRlIGFmaXJtYXIgcXVlIGV4aXN0YW4gZGlmZXJlbmNpYXMgZW4gZWwgbsO6bWVybyBkZSBhbHVtbm9zIHF1ZSBhY29tcGHDsWFuIGRvY2VudGVzIGhvbWJyZXMgbyBtdWplcmVzIChzZXLDrWEgdW4gImVtcGF0ZSB0w6ljbmljbyIpLgoKIyMgR3LDoWZpY28gZGUgSUMgcGFyYSBjb21wYXJhciBtZWRpYXMKClNlIHB1ZWRlIGdyYWZpY2FyIGFtYm9zIGludGVydmFsb3MgZGUgY29uZmlhbnphLgpQYXJhIGhhY2VyIGVzdG8sIHVzYXJlbW9zIGxhIHRhYmxhIHF1ZSBndWFyZGEgbG9zIGRhdG9zIGRlIGxvcyBpbnRlcnZhbG9zIGRlIGNvbmZpYW56YS4KCkVzdGEgdGFibGEsIHNpbiBlbWJhcmdvLCB0aWVuZSB1bmEgZmlsYSBkZSByZXN1bHRhZG9zIHBhcmEgbG9zIHZhbG9yZXMgcGVyZGlkb3MuCkVzdGEgZmlsYSBubyB0aWVuZSBkYXRvcyBwb3IgZ3JhZmljYXIsIHBvciBsbyBxdWUgdGVuZW1vcyBxdWUgZWxpbWluYXJsYS4KCkxvcyBkYXRhZnJhbWVzIHNlIG9yZ2FuaXphbiBlbiBmaWxhcyB5IGNvbHVtbmFzLgpMYSB0YWJsZSAiY2lfYWx1bXhzZXhvIiB0aWVuZSAzIGZpbGFzIHkgMyBjb2x1bW5hcy4KTGEgdGVyY2VyYSBmaWxhIGVzIGxhIHF1ZSBubyB0aWVuZSBkYXRvcyBxdWUgZ3JhZmljYXIuClBhcmEgZWxpbWluYXIgc2UgdGllbmUgcXVlIGVzcGVjaWZpY2FyIGxhIHRhYmxhIHkgY29uIGxvcyBicmFja2V0cyBgW2ZpbGFzLCBjb2x1bW5hc11gIGRlZmluaXIgbG9zIGRhdG9zIGEgZWxpbWluYXIgYFstMywgXWAuClNlIGVsaW1pbmEgY29uIGVsIHNpZ25vICItIiB5IGNvbW8gbm8gaGF5IGRhdG9zIGx1ZWdvIGRlIGxhICIsIiwgc2UgaW5kaWNhIHF1ZSBubyBzZSBjYW1iaWEgbmluZ3VuYSBjb2x1bW5hLgoKYGBge3IgY2kgeCBzZXhvfQphbHVteHNleG8gPSBhbHVteHNleG9bLTMsXQphbHVteHNleG8KYGBgCgpFc3RhIHRhYmxhIHNlIHB1ZWRlIHVzYXIgcGFyYSBjcmVhciB1biBncsOhZmljbyBxdWUgY29tcGFyZSBhbWJvcyBJQyBjb24gbGEgbGlicmVyw61hIGBnZ3Bsb3QyYCB5IGNvbiBsYSBnZW9tZXRyw61hIGBnZW9tX2Vycm9yYmFyYC4KU2UgYWdyZWdhIGBnZW9tX3RleHRgIHBhcmEgaW5jbHVpciBlbCAidGV4dG8iIGNvbiBsb3MgdmFsb3JlcyBwcm9tZWRpbyBkZSBhbWJvcyBncnVwb3MuCgpgYGB7ciBncmFmaWNvMX0KbGlicmFyeShnZ3Bsb3QyKQpncmFmMSA9IGdncGxvdChhbHVteHNleG8sIGFlcyh4PXNleG8sIHk9bWVkaWEpKSsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49bGltaW5mLCB5bWF4PWxpbXN1cCksIHdpZHRoPTAuMikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZChtZWRpYSwgMSkpLCB2anVzdD0tMSwgc2l6ZT00KSsKICB4bGFiKCJTZXhvIGRlbCBkb2NlbnRlIikgKyB5bGFiKCJQcm9tZWRpbyBkZSBhbHVtbm9zIikrCiAgeWxpbSgwLCA2MCkKZ3JhZjEKYGBgCgpFbiBlc3RlIGdyw6FmaWNvIHF1ZWRhIG3DoXMgY2xhcm8gcXVlIGFtYm9zIElDIG5vIHNlIHRyYXNsYXBhbiBwb3IgbG8gcXVlIHNlIHB1ZWRlIGRlY2lyIHF1ZSBzw60gZXhpc3RlbiBkaWZlcmVuY2lhcyBlbnRyZSBkb2NlbnRlcyBob21icmUgeSBtdWplcmVzIGVuIGVsIG7Dum1lcm8gZGUgYWx1bW5vcyBxdWUgYWNvbXBhw7FhbiBlbiBlbCBQZXLDui4KCkVzdGUgdGlwbyBkZSBncsOhZmljbyBlcyBiYXN0YW50ZSB1c3VhbCBlbiBsb3MgcmVwb3J0ZXMgZXN0YWTDrXN0aWNvcy4KUG9yIGVqZW1wbG8sIHNlIHB1ZWRlbiB2ZXIgZXN0ZSB0aXBvIGRlIGdyw6FmaWNvcyBlbiBsb3MgcmVwb3J0ZXMgZGUgW0VsIFB1bHNvIGRlIGxhIERlbW9jcmFjaWFdKGh0dHBzOi8vd3d3LnZhbmRlcmJpbHQuZWR1L2xhcG9wL2FiMjAyMS8yMDIxX0xBUE9QX0FtZXJpY2FzQmFyb21ldGVyXzIwMjFfUHVsc2Vfb2ZfRGVtb2NyYWN5X1NQQS5wZGYpIGRlbCBwcm95ZWN0byBMQVBPUC4KRW4gZWwgw7psdGltbyByZXBvcnRlIHBhcmEgUGVyw7ogc2UgcHJlc2VudGEgZWwgc2lndWllbnRlIGdyw6FmaWNvIHF1ZSBtdWVzdHJhIGxvcyBuaXZlbGVzIGRlIHNhdGlzZmFjY2nDs24gY29uIGxhIGRlbW9jcmFjaWEgZW50cmUgZ3J1cG9zIGRlIHNhdGlzZmFjY2nDs24gY29uIGxvcyBzZXJ2aWNpb3MgcMO6YmxpY29zLgpFc3RvcyBncsOhZmljb3Mgc29uIGNvbnN0cnVpZG9zIGRlIGxhIG1pc21hIG1hbmVyYSBxdWUgc2UgaGEgY29uc3RydWlkbyBlbCBncsOhZmljbyBkZSBhcnJpYmEuCgohW10oZ3JhZjYuNi5wbmcpe3dpZHRoPSI2MzUifQoKwr9Qb3IgcXXDqT8uCi4uCkFxdcOtIHZpZW5lIGxhIGludGVycHJldGFjacOzbiBkZWwgcG9saXTDs2xvZ28gLgoKT0pPOiBubyBzZSBkZWJlIGNvbmZ1bmRpciBlc3RlIGdyw6FmaWNvIGNvbiB1biBncsOhZmljbyBkZSBjYWphcy4KClRBUkVBOiBBbmFsaXphciBzaSBleGlzdGVuIGRpZmVyZW5jaWFzIGVuIGVsIG7Dum1lcm8gZGUgYWx1bW5vcyBlbnRyZSBkb2NlbnRlcyBjb24gZGlmZXJlbnRlcyBjb25kaWNpb25lcyBsYWJvcmFsZXMgKFAxXzcpLgoKIyBFamVtcGxvIDMgcGFyYSB1bmEgdmFyaWFibGUgbnVtw6lyaWNhOiBMQVBPUAoKYGBge3J9CmxpYnJhcnkocmlvKQpsYXBvcCA9IGltcG9ydCgiYmFzZXMvUEVSXzIwMjNfTEFQT1BfQW1lcmljYXNCYXJvbWV0ZXJfdjEuMF93LnNhdiIpCmBgYAoKIyMgRWplbXBsbyBwYXJhIHZhcmlhYmxlIG51bcOpcmljYSBjb24gw61uZGljZSBhZGl0aXZvCgpFbCBjdWVzdGlvbmFyaW8gZGUgTEFQT1AgaW5jbHV5ZSBkb3MgcHJlZ3VudGFzIHNvYnJlIGxhcyBmdWVyemFzIGRlbCBvcmRlbi4KQjEyLgrCv0hhc3RhIHF1w6kgcHVudG8gdGllbmUgdXN0ZWQgY29uZmlhbnphIGVuIGxhcyBGdWVyemFzIEFybWFkYXM/CnkgQjE4LgrCv0hhc3RhIHF1w6kgcHVudG8gdGllbmUgdXN0ZWQgY29uZmlhbnphIGVuIGxhIHBvbGljw61hIG5hY2lvbmFsPwoKQW1iYXMgcHJlZ3VudGFzIGVzdMOhbiBtZWRpZGFzIGVuIHVuYSBlc2NhbGEgZGUgMSBhIDcsIGRvbmRlIDEgc2lnbmlmaWNhICJOYWRhIiB5IDcgc2lnbmlmaWNhICJNdWNobyIuClVuYSBwZXJzb25hIHF1ZSB0ZW5nYSBkZXNjb25maWFuemEgZGUgbGFzIGZ1ZXJ6YXMgZGVsIG9yZGVuIGVuIGdlbmVyYWwsIHNlZ3VyYW1lbnRlIHJlcG9ydGFyw6EgcHVudGFqZXMgYmFqb3MgZW4gYW1iYXMgcHJlZ3VudGFzLgpQb3IgZWwgY29udHJhcmlvLCB1bmEgcGVyc29uYSBxdWUgdGVuZ2EgYWx0YSBjb25maWFuemEgZW4gbGFzIGZ1ZXJ6YXMgZGVsIG9yZGVuIGVuIGdlbmVyYWwsIHB1ZWRlIHJlcG9ydGFyIHB1bnRhamVzIGFsdG9zIGVuIGFtYmFzIHByZWd1bnRhcy4KClNlIHB1ZWRlbiBjb21iaW5hciBhbWJhcyBwcmVndW50YXMgcGFyYSBnZW5lcmFyIHVuIMOtbmRpY2UgYWRpdGl2byBkZSBjb25maWFuemEgZ2VuZXJhbCBlbiBsYXMgZnVlcnphcyBkZWwgb3JkZW4sIGNvbW8gbGEgc3VtYSBkZSBhbWJhcy4KQ29tbyBjYWRhIHByZWd1bnRhIHB1ZWRlIHNlciByZXNwb25kaWRhIGVudHJlIDEgeSA3LCBsYSBzdW1hIHB1ZWRlIHZhcmlhciBlbnRyZSAyIHkgMTQuClVuIHB1bnRhamUgZGUgMiBleHByZXNhcsOhIGxhIG3DoXMgYmFqYSBjb25maWFuemEgZW4gbGFzIGZ1ZXJ6YXMgZGVsIG9yZGVuLgpVbiBwdW50YWplIGRlIDE0LCBsYSBtw6FzIGFsdGEgY29uZmlhbnphIGVuIGxhcyBmdWVyemFzIGRlbCBvcmRlbi4KQ3VhbHF1aWVyIHB1bnRhamUgaW50ZXJtZWRpbywgZXhwcmVzYXLDoSB1bmEgY29uZmlhbnphIGludGVybWVkaWEuCgpDb21vIE5PIGVzIGludHVpdGl2byB0ZW5lciB1biDDrW5kaWNlIHF1ZSB2YXLDrWUgZW50cmUgMiB5IDE0LCBzZSBwdWVkZSByZXN0YXIgZG9zIGEgbGEgc3VtYSBwYXJhIHF1ZSBlbCDDrW5kaWNlIHZhcsOtZSBlbnRyZSAwIHkgMTIuCkNvbW8gZXN0YSB2YXJpYWNpw7NuIHRhbXBvY28gZXMgaW50dWl0aXZhLCBzZSBwdWVkZSBkaXZpZGlyIHRvZG8gZW50cmUgMTIgcGFyYSBxdWUgZWwgw61uZGljZSB2YXLDrWUgZW50cmUgMCB5IDEuCgp8ICAgfCBDb25maWFuemEgZW4gRkZBQSB8IENvbmZpYW56YSBlbiBwb2xpY8OtYSB8IENvbmZpYW56YSBnZW5lcmFsIHwgQ29uZmlhbnphIGdlbmVyYWwgLSAyIHwgKENvbmZpYW56YSBnZW5lcmFsIC0gMikgLyAxMiB8IChDb25maWFuemEgZ2VuZXJhbCAtIDIpIC8gMTJcKjEwMCB8CnwtLS0tLS0tLS0tLXw6LS0tLS0tLS0tOnw6LS0tLS0tLS0tOnw6LS0tLS0tLS0tOnw6LS0tLS0tLS0tOnw6LS0tLS0tLS0tOnw6LS0tLS0tLS0tOnwKfCBQZXJzb25hIGNvbiBtdWNoYSBkZXNjb25maWFuemEgZW4gbGFzIGZ1ZXJ6YXMgZGVsIG9yZGVuIHwgMSB8IDEgfCAyIHwgMCB8IDAgfCAwIHwKfCBQZXJzb25hIGNvbiBtdWNoYSBjb25maWFuemEgZW4gbGFzIGZ1ZXJ6YXMgZGVsIG9yZGVuIHwgNyB8IDcgfCAxNCB8IDEyIHwgMSB8IDEwMCB8CnwgUGVyc29uYSBjb24gY29uZmlhbnphIG1lZGlhIGVuIGxhcyBmdWVyemFzIGRlbCBvcmRlbiB8IDQgfCA1IHwgOSB8IDcgfCAwLjU4IHwgNTggfAp8IFBlcnNvbmEgY29uIGNvbmZpYW56YSBtZWRpYSBlbiBsYXMgZnVlcnphcyBkZWwgb3JkZW4gfCA2IHwgNCB8IDEwIHwgOCB8IDAuNjYgfCA2NiB8CgpEZSBlc3RhIG1hbmVyYSBjYWRhIHBlcnNvbmEgdGllbmUgdW4gcHVudGFqZSBxdWUgcHVlZGUgdmFyaWFyIGVudHJlIDAgeSAxLCBkZXBlbmRpZW5kbyBkZSBsYXMgcmVzcHVlc3RhcyBxdWUgZGlvIGEgY2FkYSB1bmEgZGUgbGFzIHByZWd1bnRhcyBpbmRpdmlkdWFsZXMuCgpFc3RvIHNlIHB1ZWRlIGNhbGN1bGFyIGVuIFIuCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxhcG9wID0gbGFwb3AgJT4lCiAgbXV0YXRlKGluZGljZSA9IChiMTIrYjE4LTIpLzEyKjEwMCkKYGBgCgpQb2RlbW9zIGFzdW1pciBxdWUgZXN0ZSDDrW5kaWNlIGVzIHVuYSB2YXJpYWJsZSBjdWFudGl0YXRpdmEsIHBvciBsbyBxdWUgcG9kZW1vcyBjYWxjdWxhciBsYSBtZWRpYSB5IGVsIGludGVydmFsbyBkZSBjb25maWFuemEgZGUgbGEgbWVkaWEuCgpgYGB7cn0KbGlicmFyeShsc3IpCmxhcG9wICU+JQogIHN1bW1hcmlzZShtZWRpYSA9IG1lYW4oaW5kaWNlLCBuYS5ybT1UKSwKICAgICAgICAgICAgbGltaW5mID0gY2lNZWFuKGluZGljZSwgbmEucm09VClbMV0sCiAgICAgICAgICAgIGxpbXN1cCA9IGNpTWVhbihpbmRpY2UsIG5hLnJtPVQpWzJdCiAgICAgICAgICAgICkKYGBgCgpNZWpvciBhw7puLCBwb2RlbW9zIGNhbGN1bGFyIGVsIMOtbmRpY2UgZGUgY29uZmlhbnphIGVuIGxhcyBmdWVyemFzIGRlbCBvcmRlbiBwb3IgYcOxbyBkZSBsYSBlbmN1ZXN0YS4KCmBgYHtyfQppbmRpY2V4d2F2ZSA9IGxhcG9wICU+JQogIGdyb3VwX2J5KHdhdmUpICU+JQogIHN1bW1hcmlzZShtZWRpYSA9IG1lYW4oaW5kaWNlLCBuYS5ybT1UKSwKICAgICAgICAgICAgbGltaW5mID0gY2lNZWFuKGluZGljZSwgbmEucm09VClbMV0sCiAgICAgICAgICAgIGxpbXN1cCA9IGNpTWVhbihpbmRpY2UsIG5hLnJtPVQpWzJdCiAgICAgICAgICAgICkKaW5kaWNleHdhdmUKYGBgCgpDb24gbG8gcXVlIHBvZGVtb3MgY29tcGFyYXIgZWwgw61uZGljZSBkZSBhcG95byBhIGxhcyBmdWVyemFzIGRlbCBvcmRlbiBwb3IgYcOxbyBwYXJhIHNhY2FyIGNvbmNsdXNpb25lcyBhY2VyY2EgZGUgZGlmZXJlbmNpYXMuCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpncmFmMyA9IGdncGxvdChpbmRpY2V4d2F2ZSwgYWVzKHg9d2F2ZSwgeT1tZWRpYSkpKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1saW1pbmYsIHltYXg9bGltc3VwKSwgd2lkdGg9MC4yKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXBhc3RlKHJvdW5kKG1lZGlhLCAxKSkpLCB2anVzdD0tMSwgc2l6ZT00KSsKICB4bGFiKCJBw7FvIGRlIGVuY3Vlc3RhcyIpICsgeWxhYigiw41uZGljZSBkZSBjb25maWFuemEgZW4gbGFzIGZ1ZXJ6YXMgZGVsIG9yZGVuIikrCiAgeWxpbSgwLCA2MCkKZ3JhZjMKYGBgCgojIEVqZW1wbG8gMSBwYXJhIHVuYSB2YXJpYWJsZSBjYXRlZ8OzcmljYTogRU5ETwoKU2lndWllbmRvIGNvbiBlbCBlamVtcGxvIGRlIGxhIEVORE8gMjAyMCwgbGEgaGlww7N0ZXNpcyBxdWUgc2UgcHVlZGUgZXZhbHVhciBlcyBzaSBleGlzdGVuIGRpZmVyZW5jaWFzIGVuIHNpIGxvcyBkb2NlbnRlcyBoYW4gcmVjaWJpZG8gYXBveW8gcHNpY29sw7NnaWNvIG8gZW1vY2lvbmFsIHBvciBzZXhvIChQMV8xMykuCgpMYSBoaXDDs3Rlc2lzIGNlcm8gc2Vyw61hOiBMYSBwcm9wb3JjacOzbiBkZSBkb2NlbnRlcyBxdWUgaGFuIHJlY2liaWRvIGFwb3lvIHBzaWNvbMOzZ2ljbyBlbnRyZSBkb2NlbnRlcyBob21icmVzID0gUHJvcG9yY2nDs24gZGUgZG9jZW50ZXMgcXVlIGhhbiByZWNpYmlkbyBhcG95byBwc2ljb2zDs2dpY28gZW50cmUgZG9jZW50ZXMgbXVqZXJlcy4KCkxvIHByaW1lcm8gZXMgdHJhbnNmb3JtYXIgbGEgdmFyaWFibGUgUDFfMTMgcXVlIGVzIGltcG9ydGFkYSBjb21vIG51bcOpcmljYSwgY29tbyB1bmEgdmFyaWFibGUgZGUgZmFjdG9yIHkgY29uIHN1cyBldGlxdWV0YXMuCgpgYGB7cn0KZW5kbzIwMjAgPSBlbmRvMjAyMCAlPiUKICBtdXRhdGUoYXBveW8gPSBmYWN0b3IoUDFfMTMsIGxhYmVscz1jKCJTw60iLCAiTm8iKSkpCmBgYAoKQWhvcmEgdGVuZW1vcyBxdWUgcHJvZHVjaXIgbGEgdGFibGEgZGUgZGlzdHJpYnVjacOzbiBkZSBmcmVjdWVuY2lhcy4KU2kgY2FsY3VsYW1vcyBsYXMgZnJlY3VlbmNpYXMgY29uIGBjb3VudGAgZGlyZWN0YW1lbnRlLCBlc3RhIHRhYmxhIGluY2x1aXLDrWEgdW5hIGZpbGEgZGUgbG9zIE5BcyB5IGx1ZWdvIGNhbGN1bGFyw6EgbG9zIHBvcmNlbnRhamVzIGluY2x1eWVuZG8gYSBlc3RlIGdydXBvLgpFcyBwb3IgZXN0byBxdWUgYW50ZXMgZGUgY2FsY3VsYXIgbGFzIGZyZWN1ZW5jaWFzLCB0ZW5lbW9zIHF1ZSBmaWx0cmFyIHBhcmEgcXVlIHNvbG8gY3VlbnRlIGxvcyAiU8OtIiB5ICJObyIuCkx1ZWdvIGRlIGxhcyBmcmVjdWVuY2lhcywgaW5jbHVpbW9zIGVsIHBvcmNlbnRhamUgY29uIGBtdXRhdGVgLgoKYGBge3J9CnRhYmxhID0gZW5kbzIwMjAgJT4lCiAgZmlsdGVyKGFwb3lvID09IlPDrSIgfCBhcG95byA9PSAiTm8iKSAlPiUKICBjb3VudChBcG95byA9IGFwb3lvLCBuYW1lPSJOIikgJT4lCiAgbXV0YXRlKHRvdGFsID0gc3VtKE4pLCAKICAgICAgICAgUG9yY2VudGFqZSA9IE4gLyB0b3RhbCAqIDEwMCkKdGFibGEKYGBgCgpQb3IgZWplbXBsbywgcGFyYSBoYWxsYXIgZWwgSUMgZGUgbGEgcHJvcG9yY2nDs24gZGUgYXF1ZWxsb3MgZG9jZW50ZXMgcXVlIHJlcG9ydGFyb24gaGFiZXIgcmVjaWJpZG8gYXBveW8gcHNpY29sw7NnaWNvLCBwb2RlbW9zIHVzYXIgZWwgY29tYW5kbyBgcHJvcC50ZXN0YC4KRXN0ZSBjb21hbmRvIHJlcXVpZXJlIGVsIG4gZGUgbGEgb3BjacOzbiAiU8OtIiBkZSBsYSB0YWJsYSB5IGVsIHRvdGFsIGRlIGNhc29zLgpQb3IgZGVmZWN0byBub3MgY2FsY3VsYSBlbCBJQyBhbCA5NSUgZGUgY29uZmlhbnphLgoKYGBge3J9CnByb3AudGVzdCg5NDc2LDE4OTMwKQpgYGAKClNlIGVzdGltYSBxdWUgZWwgbGEgcHJvcG9yY2nDs24gZGUgZG9jZW50ZXMgcXVlIHJlY2liaWVyb24gYXBveW8gcHNpY29sw7NnaWNvIGVzdMOhIGVudHJlIDQ5LjMlIHkgNTAuOCUuCgpMdWVnbywgcGFyYSByZXNwb25kZXIgYSBsYSBwcmVndW50YSBkZSBzaSBlc3RhIHByb3BvcmNpw7NuIHZhcsOtYSBlbnRyZSBkb2NlbnRlcyBob21icmVzIHkgbXVqZXJlcywgdGVuZW1vcyBxdWUgY3JlYXIgb3RyYSB0YWJsYSBjb24gbGFzIGZyZWN1ZW5jaWFzIHkgcG9yY2VudGFqZXMgcG9yIGNhZGEgZ3J1cG8gZGUgbGEgdmFyaWFibGUgInNleG8iLgpQYXJhIGVzdG8sIGFsIGPDs2RpZ28gYW50ZXJpb3IgbGUgYWdyZWdhbW9zIGVsIGNvbWFuZG8gYGdyb3VwX2J5YC4KCmBgYHtyfQp0YWJsYTIgPSBlbmRvMjAyMCAlPiUKICBmaWx0ZXIoYXBveW8gPT0iU8OtIiB8IGFwb3lvID09ICJObyIpICU+JQogIGdyb3VwX2J5KHNleG8pICU+JQogIGNvdW50KEFwb3lvID0gYXBveW8sIG5hbWU9Ik4iKSAlPiUKICBtdXRhdGUodG90YWwgPSBzdW0oTiksIAogICAgICAgICBQb3IgPSBOIC8gdG90YWwgKiAxMDAsCiAgICAgICAgIGVyciA9IHNxcnQoUG9yKigxMDAtUG9yKS9OKSwgCiAgICAgICAgIGxpbWluZiA9IFBvciAtIDEuOTYqZXJyLCAKICAgICAgICAgbGltc3VwID0gUG9yICsgMS45NiplcnIpCnRhYmxhMgpgYGAKCkVsIG1pc21vIGNvbWFuZG8gYHByb3AudGVzdGAgcGVybWl0ZSBoYWNlciBsYSBwcnVlYmEgcGFyYSBsYSBkaWZlcmVuY2lhIGRlIHByb3BvcmNpb25lcy4KUGFyYSBlc3RvLCBsb3MgdmFsb3JlcyB0YW50byBkZSBob21icmVzLCBjb21vIGRlIG11amVyZXMsIHNlIGNvbmNhdGVuYW4gY29uIGxhIGVzcGVjaWZpY2FjacOzbiBgYyjigKYpYCwgdGFudG8gcGFyYSBlbCBuIGRlICJTw60iIGRlIGNhZGEgZ3J1cG8sIGNvbW8gcGFyYSBlbCB0b3RhbCBkZSBjYXNvcyBkZSBjYWRhIGdydXBvLgoKYGBge3J9CnByb3AudGVzdChjKDI3NzcsIDY2OTkpLCBjKDYxNjMsMTI3NjcpKQpgYGAKClNlZ8O6biBsb3MgcmVzdWx0YWRvcywgc2UgZW5jdWVudHJhIHF1ZSBlbCA1Mi41JSBkZSBkb2NlbnRlcyBtdWplcmVzIHJlY2liaWVyb24gYXBveW8gcHNpY29sw7NnaWNvIHZlcnN1cyBlbCA0NS4xJSBkZSBkb2NlbnRlcyBob21icmVzLgpFc3RlIGNvbWFuZG8gbm8gbm9zIGJyaW5kYSBkaXJlY3RhbWVudGUgbG9zIGzDrW1pdGVzIGluZmVyaW9yIHkgc3VwZXJpb3IgZGUgbG9zIElDIGRlIGNhZGEgZ3J1cG8sIHBlcm8gbm9zIGJyaW5kYSBlbCBJQyBkZSBsYSBkaWZlcmVuY2lhIGRlIHByb3BvcmNpb25lcyBhbCA5NSUgZGUgY29uZmlhbnphLgpFc3RlIElDIGRlIGxhIGRpZmVyZW5jaWEgZGUgcHJvcG9yY2lvbmVzIHZhcsOtYSBlbnRyZSAtOC45JSB5IC01LjklLgoKQ29tbyBlc3RlIElDIHZhIHNvbG8gZW50cmUgdmFsb3JlcyBuZWdhdGl2b3M7IGVzIGRlY2lyLCBjb21vIGVsIElDIG5vIGluY2x1eWUgYWwgY2Vybywgc2UgcHVlZGUgY29uY2x1aXIgcXVlIGxhIGRpZmVyZW5jaWEgZGUgcHJvcG9yY2lvbmVzIG5vIHB1ZWRlIHNlciBjZXJvLCBwb3IgbG8gdGFudG8sIHF1ZSBleGlzdGUgdW5hIGRpZmVyZW5jaWEgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YSBlbiBsYXMgcHJvcG9yY2lvbmVzIGVudHJlIGFtYm9zIGdydXBvcy4KCkxhIHRhYmxhIDIgc2UgcHVlZGUgdXNhciBwYXJhIGdyYWZpY2FyLgpDb21vIG5vcyBpbnRlcmVzYSBjb21wYXJhciBsb3MgcG9yY2VudGFqZXMgZGUgZG9jZW50ZXMgcXVlIHJlcG9ydGFyb24gaGFiZXIgcmVjaWJpZG8gYXRlbmNpw7NuIHBzaWNvbMOzZ2ljYSBwb3Igc2V4bywgc2UgcHVlZGUgZWxpbWluYXIgbGFzIGZpbGFzIGRlIGFxdWVsbG9zIHF1ZSBubyByZWNpYmllcm9uIGF0ZW5jacOzbiBwc2ljb2zDs2dpY2EgZW4gbGEgdGFibGEgMi4KCmBgYHtyfQp0YWJsYTIgPSB0YWJsYTJbLWMoMiw0KSxdCmBgYAoKTHVlZ28sIGNvbiBlc3RhIHRhYmxhIHBvZGVtb3Mgc2VndWlyIGVsIG1pc21vIHByb2NlZGltaWVudG8gcXVlIGNvbiBlbCBjw6FsY3VsbyBkZSBsYXMgYmFycmFzIGRlIGVycm9yIHBhcmEgbGEgbWVkaWEsIHBlcm8gZXN0YSB2ZXogcGFyYSBsb3MgcG9yY2VudGFqZXMuCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpncmFmMiA9IGdncGxvdCh0YWJsYTIsIGFlcyh4PXNleG8sIHk9UG9yKSkrCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWxpbWluZiwgeW1heD1saW1zdXApLCB3aWR0aD0wLjIpKwogIGdlb21fdGV4dChhZXMobGFiZWw9cGFzdGUocm91bmQoUG9yLCAxKSkpLCB2anVzdD0tMSwgc2l6ZT00KSsKICB4bGFiKCJTZXhvIGRlbCBkb2NlbnRlIikgKyB5bGFiKCJQb3JjZW50YWplIHF1ZSByZWNpYmnDsyBhdGVuY2nDs24gcHNpY29sw7NnaWNhIikrCiAgeWxpbSgwLCA2MCkKZ3JhZjIKYGBgCgpEZSBlc3RlIGdyw6FmaWNvIHNlIHB1ZWRlIGNvbmNsdWlyIHF1ZSBleGlzdGVuIGRpZmVyZW5jaWFzIGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdmFzIGVuIGVsIHBvcmNlbnRhamUgZGUgZG9jZW50ZXMgcXVlIGJ1c2Nhcm9uIGF0ZW5jacOzbiBwc2ljb2zDs2dpY2EgZW50cmUgaG9tYnJlcyB5IG11amVyZXMsIGRlYmlkbyBhIHF1ZSBsb3MgaW50ZXJ2YWxvcyBkZSBjb25maWFuemEgbm8gc2UgdHJhc2xhcGFuLgoKRGUgbWFuZXJhIG3DoXMgZXNwZWPDrWZpY2EsIHNlIHB1ZWRlIGFmaXJtYXIgcXVlIGxhcyBkb2NlbnRlcyBwZXJ1YW5hcyByZWNpYmVuIG3DoXMgYXRlbmNpw7NuIHBzaWNvbMOzZ2ljYSBxdWUgbG9zIGRvY2VudGVzIGhvbWJyZXMuCgojIEVqZW1wbG8gMiBwYXJhIHVuYSB2YXJpYWJsZSBjYXRlZ8OzcmljYTogTEFQT1AKCkVuIGxhIHDDoWdpbmEgMjEgZGVsIHJlcG9ydGUgKkN1bHR1cmEgcG9sw610aWNhIGRlIGxhIGRlbW9jcmFjaWEgZW4gUGVyw7ogeSBlbiBsYXMgQW3DqXJpY2FzIDIwMjE6IFRvbcOhbmRvbGUgZWwgcHVsc28gYSBsYSBkZW1vY3JhY2lhKiBzZSBwcmVzZW50YSBlbCBncsOhZmljbyBxdWUgbXVlc3RyYSBlbCBwb3JjZW50YWplIGRlIGFwb3lvIGEgbGEgZGVtb2NyYWNpYSBlbiBQZXLDuiAobMOtbmVhIG1hZ2VudGEpIGEgbG8gbGFyZ28gZGVsIHRpZW1wbywgZW4gY29tcGFyYWNpw7NuIGNvbiBBbcOpcmljYSBMYXRpbmEgKGzDrW5lYSBtb3JhZGEpLgoKRWwgYXBveW8gYSBsYSBkZW1vY3JhY2lhLCB2YXJpYWJsZSAiSU5HNCIsIGVzdMOhIG1lZGlkYSBlbiB1bmEgZXNjYWxhIGRlbCAxIGFsIDcsIGRvbmRlIDEgc2lnbmlmaWNhICJtdXkgZW4gZGVzYWN1ZXJkbyIgeSA3IHNpZ25pZmljYSAibXV5IGRlIGFjdWVyZG8iLgpFc3RhIHZhcmlhYmxlIHNlIHRpZW5lIHF1ZSByZWNvZGlmaWNhci4KRGUgYWN1ZXJkbyBhbCByZXBvcnRlICJMYXMgcmVzcHVlc3RhcyB2YW4gZGUgMSAobXV5IGVuIGRlc2FjdWVyZG8pIGEgNyAobXV5IGRlIGFjdWVyZG8pLiBQYXJhIGVzdGUgYW7DoWxpc2lzLCBzZSBjb2RpZmljYXJvbiBsYXMgcmVzcHVlc3RhcyBlbiBlbCBleHRyZW1vImRlIGFjdWVyZG8iIGRlIGxhIGVzY2FsYSAodmFsb3JlcyBxdWUgdmFuIGRlIDUgYSA3KSBjb21vIGFwb3lvIGEgbGEgZGVtb2NyYWNpYS4iIChwLjcpLgoKIVtdKGFwb3lvX3BlcnUucG5nKQoKUGFyYSByZWNvZGlmaWNhciBsYSB2YXJpYWJsZSBzZSB1c2EgZWwgc2lndWllbnRlIGPDs2RpZ28uCkVsIHJlc3VsdGFkbyBlcyB1bmEgdmFyaWFibGUgZGljb3TDs21pY2EgKDA9Tm8sIDE9U8OtKSwgcXVlIGVzIHVuYSB2YXJpYWJsZSBjYXRlZ8OzcmljYSwgYXVucXVlIGluY2x1eWUgdW4gZ3J1cG8gcXVlIG5vIHRpZW5lIHJlc3B1ZXN0YSBlbiBlc3RhIHZhcmlhYmxlIHkgZXN0w6EgY29tbyBOQXMuCgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGFwb3AgPSBsYXBvcCAlPiUKICBtdXRhdGUoaW5nNHJlYz0gY2FzZV93aGVuKAogICAgaW5nNCA+PSAxICYgaW5nNCA8PSA0IH4gMCwKICAgIGluZzQgPj0gNSAmIGluZzQgPD0gNyB+IDEsCiAgICApKQpgYGAKClNlIHZlcmlmaWNhIGxhIHJlY29kaWZpY2FjacOzbi4KCmBgYHtyfQpsYXBvcCAlPiUKICBjb3VudChpbmc0LCBuYW1lPSJGcmVjdWVuY2lhIikKYGBgCgpMbyBxdWUgcXVlcmVtb3MgZXMgZW5jb250cmFyIGVsIGludGVydmFsbyBkZSBjb25maWFuemEgZGUgbGEgcHJvcG9yY2nDs24gKG8gcG9yY2VudGFqZSkgZGUgYXF1ZWxsb3MgcXVlIHJlc3BvbmRlbiAiU8OtIiAobGFzIDc3NTQgcGVyc29uYXMgY29uIHVuIDEpLgpPam8gcXVlIGxhIHRhYmxhIG11ZXN0cmEgYSAzOTMgcGVyc29uYXMgY29uIE5Bcy4KCmBgYHtyfQpsYXBvcCAlPiUKICBjb3VudChpbmc0cmVjLCBuYW1lPSJGcmVjdWVuY2lhIikKYGBgCgpZIHF1ZXJlbW9zIGNhbGN1bGFyIGVsIHBvcmNlbnRhamUgZGUgYXF1ZWxsb3MgcXVlIHJlc3BvbmRlbiAiU8OtIiBwb3IgYcOxbyBkZSBsYSBlbmN1ZXN0YS4KTGEgdmFyaWFibGUgcXVlIHJlZ2lzdHJhIGVsIGHDsW8gZGUgbGEgZW5jdWVzdGEgZXMgIndhdmUiLgpFc3RhIHZhcmlhYmxlIHNlIGNhcmdhIGNvbW8gdW5hIG51bcOpcmljYSAocG9yIGVzdGUgbW90aXZvLCBlbiBlbCBncsOhZmljbyBhbnRlcmlvciBlbCBlamUgWCBkZWwgZ3LDoWZpY28gYXBhcmVjZSBjb21vIHVuYSB2YXJpYWJsZSBjb250aW51YSkgeSBzZSB0aWVuZSBxdWUgdHJhbnNmb3JtYXIgYSB1bmEgZGUgZmFjdG9yIGxsYW1hZGEgInJvbmRhIi4KCmBgYHtyfQpsYXBvcCA9IGxhcG9wICU+JQogIG11dGF0ZShyb25kYSA9IGZhY3Rvcih3YXZlKSkKYGBgCgpTZSBjYWxjdWxhIGVsIGFwb3lvIGEgbGEgZGVtb2NyYWNpYSBwb3IgYcOxb3MuClBhcmEgZWwgY8OhbGN1bG8gZGUgZXN0YSB0YWJsYSBxdWVyZW1vcyBleGNsdWlyIGEgYXF1ZWxsb3MgcXVlIG5vIHRpZW5lbiByZXNwdWVzdGEgZW4gbGEgdmFyaWFibGUgYXBveW8gYSBsYSBkZW1vY3JhY2lhIChsb3MgMzkzIE5BcyBhbnRlcmlvcmVzKS4KRXN0byBsbyBwb2RlbW9zIGhhY2VyIGNvbiBlbCBjb21hbmRvIGBmaWx0ZXJgLCBkb25kZSBlc3BlY2lmaWNhbW9zIHF1ZSBzb2xvIHF1ZXJlbW9zIGNhbGN1bGFyIGxvcyBwb3JjZW50YWplcyBkZSBhcXVlbGxvcyBxdWUgcmVzcG9uZGllcm9uIE5vIChvIDAgZW4gbGEgdmFyaWFibGUpIHkgYXF1ZWxsb3MgcXVlIHJlc3BvbmRpZXJvbiBTw60gKG8gMSBlbiBsYSB2YXJpYWJsZSkuCgpFbiBjYWRhIGdydXBvIHNlIHF1aWVyZSBjYWxjdWxhciBlbCBpbnRlcnZhbG8gZGUgY29uZmlhbnphIGRlIGxhIHByb3BvcmNpw7NuLgpSZWN1ZXJkZW4gcXVlIGxhIGbDs3JtdWxhIHF1ZSBzZSB0aWVuZSBxdWUgdXNhciBlcyBsYSBkZSBpbnRlcnZhbG9zIGRlIGNvbmZpYW56YSBkZSBsYSBwcm9wb3JjacOzbi4KCkRlbnRybyBkZWwgY29tYW5kbyBgbXV0YXRlYCBjYWxjdWxhbW9zIGVsIHRvdGFsIGVuIGNhZGEgZ3J1cG8gKHRvdGFsKSwgbGEgcHJvcG9yY2nDs24gKFBvciksIGVsIGVycm9yIGVzdMOhbmRhciAoZXJyIHF1ZSBlcyBpZ3VhbCBhIGxhIHJhw616IGN1YWRyYWRhIGRlbCBwb3JjZW50YWplIHBvciAxMDAtcG9yY2VudGFqZSBlbnRyZSBOKSB5IGVsIGzDrW1pdGUgaW5mZXJpb3IgeSBzdXBlcmlvciBkZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YS4KCmBgYHtyfQp0YWJsYTMgPSBsYXBvcCAlPiUKICBmaWx0ZXIoaW5nNHJlYyA9PTAgfCBpbmc0cmVjID09IDEpICU+JQogIGdyb3VwX2J5KHJvbmRhKSAlPiUKICBjb3VudChBcG95byA9IGluZzRyZWMsIG5hbWU9Ik4iKSAlPiUKICBtdXRhdGUodG90YWwgPSBzdW0oTiksIAogICAgICAgICBQb3IgPSBOIC8gdG90YWwgKiAxMDAsIAogICAgICAgICBlcnIgPSBzcXJ0KFBvciooMTAwLVBvcikvTiksIAogICAgICAgICBsaW1pbmYgPSBQb3IgLSAxLjk2KmVyciwgCiAgICAgICAgIGxpbXN1cCA9IFBvciArIDEuOTYqZXJyKQp0YWJsYTMKYGBgCgpMYSB0YWJsYSBtdWVzdHJhIGxvcyBkYXRvcyBkZSBsb3MgcXVlIG5vIGFwb3lhbiBhIGxhIGRlbW9jcmFjaWEgKGZpbGFzIGRvbmRlIEFwb3lvPTApIHkgZGUgbG9zIHF1ZSBzw60gYXBveWFuIGEgbGEgZGVtb2NyYWNpYSAoZmlsYXMgZG9uZGUgQXBveW89MSkgcG9yIGNhZGEgcm9uZGEuCgpDb21vIHNvbG8gc2UgcXVpZXJlIGdyYWZpY2FyIGEgbG9zIHF1ZSBzw60gYXBveWFuIGEgbGEgZGVtb2NyYWNpYSwgc2UgZGViZW4gZWxpbWluYXIgdG9kYXMgbGFzIGZpbGFzIGltcGFyZXMuCgpgYGB7cn0KdGFibGEzID0gdGFibGEzWy1jKDEsMyw1LDcsOSwxMSwxMywxNSksXQp0YWJsYTMKYGBgCgpBaG9yYSwgdGVuZW1vcyBsb3MgZGF0b3MgcGFyYSBncmFmaWNhci4KCmBgYHtyfQpncmFmNCA9IGdncGxvdCh0YWJsYTMsIGFlcyh4PXJvbmRhLCB5PVBvcikpKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1saW1pbmYsIHltYXg9bGltc3VwKSwgd2lkdGg9MC4yKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXBhc3RlKHJvdW5kKFBvciwgMSkpKSwgdmp1c3Q9LTEsIHNpemU9NCkrCiAgeGxhYigiUm9uZGEiKSArIHlsYWIoIlBvcmNlbnRhamUgcXVlIGFwb3lhIGEgbGEgZGVtb2NyYWNpYSIpKwogIHlsaW0oMCwgNzApCmdyYWY0CmBgYAoKIyBOb3RhIGZpbmFsCgpMYSBjb21wYXJhY2nDs24gZGUgSUMsIHlhIHNlYSBjYWxjdWxhbmRvIGxvcyB2YWxvcmVzIHBhcmEgY2FkYSBncnVwbyBvIHlhIHNlYSBkZSBtYW5lcmEgZ3LDoWZpY2EsIGVzIHVuYSBwcmltZXJhIG1hbmVyYSBkZSBhbmFsaXphciBzaSBsYXMgZGlmZXJlbmNpYXMgZW50cmUgZ3J1cG9zIHNlIHB1ZWRlbiBleHRyYXBvbGFyIGEgbGEgcG9ibGFjacOzbi4KClBlcm8gZXN0YSBlcyB1bmEgbWFuZXJhICJpbmZvcm1hbCIgZGUgaGFjZXIgZXN0YSBjb21wYXJhY2nDs24uClBhcmEgZm9ybWFsaXphciBlc3RhIGNvbXBhcmFjacOzbiBleGlzdGUgdW5hIHBydWViYSBlc3RhZMOtc3RpY2EgbGxhbWFkYSBwcnVlYmEgdCBkZSBkaWZlcmVuY2lhcyBkZSBtZWRpYXMgbyBsYSBwcnVlYmEgZGUgcHJvcG9yY2lvbmVzLCBxdWUgc2UgdmVyw6FuIGVuIGxhIHNpZ3VpZW50ZSBzZXNpw7NuLgoKIyBCaWJsaW9ncmFmw61hCg==