Ana María Montaño Hernández

Mayo 16/ 2020

1. Introducción.

Según Víctor Olaya, un mapa es el medio más adecuado para transmitir información geográfica de manera visual, y con el objetivo de describir relaciones espaciales. Como menciona Olaya, para realizar correctamente un mapa, se deben seguir cuatro etapas importantes: recolectar los datos, manipular los datos para diseñar y construir el mapa, visualizarlo y por último interpretar la información visual que se obtiene. Lo anterior, es de gran importancia, ya que nos permite cumplir con el objetivo de la cartografía que es la representación o abstracción simbólica de un fenómeno en particular, para entender cómo ocurre y sus relaciones espaciales. En función del tipo de información que brinda, los mapas pueden ser topográficos o temáticos. En cuanto a la cartografía temática esta se centra en representar una variable espacial específica, la cual puede ser de cualquier temática, excluyendo los temas topográficos. Sin embargo, la cartografía temática debe apoyarse en la cartografía base para ubicar en un contexto geográfico la variable representada, permitiendo la comprensión de su comportamiento. Por otra parte, es necesario desarrollar la capacidad de crear un mapa y saber escoger qué tipo de mapa es el más adecuado conforme la información o variable que se desea ilustrar, así como la selección correcta de símbolos, leyendas, colores, escala, proyección, datos, a utilizar teniendo en cuenta el qué y a quién está dirigido dicho mapa. Por lo tanto, este cuaderno de R tiene como objetivo ilustrar cartografía temática para el departamento de Norte de Santander, utilizando datos como NBI (Necesidades básicas insatisfechas) y estadísticas agrícolas del departamento. Se van a ilustrar distintos tipos de mapas temáticos, como lo son: mapa de coropletas, isopletas, de símbolos proporcionales, y de etiquetas.

2. Cartografía temática.

Según Amanda Briney, un mapa temático enfatiza en un tema específico, como la distribución promedio de lluvia en un área o la densidad de población en un municipio. Son diferentes 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 tener en cuenta al diseñar mapas temáticos es la audiencia del mapa, lo 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 politólogo, 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 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”. Otro aspecto importante que menciona Víctor Olaya, es que un mapa temático se compone de dos partes principales:

Una capa específica con la información temática: Esta contiene la información principal del mapa, representando la variable espacial sobre la que se construye este.

Un mapa base:Este otorga una localización geográfica a lo que se referencia la información temática. Este mapa va a ayudar a los elementos de la componente temática a transmitir mejor la información que contienen. Cabe mencionar que la cartografía temática es la que con mayor frecuencia se genera mediante el uso de un SIG, y se centra principalmente en la representación de valores y atributos. Briney resume varias técnicas de mapeo temático que se usan con mayor frecuencia: En esta parte se utilizaron imágenes para mostrar mejor a qué se refiere cada tipo de mapa, pero posteriormente se explica como hacer un mapa temático en R, para que podamos realizar nuestras propias creaciones.

2.1 Mapa de coropleta:

Es un mapa que retrata los datos cuantitativos como el color y puede mostrar la densidad, el porcentaje, el valor promedio o la 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. Además, según Olaya los mapas de coropletas son utilizados para representar la información geográfica en un SIG. En un mapa de coropletas se tiene una serie de áreas definidas, cada una de las cuales posee un valor de una variable. Este valor de la variable afecta a toda el área y es el que se representa por medio de alguna variable visual, normalmente el color a través de su componente valor. Las zonas definidas por cada área tienen un significado arbitrario, no relacionado con la variable asociada.

A continuación se muestra un ejemplo de mapa de coropletas para la población indígena por municipio, tomado del DANE 2005.

Población indígena por municipio

Población indígena por municipio

En este link se pueden encontrar más ejemplos de mapas de coropletas.DANE

2.2.Mapa de símbolos proporcionales o graduados.

Un mapa de símbolos proporcionales representa variables cuantitativas a través de símbolos cuyo tamaño esta en relación con el valor a representar de dicha variable. Se usan para representar datos asociados con ubicaciones, como ciudades. Los datos se muestran en estos mapas con símbolos de tamaño proporcional para mostrar las diferencias en las ocurrencias. Los círculos se usan con mayor frecuencia, pero los cuadrados y otras formas geométricas también son adecuados. La forma más común de cambiar el tamaño de estos símbolos es hacer que sus áreas sean proporcionales a los valores que se representarán mediante el software de mapeo o dibujo.

Símbolos proporcionales empleados en este tipo de mapas

Símbolos proporcionales empleados en este tipo de mapas

Un tema actual que nos permite evidenciar claramente este tipo de mapa son los casos de Covid-19 confirmados en el país. A continuación, se muestra este ejemplo que realizó el TIEMPO

Covid-19 en Colombia

Covid-19 en Colombia

2.3. Mapa isarítmico o de contorno.

Los mapas de isolíneas son unos de los más usados para la representación de información cuantitativa, en particular cuando se trata de variables continuas. Se utiliza habitualmente para representar campos escalares y constituye una forma muy efectiva de incorporar esta información en un mapa, ya que puede combinarse con otros tipos de mapas y de información, debido a que, al representarse únicamente mediante líneas, permite la presencia de otros elementos dentro del mapa sin resultar obstrusiva. Un mapa de isolíneas está formado por un conjunto de líneas, cada una de las cuales une puntos que presentan el mismo valor de la variable. Estas líneas no pueden cruzarse, ya que ello significaría que en un punto se presentan dos valores Estos mapas también pueden mostrar valores tridimensionales, como la elevación, en mapas topográficos. En general, 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 isolínea. Por ejemplo, en elevación, si la isolina es de 500 pies, entonces un lado debe ser más alto que 500 pies y un lado debe ser más bajo.

A continuación, se muestra un ejemplo de este tipo de mapas tomado de la lectura de Victor Olaya.El mapa y la comunicación cartográfica

Ejemplo mapa isolíneas

Ejemplo mapa isolíneas

2.4. Mapa de puntos.

Es un mapa 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. A continuación, se muestra un ejemplo de este tipo de mapas tomado de la lectura de Victor Olaya.El mapa y la comunicación cartográfica

Ejemplo mapa de puntos

Ejemplo mapa de puntos

3. Datos.

Para este cuaderno se van a utilizar los datos sobre Necesidades Básicas Insatisfechas (NBI). Pero primero es necesario explicar a qué se refiere NBI. Según el DANE, la metodología de NBI busca determinar, con ayuda de algunos indicadores simples, si las necesidades básicas de la población se encuentran cubiertas. Los grupos que no alcancen un umbral mínimo fijado, son clasificados como pobres. Por lo tanto, la metodología de las NBI toma en cuenta si los hogares han satisfecho la serie de necesidades establecidas, considerando pobres a aquellos que no lo han logrado. Los indicadores simples seleccionados, son: Viviendas inadecuadas, Viviendas con hacinamiento crítico, Viviendas con servicios inadecuados, Viviendas con alta dependencia económica, Viviendas con niños en edad escolar que no asisten a la escuela. La medida de la pobreza por el método de Necesidades Básicas Insatisfechas (NBI) ha venido siendo utilizada para propósitos de diagnóstico social. Teniendo en cuenta que la pobreza es un fenómeno multidimensional y complejo que no puede ser captado en su totalidad por una sola medida, se puede afirmar que la medida de NBI es complementaria a la de línea de pobreza y no tiene como pretensión sustituirla, ni servir de aproximación a los resultados provistos por ella. Su campo de evaluación es el de los bienes y servicios requeridos para la satisfacción de necesidades básicas y no el de los ingresos.

Adicionalmente, cuanto más alto sea el número del NBI, mayores necesidades sufre la población en estudio y más grave será la problemática de dicho municipio.

Por otra parte, los mapas temáticos son útiles para transmitir información demográfica. Se pueden explorar varios mapas temáticos de DANE utilizando este enlace.DANE Anteriormente, se descargó el archivo NBI, en formato .xlsx, a mi computador. Luego, se utilizó Excel para eliminar datos de municipios no ubicados dentro del Departamento de Norte de Santander. También “se limpiaron” los datos, es decir, se eliminaron varias filas con imágenes institucionales o sin información. Estas filas se ubicaron tanto al principio como al final del archivo original. Se mantienen las columnas que se refieren a todo el municipio (es decir, se eliminaron las columnas correspondientes a “cabecera” y “zona rural”). Luego, se guardaron los datos resultantes, correspondientes solo a municipios de Norte de Santander como CNPV-2018-NBI.xlsx. Luego, se guardó el archivo en la carpeta del computador que se llama Intro-to-R.

4. Preparación.

Primero, se limpia la memoria

rm(list = ls())

Ahora, se instalan y se cargan las librerías que necesitamos.

library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages --------------------------------------- tidyverse 1.3.0 --
v ggplot2 3.3.0     v purrr   0.3.3
v tibble  2.1.3     v dplyr   0.8.4
v tidyr   1.0.2     v stringr 1.4.0
v readr   1.3.1     v forcats 0.5.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x tidyr::extract() masks raster::extract()
x dplyr::filter()  masks stats::filter()
x dplyr::lag()     masks stats::lag()
x dplyr::select()  masks raster::select()
library(readxl)
library(rgeos)
rgeos version: 0.5-2, (SVN revision 621)
 GEOS runtime version: 3.6.1-CAPI-1.10.1 
 Linking to sp version: 1.4-1 
 Polygon checking: TRUE 
library(raster)
library(sf)
Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3
library(cartography)

5. Leer datos de NBI

Primero, se debe leer el archivo que contiene las estadísticas municipales agropecuarias para el departamento de Norte de Santander.

nbi <- read_excel("C:/Users/user/Documents/Intro_to_R/CNPV-2018-NBI.xlsx")

Veamos los atributos de los datos:

head(nbi)

Ahora, se va a ver cuál es el municipio con el mayor porcentaje de NBI:

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

max_nbi

También, encontrar cuál es el municipio con menor porcentaje de NBI:

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

min_nbi

Estos datos de máximo y mínimo, nos permiten saber que los municipios de A continuación, se van a ordenar los municipios por NBI en orden descendente:

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

desc_nbi

6. Unir datos de NBI a municipios.

Ya se tienen descargados los municipios de Norte de Santander. Se van a leer estos datos usando la librería sf:

munic <- st_read("C:/Users/user/Documents/Norte de Santander/54_NORTE DE SANTANDER/ADMINISTRATIVO/MGN_MPIO_POLITICO.shp")
Reading layer `MGN_MPIO_POLITICO' from data source `C:\Users\user\Documents\Norte de Santander\54_NORTE DE SANTANDER\ADMINISTRATIVO\MGN_MPIO_POLITICO.shp' using driver `ESRI Shapefile'
Simple feature collection with 40 features and 9 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -73.63379 ymin: 6.872201 xmax: -72.04761 ymax: 9.290847
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs

Miremos qué hay dentro del atributo MPIO_CCDGO y MPIO_CNMBR:

head(munic$MPIO_CCDGO)
[1] 54001 54003 54051 54099 54109 54125
40 Levels: 54001 54003 54051 54099 54109 54125 54128 54172 ... 54874
head(munic$MPIO_CNMBR)
[1] CÚCUTA     ABREGO     ARBOLEDAS  BOCHALEMA  BUCARASICA CÁCOTA    
40 Levels: ABREGO ARBOLEDAS BOCHALEMA BUCARASICA CÁCHIRA ... VILLA DEL ROSARIO

Para realizar la unión entre los municipios y los datos de NBI, se va a utilizar la función left_join.

nbi_munic = left_join(munic, nbi,  by= c("MPIO_CCDGO"="CODIGO"))
Column `MPIO_CCDGO`/`CODIGO` joining factor and character vector, coercing into character vector
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:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -73.35555 ymin: 7.18928 xmax: -72.34632 ymax: 8.431296
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs
   MUNICIPIO MPIO_CCDGO      NBI                       geometry
1     CÚCUTA      54001 13.68850 MULTIPOLYGON (((-72.4778 8....
2     ABREGO      54003 27.69108 MULTIPOLYGON (((-73.01687 8...
3  ARBOLEDAS      54051 29.88151 MULTIPOLYGON (((-72.73134 7...
4  BOCHALEMA      54099 15.98952 MULTIPOLYGON (((-72.60265 7...
5 BUCARASICA      54109 36.63261 MULTIPOLYGON (((-72.95019 8...
6     CÁCOTA      54125 24.01763 MULTIPOLYGON (((-72.62101 7...

Ahora, se van a reproyectar los municipios:

nbi_munic_new <- st_transform(nbi_munic, crs = 3116)

7. Ejemplos de mapas temáticos.

Para realizar los mapas temáticos se va a utilizar la librería cartography que tiene como objetivo obtener mapas temáticos con la calidad visual de los que se construyen en un software de mapeo o en un SIG. Esta librería de cartography usa objetos sf o sp para producir los gráficos base. El formato preferido para los objetos espaciales es Sf.

7.1. Mapa base de OpenStreetMap y símbolos proporcionales.

Las funciones getTiles() y tilesLayer() descargan y muestran los mosaicos de OpenStreetMap. La función propSymbolsLayer() muestra símbolos con áreas proporcionales a una variable cuantitativa, como las NBI. Existen varios símbolos disponibles como círculos, cuadrados y barras. El argumento pulgadas (inches) se utiliza para personalizar los tamaños de los símbolos.

mun.osm <- getTiles(
  x= nbi_munic_new,
  type = "OpenStreetMap",
  zoom = 8,
  cachedir = TRUE,
  crop = FALSE
)
opar <- par(mar = c(0,0,1.2,0))
tilesLayer(x = mun.osm)
plot(st_geometry(nbi_munic_new), col = NA, border = "grey", add = TRUE)
propSymbolsLayer(
  x = nbi_munic_new,
  var = "NBI",
  inches = 0.15,
  col = "brown4",
  legend.pos = "topright",
  legend.title.txt = "Total NBI"
  )

layoutLayer(title = "Distribución de NBI en Norte de Santander",
            sources = "Fuentes: DANE, 2018/n© OpenStreetMap",
            author = "Ana María Montaño",
            frame = TRUE, north = FALSE, tabtitle = TRUE)

north(pos = "topleft")

Gracias al mapa anterior, se puede saber cuánto es el NBI en cada municipio, debido al tamaño del círculo. En este caso, el mayor NBI total es de 50, que corresponde al círculo de mayor tamaño y al municipio de El Tarra, mientras que el círculo de menor tamaño presenta un NBI de 9, que corresponde al municipio de Pamplona. Estos símbolos también nos permiten hacer un análisis rápido, de cómo están distribuidas las necesidades básicas insatisfechas en el departamento de Norte de Santander, y saber de ésta manera como orientar las soluciones a estas necesidades.

Ahora, se va a realizar el mismo mapa, pero experimentando un poco con el color, el tamaño de los círculos (símbolos), las márgenes y el color del borde del departamento.

mun.osm <- getTiles(
  x= nbi_munic_new,
  type = "OpenStreetMap",
  zoom = 8,
  cachedir = TRUE,
  crop = FALSE
)
opar <- par(mar = c(2,3,2.5,1))
tilesLayer(x = mun.osm)
plot(st_geometry(nbi_munic_new), col = NA, border = "black", add = TRUE)
propSymbolsLayer(
  x = nbi_munic_new,
  var = "NBI",
  inches = 0.10,
  col = "#A6CAE0",
  legend.pos = "topright",
  legend.title.txt = "Total NBI"
  )

layoutLayer(title = "Distribución de NBI en Norte de Santander",
            sources = "Fuentes: DANE, 2018/n© OpenStreetMap",
            author = "Ana María Montaño",
            frame = TRUE, north = FALSE, tabtitle = TRUE)

north(pos = "topleft")

También, se pueden cambiar los símbolos, de círculos a cuadrados, o a barras.

opar <- par(mar = c(2,3,2.5,1))
tilesLayer(x = mun.osm)
plot(st_geometry(nbi_munic_new), col = NA, border = "skyblue", add = TRUE)
propSymbolsLayer(
  x = nbi_munic_new,
  var = "NBI",
  inches = 0.15,
  symbols = "square",
  col = "peru",
  legend.pos = "topright",
  legend.title.txt = "Total NBI"
  )

layoutLayer(title = "Distribución de NBI en Norte de Santander",
            sources = "Fuentes: DANE, 2018/n© OpenStreetMap",
            author = "Ana María Montaño",
            frame = TRUE, north = FALSE, tabtitle = TRUE)

north(pos = "topleft")

opar <- par(mar = c(2,3,2.5,1))
tilesLayer(x = mun.osm)
plot(st_geometry(nbi_munic_new), col = NA, border = "purple", add = TRUE)
propSymbolsLayer(
  x = nbi_munic_new,
  var = "NBI",
  inches = 0.3,
  symbols = "bar",
  col = "#A6CAE0",
  legend.pos = "topright",
  legend.title.txt = "Total NBI"
  )

layoutLayer(title = "Distribución de NBI en Norte de Santander",
            sources = "Fuentes: DANE, 2018/n© OpenStreetMap",
            author = "Ana María Montaño",
            frame = TRUE, north = FALSE, tabtitle = TRUE)

north(pos = "topleft")

Adicionalmente, cabe mencionar que en la realización de cada mapa temático hay una serie de pasos para su construcción:

- Se establecen las márgenes.

- Se trazan las fronteras de los municipios.

- Se plotean los datos de NBI: Acá se incluye la posición y el texto de la leyenda, el color del mapa, el color de los bordes, el tamaño de los símbolos y el nombre de la variable.

- Información de la capa externa: Acá se incluyen datos como el título, las fuentes de la información, el autor, y si se desea colocar el norte.

- Flecha del norte: Se indica la posición donde se desea colocar la flecha que indica el norte en el mapa.

7.2. Mapas de coropletas.

En los mapas de coropletas, las áreas se sombrean de acuerdo con la variación de una variable cuantitativa, que en este caso, corresponde a los datos de NBI. Estos mapas se usan principalmente, para representar razones o índices. La función choroLayer() muestra mapas de coropletas. Los argumentos nclass, method y breaks permiten personalizar la clasificación variable. La función getBreaks() permite clasificar fuera de la función misma. Las paletas de colores se definen con col y se puede crear un conjunto de colores con carto.pal(). Se consulta también display.carto.all.

opar <- par(mar = c(0,0,1.2,0))

par(bg= "grey90")

plot(st_geometry(nbi_munic_new), col= NA, border = NA, bg = "#aadaff")

choroLayer(
  x = nbi_munic_new,
  var = "NBI",
  method = "geom",
  nclass = 5,
  col = carto.pal(pal1 = "sand.pal", n1 = 5),
  border = "white",
  lwd = 0.5,
  legend.pos = "topright",
  legend.title.txt = "NBI",
  add = TRUE
  )

layoutLayer(title = "Distribución de NBI en Norte de Santander",
           sources = "Fuente: DANE, 2018",
           author = "Ana María Montaño",
           frame = TRUE, north = TRUE, tabtitle = TRUE, col = "black")

north(pos = "topleft")

A continuación, se va a realizar nuevamente un mapa de coropletas, pero experimentando con nuevas paletas de colores, otro color de borde, el número de clases para la clasificación, otro color de fondo y distinto grosor de las líneas (gracias al comando lwd).

opar <- par(mar = c(0,0,1.2,0))

par(bg= "gray77")

plot(st_geometry(nbi_munic_new), col= NA, border = NA, bg = "#E3DEBF")

choroLayer(
  x = nbi_munic_new,
  var = "NBI",
  method = "geom",
  nclass = 7,
  col = carto.pal(pal1 = "harmo.pal", n1 = 7),
  border = "black",
  lwd = 2,
  legend.pos = "topleft",
  legend.title.txt = "NBI",
  add = TRUE
  )

layoutLayer(title = "Distribución de NBI en Norte de Santander",
           sources = "Fuente: DANE, 2018",
           author = "Ana María Montaño",
           frame = TRUE, north = TRUE, tabtitle = TRUE, col = "black")

north(pos = "topleft")

En este mapa, se muestra el NBI por municipio, basándose en una escala de colores que determinan rangos de valores (9 - 50), facilitando la clasificación y análisis de datos. En este caso, el mapa de coropletas se usa para representar la variable cuantitativa NBI, donde cada color secuencial representa un rango de valores. Sirven para observar el crecimiento de esta variable en cada municipio, ya que aquellos que se ven con tonalidades más oscuras tienen más problemáticas relacionadas a pobreza, y a estos municipios, el gobierno debe proporcionarle soluciones y orientar políticas que permiten suplir las necesidades básicas que no están siendo satisfechas, como una vivienda digna, servicios necesarios, evitando a su vez situaciones de hacinamiento y miseria. Además, en el primer mapa se toman 5 clases para dividir los valores, y en el segundo se aumentan a 7 clases, logrando una división más exhaustiva de los datos de esta variable cuantitativa.

7.3. Símbolos proporcionales y mapa de 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 cualitativa. Se utiliza una combinación de argumentos propSymbolsLayer() y typoLayer(). Para esto, primero se debe crear una variable cualitativa, para poderla relacionar con la variable cuantitativa en estudio (NBI). Se usa la función mutate para hacer esta tarea.

nbi_munic_2 <- dplyr::mutate(nbi_munic_new, pobreza = ifelse(MISERIA > 20, "Extremo", ifelse(HACINAMIENTO > 5, "Alto", "Intermedio")))

Tenga en cuenta que el nuevo atributo se llama pobreza. Su valor depende de los valores umbral definidos. Hay que asegurarse de verificar la sintaxis del comando ifelse para comprender qué está sucediendo.

head(nbi_munic_2)
Simple feature collection with 6 features and 21 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: 1079620 ymin: 1287004 xmax: 1190861 ymax: 1424479
epsg (SRID):    3116
proj4string:    +proj=tmerc +lat_0=4.596200416666666 +lon_0=-74.07750791666666 +k=1 +x_0=1000000 +y_0=1000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
  DPTO_CCDGO MPIO_CCDGO MPIO_CNMBR MPIO_CRSLC MPIO_NAREA MPIO_NANO
1         54      54001     CÚCUTA       1972  1133.2031      2017
2         54      54003     ABREGO       1806  1382.4498      2017
3         54      54051  ARBOLEDAS       1835   456.1490      2017
4         54      54099  BOCHALEMA       1826   170.2669      2017
5         54      54109 BUCARASICA       1838   270.7909      2017
6         54      54125     CÁCOTA       1630   138.9222      2017
          DPTO_CNMBR Shape_Leng Shape_Area COD_DEPTO              DEPTO
1 NORTE DE SANTANDER  2.8636253 0.09289252        54 NORTE DE SANTANDER
2 NORTE DE SANTANDER  2.2393759 0.11336240        54 NORTE DE SANTANDER
3 NORTE DE SANTANDER  1.1611936 0.03736204        54 NORTE DE SANTANDER
4 NORTE DE SANTANDER  0.7565329 0.01394455        54 NORTE DE SANTANDER
5 NORTE DE SANTANDER  0.8281364 0.02220518        54 NORTE DE SANTANDER
6 NORTE DE SANTANDER  0.5561253 0.01136823        54 NORTE DE SANTANDER
  COD_MUN  MUNICIPIO      NBI  MISERIA VIVIENDA  SERVICIOS HACINAMIENTO
1     001     CÚCUTA 13.68850 2.578558 3.835583  0.4883718     5.966907
2     003     ABREGO 27.69108 6.013015 1.872634 10.6149147     4.950528
3     051  ARBOLEDAS 29.88151 7.220439 3.764503 12.5894841    10.441866
4     099  BOCHALEMA 15.98952 3.465851 3.145478  0.9902432     5.839522
5     109 BUCARASICA 36.63261 9.046403 3.490847 17.1136654     9.961686
6     125     CÁCOTA 24.01763 3.672420 2.019831  6.4634594    12.155711
  INASISTENCIA  ECONOMIA                       geometry    pobreza
1     2.429694  4.020303 MULTIPOLYGON (((1176189 142...       Alto
2     2.699382 15.157049 MULTIPOLYGON (((1116852 140... Intermedio
3     2.752407 10.343125 MULTIPOLYGON (((1148519 134...       Alto
4     1.689238  8.373380 MULTIPOLYGON (((1162705 134...       Alto
5     1.191997 16.922095 MULTIPOLYGON (((1124233 139...       Alto
6     1.322071  6.022769 MULTIPOLYGON (((1160837 130...       Alto
library(sf)
library(cartography)

opar <- par(mar = c(0,0,1.2,0))

plot(st_geometry(nbi_munic_2), col = "#f2efe9", border="#b38e43", bg = "#aad3df", lwd = 0.5)

propSymbolsTypoLayer(
  x= nbi_munic_2,
  var = "NBI",
  inches = 0.3,
  symbols = "square",
  border = "white",
  lwd = 0.5,
  legend.var.pos = "left",
  legend.var.title.txt = "NBI",
  var2 = "pobreza",
  legend.var2.values.order = c("Extremo", "Alto", "Intermedio"),
  col = carto.pal(pal1 = "multi.pal", n1= 3),
  legend.var2.pos = "right",
  legend.var2.title.txt = "Pobreza"
)

layoutLayer(title = "Distribución de NBI en Norte de Santander",
            author = "Ana María Montaño",
            sources = "Fuente: DANE, 2018",
            scale = 1, tabtitle = TRUE, frame = TRUE)

north(pos = "topleft")

En este mapa, se han definido umbrales para clasificar la pobreza en tres clases: extrema, alta e intermedia. Se puede identificar fácilmente en el mapa, los municipios que más se ven afectados por la pobreza, y aquellos que todavía no presentan valores críticos. Estas clases se reconocen por el color y el tamaño del cuadrado es proporcional al valor del NBI.

A continuación, se muestra el mismo mapa pero cambiándole algunas características.

library(sf)
library(cartography)

opar <- par(mar = c(0,0,1.2,0))

plot(st_geometry(nbi_munic_2), col = "#f2efe9", border="darkblue", bg = "lightyellow", lwd = 1.5)

propSymbolsTypoLayer(
  x= nbi_munic_2,
  var = "NBI",
  inches = 0.3,
  symbols = "bar",
  border = "black",
  lwd = 0.5,
  legend.var.pos = "left",
  legend.var.title.txt = "NBI",
  var2 = "pobreza",
  legend.var2.values.order = c("Extremo", "Alto", "Intermedio"),
  col = carto.pal(pal1 = "pink.pal", n1= 3),
  legend.var2.pos = "topright",
  legend.var2.title.txt = "Pobreza"
)

layoutLayer(title = "Distribución de NBI en Norte de Santander",
            author = "Ana María Montaño",
            sources = "Fuente: DANE, 2018",
            scale = 1, tabtitle = TRUE, frame = TRUE)

north(pos = "topleft")

7.4. Mapas de etiquetas.

En éste mapa se van a combinar las funciones choroLayer() y labelLayer().

library(sf)
library(cartography)
opar <- par(mar = c(0,0,1.2,0))

par(bg= "grey25")
plot(st_geometry(nbi_munic_2), col= "#e4e9de", border = "darkseagreen4",
     bg = "grey75", lwd = 0.5)

choroLayer(
  x = nbi_munic_new,
  var = "NBI",
  method = "geom",
  nclass = 5,
  col = carto.pal(pal1 = "sand.pal", n1 = 5),
  border = "white",
  lwd = 0.5,
  legend.pos = "topright",
  legend.title.txt = "NBI",
  add = TRUE
)

labelLayer(
  x= nbi_munic_2,
  txt = "MUNICIPIO",
  col = "white",
  cex = 0.4,
  font = 4,
  halo = TRUE,
  bg = "grey25",
  r = 0.1,
  overlap = FALSE,
  show.lines = FALSE
)

layoutLayer(
  title = "Municipios de Norte de Santander",
  sources = "Fuente: DANE, 2018",
  author = "Ana María Montaño",
  frame = TRUE,
  north = TRUE, 
  tabtitle = TRUE,
  theme = "taupe.pal"
)

En este mapa también se usan escalas de colores para indicar rangos de valores de NBI. A diferencia de los anteriores las etiquetas nos proporcionan la información visual de forma más rápida e inmediata, permitiendo responder preguntas como ¿cuál es el municipio con mayor NBI?. Una respuesta para esto es: El municipio de El Tarra, porque presenta la coloración amarilla más oscura, y se encuentra en el rango de 50.

EL TARRA

Para contextualizar un poco,El Tarra, es un municipio colombiano ubicado en el departamento de Norte de Santander. Está a una altitud de 270 m.s.n.m, tiene una extensión de 675km2 y limita al norte y oriente con Tibú, al sur con San Calixto y al occidente con Teorama. Tiene una población de 12766 habitantes, de los cuales 9498 residen en la zona urbana y 3268 en la rural. Se encuentra a 159km de Cúcuta (la capital del departamento). Según La Defensoría del Pueblo, 2006, el municipio de El Tarra pertenece a la región del Catatumbo, y actualmente los municipios que conforman esta región presentan altos índices de pobreza (más del 53% de la población de El Tarra, Hacarí y San Calixto se encuentran bajo la línea de pobreza), el NBI, supera el 53% y presentan muy baja cobertura en servicios públicos. Sólo el 27% de la población del Catatumbo tiene cobertura de agua potable. . Además, esta región del Catatumbo es altamente vulnerable ya que la disputa por el territorio y los recursos naturales por parte de los actores armados al margen de la ley, desde hace muchos años, ha desestabilizado la región. También, la violación de derechos humanos por los grupos armados al margen de la ley, se traduce en un gran número de masacres, asesinatos selectivos, desplazamiento forzado, restricción a la libertad de movilización, pérdida del territorio, amenaza al ambiente sano y violación de otros derechos colectivos

A continuación, se realiza el mismo mapa pero con distintos colores en el mapa y en el fondo, aumento el tamaño de la letra y se cambia la posición de la leyenda.

library(sf)
library(cartography)
opar <- par(mar = c(0,0,1.2,0))

par(bg= "grey25")
plot(st_geometry(nbi_munic_2), col= "#e4e9de", border = "darkseagreen4",
     bg = "lightgreen", lwd = 0.5)

choroLayer(
  x = nbi_munic_new,
  var = "NBI",
  method = "geom",
  nclass = 7,
  col = carto.pal(pal1 = "orange.pal", n1 = 7),
  border = "white",
  lwd = 0.5,
  legend.pos = "left",
  legend.title.txt = "NBI",
  add = TRUE
)

labelLayer(
  x= nbi_munic_2,
  txt = "MUNICIPIO",
  col = "white",
  cex = 0.6,
  font = 4,
  halo = TRUE,
  bg = "grey25",
  r = 0.1,
  overlap = FALSE,
  show.lines = FALSE
)

layoutLayer(
  title = "Municipios de Norte de Santander",
  sources = "Fuente: DANE, 2018",
  author = "Ana María Montaño",
  frame = TRUE,
  north = TRUE, 
  tabtitle = TRUE,
  theme = "taupe.pal"
)

Se puede observar que si aumentamos el número de clases, los rangos de colores, se pueden analizar los datos con mayor detalle ya que existe más diferenciación de los valores de NBI para cada municipio. Además, gracias a las etiquetas se puede identificar con facilidad a que municipio corresponde cada valor de NBI.

7.5. Mapas de isopletas.

Los mapas de isopletas 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. Se usa la función smoothLayer() que depende en gran medida del paquete SpatialPosition. Esta 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. Para realizar este mapa, se utilizará otro conjunto de datos. En este caso, se tendrán en cuenta los datos sobre la producción de arroz en 2018, para el departamento de Norte de Santander. El arroz es el segundo cultivo con mayor área sembrada en el departamento, después del café. Se lee el conjunto de datos:

crops2018  <-  read_excel("C:/Users/user/Documents/Norte de Santander/EVA3_NORTEDESANTANDER.xlsx")
head(crops2018)

Ahora, se van a filtrar las filas que representan solo datos de arroz:

crops2018 %>%
  filter(CULTIVO == "ARROZ") -> arroz2018
head(arroz2018)

Luego, se va a crear un nuevo atributo que coincide con los códigos de municipios:

arroz2018$TEMP <- as.character(arroz2018$COD_MUN)
head(arroz2018)
arroz2018$MPIO_CCDGO <- as.factor(arroz2018$TEMP)

Hacer la unión:

arroz_munic = left_join(munic, arroz2018, by = "MPIO_CCDGO")
Column `MPIO_CCDGO` joining factors with different levels, coercing to character vector
head(arroz_munic)
Simple feature collection with 6 features and 25 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -72.60664 ymin: 7.721513 xmax: -72.34632 ymax: 8.431296
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs
  DPTO_CCDGO MPIO_CCDGO MPIO_CNMBR MPIO_CRSLC MPIO_NAREA MPIO_NANO
1         54      54001     CÚCUTA       1972   1133.203      2017
2         54      54001     CÚCUTA       1972   1133.203      2017
3         54      54001     CÚCUTA       1972   1133.203      2017
4         54      54001     CÚCUTA       1972   1133.203      2017
5         54      54001     CÚCUTA       1972   1133.203      2017
6         54      54001     CÚCUTA       1972   1133.203      2017
          DPTO_CNMBR Shape_Leng Shape_Area COD_DEP       DEPARTAMENTO
1 NORTE DE SANTANDER   2.863625 0.09289252      54 NORTE DE SANTANDER
2 NORTE DE SANTANDER   2.863625 0.09289252      54 NORTE DE SANTANDER
3 NORTE DE SANTANDER   2.863625 0.09289252      54 NORTE DE SANTANDER
4 NORTE DE SANTANDER   2.863625 0.09289252      54 NORTE DE SANTANDER
5 NORTE DE SANTANDER   2.863625 0.09289252      54 NORTE DE SANTANDER
6 NORTE DE SANTANDER   2.863625 0.09289252      54 NORTE DE SANTANDER
  COD_MUN MUNICIPIO    GRUPO SUBGRUPO CULTIVO YEAR Area_Sembrada(ha)
1   54001    CUCUTA CEREALES    ARROZ   ARROZ 2006              8100
2   54001    CUCUTA CEREALES    ARROZ   ARROZ 2007              8660
3   54001    CUCUTA CEREALES    ARROZ   ARROZ 2007              7948
4   54001    CUCUTA CEREALES    ARROZ   ARROZ 2008              9180
5   54001    CUCUTA CEREALES    ARROZ   ARROZ 2008             11720
6   54001    CUCUTA CEREALES    ARROZ   ARROZ 2009             10310
  Area_Cosecha(ha) Produccion Rendimiento      ESTADO       NOMBRE
1             8100      51000        6.30 PADDY VERDE ORYZA SATIVA
2             8660      54000        6.24 PADDY VERDE ORYZA SATIVA
3             7900      49770        6.30 PADDY VERDE ORYZA SATIVA
4             9000      56700        6.30 PADDY VERDE ORYZA SATIVA
5            11690      63647        5.44 PADDY VERDE ORYZA SATIVA
6            10310      70700        6.86 PADDY VERDE ORYZA SATIVA
        CICLO  TEMP                       geometry
1 TRANSITORIO 54001 MULTIPOLYGON (((-72.4778 8....
2 TRANSITORIO 54001 MULTIPOLYGON (((-72.4778 8....
3 TRANSITORIO 54001 MULTIPOLYGON (((-72.4778 8....
4 TRANSITORIO 54001 MULTIPOLYGON (((-72.4778 8....
5 TRANSITORIO 54001 MULTIPOLYGON (((-72.4778 8....
6 TRANSITORIO 54001 MULTIPOLYGON (((-72.4778 8....

Reproyección de los municipios:

rep_arroz <- st_transform(arroz_munic, crs = 3116)

Es momento de hacer el mapa:

opar <- par(mar = c(0,0,1.2,0))

plot(st_geometry(rep_arroz), col= NA, border = "black", bg = "grey75")

smoothLayer(
  x = rep_arroz,
  var =  "Produccion",
  typefct = "exponential",
  span = 15000,
  beta = 2,
  nclass = 8,
  col = carto.pal(pal1 = "turquoise.pal", n1= 8),
  border = "grey",
  lwd = 0.1,
  mask = rep_arroz,
  legend.values.rnd = 0,
  legend.title.txt =  "Produccion",
  legend.pos = "topright",
  add = TRUE
)

text(x = 650000, y= 1200000, cex = 1, adj = 0, font = 3, labels = "Función distancia:\n- type = exponential\n- beta = 2\n- span = 15 km")

layoutLayer(title = "Distribución de la producción de arroz en Norte de Santander",
            sources = "Fuente: DANE Y MADR, 2018",
            author = "Ana María Montaño",
            frame = FALSE, north = FALSE, tabtitle = TRUE, theme = "turquoise.pal")

north(pos = "topleft")

Para este mapa se utilizan los datos de producción de arroz para el departamento de Norte de Santander. Se puede observar que la mayor parte de la producción está concentrada en la parte oriental del departamento, en el municipio de Cúcuta y El Zulia. También, existe producción de arroz en otros municipios al norte y sur del departamento. - Según La Opinión, para el año 2019 la alta demanda de artículos de la canasta básica por parte de la población flotante en Cúcuta y Norte de Santander se ha convertido en un problema para el abastecimiento de productos como la harina de maíz y de trigo. Sin embargo, otros sectores productores de alimentos están aprovechando la oportunidad para incrementar sus ventas. Este es el caso de los arroceros, quienes han aumentado la producción de arroz, y esto los ha llevado a triplicar sus ventas en Cúcuta y a posicionarse en el mercado regional. Guillermo Infante Santos, gerente general de la Cooperativa Agropecuaria de Norte de Santander (Coagonorte), informó que mientras al inicio del año despachaban 35.000 toneladas diarias, ahora están enviando 65.000 toneladas hacia las plazas de Cúcuta. Además, explica que los altos niveles de producción se deben al crecimiento en la demanda del producto en supermercados y bodegas de la ciudad, esto a causa de las compras que hacen los venezolanos que viajan a Cúcuta para abastecerse.

8. Guardar mapas.

Ahora se va a realizar otro mapa de producción de arroz en 2018. Esta vez se van a usar símbolos proporcionales y mapas de coropletas. La salida se guardará como un archivo.png. Primero, algunas observaciones:

  • propSymbolsChoroLaer() crea una 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 chunk no muestra un mapa. En cambio, escribe el mapa en el nombre de archivo arroz_2018.png debajo del directorio de trabajo.

png("C:/Users/user/Documents/Intro_to_R/arroz_2018.png", width = 2048, height = 1526)

opar <- par(mar= c(0,0,5,5))
plot(st_geometry(rep_arroz), col = "darkseagreen3", border="darkseagreen4", bg= "white", lwd = 0.6)

propSymbolsChoroLayer(x = rep_arroz, 
                      var = "Produccion", 
                      var2 = "Rendimiento",
                      col = carto.pal(pal1 = "turquoise.pal", n1 = 3,
                                      pal2 = "red.pal", n2 = 3),
                      inches = 0.8, method = "q6",
                      border = "grey50", lwd = 1,
                      legend.title.cex = 1.5,
                      legend.values.cex = 1.0,
                      legend.var.pos = "right", 
                      legend.var2.pos = "left",
                      legend.var2.values.rnd = 2,
                      legend.var2.title.txt = "Rendimiento\n(Ton/Ha)",
                      legend.var.title.txt = "Produccion de arroz en 2018",
                      legend.var.style = "e")
labelLayer(
  x = rep_arroz, 
  txt = "MPIO_CNMBR", 
  col= "white", 
  cex = 2.0, 
  font = 4,
  halo = FALSE, 
  bg = "white", 
  r = 0.1, 
  overlap = FALSE, 
  show.lines = FALSE
)

layoutLayer(title="Producción y rendimiento de arroz in Norte de Santander, 2018",
            author = "Ana María Montaño", 
            sources = "Sources: MADR & DANE, 2018", 
            scale = 50, tabtitle = FALSE, frame = TRUE)

north(pos = "topleft")

title(main="Producción y rendimiento de arroz in Norte de Santander, 2018", cex.main=3,
      sub= "Source: MADR & DANE, 2018", cex.sub=2)

graticule = TRUE

par(opar)

dev.off()
null device 
          1 

Ahora, que ya hemos guardado el mapa como una imagen, se puede agregar al cuaderno de R Markdown usando la sintaxis de Markdown de la siguiente manera:

Producción de arroz en Norte de Santander, 2018

Producción de arroz en Norte de Santander, 2018

Finalmente, en este mapa se relaciona la producción y el rendimiento de arroz en el departamento, donde gracias a los símbolos circulares se observa que la producción se concentra en el municipio de Cúcuta, donde se encuentra el círculo de mayor tamaño. El rendimiento se puede observar por los diferentes colores que presentan los círculos.

sessionInfo()
R version 3.6.3 (2020-02-29)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)

Matrix products: default

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

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

other attached packages:
 [1] SpatialPosition_1.2.0 cartography_2.4.1     sf_0.8-1             
 [4] rgeos_0.5-2           readxl_1.3.1          forcats_0.5.0        
 [7] stringr_1.4.0         dplyr_0.8.4           purrr_0.3.3          
[10] readr_1.3.1           tidyr_1.0.2           tibble_2.1.3         
[13] ggplot2_3.3.0         tidyverse_1.3.0       raster_3.0-12        
[16] sp_1.4-1             

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.3         lubridate_1.7.4    lattice_0.20-38   
 [4] png_0.1-7          class_7.3-15       assertthat_0.2.1  
 [7] digest_0.6.25      R6_2.4.1           cellranger_1.1.0  
[10] backports_1.1.5    reprex_0.3.0       evaluate_0.14     
[13] e1071_1.7-3        httr_1.4.1         pillar_1.4.3      
[16] rlang_0.4.5        rstudioapi_0.11    rmarkdown_2.1     
[19] rgdal_1.4-8        munsell_0.5.0      broom_0.5.5       
[22] compiler_3.6.3     modelr_0.1.6       xfun_0.12         
[25] pkgconfig_2.0.3    base64enc_0.1-3    htmltools_0.4.0   
[28] tidyselect_1.0.0   codetools_0.2-16   fansi_0.4.1       
[31] crayon_1.3.4       dbplyr_1.4.2       withr_2.1.2       
[34] grid_3.6.3         nlme_3.1-144       jsonlite_1.6.1    
[37] gtable_0.3.0       lifecycle_0.2.0    DBI_1.1.0         
[40] magrittr_1.5       units_0.6-5        scales_1.1.0      
[43] KernSmooth_2.23-16 cli_2.0.2          stringi_1.4.6     
[46] fs_1.3.2           xml2_1.2.5         generics_0.0.2    
[49] vctrs_0.2.3        tools_3.6.3        glue_1.3.1        
[52] hms_0.5.3          slippymath_0.3.1   rsconnect_0.8.16  
[55] yaml_2.2.1         colorspace_1.4-1   classInt_0.4-2    
[58] rvest_0.3.5        knitr_1.28         haven_2.2.0       
LS0tDQp0aXRsZTogIkNhcnRvZ3JhZsOtYSB0ZW3DoXRpY2EiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpBbmEgTWFyw61hIE1vbnRhw7FvIEhlcm7DoW5kZXoNCg0KTWF5byAxNi8gMjAyMA0KDQoNCiMgMS4gSW50cm9kdWNjacOzbi4NCiA8ZGl2IHN0eWxlPSAidGV4dC1hbGlnbjoganVzdGlmeSI+DQpTZWfDum4gVsOtY3RvciBPbGF5YSwgdW4gbWFwYSBlcyBlbCBtZWRpbyBtw6FzIGFkZWN1YWRvIHBhcmEgdHJhbnNtaXRpciBpbmZvcm1hY2nDs24gZ2VvZ3LDoWZpY2EgZGUgbWFuZXJhIHZpc3VhbCwgeSBjb24gZWwgb2JqZXRpdm8gZGUgZGVzY3JpYmlyIHJlbGFjaW9uZXMgZXNwYWNpYWxlcy4gQ29tbyBtZW5jaW9uYSBPbGF5YSwgcGFyYSByZWFsaXphciBjb3JyZWN0YW1lbnRlIHVuIG1hcGEsIHNlIGRlYmVuIHNlZ3VpciBjdWF0cm8gZXRhcGFzIGltcG9ydGFudGVzOiByZWNvbGVjdGFyIGxvcyBkYXRvcywgbWFuaXB1bGFyIGxvcyBkYXRvcyBwYXJhIGRpc2XDsWFyIHkgY29uc3RydWlyIGVsIG1hcGEsIHZpc3VhbGl6YXJsbyB5IHBvciDDumx0aW1vIGludGVycHJldGFyIGxhIGluZm9ybWFjacOzbiB2aXN1YWwgcXVlIHNlIG9idGllbmUuIExvIGFudGVyaW9yLCBlcyBkZSBncmFuIGltcG9ydGFuY2lhLCB5YSBxdWUgbm9zIHBlcm1pdGUgY3VtcGxpciBjb24gZWwgb2JqZXRpdm8gZGUgbGEgY2FydG9ncmFmw61hIHF1ZSBlcyBsYSByZXByZXNlbnRhY2nDs24gbyBhYnN0cmFjY2nDs24gc2ltYsOzbGljYSBkZSB1biBmZW7Ds21lbm8gZW4gcGFydGljdWxhciwgcGFyYSBlbnRlbmRlciBjw7NtbyBvY3VycmUgeSBzdXMgcmVsYWNpb25lcyBlc3BhY2lhbGVzLiBFbiBmdW5jacOzbiBkZWwgdGlwbyBkZSBpbmZvcm1hY2nDs24gcXVlIGJyaW5kYSwgbG9zIG1hcGFzIHB1ZWRlbiBzZXIgdG9wb2dyw6FmaWNvcyBvIHRlbcOhdGljb3MuICBFbiBjdWFudG8gYSBsYSBjYXJ0b2dyYWbDrWEgdGVtw6F0aWNhIGVzdGEgc2UgY2VudHJhIGVuIHJlcHJlc2VudGFyIHVuYSB2YXJpYWJsZSBlc3BhY2lhbCBlc3BlY8OtZmljYSwgbGEgY3VhbCBwdWVkZSBzZXIgZGUgY3VhbHF1aWVyIHRlbcOhdGljYSwgZXhjbHV5ZW5kbyBsb3MgdGVtYXMgdG9wb2dyw6FmaWNvcy4gU2luIGVtYmFyZ28sIGxhIGNhcnRvZ3JhZsOtYSB0ZW3DoXRpY2EgZGViZSBhcG95YXJzZSBlbiBsYSBjYXJ0b2dyYWbDrWEgYmFzZSBwYXJhIHViaWNhciBlbiB1biBjb250ZXh0byBnZW9ncsOhZmljbyBsYSB2YXJpYWJsZSByZXByZXNlbnRhZGEsIHBlcm1pdGllbmRvIGxhIGNvbXByZW5zacOzbiBkZSBzdSBjb21wb3J0YW1pZW50by4NClBvciBvdHJhIHBhcnRlLCBlcyBuZWNlc2FyaW8gZGVzYXJyb2xsYXIgbGEgY2FwYWNpZGFkIGRlIGNyZWFyIHVuIG1hcGEgeSBzYWJlciBlc2NvZ2VyIHF1w6kgdGlwbyBkZSBtYXBhIGVzIGVsIG3DoXMgYWRlY3VhZG8gY29uZm9ybWUgbGEgaW5mb3JtYWNpw7NuIG8gdmFyaWFibGUgcXVlIHNlIGRlc2VhIGlsdXN0cmFyLCBhc8OtIGNvbW8gbGEgc2VsZWNjacOzbiBjb3JyZWN0YSBkZSBzw61tYm9sb3MsIGxleWVuZGFzLCBjb2xvcmVzLCBlc2NhbGEsIHByb3llY2Npw7NuLCBkYXRvcywgYSB1dGlsaXphciB0ZW5pZW5kbyBlbiBjdWVudGEgZWwgcXXDqSB5IGEgcXVpw6luIGVzdMOhIGRpcmlnaWRvIGRpY2hvIG1hcGEuICBQb3IgbG8gdGFudG8sIGVzdGUgY3VhZGVybm8gZGUgUiB0aWVuZSBjb21vIG9iamV0aXZvIGlsdXN0cmFyIGNhcnRvZ3JhZsOtYSB0ZW3DoXRpY2EgcGFyYSBlbCBkZXBhcnRhbWVudG8gZGUgTm9ydGUgZGUgU2FudGFuZGVyLCB1dGlsaXphbmRvIGRhdG9zIGNvbW8gTkJJIChOZWNlc2lkYWRlcyBiw6FzaWNhcyBpbnNhdGlzZmVjaGFzKSB5IGVzdGFkw61zdGljYXMgYWdyw61jb2xhcyBkZWwgZGVwYXJ0YW1lbnRvLiBTZSB2YW4gYSBpbHVzdHJhciBkaXN0aW50b3MgdGlwb3MgZGUgbWFwYXMgdGVtw6F0aWNvcywgY29tbyBsbyBzb246IG1hcGEgZGUgY29yb3BsZXRhcywgaXNvcGxldGFzLCBkZSBzw61tYm9sb3MgcHJvcG9yY2lvbmFsZXMsIHkgZGUgZXRpcXVldGFzLiANCg0KIyAyLiBDYXJ0b2dyYWbDrWEgdGVtw6F0aWNhLg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NClNlZ8O6biBBbWFuZGEgQnJpbmV5LCB1biBtYXBhIHRlbcOhdGljbyBlbmZhdGl6YSBlbiB1biB0ZW1hIGVzcGVjw61maWNvLCBjb21vIGxhIGRpc3RyaWJ1Y2nDs24gcHJvbWVkaW8gZGUgbGx1dmlhIGVuIHVuIMOhcmVhIG8gbGEgZGVuc2lkYWQgZGUgcG9ibGFjacOzbiBlbiB1biBtdW5pY2lwaW8uIFNvbiBkaWZlcmVudGVzIGRlIGxvcyBtYXBhcyBkZSByZWZlcmVuY2lhIGdlbmVyYWxlcyBwb3JxdWUgbm8gc29sbyBtdWVzdHJhbiBjYXJhY3RlcsOtc3RpY2FzIG5hdHVyYWxlcyB5IGNyZWFkYXMgcG9yIGVsIGhvbWJyZSwgY29tbyByw61vcywgY2l1ZGFkZXMsIHN1YmRpdmlzaW9uZXMgcG9sw610aWNhcyB5IGNhcnJldGVyYXMuIFNpIGVzdG9zIGVsZW1lbnRvcyBhcGFyZWNlbiBlbiB1biBtYXBhIHRlbcOhdGljbywgc29uIHB1bnRvcyBkZSByZWZlcmVuY2lhIHBhcmEgbWVqb3JhciBsYSBjb21wcmVuc2nDs24gZGVsIHRlbWEgeSBlbCBwcm9ww7NzaXRvIGRlbCBtYXBhLg0KDQpTZWfDum4gQnJpbmV5LCAiZWwgZmFjdG9yIG3DoXMgaW1wb3J0YW50ZSBhIHRlbmVyIGVuIGN1ZW50YSBhbCBkaXNlw7FhciBtYXBhcyB0ZW3DoXRpY29zIGVzIGxhIGF1ZGllbmNpYSBkZWwgbWFwYSwgbG8gcXVlIGF5dWRhIGEgZGV0ZXJtaW5hciBxdcOpIGVsZW1lbnRvcyBkZWJlbiBpbmNsdWlyc2UgZW4gZWwgbWFwYSBjb21vIHB1bnRvcyBkZSByZWZlcmVuY2lhLCBhZGVtw6FzIGRlbCB0ZW1hLiBVbiBtYXBhIHF1ZSBzZSBlc3TDoSBoYWNpZW5kbyBwYXJhIHVuIHBvbGl0w7Nsb2dvLCBwb3IgZWplbXBsbywgbmVjZXNpdGFyw61hIG1vc3RyYXIgbMOtbWl0ZXMgcG9sw610aWNvcywgbWllbnRyYXMgcXVlIHVubyBwYXJhIHVuIGJpw7Nsb2dvIHBvZHLDrWEgbmVjZXNpdGFyIGNvbnRvcm5vcyBxdWUgbXVlc3RyZW4gbGEgZWxldmFjacOzbuKAnS4NCg0KTGFzIGZ1ZW50ZXMgZGUgZGF0b3MgZGUgbG9zIG1hcGFzIHRlbcOhdGljb3Mgc29uIG11eSBpbXBvcnRhbnRlcywgZW5mYXRpemEgQnJpbmV5LiAiTG9zIGNhcnTDs2dyYWZvcyBkZWJlbiBlbmNvbnRyYXIgZnVlbnRlcyBkZSBpbmZvcm1hY2nDs24gcHJlY2lzYXMsIHJlY2llbnRlcyB5IGNvbmZpYWJsZXMgc29icmUgdW5hIGFtcGxpYSBnYW1hIGRlIHRlbWFzLCBkZXNkZSBjYXJhY3RlcsOtc3RpY2FzIGFtYmllbnRhbGVzIGhhc3RhIGRhdG9zIGRlbW9ncsOhZmljb3MsIHBhcmEgaGFjZXIgbG9zIG1lam9yZXMgbWFwYXMgcG9zaWJsZXMiLg0KT3RybyBhc3BlY3RvIGltcG9ydGFudGUgcXVlIG1lbmNpb25hIFbDrWN0b3IgT2xheWEsIGVzIHF1ZSB1biBtYXBhIHRlbcOhdGljbyBzZSBjb21wb25lIGRlIGRvcyBwYXJ0ZXMgcHJpbmNpcGFsZXM6DQoNCuKAoioqVW5hIGNhcGEgZXNwZWPDrWZpY2EgY29uIGxhIGluZm9ybWFjacOzbiB0ZW3DoXRpY2E6KiogRXN0YSBjb250aWVuZSBsYSBpbmZvcm1hY2nDs24gcHJpbmNpcGFsIGRlbCBtYXBhLCByZXByZXNlbnRhbmRvIGxhIHZhcmlhYmxlIGVzcGFjaWFsIHNvYnJlIGxhIHF1ZSBzZSBjb25zdHJ1eWUgZXN0ZS4NCg0K4oCiKipVbiBtYXBhIGJhc2U6KipFc3RlIG90b3JnYSB1bmEgbG9jYWxpemFjacOzbiBnZW9ncsOhZmljYSBhIGxvIHF1ZSBzZSByZWZlcmVuY2lhIGxhIGluZm9ybWFjacOzbiB0ZW3DoXRpY2EuIEVzdGUgbWFwYSB2YSBhIGF5dWRhciBhIGxvcyBlbGVtZW50b3MgZGUgbGEgY29tcG9uZW50ZSB0ZW3DoXRpY2EgYSB0cmFuc21pdGlyIG1lam9yIGxhIGluZm9ybWFjacOzbiBxdWUgY29udGllbmVuLiANCkNhYmUgbWVuY2lvbmFyIHF1ZSBsYSBjYXJ0b2dyYWbDrWEgdGVtw6F0aWNhIGVzIGxhIHF1ZSBjb24gbWF5b3IgZnJlY3VlbmNpYSBzZSBnZW5lcmEgbWVkaWFudGUgZWwgdXNvIGRlIHVuICoqU0lHKiosIHkgc2UgY2VudHJhIHByaW5jaXBhbG1lbnRlIGVuIGxhIHJlcHJlc2VudGFjacOzbiBkZSB2YWxvcmVzIHkgYXRyaWJ1dG9zLiANCkJyaW5leSByZXN1bWUgdmFyaWFzIHTDqWNuaWNhcyBkZSBtYXBlbyB0ZW3DoXRpY28gcXVlIHNlIHVzYW4gY29uIG1heW9yDQpmcmVjdWVuY2lhOg0KRW4gZXN0YSBwYXJ0ZSBzZSB1dGlsaXphcm9uIGltw6FnZW5lcyBwYXJhIG1vc3RyYXIgbWVqb3IgYSBxdcOpIHNlIHJlZmllcmUgY2FkYSB0aXBvIGRlIG1hcGEsIHBlcm8gcG9zdGVyaW9ybWVudGUgc2UgZXhwbGljYSBjb21vIGhhY2VyIHVuIG1hcGEgdGVtw6F0aWNvIGVuIFIsIHBhcmEgcXVlIHBvZGFtb3MgcmVhbGl6YXIgbnVlc3RyYXMgcHJvcGlhcyBjcmVhY2lvbmVzLiANCg0KDQojIDIuMSBNYXBhIGRlIGNvcm9wbGV0YToNCiA8ZGl2IHN0eWxlPSAidGV4dC1hbGlnbjoganVzdGlmeSI+DQpFcyB1biBtYXBhIHF1ZSByZXRyYXRhIGxvcyBkYXRvcyBjdWFudGl0YXRpdm9zIGNvbW8gZWwgY29sb3IgeSBwdWVkZSBtb3N0cmFyIGxhIGRlbnNpZGFkLCBlbCBwb3JjZW50YWplLCBlbCB2YWxvciBwcm9tZWRpbyBvIGxhIGNhbnRpZGFkIGRlIHVuIGV2ZW50byBkZW50cm8gZGUgdW4gw6FyZWEgZ2VvZ3LDoWZpY2EuIExvcyBjb2xvcmVzIHNlY3VlbmNpYWxlcyByZXByZXNlbnRhbiB2YWxvcmVzIGRlIGRhdG9zIHBvc2l0aXZvcyBvIG5lZ2F0aXZvcyBjcmVjaWVudGVzIG8gZGVjcmVjaWVudGVzLiBOb3JtYWxtZW50ZSwgY2FkYSBjb2xvciB0YW1iacOpbiByZXByZXNlbnRhIHVuIHJhbmdvIGRlIHZhbG9yZXMuDQpBZGVtw6FzLCBzZWfDum4gT2xheWEgbG9zIG1hcGFzIGRlIGNvcm9wbGV0YXMgc29uIHV0aWxpemFkb3MgcGFyYSByZXByZXNlbnRhciBsYSBpbmZvcm1hY2nDs24gZ2VvZ3LDoWZpY2EgZW4gdW4gU0lHLiBFbiB1biBtYXBhIGRlIGNvcm9wbGV0YXMgc2UgdGllbmUgdW5hIHNlcmllIGRlIMOhcmVhcyBkZWZpbmlkYXMsIGNhZGEgdW5hIGRlIGxhcyBjdWFsZXMgcG9zZWUgdW4gdmFsb3IgZGUgdW5hIHZhcmlhYmxlLiBFc3RlIHZhbG9yIGRlIGxhIHZhcmlhYmxlIGFmZWN0YSBhIHRvZGEgZWwgw6FyZWEgeSBlcyBlbCBxdWUgc2UgcmVwcmVzZW50YSBwb3IgbWVkaW8gZGUgYWxndW5hIHZhcmlhYmxlIHZpc3VhbCwgbm9ybWFsbWVudGUgZWwgY29sb3IgYSB0cmF2w6lzIGRlIHN1IGNvbXBvbmVudGUgdmFsb3IuIExhcyB6b25hcyBkZWZpbmlkYXMgcG9yIGNhZGEgw6FyZWEgdGllbmVuIHVuIHNpZ25pZmljYWRvIGFyYml0cmFyaW8sIG5vIHJlbGFjaW9uYWRvIGNvbiBsYSB2YXJpYWJsZSBhc29jaWFkYS4gDQoNCkEgY29udGludWFjacOzbiBzZSBtdWVzdHJhIHVuIGVqZW1wbG8gZGUgbWFwYSBkZSBjb3JvcGxldGFzIHBhcmEgbGEgcG9ibGFjacOzbiBpbmTDrWdlbmEgcG9yIG11bmljaXBpbywgdG9tYWRvIGRlbCBEQU5FIDIwMDUuDQoNCiFbUG9ibGFjacOzbiBpbmTDrWdlbmEgcG9yIG11bmljaXBpb10oQzovVXNlcnMvdXNlci9Eb2N1bWVudHMvSW50cm9fdG9fUi8xMjMucG5nKQ0KDQpFbiBlc3RlIGxpbmsgc2UgcHVlZGVuIGVuY29udHJhciBtw6FzIGVqZW1wbG9zIGRlIG1hcGFzIGRlIGNvcm9wbGV0YXMuW0RBTkVdKA0KaHR0cDovL2dlb3BvcnRhbC5kYW5lLmdvdi5jby9zZXJ2aWNpb3Mvc2VydmljaW9zLXdlYi1nZW9ncmFmaWNvcy9zcmMvZmlsZXMvaW5kaWNhZG9yZXMvc2VydmljaW9NYXguaHRtbD9zPUVzdHJ1Y3R1cmFDb21wb3NpY2lvblBvYmxhY2lvbl8xMyZjPVBvYmxhY2lvbnlEZW1vZ3JhZmlhJnNjPUVzdHJ1Y3R1cmFDb21wb3NpY2lvblBvYmxhY2lvbg0KKQ0KDQoNCiMgMi4yLk1hcGEgZGUgc8OtbWJvbG9zIHByb3BvcmNpb25hbGVzIG8gZ3JhZHVhZG9zLg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCiBVbiBtYXBhIGRlIHPDrW1ib2xvcyBwcm9wb3JjaW9uYWxlcyByZXByZXNlbnRhIHZhcmlhYmxlcyBjdWFudGl0YXRpdmFzIGEgdHJhdsOpcyBkZSBzw61tYm9sb3MgY3V5byB0YW1hw7FvIGVzdGEgZW4gcmVsYWNpw7NuIGNvbiBlbCB2YWxvciBhIHJlcHJlc2VudGFyIGRlIGRpY2hhIHZhcmlhYmxlLiBTZSB1c2FuIHBhcmEgcmVwcmVzZW50YXIgZGF0b3MgYXNvY2lhZG9zIGNvbiB1YmljYWNpb25lcywgY29tbyBjaXVkYWRlcy4gTG9zIGRhdG9zIHNlIG11ZXN0cmFuIGVuIGVzdG9zIG1hcGFzIGNvbiBzw61tYm9sb3MgZGUgdGFtYcOxbyBwcm9wb3JjaW9uYWwgcGFyYSBtb3N0cmFyIGxhcyBkaWZlcmVuY2lhcyBlbiBsYXMgb2N1cnJlbmNpYXMuIExvcyBjw61yY3Vsb3Mgc2UgdXNhbiBjb24gbWF5b3IgZnJlY3VlbmNpYSwgcGVybyBsb3MgY3VhZHJhZG9zIHkgb3RyYXMgZm9ybWFzIGdlb23DqXRyaWNhcyB0YW1iacOpbiBzb24gYWRlY3VhZG9zLiBMYSBmb3JtYSBtw6FzIGNvbcO6biBkZSBjYW1iaWFyIGVsIHRhbWHDsW8gZGUgZXN0b3Mgc8OtbWJvbG9zIGVzIGhhY2VyIHF1ZSBzdXMgw6FyZWFzIHNlYW4gcHJvcG9yY2lvbmFsZXMgYSBsb3MgdmFsb3JlcyBxdWUgc2UgcmVwcmVzZW50YXLDoW4gbWVkaWFudGUgZWwgc29mdHdhcmUgZGUgbWFwZW8gbyBkaWJ1am8uDQogDQogIVtTw61tYm9sb3MgcHJvcG9yY2lvbmFsZXMgZW1wbGVhZG9zIGVuIGVzdGUgdGlwbyBkZSBtYXBhc10oQzovVXNlcnMvdXNlci9Eb2N1bWVudHMvSW50cm9fdG9fUi9zaW1ib2xvczEucG5nKQ0KIA0KVW4gdGVtYSBhY3R1YWwgcXVlIG5vcyBwZXJtaXRlIGV2aWRlbmNpYXIgY2xhcmFtZW50ZSBlc3RlIHRpcG8gZGUgbWFwYSBzb24gbG9zIGNhc29zIGRlIENvdmlkLTE5IGNvbmZpcm1hZG9zIGVuIGVsIHBhw61zLiBBIGNvbnRpbnVhY2nDs24sIHNlIG11ZXN0cmEgZXN0ZSBlamVtcGxvIHF1ZSByZWFsaXrDsyBlbCBbVElFTVBPXShodHRwczovL3d3dy5lbHRpZW1wby5jb20vZGF0b3MvY29yb25hdmlydXMtZW4tY29sb21iaWEtY2Fzb3MtYWN0dWFsaXphZG9zLXktY29uZmlybWFkb3MtNDcxNjUwKQ0KDQohW0NvdmlkLTE5IGVuIENvbG9tYmlhXShDOi9Vc2Vycy91c2VyL0RvY3VtZW50cy9JbnRyb190b19SL2NvdmlkMi5wbmcpDQoNCiANCiMgMi4zLiBNYXBhIGlzYXLDrXRtaWNvIG8gZGUgY29udG9ybm8uIA0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCiBMb3MgbWFwYXMgZGUgaXNvbMOtbmVhcyBzb24gdW5vcyBkZSBsb3MgbcOhcyB1c2Fkb3MgcGFyYSBsYSByZXByZXNlbnRhY2nDs24gZGUgaW5mb3JtYWNpw7NuIGN1YW50aXRhdGl2YSwgZW4gcGFydGljdWxhciBjdWFuZG8gc2UgdHJhdGEgZGUgdmFyaWFibGVzIGNvbnRpbnVhcy4gU2UgdXRpbGl6YSBoYWJpdHVhbG1lbnRlIHBhcmEgcmVwcmVzZW50YXIgY2FtcG9zIGVzY2FsYXJlcyB5IGNvbnN0aXR1eWUgdW5hIGZvcm1hIG11eSBlZmVjdGl2YSBkZSBpbmNvcnBvcmFyIGVzdGEgaW5mb3JtYWNpw7NuIGVuIHVuIG1hcGEsIHlhIHF1ZSBwdWVkZSBjb21iaW5hcnNlIGNvbiBvdHJvcyB0aXBvcyBkZSBtYXBhcyB5IGRlIGluZm9ybWFjacOzbiwgZGViaWRvIGEgcXVlLCBhbCByZXByZXNlbnRhcnNlIMO6bmljYW1lbnRlIG1lZGlhbnRlIGzDrW5lYXMsIHBlcm1pdGUgbGEgcHJlc2VuY2lhIGRlIG90cm9zIGVsZW1lbnRvcyBkZW50cm8gZGVsIG1hcGEgc2luIHJlc3VsdGFyIG9ic3RydXNpdmEuDQpVbiBtYXBhIGRlIGlzb2zDrW5lYXMgZXN0w6EgZm9ybWFkbyBwb3IgdW4gY29uanVudG8gZGUgbMOtbmVhcywgY2FkYSB1bmEgZGUgbGFzIGN1YWxlcyB1bmUgcHVudG9zIHF1ZSBwcmVzZW50YW4gZWwgbWlzbW8gdmFsb3IgZGUgbGEgdmFyaWFibGUuIEVzdGFzIGzDrW5lYXMgbm8gcHVlZGVuIGNydXphcnNlLCB5YSBxdWUgZWxsbyBzaWduaWZpY2Fyw61hIHF1ZSBlbiB1biBwdW50byBzZSBwcmVzZW50YW4gZG9zIHZhbG9yZXMNCkVzdG9zIG1hcGFzIHRhbWJpw6luIHB1ZWRlbiBtb3N0cmFyIHZhbG9yZXMgdHJpZGltZW5zaW9uYWxlcywgY29tbyBsYSBlbGV2YWNpw7NuLCBlbiBtYXBhcyB0b3BvZ3LDoWZpY29zLiBFbiBnZW5lcmFsLCBsb3MgZGF0b3MgcGFyYSBtYXBhcyBpc2Fyw610bWljb3Mgc2UgcmVjb3BpbGFuIGEgdHJhdsOpcyBkZSBwdW50b3MgbWVkaWJsZXMgKHBvciBlamVtcGxvLCBlc3RhY2lvbmVzIG1ldGVvcm9sw7NnaWNhcykgbyBzZSByZWNvcGlsYW4gcG9yIMOhcmVhIChwb3IgZWplbXBsbywgdG9uZWxhZGFzIGRlIG1hw616IHBvciBhY3JlIHBvciBjb25kYWRvKS4gTG9zIG1hcGFzIGlzYXLDrXRtaWNvcyB0YW1iacOpbiBzaWd1ZW4gbGEgcmVnbGEgYsOhc2ljYSBkZSBxdWUgaGF5IGxhZG9zIGFsdG9zIHkgYmFqb3MgZW4gcmVsYWNpw7NuIGNvbiBsYSBpc29sw61uZWEuIFBvciBlamVtcGxvLCBlbiBlbGV2YWNpw7NuLCBzaSBsYSBpc29saW5hIGVzIGRlIDUwMCBwaWVzLCBlbnRvbmNlcyB1biBsYWRvIGRlYmUgc2VyIG3DoXMgYWx0byBxdWUgNTAwIHBpZXMgeSB1biBsYWRvIGRlYmUgc2VyIG3DoXMgYmFqby4NCg0KQSBjb250aW51YWNpw7NuLCBzZSBtdWVzdHJhIHVuIGVqZW1wbG8gZGUgZXN0ZSB0aXBvIGRlIG1hcGFzIHRvbWFkbyBkZSBsYSBsZWN0dXJhIGRlIFtWaWN0b3IgT2xheWEuRWwgbWFwYSB5IGxhIGNvbXVuaWNhY2nDs24gY2FydG9ncsOhZmljYV0oaHR0cHM6Ly92b2xheWEuZ2l0aHViLmlvL2xpYnJvLXNpZy9jaGFwdGVycy9NYXBhcy5odG1sKQ0KDQohW0VqZW1wbG8gbWFwYSBpc29sw61uZWFzXShDOi9Vc2Vycy91c2VyL0RvY3VtZW50cy9JbnRyb190b19SL2lzby5wbmcpDQoNCg0KIyAyLjQuIE1hcGEgZGUgcHVudG9zLg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCkVzIHVuIG1hcGEgcXVlIHV0aWxpemEgcHVudG9zIHBhcmEgbW9zdHJhciBsYSBwcmVzZW5jaWEgZGUgdW4gdGVtYSB5IG1vc3RyYXIgdW4gcGF0csOzbiBlc3BhY2lhbC4gVW4gcHVudG8gcHVlZGUgcmVwcmVzZW50YXIgdW5hIHVuaWRhZCBvIHZhcmlhcywgZGVwZW5kaWVuZG8gZGUgbG8gcXVlIHNlIGVzdMOpIHJlcHJlc2VudGFuZG8uDQpBIGNvbnRpbnVhY2nDs24sIHNlIG11ZXN0cmEgdW4gZWplbXBsbyBkZSBlc3RlIHRpcG8gZGUgbWFwYXMgdG9tYWRvIGRlIGxhIGxlY3R1cmEgZGUgW1ZpY3RvciBPbGF5YS5FbCBtYXBhIHkgbGEgY29tdW5pY2FjacOzbiBjYXJ0b2dyw6FmaWNhXShodHRwczovL3ZvbGF5YS5naXRodWIuaW8vbGlicm8tc2lnL2NoYXB0ZXJzL01hcGFzLmh0bWwpDQoNCiFbRWplbXBsbyBtYXBhIGRlIHB1bnRvc10oQzovVXNlcnMvdXNlci9Eb2N1bWVudHMvSW50cm9fdG9fUi9wdW50by5wbmcpDQoNCg0KIyAzLiBEYXRvcy4gDQogPGRpdiBzdHlsZT0gInRleHQtYWxpZ246IGp1c3RpZnkiPg0KUGFyYSBlc3RlIGN1YWRlcm5vIHNlIHZhbiBhIHV0aWxpemFyIGxvcyBkYXRvcyBzb2JyZSAqKk5lY2VzaWRhZGVzIELDoXNpY2FzIEluc2F0aXNmZWNoYXMgKE5CSSkqKi4gUGVybyBwcmltZXJvIGVzIG5lY2VzYXJpbyBleHBsaWNhciBhIHF1w6kgc2UgcmVmaWVyZSBOQkkuIA0KU2Vnw7puIGVsIERBTkUsIGxhIG1ldG9kb2xvZ8OtYSBkZSBOQkkgYnVzY2EgZGV0ZXJtaW5hciwgY29uIGF5dWRhIGRlIGFsZ3Vub3MgaW5kaWNhZG9yZXMgc2ltcGxlcywgc2kgbGFzIG5lY2VzaWRhZGVzIGLDoXNpY2FzIGRlIGxhIHBvYmxhY2nDs24gc2UgZW5jdWVudHJhbiBjdWJpZXJ0YXMuIExvcyBncnVwb3MgcXVlIG5vIGFsY2FuY2VuIHVuIHVtYnJhbCBtw61uaW1vIGZpamFkbywgc29uIGNsYXNpZmljYWRvcyBjb21vIHBvYnJlcy4gUG9yIGxvIHRhbnRvLCBsYSBtZXRvZG9sb2fDrWEgZGUgbGFzIE5CSSB0b21hIGVuIGN1ZW50YSBzaSBsb3MgaG9nYXJlcyBoYW4gc2F0aXNmZWNobyBsYSBzZXJpZSBkZSBuZWNlc2lkYWRlcyBlc3RhYmxlY2lkYXMsIGNvbnNpZGVyYW5kbyBwb2JyZXMgYSBhcXVlbGxvcyBxdWUgbm8gbG8gaGFuIGxvZ3JhZG8uICBMb3MgaW5kaWNhZG9yZXMgc2ltcGxlcyBzZWxlY2Npb25hZG9zLCBzb246IFZpdmllbmRhcyBpbmFkZWN1YWRhcywgVml2aWVuZGFzIGNvbiBoYWNpbmFtaWVudG8gY3LDrXRpY28sIFZpdmllbmRhcyBjb24gc2VydmljaW9zIGluYWRlY3VhZG9zLCBWaXZpZW5kYXMgY29uIGFsdGEgZGVwZW5kZW5jaWEgZWNvbsOzbWljYSwgVml2aWVuZGFzIGNvbiBuacOxb3MgZW4gZWRhZCBlc2NvbGFyIHF1ZSBubyBhc2lzdGVuIGEgbGEgZXNjdWVsYS4NCkxhIG1lZGlkYSBkZSBsYSBwb2JyZXphIHBvciBlbCBtw6l0b2RvIGRlIE5lY2VzaWRhZGVzIELDoXNpY2FzIEluc2F0aXNmZWNoYXMgKE5CSSkgaGEgdmVuaWRvIHNpZW5kbyB1dGlsaXphZGEgcGFyYSBwcm9ww7NzaXRvcyBkZSBkaWFnbsOzc3RpY28gc29jaWFsLiBUZW5pZW5kbyBlbiBjdWVudGEgcXVlIGxhIHBvYnJlemEgZXMgdW4gZmVuw7NtZW5vIG11bHRpZGltZW5zaW9uYWwgeSBjb21wbGVqbyBxdWUgbm8gcHVlZGUgc2VyIGNhcHRhZG8gZW4gc3UgdG90YWxpZGFkIHBvciB1bmEgc29sYSBtZWRpZGEsIHNlIHB1ZWRlIGFmaXJtYXIgcXVlIGxhIG1lZGlkYSBkZSBOQkkgZXMgY29tcGxlbWVudGFyaWEgYSBsYSBkZSBsw61uZWEgZGUgcG9icmV6YSB5IG5vIHRpZW5lIGNvbW8gcHJldGVuc2nDs24gc3VzdGl0dWlybGEsIG5pIHNlcnZpciBkZSBhcHJveGltYWNpw7NuIGEgbG9zIHJlc3VsdGFkb3MgcHJvdmlzdG9zIHBvciBlbGxhLiBTdSBjYW1wbyBkZSBldmFsdWFjacOzbiBlcyBlbCBkZSBsb3MgYmllbmVzIHkgc2VydmljaW9zIHJlcXVlcmlkb3MgcGFyYSBsYSBzYXRpc2ZhY2Npw7NuIGRlIG5lY2VzaWRhZGVzIGLDoXNpY2FzIHkgbm8gZWwgZGUgbG9zIGluZ3Jlc29zLg0KDQpBZGljaW9uYWxtZW50ZSwgY3VhbnRvIG3DoXMgYWx0byBzZWEgZWwgbsO6bWVybyBkZWwgTkJJLCBtYXlvcmVzIG5lY2VzaWRhZGVzIHN1ZnJlIGxhIHBvYmxhY2nDs24gZW4gZXN0dWRpbyB5IG3DoXMgZ3JhdmUgc2Vyw6EgbGEgcHJvYmxlbcOhdGljYSBkZSBkaWNobyBtdW5pY2lwaW8uDQoNClBvciBvdHJhIHBhcnRlLCBsb3MgbWFwYXMgdGVtw6F0aWNvcyBzb24gw7p0aWxlcyBwYXJhIHRyYW5zbWl0aXIgaW5mb3JtYWNpw7NuIGRlbW9ncsOhZmljYS4gU2UgcHVlZGVuIGV4cGxvcmFyIHZhcmlvcyBtYXBhcyB0ZW3DoXRpY29zIGRlIERBTkUgdXRpbGl6YW5kbyBlc3RlIGVubGFjZS5bREFORV0oaHR0cHM6Ly93d3cuZGFuZS5nb3YuY28vaW5kZXgucGhwL2VzdGFkaXN0aWNhcy1wb3ItdGVtYS9kZW1vZ3JhZmlhLXktcG9ibGFjaW9uL2NlbnNvLW5hY2lvbmFsLWRlLXBvYmxhY2lvbi15LXZpdmVuZGEtMjAxOC9oZXJyYW1pZW50YXMvbWFwYXMtdGVtYXRpY29zLWNucHYpDQpBbnRlcmlvcm1lbnRlLCBzZSBkZXNjYXJnw7MgZWwgYXJjaGl2byBOQkksIGVuIGZvcm1hdG8gLnhsc3gsIGEgbWkgY29tcHV0YWRvci4gTHVlZ28sIHNlIHV0aWxpesOzIEV4Y2VsIHBhcmEgZWxpbWluYXIgZGF0b3MgZGUgbXVuaWNpcGlvcyBubyB1YmljYWRvcyBkZW50cm8gZGVsIERlcGFydGFtZW50byBkZSBOb3J0ZSBkZSBTYW50YW5kZXIuIFRhbWJpw6luICJzZSBsaW1waWFyb24iIGxvcyBkYXRvcywgZXMgZGVjaXIsIHNlIGVsaW1pbmFyb24gdmFyaWFzIGZpbGFzIGNvbiBpbcOhZ2VuZXMgaW5zdGl0dWNpb25hbGVzIG8gc2luIGluZm9ybWFjacOzbi4gRXN0YXMgZmlsYXMgc2UgdWJpY2Fyb24gdGFudG8gYWwgcHJpbmNpcGlvIGNvbW8gYWwgZmluYWwgZGVsIGFyY2hpdm8gb3JpZ2luYWwuICBTZSBtYW50aWVuZW4gbGFzIGNvbHVtbmFzIHF1ZSBzZSByZWZpZXJlbiBhIHRvZG8gZWwgbXVuaWNpcGlvIChlcyBkZWNpciwgc2UgZWxpbWluYXJvbiBsYXMgY29sdW1uYXMgY29ycmVzcG9uZGllbnRlcyBhICJjYWJlY2VyYSIgeSAiem9uYSBydXJhbCIpLiBMdWVnbywgc2UgZ3VhcmRhcm9uIGxvcyBkYXRvcyByZXN1bHRhbnRlcywgY29ycmVzcG9uZGllbnRlcyBzb2xvIGEgbXVuaWNpcGlvcyBkZSBOb3J0ZSBkZSBTYW50YW5kZXIgY29tbyBDTlBWLTIwMTgtTkJJLnhsc3guIEx1ZWdvLCBzZSBndWFyZMOzIGVsIGFyY2hpdm8gZW4gbGEgY2FycGV0YSBkZWwgY29tcHV0YWRvciBxdWUgc2UgbGxhbWEgSW50cm8tdG8tUi4NCg0KIyA0LiBQcmVwYXJhY2nDs24uDQoNClByaW1lcm8sIHNlIGxpbXBpYSBsYSBtZW1vcmlhDQpgYGB7cn0NCnJtKGxpc3QgPSBscygpKQ0KYGBgDQpBaG9yYSwgc2UgaW5zdGFsYW4geSBzZSBjYXJnYW4gbGFzIGxpYnJlcsOtYXMgcXVlIG5lY2VzaXRhbW9zLiANCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShyZ2VvcykNCmxpYnJhcnkocmFzdGVyKQ0KbGlicmFyeShzZikNCmxpYnJhcnkoY2FydG9ncmFwaHkpDQoNCmBgYA0KDQojIDUuIExlZXIgZGF0b3MgZGUgTkJJDQogPGRpdiBzdHlsZT0gInRleHQtYWxpZ246IGp1c3RpZnkiPg0KUHJpbWVybywgc2UgZGViZSBsZWVyIGVsIGFyY2hpdm8gcXVlIGNvbnRpZW5lIGxhcyBlc3RhZMOtc3RpY2FzIG11bmljaXBhbGVzIGFncm9wZWN1YXJpYXMgcGFyYSBlbCBkZXBhcnRhbWVudG8gZGUgTm9ydGUgZGUgU2FudGFuZGVyLiANCmBgYHtyfQ0KbmJpIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL3VzZXIvRG9jdW1lbnRzL0ludHJvX3RvX1IvQ05QVi0yMDE4LU5CSS54bHN4IikNCmBgYA0KDQpWZWFtb3MgbG9zIGF0cmlidXRvcyBkZSBsb3MgZGF0b3M6IA0KDQpgYGB7cn0NCmhlYWQobmJpKQ0KYGBgDQoNCkFob3JhLCBzZSB2YSBhIHZlciBjdcOhbCBlcyBlbCBtdW5pY2lwaW8gY29uIGVsIG1heW9yIHBvcmNlbnRhamUgZGUgTkJJOg0KYGBge3J9DQpuYmkgJT4lDQogIHNsaWNlKHdoaWNoLm1heChOQkkpKSAtPiBtYXhfbmJpDQoNCm1heF9uYmkNCmBgYA0KDQpUYW1iacOpbiwgZW5jb250cmFyIGN1w6FsIGVzIGVsIG11bmljaXBpbyBjb24gbWVub3IgcG9yY2VudGFqZSBkZSBOQkk6DQpgYGB7cn0NCm5iaSAlPiUNCiAgc2xpY2Uod2hpY2gubWluKE5CSSkpIC0+IG1pbl9uYmkNCg0KbWluX25iaQ0KYGBgDQoNCg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCkVzdG9zIGRhdG9zIGRlIG3DoXhpbW8geSBtw61uaW1vLCBub3MgcGVybWl0ZW4gc2FiZXIgcXVlIGxvcyBtdW5pY2lwaW9zIGRlIA0KQSBjb250aW51YWNpw7NuLCBzZSB2YW4gYSBvcmRlbmFyIGxvcyBtdW5pY2lwaW9zIHBvciBOQkkgZW4gb3JkZW4gZGVzY2VuZGVudGU6DQoNCmBgYHtyfQ0KbmJpICU+JQ0KICBhcnJhbmdlKGRlc2MoTkJJKSkgLT4gZGVzY19uYmkNCg0KZGVzY19uYmkNCmBgYA0KDQoNCiMgNi4gVW5pciBkYXRvcyBkZSBOQkkgYSBtdW5pY2lwaW9zLiANCiA8ZGl2IHN0eWxlPSAidGV4dC1hbGlnbjoganVzdGlmeSI+DQpZYSBzZSB0aWVuZW4gZGVzY2FyZ2Fkb3MgbG9zIG11bmljaXBpb3MgZGUgTm9ydGUgZGUgU2FudGFuZGVyLiBTZSB2YW4gYSBsZWVyIGVzdG9zIGRhdG9zIHVzYW5kbyBsYSBsaWJyZXLDrWEgKnNmKjoNCmBgYHtyfQ0KbXVuaWMgPC0gc3RfcmVhZCgiQzovVXNlcnMvdXNlci9Eb2N1bWVudHMvTm9ydGUgZGUgU2FudGFuZGVyLzU0X05PUlRFIERFIFNBTlRBTkRFUi9BRE1JTklTVFJBVElWTy9NR05fTVBJT19QT0xJVElDTy5zaHAiKQ0KYGBgDQoNCk1pcmVtb3MgcXXDqSBoYXkgZGVudHJvIGRlbCBhdHJpYnV0byAqKk1QSU9fQ0NER08qKiB5ICoqTVBJT19DTk1CUioqOg0KYGBge3J9DQpoZWFkKG11bmljJE1QSU9fQ0NER08pDQpgYGANCg0KYGBge3J9DQpoZWFkKG11bmljJE1QSU9fQ05NQlIpDQpgYGANCiA8ZGl2IHN0eWxlPSAidGV4dC1hbGlnbjoganVzdGlmeSI+DQpQYXJhIHJlYWxpemFyIGxhIHVuacOzbiBlbnRyZSBsb3MgbXVuaWNpcGlvcyB5IGxvcyBkYXRvcyBkZSBOQkksIHNlIHZhIGEgdXRpbGl6YXIgbGEgZnVuY2nDs24gKmxlZnRfam9pbiouDQoNCmBgYHtyfQ0KbmJpX211bmljID0gbGVmdF9qb2luKG11bmljLCBuYmksICBieT0gYygiTVBJT19DQ0RHTyI9IkNPRElHTyIpKQ0KYGBgDQoNCmBgYHtyfQ0KbmJpX211bmljICU+JQ0KICBkcGx5cjo6c2VsZWN0KE1VTklDSVBJTywgTVBJT19DQ0RHTywgTkJJKSAgLT4gY2hlY2tfbmJpX211bmljDQoNCmhlYWQoY2hlY2tfbmJpX211bmljKQ0KYGBgDQoNCkFob3JhLCBzZSB2YW4gYSByZXByb3llY3RhciBsb3MgbXVuaWNpcGlvczoNCmBgYHtyfQ0KbmJpX211bmljX25ldyA8LSBzdF90cmFuc2Zvcm0obmJpX211bmljLCBjcnMgPSAzMTE2KQ0KYGBgDQoNCg0KIyA3LiBFamVtcGxvcyBkZSBtYXBhcyB0ZW3DoXRpY29zLg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCg0KUGFyYSByZWFsaXphciBsb3MgbWFwYXMgdGVtw6F0aWNvcyBzZSB2YSBhIHV0aWxpemFyIGxhIGxpYnJlcsOtYSAqY2FydG9ncmFwaHkqIHF1ZSB0aWVuZSBjb21vIG9iamV0aXZvIG9idGVuZXIgbWFwYXMgdGVtw6F0aWNvcyBjb24gbGEgY2FsaWRhZCB2aXN1YWwgZGUgbG9zIHF1ZSBzZSBjb25zdHJ1eWVuIGVuIHVuIHNvZnR3YXJlIGRlIG1hcGVvIG8gZW4gdW4gU0lHLiBFc3RhIGxpYnJlcsOtYSBkZSAqY2FydG9ncmFwaHkqIHVzYSBvYmpldG9zICpzZiogbyAqc3AqIHBhcmEgcHJvZHVjaXIgbG9zIGdyw6FmaWNvcyBiYXNlLiBFbCBmb3JtYXRvIHByZWZlcmlkbyBwYXJhIGxvcyBvYmpldG9zIGVzcGFjaWFsZXMgZXMgKlNmKi4NCg0KIyA3LjEuIE1hcGEgYmFzZSBkZSBPcGVuU3RyZWV0TWFwIHkgc8OtbWJvbG9zIHByb3BvcmNpb25hbGVzLg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCkxhcyBmdW5jaW9uZXMgKipnZXRUaWxlcygpKiogeSAqKnRpbGVzTGF5ZXIoKSoqIGRlc2NhcmdhbiB5IG11ZXN0cmFuIGxvcyBtb3NhaWNvcyBkZSBPcGVuU3RyZWV0TWFwLiANCkxhIGZ1bmNpw7NuICoqcHJvcFN5bWJvbHNMYXllcigpKiogbXVlc3RyYSBzw61tYm9sb3MgY29uIMOhcmVhcyBwcm9wb3JjaW9uYWxlcyBhIHVuYSB2YXJpYWJsZSBjdWFudGl0YXRpdmEsIGNvbW8gbGFzIE5CSS4gRXhpc3RlbiB2YXJpb3Mgc8OtbWJvbG9zIGRpc3BvbmlibGVzIGNvbW8gY8OtcmN1bG9zLCBjdWFkcmFkb3MgeSBiYXJyYXMuIEVsIGFyZ3VtZW50byBwdWxnYWRhcyAoaW5jaGVzKSBzZSB1dGlsaXphIHBhcmEgcGVyc29uYWxpemFyIGxvcyB0YW1hw7FvcyBkZSBsb3Mgc8OtbWJvbG9zLiANCg0KYGBge3J9DQptdW4ub3NtIDwtIGdldFRpbGVzKA0KICB4PSBuYmlfbXVuaWNfbmV3LA0KICB0eXBlID0gIk9wZW5TdHJlZXRNYXAiLA0KICB6b29tID0gOCwNCiAgY2FjaGVkaXIgPSBUUlVFLA0KICBjcm9wID0gRkFMU0UNCikNCmBgYA0KYGBge3J9DQpvcGFyIDwtIHBhcihtYXIgPSBjKDAsMCwxLjIsMCkpDQp0aWxlc0xheWVyKHggPSBtdW4ub3NtKQ0KcGxvdChzdF9nZW9tZXRyeShuYmlfbXVuaWNfbmV3KSwgY29sID0gTkEsIGJvcmRlciA9ICJncmV5IiwgYWRkID0gVFJVRSkNCnByb3BTeW1ib2xzTGF5ZXIoDQogIHggPSBuYmlfbXVuaWNfbmV3LA0KICB2YXIgPSAiTkJJIiwNCiAgaW5jaGVzID0gMC4xNSwNCiAgY29sID0gImJyb3duNCIsDQogIGxlZ2VuZC5wb3MgPSAidG9wcmlnaHQiLA0KICBsZWdlbmQudGl0bGUudHh0ID0gIlRvdGFsIE5CSSINCiAgKQ0KDQpsYXlvdXRMYXllcih0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIE5CSSBlbiBOb3J0ZSBkZSBTYW50YW5kZXIiLA0KICAgICAgICAgICAgc291cmNlcyA9ICJGdWVudGVzOiBEQU5FLCAyMDE4L27CqSBPcGVuU3RyZWV0TWFwIiwNCiAgICAgICAgICAgIGF1dGhvciA9ICJBbmEgTWFyw61hIE1vbnRhw7FvIiwNCiAgICAgICAgICAgIGZyYW1lID0gVFJVRSwgbm9ydGggPSBGQUxTRSwgdGFidGl0bGUgPSBUUlVFKQ0KDQpub3J0aChwb3MgPSAidG9wbGVmdCIpDQpgYGANCiA8ZGl2IHN0eWxlPSAidGV4dC1hbGlnbjoganVzdGlmeSI+DQpHcmFjaWFzIGFsIG1hcGEgYW50ZXJpb3IsIHNlIHB1ZWRlIHNhYmVyIGN1w6FudG8gZXMgZWwgTkJJIGVuIGNhZGEgbXVuaWNpcGlvLCBkZWJpZG8gYWwgdGFtYcOxbyBkZWwgY8OtcmN1bG8uIEVuIGVzdGUgY2FzbywgZWwgbWF5b3IgTkJJIHRvdGFsIGVzIGRlIDUwLCBxdWUgY29ycmVzcG9uZGUgYWwgY8OtcmN1bG8gZGUgbWF5b3IgdGFtYcOxbyB5IGFsIG11bmljaXBpbyBkZSBFbCBUYXJyYSwgbWllbnRyYXMgcXVlIGVsIGPDrXJjdWxvIGRlIG1lbm9yIHRhbWHDsW8gcHJlc2VudGEgdW4gTkJJIGRlIDksIHF1ZSBjb3JyZXNwb25kZSBhbCBtdW5pY2lwaW8gZGUgUGFtcGxvbmEuIEVzdG9zIHPDrW1ib2xvcyB0YW1iacOpbiBub3MgcGVybWl0ZW4gaGFjZXIgdW4gYW7DoWxpc2lzIHLDoXBpZG8sIGRlIGPDs21vIGVzdMOhbiBkaXN0cmlidWlkYXMgbGFzIG5lY2VzaWRhZGVzIGLDoXNpY2FzIGluc2F0aXNmZWNoYXMgZW4gZWwgZGVwYXJ0YW1lbnRvIGRlIE5vcnRlIGRlIFNhbnRhbmRlciwgeSBzYWJlciBkZSDDqXN0YSBtYW5lcmEgY29tbyBvcmllbnRhciBsYXMgc29sdWNpb25lcyBhIGVzdGFzIG5lY2VzaWRhZGVzLiANCg0KQWhvcmEsIHNlIHZhIGEgcmVhbGl6YXIgZWwgbWlzbW8gbWFwYSwgcGVybyBleHBlcmltZW50YW5kbyB1biBwb2NvIGNvbiBlbCBjb2xvciwgZWwgdGFtYcOxbyBkZSBsb3MgY8OtcmN1bG9zIChzw61tYm9sb3MpLCBsYXMgbcOhcmdlbmVzIHkgZWwgY29sb3IgZGVsIGJvcmRlIGRlbCBkZXBhcnRhbWVudG8uDQoNCmBgYHtyfQ0KbXVuLm9zbSA8LSBnZXRUaWxlcygNCiAgeD0gbmJpX211bmljX25ldywNCiAgdHlwZSA9ICJPcGVuU3RyZWV0TWFwIiwNCiAgem9vbSA9IDgsDQogIGNhY2hlZGlyID0gVFJVRSwNCiAgY3JvcCA9IEZBTFNFDQopDQpgYGANCmBgYHtyfQ0Kb3BhciA8LSBwYXIobWFyID0gYygyLDMsMi41LDEpKQ0KdGlsZXNMYXllcih4ID0gbXVuLm9zbSkNCnBsb3Qoc3RfZ2VvbWV0cnkobmJpX211bmljX25ldyksIGNvbCA9IE5BLCBib3JkZXIgPSAiYmxhY2siLCBhZGQgPSBUUlVFKQ0KcHJvcFN5bWJvbHNMYXllcigNCiAgeCA9IG5iaV9tdW5pY19uZXcsDQogIHZhciA9ICJOQkkiLA0KICBpbmNoZXMgPSAwLjEwLA0KICBjb2wgPSAiI0E2Q0FFMCIsDQogIGxlZ2VuZC5wb3MgPSAidG9wcmlnaHQiLA0KICBsZWdlbmQudGl0bGUudHh0ID0gIlRvdGFsIE5CSSINCiAgKQ0KDQpsYXlvdXRMYXllcih0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIE5CSSBlbiBOb3J0ZSBkZSBTYW50YW5kZXIiLA0KICAgICAgICAgICAgc291cmNlcyA9ICJGdWVudGVzOiBEQU5FLCAyMDE4L27CqSBPcGVuU3RyZWV0TWFwIiwNCiAgICAgICAgICAgIGF1dGhvciA9ICJBbmEgTWFyw61hIE1vbnRhw7FvIiwNCiAgICAgICAgICAgIGZyYW1lID0gVFJVRSwgbm9ydGggPSBGQUxTRSwgdGFidGl0bGUgPSBUUlVFKQ0KDQpub3J0aChwb3MgPSAidG9wbGVmdCIpDQpgYGANCg0KVGFtYmnDqW4sIHNlIHB1ZWRlbiBjYW1iaWFyIGxvcyBzw61tYm9sb3MsIGRlIGPDrXJjdWxvcyBhIGN1YWRyYWRvcywgbyBhIGJhcnJhcy4gDQoNCmBgYHtyfQ0Kb3BhciA8LSBwYXIobWFyID0gYygyLDMsMi41LDEpKQ0KdGlsZXNMYXllcih4ID0gbXVuLm9zbSkNCnBsb3Qoc3RfZ2VvbWV0cnkobmJpX211bmljX25ldyksIGNvbCA9IE5BLCBib3JkZXIgPSAic2t5Ymx1ZSIsIGFkZCA9IFRSVUUpDQpwcm9wU3ltYm9sc0xheWVyKA0KICB4ID0gbmJpX211bmljX25ldywNCiAgdmFyID0gIk5CSSIsDQogIGluY2hlcyA9IDAuMTUsDQogIHN5bWJvbHMgPSAic3F1YXJlIiwNCiAgY29sID0gInBlcnUiLA0KICBsZWdlbmQucG9zID0gInRvcHJpZ2h0IiwNCiAgbGVnZW5kLnRpdGxlLnR4dCA9ICJUb3RhbCBOQkkiDQogICkNCg0KbGF5b3V0TGF5ZXIodGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBOQkkgZW4gTm9ydGUgZGUgU2FudGFuZGVyIiwNCiAgICAgICAgICAgIHNvdXJjZXMgPSAiRnVlbnRlczogREFORSwgMjAxOC9uwqkgT3BlblN0cmVldE1hcCIsDQogICAgICAgICAgICBhdXRob3IgPSAiQW5hIE1hcsOtYSBNb250YcOxbyIsDQogICAgICAgICAgICBmcmFtZSA9IFRSVUUsIG5vcnRoID0gRkFMU0UsIHRhYnRpdGxlID0gVFJVRSkNCg0Kbm9ydGgocG9zID0gInRvcGxlZnQiKQ0KYGBgDQoNCmBgYHtyfQ0Kb3BhciA8LSBwYXIobWFyID0gYygyLDMsMi41LDEpKQ0KdGlsZXNMYXllcih4ID0gbXVuLm9zbSkNCnBsb3Qoc3RfZ2VvbWV0cnkobmJpX211bmljX25ldyksIGNvbCA9IE5BLCBib3JkZXIgPSAicHVycGxlIiwgYWRkID0gVFJVRSkNCnByb3BTeW1ib2xzTGF5ZXIoDQogIHggPSBuYmlfbXVuaWNfbmV3LA0KICB2YXIgPSAiTkJJIiwNCiAgaW5jaGVzID0gMC4zLA0KICBzeW1ib2xzID0gImJhciIsDQogIGNvbCA9ICIjQTZDQUUwIiwNCiAgbGVnZW5kLnBvcyA9ICJ0b3ByaWdodCIsDQogIGxlZ2VuZC50aXRsZS50eHQgPSAiVG90YWwgTkJJIg0KICApDQoNCmxheW91dExheWVyKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgTkJJIGVuIE5vcnRlIGRlIFNhbnRhbmRlciIsDQogICAgICAgICAgICBzb3VyY2VzID0gIkZ1ZW50ZXM6IERBTkUsIDIwMTgvbsKpIE9wZW5TdHJlZXRNYXAiLA0KICAgICAgICAgICAgYXV0aG9yID0gIkFuYSBNYXLDrWEgTW9udGHDsW8iLA0KICAgICAgICAgICAgZnJhbWUgPSBUUlVFLCBub3J0aCA9IEZBTFNFLCB0YWJ0aXRsZSA9IFRSVUUpDQoNCm5vcnRoKHBvcyA9ICJ0b3BsZWZ0IikNCmBgYA0KDQpBZGljaW9uYWxtZW50ZSwgY2FiZSBtZW5jaW9uYXIgcXVlIGVuIGxhIHJlYWxpemFjacOzbiBkZSBjYWRhIG1hcGEgdGVtw6F0aWNvIGhheSB1bmEgc2VyaWUgZGUgcGFzb3MgcGFyYSBzdSBjb25zdHJ1Y2Npw7NuOg0KDQoqKi0gU2UgZXN0YWJsZWNlbiBsYXMgbcOhcmdlbmVzLioqDQoNCioqLSBTZSB0cmF6YW4gbGFzIGZyb250ZXJhcyBkZSBsb3MgbXVuaWNpcGlvcy4gKioNCg0KKiotIFNlIHBsb3RlYW4gbG9zIGRhdG9zIGRlIE5CSTogKipBY8OhIHNlIGluY2x1eWUgbGEgcG9zaWNpw7NuIHkgZWwgdGV4dG8gZGUgbGEgbGV5ZW5kYSwgZWwgY29sb3IgZGVsIG1hcGEsIGVsIGNvbG9yIGRlIGxvcyBib3JkZXMsIGVsIHRhbWHDsW8gZGUgbG9zIHPDrW1ib2xvcyB5ICBlbCBub21icmUgZGUgbGEgdmFyaWFibGUuDQoNCioqLSBJbmZvcm1hY2nDs24gZGUgbGEgY2FwYSBleHRlcm5hOioqIEFjw6Egc2UgaW5jbHV5ZW4gZGF0b3MgY29tbyBlbCB0w610dWxvLCBsYXMgZnVlbnRlcyBkZSBsYSBpbmZvcm1hY2nDs24sIGVsIGF1dG9yLCB5IHNpIHNlIGRlc2VhIGNvbG9jYXIgZWwgbm9ydGUuDQoNCioqLSBGbGVjaGEgZGVsIG5vcnRlOioqIFNlIGluZGljYSBsYSBwb3NpY2nDs24gZG9uZGUgc2UgZGVzZWEgY29sb2NhciBsYSBmbGVjaGEgcXVlIGluZGljYSBlbCBub3J0ZSBlbiBlbCBtYXBhLiANCg0KIyA3LjIuIE1hcGFzIGRlIGNvcm9wbGV0YXMuDQogPGRpdiBzdHlsZT0gInRleHQtYWxpZ246IGp1c3RpZnkiPg0KRW4gbG9zIG1hcGFzIGRlIGNvcm9wbGV0YXMsIGxhcyDDoXJlYXMgc2Ugc29tYnJlYW4gZGUgYWN1ZXJkbyBjb24gbGEgdmFyaWFjacOzbiBkZSB1bmEgdmFyaWFibGUgY3VhbnRpdGF0aXZhLCBxdWUgZW4gZXN0ZSBjYXNvLCBjb3JyZXNwb25kZSBhIGxvcyBkYXRvcyBkZSBOQkkuIEVzdG9zIG1hcGFzIHNlIHVzYW4gcHJpbmNpcGFsbWVudGUsIHBhcmEgcmVwcmVzZW50YXIgcmF6b25lcyBvIMOtbmRpY2VzLiBMYSBmdW5jacOzbiAqKmNob3JvTGF5ZXIoKSoqIG11ZXN0cmEgbWFwYXMgZGUgY29yb3BsZXRhcy4gTG9zIGFyZ3VtZW50b3MgKm5jbGFzcyosICptZXRob2QqIHkgKmJyZWFrcyogcGVybWl0ZW4gcGVyc29uYWxpemFyIGxhIGNsYXNpZmljYWNpw7NuIHZhcmlhYmxlLiBMYSBmdW5jacOzbiAqKmdldEJyZWFrcygpKiogcGVybWl0ZSBjbGFzaWZpY2FyIGZ1ZXJhIGRlIGxhIGZ1bmNpw7NuIG1pc21hLiBMYXMgcGFsZXRhcyBkZSBjb2xvcmVzIHNlIGRlZmluZW4gY29uICpjb2wqIHkgc2UgcHVlZGUgY3JlYXIgdW4gY29uanVudG8gZGUgY29sb3JlcyBjb24gKipjYXJ0by5wYWwoKSoqLiBTZSBjb25zdWx0YSB0YW1iacOpbiAqKmRpc3BsYXkuY2FydG8uYWxsKiouDQoNCmBgYHtyfQ0Kb3BhciA8LSBwYXIobWFyID0gYygwLDAsMS4yLDApKQ0KDQpwYXIoYmc9ICJncmV5OTAiKQ0KDQpwbG90KHN0X2dlb21ldHJ5KG5iaV9tdW5pY19uZXcpLCBjb2w9IE5BLCBib3JkZXIgPSBOQSwgYmcgPSAiI2FhZGFmZiIpDQoNCmNob3JvTGF5ZXIoDQogIHggPSBuYmlfbXVuaWNfbmV3LA0KICB2YXIgPSAiTkJJIiwNCiAgbWV0aG9kID0gImdlb20iLA0KICBuY2xhc3MgPSA1LA0KICBjb2wgPSBjYXJ0by5wYWwocGFsMSA9ICJzYW5kLnBhbCIsIG4xID0gNSksDQogIGJvcmRlciA9ICJ3aGl0ZSIsDQogIGx3ZCA9IDAuNSwNCiAgbGVnZW5kLnBvcyA9ICJ0b3ByaWdodCIsDQogIGxlZ2VuZC50aXRsZS50eHQgPSAiTkJJIiwNCiAgYWRkID0gVFJVRQ0KICApDQoNCmxheW91dExheWVyKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgTkJJIGVuIE5vcnRlIGRlIFNhbnRhbmRlciIsDQogICAgICAgICAgIHNvdXJjZXMgPSAiRnVlbnRlOiBEQU5FLCAyMDE4IiwNCiAgICAgICAgICAgYXV0aG9yID0gIkFuYSBNYXLDrWEgTW9udGHDsW8iLA0KICAgICAgICAgICBmcmFtZSA9IFRSVUUsIG5vcnRoID0gVFJVRSwgdGFidGl0bGUgPSBUUlVFLCBjb2wgPSAiYmxhY2siKQ0KDQpub3J0aChwb3MgPSAidG9wbGVmdCIpDQpgYGANCiA8ZGl2IHN0eWxlPSAidGV4dC1hbGlnbjoganVzdGlmeSI+DQpBIGNvbnRpbnVhY2nDs24sIHNlIHZhIGEgcmVhbGl6YXIgbnVldmFtZW50ZSB1biBtYXBhIGRlIGNvcm9wbGV0YXMsIHBlcm8gZXhwZXJpbWVudGFuZG8gY29uIG51ZXZhcyBwYWxldGFzIGRlIGNvbG9yZXMsIG90cm8gY29sb3IgZGUgYm9yZGUsIGVsIG7Dum1lcm8gZGUgY2xhc2VzIHBhcmEgbGEgY2xhc2lmaWNhY2nDs24sIG90cm8gY29sb3IgZGUgZm9uZG8geSBkaXN0aW50byBncm9zb3IgZGUgbGFzIGzDrW5lYXMgKGdyYWNpYXMgYWwgY29tYW5kbyBsd2QpLg0KDQoNCmBgYHtyfQ0Kb3BhciA8LSBwYXIobWFyID0gYygwLDAsMS4yLDApKQ0KDQpwYXIoYmc9ICJncmF5NzciKQ0KDQpwbG90KHN0X2dlb21ldHJ5KG5iaV9tdW5pY19uZXcpLCBjb2w9IE5BLCBib3JkZXIgPSBOQSwgYmcgPSAiI0UzREVCRiIpDQoNCmNob3JvTGF5ZXIoDQogIHggPSBuYmlfbXVuaWNfbmV3LA0KICB2YXIgPSAiTkJJIiwNCiAgbWV0aG9kID0gImdlb20iLA0KICBuY2xhc3MgPSA3LA0KICBjb2wgPSBjYXJ0by5wYWwocGFsMSA9ICJoYXJtby5wYWwiLCBuMSA9IDcpLA0KICBib3JkZXIgPSAiYmxhY2siLA0KICBsd2QgPSAyLA0KICBsZWdlbmQucG9zID0gInRvcGxlZnQiLA0KICBsZWdlbmQudGl0bGUudHh0ID0gIk5CSSIsDQogIGFkZCA9IFRSVUUNCiAgKQ0KDQpsYXlvdXRMYXllcih0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIE5CSSBlbiBOb3J0ZSBkZSBTYW50YW5kZXIiLA0KICAgICAgICAgICBzb3VyY2VzID0gIkZ1ZW50ZTogREFORSwgMjAxOCIsDQogICAgICAgICAgIGF1dGhvciA9ICJBbmEgTWFyw61hIE1vbnRhw7FvIiwNCiAgICAgICAgICAgZnJhbWUgPSBUUlVFLCBub3J0aCA9IFRSVUUsIHRhYnRpdGxlID0gVFJVRSwgY29sID0gImJsYWNrIikNCg0Kbm9ydGgocG9zID0gInRvcGxlZnQiKQ0KYGBgDQogPGRpdiBzdHlsZT0gInRleHQtYWxpZ246IGp1c3RpZnkiPg0KRW4gZXN0ZSBtYXBhLCBzZSBtdWVzdHJhIGVsIE5CSSBwb3IgbXVuaWNpcGlvLCBiYXPDoW5kb3NlIGVuIHVuYSBlc2NhbGEgZGUgY29sb3JlcyBxdWUgZGV0ZXJtaW5hbiByYW5nb3MgZGUgdmFsb3JlcyAoOSAtIDUwKSwgZmFjaWxpdGFuZG8gbGEgY2xhc2lmaWNhY2nDs24geSBhbsOhbGlzaXMgZGUgZGF0b3MuIEVuIGVzdGUgY2FzbywgZWwgbWFwYSBkZSBjb3JvcGxldGFzIHNlIHVzYSBwYXJhIHJlcHJlc2VudGFyIGxhIHZhcmlhYmxlIGN1YW50aXRhdGl2YSBOQkksIGRvbmRlIGNhZGEgY29sb3Igc2VjdWVuY2lhbCByZXByZXNlbnRhIHVuIHJhbmdvIGRlIHZhbG9yZXMuIFNpcnZlbiBwYXJhIG9ic2VydmFyIGVsIGNyZWNpbWllbnRvIGRlIGVzdGEgdmFyaWFibGUgZW4gY2FkYSBtdW5pY2lwaW8sIHlhIHF1ZSBhcXVlbGxvcyBxdWUgc2UgdmVuIGNvbiB0b25hbGlkYWRlcyBtw6FzIG9zY3VyYXMgdGllbmVuIG3DoXMgcHJvYmxlbcOhdGljYXMgcmVsYWNpb25hZGFzIGEgcG9icmV6YSwgeSBhIGVzdG9zIG11bmljaXBpb3MsIGVsIGdvYmllcm5vIGRlYmUgcHJvcG9yY2lvbmFybGUgc29sdWNpb25lcyB5IG9yaWVudGFyIHBvbMOtdGljYXMgcXVlIHBlcm1pdGVuIHN1cGxpciBsYXMgbmVjZXNpZGFkZXMgYsOhc2ljYXMgcXVlIG5vIGVzdMOhbiBzaWVuZG8gc2F0aXNmZWNoYXMsIGNvbW8gdW5hIHZpdmllbmRhIGRpZ25hLCBzZXJ2aWNpb3MgbmVjZXNhcmlvcywgZXZpdGFuZG8gYSBzdSB2ZXogc2l0dWFjaW9uZXMgZGUgaGFjaW5hbWllbnRvIHkgbWlzZXJpYS4gDQpBZGVtw6FzLCBlbiBlbCBwcmltZXIgbWFwYSBzZSB0b21hbiA1IGNsYXNlcyBwYXJhIGRpdmlkaXIgbG9zIHZhbG9yZXMsIHkgZW4gZWwgc2VndW5kbyBzZSBhdW1lbnRhbiBhIDcgY2xhc2VzLCBsb2dyYW5kbyB1bmEgZGl2aXNpw7NuIG3DoXMgZXhoYXVzdGl2YSBkZSBsb3MgZGF0b3MgZGUgZXN0YSB2YXJpYWJsZSBjdWFudGl0YXRpdmEuIA0KDQojIDcuMy4gU8OtbWJvbG9zIHByb3BvcmNpb25hbGVzIHkgbWFwYSBkZSB0aXBvbG9nw61hLiANCg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCkxhIGZ1bmNpw7NuICoqcHJvcFN5bWJvbHNUeXBvTGF5ZXIoKSoqIGNyZWEgdW4gbWFwYSBkZSBzw61tYm9sb3MgcXVlIHNvbiBwcm9wb3JjaW9uYWxlcyBhIGxvcyB2YWxvcmVzIGRlIHVuYSBwcmltZXJhIHZhcmlhYmxlIHkgY29sb3JlYWRvcyBwYXJhIHJlZmxlamFyIGxhcyBtb2RhbGlkYWRlcyBkZSB1bmEgc2VndW5kYSB2YXJpYWJsZSBjdWFsaXRhdGl2YS4gU2UgdXRpbGl6YSB1bmEgY29tYmluYWNpw7NuIGRlIGFyZ3VtZW50b3MgKipwcm9wU3ltYm9sc0xheWVyKCkqKiB5ICoqdHlwb0xheWVyKCkqKi4NClBhcmEgZXN0bywgcHJpbWVybyBzZSBkZWJlIGNyZWFyIHVuYSB2YXJpYWJsZSBjdWFsaXRhdGl2YSwgcGFyYSBwb2RlcmxhIHJlbGFjaW9uYXIgY29uIGxhIHZhcmlhYmxlIGN1YW50aXRhdGl2YSBlbiBlc3R1ZGlvIChOQkkpLiBTZSB1c2EgbGEgZnVuY2nDs24gKiptdXRhdGUqKiBwYXJhIGhhY2VyIGVzdGEgdGFyZWEuIA0KDQpgYGB7cn0NCm5iaV9tdW5pY18yIDwtIGRwbHlyOjptdXRhdGUobmJpX211bmljX25ldywgcG9icmV6YSA9IGlmZWxzZShNSVNFUklBID4gMjAsICJFeHRyZW1vIiwgaWZlbHNlKEhBQ0lOQU1JRU5UTyA+IDUsICJBbHRvIiwgIkludGVybWVkaW8iKSkpDQpgYGANCg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NClRlbmdhIGVuIGN1ZW50YSBxdWUgZWwgbnVldm8gYXRyaWJ1dG8gc2UgbGxhbWEgKipwb2JyZXphKiouIFN1IHZhbG9yIGRlcGVuZGUgZGUgbG9zIHZhbG9yZXMgdW1icmFsIGRlZmluaWRvcy4gSGF5IHF1ZSBhc2VndXJhcnNlIGRlIHZlcmlmaWNhciBsYSBzaW50YXhpcyBkZWwgY29tYW5kbyAqaWZlbHNlKiBwYXJhIGNvbXByZW5kZXIgcXXDqSBlc3TDoSBzdWNlZGllbmRvLiANCg0KYGBge3J9DQpoZWFkKG5iaV9tdW5pY18yKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShzZikNCmxpYnJhcnkoY2FydG9ncmFwaHkpDQoNCm9wYXIgPC0gcGFyKG1hciA9IGMoMCwwLDEuMiwwKSkNCg0KcGxvdChzdF9nZW9tZXRyeShuYmlfbXVuaWNfMiksIGNvbCA9ICIjZjJlZmU5IiwgYm9yZGVyPSIjYjM4ZTQzIiwgYmcgPSAiI2FhZDNkZiIsIGx3ZCA9IDAuNSkNCg0KcHJvcFN5bWJvbHNUeXBvTGF5ZXIoDQogIHg9IG5iaV9tdW5pY18yLA0KICB2YXIgPSAiTkJJIiwNCiAgaW5jaGVzID0gMC4zLA0KICBzeW1ib2xzID0gInNxdWFyZSIsDQogIGJvcmRlciA9ICJ3aGl0ZSIsDQogIGx3ZCA9IDAuNSwNCiAgbGVnZW5kLnZhci5wb3MgPSAibGVmdCIsDQogIGxlZ2VuZC52YXIudGl0bGUudHh0ID0gIk5CSSIsDQogIHZhcjIgPSAicG9icmV6YSIsDQogIGxlZ2VuZC52YXIyLnZhbHVlcy5vcmRlciA9IGMoIkV4dHJlbW8iLCAiQWx0byIsICJJbnRlcm1lZGlvIiksDQogIGNvbCA9IGNhcnRvLnBhbChwYWwxID0gIm11bHRpLnBhbCIsIG4xPSAzKSwNCiAgbGVnZW5kLnZhcjIucG9zID0gInJpZ2h0IiwNCiAgbGVnZW5kLnZhcjIudGl0bGUudHh0ID0gIlBvYnJlemEiDQopDQoNCmxheW91dExheWVyKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgTkJJIGVuIE5vcnRlIGRlIFNhbnRhbmRlciIsDQogICAgICAgICAgICBhdXRob3IgPSAiQW5hIE1hcsOtYSBNb250YcOxbyIsDQogICAgICAgICAgICBzb3VyY2VzID0gIkZ1ZW50ZTogREFORSwgMjAxOCIsDQogICAgICAgICAgICBzY2FsZSA9IDEsIHRhYnRpdGxlID0gVFJVRSwgZnJhbWUgPSBUUlVFKQ0KDQpub3J0aChwb3MgPSAidG9wbGVmdCIpDQpgYGANCiA8ZGl2IHN0eWxlPSAidGV4dC1hbGlnbjoganVzdGlmeSI+DQpFbiBlc3RlIG1hcGEsIHNlIGhhbiBkZWZpbmlkbyB1bWJyYWxlcyBwYXJhIGNsYXNpZmljYXIgbGEgcG9icmV6YSBlbiB0cmVzIGNsYXNlczogZXh0cmVtYSwgYWx0YSBlIGludGVybWVkaWEuIFNlIHB1ZWRlIGlkZW50aWZpY2FyIGbDoWNpbG1lbnRlIGVuIGVsIG1hcGEsIGxvcyBtdW5pY2lwaW9zIHF1ZSBtw6FzIHNlIHZlbiBhZmVjdGFkb3MgcG9yIGxhIHBvYnJlemEsIHkgYXF1ZWxsb3MgcXVlIHRvZGF2w61hIG5vIHByZXNlbnRhbiB2YWxvcmVzIGNyw610aWNvcy4gRXN0YXMgY2xhc2VzIHNlIHJlY29ub2NlbiBwb3IgZWwgY29sb3IgeSBlbCB0YW1hw7FvIGRlbCBjdWFkcmFkbyBlcyBwcm9wb3JjaW9uYWwgYWwgdmFsb3IgZGVsIE5CSS4gDQoNCkEgY29udGludWFjacOzbiwgc2UgbXVlc3RyYSBlbCBtaXNtbyBtYXBhIHBlcm8gY2FtYmnDoW5kb2xlIGFsZ3VuYXMgY2FyYWN0ZXLDrXN0aWNhcy4gDQpgYGB7cn0NCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KGNhcnRvZ3JhcGh5KQ0KDQpvcGFyIDwtIHBhcihtYXIgPSBjKDAsMCwxLjIsMCkpDQoNCnBsb3Qoc3RfZ2VvbWV0cnkobmJpX211bmljXzIpLCBjb2wgPSAiI2YyZWZlOSIsIGJvcmRlcj0iZGFya2JsdWUiLCBiZyA9ICJsaWdodHllbGxvdyIsIGx3ZCA9IDEuNSkNCg0KcHJvcFN5bWJvbHNUeXBvTGF5ZXIoDQogIHg9IG5iaV9tdW5pY18yLA0KICB2YXIgPSAiTkJJIiwNCiAgaW5jaGVzID0gMC4zLA0KICBzeW1ib2xzID0gImJhciIsDQogIGJvcmRlciA9ICJibGFjayIsDQogIGx3ZCA9IDAuNSwNCiAgbGVnZW5kLnZhci5wb3MgPSAibGVmdCIsDQogIGxlZ2VuZC52YXIudGl0bGUudHh0ID0gIk5CSSIsDQogIHZhcjIgPSAicG9icmV6YSIsDQogIGxlZ2VuZC52YXIyLnZhbHVlcy5vcmRlciA9IGMoIkV4dHJlbW8iLCAiQWx0byIsICJJbnRlcm1lZGlvIiksDQogIGNvbCA9IGNhcnRvLnBhbChwYWwxID0gInBpbmsucGFsIiwgbjE9IDMpLA0KICBsZWdlbmQudmFyMi5wb3MgPSAidG9wcmlnaHQiLA0KICBsZWdlbmQudmFyMi50aXRsZS50eHQgPSAiUG9icmV6YSINCikNCg0KbGF5b3V0TGF5ZXIodGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBOQkkgZW4gTm9ydGUgZGUgU2FudGFuZGVyIiwNCiAgICAgICAgICAgIGF1dGhvciA9ICJBbmEgTWFyw61hIE1vbnRhw7FvIiwNCiAgICAgICAgICAgIHNvdXJjZXMgPSAiRnVlbnRlOiBEQU5FLCAyMDE4IiwNCiAgICAgICAgICAgIHNjYWxlID0gMSwgdGFidGl0bGUgPSBUUlVFLCBmcmFtZSA9IFRSVUUpDQoNCm5vcnRoKHBvcyA9ICJ0b3BsZWZ0IikNCmBgYA0KDQoNCg0KIyA3LjQuIE1hcGFzIGRlIGV0aXF1ZXRhcy4gDQoNCiA8ZGl2IHN0eWxlPSAidGV4dC1hbGlnbjoganVzdGlmeSI+DQpFbiDDqXN0ZSBtYXBhIHNlIHZhbiBhIGNvbWJpbmFyIGxhcyBmdW5jaW9uZXMgKipjaG9yb0xheWVyKCkqKiB5ICoqbGFiZWxMYXllcigpKiouDQoNCmBgYHtyfQ0KbGlicmFyeShzZikNCmxpYnJhcnkoY2FydG9ncmFwaHkpDQpvcGFyIDwtIHBhcihtYXIgPSBjKDAsMCwxLjIsMCkpDQoNCnBhcihiZz0gImdyZXkyNSIpDQpwbG90KHN0X2dlb21ldHJ5KG5iaV9tdW5pY18yKSwgY29sPSAiI2U0ZTlkZSIsIGJvcmRlciA9ICJkYXJrc2VhZ3JlZW40IiwNCiAgICAgYmcgPSAiZ3JleTc1IiwgbHdkID0gMC41KQ0KDQpjaG9yb0xheWVyKA0KICB4ID0gbmJpX211bmljX25ldywNCiAgdmFyID0gIk5CSSIsDQogIG1ldGhvZCA9ICJnZW9tIiwNCiAgbmNsYXNzID0gNSwNCiAgY29sID0gY2FydG8ucGFsKHBhbDEgPSAic2FuZC5wYWwiLCBuMSA9IDUpLA0KICBib3JkZXIgPSAid2hpdGUiLA0KICBsd2QgPSAwLjUsDQogIGxlZ2VuZC5wb3MgPSAidG9wcmlnaHQiLA0KICBsZWdlbmQudGl0bGUudHh0ID0gIk5CSSIsDQogIGFkZCA9IFRSVUUNCikNCg0KbGFiZWxMYXllcigNCiAgeD0gbmJpX211bmljXzIsDQogIHR4dCA9ICJNVU5JQ0lQSU8iLA0KICBjb2wgPSAid2hpdGUiLA0KICBjZXggPSAwLjQsDQogIGZvbnQgPSA0LA0KICBoYWxvID0gVFJVRSwNCiAgYmcgPSAiZ3JleTI1IiwNCiAgciA9IDAuMSwNCiAgb3ZlcmxhcCA9IEZBTFNFLA0KICBzaG93LmxpbmVzID0gRkFMU0UNCikNCg0KbGF5b3V0TGF5ZXIoDQogIHRpdGxlID0gIk11bmljaXBpb3MgZGUgTm9ydGUgZGUgU2FudGFuZGVyIiwNCiAgc291cmNlcyA9ICJGdWVudGU6IERBTkUsIDIwMTgiLA0KICBhdXRob3IgPSAiQW5hIE1hcsOtYSBNb250YcOxbyIsDQogIGZyYW1lID0gVFJVRSwNCiAgbm9ydGggPSBUUlVFLCANCiAgdGFidGl0bGUgPSBUUlVFLA0KICB0aGVtZSA9ICJ0YXVwZS5wYWwiDQopDQpgYGANCg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCiANCkVuIGVzdGUgbWFwYSB0YW1iacOpbiBzZSB1c2FuIGVzY2FsYXMgZGUgY29sb3JlcyBwYXJhIGluZGljYXIgcmFuZ29zIGRlIHZhbG9yZXMgZGUgTkJJLiBBIGRpZmVyZW5jaWEgZGUgbG9zIGFudGVyaW9yZXMgbGFzIGV0aXF1ZXRhcyBub3MgcHJvcG9yY2lvbmFuIGxhIGluZm9ybWFjacOzbiB2aXN1YWwgZGUgZm9ybWEgbcOhcyByw6FwaWRhIGUgaW5tZWRpYXRhLCBwZXJtaXRpZW5kbyByZXNwb25kZXIgcHJlZ3VudGFzIGNvbW8gwr9jdcOhbCBlcyBlbCBtdW5pY2lwaW8gY29uIG1heW9yIE5CST8uIFVuYSByZXNwdWVzdGEgcGFyYSBlc3RvIGVzOiBFbCBtdW5pY2lwaW8gZGUgRWwgVGFycmEsIHBvcnF1ZSBwcmVzZW50YSBsYSBjb2xvcmFjacOzbiBhbWFyaWxsYSBtw6FzIG9zY3VyYSwgeSBzZSBlbmN1ZW50cmEgZW4gZWwgcmFuZ28gZGUgNTAuDQoNCiMgKipFTCBUQVJSQSoqDQogPGRpdiBzdHlsZT0gInRleHQtYWxpZ246IGp1c3RpZnkiPg0KUGFyYSBjb250ZXh0dWFsaXphciB1biBwb2NvLEVsIFRhcnJhLCBlcyB1biBtdW5pY2lwaW8gY29sb21iaWFubyB1YmljYWRvIGVuIGVsIGRlcGFydGFtZW50byBkZSBOb3J0ZSBkZSBTYW50YW5kZXIuIEVzdMOhIGEgdW5hIGFsdGl0dWQgZGUgMjcwIG0ucy5uLm0sIHRpZW5lIHVuYSBleHRlbnNpw7NuIGRlIDY3NWttMiB5IGxpbWl0YSBhbCBub3J0ZSB5IG9yaWVudGUgY29uIFRpYsO6LCBhbCBzdXIgY29uIFNhbiBDYWxpeHRvIHkgYWwgb2NjaWRlbnRlIGNvbiBUZW9yYW1hLiBUaWVuZSB1bmEgcG9ibGFjacOzbiBkZSAxMjc2NiBoYWJpdGFudGVzLCBkZSBsb3MgY3VhbGVzIDk0OTggcmVzaWRlbiBlbiBsYSB6b25hIHVyYmFuYSB5IDMyNjggZW4gbGEgcnVyYWwuIA0KU2UgZW5jdWVudHJhIGEgMTU5a20gZGUgQ8O6Y3V0YSAobGEgY2FwaXRhbCBkZWwgZGVwYXJ0YW1lbnRvKS4gDQpTZWfDum4gTGEgRGVmZW5zb3LDrWEgZGVsIFB1ZWJsbywgMjAwNiwgZWwgbXVuaWNpcGlvIGRlIEVsIFRhcnJhIHBlcnRlbmVjZSBhIGxhIHJlZ2nDs24gZGVsIENhdGF0dW1ibywgeSBhY3R1YWxtZW50ZSBsb3MgbXVuaWNpcGlvcyBxdWUgY29uZm9ybWFuIGVzdGEgcmVnacOzbiBwcmVzZW50YW4gKiphbHRvcyDDrW5kaWNlcyBkZSBwb2JyZXphKiogKG3DoXMgZGVsIDUzJSBkZSBsYSBwb2JsYWNpw7NuIGRlIEVsIFRhcnJhLCBIYWNhcsOtIHkgU2FuIENhbGl4dG8gc2UgZW5jdWVudHJhbiBiYWpvIGxhIGzDrW5lYSBkZSBwb2JyZXphKSwgZWwgKipOQkkqKiwgc3VwZXJhIGVsIDUzJSB5IHByZXNlbnRhbiBtdXkgYmFqYSBjb2JlcnR1cmEgZW4gc2VydmljaW9zIHDDumJsaWNvcy4gU8OzbG8gZWwgMjclIGRlIGxhIHBvYmxhY2nDs24gZGVsIENhdGF0dW1ibyB0aWVuZSBjb2JlcnR1cmEgZGUgYWd1YSBwb3RhYmxlLiAuIA0KQWRlbcOhcywgZXN0YSByZWdpw7NuIGRlbCBDYXRhdHVtYm8gZXMgYWx0YW1lbnRlIHZ1bG5lcmFibGUgeWEgcXVlIGxhIGRpc3B1dGEgcG9yIGVsIHRlcnJpdG9yaW8geSBsb3MgcmVjdXJzb3MgbmF0dXJhbGVzIHBvciBwYXJ0ZSBkZSBsb3MgYWN0b3JlcyBhcm1hZG9zIGFsIG1hcmdlbiBkZSBsYSBsZXksIGRlc2RlIGhhY2UgbXVjaG9zIGHDsW9zLCBoYSBkZXNlc3RhYmlsaXphZG8gbGEgcmVnacOzbi4gVGFtYmnDqW4sICBsYSB2aW9sYWNpw7NuIGRlIGRlcmVjaG9zIGh1bWFub3MgcG9yIGxvcyBncnVwb3MgYXJtYWRvcyBhbA0KbWFyZ2VuIGRlIGxhIGxleSwgc2UgdHJhZHVjZSBlbiB1biBncmFuIG7Dum1lcm8gZGUgbWFzYWNyZXMsIGFzZXNpbmF0b3MNCnNlbGVjdGl2b3MsIGRlc3BsYXphbWllbnRvIGZvcnphZG8sIHJlc3RyaWNjacOzbiBhIGxhIGxpYmVydGFkIGRlIG1vdmlsaXphY2nDs24sDQpww6lyZGlkYSBkZWwgdGVycml0b3JpbywgYW1lbmF6YSBhbCBhbWJpZW50ZSBzYW5vIHkgdmlvbGFjacOzbiBkZSBvdHJvcyBkZXJlY2hvcw0KY29sZWN0aXZvcw0KDQpBIGNvbnRpbnVhY2nDs24sIHNlIHJlYWxpemEgZWwgbWlzbW8gbWFwYSBwZXJvIGNvbiBkaXN0aW50b3MgY29sb3JlcyBlbiBlbCBtYXBhIHkgZW4gZWwgZm9uZG8sIGF1bWVudG8gZWwgdGFtYcOxbyBkZSBsYSBsZXRyYSB5IHNlIGNhbWJpYSBsYSBwb3NpY2nDs24gZGUgbGEgbGV5ZW5kYS4gDQoNCmBgYHtyfQ0KbGlicmFyeShzZikNCmxpYnJhcnkoY2FydG9ncmFwaHkpDQpvcGFyIDwtIHBhcihtYXIgPSBjKDAsMCwxLjIsMCkpDQoNCnBhcihiZz0gImdyZXkyNSIpDQpwbG90KHN0X2dlb21ldHJ5KG5iaV9tdW5pY18yKSwgY29sPSAiI2U0ZTlkZSIsIGJvcmRlciA9ICJkYXJrc2VhZ3JlZW40IiwNCiAgICAgYmcgPSAibGlnaHRncmVlbiIsIGx3ZCA9IDAuNSkNCg0KY2hvcm9MYXllcigNCiAgeCA9IG5iaV9tdW5pY19uZXcsDQogIHZhciA9ICJOQkkiLA0KICBtZXRob2QgPSAiZ2VvbSIsDQogIG5jbGFzcyA9IDcsDQogIGNvbCA9IGNhcnRvLnBhbChwYWwxID0gIm9yYW5nZS5wYWwiLCBuMSA9IDcpLA0KICBib3JkZXIgPSAid2hpdGUiLA0KICBsd2QgPSAwLjUsDQogIGxlZ2VuZC5wb3MgPSAibGVmdCIsDQogIGxlZ2VuZC50aXRsZS50eHQgPSAiTkJJIiwNCiAgYWRkID0gVFJVRQ0KKQ0KDQpsYWJlbExheWVyKA0KICB4PSBuYmlfbXVuaWNfMiwNCiAgdHh0ID0gIk1VTklDSVBJTyIsDQogIGNvbCA9ICJ3aGl0ZSIsDQogIGNleCA9IDAuNiwNCiAgZm9udCA9IDQsDQogIGhhbG8gPSBUUlVFLA0KICBiZyA9ICJncmV5MjUiLA0KICByID0gMC4xLA0KICBvdmVybGFwID0gRkFMU0UsDQogIHNob3cubGluZXMgPSBGQUxTRQ0KKQ0KDQpsYXlvdXRMYXllcigNCiAgdGl0bGUgPSAiTXVuaWNpcGlvcyBkZSBOb3J0ZSBkZSBTYW50YW5kZXIiLA0KICBzb3VyY2VzID0gIkZ1ZW50ZTogREFORSwgMjAxOCIsDQogIGF1dGhvciA9ICJBbmEgTWFyw61hIE1vbnRhw7FvIiwNCiAgZnJhbWUgPSBUUlVFLA0KICBub3J0aCA9IFRSVUUsIA0KICB0YWJ0aXRsZSA9IFRSVUUsDQogIHRoZW1lID0gInRhdXBlLnBhbCINCikNCmBgYA0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCiANClNlIHB1ZWRlIG9ic2VydmFyIHF1ZSBzaSBhdW1lbnRhbW9zIGVsIG7Dum1lcm8gZGUgY2xhc2VzLCBsb3MgcmFuZ29zIGRlIGNvbG9yZXMsIHNlIHB1ZWRlbiBhbmFsaXphciBsb3MgZGF0b3MgY29uIG1heW9yIGRldGFsbGUgeWEgcXVlIGV4aXN0ZSBtw6FzIGRpZmVyZW5jaWFjacOzbiBkZSBsb3MgdmFsb3JlcyBkZSBOQkkgcGFyYSBjYWRhIG11bmljaXBpby4gQWRlbcOhcywgZ3JhY2lhcyBhIGxhcyBldGlxdWV0YXMgc2UgcHVlZGUgaWRlbnRpZmljYXIgY29uIGZhY2lsaWRhZCBhIHF1ZSBtdW5pY2lwaW8gY29ycmVzcG9uZGUgY2FkYSB2YWxvciBkZSBOQkkuIA0KDQoNCiMgNy41LiBNYXBhcyBkZSBpc29wbGV0YXMuIA0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCiBMb3MgbWFwYXMgZGUgaXNvcGxldGFzIHNlIGJhc2FuIGVuIGVsIHN1cHVlc3RvIGRlIHF1ZSBlbCBmZW7Ds21lbm8gYSByZXByZXNlbnRhciB0aWVuZSB1bmEgZGlzdHJpYnVjacOzbiBjb250aW51YS4gRXN0b3MgbWFwYXMgdXRpbGl6YW4gdW4gZW5mb3F1ZSBkZSBtb2RlbGFkbyBkZSBpbnRlcmFjY2nDs24gZXNwYWNpYWwgcXVlIHRpZW5lIGNvbW8gb2JqZXRpdm8gY2FsY3VsYXIgaW5kaWNhZG9yZXMgYmFzYWRvcyBlbiB2YWxvcmVzIGRlIHN0b2NrIHBvbmRlcmFkb3MgcG9yIGRpc3RhbmNpYS4gUGVybWl0ZSB1bmEgcmVwcmVzZW50YWNpw7NuIGVzcGFjaWFsIGRlbCBmZW7Ds21lbm8gaW5kZXBlbmRpZW50ZSBkZSBsYSBoZXRlcm9nZW5laWRhZCBpbmljaWFsIGRlIGxhIGRpdmlzacOzbiB0ZXJyaXRvcmlhbC4gU2UgdXNhIGxhIGZ1bmNpw7NuICoqc21vb3RoTGF5ZXIoKSoqIHF1ZSBkZXBlbmRlIGVuIGdyYW4gbWVkaWRhIGRlbCBwYXF1ZXRlIFNwYXRpYWxQb3NpdGlvbi4gRXN0YSBmdW5jacOzbiB1dGlsaXphIHVuYSBjYXBhIGRlIHB1bnRvcyBtYXJjYWRvcyB5IHVuIGNvbmp1bnRvIGRlIHBhcsOhbWV0cm9zICh1bmEgZnVuY2nDs24gZGUgaW50ZXJhY2Npw7NuIGVzcGFjaWFsIHkgc3VzIHBhcsOhbWV0cm9zKSB5IG11ZXN0cmEgdW5hIGNhcGEgZGUgbWFwYSBpc29wbGV0YS4NClBhcmEgcmVhbGl6YXIgZXN0ZSBtYXBhLCBzZSB1dGlsaXphcsOhIG90cm8gY29uanVudG8gZGUgZGF0b3MuIEVuIGVzdGUgY2Fzbywgc2UgdGVuZHLDoW4gZW4gY3VlbnRhIGxvcyBkYXRvcyBzb2JyZSBsYSBwcm9kdWNjacOzbiBkZSBhcnJveiBlbiAyMDE4LCBwYXJhIGVsIGRlcGFydGFtZW50byBkZSBOb3J0ZSBkZSBTYW50YW5kZXIuIEVsIGFycm96IGVzIGVsIHNlZ3VuZG8gY3VsdGl2byBjb24gbWF5b3Igw6FyZWEgc2VtYnJhZGEgZW4gZWwgZGVwYXJ0YW1lbnRvLCBkZXNwdcOpcyBkZWwgY2Fmw6kuIA0KU2UgbGVlIGVsIGNvbmp1bnRvIGRlIGRhdG9zOiANCg0KYGBge3J9DQpjcm9wczIwMTggIDwtICByZWFkX2V4Y2VsKCJDOi9Vc2Vycy91c2VyL0RvY3VtZW50cy9Ob3J0ZSBkZSBTYW50YW5kZXIvRVZBM19OT1JURURFU0FOVEFOREVSLnhsc3giKQ0KDQpgYGANCg0KYGBge3J9DQpoZWFkKGNyb3BzMjAxOCkNCmBgYA0KDQpBaG9yYSwgc2UgdmFuIGEgZmlsdHJhciBsYXMgZmlsYXMgcXVlIHJlcHJlc2VudGFuIHNvbG8gZGF0b3MgZGUgYXJyb3o6DQoNCmBgYHtyfQ0KY3JvcHMyMDE4ICU+JQ0KICBmaWx0ZXIoQ1VMVElWTyA9PSAiQVJST1oiKSAtPiBhcnJvejIwMTgNCmBgYA0KDQpgYGB7cn0NCmhlYWQoYXJyb3oyMDE4KQ0KYGBgDQoNCkx1ZWdvLCBzZSB2YSBhIGNyZWFyIHVuIG51ZXZvIGF0cmlidXRvIHF1ZSBjb2luY2lkZSBjb24gbG9zIGPDs2RpZ29zIGRlIG11bmljaXBpb3M6DQoNCmBgYHtyfQ0KYXJyb3oyMDE4JFRFTVAgPC0gYXMuY2hhcmFjdGVyKGFycm96MjAxOCRDT0RfTVVOKQ0KYGBgDQoNCmBgYHtyfQ0KaGVhZChhcnJvejIwMTgpDQpgYGANCg0KYGBge3J9DQphcnJvejIwMTgkTVBJT19DQ0RHTyA8LSBhcy5mYWN0b3IoYXJyb3oyMDE4JFRFTVApDQpgYGANCg0KSGFjZXIgbGEgdW5pw7NuOg0KYGBge3J9DQphcnJvel9tdW5pYyA9IGxlZnRfam9pbihtdW5pYywgYXJyb3oyMDE4LCBieSA9ICJNUElPX0NDREdPIikNCmBgYA0KDQpgYGB7cn0NCmhlYWQoYXJyb3pfbXVuaWMpDQpgYGANCg0KUmVwcm95ZWNjacOzbiBkZSBsb3MgbXVuaWNpcGlvczoNCmBgYHtyfQ0KcmVwX2Fycm96IDwtIHN0X3RyYW5zZm9ybShhcnJvel9tdW5pYywgY3JzID0gMzExNikNCmBgYA0KDQpFcyBtb21lbnRvIGRlIGhhY2VyIGVsIG1hcGE6DQoNCmBgYHtyfQ0Kb3BhciA8LSBwYXIobWFyID0gYygwLDAsMS4yLDApKQ0KDQpwbG90KHN0X2dlb21ldHJ5KHJlcF9hcnJveiksIGNvbD0gTkEsIGJvcmRlciA9ICJibGFjayIsIGJnID0gImdyZXk3NSIpDQoNCnNtb290aExheWVyKA0KICB4ID0gcmVwX2Fycm96LA0KICB2YXIgPSAgIlByb2R1Y2Npb24iLA0KICB0eXBlZmN0ID0gImV4cG9uZW50aWFsIiwNCiAgc3BhbiA9IDE1MDAwLA0KICBiZXRhID0gMiwNCiAgbmNsYXNzID0gOCwNCiAgY29sID0gY2FydG8ucGFsKHBhbDEgPSAidHVycXVvaXNlLnBhbCIsIG4xPSA4KSwNCiAgYm9yZGVyID0gImdyZXkiLA0KICBsd2QgPSAwLjEsDQogIG1hc2sgPSByZXBfYXJyb3osDQogIGxlZ2VuZC52YWx1ZXMucm5kID0gMCwNCiAgbGVnZW5kLnRpdGxlLnR4dCA9ICAiUHJvZHVjY2lvbiIsDQogIGxlZ2VuZC5wb3MgPSAidG9wcmlnaHQiLA0KICBhZGQgPSBUUlVFDQopDQoNCnRleHQoeCA9IDY1MDAwMCwgeT0gMTIwMDAwMCwgY2V4ID0gMSwgYWRqID0gMCwgZm9udCA9IDMsIGxhYmVscyA9ICJGdW5jacOzbiBkaXN0YW5jaWE6XG4tIHR5cGUgPSBleHBvbmVudGlhbFxuLSBiZXRhID0gMlxuLSBzcGFuID0gMTUga20iKQ0KDQpsYXlvdXRMYXllcih0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIGxhIHByb2R1Y2Npw7NuIGRlIGFycm96IGVuIE5vcnRlIGRlIFNhbnRhbmRlciIsDQogICAgICAgICAgICBzb3VyY2VzID0gIkZ1ZW50ZTogREFORSBZIE1BRFIsIDIwMTgiLA0KICAgICAgICAgICAgYXV0aG9yID0gIkFuYSBNYXLDrWEgTW9udGHDsW8iLA0KICAgICAgICAgICAgZnJhbWUgPSBGQUxTRSwgbm9ydGggPSBGQUxTRSwgdGFidGl0bGUgPSBUUlVFLCB0aGVtZSA9ICJ0dXJxdW9pc2UucGFsIikNCg0Kbm9ydGgocG9zID0gInRvcGxlZnQiKQ0KDQpgYGANCg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCiBQYXJhIGVzdGUgbWFwYSBzZSB1dGlsaXphbiBsb3MgZGF0b3MgZGUgcHJvZHVjY2nDs24gZGUgYXJyb3ogcGFyYSBlbCBkZXBhcnRhbWVudG8gZGUgTm9ydGUgZGUgU2FudGFuZGVyLiBTZSBwdWVkZSBvYnNlcnZhciBxdWUgbGEgbWF5b3IgcGFydGUgZGUgbGEgcHJvZHVjY2nDs24gZXN0w6EgY29uY2VudHJhZGEgZW4gbGEgcGFydGUgb3JpZW50YWwgZGVsIGRlcGFydGFtZW50bywgZW4gZWwgbXVuaWNpcGlvIGRlIEPDumN1dGEgeSBFbCBadWxpYS4gVGFtYmnDqW4sIGV4aXN0ZSBwcm9kdWNjacOzbiBkZSBhcnJveiBlbiBvdHJvcyBtdW5pY2lwaW9zIGFsIG5vcnRlIHkgc3VyIGRlbCBkZXBhcnRhbWVudG8uIA0KIC0gU2Vnw7puIExhIE9waW5pw7NuLCBwYXJhIGVsIGHDsW8gMjAxOSBsYSBhbHRhIGRlbWFuZGEgZGUgYXJ0w61jdWxvcyBkZSBsYSBjYW5hc3RhIGLDoXNpY2EgcG9yIHBhcnRlIGRlIGxhIHBvYmxhY2nDs24gZmxvdGFudGUgZW4gQ8O6Y3V0YSB5IE5vcnRlIGRlIFNhbnRhbmRlciBzZSBoYSBjb252ZXJ0aWRvIGVuIHVuIHByb2JsZW1hIHBhcmEgZWwgYWJhc3RlY2ltaWVudG8gZGUgcHJvZHVjdG9zIGNvbW8gbGEgaGFyaW5hIGRlIG1hw616IHkgZGUgdHJpZ28uIFNpbiBlbWJhcmdvLCBvdHJvcyBzZWN0b3JlcyBwcm9kdWN0b3JlcyBkZSBhbGltZW50b3MgZXN0w6FuIGFwcm92ZWNoYW5kbyBsYSBvcG9ydHVuaWRhZCBwYXJhIGluY3JlbWVudGFyIHN1cyB2ZW50YXMuIEVzdGUgZXMgZWwgY2FzbyBkZSBsb3MgYXJyb2Nlcm9zLCBxdWllbmVzIGhhbiBhdW1lbnRhZG8gbGEgcHJvZHVjY2nDs24gZGUgYXJyb3osIHkgZXN0byBsb3MgaGEgbGxldmFkbyBhIHRyaXBsaWNhciBzdXMgdmVudGFzIGVuIEPDumN1dGEgeSBhIHBvc2ljaW9uYXJzZSBlbiBlbCBtZXJjYWRvIHJlZ2lvbmFsLg0KR3VpbGxlcm1vIEluZmFudGUgU2FudG9zLCBnZXJlbnRlIGdlbmVyYWwgZGUgbGEgQ29vcGVyYXRpdmEgQWdyb3BlY3VhcmlhIGRlIE5vcnRlIGRlIFNhbnRhbmRlciAoQ29hZ29ub3J0ZSksIGluZm9ybcOzIHF1ZSBtaWVudHJhcyBhbCBpbmljaW8gZGVsIGHDsW8gZGVzcGFjaGFiYW4gMzUuMDAwIHRvbmVsYWRhcyBkaWFyaWFzLCBhaG9yYSBlc3TDoW4gZW52aWFuZG8gNjUuMDAwIHRvbmVsYWRhcyBoYWNpYSBsYXMgcGxhemFzIGRlIEPDumN1dGEuDQpBZGVtw6FzLCBleHBsaWNhIHF1ZSBsb3MgYWx0b3Mgbml2ZWxlcyBkZSBwcm9kdWNjacOzbiBzZSBkZWJlbiBhbCBjcmVjaW1pZW50byBlbiBsYSBkZW1hbmRhIGRlbCBwcm9kdWN0byBlbiBzdXBlcm1lcmNhZG9zIHkgYm9kZWdhcyBkZSBsYSBjaXVkYWQsIGVzdG8gYSBjYXVzYSBkZSBsYXMgY29tcHJhcyBxdWUgaGFjZW4gbG9zIHZlbmV6b2xhbm9zIHF1ZSB2aWFqYW4gYSBDw7pjdXRhIHBhcmEgYWJhc3RlY2Vyc2UuDQoNCg0KDQojIDguIEd1YXJkYXIgbWFwYXMuDQogPGRpdiBzdHlsZT0gInRleHQtYWxpZ246IGp1c3RpZnkiPg0KIEFob3JhIHNlIHZhIGEgcmVhbGl6YXIgb3RybyBtYXBhIGRlIHByb2R1Y2Npw7NuIGRlIGFycm96IGVuIDIwMTguIEVzdGEgdmV6IHNlIHZhbiBhIHVzYXIgc8OtbWJvbG9zIHByb3BvcmNpb25hbGVzIHkgbWFwYXMgZGUgY29yb3BsZXRhcy4gTGEgc2FsaWRhIHNlIGd1YXJkYXLDoSBjb21vIHVuICoqYXJjaGl2by5wbmcqKi4NCiBQcmltZXJvLCBhbGd1bmFzIG9ic2VydmFjaW9uZXM6DQogDQogLSAqKnByb3BTeW1ib2xzQ2hvcm9MYWVyKCkqKiBjcmVhIHVuYSBtYXBhIGRlIHPDrW1ib2xvcyBxdWUgc29uIHByb3BvcmNpb25hbGVzIGEgbG9zIHZhbG9yZXMgZGUgdW5hIHByaW1lcmEgdmFyaWFibGUgeSBjb2xvcmVhZG9zIHBhcmEgcmVmbGVqYXIgbGEgY2xhc2lmaWNhY2nDs24gZGUgdW5hIHNlZ3VuZGEgdmFyaWFibGUuDQogDQotIFNlIHV0aWxpemEgdW5hIGNvbWJpbmFjacOzbiBkZSBhcmd1bWVudG9zICoqcHJvcFN5bWJvbHNMYXllcigpKiogeSAqKkNob3JvTGF5ZXIoKSoqLg0KRWwgc2lndWllbnRlIGNodW5rIG5vIG11ZXN0cmEgdW4gbWFwYS4gRW4gY2FtYmlvLCBlc2NyaWJlIGVsIG1hcGEgZW4gZWwgbm9tYnJlIGRlIGFyY2hpdm8gYXJyb3pfMjAxOC5wbmcgZGViYWpvIGRlbCBkaXJlY3RvcmlvIGRlIHRyYWJham8uDQoNCmBgYHtyfQ0KcG5nKCJDOi9Vc2Vycy91c2VyL0RvY3VtZW50cy9JbnRyb190b19SL2Fycm96XzIwMTgucG5nIiwgd2lkdGggPSAyMDQ4LCBoZWlnaHQgPSAxNTI2KQ0KDQpvcGFyIDwtIHBhcihtYXI9IGMoMCwwLDUsNSkpDQpwbG90KHN0X2dlb21ldHJ5KHJlcF9hcnJveiksIGNvbCA9ICJkYXJrc2VhZ3JlZW4zIiwgYm9yZGVyPSJkYXJrc2VhZ3JlZW40IiwgYmc9ICJ3aGl0ZSIsIGx3ZCA9IDAuNikNCg0KcHJvcFN5bWJvbHNDaG9yb0xheWVyKHggPSByZXBfYXJyb3osIA0KICAgICAgICAgICAgICAgICAgICAgIHZhciA9ICJQcm9kdWNjaW9uIiwgDQogICAgICAgICAgICAgICAgICAgICAgdmFyMiA9ICJSZW5kaW1pZW50byIsDQogICAgICAgICAgICAgICAgICAgICAgY29sID0gY2FydG8ucGFsKHBhbDEgPSAidHVycXVvaXNlLnBhbCIsIG4xID0gMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFsMiA9ICJyZWQucGFsIiwgbjIgPSAzKSwNCiAgICAgICAgICAgICAgICAgICAgICBpbmNoZXMgPSAwLjgsIG1ldGhvZCA9ICJxNiIsDQogICAgICAgICAgICAgICAgICAgICAgYm9yZGVyID0gImdyZXk1MCIsIGx3ZCA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRpdGxlLmNleCA9IDEuNSwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFsdWVzLmNleCA9IDEuMCwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyLnBvcyA9ICJyaWdodCIsIA0KICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC52YXIyLnBvcyA9ICJsZWZ0IiwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyMi52YWx1ZXMucm5kID0gMiwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyMi50aXRsZS50eHQgPSAiUmVuZGltaWVudG9cbihUb24vSGEpIiwNCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudmFyLnRpdGxlLnR4dCA9ICJQcm9kdWNjaW9uIGRlIGFycm96IGVuIDIwMTgiLA0KICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC52YXIuc3R5bGUgPSAiZSIpDQpsYWJlbExheWVyKA0KICB4ID0gcmVwX2Fycm96LCANCiAgdHh0ID0gIk1QSU9fQ05NQlIiLCANCiAgY29sPSAid2hpdGUiLCANCiAgY2V4ID0gMi4wLCANCiAgZm9udCA9IDQsDQogIGhhbG8gPSBGQUxTRSwgDQogIGJnID0gIndoaXRlIiwgDQogIHIgPSAwLjEsIA0KICBvdmVybGFwID0gRkFMU0UsIA0KICBzaG93LmxpbmVzID0gRkFMU0UNCikNCg0KbGF5b3V0TGF5ZXIodGl0bGU9IlByb2R1Y2Npw7NuIHkgcmVuZGltaWVudG8gZGUgYXJyb3ogaW4gTm9ydGUgZGUgU2FudGFuZGVyLCAyMDE4IiwNCiAgICAgICAgICAgIGF1dGhvciA9ICJBbmEgTWFyw61hIE1vbnRhw7FvIiwgDQogICAgICAgICAgICBzb3VyY2VzID0gIlNvdXJjZXM6IE1BRFIgJiBEQU5FLCAyMDE4IiwgDQogICAgICAgICAgICBzY2FsZSA9IDUwLCB0YWJ0aXRsZSA9IEZBTFNFLCBmcmFtZSA9IFRSVUUpDQoNCm5vcnRoKHBvcyA9ICJ0b3BsZWZ0IikNCg0KdGl0bGUobWFpbj0iUHJvZHVjY2nDs24geSByZW5kaW1pZW50byBkZSBhcnJveiBpbiBOb3J0ZSBkZSBTYW50YW5kZXIsIDIwMTgiLCBjZXgubWFpbj0zLA0KICAgICAgc3ViPSAiU291cmNlOiBNQURSICYgREFORSwgMjAxOCIsIGNleC5zdWI9MikNCg0KZ3JhdGljdWxlID0gVFJVRQ0KDQpwYXIob3BhcikNCg0KZGV2Lm9mZigpDQpgYGANCg0KIDxkaXYgc3R5bGU9ICJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCiANCkFob3JhLCBxdWUgeWEgaGVtb3MgZ3VhcmRhZG8gZWwgbWFwYSBjb21vIHVuYSBpbWFnZW4sIHNlIHB1ZWRlIGFncmVnYXIgYWwgY3VhZGVybm8gZGUgUiBNYXJrZG93biB1c2FuZG8gbGEgc2ludGF4aXMgZGUgTWFya2Rvd24gZGUgbGEgc2lndWllbnRlIG1hbmVyYToNCg0KIVtQcm9kdWNjacOzbiBkZSBhcnJveiBlbiBOb3J0ZSBkZSBTYW50YW5kZXIsIDIwMThdKEM6L1VzZXJzL3VzZXIvRG9jdW1lbnRzL0ludHJvX3RvX1IvYXJyb3pfMjAxOC5wbmcpDQoNCg0KRmluYWxtZW50ZSwgZW4gZXN0ZSBtYXBhIHNlIHJlbGFjaW9uYSBsYSBwcm9kdWNjacOzbiB5IGVsIHJlbmRpbWllbnRvIGRlIGFycm96IGVuIGVsIGRlcGFydGFtZW50bywgZG9uZGUgZ3JhY2lhcyBhIGxvcyBzw61tYm9sb3MgY2lyY3VsYXJlcyBzZSBvYnNlcnZhIHF1ZSBsYSBwcm9kdWNjacOzbiBzZSBjb25jZW50cmEgZW4gZWwgbXVuaWNpcGlvIGRlIEPDumN1dGEsIGRvbmRlIHNlIGVuY3VlbnRyYSBlbCBjw61yY3VsbyBkZSBtYXlvciB0YW1hw7FvLiBFbCByZW5kaW1pZW50byBzZSBwdWVkZSBvYnNlcnZhciBwb3IgbG9zIGRpZmVyZW50ZXMgY29sb3JlcyBxdWUgcHJlc2VudGFuIGxvcyBjw61yY3Vsb3MuIA0KDQpgYGB7cn0NCnNlc3Npb25JbmZvKCkNCmBgYA0KDQoNCg==