1 Introducción

La base de datos ha sido consultada en la pagina de datos abiertos del gobierno de Colombia durante el mes de Noviembre del año 2018. Los datos contienen las de precipitaciones y temperatura promediadas de cada mes, durante 30 años.

Por ejemplo, la variable septemp30a contiene la temperatura promedio de 30 años, registrada para el mes de septiembre durante esos 30 años..

Se aplicarán algunas funciones del paquete tidyverse entre otros paquetes para explorar el conjunto de datos y hacer la depuración pertinente con el objetivo de estructurar la información de forma tabular, y así hacer un análisis descriptivo de las variables, generando gráficos con la librería ggplot2.

2 Base de Datos Original

2.1 Lectura

Primero cargamos el paquete tidyverse, el cual es un conjunto de paquetes que permiten el manejo de bases de datos de manera eficiente.

La función read_csv lee el archivo de nuestro directorio de trabajo.

library(tidyverse)
datos <- read_csv(file = "PrecipitacionTemperaturaPromedio.csv")

2.2 Estructura y Resumen

La función skim de la librería skimr permite obtener un resumen de los datos y conocer de manera general la estructura de nuestros datos.

library(skimr)
skim(datos)
── Data Summary ────────────────────────
                           Values
Name                       datos 
Number of rows             450   
Number of columns          41    
_______________________          
Column type frequency:           
  character                7     
  numeric                  34    
________________________         
Group variables            None  

── Variable type: character ─────────────────────────────────────────
  skim_variable n_missing complete_rate   min   max empty n_unique
1 nombre                0             1     4    18     0      441
2 categoria             0             1     2     2     0        5
3 departamento          0             1     4    30     0       32
4 municipio             0             1     4    27     0      342
5 corriente             0             1     3    16     0      326
6 lac                   0             1     1     1     0        2
7 loc                   0             1     1     1     0        1
  whitespace
1          0
2          0
3          0
4          0
5          0
6          0
7          0

── Variable type: numeric ───────────────────────────────────────────
   skim_variable n_missing complete_rate        mean          sd
 1 codigo                0             1 26965458.   10733727.  
 2 lag                   0             1        5.11        2.74
 3 lam                   0             1       28.2        17.1 
 4 las                   0             1       27.1        18.3 
 5 log                   0             1       74.2         1.68
 6 lom                   0             1       29.7        17.5 
 7 los                   0             1       26.7        19.7 
 8 altitud               0             1     1078.        975.  
 9 enepreci30a           0             1       88.5        98.1 
10 febpreci30a           0             1       98.5        85.2 
11 marpreci30a           0             1      138.         96.3 
12 abrpreci30a           0             1      205.        122.  
13 maypreci30a           0             1      230.        140.  
14 junpreci30a           0             1      182.        145.  
15 julpreci30a           0             1      165.        143.  
16 agopreci30a           0             1      164.        140.  
17 seppreci30a           0             1      190.        133.  
18 octpreci30a           0             1      232.        129.  
19 novpreci30a           0             1      200.        121.  
20 dicpreci30a           0             1      129.        112.  
21 totalpreci30a         0             1     2005.       1279.  
22 enetemp30a            0             1       22.2         5.59
23 febtemp30a            0             1       22.5         5.63
24 martemp30a            0             1       22.5         5.59
25 abrtemp30a            0             1       22.4         5.47
26 maytemp30a            0             1       22.3         5.41
27 juntemp30a            0             1       22.2         5.53
28 jultemp30a            0             1       22.2         5.71
29 agotemp30a            0             1       22.3         5.72
30 septemp30a            0             1       22.3         5.58
31 octtemp30a            0             1       22.1         5.43
32 novtemp30a            0             1       22.0         5.38
33 dictemp30a            0             1       22.0         5.45
34 protemp30a            0             1       22.2         5.53
           p0         p25        p50        p75       p100 hist 
 1 11025010   21187575    24035095   29045118.  57025010   ▂▇▂▁▁
 2        0          3           5          7         13   ▃▇▃▃▁
 3        0         13          28         44         59   ▇▇▇▆▆
 4        0         12          26.4       43.7       59.4 ▇▇▆▆▆
 5       67         73          74         75         81   ▁▂▇▂▁
 6        0         14          30         45         59   ▇▇▇▇▇
 7        0          7.62       27         43.6       59.7 ▇▃▅▅▅
 8        1        163.        966.      1850       4150   ▇▃▃▂▁
 9        0.8       28.2        63        104.       619.  ▇▁▁▁▁
10        0.5       43.1        81.8      124.       575.  ▇▂▁▁▁
11        1.2       73.9       122.       176.       607.  ▇▆▁▁▁
12        6.9      120.        175        267.       819.  ▇▆▂▁▁
13       27.3      129.        185.       301.       854.  ▇▅▂▁▁
14        8.2       72.9       131.       242.       853.  ▇▃▂▁▁
15        6.5       55.7       116.       224.       805.  ▇▃▂▁▁
16       17.6       57.0       128.       225.       866.  ▇▃▁▁▁
17       35.7       94.2       164.       241.       911.  ▇▃▁▁▁
18       65.7      147.        203.       284.       882.  ▇▅▁▁▁
19       53.5      119.        172.       243.       836.  ▇▃▁▁▁
20       15.2       55.5        99.3      155.       810.  ▇▂▁▁▁
21      326.      1170.       1573.      2550.      8051   ▇▅▁▁▁
22        4.4       17.9        23.9       27         30.4 ▁▂▃▃▇
23        4.6       18          24.2       27.2       30.5 ▁▂▃▃▇
24        4.8       18.1        24.0       27.3       30.9 ▁▂▃▃▇
25        5         18.2        23.8       27.2       30.2 ▁▂▃▅▇
26        5.1       18.0        23.8       27.1       29.7 ▁▂▃▃▇
27        4.9       18.0        23.6       27.2       29.9 ▁▂▃▆▇
28        4.5       17.8        23.7       27.2       30.1 ▁▂▃▆▇
29        4.5       17.8        24.0       27.4       30.3 ▁▂▃▆▇
30        4.4       18.0        24         27.1       29.9 ▁▂▃▃▇
31        4.4       17.9        23.4       26.8       29   ▁▂▃▃▇
32        4.4       17.8        23.4       26.8       29   ▁▂▃▃▇
33        4.5       17.8        23.6       26.8       29.7 ▁▂▃▃▇
34        4.6       18.0        23.8       27.2       29.8 ▁▂▃▃▇


Se tienen para esta base de datos 450 filas y 41 columnas, 7 columnas de clase character y 34 de clase ǹumeric. La dimensión de la base de datos también es posible obtenerla con la función dim().

dim(datos)
[1] 450  41

El resumen anterior nos arroja una idea del comportamiento de las variables además de entregar información acerca de los valores ausentes NA, que para esta base de datos en particular no hay. Un histograma con la distribución de las variables es reperesentado en el resumen, el cual también representaremos a través de la librería ggplot2 para cada una de las variables.

Una rápida consulta de los valores NA también puede lograrse de la siguiente manera. Solicitamos con la función table() el conteo de los valores NA a través de la función is.na().

table(is.na(datos))

FALSE 
18450 


2.3 Presentación base de datos.

datos


3 Depuración Base de Datos

Estructuraremos una base de datos que contenga la información que consideremos relevante para el análisis o exploración de la información que deseamos hacer.

  • Selección variables de interés.
  • Pasar de formato ancho a formato largo.
  • Editar el nombre de los meses.
  • Cambiar la variable meses a factor.
  • Asignar los niveles a la variable meses.

Estas acciones que se mencionan, se pueden ejecutar a través del operador %>% conocido como tubería (pipe), que permite encadenar varios comandos o funciones para que se ejecuten uno seguido de otro.

3.1 Datos Precipitaciones

Obtendremos un objeto llamado precip, que contiene las precipitaciones de los municipios por mes.

precip <- datos %>% 
  # seleccionar las variables
  select(departamento, municipio, altitud:dicpreci30a) %>% 
  # pasar de formato largo a ancho
  pivot_longer(cols = c(enepreci30a:dicpreci30a), names_to = "mes",
               values_to = "precipitaciones") %>%
  # editar nombres de la variable mes
  mutate(mes = gsub(pattern = "enepreci30a", replacement = "enero", x = mes),
         mes = gsub(pattern = "febpreci30a", replacement = "febrero", x = mes),
         mes = gsub(pattern = "marpreci30a", replacement = "marzo", x = mes),
         mes = gsub(pattern = "abrpreci30a", replacement = "abril", x = mes),
         mes = gsub(pattern = "maypreci30a", replacement = "mayo", x = mes),
         mes = gsub(pattern = "junpreci30a", replacement = "junio", x = mes),
         mes = gsub(pattern = "julpreci30a", replacement = "julio", x = mes),
         mes = gsub(pattern = "agopreci30a", replacement = "agosto", x = mes),
         mes = gsub(pattern = "seppreci30a", replacement = "septiembre", x = mes),
         mes = gsub(pattern = "octpreci30a", replacement = "octubre", x = mes),
         mes = gsub(pattern = "novpreci30a", replacement = "noviembre", x = mes),
         mes = gsub(pattern = "dicpreci30a", replacement = "diciembre", x = mes),
         # convertir la variable mes en factor
         mes = factor(x = mes, levels = c("enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre")))
precip
dim(precip)
[1] 5400    5

3.2 Datos Temperaturas

Obtendremos el objeto que contenga la información de las temperaturas de los municipios por mes.

tempe <- datos %>% 
  select(departamento, municipio, altitud, enetemp30a:dictemp30a) %>% 
  pivot_longer(cols = c(enetemp30a:dictemp30a), names_to = "mes",
               values_to = "temperaturas") %>% 
  mutate(mes = gsub(pattern = "enetemp30a", replacement = "enero", x = mes),
         mes = gsub(pattern = "febtemp30a", replacement = "febrero", x = mes),
         mes = gsub(pattern = "martemp30a", replacement = "marzo", x = mes),
         mes = gsub(pattern = "abrtemp30a", replacement = "abril", x = mes),
         mes = gsub(pattern = "maytemp30a", replacement = "mayo", x = mes),
         mes = gsub(pattern = "juntemp30a", replacement = "junio", x = mes),
         mes = gsub(pattern = "jultemp30a", replacement = "julio", x = mes),
         mes = gsub(pattern = "agotemp30a", replacement = "agosto", x = mes),
         mes = gsub(pattern = "septemp30a", replacement = "septiembre", x = mes),
         mes = gsub(pattern = "octtemp30a", replacement = "octubre", x = mes),
         mes = gsub(pattern = "novtemp30a", replacement = "noviembre", x = mes),
         mes = gsub(pattern = "dictemp30a", replacement = "diciembre", x = mes),
         mes = factor(x = mes, levels = c("enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre")))
tempe
dim(tempe)
[1] 5400    5

3.3 Unir los Datos

Uniremos los dos objetos que creamos para consolidar una única base de datos que contenga los datos de precipitación y temperatura. Las función right_join() permite unir columnas a la base de datos, en este caso a la derecha de nuestro arreglo tabular para agregar la columna con las temperaturas.

df_pretem <- right_join(x = precip, y = tempe)


df_pretem

3.4 Editar Departamentos y Crear Regiones

Se editarán los nombres de algunos departamentos que presentan errores de ortografía para presentarlos de manera correcta.

Se obtendrá una nueva columna con las regiones naturales de Colombia a la que pertenecen los diferentes departamentos, conformadas de la siguiente manera:

  • Región Pacífico : Cauca , Chocó, Nariño, Valle del Cauca

  • Región Orinoquía : Arauca, Casanare, Meta, Vichada

  • Región Amazonía : Amazonas, Caquetá, Guainía, Guaviare, Putumayo. (El departamento de Vaupés no aparece en los datos originales, por lo tanto no aparece aquí representado).

  • Región Caribe : Atlántico, Bolívar, Cesar, Cordoba, La Guajira, Magdalena, San Andrés Providencia y Santa Catalina, Sucre.

  • Región Andina : Antioquia, Boyacá, Caldas, Cundinamarca, Huila, Norte de Santander, Quindío, Risaralda, Santander, Tolima, Bogotá DC.

La región insular no se presenta en los datos. Región a la cual pertenece San Andrés, Providencia y Santa Catalina.

df_pretem <- df_pretem %>% 
  mutate(departamento = gsub(pattern = "Atlantico", replacement = "Atlántico", x = departamento),
         departamento = gsub(pattern = "Bogota DC", replacement = "Bogotá DC", x = departamento),
         departamento = gsub(pattern = "Bolivar", replacement = "Bolívar", x = departamento),
         departamento = gsub(pattern = "Boyaca", replacement = "Boyacá", x = departamento),
         departamento = gsub(pattern = "Caqueta", replacement = "Caquetá", x = departamento),
         departamento = gsub(pattern = "Choco", replacement = "Chocó", x = departamento),
         departamento = gsub(pattern = "Cordoba", replacement = "Córdoba", x = departamento),
         departamento = gsub(pattern = "Guainia", replacement = "Guainía", x = departamento),
         departamento = gsub(pattern = "Narino", replacement = "Nariño", x = departamento),
         departamento = gsub(pattern = "Quindio", replacement = "Quindío", x = departamento),
         departamento = gsub(pattern = "San Andres Providencia y Sta C", replacement = "S.Andrés-Provid.-Sta.Cat.", x = departamento)) %>%
  mutate(region = ifelse(departamento %in% c("Cauca", "Chocó", "Nariño", "Valle del Cauca"),
                         "Región Pacífico",
                         ifelse(departamento %in% c("Arauca", "Casanare", "Meta", "Vichada"),
                                "Región Orinoquía",
                                ifelse(departamento %in% c("Amazonas", "Caquetá", "Guainía", "Guaviare", "Putumayo"),
                                       "Región Amazonas",
                                       ifelse(departamento %in% c("Atlántico", "Bolívar", 
                                                                  "Cesar", "Córdoba", "La Guajira",
                                                                  "Magdalena",
                                                                  "S.Andrés-Provid.-Sta.Cat.",
                                                                  "Sucre"), "Región Caribe", "Región Andina")))))
head(df_pretem)
dim(df_pretem)
[1] 5496    7



3.5 Exportar Base de Datos

Finalmente después de la depuración y asegurar que la base de datos está como se desea, se guardará la base de datos en el directorio de trabajo en formato csv con el nombre precipitaciones_temperaturas.csv.

write_csv(x = df_pretem, file = "precipitaciones_temperaturas.csv")


4 Presentación de Nuevos Datos

Veamos la estructura de la base de datos que contruimos. Hagamos la lectura para realizar un resumen de los datos.

df_datos <- read_csv(file = "precipitaciones_temperaturas.csv")


df_datos
skim(df_datos)
── Data Summary ────────────────────────
                           Values  
Name                       df_datos
Number of rows             5496    
Number of columns          7       
_______________________            
Column type frequency:             
  character                4       
  numeric                  3       
________________________           
Group variables            None    

── Variable type: character ─────────────────────────────────────────
  skim_variable n_missing complete_rate   min   max empty n_unique
1 departamento          0             1     4    25     0       32
2 municipio             0             1     4    27     0      342
3 mes                   0             1     4    10     0       12
4 region                0             1    13    16     0        5
  whitespace
1          0
2          0
3          0
4          0

── Variable type: numeric ───────────────────────────────────────────
  skim_variable   n_missing complete_rate   mean     sd    p0   p25
1 altitud                 0             1 1068.  975.     1   152  
2 precipitaciones         0             1  172.  136.     0.5  78.9
3 temperaturas            0             1   22.3   5.52   4.4  18.0
    p50   p75   p100 hist 
1 954.   1850 4150   ▇▃▃▂▁
2 136.    225  911.  ▇▃▁▁▁
3  23.9    27   30.9 ▁▂▃▅▇


4.1 Editar Mes

Editaremos los nombres de los meses, pondremos la primera letra del mes en mayúscula.. (Se harán los cambios pero no se guardarán en la base de datos, se harán para mostrar el uso de las funciones.)

Para poner la primera letra en mayúscula de una cadena de caracteres, se usa la función capitalize del paquete Hmisc.


library(Hmisc)
capitalize(df_datos$mes)


4.2 Exploración de las Variables

Obtengamos algunas estadísticas con los paquete base de R para la variable precipitaciones:

  • media
mean(df_datos$precipitaciones)
[1] 172.1682
  • mediana
median(df_datos$precipitaciones)
[1] 136.3
  • quartiles
quantile(df_datos$precipitaciones)
     0%     25%     50%     75%    100% 
  0.500  78.875 136.300 225.000 911.300 
  • deciles
quantile(df_datos$precipitaciones, probs = seq(from = 0.1, to = 1, by = 0.1))
   10%    20%    30%    40%    50%    60%    70%    80%    90% 
 42.45  66.10  89.40 111.20 136.30 165.80 202.50 256.50 347.80 
  100% 
911.30 
  • desviación estándar
sd(df_datos$precipitaciones)
[1] 135.6864
  • coeficiente de variación
sd(df_datos$precipitaciones)/mean(df_datos$precipitaciones)
[1] 0.7881037
  • kurtosis
# Paquete con función para hallar kurtosis de un conjunto de datos.
library(moments)
kurtosis(df_datos$precipitaciones)
[1] 6.844173
  • Varianza
var(df_datos$precipitaciones)
[1] 18410.8

4.3 Distribución de las variables


library(gridExtra)

g1 <- df_datos %>% 
  ggplot(mapping = aes(x = precipitaciones)) + 
  geom_histogram(aes(y = ..density..),
                 colour = 1, fill = "firebrick2") +
  geom_density(lwd = 1, colour = 4,
               fill = 4, alpha = 0.3)+
  geom_vline(xintercept = quantile(df_datos$precipitaciones),
             linetype='dashed')+
  scale_x_continuous(n.breaks = 10)+
  labs(title = "Densidad - Histograma de Precipitaciones",
       x = "Precipitaciones (mm)",
       y = "Densidad")+
  theme_bw()

g2 <- df_datos %>% 
  ggplot(mapping = aes(x = precipitaciones))+
  geom_boxplot(fill = "firebrick2", alpha = 0.8)+
  labs(title = "Boxplot Precipitaciones",
       x = "Precipitaciones (mm)", y = "")+
  scale_x_continuous(n.breaks = 10)+
  theme_bw()

g3 <- df_datos %>% 
  ggplot(mapping = aes(x = temperaturas)) + 
  geom_histogram(aes(y = ..density..),
                 colour = 1, fill = "purple") +
  geom_density(lwd = 1, colour = "orange",
               fill = "orange", alpha = 0.3)+
  scale_x_continuous(n.breaks = 15)+
  geom_vline(xintercept = quantile(df_datos$temperaturas),
             linetype='dashed')+
  labs(title = "Densidad - Histograma de Temperaturas",
       x = "Temperaturas °C",
       y = "Densidad")+
  theme_bw()

g4 <- df_datos %>% 
  ggplot(mapping = aes(x = temperaturas))+
  geom_boxplot(fill = "purple", alpha = 0.8)+
  labs(title = "Boxplot Temperaturas",
       x = "Temperaturas °C", y = "")+
  scale_x_continuous(n.breaks = 15)+
  theme_bw()

g5 <- df_datos %>% 
  ggplot(mapping = aes(x = altitud)) + 
  geom_histogram(aes(y = ..density..),
                 colour = 1, fill = "slategray") +
  geom_density(lwd = 1, colour = 3,
               fill = 4, alpha = 0.3)+
  geom_vline(xintercept = quantile(df_datos$altitud),
             linetype='dashed')+
  scale_x_continuous(n.breaks = 10)+
  labs(title = "Densidad - Histograma de Altitud",
       x = "Altitud (m))",
       y = "Densidad")+
  theme_bw()

g6 <- df_datos %>% 
  ggplot(mapping = aes(x = altitud))+
  geom_boxplot(fill = "slategray", alpha = 0.8)+
  labs(title = "Boxplot Altitud",
       x = "Altitud (m)", y = "")+
  scale_x_continuous(n.breaks = 10)+
  theme_bw()

grid.arrange(g1, g2, g3, g4, g5, g6, nrow=3)


5 Resumen Numérico por Departamento

5.1 Resumen Precipitaciones

Se obtendrá un resumen numérico de las variables en forma tabular para cada departamento. Se obtendrán el promedio, la mediana, el valor máximo, el valor mínimo, la desviación estándar, el coeficiente de variación, kurtosis y los quartiles 25, 50 y 75.

También es posible obtener el resumen para cada municipio, basta con agrupar los datos por municipio y obtener las estadísticas que se desee.

df_datos %>%
  # agrupar por departamento
  group_by(departamento) %>%
  # obtener estadísticas
  summarise(prom_pre = mean(precipitaciones),
            med_pre = median(precipitaciones),
            max_pre = max(precipitaciones),
            min_pre = min(precipitaciones),
            de_pre = sd(precipitaciones),
            p25 = quantile(precipitaciones, probs = 0.25),
            p50 = quantile(precipitaciones, probs = 0.5),
            p75 = quantile(precipitaciones, probs = 0.75),
            cv = round(sd(precipitaciones)/mean(precipitaciones), digits = 2),
            Kurt = kurtosis(precipitaciones))


A través del diagrama de caja es posible resumir de manera gráfica algunas de las estadíticas obtenidas. Haciendo uso de la tubería %>% es posible encadenar código para hacer operaciones sobre los datos y después graficar.

df_datos %>% 
ggplot(mapping = aes(x = departamento, y = precipitaciones))+
geom_boxplot(fill = "slategray")+
  labs(title = "Distribución Precipitaciones por Departamento",
       x = "Departamento", y = "Precipitaciones (mm)")+
  theme(legend.position = "none", axis.text.x = element_text(angle = 45))


5.2 Resumen Temperaturas

df_datos %>% 
  group_by(departamento) %>% 
  summarise(prom_pre = mean(temperaturas),
            med_pre = median(temperaturas),
            max_pre = max(temperaturas),
            min_pre = min(temperaturas),
            de_pre = sd(temperaturas),
            cv = round(sd(temperaturas)/mean(temperaturas), digits = 2),
            kurt = kurtosis(temperaturas))


Para el gráfico de las temperaturas se hace uso de las facetas (facets), para dividir el gráfico en paneles que reperesentan cada departamento. Obtenedremos el diagrama de cajas y bigotes superpuesto con un gráfico de violín para conocer la distribución de la variable temperatura.

df_datos %>% 
  ggplot(mapping = aes(x = departamento, y = temperaturas), fill = departamento)+
  geom_violin(fill = "steelblue", alpha = 0.6)+
  geom_boxplot(alpha = 0.7)+
  labs(title = "Distribución de Temperaturas por Departamento",
       x = "", y = "Temperatura °C")+
  facet_wrap(facets = ~departamento, scales = "free", nrow = 8)


6 Gráficos por Departamento

  • Precipitaciones por mes para cada Departamento
df_datos %>%
  mutate(mes = factor(x = mes, levels = c("enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre")))  %>% 
  group_by(departamento, mes) %>%
  summarise(prom = mean(precipitaciones)) %>% 
  ggplot(mapping = aes(y = prom, x = mes))+
  geom_point(color = "blue")+
  labs(title = "Promedio Precipitaciones por Mes y Departamento", x = "Mes", y = "Prom. Precipitaciones (mm)")+
  facet_wrap(facets = ~departamento, nrow = 8)+
  theme_bw()+
  theme(legend.position = "none", axis.text.x = element_text(angle = 90))

  • Promedios
library(gridExtra)

h1 <- df_datos %>%
  group_by(departamento) %>% 
  summarise(tot_prep = round(mean(precipitaciones), digits = 2)) %>% 
  ggplot(mapping = aes(x = reorder(departamento, -tot_prep), y = tot_prep))+
  geom_bar(stat = "identity", alpha = 0.9)+
  scale_y_continuous(n.breaks = 6)+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 90))+
  labs(title = "Precipitaciones Promedio por Departamento", x = "", y = "Prom. Precipitaciones (mm)")

h2 <- df_datos %>%
  group_by(departamento) %>% 
  summarise(tot_prep = round(mean(temperaturas), digits = 2)) %>% 
  ggplot(mapping = aes(x = reorder(departamento, -tot_prep), y = tot_prep))+
  geom_bar(stat = "identity", alpha = 0.9)+
  scale_y_continuous(n.breaks = 6)+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 90))+
  labs(title = "Temperaturas Promedio por Departamento", x = "", y = "Prom. Temperaturas (°C)")

h3 <- df_datos %>%
  group_by(departamento) %>% 
  summarise(tot_prep = round(mean(altitud), digits = 2)) %>% 
  ggplot(mapping = aes(x = reorder(departamento, -tot_prep), y = tot_prep))+
  geom_bar(stat = "identity", alpha = 0.9)+
  scale_y_continuous(n.breaks = 6)+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 90))+
  labs(title = "Altitud Promedio por Departamento", x = "", y = "Prom. Altitud (m)")

grid.arrange(h1, h2, h3, nrow=2)


  • Municipios de Cundinamarca.
df_datos %>%
  filter(departamento == c("Cundinamarca")) %>% 
  group_by(departamento, municipio) %>% 
  summarise(tot_prep = mean(altitud)) %>%
  ungroup() %>% 
  ggplot(mapping = aes(x = municipio, y = tot_prep))+
  geom_bar(fill = "darkolivegreen4",stat = "identity")+
  geom_text(aes(label = tot_prep),
                   position = position_identity(),
                   vjust = -0.1,
                   color = "black",
                   size = 2.5)+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 90))+
  labs(title = "Precipitaciones Promedio Municipios de Cundinamarca", x = "", y = "Prom. Precipitaciones (mm)")+
  facet_wrap(facets = ~departamento, scales = "free")


  • Precipitaciones y Temperaturas por Región

p1 <- df_datos %>%
  group_by(region , departamento) %>% 
  summarise(tot_prep = mean(precipitaciones)) %>%
  ungroup() %>% 
  ggplot(mapping = aes(x = departamento, y = tot_prep))+
  geom_bar(fill = "darkslateblue",stat = "identity")+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 90))+
  labs(title = "Precipitaciones Promedio por Región", x = "", y = "Prom. Precipitaciones (mm)")+
  facet_wrap(facets = ~region, scales = "free")

t1 <- df_datos %>% 
  ggplot(mapping = aes(x = departamento, y = temperaturas)) + 
  geom_boxplot(aes(fill = region))+
  facet_wrap(facets = ~region, scales = "free")+
  labs(title = "Temperatura por Región",
       x = "Departamento", y = "Temperatura °C")+
  theme(axis.text.x = element_text(angle = 90))+
  theme(legend.position = "none")

grid.arrange(p1 , t1, nrow = 2)


  • Algunos departamentos y sus municipios


df_datos %>%
  filter(departamento == c("Meta", "Bolívar", "Chocó", "Santander",
                           "Nariño", "Arauca")) %>% 
  group_by(departamento, municipio) %>% 
  summarise(tot_prep = mean(precipitaciones)) %>%
  ungroup() %>% 
  ggplot(mapping = aes(x = municipio, y = tot_prep))+
  geom_bar(fill = "seagreen4",stat = "identity")+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 90))+
  labs(title = "Precipitaciones Promedio por Municipio y Departamento", x = "", y = "Prom. Precipitaciones (mm)")+
  facet_wrap(facets = ~departamento, scales = "free")

7 Relación Bivariada

Es posible obtener los valores de Covarianza para las variables. Para el caso de las variables altitud y temperaturas, se tiene que la realación que hay entre ellas es lineal y negativa.

cov(x = df_datos$altitud, y = df_datos$temperaturas)
[1] -5247.848
df_datos %>% 
  ggplot(mapping = aes(y = temperaturas, x = altitud))+
  geom_point(aes(color = region))+
  geom_smooth()+
  scale_y_continuous(n.breaks = 8)+
  labs(title = "Altitud vs Temperatura", x = "Altitud (m.s.n.m)", y = "Temperaturas (°C)")+
  theme_bw()


df_datos %>% 
  group_by(departamento) %>% 
  summarise(prom_al = mean(altitud),
            prom_tem = mean(temperaturas)) %>% 
  ggplot(mapping = aes(x = prom_al, y = prom_tem))+
  geom_point(aes(color = departamento))+
  geom_smooth()+
  theme_bw()+
  labs(title = "Promedio de Altitud-Temperatura",
       subtitle = "Por Departamento",
       x = "Altitud (m.s.n.m)",
       y = "Temperatura °C",
       caption = "Cada punto representa un Departamento")+
  theme(legend.position = "none")

cov(x = df_datos$precipitaciones, y = df_datos$temperaturas)
[1] 143.5816
df_datos %>% 
  ggplot(mapping = aes(x = temperaturas, y = precipitaciones))+
  geom_point(aes(color = region))+
  geom_smooth()+
  labs(title = "Temperaturas vs Precipitaciones", x = "Temperaturas °C", y = "Precipitaciones (mm)")+
  theme_bw()

NA
df_datos %>% 
  group_by(departamento) %>% 
  summarise(prom_al = mean(precipitaciones),
            prom_tem = mean(temperaturas)) %>% 
  ggplot(mapping = aes(y = prom_al, x = prom_tem))+
  geom_point(aes(color = departamento))+
  geom_smooth()+
  theme_bw()+
  labs(title = "Promedio Temperatura-Precipitaciones",
       subtitle = "Por Departamento",
       y = "Precipitaciones (mm)",
       x = "Temperatura °C",
       caption = "Cada punto representa un Departamento")+
  theme(legend.position = "none")

df_datos %>%
  ggplot(mapping = aes(y = precipitaciones, x = temperaturas))+
  geom_point(color = "darkorange", alpha = 0.8)+
  geom_smooth()+
  labs(title = "Temparaturas y Precipitaciones",
       subtitle = "Individual por Departamento",
       x = "Temperaturas °C",
       y = "Precipitaciones (mm)")+
  theme_bw()+
  facet_wrap(facets = ~departamento, scales = "free", nrow = 8)

df_datos %>%
  ggplot(mapping = aes(y = precipitaciones, x = altitud))+
  geom_smooth()+
  labs(title = "Altitud y Precipitaciones",
       subtitle = "Regiones Naturales",
       x = "Altitud (m.s.n.m)",
       y = "Precipitaciones (mm)")+
  theme_bw()+
  facet_wrap(facets = ~region, scales = "free", nrow = 2)

  • Histograma 2d

  • Densidad 2d


7.1 Correlaciones

library(GGally)
ggpairs(df_datos, columns = c("precipitaciones", "temperaturas", "altitud"), ggplot2::aes(colour=region, alpha = 0.6))

ggcorr(df_datos, method = c("everything", "pearson")) 

8 Referencias

LS0tCnRpdGxlOiAiRWplbXBsbyBNYW5lam8gZGUgRGF0b3MgY29uIFIiCnN1YnRpdGxlOiAiUHJvbWVkaW9zIFByZWNpcGl0YWNpw7NuIHkgVGVtcGVyYXR1cmEgZW4gQ29sb21iaWEuIDE5ODEtMjAxMCIKYXV0aG9yOiAiQ1JHIgpkYXRlOiAiTm92aWVtYnJlLTIwMTgiCm91dHB1dDogCiAgICBodG1sX25vdGVib29rOiAKICAgICAgICB0b2M6IHRydWUKICAgICAgICB0b2NfZmxvYXQ6IHRydWUgCiAgICAgICAgdG9jX2RlcHRoOiAzIAogICAgICAgIGNvbGxhcHNlZDogdHJ1ZQogICAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUgCiAgICAgICAgdGhlbWU6IGNlcnVsZWFuCiAgICAgICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgICAgIGRmX3ByaW50OiBwYWdlZAogICAgICAgIGNzczogZWRpY2lvbi5jc3MKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGV2YWwgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIpCmBgYAoKCiMgSW50cm9kdWNjacOzbgoKTGEgYmFzZSBkZSBkYXRvcyBoYSBzaWRvIGNvbnN1bHRhZGEgZW4gbGEgcGFnaW5hIGRlIFtkYXRvcyBhYmllcnRvcyBkZWwgZ29iaWVybm8gZGUgQ29sb21iaWFdKGh0dHBzOi8vd3d3LmRhdG9zLmdvdi5jby8pIGR1cmFudGUgZWwgbWVzIGRlIE5vdmllbWJyZSBkZWwgYcOxbyAyMDE4LiBMb3MgZGF0b3MgY29udGllbmVuIGxhcyBkZSBwcmVjaXBpdGFjaW9uZXMgeSB0ZW1wZXJhdHVyYSBwcm9tZWRpYWRhcyBkZSBjYWRhIG1lcywgZHVyYW50ZSAzMCBhw7Fvcy4gCgpQb3IgZWplbXBsbywgbGEgdmFyaWFibGUgYHNlcHRlbXAzMGFgIGNvbnRpZW5lIGxhIHRlbXBlcmF0dXJhIHByb21lZGlvIGRlIDMwIGHDsW9zLCByZWdpc3RyYWRhIHBhcmEgZWwgbWVzIGRlIHNlcHRpZW1icmUgZHVyYW50ZSBlc29zIDMwIGHDsW9zLi4KClNlIGFwbGljYXLDoW4gYWxndW5hcyBmdW5jaW9uZXMgZGVsIHBhcXVldGUgdGlkeXZlcnNlIGVudHJlIG90cm9zIHBhcXVldGVzIHBhcmEgZXhwbG9yYXIgZWwgY29uanVudG8gZGUgZGF0b3MgeSBoYWNlciBsYSBkZXB1cmFjacOzbiBwZXJ0aW5lbnRlIGNvbiBlbCBvYmpldGl2byBkZSBlc3RydWN0dXJhciBsYSBpbmZvcm1hY2nDs24gZGUgZm9ybWEgdGFidWxhciwgeSBhc8OtIGhhY2VyIHVuIGFuw6FsaXNpcyBkZXNjcmlwdGl2byBkZSBsYXMgdmFyaWFibGVzLCBnZW5lcmFuZG8gZ3LDoWZpY29zIGNvbiBsYSBsaWJyZXLDrWEgYGdncGxvdDJgLgoKCgojIEJhc2UgZGUgRGF0b3MgT3JpZ2luYWwKCiMjIExlY3R1cmEKClByaW1lcm8gY2FyZ2Ftb3MgZWwgcGFxdWV0ZSBbdGlkeXZlcnNlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyksIGVsIGN1YWwgZXMgdW4gY29uanVudG8gZGUgcGFxdWV0ZXMgcXVlIHBlcm1pdGVuIGVsIG1hbmVqbyBkZSBiYXNlcyBkZSBkYXRvcyBkZSBtYW5lcmEgZWZpY2llbnRlLgoKTGEgZnVuY2nDs24gYHJlYWRfY3N2YCBsZWUgZWwgYXJjaGl2byBkZSBudWVzdHJvIGRpcmVjdG9yaW8gZGUgdHJhYmFqby4KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKZGF0b3MgPC0gcmVhZF9jc3YoZmlsZSA9ICJQcmVjaXBpdGFjaW9uVGVtcGVyYXR1cmFQcm9tZWRpby5jc3YiKQpgYGAKCiMjIEVzdHJ1Y3R1cmEgeSBSZXN1bWVuCgpMYSBmdW5jacOzbiBza2ltIGRlIGxhIGxpYnJlcsOtYSBbc2tpbXJdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9za2ltci9pbmRleC5odG1sKSBwZXJtaXRlIG9idGVuZXIgdW4gcmVzdW1lbiBkZSBsb3MgZGF0b3MgeSBjb25vY2VyIGRlIG1hbmVyYSBnZW5lcmFsIGxhIGVzdHJ1Y3R1cmEgZGUgbnVlc3Ryb3MgZGF0b3MuCgpgYGB7cn0KbGlicmFyeShza2ltcikKc2tpbShkYXRvcykKYGBgCgo8YnI+CgpTZSB0aWVuZW4gcGFyYSBlc3RhIGJhc2UgZGUgZGF0b3MgNDUwIGZpbGFzIHkgNDEgY29sdW1uYXMsIDcgY29sdW1uYXMgZGUgY2xhc2UgYGNoYXJhY3RlcmAgeSAzNCBkZSBjbGFzZSBgx7l1bWVyaWNgLiBMYSBkaW1lbnNpw7NuIGRlIGxhIGJhc2UgZGUgZGF0b3MgdGFtYmnDqW4gZXMgcG9zaWJsZSBvYnRlbmVybGEgY29uIGxhIGZ1bmNpw7NuIGBkaW0oKWAuCgpgYGB7cn0KZGltKGRhdG9zKQpgYGAKCgpFbCByZXN1bWVuIGFudGVyaW9yIG5vcyBhcnJvamEgdW5hIGlkZWEgZGVsIGNvbXBvcnRhbWllbnRvIGRlIGxhcyB2YXJpYWJsZXMgYWRlbcOhcyBkZSBlbnRyZWdhciBpbmZvcm1hY2nDs24gYWNlcmNhIGRlIGxvcyB2YWxvcmVzIGF1c2VudGVzIGBOQWAsIHF1ZSBwYXJhIGVzdGEgYmFzZSBkZSBkYXRvcyBlbiBwYXJ0aWN1bGFyIG5vIGhheS4gVW4gaGlzdG9ncmFtYSBjb24gbGEgZGlzdHJpYnVjacOzbiBkZSBsYXMgdmFyaWFibGVzIGVzIHJlcGVyZXNlbnRhZG8gZW4gZWwgcmVzdW1lbiwgZWwgY3VhbCB0YW1iacOpbiByZXByZXNlbnRhcmVtb3MgYSB0cmF2w6lzIGRlIGxhIGxpYnJlcsOtYSBbZ2dwbG90Ml0oaHR0cHM6Ly9nZ3Bsb3QyLWJvb2sub3JnLykgcGFyYSBjYWRhIHVuYSBkZSBsYXMgdmFyaWFibGVzLgoKVW5hIHLDoXBpZGEgY29uc3VsdGEgZGUgbG9zIHZhbG9yZXMgTkEgdGFtYmnDqW4gcHVlZGUgbG9ncmFyc2UgZGUgbGEgc2lndWllbnRlIG1hbmVyYS4gU29saWNpdGFtb3MgY29uIGxhIGZ1bmNpw7NuIGB0YWJsZSgpYCBlbCBjb250ZW8gZGUgbG9zIHZhbG9yZXMgTkEgYSB0cmF2w6lzIGRlIGxhIGZ1bmNpw7NuIGBpcy5uYSgpYC4KCmBgYHtyfQp0YWJsZShpcy5uYShkYXRvcykpCmBgYAoKCjxicj4KCiMjIFByZXNlbnRhY2nDs24gYmFzZSBkZSBkYXRvcy4KCmBgYHtyfQpkYXRvcwpgYGAKCjxicj4KCiMgRGVwdXJhY2nDs24gQmFzZSBkZSBEYXRvcwoKRXN0cnVjdHVyYXJlbW9zIHVuYSBiYXNlIGRlIGRhdG9zIHF1ZSBjb250ZW5nYSBsYSBpbmZvcm1hY2nDs24gcXVlIGNvbnNpZGVyZW1vcyByZWxldmFudGUgcGFyYSBlbCBhbsOhbGlzaXMgbyBleHBsb3JhY2nDs24gZGUgbGEgaW5mb3JtYWNpw7NuIHF1ZSBkZXNlYW1vcyBoYWNlci4KCiogU2VsZWNjacOzbiB2YXJpYWJsZXMgZGUgaW50ZXLDqXMuIAoqIFBhc2FyIGRlIGZvcm1hdG8gYW5jaG8gYSBmb3JtYXRvIGxhcmdvLgoqIEVkaXRhciBlbCBub21icmUgZGUgbG9zIG1lc2VzLgoqIENhbWJpYXIgbGEgdmFyaWFibGUgbWVzZXMgYSBmYWN0b3IuCiogQXNpZ25hciBsb3Mgbml2ZWxlcyBhIGxhIHZhcmlhYmxlIG1lc2VzLgoKRXN0YXMgYWNjaW9uZXMgcXVlIHNlIG1lbmNpb25hbiwgc2UgcHVlZGVuIGVqZWN1dGFyIGEgdHJhdsOpcyBkZWwgb3BlcmFkb3IgYCAlPiUgYCBjb25vY2lkbyBjb21vIHR1YmVyw61hICgqcGlwZSopLCBxdWUgcGVybWl0ZSBlbmNhZGVuYXIgdmFyaW9zIGNvbWFuZG9zIG8gZnVuY2lvbmVzICBwYXJhIHF1ZSBzZSBlamVjdXRlbiB1bm8gc2VndWlkbyBkZSBvdHJvLgoKCiMjIERhdG9zIFByZWNpcGl0YWNpb25lcwoKT2J0ZW5kcmVtb3MgdW4gb2JqZXRvIGxsYW1hZG8gcHJlY2lwLCBxdWUgY29udGllbmUgbGFzIHByZWNpcGl0YWNpb25lcyBkZSBsb3MgbXVuaWNpcGlvcyBwb3IgbWVzLgoKYGBge3J9CnByZWNpcCA8LSBkYXRvcyAlPiUgCiAgIyBzZWxlY2Npb25hciBsYXMgdmFyaWFibGVzCiAgc2VsZWN0KGRlcGFydGFtZW50bywgbXVuaWNpcGlvLCBhbHRpdHVkOmRpY3ByZWNpMzBhKSAlPiUgCiAgIyBwYXNhciBkZSBmb3JtYXRvIGxhcmdvIGEgYW5jaG8KICBwaXZvdF9sb25nZXIoY29scyA9IGMoZW5lcHJlY2kzMGE6ZGljcHJlY2kzMGEpLCBuYW1lc190byA9ICJtZXMiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAicHJlY2lwaXRhY2lvbmVzIikgJT4lCiAgIyBlZGl0YXIgbm9tYnJlcyBkZSBsYSB2YXJpYWJsZSBtZXMKICBtdXRhdGUobWVzID0gZ3N1YihwYXR0ZXJuID0gImVuZXByZWNpMzBhIiwgcmVwbGFjZW1lbnQgPSAiZW5lcm8iLCB4ID0gbWVzKSwKICAgICAgICAgbWVzID0gZ3N1YihwYXR0ZXJuID0gImZlYnByZWNpMzBhIiwgcmVwbGFjZW1lbnQgPSAiZmVicmVybyIsIHggPSBtZXMpLAogICAgICAgICBtZXMgPSBnc3ViKHBhdHRlcm4gPSAibWFycHJlY2kzMGEiLCByZXBsYWNlbWVudCA9ICJtYXJ6byIsIHggPSBtZXMpLAogICAgICAgICBtZXMgPSBnc3ViKHBhdHRlcm4gPSAiYWJycHJlY2kzMGEiLCByZXBsYWNlbWVudCA9ICJhYnJpbCIsIHggPSBtZXMpLAogICAgICAgICBtZXMgPSBnc3ViKHBhdHRlcm4gPSAibWF5cHJlY2kzMGEiLCByZXBsYWNlbWVudCA9ICJtYXlvIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGdzdWIocGF0dGVybiA9ICJqdW5wcmVjaTMwYSIsIHJlcGxhY2VtZW50ID0gImp1bmlvIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGdzdWIocGF0dGVybiA9ICJqdWxwcmVjaTMwYSIsIHJlcGxhY2VtZW50ID0gImp1bGlvIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGdzdWIocGF0dGVybiA9ICJhZ29wcmVjaTMwYSIsIHJlcGxhY2VtZW50ID0gImFnb3N0byIsIHggPSBtZXMpLAogICAgICAgICBtZXMgPSBnc3ViKHBhdHRlcm4gPSAic2VwcHJlY2kzMGEiLCByZXBsYWNlbWVudCA9ICJzZXB0aWVtYnJlIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGdzdWIocGF0dGVybiA9ICJvY3RwcmVjaTMwYSIsIHJlcGxhY2VtZW50ID0gIm9jdHVicmUiLCB4ID0gbWVzKSwKICAgICAgICAgbWVzID0gZ3N1YihwYXR0ZXJuID0gIm5vdnByZWNpMzBhIiwgcmVwbGFjZW1lbnQgPSAibm92aWVtYnJlIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGdzdWIocGF0dGVybiA9ICJkaWNwcmVjaTMwYSIsIHJlcGxhY2VtZW50ID0gImRpY2llbWJyZSIsIHggPSBtZXMpLAogICAgICAgICAjIGNvbnZlcnRpciBsYSB2YXJpYWJsZSBtZXMgZW4gZmFjdG9yCiAgICAgICAgIG1lcyA9IGZhY3Rvcih4ID0gbWVzLCBsZXZlbHMgPSBjKCJlbmVybyIsICJmZWJyZXJvIiwgIm1hcnpvIiwgImFicmlsIiwgIm1heW8iLCAianVuaW8iLCAianVsaW8iLCAiYWdvc3RvIiwgInNlcHRpZW1icmUiLCAib2N0dWJyZSIsICJub3ZpZW1icmUiLCAiZGljaWVtYnJlIikpKQoKYGBgCgoKYGBge3J9CnByZWNpcApgYGAKCgpgYGB7cn0KZGltKHByZWNpcCkKYGBgCgoKIyMgRGF0b3MgVGVtcGVyYXR1cmFzCgpPYnRlbmRyZW1vcyBlbCBvYmpldG8gcXVlIGNvbnRlbmdhIGxhIGluZm9ybWFjacOzbiBkZSBsYXMgdGVtcGVyYXR1cmFzIGRlIGxvcyBtdW5pY2lwaW9zIHBvciBtZXMuIAoKYGBge3J9CnRlbXBlIDwtIGRhdG9zICU+JSAKICBzZWxlY3QoZGVwYXJ0YW1lbnRvLCBtdW5pY2lwaW8sIGFsdGl0dWQsIGVuZXRlbXAzMGE6ZGljdGVtcDMwYSkgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gYyhlbmV0ZW1wMzBhOmRpY3RlbXAzMGEpLCBuYW1lc190byA9ICJtZXMiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidGVtcGVyYXR1cmFzIikgJT4lIAogIG11dGF0ZShtZXMgPSBnc3ViKHBhdHRlcm4gPSAiZW5ldGVtcDMwYSIsIHJlcGxhY2VtZW50ID0gImVuZXJvIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGdzdWIocGF0dGVybiA9ICJmZWJ0ZW1wMzBhIiwgcmVwbGFjZW1lbnQgPSAiZmVicmVybyIsIHggPSBtZXMpLAogICAgICAgICBtZXMgPSBnc3ViKHBhdHRlcm4gPSAibWFydGVtcDMwYSIsIHJlcGxhY2VtZW50ID0gIm1hcnpvIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGdzdWIocGF0dGVybiA9ICJhYnJ0ZW1wMzBhIiwgcmVwbGFjZW1lbnQgPSAiYWJyaWwiLCB4ID0gbWVzKSwKICAgICAgICAgbWVzID0gZ3N1YihwYXR0ZXJuID0gIm1heXRlbXAzMGEiLCByZXBsYWNlbWVudCA9ICJtYXlvIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGdzdWIocGF0dGVybiA9ICJqdW50ZW1wMzBhIiwgcmVwbGFjZW1lbnQgPSAianVuaW8iLCB4ID0gbWVzKSwKICAgICAgICAgbWVzID0gZ3N1YihwYXR0ZXJuID0gImp1bHRlbXAzMGEiLCByZXBsYWNlbWVudCA9ICJqdWxpbyIsIHggPSBtZXMpLAogICAgICAgICBtZXMgPSBnc3ViKHBhdHRlcm4gPSAiYWdvdGVtcDMwYSIsIHJlcGxhY2VtZW50ID0gImFnb3N0byIsIHggPSBtZXMpLAogICAgICAgICBtZXMgPSBnc3ViKHBhdHRlcm4gPSAic2VwdGVtcDMwYSIsIHJlcGxhY2VtZW50ID0gInNlcHRpZW1icmUiLCB4ID0gbWVzKSwKICAgICAgICAgbWVzID0gZ3N1YihwYXR0ZXJuID0gIm9jdHRlbXAzMGEiLCByZXBsYWNlbWVudCA9ICJvY3R1YnJlIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGdzdWIocGF0dGVybiA9ICJub3Z0ZW1wMzBhIiwgcmVwbGFjZW1lbnQgPSAibm92aWVtYnJlIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGdzdWIocGF0dGVybiA9ICJkaWN0ZW1wMzBhIiwgcmVwbGFjZW1lbnQgPSAiZGljaWVtYnJlIiwgeCA9IG1lcyksCiAgICAgICAgIG1lcyA9IGZhY3Rvcih4ID0gbWVzLCBsZXZlbHMgPSBjKCJlbmVybyIsICJmZWJyZXJvIiwgIm1hcnpvIiwgImFicmlsIiwgIm1heW8iLCAianVuaW8iLCAianVsaW8iLCAiYWdvc3RvIiwgInNlcHRpZW1icmUiLCAib2N0dWJyZSIsICJub3ZpZW1icmUiLCAiZGljaWVtYnJlIikpKQoKYGBgCgpgYGB7cn0KdGVtcGUKYGBgCgoKCmBgYHtyfQpkaW0odGVtcGUpCmBgYAoKCiMjIFVuaXIgbG9zIERhdG9zCgpVbmlyZW1vcyBsb3MgZG9zIG9iamV0b3MgcXVlIGNyZWFtb3MgcGFyYSBjb25zb2xpZGFyIHVuYSDDum5pY2EgYmFzZSBkZSBkYXRvcyBxdWUgY29udGVuZ2EgbG9zIGRhdG9zIGRlIHByZWNpcGl0YWNpw7NuIHkgdGVtcGVyYXR1cmEuIExhcyBmdW5jacOzbiBgcmlnaHRfam9pbigpYCBwZXJtaXRlIHVuaXIgY29sdW1uYXMgYSBsYSBiYXNlIGRlIGRhdG9zLCBlbiBlc3RlIGNhc28gYSBsYSBkZXJlY2hhIGRlIG51ZXN0cm8gYXJyZWdsbyB0YWJ1bGFyIHBhcmEgYWdyZWdhciBsYSBjb2x1bW5hIGNvbiBsYXMgdGVtcGVyYXR1cmFzLgoKYGBge3J9CmRmX3ByZXRlbSA8LSByaWdodF9qb2luKHggPSBwcmVjaXAsIHkgPSB0ZW1wZSkKYGBgCgo8YnI+CgpgYGB7cn0KZGZfcHJldGVtCmBgYAoKCiMjIEVkaXRhciBEZXBhcnRhbWVudG9zIHkgQ3JlYXIgUmVnaW9uZXMKClNlIGVkaXRhcsOhbiBsb3Mgbm9tYnJlcyBkZSBhbGd1bm9zIGRlcGFydGFtZW50b3MgcXVlIHByZXNlbnRhbiBlcnJvcmVzIGRlIG9ydG9ncmFmw61hIHBhcmEgcHJlc2VudGFybG9zIGRlIG1hbmVyYSBjb3JyZWN0YS4KClNlIG9idGVuZHLDoSB1bmEgbnVldmEgY29sdW1uYSBjb24gbGFzIHJlZ2lvbmVzIG5hdHVyYWxlcyBkZSBDb2xvbWJpYSBhIGxhIHF1ZSBwZXJ0ZW5lY2VuIGxvcyBkaWZlcmVudGVzIGRlcGFydGFtZW50b3MsIGNvbmZvcm1hZGFzIGRlIGxhIHNpZ3VpZW50ZSBtYW5lcmE6CgoqICpSZWdpw7NuIFBhY8OtZmljbyogOiBDYXVjYSAsIENob2PDsywgTmFyacOxbywgVmFsbGUgZGVsIENhdWNhCgoqICpSZWdpw7NuIE9yaW5vcXXDrWEqIDogQXJhdWNhLCBDYXNhbmFyZSwgTWV0YSwgVmljaGFkYQoKKiAqUmVnacOzbiBBbWF6b27DrWEqIDogQW1hem9uYXMsIENhcXVldMOhLCBHdWFpbsOtYSwgR3VhdmlhcmUsIFB1dHVtYXlvLiAoRWwgZGVwYXJ0YW1lbnRvIGRlIFZhdXDDqXMgbm8gYXBhcmVjZSBlbiBsb3MgZGF0b3Mgb3JpZ2luYWxlcywgcG9yIGxvIHRhbnRvIG5vIGFwYXJlY2UgYXF1w60gcmVwcmVzZW50YWRvKS4KCiogKlJlZ2nDs24gQ2FyaWJlKiA6IEF0bMOhbnRpY28sIEJvbMOtdmFyLCBDZXNhciwgQ29yZG9iYSwgTGEgR3VhamlyYSwgTWFnZGFsZW5hLCBTYW4gQW5kcsOpcyBQcm92aWRlbmNpYSB5IFNhbnRhIENhdGFsaW5hLCBTdWNyZS4KCiogKlJlZ2nDs24gQW5kaW5hKiA6IEFudGlvcXVpYSwgQm95YWPDoSwgQ2FsZGFzLCBDdW5kaW5hbWFyY2EsIEh1aWxhLCBOb3J0ZSBkZSBTYW50YW5kZXIsIFF1aW5kw61vLCBSaXNhcmFsZGEsIFNhbnRhbmRlciwgVG9saW1hLCBCb2dvdMOhIERDLgoKKkxhIHJlZ2nDs24gaW5zdWxhciBubyBzZSBwcmVzZW50YSBlbiBsb3MgZGF0b3MuIFJlZ2nDs24gYSBsYSBjdWFsIHBlcnRlbmVjZSBTYW4gQW5kcsOpcywgUHJvdmlkZW5jaWEgeSBTYW50YSBDYXRhbGluYS4qCgpgYGB7cn0KZGZfcHJldGVtIDwtIGRmX3ByZXRlbSAlPiUgCiAgbXV0YXRlKGRlcGFydGFtZW50byA9IGdzdWIocGF0dGVybiA9ICJBdGxhbnRpY28iLCByZXBsYWNlbWVudCA9ICJBdGzDoW50aWNvIiwgeCA9IGRlcGFydGFtZW50byksCiAgICAgICAgIGRlcGFydGFtZW50byA9IGdzdWIocGF0dGVybiA9ICJCb2dvdGEgREMiLCByZXBsYWNlbWVudCA9ICJCb2dvdMOhIERDIiwgeCA9IGRlcGFydGFtZW50byksCiAgICAgICAgIGRlcGFydGFtZW50byA9IGdzdWIocGF0dGVybiA9ICJCb2xpdmFyIiwgcmVwbGFjZW1lbnQgPSAiQm9sw612YXIiLCB4ID0gZGVwYXJ0YW1lbnRvKSwKICAgICAgICAgZGVwYXJ0YW1lbnRvID0gZ3N1YihwYXR0ZXJuID0gIkJveWFjYSIsIHJlcGxhY2VtZW50ID0gIkJveWFjw6EiLCB4ID0gZGVwYXJ0YW1lbnRvKSwKICAgICAgICAgZGVwYXJ0YW1lbnRvID0gZ3N1YihwYXR0ZXJuID0gIkNhcXVldGEiLCByZXBsYWNlbWVudCA9ICJDYXF1ZXTDoSIsIHggPSBkZXBhcnRhbWVudG8pLAogICAgICAgICBkZXBhcnRhbWVudG8gPSBnc3ViKHBhdHRlcm4gPSAiQ2hvY28iLCByZXBsYWNlbWVudCA9ICJDaG9jw7MiLCB4ID0gZGVwYXJ0YW1lbnRvKSwKICAgICAgICAgZGVwYXJ0YW1lbnRvID0gZ3N1YihwYXR0ZXJuID0gIkNvcmRvYmEiLCByZXBsYWNlbWVudCA9ICJDw7NyZG9iYSIsIHggPSBkZXBhcnRhbWVudG8pLAogICAgICAgICBkZXBhcnRhbWVudG8gPSBnc3ViKHBhdHRlcm4gPSAiR3VhaW5pYSIsIHJlcGxhY2VtZW50ID0gIkd1YWluw61hIiwgeCA9IGRlcGFydGFtZW50byksCiAgICAgICAgIGRlcGFydGFtZW50byA9IGdzdWIocGF0dGVybiA9ICJOYXJpbm8iLCByZXBsYWNlbWVudCA9ICJOYXJpw7FvIiwgeCA9IGRlcGFydGFtZW50byksCiAgICAgICAgIGRlcGFydGFtZW50byA9IGdzdWIocGF0dGVybiA9ICJRdWluZGlvIiwgcmVwbGFjZW1lbnQgPSAiUXVpbmTDrW8iLCB4ID0gZGVwYXJ0YW1lbnRvKSwKICAgICAgICAgZGVwYXJ0YW1lbnRvID0gZ3N1YihwYXR0ZXJuID0gIlNhbiBBbmRyZXMgUHJvdmlkZW5jaWEgeSBTdGEgQyIsIHJlcGxhY2VtZW50ID0gIlMuQW5kcsOpcy1Qcm92aWQuLVN0YS5DYXQuIiwgeCA9IGRlcGFydGFtZW50bykpICU+JQogIG11dGF0ZShyZWdpb24gPSBpZmVsc2UoZGVwYXJ0YW1lbnRvICVpbiUgYygiQ2F1Y2EiLCAiQ2hvY8OzIiwgIk5hcmnDsW8iLCAiVmFsbGUgZGVsIENhdWNhIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAiUmVnacOzbiBQYWPDrWZpY28iLAogICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGRlcGFydGFtZW50byAlaW4lIGMoIkFyYXVjYSIsICJDYXNhbmFyZSIsICJNZXRhIiwgIlZpY2hhZGEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVnacOzbiBPcmlub3F1w61hIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZGVwYXJ0YW1lbnRvICVpbiUgYygiQW1hem9uYXMiLCAiQ2FxdWV0w6EiLCAiR3VhaW7DrWEiLCAiR3VhdmlhcmUiLCAiUHV0dW1heW8iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2nDs24gQW1hem9uYXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZGVwYXJ0YW1lbnRvICVpbiUgYygiQXRsw6FudGljbyIsICJCb2zDrXZhciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2VzYXIiLCAiQ8OzcmRvYmEiLCAiTGEgR3VhamlyYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNYWdkYWxlbmEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUy5BbmRyw6lzLVByb3ZpZC4tU3RhLkNhdC4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3VjcmUiKSwgIlJlZ2nDs24gQ2FyaWJlIiwgIlJlZ2nDs24gQW5kaW5hIikpKSkpCmBgYAoKYGBge3J9CmhlYWQoZGZfcHJldGVtKQpgYGAKCgpgYGB7cn0KZGltKGRmX3ByZXRlbSkKYGBgCgo8YnI+CgoKCjxicj4KCiMjIEV4cG9ydGFyIEJhc2UgZGUgRGF0b3MKCkZpbmFsbWVudGUgZGVzcHXDqXMgZGUgbGEgZGVwdXJhY2nDs24geSBhc2VndXJhciBxdWUgbGEgYmFzZSBkZSBkYXRvcyBlc3TDoSBjb21vIHNlIGRlc2VhLCBzZSBndWFyZGFyw6EgbGEgYmFzZSBkZSBkYXRvcyBlbiBlbCBkaXJlY3RvcmlvIGRlIHRyYWJham8gZW4gZm9ybWF0byBjc3YgY29uIGVsIG5vbWJyZSAqKnByZWNpcGl0YWNpb25lc190ZW1wZXJhdHVyYXMuY3N2KiouCgpgYGB7ciwgZXZhbD1GQUxTRX0Kd3JpdGVfY3N2KHggPSBkZl9wcmV0ZW0sIGZpbGUgPSAicHJlY2lwaXRhY2lvbmVzX3RlbXBlcmF0dXJhcy5jc3YiKQpgYGAKCgo8YnI+CgojIFByZXNlbnRhY2nDs24gZGUgTnVldm9zIERhdG9zCgpWZWFtb3MgbGEgZXN0cnVjdHVyYSBkZSBsYSBiYXNlIGRlIGRhdG9zIHF1ZSBjb250cnVpbW9zLiBIYWdhbW9zIGxhIGxlY3R1cmEgcGFyYSByZWFsaXphciB1biByZXN1bWVuIGRlIGxvcyBkYXRvcy4KCgpgYGB7cn0KZGZfZGF0b3MgPC0gcmVhZF9jc3YoZmlsZSA9ICJwcmVjaXBpdGFjaW9uZXNfdGVtcGVyYXR1cmFzLmNzdiIpCmBgYAoKPGJyPgoKYGBge3J9CmRmX2RhdG9zCmBgYAoKCmBgYHtyfQpza2ltKGRmX2RhdG9zKQpgYGAKPGJyPgoKIyMgRWRpdGFyIE1lcwoKRWRpdGFyZW1vcyBsb3Mgbm9tYnJlcyBkZSBsb3MgbWVzZXMsIHBvbmRyZW1vcyBsYSBwcmltZXJhIGxldHJhIGRlbCBtZXMgZW4gbWF5w7pzY3VsYS4uICgqU2UgaGFyw6FuIGxvcyBjYW1iaW9zIHBlcm8gbm8gc2UgZ3VhcmRhcsOhbiBlbiBsYSBiYXNlIGRlIGRhdG9zLCBzZSBoYXLDoW4gcGFyYSBtb3N0cmFyIGVsIHVzbyBkZSBsYXMgZnVuY2lvbmVzLiopCgpQYXJhIHBvbmVyIGxhIHByaW1lcmEgbGV0cmEgZW4gbWF5w7pzY3VsYSBkZSB1bmEgY2FkZW5hIGRlIGNhcmFjdGVyZXMsIHNlIHVzYSBsYSBmdW5jacOzbiBgY2FwaXRhbGl6ZWAgZGVsIHBhcXVldGUgYEhtaXNjYC4KCjxicj4KCmBgYHtyLCBldmFsPUZBTFNFfQpsaWJyYXJ5KEhtaXNjKQpjYXBpdGFsaXplKGRmX2RhdG9zJG1lcykKYGBgCgo8YnI+CgojIyBFeHBsb3JhY2nDs24gZGUgbGFzIFZhcmlhYmxlcwoKT2J0ZW5nYW1vcyBhbGd1bmFzIGVzdGFkw61zdGljYXMgY29uIGxvcyBwYXF1ZXRlIGJhc2UgZGUgUiBwYXJhIGxhIHZhcmlhYmxlIHByZWNpcGl0YWNpb25lczoKCiogbWVkaWEKCmBgYHtyfQptZWFuKGRmX2RhdG9zJHByZWNpcGl0YWNpb25lcykKYGBgCgoqIG1lZGlhbmEKCmBgYHtyfQptZWRpYW4oZGZfZGF0b3MkcHJlY2lwaXRhY2lvbmVzKQpgYGAKCiogcXVhcnRpbGVzCgpgYGB7cn0KcXVhbnRpbGUoZGZfZGF0b3MkcHJlY2lwaXRhY2lvbmVzKQpgYGAKCiogZGVjaWxlcwoKYGBge3J9CnF1YW50aWxlKGRmX2RhdG9zJHByZWNpcGl0YWNpb25lcywgcHJvYnMgPSBzZXEoZnJvbSA9IDAuMSwgdG8gPSAxLCBieSA9IDAuMSkpCmBgYAoKCiogZGVzdmlhY2nDs24gZXN0w6FuZGFyCgpgYGB7cn0Kc2QoZGZfZGF0b3MkcHJlY2lwaXRhY2lvbmVzKQpgYGAKCgoqIGNvZWZpY2llbnRlIGRlIHZhcmlhY2nDs24KCmBgYHtyfQpzZChkZl9kYXRvcyRwcmVjaXBpdGFjaW9uZXMpL21lYW4oZGZfZGF0b3MkcHJlY2lwaXRhY2lvbmVzKQpgYGAKCgoqIGt1cnRvc2lzCgpgYGB7cn0KIyBQYXF1ZXRlIGNvbiBmdW5jacOzbiBwYXJhIGhhbGxhciBrdXJ0b3NpcyBkZSB1biBjb25qdW50byBkZSBkYXRvcy4KbGlicmFyeShtb21lbnRzKQprdXJ0b3NpcyhkZl9kYXRvcyRwcmVjaXBpdGFjaW9uZXMpCmBgYAoKCiogVmFyaWFuemEKCmBgYHtyfQp2YXIoZGZfZGF0b3MkcHJlY2lwaXRhY2lvbmVzKQpgYGAKCgojIyBEaXN0cmlidWNpw7NuIGRlIGxhcyB2YXJpYWJsZXMKCjxicj4KCmBgYHtyLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9OX0KbGlicmFyeShncmlkRXh0cmEpCgpnMSA8LSBkZl9kYXRvcyAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IHByZWNpcGl0YWNpb25lcykpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksCiAgICAgICAgICAgICAgICAgY29sb3VyID0gMSwgZmlsbCA9ICJmaXJlYnJpY2syIikgKwogIGdlb21fZGVuc2l0eShsd2QgPSAxLCBjb2xvdXIgPSA0LAogICAgICAgICAgICAgICBmaWxsID0gNCwgYWxwaGEgPSAwLjMpKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHF1YW50aWxlKGRmX2RhdG9zJHByZWNpcGl0YWNpb25lcyksCiAgICAgICAgICAgICBsaW5ldHlwZT0nZGFzaGVkJykrCiAgc2NhbGVfeF9jb250aW51b3VzKG4uYnJlYWtzID0gMTApKwogIGxhYnModGl0bGUgPSAiRGVuc2lkYWQgLSBIaXN0b2dyYW1hIGRlIFByZWNpcGl0YWNpb25lcyIsCiAgICAgICB4ID0gIlByZWNpcGl0YWNpb25lcyAobW0pIiwKICAgICAgIHkgPSAiRGVuc2lkYWQiKSsKICB0aGVtZV9idygpCgpnMiA8LSBkZl9kYXRvcyAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IHByZWNpcGl0YWNpb25lcykpKwogIGdlb21fYm94cGxvdChmaWxsID0gImZpcmVicmljazIiLCBhbHBoYSA9IDAuOCkrCiAgbGFicyh0aXRsZSA9ICJCb3hwbG90IFByZWNpcGl0YWNpb25lcyIsCiAgICAgICB4ID0gIlByZWNpcGl0YWNpb25lcyAobW0pIiwgeSA9ICIiKSsKICBzY2FsZV94X2NvbnRpbnVvdXMobi5icmVha3MgPSAxMCkrCiAgdGhlbWVfYncoKQoKZzMgPC0gZGZfZGF0b3MgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSB0ZW1wZXJhdHVyYXMpKSArIAogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLAogICAgICAgICAgICAgICAgIGNvbG91ciA9IDEsIGZpbGwgPSAicHVycGxlIikgKwogIGdlb21fZGVuc2l0eShsd2QgPSAxLCBjb2xvdXIgPSAib3JhbmdlIiwKICAgICAgICAgICAgICAgZmlsbCA9ICJvcmFuZ2UiLCBhbHBoYSA9IDAuMykrCiAgc2NhbGVfeF9jb250aW51b3VzKG4uYnJlYWtzID0gMTUpKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHF1YW50aWxlKGRmX2RhdG9zJHRlbXBlcmF0dXJhcyksCiAgICAgICAgICAgICBsaW5ldHlwZT0nZGFzaGVkJykrCiAgbGFicyh0aXRsZSA9ICJEZW5zaWRhZCAtIEhpc3RvZ3JhbWEgZGUgVGVtcGVyYXR1cmFzIiwKICAgICAgIHggPSAiVGVtcGVyYXR1cmFzIMKwQyIsCiAgICAgICB5ID0gIkRlbnNpZGFkIikrCiAgdGhlbWVfYncoKQoKZzQgPC0gZGZfZGF0b3MgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSB0ZW1wZXJhdHVyYXMpKSsKICBnZW9tX2JveHBsb3QoZmlsbCA9ICJwdXJwbGUiLCBhbHBoYSA9IDAuOCkrCiAgbGFicyh0aXRsZSA9ICJCb3hwbG90IFRlbXBlcmF0dXJhcyIsCiAgICAgICB4ID0gIlRlbXBlcmF0dXJhcyDCsEMiLCB5ID0gIiIpKwogIHNjYWxlX3hfY29udGludW91cyhuLmJyZWFrcyA9IDE1KSsKICB0aGVtZV9idygpCgpnNSA8LSBkZl9kYXRvcyAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IGFsdGl0dWQpKSArIAogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLAogICAgICAgICAgICAgICAgIGNvbG91ciA9IDEsIGZpbGwgPSAic2xhdGVncmF5IikgKwogIGdlb21fZGVuc2l0eShsd2QgPSAxLCBjb2xvdXIgPSAzLAogICAgICAgICAgICAgICBmaWxsID0gNCwgYWxwaGEgPSAwLjMpKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHF1YW50aWxlKGRmX2RhdG9zJGFsdGl0dWQpLAogICAgICAgICAgICAgbGluZXR5cGU9J2Rhc2hlZCcpKwogIHNjYWxlX3hfY29udGludW91cyhuLmJyZWFrcyA9IDEwKSsKICBsYWJzKHRpdGxlID0gIkRlbnNpZGFkIC0gSGlzdG9ncmFtYSBkZSBBbHRpdHVkIiwKICAgICAgIHggPSAiQWx0aXR1ZCAobSkpIiwKICAgICAgIHkgPSAiRGVuc2lkYWQiKSsKICB0aGVtZV9idygpCgpnNiA8LSBkZl9kYXRvcyAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IGFsdGl0dWQpKSsKICBnZW9tX2JveHBsb3QoZmlsbCA9ICJzbGF0ZWdyYXkiLCBhbHBoYSA9IDAuOCkrCiAgbGFicyh0aXRsZSA9ICJCb3hwbG90IEFsdGl0dWQiLAogICAgICAgeCA9ICJBbHRpdHVkIChtKSIsIHkgPSAiIikrCiAgc2NhbGVfeF9jb250aW51b3VzKG4uYnJlYWtzID0gMTApKwogIHRoZW1lX2J3KCkKCmdyaWQuYXJyYW5nZShnMSwgZzIsIGczLCBnNCwgZzUsIGc2LCBucm93PTMpCmBgYAo8YnI+CgojIFJlc3VtZW4gTnVtw6lyaWNvIHBvciBEZXBhcnRhbWVudG8KCiMjIFJlc3VtZW4gUHJlY2lwaXRhY2lvbmVzCgpTZSBvYnRlbmRyw6EgdW4gcmVzdW1lbiBudW3DqXJpY28gZGUgbGFzIHZhcmlhYmxlcyBlbiBmb3JtYSB0YWJ1bGFyIHBhcmEgY2FkYSBkZXBhcnRhbWVudG8uIFNlIG9idGVuZHLDoW4gZWwgcHJvbWVkaW8sIGxhIG1lZGlhbmEsIGVsIHZhbG9yIG3DoXhpbW8sIGVsIHZhbG9yIG3DrW5pbW8sIGxhIGRlc3ZpYWNpw7NuIGVzdMOhbmRhciwgZWwgY29lZmljaWVudGUgZGUgdmFyaWFjacOzbiwga3VydG9zaXMgeSBsb3MgcXVhcnRpbGVzIDI1LCA1MCB5IDc1LgoKVGFtYmnDqW4gZXMgcG9zaWJsZSBvYnRlbmVyIGVsIHJlc3VtZW4gcGFyYSBjYWRhIG11bmljaXBpbywgYmFzdGEgY29uIGFncnVwYXIgbG9zIGRhdG9zIHBvciBtdW5pY2lwaW8geSBvYnRlbmVyIGxhcyBlc3RhZMOtc3RpY2FzIHF1ZSBzZSBkZXNlZS4KCgoKCmBgYHtyfQpkZl9kYXRvcyAlPiUKICAjIGFncnVwYXIgcG9yIGRlcGFydGFtZW50bwogIGdyb3VwX2J5KGRlcGFydGFtZW50bykgJT4lCiAgIyBvYnRlbmVyIGVzdGFkw61zdGljYXMKICBzdW1tYXJpc2UocHJvbV9wcmUgPSBtZWFuKHByZWNpcGl0YWNpb25lcyksCiAgICAgICAgICAgIG1lZF9wcmUgPSBtZWRpYW4ocHJlY2lwaXRhY2lvbmVzKSwKICAgICAgICAgICAgbWF4X3ByZSA9IG1heChwcmVjaXBpdGFjaW9uZXMpLAogICAgICAgICAgICBtaW5fcHJlID0gbWluKHByZWNpcGl0YWNpb25lcyksCiAgICAgICAgICAgIGRlX3ByZSA9IHNkKHByZWNpcGl0YWNpb25lcyksCiAgICAgICAgICAgIHAyNSA9IHF1YW50aWxlKHByZWNpcGl0YWNpb25lcywgcHJvYnMgPSAwLjI1KSwKICAgICAgICAgICAgcDUwID0gcXVhbnRpbGUocHJlY2lwaXRhY2lvbmVzLCBwcm9icyA9IDAuNSksCiAgICAgICAgICAgIHA3NSA9IHF1YW50aWxlKHByZWNpcGl0YWNpb25lcywgcHJvYnMgPSAwLjc1KSwKICAgICAgICAgICAgY3YgPSByb3VuZChzZChwcmVjaXBpdGFjaW9uZXMpL21lYW4ocHJlY2lwaXRhY2lvbmVzKSwgZGlnaXRzID0gMiksCiAgICAgICAgICAgIEt1cnQgPSBrdXJ0b3NpcyhwcmVjaXBpdGFjaW9uZXMpKQpgYGAKPGJyPgoKQSB0cmF2w6lzIGRlbCBkaWFncmFtYSBkZSBjYWphIGVzIHBvc2libGUgcmVzdW1pciBkZSBtYW5lcmEgZ3LDoWZpY2EgYWxndW5hcyBkZSBsYXMgZXN0YWTDrXRpY2FzIG9idGVuaWRhcy4gSGFjaWVuZG8gdXNvIGRlIGxhIHR1YmVyw61hIGAlPiVgIGVzIHBvc2libGUgZW5jYWRlbmFyIGPDs2RpZ28gcGFyYSBoYWNlciBvcGVyYWNpb25lcyBzb2JyZSBsb3MgZGF0b3MgeSBkZXNwdcOpcyBncmFmaWNhci4KCmBgYHtyLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD02fQpkZl9kYXRvcyAlPiUgCmdncGxvdChtYXBwaW5nID0gYWVzKHggPSBkZXBhcnRhbWVudG8sIHkgPSBwcmVjaXBpdGFjaW9uZXMpKSsKZ2VvbV9ib3hwbG90KGZpbGwgPSAic2xhdGVncmF5IikrCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIFByZWNpcGl0YWNpb25lcyBwb3IgRGVwYXJ0YW1lbnRvIiwKICAgICAgIHggPSAiRGVwYXJ0YW1lbnRvIiwgeSA9ICJQcmVjaXBpdGFjaW9uZXMgKG1tKSIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSkpCmBgYAoKPGJyPgoKIyMgUmVzdW1lbiBUZW1wZXJhdHVyYXMKCmBgYHtyfQpkZl9kYXRvcyAlPiUgCiAgZ3JvdXBfYnkoZGVwYXJ0YW1lbnRvKSAlPiUgCiAgc3VtbWFyaXNlKHByb21fcHJlID0gbWVhbih0ZW1wZXJhdHVyYXMpLAogICAgICAgICAgICBtZWRfcHJlID0gbWVkaWFuKHRlbXBlcmF0dXJhcyksCiAgICAgICAgICAgIG1heF9wcmUgPSBtYXgodGVtcGVyYXR1cmFzKSwKICAgICAgICAgICAgbWluX3ByZSA9IG1pbih0ZW1wZXJhdHVyYXMpLAogICAgICAgICAgICBkZV9wcmUgPSBzZCh0ZW1wZXJhdHVyYXMpLAogICAgICAgICAgICBjdiA9IHJvdW5kKHNkKHRlbXBlcmF0dXJhcykvbWVhbih0ZW1wZXJhdHVyYXMpLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAga3VydCA9IGt1cnRvc2lzKHRlbXBlcmF0dXJhcykpCmBgYAoKPGJyPgoKUGFyYSBlbCBncsOhZmljbyBkZSBsYXMgdGVtcGVyYXR1cmFzIHNlIGhhY2UgdXNvIGRlIGxhcyBmYWNldGFzICgqZmFjZXRzKiksIHBhcmEgZGl2aWRpciAgZWwgZ3LDoWZpY28gZW4gcGFuZWxlcyBxdWUgcmVwZXJlc2VudGFuIGNhZGEgZGVwYXJ0YW1lbnRvLiBPYnRlbmVkcmVtb3MgZWwgZGlhZ3JhbWEgZGUgY2FqYXMgeSBiaWdvdGVzIHN1cGVycHVlc3RvIGNvbiB1biBncsOhZmljbyBkZSB2aW9sw61uIHBhcmEgY29ub2NlciBsYSBkaXN0cmlidWNpw7NuIGRlIGxhIHZhcmlhYmxlIHRlbXBlcmF0dXJhLgoKYGBge3IsIGZpZy5oZWlnaHQ9MTUsIGZpZy53aWR0aD05fQpkZl9kYXRvcyAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IGRlcGFydGFtZW50bywgeSA9IHRlbXBlcmF0dXJhcyksIGZpbGwgPSBkZXBhcnRhbWVudG8pKwogIGdlb21fdmlvbGluKGZpbGwgPSAic3RlZWxibHVlIiwgYWxwaGEgPSAwLjYpKwogIGdlb21fYm94cGxvdChhbHBoYSA9IDAuNykrCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIFRlbXBlcmF0dXJhcyBwb3IgRGVwYXJ0YW1lbnRvIiwKICAgICAgIHggPSAiIiwgeSA9ICJUZW1wZXJhdHVyYSDCsEMiKSsKICBmYWNldF93cmFwKGZhY2V0cyA9IH5kZXBhcnRhbWVudG8sIHNjYWxlcyA9ICJmcmVlIiwgbnJvdyA9IDgpCmBgYAoKPGJyPgoKCiMgR3LDoWZpY29zIHBvciBEZXBhcnRhbWVudG8KCiogUHJlY2lwaXRhY2lvbmVzIHBvciBtZXMgcGFyYSBjYWRhIERlcGFydGFtZW50bwoKYGBge3IsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD05fQpkZl9kYXRvcyAlPiUKICBtdXRhdGUobWVzID0gZmFjdG9yKHggPSBtZXMsIGxldmVscyA9IGMoImVuZXJvIiwgImZlYnJlcm8iLCAibWFyem8iLCAiYWJyaWwiLCAibWF5byIsICJqdW5pbyIsICJqdWxpbyIsICJhZ29zdG8iLCAic2VwdGllbWJyZSIsICJvY3R1YnJlIiwgIm5vdmllbWJyZSIsICJkaWNpZW1icmUiKSkpICAlPiUgCiAgZ3JvdXBfYnkoZGVwYXJ0YW1lbnRvLCBtZXMpICU+JQogIHN1bW1hcmlzZShwcm9tID0gbWVhbihwcmVjaXBpdGFjaW9uZXMpKSAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeSA9IHByb20sIHggPSBtZXMpKSsKICBnZW9tX3BvaW50KGNvbG9yID0gImJsdWUiKSsKICBsYWJzKHRpdGxlID0gIlByb21lZGlvIFByZWNpcGl0YWNpb25lcyBwb3IgTWVzIHkgRGVwYXJ0YW1lbnRvIiwgeCA9ICJNZXMiLCB5ID0gIlByb20uIFByZWNpcGl0YWNpb25lcyAobW0pIikrCiAgZmFjZXRfd3JhcChmYWNldHMgPSB+ZGVwYXJ0YW1lbnRvLCBucm93ID0gOCkrCiAgdGhlbWVfYncoKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQpgYGAKCiogUHJvbWVkaW9zIAoKYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTl9CmxpYnJhcnkoZ3JpZEV4dHJhKQoKaDEgPC0gZGZfZGF0b3MgJT4lCiAgZ3JvdXBfYnkoZGVwYXJ0YW1lbnRvKSAlPiUgCiAgc3VtbWFyaXNlKHRvdF9wcmVwID0gcm91bmQobWVhbihwcmVjaXBpdGFjaW9uZXMpLCBkaWdpdHMgPSAyKSkgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSByZW9yZGVyKGRlcGFydGFtZW50bywgLXRvdF9wcmVwKSwgeSA9IHRvdF9wcmVwKSkrCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGFscGhhID0gMC45KSsKICBzY2FsZV95X2NvbnRpbnVvdXMobi5icmVha3MgPSA2KSsKICB0aGVtZV9idygpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSsKICBsYWJzKHRpdGxlID0gIlByZWNpcGl0YWNpb25lcyBQcm9tZWRpbyBwb3IgRGVwYXJ0YW1lbnRvIiwgeCA9ICIiLCB5ID0gIlByb20uIFByZWNpcGl0YWNpb25lcyAobW0pIikKCmgyIDwtIGRmX2RhdG9zICU+JQogIGdyb3VwX2J5KGRlcGFydGFtZW50bykgJT4lIAogIHN1bW1hcmlzZSh0b3RfcHJlcCA9IHJvdW5kKG1lYW4odGVtcGVyYXR1cmFzKSwgZGlnaXRzID0gMikpICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gcmVvcmRlcihkZXBhcnRhbWVudG8sIC10b3RfcHJlcCksIHkgPSB0b3RfcHJlcCkpKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBhbHBoYSA9IDAuOSkrCiAgc2NhbGVfeV9jb250aW51b3VzKG4uYnJlYWtzID0gNikrCiAgdGhlbWVfYncoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkrCiAgbGFicyh0aXRsZSA9ICJUZW1wZXJhdHVyYXMgUHJvbWVkaW8gcG9yIERlcGFydGFtZW50byIsIHggPSAiIiwgeSA9ICJQcm9tLiBUZW1wZXJhdHVyYXMgKMKwQykiKQoKaDMgPC0gZGZfZGF0b3MgJT4lCiAgZ3JvdXBfYnkoZGVwYXJ0YW1lbnRvKSAlPiUgCiAgc3VtbWFyaXNlKHRvdF9wcmVwID0gcm91bmQobWVhbihhbHRpdHVkKSwgZGlnaXRzID0gMikpICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gcmVvcmRlcihkZXBhcnRhbWVudG8sIC10b3RfcHJlcCksIHkgPSB0b3RfcHJlcCkpKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBhbHBoYSA9IDAuOSkrCiAgc2NhbGVfeV9jb250aW51b3VzKG4uYnJlYWtzID0gNikrCiAgdGhlbWVfYncoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkrCiAgbGFicyh0aXRsZSA9ICJBbHRpdHVkIFByb21lZGlvIHBvciBEZXBhcnRhbWVudG8iLCB4ID0gIiIsIHkgPSAiUHJvbS4gQWx0aXR1ZCAobSkiKQoKZ3JpZC5hcnJhbmdlKGgxLCBoMiwgaDMsIG5yb3c9MikKYGBgCjxicj4KCgoqIE11bmljaXBpb3MgZGUgQ3VuZGluYW1hcmNhLgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTl9CmRmX2RhdG9zICU+JQogIGZpbHRlcihkZXBhcnRhbWVudG8gPT0gYygiQ3VuZGluYW1hcmNhIikpICU+JSAKICBncm91cF9ieShkZXBhcnRhbWVudG8sIG11bmljaXBpbykgJT4lIAogIHN1bW1hcmlzZSh0b3RfcHJlcCA9IG1lYW4oYWx0aXR1ZCkpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IG11bmljaXBpbywgeSA9IHRvdF9wcmVwKSkrCiAgZ2VvbV9iYXIoZmlsbCA9ICJkYXJrb2xpdmVncmVlbjQiLHN0YXQgPSAiaWRlbnRpdHkiKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gdG90X3ByZXApLAogICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9pZGVudGl0eSgpLAogICAgICAgICAgICAgICAgICAgdmp1c3QgPSAtMC4xLAogICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSkrCiAgdGhlbWVfYncoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkrCiAgbGFicyh0aXRsZSA9ICJQcmVjaXBpdGFjaW9uZXMgUHJvbWVkaW8gTXVuaWNpcGlvcyBkZSBDdW5kaW5hbWFyY2EiLCB4ID0gIiIsIHkgPSAiUHJvbS4gUHJlY2lwaXRhY2lvbmVzIChtbSkiKSsKICBmYWNldF93cmFwKGZhY2V0cyA9IH5kZXBhcnRhbWVudG8sIHNjYWxlcyA9ICJmcmVlIikKYGBgCgo8YnI+CgoqIFByZWNpcGl0YWNpb25lcyB5IFRlbXBlcmF0dXJhcyBwb3IgUmVnacOzbgoKYGBge3IsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD05fQoKcDEgPC0gZGZfZGF0b3MgJT4lCiAgZ3JvdXBfYnkocmVnaW9uICwgZGVwYXJ0YW1lbnRvKSAlPiUgCiAgc3VtbWFyaXNlKHRvdF9wcmVwID0gbWVhbihwcmVjaXBpdGFjaW9uZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBkZXBhcnRhbWVudG8sIHkgPSB0b3RfcHJlcCkpKwogIGdlb21fYmFyKGZpbGwgPSAiZGFya3NsYXRlYmx1ZSIsc3RhdCA9ICJpZGVudGl0eSIpKwogIHRoZW1lX2J3KCkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpKwogIGxhYnModGl0bGUgPSAiUHJlY2lwaXRhY2lvbmVzIFByb21lZGlvIHBvciBSZWdpw7NuIiwgeCA9ICIiLCB5ID0gIlByb20uIFByZWNpcGl0YWNpb25lcyAobW0pIikrCiAgZmFjZXRfd3JhcChmYWNldHMgPSB+cmVnaW9uLCBzY2FsZXMgPSAiZnJlZSIpCgp0MSA8LSBkZl9kYXRvcyAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IGRlcGFydGFtZW50bywgeSA9IHRlbXBlcmF0dXJhcykpICsgCiAgZ2VvbV9ib3hwbG90KGFlcyhmaWxsID0gcmVnaW9uKSkrCiAgZmFjZXRfd3JhcChmYWNldHMgPSB+cmVnaW9uLCBzY2FsZXMgPSAiZnJlZSIpKwogIGxhYnModGl0bGUgPSAiVGVtcGVyYXR1cmEgcG9yIFJlZ2nDs24iLAogICAgICAgeCA9ICJEZXBhcnRhbWVudG8iLCB5ID0gIlRlbXBlcmF0dXJhIMKwQyIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpncmlkLmFycmFuZ2UocDEgLCB0MSwgbnJvdyA9IDIpCmBgYAoKPGJyPgoKKiBBbGd1bm9zIGRlcGFydGFtZW50b3MgeSBzdXMgbXVuaWNpcGlvcwoKPGJyPgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTl9CmRmX2RhdG9zICU+JQogIGZpbHRlcihkZXBhcnRhbWVudG8gPT0gYygiTWV0YSIsICJCb2zDrXZhciIsICJDaG9jw7MiLCAiU2FudGFuZGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5hcmnDsW8iLCAiQXJhdWNhIikpICU+JSAKICBncm91cF9ieShkZXBhcnRhbWVudG8sIG11bmljaXBpbykgJT4lIAogIHN1bW1hcmlzZSh0b3RfcHJlcCA9IG1lYW4ocHJlY2lwaXRhY2lvbmVzKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gbXVuaWNpcGlvLCB5ID0gdG90X3ByZXApKSsKICBnZW9tX2JhcihmaWxsID0gInNlYWdyZWVuNCIsc3RhdCA9ICJpZGVudGl0eSIpKwogIHRoZW1lX2J3KCkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpKwogIGxhYnModGl0bGUgPSAiUHJlY2lwaXRhY2lvbmVzIFByb21lZGlvIHBvciBNdW5pY2lwaW8geSBEZXBhcnRhbWVudG8iLCB4ID0gIiIsIHkgPSAiUHJvbS4gUHJlY2lwaXRhY2lvbmVzIChtbSkiKSsKICBmYWNldF93cmFwKGZhY2V0cyA9IH5kZXBhcnRhbWVudG8sIHNjYWxlcyA9ICJmcmVlIikKYGBgCgoKIyBSZWxhY2nDs24gQml2YXJpYWRhCgoKRXMgcG9zaWJsZSBvYnRlbmVyIGxvcyB2YWxvcmVzIGRlIENvdmFyaWFuemEgcGFyYSBsYXMgdmFyaWFibGVzLiBQYXJhIGVsIGNhc28gZGUgbGFzIHZhcmlhYmxlcyBhbHRpdHVkIHkgdGVtcGVyYXR1cmFzLCBzZSB0aWVuZSBxdWUgbGEgcmVhbGFjacOzbiBxdWUgaGF5IGVudHJlIGVsbGFzIGVzIGxpbmVhbCB5IG5lZ2F0aXZhLgoKYGBge3J9CmNvdih4ID0gZGZfZGF0b3MkYWx0aXR1ZCwgeSA9IGRmX2RhdG9zJHRlbXBlcmF0dXJhcykKYGBgCgpgYGB7cn0KZGZfZGF0b3MgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHkgPSB0ZW1wZXJhdHVyYXMsIHggPSBhbHRpdHVkKSkrCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSByZWdpb24pKSsKICBnZW9tX3Ntb290aCgpKwogIHNjYWxlX3lfY29udGludW91cyhuLmJyZWFrcyA9IDgpKwogIGxhYnModGl0bGUgPSAiQWx0aXR1ZCB2cyBUZW1wZXJhdHVyYSIsIHggPSAiQWx0aXR1ZCAobS5zLm4ubSkiLCB5ID0gIlRlbXBlcmF0dXJhcyAowrBDKSIpKwogIHRoZW1lX2J3KCkKYGBgCgo8YnI+CgpgYGB7cn0KZGZfZGF0b3MgJT4lIAogIGdyb3VwX2J5KGRlcGFydGFtZW50bykgJT4lIAogIHN1bW1hcmlzZShwcm9tX2FsID0gbWVhbihhbHRpdHVkKSwKICAgICAgICAgICAgcHJvbV90ZW0gPSBtZWFuKHRlbXBlcmF0dXJhcykpICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gcHJvbV9hbCwgeSA9IHByb21fdGVtKSkrCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBkZXBhcnRhbWVudG8pKSsKICBnZW9tX3Ntb290aCgpKwogIHRoZW1lX2J3KCkrCiAgbGFicyh0aXRsZSA9ICJQcm9tZWRpbyBkZSBBbHRpdHVkLVRlbXBlcmF0dXJhIiwKICAgICAgIHN1YnRpdGxlID0gIlBvciBEZXBhcnRhbWVudG8iLAogICAgICAgeCA9ICJBbHRpdHVkIChtLnMubi5tKSIsCiAgICAgICB5ID0gIlRlbXBlcmF0dXJhIMKwQyIsCiAgICAgICBjYXB0aW9uID0gIkNhZGEgcHVudG8gcmVwcmVzZW50YSB1biBEZXBhcnRhbWVudG8iKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKCmBgYHtyfQpjb3YoeCA9IGRmX2RhdG9zJHByZWNpcGl0YWNpb25lcywgeSA9IGRmX2RhdG9zJHRlbXBlcmF0dXJhcykKYGBgCgoKYGBge3J9CmRmX2RhdG9zICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gdGVtcGVyYXR1cmFzLCB5ID0gcHJlY2lwaXRhY2lvbmVzKSkrCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSByZWdpb24pKSsKICBnZW9tX3Ntb290aCgpKwogIGxhYnModGl0bGUgPSAiVGVtcGVyYXR1cmFzIHZzIFByZWNpcGl0YWNpb25lcyIsIHggPSAiVGVtcGVyYXR1cmFzIMKwQyIsIHkgPSAiUHJlY2lwaXRhY2lvbmVzIChtbSkiKSsKICB0aGVtZV9idygpCiAgCmBgYAoKCmBgYHtyfQpkZl9kYXRvcyAlPiUgCiAgZ3JvdXBfYnkoZGVwYXJ0YW1lbnRvKSAlPiUgCiAgc3VtbWFyaXNlKHByb21fYWwgPSBtZWFuKHByZWNpcGl0YWNpb25lcyksCiAgICAgICAgICAgIHByb21fdGVtID0gbWVhbih0ZW1wZXJhdHVyYXMpKSAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeSA9IHByb21fYWwsIHggPSBwcm9tX3RlbSkpKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gZGVwYXJ0YW1lbnRvKSkrCiAgZ2VvbV9zbW9vdGgoKSsKICB0aGVtZV9idygpKwogIGxhYnModGl0bGUgPSAiUHJvbWVkaW8gVGVtcGVyYXR1cmEtUHJlY2lwaXRhY2lvbmVzIiwKICAgICAgIHN1YnRpdGxlID0gIlBvciBEZXBhcnRhbWVudG8iLAogICAgICAgeSA9ICJQcmVjaXBpdGFjaW9uZXMgKG1tKSIsCiAgICAgICB4ID0gIlRlbXBlcmF0dXJhIMKwQyIsCiAgICAgICBjYXB0aW9uID0gIkNhZGEgcHVudG8gcmVwcmVzZW50YSB1biBEZXBhcnRhbWVudG8iKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9OX0KZGZfZGF0b3MgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeSA9IHByZWNpcGl0YWNpb25lcywgeCA9IHRlbXBlcmF0dXJhcykpKwogIGdlb21fcG9pbnQoY29sb3IgPSAiZGFya29yYW5nZSIsIGFscGhhID0gMC44KSsKICBnZW9tX3Ntb290aCgpKwogIGxhYnModGl0bGUgPSAiVGVtcGFyYXR1cmFzIHkgUHJlY2lwaXRhY2lvbmVzIiwKICAgICAgIHN1YnRpdGxlID0gIkluZGl2aWR1YWwgcG9yIERlcGFydGFtZW50byIsCiAgICAgICB4ID0gIlRlbXBlcmF0dXJhcyDCsEMiLAogICAgICAgeSA9ICJQcmVjaXBpdGFjaW9uZXMgKG1tKSIpKwogIHRoZW1lX2J3KCkrCiAgZmFjZXRfd3JhcChmYWNldHMgPSB+ZGVwYXJ0YW1lbnRvLCBzY2FsZXMgPSAiZnJlZSIsIG5yb3cgPSA4KQpgYGAKCgpgYGB7cn0KZGZfZGF0b3MgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeSA9IHByZWNpcGl0YWNpb25lcywgeCA9IGFsdGl0dWQpKSsKICBnZW9tX3Ntb290aCgpKwogIGxhYnModGl0bGUgPSAiQWx0aXR1ZCB5IFByZWNpcGl0YWNpb25lcyIsCiAgICAgICBzdWJ0aXRsZSA9ICJSZWdpb25lcyBOYXR1cmFsZXMiLAogICAgICAgeCA9ICJBbHRpdHVkIChtLnMubi5tKSIsCiAgICAgICB5ID0gIlByZWNpcGl0YWNpb25lcyAobW0pIikrCiAgdGhlbWVfYncoKSsKICBmYWNldF93cmFwKGZhY2V0cyA9IH5yZWdpb24sIHNjYWxlcyA9ICJmcmVlIiwgbnJvdyA9IDIpCmBgYAoKYGBge3J9CmRmX2RhdG9zICU+JSAKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh5ID0gIHByZWNpcGl0YWNpb25lcywgeCA9IGFsdGl0dWQpKSsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IHJlZ2lvbikpKwogIGdlb21fc21vb3RoKCkrCiAgbGFicyh0aXRsZSA9ICJBbHRpdHVkIHZzIFByZWNpcGl0YWNpb25lcyIsIHggPSAiQWx0aXR1ZCAobS5zLm4ubSkiLCB5ID0gIlByZWNpcGl0YWNpb25lcyAobW0pIikrCiAgdGhlbWVfYncoKQpgYGAKCiogSGlzdG9ncmFtYSAyZAoKYGBge3J9CmRmX2RhdG9zICU+JSAKZ2dwbG90KG1hcHBpbmcgPSBhZXMoeT1wcmVjaXBpdGFjaW9uZXMsIHg9dGVtcGVyYXR1cmFzKSkgKwogIGdlb21fYmluMmQoYmlucyA9IDUwKSArCiAgc2NhbGVfZmlsbF9jb250aW51b3VzKHR5cGUgPSAidmlyaWRpcyIpICsKICB0aGVtZV9idygpKwogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtYSBUZW1wZXJhdHVyYSB5IFByZWNpcGl0YWNpb25lcyIsCiAgICAgICB4ID0gIlRlbXBlcmF0dXJhIMKwQyIsCiAgICAgICB5ID0gIlByZWNpcGl0YWNpb25lcyAobW0pIikKYGBgCgoqIERlbnNpZGFkIDJkCgpgYGB7cn0KZGZfZGF0b3MgJT4lIApnZ3Bsb3QobWFwcGluZyA9IGFlcyh5PXByZWNpcGl0YWNpb25lcywgeD10ZW1wZXJhdHVyYXMpKSArCiAgc3RhdF9kZW5zaXR5XzJkKGFlcyhmaWxsID0gLi5kZW5zaXR5Li4pLCBnZW9tID0gInJhc3RlciIsIGNvbnRvdXIgPSBGQUxTRSkgKwogIGdlb21fc21vb3RoKHNlID0gRikrCiAgc2NhbGVfeF9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0nbm9uZScpKwogIHRoZW1lX2J3KCkrCiAgbGFicyh0aXRsZSA9ICJEZW5zaWRhZCBUZW1wZXJhdHVyYXMgeSBQcmVjaXBpdGFjaW9uZXMiLAogICAgICAgIHggPSAiVGVtcGVyYXR1cmFzIiwKICAgICAgICB5ID0gIlByZWNpcGl0YWNpb25lcyIpCmBgYAoKPGJyPgoKYGBge3J9CmRmX2RhdG9zICU+JSAKZ2dwbG90KG1hcHBpbmcgPSBhZXMoeD1wcmVjaXBpdGFjaW9uZXMsIHk9dGVtcGVyYXR1cmFzKSkgKwogIHN0YXRfZGVuc2l0eV8yZChhZXMoZmlsbCA9IC4ubGV2ZWwuLiksIGdlb20gPSAicG9seWdvbiIpKwogIGxhYnMoeCA9ICJQcmVjaXBpdGFjaW9uZXMgKG1tKSIsCiAgICAgICB5ID0gIlRlbXBlcmF0dXJhIMKwQyIpCmBgYAoKIyMgQ29ycmVsYWNpb25lcwoKYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTl9CmxpYnJhcnkoR0dhbGx5KQpnZ3BhaXJzKGRmX2RhdG9zLCBjb2x1bW5zID0gYygicHJlY2lwaXRhY2lvbmVzIiwgInRlbXBlcmF0dXJhcyIsICJhbHRpdHVkIiksIGdncGxvdDI6OmFlcyhjb2xvdXI9cmVnaW9uLCBhbHBoYSA9IDAuNikpCmBgYAoKCmBgYHtyfQpnZ2NvcnIoZGZfZGF0b3MsIG1ldGhvZCA9IGMoImV2ZXJ5dGhpbmciLCAicGVhcnNvbiIpKSAKYGBgCgoKCiMgUmVmZXJlbmNpYXMKCiogW0RhdG9zIEFiaWVydG9zIGRlbCBHb2JpZXJubyBkZSBDb2xvbWJpYV0oaHR0cHM6Ly93d3cuZGF0b3MuZ292LmNvLykKCiogW1VuaWRhZGVzIHByZWNpcGl0YWNpw7NuXShodHRwczovL2VzLndpa2lwZWRpYS5vcmcvd2lraS9QcmVjaXBpdGFjaSVDMyVCM25fKG1ldGVvcm9sb2clQzMlQURhKSkKCiogUGFxdWV0ZSBwYXJhIGNpZW5jaWEgZGUgZGF0b3M6IFt0aWR5dmVyc2VdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvKQoKKiBMaWJyZXLDrWEgcmVzdW1lbiBkZSBkYXRvcyA6W3NraW1yXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCkKCiogTGlicmVyw61hIGdyw6FmaWNhIHBhcmEgUjogW2dncGxvdDJdKGh0dHBzOi8vZ2dwbG90Mi1ib29rLm9yZy8pCgoKCg==