1. ¿Por qué este cuaderno?

Este es un cuaderno de R Markdown que ilustra cartografía temática para el departamento de Cauca en Colombia, Este cuaderno tiene como objetivo aprender a hacer mapas temáticos en R para la materia de Geomatica Básica de la Universidad Nacional.

2. Cartografía temática

Como dice Amanda Briney, un mapa temático enfatiza un tema o asunto, como la distribución promedio de las precipitaciones en un área o la densidad de población en un municipio. Se diferencian de los mapas de referencia generales porque no solo muestran características naturales y creadas por el hombre, como ríos, ciudades, subdivisiones políticas y carreteras. Si estos elementos aparecen en un mapa temático, son puntos de referencia para mejorar la comprensión del tema y el propósito del mapa.

Según Briney, “el factor más importante a considerar al diseñar mapas temáticos es la audiencia del mapa, que ayuda a determinar qué elementos deben incluirse en el mapa como puntos de referencia además del tema. Un mapa que se está haciendo para un científico político, por ejemplo, necesitaría mostrar límites políticos, mientras que uno para un biólogo podría necesitar contornos que muestren la elevación”.

Las fuentes de los datos de los mapas temáticos son muy importantes, enfatiza Briney. “Los cartógrafos deben encontrar fuentes de información precisas, recientes y confiables sobre una amplia gama de temas, desde características ambientales hasta datos demográficos, para hacer los mejores mapas posibles”.

Briney resume varias técnicas de mapeo temático que se utilizan con mayor frecuencia: ## 2.1 Mapa de coroplético que representa datos cuantitativos como un color y puede mostrar densidad, porcentaje, valor promedio o cantidad de un evento dentro de un área geográfica. Los colores secuenciales representan valores de datos positivos o negativos crecientes o decrecientes. Normalmente, cada color también representa un rango de valores.

2.2 Mapa de símbolos proporcionales o graduados

que se utilizan en otro tipo de mapa para representar datos asociados con ubicaciones, como ciudades. Los datos se muestran en estos mapas con símbolos de tamaño proporcional para mostrar diferencias en las ocurrencias. Los círculos se utilizan con mayor frecuencia, pero también son adecuados los cuadrados y otras formas geométricas. La forma más común de dimensionar estos símbolos es hacer que sus áreas sean proporcionales a los valores que se van a representar utilizando software de mapeo o dibujo.

2.3 Mapa isarítmico o de contorno

que utiliza isolíneas para representar valores continuos como los niveles de precipitación. Estos mapas también pueden mostrar valores tridimensionales, como la elevación, en mapas topográficos. Generalmente, los datos para mapas isarítmicos se recopilan a través de puntos medibles (por ejemplo, estaciones meteorológicas) o se recopilan por área (por ejemplo, toneladas de maíz por acre por condado). Los mapas isarítmicos también siguen la regla básica de que hay lados altos y bajos en relación con la isolina. Por ejemplo, en elevación, si la isolínea es de 500 pies, entonces un lado debe tener más de 500 pies y un lado debe ser más bajo.

2.4 Mapa de puntos

que utiliza puntos para mostrar la presencia de un tema y mostrar un patrón espacial. Un punto puede representar una unidad o varias, dependiendo de lo que se esté representando.

3. Datos

Usaremos datos sobre Necesidades Básicas Insatisfechas (NBI) del Censo Nacional de Población y Vivienda 2018 que están disponibles en el Geoportal del DANE.

Los mapas temáticos son útiles para transmitir información demográfica. Puede explorar varios mapas temáticos del DANE usando este enlace.

Anteriormente, descargué el archivo NBI, en formato .xlsx, a mi computadora. Luego, usé Excel para eliminar datos de municipios que no se encuentran dentro del Departamento de Cauca. También “limpié” los datos, que eliminé varias filas con imágenes institucionales o sin información. Estas filas se ubicaron tanto al principio como al final del archivo original. Conservo las columnas referentes a todo el municipio. Guardé los datos resultantes, correspondientes solo a los municipios de Cauca como NBI_Cauca.xlsx.

4. Preparación

Limpiemos la memoria:

rm(list=ls())

Ahora, instalemos las bibliotecas que necesitamos.

list.of.packages <- c("tidyverse", "rgeos", "sf", "raster", "cartography", "SpatialPosition")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) install.packages(new.packages)

Luego, carguemos las bibliotecas.

library(tidyverse)
library(readxl) ## this library is part of the tidyverse
library(rgeos)
library(raster)
library(sf)
library(cartography)
library(SpatialPosition)

5. Leer datos de NBI

Leamos el archivo csv con “estadisticas municipales agropecuarias” para Cauca.

nbi <- read_excel("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/informe dos/NBI_Cauca2.xlsx")

Veamos cuáles son los atributos de los datos.

head(nbi)
nbi2<-nbi
nbi2$cod_mun <-  as.character(nbi2$COD_MUN)
nbi2$MPIO_CCDGO <- as.factor(paste(19, nbi2$cod_mun, sep=""))

Busquemos cuál es el municipio con el porcentaje más alto de NBI:

nbi2 %>% 
    slice(which.max(NBI)) -> max_nbi

max_nbi

Busquemos cuál es el municipio con el porcentaje más bajo de NBI:

nbi2 %>% 
    slice(which.min(NBI)) -> min_nbi

min_nbi

Clasifiquemos los municipios por NBI en orden descendente:

nbi2 %>% 
  arrange(desc(NBI))  -> desc_nbi

desc_nbi

6. Unión de datos del NBI a los municipios

Comencemos a leer los datos administrativos de Cauca, dados por Marco Geoestadistico Departamental que se encuentra disponible en DANE Geoportal, usando la biblioteca sf:

munic <-st_read("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/Departamento/19_CAUCA/Cauca/ADMINISTRATIVO/MGN_MPIO_POLITICO.shp")
Reading layer `MGN_MPIO_POLITICO' from data source `C:\Users\rojas\OneDrive\Escritorio\R estudio\Geomatica\Departamento\19_CAUCA\Cauca\ADMINISTRATIVO\MGN_MPIO_POLITICO.shp' using driver `ESRI Shapefile'
Simple feature collection with 42 features and 9 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: -77.92834 ymin: 0.9580285 xmax: -75.74782 ymax: 3.328941
geographic CRS: WGS 84

Veamos qué hay dentro del atributo MPIO_CCDGO:

head(munic$MPIO_CCDGO)
[1] "19001" "19022" "19050" "19075" "19100" "19110"

Podemos usar la función left_join para unir los municipios y los datos de NBI.

nbi_munic = left_join(munic, nbi2, by=c("MPIO_CCDGO"))
nbi_munic %>%
  dplyr::select(MUNICIPIO, MPIO_CCDGO, NBI)  ->  check_nbi_munic

head(check_nbi_munic)
Simple feature collection with 6 features and 3 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: -77.40332 ymin: 1.635924 xmax: -76.38534 ymax: 3.233706
geographic CRS: WGS 84
     MUNICIPIO MPIO_CCDGO       NBI                       geometry
1      POPAYÁN      19001  8.798795 POLYGON ((-76.74145 2.57230...
2     ALMAGUER      19022 32.935908 POLYGON ((-76.80864 1.98674...
3      ARGELIA      19050 23.332497 POLYGON ((-77.3107 2.508326...
4       BALBOA      19075 20.128015 POLYGON ((-77.1431 2.156948...
5      BOLÍVAR      19100 27.177544 POLYGON ((-76.92984 2.11058...
6 BUENOS AIRES      19110 14.911238 POLYGON ((-76.76916 3.23128...

Ahora reproyectemos los datos

nbi_munic_new <- st_transform(nbi_munic, crs = 3116)

7. Ejemplos de mapas temáticos

Utilizaremos el paquete de cartografía que tiene como objetivo obtener mapas temáticos con la calidad visual de los construidos con un software clásico de cartografía o GIS. Sus funciones son intuitivas para los usuarios y garantizan la compatibilidad con los flujos de trabajo comunes de R.

La biblioteca de cartografía utiliza objetos sf o sp para producir gráficos base. Como la mayoría de los componentes internos del paquete se basan en funcionalidades sf, el formato preferido para los objetos espaciales es sf.

7. 1 Mapa base y símbolos proporcionales de OpenStreetMap

Las funciones getTiles () y tilesLayer () descargan y muestran mosaicos de OpenStreetMap. Tenga cuidado de citar la fuente de los mosaicos de manera adecuada.

propSymbolsLayer () muestra símbolos con áreas proporcionales a una variable cuantitativa (por ejemplo, NBI). Hay varios símbolos disponibles (círculos, cuadrados, barras). El argumento pulgadas se utiliza para personalizar los tamaños de los símbolos.

mun.osm <- getTiles(
x = nbi_munic_new, 
type = "OpenStreetMap", 
zoom = 10,
cachedir = TRUE,
crop = FALSE
)
Discarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded datum Unknown based on GRS80 ellipsoid in CRS definition,
 but +towgs84= values preservedDiscarded datum Unknown based on GRS80 ellipsoid in CRS definition,
 but +towgs84= values preserved
# set margins
opar <- par(mar = c(0,0,1.2,0))
# plot osm tiles
tilesLayer(x = mun.osm)
# plot municipalities (only borders are plotted)
plot(st_geometry(nbi_munic_new), col = NA, border = "Black", add=TRUE)
# plot NBI
propSymbolsLayer(
  x = nbi_munic_new, 
  var = "NBI", 
  inches = 0.15, 
  col = "Red",
  legend.pos = "topright",  
  legend.title.txt = "Total NBI"
)
# layout
layoutLayer(title = " Distribución de NBI en Cauca",
            sources = "Sources: DANE, 2018\n© OpenStreetMap",
            author = " Johan Rojas",
            frame = TRUE, north = FALSE, tabtitle = TRUE)
# north arrow
north(pos = "topleft")

7. 2 mapas de coropleticos

En los mapas de coropleticos, las áreas están sombreadas de acuerdo con la variación de una variable cuantitativa. Se utilizan para representar proporciones o índices.

choroLayer () muestra mapas de coropleticos. Los argumentos nclass, método y rupturas permiten personalizar la clasificación de las variables.

getBreaks () permite clasificar fuera de la función en sí. Las paletas de colores se definen con col y se puede crear un conjunto de colores con carto.pal (). Consulte también display.carto.all ().

# establecer márgenes
opar <- par(mar = c(0,0,1.2,0))
# establecer color de fondo de las figuras 
par(bg="grey90")
# trazar municipios (solo se traza el color de fondo)
plot(st_geometry(nbi_munic_new), col = NA, border = NA, bg = "#aadaff")
# trazar NBI
choroLayer(
  x = nbi_munic_new, 
  var = "NBI",
  method = "geom",
  nclass=5,
  col = carto.pal(pal1 = "sand.pal", n1 = 5),
  border = "Black", 
  lwd = 0.5,
  legend.pos = "topright", 
  legend.title.txt = "NBI",
  add = TRUE
) 
# Diseño
layoutLayer(title = "Distribución de NBI en Cauca", 
            sources = "Source: DANE, 2018",
            author = "Johan Rojas", 
            frame = TRUE, north = TRUE, tabtitle = TRUE, col="black") 
# Flecha del norte 
north(pos = "topleft")

7.3 Mapa de símbolos proporcionales y tipología La función propSymbolsTypoLayer () crea un mapa de símbolos que son proporcionales a los valores de una primera variable y coloreados para reflejar las modalidades de una segunda variable de calidad. Se utiliza una combinación de argumentos propSymbolsLayer () y typoLayer ().

Primero, necesitamos crear una variable cualitativa. Usemos la función mutate para esta tarea.

nbi_munic_2 <- dplyr::mutate(nbi_munic_new, pobreza = ifelse(MISERIA > 20, "Extrema", 
                                                         ifelse(HACINAMIENTO > 5, "Alta", "Intermedia")))

Tenga en cuenta que el nuevo atributo se llama pobreza. Su valor depende de los valores umbral definidos por el usuario. Asegúrese de verificar la sintaxis del comando ifelse para comprender lo que está sucediendo

head(nbi_munic_2)
Simple feature collection with 6 features and 22 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: 629875.6 ymin: 672872.9 xmax: 743251.7 ymax: 849733.9
projected CRS:  MAGNA-SIRGAS / Colombia Bogota zone
  DPTO_CCDGO MPIO_CCDGO   MPIO_CNMBR                         MPIO_CRSLC
1         19      19001      POPAYÁN                               1537
2         19      19022     ALMAGUER                               1799
3         19      19050      ARGELIA Ordenanza 2 de Noviembre 8 de 1967
4         19      19075       BALBOA  Ordenanza 1 de Octubre 20 de 1967
5         19      19100      BOLÍVAR                               1793
6         19      19110 BUENOS AIRES                               1851
  MPIO_NAREA MPIO_NANO DPTO_CNMBR Shape_Leng Shape_Area COD_DEPTO DEPTO
1   480.1798      2017      CAUCA   1.372937 0.03897000        19 CAUCA
2   236.7148      2017      CAUCA   0.710253 0.01919657        19 CAUCA
3   775.7878      2017      CAUCA   1.224153 0.06288063        19 CAUCA
4   413.2112      2017      CAUCA   1.016327 0.03349049        19 CAUCA
5   797.8203      2017      CAUCA   1.802787 0.06468337        19 CAUCA
6   435.0623      2017      CAUCA   1.633363 0.03532030        19 CAUCA
  COD_MUN    MUNICIPIO       NBI  MISERIA  VIVIENDA  SERVICIOS
1     001      POPAYÁN  8.798795 1.031876  4.481112  0.2561368
2     022     ALMAGUER 32.935908 5.555892  2.094051 24.0150094
3     050      ARGELIA 23.332497 3.723965 13.570891  1.1693852
4     075       BALBOA 20.128015 3.687050  5.062421  8.5749048
5     100      BOLÍVAR 27.177544 4.252632  2.377544 14.9726316
6     110 BUENOS AIRES 14.911238 2.092249  4.806625  3.3682042
  HACINAMIENTO INASISTENCIA ECONOMIA cod_mun
1     2.178812    0.9813082 2.067783     001
2     5.592205    1.6159293 6.233735     022
3     5.134253    3.2471769 4.577164     050
4     4.131401    1.5922556 4.914304     075
5     6.414035    2.3578947 5.959298     100
6     2.615311    1.8148676 4.632271     110
                        geometry    pobreza
1 POLYGON ((703640.6 776509.5... Intermedia
2 POLYGON ((696038 711703.1, ...       Alta
3 POLYGON ((640233.4 769570.3...       Alta
4 POLYGON ((658816 730615.4, ... Intermedia
5 POLYGON ((682562 725436.2, ...       Alta
6 POLYGON ((700729.5 849464.3... Intermedia
library(sf)
library(cartography)
# set margins
opar <- par(mar = c(0,0,1.2,0))
# Plot the municipalities
plot(st_geometry(nbi_munic_2), col="#CD853F", border="#000000", bg = "#aad3df", 
     lwd = 0.5)
# Plot symbols with choropleth coloration
propSymbolsTypoLayer(
  x = nbi_munic_2, 
  var = "NBI", 
  inches = 0.3,
  symbols = "square",
  border = "white",
  lwd = .5,
  legend.var.pos = c(845872.9, 759875.), 
  legend.var.title.txt = "NBI",
  var2 = "pobreza",
  legend.var2.values.order = c("Intermedia", "Alta", 
                               "Extrema"),
  col = carto.pal(pal1 = "orange.pal", n1 = 3),
  legend.var2.pos = c(845872.9 , 649875.6), 
  legend.var2.title.txt = "Pobreza"
) 
# layout
layoutLayer(title="Distribución de NBI en Cauca", 
            author = "Johan Rojas", 
            sources = "Source: DANE, 2018", 
            scale = 1, tabtitle = TRUE, frame = TRUE)
# north arrow
north(pos = "topleft")

7.4 Etiquetar mapas

Intentemos combinar las funciones choroLayer y labelLayer:

library(sf)
library(cartography)
# set margins
opar <- par(mar = c(0,0,1.2,0))
# set figure background color
par(bg="grey25")
# plot municipalities
plot(st_geometry(nbi_munic_2), col = "#e4e9de", border = "Black", 
     bg = "grey75", lwd = 0.5)
# plot NBI
choroLayer(
  x = nbi_munic_new, 
  var = "NBI",
  method = "geom",
  nclass=5,
  col = carto.pal(pal1 = "wine.pal", n1 = 5),
  border = "Black", 
  lwd = 0.5,
  legend.pos = "topright", 
  legend.title.txt = "NBI",
  add = TRUE
) 
# plot labels
labelLayer(
  x = nbi_munic_2, 
  txt = "MUNICIPIO", 
  col= "white", 
  cex = 0.4, 
  font = 4,
  halo = TRUE, 
  bg = "Black", 
  r = 0.1, 
  overlap = FALSE, 
  show.lines = FALSE
)
# map layout
layoutLayer(
  title = "Municipios de Cauca", 
  sources = "Source: DANE, 2018",  
  author = "Johan Rojas", 
  frame = TRUE,
  north = TRUE, 
  tabtitle = TRUE, 
  theme = "taupe.pal"
) 

7.5 Mapas de Isopleticos Los mapas de Isopleticos se basan en el supuesto de que el fenómeno a representar tiene una distribución continua. Estos mapas utilizan un enfoque de modelado de interacción espacial que tiene como objetivo calcular indicadores basados en valores de stock ponderados por distancia. Permite una representación espacial del fenómeno independiente de la heterogeneidad inicial de la división territorial. smoothLayer () depende en gran medida del paquete SpatialPosition. La función utiliza una capa de puntos marcados y un conjunto de parámetros (una función de interacción espacial y sus parámetros) y muestra una capa de mapa isopleta.

Usemos otro conjunto de datos para hacer un mapa de isopletas. En este caso, subiré datos estadísticos sobre la producción de café de 2018 en Antioquia. Ya conocemos este conjunto de datos, ya que se usó en un cuaderno anterior para ilustrar uniones basadas en atributos.

Leer el conjunto de datos:

cultivos2018 <-read_csv("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/trabajo7/EVA_cauca.csv")
Parsed with column specification:
cols(
  ID = col_double(),
  COD = col_character(),
  MUN = col_character(),
  GRUPO = col_character(),
  SUBGRUPO = col_character(),
  CULTIVO = col_character(),
  DESAGR = col_character(),
  YEAR = col_double(),
  PERIODO = col_character(),
  HA_SIEMBRA = col_double(),
  HA_COSECHA = col_double(),
  TON_PROD = col_double(),
  REND = col_double(),
  ESTADO = col_character(),
  NOMBRE = col_character(),
  CICLO = col_character()
)
head(cultivos2018) 

Filtrar filas que representan solo datos de café:

cultivos2018 %>%
  filter(CULTIVO == "CAFE") -> cafe2018
head(cafe2018)

Ahora, haz la unión

cafe_munic = left_join(munic, cafe2018, by=c("MPIO_CCDGO"="COD"))

Verifique la salida:

head(cafe_munic)
Simple feature collection with 6 features and 24 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: -76.77328 ymin: 2.311382 xmax: -76.38534 ymax: 2.573465
geographic CRS: WGS 84
  DPTO_CCDGO MPIO_CCDGO MPIO_CNMBR MPIO_CRSLC MPIO_NAREA MPIO_NANO
1         19      19001    POPAYÁN       1537   480.1798      2017
2         19      19001    POPAYÁN       1537   480.1798      2017
3         19      19001    POPAYÁN       1537   480.1798      2017
4         19      19001    POPAYÁN       1537   480.1798      2017
5         19      19001    POPAYÁN       1537   480.1798      2017
6         19      19001    POPAYÁN       1537   480.1798      2017
  DPTO_CNMBR Shape_Leng Shape_Area    ID     MUN             GRUPO
1      CAUCA   1.372937    0.03897 19000 POPAYAN OTROS PERMANENTES
2      CAUCA   1.372937    0.03897 19000 POPAYAN OTROS PERMANENTES
3      CAUCA   1.372937    0.03897 19000 POPAYAN OTROS PERMANENTES
4      CAUCA   1.372937    0.03897 19000 POPAYAN OTROS PERMANENTES
5      CAUCA   1.372937    0.03897 19000 POPAYAN OTROS PERMANENTES
6      CAUCA   1.372937    0.03897 19000 POPAYAN OTROS PERMANENTES
  SUBGRUPO CULTIVO DESAGR YEAR PERIODO HA_SIEMBRA HA_COSECHA TON_PROD REND
1     CAFE    CAFE   CAFE 2007    2007       3214       2182     2488 1.14
2     CAFE    CAFE   CAFE 2008    2008       3202       2678     2717 1.01
3     CAFE    CAFE   CAFE 2009    2009       3395       2390     2319 0.97
4     CAFE    CAFE   CAFE 2010    2010       3270       2294     2229 0.97
5     CAFE    CAFE   CAFE 2011    2011       3361       2358     2055 0.87
6     CAFE    CAFE   CAFE 2012    2012       3280       3240     2916 0.90
                  ESTADO         NOMBRE      CICLO
1 CAFE VERDE EQUIVALENTE COFFEA ARABICA PERMANENTE
2 CAFE VERDE EQUIVALENTE COFFEA ARABICA PERMANENTE
3 CAFE VERDE EQUIVALENTE COFFEA ARABICA PERMANENTE
4 CAFE VERDE EQUIVALENTE COFFEA ARABICA PERMANENTE
5 CAFE VERDE EQUIVALENTE COFFEA ARABICA PERMANENTE
6 CAFE VERDE EQUIVALENTE COFFEA ARABICA PERMANENTE
                        geometry
1 POLYGON ((-76.74145 2.57230...
2 POLYGON ((-76.74145 2.57230...
3 POLYGON ((-76.74145 2.57230...
4 POLYGON ((-76.74145 2.57230...
5 POLYGON ((-76.74145 2.57230...
6 POLYGON ((-76.74145 2.57230...

Ahora, reproyectemos los municipios:

rep_cafe <- st_transform(cafe_munic, crs = 3116)

ahora hacemos el mapeo

summary(rep_cafe$TON_PROD)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
      0     640    1276    2034    2683   11571       7 
# set margins
opar <- par(mar = c(0,0,1.2,0))
# plot municipalities (only the backgroung color is plotted)
plot(st_geometry(rep_cafe), col = NA, border = "Black", bg = "grey75")
# plot isopleth map
smoothLayer(
  x = rep_cafe, 
  var = 'TON_PROD',
  typefct = "exponential",
  span = 12000,
  beta = 2,
  nclass = 10,
  col = carto.pal(pal1 = 'green.pal', n1 = 10),
  border = "Black",
  lwd = 0.1, 
  mask = rep_cafe, 
  legend.values.rnd = -3,
  legend.title.txt = "Producción",
  legend.pos = "topright", 
  add=TRUE
)
Discarded datum Unknown based on GRS80 ellipsoid in CRS definition,
 but +towgs84= values preservedDiscarded datum Unknown based on GRS80 ellipsoid in CRS definition,
 but +towgs84= values preservedDiscarded datum Unknown based on GRS80 ellipsoid in CRS definition,
 but +towgs84= values preserved
# annotation on the map
text(x = -76.57328, y = 2.411382, cex = 0.6, adj = 0, font = 3,  labels = 
       "Distance function:\n- type = exponential\n- beta = 2\n- span = 20 km")
# layout
layoutLayer(title = "Distribución de la producción de cafe en Cauca",
            sources = "Sources: DANE and MADR, 2018",
            author = "Johan Rojas",
            frame = FALSE, north = FALSE, tabtitle = TRUE, theme = "green.pal")
# north arrow
north(pos = "topleft")

8. Guardar mapas

Produzcamos otro mapa de la producción de café en 2018. Esta vez usaremos símbolos proporcionales y mapas de coropletas. La salida se guardará como un archivo .png.

Primero, algunas observaciones: - propSymbolsChoroLayer () crea un mapa de símbolos que son proporcionales a los valores de una primera variable y coloreados para reflejar la clasificación de una segunda variable. - Se utiliza una combinación de argumentos propSymbolsLayer () y choroLayer ().

El siguiente fragmento no muestra un mapa. En su lugar, escribe el mapa con el nombre de archivo cafe_2018.png en el directorio de trabajo.

Por cuestiones de visualización vamos a dividir la producción de cafe en Cauca en dos partes, para esto vamos a dividir estos en dos grupos apartir de la media.

summary(cafe2018$TON_PROD)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
      0     640    1276    2034    2683   11571 
cafe2018 %>% 
  filter(YEAR==2018 & SUBGRUPO=="CAFE") %>% 
  group_by(MUN, CULTIVO,COD,TON_PROD,REND, HA_SIEMBRA) %>%
  summarize(sum_cosecha = sum(HA_COSECHA, na.rm = TRUE)) %>%
  filter(TON_PROD>=2034) %>%
  arrange(desc(sum_cosecha)) -> cafe20182
`summarise()` regrouping output by 'MUN', 'CULTIVO', 'COD', 'TON_PROD', 'REND' (override with `.groups` argument)
cafe20182
cafe2018 %>% 
  filter(YEAR==2018 & SUBGRUPO=="CAFE") %>% 
  group_by(MUN, CULTIVO,COD,TON_PROD,REND, HA_SIEMBRA) %>%
  summarize(sum_cosecha = sum(HA_COSECHA, na.rm = TRUE)) %>%
  filter(TON_PROD<2034) %>%
  arrange(desc(sum_cosecha)) -> cafe20182_1
`summarise()` regrouping output by 'MUN', 'CULTIVO', 'COD', 'TON_PROD', 'REND' (override with `.groups` argument)
cafe20182_1
cafe_munic2 = left_join(munic, cafe20182, by=c("MPIO_CCDGO"="COD"))
cafe_munic2_1 = left_join(munic, cafe20182_1, by=c("MPIO_CCDGO"="COD"))
rep_cafe2 <- st_transform(cafe_munic2, crs = 3116)
rep_cafe2_1 <- st_transform(cafe_munic2_1, crs = 3116)
### open the plot
png("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/informe dos/cafe_2018-2.png", width = 2048, height = 1526)
# set margins
opar <- par(mar = c(0,0,5,5))
# Plot the municipalities
plot(st_geometry(rep_cafe2), col="darkseagreen3", border="darkseagreen4",  
     bg = "white", lwd = 0.6)
# Plot symbols with choropleth coloration
propSymbolsChoroLayer(x = rep_cafe2, var = "TON_PROD", var2 = "REND",
                      col = carto.pal(pal1 = "green.pal", n1 = 3,
                                      pal2 = "red.pal", n2 = 3),
                      inches = 0.8, method = "q6",
                      border = "grey50", lwd = 1,
                      legend.title.cex = 3,
                      legend.values.cex = 1.0,
                      legend.var.pos = "right", 
                      legend.var2.pos = "left",
                      legend.var2.values.rnd = 2,
                      legend.var2.title.txt = "Rendimiento\n(en Ton/Ha)",
                      legend.var.title.txt = "producción de cafe (2018)",
                      legend.var.style = "e")
# plot labels
labelLayer(
  x = rep_cafe2, 
  txt = "MUN", 
  col= "Black", 
  cex = 1.0, 
  font = 5,
  halo = FALSE, 
  bg = "white", 
  r = 0.1, 
  overlap = FALSE, 
  show.lines = FALSE
)
# layout
layoutLayer(title="Producción y rendimiento mayor a la media de café en Cauca, 2018",
            author = "Johan Rojas", 
            sources = "Sources: MADR & DANE, 2018", 
             tabtitle = FALSE, frame = TRUE,scale = "auto",)
# north arrow
north(pos = "topleft")
#
title(main="Producción y rendimiento mayor a la media de café en Cauca, 2018", cex.main=4,
      sub= "Source: MADR & DANE, 2018", cex.sub=4)
#
graticule = TRUE
#
par(opar)
### close the plot
dev.off()
null device 
          1 
png("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/informe dos/cafe_2018-2_1.png", width = 2048, height = 1526)
# set margins
opar <- par(mar = c(0,0,5,5))
# Plot the municipalities
plot(st_geometry(rep_cafe2_1), col="darkseagreen3", border="darkseagreen4",  
     bg = "white", lwd = 0.6)
# Plot symbols with choropleth coloration
propSymbolsChoroLayer(x = rep_cafe2_1, var = "TON_PROD", var2 = "REND",
                      col = carto.pal(pal1 = "green.pal", n1 = 3,
                                      pal2 = "red.pal", n2 = 3),
                      inches = 0.8, method = "q6",
                      border = "grey50", lwd = 1,
                      legend.title.cex = 3,
                      legend.values.cex = 1.0,
                      legend.var.pos = "right", 
                      legend.var2.pos = "left",
                      legend.var2.values.rnd = 2,
                      legend.var2.title.txt = "Rendimiento\n(en Ton/Ha)",
                      legend.var.title.txt = "producción de cafe (2018)",
                      legend.var.style = "e")
# plot labels
labelLayer(
  x = rep_cafe2_1, 
  txt = "MUN", 
  col= "Black", 
  cex = 1.0, 
  font = 5,
  halo = FALSE, 
  bg = "white", 
  r = 0.1, 
  overlap = FALSE, 
  show.lines = FALSE
)
# layout
layoutLayer(title="Producción y rendimiento menor a la media de café en Cauca, 2018",
            author = "Johan Rojas", 
            sources = "Sources: MADR & DANE, 2018", 
             tabtitle = FALSE, frame = TRUE,scale = "auto",)
# north arrow
north(pos = "topleft")
#
title(main="Producción y rendimiento menor a la media de café en Cauca, 2018", cex.main=4,
      sub= "Source: MADR & DANE, 2018", cex.sub=5)
#
graticule = TRUE
#
par(opar)
### close the plot
dev.off()
null device 
          1 
knitr::include_graphics("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/informe dos/cafe_2018-2.png")

knitr::include_graphics("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/informe dos/cafe_2018-2_1.png")

Ahora vamos a ver la producción y área cosechada de café en Cauca en el 2018 de igual manera lo vamos ha hacer en dos mapas uno mayor a la media y otro menor a la media.

### open the plot
png("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/informe dos/cafe_2018c.png", width = 2048, height = 1526)
# set margins
opar <- par(mar = c(0,0,5,5))
# Plot the municipalities
plot(st_geometry(rep_cafe2), col="darkseagreen3", border="darkseagreen4",  
     bg = "white", lwd = 0.6)
# Plot symbols with choropleth coloration
propSymbolsChoroLayer(x = rep_cafe2, var = "TON_PROD", var2 = "sum_cosecha",
                      col = carto.pal(pal1 = "brown.pal", n1 = 3,
                                      pal2 = "orange.pal", n2 = 3),
                      inches = 0.8, method = "q6",
                      border = "grey50", lwd = 1,
                      legend.title.cex = 3,
                      legend.values.cex = 1.0,
                      legend.var.pos = "right", 
                      legend.var2.pos = "left",
                      legend.var2.values.rnd = 2,
                      legend.var2.title.txt = "Rendimiento\n(en Ton/Ha)",
                      legend.var.title.txt = "Área cosechada de cafe (2018)",
                      legend.var.style = "e")
# plot labels
labelLayer(
  x = rep_cafe2, 
  txt = "MUN", 
  col= "Black", 
  cex = 1.0, 
  font = 5,
  halo = FALSE, 
  bg = "white", 
  r = 0.1, 
  overlap = FALSE, 
  show.lines = FALSE
)
# layout
layoutLayer(title="Producción y área cosechada mayor a la media de café en Cauca, 2018",
            author = "Johan Rojas", 
            sources = "Sources: MADR & DANE, 2018", 
             tabtitle = FALSE, frame = TRUE,scale = "auto",)
# north arrow
north(pos = "topleft")
#
title(main="Producción y área cosechada mayor a la media de café en Cauca, 2018", cex.main=4,
      sub= "Source: MADR & DANE, 2018", cex.sub=4)
#
graticule = TRUE
#
par(opar)
### close the plot
dev.off()
null device 
          1 
### open the plot
png("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/informe dos/cafe_2018c2.png", width = 2048, height = 1526)
# set margins
opar <- par(mar = c(0,0,5,5))
# Plot the municipalities
plot(st_geometry(rep_cafe2_1), col="darkseagreen3", border="darkseagreen4",  
     bg = "white", lwd = 0.6)
# Plot symbols with choropleth coloration
propSymbolsChoroLayer(x = rep_cafe2_1, var = "TON_PROD", var2 = "sum_cosecha",
                      col = carto.pal(pal1 = "brown.pal", n1 = 3,
                                      pal2 = "orange.pal", n2 = 3),
                      inches = 0.8, method = "q6",
                      border = "grey50", lwd = 1,
                      legend.title.cex = 3,
                      legend.values.cex = 1.0,
                      legend.var.pos = "right", 
                      legend.var2.pos = "left",
                      legend.var2.values.rnd = 2,
                      legend.var2.title.txt = "Rendimiento\n(en Ton/Ha)",
                      legend.var.title.txt = "Área cosechada de cafe (2018)",
                      legend.var.style = "e")
# plot labels
labelLayer(
  x = rep_cafe2_1, 
  txt = "MUN", 
  col= "Black", 
  cex = 1.0, 
  font = 5,
  halo = FALSE, 
  bg = "white", 
  r = 0.1, 
  overlap = FALSE, 
  show.lines = FALSE
)
# layout
layoutLayer(title="Producción y área cosechada menor a la media de café en Cauca, 2018",
            author = "Johan Rojas", 
            sources = "Sources: MADR & DANE, 2018", 
             tabtitle = FALSE, frame = TRUE,scale = "auto",)
# north arrow
north(pos = "topleft")
#
title(main="Producción y área cosechada menor a la media de café en Cauca, 2018", cex.main=4,
      sub= "Source: MADR & DANE, 2018", cex.sub=4)
#
graticule = TRUE
#
par(opar)
### close the plot
dev.off()
null device 
          1 
knitr::include_graphics("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/informe dos/cafe_2018c.png")

knitr::include_graphics("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/informe dos/cafe_2018c2.png")

Ahora vamos a ver hacer un mapa cloropletico con el área de siembra en Cauca para 2018

cafe2018 %>% 
  filter(YEAR==2018 & SUBGRUPO=="CAFE") %>% 
  group_by(MUN, CULTIVO,COD,TON_PROD,REND, HA_SIEMBRA) %>%
  summarize(sum_siembra = sum(HA_SIEMBRA, na.rm = TRUE)) -> cafe2018si
`summarise()` regrouping output by 'MUN', 'CULTIVO', 'COD', 'TON_PROD', 'REND' (override with `.groups` argument)
cafe2018si
cafe_municsi = left_join(munic, cafe2018si, by=c("MPIO_CCDGO"="COD"))
rep_cafesi <- st_transform(cafe_munic2, crs = 3116)
library(sf)
library(cartography)
# set margins
opar <- par(mar = c(0,0,1.2,0))
# set figure background color
par(bg="grey25")
# plot municipalities
plot(st_geometry(rep_cafesi), col = "#e4e9de", border = "Black", 
     bg = "grey75", lwd = 0.5)
# plot NBI
choroLayer(
  x = rep_cafesi, 
  var = "HA_SIEMBRA",
  method = "geom",
  nclass=7,
  col = carto.pal(pal1 = "wine.pal", n1 = 7),
  border = "Black", 
  lwd = 0.5,
  legend.pos = "topright",
  legend.title.txt = "ÁREA DE SIEMBRA",
  add = TRUE
) 
# plot labels
labelLayer(
  x =rep_cafesi, 
  txt = "MUN", 
  col= "Black", 
  cex = 0.4, 
  font = 4,
  overlap = FALSE, 
  show.lines = FALSE
)
# map layout
layoutLayer(
  title = "Área de siembra en los municipios de Cauca", 
  sources = "Source: DANE, 2018",  
  author = "Johan Rojas", 
  frame = TRUE,
  north = TRUE, 
  tabtitle = TRUE, 
  theme = "taupe.pal")

ahora miremos la distribución del área de siembra con un mapa isopletico.

# set margins
opar <- par(mar = c(0,0,1.2,0))
# plot municipalities (only the backgroung color is plotted)
plot(st_geometry(rep_cafesi), col = NA, border = "Black", bg = "grey75")
# plot isopleth map
smoothLayer(
  x = rep_cafesi, 
  var = 'HA_SIEMBRA',
  typefct = "exponential",
  span = 8428,
  beta = 2,
  nclass = 10,
  col = carto.pal(pal1 = 'green.pal', n1 = 10),
  border = "Black",
  lwd = 0.1, 
  mask = rep_cafe, 
  legend.values.rnd = -3,
  legend.title.txt = "Área de siembra",
  legend.pos = "topright", 
  add=TRUE
)
Discarded datum Unknown based on GRS80 ellipsoid in CRS definition,
 but +towgs84= values preservedDiscarded datum Unknown based on GRS80 ellipsoid in CRS definition,
 but +towgs84= values preservedDiscarded datum Unknown based on GRS80 ellipsoid in CRS definition,
 but +towgs84= values preserved
# annotation on the map
text(x = -76.57328, y = 2.411382, cex = 0.6, adj = 0, font = 3,  labels = 
       "Distance function:\n- type = exponential\n- beta = 2\n- span = 20 km")
# layout
layoutLayer(title = "Distribución del área de siembra de cafe en Cauca",
            sources = "Sources: DANE and MADR, 2018",
            author = "Johan Rojas",
            frame = FALSE, north = FALSE, tabtitle = TRUE, theme = "green.pal")
# north arrow
north(pos = "topleft")

Por ultimo vamos a ver como se relaciona el nbi y la producción en Cauca para 2018, primero unamos los datos que necesitamos.

cafe_munic_nbi = left_join(nbi_munic, cafe2018si, by=c("MPIO_CCDGO"="COD"))
cafe_munic_nbi
Simple feature collection with 42 features and 27 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: -77.92834 ymin: 0.9580285 xmax: -75.74782 ymax: 3.328941
geographic CRS: WGS 84
First 10 features:
   DPTO_CCDGO MPIO_CCDGO   MPIO_CNMBR                         MPIO_CRSLC
1          19      19001      POPAYÁN                               1537
2          19      19022     ALMAGUER                               1799
3          19      19050      ARGELIA Ordenanza 2 de Noviembre 8 de 1967
4          19      19075       BALBOA  Ordenanza 1 de Octubre 20 de 1967
5          19      19100      BOLÍVAR                               1793
6          19      19110 BUENOS AIRES                               1851
7          19      19130      CAJIBÍO                               1824
8          19      19137      CALDONO                               1746
9          19      19142       CALOTO                               1543
10         19      19212      CORINTO                               1868
   MPIO_NAREA MPIO_NANO DPTO_CNMBR Shape_Leng Shape_Area COD_DEPTO DEPTO
1    480.1798      2017      CAUCA  1.3729371 0.03897000        19 CAUCA
2    236.7148      2017      CAUCA  0.7102530 0.01919657        19 CAUCA
3    775.7878      2017      CAUCA  1.2241529 0.06288063        19 CAUCA
4    413.2112      2017      CAUCA  1.0163274 0.03349049        19 CAUCA
5    797.8203      2017      CAUCA  1.8027866 0.06468337        19 CAUCA
6    435.0623      2017      CAUCA  1.6333631 0.03532030        19 CAUCA
7    552.2877      2017      CAUCA  1.3822054 0.04482019        19 CAUCA
8    354.7387      2017      CAUCA  1.1029614 0.02880277        19 CAUCA
9    266.5987      2017      CAUCA  1.3621191 0.02164894        19 CAUCA
10   325.9156      2017      CAUCA  0.8276564 0.02647947        19 CAUCA
   COD_MUN    MUNICIPIO       NBI  MISERIA  VIVIENDA  SERVICIOS
1      001      POPAYÁN  8.798795 1.031876  4.481112  0.2561368
2      022     ALMAGUER 32.935908 5.555892  2.094051 24.0150094
3      050      ARGELIA 23.332497 3.723965 13.570891  1.1693852
4      075       BALBOA 20.128015 3.687050  5.062421  8.5749048
5      100      BOLÍVAR 27.177544 4.252632  2.377544 14.9726316
6      110 BUENOS AIRES 14.911238 2.092249  4.806625  3.3682042
7      130      CAJIBÍO 22.860245 4.004964  7.035831  5.7701256
8      137      CALDONO 22.278883 3.895670  4.062866  3.9346820
9      142       CALOTO 22.609246 4.678594 10.995883  7.6987017
10     212      CORINTO 18.679795 3.083252  9.721259  3.0601396
   HACINAMIENTO INASISTENCIA ECONOMIA cod_mun          MUN CULTIVO
1      2.178812    0.9813082 2.067783     001      POPAYAN    CAFE
2      5.592205    1.6159293 6.233735     022     ALMAGUER    CAFE
3      5.134253    3.2471769 4.577164     050      ARGELIA    CAFE
4      4.131401    1.5922556 4.914304     075       BALBOA    CAFE
5      6.414035    2.3578947 5.959298     100      BOLIVAR    CAFE
6      2.615311    1.8148676 4.632271     110 BUENOS AIRES    CAFE
7      3.762991    2.5779432 8.279820     130      CAJIBIO    CAFE
8      7.939029    1.7360531 8.816809     137      CALDONO    CAFE
9      4.045282    0.8391387 4.694427     142       CALOTO    CAFE
10     3.804373    1.1695095 4.701151     212      CORINTO    CAFE
   TON_PROD REND HA_SIEMBRA sum_siembra                       geometry
1      2939 0.95       3510        3510 POLYGON ((-76.74145 2.57230...
2       819 0.78       1157        1157 POLYGON ((-76.80864 1.98674...
3       830 0.62       1494        1494 POLYGON ((-77.3107 2.508326...
4      2226 0.73       3352        3352 POLYGON ((-77.1431 2.156948...
5      4598 1.87       2682        2682 POLYGON ((-76.92984 2.11058...
6      1446 0.86       1825        1825 POLYGON ((-76.76916 3.23128...
7      9500 1.55       6860        6860 POLYGON ((-76.83997 2.76373...
8      5476 1.29       4936        4936 POLYGON ((-76.36326 2.90734...
9      2265 1.29       1973        1973 POLYGON ((-76.42866 3.20990...
10     1280 0.90       1660        1660 POLYGON ((-76.28278 3.22879...
cafe_munic_nbi2 = st_join(munic, cafe_munic_nbi, by=c("MPIO_CCDGO"))
although coordinates are longitude/latitude, st_intersects assumes that they are planar

Ahora vamos a crear una escala (alta, media, baja) para la producción de cafe en 2018, para esto usaremos los datos de los cuartiles de esta variable.

summary(cafe_munic_nbi2$TON_PROD)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
    228     830    2570    3529    4635   11315      48 
cafe_nbi_munic_2 <- dplyr::mutate(cafe_munic_nbi, PROD = ifelse(TON_PROD>4635, "Alta", 
                                                         ifelse(TON_PROD > 3529, "Media", "Baja")))
cafe_nbi_munic_2
Simple feature collection with 42 features and 28 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: -77.92834 ymin: 0.9580285 xmax: -75.74782 ymax: 3.328941
geographic CRS: WGS 84
First 10 features:
   DPTO_CCDGO MPIO_CCDGO   MPIO_CNMBR                         MPIO_CRSLC
1          19      19001      POPAYÁN                               1537
2          19      19022     ALMAGUER                               1799
3          19      19050      ARGELIA Ordenanza 2 de Noviembre 8 de 1967
4          19      19075       BALBOA  Ordenanza 1 de Octubre 20 de 1967
5          19      19100      BOLÍVAR                               1793
6          19      19110 BUENOS AIRES                               1851
7          19      19130      CAJIBÍO                               1824
8          19      19137      CALDONO                               1746
9          19      19142       CALOTO                               1543
10         19      19212      CORINTO                               1868
   MPIO_NAREA MPIO_NANO DPTO_CNMBR Shape_Leng Shape_Area COD_DEPTO DEPTO
1    480.1798      2017      CAUCA  1.3729371 0.03897000        19 CAUCA
2    236.7148      2017      CAUCA  0.7102530 0.01919657        19 CAUCA
3    775.7878      2017      CAUCA  1.2241529 0.06288063        19 CAUCA
4    413.2112      2017      CAUCA  1.0163274 0.03349049        19 CAUCA
5    797.8203      2017      CAUCA  1.8027866 0.06468337        19 CAUCA
6    435.0623      2017      CAUCA  1.6333631 0.03532030        19 CAUCA
7    552.2877      2017      CAUCA  1.3822054 0.04482019        19 CAUCA
8    354.7387      2017      CAUCA  1.1029614 0.02880277        19 CAUCA
9    266.5987      2017      CAUCA  1.3621191 0.02164894        19 CAUCA
10   325.9156      2017      CAUCA  0.8276564 0.02647947        19 CAUCA
   COD_MUN    MUNICIPIO       NBI  MISERIA  VIVIENDA  SERVICIOS
1      001      POPAYÁN  8.798795 1.031876  4.481112  0.2561368
2      022     ALMAGUER 32.935908 5.555892  2.094051 24.0150094
3      050      ARGELIA 23.332497 3.723965 13.570891  1.1693852
4      075       BALBOA 20.128015 3.687050  5.062421  8.5749048
5      100      BOLÍVAR 27.177544 4.252632  2.377544 14.9726316
6      110 BUENOS AIRES 14.911238 2.092249  4.806625  3.3682042
7      130      CAJIBÍO 22.860245 4.004964  7.035831  5.7701256
8      137      CALDONO 22.278883 3.895670  4.062866  3.9346820
9      142       CALOTO 22.609246 4.678594 10.995883  7.6987017
10     212      CORINTO 18.679795 3.083252  9.721259  3.0601396
   HACINAMIENTO INASISTENCIA ECONOMIA cod_mun          MUN CULTIVO
1      2.178812    0.9813082 2.067783     001      POPAYAN    CAFE
2      5.592205    1.6159293 6.233735     022     ALMAGUER    CAFE
3      5.134253    3.2471769 4.577164     050      ARGELIA    CAFE
4      4.131401    1.5922556 4.914304     075       BALBOA    CAFE
5      6.414035    2.3578947 5.959298     100      BOLIVAR    CAFE
6      2.615311    1.8148676 4.632271     110 BUENOS AIRES    CAFE
7      3.762991    2.5779432 8.279820     130      CAJIBIO    CAFE
8      7.939029    1.7360531 8.816809     137      CALDONO    CAFE
9      4.045282    0.8391387 4.694427     142       CALOTO    CAFE
10     3.804373    1.1695095 4.701151     212      CORINTO    CAFE
   TON_PROD REND HA_SIEMBRA sum_siembra                       geometry
1      2939 0.95       3510        3510 POLYGON ((-76.74145 2.57230...
2       819 0.78       1157        1157 POLYGON ((-76.80864 1.98674...
3       830 0.62       1494        1494 POLYGON ((-77.3107 2.508326...
4      2226 0.73       3352        3352 POLYGON ((-77.1431 2.156948...
5      4598 1.87       2682        2682 POLYGON ((-76.92984 2.11058...
6      1446 0.86       1825        1825 POLYGON ((-76.76916 3.23128...
7      9500 1.55       6860        6860 POLYGON ((-76.83997 2.76373...
8      5476 1.29       4936        4936 POLYGON ((-76.36326 2.90734...
9      2265 1.29       1973        1973 POLYGON ((-76.42866 3.20990...
10     1280 0.90       1660        1660 POLYGON ((-76.28278 3.22879...
    PROD
1   Baja
2   Baja
3   Baja
4   Baja
5  Media
6   Baja
7   Alta
8   Alta
9   Baja
10  Baja
pobrecafe <- st_transform(cafe_nbi_munic_2, crs = 3116)

Ahora hagamos al mapa

library(sf)
library(cartography)
# set margins
opar <- par(mar = c(0,0,1.2,0))
# Plot the municipalities
plot(st_geometry(pobrecafe), col="#CD853F", border="#000000", bg = "#aad3df", 
     lwd = 0.5)
# Plot symbols with choropleth coloration
propSymbolsTypoLayer(
  x = pobrecafe, 
  var = "NBI", 
  inches = 0.3,
  symbols = "square",
  border = "Black",
  lwd = .5,
  legend.var.pos = c(845872.9, 759875.), 
  legend.var.title.txt = "NBI",
  var2 = "PROD",
  legend.var2.values.order = c("Alta", "Media", 
                               "Baja"),
  col = carto.pal(pal1 = "orange.pal", n1 = 3),
  legend.var2.pos = c(845872.9 , 649875.6), 
  legend.var2.title.txt = "Producción"
) 
labelLayer(
  x =pobrecafe, 
  txt = "MPIO_CNMBR", 
  col= "Black", 
  cex = 0.4, 
  font = 4,
  overlap = FALSE, 
  show.lines = FALSE)
# layout
layoutLayer(title="Distribución de NBI y producción de cafe en Cauca", 
            author = "Johan Rojas", 
            sources = "Source: DANE & MADR, 2018", 
            scale = 1, tabtitle = TRUE, frame = TRUE)
# north arrow
north(pos = "topleft")

sessionInfo()
R version 4.0.2 (2020-06-22)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)

Matrix products: default

locale:
[1] LC_COLLATE=Spanish_Mexico.1252  LC_CTYPE=Spanish_Mexico.1252   
[3] LC_MONETARY=Spanish_Mexico.1252 LC_NUMERIC=C                   
[5] LC_TIME=Spanish_Mexico.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] SpatialPosition_2.0.1 cartography_2.4.2     sf_0.9-5             
 [4] rgeos_0.5-5           readxl_1.3.1          forcats_0.5.0        
 [7] stringr_1.4.0         dplyr_1.0.2           purrr_0.3.4          
[10] readr_1.3.1           tidyr_1.1.2           tibble_3.0.3         
[13] ggplot2_3.3.2         tidyverse_1.3.0       raster_3.3-13        
[16] sp_1.4-2             

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.5         lubridate_1.7.9    lattice_0.20-41   
 [4] png_0.1-7          class_7.3-17       assertthat_0.2.1  
 [7] digest_0.6.25      R6_2.4.1           cellranger_1.1.0  
[10] backports_1.1.7    reprex_0.3.0       evaluate_0.14     
[13] e1071_1.7-3        httr_1.4.2         pillar_1.4.6      
[16] rlang_0.4.7        rstudioapi_0.11    blob_1.2.1        
[19] rmarkdown_2.3      rgdal_1.5-16       munsell_0.5.0     
[22] broom_0.7.0        compiler_4.0.2     modelr_0.1.8      
[25] xfun_0.16          base64enc_0.1-3    pkgconfig_2.0.3   
[28] htmltools_0.5.0    tidyselect_1.1.0   codetools_0.2-16  
[31] fansi_0.4.1        crayon_1.3.4       dbplyr_1.4.4      
[34] withr_2.2.0        grid_4.0.2         lwgeom_0.2-5      
[37] jsonlite_1.7.0     gtable_0.3.0       lifecycle_0.2.0   
[40] DBI_1.1.0          magrittr_1.5       units_0.6-7       
[43] scales_1.1.1       KernSmooth_2.23-17 cli_2.0.2         
[46] stringi_1.4.6      fs_1.5.0           xml2_1.3.2        
[49] ellipsis_0.3.1     generics_0.0.2     vctrs_0.3.3       
[52] tools_4.0.2        glue_1.4.2         hms_0.5.3         
[55] slippymath_0.3.1   yaml_2.2.1         colorspace_1.4-1  
[58] classInt_0.4-3     rvest_0.3.6        isoband_0.2.2     
[61] knitr_1.29         haven_2.3.1       
LS0tDQp0aXRsZTogIkNhcnRvZ3JhZsOtYSB0ZW3DoXRpY2EiDQphdXRob3I6ICJKb2hhbiBTLiBSb2phcyBDaC4iDQpkYXRlOiAiMDUvMTEvMjAyMCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KDQotLS0NCg0KIyMgMS4gwr9Qb3IgcXXDqSBlc3RlIGN1YWRlcm5vPw0KRXN0ZSBlcyB1biBjdWFkZXJubyBkZSBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgcXVlIGlsdXN0cmEgY2FydG9ncmFmw61hIHRlbcOhdGljYSBwYXJhIGVsIGRlcGFydGFtZW50byBkZSBDYXVjYSBlbiBDb2xvbWJpYSwgRXN0ZSBjdWFkZXJubyB0aWVuZSBjb21vIG9iamV0aXZvIGFwcmVuZGVyIGEgaGFjZXIgbWFwYXMgdGVtw6F0aWNvcyBlbiBSIHBhcmEgbGEgbWF0ZXJpYSBkZSBHZW9tYXRpY2EgQsOhc2ljYSBkZSBsYSBVbml2ZXJzaWRhZCBOYWNpb25hbC4NCg0KIyMgMi4gQ2FydG9ncmFmw61hIHRlbcOhdGljYQ0KQ29tbyBkaWNlIFtBbWFuZGEgQnJpbmV5XShodHRwczovL3d3dy50aG91Z2h0Y28uY29tL3RoZW1hdGljLW1hcHMtb3ZlcnZpZXctMTQzNTY5MiksIHVuIG1hcGEgdGVtw6F0aWNvIGVuZmF0aXphIHVuIHRlbWEgbyBhc3VudG8sIGNvbW8gbGEgZGlzdHJpYnVjacOzbiBwcm9tZWRpbyBkZSBsYXMgcHJlY2lwaXRhY2lvbmVzIGVuIHVuIMOhcmVhIG8gbGEgZGVuc2lkYWQgZGUgcG9ibGFjacOzbiBlbiB1biBtdW5pY2lwaW8uIFNlIGRpZmVyZW5jaWFuIGRlIGxvcyBtYXBhcyBkZSByZWZlcmVuY2lhIGdlbmVyYWxlcyBwb3JxdWUgbm8gc29sbyBtdWVzdHJhbiBjYXJhY3RlcsOtc3RpY2FzIG5hdHVyYWxlcyB5IGNyZWFkYXMgcG9yIGVsIGhvbWJyZSwgY29tbyByw61vcywgY2l1ZGFkZXMsIHN1YmRpdmlzaW9uZXMgcG9sw610aWNhcyB5IGNhcnJldGVyYXMuIFNpIGVzdG9zIGVsZW1lbnRvcyBhcGFyZWNlbiBlbiB1biBtYXBhIHRlbcOhdGljbywgc29uIHB1bnRvcyBkZSByZWZlcmVuY2lhIHBhcmEgbWVqb3JhciBsYSBjb21wcmVuc2nDs24gZGVsIHRlbWEgeSBlbCBwcm9ww7NzaXRvIGRlbCBtYXBhLg0KDQpTZWfDum4gQnJpbmV5LCDigJxlbCBmYWN0b3IgbcOhcyBpbXBvcnRhbnRlIGEgY29uc2lkZXJhciBhbCBkaXNlw7FhciBtYXBhcyB0ZW3DoXRpY29zIGVzIGxhIGF1ZGllbmNpYSBkZWwgbWFwYSwgcXVlIGF5dWRhIGEgZGV0ZXJtaW5hciBxdcOpIGVsZW1lbnRvcyBkZWJlbiBpbmNsdWlyc2UgZW4gZWwgbWFwYSBjb21vIHB1bnRvcyBkZSByZWZlcmVuY2lhIGFkZW3DoXMgZGVsIHRlbWEuIFVuIG1hcGEgcXVlIHNlIGVzdMOhIGhhY2llbmRvIHBhcmEgdW4gY2llbnTDrWZpY28gcG9sw610aWNvLCBwb3IgZWplbXBsbywgbmVjZXNpdGFyw61hIG1vc3RyYXIgbMOtbWl0ZXMgcG9sw610aWNvcywgbWllbnRyYXMgcXVlIHVubyBwYXJhIHVuIGJpw7Nsb2dvIHBvZHLDrWEgbmVjZXNpdGFyIGNvbnRvcm5vcyBxdWUgbXVlc3RyZW4gbGEgZWxldmFjacOzbiDigJ0uDQoNCkxhcyBmdWVudGVzIGRlIGxvcyBkYXRvcyBkZSBsb3MgbWFwYXMgdGVtw6F0aWNvcyBzb24gbXV5IGltcG9ydGFudGVzLCBlbmZhdGl6YSBCcmluZXkuIOKAnExvcyBjYXJ0w7NncmFmb3MgZGViZW4gZW5jb250cmFyIGZ1ZW50ZXMgZGUgaW5mb3JtYWNpw7NuIHByZWNpc2FzLCByZWNpZW50ZXMgeSBjb25maWFibGVzIHNvYnJlIHVuYSBhbXBsaWEgZ2FtYSBkZSB0ZW1hcywgZGVzZGUgY2FyYWN0ZXLDrXN0aWNhcyBhbWJpZW50YWxlcyBoYXN0YSBkYXRvcyBkZW1vZ3LDoWZpY29zLCBwYXJhIGhhY2VyIGxvcyBtZWpvcmVzIG1hcGFzIHBvc2libGVz4oCdLg0KDQpCcmluZXkgcmVzdW1lIHZhcmlhcyB0w6ljbmljYXMgZGUgbWFwZW8gdGVtw6F0aWNvIHF1ZSBzZSB1dGlsaXphbiBjb24gbWF5b3IgZnJlY3VlbmNpYToNCiMjIDIuMSBNYXBhIGRlIGNvcm9wbMOpdGljbw0KcXVlIHJlcHJlc2VudGEgZGF0b3MgY3VhbnRpdGF0aXZvcyBjb21vIHVuIGNvbG9yIHkgcHVlZGUgbW9zdHJhciBkZW5zaWRhZCwgcG9yY2VudGFqZSwgdmFsb3IgcHJvbWVkaW8gbyBjYW50aWRhZCBkZSB1biBldmVudG8gZGVudHJvIGRlIHVuIMOhcmVhIGdlb2dyw6FmaWNhLiBMb3MgY29sb3JlcyBzZWN1ZW5jaWFsZXMgcmVwcmVzZW50YW4gdmFsb3JlcyBkZSBkYXRvcyBwb3NpdGl2b3MgbyBuZWdhdGl2b3MgY3JlY2llbnRlcyBvIGRlY3JlY2llbnRlcy4gTm9ybWFsbWVudGUsIGNhZGEgY29sb3IgdGFtYmnDqW4gcmVwcmVzZW50YSB1biByYW5nbyBkZSB2YWxvcmVzLg0KDQojIyAyLjIgTWFwYSBkZSBzw61tYm9sb3MgcHJvcG9yY2lvbmFsZXMgbyBncmFkdWFkb3MNCnF1ZSBzZSB1dGlsaXphbiBlbiBvdHJvIHRpcG8gZGUgbWFwYSBwYXJhIHJlcHJlc2VudGFyIGRhdG9zIGFzb2NpYWRvcyBjb24gdWJpY2FjaW9uZXMsIGNvbW8gY2l1ZGFkZXMuIExvcyBkYXRvcyBzZSBtdWVzdHJhbiBlbiBlc3RvcyBtYXBhcyBjb24gc8OtbWJvbG9zIGRlIHRhbWHDsW8gcHJvcG9yY2lvbmFsIHBhcmEgbW9zdHJhciBkaWZlcmVuY2lhcyBlbiBsYXMgb2N1cnJlbmNpYXMuIExvcyBjw61yY3Vsb3Mgc2UgdXRpbGl6YW4gY29uIG1heW9yIGZyZWN1ZW5jaWEsIHBlcm8gdGFtYmnDqW4gc29uIGFkZWN1YWRvcyBsb3MgY3VhZHJhZG9zIHkgb3RyYXMgZm9ybWFzIGdlb23DqXRyaWNhcy4gTGEgZm9ybWEgbcOhcyBjb23Dum4gZGUgZGltZW5zaW9uYXIgZXN0b3Mgc8OtbWJvbG9zIGVzIGhhY2VyIHF1ZSBzdXMgw6FyZWFzIHNlYW4gcHJvcG9yY2lvbmFsZXMgYSBsb3MgdmFsb3JlcyBxdWUgc2UgdmFuIGEgcmVwcmVzZW50YXIgdXRpbGl6YW5kbyBzb2Z0d2FyZSBkZSBtYXBlbyBvIGRpYnVqby4NCg0KIyMgMi4zIE1hcGEgaXNhcsOtdG1pY28gbyBkZSBjb250b3Jubw0KcXVlIHV0aWxpemEgaXNvbMOtbmVhcyBwYXJhIHJlcHJlc2VudGFyIHZhbG9yZXMgY29udGludW9zIGNvbW8gbG9zIG5pdmVsZXMgZGUgcHJlY2lwaXRhY2nDs24uIEVzdG9zIG1hcGFzIHRhbWJpw6luIHB1ZWRlbiBtb3N0cmFyIHZhbG9yZXMgdHJpZGltZW5zaW9uYWxlcywgY29tbyBsYSBlbGV2YWNpw7NuLCBlbiBtYXBhcyB0b3BvZ3LDoWZpY29zLiBHZW5lcmFsbWVudGUsIGxvcyBkYXRvcyBwYXJhIG1hcGFzIGlzYXLDrXRtaWNvcyBzZSByZWNvcGlsYW4gYSB0cmF2w6lzIGRlIHB1bnRvcyBtZWRpYmxlcyAocG9yIGVqZW1wbG8sIGVzdGFjaW9uZXMgbWV0ZW9yb2zDs2dpY2FzKSBvIHNlIHJlY29waWxhbiBwb3Igw6FyZWEgKHBvciBlamVtcGxvLCB0b25lbGFkYXMgZGUgbWHDrXogcG9yIGFjcmUgcG9yIGNvbmRhZG8pLiBMb3MgbWFwYXMgaXNhcsOtdG1pY29zIHRhbWJpw6luIHNpZ3VlbiBsYSByZWdsYSBiw6FzaWNhIGRlIHF1ZSBoYXkgbGFkb3MgYWx0b3MgeSBiYWpvcyBlbiByZWxhY2nDs24gY29uIGxhIGlzb2xpbmEuIFBvciBlamVtcGxvLCBlbiBlbGV2YWNpw7NuLCBzaSBsYSBpc29sw61uZWEgZXMgZGUgNTAwIHBpZXMsIGVudG9uY2VzIHVuIGxhZG8gZGViZSB0ZW5lciBtw6FzIGRlIDUwMCBwaWVzIHkgdW4gbGFkbyBkZWJlIHNlciBtw6FzIGJham8uDQoNCiMjIDIuNCBNYXBhIGRlIHB1bnRvcw0KcXVlIHV0aWxpemEgcHVudG9zIHBhcmEgbW9zdHJhciBsYSBwcmVzZW5jaWEgZGUgdW4gdGVtYSB5IG1vc3RyYXIgdW4gcGF0csOzbiBlc3BhY2lhbC4gVW4gcHVudG8gcHVlZGUgcmVwcmVzZW50YXIgdW5hIHVuaWRhZCBvIHZhcmlhcywgZGVwZW5kaWVuZG8gZGUgbG8gcXVlIHNlIGVzdMOpIHJlcHJlc2VudGFuZG8uDQoNCiMjIDMuIERhdG9zDQpVc2FyZW1vcyBkYXRvcyBzb2JyZSBbTmVjZXNpZGFkZXMgQsOhc2ljYXMgSW5zYXRpc2ZlY2hhc10oaHR0cHM6Ly93d3cuZGFuZS5nb3YuY28vaW5kZXgucGhwL2VzdGFkaXN0aWNhcy1wb3ItdGVtYS9wb2JyZXphLXktY29uZGljaW9uZXMtZGUtdmlkYS9uZWNlc2lkYWRlcy1iYXNpY2FzLWluc2F0aXNmZWNoYXMtbmJpKSAoTkJJKSBkZWwgQ2Vuc28gTmFjaW9uYWwgZGUgUG9ibGFjacOzbiB5IFZpdmllbmRhIDIwMTggcXVlIGVzdMOhbiBkaXNwb25pYmxlcyBlbiBlbCBbR2VvcG9ydGFsIGRlbCBEQU5FLl0oaHR0cHM6Ly93d3cuZGFuZS5nb3YuY28vZmlsZXMvY2Vuc28yMDE4L2luZm9ybWFjaW9uLXRlY25pY2EvQ05QVi0yMDE4LU5CSS54bHN4KQ0KDQpMb3MgbWFwYXMgdGVtw6F0aWNvcyBzb24gw7p0aWxlcyBwYXJhIHRyYW5zbWl0aXIgaW5mb3JtYWNpw7NuIGRlbW9ncsOhZmljYS4gUHVlZGUgZXhwbG9yYXIgdmFyaW9zIG1hcGFzIHRlbcOhdGljb3MgZGVsIERBTkUgdXNhbmRvIGVzdGUgZW5sYWNlLg0KDQpBbnRlcmlvcm1lbnRlLCBkZXNjYXJndcOpIGVsIGFyY2hpdm8gTkJJLCBlbiBmb3JtYXRvIC54bHN4LCBhIG1pIGNvbXB1dGFkb3JhLiBMdWVnbywgdXPDqSBFeGNlbCBwYXJhIGVsaW1pbmFyIGRhdG9zIGRlIG11bmljaXBpb3MgcXVlIG5vIHNlIGVuY3VlbnRyYW4gZGVudHJvIGRlbCBEZXBhcnRhbWVudG8gZGUgQ2F1Y2EuIFRhbWJpw6luICJsaW1wacOpIiBsb3MgZGF0b3MsIHF1ZSBlbGltaW7DqSB2YXJpYXMgZmlsYXMgY29uIGltw6FnZW5lcyBpbnN0aXR1Y2lvbmFsZXMgbyBzaW4gaW5mb3JtYWNpw7NuLiBFc3RhcyBmaWxhcyBzZSB1YmljYXJvbiB0YW50byBhbCBwcmluY2lwaW8gY29tbyBhbCBmaW5hbCBkZWwgYXJjaGl2byBvcmlnaW5hbC4gQ29uc2Vydm8gbGFzIGNvbHVtbmFzIHJlZmVyZW50ZXMgYSB0b2RvIGVsIG11bmljaXBpby4gR3VhcmTDqSBsb3MgZGF0b3MgcmVzdWx0YW50ZXMsIGNvcnJlc3BvbmRpZW50ZXMgc29sbyBhIGxvcyBtdW5pY2lwaW9zIGRlIENhdWNhIGNvbW8gTkJJX0NhdWNhLnhsc3guDQoNCiMjIDQuIFByZXBhcmFjacOzbg0KTGltcGllbW9zIGxhIG1lbW9yaWE6DQpgYGB7cn0NCnJtKGxpc3Q9bHMoKSkNCmBgYA0KDQpBaG9yYSwgaW5zdGFsZW1vcyBsYXMgYmlibGlvdGVjYXMgcXVlIG5lY2VzaXRhbW9zLg0KYGBge3J9DQpsaXN0Lm9mLnBhY2thZ2VzIDwtIGMoInRpZHl2ZXJzZSIsICJyZ2VvcyIsICJzZiIsICJyYXN0ZXIiLCAiY2FydG9ncmFwaHkiLCAiU3BhdGlhbFBvc2l0aW9uIikNCm5ldy5wYWNrYWdlcyA8LSBsaXN0Lm9mLnBhY2thZ2VzWyEobGlzdC5vZi5wYWNrYWdlcyAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpWywiUGFja2FnZSJdKV0NCmlmKGxlbmd0aChuZXcucGFja2FnZXMpKSBpbnN0YWxsLnBhY2thZ2VzKG5ldy5wYWNrYWdlcykNCmBgYA0KTHVlZ28sIGNhcmd1ZW1vcyBsYXMgYmlibGlvdGVjYXMuDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShyZWFkeGwpICMjIHRoaXMgbGlicmFyeSBpcyBwYXJ0IG9mIHRoZSB0aWR5dmVyc2UNCmxpYnJhcnkocmdlb3MpDQpsaWJyYXJ5KHJhc3RlcikNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KGNhcnRvZ3JhcGh5KQ0KbGlicmFyeShTcGF0aWFsUG9zaXRpb24pDQpgYGANCiMjIDUuIExlZXIgZGF0b3MgZGUgTkJJDQpMZWFtb3MgZWwgYXJjaGl2byBjc3YgY29uIOKAnGVzdGFkaXN0aWNhcyBtdW5pY2lwYWxlcyBhZ3JvcGVjdWFyaWFz4oCdIHBhcmEgQ2F1Y2EuDQpgYGB7cn0NCm5iaSA8LSByZWFkX2V4Y2VsKCJDOi9Vc2Vycy9yb2phcy9PbmVEcml2ZS9Fc2NyaXRvcmlvL1IgZXN0dWRpby9HZW9tYXRpY2EvaW5mb3JtZSBkb3MvTkJJX0NhdWNhMi54bHN4IikNCmBgYA0KDQpWZWFtb3MgY3XDoWxlcyBzb24gbG9zIGF0cmlidXRvcyBkZSBsb3MgZGF0b3MuDQpgYGB7cn0NCmhlYWQobmJpKQ0KYGBgDQpgYGB7cn0NCm5iaTI8LW5iaQ0KbmJpMiRjb2RfbXVuIDwtICBhcy5jaGFyYWN0ZXIobmJpMiRDT0RfTVVOKQ0KbmJpMiRNUElPX0NDREdPIDwtIGFzLmZhY3RvcihwYXN0ZSgxOSwgbmJpMiRjb2RfbXVuLCBzZXA9IiIpKQ0KDQpgYGANCg0KQnVzcXVlbW9zIGN1w6FsIGVzIGVsIG11bmljaXBpbyBjb24gZWwgcG9yY2VudGFqZSBtw6FzIGFsdG8gZGUgTkJJOg0KYGBge3J9DQpuYmkyICU+JSANCiAgICBzbGljZSh3aGljaC5tYXgoTkJJKSkgLT4gbWF4X25iaQ0KDQptYXhfbmJpDQpgYGANCkJ1c3F1ZW1vcyBjdcOhbCBlcyBlbCBtdW5pY2lwaW8gY29uIGVsIHBvcmNlbnRhamUgbcOhcyBiYWpvIGRlIE5CSToNCmBgYHtyfQ0KbmJpMiAlPiUgDQogICAgc2xpY2Uod2hpY2gubWluKE5CSSkpIC0+IG1pbl9uYmkNCg0KbWluX25iaQ0KYGBgDQpDbGFzaWZpcXVlbW9zIGxvcyBtdW5pY2lwaW9zIHBvciBOQkkgZW4gb3JkZW4gZGVzY2VuZGVudGU6DQpgYGB7cn0NCm5iaTIgJT4lIA0KICBhcnJhbmdlKGRlc2MoTkJJKSkgIC0+IGRlc2NfbmJpDQoNCmRlc2NfbmJpDQpgYGANCiMjIDYuIFVuacOzbiBkZSBkYXRvcyBkZWwgTkJJIGEgbG9zIG11bmljaXBpb3MNCkNvbWVuY2Vtb3MgYSBsZWVyIGxvcyBkYXRvcyBhZG1pbmlzdHJhdGl2b3MgZGUgQ2F1Y2EsIGRhZG9zIHBvciBNYXJjbyBHZW9lc3RhZGlzdGljbyBEZXBhcnRhbWVudGFsIHF1ZSBzZSBlbmN1ZW50cmEgZGlzcG9uaWJsZSBlbiBEQU5FIEdlb3BvcnRhbCwgdXNhbmRvIGxhIGJpYmxpb3RlY2Egc2Y6DQpgYGB7cn0NCm11bmljIDwtc3RfcmVhZCgiQzovVXNlcnMvcm9qYXMvT25lRHJpdmUvRXNjcml0b3Jpby9SIGVzdHVkaW8vR2VvbWF0aWNhL0RlcGFydGFtZW50by8xOV9DQVVDQS9DYXVjYS9BRE1JTklTVFJBVElWTy9NR05fTVBJT19QT0xJVElDTy5zaHAiKQ0KYGBgDQpWZWFtb3MgcXXDqSBoYXkgZGVudHJvIGRlbCBhdHJpYnV0byBNUElPX0NDREdPOg0KYGBge3J9DQpoZWFkKG11bmljJE1QSU9fQ0NER08pDQpgYGANCg0KUG9kZW1vcyB1c2FyIGxhIGZ1bmNpw7NuIGxlZnRfam9pbiBwYXJhIHVuaXIgbG9zIG11bmljaXBpb3MgeSBsb3MgZGF0b3MgZGUgTkJJLg0KYGBge3J9DQpuYmlfbXVuaWMgPSBsZWZ0X2pvaW4obXVuaWMsIG5iaTIsIGJ5PWMoIk1QSU9fQ0NER08iKSkNCmBgYA0KYGBge3J9DQpuYmlfbXVuaWMgJT4lDQogIGRwbHlyOjpzZWxlY3QoTVVOSUNJUElPLCBNUElPX0NDREdPLCBOQkkpICAtPiAgY2hlY2tfbmJpX211bmljDQoNCmhlYWQoY2hlY2tfbmJpX211bmljKQ0KYGBgDQpBaG9yYSByZXByb3llY3RlbW9zIGxvcyBkYXRvcyANCmBgYHtyfQ0KbmJpX211bmljX25ldyA8LSBzdF90cmFuc2Zvcm0obmJpX211bmljLCBjcnMgPSAzMTE2KQ0KYGBgDQojIyA3LiBFamVtcGxvcyBkZSBtYXBhcyB0ZW3DoXRpY29zDQpVdGlsaXphcmVtb3MgZWwgcGFxdWV0ZSBkZSBjYXJ0b2dyYWbDrWEgcXVlIHRpZW5lIGNvbW8gb2JqZXRpdm8gb2J0ZW5lciBtYXBhcyB0ZW3DoXRpY29zIGNvbiBsYSBjYWxpZGFkIHZpc3VhbCBkZSBsb3MgY29uc3RydWlkb3MgY29uIHVuIHNvZnR3YXJlIGNsw6FzaWNvIGRlIGNhcnRvZ3JhZsOtYSBvIEdJUy4gU3VzIGZ1bmNpb25lcyBzb24gaW50dWl0aXZhcyBwYXJhIGxvcyB1c3VhcmlvcyB5IGdhcmFudGl6YW4gbGEgY29tcGF0aWJpbGlkYWQgY29uIGxvcyBmbHVqb3MgZGUgdHJhYmFqbyBjb211bmVzIGRlIFIuDQoNCkxhIGJpYmxpb3RlY2EgZGUgY2FydG9ncmFmw61hIHV0aWxpemEgb2JqZXRvcyBzZiBvIHNwIHBhcmEgcHJvZHVjaXIgZ3LDoWZpY29zIGJhc2UuIENvbW8gbGEgbWF5b3LDrWEgZGUgbG9zIGNvbXBvbmVudGVzIGludGVybm9zIGRlbCBwYXF1ZXRlIHNlIGJhc2FuIGVuIGZ1bmNpb25hbGlkYWRlcyBzZiwgZWwgZm9ybWF0byBwcmVmZXJpZG8gcGFyYSBsb3Mgb2JqZXRvcyBlc3BhY2lhbGVzIGVzIHNmLg0KDQojIyA3LiAxIE1hcGEgYmFzZSB5IHPDrW1ib2xvcyBwcm9wb3JjaW9uYWxlcyBkZSBPcGVuU3RyZWV0TWFwDQpMYXMgZnVuY2lvbmVzIGdldFRpbGVzICgpIHkgdGlsZXNMYXllciAoKSBkZXNjYXJnYW4geSBtdWVzdHJhbiBtb3NhaWNvcyBkZSBPcGVuU3RyZWV0TWFwLiBUZW5nYSBjdWlkYWRvIGRlIGNpdGFyIGxhIGZ1ZW50ZSBkZSBsb3MgbW9zYWljb3MgZGUgbWFuZXJhIGFkZWN1YWRhLg0KDQpwcm9wU3ltYm9sc0xheWVyICgpIG11ZXN0cmEgc8OtbWJvbG9zIGNvbiDDoXJlYXMgcHJvcG9yY2lvbmFsZXMgYSB1bmEgdmFyaWFibGUgY3VhbnRpdGF0aXZhIChwb3IgZWplbXBsbywgTkJJKS4gSGF5IHZhcmlvcyBzw61tYm9sb3MgZGlzcG9uaWJsZXMgKGPDrXJjdWxvcywgY3VhZHJhZG9zLCBiYXJyYXMpLiBFbCBhcmd1bWVudG8gcHVsZ2FkYXMgc2UgdXRpbGl6YSBwYXJhIHBlcnNvbmFsaXphciBsb3MgdGFtYcOxb3MgZGUgbG9zIHPDrW1ib2xvcy4NCg0KYGBge3J9DQptdW4ub3NtIDwtIGdldFRpbGVzKA0KeCA9IG5iaV9tdW5pY19uZXcsIA0KdHlwZSA9ICJPcGVuU3RyZWV0TWFwIiwgDQp6b29tID0gMTAsDQpjYWNoZWRpciA9IFRSVUUsDQpjcm9wID0gRkFMU0UNCikNCg0KYGBgDQoNCmBgYHtyfQ0KIyBzZXQgbWFyZ2lucw0Kb3BhciA8LSBwYXIobWFyID0gYygwLDAsMS4yLDApKQ0KIyBwbG90IG9zbSB0aWxlcw0KdGlsZXNMYXllcih4ID0gbXVuLm9zbSkNCiMgcGxvdCBtdW5pY2lwYWxpdGllcyAob25seSBib3JkZXJzIGFyZSBwbG90dGVkKQ0KcGxvdChzdF9nZW9tZXRyeShuYmlfbXVuaWNfbmV3KSwgY29sID0gTkEsIGJvcmRlciA9ICJCbGFjayIsIGFkZD1UUlVFKQ0KIyBwbG90IE5CSQ0KcHJvcFN5bWJvbHNMYXllcigNCiAgeCA9IG5iaV9tdW5pY19uZXcsIA0KICB2YXIgPSAiTkJJIiwgDQogIGluY2hlcyA9IDAuMTUsIA0KICBjb2wgPSAiUmVkIiwNCiAgbGVnZW5kLnBvcyA9ICJ0b3ByaWdodCIsICANCiAgbGVnZW5kLnRpdGxlLnR4dCA9ICJUb3RhbCBOQkkiDQopDQojIGxheW91dA0KbGF5b3V0TGF5ZXIodGl0bGUgPSAiIERpc3RyaWJ1Y2nDs24gZGUgTkJJIGVuIENhdWNhIiwNCiAgICAgICAgICAgIHNvdXJjZXMgPSAiU291cmNlczogREFORSwgMjAxOFxuwqkgT3BlblN0cmVldE1hcCIsDQogICAgICAgICAgICBhdXRob3IgPSAiIEpvaGFuIFJvamFzIiwNCiAgICAgICAgICAgIGZyYW1lID0gVFJVRSwgbm9ydGggPSBGQUxTRSwgdGFidGl0bGUgPSBUUlVFKQ0KIyBub3J0aCBhcnJvdw0Kbm9ydGgocG9zID0gInRvcGxlZnQiKQ0KYGBgDQojIyA3LiAyIG1hcGFzIGRlIGNvcm9wbGV0aWNvcw0KRW4gbG9zIG1hcGFzIGRlIGNvcm9wbGV0aWNvcywgbGFzIMOhcmVhcyBlc3TDoW4gc29tYnJlYWRhcyBkZSBhY3VlcmRvIGNvbiBsYSB2YXJpYWNpw7NuIGRlIHVuYSB2YXJpYWJsZSBjdWFudGl0YXRpdmEuIFNlIHV0aWxpemFuIHBhcmEgcmVwcmVzZW50YXIgcHJvcG9yY2lvbmVzIG8gw61uZGljZXMuDQoNCmNob3JvTGF5ZXIgKCkgbXVlc3RyYSBtYXBhcyBkZSBjb3JvcGxldGljb3MuIExvcyBhcmd1bWVudG9zIG5jbGFzcywgbcOpdG9kbyB5IHJ1cHR1cmFzIHBlcm1pdGVuIHBlcnNvbmFsaXphciBsYSBjbGFzaWZpY2FjacOzbiBkZSBsYXMgdmFyaWFibGVzLg0KDQpnZXRCcmVha3MgKCkgcGVybWl0ZSBjbGFzaWZpY2FyIGZ1ZXJhIGRlIGxhIGZ1bmNpw7NuIGVuIHPDrS4gTGFzIHBhbGV0YXMgZGUgY29sb3JlcyBzZSBkZWZpbmVuIGNvbiBjb2wgeSBzZSBwdWVkZSBjcmVhciB1biBjb25qdW50byBkZSBjb2xvcmVzIGNvbiBjYXJ0by5wYWwgKCkuIENvbnN1bHRlIHRhbWJpw6luIGRpc3BsYXkuY2FydG8uYWxsICgpLg0KDQpgYGB7cn0NCiMgZXN0YWJsZWNlciBtw6FyZ2VuZXMNCm9wYXIgPC0gcGFyKG1hciA9IGMoMCwwLDEuMiwwKSkNCiMgZXN0YWJsZWNlciBjb2xvciBkZSBmb25kbyBkZSBsYXMgZmlndXJhcyANCnBhcihiZz0iZ3JleTkwIikNCiMgdHJhemFyIG11bmljaXBpb3MgKHNvbG8gc2UgdHJhemEgZWwgY29sb3IgZGUgZm9uZG8pDQpwbG90KHN0X2dlb21ldHJ5KG5iaV9tdW5pY19uZXcpLCBjb2wgPSBOQSwgYm9yZGVyID0gTkEsIGJnID0gIiNhYWRhZmYiKQ0KIyB0cmF6YXIgTkJJDQpjaG9yb0xheWVyKA0KICB4ID0gbmJpX211bmljX25ldywgDQogIHZhciA9ICJOQkkiLA0KICBtZXRob2QgPSAiZ2VvbSIsDQogIG5jbGFzcz01LA0KICBjb2wgPSBjYXJ0by5wYWwocGFsMSA9ICJzYW5kLnBhbCIsIG4xID0gNSksDQogIGJvcmRlciA9ICJCbGFjayIsIA0KICBsd2QgPSAwLjUsDQogIGxlZ2VuZC5wb3MgPSAidG9wcmlnaHQiLCANCiAgbGVnZW5kLnRpdGxlLnR4dCA9ICJOQkkiLA0KICBhZGQgPSBUUlVFDQopIA0KIyBEaXNlw7FvDQpsYXlvdXRMYXllcih0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIE5CSSBlbiBDYXVjYSIsIA0KICAgICAgICAgICAgc291cmNlcyA9ICJTb3VyY2U6IERBTkUsIDIwMTgiLA0KICAgICAgICAgICAgYXV0aG9yID0gIkpvaGFuIFJvamFzIiwgDQogICAgICAgICAgICBmcmFtZSA9IFRSVUUsIG5vcnRoID0gVFJVRSwgdGFidGl0bGUgPSBUUlVFLCBjb2w9ImJsYWNrIikgDQojIEZsZWNoYSBkZWwgbm9ydGUgDQpub3J0aChwb3MgPSAidG9wbGVmdCIpDQpgYGANCjcuMyBNYXBhIGRlIHPDrW1ib2xvcyBwcm9wb3JjaW9uYWxlcyB5IHRpcG9sb2fDrWENCkxhIGZ1bmNpw7NuIHByb3BTeW1ib2xzVHlwb0xheWVyICgpIGNyZWEgdW4gbWFwYSBkZSBzw61tYm9sb3MgcXVlIHNvbiBwcm9wb3JjaW9uYWxlcyBhIGxvcyB2YWxvcmVzIGRlIHVuYSBwcmltZXJhIHZhcmlhYmxlIHkgY29sb3JlYWRvcyBwYXJhIHJlZmxlamFyIGxhcyBtb2RhbGlkYWRlcyBkZSB1bmEgc2VndW5kYSB2YXJpYWJsZSBkZSBjYWxpZGFkLiBTZSB1dGlsaXphIHVuYSBjb21iaW5hY2nDs24gZGUgYXJndW1lbnRvcyBwcm9wU3ltYm9sc0xheWVyICgpIHkgdHlwb0xheWVyICgpLg0KDQpQcmltZXJvLCBuZWNlc2l0YW1vcyBjcmVhciB1bmEgdmFyaWFibGUgY3VhbGl0YXRpdmEuIFVzZW1vcyBsYSBmdW5jacOzbiBtdXRhdGUgcGFyYSBlc3RhIHRhcmVhLg0KYGBge3J9DQpuYmlfbXVuaWNfMiA8LSBkcGx5cjo6bXV0YXRlKG5iaV9tdW5pY19uZXcsIHBvYnJlemEgPSBpZmVsc2UoTUlTRVJJQSA+IDIwLCAiRXh0cmVtYSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEhBQ0lOQU1JRU5UTyA+IDUsICJBbHRhIiwgIkludGVybWVkaWEiKSkpDQpgYGANClRlbmdhIGVuIGN1ZW50YSBxdWUgZWwgbnVldm8gYXRyaWJ1dG8gc2UgbGxhbWEgcG9icmV6YS4gU3UgdmFsb3IgZGVwZW5kZSBkZSBsb3MgdmFsb3JlcyB1bWJyYWwgZGVmaW5pZG9zIHBvciBlbCB1c3VhcmlvLiBBc2Vnw7pyZXNlIGRlIHZlcmlmaWNhciBsYSBzaW50YXhpcyBkZWwgY29tYW5kbyBpZmVsc2UgcGFyYSBjb21wcmVuZGVyIGxvIHF1ZSBlc3TDoSBzdWNlZGllbmRvDQpgYGB7cn0NCmhlYWQobmJpX211bmljXzIpDQpgYGANCmBgYHtyfQ0KbGlicmFyeShzZikNCmxpYnJhcnkoY2FydG9ncmFwaHkpDQojIHNldCBtYXJnaW5zDQpvcGFyIDwtIHBhcihtYXIgPSBjKDAsMCwxLjIsMCkpDQojIFBsb3QgdGhlIG11bmljaXBhbGl0aWVzDQpwbG90KHN0X2dlb21ldHJ5KG5iaV9tdW5pY18yKSwgY29sPSIjQ0Q4NTNGIiwgYm9yZGVyPSIjMDAwMDAwIiwgYmcgPSAiI2FhZDNkZiIsIA0KICAgICBsd2QgPSAwLjUpDQojIFBsb3Qgc3ltYm9scyB3aXRoIGNob3JvcGxldGggY29sb3JhdGlvbg0KcHJvcFN5bWJvbHNUeXBvTGF5ZXIoDQogIHggPSBuYmlfbXVuaWNfMiwgDQogIHZhciA9ICJOQkkiLCANCiAgaW5jaGVzID0gMC4zLA0KICBzeW1ib2xzID0gInNxdWFyZSIsDQogIGJvcmRlciA9ICJ3aGl0ZSIsDQogIGx3ZCA9IC41LA0KICBsZWdlbmQudmFyLnBvcyA9IGMoODQ1ODcyLjksIDc1OTg3NS4pLCANCiAgbGVnZW5kLnZhci50aXRsZS50eHQgPSAiTkJJIiwNCiAgdmFyMiA9ICJwb2JyZXphIiwNCiAgbGVnZW5kLnZhcjIudmFsdWVzLm9yZGVyID0gYygiSW50ZXJtZWRpYSIsICJBbHRhIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkV4dHJlbWEiKSwNCiAgY29sID0gY2FydG8ucGFsKHBhbDEgPSAib3JhbmdlLnBhbCIsIG4xID0gMyksDQogIGxlZ2VuZC52YXIyLnBvcyA9IGMoODQ1ODcyLjkgLCA2NDk4NzUuNiksIA0KICBsZWdlbmQudmFyMi50aXRsZS50eHQgPSAiUG9icmV6YSINCikgDQojIGxheW91dA0KbGF5b3V0TGF5ZXIodGl0bGU9IkRpc3RyaWJ1Y2nDs24gZGUgTkJJIGVuIENhdWNhIiwgDQogICAgICAgICAgICBhdXRob3IgPSAiSm9oYW4gUm9qYXMiLCANCiAgICAgICAgICAgIHNvdXJjZXMgPSAiU291cmNlOiBEQU5FLCAyMDE4IiwgDQogICAgICAgICAgICBzY2FsZSA9IDEsIHRhYnRpdGxlID0gVFJVRSwgZnJhbWUgPSBUUlVFKQ0KIyBub3J0aCBhcnJvdw0Kbm9ydGgocG9zID0gInRvcGxlZnQiKQ0KYGBgDQojIyA3LjQgRXRpcXVldGFyIG1hcGFzDQpJbnRlbnRlbW9zIGNvbWJpbmFyIGxhcyBmdW5jaW9uZXMgY2hvcm9MYXllciB5IGxhYmVsTGF5ZXI6DQpgYGB7cn0NCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KGNhcnRvZ3JhcGh5KQ0KIyBzZXQgbWFyZ2lucw0Kb3BhciA8LSBwYXIobWFyID0gYygwLDAsMS4yLDApKQ0KIyBzZXQgZmlndXJlIGJhY2tncm91bmQgY29sb3INCnBhcihiZz0iZ3JleTI1IikNCiMgcGxvdCBtdW5pY2lwYWxpdGllcw0KcGxvdChzdF9nZW9tZXRyeShuYmlfbXVuaWNfMiksIGNvbCA9ICIjZTRlOWRlIiwgYm9yZGVyID0gIkJsYWNrIiwgDQogICAgIGJnID0gImdyZXk3NSIsIGx3ZCA9IDAuNSkNCiMgcGxvdCBOQkkNCmNob3JvTGF5ZXIoDQogIHggPSBuYmlfbXVuaWNfbmV3LCANCiAgdmFyID0gIk5CSSIsDQogIG1ldGhvZCA9ICJnZW9tIiwNCiAgbmNsYXNzPTUsDQogIGNvbCA9IGNhcnRvLnBhbChwYWwxID0gIndpbmUucGFsIiwgbjEgPSA1KSwNCiAgYm9yZGVyID0gIkJsYWNrIiwgDQogIGx3ZCA9IDAuNSwNCiAgbGVnZW5kLnBvcyA9ICJ0b3ByaWdodCIsIA0KICBsZWdlbmQudGl0bGUudHh0ID0gIk5CSSIsDQogIGFkZCA9IFRSVUUNCikgDQojIHBsb3QgbGFiZWxzDQpsYWJlbExheWVyKA0KICB4ID0gbmJpX211bmljXzIsIA0KICB0eHQgPSAiTVVOSUNJUElPIiwgDQogIGNvbD0gIndoaXRlIiwgDQogIGNleCA9IDAuNCwgDQogIGZvbnQgPSA0LA0KICBoYWxvID0gVFJVRSwgDQogIGJnID0gIkJsYWNrIiwgDQogIHIgPSAwLjEsIA0KICBvdmVybGFwID0gRkFMU0UsIA0KICBzaG93LmxpbmVzID0gRkFMU0UNCikNCiMgbWFwIGxheW91dA0KbGF5b3V0TGF5ZXIoDQogIHRpdGxlID0gIk11bmljaXBpb3MgZGUgQ2F1Y2EiLCANCiAgc291cmNlcyA9ICJTb3VyY2U6IERBTkUsIDIwMTgiLCAgDQogIGF1dGhvciA9ICJKb2hhbiBSb2phcyIsIA0KICBmcmFtZSA9IFRSVUUsDQogIG5vcnRoID0gVFJVRSwgDQogIHRhYnRpdGxlID0gVFJVRSwgDQogIHRoZW1lID0gInRhdXBlLnBhbCINCikgDQpgYGANCjcuNSBNYXBhcyBkZSBJc29wbGV0aWNvcw0KTG9zIG1hcGFzIGRlIElzb3BsZXRpY29zIHNlIGJhc2FuIGVuIGVsIHN1cHVlc3RvIGRlIHF1ZSBlbCBmZW7Ds21lbm8gYSByZXByZXNlbnRhciB0aWVuZSB1bmEgZGlzdHJpYnVjacOzbiBjb250aW51YS4gRXN0b3MgbWFwYXMgdXRpbGl6YW4gdW4gZW5mb3F1ZSBkZSBtb2RlbGFkbyBkZSBpbnRlcmFjY2nDs24gZXNwYWNpYWwgcXVlIHRpZW5lIGNvbW8gb2JqZXRpdm8gY2FsY3VsYXIgaW5kaWNhZG9yZXMgYmFzYWRvcyBlbiB2YWxvcmVzIGRlIHN0b2NrIHBvbmRlcmFkb3MgcG9yIGRpc3RhbmNpYS4gUGVybWl0ZSB1bmEgcmVwcmVzZW50YWNpw7NuIGVzcGFjaWFsIGRlbCBmZW7Ds21lbm8gaW5kZXBlbmRpZW50ZSBkZSBsYSBoZXRlcm9nZW5laWRhZCBpbmljaWFsIGRlIGxhIGRpdmlzacOzbiB0ZXJyaXRvcmlhbC4gc21vb3RoTGF5ZXIgKCkgZGVwZW5kZSBlbiBncmFuIG1lZGlkYSBkZWwgcGFxdWV0ZSBTcGF0aWFsUG9zaXRpb24uIExhIGZ1bmNpw7NuIHV0aWxpemEgdW5hIGNhcGEgZGUgcHVudG9zIG1hcmNhZG9zIHkgdW4gY29uanVudG8gZGUgcGFyw6FtZXRyb3MgKHVuYSBmdW5jacOzbiBkZSBpbnRlcmFjY2nDs24gZXNwYWNpYWwgeSBzdXMgcGFyw6FtZXRyb3MpIHkgbXVlc3RyYSB1bmEgY2FwYSBkZSBtYXBhIGlzb3BsZXRhLg0KDQpVc2Vtb3Mgb3RybyBjb25qdW50byBkZSBkYXRvcyBwYXJhIGhhY2VyIHVuIG1hcGEgZGUgaXNvcGxldGFzLiBFbiBlc3RlIGNhc28sIHN1Ymlyw6kgZGF0b3MgZXN0YWTDrXN0aWNvcyBzb2JyZSBsYSBwcm9kdWNjacOzbiBkZSBjYWbDqSBkZSAyMDE4IGVuIEFudGlvcXVpYS4gWWEgY29ub2NlbW9zIGVzdGUgY29uanVudG8gZGUgZGF0b3MsIHlhIHF1ZSBzZSB1c8OzIGVuIHVuIGN1YWRlcm5vIGFudGVyaW9yIHBhcmEgaWx1c3RyYXIgdW5pb25lcyBiYXNhZGFzIGVuIGF0cmlidXRvcy4NCg0KTGVlciBlbCBjb25qdW50byBkZSBkYXRvczoNCmBgYHtyfQ0KY3VsdGl2b3MyMDE4IDwtcmVhZF9jc3YoIkM6L1VzZXJzL3JvamFzL09uZURyaXZlL0VzY3JpdG9yaW8vUiBlc3R1ZGlvL0dlb21hdGljYS90cmFiYWpvNy9FVkFfY2F1Y2EuY3N2IikNCmBgYA0KYGBge3J9DQpoZWFkKGN1bHRpdm9zMjAxOCkgDQpgYGANCkZpbHRyYXIgZmlsYXMgcXVlIHJlcHJlc2VudGFuIHNvbG8gZGF0b3MgZGUgY2Fmw6k6DQpgYGB7cn0NCmN1bHRpdm9zMjAxOCAlPiUNCiAgZmlsdGVyKENVTFRJVk8gPT0gIkNBRkUiKSAtPiBjYWZlMjAxOA0KaGVhZChjYWZlMjAxOCkNCmBgYA0KDQpBaG9yYSwgaGF6IGxhIHVuacOzbg0KYGBge3J9DQpjYWZlX211bmljID0gbGVmdF9qb2luKG11bmljLCBjYWZlMjAxOCwgYnk9YygiTVBJT19DQ0RHTyI9IkNPRCIpKQ0KYGBgDQpWZXJpZmlxdWUgbGEgc2FsaWRhOg0KYGBge3J9DQpoZWFkKGNhZmVfbXVuaWMpDQpgYGANCkFob3JhLCByZXByb3llY3RlbW9zIGxvcyBtdW5pY2lwaW9zOg0KYGBge3J9DQpyZXBfY2FmZSA8LSBzdF90cmFuc2Zvcm0oY2FmZV9tdW5pYywgY3JzID0gMzExNikNCmBgYA0KDQphaG9yYSBoYWNlbW9zIGVsIG1hcGVvDQpgYGB7cn0NCnN1bW1hcnkocmVwX2NhZmUkVE9OX1BST0QpDQoNCmBgYA0KDQpgYGB7cn0NCiMgc2V0IG1hcmdpbnMNCm9wYXIgPC0gcGFyKG1hciA9IGMoMCwwLDEuMiwwKSkNCiMgcGxvdCBtdW5pY2lwYWxpdGllcyAob25seSB0aGUgYmFja2dyb3VuZyBjb2xvciBpcyBwbG90dGVkKQ0KcGxvdChzdF9nZW9tZXRyeShyZXBfY2FmZSksIGNvbCA9IE5BLCBib3JkZXIgPSAiQmxhY2siLCBiZyA9ICJncmV5NzUiKQ0KIyBwbG90IGlzb3BsZXRoIG1hcA0Kc21vb3RoTGF5ZXIoDQogIHggPSByZXBfY2FmZSwgDQogIHZhciA9ICdUT05fUFJPRCcsDQogIHR5cGVmY3QgPSAiZXhwb25lbnRpYWwiLA0KICBzcGFuID0gMTIwMDAsDQogIGJldGEgPSAyLA0KICBuY2xhc3MgPSAxMCwNCiAgY29sID0gY2FydG8ucGFsKHBhbDEgPSAnZ3JlZW4ucGFsJywgbjEgPSAxMCksDQogIGJvcmRlciA9ICJCbGFjayIsDQogIGx3ZCA9IDAuMSwgDQogIG1hc2sgPSByZXBfY2FmZSwgDQogIGxlZ2VuZC52YWx1ZXMucm5kID0gLTMsDQogIGxlZ2VuZC50aXRsZS50eHQgPSAiUHJvZHVjY2nDs24iLA0KICBsZWdlbmQucG9zID0gInRvcHJpZ2h0IiwgDQogIGFkZD1UUlVFDQopDQojIGFubm90YXRpb24gb24gdGhlIG1hcA0KdGV4dCh4ID0gLTc2LjU3MzI4LCB5ID0gMi40MTEzODIsIGNleCA9IDAuNiwgYWRqID0gMCwgZm9udCA9IDMsICBsYWJlbHMgPSANCiAgICAgICAiRGlzdGFuY2UgZnVuY3Rpb246XG4tIHR5cGUgPSBleHBvbmVudGlhbFxuLSBiZXRhID0gMlxuLSBzcGFuID0gMjAga20iKQ0KIyBsYXlvdXQNCmxheW91dExheWVyKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgbGEgcHJvZHVjY2nDs24gZGUgY2FmZSBlbiBDYXVjYSIsDQogICAgICAgICAgICBzb3VyY2VzID0gIlNvdXJjZXM6IERBTkUgYW5kIE1BRFIsIDIwMTgiLA0KICAgICAgICAgICAgYXV0aG9yID0gIkpvaGFuIFJvamFzIiwNCiAgICAgICAgICAgIGZyYW1lID0gRkFMU0UsIG5vcnRoID0gRkFMU0UsIHRhYnRpdGxlID0gVFJVRSwgdGhlbWUgPSAiZ3JlZW4ucGFsIikNCiMgbm9ydGggYXJyb3cNCm5vcnRoKHBvcyA9ICJ0b3BsZWZ0IikNCmBgYA0KDQoNCg0KIyMgOC4gR3VhcmRhciBtYXBhcw0KUHJvZHV6Y2Ftb3Mgb3RybyBtYXBhIGRlIGxhIHByb2R1Y2Npw7NuIGRlIGNhZsOpIGVuIDIwMTguIEVzdGEgdmV6IHVzYXJlbW9zIHPDrW1ib2xvcyBwcm9wb3JjaW9uYWxlcyB5IG1hcGFzIGRlIGNvcm9wbGV0YXMuIExhIHNhbGlkYSBzZSBndWFyZGFyw6EgY29tbyB1biBhcmNoaXZvIC5wbmcuDQoNClByaW1lcm8sIGFsZ3VuYXMgb2JzZXJ2YWNpb25lczogLSBwcm9wU3ltYm9sc0Nob3JvTGF5ZXIgKCkgY3JlYSB1biBtYXBhIGRlIHPDrW1ib2xvcyBxdWUgc29uIHByb3BvcmNpb25hbGVzIGEgbG9zIHZhbG9yZXMgZGUgdW5hIHByaW1lcmEgdmFyaWFibGUgeSBjb2xvcmVhZG9zIHBhcmEgcmVmbGVqYXIgbGEgY2xhc2lmaWNhY2nDs24gZGUgdW5hIHNlZ3VuZGEgdmFyaWFibGUuIC0gU2UgdXRpbGl6YSB1bmEgY29tYmluYWNpw7NuIGRlIGFyZ3VtZW50b3MgcHJvcFN5bWJvbHNMYXllciAoKSB5IGNob3JvTGF5ZXIgKCkuDQoNCkVsIHNpZ3VpZW50ZSBmcmFnbWVudG8gbm8gbXVlc3RyYSB1biBtYXBhLiBFbiBzdSBsdWdhciwgZXNjcmliZSBlbCBtYXBhIGNvbiBlbCBub21icmUgZGUgYXJjaGl2byBjYWZlXzIwMTgucG5nIGVuIGVsIGRpcmVjdG9yaW8gZGUgdHJhYmFqby4NCg0KUG9yIGN1ZXN0aW9uZXMgZGUgdmlzdWFsaXphY2nDs24gdmFtb3MgYSBkaXZpZGlyIGxhIHByb2R1Y2Npw7NuIGRlIGNhZmUgZW4gQ2F1Y2EgZW4gZG9zIHBhcnRlcywgcGFyYSBlc3RvIHZhbW9zIGEgZGl2aWRpciBlc3RvcyBlbiBkb3MgZ3J1cG9zIGFwYXJ0aXIgZGUgbGEgbWVkaWEuDQpgYGB7cn0NCnN1bW1hcnkoY2FmZTIwMTgkVE9OX1BST0QpDQpgYGANCg0KYGBge3J9DQpjYWZlMjAxOCAlPiUgDQogIGZpbHRlcihZRUFSPT0yMDE4ICYgU1VCR1JVUE89PSJDQUZFIikgJT4lIA0KICBncm91cF9ieShNVU4sIENVTFRJVk8sQ09ELFRPTl9QUk9ELFJFTkQsIEhBX1NJRU1CUkEpICU+JQ0KICBzdW1tYXJpemUoc3VtX2Nvc2VjaGEgPSBzdW0oSEFfQ09TRUNIQSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGZpbHRlcihUT05fUFJPRD49MjAzNCkgJT4lDQogIGFycmFuZ2UoZGVzYyhzdW1fY29zZWNoYSkpIC0+IGNhZmUyMDE4Mg0KDQpjYWZlMjAxODINCmBgYA0KYGBge3J9DQpjYWZlMjAxOCAlPiUgDQogIGZpbHRlcihZRUFSPT0yMDE4ICYgU1VCR1JVUE89PSJDQUZFIikgJT4lIA0KICBncm91cF9ieShNVU4sIENVTFRJVk8sQ09ELFRPTl9QUk9ELFJFTkQsIEhBX1NJRU1CUkEpICU+JQ0KICBzdW1tYXJpemUoc3VtX2Nvc2VjaGEgPSBzdW0oSEFfQ09TRUNIQSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGZpbHRlcihUT05fUFJPRDwyMDM0KSAlPiUNCiAgYXJyYW5nZShkZXNjKHN1bV9jb3NlY2hhKSkgLT4gY2FmZTIwMTgyXzENCg0KY2FmZTIwMTgyXzENCmBgYA0KDQoNCg0KYGBge3J9DQpjYWZlX211bmljMiA9IGxlZnRfam9pbihtdW5pYywgY2FmZTIwMTgyLCBieT1jKCJNUElPX0NDREdPIj0iQ09EIikpDQpgYGANCmBgYHtyfQ0KY2FmZV9tdW5pYzJfMSA9IGxlZnRfam9pbihtdW5pYywgY2FmZTIwMTgyXzEsIGJ5PWMoIk1QSU9fQ0NER08iPSJDT0QiKSkNCmBgYA0KDQpgYGB7cn0NCnJlcF9jYWZlMiA8LSBzdF90cmFuc2Zvcm0oY2FmZV9tdW5pYzIsIGNycyA9IDMxMTYpDQpgYGANCmBgYHtyfQ0KcmVwX2NhZmUyXzEgPC0gc3RfdHJhbnNmb3JtKGNhZmVfbXVuaWMyXzEsIGNycyA9IDMxMTYpDQpgYGANCg0KDQpgYGB7cn0NCiMjIyBvcGVuIHRoZSBwbG90DQpwbmcoIkM6L1VzZXJzL3JvamFzL09uZURyaXZlL0VzY3JpdG9yaW8vUiBlc3R1ZGlvL0dlb21hdGljYS9pbmZvcm1lIGRvcy9jYWZlXzIwMTgtMi5wbmciLCB3aWR0aCA9IDIwNDgsIGhlaWdodCA9IDE1MjYpDQojIHNldCBtYXJnaW5zDQpvcGFyIDwtIHBhcihtYXIgPSBjKDAsMCw1LDUpKQ0KIyBQbG90IHRoZSBtdW5pY2lwYWxpdGllcw0KcGxvdChzdF9nZW9tZXRyeShyZXBfY2FmZTIpLCBjb2w9ImRhcmtzZWFncmVlbjMiLCBib3JkZXI9ImRhcmtzZWFncmVlbjQiLCAgDQogICAgIGJnID0gIndoaXRlIiwgbHdkID0gMC42KQ0KIyBQbG90IHN5bWJvbHMgd2l0aCBjaG9yb3BsZXRoIGNvbG9yYXRpb24NCnByb3BTeW1ib2xzQ2hvcm9MYXllcih4ID0gcmVwX2NhZmUyLCB2YXIgPSAiVE9OX1BST0QiLCB2YXIyID0gIlJFTkQiLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IGNhcnRvLnBhbChwYWwxID0gImdyZWVuLnBhbCIsIG4xID0gMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFsMiA9ICJyZWQucGFsIiwgbjIgPSAzKSwNCiAgICAgICAgICAgICAgICAgICAgICBpbmNoZXMgPSAwLjgsIG1ldGhvZCA9ICJxNiIsDQogICAgICAgICAgICAgICAgICAgICAgYm9yZGVyID0gImdyZXk1MCIsIGx3ZCA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRpdGxlLmNleCA9IDMsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhbHVlcy5jZXggPSAxLjAsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhci5wb3MgPSAicmlnaHQiLCANCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyMi5wb3MgPSAibGVmdCIsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhcjIudmFsdWVzLnJuZCA9IDIsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhcjIudGl0bGUudHh0ID0gIlJlbmRpbWllbnRvXG4oZW4gVG9uL0hhKSIsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhci50aXRsZS50eHQgPSAicHJvZHVjY2nDs24gZGUgY2FmZSAoMjAxOCkiLA0KICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC52YXIuc3R5bGUgPSAiZSIpDQojIHBsb3QgbGFiZWxzDQpsYWJlbExheWVyKA0KICB4ID0gcmVwX2NhZmUyLCANCiAgdHh0ID0gIk1VTiIsIA0KICBjb2w9ICJCbGFjayIsIA0KICBjZXggPSAxLjAsIA0KICBmb250ID0gNSwNCiAgaGFsbyA9IEZBTFNFLCANCiAgYmcgPSAid2hpdGUiLCANCiAgciA9IDAuMSwgDQogIG92ZXJsYXAgPSBGQUxTRSwgDQogIHNob3cubGluZXMgPSBGQUxTRQ0KKQ0KIyBsYXlvdXQNCmxheW91dExheWVyKHRpdGxlPSJQcm9kdWNjacOzbiB5IHJlbmRpbWllbnRvIG1heW9yIGEgbGEgbWVkaWEgZGUgY2Fmw6kgZW4gQ2F1Y2EsIDIwMTgiLA0KICAgICAgICAgICAgYXV0aG9yID0gIkpvaGFuIFJvamFzIiwgDQogICAgICAgICAgICBzb3VyY2VzID0gIlNvdXJjZXM6IE1BRFIgJiBEQU5FLCAyMDE4IiwgDQogICAgICAgICAgICAgdGFidGl0bGUgPSBGQUxTRSwgZnJhbWUgPSBUUlVFLHNjYWxlID0gImF1dG8iLCkNCiMgbm9ydGggYXJyb3cNCm5vcnRoKHBvcyA9ICJ0b3BsZWZ0IikNCiMNCnRpdGxlKG1haW49IlByb2R1Y2Npw7NuIHkgcmVuZGltaWVudG8gbWF5b3IgYSBsYSBtZWRpYSBkZSBjYWbDqSBlbiBDYXVjYSwgMjAxOCIsIGNleC5tYWluPTQsDQogICAgICBzdWI9ICJTb3VyY2U6IE1BRFIgJiBEQU5FLCAyMDE4IiwgY2V4LnN1Yj00KQ0KIw0KZ3JhdGljdWxlID0gVFJVRQ0KIw0KcGFyKG9wYXIpDQojIyMgY2xvc2UgdGhlIHBsb3QNCmRldi5vZmYoKQ0KYGBgDQpgYGB7cn0NCnBuZygiQzovVXNlcnMvcm9qYXMvT25lRHJpdmUvRXNjcml0b3Jpby9SIGVzdHVkaW8vR2VvbWF0aWNhL2luZm9ybWUgZG9zL2NhZmVfMjAxOC0yXzEucG5nIiwgd2lkdGggPSAyMDQ4LCBoZWlnaHQgPSAxNTI2KQ0KIyBzZXQgbWFyZ2lucw0Kb3BhciA8LSBwYXIobWFyID0gYygwLDAsNSw1KSkNCiMgUGxvdCB0aGUgbXVuaWNpcGFsaXRpZXMNCnBsb3Qoc3RfZ2VvbWV0cnkocmVwX2NhZmUyXzEpLCBjb2w9ImRhcmtzZWFncmVlbjMiLCBib3JkZXI9ImRhcmtzZWFncmVlbjQiLCAgDQogICAgIGJnID0gIndoaXRlIiwgbHdkID0gMC42KQ0KIyBQbG90IHN5bWJvbHMgd2l0aCBjaG9yb3BsZXRoIGNvbG9yYXRpb24NCnByb3BTeW1ib2xzQ2hvcm9MYXllcih4ID0gcmVwX2NhZmUyXzEsIHZhciA9ICJUT05fUFJPRCIsIHZhcjIgPSAiUkVORCIsDQogICAgICAgICAgICAgICAgICAgICAgY29sID0gY2FydG8ucGFsKHBhbDEgPSAiZ3JlZW4ucGFsIiwgbjEgPSAzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWwyID0gInJlZC5wYWwiLCBuMiA9IDMpLA0KICAgICAgICAgICAgICAgICAgICAgIGluY2hlcyA9IDAuOCwgbWV0aG9kID0gInE2IiwNCiAgICAgICAgICAgICAgICAgICAgICBib3JkZXIgPSAiZ3JleTUwIiwgbHdkID0gMSwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGl0bGUuY2V4ID0gMywNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFsdWVzLmNleCA9IDEuMCwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyLnBvcyA9ICJyaWdodCIsIA0KICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC52YXIyLnBvcyA9ICJsZWZ0IiwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyMi52YWx1ZXMucm5kID0gMiwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyMi50aXRsZS50eHQgPSAiUmVuZGltaWVudG9cbihlbiBUb24vSGEpIiwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyLnRpdGxlLnR4dCA9ICJwcm9kdWNjacOzbiBkZSBjYWZlICgyMDE4KSIsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhci5zdHlsZSA9ICJlIikNCiMgcGxvdCBsYWJlbHMNCmxhYmVsTGF5ZXIoDQogIHggPSByZXBfY2FmZTJfMSwgDQogIHR4dCA9ICJNVU4iLCANCiAgY29sPSAiQmxhY2siLCANCiAgY2V4ID0gMS4wLCANCiAgZm9udCA9IDUsDQogIGhhbG8gPSBGQUxTRSwgDQogIGJnID0gIndoaXRlIiwgDQogIHIgPSAwLjEsIA0KICBvdmVybGFwID0gRkFMU0UsIA0KICBzaG93LmxpbmVzID0gRkFMU0UNCikNCiMgbGF5b3V0DQpsYXlvdXRMYXllcih0aXRsZT0iUHJvZHVjY2nDs24geSByZW5kaW1pZW50byBtZW5vciBhIGxhIG1lZGlhIGRlIGNhZsOpIGVuIENhdWNhLCAyMDE4IiwNCiAgICAgICAgICAgIGF1dGhvciA9ICJKb2hhbiBSb2phcyIsIA0KICAgICAgICAgICAgc291cmNlcyA9ICJTb3VyY2VzOiBNQURSICYgREFORSwgMjAxOCIsIA0KICAgICAgICAgICAgIHRhYnRpdGxlID0gRkFMU0UsIGZyYW1lID0gVFJVRSxzY2FsZSA9ICJhdXRvIiwpDQojIG5vcnRoIGFycm93DQpub3J0aChwb3MgPSAidG9wbGVmdCIpDQojDQp0aXRsZShtYWluPSJQcm9kdWNjacOzbiB5IHJlbmRpbWllbnRvIG1lbm9yIGEgbGEgbWVkaWEgZGUgY2Fmw6kgZW4gQ2F1Y2EsIDIwMTgiLCBjZXgubWFpbj00LA0KICAgICAgc3ViPSAiU291cmNlOiBNQURSICYgREFORSwgMjAxOCIsIGNleC5zdWI9NSkNCiMNCmdyYXRpY3VsZSA9IFRSVUUNCiMNCnBhcihvcGFyKQ0KIyMjIGNsb3NlIHRoZSBwbG90DQpkZXYub2ZmKCkNCmBgYA0KDQpgYGB7cn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9yb2phcy9PbmVEcml2ZS9Fc2NyaXRvcmlvL1IgZXN0dWRpby9HZW9tYXRpY2EvaW5mb3JtZSBkb3MvY2FmZV8yMDE4LTIucG5nIikNCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9yb2phcy9PbmVEcml2ZS9Fc2NyaXRvcmlvL1IgZXN0dWRpby9HZW9tYXRpY2EvaW5mb3JtZSBkb3MvY2FmZV8yMDE4LTJfMS5wbmciKQ0KYGBgDQpBaG9yYSB2YW1vcyBhIHZlciBsYSBwcm9kdWNjacOzbiB5IMOhcmVhIGNvc2VjaGFkYSBkZSBjYWbDqSBlbiBDYXVjYSBlbiBlbCAyMDE4IGRlIGlndWFsIG1hbmVyYSBsbyB2YW1vcyBoYSBoYWNlciBlbiBkb3MgbWFwYXMgdW5vIG1heW9yIGEgbGEgbWVkaWEgeSBvdHJvIG1lbm9yIGEgbGEgbWVkaWEuDQpgYGB7cn0NCiMjIyBvcGVuIHRoZSBwbG90DQpwbmcoIkM6L1VzZXJzL3JvamFzL09uZURyaXZlL0VzY3JpdG9yaW8vUiBlc3R1ZGlvL0dlb21hdGljYS9pbmZvcm1lIGRvcy9jYWZlXzIwMThjLnBuZyIsIHdpZHRoID0gMjA0OCwgaGVpZ2h0ID0gMTUyNikNCiMgc2V0IG1hcmdpbnMNCm9wYXIgPC0gcGFyKG1hciA9IGMoMCwwLDUsNSkpDQojIFBsb3QgdGhlIG11bmljaXBhbGl0aWVzDQpwbG90KHN0X2dlb21ldHJ5KHJlcF9jYWZlMiksIGNvbD0iZGFya3NlYWdyZWVuMyIsIGJvcmRlcj0iZGFya3NlYWdyZWVuNCIsICANCiAgICAgYmcgPSAid2hpdGUiLCBsd2QgPSAwLjYpDQojIFBsb3Qgc3ltYm9scyB3aXRoIGNob3JvcGxldGggY29sb3JhdGlvbg0KcHJvcFN5bWJvbHNDaG9yb0xheWVyKHggPSByZXBfY2FmZTIsIHZhciA9ICJUT05fUFJPRCIsIHZhcjIgPSAic3VtX2Nvc2VjaGEiLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IGNhcnRvLnBhbChwYWwxID0gImJyb3duLnBhbCIsIG4xID0gMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFsMiA9ICJvcmFuZ2UucGFsIiwgbjIgPSAzKSwNCiAgICAgICAgICAgICAgICAgICAgICBpbmNoZXMgPSAwLjgsIG1ldGhvZCA9ICJxNiIsDQogICAgICAgICAgICAgICAgICAgICAgYm9yZGVyID0gImdyZXk1MCIsIGx3ZCA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRpdGxlLmNleCA9IDMsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhbHVlcy5jZXggPSAxLjAsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhci5wb3MgPSAicmlnaHQiLCANCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyMi5wb3MgPSAibGVmdCIsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhcjIudmFsdWVzLnJuZCA9IDIsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhcjIudGl0bGUudHh0ID0gIlJlbmRpbWllbnRvXG4oZW4gVG9uL0hhKSIsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnZhci50aXRsZS50eHQgPSAiw4FyZWEgY29zZWNoYWRhIGRlIGNhZmUgKDIwMTgpIiwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyLnN0eWxlID0gImUiKQ0KIyBwbG90IGxhYmVscw0KbGFiZWxMYXllcigNCiAgeCA9IHJlcF9jYWZlMiwgDQogIHR4dCA9ICJNVU4iLCANCiAgY29sPSAiQmxhY2siLCANCiAgY2V4ID0gMS4wLCANCiAgZm9udCA9IDUsDQogIGhhbG8gPSBGQUxTRSwgDQogIGJnID0gIndoaXRlIiwgDQogIHIgPSAwLjEsIA0KICBvdmVybGFwID0gRkFMU0UsIA0KICBzaG93LmxpbmVzID0gRkFMU0UNCikNCiMgbGF5b3V0DQpsYXlvdXRMYXllcih0aXRsZT0iUHJvZHVjY2nDs24geSDDoXJlYSBjb3NlY2hhZGEgbWF5b3IgYSBsYSBtZWRpYSBkZSBjYWbDqSBlbiBDYXVjYSwgMjAxOCIsDQogICAgICAgICAgICBhdXRob3IgPSAiSm9oYW4gUm9qYXMiLCANCiAgICAgICAgICAgIHNvdXJjZXMgPSAiU291cmNlczogTUFEUiAmIERBTkUsIDIwMTgiLCANCiAgICAgICAgICAgICB0YWJ0aXRsZSA9IEZBTFNFLCBmcmFtZSA9IFRSVUUsc2NhbGUgPSAiYXV0byIsKQ0KIyBub3J0aCBhcnJvdw0Kbm9ydGgocG9zID0gInRvcGxlZnQiKQ0KIw0KdGl0bGUobWFpbj0iUHJvZHVjY2nDs24geSDDoXJlYSBjb3NlY2hhZGEgbWF5b3IgYSBsYSBtZWRpYSBkZSBjYWbDqSBlbiBDYXVjYSwgMjAxOCIsIGNleC5tYWluPTQsDQogICAgICBzdWI9ICJTb3VyY2U6IE1BRFIgJiBEQU5FLCAyMDE4IiwgY2V4LnN1Yj00KQ0KIw0KZ3JhdGljdWxlID0gVFJVRQ0KIw0KcGFyKG9wYXIpDQojIyMgY2xvc2UgdGhlIHBsb3QNCmRldi5vZmYoKQ0KYGBgDQpgYGB7cn0NCiMjIyBvcGVuIHRoZSBwbG90DQpwbmcoIkM6L1VzZXJzL3JvamFzL09uZURyaXZlL0VzY3JpdG9yaW8vUiBlc3R1ZGlvL0dlb21hdGljYS9pbmZvcm1lIGRvcy9jYWZlXzIwMThjMi5wbmciLCB3aWR0aCA9IDIwNDgsIGhlaWdodCA9IDE1MjYpDQojIHNldCBtYXJnaW5zDQpvcGFyIDwtIHBhcihtYXIgPSBjKDAsMCw1LDUpKQ0KIyBQbG90IHRoZSBtdW5pY2lwYWxpdGllcw0KcGxvdChzdF9nZW9tZXRyeShyZXBfY2FmZTJfMSksIGNvbD0iZGFya3NlYWdyZWVuMyIsIGJvcmRlcj0iZGFya3NlYWdyZWVuNCIsICANCiAgICAgYmcgPSAid2hpdGUiLCBsd2QgPSAwLjYpDQojIFBsb3Qgc3ltYm9scyB3aXRoIGNob3JvcGxldGggY29sb3JhdGlvbg0KcHJvcFN5bWJvbHNDaG9yb0xheWVyKHggPSByZXBfY2FmZTJfMSwgdmFyID0gIlRPTl9QUk9EIiwgdmFyMiA9ICJzdW1fY29zZWNoYSIsDQogICAgICAgICAgICAgICAgICAgICAgY29sID0gY2FydG8ucGFsKHBhbDEgPSAiYnJvd24ucGFsIiwgbjEgPSAzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWwyID0gIm9yYW5nZS5wYWwiLCBuMiA9IDMpLA0KICAgICAgICAgICAgICAgICAgICAgIGluY2hlcyA9IDAuOCwgbWV0aG9kID0gInE2IiwNCiAgICAgICAgICAgICAgICAgICAgICBib3JkZXIgPSAiZ3JleTUwIiwgbHdkID0gMSwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGl0bGUuY2V4ID0gMywNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFsdWVzLmNleCA9IDEuMCwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyLnBvcyA9ICJyaWdodCIsIA0KICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC52YXIyLnBvcyA9ICJsZWZ0IiwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyMi52YWx1ZXMucm5kID0gMiwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyMi50aXRsZS50eHQgPSAiUmVuZGltaWVudG9cbihlbiBUb24vSGEpIiwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyLnRpdGxlLnR4dCA9ICLDgXJlYSBjb3NlY2hhZGEgZGUgY2FmZSAoMjAxOCkiLA0KICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC52YXIuc3R5bGUgPSAiZSIpDQojIHBsb3QgbGFiZWxzDQpsYWJlbExheWVyKA0KICB4ID0gcmVwX2NhZmUyXzEsIA0KICB0eHQgPSAiTVVOIiwgDQogIGNvbD0gIkJsYWNrIiwgDQogIGNleCA9IDEuMCwgDQogIGZvbnQgPSA1LA0KICBoYWxvID0gRkFMU0UsIA0KICBiZyA9ICJ3aGl0ZSIsIA0KICByID0gMC4xLCANCiAgb3ZlcmxhcCA9IEZBTFNFLCANCiAgc2hvdy5saW5lcyA9IEZBTFNFDQopDQojIGxheW91dA0KbGF5b3V0TGF5ZXIodGl0bGU9IlByb2R1Y2Npw7NuIHkgw6FyZWEgY29zZWNoYWRhIG1lbm9yIGEgbGEgbWVkaWEgZGUgY2Fmw6kgZW4gQ2F1Y2EsIDIwMTgiLA0KICAgICAgICAgICAgYXV0aG9yID0gIkpvaGFuIFJvamFzIiwgDQogICAgICAgICAgICBzb3VyY2VzID0gIlNvdXJjZXM6IE1BRFIgJiBEQU5FLCAyMDE4IiwgDQogICAgICAgICAgICAgdGFidGl0bGUgPSBGQUxTRSwgZnJhbWUgPSBUUlVFLHNjYWxlID0gImF1dG8iLCkNCiMgbm9ydGggYXJyb3cNCm5vcnRoKHBvcyA9ICJ0b3BsZWZ0IikNCiMNCnRpdGxlKG1haW49IlByb2R1Y2Npw7NuIHkgw6FyZWEgY29zZWNoYWRhIG1lbm9yIGEgbGEgbWVkaWEgZGUgY2Fmw6kgZW4gQ2F1Y2EsIDIwMTgiLCBjZXgubWFpbj00LA0KICAgICAgc3ViPSAiU291cmNlOiBNQURSICYgREFORSwgMjAxOCIsIGNleC5zdWI9NCkNCiMNCmdyYXRpY3VsZSA9IFRSVUUNCiMNCnBhcihvcGFyKQ0KIyMjIGNsb3NlIHRoZSBwbG90DQpkZXYub2ZmKCkNCmBgYA0KYGBge3J9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiQzovVXNlcnMvcm9qYXMvT25lRHJpdmUvRXNjcml0b3Jpby9SIGVzdHVkaW8vR2VvbWF0aWNhL2luZm9ybWUgZG9zL2NhZmVfMjAxOGMucG5nIikNCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9yb2phcy9PbmVEcml2ZS9Fc2NyaXRvcmlvL1IgZXN0dWRpby9HZW9tYXRpY2EvaW5mb3JtZSBkb3MvY2FmZV8yMDE4YzIucG5nIikNCmBgYA0KQWhvcmEgdmFtb3MgYSB2ZXIgaGFjZXIgdW4gbWFwYSBjbG9yb3BsZXRpY28gY29uIGVsIMOhcmVhIGRlIHNpZW1icmEgZW4gQ2F1Y2EgcGFyYSAyMDE4DQpgYGB7cn0NCmNhZmUyMDE4ICU+JSANCiAgZmlsdGVyKFlFQVI9PTIwMTggJiBTVUJHUlVQTz09IkNBRkUiKSAlPiUgDQogIGdyb3VwX2J5KE1VTiwgQ1VMVElWTyxDT0QsVE9OX1BST0QsUkVORCwgSEFfU0lFTUJSQSkgJT4lDQogIHN1bW1hcml6ZShzdW1fc2llbWJyYSA9IHN1bShIQV9TSUVNQlJBLCBuYS5ybSA9IFRSVUUpKSAtPiBjYWZlMjAxOHNpDQoNCmNhZmUyMDE4c2kNCmBgYA0KDQoNCg0KYGBge3J9DQpjYWZlX211bmljc2kgPSBsZWZ0X2pvaW4obXVuaWMsIGNhZmUyMDE4c2ksIGJ5PWMoIk1QSU9fQ0NER08iPSJDT0QiKSkNCmBgYA0KDQoNCmBgYHtyfQ0KcmVwX2NhZmVzaSA8LSBzdF90cmFuc2Zvcm0oY2FmZV9tdW5pYzIsIGNycyA9IDMxMTYpDQpgYGANCg0KDQoNCmBgYHtyfQ0KbGlicmFyeShzZikNCmxpYnJhcnkoY2FydG9ncmFwaHkpDQojIHNldCBtYXJnaW5zDQpvcGFyIDwtIHBhcihtYXIgPSBjKDAsMCwxLjIsMCkpDQojIHNldCBmaWd1cmUgYmFja2dyb3VuZCBjb2xvcg0KcGFyKGJnPSJncmV5MjUiKQ0KIyBwbG90IG11bmljaXBhbGl0aWVzDQpwbG90KHN0X2dlb21ldHJ5KHJlcF9jYWZlc2kpLCBjb2wgPSAiI2U0ZTlkZSIsIGJvcmRlciA9ICJCbGFjayIsIA0KICAgICBiZyA9ICJncmV5NzUiLCBsd2QgPSAwLjUpDQojIHBsb3QgTkJJDQpjaG9yb0xheWVyKA0KICB4ID0gcmVwX2NhZmVzaSwgDQogIHZhciA9ICJIQV9TSUVNQlJBIiwNCiAgbWV0aG9kID0gImdlb20iLA0KICBuY2xhc3M9NywNCiAgY29sID0gY2FydG8ucGFsKHBhbDEgPSAid2luZS5wYWwiLCBuMSA9IDcpLA0KICBib3JkZXIgPSAiQmxhY2siLCANCiAgbHdkID0gMC41LA0KICBsZWdlbmQucG9zID0gInRvcHJpZ2h0IiwNCiAgbGVnZW5kLnRpdGxlLnR4dCA9ICLDgVJFQSBERSBTSUVNQlJBIiwNCiAgYWRkID0gVFJVRQ0KKSANCiMgcGxvdCBsYWJlbHMNCmxhYmVsTGF5ZXIoDQogIHggPXJlcF9jYWZlc2ksIA0KICB0eHQgPSAiTVVOIiwgDQogIGNvbD0gIkJsYWNrIiwgDQogIGNleCA9IDAuNCwgDQogIGZvbnQgPSA0LA0KICBvdmVybGFwID0gRkFMU0UsIA0KICBzaG93LmxpbmVzID0gRkFMU0UNCikNCiMgbWFwIGxheW91dA0KbGF5b3V0TGF5ZXIoDQogIHRpdGxlID0gIsOBcmVhIGRlIHNpZW1icmEgZW4gbG9zIG11bmljaXBpb3MgZGUgQ2F1Y2EiLCANCiAgc291cmNlcyA9ICJTb3VyY2U6IERBTkUsIDIwMTgiLCAgDQogIGF1dGhvciA9ICJKb2hhbiBSb2phcyIsIA0KICBmcmFtZSA9IFRSVUUsDQogIG5vcnRoID0gVFJVRSwgDQogIHRhYnRpdGxlID0gVFJVRSwgDQogIHRoZW1lID0gInRhdXBlLnBhbCIpDQpgYGANCmFob3JhIG1pcmVtb3MgbGEgZGlzdHJpYnVjacOzbiBkZWwgw6FyZWEgZGUgc2llbWJyYSBjb24gdW4gbWFwYSBpc29wbGV0aWNvLiANCg0KYGBge3J9DQojIHNldCBtYXJnaW5zDQpvcGFyIDwtIHBhcihtYXIgPSBjKDAsMCwxLjIsMCkpDQojIHBsb3QgbXVuaWNpcGFsaXRpZXMgKG9ubHkgdGhlIGJhY2tncm91bmcgY29sb3IgaXMgcGxvdHRlZCkNCnBsb3Qoc3RfZ2VvbWV0cnkocmVwX2NhZmVzaSksIGNvbCA9IE5BLCBib3JkZXIgPSAiQmxhY2siLCBiZyA9ICJncmV5NzUiKQ0KIyBwbG90IGlzb3BsZXRoIG1hcA0Kc21vb3RoTGF5ZXIoDQogIHggPSByZXBfY2FmZXNpLCANCiAgdmFyID0gJ0hBX1NJRU1CUkEnLA0KICB0eXBlZmN0ID0gImV4cG9uZW50aWFsIiwNCiAgc3BhbiA9IDg0MjgsDQogIGJldGEgPSAyLA0KICBuY2xhc3MgPSAxMCwNCiAgY29sID0gY2FydG8ucGFsKHBhbDEgPSAnZ3JlZW4ucGFsJywgbjEgPSAxMCksDQogIGJvcmRlciA9ICJCbGFjayIsDQogIGx3ZCA9IDAuMSwgDQogIG1hc2sgPSByZXBfY2FmZSwgDQogIGxlZ2VuZC52YWx1ZXMucm5kID0gLTMsDQogIGxlZ2VuZC50aXRsZS50eHQgPSAiw4FyZWEgZGUgc2llbWJyYSIsDQogIGxlZ2VuZC5wb3MgPSAidG9wcmlnaHQiLCANCiAgYWRkPVRSVUUNCikNCiMgYW5ub3RhdGlvbiBvbiB0aGUgbWFwDQp0ZXh0KHggPSAtNzYuNTczMjgsIHkgPSAyLjQxMTM4MiwgY2V4ID0gMC42LCBhZGogPSAwLCBmb250ID0gMywgIGxhYmVscyA9IA0KICAgICAgICJEaXN0YW5jZSBmdW5jdGlvbjpcbi0gdHlwZSA9IGV4cG9uZW50aWFsXG4tIGJldGEgPSAyXG4tIHNwYW4gPSAyMCBrbSIpDQojIGxheW91dA0KbGF5b3V0TGF5ZXIodGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZWwgw6FyZWEgZGUgc2llbWJyYSBkZSBjYWZlIGVuIENhdWNhIiwNCiAgICAgICAgICAgIHNvdXJjZXMgPSAiU291cmNlczogREFORSBhbmQgTUFEUiwgMjAxOCIsDQogICAgICAgICAgICBhdXRob3IgPSAiSm9oYW4gUm9qYXMiLA0KICAgICAgICAgICAgZnJhbWUgPSBGQUxTRSwgbm9ydGggPSBGQUxTRSwgdGFidGl0bGUgPSBUUlVFLCB0aGVtZSA9ICJncmVlbi5wYWwiKQ0KIyBub3J0aCBhcnJvdw0Kbm9ydGgocG9zID0gInRvcGxlZnQiKQ0KYGBgDQpQb3IgdWx0aW1vIHZhbW9zIGEgdmVyIGNvbW8gc2UgcmVsYWNpb25hIGVsIG5iaSB5IGxhIHByb2R1Y2Npw7NuIGVuIENhdWNhIHBhcmEgMjAxOCwgcHJpbWVybyB1bmFtb3MgbG9zIGRhdG9zIHF1ZSBuZWNlc2l0YW1vcy4NCmBgYHtyfQ0KY2FmZV9tdW5pY19uYmkgPSBsZWZ0X2pvaW4obmJpX211bmljLCBjYWZlMjAxOHNpLCBieT1jKCJNUElPX0NDREdPIj0iQ09EIikpDQpgYGANCmBgYHtyfQ0KY2FmZV9tdW5pY19uYmkNCmBgYA0KYGBge3J9DQpjYWZlX211bmljX25iaTIgPSBzdF9qb2luKG11bmljLCBjYWZlX211bmljX25iaSwgYnk9YygiTVBJT19DQ0RHTyIpKQ0KYGBgDQpBaG9yYSB2YW1vcyBhIGNyZWFyIHVuYSBlc2NhbGEgKGFsdGEsIG1lZGlhLCBiYWphKSBwYXJhIGxhIHByb2R1Y2Npw7NuIGRlIGNhZmUgZW4gMjAxOCwgcGFyYSBlc3RvIHVzYXJlbW9zIGxvcyBkYXRvcyBkZSBsb3MgY3VhcnRpbGVzIGRlIGVzdGEgdmFyaWFibGUuDQpgYGB7cn0NCnN1bW1hcnkoY2FmZV9tdW5pY19uYmkyJFRPTl9QUk9EKQ0KYGBgDQpgYGB7cn0NCmNhZmVfbmJpX211bmljXzIgPC0gZHBseXI6Om11dGF0ZShjYWZlX211bmljX25iaSwgUFJPRCA9IGlmZWxzZShUT05fUFJPRD40NjM1LCAiQWx0YSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKFRPTl9QUk9EID4gMzUyOSwgIk1lZGlhIiwgIkJhamEiKSkpDQpgYGANCg0KYGBge3J9DQpjYWZlX25iaV9tdW5pY18yDQpgYGANCmBgYHtyfQ0KcG9icmVjYWZlIDwtIHN0X3RyYW5zZm9ybShjYWZlX25iaV9tdW5pY18yLCBjcnMgPSAzMTE2KQ0KYGBgDQoNCkFob3JhIGhhZ2Ftb3MgYWwgbWFwYSANCmBgYHtyfQ0KbGlicmFyeShzZikNCmxpYnJhcnkoY2FydG9ncmFwaHkpDQojIHNldCBtYXJnaW5zDQpvcGFyIDwtIHBhcihtYXIgPSBjKDAsMCwxLjIsMCkpDQojIFBsb3QgdGhlIG11bmljaXBhbGl0aWVzDQpwbG90KHN0X2dlb21ldHJ5KHBvYnJlY2FmZSksIGNvbD0iI0NEODUzRiIsIGJvcmRlcj0iIzAwMDAwMCIsIGJnID0gIiNhYWQzZGYiLCANCiAgICAgbHdkID0gMC41KQ0KIyBQbG90IHN5bWJvbHMgd2l0aCBjaG9yb3BsZXRoIGNvbG9yYXRpb24NCnByb3BTeW1ib2xzVHlwb0xheWVyKA0KICB4ID0gcG9icmVjYWZlLCANCiAgdmFyID0gIk5CSSIsIA0KICBpbmNoZXMgPSAwLjMsDQogIHN5bWJvbHMgPSAic3F1YXJlIiwNCiAgYm9yZGVyID0gIkJsYWNrIiwNCiAgbHdkID0gLjUsDQogIGxlZ2VuZC52YXIucG9zID0gYyg4NDU4NzIuOSwgNzU5ODc1LiksIA0KICBsZWdlbmQudmFyLnRpdGxlLnR4dCA9ICJOQkkiLA0KICB2YXIyID0gIlBST0QiLA0KICBsZWdlbmQudmFyMi52YWx1ZXMub3JkZXIgPSBjKCJBbHRhIiwgIk1lZGlhIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJhamEiKSwNCiAgY29sID0gY2FydG8ucGFsKHBhbDEgPSAib3JhbmdlLnBhbCIsIG4xID0gMyksDQogIGxlZ2VuZC52YXIyLnBvcyA9IGMoODQ1ODcyLjkgLCA2NDk4NzUuNiksIA0KICBsZWdlbmQudmFyMi50aXRsZS50eHQgPSAiUHJvZHVjY2nDs24iDQopIA0KbGFiZWxMYXllcigNCiAgeCA9cG9icmVjYWZlLCANCiAgdHh0ID0gIk1QSU9fQ05NQlIiLCANCiAgY29sPSAiQmxhY2siLCANCiAgY2V4ID0gMC40LCANCiAgZm9udCA9IDQsDQogIG92ZXJsYXAgPSBGQUxTRSwgDQogIHNob3cubGluZXMgPSBGQUxTRSkNCiMgbGF5b3V0DQpsYXlvdXRMYXllcih0aXRsZT0iRGlzdHJpYnVjacOzbiBkZSBOQkkgeSBwcm9kdWNjacOzbiBkZSBjYWZlIGVuIENhdWNhIiwgDQogICAgICAgICAgICBhdXRob3IgPSAiSm9oYW4gUm9qYXMiLCANCiAgICAgICAgICAgIHNvdXJjZXMgPSAiU291cmNlOiBEQU5FICYgTUFEUiwgMjAxOCIsIA0KICAgICAgICAgICAgc2NhbGUgPSAxLCB0YWJ0aXRsZSA9IFRSVUUsIGZyYW1lID0gVFJVRSkNCiMgbm9ydGggYXJyb3cNCm5vcnRoKHBvcyA9ICJ0b3BsZWZ0IikNCmBgYA0KYGBge3J9DQpzZXNzaW9uSW5mbygpDQpgYGANCg0KDQoNCg0KDQo=