VISUALIZACIÓN DE DATOS

Inseguridad y territorio en Bogotá:
¿qué nos cuentan las UPZ?
Docente: Carlos Amortegui

Logo de la institución

Preparación de los datos

a. Instalación de paquetes

Para realizar la exploración de los datos se utilizarán paquetes de R que permiten importar archivos, organizar la información y realizar cálculos estadísticos.

El siguiente código instala los paquetes necesarios para trabajar con archivos Excel y CSV, manipular datos y elaborar gráficos.

# Instalación de paquetes necesarios para el proyecto

install.packages("tidyverse")  # Manipulación, transformación y exploración de datos. Incluye dplyr, tidyr, ggplot2 y readr.
install.packages("sf")         # Lectura y manejo de información geográfica. Permite trabajar con los polígonos de las UPZ y localidades.
install.packages("leaflet")    # Creación de mapas interactivos con zoom, etiquetas y resaltado de territorios.
install.packages("scales")     # Formato de números, porcentajes, tasas y escalas en gráficos.
install.packages("knitr")      # Organización y presentación de tablas y resultados dentro del informe R Markdown.

b. Carga de paquetes

Una vez instalados, los paquetes se cargan para poder utilizar sus funciones durante el análisis.

# Cargar las librerías necesarias
library(tidyverse)
library(sf)
library(leaflet)
library(scales)
library(knitr)

c. Configuración general del documento

Configuración del comportamiento general del documento

# Definir la paleta de colores del proyecto
morado   <- "#351A4F"
magenta  <- "#D9006C"
turquesa <- "#168C86"
gris     <- "#D9D6DD"

# Configuración general de los gráficos
tema_clase <- theme_minimal(base_size = 12) +
  theme(
    plot.title.position = "plot",
    plot.title = element_text(
      face = "bold", size = 15, color = morado
    ),
    plot.subtitle = element_text(
      size = 10.5, color = "grey35"
    ),
    panel.grid.minor = element_blank(),
    plot.caption = element_text(
      hjust = 0, color = "grey45", size = 8.5
    ),
    plot.margin = margin(10, 20, 10, 10)
  )

# Opciones generales de presentación del informe
knitr::opts_chunk$set(
  echo = TRUE,
  warning = FALSE,
  message = FALSE,
  fig.align = "center",
  fig.width = 8,
  fig.height = 5,
  dpi = 120
)

1. Introducción

La seguridad ciudadana es una de las dimensiones que influye en la calidad de vida y en las condiciones de convivencia de una ciudad. Sin embargo, su comportamiento no necesariamente es igual en todos los territorios, ya que cada zona presenta características particulares relacionadas con su población, infraestructura, condiciones socioeconómicas y entorno urbano.

En Bogotá, las Unidades de Planeamiento Zonal (UPZ) permiten observar estas diferencias desde una perspectiva territorial. A través de ellas es posible comparar las condiciones de distintos sectores de la ciudad y explorar cómo se relacionan con los registros de delitos y la percepción de inseguridad de sus habitantes.

Este trabajo desarrolla un análisis exploratorio de datos (EDA) sobre las 112 UPZ urbanas de Bogotá, utilizando información relacionada con delitos denunciados, población, vivienda, alumbrado público y condiciones socioeconómicas.

El propósito es identificar patrones, diferencias y posibles relaciones entre las características de cada territorio y los indicadores de seguridad disponibles. Para ello, se utilizarán herramientas estadísticas y visualizaciones que faciliten la interpretación de los resultados, incluyendo representaciones geográficas que permitan reconocer las diferencias entre las zonas de la ciudad.

El análisis no busca establecer relaciones de causalidad ni afirmar que una característica territorial sea la causa directa de determinados comportamientos delictivos. Su alcance es exploratorio y pretende comprender mejor la información disponible, reconocer patrones y generar preguntas que puedan orientar investigaciones posteriores.

1.1. Objetivo general

Explorar las condiciones de seguridad y las características territoriales, demográficas y socioeconómicas de las UPZ urbanas de Bogotá, mediante técnicas de análisis exploratorio de datos y visualización, con el propósito de identificar patrones, diferencias y posibles relaciones que permitan comprender el comportamiento de los indicadores de inseguridad en la ciudad.

1.2. Objetivos específicos

  • Describir la estructura y las características de la información disponible para las 112 UPZ de Bogotá.

  • Explorar la distribución de los indicadores de delitos, población, vivienda, infraestructura y condiciones socioeconómicas.

  • Identificar diferencias territoriales mediante el uso de estadísticas descriptivas, comparaciones y mapas.

  • Examinar posibles relaciones entre los indicadores de seguridad y las características de cada UPZ.

  • Comunicar los principales hallazgos mediante visualizaciones y una narrativa basada en los datos.

2. Descripción de los datos

Para desarrollar el análisis se utiliza una base de datos consolidada que contiene información de 112 Unidades de Planeamiento Zonal de Bogotá. Cada registro representa una UPZ e incluye variables relacionadas con su territorio, población, condiciones de vivienda, infraestructura, delitos denunciados y características socioeconómicas.

La información se encuentra organizada en cinco grandes bloques:

  1. Territorio: identificación de la UPZ, localidad y extensión geográfica.

  2. Demografía: población, densidad poblacional y composición por grupos de edad.

  3. Vivienda e infraestructura: características de las viviendas y disponibilidad de alumbrado público.

  4. Delitos: registros de denuncias y tasas por cada 10.000 habitantes para diez categorías de delitos.

  5. Encuesta Multipropósito: información relacionada con pobreza, ingresos, estrato, educación, percepción de inseguridad y condiciones del entorno.

Adicionalmente, se dispone de archivos geográficos que representan los límites de las UPZ y las localidades urbanas de Bogotá. Estos archivos permitirán integrar la información estadística con su ubicación territorial.

3. Carga de la información

Vamos a conectar nuestro informe con los archivos.

Se cargaran tres fuentes: 1. La base estadística de las UPZ. 2. El mapa de las UPZ. 3. El mapa de las localidades.

# 3.1. Importación de la base estadística

upz <- read_csv(
  "input/upz_variables.csv",
  show_col_types = FALSE
)

# 3.2. Importación de los archivos geográficos

upz_shp <- st_read(
  "input/shp/upz_bogota.shp",
  quiet = TRUE
)

localidades_shp <- st_read(
  "input/shp/localidades_bogota.shp",
  quiet = TRUE
)

Notas:

  • read_csv() permite importar la información estadística.

  • st_read() permite leer los archivos geográficos.

  • Los objetos terminados en **_shp** contienen geometrías que representan los límites territoriales.

4. Exploración inicial de los datos

Antes de realizar los análisis estadísticos y las visualizaciones, es necesario conocer la estructura de la información disponible y verificar sus características generales.

Esta primera exploración permite identificar la cantidad de registros y variables, los tipos de datos utilizados y las condiciones generales de la base. De esta manera, se busca establecer un punto de partida que facilite el desarrollo de las siguientes etapas del análisis.

4.1. Dimensiones y estructura de la información

La base de datos contiene información de diferentes características de las UPZ de Bogotá. Para comenzar, se revisa su dimensión general, identificando cuántos registros y variables están disponibles.

Cada registro representa una UPZ, mientras que las columnas corresponden a las diferentes características e indicadores recopilados para el análisis.

# Consultar las dimensiones generales de la base
dim(upz)
## [1] 112  67
# Identificar la cantidad de registros
nrow(upz)
## [1] 112
# Identificar la cantidad de variables
ncol(upz)
## [1] 67
# Consultar los primeros registros
head(upz)
upz_cod upz_nombre localidad_cod localidad area_km2 poblacion densidad_hab_km2 pct_mujeres pct_0_14 pct_15_29 pct_60_mas viviendas_totales viviendas_ocupadas pct_viviendas_desocupadas personas_por_vivienda luminarias luminarias_km2 luminarias_1000hab pct_luminarias_led casos_homicidios casos_lesiones casos_hurto_personas casos_hurto_residencias casos_hurto_automotor casos_hurto_bicicletas casos_hurto_comercio casos_hurto_celulares casos_hurto_motos casos_violencia_intrafamiliar casos_total tasa_homicidios tasa_lesiones tasa_hurto_personas tasa_hurto_residencias tasa_hurto_automotor tasa_hurto_bicicletas tasa_hurto_comercio tasa_hurto_celulares tasa_hurto_motos tasa_violencia_intrafamiliar tasa_total em_agrupada pct_pobreza edad_promedio salario_promedio pct_estrato_1_2 pct_estrato_3_4 pct_estrato_5_6 pct_vivienda_propia pct_arriendo anios_educacion_15mas pct_padre_universitario pct_madre_universitaria pct_percibe_inseguridad pct_cerca_ollas pct_cerca_bares pct_cerca_lotes_oscuros pct_cerca_basureros pct_cerca_terminales pct_cerca_fabricas min_transmilenio min_sitp min_parque min_cai_policia min_centro_medico min_cultura min_ciclorruta
1 Paseo De Los Libertadores 1 Usaquén 6.33 2690 424.81 51.26 18.85 26.13 12.94 1087 1022 5.98 2.63 524 82.75 194.80 28.44 0 8 44 1 0 1 3 17 0 0 74 0.00 29.74 163.57 3.72 0.00 3.72 11.15 63.20 0.00 0.00 275.09 TRUE 1.37 36.54 3937004 13.92 83.87 2.21 54.45 38.00 12.16 24.14 17.37 36.18 17.53 15.68 24.15 6.13 20.93 11.55 13.01 9.99 7.00 21.66 29.82 33.90 9.00
2 La Academia 11 Suba 6.74 5260 779.85 51.35 24.11 18.46 9.26 1554 1515 2.51 3.47 534 79.17 101.52 0.37 1 3 75 0 3 1 9 26 0 5 123 1.90 5.70 142.59 0.00 5.70 1.90 17.11 49.43 0.00 9.51 233.84 TRUE 0.86 38.71 4280663 0.63 87.06 12.31 57.98 36.81 13.57 24.16 14.82 40.88 7.43 17.03 16.71 1.35 26.66 1.70 10.78 9.56 5.44 24.50 34.17 29.61 13.45
3 Guaymaral 11 Suba 4.55 2692 591.30 51.63 18.31 20.88 14.04 789 698 11.53 3.86 184 40.42 68.35 0.00 0 1 29 0 0 2 2 9 0 2 45 0.00 3.71 107.73 0.00 0.00 7.43 7.43 33.43 0.00 7.43 167.16 TRUE 0.86 38.71 4280663 0.63 87.06 12.31 57.98 36.81 13.57 24.16 14.82 40.88 7.43 17.03 16.71 1.35 26.66 1.70 10.78 9.56 5.44 24.50 34.17 29.61 13.45
9 Verbenal 1 Usaquén 3.57 131999 36967.66 52.77 20.15 25.15 11.61 46809 45055 3.75 2.93 3555 995.61 26.93 65.77 3 104 386 29 19 17 26 125 30 205 944 0.23 7.88 29.24 2.20 1.44 1.29 1.97 9.47 2.27 15.53 71.52 FALSE 3.12 33.28 1933709 31.32 66.05 2.63 36.78 55.53 12.16 8.36 6.13 65.43 17.53 15.68 24.15 6.13 20.93 11.55 6.96 5.96 8.60 18.39 34.18 42.77 14.45
10 La Uribe 1 Usaquén 3.47 37014 10682.12 54.34 17.24 20.18 15.62 14399 13763 4.42 2.69 1328 383.26 35.88 49.25 1 26 328 31 4 14 47 129 1 40 621 0.27 7.02 88.62 8.38 1.08 3.78 12.70 34.85 0.27 10.81 167.77 TRUE 1.37 36.54 3937004 13.92 83.87 2.21 54.45 38.00 12.16 24.14 17.37 36.18 17.53 15.68 24.15 6.13 20.93 11.55 13.01 9.99 7.00 21.66 29.82 33.90 9.00
11 San Cristobal Norte 1 Usaquén 2.76 72939 26401.70 52.65 19.59 24.65 14.38 24886 24401 1.95 2.99 2578 933.16 35.34 49.34 4 73 351 27 5 11 39 117 9 157 793 0.55 10.01 48.12 3.70 0.69 1.51 5.35 16.04 1.23 21.52 108.72 FALSE 5.19 34.50 1368739 29.48 68.87 1.65 28.86 58.05 10.95 4.76 3.31 49.84 25.91 15.41 19.15 8.30 3.38 5.99 17.76 11.43 10.39 25.32 29.71 28.10 18.27

4.2. Tipos de variables y estructura

Además de conocer el tamaño de la base, es importante identificar el tipo de información que contiene cada variable.

Esta revisión permite diferenciar los campos que representan cantidades, porcentajes, tasas, categorías territoriales y otras características.

La identificación de estos tipos de datos es importante porque no todas las variables pueden analizarse de la misma manera. Por ejemplo, una variable de población permite realizar cálculos estadísticos, mientras que una variable como el nombre de la localidad se utiliza principalmente para clasificar y agrupar la información.

# Consultar la estructura y los tipos de variables
glimpse(upz)
## Rows: 112
## Columns: 67
## $ upz_cod                       <dbl> 1, 2, 3, 9, 10, 11, 12, 13, 14, 15, 16, …
## $ upz_nombre                    <chr> "Paseo De Los Libertadores", "La Academi…
## $ localidad_cod                 <dbl> 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 11, 1…
## $ localidad                     <chr> "Usaquén", "Suba", "Suba", "Usaquén", "U…
## $ area_km2                      <dbl> 6.33, 6.74, 4.55, 3.57, 3.47, 2.76, 2.92…
## $ poblacion                     <dbl> 2690, 5260, 2692, 131999, 37014, 72939, …
## $ densidad_hab_km2              <dbl> 424.81, 779.85, 591.30, 36967.66, 10682.…
## $ pct_mujeres                   <dbl> 51.26, 51.35, 51.63, 52.77, 54.34, 52.65…
## $ pct_0_14                      <dbl> 18.85, 24.11, 18.31, 20.15, 17.24, 19.59…
## $ pct_15_29                     <dbl> 26.13, 18.46, 20.88, 25.15, 20.18, 24.65…
## $ pct_60_mas                    <dbl> 12.94, 9.26, 14.04, 11.61, 15.62, 14.38,…
## $ viviendas_totales             <dbl> 1087, 1554, 789, 46809, 14399, 24886, 24…
## $ viviendas_ocupadas            <dbl> 1022, 1515, 698, 45055, 13763, 24401, 23…
## $ pct_viviendas_desocupadas     <dbl> 5.98, 2.51, 11.53, 3.75, 4.42, 1.95, 3.6…
## $ personas_por_vivienda         <dbl> 2.63, 3.47, 3.86, 2.93, 2.69, 2.99, 2.68…
## $ luminarias                    <dbl> 524, 534, 184, 3555, 1328, 2578, 2734, 5…
## $ luminarias_km2                <dbl> 82.75, 79.17, 40.42, 995.61, 383.26, 933…
## $ luminarias_1000hab            <dbl> 194.80, 101.52, 68.35, 26.93, 35.88, 35.…
## $ pct_luminarias_led            <dbl> 28.44, 0.37, 0.00, 65.77, 49.25, 49.34, …
## $ casos_homicidios              <dbl> 0, 1, 0, 3, 1, 4, 1, 0, 0, 0, 3, 1, 2, 0…
## $ casos_lesiones                <dbl> 8, 3, 1, 104, 26, 73, 52, 75, 36, 14, 49…
## $ casos_hurto_personas          <dbl> 44, 75, 29, 386, 328, 351, 500, 1189, 78…
## $ casos_hurto_residencias       <dbl> 1, 0, 0, 29, 31, 27, 19, 87, 35, 24, 76,…
## $ casos_hurto_automotor         <dbl> 0, 3, 0, 19, 4, 5, 7, 11, 3, 1, 8, 14, 1…
## $ casos_hurto_bicicletas        <dbl> 1, 1, 2, 17, 14, 11, 38, 71, 26, 12, 32,…
## $ casos_hurto_comercio          <dbl> 3, 9, 2, 26, 47, 39, 58, 95, 72, 28, 125…
## $ casos_hurto_celulares         <dbl> 17, 26, 9, 125, 129, 117, 170, 368, 262,…
## $ casos_hurto_motos             <dbl> 0, 0, 0, 30, 1, 9, 6, 3, 3, 0, 5, 8, 8, …
## $ casos_violencia_intrafamiliar <dbl> 0, 5, 2, 205, 40, 157, 92, 92, 73, 14, 4…
## $ casos_total                   <dbl> 74, 123, 45, 944, 621, 793, 943, 1991, 1…
## $ tasa_homicidios               <dbl> 0.00, 1.90, 0.00, 0.23, 0.27, 0.55, 0.16…
## $ tasa_lesiones                 <dbl> 29.74, 5.70, 3.71, 7.88, 7.02, 10.01, 8.…
## $ tasa_hurto_personas           <dbl> 163.57, 142.59, 107.73, 29.24, 88.62, 48…
## $ tasa_hurto_residencias        <dbl> 3.72, 0.00, 0.00, 2.20, 8.38, 3.70, 3.01…
## $ tasa_hurto_automotor          <dbl> 0.00, 5.70, 0.00, 1.44, 1.08, 0.69, 1.11…
## $ tasa_hurto_bicicletas         <dbl> 3.72, 1.90, 7.43, 1.29, 3.78, 1.51, 6.03…
## $ tasa_hurto_comercio           <dbl> 11.15, 17.11, 7.43, 1.97, 12.70, 5.35, 9…
## $ tasa_hurto_celulares          <dbl> 63.20, 49.43, 33.43, 9.47, 34.85, 16.04,…
## $ tasa_hurto_motos              <dbl> 0.00, 0.00, 0.00, 2.27, 0.27, 1.23, 0.95…
## $ tasa_violencia_intrafamiliar  <dbl> 0.00, 9.51, 7.43, 15.53, 10.81, 21.52, 1…
## $ tasa_total                    <dbl> 275.09, 233.84, 167.16, 71.52, 167.77, 1…
## $ em_agrupada                   <lgl> TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FA…
## $ pct_pobreza                   <dbl> 1.37, 0.86, 0.86, 3.12, 1.37, 5.19, 0.84…
## $ edad_promedio                 <dbl> 36.54, 38.71, 38.71, 33.28, 36.54, 34.50…
## $ salario_promedio              <dbl> 3937004, 4280663, 4280663, 1933709, 3937…
## $ pct_estrato_1_2               <dbl> 13.92, 0.63, 0.63, 31.32, 13.92, 29.48, …
## $ pct_estrato_3_4               <dbl> 83.87, 87.06, 87.06, 66.05, 83.87, 68.87…
## $ pct_estrato_5_6               <dbl> 2.21, 12.31, 12.31, 2.63, 2.21, 1.65, 0.…
## $ pct_vivienda_propia           <dbl> 54.45, 57.98, 57.98, 36.78, 54.45, 28.86…
## $ pct_arriendo                  <dbl> 38.00, 36.81, 36.81, 55.53, 38.00, 58.05…
## $ anios_educacion_15mas         <dbl> 12.16, 13.57, 13.57, 12.16, 12.16, 10.95…
## $ pct_padre_universitario       <dbl> 24.14, 24.16, 24.16, 8.36, 24.14, 4.76, …
## $ pct_madre_universitaria       <dbl> 17.37, 14.82, 14.82, 6.13, 17.37, 3.31, …
## $ pct_percibe_inseguridad       <dbl> 36.18, 40.88, 40.88, 65.43, 36.18, 49.84…
## $ pct_cerca_ollas               <dbl> 17.53, 7.43, 7.43, 17.53, 17.53, 25.91, …
## $ pct_cerca_bares               <dbl> 15.68, 17.03, 17.03, 15.68, 15.68, 15.41…
## $ pct_cerca_lotes_oscuros       <dbl> 24.15, 16.71, 16.71, 24.15, 24.15, 19.15…
## $ pct_cerca_basureros           <dbl> 6.13, 1.35, 1.35, 6.13, 6.13, 8.30, 11.7…
## $ pct_cerca_terminales          <dbl> 20.93, 26.66, 26.66, 20.93, 20.93, 3.38,…
## $ pct_cerca_fabricas            <dbl> 11.55, 1.70, 1.70, 11.55, 11.55, 5.99, 2…
## $ min_transmilenio              <dbl> 13.01, 10.78, 10.78, 6.96, 13.01, 17.76,…
## $ min_sitp                      <dbl> 9.99, 9.56, 9.56, 5.96, 9.99, 11.43, 6.8…
## $ min_parque                    <dbl> 7.00, 5.44, 5.44, 8.60, 7.00, 10.39, 5.1…
## $ min_cai_policia               <dbl> 21.66, 24.50, 24.50, 18.39, 21.66, 25.32…
## $ min_centro_medico             <dbl> 29.82, 34.17, 34.17, 34.18, 29.82, 29.71…
## $ min_cultura                   <dbl> 33.90, 29.61, 29.61, 42.77, 33.90, 28.10…
## $ min_ciclorruta                <dbl> 9.00, 13.45, 13.45, 14.45, 9.00, 18.27, …

4.3. Revisión de valores faltantes

Los valores faltantes representan información que no se encuentra disponible para una o varias variables. Su identificación es importante porque pueden afectar los cálculos estadísticos, las comparaciones y las relaciones entre variables.

En esta etapa se revisa la cantidad de datos faltantes en cada columna, con el propósito de determinar si existen limitaciones en la información disponible.

# Calcular la cantidad de valores faltantes por variable

faltantes <- upz %>%
  summarise(
    across(
      everything(),
      ~ sum(is.na(.))
    )
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Variable",
    values_to = "Cantidad_faltantes"
  ) %>%
  filter(Cantidad_faltantes > 0) %>%
  arrange(desc(Cantidad_faltantes))

# Presentar los resultados

if (nrow(faltantes) == 0) {

  cat("No se encontraron valores faltantes en la base de datos.")

} else {

  knitr::kable(
    faltantes,
    caption = "Variables con valores faltantes"
  )

}
## No se encontraron valores faltantes en la base de datos.

4.4. Identificación de registros duplicados

Debido a que cada registro representa una UPZ, el código de identificación territorial debe ser único dentro de la base de datos.

Por esta razón, se revisa si existen códigos repetidos que puedan generar duplicidad de información o afectar las comparaciones posteriores.

# Identificar códigos UPZ repetidos

duplicados_upz <- upz %>%
  count(upz_cod, name = "Frecuencia") %>%
  filter(Frecuencia > 1)

# Presentar el resultado

if (nrow(duplicados_upz) == 0) {

  cat("No se encontraron códigos UPZ duplicados.")

} else {

  knitr::kable(
    duplicados_upz,
    caption = "Códigos UPZ duplicados"
  )

}
## No se encontraron códigos UPZ duplicados.

4.5. Resumen general de la exploración inicial

Una vez realizadas las verificaciones iniciales, se consolida un resumen de las principales características de la base de datos.

Este resultado permite establecer las condiciones generales de la información con la que se desarrollará el análisis exploratorio.

resumen_base <- tibble(
  Indicador = c(
    "Cantidad de registros",
    "Cantidad de variables",
    "Códigos UPZ únicos",
    "Valores faltantes",
    "Códigos UPZ duplicados"
  ),

  Resultado = c(
    nrow(upz),
    ncol(upz),
    n_distinct(upz$upz_cod),
    sum(is.na(upz)),
    nrow(duplicados_upz)
  )
)

knitr::kable(
  resumen_base,
  col.names = c("Indicador", "Resultado"),
  caption = "Resumen de la exploración inicial"
)
Resumen de la exploración inicial
Indicador Resultado
Cantidad de registros 112
Cantidad de variables 67
Códigos UPZ únicos 112
Valores faltantes 0
Códigos UPZ duplicados 0

Interpretación de la revisión inicial

Los resultados muestran que la base de datos está conformada por 112 registros y 67 variables, con una correspondencia de un registro por cada código UPZ.

En la revisión realizada no se identificaron valores faltantes ni códigos territoriales duplicados. Esto representa una condición favorable para continuar con el análisis exploratorio.

Sin embargo, la ausencia de valores faltantes y duplicados no garantiza por sí sola la calidad de toda la información. Todavía es necesario revisar la distribución de las variables, identificar posibles valores extremos y evaluar la coherencia de los indicadores calculados.

Por lo tanto, esta primera revisión constituye un punto de partida para profundizar en el comportamiento estadístico de las variables.

5. Análisis exploratorio de las variables

Una vez revisada la estructura general de la información, se inicia el análisis exploratorio de las variables con el propósito de comprender su comportamiento, identificar diferencias entre los territorios y reconocer posibles patrones que puedan orientar la investigación.

En esta etapa se utilizarán estadísticas descriptivas y representaciones gráficas para examinar las principales características de las UPZ de Bogotá.

5.1. Análisis demográfico: población y distribución territorial

La población constituye una de las variables fundamentales para comprender las diferencias entre las UPZ, ya que permite dimensionar el tamaño de cada territorio en términos de habitantes.

Su análisis es especialmente importante para este trabajo, porque los indicadores de delitos se expresan tanto en cantidades absolutas como en tasas por cada 10.000 habitantes. Por lo tanto, conocer cómo se distribuye la población permitirá interpretar posteriormente las diferencias en los indicadores de seguridad.

5.1.1. Distribución de la población por UPZ

Inicialmente se analiza la cantidad de habitantes registrados en cada UPZ, con el propósito de identificar las diferencias existentes entre los territorios y reconocer cuáles concentran una mayor o menor población.

a. Estadísticas descriptivas de población

Primero vamos a calcular las principales medidas estadísticas.

# Calcular las principales medidas descriptivas
# de la población de las UPZ

estadisticas_poblacion <- upz %>%
  summarise(
    Total_UPZ = n(),
    Poblacion_total = sum(poblacion),
    Media = mean(poblacion),
    Mediana = median(poblacion),
    Desviacion_estandar = sd(poblacion),
    Minimo = min(poblacion),
    Q1 = quantile(poblacion, 0.25),
    Q3 = quantile(poblacion, 0.75),
    Maximo = max(poblacion)
  )


# Presentar resultados

estadisticas_poblacion %>%
  tidyr::pivot_longer(
    cols = everything(),
    names_to = "Estadística",
    values_to = "Valor"
  ) %>%
  knitr::kable(
    col.names = c("Estadística", "Resultado"),
    caption = "Estadísticas descriptivas de población por UPZ"
  )
Estadísticas descriptivas de población por UPZ
Estadística Resultado
Total_UPZ 112.00
Poblacion_total 7936532.00
Media 70861.89
Mediana 54102.50
Desviacion_estandar 58406.41
Minimo 30.00
Q1 30081.75
Q3 100972.25
Maximo 305907.00

¿Qué estamos calculando?

Medida Qué nos permite conocer
Media Población promedio por UPZ.
Mediana Valor que divide las UPZ en dos grupos iguales.
Desviación estándar Qué tan dispersa está la población respecto a la media.
Mínimo y máximo Los extremos de población.
Q1 El 25 % de las UPZ tiene una población igual o inferior a este valor.
Q3 El 75 % de las UPZ tiene una población igual o inferior a este valor.

Una comparación especialmente importante será la media frente a la mediana. Si la primera es considerablemente mayor, puede indicar que algunas UPZ con poblaciones muy elevadas están influyendo en el promedio.

b. Distribución gráfica de la población

Ahora vamos a visualizar cómo se distribuye la población entre las 112 UPZ

# Histograma de la población por UPZ

ggplot(upz, aes(x = poblacion)) +

  geom_histogram(
    bins = 20,
    fill = magenta,
    color = "white",
    alpha = 0.85
  ) +

  labs(
    title = "Distribución de la población por UPZ",
    subtitle = "Población proyectada para el año 2023",
    x = "Cantidad de habitantes",
    y = "Número de UPZ",
    caption = "Fuente: Base de datos del taller."
  ) +

  scale_x_continuous(
    labels = scales::label_number(
      big.mark = ".",
      decimal.mark = ","
    )
  ) +

  tema_clase

¿Qué buscamos identificar?

El histograma nos permite observar dónde se concentra la mayor cantidad de UPZ según su población.

También nos ayuda a identificar si la distribución es simétrica o si presenta una concentración de territorios con poblaciones pequeñas y unos pocos territorios con poblaciones considerablemente mayores.

No debemos asumir que la población se distribuye de manera uniforme entre las UPZ.

c. Identificación de las UPZ con mayor y menor población

Y como el histograma nos muestra el comportamiento general, pero ahora necesitamos identificar los territorios que se encuentran en los extremos.

Vamos a construir dos rankings: las 10 UPZ más pobladas y las 10 menos pobladas.

# 10 UPZ con mayor población

upz_mayor_poblacion <- upz %>%
  arrange(desc(poblacion)) %>%
  select(
    upz_nombre,
    localidad,
    poblacion
  ) %>%
  slice_head(n = 10)

# 10 UPZ con menor población

upz_menor_poblacion <- upz %>%
  arrange(poblacion) %>%
  select(
    upz_nombre,
    localidad,
    poblacion
  ) %>%
  slice_head(n = 10)

# Presentar las UPZ más pobladas

knitr::kable(
  upz_mayor_poblacion,
  col.names = c("UPZ", "Localidad", "Habitantes"),
  caption = "Las 10 UPZ con mayor población",
  digits = 0
)
Las 10 UPZ con mayor población
UPZ Localidad Habitantes
Tibabuyes Suba 305907
El Rincon Suba 295322
Bosa Central Bosa 237111
Bosa Occidental Bosa 199365
Suba Suba 186728
Garces Navas Engativá 168657
Ismael Perdomo Ciudad Bolívar 166602
Lucero Ciudad Bolívar 163588
El Porvenir Bosa 143758
Engativa Engativá 142612
# Presentar las UPZ menos pobladas

knitr::kable(
  upz_menor_poblacion,
  col.names = c("UPZ", "Localidad", "Habitantes"),
  caption = "Las 10 UPZ con menor población",
  digits = 0
)
Las 10 UPZ con menor población
UPZ Localidad Habitantes
El Mochuelo Ciudad Bolívar 30
Aeropuerto El Dorado Fontibón 883
Parque Entrenubes Usme 1169
Parque Salitre Barrios Unidos 1442
Paseo De Los Libertadores Usaquén 2690
Guaymaral Suba 2692
Jardin Botanico Engativá 2900
Parque Simon Bolivar - Can Teusaquillo 3323
La Academia Suba 5260
Monte Blanco Ciudad Bolívar 6575

d. Visualización - Grafico

Ahora vamos a representar visualmente estos resultados.

# Preparar los datos de las 10 UPZ más pobladas

ggplot(
  upz_mayor_poblacion,
  aes(
    x = reorder(upz_nombre, poblacion),
    y = poblacion
  )
) +

  geom_col(
    fill = morado,
    width = 0.7
  ) +

  coord_flip() +

  labs(
    title = "Las UPZ con mayor concentración de población",
    subtitle = "Ranking de las 10 UPZ más pobladas de Bogotá",
    x = NULL,
    y = "Cantidad de habitantes",
    caption = "Fuente: Base de datos del taller."
  ) +

  scale_y_continuous(
    labels = scales::label_number(
      big.mark = ".",
      decimal.mark = ","
    )
  ) +

  tema_clase

5.1.2. Análisis de la densidad poblacional

La cantidad de habitantes no es el único elemento que permite caracterizar un territorio. También es importante considerar su extensión geográfica para comprender qué tan concentrada se encuentra la población.

Para ello se utiliza la densidad poblacional, medida en habitantes por kilómetro cuadrado (hab/km²). Este indicador relaciona la población de cada UPZ con el área que ocupa.

Su análisis permite diferenciar territorios con grandes poblaciones y extensiones amplias de aquellos que presentan una mayor concentración de habitantes en superficies más reducidas.

a. Estadísticas descriptivas de densidad

# Estadísticas descriptivas de densidad poblacional

estadisticas_densidad <- upz %>%
  summarise(
    Media = mean(densidad_hab_km2),
    Mediana = median(densidad_hab_km2),
    Desviacion_estandar = sd(densidad_hab_km2),
    Minimo = min(densidad_hab_km2),
    Q1 = quantile(densidad_hab_km2, 0.25),
    Q3 = quantile(densidad_hab_km2, 0.75),
    Maximo = max(densidad_hab_km2)
  )

knitr::kable(
  estadisticas_densidad,
  digits = 2,
  caption = "Estadísticas descriptivas de la densidad poblacional"
)
Estadísticas descriptivas de la densidad poblacional
Media Mediana Desviacion_estandar Minimo Q1 Q3 Maximo
19119.36 20180.22 10801.85 9.44 11160.41 25826.54 46156.87

b. UPZ con mayor y menor densidad

# Identificar las UPZ con mayor densidad poblacional

ranking_densidad <- upz %>%
  arrange(desc(densidad_hab_km2)) %>%
  select(
    upz_nombre,
    localidad,
    poblacion,
    area_km2,
    densidad_hab_km2
  )

# Presentar las 10 UPZ con mayor densidad

knitr::kable(
  ranking_densidad %>% slice_head(n = 10),
  col.names = c(
    "UPZ",
    "Localidad",
    "Habitantes",
    "Área (km²)",
    "Densidad (hab/km²)"
  ),
  digits = 2,
  caption = "Las 10 UPZ con mayor densidad poblacional"
)
Las 10 UPZ con mayor densidad poblacional
UPZ Localidad Habitantes Área (km²) Densidad (hab/km²)
Bosa Occidental Bosa 199365 4.32 46156.87
Patio Bonito Kennedy 137776 3.18 43262.66
Calandaima Kennedy 134340 3.20 41970.43
Tibabuyes Suba 305907 7.29 41963.01
El Rincon Suba 295322 7.13 41440.43
San Francisco Ciudad Bolívar 72057 1.79 40199.86
Verbenal Usaquén 131999 3.57 36967.66
Diana Turbay Rafael Uribe Uribe 76093 2.12 35859.94
Gran Britalia Kennedy 62139 1.81 34416.53
Marruecos Rafael Uribe Uribe 123085 3.64 33796.36
# Presentar las 10 UPZ con menor densidad

knitr::kable(
  ranking_densidad %>% arrange(densidad_hab_km2) %>% slice_head(n = 10),
  col.names = c(
    "UPZ",
    "Localidad",
    "Habitantes",
    "Área (km²)",
    "Densidad (hab/km²)"
  ),
  digits = 2,
  caption = "Las 10 UPZ con menor densidad poblacional"
)
Las 10 UPZ con menor densidad poblacional
UPZ Localidad Habitantes Área (km²) Densidad (hab/km²)
El Mochuelo Ciudad Bolívar 30 3.18 9.44
Aeropuerto El Dorado Fontibón 883 7.46 118.40
Parque Entrenubes Usme 1169 4.21 277.97
Paseo De Los Libertadores Usaquén 2690 6.33 424.81
Guaymaral Suba 2692 4.55 591.30
La Academia Suba 5260 6.74 779.85
Parque Simon Bolivar - Can Teusaquillo 3323 4.00 830.50
Parque Salitre Barrios Unidos 1442 1.66 869.50
Monte Blanco Ciudad Bolívar 6575 6.98 941.73
Jardin Botanico Engativá 2900 1.62 1786.96

c. Comparación gráfica de densidad

# Visualizar las 10 UPZ con mayor densidad poblacional

ggplot(
  ranking_densidad %>% slice_head(n = 10),
  aes(
    x = reorder(upz_nombre, densidad_hab_km2),
    y = densidad_hab_km2
  )
) +

  geom_col(
    fill = turquesa,
    width = 0.7
  ) +

  coord_flip() +

  labs(
    title = "Concentración de población en las UPZ",
    subtitle = "Territorios con mayor densidad poblacional",
    x = NULL,
    y = "Habitantes por km²",
    caption = "Fuente: Base de datos del taller."
  ) +

  scale_y_continuous(
    labels = scales::label_number(
      big.mark = ".",
      decimal.mark = ","
    )
  ) +

  tema_clase

5.1.3. Relación entre población y extensión territorial

Para complementar el análisis anterior, se examina la relación entre la población y el área geográfica de cada UPZ.

Esta comparación permite observar si los territorios con mayor extensión también concentran una mayor cantidad de habitantes o si existen diferencias importantes en la ocupación del espacio.

La visualización se realiza mediante un diagrama de dispersión, en el que cada punto representa una UPZ.

# Relación entre población y área territorial

ggplot(
  upz,
  aes(
    x = area_km2,
    y = poblacion
  )
) +

  geom_point(
    color = magenta,
    size = 2.8,
    alpha = 0.75
  ) +

  geom_smooth(
    method = "lm",
    se = FALSE,
    color = morado,
    linewidth = 0.9
  ) +

  labs(
    title = "Relación entre población y área de las UPZ",
    subtitle = "Cada punto representa una unidad territorial",
    x = "Área de la UPZ (km²)",
    y = "Cantidad de habitantes",
    caption = "Fuente: Base de datos del taller."
  ) +

  scale_y_continuous(
    labels = scales::label_number(
      big.mark = ".",
      decimal.mark = ","
    )
  ) +

  tema_clase

¿Qué debemos observar?

  • Si existe una tendencia positiva entre el área y la población.

  • Si las UPZ de mayor extensión concentran necesariamente más habitantes.

  • Si existen territorios que se apartan del comportamiento general.

La línea representa una tendencia lineal de referencia. No significa que el área territorial explique por sí sola la cantidad de habitantes.

5.1.4. Identificación de valores extremos en la población

Durante el análisis de la población es importante identificar territorios que presenten valores considerablemente diferentes al comportamiento general de las UPZ.

Para ello se utiliza el rango intercuartílico (IQR), que corresponde a la diferencia entre el tercer y el primer cuartil de la distribución.

Mediante este procedimiento se identifican posibles valores atípicos, entendidos como observaciones que se encuentran por fuera de los límites estadísticos establecidos.

La identificación de estos valores no significa que deban eliminarse de la información. Por el contrario, permite reconocer territorios con características particulares que deben considerarse en las comparaciones posteriores.

# Calcular los límites para identificar posibles valores atípicos

q1_poblacion <- quantile(upz$poblacion, 0.25)

q3_poblacion <- quantile(upz$poblacion, 0.75)

iqr_poblacion <- IQR(upz$poblacion)

limite_inferior <- q1_poblacion - 1.5 * iqr_poblacion

limite_superior <- q3_poblacion + 1.5 * iqr_poblacion

# Identificar las UPZ que se encuentran fuera de los límites

valores_extremos <- upz %>%
  filter(
    poblacion < limite_inferior |
    poblacion > limite_superior
  ) %>%
  select(
    upz_nombre,
    localidad,
    poblacion,
    area_km2,
    densidad_hab_km2
  ) %>%
  arrange(desc(poblacion))

# Presentar resultados

knitr::kable(
  valores_extremos,
  col.names = c(
    "UPZ",
    "Localidad",
    "Habitantes",
    "Área (km²)",
    "Densidad (hab/km²)"
  ),
  digits = 2,
  caption = "UPZ identificadas como posibles valores atípicos en población"
)
UPZ identificadas como posibles valores atípicos en población
UPZ Localidad Habitantes Área (km²) Densidad (hab/km²)
Tibabuyes Suba 305907 7.29 41963.01
El Rincon Suba 295322 7.13 41440.43
Bosa Central Bosa 237111 7.17 33059.28
# Mostrar los límites estadísticos

cat("Límite inferior:", round(limite_inferior, 2), "\n")
## Límite inferior: -76254
cat("Límite superior:", round(limite_superior, 2), "\n")
## Límite superior: 207308
cat("Cantidad de posibles valores atípicos:", nrow(valores_extremos))
## Cantidad de posibles valores atípicos: 3

5.1.5. Interpretación del análisis demográfico

El análisis demográfico permite reconocer que las UPZ presentan características diferentes en cuanto a su población, extensión y densidad.

Estas diferencias son relevantes para el desarrollo de la investigación, debido a que los indicadores de seguridad pueden presentar comportamientos distintos dependiendo del tamaño y las características de cada territorio.

La identificación de posibles valores extremos también permite reconocer que algunas UPZ pueden tener condiciones particulares que requieren un tratamiento diferenciado al momento de realizar comparaciones estadísticas.

A partir de estos resultados será posible establecer una base más sólida para analizar los indicadores de delitos, diferenciando las cantidades absolutas de las tasas calculadas por habitante.

5.2. Análisis de vivienda e infraestructura

En este apartado se analizan las condiciones de vivienda y la infraestructura de alumbrado público de las UPZ de Bogotá. Estas variables permiten ampliar la caracterización territorial, incorporando aspectos relacionados con la ocupación residencial y las condiciones físicas del entorno urbano.

Se consideran variables como la cantidad de viviendas, el porcentaje de viviendas desocupadas, el número de personas por vivienda y la disponibilidad de luminarias por unidad de superficie.

El análisis busca identificar diferencias entre territorios y explorar posibles patrones que posteriormente puedan contrastarse con los indicadores de seguridad.

5.2.1. Caracterización de las viviendas

Inicialmente se realiza una descripción estadística de las variables relacionadas con la vivienda. Se consideran la cantidad total de viviendas, las viviendas ocupadas, el porcentaje de viviendas desocupadas y el promedio de personas por vivienda.

El propósito es reconocer cómo se distribuyen estas características entre las UPZ e identificar posibles diferencias territoriales.

estadisticas_vivienda <- upz %>%
  summarise(
    Total_UPZ = n(),

    Media_viviendas = mean(viviendas_totales),
    Mediana_viviendas = median(viviendas_totales),
    Desv_viviendas = sd(viviendas_totales),
    Q1_viviendas = quantile(viviendas_totales, 0.25),
    Q3_viviendas = quantile(viviendas_totales, 0.75),

    Media_ocupadas = mean(viviendas_ocupadas),
    Mediana_ocupadas = median(viviendas_ocupadas),

    Media_desocupacion = mean(pct_viviendas_desocupadas),
    Mediana_desocupacion = median(pct_viviendas_desocupadas),

    Media_personas = mean(personas_por_vivienda),
    Mediana_personas = median(personas_por_vivienda)
  )

knitr::kable(
  estadisticas_vivienda,
  digits = 2,
  caption = "Estadísticas descriptivas de las variables de vivienda"
)
Estadísticas descriptivas de las variables de vivienda
Total_UPZ Media_viviendas Mediana_viviendas Desv_viviendas Q1_viviendas Q3_viviendas Media_ocupadas Mediana_ocupadas Media_desocupacion Mediana_desocupacion Media_personas Mediana_personas
112 26456.44 21155 20192.39 12908.75 35986 25127.23 19897 6.06 4.38 2.81 2.82

5.2.2. Distribución de viviendas desocupadas

El porcentaje de viviendas desocupadas permite observar qué proporción de las viviendas de cada UPZ no se encuentra ocupada.

Se utiliza un histograma para examinar la distribución de esta variable, identificar su concentración y reconocer si existen territorios con porcentajes considerablemente diferentes al comportamiento general.

ggplot(upz, aes(x = pct_viviendas_desocupadas)) +
  geom_histogram(
    bins = 20,
    fill = magenta,
    color = "white",
    alpha = 0.9
  ) +
  labs(
    title = "Distribución de viviendas desocupadas por UPZ",
    subtitle = "Porcentaje de viviendas desocupadas en cada territorio",
    x = "Porcentaje de viviendas desocupadas",
    y = "Cantidad de UPZ",
    caption = "Fuente: información consolidada en la base UPZ."
  ) +
  tema_clase

Para complementar la distribución general, se identifican las diez UPZ con mayores y menores porcentajes de viviendas desocupadas. Esto permite reconocer los territorios que presentan los valores extremos de esta característica.

mayor_desocupacion <- upz %>%
  arrange(desc(pct_viviendas_desocupadas)) %>%
  select(
    upz_nombre,
    localidad,
    viviendas_totales,
    viviendas_ocupadas,
    pct_viviendas_desocupadas
  ) %>%
  slice_head(n = 10)

menor_desocupacion <- upz %>%
  arrange(pct_viviendas_desocupadas) %>%
  select(
    upz_nombre,
    localidad,
    viviendas_totales,
    viviendas_ocupadas,
    pct_viviendas_desocupadas
  ) %>%
  slice_head(n = 10)

knitr::kable(
  mayor_desocupacion,
  digits = 2,
  caption = "Diez UPZ con mayor porcentaje de viviendas desocupadas"
)
Diez UPZ con mayor porcentaje de viviendas desocupadas
upz_nombre localidad viviendas_totales viviendas_ocupadas pct_viviendas_desocupadas
Tintal Norte Kennedy 16184 9082 43.88
Las Nieves Santa Fe 12994 9276 28.61
La Macarena Santa Fe 7361 5795 21.27
Parque Entrenubes Usme 449 355 20.94
Parque Salitre Barrios Unidos 754 620 17.77
El Refugio Chapinero 22261 18434 17.19
Chico Lago Chapinero 23343 19458 16.64
La Alhambra Suba 23749 20038 15.63
Chapinero Chapinero 18209 15624 14.20
Los Alcazares Barrios Unidos 21714 18946 12.75
knitr::kable(
  menor_desocupacion,
  digits = 2,
  caption = "Diez UPZ con menor porcentaje de viviendas desocupadas"
)
Diez UPZ con menor porcentaje de viviendas desocupadas
upz_nombre localidad viviendas_totales viviendas_ocupadas pct_viviendas_desocupadas
El Mochuelo Ciudad Bolívar 7 7 0.00
San Francisco Ciudad Bolívar 25727 25689 0.15
Patio Bonito Kennedy 46233 46145 0.19
Tunjuelito Tunjuelito 12653 12614 0.31
Bosa Central Bosa 74624 74387 0.32
Lucero Ciudad Bolívar 59218 59024 0.33
Minuto De Dios Engativá 38880 38721 0.41
Apogeo Bosa 11249 11202 0.42
Timiza Kennedy 45336 45076 0.57
Kennedy Central Kennedy 33444 33250 0.58

5.2.3. Análisis del alumbrado público

El alumbrado público constituye una característica relevante de la infraestructura urbana y permite describir las condiciones físicas de los territorios.

Para este análisis se consideran tres variables: cantidad de luminarias, densidad de luminarias por kilómetro cuadrado y porcentaje de luminarias con tecnología LED.

Se diferencia entre la cantidad total de luminarias y su densidad territorial, debido a que las UPZ presentan extensiones geográficas distintas. La densidad permite realizar una comparación que considera el tamaño del territorio.

estadisticas_alumbrado <- upz %>%
  summarise(
    Media_luminarias = mean(luminarias),
    Mediana_luminarias = median(luminarias),
    Desv_luminarias = sd(luminarias),
    Q1_luminarias = quantile(luminarias, 0.25),
    Q3_luminarias = quantile(luminarias, 0.75),

    Media_luminarias_km2 = mean(luminarias_km2),
    Mediana_luminarias_km2 = median(luminarias_km2),

    Media_led = mean(pct_luminarias_led),
    Mediana_led = median(pct_luminarias_led)
  )

knitr::kable(
  estadisticas_alumbrado,
  digits = 2,
  caption = "Estadísticas descriptivas del alumbrado público"
)
Estadísticas descriptivas del alumbrado público
Media_luminarias Mediana_luminarias Desv_luminarias Q1_luminarias Q3_luminarias Media_luminarias_km2 Mediana_luminarias_km2 Media_led Mediana_led
3138.54 2741.5 1875.89 1739 4530.75 908.47 1000 42.64 49.31

5.2.4. Distribución de la densidad de luminarias

Se analiza la distribución de luminarias por kilómetro cuadrado mediante un histograma. Esta representación permite observar cómo se concentra la infraestructura de alumbrado entre las UPZ y reconocer posibles diferencias territoriales.

Esta variable resulta especialmente útil porque permite comparar la disponibilidad de luminarias teniendo en cuenta la extensión geográfica de cada UPZ.

ggplot(upz, aes(x = luminarias_km2)) +
  geom_histogram(
    bins = 20,
    fill = turquesa,
    color = "white",
    alpha = 0.9
  ) +
  labs(
    title = "Distribución de la densidad de luminarias",
    subtitle = "Cantidad de luminarias por kilómetro cuadrado en cada UPZ",
    x = "Luminarias por km²",
    y = "Cantidad de UPZ",
    caption = "Fuente: información de alumbrado público, última actualización 2021."
  ) +
  tema_clase

Para identificar las diferencias territoriales, se construyen dos rankings que permiten reconocer las diez UPZ con mayor y menor densidad de luminarias. Se incluyen también el área y la cantidad total de luminarias para facilitar la comparación.

mayor_alumbrado <- upz %>%
  arrange(desc(luminarias_km2)) %>%
  select(
    upz_nombre,
    localidad,
    area_km2,
    luminarias,
    luminarias_km2,
    pct_luminarias_led
  ) %>%
  slice_head(n = 10)

menor_alumbrado <- upz %>%
  arrange(luminarias_km2) %>%
  select(
    upz_nombre,
    localidad,
    area_km2,
    luminarias,
    luminarias_km2,
    pct_luminarias_led
  ) %>%
  slice_head(n = 10)

knitr::kable(
  mayor_alumbrado,
  digits = 2,
  caption = "Diez UPZ con mayor densidad de luminarias"
)
Diez UPZ con mayor densidad de luminarias
upz_nombre localidad area_km2 luminarias luminarias_km2 pct_luminarias_led
Minuto De Dios Engativá 3.75 6561 1751.44 60.75
Las Nieves Santa Fe 1.73 2863 1653.05 36.22
Patio Bonito Kennedy 3.18 5157 1619.34 87.61
Muzu Puente Aranda 2.54 4054 1597.74 75.85
Diana Turbay Rafael Uribe Uribe 2.12 3269 1540.56 89.81
Timiza Kennedy 4.32 6309 1460.46 81.80
La Candelaria Candelaria 2.07 2985 1443.66 15.61
Bosa Occidental Bosa 4.32 6110 1414.58 88.09
Chico Lago Chapinero 4.24 5987 1412.14 38.85
San Francisco Ciudad Bolívar 1.79 2516 1403.65 4.53
knitr::kable(
  menor_alumbrado,
  digits = 2,
  caption = "Diez UPZ con menor densidad de luminarias"
)
Diez UPZ con menor densidad de luminarias
upz_nombre localidad area_km2 luminarias luminarias_km2 pct_luminarias_led
Parque Entrenubes Usme 4.21 77 18.31 67.53
Guaymaral Suba 4.55 184 40.42 0.00
El Mochuelo Ciudad Bolívar 3.18 131 41.21 0.00
Monte Blanco Ciudad Bolívar 6.98 388 55.57 11.86
Aeropuerto El Dorado Fontibón 7.46 515 69.06 22.52
La Academia Suba 6.74 534 79.17 0.37
Paseo De Los Libertadores Usaquén 6.33 524 82.75 28.44
Ciudad Usme Usme 9.29 1080 116.28 74.44
Tintal Norte Kennedy 3.45 461 133.77 51.84
Zona Franca Fontibón 4.93 1189 241.00 45.16

5.2.5. Relación entre viviendas desocupadas y alumbrado público

Finalmente, se explora la relación entre el porcentaje de viviendas desocupadas y la densidad de luminarias por kilómetro cuadrado.

Esta comparación permite observar si existen patrones entre ambas características del entorno urbano. Se incorpora una línea de tendencia como apoyo visual para identificar el comportamiento general de los datos.

Este ejercicio tiene un alcance exploratorio y no permite establecer relaciones de causalidad.

ggplot(
  upz,
  aes(
    x = pct_viviendas_desocupadas,
    y = luminarias_km2
  )
) +
  geom_point(
    color = morado,
    alpha = 0.7,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = FALSE,
    color = magenta,
    linewidth = 1
  ) +
  labs(
    title = "Viviendas desocupadas y densidad de alumbrado",
    subtitle = "Relación exploratoria entre características del entorno urbano",
    x = "Porcentaje de viviendas desocupadas",
    y = "Luminarias por km²",
    caption = "Fuente: información consolidada de las UPZ."
  ) +
  tema_clase

5.2.6. Interpretación de resultados

Los resultados de este apartado permiten complementar la caracterización territorial de las UPZ mediante variables relacionadas con las condiciones de vivienda y la infraestructura de alumbrado público.

La interpretación se centrará en las diferencias observadas entre territorios, la distribución de las variables y los posibles patrones identificados en la comparación entre viviendas desocupadas y densidad de luminarias.

Se tendrá en cuenta que estos indicadores describen características del entorno urbano y que, por sí solos, no permiten explicar ni establecer causas del comportamiento delictivo.

5.3. Análisis socioeconómico

En esta sección se exploran las condiciones socioeconómicas de las UPZ de Bogotá a partir de la información de la Encuesta Multipropósito de 2021.

Se analizan variables relacionadas con la pobreza, el ingreso promedio, la composición por estrato socioeconómico y el nivel educativo de la población. Estas características permiten ampliar la comprensión de las diferencias territoriales e incorporar elementos sociales y económicos al análisis de la inseguridad.

El propósito es identificar cómo se distribuyen estas condiciones entre las UPZ y reconocer posibles patrones que posteriormente puedan contrastarse con los indicadores de delitos y percepción de inseguridad.

Es importante tener en cuenta que la Encuesta Multipropósito presenta información agrupada para 32 UPZ. En estos casos, varias unidades territoriales comparten el mismo valor estimado. Por esta razón, los resultados deben interpretarse con precaución y no asumir que cada registro representa una observación socioeconómica independiente.

5.3.1. Revisión de la información socioeconómica

Antes de analizar las variables socioeconómicas, se revisa la cobertura de la información de la Encuesta Multipropósito.

Esta verificación permite identificar cuántas UPZ cuentan con información individual y cuántas reciben valores compartidos con otras unidades territoriales. Esta distinción es importante para interpretar correctamente las estadísticas y evitar asumir que todos los registros representan mediciones independientes.

# Revisar la cantidad de UPZ con información individual y agrupada

revision_encuesta <- upz %>%
  count(em_agrupada) %>%
  mutate(
    Tipo_informacion = if_else(
      em_agrupada,
      "Información agrupada",
      "Información individual"
    ),
    Porcentaje = n / sum(n) * 100
  ) %>%
  select(
    Tipo_informacion,
    Cantidad_UPZ = n,
    Porcentaje
  )

knitr::kable(
  revision_encuesta,
  digits = 2,
  caption = "Cobertura de la Encuesta Multipropósito por tipo de información"
)
Cobertura de la Encuesta Multipropósito por tipo de información
Tipo_informacion Cantidad_UPZ Porcentaje
Información individual 80 71.43
Información agrupada 32 28.57

¿Qué buscamos identificar?

  • La cantidad de UPZ que tienen información individual.

  • La cantidad de UPZ que comparten información con otras unidades territoriales.

  • La proporción que representa cada grupo sobre el total de UPZ.

5.3.2. Estadísticas descriptivas de las condiciones socioeconómicas

Para caracterizar las condiciones socioeconómicas se seleccionan variables relacionadas con la pobreza, los ingresos, la composición por estrato y el nivel educativo.

Se calculan medidas de tendencia central y dispersión, incluyendo media, mediana, desviación estándar, cuartiles, valores mínimos y máximos. Estas medidas permiten reconocer las diferencias entre territorios y observar qué tan concentrados o dispersos se encuentran los indicadores.

La selección de estas variables busca representar diferentes dimensiones de las condiciones de vida, evitando limitar el análisis a una sola característica económica.

# Seleccionar las variables socioeconómicas de interés

variables_socioeconomicas <- upz %>%
  select(
    pct_pobreza,
    salario_promedio,
    pct_estrato_1_2,
    pct_estrato_3_4,
    pct_estrato_5_6,
    anios_educacion_15mas
  )

# Calcular estadísticas descriptivas

estadisticas_socioeconomicas <- variables_socioeconomicas %>%
  summarise(
    across(
      everything(),
      list(
        Media = ~ mean(.),
        Mediana = ~ median(.),
        Desviacion = ~ sd(.),
        Minimo = ~ min(.),
        Q1 = ~ quantile(., 0.25),
        Q3 = ~ quantile(., 0.75),
        Maximo = ~ max(.)
      )
    )
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = c("Variable", "Estadistica"),
    names_sep = "_(?=[^_]+$)",
    values_to = "Valor"
  ) %>%
  pivot_wider(
    names_from = Estadistica,
    values_from = Valor
  )

knitr::kable(
  estadisticas_socioeconomicas,
  digits = 2,
  caption = "Estadísticas descriptivas de las variables socioeconómicas"
)
Estadísticas descriptivas de las variables socioeconómicas
Variable Media Mediana Desviacion Minimo Q1 Q3 Maximo
pct_pobreza 4.01 2.58 3.95 0.07 0.98 5.82 16.56
salario_promedio 2580110.85 1866476.08 1735971.89 845688.39 1227872.19 3689024.52 7977532.49
pct_estrato_1_2 40.49 20.48 43.01 0.00 0.56 97.04 100.00
pct_estrato_3_4 51.62 69.13 41.59 0.00 2.15 93.17 100.00
pct_estrato_5_6 7.79 0.00 21.97 0.00 0.00 0.62 98.94
anios_educacion_15mas 11.89 11.80 2.23 7.98 9.89 13.57 15.91

5.3.3. Distribución de la pobreza

El porcentaje de pobreza permite aproximarse a las condiciones económicas de la población de cada territorio.

Mediante un histograma se examina la distribución de este indicador entre las UPZ, buscando identificar dónde se concentran los valores y si existen territorios con porcentajes considerablemente superiores al comportamiento general.

Este análisis permite reconocer diferencias socioeconómicas que posteriormente podrán contrastarse con los indicadores de seguridad.

ggplot(upz, aes(x = pct_pobreza)) +
  geom_histogram(
    bins = 20,
    fill = magenta,
    color = "white",
    alpha = 0.9
  ) +
  labs(
    title = "Distribución del porcentaje de pobreza por UPZ",
    subtitle = "Porcentaje de personas clasificadas como pobres",
    x = "Población en condición de pobreza (%)",
    y = "Cantidad de UPZ",
    caption = "Fuente: Encuesta Multipropósito DANE, 2021."
  ) +
  tema_clase

Para complementar el gráfico, identificamos los territorios con mayores y menores porcentajes de pobreza.

ranking_pobreza <- upz %>%
  arrange(desc(pct_pobreza)) %>%
  select(
    upz_nombre,
    localidad,
    em_agrupada,
    pct_pobreza
  )

knitr::kable(
  ranking_pobreza %>% slice_head(n = 10),
  digits = 2,
  caption = "Diez UPZ con mayor porcentaje de pobreza"
)
Diez UPZ con mayor porcentaje de pobreza
upz_nombre localidad em_agrupada pct_pobreza
Alfonso Lopez Usme TRUE 16.56
Ciudad Usme Usme TRUE 16.56
La Flora Usme FALSE 15.09
Lourdes Santa Fe FALSE 14.12
El Mochuelo Ciudad Bolívar TRUE 12.89
Monte Blanco Ciudad Bolívar TRUE 12.89
El Tesoro Ciudad Bolívar TRUE 12.89
Lucero Ciudad Bolívar FALSE 10.47
Danubio Usme TRUE 10.31
Parque Entrenubes Usme TRUE 10.31
knitr::kable(
  ranking_pobreza %>%
    arrange(pct_pobreza) %>%
    slice_head(n = 10),
  digits = 2,
  caption = "Diez UPZ con menor porcentaje de pobreza"
)
Diez UPZ con menor porcentaje de pobreza
upz_nombre localidad em_agrupada pct_pobreza
Country Club Usaquén TRUE 0.07
Santa Barbara Usaquén TRUE 0.07
Granjas De Techo Fontibón FALSE 0.09
Ciudad Salitre Oriental Teusaquillo FALSE 0.12
La Alhambra Suba FALSE 0.22
Parque Simon Bolivar - Can Teusaquillo TRUE 0.26
La Esmeralda Teusaquillo TRUE 0.26
Ciudad Salitre Occidental Fontibón FALSE 0.26
Modelia Fontibón FALSE 0.31
Teusaquillo Teusaquillo FALSE 0.33

5.3.4. Distribución del salario promedio

El salario promedio permite explorar las diferencias económicas entre los territorios.

Se utiliza un histograma para observar la distribución de los ingresos y reconocer posibles concentraciones o valores extremos. También se identifican las UPZ con mayores y menores salarios promedio.

Debido a que los ingresos pueden presentar diferencias importantes entre territorios, se compararán la media y la mediana para evaluar la influencia de los valores extremos sobre el promedio.

ggplot(upz, aes(x = salario_promedio)) +
  geom_histogram(
    bins = 20,
    fill = turquesa,
    color = "white",
    alpha = 0.9
  ) +
  labs(
    title = "Distribución del salario promedio por UPZ",
    subtitle = "Ingreso mensual promedio reportado en la Encuesta Multipropósito",
    x = "Salario promedio mensual (pesos)",
    y = "Cantidad de UPZ",
    caption = "Fuente: Encuesta Multipropósito DANE, 2021."
  ) +
  scale_x_continuous(
    labels = scales::label_number(
      prefix = "$",
      big.mark = ".",
      decimal.mark = ","
    )
  ) +
  tema_clase

Ranking de salarios:

ranking_salario <- upz %>%
  arrange(desc(salario_promedio)) %>%
  select(
    upz_nombre,
    localidad,
    em_agrupada,
    salario_promedio
  )

knitr::kable(
  ranking_salario %>% slice_head(n = 10),
  digits = 0,
  caption = "Diez UPZ con mayor salario promedio"
)
Diez UPZ con mayor salario promedio
upz_nombre localidad em_agrupada salario_promedio
El Refugio Chapinero TRUE 7977532
Chico Lago Chapinero TRUE 7977532
Country Club Usaquén TRUE 7624587
Santa Barbara Usaquén TRUE 7624587
Usaquen Usaquén FALSE 6893541
La Alhambra Suba FALSE 5907659
Ciudad Salitre Oriental Teusaquillo FALSE 5887923
Niza Suba FALSE 5276414
Los Cedros Usaquén FALSE 5226504
Pardo Rubio Chapinero TRUE 4981378
knitr::kable(
  ranking_salario %>%
    arrange(salario_promedio) %>%
    slice_head(n = 10),
  digits = 0,
  caption = "Diez UPZ con menor salario promedio"
)
Diez UPZ con menor salario promedio
upz_nombre localidad em_agrupada salario_promedio
La Flora Usme FALSE 845688
Lucero Ciudad Bolívar FALSE 949613
Patio Bonito Kennedy FALSE 956988
El Mochuelo Ciudad Bolívar TRUE 966749
Monte Blanco Ciudad Bolívar TRUE 966749
El Tesoro Ciudad Bolívar TRUE 966749
Jerusalem Ciudad Bolívar FALSE 985043
Alfonso Lopez Usme TRUE 1007783
Ciudad Usme Usme TRUE 1007783
Diana Turbay Rafael Uribe Uribe FALSE 1036645

5.3.5. Composición por estrato socioeconómico

La composición por estrato permite observar las características socioeconómicas de las viviendas de cada UPZ.

Para este análisis se consideran tres grupos: estratos 1 y 2, estratos 3 y 4, y estratos 5 y 6. La comparación permite identificar qué grupos tienen mayor participación en cada territorio y reconocer las diferencias en la composición socioeconómica de las UPZ.

Es importante recordar que los porcentajes representan la distribución de viviendas por grupo de estrato y no deben interpretarse como una medición directa del ingreso de todos sus habitantes.

# Calcular el promedio de participación de cada grupo de estrato

promedio_estratos <- upz %>%
  summarise(
    `Estratos 1 y 2` = mean(pct_estrato_1_2),
    `Estratos 3 y 4` = mean(pct_estrato_3_4),
    `Estratos 5 y 6` = mean(pct_estrato_5_6)
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Grupo_estrato",
    values_to = "Porcentaje_promedio"
  )

knitr::kable(
  promedio_estratos,
  digits = 2,
  caption = "Participación promedio de los grupos de estrato entre las UPZ"
)
Participación promedio de los grupos de estrato entre las UPZ
Grupo_estrato Porcentaje_promedio
Estratos 1 y 2 40.49
Estratos 3 y 4 51.62
Estratos 5 y 6 7.79

Ahora visualizamos los resultados:

ggplot(
  promedio_estratos,
  aes(
    x = Grupo_estrato,
    y = Porcentaje_promedio
  )
) +
  geom_col(
    fill = morado,
    width = 0.65
  ) +
  labs(
    title = "Composición promedio por grupos de estrato",
    subtitle = "Participación promedio de cada grupo entre las UPZ",
    x = "Grupo de estrato",
    y = "Porcentaje promedio (%)",
    caption = "Fuente: Encuesta Multipropósito DANE, 2021."
  ) +
  tema_clase

Una precisión: este gráfico muestra el promedio simple de los porcentajes de las UPZ, no la distribución ponderada de todas las viviendas de Bogotá.

5.3.6. Nivel educativo

El nivel educativo constituye otra dimensión importante para caracterizar las condiciones socioeconómicas de los territorios.

En este apartado se analiza el promedio de años de educación de las personas de 15 años o más. Esta variable permite explorar las diferencias educativas entre UPZ y complementar la caracterización económica realizada anteriormente.

estadisticas_educacion <- upz %>%
  summarise(
    Media = mean(anios_educacion_15mas),
    Mediana = median(anios_educacion_15mas),
    Desviacion_estandar = sd(anios_educacion_15mas),
    Minimo = min(anios_educacion_15mas),
    Q1 = quantile(anios_educacion_15mas, 0.25),
    Q3 = quantile(anios_educacion_15mas, 0.75),
    Maximo = max(anios_educacion_15mas)
  )

knitr::kable(
  estadisticas_educacion,
  digits = 2,
  caption = "Estadísticas descriptivas del nivel educativo por UPZ"
)
Estadísticas descriptivas del nivel educativo por UPZ
Media Mediana Desviacion_estandar Minimo Q1 Q3 Maximo
11.89 11.8 2.23 7.98 9.89 13.57 15.91

Distribución del nivel educativo:

ggplot(upz, aes(x = anios_educacion_15mas)) +
  geom_histogram(
    bins = 20,
    fill = magenta,
    color = "white",
    alpha = 0.9
  ) +
  labs(
    title = "Distribución de los años promedio de educación",
    subtitle = "Personas de 15 años o más por UPZ",
    x = "Años promedio de educación",
    y = "Cantidad de UPZ",
    caption = "Fuente: Encuesta Multipropósito DANE, 2021."
  ) +
  tema_clase

5.3.7. Relación entre pobreza y salario promedio

Para complementar la descripción individual de las variables, se explora la relación entre el porcentaje de pobreza y el salario promedio mensual de las UPZ.

Se utiliza un diagrama de dispersión, en el que cada punto representa una unidad territorial. Se incorpora una línea de tendencia para observar el comportamiento general de ambas variables.

Esta comparación permite identificar posibles asociaciones entre las condiciones de pobreza y los ingresos promedio, sin asumir que una variable sea necesariamente la causa de la otra.

ggplot(
  upz,
  aes(
    x = pct_pobreza,
    y = salario_promedio
  )
) +
  geom_point(
    color = morado,
    alpha = 0.7,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = FALSE,
    color = magenta,
    linewidth = 1
  ) +
  labs(
    title = "Relación entre pobreza y salario promedio",
    subtitle = "Comparación de condiciones socioeconómicas entre UPZ",
    x = "Porcentaje de pobreza (%)",
    y = "Salario promedio mensual (pesos)",
    caption = "Fuente: Encuesta Multipropósito DANE, 2021."
  ) +
  scale_y_continuous(
    labels = scales::label_number(
      prefix = "$",
      big.mark = ".",
      decimal.mark = ","
    )
  ) +
  tema_clase

5.3.8. Interpretación de resultados

El análisis socioeconómico permite ampliar la caracterización de las UPZ mediante indicadores relacionados con la pobreza, los ingresos, la composición por estrato y el nivel educativo.

A partir de las estadísticas descriptivas y las visualizaciones se examinarán las diferencias entre territorios, la dispersión de los indicadores y los posibles patrones entre las condiciones económicas y educativas.

Estos resultados servirán como referencia para los análisis posteriores, especialmente al explorar posibles relaciones entre las características socioeconómicas y los indicadores de seguridad.

5.4. Análisis de percepción de inseguridad y condiciones del entorno

La percepción de inseguridad constituye una dimensión importante para comprender las condiciones de seguridad de un territorio. A diferencia de los registros de delitos denunciados, este indicador recoge la experiencia y percepción de las personas frente a los problemas de inseguridad presentes en el entorno de su vivienda.

En esta sección se exploran las diferencias entre UPZ en cuanto a la percepción de inseguridad, algunas condiciones del entorno y la accesibilidad a los servicios de policía. El propósito es identificar patrones y posibles asociaciones que permitan ampliar la comprensión de las características territoriales relacionadas con la seguridad.

5.4.1. Selección de variables

Para desarrollar este análisis se seleccionamos seis variables de la Encuesta Multipropósito, relacionadas con la percepción de inseguridad, las condiciones del entorno y la accesibilidad a los servicios de policía.

La selección permite explorar diferentes características territoriales que pueden aportar información para comprender las diferencias entre las UPZ. Se analizará el porcentaje de percepción de inseguridad, la cercanía a determinados elementos del entorno y el tiempo promedio caminando hasta un CAI o estación de policía.

# Selección de variables de percepción y condiciones del entorno

variables_entorno <- upz %>%
  select(
    pct_percibe_inseguridad,
    pct_cerca_ollas,
    pct_cerca_bares,
    pct_cerca_lotes_oscuros,
    pct_cerca_basureros,
    min_cai_policia
  )

# Visualización de las primeras observaciones

head(variables_entorno)
pct_percibe_inseguridad pct_cerca_ollas pct_cerca_bares pct_cerca_lotes_oscuros pct_cerca_basureros min_cai_policia
36.18 17.53 15.68 24.15 6.13 21.66
40.88 7.43 17.03 16.71 1.35 24.50
40.88 7.43 17.03 16.71 1.35 24.50
65.43 17.53 15.68 24.15 6.13 18.39
36.18 17.53 15.68 24.15 6.13 21.66
49.84 25.91 15.41 19.15 8.30 25.32

5.4.2. Estadísticas descriptivas de percepción y entorno

Como punto de partida, se calculan las principales medidas de estadística descriptiva para las variables seleccionadas. Este ejercicio permite conocer los niveles generales de percepción de inseguridad, las condiciones del entorno y los tiempos promedio de desplazamiento hasta los servicios de policía.

Se consideran medidas de tendencia central, dispersión y posición, con el propósito de identificar tanto el comportamiento general como las diferencias existentes entre las UPZ.

# Cálculo de estadísticas descriptivas

estadisticas_entorno <- variables_entorno %>%
  summarise(
    across(
      everything(),
      list(
        Media = ~mean(.),
        Mediana = ~median(.),
        Desviacion = ~sd(.),
        Minimo = ~min(.),
        Q1 = ~quantile(., 0.25),
        Q3 = ~quantile(., 0.75),
        Maximo = ~max(.)
      )
    )
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = c("Variable", "Estadistica"),
    names_sep = "_(?=[^_]+$)",
    values_to = "Valor"
  ) %>%
  pivot_wider(
    names_from = Estadistica,
    values_from = Valor
  )

knitr::kable(
  estadisticas_entorno,
  digits = 2,
  caption = "Estadísticas descriptivas de percepción de inseguridad y condiciones del entorno"
)
Estadísticas descriptivas de percepción de inseguridad y condiciones del entorno
Variable Media Mediana Desviacion Minimo Q1 Q3 Maximo
pct_percibe_inseguridad 60.84 65.97 18.87 17.45 44.75 74.33 92.11
pct_cerca_ollas 21.59 20.56 15.85 0.31 9.05 31.11 75.60
pct_cerca_bares 14.42 12.96 10.76 0.64 5.71 19.40 53.91
pct_cerca_lotes_oscuros 19.98 18.16 12.56 0.64 11.68 26.01 59.76
pct_cerca_basureros 9.50 6.12 9.63 0.24 2.72 12.11 45.01
min_cai_policia 18.36 17.64 4.57 10.06 15.38 20.84 35.11

5.4.3. Distribución de la percepción de inseguridad

La percepción de inseguridad permite aproximarse a la manera en que los habitantes reconocen los problemas de seguridad presentes en su entorno cotidiano.

Para explorar su comportamiento entre las UPZ, se utiliza un histograma que permite visualizar la distribución de los porcentajes reportados. Esta representación facilita identificar los rangos de mayor concentración, la dispersión de los valores y posibles diferencias entre los territorios.

El análisis permite reconocer si la percepción de inseguridad presenta un comportamiento relativamente homogéneo o si existen diferencias importantes entre las zonas estudiadas.

ggplot(
  upz,
  aes(x = pct_percibe_inseguridad)
) +
  geom_histogram(
    bins = 15,
    fill = magenta,
    color = "white",
    alpha = 0.85
  ) +
  labs(
    title = "Distribución de la percepción de inseguridad",
    subtitle = "Porcentaje reportado en las UPZ de Bogotá",
    x = "Percepción de inseguridad (%)",
    y = "Cantidad de UPZ",
    caption = "Fuente: Encuesta Multipropósito DANE, 2021."
  ) +
  scale_x_continuous(
    labels = scales::label_number(suffix = "%")
  ) +
  tema_clase

5.4.4. Identificación de las UPZ con mayor y menor percepción de inseguridad

Con el propósito de identificar las diferencias territoriales, se construyen dos rankings que permiten reconocer las diez UPZ con mayores y menores porcentajes de percepción de inseguridad.

Esta comparación facilita identificar los territorios que presentan los valores más altos y bajos del indicador, complementando la lectura general obtenida mediante el histograma.

Adicionalmente, se incluye la variable em_agrupada para identificar las UPZ cuyos resultados provienen de estimaciones compartidas con otros territorios, condición que debe tenerse en cuenta al interpretar las posiciones del ranking.

# Diez UPZ con mayor percepción de inseguridad

mayor_percepcion <- upz %>%
  arrange(desc(pct_percibe_inseguridad)) %>%
  select(
    upz_nombre,
    localidad,
    em_agrupada,
    pct_percibe_inseguridad
  ) %>%
  slice_head(n = 10)

knitr::kable(
  mayor_percepcion,
  digits = 2,
  caption = "Diez UPZ con mayor percepción de inseguridad"
)
Diez UPZ con mayor percepción de inseguridad
upz_nombre localidad em_agrupada pct_percibe_inseguridad
Corabastos Kennedy FALSE 92.11
Tunjuelito Tunjuelito FALSE 91.82
Bosa Central Bosa FALSE 89.69
El Mochuelo Ciudad Bolívar TRUE 86.83
Monte Blanco Ciudad Bolívar TRUE 86.83
El Tesoro Ciudad Bolívar TRUE 86.83
Patio Bonito Kennedy FALSE 86.07
La Gloria San Cristóbal FALSE 86.04
Las Cruces Santa Fe FALSE 85.97
La Sabana Los Mártires FALSE 83.45
# Diez UPZ con menor percepción de inseguridad

menor_percepcion <- upz %>%
  arrange(pct_percibe_inseguridad) %>%
  select(
    upz_nombre,
    localidad,
    em_agrupada,
    pct_percibe_inseguridad
  ) %>%
  slice_head(n = 10)

knitr::kable(
  menor_percepcion,
  digits = 2,
  caption = "Diez UPZ con menor percepción de inseguridad"
)
Diez UPZ con menor percepción de inseguridad
upz_nombre localidad em_agrupada pct_percibe_inseguridad
Casa Blanca Suba Suba FALSE 17.45
Bolivia Engativá FALSE 19.37
Ciudad Salitre Oriental Teusaquillo FALSE 20.37
El Refugio Chapinero TRUE 21.48
Chico Lago Chapinero TRUE 21.48
Usaquen Usaquén FALSE 24.45
Ciudad Salitre Occidental Fontibón FALSE 26.72
Capellania Fontibón TRUE 32.58
Aeropuerto El Dorado Fontibón TRUE 32.58
Parque Simon Bolivar - Can Teusaquillo TRUE 32.98

5.4.5. Comparación de las condiciones del entorno

Las condiciones del entorno constituyen una dimensión complementaria para comprender las características territoriales asociadas con la percepción de inseguridad. En este apartado se analizan cuatro indicadores relacionados con la cercanía a expendios de droga, bares o prostíbulos, lotes baldíos o sitios oscuros y basureros.

Para facilitar la comparación, se calcula el promedio simple de los porcentajes reportados por las UPZ y se presentan los resultados mediante una tabla y un gráfico de barras. Esto permite reconocer cuáles de las condiciones analizadas presentan una mayor presencia promedio en los territorios estudiados.

Es importante aclarar que estos resultados corresponden al promedio de los porcentajes de las UPZ y no al porcentaje agregado de viviendas afectadas en Bogotá. Cada UPZ tiene el mismo peso en el cálculo, independientemente de su cantidad de viviendas.

# Cálculo del promedio simple de cada condición entre las UPZ

promedios_entorno <- upz %>%
  summarise(
    Ollas = mean(pct_cerca_ollas),
    Bares = mean(pct_cerca_bares),
    Lotes_oscuros = mean(pct_cerca_lotes_oscuros),
    Basureros = mean(pct_cerca_basureros)
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Condicion",
    values_to = "Promedio"
  ) %>%
  arrange(desc(Promedio))

# Presentación de resultados

knitr::kable(
  promedios_entorno,
  digits = 2,
  caption = "Promedio simple de las condiciones del entorno por UPZ"
)
Promedio simple de las condiciones del entorno por UPZ
Condicion Promedio
Ollas 21.59
Lotes_oscuros 19.98
Bares 14.42
Basureros 9.50

Ahora representamos los resultados mediante un gráfico de barras.

ggplot(
  promedios_entorno,
  aes(
    x = reorder(Condicion, Promedio),
    y = Promedio
  )
) +
  geom_col(
    fill = turquesa,
    width = 0.65
  ) +
  coord_flip() +
  labs(
    title = "Condiciones del entorno reportadas en las UPZ",
    subtitle = "Promedio simple de los porcentajes por UPZ",
    x = NULL,
    y = "Promedio (%)",
    caption = "Fuente: Encuesta Multipropósito DANE, 2021."
  ) +
  scale_y_continuous(
    labels = scales::label_number(suffix = "%")
  ) +
  tema_clase

5.4.6. Tiempo de desplazamiento hasta un CAI o estación de policía

La accesibilidad a los servicios de policía representa otra característica relevante para el análisis territorial. En este apartado se examina el tiempo promedio caminando desde las viviendas hasta un CAI o estación de policía, con el propósito de identificar diferencias entre las UPZ.

Se utilizan medidas descriptivas, un histograma y una comparación de los territorios con mayores y menores tiempos de desplazamiento. De esta manera, se busca reconocer cómo se distribuye la accesibilidad a estos servicios en las zonas estudiadas.

Este indicador representa un tiempo promedio de desplazamiento y no debe interpretarse como una medida directa de presencia policial, cobertura operativa o tiempo de respuesta ante una emergencia.

estadisticas_cai <- upz %>%
  summarise(
    Media = mean(min_cai_policia),
    Mediana = median(min_cai_policia),
    Desviacion = sd(min_cai_policia),
    Minimo = min(min_cai_policia),
    Q1 = quantile(min_cai_policia, 0.25),
    Q3 = quantile(min_cai_policia, 0.75),
    Maximo = max(min_cai_policia)
  )

knitr::kable(
  estadisticas_cai,
  digits = 2,
  caption = "Estadísticas descriptivas del tiempo de desplazamiento hasta un CAI"
)
Estadísticas descriptivas del tiempo de desplazamiento hasta un CAI
Media Mediana Desviacion Minimo Q1 Q3 Maximo
18.36 17.64 4.57 10.06 15.38 20.84 35.11

Ahora visualizamos la distribución de los tiempos.

ggplot(
  upz,
  aes(x = min_cai_policia)
) +
  geom_histogram(
    bins = 15,
    fill = morado,
    color = "white",
    alpha = 0.85
  ) +
  labs(
    title = "Distribución del tiempo de desplazamiento a un CAI",
    subtitle = "Tiempo promedio caminando por UPZ",
    x = "Minutos caminando",
    y = "Cantidad de UPZ",
    caption = "Fuente: Encuesta Multipropósito DANE, 2021."
  ) +
  tema_clase

Finalmente, identificamos las diez UPZ con mayores y menores tiempos.

# Diez UPZ con mayor tiempo de desplazamiento

mayor_tiempo_cai <- upz %>%
  arrange(desc(min_cai_policia)) %>%
  select(
    upz_nombre,
    localidad,
    em_agrupada,
    min_cai_policia
  ) %>%
  slice_head(n = 10)

knitr::kable(
  mayor_tiempo_cai,
  digits = 2,
  caption = "Diez UPZ con mayor tiempo promedio caminando hasta un CAI"
)
Diez UPZ con mayor tiempo promedio caminando hasta un CAI
upz_nombre localidad em_agrupada min_cai_policia
San Isidro - Patios Chapinero FALSE 35.11
Fontibon San Pablo Fontibón FALSE 28.50
Quinta Paredes Teusaquillo FALSE 27.64
El Mochuelo Ciudad Bolívar TRUE 27.39
Monte Blanco Ciudad Bolívar TRUE 27.39
El Tesoro Ciudad Bolívar TRUE 27.39
Zona Franca Fontibón FALSE 27.00
Capellania Fontibón TRUE 26.31
Aeropuerto El Dorado Fontibón TRUE 26.31
San Cristobal Norte Usaquén FALSE 25.32
# Diez UPZ con menor tiempo de desplazamiento

menor_tiempo_cai <- upz %>%
  arrange(min_cai_policia) %>%
  select(
    upz_nombre,
    localidad,
    em_agrupada,
    min_cai_policia
  ) %>%
  slice_head(n = 10)

knitr::kable(
  menor_tiempo_cai,
  digits = 2,
  caption = "Diez UPZ con menor tiempo promedio caminando hasta un CAI"
)
Diez UPZ con menor tiempo promedio caminando hasta un CAI
upz_nombre localidad em_agrupada min_cai_policia
Sagrado Corazon Santa Fe TRUE 10.06
Las Nieves Santa Fe TRUE 10.06
Teusaquillo Teusaquillo FALSE 10.36
La Macarena Santa Fe FALSE 10.95
Lourdes Santa Fe FALSE 11.39
Restrepo Antonio Nariño FALSE 12.17
La Candelaria Candelaria FALSE 12.73
Los Alcazares Barrios Unidos FALSE 12.78
Galerias Teusaquillo FALSE 12.79
Danubio Usme TRUE 12.88

5.4.7. Relación entre la percepción de inseguridad y las condiciones del entorno

Después de analizar individualmente la percepción de inseguridad, las condiciones del entorno y la accesibilidad a los servicios de policía, se exploran las posibles relaciones entre estas variables.

El propósito es identificar si las UPZ que presentan mayores porcentajes de percepción de inseguridad también registran mayores porcentajes de viviendas cercanas a expendios de droga, bares o prostíbulos, lotes baldíos o sitios oscuros y basureros. De igual manera, se examina la posible relación entre la percepción de inseguridad y el tiempo promedio de desplazamiento caminando hasta un CAI o estación de policía.

Para este ejercicio se utilizan gráficos de dispersión y el coeficiente de correlación de Spearman. Esta medida permite explorar la dirección y la intensidad de las asociaciones entre las variables, sin asumir necesariamente una relación lineal.

Los resultados deben interpretarse como asociaciones exploratorias y no como evidencia de causalidad. Adicionalmente, se debe considerar que algunas estimaciones de la Encuesta Multipropósito se encuentran agrupadas entre varias UPZ, lo que limita la independencia de las observaciones y exige precaución al comparar los resultados.

# Preparación de las variables para comparar las relaciones

relaciones_entorno <- upz %>%
  select(
    upz_nombre,
    pct_percibe_inseguridad,
    pct_cerca_ollas,
    pct_cerca_bares,
    pct_cerca_lotes_oscuros,
    pct_cerca_basureros,
    min_cai_policia
  ) %>%
  pivot_longer(
    cols = c(
      pct_cerca_ollas,
      pct_cerca_bares,
      pct_cerca_lotes_oscuros,
      pct_cerca_basureros,
      min_cai_policia
    ),
    names_to = "Condicion",
    values_to = "Valor"
  ) %>%
  mutate(
    Condicion = recode(
      Condicion,
      pct_cerca_ollas = "Cercanía a expendios de droga",
      pct_cerca_bares = "Cercanía a bares o prostíbulos",
      pct_cerca_lotes_oscuros = "Cercanía a lotes oscuros",
      pct_cerca_basureros = "Cercanía a basureros",
      min_cai_policia = "Tiempo de desplazamiento a un CAI"
    )
  )

# Gráfico de dispersión por condición del entorno

ggplot(
  relaciones_entorno,
  aes(
    x = Valor,
    y = pct_percibe_inseguridad
  )
) +
  geom_point(
    color = turquesa,
    alpha = 0.65,
    size = 2
  ) +
  geom_smooth(
    method = "lm",
    se = FALSE,
    color = magenta,
    linewidth = 0.8
  ) +
  facet_wrap(
    ~Condicion,
    scales = "free_x"
  ) +
  labs(
    title = "Percepción de inseguridad y condiciones del entorno",
    subtitle = "Relación exploratoria entre variables por UPZ",
    x = "Valor de la condición analizada",
    y = "Percepción de inseguridad (%)",
    caption = "Fuente: Encuesta Multipropósito DANE, 2021."
  ) +
  tema_clase

La línea representa una tendencia lineal de referencia. No significa que exista una relación causal.

Con este cálculo podremos complementar visualmente los gráficos y comparar la intensidad de las asociaciones mediante valores entre -1 y 1.

# Selección de variables para el análisis de correlación

datos_correlacion_entorno <- upz %>%
  select(
    pct_percibe_inseguridad,
    pct_cerca_ollas,
    pct_cerca_bares,
    pct_cerca_lotes_oscuros,
    pct_cerca_basureros,
    min_cai_policia
  )

# Cálculo de la matriz de correlaciones de Spearman

matriz_correlacion_entorno <- cor(
  datos_correlacion_entorno,
  method = "spearman",
  use = "complete.obs"
)

# Presentación de la matriz

knitr::kable(
  round(matriz_correlacion_entorno, 2),
  caption = "Matriz de correlaciones de Spearman entre percepción de inseguridad y condiciones del entorno"
)
Matriz de correlaciones de Spearman entre percepción de inseguridad y condiciones del entorno
pct_percibe_inseguridad pct_cerca_ollas pct_cerca_bares pct_cerca_lotes_oscuros pct_cerca_basureros min_cai_policia
pct_percibe_inseguridad 1.00 0.67 0.23 0.33 0.61 0.02
pct_cerca_ollas 0.67 1.00 0.52 0.72 0.83 0.05
pct_cerca_bares 0.23 0.52 1.00 0.40 0.39 -0.09
pct_cerca_lotes_oscuros 0.33 0.72 0.40 1.00 0.76 0.35
pct_cerca_basureros 0.61 0.83 0.39 0.76 1.00 0.04
min_cai_policia 0.02 0.05 -0.09 0.35 0.04 1.00

Matriz de correlaciones entre percepción de inseguridad y condiciones del entorno

Para complementar el análisis de las relaciones entre las variables, se construye una matriz de correlaciones representada mediante un mapa de calor. Esta visualización permite identificar de manera conjunta la dirección y la intensidad de las asociaciones entre la percepción de inseguridad, las condiciones del entorno y el tiempo de desplazamiento hasta los servicios de policía.

Se utiliza el coeficiente de correlación de Spearman, cuyos valores oscilan entre -1 y 1. Los valores positivos representan asociaciones directas, mientras que los negativos indican asociaciones inversas. Los valores cercanos a cero reflejan asociaciones monotónicas débiles.

La representación mediante colores facilita la identificación de patrones y permite comparar visualmente las relaciones entre las variables seleccionadas.

# Cálculo de la matriz de correlaciones de Spearman

matriz_correlacion_entorno <- upz %>%
  select(
    pct_percibe_inseguridad,
    pct_cerca_ollas,
    pct_cerca_bares,
    pct_cerca_lotes_oscuros,
    pct_cerca_basureros,
    min_cai_policia
  ) %>%
  cor(
    method = "spearman",
    use = "complete.obs"
  )

# Transformación de la matriz a formato largo

correlaciones_largas <- as.data.frame(
  as.table(matriz_correlacion_entorno)
) %>%
  rename(
    Variable_1 = Var1,
    Variable_2 = Var2,
    Correlacion = Freq
  )

# Construcción del mapa de calor

ggplot(
  correlaciones_largas,
  aes(
    x = Variable_1,
    y = Variable_2,
    fill = Correlacion
  )
) +
  geom_tile(
    color = "white",
    linewidth = 1
  ) +
  geom_text(
    aes(label = round(Correlacion, 2)),
    color = "black",
    size = 3.5
  ) +
  scale_fill_gradient2(
    low = morado,
    mid = "white",
    high = magenta,
    midpoint = 0,
    limits = c(-1, 1),
    name = "Correlación"
  ) +
  labs(
    title = "Mapa de calor de correlaciones",
    subtitle = "Percepción de inseguridad y condiciones del entorno",
    x = NULL,
    y = NULL,
    caption = "Método: Spearman | Fuente: Encuesta Multipropósito DANE, 2021."
  ) +
  coord_fixed() +
  tema_clase +
  theme(
    axis.text.x = element_text(
      angle = 45,
      hjust = 1,
      color = morado
    ),
    axis.text.y = element_text(
      color = morado
    ),
    panel.grid = element_blank(),
    legend.position = "right"
  )

5.5. Análisis de delitos de alto impacto

En esta sección se analiza el comportamiento de los delitos de alto impacto registrados en las UPZ de Bogotá, con el propósito de identificar diferencias territoriales en la cantidad de denuncias y en las tasas de ocurrencia por habitante.

A diferencia del análisis anterior, centrado en la percepción de inseguridad y las condiciones del entorno, este apartado utiliza registros administrativos de delitos denunciados. De esta manera, se busca complementar la exploración territorial mediante información sobre homicidios, lesiones personales, hurtos y violencia intrafamiliar, entre otras categorías.

Para el análisis se consideran dos medidas principales: el número de casos registrados y la tasa por cada 10.000 habitantes. La primera permite dimensionar el volumen de denuncias, mientras que la segunda facilita la comparación entre UPZ con tamaños poblacionales diferentes.

Es importante señalar que los registros corresponden al periodo comprendido entre enero y julio de 2023, por lo que no representan el comportamiento de todo el año. Además, se trata de denuncias y no de la totalidad de los hechos delictivos ocurridos, debido a la posible existencia de subregistro.

Finalmente, las tasas deben interpretarse con precaución en las UPZ con poblaciones reducidas, ya que un número pequeño de casos puede producir valores relativamente elevados.

# Selección de variables relacionadas con los delitos de alto impacto

variables_delitos <- upz %>%
  select(
    upz_cod,
    upz_nombre,
    localidad,
    poblacion,
    starts_with("casos_"),
    starts_with("tasa_")
  )

# Revisar las primeras observaciones

head(variables_delitos)
upz_cod upz_nombre localidad poblacion casos_homicidios casos_lesiones casos_hurto_personas casos_hurto_residencias casos_hurto_automotor casos_hurto_bicicletas casos_hurto_comercio casos_hurto_celulares casos_hurto_motos casos_violencia_intrafamiliar casos_total tasa_homicidios tasa_lesiones tasa_hurto_personas tasa_hurto_residencias tasa_hurto_automotor tasa_hurto_bicicletas tasa_hurto_comercio tasa_hurto_celulares tasa_hurto_motos tasa_violencia_intrafamiliar tasa_total
1 Paseo De Los Libertadores Usaquén 2690 0 8 44 1 0 1 3 17 0 0 74 0.00 29.74 163.57 3.72 0.00 3.72 11.15 63.20 0.00 0.00 275.09
2 La Academia Suba 5260 1 3 75 0 3 1 9 26 0 5 123 1.90 5.70 142.59 0.00 5.70 1.90 17.11 49.43 0.00 9.51 233.84
3 Guaymaral Suba 2692 0 1 29 0 0 2 2 9 0 2 45 0.00 3.71 107.73 0.00 0.00 7.43 7.43 33.43 0.00 7.43 167.16
9 Verbenal Usaquén 131999 3 104 386 29 19 17 26 125 30 205 944 0.23 7.88 29.24 2.20 1.44 1.29 1.97 9.47 2.27 15.53 71.52
10 La Uribe Usaquén 37014 1 26 328 31 4 14 47 129 1 40 621 0.27 7.02 88.62 8.38 1.08 3.78 12.70 34.85 0.27 10.81 167.77
11 San Cristobal Norte Usaquén 72939 4 73 351 27 5 11 39 117 9 157 793 0.55 10.01 48.12 3.70 0.69 1.51 5.35 16.04 1.23 21.52 108.72

5.5.2. Estadísticas descriptivas de los delitos de alto impacto

Como punto de partida, se calculan las principales medidas de estadística descriptiva para las variables relacionadas con los delitos de alto impacto. Este ejercicio permite conocer la distribución de los casos registrados y de las tasas por cada 10.000 habitantes entre las UPZ de Bogotá.

Se consideran medidas de tendencia central, dispersión y posición, como la media, la mediana, la desviación estándar, los valores mínimos y máximos, y los cuartiles primero y tercero.

El análisis de estas medidas permite identificar diferencias en el comportamiento de los delitos entre los territorios. También facilita reconocer posibles valores extremos y establecer si los registros presentan una distribución homogénea o una concentración importante en determinadas UPZ.

Es importante diferenciar la interpretación de los casos y las tasas. Mientras los casos representan el volumen de denuncias registradas, las tasas permiten comparar los territorios considerando su tamaño poblacional. Sin embargo, estas últimas pueden presentar valores elevados en UPZ con poblaciones reducidas.

a. Estadísticas de casos registrados.

# Selección de variables de casos registrados

datos_casos <- variables_delitos %>%
  select(starts_with("casos_"))

# Cálculo de estadísticas descriptivas

estadisticas_casos <- datos_casos %>%
  pivot_longer(
    cols = everything(),
    names_to = "Delito",
    values_to = "Casos"
  ) %>%
  group_by(Delito) %>%
  summarise(
    Media = mean(Casos),
    Mediana = median(Casos),
    Desviacion = sd(Casos),
    Minimo = min(Casos),
    Q1 = quantile(Casos, 0.25),
    Q3 = quantile(Casos, 0.75),
    Maximo = max(Casos),
    .groups = "drop"
  ) %>%
  arrange(desc(Media))

# Presentación de resultados

knitr::kable(
  estadisticas_casos,
  digits = 2,
  caption = "Estadísticas descriptivas de los casos de delitos por UPZ"
)
Estadísticas descriptivas de los casos de delitos por UPZ
Delito Media Mediana Desviacion Minimo Q1 Q3 Maximo
casos_total 1453.88 1222.0 1023.07 16 779.50 1961.50 5441
casos_hurto_personas 762.48 597.5 602.99 5 358.50 978.75 3311
casos_hurto_celulares 275.95 233.5 228.52 1 125.00 346.50 1266
casos_violencia_intrafamiliar 143.33 100.5 150.84 0 48.00 182.25 818
casos_lesiones 88.34 74.5 67.44 1 38.25 122.00 317
casos_hurto_comercio 53.71 44.5 43.03 1 26.00 70.25 217
casos_hurto_bicicletas 40.95 30.5 36.55 0 11.75 58.25 171
casos_hurto_residencias 38.75 32.5 31.46 0 15.00 54.25 193
casos_hurto_motos 25.56 16.0 24.38 0 6.00 40.25 93
casos_hurto_automotor 19.46 14.5 18.05 0 5.00 26.25 74
casos_homicidios 5.35 3.0 6.81 0 1.00 7.00 47

b. Estadísticas de tasas por cada 10.000 habitantes.

# Selección de variables de tasas

datos_tasas <- variables_delitos %>%
  select(starts_with("tasa_"))

# Cálculo de estadísticas descriptivas

estadisticas_tasas <- datos_tasas %>%
  pivot_longer(
    cols = everything(),
    names_to = "Delito",
    values_to = "Tasa"
  ) %>%
  group_by(Delito) %>%
  summarise(
    Media = mean(Tasa),
    Mediana = median(Tasa),
    Desviacion = sd(Tasa),
    Minimo = min(Tasa),
    Q1 = quantile(Tasa, 0.25),
    Q3 = quantile(Tasa, 0.75),
    Maximo = max(Tasa),
    .groups = "drop"
  ) %>%
  arrange(desc(Media))

# Presentación de resultados

knitr::kable(
  estadisticas_tasas,
  digits = 2,
  caption = "Estadísticas descriptivas de las tasas de delitos por cada 10.000 habitantes y por UPZ"
)
Estadísticas descriptivas de las tasas de delitos por cada 10.000 habitantes y por UPZ
Delito Media Mediana Desviacion Minimo Q1 Q3 Maximo
tasa_total 503.64 192.52 1263.44 64.47 129.51 287.62 11333.33
tasa_hurto_personas 292.23 100.64 762.34 15.70 55.44 167.36 6333.33
tasa_hurto_celulares 104.48 35.11 282.79 7.29 19.32 61.84 2666.67
tasa_hurto_comercio 25.99 7.42 126.18 0.94 3.98 15.63 1333.33
tasa_violencia_intrafamiliar 23.74 17.63 30.99 0.00 11.88 24.22 232.06
tasa_lesiones 23.58 12.17 42.59 3.71 8.32 16.70 333.33
tasa_hurto_bicicletas 14.47 5.81 40.63 0.00 2.88 9.38 333.33
tasa_hurto_automotor 7.03 2.52 31.99 0.00 1.37 4.10 333.33
tasa_hurto_residencias 6.69 5.98 4.50 0.00 3.48 8.78 26.31
tasa_hurto_motos 4.51 3.22 7.96 0.00 1.53 5.27 79.28
tasa_homicidios 0.93 0.56 1.29 0.00 0.20 1.15 6.93

5.5.3. Distribución de los delitos de alto impacto

Con el propósito de complementar las medidas descriptivas, se analiza la distribución de los casos registrados y de las tasas de delitos entre las UPZ de Bogotá.

Para ello se utilizan histogramas que permiten observar la frecuencia con la que se presentan determinados rangos de valores. Esta representación facilita identificar concentraciones, asimetrías y posibles observaciones extremas en las diferentes categorías de delitos.

En primer lugar, se examina la distribución del número de casos registrados. Posteriormente, se realiza el mismo ejercicio para las tasas por cada 10.000 habitantes, con el fin de reconocer si el comportamiento de los delitos cambia al considerar el tamaño poblacional de cada territorio.

La comparación de ambas distribuciones permite distinguir entre la concentración de denuncias y las diferencias relativas entre las UPZ. Se debe tener en cuenta que las escalas de los gráficos son independientes para facilitar la visualización de cada categoría.

# Organización de los casos en formato largo

distribucion_casos <- variables_delitos %>%
  select(starts_with("casos_")) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Delito",
    values_to = "Casos"
  ) %>%
  mutate(
    Delito = str_remove(Delito, "^casos_"),
    Delito = str_replace_all(Delito, "_", " "),
    Delito = str_to_title(Delito)
  )

# Histograma de casos por categoría de delito

ggplot(
  distribucion_casos,
  aes(x = Casos)
) +
  geom_histogram(
    bins = 15,
    fill = turquesa,
    color = "white",
    alpha = 0.85
  ) +
  facet_wrap(
    ~Delito,
    scales = "free_x"
  ) +
  labs(
    title = "Distribución de los casos de delitos por UPZ",
    subtitle = "Número de denuncias registradas entre enero y julio de 2023",
    x = "Número de casos",
    y = "Cantidad de UPZ",
    caption = "Fuente: Secretaría Distrital de Seguridad, Convivencia y Justicia, 2023."
  ) +
  tema_clase

# Organización de las tasas en formato largo

distribucion_tasas <- variables_delitos %>%
  select(starts_with("tasa_")) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Delito",
    values_to = "Tasa"
  ) %>%
  mutate(
    Delito = str_remove(Delito, "^tasa_"),
    Delito = str_replace_all(Delito, "_", " "),
    Delito = str_to_title(Delito)
  )

# Histograma de tasas por categoría de delito

ggplot(
  distribucion_tasas,
  aes(x = Tasa)
) +
  geom_histogram(
    bins = 15,
    fill = magenta,
    color = "white",
    alpha = 0.85
  ) +
  facet_wrap(
    ~Delito,
    scales = "free_x"
  ) +
  labs(
    title = "Distribución de las tasas de delitos por UPZ",
    subtitle = "Casos registrados por cada 10.000 habitantes",
    x = "Tasa por cada 10.000 habitantes",
    y = "Cantidad de UPZ",
    caption = "Fuente: Secretaría Distrital de Seguridad, Convivencia y Justicia, 2023."
  ) +
  tema_clase

5.5.4. Participación de cada delito en el total de casos registrados

Con el propósito de identificar cuáles categorías concentran una mayor proporción de las denuncias registradas, se analiza la composición del total de casos de delitos de alto impacto en las UPZ estudiadas.

Para este ejercicio se suman los casos registrados en cada categoría de delito y se calcula su participación porcentual frente al total de denuncias acumuladas. Los resultados se presentan mediante una tabla y un gráfico de barras que facilitan la comparación entre las diferentes categorías.

Este análisis permite reconocer la composición de los registros administrativos y establecer cuáles tipos de delitos tienen mayor participación dentro del conjunto analizado.

Para evitar duplicaciones, se excluye la variable de total de casos del cálculo, dado que esta corresponde a la suma de las categorías individuales. Los resultados se limitan al periodo comprendido entre enero y julio de 2023 y representan denuncias registradas, no necesariamente la totalidad de los hechos ocurridos.

# Sumar los casos registrados por categoría de delito
# Se excluye casos_total porque ya contiene la suma de las categorías

participacion_delitos <- variables_delitos %>%
  select(starts_with("casos_"), -casos_total) %>%
  summarise(
    across(everything(), ~sum(.))
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Delito",
    values_to = "Casos"
  ) %>%
  mutate(
    Delito = str_remove(Delito, "^casos_"),
    Delito = str_replace_all(Delito, "_", " "),
    Delito = str_to_title(Delito),
    Participacion = Casos / sum(Casos) * 100
  ) %>%
  arrange(desc(Participacion))

# Presentación de resultados

knitr::kable(
  participacion_delitos,
  digits = 2,
  col.names = c("Tipo de delito", "Casos registrados", "Participación (%)"),
  caption = "Participación de cada categoría en el total de casos registrados"
)
Participación de cada categoría en el total de casos registrados
Tipo de delito Casos registrados Participación (%)
Hurto Personas 85398 52.44
Hurto Celulares 30906 18.98
Violencia Intrafamiliar 16053 9.86
Lesiones 9894 6.08
Hurto Comercio 6016 3.69
Hurto Bicicletas 4586 2.82
Hurto Residencias 4340 2.67
Hurto Motos 2863 1.76
Hurto Automotor 2180 1.34
Homicidios 599 0.37
ggplot(
  participacion_delitos,
  aes(
    x = reorder(Delito, Participacion),
    y = Participacion
  )
) +
  geom_col(
    fill = magenta,
    width = 0.7
  ) +
  geom_text(
    aes(label = paste0(round(Participacion, 1), "%")),
    hjust = -0.15,
    size = 3.5,
    color = morado
  ) +
  coord_flip() +
  scale_y_continuous(
    labels = scales::label_number(suffix = "%"),
    expand = expansion(mult = c(0, 0.15))
  ) +
  labs(
    title = "Composición de los delitos de alto impacto",
    subtitle = "Participación porcentual de cada categoría en los casos registrados",
    x = NULL,
    y = "Participación (%)",
    caption = "Fuente: Secretaría Distrital de Seguridad, Convivencia y Justicia, enero-julio de 2023."
  ) +
  tema_clase

5.5.5. Identificación de las UPZ con mayor número de casos registrados

Una vez analizada la composición general de los delitos, se identifican las UPZ que concentran el mayor número de casos registrados durante el periodo de estudio.

Para ello se construye un ranking de las diez UPZ con mayor cantidad de denuncias por delitos de alto impacto. La comparación incorpora la población y la tasa total por cada 10.000 habitantes, con el propósito de complementar la lectura del volumen de casos con una medida relativa al tamaño poblacional.

Este ejercicio permite reconocer los territorios que acumulan más registros y explorar si su posición en el ranking coincide con tasas elevadas o si puede estar relacionada con una mayor concentración de habitantes.

La identificación de estas UPZ constituye un primer acercamiento a las diferencias territoriales en los registros de delitos. Sin embargo, el número de denuncias no debe interpretarse por sí solo como una medida de riesgo individual ni como una representación completa de los hechos delictivos ocurridos.

# Identificación de las diez UPZ con mayor número de casos

ranking_casos_delitos <- variables_delitos %>%
  select(
    upz_nombre,
    localidad,
    poblacion,
    casos_total,
    tasa_total
  ) %>%
  arrange(desc(casos_total)) %>%
  slice_head(n = 10)

# Presentación del ranking

knitr::kable(
  ranking_casos_delitos,
  digits = 2,
  col.names = c(
    "UPZ",
    "Localidad",
    "Población",
    "Casos totales",
    "Tasa por 10.000 hab."
  ),
  caption = "Diez UPZ con mayor número de casos de delitos de alto impacto"
)
Diez UPZ con mayor número de casos de delitos de alto impacto
UPZ Localidad Población Casos totales Tasa por 10.000 hab.
La Sabana Los Mártires 38856 5441 1400.30
Chico Lago Chapinero 38608 4985 1291.18
Las Nieves Santa Fe 17203 4033 2344.36
El Rincon Suba 295322 3812 129.08
Los Alcazares Barrios Unidos 44678 3495 782.26
Bosa Central Bosa 237111 3346 141.12
Las Ferias Engativá 100848 3139 311.26
Galerias Teusaquillo 38425 3067 798.18
Teusaquillo Teusaquillo 28881 2976 1030.44
Chapinero Chapinero 26491 2901 1095.09
ggplot(
  ranking_casos_delitos,
  aes(
    x = reorder(upz_nombre, casos_total),
    y = casos_total
  )
) +
  geom_col(
    fill = magenta,
    width = 0.7
  ) +
  geom_text(
    aes(label = scales::label_number(big.mark = ".")(casos_total)),
    hjust = -0.15,
    size = 3.5,
    color = morado
  ) +
  coord_flip() +
  scale_y_continuous(
    labels = scales::label_number(big.mark = "."),
    expand = expansion(mult = c(0, 0.15))
  ) +
  labs(
    title = "UPZ con mayor número de casos registrados",
    subtitle = "Diez territorios con más denuncias entre enero y julio de 2023",
    x = NULL,
    y = "Número de casos",
    caption = "Fuente: Secretaría Distrital de Seguridad, Convivencia y Justicia, 2023."
  ) +
  tema_clase

5.5.6. Identificación de las UPZ con mayores tasas de delitos

A diferencia del ranking anterior, centrado en el volumen de denuncias, en este apartado se identifican las UPZ que presentan las mayores tasas de delitos de alto impacto por cada 10.000 habitantes.

Esta comparación permite incorporar el tamaño poblacional como elemento de referencia y reconocer territorios que, aunque no necesariamente concentran la mayor cantidad de casos, presentan valores elevados en relación con su población.

Para ello se construye un ranking de las diez UPZ con mayores tasas totales. Adicionalmente, se incluyen el número de casos registrados y la población de cada territorio, con el propósito de facilitar la interpretación de los resultados.

Se debe prestar especial atención a las UPZ con poblaciones reducidas, debido a que un número pequeño de denuncias puede generar tasas elevadas. Por esta razón, el ranking se considera una herramienta exploratoria y no una clasificación definitiva del riesgo de inseguridad de los territorios.

# Identificación de las diez UPZ con mayores tasas de delitos

ranking_tasas_delitos <- variables_delitos %>%
  select(
    upz_nombre,
    localidad,
    poblacion,
    casos_total,
    tasa_total
  ) %>%
  arrange(desc(tasa_total)) %>%
  slice_head(n = 10)

# Presentación del ranking

knitr::kable(
  ranking_tasas_delitos,
  digits = 2,
  col.names = c(
    "UPZ",
    "Localidad",
    "Población",
    "Casos totales",
    "Tasa por 10.000 hab."
  ),
  caption = "Diez UPZ con mayores tasas de delitos de alto impacto"
)
Diez UPZ con mayores tasas de delitos de alto impacto
UPZ Localidad Población Casos totales Tasa por 10.000 hab.
El Mochuelo Ciudad Bolívar 30 34 11333.33
Aeropuerto El Dorado Fontibón 883 545 6172.14
Parque Simon Bolivar - Can Teusaquillo 3323 958 2882.94
Zona Industrial Puente Aranda 6666 1573 2359.74
Las Nieves Santa Fe 17203 4033 2344.36
Parque Salitre Barrios Unidos 1442 233 1615.81
Sagrado Corazon Santa Fe 11247 1707 1517.74
La Sabana Los Mártires 38856 5441 1400.30
Chico Lago Chapinero 38608 4985 1291.18
Puente Aranda Puente Aranda 12482 1561 1250.60
ggplot(
  ranking_tasas_delitos,
  aes(
    x = reorder(upz_nombre, tasa_total),
    y = tasa_total
  )
) +
  geom_col(
    fill = turquesa,
    width = 0.7
  ) +
  geom_text(
    aes(label = round(tasa_total, 1)),
    hjust = -0.15,
    size = 3.5,
    color = morado
  ) +
  coord_flip() +
  scale_y_continuous(
    expand = expansion(mult = c(0, 0.15))
  ) +
  labs(
    title = "UPZ con mayores tasas de delitos",
    subtitle = "Casos registrados por cada 10.000 habitantes",
    x = NULL,
    y = "Tasa por cada 10.000 habitantes",
    caption = "Fuente: Secretaría Distrital de Seguridad, Convivencia y Justicia y proyecciones de población DANE, 2023."
  ) +
  tema_clase

5.5.7. Comparación entre el volumen de casos y las tasas de delitos

Con el propósito de profundizar en las diferencias territoriales, se realiza una comparación entre el número total de casos registrados y la tasa total de delitos por cada 10.000 habitantes.

Este ejercicio permite explorar si las UPZ que concentran mayores cantidades de denuncias también presentan tasas elevadas al considerar su tamaño poblacional. Para ello se utiliza un gráfico de dispersión en el que cada punto representa una UPZ y su tamaño permite visualizar de manera complementaria la población de cada territorio.

Adicionalmente, se incorporan líneas de referencia correspondientes a las medianas de casos y tasas, con el propósito de dividir el gráfico en cuatro cuadrantes. Esta clasificación facilita reconocer diferentes comportamientos territoriales: UPZ con valores altos en ambas medidas, territorios con muchos casos pero tasas relativamente bajas, zonas con pocos casos y tasas elevadas, y territorios con valores bajos en ambos indicadores.

Esta comparación permite comprender que el volumen de denuncias y la tasa por habitante representan dimensiones diferentes del fenómeno. Sin embargo, los resultados deben interpretarse considerando que las tasas pueden presentar valores extremos en UPZ con poblaciones reducidas y que los registros corresponden únicamente a denuncias del periodo enero-julio de 2023.

# Cálculo de las medianas como puntos de referencia

mediana_casos <- median(variables_delitos$casos_total)

mediana_tasa <- median(variables_delitos$tasa_total)

# Clasificación de las UPZ según casos y tasas

comparacion_delitos <- variables_delitos %>%
  select(
    upz_nombre,
    localidad,
    poblacion,
    casos_total,
    tasa_total
  ) %>%
  mutate(
    Clasificacion = case_when(
      casos_total >= mediana_casos &
        tasa_total >= mediana_tasa ~ "Muchos casos y tasa alta",

      casos_total >= mediana_casos &
        tasa_total < mediana_tasa ~ "Muchos casos y tasa baja",

      casos_total < mediana_casos &
        tasa_total >= mediana_tasa ~ "Pocos casos y tasa alta",

      TRUE ~ "Pocos casos y tasa baja"
    )
  )

# Resumen de la cantidad de UPZ en cada cuadrante

resumen_cuadrantes <- comparacion_delitos %>%
  count(Clasificacion, name = "Cantidad_UPZ") %>%
  mutate(
    Participacion = Cantidad_UPZ / sum(Cantidad_UPZ) * 100
  ) %>%
  arrange(desc(Cantidad_UPZ))

knitr::kable(
  resumen_cuadrantes,
  digits = 2,
  col.names = c(
    "Clasificación",
    "Cantidad de UPZ",
    "Participación (%)"
  ),
  caption = "Distribución de las UPZ según volumen de casos y tasa de delitos"
)
Distribución de las UPZ según volumen de casos y tasa de delitos
Clasificación Cantidad de UPZ Participación (%)
Muchos casos y tasa alta 34 30.36
Pocos casos y tasa baja 34 30.36
Muchos casos y tasa baja 22 19.64
Pocos casos y tasa alta 22 19.64
# Identificación de las diez UPZ con mayores tasas para etiquetarlas

upz_etiquetadas <- comparacion_delitos %>%
  slice_max(
    order_by = tasa_total,
    n = 10,
    with_ties = FALSE
  )

# Gráfico de dispersión

ggplot(
  comparacion_delitos,
  aes(
    x = casos_total,
    y = tasa_total,
    color = Clasificacion,
    size = poblacion
  )
) +
  geom_point(
    alpha = 0.75
  ) +
  geom_vline(
    xintercept = mediana_casos,
    linetype = "dashed",
    color = "grey40"
  ) +
  geom_hline(
    yintercept = mediana_tasa,
    linetype = "dashed",
    color = "grey40"
  ) +
  geom_text(
    data = upz_etiquetadas,
    aes(label = upz_nombre),
    size = 2.8,
    show.legend = FALSE,
    vjust = -0.8
  ) +
  scale_color_manual(
    values = c(
      "Muchos casos y tasa alta" = magenta,
      "Muchos casos y tasa baja" = turquesa,
      "Pocos casos y tasa alta" = morado,
      "Pocos casos y tasa baja" = gris
    )
  ) +
  scale_size_continuous(
    range = c(2, 8),
    name = "Población"
  ) +
  scale_x_continuous(
    labels = scales::label_number(big.mark = ".")
  ) +
  labs(
    title = "Relación entre casos registrados y tasas de delitos",
    subtitle = "Comparación territorial de las UPZ mediante cuatro cuadrantes",
    x = "Número total de casos registrados",
    y = "Tasa por cada 10.000 habitantes",
    color = "Clasificación",
    caption = "Las líneas discontinuas representan las medianas. Fuente: Secretaría Distrital de Seguridad y proyecciones DANE, 2023."
  ) +
  tema_clase +
  theme(
    legend.position = "bottom",
    legend.box = "vertical"
  )

5.6. Análisis de relaciones entre variables

Después de explorar individualmente las características demográficas, las condiciones de vivienda e infraestructura, las variables socioeconómicas, la percepción de inseguridad y los registros de delitos, se desarrolla un análisis integrado para explorar las posibles relaciones entre estas dimensiones.

El propósito es identificar patrones de asociación entre las características territoriales y los indicadores de seguridad, con el fin de ampliar la comprensión de las diferencias existentes entre las UPZ de Bogotá.

Para este análisis se seleccionan variables de diferentes bloques temáticos, incluyendo aspectos demográficos, infraestructura urbana, condiciones socioeconómicas, percepción de inseguridad y registros administrativos de delitos.

Se utiliza el coeficiente de correlación de Spearman para explorar la dirección y la intensidad de las asociaciones entre las variables. Los resultados se presentan mediante una matriz de correlaciones y un mapa de calor que facilitan la identificación de posibles patrones.

Es importante señalar que las correlaciones permiten identificar asociaciones estadísticas, pero no demuestran relaciones de causalidad. Adicionalmente, se deben considerar las diferencias en los años de referencia de las fuentes y las limitaciones relacionadas con las estimaciones agrupadas de la Encuesta Multipropósito.

5.6.1. Selección de variables para el análisis integrado

Para el análisis de relaciones se seleccionaron diez variables pertenecientes a cinco dimensiones del estudio: demografía, infraestructura, condiciones socioeconómicas, percepción de inseguridad y delitos de alto impacto.

La selección busca explorar si las características poblacionales, la disponibilidad de alumbrado público, las condiciones socioeconómicas y la percepción del entorno presentan asociaciones con los indicadores de delitos registrados en las UPZ.

Las variables seleccionadas son:

  • Demografía: población y densidad poblacional.
  • Infraestructura: luminarias por km².
  • Condiciones socioeconómicas: porcentaje de pobreza y salario promedio.
  • Percepción y entorno: percepción de inseguridad y cercanía a lotes oscuros.
  • Delitos: número total de casos y tasa total por cada 10.000 habitantes.
  • Accesibilidad: tiempo promedio caminando hasta un CAI o estación de policía.

Esta selección permite integrar diferentes dimensiones del territorio y explorar sus posibles relaciones. Los resultados se interpretarán de manera exploratoria, considerando las limitaciones propias de las fuentes utilizadas.

# Selección de variables para el análisis integrado

variables_integradas <- upz %>%
  select(
    upz_nombre,
    localidad,
    em_agrupada,
    poblacion,
    densidad_hab_km2,
    luminarias_km2,
    pct_pobreza,
    salario_promedio,
    pct_percibe_inseguridad,
    pct_cerca_lotes_oscuros,
    min_cai_policia,
    casos_total,
    tasa_total
  )

# Revisión de las variables seleccionadas

glimpse(variables_integradas)
## Rows: 112
## Columns: 13
## $ upz_nombre              <chr> "Paseo De Los Libertadores", "La Academia", "G…
## $ localidad               <chr> "Usaquén", "Suba", "Suba", "Usaquén", "Usaquén…
## $ em_agrupada             <lgl> TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, F…
## $ poblacion               <dbl> 2690, 5260, 2692, 131999, 37014, 72939, 63068,…
## $ densidad_hab_km2        <dbl> 424.81, 779.85, 591.30, 36967.66, 10682.12, 26…
## $ luminarias_km2          <dbl> 82.75, 79.17, 40.42, 995.61, 383.26, 933.16, 9…
## $ pct_pobreza             <dbl> 1.37, 0.86, 0.86, 3.12, 1.37, 5.19, 0.84, 0.37…
## $ salario_promedio        <dbl> 3937004, 4280663, 4280663, 1933709, 3937004, 1…
## $ pct_percibe_inseguridad <dbl> 36.18, 40.88, 40.88, 65.43, 36.18, 49.84, 60.4…
## $ pct_cerca_lotes_oscuros <dbl> 24.15, 16.71, 16.71, 24.15, 24.15, 19.15, 18.8…
## $ min_cai_policia         <dbl> 21.66, 24.50, 24.50, 18.39, 21.66, 25.32, 18.5…
## $ casos_total             <dbl> 74, 123, 45, 944, 621, 793, 943, 1991, 1298, 4…
## $ tasa_total              <dbl> 275.09, 233.84, 167.16, 71.52, 167.77, 108.72,…
# Visualización de las primeras observaciones

head(variables_integradas)
upz_nombre localidad em_agrupada poblacion densidad_hab_km2 luminarias_km2 pct_pobreza salario_promedio pct_percibe_inseguridad pct_cerca_lotes_oscuros min_cai_policia casos_total tasa_total
Paseo De Los Libertadores Usaquén TRUE 2690 424.81 82.75 1.37 3937004 36.18 24.15 21.66 74 275.09
La Academia Suba TRUE 5260 779.85 79.17 0.86 4280663 40.88 16.71 24.50 123 233.84
Guaymaral Suba TRUE 2692 591.30 40.42 0.86 4280663 40.88 16.71 24.50 45 167.16
Verbenal Usaquén FALSE 131999 36967.66 995.61 3.12 1933709 65.43 24.15 18.39 944 71.52
La Uribe Usaquén TRUE 37014 10682.12 383.26 1.37 3937004 36.18 24.15 21.66 621 167.77
San Cristobal Norte Usaquén FALSE 72939 26401.70 933.16 5.19 1368739 49.84 19.15 25.32 793 108.72

5.6.2. Matriz de correlaciones entre las variables territoriales

Una vez seleccionadas las variables de los diferentes bloques temáticos, se construye una matriz de correlaciones para explorar las asociaciones existentes entre las características demográficas, la infraestructura, las condiciones socioeconómicas, la percepción de inseguridad, la accesibilidad y los delitos registrados.

Se utiliza el coeficiente de correlación de Spearman, que permite identificar asociaciones monotónicas entre las variables. Sus valores oscilan entre -1 y 1, donde los valores positivos representan asociaciones directas y los negativos asociaciones inversas.

La matriz se representa mediante un mapa de calor, en el que los colores permiten reconocer visualmente la dirección y la intensidad de las correlaciones.

Este ejercicio busca identificar relaciones que puedan orientar el desarrollo de las preguntas de investigación y los análisis posteriores. Sin embargo, las asociaciones observadas no deben interpretarse como relaciones de causalidad.

# Selección exclusiva de variables numéricas

datos_correlacion_integrada <- variables_integradas %>%
  select(
    poblacion,
    densidad_hab_km2,
    luminarias_km2,
    pct_pobreza,
    salario_promedio,
    pct_percibe_inseguridad,
    pct_cerca_lotes_oscuros,
    min_cai_policia,
    casos_total,
    tasa_total
  )

# Cálculo de la matriz de correlaciones de Spearman

matriz_correlacion_integrada <- cor(
  datos_correlacion_integrada,
  method = "spearman",
  use = "complete.obs"
)

# Transformación de la matriz a formato largo

correlaciones_integradas_largas <- as.data.frame(
  as.table(matriz_correlacion_integrada)
) %>%
  rename(
    Variable_1 = Var1,
    Variable_2 = Var2,
    Correlacion = Freq
  )

# Construcción del mapa de calor

ggplot(
  correlaciones_integradas_largas,
  aes(
    x = Variable_1,
    y = Variable_2,
    fill = Correlacion
  )
) +
  geom_tile(
    color = "white",
    linewidth = 1
  ) +
  geom_text(
    aes(label = round(Correlacion, 2)),
    color = "black",
    size = 3
  ) +
  scale_fill_gradient2(
    low = morado,
    mid = "white",
    high = magenta,
    midpoint = 0,
    limits = c(-1, 1),
    name = "Correlación"
  ) +
  labs(
    title = "Relaciones entre las características territoriales",
    subtitle = "Matriz de correlaciones de Spearman entre variables seleccionadas",
    x = NULL,
    y = NULL,
    caption = "Fuente: Elaboración propia con información DANE, Secretaría Distrital de Seguridad y Datos Abiertos Bogotá."
  ) +
  coord_fixed() +
  tema_clase +
  theme(
    axis.text.x = element_text(
      angle = 45,
      hjust = 1,
      color = morado,
      size = 8
    ),
    axis.text.y = element_text(
      color = morado,
      size = 8
    ),
    panel.grid = element_blank(),
    legend.position = "right"
  )

5.6.3. Relación entre población, densidad poblacional y delitos

Las características demográficas de los territorios pueden aportar elementos importantes para comprender las diferencias en los registros de delitos. Por esta razón, se exploran las relaciones entre el tamaño de la población, la densidad poblacional y los indicadores de delitos de alto impacto.

En primer lugar, se analiza la relación entre la población y el número total de casos registrados, con el propósito de identificar si las UPZ con mayor cantidad de habitantes también concentran un mayor volumen de denuncias.

En segundo lugar, se examina la relación entre la densidad poblacional y la tasa total de delitos por cada 10.000 habitantes. Este ejercicio permite explorar si las características de concentración de la población presentan alguna asociación con las diferencias territoriales en las tasas registradas.

Para complementar la visualización, se calculan los coeficientes de correlación de Spearman. Los resultados permiten identificar asociaciones entre las variables, sin establecer relaciones de causalidad.

ggplot(
  variables_integradas,
  aes(
    x = poblacion,
    y = casos_total
  )
) +
  geom_point(
    color = turquesa,
    alpha = 0.7,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = FALSE,
    color = magenta,
    linewidth = 0.9
  ) +
  scale_x_continuous(
    labels = scales::label_number(big.mark = ".")
  ) +
  scale_y_continuous(
    labels = scales::label_number(big.mark = ".")
  ) +
  labs(
    title = "Relación entre población y casos de delitos",
    subtitle = "Número de habitantes y denuncias registradas por UPZ",
    x = "Población",
    y = "Casos totales registrados",
    caption = "Fuente: Proyecciones DANE y Secretaría Distrital de Seguridad, 2023."
  ) +
  tema_clase

ggplot(
  variables_integradas,
  aes(
    x = densidad_hab_km2,
    y = tasa_total
  )
) +
  geom_point(
    color = magenta,
    alpha = 0.7,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = FALSE,
    color = morado,
    linewidth = 0.9
  ) +
  scale_x_continuous(
    labels = scales::label_number(big.mark = ".")
  ) +
  labs(
    title = "Relación entre densidad poblacional y tasa de delitos",
    subtitle = "Concentración de habitantes y casos por cada 10.000 habitantes",
    x = "Densidad poblacional (habitantes por km²)",
    y = "Tasa de delitos por cada 10.000 habitantes",
    caption = "Fuente: Proyecciones DANE y Secretaría Distrital de Seguridad, 2023."
  ) +
  tema_clase

Para complementar los gráficos de dispersión, se calculan los coeficientes de correlación de Spearman entre la población y los casos totales, así como entre la densidad poblacional y la tasa de delitos.

Esta comparación permite evaluar la dirección y la intensidad de las asociaciones observadas visualmente, facilitando la identificación de posibles diferencias entre el volumen de denuncias y las tasas relativas a la población.

# Cálculo de las correlaciones seleccionadas

correlaciones_demografia <- variables_integradas %>%
  select(
    poblacion,
    casos_total,
    densidad_hab_km2,
    tasa_total
  ) %>%
  cor(
    method = "spearman",
    use = "complete.obs"
  )

# Transformación para presentar únicamente las dos relaciones de interés

resultado_correlaciones_demografia <- tibble(
  Relacion = c(
    "Población y casos totales",
    "Densidad poblacional y tasa de delitos"
  ),
  Correlacion = c(
    correlaciones_demografia["poblacion", "casos_total"],
    correlaciones_demografia["densidad_hab_km2", "tasa_total"]
  )
)

knitr::kable(
  resultado_correlaciones_demografia,
  digits = 3,
  caption = "Correlaciones de Spearman entre variables demográficas e indicadores de delitos"
)
Correlaciones de Spearman entre variables demográficas e indicadores de delitos
Relacion Correlacion
Población y casos totales 0.555
Densidad poblacional y tasa de delitos -0.538

5.6.4. Relación entre infraestructura urbana y delitos

En este apartado se explora la relación entre las condiciones del alumbrado público y la tasa de delitos de alto impacto en las UPZ de Bogotá. Para ello, se consideran tres indicadores: la cantidad de luminarias por kilómetro cuadrado, la cantidad de luminarias por cada 1.000 habitantes y el porcentaje de luminarias LED.

El propósito es identificar si existe alguna asociación estadística entre la disponibilidad y las características del alumbrado público y los niveles de criminalidad registrados en cada UPZ.

Se utiliza la correlación de Spearman, debido a que permite evaluar relaciones monotónicas sin exigir que las variables presenten una distribución normal. Adicionalmente, se emplean diagramas de dispersión para observar el comportamiento de las variables y posibles patrones o valores extremos.

Es importante considerar que los indicadores de alumbrado corresponden a 2021, mientras que los registros de delitos corresponden al periodo enero-julio de 2023. Por tanto, las relaciones encontradas deben interpretarse como asociaciones exploratorias y no como evidencia de una relación causal.

Asimismo, una mayor cantidad de luminarias no necesariamente representa mejores condiciones de iluminación en todos los espacios públicos, ya que estos indicadores no incorporan aspectos como su ubicación, funcionamiento, intensidad o distribución efectiva.

# Selección de variables de infraestructura y delitos

infraestructura_delitos <- upz %>%
  select(
    upz_nombre,
    localidad,
    luminarias_km2,
    luminarias_1000hab,
    pct_luminarias_led,
    tasa_total
  )

# Visualización de los primeros registros

kable(
  head(infraestructura_delitos, 10),
  digits = 2,
  caption = "Indicadores de infraestructura y tasa de delitos por UPZ"
)
Indicadores de infraestructura y tasa de delitos por UPZ
upz_nombre localidad luminarias_km2 luminarias_1000hab pct_luminarias_led tasa_total
Paseo De Los Libertadores Usaquén 82.75 194.80 28.44 275.09
La Academia Suba 79.17 101.52 0.37 233.84
Guaymaral Suba 40.42 68.35 0.00 167.16
Verbenal Usaquén 995.61 26.93 65.77 71.52
La Uribe Usaquén 383.26 35.88 49.25 167.77
San Cristobal Norte Usaquén 933.16 35.34 49.34 108.72
Toberin Usaquén 937.24 43.35 50.62 149.52
Los Cedros Usaquén 768.37 38.41 53.32 147.51
Usaquen Usaquén 648.58 74.30 50.42 300.74
Country Club Usaquén 487.38 53.47 57.98 169.17

5.6.4.1. Relación entre densidad de luminarias y tasa de delitos

# Relación entre luminarias por km2 y tasa de delitos

ggplot(
  infraestructura_delitos,
  aes(x = luminarias_km2, y = tasa_total)
) +
  geom_point(
    color = "#351A4F",
    alpha = 0.75,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = TRUE,
    color = "#D9006C",
    fill = "#D9006C",
    alpha = 0.15
  ) +
  labs(
    title = "Densidad de luminarias y tasa de delitos",
    subtitle = "Comparación entre UPZ de Bogotá",
    x = "Luminarias por km²",
    y = "Delitos por cada 10.000 habitantes",
    caption = "Fuentes: indicadores de alumbrado 2021 y registros de delitos enero-julio 2023"
  ) +
  tema_clase

5.6.4.2. Relación entre luminarias por habitante y tasa de delitos

# Relación entre luminarias por cada 1.000 habitantes y tasa de delitos

ggplot(
  infraestructura_delitos,
  aes(x = luminarias_1000hab, y = tasa_total)
) +
  geom_point(
    color = "#168C86",
    alpha = 0.75,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = TRUE,
    color = "#D9006C",
    fill = "#D9006C",
    alpha = 0.15
  ) +
  labs(
    title = "Disponibilidad de luminarias por habitante y tasa de delitos",
    subtitle = "Luminarias por cada 1.000 habitantes",
    x = "Luminarias por cada 1.000 habitantes",
    y = "Delitos por cada 10.000 habitantes",
    caption = "Fuentes: indicadores de alumbrado 2021 y registros de delitos enero-julio 2023"
  ) +
  tema_clase

5.6.4.3. Relación entre porcentaje de luminarias LED y tasa de delitos

# Relación entre porcentaje de luminarias LED y tasa de delitos

ggplot(
  infraestructura_delitos,
  aes(x = pct_luminarias_led, y = tasa_total)
) +
  geom_point(
    color = "#351A4F",
    alpha = 0.75,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = TRUE,
    color = "#D9006C",
    fill = "#D9006C",
    alpha = 0.15
  ) +
  labs(
    title = "Participación de luminarias LED y tasa de delitos",
    subtitle = "Comparación de la composición tecnológica del alumbrado",
    x = "Luminarias LED (%)",
    y = "Delitos por cada 10.000 habitantes",
    caption = "Fuentes: indicadores de alumbrado 2021 y registros de delitos enero-julio 2023"
  ) +
  tema_clase

5.6.4.4. Correlaciones entre infraestructura y delitos

# Cálculo de correlaciones de Spearman

correlaciones_infraestructura <- infraestructura_delitos %>%
  summarise(
    Cor_luminarias_km2 = cor(
      luminarias_km2,
      tasa_total,
      method = "spearman",
      use = "complete.obs"
    ),
    Cor_luminarias_1000hab = cor(
      luminarias_1000hab,
      tasa_total,
      method = "spearman",
      use = "complete.obs"
    ),
    Cor_pct_led = cor(
      pct_luminarias_led,
      tasa_total,
      method = "spearman",
      use = "complete.obs"
    )
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Relacion",
    values_to = "Correlacion_Spearman"
  ) %>%
  mutate(
    Interpretacion = case_when(
      abs(Correlacion_Spearman) < 0.20 ~ "Muy débil",
      abs(Correlacion_Spearman) < 0.40 ~ "Débil",
      abs(Correlacion_Spearman) < 0.60 ~ "Moderada",
      abs(Correlacion_Spearman) < 0.80 ~ "Fuerte",
      TRUE ~ "Muy fuerte"
    )
  )

kable(
  correlaciones_infraestructura,
  digits = 3,
  caption = "Correlaciones de Spearman entre indicadores de alumbrado y tasa de delitos"
)
Correlaciones de Spearman entre indicadores de alumbrado y tasa de delitos
Relacion Correlacion_Spearman Interpretacion
Cor_luminarias_km2 0.119 Muy débil
Cor_luminarias_1000hab 0.775 Fuerte
Cor_pct_led -0.061 Muy débil

5.6.5. Relación entre condiciones socioeconómicas, percepción de inseguridad y delitos

En este apartado se integran variables socioeconómicas y de percepción ciudadana con los registros de delitos de alto impacto, con el propósito de explorar posibles asociaciones entre las condiciones de vida de las UPZ y los indicadores de seguridad.

Se consideran tres relaciones principales: el porcentaje de pobreza frente a la tasa total de delitos, el salario promedio frente a la tasa total de delitos y el porcentaje de percepción de inseguridad frente a la tasa total de delitos.

Estas comparaciones permiten examinar si las diferencias socioeconómicas entre territorios presentan algún patrón asociado con los niveles de criminalidad registrados y si la percepción ciudadana guarda correspondencia con las denuncias de delitos.

Para evaluar estas relaciones se utilizan diagramas de dispersión y el coeficiente de correlación de Spearman. Este último permite identificar asociaciones monotónicas entre las variables sin exigir una relación lineal.

Es importante diferenciar la percepción de inseguridad de los delitos denunciados. La primera corresponde a la proporción de personas que manifiestan percibir problemas de inseguridad en el entorno de su vivienda, mientras que la segunda representa registros administrativos de denuncias. Por tanto, ambas dimensiones describen aspectos diferentes del fenómeno de la seguridad.

Adicionalmente, los indicadores socioeconómicos y de percepción corresponden a la Encuesta Multipropósito de 2021, mientras que los delitos corresponden al periodo enero-julio de 2023. También se debe considerar que algunas estimaciones de la encuesta fueron agrupadas entre UPZ vecinas, lo que limita la independencia de las observaciones territoriales.

5.6.5.1. Selección de variables

Primero, organizamos las variables que utilizaremos en este análisis.

# Selección de variables socioeconómicas y de seguridad

socioeconomia_seguridad <- upz %>%
  select(
    upz_nombre,
    localidad,
    em_agrupada,
    pct_pobreza,
    salario_promedio,
    pct_percibe_inseguridad,
    tasa_total
  )

# Visualización de los primeros registros

knitr::kable(
  head(socioeconomia_seguridad, 10),
  digits = 2,
  caption = "Variables socioeconómicas y de seguridad por UPZ"
)
Variables socioeconómicas y de seguridad por UPZ
upz_nombre localidad em_agrupada pct_pobreza salario_promedio pct_percibe_inseguridad tasa_total
Paseo De Los Libertadores Usaquén TRUE 1.37 3937004 36.18 275.09
La Academia Suba TRUE 0.86 4280663 40.88 233.84
Guaymaral Suba TRUE 0.86 4280663 40.88 167.16
Verbenal Usaquén FALSE 3.12 1933709 65.43 71.52
La Uribe Usaquén TRUE 1.37 3937004 36.18 167.77
San Cristobal Norte Usaquén FALSE 5.19 1368739 49.84 108.72
Toberin Usaquén FALSE 0.84 3434906 60.44 149.52
Los Cedros Usaquén FALSE 0.37 5226504 41.49 147.51
Usaquen Usaquén FALSE 0.67 6893541 24.45 300.74
Country Club Usaquén TRUE 0.07 7624587 40.67 169.17

5.6.5.2. Relación entre pobreza y tasa de delitos

ggplot(
  socioeconomia_seguridad,
  aes(
    x = pct_pobreza,
    y = tasa_total
  )
) +
  geom_point(
    aes(color = em_agrupada),
    alpha = 0.8,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = TRUE,
    color = magenta,
    fill = magenta,
    alpha = 0.15
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = morado,
      "TRUE" = turquesa
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    )
  ) +
  labs(
    title = "Relación entre pobreza y tasa de delitos",
    subtitle = "Comparación de condiciones socioeconómicas entre UPZ",
    x = "Población en condición de pobreza (%)",
    y = "Delitos por cada 10.000 habitantes",
    color = "Tipo de estimación",
    caption = "Fuentes: Encuesta Multipropósito 2021 y registros de delitos enero-julio 2023"
  ) +
  tema_clase

5.6.5.3. Relación entre salario promedio y tasa de delitos

ggplot(
  socioeconomia_seguridad,
  aes(
    x = salario_promedio,
    y = tasa_total
  )
) +
  geom_point(
    aes(color = em_agrupada),
    alpha = 0.8,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = TRUE,
    color = magenta,
    fill = magenta,
    alpha = 0.15
  ) +
  scale_x_continuous(
    labels = scales::label_number(
      prefix = "$",
      big.mark = ".",
      decimal.mark = ","
    )
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = morado,
      "TRUE" = turquesa
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    )
  ) +
  labs(
    title = "Relación entre salario promedio y tasa de delitos",
    subtitle = "Comparación de ingresos promedio entre UPZ",
    x = "Salario promedio mensual",
    y = "Delitos por cada 10.000 habitantes",
    color = "Tipo de estimación",
    caption = "Fuentes: Encuesta Multipropósito 2021 y registros de delitos enero-julio 2023"
  ) +
  tema_clase

5.6.5.4. Relación entre percepción de inseguridad y tasa de delitos

ggplot(
  socioeconomia_seguridad,
  aes(
    x = pct_percibe_inseguridad,
    y = tasa_total
  )
) +
  geom_point(
    aes(color = em_agrupada),
    alpha = 0.8,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = TRUE,
    color = magenta,
    fill = magenta,
    alpha = 0.15
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = morado,
      "TRUE" = turquesa
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    )
  ) +
  labs(
    title = "Percepción de inseguridad y tasa de delitos",
    subtitle = "Comparación entre percepción ciudadana y registros administrativos",
    x = "Personas que perciben inseguridad en su entorno (%)",
    y = "Delitos por cada 10.000 habitantes",
    color = "Tipo de estimación",
    caption = "Fuentes: Encuesta Multipropósito 2021 y registros de delitos enero-julio 2023"
  ) +
  tema_clase

5.6.5.5. Matriz de correlaciones socioeconómicas y de seguridad

# Selección integrada de variables

variables_correlacion <- upz %>%
  select(
    poblacion,
    densidad_hab_km2,
    luminarias_km2,
    pct_pobreza,
    salario_promedio,
    pct_percibe_inseguridad,
    pct_cerca_lotes_oscuros,
    min_cai_policia,
    casos_total,
    tasa_total
  )

# Cálculo de la matriz de correlaciones de Spearman

matriz_correlaciones <- cor(
  variables_correlacion,
  method = "spearman",
  use = "complete.obs"
)

# Transformación de la matriz para visualizarla

matriz_larga <- as.data.frame(
  as.table(matriz_correlaciones)
) %>%
  rename(
    Variable_1 = Var1,
    Variable_2 = Var2,
    Correlacion = Freq
  )

# Mapa de calor de correlaciones

ggplot(
  matriz_larga,
  aes(
    x = Variable_1,
    y = Variable_2,
    fill = Correlacion
  )
) +
  geom_tile(color = "white", linewidth = 0.5) +
  geom_text(
    aes(label = round(Correlacion, 2)),
    color = "black",
    size = 3
  ) +
  scale_fill_gradient2(
    low = morado,
    mid = "white",
    high = magenta,
    midpoint = 0,
    limits = c(-1, 1)
  ) +
  coord_equal() +
  labs(
    title = "Matriz integrada de correlaciones entre variables",
    subtitle = "Coeficientes de Spearman para las dimensiones territoriales y de seguridad",
    x = NULL,
    y = NULL,
    fill = "Correlación",
    caption = "Fuente: elaboración propia a partir de los indicadores de las UPZ."
  ) +
  tema_clase +
  theme(
    axis.text.x = element_text(
      angle = 45,
      hjust = 1,
      size = 9
    ),
    axis.text.y = element_text(size = 9),
    panel.grid = element_blank()
  )

5.6.6. Síntesis de las relaciones entre variables

Después de explorar las relaciones entre las características demográficas, la infraestructura urbana, las condiciones socioeconómicas, la percepción de inseguridad y los registros de delitos, se realiza una síntesis de las correlaciones obtenidas.

El propósito de esta etapa es identificar las asociaciones estadísticas de mayor magnitud entre las variables seleccionadas y facilitar su interpretación desde una perspectiva integral del territorio.

Para ello, se organizan los coeficientes de correlación de Spearman en una tabla comparativa, ordenada según el valor absoluto de cada correlación. De esta manera, es posible reconocer las relaciones positivas y negativas de mayor intensidad, sin limitar el análisis exclusivamente a las variables relacionadas con los delitos.

Esta síntesis permite identificar patrones que pueden orientar la interpretación de los resultados y la selección de indicadores relevantes para la siguiente etapa de visualización geográfica.

Es importante señalar que la magnitud de una correlación no implica causalidad. Además, las relaciones deben interpretarse considerando las diferencias temporales entre las fuentes de información y las estimaciones socioeconómicas agrupadas para algunas UPZ.

5.6.6.1. Identificación de las correlaciones más relevantes

# Convertir la matriz de correlaciones en una tabla

ranking_correlaciones <- as.data.frame(
  as.table(matriz_correlaciones)
) %>%
  rename(
    Variable_1 = Var1,
    Variable_2 = Var2,
    Correlacion = Freq
  ) %>%
  mutate(
    Variable_1 = as.character(Variable_1),
    Variable_2 = as.character(Variable_2)
  ) %>%
  # Eliminar diagonal y relaciones duplicadas
  filter(Variable_1 < Variable_2) %>%
  # Clasificar la dirección de la relación
  mutate(
    Direccion = if_else(
      Correlacion >= 0,
      "Positiva",
      "Negativa"
    ),
    Magnitud = case_when(
      abs(Correlacion) < 0.20 ~ "Muy débil",
      abs(Correlacion) < 0.40 ~ "Débil",
      abs(Correlacion) < 0.60 ~ "Moderada",
      abs(Correlacion) < 0.80 ~ "Fuerte",
      TRUE ~ "Muy fuerte"
    ),
    Magnitud_absoluta = abs(Correlacion)
  ) %>%
  arrange(desc(Magnitud_absoluta))

# Presentar las 10 asociaciones de mayor magnitud

top_correlaciones <- ranking_correlaciones %>%
  slice_head(n = 10) %>%
  select(
    Variable_1,
    Variable_2,
    Correlacion,
    Direccion,
    Magnitud
  )

knitr::kable(
  top_correlaciones,
  digits = 3,
  col.names = c(
    "Variable 1",
    "Variable 2",
    "Correlación",
    "Dirección",
    "Magnitud"
  ),
  caption = "Las 10 correlaciones de mayor magnitud entre las variables analizadas"
)
Las 10 correlaciones de mayor magnitud entre las variables analizadas
Variable 1 Variable 2 Correlación Dirección Magnitud
pct_pobreza salario_promedio -0.928 Negativa Muy fuerte
densidad_hab_km2 poblacion 0.833 Positiva Muy fuerte
pct_percibe_inseguridad salario_promedio -0.790 Negativa Fuerte
pct_percibe_inseguridad pct_pobreza 0.740 Positiva Fuerte
salario_promedio tasa_total 0.584 Positiva Moderada
pct_cerca_lotes_oscuros pct_pobreza 0.578 Positiva Moderada
casos_total luminarias_km2 0.577 Positiva Moderada
pct_cerca_lotes_oscuros salario_promedio -0.572 Negativa Moderada
poblacion tasa_total -0.564 Negativa Moderada
densidad_hab_km2 luminarias_km2 0.563 Positiva Moderada

5.6.6.2. Visualización de las correlaciones más relevantes

ggplot(
  top_correlaciones,
  aes(
    x = reorder(
      paste(Variable_1, "vs.", Variable_2),
      Correlacion
    ),
    y = Correlacion,
    fill = Direccion
  )
) +
  geom_col(width = 0.7) +
  geom_hline(
    yintercept = 0,
    color = "grey40",
    linewidth = 0.5
  ) +
  coord_flip() +
  scale_fill_manual(
    values = c(
      "Positiva" = magenta,
      "Negativa" = morado
    )
  ) +
  labs(
    title = "Principales asociaciones entre variables",
    subtitle = "Diez correlaciones de mayor magnitud absoluta",
    x = NULL,
    y = "Coeficiente de Spearman",
    fill = "Dirección",
    caption = "Fuente: elaboración propia a partir de los indicadores de las UPZ."
  ) +
  tema_clase

5.6.6.3. Correlaciones específicas con la tasa de delitos

# Identificar las variables relacionadas con la tasa total de delitos

correlaciones_tasa <- ranking_correlaciones %>%
  filter(
    Variable_1 == "tasa_total" |
    Variable_2 == "tasa_total"
  ) %>%
  mutate(
    Variable_relacionada = if_else(
      Variable_1 == "tasa_total",
      Variable_2,
      Variable_1
    )
  ) %>%
  arrange(desc(Magnitud_absoluta)) %>%
  select(
    Variable_relacionada,
    Correlacion,
    Direccion,
    Magnitud
  )

knitr::kable(
  correlaciones_tasa,
  digits = 3,
  col.names = c(
    "Variable relacionada",
    "Correlación",
    "Dirección",
    "Magnitud"
  ),
  caption = "Relaciones de las variables seleccionadas con la tasa total de delitos"
)
Relaciones de las variables seleccionadas con la tasa total de delitos
Variable relacionada Correlación Dirección Magnitud
salario_promedio 0.584 Positiva Moderada
poblacion -0.564 Negativa Moderada
densidad_hab_km2 -0.538 Negativa Moderada
pct_pobreza -0.517 Negativa Moderada
pct_cerca_lotes_oscuros -0.365 Negativa Débil
min_cai_policia -0.339 Negativa Débil
pct_percibe_inseguridad -0.293 Negativa Débil
casos_total 0.243 Positiva Débil
luminarias_km2 0.119 Positiva Muy débil

5.6.7. Consideraciones generales del análisis de relaciones

El análisis de correlaciones permitió integrar diferentes dimensiones de las UPZ y explorar posibles asociaciones entre las características territoriales y los indicadores de seguridad.

La matriz integrada y las tablas de correlaciones facilitan la identificación de relaciones que pueden ser relevantes para comprender las diferencias entre territorios. Sin embargo, estos resultados deben interpretarse dentro del alcance exploratorio del estudio.

Las asociaciones estadísticas no permiten establecer relaciones de causalidad y tampoco garantizan que los patrones observados se mantengan en otros periodos. Adicionalmente, las diferencias temporales entre las fuentes y las estimaciones agrupadas de la Encuesta Multipropósito representan limitaciones que deben considerarse en la interpretación.

Los resultados de esta sección servirán como referencia para profundizar en la distribución espacial de los indicadores y examinar si los patrones estadísticos identificados también se manifiestan territorialmente.

6. Visualización geográfica: distribución territorial de la inseguridad en Bogotá

El análisis geográfico permite complementar los resultados estadísticos mediante la representación espacial de los indicadores asociados con las condiciones de seguridad de las UPZ de Bogotá.

Mientras que las tablas y los gráficos anteriores permiten identificar distribuciones, diferencias y asociaciones entre variables, los mapas facilitan la comprensión de cómo se distribuyen estos comportamientos en el territorio.

Para desarrollar esta etapa se integrará la información estadística de las UPZ con los archivos geográficos que contienen sus límites territoriales. De esta manera, será posible representar indicadores como la cantidad de delitos denunciados, las tasas de criminalidad, la percepción de inseguridad y algunas características socioeconómicas y de infraestructura.

La visualización se realizará mediante mapas temáticos, utilizando escalas de color que permitan diferenciar los niveles de cada indicador entre las unidades territoriales.

El propósito no es únicamente identificar las UPZ con valores altos o bajos, sino reconocer posibles concentraciones espaciales, diferencias entre localidades y patrones territoriales que complementen los resultados del análisis exploratorio.

Es importante tener presente que la representación geográfica no modifica las limitaciones de las fuentes originales. Por tanto, los mapas deben interpretarse considerando los periodos de referencia de los datos, las diferencias en las metodologías de medición y las características de las estimaciones disponibles.

6.1. Revisión de la información geográfica

Primero debemos conocer la estructura de los archivos geográficos. Aunque ya los cargamos, necesitamos identificar sus campos, sistemas de coordenadas y características generales.

# Revisar la estructura del archivo geográfico de UPZ

cat("ESTRUCTURA DEL ARCHIVO DE UPZ\n")
## ESTRUCTURA DEL ARCHIVO DE UPZ
glimpse(upz_shp)
## Rows: 112
## Columns: 3
## $ upz_cod    <int> 80, 11, 59, 25, 70, 46, 29, 85, 50, 22, 108, 48, 96, 75, 51…
## $ upz_nombre <chr> "Corabastos", "San Cristobal Norte", "Alfonso Lopez", "La F…
## $ geometry   <MULTIPOLYGON [°]> MULTIPOLYGON (((-74.15509 4..., MULTIPOLYGON (…
# Identificar los campos disponibles

names(upz_shp)
## [1] "upz_cod"    "upz_nombre" "geometry"
# Revisar el sistema de coordenadas

st_crs(upz_shp)
## Coordinate Reference System:
##   User input: WGS 84 
##   wkt:
## GEOGCRS["WGS 84",
##     DATUM["World Geodetic System 1984",
##         ELLIPSOID["WGS 84",6378137,298.257223563,
##             LENGTHUNIT["metre",1]]],
##     PRIMEM["Greenwich",0,
##         ANGLEUNIT["degree",0.0174532925199433]],
##     CS[ellipsoidal,2],
##         AXIS["latitude",north,
##             ORDER[1],
##             ANGLEUNIT["degree",0.0174532925199433]],
##         AXIS["longitude",east,
##             ORDER[2],
##             ANGLEUNIT["degree",0.0174532925199433]],
##     ID["EPSG",4326]]
# Consultar la cantidad de polígonos

nrow(upz_shp)
## [1] 112
# Revisar los primeros registros

head(st_drop_geometry(upz_shp), 5)
upz_cod upz_nombre
80 Corabastos
11 San Cristobal Norte
59 Alfonso Lopez
25 La Floresta
70 Jerusalem

Ahora realizamos la misma revisión para el archivo geográfico de localidades.

# Revisar la estructura del archivo de localidades

cat("ESTRUCTURA DEL ARCHIVO DE LOCALIDADES\n")
## ESTRUCTURA DEL ARCHIVO DE LOCALIDADES
glimpse(localidades_shp)
## Rows: 19
## Columns: 3
## $ loc_cod   <int> 9, 18, 17, 12, 13, 16, 14, 1, 2, 4, 5, 19, 7, 8, 10, 11, 6, …
## $ localidad <chr> "Fontibón", "Rafael Uribe Uribe", "Candelaria", "Barrios Uni…
## $ geometry  <MULTIPOLYGON [°]> MULTIPOLYGON (((-74.15857 4..., MULTIPOLYGON ((…
# Identificar los campos disponibles

names(localidades_shp)
## [1] "loc_cod"   "localidad" "geometry"
# Revisar el sistema de coordenadas

st_crs(localidades_shp)
## Coordinate Reference System:
##   User input: WGS 84 
##   wkt:
## GEOGCRS["WGS 84",
##     DATUM["World Geodetic System 1984",
##         ELLIPSOID["WGS 84",6378137,298.257223563,
##             LENGTHUNIT["metre",1]]],
##     PRIMEM["Greenwich",0,
##         ANGLEUNIT["degree",0.0174532925199433]],
##     CS[ellipsoidal,2],
##         AXIS["latitude",north,
##             ORDER[1],
##             ANGLEUNIT["degree",0.0174532925199433]],
##         AXIS["longitude",east,
##             ORDER[2],
##             ANGLEUNIT["degree",0.0174532925199433]],
##     ID["EPSG",4326]]
# Consultar la cantidad de polígonos

nrow(localidades_shp)
## [1] 19
# Revisar los primeros registros

head(st_drop_geometry(localidades_shp), 5)
loc_cod localidad
9 Fontibón
18 Rafael Uribe Uribe
17 Candelaria
12 Barrios Unidos
13 Teusaquillo

6.1.1. Verificación visual de los archivos geográficos

Antes de integrar la información estadística, también es conveniente visualizar los polígonos originales. Esto permite comprobar que las geometrías se encuentran correctamente cargadas y que corresponden al territorio de Bogotá.

# Visualización inicial de los polígonos de las UPZ

ggplot() +
  geom_sf(
    data = upz_shp,
    fill = "#E9E3ED",
    color = morado,
    linewidth = 0.25
  ) +
  labs(
    title = "División territorial de Bogotá por UPZ",
    subtitle = "Representación de los polígonos geográficos disponibles",
    caption = "Fuente: archivo geográfico de UPZ suministrado para el taller."
  ) +
  tema_clase +
  theme(
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank()
  )

6.2. Integración de la información estadística y geográfica

Una vez revisada la estructura de los archivos geográficos, se procede a integrar la información estadística de las UPZ con sus respectivos polígonos territoriales.

Para realizar esta operación se utiliza el campo upz_cod, que funciona como identificador común entre ambas fuentes. Este procedimiento permite incorporar los indicadores demográficos, socioeconómicos, de infraestructura y de seguridad a cada unidad geográfica, conservando la geometría necesaria para su representación cartográfica.

Antes de construir los mapas temáticos, se valida que la unión conserve la totalidad de los registros, que no existan códigos sin correspondencia y que las variables estadísticas se encuentren disponibles después de la integración.

Esta validación es importante porque cualquier inconsistencia en la relación entre los datos y los polígonos podría generar representaciones territoriales incompletas o asignaciones incorrectas de los indicadores.

# Integrar la información estadística con los polígonos de las UPZ

upz_mapa <- upz_shp %>%
  left_join(
    upz %>% select(-upz_nombre),
    by = "upz_cod"
  )

# Validar la cantidad de registros y polígonos

cat("REGISTROS DE LA BASE ESTADÍSTICA:", nrow(upz), "\n")
## REGISTROS DE LA BASE ESTADÍSTICA: 112
cat("POLÍGONOS DEL ARCHIVO GEOGRÁFICO:", nrow(upz_shp), "\n")
## POLÍGONOS DEL ARCHIVO GEOGRÁFICO: 112
cat("REGISTROS DESPUÉS DE LA UNIÓN:", nrow(upz_mapa), "\n")
## REGISTROS DESPUÉS DE LA UNIÓN: 112
# Identificar códigos de la base estadística sin geometría

upz_sin_geometria <- upz %>%
  anti_join(
    st_drop_geometry(upz_shp),
    by = "upz_cod"
  )

# Identificar polígonos sin información estadística

poligonos_sin_datos <- st_drop_geometry(upz_shp) %>%
  anti_join(
    upz,
    by = "upz_cod"
  )

# Revisar valores faltantes en las variables estadísticas integradas

faltantes_integracion <- upz_mapa %>%
  st_drop_geometry() %>%
  summarise(
    across(
      everything(),
      ~ sum(is.na(.))
    )
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Variable",
    values_to = "Valores_faltantes"
  ) %>%
  filter(Valores_faltantes > 0)

# Presentar resultados de validación

cat("\nCÓDIGOS SIN GEOMETRÍA:", nrow(upz_sin_geometria), "\n")
## 
## CÓDIGOS SIN GEOMETRÍA: 0
cat("POLÍGONOS SIN DATOS:", nrow(poligonos_sin_datos), "\n")
## POLÍGONOS SIN DATOS: 0
cat("VARIABLES CON VALORES FALTANTES:", nrow(faltantes_integracion), "\n")
## VARIABLES CON VALORES FALTANTES: 0
# Consultar los primeros registros de la base integrada

head(
  st_drop_geometry(upz_mapa) %>%
    select(
      upz_cod,
      upz_nombre,
      poblacion,
      casos_total,
      tasa_total
    ),
  10
)
upz_cod upz_nombre poblacion casos_total tasa_total
80 Corabastos 56102 1103 196.61
11 San Cristobal Norte 72939 793 108.72
59 Alfonso Lopez 53774 455 84.61
25 La Floresta 46543 886 190.36
70 Jerusalem 102981 1061 103.03
46 Castilla 141571 2646 186.90
29 Minuto De Dios 110520 2183 197.52
85 Bosa Central 237111 3346 141.12
50 La Gloria 96862 918 94.77
22 Doce De Octubre 75666 2031 268.42

6.3. Distribución territorial de los delitos

Una vez integrada la información estadística y geográfica, se inicia la representación espacial de los indicadores de seguridad.

En primer lugar, se analiza la distribución de la tasa total de delitos por cada 10.000 habitantes. Este indicador permite comparar las UPZ considerando su población y evita interpretar los conteos absolutos como si fueran directamente equivalentes a una mayor intensidad delictiva.

La representación mediante un mapa coroplético permite identificar diferencias territoriales en los niveles de la tasa y reconocer posibles concentraciones espaciales. Para complementar esta lectura, también se analizará la distribución del número total de casos denunciados.

Es importante recordar que los indicadores de delitos corresponden al periodo enero-julio de 2023 y representan denuncias registradas, no necesariamente la totalidad de los hechos ocurridos.

# Mapa de la tasa total de delitos por cada 10.000 habitantes

ggplot(upz_mapa) +
  geom_sf(
    aes(fill = tasa_total),
    color = "white",
    linewidth = 0.15
  ) +
  scale_fill_gradientn(
    colours = c("#E9E3ED", "#A98DBB", "#D9006C", "#351A4F"),
    name = "Tasa por\n10.000 habitantes",
    labels = scales::label_number(accuracy = 0.1),
    na.value = "grey85"
  ) +
  labs(
    title = "Distribución territorial de la tasa total de delitos",
    subtitle = "UPZ de Bogotá · Enero a julio de 2023",
    caption = "Fuente: elaboración propia con información estadística y geográfica suministrada para el taller."
  ) +
  tema_clase +
  theme(
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    legend.position = "right"
  )

Mapa de casos totales denunciados

# Mapa del número total de casos denunciados

ggplot(upz_mapa) +
  geom_sf(
    aes(fill = casos_total),
    color = "white",
    linewidth = 0.15
  ) +
  scale_fill_gradientn(
    colours = c("#E9E3ED", "#A98DBB", "#D9006C", "#351A4F"),
    name = "Casos\ndenunciados",
    labels = scales::label_comma(),
    na.value = "grey85"
  ) +
  labs(
    title = "Distribución territorial de los casos denunciados",
    subtitle = "UPZ de Bogotá · Enero a julio de 2023",
    caption = "Fuente: elaboración propia con información estadística y geográfica suministrada para el taller."
  ) +
  tema_clase +
  theme(
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    legend.position = "right"
  )

6.3.1. Evaluación de la asimetría y los valores extremos

Antes de construir la representación cartográfica definitiva, se revisó la distribución de la tasa total de delitos para identificar posibles valores extremos que pudieran afectar la interpretación visual.

Esta revisión permite reconocer que las tasas pueden presentar valores elevados cuando el número de habitantes de una UPZ es reducido. En estos casos, una cantidad relativamente pequeña de denuncias puede producir tasas considerablemente altas.

Por esta razón, se considera necesario diferenciar entre el valor numérico de la tasa y su estabilidad como indicador comparativo. Los valores originales se conservarán, pero se evaluarán alternativas de representación que permitan visualizar mejor las diferencias entre las unidades territoriales.

# Crear vector con los valores válidos
tasas_validas <- upz$tasa_total[
  !is.na(upz$tasa_total) & is.finite(upz$tasa_total)
]

# Calcular asimetría mediante el tercer momento estandarizado
asimetria <- mean(
  (tasas_validas - mean(tasas_validas))^3
) / sd(tasas_validas)^3

# Resumen de la distribución de la tasa total

upz %>%
  summarise(
    Minimo = min(tasa_total, na.rm = TRUE),
    Q1 = quantile(tasa_total, 0.25, na.rm = TRUE),
    Mediana = median(tasa_total, na.rm = TRUE),
    Q3 = quantile(tasa_total, 0.75, na.rm = TRUE),
    P90 = quantile(tasa_total, 0.90, na.rm = TRUE),
    P95 = quantile(tasa_total, 0.95, na.rm = TRUE),
    Maximo = max(tasa_total, na.rm = TRUE)
  )
Minimo Q1 Mediana Q3 P90 P95 Maximo
64.47 129.5075 192.525 287.615 1019.12 1561.871 11333.33
# Presentar el coeficiente de asimetría

cat(
  "Coeficiente de asimetría:",
  round(asimetria, 3),
  "\n"
)
## Coeficiente de asimetría: 6.549
# Identificar las 10 UPZ con mayores tasas

upz %>%
  arrange(desc(tasa_total)) %>%
  select(
    upz_nombre,
    poblacion,
    casos_total,
    tasa_total
  ) %>%
  slice_head(n = 10)
upz_nombre poblacion casos_total tasa_total
El Mochuelo 30 34 11333.33
Aeropuerto El Dorado 883 545 6172.14
Parque Simon Bolivar - Can 3323 958 2882.94
Zona Industrial 6666 1573 2359.74
Las Nieves 17203 4033 2344.36
Parque Salitre 1442 233 1615.81
Sagrado Corazon 11247 1707 1517.74
La Sabana 38856 5441 1400.30
Chico Lago 38608 4985 1291.18
Puente Aranda 12482 1561 1250.60

6.3.2. Representación de la tasa mediante escala logarítmica

Debido a la asimetría identificada en la distribución de la tasa total de delitos, se propone una representación cartográfica complementaria mediante una escala logarítmica.

Esta transformación permite reducir el efecto visual de los valores extremos y mejorar la diferenciación de las UPZ que presentan tasas bajas y medias. Es importante aclarar que la transformación se aplica exclusivamente a la escala de representación y no modifica los valores originales utilizados en el análisis estadístico.

De esta manera, se busca facilitar la comparación territorial sin eliminar observaciones ni ocultar la existencia de valores elevados.

# Identificar UPZ con poblaciones más pequeñas

upz %>%
  arrange(poblacion) %>%
  select(
    upz_nombre,
    poblacion,
    casos_total,
    tasa_total
  ) %>%
  slice_head(n = 15)
upz_nombre poblacion casos_total tasa_total
El Mochuelo 30 34 11333.33
Aeropuerto El Dorado 883 545 6172.14
Parque Entrenubes 1169 16 136.87
Parque Salitre 1442 233 1615.81
Paseo De Los Libertadores 2690 74 275.09
Guaymaral 2692 45 167.16
Jardin Botanico 2900 266 917.24
Parque Simon Bolivar - Can 3323 958 2882.94
La Academia 5260 123 233.84
Monte Blanco 6575 80 121.67
Zona Industrial 6666 1573 2359.74
Sagrado Corazon 11247 1707 1517.74
Alamos 12077 642 531.59
La Macarena 12253 507 413.78
Puente Aranda 12482 1561 1250.60

6.3.3. Clasificación territorial mediante quintiles

Como alternativa a la representación mediante escalas continuas, se construye un mapa temático basado en quintiles. Esta clasificación organiza las UPZ en cinco grupos de acuerdo con la posición relativa de sus tasas de delitos.

La utilización de quintiles facilita la identificación de las unidades territoriales que presentan niveles relativamente bajos, intermedios o altos dentro del conjunto analizado.

A diferencia de la transformación logarítmica, esta clasificación no modifica la escala numérica de los datos, sino que agrupa las observaciones en categorías. Por tanto, debe interpretarse como una herramienta de comparación relativa y no como una clasificación de riesgo absoluto.

Los valores originales de las tasas se conservan para los análisis estadísticos y para la identificación de posibles valores extremos.

# Clasificar las UPZ en cinco grupos según su tasa total

upz_mapa <- upz_mapa %>%
  mutate(
    quintil_tasa = ntile(tasa_total, 5),
    quintil_tasa = factor(
      quintil_tasa,
      levels = 1:5,
      labels = c(
        "Q1 - Muy bajo",
        "Q2 - Bajo",
        "Q3 - Medio",
        "Q4 - Alto",
        "Q5 - Muy alto"
      )
    )
  )

# Construir mapa por quintiles

ggplot(upz_mapa) +
  geom_sf(
    aes(fill = quintil_tasa),
    color = "white",
    linewidth = 0.15
  ) +
  scale_fill_manual(
    values = c(
      "Q1 - Muy bajo" = "#E9E3ED",
      "Q2 - Bajo" = "#C8B5D3",
      "Q3 - Medio" = "#A98DBB",
      "Q4 - Alto" = "#D9006C",
      "Q5 - Muy alto" = "#351A4F"
    ),
    name = "Quintiles",
    na.value = "grey85"
  ) +
  labs(
    title = "Clasificación territorial de la tasa de delitos",
    subtitle = "UPZ agrupadas en cinco quintiles · Enero a julio de 2023",
    caption = "Los quintiles representan posiciones relativas dentro de las UPZ analizadas. No constituyen categorías de riesgo absoluto."
  ) +
  tema_clase +
  theme(
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    legend.position = "right"
  )

upz_mapa %>%
  st_drop_geometry() %>%
  group_by(quintil_tasa) %>%
  summarise(
    Numero_UPZ = n(),
    Tasa_minima = min(tasa_total, na.rm = TRUE),
    Tasa_mediana = median(tasa_total, na.rm = TRUE),
    Tasa_maxima = max(tasa_total, na.rm = TRUE),
    Poblacion_total = sum(poblacion, na.rm = TRUE),
    .groups = "drop"
  )
quintil_tasa Numero_UPZ Tasa_minima Tasa_mediana Tasa_maxima Poblacion_total
Q1 - Muy bajo 23 64.47 99.850 119.89 2584989
Q2 - Bajo 23 121.67 143.740 167.17 2048928
Q3 - Medio 22 167.77 195.650 225.79 1775200
Q4 - Alto 22 233.84 270.825 413.78 1068099
Q5 - Muy alto 22 427.21 1062.765 11333.33 459316

6.3.4. Evaluación de las tasas en UPZ con poblaciones pequeñas

Antes de interpretar los mapas como una distribución territorial de inseguridad, debemos revisar el tamaño de la población que sirve como denominador de las tasas.

# Identificar las 15 UPZ con menor población

upz %>%
  arrange(poblacion) %>%
  select(
    upz_nombre,
    poblacion,
    casos_total,
    tasa_total
  ) %>%
  slice_head(n = 15)
upz_nombre poblacion casos_total tasa_total
El Mochuelo 30 34 11333.33
Aeropuerto El Dorado 883 545 6172.14
Parque Entrenubes 1169 16 136.87
Parque Salitre 1442 233 1615.81
Paseo De Los Libertadores 2690 74 275.09
Guaymaral 2692 45 167.16
Jardin Botanico 2900 266 917.24
Parque Simon Bolivar - Can 3323 958 2882.94
La Academia 5260 123 233.84
Monte Blanco 6575 80 121.67
Zona Industrial 6666 1573 2359.74
Sagrado Corazon 11247 1707 1517.74
Alamos 12077 642 531.59
La Macarena 12253 507 413.78
Puente Aranda 12482 1561 1250.60
# Relación entre población y tasa total

ggplot(upz, aes(x = poblacion, y = tasa_total)) +
  geom_point(
    color = "#D9006C",
    alpha = 0.75,
    size = 2.5
  ) +
  scale_x_continuous(
    labels = scales::label_comma()
  ) +
  scale_y_continuous(
    labels = scales::label_comma()
  ) +
  labs(
    title = "Población y tasa total de delitos por UPZ",
    subtitle = "Evaluación de la influencia del tamaño poblacional",
    x = "Población",
    y = "Tasa por cada 10.000 habitantes"
  ) +
  tema_clase

6.4. Mapa interactivo de la distribución territorial de los delitos

Como complemento a las representaciones cartográficas estáticas, se construye un mapa interactivo mediante la librería Leaflet. Esta herramienta permite explorar las unidades territoriales con mayor detalle y consultar información específica de cada UPZ.

La visualización utiliza la clasificación por quintiles de la tasa total de delitos, conservando la misma categorización del mapa estático. Al seleccionar o ubicar el cursor sobre cada polígono, es posible consultar el nombre de la UPZ, su población, el número de casos denunciados y la tasa registrada durante el periodo analizado.

Esta representación facilita la exploración individual de los territorios y permite contrastar los valores absolutos con las tasas relativas, sin perder de vista las limitaciones asociadas al tamaño poblacional de algunas UPZ.

# Definir la paleta de colores para los quintiles

paleta_quintiles <- colorFactor(
  palette = c(
    "#E9E3ED",
    "#C8B5D3",
    "#A98DBB",
    "#D9006C",
    "#351A4F"
  ),
  domain = levels(upz_mapa$quintil_tasa),
  na.color = "grey85"
)

# Construir etiquetas de las UPZ

etiquetas_upz <- paste0(
  "<strong>UPZ: </strong>",
  upz_mapa$upz_nombre,
  "<br><strong>Población: </strong>",
  scales::comma(upz_mapa$poblacion),
  "<br><strong>Casos denunciados: </strong>",
  scales::comma(upz_mapa$casos_total),
  "<br><strong>Tasa por 10.000 habitantes: </strong>",
  scales::number(upz_mapa$tasa_total, accuracy = 0.1),
  "<br><strong>Clasificación: </strong>",
  upz_mapa$quintil_tasa
)

# Crear mapa interactivo

leaflet(upz_mapa) %>%
  addProviderTiles(
    providers$OpenStreetMap.Mapnik
  ) %>%
  addPolygons(
    fillColor = ~paleta_quintiles(quintil_tasa),
    fillOpacity = 0.75,
    color = "white",
    weight = 1,
    opacity = 1,
    label = lapply(etiquetas_upz, htmltools::HTML),
    highlightOptions = highlightOptions(
      weight = 3,
      color = "#D9006C",
      fillOpacity = 0.9,
      bringToFront = TRUE
    )
  ) %>%
  addLegend(
    position = "bottomright",
    pal = paleta_quintiles,
    values = ~quintil_tasa,
    title = "Tasa de delitos",
    opacity = 0.8
  )

6.5. Comparación de las representaciones cartográficas

Las representaciones cartográficas desarrolladas permiten observar la distribución territorial de los delitos desde diferentes perspectivas.

La escala continua conserva la magnitud original de las tasas, aunque puede verse condicionada por la presencia de valores extremos. La escala logarítmica facilita la diferenciación visual de los valores bajos e intermedios, mientras que la clasificación por quintiles permite comparar la posición relativa de cada UPZ dentro del conjunto analizado.

Estas alternativas no son excluyentes, ya que responden a objetivos de visualización diferentes. Por esta razón, su interpretación debe considerar tanto la escala utilizada como las características de la población de cada unidad territorial.

En particular, las tasas calculadas sobre poblaciones pequeñas requieren precaución, debido a que pocos casos pueden generar variaciones importantes en el indicador. Por tanto, los mapas deben interpretarse como una exploración de las denuncias registradas y no como una medición definitiva de la inseguridad real de cada territorio.

6.5. Distribución territorial de la percepción de inseguridad y las condiciones del entorno

Además de los registros de delitos denunciados, el análisis incorpora variables relacionadas con la percepción de inseguridad y las características del entorno urbano.

Estas dimensiones permiten ampliar la comprensión del fenómeno, considerando que la experiencia de inseguridad de los habitantes no necesariamente coincide con la cantidad de denuncias registradas en cada territorio.

En esta sección se explora la distribución geográfica de la percepción de inseguridad, la cercanía a determinados elementos del entorno y la accesibilidad a los CAI de policía. El propósito es identificar diferencias territoriales y contrastarlas con los indicadores de delitos analizados anteriormente.

# Mapa de percepción de inseguridad

ggplot(upz_mapa) +
  geom_sf(
    aes(fill = pct_percibe_inseguridad),
    color = "white",
    linewidth = 0.15
  ) +
  scale_fill_gradientn(
    colours = c("#E9E3ED", "#A98DBB", "#D9006C", "#351A4F"),
    name = "Percepción\n(%)",
    na.value = "grey85"
  ) +
  labs(
    title = "Percepción de inseguridad en el entorno de las UPZ",
    subtitle = "Porcentaje reportado en la Encuesta Multipropósito 2021",
    caption = "Fuente: Encuesta Multipropósito DANE 2021. Algunas UPZ comparten estimaciones agrupadas."
  ) +
  tema_clase +
  theme(
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    legend.position = "right"
  )

6.5.2. Condiciones del entorno urbano

Las características del entorno pueden aportar información adicional para comprender las diferencias territoriales relacionadas con la seguridad.

Para este análisis se consideran dos indicadores de la Encuesta Multipropósito: el porcentaje de viviendas afectadas por la cercanía a lotes baldíos o sitios oscuros y el porcentaje de viviendas afectadas por la cercanía a expendios de droga.

La representación geográfica de estas variables permite explorar cómo se distribuyen dichas condiciones entre las UPZ y posteriormente contrastarlas con las tasas de delitos denunciados.

Es importante señalar que estos indicadores corresponden a percepciones o condiciones reportadas por los hogares encuestados. Por tanto, no deben interpretarse como evidencia directa de que estos elementos ocasionen mayores niveles de delincuencia.

ggplot(upz_mapa) +
  geom_sf(
    aes(fill = pct_cerca_lotes_oscuros),
    color = "white",
    linewidth = 0.15
  ) +
  scale_fill_gradientn(
    colours = c("#E9E3ED", "#A98DBB", "#D9006C", "#351A4F"),
    name = "Viviendas\nafectadas (%)",
    na.value = "grey85"
  ) +
  labs(
    title = "Cercanía a lotes baldíos y sitios oscuros",
    subtitle = "Porcentaje de viviendas afectadas · Encuesta 2021",
    caption = "Fuente: Encuesta Multipropósito DANE 2021. Algunas UPZ comparten estimaciones agrupadas."
  ) +
  tema_clase +
  theme(
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    legend.position = "right"
  )

ggplot(upz_mapa) +
  geom_sf(
    aes(fill = pct_cerca_ollas),
    color = "white",
    linewidth = 0.15
  ) +
  scale_fill_gradientn(
    colours = c("#E9E3ED", "#A98DBB", "#D9006C", "#351A4F"),
    name = "Viviendas\nafectadas (%)",
    na.value = "grey85"
  ) +
  labs(
    title = "Cercanía a expendios de droga",
    subtitle = "Porcentaje de viviendas afectadas · Encuesta 2021",
    caption = "Fuente: Encuesta Multipropósito DANE 2021. Algunas UPZ comparten estimaciones agrupadas."
  ) +
  tema_clase +
  theme(
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    legend.position = "right"
  )

6.5.3. Accesibilidad territorial a los CAI de policía

La accesibilidad a los servicios de seguridad constituye otra dimensión de interés para el análisis territorial.

Para explorar esta característica se utiliza la variable min_cai_policia, que representa el tiempo promedio caminando desde las viviendas hasta un CAI de policía.

Su representación geográfica permite identificar diferencias en la accesibilidad territorial y contrastarlas posteriormente con los indicadores de delitos y percepción de inseguridad.

Sin embargo, este indicador debe interpretarse con precaución, ya que la distancia o el tiempo promedio de desplazamiento no representan por sí mismos la capacidad operativa de la Policía, su presencia permanente en el territorio ni los tiempos efectivos de atención.

ggplot(upz_mapa) +
  geom_sf(
    aes(fill = min_cai_policia),
    color = "white",
    linewidth = 0.15
  ) +
  scale_fill_gradientn(
    colours = c("#E9E3ED", "#A98DBB", "#D9006C", "#351A4F"),
    name = "Minutos\ncaminando",
    na.value = "grey85"
  ) +
  labs(
    title = "Accesibilidad territorial a los CAI de policía",
    subtitle = "Tiempo promedio caminando desde las viviendas",
    caption = "Fuente: Encuesta Multipropósito DANE 2021. Algunas UPZ comparten estimaciones agrupadas."
  ) +
  tema_clase +
  theme(
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    legend.position = "right"
  )

6.5.4. Consolidación de indicadores territoriales

Antes de pasar a la interpretación, construimos una tabla que reúne los indicadores de seguridad, percepción y entorno. Esto nos permitirá identificar las UPZ que presentan valores destacados en diferentes dimensiones.

tabla_indicadores_territoriales <- upz %>%
  select(
    upz_nombre,
    poblacion,
    casos_total,
    tasa_total,
    pct_percibe_inseguridad,
    pct_cerca_lotes_oscuros,
    pct_cerca_ollas,
    min_cai_policia,
    em_agrupada
  ) %>%
  arrange(desc(tasa_total))

knitr::kable(
  head(tabla_indicadores_territoriales, 15),
  digits = 2,
  caption = "UPZ con mayores tasas de delitos y sus indicadores territoriales"
)
UPZ con mayores tasas de delitos y sus indicadores territoriales
upz_nombre poblacion casos_total tasa_total pct_percibe_inseguridad pct_cerca_lotes_oscuros pct_cerca_ollas min_cai_policia em_agrupada
El Mochuelo 30 34 11333.33 86.83 44.99 52.33 27.39 TRUE
Aeropuerto El Dorado 883 545 6172.14 32.58 40.06 17.00 26.31 TRUE
Parque Simon Bolivar - Can 3323 958 2882.94 32.98 1.22 0.31 13.10 TRUE
Zona Industrial 6666 1573 2359.74 66.27 45.32 51.50 17.17 TRUE
Las Nieves 17203 4033 2344.36 59.85 18.59 23.13 10.06 TRUE
Parque Salitre 1442 233 1615.81 65.97 13.78 10.63 16.14 TRUE
Sagrado Corazon 11247 1707 1517.74 59.85 18.59 23.13 10.06 TRUE
La Sabana 38856 5441 1400.30 83.45 38.71 61.44 16.00 FALSE
Chico Lago 38608 4985 1291.18 21.48 0.64 3.12 13.11 TRUE
Puente Aranda 12482 1561 1250.60 66.27 45.32 51.50 17.17 TRUE
Chapinero 26491 2901 1095.09 50.28 10.35 20.92 15.62 TRUE
Teusaquillo 28881 2976 1030.44 62.90 5.91 6.04 10.36 FALSE
Jardin Botanico 2900 266 917.24 76.48 8.34 3.18 17.71 TRUE
Galerias 38425 3067 798.18 48.52 17.51 22.49 12.79 FALSE
Los Alcazares 44678 3495 782.26 69.78 11.13 18.43 12.78 FALSE

6.6. Comparación territorial entre delitos y condiciones del entorno

Después de explorar la distribución geográfica de los indicadores, se realiza una comparación visual entre la tasa total de delitos y algunas características sociales y urbanas de las UPZ.

El propósito es identificar si las unidades territoriales que presentan mayores niveles de percepción de inseguridad o determinadas condiciones del entorno también registran tasas de delitos más elevadas.

Este análisis complementa las correlaciones estadísticas desarrolladas anteriormente, ya que permite observar la dispersión de las observaciones, reconocer posibles valores extremos y evaluar si existe algún patrón visual entre las variables.

# Relación entre tasa de delitos y percepción de inseguridad

ggplot(
  upz,
  aes(
    x = pct_percibe_inseguridad,
    y = tasa_total,
    color = em_agrupada
  )
) +
  geom_point(
    alpha = 0.75,
    size = 2.5
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = "#168C86",
      "TRUE" = "#D9006C"
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    ),
    name = "Tipo de estimación"
  ) +
  labs(
    title = "Tasa de delitos y percepción de inseguridad",
    subtitle = "Comparación entre UPZ · Eje vertical en escala logarítmica",
    x = "Percepción de inseguridad (%)",
    y = "Tasa de delitos por 10.000 habitantes",
    caption = "Fuentes: Encuesta Multipropósito 2021 y registros de delitos enero-julio 2023."
  ) +
  tema_clase

6.6.2. Tasa de delitos y condiciones del entorno

Se explora la relación entre la tasa total de delitos y dos indicadores asociados con las condiciones del entorno urbano: la cercanía a lotes baldíos o sitios oscuros y la cercanía a expendios de droga.

Estas variables permiten examinar si las UPZ donde una mayor proporción de viviendas reporta estas condiciones también presentan mayores tasas de delitos denunciados.

La comparación se realiza mediante gráficos de dispersión, manteniendo identificadas las estimaciones agrupadas de la Encuesta Multipropósito. Los resultados permiten reconocer posibles tendencias y diferencias entre las unidades territoriales, sin asumir que las condiciones observadas expliquen directamente la ocurrencia de delitos.

ggplot(
  upz,
  aes(
    x = pct_cerca_lotes_oscuros,
    y = tasa_total,
    color = em_agrupada
  )
) +
  geom_point(
    alpha = 0.75,
    size = 2.5
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = "#168C86",
      "TRUE" = "#D9006C"
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    ),
    name = "Tipo de estimación"
  ) +
  labs(
    title = "Cercanía a lotes oscuros y tasa de delitos",
    subtitle = "Eje vertical en escala logarítmica",
    x = "Viviendas afectadas por cercanía a lotes oscuros (%)",
    y = "Tasa de delitos por 10.000 habitantes",
    caption = "Fuentes: Encuesta Multipropósito 2021 y registros de delitos enero-julio 2023."
  ) +
  tema_clase

ggplot(
  upz,
  aes(
    x = pct_cerca_ollas,
    y = tasa_total,
    color = em_agrupada
  )
) +
  geom_point(
    alpha = 0.75,
    size = 2.5
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = "#168C86",
      "TRUE" = "#D9006C"
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    ),
    name = "Tipo de estimación"
  ) +
  labs(
    title = "Cercanía a expendios de droga y tasa de delitos",
    subtitle = "Eje vertical en escala logarítmica",
    x = "Viviendas afectadas por cercanía a expendios de droga (%)",
    y = "Tasa de delitos por 10.000 habitantes",
    caption = "Fuentes: Encuesta Multipropósito 2021 y registros de delitos enero-julio 2023."
  ) +
  tema_clase

6.6.3. Tasa de delitos y accesibilidad a los CAI

Como última comparación se analiza la relación entre la tasa total de delitos y el tiempo promedio caminando hasta un CAI de policía.

Esta exploración permite observar si existen diferencias en las tasas de delitos entre las UPZ según su nivel de accesibilidad territorial a este servicio.

La variable utilizada representa tiempos promedio de desplazamiento y no mide directamente la cobertura policial, la cantidad de uniformados o la capacidad de respuesta institucional. Por tanto, cualquier asociación identificada debe interpretarse considerando el alcance específico del indicador.

ggplot(
  upz,
  aes(
    x = min_cai_policia,
    y = tasa_total,
    color = em_agrupada
  )
) +
  geom_point(
    alpha = 0.75,
    size = 2.5
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = "#168C86",
      "TRUE" = "#D9006C"
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    ),
    name = "Tipo de estimación"
  ) +
  labs(
    title = "Accesibilidad a los CAI y tasa de delitos",
    subtitle = "Eje vertical en escala logarítmica",
    x = "Tiempo promedio caminando hasta un CAI (minutos)",
    y = "Tasa de delitos por 10.000 habitantes",
    caption = "Fuentes: Encuesta Multipropósito 2021 y registros de delitos enero-julio 2023."
  ) +
  tema_clase

6.6.4. Síntesis de las relaciones territoriales

Los gráficos de dispersión permiten observar el comportamiento conjunto de los indicadores de seguridad y las condiciones territoriales. Para complementar esta exploración visual, se presenta una síntesis de las correlaciones de Spearman entre la tasa total de delitos y las variables seleccionadas.

El coeficiente de Spearman permite evaluar la dirección y la intensidad de una asociación monotónica entre dos variables. Su utilización resulta conveniente en esta etapa exploratoria, debido a que los indicadores presentan distribuciones con asimetrías y posibles valores extremos.

Los coeficientes deben interpretarse como asociaciones estadísticas y no como evidencia de causalidad. Adicionalmente, las variables provenientes de la Encuesta Multipropósito tienen la limitación de contar con estimaciones agrupadas para algunas UPZ.

# Variables seleccionadas para la comparación territorial

variables_territoriales <- upz %>%
  select(
    tasa_total,
    pct_percibe_inseguridad,
    pct_cerca_lotes_oscuros,
    pct_cerca_ollas,
    min_cai_policia
  )

# Calcular correlaciones de Spearman con la tasa total

correlaciones_territoriales <- tibble(
  Variable = c(
    "Percepción de inseguridad",
    "Cercanía a lotes oscuros",
    "Cercanía a expendios de droga",
    "Tiempo de acceso a CAI"
  ),
  rho = c(
    cor(
      variables_territoriales$tasa_total,
      variables_territoriales$pct_percibe_inseguridad,
      method = "spearman",
      use = "complete.obs"
    ),
    cor(
      variables_territoriales$tasa_total,
      variables_territoriales$pct_cerca_lotes_oscuros,
      method = "spearman",
      use = "complete.obs"
    ),
    cor(
      variables_territoriales$tasa_total,
      variables_territoriales$pct_cerca_ollas,
      method = "spearman",
      use = "complete.obs"
    ),
    cor(
      variables_territoriales$tasa_total,
      variables_territoriales$min_cai_policia,
      method = "spearman",
      use = "complete.obs"
    )
  )
) %>%
  mutate(
    Intensidad = case_when(
      abs(rho) < 0.20 ~ "Muy débil",
      abs(rho) < 0.40 ~ "Débil",
      abs(rho) < 0.60 ~ "Moderada",
      abs(rho) < 0.80 ~ "Fuerte",
      TRUE ~ "Muy fuerte"
    ),
    Direccion = if_else(
      rho >= 0,
      "Positiva",
      "Negativa"
    )
  ) %>%
  arrange(desc(abs(rho)))

# Presentar resultados

knitr::kable(
  correlaciones_territoriales,
  digits = 3,
  caption = "Correlaciones de Spearman entre tasa de delitos y condiciones territoriales"
)
Correlaciones de Spearman entre tasa de delitos y condiciones territoriales
Variable rho Intensidad Direccion
Cercanía a lotes oscuros -0.365 Débil Negativa
Tiempo de acceso a CAI -0.339 Débil Negativa
Cercanía a expendios de droga -0.335 Débil Negativa
Percepción de inseguridad -0.293 Débil Negativa

6.6.5. Análisis de sensibilidad de las correlaciones

Debido a que una parte de las UPZ comparte estimaciones provenientes de la Encuesta Multipropósito, se realiza un análisis de sensibilidad para evaluar si esta característica puede influir en las asociaciones identificadas.

Para ello, se comparan las correlaciones de Spearman calculadas con el conjunto completo de UPZ y aquellas obtenidas únicamente con las unidades territoriales que cuentan con estimaciones individuales.

La comparación permite observar si la dirección y la magnitud de las asociaciones se mantienen bajo ambos escenarios. También se considera la cantidad de observaciones utilizadas en cada cálculo, dado que la exclusión de las estimaciones agrupadas reduce el tamaño del conjunto analizado.

Este ejercicio constituye una validación complementaria de los resultados exploratorios. No obstante, el análisis con estimaciones individuales representa un subconjunto de las UPZ y no elimina necesariamente todas las limitaciones de representatividad de la encuesta.

# Definir las variables que se van a comparar

variables_sensibilidad <- c(
  "pct_percibe_inseguridad",
  "pct_cerca_lotes_oscuros",
  "pct_cerca_ollas",
  "min_cai_policia"
)

# Función para calcular las correlaciones de Spearman

calcular_correlaciones <- function(datos, escenario) {

  purrr::map_dfr(variables_sensibilidad, function(variable) {

    datos_validos <- datos %>%
      select(
        tasa_total,
        all_of(variable)
      ) %>%
      drop_na() %>%
      filter(
        is.finite(tasa_total),
        is.finite(.data[[variable]])
      )

    tibble(
      Escenario = escenario,
      Variable = variable,
      Numero_UPZ = nrow(datos_validos),
      rho = if (nrow(datos_validos) >= 3) {
        cor(
          datos_validos$tasa_total,
          datos_validos[[variable]],
          method = "spearman"
        )
      } else {
        NA_real_
      }
    )
  })
}

# Escenario 1: todas las UPZ

correlaciones_completas <- calcular_correlaciones(
  upz,
  "Todas_UPZ"
)

# Escenario 2: únicamente estimaciones individuales

upz_individuales <- upz %>%
  filter(em_agrupada == FALSE)

correlaciones_individuales <- calcular_correlaciones(
  upz_individuales,
  "UPZ_individuales"
)

# Integrar los resultados

comparacion_sensibilidad <- bind_rows(
  correlaciones_completas,
  correlaciones_individuales
) %>%
  mutate(
    Variable = recode(
      Variable,
      pct_percibe_inseguridad = "Percepción de inseguridad",
      pct_cerca_lotes_oscuros = "Cercanía a lotes oscuros",
      pct_cerca_ollas = "Cercanía a expendios de droga",
      min_cai_policia = "Tiempo de acceso a CAI"
    )
  )

# Organizar la comparación en columnas

tabla_sensibilidad <- comparacion_sensibilidad %>%
  pivot_wider(
    names_from = Escenario,
    values_from = c(rho, Numero_UPZ)
  ) %>%
  mutate(
    Diferencia_rho = rho_Todas_UPZ -
      rho_UPZ_individuales,

    Direccion_consistente = case_when(
      is.na(rho_Todas_UPZ) |
        is.na(rho_UPZ_individuales) ~ "No evaluable",

      sign(rho_Todas_UPZ) ==
        sign(rho_UPZ_individuales) ~ "Sí",

      TRUE ~ "No"
    )
  ) %>%
  arrange(desc(abs(rho_Todas_UPZ)))

# Presentar resultados

knitr::kable(
  tabla_sensibilidad,
  digits = 3,
  caption = "Análisis de sensibilidad de las correlaciones de Spearman"
)
Análisis de sensibilidad de las correlaciones de Spearman
Variable rho_Todas_UPZ rho_UPZ_individuales Numero_UPZ_Todas_UPZ Numero_UPZ_UPZ_individuales Diferencia_rho Direccion_consistente
Cercanía a lotes oscuros -0.365 -0.511 112 80 0.145 Sí
Tiempo de acceso a CAI -0.339 -0.455 112 80 0.117 Sí
Cercanía a expendios de droga -0.335 -0.342 112 80 0.007 Sí
Percepción de inseguridad -0.293 -0.253 112 80 -0.040 Sí

Para complementar la comparación numérica, se presenta una visualización de los coeficientes de correlación obtenidos en ambos escenarios. Esta representación permite identificar de manera directa si las asociaciones conservan su dirección y si presentan cambios importantes en su magnitud.

ggplot(
  comparacion_sensibilidad,
  aes(
    x = rho,
    y = reorder(Variable, rho),
    color = Escenario
  )
) +
  geom_vline(
    xintercept = 0,
    linetype = "dashed",
    color = "grey50"
  ) +
  geom_point(
    size = 3,
    position = position_dodge(width = 0.5)
  ) +
  scale_color_manual(
    values = c(
      "Todas_UPZ" = "#351A4F",
      "UPZ_individuales" = "#168C86"
    ),
    labels = c(
      "Todas_UPZ" = "Todas las UPZ",
      "UPZ_individuales" = "Estimaciones individuales"
    ),
    name = "Escenario"
  ) +
  scale_x_continuous(
    limits = c(-1, 1),
    breaks = seq(-1, 1, by = 0.2)
  ) +
  labs(
    title = "Estabilidad de las correlaciones según tipo de estimación",
    subtitle = "Comparación de los coeficientes de Spearman",
    x = "Coeficiente de Spearman",
    y = NULL
  ) +
  tema_clase

7. Preguntas de investigación y hallazgos

7.1. Preguntas que orientan el análisis

El análisis exploratorio se desarrolló a partir de preguntas orientadas a comprender las diferencias territoriales en los indicadores de seguridad y su posible relación con las características demográficas, socioeconómicas y urbanas de las UPZ de Bogotá.

A partir de la información disponible, se establecieron las siguientes preguntas de investigación:

  1. ¿Las UPZ con mayor cantidad de denuncias son también las que presentan mayores tasas de delitos por habitante?
  2. ¿Cómo influye el tamaño poblacional en la interpretación de las tasas de delitos?
  3. ¿Qué diferencias territoriales se observan en la distribución de los delitos denunciados?
  4. ¿Existe alguna asociación entre el alumbrado público y las tasas de delitos?
  5. ¿Qué relación se observa entre pobreza, salario, estrato y los indicadores de seguridad?
  6. ¿La percepción de inseguridad presenta un comportamiento similar al de los delitos denunciados?
  7. ¿Las condiciones del entorno y la accesibilidad a los CAI presentan alguna asociación con las tasas de delitos?

Estas preguntas articulan los análisis estadísticos y las representaciones gráficas desarrolladas en las secciones anteriores. Su propósito es integrar los resultados en una narrativa que permita comprender no solo dónde se registran más denuncias, sino también cómo se relacionan estos registros con las características de cada territorio.

7.2. Matriz de preguntas, variables y análisis realizados

Esta matriz nos permitirá demostrar que cada pregunta tiene un respaldo analítico y que no estamos incluyendo gráficos sin una finalidad concreta.

matriz_preguntas <- tibble(
  Pregunta = c(
    "¿Las UPZ con más denuncias también tienen mayores tasas?",
    "¿Cómo influye el tamaño poblacional en las tasas?",
    "¿Qué diferencias territoriales existen en los delitos?",
    "¿Existe asociación entre alumbrado y delitos?",
    "¿Cómo se relacionan las condiciones socioeconómicas y los delitos?",
    "¿La percepción coincide con los delitos denunciados?",
    "¿Qué relación tienen el entorno y la accesibilidad a los CAI?"
  ),

  Variables = c(
    "casos_total, tasa_total",
    "poblacion, densidad_hab_km2, tasa_total",
    "casos_total, tasa_total, upz_nombre",
    "luminarias_km2, luminarias_1000hab, pct_luminarias_led, tasa_total",
    "pct_pobreza, salario_promedio, pct_estrato_1_2, tasa_total",
    "pct_percibe_inseguridad, tasa_total",
    "pct_cerca_lotes_oscuros, pct_cerca_ollas, min_cai_policia, tasa_total"
  ),

  Analisis = c(
    "Comparación de casos y tasas",
    "Distribuciones y valores extremos",
    "Mapas de tasas y casos",
    "Correlaciones y gráficos de dispersión",
    "Estadísticas descriptivas y correlaciones",
    "Mapas, dispersión y correlación",
    "Mapas, dispersión y análisis de sensibilidad"
  )
)

knitr::kable(
  matriz_preguntas,
  caption = "Relación entre preguntas de investigación, variables y análisis"
)
Relación entre preguntas de investigación, variables y análisis
Pregunta Variables Analisis
¿Las UPZ con más denuncias también tienen mayores tasas? casos_total, tasa_total Comparación de casos y tasas
¿Cómo influye el tamaño poblacional en las tasas? poblacion, densidad_hab_km2, tasa_total Distribuciones y valores extremos
¿Qué diferencias territoriales existen en los delitos? casos_total, tasa_total, upz_nombre Mapas de tasas y casos
¿Existe asociación entre alumbrado y delitos? luminarias_km2, luminarias_1000hab, pct_luminarias_led, tasa_total Correlaciones y gráficos de dispersión
¿Cómo se relacionan las condiciones socioeconómicas y los delitos? pct_pobreza, salario_promedio, pct_estrato_1_2, tasa_total Estadísticas descriptivas y correlaciones
¿La percepción coincide con los delitos denunciados? pct_percibe_inseguridad, tasa_total Mapas, dispersión y correlación
¿Qué relación tienen el entorno y la accesibilidad a los CAI? pct_cerca_lotes_oscuros, pct_cerca_ollas, min_cai_policia, tasa_total Mapas, dispersión y análisis de sensibilidad

7.3. Desarrollo de los hallazgos e insights

7.3.1. ¿Las UPZ con más denuncias son también las que presentan mayores tasas de delitos?

La primera pregunta busca establecer si las unidades territoriales que concentran el mayor número de denuncias son también aquellas que presentan una mayor intensidad delictiva en relación con su población.

Para responderla se comparan dos indicadores: el número total de casos denunciados y la tasa de delitos por cada 10.000 habitantes. Esta distinción es importante porque el volumen de denuncias puede estar relacionado con el tamaño poblacional de cada UPZ, mientras que la tasa permite realizar una comparación relativa.

El análisis se desarrolla mediante la comparación de los rankings de casos y tasas, así como de la relación entre población y número de denuncias. De esta manera, se busca identificar si los territorios que concentran más casos también ocupan las primeras posiciones cuando se considera su población.

# Top 10 de UPZ por número de casos denunciados

ranking_casos_731 <- upz %>%
  arrange(desc(casos_total)) %>%
  select(
    upz_nombre,
    poblacion,
    casos_total,
    tasa_total
  ) %>%
  slice_head(n = 10) %>%
  mutate(Posicion_casos = row_number())

# Top 10 de UPZ por tasa de delitos

ranking_tasas_731 <- upz %>%
  arrange(desc(tasa_total)) %>%
  select(
    upz_nombre,
    poblacion,
    casos_total,
    tasa_total
  ) %>%
  slice_head(n = 10) %>%
  mutate(Posicion_tasa = row_number())

# Presentar ranking por casos

knitr::kable(
  ranking_casos_731,
  digits = 2,
  caption = "Top 10 de UPZ según número de casos denunciados"
)
Top 10 de UPZ según número de casos denunciados
upz_nombre poblacion casos_total tasa_total Posicion_casos
La Sabana 38856 5441 1400.30 1
Chico Lago 38608 4985 1291.18 2
Las Nieves 17203 4033 2344.36 3
El Rincon 295322 3812 129.08 4
Los Alcazares 44678 3495 782.26 5
Bosa Central 237111 3346 141.12 6
Las Ferias 100848 3139 311.26 7
Galerias 38425 3067 798.18 8
Teusaquillo 28881 2976 1030.44 9
Chapinero 26491 2901 1095.09 10
# Presentar ranking por tasa

knitr::kable(
  ranking_tasas_731,
  digits = 2,
  caption = "Top 10 de UPZ según tasa de delitos por 10.000 habitantes"
)
Top 10 de UPZ según tasa de delitos por 10.000 habitantes
upz_nombre poblacion casos_total tasa_total Posicion_tasa
El Mochuelo 30 34 11333.33 1
Aeropuerto El Dorado 883 545 6172.14 2
Parque Simon Bolivar - Can 3323 958 2882.94 3
Zona Industrial 6666 1573 2359.74 4
Las Nieves 17203 4033 2344.36 5
Parque Salitre 1442 233 1615.81 6
Sagrado Corazon 11247 1707 1517.74 7
La Sabana 38856 5441 1400.30 8
Chico Lago 38608 4985 1291.18 9
Puente Aranda 12482 1561 1250.60 10
# Unir las posiciones de los dos rankings

comparacion_rankings_731 <- full_join(
  ranking_casos_731 %>%
    select(
      upz_nombre,
      Posicion_casos
    ),
  ranking_tasas_731 %>%
    select(
      upz_nombre,
      Posicion_tasa
    ),
  by = "upz_nombre"
) %>%
  mutate(
    Grupo = case_when(
      !is.na(Posicion_casos) & !is.na(Posicion_tasa) ~
        "Aparece en ambos rankings",
      !is.na(Posicion_casos) ~
        "Solo en ranking de casos",
      TRUE ~ "Solo en ranking de tasas"
    )
  )

# Tabla comparativa

knitr::kable(
  comparacion_rankings_731,
  caption = "Comparación de las UPZ que integran los dos rankings"
)
Comparación de las UPZ que integran los dos rankings
upz_nombre Posicion_casos Posicion_tasa Grupo
La Sabana 1 8 Aparece en ambos rankings
Chico Lago 2 9 Aparece en ambos rankings
Las Nieves 3 5 Aparece en ambos rankings
El Rincon 4 NA Solo en ranking de casos
Los Alcazares 5 NA Solo en ranking de casos
Bosa Central 6 NA Solo en ranking de casos
Las Ferias 7 NA Solo en ranking de casos
Galerias 8 NA Solo en ranking de casos
Teusaquillo 9 NA Solo en ranking de casos
Chapinero 10 NA Solo en ranking de casos
El Mochuelo NA 1 Solo en ranking de tasas
Aeropuerto El Dorado NA 2 Solo en ranking de tasas
Parque Simon Bolivar - Can NA 3 Solo en ranking de tasas
Zona Industrial NA 4 Solo en ranking de tasas
Parque Salitre NA 6 Solo en ranking de tasas
Sagrado Corazon NA 7 Solo en ranking de tasas
Puente Aranda NA 10 Solo en ranking de tasas
# Visualización de las posiciones

ggplot(
  comparacion_rankings_731,
  aes(
    x = Posicion_casos,
    y = Posicion_tasa,
    color = Grupo,
    label = upz_nombre
  )
) +
  geom_point(
    size = 3,
    na.rm = TRUE
  ) +
  scale_x_reverse(
    breaks = 1:10,
    limits = c(10, 1)
  ) +
  scale_y_reverse(
    breaks = 1:10,
    limits = c(10, 1)
  ) +
  scale_color_manual(
    values = c(
      "Aparece en ambos rankings" = "#351A4F",
      "Solo en ranking de casos" = "#168C86",
      "Solo en ranking de tasas" = "#D9006C"
    ),
    name = "Participación"
  ) +
  labs(
    title = "Las UPZ con más denuncias no necesariamente lideran las tasas",
    subtitle = "Posición de cada UPZ en los dos rankings",
    x = "Posición en el ranking de casos",
    y = "Posición en el ranking de tasas"
  ) +
  tema_clase

# Relación entre población y número de casos denunciados

ggplot(
  upz,
  aes(
    x = poblacion,
    y = casos_total
  )
) +
  geom_point(
    color = "#168C86",
    alpha = 0.75,
    size = 2.5
  ) +
  geom_smooth(
    method = "lm",
    se = TRUE,
    color = "#D9006C",
    linewidth = 0.8
  ) +
  scale_x_log10(
    labels = scales::label_comma()
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  labs(
    title = "El volumen de denuncias debe interpretarse junto con la población",
    subtitle = "Relación entre habitantes y casos denunciados por UPZ",
    x = "Población de la UPZ (escala logarítmica)",
    y = "Casos denunciados (escala logarítmica)",
    caption = "La línea representa una tendencia lineal ajustada sobre los valores transformados."
  ) +
  tema_clase

Interpretación y conclusión

Insight principal: un mayor número de denuncias no implica necesariamente una mayor tasa de delitos. El ejemplo más representativo es la UPZ asociada al Aeropuerto El Dorado, donde una población residente relativamente baja puede generar una tasa elevada cuando se compara con el número de casos registrados en el territorio.

Este comportamiento plantea una consideración importante: la población residente no siempre representa la totalidad de personas expuestas a las dinámicas de un territorio. En zonas como el aeropuerto existe un flujo importante de personas que transitan diariamente, pero que no necesariamente viven allí. Esta población flotante podría contribuir a explicar por qué los registros de denuncias son elevados en proporción a los habitantes residentes.

Por lo tanto, utilizar exclusivamente el número de casos puede ocultar diferencias en la intensidad relativa de los registros, mientras que interpretar las tasas sin considerar el tamaño y las características de la población puede conducir a conclusiones equivocadas.

En consecuencia, la lectura de la inseguridad territorial debe considerar conjuntamente los casos absolutos, las tasas por habitante y las dinámicas particulares de cada territorio. El caso del Aeropuerto El Dorado evidencia la importancia de considerar factores adicionales, como la población flotante, en futuros análisis.

7.3.2. ¿Cómo influye el tamaño poblacional en la interpretación de las tasas de delitos?

La segunda pregunta busca comprender cómo influye el tamaño de la población residente en la interpretación de las tasas de delitos de las UPZ.

Como se explicó anteriormente, la tasa se calcula relacionando el número de casos denunciados con la población de cada unidad territorial, expresando el resultado por cada 10.000 habitantes. Por lo tanto, cuando el denominador es reducido, una cantidad relativamente pequeña de denuncias puede generar una tasa considerablemente elevada.

Para profundizar en este comportamiento se analiza la distribución de la población, su relación con la tasa total de delitos y las características de las UPZ que presentan poblaciones más pequeñas.

Este análisis también permite reconocer una limitación del indicador: la población residente no necesariamente representa el total de personas que utilizan o transitan por un territorio. En zonas con alta circulación de población flotante, como el Aeropuerto El Dorado, los registros de denuncias pueden estar relacionados con dinámicas que no quedan representadas en el denominador poblacional.

En consecuencia, las tasas deben interpretarse conjuntamente con los casos absolutos, el tamaño poblacional y las características particulares de cada territorio.

# Ordenar las UPZ según su población

upz %>%
  arrange(poblacion) %>%
  mutate(
    upz_nombre = factor(
      upz_nombre,
      levels = upz_nombre
    )
  ) %>%
  ggplot(
    aes(
      x = poblacion,
      y = upz_nombre
    )
  ) +
  geom_col(
    fill = "#168C86",
    alpha = 0.85
  ) +
  scale_x_log10(
    labels = scales::label_comma()
  ) +
  labs(
    title = "La población residente presenta diferencias importantes entre UPZ",
    subtitle = "Distribución de habitantes por unidad territorial",
    x = "Población residente (escala logarítmica)",
    y = NULL
  ) +
  tema_clase +
  theme(
    axis.text.y = element_text(size = 7)
  )

# Identificar el primer cuartil de población

limite_poblacion_baja <- quantile(
  upz$poblacion,
  0.25,
  na.rm = TRUE
)

# Clasificar las UPZ según su tamaño poblacional

upz_analisis_poblacional <- upz %>%
  mutate(
    Grupo_poblacional = if_else(
      poblacion <= limite_poblacion_baja,
      "Población en el cuartil inferior",
      "Resto de las UPZ"
    )
  )

# Construir gráfico de dispersión

ggplot(
  upz_analisis_poblacional,
  aes(
    x = poblacion,
    y = tasa_total,
    color = Grupo_poblacional
  )
) +
  geom_point(
    size = 2.7,
    alpha = 0.8
  ) +
  scale_x_log10(
    labels = scales::label_comma()
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  scale_color_manual(
    values = c(
      "Población en el cuartil inferior" = "#D9006C",
      "Resto de las UPZ" = "#168C86"
    ),
    name = "Tamaño poblacional"
  ) +
  labs(
    title = "Las tasas extremas deben interpretarse considerando la población",
    subtitle = "Relación entre habitantes y tasa total de delitos por UPZ",
    x = "Población residente (escala logarítmica)",
    y = "Tasa por 10.000 habitantes (escala logarítmica)",
    caption = "El grupo poblacional inferior corresponde al 25% de las UPZ con menor población."
  ) +
  tema_clase

# Identificar las 15 UPZ con menor población

tabla_poblacion_baja <- upz %>%
  arrange(poblacion) %>%
  select(
    upz_nombre,
    poblacion,
    casos_total,
    tasa_total
  ) %>%
  slice_head(n = 15)

knitr::kable(
  tabla_poblacion_baja,
  digits = 2,
  caption = "UPZ con menor población y sus respectivos indicadores de delitos"
)
UPZ con menor población y sus respectivos indicadores de delitos
upz_nombre poblacion casos_total tasa_total
El Mochuelo 30 34 11333.33
Aeropuerto El Dorado 883 545 6172.14
Parque Entrenubes 1169 16 136.87
Parque Salitre 1442 233 1615.81
Paseo De Los Libertadores 2690 74 275.09
Guaymaral 2692 45 167.16
Jardin Botanico 2900 266 917.24
Parque Simon Bolivar - Can 3323 958 2882.94
La Academia 5260 123 233.84
Monte Blanco 6575 80 121.67
Zona Industrial 6666 1573 2359.74
Sagrado Corazon 11247 1707 1517.74
Alamos 12077 642 531.59
La Macarena 12253 507 413.78
Puente Aranda 12482 1561 1250.60
# Identificar las 15 UPZ con mayores tasas

tabla_tasas_altas <- upz %>%
  arrange(desc(tasa_total)) %>%
  select(
    upz_nombre,
    poblacion,
    casos_total,
    tasa_total
  ) %>%
  slice_head(n = 15)

knitr::kable(
  tabla_tasas_altas,
  digits = 2,
  caption = "UPZ con mayores tasas de delitos y sus respectivos indicadores"
)
UPZ con mayores tasas de delitos y sus respectivos indicadores
upz_nombre poblacion casos_total tasa_total
El Mochuelo 30 34 11333.33
Aeropuerto El Dorado 883 545 6172.14
Parque Simon Bolivar - Can 3323 958 2882.94
Zona Industrial 6666 1573 2359.74
Las Nieves 17203 4033 2344.36
Parque Salitre 1442 233 1615.81
Sagrado Corazon 11247 1707 1517.74
La Sabana 38856 5441 1400.30
Chico Lago 38608 4985 1291.18
Puente Aranda 12482 1561 1250.60
Chapinero 26491 2901 1095.09
Teusaquillo 28881 2976 1030.44
Jardin Botanico 2900 266 917.24
Galerias 38425 3067 798.18
Los Alcazares 44678 3495 782.26

Interpretación y conclusión

El análisis de la población y las tasas de delitos permite reconocer que el tamaño de la población residente tiene una influencia matemática directa en el valor del indicador. Cuando el denominador es reducido, cada caso adicional representa una proporción mayor y puede generar variaciones importantes en la tasa.

Este comportamiento se evidencia especialmente en las UPZ con poblaciones pequeñas, donde los valores deben interpretarse junto con el número absoluto de denuncias. No sería adecuado asumir que una tasa elevada representa necesariamente una mayor concentración de delitos o un mayor riesgo para sus habitantes.

Adicionalmente, el caso del Aeropuerto El Dorado permite identificar otra limitación: la población residente no siempre representa la cantidad de personas que utilizan un territorio. La circulación de viajeros, trabajadores y visitantes puede generar dinámicas que no quedan reflejadas en el denominador utilizado.

Insight principal: La tasa por habitante es una herramienta útil para comparar territorios, pero su interpretación depende del tamaño y las características de la población utilizada como denominador. En consecuencia, una tasa elevada no debe analizarse de manera aislada: es necesario considerar los casos absolutos, la población residente y las dinámicas particulares de cada UPZ.

7.3.3. ¿Qué diferencias territoriales se observan en la distribución de los delitos denunciados?

Esta pregunta busca identificar si los delitos denunciados presentan diferencias territoriales entre las UPZ de Bogotá y reconocer las zonas donde se concentra un mayor volumen de casos o una mayor intensidad relativa de denuncias.

Para desarrollar este análisis se retoman los mapas temáticos construidos en la sección 6, especialmente la distribución de los casos totales y de las tasas de delitos por cada 10.000 habitantes. Estas representaciones permiten observar los contrastes espaciales y reconocer unidades territoriales con comportamientos diferenciados.

Adicionalmente, se realiza una consolidación de los indicadores por localidad, con el propósito de ampliar la lectura territorial y comparar el volumen de denuncias y las tasas agregadas entre estas unidades geográficas.

Distribución espacial de los casos y las tasas

Los mapas permiten observar que la distribución territorial de los delitos puede presentar diferencias dependiendo del indicador utilizado. Mientras el número de casos muestra la concentración absoluta de las denuncias, la tasa permite comparar su magnitud en relación con la población residente.

La representación por quintiles complementa esta lectura al identificar la posición relativa de cada UPZ frente al conjunto analizado. Por su parte, la escala logarítmica facilita la visualización de las diferencias cuando existen valores extremos.

Comparación territorial de los indicadores por localidad

Para ampliar la interpretación espacial, se agrupan los registros de las UPZ según la localidad a la que pertenecen. Esta consolidación permite comparar el volumen de denuncias y la tasa agregada de delitos entre las diferentes localidades de Bogotá.

La tasa por localidad se calcula relacionando la suma de los casos registrados en sus UPZ con la población total correspondiente. De esta manera, se obtiene un indicador ponderado por población, evitando calcular el promedio simple de las tasas individuales de las UPZ.

Esta comparación permite identificar diferencias territoriales a una escala más amplia, aunque debe considerarse que la agregación por localidad puede ocultar contrastes existentes entre las UPZ que la conforman.

# Consolidar los indicadores por localidad

resumen_localidades <- upz %>%
  group_by(localidad) %>%
  summarise(
    Numero_UPZ = n(),
    Poblacion_total = sum(poblacion, na.rm = TRUE),
    Casos_total = sum(casos_total, na.rm = TRUE),
    Tasa_agregada = (
      sum(casos_total, na.rm = TRUE) /
      sum(poblacion, na.rm = TRUE)
    ) * 10000,
    .groups = "drop"
  )

# Ranking por volumen de denuncias

ranking_localidades_casos <- resumen_localidades %>%
  arrange(desc(Casos_total))

knitr::kable(
  ranking_localidades_casos,
  digits = 2,
  caption = "Indicadores de delitos denunciados por localidad"
)
Indicadores de delitos denunciados por localidad
localidad Numero_UPZ Poblacion_total Casos_total Tasa_agregada
Suba 12 1290144 19028 147.49
Kennedy 12 1035224 18517 178.87
Engativá 9 817019 16715 204.59
Teusaquillo 6 166428 9978 599.54
Chapinero 5 178317 9754 547.00
Fontibón 8 404252 9593 237.30
Usaquén 9 586346 9078 154.82
Ciudad Bolívar 8 650967 9052 139.05
Puente Aranda 5 256731 8562 333.50
Bosa 5 729781 8120 111.27
Santa Fe 5 106587 7705 722.88
Barrios Unidos 4 153342 7334 478.28
Los Mártires 2 82848 6643 801.83
Rafael Uribe Uribe 5 389238 6438 165.40
San Cristóbal 5 406428 4723 116.21
Usme 7 397603 4347 109.33
Antonio Nariño 2 83925 3429 408.58
Tunjuelito 2 182943 2448 133.81
Candelaria 1 18409 1371 744.74
# Gráfico de casos totales por localidad

ggplot(
  resumen_localidades,
  aes(
    x = reorder(localidad, Casos_total),
    y = Casos_total
  )
) +
  geom_col(
    fill = "#351A4F",
    alpha = 0.9
  ) +
  coord_flip() +
  scale_y_continuous(
    labels = scales::label_comma()
  ) +
  labs(
    title = "Concentración de denuncias por localidad",
    subtitle = "Número total de casos registrados",
    x = NULL,
    y = "Casos denunciados"
  ) +
  tema_clase

# Gráfico de tasas agregadas por localidad

ggplot(
  resumen_localidades,
  aes(
    x = reorder(localidad, Tasa_agregada),
    y = Tasa_agregada
  )
) +
  geom_col(
    fill = "#D9006C",
    alpha = 0.9
  ) +
  coord_flip() +
  scale_y_continuous(
    labels = scales::label_comma(accuracy = 0.1)
  ) +
  labs(
    title = "Intensidad relativa de las denuncias por localidad",
    subtitle = "Tasa agregada por cada 10.000 habitantes",
    x = NULL,
    y = "Tasa por 10.000 habitantes"
  ) +
  tema_clase

Interpretación y conclusión

La representación geográfica permite reconocer diferencias territoriales en la distribución de las denuncias registradas. Al comparar los casos absolutos con las tasas, se evidencia la importancia de utilizar ambos indicadores para comprender el comportamiento de los registros en las diferentes unidades territoriales.

La consolidación por localidad permite ampliar la lectura territorial, pero también puede ocultar diferencias entre las UPZ que conforman cada localidad. Por esta razón, resulta importante conservar el análisis a escala de UPZ y utilizar la localidad como un nivel complementario de interpretación.

Insight principal: La inseguridad registrada en Bogotá no presenta una única lectura territorial. La identificación de las zonas con mayor concentración de denuncias puede ser diferente de la identificación de aquellas con mayores tasas relativas. Por ello, la escala geográfica y el indicador utilizado condicionan la interpretación de los resultados.

7.3.4. ¿Existe alguna asociación entre el alumbrado público y las tasas de delitos?

Esta pregunta busca explorar si la disponibilidad y las características del alumbrado público presentan alguna asociación con las tasas de delitos denunciados en las UPZ de Bogotá.

Para desarrollar el análisis se consideran tres indicadores: la cantidad de luminarias por kilómetro cuadrado, la cantidad de luminarias por cada 1.000 habitantes y el porcentaje de luminarias con tecnología LED.

La utilización de estas variables permite analizar el alumbrado desde diferentes dimensiones, considerando tanto su distribución territorial como su disponibilidad relativa frente a la población y su composición tecnológica.

Se comparan estos indicadores con la tasa total de delitos por cada 10.000 habitantes, mediante gráficos de dispersión y correlaciones de Spearman. El propósito es identificar posibles patrones y diferencias entre las unidades territoriales.

ggplot(
  upz,
  aes(
    x = luminarias_km2,
    y = tasa_total
  )
) +
  geom_point(
    color = "#168C86",
    alpha = 0.75,
    size = 2.5
  ) +
  scale_x_log10(
    labels = scales::label_comma()
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  labs(
    title = "Disponibilidad espacial de alumbrado y tasa de delitos",
    subtitle = "Luminarias por km² frente a denuncias por cada 10.000 habitantes",
    x = "Luminarias por km² (escala logarítmica)",
    y = "Tasa de delitos (escala logarítmica)"
  ) +
  tema_clase

ggplot(
  upz,
  aes(
    x = luminarias_1000hab,
    y = tasa_total
  )
) +
  geom_point(
    color = "#D9006C",
    alpha = 0.75,
    size = 2.5
  ) +
  scale_x_log10(
    labels = scales::label_comma()
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  labs(
    title = "Alumbrado por habitante y tasa de delitos",
    subtitle = "Disponibilidad de luminarias por cada 1.000 habitantes",
    x = "Luminarias por cada 1.000 habitantes (escala logarítmica)",
    y = "Tasa de delitos (escala logarítmica)"
  ) +
  tema_clase

ggplot(
  upz,
  aes(
    x = pct_luminarias_led,
    y = tasa_total
  )
) +
  geom_point(
    color = "#351A4F",
    alpha = 0.75,
    size = 2.5
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  labs(
    title = "Participación de luminarias LED y tasa de delitos",
    subtitle = "Porcentaje de luminarias LED por UPZ",
    x = "Luminarias LED (%)",
    y = "Tasa de delitos (escala logarítmica)"
  ) +
  tema_clase

Para complementar la exploración visual, se calculan las correlaciones de Spearman entre los tres indicadores de alumbrado público y la tasa total de delitos.

Esta comparación permite identificar la dirección y la intensidad de las asociaciones monotónicas entre las variables, facilitando una lectura conjunta de las diferentes dimensiones de la infraestructura de iluminación.

variables_alumbrado <- c(
  "luminarias_km2",
  "luminarias_1000hab",
  "pct_luminarias_led"
)

correlaciones_alumbrado <- purrr::map_dfr(
  variables_alumbrado,
  function(variable) {

    datos_validos <- upz %>%
      select(
        tasa_total,
        all_of(variable)
      ) %>%
      drop_na()

    tibble(
      Indicador = variable,
      Numero_UPZ = nrow(datos_validos),
      rho = cor(
        datos_validos$tasa_total,
        datos_validos[[variable]],
        method = "spearman"
      )
    )
  }
) %>%
  mutate(
    Indicador = recode(
      Indicador,
      luminarias_km2 = "Luminarias por km²",
      luminarias_1000hab = "Luminarias por 1.000 habitantes",
      pct_luminarias_led = "Porcentaje de luminarias LED"
    ),
    Direccion = if_else(
      rho >= 0,
      "Positiva",
      "Negativa"
    ),
    Intensidad = case_when(
      abs(rho) < 0.20 ~ "Muy débil",
      abs(rho) < 0.40 ~ "Débil",
      abs(rho) < 0.60 ~ "Moderada",
      abs(rho) < 0.80 ~ "Fuerte",
      TRUE ~ "Muy fuerte"
    )
  ) %>%
  arrange(desc(abs(rho)))

knitr::kable(
  correlaciones_alumbrado,
  digits = 3,
  caption = "Correlaciones de Spearman entre alumbrado público y tasa de delitos"
)
Correlaciones de Spearman entre alumbrado público y tasa de delitos
Indicador Numero_UPZ rho Direccion Intensidad
Luminarias por 1.000 habitantes 112 0.775 Positiva Fuerte
Luminarias por km² 112 0.119 Positiva Muy débil
Porcentaje de luminarias LED 112 -0.061 Negativa Muy débil

Interpretación y conclusión

Al comparar los indicadores de alumbrado público con las tasas de delitos, no se identifica una relación visual negativa clara que permita afirmar que una mayor disponibilidad de luminarias esté asociada con menores tasas de denuncias.

En el gráfico de luminarias por kilómetro cuadrado se observa una concentración importante de UPZ en niveles relativamente altos de disponibilidad espacial de alumbrado, mientras que las tasas de delitos presentan una dispersión considerable. Esto indica que una mayor cantidad de luminarias por superficie no se traduce necesariamente en una menor tasa de delitos.

Por otra parte, en el gráfico de luminarias por cada 1.000 habitantes se aprecia una posible tendencia positiva, donde algunas UPZ con mayor disponibilidad relativa de luminarias también presentan tasas elevadas. Sin embargo, este comportamiento debe interpretarse con precaución, debido a la presencia de valores extremos y a que el indicador puede amplificarse en territorios con poblaciones residentes reducidas.

Un aspecto interesante es que la relación observada también podría plantear una hipótesis de respuesta institucional: los territorios que presentan mayores dinámicas de actividad, circulación de personas o problemáticas de seguridad podrían recibir una mayor dotación de infraestructura de iluminación. No obstante, la información disponible no permite comprobar esta hipótesis ni establecer si la infraestructura precede o responde a las condiciones de seguridad.

Insight principal: Una mayor disponibilidad de alumbrado público no implica directamente menores tasas de delitos. Los resultados muestran que la relación entre iluminación y seguridad es más compleja de lo que podría suponerse inicialmente. Incluso, la posible asociación positiva entre luminarias por habitante y tasas de delitos plantea la necesidad de estudiar si la infraestructura responde a las características y necesidades de cada territorio, en lugar de interpretar la iluminación como un factor que por sí solo determina los niveles de seguridad.

7.3.5. ¿Qué relación existe entre las condiciones socioeconómicas y los delitos denunciados?

Esta pregunta busca explorar si las diferencias socioeconómicas entre las UPZ presentan alguna asociación con los indicadores de delitos denunciados.

Para desarrollar el análisis se consideran tres dimensiones: el porcentaje de población en condición de pobreza, el salario mensual promedio y la composición de las viviendas según rangos de estrato socioeconómico.

En primer lugar, se examina la relación entre estas variables y la tasa total de delitos por cada 10.000 habitantes. Posteriormente, se explora si el tipo de delito predominante presenta diferencias entre territorios con distintas características socioeconómicas.

Este análisis permite ampliar la interpretación de la inseguridad territorial, considerando que las UPZ presentan condiciones de vida y estructuras socioeconómicas diferentes.

ggplot(
  upz,
  aes(
    x = pct_pobreza,
    y = tasa_total,
    color = em_agrupada
  )
) +
  geom_point(
    alpha = 0.75,
    size = 2.5
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = "#168C86",
      "TRUE" = "#D9006C"
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    ),
    name = "Tipo de estimación"
  ) +
  labs(
    title = "Pobreza y tasa de delitos por UPZ",
    subtitle = "Comparación entre condiciones socioeconómicas y denuncias",
    x = "Población en condición de pobreza (%)",
    y = "Tasa de delitos por 10.000 habitantes (escala logarítmica)"
  ) +
  tema_clase

ggplot(
  upz,
  aes(
    x = salario_promedio,
    y = tasa_total,
    color = em_agrupada
  )
) +
  geom_point(
    alpha = 0.75,
    size = 2.5
  ) +
  scale_x_log10(
    labels = scales::label_comma(prefix = "$")
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = "#168C86",
      "TRUE" = "#D9006C"
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    ),
    name = "Tipo de estimación"
  ) +
  labs(
    title = "Salario promedio y tasa de delitos por UPZ",
    subtitle = "Relación entre ingreso promedio y denuncias registradas",
    x = "Salario mensual promedio (escala logarítmica)",
    y = "Tasa de delitos por 10.000 habitantes (escala logarítmica)"
  ) +
  tema_clase

# Transformar la composición por estrato a formato largo

datos_estratos <- upz %>%
  select(
    upz_nombre,
    tasa_total,
    pct_estrato_1_2,
    pct_estrato_3_4,
    pct_estrato_5_6
  ) %>%
  pivot_longer(
    cols = starts_with("pct_estrato"),
    names_to = "Estrato",
    values_to = "Porcentaje"
  ) %>%
  mutate(
    Estrato = recode(
      Estrato,
      pct_estrato_1_2 = "Estratos 1 y 2",
      pct_estrato_3_4 = "Estratos 3 y 4",
      pct_estrato_5_6 = "Estratos 5 y 6"
    )
  )

# Comparar composición socioeconómica y tasa de delitos

ggplot(
  datos_estratos,
  aes(
    x = Porcentaje,
    y = tasa_total
  )
) +
  geom_point(
    color = "#168C86",
    alpha = 0.65,
    size = 2
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  facet_wrap(
    ~ Estrato,
    ncol = 1,
    scales = "free_x"
  ) +
  labs(
    title = "Composición por estrato y tasa de delitos",
    subtitle = "Participación porcentual de viviendas por rango de estrato",
    x = "Viviendas del rango de estrato (%)",
    y = "Tasa de delitos por 10.000 habitantes (escala logarítmica)"
  ) +
  tema_clase

variables_socioeconomicas <- c(
  "pct_pobreza",
  "salario_promedio",
  "pct_estrato_1_2",
  "pct_estrato_3_4",
  "pct_estrato_5_6"
)

correlaciones_socioeconomicas <- purrr::map_dfr(
  variables_socioeconomicas,
  function(variable) {

    datos_validos <- upz %>%
      select(
        tasa_total,
        all_of(variable)
      ) %>%
      drop_na()

    tibble(
      Variable = variable,
      Numero_UPZ = nrow(datos_validos),
      rho = cor(
        datos_validos$tasa_total,
        datos_validos[[variable]],
        method = "spearman"
      )
    )
  }
) %>%
  mutate(
    Variable = recode(
      Variable,
      pct_pobreza = "Población en condición de pobreza",
      salario_promedio = "Salario promedio",
      pct_estrato_1_2 = "Viviendas en estratos 1 y 2",
      pct_estrato_3_4 = "Viviendas en estratos 3 y 4",
      pct_estrato_5_6 = "Viviendas en estratos 5 y 6"
    ),
    Direccion = if_else(
      rho >= 0,
      "Positiva",
      "Negativa"
    ),
    Intensidad = case_when(
      abs(rho) < 0.20 ~ "Muy débil",
      abs(rho) < 0.40 ~ "Débil",
      abs(rho) < 0.60 ~ "Moderada",
      abs(rho) < 0.80 ~ "Fuerte",
      TRUE ~ "Muy fuerte"
    )
  ) %>%
  arrange(desc(abs(rho)))

knitr::kable(
  correlaciones_socioeconomicas,
  digits = 3,
  caption = "Correlaciones de Spearman entre condiciones socioeconómicas y tasa de delitos"
)
Correlaciones de Spearman entre condiciones socioeconómicas y tasa de delitos
Variable Numero_UPZ rho Direccion Intensidad
Viviendas en estratos 1 y 2 112 -0.623 Negativa Fuerte
Viviendas en estratos 3 y 4 112 0.616 Positiva Fuerte
Salario promedio 112 0.584 Positiva Moderada
Población en condición de pobreza 112 -0.517 Negativa Moderada
Viviendas en estratos 5 y 6 112 0.205 Positiva Débil

Diferencias en los tipos de delitos según el salario promedio

Además de examinar la relación entre las condiciones socioeconómicas y la tasa total, se explora si el comportamiento de los distintos tipos de delitos presenta diferencias entre UPZ con niveles de salario promedio relativamente bajos y altos.

Para ello, las unidades territoriales se clasifican utilizando la mediana del salario promedio y se comparan las tasas específicas de los diez tipos de delitos incluidos en la base.

Este procedimiento permite identificar qué categorías presentan mayores tasas relativas dentro de cada grupo socioeconómico. La clasificación representa una comparación exploratoria entre territorios y no implica que el nivel de ingreso determine el tipo de delito predominante.

# Definir las tasas específicas de los delitos

variables_tasas_delitos <- c(
  "tasa_homicidios",
  "tasa_lesiones",
  "tasa_hurto_personas",
  "tasa_hurto_residencias",
  "tasa_hurto_automotor",
  "tasa_hurto_bicicletas",
  "tasa_hurto_comercio",
  "tasa_hurto_celulares",
  "tasa_hurto_motos",
  "tasa_violencia_intrafamiliar"
)

# Clasificar las UPZ según la mediana del salario

mediana_salario <- median(
  upz$salario_promedio,
  na.rm = TRUE
)

upz_grupos_salario <- upz %>%
  mutate(
    Grupo_salario = if_else(
      salario_promedio <= mediana_salario,
      "Salario bajo o igual a mediana",
      "Salario superior a mediana"
    )
  )

# Convertir las tasas específicas a formato largo

delitos_por_salario <- upz_grupos_salario %>%
  select(
    upz_nombre,
    Grupo_salario,
    all_of(variables_tasas_delitos)
  ) %>%
  pivot_longer(
    cols = all_of(variables_tasas_delitos),
    names_to = "Tipo_delito",
    values_to = "Tasa"
  ) %>%
  mutate(
    Tipo_delito = recode(
      Tipo_delito,
      tasa_homicidios = "Homicidios",
      tasa_lesiones = "Lesiones",
      tasa_hurto_personas = "Hurto a personas",
      tasa_hurto_residencias = "Hurto a residencias",
      tasa_hurto_automotor = "Hurto de automotores",
      tasa_hurto_bicicletas = "Hurto de bicicletas",
      tasa_hurto_comercio = "Hurto a comercio",
      tasa_hurto_celulares = "Hurto de celulares",
      tasa_hurto_motos = "Hurto de motos",
      tasa_violencia_intrafamiliar = "Violencia intrafamiliar"
    )
  )

# Calcular la mediana de cada tipo de delito por grupo salarial

resumen_delitos_salario <- delitos_por_salario %>%
  group_by(
    Grupo_salario,
    Tipo_delito
  ) %>%
  summarise(
    Tasa_mediana = median(Tasa, na.rm = TRUE),
    Numero_UPZ = sum(!is.na(Tasa)),
    .groups = "drop"
  ) %>%
  group_by(Grupo_salario) %>%
  mutate(
    Posicion = min_rank(desc(Tasa_mediana))
  ) %>%
  ungroup()

# Presentar ranking de tipos de delitos por grupo

knitr::kable(
  resumen_delitos_salario %>%
    arrange(Grupo_salario, Posicion),
  digits = 3,
  caption = "Tasas medianas por tipo de delito según grupo salarial"
)
Tasas medianas por tipo de delito según grupo salarial
Grupo_salario Tipo_delito Tasa_mediana Numero_UPZ Posicion
Salario bajo o igual a mediana Hurto a personas 56.710 56 1
Salario bajo o igual a mediana Violencia intrafamiliar 22.010 56 2
Salario bajo o igual a mediana Hurto de celulares 19.525 56 3
Salario bajo o igual a mediana Lesiones 12.595 56 4
Salario bajo o igual a mediana Hurto a comercio 4.285 56 5
Salario bajo o igual a mediana Hurto a residencias 4.160 56 6
Salario bajo o igual a mediana Hurto de motos 3.905 56 7
Salario bajo o igual a mediana Hurto de bicicletas 3.240 56 8
Salario bajo o igual a mediana Hurto de automotores 2.405 56 9
Salario bajo o igual a mediana Homicidios 0.765 56 10
Salario superior a mediana Hurto a personas 161.240 56 1
Salario superior a mediana Hurto de celulares 59.815 56 2
Salario superior a mediana Violencia intrafamiliar 13.300 56 3
Salario superior a mediana Hurto a comercio 11.470 56 4
Salario superior a mediana Lesiones 9.505 56 5
Salario superior a mediana Hurto a residencias 7.930 56 6
Salario superior a mediana Hurto de bicicletas 7.485 56 7
Salario superior a mediana Hurto de automotores 2.610 56 8
Salario superior a mediana Hurto de motos 2.445 56 9
Salario superior a mediana Homicidios 0.240 56 10
# Comparación visual

ggplot(
  resumen_delitos_salario,
  aes(
    x = reorder(Tipo_delito, Tasa_mediana),
    y = Tasa_mediana,
    fill = Grupo_salario
  )
) +
  geom_col(
    position = "dodge"
  ) +
  coord_flip() +
  scale_fill_manual(
    values = c(
      "Salario bajo o igual a mediana" = "#168C86",
      "Salario superior a mediana" = "#D9006C"
    ),
    name = "Grupo socioeconómico"
  ) +
  labs(
    title = "Comportamiento de los delitos según grupo salarial",
    subtitle = "Comparación de las tasas medianas por tipo de delito",
    x = NULL,
    y = "Tasa mediana por cada 10.000 habitantes"
  ) +
  tema_clase

Interpretación y conclusión

Los resultados obtenidos muestran un comportamiento interesante entre las condiciones socioeconómicas y las tasas de delitos denunciados. Se observa una tendencia en la que las UPZ con menores porcentajes de población en condición de pobreza presentan mayores tasas de delitos. De manera similar, las unidades territoriales con mayores salarios promedio también muestran tasas más elevadas.

Este comportamiento permite cuestionar la idea de que las condiciones socioeconómicas más favorables necesariamente se relacionan con menores niveles de inseguridad. Por el contrario, los resultados sugieren que los territorios con mayores ingresos pueden presentar una mayor intensidad de denuncias por habitante.

Una posible explicación está relacionada con la capacidad adquisitiva y las dinámicas económicas de estos territorios, que podrían influir en la exposición a determinados delitos, especialmente aquellos relacionados con el hurto. También es posible que existan diferencias en la disposición o capacidad de los habitantes para denunciar los hechos. Sin embargo, estas explicaciones constituyen hipótesis que no pueden comprobarse directamente con las variables disponibles.

Al profundizar en los tipos de delitos, se identifica que el hurto a personas y el hurto de celulares concentran los mayores registros numéricos dentro de las categorías analizadas. No obstante, al comparar las tasas medianas por tipo de delito entre los grupos de UPZ clasificados según su salario promedio, aparece un resultado particular: la violencia intrafamiliar y lesiones son los únicos delitos cuya tasa mediana es superior en el grupo de territorios con salarios por debajo de la mediana.

Este resultado resulta especialmente relevante porque muestra que las diferencias socioeconómicas no necesariamente se manifiestan de la misma manera en todas las categorías delictivas. Mientras los hurtos representan una parte importante de los registros, la violencia intrafamiliar presenta un comportamiento diferenciado que merece una lectura independiente.

Insight principal: Las UPZ con mejores condiciones económicas no necesariamente presentan menores tasas de delitos denunciados. En los resultados analizados, las mayores tasas se observan en territorios con menores porcentajes de pobreza y mayores salarios promedio. Además, el comportamiento de la violencia intrafamiliar rompe el patrón general de comparación por ingresos, al presentar una tasa mediana superior en las UPZ del grupo salarial más alto.

En conjunto, estos resultados sugieren que la relación entre condiciones socioeconómicas e inseguridad es multidimensional. El nivel de ingresos, la pobreza y la composición de los delitos aportan perspectivas diferentes para comprender las dinámicas territoriales, por lo que no sería adecuado utilizar una sola variable socioeconómica para explicar el comportamiento de la inseguridad.

7.3.6. ¿La percepción de inseguridad coincide con los delitos denunciados?

Esta pregunta busca establecer si las UPZ donde se perciben mayores problemas de inseguridad son también aquellas que presentan mayores tasas de delitos denunciados.

Para desarrollar el análisis se comparan dos dimensiones: la percepción de inseguridad reportada por los habitantes y los registros administrativos de denuncias. La primera representa la valoración que las personas hacen sobre las condiciones de seguridad en el entorno de su vivienda, mientras que la segunda refleja los casos registrados por las autoridades.

Se analiza la relación entre el porcentaje de percepción de inseguridad y la tasa total de delitos por cada 10.000 habitantes. Adicionalmente, se incorpora el número absoluto de denuncias para identificar posibles diferencias entre la percepción, la concentración de casos y la intensidad relativa de los registros.

El propósito es reconocer si ambas dimensiones presentan comportamientos similares o si existen territorios donde la percepción de inseguridad no coincide con los indicadores de denuncias.

Es importante señalar que percepción y denuncia no miden exactamente el mismo fenómeno. Una persona puede percibir inseguridad sin haber sido víctima de un delito, y no todos los hechos delictivos son denunciados. Por lo tanto, las diferencias entre ambos indicadores no deben interpretarse automáticamente como errores de percepción o de registro.

ggplot(
  upz,
  aes(
    x = pct_percibe_inseguridad,
    y = tasa_total,
    color = em_agrupada
  )
) +
  geom_point(
    alpha = 0.75,
    size = 2.5
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = "#168C86",
      "TRUE" = "#D9006C"
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    ),
    name = "Tipo de estimación"
  ) +
  labs(
    title = "La percepción de inseguridad no necesariamente coincide con las tasas de delitos",
    subtitle = "Percepción reportada frente a denuncias por cada 10.000 habitantes",
    x = "Población que percibe problemas de inseguridad (%)",
    y = "Tasa total de delitos (escala logarítmica)"
  ) +
  tema_clase

ggplot(
  upz,
  aes(
    x = pct_percibe_inseguridad,
    y = casos_total,
    color = em_agrupada
  )
) +
  geom_point(
    alpha = 0.75,
    size = 2.5
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  scale_color_manual(
    values = c(
      "FALSE" = "#168C86",
      "TRUE" = "#D9006C"
    ),
    labels = c(
      "FALSE" = "Estimación individual",
      "TRUE" = "Estimación agrupada"
    ),
    name = "Tipo de estimación"
  ) +
  labs(
    title = "Percepción de inseguridad y volumen de denuncias",
    subtitle = "Comparación entre percepción y número de casos por UPZ",
    x = "Población que percibe problemas de inseguridad (%)",
    y = "Número de denuncias (escala logarítmica)"
  ) +
  tema_clase

variables_percepcion <- c(
  "tasa_total",
  "casos_total",
  "poblacion"
)

correlaciones_percepcion <- purrr::map_dfr(
  variables_percepcion,
  function(variable) {

    datos_validos <- upz %>%
      select(
        pct_percibe_inseguridad,
        all_of(variable)
      ) %>%
      drop_na()

    tibble(
      Variable = variable,
      Numero_UPZ = nrow(datos_validos),
      rho = cor(
        datos_validos$pct_percibe_inseguridad,
        datos_validos[[variable]],
        method = "spearman"
      )
    )
  }
) %>%
  mutate(
    Variable = recode(
      Variable,
      tasa_total = "Tasa total de delitos",
      casos_total = "Número de casos denunciados",
      poblacion = "Población residente"
    ),
    Direccion = if_else(
      rho >= 0,
      "Positiva",
      "Negativa"
    ),
    Intensidad = case_when(
      abs(rho) < 0.20 ~ "Muy débil",
      abs(rho) < 0.40 ~ "Débil",
      abs(rho) < 0.60 ~ "Moderada",
      abs(rho) < 0.80 ~ "Fuerte",
      TRUE ~ "Muy fuerte"
    )
  )

knitr::kable(
  correlaciones_percepcion,
  digits = 3,
  caption = "Correlaciones de Spearman entre percepción de inseguridad y variables de delitos"
)
Correlaciones de Spearman entre percepción de inseguridad y variables de delitos
Variable Numero_UPZ rho Direccion Intensidad
Tasa total de delitos 112 -0.293 Negativa Débil
Número de casos denunciados 112 0.063 Positiva Muy débil
Población residente 112 0.289 Positiva Débil
# Calcular medianas de referencia

mediana_percepcion <- median(
  upz$pct_percibe_inseguridad,
  na.rm = TRUE
)

mediana_tasa <- median(
  upz$tasa_total,
  na.rm = TRUE
)

# Clasificar las UPZ según percepción y tasa

upz_percepcion_grupos <- upz %>%
  mutate(
    Grupo_percepcion_tasa = case_when(
      pct_percibe_inseguridad >= mediana_percepcion &
        tasa_total >= mediana_tasa ~ "Percepción alta - Tasa alta",

      pct_percibe_inseguridad >= mediana_percepcion &
        tasa_total < mediana_tasa ~ "Percepción alta - Tasa baja",

      pct_percibe_inseguridad < mediana_percepcion &
        tasa_total >= mediana_tasa ~ "Percepción baja - Tasa alta",

      TRUE ~ "Percepción baja - Tasa baja"
    )
  )

# Resumen de UPZ por grupo

resumen_percepcion_grupos <- upz_percepcion_grupos %>%
  group_by(Grupo_percepcion_tasa) %>%
  summarise(
    Numero_UPZ = n(),
    Percepcion_mediana = median(
      pct_percibe_inseguridad,
      na.rm = TRUE
    ),
    Tasa_mediana = median(
      tasa_total,
      na.rm = TRUE
    ),
    Casos_mediana = median(
      casos_total,
      na.rm = TRUE
    ),
    .groups = "drop"
  )

knitr::kable(
  resumen_percepcion_grupos,
  digits = 2,
  caption = "Clasificación territorial según percepción y tasa de delitos"
)
Clasificación territorial según percepción y tasa de delitos
Grupo_percepcion_tasa Numero_UPZ Percepcion_mediana Tasa_mediana Casos_mediana
Percepción alta - Tasa alta 24 73.10 274.20 1567.0
Percepción alta - Tasa baja 32 76.83 120.78 1181.0
Percepción baja - Tasa alta 32 40.88 299.56 1317.5
Percepción baja - Tasa baja 24 47.37 148.51 921.5
# Identificar las UPZ de cada grupo

tabla_upz_percepcion <- upz_percepcion_grupos %>%
  select(
    upz_nombre,
    poblacion,
    casos_total,
    tasa_total,
    pct_percibe_inseguridad,
    Grupo_percepcion_tasa
  ) %>%
  arrange(Grupo_percepcion_tasa)

knitr::kable(
  tabla_upz_percepcion,
  digits = 2,
  caption = "UPZ clasificadas según percepción de inseguridad y tasa de delitos"
)
UPZ clasificadas según percepción de inseguridad y tasa de delitos
upz_nombre poblacion casos_total tasa_total pct_percibe_inseguridad Grupo_percepcion_tasa
Doce De Octubre 75666 2031 268.42 65.97 Percepción alta - Tasa alta
Las Ferias 100848 3139 311.26 72.92 Percepción alta - Tasa alta
Boyaca Real 128214 2794 217.92 74.08 Percepción alta - Tasa alta
Santa Cecilia 67416 1855 275.16 76.48 Percepción alta - Tasa alta
Sosiego 44546 975 218.87 70.31 Percepción alta - Tasa alta
Santa Isabel 43992 1202 273.23 69.99 Percepción alta - Tasa alta
Restrepo 56948 2690 472.36 73.27 Percepción alta - Tasa alta
Quiroga 93328 2448 262.30 70.92 Percepción alta - Tasa alta
Ciudad Montes 103350 2191 212.00 68.00 Percepción alta - Tasa alta
Muzu 60006 1561 260.14 79.06 Percepción alta - Tasa alta
San Rafael 74227 1676 225.79 70.62 Percepción alta - Tasa alta
Carvajal 88914 1958 220.21 82.88 Percepción alta - Tasa alta
Marco Fidel Suarez 47615 927 194.69 73.41 Percepción alta - Tasa alta
El Mochuelo 30 34 11333.33 86.83 Percepción alta - Tasa alta
Fontibon San Pablo 35141 902 256.68 69.94 Percepción alta - Tasa alta
Corabastos 56102 1103 196.61 92.11 Percepción alta - Tasa alta
Las Cruces 20786 888 427.21 85.97 Percepción alta - Tasa alta
Los Alcazares 44678 3495 782.26 69.78 Percepción alta - Tasa alta
La Sabana 38856 5441 1400.30 83.45 Percepción alta - Tasa alta
Parque Salitre 1442 233 1615.81 65.97 Percepción alta - Tasa alta
Jardin Botanico 2900 266 917.24 76.48 Percepción alta - Tasa alta
Zona Industrial 6666 1573 2359.74 66.27 Percepción alta - Tasa alta
Puente Aranda 12482 1561 1250.60 66.27 Percepción alta - Tasa alta
Alamos 12077 642 531.59 76.89 Percepción alta - Tasa alta
El Rincon 295322 3812 129.08 78.63 Percepción alta - Tasa baja
San Blas 105092 955 90.87 74.26 Percepción alta - Tasa baja
20 De Julio 81050 1165 143.74 82.64 Percepción alta - Tasa baja
Venecia 141537 1835 129.65 81.09 Percepción alta - Tasa baja
Timiza 139473 1604 115.00 66.20 Percepción alta - Tasa baja
Apogeo 36013 451 125.23 69.38 Percepción alta - Tasa baja
La Gloria 96862 918 94.77 86.04 Percepción alta - Tasa baja
La Flora 20151 189 93.79 76.97 Percepción alta - Tasa baja
Marruecos 123085 1229 99.85 76.68 Percepción alta - Tasa baja
Diana Turbay 76093 804 105.66 79.62 Percepción alta - Tasa baja
Gran Yomasa 134412 1477 109.89 82.71 Percepción alta - Tasa baja
Comuneros 101345 1215 119.89 81.41 Percepción alta - Tasa baja
Alfonso Lopez 53774 455 84.61 70.34 Percepción alta - Tasa baja
Ciudad Usme 28258 356 125.98 70.34 Percepción alta - Tasa baja
Tunjuelito 41406 613 148.05 91.82 Percepción alta - Tasa baja
Monte Blanco 6575 80 121.67 86.83 Percepción alta - Tasa baja
San Francisco 72057 1244 172.64 70.00 Percepción alta - Tasa baja
Lucero 163588 2661 162.66 77.15 Percepción alta - Tasa baja
El Tesoro 54369 721 132.61 86.83 Percepción alta - Tasa baja
Ismael Perdomo 166602 1863 111.82 70.91 Percepción alta - Tasa baja
Jerusalem 102981 1061 103.03 83.17 Percepción alta - Tasa baja
Tibabuyes 305907 2669 87.25 72.98 Percepción alta - Tasa baja
Garces Navas 168657 2684 159.14 70.18 Percepción alta - Tasa baja
Engativa 142612 1702 119.34 74.63 Percepción alta - Tasa baja
Gran Britalia 62139 1151 185.23 70.70 Percepción alta - Tasa baja
Patio Bonito 137776 2544 184.65 86.07 Percepción alta - Tasa baja
Las Margaritas 32008 471 147.15 72.10 Percepción alta - Tasa baja
Bosa Occidental 199365 2272 113.96 74.30 Percepción alta - Tasa baja
Bosa Central 237111 3346 141.12 89.69 Percepción alta - Tasa baja
El Porvenir 143758 1197 83.26 74.01 Percepción alta - Tasa baja
Tintal Sur 113534 854 75.22 74.43 Percepción alta - Tasa baja
Lourdes 45098 570 126.39 81.16 Percepción alta - Tasa baja
Paseo De Los Libertadores 2690 74 275.09 36.18 Percepción baja - Tasa alta
La Academia 5260 123 233.84 40.88 Percepción baja - Tasa alta
Usaquen 43160 1298 300.74 24.45 Percepción baja - Tasa alta
Santa Barbara 74375 1972 265.14 40.67 Percepción baja - Tasa alta
San Jose De Bavaria 52099 1337 256.63 40.88 Percepción baja - Tasa alta
El Prado 106920 2267 212.03 48.84 Percepción baja - Tasa alta
La Alhambra 43531 1343 308.52 34.17 Percepción baja - Tasa alta
Los Andes 31556 1575 499.11 37.36 Percepción baja - Tasa alta
Minuto De Dios 110520 2183 197.52 62.71 Percepción baja - Tasa alta
Ciudad Jardin 26977 739 273.94 62.16 Percepción baja - Tasa alta
San Jose 49117 1030 209.70 65.36 Percepción baja - Tasa alta
Americas 78380 2449 312.45 63.34 Percepción baja - Tasa alta
Kennedy Central 92968 1856 199.64 65.96 Percepción baja - Tasa alta
El Refugio 41543 853 205.33 21.48 Percepción baja - Tasa alta
Sagrado Corazon 11247 1707 1517.74 59.85 Percepción baja - Tasa alta
La Macarena 12253 507 413.78 44.82 Percepción baja - Tasa alta
Las Nieves 17203 4033 2344.36 59.85 Percepción baja - Tasa alta
La Candelaria 18409 1371 744.74 64.66 Percepción baja - Tasa alta
Chico Lago 38608 4985 1291.18 21.48 Percepción baja - Tasa alta
Chapinero 26491 2901 1095.09 50.28 Percepción baja - Tasa alta
Galerias 38425 3067 798.18 48.52 Percepción baja - Tasa alta
Teusaquillo 28881 2976 1030.44 62.90 Percepción baja - Tasa alta
Parque Simon Bolivar - Can 3323 958 2882.94 32.98 Percepción baja - Tasa alta
La Esmeralda 41130 1021 248.24 32.98 Percepción baja - Tasa alta
Quinta Paredes 28926 1285 444.24 34.58 Percepción baja - Tasa alta
Ciudad Salitre Oriental 25743 671 260.65 20.37 Percepción baja - Tasa alta
Ciudad Salitre Occidental 46658 1251 268.12 26.72 Percepción baja - Tasa alta
Granjas De Techo 53189 1587 298.37 40.63 Percepción baja - Tasa alta
Bavaria 41086 1100 267.73 52.84 Percepción baja - Tasa alta
Modelia 45171 1283 284.03 49.08 Percepción baja - Tasa alta
Capellania 18499 874 472.46 32.58 Percepción baja - Tasa alta
Aeropuerto El Dorado 883 545 6172.14 32.58 Percepción baja - Tasa alta
Guaymaral 2692 45 167.16 40.88 Percepción baja - Tasa baja
Verbenal 131999 944 71.52 65.43 Percepción baja - Tasa baja
La Uribe 37014 621 167.77 36.18 Percepción baja - Tasa baja
San Cristobal Norte 72939 793 108.72 49.84 Percepción baja - Tasa baja
Toberin 63068 943 149.52 60.44 Percepción baja - Tasa baja
Los Cedros 134973 1991 147.51 41.49 Percepción baja - Tasa baja
Country Club 26128 442 169.17 40.67 Percepción baja - Tasa baja
Britalia 97578 1428 146.34 38.20 Percepción baja - Tasa baja
Casa Blanca Suba 62660 947 151.13 17.45 Percepción baja - Tasa baja
Niza 84904 1584 186.56 38.99 Percepción baja - Tasa baja
La Floresta 46543 886 190.36 43.20 Percepción baja - Tasa baja
Suba 186728 2587 138.54 44.41 Percepción baja - Tasa baja
Castilla 141571 2646 186.90 52.84 Percepción baja - Tasa baja
Los Libertadores 78878 710 90.01 55.05 Percepción baja - Tasa baja
Danubio 58494 639 109.24 58.33 Percepción baja - Tasa baja
Parque Entrenubes 1169 16 136.87 58.33 Percepción baja - Tasa baja
Arborizadora 84765 1388 163.75 63.38 Percepción baja - Tasa baja
Bolivia 83775 1450 173.08 19.37 Percepción baja - Tasa baja
Fontibon 139257 2454 176.22 44.54 Percepción baja - Tasa baja
Zona Franca 65454 697 106.49 44.89 Percepción baja - Tasa baja
Tintal Norte 30467 420 137.85 54.05 Percepción baja - Tasa baja
Calandaima 134340 1215 90.44 58.77 Percepción baja - Tasa baja
San Isidro - Patios 17839 115 64.47 54.34 Percepción baja - Tasa baja
Pardo Rubio 53836 900 167.17 50.28 Percepción baja - Tasa baja
# Visualización de los cuatro grupos

ggplot(
  upz_percepcion_grupos,
  aes(
    x = pct_percibe_inseguridad,
    y = tasa_total,
    color = Grupo_percepcion_tasa
  )
) +
  geom_point(
    size = 2.7,
    alpha = 0.8
  ) +
  geom_vline(
    xintercept = mediana_percepcion,
    linetype = "dashed",
    color = "grey45"
  ) +
  geom_hline(
    yintercept = mediana_tasa,
    linetype = "dashed",
    color = "grey45"
  ) +
  scale_y_log10(
    labels = scales::label_comma()
  ) +
  scale_color_manual(
    values = c(
      "Percepción alta - Tasa alta" = "#351A4F",
      "Percepción alta - Tasa baja" = "#D9006C",
      "Percepción baja - Tasa alta" = "#168C86",
      "Percepción baja - Tasa baja" = "#A69BAF"
    ),
    name = "Clasificación"
  ) +
  labs(
    title = "Percepción y denuncias permiten identificar cuatro perfiles territoriales",
    subtitle = "Clasificación relativa según las medianas de las variables",
    x = "Percepción de inseguridad (%)",
    y = "Tasa de delitos por 10.000 habitantes (escala logarítmica)"
  ) +
  tema_clase

# Resumen ejecutivo de los cuatro grupos

resumen_cuatro_grupos <- upz_percepcion_grupos %>%
  mutate(
    Grupo = case_when(
      Grupo_percepcion_tasa == "Percepción alta - Tasa alta" ~ "G1",
      Grupo_percepcion_tasa == "Percepción alta - Tasa baja" ~ "G2",
      Grupo_percepcion_tasa == "Percepción baja - Tasa alta" ~ "G3",
      Grupo_percepcion_tasa == "Percepción baja - Tasa baja" ~ "G4"
    )
  ) %>%
  group_by(Grupo) %>%
  summarise(
    Numero_UPZ = n(),
    Poblacion_total = sum(poblacion, na.rm = TRUE),
    Porcentaje_UPZ = n() / nrow(upz_percepcion_grupos) * 100,
    Percepcion_mediana = median(
      pct_percibe_inseguridad,
      na.rm = TRUE
    ),
    Tasa_mediana = median(
      tasa_total,
      na.rm = TRUE
    ),
    Casos_totales = sum(casos_total, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  mutate(
    Grupo = factor(Grupo, levels = c("G1", "G2", "G3", "G4")),
    Participacion = paste0(
      round(Porcentaje_UPZ, 1),
      "%"
    )
  ) %>%
  arrange(Grupo)

# Tabla resumen

knitr::kable(
  resumen_cuatro_grupos %>%
    select(
      Grupo,
      Numero_UPZ,
      Participacion,
      Poblacion_total,
      Percepcion_mediana,
      Tasa_mediana,
      Casos_totales
    ),
  digits = 2,
  col.names = c(
    "Grupo",
    "N.º UPZ",
    "Participación",
    "Población",
    "Percepción mediana (%)",
    "Tasa mediana",
    "Casos totales"
  ),
  caption = "Resumen de los cuatro perfiles territoriales"
)
Resumen de los cuatro perfiles territoriales
Grupo N.º UPZ Participación Población Percepción mediana (%) Tasa mediana Casos totales
G1 24 21.4% 1216230 73.10 274.20 41585
G2 32 28.6% 3628010 76.83 120.78 44168
G3 32 28.6% 1255221 40.88 299.56 51221
G4 24 21.4% 1837071 47.37 148.51 25861
# Preparar los cuatro grupos y sus porcentajes

grafica_clasificacion_736 <- resumen_cuatro_grupos %>%
  mutate(
    Grupo = as.character(Grupo),
    Clasificacion = case_when(
      Grupo == "G1" ~ "Alta percepción - Alta tasa",
      Grupo == "G2" ~ "Alta percepción - Baja tasa",
      Grupo == "G3" ~ "Baja percepción - Alta tasa",
      Grupo == "G4" ~ "Baja percepción - Baja tasa"
    ),
    Etiqueta = paste0(
      Grupo, "\n",
      round(Porcentaje_UPZ, 1), "%\n",
      Numero_UPZ, " UPZ"
    )
  )

# Gráfica de distribución porcentual

ggplot(
  grafica_clasificacion_736,
  aes(
    x = 2,
    y = Porcentaje_UPZ,
    fill = Grupo
  )
) +
  geom_col(
    width = 0.75,
    color = "white",
    linewidth = 1
  ) +
  geom_text(
    aes(label = Etiqueta),
    position = position_stack(vjust = 0.5),
    color = "white",
    fontface = "bold",
    size = 3.5
  ) +
  coord_polar(theta = "y") +
  xlim(0.5, 2.5) +
  scale_fill_manual(
    values = c(
      "G1" = "#351A4F",
      "G2" = "#D9006C",
      "G3" = "#168C86",
      "G4" = "#A69BAF"
    ),
    labels = c(
      "G1" = "Percepción alta - Tasa alta",
      "G2" = "Percepción alta - Tasa baja",
      "G3" = "Percepción baja - Tasa alta",
      "G4" = "Percepción baja - Tasa baja"
    ),
    name = "Perfil territorial"
  ) +
  labs(
    title = "Distribución de las UPZ según percepción y tasa de delitos",
    subtitle = "Clasificación relativa basada en las medianas de ambas variables",
    caption = "Total: 112 UPZ. Los porcentajes representan participación sobre el total."
  ) +
  tema_clase +
  theme(
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    legend.position = "right"
  )

# Agrupar los cuatro perfiles en dos categorías generales

resumen_correspondencia <- resumen_cuatro_grupos %>%
  mutate(
    Tipo = case_when(
      Grupo %in% c("G1", "G4") ~ "Coincidencia",
      Grupo %in% c("G2", "G3") ~ "Diferencia"
    )
  ) %>%
  group_by(Tipo) %>%
  summarise(
    Porcentaje = sum(Porcentaje_UPZ),
    Numero_UPZ = sum(Numero_UPZ),
    .groups = "drop"
  ) %>%
  mutate(
    Tipo = factor(
      Tipo,
      levels = c("Diferencia", "Coincidencia")
    ),
    Etiqueta = paste0(
      round(Porcentaje, 1), "%",
      " (", Numero_UPZ, " UPZ)"
    )
  )

# Gráfico de correspondencia

ggplot(
  resumen_correspondencia,
  aes(
    x = Porcentaje,
    y = Tipo,
    fill = Tipo
  )
) +
  geom_col(
    width = 0.45,
    color = NA
  ) +
  geom_text(
    aes(
      label = Etiqueta
    ),
    hjust = -0.12,
    fontface = "bold",
    size = 4
  ) +
  scale_fill_manual(
    values = c(
      "Coincidencia" = "#168C86",
      "Diferencia" = "#D9006C"
    )
  ) +
  scale_x_continuous(
    limits = c(0, 75),
    breaks = seq(0, 75, 15),
    labels = function(x) paste0(x, "%"),
    expand = expansion(mult = c(0, 0))
  ) +
  labs(
    title = "Correspondencia entre percepción y denuncias",
    subtitle = "Coincidencia: G1 + G4 | Diferencia: G2 + G3",
    x = NULL,
    y = NULL,
    caption = "Clasificación relativa de las 112 UPZ según las medianas de percepción y tasa."
  ) +
  tema_clase +
  theme(
    legend.position = "none",
    panel.grid.major.y = element_blank(),
    panel.grid.minor = element_blank(),
    axis.text.y = element_text(
      face = "bold",
      size = 11
    ),
    axis.text.x = element_text(size = 9)
  )

Interpretación y conclusión

La clasificación de las UPZ en cuatro perfiles territoriales permite identificar diferencias importantes entre la percepción de inseguridad reportada por los habitantes y las tasas de delitos denunciados.

Uno de los resultados más relevantes es que el 57,2 % de las UPZ presenta una diferencia entre ambas dimensiones. En particular, el 28,6 % corresponde al grupo G2, caracterizado por una percepción de inseguridad superior a la mediana y tasas de denuncias inferiores a esta. Por su parte, otro 28,6 % pertenece al grupo G3, donde se observa el comportamiento contrario: una percepción relativamente baja frente a tasas de denuncias superiores a la mediana.

Los grupos G1 y G4, que representan conjuntamente el 42,8 % de las UPZ, muestran una correspondencia relativa entre percepción y registros: en el primero coinciden niveles altos de percepción y tasas, mientras que en el segundo ambas variables se ubican por debajo de sus respectivas medianas.

Este comportamiento permite reconocer que la experiencia de inseguridad de los habitantes no necesariamente coincide con los registros administrativos de denuncias. En algunos territorios, la percepción puede ser elevada incluso cuando las tasas registradas son relativamente bajas; en otros, las tasas pueden ser elevadas sin que la percepción reportada alcance niveles similares.

Una posible explicación es que la denuncia no recoge la totalidad de los hechos delictivos. También pueden intervenir factores como la disposición de las personas a denunciar, sus experiencias de inseguridad, la exposición a situaciones de riesgo y las características particulares del entorno. Sin embargo, la información disponible no permite determinar cuál de estos factores explica las diferencias identificadas.

Insight principal: La percepción de inseguridad y los delitos denunciados no representan necesariamente la misma realidad territorial. El 57,2 % de las UPZ presenta una diferencia entre ambas dimensiones, lo que evidencia que los registros administrativos, aunque fundamentales para analizar la seguridad, no son suficientes por sí solos para comprender cómo experimentan los habitantes la inseguridad en su entorno.

En consecuencia, el análisis de la seguridad territorial debe integrar tanto los registros de denuncias como la percepción de los habitantes, reconociendo que son indicadores complementarios y que ninguno representa por sí solo la totalidad del fenómeno.

Nota de transparencia sobre el uso de inteligencia artificial

Durante el desarrollo de este trabajo se utilizó ChatGPT como herramienta de apoyo para la construcción y ejecución del análisis exploratorio de datos (EDA), especialmente en la elaboración de código en R, la estructuración de procedimientos estadísticos, la generación de visualizaciones y la organización de los resultados dentro del documento R Markdown.

El desarrollo se realizó mediante un proceso de trabajo guiado, progresivo e iterativo. Los autores definieron el enfoque del proyecto, formularon las preguntas de investigación, establecieron las variables de interés, orientaron las decisiones metodológicas y determinaron los análisis que debían realizarse en función de los objetivos del taller.

ChatGPT proporcionó asistencia técnica en la escritura y corrección del código, así como en la propuesta de procedimientos estadísticos y alternativas de visualización. Esta colaboración se desarrolló paso a paso, revisando los resultados obtenidos, identificando errores, ajustando los procedimientos y profundizando en la interpretación de los hallazgos.

La selección de los análisis, la revisión de su pertinencia, la orientación de las preguntas y la interpretación crítica de los resultados estuvieron bajo el criterio y la dirección de los autores. De esta manera, la inteligencia artificial se utilizó como un recurso de acompañamiento y asistencia técnica, sin sustituir el proceso de análisis, reflexión y toma de decisiones de los estudiantes.

Los resultados y conclusiones presentados fueron construidos a partir de la ejecución del código sobre los datos del proyecto y de la revisión de las evidencias obtenidas durante el desarrollo del trabajo.

LS0tDQp0aXRsZTogIlRBTExFUiBERSBJTlNJR0hUUyDCtyBBTsOBTElTSVMgRVhQTE9SQVRPUklPIChFREEpIg0KYXV0aG9yOiAiSmVyc29uIERhdmlkIEN1ZWxsYXIgVmFuZWdhcyB5IEpvc2UgRWZyYWluIENhc3RpbGxvIg0KZGF0ZTogMDEgZGUgbm92aWVtYnJlIGRlIDIwMjYNCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICB0aGVtZTogZmxhdGx5DQogICAgZGZfcHJpbnQ6IGthYmxlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZSAgICMgYWdyZWdhIHVuIGJvdMOzbiBwYXJhIGRlc2NhcmdhciBlbCAuUm1kIG9yaWdpbmFsIC0tIHJlZnVlcnphIGxhIHJlcHJvZHVjaWJpbGlkYWQNCi0tLQ0KDQoNCmBgYHs9aHRtbH0NCjxzdHlsZT4NCi8qIFRpcG9ncmFmw61hIGVkaXRvcmlhbCBkZWwgY3Vyc28gKG1pc21hIHF1ZSBsbGV2YW4gbG9zIGdyw6FmaWNvcyB2w61hDQogICBzaG93dGV4dCkgdGFtYmnDqW4gcGFyYSBlbCB0ZXh0byBkZWwgZG9jdW1lbnRvIC0tIHF1ZSB0b2RvIGVsIGluZm9ybWUNCiAgIHNlIHNpZW50YSBjb21vIHVuYSBzb2xhIHBpZXphLCBubyB1biBIVE1MIGdlbsOpcmljbyBjb24gZ3LDoWZpY29zIHBlZ2Fkb3MuICovDQpAaW1wb3J0IHVybCgnaHR0cHM6Ly9mb250cy5nb29nbGVhcGlzLmNvbS9jc3MyP2ZhbWlseT1GaXJhK1NhbnM6d2dodEA0MDA7NjAwOzcwMCZkaXNwbGF5PXN3YXAnKTsNCg0KYm9keSB7IGZvbnQtZmFtaWx5OiAnRmlyYSBTYW5zJywgLWFwcGxlLXN5c3RlbSwgQmxpbmtNYWNTeXN0ZW1Gb250LCBzYW5zLXNlcmlmOyBjb2xvcjogIzJCMjUzMDsgfQ0KaDEsIGgyLCBoMyB7IGZvbnQtZmFtaWx5OiAnRmlyYSBTYW5zJywgc2Fucy1zZXJpZjsgY29sb3I6ICMzNTFBNEY7IH0NCmgxIHsgYm9yZGVyLWJvdHRvbTogM3B4IHNvbGlkICNEOTAwNkM7IHBhZGRpbmctYm90dG9tOiA4cHg7IG1hcmdpbi10b3A6IDQ4cHg7IH0NCmgyIHsgbWFyZ2luLXRvcDogMzZweDsgfQ0KYSB7IGNvbG9yOiAjRDkwMDZDOyB9DQphOmhvdmVyIHsgY29sb3I6ICMxNjhDODY7IH0NCiNUT0MgeyBib3JkZXItcmFkaXVzOiAxMHB4OyB9DQoubmF2LXBpbGxzID4gbGkuYWN0aXZlID4gYSwgLm5hdi1waWxscyA+IGxpLmFjdGl2ZSA+IGE6aG92ZXIgeyBiYWNrZ3JvdW5kLWNvbG9yOiAjMzUxQTRGICFpbXBvcnRhbnQ7IH0NCmNhcHRpb24geyBjb2xvcjogIzVBNTU2MDsgZm9udC1zdHlsZTogaXRhbGljOyBjYXB0aW9uLXNpZGU6IHRvcDsgfQ0KY29kZSB7IGNvbG9yOiAjOEExQTVDOyBiYWNrZ3JvdW5kOiAjRjZFRUYyOyBwYWRkaW5nOiAxcHggNXB4OyBib3JkZXItcmFkaXVzOiA0cHg7IH0NCnRhYmxlLmRhdGFUYWJsZSB7IGZvbnQtc2l6ZTogMC45MnJlbTsgfQ0KLmxlYWZsZXQtY29udGFpbmVyIHsgYm9yZGVyLXJhZGl1czogMTBweDsgYmFja2dyb3VuZDogI0VBRjBGNCAhaW1wb3J0YW50OyB9DQo8L3N0eWxlPg0KYGBgDQoNCg0KOjo6Ojo6OiB7c3R5bGU9ImJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMzNTFBNEYgMCUsICNEOTAwNkMgMTAwJSk7IHBhZGRpbmc6IDI2cHggMzBweDsgYm9yZGVyLXJhZGl1czogMTRweDsgbWFyZ2luLWJvdHRvbTogMzBweDsgZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IGNlbnRlcjsganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuOyBmbGV4LXdyYXA6IHdyYXA7IGdhcDogMThweDsifQ0KOjo6Ojoge3N0eWxlPSJtYXgtd2lkdGg6IDYyMHB4OyJ9DQo6Ojoge3N0eWxlPSJjb2xvcjogd2hpdGU7IGZvbnQtc2l6ZTogMS41NXJlbTsgZm9udC13ZWlnaHQ6IDcwMDsgbGluZS1oZWlnaHQ6IDEuMjU7In0NClZJU1VBTElaQUNJw5NOIERFIERBVE9TDQo6OjoNCg0KOjo6IHtzdHlsZT0iY29sb3I6ICNGNERDRTk7IGZvbnQtc2l6ZTogMXJlbTsgbWFyZ2luLXRvcDogNnB4OyJ9DQpJbnNlZ3VyaWRhZCB5IHRlcnJpdG9yaW8gZW4gQm9nb3TDoTogPGJyPg0Kwr9xdcOpIG5vcyBjdWVudGFuIGxhcyBVUFo/IDxicj4NCkRvY2VudGU6IENhcmxvcyBBbW9ydGVndWkNCjo6Og0KOjo6OjoNCg0KOjo6IHtzdHlsZT0iYmFja2dyb3VuZDogd2hpdGU7IHBhZGRpbmc6IDEwcHggMThweDsgYm9yZGVyLXJhZGl1czogMTBweDsgZmxleC1zaHJpbms6IDA7In0NCjxpbWcgc3JjPSJDOi9Vc2Vycy9qZXJzby9PbmVEcml2ZS9Eb2N1bWVudG9zL0VkdWNhY2lvbi9SJTIwTWFya2Rvd24vUHJveWVjdG9fVmlzdWFsaXphY2lvbi9fb3Ryb3MvbG9nb19Lb25yYWRfTG9yZW56LnBuZyINCiAgICAgYWx0PSJMb2dvIGRlIGxhIGluc3RpdHVjacOzbiINCiAgICAgc3R5bGU9Im1heC13aWR0aDogMjEwcHg7IGRpc3BsYXk6IGJsb2NrOyIvPg0KOjo6DQo6Ojo6Ojo6DQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBpbmNsdWRlPUZBTFNFOiBlc3RlIGNodW5rIGNvbmZpZ3VyYSBlbCBkb2N1bWVudG8gcGVybyBubyBhcGFyZWNlIGVuIGVsDQojIEhUTUwgZmluYWwgLS0gbmkgZWwgY8OzZGlnbyBuaSBuaW5nw7puIHJlc3VsdGFkby4NCiMNCiMga25pdHI6Om9wdHNfY2h1bmskc2V0KCkgY2FtYmlhIGVsIGNvbXBvcnRhbWllbnRvIGRlIFRPRE9TIGxvcyBjaHVua3MNCiMgcXVlIHZpZW5lbiBkZXNwdcOpcywgZGUgdW5hIHNvbGEgdmV6LCBlbiB2ZXogZGUgcmVwZXRpciBsYSBtaXNtYSBvcGNpw7NuDQojIGNodW5rIHBvciBjaHVuay4NCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgZWNobyA9IFRSVUUsICAgICAgICAjIG11ZXN0cmEgZWwgY8OzZGlnbyBkZSBSIGVuIGVsIEhUTUwgKGNvbiAiY29kZV9mb2xkaW5nOiBoaWRlIiBhcnJpYmEsIHF1ZWRhIG9jdWx0byBwb3IgZGVmZWN0byBwZXJvIHNlIHB1ZWRlIGRlc3BsZWdhcikNCiAgd2FybmluZyA9IEZBTFNFLCAgICAgIyBubyBtdWVzdHJhIHdhcm5pbmdzIGRlIFIgZW4gZWwgcmVwb3J0ZQ0KICBtZXNzYWdlID0gRkFMU0UsICAgICAjIG5vIG11ZXN0cmEgbWVuc2FqZXMgaW5mb3JtYXRpdm9zIChjb21vIGxvcyBkZSBsaWJyYXJ5KCkpDQogIGZpZy5hbGlnbiA9ICJjZW50ZXIiLA0KICBmaWcud2lkdGggPSA4LA0KICBmaWcuaGVpZ2h0ID0gNQ0KKQ0KYGBgDQoNCiMgUHJlcGFyYWNpw7NuIGRlIGxvcyBkYXRvcw0KDQojIyBhLiBJbnN0YWxhY2nDs24gZGUgcGFxdWV0ZXMNClBhcmEgcmVhbGl6YXIgbGEgZXhwbG9yYWNpw7NuIGRlIGxvcyBkYXRvcyBzZSB1dGlsaXphcsOhbiBwYXF1ZXRlcw0KZGUgUiBxdWUgcGVybWl0ZW4gaW1wb3J0YXIgYXJjaGl2b3MsIG9yZ2FuaXphciBsYSBpbmZvcm1hY2nDs24NCnkgcmVhbGl6YXIgY8OhbGN1bG9zIGVzdGFkw61zdGljb3MuDQoNCkVsIHNpZ3VpZW50ZSBjw7NkaWdvIGluc3RhbGEgbG9zIHBhcXVldGVzIG5lY2VzYXJpb3MgcGFyYSB0cmFiYWphcg0KY29uIGFyY2hpdm9zIEV4Y2VsIHkgQ1NWLCBtYW5pcHVsYXIgZGF0b3MgeSBlbGFib3JhciBncsOhZmljb3MuDQoNCmBgYHtyIGluc3RhbGFjaW9uLXBhcXVldGVzLCBldmFsPUZBTFNFfQ0KDQojIEluc3RhbGFjacOzbiBkZSBwYXF1ZXRlcyBuZWNlc2FyaW9zIHBhcmEgZWwgcHJveWVjdG8NCg0KaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikgICMgTWFuaXB1bGFjacOzbiwgdHJhbnNmb3JtYWNpw7NuIHkgZXhwbG9yYWNpw7NuIGRlIGRhdG9zLiBJbmNsdXllIGRwbHlyLCB0aWR5ciwgZ2dwbG90MiB5IHJlYWRyLg0KaW5zdGFsbC5wYWNrYWdlcygic2YiKSAgICAgICAgICMgTGVjdHVyYSB5IG1hbmVqbyBkZSBpbmZvcm1hY2nDs24gZ2VvZ3LDoWZpY2EuIFBlcm1pdGUgdHJhYmFqYXIgY29uIGxvcyBwb2zDrWdvbm9zIGRlIGxhcyBVUFogeSBsb2NhbGlkYWRlcy4NCmluc3RhbGwucGFja2FnZXMoImxlYWZsZXQiKSAgICAjIENyZWFjacOzbiBkZSBtYXBhcyBpbnRlcmFjdGl2b3MgY29uIHpvb20sIGV0aXF1ZXRhcyB5IHJlc2FsdGFkbyBkZSB0ZXJyaXRvcmlvcy4NCmluc3RhbGwucGFja2FnZXMoInNjYWxlcyIpICAgICAjIEZvcm1hdG8gZGUgbsO6bWVyb3MsIHBvcmNlbnRhamVzLCB0YXNhcyB5IGVzY2FsYXMgZW4gZ3LDoWZpY29zLg0KaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKSAgICAgICMgT3JnYW5pemFjacOzbiB5IHByZXNlbnRhY2nDs24gZGUgdGFibGFzIHkgcmVzdWx0YWRvcyBkZW50cm8gZGVsIGluZm9ybWUgUiBNYXJrZG93bi4NCmBgYA0KDQojIyBiLiBDYXJnYSBkZSBwYXF1ZXRlcw0KVW5hIHZleiBpbnN0YWxhZG9zLCBsb3MgcGFxdWV0ZXMgc2UgY2FyZ2FuIHBhcmEgcG9kZXIgdXRpbGl6YXINCnN1cyBmdW5jaW9uZXMgZHVyYW50ZSBlbCBhbsOhbGlzaXMuDQoNCmBgYHtyIGNhcmdhLXBhcXVldGVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQojIENhcmdhciBsYXMgbGlicmVyw61hcyBuZWNlc2FyaWFzDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KGxlYWZsZXQpDQpsaWJyYXJ5KHNjYWxlcykNCmxpYnJhcnkoa25pdHIpDQpgYGANCg0KIyMgYy4gQ29uZmlndXJhY2nDs24gZ2VuZXJhbCBkZWwgZG9jdW1lbnRvDQpDb25maWd1cmFjacOzbiBkZWwgY29tcG9ydGFtaWVudG8gZ2VuZXJhbCBkZWwgZG9jdW1lbnRvDQoNCmBgYHtyIENvbmZpZ3VyYWNpb24tZG9jLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQojIERlZmluaXIgbGEgcGFsZXRhIGRlIGNvbG9yZXMgZGVsIHByb3llY3RvDQptb3JhZG8gICA8LSAiIzM1MUE0RiINCm1hZ2VudGEgIDwtICIjRDkwMDZDIg0KdHVycXVlc2EgPC0gIiMxNjhDODYiDQpncmlzICAgICA8LSAiI0Q5RDZERCINCg0KIyBDb25maWd1cmFjacOzbiBnZW5lcmFsIGRlIGxvcyBncsOhZmljb3MNCnRlbWFfY2xhc2UgPC0gdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoDQogICAgICBmYWNlID0gImJvbGQiLCBzaXplID0gMTUsIGNvbG9yID0gbW9yYWRvDQogICAgKSwNCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KA0KICAgICAgc2l6ZSA9IDEwLjUsIGNvbG9yID0gImdyZXkzNSINCiAgICApLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KA0KICAgICAgaGp1c3QgPSAwLCBjb2xvciA9ICJncmV5NDUiLCBzaXplID0gOC41DQogICAgKSwNCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigxMCwgMjAsIDEwLCAxMCkNCiAgKQ0KDQojIE9wY2lvbmVzIGdlbmVyYWxlcyBkZSBwcmVzZW50YWNpw7NuIGRlbCBpbmZvcm1lDQprbml0cjo6b3B0c19jaHVuayRzZXQoDQogIGVjaG8gPSBUUlVFLA0KICB3YXJuaW5nID0gRkFMU0UsDQogIG1lc3NhZ2UgPSBGQUxTRSwNCiAgZmlnLmFsaWduID0gImNlbnRlciIsDQogIGZpZy53aWR0aCA9IDgsDQogIGZpZy5oZWlnaHQgPSA1LA0KICBkcGkgPSAxMjANCikNCg0KYGBgDQoNCg0KIyAxLiBJbnRyb2R1Y2Npw7NuDQoNCkxhIHNlZ3VyaWRhZCBjaXVkYWRhbmEgZXMgdW5hIGRlIGxhcyBkaW1lbnNpb25lcyBxdWUgaW5mbHV5ZQ0KZW4gbGEgY2FsaWRhZCBkZSB2aWRhIHkgZW4gbGFzIGNvbmRpY2lvbmVzIGRlIGNvbnZpdmVuY2lhIGRlDQp1bmEgY2l1ZGFkLiBTaW4gZW1iYXJnbywgc3UgY29tcG9ydGFtaWVudG8gbm8gbmVjZXNhcmlhbWVudGUNCmVzIGlndWFsIGVuIHRvZG9zIGxvcyB0ZXJyaXRvcmlvcywgeWEgcXVlIGNhZGEgem9uYSBwcmVzZW50YQ0KY2FyYWN0ZXLDrXN0aWNhcyBwYXJ0aWN1bGFyZXMgcmVsYWNpb25hZGFzIGNvbiBzdSBwb2JsYWNpw7NuLA0KaW5mcmFlc3RydWN0dXJhLCBjb25kaWNpb25lcyBzb2Npb2Vjb27Ds21pY2FzIHkgZW50b3JubyB1cmJhbm8uDQoNCkVuIEJvZ290w6EsIGxhcyBVbmlkYWRlcyBkZSBQbGFuZWFtaWVudG8gWm9uYWwgKFVQWikgcGVybWl0ZW4NCm9ic2VydmFyIGVzdGFzIGRpZmVyZW5jaWFzIGRlc2RlIHVuYSBwZXJzcGVjdGl2YSB0ZXJyaXRvcmlhbC4NCkEgdHJhdsOpcyBkZSBlbGxhcyBlcyBwb3NpYmxlIGNvbXBhcmFyIGxhcyBjb25kaWNpb25lcyBkZQ0KZGlzdGludG9zIHNlY3RvcmVzIGRlIGxhIGNpdWRhZCB5IGV4cGxvcmFyIGPDs21vIHNlIHJlbGFjaW9uYW4NCmNvbiBsb3MgcmVnaXN0cm9zIGRlIGRlbGl0b3MgeSBsYSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZA0KZGUgc3VzIGhhYml0YW50ZXMuDQoNCkVzdGUgdHJhYmFqbyBkZXNhcnJvbGxhIHVuIGFuw6FsaXNpcyBleHBsb3JhdG9yaW8gZGUgZGF0b3MNCihFREEpIHNvYnJlIGxhcyAxMTIgVVBaIHVyYmFuYXMgZGUgQm9nb3TDoSwgdXRpbGl6YW5kbw0KaW5mb3JtYWNpw7NuIHJlbGFjaW9uYWRhIGNvbiBkZWxpdG9zIGRlbnVuY2lhZG9zLCBwb2JsYWNpw7NuLA0Kdml2aWVuZGEsIGFsdW1icmFkbyBww7pibGljbyB5IGNvbmRpY2lvbmVzIHNvY2lvZWNvbsOzbWljYXMuDQoNCkVsIHByb3DDs3NpdG8gZXMgaWRlbnRpZmljYXIgcGF0cm9uZXMsIGRpZmVyZW5jaWFzIHkgcG9zaWJsZXMNCnJlbGFjaW9uZXMgZW50cmUgbGFzIGNhcmFjdGVyw61zdGljYXMgZGUgY2FkYSB0ZXJyaXRvcmlvIHkNCmxvcyBpbmRpY2Fkb3JlcyBkZSBzZWd1cmlkYWQgZGlzcG9uaWJsZXMuIFBhcmEgZWxsbywgc2UNCnV0aWxpemFyw6FuIGhlcnJhbWllbnRhcyBlc3RhZMOtc3RpY2FzIHkgdmlzdWFsaXphY2lvbmVzDQpxdWUgZmFjaWxpdGVuIGxhIGludGVycHJldGFjacOzbiBkZSBsb3MgcmVzdWx0YWRvcywgaW5jbHV5ZW5kbw0KcmVwcmVzZW50YWNpb25lcyBnZW9ncsOhZmljYXMgcXVlIHBlcm1pdGFuIHJlY29ub2NlciBsYXMNCmRpZmVyZW5jaWFzIGVudHJlIGxhcyB6b25hcyBkZSBsYSBjaXVkYWQuDQoNCkVsIGFuw6FsaXNpcyBubyBidXNjYSBlc3RhYmxlY2VyIHJlbGFjaW9uZXMgZGUgY2F1c2FsaWRhZA0KbmkgYWZpcm1hciBxdWUgdW5hIGNhcmFjdGVyw61zdGljYSB0ZXJyaXRvcmlhbCBzZWEgbGEgY2F1c2ENCmRpcmVjdGEgZGUgZGV0ZXJtaW5hZG9zIGNvbXBvcnRhbWllbnRvcyBkZWxpY3Rpdm9zLiBTdQ0KYWxjYW5jZSBlcyBleHBsb3JhdG9yaW8geSBwcmV0ZW5kZSBjb21wcmVuZGVyIG1lam9yIGxhDQppbmZvcm1hY2nDs24gZGlzcG9uaWJsZSwgcmVjb25vY2VyIHBhdHJvbmVzIHkgZ2VuZXJhcg0KcHJlZ3VudGFzIHF1ZSBwdWVkYW4gb3JpZW50YXIgaW52ZXN0aWdhY2lvbmVzIHBvc3RlcmlvcmVzLg0KDQoNCiMjIDEuMS4gT2JqZXRpdm8gZ2VuZXJhbA0KDQpFeHBsb3JhciBsYXMgY29uZGljaW9uZXMgZGUgc2VndXJpZGFkIHkgbGFzIGNhcmFjdGVyw61zdGljYXMNCnRlcnJpdG9yaWFsZXMsIGRlbW9ncsOhZmljYXMgeSBzb2Npb2Vjb27Ds21pY2FzIGRlIGxhcyBVUFoNCnVyYmFuYXMgZGUgQm9nb3TDoSwgbWVkaWFudGUgdMOpY25pY2FzIGRlIGFuw6FsaXNpcyBleHBsb3JhdG9yaW8NCmRlIGRhdG9zIHkgdmlzdWFsaXphY2nDs24sIGNvbiBlbCBwcm9ww7NzaXRvIGRlIGlkZW50aWZpY2FyDQpwYXRyb25lcywgZGlmZXJlbmNpYXMgeSBwb3NpYmxlcyByZWxhY2lvbmVzIHF1ZSBwZXJtaXRhbg0KY29tcHJlbmRlciBlbCBjb21wb3J0YW1pZW50byBkZSBsb3MgaW5kaWNhZG9yZXMgZGUNCmluc2VndXJpZGFkIGVuIGxhIGNpdWRhZC4NCg0KDQojIyAxLjIuIE9iamV0aXZvcyBlc3BlY8OtZmljb3MNCg0KLSBEZXNjcmliaXIgbGEgZXN0cnVjdHVyYSB5IGxhcyBjYXJhY3RlcsOtc3RpY2FzIGRlIGxhDQogIGluZm9ybWFjacOzbiBkaXNwb25pYmxlIHBhcmEgbGFzIDExMiBVUFogZGUgQm9nb3TDoS4NCg0KLSBFeHBsb3JhciBsYSBkaXN0cmlidWNpw7NuIGRlIGxvcyBpbmRpY2Fkb3JlcyBkZSBkZWxpdG9zLA0KICBwb2JsYWNpw7NuLCB2aXZpZW5kYSwgaW5mcmFlc3RydWN0dXJhIHkgY29uZGljaW9uZXMNCiAgc29jaW9lY29uw7NtaWNhcy4NCg0KLSBJZGVudGlmaWNhciBkaWZlcmVuY2lhcyB0ZXJyaXRvcmlhbGVzIG1lZGlhbnRlIGVsIHVzbw0KICBkZSBlc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcywgY29tcGFyYWNpb25lcyB5IG1hcGFzLg0KDQotIEV4YW1pbmFyIHBvc2libGVzIHJlbGFjaW9uZXMgZW50cmUgbG9zIGluZGljYWRvcmVzIGRlDQogIHNlZ3VyaWRhZCB5IGxhcyBjYXJhY3RlcsOtc3RpY2FzIGRlIGNhZGEgVVBaLg0KDQotIENvbXVuaWNhciBsb3MgcHJpbmNpcGFsZXMgaGFsbGF6Z29zIG1lZGlhbnRlDQogIHZpc3VhbGl6YWNpb25lcyB5IHVuYSBuYXJyYXRpdmEgYmFzYWRhIGVuIGxvcyBkYXRvcy4NCg0KDQojIDIuIERlc2NyaXBjacOzbiBkZSBsb3MgZGF0b3MNCg0KUGFyYSBkZXNhcnJvbGxhciBlbCBhbsOhbGlzaXMgc2UgdXRpbGl6YSB1bmEgYmFzZSBkZSBkYXRvcw0KY29uc29saWRhZGEgcXVlIGNvbnRpZW5lIGluZm9ybWFjacOzbiBkZSAxMTIgVW5pZGFkZXMgZGUNClBsYW5lYW1pZW50byBab25hbCBkZSBCb2dvdMOhLiBDYWRhIHJlZ2lzdHJvIHJlcHJlc2VudGEgdW5hDQpVUFogZSBpbmNsdXllIHZhcmlhYmxlcyByZWxhY2lvbmFkYXMgY29uIHN1IHRlcnJpdG9yaW8sDQpwb2JsYWNpw7NuLCBjb25kaWNpb25lcyBkZSB2aXZpZW5kYSwgaW5mcmFlc3RydWN0dXJhLA0KZGVsaXRvcyBkZW51bmNpYWRvcyB5IGNhcmFjdGVyw61zdGljYXMgc29jaW9lY29uw7NtaWNhcy4NCg0KTGEgaW5mb3JtYWNpw7NuIHNlIGVuY3VlbnRyYSBvcmdhbml6YWRhIGVuIGNpbmNvIGdyYW5kZXMNCmJsb3F1ZXM6DQoNCjEuICoqVGVycml0b3JpbzoqKiBpZGVudGlmaWNhY2nDs24gZGUgbGEgVVBaLCBsb2NhbGlkYWQNCiAgIHkgZXh0ZW5zacOzbiBnZW9ncsOhZmljYS4NCg0KMi4gKipEZW1vZ3JhZsOtYToqKiBwb2JsYWNpw7NuLCBkZW5zaWRhZCBwb2JsYWNpb25hbCB5DQogICBjb21wb3NpY2nDs24gcG9yIGdydXBvcyBkZSBlZGFkLg0KDQozLiAqKlZpdmllbmRhIGUgaW5mcmFlc3RydWN0dXJhOioqIGNhcmFjdGVyw61zdGljYXMgZGUNCiAgIGxhcyB2aXZpZW5kYXMgeSBkaXNwb25pYmlsaWRhZCBkZSBhbHVtYnJhZG8gcMO6YmxpY28uDQoNCjQuICoqRGVsaXRvczoqKiByZWdpc3Ryb3MgZGUgZGVudW5jaWFzIHkgdGFzYXMgcG9yIGNhZGENCiAgIDEwLjAwMCBoYWJpdGFudGVzIHBhcmEgZGlleiBjYXRlZ29yw61hcyBkZSBkZWxpdG9zLg0KDQo1LiAqKkVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0bzoqKiBpbmZvcm1hY2nDs24gcmVsYWNpb25hZGENCiAgIGNvbiBwb2JyZXphLCBpbmdyZXNvcywgZXN0cmF0bywgZWR1Y2FjacOzbiwgcGVyY2VwY2nDs24NCiAgIGRlIGluc2VndXJpZGFkIHkgY29uZGljaW9uZXMgZGVsIGVudG9ybm8uDQoNCkFkaWNpb25hbG1lbnRlLCBzZSBkaXNwb25lIGRlIGFyY2hpdm9zIGdlb2dyw6FmaWNvcyBxdWUNCnJlcHJlc2VudGFuIGxvcyBsw61taXRlcyBkZSBsYXMgVVBaIHkgbGFzIGxvY2FsaWRhZGVzDQp1cmJhbmFzIGRlIEJvZ290w6EuIEVzdG9zIGFyY2hpdm9zIHBlcm1pdGlyw6FuIGludGVncmFyDQpsYSBpbmZvcm1hY2nDs24gZXN0YWTDrXN0aWNhIGNvbiBzdSB1YmljYWNpw7NuIHRlcnJpdG9yaWFsLg0KDQojIDMuIENhcmdhIGRlIGxhIGluZm9ybWFjacOzbg0KVmFtb3MgYSBjb25lY3RhciBudWVzdHJvIGluZm9ybWUgY29uIGxvcyBhcmNoaXZvcy4NCg0KU2UgY2FyZ2FyYW4gdHJlcyBmdWVudGVzOg0KMS4gTGEgYmFzZSBlc3RhZMOtc3RpY2EgZGUgbGFzIFVQWi4NCjIuIEVsIG1hcGEgZGUgbGFzIFVQWi4NCjMuIEVsIG1hcGEgZGUgbGFzIGxvY2FsaWRhZGVzLg0KDQoNCmBgYHtyIGltcG9ydGFjaW9uLWRhdG9zfQ0KDQojIDMuMS4gSW1wb3J0YWNpw7NuIGRlIGxhIGJhc2UgZXN0YWTDrXN0aWNhDQoNCnVweiA8LSByZWFkX2NzdigNCiAgImlucHV0L3Vwel92YXJpYWJsZXMuY3N2IiwNCiAgc2hvd19jb2xfdHlwZXMgPSBGQUxTRQ0KKQ0KDQojIDMuMi4gSW1wb3J0YWNpw7NuIGRlIGxvcyBhcmNoaXZvcyBnZW9ncsOhZmljb3MNCg0KdXB6X3NocCA8LSBzdF9yZWFkKA0KICAiaW5wdXQvc2hwL3Vwel9ib2dvdGEuc2hwIiwNCiAgcXVpZXQgPSBUUlVFDQopDQoNCmxvY2FsaWRhZGVzX3NocCA8LSBzdF9yZWFkKA0KICAiaW5wdXQvc2hwL2xvY2FsaWRhZGVzX2JvZ290YS5zaHAiLA0KICBxdWlldCA9IFRSVUUNCikNCg0KYGBgDQoqKk5vdGFzOioqIA0KDQotICoqcmVhZF9jc3YoKSoqIHBlcm1pdGUgaW1wb3J0YXIgbGEgaW5mb3JtYWNpw7NuIGVzdGFkw61zdGljYS4NCg0KLSAqKnN0X3JlYWQoKSoqIHBlcm1pdGUgbGVlciBsb3MgYXJjaGl2b3MgZ2VvZ3LDoWZpY29zLg0KDQotIExvcyBvYmpldG9zIHRlcm1pbmFkb3MgZW4gKipfc2hwKiogY29udGllbmVuIGdlb21ldHLDrWFzIHF1ZSByZXByZXNlbnRhbiBsb3MgbMOtbWl0ZXMgdGVycml0b3JpYWxlcy4NCg0KDQojIDQuIEV4cGxvcmFjacOzbiBpbmljaWFsIGRlIGxvcyBkYXRvcw0KDQpBbnRlcyBkZSByZWFsaXphciBsb3MgYW7DoWxpc2lzIGVzdGFkw61zdGljb3MgeSBsYXMNCnZpc3VhbGl6YWNpb25lcywgZXMgbmVjZXNhcmlvIGNvbm9jZXIgbGEgZXN0cnVjdHVyYQ0KZGUgbGEgaW5mb3JtYWNpw7NuIGRpc3BvbmlibGUgeSB2ZXJpZmljYXIgc3VzDQpjYXJhY3RlcsOtc3RpY2FzIGdlbmVyYWxlcy4NCg0KRXN0YSBwcmltZXJhIGV4cGxvcmFjacOzbiBwZXJtaXRlIGlkZW50aWZpY2FyIGxhIGNhbnRpZGFkDQpkZSByZWdpc3Ryb3MgeSB2YXJpYWJsZXMsIGxvcyB0aXBvcyBkZSBkYXRvcyB1dGlsaXphZG9zDQp5IGxhcyBjb25kaWNpb25lcyBnZW5lcmFsZXMgZGUgbGEgYmFzZS4gRGUgZXN0YSBtYW5lcmEsDQpzZSBidXNjYSBlc3RhYmxlY2VyIHVuIHB1bnRvIGRlIHBhcnRpZGEgcXVlIGZhY2lsaXRlDQplbCBkZXNhcnJvbGxvIGRlIGxhcyBzaWd1aWVudGVzIGV0YXBhcyBkZWwgYW7DoWxpc2lzLg0KIA0KIyMgNC4xLiBEaW1lbnNpb25lcyB5IGVzdHJ1Y3R1cmEgZGUgbGEgaW5mb3JtYWNpw7NuDQoNCkxhIGJhc2UgZGUgZGF0b3MgY29udGllbmUgaW5mb3JtYWNpw7NuIGRlIGRpZmVyZW50ZXMNCmNhcmFjdGVyw61zdGljYXMgZGUgbGFzIFVQWiBkZSBCb2dvdMOhLiBQYXJhIGNvbWVuemFyLA0Kc2UgcmV2aXNhIHN1IGRpbWVuc2nDs24gZ2VuZXJhbCwgaWRlbnRpZmljYW5kbyBjdcOhbnRvcw0KcmVnaXN0cm9zIHkgdmFyaWFibGVzIGVzdMOhbiBkaXNwb25pYmxlcy4NCg0KQ2FkYSByZWdpc3RybyByZXByZXNlbnRhIHVuYSBVUFosIG1pZW50cmFzIHF1ZSBsYXMNCmNvbHVtbmFzIGNvcnJlc3BvbmRlbiBhIGxhcyBkaWZlcmVudGVzIGNhcmFjdGVyw61zdGljYXMNCmUgaW5kaWNhZG9yZXMgcmVjb3BpbGFkb3MgcGFyYSBlbCBhbsOhbGlzaXMuDQoNCg0KYGBge3IgZGltZW5zaW9uZXMtYmFzZX0NCg0KIyBDb25zdWx0YXIgbGFzIGRpbWVuc2lvbmVzIGdlbmVyYWxlcyBkZSBsYSBiYXNlDQpkaW0odXB6KQ0KDQojIElkZW50aWZpY2FyIGxhIGNhbnRpZGFkIGRlIHJlZ2lzdHJvcw0KbnJvdyh1cHopDQoNCiMgSWRlbnRpZmljYXIgbGEgY2FudGlkYWQgZGUgdmFyaWFibGVzDQpuY29sKHVweikNCg0KIyBDb25zdWx0YXIgbG9zIHByaW1lcm9zIHJlZ2lzdHJvcw0KaGVhZCh1cHopDQoNCmBgYA0KDQojIyA0LjIuIFRpcG9zIGRlIHZhcmlhYmxlcyB5IGVzdHJ1Y3R1cmENCg0KQWRlbcOhcyBkZSBjb25vY2VyIGVsIHRhbWHDsW8gZGUgbGEgYmFzZSwgZXMgaW1wb3J0YW50ZQ0KaWRlbnRpZmljYXIgZWwgdGlwbyBkZSBpbmZvcm1hY2nDs24gcXVlIGNvbnRpZW5lIGNhZGENCnZhcmlhYmxlLg0KDQpFc3RhIHJldmlzacOzbiBwZXJtaXRlIGRpZmVyZW5jaWFyIGxvcyBjYW1wb3MgcXVlDQpyZXByZXNlbnRhbiBjYW50aWRhZGVzLCBwb3JjZW50YWplcywgdGFzYXMsIGNhdGVnb3LDrWFzDQp0ZXJyaXRvcmlhbGVzIHkgb3RyYXMgY2FyYWN0ZXLDrXN0aWNhcy4NCg0KTGEgaWRlbnRpZmljYWNpw7NuIGRlIGVzdG9zIHRpcG9zIGRlIGRhdG9zIGVzIGltcG9ydGFudGUNCnBvcnF1ZSBubyB0b2RhcyBsYXMgdmFyaWFibGVzIHB1ZWRlbiBhbmFsaXphcnNlIGRlIGxhDQptaXNtYSBtYW5lcmEuIFBvciBlamVtcGxvLCB1bmEgdmFyaWFibGUgZGUgcG9ibGFjacOzbg0KcGVybWl0ZSByZWFsaXphciBjw6FsY3Vsb3MgZXN0YWTDrXN0aWNvcywgbWllbnRyYXMgcXVlDQp1bmEgdmFyaWFibGUgY29tbyBlbCBub21icmUgZGUgbGEgbG9jYWxpZGFkIHNlIHV0aWxpemENCnByaW5jaXBhbG1lbnRlIHBhcmEgY2xhc2lmaWNhciB5IGFncnVwYXIgbGEgaW5mb3JtYWNpw7NuLg0KDQoNCmBgYHtyIGVzdHJ1Y3R1cmEtdmFyaWFibGVzfQ0KDQojIENvbnN1bHRhciBsYSBlc3RydWN0dXJhIHkgbG9zIHRpcG9zIGRlIHZhcmlhYmxlcw0KZ2xpbXBzZSh1cHopDQoNCmBgYA0KDQoNCiMjIDQuMy4gUmV2aXNpw7NuIGRlIHZhbG9yZXMgZmFsdGFudGVzDQoNCkxvcyB2YWxvcmVzIGZhbHRhbnRlcyByZXByZXNlbnRhbiBpbmZvcm1hY2nDs24gcXVlIG5vDQpzZSBlbmN1ZW50cmEgZGlzcG9uaWJsZSBwYXJhIHVuYSBvIHZhcmlhcyB2YXJpYWJsZXMuDQpTdSBpZGVudGlmaWNhY2nDs24gZXMgaW1wb3J0YW50ZSBwb3JxdWUgcHVlZGVuIGFmZWN0YXINCmxvcyBjw6FsY3Vsb3MgZXN0YWTDrXN0aWNvcywgbGFzIGNvbXBhcmFjaW9uZXMgeSBsYXMNCnJlbGFjaW9uZXMgZW50cmUgdmFyaWFibGVzLg0KDQpFbiBlc3RhIGV0YXBhIHNlIHJldmlzYSBsYSBjYW50aWRhZCBkZSBkYXRvcyBmYWx0YW50ZXMNCmVuIGNhZGEgY29sdW1uYSwgY29uIGVsIHByb3DDs3NpdG8gZGUgZGV0ZXJtaW5hciBzaQ0KZXhpc3RlbiBsaW1pdGFjaW9uZXMgZW4gbGEgaW5mb3JtYWNpw7NuIGRpc3BvbmlibGUuDQoNCg0KYGBge3IgcmV2aXNpb24tZmFsdGFudGVzfQ0KDQojIENhbGN1bGFyIGxhIGNhbnRpZGFkIGRlIHZhbG9yZXMgZmFsdGFudGVzIHBvciB2YXJpYWJsZQ0KDQpmYWx0YW50ZXMgPC0gdXB6ICU+JQ0KICBzdW1tYXJpc2UoDQogICAgYWNyb3NzKA0KICAgICAgZXZlcnl0aGluZygpLA0KICAgICAgfiBzdW0oaXMubmEoLikpDQogICAgKQ0KICApICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGV2ZXJ5dGhpbmcoKSwNCiAgICBuYW1lc190byA9ICJWYXJpYWJsZSIsDQogICAgdmFsdWVzX3RvID0gIkNhbnRpZGFkX2ZhbHRhbnRlcyINCiAgKSAlPiUNCiAgZmlsdGVyKENhbnRpZGFkX2ZhbHRhbnRlcyA+IDApICU+JQ0KICBhcnJhbmdlKGRlc2MoQ2FudGlkYWRfZmFsdGFudGVzKSkNCg0KIyBQcmVzZW50YXIgbG9zIHJlc3VsdGFkb3MNCg0KaWYgKG5yb3coZmFsdGFudGVzKSA9PSAwKSB7DQoNCiAgY2F0KCJObyBzZSBlbmNvbnRyYXJvbiB2YWxvcmVzIGZhbHRhbnRlcyBlbiBsYSBiYXNlIGRlIGRhdG9zLiIpDQoNCn0gZWxzZSB7DQoNCiAga25pdHI6OmthYmxlKA0KICAgIGZhbHRhbnRlcywNCiAgICBjYXB0aW9uID0gIlZhcmlhYmxlcyBjb24gdmFsb3JlcyBmYWx0YW50ZXMiDQogICkNCg0KfQ0KDQpgYGANCg0KIyMgNC40LiBJZGVudGlmaWNhY2nDs24gZGUgcmVnaXN0cm9zIGR1cGxpY2Fkb3MNCg0KRGViaWRvIGEgcXVlIGNhZGEgcmVnaXN0cm8gcmVwcmVzZW50YSB1bmEgVVBaLCBlbA0KY8OzZGlnbyBkZSBpZGVudGlmaWNhY2nDs24gdGVycml0b3JpYWwgZGViZSBzZXIgw7puaWNvDQpkZW50cm8gZGUgbGEgYmFzZSBkZSBkYXRvcy4NCg0KUG9yIGVzdGEgcmF6w7NuLCBzZSByZXZpc2Egc2kgZXhpc3RlbiBjw7NkaWdvcyByZXBldGlkb3MNCnF1ZSBwdWVkYW4gZ2VuZXJhciBkdXBsaWNpZGFkIGRlIGluZm9ybWFjacOzbiBvIGFmZWN0YXINCmxhcyBjb21wYXJhY2lvbmVzIHBvc3RlcmlvcmVzLg0KDQoNCmBgYHtyIHJldmlzaW9uLWR1cGxpY2Fkb3N9DQoNCiMgSWRlbnRpZmljYXIgY8OzZGlnb3MgVVBaIHJlcGV0aWRvcw0KDQpkdXBsaWNhZG9zX3VweiA8LSB1cHogJT4lDQogIGNvdW50KHVwel9jb2QsIG5hbWUgPSAiRnJlY3VlbmNpYSIpICU+JQ0KICBmaWx0ZXIoRnJlY3VlbmNpYSA+IDEpDQoNCiMgUHJlc2VudGFyIGVsIHJlc3VsdGFkbw0KDQppZiAobnJvdyhkdXBsaWNhZG9zX3VweikgPT0gMCkgew0KDQogIGNhdCgiTm8gc2UgZW5jb250cmFyb24gY8OzZGlnb3MgVVBaIGR1cGxpY2Fkb3MuIikNCg0KfSBlbHNlIHsNCg0KICBrbml0cjo6a2FibGUoDQogICAgZHVwbGljYWRvc191cHosDQogICAgY2FwdGlvbiA9ICJDw7NkaWdvcyBVUFogZHVwbGljYWRvcyINCiAgKQ0KDQp9DQoNCmBgYA0KDQojIyA0LjUuIFJlc3VtZW4gZ2VuZXJhbCBkZSBsYSBleHBsb3JhY2nDs24gaW5pY2lhbA0KDQpVbmEgdmV6IHJlYWxpemFkYXMgbGFzIHZlcmlmaWNhY2lvbmVzIGluaWNpYWxlcywNCnNlIGNvbnNvbGlkYSB1biByZXN1bWVuIGRlIGxhcyBwcmluY2lwYWxlcw0KY2FyYWN0ZXLDrXN0aWNhcyBkZSBsYSBiYXNlIGRlIGRhdG9zLg0KDQpFc3RlIHJlc3VsdGFkbyBwZXJtaXRlIGVzdGFibGVjZXIgbGFzIGNvbmRpY2lvbmVzDQpnZW5lcmFsZXMgZGUgbGEgaW5mb3JtYWNpw7NuIGNvbiBsYSBxdWUgc2UgZGVzYXJyb2xsYXLDoQ0KZWwgYW7DoWxpc2lzIGV4cGxvcmF0b3Jpby4NCg0KDQpgYGB7ciByZXN1bWVuLWV4cGxvcmFjaW9ufQ0KDQpyZXN1bWVuX2Jhc2UgPC0gdGliYmxlKA0KICBJbmRpY2Fkb3IgPSBjKA0KICAgICJDYW50aWRhZCBkZSByZWdpc3Ryb3MiLA0KICAgICJDYW50aWRhZCBkZSB2YXJpYWJsZXMiLA0KICAgICJDw7NkaWdvcyBVUFogw7puaWNvcyIsDQogICAgIlZhbG9yZXMgZmFsdGFudGVzIiwNCiAgICAiQ8OzZGlnb3MgVVBaIGR1cGxpY2Fkb3MiDQogICksDQoNCiAgUmVzdWx0YWRvID0gYygNCiAgICBucm93KHVweiksDQogICAgbmNvbCh1cHopLA0KICAgIG5fZGlzdGluY3QodXB6JHVwel9jb2QpLA0KICAgIHN1bShpcy5uYSh1cHopKSwNCiAgICBucm93KGR1cGxpY2Fkb3NfdXB6KQ0KICApDQopDQoNCmtuaXRyOjprYWJsZSgNCiAgcmVzdW1lbl9iYXNlLA0KICBjb2wubmFtZXMgPSBjKCJJbmRpY2Fkb3IiLCAiUmVzdWx0YWRvIiksDQogIGNhcHRpb24gPSAiUmVzdW1lbiBkZSBsYSBleHBsb3JhY2nDs24gaW5pY2lhbCINCikNCg0KYGBgDQoNCg0KIyMjIEludGVycHJldGFjacOzbiBkZSBsYSByZXZpc2nDs24gaW5pY2lhbA0KDQpMb3MgcmVzdWx0YWRvcyBtdWVzdHJhbiBxdWUgbGEgYmFzZSBkZSBkYXRvcyBlc3TDoQ0KY29uZm9ybWFkYSBwb3IgMTEyIHJlZ2lzdHJvcyB5IDY3IHZhcmlhYmxlcywgY29uIHVuYQ0KY29ycmVzcG9uZGVuY2lhIGRlIHVuIHJlZ2lzdHJvIHBvciBjYWRhIGPDs2RpZ28gVVBaLg0KDQpFbiBsYSByZXZpc2nDs24gcmVhbGl6YWRhIG5vIHNlIGlkZW50aWZpY2Fyb24gdmFsb3Jlcw0KZmFsdGFudGVzIG5pIGPDs2RpZ29zIHRlcnJpdG9yaWFsZXMgZHVwbGljYWRvcy4gRXN0bw0KcmVwcmVzZW50YSB1bmEgY29uZGljacOzbiBmYXZvcmFibGUgcGFyYSBjb250aW51YXIgY29uDQplbCBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvLg0KDQpTaW4gZW1iYXJnbywgbGEgYXVzZW5jaWEgZGUgdmFsb3JlcyBmYWx0YW50ZXMgeQ0KZHVwbGljYWRvcyBubyBnYXJhbnRpemEgcG9yIHPDrSBzb2xhIGxhIGNhbGlkYWQgZGUNCnRvZGEgbGEgaW5mb3JtYWNpw7NuLiBUb2RhdsOtYSBlcyBuZWNlc2FyaW8gcmV2aXNhcg0KbGEgZGlzdHJpYnVjacOzbiBkZSBsYXMgdmFyaWFibGVzLCBpZGVudGlmaWNhciBwb3NpYmxlcw0KdmFsb3JlcyBleHRyZW1vcyB5IGV2YWx1YXIgbGEgY29oZXJlbmNpYSBkZSBsb3MNCmluZGljYWRvcmVzIGNhbGN1bGFkb3MuDQoNClBvciBsbyB0YW50bywgZXN0YSBwcmltZXJhIHJldmlzacOzbiBjb25zdGl0dXllIHVuDQpwdW50byBkZSBwYXJ0aWRhIHBhcmEgcHJvZnVuZGl6YXIgZW4gZWwgY29tcG9ydGFtaWVudG8NCmVzdGFkw61zdGljbyBkZSBsYXMgdmFyaWFibGVzLg0KDQoNCiMgNS4gQW7DoWxpc2lzIGV4cGxvcmF0b3JpbyBkZSBsYXMgdmFyaWFibGVzDQoNClVuYSB2ZXogcmV2aXNhZGEgbGEgZXN0cnVjdHVyYSBnZW5lcmFsIGRlIGxhIGluZm9ybWFjacOzbiwNCnNlIGluaWNpYSBlbCBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvIGRlIGxhcyB2YXJpYWJsZXMgY29uDQplbCBwcm9ww7NzaXRvIGRlIGNvbXByZW5kZXIgc3UgY29tcG9ydGFtaWVudG8sIGlkZW50aWZpY2FyDQpkaWZlcmVuY2lhcyBlbnRyZSBsb3MgdGVycml0b3Jpb3MgeSByZWNvbm9jZXIgcG9zaWJsZXMNCnBhdHJvbmVzIHF1ZSBwdWVkYW4gb3JpZW50YXIgbGEgaW52ZXN0aWdhY2nDs24uDQoNCkVuIGVzdGEgZXRhcGEgc2UgdXRpbGl6YXLDoW4gZXN0YWTDrXN0aWNhcyBkZXNjcmlwdGl2YXMNCnkgcmVwcmVzZW50YWNpb25lcyBncsOhZmljYXMgcGFyYSBleGFtaW5hciBsYXMgcHJpbmNpcGFsZXMNCmNhcmFjdGVyw61zdGljYXMgZGUgbGFzIFVQWiBkZSBCb2dvdMOhLg0KDQojIyA1LjEuIEFuw6FsaXNpcyBkZW1vZ3LDoWZpY286IHBvYmxhY2nDs24geSBkaXN0cmlidWNpw7NuIHRlcnJpdG9yaWFsDQoNCkxhIHBvYmxhY2nDs24gY29uc3RpdHV5ZSB1bmEgZGUgbGFzIHZhcmlhYmxlcyBmdW5kYW1lbnRhbGVzDQpwYXJhIGNvbXByZW5kZXIgbGFzIGRpZmVyZW5jaWFzIGVudHJlIGxhcyBVUFosIHlhIHF1ZQ0KcGVybWl0ZSBkaW1lbnNpb25hciBlbCB0YW1hw7FvIGRlIGNhZGEgdGVycml0b3JpbyBlbg0KdMOpcm1pbm9zIGRlIGhhYml0YW50ZXMuDQoNClN1IGFuw6FsaXNpcyBlcyBlc3BlY2lhbG1lbnRlIGltcG9ydGFudGUgcGFyYSBlc3RlIHRyYWJham8sDQpwb3JxdWUgbG9zIGluZGljYWRvcmVzIGRlIGRlbGl0b3Mgc2UgZXhwcmVzYW4gdGFudG8gZW4NCmNhbnRpZGFkZXMgYWJzb2x1dGFzIGNvbW8gZW4gdGFzYXMgcG9yIGNhZGEgMTAuMDAwDQpoYWJpdGFudGVzLiBQb3IgbG8gdGFudG8sIGNvbm9jZXIgY8OzbW8gc2UgZGlzdHJpYnV5ZSBsYQ0KcG9ibGFjacOzbiBwZXJtaXRpcsOhIGludGVycHJldGFyIHBvc3Rlcmlvcm1lbnRlIGxhcw0KZGlmZXJlbmNpYXMgZW4gbG9zIGluZGljYWRvcmVzIGRlIHNlZ3VyaWRhZC4NCg0KIyMjIDUuMS4xLiBEaXN0cmlidWNpw7NuIGRlIGxhIHBvYmxhY2nDs24gcG9yIFVQWg0KDQpJbmljaWFsbWVudGUgc2UgYW5hbGl6YSBsYSBjYW50aWRhZCBkZSBoYWJpdGFudGVzDQpyZWdpc3RyYWRvcyBlbiBjYWRhIFVQWiwgY29uIGVsIHByb3DDs3NpdG8gZGUgaWRlbnRpZmljYXINCmxhcyBkaWZlcmVuY2lhcyBleGlzdGVudGVzIGVudHJlIGxvcyB0ZXJyaXRvcmlvcyB5DQpyZWNvbm9jZXIgY3XDoWxlcyBjb25jZW50cmFuIHVuYSBtYXlvciBvIG1lbm9yIHBvYmxhY2nDs24uDQoNCiMjIyMgYS4gRXN0YWTDrXN0aWNhcyBkZXNjcmlwdGl2YXMgZGUgcG9ibGFjacOzbg0KUHJpbWVybyB2YW1vcyBhIGNhbGN1bGFyIGxhcyBwcmluY2lwYWxlcyBtZWRpZGFzIGVzdGFkw61zdGljYXMuDQpgYGB7ciBlc3RhZGlzdGljYXMtcG9ibGFjaW9ufQ0KDQojIENhbGN1bGFyIGxhcyBwcmluY2lwYWxlcyBtZWRpZGFzIGRlc2NyaXB0aXZhcw0KIyBkZSBsYSBwb2JsYWNpw7NuIGRlIGxhcyBVUFoNCg0KZXN0YWRpc3RpY2FzX3BvYmxhY2lvbiA8LSB1cHogJT4lDQogIHN1bW1hcmlzZSgNCiAgICBUb3RhbF9VUFogPSBuKCksDQogICAgUG9ibGFjaW9uX3RvdGFsID0gc3VtKHBvYmxhY2lvbiksDQogICAgTWVkaWEgPSBtZWFuKHBvYmxhY2lvbiksDQogICAgTWVkaWFuYSA9IG1lZGlhbihwb2JsYWNpb24pLA0KICAgIERlc3ZpYWNpb25fZXN0YW5kYXIgPSBzZChwb2JsYWNpb24pLA0KICAgIE1pbmltbyA9IG1pbihwb2JsYWNpb24pLA0KICAgIFExID0gcXVhbnRpbGUocG9ibGFjaW9uLCAwLjI1KSwNCiAgICBRMyA9IHF1YW50aWxlKHBvYmxhY2lvbiwgMC43NSksDQogICAgTWF4aW1vID0gbWF4KHBvYmxhY2lvbikNCiAgKQ0KDQoNCiMgUHJlc2VudGFyIHJlc3VsdGFkb3MNCg0KZXN0YWRpc3RpY2FzX3BvYmxhY2lvbiAlPiUNCiAgdGlkeXI6OnBpdm90X2xvbmdlcigNCiAgICBjb2xzID0gZXZlcnl0aGluZygpLA0KICAgIG5hbWVzX3RvID0gIkVzdGFkw61zdGljYSIsDQogICAgdmFsdWVzX3RvID0gIlZhbG9yIg0KICApICU+JQ0KICBrbml0cjo6a2FibGUoDQogICAgY29sLm5hbWVzID0gYygiRXN0YWTDrXN0aWNhIiwgIlJlc3VsdGFkbyIpLA0KICAgIGNhcHRpb24gPSAiRXN0YWTDrXN0aWNhcyBkZXNjcmlwdGl2YXMgZGUgcG9ibGFjacOzbiBwb3IgVVBaIg0KICApDQoNCmBgYA0KIyMjIyDCv1F1w6kgZXN0YW1vcyBjYWxjdWxhbmRvPw0KDQp8ICoqTWVkaWRhKiogfCAqKlF1w6kgbm9zIHBlcm1pdGUgY29ub2NlcioqIHwNCnw6LS0tfDotLS18DQp8IE1lZGlhIHwgUG9ibGFjacOzbiBwcm9tZWRpbyBwb3IgVVBaLiB8DQp8IE1lZGlhbmEgfCBWYWxvciBxdWUgZGl2aWRlIGxhcyBVUFogZW4gZG9zIGdydXBvcyBpZ3VhbGVzLiB8DQp8IERlc3ZpYWNpw7NuIGVzdMOhbmRhciB8IFF1w6kgdGFuIGRpc3BlcnNhIGVzdMOhIGxhIHBvYmxhY2nDs24gcmVzcGVjdG8gYSBsYSBtZWRpYS4gfA0KfCBNw61uaW1vIHkgbcOheGltbyB8IExvcyBleHRyZW1vcyBkZSBwb2JsYWNpw7NuLiB8DQp8IFExIHwgRWwgMjUgJSBkZSBsYXMgVVBaIHRpZW5lIHVuYSBwb2JsYWNpw7NuIGlndWFsIG8gaW5mZXJpb3IgYSBlc3RlIHZhbG9yLiB8DQp8IFEzIHwgRWwgNzUgJSBkZSBsYXMgVVBaIHRpZW5lIHVuYSBwb2JsYWNpw7NuIGlndWFsIG8gaW5mZXJpb3IgYSBlc3RlIHZhbG9yLiB8DQoNClVuYSBjb21wYXJhY2nDs24gZXNwZWNpYWxtZW50ZSBpbXBvcnRhbnRlIHNlcsOhIGxhIG1lZGlhIGZyZW50ZSBhIGxhIG1lZGlhbmEuIFNpIGxhIHByaW1lcmEgZXMgY29uc2lkZXJhYmxlbWVudGUgbWF5b3IsIHB1ZWRlIGluZGljYXIgcXVlIGFsZ3VuYXMgVVBaIGNvbiBwb2JsYWNpb25lcyBtdXkgZWxldmFkYXMgZXN0w6FuIGluZmx1eWVuZG8gZW4gZWwgcHJvbWVkaW8uDQoNCiMjIyMgYi4gRGlzdHJpYnVjacOzbiBncsOhZmljYSBkZSBsYSBwb2JsYWNpw7NuDQoNCkFob3JhIHZhbW9zIGEgdmlzdWFsaXphciBjw7NtbyBzZSBkaXN0cmlidXllIGxhIHBvYmxhY2nDs24gZW50cmUgbGFzIDExMiBVUFoNCg0KYGBge3IgZ3JhZmljby1kaXN0cmlidWNpb24tcG9ibGFjaW9ufQ0KDQojIEhpc3RvZ3JhbWEgZGUgbGEgcG9ibGFjacOzbiBwb3IgVVBaDQoNCmdncGxvdCh1cHosIGFlcyh4ID0gcG9ibGFjaW9uKSkgKw0KDQogIGdlb21faGlzdG9ncmFtKA0KICAgIGJpbnMgPSAyMCwNCiAgICBmaWxsID0gbWFnZW50YSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgYWxwaGEgPSAwLjg1DQogICkgKw0KDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBsYSBwb2JsYWNpw7NuIHBvciBVUFoiLA0KICAgIHN1YnRpdGxlID0gIlBvYmxhY2nDs24gcHJveWVjdGFkYSBwYXJhIGVsIGHDsW8gMjAyMyIsDQogICAgeCA9ICJDYW50aWRhZCBkZSBoYWJpdGFudGVzIiwNCiAgICB5ID0gIk7Dum1lcm8gZGUgVVBaIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogQmFzZSBkZSBkYXRvcyBkZWwgdGFsbGVyLiINCiAgKSArDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKA0KICAgICAgYmlnLm1hcmsgPSAiLiIsDQogICAgICBkZWNpbWFsLm1hcmsgPSAiLCINCiAgICApDQogICkgKw0KDQogIHRlbWFfY2xhc2UNCg0KYGBgDQoNCiMjIyDCv1F1w6kgYnVzY2Ftb3MgaWRlbnRpZmljYXI/DQoNCkVsIGhpc3RvZ3JhbWEgbm9zIHBlcm1pdGUgb2JzZXJ2YXIgZMOzbmRlIHNlIGNvbmNlbnRyYSBsYSBtYXlvciBjYW50aWRhZCBkZSBVUFogc2Vnw7puIHN1IHBvYmxhY2nDs24uDQoNClRhbWJpw6luIG5vcyBheXVkYSBhIGlkZW50aWZpY2FyIHNpIGxhIGRpc3RyaWJ1Y2nDs24gZXMgc2ltw6l0cmljYSBvIHNpIHByZXNlbnRhIHVuYSBjb25jZW50cmFjacOzbiBkZSB0ZXJyaXRvcmlvcyBjb24gcG9ibGFjaW9uZXMgcGVxdWXDsWFzIHkgdW5vcyBwb2NvcyB0ZXJyaXRvcmlvcyBjb24gcG9ibGFjaW9uZXMgY29uc2lkZXJhYmxlbWVudGUgbWF5b3Jlcy4NCg0KTm8gZGViZW1vcyBhc3VtaXIgcXVlIGxhIHBvYmxhY2nDs24gc2UgZGlzdHJpYnV5ZSBkZSBtYW5lcmEgdW5pZm9ybWUgZW50cmUgbGFzIFVQWi4NCg0KIyMjIyBjLiBJZGVudGlmaWNhY2nDs24gZGUgbGFzIFVQWiBjb24gbWF5b3IgeSBtZW5vciBwb2JsYWNpw7NuDQoNClkgY29tbyBlbCBoaXN0b2dyYW1hIG5vcyBtdWVzdHJhIGVsIGNvbXBvcnRhbWllbnRvIGdlbmVyYWwsIHBlcm8gYWhvcmEgbmVjZXNpdGFtb3MgaWRlbnRpZmljYXIgbG9zIHRlcnJpdG9yaW9zIHF1ZSBzZSBlbmN1ZW50cmFuIGVuIGxvcyBleHRyZW1vcy4NCg0KVmFtb3MgYSBjb25zdHJ1aXIgZG9zIHJhbmtpbmdzOiBsYXMgMTAgVVBaIG3DoXMgcG9ibGFkYXMgeSBsYXMgMTAgbWVub3MgcG9ibGFkYXMuDQoNCmBgYHtyIHJhbmtpbmctcG9ibGFjaW9ufQ0KDQojIDEwIFVQWiBjb24gbWF5b3IgcG9ibGFjacOzbg0KDQp1cHpfbWF5b3JfcG9ibGFjaW9uIDwtIHVweiAlPiUNCiAgYXJyYW5nZShkZXNjKHBvYmxhY2lvbikpICU+JQ0KICBzZWxlY3QoDQogICAgdXB6X25vbWJyZSwNCiAgICBsb2NhbGlkYWQsDQogICAgcG9ibGFjaW9uDQogICkgJT4lDQogIHNsaWNlX2hlYWQobiA9IDEwKQ0KDQojIDEwIFVQWiBjb24gbWVub3IgcG9ibGFjacOzbg0KDQp1cHpfbWVub3JfcG9ibGFjaW9uIDwtIHVweiAlPiUNCiAgYXJyYW5nZShwb2JsYWNpb24pICU+JQ0KICBzZWxlY3QoDQogICAgdXB6X25vbWJyZSwNCiAgICBsb2NhbGlkYWQsDQogICAgcG9ibGFjaW9uDQogICkgJT4lDQogIHNsaWNlX2hlYWQobiA9IDEwKQ0KDQojIFByZXNlbnRhciBsYXMgVVBaIG3DoXMgcG9ibGFkYXMNCg0Ka25pdHI6OmthYmxlKA0KICB1cHpfbWF5b3JfcG9ibGFjaW9uLA0KICBjb2wubmFtZXMgPSBjKCJVUFoiLCAiTG9jYWxpZGFkIiwgIkhhYml0YW50ZXMiKSwNCiAgY2FwdGlvbiA9ICJMYXMgMTAgVVBaIGNvbiBtYXlvciBwb2JsYWNpw7NuIiwNCiAgZGlnaXRzID0gMA0KKQ0KDQojIFByZXNlbnRhciBsYXMgVVBaIG1lbm9zIHBvYmxhZGFzDQoNCmtuaXRyOjprYWJsZSgNCiAgdXB6X21lbm9yX3BvYmxhY2lvbiwNCiAgY29sLm5hbWVzID0gYygiVVBaIiwgIkxvY2FsaWRhZCIsICJIYWJpdGFudGVzIiksDQogIGNhcHRpb24gPSAiTGFzIDEwIFVQWiBjb24gbWVub3IgcG9ibGFjacOzbiIsDQogIGRpZ2l0cyA9IDANCikNCg0KYGBgDQoNCiMjIyMgZC4gVmlzdWFsaXphY2nDs24gLSBHcmFmaWNvDQoNCkFob3JhIHZhbW9zIGEgcmVwcmVzZW50YXIgdmlzdWFsbWVudGUgZXN0b3MgcmVzdWx0YWRvcy4NCmBgYHtyIGdyYWZpY28tcmFua2luZy1wb2JsYWNpb259DQoNCiMgUHJlcGFyYXIgbG9zIGRhdG9zIGRlIGxhcyAxMCBVUFogbcOhcyBwb2JsYWRhcw0KDQpnZ3Bsb3QoDQogIHVwel9tYXlvcl9wb2JsYWNpb24sDQogIGFlcygNCiAgICB4ID0gcmVvcmRlcih1cHpfbm9tYnJlLCBwb2JsYWNpb24pLA0KICAgIHkgPSBwb2JsYWNpb24NCiAgKQ0KKSArDQoNCiAgZ2VvbV9jb2woDQogICAgZmlsbCA9IG1vcmFkbywNCiAgICB3aWR0aCA9IDAuNw0KICApICsNCg0KICBjb29yZF9mbGlwKCkgKw0KDQogIGxhYnMoDQogICAgdGl0bGUgPSAiTGFzIFVQWiBjb24gbWF5b3IgY29uY2VudHJhY2nDs24gZGUgcG9ibGFjacOzbiIsDQogICAgc3VidGl0bGUgPSAiUmFua2luZyBkZSBsYXMgMTAgVVBaIG3DoXMgcG9ibGFkYXMgZGUgQm9nb3TDoSIsDQogICAgeCA9IE5VTEwsDQogICAgeSA9ICJDYW50aWRhZCBkZSBoYWJpdGFudGVzIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogQmFzZSBkZSBkYXRvcyBkZWwgdGFsbGVyLiINCiAgKSArDQoNCiAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKA0KICAgICAgYmlnLm1hcmsgPSAiLiIsDQogICAgICBkZWNpbWFsLm1hcmsgPSAiLCINCiAgICApDQogICkgKw0KDQogIHRlbWFfY2xhc2UNCg0KYGBgDQoNCg0KIyMjIDUuMS4yLiBBbsOhbGlzaXMgZGUgbGEgZGVuc2lkYWQgcG9ibGFjaW9uYWwNCg0KTGEgY2FudGlkYWQgZGUgaGFiaXRhbnRlcyBubyBlcyBlbCDDum5pY28gZWxlbWVudG8NCnF1ZSBwZXJtaXRlIGNhcmFjdGVyaXphciB1biB0ZXJyaXRvcmlvLiBUYW1iacOpbiBlcw0KaW1wb3J0YW50ZSBjb25zaWRlcmFyIHN1IGV4dGVuc2nDs24gZ2VvZ3LDoWZpY2EgcGFyYQ0KY29tcHJlbmRlciBxdcOpIHRhbiBjb25jZW50cmFkYSBzZSBlbmN1ZW50cmEgbGEgcG9ibGFjacOzbi4NCg0KUGFyYSBlbGxvIHNlIHV0aWxpemEgbGEgZGVuc2lkYWQgcG9ibGFjaW9uYWwsIG1lZGlkYQ0KZW4gaGFiaXRhbnRlcyBwb3Iga2lsw7NtZXRybyBjdWFkcmFkbyAoaGFiL2ttwrIpLg0KRXN0ZSBpbmRpY2Fkb3IgcmVsYWNpb25hIGxhIHBvYmxhY2nDs24gZGUgY2FkYSBVUFoNCmNvbiBlbCDDoXJlYSBxdWUgb2N1cGEuDQoNClN1IGFuw6FsaXNpcyBwZXJtaXRlIGRpZmVyZW5jaWFyIHRlcnJpdG9yaW9zIGNvbg0KZ3JhbmRlcyBwb2JsYWNpb25lcyB5IGV4dGVuc2lvbmVzIGFtcGxpYXMgZGUgYXF1ZWxsb3MNCnF1ZSBwcmVzZW50YW4gdW5hIG1heW9yIGNvbmNlbnRyYWNpw7NuIGRlIGhhYml0YW50ZXMNCmVuIHN1cGVyZmljaWVzIG3DoXMgcmVkdWNpZGFzLg0KDQojIyMjIGEuIEVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzIGRlIGRlbnNpZGFkDQoNCmBgYHtyIGVzdGFkaXN0aWNhcy1kZW5zaWRhZH0NCg0KIyBFc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcyBkZSBkZW5zaWRhZCBwb2JsYWNpb25hbA0KDQplc3RhZGlzdGljYXNfZGVuc2lkYWQgPC0gdXB6ICU+JQ0KICBzdW1tYXJpc2UoDQogICAgTWVkaWEgPSBtZWFuKGRlbnNpZGFkX2hhYl9rbTIpLA0KICAgIE1lZGlhbmEgPSBtZWRpYW4oZGVuc2lkYWRfaGFiX2ttMiksDQogICAgRGVzdmlhY2lvbl9lc3RhbmRhciA9IHNkKGRlbnNpZGFkX2hhYl9rbTIpLA0KICAgIE1pbmltbyA9IG1pbihkZW5zaWRhZF9oYWJfa20yKSwNCiAgICBRMSA9IHF1YW50aWxlKGRlbnNpZGFkX2hhYl9rbTIsIDAuMjUpLA0KICAgIFEzID0gcXVhbnRpbGUoZGVuc2lkYWRfaGFiX2ttMiwgMC43NSksDQogICAgTWF4aW1vID0gbWF4KGRlbnNpZGFkX2hhYl9rbTIpDQogICkNCg0Ka25pdHI6OmthYmxlKA0KICBlc3RhZGlzdGljYXNfZGVuc2lkYWQsDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiRXN0YWTDrXN0aWNhcyBkZXNjcmlwdGl2YXMgZGUgbGEgZGVuc2lkYWQgcG9ibGFjaW9uYWwiDQopDQoNCmBgYA0KDQojIyMjIGIuIFVQWiBjb24gbWF5b3IgeSBtZW5vciBkZW5zaWRhZA0KDQoNCmBgYHtyIHJhbmtpbmctZGVuc2lkYWR9DQoNCiMgSWRlbnRpZmljYXIgbGFzIFVQWiBjb24gbWF5b3IgZGVuc2lkYWQgcG9ibGFjaW9uYWwNCg0KcmFua2luZ19kZW5zaWRhZCA8LSB1cHogJT4lDQogIGFycmFuZ2UoZGVzYyhkZW5zaWRhZF9oYWJfa20yKSkgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICBwb2JsYWNpb24sDQogICAgYXJlYV9rbTIsDQogICAgZGVuc2lkYWRfaGFiX2ttMg0KICApDQoNCiMgUHJlc2VudGFyIGxhcyAxMCBVUFogY29uIG1heW9yIGRlbnNpZGFkDQoNCmtuaXRyOjprYWJsZSgNCiAgcmFua2luZ19kZW5zaWRhZCAlPiUgc2xpY2VfaGVhZChuID0gMTApLA0KICBjb2wubmFtZXMgPSBjKA0KICAgICJVUFoiLA0KICAgICJMb2NhbGlkYWQiLA0KICAgICJIYWJpdGFudGVzIiwNCiAgICAiw4FyZWEgKGttwrIpIiwNCiAgICAiRGVuc2lkYWQgKGhhYi9rbcKyKSINCiAgKSwNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJMYXMgMTAgVVBaIGNvbiBtYXlvciBkZW5zaWRhZCBwb2JsYWNpb25hbCINCikNCg0KIyBQcmVzZW50YXIgbGFzIDEwIFVQWiBjb24gbWVub3IgZGVuc2lkYWQNCg0Ka25pdHI6OmthYmxlKA0KICByYW5raW5nX2RlbnNpZGFkICU+JSBhcnJhbmdlKGRlbnNpZGFkX2hhYl9rbTIpICU+JSBzbGljZV9oZWFkKG4gPSAxMCksDQogIGNvbC5uYW1lcyA9IGMoDQogICAgIlVQWiIsDQogICAgIkxvY2FsaWRhZCIsDQogICAgIkhhYml0YW50ZXMiLA0KICAgICLDgXJlYSAoa23CsikiLA0KICAgICJEZW5zaWRhZCAoaGFiL2ttwrIpIg0KICApLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIkxhcyAxMCBVUFogY29uIG1lbm9yIGRlbnNpZGFkIHBvYmxhY2lvbmFsIg0KKQ0KDQpgYGANCg0KIyMjIyBjLiBDb21wYXJhY2nDs24gZ3LDoWZpY2EgZGUgZGVuc2lkYWQNCg0KYGBge3IgZ3JhZmljby1kZW5zaWRhZH0NCg0KIyBWaXN1YWxpemFyIGxhcyAxMCBVUFogY29uIG1heW9yIGRlbnNpZGFkIHBvYmxhY2lvbmFsDQoNCmdncGxvdCgNCiAgcmFua2luZ19kZW5zaWRhZCAlPiUgc2xpY2VfaGVhZChuID0gMTApLA0KICBhZXMoDQogICAgeCA9IHJlb3JkZXIodXB6X25vbWJyZSwgZGVuc2lkYWRfaGFiX2ttMiksDQogICAgeSA9IGRlbnNpZGFkX2hhYl9rbTINCiAgKQ0KKSArDQoNCiAgZ2VvbV9jb2woDQogICAgZmlsbCA9IHR1cnF1ZXNhLA0KICAgIHdpZHRoID0gMC43DQogICkgKw0KDQogIGNvb3JkX2ZsaXAoKSArDQoNCiAgbGFicygNCiAgICB0aXRsZSA9ICJDb25jZW50cmFjacOzbiBkZSBwb2JsYWNpw7NuIGVuIGxhcyBVUFoiLA0KICAgIHN1YnRpdGxlID0gIlRlcnJpdG9yaW9zIGNvbiBtYXlvciBkZW5zaWRhZCBwb2JsYWNpb25hbCIsDQogICAgeCA9IE5VTEwsDQogICAgeSA9ICJIYWJpdGFudGVzIHBvciBrbcKyIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogQmFzZSBkZSBkYXRvcyBkZWwgdGFsbGVyLiINCiAgKSArDQoNCiAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKA0KICAgICAgYmlnLm1hcmsgPSAiLiIsDQogICAgICBkZWNpbWFsLm1hcmsgPSAiLCINCiAgICApDQogICkgKw0KDQogIHRlbWFfY2xhc2UNCg0KYGBgDQoNCg0KIyMjIDUuMS4zLiBSZWxhY2nDs24gZW50cmUgcG9ibGFjacOzbiB5IGV4dGVuc2nDs24gdGVycml0b3JpYWwNCg0KUGFyYSBjb21wbGVtZW50YXIgZWwgYW7DoWxpc2lzIGFudGVyaW9yLCBzZSBleGFtaW5hDQpsYSByZWxhY2nDs24gZW50cmUgbGEgcG9ibGFjacOzbiB5IGVsIMOhcmVhIGdlb2dyw6FmaWNhDQpkZSBjYWRhIFVQWi4NCg0KRXN0YSBjb21wYXJhY2nDs24gcGVybWl0ZSBvYnNlcnZhciBzaSBsb3MgdGVycml0b3Jpb3MNCmNvbiBtYXlvciBleHRlbnNpw7NuIHRhbWJpw6luIGNvbmNlbnRyYW4gdW5hIG1heW9yDQpjYW50aWRhZCBkZSBoYWJpdGFudGVzIG8gc2kgZXhpc3RlbiBkaWZlcmVuY2lhcw0KaW1wb3J0YW50ZXMgZW4gbGEgb2N1cGFjacOzbiBkZWwgZXNwYWNpby4NCg0KTGEgdmlzdWFsaXphY2nDs24gc2UgcmVhbGl6YSBtZWRpYW50ZSB1biBkaWFncmFtYQ0KZGUgZGlzcGVyc2nDs24sIGVuIGVsIHF1ZSBjYWRhIHB1bnRvIHJlcHJlc2VudGEgdW5hIFVQWi4NCg0KDQpgYGB7ciByZWxhY2lvbi1wb2JsYWNpb24tYXJlYX0NCg0KIyBSZWxhY2nDs24gZW50cmUgcG9ibGFjacOzbiB5IMOhcmVhIHRlcnJpdG9yaWFsDQoNCmdncGxvdCgNCiAgdXB6LA0KICBhZXMoDQogICAgeCA9IGFyZWFfa20yLA0KICAgIHkgPSBwb2JsYWNpb24NCiAgKQ0KKSArDQoNCiAgZ2VvbV9wb2ludCgNCiAgICBjb2xvciA9IG1hZ2VudGEsDQogICAgc2l6ZSA9IDIuOCwNCiAgICBhbHBoYSA9IDAuNzUNCiAgKSArDQoNCiAgZ2VvbV9zbW9vdGgoDQogICAgbWV0aG9kID0gImxtIiwNCiAgICBzZSA9IEZBTFNFLA0KICAgIGNvbG9yID0gbW9yYWRvLA0KICAgIGxpbmV3aWR0aCA9IDAuOQ0KICApICsNCg0KICBsYWJzKA0KICAgIHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBwb2JsYWNpw7NuIHkgw6FyZWEgZGUgbGFzIFVQWiIsDQogICAgc3VidGl0bGUgPSAiQ2FkYSBwdW50byByZXByZXNlbnRhIHVuYSB1bmlkYWQgdGVycml0b3JpYWwiLA0KICAgIHggPSAiw4FyZWEgZGUgbGEgVVBaIChrbcKyKSIsDQogICAgeSA9ICJDYW50aWRhZCBkZSBoYWJpdGFudGVzIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogQmFzZSBkZSBkYXRvcyBkZWwgdGFsbGVyLiINCiAgKSArDQoNCiAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKA0KICAgICAgYmlnLm1hcmsgPSAiLiIsDQogICAgICBkZWNpbWFsLm1hcmsgPSAiLCINCiAgICApDQogICkgKw0KDQogIHRlbWFfY2xhc2UNCg0KYGBgDQoNCiMjIyMgwr9RdcOpIGRlYmVtb3Mgb2JzZXJ2YXI/DQoNCi0gU2kgZXhpc3RlIHVuYSB0ZW5kZW5jaWEgcG9zaXRpdmEgZW50cmUgZWwgw6FyZWEgeSBsYSBwb2JsYWNpw7NuLg0KDQotIFNpIGxhcyBVUFogZGUgbWF5b3IgZXh0ZW5zacOzbiBjb25jZW50cmFuIG5lY2VzYXJpYW1lbnRlIG3DoXMgaGFiaXRhbnRlcy4NCg0KLSBTaSBleGlzdGVuIHRlcnJpdG9yaW9zIHF1ZSBzZSBhcGFydGFuIGRlbCBjb21wb3J0YW1pZW50byBnZW5lcmFsLg0KDQpMYSBsw61uZWEgcmVwcmVzZW50YSB1bmEgdGVuZGVuY2lhIGxpbmVhbCBkZSByZWZlcmVuY2lhLiBObyBzaWduaWZpY2EgcXVlIGVsIMOhcmVhIHRlcnJpdG9yaWFsIGV4cGxpcXVlIHBvciBzw60gc29sYSBsYSBjYW50aWRhZCBkZSBoYWJpdGFudGVzLg0KDQoNCiMjIyA1LjEuNC4gSWRlbnRpZmljYWNpw7NuIGRlIHZhbG9yZXMgZXh0cmVtb3MgZW4gbGEgcG9ibGFjacOzbg0KDQpEdXJhbnRlIGVsIGFuw6FsaXNpcyBkZSBsYSBwb2JsYWNpw7NuIGVzIGltcG9ydGFudGUNCmlkZW50aWZpY2FyIHRlcnJpdG9yaW9zIHF1ZSBwcmVzZW50ZW4gdmFsb3Jlcw0KY29uc2lkZXJhYmxlbWVudGUgZGlmZXJlbnRlcyBhbCBjb21wb3J0YW1pZW50bw0KZ2VuZXJhbCBkZSBsYXMgVVBaLg0KDQpQYXJhIGVsbG8gc2UgdXRpbGl6YSBlbCByYW5nbyBpbnRlcmN1YXJ0w61saWNvIChJUVIpLA0KcXVlIGNvcnJlc3BvbmRlIGEgbGEgZGlmZXJlbmNpYSBlbnRyZSBlbCB0ZXJjZXINCnkgZWwgcHJpbWVyIGN1YXJ0aWwgZGUgbGEgZGlzdHJpYnVjacOzbi4NCg0KTWVkaWFudGUgZXN0ZSBwcm9jZWRpbWllbnRvIHNlIGlkZW50aWZpY2FuIHBvc2libGVzDQp2YWxvcmVzIGF0w61waWNvcywgZW50ZW5kaWRvcyBjb21vIG9ic2VydmFjaW9uZXMgcXVlDQpzZSBlbmN1ZW50cmFuIHBvciBmdWVyYSBkZSBsb3MgbMOtbWl0ZXMgZXN0YWTDrXN0aWNvcw0KZXN0YWJsZWNpZG9zLg0KDQpMYSBpZGVudGlmaWNhY2nDs24gZGUgZXN0b3MgdmFsb3JlcyBubyBzaWduaWZpY2ENCnF1ZSBkZWJhbiBlbGltaW5hcnNlIGRlIGxhIGluZm9ybWFjacOzbi4gUG9yIGVsDQpjb250cmFyaW8sIHBlcm1pdGUgcmVjb25vY2VyIHRlcnJpdG9yaW9zIGNvbg0KY2FyYWN0ZXLDrXN0aWNhcyBwYXJ0aWN1bGFyZXMgcXVlIGRlYmVuIGNvbnNpZGVyYXJzZQ0KZW4gbGFzIGNvbXBhcmFjaW9uZXMgcG9zdGVyaW9yZXMuDQoNCg0KYGBge3IgdmFsb3Jlcy1leHRyZW1vcy1wb2JsYWNpb259DQoNCiMgQ2FsY3VsYXIgbG9zIGzDrW1pdGVzIHBhcmEgaWRlbnRpZmljYXIgcG9zaWJsZXMgdmFsb3JlcyBhdMOtcGljb3MNCg0KcTFfcG9ibGFjaW9uIDwtIHF1YW50aWxlKHVweiRwb2JsYWNpb24sIDAuMjUpDQoNCnEzX3BvYmxhY2lvbiA8LSBxdWFudGlsZSh1cHokcG9ibGFjaW9uLCAwLjc1KQ0KDQppcXJfcG9ibGFjaW9uIDwtIElRUih1cHokcG9ibGFjaW9uKQ0KDQpsaW1pdGVfaW5mZXJpb3IgPC0gcTFfcG9ibGFjaW9uIC0gMS41ICogaXFyX3BvYmxhY2lvbg0KDQpsaW1pdGVfc3VwZXJpb3IgPC0gcTNfcG9ibGFjaW9uICsgMS41ICogaXFyX3BvYmxhY2lvbg0KDQojIElkZW50aWZpY2FyIGxhcyBVUFogcXVlIHNlIGVuY3VlbnRyYW4gZnVlcmEgZGUgbG9zIGzDrW1pdGVzDQoNCnZhbG9yZXNfZXh0cmVtb3MgPC0gdXB6ICU+JQ0KICBmaWx0ZXIoDQogICAgcG9ibGFjaW9uIDwgbGltaXRlX2luZmVyaW9yIHwNCiAgICBwb2JsYWNpb24gPiBsaW1pdGVfc3VwZXJpb3INCiAgKSAlPiUNCiAgc2VsZWN0KA0KICAgIHVwel9ub21icmUsDQogICAgbG9jYWxpZGFkLA0KICAgIHBvYmxhY2lvbiwNCiAgICBhcmVhX2ttMiwNCiAgICBkZW5zaWRhZF9oYWJfa20yDQogICkgJT4lDQogIGFycmFuZ2UoZGVzYyhwb2JsYWNpb24pKQ0KDQojIFByZXNlbnRhciByZXN1bHRhZG9zDQoNCmtuaXRyOjprYWJsZSgNCiAgdmFsb3Jlc19leHRyZW1vcywNCiAgY29sLm5hbWVzID0gYygNCiAgICAiVVBaIiwNCiAgICAiTG9jYWxpZGFkIiwNCiAgICAiSGFiaXRhbnRlcyIsDQogICAgIsOBcmVhIChrbcKyKSIsDQogICAgIkRlbnNpZGFkIChoYWIva23CsikiDQogICksDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiVVBaIGlkZW50aWZpY2FkYXMgY29tbyBwb3NpYmxlcyB2YWxvcmVzIGF0w61waWNvcyBlbiBwb2JsYWNpw7NuIg0KKQ0KDQojIE1vc3RyYXIgbG9zIGzDrW1pdGVzIGVzdGFkw61zdGljb3MNCg0KY2F0KCJMw61taXRlIGluZmVyaW9yOiIsIHJvdW5kKGxpbWl0ZV9pbmZlcmlvciwgMiksICJcbiIpDQoNCmNhdCgiTMOtbWl0ZSBzdXBlcmlvcjoiLCByb3VuZChsaW1pdGVfc3VwZXJpb3IsIDIpLCAiXG4iKQ0KDQpjYXQoIkNhbnRpZGFkIGRlIHBvc2libGVzIHZhbG9yZXMgYXTDrXBpY29zOiIsIG5yb3codmFsb3Jlc19leHRyZW1vcykpDQoNCmBgYA0KDQoNCiMjIyA1LjEuNS4gSW50ZXJwcmV0YWNpw7NuIGRlbCBhbsOhbGlzaXMgZGVtb2dyw6FmaWNvDQoNCkVsIGFuw6FsaXNpcyBkZW1vZ3LDoWZpY28gcGVybWl0ZSByZWNvbm9jZXIgcXVlIGxhcyBVUFoNCnByZXNlbnRhbiBjYXJhY3RlcsOtc3RpY2FzIGRpZmVyZW50ZXMgZW4gY3VhbnRvIGEgc3UNCnBvYmxhY2nDs24sIGV4dGVuc2nDs24geSBkZW5zaWRhZC4NCg0KRXN0YXMgZGlmZXJlbmNpYXMgc29uIHJlbGV2YW50ZXMgcGFyYSBlbCBkZXNhcnJvbGxvDQpkZSBsYSBpbnZlc3RpZ2FjacOzbiwgZGViaWRvIGEgcXVlIGxvcyBpbmRpY2Fkb3Jlcw0KZGUgc2VndXJpZGFkIHB1ZWRlbiBwcmVzZW50YXIgY29tcG9ydGFtaWVudG9zDQpkaXN0aW50b3MgZGVwZW5kaWVuZG8gZGVsIHRhbWHDsW8geSBsYXMgY2FyYWN0ZXLDrXN0aWNhcw0KZGUgY2FkYSB0ZXJyaXRvcmlvLg0KDQpMYSBpZGVudGlmaWNhY2nDs24gZGUgcG9zaWJsZXMgdmFsb3JlcyBleHRyZW1vcyB0YW1iacOpbg0KcGVybWl0ZSByZWNvbm9jZXIgcXVlIGFsZ3VuYXMgVVBaIHB1ZWRlbiB0ZW5lcg0KY29uZGljaW9uZXMgcGFydGljdWxhcmVzIHF1ZSByZXF1aWVyZW4gdW4gdHJhdGFtaWVudG8NCmRpZmVyZW5jaWFkbyBhbCBtb21lbnRvIGRlIHJlYWxpemFyIGNvbXBhcmFjaW9uZXMNCmVzdGFkw61zdGljYXMuDQoNCkEgcGFydGlyIGRlIGVzdG9zIHJlc3VsdGFkb3Mgc2Vyw6EgcG9zaWJsZSBlc3RhYmxlY2VyDQp1bmEgYmFzZSBtw6FzIHPDs2xpZGEgcGFyYSBhbmFsaXphciBsb3MgaW5kaWNhZG9yZXMNCmRlIGRlbGl0b3MsIGRpZmVyZW5jaWFuZG8gbGFzIGNhbnRpZGFkZXMgYWJzb2x1dGFzDQpkZSBsYXMgdGFzYXMgY2FsY3VsYWRhcyBwb3IgaGFiaXRhbnRlLg0KDQojIyMgNS4yLiBBbsOhbGlzaXMgZGUgdml2aWVuZGEgZSBpbmZyYWVzdHJ1Y3R1cmENCg0KRW4gZXN0ZSBhcGFydGFkbyBzZSBhbmFsaXphbiBsYXMgY29uZGljaW9uZXMgZGUgdml2aWVuZGEgeSBsYSBpbmZyYWVzdHJ1Y3R1cmEgZGUgYWx1bWJyYWRvIHDDumJsaWNvIGRlIGxhcyBVUFogZGUgQm9nb3TDoS4gRXN0YXMgdmFyaWFibGVzIHBlcm1pdGVuIGFtcGxpYXIgbGEgY2FyYWN0ZXJpemFjacOzbiB0ZXJyaXRvcmlhbCwgaW5jb3Jwb3JhbmRvIGFzcGVjdG9zIHJlbGFjaW9uYWRvcyBjb24gbGEgb2N1cGFjacOzbiByZXNpZGVuY2lhbCB5IGxhcyBjb25kaWNpb25lcyBmw61zaWNhcyBkZWwgZW50b3JubyB1cmJhbm8uDQoNClNlIGNvbnNpZGVyYW4gdmFyaWFibGVzIGNvbW8gbGEgY2FudGlkYWQgZGUgdml2aWVuZGFzLCBlbCBwb3JjZW50YWplIGRlIHZpdmllbmRhcyBkZXNvY3VwYWRhcywgZWwgbsO6bWVybyBkZSBwZXJzb25hcyBwb3Igdml2aWVuZGEgeSBsYSBkaXNwb25pYmlsaWRhZCBkZSBsdW1pbmFyaWFzIHBvciB1bmlkYWQgZGUgc3VwZXJmaWNpZS4NCg0KRWwgYW7DoWxpc2lzIGJ1c2NhIGlkZW50aWZpY2FyIGRpZmVyZW5jaWFzIGVudHJlIHRlcnJpdG9yaW9zIHkgZXhwbG9yYXIgcG9zaWJsZXMgcGF0cm9uZXMgcXVlIHBvc3Rlcmlvcm1lbnRlIHB1ZWRhbiBjb250cmFzdGFyc2UgY29uIGxvcyBpbmRpY2Fkb3JlcyBkZSBzZWd1cmlkYWQuDQoNCiMjIyMgNS4yLjEuIENhcmFjdGVyaXphY2nDs24gZGUgbGFzIHZpdmllbmRhcw0KDQpJbmljaWFsbWVudGUgc2UgcmVhbGl6YSB1bmEgZGVzY3JpcGNpw7NuIGVzdGFkw61zdGljYSBkZSBsYXMgdmFyaWFibGVzIHJlbGFjaW9uYWRhcyBjb24gbGEgdml2aWVuZGEuIFNlIGNvbnNpZGVyYW4gbGEgY2FudGlkYWQgdG90YWwgZGUgdml2aWVuZGFzLCBsYXMgdml2aWVuZGFzIG9jdXBhZGFzLCBlbCBwb3JjZW50YWplIGRlIHZpdmllbmRhcyBkZXNvY3VwYWRhcyB5IGVsIHByb21lZGlvIGRlIHBlcnNvbmFzIHBvciB2aXZpZW5kYS4NCg0KRWwgcHJvcMOzc2l0byBlcyByZWNvbm9jZXIgY8OzbW8gc2UgZGlzdHJpYnV5ZW4gZXN0YXMgY2FyYWN0ZXLDrXN0aWNhcyBlbnRyZSBsYXMgVVBaIGUgaWRlbnRpZmljYXIgcG9zaWJsZXMgZGlmZXJlbmNpYXMgdGVycml0b3JpYWxlcy4NCg0KYGBge3IgZXN0YWRpc3RpY2FzX3ZpdmllbmRhLCBlY2hvPVRSVUV9DQplc3RhZGlzdGljYXNfdml2aWVuZGEgPC0gdXB6ICU+JQ0KICBzdW1tYXJpc2UoDQogICAgVG90YWxfVVBaID0gbigpLA0KDQogICAgTWVkaWFfdml2aWVuZGFzID0gbWVhbih2aXZpZW5kYXNfdG90YWxlcyksDQogICAgTWVkaWFuYV92aXZpZW5kYXMgPSBtZWRpYW4odml2aWVuZGFzX3RvdGFsZXMpLA0KICAgIERlc3Zfdml2aWVuZGFzID0gc2Qodml2aWVuZGFzX3RvdGFsZXMpLA0KICAgIFExX3ZpdmllbmRhcyA9IHF1YW50aWxlKHZpdmllbmRhc190b3RhbGVzLCAwLjI1KSwNCiAgICBRM192aXZpZW5kYXMgPSBxdWFudGlsZSh2aXZpZW5kYXNfdG90YWxlcywgMC43NSksDQoNCiAgICBNZWRpYV9vY3VwYWRhcyA9IG1lYW4odml2aWVuZGFzX29jdXBhZGFzKSwNCiAgICBNZWRpYW5hX29jdXBhZGFzID0gbWVkaWFuKHZpdmllbmRhc19vY3VwYWRhcyksDQoNCiAgICBNZWRpYV9kZXNvY3VwYWNpb24gPSBtZWFuKHBjdF92aXZpZW5kYXNfZGVzb2N1cGFkYXMpLA0KICAgIE1lZGlhbmFfZGVzb2N1cGFjaW9uID0gbWVkaWFuKHBjdF92aXZpZW5kYXNfZGVzb2N1cGFkYXMpLA0KDQogICAgTWVkaWFfcGVyc29uYXMgPSBtZWFuKHBlcnNvbmFzX3Bvcl92aXZpZW5kYSksDQogICAgTWVkaWFuYV9wZXJzb25hcyA9IG1lZGlhbihwZXJzb25hc19wb3Jfdml2aWVuZGEpDQogICkNCg0Ka25pdHI6OmthYmxlKA0KICBlc3RhZGlzdGljYXNfdml2aWVuZGEsDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiRXN0YWTDrXN0aWNhcyBkZXNjcmlwdGl2YXMgZGUgbGFzIHZhcmlhYmxlcyBkZSB2aXZpZW5kYSINCikNCmBgYA0KDQojIyMgNS4yLjIuIERpc3RyaWJ1Y2nDs24gZGUgdml2aWVuZGFzIGRlc29jdXBhZGFzDQoNCkVsIHBvcmNlbnRhamUgZGUgdml2aWVuZGFzIGRlc29jdXBhZGFzIHBlcm1pdGUgb2JzZXJ2YXIgcXXDqSBwcm9wb3JjacOzbiBkZSBsYXMgdml2aWVuZGFzIGRlIGNhZGEgVVBaIG5vIHNlIGVuY3VlbnRyYSBvY3VwYWRhLg0KDQpTZSB1dGlsaXphIHVuIGhpc3RvZ3JhbWEgcGFyYSBleGFtaW5hciBsYSBkaXN0cmlidWNpw7NuIGRlIGVzdGEgdmFyaWFibGUsIGlkZW50aWZpY2FyIHN1IGNvbmNlbnRyYWNpw7NuIHkgcmVjb25vY2VyIHNpIGV4aXN0ZW4gdGVycml0b3Jpb3MgY29uIHBvcmNlbnRhamVzIGNvbnNpZGVyYWJsZW1lbnRlIGRpZmVyZW50ZXMgYWwgY29tcG9ydGFtaWVudG8gZ2VuZXJhbC4NCg0KYGBge3IgZGlzdHJpYnVjaW9uX3ZpdmllbmRhc19kZXNvY3VwYWRhcywgZWNobz1UUlVFfQ0KZ2dwbG90KHVweiwgYWVzKHggPSBwY3Rfdml2aWVuZGFzX2Rlc29jdXBhZGFzKSkgKw0KICBnZW9tX2hpc3RvZ3JhbSgNCiAgICBiaW5zID0gMjAsDQogICAgZmlsbCA9IG1hZ2VudGEsDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIGFscGhhID0gMC45DQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgdml2aWVuZGFzIGRlc29jdXBhZGFzIHBvciBVUFoiLA0KICAgIHN1YnRpdGxlID0gIlBvcmNlbnRhamUgZGUgdml2aWVuZGFzIGRlc29jdXBhZGFzIGVuIGNhZGEgdGVycml0b3JpbyIsDQogICAgeCA9ICJQb3JjZW50YWplIGRlIHZpdmllbmRhcyBkZXNvY3VwYWRhcyIsDQogICAgeSA9ICJDYW50aWRhZCBkZSBVUFoiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBpbmZvcm1hY2nDs24gY29uc29saWRhZGEgZW4gbGEgYmFzZSBVUFouIg0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQoNClBhcmEgY29tcGxlbWVudGFyIGxhIGRpc3RyaWJ1Y2nDs24gZ2VuZXJhbCwgc2UgaWRlbnRpZmljYW4gbGFzIGRpZXogVVBaIGNvbiBtYXlvcmVzIHkgbWVub3JlcyBwb3JjZW50YWplcyBkZSB2aXZpZW5kYXMgZGVzb2N1cGFkYXMuIEVzdG8gcGVybWl0ZSByZWNvbm9jZXIgbG9zIHRlcnJpdG9yaW9zIHF1ZSBwcmVzZW50YW4gbG9zIHZhbG9yZXMgZXh0cmVtb3MgZGUgZXN0YSBjYXJhY3RlcsOtc3RpY2EuDQoNCmBgYHtyIHJhbmtpbmdfdml2aWVuZGFzX2Rlc29jdXBhZGFzLCBlY2hvPVRSVUV9DQptYXlvcl9kZXNvY3VwYWNpb24gPC0gdXB6ICU+JQ0KICBhcnJhbmdlKGRlc2MocGN0X3ZpdmllbmRhc19kZXNvY3VwYWRhcykpICU+JQ0KICBzZWxlY3QoDQogICAgdXB6X25vbWJyZSwNCiAgICBsb2NhbGlkYWQsDQogICAgdml2aWVuZGFzX3RvdGFsZXMsDQogICAgdml2aWVuZGFzX29jdXBhZGFzLA0KICAgIHBjdF92aXZpZW5kYXNfZGVzb2N1cGFkYXMNCiAgKSAlPiUNCiAgc2xpY2VfaGVhZChuID0gMTApDQoNCm1lbm9yX2Rlc29jdXBhY2lvbiA8LSB1cHogJT4lDQogIGFycmFuZ2UocGN0X3ZpdmllbmRhc19kZXNvY3VwYWRhcykgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICB2aXZpZW5kYXNfdG90YWxlcywNCiAgICB2aXZpZW5kYXNfb2N1cGFkYXMsDQogICAgcGN0X3ZpdmllbmRhc19kZXNvY3VwYWRhcw0KICApICU+JQ0KICBzbGljZV9oZWFkKG4gPSAxMCkNCg0Ka25pdHI6OmthYmxlKA0KICBtYXlvcl9kZXNvY3VwYWNpb24sDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiRGlleiBVUFogY29uIG1heW9yIHBvcmNlbnRhamUgZGUgdml2aWVuZGFzIGRlc29jdXBhZGFzIg0KKQ0KDQprbml0cjo6a2FibGUoDQogIG1lbm9yX2Rlc29jdXBhY2lvbiwNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJEaWV6IFVQWiBjb24gbWVub3IgcG9yY2VudGFqZSBkZSB2aXZpZW5kYXMgZGVzb2N1cGFkYXMiDQopDQpgYGANCg0KIyMjIDUuMi4zLiBBbsOhbGlzaXMgZGVsIGFsdW1icmFkbyBww7pibGljbw0KDQpFbCBhbHVtYnJhZG8gcMO6YmxpY28gY29uc3RpdHV5ZSB1bmEgY2FyYWN0ZXLDrXN0aWNhIHJlbGV2YW50ZSBkZSBsYSBpbmZyYWVzdHJ1Y3R1cmEgdXJiYW5hIHkgcGVybWl0ZSBkZXNjcmliaXIgbGFzIGNvbmRpY2lvbmVzIGbDrXNpY2FzIGRlIGxvcyB0ZXJyaXRvcmlvcy4NCg0KUGFyYSBlc3RlIGFuw6FsaXNpcyBzZSBjb25zaWRlcmFuIHRyZXMgdmFyaWFibGVzOiBjYW50aWRhZCBkZSBsdW1pbmFyaWFzLCBkZW5zaWRhZCBkZSBsdW1pbmFyaWFzIHBvciBraWzDs21ldHJvIGN1YWRyYWRvIHkgcG9yY2VudGFqZSBkZSBsdW1pbmFyaWFzIGNvbiB0ZWNub2xvZ8OtYSBMRUQuDQoNClNlIGRpZmVyZW5jaWEgZW50cmUgbGEgY2FudGlkYWQgdG90YWwgZGUgbHVtaW5hcmlhcyB5IHN1IGRlbnNpZGFkIHRlcnJpdG9yaWFsLCBkZWJpZG8gYSBxdWUgbGFzIFVQWiBwcmVzZW50YW4gZXh0ZW5zaW9uZXMgZ2VvZ3LDoWZpY2FzIGRpc3RpbnRhcy4gTGEgZGVuc2lkYWQgcGVybWl0ZSByZWFsaXphciB1bmEgY29tcGFyYWNpw7NuIHF1ZSBjb25zaWRlcmEgZWwgdGFtYcOxbyBkZWwgdGVycml0b3Jpby4NCg0KYGBge3IgZXN0YWRpc3RpY2FzX2FsdW1icmFkbywgZWNobz1UUlVFfQ0KZXN0YWRpc3RpY2FzX2FsdW1icmFkbyA8LSB1cHogJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYV9sdW1pbmFyaWFzID0gbWVhbihsdW1pbmFyaWFzKSwNCiAgICBNZWRpYW5hX2x1bWluYXJpYXMgPSBtZWRpYW4obHVtaW5hcmlhcyksDQogICAgRGVzdl9sdW1pbmFyaWFzID0gc2QobHVtaW5hcmlhcyksDQogICAgUTFfbHVtaW5hcmlhcyA9IHF1YW50aWxlKGx1bWluYXJpYXMsIDAuMjUpLA0KICAgIFEzX2x1bWluYXJpYXMgPSBxdWFudGlsZShsdW1pbmFyaWFzLCAwLjc1KSwNCg0KICAgIE1lZGlhX2x1bWluYXJpYXNfa20yID0gbWVhbihsdW1pbmFyaWFzX2ttMiksDQogICAgTWVkaWFuYV9sdW1pbmFyaWFzX2ttMiA9IG1lZGlhbihsdW1pbmFyaWFzX2ttMiksDQoNCiAgICBNZWRpYV9sZWQgPSBtZWFuKHBjdF9sdW1pbmFyaWFzX2xlZCksDQogICAgTWVkaWFuYV9sZWQgPSBtZWRpYW4ocGN0X2x1bWluYXJpYXNfbGVkKQ0KICApDQoNCmtuaXRyOjprYWJsZSgNCiAgZXN0YWRpc3RpY2FzX2FsdW1icmFkbywNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJFc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcyBkZWwgYWx1bWJyYWRvIHDDumJsaWNvIg0KKQ0KYGBgDQoNCiMjIyA1LjIuNC4gRGlzdHJpYnVjacOzbiBkZSBsYSBkZW5zaWRhZCBkZSBsdW1pbmFyaWFzDQoNClNlIGFuYWxpemEgbGEgZGlzdHJpYnVjacOzbiBkZSBsdW1pbmFyaWFzIHBvciBraWzDs21ldHJvIGN1YWRyYWRvIG1lZGlhbnRlIHVuIGhpc3RvZ3JhbWEuIEVzdGEgcmVwcmVzZW50YWNpw7NuIHBlcm1pdGUgb2JzZXJ2YXIgY8OzbW8gc2UgY29uY2VudHJhIGxhIGluZnJhZXN0cnVjdHVyYSBkZSBhbHVtYnJhZG8gZW50cmUgbGFzIFVQWiB5IHJlY29ub2NlciBwb3NpYmxlcyBkaWZlcmVuY2lhcyB0ZXJyaXRvcmlhbGVzLg0KDQpFc3RhIHZhcmlhYmxlIHJlc3VsdGEgZXNwZWNpYWxtZW50ZSDDunRpbCBwb3JxdWUgcGVybWl0ZSBjb21wYXJhciBsYSBkaXNwb25pYmlsaWRhZCBkZSBsdW1pbmFyaWFzIHRlbmllbmRvIGVuIGN1ZW50YSBsYSBleHRlbnNpw7NuIGdlb2dyw6FmaWNhIGRlIGNhZGEgVVBaLg0KDQpgYGB7ciBkaXN0cmlidWNpb25fZGVuc2lkYWRfbHVtaW5hcmlhcywgZWNobz1UUlVFfQ0KZ2dwbG90KHVweiwgYWVzKHggPSBsdW1pbmFyaWFzX2ttMikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oDQogICAgYmlucyA9IDIwLA0KICAgIGZpbGwgPSB0dXJxdWVzYSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgYWxwaGEgPSAwLjkNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBsYSBkZW5zaWRhZCBkZSBsdW1pbmFyaWFzIiwNCiAgICBzdWJ0aXRsZSA9ICJDYW50aWRhZCBkZSBsdW1pbmFyaWFzIHBvciBraWzDs21ldHJvIGN1YWRyYWRvIGVuIGNhZGEgVVBaIiwNCiAgICB4ID0gIkx1bWluYXJpYXMgcG9yIGttwrIiLA0KICAgIHkgPSAiQ2FudGlkYWQgZGUgVVBaIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogaW5mb3JtYWNpw7NuIGRlIGFsdW1icmFkbyBww7pibGljbywgw7psdGltYSBhY3R1YWxpemFjacOzbiAyMDIxLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQpQYXJhIGlkZW50aWZpY2FyIGxhcyBkaWZlcmVuY2lhcyB0ZXJyaXRvcmlhbGVzLCBzZSBjb25zdHJ1eWVuIGRvcyByYW5raW5ncyBxdWUgcGVybWl0ZW4gcmVjb25vY2VyIGxhcyBkaWV6IFVQWiBjb24gbWF5b3IgeSBtZW5vciBkZW5zaWRhZCBkZSBsdW1pbmFyaWFzLiBTZSBpbmNsdXllbiB0YW1iacOpbiBlbCDDoXJlYSB5IGxhIGNhbnRpZGFkIHRvdGFsIGRlIGx1bWluYXJpYXMgcGFyYSBmYWNpbGl0YXIgbGEgY29tcGFyYWNpw7NuLg0KDQpgYGB7ciByYW5raW5nX2RlbnNpZGFkX2x1bWluYXJpYXMsIGVjaG89VFJVRX0NCm1heW9yX2FsdW1icmFkbyA8LSB1cHogJT4lDQogIGFycmFuZ2UoZGVzYyhsdW1pbmFyaWFzX2ttMikpICU+JQ0KICBzZWxlY3QoDQogICAgdXB6X25vbWJyZSwNCiAgICBsb2NhbGlkYWQsDQogICAgYXJlYV9rbTIsDQogICAgbHVtaW5hcmlhcywNCiAgICBsdW1pbmFyaWFzX2ttMiwNCiAgICBwY3RfbHVtaW5hcmlhc19sZWQNCiAgKSAlPiUNCiAgc2xpY2VfaGVhZChuID0gMTApDQoNCm1lbm9yX2FsdW1icmFkbyA8LSB1cHogJT4lDQogIGFycmFuZ2UobHVtaW5hcmlhc19rbTIpICU+JQ0KICBzZWxlY3QoDQogICAgdXB6X25vbWJyZSwNCiAgICBsb2NhbGlkYWQsDQogICAgYXJlYV9rbTIsDQogICAgbHVtaW5hcmlhcywNCiAgICBsdW1pbmFyaWFzX2ttMiwNCiAgICBwY3RfbHVtaW5hcmlhc19sZWQNCiAgKSAlPiUNCiAgc2xpY2VfaGVhZChuID0gMTApDQoNCmtuaXRyOjprYWJsZSgNCiAgbWF5b3JfYWx1bWJyYWRvLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIkRpZXogVVBaIGNvbiBtYXlvciBkZW5zaWRhZCBkZSBsdW1pbmFyaWFzIg0KKQ0KDQprbml0cjo6a2FibGUoDQogIG1lbm9yX2FsdW1icmFkbywNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJEaWV6IFVQWiBjb24gbWVub3IgZGVuc2lkYWQgZGUgbHVtaW5hcmlhcyINCikNCmBgYA0KDQojIyMgNS4yLjUuIFJlbGFjacOzbiBlbnRyZSB2aXZpZW5kYXMgZGVzb2N1cGFkYXMgeSBhbHVtYnJhZG8gcMO6YmxpY28NCg0KRmluYWxtZW50ZSwgc2UgZXhwbG9yYSBsYSByZWxhY2nDs24gZW50cmUgZWwgcG9yY2VudGFqZSBkZSB2aXZpZW5kYXMgZGVzb2N1cGFkYXMgeSBsYSBkZW5zaWRhZCBkZSBsdW1pbmFyaWFzIHBvciBraWzDs21ldHJvIGN1YWRyYWRvLg0KDQpFc3RhIGNvbXBhcmFjacOzbiBwZXJtaXRlIG9ic2VydmFyIHNpIGV4aXN0ZW4gcGF0cm9uZXMgZW50cmUgYW1iYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZWwgZW50b3JubyB1cmJhbm8uIFNlIGluY29ycG9yYSB1bmEgbMOtbmVhIGRlIHRlbmRlbmNpYSBjb21vIGFwb3lvIHZpc3VhbCBwYXJhIGlkZW50aWZpY2FyIGVsIGNvbXBvcnRhbWllbnRvIGdlbmVyYWwgZGUgbG9zIGRhdG9zLg0KDQpFc3RlIGVqZXJjaWNpbyB0aWVuZSB1biBhbGNhbmNlIGV4cGxvcmF0b3JpbyB5IG5vIHBlcm1pdGUgZXN0YWJsZWNlciByZWxhY2lvbmVzIGRlIGNhdXNhbGlkYWQuDQoNCmBgYHtyIHJlbGFjaW9uX3ZpdmllbmRhX2FsdW1icmFkbywgZWNobz1UUlVFfQ0KZ2dwbG90KA0KICB1cHosDQogIGFlcygNCiAgICB4ID0gcGN0X3ZpdmllbmRhc19kZXNvY3VwYWRhcywNCiAgICB5ID0gbHVtaW5hcmlhc19rbTINCiAgKQ0KKSArDQogIGdlb21fcG9pbnQoDQogICAgY29sb3IgPSBtb3JhZG8sDQogICAgYWxwaGEgPSAwLjcsDQogICAgc2l6ZSA9IDIuNQ0KICApICsNCiAgZ2VvbV9zbW9vdGgoDQogICAgbWV0aG9kID0gImxtIiwNCiAgICBzZSA9IEZBTFNFLA0KICAgIGNvbG9yID0gbWFnZW50YSwNCiAgICBsaW5ld2lkdGggPSAxDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlZpdmllbmRhcyBkZXNvY3VwYWRhcyB5IGRlbnNpZGFkIGRlIGFsdW1icmFkbyIsDQogICAgc3VidGl0bGUgPSAiUmVsYWNpw7NuIGV4cGxvcmF0b3JpYSBlbnRyZSBjYXJhY3RlcsOtc3RpY2FzIGRlbCBlbnRvcm5vIHVyYmFubyIsDQogICAgeCA9ICJQb3JjZW50YWplIGRlIHZpdmllbmRhcyBkZXNvY3VwYWRhcyIsDQogICAgeSA9ICJMdW1pbmFyaWFzIHBvciBrbcKyIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogaW5mb3JtYWNpw7NuIGNvbnNvbGlkYWRhIGRlIGxhcyBVUFouIg0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQoNCiMjIyA1LjIuNi4gSW50ZXJwcmV0YWNpw7NuIGRlIHJlc3VsdGFkb3MNCg0KTG9zIHJlc3VsdGFkb3MgZGUgZXN0ZSBhcGFydGFkbyBwZXJtaXRlbiBjb21wbGVtZW50YXIgbGEgY2FyYWN0ZXJpemFjacOzbiB0ZXJyaXRvcmlhbCBkZSBsYXMgVVBaIG1lZGlhbnRlIHZhcmlhYmxlcyByZWxhY2lvbmFkYXMgY29uIGxhcyBjb25kaWNpb25lcyBkZSB2aXZpZW5kYSB5IGxhIGluZnJhZXN0cnVjdHVyYSBkZSBhbHVtYnJhZG8gcMO6YmxpY28uDQoNCkxhIGludGVycHJldGFjacOzbiBzZSBjZW50cmFyw6EgZW4gbGFzIGRpZmVyZW5jaWFzIG9ic2VydmFkYXMgZW50cmUgdGVycml0b3Jpb3MsIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbGFzIHZhcmlhYmxlcyB5IGxvcyBwb3NpYmxlcyBwYXRyb25lcyBpZGVudGlmaWNhZG9zIGVuIGxhIGNvbXBhcmFjacOzbiBlbnRyZSB2aXZpZW5kYXMgZGVzb2N1cGFkYXMgeSBkZW5zaWRhZCBkZSBsdW1pbmFyaWFzLg0KDQpTZSB0ZW5kcsOhIGVuIGN1ZW50YSBxdWUgZXN0b3MgaW5kaWNhZG9yZXMgZGVzY3JpYmVuIGNhcmFjdGVyw61zdGljYXMgZGVsIGVudG9ybm8gdXJiYW5vIHkgcXVlLCBwb3Igc8OtIHNvbG9zLCBubyBwZXJtaXRlbiBleHBsaWNhciBuaSBlc3RhYmxlY2VyIGNhdXNhcyBkZWwgY29tcG9ydGFtaWVudG8gZGVsaWN0aXZvLg0KDQojIyA1LjMuIEFuw6FsaXNpcyBzb2Npb2Vjb27Ds21pY28NCg0KRW4gZXN0YSBzZWNjacOzbiBzZSBleHBsb3JhbiBsYXMgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcyBkZSBsYXMgVVBaIGRlIEJvZ290w6EgYSBwYXJ0aXIgZGUgbGEgaW5mb3JtYWNpw7NuIGRlIGxhIEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byBkZSAyMDIxLg0KDQpTZSBhbmFsaXphbiB2YXJpYWJsZXMgcmVsYWNpb25hZGFzIGNvbiBsYSBwb2JyZXphLCBlbCBpbmdyZXNvIHByb21lZGlvLCBsYSBjb21wb3NpY2nDs24gcG9yIGVzdHJhdG8gc29jaW9lY29uw7NtaWNvIHkgZWwgbml2ZWwgZWR1Y2F0aXZvIGRlIGxhIHBvYmxhY2nDs24uIEVzdGFzIGNhcmFjdGVyw61zdGljYXMgcGVybWl0ZW4gYW1wbGlhciBsYSBjb21wcmVuc2nDs24gZGUgbGFzIGRpZmVyZW5jaWFzIHRlcnJpdG9yaWFsZXMgZSBpbmNvcnBvcmFyIGVsZW1lbnRvcyBzb2NpYWxlcyB5IGVjb27Ds21pY29zIGFsIGFuw6FsaXNpcyBkZSBsYSBpbnNlZ3VyaWRhZC4NCg0KRWwgcHJvcMOzc2l0byBlcyBpZGVudGlmaWNhciBjw7NtbyBzZSBkaXN0cmlidXllbiBlc3RhcyBjb25kaWNpb25lcyBlbnRyZSBsYXMgVVBaIHkgcmVjb25vY2VyIHBvc2libGVzIHBhdHJvbmVzIHF1ZSBwb3N0ZXJpb3JtZW50ZSBwdWVkYW4gY29udHJhc3RhcnNlIGNvbiBsb3MgaW5kaWNhZG9yZXMgZGUgZGVsaXRvcyB5IHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkLg0KDQpFcyBpbXBvcnRhbnRlIHRlbmVyIGVuIGN1ZW50YSBxdWUgbGEgRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvIHByZXNlbnRhIGluZm9ybWFjacOzbiBhZ3J1cGFkYSBwYXJhIDMyIFVQWi4gRW4gZXN0b3MgY2Fzb3MsIHZhcmlhcyB1bmlkYWRlcyB0ZXJyaXRvcmlhbGVzIGNvbXBhcnRlbiBlbCBtaXNtbyB2YWxvciBlc3RpbWFkby4gUG9yIGVzdGEgcmF6w7NuLCBsb3MgcmVzdWx0YWRvcyBkZWJlbiBpbnRlcnByZXRhcnNlIGNvbiBwcmVjYXVjacOzbiB5IG5vIGFzdW1pciBxdWUgY2FkYSByZWdpc3RybyByZXByZXNlbnRhIHVuYSBvYnNlcnZhY2nDs24gc29jaW9lY29uw7NtaWNhIGluZGVwZW5kaWVudGUuDQoNCiMjIyA1LjMuMS4gUmV2aXNpw7NuIGRlIGxhIGluZm9ybWFjacOzbiBzb2Npb2Vjb27Ds21pY2ENCg0KQW50ZXMgZGUgYW5hbGl6YXIgbGFzIHZhcmlhYmxlcyBzb2Npb2Vjb27Ds21pY2FzLCBzZSByZXZpc2EgbGEgY29iZXJ0dXJhIGRlIGxhIGluZm9ybWFjacOzbiBkZSBsYSBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8uDQoNCkVzdGEgdmVyaWZpY2FjacOzbiBwZXJtaXRlIGlkZW50aWZpY2FyIGN1w6FudGFzIFVQWiBjdWVudGFuIGNvbiBpbmZvcm1hY2nDs24gaW5kaXZpZHVhbCB5IGN1w6FudGFzIHJlY2liZW4gdmFsb3JlcyBjb21wYXJ0aWRvcyBjb24gb3RyYXMgdW5pZGFkZXMgdGVycml0b3JpYWxlcy4gRXN0YSBkaXN0aW5jacOzbiBlcyBpbXBvcnRhbnRlIHBhcmEgaW50ZXJwcmV0YXIgY29ycmVjdGFtZW50ZSBsYXMgZXN0YWTDrXN0aWNhcyB5IGV2aXRhciBhc3VtaXIgcXVlIHRvZG9zIGxvcyByZWdpc3Ryb3MgcmVwcmVzZW50YW4gbWVkaWNpb25lcyBpbmRlcGVuZGllbnRlcy4NCg0KYGBge3IgcmV2aXNpb24tZW5jdWVzdGEtbXVsdGlwcm9wb3NpdG8sIGVjaG89VFJVRX0NCiMgUmV2aXNhciBsYSBjYW50aWRhZCBkZSBVUFogY29uIGluZm9ybWFjacOzbiBpbmRpdmlkdWFsIHkgYWdydXBhZGENCg0KcmV2aXNpb25fZW5jdWVzdGEgPC0gdXB6ICU+JQ0KICBjb3VudChlbV9hZ3J1cGFkYSkgJT4lDQogIG11dGF0ZSgNCiAgICBUaXBvX2luZm9ybWFjaW9uID0gaWZfZWxzZSgNCiAgICAgIGVtX2FncnVwYWRhLA0KICAgICAgIkluZm9ybWFjacOzbiBhZ3J1cGFkYSIsDQogICAgICAiSW5mb3JtYWNpw7NuIGluZGl2aWR1YWwiDQogICAgKSwNCiAgICBQb3JjZW50YWplID0gbiAvIHN1bShuKSAqIDEwMA0KICApICU+JQ0KICBzZWxlY3QoDQogICAgVGlwb19pbmZvcm1hY2lvbiwNCiAgICBDYW50aWRhZF9VUFogPSBuLA0KICAgIFBvcmNlbnRhamUNCiAgKQ0KDQprbml0cjo6a2FibGUoDQogIHJldmlzaW9uX2VuY3Vlc3RhLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIkNvYmVydHVyYSBkZSBsYSBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8gcG9yIHRpcG8gZGUgaW5mb3JtYWNpw7NuIg0KKQ0KYGBgDQoNCiMjIyMgwr9RdcOpIGJ1c2NhbW9zIGlkZW50aWZpY2FyPw0KDQotIExhIGNhbnRpZGFkIGRlIFVQWiBxdWUgdGllbmVuIGluZm9ybWFjacOzbiBpbmRpdmlkdWFsLg0KDQotIExhIGNhbnRpZGFkIGRlIFVQWiBxdWUgY29tcGFydGVuIGluZm9ybWFjacOzbiBjb24gb3RyYXMgdW5pZGFkZXMgdGVycml0b3JpYWxlcy4NCg0KLSBMYSBwcm9wb3JjacOzbiBxdWUgcmVwcmVzZW50YSBjYWRhIGdydXBvIHNvYnJlIGVsIHRvdGFsIGRlIFVQWi4NCg0KIyMjIDUuMy4yLiBFc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcyBkZSBsYXMgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcw0KDQpQYXJhIGNhcmFjdGVyaXphciBsYXMgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcyBzZSBzZWxlY2Npb25hbiB2YXJpYWJsZXMgcmVsYWNpb25hZGFzIGNvbiBsYSBwb2JyZXphLCBsb3MgaW5ncmVzb3MsIGxhIGNvbXBvc2ljacOzbiBwb3IgZXN0cmF0byB5IGVsIG5pdmVsIGVkdWNhdGl2by4NCg0KU2UgY2FsY3VsYW4gbWVkaWRhcyBkZSB0ZW5kZW5jaWEgY2VudHJhbCB5IGRpc3BlcnNpw7NuLCBpbmNsdXllbmRvIG1lZGlhLCBtZWRpYW5hLCBkZXN2aWFjacOzbiBlc3TDoW5kYXIsIGN1YXJ0aWxlcywgdmFsb3JlcyBtw61uaW1vcyB5IG3DoXhpbW9zLiBFc3RhcyBtZWRpZGFzIHBlcm1pdGVuIHJlY29ub2NlciBsYXMgZGlmZXJlbmNpYXMgZW50cmUgdGVycml0b3Jpb3MgeSBvYnNlcnZhciBxdcOpIHRhbiBjb25jZW50cmFkb3MgbyBkaXNwZXJzb3Mgc2UgZW5jdWVudHJhbiBsb3MgaW5kaWNhZG9yZXMuDQoNCkxhIHNlbGVjY2nDs24gZGUgZXN0YXMgdmFyaWFibGVzIGJ1c2NhIHJlcHJlc2VudGFyIGRpZmVyZW50ZXMgZGltZW5zaW9uZXMgZGUgbGFzIGNvbmRpY2lvbmVzIGRlIHZpZGEsIGV2aXRhbmRvIGxpbWl0YXIgZWwgYW7DoWxpc2lzIGEgdW5hIHNvbGEgY2FyYWN0ZXLDrXN0aWNhIGVjb27Ds21pY2EuDQoNCmBgYHtyIGVzdGFkaXN0aWNhcy1zb2Npb2Vjb25vbWljYXMsIGVjaG89VFJVRX0NCiMgU2VsZWNjaW9uYXIgbGFzIHZhcmlhYmxlcyBzb2Npb2Vjb27Ds21pY2FzIGRlIGludGVyw6lzDQoNCnZhcmlhYmxlc19zb2Npb2Vjb25vbWljYXMgPC0gdXB6ICU+JQ0KICBzZWxlY3QoDQogICAgcGN0X3BvYnJlemEsDQogICAgc2FsYXJpb19wcm9tZWRpbywNCiAgICBwY3RfZXN0cmF0b18xXzIsDQogICAgcGN0X2VzdHJhdG9fM180LA0KICAgIHBjdF9lc3RyYXRvXzVfNiwNCiAgICBhbmlvc19lZHVjYWNpb25fMTVtYXMNCiAgKQ0KDQojIENhbGN1bGFyIGVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzDQoNCmVzdGFkaXN0aWNhc19zb2Npb2Vjb25vbWljYXMgPC0gdmFyaWFibGVzX3NvY2lvZWNvbm9taWNhcyAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGFjcm9zcygNCiAgICAgIGV2ZXJ5dGhpbmcoKSwNCiAgICAgIGxpc3QoDQogICAgICAgIE1lZGlhID0gfiBtZWFuKC4pLA0KICAgICAgICBNZWRpYW5hID0gfiBtZWRpYW4oLiksDQogICAgICAgIERlc3ZpYWNpb24gPSB+IHNkKC4pLA0KICAgICAgICBNaW5pbW8gPSB+IG1pbiguKSwNCiAgICAgICAgUTEgPSB+IHF1YW50aWxlKC4sIDAuMjUpLA0KICAgICAgICBRMyA9IH4gcXVhbnRpbGUoLiwgMC43NSksDQogICAgICAgIE1heGltbyA9IH4gbWF4KC4pDQogICAgICApDQogICAgKQ0KICApICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGV2ZXJ5dGhpbmcoKSwNCiAgICBuYW1lc190byA9IGMoIlZhcmlhYmxlIiwgIkVzdGFkaXN0aWNhIiksDQogICAgbmFtZXNfc2VwID0gIl8oPz1bXl9dKyQpIiwNCiAgICB2YWx1ZXNfdG8gPSAiVmFsb3IiDQogICkgJT4lDQogIHBpdm90X3dpZGVyKA0KICAgIG5hbWVzX2Zyb20gPSBFc3RhZGlzdGljYSwNCiAgICB2YWx1ZXNfZnJvbSA9IFZhbG9yDQogICkNCg0Ka25pdHI6OmthYmxlKA0KICBlc3RhZGlzdGljYXNfc29jaW9lY29ub21pY2FzLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIkVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzIGRlIGxhcyB2YXJpYWJsZXMgc29jaW9lY29uw7NtaWNhcyINCikNCmBgYA0KDQojIyMgNS4zLjMuIERpc3RyaWJ1Y2nDs24gZGUgbGEgcG9icmV6YQ0KDQpFbCBwb3JjZW50YWplIGRlIHBvYnJlemEgcGVybWl0ZSBhcHJveGltYXJzZSBhIGxhcyBjb25kaWNpb25lcyBlY29uw7NtaWNhcyBkZSBsYSBwb2JsYWNpw7NuIGRlIGNhZGEgdGVycml0b3Jpby4NCg0KTWVkaWFudGUgdW4gaGlzdG9ncmFtYSBzZSBleGFtaW5hIGxhIGRpc3RyaWJ1Y2nDs24gZGUgZXN0ZSBpbmRpY2Fkb3IgZW50cmUgbGFzIFVQWiwgYnVzY2FuZG8gaWRlbnRpZmljYXIgZMOzbmRlIHNlIGNvbmNlbnRyYW4gbG9zIHZhbG9yZXMgeSBzaSBleGlzdGVuIHRlcnJpdG9yaW9zIGNvbiBwb3JjZW50YWplcyBjb25zaWRlcmFibGVtZW50ZSBzdXBlcmlvcmVzIGFsIGNvbXBvcnRhbWllbnRvIGdlbmVyYWwuDQoNCkVzdGUgYW7DoWxpc2lzIHBlcm1pdGUgcmVjb25vY2VyIGRpZmVyZW5jaWFzIHNvY2lvZWNvbsOzbWljYXMgcXVlIHBvc3Rlcmlvcm1lbnRlIHBvZHLDoW4gY29udHJhc3RhcnNlIGNvbiBsb3MgaW5kaWNhZG9yZXMgZGUgc2VndXJpZGFkLg0KDQpgYGB7ciBkaXN0cmlidWNpb24tcG9icmV6YSwgZWNobz1UUlVFfQ0KZ2dwbG90KHVweiwgYWVzKHggPSBwY3RfcG9icmV6YSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oDQogICAgYmlucyA9IDIwLA0KICAgIGZpbGwgPSBtYWdlbnRhLA0KICAgIGNvbG9yID0gIndoaXRlIiwNCiAgICBhbHBoYSA9IDAuOQ0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlbCBwb3JjZW50YWplIGRlIHBvYnJlemEgcG9yIFVQWiIsDQogICAgc3VidGl0bGUgPSAiUG9yY2VudGFqZSBkZSBwZXJzb25hcyBjbGFzaWZpY2FkYXMgY29tbyBwb2JyZXMiLA0KICAgIHggPSAiUG9ibGFjacOzbiBlbiBjb25kaWNpw7NuIGRlIHBvYnJlemEgKCUpIiwNCiAgICB5ID0gIkNhbnRpZGFkIGRlIFVQWiIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byBEQU5FLCAyMDIxLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQpQYXJhIGNvbXBsZW1lbnRhciBlbCBncsOhZmljbywgaWRlbnRpZmljYW1vcyBsb3MgdGVycml0b3Jpb3MgY29uIG1heW9yZXMgeSBtZW5vcmVzIHBvcmNlbnRhamVzIGRlIHBvYnJlemEuDQoNCmBgYHtyIHJhbmtpbmctcG9icmV6YSwgZWNobz1UUlVFfQ0KcmFua2luZ19wb2JyZXphIDwtIHVweiAlPiUNCiAgYXJyYW5nZShkZXNjKHBjdF9wb2JyZXphKSkgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICBlbV9hZ3J1cGFkYSwNCiAgICBwY3RfcG9icmV6YQ0KICApDQoNCmtuaXRyOjprYWJsZSgNCiAgcmFua2luZ19wb2JyZXphICU+JSBzbGljZV9oZWFkKG4gPSAxMCksDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiRGlleiBVUFogY29uIG1heW9yIHBvcmNlbnRhamUgZGUgcG9icmV6YSINCikNCg0Ka25pdHI6OmthYmxlKA0KICByYW5raW5nX3BvYnJlemEgJT4lDQogICAgYXJyYW5nZShwY3RfcG9icmV6YSkgJT4lDQogICAgc2xpY2VfaGVhZChuID0gMTApLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIkRpZXogVVBaIGNvbiBtZW5vciBwb3JjZW50YWplIGRlIHBvYnJlemEiDQopDQpgYGANCg0KIyMjIDUuMy40LiBEaXN0cmlidWNpw7NuIGRlbCBzYWxhcmlvIHByb21lZGlvDQoNCkVsIHNhbGFyaW8gcHJvbWVkaW8gcGVybWl0ZSBleHBsb3JhciBsYXMgZGlmZXJlbmNpYXMgZWNvbsOzbWljYXMgZW50cmUgbG9zIHRlcnJpdG9yaW9zLg0KDQpTZSB1dGlsaXphIHVuIGhpc3RvZ3JhbWEgcGFyYSBvYnNlcnZhciBsYSBkaXN0cmlidWNpw7NuIGRlIGxvcyBpbmdyZXNvcyB5IHJlY29ub2NlciBwb3NpYmxlcyBjb25jZW50cmFjaW9uZXMgbyB2YWxvcmVzIGV4dHJlbW9zLiBUYW1iacOpbiBzZSBpZGVudGlmaWNhbiBsYXMgVVBaIGNvbiBtYXlvcmVzIHkgbWVub3JlcyBzYWxhcmlvcyBwcm9tZWRpby4NCg0KRGViaWRvIGEgcXVlIGxvcyBpbmdyZXNvcyBwdWVkZW4gcHJlc2VudGFyIGRpZmVyZW5jaWFzIGltcG9ydGFudGVzIGVudHJlIHRlcnJpdG9yaW9zLCBzZSBjb21wYXJhcsOhbiBsYSBtZWRpYSB5IGxhIG1lZGlhbmEgcGFyYSBldmFsdWFyIGxhIGluZmx1ZW5jaWEgZGUgbG9zIHZhbG9yZXMgZXh0cmVtb3Mgc29icmUgZWwgcHJvbWVkaW8uDQoNCmBgYHtyIGRpc3RyaWJ1Y2lvbi1zYWxhcmlvLCBlY2hvPVRSVUV9DQpnZ3Bsb3QodXB6LCBhZXMoeCA9IHNhbGFyaW9fcHJvbWVkaW8pKSArDQogIGdlb21faGlzdG9ncmFtKA0KICAgIGJpbnMgPSAyMCwNCiAgICBmaWxsID0gdHVycXVlc2EsDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIGFscGhhID0gMC45DQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGVsIHNhbGFyaW8gcHJvbWVkaW8gcG9yIFVQWiIsDQogICAgc3VidGl0bGUgPSAiSW5ncmVzbyBtZW5zdWFsIHByb21lZGlvIHJlcG9ydGFkbyBlbiBsYSBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8iLA0KICAgIHggPSAiU2FsYXJpbyBwcm9tZWRpbyBtZW5zdWFsIChwZXNvcykiLA0KICAgIHkgPSAiQ2FudGlkYWQgZGUgVVBaIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvIERBTkUsIDIwMjEuIg0KICApICsNCiAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKA0KICAgICAgcHJlZml4ID0gIiQiLA0KICAgICAgYmlnLm1hcmsgPSAiLiIsDQogICAgICBkZWNpbWFsLm1hcmsgPSAiLCINCiAgICApDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KUmFua2luZyBkZSBzYWxhcmlvczoNCg0KYGBge3IgcmFua2luZy1zYWxhcmlvLCBlY2hvPVRSVUV9DQpyYW5raW5nX3NhbGFyaW8gPC0gdXB6ICU+JQ0KICBhcnJhbmdlKGRlc2Moc2FsYXJpb19wcm9tZWRpbykpICU+JQ0KICBzZWxlY3QoDQogICAgdXB6X25vbWJyZSwNCiAgICBsb2NhbGlkYWQsDQogICAgZW1fYWdydXBhZGEsDQogICAgc2FsYXJpb19wcm9tZWRpbw0KICApDQoNCmtuaXRyOjprYWJsZSgNCiAgcmFua2luZ19zYWxhcmlvICU+JSBzbGljZV9oZWFkKG4gPSAxMCksDQogIGRpZ2l0cyA9IDAsDQogIGNhcHRpb24gPSAiRGlleiBVUFogY29uIG1heW9yIHNhbGFyaW8gcHJvbWVkaW8iDQopDQoNCmtuaXRyOjprYWJsZSgNCiAgcmFua2luZ19zYWxhcmlvICU+JQ0KICAgIGFycmFuZ2Uoc2FsYXJpb19wcm9tZWRpbykgJT4lDQogICAgc2xpY2VfaGVhZChuID0gMTApLA0KICBkaWdpdHMgPSAwLA0KICBjYXB0aW9uID0gIkRpZXogVVBaIGNvbiBtZW5vciBzYWxhcmlvIHByb21lZGlvIg0KKQ0KYGBgDQoNCiMjIyA1LjMuNS4gQ29tcG9zaWNpw7NuIHBvciBlc3RyYXRvIHNvY2lvZWNvbsOzbWljbw0KDQpMYSBjb21wb3NpY2nDs24gcG9yIGVzdHJhdG8gcGVybWl0ZSBvYnNlcnZhciBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBzb2Npb2Vjb27Ds21pY2FzIGRlIGxhcyB2aXZpZW5kYXMgZGUgY2FkYSBVUFouDQoNClBhcmEgZXN0ZSBhbsOhbGlzaXMgc2UgY29uc2lkZXJhbiB0cmVzIGdydXBvczogZXN0cmF0b3MgMSB5IDIsIGVzdHJhdG9zIDMgeSA0LCB5IGVzdHJhdG9zIDUgeSA2LiBMYSBjb21wYXJhY2nDs24gcGVybWl0ZSBpZGVudGlmaWNhciBxdcOpIGdydXBvcyB0aWVuZW4gbWF5b3IgcGFydGljaXBhY2nDs24gZW4gY2FkYSB0ZXJyaXRvcmlvIHkgcmVjb25vY2VyIGxhcyBkaWZlcmVuY2lhcyBlbiBsYSBjb21wb3NpY2nDs24gc29jaW9lY29uw7NtaWNhIGRlIGxhcyBVUFouDQoNCkVzIGltcG9ydGFudGUgcmVjb3JkYXIgcXVlIGxvcyBwb3JjZW50YWplcyByZXByZXNlbnRhbiBsYSBkaXN0cmlidWNpw7NuIGRlIHZpdmllbmRhcyBwb3IgZ3J1cG8gZGUgZXN0cmF0byB5IG5vIGRlYmVuIGludGVycHJldGFyc2UgY29tbyB1bmEgbWVkaWNpw7NuIGRpcmVjdGEgZGVsIGluZ3Jlc28gZGUgdG9kb3Mgc3VzIGhhYml0YW50ZXMuDQoNCmBgYHtyIGNvbXBvc2ljaW9uLWVzdHJhdG9zLCBlY2hvPVRSVUV9DQojIENhbGN1bGFyIGVsIHByb21lZGlvIGRlIHBhcnRpY2lwYWNpw7NuIGRlIGNhZGEgZ3J1cG8gZGUgZXN0cmF0bw0KDQpwcm9tZWRpb19lc3RyYXRvcyA8LSB1cHogJT4lDQogIHN1bW1hcmlzZSgNCiAgICBgRXN0cmF0b3MgMSB5IDJgID0gbWVhbihwY3RfZXN0cmF0b18xXzIpLA0KICAgIGBFc3RyYXRvcyAzIHkgNGAgPSBtZWFuKHBjdF9lc3RyYXRvXzNfNCksDQogICAgYEVzdHJhdG9zIDUgeSA2YCA9IG1lYW4ocGN0X2VzdHJhdG9fNV82KQ0KICApICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGV2ZXJ5dGhpbmcoKSwNCiAgICBuYW1lc190byA9ICJHcnVwb19lc3RyYXRvIiwNCiAgICB2YWx1ZXNfdG8gPSAiUG9yY2VudGFqZV9wcm9tZWRpbyINCiAgKQ0KDQprbml0cjo6a2FibGUoDQogIHByb21lZGlvX2VzdHJhdG9zLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIlBhcnRpY2lwYWNpw7NuIHByb21lZGlvIGRlIGxvcyBncnVwb3MgZGUgZXN0cmF0byBlbnRyZSBsYXMgVVBaIg0KKQ0KYGBgDQoNCkFob3JhIHZpc3VhbGl6YW1vcyBsb3MgcmVzdWx0YWRvczoNCg0KYGBge3IgZ3JhZmljby1jb21wb3NpY2lvbi1lc3RyYXRvcywgZWNobz1UUlVFfQ0KZ2dwbG90KA0KICBwcm9tZWRpb19lc3RyYXRvcywNCiAgYWVzKA0KICAgIHggPSBHcnVwb19lc3RyYXRvLA0KICAgIHkgPSBQb3JjZW50YWplX3Byb21lZGlvDQogICkNCikgKw0KICBnZW9tX2NvbCgNCiAgICBmaWxsID0gbW9yYWRvLA0KICAgIHdpZHRoID0gMC42NQ0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJDb21wb3NpY2nDs24gcHJvbWVkaW8gcG9yIGdydXBvcyBkZSBlc3RyYXRvIiwNCiAgICBzdWJ0aXRsZSA9ICJQYXJ0aWNpcGFjacOzbiBwcm9tZWRpbyBkZSBjYWRhIGdydXBvIGVudHJlIGxhcyBVUFoiLA0KICAgIHggPSAiR3J1cG8gZGUgZXN0cmF0byIsDQogICAgeSA9ICJQb3JjZW50YWplIHByb21lZGlvICglKSIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byBEQU5FLCAyMDIxLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KVW5hIHByZWNpc2nDs246IGVzdGUgZ3LDoWZpY28gbXVlc3RyYSBlbCBwcm9tZWRpbyBzaW1wbGUgZGUgbG9zIHBvcmNlbnRhamVzIGRlIGxhcyBVUFosIG5vIGxhIGRpc3RyaWJ1Y2nDs24gcG9uZGVyYWRhIGRlIHRvZGFzIGxhcyB2aXZpZW5kYXMgZGUgQm9nb3TDoS4NCg0KIyMjIDUuMy42LiBOaXZlbCBlZHVjYXRpdm8NCg0KRWwgbml2ZWwgZWR1Y2F0aXZvIGNvbnN0aXR1eWUgb3RyYSBkaW1lbnNpw7NuIGltcG9ydGFudGUgcGFyYSBjYXJhY3Rlcml6YXIgbGFzIGNvbmRpY2lvbmVzIHNvY2lvZWNvbsOzbWljYXMgZGUgbG9zIHRlcnJpdG9yaW9zLg0KDQpFbiBlc3RlIGFwYXJ0YWRvIHNlIGFuYWxpemEgZWwgcHJvbWVkaW8gZGUgYcOxb3MgZGUgZWR1Y2FjacOzbiBkZSBsYXMgcGVyc29uYXMgZGUgMTUgYcOxb3MgbyBtw6FzLiBFc3RhIHZhcmlhYmxlIHBlcm1pdGUgZXhwbG9yYXIgbGFzIGRpZmVyZW5jaWFzIGVkdWNhdGl2YXMgZW50cmUgVVBaIHkgY29tcGxlbWVudGFyIGxhIGNhcmFjdGVyaXphY2nDs24gZWNvbsOzbWljYSByZWFsaXphZGEgYW50ZXJpb3JtZW50ZS4NCg0KYGBge3IgZXN0YWRpc3RpY2FzLWVkdWNhY2lvbiwgZWNobz1UUlVFfQ0KZXN0YWRpc3RpY2FzX2VkdWNhY2lvbiA8LSB1cHogJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYSA9IG1lYW4oYW5pb3NfZWR1Y2FjaW9uXzE1bWFzKSwNCiAgICBNZWRpYW5hID0gbWVkaWFuKGFuaW9zX2VkdWNhY2lvbl8xNW1hcyksDQogICAgRGVzdmlhY2lvbl9lc3RhbmRhciA9IHNkKGFuaW9zX2VkdWNhY2lvbl8xNW1hcyksDQogICAgTWluaW1vID0gbWluKGFuaW9zX2VkdWNhY2lvbl8xNW1hcyksDQogICAgUTEgPSBxdWFudGlsZShhbmlvc19lZHVjYWNpb25fMTVtYXMsIDAuMjUpLA0KICAgIFEzID0gcXVhbnRpbGUoYW5pb3NfZWR1Y2FjaW9uXzE1bWFzLCAwLjc1KSwNCiAgICBNYXhpbW8gPSBtYXgoYW5pb3NfZWR1Y2FjaW9uXzE1bWFzKQ0KICApDQoNCmtuaXRyOjprYWJsZSgNCiAgZXN0YWRpc3RpY2FzX2VkdWNhY2lvbiwNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJFc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcyBkZWwgbml2ZWwgZWR1Y2F0aXZvIHBvciBVUFoiDQopDQpgYGANCg0KRGlzdHJpYnVjacOzbiBkZWwgbml2ZWwgZWR1Y2F0aXZvOg0KYGBge3IgZGlzdHJpYnVjaW9uLWVkdWNhY2lvbiwgZWNobz1UUlVFfQ0KZ2dwbG90KHVweiwgYWVzKHggPSBhbmlvc19lZHVjYWNpb25fMTVtYXMpKSArDQogIGdlb21faGlzdG9ncmFtKA0KICAgIGJpbnMgPSAyMCwNCiAgICBmaWxsID0gbWFnZW50YSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgYWxwaGEgPSAwLjkNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBsb3MgYcOxb3MgcHJvbWVkaW8gZGUgZWR1Y2FjacOzbiIsDQogICAgc3VidGl0bGUgPSAiUGVyc29uYXMgZGUgMTUgYcOxb3MgbyBtw6FzIHBvciBVUFoiLA0KICAgIHggPSAiQcOxb3MgcHJvbWVkaW8gZGUgZWR1Y2FjacOzbiIsDQogICAgeSA9ICJDYW50aWRhZCBkZSBVUFoiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8gREFORSwgMjAyMS4iDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KIyMjIDUuMy43LiBSZWxhY2nDs24gZW50cmUgcG9icmV6YSB5IHNhbGFyaW8gcHJvbWVkaW8NCg0KUGFyYSBjb21wbGVtZW50YXIgbGEgZGVzY3JpcGNpw7NuIGluZGl2aWR1YWwgZGUgbGFzIHZhcmlhYmxlcywgc2UgZXhwbG9yYSBsYSByZWxhY2nDs24gZW50cmUgZWwgcG9yY2VudGFqZSBkZSBwb2JyZXphIHkgZWwgc2FsYXJpbyBwcm9tZWRpbyBtZW5zdWFsIGRlIGxhcyBVUFouDQoNClNlIHV0aWxpemEgdW4gZGlhZ3JhbWEgZGUgZGlzcGVyc2nDs24sIGVuIGVsIHF1ZSBjYWRhIHB1bnRvIHJlcHJlc2VudGEgdW5hIHVuaWRhZCB0ZXJyaXRvcmlhbC4gU2UgaW5jb3Jwb3JhIHVuYSBsw61uZWEgZGUgdGVuZGVuY2lhIHBhcmEgb2JzZXJ2YXIgZWwgY29tcG9ydGFtaWVudG8gZ2VuZXJhbCBkZSBhbWJhcyB2YXJpYWJsZXMuDQoNCkVzdGEgY29tcGFyYWNpw7NuIHBlcm1pdGUgaWRlbnRpZmljYXIgcG9zaWJsZXMgYXNvY2lhY2lvbmVzIGVudHJlIGxhcyBjb25kaWNpb25lcyBkZSBwb2JyZXphIHkgbG9zIGluZ3Jlc29zIHByb21lZGlvLCBzaW4gYXN1bWlyIHF1ZSB1bmEgdmFyaWFibGUgc2VhIG5lY2VzYXJpYW1lbnRlIGxhIGNhdXNhIGRlIGxhIG90cmEuDQoNCmBgYHtyIHJlbGFjaW9uLXBvYnJlemEtc2FsYXJpbywgZWNobz1UUlVFfQ0KZ2dwbG90KA0KICB1cHosDQogIGFlcygNCiAgICB4ID0gcGN0X3BvYnJlemEsDQogICAgeSA9IHNhbGFyaW9fcHJvbWVkaW8NCiAgKQ0KKSArDQogIGdlb21fcG9pbnQoDQogICAgY29sb3IgPSBtb3JhZG8sDQogICAgYWxwaGEgPSAwLjcsDQogICAgc2l6ZSA9IDIuNQ0KICApICsNCiAgZ2VvbV9zbW9vdGgoDQogICAgbWV0aG9kID0gImxtIiwNCiAgICBzZSA9IEZBTFNFLA0KICAgIGNvbG9yID0gbWFnZW50YSwNCiAgICBsaW5ld2lkdGggPSAxDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBwb2JyZXphIHkgc2FsYXJpbyBwcm9tZWRpbyIsDQogICAgc3VidGl0bGUgPSAiQ29tcGFyYWNpw7NuIGRlIGNvbmRpY2lvbmVzIHNvY2lvZWNvbsOzbWljYXMgZW50cmUgVVBaIiwNCiAgICB4ID0gIlBvcmNlbnRhamUgZGUgcG9icmV6YSAoJSkiLA0KICAgIHkgPSAiU2FsYXJpbyBwcm9tZWRpbyBtZW5zdWFsIChwZXNvcykiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8gREFORSwgMjAyMS4iDQogICkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoDQogICAgICBwcmVmaXggPSAiJCIsDQogICAgICBiaWcubWFyayA9ICIuIiwNCiAgICAgIGRlY2ltYWwubWFyayA9ICIsIg0KICAgICkNCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMgNS4zLjguIEludGVycHJldGFjacOzbiBkZSByZXN1bHRhZG9zDQoNCkVsIGFuw6FsaXNpcyBzb2Npb2Vjb27Ds21pY28gcGVybWl0ZSBhbXBsaWFyIGxhIGNhcmFjdGVyaXphY2nDs24gZGUgbGFzIFVQWiBtZWRpYW50ZSBpbmRpY2Fkb3JlcyByZWxhY2lvbmFkb3MgY29uIGxhIHBvYnJlemEsIGxvcyBpbmdyZXNvcywgbGEgY29tcG9zaWNpw7NuIHBvciBlc3RyYXRvIHkgZWwgbml2ZWwgZWR1Y2F0aXZvLg0KDQpBIHBhcnRpciBkZSBsYXMgZXN0YWTDrXN0aWNhcyBkZXNjcmlwdGl2YXMgeSBsYXMgdmlzdWFsaXphY2lvbmVzIHNlIGV4YW1pbmFyw6FuIGxhcyBkaWZlcmVuY2lhcyBlbnRyZSB0ZXJyaXRvcmlvcywgbGEgZGlzcGVyc2nDs24gZGUgbG9zIGluZGljYWRvcmVzIHkgbG9zIHBvc2libGVzIHBhdHJvbmVzIGVudHJlIGxhcyBjb25kaWNpb25lcyBlY29uw7NtaWNhcyB5IGVkdWNhdGl2YXMuDQoNCkVzdG9zIHJlc3VsdGFkb3Mgc2Vydmlyw6FuIGNvbW8gcmVmZXJlbmNpYSBwYXJhIGxvcyBhbsOhbGlzaXMgcG9zdGVyaW9yZXMsIGVzcGVjaWFsbWVudGUgYWwgZXhwbG9yYXIgcG9zaWJsZXMgcmVsYWNpb25lcyBlbnRyZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBzb2Npb2Vjb27Ds21pY2FzIHkgbG9zIGluZGljYWRvcmVzIGRlIHNlZ3VyaWRhZC4NCg0KIyMgNS40LiBBbsOhbGlzaXMgZGUgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgeSBjb25kaWNpb25lcyBkZWwgZW50b3Jubw0KDQpMYSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCBjb25zdGl0dXllIHVuYSBkaW1lbnNpw7NuIGltcG9ydGFudGUgcGFyYSBjb21wcmVuZGVyIGxhcyBjb25kaWNpb25lcyBkZSBzZWd1cmlkYWQgZGUgdW4gdGVycml0b3Jpby4gQSBkaWZlcmVuY2lhIGRlIGxvcyByZWdpc3Ryb3MgZGUgZGVsaXRvcyBkZW51bmNpYWRvcywgZXN0ZSBpbmRpY2Fkb3IgcmVjb2dlIGxhIGV4cGVyaWVuY2lhIHkgcGVyY2VwY2nDs24gZGUgbGFzIHBlcnNvbmFzIGZyZW50ZSBhIGxvcyBwcm9ibGVtYXMgZGUgaW5zZWd1cmlkYWQgcHJlc2VudGVzIGVuIGVsIGVudG9ybm8gZGUgc3Ugdml2aWVuZGEuDQoNCkVuIGVzdGEgc2VjY2nDs24gc2UgZXhwbG9yYW4gbGFzIGRpZmVyZW5jaWFzIGVudHJlIFVQWiBlbiBjdWFudG8gYSBsYSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCwgYWxndW5hcyBjb25kaWNpb25lcyBkZWwgZW50b3JubyB5IGxhIGFjY2VzaWJpbGlkYWQgYSBsb3Mgc2VydmljaW9zIGRlIHBvbGljw61hLiBFbCBwcm9ww7NzaXRvIGVzIGlkZW50aWZpY2FyIHBhdHJvbmVzIHkgcG9zaWJsZXMgYXNvY2lhY2lvbmVzIHF1ZSBwZXJtaXRhbiBhbXBsaWFyIGxhIGNvbXByZW5zacOzbiBkZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyB0ZXJyaXRvcmlhbGVzIHJlbGFjaW9uYWRhcyBjb24gbGEgc2VndXJpZGFkLg0KDQojIyMgNS40LjEuIFNlbGVjY2nDs24gZGUgdmFyaWFibGVzDQoNClBhcmEgZGVzYXJyb2xsYXIgZXN0ZSBhbsOhbGlzaXMgc2Ugc2VsZWNjaW9uYW1vcyBzZWlzIHZhcmlhYmxlcyBkZSBsYSBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8sIHJlbGFjaW9uYWRhcyBjb24gbGEgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQsIGxhcyBjb25kaWNpb25lcyBkZWwgZW50b3JubyB5IGxhIGFjY2VzaWJpbGlkYWQgYSBsb3Mgc2VydmljaW9zIGRlIHBvbGljw61hLg0KDQpMYSBzZWxlY2Npw7NuIHBlcm1pdGUgZXhwbG9yYXIgZGlmZXJlbnRlcyBjYXJhY3RlcsOtc3RpY2FzIHRlcnJpdG9yaWFsZXMgcXVlIHB1ZWRlbiBhcG9ydGFyIGluZm9ybWFjacOzbiBwYXJhIGNvbXByZW5kZXIgbGFzIGRpZmVyZW5jaWFzIGVudHJlIGxhcyBVUFouIFNlIGFuYWxpemFyw6EgZWwgcG9yY2VudGFqZSBkZSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCwgbGEgY2VyY2Fuw61hIGEgZGV0ZXJtaW5hZG9zIGVsZW1lbnRvcyBkZWwgZW50b3JubyB5IGVsIHRpZW1wbyBwcm9tZWRpbyBjYW1pbmFuZG8gaGFzdGEgdW4gQ0FJIG8gZXN0YWNpw7NuIGRlIHBvbGljw61hLg0KDQpgYGB7ciBzZWxlY2Npb24tdmFyaWFibGVzLWVudG9ybm8sIGVjaG89VFJVRX0NCiMgU2VsZWNjacOzbiBkZSB2YXJpYWJsZXMgZGUgcGVyY2VwY2nDs24geSBjb25kaWNpb25lcyBkZWwgZW50b3Jubw0KDQp2YXJpYWJsZXNfZW50b3JubyA8LSB1cHogJT4lDQogIHNlbGVjdCgNCiAgICBwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZCwNCiAgICBwY3RfY2VyY2Ffb2xsYXMsDQogICAgcGN0X2NlcmNhX2JhcmVzLA0KICAgIHBjdF9jZXJjYV9sb3Rlc19vc2N1cm9zLA0KICAgIHBjdF9jZXJjYV9iYXN1cmVyb3MsDQogICAgbWluX2NhaV9wb2xpY2lhDQogICkNCg0KIyBWaXN1YWxpemFjacOzbiBkZSBsYXMgcHJpbWVyYXMgb2JzZXJ2YWNpb25lcw0KDQpoZWFkKHZhcmlhYmxlc19lbnRvcm5vKQ0KYGBgDQoNCiMjIyA1LjQuMi4gRXN0YWTDrXN0aWNhcyBkZXNjcmlwdGl2YXMgZGUgcGVyY2VwY2nDs24geSBlbnRvcm5vDQoNCkNvbW8gcHVudG8gZGUgcGFydGlkYSwgc2UgY2FsY3VsYW4gbGFzIHByaW5jaXBhbGVzIG1lZGlkYXMgZGUgZXN0YWTDrXN0aWNhIGRlc2NyaXB0aXZhIHBhcmEgbGFzIHZhcmlhYmxlcyBzZWxlY2Npb25hZGFzLiBFc3RlIGVqZXJjaWNpbyBwZXJtaXRlIGNvbm9jZXIgbG9zIG5pdmVsZXMgZ2VuZXJhbGVzIGRlIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkLCBsYXMgY29uZGljaW9uZXMgZGVsIGVudG9ybm8geSBsb3MgdGllbXBvcyBwcm9tZWRpbyBkZSBkZXNwbGF6YW1pZW50byBoYXN0YSBsb3Mgc2VydmljaW9zIGRlIHBvbGljw61hLg0KDQpTZSBjb25zaWRlcmFuIG1lZGlkYXMgZGUgdGVuZGVuY2lhIGNlbnRyYWwsIGRpc3BlcnNpw7NuIHkgcG9zaWNpw7NuLCBjb24gZWwgcHJvcMOzc2l0byBkZSBpZGVudGlmaWNhciB0YW50byBlbCBjb21wb3J0YW1pZW50byBnZW5lcmFsIGNvbW8gbGFzIGRpZmVyZW5jaWFzIGV4aXN0ZW50ZXMgZW50cmUgbGFzIFVQWi4NCg0KYGBge3IgZXN0YWRpc3RpY2FzLXBlcmNlcGNpb24tZW50b3JubywgZWNobz1UUlVFfQ0KIyBDw6FsY3VsbyBkZSBlc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcw0KDQplc3RhZGlzdGljYXNfZW50b3JubyA8LSB2YXJpYWJsZXNfZW50b3JubyAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGFjcm9zcygNCiAgICAgIGV2ZXJ5dGhpbmcoKSwNCiAgICAgIGxpc3QoDQogICAgICAgIE1lZGlhID0gfm1lYW4oLiksDQogICAgICAgIE1lZGlhbmEgPSB+bWVkaWFuKC4pLA0KICAgICAgICBEZXN2aWFjaW9uID0gfnNkKC4pLA0KICAgICAgICBNaW5pbW8gPSB+bWluKC4pLA0KICAgICAgICBRMSA9IH5xdWFudGlsZSguLCAwLjI1KSwNCiAgICAgICAgUTMgPSB+cXVhbnRpbGUoLiwgMC43NSksDQogICAgICAgIE1heGltbyA9IH5tYXgoLikNCiAgICAgICkNCiAgICApDQogICkgJT4lDQogIHBpdm90X2xvbmdlcigNCiAgICBjb2xzID0gZXZlcnl0aGluZygpLA0KICAgIG5hbWVzX3RvID0gYygiVmFyaWFibGUiLCAiRXN0YWRpc3RpY2EiKSwNCiAgICBuYW1lc19zZXAgPSAiXyg/PVteX10rJCkiLA0KICAgIHZhbHVlc190byA9ICJWYWxvciINCiAgKSAlPiUNCiAgcGl2b3Rfd2lkZXIoDQogICAgbmFtZXNfZnJvbSA9IEVzdGFkaXN0aWNhLA0KICAgIHZhbHVlc19mcm9tID0gVmFsb3INCiAgKQ0KDQprbml0cjo6a2FibGUoDQogIGVzdGFkaXN0aWNhc19lbnRvcm5vLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIkVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzIGRlIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHkgY29uZGljaW9uZXMgZGVsIGVudG9ybm8iDQopDQpgYGANCg0KIyMjIDUuNC4zLiBEaXN0cmlidWNpw7NuIGRlIGxhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkDQoNCkxhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHBlcm1pdGUgYXByb3hpbWFyc2UgYSBsYSBtYW5lcmEgZW4gcXVlIGxvcyBoYWJpdGFudGVzIHJlY29ub2NlbiBsb3MgcHJvYmxlbWFzIGRlIHNlZ3VyaWRhZCBwcmVzZW50ZXMgZW4gc3UgZW50b3JubyBjb3RpZGlhbm8uDQoNClBhcmEgZXhwbG9yYXIgc3UgY29tcG9ydGFtaWVudG8gZW50cmUgbGFzIFVQWiwgc2UgdXRpbGl6YSB1biBoaXN0b2dyYW1hIHF1ZSBwZXJtaXRlIHZpc3VhbGl6YXIgbGEgZGlzdHJpYnVjacOzbiBkZSBsb3MgcG9yY2VudGFqZXMgcmVwb3J0YWRvcy4gRXN0YSByZXByZXNlbnRhY2nDs24gZmFjaWxpdGEgaWRlbnRpZmljYXIgbG9zIHJhbmdvcyBkZSBtYXlvciBjb25jZW50cmFjacOzbiwgbGEgZGlzcGVyc2nDs24gZGUgbG9zIHZhbG9yZXMgeSBwb3NpYmxlcyBkaWZlcmVuY2lhcyBlbnRyZSBsb3MgdGVycml0b3Jpb3MuDQoNCkVsIGFuw6FsaXNpcyBwZXJtaXRlIHJlY29ub2NlciBzaSBsYSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCBwcmVzZW50YSB1biBjb21wb3J0YW1pZW50byByZWxhdGl2YW1lbnRlIGhvbW9nw6luZW8gbyBzaSBleGlzdGVuIGRpZmVyZW5jaWFzIGltcG9ydGFudGVzIGVudHJlIGxhcyB6b25hcyBlc3R1ZGlhZGFzLg0KDQpgYGB7ciBkaXN0cmlidWNpb24tcGVyY2VwY2lvbi1pbnNlZ3VyaWRhZCwgZWNobz1UUlVFfQ0KZ2dwbG90KA0KICB1cHosDQogIGFlcyh4ID0gcGN0X3BlcmNpYmVfaW5zZWd1cmlkYWQpDQopICsNCiAgZ2VvbV9oaXN0b2dyYW0oDQogICAgYmlucyA9IDE1LA0KICAgIGZpbGwgPSBtYWdlbnRhLA0KICAgIGNvbG9yID0gIndoaXRlIiwNCiAgICBhbHBoYSA9IDAuODUNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBsYSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCIsDQogICAgc3VidGl0bGUgPSAiUG9yY2VudGFqZSByZXBvcnRhZG8gZW4gbGFzIFVQWiBkZSBCb2dvdMOhIiwNCiAgICB4ID0gIlBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkICglKSIsDQogICAgeSA9ICJDYW50aWRhZCBkZSBVUFoiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8gREFORSwgMjAyMS4iDQogICkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoc3VmZml4ID0gIiUiKQ0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQoNCiMjIyA1LjQuNC4gSWRlbnRpZmljYWNpw7NuIGRlIGxhcyBVUFogY29uIG1heW9yIHkgbWVub3IgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQNCg0KQ29uIGVsIHByb3DDs3NpdG8gZGUgaWRlbnRpZmljYXIgbGFzIGRpZmVyZW5jaWFzIHRlcnJpdG9yaWFsZXMsIHNlIGNvbnN0cnV5ZW4gZG9zIHJhbmtpbmdzIHF1ZSBwZXJtaXRlbiByZWNvbm9jZXIgbGFzIGRpZXogVVBaIGNvbiBtYXlvcmVzIHkgbWVub3JlcyBwb3JjZW50YWplcyBkZSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZC4NCg0KRXN0YSBjb21wYXJhY2nDs24gZmFjaWxpdGEgaWRlbnRpZmljYXIgbG9zIHRlcnJpdG9yaW9zIHF1ZSBwcmVzZW50YW4gbG9zIHZhbG9yZXMgbcOhcyBhbHRvcyB5IGJham9zIGRlbCBpbmRpY2Fkb3IsIGNvbXBsZW1lbnRhbmRvIGxhIGxlY3R1cmEgZ2VuZXJhbCBvYnRlbmlkYSBtZWRpYW50ZSBlbCBoaXN0b2dyYW1hLg0KDQpBZGljaW9uYWxtZW50ZSwgc2UgaW5jbHV5ZSBsYSB2YXJpYWJsZSBgZW1fYWdydXBhZGFgIHBhcmEgaWRlbnRpZmljYXIgbGFzIFVQWiBjdXlvcyByZXN1bHRhZG9zIHByb3ZpZW5lbiBkZSBlc3RpbWFjaW9uZXMgY29tcGFydGlkYXMgY29uIG90cm9zIHRlcnJpdG9yaW9zLCBjb25kaWNpw7NuIHF1ZSBkZWJlIHRlbmVyc2UgZW4gY3VlbnRhIGFsIGludGVycHJldGFyIGxhcyBwb3NpY2lvbmVzIGRlbCByYW5raW5nLg0KDQpgYGB7ciByYW5raW5nLXBlcmNlcGNpb24taW5zZWd1cmlkYWQsIGVjaG89VFJVRX0NCiMgRGlleiBVUFogY29uIG1heW9yIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkDQoNCm1heW9yX3BlcmNlcGNpb24gPC0gdXB6ICU+JQ0KICBhcnJhbmdlKGRlc2MocGN0X3BlcmNpYmVfaW5zZWd1cmlkYWQpKSAlPiUNCiAgc2VsZWN0KA0KICAgIHVwel9ub21icmUsDQogICAgbG9jYWxpZGFkLA0KICAgIGVtX2FncnVwYWRhLA0KICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkDQogICkgJT4lDQogIHNsaWNlX2hlYWQobiA9IDEwKQ0KDQprbml0cjo6a2FibGUoDQogIG1heW9yX3BlcmNlcGNpb24sDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiRGlleiBVUFogY29uIG1heW9yIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIg0KKQ0KDQojIERpZXogVVBaIGNvbiBtZW5vciBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZA0KDQptZW5vcl9wZXJjZXBjaW9uIDwtIHVweiAlPiUNCiAgYXJyYW5nZShwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZCkgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICBlbV9hZ3J1cGFkYSwNCiAgICBwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZA0KICApICU+JQ0KICBzbGljZV9oZWFkKG4gPSAxMCkNCg0Ka25pdHI6OmthYmxlKA0KICBtZW5vcl9wZXJjZXBjaW9uLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIkRpZXogVVBaIGNvbiBtZW5vciBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCINCikNCmBgYA0KDQojIyMgNS40LjUuIENvbXBhcmFjacOzbiBkZSBsYXMgY29uZGljaW9uZXMgZGVsIGVudG9ybm8NCg0KTGFzIGNvbmRpY2lvbmVzIGRlbCBlbnRvcm5vIGNvbnN0aXR1eWVuIHVuYSBkaW1lbnNpw7NuIGNvbXBsZW1lbnRhcmlhIHBhcmEgY29tcHJlbmRlciBsYXMgY2FyYWN0ZXLDrXN0aWNhcyB0ZXJyaXRvcmlhbGVzIGFzb2NpYWRhcyBjb24gbGEgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQuIEVuIGVzdGUgYXBhcnRhZG8gc2UgYW5hbGl6YW4gY3VhdHJvIGluZGljYWRvcmVzIHJlbGFjaW9uYWRvcyBjb24gbGEgY2VyY2Fuw61hIGEgZXhwZW5kaW9zIGRlIGRyb2dhLCBiYXJlcyBvIHByb3N0w61idWxvcywgbG90ZXMgYmFsZMOtb3MgbyBzaXRpb3Mgb3NjdXJvcyB5IGJhc3VyZXJvcy4NCg0KUGFyYSBmYWNpbGl0YXIgbGEgY29tcGFyYWNpw7NuLCBzZSBjYWxjdWxhIGVsIHByb21lZGlvIHNpbXBsZSBkZSBsb3MgcG9yY2VudGFqZXMgcmVwb3J0YWRvcyBwb3IgbGFzIFVQWiB5IHNlIHByZXNlbnRhbiBsb3MgcmVzdWx0YWRvcyBtZWRpYW50ZSB1bmEgdGFibGEgeSB1biBncsOhZmljbyBkZSBiYXJyYXMuIEVzdG8gcGVybWl0ZSByZWNvbm9jZXIgY3XDoWxlcyBkZSBsYXMgY29uZGljaW9uZXMgYW5hbGl6YWRhcyBwcmVzZW50YW4gdW5hIG1heW9yIHByZXNlbmNpYSBwcm9tZWRpbyBlbiBsb3MgdGVycml0b3Jpb3MgZXN0dWRpYWRvcy4NCg0KRXMgaW1wb3J0YW50ZSBhY2xhcmFyIHF1ZSBlc3RvcyByZXN1bHRhZG9zIGNvcnJlc3BvbmRlbiBhbCBwcm9tZWRpbyBkZSBsb3MgcG9yY2VudGFqZXMgZGUgbGFzIFVQWiB5IG5vIGFsIHBvcmNlbnRhamUgYWdyZWdhZG8gZGUgdml2aWVuZGFzIGFmZWN0YWRhcyBlbiBCb2dvdMOhLiBDYWRhIFVQWiB0aWVuZSBlbCBtaXNtbyBwZXNvIGVuIGVsIGPDoWxjdWxvLCBpbmRlcGVuZGllbnRlbWVudGUgZGUgc3UgY2FudGlkYWQgZGUgdml2aWVuZGFzLg0KDQpgYGB7ciBjb21wYXJhY2lvbi1jb25kaWNpb25lcy1lbnRvcm5vLCBlY2hvPVRSVUV9DQojIEPDoWxjdWxvIGRlbCBwcm9tZWRpbyBzaW1wbGUgZGUgY2FkYSBjb25kaWNpw7NuIGVudHJlIGxhcyBVUFoNCg0KcHJvbWVkaW9zX2VudG9ybm8gPC0gdXB6ICU+JQ0KICBzdW1tYXJpc2UoDQogICAgT2xsYXMgPSBtZWFuKHBjdF9jZXJjYV9vbGxhcyksDQogICAgQmFyZXMgPSBtZWFuKHBjdF9jZXJjYV9iYXJlcyksDQogICAgTG90ZXNfb3NjdXJvcyA9IG1lYW4ocGN0X2NlcmNhX2xvdGVzX29zY3Vyb3MpLA0KICAgIEJhc3VyZXJvcyA9IG1lYW4ocGN0X2NlcmNhX2Jhc3VyZXJvcykNCiAgKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKA0KICAgIGNvbHMgPSBldmVyeXRoaW5nKCksDQogICAgbmFtZXNfdG8gPSAiQ29uZGljaW9uIiwNCiAgICB2YWx1ZXNfdG8gPSAiUHJvbWVkaW8iDQogICkgJT4lDQogIGFycmFuZ2UoZGVzYyhQcm9tZWRpbykpDQoNCiMgUHJlc2VudGFjacOzbiBkZSByZXN1bHRhZG9zDQoNCmtuaXRyOjprYWJsZSgNCiAgcHJvbWVkaW9zX2VudG9ybm8sDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiUHJvbWVkaW8gc2ltcGxlIGRlIGxhcyBjb25kaWNpb25lcyBkZWwgZW50b3JubyBwb3IgVVBaIg0KKQ0KYGBgDQoNCkFob3JhIHJlcHJlc2VudGFtb3MgbG9zIHJlc3VsdGFkb3MgbWVkaWFudGUgdW4gZ3LDoWZpY28gZGUgYmFycmFzLg0KDQpgYGB7ciBncmFmaWNvLWNvbmRpY2lvbmVzLWVudG9ybm8sIGVjaG89VFJVRX0NCmdncGxvdCgNCiAgcHJvbWVkaW9zX2VudG9ybm8sDQogIGFlcygNCiAgICB4ID0gcmVvcmRlcihDb25kaWNpb24sIFByb21lZGlvKSwNCiAgICB5ID0gUHJvbWVkaW8NCiAgKQ0KKSArDQogIGdlb21fY29sKA0KICAgIGZpbGwgPSB0dXJxdWVzYSwNCiAgICB3aWR0aCA9IDAuNjUNCiAgKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ29uZGljaW9uZXMgZGVsIGVudG9ybm8gcmVwb3J0YWRhcyBlbiBsYXMgVVBaIiwNCiAgICBzdWJ0aXRsZSA9ICJQcm9tZWRpbyBzaW1wbGUgZGUgbG9zIHBvcmNlbnRhamVzIHBvciBVUFoiLA0KICAgIHggPSBOVUxMLA0KICAgIHkgPSAiUHJvbWVkaW8gKCUpIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvIERBTkUsIDIwMjEuIg0KICApICsNCiAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKHN1ZmZpeCA9ICIlIikNCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMgNS40LjYuIFRpZW1wbyBkZSBkZXNwbGF6YW1pZW50byBoYXN0YSB1biBDQUkgbyBlc3RhY2nDs24gZGUgcG9saWPDrWENCg0KTGEgYWNjZXNpYmlsaWRhZCBhIGxvcyBzZXJ2aWNpb3MgZGUgcG9saWPDrWEgcmVwcmVzZW50YSBvdHJhIGNhcmFjdGVyw61zdGljYSByZWxldmFudGUgcGFyYSBlbCBhbsOhbGlzaXMgdGVycml0b3JpYWwuIEVuIGVzdGUgYXBhcnRhZG8gc2UgZXhhbWluYSBlbCB0aWVtcG8gcHJvbWVkaW8gY2FtaW5hbmRvIGRlc2RlIGxhcyB2aXZpZW5kYXMgaGFzdGEgdW4gQ0FJIG8gZXN0YWNpw7NuIGRlIHBvbGljw61hLCBjb24gZWwgcHJvcMOzc2l0byBkZSBpZGVudGlmaWNhciBkaWZlcmVuY2lhcyBlbnRyZSBsYXMgVVBaLg0KDQpTZSB1dGlsaXphbiBtZWRpZGFzIGRlc2NyaXB0aXZhcywgdW4gaGlzdG9ncmFtYSB5IHVuYSBjb21wYXJhY2nDs24gZGUgbG9zIHRlcnJpdG9yaW9zIGNvbiBtYXlvcmVzIHkgbWVub3JlcyB0aWVtcG9zIGRlIGRlc3BsYXphbWllbnRvLiBEZSBlc3RhIG1hbmVyYSwgc2UgYnVzY2EgcmVjb25vY2VyIGPDs21vIHNlIGRpc3RyaWJ1eWUgbGEgYWNjZXNpYmlsaWRhZCBhIGVzdG9zIHNlcnZpY2lvcyBlbiBsYXMgem9uYXMgZXN0dWRpYWRhcy4NCg0KRXN0ZSBpbmRpY2Fkb3IgcmVwcmVzZW50YSB1biB0aWVtcG8gcHJvbWVkaW8gZGUgZGVzcGxhemFtaWVudG8geSBubyBkZWJlIGludGVycHJldGFyc2UgY29tbyB1bmEgbWVkaWRhIGRpcmVjdGEgZGUgcHJlc2VuY2lhIHBvbGljaWFsLCBjb2JlcnR1cmEgb3BlcmF0aXZhIG8gdGllbXBvIGRlIHJlc3B1ZXN0YSBhbnRlIHVuYSBlbWVyZ2VuY2lhLg0KDQpgYGB7ciBlc3RhZGlzdGljYXMtdGllbXBvLWNhaSwgZWNobz1UUlVFfQ0KZXN0YWRpc3RpY2FzX2NhaSA8LSB1cHogJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYSA9IG1lYW4obWluX2NhaV9wb2xpY2lhKSwNCiAgICBNZWRpYW5hID0gbWVkaWFuKG1pbl9jYWlfcG9saWNpYSksDQogICAgRGVzdmlhY2lvbiA9IHNkKG1pbl9jYWlfcG9saWNpYSksDQogICAgTWluaW1vID0gbWluKG1pbl9jYWlfcG9saWNpYSksDQogICAgUTEgPSBxdWFudGlsZShtaW5fY2FpX3BvbGljaWEsIDAuMjUpLA0KICAgIFEzID0gcXVhbnRpbGUobWluX2NhaV9wb2xpY2lhLCAwLjc1KSwNCiAgICBNYXhpbW8gPSBtYXgobWluX2NhaV9wb2xpY2lhKQ0KICApDQoNCmtuaXRyOjprYWJsZSgNCiAgZXN0YWRpc3RpY2FzX2NhaSwNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJFc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcyBkZWwgdGllbXBvIGRlIGRlc3BsYXphbWllbnRvIGhhc3RhIHVuIENBSSINCikNCmBgYA0KDQpBaG9yYSB2aXN1YWxpemFtb3MgbGEgZGlzdHJpYnVjacOzbiBkZSBsb3MgdGllbXBvcy4NCg0KYGBge3IgZGlzdHJpYnVjaW9uLXRpZW1wby1jYWksIGVjaG89VFJVRX0NCmdncGxvdCgNCiAgdXB6LA0KICBhZXMoeCA9IG1pbl9jYWlfcG9saWNpYSkNCikgKw0KICBnZW9tX2hpc3RvZ3JhbSgNCiAgICBiaW5zID0gMTUsDQogICAgZmlsbCA9IG1vcmFkbywNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgYWxwaGEgPSAwLjg1DQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGVsIHRpZW1wbyBkZSBkZXNwbGF6YW1pZW50byBhIHVuIENBSSIsDQogICAgc3VidGl0bGUgPSAiVGllbXBvIHByb21lZGlvIGNhbWluYW5kbyBwb3IgVVBaIiwNCiAgICB4ID0gIk1pbnV0b3MgY2FtaW5hbmRvIiwNCiAgICB5ID0gIkNhbnRpZGFkIGRlIFVQWiIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byBEQU5FLCAyMDIxLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQpGaW5hbG1lbnRlLCBpZGVudGlmaWNhbW9zIGxhcyBkaWV6IFVQWiBjb24gbWF5b3JlcyB5IG1lbm9yZXMgdGllbXBvcy4NCg0KYGBge3IgcmFua2luZy10aWVtcG8tY2FpLCBlY2hvPVRSVUV9DQojIERpZXogVVBaIGNvbiBtYXlvciB0aWVtcG8gZGUgZGVzcGxhemFtaWVudG8NCg0KbWF5b3JfdGllbXBvX2NhaSA8LSB1cHogJT4lDQogIGFycmFuZ2UoZGVzYyhtaW5fY2FpX3BvbGljaWEpKSAlPiUNCiAgc2VsZWN0KA0KICAgIHVwel9ub21icmUsDQogICAgbG9jYWxpZGFkLA0KICAgIGVtX2FncnVwYWRhLA0KICAgIG1pbl9jYWlfcG9saWNpYQ0KICApICU+JQ0KICBzbGljZV9oZWFkKG4gPSAxMCkNCg0Ka25pdHI6OmthYmxlKA0KICBtYXlvcl90aWVtcG9fY2FpLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIkRpZXogVVBaIGNvbiBtYXlvciB0aWVtcG8gcHJvbWVkaW8gY2FtaW5hbmRvIGhhc3RhIHVuIENBSSINCikNCg0KIyBEaWV6IFVQWiBjb24gbWVub3IgdGllbXBvIGRlIGRlc3BsYXphbWllbnRvDQoNCm1lbm9yX3RpZW1wb19jYWkgPC0gdXB6ICU+JQ0KICBhcnJhbmdlKG1pbl9jYWlfcG9saWNpYSkgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICBlbV9hZ3J1cGFkYSwNCiAgICBtaW5fY2FpX3BvbGljaWENCiAgKSAlPiUNCiAgc2xpY2VfaGVhZChuID0gMTApDQoNCmtuaXRyOjprYWJsZSgNCiAgbWVub3JfdGllbXBvX2NhaSwNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJEaWV6IFVQWiBjb24gbWVub3IgdGllbXBvIHByb21lZGlvIGNhbWluYW5kbyBoYXN0YSB1biBDQUkiDQopDQpgYGANCg0KIyMjIDUuNC43LiBSZWxhY2nDs24gZW50cmUgbGEgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgeSBsYXMgY29uZGljaW9uZXMgZGVsIGVudG9ybm8NCg0KRGVzcHXDqXMgZGUgYW5hbGl6YXIgaW5kaXZpZHVhbG1lbnRlIGxhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkLCBsYXMgY29uZGljaW9uZXMgZGVsIGVudG9ybm8geSBsYSBhY2Nlc2liaWxpZGFkIGEgbG9zIHNlcnZpY2lvcyBkZSBwb2xpY8OtYSwgc2UgZXhwbG9yYW4gbGFzIHBvc2libGVzIHJlbGFjaW9uZXMgZW50cmUgZXN0YXMgdmFyaWFibGVzLg0KDQpFbCBwcm9ww7NzaXRvIGVzIGlkZW50aWZpY2FyIHNpIGxhcyBVUFogcXVlIHByZXNlbnRhbiBtYXlvcmVzIHBvcmNlbnRhamVzIGRlIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHRhbWJpw6luIHJlZ2lzdHJhbiBtYXlvcmVzIHBvcmNlbnRhamVzIGRlIHZpdmllbmRhcyBjZXJjYW5hcyBhIGV4cGVuZGlvcyBkZSBkcm9nYSwgYmFyZXMgbyBwcm9zdMOtYnVsb3MsIGxvdGVzIGJhbGTDrW9zIG8gc2l0aW9zIG9zY3Vyb3MgeSBiYXN1cmVyb3MuIERlIGlndWFsIG1hbmVyYSwgc2UgZXhhbWluYSBsYSBwb3NpYmxlIHJlbGFjacOzbiBlbnRyZSBsYSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCB5IGVsIHRpZW1wbyBwcm9tZWRpbyBkZSBkZXNwbGF6YW1pZW50byBjYW1pbmFuZG8gaGFzdGEgdW4gQ0FJIG8gZXN0YWNpw7NuIGRlIHBvbGljw61hLg0KDQpQYXJhIGVzdGUgZWplcmNpY2lvIHNlIHV0aWxpemFuIGdyw6FmaWNvcyBkZSBkaXNwZXJzacOzbiB5IGVsIGNvZWZpY2llbnRlIGRlIGNvcnJlbGFjacOzbiBkZSBTcGVhcm1hbi4gRXN0YSBtZWRpZGEgcGVybWl0ZSBleHBsb3JhciBsYSBkaXJlY2Npw7NuIHkgbGEgaW50ZW5zaWRhZCBkZSBsYXMgYXNvY2lhY2lvbmVzIGVudHJlIGxhcyB2YXJpYWJsZXMsIHNpbiBhc3VtaXIgbmVjZXNhcmlhbWVudGUgdW5hIHJlbGFjacOzbiBsaW5lYWwuDQoNCkxvcyByZXN1bHRhZG9zIGRlYmVuIGludGVycHJldGFyc2UgY29tbyBhc29jaWFjaW9uZXMgZXhwbG9yYXRvcmlhcyB5IG5vIGNvbW8gZXZpZGVuY2lhIGRlIGNhdXNhbGlkYWQuIEFkaWNpb25hbG1lbnRlLCBzZSBkZWJlIGNvbnNpZGVyYXIgcXVlIGFsZ3VuYXMgZXN0aW1hY2lvbmVzIGRlIGxhIEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byBzZSBlbmN1ZW50cmFuIGFncnVwYWRhcyBlbnRyZSB2YXJpYXMgVVBaLCBsbyBxdWUgbGltaXRhIGxhIGluZGVwZW5kZW5jaWEgZGUgbGFzIG9ic2VydmFjaW9uZXMgeSBleGlnZSBwcmVjYXVjacOzbiBhbCBjb21wYXJhciBsb3MgcmVzdWx0YWRvcy4NCg0KYGBge3IgcmVsYWNpb24tcGVyY2VwY2lvbi1lbnRvcm5vLCBlY2hvPVRSVUV9DQojIFByZXBhcmFjacOzbiBkZSBsYXMgdmFyaWFibGVzIHBhcmEgY29tcGFyYXIgbGFzIHJlbGFjaW9uZXMNCg0KcmVsYWNpb25lc19lbnRvcm5vIDwtIHVweiAlPiUNCiAgc2VsZWN0KA0KICAgIHVwel9ub21icmUsDQogICAgcGN0X3BlcmNpYmVfaW5zZWd1cmlkYWQsDQogICAgcGN0X2NlcmNhX29sbGFzLA0KICAgIHBjdF9jZXJjYV9iYXJlcywNCiAgICBwY3RfY2VyY2FfbG90ZXNfb3NjdXJvcywNCiAgICBwY3RfY2VyY2FfYmFzdXJlcm9zLA0KICAgIG1pbl9jYWlfcG9saWNpYQ0KICApICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGMoDQogICAgICBwY3RfY2VyY2Ffb2xsYXMsDQogICAgICBwY3RfY2VyY2FfYmFyZXMsDQogICAgICBwY3RfY2VyY2FfbG90ZXNfb3NjdXJvcywNCiAgICAgIHBjdF9jZXJjYV9iYXN1cmVyb3MsDQogICAgICBtaW5fY2FpX3BvbGljaWENCiAgICApLA0KICAgIG5hbWVzX3RvID0gIkNvbmRpY2lvbiIsDQogICAgdmFsdWVzX3RvID0gIlZhbG9yIg0KICApICU+JQ0KICBtdXRhdGUoDQogICAgQ29uZGljaW9uID0gcmVjb2RlKA0KICAgICAgQ29uZGljaW9uLA0KICAgICAgcGN0X2NlcmNhX29sbGFzID0gIkNlcmNhbsOtYSBhIGV4cGVuZGlvcyBkZSBkcm9nYSIsDQogICAgICBwY3RfY2VyY2FfYmFyZXMgPSAiQ2VyY2Fuw61hIGEgYmFyZXMgbyBwcm9zdMOtYnVsb3MiLA0KICAgICAgcGN0X2NlcmNhX2xvdGVzX29zY3Vyb3MgPSAiQ2VyY2Fuw61hIGEgbG90ZXMgb3NjdXJvcyIsDQogICAgICBwY3RfY2VyY2FfYmFzdXJlcm9zID0gIkNlcmNhbsOtYSBhIGJhc3VyZXJvcyIsDQogICAgICBtaW5fY2FpX3BvbGljaWEgPSAiVGllbXBvIGRlIGRlc3BsYXphbWllbnRvIGEgdW4gQ0FJIg0KICAgICkNCiAgKQ0KDQojIEdyw6FmaWNvIGRlIGRpc3BlcnNpw7NuIHBvciBjb25kaWNpw7NuIGRlbCBlbnRvcm5vDQoNCmdncGxvdCgNCiAgcmVsYWNpb25lc19lbnRvcm5vLA0KICBhZXMoDQogICAgeCA9IFZhbG9yLA0KICAgIHkgPSBwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZA0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBjb2xvciA9IHR1cnF1ZXNhLA0KICAgIGFscGhhID0gMC42NSwNCiAgICBzaXplID0gMg0KICApICsNCiAgZ2VvbV9zbW9vdGgoDQogICAgbWV0aG9kID0gImxtIiwNCiAgICBzZSA9IEZBTFNFLA0KICAgIGNvbG9yID0gbWFnZW50YSwNCiAgICBsaW5ld2lkdGggPSAwLjgNCiAgKSArDQogIGZhY2V0X3dyYXAoDQogICAgfkNvbmRpY2lvbiwNCiAgICBzY2FsZXMgPSAiZnJlZV94Ig0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJQZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCB5IGNvbmRpY2lvbmVzIGRlbCBlbnRvcm5vIiwNCiAgICBzdWJ0aXRsZSA9ICJSZWxhY2nDs24gZXhwbG9yYXRvcmlhIGVudHJlIHZhcmlhYmxlcyBwb3IgVVBaIiwNCiAgICB4ID0gIlZhbG9yIGRlIGxhIGNvbmRpY2nDs24gYW5hbGl6YWRhIiwNCiAgICB5ID0gIlBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkICglKSIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byBEQU5FLCAyMDIxLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQpMYSBsw61uZWEgcmVwcmVzZW50YSB1bmEgdGVuZGVuY2lhIGxpbmVhbCBkZSByZWZlcmVuY2lhLiBObyBzaWduaWZpY2EgcXVlIGV4aXN0YSB1bmEgcmVsYWNpw7NuIGNhdXNhbC4NCg0KQ29uIGVzdGUgY8OhbGN1bG8gcG9kcmVtb3MgY29tcGxlbWVudGFyIHZpc3VhbG1lbnRlIGxvcyBncsOhZmljb3MgeSBjb21wYXJhciBsYSBpbnRlbnNpZGFkIGRlIGxhcyBhc29jaWFjaW9uZXMgbWVkaWFudGUgdmFsb3JlcyBlbnRyZSAtMSB5IDEuDQoNCmBgYHtyIGNvcnJlbGFjaW9uZXMtcGVyY2VwY2lvbi1lbnRvcm5vLCBlY2hvPVRSVUV9DQojIFNlbGVjY2nDs24gZGUgdmFyaWFibGVzIHBhcmEgZWwgYW7DoWxpc2lzIGRlIGNvcnJlbGFjacOzbg0KDQpkYXRvc19jb3JyZWxhY2lvbl9lbnRvcm5vIDwtIHVweiAlPiUNCiAgc2VsZWN0KA0KICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkLA0KICAgIHBjdF9jZXJjYV9vbGxhcywNCiAgICBwY3RfY2VyY2FfYmFyZXMsDQogICAgcGN0X2NlcmNhX2xvdGVzX29zY3Vyb3MsDQogICAgcGN0X2NlcmNhX2Jhc3VyZXJvcywNCiAgICBtaW5fY2FpX3BvbGljaWENCiAgKQ0KDQojIEPDoWxjdWxvIGRlIGxhIG1hdHJpeiBkZSBjb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuDQoNCm1hdHJpel9jb3JyZWxhY2lvbl9lbnRvcm5vIDwtIGNvcigNCiAgZGF0b3NfY29ycmVsYWNpb25fZW50b3JubywNCiAgbWV0aG9kID0gInNwZWFybWFuIiwNCiAgdXNlID0gImNvbXBsZXRlLm9icyINCikNCg0KIyBQcmVzZW50YWNpw7NuIGRlIGxhIG1hdHJpeg0KDQprbml0cjo6a2FibGUoDQogIHJvdW5kKG1hdHJpel9jb3JyZWxhY2lvbl9lbnRvcm5vLCAyKSwNCiAgY2FwdGlvbiA9ICJNYXRyaXogZGUgY29ycmVsYWNpb25lcyBkZSBTcGVhcm1hbiBlbnRyZSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCB5IGNvbmRpY2lvbmVzIGRlbCBlbnRvcm5vIg0KKQ0KYGBgDQoNCiMjIyMgTWF0cml6IGRlIGNvcnJlbGFjaW9uZXMgZW50cmUgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgeSBjb25kaWNpb25lcyBkZWwgZW50b3Jubw0KDQpQYXJhIGNvbXBsZW1lbnRhciBlbCBhbsOhbGlzaXMgZGUgbGFzIHJlbGFjaW9uZXMgZW50cmUgbGFzIHZhcmlhYmxlcywgc2UgY29uc3RydXllIHVuYSBtYXRyaXogZGUgY29ycmVsYWNpb25lcyByZXByZXNlbnRhZGEgbWVkaWFudGUgdW4gbWFwYSBkZSBjYWxvci4gRXN0YSB2aXN1YWxpemFjacOzbiBwZXJtaXRlIGlkZW50aWZpY2FyIGRlIG1hbmVyYSBjb25qdW50YSBsYSBkaXJlY2Npw7NuIHkgbGEgaW50ZW5zaWRhZCBkZSBsYXMgYXNvY2lhY2lvbmVzIGVudHJlIGxhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkLCBsYXMgY29uZGljaW9uZXMgZGVsIGVudG9ybm8geSBlbCB0aWVtcG8gZGUgZGVzcGxhemFtaWVudG8gaGFzdGEgbG9zIHNlcnZpY2lvcyBkZSBwb2xpY8OtYS4NCg0KU2UgdXRpbGl6YSBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gZGUgU3BlYXJtYW4sIGN1eW9zIHZhbG9yZXMgb3NjaWxhbiBlbnRyZSAtMSB5IDEuIExvcyB2YWxvcmVzIHBvc2l0aXZvcyByZXByZXNlbnRhbiBhc29jaWFjaW9uZXMgZGlyZWN0YXMsIG1pZW50cmFzIHF1ZSBsb3MgbmVnYXRpdm9zIGluZGljYW4gYXNvY2lhY2lvbmVzIGludmVyc2FzLiBMb3MgdmFsb3JlcyBjZXJjYW5vcyBhIGNlcm8gcmVmbGVqYW4gYXNvY2lhY2lvbmVzIG1vbm90w7NuaWNhcyBkw6liaWxlcy4NCg0KTGEgcmVwcmVzZW50YWNpw7NuIG1lZGlhbnRlIGNvbG9yZXMgZmFjaWxpdGEgbGEgaWRlbnRpZmljYWNpw7NuIGRlIHBhdHJvbmVzIHkgcGVybWl0ZSBjb21wYXJhciB2aXN1YWxtZW50ZSBsYXMgcmVsYWNpb25lcyBlbnRyZSBsYXMgdmFyaWFibGVzIHNlbGVjY2lvbmFkYXMuDQoNCmBgYHtyIG1hcGEtY2Fsb3ItY29ycmVsYWNpb25lcy1lbnRvcm5vLCBlY2hvPVRSVUV9DQojIEPDoWxjdWxvIGRlIGxhIG1hdHJpeiBkZSBjb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuDQoNCm1hdHJpel9jb3JyZWxhY2lvbl9lbnRvcm5vIDwtIHVweiAlPiUNCiAgc2VsZWN0KA0KICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkLA0KICAgIHBjdF9jZXJjYV9vbGxhcywNCiAgICBwY3RfY2VyY2FfYmFyZXMsDQogICAgcGN0X2NlcmNhX2xvdGVzX29zY3Vyb3MsDQogICAgcGN0X2NlcmNhX2Jhc3VyZXJvcywNCiAgICBtaW5fY2FpX3BvbGljaWENCiAgKSAlPiUNCiAgY29yKA0KICAgIG1ldGhvZCA9ICJzcGVhcm1hbiIsDQogICAgdXNlID0gImNvbXBsZXRlLm9icyINCiAgKQ0KDQojIFRyYW5zZm9ybWFjacOzbiBkZSBsYSBtYXRyaXogYSBmb3JtYXRvIGxhcmdvDQoNCmNvcnJlbGFjaW9uZXNfbGFyZ2FzIDwtIGFzLmRhdGEuZnJhbWUoDQogIGFzLnRhYmxlKG1hdHJpel9jb3JyZWxhY2lvbl9lbnRvcm5vKQ0KKSAlPiUNCiAgcmVuYW1lKA0KICAgIFZhcmlhYmxlXzEgPSBWYXIxLA0KICAgIFZhcmlhYmxlXzIgPSBWYXIyLA0KICAgIENvcnJlbGFjaW9uID0gRnJlcQ0KICApDQoNCiMgQ29uc3RydWNjacOzbiBkZWwgbWFwYSBkZSBjYWxvcg0KDQpnZ3Bsb3QoDQogIGNvcnJlbGFjaW9uZXNfbGFyZ2FzLA0KICBhZXMoDQogICAgeCA9IFZhcmlhYmxlXzEsDQogICAgeSA9IFZhcmlhYmxlXzIsDQogICAgZmlsbCA9IENvcnJlbGFjaW9uDQogICkNCikgKw0KICBnZW9tX3RpbGUoDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIGxpbmV3aWR0aCA9IDENCiAgKSArDQogIGdlb21fdGV4dCgNCiAgICBhZXMobGFiZWwgPSByb3VuZChDb3JyZWxhY2lvbiwgMikpLA0KICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICBzaXplID0gMy41DQogICkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50MigNCiAgICBsb3cgPSBtb3JhZG8sDQogICAgbWlkID0gIndoaXRlIiwNCiAgICBoaWdoID0gbWFnZW50YSwNCiAgICBtaWRwb2ludCA9IDAsDQogICAgbGltaXRzID0gYygtMSwgMSksDQogICAgbmFtZSA9ICJDb3JyZWxhY2nDs24iDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIk1hcGEgZGUgY2Fsb3IgZGUgY29ycmVsYWNpb25lcyIsDQogICAgc3VidGl0bGUgPSAiUGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgeSBjb25kaWNpb25lcyBkZWwgZW50b3JubyIsDQogICAgeCA9IE5VTEwsDQogICAgeSA9IE5VTEwsDQogICAgY2FwdGlvbiA9ICJNw6l0b2RvOiBTcGVhcm1hbiB8IEZ1ZW50ZTogRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvIERBTkUsIDIwMjEuIg0KICApICsNCiAgY29vcmRfZml4ZWQoKSArDQogIHRlbWFfY2xhc2UgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dCgNCiAgICAgIGFuZ2xlID0gNDUsDQogICAgICBoanVzdCA9IDEsDQogICAgICBjb2xvciA9IG1vcmFkbw0KICAgICksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoDQogICAgICBjb2xvciA9IG1vcmFkbw0KICAgICksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiDQogICkNCmBgYA0KDQojIyA1LjUuIEFuw6FsaXNpcyBkZSBkZWxpdG9zIGRlIGFsdG8gaW1wYWN0bw0KDQpFbiBlc3RhIHNlY2Npw7NuIHNlIGFuYWxpemEgZWwgY29tcG9ydGFtaWVudG8gZGUgbG9zIGRlbGl0b3MgZGUgYWx0byBpbXBhY3RvIHJlZ2lzdHJhZG9zIGVuIGxhcyBVUFogZGUgQm9nb3TDoSwgY29uIGVsIHByb3DDs3NpdG8gZGUgaWRlbnRpZmljYXIgZGlmZXJlbmNpYXMgdGVycml0b3JpYWxlcyBlbiBsYSBjYW50aWRhZCBkZSBkZW51bmNpYXMgeSBlbiBsYXMgdGFzYXMgZGUgb2N1cnJlbmNpYSBwb3IgaGFiaXRhbnRlLg0KDQpBIGRpZmVyZW5jaWEgZGVsIGFuw6FsaXNpcyBhbnRlcmlvciwgY2VudHJhZG8gZW4gbGEgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgeSBsYXMgY29uZGljaW9uZXMgZGVsIGVudG9ybm8sIGVzdGUgYXBhcnRhZG8gdXRpbGl6YSByZWdpc3Ryb3MgYWRtaW5pc3RyYXRpdm9zIGRlIGRlbGl0b3MgZGVudW5jaWFkb3MuIERlIGVzdGEgbWFuZXJhLCBzZSBidXNjYSBjb21wbGVtZW50YXIgbGEgZXhwbG9yYWNpw7NuIHRlcnJpdG9yaWFsIG1lZGlhbnRlIGluZm9ybWFjacOzbiBzb2JyZSBob21pY2lkaW9zLCBsZXNpb25lcyBwZXJzb25hbGVzLCBodXJ0b3MgeSB2aW9sZW5jaWEgaW50cmFmYW1pbGlhciwgZW50cmUgb3RyYXMgY2F0ZWdvcsOtYXMuDQoNClBhcmEgZWwgYW7DoWxpc2lzIHNlIGNvbnNpZGVyYW4gZG9zIG1lZGlkYXMgcHJpbmNpcGFsZXM6IGVsIG7Dum1lcm8gZGUgY2Fzb3MgcmVnaXN0cmFkb3MgeSBsYSB0YXNhIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzLiBMYSBwcmltZXJhIHBlcm1pdGUgZGltZW5zaW9uYXIgZWwgdm9sdW1lbiBkZSBkZW51bmNpYXMsIG1pZW50cmFzIHF1ZSBsYSBzZWd1bmRhIGZhY2lsaXRhIGxhIGNvbXBhcmFjacOzbiBlbnRyZSBVUFogY29uIHRhbWHDsW9zIHBvYmxhY2lvbmFsZXMgZGlmZXJlbnRlcy4NCg0KRXMgaW1wb3J0YW50ZSBzZcOxYWxhciBxdWUgbG9zIHJlZ2lzdHJvcyBjb3JyZXNwb25kZW4gYWwgcGVyaW9kbyBjb21wcmVuZGlkbyBlbnRyZSBlbmVybyB5IGp1bGlvIGRlIDIwMjMsIHBvciBsbyBxdWUgbm8gcmVwcmVzZW50YW4gZWwgY29tcG9ydGFtaWVudG8gZGUgdG9kbyBlbCBhw7FvLiBBZGVtw6FzLCBzZSB0cmF0YSBkZSBkZW51bmNpYXMgeSBubyBkZSBsYSB0b3RhbGlkYWQgZGUgbG9zIGhlY2hvcyBkZWxpY3Rpdm9zIG9jdXJyaWRvcywgZGViaWRvIGEgbGEgcG9zaWJsZSBleGlzdGVuY2lhIGRlIHN1YnJlZ2lzdHJvLg0KDQpGaW5hbG1lbnRlLCBsYXMgdGFzYXMgZGViZW4gaW50ZXJwcmV0YXJzZSBjb24gcHJlY2F1Y2nDs24gZW4gbGFzIFVQWiBjb24gcG9ibGFjaW9uZXMgcmVkdWNpZGFzLCB5YSBxdWUgdW4gbsO6bWVybyBwZXF1ZcOxbyBkZSBjYXNvcyBwdWVkZSBwcm9kdWNpciB2YWxvcmVzIHJlbGF0aXZhbWVudGUgZWxldmFkb3MuDQoNCmBgYHtyIHNlbGVjY2lvbi12YXJpYWJsZXMtZGVsaXRvcywgZWNobz1UUlVFfQ0KIyBTZWxlY2Npw7NuIGRlIHZhcmlhYmxlcyByZWxhY2lvbmFkYXMgY29uIGxvcyBkZWxpdG9zIGRlIGFsdG8gaW1wYWN0bw0KDQp2YXJpYWJsZXNfZGVsaXRvcyA8LSB1cHogJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfY29kLA0KICAgIHVwel9ub21icmUsDQogICAgbG9jYWxpZGFkLA0KICAgIHBvYmxhY2lvbiwNCiAgICBzdGFydHNfd2l0aCgiY2Fzb3NfIiksDQogICAgc3RhcnRzX3dpdGgoInRhc2FfIikNCiAgKQ0KDQojIFJldmlzYXIgbGFzIHByaW1lcmFzIG9ic2VydmFjaW9uZXMNCg0KaGVhZCh2YXJpYWJsZXNfZGVsaXRvcykNCmBgYA0KDQojIyMgNS41LjIuIEVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzIGRlIGxvcyBkZWxpdG9zIGRlIGFsdG8gaW1wYWN0bw0KDQpDb21vIHB1bnRvIGRlIHBhcnRpZGEsIHNlIGNhbGN1bGFuIGxhcyBwcmluY2lwYWxlcyBtZWRpZGFzIGRlIGVzdGFkw61zdGljYSBkZXNjcmlwdGl2YSBwYXJhIGxhcyB2YXJpYWJsZXMgcmVsYWNpb25hZGFzIGNvbiBsb3MgZGVsaXRvcyBkZSBhbHRvIGltcGFjdG8uIEVzdGUgZWplcmNpY2lvIHBlcm1pdGUgY29ub2NlciBsYSBkaXN0cmlidWNpw7NuIGRlIGxvcyBjYXNvcyByZWdpc3RyYWRvcyB5IGRlIGxhcyB0YXNhcyBwb3IgY2FkYSAxMC4wMDAgaGFiaXRhbnRlcyBlbnRyZSBsYXMgVVBaIGRlIEJvZ290w6EuDQoNClNlIGNvbnNpZGVyYW4gbWVkaWRhcyBkZSB0ZW5kZW5jaWEgY2VudHJhbCwgZGlzcGVyc2nDs24geSBwb3NpY2nDs24sIGNvbW8gbGEgbWVkaWEsIGxhIG1lZGlhbmEsIGxhIGRlc3ZpYWNpw7NuIGVzdMOhbmRhciwgbG9zIHZhbG9yZXMgbcOtbmltb3MgeSBtw6F4aW1vcywgeSBsb3MgY3VhcnRpbGVzIHByaW1lcm8geSB0ZXJjZXJvLg0KDQpFbCBhbsOhbGlzaXMgZGUgZXN0YXMgbWVkaWRhcyBwZXJtaXRlIGlkZW50aWZpY2FyIGRpZmVyZW5jaWFzIGVuIGVsIGNvbXBvcnRhbWllbnRvIGRlIGxvcyBkZWxpdG9zIGVudHJlIGxvcyB0ZXJyaXRvcmlvcy4gVGFtYmnDqW4gZmFjaWxpdGEgcmVjb25vY2VyIHBvc2libGVzIHZhbG9yZXMgZXh0cmVtb3MgeSBlc3RhYmxlY2VyIHNpIGxvcyByZWdpc3Ryb3MgcHJlc2VudGFuIHVuYSBkaXN0cmlidWNpw7NuIGhvbW9nw6luZWEgbyB1bmEgY29uY2VudHJhY2nDs24gaW1wb3J0YW50ZSBlbiBkZXRlcm1pbmFkYXMgVVBaLg0KDQpFcyBpbXBvcnRhbnRlIGRpZmVyZW5jaWFyIGxhIGludGVycHJldGFjacOzbiBkZSBsb3MgY2Fzb3MgeSBsYXMgdGFzYXMuIE1pZW50cmFzIGxvcyBjYXNvcyByZXByZXNlbnRhbiBlbCB2b2x1bWVuIGRlIGRlbnVuY2lhcyByZWdpc3RyYWRhcywgbGFzIHRhc2FzIHBlcm1pdGVuIGNvbXBhcmFyIGxvcyB0ZXJyaXRvcmlvcyBjb25zaWRlcmFuZG8gc3UgdGFtYcOxbyBwb2JsYWNpb25hbC4gU2luIGVtYmFyZ28sIGVzdGFzIMO6bHRpbWFzIHB1ZWRlbiBwcmVzZW50YXIgdmFsb3JlcyBlbGV2YWRvcyBlbiBVUFogY29uIHBvYmxhY2lvbmVzIHJlZHVjaWRhcy4NCg0KIyMjIyBhLiBFc3RhZMOtc3RpY2FzIGRlIGNhc29zIHJlZ2lzdHJhZG9zLg0KDQpgYGB7ciBlc3RhZGlzdGljYXMtY2Fzb3MtZGVsaXRvcywgZWNobz1UUlVFfQ0KIyBTZWxlY2Npw7NuIGRlIHZhcmlhYmxlcyBkZSBjYXNvcyByZWdpc3RyYWRvcw0KDQpkYXRvc19jYXNvcyA8LSB2YXJpYWJsZXNfZGVsaXRvcyAlPiUNCiAgc2VsZWN0KHN0YXJ0c193aXRoKCJjYXNvc18iKSkNCg0KIyBDw6FsY3VsbyBkZSBlc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcw0KDQplc3RhZGlzdGljYXNfY2Fzb3MgPC0gZGF0b3NfY2Fzb3MgJT4lDQogIHBpdm90X2xvbmdlcigNCiAgICBjb2xzID0gZXZlcnl0aGluZygpLA0KICAgIG5hbWVzX3RvID0gIkRlbGl0byIsDQogICAgdmFsdWVzX3RvID0gIkNhc29zIg0KICApICU+JQ0KICBncm91cF9ieShEZWxpdG8pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgTWVkaWEgPSBtZWFuKENhc29zKSwNCiAgICBNZWRpYW5hID0gbWVkaWFuKENhc29zKSwNCiAgICBEZXN2aWFjaW9uID0gc2QoQ2Fzb3MpLA0KICAgIE1pbmltbyA9IG1pbihDYXNvcyksDQogICAgUTEgPSBxdWFudGlsZShDYXNvcywgMC4yNSksDQogICAgUTMgPSBxdWFudGlsZShDYXNvcywgMC43NSksDQogICAgTWF4aW1vID0gbWF4KENhc29zKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkgJT4lDQogIGFycmFuZ2UoZGVzYyhNZWRpYSkpDQoNCiMgUHJlc2VudGFjacOzbiBkZSByZXN1bHRhZG9zDQoNCmtuaXRyOjprYWJsZSgNCiAgZXN0YWRpc3RpY2FzX2Nhc29zLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIkVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzIGRlIGxvcyBjYXNvcyBkZSBkZWxpdG9zIHBvciBVUFoiDQopDQpgYGANCg0KIyMjIyBiLiBFc3RhZMOtc3RpY2FzIGRlIHRhc2FzIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzLg0KDQpgYGB7ciBlc3RhZGlzdGljYXMtdGFzYXMtZGVsaXRvcywgZWNobz1UUlVFfQ0KIyBTZWxlY2Npw7NuIGRlIHZhcmlhYmxlcyBkZSB0YXNhcw0KDQpkYXRvc190YXNhcyA8LSB2YXJpYWJsZXNfZGVsaXRvcyAlPiUNCiAgc2VsZWN0KHN0YXJ0c193aXRoKCJ0YXNhXyIpKQ0KDQojIEPDoWxjdWxvIGRlIGVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzDQoNCmVzdGFkaXN0aWNhc190YXNhcyA8LSBkYXRvc190YXNhcyAlPiUNCiAgcGl2b3RfbG9uZ2VyKA0KICAgIGNvbHMgPSBldmVyeXRoaW5nKCksDQogICAgbmFtZXNfdG8gPSAiRGVsaXRvIiwNCiAgICB2YWx1ZXNfdG8gPSAiVGFzYSINCiAgKSAlPiUNCiAgZ3JvdXBfYnkoRGVsaXRvKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE1lZGlhID0gbWVhbihUYXNhKSwNCiAgICBNZWRpYW5hID0gbWVkaWFuKFRhc2EpLA0KICAgIERlc3ZpYWNpb24gPSBzZChUYXNhKSwNCiAgICBNaW5pbW8gPSBtaW4oVGFzYSksDQogICAgUTEgPSBxdWFudGlsZShUYXNhLCAwLjI1KSwNCiAgICBRMyA9IHF1YW50aWxlKFRhc2EsIDAuNzUpLA0KICAgIE1heGltbyA9IG1heChUYXNhKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkgJT4lDQogIGFycmFuZ2UoZGVzYyhNZWRpYSkpDQoNCiMgUHJlc2VudGFjacOzbiBkZSByZXN1bHRhZG9zDQoNCmtuaXRyOjprYWJsZSgNCiAgZXN0YWRpc3RpY2FzX3Rhc2FzLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIkVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzIGRlIGxhcyB0YXNhcyBkZSBkZWxpdG9zIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzIHkgcG9yIFVQWiINCikNCmBgYA0KDQojIyMgNS41LjMuIERpc3RyaWJ1Y2nDs24gZGUgbG9zIGRlbGl0b3MgZGUgYWx0byBpbXBhY3RvDQoNCkNvbiBlbCBwcm9ww7NzaXRvIGRlIGNvbXBsZW1lbnRhciBsYXMgbWVkaWRhcyBkZXNjcmlwdGl2YXMsIHNlIGFuYWxpemEgbGEgZGlzdHJpYnVjacOzbiBkZSBsb3MgY2Fzb3MgcmVnaXN0cmFkb3MgeSBkZSBsYXMgdGFzYXMgZGUgZGVsaXRvcyBlbnRyZSBsYXMgVVBaIGRlIEJvZ290w6EuDQoNClBhcmEgZWxsbyBzZSB1dGlsaXphbiBoaXN0b2dyYW1hcyBxdWUgcGVybWl0ZW4gb2JzZXJ2YXIgbGEgZnJlY3VlbmNpYSBjb24gbGEgcXVlIHNlIHByZXNlbnRhbiBkZXRlcm1pbmFkb3MgcmFuZ29zIGRlIHZhbG9yZXMuIEVzdGEgcmVwcmVzZW50YWNpw7NuIGZhY2lsaXRhIGlkZW50aWZpY2FyIGNvbmNlbnRyYWNpb25lcywgYXNpbWV0csOtYXMgeSBwb3NpYmxlcyBvYnNlcnZhY2lvbmVzIGV4dHJlbWFzIGVuIGxhcyBkaWZlcmVudGVzIGNhdGVnb3LDrWFzIGRlIGRlbGl0b3MuDQoNCkVuIHByaW1lciBsdWdhciwgc2UgZXhhbWluYSBsYSBkaXN0cmlidWNpw7NuIGRlbCBuw7ptZXJvIGRlIGNhc29zIHJlZ2lzdHJhZG9zLiBQb3N0ZXJpb3JtZW50ZSwgc2UgcmVhbGl6YSBlbCBtaXNtbyBlamVyY2ljaW8gcGFyYSBsYXMgdGFzYXMgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMsIGNvbiBlbCBmaW4gZGUgcmVjb25vY2VyIHNpIGVsIGNvbXBvcnRhbWllbnRvIGRlIGxvcyBkZWxpdG9zIGNhbWJpYSBhbCBjb25zaWRlcmFyIGVsIHRhbWHDsW8gcG9ibGFjaW9uYWwgZGUgY2FkYSB0ZXJyaXRvcmlvLg0KDQpMYSBjb21wYXJhY2nDs24gZGUgYW1iYXMgZGlzdHJpYnVjaW9uZXMgcGVybWl0ZSBkaXN0aW5ndWlyIGVudHJlIGxhIGNvbmNlbnRyYWNpw7NuIGRlIGRlbnVuY2lhcyB5IGxhcyBkaWZlcmVuY2lhcyByZWxhdGl2YXMgZW50cmUgbGFzIFVQWi4gU2UgZGViZSB0ZW5lciBlbiBjdWVudGEgcXVlIGxhcyBlc2NhbGFzIGRlIGxvcyBncsOhZmljb3Mgc29uIGluZGVwZW5kaWVudGVzIHBhcmEgZmFjaWxpdGFyIGxhIHZpc3VhbGl6YWNpw7NuIGRlIGNhZGEgY2F0ZWdvcsOtYS4NCg0KYGBge3IgZGlzdHJpYnVjaW9uLWNhc29zLWRlbGl0b3MsIGVjaG89VFJVRX0NCiMgT3JnYW5pemFjacOzbiBkZSBsb3MgY2Fzb3MgZW4gZm9ybWF0byBsYXJnbw0KDQpkaXN0cmlidWNpb25fY2Fzb3MgPC0gdmFyaWFibGVzX2RlbGl0b3MgJT4lDQogIHNlbGVjdChzdGFydHNfd2l0aCgiY2Fzb3NfIikpICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGV2ZXJ5dGhpbmcoKSwNCiAgICBuYW1lc190byA9ICJEZWxpdG8iLA0KICAgIHZhbHVlc190byA9ICJDYXNvcyINCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIERlbGl0byA9IHN0cl9yZW1vdmUoRGVsaXRvLCAiXmNhc29zXyIpLA0KICAgIERlbGl0byA9IHN0cl9yZXBsYWNlX2FsbChEZWxpdG8sICJfIiwgIiAiKSwNCiAgICBEZWxpdG8gPSBzdHJfdG9fdGl0bGUoRGVsaXRvKQ0KICApDQoNCiMgSGlzdG9ncmFtYSBkZSBjYXNvcyBwb3IgY2F0ZWdvcsOtYSBkZSBkZWxpdG8NCg0KZ2dwbG90KA0KICBkaXN0cmlidWNpb25fY2Fzb3MsDQogIGFlcyh4ID0gQ2Fzb3MpDQopICsNCiAgZ2VvbV9oaXN0b2dyYW0oDQogICAgYmlucyA9IDE1LA0KICAgIGZpbGwgPSB0dXJxdWVzYSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgYWxwaGEgPSAwLjg1DQogICkgKw0KICBmYWNldF93cmFwKA0KICAgIH5EZWxpdG8sDQogICAgc2NhbGVzID0gImZyZWVfeCINCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBsb3MgY2Fzb3MgZGUgZGVsaXRvcyBwb3IgVVBaIiwNCiAgICBzdWJ0aXRsZSA9ICJOw7ptZXJvIGRlIGRlbnVuY2lhcyByZWdpc3RyYWRhcyBlbnRyZSBlbmVybyB5IGp1bGlvIGRlIDIwMjMiLA0KICAgIHggPSAiTsO6bWVybyBkZSBjYXNvcyIsDQogICAgeSA9ICJDYW50aWRhZCBkZSBVUFoiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBTZWNyZXRhcsOtYSBEaXN0cml0YWwgZGUgU2VndXJpZGFkLCBDb252aXZlbmNpYSB5IEp1c3RpY2lhLCAyMDIzLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQpgYGB7ciBkaXN0cmlidWNpb24tdGFzYXMtZGVsaXRvcywgZWNobz1UUlVFfQ0KIyBPcmdhbml6YWNpw7NuIGRlIGxhcyB0YXNhcyBlbiBmb3JtYXRvIGxhcmdvDQoNCmRpc3RyaWJ1Y2lvbl90YXNhcyA8LSB2YXJpYWJsZXNfZGVsaXRvcyAlPiUNCiAgc2VsZWN0KHN0YXJ0c193aXRoKCJ0YXNhXyIpKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKA0KICAgIGNvbHMgPSBldmVyeXRoaW5nKCksDQogICAgbmFtZXNfdG8gPSAiRGVsaXRvIiwNCiAgICB2YWx1ZXNfdG8gPSAiVGFzYSINCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIERlbGl0byA9IHN0cl9yZW1vdmUoRGVsaXRvLCAiXnRhc2FfIiksDQogICAgRGVsaXRvID0gc3RyX3JlcGxhY2VfYWxsKERlbGl0bywgIl8iLCAiICIpLA0KICAgIERlbGl0byA9IHN0cl90b190aXRsZShEZWxpdG8pDQogICkNCg0KIyBIaXN0b2dyYW1hIGRlIHRhc2FzIHBvciBjYXRlZ29yw61hIGRlIGRlbGl0bw0KDQpnZ3Bsb3QoDQogIGRpc3RyaWJ1Y2lvbl90YXNhcywNCiAgYWVzKHggPSBUYXNhKQ0KKSArDQogIGdlb21faGlzdG9ncmFtKA0KICAgIGJpbnMgPSAxNSwNCiAgICBmaWxsID0gbWFnZW50YSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgYWxwaGEgPSAwLjg1DQogICkgKw0KICBmYWNldF93cmFwKA0KICAgIH5EZWxpdG8sDQogICAgc2NhbGVzID0gImZyZWVfeCINCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBsYXMgdGFzYXMgZGUgZGVsaXRvcyBwb3IgVVBaIiwNCiAgICBzdWJ0aXRsZSA9ICJDYXNvcyByZWdpc3RyYWRvcyBwb3IgY2FkYSAxMC4wMDAgaGFiaXRhbnRlcyIsDQogICAgeCA9ICJUYXNhIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzIiwNCiAgICB5ID0gIkNhbnRpZGFkIGRlIFVQWiIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IFNlY3JldGFyw61hIERpc3RyaXRhbCBkZSBTZWd1cmlkYWQsIENvbnZpdmVuY2lhIHkgSnVzdGljaWEsIDIwMjMuIg0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQoNCiMjIyA1LjUuNC4gUGFydGljaXBhY2nDs24gZGUgY2FkYSBkZWxpdG8gZW4gZWwgdG90YWwgZGUgY2Fzb3MgcmVnaXN0cmFkb3MNCg0KQ29uIGVsIHByb3DDs3NpdG8gZGUgaWRlbnRpZmljYXIgY3XDoWxlcyBjYXRlZ29yw61hcyBjb25jZW50cmFuIHVuYSBtYXlvciBwcm9wb3JjacOzbiBkZSBsYXMgZGVudW5jaWFzIHJlZ2lzdHJhZGFzLCBzZSBhbmFsaXphIGxhIGNvbXBvc2ljacOzbiBkZWwgdG90YWwgZGUgY2Fzb3MgZGUgZGVsaXRvcyBkZSBhbHRvIGltcGFjdG8gZW4gbGFzIFVQWiBlc3R1ZGlhZGFzLg0KDQpQYXJhIGVzdGUgZWplcmNpY2lvIHNlIHN1bWFuIGxvcyBjYXNvcyByZWdpc3RyYWRvcyBlbiBjYWRhIGNhdGVnb3LDrWEgZGUgZGVsaXRvIHkgc2UgY2FsY3VsYSBzdSBwYXJ0aWNpcGFjacOzbiBwb3JjZW50dWFsIGZyZW50ZSBhbCB0b3RhbCBkZSBkZW51bmNpYXMgYWN1bXVsYWRhcy4gTG9zIHJlc3VsdGFkb3Mgc2UgcHJlc2VudGFuIG1lZGlhbnRlIHVuYSB0YWJsYSB5IHVuIGdyw6FmaWNvIGRlIGJhcnJhcyBxdWUgZmFjaWxpdGFuIGxhIGNvbXBhcmFjacOzbiBlbnRyZSBsYXMgZGlmZXJlbnRlcyBjYXRlZ29yw61hcy4NCg0KRXN0ZSBhbsOhbGlzaXMgcGVybWl0ZSByZWNvbm9jZXIgbGEgY29tcG9zaWNpw7NuIGRlIGxvcyByZWdpc3Ryb3MgYWRtaW5pc3RyYXRpdm9zIHkgZXN0YWJsZWNlciBjdcOhbGVzIHRpcG9zIGRlIGRlbGl0b3MgdGllbmVuIG1heW9yIHBhcnRpY2lwYWNpw7NuIGRlbnRybyBkZWwgY29uanVudG8gYW5hbGl6YWRvLg0KDQpQYXJhIGV2aXRhciBkdXBsaWNhY2lvbmVzLCBzZSBleGNsdXllIGxhIHZhcmlhYmxlIGRlIHRvdGFsIGRlIGNhc29zIGRlbCBjw6FsY3VsbywgZGFkbyBxdWUgZXN0YSBjb3JyZXNwb25kZSBhIGxhIHN1bWEgZGUgbGFzIGNhdGVnb3LDrWFzIGluZGl2aWR1YWxlcy4gTG9zIHJlc3VsdGFkb3Mgc2UgbGltaXRhbiBhbCBwZXJpb2RvIGNvbXByZW5kaWRvIGVudHJlIGVuZXJvIHkganVsaW8gZGUgMjAyMyB5IHJlcHJlc2VudGFuIGRlbnVuY2lhcyByZWdpc3RyYWRhcywgbm8gbmVjZXNhcmlhbWVudGUgbGEgdG90YWxpZGFkIGRlIGxvcyBoZWNob3Mgb2N1cnJpZG9zLg0KDQpgYGB7ciBwYXJ0aWNpcGFjaW9uLWRlbGl0b3MsIGVjaG89VFJVRX0NCiMgU3VtYXIgbG9zIGNhc29zIHJlZ2lzdHJhZG9zIHBvciBjYXRlZ29yw61hIGRlIGRlbGl0bw0KIyBTZSBleGNsdXllIGNhc29zX3RvdGFsIHBvcnF1ZSB5YSBjb250aWVuZSBsYSBzdW1hIGRlIGxhcyBjYXRlZ29yw61hcw0KDQpwYXJ0aWNpcGFjaW9uX2RlbGl0b3MgPC0gdmFyaWFibGVzX2RlbGl0b3MgJT4lDQogIHNlbGVjdChzdGFydHNfd2l0aCgiY2Fzb3NfIiksIC1jYXNvc190b3RhbCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBhY3Jvc3MoZXZlcnl0aGluZygpLCB+c3VtKC4pKQ0KICApICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGV2ZXJ5dGhpbmcoKSwNCiAgICBuYW1lc190byA9ICJEZWxpdG8iLA0KICAgIHZhbHVlc190byA9ICJDYXNvcyINCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIERlbGl0byA9IHN0cl9yZW1vdmUoRGVsaXRvLCAiXmNhc29zXyIpLA0KICAgIERlbGl0byA9IHN0cl9yZXBsYWNlX2FsbChEZWxpdG8sICJfIiwgIiAiKSwNCiAgICBEZWxpdG8gPSBzdHJfdG9fdGl0bGUoRGVsaXRvKSwNCiAgICBQYXJ0aWNpcGFjaW9uID0gQ2Fzb3MgLyBzdW0oQ2Fzb3MpICogMTAwDQogICkgJT4lDQogIGFycmFuZ2UoZGVzYyhQYXJ0aWNpcGFjaW9uKSkNCg0KIyBQcmVzZW50YWNpw7NuIGRlIHJlc3VsdGFkb3MNCg0Ka25pdHI6OmthYmxlKA0KICBwYXJ0aWNpcGFjaW9uX2RlbGl0b3MsDQogIGRpZ2l0cyA9IDIsDQogIGNvbC5uYW1lcyA9IGMoIlRpcG8gZGUgZGVsaXRvIiwgIkNhc29zIHJlZ2lzdHJhZG9zIiwgIlBhcnRpY2lwYWNpw7NuICglKSIpLA0KICBjYXB0aW9uID0gIlBhcnRpY2lwYWNpw7NuIGRlIGNhZGEgY2F0ZWdvcsOtYSBlbiBlbCB0b3RhbCBkZSBjYXNvcyByZWdpc3RyYWRvcyINCikNCmBgYA0KDQpgYGB7ciBncmFmaWNvLXBhcnRpY2lwYWNpb24tZGVsaXRvcywgZWNobz1UUlVFfQ0KZ2dwbG90KA0KICBwYXJ0aWNpcGFjaW9uX2RlbGl0b3MsDQogIGFlcygNCiAgICB4ID0gcmVvcmRlcihEZWxpdG8sIFBhcnRpY2lwYWNpb24pLA0KICAgIHkgPSBQYXJ0aWNpcGFjaW9uDQogICkNCikgKw0KICBnZW9tX2NvbCgNCiAgICBmaWxsID0gbWFnZW50YSwNCiAgICB3aWR0aCA9IDAuNw0KICApICsNCiAgZ2VvbV90ZXh0KA0KICAgIGFlcyhsYWJlbCA9IHBhc3RlMChyb3VuZChQYXJ0aWNpcGFjaW9uLCAxKSwgIiUiKSksDQogICAgaGp1c3QgPSAtMC4xNSwNCiAgICBzaXplID0gMy41LA0KICAgIGNvbG9yID0gbW9yYWRvDQogICkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoc3VmZml4ID0gIiUiKSwNCiAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4xNSkpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkNvbXBvc2ljacOzbiBkZSBsb3MgZGVsaXRvcyBkZSBhbHRvIGltcGFjdG8iLA0KICAgIHN1YnRpdGxlID0gIlBhcnRpY2lwYWNpw7NuIHBvcmNlbnR1YWwgZGUgY2FkYSBjYXRlZ29yw61hIGVuIGxvcyBjYXNvcyByZWdpc3RyYWRvcyIsDQogICAgeCA9IE5VTEwsDQogICAgeSA9ICJQYXJ0aWNpcGFjacOzbiAoJSkiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBTZWNyZXRhcsOtYSBEaXN0cml0YWwgZGUgU2VndXJpZGFkLCBDb252aXZlbmNpYSB5IEp1c3RpY2lhLCBlbmVyby1qdWxpbyBkZSAyMDIzLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMgNS41LjUuIElkZW50aWZpY2FjacOzbiBkZSBsYXMgVVBaIGNvbiBtYXlvciBuw7ptZXJvIGRlIGNhc29zIHJlZ2lzdHJhZG9zDQoNClVuYSB2ZXogYW5hbGl6YWRhIGxhIGNvbXBvc2ljacOzbiBnZW5lcmFsIGRlIGxvcyBkZWxpdG9zLCBzZSBpZGVudGlmaWNhbiBsYXMgVVBaIHF1ZSBjb25jZW50cmFuIGVsIG1heW9yIG7Dum1lcm8gZGUgY2Fzb3MgcmVnaXN0cmFkb3MgZHVyYW50ZSBlbCBwZXJpb2RvIGRlIGVzdHVkaW8uDQoNClBhcmEgZWxsbyBzZSBjb25zdHJ1eWUgdW4gcmFua2luZyBkZSBsYXMgZGlleiBVUFogY29uIG1heW9yIGNhbnRpZGFkIGRlIGRlbnVuY2lhcyBwb3IgZGVsaXRvcyBkZSBhbHRvIGltcGFjdG8uIExhIGNvbXBhcmFjacOzbiBpbmNvcnBvcmEgbGEgcG9ibGFjacOzbiB5IGxhIHRhc2EgdG90YWwgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMsIGNvbiBlbCBwcm9ww7NzaXRvIGRlIGNvbXBsZW1lbnRhciBsYSBsZWN0dXJhIGRlbCB2b2x1bWVuIGRlIGNhc29zIGNvbiB1bmEgbWVkaWRhIHJlbGF0aXZhIGFsIHRhbWHDsW8gcG9ibGFjaW9uYWwuDQoNCkVzdGUgZWplcmNpY2lvIHBlcm1pdGUgcmVjb25vY2VyIGxvcyB0ZXJyaXRvcmlvcyBxdWUgYWN1bXVsYW4gbcOhcyByZWdpc3Ryb3MgeSBleHBsb3JhciBzaSBzdSBwb3NpY2nDs24gZW4gZWwgcmFua2luZyBjb2luY2lkZSBjb24gdGFzYXMgZWxldmFkYXMgbyBzaSBwdWVkZSBlc3RhciByZWxhY2lvbmFkYSBjb24gdW5hIG1heW9yIGNvbmNlbnRyYWNpw7NuIGRlIGhhYml0YW50ZXMuDQoNCkxhIGlkZW50aWZpY2FjacOzbiBkZSBlc3RhcyBVUFogY29uc3RpdHV5ZSB1biBwcmltZXIgYWNlcmNhbWllbnRvIGEgbGFzIGRpZmVyZW5jaWFzIHRlcnJpdG9yaWFsZXMgZW4gbG9zIHJlZ2lzdHJvcyBkZSBkZWxpdG9zLiBTaW4gZW1iYXJnbywgZWwgbsO6bWVybyBkZSBkZW51bmNpYXMgbm8gZGViZSBpbnRlcnByZXRhcnNlIHBvciBzw60gc29sbyBjb21vIHVuYSBtZWRpZGEgZGUgcmllc2dvIGluZGl2aWR1YWwgbmkgY29tbyB1bmEgcmVwcmVzZW50YWNpw7NuIGNvbXBsZXRhIGRlIGxvcyBoZWNob3MgZGVsaWN0aXZvcyBvY3Vycmlkb3MuDQoNCmBgYHtyIHJhbmtpbmctdXB6LWNhc29zLWRlbGl0b3MsIGVjaG89VFJVRX0NCiMgSWRlbnRpZmljYWNpw7NuIGRlIGxhcyBkaWV6IFVQWiBjb24gbWF5b3IgbsO6bWVybyBkZSBjYXNvcw0KDQpyYW5raW5nX2Nhc29zX2RlbGl0b3MgPC0gdmFyaWFibGVzX2RlbGl0b3MgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICBwb2JsYWNpb24sDQogICAgY2Fzb3NfdG90YWwsDQogICAgdGFzYV90b3RhbA0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MoY2Fzb3NfdG90YWwpKSAlPiUNCiAgc2xpY2VfaGVhZChuID0gMTApDQoNCiMgUHJlc2VudGFjacOzbiBkZWwgcmFua2luZw0KDQprbml0cjo6a2FibGUoDQogIHJhbmtpbmdfY2Fzb3NfZGVsaXRvcywNCiAgZGlnaXRzID0gMiwNCiAgY29sLm5hbWVzID0gYygNCiAgICAiVVBaIiwNCiAgICAiTG9jYWxpZGFkIiwNCiAgICAiUG9ibGFjacOzbiIsDQogICAgIkNhc29zIHRvdGFsZXMiLA0KICAgICJUYXNhIHBvciAxMC4wMDAgaGFiLiINCiAgKSwNCiAgY2FwdGlvbiA9ICJEaWV6IFVQWiBjb24gbWF5b3IgbsO6bWVybyBkZSBjYXNvcyBkZSBkZWxpdG9zIGRlIGFsdG8gaW1wYWN0byINCikNCmBgYA0KDQpgYGB7ciBncmFmaWNvLXJhbmtpbmctY2Fzb3MtZGVsaXRvcywgZWNobz1UUlVFfQ0KZ2dwbG90KA0KICByYW5raW5nX2Nhc29zX2RlbGl0b3MsDQogIGFlcygNCiAgICB4ID0gcmVvcmRlcih1cHpfbm9tYnJlLCBjYXNvc190b3RhbCksDQogICAgeSA9IGNhc29zX3RvdGFsDQogICkNCikgKw0KICBnZW9tX2NvbCgNCiAgICBmaWxsID0gbWFnZW50YSwNCiAgICB3aWR0aCA9IDAuNw0KICApICsNCiAgZ2VvbV90ZXh0KA0KICAgIGFlcyhsYWJlbCA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKGJpZy5tYXJrID0gIi4iKShjYXNvc190b3RhbCkpLA0KICAgIGhqdXN0ID0gLTAuMTUsDQogICAgc2l6ZSA9IDMuNSwNCiAgICBjb2xvciA9IG1vcmFkbw0KICApICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKGJpZy5tYXJrID0gIi4iKSwNCiAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4xNSkpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlVQWiBjb24gbWF5b3IgbsO6bWVybyBkZSBjYXNvcyByZWdpc3RyYWRvcyIsDQogICAgc3VidGl0bGUgPSAiRGlleiB0ZXJyaXRvcmlvcyBjb24gbcOhcyBkZW51bmNpYXMgZW50cmUgZW5lcm8geSBqdWxpbyBkZSAyMDIzIiwNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gIk7Dum1lcm8gZGUgY2Fzb3MiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBTZWNyZXRhcsOtYSBEaXN0cml0YWwgZGUgU2VndXJpZGFkLCBDb252aXZlbmNpYSB5IEp1c3RpY2lhLCAyMDIzLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMgNS41LjYuIElkZW50aWZpY2FjacOzbiBkZSBsYXMgVVBaIGNvbiBtYXlvcmVzIHRhc2FzIGRlIGRlbGl0b3MNCg0KQSBkaWZlcmVuY2lhIGRlbCByYW5raW5nIGFudGVyaW9yLCBjZW50cmFkbyBlbiBlbCB2b2x1bWVuIGRlIGRlbnVuY2lhcywgZW4gZXN0ZSBhcGFydGFkbyBzZSBpZGVudGlmaWNhbiBsYXMgVVBaIHF1ZSBwcmVzZW50YW4gbGFzIG1heW9yZXMgdGFzYXMgZGUgZGVsaXRvcyBkZSBhbHRvIGltcGFjdG8gcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMuDQoNCkVzdGEgY29tcGFyYWNpw7NuIHBlcm1pdGUgaW5jb3Jwb3JhciBlbCB0YW1hw7FvIHBvYmxhY2lvbmFsIGNvbW8gZWxlbWVudG8gZGUgcmVmZXJlbmNpYSB5IHJlY29ub2NlciB0ZXJyaXRvcmlvcyBxdWUsIGF1bnF1ZSBubyBuZWNlc2FyaWFtZW50ZSBjb25jZW50cmFuIGxhIG1heW9yIGNhbnRpZGFkIGRlIGNhc29zLCBwcmVzZW50YW4gdmFsb3JlcyBlbGV2YWRvcyBlbiByZWxhY2nDs24gY29uIHN1IHBvYmxhY2nDs24uDQoNClBhcmEgZWxsbyBzZSBjb25zdHJ1eWUgdW4gcmFua2luZyBkZSBsYXMgZGlleiBVUFogY29uIG1heW9yZXMgdGFzYXMgdG90YWxlcy4gQWRpY2lvbmFsbWVudGUsIHNlIGluY2x1eWVuIGVsIG7Dum1lcm8gZGUgY2Fzb3MgcmVnaXN0cmFkb3MgeSBsYSBwb2JsYWNpw7NuIGRlIGNhZGEgdGVycml0b3JpbywgY29uIGVsIHByb3DDs3NpdG8gZGUgZmFjaWxpdGFyIGxhIGludGVycHJldGFjacOzbiBkZSBsb3MgcmVzdWx0YWRvcy4NCg0KU2UgZGViZSBwcmVzdGFyIGVzcGVjaWFsIGF0ZW5jacOzbiBhIGxhcyBVUFogY29uIHBvYmxhY2lvbmVzIHJlZHVjaWRhcywgZGViaWRvIGEgcXVlIHVuIG7Dum1lcm8gcGVxdWXDsW8gZGUgZGVudW5jaWFzIHB1ZWRlIGdlbmVyYXIgdGFzYXMgZWxldmFkYXMuIFBvciBlc3RhIHJhesOzbiwgZWwgcmFua2luZyBzZSBjb25zaWRlcmEgdW5hIGhlcnJhbWllbnRhIGV4cGxvcmF0b3JpYSB5IG5vIHVuYSBjbGFzaWZpY2FjacOzbiBkZWZpbml0aXZhIGRlbCByaWVzZ28gZGUgaW5zZWd1cmlkYWQgZGUgbG9zIHRlcnJpdG9yaW9zLg0KDQpgYGB7ciByYW5raW5nLXVwei10YXNhcy1kZWxpdG9zLCBlY2hvPVRSVUV9DQojIElkZW50aWZpY2FjacOzbiBkZSBsYXMgZGlleiBVUFogY29uIG1heW9yZXMgdGFzYXMgZGUgZGVsaXRvcw0KDQpyYW5raW5nX3Rhc2FzX2RlbGl0b3MgPC0gdmFyaWFibGVzX2RlbGl0b3MgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICBwb2JsYWNpb24sDQogICAgY2Fzb3NfdG90YWwsDQogICAgdGFzYV90b3RhbA0KICApICU+JQ0KICBhcnJhbmdlKGRlc2ModGFzYV90b3RhbCkpICU+JQ0KICBzbGljZV9oZWFkKG4gPSAxMCkNCg0KIyBQcmVzZW50YWNpw7NuIGRlbCByYW5raW5nDQoNCmtuaXRyOjprYWJsZSgNCiAgcmFua2luZ190YXNhc19kZWxpdG9zLA0KICBkaWdpdHMgPSAyLA0KICBjb2wubmFtZXMgPSBjKA0KICAgICJVUFoiLA0KICAgICJMb2NhbGlkYWQiLA0KICAgICJQb2JsYWNpw7NuIiwNCiAgICAiQ2Fzb3MgdG90YWxlcyIsDQogICAgIlRhc2EgcG9yIDEwLjAwMCBoYWIuIg0KICApLA0KICBjYXB0aW9uID0gIkRpZXogVVBaIGNvbiBtYXlvcmVzIHRhc2FzIGRlIGRlbGl0b3MgZGUgYWx0byBpbXBhY3RvIg0KKQ0KYGBgDQoNCmBgYHtyIGdyYWZpY28tcmFua2luZy10YXNhcy1kZWxpdG9zLCBlY2hvPVRSVUV9DQpnZ3Bsb3QoDQogIHJhbmtpbmdfdGFzYXNfZGVsaXRvcywNCiAgYWVzKA0KICAgIHggPSByZW9yZGVyKHVwel9ub21icmUsIHRhc2FfdG90YWwpLA0KICAgIHkgPSB0YXNhX3RvdGFsDQogICkNCikgKw0KICBnZW9tX2NvbCgNCiAgICBmaWxsID0gdHVycXVlc2EsDQogICAgd2lkdGggPSAwLjcNCiAgKSArDQogIGdlb21fdGV4dCgNCiAgICBhZXMobGFiZWwgPSByb3VuZCh0YXNhX3RvdGFsLCAxKSksDQogICAgaGp1c3QgPSAtMC4xNSwNCiAgICBzaXplID0gMy41LA0KICAgIGNvbG9yID0gbW9yYWRvDQogICkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAsIDAuMTUpKQ0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJVUFogY29uIG1heW9yZXMgdGFzYXMgZGUgZGVsaXRvcyIsDQogICAgc3VidGl0bGUgPSAiQ2Fzb3MgcmVnaXN0cmFkb3MgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMiLA0KICAgIHggPSBOVUxMLA0KICAgIHkgPSAiVGFzYSBwb3IgY2FkYSAxMC4wMDAgaGFiaXRhbnRlcyIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IFNlY3JldGFyw61hIERpc3RyaXRhbCBkZSBTZWd1cmlkYWQsIENvbnZpdmVuY2lhIHkgSnVzdGljaWEgeSBwcm95ZWNjaW9uZXMgZGUgcG9ibGFjacOzbiBEQU5FLCAyMDIzLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMgNS41LjcuIENvbXBhcmFjacOzbiBlbnRyZSBlbCB2b2x1bWVuIGRlIGNhc29zIHkgbGFzIHRhc2FzIGRlIGRlbGl0b3MNCg0KQ29uIGVsIHByb3DDs3NpdG8gZGUgcHJvZnVuZGl6YXIgZW4gbGFzIGRpZmVyZW5jaWFzIHRlcnJpdG9yaWFsZXMsIHNlIHJlYWxpemEgdW5hIGNvbXBhcmFjacOzbiBlbnRyZSBlbCBuw7ptZXJvIHRvdGFsIGRlIGNhc29zIHJlZ2lzdHJhZG9zIHkgbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzLg0KDQpFc3RlIGVqZXJjaWNpbyBwZXJtaXRlIGV4cGxvcmFyIHNpIGxhcyBVUFogcXVlIGNvbmNlbnRyYW4gbWF5b3JlcyBjYW50aWRhZGVzIGRlIGRlbnVuY2lhcyB0YW1iacOpbiBwcmVzZW50YW4gdGFzYXMgZWxldmFkYXMgYWwgY29uc2lkZXJhciBzdSB0YW1hw7FvIHBvYmxhY2lvbmFsLiBQYXJhIGVsbG8gc2UgdXRpbGl6YSB1biBncsOhZmljbyBkZSBkaXNwZXJzacOzbiBlbiBlbCBxdWUgY2FkYSBwdW50byByZXByZXNlbnRhIHVuYSBVUFogeSBzdSB0YW1hw7FvIHBlcm1pdGUgdmlzdWFsaXphciBkZSBtYW5lcmEgY29tcGxlbWVudGFyaWEgbGEgcG9ibGFjacOzbiBkZSBjYWRhIHRlcnJpdG9yaW8uDQoNCkFkaWNpb25hbG1lbnRlLCBzZSBpbmNvcnBvcmFuIGzDrW5lYXMgZGUgcmVmZXJlbmNpYSBjb3JyZXNwb25kaWVudGVzIGEgbGFzIG1lZGlhbmFzIGRlIGNhc29zIHkgdGFzYXMsIGNvbiBlbCBwcm9ww7NzaXRvIGRlIGRpdmlkaXIgZWwgZ3LDoWZpY28gZW4gY3VhdHJvIGN1YWRyYW50ZXMuIEVzdGEgY2xhc2lmaWNhY2nDs24gZmFjaWxpdGEgcmVjb25vY2VyIGRpZmVyZW50ZXMgY29tcG9ydGFtaWVudG9zIHRlcnJpdG9yaWFsZXM6IFVQWiBjb24gdmFsb3JlcyBhbHRvcyBlbiBhbWJhcyBtZWRpZGFzLCB0ZXJyaXRvcmlvcyBjb24gbXVjaG9zIGNhc29zIHBlcm8gdGFzYXMgcmVsYXRpdmFtZW50ZSBiYWphcywgem9uYXMgY29uIHBvY29zIGNhc29zIHkgdGFzYXMgZWxldmFkYXMsIHkgdGVycml0b3Jpb3MgY29uIHZhbG9yZXMgYmFqb3MgZW4gYW1ib3MgaW5kaWNhZG9yZXMuDQoNCkVzdGEgY29tcGFyYWNpw7NuIHBlcm1pdGUgY29tcHJlbmRlciBxdWUgZWwgdm9sdW1lbiBkZSBkZW51bmNpYXMgeSBsYSB0YXNhIHBvciBoYWJpdGFudGUgcmVwcmVzZW50YW4gZGltZW5zaW9uZXMgZGlmZXJlbnRlcyBkZWwgZmVuw7NtZW5vLiBTaW4gZW1iYXJnbywgbG9zIHJlc3VsdGFkb3MgZGViZW4gaW50ZXJwcmV0YXJzZSBjb25zaWRlcmFuZG8gcXVlIGxhcyB0YXNhcyBwdWVkZW4gcHJlc2VudGFyIHZhbG9yZXMgZXh0cmVtb3MgZW4gVVBaIGNvbiBwb2JsYWNpb25lcyByZWR1Y2lkYXMgeSBxdWUgbG9zIHJlZ2lzdHJvcyBjb3JyZXNwb25kZW4gw7puaWNhbWVudGUgYSBkZW51bmNpYXMgZGVsIHBlcmlvZG8gZW5lcm8tanVsaW8gZGUgMjAyMy4NCg0KYGBge3IgY2xhc2lmaWNhY2lvbi1jdWFkcmFudGVzLWRlbGl0b3MsIGVjaG89VFJVRX0NCiMgQ8OhbGN1bG8gZGUgbGFzIG1lZGlhbmFzIGNvbW8gcHVudG9zIGRlIHJlZmVyZW5jaWENCg0KbWVkaWFuYV9jYXNvcyA8LSBtZWRpYW4odmFyaWFibGVzX2RlbGl0b3MkY2Fzb3NfdG90YWwpDQoNCm1lZGlhbmFfdGFzYSA8LSBtZWRpYW4odmFyaWFibGVzX2RlbGl0b3MkdGFzYV90b3RhbCkNCg0KIyBDbGFzaWZpY2FjacOzbiBkZSBsYXMgVVBaIHNlZ8O6biBjYXNvcyB5IHRhc2FzDQoNCmNvbXBhcmFjaW9uX2RlbGl0b3MgPC0gdmFyaWFibGVzX2RlbGl0b3MgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICBwb2JsYWNpb24sDQogICAgY2Fzb3NfdG90YWwsDQogICAgdGFzYV90b3RhbA0KICApICU+JQ0KICBtdXRhdGUoDQogICAgQ2xhc2lmaWNhY2lvbiA9IGNhc2Vfd2hlbigNCiAgICAgIGNhc29zX3RvdGFsID49IG1lZGlhbmFfY2Fzb3MgJg0KICAgICAgICB0YXNhX3RvdGFsID49IG1lZGlhbmFfdGFzYSB+ICJNdWNob3MgY2Fzb3MgeSB0YXNhIGFsdGEiLA0KDQogICAgICBjYXNvc190b3RhbCA+PSBtZWRpYW5hX2Nhc29zICYNCiAgICAgICAgdGFzYV90b3RhbCA8IG1lZGlhbmFfdGFzYSB+ICJNdWNob3MgY2Fzb3MgeSB0YXNhIGJhamEiLA0KDQogICAgICBjYXNvc190b3RhbCA8IG1lZGlhbmFfY2Fzb3MgJg0KICAgICAgICB0YXNhX3RvdGFsID49IG1lZGlhbmFfdGFzYSB+ICJQb2NvcyBjYXNvcyB5IHRhc2EgYWx0YSIsDQoNCiAgICAgIFRSVUUgfiAiUG9jb3MgY2Fzb3MgeSB0YXNhIGJhamEiDQogICAgKQ0KICApDQoNCiMgUmVzdW1lbiBkZSBsYSBjYW50aWRhZCBkZSBVUFogZW4gY2FkYSBjdWFkcmFudGUNCg0KcmVzdW1lbl9jdWFkcmFudGVzIDwtIGNvbXBhcmFjaW9uX2RlbGl0b3MgJT4lDQogIGNvdW50KENsYXNpZmljYWNpb24sIG5hbWUgPSAiQ2FudGlkYWRfVVBaIikgJT4lDQogIG11dGF0ZSgNCiAgICBQYXJ0aWNpcGFjaW9uID0gQ2FudGlkYWRfVVBaIC8gc3VtKENhbnRpZGFkX1VQWikgKiAxMDANCiAgKSAlPiUNCiAgYXJyYW5nZShkZXNjKENhbnRpZGFkX1VQWikpDQoNCmtuaXRyOjprYWJsZSgNCiAgcmVzdW1lbl9jdWFkcmFudGVzLA0KICBkaWdpdHMgPSAyLA0KICBjb2wubmFtZXMgPSBjKA0KICAgICJDbGFzaWZpY2FjacOzbiIsDQogICAgIkNhbnRpZGFkIGRlIFVQWiIsDQogICAgIlBhcnRpY2lwYWNpw7NuICglKSINCiAgKSwNCiAgY2FwdGlvbiA9ICJEaXN0cmlidWNpw7NuIGRlIGxhcyBVUFogc2Vnw7puIHZvbHVtZW4gZGUgY2Fzb3MgeSB0YXNhIGRlIGRlbGl0b3MiDQopDQpgYGANCg0KYGBge3IgZ3JhZmljby1jdWFkcmFudGVzLWRlbGl0b3MsIGVjaG89VFJVRX0NCiMgSWRlbnRpZmljYWNpw7NuIGRlIGxhcyBkaWV6IFVQWiBjb24gbWF5b3JlcyB0YXNhcyBwYXJhIGV0aXF1ZXRhcmxhcw0KDQp1cHpfZXRpcXVldGFkYXMgPC0gY29tcGFyYWNpb25fZGVsaXRvcyAlPiUNCiAgc2xpY2VfbWF4KA0KICAgIG9yZGVyX2J5ID0gdGFzYV90b3RhbCwNCiAgICBuID0gMTAsDQogICAgd2l0aF90aWVzID0gRkFMU0UNCiAgKQ0KDQojIEdyw6FmaWNvIGRlIGRpc3BlcnNpw7NuDQoNCmdncGxvdCgNCiAgY29tcGFyYWNpb25fZGVsaXRvcywNCiAgYWVzKA0KICAgIHggPSBjYXNvc190b3RhbCwNCiAgICB5ID0gdGFzYV90b3RhbCwNCiAgICBjb2xvciA9IENsYXNpZmljYWNpb24sDQogICAgc2l6ZSA9IHBvYmxhY2lvbg0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBhbHBoYSA9IDAuNzUNCiAgKSArDQogIGdlb21fdmxpbmUoDQogICAgeGludGVyY2VwdCA9IG1lZGlhbmFfY2Fzb3MsDQogICAgbGluZXR5cGUgPSAiZGFzaGVkIiwNCiAgICBjb2xvciA9ICJncmV5NDAiDQogICkgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBtZWRpYW5hX3Rhc2EsDQogICAgbGluZXR5cGUgPSAiZGFzaGVkIiwNCiAgICBjb2xvciA9ICJncmV5NDAiDQogICkgKw0KICBnZW9tX3RleHQoDQogICAgZGF0YSA9IHVwel9ldGlxdWV0YWRhcywNCiAgICBhZXMobGFiZWwgPSB1cHpfbm9tYnJlKSwNCiAgICBzaXplID0gMi44LA0KICAgIHNob3cubGVnZW5kID0gRkFMU0UsDQogICAgdmp1c3QgPSAtMC44DQogICkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICJNdWNob3MgY2Fzb3MgeSB0YXNhIGFsdGEiID0gbWFnZW50YSwNCiAgICAgICJNdWNob3MgY2Fzb3MgeSB0YXNhIGJhamEiID0gdHVycXVlc2EsDQogICAgICAiUG9jb3MgY2Fzb3MgeSB0YXNhIGFsdGEiID0gbW9yYWRvLA0KICAgICAgIlBvY29zIGNhc29zIHkgdGFzYSBiYWphIiA9IGdyaXMNCiAgICApDQogICkgKw0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMoDQogICAgcmFuZ2UgPSBjKDIsIDgpLA0KICAgIG5hbWUgPSAiUG9ibGFjacOzbiINCiAgKSArDQogIHNjYWxlX3hfY29udGludW91cygNCiAgICBsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX251bWJlcihiaWcubWFyayA9ICIuIikNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUmVsYWNpw7NuIGVudHJlIGNhc29zIHJlZ2lzdHJhZG9zIHkgdGFzYXMgZGUgZGVsaXRvcyIsDQogICAgc3VidGl0bGUgPSAiQ29tcGFyYWNpw7NuIHRlcnJpdG9yaWFsIGRlIGxhcyBVUFogbWVkaWFudGUgY3VhdHJvIGN1YWRyYW50ZXMiLA0KICAgIHggPSAiTsO6bWVybyB0b3RhbCBkZSBjYXNvcyByZWdpc3RyYWRvcyIsDQogICAgeSA9ICJUYXNhIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzIiwNCiAgICBjb2xvciA9ICJDbGFzaWZpY2FjacOzbiIsDQogICAgY2FwdGlvbiA9ICJMYXMgbMOtbmVhcyBkaXNjb250aW51YXMgcmVwcmVzZW50YW4gbGFzIG1lZGlhbmFzLiBGdWVudGU6IFNlY3JldGFyw61hIERpc3RyaXRhbCBkZSBTZWd1cmlkYWQgeSBwcm95ZWNjaW9uZXMgREFORSwgMjAyMy4iDQogICkgKw0KICB0ZW1hX2NsYXNlICsNCiAgdGhlbWUoDQogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgbGVnZW5kLmJveCA9ICJ2ZXJ0aWNhbCINCiAgKQ0KYGBgDQoNCiMgNS42LiBBbsOhbGlzaXMgZGUgcmVsYWNpb25lcyBlbnRyZSB2YXJpYWJsZXMNCg0KRGVzcHXDqXMgZGUgZXhwbG9yYXIgaW5kaXZpZHVhbG1lbnRlIGxhcyBjYXJhY3RlcsOtc3RpY2FzIGRlbW9ncsOhZmljYXMsIGxhcyBjb25kaWNpb25lcyBkZSB2aXZpZW5kYSBlIGluZnJhZXN0cnVjdHVyYSwgbGFzIHZhcmlhYmxlcyBzb2Npb2Vjb27Ds21pY2FzLCBsYSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCB5IGxvcyByZWdpc3Ryb3MgZGUgZGVsaXRvcywgc2UgZGVzYXJyb2xsYSB1biBhbsOhbGlzaXMgaW50ZWdyYWRvIHBhcmEgZXhwbG9yYXIgbGFzIHBvc2libGVzIHJlbGFjaW9uZXMgZW50cmUgZXN0YXMgZGltZW5zaW9uZXMuDQoNCkVsIHByb3DDs3NpdG8gZXMgaWRlbnRpZmljYXIgcGF0cm9uZXMgZGUgYXNvY2lhY2nDs24gZW50cmUgbGFzIGNhcmFjdGVyw61zdGljYXMgdGVycml0b3JpYWxlcyB5IGxvcyBpbmRpY2Fkb3JlcyBkZSBzZWd1cmlkYWQsIGNvbiBlbCBmaW4gZGUgYW1wbGlhciBsYSBjb21wcmVuc2nDs24gZGUgbGFzIGRpZmVyZW5jaWFzIGV4aXN0ZW50ZXMgZW50cmUgbGFzIFVQWiBkZSBCb2dvdMOhLg0KDQpQYXJhIGVzdGUgYW7DoWxpc2lzIHNlIHNlbGVjY2lvbmFuIHZhcmlhYmxlcyBkZSBkaWZlcmVudGVzIGJsb3F1ZXMgdGVtw6F0aWNvcywgaW5jbHV5ZW5kbyBhc3BlY3RvcyBkZW1vZ3LDoWZpY29zLCBpbmZyYWVzdHJ1Y3R1cmEgdXJiYW5hLCBjb25kaWNpb25lcyBzb2Npb2Vjb27Ds21pY2FzLCBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCB5IHJlZ2lzdHJvcyBhZG1pbmlzdHJhdGl2b3MgZGUgZGVsaXRvcy4NCg0KU2UgdXRpbGl6YSBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gZGUgU3BlYXJtYW4gcGFyYSBleHBsb3JhciBsYSBkaXJlY2Npw7NuIHkgbGEgaW50ZW5zaWRhZCBkZSBsYXMgYXNvY2lhY2lvbmVzIGVudHJlIGxhcyB2YXJpYWJsZXMuIExvcyByZXN1bHRhZG9zIHNlIHByZXNlbnRhbiBtZWRpYW50ZSB1bmEgbWF0cml6IGRlIGNvcnJlbGFjaW9uZXMgeSB1biBtYXBhIGRlIGNhbG9yIHF1ZSBmYWNpbGl0YW4gbGEgaWRlbnRpZmljYWNpw7NuIGRlIHBvc2libGVzIHBhdHJvbmVzLg0KDQpFcyBpbXBvcnRhbnRlIHNlw7FhbGFyIHF1ZSBsYXMgY29ycmVsYWNpb25lcyBwZXJtaXRlbiBpZGVudGlmaWNhciBhc29jaWFjaW9uZXMgZXN0YWTDrXN0aWNhcywgcGVybyBubyBkZW11ZXN0cmFuIHJlbGFjaW9uZXMgZGUgY2F1c2FsaWRhZC4gQWRpY2lvbmFsbWVudGUsIHNlIGRlYmVuIGNvbnNpZGVyYXIgbGFzIGRpZmVyZW5jaWFzIGVuIGxvcyBhw7FvcyBkZSByZWZlcmVuY2lhIGRlIGxhcyBmdWVudGVzIHkgbGFzIGxpbWl0YWNpb25lcyByZWxhY2lvbmFkYXMgY29uIGxhcyBlc3RpbWFjaW9uZXMgYWdydXBhZGFzIGRlIGxhIEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0by4NCg0KIyMjIDUuNi4xLiBTZWxlY2Npw7NuIGRlIHZhcmlhYmxlcyBwYXJhIGVsIGFuw6FsaXNpcyBpbnRlZ3JhZG8NCg0KUGFyYSBlbCBhbsOhbGlzaXMgZGUgcmVsYWNpb25lcyBzZSBzZWxlY2Npb25hcm9uIGRpZXogdmFyaWFibGVzIHBlcnRlbmVjaWVudGVzIGEgY2luY28gZGltZW5zaW9uZXMgZGVsIGVzdHVkaW86IGRlbW9ncmFmw61hLCBpbmZyYWVzdHJ1Y3R1cmEsIGNvbmRpY2lvbmVzIHNvY2lvZWNvbsOzbWljYXMsIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHkgZGVsaXRvcyBkZSBhbHRvIGltcGFjdG8uDQoNCkxhIHNlbGVjY2nDs24gYnVzY2EgZXhwbG9yYXIgc2kgbGFzIGNhcmFjdGVyw61zdGljYXMgcG9ibGFjaW9uYWxlcywgbGEgZGlzcG9uaWJpbGlkYWQgZGUgYWx1bWJyYWRvIHDDumJsaWNvLCBsYXMgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcyB5IGxhIHBlcmNlcGNpw7NuIGRlbCBlbnRvcm5vIHByZXNlbnRhbiBhc29jaWFjaW9uZXMgY29uIGxvcyBpbmRpY2Fkb3JlcyBkZSBkZWxpdG9zIHJlZ2lzdHJhZG9zIGVuIGxhcyBVUFouDQoNCkxhcyB2YXJpYWJsZXMgc2VsZWNjaW9uYWRhcyBzb246DQoNCi0gKipEZW1vZ3JhZsOtYToqKiBwb2JsYWNpw7NuIHkgZGVuc2lkYWQgcG9ibGFjaW9uYWwuDQotICoqSW5mcmFlc3RydWN0dXJhOioqIGx1bWluYXJpYXMgcG9yIGttwrIuDQotICoqQ29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhczoqKiBwb3JjZW50YWplIGRlIHBvYnJlemEgeSBzYWxhcmlvIHByb21lZGlvLg0KLSAqKlBlcmNlcGNpw7NuIHkgZW50b3JubzoqKiBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCB5IGNlcmNhbsOtYSBhIGxvdGVzIG9zY3Vyb3MuDQotICoqRGVsaXRvczoqKiBuw7ptZXJvIHRvdGFsIGRlIGNhc29zIHkgdGFzYSB0b3RhbCBwb3IgY2FkYSAxMC4wMDAgaGFiaXRhbnRlcy4NCi0gKipBY2Nlc2liaWxpZGFkOioqIHRpZW1wbyBwcm9tZWRpbyBjYW1pbmFuZG8gaGFzdGEgdW4gQ0FJIG8gZXN0YWNpw7NuIGRlIHBvbGljw61hLg0KDQpFc3RhIHNlbGVjY2nDs24gcGVybWl0ZSBpbnRlZ3JhciBkaWZlcmVudGVzIGRpbWVuc2lvbmVzIGRlbCB0ZXJyaXRvcmlvIHkgZXhwbG9yYXIgc3VzIHBvc2libGVzIHJlbGFjaW9uZXMuIExvcyByZXN1bHRhZG9zIHNlIGludGVycHJldGFyw6FuIGRlIG1hbmVyYSBleHBsb3JhdG9yaWEsIGNvbnNpZGVyYW5kbyBsYXMgbGltaXRhY2lvbmVzIHByb3BpYXMgZGUgbGFzIGZ1ZW50ZXMgdXRpbGl6YWRhcy4NCg0KYGBge3Igc2VsZWNjaW9uLXZhcmlhYmxlcy1pbnRlZ3JhZGFzLCBlY2hvPVRSVUV9DQojIFNlbGVjY2nDs24gZGUgdmFyaWFibGVzIHBhcmEgZWwgYW7DoWxpc2lzIGludGVncmFkbw0KDQp2YXJpYWJsZXNfaW50ZWdyYWRhcyA8LSB1cHogJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICBlbV9hZ3J1cGFkYSwNCiAgICBwb2JsYWNpb24sDQogICAgZGVuc2lkYWRfaGFiX2ttMiwNCiAgICBsdW1pbmFyaWFzX2ttMiwNCiAgICBwY3RfcG9icmV6YSwNCiAgICBzYWxhcmlvX3Byb21lZGlvLA0KICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkLA0KICAgIHBjdF9jZXJjYV9sb3Rlc19vc2N1cm9zLA0KICAgIG1pbl9jYWlfcG9saWNpYSwNCiAgICBjYXNvc190b3RhbCwNCiAgICB0YXNhX3RvdGFsDQogICkNCg0KIyBSZXZpc2nDs24gZGUgbGFzIHZhcmlhYmxlcyBzZWxlY2Npb25hZGFzDQoNCmdsaW1wc2UodmFyaWFibGVzX2ludGVncmFkYXMpDQoNCiMgVmlzdWFsaXphY2nDs24gZGUgbGFzIHByaW1lcmFzIG9ic2VydmFjaW9uZXMNCg0KaGVhZCh2YXJpYWJsZXNfaW50ZWdyYWRhcykNCmBgYA0KDQojIyMgNS42LjIuIE1hdHJpeiBkZSBjb3JyZWxhY2lvbmVzIGVudHJlIGxhcyB2YXJpYWJsZXMgdGVycml0b3JpYWxlcw0KDQpVbmEgdmV6IHNlbGVjY2lvbmFkYXMgbGFzIHZhcmlhYmxlcyBkZSBsb3MgZGlmZXJlbnRlcyBibG9xdWVzIHRlbcOhdGljb3MsIHNlIGNvbnN0cnV5ZSB1bmEgbWF0cml6IGRlIGNvcnJlbGFjaW9uZXMgcGFyYSBleHBsb3JhciBsYXMgYXNvY2lhY2lvbmVzIGV4aXN0ZW50ZXMgZW50cmUgbGFzIGNhcmFjdGVyw61zdGljYXMgZGVtb2dyw6FmaWNhcywgbGEgaW5mcmFlc3RydWN0dXJhLCBsYXMgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcywgbGEgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQsIGxhIGFjY2VzaWJpbGlkYWQgeSBsb3MgZGVsaXRvcyByZWdpc3RyYWRvcy4NCg0KU2UgdXRpbGl6YSBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gZGUgU3BlYXJtYW4sIHF1ZSBwZXJtaXRlIGlkZW50aWZpY2FyIGFzb2NpYWNpb25lcyBtb25vdMOzbmljYXMgZW50cmUgbGFzIHZhcmlhYmxlcy4gU3VzIHZhbG9yZXMgb3NjaWxhbiBlbnRyZSAtMSB5IDEsIGRvbmRlIGxvcyB2YWxvcmVzIHBvc2l0aXZvcyByZXByZXNlbnRhbiBhc29jaWFjaW9uZXMgZGlyZWN0YXMgeSBsb3MgbmVnYXRpdm9zIGFzb2NpYWNpb25lcyBpbnZlcnNhcy4NCg0KTGEgbWF0cml6IHNlIHJlcHJlc2VudGEgbWVkaWFudGUgdW4gbWFwYSBkZSBjYWxvciwgZW4gZWwgcXVlIGxvcyBjb2xvcmVzIHBlcm1pdGVuIHJlY29ub2NlciB2aXN1YWxtZW50ZSBsYSBkaXJlY2Npw7NuIHkgbGEgaW50ZW5zaWRhZCBkZSBsYXMgY29ycmVsYWNpb25lcy4NCg0KRXN0ZSBlamVyY2ljaW8gYnVzY2EgaWRlbnRpZmljYXIgcmVsYWNpb25lcyBxdWUgcHVlZGFuIG9yaWVudGFyIGVsIGRlc2Fycm9sbG8gZGUgbGFzIHByZWd1bnRhcyBkZSBpbnZlc3RpZ2FjacOzbiB5IGxvcyBhbsOhbGlzaXMgcG9zdGVyaW9yZXMuIFNpbiBlbWJhcmdvLCBsYXMgYXNvY2lhY2lvbmVzIG9ic2VydmFkYXMgbm8gZGViZW4gaW50ZXJwcmV0YXJzZSBjb21vIHJlbGFjaW9uZXMgZGUgY2F1c2FsaWRhZC4NCg0KYGBge3IgbWF0cml6LWNvcnJlbGFjaW9uZXMtaW50ZWdyYWRhcywgZWNobz1UUlVFfQ0KIyBTZWxlY2Npw7NuIGV4Y2x1c2l2YSBkZSB2YXJpYWJsZXMgbnVtw6lyaWNhcw0KDQpkYXRvc19jb3JyZWxhY2lvbl9pbnRlZ3JhZGEgPC0gdmFyaWFibGVzX2ludGVncmFkYXMgJT4lDQogIHNlbGVjdCgNCiAgICBwb2JsYWNpb24sDQogICAgZGVuc2lkYWRfaGFiX2ttMiwNCiAgICBsdW1pbmFyaWFzX2ttMiwNCiAgICBwY3RfcG9icmV6YSwNCiAgICBzYWxhcmlvX3Byb21lZGlvLA0KICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkLA0KICAgIHBjdF9jZXJjYV9sb3Rlc19vc2N1cm9zLA0KICAgIG1pbl9jYWlfcG9saWNpYSwNCiAgICBjYXNvc190b3RhbCwNCiAgICB0YXNhX3RvdGFsDQogICkNCg0KIyBDw6FsY3VsbyBkZSBsYSBtYXRyaXogZGUgY29ycmVsYWNpb25lcyBkZSBTcGVhcm1hbg0KDQptYXRyaXpfY29ycmVsYWNpb25faW50ZWdyYWRhIDwtIGNvcigNCiAgZGF0b3NfY29ycmVsYWNpb25faW50ZWdyYWRhLA0KICBtZXRob2QgPSAic3BlYXJtYW4iLA0KICB1c2UgPSAiY29tcGxldGUub2JzIg0KKQ0KDQojIFRyYW5zZm9ybWFjacOzbiBkZSBsYSBtYXRyaXogYSBmb3JtYXRvIGxhcmdvDQoNCmNvcnJlbGFjaW9uZXNfaW50ZWdyYWRhc19sYXJnYXMgPC0gYXMuZGF0YS5mcmFtZSgNCiAgYXMudGFibGUobWF0cml6X2NvcnJlbGFjaW9uX2ludGVncmFkYSkNCikgJT4lDQogIHJlbmFtZSgNCiAgICBWYXJpYWJsZV8xID0gVmFyMSwNCiAgICBWYXJpYWJsZV8yID0gVmFyMiwNCiAgICBDb3JyZWxhY2lvbiA9IEZyZXENCiAgKQ0KDQojIENvbnN0cnVjY2nDs24gZGVsIG1hcGEgZGUgY2Fsb3INCg0KZ2dwbG90KA0KICBjb3JyZWxhY2lvbmVzX2ludGVncmFkYXNfbGFyZ2FzLA0KICBhZXMoDQogICAgeCA9IFZhcmlhYmxlXzEsDQogICAgeSA9IFZhcmlhYmxlXzIsDQogICAgZmlsbCA9IENvcnJlbGFjaW9uDQogICkNCikgKw0KICBnZW9tX3RpbGUoDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIGxpbmV3aWR0aCA9IDENCiAgKSArDQogIGdlb21fdGV4dCgNCiAgICBhZXMobGFiZWwgPSByb3VuZChDb3JyZWxhY2lvbiwgMikpLA0KICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICBzaXplID0gMw0KICApICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIoDQogICAgbG93ID0gbW9yYWRvLA0KICAgIG1pZCA9ICJ3aGl0ZSIsDQogICAgaGlnaCA9IG1hZ2VudGEsDQogICAgbWlkcG9pbnQgPSAwLA0KICAgIGxpbWl0cyA9IGMoLTEsIDEpLA0KICAgIG5hbWUgPSAiQ29ycmVsYWNpw7NuIg0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSZWxhY2lvbmVzIGVudHJlIGxhcyBjYXJhY3RlcsOtc3RpY2FzIHRlcnJpdG9yaWFsZXMiLA0KICAgIHN1YnRpdGxlID0gIk1hdHJpeiBkZSBjb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuIGVudHJlIHZhcmlhYmxlcyBzZWxlY2Npb25hZGFzIiwNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gTlVMTCwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSBjb24gaW5mb3JtYWNpw7NuIERBTkUsIFNlY3JldGFyw61hIERpc3RyaXRhbCBkZSBTZWd1cmlkYWQgeSBEYXRvcyBBYmllcnRvcyBCb2dvdMOhLiINCiAgKSArDQogIGNvb3JkX2ZpeGVkKCkgKw0KICB0ZW1hX2NsYXNlICsNCiAgdGhlbWUoDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoDQogICAgICBhbmdsZSA9IDQ1LA0KICAgICAgaGp1c3QgPSAxLA0KICAgICAgY29sb3IgPSBtb3JhZG8sDQogICAgICBzaXplID0gOA0KICAgICksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoDQogICAgICBjb2xvciA9IG1vcmFkbywNCiAgICAgIHNpemUgPSA4DQogICAgKSwNCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCINCiAgKQ0KYGBgDQoNCiMjIyA1LjYuMy4gUmVsYWNpw7NuIGVudHJlIHBvYmxhY2nDs24sIGRlbnNpZGFkIHBvYmxhY2lvbmFsIHkgZGVsaXRvcw0KDQpMYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZW1vZ3LDoWZpY2FzIGRlIGxvcyB0ZXJyaXRvcmlvcyBwdWVkZW4gYXBvcnRhciBlbGVtZW50b3MgaW1wb3J0YW50ZXMgcGFyYSBjb21wcmVuZGVyIGxhcyBkaWZlcmVuY2lhcyBlbiBsb3MgcmVnaXN0cm9zIGRlIGRlbGl0b3MuIFBvciBlc3RhIHJhesOzbiwgc2UgZXhwbG9yYW4gbGFzIHJlbGFjaW9uZXMgZW50cmUgZWwgdGFtYcOxbyBkZSBsYSBwb2JsYWNpw7NuLCBsYSBkZW5zaWRhZCBwb2JsYWNpb25hbCB5IGxvcyBpbmRpY2Fkb3JlcyBkZSBkZWxpdG9zIGRlIGFsdG8gaW1wYWN0by4NCg0KRW4gcHJpbWVyIGx1Z2FyLCBzZSBhbmFsaXphIGxhIHJlbGFjacOzbiBlbnRyZSBsYSBwb2JsYWNpw7NuIHkgZWwgbsO6bWVybyB0b3RhbCBkZSBjYXNvcyByZWdpc3RyYWRvcywgY29uIGVsIHByb3DDs3NpdG8gZGUgaWRlbnRpZmljYXIgc2kgbGFzIFVQWiBjb24gbWF5b3IgY2FudGlkYWQgZGUgaGFiaXRhbnRlcyB0YW1iacOpbiBjb25jZW50cmFuIHVuIG1heW9yIHZvbHVtZW4gZGUgZGVudW5jaWFzLg0KDQpFbiBzZWd1bmRvIGx1Z2FyLCBzZSBleGFtaW5hIGxhIHJlbGFjacOzbiBlbnRyZSBsYSBkZW5zaWRhZCBwb2JsYWNpb25hbCB5IGxhIHRhc2EgdG90YWwgZGUgZGVsaXRvcyBwb3IgY2FkYSAxMC4wMDAgaGFiaXRhbnRlcy4gRXN0ZSBlamVyY2ljaW8gcGVybWl0ZSBleHBsb3JhciBzaSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBjb25jZW50cmFjacOzbiBkZSBsYSBwb2JsYWNpw7NuIHByZXNlbnRhbiBhbGd1bmEgYXNvY2lhY2nDs24gY29uIGxhcyBkaWZlcmVuY2lhcyB0ZXJyaXRvcmlhbGVzIGVuIGxhcyB0YXNhcyByZWdpc3RyYWRhcy4NCg0KUGFyYSBjb21wbGVtZW50YXIgbGEgdmlzdWFsaXphY2nDs24sIHNlIGNhbGN1bGFuIGxvcyBjb2VmaWNpZW50ZXMgZGUgY29ycmVsYWNpw7NuIGRlIFNwZWFybWFuLiBMb3MgcmVzdWx0YWRvcyBwZXJtaXRlbiBpZGVudGlmaWNhciBhc29jaWFjaW9uZXMgZW50cmUgbGFzIHZhcmlhYmxlcywgc2luIGVzdGFibGVjZXIgcmVsYWNpb25lcyBkZSBjYXVzYWxpZGFkLg0KDQpgYGB7ciByZWxhY2lvbi1wb2JsYWNpb24tY2Fzb3MsIGVjaG89VFJVRX0NCmdncGxvdCgNCiAgdmFyaWFibGVzX2ludGVncmFkYXMsDQogIGFlcygNCiAgICB4ID0gcG9ibGFjaW9uLA0KICAgIHkgPSBjYXNvc190b3RhbA0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBjb2xvciA9IHR1cnF1ZXNhLA0KICAgIGFscGhhID0gMC43LA0KICAgIHNpemUgPSAyLjUNCiAgKSArDQogIGdlb21fc21vb3RoKA0KICAgIG1ldGhvZCA9ICJsbSIsDQogICAgc2UgPSBGQUxTRSwNCiAgICBjb2xvciA9IG1hZ2VudGEsDQogICAgbGluZXdpZHRoID0gMC45DQogICkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoYmlnLm1hcmsgPSAiLiIpDQogICkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoYmlnLm1hcmsgPSAiLiIpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBwb2JsYWNpw7NuIHkgY2Fzb3MgZGUgZGVsaXRvcyIsDQogICAgc3VidGl0bGUgPSAiTsO6bWVybyBkZSBoYWJpdGFudGVzIHkgZGVudW5jaWFzIHJlZ2lzdHJhZGFzIHBvciBVUFoiLA0KICAgIHggPSAiUG9ibGFjacOzbiIsDQogICAgeSA9ICJDYXNvcyB0b3RhbGVzIHJlZ2lzdHJhZG9zIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogUHJveWVjY2lvbmVzIERBTkUgeSBTZWNyZXRhcsOtYSBEaXN0cml0YWwgZGUgU2VndXJpZGFkLCAyMDIzLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQpgYGB7ciByZWxhY2lvbi1kZW5zaWRhZC10YXNhLWRlbGl0b3MsIGVjaG89VFJVRX0NCmdncGxvdCgNCiAgdmFyaWFibGVzX2ludGVncmFkYXMsDQogIGFlcygNCiAgICB4ID0gZGVuc2lkYWRfaGFiX2ttMiwNCiAgICB5ID0gdGFzYV90b3RhbA0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBjb2xvciA9IG1hZ2VudGEsDQogICAgYWxwaGEgPSAwLjcsDQogICAgc2l6ZSA9IDIuNQ0KICApICsNCiAgZ2VvbV9zbW9vdGgoDQogICAgbWV0aG9kID0gImxtIiwNCiAgICBzZSA9IEZBTFNFLA0KICAgIGNvbG9yID0gbW9yYWRvLA0KICAgIGxpbmV3aWR0aCA9IDAuOQ0KICApICsNCiAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKGJpZy5tYXJrID0gIi4iKQ0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgZGVuc2lkYWQgcG9ibGFjaW9uYWwgeSB0YXNhIGRlIGRlbGl0b3MiLA0KICAgIHN1YnRpdGxlID0gIkNvbmNlbnRyYWNpw7NuIGRlIGhhYml0YW50ZXMgeSBjYXNvcyBwb3IgY2FkYSAxMC4wMDAgaGFiaXRhbnRlcyIsDQogICAgeCA9ICJEZW5zaWRhZCBwb2JsYWNpb25hbCAoaGFiaXRhbnRlcyBwb3Iga23CsikiLA0KICAgIHkgPSAiVGFzYSBkZSBkZWxpdG9zIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogUHJveWVjY2lvbmVzIERBTkUgeSBTZWNyZXRhcsOtYSBEaXN0cml0YWwgZGUgU2VndXJpZGFkLCAyMDIzLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQpQYXJhIGNvbXBsZW1lbnRhciBsb3MgZ3LDoWZpY29zIGRlIGRpc3BlcnNpw7NuLCBzZSBjYWxjdWxhbiBsb3MgY29lZmljaWVudGVzIGRlIGNvcnJlbGFjacOzbiBkZSBTcGVhcm1hbiBlbnRyZSBsYSBwb2JsYWNpw7NuIHkgbG9zIGNhc29zIHRvdGFsZXMsIGFzw60gY29tbyBlbnRyZSBsYSBkZW5zaWRhZCBwb2JsYWNpb25hbCB5IGxhIHRhc2EgZGUgZGVsaXRvcy4NCg0KRXN0YSBjb21wYXJhY2nDs24gcGVybWl0ZSBldmFsdWFyIGxhIGRpcmVjY2nDs24geSBsYSBpbnRlbnNpZGFkIGRlIGxhcyBhc29jaWFjaW9uZXMgb2JzZXJ2YWRhcyB2aXN1YWxtZW50ZSwgZmFjaWxpdGFuZG8gbGEgaWRlbnRpZmljYWNpw7NuIGRlIHBvc2libGVzIGRpZmVyZW5jaWFzIGVudHJlIGVsIHZvbHVtZW4gZGUgZGVudW5jaWFzIHkgbGFzIHRhc2FzIHJlbGF0aXZhcyBhIGxhIHBvYmxhY2nDs24uDQoNCmBgYHtyIGNvcnJlbGFjaW9uZXMtZGVtb2dyYWZpYS1kZWxpdG9zLCBlY2hvPVRSVUV9DQojIEPDoWxjdWxvIGRlIGxhcyBjb3JyZWxhY2lvbmVzIHNlbGVjY2lvbmFkYXMNCg0KY29ycmVsYWNpb25lc19kZW1vZ3JhZmlhIDwtIHZhcmlhYmxlc19pbnRlZ3JhZGFzICU+JQ0KICBzZWxlY3QoDQogICAgcG9ibGFjaW9uLA0KICAgIGNhc29zX3RvdGFsLA0KICAgIGRlbnNpZGFkX2hhYl9rbTIsDQogICAgdGFzYV90b3RhbA0KICApICU+JQ0KICBjb3IoDQogICAgbWV0aG9kID0gInNwZWFybWFuIiwNCiAgICB1c2UgPSAiY29tcGxldGUub2JzIg0KICApDQoNCiMgVHJhbnNmb3JtYWNpw7NuIHBhcmEgcHJlc2VudGFyIMO6bmljYW1lbnRlIGxhcyBkb3MgcmVsYWNpb25lcyBkZSBpbnRlcsOpcw0KDQpyZXN1bHRhZG9fY29ycmVsYWNpb25lc19kZW1vZ3JhZmlhIDwtIHRpYmJsZSgNCiAgUmVsYWNpb24gPSBjKA0KICAgICJQb2JsYWNpw7NuIHkgY2Fzb3MgdG90YWxlcyIsDQogICAgIkRlbnNpZGFkIHBvYmxhY2lvbmFsIHkgdGFzYSBkZSBkZWxpdG9zIg0KICApLA0KICBDb3JyZWxhY2lvbiA9IGMoDQogICAgY29ycmVsYWNpb25lc19kZW1vZ3JhZmlhWyJwb2JsYWNpb24iLCAiY2Fzb3NfdG90YWwiXSwNCiAgICBjb3JyZWxhY2lvbmVzX2RlbW9ncmFmaWFbImRlbnNpZGFkX2hhYl9rbTIiLCAidGFzYV90b3RhbCJdDQogICkNCikNCg0Ka25pdHI6OmthYmxlKA0KICByZXN1bHRhZG9fY29ycmVsYWNpb25lc19kZW1vZ3JhZmlhLA0KICBkaWdpdHMgPSAzLA0KICBjYXB0aW9uID0gIkNvcnJlbGFjaW9uZXMgZGUgU3BlYXJtYW4gZW50cmUgdmFyaWFibGVzIGRlbW9ncsOhZmljYXMgZSBpbmRpY2Fkb3JlcyBkZSBkZWxpdG9zIg0KKQ0KYGBgDQoNCiMjIyA1LjYuNC4gUmVsYWNpw7NuIGVudHJlIGluZnJhZXN0cnVjdHVyYSB1cmJhbmEgeSBkZWxpdG9zDQoNCkVuIGVzdGUgYXBhcnRhZG8gc2UgZXhwbG9yYSBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNvbmRpY2lvbmVzIGRlbCBhbHVtYnJhZG8gcMO6YmxpY28geSBsYSB0YXNhIGRlIGRlbGl0b3MgZGUgYWx0byBpbXBhY3RvIGVuIGxhcyBVUFogZGUgQm9nb3TDoS4gUGFyYSBlbGxvLCBzZSBjb25zaWRlcmFuIHRyZXMgaW5kaWNhZG9yZXM6IGxhIGNhbnRpZGFkIGRlIGx1bWluYXJpYXMgcG9yIGtpbMOzbWV0cm8gY3VhZHJhZG8sIGxhIGNhbnRpZGFkIGRlIGx1bWluYXJpYXMgcG9yIGNhZGEgMS4wMDAgaGFiaXRhbnRlcyB5IGVsIHBvcmNlbnRhamUgZGUgbHVtaW5hcmlhcyBMRUQuDQoNCkVsIHByb3DDs3NpdG8gZXMgaWRlbnRpZmljYXIgc2kgZXhpc3RlIGFsZ3VuYSBhc29jaWFjacOzbiBlc3RhZMOtc3RpY2EgZW50cmUgbGEgZGlzcG9uaWJpbGlkYWQgeSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZWwgYWx1bWJyYWRvIHDDumJsaWNvIHkgbG9zIG5pdmVsZXMgZGUgY3JpbWluYWxpZGFkIHJlZ2lzdHJhZG9zIGVuIGNhZGEgVVBaLg0KDQpTZSB1dGlsaXphIGxhIGNvcnJlbGFjacOzbiBkZSBTcGVhcm1hbiwgZGViaWRvIGEgcXVlIHBlcm1pdGUgZXZhbHVhciByZWxhY2lvbmVzIG1vbm90w7NuaWNhcyBzaW4gZXhpZ2lyIHF1ZSBsYXMgdmFyaWFibGVzIHByZXNlbnRlbiB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwuIEFkaWNpb25hbG1lbnRlLCBzZSBlbXBsZWFuIGRpYWdyYW1hcyBkZSBkaXNwZXJzacOzbiBwYXJhIG9ic2VydmFyIGVsIGNvbXBvcnRhbWllbnRvIGRlIGxhcyB2YXJpYWJsZXMgeSBwb3NpYmxlcyBwYXRyb25lcyBvIHZhbG9yZXMgZXh0cmVtb3MuDQoNCkVzIGltcG9ydGFudGUgY29uc2lkZXJhciBxdWUgbG9zIGluZGljYWRvcmVzIGRlIGFsdW1icmFkbyBjb3JyZXNwb25kZW4gYSAyMDIxLCBtaWVudHJhcyBxdWUgbG9zIHJlZ2lzdHJvcyBkZSBkZWxpdG9zIGNvcnJlc3BvbmRlbiBhbCBwZXJpb2RvIGVuZXJvLWp1bGlvIGRlIDIwMjMuIFBvciB0YW50bywgbGFzIHJlbGFjaW9uZXMgZW5jb250cmFkYXMgZGViZW4gaW50ZXJwcmV0YXJzZSBjb21vIGFzb2NpYWNpb25lcyBleHBsb3JhdG9yaWFzIHkgbm8gY29tbyBldmlkZW5jaWEgZGUgdW5hIHJlbGFjacOzbiBjYXVzYWwuDQoNCkFzaW1pc21vLCB1bmEgbWF5b3IgY2FudGlkYWQgZGUgbHVtaW5hcmlhcyBubyBuZWNlc2FyaWFtZW50ZSByZXByZXNlbnRhIG1lam9yZXMgY29uZGljaW9uZXMgZGUgaWx1bWluYWNpw7NuIGVuIHRvZG9zIGxvcyBlc3BhY2lvcyBww7pibGljb3MsIHlhIHF1ZSBlc3RvcyBpbmRpY2Fkb3JlcyBubyBpbmNvcnBvcmFuIGFzcGVjdG9zIGNvbW8gc3UgdWJpY2FjacOzbiwgZnVuY2lvbmFtaWVudG8sIGludGVuc2lkYWQgbyBkaXN0cmlidWNpw7NuIGVmZWN0aXZhLg0KDQpgYGB7ciB2YXJpYWJsZXMtaW5mcmFlc3RydWN0dXJhLWRlbGl0b3MsIGVjaG89VFJVRX0NCiMgU2VsZWNjacOzbiBkZSB2YXJpYWJsZXMgZGUgaW5mcmFlc3RydWN0dXJhIHkgZGVsaXRvcw0KDQppbmZyYWVzdHJ1Y3R1cmFfZGVsaXRvcyA8LSB1cHogJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICBsdW1pbmFyaWFzX2ttMiwNCiAgICBsdW1pbmFyaWFzXzEwMDBoYWIsDQogICAgcGN0X2x1bWluYXJpYXNfbGVkLA0KICAgIHRhc2FfdG90YWwNCiAgKQ0KDQojIFZpc3VhbGl6YWNpw7NuIGRlIGxvcyBwcmltZXJvcyByZWdpc3Ryb3MNCg0Ka2FibGUoDQogIGhlYWQoaW5mcmFlc3RydWN0dXJhX2RlbGl0b3MsIDEwKSwNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJJbmRpY2Fkb3JlcyBkZSBpbmZyYWVzdHJ1Y3R1cmEgeSB0YXNhIGRlIGRlbGl0b3MgcG9yIFVQWiINCikNCmBgYA0KDQojIyMjIDUuNi40LjEuIFJlbGFjacOzbiBlbnRyZSBkZW5zaWRhZCBkZSBsdW1pbmFyaWFzIHkgdGFzYSBkZSBkZWxpdG9zDQoNCmBgYHtyIHJlbGFjaW9uLWx1bWluYXJpYXMtdGFzYSwgZWNobz1UUlVFfQ0KIyBSZWxhY2nDs24gZW50cmUgbHVtaW5hcmlhcyBwb3Iga20yIHkgdGFzYSBkZSBkZWxpdG9zDQoNCmdncGxvdCgNCiAgaW5mcmFlc3RydWN0dXJhX2RlbGl0b3MsDQogIGFlcyh4ID0gbHVtaW5hcmlhc19rbTIsIHkgPSB0YXNhX3RvdGFsKQ0KKSArDQogIGdlb21fcG9pbnQoDQogICAgY29sb3IgPSAiIzM1MUE0RiIsDQogICAgYWxwaGEgPSAwLjc1LA0KICAgIHNpemUgPSAyLjUNCiAgKSArDQogIGdlb21fc21vb3RoKA0KICAgIG1ldGhvZCA9ICJsbSIsDQogICAgc2UgPSBUUlVFLA0KICAgIGNvbG9yID0gIiNEOTAwNkMiLA0KICAgIGZpbGwgPSAiI0Q5MDA2QyIsDQogICAgYWxwaGEgPSAwLjE1DQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRlbnNpZGFkIGRlIGx1bWluYXJpYXMgeSB0YXNhIGRlIGRlbGl0b3MiLA0KICAgIHN1YnRpdGxlID0gIkNvbXBhcmFjacOzbiBlbnRyZSBVUFogZGUgQm9nb3TDoSIsDQogICAgeCA9ICJMdW1pbmFyaWFzIHBvciBrbcKyIiwNCiAgICB5ID0gIkRlbGl0b3MgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlczogaW5kaWNhZG9yZXMgZGUgYWx1bWJyYWRvIDIwMjEgeSByZWdpc3Ryb3MgZGUgZGVsaXRvcyBlbmVyby1qdWxpbyAyMDIzIg0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQoNCiMjIyMgNS42LjQuMi4gUmVsYWNpw7NuIGVudHJlIGx1bWluYXJpYXMgcG9yIGhhYml0YW50ZSB5IHRhc2EgZGUgZGVsaXRvcw0KDQpgYGB7ciByZWxhY2lvbi1sdW1pbmFyaWFzLXBvYmxhY2lvbi10YXNhLCBlY2hvPVRSVUV9DQojIFJlbGFjacOzbiBlbnRyZSBsdW1pbmFyaWFzIHBvciBjYWRhIDEuMDAwIGhhYml0YW50ZXMgeSB0YXNhIGRlIGRlbGl0b3MNCg0KZ2dwbG90KA0KICBpbmZyYWVzdHJ1Y3R1cmFfZGVsaXRvcywNCiAgYWVzKHggPSBsdW1pbmFyaWFzXzEwMDBoYWIsIHkgPSB0YXNhX3RvdGFsKQ0KKSArDQogIGdlb21fcG9pbnQoDQogICAgY29sb3IgPSAiIzE2OEM4NiIsDQogICAgYWxwaGEgPSAwLjc1LA0KICAgIHNpemUgPSAyLjUNCiAgKSArDQogIGdlb21fc21vb3RoKA0KICAgIG1ldGhvZCA9ICJsbSIsDQogICAgc2UgPSBUUlVFLA0KICAgIGNvbG9yID0gIiNEOTAwNkMiLA0KICAgIGZpbGwgPSAiI0Q5MDA2QyIsDQogICAgYWxwaGEgPSAwLjE1DQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3BvbmliaWxpZGFkIGRlIGx1bWluYXJpYXMgcG9yIGhhYml0YW50ZSB5IHRhc2EgZGUgZGVsaXRvcyIsDQogICAgc3VidGl0bGUgPSAiTHVtaW5hcmlhcyBwb3IgY2FkYSAxLjAwMCBoYWJpdGFudGVzIiwNCiAgICB4ID0gIkx1bWluYXJpYXMgcG9yIGNhZGEgMS4wMDAgaGFiaXRhbnRlcyIsDQogICAgeSA9ICJEZWxpdG9zIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZXM6IGluZGljYWRvcmVzIGRlIGFsdW1icmFkbyAyMDIxIHkgcmVnaXN0cm9zIGRlIGRlbGl0b3MgZW5lcm8tanVsaW8gMjAyMyINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMjIDUuNi40LjMuIFJlbGFjacOzbiBlbnRyZSBwb3JjZW50YWplIGRlIGx1bWluYXJpYXMgTEVEIHkgdGFzYSBkZSBkZWxpdG9zDQoNCmBgYHtyIHJlbGFjaW9uLWxlZC10YXNhLWRlbGl0b3MsIGVjaG89VFJVRX0NCiMgUmVsYWNpw7NuIGVudHJlIHBvcmNlbnRhamUgZGUgbHVtaW5hcmlhcyBMRUQgeSB0YXNhIGRlIGRlbGl0b3MNCg0KZ2dwbG90KA0KICBpbmZyYWVzdHJ1Y3R1cmFfZGVsaXRvcywNCiAgYWVzKHggPSBwY3RfbHVtaW5hcmlhc19sZWQsIHkgPSB0YXNhX3RvdGFsKQ0KKSArDQogIGdlb21fcG9pbnQoDQogICAgY29sb3IgPSAiIzM1MUE0RiIsDQogICAgYWxwaGEgPSAwLjc1LA0KICAgIHNpemUgPSAyLjUNCiAgKSArDQogIGdlb21fc21vb3RoKA0KICAgIG1ldGhvZCA9ICJsbSIsDQogICAgc2UgPSBUUlVFLA0KICAgIGNvbG9yID0gIiNEOTAwNkMiLA0KICAgIGZpbGwgPSAiI0Q5MDA2QyIsDQogICAgYWxwaGEgPSAwLjE1DQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBhcnRpY2lwYWNpw7NuIGRlIGx1bWluYXJpYXMgTEVEIHkgdGFzYSBkZSBkZWxpdG9zIiwNCiAgICBzdWJ0aXRsZSA9ICJDb21wYXJhY2nDs24gZGUgbGEgY29tcG9zaWNpw7NuIHRlY25vbMOzZ2ljYSBkZWwgYWx1bWJyYWRvIiwNCiAgICB4ID0gIkx1bWluYXJpYXMgTEVEICglKSIsDQogICAgeSA9ICJEZWxpdG9zIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZXM6IGluZGljYWRvcmVzIGRlIGFsdW1icmFkbyAyMDIxIHkgcmVnaXN0cm9zIGRlIGRlbGl0b3MgZW5lcm8tanVsaW8gMjAyMyINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQo1LjYuNC40LiBDb3JyZWxhY2lvbmVzIGVudHJlIGluZnJhZXN0cnVjdHVyYSB5IGRlbGl0b3MNCg0KYGBge3IgY29ycmVsYWNpb25lcy1pbmZyYWVzdHJ1Y3R1cmEtZGVsaXRvcywgZWNobz1UUlVFfQ0KIyBDw6FsY3VsbyBkZSBjb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuDQoNCmNvcnJlbGFjaW9uZXNfaW5mcmFlc3RydWN0dXJhIDwtIGluZnJhZXN0cnVjdHVyYV9kZWxpdG9zICU+JQ0KICBzdW1tYXJpc2UoDQogICAgQ29yX2x1bWluYXJpYXNfa20yID0gY29yKA0KICAgICAgbHVtaW5hcmlhc19rbTIsDQogICAgICB0YXNhX3RvdGFsLA0KICAgICAgbWV0aG9kID0gInNwZWFybWFuIiwNCiAgICAgIHVzZSA9ICJjb21wbGV0ZS5vYnMiDQogICAgKSwNCiAgICBDb3JfbHVtaW5hcmlhc18xMDAwaGFiID0gY29yKA0KICAgICAgbHVtaW5hcmlhc18xMDAwaGFiLA0KICAgICAgdGFzYV90b3RhbCwNCiAgICAgIG1ldGhvZCA9ICJzcGVhcm1hbiIsDQogICAgICB1c2UgPSAiY29tcGxldGUub2JzIg0KICAgICksDQogICAgQ29yX3BjdF9sZWQgPSBjb3IoDQogICAgICBwY3RfbHVtaW5hcmlhc19sZWQsDQogICAgICB0YXNhX3RvdGFsLA0KICAgICAgbWV0aG9kID0gInNwZWFybWFuIiwNCiAgICAgIHVzZSA9ICJjb21wbGV0ZS5vYnMiDQogICAgKQ0KICApICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGV2ZXJ5dGhpbmcoKSwNCiAgICBuYW1lc190byA9ICJSZWxhY2lvbiIsDQogICAgdmFsdWVzX3RvID0gIkNvcnJlbGFjaW9uX1NwZWFybWFuIg0KICApICU+JQ0KICBtdXRhdGUoDQogICAgSW50ZXJwcmV0YWNpb24gPSBjYXNlX3doZW4oDQogICAgICBhYnMoQ29ycmVsYWNpb25fU3BlYXJtYW4pIDwgMC4yMCB+ICJNdXkgZMOpYmlsIiwNCiAgICAgIGFicyhDb3JyZWxhY2lvbl9TcGVhcm1hbikgPCAwLjQwIH4gIkTDqWJpbCIsDQogICAgICBhYnMoQ29ycmVsYWNpb25fU3BlYXJtYW4pIDwgMC42MCB+ICJNb2RlcmFkYSIsDQogICAgICBhYnMoQ29ycmVsYWNpb25fU3BlYXJtYW4pIDwgMC44MCB+ICJGdWVydGUiLA0KICAgICAgVFJVRSB+ICJNdXkgZnVlcnRlIg0KICAgICkNCiAgKQ0KDQprYWJsZSgNCiAgY29ycmVsYWNpb25lc19pbmZyYWVzdHJ1Y3R1cmEsDQogIGRpZ2l0cyA9IDMsDQogIGNhcHRpb24gPSAiQ29ycmVsYWNpb25lcyBkZSBTcGVhcm1hbiBlbnRyZSBpbmRpY2Fkb3JlcyBkZSBhbHVtYnJhZG8geSB0YXNhIGRlIGRlbGl0b3MiDQopDQpgYGANCg0KIyMjIDUuNi41LiBSZWxhY2nDs24gZW50cmUgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcywgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgeSBkZWxpdG9zDQoNCkVuIGVzdGUgYXBhcnRhZG8gc2UgaW50ZWdyYW4gdmFyaWFibGVzIHNvY2lvZWNvbsOzbWljYXMgeSBkZSBwZXJjZXBjacOzbiBjaXVkYWRhbmEgY29uIGxvcyByZWdpc3Ryb3MgZGUgZGVsaXRvcyBkZSBhbHRvIGltcGFjdG8sIGNvbiBlbCBwcm9ww7NzaXRvIGRlIGV4cGxvcmFyIHBvc2libGVzIGFzb2NpYWNpb25lcyBlbnRyZSBsYXMgY29uZGljaW9uZXMgZGUgdmlkYSBkZSBsYXMgVVBaIHkgbG9zIGluZGljYWRvcmVzIGRlIHNlZ3VyaWRhZC4NCg0KU2UgY29uc2lkZXJhbiB0cmVzIHJlbGFjaW9uZXMgcHJpbmNpcGFsZXM6IGVsIHBvcmNlbnRhamUgZGUgcG9icmV6YSBmcmVudGUgYSBsYSB0YXNhIHRvdGFsIGRlIGRlbGl0b3MsIGVsIHNhbGFyaW8gcHJvbWVkaW8gZnJlbnRlIGEgbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zIHkgZWwgcG9yY2VudGFqZSBkZSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCBmcmVudGUgYSBsYSB0YXNhIHRvdGFsIGRlIGRlbGl0b3MuDQoNCkVzdGFzIGNvbXBhcmFjaW9uZXMgcGVybWl0ZW4gZXhhbWluYXIgc2kgbGFzIGRpZmVyZW5jaWFzIHNvY2lvZWNvbsOzbWljYXMgZW50cmUgdGVycml0b3Jpb3MgcHJlc2VudGFuIGFsZ8O6biBwYXRyw7NuIGFzb2NpYWRvIGNvbiBsb3Mgbml2ZWxlcyBkZSBjcmltaW5hbGlkYWQgcmVnaXN0cmFkb3MgeSBzaSBsYSBwZXJjZXBjacOzbiBjaXVkYWRhbmEgZ3VhcmRhIGNvcnJlc3BvbmRlbmNpYSBjb24gbGFzIGRlbnVuY2lhcyBkZSBkZWxpdG9zLg0KDQpQYXJhIGV2YWx1YXIgZXN0YXMgcmVsYWNpb25lcyBzZSB1dGlsaXphbiBkaWFncmFtYXMgZGUgZGlzcGVyc2nDs24geSBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gZGUgU3BlYXJtYW4uIEVzdGUgw7psdGltbyBwZXJtaXRlIGlkZW50aWZpY2FyIGFzb2NpYWNpb25lcyBtb25vdMOzbmljYXMgZW50cmUgbGFzIHZhcmlhYmxlcyBzaW4gZXhpZ2lyIHVuYSByZWxhY2nDs24gbGluZWFsLg0KDQpFcyBpbXBvcnRhbnRlIGRpZmVyZW5jaWFyIGxhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIGRlIGxvcyBkZWxpdG9zIGRlbnVuY2lhZG9zLiBMYSBwcmltZXJhIGNvcnJlc3BvbmRlIGEgbGEgcHJvcG9yY2nDs24gZGUgcGVyc29uYXMgcXVlIG1hbmlmaWVzdGFuIHBlcmNpYmlyIHByb2JsZW1hcyBkZSBpbnNlZ3VyaWRhZCBlbiBlbCBlbnRvcm5vIGRlIHN1IHZpdmllbmRhLCBtaWVudHJhcyBxdWUgbGEgc2VndW5kYSByZXByZXNlbnRhIHJlZ2lzdHJvcyBhZG1pbmlzdHJhdGl2b3MgZGUgZGVudW5jaWFzLiBQb3IgdGFudG8sIGFtYmFzIGRpbWVuc2lvbmVzIGRlc2NyaWJlbiBhc3BlY3RvcyBkaWZlcmVudGVzIGRlbCBmZW7Ds21lbm8gZGUgbGEgc2VndXJpZGFkLg0KDQpBZGljaW9uYWxtZW50ZSwgbG9zIGluZGljYWRvcmVzIHNvY2lvZWNvbsOzbWljb3MgeSBkZSBwZXJjZXBjacOzbiBjb3JyZXNwb25kZW4gYSBsYSBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8gZGUgMjAyMSwgbWllbnRyYXMgcXVlIGxvcyBkZWxpdG9zIGNvcnJlc3BvbmRlbiBhbCBwZXJpb2RvIGVuZXJvLWp1bGlvIGRlIDIwMjMuIFRhbWJpw6luIHNlIGRlYmUgY29uc2lkZXJhciBxdWUgYWxndW5hcyBlc3RpbWFjaW9uZXMgZGUgbGEgZW5jdWVzdGEgZnVlcm9uIGFncnVwYWRhcyBlbnRyZSBVUFogdmVjaW5hcywgbG8gcXVlIGxpbWl0YSBsYSBpbmRlcGVuZGVuY2lhIGRlIGxhcyBvYnNlcnZhY2lvbmVzIHRlcnJpdG9yaWFsZXMuDQoNCiMjIyMgNS42LjUuMS4gU2VsZWNjacOzbiBkZSB2YXJpYWJsZXMNCg0KUHJpbWVybywgb3JnYW5pemFtb3MgbGFzIHZhcmlhYmxlcyBxdWUgdXRpbGl6YXJlbW9zIGVuIGVzdGUgYW7DoWxpc2lzLg0KDQpgYGB7ciBzZWxlY2Npb24tc29jaW9lY29ub21pYS1zZWd1cmlkYWQsIGVjaG89VFJVRX0NCiMgU2VsZWNjacOzbiBkZSB2YXJpYWJsZXMgc29jaW9lY29uw7NtaWNhcyB5IGRlIHNlZ3VyaWRhZA0KDQpzb2Npb2Vjb25vbWlhX3NlZ3VyaWRhZCA8LSB1cHogJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIGxvY2FsaWRhZCwNCiAgICBlbV9hZ3J1cGFkYSwNCiAgICBwY3RfcG9icmV6YSwNCiAgICBzYWxhcmlvX3Byb21lZGlvLA0KICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkLA0KICAgIHRhc2FfdG90YWwNCiAgKQ0KDQojIFZpc3VhbGl6YWNpw7NuIGRlIGxvcyBwcmltZXJvcyByZWdpc3Ryb3MNCg0Ka25pdHI6OmthYmxlKA0KICBoZWFkKHNvY2lvZWNvbm9taWFfc2VndXJpZGFkLCAxMCksDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiVmFyaWFibGVzIHNvY2lvZWNvbsOzbWljYXMgeSBkZSBzZWd1cmlkYWQgcG9yIFVQWiINCikNCmBgYA0KDQojIyMjIDUuNi41LjIuIFJlbGFjacOzbiBlbnRyZSBwb2JyZXphIHkgdGFzYSBkZSBkZWxpdG9zDQoNCmBgYHtyIHJlbGFjaW9uLXBvYnJlemEtdGFzYS1kZWxpdG9zLCBlY2hvPVRSVUV9DQpnZ3Bsb3QoDQogIHNvY2lvZWNvbm9taWFfc2VndXJpZGFkLA0KICBhZXMoDQogICAgeCA9IHBjdF9wb2JyZXphLA0KICAgIHkgPSB0YXNhX3RvdGFsDQogICkNCikgKw0KICBnZW9tX3BvaW50KA0KICAgIGFlcyhjb2xvciA9IGVtX2FncnVwYWRhKSwNCiAgICBhbHBoYSA9IDAuOCwNCiAgICBzaXplID0gMi41DQogICkgKw0KICBnZW9tX3Ntb290aCgNCiAgICBtZXRob2QgPSAibG0iLA0KICAgIHNlID0gVFJVRSwNCiAgICBjb2xvciA9IG1hZ2VudGEsDQogICAgZmlsbCA9IG1hZ2VudGEsDQogICAgYWxwaGEgPSAwLjE1DQogICkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICJGQUxTRSIgPSBtb3JhZG8sDQogICAgICAiVFJVRSIgPSB0dXJxdWVzYQ0KICAgICksDQogICAgbGFiZWxzID0gYygNCiAgICAgICJGQUxTRSIgPSAiRXN0aW1hY2nDs24gaW5kaXZpZHVhbCIsDQogICAgICAiVFJVRSIgPSAiRXN0aW1hY2nDs24gYWdydXBhZGEiDQogICAgKQ0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgcG9icmV6YSB5IHRhc2EgZGUgZGVsaXRvcyIsDQogICAgc3VidGl0bGUgPSAiQ29tcGFyYWNpw7NuIGRlIGNvbmRpY2lvbmVzIHNvY2lvZWNvbsOzbWljYXMgZW50cmUgVVBaIiwNCiAgICB4ID0gIlBvYmxhY2nDs24gZW4gY29uZGljacOzbiBkZSBwb2JyZXphICglKSIsDQogICAgeSA9ICJEZWxpdG9zIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzIiwNCiAgICBjb2xvciA9ICJUaXBvIGRlIGVzdGltYWNpw7NuIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZXM6IEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byAyMDIxIHkgcmVnaXN0cm9zIGRlIGRlbGl0b3MgZW5lcm8tanVsaW8gMjAyMyINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMjIDUuNi41LjMuIFJlbGFjacOzbiBlbnRyZSBzYWxhcmlvIHByb21lZGlvIHkgdGFzYSBkZSBkZWxpdG9zDQoNCmBgYHtyIHJlbGFjaW9uLXNhbGFyaW8tdGFzYS1kZWxpdG9zLCBlY2hvPVRSVUV9DQpnZ3Bsb3QoDQogIHNvY2lvZWNvbm9taWFfc2VndXJpZGFkLA0KICBhZXMoDQogICAgeCA9IHNhbGFyaW9fcHJvbWVkaW8sDQogICAgeSA9IHRhc2FfdG90YWwNCiAgKQ0KKSArDQogIGdlb21fcG9pbnQoDQogICAgYWVzKGNvbG9yID0gZW1fYWdydXBhZGEpLA0KICAgIGFscGhhID0gMC44LA0KICAgIHNpemUgPSAyLjUNCiAgKSArDQogIGdlb21fc21vb3RoKA0KICAgIG1ldGhvZCA9ICJsbSIsDQogICAgc2UgPSBUUlVFLA0KICAgIGNvbG9yID0gbWFnZW50YSwNCiAgICBmaWxsID0gbWFnZW50YSwNCiAgICBhbHBoYSA9IDAuMTUNCiAgKSArDQogIHNjYWxlX3hfY29udGludW91cygNCiAgICBsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX251bWJlcigNCiAgICAgIHByZWZpeCA9ICIkIiwNCiAgICAgIGJpZy5tYXJrID0gIi4iLA0KICAgICAgZGVjaW1hbC5tYXJrID0gIiwiDQogICAgKQ0KICApICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoDQogICAgICAiRkFMU0UiID0gbW9yYWRvLA0KICAgICAgIlRSVUUiID0gdHVycXVlc2ENCiAgICApLA0KICAgIGxhYmVscyA9IGMoDQogICAgICAiRkFMU0UiID0gIkVzdGltYWNpw7NuIGluZGl2aWR1YWwiLA0KICAgICAgIlRSVUUiID0gIkVzdGltYWNpw7NuIGFncnVwYWRhIg0KICAgICkNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUmVsYWNpw7NuIGVudHJlIHNhbGFyaW8gcHJvbWVkaW8geSB0YXNhIGRlIGRlbGl0b3MiLA0KICAgIHN1YnRpdGxlID0gIkNvbXBhcmFjacOzbiBkZSBpbmdyZXNvcyBwcm9tZWRpbyBlbnRyZSBVUFoiLA0KICAgIHggPSAiU2FsYXJpbyBwcm9tZWRpbyBtZW5zdWFsIiwNCiAgICB5ID0gIkRlbGl0b3MgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMiLA0KICAgIGNvbG9yID0gIlRpcG8gZGUgZXN0aW1hY2nDs24iLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlczogRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvIDIwMjEgeSByZWdpc3Ryb3MgZGUgZGVsaXRvcyBlbmVyby1qdWxpbyAyMDIzIg0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQoNCiMjIyMgNS42LjUuNC4gUmVsYWNpw7NuIGVudHJlIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHkgdGFzYSBkZSBkZWxpdG9zDQoNCmBgYHtyIHJlbGFjaW9uLXBlcmNlcGNpb24tdGFzYS1kZWxpdG9zLCBlY2hvPVRSVUV9DQpnZ3Bsb3QoDQogIHNvY2lvZWNvbm9taWFfc2VndXJpZGFkLA0KICBhZXMoDQogICAgeCA9IHBjdF9wZXJjaWJlX2luc2VndXJpZGFkLA0KICAgIHkgPSB0YXNhX3RvdGFsDQogICkNCikgKw0KICBnZW9tX3BvaW50KA0KICAgIGFlcyhjb2xvciA9IGVtX2FncnVwYWRhKSwNCiAgICBhbHBoYSA9IDAuOCwNCiAgICBzaXplID0gMi41DQogICkgKw0KICBnZW9tX3Ntb290aCgNCiAgICBtZXRob2QgPSAibG0iLA0KICAgIHNlID0gVFJVRSwNCiAgICBjb2xvciA9IG1hZ2VudGEsDQogICAgZmlsbCA9IG1hZ2VudGEsDQogICAgYWxwaGEgPSAwLjE1DQogICkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICJGQUxTRSIgPSBtb3JhZG8sDQogICAgICAiVFJVRSIgPSB0dXJxdWVzYQ0KICAgICksDQogICAgbGFiZWxzID0gYygNCiAgICAgICJGQUxTRSIgPSAiRXN0aW1hY2nDs24gaW5kaXZpZHVhbCIsDQogICAgICAiVFJVRSIgPSAiRXN0aW1hY2nDs24gYWdydXBhZGEiDQogICAgKQ0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJQZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCB5IHRhc2EgZGUgZGVsaXRvcyIsDQogICAgc3VidGl0bGUgPSAiQ29tcGFyYWNpw7NuIGVudHJlIHBlcmNlcGNpw7NuIGNpdWRhZGFuYSB5IHJlZ2lzdHJvcyBhZG1pbmlzdHJhdGl2b3MiLA0KICAgIHggPSAiUGVyc29uYXMgcXVlIHBlcmNpYmVuIGluc2VndXJpZGFkIGVuIHN1IGVudG9ybm8gKCUpIiwNCiAgICB5ID0gIkRlbGl0b3MgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMiLA0KICAgIGNvbG9yID0gIlRpcG8gZGUgZXN0aW1hY2nDs24iLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlczogRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvIDIwMjEgeSByZWdpc3Ryb3MgZGUgZGVsaXRvcyBlbmVyby1qdWxpbyAyMDIzIg0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQoNCiMjIyMgNS42LjUuNS4gTWF0cml6IGRlIGNvcnJlbGFjaW9uZXMgc29jaW9lY29uw7NtaWNhcyB5IGRlIHNlZ3VyaWRhZA0KYGBge3IgbWF0cml6LWNvcnJlbGFjaW9uZXMtc29jaW9lY29ub21pYS1zZWd1cmlkYWQsIGVjaG89VFJVRX0NCiMgU2VsZWNjacOzbiBpbnRlZ3JhZGEgZGUgdmFyaWFibGVzDQoNCnZhcmlhYmxlc19jb3JyZWxhY2lvbiA8LSB1cHogJT4lDQogIHNlbGVjdCgNCiAgICBwb2JsYWNpb24sDQogICAgZGVuc2lkYWRfaGFiX2ttMiwNCiAgICBsdW1pbmFyaWFzX2ttMiwNCiAgICBwY3RfcG9icmV6YSwNCiAgICBzYWxhcmlvX3Byb21lZGlvLA0KICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkLA0KICAgIHBjdF9jZXJjYV9sb3Rlc19vc2N1cm9zLA0KICAgIG1pbl9jYWlfcG9saWNpYSwNCiAgICBjYXNvc190b3RhbCwNCiAgICB0YXNhX3RvdGFsDQogICkNCg0KIyBDw6FsY3VsbyBkZSBsYSBtYXRyaXogZGUgY29ycmVsYWNpb25lcyBkZSBTcGVhcm1hbg0KDQptYXRyaXpfY29ycmVsYWNpb25lcyA8LSBjb3IoDQogIHZhcmlhYmxlc19jb3JyZWxhY2lvbiwNCiAgbWV0aG9kID0gInNwZWFybWFuIiwNCiAgdXNlID0gImNvbXBsZXRlLm9icyINCikNCg0KIyBUcmFuc2Zvcm1hY2nDs24gZGUgbGEgbWF0cml6IHBhcmEgdmlzdWFsaXphcmxhDQoNCm1hdHJpel9sYXJnYSA8LSBhcy5kYXRhLmZyYW1lKA0KICBhcy50YWJsZShtYXRyaXpfY29ycmVsYWNpb25lcykNCikgJT4lDQogIHJlbmFtZSgNCiAgICBWYXJpYWJsZV8xID0gVmFyMSwNCiAgICBWYXJpYWJsZV8yID0gVmFyMiwNCiAgICBDb3JyZWxhY2lvbiA9IEZyZXENCiAgKQ0KDQojIE1hcGEgZGUgY2Fsb3IgZGUgY29ycmVsYWNpb25lcw0KDQpnZ3Bsb3QoDQogIG1hdHJpel9sYXJnYSwNCiAgYWVzKA0KICAgIHggPSBWYXJpYWJsZV8xLA0KICAgIHkgPSBWYXJpYWJsZV8yLA0KICAgIGZpbGwgPSBDb3JyZWxhY2lvbg0KICApDQopICsNCiAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIiwgbGluZXdpZHRoID0gMC41KSArDQogIGdlb21fdGV4dCgNCiAgICBhZXMobGFiZWwgPSByb3VuZChDb3JyZWxhY2lvbiwgMikpLA0KICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICBzaXplID0gMw0KICApICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIoDQogICAgbG93ID0gbW9yYWRvLA0KICAgIG1pZCA9ICJ3aGl0ZSIsDQogICAgaGlnaCA9IG1hZ2VudGEsDQogICAgbWlkcG9pbnQgPSAwLA0KICAgIGxpbWl0cyA9IGMoLTEsIDEpDQogICkgKw0KICBjb29yZF9lcXVhbCgpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJNYXRyaXogaW50ZWdyYWRhIGRlIGNvcnJlbGFjaW9uZXMgZW50cmUgdmFyaWFibGVzIiwNCiAgICBzdWJ0aXRsZSA9ICJDb2VmaWNpZW50ZXMgZGUgU3BlYXJtYW4gcGFyYSBsYXMgZGltZW5zaW9uZXMgdGVycml0b3JpYWxlcyB5IGRlIHNlZ3VyaWRhZCIsDQogICAgeCA9IE5VTEwsDQogICAgeSA9IE5VTEwsDQogICAgZmlsbCA9ICJDb3JyZWxhY2nDs24iLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBlbGFib3JhY2nDs24gcHJvcGlhIGEgcGFydGlyIGRlIGxvcyBpbmRpY2Fkb3JlcyBkZSBsYXMgVVBaLiINCiAgKSArDQogIHRlbWFfY2xhc2UgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dCgNCiAgICAgIGFuZ2xlID0gNDUsDQogICAgICBoanVzdCA9IDEsDQogICAgICBzaXplID0gOQ0KICAgICksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLA0KICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkNCiAgKQ0KYGBgDQoNCiMjIyA1LjYuNi4gU8OtbnRlc2lzIGRlIGxhcyByZWxhY2lvbmVzIGVudHJlIHZhcmlhYmxlcw0KDQpEZXNwdcOpcyBkZSBleHBsb3JhciBsYXMgcmVsYWNpb25lcyBlbnRyZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZW1vZ3LDoWZpY2FzLCBsYSBpbmZyYWVzdHJ1Y3R1cmEgdXJiYW5hLCBsYXMgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcywgbGEgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgeSBsb3MgcmVnaXN0cm9zIGRlIGRlbGl0b3MsIHNlIHJlYWxpemEgdW5hIHPDrW50ZXNpcyBkZSBsYXMgY29ycmVsYWNpb25lcyBvYnRlbmlkYXMuDQoNCkVsIHByb3DDs3NpdG8gZGUgZXN0YSBldGFwYSBlcyBpZGVudGlmaWNhciBsYXMgYXNvY2lhY2lvbmVzIGVzdGFkw61zdGljYXMgZGUgbWF5b3IgbWFnbml0dWQgZW50cmUgbGFzIHZhcmlhYmxlcyBzZWxlY2Npb25hZGFzIHkgZmFjaWxpdGFyIHN1IGludGVycHJldGFjacOzbiBkZXNkZSB1bmEgcGVyc3BlY3RpdmEgaW50ZWdyYWwgZGVsIHRlcnJpdG9yaW8uDQoNClBhcmEgZWxsbywgc2Ugb3JnYW5pemFuIGxvcyBjb2VmaWNpZW50ZXMgZGUgY29ycmVsYWNpw7NuIGRlIFNwZWFybWFuIGVuIHVuYSB0YWJsYSBjb21wYXJhdGl2YSwgb3JkZW5hZGEgc2Vnw7puIGVsIHZhbG9yIGFic29sdXRvIGRlIGNhZGEgY29ycmVsYWNpw7NuLiBEZSBlc3RhIG1hbmVyYSwgZXMgcG9zaWJsZSByZWNvbm9jZXIgbGFzIHJlbGFjaW9uZXMgcG9zaXRpdmFzIHkgbmVnYXRpdmFzIGRlIG1heW9yIGludGVuc2lkYWQsIHNpbiBsaW1pdGFyIGVsIGFuw6FsaXNpcyBleGNsdXNpdmFtZW50ZSBhIGxhcyB2YXJpYWJsZXMgcmVsYWNpb25hZGFzIGNvbiBsb3MgZGVsaXRvcy4NCg0KRXN0YSBzw61udGVzaXMgcGVybWl0ZSBpZGVudGlmaWNhciBwYXRyb25lcyBxdWUgcHVlZGVuIG9yaWVudGFyIGxhIGludGVycHJldGFjacOzbiBkZSBsb3MgcmVzdWx0YWRvcyB5IGxhIHNlbGVjY2nDs24gZGUgaW5kaWNhZG9yZXMgcmVsZXZhbnRlcyBwYXJhIGxhIHNpZ3VpZW50ZSBldGFwYSBkZSB2aXN1YWxpemFjacOzbiBnZW9ncsOhZmljYS4NCg0KRXMgaW1wb3J0YW50ZSBzZcOxYWxhciBxdWUgbGEgbWFnbml0dWQgZGUgdW5hIGNvcnJlbGFjacOzbiBubyBpbXBsaWNhIGNhdXNhbGlkYWQuIEFkZW3DoXMsIGxhcyByZWxhY2lvbmVzIGRlYmVuIGludGVycHJldGFyc2UgY29uc2lkZXJhbmRvIGxhcyBkaWZlcmVuY2lhcyB0ZW1wb3JhbGVzIGVudHJlIGxhcyBmdWVudGVzIGRlIGluZm9ybWFjacOzbiB5IGxhcyBlc3RpbWFjaW9uZXMgc29jaW9lY29uw7NtaWNhcyBhZ3J1cGFkYXMgcGFyYSBhbGd1bmFzIFVQWi4NCg0KIyMjIyA1LjYuNi4xLiBJZGVudGlmaWNhY2nDs24gZGUgbGFzIGNvcnJlbGFjaW9uZXMgbcOhcyByZWxldmFudGVzDQoNCmBgYHtyIHJhbmtpbmctY29ycmVsYWNpb25lcy1pbnRlZ3JhZGFzLCBlY2hvPVRSVUV9DQojIENvbnZlcnRpciBsYSBtYXRyaXogZGUgY29ycmVsYWNpb25lcyBlbiB1bmEgdGFibGENCg0KcmFua2luZ19jb3JyZWxhY2lvbmVzIDwtIGFzLmRhdGEuZnJhbWUoDQogIGFzLnRhYmxlKG1hdHJpel9jb3JyZWxhY2lvbmVzKQ0KKSAlPiUNCiAgcmVuYW1lKA0KICAgIFZhcmlhYmxlXzEgPSBWYXIxLA0KICAgIFZhcmlhYmxlXzIgPSBWYXIyLA0KICAgIENvcnJlbGFjaW9uID0gRnJlcQ0KICApICU+JQ0KICBtdXRhdGUoDQogICAgVmFyaWFibGVfMSA9IGFzLmNoYXJhY3RlcihWYXJpYWJsZV8xKSwNCiAgICBWYXJpYWJsZV8yID0gYXMuY2hhcmFjdGVyKFZhcmlhYmxlXzIpDQogICkgJT4lDQogICMgRWxpbWluYXIgZGlhZ29uYWwgeSByZWxhY2lvbmVzIGR1cGxpY2FkYXMNCiAgZmlsdGVyKFZhcmlhYmxlXzEgPCBWYXJpYWJsZV8yKSAlPiUNCiAgIyBDbGFzaWZpY2FyIGxhIGRpcmVjY2nDs24gZGUgbGEgcmVsYWNpw7NuDQogIG11dGF0ZSgNCiAgICBEaXJlY2Npb24gPSBpZl9lbHNlKA0KICAgICAgQ29ycmVsYWNpb24gPj0gMCwNCiAgICAgICJQb3NpdGl2YSIsDQogICAgICAiTmVnYXRpdmEiDQogICAgKSwNCiAgICBNYWduaXR1ZCA9IGNhc2Vfd2hlbigNCiAgICAgIGFicyhDb3JyZWxhY2lvbikgPCAwLjIwIH4gIk11eSBkw6liaWwiLA0KICAgICAgYWJzKENvcnJlbGFjaW9uKSA8IDAuNDAgfiAiRMOpYmlsIiwNCiAgICAgIGFicyhDb3JyZWxhY2lvbikgPCAwLjYwIH4gIk1vZGVyYWRhIiwNCiAgICAgIGFicyhDb3JyZWxhY2lvbikgPCAwLjgwIH4gIkZ1ZXJ0ZSIsDQogICAgICBUUlVFIH4gIk11eSBmdWVydGUiDQogICAgKSwNCiAgICBNYWduaXR1ZF9hYnNvbHV0YSA9IGFicyhDb3JyZWxhY2lvbikNCiAgKSAlPiUNCiAgYXJyYW5nZShkZXNjKE1hZ25pdHVkX2Fic29sdXRhKSkNCg0KIyBQcmVzZW50YXIgbGFzIDEwIGFzb2NpYWNpb25lcyBkZSBtYXlvciBtYWduaXR1ZA0KDQp0b3BfY29ycmVsYWNpb25lcyA8LSByYW5raW5nX2NvcnJlbGFjaW9uZXMgJT4lDQogIHNsaWNlX2hlYWQobiA9IDEwKSAlPiUNCiAgc2VsZWN0KA0KICAgIFZhcmlhYmxlXzEsDQogICAgVmFyaWFibGVfMiwNCiAgICBDb3JyZWxhY2lvbiwNCiAgICBEaXJlY2Npb24sDQogICAgTWFnbml0dWQNCiAgKQ0KDQprbml0cjo6a2FibGUoDQogIHRvcF9jb3JyZWxhY2lvbmVzLA0KICBkaWdpdHMgPSAzLA0KICBjb2wubmFtZXMgPSBjKA0KICAgICJWYXJpYWJsZSAxIiwNCiAgICAiVmFyaWFibGUgMiIsDQogICAgIkNvcnJlbGFjacOzbiIsDQogICAgIkRpcmVjY2nDs24iLA0KICAgICJNYWduaXR1ZCINCiAgKSwNCiAgY2FwdGlvbiA9ICJMYXMgMTAgY29ycmVsYWNpb25lcyBkZSBtYXlvciBtYWduaXR1ZCBlbnRyZSBsYXMgdmFyaWFibGVzIGFuYWxpemFkYXMiDQopDQpgYGANCg0KIyMjIyA1LjYuNi4yLiBWaXN1YWxpemFjacOzbiBkZSBsYXMgY29ycmVsYWNpb25lcyBtw6FzIHJlbGV2YW50ZXMNCg0KYGBge3IgZ3JhZmljby1yYW5raW5nLWNvcnJlbGFjaW9uZXMsIGVjaG89VFJVRX0NCmdncGxvdCgNCiAgdG9wX2NvcnJlbGFjaW9uZXMsDQogIGFlcygNCiAgICB4ID0gcmVvcmRlcigNCiAgICAgIHBhc3RlKFZhcmlhYmxlXzEsICJ2cy4iLCBWYXJpYWJsZV8yKSwNCiAgICAgIENvcnJlbGFjaW9uDQogICAgKSwNCiAgICB5ID0gQ29ycmVsYWNpb24sDQogICAgZmlsbCA9IERpcmVjY2lvbg0KICApDQopICsNCiAgZ2VvbV9jb2wod2lkdGggPSAwLjcpICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gMCwNCiAgICBjb2xvciA9ICJncmV5NDAiLA0KICAgIGxpbmV3aWR0aCA9IDAuNQ0KICApICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICJQb3NpdGl2YSIgPSBtYWdlbnRhLA0KICAgICAgIk5lZ2F0aXZhIiA9IG1vcmFkbw0KICAgICkNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUHJpbmNpcGFsZXMgYXNvY2lhY2lvbmVzIGVudHJlIHZhcmlhYmxlcyIsDQogICAgc3VidGl0bGUgPSAiRGlleiBjb3JyZWxhY2lvbmVzIGRlIG1heW9yIG1hZ25pdHVkIGFic29sdXRhIiwNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gIkNvZWZpY2llbnRlIGRlIFNwZWFybWFuIiwNCiAgICBmaWxsID0gIkRpcmVjY2nDs24iLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBlbGFib3JhY2nDs24gcHJvcGlhIGEgcGFydGlyIGRlIGxvcyBpbmRpY2Fkb3JlcyBkZSBsYXMgVVBaLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMjIDUuNi42LjMuIENvcnJlbGFjaW9uZXMgZXNwZWPDrWZpY2FzIGNvbiBsYSB0YXNhIGRlIGRlbGl0b3MNCg0KYGBge3IgY29ycmVsYWNpb25lcy10YXNhLWRlbGl0b3MsIGVjaG89VFJVRX0NCiMgSWRlbnRpZmljYXIgbGFzIHZhcmlhYmxlcyByZWxhY2lvbmFkYXMgY29uIGxhIHRhc2EgdG90YWwgZGUgZGVsaXRvcw0KDQpjb3JyZWxhY2lvbmVzX3Rhc2EgPC0gcmFua2luZ19jb3JyZWxhY2lvbmVzICU+JQ0KICBmaWx0ZXIoDQogICAgVmFyaWFibGVfMSA9PSAidGFzYV90b3RhbCIgfA0KICAgIFZhcmlhYmxlXzIgPT0gInRhc2FfdG90YWwiDQogICkgJT4lDQogIG11dGF0ZSgNCiAgICBWYXJpYWJsZV9yZWxhY2lvbmFkYSA9IGlmX2Vsc2UoDQogICAgICBWYXJpYWJsZV8xID09ICJ0YXNhX3RvdGFsIiwNCiAgICAgIFZhcmlhYmxlXzIsDQogICAgICBWYXJpYWJsZV8xDQogICAgKQ0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MoTWFnbml0dWRfYWJzb2x1dGEpKSAlPiUNCiAgc2VsZWN0KA0KICAgIFZhcmlhYmxlX3JlbGFjaW9uYWRhLA0KICAgIENvcnJlbGFjaW9uLA0KICAgIERpcmVjY2lvbiwNCiAgICBNYWduaXR1ZA0KICApDQoNCmtuaXRyOjprYWJsZSgNCiAgY29ycmVsYWNpb25lc190YXNhLA0KICBkaWdpdHMgPSAzLA0KICBjb2wubmFtZXMgPSBjKA0KICAgICJWYXJpYWJsZSByZWxhY2lvbmFkYSIsDQogICAgIkNvcnJlbGFjacOzbiIsDQogICAgIkRpcmVjY2nDs24iLA0KICAgICJNYWduaXR1ZCINCiAgKSwNCiAgY2FwdGlvbiA9ICJSZWxhY2lvbmVzIGRlIGxhcyB2YXJpYWJsZXMgc2VsZWNjaW9uYWRhcyBjb24gbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zIg0KKQ0KYGBgDQoNCiMjIyA1LjYuNy4gQ29uc2lkZXJhY2lvbmVzIGdlbmVyYWxlcyBkZWwgYW7DoWxpc2lzIGRlIHJlbGFjaW9uZXMNCg0KRWwgYW7DoWxpc2lzIGRlIGNvcnJlbGFjaW9uZXMgcGVybWl0acOzIGludGVncmFyIGRpZmVyZW50ZXMgZGltZW5zaW9uZXMgZGUgbGFzIFVQWiB5IGV4cGxvcmFyIHBvc2libGVzIGFzb2NpYWNpb25lcyBlbnRyZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyB0ZXJyaXRvcmlhbGVzIHkgbG9zIGluZGljYWRvcmVzIGRlIHNlZ3VyaWRhZC4NCg0KTGEgbWF0cml6IGludGVncmFkYSB5IGxhcyB0YWJsYXMgZGUgY29ycmVsYWNpb25lcyBmYWNpbGl0YW4gbGEgaWRlbnRpZmljYWNpw7NuIGRlIHJlbGFjaW9uZXMgcXVlIHB1ZWRlbiBzZXIgcmVsZXZhbnRlcyBwYXJhIGNvbXByZW5kZXIgbGFzIGRpZmVyZW5jaWFzIGVudHJlIHRlcnJpdG9yaW9zLiBTaW4gZW1iYXJnbywgZXN0b3MgcmVzdWx0YWRvcyBkZWJlbiBpbnRlcnByZXRhcnNlIGRlbnRybyBkZWwgYWxjYW5jZSBleHBsb3JhdG9yaW8gZGVsIGVzdHVkaW8uDQoNCkxhcyBhc29jaWFjaW9uZXMgZXN0YWTDrXN0aWNhcyBubyBwZXJtaXRlbiBlc3RhYmxlY2VyIHJlbGFjaW9uZXMgZGUgY2F1c2FsaWRhZCB5IHRhbXBvY28gZ2FyYW50aXphbiBxdWUgbG9zIHBhdHJvbmVzIG9ic2VydmFkb3Mgc2UgbWFudGVuZ2FuIGVuIG90cm9zIHBlcmlvZG9zLiBBZGljaW9uYWxtZW50ZSwgbGFzIGRpZmVyZW5jaWFzIHRlbXBvcmFsZXMgZW50cmUgbGFzIGZ1ZW50ZXMgeSBsYXMgZXN0aW1hY2lvbmVzIGFncnVwYWRhcyBkZSBsYSBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8gcmVwcmVzZW50YW4gbGltaXRhY2lvbmVzIHF1ZSBkZWJlbiBjb25zaWRlcmFyc2UgZW4gbGEgaW50ZXJwcmV0YWNpw7NuLg0KDQpMb3MgcmVzdWx0YWRvcyBkZSBlc3RhIHNlY2Npw7NuIHNlcnZpcsOhbiBjb21vIHJlZmVyZW5jaWEgcGFyYSBwcm9mdW5kaXphciBlbiBsYSBkaXN0cmlidWNpw7NuIGVzcGFjaWFsIGRlIGxvcyBpbmRpY2Fkb3JlcyB5IGV4YW1pbmFyIHNpIGxvcyBwYXRyb25lcyBlc3RhZMOtc3RpY29zIGlkZW50aWZpY2Fkb3MgdGFtYmnDqW4gc2UgbWFuaWZpZXN0YW4gdGVycml0b3JpYWxtZW50ZS4NCg0KIyA2LiBWaXN1YWxpemFjacOzbiBnZW9ncsOhZmljYTogZGlzdHJpYnVjacOzbiB0ZXJyaXRvcmlhbCBkZSBsYSBpbnNlZ3VyaWRhZCBlbiBCb2dvdMOhDQoNCkVsIGFuw6FsaXNpcyBnZW9ncsOhZmljbyBwZXJtaXRlIGNvbXBsZW1lbnRhciBsb3MgcmVzdWx0YWRvcyBlc3RhZMOtc3RpY29zIG1lZGlhbnRlIGxhIHJlcHJlc2VudGFjacOzbiBlc3BhY2lhbCBkZSBsb3MgaW5kaWNhZG9yZXMgYXNvY2lhZG9zIGNvbiBsYXMgY29uZGljaW9uZXMgZGUgc2VndXJpZGFkIGRlIGxhcyBVUFogZGUgQm9nb3TDoS4NCg0KTWllbnRyYXMgcXVlIGxhcyB0YWJsYXMgeSBsb3MgZ3LDoWZpY29zIGFudGVyaW9yZXMgcGVybWl0ZW4gaWRlbnRpZmljYXIgZGlzdHJpYnVjaW9uZXMsIGRpZmVyZW5jaWFzIHkgYXNvY2lhY2lvbmVzIGVudHJlIHZhcmlhYmxlcywgbG9zIG1hcGFzIGZhY2lsaXRhbiBsYSBjb21wcmVuc2nDs24gZGUgY8OzbW8gc2UgZGlzdHJpYnV5ZW4gZXN0b3MgY29tcG9ydGFtaWVudG9zIGVuIGVsIHRlcnJpdG9yaW8uDQoNClBhcmEgZGVzYXJyb2xsYXIgZXN0YSBldGFwYSBzZSBpbnRlZ3JhcsOhIGxhIGluZm9ybWFjacOzbiBlc3RhZMOtc3RpY2EgZGUgbGFzIFVQWiBjb24gbG9zIGFyY2hpdm9zIGdlb2dyw6FmaWNvcyBxdWUgY29udGllbmVuIHN1cyBsw61taXRlcyB0ZXJyaXRvcmlhbGVzLiBEZSBlc3RhIG1hbmVyYSwgc2Vyw6EgcG9zaWJsZSByZXByZXNlbnRhciBpbmRpY2Fkb3JlcyBjb21vIGxhIGNhbnRpZGFkIGRlIGRlbGl0b3MgZGVudW5jaWFkb3MsIGxhcyB0YXNhcyBkZSBjcmltaW5hbGlkYWQsIGxhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHkgYWxndW5hcyBjYXJhY3RlcsOtc3RpY2FzIHNvY2lvZWNvbsOzbWljYXMgeSBkZSBpbmZyYWVzdHJ1Y3R1cmEuDQoNCkxhIHZpc3VhbGl6YWNpw7NuIHNlIHJlYWxpemFyw6EgbWVkaWFudGUgbWFwYXMgdGVtw6F0aWNvcywgdXRpbGl6YW5kbyBlc2NhbGFzIGRlIGNvbG9yIHF1ZSBwZXJtaXRhbiBkaWZlcmVuY2lhciBsb3Mgbml2ZWxlcyBkZSBjYWRhIGluZGljYWRvciBlbnRyZSBsYXMgdW5pZGFkZXMgdGVycml0b3JpYWxlcy4NCg0KRWwgcHJvcMOzc2l0byBubyBlcyDDum5pY2FtZW50ZSBpZGVudGlmaWNhciBsYXMgVVBaIGNvbiB2YWxvcmVzIGFsdG9zIG8gYmFqb3MsIHNpbm8gcmVjb25vY2VyIHBvc2libGVzIGNvbmNlbnRyYWNpb25lcyBlc3BhY2lhbGVzLCBkaWZlcmVuY2lhcyBlbnRyZSBsb2NhbGlkYWRlcyB5IHBhdHJvbmVzIHRlcnJpdG9yaWFsZXMgcXVlIGNvbXBsZW1lbnRlbiBsb3MgcmVzdWx0YWRvcyBkZWwgYW7DoWxpc2lzIGV4cGxvcmF0b3Jpby4NCg0KRXMgaW1wb3J0YW50ZSB0ZW5lciBwcmVzZW50ZSBxdWUgbGEgcmVwcmVzZW50YWNpw7NuIGdlb2dyw6FmaWNhIG5vIG1vZGlmaWNhIGxhcyBsaW1pdGFjaW9uZXMgZGUgbGFzIGZ1ZW50ZXMgb3JpZ2luYWxlcy4gUG9yIHRhbnRvLCBsb3MgbWFwYXMgZGViZW4gaW50ZXJwcmV0YXJzZSBjb25zaWRlcmFuZG8gbG9zIHBlcmlvZG9zIGRlIHJlZmVyZW5jaWEgZGUgbG9zIGRhdG9zLCBsYXMgZGlmZXJlbmNpYXMgZW4gbGFzIG1ldG9kb2xvZ8OtYXMgZGUgbWVkaWNpw7NuIHkgbGFzIGNhcmFjdGVyw61zdGljYXMgZGUgbGFzIGVzdGltYWNpb25lcyBkaXNwb25pYmxlcy4NCg0KIyMgNi4xLiBSZXZpc2nDs24gZGUgbGEgaW5mb3JtYWNpw7NuIGdlb2dyw6FmaWNhDQoNClByaW1lcm8gZGViZW1vcyBjb25vY2VyIGxhIGVzdHJ1Y3R1cmEgZGUgbG9zIGFyY2hpdm9zIGdlb2dyw6FmaWNvcy4gQXVucXVlIHlhIGxvcyBjYXJnYW1vcywgbmVjZXNpdGFtb3MgaWRlbnRpZmljYXIgc3VzIGNhbXBvcywgc2lzdGVtYXMgZGUgY29vcmRlbmFkYXMgeSBjYXJhY3RlcsOtc3RpY2FzIGdlbmVyYWxlcy4NCg0KYGBge3IgcmV2aXNpb24tYXJjaGl2b3MtZ2VvZ3JhZmljb3MsIGVjaG89VFJVRX0NCiMgUmV2aXNhciBsYSBlc3RydWN0dXJhIGRlbCBhcmNoaXZvIGdlb2dyw6FmaWNvIGRlIFVQWg0KDQpjYXQoIkVTVFJVQ1RVUkEgREVMIEFSQ0hJVk8gREUgVVBaXG4iKQ0KDQpnbGltcHNlKHVwel9zaHApDQoNCiMgSWRlbnRpZmljYXIgbG9zIGNhbXBvcyBkaXNwb25pYmxlcw0KDQpuYW1lcyh1cHpfc2hwKQ0KDQojIFJldmlzYXIgZWwgc2lzdGVtYSBkZSBjb29yZGVuYWRhcw0KDQpzdF9jcnModXB6X3NocCkNCg0KIyBDb25zdWx0YXIgbGEgY2FudGlkYWQgZGUgcG9sw61nb25vcw0KDQpucm93KHVwel9zaHApDQoNCiMgUmV2aXNhciBsb3MgcHJpbWVyb3MgcmVnaXN0cm9zDQoNCmhlYWQoc3RfZHJvcF9nZW9tZXRyeSh1cHpfc2hwKSwgNSkNCmBgYA0KDQpBaG9yYSByZWFsaXphbW9zIGxhIG1pc21hIHJldmlzacOzbiBwYXJhIGVsIGFyY2hpdm8gZ2VvZ3LDoWZpY28gZGUgbG9jYWxpZGFkZXMuDQoNCmBgYHtyIHJldmlzaW9uLWFyY2hpdm8tbG9jYWxpZGFkZXMsIGVjaG89VFJVRX0NCiMgUmV2aXNhciBsYSBlc3RydWN0dXJhIGRlbCBhcmNoaXZvIGRlIGxvY2FsaWRhZGVzDQoNCmNhdCgiRVNUUlVDVFVSQSBERUwgQVJDSElWTyBERSBMT0NBTElEQURFU1xuIikNCg0KZ2xpbXBzZShsb2NhbGlkYWRlc19zaHApDQoNCiMgSWRlbnRpZmljYXIgbG9zIGNhbXBvcyBkaXNwb25pYmxlcw0KDQpuYW1lcyhsb2NhbGlkYWRlc19zaHApDQoNCiMgUmV2aXNhciBlbCBzaXN0ZW1hIGRlIGNvb3JkZW5hZGFzDQoNCnN0X2Nycyhsb2NhbGlkYWRlc19zaHApDQoNCiMgQ29uc3VsdGFyIGxhIGNhbnRpZGFkIGRlIHBvbMOtZ29ub3MNCg0KbnJvdyhsb2NhbGlkYWRlc19zaHApDQoNCiMgUmV2aXNhciBsb3MgcHJpbWVyb3MgcmVnaXN0cm9zDQoNCmhlYWQoc3RfZHJvcF9nZW9tZXRyeShsb2NhbGlkYWRlc19zaHApLCA1KQ0KYGBgDQoNCiMjIyA2LjEuMS4gVmVyaWZpY2FjacOzbiB2aXN1YWwgZGUgbG9zIGFyY2hpdm9zIGdlb2dyw6FmaWNvcw0KDQpBbnRlcyBkZSBpbnRlZ3JhciBsYSBpbmZvcm1hY2nDs24gZXN0YWTDrXN0aWNhLCB0YW1iacOpbiBlcyBjb252ZW5pZW50ZSB2aXN1YWxpemFyIGxvcyBwb2zDrWdvbm9zIG9yaWdpbmFsZXMuIEVzdG8gcGVybWl0ZSBjb21wcm9iYXIgcXVlIGxhcyBnZW9tZXRyw61hcyBzZSBlbmN1ZW50cmFuIGNvcnJlY3RhbWVudGUgY2FyZ2FkYXMgeSBxdWUgY29ycmVzcG9uZGVuIGFsIHRlcnJpdG9yaW8gZGUgQm9nb3TDoS4NCg0KYGBge3IgdmlzdWFsaXphY2lvbi1iYXNlLXVweiwgZWNobz1UUlVFfQ0KIyBWaXN1YWxpemFjacOzbiBpbmljaWFsIGRlIGxvcyBwb2zDrWdvbm9zIGRlIGxhcyBVUFoNCg0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKA0KICAgIGRhdGEgPSB1cHpfc2hwLA0KICAgIGZpbGwgPSAiI0U5RTNFRCIsDQogICAgY29sb3IgPSBtb3JhZG8sDQogICAgbGluZXdpZHRoID0gMC4yNQ0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEaXZpc2nDs24gdGVycml0b3JpYWwgZGUgQm9nb3TDoSBwb3IgVVBaIiwNCiAgICBzdWJ0aXRsZSA9ICJSZXByZXNlbnRhY2nDs24gZGUgbG9zIHBvbMOtZ29ub3MgZ2VvZ3LDoWZpY29zIGRpc3BvbmlibGVzIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogYXJjaGl2byBnZW9ncsOhZmljbyBkZSBVUFogc3VtaW5pc3RyYWRvIHBhcmEgZWwgdGFsbGVyLiINCiAgKSArDQogIHRlbWFfY2xhc2UgKw0KICB0aGVtZSgNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkNCiAgKQ0KYGBgDQoNCiMjIyA2LjIuIEludGVncmFjacOzbiBkZSBsYSBpbmZvcm1hY2nDs24gZXN0YWTDrXN0aWNhIHkgZ2VvZ3LDoWZpY2ENCg0KVW5hIHZleiByZXZpc2FkYSBsYSBlc3RydWN0dXJhIGRlIGxvcyBhcmNoaXZvcyBnZW9ncsOhZmljb3MsIHNlIHByb2NlZGUgYSBpbnRlZ3JhciBsYSBpbmZvcm1hY2nDs24gZXN0YWTDrXN0aWNhIGRlIGxhcyBVUFogY29uIHN1cyByZXNwZWN0aXZvcyBwb2zDrWdvbm9zIHRlcnJpdG9yaWFsZXMuDQoNClBhcmEgcmVhbGl6YXIgZXN0YSBvcGVyYWNpw7NuIHNlIHV0aWxpemEgZWwgY2FtcG8gYHVwel9jb2RgLCBxdWUgZnVuY2lvbmEgY29tbyBpZGVudGlmaWNhZG9yIGNvbcO6biBlbnRyZSBhbWJhcyBmdWVudGVzLiBFc3RlIHByb2NlZGltaWVudG8gcGVybWl0ZSBpbmNvcnBvcmFyIGxvcyBpbmRpY2Fkb3JlcyBkZW1vZ3LDoWZpY29zLCBzb2Npb2Vjb27Ds21pY29zLCBkZSBpbmZyYWVzdHJ1Y3R1cmEgeSBkZSBzZWd1cmlkYWQgYSBjYWRhIHVuaWRhZCBnZW9ncsOhZmljYSwgY29uc2VydmFuZG8gbGEgZ2VvbWV0csOtYSBuZWNlc2FyaWEgcGFyYSBzdSByZXByZXNlbnRhY2nDs24gY2FydG9ncsOhZmljYS4NCg0KQW50ZXMgZGUgY29uc3RydWlyIGxvcyBtYXBhcyB0ZW3DoXRpY29zLCBzZSB2YWxpZGEgcXVlIGxhIHVuacOzbiBjb25zZXJ2ZSBsYSB0b3RhbGlkYWQgZGUgbG9zIHJlZ2lzdHJvcywgcXVlIG5vIGV4aXN0YW4gY8OzZGlnb3Mgc2luIGNvcnJlc3BvbmRlbmNpYSB5IHF1ZSBsYXMgdmFyaWFibGVzIGVzdGFkw61zdGljYXMgc2UgZW5jdWVudHJlbiBkaXNwb25pYmxlcyBkZXNwdcOpcyBkZSBsYSBpbnRlZ3JhY2nDs24uDQoNCkVzdGEgdmFsaWRhY2nDs24gZXMgaW1wb3J0YW50ZSBwb3JxdWUgY3VhbHF1aWVyIGluY29uc2lzdGVuY2lhIGVuIGxhIHJlbGFjacOzbiBlbnRyZSBsb3MgZGF0b3MgeSBsb3MgcG9sw61nb25vcyBwb2Ryw61hIGdlbmVyYXIgcmVwcmVzZW50YWNpb25lcyB0ZXJyaXRvcmlhbGVzIGluY29tcGxldGFzIG8gYXNpZ25hY2lvbmVzIGluY29ycmVjdGFzIGRlIGxvcyBpbmRpY2Fkb3Jlcy4NCg0KYGBge3IgaW50ZWdyYWNpb24tZGF0b3MtZ2VvZ3JhZmljb3MsIGVjaG89VFJVRX0NCiMgSW50ZWdyYXIgbGEgaW5mb3JtYWNpw7NuIGVzdGFkw61zdGljYSBjb24gbG9zIHBvbMOtZ29ub3MgZGUgbGFzIFVQWg0KDQp1cHpfbWFwYSA8LSB1cHpfc2hwICU+JQ0KICBsZWZ0X2pvaW4oDQogICAgdXB6ICU+JSBzZWxlY3QoLXVwel9ub21icmUpLA0KICAgIGJ5ID0gInVwel9jb2QiDQogICkNCg0KIyBWYWxpZGFyIGxhIGNhbnRpZGFkIGRlIHJlZ2lzdHJvcyB5IHBvbMOtZ29ub3MNCg0KY2F0KCJSRUdJU1RST1MgREUgTEEgQkFTRSBFU1RBRMONU1RJQ0E6IiwgbnJvdyh1cHopLCAiXG4iKQ0KY2F0KCJQT0zDjUdPTk9TIERFTCBBUkNISVZPIEdFT0dSw4FGSUNPOiIsIG5yb3codXB6X3NocCksICJcbiIpDQpjYXQoIlJFR0lTVFJPUyBERVNQVcOJUyBERSBMQSBVTknDk046IiwgbnJvdyh1cHpfbWFwYSksICJcbiIpDQoNCiMgSWRlbnRpZmljYXIgY8OzZGlnb3MgZGUgbGEgYmFzZSBlc3RhZMOtc3RpY2Egc2luIGdlb21ldHLDrWENCg0KdXB6X3Npbl9nZW9tZXRyaWEgPC0gdXB6ICU+JQ0KICBhbnRpX2pvaW4oDQogICAgc3RfZHJvcF9nZW9tZXRyeSh1cHpfc2hwKSwNCiAgICBieSA9ICJ1cHpfY29kIg0KICApDQoNCiMgSWRlbnRpZmljYXIgcG9sw61nb25vcyBzaW4gaW5mb3JtYWNpw7NuIGVzdGFkw61zdGljYQ0KDQpwb2xpZ29ub3Nfc2luX2RhdG9zIDwtIHN0X2Ryb3BfZ2VvbWV0cnkodXB6X3NocCkgJT4lDQogIGFudGlfam9pbigNCiAgICB1cHosDQogICAgYnkgPSAidXB6X2NvZCINCiAgKQ0KDQojIFJldmlzYXIgdmFsb3JlcyBmYWx0YW50ZXMgZW4gbGFzIHZhcmlhYmxlcyBlc3RhZMOtc3RpY2FzIGludGVncmFkYXMNCg0KZmFsdGFudGVzX2ludGVncmFjaW9uIDwtIHVwel9tYXBhICU+JQ0KICBzdF9kcm9wX2dlb21ldHJ5KCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBhY3Jvc3MoDQogICAgICBldmVyeXRoaW5nKCksDQogICAgICB+IHN1bShpcy5uYSguKSkNCiAgICApDQogICkgJT4lDQogIHBpdm90X2xvbmdlcigNCiAgICBjb2xzID0gZXZlcnl0aGluZygpLA0KICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwNCiAgICB2YWx1ZXNfdG8gPSAiVmFsb3Jlc19mYWx0YW50ZXMiDQogICkgJT4lDQogIGZpbHRlcihWYWxvcmVzX2ZhbHRhbnRlcyA+IDApDQoNCiMgUHJlc2VudGFyIHJlc3VsdGFkb3MgZGUgdmFsaWRhY2nDs24NCg0KY2F0KCJcbkPDk0RJR09TIFNJTiBHRU9NRVRSw41BOiIsIG5yb3codXB6X3Npbl9nZW9tZXRyaWEpLCAiXG4iKQ0KY2F0KCJQT0zDjUdPTk9TIFNJTiBEQVRPUzoiLCBucm93KHBvbGlnb25vc19zaW5fZGF0b3MpLCAiXG4iKQ0KY2F0KCJWQVJJQUJMRVMgQ09OIFZBTE9SRVMgRkFMVEFOVEVTOiIsIG5yb3coZmFsdGFudGVzX2ludGVncmFjaW9uKSwgIlxuIikNCg0KIyBDb25zdWx0YXIgbG9zIHByaW1lcm9zIHJlZ2lzdHJvcyBkZSBsYSBiYXNlIGludGVncmFkYQ0KDQpoZWFkKA0KICBzdF9kcm9wX2dlb21ldHJ5KHVwel9tYXBhKSAlPiUNCiAgICBzZWxlY3QoDQogICAgICB1cHpfY29kLA0KICAgICAgdXB6X25vbWJyZSwNCiAgICAgIHBvYmxhY2lvbiwNCiAgICAgIGNhc29zX3RvdGFsLA0KICAgICAgdGFzYV90b3RhbA0KICAgICksDQogIDEwDQopDQpgYGANCg0KIyMgNi4zLiBEaXN0cmlidWNpw7NuIHRlcnJpdG9yaWFsIGRlIGxvcyBkZWxpdG9zDQoNClVuYSB2ZXogaW50ZWdyYWRhIGxhIGluZm9ybWFjacOzbiBlc3RhZMOtc3RpY2EgeSBnZW9ncsOhZmljYSwgc2UgaW5pY2lhIGxhIHJlcHJlc2VudGFjacOzbiBlc3BhY2lhbCBkZSBsb3MgaW5kaWNhZG9yZXMgZGUgc2VndXJpZGFkLg0KDQpFbiBwcmltZXIgbHVnYXIsIHNlIGFuYWxpemEgbGEgZGlzdHJpYnVjacOzbiBkZSBsYSB0YXNhIHRvdGFsIGRlIGRlbGl0b3MgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMuIEVzdGUgaW5kaWNhZG9yIHBlcm1pdGUgY29tcGFyYXIgbGFzIFVQWiBjb25zaWRlcmFuZG8gc3UgcG9ibGFjacOzbiB5IGV2aXRhIGludGVycHJldGFyIGxvcyBjb250ZW9zIGFic29sdXRvcyBjb21vIHNpIGZ1ZXJhbiBkaXJlY3RhbWVudGUgZXF1aXZhbGVudGVzIGEgdW5hIG1heW9yIGludGVuc2lkYWQgZGVsaWN0aXZhLg0KDQpMYSByZXByZXNlbnRhY2nDs24gbWVkaWFudGUgdW4gbWFwYSBjb3JvcGzDqXRpY28gcGVybWl0ZSBpZGVudGlmaWNhciBkaWZlcmVuY2lhcyB0ZXJyaXRvcmlhbGVzIGVuIGxvcyBuaXZlbGVzIGRlIGxhIHRhc2EgeSByZWNvbm9jZXIgcG9zaWJsZXMgY29uY2VudHJhY2lvbmVzIGVzcGFjaWFsZXMuIFBhcmEgY29tcGxlbWVudGFyIGVzdGEgbGVjdHVyYSwgdGFtYmnDqW4gc2UgYW5hbGl6YXLDoSBsYSBkaXN0cmlidWNpw7NuIGRlbCBuw7ptZXJvIHRvdGFsIGRlIGNhc29zIGRlbnVuY2lhZG9zLg0KDQpFcyBpbXBvcnRhbnRlIHJlY29yZGFyIHF1ZSBsb3MgaW5kaWNhZG9yZXMgZGUgZGVsaXRvcyBjb3JyZXNwb25kZW4gYWwgcGVyaW9kbyBlbmVyby1qdWxpbyBkZSAyMDIzIHkgcmVwcmVzZW50YW4gZGVudW5jaWFzIHJlZ2lzdHJhZGFzLCBubyBuZWNlc2FyaWFtZW50ZSBsYSB0b3RhbGlkYWQgZGUgbG9zIGhlY2hvcyBvY3Vycmlkb3MuDQoNCmBgYHtyIG1hcGEtdGFzYS10b3RhbC1kZWxpdG9zLCBlY2hvPVRSVUV9DQojIE1hcGEgZGUgbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzDQoNCmdncGxvdCh1cHpfbWFwYSkgKw0KICBnZW9tX3NmKA0KICAgIGFlcyhmaWxsID0gdGFzYV90b3RhbCksDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIGxpbmV3aWR0aCA9IDAuMTUNCiAgKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKA0KICAgIGNvbG91cnMgPSBjKCIjRTlFM0VEIiwgIiNBOThEQkIiLCAiI0Q5MDA2QyIsICIjMzUxQTRGIiksDQogICAgbmFtZSA9ICJUYXNhIHBvclxuMTAuMDAwIGhhYml0YW50ZXMiLA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfbnVtYmVyKGFjY3VyYWN5ID0gMC4xKSwNCiAgICBuYS52YWx1ZSA9ICJncmV5ODUiDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gdGVycml0b3JpYWwgZGUgbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zIiwNCiAgICBzdWJ0aXRsZSA9ICJVUFogZGUgQm9nb3TDoSDCtyBFbmVybyBhIGp1bGlvIGRlIDIwMjMiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBlbGFib3JhY2nDs24gcHJvcGlhIGNvbiBpbmZvcm1hY2nDs24gZXN0YWTDrXN0aWNhIHkgZ2VvZ3LDoWZpY2Egc3VtaW5pc3RyYWRhIHBhcmEgZWwgdGFsbGVyLiINCiAgKSArDQogIHRlbWFfY2xhc2UgKw0KICB0aGVtZSgNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0Ig0KICApDQpgYGANCg0KIyMjIyBNYXBhIGRlIGNhc29zIHRvdGFsZXMgZGVudW5jaWFkb3MNCg0KYGBge3IgbWFwYS1jYXNvcy10b3RhbC1kZWxpdG9zLCBlY2hvPVRSVUV9DQojIE1hcGEgZGVsIG7Dum1lcm8gdG90YWwgZGUgY2Fzb3MgZGVudW5jaWFkb3MNCg0KZ2dwbG90KHVwel9tYXBhKSArDQogIGdlb21fc2YoDQogICAgYWVzKGZpbGwgPSBjYXNvc190b3RhbCksDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIGxpbmV3aWR0aCA9IDAuMTUNCiAgKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKA0KICAgIGNvbG91cnMgPSBjKCIjRTlFM0VEIiwgIiNBOThEQkIiLCAiI0Q5MDA2QyIsICIjMzUxQTRGIiksDQogICAgbmFtZSA9ICJDYXNvc1xuZGVudW5jaWFkb3MiLA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEoKSwNCiAgICBuYS52YWx1ZSA9ICJncmV5ODUiDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gdGVycml0b3JpYWwgZGUgbG9zIGNhc29zIGRlbnVuY2lhZG9zIiwNCiAgICBzdWJ0aXRsZSA9ICJVUFogZGUgQm9nb3TDoSDCtyBFbmVybyBhIGp1bGlvIGRlIDIwMjMiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBlbGFib3JhY2nDs24gcHJvcGlhIGNvbiBpbmZvcm1hY2nDs24gZXN0YWTDrXN0aWNhIHkgZ2VvZ3LDoWZpY2Egc3VtaW5pc3RyYWRhIHBhcmEgZWwgdGFsbGVyLiINCiAgKSArDQogIHRlbWFfY2xhc2UgKw0KICB0aGVtZSgNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0Ig0KICApDQpgYGANCg0KIyMjIDYuMy4xLiBFdmFsdWFjacOzbiBkZSBsYSBhc2ltZXRyw61hIHkgbG9zIHZhbG9yZXMgZXh0cmVtb3MNCg0KQW50ZXMgZGUgY29uc3RydWlyIGxhIHJlcHJlc2VudGFjacOzbiBjYXJ0b2dyw6FmaWNhIGRlZmluaXRpdmEsIHNlIHJldmlzw7MgbGEgZGlzdHJpYnVjacOzbiBkZSBsYSB0YXNhIHRvdGFsIGRlIGRlbGl0b3MgcGFyYSBpZGVudGlmaWNhciBwb3NpYmxlcyB2YWxvcmVzIGV4dHJlbW9zIHF1ZSBwdWRpZXJhbiBhZmVjdGFyIGxhIGludGVycHJldGFjacOzbiB2aXN1YWwuDQoNCkVzdGEgcmV2aXNpw7NuIHBlcm1pdGUgcmVjb25vY2VyIHF1ZSBsYXMgdGFzYXMgcHVlZGVuIHByZXNlbnRhciB2YWxvcmVzIGVsZXZhZG9zIGN1YW5kbyBlbCBuw7ptZXJvIGRlIGhhYml0YW50ZXMgZGUgdW5hIFVQWiBlcyByZWR1Y2lkby4gRW4gZXN0b3MgY2Fzb3MsIHVuYSBjYW50aWRhZCByZWxhdGl2YW1lbnRlIHBlcXVlw7FhIGRlIGRlbnVuY2lhcyBwdWVkZSBwcm9kdWNpciB0YXNhcyBjb25zaWRlcmFibGVtZW50ZSBhbHRhcy4NCg0KUG9yIGVzdGEgcmF6w7NuLCBzZSBjb25zaWRlcmEgbmVjZXNhcmlvIGRpZmVyZW5jaWFyIGVudHJlIGVsIHZhbG9yIG51bcOpcmljbyBkZSBsYSB0YXNhIHkgc3UgZXN0YWJpbGlkYWQgY29tbyBpbmRpY2Fkb3IgY29tcGFyYXRpdm8uIExvcyB2YWxvcmVzIG9yaWdpbmFsZXMgc2UgY29uc2VydmFyw6FuLCBwZXJvIHNlIGV2YWx1YXLDoW4gYWx0ZXJuYXRpdmFzIGRlIHJlcHJlc2VudGFjacOzbiBxdWUgcGVybWl0YW4gdmlzdWFsaXphciBtZWpvciBsYXMgZGlmZXJlbmNpYXMgZW50cmUgbGFzIHVuaWRhZGVzIHRlcnJpdG9yaWFsZXMuDQoNCg0KYGBge3IgZGlhZ25vc3RpY28tdmFsb3Jlcy1leHRyZW1vcy10YXNhLCBlY2hvPVRSVUV9DQojIENyZWFyIHZlY3RvciBjb24gbG9zIHZhbG9yZXMgdsOhbGlkb3MNCnRhc2FzX3ZhbGlkYXMgPC0gdXB6JHRhc2FfdG90YWxbDQogICFpcy5uYSh1cHokdGFzYV90b3RhbCkgJiBpcy5maW5pdGUodXB6JHRhc2FfdG90YWwpDQpdDQoNCiMgQ2FsY3VsYXIgYXNpbWV0csOtYSBtZWRpYW50ZSBlbCB0ZXJjZXIgbW9tZW50byBlc3RhbmRhcml6YWRvDQphc2ltZXRyaWEgPC0gbWVhbigNCiAgKHRhc2FzX3ZhbGlkYXMgLSBtZWFuKHRhc2FzX3ZhbGlkYXMpKV4zDQopIC8gc2QodGFzYXNfdmFsaWRhcyleMw0KDQojIFJlc3VtZW4gZGUgbGEgZGlzdHJpYnVjacOzbiBkZSBsYSB0YXNhIHRvdGFsDQoNCnVweiAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE1pbmltbyA9IG1pbih0YXNhX3RvdGFsLCBuYS5ybSA9IFRSVUUpLA0KICAgIFExID0gcXVhbnRpbGUodGFzYV90b3RhbCwgMC4yNSwgbmEucm0gPSBUUlVFKSwNCiAgICBNZWRpYW5hID0gbWVkaWFuKHRhc2FfdG90YWwsIG5hLnJtID0gVFJVRSksDQogICAgUTMgPSBxdWFudGlsZSh0YXNhX3RvdGFsLCAwLjc1LCBuYS5ybSA9IFRSVUUpLA0KICAgIFA5MCA9IHF1YW50aWxlKHRhc2FfdG90YWwsIDAuOTAsIG5hLnJtID0gVFJVRSksDQogICAgUDk1ID0gcXVhbnRpbGUodGFzYV90b3RhbCwgMC45NSwgbmEucm0gPSBUUlVFKSwNCiAgICBNYXhpbW8gPSBtYXgodGFzYV90b3RhbCwgbmEucm0gPSBUUlVFKQ0KICApDQoNCiMgUHJlc2VudGFyIGVsIGNvZWZpY2llbnRlIGRlIGFzaW1ldHLDrWENCg0KY2F0KA0KICAiQ29lZmljaWVudGUgZGUgYXNpbWV0csOtYToiLA0KICByb3VuZChhc2ltZXRyaWEsIDMpLA0KICAiXG4iDQopDQoNCiMgSWRlbnRpZmljYXIgbGFzIDEwIFVQWiBjb24gbWF5b3JlcyB0YXNhcw0KDQp1cHogJT4lDQogIGFycmFuZ2UoZGVzYyh0YXNhX3RvdGFsKSkgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIHBvYmxhY2lvbiwNCiAgICBjYXNvc190b3RhbCwNCiAgICB0YXNhX3RvdGFsDQogICkgJT4lDQogIHNsaWNlX2hlYWQobiA9IDEwKQ0KYGBgDQoNCiMjIyA2LjMuMi4gUmVwcmVzZW50YWNpw7NuIGRlIGxhIHRhc2EgbWVkaWFudGUgZXNjYWxhIGxvZ2Fyw610bWljYQ0KDQpEZWJpZG8gYSBsYSBhc2ltZXRyw61hIGlkZW50aWZpY2FkYSBlbiBsYSBkaXN0cmlidWNpw7NuIGRlIGxhIHRhc2EgdG90YWwgZGUgZGVsaXRvcywgc2UgcHJvcG9uZSB1bmEgcmVwcmVzZW50YWNpw7NuIGNhcnRvZ3LDoWZpY2EgY29tcGxlbWVudGFyaWEgbWVkaWFudGUgdW5hIGVzY2FsYSBsb2dhcsOtdG1pY2EuDQoNCkVzdGEgdHJhbnNmb3JtYWNpw7NuIHBlcm1pdGUgcmVkdWNpciBlbCBlZmVjdG8gdmlzdWFsIGRlIGxvcyB2YWxvcmVzIGV4dHJlbW9zIHkgbWVqb3JhciBsYSBkaWZlcmVuY2lhY2nDs24gZGUgbGFzIFVQWiBxdWUgcHJlc2VudGFuIHRhc2FzIGJhamFzIHkgbWVkaWFzLiBFcyBpbXBvcnRhbnRlIGFjbGFyYXIgcXVlIGxhIHRyYW5zZm9ybWFjacOzbiBzZSBhcGxpY2EgZXhjbHVzaXZhbWVudGUgYSBsYSBlc2NhbGEgZGUgcmVwcmVzZW50YWNpw7NuIHkgbm8gbW9kaWZpY2EgbG9zIHZhbG9yZXMgb3JpZ2luYWxlcyB1dGlsaXphZG9zIGVuIGVsIGFuw6FsaXNpcyBlc3RhZMOtc3RpY28uDQoNCkRlIGVzdGEgbWFuZXJhLCBzZSBidXNjYSBmYWNpbGl0YXIgbGEgY29tcGFyYWNpw7NuIHRlcnJpdG9yaWFsIHNpbiBlbGltaW5hciBvYnNlcnZhY2lvbmVzIG5pIG9jdWx0YXIgbGEgZXhpc3RlbmNpYSBkZSB2YWxvcmVzIGVsZXZhZG9zLg0KDQpgYGB7ciByZXZpc2lvbi1kZW5vbWluYWRvcmVzLXBlcXVlbm9zLCBlY2hvPVRSVUV9DQojIElkZW50aWZpY2FyIFVQWiBjb24gcG9ibGFjaW9uZXMgbcOhcyBwZXF1ZcOxYXMNCg0KdXB6ICU+JQ0KICBhcnJhbmdlKHBvYmxhY2lvbikgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIHBvYmxhY2lvbiwNCiAgICBjYXNvc190b3RhbCwNCiAgICB0YXNhX3RvdGFsDQogICkgJT4lDQogIHNsaWNlX2hlYWQobiA9IDE1KQ0KYGBgDQoNCiMjIyA2LjMuMy4gQ2xhc2lmaWNhY2nDs24gdGVycml0b3JpYWwgbWVkaWFudGUgcXVpbnRpbGVzDQoNCkNvbW8gYWx0ZXJuYXRpdmEgYSBsYSByZXByZXNlbnRhY2nDs24gbWVkaWFudGUgZXNjYWxhcyBjb250aW51YXMsIHNlIGNvbnN0cnV5ZSB1biBtYXBhIHRlbcOhdGljbyBiYXNhZG8gZW4gcXVpbnRpbGVzLiBFc3RhIGNsYXNpZmljYWNpw7NuIG9yZ2FuaXphIGxhcyBVUFogZW4gY2luY28gZ3J1cG9zIGRlIGFjdWVyZG8gY29uIGxhIHBvc2ljacOzbiByZWxhdGl2YSBkZSBzdXMgdGFzYXMgZGUgZGVsaXRvcy4NCg0KTGEgdXRpbGl6YWNpw7NuIGRlIHF1aW50aWxlcyBmYWNpbGl0YSBsYSBpZGVudGlmaWNhY2nDs24gZGUgbGFzIHVuaWRhZGVzIHRlcnJpdG9yaWFsZXMgcXVlIHByZXNlbnRhbiBuaXZlbGVzIHJlbGF0aXZhbWVudGUgYmFqb3MsIGludGVybWVkaW9zIG8gYWx0b3MgZGVudHJvIGRlbCBjb25qdW50byBhbmFsaXphZG8uDQoNCkEgZGlmZXJlbmNpYSBkZSBsYSB0cmFuc2Zvcm1hY2nDs24gbG9nYXLDrXRtaWNhLCBlc3RhIGNsYXNpZmljYWNpw7NuIG5vIG1vZGlmaWNhIGxhIGVzY2FsYSBudW3DqXJpY2EgZGUgbG9zIGRhdG9zLCBzaW5vIHF1ZSBhZ3J1cGEgbGFzIG9ic2VydmFjaW9uZXMgZW4gY2F0ZWdvcsOtYXMuIFBvciB0YW50bywgZGViZSBpbnRlcnByZXRhcnNlIGNvbW8gdW5hIGhlcnJhbWllbnRhIGRlIGNvbXBhcmFjacOzbiByZWxhdGl2YSB5IG5vIGNvbW8gdW5hIGNsYXNpZmljYWNpw7NuIGRlIHJpZXNnbyBhYnNvbHV0by4NCg0KTG9zIHZhbG9yZXMgb3JpZ2luYWxlcyBkZSBsYXMgdGFzYXMgc2UgY29uc2VydmFuIHBhcmEgbG9zIGFuw6FsaXNpcyBlc3RhZMOtc3RpY29zIHkgcGFyYSBsYSBpZGVudGlmaWNhY2nDs24gZGUgcG9zaWJsZXMgdmFsb3JlcyBleHRyZW1vcy4NCg0KYGBge3IgbWFwYS10YXNhLWRlbGl0b3MtcXVpbnRpbGVzLCBlY2hvPVRSVUV9DQojIENsYXNpZmljYXIgbGFzIFVQWiBlbiBjaW5jbyBncnVwb3Mgc2Vnw7puIHN1IHRhc2EgdG90YWwNCg0KdXB6X21hcGEgPC0gdXB6X21hcGEgJT4lDQogIG11dGF0ZSgNCiAgICBxdWludGlsX3Rhc2EgPSBudGlsZSh0YXNhX3RvdGFsLCA1KSwNCiAgICBxdWludGlsX3Rhc2EgPSBmYWN0b3IoDQogICAgICBxdWludGlsX3Rhc2EsDQogICAgICBsZXZlbHMgPSAxOjUsDQogICAgICBsYWJlbHMgPSBjKA0KICAgICAgICAiUTEgLSBNdXkgYmFqbyIsDQogICAgICAgICJRMiAtIEJham8iLA0KICAgICAgICAiUTMgLSBNZWRpbyIsDQogICAgICAgICJRNCAtIEFsdG8iLA0KICAgICAgICAiUTUgLSBNdXkgYWx0byINCiAgICAgICkNCiAgICApDQogICkNCg0KIyBDb25zdHJ1aXIgbWFwYSBwb3IgcXVpbnRpbGVzDQoNCmdncGxvdCh1cHpfbWFwYSkgKw0KICBnZW9tX3NmKA0KICAgIGFlcyhmaWxsID0gcXVpbnRpbF90YXNhKSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgbGluZXdpZHRoID0gMC4xNQ0KICApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICJRMSAtIE11eSBiYWpvIiA9ICIjRTlFM0VEIiwNCiAgICAgICJRMiAtIEJham8iID0gIiNDOEI1RDMiLA0KICAgICAgIlEzIC0gTWVkaW8iID0gIiNBOThEQkIiLA0KICAgICAgIlE0IC0gQWx0byIgPSAiI0Q5MDA2QyIsDQogICAgICAiUTUgLSBNdXkgYWx0byIgPSAiIzM1MUE0RiINCiAgICApLA0KICAgIG5hbWUgPSAiUXVpbnRpbGVzIiwNCiAgICBuYS52YWx1ZSA9ICJncmV5ODUiDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkNsYXNpZmljYWNpw7NuIHRlcnJpdG9yaWFsIGRlIGxhIHRhc2EgZGUgZGVsaXRvcyIsDQogICAgc3VidGl0bGUgPSAiVVBaIGFncnVwYWRhcyBlbiBjaW5jbyBxdWludGlsZXMgwrcgRW5lcm8gYSBqdWxpbyBkZSAyMDIzIiwNCiAgICBjYXB0aW9uID0gIkxvcyBxdWludGlsZXMgcmVwcmVzZW50YW4gcG9zaWNpb25lcyByZWxhdGl2YXMgZGVudHJvIGRlIGxhcyBVUFogYW5hbGl6YWRhcy4gTm8gY29uc3RpdHV5ZW4gY2F0ZWdvcsOtYXMgZGUgcmllc2dvIGFic29sdXRvLiINCiAgKSArDQogIHRlbWFfY2xhc2UgKw0KICB0aGVtZSgNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0Ig0KICApDQpgYGANCg0KYGBge3IgcmVzdW1lbi1xdWludGlsZXMtdGFzYSwgZWNobz1UUlVFfQ0KdXB6X21hcGEgJT4lDQogIHN0X2Ryb3BfZ2VvbWV0cnkoKSAlPiUNCiAgZ3JvdXBfYnkocXVpbnRpbF90YXNhKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE51bWVyb19VUFogPSBuKCksDQogICAgVGFzYV9taW5pbWEgPSBtaW4odGFzYV90b3RhbCwgbmEucm0gPSBUUlVFKSwNCiAgICBUYXNhX21lZGlhbmEgPSBtZWRpYW4odGFzYV90b3RhbCwgbmEucm0gPSBUUlVFKSwNCiAgICBUYXNhX21heGltYSA9IG1heCh0YXNhX3RvdGFsLCBuYS5ybSA9IFRSVUUpLA0KICAgIFBvYmxhY2lvbl90b3RhbCA9IHN1bShwb2JsYWNpb24sIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQpgYGANCg0KIyMjIDYuMy40LiBFdmFsdWFjacOzbiBkZSBsYXMgdGFzYXMgZW4gVVBaIGNvbiBwb2JsYWNpb25lcyBwZXF1ZcOxYXMNCg0KQW50ZXMgZGUgaW50ZXJwcmV0YXIgbG9zIG1hcGFzIGNvbW8gdW5hIGRpc3RyaWJ1Y2nDs24gdGVycml0b3JpYWwgZGUgaW5zZWd1cmlkYWQsIGRlYmVtb3MgcmV2aXNhciBlbCB0YW1hw7FvIGRlIGxhIHBvYmxhY2nDs24gcXVlIHNpcnZlIGNvbW8gZGVub21pbmFkb3IgZGUgbGFzIHRhc2FzLg0KDQpgYGB7ciByZXZpc2lvbi1lc3RhYmlsaWRhZC10YXNhcywgZWNobz1UUlVFfQ0KIyBJZGVudGlmaWNhciBsYXMgMTUgVVBaIGNvbiBtZW5vciBwb2JsYWNpw7NuDQoNCnVweiAlPiUNCiAgYXJyYW5nZShwb2JsYWNpb24pICU+JQ0KICBzZWxlY3QoDQogICAgdXB6X25vbWJyZSwNCiAgICBwb2JsYWNpb24sDQogICAgY2Fzb3NfdG90YWwsDQogICAgdGFzYV90b3RhbA0KICApICU+JQ0KICBzbGljZV9oZWFkKG4gPSAxNSkNCg0KIyBSZWxhY2nDs24gZW50cmUgcG9ibGFjacOzbiB5IHRhc2EgdG90YWwNCg0KZ2dwbG90KHVweiwgYWVzKHggPSBwb2JsYWNpb24sIHkgPSB0YXNhX3RvdGFsKSkgKw0KICBnZW9tX3BvaW50KA0KICAgIGNvbG9yID0gIiNEOTAwNkMiLA0KICAgIGFscGhhID0gMC43NSwNCiAgICBzaXplID0gMi41DQogICkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9jb21tYSgpDQogICkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9jb21tYSgpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBvYmxhY2nDs24geSB0YXNhIHRvdGFsIGRlIGRlbGl0b3MgcG9yIFVQWiIsDQogICAgc3VidGl0bGUgPSAiRXZhbHVhY2nDs24gZGUgbGEgaW5mbHVlbmNpYSBkZWwgdGFtYcOxbyBwb2JsYWNpb25hbCIsDQogICAgeCA9ICJQb2JsYWNpw7NuIiwNCiAgICB5ID0gIlRhc2EgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMiDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KIyMgNi40LiBNYXBhIGludGVyYWN0aXZvIGRlIGxhIGRpc3RyaWJ1Y2nDs24gdGVycml0b3JpYWwgZGUgbG9zIGRlbGl0b3MNCg0KQ29tbyBjb21wbGVtZW50byBhIGxhcyByZXByZXNlbnRhY2lvbmVzIGNhcnRvZ3LDoWZpY2FzIGVzdMOhdGljYXMsIHNlIGNvbnN0cnV5ZSB1biBtYXBhIGludGVyYWN0aXZvIG1lZGlhbnRlIGxhIGxpYnJlcsOtYSBMZWFmbGV0LiBFc3RhIGhlcnJhbWllbnRhIHBlcm1pdGUgZXhwbG9yYXIgbGFzIHVuaWRhZGVzIHRlcnJpdG9yaWFsZXMgY29uIG1heW9yIGRldGFsbGUgeSBjb25zdWx0YXIgaW5mb3JtYWNpw7NuIGVzcGVjw61maWNhIGRlIGNhZGEgVVBaLg0KDQpMYSB2aXN1YWxpemFjacOzbiB1dGlsaXphIGxhIGNsYXNpZmljYWNpw7NuIHBvciBxdWludGlsZXMgZGUgbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zLCBjb25zZXJ2YW5kbyBsYSBtaXNtYSBjYXRlZ29yaXphY2nDs24gZGVsIG1hcGEgZXN0w6F0aWNvLiBBbCBzZWxlY2Npb25hciBvIHViaWNhciBlbCBjdXJzb3Igc29icmUgY2FkYSBwb2zDrWdvbm8sIGVzIHBvc2libGUgY29uc3VsdGFyIGVsIG5vbWJyZSBkZSBsYSBVUFosIHN1IHBvYmxhY2nDs24sIGVsIG7Dum1lcm8gZGUgY2Fzb3MgZGVudW5jaWFkb3MgeSBsYSB0YXNhIHJlZ2lzdHJhZGEgZHVyYW50ZSBlbCBwZXJpb2RvIGFuYWxpemFkby4NCg0KRXN0YSByZXByZXNlbnRhY2nDs24gZmFjaWxpdGEgbGEgZXhwbG9yYWNpw7NuIGluZGl2aWR1YWwgZGUgbG9zIHRlcnJpdG9yaW9zIHkgcGVybWl0ZSBjb250cmFzdGFyIGxvcyB2YWxvcmVzIGFic29sdXRvcyBjb24gbGFzIHRhc2FzIHJlbGF0aXZhcywgc2luIHBlcmRlciBkZSB2aXN0YSBsYXMgbGltaXRhY2lvbmVzIGFzb2NpYWRhcyBhbCB0YW1hw7FvIHBvYmxhY2lvbmFsIGRlIGFsZ3VuYXMgVVBaLg0KDQpgYGB7ciBtYXBhLWludGVyYWN0aXZvLWRlbGl0b3MsIGVjaG89VFJVRX0NCiMgRGVmaW5pciBsYSBwYWxldGEgZGUgY29sb3JlcyBwYXJhIGxvcyBxdWludGlsZXMNCg0KcGFsZXRhX3F1aW50aWxlcyA8LSBjb2xvckZhY3RvcigNCiAgcGFsZXR0ZSA9IGMoDQogICAgIiNFOUUzRUQiLA0KICAgICIjQzhCNUQzIiwNCiAgICAiI0E5OERCQiIsDQogICAgIiNEOTAwNkMiLA0KICAgICIjMzUxQTRGIg0KICApLA0KICBkb21haW4gPSBsZXZlbHModXB6X21hcGEkcXVpbnRpbF90YXNhKSwNCiAgbmEuY29sb3IgPSAiZ3JleTg1Ig0KKQ0KDQojIENvbnN0cnVpciBldGlxdWV0YXMgZGUgbGFzIFVQWg0KDQpldGlxdWV0YXNfdXB6IDwtIHBhc3RlMCgNCiAgIjxzdHJvbmc+VVBaOiA8L3N0cm9uZz4iLA0KICB1cHpfbWFwYSR1cHpfbm9tYnJlLA0KICAiPGJyPjxzdHJvbmc+UG9ibGFjacOzbjogPC9zdHJvbmc+IiwNCiAgc2NhbGVzOjpjb21tYSh1cHpfbWFwYSRwb2JsYWNpb24pLA0KICAiPGJyPjxzdHJvbmc+Q2Fzb3MgZGVudW5jaWFkb3M6IDwvc3Ryb25nPiIsDQogIHNjYWxlczo6Y29tbWEodXB6X21hcGEkY2Fzb3NfdG90YWwpLA0KICAiPGJyPjxzdHJvbmc+VGFzYSBwb3IgMTAuMDAwIGhhYml0YW50ZXM6IDwvc3Ryb25nPiIsDQogIHNjYWxlczo6bnVtYmVyKHVwel9tYXBhJHRhc2FfdG90YWwsIGFjY3VyYWN5ID0gMC4xKSwNCiAgIjxicj48c3Ryb25nPkNsYXNpZmljYWNpw7NuOiA8L3N0cm9uZz4iLA0KICB1cHpfbWFwYSRxdWludGlsX3Rhc2ENCikNCg0KIyBDcmVhciBtYXBhIGludGVyYWN0aXZvDQoNCmxlYWZsZXQodXB6X21hcGEpICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKA0KICAgIHByb3ZpZGVycyRPcGVuU3RyZWV0TWFwLk1hcG5paw0KICApICU+JQ0KICBhZGRQb2x5Z29ucygNCiAgICBmaWxsQ29sb3IgPSB+cGFsZXRhX3F1aW50aWxlcyhxdWludGlsX3Rhc2EpLA0KICAgIGZpbGxPcGFjaXR5ID0gMC43NSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgd2VpZ2h0ID0gMSwNCiAgICBvcGFjaXR5ID0gMSwNCiAgICBsYWJlbCA9IGxhcHBseShldGlxdWV0YXNfdXB6LCBodG1sdG9vbHM6OkhUTUwpLA0KICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKA0KICAgICAgd2VpZ2h0ID0gMywNCiAgICAgIGNvbG9yID0gIiNEOTAwNkMiLA0KICAgICAgZmlsbE9wYWNpdHkgPSAwLjksDQogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFDQogICAgKQ0KICApICU+JQ0KICBhZGRMZWdlbmQoDQogICAgcG9zaXRpb24gPSAiYm90dG9tcmlnaHQiLA0KICAgIHBhbCA9IHBhbGV0YV9xdWludGlsZXMsDQogICAgdmFsdWVzID0gfnF1aW50aWxfdGFzYSwNCiAgICB0aXRsZSA9ICJUYXNhIGRlIGRlbGl0b3MiLA0KICAgIG9wYWNpdHkgPSAwLjgNCiAgKQ0KYGBgDQoNCiMjIDYuNS4gQ29tcGFyYWNpw7NuIGRlIGxhcyByZXByZXNlbnRhY2lvbmVzIGNhcnRvZ3LDoWZpY2FzDQoNCkxhcyByZXByZXNlbnRhY2lvbmVzIGNhcnRvZ3LDoWZpY2FzIGRlc2Fycm9sbGFkYXMgcGVybWl0ZW4gb2JzZXJ2YXIgbGEgZGlzdHJpYnVjacOzbiB0ZXJyaXRvcmlhbCBkZSBsb3MgZGVsaXRvcyBkZXNkZSBkaWZlcmVudGVzIHBlcnNwZWN0aXZhcy4NCg0KTGEgZXNjYWxhIGNvbnRpbnVhIGNvbnNlcnZhIGxhIG1hZ25pdHVkIG9yaWdpbmFsIGRlIGxhcyB0YXNhcywgYXVucXVlIHB1ZWRlIHZlcnNlIGNvbmRpY2lvbmFkYSBwb3IgbGEgcHJlc2VuY2lhIGRlIHZhbG9yZXMgZXh0cmVtb3MuIExhIGVzY2FsYSBsb2dhcsOtdG1pY2EgZmFjaWxpdGEgbGEgZGlmZXJlbmNpYWNpw7NuIHZpc3VhbCBkZSBsb3MgdmFsb3JlcyBiYWpvcyBlIGludGVybWVkaW9zLCBtaWVudHJhcyBxdWUgbGEgY2xhc2lmaWNhY2nDs24gcG9yIHF1aW50aWxlcyBwZXJtaXRlIGNvbXBhcmFyIGxhIHBvc2ljacOzbiByZWxhdGl2YSBkZSBjYWRhIFVQWiBkZW50cm8gZGVsIGNvbmp1bnRvIGFuYWxpemFkby4NCg0KRXN0YXMgYWx0ZXJuYXRpdmFzIG5vIHNvbiBleGNsdXllbnRlcywgeWEgcXVlIHJlc3BvbmRlbiBhIG9iamV0aXZvcyBkZSB2aXN1YWxpemFjacOzbiBkaWZlcmVudGVzLiBQb3IgZXN0YSByYXrDs24sIHN1IGludGVycHJldGFjacOzbiBkZWJlIGNvbnNpZGVyYXIgdGFudG8gbGEgZXNjYWxhIHV0aWxpemFkYSBjb21vIGxhcyBjYXJhY3RlcsOtc3RpY2FzIGRlIGxhIHBvYmxhY2nDs24gZGUgY2FkYSB1bmlkYWQgdGVycml0b3JpYWwuDQoNCkVuIHBhcnRpY3VsYXIsIGxhcyB0YXNhcyBjYWxjdWxhZGFzIHNvYnJlIHBvYmxhY2lvbmVzIHBlcXVlw7FhcyByZXF1aWVyZW4gcHJlY2F1Y2nDs24sIGRlYmlkbyBhIHF1ZSBwb2NvcyBjYXNvcyBwdWVkZW4gZ2VuZXJhciB2YXJpYWNpb25lcyBpbXBvcnRhbnRlcyBlbiBlbCBpbmRpY2Fkb3IuIFBvciB0YW50bywgbG9zIG1hcGFzIGRlYmVuIGludGVycHJldGFyc2UgY29tbyB1bmEgZXhwbG9yYWNpw7NuIGRlIGxhcyBkZW51bmNpYXMgcmVnaXN0cmFkYXMgeSBubyBjb21vIHVuYSBtZWRpY2nDs24gZGVmaW5pdGl2YSBkZSBsYSBpbnNlZ3VyaWRhZCByZWFsIGRlIGNhZGEgdGVycml0b3Jpby4NCg0KIyMgNi41LiBEaXN0cmlidWNpw7NuIHRlcnJpdG9yaWFsIGRlIGxhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHkgbGFzIGNvbmRpY2lvbmVzIGRlbCBlbnRvcm5vDQoNCkFkZW3DoXMgZGUgbG9zIHJlZ2lzdHJvcyBkZSBkZWxpdG9zIGRlbnVuY2lhZG9zLCBlbCBhbsOhbGlzaXMgaW5jb3Jwb3JhIHZhcmlhYmxlcyByZWxhY2lvbmFkYXMgY29uIGxhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHkgbGFzIGNhcmFjdGVyw61zdGljYXMgZGVsIGVudG9ybm8gdXJiYW5vLg0KDQpFc3RhcyBkaW1lbnNpb25lcyBwZXJtaXRlbiBhbXBsaWFyIGxhIGNvbXByZW5zacOzbiBkZWwgZmVuw7NtZW5vLCBjb25zaWRlcmFuZG8gcXVlIGxhIGV4cGVyaWVuY2lhIGRlIGluc2VndXJpZGFkIGRlIGxvcyBoYWJpdGFudGVzIG5vIG5lY2VzYXJpYW1lbnRlIGNvaW5jaWRlIGNvbiBsYSBjYW50aWRhZCBkZSBkZW51bmNpYXMgcmVnaXN0cmFkYXMgZW4gY2FkYSB0ZXJyaXRvcmlvLg0KDQpFbiBlc3RhIHNlY2Npw7NuIHNlIGV4cGxvcmEgbGEgZGlzdHJpYnVjacOzbiBnZW9ncsOhZmljYSBkZSBsYSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCwgbGEgY2VyY2Fuw61hIGEgZGV0ZXJtaW5hZG9zIGVsZW1lbnRvcyBkZWwgZW50b3JubyB5IGxhIGFjY2VzaWJpbGlkYWQgYSBsb3MgQ0FJIGRlIHBvbGljw61hLiBFbCBwcm9ww7NzaXRvIGVzIGlkZW50aWZpY2FyIGRpZmVyZW5jaWFzIHRlcnJpdG9yaWFsZXMgeSBjb250cmFzdGFybGFzIGNvbiBsb3MgaW5kaWNhZG9yZXMgZGUgZGVsaXRvcyBhbmFsaXphZG9zIGFudGVyaW9ybWVudGUuDQoNCmBgYHtyIG1hcGEtcGVyY2VwY2lvbi1pbnNlZ3VyaWRhZCwgZWNobz1UUlVFfQ0KIyBNYXBhIGRlIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkDQoNCmdncGxvdCh1cHpfbWFwYSkgKw0KICBnZW9tX3NmKA0KICAgIGFlcyhmaWxsID0gcGN0X3BlcmNpYmVfaW5zZWd1cmlkYWQpLA0KICAgIGNvbG9yID0gIndoaXRlIiwNCiAgICBsaW5ld2lkdGggPSAwLjE1DQogICkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bigNCiAgICBjb2xvdXJzID0gYygiI0U5RTNFRCIsICIjQTk4REJCIiwgIiNEOTAwNkMiLCAiIzM1MUE0RiIpLA0KICAgIG5hbWUgPSAiUGVyY2VwY2nDs25cbiglKSIsDQogICAgbmEudmFsdWUgPSAiZ3JleTg1Ig0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJQZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCBlbiBlbCBlbnRvcm5vIGRlIGxhcyBVUFoiLA0KICAgIHN1YnRpdGxlID0gIlBvcmNlbnRhamUgcmVwb3J0YWRvIGVuIGxhIEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byAyMDIxIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvIERBTkUgMjAyMS4gQWxndW5hcyBVUFogY29tcGFydGVuIGVzdGltYWNpb25lcyBhZ3J1cGFkYXMuIg0KICApICsNCiAgdGVtYV9jbGFzZSArDQogIHRoZW1lKA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiDQogICkNCmBgYA0KDQojIyMgNi41LjIuIENvbmRpY2lvbmVzIGRlbCBlbnRvcm5vIHVyYmFubw0KDQpMYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZWwgZW50b3JubyBwdWVkZW4gYXBvcnRhciBpbmZvcm1hY2nDs24gYWRpY2lvbmFsIHBhcmEgY29tcHJlbmRlciBsYXMgZGlmZXJlbmNpYXMgdGVycml0b3JpYWxlcyByZWxhY2lvbmFkYXMgY29uIGxhIHNlZ3VyaWRhZC4NCg0KUGFyYSBlc3RlIGFuw6FsaXNpcyBzZSBjb25zaWRlcmFuIGRvcyBpbmRpY2Fkb3JlcyBkZSBsYSBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG86IGVsIHBvcmNlbnRhamUgZGUgdml2aWVuZGFzIGFmZWN0YWRhcyBwb3IgbGEgY2VyY2Fuw61hIGEgbG90ZXMgYmFsZMOtb3MgbyBzaXRpb3Mgb3NjdXJvcyB5IGVsIHBvcmNlbnRhamUgZGUgdml2aWVuZGFzIGFmZWN0YWRhcyBwb3IgbGEgY2VyY2Fuw61hIGEgZXhwZW5kaW9zIGRlIGRyb2dhLg0KDQpMYSByZXByZXNlbnRhY2nDs24gZ2VvZ3LDoWZpY2EgZGUgZXN0YXMgdmFyaWFibGVzIHBlcm1pdGUgZXhwbG9yYXIgY8OzbW8gc2UgZGlzdHJpYnV5ZW4gZGljaGFzIGNvbmRpY2lvbmVzIGVudHJlIGxhcyBVUFogeSBwb3N0ZXJpb3JtZW50ZSBjb250cmFzdGFybGFzIGNvbiBsYXMgdGFzYXMgZGUgZGVsaXRvcyBkZW51bmNpYWRvcy4NCg0KRXMgaW1wb3J0YW50ZSBzZcOxYWxhciBxdWUgZXN0b3MgaW5kaWNhZG9yZXMgY29ycmVzcG9uZGVuIGEgcGVyY2VwY2lvbmVzIG8gY29uZGljaW9uZXMgcmVwb3J0YWRhcyBwb3IgbG9zIGhvZ2FyZXMgZW5jdWVzdGFkb3MuIFBvciB0YW50bywgbm8gZGViZW4gaW50ZXJwcmV0YXJzZSBjb21vIGV2aWRlbmNpYSBkaXJlY3RhIGRlIHF1ZSBlc3RvcyBlbGVtZW50b3Mgb2Nhc2lvbmVuIG1heW9yZXMgbml2ZWxlcyBkZSBkZWxpbmN1ZW5jaWEuDQoNCmBgYHtyIG1hcGEtbG90ZXMtb3NjdXJvcywgZWNobz1UUlVFfQ0KZ2dwbG90KHVwel9tYXBhKSArDQogIGdlb21fc2YoDQogICAgYWVzKGZpbGwgPSBwY3RfY2VyY2FfbG90ZXNfb3NjdXJvcyksDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIGxpbmV3aWR0aCA9IDAuMTUNCiAgKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKA0KICAgIGNvbG91cnMgPSBjKCIjRTlFM0VEIiwgIiNBOThEQkIiLCAiI0Q5MDA2QyIsICIjMzUxQTRGIiksDQogICAgbmFtZSA9ICJWaXZpZW5kYXNcbmFmZWN0YWRhcyAoJSkiLA0KICAgIG5hLnZhbHVlID0gImdyZXk4NSINCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ2VyY2Fuw61hIGEgbG90ZXMgYmFsZMOtb3MgeSBzaXRpb3Mgb3NjdXJvcyIsDQogICAgc3VidGl0bGUgPSAiUG9yY2VudGFqZSBkZSB2aXZpZW5kYXMgYWZlY3RhZGFzIMK3IEVuY3Vlc3RhIDIwMjEiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8gREFORSAyMDIxLiBBbGd1bmFzIFVQWiBjb21wYXJ0ZW4gZXN0aW1hY2lvbmVzIGFncnVwYWRhcy4iDQogICkgKw0KICB0ZW1hX2NsYXNlICsNCiAgdGhlbWUoDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCINCiAgKQ0KYGBgDQoNCmBgYHtyIG1hcGEtY2VyY2FuaWEtb2xsYXMsIGVjaG89VFJVRX0NCmdncGxvdCh1cHpfbWFwYSkgKw0KICBnZW9tX3NmKA0KICAgIGFlcyhmaWxsID0gcGN0X2NlcmNhX29sbGFzKSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgbGluZXdpZHRoID0gMC4xNQ0KICApICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oDQogICAgY29sb3VycyA9IGMoIiNFOUUzRUQiLCAiI0E5OERCQiIsICIjRDkwMDZDIiwgIiMzNTFBNEYiKSwNCiAgICBuYW1lID0gIlZpdmllbmRhc1xuYWZlY3RhZGFzICglKSIsDQogICAgbmEudmFsdWUgPSAiZ3JleTg1Ig0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJDZXJjYW7DrWEgYSBleHBlbmRpb3MgZGUgZHJvZ2EiLA0KICAgIHN1YnRpdGxlID0gIlBvcmNlbnRhamUgZGUgdml2aWVuZGFzIGFmZWN0YWRhcyDCtyBFbmN1ZXN0YSAyMDIxIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvIERBTkUgMjAyMS4gQWxndW5hcyBVUFogY29tcGFydGVuIGVzdGltYWNpb25lcyBhZ3J1cGFkYXMuIg0KICApICsNCiAgdGVtYV9jbGFzZSArDQogIHRoZW1lKA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiDQogICkNCmBgYA0KDQojIyMgNi41LjMuIEFjY2VzaWJpbGlkYWQgdGVycml0b3JpYWwgYSBsb3MgQ0FJIGRlIHBvbGljw61hDQoNCkxhIGFjY2VzaWJpbGlkYWQgYSBsb3Mgc2VydmljaW9zIGRlIHNlZ3VyaWRhZCBjb25zdGl0dXllIG90cmEgZGltZW5zacOzbiBkZSBpbnRlcsOpcyBwYXJhIGVsIGFuw6FsaXNpcyB0ZXJyaXRvcmlhbC4NCg0KUGFyYSBleHBsb3JhciBlc3RhIGNhcmFjdGVyw61zdGljYSBzZSB1dGlsaXphIGxhIHZhcmlhYmxlIGBtaW5fY2FpX3BvbGljaWFgLCBxdWUgcmVwcmVzZW50YSBlbCB0aWVtcG8gcHJvbWVkaW8gY2FtaW5hbmRvIGRlc2RlIGxhcyB2aXZpZW5kYXMgaGFzdGEgdW4gQ0FJIGRlIHBvbGljw61hLg0KDQpTdSByZXByZXNlbnRhY2nDs24gZ2VvZ3LDoWZpY2EgcGVybWl0ZSBpZGVudGlmaWNhciBkaWZlcmVuY2lhcyBlbiBsYSBhY2Nlc2liaWxpZGFkIHRlcnJpdG9yaWFsIHkgY29udHJhc3RhcmxhcyBwb3N0ZXJpb3JtZW50ZSBjb24gbG9zIGluZGljYWRvcmVzIGRlIGRlbGl0b3MgeSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZC4NCg0KU2luIGVtYmFyZ28sIGVzdGUgaW5kaWNhZG9yIGRlYmUgaW50ZXJwcmV0YXJzZSBjb24gcHJlY2F1Y2nDs24sIHlhIHF1ZSBsYSBkaXN0YW5jaWEgbyBlbCB0aWVtcG8gcHJvbWVkaW8gZGUgZGVzcGxhemFtaWVudG8gbm8gcmVwcmVzZW50YW4gcG9yIHPDrSBtaXNtb3MgbGEgY2FwYWNpZGFkIG9wZXJhdGl2YSBkZSBsYSBQb2xpY8OtYSwgc3UgcHJlc2VuY2lhIHBlcm1hbmVudGUgZW4gZWwgdGVycml0b3JpbyBuaSBsb3MgdGllbXBvcyBlZmVjdGl2b3MgZGUgYXRlbmNpw7NuLg0KDQpgYGB7ciBtYXBhLWFjY2VzaWJpbGlkYWQtY2FpLCBlY2hvPVRSVUV9DQpnZ3Bsb3QodXB6X21hcGEpICsNCiAgZ2VvbV9zZigNCiAgICBhZXMoZmlsbCA9IG1pbl9jYWlfcG9saWNpYSksDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIGxpbmV3aWR0aCA9IDAuMTUNCiAgKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKA0KICAgIGNvbG91cnMgPSBjKCIjRTlFM0VEIiwgIiNBOThEQkIiLCAiI0Q5MDA2QyIsICIjMzUxQTRGIiksDQogICAgbmFtZSA9ICJNaW51dG9zXG5jYW1pbmFuZG8iLA0KICAgIG5hLnZhbHVlID0gImdyZXk4NSINCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQWNjZXNpYmlsaWRhZCB0ZXJyaXRvcmlhbCBhIGxvcyBDQUkgZGUgcG9saWPDrWEiLA0KICAgIHN1YnRpdGxlID0gIlRpZW1wbyBwcm9tZWRpbyBjYW1pbmFuZG8gZGVzZGUgbGFzIHZpdmllbmRhcyIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byBEQU5FIDIwMjEuIEFsZ3VuYXMgVVBaIGNvbXBhcnRlbiBlc3RpbWFjaW9uZXMgYWdydXBhZGFzLiINCiAgKSArDQogIHRlbWFfY2xhc2UgKw0KICB0aGVtZSgNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0Ig0KICApDQpgYGANCg0KIyMjIDYuNS40LiBDb25zb2xpZGFjacOzbiBkZSBpbmRpY2Fkb3JlcyB0ZXJyaXRvcmlhbGVzDQoNCkFudGVzIGRlIHBhc2FyIGEgbGEgaW50ZXJwcmV0YWNpw7NuLCBjb25zdHJ1aW1vcyB1bmEgdGFibGEgcXVlIHJlw7puZSBsb3MgaW5kaWNhZG9yZXMgZGUgc2VndXJpZGFkLCBwZXJjZXBjacOzbiB5IGVudG9ybm8uIEVzdG8gbm9zIHBlcm1pdGlyw6EgaWRlbnRpZmljYXIgbGFzIFVQWiBxdWUgcHJlc2VudGFuIHZhbG9yZXMgZGVzdGFjYWRvcyBlbiBkaWZlcmVudGVzIGRpbWVuc2lvbmVzLg0KDQpgYGB7ciB0YWJsYS1pbnRlZ3JhZGEtaW5kaWNhZG9yZXMtdGVycml0b3JpYWxlcywgZWNobz1UUlVFfQ0KdGFibGFfaW5kaWNhZG9yZXNfdGVycml0b3JpYWxlcyA8LSB1cHogJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIHBvYmxhY2lvbiwNCiAgICBjYXNvc190b3RhbCwNCiAgICB0YXNhX3RvdGFsLA0KICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkLA0KICAgIHBjdF9jZXJjYV9sb3Rlc19vc2N1cm9zLA0KICAgIHBjdF9jZXJjYV9vbGxhcywNCiAgICBtaW5fY2FpX3BvbGljaWEsDQogICAgZW1fYWdydXBhZGENCiAgKSAlPiUNCiAgYXJyYW5nZShkZXNjKHRhc2FfdG90YWwpKQ0KDQprbml0cjo6a2FibGUoDQogIGhlYWQodGFibGFfaW5kaWNhZG9yZXNfdGVycml0b3JpYWxlcywgMTUpLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIlVQWiBjb24gbWF5b3JlcyB0YXNhcyBkZSBkZWxpdG9zIHkgc3VzIGluZGljYWRvcmVzIHRlcnJpdG9yaWFsZXMiDQopDQpgYGANCg0KIyMgNi42LiBDb21wYXJhY2nDs24gdGVycml0b3JpYWwgZW50cmUgZGVsaXRvcyB5IGNvbmRpY2lvbmVzIGRlbCBlbnRvcm5vDQoNCkRlc3B1w6lzIGRlIGV4cGxvcmFyIGxhIGRpc3RyaWJ1Y2nDs24gZ2VvZ3LDoWZpY2EgZGUgbG9zIGluZGljYWRvcmVzLCBzZSByZWFsaXphIHVuYSBjb21wYXJhY2nDs24gdmlzdWFsIGVudHJlIGxhIHRhc2EgdG90YWwgZGUgZGVsaXRvcyB5IGFsZ3VuYXMgY2FyYWN0ZXLDrXN0aWNhcyBzb2NpYWxlcyB5IHVyYmFuYXMgZGUgbGFzIFVQWi4NCg0KRWwgcHJvcMOzc2l0byBlcyBpZGVudGlmaWNhciBzaSBsYXMgdW5pZGFkZXMgdGVycml0b3JpYWxlcyBxdWUgcHJlc2VudGFuIG1heW9yZXMgbml2ZWxlcyBkZSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCBvIGRldGVybWluYWRhcyBjb25kaWNpb25lcyBkZWwgZW50b3JubyB0YW1iacOpbiByZWdpc3RyYW4gdGFzYXMgZGUgZGVsaXRvcyBtw6FzIGVsZXZhZGFzLg0KDQpFc3RlIGFuw6FsaXNpcyBjb21wbGVtZW50YSBsYXMgY29ycmVsYWNpb25lcyBlc3RhZMOtc3RpY2FzIGRlc2Fycm9sbGFkYXMgYW50ZXJpb3JtZW50ZSwgeWEgcXVlIHBlcm1pdGUgb2JzZXJ2YXIgbGEgZGlzcGVyc2nDs24gZGUgbGFzIG9ic2VydmFjaW9uZXMsIHJlY29ub2NlciBwb3NpYmxlcyB2YWxvcmVzIGV4dHJlbW9zIHkgZXZhbHVhciBzaSBleGlzdGUgYWxnw7puIHBhdHLDs24gdmlzdWFsIGVudHJlIGxhcyB2YXJpYWJsZXMuDQoNCmBgYHtyIGRpc3BlcnNpb24tdGFzYS1wZXJjZXBjaW9uLCBlY2hvPVRSVUV9DQojIFJlbGFjacOzbiBlbnRyZSB0YXNhIGRlIGRlbGl0b3MgeSBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZA0KDQpnZ3Bsb3QoDQogIHVweiwNCiAgYWVzKA0KICAgIHggPSBwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZCwNCiAgICB5ID0gdGFzYV90b3RhbCwNCiAgICBjb2xvciA9IGVtX2FncnVwYWRhDQogICkNCikgKw0KICBnZW9tX3BvaW50KA0KICAgIGFscGhhID0gMC43NSwNCiAgICBzaXplID0gMi41DQogICkgKw0KICBzY2FsZV95X2xvZzEwKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEoKQ0KICApICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoDQogICAgICAiRkFMU0UiID0gIiMxNjhDODYiLA0KICAgICAgIlRSVUUiID0gIiNEOTAwNkMiDQogICAgKSwNCiAgICBsYWJlbHMgPSBjKA0KICAgICAgIkZBTFNFIiA9ICJFc3RpbWFjacOzbiBpbmRpdmlkdWFsIiwNCiAgICAgICJUUlVFIiA9ICJFc3RpbWFjacOzbiBhZ3J1cGFkYSINCiAgICApLA0KICAgIG5hbWUgPSAiVGlwbyBkZSBlc3RpbWFjacOzbiINCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiVGFzYSBkZSBkZWxpdG9zIHkgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQiLA0KICAgIHN1YnRpdGxlID0gIkNvbXBhcmFjacOzbiBlbnRyZSBVUFogwrcgRWplIHZlcnRpY2FsIGVuIGVzY2FsYSBsb2dhcsOtdG1pY2EiLA0KICAgIHggPSAiUGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgKCUpIiwNCiAgICB5ID0gIlRhc2EgZGUgZGVsaXRvcyBwb3IgMTAuMDAwIGhhYml0YW50ZXMiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlczogRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvIDIwMjEgeSByZWdpc3Ryb3MgZGUgZGVsaXRvcyBlbmVyby1qdWxpbyAyMDIzLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMgNi42LjIuIFRhc2EgZGUgZGVsaXRvcyB5IGNvbmRpY2lvbmVzIGRlbCBlbnRvcm5vDQoNClNlIGV4cGxvcmEgbGEgcmVsYWNpw7NuIGVudHJlIGxhIHRhc2EgdG90YWwgZGUgZGVsaXRvcyB5IGRvcyBpbmRpY2Fkb3JlcyBhc29jaWFkb3MgY29uIGxhcyBjb25kaWNpb25lcyBkZWwgZW50b3JubyB1cmJhbm86IGxhIGNlcmNhbsOtYSBhIGxvdGVzIGJhbGTDrW9zIG8gc2l0aW9zIG9zY3Vyb3MgeSBsYSBjZXJjYW7DrWEgYSBleHBlbmRpb3MgZGUgZHJvZ2EuDQoNCkVzdGFzIHZhcmlhYmxlcyBwZXJtaXRlbiBleGFtaW5hciBzaSBsYXMgVVBaIGRvbmRlIHVuYSBtYXlvciBwcm9wb3JjacOzbiBkZSB2aXZpZW5kYXMgcmVwb3J0YSBlc3RhcyBjb25kaWNpb25lcyB0YW1iacOpbiBwcmVzZW50YW4gbWF5b3JlcyB0YXNhcyBkZSBkZWxpdG9zIGRlbnVuY2lhZG9zLg0KDQpMYSBjb21wYXJhY2nDs24gc2UgcmVhbGl6YSBtZWRpYW50ZSBncsOhZmljb3MgZGUgZGlzcGVyc2nDs24sIG1hbnRlbmllbmRvIGlkZW50aWZpY2FkYXMgbGFzIGVzdGltYWNpb25lcyBhZ3J1cGFkYXMgZGUgbGEgRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvLiBMb3MgcmVzdWx0YWRvcyBwZXJtaXRlbiByZWNvbm9jZXIgcG9zaWJsZXMgdGVuZGVuY2lhcyB5IGRpZmVyZW5jaWFzIGVudHJlIGxhcyB1bmlkYWRlcyB0ZXJyaXRvcmlhbGVzLCBzaW4gYXN1bWlyIHF1ZSBsYXMgY29uZGljaW9uZXMgb2JzZXJ2YWRhcyBleHBsaXF1ZW4gZGlyZWN0YW1lbnRlIGxhIG9jdXJyZW5jaWEgZGUgZGVsaXRvcy4NCg0KYGBge3IgZGlzcGVyc2lvbi10YXNhLWxvdGVzLW9zY3Vyb3MsIGVjaG89VFJVRX0NCmdncGxvdCgNCiAgdXB6LA0KICBhZXMoDQogICAgeCA9IHBjdF9jZXJjYV9sb3Rlc19vc2N1cm9zLA0KICAgIHkgPSB0YXNhX3RvdGFsLA0KICAgIGNvbG9yID0gZW1fYWdydXBhZGENCiAgKQ0KKSArDQogIGdlb21fcG9pbnQoDQogICAgYWxwaGEgPSAwLjc1LA0KICAgIHNpemUgPSAyLjUNCiAgKSArDQogIHNjYWxlX3lfbG9nMTAoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9jb21tYSgpDQogICkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICJGQUxTRSIgPSAiIzE2OEM4NiIsDQogICAgICAiVFJVRSIgPSAiI0Q5MDA2QyINCiAgICApLA0KICAgIGxhYmVscyA9IGMoDQogICAgICAiRkFMU0UiID0gIkVzdGltYWNpw7NuIGluZGl2aWR1YWwiLA0KICAgICAgIlRSVUUiID0gIkVzdGltYWNpw7NuIGFncnVwYWRhIg0KICAgICksDQogICAgbmFtZSA9ICJUaXBvIGRlIGVzdGltYWNpw7NuIg0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJDZXJjYW7DrWEgYSBsb3RlcyBvc2N1cm9zIHkgdGFzYSBkZSBkZWxpdG9zIiwNCiAgICBzdWJ0aXRsZSA9ICJFamUgdmVydGljYWwgZW4gZXNjYWxhIGxvZ2Fyw610bWljYSIsDQogICAgeCA9ICJWaXZpZW5kYXMgYWZlY3RhZGFzIHBvciBjZXJjYW7DrWEgYSBsb3RlcyBvc2N1cm9zICglKSIsDQogICAgeSA9ICJUYXNhIGRlIGRlbGl0b3MgcG9yIDEwLjAwMCBoYWJpdGFudGVzIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZXM6IEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byAyMDIxIHkgcmVnaXN0cm9zIGRlIGRlbGl0b3MgZW5lcm8tanVsaW8gMjAyMy4iDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KYGBge3IgZGlzcGVyc2lvbi10YXNhLW9sbGFzLCBlY2hvPVRSVUV9DQpnZ3Bsb3QoDQogIHVweiwNCiAgYWVzKA0KICAgIHggPSBwY3RfY2VyY2Ffb2xsYXMsDQogICAgeSA9IHRhc2FfdG90YWwsDQogICAgY29sb3IgPSBlbV9hZ3J1cGFkYQ0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBhbHBoYSA9IDAuNzUsDQogICAgc2l6ZSA9IDIuNQ0KICApICsNCiAgc2NhbGVfeV9sb2cxMCgNCiAgICBsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2NvbW1hKCkNCiAgKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKA0KICAgICAgIkZBTFNFIiA9ICIjMTY4Qzg2IiwNCiAgICAgICJUUlVFIiA9ICIjRDkwMDZDIg0KICAgICksDQogICAgbGFiZWxzID0gYygNCiAgICAgICJGQUxTRSIgPSAiRXN0aW1hY2nDs24gaW5kaXZpZHVhbCIsDQogICAgICAiVFJVRSIgPSAiRXN0aW1hY2nDs24gYWdydXBhZGEiDQogICAgKSwNCiAgICBuYW1lID0gIlRpcG8gZGUgZXN0aW1hY2nDs24iDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkNlcmNhbsOtYSBhIGV4cGVuZGlvcyBkZSBkcm9nYSB5IHRhc2EgZGUgZGVsaXRvcyIsDQogICAgc3VidGl0bGUgPSAiRWplIHZlcnRpY2FsIGVuIGVzY2FsYSBsb2dhcsOtdG1pY2EiLA0KICAgIHggPSAiVml2aWVuZGFzIGFmZWN0YWRhcyBwb3IgY2VyY2Fuw61hIGEgZXhwZW5kaW9zIGRlIGRyb2dhICglKSIsDQogICAgeSA9ICJUYXNhIGRlIGRlbGl0b3MgcG9yIDEwLjAwMCBoYWJpdGFudGVzIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZXM6IEVuY3Vlc3RhIE11bHRpcHJvcMOzc2l0byAyMDIxIHkgcmVnaXN0cm9zIGRlIGRlbGl0b3MgZW5lcm8tanVsaW8gMjAyMy4iDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KIyMjIDYuNi4zLiBUYXNhIGRlIGRlbGl0b3MgeSBhY2Nlc2liaWxpZGFkIGEgbG9zIENBSQ0KDQpDb21vIMO6bHRpbWEgY29tcGFyYWNpw7NuIHNlIGFuYWxpemEgbGEgcmVsYWNpw7NuIGVudHJlIGxhIHRhc2EgdG90YWwgZGUgZGVsaXRvcyB5IGVsIHRpZW1wbyBwcm9tZWRpbyBjYW1pbmFuZG8gaGFzdGEgdW4gQ0FJIGRlIHBvbGljw61hLg0KDQpFc3RhIGV4cGxvcmFjacOzbiBwZXJtaXRlIG9ic2VydmFyIHNpIGV4aXN0ZW4gZGlmZXJlbmNpYXMgZW4gbGFzIHRhc2FzIGRlIGRlbGl0b3MgZW50cmUgbGFzIFVQWiBzZWfDum4gc3Ugbml2ZWwgZGUgYWNjZXNpYmlsaWRhZCB0ZXJyaXRvcmlhbCBhIGVzdGUgc2VydmljaW8uDQoNCkxhIHZhcmlhYmxlIHV0aWxpemFkYSByZXByZXNlbnRhIHRpZW1wb3MgcHJvbWVkaW8gZGUgZGVzcGxhemFtaWVudG8geSBubyBtaWRlIGRpcmVjdGFtZW50ZSBsYSBjb2JlcnR1cmEgcG9saWNpYWwsIGxhIGNhbnRpZGFkIGRlIHVuaWZvcm1hZG9zIG8gbGEgY2FwYWNpZGFkIGRlIHJlc3B1ZXN0YSBpbnN0aXR1Y2lvbmFsLiBQb3IgdGFudG8sIGN1YWxxdWllciBhc29jaWFjacOzbiBpZGVudGlmaWNhZGEgZGViZSBpbnRlcnByZXRhcnNlIGNvbnNpZGVyYW5kbyBlbCBhbGNhbmNlIGVzcGVjw61maWNvIGRlbCBpbmRpY2Fkb3IuDQoNCmBgYHtyIGRpc3BlcnNpb24tdGFzYS1hY2Nlc2liaWxpZGFkLWNhaSwgZWNobz1UUlVFfQ0KZ2dwbG90KA0KICB1cHosDQogIGFlcygNCiAgICB4ID0gbWluX2NhaV9wb2xpY2lhLA0KICAgIHkgPSB0YXNhX3RvdGFsLA0KICAgIGNvbG9yID0gZW1fYWdydXBhZGENCiAgKQ0KKSArDQogIGdlb21fcG9pbnQoDQogICAgYWxwaGEgPSAwLjc1LA0KICAgIHNpemUgPSAyLjUNCiAgKSArDQogIHNjYWxlX3lfbG9nMTAoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9jb21tYSgpDQogICkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICJGQUxTRSIgPSAiIzE2OEM4NiIsDQogICAgICAiVFJVRSIgPSAiI0Q5MDA2QyINCiAgICApLA0KICAgIGxhYmVscyA9IGMoDQogICAgICAiRkFMU0UiID0gIkVzdGltYWNpw7NuIGluZGl2aWR1YWwiLA0KICAgICAgIlRSVUUiID0gIkVzdGltYWNpw7NuIGFncnVwYWRhIg0KICAgICksDQogICAgbmFtZSA9ICJUaXBvIGRlIGVzdGltYWNpw7NuIg0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJBY2Nlc2liaWxpZGFkIGEgbG9zIENBSSB5IHRhc2EgZGUgZGVsaXRvcyIsDQogICAgc3VidGl0bGUgPSAiRWplIHZlcnRpY2FsIGVuIGVzY2FsYSBsb2dhcsOtdG1pY2EiLA0KICAgIHggPSAiVGllbXBvIHByb21lZGlvIGNhbWluYW5kbyBoYXN0YSB1biBDQUkgKG1pbnV0b3MpIiwNCiAgICB5ID0gIlRhc2EgZGUgZGVsaXRvcyBwb3IgMTAuMDAwIGhhYml0YW50ZXMiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlczogRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvIDIwMjEgeSByZWdpc3Ryb3MgZGUgZGVsaXRvcyBlbmVyby1qdWxpbyAyMDIzLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMgNi42LjQuIFPDrW50ZXNpcyBkZSBsYXMgcmVsYWNpb25lcyB0ZXJyaXRvcmlhbGVzDQoNCkxvcyBncsOhZmljb3MgZGUgZGlzcGVyc2nDs24gcGVybWl0ZW4gb2JzZXJ2YXIgZWwgY29tcG9ydGFtaWVudG8gY29uanVudG8gZGUgbG9zIGluZGljYWRvcmVzIGRlIHNlZ3VyaWRhZCB5IGxhcyBjb25kaWNpb25lcyB0ZXJyaXRvcmlhbGVzLiBQYXJhIGNvbXBsZW1lbnRhciBlc3RhIGV4cGxvcmFjacOzbiB2aXN1YWwsIHNlIHByZXNlbnRhIHVuYSBzw61udGVzaXMgZGUgbGFzIGNvcnJlbGFjaW9uZXMgZGUgU3BlYXJtYW4gZW50cmUgbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zIHkgbGFzIHZhcmlhYmxlcyBzZWxlY2Npb25hZGFzLg0KDQpFbCBjb2VmaWNpZW50ZSBkZSBTcGVhcm1hbiBwZXJtaXRlIGV2YWx1YXIgbGEgZGlyZWNjacOzbiB5IGxhIGludGVuc2lkYWQgZGUgdW5hIGFzb2NpYWNpw7NuIG1vbm90w7NuaWNhIGVudHJlIGRvcyB2YXJpYWJsZXMuIFN1IHV0aWxpemFjacOzbiByZXN1bHRhIGNvbnZlbmllbnRlIGVuIGVzdGEgZXRhcGEgZXhwbG9yYXRvcmlhLCBkZWJpZG8gYSBxdWUgbG9zIGluZGljYWRvcmVzIHByZXNlbnRhbiBkaXN0cmlidWNpb25lcyBjb24gYXNpbWV0csOtYXMgeSBwb3NpYmxlcyB2YWxvcmVzIGV4dHJlbW9zLg0KDQpMb3MgY29lZmljaWVudGVzIGRlYmVuIGludGVycHJldGFyc2UgY29tbyBhc29jaWFjaW9uZXMgZXN0YWTDrXN0aWNhcyB5IG5vIGNvbW8gZXZpZGVuY2lhIGRlIGNhdXNhbGlkYWQuIEFkaWNpb25hbG1lbnRlLCBsYXMgdmFyaWFibGVzIHByb3ZlbmllbnRlcyBkZSBsYSBFbmN1ZXN0YSBNdWx0aXByb3DDs3NpdG8gdGllbmVuIGxhIGxpbWl0YWNpw7NuIGRlIGNvbnRhciBjb24gZXN0aW1hY2lvbmVzIGFncnVwYWRhcyBwYXJhIGFsZ3VuYXMgVVBaLg0KDQpgYGB7ciBzaW50ZXNpcy1jb3JyZWxhY2lvbmVzLXRlcnJpdG9yaWFsZXMsIGVjaG89VFJVRX0NCiMgVmFyaWFibGVzIHNlbGVjY2lvbmFkYXMgcGFyYSBsYSBjb21wYXJhY2nDs24gdGVycml0b3JpYWwNCg0KdmFyaWFibGVzX3RlcnJpdG9yaWFsZXMgPC0gdXB6ICU+JQ0KICBzZWxlY3QoDQogICAgdGFzYV90b3RhbCwNCiAgICBwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZCwNCiAgICBwY3RfY2VyY2FfbG90ZXNfb3NjdXJvcywNCiAgICBwY3RfY2VyY2Ffb2xsYXMsDQogICAgbWluX2NhaV9wb2xpY2lhDQogICkNCg0KIyBDYWxjdWxhciBjb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuIGNvbiBsYSB0YXNhIHRvdGFsDQoNCmNvcnJlbGFjaW9uZXNfdGVycml0b3JpYWxlcyA8LSB0aWJibGUoDQogIFZhcmlhYmxlID0gYygNCiAgICAiUGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQiLA0KICAgICJDZXJjYW7DrWEgYSBsb3RlcyBvc2N1cm9zIiwNCiAgICAiQ2VyY2Fuw61hIGEgZXhwZW5kaW9zIGRlIGRyb2dhIiwNCiAgICAiVGllbXBvIGRlIGFjY2VzbyBhIENBSSINCiAgKSwNCiAgcmhvID0gYygNCiAgICBjb3IoDQogICAgICB2YXJpYWJsZXNfdGVycml0b3JpYWxlcyR0YXNhX3RvdGFsLA0KICAgICAgdmFyaWFibGVzX3RlcnJpdG9yaWFsZXMkcGN0X3BlcmNpYmVfaW5zZWd1cmlkYWQsDQogICAgICBtZXRob2QgPSAic3BlYXJtYW4iLA0KICAgICAgdXNlID0gImNvbXBsZXRlLm9icyINCiAgICApLA0KICAgIGNvcigNCiAgICAgIHZhcmlhYmxlc190ZXJyaXRvcmlhbGVzJHRhc2FfdG90YWwsDQogICAgICB2YXJpYWJsZXNfdGVycml0b3JpYWxlcyRwY3RfY2VyY2FfbG90ZXNfb3NjdXJvcywNCiAgICAgIG1ldGhvZCA9ICJzcGVhcm1hbiIsDQogICAgICB1c2UgPSAiY29tcGxldGUub2JzIg0KICAgICksDQogICAgY29yKA0KICAgICAgdmFyaWFibGVzX3RlcnJpdG9yaWFsZXMkdGFzYV90b3RhbCwNCiAgICAgIHZhcmlhYmxlc190ZXJyaXRvcmlhbGVzJHBjdF9jZXJjYV9vbGxhcywNCiAgICAgIG1ldGhvZCA9ICJzcGVhcm1hbiIsDQogICAgICB1c2UgPSAiY29tcGxldGUub2JzIg0KICAgICksDQogICAgY29yKA0KICAgICAgdmFyaWFibGVzX3RlcnJpdG9yaWFsZXMkdGFzYV90b3RhbCwNCiAgICAgIHZhcmlhYmxlc190ZXJyaXRvcmlhbGVzJG1pbl9jYWlfcG9saWNpYSwNCiAgICAgIG1ldGhvZCA9ICJzcGVhcm1hbiIsDQogICAgICB1c2UgPSAiY29tcGxldGUub2JzIg0KICAgICkNCiAgKQ0KKSAlPiUNCiAgbXV0YXRlKA0KICAgIEludGVuc2lkYWQgPSBjYXNlX3doZW4oDQogICAgICBhYnMocmhvKSA8IDAuMjAgfiAiTXV5IGTDqWJpbCIsDQogICAgICBhYnMocmhvKSA8IDAuNDAgfiAiRMOpYmlsIiwNCiAgICAgIGFicyhyaG8pIDwgMC42MCB+ICJNb2RlcmFkYSIsDQogICAgICBhYnMocmhvKSA8IDAuODAgfiAiRnVlcnRlIiwNCiAgICAgIFRSVUUgfiAiTXV5IGZ1ZXJ0ZSINCiAgICApLA0KICAgIERpcmVjY2lvbiA9IGlmX2Vsc2UoDQogICAgICByaG8gPj0gMCwNCiAgICAgICJQb3NpdGl2YSIsDQogICAgICAiTmVnYXRpdmEiDQogICAgKQ0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MoYWJzKHJobykpKQ0KDQojIFByZXNlbnRhciByZXN1bHRhZG9zDQoNCmtuaXRyOjprYWJsZSgNCiAgY29ycmVsYWNpb25lc190ZXJyaXRvcmlhbGVzLA0KICBkaWdpdHMgPSAzLA0KICBjYXB0aW9uID0gIkNvcnJlbGFjaW9uZXMgZGUgU3BlYXJtYW4gZW50cmUgdGFzYSBkZSBkZWxpdG9zIHkgY29uZGljaW9uZXMgdGVycml0b3JpYWxlcyINCikNCmBgYA0KDQojIyMgNi42LjUuIEFuw6FsaXNpcyBkZSBzZW5zaWJpbGlkYWQgZGUgbGFzIGNvcnJlbGFjaW9uZXMNCg0KRGViaWRvIGEgcXVlIHVuYSBwYXJ0ZSBkZSBsYXMgVVBaIGNvbXBhcnRlIGVzdGltYWNpb25lcyBwcm92ZW5pZW50ZXMgZGUgbGEgRW5jdWVzdGEgTXVsdGlwcm9ww7NzaXRvLCBzZSByZWFsaXphIHVuIGFuw6FsaXNpcyBkZSBzZW5zaWJpbGlkYWQgcGFyYSBldmFsdWFyIHNpIGVzdGEgY2FyYWN0ZXLDrXN0aWNhIHB1ZWRlIGluZmx1aXIgZW4gbGFzIGFzb2NpYWNpb25lcyBpZGVudGlmaWNhZGFzLg0KDQpQYXJhIGVsbG8sIHNlIGNvbXBhcmFuIGxhcyBjb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuIGNhbGN1bGFkYXMgY29uIGVsIGNvbmp1bnRvIGNvbXBsZXRvIGRlIFVQWiB5IGFxdWVsbGFzIG9idGVuaWRhcyDDum5pY2FtZW50ZSBjb24gbGFzIHVuaWRhZGVzIHRlcnJpdG9yaWFsZXMgcXVlIGN1ZW50YW4gY29uIGVzdGltYWNpb25lcyBpbmRpdmlkdWFsZXMuDQoNCkxhIGNvbXBhcmFjacOzbiBwZXJtaXRlIG9ic2VydmFyIHNpIGxhIGRpcmVjY2nDs24geSBsYSBtYWduaXR1ZCBkZSBsYXMgYXNvY2lhY2lvbmVzIHNlIG1hbnRpZW5lbiBiYWpvIGFtYm9zIGVzY2VuYXJpb3MuIFRhbWJpw6luIHNlIGNvbnNpZGVyYSBsYSBjYW50aWRhZCBkZSBvYnNlcnZhY2lvbmVzIHV0aWxpemFkYXMgZW4gY2FkYSBjw6FsY3VsbywgZGFkbyBxdWUgbGEgZXhjbHVzacOzbiBkZSBsYXMgZXN0aW1hY2lvbmVzIGFncnVwYWRhcyByZWR1Y2UgZWwgdGFtYcOxbyBkZWwgY29uanVudG8gYW5hbGl6YWRvLg0KDQpFc3RlIGVqZXJjaWNpbyBjb25zdGl0dXllIHVuYSB2YWxpZGFjacOzbiBjb21wbGVtZW50YXJpYSBkZSBsb3MgcmVzdWx0YWRvcyBleHBsb3JhdG9yaW9zLiBObyBvYnN0YW50ZSwgZWwgYW7DoWxpc2lzIGNvbiBlc3RpbWFjaW9uZXMgaW5kaXZpZHVhbGVzIHJlcHJlc2VudGEgdW4gc3ViY29uanVudG8gZGUgbGFzIFVQWiB5IG5vIGVsaW1pbmEgbmVjZXNhcmlhbWVudGUgdG9kYXMgbGFzIGxpbWl0YWNpb25lcyBkZSByZXByZXNlbnRhdGl2aWRhZCBkZSBsYSBlbmN1ZXN0YS4NCg0KYGBge3Igc2Vuc2liaWxpZGFkLWNvcnJlbGFjaW9uZXMtYWdydXBhZGFzLCBlY2hvPVRSVUV9DQojIERlZmluaXIgbGFzIHZhcmlhYmxlcyBxdWUgc2UgdmFuIGEgY29tcGFyYXINCg0KdmFyaWFibGVzX3NlbnNpYmlsaWRhZCA8LSBjKA0KICAicGN0X3BlcmNpYmVfaW5zZWd1cmlkYWQiLA0KICAicGN0X2NlcmNhX2xvdGVzX29zY3Vyb3MiLA0KICAicGN0X2NlcmNhX29sbGFzIiwNCiAgIm1pbl9jYWlfcG9saWNpYSINCikNCg0KIyBGdW5jacOzbiBwYXJhIGNhbGN1bGFyIGxhcyBjb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuDQoNCmNhbGN1bGFyX2NvcnJlbGFjaW9uZXMgPC0gZnVuY3Rpb24oZGF0b3MsIGVzY2VuYXJpbykgew0KDQogIHB1cnJyOjptYXBfZGZyKHZhcmlhYmxlc19zZW5zaWJpbGlkYWQsIGZ1bmN0aW9uKHZhcmlhYmxlKSB7DQoNCiAgICBkYXRvc192YWxpZG9zIDwtIGRhdG9zICU+JQ0KICAgICAgc2VsZWN0KA0KICAgICAgICB0YXNhX3RvdGFsLA0KICAgICAgICBhbGxfb2YodmFyaWFibGUpDQogICAgICApICU+JQ0KICAgICAgZHJvcF9uYSgpICU+JQ0KICAgICAgZmlsdGVyKA0KICAgICAgICBpcy5maW5pdGUodGFzYV90b3RhbCksDQogICAgICAgIGlzLmZpbml0ZSguZGF0YVtbdmFyaWFibGVdXSkNCiAgICAgICkNCg0KICAgIHRpYmJsZSgNCiAgICAgIEVzY2VuYXJpbyA9IGVzY2VuYXJpbywNCiAgICAgIFZhcmlhYmxlID0gdmFyaWFibGUsDQogICAgICBOdW1lcm9fVVBaID0gbnJvdyhkYXRvc192YWxpZG9zKSwNCiAgICAgIHJobyA9IGlmIChucm93KGRhdG9zX3ZhbGlkb3MpID49IDMpIHsNCiAgICAgICAgY29yKA0KICAgICAgICAgIGRhdG9zX3ZhbGlkb3MkdGFzYV90b3RhbCwNCiAgICAgICAgICBkYXRvc192YWxpZG9zW1t2YXJpYWJsZV1dLA0KICAgICAgICAgIG1ldGhvZCA9ICJzcGVhcm1hbiINCiAgICAgICAgKQ0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgTkFfcmVhbF8NCiAgICAgIH0NCiAgICApDQogIH0pDQp9DQoNCiMgRXNjZW5hcmlvIDE6IHRvZGFzIGxhcyBVUFoNCg0KY29ycmVsYWNpb25lc19jb21wbGV0YXMgPC0gY2FsY3VsYXJfY29ycmVsYWNpb25lcygNCiAgdXB6LA0KICAiVG9kYXNfVVBaIg0KKQ0KDQojIEVzY2VuYXJpbyAyOiDDum5pY2FtZW50ZSBlc3RpbWFjaW9uZXMgaW5kaXZpZHVhbGVzDQoNCnVwel9pbmRpdmlkdWFsZXMgPC0gdXB6ICU+JQ0KICBmaWx0ZXIoZW1fYWdydXBhZGEgPT0gRkFMU0UpDQoNCmNvcnJlbGFjaW9uZXNfaW5kaXZpZHVhbGVzIDwtIGNhbGN1bGFyX2NvcnJlbGFjaW9uZXMoDQogIHVwel9pbmRpdmlkdWFsZXMsDQogICJVUFpfaW5kaXZpZHVhbGVzIg0KKQ0KDQojIEludGVncmFyIGxvcyByZXN1bHRhZG9zDQoNCmNvbXBhcmFjaW9uX3NlbnNpYmlsaWRhZCA8LSBiaW5kX3Jvd3MoDQogIGNvcnJlbGFjaW9uZXNfY29tcGxldGFzLA0KICBjb3JyZWxhY2lvbmVzX2luZGl2aWR1YWxlcw0KKSAlPiUNCiAgbXV0YXRlKA0KICAgIFZhcmlhYmxlID0gcmVjb2RlKA0KICAgICAgVmFyaWFibGUsDQogICAgICBwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZCA9ICJQZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCIsDQogICAgICBwY3RfY2VyY2FfbG90ZXNfb3NjdXJvcyA9ICJDZXJjYW7DrWEgYSBsb3RlcyBvc2N1cm9zIiwNCiAgICAgIHBjdF9jZXJjYV9vbGxhcyA9ICJDZXJjYW7DrWEgYSBleHBlbmRpb3MgZGUgZHJvZ2EiLA0KICAgICAgbWluX2NhaV9wb2xpY2lhID0gIlRpZW1wbyBkZSBhY2Nlc28gYSBDQUkiDQogICAgKQ0KICApDQoNCiMgT3JnYW5pemFyIGxhIGNvbXBhcmFjacOzbiBlbiBjb2x1bW5hcw0KDQp0YWJsYV9zZW5zaWJpbGlkYWQgPC0gY29tcGFyYWNpb25fc2Vuc2liaWxpZGFkICU+JQ0KICBwaXZvdF93aWRlcigNCiAgICBuYW1lc19mcm9tID0gRXNjZW5hcmlvLA0KICAgIHZhbHVlc19mcm9tID0gYyhyaG8sIE51bWVyb19VUFopDQogICkgJT4lDQogIG11dGF0ZSgNCiAgICBEaWZlcmVuY2lhX3JobyA9IHJob19Ub2Rhc19VUFogLQ0KICAgICAgcmhvX1VQWl9pbmRpdmlkdWFsZXMsDQoNCiAgICBEaXJlY2Npb25fY29uc2lzdGVudGUgPSBjYXNlX3doZW4oDQogICAgICBpcy5uYShyaG9fVG9kYXNfVVBaKSB8DQogICAgICAgIGlzLm5hKHJob19VUFpfaW5kaXZpZHVhbGVzKSB+ICJObyBldmFsdWFibGUiLA0KDQogICAgICBzaWduKHJob19Ub2Rhc19VUFopID09DQogICAgICAgIHNpZ24ocmhvX1VQWl9pbmRpdmlkdWFsZXMpIH4gIlPDrSIsDQoNCiAgICAgIFRSVUUgfiAiTm8iDQogICAgKQ0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MoYWJzKHJob19Ub2Rhc19VUFopKSkNCg0KIyBQcmVzZW50YXIgcmVzdWx0YWRvcw0KDQprbml0cjo6a2FibGUoDQogIHRhYmxhX3NlbnNpYmlsaWRhZCwNCiAgZGlnaXRzID0gMywNCiAgY2FwdGlvbiA9ICJBbsOhbGlzaXMgZGUgc2Vuc2liaWxpZGFkIGRlIGxhcyBjb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuIg0KKQ0KYGBgDQoNClBhcmEgY29tcGxlbWVudGFyIGxhIGNvbXBhcmFjacOzbiBudW3DqXJpY2EsIHNlIHByZXNlbnRhIHVuYSB2aXN1YWxpemFjacOzbiBkZSBsb3MgY29lZmljaWVudGVzIGRlIGNvcnJlbGFjacOzbiBvYnRlbmlkb3MgZW4gYW1ib3MgZXNjZW5hcmlvcy4gRXN0YSByZXByZXNlbnRhY2nDs24gcGVybWl0ZSBpZGVudGlmaWNhciBkZSBtYW5lcmEgZGlyZWN0YSBzaSBsYXMgYXNvY2lhY2lvbmVzIGNvbnNlcnZhbiBzdSBkaXJlY2Npw7NuIHkgc2kgcHJlc2VudGFuIGNhbWJpb3MgaW1wb3J0YW50ZXMgZW4gc3UgbWFnbml0dWQuDQoNCmBgYHtyIGdyYWZpY28tY29tcGFyYWNpb24tc2Vuc2liaWxpZGFkLCBlY2hvPVRSVUV9DQpnZ3Bsb3QoDQogIGNvbXBhcmFjaW9uX3NlbnNpYmlsaWRhZCwNCiAgYWVzKA0KICAgIHggPSByaG8sDQogICAgeSA9IHJlb3JkZXIoVmFyaWFibGUsIHJobyksDQogICAgY29sb3IgPSBFc2NlbmFyaW8NCiAgKQ0KKSArDQogIGdlb21fdmxpbmUoDQogICAgeGludGVyY2VwdCA9IDAsDQogICAgbGluZXR5cGUgPSAiZGFzaGVkIiwNCiAgICBjb2xvciA9ICJncmV5NTAiDQogICkgKw0KICBnZW9tX3BvaW50KA0KICAgIHNpemUgPSAzLA0KICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpDQogICkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICJUb2Rhc19VUFoiID0gIiMzNTFBNEYiLA0KICAgICAgIlVQWl9pbmRpdmlkdWFsZXMiID0gIiMxNjhDODYiDQogICAgKSwNCiAgICBsYWJlbHMgPSBjKA0KICAgICAgIlRvZGFzX1VQWiIgPSAiVG9kYXMgbGFzIFVQWiIsDQogICAgICAiVVBaX2luZGl2aWR1YWxlcyIgPSAiRXN0aW1hY2lvbmVzIGluZGl2aWR1YWxlcyINCiAgICApLA0KICAgIG5hbWUgPSAiRXNjZW5hcmlvIg0KICApICsNCiAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgIGxpbWl0cyA9IGMoLTEsIDEpLA0KICAgIGJyZWFrcyA9IHNlcSgtMSwgMSwgYnkgPSAwLjIpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkVzdGFiaWxpZGFkIGRlIGxhcyBjb3JyZWxhY2lvbmVzIHNlZ8O6biB0aXBvIGRlIGVzdGltYWNpw7NuIiwNCiAgICBzdWJ0aXRsZSA9ICJDb21wYXJhY2nDs24gZGUgbG9zIGNvZWZpY2llbnRlcyBkZSBTcGVhcm1hbiIsDQogICAgeCA9ICJDb2VmaWNpZW50ZSBkZSBTcGVhcm1hbiIsDQogICAgeSA9IE5VTEwNCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIDcuIFByZWd1bnRhcyBkZSBpbnZlc3RpZ2FjacOzbiB5IGhhbGxhemdvcw0KDQojIyA3LjEuIFByZWd1bnRhcyBxdWUgb3JpZW50YW4gZWwgYW7DoWxpc2lzDQoNCkVsIGFuw6FsaXNpcyBleHBsb3JhdG9yaW8gc2UgZGVzYXJyb2xsw7MgYSBwYXJ0aXIgZGUgcHJlZ3VudGFzIG9yaWVudGFkYXMgYSBjb21wcmVuZGVyIGxhcyBkaWZlcmVuY2lhcyB0ZXJyaXRvcmlhbGVzIGVuIGxvcyBpbmRpY2Fkb3JlcyBkZSBzZWd1cmlkYWQgeSBzdSBwb3NpYmxlIHJlbGFjacOzbiBjb24gbGFzIGNhcmFjdGVyw61zdGljYXMgZGVtb2dyw6FmaWNhcywgc29jaW9lY29uw7NtaWNhcyB5IHVyYmFuYXMgZGUgbGFzIFVQWiBkZSBCb2dvdMOhLg0KDQpBIHBhcnRpciBkZSBsYSBpbmZvcm1hY2nDs24gZGlzcG9uaWJsZSwgc2UgZXN0YWJsZWNpZXJvbiBsYXMgc2lndWllbnRlcyBwcmVndW50YXMgZGUgaW52ZXN0aWdhY2nDs246DQoNCjEuIMK/TGFzIFVQWiBjb24gbWF5b3IgY2FudGlkYWQgZGUgZGVudW5jaWFzIHNvbiB0YW1iacOpbiBsYXMgcXVlIHByZXNlbnRhbiBtYXlvcmVzIHRhc2FzIGRlIGRlbGl0b3MgcG9yIGhhYml0YW50ZT8NCjIuIMK/Q8OzbW8gaW5mbHV5ZSBlbCB0YW1hw7FvIHBvYmxhY2lvbmFsIGVuIGxhIGludGVycHJldGFjacOzbiBkZSBsYXMgdGFzYXMgZGUgZGVsaXRvcz8NCjMuIMK/UXXDqSBkaWZlcmVuY2lhcyB0ZXJyaXRvcmlhbGVzIHNlIG9ic2VydmFuIGVuIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGRlbGl0b3MgZGVudW5jaWFkb3M/DQo0LiDCv0V4aXN0ZSBhbGd1bmEgYXNvY2lhY2nDs24gZW50cmUgZWwgYWx1bWJyYWRvIHDDumJsaWNvIHkgbGFzIHRhc2FzIGRlIGRlbGl0b3M/DQo1LiDCv1F1w6kgcmVsYWNpw7NuIHNlIG9ic2VydmEgZW50cmUgcG9icmV6YSwgc2FsYXJpbywgZXN0cmF0byB5IGxvcyBpbmRpY2Fkb3JlcyBkZSBzZWd1cmlkYWQ/DQo2LiDCv0xhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHByZXNlbnRhIHVuIGNvbXBvcnRhbWllbnRvIHNpbWlsYXIgYWwgZGUgbG9zIGRlbGl0b3MgZGVudW5jaWFkb3M/DQo3LiDCv0xhcyBjb25kaWNpb25lcyBkZWwgZW50b3JubyB5IGxhIGFjY2VzaWJpbGlkYWQgYSBsb3MgQ0FJIHByZXNlbnRhbiBhbGd1bmEgYXNvY2lhY2nDs24gY29uIGxhcyB0YXNhcyBkZSBkZWxpdG9zPw0KDQpFc3RhcyBwcmVndW50YXMgYXJ0aWN1bGFuIGxvcyBhbsOhbGlzaXMgZXN0YWTDrXN0aWNvcyB5IGxhcyByZXByZXNlbnRhY2lvbmVzIGdyw6FmaWNhcyBkZXNhcnJvbGxhZGFzIGVuIGxhcyBzZWNjaW9uZXMgYW50ZXJpb3Jlcy4gU3UgcHJvcMOzc2l0byBlcyBpbnRlZ3JhciBsb3MgcmVzdWx0YWRvcyBlbiB1bmEgbmFycmF0aXZhIHF1ZSBwZXJtaXRhIGNvbXByZW5kZXIgbm8gc29sbyBkw7NuZGUgc2UgcmVnaXN0cmFuIG3DoXMgZGVudW5jaWFzLCBzaW5vIHRhbWJpw6luIGPDs21vIHNlIHJlbGFjaW9uYW4gZXN0b3MgcmVnaXN0cm9zIGNvbiBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBjYWRhIHRlcnJpdG9yaW8uDQoNCiMjIDcuMi4gTWF0cml6IGRlIHByZWd1bnRhcywgdmFyaWFibGVzIHkgYW7DoWxpc2lzIHJlYWxpemFkb3MNCg0KRXN0YSBtYXRyaXogbm9zIHBlcm1pdGlyw6EgZGVtb3N0cmFyIHF1ZSBjYWRhIHByZWd1bnRhIHRpZW5lIHVuIHJlc3BhbGRvIGFuYWzDrXRpY28geSBxdWUgbm8gZXN0YW1vcyBpbmNsdXllbmRvIGdyw6FmaWNvcyBzaW4gdW5hIGZpbmFsaWRhZCBjb25jcmV0YS4NCg0KYGBge3IgbWF0cml6LXByZWd1bnRhcy1pbnZlc3RpZ2FjaW9uLCBlY2hvPVRSVUV9DQptYXRyaXpfcHJlZ3VudGFzIDwtIHRpYmJsZSgNCiAgUHJlZ3VudGEgPSBjKA0KICAgICLCv0xhcyBVUFogY29uIG3DoXMgZGVudW5jaWFzIHRhbWJpw6luIHRpZW5lbiBtYXlvcmVzIHRhc2FzPyIsDQogICAgIsK/Q8OzbW8gaW5mbHV5ZSBlbCB0YW1hw7FvIHBvYmxhY2lvbmFsIGVuIGxhcyB0YXNhcz8iLA0KICAgICLCv1F1w6kgZGlmZXJlbmNpYXMgdGVycml0b3JpYWxlcyBleGlzdGVuIGVuIGxvcyBkZWxpdG9zPyIsDQogICAgIsK/RXhpc3RlIGFzb2NpYWNpw7NuIGVudHJlIGFsdW1icmFkbyB5IGRlbGl0b3M/IiwNCiAgICAiwr9Dw7NtbyBzZSByZWxhY2lvbmFuIGxhcyBjb25kaWNpb25lcyBzb2Npb2Vjb27Ds21pY2FzIHkgbG9zIGRlbGl0b3M/IiwNCiAgICAiwr9MYSBwZXJjZXBjacOzbiBjb2luY2lkZSBjb24gbG9zIGRlbGl0b3MgZGVudW5jaWFkb3M/IiwNCiAgICAiwr9RdcOpIHJlbGFjacOzbiB0aWVuZW4gZWwgZW50b3JubyB5IGxhIGFjY2VzaWJpbGlkYWQgYSBsb3MgQ0FJPyINCiAgKSwNCg0KICBWYXJpYWJsZXMgPSBjKA0KICAgICJjYXNvc190b3RhbCwgdGFzYV90b3RhbCIsDQogICAgInBvYmxhY2lvbiwgZGVuc2lkYWRfaGFiX2ttMiwgdGFzYV90b3RhbCIsDQogICAgImNhc29zX3RvdGFsLCB0YXNhX3RvdGFsLCB1cHpfbm9tYnJlIiwNCiAgICAibHVtaW5hcmlhc19rbTIsIGx1bWluYXJpYXNfMTAwMGhhYiwgcGN0X2x1bWluYXJpYXNfbGVkLCB0YXNhX3RvdGFsIiwNCiAgICAicGN0X3BvYnJlemEsIHNhbGFyaW9fcHJvbWVkaW8sIHBjdF9lc3RyYXRvXzFfMiwgdGFzYV90b3RhbCIsDQogICAgInBjdF9wZXJjaWJlX2luc2VndXJpZGFkLCB0YXNhX3RvdGFsIiwNCiAgICAicGN0X2NlcmNhX2xvdGVzX29zY3Vyb3MsIHBjdF9jZXJjYV9vbGxhcywgbWluX2NhaV9wb2xpY2lhLCB0YXNhX3RvdGFsIg0KICApLA0KDQogIEFuYWxpc2lzID0gYygNCiAgICAiQ29tcGFyYWNpw7NuIGRlIGNhc29zIHkgdGFzYXMiLA0KICAgICJEaXN0cmlidWNpb25lcyB5IHZhbG9yZXMgZXh0cmVtb3MiLA0KICAgICJNYXBhcyBkZSB0YXNhcyB5IGNhc29zIiwNCiAgICAiQ29ycmVsYWNpb25lcyB5IGdyw6FmaWNvcyBkZSBkaXNwZXJzacOzbiIsDQogICAgIkVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzIHkgY29ycmVsYWNpb25lcyIsDQogICAgIk1hcGFzLCBkaXNwZXJzacOzbiB5IGNvcnJlbGFjacOzbiIsDQogICAgIk1hcGFzLCBkaXNwZXJzacOzbiB5IGFuw6FsaXNpcyBkZSBzZW5zaWJpbGlkYWQiDQogICkNCikNCg0Ka25pdHI6OmthYmxlKA0KICBtYXRyaXpfcHJlZ3VudGFzLA0KICBjYXB0aW9uID0gIlJlbGFjacOzbiBlbnRyZSBwcmVndW50YXMgZGUgaW52ZXN0aWdhY2nDs24sIHZhcmlhYmxlcyB5IGFuw6FsaXNpcyINCikNCmBgYA0KDQojIyA3LjMuIERlc2Fycm9sbG8gZGUgbG9zIGhhbGxhemdvcyBlIGluc2lnaHRzDQoNCiMjIyA3LjMuMS4gwr9MYXMgVVBaIGNvbiBtw6FzIGRlbnVuY2lhcyBzb24gdGFtYmnDqW4gbGFzIHF1ZSBwcmVzZW50YW4gbWF5b3JlcyB0YXNhcyBkZSBkZWxpdG9zPw0KDQpMYSBwcmltZXJhIHByZWd1bnRhIGJ1c2NhIGVzdGFibGVjZXIgc2kgbGFzIHVuaWRhZGVzIHRlcnJpdG9yaWFsZXMgcXVlIGNvbmNlbnRyYW4gZWwgbWF5b3IgbsO6bWVybyBkZSBkZW51bmNpYXMgc29uIHRhbWJpw6luIGFxdWVsbGFzIHF1ZSBwcmVzZW50YW4gdW5hIG1heW9yIGludGVuc2lkYWQgZGVsaWN0aXZhIGVuIHJlbGFjacOzbiBjb24gc3UgcG9ibGFjacOzbi4NCg0KUGFyYSByZXNwb25kZXJsYSBzZSBjb21wYXJhbiBkb3MgaW5kaWNhZG9yZXM6IGVsIG7Dum1lcm8gdG90YWwgZGUgY2Fzb3MgZGVudW5jaWFkb3MgeSBsYSB0YXNhIGRlIGRlbGl0b3MgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMuIEVzdGEgZGlzdGluY2nDs24gZXMgaW1wb3J0YW50ZSBwb3JxdWUgZWwgdm9sdW1lbiBkZSBkZW51bmNpYXMgcHVlZGUgZXN0YXIgcmVsYWNpb25hZG8gY29uIGVsIHRhbWHDsW8gcG9ibGFjaW9uYWwgZGUgY2FkYSBVUFosIG1pZW50cmFzIHF1ZSBsYSB0YXNhIHBlcm1pdGUgcmVhbGl6YXIgdW5hIGNvbXBhcmFjacOzbiByZWxhdGl2YS4NCg0KRWwgYW7DoWxpc2lzIHNlIGRlc2Fycm9sbGEgbWVkaWFudGUgbGEgY29tcGFyYWNpw7NuIGRlIGxvcyByYW5raW5ncyBkZSBjYXNvcyB5IHRhc2FzLCBhc8OtIGNvbW8gZGUgbGEgcmVsYWNpw7NuIGVudHJlIHBvYmxhY2nDs24geSBuw7ptZXJvIGRlIGRlbnVuY2lhcy4gRGUgZXN0YSBtYW5lcmEsIHNlIGJ1c2NhIGlkZW50aWZpY2FyIHNpIGxvcyB0ZXJyaXRvcmlvcyBxdWUgY29uY2VudHJhbiBtw6FzIGNhc29zIHRhbWJpw6luIG9jdXBhbiBsYXMgcHJpbWVyYXMgcG9zaWNpb25lcyBjdWFuZG8gc2UgY29uc2lkZXJhIHN1IHBvYmxhY2nDs24uDQoNCmBgYHtyIGhhbGxhemdvLTczMS1yYW5raW5nLWNhc29zLXRhc2FzLCBlY2hvPVRSVUV9DQojIFRvcCAxMCBkZSBVUFogcG9yIG7Dum1lcm8gZGUgY2Fzb3MgZGVudW5jaWFkb3MNCg0KcmFua2luZ19jYXNvc183MzEgPC0gdXB6ICU+JQ0KICBhcnJhbmdlKGRlc2MoY2Fzb3NfdG90YWwpKSAlPiUNCiAgc2VsZWN0KA0KICAgIHVwel9ub21icmUsDQogICAgcG9ibGFjaW9uLA0KICAgIGNhc29zX3RvdGFsLA0KICAgIHRhc2FfdG90YWwNCiAgKSAlPiUNCiAgc2xpY2VfaGVhZChuID0gMTApICU+JQ0KICBtdXRhdGUoUG9zaWNpb25fY2Fzb3MgPSByb3dfbnVtYmVyKCkpDQoNCiMgVG9wIDEwIGRlIFVQWiBwb3IgdGFzYSBkZSBkZWxpdG9zDQoNCnJhbmtpbmdfdGFzYXNfNzMxIDwtIHVweiAlPiUNCiAgYXJyYW5nZShkZXNjKHRhc2FfdG90YWwpKSAlPiUNCiAgc2VsZWN0KA0KICAgIHVwel9ub21icmUsDQogICAgcG9ibGFjaW9uLA0KICAgIGNhc29zX3RvdGFsLA0KICAgIHRhc2FfdG90YWwNCiAgKSAlPiUNCiAgc2xpY2VfaGVhZChuID0gMTApICU+JQ0KICBtdXRhdGUoUG9zaWNpb25fdGFzYSA9IHJvd19udW1iZXIoKSkNCg0KIyBQcmVzZW50YXIgcmFua2luZyBwb3IgY2Fzb3MNCg0Ka25pdHI6OmthYmxlKA0KICByYW5raW5nX2Nhc29zXzczMSwNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJUb3AgMTAgZGUgVVBaIHNlZ8O6biBuw7ptZXJvIGRlIGNhc29zIGRlbnVuY2lhZG9zIg0KKQ0KDQojIFByZXNlbnRhciByYW5raW5nIHBvciB0YXNhDQoNCmtuaXRyOjprYWJsZSgNCiAgcmFua2luZ190YXNhc183MzEsDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiVG9wIDEwIGRlIFVQWiBzZWfDum4gdGFzYSBkZSBkZWxpdG9zIHBvciAxMC4wMDAgaGFiaXRhbnRlcyINCikNCmBgYA0KDQpgYGB7ciBoYWxsYXpnby03MzEtY29tcGFyYWNpb24tcmFua2luZ3MsIGVjaG89VFJVRX0NCiMgVW5pciBsYXMgcG9zaWNpb25lcyBkZSBsb3MgZG9zIHJhbmtpbmdzDQoNCmNvbXBhcmFjaW9uX3JhbmtpbmdzXzczMSA8LSBmdWxsX2pvaW4oDQogIHJhbmtpbmdfY2Fzb3NfNzMxICU+JQ0KICAgIHNlbGVjdCgNCiAgICAgIHVwel9ub21icmUsDQogICAgICBQb3NpY2lvbl9jYXNvcw0KICAgICksDQogIHJhbmtpbmdfdGFzYXNfNzMxICU+JQ0KICAgIHNlbGVjdCgNCiAgICAgIHVwel9ub21icmUsDQogICAgICBQb3NpY2lvbl90YXNhDQogICAgKSwNCiAgYnkgPSAidXB6X25vbWJyZSINCikgJT4lDQogIG11dGF0ZSgNCiAgICBHcnVwbyA9IGNhc2Vfd2hlbigNCiAgICAgICFpcy5uYShQb3NpY2lvbl9jYXNvcykgJiAhaXMubmEoUG9zaWNpb25fdGFzYSkgfg0KICAgICAgICAiQXBhcmVjZSBlbiBhbWJvcyByYW5raW5ncyIsDQogICAgICAhaXMubmEoUG9zaWNpb25fY2Fzb3MpIH4NCiAgICAgICAgIlNvbG8gZW4gcmFua2luZyBkZSBjYXNvcyIsDQogICAgICBUUlVFIH4gIlNvbG8gZW4gcmFua2luZyBkZSB0YXNhcyINCiAgICApDQogICkNCg0KIyBUYWJsYSBjb21wYXJhdGl2YQ0KDQprbml0cjo6a2FibGUoDQogIGNvbXBhcmFjaW9uX3JhbmtpbmdzXzczMSwNCiAgY2FwdGlvbiA9ICJDb21wYXJhY2nDs24gZGUgbGFzIFVQWiBxdWUgaW50ZWdyYW4gbG9zIGRvcyByYW5raW5ncyINCikNCg0KIyBWaXN1YWxpemFjacOzbiBkZSBsYXMgcG9zaWNpb25lcw0KDQpnZ3Bsb3QoDQogIGNvbXBhcmFjaW9uX3JhbmtpbmdzXzczMSwNCiAgYWVzKA0KICAgIHggPSBQb3NpY2lvbl9jYXNvcywNCiAgICB5ID0gUG9zaWNpb25fdGFzYSwNCiAgICBjb2xvciA9IEdydXBvLA0KICAgIGxhYmVsID0gdXB6X25vbWJyZQ0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBzaXplID0gMywNCiAgICBuYS5ybSA9IFRSVUUNCiAgKSArDQogIHNjYWxlX3hfcmV2ZXJzZSgNCiAgICBicmVha3MgPSAxOjEwLA0KICAgIGxpbWl0cyA9IGMoMTAsIDEpDQogICkgKw0KICBzY2FsZV95X3JldmVyc2UoDQogICAgYnJlYWtzID0gMToxMCwNCiAgICBsaW1pdHMgPSBjKDEwLCAxKQ0KICApICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoDQogICAgICAiQXBhcmVjZSBlbiBhbWJvcyByYW5raW5ncyIgPSAiIzM1MUE0RiIsDQogICAgICAiU29sbyBlbiByYW5raW5nIGRlIGNhc29zIiA9ICIjMTY4Qzg2IiwNCiAgICAgICJTb2xvIGVuIHJhbmtpbmcgZGUgdGFzYXMiID0gIiNEOTAwNkMiDQogICAgKSwNCiAgICBuYW1lID0gIlBhcnRpY2lwYWNpw7NuIg0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJMYXMgVVBaIGNvbiBtw6FzIGRlbnVuY2lhcyBubyBuZWNlc2FyaWFtZW50ZSBsaWRlcmFuIGxhcyB0YXNhcyIsDQogICAgc3VidGl0bGUgPSAiUG9zaWNpw7NuIGRlIGNhZGEgVVBaIGVuIGxvcyBkb3MgcmFua2luZ3MiLA0KICAgIHggPSAiUG9zaWNpw7NuIGVuIGVsIHJhbmtpbmcgZGUgY2Fzb3MiLA0KICAgIHkgPSAiUG9zaWNpw7NuIGVuIGVsIHJhbmtpbmcgZGUgdGFzYXMiDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KYGBge3IgaGFsbGF6Z28tNzMxLXBvYmxhY2lvbi1jYXNvcywgZWNobz1UUlVFfQ0KIyBSZWxhY2nDs24gZW50cmUgcG9ibGFjacOzbiB5IG7Dum1lcm8gZGUgY2Fzb3MgZGVudW5jaWFkb3MNCg0KZ2dwbG90KA0KICB1cHosDQogIGFlcygNCiAgICB4ID0gcG9ibGFjaW9uLA0KICAgIHkgPSBjYXNvc190b3RhbA0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBjb2xvciA9ICIjMTY4Qzg2IiwNCiAgICBhbHBoYSA9IDAuNzUsDQogICAgc2l6ZSA9IDIuNQ0KICApICsNCiAgZ2VvbV9zbW9vdGgoDQogICAgbWV0aG9kID0gImxtIiwNCiAgICBzZSA9IFRSVUUsDQogICAgY29sb3IgPSAiI0Q5MDA2QyIsDQogICAgbGluZXdpZHRoID0gMC44DQogICkgKw0KICBzY2FsZV94X2xvZzEwKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEoKQ0KICApICsNCiAgc2NhbGVfeV9sb2cxMCgNCiAgICBsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2NvbW1hKCkNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRWwgdm9sdW1lbiBkZSBkZW51bmNpYXMgZGViZSBpbnRlcnByZXRhcnNlIGp1bnRvIGNvbiBsYSBwb2JsYWNpw7NuIiwNCiAgICBzdWJ0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgaGFiaXRhbnRlcyB5IGNhc29zIGRlbnVuY2lhZG9zIHBvciBVUFoiLA0KICAgIHggPSAiUG9ibGFjacOzbiBkZSBsYSBVUFogKGVzY2FsYSBsb2dhcsOtdG1pY2EpIiwNCiAgICB5ID0gIkNhc29zIGRlbnVuY2lhZG9zIChlc2NhbGEgbG9nYXLDrXRtaWNhKSIsDQogICAgY2FwdGlvbiA9ICJMYSBsw61uZWEgcmVwcmVzZW50YSB1bmEgdGVuZGVuY2lhIGxpbmVhbCBhanVzdGFkYSBzb2JyZSBsb3MgdmFsb3JlcyB0cmFuc2Zvcm1hZG9zLiINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMjIEludGVycHJldGFjacOzbiB5IGNvbmNsdXNpw7NuDQoNCioqSW5zaWdodCBwcmluY2lwYWw6IHVuIG1heW9yIG7Dum1lcm8gZGUgZGVudW5jaWFzIG5vIGltcGxpY2EgbmVjZXNhcmlhbWVudGUgdW5hIG1heW9yIHRhc2EgZGUgZGVsaXRvcy4qKiBFbCBlamVtcGxvIG3DoXMgcmVwcmVzZW50YXRpdm8gZXMgbGEgVVBaIGFzb2NpYWRhIGFsIEFlcm9wdWVydG8gRWwgRG9yYWRvLCBkb25kZSB1bmEgcG9ibGFjacOzbiByZXNpZGVudGUgcmVsYXRpdmFtZW50ZSBiYWphIHB1ZWRlIGdlbmVyYXIgdW5hIHRhc2EgZWxldmFkYSBjdWFuZG8gc2UgY29tcGFyYSBjb24gZWwgbsO6bWVybyBkZSBjYXNvcyByZWdpc3RyYWRvcyBlbiBlbCB0ZXJyaXRvcmlvLg0KDQpFc3RlIGNvbXBvcnRhbWllbnRvIHBsYW50ZWEgdW5hIGNvbnNpZGVyYWNpw7NuIGltcG9ydGFudGU6IGxhIHBvYmxhY2nDs24gcmVzaWRlbnRlIG5vIHNpZW1wcmUgcmVwcmVzZW50YSBsYSB0b3RhbGlkYWQgZGUgcGVyc29uYXMgZXhwdWVzdGFzIGEgbGFzIGRpbsOhbWljYXMgZGUgdW4gdGVycml0b3Jpby4gRW4gem9uYXMgY29tbyBlbCBhZXJvcHVlcnRvIGV4aXN0ZSB1biBmbHVqbyBpbXBvcnRhbnRlIGRlIHBlcnNvbmFzIHF1ZSB0cmFuc2l0YW4gZGlhcmlhbWVudGUsIHBlcm8gcXVlIG5vIG5lY2VzYXJpYW1lbnRlIHZpdmVuIGFsbMOtLiBFc3RhIHBvYmxhY2nDs24gZmxvdGFudGUgcG9kcsOtYSBjb250cmlidWlyIGEgZXhwbGljYXIgcG9yIHF1w6kgbG9zIHJlZ2lzdHJvcyBkZSBkZW51bmNpYXMgc29uIGVsZXZhZG9zIGVuIHByb3BvcmNpw7NuIGEgbG9zIGhhYml0YW50ZXMgcmVzaWRlbnRlcy4NCg0KUG9yIGxvIHRhbnRvLCB1dGlsaXphciBleGNsdXNpdmFtZW50ZSBlbCBuw7ptZXJvIGRlIGNhc29zIHB1ZWRlIG9jdWx0YXIgZGlmZXJlbmNpYXMgZW4gbGEgaW50ZW5zaWRhZCByZWxhdGl2YSBkZSBsb3MgcmVnaXN0cm9zLCBtaWVudHJhcyBxdWUgaW50ZXJwcmV0YXIgbGFzIHRhc2FzIHNpbiBjb25zaWRlcmFyIGVsIHRhbWHDsW8geSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBsYSBwb2JsYWNpw7NuIHB1ZWRlIGNvbmR1Y2lyIGEgY29uY2x1c2lvbmVzIGVxdWl2b2NhZGFzLg0KDQpFbiBjb25zZWN1ZW5jaWEsICoqbGEgbGVjdHVyYSBkZSBsYSBpbnNlZ3VyaWRhZCB0ZXJyaXRvcmlhbCBkZWJlIGNvbnNpZGVyYXIgY29uanVudGFtZW50ZSBsb3MgY2Fzb3MgYWJzb2x1dG9zLCBsYXMgdGFzYXMgcG9yIGhhYml0YW50ZSB5IGxhcyBkaW7DoW1pY2FzIHBhcnRpY3VsYXJlcyBkZSBjYWRhIHRlcnJpdG9yaW8qKi4gRWwgY2FzbyBkZWwgQWVyb3B1ZXJ0byBFbCBEb3JhZG8gZXZpZGVuY2lhIGxhIGltcG9ydGFuY2lhIGRlIGNvbnNpZGVyYXIgZmFjdG9yZXMgYWRpY2lvbmFsZXMsIGNvbW8gbGEgcG9ibGFjacOzbiBmbG90YW50ZSwgZW4gZnV0dXJvcyBhbsOhbGlzaXMuDQoNCiMjIyA3LjMuMi4gwr9Dw7NtbyBpbmZsdXllIGVsIHRhbWHDsW8gcG9ibGFjaW9uYWwgZW4gbGEgaW50ZXJwcmV0YWNpw7NuIGRlIGxhcyB0YXNhcyBkZSBkZWxpdG9zPw0KDQpMYSBzZWd1bmRhIHByZWd1bnRhIGJ1c2NhIGNvbXByZW5kZXIgY8OzbW8gaW5mbHV5ZSBlbCB0YW1hw7FvIGRlIGxhIHBvYmxhY2nDs24gcmVzaWRlbnRlIGVuIGxhIGludGVycHJldGFjacOzbiBkZSBsYXMgdGFzYXMgZGUgZGVsaXRvcyBkZSBsYXMgVVBaLg0KDQpDb21vIHNlIGV4cGxpY8OzIGFudGVyaW9ybWVudGUsIGxhIHRhc2Egc2UgY2FsY3VsYSByZWxhY2lvbmFuZG8gZWwgbsO6bWVybyBkZSBjYXNvcyBkZW51bmNpYWRvcyBjb24gbGEgcG9ibGFjacOzbiBkZSBjYWRhIHVuaWRhZCB0ZXJyaXRvcmlhbCwgZXhwcmVzYW5kbyBlbCByZXN1bHRhZG8gcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMuIFBvciBsbyB0YW50bywgY3VhbmRvIGVsIGRlbm9taW5hZG9yIGVzIHJlZHVjaWRvLCB1bmEgY2FudGlkYWQgcmVsYXRpdmFtZW50ZSBwZXF1ZcOxYSBkZSBkZW51bmNpYXMgcHVlZGUgZ2VuZXJhciB1bmEgdGFzYSBjb25zaWRlcmFibGVtZW50ZSBlbGV2YWRhLg0KDQpQYXJhIHByb2Z1bmRpemFyIGVuIGVzdGUgY29tcG9ydGFtaWVudG8gc2UgYW5hbGl6YSBsYSBkaXN0cmlidWNpw7NuIGRlIGxhIHBvYmxhY2nDs24sIHN1IHJlbGFjacOzbiBjb24gbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zIHkgbGFzIGNhcmFjdGVyw61zdGljYXMgZGUgbGFzIFVQWiBxdWUgcHJlc2VudGFuIHBvYmxhY2lvbmVzIG3DoXMgcGVxdWXDsWFzLg0KDQpFc3RlIGFuw6FsaXNpcyB0YW1iacOpbiBwZXJtaXRlIHJlY29ub2NlciB1bmEgbGltaXRhY2nDs24gZGVsIGluZGljYWRvcjogbGEgcG9ibGFjacOzbiByZXNpZGVudGUgbm8gbmVjZXNhcmlhbWVudGUgcmVwcmVzZW50YSBlbCB0b3RhbCBkZSBwZXJzb25hcyBxdWUgdXRpbGl6YW4gbyB0cmFuc2l0YW4gcG9yIHVuIHRlcnJpdG9yaW8uIEVuIHpvbmFzIGNvbiBhbHRhIGNpcmN1bGFjacOzbiBkZSBwb2JsYWNpw7NuIGZsb3RhbnRlLCBjb21vIGVsIEFlcm9wdWVydG8gRWwgRG9yYWRvLCBsb3MgcmVnaXN0cm9zIGRlIGRlbnVuY2lhcyBwdWVkZW4gZXN0YXIgcmVsYWNpb25hZG9zIGNvbiBkaW7DoW1pY2FzIHF1ZSBubyBxdWVkYW4gcmVwcmVzZW50YWRhcyBlbiBlbCBkZW5vbWluYWRvciBwb2JsYWNpb25hbC4NCg0KRW4gY29uc2VjdWVuY2lhLCBsYXMgdGFzYXMgZGViZW4gaW50ZXJwcmV0YXJzZSBjb25qdW50YW1lbnRlIGNvbiBsb3MgY2Fzb3MgYWJzb2x1dG9zLCBlbCB0YW1hw7FvIHBvYmxhY2lvbmFsIHkgbGFzIGNhcmFjdGVyw61zdGljYXMgcGFydGljdWxhcmVzIGRlIGNhZGEgdGVycml0b3Jpby4NCg0KYGBge3IgaGFsbGF6Z28tNzMyLWRpc3RyaWJ1Y2lvbi1wb2JsYWNpb24sIGVjaG89VFJVRX0NCiMgT3JkZW5hciBsYXMgVVBaIHNlZ8O6biBzdSBwb2JsYWNpw7NuDQoNCnVweiAlPiUNCiAgYXJyYW5nZShwb2JsYWNpb24pICU+JQ0KICBtdXRhdGUoDQogICAgdXB6X25vbWJyZSA9IGZhY3RvcigNCiAgICAgIHVwel9ub21icmUsDQogICAgICBsZXZlbHMgPSB1cHpfbm9tYnJlDQogICAgKQ0KICApICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKA0KICAgICAgeCA9IHBvYmxhY2lvbiwNCiAgICAgIHkgPSB1cHpfbm9tYnJlDQogICAgKQ0KICApICsNCiAgZ2VvbV9jb2woDQogICAgZmlsbCA9ICIjMTY4Qzg2IiwNCiAgICBhbHBoYSA9IDAuODUNCiAgKSArDQogIHNjYWxlX3hfbG9nMTAoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9jb21tYSgpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkxhIHBvYmxhY2nDs24gcmVzaWRlbnRlIHByZXNlbnRhIGRpZmVyZW5jaWFzIGltcG9ydGFudGVzIGVudHJlIFVQWiIsDQogICAgc3VidGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBoYWJpdGFudGVzIHBvciB1bmlkYWQgdGVycml0b3JpYWwiLA0KICAgIHggPSAiUG9ibGFjacOzbiByZXNpZGVudGUgKGVzY2FsYSBsb2dhcsOtdG1pY2EpIiwNCiAgICB5ID0gTlVMTA0KICApICsNCiAgdGVtYV9jbGFzZSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KQ0KICApDQpgYGANCg0KYGBge3IgaGFsbGF6Z28tNzMyLXBvYmxhY2lvbi10YXNhLCBlY2hvPVRSVUV9DQojIElkZW50aWZpY2FyIGVsIHByaW1lciBjdWFydGlsIGRlIHBvYmxhY2nDs24NCg0KbGltaXRlX3BvYmxhY2lvbl9iYWphIDwtIHF1YW50aWxlKA0KICB1cHokcG9ibGFjaW9uLA0KICAwLjI1LA0KICBuYS5ybSA9IFRSVUUNCikNCg0KIyBDbGFzaWZpY2FyIGxhcyBVUFogc2Vnw7puIHN1IHRhbWHDsW8gcG9ibGFjaW9uYWwNCg0KdXB6X2FuYWxpc2lzX3BvYmxhY2lvbmFsIDwtIHVweiAlPiUNCiAgbXV0YXRlKA0KICAgIEdydXBvX3BvYmxhY2lvbmFsID0gaWZfZWxzZSgNCiAgICAgIHBvYmxhY2lvbiA8PSBsaW1pdGVfcG9ibGFjaW9uX2JhamEsDQogICAgICAiUG9ibGFjacOzbiBlbiBlbCBjdWFydGlsIGluZmVyaW9yIiwNCiAgICAgICJSZXN0byBkZSBsYXMgVVBaIg0KICAgICkNCiAgKQ0KDQojIENvbnN0cnVpciBncsOhZmljbyBkZSBkaXNwZXJzacOzbg0KDQpnZ3Bsb3QoDQogIHVwel9hbmFsaXNpc19wb2JsYWNpb25hbCwNCiAgYWVzKA0KICAgIHggPSBwb2JsYWNpb24sDQogICAgeSA9IHRhc2FfdG90YWwsDQogICAgY29sb3IgPSBHcnVwb19wb2JsYWNpb25hbA0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBzaXplID0gMi43LA0KICAgIGFscGhhID0gMC44DQogICkgKw0KICBzY2FsZV94X2xvZzEwKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEoKQ0KICApICsNCiAgc2NhbGVfeV9sb2cxMCgNCiAgICBsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2NvbW1hKCkNCiAgKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKA0KICAgICAgIlBvYmxhY2nDs24gZW4gZWwgY3VhcnRpbCBpbmZlcmlvciIgPSAiI0Q5MDA2QyIsDQogICAgICAiUmVzdG8gZGUgbGFzIFVQWiIgPSAiIzE2OEM4NiINCiAgICApLA0KICAgIG5hbWUgPSAiVGFtYcOxbyBwb2JsYWNpb25hbCINCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiTGFzIHRhc2FzIGV4dHJlbWFzIGRlYmVuIGludGVycHJldGFyc2UgY29uc2lkZXJhbmRvIGxhIHBvYmxhY2nDs24iLA0KICAgIHN1YnRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBoYWJpdGFudGVzIHkgdGFzYSB0b3RhbCBkZSBkZWxpdG9zIHBvciBVUFoiLA0KICAgIHggPSAiUG9ibGFjacOzbiByZXNpZGVudGUgKGVzY2FsYSBsb2dhcsOtdG1pY2EpIiwNCiAgICB5ID0gIlRhc2EgcG9yIDEwLjAwMCBoYWJpdGFudGVzIChlc2NhbGEgbG9nYXLDrXRtaWNhKSIsDQogICAgY2FwdGlvbiA9ICJFbCBncnVwbyBwb2JsYWNpb25hbCBpbmZlcmlvciBjb3JyZXNwb25kZSBhbCAyNSUgZGUgbGFzIFVQWiBjb24gbWVub3IgcG9ibGFjacOzbi4iDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KYGBge3IgaGFsbGF6Z28tNzMyLXRhYmxhLWV4dHJlbW9zLCBlY2hvPVRSVUV9DQojIElkZW50aWZpY2FyIGxhcyAxNSBVUFogY29uIG1lbm9yIHBvYmxhY2nDs24NCg0KdGFibGFfcG9ibGFjaW9uX2JhamEgPC0gdXB6ICU+JQ0KICBhcnJhbmdlKHBvYmxhY2lvbikgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIHBvYmxhY2lvbiwNCiAgICBjYXNvc190b3RhbCwNCiAgICB0YXNhX3RvdGFsDQogICkgJT4lDQogIHNsaWNlX2hlYWQobiA9IDE1KQ0KDQprbml0cjo6a2FibGUoDQogIHRhYmxhX3BvYmxhY2lvbl9iYWphLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIlVQWiBjb24gbWVub3IgcG9ibGFjacOzbiB5IHN1cyByZXNwZWN0aXZvcyBpbmRpY2Fkb3JlcyBkZSBkZWxpdG9zIg0KKQ0KDQojIElkZW50aWZpY2FyIGxhcyAxNSBVUFogY29uIG1heW9yZXMgdGFzYXMNCg0KdGFibGFfdGFzYXNfYWx0YXMgPC0gdXB6ICU+JQ0KICBhcnJhbmdlKGRlc2ModGFzYV90b3RhbCkpICU+JQ0KICBzZWxlY3QoDQogICAgdXB6X25vbWJyZSwNCiAgICBwb2JsYWNpb24sDQogICAgY2Fzb3NfdG90YWwsDQogICAgdGFzYV90b3RhbA0KICApICU+JQ0KICBzbGljZV9oZWFkKG4gPSAxNSkNCg0Ka25pdHI6OmthYmxlKA0KICB0YWJsYV90YXNhc19hbHRhcywNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJVUFogY29uIG1heW9yZXMgdGFzYXMgZGUgZGVsaXRvcyB5IHN1cyByZXNwZWN0aXZvcyBpbmRpY2Fkb3JlcyINCikNCmBgYA0KDQojIyMjIEludGVycHJldGFjacOzbiB5IGNvbmNsdXNpw7NuDQoNCkVsIGFuw6FsaXNpcyBkZSBsYSBwb2JsYWNpw7NuIHkgbGFzIHRhc2FzIGRlIGRlbGl0b3MgcGVybWl0ZSByZWNvbm9jZXIgcXVlIGVsIHRhbWHDsW8gZGUgbGEgcG9ibGFjacOzbiByZXNpZGVudGUgdGllbmUgdW5hIGluZmx1ZW5jaWEgbWF0ZW3DoXRpY2EgZGlyZWN0YSBlbiBlbCB2YWxvciBkZWwgaW5kaWNhZG9yLiBDdWFuZG8gZWwgZGVub21pbmFkb3IgZXMgcmVkdWNpZG8sIGNhZGEgY2FzbyBhZGljaW9uYWwgcmVwcmVzZW50YSB1bmEgcHJvcG9yY2nDs24gbWF5b3IgeSBwdWVkZSBnZW5lcmFyIHZhcmlhY2lvbmVzIGltcG9ydGFudGVzIGVuIGxhIHRhc2EuDQoNCkVzdGUgY29tcG9ydGFtaWVudG8gc2UgZXZpZGVuY2lhIGVzcGVjaWFsbWVudGUgZW4gbGFzIFVQWiBjb24gcG9ibGFjaW9uZXMgcGVxdWXDsWFzLCBkb25kZSBsb3MgdmFsb3JlcyBkZWJlbiBpbnRlcnByZXRhcnNlIGp1bnRvIGNvbiBlbCBuw7ptZXJvIGFic29sdXRvIGRlIGRlbnVuY2lhcy4gTm8gc2Vyw61hIGFkZWN1YWRvIGFzdW1pciBxdWUgdW5hIHRhc2EgZWxldmFkYSByZXByZXNlbnRhIG5lY2VzYXJpYW1lbnRlIHVuYSBtYXlvciBjb25jZW50cmFjacOzbiBkZSBkZWxpdG9zIG8gdW4gbWF5b3Igcmllc2dvIHBhcmEgc3VzIGhhYml0YW50ZXMuDQoNCkFkaWNpb25hbG1lbnRlLCBlbCBjYXNvIGRlbCBBZXJvcHVlcnRvIEVsIERvcmFkbyBwZXJtaXRlIGlkZW50aWZpY2FyIG90cmEgbGltaXRhY2nDs246IGxhIHBvYmxhY2nDs24gcmVzaWRlbnRlIG5vIHNpZW1wcmUgcmVwcmVzZW50YSBsYSBjYW50aWRhZCBkZSBwZXJzb25hcyBxdWUgdXRpbGl6YW4gdW4gdGVycml0b3Jpby4gTGEgY2lyY3VsYWNpw7NuIGRlIHZpYWplcm9zLCB0cmFiYWphZG9yZXMgeSB2aXNpdGFudGVzIHB1ZWRlIGdlbmVyYXIgZGluw6FtaWNhcyBxdWUgbm8gcXVlZGFuIHJlZmxlamFkYXMgZW4gZWwgZGVub21pbmFkb3IgdXRpbGl6YWRvLg0KDQoqKkluc2lnaHQgcHJpbmNpcGFsOioqIExhIHRhc2EgcG9yIGhhYml0YW50ZSBlcyB1bmEgaGVycmFtaWVudGEgw7p0aWwgcGFyYSBjb21wYXJhciB0ZXJyaXRvcmlvcywgcGVybyBzdSBpbnRlcnByZXRhY2nDs24gZGVwZW5kZSBkZWwgdGFtYcOxbyB5IGxhcyBjYXJhY3RlcsOtc3RpY2FzIGRlIGxhIHBvYmxhY2nDs24gdXRpbGl6YWRhIGNvbW8gZGVub21pbmFkb3IuIEVuIGNvbnNlY3VlbmNpYSwgdW5hIHRhc2EgZWxldmFkYSBubyBkZWJlIGFuYWxpemFyc2UgZGUgbWFuZXJhIGFpc2xhZGE6IGVzIG5lY2VzYXJpbyBjb25zaWRlcmFyIGxvcyBjYXNvcyBhYnNvbHV0b3MsIGxhIHBvYmxhY2nDs24gcmVzaWRlbnRlIHkgbGFzIGRpbsOhbWljYXMgcGFydGljdWxhcmVzIGRlIGNhZGEgVVBaLg0KDQojIyMgNy4zLjMuIMK/UXXDqSBkaWZlcmVuY2lhcyB0ZXJyaXRvcmlhbGVzIHNlIG9ic2VydmFuIGVuIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGRlbGl0b3MgZGVudW5jaWFkb3M/DQoNCkVzdGEgcHJlZ3VudGEgYnVzY2EgaWRlbnRpZmljYXIgc2kgbG9zIGRlbGl0b3MgZGVudW5jaWFkb3MgcHJlc2VudGFuIGRpZmVyZW5jaWFzIHRlcnJpdG9yaWFsZXMgZW50cmUgbGFzIFVQWiBkZSBCb2dvdMOhIHkgcmVjb25vY2VyIGxhcyB6b25hcyBkb25kZSBzZSBjb25jZW50cmEgdW4gbWF5b3Igdm9sdW1lbiBkZSBjYXNvcyBvIHVuYSBtYXlvciBpbnRlbnNpZGFkIHJlbGF0aXZhIGRlIGRlbnVuY2lhcy4NCg0KUGFyYSBkZXNhcnJvbGxhciBlc3RlIGFuw6FsaXNpcyBzZSByZXRvbWFuIGxvcyBtYXBhcyB0ZW3DoXRpY29zIGNvbnN0cnVpZG9zIGVuIGxhIHNlY2Npw7NuIDYsIGVzcGVjaWFsbWVudGUgbGEgZGlzdHJpYnVjacOzbiBkZSBsb3MgY2Fzb3MgdG90YWxlcyB5IGRlIGxhcyB0YXNhcyBkZSBkZWxpdG9zIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzLiBFc3RhcyByZXByZXNlbnRhY2lvbmVzIHBlcm1pdGVuIG9ic2VydmFyIGxvcyBjb250cmFzdGVzIGVzcGFjaWFsZXMgeSByZWNvbm9jZXIgdW5pZGFkZXMgdGVycml0b3JpYWxlcyBjb24gY29tcG9ydGFtaWVudG9zIGRpZmVyZW5jaWFkb3MuDQoNCkFkaWNpb25hbG1lbnRlLCBzZSByZWFsaXphIHVuYSBjb25zb2xpZGFjacOzbiBkZSBsb3MgaW5kaWNhZG9yZXMgcG9yIGxvY2FsaWRhZCwgY29uIGVsIHByb3DDs3NpdG8gZGUgYW1wbGlhciBsYSBsZWN0dXJhIHRlcnJpdG9yaWFsIHkgY29tcGFyYXIgZWwgdm9sdW1lbiBkZSBkZW51bmNpYXMgeSBsYXMgdGFzYXMgYWdyZWdhZGFzIGVudHJlIGVzdGFzIHVuaWRhZGVzIGdlb2dyw6FmaWNhcy4NCg0KIyMjIyBEaXN0cmlidWNpw7NuIGVzcGFjaWFsIGRlIGxvcyBjYXNvcyB5IGxhcyB0YXNhcw0KDQpMb3MgbWFwYXMgcGVybWl0ZW4gb2JzZXJ2YXIgcXVlIGxhIGRpc3RyaWJ1Y2nDs24gdGVycml0b3JpYWwgZGUgbG9zIGRlbGl0b3MgcHVlZGUgcHJlc2VudGFyIGRpZmVyZW5jaWFzIGRlcGVuZGllbmRvIGRlbCBpbmRpY2Fkb3IgdXRpbGl6YWRvLiBNaWVudHJhcyBlbCBuw7ptZXJvIGRlIGNhc29zIG11ZXN0cmEgbGEgY29uY2VudHJhY2nDs24gYWJzb2x1dGEgZGUgbGFzIGRlbnVuY2lhcywgbGEgdGFzYSBwZXJtaXRlIGNvbXBhcmFyIHN1IG1hZ25pdHVkIGVuIHJlbGFjacOzbiBjb24gbGEgcG9ibGFjacOzbiByZXNpZGVudGUuDQoNCkxhIHJlcHJlc2VudGFjacOzbiBwb3IgcXVpbnRpbGVzIGNvbXBsZW1lbnRhIGVzdGEgbGVjdHVyYSBhbCBpZGVudGlmaWNhciBsYSBwb3NpY2nDs24gcmVsYXRpdmEgZGUgY2FkYSBVUFogZnJlbnRlIGFsIGNvbmp1bnRvIGFuYWxpemFkby4gUG9yIHN1IHBhcnRlLCBsYSBlc2NhbGEgbG9nYXLDrXRtaWNhIGZhY2lsaXRhIGxhIHZpc3VhbGl6YWNpw7NuIGRlIGxhcyBkaWZlcmVuY2lhcyBjdWFuZG8gZXhpc3RlbiB2YWxvcmVzIGV4dHJlbW9zLg0KDQojIyMjIENvbXBhcmFjacOzbiB0ZXJyaXRvcmlhbCBkZSBsb3MgaW5kaWNhZG9yZXMgcG9yIGxvY2FsaWRhZA0KDQpQYXJhIGFtcGxpYXIgbGEgaW50ZXJwcmV0YWNpw7NuIGVzcGFjaWFsLCBzZSBhZ3J1cGFuIGxvcyByZWdpc3Ryb3MgZGUgbGFzIFVQWiBzZWfDum4gbGEgbG9jYWxpZGFkIGEgbGEgcXVlIHBlcnRlbmVjZW4uIEVzdGEgY29uc29saWRhY2nDs24gcGVybWl0ZSBjb21wYXJhciBlbCB2b2x1bWVuIGRlIGRlbnVuY2lhcyB5IGxhIHRhc2EgYWdyZWdhZGEgZGUgZGVsaXRvcyBlbnRyZSBsYXMgZGlmZXJlbnRlcyBsb2NhbGlkYWRlcyBkZSBCb2dvdMOhLg0KDQpMYSB0YXNhIHBvciBsb2NhbGlkYWQgc2UgY2FsY3VsYSByZWxhY2lvbmFuZG8gbGEgc3VtYSBkZSBsb3MgY2Fzb3MgcmVnaXN0cmFkb3MgZW4gc3VzIFVQWiBjb24gbGEgcG9ibGFjacOzbiB0b3RhbCBjb3JyZXNwb25kaWVudGUuIERlIGVzdGEgbWFuZXJhLCBzZSBvYnRpZW5lIHVuIGluZGljYWRvciBwb25kZXJhZG8gcG9yIHBvYmxhY2nDs24sIGV2aXRhbmRvIGNhbGN1bGFyIGVsIHByb21lZGlvIHNpbXBsZSBkZSBsYXMgdGFzYXMgaW5kaXZpZHVhbGVzIGRlIGxhcyBVUFouDQoNCkVzdGEgY29tcGFyYWNpw7NuIHBlcm1pdGUgaWRlbnRpZmljYXIgZGlmZXJlbmNpYXMgdGVycml0b3JpYWxlcyBhIHVuYSBlc2NhbGEgbcOhcyBhbXBsaWEsIGF1bnF1ZSBkZWJlIGNvbnNpZGVyYXJzZSBxdWUgbGEgYWdyZWdhY2nDs24gcG9yIGxvY2FsaWRhZCBwdWVkZSBvY3VsdGFyIGNvbnRyYXN0ZXMgZXhpc3RlbnRlcyBlbnRyZSBsYXMgVVBaIHF1ZSBsYSBjb25mb3JtYW4uDQoNCmBgYHtyIGhhbGxhemdvLTczMy1pbmRpY2Fkb3Jlcy1sb2NhbGlkYWQsIGVjaG89VFJVRX0NCiMgQ29uc29saWRhciBsb3MgaW5kaWNhZG9yZXMgcG9yIGxvY2FsaWRhZA0KDQpyZXN1bWVuX2xvY2FsaWRhZGVzIDwtIHVweiAlPiUNCiAgZ3JvdXBfYnkobG9jYWxpZGFkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE51bWVyb19VUFogPSBuKCksDQogICAgUG9ibGFjaW9uX3RvdGFsID0gc3VtKHBvYmxhY2lvbiwgbmEucm0gPSBUUlVFKSwNCiAgICBDYXNvc190b3RhbCA9IHN1bShjYXNvc190b3RhbCwgbmEucm0gPSBUUlVFKSwNCiAgICBUYXNhX2FncmVnYWRhID0gKA0KICAgICAgc3VtKGNhc29zX3RvdGFsLCBuYS5ybSA9IFRSVUUpIC8NCiAgICAgIHN1bShwb2JsYWNpb24sIG5hLnJtID0gVFJVRSkNCiAgICApICogMTAwMDAsDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCiMgUmFua2luZyBwb3Igdm9sdW1lbiBkZSBkZW51bmNpYXMNCg0KcmFua2luZ19sb2NhbGlkYWRlc19jYXNvcyA8LSByZXN1bWVuX2xvY2FsaWRhZGVzICU+JQ0KICBhcnJhbmdlKGRlc2MoQ2Fzb3NfdG90YWwpKQ0KDQprbml0cjo6a2FibGUoDQogIHJhbmtpbmdfbG9jYWxpZGFkZXNfY2Fzb3MsDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiSW5kaWNhZG9yZXMgZGUgZGVsaXRvcyBkZW51bmNpYWRvcyBwb3IgbG9jYWxpZGFkIg0KKQ0KYGBgDQoNCmBgYHtyIGhhbGxhemdvLTczMy1ncmFmaWNvcy1sb2NhbGlkYWQsIGVjaG89VFJVRX0NCiMgR3LDoWZpY28gZGUgY2Fzb3MgdG90YWxlcyBwb3IgbG9jYWxpZGFkDQoNCmdncGxvdCgNCiAgcmVzdW1lbl9sb2NhbGlkYWRlcywNCiAgYWVzKA0KICAgIHggPSByZW9yZGVyKGxvY2FsaWRhZCwgQ2Fzb3NfdG90YWwpLA0KICAgIHkgPSBDYXNvc190b3RhbA0KICApDQopICsNCiAgZ2VvbV9jb2woDQogICAgZmlsbCA9ICIjMzUxQTRGIiwNCiAgICBhbHBoYSA9IDAuOQ0KICApICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEoKQ0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJDb25jZW50cmFjacOzbiBkZSBkZW51bmNpYXMgcG9yIGxvY2FsaWRhZCIsDQogICAgc3VidGl0bGUgPSAiTsO6bWVybyB0b3RhbCBkZSBjYXNvcyByZWdpc3RyYWRvcyIsDQogICAgeCA9IE5VTEwsDQogICAgeSA9ICJDYXNvcyBkZW51bmNpYWRvcyINCiAgKSArDQogIHRlbWFfY2xhc2UNCg0KIyBHcsOhZmljbyBkZSB0YXNhcyBhZ3JlZ2FkYXMgcG9yIGxvY2FsaWRhZA0KDQpnZ3Bsb3QoDQogIHJlc3VtZW5fbG9jYWxpZGFkZXMsDQogIGFlcygNCiAgICB4ID0gcmVvcmRlcihsb2NhbGlkYWQsIFRhc2FfYWdyZWdhZGEpLA0KICAgIHkgPSBUYXNhX2FncmVnYWRhDQogICkNCikgKw0KICBnZW9tX2NvbCgNCiAgICBmaWxsID0gIiNEOTAwNkMiLA0KICAgIGFscGhhID0gMC45DQogICkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9jb21tYShhY2N1cmFjeSA9IDAuMSkNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiSW50ZW5zaWRhZCByZWxhdGl2YSBkZSBsYXMgZGVudW5jaWFzIHBvciBsb2NhbGlkYWQiLA0KICAgIHN1YnRpdGxlID0gIlRhc2EgYWdyZWdhZGEgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMiLA0KICAgIHggPSBOVUxMLA0KICAgIHkgPSAiVGFzYSBwb3IgMTAuMDAwIGhhYml0YW50ZXMiDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KIyMjIyBJbnRlcnByZXRhY2nDs24geSBjb25jbHVzacOzbg0KDQpMYSByZXByZXNlbnRhY2nDs24gZ2VvZ3LDoWZpY2EgcGVybWl0ZSByZWNvbm9jZXIgZGlmZXJlbmNpYXMgdGVycml0b3JpYWxlcyBlbiBsYSBkaXN0cmlidWNpw7NuIGRlIGxhcyBkZW51bmNpYXMgcmVnaXN0cmFkYXMuIEFsIGNvbXBhcmFyIGxvcyBjYXNvcyBhYnNvbHV0b3MgY29uIGxhcyB0YXNhcywgc2UgZXZpZGVuY2lhIGxhIGltcG9ydGFuY2lhIGRlIHV0aWxpemFyIGFtYm9zIGluZGljYWRvcmVzIHBhcmEgY29tcHJlbmRlciBlbCBjb21wb3J0YW1pZW50byBkZSBsb3MgcmVnaXN0cm9zIGVuIGxhcyBkaWZlcmVudGVzIHVuaWRhZGVzIHRlcnJpdG9yaWFsZXMuDQoNCkxhIGNvbnNvbGlkYWNpw7NuIHBvciBsb2NhbGlkYWQgcGVybWl0ZSBhbXBsaWFyIGxhIGxlY3R1cmEgdGVycml0b3JpYWwsIHBlcm8gdGFtYmnDqW4gcHVlZGUgb2N1bHRhciBkaWZlcmVuY2lhcyBlbnRyZSBsYXMgVVBaIHF1ZSBjb25mb3JtYW4gY2FkYSBsb2NhbGlkYWQuIFBvciBlc3RhIHJhesOzbiwgcmVzdWx0YSBpbXBvcnRhbnRlIGNvbnNlcnZhciBlbCBhbsOhbGlzaXMgYSBlc2NhbGEgZGUgVVBaIHkgdXRpbGl6YXIgbGEgbG9jYWxpZGFkIGNvbW8gdW4gbml2ZWwgY29tcGxlbWVudGFyaW8gZGUgaW50ZXJwcmV0YWNpw7NuLg0KDQoqKkluc2lnaHQgcHJpbmNpcGFsOioqIExhIGluc2VndXJpZGFkIHJlZ2lzdHJhZGEgZW4gQm9nb3TDoSBubyBwcmVzZW50YSB1bmEgw7puaWNhIGxlY3R1cmEgdGVycml0b3JpYWwuIExhIGlkZW50aWZpY2FjacOzbiBkZSBsYXMgem9uYXMgY29uIG1heW9yIGNvbmNlbnRyYWNpw7NuIGRlIGRlbnVuY2lhcyBwdWVkZSBzZXIgZGlmZXJlbnRlIGRlIGxhIGlkZW50aWZpY2FjacOzbiBkZSBhcXVlbGxhcyBjb24gbWF5b3JlcyB0YXNhcyByZWxhdGl2YXMuIFBvciBlbGxvLCBsYSBlc2NhbGEgZ2VvZ3LDoWZpY2EgeSBlbCBpbmRpY2Fkb3IgdXRpbGl6YWRvIGNvbmRpY2lvbmFuIGxhIGludGVycHJldGFjacOzbiBkZSBsb3MgcmVzdWx0YWRvcy4NCg0KIyMjIDcuMy40LiDCv0V4aXN0ZSBhbGd1bmEgYXNvY2lhY2nDs24gZW50cmUgZWwgYWx1bWJyYWRvIHDDumJsaWNvIHkgbGFzIHRhc2FzIGRlIGRlbGl0b3M/DQoNCkVzdGEgcHJlZ3VudGEgYnVzY2EgZXhwbG9yYXIgc2kgbGEgZGlzcG9uaWJpbGlkYWQgeSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZWwgYWx1bWJyYWRvIHDDumJsaWNvIHByZXNlbnRhbiBhbGd1bmEgYXNvY2lhY2nDs24gY29uIGxhcyB0YXNhcyBkZSBkZWxpdG9zIGRlbnVuY2lhZG9zIGVuIGxhcyBVUFogZGUgQm9nb3TDoS4NCg0KUGFyYSBkZXNhcnJvbGxhciBlbCBhbsOhbGlzaXMgc2UgY29uc2lkZXJhbiB0cmVzIGluZGljYWRvcmVzOiBsYSBjYW50aWRhZCBkZSBsdW1pbmFyaWFzIHBvciBraWzDs21ldHJvIGN1YWRyYWRvLCBsYSBjYW50aWRhZCBkZSBsdW1pbmFyaWFzIHBvciBjYWRhIDEuMDAwIGhhYml0YW50ZXMgeSBlbCBwb3JjZW50YWplIGRlIGx1bWluYXJpYXMgY29uIHRlY25vbG9nw61hIExFRC4NCg0KTGEgdXRpbGl6YWNpw7NuIGRlIGVzdGFzIHZhcmlhYmxlcyBwZXJtaXRlIGFuYWxpemFyIGVsIGFsdW1icmFkbyBkZXNkZSBkaWZlcmVudGVzIGRpbWVuc2lvbmVzLCBjb25zaWRlcmFuZG8gdGFudG8gc3UgZGlzdHJpYnVjacOzbiB0ZXJyaXRvcmlhbCBjb21vIHN1IGRpc3BvbmliaWxpZGFkIHJlbGF0aXZhIGZyZW50ZSBhIGxhIHBvYmxhY2nDs24geSBzdSBjb21wb3NpY2nDs24gdGVjbm9sw7NnaWNhLg0KDQpTZSBjb21wYXJhbiBlc3RvcyBpbmRpY2Fkb3JlcyBjb24gbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzLCBtZWRpYW50ZSBncsOhZmljb3MgZGUgZGlzcGVyc2nDs24geSBjb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuLiBFbCBwcm9ww7NzaXRvIGVzIGlkZW50aWZpY2FyIHBvc2libGVzIHBhdHJvbmVzIHkgZGlmZXJlbmNpYXMgZW50cmUgbGFzIHVuaWRhZGVzIHRlcnJpdG9yaWFsZXMuDQoNCmBgYHtyIGhhbGxhemdvLTczNC1sdW1pbmFyaWFzLXN1cGVyZmljaWUsIGVjaG89VFJVRX0NCmdncGxvdCgNCiAgdXB6LA0KICBhZXMoDQogICAgeCA9IGx1bWluYXJpYXNfa20yLA0KICAgIHkgPSB0YXNhX3RvdGFsDQogICkNCikgKw0KICBnZW9tX3BvaW50KA0KICAgIGNvbG9yID0gIiMxNjhDODYiLA0KICAgIGFscGhhID0gMC43NSwNCiAgICBzaXplID0gMi41DQogICkgKw0KICBzY2FsZV94X2xvZzEwKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEoKQ0KICApICsNCiAgc2NhbGVfeV9sb2cxMCgNCiAgICBsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2NvbW1hKCkNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzcG9uaWJpbGlkYWQgZXNwYWNpYWwgZGUgYWx1bWJyYWRvIHkgdGFzYSBkZSBkZWxpdG9zIiwNCiAgICBzdWJ0aXRsZSA9ICJMdW1pbmFyaWFzIHBvciBrbcKyIGZyZW50ZSBhIGRlbnVuY2lhcyBwb3IgY2FkYSAxMC4wMDAgaGFiaXRhbnRlcyIsDQogICAgeCA9ICJMdW1pbmFyaWFzIHBvciBrbcKyIChlc2NhbGEgbG9nYXLDrXRtaWNhKSIsDQogICAgeSA9ICJUYXNhIGRlIGRlbGl0b3MgKGVzY2FsYSBsb2dhcsOtdG1pY2EpIg0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQoNCmBgYHtyIGhhbGxhemdvLTczNC1sdW1pbmFyaWFzLXBvYmxhY2lvbiwgZWNobz1UUlVFfQ0KZ2dwbG90KA0KICB1cHosDQogIGFlcygNCiAgICB4ID0gbHVtaW5hcmlhc18xMDAwaGFiLA0KICAgIHkgPSB0YXNhX3RvdGFsDQogICkNCikgKw0KICBnZW9tX3BvaW50KA0KICAgIGNvbG9yID0gIiNEOTAwNkMiLA0KICAgIGFscGhhID0gMC43NSwNCiAgICBzaXplID0gMi41DQogICkgKw0KICBzY2FsZV94X2xvZzEwKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEoKQ0KICApICsNCiAgc2NhbGVfeV9sb2cxMCgNCiAgICBsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2NvbW1hKCkNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQWx1bWJyYWRvIHBvciBoYWJpdGFudGUgeSB0YXNhIGRlIGRlbGl0b3MiLA0KICAgIHN1YnRpdGxlID0gIkRpc3BvbmliaWxpZGFkIGRlIGx1bWluYXJpYXMgcG9yIGNhZGEgMS4wMDAgaGFiaXRhbnRlcyIsDQogICAgeCA9ICJMdW1pbmFyaWFzIHBvciBjYWRhIDEuMDAwIGhhYml0YW50ZXMgKGVzY2FsYSBsb2dhcsOtdG1pY2EpIiwNCiAgICB5ID0gIlRhc2EgZGUgZGVsaXRvcyAoZXNjYWxhIGxvZ2Fyw610bWljYSkiDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KYGBge3IgaGFsbGF6Z28tNzM0LWxlZC10YXNhLCBlY2hvPVRSVUV9DQpnZ3Bsb3QoDQogIHVweiwNCiAgYWVzKA0KICAgIHggPSBwY3RfbHVtaW5hcmlhc19sZWQsDQogICAgeSA9IHRhc2FfdG90YWwNCiAgKQ0KKSArDQogIGdlb21fcG9pbnQoDQogICAgY29sb3IgPSAiIzM1MUE0RiIsDQogICAgYWxwaGEgPSAwLjc1LA0KICAgIHNpemUgPSAyLjUNCiAgKSArDQogIHNjYWxlX3lfbG9nMTAoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9jb21tYSgpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBhcnRpY2lwYWNpw7NuIGRlIGx1bWluYXJpYXMgTEVEIHkgdGFzYSBkZSBkZWxpdG9zIiwNCiAgICBzdWJ0aXRsZSA9ICJQb3JjZW50YWplIGRlIGx1bWluYXJpYXMgTEVEIHBvciBVUFoiLA0KICAgIHggPSAiTHVtaW5hcmlhcyBMRUQgKCUpIiwNCiAgICB5ID0gIlRhc2EgZGUgZGVsaXRvcyAoZXNjYWxhIGxvZ2Fyw610bWljYSkiDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KUGFyYSBjb21wbGVtZW50YXIgbGEgZXhwbG9yYWNpw7NuIHZpc3VhbCwgc2UgY2FsY3VsYW4gbGFzIGNvcnJlbGFjaW9uZXMgZGUgU3BlYXJtYW4gZW50cmUgbG9zIHRyZXMgaW5kaWNhZG9yZXMgZGUgYWx1bWJyYWRvIHDDumJsaWNvIHkgbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zLg0KDQpFc3RhIGNvbXBhcmFjacOzbiBwZXJtaXRlIGlkZW50aWZpY2FyIGxhIGRpcmVjY2nDs24geSBsYSBpbnRlbnNpZGFkIGRlIGxhcyBhc29jaWFjaW9uZXMgbW9ub3TDs25pY2FzIGVudHJlIGxhcyB2YXJpYWJsZXMsIGZhY2lsaXRhbmRvIHVuYSBsZWN0dXJhIGNvbmp1bnRhIGRlIGxhcyBkaWZlcmVudGVzIGRpbWVuc2lvbmVzIGRlIGxhIGluZnJhZXN0cnVjdHVyYSBkZSBpbHVtaW5hY2nDs24uDQoNCmBgYHtyIGhhbGxhemdvLTczNC1jb3JyZWxhY2lvbmVzLWFsdW1icmFkbywgZWNobz1UUlVFfQ0KdmFyaWFibGVzX2FsdW1icmFkbyA8LSBjKA0KICAibHVtaW5hcmlhc19rbTIiLA0KICAibHVtaW5hcmlhc18xMDAwaGFiIiwNCiAgInBjdF9sdW1pbmFyaWFzX2xlZCINCikNCg0KY29ycmVsYWNpb25lc19hbHVtYnJhZG8gPC0gcHVycnI6Om1hcF9kZnIoDQogIHZhcmlhYmxlc19hbHVtYnJhZG8sDQogIGZ1bmN0aW9uKHZhcmlhYmxlKSB7DQoNCiAgICBkYXRvc192YWxpZG9zIDwtIHVweiAlPiUNCiAgICAgIHNlbGVjdCgNCiAgICAgICAgdGFzYV90b3RhbCwNCiAgICAgICAgYWxsX29mKHZhcmlhYmxlKQ0KICAgICAgKSAlPiUNCiAgICAgIGRyb3BfbmEoKQ0KDQogICAgdGliYmxlKA0KICAgICAgSW5kaWNhZG9yID0gdmFyaWFibGUsDQogICAgICBOdW1lcm9fVVBaID0gbnJvdyhkYXRvc192YWxpZG9zKSwNCiAgICAgIHJobyA9IGNvcigNCiAgICAgICAgZGF0b3NfdmFsaWRvcyR0YXNhX3RvdGFsLA0KICAgICAgICBkYXRvc192YWxpZG9zW1t2YXJpYWJsZV1dLA0KICAgICAgICBtZXRob2QgPSAic3BlYXJtYW4iDQogICAgICApDQogICAgKQ0KICB9DQopICU+JQ0KICBtdXRhdGUoDQogICAgSW5kaWNhZG9yID0gcmVjb2RlKA0KICAgICAgSW5kaWNhZG9yLA0KICAgICAgbHVtaW5hcmlhc19rbTIgPSAiTHVtaW5hcmlhcyBwb3Iga23CsiIsDQogICAgICBsdW1pbmFyaWFzXzEwMDBoYWIgPSAiTHVtaW5hcmlhcyBwb3IgMS4wMDAgaGFiaXRhbnRlcyIsDQogICAgICBwY3RfbHVtaW5hcmlhc19sZWQgPSAiUG9yY2VudGFqZSBkZSBsdW1pbmFyaWFzIExFRCINCiAgICApLA0KICAgIERpcmVjY2lvbiA9IGlmX2Vsc2UoDQogICAgICByaG8gPj0gMCwNCiAgICAgICJQb3NpdGl2YSIsDQogICAgICAiTmVnYXRpdmEiDQogICAgKSwNCiAgICBJbnRlbnNpZGFkID0gY2FzZV93aGVuKA0KICAgICAgYWJzKHJobykgPCAwLjIwIH4gIk11eSBkw6liaWwiLA0KICAgICAgYWJzKHJobykgPCAwLjQwIH4gIkTDqWJpbCIsDQogICAgICBhYnMocmhvKSA8IDAuNjAgfiAiTW9kZXJhZGEiLA0KICAgICAgYWJzKHJobykgPCAwLjgwIH4gIkZ1ZXJ0ZSIsDQogICAgICBUUlVFIH4gIk11eSBmdWVydGUiDQogICAgKQ0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MoYWJzKHJobykpKQ0KDQprbml0cjo6a2FibGUoDQogIGNvcnJlbGFjaW9uZXNfYWx1bWJyYWRvLA0KICBkaWdpdHMgPSAzLA0KICBjYXB0aW9uID0gIkNvcnJlbGFjaW9uZXMgZGUgU3BlYXJtYW4gZW50cmUgYWx1bWJyYWRvIHDDumJsaWNvIHkgdGFzYSBkZSBkZWxpdG9zIg0KKQ0KYGBgDQoNCiMjIyMgSW50ZXJwcmV0YWNpw7NuIHkgY29uY2x1c2nDs24NCg0KQWwgY29tcGFyYXIgbG9zIGluZGljYWRvcmVzIGRlIGFsdW1icmFkbyBww7pibGljbyBjb24gbGFzIHRhc2FzIGRlIGRlbGl0b3MsIG5vIHNlIGlkZW50aWZpY2EgdW5hIHJlbGFjacOzbiB2aXN1YWwgbmVnYXRpdmEgY2xhcmEgcXVlIHBlcm1pdGEgYWZpcm1hciBxdWUgdW5hIG1heW9yIGRpc3BvbmliaWxpZGFkIGRlIGx1bWluYXJpYXMgZXN0w6kgYXNvY2lhZGEgY29uIG1lbm9yZXMgdGFzYXMgZGUgZGVudW5jaWFzLg0KDQpFbiBlbCBncsOhZmljbyBkZSBsdW1pbmFyaWFzIHBvciBraWzDs21ldHJvIGN1YWRyYWRvIHNlIG9ic2VydmEgdW5hIGNvbmNlbnRyYWNpw7NuIGltcG9ydGFudGUgZGUgVVBaIGVuIG5pdmVsZXMgcmVsYXRpdmFtZW50ZSBhbHRvcyBkZSBkaXNwb25pYmlsaWRhZCBlc3BhY2lhbCBkZSBhbHVtYnJhZG8sIG1pZW50cmFzIHF1ZSBsYXMgdGFzYXMgZGUgZGVsaXRvcyBwcmVzZW50YW4gdW5hIGRpc3BlcnNpw7NuIGNvbnNpZGVyYWJsZS4gRXN0byBpbmRpY2EgcXVlIHVuYSBtYXlvciBjYW50aWRhZCBkZSBsdW1pbmFyaWFzIHBvciBzdXBlcmZpY2llIG5vIHNlIHRyYWR1Y2UgbmVjZXNhcmlhbWVudGUgZW4gdW5hIG1lbm9yIHRhc2EgZGUgZGVsaXRvcy4NCg0KUG9yIG90cmEgcGFydGUsIGVuIGVsIGdyw6FmaWNvIGRlIGx1bWluYXJpYXMgcG9yIGNhZGEgMS4wMDAgaGFiaXRhbnRlcyBzZSBhcHJlY2lhIHVuYSBwb3NpYmxlIHRlbmRlbmNpYSBwb3NpdGl2YSwgZG9uZGUgYWxndW5hcyBVUFogY29uIG1heW9yIGRpc3BvbmliaWxpZGFkIHJlbGF0aXZhIGRlIGx1bWluYXJpYXMgdGFtYmnDqW4gcHJlc2VudGFuIHRhc2FzIGVsZXZhZGFzLiBTaW4gZW1iYXJnbywgZXN0ZSBjb21wb3J0YW1pZW50byBkZWJlIGludGVycHJldGFyc2UgY29uIHByZWNhdWNpw7NuLCBkZWJpZG8gYSBsYSBwcmVzZW5jaWEgZGUgdmFsb3JlcyBleHRyZW1vcyB5IGEgcXVlIGVsIGluZGljYWRvciBwdWVkZSBhbXBsaWZpY2Fyc2UgZW4gdGVycml0b3Jpb3MgY29uIHBvYmxhY2lvbmVzIHJlc2lkZW50ZXMgcmVkdWNpZGFzLg0KDQpVbiBhc3BlY3RvIGludGVyZXNhbnRlIGVzIHF1ZSBsYSByZWxhY2nDs24gb2JzZXJ2YWRhIHRhbWJpw6luIHBvZHLDrWEgcGxhbnRlYXIgdW5hIGhpcMOzdGVzaXMgZGUgcmVzcHVlc3RhIGluc3RpdHVjaW9uYWw6IGxvcyB0ZXJyaXRvcmlvcyBxdWUgcHJlc2VudGFuIG1heW9yZXMgZGluw6FtaWNhcyBkZSBhY3RpdmlkYWQsIGNpcmN1bGFjacOzbiBkZSBwZXJzb25hcyBvIHByb2JsZW3DoXRpY2FzIGRlIHNlZ3VyaWRhZCBwb2Ryw61hbiByZWNpYmlyIHVuYSBtYXlvciBkb3RhY2nDs24gZGUgaW5mcmFlc3RydWN0dXJhIGRlIGlsdW1pbmFjacOzbi4gTm8gb2JzdGFudGUsIGxhIGluZm9ybWFjacOzbiBkaXNwb25pYmxlIG5vIHBlcm1pdGUgY29tcHJvYmFyIGVzdGEgaGlww7N0ZXNpcyBuaSBlc3RhYmxlY2VyIHNpIGxhIGluZnJhZXN0cnVjdHVyYSBwcmVjZWRlIG8gcmVzcG9uZGUgYSBsYXMgY29uZGljaW9uZXMgZGUgc2VndXJpZGFkLg0KDQoqKkluc2lnaHQgcHJpbmNpcGFsOioqIFVuYSBtYXlvciBkaXNwb25pYmlsaWRhZCBkZSBhbHVtYnJhZG8gcMO6YmxpY28gbm8gaW1wbGljYSBkaXJlY3RhbWVudGUgbWVub3JlcyB0YXNhcyBkZSBkZWxpdG9zLiBMb3MgcmVzdWx0YWRvcyBtdWVzdHJhbiBxdWUgbGEgcmVsYWNpw7NuIGVudHJlIGlsdW1pbmFjacOzbiB5IHNlZ3VyaWRhZCBlcyBtw6FzIGNvbXBsZWphIGRlIGxvIHF1ZSBwb2Ryw61hIHN1cG9uZXJzZSBpbmljaWFsbWVudGUuIEluY2x1c28sIGxhIHBvc2libGUgYXNvY2lhY2nDs24gcG9zaXRpdmEgZW50cmUgbHVtaW5hcmlhcyBwb3IgaGFiaXRhbnRlIHkgdGFzYXMgZGUgZGVsaXRvcyBwbGFudGVhIGxhIG5lY2VzaWRhZCBkZSBlc3R1ZGlhciBzaSBsYSBpbmZyYWVzdHJ1Y3R1cmEgcmVzcG9uZGUgYSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyB5IG5lY2VzaWRhZGVzIGRlIGNhZGEgdGVycml0b3JpbywgZW4gbHVnYXIgZGUgaW50ZXJwcmV0YXIgbGEgaWx1bWluYWNpw7NuIGNvbW8gdW4gZmFjdG9yIHF1ZSBwb3Igc8OtIHNvbG8gZGV0ZXJtaW5hIGxvcyBuaXZlbGVzIGRlIHNlZ3VyaWRhZC4NCg0KIyMjIDcuMy41LiDCv1F1w6kgcmVsYWNpw7NuIGV4aXN0ZSBlbnRyZSBsYXMgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcyB5IGxvcyBkZWxpdG9zIGRlbnVuY2lhZG9zPw0KDQpFc3RhIHByZWd1bnRhIGJ1c2NhIGV4cGxvcmFyIHNpIGxhcyBkaWZlcmVuY2lhcyBzb2Npb2Vjb27Ds21pY2FzIGVudHJlIGxhcyBVUFogcHJlc2VudGFuIGFsZ3VuYSBhc29jaWFjacOzbiBjb24gbG9zIGluZGljYWRvcmVzIGRlIGRlbGl0b3MgZGVudW5jaWFkb3MuDQoNClBhcmEgZGVzYXJyb2xsYXIgZWwgYW7DoWxpc2lzIHNlIGNvbnNpZGVyYW4gdHJlcyBkaW1lbnNpb25lczogZWwgcG9yY2VudGFqZSBkZSBwb2JsYWNpw7NuIGVuIGNvbmRpY2nDs24gZGUgcG9icmV6YSwgZWwgc2FsYXJpbyBtZW5zdWFsIHByb21lZGlvIHkgbGEgY29tcG9zaWNpw7NuIGRlIGxhcyB2aXZpZW5kYXMgc2Vnw7puIHJhbmdvcyBkZSBlc3RyYXRvIHNvY2lvZWNvbsOzbWljby4NCg0KRW4gcHJpbWVyIGx1Z2FyLCBzZSBleGFtaW5hIGxhIHJlbGFjacOzbiBlbnRyZSBlc3RhcyB2YXJpYWJsZXMgeSBsYSB0YXNhIHRvdGFsIGRlIGRlbGl0b3MgcG9yIGNhZGEgMTAuMDAwIGhhYml0YW50ZXMuIFBvc3Rlcmlvcm1lbnRlLCBzZSBleHBsb3JhIHNpIGVsIHRpcG8gZGUgZGVsaXRvIHByZWRvbWluYW50ZSBwcmVzZW50YSBkaWZlcmVuY2lhcyBlbnRyZSB0ZXJyaXRvcmlvcyBjb24gZGlzdGludGFzIGNhcmFjdGVyw61zdGljYXMgc29jaW9lY29uw7NtaWNhcy4NCg0KRXN0ZSBhbsOhbGlzaXMgcGVybWl0ZSBhbXBsaWFyIGxhIGludGVycHJldGFjacOzbiBkZSBsYSBpbnNlZ3VyaWRhZCB0ZXJyaXRvcmlhbCwgY29uc2lkZXJhbmRvIHF1ZSBsYXMgVVBaIHByZXNlbnRhbiBjb25kaWNpb25lcyBkZSB2aWRhIHkgZXN0cnVjdHVyYXMgc29jaW9lY29uw7NtaWNhcyBkaWZlcmVudGVzLg0KDQpgYGB7ciBoYWxsYXpnby03MzUtcG9icmV6YS1kZWxpdG9zLCBlY2hvPVRSVUV9DQpnZ3Bsb3QoDQogIHVweiwNCiAgYWVzKA0KICAgIHggPSBwY3RfcG9icmV6YSwNCiAgICB5ID0gdGFzYV90b3RhbCwNCiAgICBjb2xvciA9IGVtX2FncnVwYWRhDQogICkNCikgKw0KICBnZW9tX3BvaW50KA0KICAgIGFscGhhID0gMC43NSwNCiAgICBzaXplID0gMi41DQogICkgKw0KICBzY2FsZV95X2xvZzEwKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEoKQ0KICApICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoDQogICAgICAiRkFMU0UiID0gIiMxNjhDODYiLA0KICAgICAgIlRSVUUiID0gIiNEOTAwNkMiDQogICAgKSwNCiAgICBsYWJlbHMgPSBjKA0KICAgICAgIkZBTFNFIiA9ICJFc3RpbWFjacOzbiBpbmRpdmlkdWFsIiwNCiAgICAgICJUUlVFIiA9ICJFc3RpbWFjacOzbiBhZ3J1cGFkYSINCiAgICApLA0KICAgIG5hbWUgPSAiVGlwbyBkZSBlc3RpbWFjacOzbiINCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUG9icmV6YSB5IHRhc2EgZGUgZGVsaXRvcyBwb3IgVVBaIiwNCiAgICBzdWJ0aXRsZSA9ICJDb21wYXJhY2nDs24gZW50cmUgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcyB5IGRlbnVuY2lhcyIsDQogICAgeCA9ICJQb2JsYWNpw7NuIGVuIGNvbmRpY2nDs24gZGUgcG9icmV6YSAoJSkiLA0KICAgIHkgPSAiVGFzYSBkZSBkZWxpdG9zIHBvciAxMC4wMDAgaGFiaXRhbnRlcyAoZXNjYWxhIGxvZ2Fyw610bWljYSkiDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KYGBge3IgaGFsbGF6Z28tNzM1LXNhbGFyaW8tZGVsaXRvcywgZWNobz1UUlVFfQ0KZ2dwbG90KA0KICB1cHosDQogIGFlcygNCiAgICB4ID0gc2FsYXJpb19wcm9tZWRpbywNCiAgICB5ID0gdGFzYV90b3RhbCwNCiAgICBjb2xvciA9IGVtX2FncnVwYWRhDQogICkNCikgKw0KICBnZW9tX3BvaW50KA0KICAgIGFscGhhID0gMC43NSwNCiAgICBzaXplID0gMi41DQogICkgKw0KICBzY2FsZV94X2xvZzEwKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEocHJlZml4ID0gIiQiKQ0KICApICsNCiAgc2NhbGVfeV9sb2cxMCgNCiAgICBsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2NvbW1hKCkNCiAgKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKA0KICAgICAgIkZBTFNFIiA9ICIjMTY4Qzg2IiwNCiAgICAgICJUUlVFIiA9ICIjRDkwMDZDIg0KICAgICksDQogICAgbGFiZWxzID0gYygNCiAgICAgICJGQUxTRSIgPSAiRXN0aW1hY2nDs24gaW5kaXZpZHVhbCIsDQogICAgICAiVFJVRSIgPSAiRXN0aW1hY2nDs24gYWdydXBhZGEiDQogICAgKSwNCiAgICBuYW1lID0gIlRpcG8gZGUgZXN0aW1hY2nDs24iDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlNhbGFyaW8gcHJvbWVkaW8geSB0YXNhIGRlIGRlbGl0b3MgcG9yIFVQWiIsDQogICAgc3VidGl0bGUgPSAiUmVsYWNpw7NuIGVudHJlIGluZ3Jlc28gcHJvbWVkaW8geSBkZW51bmNpYXMgcmVnaXN0cmFkYXMiLA0KICAgIHggPSAiU2FsYXJpbyBtZW5zdWFsIHByb21lZGlvIChlc2NhbGEgbG9nYXLDrXRtaWNhKSIsDQogICAgeSA9ICJUYXNhIGRlIGRlbGl0b3MgcG9yIDEwLjAwMCBoYWJpdGFudGVzIChlc2NhbGEgbG9nYXLDrXRtaWNhKSINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQpgYGB7ciBoYWxsYXpnby03MzUtZXN0cmF0b3MtZGVsaXRvcywgZWNobz1UUlVFfQ0KIyBUcmFuc2Zvcm1hciBsYSBjb21wb3NpY2nDs24gcG9yIGVzdHJhdG8gYSBmb3JtYXRvIGxhcmdvDQoNCmRhdG9zX2VzdHJhdG9zIDwtIHVweiAlPiUNCiAgc2VsZWN0KA0KICAgIHVwel9ub21icmUsDQogICAgdGFzYV90b3RhbCwNCiAgICBwY3RfZXN0cmF0b18xXzIsDQogICAgcGN0X2VzdHJhdG9fM180LA0KICAgIHBjdF9lc3RyYXRvXzVfNg0KICApICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IHN0YXJ0c193aXRoKCJwY3RfZXN0cmF0byIpLA0KICAgIG5hbWVzX3RvID0gIkVzdHJhdG8iLA0KICAgIHZhbHVlc190byA9ICJQb3JjZW50YWplIg0KICApICU+JQ0KICBtdXRhdGUoDQogICAgRXN0cmF0byA9IHJlY29kZSgNCiAgICAgIEVzdHJhdG8sDQogICAgICBwY3RfZXN0cmF0b18xXzIgPSAiRXN0cmF0b3MgMSB5IDIiLA0KICAgICAgcGN0X2VzdHJhdG9fM180ID0gIkVzdHJhdG9zIDMgeSA0IiwNCiAgICAgIHBjdF9lc3RyYXRvXzVfNiA9ICJFc3RyYXRvcyA1IHkgNiINCiAgICApDQogICkNCg0KIyBDb21wYXJhciBjb21wb3NpY2nDs24gc29jaW9lY29uw7NtaWNhIHkgdGFzYSBkZSBkZWxpdG9zDQoNCmdncGxvdCgNCiAgZGF0b3NfZXN0cmF0b3MsDQogIGFlcygNCiAgICB4ID0gUG9yY2VudGFqZSwNCiAgICB5ID0gdGFzYV90b3RhbA0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBjb2xvciA9ICIjMTY4Qzg2IiwNCiAgICBhbHBoYSA9IDAuNjUsDQogICAgc2l6ZSA9IDINCiAgKSArDQogIHNjYWxlX3lfbG9nMTAoDQogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9jb21tYSgpDQogICkgKw0KICBmYWNldF93cmFwKA0KICAgIH4gRXN0cmF0bywNCiAgICBuY29sID0gMSwNCiAgICBzY2FsZXMgPSAiZnJlZV94Ig0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJDb21wb3NpY2nDs24gcG9yIGVzdHJhdG8geSB0YXNhIGRlIGRlbGl0b3MiLA0KICAgIHN1YnRpdGxlID0gIlBhcnRpY2lwYWNpw7NuIHBvcmNlbnR1YWwgZGUgdml2aWVuZGFzIHBvciByYW5nbyBkZSBlc3RyYXRvIiwNCiAgICB4ID0gIlZpdmllbmRhcyBkZWwgcmFuZ28gZGUgZXN0cmF0byAoJSkiLA0KICAgIHkgPSAiVGFzYSBkZSBkZWxpdG9zIHBvciAxMC4wMDAgaGFiaXRhbnRlcyAoZXNjYWxhIGxvZ2Fyw610bWljYSkiDQogICkgKw0KICB0ZW1hX2NsYXNlDQpgYGANCg0KYGBge3IgaGFsbGF6Z28tNzM1LWNvcnJlbGFjaW9uZXMtc29jaW9lY29ub21pY2FzLCBlY2hvPVRSVUV9DQp2YXJpYWJsZXNfc29jaW9lY29ub21pY2FzIDwtIGMoDQogICJwY3RfcG9icmV6YSIsDQogICJzYWxhcmlvX3Byb21lZGlvIiwNCiAgInBjdF9lc3RyYXRvXzFfMiIsDQogICJwY3RfZXN0cmF0b18zXzQiLA0KICAicGN0X2VzdHJhdG9fNV82Ig0KKQ0KDQpjb3JyZWxhY2lvbmVzX3NvY2lvZWNvbm9taWNhcyA8LSBwdXJycjo6bWFwX2RmcigNCiAgdmFyaWFibGVzX3NvY2lvZWNvbm9taWNhcywNCiAgZnVuY3Rpb24odmFyaWFibGUpIHsNCg0KICAgIGRhdG9zX3ZhbGlkb3MgPC0gdXB6ICU+JQ0KICAgICAgc2VsZWN0KA0KICAgICAgICB0YXNhX3RvdGFsLA0KICAgICAgICBhbGxfb2YodmFyaWFibGUpDQogICAgICApICU+JQ0KICAgICAgZHJvcF9uYSgpDQoNCiAgICB0aWJibGUoDQogICAgICBWYXJpYWJsZSA9IHZhcmlhYmxlLA0KICAgICAgTnVtZXJvX1VQWiA9IG5yb3coZGF0b3NfdmFsaWRvcyksDQogICAgICByaG8gPSBjb3IoDQogICAgICAgIGRhdG9zX3ZhbGlkb3MkdGFzYV90b3RhbCwNCiAgICAgICAgZGF0b3NfdmFsaWRvc1tbdmFyaWFibGVdXSwNCiAgICAgICAgbWV0aG9kID0gInNwZWFybWFuIg0KICAgICAgKQ0KICAgICkNCiAgfQ0KKSAlPiUNCiAgbXV0YXRlKA0KICAgIFZhcmlhYmxlID0gcmVjb2RlKA0KICAgICAgVmFyaWFibGUsDQogICAgICBwY3RfcG9icmV6YSA9ICJQb2JsYWNpw7NuIGVuIGNvbmRpY2nDs24gZGUgcG9icmV6YSIsDQogICAgICBzYWxhcmlvX3Byb21lZGlvID0gIlNhbGFyaW8gcHJvbWVkaW8iLA0KICAgICAgcGN0X2VzdHJhdG9fMV8yID0gIlZpdmllbmRhcyBlbiBlc3RyYXRvcyAxIHkgMiIsDQogICAgICBwY3RfZXN0cmF0b18zXzQgPSAiVml2aWVuZGFzIGVuIGVzdHJhdG9zIDMgeSA0IiwNCiAgICAgIHBjdF9lc3RyYXRvXzVfNiA9ICJWaXZpZW5kYXMgZW4gZXN0cmF0b3MgNSB5IDYiDQogICAgKSwNCiAgICBEaXJlY2Npb24gPSBpZl9lbHNlKA0KICAgICAgcmhvID49IDAsDQogICAgICAiUG9zaXRpdmEiLA0KICAgICAgIk5lZ2F0aXZhIg0KICAgICksDQogICAgSW50ZW5zaWRhZCA9IGNhc2Vfd2hlbigNCiAgICAgIGFicyhyaG8pIDwgMC4yMCB+ICJNdXkgZMOpYmlsIiwNCiAgICAgIGFicyhyaG8pIDwgMC40MCB+ICJEw6liaWwiLA0KICAgICAgYWJzKHJobykgPCAwLjYwIH4gIk1vZGVyYWRhIiwNCiAgICAgIGFicyhyaG8pIDwgMC44MCB+ICJGdWVydGUiLA0KICAgICAgVFJVRSB+ICJNdXkgZnVlcnRlIg0KICAgICkNCiAgKSAlPiUNCiAgYXJyYW5nZShkZXNjKGFicyhyaG8pKSkNCg0Ka25pdHI6OmthYmxlKA0KICBjb3JyZWxhY2lvbmVzX3NvY2lvZWNvbm9taWNhcywNCiAgZGlnaXRzID0gMywNCiAgY2FwdGlvbiA9ICJDb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuIGVudHJlIGNvbmRpY2lvbmVzIHNvY2lvZWNvbsOzbWljYXMgeSB0YXNhIGRlIGRlbGl0b3MiDQopDQpgYGANCg0KIyMjIyBEaWZlcmVuY2lhcyBlbiBsb3MgdGlwb3MgZGUgZGVsaXRvcyBzZWfDum4gZWwgc2FsYXJpbyBwcm9tZWRpbw0KDQpBZGVtw6FzIGRlIGV4YW1pbmFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcyB5IGxhIHRhc2EgdG90YWwsIHNlIGV4cGxvcmEgc2kgZWwgY29tcG9ydGFtaWVudG8gZGUgbG9zIGRpc3RpbnRvcyB0aXBvcyBkZSBkZWxpdG9zIHByZXNlbnRhIGRpZmVyZW5jaWFzIGVudHJlIFVQWiBjb24gbml2ZWxlcyBkZSBzYWxhcmlvIHByb21lZGlvIHJlbGF0aXZhbWVudGUgYmFqb3MgeSBhbHRvcy4NCg0KUGFyYSBlbGxvLCBsYXMgdW5pZGFkZXMgdGVycml0b3JpYWxlcyBzZSBjbGFzaWZpY2FuIHV0aWxpemFuZG8gbGEgbWVkaWFuYSBkZWwgc2FsYXJpbyBwcm9tZWRpbyB5IHNlIGNvbXBhcmFuIGxhcyB0YXNhcyBlc3BlY8OtZmljYXMgZGUgbG9zIGRpZXogdGlwb3MgZGUgZGVsaXRvcyBpbmNsdWlkb3MgZW4gbGEgYmFzZS4NCg0KRXN0ZSBwcm9jZWRpbWllbnRvIHBlcm1pdGUgaWRlbnRpZmljYXIgcXXDqSBjYXRlZ29yw61hcyBwcmVzZW50YW4gbWF5b3JlcyB0YXNhcyByZWxhdGl2YXMgZGVudHJvIGRlIGNhZGEgZ3J1cG8gc29jaW9lY29uw7NtaWNvLiBMYSBjbGFzaWZpY2FjacOzbiByZXByZXNlbnRhIHVuYSBjb21wYXJhY2nDs24gZXhwbG9yYXRvcmlhIGVudHJlIHRlcnJpdG9yaW9zIHkgbm8gaW1wbGljYSBxdWUgZWwgbml2ZWwgZGUgaW5ncmVzbyBkZXRlcm1pbmUgZWwgdGlwbyBkZSBkZWxpdG8gcHJlZG9taW5hbnRlLg0KDQpgYGB7ciBoYWxsYXpnby03MzUtdGlwby1kZWxpdG8tc2FsYXJpbywgZWNobz1UUlVFfQ0KIyBEZWZpbmlyIGxhcyB0YXNhcyBlc3BlY8OtZmljYXMgZGUgbG9zIGRlbGl0b3MNCg0KdmFyaWFibGVzX3Rhc2FzX2RlbGl0b3MgPC0gYygNCiAgInRhc2FfaG9taWNpZGlvcyIsDQogICJ0YXNhX2xlc2lvbmVzIiwNCiAgInRhc2FfaHVydG9fcGVyc29uYXMiLA0KICAidGFzYV9odXJ0b19yZXNpZGVuY2lhcyIsDQogICJ0YXNhX2h1cnRvX2F1dG9tb3RvciIsDQogICJ0YXNhX2h1cnRvX2JpY2ljbGV0YXMiLA0KICAidGFzYV9odXJ0b19jb21lcmNpbyIsDQogICJ0YXNhX2h1cnRvX2NlbHVsYXJlcyIsDQogICJ0YXNhX2h1cnRvX21vdG9zIiwNCiAgInRhc2FfdmlvbGVuY2lhX2ludHJhZmFtaWxpYXIiDQopDQoNCiMgQ2xhc2lmaWNhciBsYXMgVVBaIHNlZ8O6biBsYSBtZWRpYW5hIGRlbCBzYWxhcmlvDQoNCm1lZGlhbmFfc2FsYXJpbyA8LSBtZWRpYW4oDQogIHVweiRzYWxhcmlvX3Byb21lZGlvLA0KICBuYS5ybSA9IFRSVUUNCikNCg0KdXB6X2dydXBvc19zYWxhcmlvIDwtIHVweiAlPiUNCiAgbXV0YXRlKA0KICAgIEdydXBvX3NhbGFyaW8gPSBpZl9lbHNlKA0KICAgICAgc2FsYXJpb19wcm9tZWRpbyA8PSBtZWRpYW5hX3NhbGFyaW8sDQogICAgICAiU2FsYXJpbyBiYWpvIG8gaWd1YWwgYSBtZWRpYW5hIiwNCiAgICAgICJTYWxhcmlvIHN1cGVyaW9yIGEgbWVkaWFuYSINCiAgICApDQogICkNCg0KIyBDb252ZXJ0aXIgbGFzIHRhc2FzIGVzcGVjw61maWNhcyBhIGZvcm1hdG8gbGFyZ28NCg0KZGVsaXRvc19wb3Jfc2FsYXJpbyA8LSB1cHpfZ3J1cG9zX3NhbGFyaW8gJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIEdydXBvX3NhbGFyaW8sDQogICAgYWxsX29mKHZhcmlhYmxlc190YXNhc19kZWxpdG9zKQ0KICApICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGFsbF9vZih2YXJpYWJsZXNfdGFzYXNfZGVsaXRvcyksDQogICAgbmFtZXNfdG8gPSAiVGlwb19kZWxpdG8iLA0KICAgIHZhbHVlc190byA9ICJUYXNhIg0KICApICU+JQ0KICBtdXRhdGUoDQogICAgVGlwb19kZWxpdG8gPSByZWNvZGUoDQogICAgICBUaXBvX2RlbGl0bywNCiAgICAgIHRhc2FfaG9taWNpZGlvcyA9ICJIb21pY2lkaW9zIiwNCiAgICAgIHRhc2FfbGVzaW9uZXMgPSAiTGVzaW9uZXMiLA0KICAgICAgdGFzYV9odXJ0b19wZXJzb25hcyA9ICJIdXJ0byBhIHBlcnNvbmFzIiwNCiAgICAgIHRhc2FfaHVydG9fcmVzaWRlbmNpYXMgPSAiSHVydG8gYSByZXNpZGVuY2lhcyIsDQogICAgICB0YXNhX2h1cnRvX2F1dG9tb3RvciA9ICJIdXJ0byBkZSBhdXRvbW90b3JlcyIsDQogICAgICB0YXNhX2h1cnRvX2JpY2ljbGV0YXMgPSAiSHVydG8gZGUgYmljaWNsZXRhcyIsDQogICAgICB0YXNhX2h1cnRvX2NvbWVyY2lvID0gIkh1cnRvIGEgY29tZXJjaW8iLA0KICAgICAgdGFzYV9odXJ0b19jZWx1bGFyZXMgPSAiSHVydG8gZGUgY2VsdWxhcmVzIiwNCiAgICAgIHRhc2FfaHVydG9fbW90b3MgPSAiSHVydG8gZGUgbW90b3MiLA0KICAgICAgdGFzYV92aW9sZW5jaWFfaW50cmFmYW1pbGlhciA9ICJWaW9sZW5jaWEgaW50cmFmYW1pbGlhciINCiAgICApDQogICkNCg0KIyBDYWxjdWxhciBsYSBtZWRpYW5hIGRlIGNhZGEgdGlwbyBkZSBkZWxpdG8gcG9yIGdydXBvIHNhbGFyaWFsDQoNCnJlc3VtZW5fZGVsaXRvc19zYWxhcmlvIDwtIGRlbGl0b3NfcG9yX3NhbGFyaW8gJT4lDQogIGdyb3VwX2J5KA0KICAgIEdydXBvX3NhbGFyaW8sDQogICAgVGlwb19kZWxpdG8NCiAgKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIFRhc2FfbWVkaWFuYSA9IG1lZGlhbihUYXNhLCBuYS5ybSA9IFRSVUUpLA0KICAgIE51bWVyb19VUFogPSBzdW0oIWlzLm5hKFRhc2EpKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkgJT4lDQogIGdyb3VwX2J5KEdydXBvX3NhbGFyaW8pICU+JQ0KICBtdXRhdGUoDQogICAgUG9zaWNpb24gPSBtaW5fcmFuayhkZXNjKFRhc2FfbWVkaWFuYSkpDQogICkgJT4lDQogIHVuZ3JvdXAoKQ0KDQojIFByZXNlbnRhciByYW5raW5nIGRlIHRpcG9zIGRlIGRlbGl0b3MgcG9yIGdydXBvDQoNCmtuaXRyOjprYWJsZSgNCiAgcmVzdW1lbl9kZWxpdG9zX3NhbGFyaW8gJT4lDQogICAgYXJyYW5nZShHcnVwb19zYWxhcmlvLCBQb3NpY2lvbiksDQogIGRpZ2l0cyA9IDMsDQogIGNhcHRpb24gPSAiVGFzYXMgbWVkaWFuYXMgcG9yIHRpcG8gZGUgZGVsaXRvIHNlZ8O6biBncnVwbyBzYWxhcmlhbCINCikNCg0KIyBDb21wYXJhY2nDs24gdmlzdWFsDQoNCmdncGxvdCgNCiAgcmVzdW1lbl9kZWxpdG9zX3NhbGFyaW8sDQogIGFlcygNCiAgICB4ID0gcmVvcmRlcihUaXBvX2RlbGl0bywgVGFzYV9tZWRpYW5hKSwNCiAgICB5ID0gVGFzYV9tZWRpYW5hLA0KICAgIGZpbGwgPSBHcnVwb19zYWxhcmlvDQogICkNCikgKw0KICBnZW9tX2NvbCgNCiAgICBwb3NpdGlvbiA9ICJkb2RnZSINCiAgKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoDQogICAgICAiU2FsYXJpbyBiYWpvIG8gaWd1YWwgYSBtZWRpYW5hIiA9ICIjMTY4Qzg2IiwNCiAgICAgICJTYWxhcmlvIHN1cGVyaW9yIGEgbWVkaWFuYSIgPSAiI0Q5MDA2QyINCiAgICApLA0KICAgIG5hbWUgPSAiR3J1cG8gc29jaW9lY29uw7NtaWNvIg0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJDb21wb3J0YW1pZW50byBkZSBsb3MgZGVsaXRvcyBzZWfDum4gZ3J1cG8gc2FsYXJpYWwiLA0KICAgIHN1YnRpdGxlID0gIkNvbXBhcmFjacOzbiBkZSBsYXMgdGFzYXMgbWVkaWFuYXMgcG9yIHRpcG8gZGUgZGVsaXRvIiwNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gIlRhc2EgbWVkaWFuYSBwb3IgY2FkYSAxMC4wMDAgaGFiaXRhbnRlcyINCiAgKSArDQogIHRlbWFfY2xhc2UNCmBgYA0KDQojIyMjIEludGVycHJldGFjacOzbiB5IGNvbmNsdXNpw7NuDQoNCkxvcyByZXN1bHRhZG9zIG9idGVuaWRvcyBtdWVzdHJhbiB1biBjb21wb3J0YW1pZW50byBpbnRlcmVzYW50ZSBlbnRyZSBsYXMgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcyB5IGxhcyB0YXNhcyBkZSBkZWxpdG9zIGRlbnVuY2lhZG9zLiBTZSBvYnNlcnZhIHVuYSB0ZW5kZW5jaWEgZW4gbGEgcXVlIGxhcyBVUFogY29uIG1lbm9yZXMgcG9yY2VudGFqZXMgZGUgcG9ibGFjacOzbiBlbiBjb25kaWNpw7NuIGRlIHBvYnJlemEgcHJlc2VudGFuIG1heW9yZXMgdGFzYXMgZGUgZGVsaXRvcy4gRGUgbWFuZXJhIHNpbWlsYXIsIGxhcyB1bmlkYWRlcyB0ZXJyaXRvcmlhbGVzIGNvbiBtYXlvcmVzIHNhbGFyaW9zIHByb21lZGlvIHRhbWJpw6luIG11ZXN0cmFuIHRhc2FzIG3DoXMgZWxldmFkYXMuDQoNCkVzdGUgY29tcG9ydGFtaWVudG8gcGVybWl0ZSBjdWVzdGlvbmFyIGxhIGlkZWEgZGUgcXVlIGxhcyBjb25kaWNpb25lcyBzb2Npb2Vjb27Ds21pY2FzIG3DoXMgZmF2b3JhYmxlcyBuZWNlc2FyaWFtZW50ZSBzZSByZWxhY2lvbmFuIGNvbiBtZW5vcmVzIG5pdmVsZXMgZGUgaW5zZWd1cmlkYWQuIFBvciBlbCBjb250cmFyaW8sIGxvcyByZXN1bHRhZG9zIHN1Z2llcmVuIHF1ZSBsb3MgdGVycml0b3Jpb3MgY29uIG1heW9yZXMgaW5ncmVzb3MgcHVlZGVuIHByZXNlbnRhciB1bmEgbWF5b3IgaW50ZW5zaWRhZCBkZSBkZW51bmNpYXMgcG9yIGhhYml0YW50ZS4NCg0KVW5hIHBvc2libGUgZXhwbGljYWNpw7NuIGVzdMOhIHJlbGFjaW9uYWRhIGNvbiBsYSBjYXBhY2lkYWQgYWRxdWlzaXRpdmEgeSBsYXMgZGluw6FtaWNhcyBlY29uw7NtaWNhcyBkZSBlc3RvcyB0ZXJyaXRvcmlvcywgcXVlIHBvZHLDrWFuIGluZmx1aXIgZW4gbGEgZXhwb3NpY2nDs24gYSBkZXRlcm1pbmFkb3MgZGVsaXRvcywgZXNwZWNpYWxtZW50ZSBhcXVlbGxvcyByZWxhY2lvbmFkb3MgY29uIGVsIGh1cnRvLiBUYW1iacOpbiBlcyBwb3NpYmxlIHF1ZSBleGlzdGFuIGRpZmVyZW5jaWFzIGVuIGxhIGRpc3Bvc2ljacOzbiBvIGNhcGFjaWRhZCBkZSBsb3MgaGFiaXRhbnRlcyBwYXJhIGRlbnVuY2lhciBsb3MgaGVjaG9zLiBTaW4gZW1iYXJnbywgZXN0YXMgZXhwbGljYWNpb25lcyBjb25zdGl0dXllbiBoaXDDs3Rlc2lzIHF1ZSBubyBwdWVkZW4gY29tcHJvYmFyc2UgZGlyZWN0YW1lbnRlIGNvbiBsYXMgdmFyaWFibGVzIGRpc3BvbmlibGVzLg0KDQpBbCBwcm9mdW5kaXphciBlbiBsb3MgdGlwb3MgZGUgZGVsaXRvcywgc2UgaWRlbnRpZmljYSBxdWUgZWwgaHVydG8gYSBwZXJzb25hcyB5IGVsIGh1cnRvIGRlIGNlbHVsYXJlcyBjb25jZW50cmFuIGxvcyBtYXlvcmVzIHJlZ2lzdHJvcyBudW3DqXJpY29zIGRlbnRybyBkZSBsYXMgY2F0ZWdvcsOtYXMgYW5hbGl6YWRhcy4gTm8gb2JzdGFudGUsIGFsIGNvbXBhcmFyIGxhcyB0YXNhcyBtZWRpYW5hcyBwb3IgdGlwbyBkZSBkZWxpdG8gZW50cmUgbG9zIGdydXBvcyBkZSBVUFogY2xhc2lmaWNhZG9zIHNlZ8O6biBzdSBzYWxhcmlvIHByb21lZGlvLCBhcGFyZWNlIHVuIHJlc3VsdGFkbyBwYXJ0aWN1bGFyOiBsYSB2aW9sZW5jaWEgaW50cmFmYW1pbGlhciB5IGxlc2lvbmVzIHNvbiBsb3Mgw7puaWNvcyBkZWxpdG9zIGN1eWEgdGFzYSBtZWRpYW5hIGVzIHN1cGVyaW9yIGVuIGVsIGdydXBvIGRlIHRlcnJpdG9yaW9zIGNvbiBzYWxhcmlvcyBwb3IgZGViYWpvIGRlIGxhIG1lZGlhbmEuDQoNCkVzdGUgcmVzdWx0YWRvIHJlc3VsdGEgZXNwZWNpYWxtZW50ZSByZWxldmFudGUgcG9ycXVlIG11ZXN0cmEgcXVlIGxhcyBkaWZlcmVuY2lhcyBzb2Npb2Vjb27Ds21pY2FzIG5vIG5lY2VzYXJpYW1lbnRlIHNlIG1hbmlmaWVzdGFuIGRlIGxhIG1pc21hIG1hbmVyYSBlbiB0b2RhcyBsYXMgY2F0ZWdvcsOtYXMgZGVsaWN0aXZhcy4gTWllbnRyYXMgbG9zIGh1cnRvcyByZXByZXNlbnRhbiB1bmEgcGFydGUgaW1wb3J0YW50ZSBkZSBsb3MgcmVnaXN0cm9zLCBsYSB2aW9sZW5jaWEgaW50cmFmYW1pbGlhciBwcmVzZW50YSB1biBjb21wb3J0YW1pZW50byBkaWZlcmVuY2lhZG8gcXVlIG1lcmVjZSB1bmEgbGVjdHVyYSBpbmRlcGVuZGllbnRlLg0KDQoqKkluc2lnaHQgcHJpbmNpcGFsOioqIExhcyBVUFogY29uIG1lam9yZXMgY29uZGljaW9uZXMgZWNvbsOzbWljYXMgbm8gbmVjZXNhcmlhbWVudGUgcHJlc2VudGFuIG1lbm9yZXMgdGFzYXMgZGUgZGVsaXRvcyBkZW51bmNpYWRvcy4gRW4gbG9zIHJlc3VsdGFkb3MgYW5hbGl6YWRvcywgbGFzIG1heW9yZXMgdGFzYXMgc2Ugb2JzZXJ2YW4gZW4gdGVycml0b3Jpb3MgY29uIG1lbm9yZXMgcG9yY2VudGFqZXMgZGUgcG9icmV6YSB5IG1heW9yZXMgc2FsYXJpb3MgcHJvbWVkaW8uIEFkZW3DoXMsIGVsIGNvbXBvcnRhbWllbnRvIGRlIGxhIHZpb2xlbmNpYSBpbnRyYWZhbWlsaWFyIHJvbXBlIGVsIHBhdHLDs24gZ2VuZXJhbCBkZSBjb21wYXJhY2nDs24gcG9yIGluZ3Jlc29zLCBhbCBwcmVzZW50YXIgdW5hIHRhc2EgbWVkaWFuYSBzdXBlcmlvciBlbiBsYXMgVVBaIGRlbCBncnVwbyBzYWxhcmlhbCBtw6FzIGFsdG8uDQoNCkVuIGNvbmp1bnRvLCBlc3RvcyByZXN1bHRhZG9zIHN1Z2llcmVuIHF1ZSBsYSByZWxhY2nDs24gZW50cmUgY29uZGljaW9uZXMgc29jaW9lY29uw7NtaWNhcyBlIGluc2VndXJpZGFkIGVzIG11bHRpZGltZW5zaW9uYWwuIEVsIG5pdmVsIGRlIGluZ3Jlc29zLCBsYSBwb2JyZXphIHkgbGEgY29tcG9zaWNpw7NuIGRlIGxvcyBkZWxpdG9zIGFwb3J0YW4gcGVyc3BlY3RpdmFzIGRpZmVyZW50ZXMgcGFyYSBjb21wcmVuZGVyIGxhcyBkaW7DoW1pY2FzIHRlcnJpdG9yaWFsZXMsIHBvciBsbyBxdWUgbm8gc2Vyw61hIGFkZWN1YWRvIHV0aWxpemFyIHVuYSBzb2xhIHZhcmlhYmxlIHNvY2lvZWNvbsOzbWljYSBwYXJhIGV4cGxpY2FyIGVsIGNvbXBvcnRhbWllbnRvIGRlIGxhIGluc2VndXJpZGFkLg0KDQojIyMgNy4zLjYuIMK/TGEgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgY29pbmNpZGUgY29uIGxvcyBkZWxpdG9zIGRlbnVuY2lhZG9zPw0KDQpFc3RhIHByZWd1bnRhIGJ1c2NhIGVzdGFibGVjZXIgc2kgbGFzIFVQWiBkb25kZSBzZSBwZXJjaWJlbiBtYXlvcmVzIHByb2JsZW1hcyBkZSBpbnNlZ3VyaWRhZCBzb24gdGFtYmnDqW4gYXF1ZWxsYXMgcXVlIHByZXNlbnRhbiBtYXlvcmVzIHRhc2FzIGRlIGRlbGl0b3MgZGVudW5jaWFkb3MuDQoNClBhcmEgZGVzYXJyb2xsYXIgZWwgYW7DoWxpc2lzIHNlIGNvbXBhcmFuIGRvcyBkaW1lbnNpb25lczogbGEgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgcmVwb3J0YWRhIHBvciBsb3MgaGFiaXRhbnRlcyB5IGxvcyByZWdpc3Ryb3MgYWRtaW5pc3RyYXRpdm9zIGRlIGRlbnVuY2lhcy4gTGEgcHJpbWVyYSByZXByZXNlbnRhIGxhIHZhbG9yYWNpw7NuIHF1ZSBsYXMgcGVyc29uYXMgaGFjZW4gc29icmUgbGFzIGNvbmRpY2lvbmVzIGRlIHNlZ3VyaWRhZCBlbiBlbCBlbnRvcm5vIGRlIHN1IHZpdmllbmRhLCBtaWVudHJhcyBxdWUgbGEgc2VndW5kYSByZWZsZWphIGxvcyBjYXNvcyByZWdpc3RyYWRvcyBwb3IgbGFzIGF1dG9yaWRhZGVzLg0KDQpTZSBhbmFsaXphIGxhIHJlbGFjacOzbiBlbnRyZSBlbCBwb3JjZW50YWplIGRlIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHkgbGEgdGFzYSB0b3RhbCBkZSBkZWxpdG9zIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzLiBBZGljaW9uYWxtZW50ZSwgc2UgaW5jb3Jwb3JhIGVsIG7Dum1lcm8gYWJzb2x1dG8gZGUgZGVudW5jaWFzIHBhcmEgaWRlbnRpZmljYXIgcG9zaWJsZXMgZGlmZXJlbmNpYXMgZW50cmUgbGEgcGVyY2VwY2nDs24sIGxhIGNvbmNlbnRyYWNpw7NuIGRlIGNhc29zIHkgbGEgaW50ZW5zaWRhZCByZWxhdGl2YSBkZSBsb3MgcmVnaXN0cm9zLg0KDQpFbCBwcm9ww7NzaXRvIGVzIHJlY29ub2NlciBzaSBhbWJhcyBkaW1lbnNpb25lcyBwcmVzZW50YW4gY29tcG9ydGFtaWVudG9zIHNpbWlsYXJlcyBvIHNpIGV4aXN0ZW4gdGVycml0b3Jpb3MgZG9uZGUgbGEgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgbm8gY29pbmNpZGUgY29uIGxvcyBpbmRpY2Fkb3JlcyBkZSBkZW51bmNpYXMuDQoNCkVzIGltcG9ydGFudGUgc2XDsWFsYXIgcXVlIHBlcmNlcGNpw7NuIHkgZGVudW5jaWEgbm8gbWlkZW4gZXhhY3RhbWVudGUgZWwgbWlzbW8gZmVuw7NtZW5vLiBVbmEgcGVyc29uYSBwdWVkZSBwZXJjaWJpciBpbnNlZ3VyaWRhZCBzaW4gaGFiZXIgc2lkbyB2w61jdGltYSBkZSB1biBkZWxpdG8sIHkgbm8gdG9kb3MgbG9zIGhlY2hvcyBkZWxpY3Rpdm9zIHNvbiBkZW51bmNpYWRvcy4gUG9yIGxvIHRhbnRvLCBsYXMgZGlmZXJlbmNpYXMgZW50cmUgYW1ib3MgaW5kaWNhZG9yZXMgbm8gZGViZW4gaW50ZXJwcmV0YXJzZSBhdXRvbcOhdGljYW1lbnRlIGNvbW8gZXJyb3JlcyBkZSBwZXJjZXBjacOzbiBvIGRlIHJlZ2lzdHJvLg0KDQpgYGB7ciBoYWxsYXpnby03MzYtcGVyY2VwY2lvbi10YXNhLCBlY2hvPVRSVUV9DQpnZ3Bsb3QoDQogIHVweiwNCiAgYWVzKA0KICAgIHggPSBwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZCwNCiAgICB5ID0gdGFzYV90b3RhbCwNCiAgICBjb2xvciA9IGVtX2FncnVwYWRhDQogICkNCikgKw0KICBnZW9tX3BvaW50KA0KICAgIGFscGhhID0gMC43NSwNCiAgICBzaXplID0gMi41DQogICkgKw0KICBzY2FsZV95X2xvZzEwKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEoKQ0KICApICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoDQogICAgICAiRkFMU0UiID0gIiMxNjhDODYiLA0KICAgICAgIlRSVUUiID0gIiNEOTAwNkMiDQogICAgKSwNCiAgICBsYWJlbHMgPSBjKA0KICAgICAgIkZBTFNFIiA9ICJFc3RpbWFjacOzbiBpbmRpdmlkdWFsIiwNCiAgICAgICJUUlVFIiA9ICJFc3RpbWFjacOzbiBhZ3J1cGFkYSINCiAgICApLA0KICAgIG5hbWUgPSAiVGlwbyBkZSBlc3RpbWFjacOzbiINCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiTGEgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgbm8gbmVjZXNhcmlhbWVudGUgY29pbmNpZGUgY29uIGxhcyB0YXNhcyBkZSBkZWxpdG9zIiwNCiAgICBzdWJ0aXRsZSA9ICJQZXJjZXBjacOzbiByZXBvcnRhZGEgZnJlbnRlIGEgZGVudW5jaWFzIHBvciBjYWRhIDEwLjAwMCBoYWJpdGFudGVzIiwNCiAgICB4ID0gIlBvYmxhY2nDs24gcXVlIHBlcmNpYmUgcHJvYmxlbWFzIGRlIGluc2VndXJpZGFkICglKSIsDQogICAgeSA9ICJUYXNhIHRvdGFsIGRlIGRlbGl0b3MgKGVzY2FsYSBsb2dhcsOtdG1pY2EpIg0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQoNCmBgYHtyIGhhbGxhemdvLTczNi1wZXJjZXBjaW9uLWNhc29zLCBlY2hvPVRSVUV9DQpnZ3Bsb3QoDQogIHVweiwNCiAgYWVzKA0KICAgIHggPSBwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZCwNCiAgICB5ID0gY2Fzb3NfdG90YWwsDQogICAgY29sb3IgPSBlbV9hZ3J1cGFkYQ0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBhbHBoYSA9IDAuNzUsDQogICAgc2l6ZSA9IDIuNQ0KICApICsNCiAgc2NhbGVfeV9sb2cxMCgNCiAgICBsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2NvbW1hKCkNCiAgKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKA0KICAgICAgIkZBTFNFIiA9ICIjMTY4Qzg2IiwNCiAgICAgICJUUlVFIiA9ICIjRDkwMDZDIg0KICAgICksDQogICAgbGFiZWxzID0gYygNCiAgICAgICJGQUxTRSIgPSAiRXN0aW1hY2nDs24gaW5kaXZpZHVhbCIsDQogICAgICAiVFJVRSIgPSAiRXN0aW1hY2nDs24gYWdydXBhZGEiDQogICAgKSwNCiAgICBuYW1lID0gIlRpcG8gZGUgZXN0aW1hY2nDs24iDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHkgdm9sdW1lbiBkZSBkZW51bmNpYXMiLA0KICAgIHN1YnRpdGxlID0gIkNvbXBhcmFjacOzbiBlbnRyZSBwZXJjZXBjacOzbiB5IG7Dum1lcm8gZGUgY2Fzb3MgcG9yIFVQWiIsDQogICAgeCA9ICJQb2JsYWNpw7NuIHF1ZSBwZXJjaWJlIHByb2JsZW1hcyBkZSBpbnNlZ3VyaWRhZCAoJSkiLA0KICAgIHkgPSAiTsO6bWVybyBkZSBkZW51bmNpYXMgKGVzY2FsYSBsb2dhcsOtdG1pY2EpIg0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQoNCmBgYHtyIGhhbGxhemdvLTczNi1jb3JyZWxhY2lvbmVzLCBlY2hvPVRSVUV9DQp2YXJpYWJsZXNfcGVyY2VwY2lvbiA8LSBjKA0KICAidGFzYV90b3RhbCIsDQogICJjYXNvc190b3RhbCIsDQogICJwb2JsYWNpb24iDQopDQoNCmNvcnJlbGFjaW9uZXNfcGVyY2VwY2lvbiA8LSBwdXJycjo6bWFwX2RmcigNCiAgdmFyaWFibGVzX3BlcmNlcGNpb24sDQogIGZ1bmN0aW9uKHZhcmlhYmxlKSB7DQoNCiAgICBkYXRvc192YWxpZG9zIDwtIHVweiAlPiUNCiAgICAgIHNlbGVjdCgNCiAgICAgICAgcGN0X3BlcmNpYmVfaW5zZWd1cmlkYWQsDQogICAgICAgIGFsbF9vZih2YXJpYWJsZSkNCiAgICAgICkgJT4lDQogICAgICBkcm9wX25hKCkNCg0KICAgIHRpYmJsZSgNCiAgICAgIFZhcmlhYmxlID0gdmFyaWFibGUsDQogICAgICBOdW1lcm9fVVBaID0gbnJvdyhkYXRvc192YWxpZG9zKSwNCiAgICAgIHJobyA9IGNvcigNCiAgICAgICAgZGF0b3NfdmFsaWRvcyRwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZCwNCiAgICAgICAgZGF0b3NfdmFsaWRvc1tbdmFyaWFibGVdXSwNCiAgICAgICAgbWV0aG9kID0gInNwZWFybWFuIg0KICAgICAgKQ0KICAgICkNCiAgfQ0KKSAlPiUNCiAgbXV0YXRlKA0KICAgIFZhcmlhYmxlID0gcmVjb2RlKA0KICAgICAgVmFyaWFibGUsDQogICAgICB0YXNhX3RvdGFsID0gIlRhc2EgdG90YWwgZGUgZGVsaXRvcyIsDQogICAgICBjYXNvc190b3RhbCA9ICJOw7ptZXJvIGRlIGNhc29zIGRlbnVuY2lhZG9zIiwNCiAgICAgIHBvYmxhY2lvbiA9ICJQb2JsYWNpw7NuIHJlc2lkZW50ZSINCiAgICApLA0KICAgIERpcmVjY2lvbiA9IGlmX2Vsc2UoDQogICAgICByaG8gPj0gMCwNCiAgICAgICJQb3NpdGl2YSIsDQogICAgICAiTmVnYXRpdmEiDQogICAgKSwNCiAgICBJbnRlbnNpZGFkID0gY2FzZV93aGVuKA0KICAgICAgYWJzKHJobykgPCAwLjIwIH4gIk11eSBkw6liaWwiLA0KICAgICAgYWJzKHJobykgPCAwLjQwIH4gIkTDqWJpbCIsDQogICAgICBhYnMocmhvKSA8IDAuNjAgfiAiTW9kZXJhZGEiLA0KICAgICAgYWJzKHJobykgPCAwLjgwIH4gIkZ1ZXJ0ZSIsDQogICAgICBUUlVFIH4gIk11eSBmdWVydGUiDQogICAgKQ0KICApDQoNCmtuaXRyOjprYWJsZSgNCiAgY29ycmVsYWNpb25lc19wZXJjZXBjaW9uLA0KICBkaWdpdHMgPSAzLA0KICBjYXB0aW9uID0gIkNvcnJlbGFjaW9uZXMgZGUgU3BlYXJtYW4gZW50cmUgcGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgeSB2YXJpYWJsZXMgZGUgZGVsaXRvcyINCikNCmBgYA0KDQpgYGB7ciBoYWxsYXpnby03MzYtY3VhZHJhbnRlcywgZWNobz1UUlVFfQ0KIyBDYWxjdWxhciBtZWRpYW5hcyBkZSByZWZlcmVuY2lhDQoNCm1lZGlhbmFfcGVyY2VwY2lvbiA8LSBtZWRpYW4oDQogIHVweiRwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZCwNCiAgbmEucm0gPSBUUlVFDQopDQoNCm1lZGlhbmFfdGFzYSA8LSBtZWRpYW4oDQogIHVweiR0YXNhX3RvdGFsLA0KICBuYS5ybSA9IFRSVUUNCikNCg0KIyBDbGFzaWZpY2FyIGxhcyBVUFogc2Vnw7puIHBlcmNlcGNpw7NuIHkgdGFzYQ0KDQp1cHpfcGVyY2VwY2lvbl9ncnVwb3MgPC0gdXB6ICU+JQ0KICBtdXRhdGUoDQogICAgR3J1cG9fcGVyY2VwY2lvbl90YXNhID0gY2FzZV93aGVuKA0KICAgICAgcGN0X3BlcmNpYmVfaW5zZWd1cmlkYWQgPj0gbWVkaWFuYV9wZXJjZXBjaW9uICYNCiAgICAgICAgdGFzYV90b3RhbCA+PSBtZWRpYW5hX3Rhc2EgfiAiUGVyY2VwY2nDs24gYWx0YSAtIFRhc2EgYWx0YSIsDQoNCiAgICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkID49IG1lZGlhbmFfcGVyY2VwY2lvbiAmDQogICAgICAgIHRhc2FfdG90YWwgPCBtZWRpYW5hX3Rhc2EgfiAiUGVyY2VwY2nDs24gYWx0YSAtIFRhc2EgYmFqYSIsDQoNCiAgICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkIDwgbWVkaWFuYV9wZXJjZXBjaW9uICYNCiAgICAgICAgdGFzYV90b3RhbCA+PSBtZWRpYW5hX3Rhc2EgfiAiUGVyY2VwY2nDs24gYmFqYSAtIFRhc2EgYWx0YSIsDQoNCiAgICAgIFRSVUUgfiAiUGVyY2VwY2nDs24gYmFqYSAtIFRhc2EgYmFqYSINCiAgICApDQogICkNCg0KIyBSZXN1bWVuIGRlIFVQWiBwb3IgZ3J1cG8NCg0KcmVzdW1lbl9wZXJjZXBjaW9uX2dydXBvcyA8LSB1cHpfcGVyY2VwY2lvbl9ncnVwb3MgJT4lDQogIGdyb3VwX2J5KEdydXBvX3BlcmNlcGNpb25fdGFzYSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBOdW1lcm9fVVBaID0gbigpLA0KICAgIFBlcmNlcGNpb25fbWVkaWFuYSA9IG1lZGlhbigNCiAgICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkLA0KICAgICAgbmEucm0gPSBUUlVFDQogICAgKSwNCiAgICBUYXNhX21lZGlhbmEgPSBtZWRpYW4oDQogICAgICB0YXNhX3RvdGFsLA0KICAgICAgbmEucm0gPSBUUlVFDQogICAgKSwNCiAgICBDYXNvc19tZWRpYW5hID0gbWVkaWFuKA0KICAgICAgY2Fzb3NfdG90YWwsDQogICAgICBuYS5ybSA9IFRSVUUNCiAgICApLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQprbml0cjo6a2FibGUoDQogIHJlc3VtZW5fcGVyY2VwY2lvbl9ncnVwb3MsDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiQ2xhc2lmaWNhY2nDs24gdGVycml0b3JpYWwgc2Vnw7puIHBlcmNlcGNpw7NuIHkgdGFzYSBkZSBkZWxpdG9zIg0KKQ0KDQojIElkZW50aWZpY2FyIGxhcyBVUFogZGUgY2FkYSBncnVwbw0KDQp0YWJsYV91cHpfcGVyY2VwY2lvbiA8LSB1cHpfcGVyY2VwY2lvbl9ncnVwb3MgJT4lDQogIHNlbGVjdCgNCiAgICB1cHpfbm9tYnJlLA0KICAgIHBvYmxhY2lvbiwNCiAgICBjYXNvc190b3RhbCwNCiAgICB0YXNhX3RvdGFsLA0KICAgIHBjdF9wZXJjaWJlX2luc2VndXJpZGFkLA0KICAgIEdydXBvX3BlcmNlcGNpb25fdGFzYQ0KICApICU+JQ0KICBhcnJhbmdlKEdydXBvX3BlcmNlcGNpb25fdGFzYSkNCg0Ka25pdHI6OmthYmxlKA0KICB0YWJsYV91cHpfcGVyY2VwY2lvbiwNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJVUFogY2xhc2lmaWNhZGFzIHNlZ8O6biBwZXJjZXBjacOzbiBkZSBpbnNlZ3VyaWRhZCB5IHRhc2EgZGUgZGVsaXRvcyINCikNCg0KIyBWaXN1YWxpemFjacOzbiBkZSBsb3MgY3VhdHJvIGdydXBvcw0KDQpnZ3Bsb3QoDQogIHVwel9wZXJjZXBjaW9uX2dydXBvcywNCiAgYWVzKA0KICAgIHggPSBwY3RfcGVyY2liZV9pbnNlZ3VyaWRhZCwNCiAgICB5ID0gdGFzYV90b3RhbCwNCiAgICBjb2xvciA9IEdydXBvX3BlcmNlcGNpb25fdGFzYQ0KICApDQopICsNCiAgZ2VvbV9wb2ludCgNCiAgICBzaXplID0gMi43LA0KICAgIGFscGhhID0gMC44DQogICkgKw0KICBnZW9tX3ZsaW5lKA0KICAgIHhpbnRlcmNlcHQgPSBtZWRpYW5hX3BlcmNlcGNpb24sDQogICAgbGluZXR5cGUgPSAiZGFzaGVkIiwNCiAgICBjb2xvciA9ICJncmV5NDUiDQogICkgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBtZWRpYW5hX3Rhc2EsDQogICAgbGluZXR5cGUgPSAiZGFzaGVkIiwNCiAgICBjb2xvciA9ICJncmV5NDUiDQogICkgKw0KICBzY2FsZV95X2xvZzEwKA0KICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfY29tbWEoKQ0KICApICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoDQogICAgICAiUGVyY2VwY2nDs24gYWx0YSAtIFRhc2EgYWx0YSIgPSAiIzM1MUE0RiIsDQogICAgICAiUGVyY2VwY2nDs24gYWx0YSAtIFRhc2EgYmFqYSIgPSAiI0Q5MDA2QyIsDQogICAgICAiUGVyY2VwY2nDs24gYmFqYSAtIFRhc2EgYWx0YSIgPSAiIzE2OEM4NiIsDQogICAgICAiUGVyY2VwY2nDs24gYmFqYSAtIFRhc2EgYmFqYSIgPSAiI0E2OUJBRiINCiAgICApLA0KICAgIG5hbWUgPSAiQ2xhc2lmaWNhY2nDs24iDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBlcmNlcGNpw7NuIHkgZGVudW5jaWFzIHBlcm1pdGVuIGlkZW50aWZpY2FyIGN1YXRybyBwZXJmaWxlcyB0ZXJyaXRvcmlhbGVzIiwNCiAgICBzdWJ0aXRsZSA9ICJDbGFzaWZpY2FjacOzbiByZWxhdGl2YSBzZWfDum4gbGFzIG1lZGlhbmFzIGRlIGxhcyB2YXJpYWJsZXMiLA0KICAgIHggPSAiUGVyY2VwY2nDs24gZGUgaW5zZWd1cmlkYWQgKCUpIiwNCiAgICB5ID0gIlRhc2EgZGUgZGVsaXRvcyBwb3IgMTAuMDAwIGhhYml0YW50ZXMgKGVzY2FsYSBsb2dhcsOtdG1pY2EpIg0KICApICsNCiAgdGVtYV9jbGFzZQ0KYGBgDQpgYGB7ciBoYWxsYXpnby03MzYtcmVzdW1lbi1jdWF0cm8tZ3J1cG9zLCBlY2hvPVRSVUV9DQojIFJlc3VtZW4gZWplY3V0aXZvIGRlIGxvcyBjdWF0cm8gZ3J1cG9zDQoNCnJlc3VtZW5fY3VhdHJvX2dydXBvcyA8LSB1cHpfcGVyY2VwY2lvbl9ncnVwb3MgJT4lDQogIG11dGF0ZSgNCiAgICBHcnVwbyA9IGNhc2Vfd2hlbigNCiAgICAgIEdydXBvX3BlcmNlcGNpb25fdGFzYSA9PSAiUGVyY2VwY2nDs24gYWx0YSAtIFRhc2EgYWx0YSIgfiAiRzEiLA0KICAgICAgR3J1cG9fcGVyY2VwY2lvbl90YXNhID09ICJQZXJjZXBjacOzbiBhbHRhIC0gVGFzYSBiYWphIiB+ICJHMiIsDQogICAgICBHcnVwb19wZXJjZXBjaW9uX3Rhc2EgPT0gIlBlcmNlcGNpw7NuIGJhamEgLSBUYXNhIGFsdGEiIH4gIkczIiwNCiAgICAgIEdydXBvX3BlcmNlcGNpb25fdGFzYSA9PSAiUGVyY2VwY2nDs24gYmFqYSAtIFRhc2EgYmFqYSIgfiAiRzQiDQogICAgKQ0KICApICU+JQ0KICBncm91cF9ieShHcnVwbykgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBOdW1lcm9fVVBaID0gbigpLA0KICAgIFBvYmxhY2lvbl90b3RhbCA9IHN1bShwb2JsYWNpb24sIG5hLnJtID0gVFJVRSksDQogICAgUG9yY2VudGFqZV9VUFogPSBuKCkgLyBucm93KHVwel9wZXJjZXBjaW9uX2dydXBvcykgKiAxMDAsDQogICAgUGVyY2VwY2lvbl9tZWRpYW5hID0gbWVkaWFuKA0KICAgICAgcGN0X3BlcmNpYmVfaW5zZWd1cmlkYWQsDQogICAgICBuYS5ybSA9IFRSVUUNCiAgICApLA0KICAgIFRhc2FfbWVkaWFuYSA9IG1lZGlhbigNCiAgICAgIHRhc2FfdG90YWwsDQogICAgICBuYS5ybSA9IFRSVUUNCiAgICApLA0KICAgIENhc29zX3RvdGFsZXMgPSBzdW0oY2Fzb3NfdG90YWwsIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApICU+JQ0KICBtdXRhdGUoDQogICAgR3J1cG8gPSBmYWN0b3IoR3J1cG8sIGxldmVscyA9IGMoIkcxIiwgIkcyIiwgIkczIiwgIkc0IikpLA0KICAgIFBhcnRpY2lwYWNpb24gPSBwYXN0ZTAoDQogICAgICByb3VuZChQb3JjZW50YWplX1VQWiwgMSksDQogICAgICAiJSINCiAgICApDQogICkgJT4lDQogIGFycmFuZ2UoR3J1cG8pDQoNCiMgVGFibGEgcmVzdW1lbg0KDQprbml0cjo6a2FibGUoDQogIHJlc3VtZW5fY3VhdHJvX2dydXBvcyAlPiUNCiAgICBzZWxlY3QoDQogICAgICBHcnVwbywNCiAgICAgIE51bWVyb19VUFosDQogICAgICBQYXJ0aWNpcGFjaW9uLA0KICAgICAgUG9ibGFjaW9uX3RvdGFsLA0KICAgICAgUGVyY2VwY2lvbl9tZWRpYW5hLA0KICAgICAgVGFzYV9tZWRpYW5hLA0KICAgICAgQ2Fzb3NfdG90YWxlcw0KICAgICksDQogIGRpZ2l0cyA9IDIsDQogIGNvbC5uYW1lcyA9IGMoDQogICAgIkdydXBvIiwNCiAgICAiTi7CuiBVUFoiLA0KICAgICJQYXJ0aWNpcGFjacOzbiIsDQogICAgIlBvYmxhY2nDs24iLA0KICAgICJQZXJjZXBjacOzbiBtZWRpYW5hICglKSIsDQogICAgIlRhc2EgbWVkaWFuYSIsDQogICAgIkNhc29zIHRvdGFsZXMiDQogICksDQogIGNhcHRpb24gPSAiUmVzdW1lbiBkZSBsb3MgY3VhdHJvIHBlcmZpbGVzIHRlcnJpdG9yaWFsZXMiDQopDQpgYGANCmBgYHtyIGhhbGxhemdvLTczNi1ncmFmaWNhLWNsYXNpZmljYWNpb24tcmVsYXRpdmEsIGVjaG89VFJVRX0NCiMgUHJlcGFyYXIgbG9zIGN1YXRybyBncnVwb3MgeSBzdXMgcG9yY2VudGFqZXMNCg0KZ3JhZmljYV9jbGFzaWZpY2FjaW9uXzczNiA8LSByZXN1bWVuX2N1YXRyb19ncnVwb3MgJT4lDQogIG11dGF0ZSgNCiAgICBHcnVwbyA9IGFzLmNoYXJhY3RlcihHcnVwbyksDQogICAgQ2xhc2lmaWNhY2lvbiA9IGNhc2Vfd2hlbigNCiAgICAgIEdydXBvID09ICJHMSIgfiAiQWx0YSBwZXJjZXBjacOzbiAtIEFsdGEgdGFzYSIsDQogICAgICBHcnVwbyA9PSAiRzIiIH4gIkFsdGEgcGVyY2VwY2nDs24gLSBCYWphIHRhc2EiLA0KICAgICAgR3J1cG8gPT0gIkczIiB+ICJCYWphIHBlcmNlcGNpw7NuIC0gQWx0YSB0YXNhIiwNCiAgICAgIEdydXBvID09ICJHNCIgfiAiQmFqYSBwZXJjZXBjacOzbiAtIEJhamEgdGFzYSINCiAgICApLA0KICAgIEV0aXF1ZXRhID0gcGFzdGUwKA0KICAgICAgR3J1cG8sICJcbiIsDQogICAgICByb3VuZChQb3JjZW50YWplX1VQWiwgMSksICIlXG4iLA0KICAgICAgTnVtZXJvX1VQWiwgIiBVUFoiDQogICAgKQ0KICApDQoNCiMgR3LDoWZpY2EgZGUgZGlzdHJpYnVjacOzbiBwb3JjZW50dWFsDQoNCmdncGxvdCgNCiAgZ3JhZmljYV9jbGFzaWZpY2FjaW9uXzczNiwNCiAgYWVzKA0KICAgIHggPSAyLA0KICAgIHkgPSBQb3JjZW50YWplX1VQWiwNCiAgICBmaWxsID0gR3J1cG8NCiAgKQ0KKSArDQogIGdlb21fY29sKA0KICAgIHdpZHRoID0gMC43NSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgbGluZXdpZHRoID0gMQ0KICApICsNCiAgZ2VvbV90ZXh0KA0KICAgIGFlcyhsYWJlbCA9IEV0aXF1ZXRhKSwNCiAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwNCiAgICBjb2xvciA9ICJ3aGl0ZSIsDQogICAgZm9udGZhY2UgPSAiYm9sZCIsDQogICAgc2l6ZSA9IDMuNQ0KICApICsNCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsNCiAgeGxpbSgwLjUsIDIuNSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKA0KICAgICAgIkcxIiA9ICIjMzUxQTRGIiwNCiAgICAgICJHMiIgPSAiI0Q5MDA2QyIsDQogICAgICAiRzMiID0gIiMxNjhDODYiLA0KICAgICAgIkc0IiA9ICIjQTY5QkFGIg0KICAgICksDQogICAgbGFiZWxzID0gYygNCiAgICAgICJHMSIgPSAiUGVyY2VwY2nDs24gYWx0YSAtIFRhc2EgYWx0YSIsDQogICAgICAiRzIiID0gIlBlcmNlcGNpw7NuIGFsdGEgLSBUYXNhIGJhamEiLA0KICAgICAgIkczIiA9ICJQZXJjZXBjacOzbiBiYWphIC0gVGFzYSBhbHRhIiwNCiAgICAgICJHNCIgPSAiUGVyY2VwY2nDs24gYmFqYSAtIFRhc2EgYmFqYSINCiAgICApLA0KICAgIG5hbWUgPSAiUGVyZmlsIHRlcnJpdG9yaWFsIg0KICApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIGxhcyBVUFogc2Vnw7puIHBlcmNlcGNpw7NuIHkgdGFzYSBkZSBkZWxpdG9zIiwNCiAgICBzdWJ0aXRsZSA9ICJDbGFzaWZpY2FjacOzbiByZWxhdGl2YSBiYXNhZGEgZW4gbGFzIG1lZGlhbmFzIGRlIGFtYmFzIHZhcmlhYmxlcyIsDQogICAgY2FwdGlvbiA9ICJUb3RhbDogMTEyIFVQWi4gTG9zIHBvcmNlbnRhamVzIHJlcHJlc2VudGFuIHBhcnRpY2lwYWNpw7NuIHNvYnJlIGVsIHRvdGFsLiINCiAgKSArDQogIHRlbWFfY2xhc2UgKw0KICB0aGVtZSgNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0Ig0KICApDQpgYGANCg0KYGBge3IgaGFsbGF6Z28tNzM2LWdyYWZpY2EtY29ycmVzcG9uZGVuY2lhLCBlY2hvPVRSVUV9DQojIEFncnVwYXIgbG9zIGN1YXRybyBwZXJmaWxlcyBlbiBkb3MgY2F0ZWdvcsOtYXMgZ2VuZXJhbGVzDQoNCnJlc3VtZW5fY29ycmVzcG9uZGVuY2lhIDwtIHJlc3VtZW5fY3VhdHJvX2dydXBvcyAlPiUNCiAgbXV0YXRlKA0KICAgIFRpcG8gPSBjYXNlX3doZW4oDQogICAgICBHcnVwbyAlaW4lIGMoIkcxIiwgIkc0IikgfiAiQ29pbmNpZGVuY2lhIiwNCiAgICAgIEdydXBvICVpbiUgYygiRzIiLCAiRzMiKSB+ICJEaWZlcmVuY2lhIg0KICAgICkNCiAgKSAlPiUNCiAgZ3JvdXBfYnkoVGlwbykgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBQb3JjZW50YWplID0gc3VtKFBvcmNlbnRhamVfVVBaKSwNCiAgICBOdW1lcm9fVVBaID0gc3VtKE51bWVyb19VUFopLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIFRpcG8gPSBmYWN0b3IoDQogICAgICBUaXBvLA0KICAgICAgbGV2ZWxzID0gYygiRGlmZXJlbmNpYSIsICJDb2luY2lkZW5jaWEiKQ0KICAgICksDQogICAgRXRpcXVldGEgPSBwYXN0ZTAoDQogICAgICByb3VuZChQb3JjZW50YWplLCAxKSwgIiUiLA0KICAgICAgIiAoIiwgTnVtZXJvX1VQWiwgIiBVUFopIg0KICAgICkNCiAgKQ0KDQojIEdyw6FmaWNvIGRlIGNvcnJlc3BvbmRlbmNpYQ0KDQpnZ3Bsb3QoDQogIHJlc3VtZW5fY29ycmVzcG9uZGVuY2lhLA0KICBhZXMoDQogICAgeCA9IFBvcmNlbnRhamUsDQogICAgeSA9IFRpcG8sDQogICAgZmlsbCA9IFRpcG8NCiAgKQ0KKSArDQogIGdlb21fY29sKA0KICAgIHdpZHRoID0gMC40NSwNCiAgICBjb2xvciA9IE5BDQogICkgKw0KICBnZW9tX3RleHQoDQogICAgYWVzKA0KICAgICAgbGFiZWwgPSBFdGlxdWV0YQ0KICAgICksDQogICAgaGp1c3QgPSAtMC4xMiwNCiAgICBmb250ZmFjZSA9ICJib2xkIiwNCiAgICBzaXplID0gNA0KICApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwoDQogICAgdmFsdWVzID0gYygNCiAgICAgICJDb2luY2lkZW5jaWEiID0gIiMxNjhDODYiLA0KICAgICAgIkRpZmVyZW5jaWEiID0gIiNEOTAwNkMiDQogICAgKQ0KICApICsNCiAgc2NhbGVfeF9jb250aW51b3VzKA0KICAgIGxpbWl0cyA9IGMoMCwgNzUpLA0KICAgIGJyZWFrcyA9IHNlcSgwLCA3NSwgMTUpLA0KICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4LCAiJSIpLA0KICAgIGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLCAwKSkNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ29ycmVzcG9uZGVuY2lhIGVudHJlIHBlcmNlcGNpw7NuIHkgZGVudW5jaWFzIiwNCiAgICBzdWJ0aXRsZSA9ICJDb2luY2lkZW5jaWE6IEcxICsgRzQgfCBEaWZlcmVuY2lhOiBHMiArIEczIiwNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gTlVMTCwNCiAgICBjYXB0aW9uID0gIkNsYXNpZmljYWNpw7NuIHJlbGF0aXZhIGRlIGxhcyAxMTIgVVBaIHNlZ8O6biBsYXMgbWVkaWFuYXMgZGUgcGVyY2VwY2nDs24geSB0YXNhLiINCiAgKSArDQogIHRlbWFfY2xhc2UgKw0KICB0aGVtZSgNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoDQogICAgICBmYWNlID0gImJvbGQiLA0KICAgICAgc2l6ZSA9IDExDQogICAgKSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSkNCiAgKQ0KYGBgDQoNCiMjIyMgSW50ZXJwcmV0YWNpw7NuIHkgY29uY2x1c2nDs24NCg0KTGEgY2xhc2lmaWNhY2nDs24gZGUgbGFzIFVQWiBlbiBjdWF0cm8gcGVyZmlsZXMgdGVycml0b3JpYWxlcyBwZXJtaXRlIGlkZW50aWZpY2FyIGRpZmVyZW5jaWFzIGltcG9ydGFudGVzIGVudHJlIGxhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHJlcG9ydGFkYSBwb3IgbG9zIGhhYml0YW50ZXMgeSBsYXMgdGFzYXMgZGUgZGVsaXRvcyBkZW51bmNpYWRvcy4NCg0KVW5vIGRlIGxvcyByZXN1bHRhZG9zIG3DoXMgcmVsZXZhbnRlcyBlcyBxdWUgZWwgNTcsMiAlIGRlIGxhcyBVUFogcHJlc2VudGEgdW5hIGRpZmVyZW5jaWEgZW50cmUgYW1iYXMgZGltZW5zaW9uZXMuIEVuIHBhcnRpY3VsYXIsIGVsIDI4LDYgJSBjb3JyZXNwb25kZSBhbCBncnVwbyBHMiwgY2FyYWN0ZXJpemFkbyBwb3IgdW5hIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHN1cGVyaW9yIGEgbGEgbWVkaWFuYSB5IHRhc2FzIGRlIGRlbnVuY2lhcyBpbmZlcmlvcmVzIGEgZXN0YS4gUG9yIHN1IHBhcnRlLCBvdHJvIDI4LDYgJSBwZXJ0ZW5lY2UgYWwgZ3J1cG8gRzMsIGRvbmRlIHNlIG9ic2VydmEgZWwgY29tcG9ydGFtaWVudG8gY29udHJhcmlvOiB1bmEgcGVyY2VwY2nDs24gcmVsYXRpdmFtZW50ZSBiYWphIGZyZW50ZSBhIHRhc2FzIGRlIGRlbnVuY2lhcyBzdXBlcmlvcmVzIGEgbGEgbWVkaWFuYS4NCg0KTG9zIGdydXBvcyBHMSB5IEc0LCBxdWUgcmVwcmVzZW50YW4gY29uanVudGFtZW50ZSBlbCA0Miw4ICUgZGUgbGFzIFVQWiwgbXVlc3RyYW4gdW5hIGNvcnJlc3BvbmRlbmNpYSByZWxhdGl2YSBlbnRyZSBwZXJjZXBjacOzbiB5IHJlZ2lzdHJvczogZW4gZWwgcHJpbWVybyBjb2luY2lkZW4gbml2ZWxlcyBhbHRvcyBkZSBwZXJjZXBjacOzbiB5IHRhc2FzLCBtaWVudHJhcyBxdWUgZW4gZWwgc2VndW5kbyBhbWJhcyB2YXJpYWJsZXMgc2UgdWJpY2FuIHBvciBkZWJham8gZGUgc3VzIHJlc3BlY3RpdmFzIG1lZGlhbmFzLg0KDQpFc3RlIGNvbXBvcnRhbWllbnRvIHBlcm1pdGUgcmVjb25vY2VyIHF1ZSBsYSBleHBlcmllbmNpYSBkZSBpbnNlZ3VyaWRhZCBkZSBsb3MgaGFiaXRhbnRlcyBubyBuZWNlc2FyaWFtZW50ZSBjb2luY2lkZSBjb24gbG9zIHJlZ2lzdHJvcyBhZG1pbmlzdHJhdGl2b3MgZGUgZGVudW5jaWFzLiBFbiBhbGd1bm9zIHRlcnJpdG9yaW9zLCBsYSBwZXJjZXBjacOzbiBwdWVkZSBzZXIgZWxldmFkYSBpbmNsdXNvIGN1YW5kbyBsYXMgdGFzYXMgcmVnaXN0cmFkYXMgc29uIHJlbGF0aXZhbWVudGUgYmFqYXM7IGVuIG90cm9zLCBsYXMgdGFzYXMgcHVlZGVuIHNlciBlbGV2YWRhcyBzaW4gcXVlIGxhIHBlcmNlcGNpw7NuIHJlcG9ydGFkYSBhbGNhbmNlIG5pdmVsZXMgc2ltaWxhcmVzLg0KDQpVbmEgcG9zaWJsZSBleHBsaWNhY2nDs24gZXMgcXVlIGxhIGRlbnVuY2lhIG5vIHJlY29nZSBsYSB0b3RhbGlkYWQgZGUgbG9zIGhlY2hvcyBkZWxpY3Rpdm9zLiBUYW1iacOpbiBwdWVkZW4gaW50ZXJ2ZW5pciBmYWN0b3JlcyBjb21vIGxhIGRpc3Bvc2ljacOzbiBkZSBsYXMgcGVyc29uYXMgYSBkZW51bmNpYXIsIHN1cyBleHBlcmllbmNpYXMgZGUgaW5zZWd1cmlkYWQsIGxhIGV4cG9zaWNpw7NuIGEgc2l0dWFjaW9uZXMgZGUgcmllc2dvIHkgbGFzIGNhcmFjdGVyw61zdGljYXMgcGFydGljdWxhcmVzIGRlbCBlbnRvcm5vLiBTaW4gZW1iYXJnbywgbGEgaW5mb3JtYWNpw7NuIGRpc3BvbmlibGUgbm8gcGVybWl0ZSBkZXRlcm1pbmFyIGN1w6FsIGRlIGVzdG9zIGZhY3RvcmVzIGV4cGxpY2EgbGFzIGRpZmVyZW5jaWFzIGlkZW50aWZpY2FkYXMuDQoNCioqSW5zaWdodCBwcmluY2lwYWw6IExhIHBlcmNlcGNpw7NuIGRlIGluc2VndXJpZGFkIHkgbG9zIGRlbGl0b3MgZGVudW5jaWFkb3Mgbm8gcmVwcmVzZW50YW4gbmVjZXNhcmlhbWVudGUgbGEgbWlzbWEgcmVhbGlkYWQgdGVycml0b3JpYWwuIEVsIDU3LDIgJSBkZSBsYXMgVVBaIHByZXNlbnRhIHVuYSBkaWZlcmVuY2lhIGVudHJlIGFtYmFzIGRpbWVuc2lvbmVzLCBsbyBxdWUgZXZpZGVuY2lhIHF1ZSBsb3MgcmVnaXN0cm9zIGFkbWluaXN0cmF0aXZvcywgYXVucXVlIGZ1bmRhbWVudGFsZXMgcGFyYSBhbmFsaXphciBsYSBzZWd1cmlkYWQsIG5vIHNvbiBzdWZpY2llbnRlcyBwb3Igc8OtIHNvbG9zIHBhcmEgY29tcHJlbmRlciBjw7NtbyBleHBlcmltZW50YW4gbG9zIGhhYml0YW50ZXMgbGEgaW5zZWd1cmlkYWQgZW4gc3UgZW50b3Juby4qKg0KDQpFbiBjb25zZWN1ZW5jaWEsIGVsIGFuw6FsaXNpcyBkZSBsYSBzZWd1cmlkYWQgdGVycml0b3JpYWwgZGViZSBpbnRlZ3JhciB0YW50byBsb3MgcmVnaXN0cm9zIGRlIGRlbnVuY2lhcyBjb21vIGxhIHBlcmNlcGNpw7NuIGRlIGxvcyBoYWJpdGFudGVzLCByZWNvbm9jaWVuZG8gcXVlIHNvbiBpbmRpY2Fkb3JlcyBjb21wbGVtZW50YXJpb3MgeSBxdWUgbmluZ3VubyByZXByZXNlbnRhIHBvciBzw60gc29sbyBsYSB0b3RhbGlkYWQgZGVsIGZlbsOzbWVuby4NCg0KDQojIyBOb3RhIGRlIHRyYW5zcGFyZW5jaWEgc29icmUgZWwgdXNvIGRlIGludGVsaWdlbmNpYSBhcnRpZmljaWFsDQoNCkR1cmFudGUgZWwgZGVzYXJyb2xsbyBkZSBlc3RlIHRyYWJham8gc2UgdXRpbGl6w7MgQ2hhdEdQVCBjb21vIGhlcnJhbWllbnRhIGRlIGFwb3lvIHBhcmEgbGEgY29uc3RydWNjacOzbiB5IGVqZWN1Y2nDs24gZGVsIGFuw6FsaXNpcyBleHBsb3JhdG9yaW8gZGUgZGF0b3MgKEVEQSksIGVzcGVjaWFsbWVudGUgZW4gbGEgZWxhYm9yYWNpw7NuIGRlIGPDs2RpZ28gZW4gUiwgbGEgZXN0cnVjdHVyYWNpw7NuIGRlIHByb2NlZGltaWVudG9zIGVzdGFkw61zdGljb3MsIGxhIGdlbmVyYWNpw7NuIGRlIHZpc3VhbGl6YWNpb25lcyB5IGxhIG9yZ2FuaXphY2nDs24gZGUgbG9zIHJlc3VsdGFkb3MgZGVudHJvIGRlbCBkb2N1bWVudG8gUiBNYXJrZG93bi4NCg0KRWwgZGVzYXJyb2xsbyBzZSByZWFsaXrDsyBtZWRpYW50ZSB1biBwcm9jZXNvIGRlIHRyYWJham8gZ3VpYWRvLCBwcm9ncmVzaXZvIGUgaXRlcmF0aXZvLiBMb3MgYXV0b3JlcyBkZWZpbmllcm9uIGVsIGVuZm9xdWUgZGVsIHByb3llY3RvLCBmb3JtdWxhcm9uIGxhcyBwcmVndW50YXMgZGUgaW52ZXN0aWdhY2nDs24sIGVzdGFibGVjaWVyb24gbGFzIHZhcmlhYmxlcyBkZSBpbnRlcsOpcywgb3JpZW50YXJvbiBsYXMgZGVjaXNpb25lcyBtZXRvZG9sw7NnaWNhcyB5IGRldGVybWluYXJvbiBsb3MgYW7DoWxpc2lzIHF1ZSBkZWLDrWFuIHJlYWxpemFyc2UgZW4gZnVuY2nDs24gZGUgbG9zIG9iamV0aXZvcyBkZWwgdGFsbGVyLg0KDQpDaGF0R1BUIHByb3BvcmNpb27DsyBhc2lzdGVuY2lhIHTDqWNuaWNhIGVuIGxhIGVzY3JpdHVyYSB5IGNvcnJlY2Npw7NuIGRlbCBjw7NkaWdvLCBhc8OtIGNvbW8gZW4gbGEgcHJvcHVlc3RhIGRlIHByb2NlZGltaWVudG9zIGVzdGFkw61zdGljb3MgeSBhbHRlcm5hdGl2YXMgZGUgdmlzdWFsaXphY2nDs24uIEVzdGEgY29sYWJvcmFjacOzbiBzZSBkZXNhcnJvbGzDsyBwYXNvIGEgcGFzbywgcmV2aXNhbmRvIGxvcyByZXN1bHRhZG9zIG9idGVuaWRvcywgaWRlbnRpZmljYW5kbyBlcnJvcmVzLCBhanVzdGFuZG8gbG9zIHByb2NlZGltaWVudG9zIHkgcHJvZnVuZGl6YW5kbyBlbiBsYSBpbnRlcnByZXRhY2nDs24gZGUgbG9zIGhhbGxhemdvcy4NCg0KTGEgc2VsZWNjacOzbiBkZSBsb3MgYW7DoWxpc2lzLCBsYSByZXZpc2nDs24gZGUgc3UgcGVydGluZW5jaWEsIGxhIG9yaWVudGFjacOzbiBkZSBsYXMgcHJlZ3VudGFzIHkgbGEgaW50ZXJwcmV0YWNpw7NuIGNyw610aWNhIGRlIGxvcyByZXN1bHRhZG9zIGVzdHV2aWVyb24gYmFqbyBlbCBjcml0ZXJpbyB5IGxhIGRpcmVjY2nDs24gZGUgbG9zIGF1dG9yZXMuIERlIGVzdGEgbWFuZXJhLCBsYSBpbnRlbGlnZW5jaWEgYXJ0aWZpY2lhbCBzZSB1dGlsaXrDsyBjb21vIHVuIHJlY3Vyc28gZGUgYWNvbXBhw7FhbWllbnRvIHkgYXNpc3RlbmNpYSB0w6ljbmljYSwgc2luIHN1c3RpdHVpciBlbCBwcm9jZXNvIGRlIGFuw6FsaXNpcywgcmVmbGV4acOzbiB5IHRvbWEgZGUgZGVjaXNpb25lcyBkZSBsb3MgZXN0dWRpYW50ZXMuDQoNCkxvcyByZXN1bHRhZG9zIHkgY29uY2x1c2lvbmVzIHByZXNlbnRhZG9zIGZ1ZXJvbiBjb25zdHJ1aWRvcyBhIHBhcnRpciBkZSBsYSBlamVjdWNpw7NuIGRlbCBjw7NkaWdvIHNvYnJlIGxvcyBkYXRvcyBkZWwgcHJveWVjdG8geSBkZSBsYSByZXZpc2nDs24gZGUgbGFzIGV2aWRlbmNpYXMgb2J0ZW5pZGFzIGR1cmFudGUgZWwgZGVzYXJyb2xsbyBkZWwgdHJhYmFqby4=