Este cuaderno pretende mostrar un acercamiento hacia la economia agricola del departamento, basado en datos espaciales y no espaciales, especificamente un archivo de evaluaciones agropecuarias del departamento y datos del marco geoestadistico nacional del año 2017

##esta primera linea borra cualquier objeto que pudiera tener almacenado el programa

rm(list=ls())

estas librerias seràn de gran utilidad para el desarrollo de la pràctica, con esta linea nos aseguramos de que se instalen solo una vez en el programa

list.of.packages <- c("here", "tidyverse", "rgeos", "maptools", "raster", "sf",  "viridis", "rnaturalearth", "GSODR", "ggrepel", "cowplot")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) install.packages(new.packages)
library(here)
here() starts at C:/Users/juane/Desktop
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages --------------------------------------- tidyverse 1.3.0 --
v ggplot2 3.3.0     v purrr   0.3.3
v tibble  2.1.3     v dplyr   0.8.4
v tidyr   1.0.2     v stringr 1.4.0
v readr   1.3.1     v forcats 0.5.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(rgeos)
Loading required package: sp
rgeos version: 0.5-2, (SVN revision 621)
 GEOS runtime version: 3.6.1-CAPI-1.10.1 
 Linking to sp version: 1.4-1 
 Polygon checking: TRUE 
library(maptools)
Checking rgeos availability: TRUE
library(raster)

Attaching package: 㤼㸱raster㤼㸲

The following object is masked from 㤼㸱package:dplyr㤼㸲:

    select

The following object is masked from 㤼㸱package:tidyr㤼㸲:

    extract
library(sf)
Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3
library(viridis)
Loading required package: viridisLite
library(rnaturalearth)
library(GSODR)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
library(ggrepel)
library(cowplot)

********************************************************
Note: As of version 1.0.0, cowplot does not change the
  default ggplot2 theme anymore. To recover the previous
  behavior, execute:
  theme_set(theme_cowplot())
********************************************************

En este objeto vamos a asignar los datos no espaciales asociados a las evaluaciones agropecuarias del departamento, donde se hace un resumen de los cultivos producidos en cada municipio, ademas de datos estadisticos como el area cultivada por cada elemento ademas de valores de produccion anual de los mismos

datos <- read_csv2("D:/unal/geomatica/santander/evaluacion agropecuaria_Santander.csv")
Using ',' as decimal and '.' as grouping mark. Use read_delim() for more control.
Parsed with column specification:
cols(
  COD_DPTO = col_double(),
  DPTO = col_character(),
  COD_MUN = col_double(),
  MUN = col_character(),
  GRU_CUL = col_character(),
  SGRU_CUL = col_character(),
  CULT = col_character(),
  YEAR = col_double(),
  PERIODO = col_character(),
  AREA_SEM = col_double(),
  AREA_COS = col_double(),
  PROD = col_double(),
  REND = col_double(),
  ESTADO = col_character(),
  NOM_CIEN = col_character(),
  CICLO_CULTIVO = col_character()
)
datos

las siguientes dos lineas nos dejan ver unas muestras de los datos anteriores, la priemra nos deja ver las primeras seis filas y la segunda nos deja ver las ultimas seis del archivo

head(datos)
tail(datos)

vamos a iniciar el trabajo mostrando el rendimiento promedio de la produccion de los diferentes cultivos en cada uno de los muncipios, con esto podemos ver que grupo de cultivos predominan en tema de rendimiento anual en cada municipio

datos %>%
  group_by(MUN, GRU_CUL) %>%
  summarise(rend_prom = mean(REND, na.rm = TRUE)) -> REND_resumen
REND_resumen

##En esta nueva exploracion, vemos otra agrupacion de los datos, en donde se muestra el rendimiento promedio de cada grupo de cultivo en Ton/año en el departamento, donde observamos que se destacan las hortalizas y las oleaginosas, mas adelante veremos que importancia pueden tener estos datos

datos %>% group_by(GRU_CUL) %>% summarise(PROD_DPTO=mean(PROD,na.rm= TRUE))->PROD_Santander
PROD_Santander

aqui vamos a mostrar que municipio tuvo un mayor rendimiento para cada grupo de cultivo especificamente en el año 2018

datos %>%filter(YEAR==2018) %>% 
  group_by(GRU_CUL, MUN) %>%
  summarize(max_rend = max(REND, na.rm = TRUE)) %>%
    slice(which.max(max_rend)) -> REND_max_2018

REND_max_2018

para esta nueva visualizacion, realizaremos un filtro de los datos donde que municipio tuvo una mayor area cosechada para cada grupo de cultivo, observando que hay municipios que destinan una gran superficie para el tema agricola, como lo son Puerto Wilches

datos %>%filter(YEAR==2018) %>% group_by(GRU_CUL, MUN) %>%
  summarize(max_AREA_COS = max(AREA_COS, na.rm = TRUE)) %>%
    slice(which.max(max_AREA_COS)) -> area_cosecha_max

area_cosecha_max

aqui realizamos un filtro de los datos para explorar el grupo de cultivo Otros permanentes para ver que cual fue la maxima produccion de estos cultivos dentro del tiempo que cubren los datos

datos %>% filter(GRU_CUL=="Otros Permanentes") %>% group_by(MUN,SGRU_CUL="Cacao") %>% summarise (max_PROD=max(PROD, na.rm = TRUE)) %>% slice(which.max(max_PROD))->PROD_max
PROD_max

he decicido realizar una observacion de los datos en el municipio de San Benito, debido a que en la consulta anterior, se observo que este municipio presenta una alta produccion de cacao, llegando llegando hasta un maximo de 36000 hectareas del mismo

datos %>% 
  filter(MUN=="San Benito" & SGRU_CUL=="Cacao") %>% 
  group_by(YEAR, CULT) ->  VICEN_CACAO
VICEN_CACAO

para ver estos datos de una forma grafica, nos aprovecharemos de la funcion ggplot para vrlos de forma grafica y analizarlos de mejor manera, donde observamos que el año de mayor produccion en el municipio fue el 2013 llegando a las 200 toneladas en ese año

g <- ggplot(aes(x=YEAR, y=PROD/100), data = VICEN_CACAO) + geom_bar(stat='identity') + labs(y='Cacao Production [Ton x 1000]')

g + ggtitle("Evolution of cacao production in San Benito from 2013 to 2018") + labs(caption= "Based on EMA data (DANE, 2018)")

ahora, se realizara otra consulta, esta vez para observar la superficie cosechada total por cada grupo de cultivo en el año 2018, donde se observa que los cultivos Otros Permanentes detacan ampliamente sobre el resto

datos %>% 
  filter(YEAR==2018) %>% 
  group_by(GRU_CUL) %>%
  summarize(sum_AREA_COS = sum(AREA_COS, na.rm = TRUE)) %>%
     arrange(desc(sum_AREA_COS)) -> total_AREA_COS
total_AREA_COS

basados en lo anterior, vamos a realizar un filtro sobre el mismo año, pero tomando solo los cultivos otros permanentes, esto para ver cual cultivo en especifico es el que predomina respecto al area cosechada en el departamento. Como se observa, el cacao junto al cafe, presntan un gran porcentaje del total, donde destaca el cacao

datos %>% filter(GRU_CUL=="Otros Permanentes"& YEAR==2018) %>% group_by(CULT) %>% summarize(sum_cosecha = sum(AREA_COS, na.rm = TRUE)) %>%
     arrange(desc(sum_cosecha)) -> TOT_COSECHA

TOT_COSECHA

ahora que ya sabemos que el cacao es el cultivo otro permanente de mayor area cosechada, con este nuevo filtro veremos que municipio presenta una mayor area cosechada de cacao en el año 2018, donde vemos que el mayor exponente es el municipio San Vicente De Chucuri

datos %>% 
  filter(YEAR==2018 & GRU_CUL=="Otros Permanentes") %>% 
  group_by(CULT, MUN) %>%
  summarize(AREA_COS_MUN = max(AREA_COS, na.rm = TRUE)) %>%
    slice(which.max(AREA_COS_MUN)) ->max_area2 

max_area2

antes de realizar el ploteo, a cada una de las clases, que seran los grupos de cultivo, vamos a realizarles una abreviatura, para que se pueda leer con claridad en el ploteo

total_AREA_COS$CROP <- abbreviate(total_AREA_COS$GRU_CUL, 3)

este ploteo nos muestra el area cultivada por cada grupo de cultivo en el año 2018, veremos la misma informacion de hace varias lineas, pero con este grafico, sera mucho mas facil de sacar conclusiones sobre el mismo

g <- ggplot(aes(x=CROP, y=sum_AREA_COS), data = total_AREA_COS) + geom_bar(stat='identity') + labs(y='Total Harvested Area [Ha]')
g+ ggtitle("Total harvested area by crop groups in 2018 for Santander") + theme(plot.title = element_text(hjust = 0.5)) +
   labs(caption= "Based on EMA data (DANE, 2018)")

la segunda parte del informe consistira en realizar una union entre los datos no espacilaes mostrados en la primeraparte y un archivo de datos espaciales proveniente del marco geoestadistico del pais provenineto del DANE

Sant_MUN <-sf::st_read("D:/unal/geomatica/santander/marco geoestadisitico/68_SANTANDER/ADMINISTRATIVO/MGN_MPIO_POLITICO.shp")
Reading layer `MGN_MPIO_POLITICO' from data source `' using driver `ESRI Shapefile'
Simple feature collection with 87 features and 9 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: -74.52895 ymin: 5.707536 xmax: -72.47706 ymax: 8.14501
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs

veamos que tiene este archivo .shp

Simple feature collection with 87 features and 9 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: -74.52895 ymin: 5.707536 xmax: -72.47706 ymax: 8.14501
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs
First 10 features:
   DPTO_CCDGO MPIO_CCDGO      MPIO_CNMBR
1          68      68001     BUCARAMANGA
2          68      68013          AGUADA
3          68      68020         ALBANIA
4          68      68051         ARATOCA
5          68      68077         BARBOSA
6          68      68079       BARICHARA
7          68      68081 BARRANCABERMEJA
8          68      68092         BETULIA
9          68      68101         BOLIVAR
10         68      68121         CABRERA
                             MPIO_CRSLC MPIO_NAREA
3                  Ordenanza 33 de 1919  166.21697      2017  SANTANDER
4                                  1750  169.79155      2017  SANTANDER
5  Ordenanza 30 del 25 de Abril de 1936   46.66489      2017  SANTANDER
6                                  1799  137.27581      2017  SANTANDER
7  Ordenanza 13 del 17 de Abril de 1922 1326.83512      2017  SANTANDER
8                                  1874  431.24871      2017  SANTANDER
9                                  1844 1010.11035      2017  SANTANDER
10                                 1869   65.57431      2017  SANTANDER
   Shape_Leng  Shape_Area                       geometry
1   0.6922752 0.012513526 POLYGON ((-73.08418 7.23063...
2   0.4758098 0.006146093 POLYGON ((-73.56261 6.24032...
3   0.8761299 0.013570466 POLYGON ((-73.73616 5.87092...
4   0.6746922 0.013882031 POLYGON ((-72.98158 6.76065...
5   0.2703415 0.003810882 POLYGON ((-73.58988 5.99809...
6   0.5610888 0.011223345 POLYGON ((-73.22126 6.73288...
7   2.7351901 0.108590745 POLYGON ((-73.6939 7.254447...
8   1.2718180 0.035286963 POLYGON ((-73.53993 7.15392...
9   4.3603864 0.082514928 POLYGON ((-74.50132 6.27574...
10  0.3515706 0.005360404 POLYGON ((-73.25696 6.6213,...

para realizar el join necesitamos un campo en comun entre ambos paquetes de datos, por lo que usaremos el codigo de municipio para ello, estas dos lineas nos serviran para crear dos campos nuevos a los datos no espaciales, conel objetivo de convertir la columna COD_MUN que es un objeto de tipo numerico a un objeto de tipo factor, cosa fundamental para realizar el join

datos_2 <- datos
datos_2$TEMP <-  as.character(datos_2$COD_MUN)
datos_2

ahora al objeto datos_2 le realizaremos un filtro que consistira en que solo tomara los datos en el que se analize el cacao en cada uno de los municipios del departamento. El resultado de esto se almacenara en un nuevo objeto llamado datos_3

datos_2 %>% filter(CULT == "Cacao")  -> datos_3
datos_3

Aqui vemos la clase del objeto recien creado, vemos que se trata de un dataframe, cosa que es buena para realizar el join

class(datos_3)
[1] "spec_tbl_df" "tbl_df"      "tbl"         "data.frame" 

para este nuevo objeto tomaremos solo los campos que nos sean de real interes del objeto datos_3, entre ellos el campo creado previamente que es un factor

datos_4 <- datos_3 %>% dplyr::select(MUN, MPIO_CCDGO, YEAR, PROD, REND) 

ahora al resultado de la linea anterior vamos a organizarlo de manera cronologica, es decir, veremos los datos de cada municipio en un año, luego los del siguiente asi hasta cubrir todos los datos

datos_4 %>% 
  gather("YEAR", "PROD", "REND" , key = variable, value = number)
datos_4

ahora vamos a pasar de una organizacion de los datos en forma larga, es decir con muchas filas y pocas columnas a una orgnizacion larga con muchas columnas y pocas filas, de manera que en cada columna veamos los datos de produccion y rendimiento de cada añ en columnas independientes, el resultado de este proceso se alamacenara en un nuevo objeto de nombre datos_5

datos_4 %>% 
  group_by(MPIO_CCDGO) %>% 
  mutate(Visit = 1:n()) %>% 
  gather("YEAR", "PROD", "REND", key = variable, value = number) %>% 
  unite(combi, variable, Visit) %>%
  spread(combi, number) -> datos_5
head(datos_5)

ya que tenemos todos los elementos necesarios, procedemos a realizar el join entre los datos no espaciales y los datos espaciales, tomando como punto comun el campo MPIO_CCDGO

Sant_MUN_stat =left_join(Sant_MUN, datos_5, by="MPIO_CCDGO")
summary(Sant_MUN_stat)
 DPTO_CCDGO   MPIO_CCDGO           MPIO_CNMBR   MPIO_CRSLC
 68:87      68001  : 1   AGUADA         : 1   1899   :11  
            68013  : 1   ALBANIA        : 1   1887   : 9  
            68020  : 1   ARATOCA        : 1   1799   : 8  
            68051  : 1   BARBOSA        : 1   1743   : 2  
            68077  : 1   BARICHARA      : 1   1750   : 2  
            68079  : 1   BARRANCABERMEJA: 1   1762   : 2  
            (Other):81   (Other)        :81   (Other):53  
   MPIO_NAREA        MPIO_NANO        DPTO_CNMBR   Shape_Leng    
 Min.   :  19.69   Min.   :2017   SANTANDER:87   Min.   :0.2700  
 1st Qu.:  91.01   1st Qu.:2017                  1st Qu.:0.4765  
 Median : 201.73   Median :2017                  Median :0.7392  
 Mean   : 351.28   Mean   :2017                  Mean   :1.0298  
 3rd Qu.: 426.17   3rd Qu.:2017                  3rd Qu.:1.2240  
 Max.   :3174.28   Max.   :2017                  Max.   :4.3604                                                                   
   Shape_Area          MUN               PROD_10      
 Min.   :0.00161   Length:87          Min.   :   0.0   Min.   :   6.0  
 1st Qu.:0.00744   Class :character   1st Qu.:   4.0   1st Qu.:  61.5  
 Median :0.01649   Mode  :character   Median :  30.0   Median : 140.0  
 Mean   :0.02873                      Mean   : 468.1   Mean   : 661.3  
 3rd Qu.:0.03486                      3rd Qu.: 100.0   3rd Qu.: 375.0  
 Max.   :0.25946                      Max.   :7200.0   Max.   :6625.0  
                                      NA's   :40       NA's   :52      
    PROD_11          PROD_12           PROD_2           PROD_3       Min.   :  20.0   Min.   :  28.0   Min.   :   0.0   Min.   :   0.0  
 1st Qu.:  63.0   1st Qu.:  88.0   1st Qu.:   7.0   1st Qu.:  14.0  
 Median : 137.5   Median : 166.0   Median :  39.0   Median :  43.0  
 Mean   : 702.9   Mean   : 837.4   Mean   : 460.5   Mean   : 432.1   3rd Qu.: 423.2   3rd Qu.: 578.0   3rd Qu.: 100.0   3rd Qu.: 110.0  
 Max.   :6540.0   Max.   :6540.0   Max.   :7490.0   Max.   :5640.0  
 NA's   :55       NA's   :58       NA's   :40       NA's   :42      
     PROD_4           PROD_5           PROD_6           PROD_7       
 Min.   :   2.0   Min.   :   2.0   Min.   :   2.0   Min.   :   2.00  
 1st Qu.:  20.5   1st Qu.:  28.0   1st Qu.:  27.0   1st Qu.:  24.25  
 Median :  53.0   Median :  62.0   Median :  94.0   Median : 100.50  
 Mean   : 478.8   Mean   : 502.1   Mean   : 499.9   Mean   : 538.35  
 3rd Qu.: 135.5   3rd Qu.: 144.0   3rd Qu.: 237.0   3rd Qu.: 285.50  
 Max.   :5350.0   Max.   :5014.0   Max.   :4993.0   Max.   :5145.00  
 NA's   :43       NA's   :44       NA's   :46       NA's   :47       
     PROD_8           PROD_9           REND_1         REND_10    
 Min.   :   2.0   Min.   :   3.0   Min.   : 1.00   Min.   : 1.0  
 1st Qu.:  36.0   1st Qu.:  54.0   1st Qu.: 5.00   1st Qu.: 5.0  
 Median : 116.0   Median : 140.5   Median : 7.50   Median : 6.0  
 Mean   : 505.9   Mean   : 602.7   Mean   :25.12   Mean   :10.4  
 3rd Qu.: 270.0   3rd Qu.: 325.5   3rd Qu.:51.50   3rd Qu.: 7.0  
 Max.   :5000.0   Max.   :5400.0   Max.   :76.00   Max.   :55.0  
 NA's   :50       NA's   :51       NA's   :47      NA's   :52    
    REND_11          REND_12           REND_2          REND_3     
 Min.   : 1.000   Min.   : 1.000   Min.   : 1.00   Min.   : 1.00  
 1st Qu.: 5.000   1st Qu.: 5.000   1st Qu.: 5.00   1st Qu.: 5.00  
 Median : 6.000   Median : 6.000   Median : 8.00   Median : 7.00  
 Mean   : 9.812   Mean   : 8.862   Mean   :30.05   Mean   :20.82  
 3rd Qu.: 8.000   3rd Qu.: 8.000   3rd Qu.:55.25   3rd Qu.:47.50  
 Max.   :55.000   Max.   :55.000   Max.   :75.00   Max.   :83.00  
 NA's   :55       NA's   :58       NA's   :45      NA's   :43     
     REND_4          REND_5           REND_6          REND_7     
 Min.   : 1.00   Min.   :  1.00   Min.   : 1.00   Min.   : 4.00  
 1st Qu.: 5.00   1st Qu.:  5.00   1st Qu.: 5.00   1st Qu.: 5.00  
 Median : 6.00   Median :  6.00   Median : 5.00   Median : 6.00  
 Mean   :19.09   Mean   : 14.26   Mean   :12.53  
 3rd Qu.: 8.00   3rd Qu.:  8.00   3rd Qu.: 8.00   3rd Qu.: 7.25  
 Max.   :94.00   Max.   :116.00   Max.   :94.00   Max.   :75.00  
 NA's   :43      NA's   :44       NA's   :46      NA's   :47     
     REND_8          YEAR_1        YEAR_10    
 Min.   : 1.00   Min.   : 1.000   Min.   :2007   Min.   :2016   1st Qu.: 5.00   1st Qu.: 5.000   1st Qu.:2007   1st Qu.:2016  
 Median : 6.00   Median : 5.000   Median :2007   Median :2016  
 Mean   :12.22   Mean   :2009   Mean   :2016  
 3rd Qu.: 8.00   3rd Qu.: 6.000   3rd Qu.:2009   3rd Qu.:2016  
 Max.   :67.00   Max.   :55.000   Max.   :2017   Max.   :2018  
 NA's   :50      NA's   :51       NA's   :40     NA's   :52    
    YEAR_11        YEAR_12         YEAR_2         YEAR_3    
 Min.   :2017   Min.   :2018   Min.   :2008   Min.   :2009  
 1st Qu.:2017   1st Qu.:2018   1st Qu.:2008   1st Qu.:2009  
 Median :2017   Median :2018   Median :2008   Median :2009  
 Mean   :2017   Mean   :2018   Mean   :2010   Mean   :2010  
 3rd Qu.:2017   3rd Qu.:2010   3rd Qu.:2011  
 Max.   :2018   Max.   :2018   Max.   :2018   Max.   :2018  

     YEAR_4         YEAR_5         YEAR_6         YEAR_7    
 Min.   :2010   Min.   :2011   Min.   :2012   Min.   :2013  
 1st Qu.:2010   1st Qu.:2011   1st Qu.:2012   1st Qu.:2013   Median :2010   Median :2011   Median :2012   Median :2013  
 Mean   :2011   Mean   :2012   Mean   :2013   Mean   :2014  
 3rd Qu.:2011   3rd Qu.:2012   3rd Qu.:2013   3rd Qu.:2014  
 Max.   :2018   Max.   :2018   Max.   :2018   Max.   :2018  
 NA's   :43     NA's   :44     NA's   :46     NA's   :47    
     YEAR_8         YEAR_9              geometry 
 Min.   :2014   Min.   :2015   POLYGON      :87  
 1st Qu.:2014   1st Qu.:2015   epsg:4326    : 0  
 Median :2014   Median :2015   +proj=long...: 0  
 Mean   :2014   Mean   :2015                     
 3rd Qu.:2014   3rd Qu.:2015                     
 Max.   :2017   Max.   :2018                     
 NA's   :50     NA's   :51                       

para el mapa final estas librerias seran de gran ayuda

library(leaflet)

esta instruccion nos permite ver en un mapa del departamento los valores de produccion de cada departamente en un año especifico

bins <- c(0, 250, 500, 1000, 2000, 5000, 10000, 15000)
pal <- colorBin("YlOrRd", domain = Sant_MUN_stat$PROD_12, bins = bins)

  mapa <- leaflet(data = Sant_MUN_stat) %>%
  addTiles() %>%
  addPolygons(label = ~PROD_12,
              popup = ~MPIO_CNMBR,
              fillColor = ~pal(PROD_12),
              color = "#444444",
              weight = 1,
              smoothFactor = 0.5,
              opacity = 1.0,
              fillOpacity = 0.5,
              highlightOptions = highlightOptions(color = "white", weight = 2, bringToFront = TRUE)
              ) %>%
  addProviderTiles(providers$OpenStreetMap) %>%
  addLegend("bottomright", pal = pal, values = ~PROD_12,
    title = "Cacao production in Santander [Ton] (2018)",
    opacity = 1
  )
  

este es el resultado

mapa
LS0tDQp0aXRsZTogIkluZm9ybWUgdGVjbmljbyBTYW50YW5kZXIiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIyMjIEVzdGUgY3VhZGVybm8gcHJldGVuZGUgbW9zdHJhciB1biBhY2VyY2FtaWVudG8gaGFjaWEgbGEgZWNvbm9taWEgYWdyaWNvbGEgZGVsIGRlcGFydGFtZW50bywgYmFzYWRvIGVuIGRhdG9zIGVzcGFjaWFsZXMgeSBubyBlc3BhY2lhbGVzLCBlc3BlY2lmaWNhbWVudGUgdW4gYXJjaGl2byBkZSBldmFsdWFjaW9uZXMgYWdyb3BlY3VhcmlhcyBkZWwgZGVwYXJ0YW1lbnRvIHkgZGF0b3MgZGVsIG1hcmNvIGdlb2VzdGFkaXN0aWNvIG5hY2lvbmFsIGRlbCBhw7FvIDIwMTcNCiMjZXN0YSBwcmltZXJhIGxpbmVhIGJvcnJhIGN1YWxxdWllciBvYmpldG8gcXVlIHB1ZGllcmEgdGVuZXIgYWxtYWNlbmFkbyBlbCBwcm9ncmFtYQ0KYGBge3J9DQpybShsaXN0PWxzKCkpDQpgYGANCiMjIyBlc3RhcyBsaWJyZXJpYXMgc2Vyw6BuIGRlIGdyYW4gdXRpbGlkYWQgcGFyYSBlbCBkZXNhcnJvbGxvIGRlIGxhIHByw6BjdGljYSwgY29uIGVzdGEgbGluZWEgbm9zIGFzZWd1cmFtb3MgZGUgcXVlIHNlIGluc3RhbGVuIHNvbG8gdW5hIHZleiBlbiBlbCBwcm9ncmFtYQ0KYGBge3J9DQpsaXN0Lm9mLnBhY2thZ2VzIDwtIGMoImhlcmUiLCAidGlkeXZlcnNlIiwgInJnZW9zIiwgIm1hcHRvb2xzIiwgInJhc3RlciIsICJzZiIsICAidmlyaWRpcyIsICJybmF0dXJhbGVhcnRoIiwgIkdTT0RSIiwgImdncmVwZWwiLCAiY293cGxvdCIpDQpuZXcucGFja2FnZXMgPC0gbGlzdC5vZi5wYWNrYWdlc1shKGxpc3Qub2YucGFja2FnZXMgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKVssIlBhY2thZ2UiXSldDQppZihsZW5ndGgobmV3LnBhY2thZ2VzKSkgaW5zdGFsbC5wYWNrYWdlcyhuZXcucGFja2FnZXMpDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KGhlcmUpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkocmdlb3MpDQpsaWJyYXJ5KG1hcHRvb2xzKQ0KbGlicmFyeShyYXN0ZXIpDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeSh2aXJpZGlzKQ0KbGlicmFyeShybmF0dXJhbGVhcnRoKQ0KbGlicmFyeShHU09EUikNCmxpYnJhcnkoZ2dyZXBlbCkNCmxpYnJhcnkoY293cGxvdCkNCmBgYA0KIyMgRW4gZXN0ZSBvYmpldG8gdmFtb3MgYSBhc2lnbmFyIGxvcyBkYXRvcyBubyBlc3BhY2lhbGVzIGFzb2NpYWRvcyBhIGxhcyBldmFsdWFjaW9uZXMgYWdyb3BlY3VhcmlhcyBkZWwgZGVwYXJ0YW1lbnRvLCBkb25kZSBzZSBoYWNlIHVuIHJlc3VtZW4gZGUgbG9zIGN1bHRpdm9zIHByb2R1Y2lkb3MgZW4gY2FkYSBtdW5pY2lwaW8sIGFkZW1hcyBkZSBkYXRvcyBlc3RhZGlzdGljb3MgY29tbyBlbCBhcmVhIGN1bHRpdmFkYSBwb3IgY2FkYSBlbGVtZW50byBhZGVtYXMgZGUgdmFsb3JlcyBkZSBwcm9kdWNjaW9uIGFudWFsIGRlIGxvcyBtaXNtb3MNCmBgYHtyfQ0KZGF0b3MgPC0gcmVhZF9jc3YyKCJEOi91bmFsL2dlb21hdGljYS9zYW50YW5kZXIvZXZhbHVhY2lvbiBhZ3JvcGVjdWFyaWFfU2FudGFuZGVyLmNzdiIpDQpkYXRvcw0KYGBgDQojIyBsYXMgc2lndWllbnRlcyBkb3MgbGluZWFzIG5vcyBkZWphbiB2ZXIgdW5hcyBtdWVzdHJhcyBkZSBsb3MgZGF0b3MgYW50ZXJpb3JlcywgbGEgcHJpZW1yYSBub3MgZGVqYSB2ZXIgbGFzIHByaW1lcmFzIHNlaXMgZmlsYXMgeSBsYSBzZWd1bmRhIG5vcyBkZWphIHZlciBsYXMgdWx0aW1hcyBzZWlzIGRlbCBhcmNoaXZvDQpgYGB7cn0NCmhlYWQoZGF0b3MpDQpgYGANCg0KYGBge3J9DQp0YWlsKGRhdG9zKQ0KYGBgDQojIyB2YW1vcyBhIGluaWNpYXIgZWwgdHJhYmFqbyBtb3N0cmFuZG8gZWwgcmVuZGltaWVudG8gcHJvbWVkaW8gZGUgbGEgcHJvZHVjY2lvbiBkZSBsb3MgZGlmZXJlbnRlcyBjdWx0aXZvcyBlbiBjYWRhIHVubyBkZSBsb3MgbXVuY2lwaW9zLCBjb24gZXN0byBwb2RlbW9zIHZlciBxdWUgZ3J1cG8gZGUgY3VsdGl2b3MgcHJlZG9taW5hbiBlbiB0ZW1hIGRlIHJlbmRpbWllbnRvIGFudWFsIGVuIGNhZGEgbXVuaWNpcGlvDQpgYGB7cn0NCmRhdG9zICU+JQ0KICBncm91cF9ieShNVU4sIEdSVV9DVUwpICU+JQ0KICBzdW1tYXJpc2UocmVuZF9wcm9tID0gbWVhbihSRU5ELCBuYS5ybSA9IFRSVUUpKSAtPiBSRU5EX3Jlc3VtZW4NClJFTkRfcmVzdW1lbg0KYGBgDQojI0VuIGVzdGEgbnVldmEgZXhwbG9yYWNpb24sIHZlbW9zIG90cmEgYWdydXBhY2lvbiBkZSBsb3MgZGF0b3MsIGVuIGRvbmRlIHNlIG11ZXN0cmEgZWwgcmVuZGltaWVudG8gcHJvbWVkaW8gZGUgY2FkYSBncnVwbyBkZSBjdWx0aXZvIGVuIFRvbi9hw7FvIGVuIGVsIGRlcGFydGFtZW50bywgZG9uZGUgb2JzZXJ2YW1vcyBxdWUgc2UgZGVzdGFjYW4gbGFzIGhvcnRhbGl6YXMgeSBsYXMgb2xlYWdpbm9zYXMsIG1hcyBhZGVsYW50ZSB2ZXJlbW9zIHF1ZSBpbXBvcnRhbmNpYSBwdWVkZW4gdGVuZXIgZXN0b3MgZGF0b3MNCmBgYHtyfQ0KZGF0b3MgJT4lIGdyb3VwX2J5KEdSVV9DVUwpICU+JSBzdW1tYXJpc2UoUFJPRF9EUFRPPW1lYW4oUFJPRCxuYS5ybT0gVFJVRSkpLT5QUk9EX1NhbnRhbmRlcg0KUFJPRF9TYW50YW5kZXINCmBgYA0KIyMgYXF1aSB2YW1vcyBhIG1vc3RyYXIgcXVlIG11bmljaXBpbyB0dXZvIHVuIG1heW9yIHJlbmRpbWllbnRvIHBhcmEgY2FkYSBncnVwbyBkZSBjdWx0aXZvIGVzcGVjaWZpY2FtZW50ZSBlbiBlbCBhw7FvIDIwMTgNCmBgYHtyfQ0KZGF0b3MgJT4lZmlsdGVyKFlFQVI9PTIwMTgpICU+JSANCiAgZ3JvdXBfYnkoR1JVX0NVTCwgTVVOKSAlPiUNCiAgc3VtbWFyaXplKG1heF9yZW5kID0gbWF4KFJFTkQsIG5hLnJtID0gVFJVRSkpICU+JQ0KICAgIHNsaWNlKHdoaWNoLm1heChtYXhfcmVuZCkpIC0+IFJFTkRfbWF4XzIwMTgNCg0KUkVORF9tYXhfMjAxOA0KYGBgDQojIyBwYXJhIGVzdGEgbnVldmEgdmlzdWFsaXphY2lvbiwgcmVhbGl6YXJlbW9zIHVuIGZpbHRybyBkZSBsb3MgZGF0b3MgZG9uZGUgIHF1ZSBtdW5pY2lwaW8gdHV2byB1bmEgbWF5b3IgYXJlYSBjb3NlY2hhZGEgcGFyYSBjYWRhIGdydXBvIGRlIGN1bHRpdm8sIG9ic2VydmFuZG8gcXVlIGhheSBtdW5pY2lwaW9zIHF1ZSBkZXN0aW5hbiB1bmEgZ3JhbiBzdXBlcmZpY2llIHBhcmEgZWwgdGVtYSBhZ3JpY29sYSwgY29tbyBsbyBzb24gUHVlcnRvIFdpbGNoZXMNCmBgYHtyfQ0KZGF0b3MgJT4lZmlsdGVyKFlFQVI9PTIwMTgpICU+JSBncm91cF9ieShHUlVfQ1VMLCBNVU4pICU+JQ0KICBzdW1tYXJpemUobWF4X0FSRUFfQ09TID0gbWF4KEFSRUFfQ09TLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgICBzbGljZSh3aGljaC5tYXgobWF4X0FSRUFfQ09TKSkgLT4gYXJlYV9jb3NlY2hhX21heA0KDQphcmVhX2Nvc2VjaGFfbWF4DQpgYGANCiMjIGFxdWkgcmVhbGl6YW1vcyB1biBmaWx0cm8gZGUgbG9zIGRhdG9zIHBhcmEgZXhwbG9yYXIgZWwgZ3J1cG8gZGUgY3VsdGl2byBPdHJvcyBwZXJtYW5lbnRlcyBwYXJhIHZlciBxdWUgY3VhbCBmdWUgbGEgbWF4aW1hIHByb2R1Y2Npb24gZGUgZXN0b3MgY3VsdGl2b3MgZGVudHJvIGRlbCB0aWVtcG8gcXVlIGN1YnJlbiBsb3MgZGF0b3MNCmBgYHtyfQ0KZGF0b3MgJT4lIGZpbHRlcihHUlVfQ1VMPT0iT3Ryb3MgUGVybWFuZW50ZXMiKSAlPiUgZ3JvdXBfYnkoTVVOLFNHUlVfQ1VMPSJDYWNhbyIpICU+JSBzdW1tYXJpc2UgKG1heF9QUk9EPW1heChQUk9ELCBuYS5ybSA9IFRSVUUpKSAlPiUgc2xpY2Uod2hpY2gubWF4KG1heF9QUk9EKSktPlBST0RfbWF4DQpQUk9EX21heA0KYGBgDQojIyBoZSBkZWNpY2lkbyByZWFsaXphciB1bmEgb2JzZXJ2YWNpb24gZGUgbG9zIGRhdG9zIGVuIGVsIG11bmljaXBpbyBkZSBTYW4gQmVuaXRvLCBkZWJpZG8gYSBxdWUgZW4gbGEgY29uc3VsdGEgYW50ZXJpb3IsIHNlIG9ic2Vydm8gcXVlIGVzdGUgbXVuaWNpcGlvIHByZXNlbnRhIHVuYSBhbHRhIHByb2R1Y2Npb24gZGUgY2FjYW8sIGxsZWdhbmRvIGxsZWdhbmRvIGhhc3RhIHVuIG1heGltbyBkZSAzNjAwMCBoZWN0YXJlYXMgZGVsIG1pc21vDQpgYGB7cn0NCmRhdG9zICU+JSANCiAgZmlsdGVyKE1VTj09IlNhbiBCZW5pdG8iICYgU0dSVV9DVUw9PSJDYWNhbyIpICU+JSANCiAgZ3JvdXBfYnkoWUVBUiwgQ1VMVCkgLT4gIFZJQ0VOX0NBQ0FPDQpWSUNFTl9DQUNBTw0KYGBgDQojIyBwYXJhIHZlciBlc3RvcyBkYXRvcyBkZSB1bmEgZm9ybWEgZ3JhZmljYSwgbm9zIGFwcm92ZWNoYXJlbW9zIGRlIGxhIGZ1bmNpb24gZ2dwbG90IHBhcmEgdnJsb3MgZGUgZm9ybWEgZ3JhZmljYSB5IGFuYWxpemFybG9zIGRlIG1lam9yIG1hbmVyYSwgZG9uZGUgb2JzZXJ2YW1vcyBxdWUgZWwgYcOxbyBkZSBtYXlvciBwcm9kdWNjaW9uIGVuIGVsIG11bmljaXBpbyBmdWUgZWwgMjAxMyBsbGVnYW5kbyBhIGxhcyAyMDAgdG9uZWxhZGFzIGVuIGVzZSBhw7FvDQpgYGB7cn0NCmcgPC0gZ2dwbG90KGFlcyh4PVlFQVIsIHk9UFJPRC8xMDApLCBkYXRhID0gVklDRU5fQ0FDQU8pICsgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknKSArIGxhYnMoeT0nQ2FjYW8gUHJvZHVjdGlvbiBbVG9uIHggMTAwMF0nKQ0KDQpnICsgZ2d0aXRsZSgiRXZvbHV0aW9uIG9mIGNhY2FvIHByb2R1Y3Rpb24gaW4gU2FuIEJlbml0byBmcm9tIDIwMTMgdG8gMjAxOCIpICsgbGFicyhjYXB0aW9uPSAiQmFzZWQgb24gRU1BIGRhdGEgKERBTkUsIDIwMTgpIikNCmBgYA0KIyMgYWhvcmEsIHNlIHJlYWxpemFyYSBvdHJhIGNvbnN1bHRhLCBlc3RhIHZleiBwYXJhIG9ic2VydmFyIGxhIHN1cGVyZmljaWUgY29zZWNoYWRhIHRvdGFsIHBvciBjYWRhIGdydXBvIGRlIGN1bHRpdm8gZW4gZWwgYcOxbyAyMDE4LCBkb25kZSBzZSBvYnNlcnZhIHF1ZSBsb3MgY3VsdGl2b3MgT3Ryb3MgUGVybWFuZW50ZXMgZGV0YWNhbiBhbXBsaWFtZW50ZSBzb2JyZSBlbCByZXN0bw0KYGBge3J9DQpkYXRvcyAlPiUgDQogIGZpbHRlcihZRUFSPT0yMDE4KSAlPiUgDQogIGdyb3VwX2J5KEdSVV9DVUwpICU+JQ0KICBzdW1tYXJpemUoc3VtX0FSRUFfQ09TID0gc3VtKEFSRUFfQ09TLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgICAgYXJyYW5nZShkZXNjKHN1bV9BUkVBX0NPUykpIC0+IHRvdGFsX0FSRUFfQ09TDQp0b3RhbF9BUkVBX0NPUw0KYGBgDQojIyBiYXNhZG9zIGVuIGxvIGFudGVyaW9yLCB2YW1vcyBhIHJlYWxpemFyIHVuIGZpbHRybyBzb2JyZSBlbCBtaXNtbyBhw7FvLCBwZXJvIHRvbWFuZG8gc29sbyBsb3MgY3VsdGl2b3Mgb3Ryb3MgcGVybWFuZW50ZXMsIGVzdG8gcGFyYSB2ZXIgY3VhbCBjdWx0aXZvIGVuIGVzcGVjaWZpY28gZXMgZWwgcXVlIHByZWRvbWluYSByZXNwZWN0byBhbCBhcmVhIGNvc2VjaGFkYSBlbiBlbCBkZXBhcnRhbWVudG8uIENvbW8gc2Ugb2JzZXJ2YSwgZWwgY2FjYW8ganVudG8gYWwgY2FmZSwgcHJlc250YW4gdW4gZ3JhbiBwb3JjZW50YWplIGRlbCB0b3RhbCwgZG9uZGUgZGVzdGFjYSBlbCBjYWNhbw0KYGBge3J9DQpkYXRvcyAlPiUgZmlsdGVyKEdSVV9DVUw9PSJPdHJvcyBQZXJtYW5lbnRlcyImIFlFQVI9PTIwMTgpICU+JSBncm91cF9ieShDVUxUKSAlPiUgc3VtbWFyaXplKHN1bV9jb3NlY2hhID0gc3VtKEFSRUFfQ09TLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgICAgYXJyYW5nZShkZXNjKHN1bV9jb3NlY2hhKSkgLT4gVE9UX0NPU0VDSEENCg0KVE9UX0NPU0VDSEENCmBgYA0KIyMgYWhvcmEgcXVlIHlhIHNhYmVtb3MgcXVlIGVsIGNhY2FvIGVzIGVsIGN1bHRpdm8gb3RybyBwZXJtYW5lbnRlIGRlIG1heW9yIGFyZWEgY29zZWNoYWRhLCBjb24gZXN0ZSBudWV2byBmaWx0cm8gdmVyZW1vcyBxdWUgbXVuaWNpcGlvIHByZXNlbnRhIHVuYSBtYXlvciBhcmVhIGNvc2VjaGFkYSBkZSBjYWNhbyBlbiBlbCBhw7FvIDIwMTgsIGRvbmRlIHZlbW9zIHF1ZSBlbCBtYXlvciBleHBvbmVudGUgZXMgZWwgbXVuaWNpcGlvIFNhbiBWaWNlbnRlIERlIENodWN1cmkNCmBgYHtyfQ0KZGF0b3MgJT4lIA0KICBmaWx0ZXIoWUVBUj09MjAxOCAmIEdSVV9DVUw9PSJPdHJvcyBQZXJtYW5lbnRlcyIpICU+JSANCiAgZ3JvdXBfYnkoQ1VMVCwgTVVOKSAlPiUNCiAgc3VtbWFyaXplKEFSRUFfQ09TX01VTiA9IG1heChBUkVBX0NPUywgbmEucm0gPSBUUlVFKSkgJT4lDQogICAgc2xpY2Uod2hpY2gubWF4KEFSRUFfQ09TX01VTikpIC0+bWF4X2FyZWEyIA0KDQptYXhfYXJlYTINCmBgYA0KIyMgYW50ZXMgZGUgcmVhbGl6YXIgZWwgcGxvdGVvLCBhIGNhZGEgdW5hIGRlIGxhcyBjbGFzZXMsIHF1ZSBzZXJhbiBsb3MgZ3J1cG9zIGRlIGN1bHRpdm8sIHZhbW9zIGEgcmVhbGl6YXJsZXMgdW5hIGFicmV2aWF0dXJhLCBwYXJhIHF1ZSBzZSBwdWVkYSBsZWVyIGNvbiBjbGFyaWRhZCBlbiBlbCBwbG90ZW8NCmBgYHtyfQ0KdG90YWxfQVJFQV9DT1MkQ1JPUCA8LSBhYmJyZXZpYXRlKHRvdGFsX0FSRUFfQ09TJEdSVV9DVUwsIDMpDQpgYGANCiMjIGVzdGUgcGxvdGVvIG5vcyBtdWVzdHJhIGVsIGFyZWEgY3VsdGl2YWRhIHBvciBjYWRhIGdydXBvIGRlIGN1bHRpdm8gZW4gZWwgYcOxbyAyMDE4LCB2ZXJlbW9zIGxhIG1pc21hIGluZm9ybWFjaW9uIGRlIGhhY2UgdmFyaWFzIGxpbmVhcywgcGVybyBjb24gZXN0ZSBncmFmaWNvLCBzZXJhIG11Y2hvIG1hcyBmYWNpbCBkZSBzYWNhciBjb25jbHVzaW9uZXMgc29icmUgZWwgbWlzbW8NCmBgYHtyfQ0KZyA8LSBnZ3Bsb3QoYWVzKHg9Q1JPUCwgeT1zdW1fQVJFQV9DT1MpLCBkYXRhID0gdG90YWxfQVJFQV9DT1MpICsgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknKSArIGxhYnMoeT0nVG90YWwgSGFydmVzdGVkIEFyZWEgW0hhXScpDQpgYGANCg0KYGBge3J9DQpnKyBnZ3RpdGxlKCJUb3RhbCBoYXJ2ZXN0ZWQgYXJlYSBieSBjcm9wIGdyb3VwcyBpbiAyMDE4IGZvciBTYW50YW5kZXIiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArDQogICBsYWJzKGNhcHRpb249ICJCYXNlZCBvbiBFTUEgZGF0YSAoREFORSwgMjAxOCkiKQ0KYGBgDQojIyBsYSBzZWd1bmRhIHBhcnRlIGRlbCBpbmZvcm1lIGNvbnNpc3RpcmEgZW4gcmVhbGl6YXIgdW5hIHVuaW9uIGVudHJlIGxvcyBkYXRvcyBubyBlc3BhY2lsYWVzIG1vc3RyYWRvcyBlbiBsYSBwcmltZXJhcGFydGUgeSB1biBhcmNoaXZvIGRlIGRhdG9zIGVzcGFjaWFsZXMgcHJvdmVuaWVudGUgZGVsIG1hcmNvIGdlb2VzdGFkaXN0aWNvIGRlbCBwYWlzIHByb3ZlbmluZXRvIGRlbCBEQU5FDQpgYGB7cn0NClNhbnRfTVVOIDwtc2Y6OnN0X3JlYWQoIkQ6L3VuYWwvZ2VvbWF0aWNhL3NhbnRhbmRlci9tYXJjbyBnZW9lc3RhZGlzaXRpY28vNjhfU0FOVEFOREVSL0FETUlOSVNUUkFUSVZPL01HTl9NUElPX1BPTElUSUNPLnNocCIpDQpgYGANCiMjIHZlYW1vcyBxdWUgdGllbmUgZXN0ZSBhcmNoaXZvIC5zaHANCmBgYHtyfQ0KU2FudF9NVU4NCmBgYA0KIyMgcGFyYSByZWFsaXphciBlbCBqb2luIG5lY2VzaXRhbW9zIHVuIGNhbXBvIGVuIGNvbXVuIGVudHJlIGFtYm9zIHBhcXVldGVzIGRlIGRhdG9zLCBwb3IgbG8gcXVlIHVzYXJlbW9zIGVsIGNvZGlnbyBkZSBtdW5pY2lwaW8gcGFyYSBlbGxvLCBlc3RhcyBkb3MgbGluZWFzIG5vcyBzZXJ2aXJhbiBwYXJhIGNyZWFyIGRvcyBjYW1wb3MgbnVldm9zIGEgbG9zIGRhdG9zIG5vIGVzcGFjaWFsZXMsIGNvbmVsIG9iamV0aXZvIGRlIGNvbnZlcnRpciBsYSBjb2x1bW5hIENPRF9NVU4gcXVlIGVzIHVuIG9iamV0byBkZSB0aXBvIG51bWVyaWNvIGEgdW4gb2JqZXRvIGRlIHRpcG8gZmFjdG9yLCBjb3NhIGZ1bmRhbWVudGFsIHBhcmEgcmVhbGl6YXIgZWwgam9pbg0KYGBge3J9DQpkYXRvc18yIDwtIGRhdG9zDQpkYXRvc18yJFRFTVAgPC0gIGFzLmNoYXJhY3RlcihkYXRvc18yJENPRF9NVU4pDQpgYGANCg0KDQpgYGB7cn0NCmRhdG9zXzIkTVBJT19DQ0RHTyA8LSBhcy5mYWN0b3IoZGF0b3NfMiRURU1QKQ0KZGF0b3NfMg0KYGBgDQojIyBhaG9yYSBhbCBvYmpldG8gZGF0b3NfMiBsZSByZWFsaXphcmVtb3MgdW4gZmlsdHJvIHF1ZSBjb25zaXN0aXJhIGVuIHF1ZSBzb2xvIHRvbWFyYSBsb3MgZGF0b3MgZW4gZWwgcXVlIHNlIGFuYWxpemUgZWwgY2FjYW8gZW4gY2FkYSB1bm8gZGUgbG9zIG11bmljaXBpb3MgZGVsIGRlcGFydGFtZW50by4gRWwgcmVzdWx0YWRvIGRlIGVzdG8gc2UgYWxtYWNlbmFyYSBlbiB1biBudWV2byBvYmpldG8gbGxhbWFkbyBkYXRvc18zDQpgYGB7cn0NCmRhdG9zXzIgJT4lIGZpbHRlcihDVUxUID09ICJDYWNhbyIpICAtPiBkYXRvc18zDQpkYXRvc18zDQpgYGANCiMjIEFxdWkgdmVtb3MgbGEgY2xhc2UgZGVsIG9iamV0byByZWNpZW4gY3JlYWRvLCB2ZW1vcyBxdWUgc2UgdHJhdGEgZGUgdW4gZGF0YWZyYW1lLCBjb3NhIHF1ZSBlcyBidWVuYSBwYXJhIHJlYWxpemFyIGVsIGpvaW4NCmBgYHtyfQ0KY2xhc3MoZGF0b3NfMykNCmBgYA0KIyMgcGFyYSBlc3RlIG51ZXZvIG9iamV0byB0b21hcmVtb3Mgc29sbyBsb3MgY2FtcG9zIHF1ZSBub3Mgc2VhbiBkZSByZWFsIGludGVyZXMgZGVsIG9iamV0byBkYXRvc18zLCBlbnRyZSBlbGxvcyBlbCBjYW1wbyBjcmVhZG8gcHJldmlhbWVudGUgcXVlIGVzIHVuIGZhY3Rvcg0KYGBge3J9DQpkYXRvc180IDwtIGRhdG9zXzMgJT4lIGRwbHlyOjpzZWxlY3QoTVVOLCBNUElPX0NDREdPLCBZRUFSLCBQUk9ELCBSRU5EKSANCmBgYA0KIyMgYWhvcmEgYWwgcmVzdWx0YWRvIGRlIGxhIGxpbmVhIGFudGVyaW9yIHZhbW9zIGEgb3JnYW5pemFybG8gZGUgbWFuZXJhIGNyb25vbG9naWNhLCBlcyBkZWNpciwgdmVyZW1vcyBsb3MgZGF0b3MgZGUgY2FkYSBtdW5pY2lwaW8gZW4gdW4gYcOxbywgbHVlZ28gbG9zIGRlbCBzaWd1aWVudGUgYXNpIGhhc3RhIGN1YnJpciB0b2RvcyBsb3MgZGF0b3MNCmBgYHtyfQ0KZGF0b3NfNCAlPiUgDQogIGdhdGhlcigiWUVBUiIsICJQUk9EIiwgIlJFTkQiICwga2V5ID0gdmFyaWFibGUsIHZhbHVlID0gbnVtYmVyKQ0KZGF0b3NfNA0KYGBgDQojIGFob3JhIHZhbW9zIGEgcGFzYXIgZGUgdW5hIG9yZ2FuaXphY2lvbiBkZSBsb3MgZGF0b3MgZW4gZm9ybWEgbGFyZ2EsIGVzIGRlY2lyIGNvbiBtdWNoYXMgZmlsYXMgeSBwb2NhcyBjb2x1bW5hcyBhIHVuYSBvcmduaXphY2lvbiBsYXJnYSBjb24gbXVjaGFzIGNvbHVtbmFzIHkgcG9jYXMgZmlsYXMsIGRlIG1hbmVyYSBxdWUgZW4gY2FkYSBjb2x1bW5hIHZlYW1vcyBsb3MgZGF0b3MgZGUgcHJvZHVjY2lvbiB5IHJlbmRpbWllbnRvIGRlIGNhZGEgYcOxIGVuIGNvbHVtbmFzIGluZGVwZW5kaWVudGVzLCBlbCByZXN1bHRhZG8gZGUgZXN0ZSBwcm9jZXNvIHNlIGFsYW1hY2VuYXJhIGVuIHVuIG51ZXZvIG9iamV0byBkZSBub21icmUgZGF0b3NfNQ0KYGBge3J9DQpkYXRvc180ICU+JSANCiAgZ3JvdXBfYnkoTVBJT19DQ0RHTykgJT4lIA0KICBtdXRhdGUoVmlzaXQgPSAxOm4oKSkgJT4lIA0KICBnYXRoZXIoIllFQVIiLCAiUFJPRCIsICJSRU5EIiwga2V5ID0gdmFyaWFibGUsIHZhbHVlID0gbnVtYmVyKSAlPiUgDQogIHVuaXRlKGNvbWJpLCB2YXJpYWJsZSwgVmlzaXQpICU+JQ0KICBzcHJlYWQoY29tYmksIG51bWJlcikgLT4gZGF0b3NfNQ0KaGVhZChkYXRvc181KQ0KYGBgDQoNCiMjIHlhIHF1ZSB0ZW5lbW9zIHRvZG9zIGxvcyBlbGVtZW50b3MgbmVjZXNhcmlvcywgcHJvY2VkZW1vcyBhIHJlYWxpemFyIGVsIGpvaW4gZW50cmUgbG9zIGRhdG9zIG5vIGVzcGFjaWFsZXMgeSBsb3MgZGF0b3MgZXNwYWNpYWxlcywgdG9tYW5kbyBjb21vIHB1bnRvIGNvbXVuIGVsIGNhbXBvIE1QSU9fQ0NER08NCmBgYHtyfQ0KU2FudF9NVU5fc3RhdCA9bGVmdF9qb2luKFNhbnRfTVVOLCBkYXRvc181LCBieT0iTVBJT19DQ0RHTyIpDQpzdW1tYXJ5KFNhbnRfTVVOX3N0YXQpDQpgYGANCiMjIHBhcmEgZWwgbWFwYSBmaW5hbCBlc3RhcyBsaWJyZXJpYXMgc2VyYW4gZGUgZ3JhbiBheXVkYQ0KYGBge3J9DQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkobGVhZmxldCkNCmBgYA0KIyMgZXN0YSBpbnN0cnVjY2lvbiBub3MgcGVybWl0ZSB2ZXIgZW4gdW4gbWFwYSBkZWwgZGVwYXJ0YW1lbnRvIGxvcyB2YWxvcmVzIGRlIHByb2R1Y2Npb24gZGUgY2FkYSBkZXBhcnRhbWVudGUgZW4gdW4gYcOxbyBlc3BlY2lmaWNvDQpgYGB7cn0NCmJpbnMgPC0gYygwLCAyNTAsIDUwMCwgMTAwMCwgMjAwMCwgNTAwMCwgMTAwMDAsIDE1MDAwKQ0KcGFsIDwtIGNvbG9yQmluKCJZbE9yUmQiLCBkb21haW4gPSBTYW50X01VTl9zdGF0JFBST0RfMTIsIGJpbnMgPSBiaW5zKQ0KDQogIG1hcGEgPC0gbGVhZmxldChkYXRhID0gU2FudF9NVU5fc3RhdCkgJT4lDQogIGFkZFRpbGVzKCkgJT4lDQogIGFkZFBvbHlnb25zKGxhYmVsID0gflBST0RfMTIsDQogICAgICAgICAgICAgIHBvcHVwID0gfk1QSU9fQ05NQlIsDQogICAgICAgICAgICAgIGZpbGxDb2xvciA9IH5wYWwoUFJPRF8xMiksDQogICAgICAgICAgICAgIGNvbG9yID0gIiM0NDQ0NDQiLA0KICAgICAgICAgICAgICB3ZWlnaHQgPSAxLA0KICAgICAgICAgICAgICBzbW9vdGhGYWN0b3IgPSAwLjUsDQogICAgICAgICAgICAgIG9wYWNpdHkgPSAxLjAsDQogICAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0gMC41LA0KICAgICAgICAgICAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucyhjb2xvciA9ICJ3aGl0ZSIsIHdlaWdodCA9IDIsIGJyaW5nVG9Gcm9udCA9IFRSVUUpDQogICAgICAgICAgICAgICkgJT4lDQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJE9wZW5TdHJlZXRNYXApICU+JQ0KICBhZGRMZWdlbmQoImJvdHRvbXJpZ2h0IiwgcGFsID0gcGFsLCB2YWx1ZXMgPSB+UFJPRF8xMiwNCiAgICB0aXRsZSA9ICJDYWNhbyBwcm9kdWN0aW9uIGluIFNhbnRhbmRlciBbVG9uXSAoMjAxOCkiLA0KICAgIG9wYWNpdHkgPSAxDQogICkNCiAgDQpgYGANCiMjIGVzdGUgZXMgZWwgcmVzdWx0YWRvDQpgYGB7cn0NCm1hcGENCmBgYA0KDQo=