rm(list=ls())

Tidyverse

Este paquete agrupa una serie de paquetes que tienen una misma lógica en su diseño y por ende funcionan en armonía.
Entre ellos usaremos principalmente ggplot para realizar gráficos, y dplyr y tidyr para realizar transformaciones sobre nuestro set de datos.

A continuación cargamos la librería a nuestro ambiente. Para ello debe estar previamente instalada en nuestra pc.

library(tidyverse)
library(dplyr)
library(tidyr)
library(ggplot2)
library(lubridate)

Para mostrar el funcionamiento básico de tydyverse retomaremos el ejemplo de la clase 1, con lo cual volvemos a crear el set de datos del Indice de salarios.

INDICE  <- c(100,   100,   100,
             101.8, 101.2, 100.73,
             102.9, 102.4, 103.2)
FECHA  <-  c("Oct-16", "Oct-16", "Oct-16",
             "Nov-16", "Nov-16", "Nov-16",
             "Dec-16", "Dec-16", "Dec-16")
GRUPO  <-  c("Privado_Registrado","Público","Privado_No_Registrado",
             "Privado_Registrado","Público","Privado_No_Registrado",
             "Privado_Registrado","Público","Privado_No_Registrado")
Datos <- data.frame(INDICE, FECHA, GRUPO)

Dplyr

El caracter principal para utilizar este paquete es %>% , pipe (de tubería).

Los %>% toman el set de datos a su izquierda, y los transforman mediante los comandos a su derecha, en los cuales los elementos de la izquierda están implícitos. En otros términos.

\(f(x,y)\) es equivalente a \(x\) %>% \(f(.,y)\)

Veamos las principales funciones que pueden utilizarse con la lógica de este paquete:

glimpse

Permite ver la estructura de la tabla. Nos muestra:

  • número de filas
  • número de columnas
  • nombre de las columnas
  • tipo de dato de cada columna
  • las primeras observaciones de la tabla
glimpse(Datos)
Observations: 9
Variables: 3
$ INDICE <dbl> 100.00, 100.00, 100.00, 101.80, 101.20, 100.73, 102.90, 102.40, 103.20
$ FECHA  <fct> Oct-16, Oct-16, Oct-16, Nov-16, Nov-16, Nov-16, Dec-16, Dec-16, Dec-16
$ GRUPO  <fct> Privado_Registrado, Público, Privado_No_Registrado, Privado_Registrado, Público, Privado_No_Registrado, ...

filter

Permite filtrar la tabla acorde al cumplimiento de condiciones lógicas

Datos %>% 
  filter(INDICE>101 , GRUPO == "Privado_Registrado")

Nótese que en este caso al separar con una , las condiciones se exige el cumplimiento de ambas. En caso de desear que se cumpla una sola condición debe utilizarse el caracter |

Datos %>% 
  filter(INDICE>101 | GRUPO == "Privado_Registrado")

rename

Permite renombrar una columna de la tabla. Funciona de la siguiente manera: Data %>% rename( nuevo_nombre = viejo_nombre )

Datos %>% 
  rename(Periodo = FECHA)

Nótese que a diferencia del ejemplo de la función filter donde utilizábamos == para comprobar una condición lógica, en este caso se utiliza sólo un = ya que lo estamos haciendo es asignar un nombre.

mutate

Permite agregar una variable a la tabla (especificando el nombre que tomará esta), que puede ser el resultado de operaciones sobre otras variables de la misma tabla.

En caso de especificar el nombre de una columna existente, el resultado de la operación realizada “sobrescribirá” la información de la columna con dicho nombre

Datos <- Datos %>% 
  mutate(Doble=INDICE*2)
Datos

case_when

Permite definir una variable, la cual toma un valor particular para cada condición establecida. En caso de no cumplir ninguna de las condiciones establecidas la variable tomara valor NA La sintaxis de la función es case_when( condicion lógica1 ~ valor asignado1).

Datos <- Datos %>% 
  mutate(Caso_cuando = case_when(GRUPO == "Privado_Registrado"   ~ INDICE*2,
                                 GRUPO == "Público"              ~ INDICE*3,
                                 GRUPO == "Privado_No_Registrado"~ INDICE*5))
Datos

select

Permite especificar la serie de columnas que se desea conservar de un DataFrame. También pueden especificarse las columnas que se desean descartar (agregándoles un -). Muy útil para agilizar el trabajo en bases de datos de gran tamaño.

Datos2 <- Datos %>% 
  select(INDICE, FECHA, GRUPO)
Datos2
Datos <- Datos %>% 
  select(-c(Doble,Caso_cuando))
Datos

arrange

Permite ordenar la tabla por los valores de determinada/s variable/s. Es útil cuando luego deben hacerse otras operaciones que requieran del ordenamiento de la tabla

Datos <- Datos %>% 
  arrange(GRUPO, INDICE)
Datos

summarise

Crea una nueva tabla que resuma la información original. Para ello, definimos las variables de resumen y las formas de agregación.

Datos %>% 
  summarise(Indprom = mean(INDICE))

group_by

Esta función permite realizar operaciones de forma agrupada. Lo que hace la función es “separar” a la tabla según los valores de la variable indicada y realizar las operaciones que se especificaba continuación, de manera independiente para cada una de las “subtablas”. En nuestro ejemplo, sería útil para calcular el promedio de los indices por Fecha

Datos %>% 
  group_by(FECHA) %>%
  summarise(Indprom = mean(INDICE))

Joins

Otra implementación muy importante del paquete dplyr son las funciones para unir tablas (joins)

left_join

Veamos un ejemplo de la función left_join (una de las más utilizadas en la práctica).
Para ello crearemos previamente un Dataframe que contenga un Ponderador para cada uno de los Grupos del Dataframe Datos. Aprovecharemos el ejemplo para introducir la función weigthed.mean, y así calcular un Indice Ponderado.

Ponderadores <- data.frame(GRUPO = c("Privado_Registrado","Público","Privado_No_Registrado"),
                            PONDERADOR = c(50.16,29.91,19.93))
Datos_join <- Datos %>% 
  left_join(.,Ponderadores, by = "GRUPO")
Datos_join
Datos_Indice_Gral <- Datos_join %>% 
  group_by(FECHA) %>% 
  summarise(Indice_Gral = weighted.mean(INDICE,w = PONDERADOR))
Datos_Indice_Gral

Tidyr

El paquete tidyr esta pensado para facilitar el emprolijamiento de los datos.

Gather es una función que nos permite pasar los datos de forma horizontal a una forma vertical.

spread es una función que nos permite pasar los datos de forma vertical a una forma horizontal.

#Utilzamos un conjunto de datos que viene con la librería datasets
library(datasets)
data(iris)
iris <- iris %>% 
  mutate(id = 1:nrow(.)) %>%  #le agrego un ID
  select(id, everything()) # lo acomodo para que el id este primero. 
iris

Gather y Spread

iris_vertical <- iris %>% gather(., # el . llama a lo que esta atras del %>% 
                                 key   = Variables,
                                 value = Valores,
                                 2:5) #le indico que columnas juntar
iris_vertical

Podemos deshacer el gather con un Spread

iris_horizontal <- iris_vertical %>%
  spread(. ,
         key   = Variables, #la llave es la variable que va a dar los nombres de columna
         value = Valores) #los valores con que se llenan las celdas
iris_horizontal

Lubridate

El paquete lubridate está pensado para trabajar con los datos tipo fecha(date) o fecha-hora(datetime) para cambiarles el formato, realizar operaciones y extraer información

Cambio de formato

Existe una gran cantidad de funciones para realizar esto. La idea general es poder llevar los objetos datetime a un formato común compuesto de los elementos: año, mes, día, hora, minuto y segundo (también se puede setear el huso horario)

fecha  <- "04/12/92 17:35:16"
fecha
[1] "04/12/92 17:35:16"

Con la función dmy_hms podemos convertir este string a una fecha: estamos indicando que el formato de la fecha es día(d), mes(m), año(y), hora(h), minuto(m) y segundo(s)

fecha  <- dmy_hms(fecha)
fecha
[1] "1992-12-04 17:35:16 UTC"

Muchas funciones de lubridate operan con esta misma lógica

Otra función para realizar un cambio de formato es parse_date_time. Permite construir objetos datetime a partir de datos más complejos, como por ejemplo cuando aparece el nombre del mes y el año.

En el parámetro x pasamos el dato de la fecha y en el parámetro orders especificamos el orden en el cual se encuentra la información de la fecha

fecha2  <- "Dec-92"
fecha2 <- parse_date_time(fecha2, orders = 'my')
fecha2
[1] "1992-12-01 UTC"

Extracción de información

Existen muchas funciones muy sencillas para extraer información de un objeto datetime. Algunas son

year(fecha) # Obtener el año
[1] 1992
month(fecha) #Obtener el mes
[1] 12
day(fecha) # Obtener el día
[1] 4
wday(fecha, label = TRUE) #Obtener el nombre del día
[1] vie
Levels: dom < lun < mar < mié < jue < vie < sáb
hour(fecha) #Obtener la hora
[1] 17

Operaciones

Podemos sumar o restarle cualquier período de tiempo a un objeto datetime

# Sumo dos días 
fecha + days(2)
[1] "1992-12-06 17:35:16 UTC"
# Resto 1 semana y dos horas
fecha - (weeks(1) + hours(2))
[1] "1992-11-27 15:35:16 UTC"

Gráficos

Gráficos Básicos en R

Rbase tiene algunos comandos genéricos para realizar gráficos, que se adaptan al tipo de información que se le pide graficar, por ejemplo:

  • plot()
  • hist()
iris
plot(iris)

plot(iris$Sepal.Length,type = "p")

plot(iris$Sepal.Length,type = "l")

plot(iris$Sepal.Length,type = "b")

hist(iris$Sepal.Length, col = "lightsalmon1", main = "Histograma")

Para guardar los gráficos

png("Grafico1.png")
plot(iris$Sepal.Length,type = "b")
dev.off()
null device 
          1 

La función png() abre el dispositivo de imagen, luego podemos hacer los gráficos, y a continuación, con dev.off() se cierra el dispositivo y se graban los gráficos.

Los gráficos del R base son útiles para escribir de forma rápida y obtener alguna información mientras trabajamos. Muchos paquetes estadísticos permiten mostrar los resultados de forma gráfica con el comando plot (por ejemplo, las regresiones lineales lm()).

Sin embargo, existen librerías mucho mejores para crear gráficos de nivel de publicación. La más importante es ggplot2, que a su vez tiene extensiones mediante otras librerías.

Ggplot2

ggplot tiene su sintaxis propia. La idea central es pensar los gráficos como una sucesión de capas, que se construyen una a la vez.

  • El operador + nos permite incorporar nuevas capas al gráfico.

  • El comando ggplot() nos permite definir los datos y las variables (x,y,color,forma,etc).

  • Las sucesivas capas nos permiten definir:
    • Uno o más tipos de gráficos (de columnas, geom_col(), de línea, geom_line(), de puntos,geom_point(), boxplot, geom_boxplot())
    • Títulos labs()
    • Estilo del gráfico theme()
    • Escalas de los ejes scale_y_continuous,scale_x_discrete
    • División en subconjuntos facet_wrap(),facet_grid()

ggplot tiene muchos comandos, y no tiene sentido saberlos de memoria, es siempre útil reutilizar gráficos viejos y tener a mano el machete.

library(ggplot2)
library(ggthemes)  # estilos de gráficos
library(ggrepel)   # etiquetas de texto más prolijas que las de ggplot
library(scales)    # tiene la función 'percent()'
ggplot(data = iris, aes(x = Sepal.Length, fill = Species))+
  geom_histogram(alpha=0.75, binwidth = .5)+
  facet_wrap(~Species)+
  labs(title = "Histograma por especie")+
  theme(legend.position = 'none')

Lo útil de hacer gráficos en R, en lugar de por ejemplo excel, es que podemos hacer uso de más dimensiones, por ejemplo:

  • Gráficos que necesitan la información a nivel de microdatos. puntos, boxplots, Kernels, etc.
  • Abrir el mismo gráfico según alguna variable discreta: facet_wrap()
  • Parametrizar otras variables, para aumentar la dimensionalidad del gráficos.
    • color color =
    • rellenofill =
    • forma shape =
    • tamaño size =
    • transparencia alpha =

Esto permite tener, en el plano, gráficos de muchas dimensiones de análisis

Cuando queremos utilizar estos parámetros para representar una variable, los definimos dentro del aes(), aes(... color = ingresos), cuando queremos simplemente mejorar el diseño, se asignan por fuera, o dentro de cada tipo de gráficos, geom_col(color = 'green').

levanto una base de microdatos de EPH para graficar

Individual_t117 <- read.table(paste0("../Fuentes/usu_individual_t117.txt"),
                              sep=";", dec=",", header = TRUE, fill = TRUE)

Boxplots

Hacemos un procesamiento simple: Sacamos los ingresos iguales a cero y las no respuestas de nivel educativo.
Las variables sexo( CH04 ) y Nivel educativo están codificadas como números, y el R las entiende como numéricas.

Es importante que las variables sean del tipo que conceptualmente les corresponde (el nivel educativo es una variable categórica, no continua), para que el ggplot pueda graficarlo correctamente.

ggdata <- Individual_t117 %>% 
  filter(P21>0, !is.na(NIVEL_ED)) %>% 
  mutate(NIVEL_ED = as.factor(NIVEL_ED),
         CH04     = as.factor(CH04))

si queremos hacer un boxplot del ingreso para cada nivel educativo, asignamos esta variable a x, group y fill

ggplot(ggdata, aes(x = NIVEL_ED, y = P21, group = NIVEL_ED, fill = NIVEL_ED )) +
  geom_boxplot()+
  scale_y_continuous(limits = c(0, 40000))

Si queremos agregar la dimensión sexo, podemos hacer un facet_wrap()

ggplot(ggdata, aes(x= NIVEL_ED, y = P21, group = NIVEL_ED, fill = NIVEL_ED )) +
  geom_boxplot()+
  scale_y_continuous(limits = c(0, 40000))+
  facet_wrap(~ CH04, labeller = "label_both")

En este gráfico, el foco de atención sigue puesto en las diferencias de nivel educativo, pero neutralizamos el efecto de la variable sexo.

Si lo que queremos hacer es poner el foco de atención en las diferencias por sexo, neutralizamos el efecto del nivel educativo, facetiando por nivel educativo.

ggplot(ggdata, aes(x= CH04, y = P21, group = CH04, fill = CH04 )) +
  geom_boxplot()+
  scale_y_continuous(limits = c(0, 40000))+
  facet_wrap(~ NIVEL_ED, labeller = "label_both")

Kernels

Podemos hacer una nueva versión del gráfico 2. Utilizando un procesamiento similar al que hicimos antes.

datagraf <-Individual_t117 %>% 
  select(REGION,P47T,T_VI, TOT_P12, P21 , PONDII, CH04) %>% 
  filter(!is.na(P47T), P47T > 0 ) %>% 
  mutate(REGION             = case_when(REGION == 1    ~ 'GBA',
                                        REGION == 40   ~ 'NOA',
                                        REGION == 41   ~ 'NEA',
                                        REGION == 42   ~ 'Cuyo',
                                        REGION == 43   ~ 'Peampeana',
                                        REGION == 44   ~ 'Patagonia',
                                        FALSE          ~ 'otro'),
         ingreso_laboral    = as.numeric(TOT_P12 + P21),
         ingreso_no_laboral = as.numeric(T_VI),
         CH04               = case_when(CH04 == 1 ~ "Varon",
                                        CH04 == 2 ~ "Mujer",
                                        FALSE     ~ "Otro") ) %>% 
  gather(., key = Tipo_ingreso, Ingreso, c((ncol(.)-1):ncol(.)))
datagraf  

Con los Kernels, no necesitamos dividir a la población en deciles, porque podemos tener una mirada completa de la forma de la distribución.

Para este gráfico, quiero eliminar los ingresos = 0

datagraf2 <- datagraf %>% filter( Ingreso !=0)
  
  
ggplot(datagraf2, aes(
  x = Ingreso,
  weights = PONDII,
  group = Tipo_ingreso,
  fill = Tipo_ingreso)) +
  geom_density(alpha=0.7,adjust =2)+
  labs(x="Distribución del ingreso", y="",
       title=" Total según tipo de ingreso y género", 
       caption = "Fuente: Encuesta Permanente de Hogares")+
  scale_x_continuous(limits = c(0,50000))+
  theme_tufte()+
  scale_fill_gdocs()+
  theme(legend.position = "bottom",
        plot.title      = element_text(size=12))+
  facet_wrap(~ CH04, scales = "free")
ggsave(filename = paste0("../Resultados/", "Kernel_1.png"),scale = 2)
Saving 14.6 x 9 in image

En este tipo de gráficos, importa mucho qué variable se utiliza para facetear y qué variable para agrupar, ya que la construcción de la distribución es diferente.

ggplot(datagraf2, aes(
  x = Ingreso,
  weights = PONDII,
  group = CH04,
  fill = CH04)) +
  geom_density(alpha=0.7,adjust =2)+
  labs(x="Distribución del ingreso", y="",
       title=" Total según tipo de ingreso y género", 
       caption = "Fuente: Encuesta Permanente de Hogares")+
  scale_x_continuous(limits = c(0,50000))+
  theme_tufte()+
  scale_fill_gdocs()+
  theme(legend.position = "bottom",
        plot.title      = element_text(size=12))+
  facet_wrap(~Tipo_ingreso, scales = "free")
ggsave(filename = paste0("../Resultados/", "Kernel_1.png"),scale = 2)
Saving 14.6 x 9 in image

El eje y no tiene demasiada interpretabilidad en los Kernel, porque hace a la forma en que se construyen las distribuciones.

Tendencia

Para realizar estos gráficos, vamos a modificar un poco los datos:

  • filtramos los ingresos iguales a 0.
  • eliminamos las no respuestas de nivel educativo y las personas con educación especial.
  • eliminamos las respuestas de tipo de establecimiento = ‘otros’.
  • recodificamos las variables para que tengan nombres más sugestivos:
    • Nivel educativo además la convertimos a factor, porque queremos explicitarle el orden de los valores con levels(). El “\n”" es un caracter especial que permite que el string continúe en la siguiente línea.
    • Sexo.
    • Tipo de establecimiento.
ggdata <- Individual_t117 %>% 
  filter(P21>0,
         !is.na(NIVEL_ED),
         NIVEL_ED!=7, 
         PP04A !=3) %>% 
  mutate(NIVEL_ED = factor(case_when(NIVEL_ED == 1  ~ 'Primaria \n Incompleta', # '\n' significa carriage return, o enter
                                     NIVEL_ED == 2  ~ 'Primaria \n Completa',
                                     NIVEL_ED == 3  ~ 'Secundaria \nIncompleta',
                                     NIVEL_ED == 4  ~ 'Secundaria \nCompleta',
                                     NIVEL_ED == 5  ~ 'Superior \nUniversitaria \nIncompleta',
                                     NIVEL_ED == 6  ~ 'Superior \nUniversitaria \nCompleta',
                                     FALSE          ~ 'Otro'),
                           levels= c('Primaria \n Incompleta',
                                     'Primaria \n Completa',
                                     'Secundaria \nIncompleta',
                                     'Secundaria \nCompleta',
                                     'Superior \nUniversitaria \nIncompleta',
                                     'Superior \nUniversitaria \nCompleta')),
         Sexo     = case_when(CH04 == 1 ~ 'Varón',
                              CH04 == 2 ~ 'Mujer'),
         Establecimiento    = case_when(PP04A == 1 ~ 'Estatal',
                                        PP04A == 2 ~ 'Privado',
                                        FALSE      ~ 'Otro'))
ggdata

Para graficar un suavizado de las series, se utiliza la función geom_smooth(). Con suavizado nos referimos al gráfico de un modelo realizado sobre los datos, que estima el valor en el punto x,y (para el grupo). Las regresiones lineales son un ejemplo de esto, aunque no el único, ni el que viene por default.

ggplot(ggdata, aes(CH06, P21, colour = Sexo, shape = Sexo, alpha = P21))+
  geom_smooth() + 
  labs(
    x = 'Edad',
    y = 'ingreso',
    title = 'Ingreso por ocupación principal',
    subtitle = 'Según edad, nivel educativo y sexo') +
  theme_minimal()+
  scale_y_continuous(labels = comma)+
  scale_alpha(guide = FALSE)+
  facet_grid(.~NIVEL_ED)

Si corremos el comando geom_smooth() por default, nos advierte que esta utilizando el método GAM, de general additive models.

el sombreado gris que envuelve cada línea es el intervalo de confianza de dicho punto (95% por default).

También podemos utilizar métodos lineales, agregando el parámetro method = 'lm'. Haciendo esto, el gráfico muestra una regresión lineal simple. Si queremos otro tipo de regresión lineal, le podemos explicitar la fórmula.
En el ejemplo siguiente, utilizamos la formula $y = _0 +_1x +_2 x^2 $.

ggplot(ggdata, aes(CH06, P21, colour = Sexo, weight = PONDIIO)) +
  geom_smooth(method = "lm", formula = y ~ poly(x, 2)) +
  labs(x = 'Edad',
       y = 'ingreso',
       title = 'Regresion cuadrática del Ingreso por ocupación principal respecto de la Edad',
       subtitle = 'Según Nivel educativo y sexo') +
  theme_minimal()+
  facet_grid(. ~ NIVEL_ED)

Si quisiéramos, además de ver la relación entre ingreso, Edad, Sexo y Nivel educativo, incorporar el tipo de establecimiento,público o privado. Podemos facetear el gráfico por dos variables en lugar de una, lo que crea una matriz de gráficos según los cruces.

ggplot(ggdata, aes(CH06, P21, colour = Establecimiento, weight = PONDIIO)) +
  geom_smooth(method = "lm") +
  labs(
  x = 'Edad',
  y = 'ingreso',
  title = 'Tendencia del ingreso por ocupación principal',
  subtitle = 'Según edad, nivel educativo, sexo y tipo de establecimiento') +
  theme_minimal()+
  facet_grid(Sexo ~ NIVEL_ED)

ggsave(filename = paste0("../Resultados/", "regresion lineal.png"),scale = 2)
Saving 16 x 10 in image

Ejercicios para practicar

Precios y dólar

En la carpeta fuentes se encuentran los archivos dolar-diario.csv y ipc-mensual.csv. Con ellos, el objetivo es realizar un análisis exploratorio de estas variables de la economía argentina. La base de datos del dolar tiene frecuencia diaria y comienza en Marzo de 2002. La base de datos del IPC tiene frecuencia mensual y comienza en Abril de 2016.

Para trabajar con el dòlar en una frecuencia mensual vamos a considerar la cotización del primer día hábil de cada mes como la cotización de dicho mes.

Deben poder mostrar los siguientes gráficos y contestar estas preguntas:

  1. Gráfico de la evolución del dólar (construir la frecuencia mensual del dólar con el tipo de cambio del primer día hábil del mes)
  2. Gráfico de la evolución del IPC General
  3. Gráfico de la evolución de los cuatro grupos del IPC
  4. ¿Cuál es la media, el desvío estándar, la mediana y el rango del dólar y del IPC General para cada uno de los años?
  5. Gráfico de la evolución del dólar y del IPC General para el período de tiempo que tenemos datos de ambas variables
  6. Gráfico de la evolución del dólar y de los 4 grupos de IPC para el período de tiempo que tenemos datos de ambas variables

Recomendamos que intenten ir resolviendo los problemas que surjan consultandonos a nosotros, los “machetes” de R y otras páginas pero dejamos una guía de pasos y ayudas

  1. Levantar ambos conjuntos de datos
  2. En el dataset del dólar renombramos la variable del tipo de cambio por algo más sencillo
  3. Creamos las variables fecha, año, mes y día
  4. Seleccionamos el primer día hábil del mes para obtener la primer cotización del mes (para el dolar)
  5. Graficamos la evolución del tipo de cambio
  6. Normalizar los datos del IPC. Pista: piensen si tienen que usar \(spread\) o \(gather\)
  7. Creamos las variables fecha, año y mes
  8. Graficamos la evolución del nivel general del IPC
  9. Graficamos la evolución de los 4 grupos
  10. Realizamos un join de ambos conjuntos de datos. Consideren qué tipo de join tienen que usar
  11. Obtenemos las estadisticas de resumen de la pregunta d)
  12. Graficamos la evoluciòn del dólar y del nivel general del IPC (tener en cuenta el rango de las variables)
  13. Graficamos la evoluciòn del dólar y de los grupos del IPC

EPH

El Objetivo de estos ejercicios es practicar el uso del \(tidyverse\) para la manipulación de los datos, y \(ggplot\) para graficar la información. En las consignas, se propone de manera general qué variables se quiere observar. Ustedes deberán levantar y procesar los datos de la Encuesta Permanente de Hogares, y gráficarlos como consideren que mejor se aprecia la relación entre las variables.

Una ayuda es utilizar el diseño de registro para codificar las variables

ejercicios

  • Graficar la distribución del ingreso por ocupación principal (p21) según categoría ocupacional (CAT_OCUP). (opcional: utilizar la librería ggridges)

  • Incorporar en el gráfico anterior la condición de precariedad laboral (PP07H).

  • Quedarse sólo con los asalariados (CAT_OCUP = 3), y graficar la relación entre ingreso por ocupación principal(p21), precariedad laboral (PP07H) y tamaño del establecimiento(PP04C99).

  • Quedarse con los Cuentapropistas y asalariados (CAT_OCUP = 2 y 3) y comparar, según la condición de precariedad laboral (PP07H) la distribución del ingreso según sexo (CH04)

  • Incorporar en el gráfico anterior el tamaño del establecimiento(PP04C99)

yapa: Si quisieramos modelar la probabilidad de un evento podemos usar una regresión logísitca (en ggplot stat_smooth(method="glm", method.args=list(family="binomial")).
Utilicen este modelo para hacer un gráfico que eche luz sobre el siguiente fenómeno:

  • ¿Cómo se distribuye la probabilidad de querer trabajar más horas (PP03G) según el total de horas trabajadas por semana (PP3E_TOT)? ¿Es diferente el modelo según sexo(CH04)?
LS0tCnRpdGxlOiAiQ2xhc2UgMi4gVGlkeXZlcnNlIgphdXRob3I6ICJEaWVnbyBLb3psb3dza2kgeSBKdWFuIEJhcnJpb2xhIgpkYXRlOiAiMjUgZGUgQWdvc3RvIGRlIDIwMTgiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazogCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgZGVwdGg6IDIKLS0tCgpgYGB7ciwgd2FybmluZz1GQUxTRX0Kcm0obGlzdD1scygpKQpgYGAKCiMgW1RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pICAgICAgICAgCgpFc3RlIHBhcXVldGUgYWdydXBhIHVuYSBzZXJpZSBkZSBwYXF1ZXRlcyBxdWUgdGllbmVuIHVuYSBtaXNtYSBsw7NnaWNhIGVuIHN1IGRpc2XDsW8geSBwb3IgZW5kZSBmdW5jaW9uYW4gZW4gYXJtb27DrWEuICAgICAKRW50cmUgZWxsb3MgdXNhcmVtb3MgcHJpbmNpcGFsbWVudGUgX19nZ3Bsb3RfXyBwYXJhIHJlYWxpemFyIGdyw6FmaWNvcywgeSBfX2RwbHlyX18geSBfX3RpZHlyX18gcGFyYSByZWFsaXphciB0cmFuc2Zvcm1hY2lvbmVzIHNvYnJlIG51ZXN0cm8gc2V0IGRlIGRhdG9zLgoKQSBjb250aW51YWNpw7NuIGNhcmdhbW9zIGxhIGxpYnJlcsOtYSBhIG51ZXN0cm8gYW1iaWVudGUuIFBhcmEgZWxsbyBkZWJlIGVzdGFyIHByZXZpYW1lbnRlIGluc3RhbGFkYSBlbiBudWVzdHJhIHBjLgpgYGB7cixldmFsPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkobHVicmlkYXRlKQpgYGAKUGFyYSBtb3N0cmFyIGVsIGZ1bmNpb25hbWllbnRvIGLDoXNpY28gZGUgdHlkeXZlcnNlIHJldG9tYXJlbW9zIGVsIGVqZW1wbG8gZGUgbGEgY2xhc2UgMSwgY29uIGxvIGN1YWwgdm9sdmVtb3MgYSBjcmVhciBlbCBzZXQgZGUgZGF0b3MgZGVsIFtJbmRpY2UgZGUgc2FsYXJpb3NdKGh0dHA6Ly93d3cuaW5kZWMuZ29iLmFyL2JhamFyQ3VhZHJvRXN0YWRpc3RpY28uYXNwP2lkYz00MDIwQjMzNDQwNjA5NDYyNjU0NTQyQkQwQkMzMjBGMTUyM0RBMERDNTJDMzk2MjAxREI0REQ1ODYxRkZFREM5QUQxNDM2NjgxQUM4NDE3OSkuCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KCklORElDRSAgPC0gYygxMDAsICAgMTAwLCAgIDEwMCwKICAgICAgICAgICAgIDEwMS44LCAxMDEuMiwgMTAwLjczLAogICAgICAgICAgICAgMTAyLjksIDEwMi40LCAxMDMuMikKCkZFQ0hBICA8LSAgYygiT2N0LTE2IiwgIk9jdC0xNiIsICJPY3QtMTYiLAogICAgICAgICAgICAgIk5vdi0xNiIsICJOb3YtMTYiLCAiTm92LTE2IiwKICAgICAgICAgICAgICJEZWMtMTYiLCAiRGVjLTE2IiwgIkRlYy0xNiIpCgoKR1JVUE8gIDwtICBjKCJQcml2YWRvX1JlZ2lzdHJhZG8iLCJQw7pibGljbyIsIlByaXZhZG9fTm9fUmVnaXN0cmFkbyIsCiAgICAgICAgICAgICAiUHJpdmFkb19SZWdpc3RyYWRvIiwiUMO6YmxpY28iLCJQcml2YWRvX05vX1JlZ2lzdHJhZG8iLAogICAgICAgICAgICAgIlByaXZhZG9fUmVnaXN0cmFkbyIsIlDDumJsaWNvIiwiUHJpdmFkb19Ob19SZWdpc3RyYWRvIikKCkRhdG9zIDwtIGRhdGEuZnJhbWUoSU5ESUNFLCBGRUNIQSwgR1JVUE8pCmBgYAoKCiMjIERwbHlyCgpFbCBjYXJhY3RlciBwcmluY2lwYWwgcGFyYSB1dGlsaXphciBlc3RlIHBhcXVldGUgZXMgYGBgJT4lYGBgICwgX3BpcGVfIChkZSB0dWJlcsOtYSkuCgpMb3MgYGBgJT4lYGBgIHRvbWFuIGVsIHNldCBkZSBkYXRvcyBhIHN1IGl6cXVpZXJkYSwgeSBsb3MgdHJhbnNmb3JtYW4gbWVkaWFudGUgbG9zIGNvbWFuZG9zIGEgc3UgZGVyZWNoYSwgZW4gbG9zIGN1YWxlcyBsb3MgZWxlbWVudG9zIGRlIGxhIGl6cXVpZXJkYSBlc3TDoW4gaW1wbMOtY2l0b3MuIEVuIG90cm9zIHTDqXJtaW5vcy4KCiRmKHgseSkkIGVzIGVxdWl2YWxlbnRlIGEgJHgkICU+JSAkZiguLHkpJCAKClZlYW1vcyBsYXMgcHJpbmNpcGFsZXMgZnVuY2lvbmVzIHF1ZSBwdWVkZW4gdXRpbGl6YXJzZSBjb24gbGEgbMOzZ2ljYSBkZSBlc3RlIHBhcXVldGU6CgojIyMgZ2xpbXBzZQoKUGVybWl0ZSB2ZXIgbGEgZXN0cnVjdHVyYSBkZSBsYSB0YWJsYS4gTm9zIG11ZXN0cmE6IAoKKiBuw7ptZXJvIGRlIGZpbGFzCiogbsO6bWVybyBkZSBjb2x1bW5hcwoqIG5vbWJyZSBkZSBsYXMgY29sdW1uYXMKKiB0aXBvIGRlIGRhdG8gZGUgY2FkYSBjb2x1bW5hCiogbGFzIHByaW1lcmFzIG9ic2VydmFjaW9uZXMgZGUgbGEgdGFibGEKCmBgYHtyfQpnbGltcHNlKERhdG9zKQpgYGAKCgojIyMgZmlsdGVyCgpQZXJtaXRlIGZpbHRyYXIgbGEgdGFibGEgYWNvcmRlIGFsIGN1bXBsaW1pZW50byBkZSBjb25kaWNpb25lcyBsw7NnaWNhcwogCmBgYHtyfQpEYXRvcyAlPiUgCiAgZmlsdGVyKElORElDRT4xMDEgLCBHUlVQTyA9PSAiUHJpdmFkb19SZWdpc3RyYWRvIikKYGBgCgpOw7N0ZXNlIHF1ZSBlbiBlc3RlIGNhc28gYWwgc2VwYXJhciBjb24gdW5hICBfXyxfXyBsYXMgY29uZGljaW9uZXMgc2UgZXhpZ2UgZWwgY3VtcGxpbWllbnRvIGRlIGFtYmFzLiBFbiBjYXNvIGRlIGRlc2VhciBxdWUgc2UgY3VtcGxhIHVuYSBzb2xhIGNvbmRpY2nDs24gZGViZSB1dGlsaXphcnNlIGVsIGNhcmFjdGVyIF9ffF9fCgpgYGB7cn0KRGF0b3MgJT4lIAogIGZpbHRlcihJTkRJQ0U+MTAxIHwgR1JVUE8gPT0gIlByaXZhZG9fUmVnaXN0cmFkbyIpCmBgYAoKIyMjIHJlbmFtZQpQZXJtaXRlIHJlbm9tYnJhciB1bmEgY29sdW1uYSBkZSBsYSB0YWJsYS4gRnVuY2lvbmEgZGUgbGEgc2lndWllbnRlIG1hbmVyYTogCiBgYGBEYXRhICU+JSByZW5hbWUoIG51ZXZvX25vbWJyZSA9IHZpZWpvX25vbWJyZSApYGBgIApgYGB7cn0KRGF0b3MgJT4lIAogIHJlbmFtZShQZXJpb2RvID0gRkVDSEEpCmBgYApOw7N0ZXNlIHF1ZSBhIGRpZmVyZW5jaWEgZGVsIGVqZW1wbG8gZGUgbGEgZnVuY2nDs24gX19maWx0ZXJfXyBkb25kZSB1dGlsaXrDoWJhbW9zIF9fPT1fXyBwYXJhIGNvbXByb2JhciB1bmEgY29uZGljacOzbiBsw7NnaWNhLCBlbiBlc3RlIGNhc28gc2UgdXRpbGl6YSBzw7NsbyB1biBfXz1fXyB5YSBxdWUgbG8gZXN0YW1vcyBoYWNpZW5kbyBlcyBfYXNpZ25hcl8gdW4gbm9tYnJlLgoKIyMjIG11dGF0ZQpQZXJtaXRlIGFncmVnYXIgdW5hIHZhcmlhYmxlIGEgbGEgdGFibGEgKGVzcGVjaWZpY2FuZG8gZWwgbm9tYnJlIHF1ZSB0b21hcsOhIGVzdGEpLCBxdWUgcHVlZGUgc2VyIGVsIHJlc3VsdGFkbyBkZSBvcGVyYWNpb25lcyBzb2JyZSBvdHJhcyB2YXJpYWJsZXMgZGUgbGEgbWlzbWEgdGFibGEuICAgICAgIAoKRW4gY2FzbyBkZSBlc3BlY2lmaWNhciBlbCBub21icmUgZGUgdW5hIGNvbHVtbmEgZXhpc3RlbnRlLCBlbCByZXN1bHRhZG8gZGUgbGEgb3BlcmFjacOzbiByZWFsaXphZGEgInNvYnJlc2NyaWJpcsOhIiBsYSBpbmZvcm1hY2nDs24gZGUgbGEgY29sdW1uYSBjb24gZGljaG8gbm9tYnJlCmBgYHtyfQpEYXRvcyA8LSBEYXRvcyAlPiUgCiAgbXV0YXRlKERvYmxlPUlORElDRSoyKQpEYXRvcwpgYGAKCiMjIyBjYXNlX3doZW4KUGVybWl0ZSBkZWZpbmlyIHVuYSB2YXJpYWJsZSwgbGEgY3VhbCB0b21hIHVuIHZhbG9yIHBhcnRpY3VsYXIgcGFyYSBjYWRhIGNvbmRpY2nDs24gZXN0YWJsZWNpZGEuIEVuIGNhc28gZGUgbm8gY3VtcGxpciBuaW5ndW5hIGRlIGxhcyBjb25kaWNpb25lcyBlc3RhYmxlY2lkYXMgbGEgdmFyaWFibGUgdG9tYXJhIHZhbG9yIF9fTkFfXwpMYSBzaW50YXhpcyBkZSBsYSBmdW5jacOzbiBlcyBjYXNlX3doZW4oIF9jb25kaWNpb24gbMOzZ2ljYTFfIF9ffl9fIF92YWxvciBhc2lnbmFkbzFfKS4KCmBgYHtyfQpEYXRvcyA8LSBEYXRvcyAlPiUgCiAgbXV0YXRlKENhc29fY3VhbmRvID0gY2FzZV93aGVuKEdSVVBPID09ICJQcml2YWRvX1JlZ2lzdHJhZG8iICAgfiBJTkRJQ0UqMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR1JVUE8gPT0gIlDDumJsaWNvIiAgICAgICAgICAgICAgfiBJTkRJQ0UqMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR1JVUE8gPT0gIlByaXZhZG9fTm9fUmVnaXN0cmFkbyJ+IElORElDRSo1KSkKRGF0b3MKYGBgCgojIyMgc2VsZWN0ClBlcm1pdGUgZXNwZWNpZmljYXIgbGEgc2VyaWUgZGUgY29sdW1uYXMgcXVlIHNlIGRlc2VhIGNvbnNlcnZhciBkZSB1biBEYXRhRnJhbWUuIFRhbWJpw6luIHB1ZWRlbiBlc3BlY2lmaWNhcnNlIGxhcyBjb2x1bW5hcyBxdWUgc2UgZGVzZWFuIGRlc2NhcnRhciAoYWdyZWfDoW5kb2xlcyB1biBfLV8pLiBNdXkgw7p0aWwgcGFyYSBhZ2lsaXphciBlbCB0cmFiYWpvIGVuIGJhc2VzIGRlIGRhdG9zIGRlIGdyYW4gdGFtYcOxby4KYGBge3J9CkRhdG9zMiA8LSBEYXRvcyAlPiUgCiAgc2VsZWN0KElORElDRSwgRkVDSEEsIEdSVVBPKQpEYXRvczIKCkRhdG9zIDwtIERhdG9zICU+JSAKICBzZWxlY3QoLWMoRG9ibGUsQ2Fzb19jdWFuZG8pKQpEYXRvcwpgYGAKCiMjIyBhcnJhbmdlClBlcm1pdGUgb3JkZW5hciBsYSB0YWJsYSBwb3IgbG9zIHZhbG9yZXMgZGUgZGV0ZXJtaW5hZGEvcyB2YXJpYWJsZS9zLiBFcyDDunRpbCBjdWFuZG8gbHVlZ28gZGViZW4gaGFjZXJzZSBvdHJhcyBvcGVyYWNpb25lcyBxdWUgcmVxdWllcmFuIGRlbCBvcmRlbmFtaWVudG8gZGUgbGEgdGFibGEKYGBge3J9CkRhdG9zIDwtIERhdG9zICU+JSAKICBhcnJhbmdlKEdSVVBPLCBJTkRJQ0UpCkRhdG9zCmBgYAoKIyMjIHN1bW1hcmlzZQpDcmVhIHVuYSBudWV2YSB0YWJsYSBxdWUgcmVzdW1hIGxhIGluZm9ybWFjacOzbiBvcmlnaW5hbC4gUGFyYSBlbGxvLCBkZWZpbmltb3MgbGFzIHZhcmlhYmxlcyBkZSByZXN1bWVuIHkgbGFzIGZvcm1hcyBkZSBhZ3JlZ2FjacOzbi4KYGBge3J9CkRhdG9zICU+JSAKICBzdW1tYXJpc2UoSW5kcHJvbSA9IG1lYW4oSU5ESUNFKSkKCmBgYAoKIyMjIGdyb3VwX2J5CkVzdGEgZnVuY2nDs24gcGVybWl0ZSByZWFsaXphciBvcGVyYWNpb25lcyBkZSBmb3JtYSBhZ3J1cGFkYS4gTG8gcXVlIGhhY2UgbGEgZnVuY2nDs24gZXMgInNlcGFyYXIiIGEgbGEgdGFibGEgc2Vnw7puIGxvcyB2YWxvcmVzIGRlIGxhIHZhcmlhYmxlIGluZGljYWRhIHkgcmVhbGl6YXIgbGFzIG9wZXJhY2lvbmVzIHF1ZSBzZSBlc3BlY2lmaWNhYmEgIGNvbnRpbnVhY2nDs24sIGRlIG1hbmVyYSBpbmRlcGVuZGllbnRlIHBhcmEgY2FkYSB1bmEgZGUgbGFzICJzdWJ0YWJsYXMiLiBFbiBudWVzdHJvIGVqZW1wbG8sIHNlcsOtYSDDunRpbCBwYXJhIGNhbGN1bGFyIGVsIHByb21lZGlvIGRlIGxvcyBpbmRpY2VzIHBvciBfRmVjaGFfIApgYGB7cn0KRGF0b3MgJT4lIAogIGdyb3VwX2J5KEZFQ0hBKSAlPiUKICBzdW1tYXJpc2UoSW5kcHJvbSA9IG1lYW4oSU5ESUNFKSkKYGBgCgojIyBKb2lucwoKT3RyYSBpbXBsZW1lbnRhY2nDs24gbXV5IGltcG9ydGFudGUgZGVsIHBhcXVldGUgZHBseXIgc29uIGxhcyBmdW5jaW9uZXMgcGFyYSB1bmlyIHRhYmxhcyAoam9pbnMpCgoKIVtmdWVudGU6IGh0dHA6Ly9yc3R1ZGlvLXB1YnMtc3RhdGljLnMzLmFtYXpvbmF3cy5jb20vMjI3MTcxXzYxOGViZGNlMGI5ZDQ0ZjNhZjY1NzAwZTgzMzU5M2RiLmh0bWxdKGpvaW5zLnBuZykgICAgICAgICAKCiMjI2xlZnRfam9pbiAgICAKClZlYW1vcyB1biBlamVtcGxvIGRlIGxhIGZ1bmNpw7NuIF9fbGVmdF9qb2luX18gKHVuYSBkZSBsYXMgbcOhcyB1dGlsaXphZGFzIGVuIGxhIHByw6FjdGljYSkuICAgICAgIApQYXJhIGVsbG8gY3JlYXJlbW9zIHByZXZpYW1lbnRlIHVuIERhdGFmcmFtZSBxdWUgY29udGVuZ2EgdW4gUG9uZGVyYWRvciBwYXJhIGNhZGEgdW5vIGRlIGxvcyBHcnVwb3MgZGVsIERhdGFmcmFtZSBfRGF0b3NfLiBBcHJvdmVjaGFyZW1vcyBlbCBlamVtcGxvIHBhcmEgaW50cm9kdWNpciBsYSBmdW5jacOzbiBfX3dlaWd0aGVkLm1lYW5fXywgeSBhc8OtIGNhbGN1bGFyIHVuIEluZGljZSBQb25kZXJhZG8uCgpgYGB7cn0KUG9uZGVyYWRvcmVzIDwtIGRhdGEuZnJhbWUoR1JVUE8gPSBjKCJQcml2YWRvX1JlZ2lzdHJhZG8iLCJQw7pibGljbyIsIlByaXZhZG9fTm9fUmVnaXN0cmFkbyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUE9OREVSQURPUiA9IGMoNTAuMTYsMjkuOTEsMTkuOTMpKQoKRGF0b3Nfam9pbiA8LSBEYXRvcyAlPiUgCiAgbGVmdF9qb2luKC4sUG9uZGVyYWRvcmVzLCBieSA9ICJHUlVQTyIpCkRhdG9zX2pvaW4KCkRhdG9zX0luZGljZV9HcmFsIDwtIERhdG9zX2pvaW4gJT4lIAogIGdyb3VwX2J5KEZFQ0hBKSAlPiUgCiAgc3VtbWFyaXNlKEluZGljZV9HcmFsID0gd2VpZ2h0ZWQubWVhbihJTkRJQ0UsdyA9IFBPTkRFUkFET1IpKQoKRGF0b3NfSW5kaWNlX0dyYWwKYGBgCgojIyBUaWR5cgoKRWwgcGFxdWV0ZSB0aWR5ciBlc3RhIHBlbnNhZG8gcGFyYSBmYWNpbGl0YXIgZWwgZW1wcm9saWphbWllbnRvIGRlIGxvcyBkYXRvcy4KCl9fR2F0aGVyX18gZXMgdW5hIGZ1bmNpw7NuIHF1ZSBub3MgcGVybWl0ZSBwYXNhciBsb3MgZGF0b3MgZGUgZm9ybWEgaG9yaXpvbnRhbCBhIHVuYSBmb3JtYSB2ZXJ0aWNhbC4gCgpfX3NwcmVhZF9fIGVzIHVuYSBmdW5jacOzbiBxdWUgbm9zIHBlcm1pdGUgcGFzYXIgbG9zIGRhdG9zIGRlIGZvcm1hIHZlcnRpY2FsIGEgdW5hIGZvcm1hIGhvcml6b250YWwuCgohW2Z1ZW50ZTogaHR0cDovL3d3dy5naXMtYmxvZy5jb20vZGF0YS1tYW5hZ2VtZW50LXdpdGgtci10aWR5ci1wYXJ0LTEvXShzcHJlYWRWU2dhdGhlci5wbmcpCgoKYGBge3J9CiNVdGlsemFtb3MgdW4gY29uanVudG8gZGUgZGF0b3MgcXVlIHZpZW5lIGNvbiBsYSBsaWJyZXLDrWEgZGF0YXNldHMKbGlicmFyeShkYXRhc2V0cykKCmRhdGEoaXJpcykKaXJpcyA8LSBpcmlzICU+JSAKICBtdXRhdGUoaWQgPSAxOm5yb3coLikpICU+JSAgI2xlIGFncmVnbyB1biBJRAogIHNlbGVjdChpZCwgZXZlcnl0aGluZygpKSAjIGxvIGFjb21vZG8gcGFyYSBxdWUgZWwgaWQgZXN0ZSBwcmltZXJvLiAKCmlyaXMKYGBgCgoKICAKIyMjIEdhdGhlciB5IFNwcmVhZAoKYGBge3J9CmlyaXNfdmVydGljYWwgPC0gaXJpcyAlPiUgZ2F0aGVyKC4sICMgZWwgLiBsbGFtYSBhIGxvIHF1ZSBlc3RhIGF0cmFzIGRlbCAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleSAgID0gVmFyaWFibGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IFZhbG9yZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDI6NSkgI2xlIGluZGljbyBxdWUgY29sdW1uYXMganVudGFyCmlyaXNfdmVydGljYWwKYGBgCgpQb2RlbW9zIGRlc2hhY2VyIGVsIF9fZ2F0aGVyX18gY29uIHVuIF9fU3ByZWFkX18KYGBge3J9CmlyaXNfaG9yaXpvbnRhbCA8LSBpcmlzX3ZlcnRpY2FsICU+JQogIHNwcmVhZCguICwKICAgICAgICAga2V5ICAgPSBWYXJpYWJsZXMsICNsYSBsbGF2ZSBlcyBsYSB2YXJpYWJsZSBxdWUgdmEgYSBkYXIgbG9zIG5vbWJyZXMgZGUgY29sdW1uYQogICAgICAgICB2YWx1ZSA9IFZhbG9yZXMpICNsb3MgdmFsb3JlcyBjb24gcXVlIHNlIGxsZW5hbiBsYXMgY2VsZGFzCmlyaXNfaG9yaXpvbnRhbApgYGAKCiMjIEx1YnJpZGF0ZQoKRWwgcGFxdWV0ZSBsdWJyaWRhdGUgZXN0w6EgcGVuc2FkbyBwYXJhIHRyYWJhamFyIGNvbiBsb3MgZGF0b3MgdGlwbyBmZWNoYShkYXRlKSBvIGZlY2hhLWhvcmEoZGF0ZXRpbWUpIHBhcmEgY2FtYmlhcmxlcyBlbCBmb3JtYXRvLCByZWFsaXphciBvcGVyYWNpb25lcyB5IGV4dHJhZXIgaW5mb3JtYWNpw7NuCgojIyMgQ2FtYmlvIGRlIGZvcm1hdG8KCkV4aXN0ZSB1bmEgZ3JhbiBjYW50aWRhZCBkZSBmdW5jaW9uZXMgcGFyYSByZWFsaXphciBlc3RvLiBMYSBpZGVhIGdlbmVyYWwgZXMgcG9kZXIgbGxldmFyIGxvcyBvYmpldG9zIGRhdGV0aW1lIGEgdW4gZm9ybWF0byBjb23Dum4gY29tcHVlc3RvIGRlIGxvcyBlbGVtZW50b3M6IGHDsW8sIG1lcywgZMOtYSwgaG9yYSwgbWludXRvIHkgc2VndW5kbyAodGFtYmnDqW4gc2UgcHVlZGUgc2V0ZWFyIGVsIGh1c28gaG9yYXJpbykKCmBgYHtyfQpmZWNoYSAgPC0gIjA0LzEyLzkyIDE3OjM1OjE2IgpmZWNoYQpgYGAKCkNvbiBsYSBmdW5jacOzbiBkbXlfaG1zIHBvZGVtb3MgY29udmVydGlyIGVzdGUgc3RyaW5nIGEgdW5hIGZlY2hhOiBlc3RhbW9zIGluZGljYW5kbyBxdWUgZWwgZm9ybWF0byBkZSBsYSBmZWNoYSBlcyBkw61hKGQpLCBtZXMobSksIGHDsW8oeSksIGhvcmEoaCksIG1pbnV0byhtKSB5IHNlZ3VuZG8ocykKYGBge3J9CmZlY2hhICA8LSBkbXlfaG1zKGZlY2hhKQpmZWNoYQpgYGAKTXVjaGFzIGZ1bmNpb25lcyBkZSBsdWJyaWRhdGUgb3BlcmFuIGNvbiBlc3RhIG1pc21hIGzDs2dpY2EKCk90cmEgZnVuY2nDs24gcGFyYSByZWFsaXphciB1biBjYW1iaW8gZGUgZm9ybWF0byBlcyAqcGFyc2VfZGF0ZV90aW1lKi4gUGVybWl0ZSBjb25zdHJ1aXIgb2JqZXRvcyBkYXRldGltZSBhIHBhcnRpciBkZSBkYXRvcyBtw6FzIGNvbXBsZWpvcywgY29tbyBwb3IgZWplbXBsbyBjdWFuZG8gYXBhcmVjZSBlbCBub21icmUgZGVsIG1lcyB5IGVsIGHDsW8uCgpFbiBlbCBwYXLDoW1ldHJvICp4KiBwYXNhbW9zIGVsIGRhdG8gZGUgbGEgZmVjaGEgeSBlbiBlbCBwYXLDoW1ldHJvICpvcmRlcnMqIGVzcGVjaWZpY2Ftb3MgZWwgb3JkZW4gZW4gZWwgY3VhbCBzZSBlbmN1ZW50cmEgbGEgaW5mb3JtYWNpw7NuIGRlIGxhIGZlY2hhCgpgYGB7cn0KZmVjaGEyICA8LSAiRGVjLTkyIgpmZWNoYTIgPC0gcGFyc2VfZGF0ZV90aW1lKGZlY2hhMiwgb3JkZXJzID0gJ215JykKZmVjaGEyCmBgYAoKCiMjIyBFeHRyYWNjacOzbiBkZSBpbmZvcm1hY2nDs24KCkV4aXN0ZW4gbXVjaGFzIGZ1bmNpb25lcyBtdXkgc2VuY2lsbGFzIHBhcmEgZXh0cmFlciBpbmZvcm1hY2nDs24gZGUgdW4gb2JqZXRvIGRhdGV0aW1lLiBBbGd1bmFzIHNvbgoKYGBge3J9CnllYXIoZmVjaGEpICMgT2J0ZW5lciBlbCBhw7FvCm1vbnRoKGZlY2hhKSAjT2J0ZW5lciBlbCBtZXMKZGF5KGZlY2hhKSAjIE9idGVuZXIgZWwgZMOtYQp3ZGF5KGZlY2hhLCBsYWJlbCA9IFRSVUUpICNPYnRlbmVyIGVsIG5vbWJyZSBkZWwgZMOtYQpob3VyKGZlY2hhKSAjT2J0ZW5lciBsYSBob3JhCmBgYAoKIyMjIE9wZXJhY2lvbmVzCgpQb2RlbW9zIHN1bWFyIG8gcmVzdGFybGUgY3VhbHF1aWVyIHBlcsOtb2RvIGRlIHRpZW1wbyBhIHVuIG9iamV0byBkYXRldGltZQoKYGBge3J9CiMgU3VtbyBkb3MgZMOtYXMgCmZlY2hhICsgZGF5cygyKQojIFJlc3RvIDEgc2VtYW5hIHkgZG9zIGhvcmFzCmZlY2hhIC0gKHdlZWtzKDEpICsgaG91cnMoMikpCmBgYAoKCiMgR3LDoWZpY29zCgojIyMgR3LDoWZpY29zIELDoXNpY29zIGVuIFIKClJiYXNlICB0aWVuZSBhbGd1bm9zIGNvbWFuZG9zIGdlbsOpcmljb3MgcGFyYSByZWFsaXphciBncsOhZmljb3MsIHF1ZSBzZSBhZGFwdGFuIGFsIHRpcG8gZGUgaW5mb3JtYWNpw7NuIHF1ZSBzZSBsZSBwaWRlIGdyYWZpY2FyLCBwb3IgZWplbXBsbzoKCi0gcGxvdCgpCi0gaGlzdCgpCgoKCmBgYHtyfQppcmlzCgpwbG90KGlyaXMpCnBsb3QoaXJpcyRTZXBhbC5MZW5ndGgsdHlwZSA9ICJwIikKcGxvdChpcmlzJFNlcGFsLkxlbmd0aCx0eXBlID0gImwiKQpwbG90KGlyaXMkU2VwYWwuTGVuZ3RoLHR5cGUgPSAiYiIpCmhpc3QoaXJpcyRTZXBhbC5MZW5ndGgsIGNvbCA9ICJsaWdodHNhbG1vbjEiLCBtYWluID0gIkhpc3RvZ3JhbWEiKQoKYGBgCgoKUGFyYSBndWFyZGFyIGxvcyBncsOhZmljb3MKCmBgYHtyfQpwbmcoIkdyYWZpY28xLnBuZyIpCnBsb3QoaXJpcyRTZXBhbC5MZW5ndGgsdHlwZSA9ICJiIikKZGV2Lm9mZigpCgpgYGAKCgpMYSBmdW5jacOzbiBgYGBwbmcoKWBgYCBfYWJyZSBlbCBkaXNwb3NpdGl2byBkZSBpbWFnZW5fLCBsdWVnbyBwb2RlbW9zIGhhY2VyIGxvcyBncsOhZmljb3MsIHkgYSBjb250aW51YWNpw7NuLCBjb24gYGBgZGV2Lm9mZigpYGBgIHNlIF9jaWVycmEgZWwgZGlzcG9zaXRpdm9fIHkgc2UgZ3JhYmFuIGxvcyBncsOhZmljb3MuIAoKTG9zIGdyw6FmaWNvcyBkZWwgUiBiYXNlIHNvbiDDunRpbGVzIHBhcmEgZXNjcmliaXIgZGUgZm9ybWEgcsOhcGlkYSB5IG9idGVuZXIgYWxndW5hIGluZm9ybWFjacOzbiBtaWVudHJhcyB0cmFiYWphbW9zLiBNdWNob3MgcGFxdWV0ZXMgZXN0YWTDrXN0aWNvcyBwZXJtaXRlbiBtb3N0cmFyIGxvcyByZXN1bHRhZG9zIGRlIGZvcm1hIGdyw6FmaWNhIGNvbiBlbCBjb21hbmRvIHBsb3QgKHBvciBlamVtcGxvLCBsYXMgcmVncmVzaW9uZXMgbGluZWFsZXMgYGBgbG0oKWBgYCkuICAgICAgIAogClNpbiBlbWJhcmdvLCBleGlzdGVuIGxpYnJlcsOtYXMgbXVjaG8gbWVqb3JlcyBwYXJhIGNyZWFyIGdyw6FmaWNvcyBkZSBuaXZlbCBkZSBwdWJsaWNhY2nDs24uIExhIG3DoXMgaW1wb3J0YW50ZSBlcyBfX2dncGxvdDJfXywgcXVlIGEgc3UgdmV6IHRpZW5lIGV4dGVuc2lvbmVzIG1lZGlhbnRlIG90cmFzIGxpYnJlcsOtYXMuCgoKI1tHZ3Bsb3QyXShodHRwOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS8pCgoKZ2dwbG90IHRpZW5lIHN1IHNpbnRheGlzIHByb3BpYS4gTGEgaWRlYSBjZW50cmFsIGVzIHBlbnNhciBsb3MgZ3LDoWZpY29zIGNvbW8gdW5hIHN1Y2VzacOzbiBkZSBjYXBhcywgcXVlIHNlIGNvbnN0cnV5ZW4gdW5hIGEgbGEgdmV6LiAgICAKCi0gRWwgb3BlcmFkb3IgX19gYGArYGBgX18gbm9zIHBlcm1pdGUgaW5jb3Jwb3JhciBudWV2YXMgY2FwYXMgYWwgZ3LDoWZpY28uCgotIEVsIGNvbWFuZG8gYGBgZ2dwbG90KClgYGAgbm9zIHBlcm1pdGUgZGVmaW5pciBsb3MgX19kYXRvc19fIHkgbGFzIF9fdmFyaWFibGVzX18gKHgseSxjb2xvcixmb3JtYSxldGMpLiAKCi0gTGFzIHN1Y2VzaXZhcyBjYXBhcyBub3MgcGVybWl0ZW4gZGVmaW5pcjoKICAgIC0gVW5vIG8gbcOhcyB0aXBvcyBkZSBncsOhZmljb3MgKGRlIGNvbHVtbmFzLCBgYGBnZW9tX2NvbCgpYGBgLCBkZSBsw61uZWEsIGBgYGdlb21fbGluZSgpYGBgLCBkZSBwdW50b3MsYGBgZ2VvbV9wb2ludCgpYGBgLCBib3hwbG90LCBgYGBnZW9tX2JveHBsb3QoKWBgYCkKICAgIC0gVMOtdHVsb3MgYGBgbGFicygpYGBgCiAgICAtIEVzdGlsbyBkZWwgZ3LDoWZpY28gYGBgdGhlbWUoKWBgYAogICAgLSBFc2NhbGFzIGRlIGxvcyBlamVzIGBgYHNjYWxlX3lfY29udGludW91c2BgYCxgYGBzY2FsZV94X2Rpc2NyZXRlYGBgIAogICAgLSBEaXZpc2nDs24gZW4gc3ViY29uanVudG9zIGBgYGZhY2V0X3dyYXAoKWBgYCxgYGBmYWNldF9ncmlkKClgYGAKCmdncGxvdCB0aWVuZSBfX211Y2hvc19fIGNvbWFuZG9zLCB5IG5vIHRpZW5lIHNlbnRpZG8gc2FiZXJsb3MgZGUgbWVtb3JpYSwgZXMgc2llbXByZSDDunRpbCByZXV0aWxpemFyIGdyw6FmaWNvcyB2aWVqb3MgeSB0ZW5lciBhIG1hbm8gZWwgW21hY2hldGVdKGh0dHBzOi8vd3d3LnJzdHVkaW8uY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDE2LzExL2dncGxvdDItY2hlYXRzaGVldC0yLjEucGRmKS4KCgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3RoZW1lcykgICMgZXN0aWxvcyBkZSBncsOhZmljb3MKbGlicmFyeShnZ3JlcGVsKSAgICMgZXRpcXVldGFzIGRlIHRleHRvIG3DoXMgcHJvbGlqYXMgcXVlIGxhcyBkZSBnZ3Bsb3QKbGlicmFyeShzY2FsZXMpICAgICMgdGllbmUgbGEgZnVuY2nDs24gJ3BlcmNlbnQoKScKCgpnZ3Bsb3QoZGF0YSA9IGlyaXMsIGFlcyh4ID0gU2VwYWwuTGVuZ3RoLCBmaWxsID0gU3BlY2llcykpKwogIGdlb21faGlzdG9ncmFtKGFscGhhPTAuNzUsIGJpbndpZHRoID0gLjUpKwogIGZhY2V0X3dyYXAoflNwZWNpZXMpKwogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtYSBwb3IgZXNwZWNpZSIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykKYGBgCgoKTG8gw7p0aWwgZGUgaGFjZXIgZ3LDoWZpY29zIGVuIFIsIGVuIGx1Z2FyIGRlIHBvciBlamVtcGxvIGV4Y2VsLCBlcyBxdWUgcG9kZW1vcyBoYWNlciB1c28gZGUgbcOhcyBkaW1lbnNpb25lcywgcG9yIGVqZW1wbG86CgotIEdyw6FmaWNvcyBxdWUgbmVjZXNpdGFuIGxhIGluZm9ybWFjacOzbiBhIG5pdmVsIGRlIG1pY3JvZGF0b3MuIF9fcHVudG9zX18sICBfX2JveHBsb3RzX18sIF9fS2VybmVsc19fLCBldGMuCi0gQWJyaXIgZWwgbWlzbW8gZ3LDoWZpY28gc2Vnw7puIGFsZ3VuYSB2YXJpYWJsZSBkaXNjcmV0YTogYGBgZmFjZXRfd3JhcCgpYGBgCi0gUGFyYW1ldHJpemFyIG90cmFzIHZhcmlhYmxlcywgcGFyYSBhdW1lbnRhciBsYSBkaW1lbnNpb25hbGlkYWQgZGVsIGdyw6FmaWNvcy4KICAgIC0gW19fY29sb3JfX10oaHR0cDovL3d3dy5zdGF0LmNvbHVtYmlhLmVkdS9+dHpoZW5nL2ZpbGVzL1Jjb2xvci5wZGYpIGBgYGNvbG9yID0gYGBgCiAgICAtIF9fcmVsbGVub19fYGBgZmlsbCA9IGBgYAogICAgLSBfX2Zvcm1hX18gYGBgc2hhcGUgPSBgYGAKICAgIC0gX190YW1hw7FvX18gYGBgc2l6ZSA9IGBgYAogICAgLSBfX3RyYW5zcGFyZW5jaWFfXyBgYGBhbHBoYSA9IGBgYAoKRXN0byBwZXJtaXRlIHRlbmVyLCBlbiBlbCBwbGFubywgZ3LDoWZpY29zIGRlIG11Y2hhcyBkaW1lbnNpb25lcyBkZSBhbsOhbGlzaXMKCkN1YW5kbyBxdWVyZW1vcyB1dGlsaXphciBlc3RvcyBwYXLDoW1ldHJvcyBwYXJhIHJlcHJlc2VudGFyIHVuYSB2YXJpYWJsZSwgbG9zIGRlZmluaW1vcyBfX2RlbnRybyBkZWwgYWVzKClfXywgYGBgYWVzKC4uLiBjb2xvciA9IGluZ3Jlc29zKWBgYCwgY3VhbmRvIHF1ZXJlbW9zIHNpbXBsZW1lbnRlIG1lam9yYXIgZWwgZGlzZcOxbywgc2UgYXNpZ25hbiBwb3IgZnVlcmEsIG8gZGVudHJvIGRlIGNhZGEgdGlwbyBkZSBncsOhZmljb3MsIGBgYGdlb21fY29sKGNvbG9yID0gJ2dyZWVuJylgYGAuCgoKX19sZXZhbnRvIHVuYSBiYXNlIGRlIG1pY3JvZGF0b3MgZGUgRVBIIHBhcmEgZ3JhZmljYXJfXwoKYGBge3J9CgpJbmRpdmlkdWFsX3QxMTcgPC0gcmVhZC50YWJsZShwYXN0ZTAoIi4uL0Z1ZW50ZXMvdXN1X2luZGl2aWR1YWxfdDExNy50eHQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwPSI7IiwgZGVjPSIsIiwgaGVhZGVyID0gVFJVRSwgZmlsbCA9IFRSVUUpCmBgYAoKCiMjIyBCb3hwbG90cwoKSGFjZW1vcyB1biBwcm9jZXNhbWllbnRvIHNpbXBsZTogU2FjYW1vcyBsb3MgaW5ncmVzb3MgaWd1YWxlcyBhIGNlcm8geSBsYXMgbm8gcmVzcHVlc3RhcyBkZSBuaXZlbCBlZHVjYXRpdm8uICAgIApMYXMgdmFyaWFibGVzIHNleG8oIENIMDQgKSB5IE5pdmVsIGVkdWNhdGl2byBlc3TDoW4gY29kaWZpY2FkYXMgY29tbyBuw7ptZXJvcywgeSBlbCBSIGxhcyBlbnRpZW5kZSBjb21vIG51bcOpcmljYXMuCgoKCkVzIGltcG9ydGFudGUgcXVlIGxhcyB2YXJpYWJsZXMgc2VhbiBkZWwgdGlwbyBxdWUgY29uY2VwdHVhbG1lbnRlIGxlcyBjb3JyZXNwb25kZSAoZWwgbml2ZWwgZWR1Y2F0aXZvIGVzIHVuYSB2YXJpYWJsZSBjYXRlZ8OzcmljYSwgbm8gY29udGludWEpLCBwYXJhIHF1ZSBlbCBnZ3Bsb3QgcHVlZGEgZ3JhZmljYXJsbyBjb3JyZWN0YW1lbnRlLiAKCmBgYHtyfQoKZ2dkYXRhIDwtIEluZGl2aWR1YWxfdDExNyAlPiUgCiAgZmlsdGVyKFAyMT4wLCAhaXMubmEoTklWRUxfRUQpKSAlPiUgCiAgbXV0YXRlKE5JVkVMX0VEID0gYXMuZmFjdG9yKE5JVkVMX0VEKSwKICAgICAgICAgQ0gwNCAgICAgPSBhcy5mYWN0b3IoQ0gwNCkpCmBgYAoKCgoKc2kgcXVlcmVtb3MgaGFjZXIgdW4gYm94cGxvdCBkZWwgaW5ncmVzbyBwYXJhIGNhZGEgbml2ZWwgZWR1Y2F0aXZvLCBhc2lnbmFtb3MgZXN0YSB2YXJpYWJsZSBhIF94LCBncm91cCB5IGZpbGxfCmBgYHtyfQoKZ2dwbG90KGdnZGF0YSwgYWVzKHggPSBOSVZFTF9FRCwgeSA9IFAyMSwgZ3JvdXAgPSBOSVZFTF9FRCwgZmlsbCA9IE5JVkVMX0VEICkpICsKICBnZW9tX2JveHBsb3QoKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA0MDAwMCkpCmBgYAoKU2kgcXVlcmVtb3MgYWdyZWdhciBsYSBkaW1lbnNpw7NuIF9zZXhvXywgcG9kZW1vcyBoYWNlciB1biBgYGBmYWNldF93cmFwKClgYGAKCmBgYHtyfQoKZ2dwbG90KGdnZGF0YSwgYWVzKHg9IE5JVkVMX0VELCB5ID0gUDIxLCBncm91cCA9IE5JVkVMX0VELCBmaWxsID0gTklWRUxfRUQgKSkgKwogIGdlb21fYm94cGxvdCgpKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDQwMDAwKSkrCiAgZmFjZXRfd3JhcCh+IENIMDQsIGxhYmVsbGVyID0gImxhYmVsX2JvdGgiKQpgYGAKCkVuIGVzdGUgZ3LDoWZpY28sIGVsIGZvY28gZGUgYXRlbmNpw7NuIHNpZ3VlIHB1ZXN0byBlbiBsYXMgZGlmZXJlbmNpYXMgZGUgbml2ZWwgZWR1Y2F0aXZvLCBwZXJvIF9uZXV0cmFsaXphbW9zXyBlbCBlZmVjdG8gZGUgbGEgdmFyaWFibGUgc2V4by4gICAgIAoKU2kgbG8gcXVlIHF1ZXJlbW9zIGhhY2VyIGVzIHBvbmVyIGVsIGZvY28gZGUgYXRlbmNpw7NuIGVuIGxhcyBkaWZlcmVuY2lhcyBwb3Igc2V4bywgX25ldXRyYWxpemFtb3NfIGVsIGVmZWN0byBkZWwgbml2ZWwgZWR1Y2F0aXZvLCBmYWNldGlhbmRvIHBvciBuaXZlbCBlZHVjYXRpdm8uCgoKYGBge3J9CmdncGxvdChnZ2RhdGEsIGFlcyh4PSBDSDA0LCB5ID0gUDIxLCBncm91cCA9IENIMDQsIGZpbGwgPSBDSDA0ICkpICsKICBnZW9tX2JveHBsb3QoKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA0MDAwMCkpKwogIGZhY2V0X3dyYXAofiBOSVZFTF9FRCwgbGFiZWxsZXIgPSAibGFiZWxfYm90aCIpCgpgYGAKCgojIyMgS2VybmVscwoKUG9kZW1vcyBoYWNlciB1bmEgbnVldmEgdmVyc2nDs24gZGVsIGdyw6FmaWNvIDIuIFV0aWxpemFuZG8gdW4gcHJvY2VzYW1pZW50byBzaW1pbGFyIGFsIHF1ZSBoaWNpbW9zIGFudGVzLgoKYGBge3Igd2FybmluZz1GQUxTRX0KCmRhdGFncmFmIDwtSW5kaXZpZHVhbF90MTE3ICU+JSAKICBzZWxlY3QoUkVHSU9OLFA0N1QsVF9WSSwgVE9UX1AxMiwgUDIxICwgUE9ORElJLCBDSDA0KSAlPiUgCiAgZmlsdGVyKCFpcy5uYShQNDdUKSwgUDQ3VCA+IDAgKSAlPiUgCiAgbXV0YXRlKFJFR0lPTiAgICAgICAgICAgICA9IGNhc2Vfd2hlbihSRUdJT04gPT0gMSAgICB+ICdHQkEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVHSU9OID09IDQwICAgfiAnTk9BJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFR0lPTiA9PSA0MSAgIH4gJ05FQScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRUdJT04gPT0gNDIgICB+ICdDdXlvJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFR0lPTiA9PSA0MyAgIH4gJ1BlYW1wZWFuYScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRUdJT04gPT0gNDQgICB+ICdQYXRhZ29uaWEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRkFMU0UgICAgICAgICAgfiAnb3RybycpLAogICAgICAgICBpbmdyZXNvX2xhYm9yYWwgICAgPSBhcy5udW1lcmljKFRPVF9QMTIgKyBQMjEpLAogICAgICAgICBpbmdyZXNvX25vX2xhYm9yYWwgPSBhcy5udW1lcmljKFRfVkkpLAogICAgICAgICBDSDA0ICAgICAgICAgICAgICAgPSBjYXNlX3doZW4oQ0gwNCA9PSAxIH4gIlZhcm9uIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENIMDQgPT0gMiB+ICJNdWplciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGQUxTRSAgICAgfiAiT3RybyIpICkgJT4lIAogIGdhdGhlciguLCBrZXkgPSBUaXBvX2luZ3Jlc28sIEluZ3Jlc28sIGMoKG5jb2woLiktMSk6bmNvbCguKSkpCmRhdGFncmFmICAKYGBgCgpDb24gbG9zIEtlcm5lbHMsIG5vIG5lY2VzaXRhbW9zIGRpdmlkaXIgYSBsYSBwb2JsYWNpw7NuIGVuIGRlY2lsZXMsIHBvcnF1ZSBwb2RlbW9zIHRlbmVyIHVuYSBtaXJhZGEgY29tcGxldGEgZGUgbGEgZm9ybWEgZGUgbGEgZGlzdHJpYnVjacOzbi4gICAgCgpQYXJhIGVzdGUgZ3LDoWZpY28sIHF1aWVybyBlbGltaW5hciBsb3MgaW5ncmVzb3MgPSAwCgpgYGB7cn0KZGF0YWdyYWYyIDwtIGRhdGFncmFmICU+JSBmaWx0ZXIoIEluZ3Jlc28gIT0wKQogIAogIApnZ3Bsb3QoZGF0YWdyYWYyLCBhZXMoCiAgeCA9IEluZ3Jlc28sCiAgd2VpZ2h0cyA9IFBPTkRJSSwKICBncm91cCA9IFRpcG9faW5ncmVzbywKICBmaWxsID0gVGlwb19pbmdyZXNvKSkgKwogIGdlb21fZGVuc2l0eShhbHBoYT0wLjcsYWRqdXN0ID0yKSsKICBsYWJzKHg9IkRpc3RyaWJ1Y2nDs24gZGVsIGluZ3Jlc28iLCB5PSIiLAogICAgICAgdGl0bGU9IiBUb3RhbCBzZWfDum4gdGlwbyBkZSBpbmdyZXNvIHkgZ8OpbmVybyIsIAogICAgICAgY2FwdGlvbiA9ICJGdWVudGU6IEVuY3Vlc3RhIFBlcm1hbmVudGUgZGUgSG9nYXJlcyIpKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsNTAwMDApKSsKICB0aGVtZV90dWZ0ZSgpKwogIHNjYWxlX2ZpbGxfZ2RvY3MoKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBwbG90LnRpdGxlICAgICAgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpKwogIGZhY2V0X3dyYXAofiBDSDA0LCBzY2FsZXMgPSAiZnJlZSIpCgpnZ3NhdmUoZmlsZW5hbWUgPSBwYXN0ZTAoIi4uL1Jlc3VsdGFkb3MvIiwgIktlcm5lbF8xLnBuZyIpLHNjYWxlID0gMikKCmBgYAoKRW4gZXN0ZSB0aXBvIGRlIGdyw6FmaWNvcywgaW1wb3J0YSBtdWNobyBxdcOpIHZhcmlhYmxlIHNlIHV0aWxpemEgcGFyYSBfZmFjZXRlYXJfIHkgcXXDqSB2YXJpYWJsZSBwYXJhIGFncnVwYXIsIHlhIHF1ZSBsYSBjb25zdHJ1Y2Npw7NuIGRlIGxhIGRpc3RyaWJ1Y2nDs24gZXMgZGlmZXJlbnRlLiAKCmBgYHtyfQpnZ3Bsb3QoZGF0YWdyYWYyLCBhZXMoCiAgeCA9IEluZ3Jlc28sCiAgd2VpZ2h0cyA9IFBPTkRJSSwKICBncm91cCA9IENIMDQsCiAgZmlsbCA9IENIMDQpKSArCiAgZ2VvbV9kZW5zaXR5KGFscGhhPTAuNyxhZGp1c3QgPTIpKwogIGxhYnMoeD0iRGlzdHJpYnVjacOzbiBkZWwgaW5ncmVzbyIsIHk9IiIsCiAgICAgICB0aXRsZT0iIFRvdGFsIHNlZ8O6biB0aXBvIGRlIGluZ3Jlc28geSBnw6luZXJvIiwgCiAgICAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRW5jdWVzdGEgUGVybWFuZW50ZSBkZSBIb2dhcmVzIikrCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCw1MDAwMCkpKwogIHRoZW1lX3R1ZnRlKCkrCiAgc2NhbGVfZmlsbF9nZG9jcygpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgIHBsb3QudGl0bGUgICAgICA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkrCiAgZmFjZXRfd3JhcCh+VGlwb19pbmdyZXNvLCBzY2FsZXMgPSAiZnJlZSIpCgpnZ3NhdmUoZmlsZW5hbWUgPSBwYXN0ZTAoIi4uL1Jlc3VsdGFkb3MvIiwgIktlcm5lbF8xLnBuZyIpLHNjYWxlID0gMikKCmBgYAoKCkVsIGVqZSB5IG5vIHRpZW5lIGRlbWFzaWFkYSBpbnRlcnByZXRhYmlsaWRhZCBlbiBsb3MgS2VybmVsLCBwb3JxdWUgaGFjZSBhIGxhIGZvcm1hIGVuIHF1ZSBzZSBjb25zdHJ1eWVuIGxhcyBkaXN0cmlidWNpb25lcy4gCgoKIyMjIFRlbmRlbmNpYQoKClBhcmEgcmVhbGl6YXIgZXN0b3MgZ3LDoWZpY29zLCB2YW1vcyBhIG1vZGlmaWNhciB1biBwb2NvIGxvcyBkYXRvczoKCi0gZmlsdHJhbW9zIGxvcyBpbmdyZXNvcyBpZ3VhbGVzIGEgMC4KLSBlbGltaW5hbW9zIGxhcyBubyByZXNwdWVzdGFzIGRlIG5pdmVsIGVkdWNhdGl2byB5IGxhcyBwZXJzb25hcyBjb24gZWR1Y2FjacOzbiBlc3BlY2lhbC4KLSBlbGltaW5hbW9zIGxhcyByZXNwdWVzdGFzIGRlIHRpcG8gZGUgZXN0YWJsZWNpbWllbnRvID0gJ290cm9zJy4KLSByZWNvZGlmaWNhbW9zIGxhcyB2YXJpYWJsZXMgcGFyYSBxdWUgdGVuZ2FuIG5vbWJyZXMgbcOhcyBzdWdlc3Rpdm9zOgogICAgLSBfX05pdmVsIGVkdWNhdGl2b19fIGFkZW3DoXMgbGEgY29udmVydGltb3MgYSBmYWN0b3IsIHBvcnF1ZSBxdWVyZW1vcyBleHBsaWNpdGFybGUgZWwgb3JkZW4gZGUgbG9zIHZhbG9yZXMgY29uIGBgYGxldmVscygpYGBgLiBFbCAiXFxuIiIgZXMgdW4gX2NhcmFjdGVyIGVzcGVjaWFsXyBxdWUgcGVybWl0ZSBxdWUgZWwgc3RyaW5nIGNvbnRpbsO6ZSBlbiBsYSBzaWd1aWVudGUgbMOtbmVhLgogICAgLSBTZXhvLgogICAgLSBUaXBvIGRlIGVzdGFibGVjaW1pZW50by4KICAgIAogICAgCmBgYHtyIH0KZ2dkYXRhIDwtIEluZGl2aWR1YWxfdDExNyAlPiUgCiAgZmlsdGVyKFAyMT4wLAogICAgICAgICAhaXMubmEoTklWRUxfRUQpLAogICAgICAgICBOSVZFTF9FRCE9NywgCiAgICAgICAgIFBQMDRBICE9MykgJT4lIAogIG11dGF0ZShOSVZFTF9FRCA9IGZhY3RvcihjYXNlX3doZW4oTklWRUxfRUQgPT0gMSAgfiAnUHJpbWFyaWEgXG4gSW5jb21wbGV0YScsICMgJ1xuJyBzaWduaWZpY2EgY2FycmlhZ2UgcmV0dXJuLCBvIGVudGVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOSVZFTF9FRCA9PSAyICB+ICdQcmltYXJpYSBcbiBDb21wbGV0YScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOSVZFTF9FRCA9PSAzICB+ICdTZWN1bmRhcmlhIFxuSW5jb21wbGV0YScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOSVZFTF9FRCA9PSA0ICB+ICdTZWN1bmRhcmlhIFxuQ29tcGxldGEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTklWRUxfRUQgPT0gNSAgfiAnU3VwZXJpb3IgXG5Vbml2ZXJzaXRhcmlhIFxuSW5jb21wbGV0YScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOSVZFTF9FRCA9PSA2ICB+ICdTdXBlcmlvciBcblVuaXZlcnNpdGFyaWEgXG5Db21wbGV0YScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGQUxTRSAgICAgICAgICB+ICdPdHJvJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscz0gYygnUHJpbWFyaWEgXG4gSW5jb21wbGV0YScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnUHJpbWFyaWEgXG4gQ29tcGxldGEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1NlY3VuZGFyaWEgXG5JbmNvbXBsZXRhJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdTZWN1bmRhcmlhIFxuQ29tcGxldGEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1N1cGVyaW9yIFxuVW5pdmVyc2l0YXJpYSBcbkluY29tcGxldGEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1N1cGVyaW9yIFxuVW5pdmVyc2l0YXJpYSBcbkNvbXBsZXRhJykpLAogICAgICAgICBTZXhvICAgICA9IGNhc2Vfd2hlbihDSDA0ID09IDEgfiAnVmFyw7NuJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0gwNCA9PSAyIH4gJ011amVyJyksCiAgICAgICAgIEVzdGFibGVjaW1pZW50byAgICA9IGNhc2Vfd2hlbihQUDA0QSA9PSAxIH4gJ0VzdGF0YWwnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUFAwNEEgPT0gMiB+ICdQcml2YWRvJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZBTFNFICAgICAgfiAnT3RybycpKQoKZ2dkYXRhCmBgYAoKUGFyYSBncmFmaWNhciB1biBzdWF2aXphZG8gZGUgbGFzIHNlcmllcywgc2UgdXRpbGl6YSBsYSBmdW5jacOzbiBbYGBgZ2VvbV9zbW9vdGgoKWBgYF0oaHR0cDovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbCkuIENvbiBzdWF2aXphZG8gbm9zIHJlZmVyaW1vcyBhbCBncsOhZmljbyBkZSB1biBtb2RlbG8gcmVhbGl6YWRvIHNvYnJlIGxvcyBkYXRvcywgcXVlIGVzdGltYSBlbCB2YWxvciBlbiBlbCBwdW50byB4LHkgKHBhcmEgZWwgZ3J1cG8pLiBMYXMgcmVncmVzaW9uZXMgbGluZWFsZXMgc29uIHVuIGVqZW1wbG8gZGUgZXN0bywgYXVucXVlIG5vIGVsIMO6bmljbywgbmkgZWwgcXVlIHZpZW5lIHBvciBkZWZhdWx0LgoKYGBge3IgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9OH0KZ2dwbG90KGdnZGF0YSwgYWVzKENIMDYsIFAyMSwgY29sb3VyID0gU2V4bywgc2hhcGUgPSBTZXhvLCBhbHBoYSA9IFAyMSkpKwogIGdlb21fc21vb3RoKCkgKyAKICBsYWJzKAogICAgeCA9ICdFZGFkJywKICAgIHkgPSAnaW5ncmVzbycsCiAgICB0aXRsZSA9ICdJbmdyZXNvIHBvciBvY3VwYWNpw7NuIHByaW5jaXBhbCcsCiAgICBzdWJ0aXRsZSA9ICdTZWfDum4gZWRhZCwgbml2ZWwgZWR1Y2F0aXZvIHkgc2V4bycpICsKICB0aGVtZV9taW5pbWFsKCkrCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSsKICBzY2FsZV9hbHBoYShndWlkZSA9IEZBTFNFKSsKICBmYWNldF9ncmlkKC5+TklWRUxfRUQpCmBgYAoKClNpIGNvcnJlbW9zIGVsIGNvbWFuZG8gYGBgZ2VvbV9zbW9vdGgoKWBgYCAgcG9yIGRlZmF1bHQsIG5vcyBhZHZpZXJ0ZSBxdWUgZXN0YSB1dGlsaXphbmRvIGVsIG3DqXRvZG8gR0FNLCBkZSBbZ2VuZXJhbCBhZGRpdGl2ZSBtb2RlbHNdKGh0dHBzOi8vbS1jbGFyay5naXRodWIuaW8vZG9jcy9HQU0uaHRtbCkuICAgICAgCgplbCBfX3NvbWJyZWFkbyBncmlzX18gcXVlIGVudnVlbHZlIGNhZGEgbMOtbmVhIGVzIGVsIGludGVydmFsbyBkZSBjb25maWFuemEgZGUgZGljaG8gcHVudG8gKDk1JSBwb3IgZGVmYXVsdCkuCgpUYW1iacOpbiBwb2RlbW9zIHV0aWxpemFyIG3DqXRvZG9zIGxpbmVhbGVzLCBhZ3JlZ2FuZG8gZWwgcGFyw6FtZXRybyBgYGBtZXRob2QgPSAnbG0nYGBgLiBIYWNpZW5kbyBlc3RvLCBlbCBncsOhZmljbyBtdWVzdHJhIHVuYSByZWdyZXNpw7NuIGxpbmVhbCBzaW1wbGUuIFNpIHF1ZXJlbW9zIG90cm8gdGlwbyBkZSByZWdyZXNpw7NuIGxpbmVhbCwgbGUgcG9kZW1vcyBleHBsaWNpdGFyIGxhIGbDs3JtdWxhLiAgICAKRW4gZWwgZWplbXBsbyBzaWd1aWVudGUsIHV0aWxpemFtb3MgbGEgZm9ybXVsYSAkeSA9IFxiZXRhXzAgK1xiZXRhXzF4ICtcYmV0YV8yIHheMiAkLgoKYGBge3IgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9OH0KCmdncGxvdChnZ2RhdGEsIGFlcyhDSDA2LCBQMjEsIGNvbG91ciA9IFNleG8sIHdlaWdodCA9IFBPTkRJSU8pKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgZm9ybXVsYSA9IHkgfiBwb2x5KHgsIDIpKSArCiAgbGFicyh4ID0gJ0VkYWQnLAogICAgICAgeSA9ICdpbmdyZXNvJywKICAgICAgIHRpdGxlID0gJ1JlZ3Jlc2lvbiBjdWFkcsOhdGljYSBkZWwgSW5ncmVzbyBwb3Igb2N1cGFjacOzbiBwcmluY2lwYWwgcmVzcGVjdG8gZGUgbGEgRWRhZCcsCiAgICAgICBzdWJ0aXRsZSA9ICdTZWfDum4gTml2ZWwgZWR1Y2F0aXZvIHkgc2V4bycpICsKICB0aGVtZV9taW5pbWFsKCkrCiAgZmFjZXRfZ3JpZCguIH4gTklWRUxfRUQpCmBgYAoKClNpIHF1aXNpw6lyYW1vcywgYWRlbcOhcyBkZSB2ZXIgbGEgcmVsYWNpw7NuIGVudHJlIGluZ3Jlc28sIEVkYWQsIFNleG8geSBOaXZlbCBlZHVjYXRpdm8sIGluY29ycG9yYXIgZWwgdGlwbyBkZSBlc3RhYmxlY2ltaWVudG8scMO6YmxpY28gbyBwcml2YWRvLiBQb2RlbW9zIGZhY2V0ZWFyIGVsIGdyw6FmaWNvIHBvciBkb3MgdmFyaWFibGVzIGVuIGx1Z2FyIGRlIHVuYSwgbG8gcXVlIGNyZWEgdW5hIF9fbWF0cml6IGRlIGdyw6FmaWNvc19fIHNlZ8O6biBsb3MgY3J1Y2VzLgoKYGBge3IgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9OH0KZ2dwbG90KGdnZGF0YSwgYWVzKENIMDYsIFAyMSwgY29sb3VyID0gRXN0YWJsZWNpbWllbnRvLCB3ZWlnaHQgPSBQT05ESUlPKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICBsYWJzKAogIHggPSAnRWRhZCcsCiAgeSA9ICdpbmdyZXNvJywKICB0aXRsZSA9ICdUZW5kZW5jaWEgZGVsIGluZ3Jlc28gcG9yIG9jdXBhY2nDs24gcHJpbmNpcGFsJywKICBzdWJ0aXRsZSA9ICdTZWfDum4gZWRhZCwgbml2ZWwgZWR1Y2F0aXZvLCBzZXhvIHkgdGlwbyBkZSBlc3RhYmxlY2ltaWVudG8nKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIGZhY2V0X2dyaWQoU2V4byB+IE5JVkVMX0VEKQoKZ2dzYXZlKGZpbGVuYW1lID0gcGFzdGUwKCIuLi9SZXN1bHRhZG9zLyIsICJyZWdyZXNpb24gbGluZWFsLnBuZyIpLHNjYWxlID0gMikKCmBgYAoKCgoKIyBFamVyY2ljaW9zIHBhcmEgcHJhY3RpY2FyCgojIyBQcmVjaW9zIHkgZMOzbGFyCgpFbiBsYSBjYXJwZXRhIF9fZnVlbnRlc19fIHNlIGVuY3VlbnRyYW4gbG9zIGFyY2hpdm9zIF9fZG9sYXItZGlhcmlvLmNzdl9fIHkgX19pcGMtbWVuc3VhbC5jc3ZfXy4gQ29uIGVsbG9zLCBlbCBvYmpldGl2byBlcyByZWFsaXphciB1biBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvIGRlIGVzdGFzIHZhcmlhYmxlcyBkZSBsYSBlY29ub23DrWEgYXJnZW50aW5hLiAKTGEgYmFzZSBkZSBkYXRvcyBkZWwgZG9sYXIgdGllbmUgZnJlY3VlbmNpYSBkaWFyaWEgeSBjb21pZW56YSBlbiBNYXJ6byBkZSAyMDAyLgpMYSBiYXNlIGRlIGRhdG9zIGRlbCBJUEMgdGllbmUgZnJlY3VlbmNpYSBtZW5zdWFsIHkgY29taWVuemEgZW4gQWJyaWwgZGUgMjAxNi4KClBhcmEgdHJhYmFqYXIgY29uIGVsIGTDsmxhciBlbiB1bmEgZnJlY3VlbmNpYSBtZW5zdWFsIHZhbW9zIGEgY29uc2lkZXJhciBsYSBjb3RpemFjacOzbiBkZWwgcHJpbWVyIGTDrWEgaMOhYmlsIGRlIGNhZGEgbWVzIGNvbW8gbGEgY290aXphY2nDs24gZGUgZGljaG8gbWVzLgoKRGViZW4gcG9kZXIgbW9zdHJhciBsb3Mgc2lndWllbnRlcyBncsOhZmljb3MgeSBjb250ZXN0YXIgZXN0YXMgcHJlZ3VudGFzOgoKYSkgR3LDoWZpY28gZGUgbGEgZXZvbHVjacOzbiBkZWwgZMOzbGFyIChjb25zdHJ1aXIgbGEgZnJlY3VlbmNpYSBtZW5zdWFsIGRlbCBkw7NsYXIgY29uIGVsIHRpcG8gZGUgY2FtYmlvIGRlbCBwcmltZXIgZMOtYSBow6FiaWwgZGVsIG1lcykKYikgR3LDoWZpY28gZGUgbGEgZXZvbHVjacOzbiBkZWwgSVBDIEdlbmVyYWwKYykgR3LDoWZpY28gZGUgbGEgZXZvbHVjacOzbiBkZSBsb3MgY3VhdHJvIGdydXBvcyBkZWwgSVBDCmQpIMK/Q3XDoWwgZXMgbGEgbWVkaWEsIGVsIGRlc3bDrW8gZXN0w6FuZGFyLCBsYSBtZWRpYW5hIHkgZWwgcmFuZ28gZGVsIGTDs2xhciB5IGRlbCBJUEMgR2VuZXJhbCBwYXJhIGNhZGEgdW5vIGRlIGxvcyBhw7Fvcz8KZSkgR3LDoWZpY28gZGUgbGEgZXZvbHVjacOzbiBkZWwgZMOzbGFyIHkgZGVsIElQQyBHZW5lcmFsIHBhcmEgZWwgcGVyw61vZG8gZGUgdGllbXBvIHF1ZSB0ZW5lbW9zIGRhdG9zIGRlIGFtYmFzIHZhcmlhYmxlcwpmKSBHcsOhZmljbyBkZSBsYSBldm9sdWNpw7NuIGRlbCBkw7NsYXIgeSBkZSBsb3MgNCBncnVwb3MgZGUgSVBDIHBhcmEgZWwgcGVyw61vZG8gZGUgdGllbXBvIHF1ZSB0ZW5lbW9zIGRhdG9zIGRlIGFtYmFzIHZhcmlhYmxlcwoKUmVjb21lbmRhbW9zIHF1ZSBpbnRlbnRlbiBpciByZXNvbHZpZW5kbyBsb3MgcHJvYmxlbWFzIHF1ZSBzdXJqYW4gY29uc3VsdGFuZG9ub3MgYSBub3NvdHJvcywgbG9zICJtYWNoZXRlcyIgZGUgUiB5IG90cmFzIHDDoWdpbmFzIHBlcm8gZGVqYW1vcyB1bmEgZ3XDrWEgZGUgcGFzb3MgeSBheXVkYXMgCgoxLiBMZXZhbnRhciBhbWJvcyBjb25qdW50b3MgZGUgZGF0b3MKMi4gRW4gZWwgZGF0YXNldCBkZWwgZMOzbGFyIHJlbm9tYnJhbW9zIGxhIHZhcmlhYmxlIGRlbCB0aXBvIGRlIGNhbWJpbyBwb3IgYWxnbyBtw6FzIHNlbmNpbGxvCjMuIENyZWFtb3MgbGFzIHZhcmlhYmxlcyBmZWNoYSwgYcOxbywgbWVzIHkgZMOtYSAKNC4gU2VsZWNjaW9uYW1vcyBlbCBwcmltZXIgZMOtYSBow6FiaWwgZGVsIG1lcyBwYXJhIG9idGVuZXIgbGEgcHJpbWVyIGNvdGl6YWNpw7NuIGRlbCBtZXMgKHBhcmEgZWwgZG9sYXIpCjUuIEdyYWZpY2Ftb3MgbGEgZXZvbHVjacOzbiBkZWwgdGlwbyBkZSBjYW1iaW8KNi4gTm9ybWFsaXphciBsb3MgZGF0b3MgZGVsIElQQy4gKlBpc3RhKjogcGllbnNlbiBzaSB0aWVuZW4gcXVlIHVzYXIgJHNwcmVhZCQgbyAkZ2F0aGVyJAo3LiBDcmVhbW9zIGxhcyB2YXJpYWJsZXMgZmVjaGEsIGHDsW8geSBtZXMKOC4gR3JhZmljYW1vcyBsYSBldm9sdWNpw7NuIGRlbCBuaXZlbCBnZW5lcmFsIGRlbCBJUEMKOS4gR3JhZmljYW1vcyBsYSBldm9sdWNpw7NuIGRlIGxvcyA0IGdydXBvcwoxMC4gUmVhbGl6YW1vcyB1biBqb2luIGRlIGFtYm9zIGNvbmp1bnRvcyBkZSBkYXRvcy4gQ29uc2lkZXJlbiBxdcOpIHRpcG8gZGUgam9pbiB0aWVuZW4gcXVlIHVzYXIgCjExLiBPYnRlbmVtb3MgbGFzIGVzdGFkaXN0aWNhcyBkZSByZXN1bWVuIGRlIGxhIHByZWd1bnRhIGQpCjExLiBHcmFmaWNhbW9zIGxhIGV2b2x1Y2nDsm4gZGVsIGTDs2xhciB5IGRlbCBuaXZlbCBnZW5lcmFsIGRlbCBJUEMgKHRlbmVyIGVuIGN1ZW50YSBlbCByYW5nbyBkZSBsYXMgdmFyaWFibGVzKQoxMi4gR3JhZmljYW1vcyBsYSBldm9sdWNpw7JuIGRlbCBkw7NsYXIgeSBkZSBsb3MgZ3J1cG9zIGRlbCBJUEMKCiMjIEVQSAoKRWwgT2JqZXRpdm8gZGUgZXN0b3MgZWplcmNpY2lvcyBlcyBwcmFjdGljYXIgZWwgdXNvIGRlbCAkdGlkeXZlcnNlJCBwYXJhIGxhIG1hbmlwdWxhY2nDs24gZGUgbG9zIGRhdG9zLCB5ICRnZ3Bsb3QkIHBhcmEgZ3JhZmljYXIgbGEgaW5mb3JtYWNpw7NuLiBFbiBsYXMgY29uc2lnbmFzLCBzZSBwcm9wb25lIGRlIG1hbmVyYSBnZW5lcmFsIHF1w6kgdmFyaWFibGVzIHNlIHF1aWVyZSBvYnNlcnZhci4gVXN0ZWRlcyBkZWJlcsOhbiBsZXZhbnRhciB5IHByb2Nlc2FyIGxvcyBkYXRvcyBkZSBsYSBFbmN1ZXN0YSBQZXJtYW5lbnRlIGRlIEhvZ2FyZXMsIHkgZ3LDoWZpY2FybG9zIGNvbW8gY29uc2lkZXJlbiBxdWUgbWVqb3Igc2UgYXByZWNpYSBsYSByZWxhY2nDs24gZW50cmUgbGFzIHZhcmlhYmxlcy4gICAgIAoKVW5hIF9fYXl1ZGFfXyBlcyB1dGlsaXphciBlbCBbZGlzZcOxbyBkZSByZWdpc3Ryb10oLi4vRnVlbnRlcy9FUEhfcmVnaXN0cm9fMl90cmltXzIwMTYucGRmKSBwYXJhIGNvZGlmaWNhciBsYXMgdmFyaWFibGVzCgoKX19lamVyY2ljaW9zX18KCi0gR3JhZmljYXIgbGEgZGlzdHJpYnVjacOzbiBkZWwgaW5ncmVzbyBwb3Igb2N1cGFjacOzbiBwcmluY2lwYWwgKHAyMSkgc2Vnw7puIGNhdGVnb3LDrWEgb2N1cGFjaW9uYWwgKENBVF9PQ1VQKS4gKG9wY2lvbmFsOiB1dGlsaXphciBsYSBsaWJyZXLDrWEgW2dncmlkZ2VzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2dyaWRnZXMvdmlnbmV0dGVzL2ludHJvZHVjdGlvbi5odG1sKSkKCi0gSW5jb3Jwb3JhciBlbiBlbCBncsOhZmljbyBhbnRlcmlvciBsYSBjb25kaWNpw7NuIGRlIHByZWNhcmllZGFkIGxhYm9yYWwgKFBQMDdIKS4KCi0gUXVlZGFyc2Ugc8OzbG8gY29uIGxvcyBhc2FsYXJpYWRvcyAoQ0FUX09DVVAgPSAzKSwgeSBncmFmaWNhciBsYSByZWxhY2nDs24gZW50cmUgaW5ncmVzbyBwb3Igb2N1cGFjacOzbiBwcmluY2lwYWwocDIxKSwgcHJlY2FyaWVkYWQgbGFib3JhbCAoUFAwN0gpIHkgdGFtYcOxbyBkZWwgZXN0YWJsZWNpbWllbnRvKFBQMDRDOTkpLgoKLSBRdWVkYXJzZSBjb24gbG9zIEN1ZW50YXByb3Bpc3RhcyB5IGFzYWxhcmlhZG9zIChDQVRfT0NVUCA9IDIgeSAzKSB5IGNvbXBhcmFyLCBzZWfDum4gbGEgY29uZGljacOzbiBkZSBwcmVjYXJpZWRhZCBsYWJvcmFsIChQUDA3SCkgbGEgZGlzdHJpYnVjacOzbiBkZWwgaW5ncmVzbyBzZWfDum4gc2V4byAoQ0gwNCkKCi0gSW5jb3Jwb3JhciBlbiBlbCBncsOhZmljbyBhbnRlcmlvciBlbCB0YW1hw7FvIGRlbCBlc3RhYmxlY2ltaWVudG8oUFAwNEM5OSkKCgpfX3lhcGE6X18gU2kgcXVpc2llcmFtb3MgbW9kZWxhciBsYSBwcm9iYWJpbGlkYWQgZGUgdW4gZXZlbnRvIHBvZGVtb3MgdXNhciB1bmEgcmVncmVzacOzbiBsb2fDrXNpdGNhIChlbiBnZ3Bsb3QgYGBgc3RhdF9zbW9vdGgobWV0aG9kPSJnbG0iLCBtZXRob2QuYXJncz1saXN0KGZhbWlseT0iYmlub21pYWwiKWBgYCkuICAgICAKVXRpbGljZW4gZXN0ZSBtb2RlbG8gcGFyYSBoYWNlciB1biBncsOhZmljbyBxdWUgZWNoZSBsdXogc29icmUgZWwgc2lndWllbnRlIGZlbsOzbWVubzogCgotIMK/Q8OzbW8gc2UgZGlzdHJpYnV5ZSBsYSBwcm9iYWJpbGlkYWQgZGUgcXVlcmVyIHRyYWJhamFyIG3DoXMgaG9yYXMgKFBQMDNHKSBzZWfDum4gZWwgdG90YWwgZGUgaG9yYXMgdHJhYmFqYWRhcyBwb3Igc2VtYW5hIChQUDNFX1RPVCk/IMK/RXMgZGlmZXJlbnRlIGVsIG1vZGVsbyBzZWfDum4gc2V4byhDSDA0KT8KCgoK