Presentación

Este documento es un ejercicio práctico para aplicar algunos conceptos del lenguaje de programación R; editar bases de datos, realizar gráficos descriptivos, crear tablas. Es un ejemplo demostrativo, que a su vez, es usado por quien escribe estas líneas, para dejar nota de los códigos.

Siéntase en la libertad de copiar, compartir, criticar, satirizar, reproducir las ideas del documento; como también sugerir mejoras u opinar acerca del mismo.

La interpretación y análisis conceptual se deja al lector interesado en la temática propuesta para el ejercicio.

Datos

Fuente de la base de datos

La base de datos fué obtenida el día 13 de Noviembre de 2020 a través de la página de datos abiertos del gobierno de Colombia: datos.gov.co

Lectura de datos

library(data.table)
datos <- fread("Casos_positivos_de_COVID-19_en_Colombia.csv",
               encoding = "UTF-8", na.strings = "N/A")
|--------------------------------------------------|
|==================================================|
datos[datos == ""] <- NA

La base de datos tiene 1’165.326 filas y 23 columnas (variables).

# dimensión de la base de datos
dim(datos)
[1] 1165326      23

Mostrar los primeros 100 datos

library(DT)
head(datos, 100)

Nombres de las variables o columnas.

Una descripción completa de las variables se presenta en el sitio web de datos abiertos del gobierno de Colombia.

names(datos)
 [1] "fecha reporte web"            "ID de caso"                  
 [3] "Fecha de notificación"        "Código DIVIPOLA departamento"
 [5] "Nombre departamento"          "Código DIVIPOLA municipio"   
 [7] "Nombre municipio"             "Edad"                        
 [9] "Unidad de medida de edad"     "Sexo"                        
[11] "Tipo de contagio"             "Ubicación del caso"          
[13] "Estado"                       "Código ISO del país"         
[15] "Nombre del país"              "Recuperado"                  
[17] "Fecha de inicio de síntomas"  "Fecha de muerte"             
[19] "Fecha de diagnóstico"         "Fecha de recuperación"       
[21] "Tipo de recuperación"         "Pertenencia étnica"          
[23] "Nombre del grupo étnico"     

Editar base de datos

  • Se editarán los nombres de las variables con el objetivo de que no generen confusión en el análisis.

  • Se precisa tener nombres cortos preferiblemente, que no contengan caracteres especiales tales como ")%(&´’/#¨!$.

  • Tampoco es recomendable que contengan acentos característicos del lenguaje natural, tildes o la letra ñ por ejemplo.

  • La variable etnia tiene seis niveles, establecidos de la siquiente manera:

      1. Indígena
      1. ROM
      1. Raizal
      1. Palenquero
      1. Negro
      1. Otro
  • fecha_notif es la fecha de notificación ante el SIVIGILA

  • fecha_diagnos Fecha de confirmación por laboratorio.

#librerías
library(lubridate)
library(tidyverse)
library(janitor)
library(Hmisc)
datos %>% 
  #nombres de las variables en minúsculas
  clean_names() %>% 
  #seleccionar y renombrar las variables de interés
  select(fecha_sintomas = fecha_de_inicio_de_sintomas,
         fecha_diagnos = fecha_de_diagnostico,
         fecha_notif = fecha_de_notificacion,
         fecha_recu = fecha_de_recuperacion,
         departamento = nombre_departamento,
         municipio = nombre_municipio,
         edad,
         sexo,
         contagio = tipo_de_contagio,
         ubicacion_caso = ubicacion_del_caso,
         estado,
         pais = nombre_del_pais,
         recuperado,
         tipo_recuperacion = tipo_de_recuperacion,
         etnia = pertenencia_etnica) %>% 
  mutate(#cambiar a formato fecha (date)
         fecha_sintomas = as.Date(fecha_sintomas, format="%d/%m/%Y"),
         fecha_diagnos = as.Date(fecha_diagnos, format="%d/%m/%Y"),
         fecha_notif = as.Date(fecha_notif, format="%d/%m/%Y"),
         fecha_recu = as.Date(fecha_recu, format="%d/%m/%Y"),
         #editar los valores de la variable sexo
         sexo = gsub("f", "F", sexo),
         sexo = gsub("m", "M", sexo),
         #editar nombres de los departamentos
         departamento = capitalize(tolower(departamento)),
         departamento = gsub("Sta marta d.e.", "Sta marta",departamento),
         departamento = gsub("Atlantico", "Atlántico",departamento),
         departamento = gsub("Bogota", "Bogotá",departamento),
         departamento = gsub("Boyaca", "Boyacá",departamento),
         departamento = gsub("Caqueta", "Caquetá",departamento),
         departamento = gsub("Choco", "Chocó",departamento),
         departamento = gsub("Cordoba", "Córdoba",departamento),
         departamento = gsub("Guainia", "Guainía",departamento),
         departamento = gsub("Norte santander", "Norte Santander",departamento),
         departamento = gsub("Valle", "Valle del Cauca",departamento),
         #editar nombres de los municipios
         municipio = capitalize(tolower(municipio)),
         #editar los valores de la variable estado
         estado = gsub("LEVE", "Leve", estado),
         estado = gsub("leve", "Leve", estado),
         estado = gsub("moderado", "Moderado", estado),
         #editar los valores de la variable contagio
         contagio = gsub("En estudio", "en_estudio",contagio),
         contagio = gsub("EN ESTUDIO", "en_estudio",contagio),
         contagio = gsub("En Estudio", "en_estudio",contagio),
         contagio = gsub("relacionado", "Relacionado",contagio),
         contagio = gsub("Relacioando", "Relacionado",contagio),
         contagio = gsub("RELACIONADO", "Relacionado",contagio),
         #editar los valores de la variable pais
         pais = capitalize(tolower(pais)),
         pais = gsub("Arabia saudita" , "Arabia saudí",pais),
         pais = gsub("Arabia saudita" , "Arabia saudí",pais),
         pais = gsub("Estados unidos de america", "Estados unidos",pais),
         pais = gsub("Estados unidos de américa", "Estados unidos",pais),
         pais = gsub("Mexico" , "México",pais),
         pais = gsub("Panama" , "Panamá",pais),
         pais = gsub("Peru" , "Perú",pais),
         pais = gsub("Reino unido de gran bretaña e irlanda del norte" , "Reino unido",pais),
         pais = gsub("República árabe siria" , "Siria",pais),
         #editar los valores de la variable recuperado
         recuperado = gsub("fallecido" , "Fallecido", recuperado),
         #editar los valores de la variable ubicacion_caso
         ubicacion_caso = gsub("CASA" , "Casa", ubicacion_caso),
         ubicacion_caso = gsub("Hospital UCI" , "UCI", ubicacion_caso),
         #convertir variable etnia en factor
         etnia = as.factor(etnia)) %>% 
  #convertir las variables que estén en formato character a formato factor
  mutate_if(is.character, as.factor) -> covid

Base de datos editada, primeros 100 datos

head(covid, 100)

Exportar la base de datos

Se guardará la base de datos editada en un archivo .csv con el nombre datos_covid.csv.

write_csv(x = covid, file = "datos_covid.csv")

Series de tiempo

Las líneas rojas verticales punteadas representan algunas fechas durante la pandemia; de izquierda a derecha:

Casos Totales por día

library(plotly)
ggplotly(
  covid %>% 
  group_by(fecha_diagnos) %>% 
  summarise(Total = n()) %>%
  ggplot(., mapping = aes(x = fecha_diagnos, y = Total))+
  geom_point(color = "darkcyan")+
  scale_x_date(date_breaks = "15 day") +
  geom_line(color  = "gray") +
  geom_smooth(se = FALSE, color = "cornflowerblue")+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-06-19")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-09-01")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-07-03")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-10-9")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  labs(x = "Fecha", y = "Casos", title = "Total Casos por Día",
       subtitle = "", caption = "")+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))+
  theme(panel.border = element_blank())
  ) %>% 
  layout(height = 500, width = 700)

NA

Logaritmo de los casos totales por día

library(plotly)
ggplotly(
  covid %>% 
  group_by(fecha_diagnos) %>% 
  summarise(Total = n()) %>%
  ggplot(., mapping = aes(x = fecha_diagnos, y = log(Total)))+
  geom_point(color = "darkcyan")+
  scale_x_date(date_breaks = "15 day") +
  geom_line(color  = "gray") +
  geom_smooth(se = FALSE, color = "cornflowerblue")+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-06-19")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-09-01")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-07-03")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-10-9")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  labs(x = "Fecha", y = "log(Casos)", title = "Escala logaritmica para casos diarios",
       subtitle = "", caption = "")+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))+
  theme(panel.border = element_blank())
  ) %>% 
  layout(height = 500, width = 700)

Total casos acumulados del país

ggplotly(covid %>% 
  group_by(fecha_notif) %>% 
  summarise(Total = n()) %>%
  ungroup() %>% 
  mutate(T.Acumulado = cumsum(Total)) %>% 
  ggplot(otro, mapping = aes(x = fecha_notif, y = T.Acumulado))+
  geom_line(color = "aquamarine4", size=1)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-06-19")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-09-01")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-07-03")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-10-9")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  scale_x_date(date_breaks = "15 day") +
  labs(x = "Fecha", y = "Casos", title = "Casos Totales Acumulados Nacional",
       subtitle = "", caption = "")+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))+
  theme(panel.border = element_blank())
)

Logaritmo de total casos en el país

ggplotly(covid %>% 
  group_by(fecha_notif) %>% 
  summarise(Total = n()) %>%
  ungroup() %>% 
  mutate(T.Acumulado = cumsum(Total)) %>% 
  ggplot(otro, mapping = aes(x = fecha_notif, y = log(T.Acumulado)))+
  geom_line(color = "aquamarine4", size=1)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-06-19")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-09-01")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-07-03")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  geom_vline ( xintercept = as.numeric(as.Date ("2020-10-9")),
               linetype="dashed", 
               color = "firebrick", size=0.5, alpha=0.5)+
  scale_x_date(date_breaks = "15 day") +
  labs(x = "", y = "log(casos)", title = "Escala Logarítmica Casos Acumulados Nacional",
       subtitle = "", caption = "")+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))+
  theme(panel.border = element_blank())
)

Casos totales por departamento

Tabla con el total de casos positivos en cada departamento.

covid %>% 
  group_by(departamento) %>% 
  summarise(Total = n()) %>%
  ungroup() %>% 
  arrange(desc(Total)) %>% 
  datatable(extensions = 'Buttons',
            rownames = FALSE,
            filter = "top",
            selection = "multiple",
            options = list(dom = 'Bfrtip',
                           buttons = c('csv', 'excel', 'pdf')))

Variación diaria por Departamento

El punto rojo representa la media

ggplotly(covid %>% 
  group_by(departamento, fecha_notif) %>% 
  summarise(Total = n()) %>% 
  ungroup() %>% 
  group_by(departamento, fecha_notif) %>% 
  summarise(Total = sum(Total)) %>% 
  ggplot(aes(x = reorder(departamento, Total), y = Total))+
  geom_boxplot(fill = "cornflowerblue")+
  labs(x = "", y = "Casos", title = "",
       subtitle = "", caption = "")+
  stat_summary(fun.y = mean, geom = "point", color = "firebrick")+
  scale_y_log10()+
  theme_bw()+
  theme(panel.border = element_blank())+
  coord_flip())

NA

Representación por género de los casos acumulados

Serie de tiempo de los casos positivos presentados por género.

ggplotly(
  covid%>% 
  group_by(sexo, fecha_notif) %>% 
  summarise(Total = n()) %>%
  mutate(T.Acumulado = cumsum(Total)) %>% 
  ggplot(mapping = aes(x = fecha_notif, y = T.Acumulado, color = sexo))+
  geom_line(size=1, alpha=0.7)+
  scale_color_manual(values = c("aquamarine2", "chocolate2"))+
  scale_x_date(date_breaks = "15 day") +
  labs(x = "Fecha", y = "Casos", title = "Casos totales por género",
       subtitle = "", caption = "")+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))+
  theme(panel.border = element_blank())
  )

Logaritmo casos acumulados por género

Serie de tiempo en escala logartítmica de casos acumulados por género.

ggplotly(
  covid%>% 
  group_by(sexo, fecha_notif) %>% 
  summarise(Total = n()) %>%
  mutate(T.Acumulado = cumsum(Total)) %>% 
  ggplot(mapping = aes(x = fecha_notif, y = log(T.Acumulado), color = sexo))+
  geom_line(size=1)+
  scale_color_manual(values = c("aquamarine2", "chocolate2"))+
  scale_x_date(date_breaks = "15 day") +
  labs(x = "Fecha", y = "log(casos)", title = "Escala logarítmica casos totales por género",
       subtitle = "", caption = "")+
  theme_bw()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))+
  theme(panel.border = element_blank())
  )

Distribución de los casos presentados por semana y género

Variación semanal

  • En la semana 25 se encuentra el día 19 de Junio. Primer día sin IVA.

  • En la semana 27 se encuentra el día 3 de Julio. Segundo día sín IVA.

  • En la semana 36 se encuentra el día 1 de Septiembre. Inicia el aislamiento selectivo.

  • En la semana 41 y 42 se encuentra el 9 de Octubre y el 13 de Octubre. Eliminatorias copa mundial de fútbol Qatar 2022.

library(ggridges)
covid %>% 
  group_by(fecha_notif) %>% 
  count(name = "Total_dia") %>%
  ungroup() %>% 
  mutate(Semana = week(fecha_notif)) %>% 
  ggplot(aes(x = Total_dia, y = as.factor(Semana)))+
  geom_density_ridges(fill = "cadetblue")+theme_bw()+
  theme(panel.border = element_blank())+
  labs(x = "Casos por día", y = "Semana", title = "Variación semanal")

NA

Variación semanal por género

covid %>% 
  group_by(fecha_notif, sexo) %>% 
  count(name = "Total_dia") %>%
  ungroup() %>% 
  mutate(Semana = week(fecha_notif)) %>% 
  ggplot(aes(x = Total_dia, y = as.factor(Semana), fill = sexo))+
  scale_fill_manual(values = c("cadetblue", "firebrick2"))+
  geom_density_ridges(alpha = 0.7)+theme_bw()+
  theme(panel.border = element_blank(), legend.position = "right")+
  labs(x = "Casos por día", y = "Semana", title = "Variación semanal por género")

Representación gráfica para las edades

Gráfico de densidad por edad.

ggplot(data = covid, aes(edad))+
  geom_density(alpha = 0.5, fill = "darkcyan")+
  labs(x = "Edad", y = "Densidad", title = "Gráfico de densidad", subtitle="Distribución de casos según la edad")

Gráfico de densidad por edad y género

ggplot(data = covid, aes(edad, fill = sexo))+
  geom_density(alpha = 0.5)+
  labs(x = "Edad", y = "Densidad", title= "Gráfico de densidad",
       subtitle = "Distribución casos según la edad y el género")+
  scale_fill_manual(values = c("cadetblue", "firebrick2"))

Gráfico de violín por género y edades

Un diagrama de violín se utiliza para visualizar la distribución de los datos y su densidad de probabilidad. Este gráfico es una combinación de un diagrama de cajas y bigotes y un diagrama de densidad girado y colocado a cada lado, para mostrar la forma de distribución de los datos. Fuente

covid %>% 
  ggplot(aes(x = sexo, y = edad))+
  geom_violin(aes(color = sexo, fill = sexo), alpha = 0.7)+
  geom_boxplot(aes(fill = sexo),width = 0.2, outlier.alpha = 0.01)+
  scale_fill_manual(values = c("mediumpurple2", "darkslategray3"))+
  labs(x = "Sexo", y = "Edad", title = "Gráfico de violín para edades y género")

NA

Grafico de densidad Edad/Género/Fallecido

Se filtran casos en los que el estado es Fallecido para representarlos por género y edad.

fallecido <- covid %>% 
  filter(estado == "Fallecido")

ggplot(data = fallecido, mapping=aes(x = edad, fill = sexo))+
geom_density(alpha = 0.7)+
labs(x="Edad", y="Densidad", title="Distribución fallecidos por edad y género")+
scale_fill_manual(values = c("gold", "darkslategray3"))

NA
NA

Gráfico de densidad Edad/Género/Recuperado

Se filtran los valores de Recuperado para representarlos por género y edad.

recuperado <- covid %>% 
  filter(recuperado == "Recuperado")

ggplot(data = covid, mapping=aes(x = edad, fill = sexo))+
geom_density(alpha = 0.7)+
labs(x = "Edad", y="Densidad", title="Distribución recuperados por género y edad")+
scale_fill_manual(values = c("gold", "darkslategray3"))

NA
NA

Frecuencias para las variables pais y etnia

pais

Tabla de frecuencias para la variable pais. En orden descendente.

sort(desc(table(covid$pais)))

                España         Estados unidos                Ecuador 
                  -258                   -219                    -65 
                México                 Brasil                 Panamá 
                   -55                    -52                    -36 
               Turquía                   Perú                  Chile 
                   -27                    -24                    -20 
               Francia              Venezuela                Jamaica 
                   -19                    -18                    -16 
           Reino unido            Puerto rico               Alemania 
                   -15                    -13                    -11 
                Egipto                 Italia   República dominicana 
                   -11                    -11                    -10 
 Antillas neerlandesas                 Israel              Argentina 
                    -8                     -6                     -4 
                  Cuba                 Grecia                  Aruba 
                    -4                     -4                     -3 
                Canadá           Arabia saudí             Costa rica 
                    -3                     -2                     -2 
               Curazao              Marruecos              Nicaragua 
                    -2                     -2                     -2 
             Australia                Bélgica                Croacia 
                    -1                     -1                     -1 
Emiratos arabes unidos              Guatemala               Honduras 
                    -1                     -1                     -1 
               Irlanda                  Kenya               Portugal 
                    -1                     -1                     -1 
                 Siria                 Suecia                  Suiza 
                    -1                     -1                     -1 
               Uruguay 
                    -1 

etnia

Descripción obtenida del sitio web:

1-Indígena 2-ROM 3-Raizal 4-Palenquero 5-Negro 6-Otro. Esta variable se actualizará cada semana. ADVERTENCIA DE RESPONSABILIDAD: La variable etnia depende totalmente de tres cosas: - El correcto diligenciamiento de la variable Etnia por los profesionales de salud que notifican en más de 10.000 instituciones de salud en todos los municipios y departamentos. - Del autorreconocimiento de la persona cuando se le pregunta por esta variable. - Del listado censal que haga y mantenga actualizado cada departamento. No depende del Instituto Nacional de Salud, y por lo tanto, es responsabilidad de las autoridades de cada municipio, departamento y distrito de Colombia; la calidad y consistencia de dicha variable

Frecuencias obtenidas para la variable etnia.

table(covid$etnia)

      1       2       3       5       6 
  24181      36     405   40649 1052704 

Gráficos de barra

Se presenta una breve descripción para algunas variables, y se representan gráficamente a través de un diagrama de barras conjunto. En algunos casos las barras de las variables no se aprecian debido a que es bastante pequeña comparada con las otras variables presentes.

Variables

  • contagio: La barra para el valor Importado es bastante pequeña comparada con las otras dos debido a que la diferencia de contagios en este rubro es mucho menor; por lo tanto no se aprecia en el gráfico de manera correcta.

  • ubicacion_caso: *Corresponde a muertes no relacionadas con COVID-19, aún si eran casos activos **Hay pacientes recuperados para COVID-19, que pueden permanecer en hospitalización por otras comorbilidades.* (Descripción obtenida de la página oficial de datos abiertos.)

  • estado: *Corresponde a muertes no relacionadas con COVID-19, aún si eran casos activos **Hay pacientes recuperados para COVID-19, que pueden permanecer en hospitalización por otras comorbilidades.* (Descripción obtenida de la página oficial de datos abiertos.)

  • recuperado: Recuperado Fallecido N/A (Vacío). N/A se refiere a los fallecidos no COVID. Pueden haber casos recuperados con ubicación Hospital u Hospital UCI, ya que permanecen en hospitalización por causas diferentes. Los casos con información en blanco en esta columna corresponde a los casos activos (Descripción obtenida de la página oficial de datos abiertos.)

  • tipo_recuperacion

  • tipo_recuperacion: Se refiere a la variable de tipo de recuperación que tiene dos opciones: PCR y tiempo. PCR indica que la persona se encuentra recuperada por segunda muestra, en donde dio negativo para el virus; mientras que tiempo significa que son personas que cumplieron 30 días posteriores al inicio de síntomas o toma de muestras que no tienen síntomas, que no tengan más de 70 años ni que estén hospitalizados. (Descripción obtenida de la página oficial de datos abiertos.)

library(cowplot)

g1 <- ggplot(data = covid, aes(x = contagio)) +
geom_bar(stat = "count", fill = "cornflowerblue") + 
stat_count(geom = "text", colour = "black", size = 3.5,
aes(label = ..count..),position=position_stack(vjust=0.7))+
  labs(x = "", y = "",
       title = "Frecuencia Tipos de Contagio")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

g2 <- ggplot(data = covid, aes(x = ubicacion_caso)) +
geom_bar(stat = "count", fill = "cornflowerblue") + 
stat_count(geom = "text", colour = "black", size = 3.5,
aes(label = ..count..),position=position_stack(vjust=1.1))+
  labs(x = "", y = "",
       title = "Frecuencia Ubicación Caso")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

g3 <- ggplot(data = covid, aes(x = estado)) +
geom_bar(stat = "count", fill = "cornflowerblue") + 
stat_count(geom = "text", colour = "black", size = 3.5,
aes(label = ..count..),position=position_stack(vjust=1.1))+
  labs(x = "", y = "",
       title = "Frecuencia de la Variable Estado")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

g4 <- ggplot(data = covid, aes(x = recuperado)) +
geom_bar(stat = "count", fill = "cornflowerblue") + 
stat_count(geom = "text", colour = "black", size = 3.5,
aes(label = ..count..),position=position_stack(vjust=1.1))+
  labs(x = "", y = "",
       title = "Frecuencia de Recuperado")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

g5 <- ggplot(data = covid, aes(x = tipo_recuperacion)) +
geom_bar(stat = "count", fill = "cornflowerblue") + 
stat_count(geom = "text", colour = "black", size = 3.5,
aes(label = ..count..),position=position_stack(vjust=0.5))+
  labs(x = "", y = "",
       title = "Frecuencia Tipo de Recuperación")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))


plot_grid(g1, g2, g3, g4, g5, scale = 1)

Gráficos de densidad

Distribución para la variable contagio

covid %>% 
  ggplot(data = covid, mapping = aes(x = edad, fill = contagio))+
  geom_density(alpha = 0.7)+
  labs(x = "Edad", y="Densidad", title="Distribución de tipo de contagio por edad")

Distribución de la variable ubicacion_caso

covid %>% 
  ggplot(data = covid, mapping = aes(x = edad, fill = ubicacion_caso))+
  geom_density(alpha = 0.7)+
  labs(x = "Edad", y="Densidad", title="Distribución ubicación de los casos por edad")

Distribución de la variable estado

covid %>% 
  ggplot(data = covid, mapping = aes(x = edad, fill = estado))+
  geom_density(alpha = 0.7)+
  labs(x = "Edad", y="Densidad", title="Distribución del estado por edad")

Distribución de la variable recuperado

covid %>% 
  ggplot(data = covid, mapping = aes(x = edad, fill = recuperado))+
  geom_density(alpha = 0.7)+
  labs(x = "Edad", y="Densidad", title="Distribución de recuperados por edad")

Distribución de la variable tipo_recuperacion

covid %>% 
  ggplot(data = covid, mapping = aes(x = edad, fill = tipo_recuperacion))+
  geom_density(alpha = 0.7)+
  labs(x = "Edad", y="Densidad", title="Distribución de recuperados por edad")+
  facet_grid()

Tablas

Tabla resumen por ciudad

ciudad1 <- covid %>% 
  group_by(municipio, departamento, contagio) %>% 
  summarise(Total = n()) %>% 
  ungroup()

ciudad11 <-  spread(data = ciudad1, key = contagio, value = Total) %>% 
  datatable(extensions = 'Buttons',
            rownames = FALSE,
            filter = "top",
            selection = "multiple",
            options = list(dom = 'Bfrtip',
                           buttons = c('csv', 'excel', 'pdf')))

ciudad11
ciudad2 <- covid %>% 
  group_by(municipio, departamento, ubicacion_caso) %>% 
  summarise(Total = n()) %>% 
  ungroup()

ciudad22 <-  spread(data = ciudad2, key = ubicacion_caso, value = Total) %>% 
  datatable(extensions = 'Buttons',
            rownames = FALSE,
            filter = "top",
            selection = "multiple",
            options = list(dom = 'Bfrtip',
                           buttons = c('csv', 'excel', 'pdf')))

ciudad22
ciudad3 <- covid %>% 
  group_by(municipio, departamento, estado) %>% 
  summarise(Total = n()) %>% 
  ungroup()

ciudad33 <-  spread(data = ciudad3, key = estado, value = Total) %>% 
  datatable(extensions = 'Buttons',
            rownames = FALSE,
            filter = "top",
            selection = "multiple",
            options = list(dom = 'Bfrtip',
                           buttons = c('csv', 'excel', 'pdf')))

ciudad33
ciudad4 <- covid %>% 
  group_by(municipio, departamento, recuperado) %>% 
  summarise(Total = n()) %>% 
  ungroup()

ciudad44 <-  spread(data = ciudad4, key = recuperado, value = Total) %>% 
  datatable(extensions = 'Buttons',
            rownames = FALSE,
            filter = "top",
            selection = "multiple",
            options = list(dom = 'Bfrtip',
                           buttons = c('csv', 'excel', 'pdf')))

ciudad44
ciudad5 <- covid %>% 
  group_by(municipio, departamento, tipo_recuperacion) %>% 
  summarise(Total = n()) %>% 
  ungroup()

ciudad55 <-  spread(data = ciudad5, key = tipo_recuperacion, value = Total) %>%
  datatable(extensions = 'Buttons',
            rownames = FALSE,
            filter = "top",
            selection = "multiple",
            options = list(dom = 'Bfrtip',
                           buttons = c('csv', 'excel', 'pdf')))

ciudad55
LS0tCnRpdGxlOiAiRXhwbG9yYWNpw7NuIGRhdG9zIGRlIENvdmlkLTE5IGVuIENvbG9tYmlhIiAKc3VidGl0bGU6ICJDw7NtcHV0b3MgY29uIGVsIGxlbmd1YWplIFIiCmF1dGhvcjogIkNSRyIKZGF0ZTogMTMvMTEvMjAyMApvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdGhlbWU6IGZsYXRseQogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSkKYGBgCgojIFByZXNlbnRhY2nDs24KCkVzdGUgZG9jdW1lbnRvIGVzIHVuIGVqZXJjaWNpbyBwcsOhY3RpY28gcGFyYSBhcGxpY2FyIGFsZ3Vub3MgY29uY2VwdG9zIGRlbCBsZW5ndWFqZSBkZSBwcm9ncmFtYWNpw7NuIFI7IGVkaXRhciBiYXNlcyBkZSBkYXRvcywgcmVhbGl6YXIgZ3LDoWZpY29zIGRlc2NyaXB0aXZvcywgY3JlYXIgdGFibGFzLiBFcyB1biBlamVtcGxvIGRlbW9zdHJhdGl2bywgcXVlIGEgc3UgdmV6LCBlcyB1c2FkbyBwb3IgcXVpZW4gZXNjcmliZSBlc3RhcyBsw61uZWFzLCBwYXJhIGRlamFyIG5vdGEgZGUgbG9zIGPDs2RpZ29zLgoKU2nDqW50YXNlIGVuIGxhIGxpYmVydGFkIGRlIGNvcGlhciwgY29tcGFydGlyLCBjcml0aWNhciwgc2F0aXJpemFyLCByZXByb2R1Y2lyIGxhcyBpZGVhcyBkZWwgZG9jdW1lbnRvOyBjb21vIHRhbWJpw6luIHN1Z2VyaXIgbWVqb3JhcyB1IG9waW5hciBhY2VyY2EgZGVsIG1pc21vLgoKTGEgaW50ZXJwcmV0YWNpw7NuIHkgYW7DoWxpc2lzIGNvbmNlcHR1YWwgc2UgZGVqYSBhbCBsZWN0b3IgaW50ZXJlc2FkbyBlbiBsYSB0ZW3DoXRpY2EgcHJvcHVlc3RhIHBhcmEgZWwgZWplcmNpY2lvLgoKIyBEYXRvcwoKIyMgRnVlbnRlIGRlIGxhIGJhc2UgZGUgZGF0b3MKCkxhIGJhc2UgZGUgZGF0b3MgZnXDqSBvYnRlbmlkYSBlbCBkw61hIDEzIGRlIE5vdmllbWJyZSBkZSAyMDIwIGEgdHJhdsOpcyBkZSBsYSBww6FnaW5hIGRlIGRhdG9zIGFiaWVydG9zIGRlbCBnb2JpZXJubyBkZSBDb2xvbWJpYTogW2RhdG9zLmdvdi5jb10oaHR0cHM6Ly93d3cuZGF0b3MuZ292LmNvLykgIAoKCiFbXShpbWFnZW5lcy9kYXRvc19nb3YucG5nKQoKCgojIyBMZWN0dXJhIGRlIGRhdG9zCgpgYGB7cn0KbGlicmFyeShkYXRhLnRhYmxlKQpkYXRvcyA8LSBmcmVhZCgiQ2Fzb3NfcG9zaXRpdm9zX2RlX0NPVklELTE5X2VuX0NvbG9tYmlhLmNzdiIsCiAgICAgICAgICAgICAgIGVuY29kaW5nID0gIlVURi04IiwgbmEuc3RyaW5ncyA9ICJOL0EiKQoKZGF0b3NbZGF0b3MgPT0gIiJdIDwtIE5BCmBgYCAgCgpMYSBiYXNlIGRlIGRhdG9zIHRpZW5lICoxJzE2NS4zMjYqIGZpbGFzIHkgKjIzKiBjb2x1bW5hcyAodmFyaWFibGVzKS4KCgpgYGB7cn0KIyBkaW1lbnNpw7NuIGRlIGxhIGJhc2UgZGUgZGF0b3MKZGltKGRhdG9zKQpgYGAgIAojIyBNb3N0cmFyIGxvcyBwcmltZXJvcyAxMDAgZGF0b3MKCmBgYHtyfQpsaWJyYXJ5KERUKQpoZWFkKGRhdG9zLCAxMDApCmBgYAoKCgojIyBOb21icmVzIGRlIGxhcyB2YXJpYWJsZXMgbyBjb2x1bW5hcy4KClVuYSBkZXNjcmlwY2nDs24gY29tcGxldGEgZGUgbGFzIHZhcmlhYmxlcyBzZSBwcmVzZW50YSBlbiBlbCBzaXRpbyB3ZWIgZGUgW2RhdG9zIGFiaWVydG9zIGRlbCBnb2JpZXJubyBkZSBDb2xvbWJpYV0oaHR0cHM6Ly93d3cuZGF0b3MuZ292LmNvL1NhbHVkLXktUHJvdGVjY2ktbi1Tb2NpYWwvQ2Fzb3MtcG9zaXRpdm9zLWRlLUNPVklELTE5LWVuLUNvbG9tYmlhL2d0MmotOHlrcikuCgpgYGB7cn0KbmFtZXMoZGF0b3MpCmBgYAoKIyBFZGl0YXIgYmFzZSBkZSBkYXRvcwoKKiBTZSBlZGl0YXLDoW4gbG9zIG5vbWJyZXMgZGUgbGFzIHZhcmlhYmxlcyBjb24gZWwgb2JqZXRpdm8gZGUgcXVlIG5vIGdlbmVyZW4gY29uZnVzacOzbiBlbiBlbCBhbsOhbGlzaXMuICAKCiogU2UgcHJlY2lzYSB0ZW5lciBub21icmVzIGNvcnRvcyBwcmVmZXJpYmxlbWVudGUsIHF1ZSBubyBjb250ZW5nYW4gY2FyYWN0ZXJlcyBlc3BlY2lhbGVzIHRhbGVzIGNvbW8gKioiKSUoJsK0Jy8jwqghXCQqKi4gIAoKKiBUYW1wb2NvIGVzIHJlY29tZW5kYWJsZSBxdWUgY29udGVuZ2FuIGFjZW50b3MgY2FyYWN0ZXLDrXN0aWNvcyBkZWwgbGVuZ3VhamUgbmF0dXJhbCwgdGlsZGVzIG8gbGEgbGV0cmEgKirDsSoqIHBvciBlamVtcGxvLiAgCgoqIExhIHZhcmlhYmxlIGBldG5pYWAgdGllbmUgc2VpcyBuaXZlbGVzLCBlc3RhYmxlY2lkb3MgZGUgbGEgc2lxdWllbnRlIG1hbmVyYTogIAoKICAgICogMS4gSW5kw61nZW5hCgogICAgKiAyLiBST00KCiAgICAqIDMuIFJhaXphbAoKICAgICogNC4gUGFsZW5xdWVybwoKICAgICogNS4gTmVncm8KCiAgICAqIDYuIE90cm8gICAgCiAgICAKCgoqIGBmZWNoYV9ub3RpZmAgZXMgbGEgZmVjaGEgZGUgbm90aWZpY2FjacOzbiBhbnRlIGVsIFtTSVZJR0lMQV0oaHR0cDovL3BvcnRhbHNpdmlnaWxhLmlucy5nb3YuY28vKQoKKiBgZmVjaGFfZGlhZ25vc2AgRmVjaGEgZGUgY29uZmlybWFjacOzbiBwb3IgbGFib3JhdG9yaW8uICAKCgpgYGB7cn0KI2xpYnJlcsOtYXMKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoSG1pc2MpCmRhdG9zICU+JSAKICAjbm9tYnJlcyBkZSBsYXMgdmFyaWFibGVzIGVuIG1pbsO6c2N1bGFzCiAgY2xlYW5fbmFtZXMoKSAlPiUgCiAgI3NlbGVjY2lvbmFyIHkgcmVub21icmFyIGxhcyB2YXJpYWJsZXMgZGUgaW50ZXLDqXMKICBzZWxlY3QoZmVjaGFfc2ludG9tYXMgPSBmZWNoYV9kZV9pbmljaW9fZGVfc2ludG9tYXMsCiAgICAgICAgIGZlY2hhX2RpYWdub3MgPSBmZWNoYV9kZV9kaWFnbm9zdGljbywKICAgICAgICAgZmVjaGFfbm90aWYgPSBmZWNoYV9kZV9ub3RpZmljYWNpb24sCiAgICAgICAgIGZlY2hhX3JlY3UgPSBmZWNoYV9kZV9yZWN1cGVyYWNpb24sCiAgICAgICAgIGRlcGFydGFtZW50byA9IG5vbWJyZV9kZXBhcnRhbWVudG8sCiAgICAgICAgIG11bmljaXBpbyA9IG5vbWJyZV9tdW5pY2lwaW8sCiAgICAgICAgIGVkYWQsCiAgICAgICAgIHNleG8sCiAgICAgICAgIGNvbnRhZ2lvID0gdGlwb19kZV9jb250YWdpbywKICAgICAgICAgdWJpY2FjaW9uX2Nhc28gPSB1YmljYWNpb25fZGVsX2Nhc28sCiAgICAgICAgIGVzdGFkbywKICAgICAgICAgcGFpcyA9IG5vbWJyZV9kZWxfcGFpcywKICAgICAgICAgcmVjdXBlcmFkbywKICAgICAgICAgdGlwb19yZWN1cGVyYWNpb24gPSB0aXBvX2RlX3JlY3VwZXJhY2lvbiwKICAgICAgICAgZXRuaWEgPSBwZXJ0ZW5lbmNpYV9ldG5pY2EpICU+JSAKICBtdXRhdGUoI2NhbWJpYXIgYSBmb3JtYXRvIGZlY2hhIChkYXRlKQogICAgICAgICBmZWNoYV9zaW50b21hcyA9IGFzLkRhdGUoZmVjaGFfc2ludG9tYXMsIGZvcm1hdD0iJWQvJW0vJVkiKSwKICAgICAgICAgZmVjaGFfZGlhZ25vcyA9IGFzLkRhdGUoZmVjaGFfZGlhZ25vcywgZm9ybWF0PSIlZC8lbS8lWSIpLAogICAgICAgICBmZWNoYV9ub3RpZiA9IGFzLkRhdGUoZmVjaGFfbm90aWYsIGZvcm1hdD0iJWQvJW0vJVkiKSwKICAgICAgICAgZmVjaGFfcmVjdSA9IGFzLkRhdGUoZmVjaGFfcmVjdSwgZm9ybWF0PSIlZC8lbS8lWSIpLAogICAgICAgICAjZWRpdGFyIGxvcyB2YWxvcmVzIGRlIGxhIHZhcmlhYmxlIHNleG8KICAgICAgICAgc2V4byA9IGdzdWIoImYiLCAiRiIsIHNleG8pLAogICAgICAgICBzZXhvID0gZ3N1YigibSIsICJNIiwgc2V4byksCiAgICAgICAgICNlZGl0YXIgbm9tYnJlcyBkZSBsb3MgZGVwYXJ0YW1lbnRvcwogICAgICAgICBkZXBhcnRhbWVudG8gPSBjYXBpdGFsaXplKHRvbG93ZXIoZGVwYXJ0YW1lbnRvKSksCiAgICAgICAgIGRlcGFydGFtZW50byA9IGdzdWIoIlN0YSBtYXJ0YSBkLmUuIiwgIlN0YSBtYXJ0YSIsZGVwYXJ0YW1lbnRvKSwKICAgICAgICAgZGVwYXJ0YW1lbnRvID0gZ3N1YigiQXRsYW50aWNvIiwgIkF0bMOhbnRpY28iLGRlcGFydGFtZW50byksCiAgICAgICAgIGRlcGFydGFtZW50byA9IGdzdWIoIkJvZ290YSIsICJCb2dvdMOhIixkZXBhcnRhbWVudG8pLAogICAgICAgICBkZXBhcnRhbWVudG8gPSBnc3ViKCJCb3lhY2EiLCAiQm95YWPDoSIsZGVwYXJ0YW1lbnRvKSwKICAgICAgICAgZGVwYXJ0YW1lbnRvID0gZ3N1YigiQ2FxdWV0YSIsICJDYXF1ZXTDoSIsZGVwYXJ0YW1lbnRvKSwKICAgICAgICAgZGVwYXJ0YW1lbnRvID0gZ3N1YigiQ2hvY28iLCAiQ2hvY8OzIixkZXBhcnRhbWVudG8pLAogICAgICAgICBkZXBhcnRhbWVudG8gPSBnc3ViKCJDb3Jkb2JhIiwgIkPDs3Jkb2JhIixkZXBhcnRhbWVudG8pLAogICAgICAgICBkZXBhcnRhbWVudG8gPSBnc3ViKCJHdWFpbmlhIiwgIkd1YWluw61hIixkZXBhcnRhbWVudG8pLAogICAgICAgICBkZXBhcnRhbWVudG8gPSBnc3ViKCJOb3J0ZSBzYW50YW5kZXIiLCAiTm9ydGUgU2FudGFuZGVyIixkZXBhcnRhbWVudG8pLAogICAgICAgICBkZXBhcnRhbWVudG8gPSBnc3ViKCJWYWxsZSIsICJWYWxsZSBkZWwgQ2F1Y2EiLGRlcGFydGFtZW50byksCiAgICAgICAgICNlZGl0YXIgbm9tYnJlcyBkZSBsb3MgbXVuaWNpcGlvcwogICAgICAgICBtdW5pY2lwaW8gPSBjYXBpdGFsaXplKHRvbG93ZXIobXVuaWNpcGlvKSksCiAgICAgICAgICNlZGl0YXIgbG9zIHZhbG9yZXMgZGUgbGEgdmFyaWFibGUgZXN0YWRvCiAgICAgICAgIGVzdGFkbyA9IGdzdWIoIkxFVkUiLCAiTGV2ZSIsIGVzdGFkbyksCiAgICAgICAgIGVzdGFkbyA9IGdzdWIoImxldmUiLCAiTGV2ZSIsIGVzdGFkbyksCiAgICAgICAgIGVzdGFkbyA9IGdzdWIoIm1vZGVyYWRvIiwgIk1vZGVyYWRvIiwgZXN0YWRvKSwKICAgICAgICAgI2VkaXRhciBsb3MgdmFsb3JlcyBkZSBsYSB2YXJpYWJsZSBjb250YWdpbwogICAgICAgICBjb250YWdpbyA9IGdzdWIoIkVuIGVzdHVkaW8iLCAiZW5fZXN0dWRpbyIsY29udGFnaW8pLAogICAgICAgICBjb250YWdpbyA9IGdzdWIoIkVOIEVTVFVESU8iLCAiZW5fZXN0dWRpbyIsY29udGFnaW8pLAogICAgICAgICBjb250YWdpbyA9IGdzdWIoIkVuIEVzdHVkaW8iLCAiZW5fZXN0dWRpbyIsY29udGFnaW8pLAogICAgICAgICBjb250YWdpbyA9IGdzdWIoInJlbGFjaW9uYWRvIiwgIlJlbGFjaW9uYWRvIixjb250YWdpbyksCiAgICAgICAgIGNvbnRhZ2lvID0gZ3N1YigiUmVsYWNpb2FuZG8iLCAiUmVsYWNpb25hZG8iLGNvbnRhZ2lvKSwKICAgICAgICAgY29udGFnaW8gPSBnc3ViKCJSRUxBQ0lPTkFETyIsICJSZWxhY2lvbmFkbyIsY29udGFnaW8pLAogICAgICAgICAjZWRpdGFyIGxvcyB2YWxvcmVzIGRlIGxhIHZhcmlhYmxlIHBhaXMKICAgICAgICAgcGFpcyA9IGNhcGl0YWxpemUodG9sb3dlcihwYWlzKSksCiAgICAgICAgIHBhaXMgPSBnc3ViKCJBcmFiaWEgc2F1ZGl0YSIgLCAiQXJhYmlhIHNhdWTDrSIscGFpcyksCiAgICAgICAgIHBhaXMgPSBnc3ViKCJBcmFiaWEgc2F1ZGl0YSIgLCAiQXJhYmlhIHNhdWTDrSIscGFpcyksCiAgICAgICAgIHBhaXMgPSBnc3ViKCJFc3RhZG9zIHVuaWRvcyBkZSBhbWVyaWNhIiwgIkVzdGFkb3MgdW5pZG9zIixwYWlzKSwKICAgICAgICAgcGFpcyA9IGdzdWIoIkVzdGFkb3MgdW5pZG9zIGRlIGFtw6lyaWNhIiwgIkVzdGFkb3MgdW5pZG9zIixwYWlzKSwKICAgICAgICAgcGFpcyA9IGdzdWIoIk1leGljbyIgLCAiTcOpeGljbyIscGFpcyksCiAgICAgICAgIHBhaXMgPSBnc3ViKCJQYW5hbWEiICwgIlBhbmFtw6EiLHBhaXMpLAogICAgICAgICBwYWlzID0gZ3N1YigiUGVydSIgLCAiUGVyw7oiLHBhaXMpLAogICAgICAgICBwYWlzID0gZ3N1YigiUmVpbm8gdW5pZG8gZGUgZ3JhbiBicmV0YcOxYSBlIGlybGFuZGEgZGVsIG5vcnRlIiAsICJSZWlubyB1bmlkbyIscGFpcyksCiAgICAgICAgIHBhaXMgPSBnc3ViKCJSZXDDumJsaWNhIMOhcmFiZSBzaXJpYSIgLCAiU2lyaWEiLHBhaXMpLAogICAgICAgICAjZWRpdGFyIGxvcyB2YWxvcmVzIGRlIGxhIHZhcmlhYmxlIHJlY3VwZXJhZG8KICAgICAgICAgcmVjdXBlcmFkbyA9IGdzdWIoImZhbGxlY2lkbyIgLCAiRmFsbGVjaWRvIiwgcmVjdXBlcmFkbyksCiAgICAgICAgICNlZGl0YXIgbG9zIHZhbG9yZXMgZGUgbGEgdmFyaWFibGUgdWJpY2FjaW9uX2Nhc28KICAgICAgICAgdWJpY2FjaW9uX2Nhc28gPSBnc3ViKCJDQVNBIiAsICJDYXNhIiwgdWJpY2FjaW9uX2Nhc28pLAogICAgICAgICB1YmljYWNpb25fY2FzbyA9IGdzdWIoIkhvc3BpdGFsIFVDSSIgLCAiVUNJIiwgdWJpY2FjaW9uX2Nhc28pLAogICAgICAgICAjY29udmVydGlyIHZhcmlhYmxlIGV0bmlhIGVuIGZhY3RvcgogICAgICAgICBldG5pYSA9IGFzLmZhY3RvcihldG5pYSkpICU+JSAKICAjY29udmVydGlyIGxhcyB2YXJpYWJsZXMgcXVlIGVzdMOpbiBlbiBmb3JtYXRvIGNoYXJhY3RlciBhIGZvcm1hdG8gZmFjdG9yCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgYXMuZmFjdG9yKSAtPiBjb3ZpZApgYGAKCiMjIEJhc2UgZGUgZGF0b3MgZWRpdGFkYSwgcHJpbWVyb3MgMTAwIGRhdG9zCgpgYGB7cn0KaGVhZChjb3ZpZCwgMTAwKQpgYGAKCiMgRXhwb3J0YXIgbGEgYmFzZSBkZSBkYXRvcwoKU2UgZ3VhcmRhcsOhIGxhIGJhc2UgZGUgZGF0b3MgZWRpdGFkYSBlbiB1biBhcmNoaXZvIGAuY3N2YCBjb24gZWwgbm9tYnJlIGBkYXRvc19jb3ZpZC5jc3ZgLgoKYGBge3IgLCBldmFsPUZBTFNFfQp3cml0ZV9jc3YoeCA9IGNvdmlkLCBmaWxlID0gImRhdG9zX2NvdmlkLmNzdiIpCgpgYGAKCgojIFNlcmllcyBkZSB0aWVtcG8KCkxhcyBsw61uZWFzIHJvamFzIHZlcnRpY2FsZXMgcHVudGVhZGFzIHJlcHJlc2VudGFuIGFsZ3VuYXMgZmVjaGFzIGR1cmFudGUgbGEgcGFuZGVtaWE7IGRlIGl6cXVpZXJkYSBhIGRlcmVjaGE6CgoqIDE5IGRlIEp1bmlvIGRlIDIwMjAuIFtQcmltZXIgZMOtYSBzw61uIElWQV0oaHR0cHM6Ly9pZC5wcmVzaWRlbmNpYS5nb3YuY28vUGFnaW5hcy9wcmVuc2EvMjAyMC9Fc3RlLXZpZXJuZXMtMTktZGUtanVuaW8tc2UtcmVhbGl6YXJhLWVsLXByaW1lci1kaWEtc2luLUlWQS1lbi1Db2xvbWJpYS0yMDA2MTYuYXNweCkuCgoqIDMgZGUgSnVsaW8gZGUgMjAyMC4gW1NlZ3VuZG8gZMOtYSBzw61uIElWQV0oaHR0cHM6Ly9pZC5wcmVzaWRlbmNpYS5nb3YuY28vUGFnaW5hcy9wcmVuc2EvMjAyMC9TRUdVTkRPLURJQS1TSU4tSVZBLUVsLWNvbWVyY2lvLWhhLXJlZG9ibGFkby1zdXMtZXNmdWVyem9zLXBhcmEtaGFjZXItY3VtcGxpci1wcm90b2NvbG9zLWFmaXJtYS1GZW5hbGNvLTIwMDIwNy5hc3B4KS4KCiogMSBkZSBTZXB0aWVtYnJlIGRlIDIwMjAuIFtJbmljaWEgZWwgYWlzbGFtaWVudG8gc2VsZWN0aXZvXShodHRwczovL3d3dy5zZW1hbmEuY29tL25hY2lvbi9hcnRpY3Vsby9wcmVzaWRlbnRlLWR1cXVlLWFudW5jaWEtcXVlLWVsLTEtZGUtc2VwdGllbWJyZS1lbXBpZXphLWFpc2xhbWllbnRvLXNlbGVjdGl2by82OTY3NDAvKS4KCiogOSBkZSBPY3R1YnJlIGRlIDIwMjAuIFtFbGltaW5hdG9yaWFzIGNvcGEgZGVsIG11bmRvIGRlIGbDunRib2wgUWF0YXIgMjAyMl0oaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9zZWFyY2g/cT1lbGltaW5hdG9yaWFzK3FhdGFyKzIwMjIrY29sb21iaWEmb3E9ZWxpbWluYXRvcmlhKyZhcXM9Y2hyb21lLjEuNjlpNTdqNjlpNTkuMzM1MGowajQmc291cmNlaWQ9Y2hyb21lJmllPVVURi04I3NpZT1tOy9nLzExajRkazJwMTg7MjsvZy8xMjI2bW45ZDtkdDtmcDsxOzspCgoKIyMgQ2Fzb3MgVG90YWxlcyBwb3IgZMOtYQoKCmBgYHtyfQpsaWJyYXJ5KHBsb3RseSkKZ2dwbG90bHkoCiAgY292aWQgJT4lIAogIGdyb3VwX2J5KGZlY2hhX2RpYWdub3MpICU+JSAKICBzdW1tYXJpc2UoVG90YWwgPSBuKCkpICU+JQogIGdncGxvdCguLCBtYXBwaW5nID0gYWVzKHggPSBmZWNoYV9kaWFnbm9zLCB5ID0gVG90YWwpKSsKICBnZW9tX3BvaW50KGNvbG9yID0gImRhcmtjeWFuIikrCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjE1IGRheSIpICsKICBnZW9tX2xpbmUoY29sb3IgID0gImdyYXkiKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSwgY29sb3IgPSAiY29ybmZsb3dlcmJsdWUiKSsKICBnZW9tX3ZsaW5lICggeGludGVyY2VwdCA9IGFzLm51bWVyaWMoYXMuRGF0ZSAoIjIwMjAtMDYtMTkiKSksCiAgICAgICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiLCAKICAgICAgICAgICAgICAgY29sb3IgPSAiZmlyZWJyaWNrIiwgc2l6ZT0wLjUsIGFscGhhPTAuNSkrCiAgZ2VvbV92bGluZSAoIHhpbnRlcmNlcHQgPSBhcy5udW1lcmljKGFzLkRhdGUgKCIyMDIwLTA5LTAxIikpLAogICAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIiwgCiAgICAgICAgICAgICAgIGNvbG9yID0gImZpcmVicmljayIsIHNpemU9MC41LCBhbHBoYT0wLjUpKwogIGdlb21fdmxpbmUgKCB4aW50ZXJjZXB0ID0gYXMubnVtZXJpYyhhcy5EYXRlICgiMjAyMC0wNy0wMyIpKSwKICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIsIAogICAgICAgICAgICAgICBjb2xvciA9ICJmaXJlYnJpY2siLCBzaXplPTAuNSwgYWxwaGE9MC41KSsKICBnZW9tX3ZsaW5lICggeGludGVyY2VwdCA9IGFzLm51bWVyaWMoYXMuRGF0ZSAoIjIwMjAtMTAtOSIpKSwKICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIsIAogICAgICAgICAgICAgICBjb2xvciA9ICJmaXJlYnJpY2siLCBzaXplPTAuNSwgYWxwaGE9MC41KSsKICBsYWJzKHggPSAiRmVjaGEiLCB5ID0gIkNhc29zIiwgdGl0bGUgPSAiVG90YWwgQ2Fzb3MgcG9yIETDrWEiLAogICAgICAgc3VidGl0bGUgPSAiIiwgY2FwdGlvbiA9ICIiKSsKICB0aGVtZV9idygpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSkKICApICU+JSAKICBsYXlvdXQoaGVpZ2h0ID0gNTAwLCB3aWR0aCA9IDcwMCkKCmBgYAoKCgojIyBMb2dhcml0bW8gZGUgbG9zIGNhc29zIHRvdGFsZXMgcG9yIGTDrWEKCmBgYHtyfQpsaWJyYXJ5KHBsb3RseSkKZ2dwbG90bHkoCiAgY292aWQgJT4lIAogIGdyb3VwX2J5KGZlY2hhX2RpYWdub3MpICU+JSAKICBzdW1tYXJpc2UoVG90YWwgPSBuKCkpICU+JQogIGdncGxvdCguLCBtYXBwaW5nID0gYWVzKHggPSBmZWNoYV9kaWFnbm9zLCB5ID0gbG9nKFRvdGFsKSkpKwogIGdlb21fcG9pbnQoY29sb3IgPSAiZGFya2N5YW4iKSsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMTUgZGF5IikgKwogIGdlb21fbGluZShjb2xvciAgPSAiZ3JheSIpICsKICBnZW9tX3Ntb290aChzZSA9IEZBTFNFLCBjb2xvciA9ICJjb3JuZmxvd2VyYmx1ZSIpKwogIGdlb21fdmxpbmUgKCB4aW50ZXJjZXB0ID0gYXMubnVtZXJpYyhhcy5EYXRlICgiMjAyMC0wNi0xOSIpKSwKICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIsIAogICAgICAgICAgICAgICBjb2xvciA9ICJmaXJlYnJpY2siLCBzaXplPTAuNSwgYWxwaGE9MC41KSsKICBnZW9tX3ZsaW5lICggeGludGVyY2VwdCA9IGFzLm51bWVyaWMoYXMuRGF0ZSAoIjIwMjAtMDktMDEiKSksCiAgICAgICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiLCAKICAgICAgICAgICAgICAgY29sb3IgPSAiZmlyZWJyaWNrIiwgc2l6ZT0wLjUsIGFscGhhPTAuNSkrCiAgZ2VvbV92bGluZSAoIHhpbnRlcmNlcHQgPSBhcy5udW1lcmljKGFzLkRhdGUgKCIyMDIwLTA3LTAzIikpLAogICAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIiwgCiAgICAgICAgICAgICAgIGNvbG9yID0gImZpcmVicmljayIsIHNpemU9MC41LCBhbHBoYT0wLjUpKwogIGdlb21fdmxpbmUgKCB4aW50ZXJjZXB0ID0gYXMubnVtZXJpYyhhcy5EYXRlICgiMjAyMC0xMC05IikpLAogICAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIiwgCiAgICAgICAgICAgICAgIGNvbG9yID0gImZpcmVicmljayIsIHNpemU9MC41LCBhbHBoYT0wLjUpKwogIGxhYnMoeCA9ICJGZWNoYSIsIHkgPSAibG9nKENhc29zKSIsIHRpdGxlID0gIkVzY2FsYSBsb2dhcml0bWljYSBwYXJhIGNhc29zIGRpYXJpb3MiLAogICAgICAgc3VidGl0bGUgPSAiIiwgY2FwdGlvbiA9ICIiKSsKICB0aGVtZV9idygpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSkKICApICU+JSAKICBsYXlvdXQoaGVpZ2h0ID0gNTAwLCB3aWR0aCA9IDcwMCkKYGBgCgoKIyMgVG90YWwgY2Fzb3MgYWN1bXVsYWRvcyBkZWwgcGHDrXMKCmBgYHtyfQpnZ3Bsb3RseShjb3ZpZCAlPiUgCiAgZ3JvdXBfYnkoZmVjaGFfbm90aWYpICU+JSAKICBzdW1tYXJpc2UoVG90YWwgPSBuKCkpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgbXV0YXRlKFQuQWN1bXVsYWRvID0gY3Vtc3VtKFRvdGFsKSkgJT4lIAogIGdncGxvdChvdHJvLCBtYXBwaW5nID0gYWVzKHggPSBmZWNoYV9ub3RpZiwgeSA9IFQuQWN1bXVsYWRvKSkrCiAgZ2VvbV9saW5lKGNvbG9yID0gImFxdWFtYXJpbmU0Iiwgc2l6ZT0xKSsKICBnZW9tX3ZsaW5lICggeGludGVyY2VwdCA9IGFzLm51bWVyaWMoYXMuRGF0ZSAoIjIwMjAtMDYtMTkiKSksCiAgICAgICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiLCAKICAgICAgICAgICAgICAgY29sb3IgPSAiZmlyZWJyaWNrIiwgc2l6ZT0wLjUsIGFscGhhPTAuNSkrCiAgZ2VvbV92bGluZSAoIHhpbnRlcmNlcHQgPSBhcy5udW1lcmljKGFzLkRhdGUgKCIyMDIwLTA5LTAxIikpLAogICAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIiwgCiAgICAgICAgICAgICAgIGNvbG9yID0gImZpcmVicmljayIsIHNpemU9MC41LCBhbHBoYT0wLjUpKwogIGdlb21fdmxpbmUgKCB4aW50ZXJjZXB0ID0gYXMubnVtZXJpYyhhcy5EYXRlICgiMjAyMC0wNy0wMyIpKSwKICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIsIAogICAgICAgICAgICAgICBjb2xvciA9ICJmaXJlYnJpY2siLCBzaXplPTAuNSwgYWxwaGE9MC41KSsKICBnZW9tX3ZsaW5lICggeGludGVyY2VwdCA9IGFzLm51bWVyaWMoYXMuRGF0ZSAoIjIwMjAtMTAtOSIpKSwKICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIsIAogICAgICAgICAgICAgICBjb2xvciA9ICJmaXJlYnJpY2siLCBzaXplPTAuNSwgYWxwaGE9MC41KSsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMTUgZGF5IikgKwogIGxhYnMoeCA9ICJGZWNoYSIsIHkgPSAiQ2Fzb3MiLCB0aXRsZSA9ICJDYXNvcyBUb3RhbGVzIEFjdW11bGFkb3MgTmFjaW9uYWwiLAogICAgICAgc3VidGl0bGUgPSAiIiwgY2FwdGlvbiA9ICIiKSsKICB0aGVtZV9idygpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSkKKQpgYGAKCiMjIExvZ2FyaXRtbyBkZSB0b3RhbCBjYXNvcyBlbiBlbCBwYcOtcwoKYGBge3J9CmdncGxvdGx5KGNvdmlkICU+JSAKICBncm91cF9ieShmZWNoYV9ub3RpZikgJT4lIAogIHN1bW1hcmlzZShUb3RhbCA9IG4oKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBtdXRhdGUoVC5BY3VtdWxhZG8gPSBjdW1zdW0oVG90YWwpKSAlPiUgCiAgZ2dwbG90KG90cm8sIG1hcHBpbmcgPSBhZXMoeCA9IGZlY2hhX25vdGlmLCB5ID0gbG9nKFQuQWN1bXVsYWRvKSkpKwogIGdlb21fbGluZShjb2xvciA9ICJhcXVhbWFyaW5lNCIsIHNpemU9MSkrCiAgZ2VvbV92bGluZSAoIHhpbnRlcmNlcHQgPSBhcy5udW1lcmljKGFzLkRhdGUgKCIyMDIwLTA2LTE5IikpLAogICAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIiwgCiAgICAgICAgICAgICAgIGNvbG9yID0gImZpcmVicmljayIsIHNpemU9MC41LCBhbHBoYT0wLjUpKwogIGdlb21fdmxpbmUgKCB4aW50ZXJjZXB0ID0gYXMubnVtZXJpYyhhcy5EYXRlICgiMjAyMC0wOS0wMSIpKSwKICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIsIAogICAgICAgICAgICAgICBjb2xvciA9ICJmaXJlYnJpY2siLCBzaXplPTAuNSwgYWxwaGE9MC41KSsKICBnZW9tX3ZsaW5lICggeGludGVyY2VwdCA9IGFzLm51bWVyaWMoYXMuRGF0ZSAoIjIwMjAtMDctMDMiKSksCiAgICAgICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiLCAKICAgICAgICAgICAgICAgY29sb3IgPSAiZmlyZWJyaWNrIiwgc2l6ZT0wLjUsIGFscGhhPTAuNSkrCiAgZ2VvbV92bGluZSAoIHhpbnRlcmNlcHQgPSBhcy5udW1lcmljKGFzLkRhdGUgKCIyMDIwLTEwLTkiKSksCiAgICAgICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiLCAKICAgICAgICAgICAgICAgY29sb3IgPSAiZmlyZWJyaWNrIiwgc2l6ZT0wLjUsIGFscGhhPTAuNSkrCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjE1IGRheSIpICsKICBsYWJzKHggPSAiIiwgeSA9ICJsb2coY2Fzb3MpIiwgdGl0bGUgPSAiRXNjYWxhIExvZ2Fyw610bWljYSBDYXNvcyBBY3VtdWxhZG9zIE5hY2lvbmFsIiwKICAgICAgIHN1YnRpdGxlID0gIiIsIGNhcHRpb24gPSAiIikrCiAgdGhlbWVfYncoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSsKICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCkpCikKYGBgCgojIENhc29zIHRvdGFsZXMgcG9yIGRlcGFydGFtZW50bwoKVGFibGEgY29uIGVsIHRvdGFsIGRlIGNhc29zIHBvc2l0aXZvcyBlbiBjYWRhIGRlcGFydGFtZW50by4KCmBgYHtyfQpjb3ZpZCAlPiUgCiAgZ3JvdXBfYnkoZGVwYXJ0YW1lbnRvKSAlPiUgCiAgc3VtbWFyaXNlKFRvdGFsID0gbigpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGFycmFuZ2UoZGVzYyhUb3RhbCkpICU+JSAKICBkYXRhdGFibGUoZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgICAgZmlsdGVyID0gInRvcCIsCiAgICAgICAgICAgIHNlbGVjdGlvbiA9ICJtdWx0aXBsZSIsCiAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KGRvbSA9ICdCZnJ0aXAnLAogICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gYygnY3N2JywgJ2V4Y2VsJywgJ3BkZicpKSkKYGBgCgojIFZhcmlhY2nDs24gZGlhcmlhIHBvciBEZXBhcnRhbWVudG8KICAgIAoqKkVsIHB1bnRvIHJvam8gcmVwcmVzZW50YSBsYSBtZWRpYSoqICAgIAogICAgCmBgYHtyIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD03fQpnZ3Bsb3RseShjb3ZpZCAlPiUgCiAgZ3JvdXBfYnkoZGVwYXJ0YW1lbnRvLCBmZWNoYV9ub3RpZikgJT4lIAogIHN1bW1hcmlzZShUb3RhbCA9IG4oKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZ3JvdXBfYnkoZGVwYXJ0YW1lbnRvLCBmZWNoYV9ub3RpZikgJT4lIAogIHN1bW1hcmlzZShUb3RhbCA9IHN1bShUb3RhbCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKGRlcGFydGFtZW50bywgVG90YWwpLCB5ID0gVG90YWwpKSsKICBnZW9tX2JveHBsb3QoZmlsbCA9ICJjb3JuZmxvd2VyYmx1ZSIpKwogIGxhYnMoeCA9ICIiLCB5ID0gIkNhc29zIiwgdGl0bGUgPSAiIiwKICAgICAgIHN1YnRpdGxlID0gIiIsIGNhcHRpb24gPSAiIikrCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgZ2VvbSA9ICJwb2ludCIsIGNvbG9yID0gImZpcmVicmljayIpKwogIHNjYWxlX3lfbG9nMTAoKSsKICB0aGVtZV9idygpKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSkrCiAgY29vcmRfZmxpcCgpKQogIApgYGAKCgoKIyBSZXByZXNlbnRhY2nDs24gcG9yIGfDqW5lcm8gZGUgbG9zIGNhc29zIGFjdW11bGFkb3MKClNlcmllIGRlIHRpZW1wbyBkZSBsb3MgY2Fzb3MgcG9zaXRpdm9zIHByZXNlbnRhZG9zIHBvciBnw6luZXJvLgoKYGBge3J9CmdncGxvdGx5KAogIGNvdmlkJT4lIAogIGdyb3VwX2J5KHNleG8sIGZlY2hhX25vdGlmKSAlPiUgCiAgc3VtbWFyaXNlKFRvdGFsID0gbigpKSAlPiUKICBtdXRhdGUoVC5BY3VtdWxhZG8gPSBjdW1zdW0oVG90YWwpKSAlPiUgCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IGZlY2hhX25vdGlmLCB5ID0gVC5BY3VtdWxhZG8sIGNvbG9yID0gc2V4bykpKwogIGdlb21fbGluZShzaXplPTEsIGFscGhhPTAuNykrCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImFxdWFtYXJpbmUyIiwgImNob2NvbGF0ZTIiKSkrCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjE1IGRheSIpICsKICBsYWJzKHggPSAiRmVjaGEiLCB5ID0gIkNhc29zIiwgdGl0bGUgPSAiQ2Fzb3MgdG90YWxlcyBwb3IgZ8OpbmVybyIsCiAgICAgICBzdWJ0aXRsZSA9ICIiLCBjYXB0aW9uID0gIiIpKwogIHRoZW1lX2J3KCkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkrCiAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpKQogICkKYGBgCgojIExvZ2FyaXRtbyBjYXNvcyBhY3VtdWxhZG9zIHBvciBnw6luZXJvCgpTZXJpZSBkZSB0aWVtcG8gZW4gZXNjYWxhIGxvZ2FydMOtdG1pY2EgZGUgY2Fzb3MgYWN1bXVsYWRvcyBwb3IgZ8OpbmVyby4KCmBgYHtyfQpnZ3Bsb3RseSgKICBjb3ZpZCU+JSAKICBncm91cF9ieShzZXhvLCBmZWNoYV9ub3RpZikgJT4lIAogIHN1bW1hcmlzZShUb3RhbCA9IG4oKSkgJT4lCiAgbXV0YXRlKFQuQWN1bXVsYWRvID0gY3Vtc3VtKFRvdGFsKSkgJT4lIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBmZWNoYV9ub3RpZiwgeSA9IGxvZyhULkFjdW11bGFkbyksIGNvbG9yID0gc2V4bykpKwogIGdlb21fbGluZShzaXplPTEpKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJhcXVhbWFyaW5lMiIsICJjaG9jb2xhdGUyIikpKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxNSBkYXkiKSArCiAgbGFicyh4ID0gIkZlY2hhIiwgeSA9ICJsb2coY2Fzb3MpIiwgdGl0bGUgPSAiRXNjYWxhIGxvZ2Fyw610bWljYSBjYXNvcyB0b3RhbGVzIHBvciBnw6luZXJvIiwKICAgICAgIHN1YnRpdGxlID0gIiIsIGNhcHRpb24gPSAiIikrCiAgdGhlbWVfYncoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSsKICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCkpCiAgKQpgYGAKCiMgRGlzdHJpYnVjacOzbiBkZSBsb3MgY2Fzb3MgcHJlc2VudGFkb3MgcG9yIHNlbWFuYSB5IGfDqW5lcm8KCiMjIFZhcmlhY2nDs24gc2VtYW5hbAoKKiBFbiBsYSBzZW1hbmEgMjUgc2UgZW5jdWVudHJhIGVsIGTDrWEgMTkgZGUgSnVuaW8uIFByaW1lciBkw61hIHNpbiBJVkEuICAKCiogRW4gbGEgc2VtYW5hIDI3IHNlIGVuY3VlbnRyYSBlbCBkw61hIDMgZGUgSnVsaW8uIFNlZ3VuZG8gZMOtYSBzw61uIElWQS4gIAoKKiBFbiBsYSBzZW1hbmEgMzYgc2UgZW5jdWVudHJhIGVsIGTDrWEgMSBkZSBTZXB0aWVtYnJlLiBJbmljaWEgZWwgYWlzbGFtaWVudG8gc2VsZWN0aXZvLiAgCgoqIEVuIGxhIHNlbWFuYSA0MSB5IDQyIHNlIGVuY3VlbnRyYSBlbCA5IGRlIE9jdHVicmUgeSBlbCAxMyBkZSBPY3R1YnJlLiBFbGltaW5hdG9yaWFzIGNvcGEgbXVuZGlhbCBkZSBmw7p0Ym9sIFFhdGFyIDIwMjIuCgpgYGB7ciwgZmlnLmhlaWdodD01LjUsIGZpZy5hc3A9MX0KbGlicmFyeShnZ3JpZGdlcykKY292aWQgJT4lIAogIGdyb3VwX2J5KGZlY2hhX25vdGlmKSAlPiUgCiAgY291bnQobmFtZSA9ICJUb3RhbF9kaWEiKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZShTZW1hbmEgPSB3ZWVrKGZlY2hhX25vdGlmKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IFRvdGFsX2RpYSwgeSA9IGFzLmZhY3RvcihTZW1hbmEpKSkrCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhmaWxsID0gImNhZGV0Ymx1ZSIpK3RoZW1lX2J3KCkrCiAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpKSsKICBsYWJzKHggPSAiQ2Fzb3MgcG9yIGTDrWEiLCB5ID0gIlNlbWFuYSIsIHRpdGxlID0gIlZhcmlhY2nDs24gc2VtYW5hbCIpCiAgCmBgYAoKIyMgVmFyaWFjacOzbiBzZW1hbmFsIHBvciBnw6luZXJvCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcuYXNwPTF9CmNvdmlkICU+JSAKICBncm91cF9ieShmZWNoYV9ub3RpZiwgc2V4bykgJT4lIAogIGNvdW50KG5hbWUgPSAiVG90YWxfZGlhIikgJT4lCiAgdW5ncm91cCgpICU+JSAKICBtdXRhdGUoU2VtYW5hID0gd2VlayhmZWNoYV9ub3RpZikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBUb3RhbF9kaWEsIHkgPSBhcy5mYWN0b3IoU2VtYW5hKSwgZmlsbCA9IHNleG8pKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjYWRldGJsdWUiLCAiZmlyZWJyaWNrMiIpKSsKICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGFscGhhID0gMC43KSt0aGVtZV9idygpKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikrCiAgbGFicyh4ID0gIkNhc29zIHBvciBkw61hIiwgeSA9ICJTZW1hbmEiLCB0aXRsZSA9ICJWYXJpYWNpw7NuIHNlbWFuYWwgcG9yIGfDqW5lcm8iKQpgYGAKCiMgUmVwcmVzZW50YWNpw7NuIGdyw6FmaWNhIHBhcmEgbGFzIGVkYWRlcwoKIyMgR3LDoWZpY28gZGUgZGVuc2lkYWQgcG9yIGVkYWQuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBjb3ZpZCwgYWVzKGVkYWQpKSsKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjUsIGZpbGwgPSAiZGFya2N5YW4iKSsKICBsYWJzKHggPSAiRWRhZCIsIHkgPSAiRGVuc2lkYWQiLCB0aXRsZSA9ICJHcsOhZmljbyBkZSBkZW5zaWRhZCIsIHN1YnRpdGxlPSJEaXN0cmlidWNpw7NuIGRlIGNhc29zIHNlZ8O6biBsYSBlZGFkIikKYGBgCgojIyBHcsOhZmljbyBkZSBkZW5zaWRhZCBwb3IgZWRhZCB5IGfDqW5lcm8KCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGNvdmlkLCBhZXMoZWRhZCwgZmlsbCA9IHNleG8pKSsKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjUpKwogIGxhYnMoeCA9ICJFZGFkIiwgeSA9ICJEZW5zaWRhZCIsIHRpdGxlPSAiR3LDoWZpY28gZGUgZGVuc2lkYWQiLAogICAgICAgc3VidGl0bGUgPSAiRGlzdHJpYnVjacOzbiBjYXNvcyBzZWfDum4gbGEgZWRhZCB5IGVsIGfDqW5lcm8iKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjYWRldGJsdWUiLCAiZmlyZWJyaWNrMiIpKQpgYGAKCgojIyBHcsOhZmljbyBkZSB2aW9sw61uIHBvciBnw6luZXJvIHkgZWRhZGVzCgpVbiBkaWFncmFtYSBkZSB2aW9sw61uIHNlIHV0aWxpemEgcGFyYSB2aXN1YWxpemFyIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGRhdG9zIHkgc3UgZGVuc2lkYWQgZGUgcHJvYmFiaWxpZGFkLiBFc3RlIGdyw6FmaWNvIGVzIHVuYSBjb21iaW5hY2nDs24gZGUgdW4gZGlhZ3JhbWEgZGUgY2FqYXMgeSBiaWdvdGVzIHkgdW4gZGlhZ3JhbWEgZGUgZGVuc2lkYWQgZ2lyYWRvIHkgY29sb2NhZG8gYSBjYWRhIGxhZG8sIHBhcmEgbW9zdHJhciBsYSBmb3JtYSBkZSBkaXN0cmlidWNpw7NuIGRlIGxvcyBkYXRvcy4gW0Z1ZW50ZV0oaHR0cHM6Ly9kYXRhdml6Y2F0YWxvZ3VlLmNvbS9FUy9tZXRvZG9zL2RpYWdyYW1hX2RlX3Zpb2xpbi5odG1sIzp+OnRleHQ9VW4lMjBkaWFncmFtYSUyMGRlJTIwdmlvbCVDMyVBRG4lMjBzZSxkZSUyMGRpc3RyaWJ1Y2klQzMlQjNuJTIwZGUlMjBsb3MlMjBkYXRvcy4pCgoKYGBge3J9CmNvdmlkICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzZXhvLCB5ID0gZWRhZCkpKwogIGdlb21fdmlvbGluKGFlcyhjb2xvciA9IHNleG8sIGZpbGwgPSBzZXhvKSwgYWxwaGEgPSAwLjcpKwogIGdlb21fYm94cGxvdChhZXMoZmlsbCA9IHNleG8pLHdpZHRoID0gMC4yLCBvdXRsaWVyLmFscGhhID0gMC4wMSkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygibWVkaXVtcHVycGxlMiIsICJkYXJrc2xhdGVncmF5MyIpKSsKICBsYWJzKHggPSAiU2V4byIsIHkgPSAiRWRhZCIsIHRpdGxlID0gIkdyw6FmaWNvIGRlIHZpb2zDrW4gcGFyYSBlZGFkZXMgeSBnw6luZXJvIikKICAKYGBgCgoKCiMjIEdyYWZpY28gZGUgZGVuc2lkYWQgRWRhZC9Hw6luZXJvL0ZhbGxlY2lkbwoKU2UgZmlsdHJhbiBjYXNvcyBlbiBsb3MgcXVlIGVsIGVzdGFkbyBlcyBgRmFsbGVjaWRvYCBwYXJhIHJlcHJlc2VudGFybG9zIHBvciBnw6luZXJvIHkgZWRhZC4KCmBgYHtyfQpmYWxsZWNpZG8gPC0gY292aWQgJT4lIAogIGZpbHRlcihlc3RhZG8gPT0gIkZhbGxlY2lkbyIpCgpnZ3Bsb3QoZGF0YSA9IGZhbGxlY2lkbywgbWFwcGluZz1hZXMoeCA9IGVkYWQsIGZpbGwgPSBzZXhvKSkrCmdlb21fZGVuc2l0eShhbHBoYSA9IDAuNykrCmxhYnMoeD0iRWRhZCIsIHk9IkRlbnNpZGFkIiwgdGl0bGU9IkRpc3RyaWJ1Y2nDs24gZmFsbGVjaWRvcyBwb3IgZWRhZCB5IGfDqW5lcm8iKSsKc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZ29sZCIsICJkYXJrc2xhdGVncmF5MyIpKQoKICAKYGBgCgojIyBHcsOhZmljbyBkZSBkZW5zaWRhZCBFZGFkL0fDqW5lcm8vUmVjdXBlcmFkbwoKU2UgZmlsdHJhbiBsb3MgdmFsb3JlcyBkZSBgUmVjdXBlcmFkb2AgcGFyYSByZXByZXNlbnRhcmxvcyBwb3IgZ8OpbmVybyB5IGVkYWQuCgpgYGB7cn0KcmVjdXBlcmFkbyA8LSBjb3ZpZCAlPiUgCiAgZmlsdGVyKHJlY3VwZXJhZG8gPT0gIlJlY3VwZXJhZG8iKQoKZ2dwbG90KGRhdGEgPSBjb3ZpZCwgbWFwcGluZz1hZXMoeCA9IGVkYWQsIGZpbGwgPSBzZXhvKSkrCmdlb21fZGVuc2l0eShhbHBoYSA9IDAuNykrCmxhYnMoeCA9ICJFZGFkIiwgeT0iRGVuc2lkYWQiLCB0aXRsZT0iRGlzdHJpYnVjacOzbiByZWN1cGVyYWRvcyBwb3IgZ8OpbmVybyB5IGVkYWQiKSsKc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZ29sZCIsICJkYXJrc2xhdGVncmF5MyIpKQogIAogIApgYGAKCiMgRnJlY3VlbmNpYXMgcGFyYSBsYXMgdmFyaWFibGVzIGBwYWlzYCB5IGBldG5pYWAKCiMjIGBwYWlzYAoKVGFibGEgZGUgZnJlY3VlbmNpYXMgcGFyYSBsYSB2YXJpYWJsZSBgcGFpc2AuIEVuIG9yZGVuIGRlc2NlbmRlbnRlLgoKYGBge3J9CnNvcnQoZGVzYyh0YWJsZShjb3ZpZCRwYWlzKSkpCmBgYAoKIyMgYGV0bmlhYAoKRGVzY3JpcGNpw7NuIG9idGVuaWRhIGRlbCBzaXRpbyB3ZWI6CgoqMS1JbmTDrWdlbmEgMi1ST00gMy1SYWl6YWwgNC1QYWxlbnF1ZXJvIDUtTmVncm8gNi1PdHJvLiBFc3RhIHZhcmlhYmxlIHNlIGFjdHVhbGl6YXLDoSBjYWRhIHNlbWFuYS4gQURWRVJURU5DSUEgREUgUkVTUE9OU0FCSUxJREFEOiBMYSB2YXJpYWJsZSBldG5pYSBkZXBlbmRlIHRvdGFsbWVudGUgZGUgdHJlcyBjb3NhczogLSBFbCBjb3JyZWN0byBkaWxpZ2VuY2lhbWllbnRvIGRlIGxhIHZhcmlhYmxlIEV0bmlhIHBvciBsb3MgcHJvZmVzaW9uYWxlcyBkZSBzYWx1ZCBxdWUgbm90aWZpY2FuIGVuIG3DoXMgZGUgMTAuMDAwIGluc3RpdHVjaW9uZXMgZGUgc2FsdWQgZW4gdG9kb3MgbG9zIG11bmljaXBpb3MgeSBkZXBhcnRhbWVudG9zLiAtIERlbCBhdXRvcnJlY29ub2NpbWllbnRvIGRlIGxhIHBlcnNvbmEgY3VhbmRvIHNlIGxlIHByZWd1bnRhIHBvciBlc3RhIHZhcmlhYmxlLiAtIERlbCBsaXN0YWRvIGNlbnNhbCBxdWUgaGFnYSB5IG1hbnRlbmdhIGFjdHVhbGl6YWRvIGNhZGEgZGVwYXJ0YW1lbnRvLiBObyBkZXBlbmRlIGRlbCBJbnN0aXR1dG8gTmFjaW9uYWwgZGUgU2FsdWQsIHkgcG9yIGxvIHRhbnRvLCBlcyByZXNwb25zYWJpbGlkYWQgZGUgbGFzIGF1dG9yaWRhZGVzIGRlIGNhZGEgbXVuaWNpcGlvLCBkZXBhcnRhbWVudG8geSBkaXN0cml0byBkZSBDb2xvbWJpYTsgbGEgY2FsaWRhZCB5IGNvbnNpc3RlbmNpYSBkZSBkaWNoYSB2YXJpYWJsZSogCgpGcmVjdWVuY2lhcyBvYnRlbmlkYXMgcGFyYSBsYSB2YXJpYWJsZSBgZXRuaWFgLgoKYGBge3J9CnRhYmxlKGNvdmlkJGV0bmlhKQpgYGAKCgojIEdyw6FmaWNvcyBkZSBiYXJyYQoKU2UgcHJlc2VudGEgdW5hIGJyZXZlIGRlc2NyaXBjacOzbiBwYXJhIGFsZ3VuYXMgdmFyaWFibGVzLCB5IHNlIHJlcHJlc2VudGFuIGdyw6FmaWNhbWVudGUgYSB0cmF2w6lzIGRlIHVuIGRpYWdyYW1hIGRlIGJhcnJhcyBjb25qdW50by4gRW4gYWxndW5vcyBjYXNvcyBsYXMgYmFycmFzIGRlIGxhcyB2YXJpYWJsZXMgbm8gc2UgYXByZWNpYW4gZGViaWRvIGEgcXVlIGVzIGJhc3RhbnRlIHBlcXVlw7FhIGNvbXBhcmFkYSBjb24gbGFzIG90cmFzIHZhcmlhYmxlcyBwcmVzZW50ZXMuCgojIyBWYXJpYWJsZXMKCi0gYGNvbnRhZ2lvYDogTGEgYmFycmEgcGFyYSBlbCB2YWxvciBgSW1wb3J0YWRvYCBlcyBiYXN0YW50ZSBwZXF1ZcOxYSBjb21wYXJhZGEgY29uIGxhcyBvdHJhcyBkb3MgZGViaWRvIGEgcXVlIGxhIGRpZmVyZW5jaWEgZGUgY29udGFnaW9zIGVuIGVzdGUgcnVicm8gZXMgbXVjaG8gbWVub3I7IHBvciBsbyB0YW50byBubyBzZSBhcHJlY2lhIGVuIGVsIGdyw6FmaWNvIGRlIG1hbmVyYSBjb3JyZWN0YS4KCgoKLSAgYHViaWNhY2lvbl9jYXNvYDogKkNvcnJlc3BvbmRlIGEgbXVlcnRlcyBubyByZWxhY2lvbmFkYXMgY29uIENPVklELTE5LCBhw7puIHNpIGVyYW4gY2Fzb3MgYWN0aXZvcyAqKkhheSBwYWNpZW50ZXMgcmVjdXBlcmFkb3MgcGFyYSBDT1ZJRC0xOSwgcXVlIHB1ZWRlbiBwZXJtYW5lY2VyIGVuIGhvc3BpdGFsaXphY2nDs24gcG9yIG90cmFzIGNvbW9yYmlsaWRhZGVzLiogKERlc2NyaXBjacOzbiBvYnRlbmlkYSBkZSBsYSBww6FnaW5hIG9maWNpYWwgZGUgZGF0b3MgYWJpZXJ0b3MuKQoKCgotIGBlc3RhZG9gOiAqQ29ycmVzcG9uZGUgYSBtdWVydGVzIG5vIHJlbGFjaW9uYWRhcyBjb24gQ09WSUQtMTksIGHDum4gc2kgZXJhbiBjYXNvcyBhY3Rpdm9zICoqSGF5IHBhY2llbnRlcyByZWN1cGVyYWRvcyBwYXJhIENPVklELTE5LCBxdWUgcHVlZGVuIHBlcm1hbmVjZXIgZW4gaG9zcGl0YWxpemFjacOzbiBwb3Igb3RyYXMgY29tb3JiaWxpZGFkZXMuKiAoRGVzY3JpcGNpw7NuIG9idGVuaWRhIGRlIGxhIHDDoWdpbmEgb2ZpY2lhbCBkZSBkYXRvcyBhYmllcnRvcy4pCgoKCi0gYHJlY3VwZXJhZG9gOiAqUmVjdXBlcmFkbyBGYWxsZWNpZG8gTi9BIChWYWPDrW8pLiBOL0Egc2UgcmVmaWVyZSBhIGxvcyBmYWxsZWNpZG9zIG5vIENPVklELiBQdWVkZW4gaGFiZXIgY2Fzb3MgcmVjdXBlcmFkb3MgY29uIHViaWNhY2nDs24gSG9zcGl0YWwgdSBIb3NwaXRhbCBVQ0ksIHlhIHF1ZSBwZXJtYW5lY2VuIGVuIGhvc3BpdGFsaXphY2nDs24gcG9yIGNhdXNhcyBkaWZlcmVudGVzLiBMb3MgY2Fzb3MgY29uIGluZm9ybWFjacOzbiBlbiBibGFuY28gZW4gZXN0YSBjb2x1bW5hIGNvcnJlc3BvbmRlIGEgbG9zIGNhc29zIGFjdGl2b3MqIChEZXNjcmlwY2nDs24gb2J0ZW5pZGEgZGUgbGEgcMOhZ2luYSBvZmljaWFsIGRlIGRhdG9zIGFiaWVydG9zLikKCgoKLSBgdGlwb19yZWN1cGVyYWNpb25gCgoKCgoKLSBgdGlwb19yZWN1cGVyYWNpb25gOiAqU2UgcmVmaWVyZSBhIGxhIHZhcmlhYmxlIGRlIHRpcG8gZGUgcmVjdXBlcmFjacOzbiBxdWUgdGllbmUgZG9zIG9wY2lvbmVzOiBQQ1IgeSB0aWVtcG8uIFBDUiBpbmRpY2EgcXVlIGxhIHBlcnNvbmEgc2UgZW5jdWVudHJhIHJlY3VwZXJhZGEgcG9yIHNlZ3VuZGEgbXVlc3RyYSwgZW4gZG9uZGUgZGlvIG5lZ2F0aXZvIHBhcmEgZWwgdmlydXM7IG1pZW50cmFzIHF1ZSB0aWVtcG8gc2lnbmlmaWNhIHF1ZSBzb24gcGVyc29uYXMgcXVlIGN1bXBsaWVyb24gMzAgZMOtYXMgcG9zdGVyaW9yZXMgYWwgaW5pY2lvIGRlIHPDrW50b21hcyBvIHRvbWEgZGUgbXVlc3RyYXMgcXVlIG5vIHRpZW5lbiBzw61udG9tYXMsIHF1ZSBubyB0ZW5nYW4gbcOhcyBkZSA3MCBhw7FvcyBuaSBxdWUgZXN0w6luIGhvc3BpdGFsaXphZG9zLiogKERlc2NyaXBjacOzbiBvYnRlbmlkYSBkZSBsYSBww6FnaW5hIG9maWNpYWwgZGUgZGF0b3MgYWJpZXJ0b3MuKQoKCmBgYHtyLCBmaWcud2lkdGg9MTEsIGZpZy5oZWlnaHQ9N30KbGlicmFyeShjb3dwbG90KQoKZzEgPC0gZ2dwbG90KGRhdGEgPSBjb3ZpZCwgYWVzKHggPSBjb250YWdpbykpICsKZ2VvbV9iYXIoc3RhdCA9ICJjb3VudCIsIGZpbGwgPSAiY29ybmZsb3dlcmJsdWUiKSArIApzdGF0X2NvdW50KGdlb20gPSAidGV4dCIsIGNvbG91ciA9ICJibGFjayIsIHNpemUgPSAzLjUsCmFlcyhsYWJlbCA9IC4uY291bnQuLikscG9zaXRpb249cG9zaXRpb25fc3RhY2sodmp1c3Q9MC43KSkrCiAgbGFicyh4ID0gIiIsIHkgPSAiIiwKICAgICAgIHRpdGxlID0gIkZyZWN1ZW5jaWEgVGlwb3MgZGUgQ29udGFnaW8iKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkKCmcyIDwtIGdncGxvdChkYXRhID0gY292aWQsIGFlcyh4ID0gdWJpY2FjaW9uX2Nhc28pKSArCmdlb21fYmFyKHN0YXQgPSAiY291bnQiLCBmaWxsID0gImNvcm5mbG93ZXJibHVlIikgKyAKc3RhdF9jb3VudChnZW9tID0gInRleHQiLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMy41LAphZXMobGFiZWwgPSAuLmNvdW50Li4pLHBvc2l0aW9uPXBvc2l0aW9uX3N0YWNrKHZqdXN0PTEuMSkpKwogIGxhYnMoeCA9ICIiLCB5ID0gIiIsCiAgICAgICB0aXRsZSA9ICJGcmVjdWVuY2lhIFViaWNhY2nDs24gQ2FzbyIpKwogIHRoZW1lX21pbmltYWwoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQoKZzMgPC0gZ2dwbG90KGRhdGEgPSBjb3ZpZCwgYWVzKHggPSBlc3RhZG8pKSArCmdlb21fYmFyKHN0YXQgPSAiY291bnQiLCBmaWxsID0gImNvcm5mbG93ZXJibHVlIikgKyAKc3RhdF9jb3VudChnZW9tID0gInRleHQiLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMy41LAphZXMobGFiZWwgPSAuLmNvdW50Li4pLHBvc2l0aW9uPXBvc2l0aW9uX3N0YWNrKHZqdXN0PTEuMSkpKwogIGxhYnMoeCA9ICIiLCB5ID0gIiIsCiAgICAgICB0aXRsZSA9ICJGcmVjdWVuY2lhIGRlIGxhIFZhcmlhYmxlIEVzdGFkbyIpKwogIHRoZW1lX21pbmltYWwoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQoKZzQgPC0gZ2dwbG90KGRhdGEgPSBjb3ZpZCwgYWVzKHggPSByZWN1cGVyYWRvKSkgKwpnZW9tX2JhcihzdGF0ID0gImNvdW50IiwgZmlsbCA9ICJjb3JuZmxvd2VyYmx1ZSIpICsgCnN0YXRfY291bnQoZ2VvbSA9ICJ0ZXh0IiwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDMuNSwKYWVzKGxhYmVsID0gLi5jb3VudC4uKSxwb3NpdGlvbj1wb3NpdGlvbl9zdGFjayh2anVzdD0xLjEpKSsKICBsYWJzKHggPSAiIiwgeSA9ICIiLAogICAgICAgdGl0bGUgPSAiRnJlY3VlbmNpYSBkZSBSZWN1cGVyYWRvIikrCiAgdGhlbWVfbWluaW1hbCgpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCgpnNSA8LSBnZ3Bsb3QoZGF0YSA9IGNvdmlkLCBhZXMoeCA9IHRpcG9fcmVjdXBlcmFjaW9uKSkgKwpnZW9tX2JhcihzdGF0ID0gImNvdW50IiwgZmlsbCA9ICJjb3JuZmxvd2VyYmx1ZSIpICsgCnN0YXRfY291bnQoZ2VvbSA9ICJ0ZXh0IiwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDMuNSwKYWVzKGxhYmVsID0gLi5jb3VudC4uKSxwb3NpdGlvbj1wb3NpdGlvbl9zdGFjayh2anVzdD0wLjUpKSsKICBsYWJzKHggPSAiIiwgeSA9ICIiLAogICAgICAgdGl0bGUgPSAiRnJlY3VlbmNpYSBUaXBvIGRlIFJlY3VwZXJhY2nDs24iKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkKCgpwbG90X2dyaWQoZzEsIGcyLCBnMywgZzQsIGc1LCBzY2FsZSA9IDEpCmBgYAoKCiMgR3LDoWZpY29zIGRlIGRlbnNpZGFkCgojIyBEaXN0cmlidWNpw7NuIHBhcmEgbGEgdmFyaWFibGUgYGNvbnRhZ2lvYAoKYGBge3J9CmNvdmlkICU+JSAKICBnZ3Bsb3QoZGF0YSA9IGNvdmlkLCBtYXBwaW5nID0gYWVzKHggPSBlZGFkLCBmaWxsID0gY29udGFnaW8pKSsKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjcpKwogIGxhYnMoeCA9ICJFZGFkIiwgeT0iRGVuc2lkYWQiLCB0aXRsZT0iRGlzdHJpYnVjacOzbiBkZSB0aXBvIGRlIGNvbnRhZ2lvIHBvciBlZGFkIikKYGBgCgojIyBEaXN0cmlidWNpw7NuIGRlIGxhIHZhcmlhYmxlIGB1YmljYWNpb25fY2Fzb2AKCmBgYHtyfQpjb3ZpZCAlPiUgCiAgZ2dwbG90KGRhdGEgPSBjb3ZpZCwgbWFwcGluZyA9IGFlcyh4ID0gZWRhZCwgZmlsbCA9IHViaWNhY2lvbl9jYXNvKSkrCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC43KSsKICBsYWJzKHggPSAiRWRhZCIsIHk9IkRlbnNpZGFkIiwgdGl0bGU9IkRpc3RyaWJ1Y2nDs24gdWJpY2FjacOzbiBkZSBsb3MgY2Fzb3MgcG9yIGVkYWQiKQpgYGAKCiMjIERpc3RyaWJ1Y2nDs24gZGUgbGEgdmFyaWFibGUgYGVzdGFkb2AKCmBgYHtyfQpjb3ZpZCAlPiUgCiAgZ2dwbG90KGRhdGEgPSBjb3ZpZCwgbWFwcGluZyA9IGFlcyh4ID0gZWRhZCwgZmlsbCA9IGVzdGFkbykpKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNykrCiAgbGFicyh4ID0gIkVkYWQiLCB5PSJEZW5zaWRhZCIsIHRpdGxlPSJEaXN0cmlidWNpw7NuIGRlbCBlc3RhZG8gcG9yIGVkYWQiKQpgYGAKIyMgRGlzdHJpYnVjacOzbiBkZSBsYSB2YXJpYWJsZSBgcmVjdXBlcmFkb2AKCmBgYHtyfQpjb3ZpZCAlPiUgCiAgZ2dwbG90KGRhdGEgPSBjb3ZpZCwgbWFwcGluZyA9IGFlcyh4ID0gZWRhZCwgZmlsbCA9IHJlY3VwZXJhZG8pKSsKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjcpKwogIGxhYnMoeCA9ICJFZGFkIiwgeT0iRGVuc2lkYWQiLCB0aXRsZT0iRGlzdHJpYnVjacOzbiBkZSByZWN1cGVyYWRvcyBwb3IgZWRhZCIpCmBgYAojIyBEaXN0cmlidWNpw7NuIGRlIGxhIHZhcmlhYmxlIGB0aXBvX3JlY3VwZXJhY2lvbmAKCmBgYHtyfQpjb3ZpZCAlPiUgCiAgZ2dwbG90KGRhdGEgPSBjb3ZpZCwgbWFwcGluZyA9IGFlcyh4ID0gZWRhZCwgZmlsbCA9IHRpcG9fcmVjdXBlcmFjaW9uKSkrCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC43KSsKICBsYWJzKHggPSAiRWRhZCIsIHk9IkRlbnNpZGFkIiwgdGl0bGU9IkRpc3RyaWJ1Y2nDs24gZGUgcmVjdXBlcmFkb3MgcG9yIGVkYWQiKSsKICBmYWNldF9ncmlkKCkKYGBgCgoKIyBUYWJsYXMKCiMjIFRhYmxhIHJlc3VtZW4gcG9yIGNpdWRhZAoKYGBge3J9CmNpdWRhZDEgPC0gY292aWQgJT4lIAogIGdyb3VwX2J5KG11bmljaXBpbywgZGVwYXJ0YW1lbnRvLCBjb250YWdpbykgJT4lIAogIHN1bW1hcmlzZShUb3RhbCA9IG4oKSkgJT4lIAogIHVuZ3JvdXAoKQoKY2l1ZGFkMTEgPC0gIHNwcmVhZChkYXRhID0gY2l1ZGFkMSwga2V5ID0gY29udGFnaW8sIHZhbHVlID0gVG90YWwpICU+JSAKICBkYXRhdGFibGUoZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgICAgZmlsdGVyID0gInRvcCIsCiAgICAgICAgICAgIHNlbGVjdGlvbiA9ICJtdWx0aXBsZSIsCiAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KGRvbSA9ICdCZnJ0aXAnLAogICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gYygnY3N2JywgJ2V4Y2VsJywgJ3BkZicpKSkKCmNpdWRhZDExCmBgYAoKYGBge3J9CmNpdWRhZDIgPC0gY292aWQgJT4lIAogIGdyb3VwX2J5KG11bmljaXBpbywgZGVwYXJ0YW1lbnRvLCB1YmljYWNpb25fY2FzbykgJT4lIAogIHN1bW1hcmlzZShUb3RhbCA9IG4oKSkgJT4lIAogIHVuZ3JvdXAoKQoKY2l1ZGFkMjIgPC0gIHNwcmVhZChkYXRhID0gY2l1ZGFkMiwga2V5ID0gdWJpY2FjaW9uX2Nhc28sIHZhbHVlID0gVG90YWwpICU+JSAKICBkYXRhdGFibGUoZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgICAgZmlsdGVyID0gInRvcCIsCiAgICAgICAgICAgIHNlbGVjdGlvbiA9ICJtdWx0aXBsZSIsCiAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KGRvbSA9ICdCZnJ0aXAnLAogICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gYygnY3N2JywgJ2V4Y2VsJywgJ3BkZicpKSkKCmNpdWRhZDIyCmBgYAoKYGBge3J9CmNpdWRhZDMgPC0gY292aWQgJT4lIAogIGdyb3VwX2J5KG11bmljaXBpbywgZGVwYXJ0YW1lbnRvLCBlc3RhZG8pICU+JSAKICBzdW1tYXJpc2UoVG90YWwgPSBuKCkpICU+JSAKICB1bmdyb3VwKCkKCmNpdWRhZDMzIDwtICBzcHJlYWQoZGF0YSA9IGNpdWRhZDMsIGtleSA9IGVzdGFkbywgdmFsdWUgPSBUb3RhbCkgJT4lIAogIGRhdGF0YWJsZShleHRlbnNpb25zID0gJ0J1dHRvbnMnLAogICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgICBmaWx0ZXIgPSAidG9wIiwKICAgICAgICAgICAgc2VsZWN0aW9uID0gIm11bHRpcGxlIiwKICAgICAgICAgICAgb3B0aW9ucyA9IGxpc3QoZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBjKCdjc3YnLCAnZXhjZWwnLCAncGRmJykpKQoKY2l1ZGFkMzMKYGBgCgpgYGB7cn0KY2l1ZGFkNCA8LSBjb3ZpZCAlPiUgCiAgZ3JvdXBfYnkobXVuaWNpcGlvLCBkZXBhcnRhbWVudG8sIHJlY3VwZXJhZG8pICU+JSAKICBzdW1tYXJpc2UoVG90YWwgPSBuKCkpICU+JSAKICB1bmdyb3VwKCkKCmNpdWRhZDQ0IDwtICBzcHJlYWQoZGF0YSA9IGNpdWRhZDQsIGtleSA9IHJlY3VwZXJhZG8sIHZhbHVlID0gVG90YWwpICU+JSAKICBkYXRhdGFibGUoZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywKICAgICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgICAgZmlsdGVyID0gInRvcCIsCiAgICAgICAgICAgIHNlbGVjdGlvbiA9ICJtdWx0aXBsZSIsCiAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KGRvbSA9ICdCZnJ0aXAnLAogICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gYygnY3N2JywgJ2V4Y2VsJywgJ3BkZicpKSkKCmNpdWRhZDQ0CmBgYAoKYGBge3J9CmNpdWRhZDUgPC0gY292aWQgJT4lIAogIGdyb3VwX2J5KG11bmljaXBpbywgZGVwYXJ0YW1lbnRvLCB0aXBvX3JlY3VwZXJhY2lvbikgJT4lIAogIHN1bW1hcmlzZShUb3RhbCA9IG4oKSkgJT4lIAogIHVuZ3JvdXAoKQoKY2l1ZGFkNTUgPC0gIHNwcmVhZChkYXRhID0gY2l1ZGFkNSwga2V5ID0gdGlwb19yZWN1cGVyYWNpb24sIHZhbHVlID0gVG90YWwpICU+JQogIGRhdGF0YWJsZShleHRlbnNpb25zID0gJ0J1dHRvbnMnLAogICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgICBmaWx0ZXIgPSAidG9wIiwKICAgICAgICAgICAgc2VsZWN0aW9uID0gIm11bHRpcGxlIiwKICAgICAgICAgICAgb3B0aW9ucyA9IGxpc3QoZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBjKCdjc3YnLCAnZXhjZWwnLCAncGRmJykpKQoKY2l1ZGFkNTUKYGBg