Introducción

Durante octubre de 2020 realizamos con el Club de R para RRHH un relevamiento de sueldos de RH para Argentina y otros países de Latinoamérica. Si bien parte de ese análisis está publicado no hicimos ningún análisis de los sueldos por provincias. Con lo cual el objetivo de este trabajo será:

Analizar los sueldos de los y las profesionales que trabajan en Recursos Humanos por provincia y región de la Argentina.

Para lograr este objetivo utilizaré algunas técnicas aprendidas en los Módulos I y II de la Diplomatura de Ciencias Sociales Computacionales y Humanidades Digitales de la UNSAM.

Preparación de los Datos

Para este trabajo utilizaré dos datasets, un archivo shape de Argentina obtenida de la página datos.gob.ar para poder visualizar los resultados de las distintas provincias del país, y una muestra de la Encuesta KIWI (Key Investigation of Wages and Incomes) de Sueldos de RH con las respuestas obtenidas de profesionales de Argentina.

En el análisis utilizaré los paquetes tidyverse() para la transformación y visualización de datos, el paquete funModeling() para hacer una limpieza de los sueldos extremos. El paquete sf() para poder leer los datos espaciales, y hacer las visualizaciones en un mapa. También utilizaré el paquete extrafont() para poder cambiar las fuentes de las visualizaciones.

En primer lugar cargamos las librerías necesarias, y luego cargamos los datos.

# Librerías ------------
library(tidyverse)
library(funModeling)
library(sf)
library(extrafont)
library(scales)

# Datos ---------------

# Datos de sueldos de RH
rh <- read_delim("Fuentes/rh.csv",
                 delim = ";")

# Mapa de Argentina
arg <- st_read("ign_provincia/Provincia/ign_provincia.shp")
## Reading layer `ign_provincia' from data source 
##   `C:\Users\chech\OneDrive\Documents\R\unsam_dcschd\ign_provincia\Provincia\ign_provincia.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 24 features and 11 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XYZ
## Bounding box:  xmin: -74 ymin: -90 xmax: -25 ymax: -21.78086
## z_range:       zmin: 0 zmax: 0
## Geodetic CRS:  WGS 84 + WGS_1984_Geoid

Elementos accesorios

Con el objetivo de generar visualizaciones más atractivas y personalizadas vamos a crear una serie de objetos personalizados para reutilizar en los gráficos.

options(scipen = 999)   # Elimina notación científica de los gráficos.

loadfonts(quiet = TRUE) # Permite cargar en R otros tipos de fuentes.

# Estilo limpio sin líneas de fondo
estilo <- theme(panel.grid = element_blank(),
                plot.background = element_rect(fill = "#FBFCFC"),
                panel.background = element_blank(),
                text = element_text(family = "Ubuntu"),
                plot.title.position = "plot")

# Estilo limpio con líneas de referencia verticales en gris claro
estilov <- theme(panel.grid = element_blank(),
                 plot.background = element_rect(fill = "#FBFCFC"),
                 panel.background = element_blank(),
                 panel.grid.major.x = element_line(color = "#AEB6BF"),
                 text = element_text(family = "Ubuntu"),
                 plot.title.position = "plot")

# Estilo limpio con líneas de referencia horizontales en gris claro
estiloh <- theme(panel.grid = element_blank(),
                 plot.background = element_rect(fill = "#FBFCFC"),
                 panel.background = element_blank(),
                 panel.grid.major.y = element_line(color = "#AEB6BF"),
                 text = element_text(family = "Ubuntu"),
                 plot.title.position = "plot")

# Paleta de colores para género
colores <-  c("#1FC3AA", "#8624F5")

# Creo objetos para formatear las etiquetas numéricas de los ejes x e y
eje_x_n <- scale_x_continuous(labels = comma_format(big.mark = ".", decimal.mark = ","))

eje_y_n <- scale_y_continuous(labels = comma_format(big.mark = ".", decimal.mark = ","))

Exploración de los datos

En primer lugar, exploremos algunas características de los data frames que acabamos de cargar.

# Tipo de objeto
class(arg)
## [1] "sf"         "data.frame"
# Tamaño del data frame
dim(arg)
## [1] 24 12
# Nombres y muestras de datos
glimpse(arg)
## Rows: 24
## Columns: 12
## $ OBJECTID   <dbl> 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438,~
## $ Entidad    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,~
## $ Objeto     <chr> "Provincia", "Provincia", "Provincia", "Provincia", "Provin~
## $ FNA        <chr> "Ciudad Autónoma de Buenos Aires", "Provincia del Neuquén",~
## $ GNA        <chr> "Ciudad Autónoma", "Provincia", "Provincia", "Provincia", "~
## $ NAM        <chr> "Ciudad Autónoma de Buenos Aires", "Neuquén", "La Pampa", "~
## $ SAG        <chr> "IGN", "IGN", "IGN", "IGN", "IGN", "IGN", "IGN", "IGN", "IG~
## $ FDC        <chr> "Geografía", "Geografía", "Geografía", "Geografía", "Geogra~
## $ IN1        <chr> "02", "58", "42", "50", "74", "14", "82", "30", "70", "46",~
## $ SHAPE_STAr <dbl> 0.02024179, 9.77181088, 14.55301930, 14.65838794, 7.3337705~
## $ SHAPE_STLe <dbl> 0.7438065, 21.5159846, 19.6656145, 23.2599862, 14.4901958, ~
## $ geometry   <MULTIPOLYGON [°]> MULTIPOLYGON Z (((-58.34189..., MULTIPOLYGON Z~

Podemos apreciar que el objeto arg es un data frame de tipo sf, es decir que contiene las coordenadas geográficas para graficar un mapa, que contiene 24 filas y 12 columnas. La variable que contiene los nombres de las provincias para hacer un join con el dataset rh es la columna NAM.

Ahora, realicemos un análisis inicial similar del data frame de sueldos de RH.

# Tipo de objeto
class(rh)
## [1] "spec_tbl_df" "tbl_df"      "tbl"         "data.frame"
# Tamaño del data frame
dim(rh)
## [1] 661  43

Este data frame es un tabla de tipo tibble que contiene 661 filas y 43 columnas. Al ser tanta, en vez de utilizar la función glimpse() usaremos la función names() para ver los nombres de las columnas.

names(rh)
##  [1] "Marca.temporal"             "genero"                    
##  [3] "genero_diverso"             "edad"                      
##  [5] "discapacidad"               "nivel_formacion"           
##  [7] "carrera_grado"              "tipo_universidad"          
##  [9] "pais"                       "provincia"                 
## [11] "trabajo"                    "rubro"                     
## [13] "dotacion"                   "origen_capital"            
## [15] "dotacion_rh"                "puesto"                    
## [17] "tipo_contratacion"          "funcion_rh"                
## [19] "personas_a_cargo"           "anios_en_empresa"          
## [21] "anios_en_puesto"            "anios_experiencia"         
## [23] "sueldo_bruto"               "beneficios"                
## [25] "bono"                       "ajuste"                    
## [27] "ajuste_porcentaje"          "ajuste_mes"                
## [29] "otros_proyectos"            "erp"                       
## [31] "nombre_area"                "mate"                      
## [33] "idioma_exigencia"           "idioma_porcentaje"         
## [35] "contactos_linkedin"         "satisfaccion"              
## [37] "busqueda"                   "beneficios_expectativa"    
## [39] "rh_una_palabra"             "pregunta_bizarra"          
## [41] "teletrabajo"                "elementos"                 
## [43] "valoracion_gestion_empresa"

El relevamiento de la Encuesta KIWI abarcó temas muy diversos como salario y género, y otros totalmente ridículos como si se podía tomar mate en la oficina (prepandemia) o el nombre del área. Para los propósitos de este trabajo limitaremos la cantidad de columnas para analizar.

Nos quedaremos únicamente con las variables provincia, genero, puesto, y sueldo_bruto. Hay mucha tela para cortar en el análisis pero por el alcance del trabajo nos limitaremos en el desarrollo.

rh <- rh %>% # Sobrescribimos el objeto rh 
  filter(pais == "Argentina",                        # Seleccionamos las respuestas de Argentina
         genero %in% c("Masculino", "Femenino")) %>% # Seleccionamos géneros para analizar   
  select(provincia, genero, puesto, sueldo_bruto) %>%  # Variables seleccionadas
  mutate_if(is.character, as_factor) # Pasamos las varibles character como factor

Realicemos un primer análisis exploratorio del data frame rh.

summary(rh)
##                            provincia         genero               puesto   
##  Ciudad Autónoma de Buenos Aires:275   Masculino:186   Analista      :221  
##  Buenos Aires                   :119   Femenino :409   Responsable   :134  
##  Córdoba                        : 44                   Jefe          : 69  
##  San Juan                       : 42                   HRBP          : 57  
##  Santa Fe                       : 29                   Gerente       : 48  
##  Chaco                          : 14                   Administrativo: 47  
##  (Other)                        : 72                   (Other)       : 19  
##   sueldo_bruto    
##  Min.   :      0  
##  1st Qu.:  52000  
##  Median :  72000  
##  Mean   :  90758  
##  3rd Qu.: 102000  
##  Max.   :2140000  
## 

Una primera limpieza que vamos a realizar es la de reducir la cantidad de posiciones. Dada la cantidad de respuestas recibidas, vamos a eliminar las posiciones de Director y de Pasante. Y luego vamos a definir el orden correspondiente a la jerarquía de las posiciones.

rh <- rh %>% 
  filter(!puesto %in% c("Pasante", "Director")) %>% 
  mutate(puesto = factor(puesto, 
                         levels = c("Administrativo", "Analista", "HRBP",
                                    "Responsable", "Jefe", "Gerente"))) 

Y otra variable que hace falta limpiar es la de sueldo_bruto. Tenemos registrado un sueldo mínimo de AR$ 2 y el sueldo máximo es de AR$ 2140000. Para lograr sueldos más representativos, vamos a eliminar los valores que estén por debajo del percentil 5 y los valores que están por encima del percentil 95.

Nos apoyaremos en el paquete funModeling para detectar los valores en ambos percentiles y usarlo posteriormente en el análisis.

# Sacamos los valores descriptivos de la variable numérica
valores <- profiling_num(rh)

# Extraemos los percentiles 5 y 95
p05 <- valores[1,6]
p95 <- valores[1,10]

# Filtramos en la variable sueldo_bruto los valores extremos 
rh1 <- rh %>% 
  filter(between(   # Función auxiliar para filtrar valores
    sueldo_bruto,   # Variable a filtrar
    p05,            # Filtro inferior
    p95             # Filtro superior
  ))

# Eliminamos objetos que no reutilizaremos para liberar memoria
rm(valores, p05, p95)

# Análisis descriptivo de la variable sueldo_bruto
summary(rh1$sueldo_bruto)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   30000   54100   72000   79375   95500  190000

Comparemos cómo queda la variable sueldo_bruto antes y después de la limpieza:

# Boxplot variable original
ggplot(rh, aes(x = sueldo_bruto)) +
  geom_histogram() +
  ggtitle("Distribución variable original") +
  estiloh +
  eje_x_n

# Boxplot variable original
ggplot(rh1, aes(x = sueldo_bruto)) +
  geom_histogram() +
  ggtitle("Distribución variable limpia") +
  estiloh +
  eje_x_n

En estos dos histogramas podemos apreciar la influencia de los outliers, que nos impiden en el data frame original la distribución de los sueldos por debajo de los AR$ 500.000. En el segundo gráfico, luego de la limpieza de la variable sueldo_bruto podemos apreciar los picos en los AR$ 50.000 y en los AR$ 75.000.

Analizar la distribución de las variables es muy importante, porque muchas veces, las métricas de resumen estadístico pueden estar “tapando” algunos problemas. Por ejemplo, miremos la mediana salarial de los sueldos por género y por puesto.

rh1 %>% 
  group_by(puesto, genero) %>% 
  summarise(mediana_salarial = median(sueldo_bruto)) %>% 
  ggplot(aes(x = puesto, y = mediana_salarial, fill = genero)) +
  geom_col(position = "dodge") +
  scale_fill_manual(values = colores) +
  estiloh +
  eje_y_n +
    labs(title = "Mediana salarial por puesto y género",
         subtitle = "En AR$",
         fill = "Género",
         x = "", y = "")

En el gráfico de barras, podemos apreciar que si bien en varios puestos, como el de Responsable, o el de Analista los sueldos de los varones son más altos que en el caso de las mujeres, podemos apreciar una paridad en las posiciones de HRBP y Jefe. Pero analicemos la misma variable con un boxplot que nos permite apreciar la distribución de los gráficos.

ggplot(rh1, aes(x = puesto, y = sueldo_bruto, fill = genero)) +
  geom_boxplot() +
  scale_fill_manual(values = colores) +
  estiloh +
  eje_y_n +
  labs(title = "Distribución de sueldos brutos por puesto y género",
       subtitle = "En AR$",
       x = "", y = "",
       fill = "Género")

En los boxplots podemos apreciar la mediana salarial con la barra negra que está dentro de las cajas. El ancho de las cajas nos dan la idea de cómo se distribuyen los salarios entre el 1° cuartil y el 3° cuartil.

Analicemos el puesto de Gerente. La caja correspondiente a las personas de género masculino están bien concentradas en torno a la mediana, mientras que el recorrido de los sueldos de las personas de género femenino es más amplio, y llegando a valores mucho más bajos.

Y si analizamos el puesto de Jefe, donde la mediana es prácticamente la misma para hombres y mujeres, pero la amplitud de la caja entre el 1° cuartil y la mediana es mayor en las mujeres que en los hombres; lo opuesto a lo que sucede entre la mediana y el 3° cuartil. Esto significa que los sueldos de las mujeres en el puesto de Jefe llegan a valores más bajos que en los varones, y que el sueldo de los varones, llega a sueldos más altos que sus pares mujeres.

Análisis provincial

Un análisis que faltó hacer en el trabajo publicado es el análisis de sueldos por provincia. En parte, por la disparidad en la cantidad de respuestas recibidas.

DT::datatable(rh1 %>% 
  count(provincia, sort = T))

Podríamos hacer un ranking simple de sueldo promedio por provincia, con un gráfico de pirulín (Vazquez Brust dixit):

rh1 %>% 
  group_by(provincia) %>% 
  summarise(media_salarial = mean(sueldo_bruto)) %>% 
  ggplot(aes(x = media_salarial, y = fct_reorder(provincia, media_salarial))) +
  geom_point(color = "#3B3176", size = 3) +
  geom_segment(aes(x = 0, xend = media_salarial, y = provincia, yend = provincia), 
               color = "#5C5393") +
  labs(title = "Ranking de sueldo promedio por provincia",
       subtitle = "En AR$",
       x = "Sueldo promedio",
       y = "") +
  eje_x_n +
  estilov

Unificando data frames

El objetivo del trabajo es realizar un análisis de los sueldos en RRHH en el país. En el gráfico anterior podíamos ver en el top-five a tres provincias patagónicas, pero exige cierto esfuerzo por parte del lector interpretar las diferencias salariales entre regiones. Para facilitar la interpretación de las diferencias salariales crearemos una variable nueva en el data frame arg.

Para definir las regiones utilizaremos esta guía.

regiones <- data.frame(
  provincia = c("Buenos Aires", "Entre Ríos", "Santa Fe", "La Pampa", "Córdoba",
          "Misiones", "Corrientes", "Chaco", "Formosa",
          "Jujuy", "Salta", "Tucumán", "Catamarca", "Santiago del Estero",
          "Mendoza", "San Juan", "San Luis", "La Rioja",
          "Neuquén", "Río Negro", "Chubut", "Santa Cruz", "Tierra del Fuego, Antártida e Islas del Atlántico Sur"),
  region = c(rep("Centro", 5),
             rep("NEA", 4),
             rep("NOA", 5),
             rep("Cuyo", 4),
             rep("Patagonia", 5)
             )
  )

Luego, agregamos el dato de la región al data frame de arg. sueldos promedio por provincia. Renombramos la columna provincia por NAM para poder hacer incorporar la información de sueldos y de región al data frame del país.

arg <- left_join(arg, regiones,
                 by = c("NAM" = "provincia"))

glimpse(arg)
## Rows: 24
## Columns: 13
## $ OBJECTID   <dbl> 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438,~
## $ Entidad    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,~
## $ Objeto     <chr> "Provincia", "Provincia", "Provincia", "Provincia", "Provin~
## $ FNA        <chr> "Ciudad Autónoma de Buenos Aires", "Provincia del Neuquén",~
## $ GNA        <chr> "Ciudad Autónoma", "Provincia", "Provincia", "Provincia", "~
## $ NAM        <chr> "Ciudad Autónoma de Buenos Aires", "Neuquén", "La Pampa", "~
## $ SAG        <chr> "IGN", "IGN", "IGN", "IGN", "IGN", "IGN", "IGN", "IGN", "IG~
## $ FDC        <chr> "Geografía", "Geografía", "Geografía", "Geografía", "Geogra~
## $ IN1        <chr> "02", "58", "42", "50", "74", "14", "82", "30", "70", "46",~
## $ SHAPE_STAr <dbl> 0.02024179, 9.77181088, 14.55301930, 14.65838794, 7.3337705~
## $ SHAPE_STLe <dbl> 0.7438065, 21.5159846, 19.6656145, 23.2599862, 14.4901958, ~
## $ region     <chr> NA, "Patagonia", "Centro", "Cuyo", "Cuyo", "Centro", "Centr~
## $ geometry   <MULTIPOLYGON [°]> MULTIPOLYGON Z (((-58.34189..., MULTIPOLYGON Z~

El próximo paso es incorporar la columna de la región a rh1 y crear un nuevo data frame resumiendo los sueldos promedio por región.

# Realizo el join
rh1 <- left_join(rh1, regiones, 
                 by = "provincia")

# Creación del data frame con sueldos promedio por región
sueldo_region <- rh1 %>% 
  group_by(region) %>% 
  summarise(sueldo_promedio = mean(sueldo_bruto)) %>% 
  ungroup()

Finalmente, incorporamos los sueldos y la región al data frame arg.

arg <- left_join(arg, sueldo_region,
                 by = "region") 

glimpse(arg)
## Rows: 24
## Columns: 14
## $ OBJECTID        <dbl> 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437,~
## $ Entidad         <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ Objeto          <chr> "Provincia", "Provincia", "Provincia", "Provincia", "P~
## $ FNA             <chr> "Ciudad Autónoma de Buenos Aires", "Provincia del Neuq~
## $ GNA             <chr> "Ciudad Autónoma", "Provincia", "Provincia", "Provinci~
## $ NAM             <chr> "Ciudad Autónoma de Buenos Aires", "Neuquén", "La Pamp~
## $ SAG             <chr> "IGN", "IGN", "IGN", "IGN", "IGN", "IGN", "IGN", "IGN"~
## $ FDC             <chr> "Geografía", "Geografía", "Geografía", "Geografía", "G~
## $ IN1             <chr> "02", "58", "42", "50", "74", "14", "82", "30", "70", ~
## $ SHAPE_STAr      <dbl> 0.02024179, 9.77181088, 14.55301930, 14.65838794, 7.33~
## $ SHAPE_STLe      <dbl> 0.7438065, 21.5159846, 19.6656145, 23.2599862, 14.4901~
## $ region          <chr> NA, "Patagonia", "Centro", "Cuyo", "Cuyo", "Centro", "~
## $ sueldo_promedio <dbl> 80758.42, 106113.60, 80947.51, 71533.75, 71533.75, 809~
## $ geometry        <MULTIPOLYGON [°]> MULTIPOLYGON Z (((-58.34189..., MULTIPOLY~

Análisis final y conclusiones

Una vez que contamos con toda la información unificada, podemos hacer un análisis de los sueldos promedio por región. Para este propósito visualizaremos en un mapa de la Argentina los sueldos de cada región.

ggplot(arg, aes(fill = sueldo_promedio)) +
  geom_sf() +
  scale_fill_viridis_b() +
  # Limitamos los ejes para visualizar mejor al país
  scale_y_continuous(limits = c(-22, -56)) +
  scale_x_continuous(limits = c(-53, -74)) +
  labs(title ="Sueldo promedio por región",
       subtitle = "en AR$",
       fill = "Sueldo promedio") +
  estilo

En el gráfico podemos apreciar que los sueldos en la Patagonia son los más altos del país y en la región del NEA se encuentran los más bajos. Podríamos haber hecho la visualización por provincia, pero dado que hubieron provincias de las que no obtuvimos información, como Santiago del Estero por ejemplo, y en algunos casos sólo recibimos una sola respuesta como en el caso de Tierra del Fuego, decidimos tomar los datos de forma regional.

Conclusiones

Si bien el análisis es imperfecto dada la disparidad de respuestas recibidas por provincias, tiene sentido que los sueldos más altos se encuentren en el sur del país, por un lado por la presencia de empresas petroleras y mineras, y además que al ser provincias tan remotas, también haya incentivos para relocalizar profesionales.

La región central nuclea a un gran número de empresas, concentra actividades con gran peso en la economía del país, y es la región que concentra la mayoría de la actividad económica y productiva del país, lo cual explica que estén los sueldos más altos a nivel nacional.

En un futuro análisis se podría incorporar más información sobre la actividad económica de las regiones, del peso del trabajo en ámbitos públicos y privados en las provincias, y la diversidad de actividades para poder buscar correlatos entre la actividad económica y los sueldos de los profesionales de Recursos Humanos.

Hubiera sido ideal contar con una mayor homogeneidad de respuestas de todas las provincias para poder que la información sea más representativa de la situación de los profesionales de Recursos Humanos en el país pero a priori fue una sorpresa que los sueldos en la Patagonia sean más altos que los de la región Central del país.

LS0tDQp0aXRsZTogIlRyYWJham8gSW50ZWdyYWRvciBNw7NkdWxvcyBJIHkgSUkiDQpzdWJ0aXRsZTogIkRpcGxvbWF0dXJhIENpZW5jaWFzIFNvY2lhbGVzIENvbXB1dGFjaW9uYWxlcyB5IEh1bWFuaWRhZGVzIERpZ2l0YWxlcyINCmF1dGhvcjogIlNlcmdpbyBHYXJjaWEgTW9yYSINCmRhdGU6ICI3LzgvMjAyMSINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdGhlbWU6IGx1bWVuDQogICAgaGlnaGxpZ2h0OiBweWdtZW50cw0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZpZy5yZXRpbmEgPSAzKQ0KYGBgDQoNCiMgSW50cm9kdWNjacOzbg0KDQpEdXJhbnRlIG9jdHVicmUgZGUgMjAyMCByZWFsaXphbW9zIGNvbiBlbCBbQ2x1YiBkZSBSIHBhcmEgUlJISF0oaHR0cHM6Ly9yNGhyLmNsdWIpIHVuIHJlbGV2YW1pZW50byBkZSBzdWVsZG9zIGRlIFJIIHBhcmEgQXJnZW50aW5hIHkgb3Ryb3MgcGHDrXNlcyBkZSBMYXRpbm9hbcOpcmljYS4gU2kgYmllbiBwYXJ0ZSBkZSBlc2UgYW7DoWxpc2lzIFtlc3TDoSBwdWJsaWNhZG9dKGh0dHBzOi8vcnB1YnMuY29tL0RhdGE0SFIvZW5jdWVzdGEta2l3aS0yMDIwKSBubyBoaWNpbW9zIG5pbmfDum4gYW7DoWxpc2lzIGRlIGxvcyBzdWVsZG9zIHBvciBwcm92aW5jaWFzLiBDb24gbG8gY3VhbCBlbCBvYmpldGl2byBkZSBlc3RlIHRyYWJham8gc2Vyw6E6DQoNCj4gQW5hbGl6YXIgbG9zIHN1ZWxkb3MgZGUgbG9zIHkgbGFzIHByb2Zlc2lvbmFsZXMgcXVlIHRyYWJhamFuIGVuIFJlY3Vyc29zIEh1bWFub3MgcG9yIHByb3ZpbmNpYSB5IHJlZ2nDs24gZGUgbGEgQXJnZW50aW5hLg0KDQpQYXJhIGxvZ3JhciBlc3RlIG9iamV0aXZvIHV0aWxpemFyw6kgYWxndW5hcyB0w6ljbmljYXMgYXByZW5kaWRhcyBlbiBsb3MgTcOzZHVsb3MgSSB5IElJIGRlIGxhIERpcGxvbWF0dXJhIGRlIENpZW5jaWFzIFNvY2lhbGVzIENvbXB1dGFjaW9uYWxlcyB5IEh1bWFuaWRhZGVzIERpZ2l0YWxlcyBkZSBsYSBbVU5TQU1dKGh0dHBzOi8vbm90aWNpYXMudW5zYW0uZWR1LmFyLzIwMjAvMTEvMjAvbnVldm9zLXByb2dyYW1hcy1kZS1wb3NncmFkby1wcm9jZXNvcy1kZS1sYS1oaXN0b3JpYS1hcmdlbnRpbmEteS1hcGxpY2FjaW9uZXMtZGUtY2llbmNpYS1kZS1kYXRvcy8pLg0KDQojIFByZXBhcmFjacOzbiBkZSBsb3MgRGF0b3MNCg0KUGFyYSBlc3RlIHRyYWJham8gdXRpbGl6YXLDqSBkb3MgZGF0YXNldHMsIHVuIGFyY2hpdm8gKnNoYXBlKiBkZSBBcmdlbnRpbmEgb2J0ZW5pZGEgZGUgbGEgcMOhZ2luYSBbZGF0b3MuZ29iLmFyXShodHRwczovL2RhdG9zLmdvYi5hci9kYXRhc2V0L2lnbi11bmlkYWRlcy10ZXJyaXRvcmlhbGVzL2FyY2hpdm8vaWduXzAxLjAyLjAyKSBwYXJhIHBvZGVyIHZpc3VhbGl6YXIgbG9zIHJlc3VsdGFkb3MgZGUgbGFzIGRpc3RpbnRhcyBwcm92aW5jaWFzIGRlbCBwYcOtcywgeSB1bmEgbXVlc3RyYSBkZSBsYSBFbmN1ZXN0YSBLSVdJIChLZXkgSW52ZXN0aWdhdGlvbiBvZiBXYWdlcyBhbmQgSW5jb21lcykgZGUgU3VlbGRvcyBkZSBSSCBjb24gbGFzIHJlc3B1ZXN0YXMgb2J0ZW5pZGFzIGRlIHByb2Zlc2lvbmFsZXMgZGUgQXJnZW50aW5hLg0KDQpFbiBlbCBhbsOhbGlzaXMgdXRpbGl6YXLDqSBsb3MgcGFxdWV0ZXMgYHRpZHl2ZXJzZSgpYCBwYXJhIGxhIHRyYW5zZm9ybWFjacOzbiB5IHZpc3VhbGl6YWNpw7NuIGRlIGRhdG9zLCBlbCBwYXF1ZXRlIGBmdW5Nb2RlbGluZygpYCBwYXJhIGhhY2VyIHVuYSBsaW1waWV6YSBkZSBsb3Mgc3VlbGRvcyBleHRyZW1vcy4gRWwgcGFxdWV0ZSBgc2YoKWAgcGFyYSBwb2RlciBsZWVyIGxvcyBkYXRvcyBlc3BhY2lhbGVzLCB5IGhhY2VyIGxhcyB2aXN1YWxpemFjaW9uZXMgZW4gdW4gbWFwYS4gVGFtYmnDqW4gdXRpbGl6YXLDqSBlbCBwYXF1ZXRlIGBleHRyYWZvbnQoKWAgcGFyYSBwb2RlciBjYW1iaWFyIGxhcyBmdWVudGVzIGRlIGxhcyB2aXN1YWxpemFjaW9uZXMuDQoNCkVuIHByaW1lciBsdWdhciBjYXJnYW1vcyBsYXMgbGlicmVyw61hcyBuZWNlc2FyaWFzLCB5IGx1ZWdvIGNhcmdhbW9zIGxvcyBkYXRvcy4NCg0KYGBge3IgY2FyZ2F9DQojIExpYnJlcsOtYXMgLS0tLS0tLS0tLS0tDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZnVuTW9kZWxpbmcpDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShleHRyYWZvbnQpDQpsaWJyYXJ5KHNjYWxlcykNCg0KIyBEYXRvcyAtLS0tLS0tLS0tLS0tLS0NCg0KIyBEYXRvcyBkZSBzdWVsZG9zIGRlIFJIDQpyaCA8LSByZWFkX2RlbGltKCJGdWVudGVzL3JoLmNzdiIsDQogICAgICAgICAgICAgICAgIGRlbGltID0gIjsiKQ0KDQojIE1hcGEgZGUgQXJnZW50aW5hDQphcmcgPC0gc3RfcmVhZCgiaWduX3Byb3ZpbmNpYS9Qcm92aW5jaWEvaWduX3Byb3ZpbmNpYS5zaHAiKQ0KYGBgDQoNCiMjIEVsZW1lbnRvcyBhY2Nlc29yaW9zDQoNCkNvbiBlbCBvYmpldGl2byBkZSBnZW5lcmFyIHZpc3VhbGl6YWNpb25lcyBtw6FzIGF0cmFjdGl2YXMgeSBwZXJzb25hbGl6YWRhcyB2YW1vcyBhIGNyZWFyIHVuYSBzZXJpZSBkZSBvYmpldG9zIHBlcnNvbmFsaXphZG9zIHBhcmEgcmV1dGlsaXphciBlbiBsb3MgZ3LDoWZpY29zLg0KDQpgYGB7ciBlc3RpbG99DQoNCm9wdGlvbnMoc2NpcGVuID0gOTk5KSAgICMgRWxpbWluYSBub3RhY2nDs24gY2llbnTDrWZpY2EgZGUgbG9zIGdyw6FmaWNvcy4NCg0KbG9hZGZvbnRzKHF1aWV0ID0gVFJVRSkgIyBQZXJtaXRlIGNhcmdhciBlbiBSIG90cm9zIHRpcG9zIGRlIGZ1ZW50ZXMuDQoNCiMgRXN0aWxvIGxpbXBpbyBzaW4gbMOtbmVhcyBkZSBmb25kbw0KZXN0aWxvIDwtIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZCRkNGQyIpLA0KICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiVWJ1bnR1IiksDQogICAgICAgICAgICAgICAgcGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IikNCg0KIyBFc3RpbG8gbGltcGlvIGNvbiBsw61uZWFzIGRlIHJlZmVyZW5jaWEgdmVydGljYWxlcyBlbiBncmlzIGNsYXJvDQplc3RpbG92IDwtIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGQkZDRkMiKSwNCiAgICAgICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGNvbG9yID0gIiNBRUI2QkYiKSwNCiAgICAgICAgICAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiVWJ1bnR1IiksDQogICAgICAgICAgICAgICAgIHBsb3QudGl0bGUucG9zaXRpb24gPSAicGxvdCIpDQoNCiMgRXN0aWxvIGxpbXBpbyBjb24gbMOtbmVhcyBkZSByZWZlcmVuY2lhIGhvcml6b250YWxlcyBlbiBncmlzIGNsYXJvDQplc3RpbG9oIDwtIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGQkZDRkMiKSwNCiAgICAgICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG9yID0gIiNBRUI2QkYiKSwNCiAgICAgICAgICAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiVWJ1bnR1IiksDQogICAgICAgICAgICAgICAgIHBsb3QudGl0bGUucG9zaXRpb24gPSAicGxvdCIpDQoNCiMgUGFsZXRhIGRlIGNvbG9yZXMgcGFyYSBnw6luZXJvDQpjb2xvcmVzIDwtICBjKCIjMUZDM0FBIiwgIiM4NjI0RjUiKQ0KDQojIENyZW8gb2JqZXRvcyBwYXJhIGZvcm1hdGVhciBsYXMgZXRpcXVldGFzIG51bcOpcmljYXMgZGUgbG9zIGVqZXMgeCBlIHkNCmVqZV94X24gPC0gc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hX2Zvcm1hdChiaWcubWFyayA9ICIuIiwgZGVjaW1hbC5tYXJrID0gIiwiKSkNCg0KZWplX3lfbiA8LSBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWFfZm9ybWF0KGJpZy5tYXJrID0gIi4iLCBkZWNpbWFsLm1hcmsgPSAiLCIpKQ0KYGBgDQoNCiMjIEV4cGxvcmFjacOzbiBkZSBsb3MgZGF0b3MNCg0KRW4gcHJpbWVyIGx1Z2FyLCBleHBsb3JlbW9zIGFsZ3VuYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBsb3MgZGF0YSBmcmFtZXMgcXVlIGFjYWJhbW9zIGRlIGNhcmdhci4NCg0KYGBge3IgYXJnMX0NCiMgVGlwbyBkZSBvYmpldG8NCmNsYXNzKGFyZykNCg0KIyBUYW1hw7FvIGRlbCBkYXRhIGZyYW1lDQpkaW0oYXJnKQ0KDQojIE5vbWJyZXMgeSBtdWVzdHJhcyBkZSBkYXRvcw0KZ2xpbXBzZShhcmcpDQpgYGANCg0KUG9kZW1vcyBhcHJlY2lhciBxdWUgZWwgb2JqZXRvIGBhcmdgIGVzIHVuIGRhdGEgZnJhbWUgZGUgdGlwbyAqc2YqLCBlcyBkZWNpciBxdWUgY29udGllbmUgbGFzIGNvb3JkZW5hZGFzIGdlb2dyw6FmaWNhcyBwYXJhIGdyYWZpY2FyIHVuIG1hcGEsIHF1ZSBjb250aWVuZSBgciBucm93KGFyZylgIGZpbGFzIHkgYHIgbmNvbChhcmcpYCBjb2x1bW5hcy4gTGEgdmFyaWFibGUgcXVlIGNvbnRpZW5lIGxvcyBub21icmVzIGRlIGxhcyBwcm92aW5jaWFzIHBhcmEgaGFjZXIgdW4gam9pbiBjb24gZWwgZGF0YXNldCBgcmhgIGVzIGxhIGNvbHVtbmEgYE5BTWAuDQoNCkFob3JhLCByZWFsaWNlbW9zIHVuIGFuw6FsaXNpcyBpbmljaWFsIHNpbWlsYXIgZGVsIGRhdGEgZnJhbWUgZGUgc3VlbGRvcyBkZSBSSC4NCg0KYGBge3IgcmgxfQ0KIyBUaXBvIGRlIG9iamV0bw0KY2xhc3MocmgpDQoNCiMgVGFtYcOxbyBkZWwgZGF0YSBmcmFtZQ0KZGltKHJoKQ0KDQpgYGANCg0KRXN0ZSBkYXRhIGZyYW1lIGVzIHVuIHRhYmxhIGRlIHRpcG8gKnRpYmJsZSogcXVlIGNvbnRpZW5lIGByIG5yb3cocmgpYCBmaWxhcyB5IGByIG5jb2wocmgpYCBjb2x1bW5hcy4gQWwgc2VyIHRhbnRhLCBlbiB2ZXogZGUgdXRpbGl6YXIgbGEgZnVuY2nDs24gYGdsaW1wc2UoKWAgdXNhcmVtb3MgbGEgZnVuY2nDs24gYG5hbWVzKClgIHBhcmEgdmVyIGxvcyBub21icmVzIGRlIGxhcyBjb2x1bW5hcy4NCg0KYGBge3IgcmgyfQ0KbmFtZXMocmgpDQpgYGANCg0KRWwgcmVsZXZhbWllbnRvIGRlIGxhIEVuY3Vlc3RhIEtJV0kgYWJhcmPDsyB0ZW1hcyBtdXkgZGl2ZXJzb3MgY29tbyBzYWxhcmlvIHkgZ8OpbmVybywgeSBvdHJvcyB0b3RhbG1lbnRlIHJpZMOtY3Vsb3MgY29tbyBzaSBzZSBwb2TDrWEgdG9tYXIgbWF0ZSBlbiBsYSBvZmljaW5hIChwcmVwYW5kZW1pYSkgbyBlbCBub21icmUgZGVsIMOhcmVhLiBQYXJhIGxvcyBwcm9ww7NzaXRvcyBkZSBlc3RlIHRyYWJham8gbGltaXRhcmVtb3MgbGEgY2FudGlkYWQgZGUgY29sdW1uYXMgcGFyYSBhbmFsaXphci4NCg0KTm9zIHF1ZWRhcmVtb3Mgw7puaWNhbWVudGUgY29uIGxhcyB2YXJpYWJsZXMgYHByb3ZpbmNpYWAsIGBnZW5lcm9gLCBgcHVlc3RvYCwgeSBgc3VlbGRvX2JydXRvYC4gSGF5IG11Y2hhIHRlbGEgcGFyYSBjb3J0YXIgZW4gZWwgYW7DoWxpc2lzIHBlcm8gcG9yIGVsIGFsY2FuY2UgZGVsIHRyYWJham8gbm9zIGxpbWl0YXJlbW9zIGVuIGVsIGRlc2Fycm9sbG8uDQoNCmBgYHtyIHJoLXNlbGVjdH0NCg0KcmggPC0gcmggJT4lICMgU29icmVzY3JpYmltb3MgZWwgb2JqZXRvIHJoIA0KICBmaWx0ZXIocGFpcyA9PSAiQXJnZW50aW5hIiwgICAgICAgICAgICAgICAgICAgICAgICAjIFNlbGVjY2lvbmFtb3MgbGFzIHJlc3B1ZXN0YXMgZGUgQXJnZW50aW5hDQogICAgICAgICBnZW5lcm8gJWluJSBjKCJNYXNjdWxpbm8iLCAiRmVtZW5pbm8iKSkgJT4lICMgU2VsZWNjaW9uYW1vcyBnw6luZXJvcyBwYXJhIGFuYWxpemFyICAgDQogIHNlbGVjdChwcm92aW5jaWEsIGdlbmVybywgcHVlc3RvLCBzdWVsZG9fYnJ1dG8pICU+JSAgIyBWYXJpYWJsZXMgc2VsZWNjaW9uYWRhcw0KICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLCBhc19mYWN0b3IpICMgUGFzYW1vcyBsYXMgdmFyaWJsZXMgY2hhcmFjdGVyIGNvbW8gZmFjdG9yDQoNCmBgYA0KDQpSZWFsaWNlbW9zIHVuIHByaW1lciBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvIGRlbCBkYXRhIGZyYW1lIGByaGAuDQoNCmBgYHtyIHJoLXN1bW1hcnl9DQpzdW1tYXJ5KHJoKQ0KDQpgYGANCg0KVW5hIHByaW1lcmEgbGltcGllemEgcXVlIHZhbW9zIGEgcmVhbGl6YXIgZXMgbGEgZGUgcmVkdWNpciBsYSBjYW50aWRhZCBkZSBwb3NpY2lvbmVzLiBEYWRhIGxhIGNhbnRpZGFkIGRlIHJlc3B1ZXN0YXMgcmVjaWJpZGFzLCB2YW1vcyBhIGVsaW1pbmFyIGxhcyBwb3NpY2lvbmVzIGRlIGBEaXJlY3RvcmAgeSBkZSBgUGFzYW50ZWAuIFkgbHVlZ28gdmFtb3MgYSBkZWZpbmlyIGVsIG9yZGVuIGNvcnJlc3BvbmRpZW50ZSBhIGxhIGplcmFycXXDrWEgZGUgbGFzIHBvc2ljaW9uZXMuDQoNCmBgYHtyIHJoLWNsZWFuMX0NCg0KcmggPC0gcmggJT4lIA0KICBmaWx0ZXIoIXB1ZXN0byAlaW4lIGMoIlBhc2FudGUiLCAiRGlyZWN0b3IiKSkgJT4lIA0KICBtdXRhdGUocHVlc3RvID0gZmFjdG9yKHB1ZXN0bywgDQogICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiQWRtaW5pc3RyYXRpdm8iLCAiQW5hbGlzdGEiLCAiSFJCUCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVzcG9uc2FibGUiLCAiSmVmZSIsICJHZXJlbnRlIikpKSANCmBgYA0KDQpZIG90cmEgdmFyaWFibGUgcXVlIGhhY2UgZmFsdGEgbGltcGlhciBlcyBsYSBkZSBgc3VlbGRvX2JydXRvYC4gVGVuZW1vcyByZWdpc3RyYWRvIHVuIHN1ZWxkbyBtw61uaW1vIGRlIGByIHBhc3RlMCgiQVIkICIsIG1pbihyaCRzdWVsZG9fYnJ1dG8pKWAgeSBlbCBzdWVsZG8gbcOheGltbyBlcyBkZSBgciBwYXN0ZTAoIkFSJCAiLCBtYXgocmgkc3VlbGRvX2JydXRvKSlgLiBQYXJhIGxvZ3JhciBzdWVsZG9zIG3DoXMgcmVwcmVzZW50YXRpdm9zLCB2YW1vcyBhIGVsaW1pbmFyIGxvcyB2YWxvcmVzIHF1ZSBlc3TDqW4gcG9yIGRlYmFqbyBkZWwgKnBlcmNlbnRpbCA1KiB5IGxvcyB2YWxvcmVzIHF1ZSBlc3TDoW4gcG9yIGVuY2ltYSBkZWwgKnBlcmNlbnRpbCA5NSouDQoNCk5vcyBhcG95YXJlbW9zIGVuIGVsIHBhcXVldGUgYGZ1bk1vZGVsaW5nYCBwYXJhIGRldGVjdGFyIGxvcyB2YWxvcmVzIGVuIGFtYm9zIHBlcmNlbnRpbGVzIHkgdXNhcmxvIHBvc3Rlcmlvcm1lbnRlIGVuIGVsIGFuw6FsaXNpcy4NCg0KYGBge3IgcmgtY2xlYW4yfQ0KIyBTYWNhbW9zIGxvcyB2YWxvcmVzIGRlc2NyaXB0aXZvcyBkZSBsYSB2YXJpYWJsZSBudW3DqXJpY2ENCnZhbG9yZXMgPC0gcHJvZmlsaW5nX251bShyaCkNCg0KIyBFeHRyYWVtb3MgbG9zIHBlcmNlbnRpbGVzIDUgeSA5NQ0KcDA1IDwtIHZhbG9yZXNbMSw2XQ0KcDk1IDwtIHZhbG9yZXNbMSwxMF0NCg0KIyBGaWx0cmFtb3MgZW4gbGEgdmFyaWFibGUgc3VlbGRvX2JydXRvIGxvcyB2YWxvcmVzIGV4dHJlbW9zIA0KcmgxIDwtIHJoICU+JSANCiAgZmlsdGVyKGJldHdlZW4oICAgIyBGdW5jacOzbiBhdXhpbGlhciBwYXJhIGZpbHRyYXIgdmFsb3Jlcw0KICAgIHN1ZWxkb19icnV0bywgICAjIFZhcmlhYmxlIGEgZmlsdHJhcg0KICAgIHAwNSwgICAgICAgICAgICAjIEZpbHRybyBpbmZlcmlvcg0KICAgIHA5NSAgICAgICAgICAgICAjIEZpbHRybyBzdXBlcmlvcg0KICApKQ0KDQojIEVsaW1pbmFtb3Mgb2JqZXRvcyBxdWUgbm8gcmV1dGlsaXphcmVtb3MgcGFyYSBsaWJlcmFyIG1lbW9yaWENCnJtKHZhbG9yZXMsIHAwNSwgcDk1KQ0KDQojIEFuw6FsaXNpcyBkZXNjcmlwdGl2byBkZSBsYSB2YXJpYWJsZSBzdWVsZG9fYnJ1dG8NCnN1bW1hcnkocmgxJHN1ZWxkb19icnV0bykNCg0KYGBgDQoNCkNvbXBhcmVtb3MgY8OzbW8gcXVlZGEgbGEgdmFyaWFibGUgYHN1ZWxkb19icnV0b2AgYW50ZXMgeSBkZXNwdcOpcyBkZSBsYSBsaW1waWV6YToNCg0KYGBge3IgYm94cGxvdC1zdWVsZG9zLCBmaWcuc2hvdz0naG9sZCcsIG91dC53aWR0aD0iNTAlIn0NCiMgQm94cGxvdCB2YXJpYWJsZSBvcmlnaW5hbA0KZ2dwbG90KHJoLCBhZXMoeCA9IHN1ZWxkb19icnV0bykpICsNCiAgZ2VvbV9oaXN0b2dyYW0oKSArDQogIGdndGl0bGUoIkRpc3RyaWJ1Y2nDs24gdmFyaWFibGUgb3JpZ2luYWwiKSArDQogIGVzdGlsb2ggKw0KICBlamVfeF9uDQoNCiMgQm94cGxvdCB2YXJpYWJsZSBvcmlnaW5hbA0KZ2dwbG90KHJoMSwgYWVzKHggPSBzdWVsZG9fYnJ1dG8pKSArDQogIGdlb21faGlzdG9ncmFtKCkgKw0KICBnZ3RpdGxlKCJEaXN0cmlidWNpw7NuIHZhcmlhYmxlIGxpbXBpYSIpICsNCiAgZXN0aWxvaCArDQogIGVqZV94X24NCmBgYA0KDQpFbiBlc3RvcyBkb3MgKmhpc3RvZ3JhbWFzKiBwb2RlbW9zIGFwcmVjaWFyIGxhIGluZmx1ZW5jaWEgZGUgbG9zICoqb3V0bGllcnMqKiwgcXVlIG5vcyBpbXBpZGVuIGVuIGVsIGRhdGEgZnJhbWUgb3JpZ2luYWwgbGEgZGlzdHJpYnVjacOzbiBkZSBsb3Mgc3VlbGRvcyBwb3IgZGViYWpvIGRlIGxvcyBBUlwkIDUwMC4wMDAuIEVuIGVsIHNlZ3VuZG8gZ3LDoWZpY28sIGx1ZWdvIGRlIGxhIGxpbXBpZXphIGRlIGxhIHZhcmlhYmxlIGBzdWVsZG9fYnJ1dG9gIHBvZGVtb3MgYXByZWNpYXIgbG9zIHBpY29zIGVuIGxvcyBBUlwkIDUwLjAwMCB5IGVuIGxvcyBBUlwkIDc1LjAwMC4NCg0KQW5hbGl6YXIgbGEgKipkaXN0cmlidWNpw7NuKiogZGUgbGFzIHZhcmlhYmxlcyBlcyBtdXkgaW1wb3J0YW50ZSwgcG9ycXVlIG11Y2hhcyB2ZWNlcywgbGFzIG3DqXRyaWNhcyBkZSByZXN1bWVuIGVzdGFkw61zdGljbyBwdWVkZW4gZXN0YXIgInRhcGFuZG8iIGFsZ3Vub3MgcHJvYmxlbWFzLiBQb3IgZWplbXBsbywgbWlyZW1vcyBsYSBtZWRpYW5hIHNhbGFyaWFsIGRlIGxvcyBzdWVsZG9zIHBvciBnw6luZXJvIHkgcG9yIHB1ZXN0by4NCg0KYGBge3IgY29tcF9zdWVsZG9zfQ0KcmgxICU+JSANCiAgZ3JvdXBfYnkocHVlc3RvLCBnZW5lcm8pICU+JSANCiAgc3VtbWFyaXNlKG1lZGlhbmFfc2FsYXJpYWwgPSBtZWRpYW4oc3VlbGRvX2JydXRvKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBwdWVzdG8sIHkgPSBtZWRpYW5hX3NhbGFyaWFsLCBmaWxsID0gZ2VuZXJvKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG9oICsNCiAgZWplX3lfbiArDQogICAgbGFicyh0aXRsZSA9ICJNZWRpYW5hIHNhbGFyaWFsIHBvciBwdWVzdG8geSBnw6luZXJvIiwNCiAgICAgICAgIHN1YnRpdGxlID0gIkVuIEFSJCIsDQogICAgICAgICBmaWxsID0gIkfDqW5lcm8iLA0KICAgICAgICAgeCA9ICIiLCB5ID0gIiIpDQpgYGANCg0KRW4gZWwgZ3LDoWZpY28gZGUgYmFycmFzLCBwb2RlbW9zIGFwcmVjaWFyIHF1ZSBzaSBiaWVuIGVuIHZhcmlvcyBwdWVzdG9zLCBjb21vIGVsIGRlICpSZXNwb25zYWJsZSosIG8gZWwgZGUgKkFuYWxpc3RhKiBsb3Mgc3VlbGRvcyBkZSBsb3MgdmFyb25lcyBzb24gbcOhcyBhbHRvcyBxdWUgZW4gZWwgY2FzbyBkZSBsYXMgbXVqZXJlcywgcG9kZW1vcyBhcHJlY2lhciB1bmEgcGFyaWRhZCBlbiBsYXMgcG9zaWNpb25lcyBkZSAqSFJCUCogeSAqSmVmZSouIFBlcm8gYW5hbGljZW1vcyBsYSBtaXNtYSB2YXJpYWJsZSBjb24gdW4gKipib3hwbG90KiogcXVlIG5vcyBwZXJtaXRlIGFwcmVjaWFyIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGdyw6FmaWNvcy4NCg0KYGBge3IgY29tcF9zdWVsZG9zMn0NCmdncGxvdChyaDEsIGFlcyh4ID0gcHVlc3RvLCB5ID0gc3VlbGRvX2JydXRvLCBmaWxsID0gZ2VuZXJvKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXMpICsNCiAgZXN0aWxvaCArDQogIGVqZV95X24gKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgc3VlbGRvcyBicnV0b3MgcG9yIHB1ZXN0byB5IGfDqW5lcm8iLA0KICAgICAgIHN1YnRpdGxlID0gIkVuIEFSJCIsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgZmlsbCA9ICJHw6luZXJvIikNCmBgYA0KDQpFbiBsb3MgKmJveHBsb3RzKiBwb2RlbW9zIGFwcmVjaWFyIGxhIG1lZGlhbmEgc2FsYXJpYWwgY29uIGxhIGJhcnJhIG5lZ3JhIHF1ZSBlc3TDoSBkZW50cm8gZGUgbGFzICpjYWphcyouIEVsIGFuY2hvIGRlIGxhcyBjYWphcyBub3MgZGFuIGxhIGlkZWEgZGUgY8OzbW8gc2UgZGlzdHJpYnV5ZW4gbG9zIHNhbGFyaW9zIGVudHJlIGVsIDHCsCBjdWFydGlsIHkgZWwgM8KwIGN1YXJ0aWwuDQoNCkFuYWxpY2Vtb3MgZWwgcHVlc3RvIGRlICpHZXJlbnRlKi4gTGEgKmNhamEqIGNvcnJlc3BvbmRpZW50ZSBhIGxhcyBwZXJzb25hcyBkZSBnw6luZXJvIG1hc2N1bGlubyBlc3TDoW4gYmllbiBjb25jZW50cmFkYXMgZW4gdG9ybm8gYSBsYSBtZWRpYW5hLCBtaWVudHJhcyBxdWUgZWwgcmVjb3JyaWRvIGRlIGxvcyBzdWVsZG9zIGRlIGxhcyBwZXJzb25hcyBkZSBnw6luZXJvIGZlbWVuaW5vIGVzIG3DoXMgYW1wbGlvLCB5IGxsZWdhbmRvIGEgdmFsb3JlcyBtdWNobyBtw6FzIGJham9zLg0KDQpZIHNpIGFuYWxpemFtb3MgZWwgcHVlc3RvIGRlICpKZWZlKiwgZG9uZGUgbGEgbWVkaWFuYSBlcyBwcsOhY3RpY2FtZW50ZSBsYSBtaXNtYSBwYXJhIGhvbWJyZXMgeSBtdWplcmVzLCBwZXJvIGxhIGFtcGxpdHVkIGRlIGxhIGNhamEgZW50cmUgZWwgMcKwIGN1YXJ0aWwgeSBsYSBtZWRpYW5hIGVzIG1heW9yIGVuIGxhcyBtdWplcmVzIHF1ZSBlbiBsb3MgaG9tYnJlczsgbG8gb3B1ZXN0byBhIGxvIHF1ZSBzdWNlZGUgZW50cmUgbGEgbWVkaWFuYSB5IGVsIDPCsCBjdWFydGlsLiBFc3RvIHNpZ25pZmljYSBxdWUgbG9zIHN1ZWxkb3MgZGUgbGFzIG11amVyZXMgZW4gZWwgcHVlc3RvIGRlIEplZmUgbGxlZ2FuIGEgdmFsb3JlcyBtw6FzIGJham9zIHF1ZSBlbiBsb3MgdmFyb25lcywgeSBxdWUgZWwgc3VlbGRvIGRlIGxvcyB2YXJvbmVzLCBsbGVnYSBhIHN1ZWxkb3MgbcOhcyBhbHRvcyBxdWUgc3VzIHBhcmVzIG11amVyZXMuDQoNCiMjIEFuw6FsaXNpcyBwcm92aW5jaWFsDQoNClVuIGFuw6FsaXNpcyBxdWUgZmFsdMOzIGhhY2VyIGVuIGVsIHRyYWJham8gcHVibGljYWRvIGVzIGVsIGFuw6FsaXNpcyBkZSBzdWVsZG9zIHBvciBwcm92aW5jaWEuIEVuIHBhcnRlLCBwb3IgbGEgZGlzcGFyaWRhZCBlbiBsYSBjYW50aWRhZCBkZSByZXNwdWVzdGFzIHJlY2liaWRhcy4NCg0KYGBge3IgcHJvdjF9DQpEVDo6ZGF0YXRhYmxlKHJoMSAlPiUgDQogIGNvdW50KHByb3ZpbmNpYSwgc29ydCA9IFQpKQ0KYGBgDQoNClBvZHLDrWFtb3MgaGFjZXIgdW4gcmFua2luZyBzaW1wbGUgZGUgc3VlbGRvIHByb21lZGlvIHBvciBwcm92aW5jaWEsIGNvbiB1biBncsOhZmljbyBkZSAqcGlydWzDrW4qIChWYXpxdWV6IEJydXN0IGRpeGl0KToNCg0KYGBge3IgcHJvdjJ9DQpyaDEgJT4lIA0KICBncm91cF9ieShwcm92aW5jaWEpICU+JSANCiAgc3VtbWFyaXNlKG1lZGlhX3NhbGFyaWFsID0gbWVhbihzdWVsZG9fYnJ1dG8pKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IG1lZGlhX3NhbGFyaWFsLCB5ID0gZmN0X3Jlb3JkZXIocHJvdmluY2lhLCBtZWRpYV9zYWxhcmlhbCkpKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAiIzNCMzE3NiIsIHNpemUgPSAzKSArDQogIGdlb21fc2VnbWVudChhZXMoeCA9IDAsIHhlbmQgPSBtZWRpYV9zYWxhcmlhbCwgeSA9IHByb3ZpbmNpYSwgeWVuZCA9IHByb3ZpbmNpYSksIA0KICAgICAgICAgICAgICAgY29sb3IgPSAiIzVDNTM5MyIpICsNCiAgbGFicyh0aXRsZSA9ICJSYW5raW5nIGRlIHN1ZWxkbyBwcm9tZWRpbyBwb3IgcHJvdmluY2lhIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJFbiBBUiQiLA0KICAgICAgIHggPSAiU3VlbGRvIHByb21lZGlvIiwNCiAgICAgICB5ID0gIiIpICsNCiAgZWplX3hfbiArDQogIGVzdGlsb3YNCmBgYA0KDQojIFVuaWZpY2FuZG8gZGF0YSBmcmFtZXMNCg0KRWwgb2JqZXRpdm8gZGVsIHRyYWJham8gZXMgcmVhbGl6YXIgdW4gYW7DoWxpc2lzIGRlIGxvcyBzdWVsZG9zIGVuIFJSSEggZW4gZWwgcGHDrXMuIEVuIGVsIGdyw6FmaWNvIGFudGVyaW9yIHBvZMOtYW1vcyB2ZXIgZW4gZWwgdG9wLWZpdmUgYSB0cmVzIHByb3ZpbmNpYXMgcGF0YWfDs25pY2FzLCBwZXJvIGV4aWdlIGNpZXJ0byBlc2Z1ZXJ6byBwb3IgcGFydGUgZGVsIGxlY3RvciBpbnRlcnByZXRhciBsYXMgZGlmZXJlbmNpYXMgc2FsYXJpYWxlcyBlbnRyZSByZWdpb25lcy4gUGFyYSBmYWNpbGl0YXIgbGEgaW50ZXJwcmV0YWNpw7NuIGRlIGxhcyBkaWZlcmVuY2lhcyBzYWxhcmlhbGVzIGNyZWFyZW1vcyB1bmEgdmFyaWFibGUgbnVldmEgZW4gZWwgZGF0YSBmcmFtZSBgYXJnYC4NCg0KUGFyYSBkZWZpbmlyIGxhcyByZWdpb25lcyB1dGlsaXphcmVtb3MgW2VzdGEgZ3XDrWFdKGh0dHBzOi8vYXJnZW50aW5hbG9tZWpvci5jb20vYy1nZW5lcmFsaWRhZGVzLWRlbC1wYWlzL3JlZ2lvbmVzLWRlLWFyZ2VudGluYS8pLg0KDQpgYGB7ciByZWdpb25lc30NCg0KcmVnaW9uZXMgPC0gZGF0YS5mcmFtZSgNCiAgcHJvdmluY2lhID0gYygiQnVlbm9zIEFpcmVzIiwgIkVudHJlIFLDrW9zIiwgIlNhbnRhIEZlIiwgIkxhIFBhbXBhIiwgIkPDs3Jkb2JhIiwNCiAgICAgICAgICAiTWlzaW9uZXMiLCAiQ29ycmllbnRlcyIsICJDaGFjbyIsICJGb3Jtb3NhIiwNCiAgICAgICAgICAiSnVqdXkiLCAiU2FsdGEiLCAiVHVjdW3DoW4iLCAiQ2F0YW1hcmNhIiwgIlNhbnRpYWdvIGRlbCBFc3Rlcm8iLA0KICAgICAgICAgICJNZW5kb3phIiwgIlNhbiBKdWFuIiwgIlNhbiBMdWlzIiwgIkxhIFJpb2phIiwNCiAgICAgICAgICAiTmV1cXXDqW4iLCAiUsOtbyBOZWdybyIsICJDaHVidXQiLCAiU2FudGEgQ3J1eiIsICJUaWVycmEgZGVsIEZ1ZWdvLCBBbnTDoXJ0aWRhIGUgSXNsYXMgZGVsIEF0bMOhbnRpY28gU3VyIiksDQogIHJlZ2lvbiA9IGMocmVwKCJDZW50cm8iLCA1KSwNCiAgICAgICAgICAgICByZXAoIk5FQSIsIDQpLA0KICAgICAgICAgICAgIHJlcCgiTk9BIiwgNSksDQogICAgICAgICAgICAgcmVwKCJDdXlvIiwgNCksDQogICAgICAgICAgICAgcmVwKCJQYXRhZ29uaWEiLCA1KQ0KICAgICAgICAgICAgICkNCiAgKQ0KYGBgDQoNCkx1ZWdvLCBhZ3JlZ2Ftb3MgZWwgZGF0byBkZSBsYSByZWdpw7NuIGFsIGRhdGEgZnJhbWUgZGUgYGFyZ2AuIHN1ZWxkb3MgcHJvbWVkaW8gcG9yIHByb3ZpbmNpYS4gUmVub21icmFtb3MgbGEgY29sdW1uYSBgcHJvdmluY2lhYCBwb3IgYE5BTWAgcGFyYSBwb2RlciBoYWNlciBpbmNvcnBvcmFyIGxhIGluZm9ybWFjacOzbiBkZSBzdWVsZG9zIHkgZGUgcmVnacOzbiBhbCBkYXRhIGZyYW1lIGRlbCBwYcOtcy4NCg0KYGBge3Igam9pbjF9DQphcmcgPC0gbGVmdF9qb2luKGFyZywgcmVnaW9uZXMsDQogICAgICAgICAgICAgICAgIGJ5ID0gYygiTkFNIiA9ICJwcm92aW5jaWEiKSkNCg0KZ2xpbXBzZShhcmcpDQpgYGANCg0KRWwgcHLDs3hpbW8gcGFzbyBlcyBpbmNvcnBvcmFyIGxhIGNvbHVtbmEgZGUgbGEgcmVnacOzbiBhIGByaDFgIHkgY3JlYXIgdW4gbnVldm8gZGF0YSBmcmFtZSByZXN1bWllbmRvIGxvcyBzdWVsZG9zIHByb21lZGlvIHBvciByZWdpw7NuLg0KDQpgYGB7ciBqb2luMn0NCiMgUmVhbGl6byBlbCBqb2luDQpyaDEgPC0gbGVmdF9qb2luKHJoMSwgcmVnaW9uZXMsIA0KICAgICAgICAgICAgICAgICBieSA9ICJwcm92aW5jaWEiKQ0KDQojIENyZWFjacOzbiBkZWwgZGF0YSBmcmFtZSBjb24gc3VlbGRvcyBwcm9tZWRpbyBwb3IgcmVnacOzbg0Kc3VlbGRvX3JlZ2lvbiA8LSByaDEgJT4lIA0KICBncm91cF9ieShyZWdpb24pICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2JydXRvKSkgJT4lIA0KICB1bmdyb3VwKCkNCmBgYA0KDQpGaW5hbG1lbnRlLCBpbmNvcnBvcmFtb3MgbG9zIHN1ZWxkb3MgeSBsYSByZWdpw7NuIGFsIGRhdGEgZnJhbWUgYGFyZ2AuDQoNCmBgYHtyIGpvaW4zfQ0KYXJnIDwtIGxlZnRfam9pbihhcmcsIHN1ZWxkb19yZWdpb24sDQogICAgICAgICAgICAgICAgIGJ5ID0gInJlZ2lvbiIpIA0KDQpnbGltcHNlKGFyZykNCmBgYA0KDQojIEFuw6FsaXNpcyBmaW5hbCB5IGNvbmNsdXNpb25lcw0KDQpVbmEgdmV6IHF1ZSBjb250YW1vcyBjb24gdG9kYSBsYSBpbmZvcm1hY2nDs24gdW5pZmljYWRhLCBwb2RlbW9zIGhhY2VyIHVuIGFuw6FsaXNpcyBkZSBsb3Mgc3VlbGRvcyBwcm9tZWRpbyBwb3IgcmVnacOzbi4gUGFyYSBlc3RlIHByb3DDs3NpdG8gdmlzdWFsaXphcmVtb3MgZW4gdW4gbWFwYSBkZSBsYSBBcmdlbnRpbmEgbG9zIHN1ZWxkb3MgZGUgY2FkYSByZWdpw7NuLg0KDQpgYGB7ciBhbi1yZWdpb259DQpnZ3Bsb3QoYXJnLCBhZXMoZmlsbCA9IHN1ZWxkb19wcm9tZWRpbykpICsNCiAgZ2VvbV9zZigpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2IoKSArDQogICMgTGltaXRhbW9zIGxvcyBlamVzIHBhcmEgdmlzdWFsaXphciBtZWpvciBhbCBwYcOtcw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtMjIsIC01NikpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUzLCAtNzQpKSArDQogIGxhYnModGl0bGUgPSJTdWVsZG8gcHJvbWVkaW8gcG9yIHJlZ2nDs24iLA0KICAgICAgIHN1YnRpdGxlID0gImVuIEFSJCIsDQogICAgICAgZmlsbCA9ICJTdWVsZG8gcHJvbWVkaW8iKSArDQogIGVzdGlsbw0KYGBgDQoNCkVuIGVsIGdyw6FmaWNvIHBvZGVtb3MgYXByZWNpYXIgcXVlIGxvcyBzdWVsZG9zIGVuIGxhIFBhdGFnb25pYSBzb24gbG9zIG3DoXMgYWx0b3MgZGVsIHBhw61zIHkgZW4gbGEgcmVnacOzbiBkZWwgTkVBIHNlIGVuY3VlbnRyYW4gbG9zIG3DoXMgYmFqb3MuIFBvZHLDrWFtb3MgaGFiZXIgaGVjaG8gbGEgdmlzdWFsaXphY2nDs24gcG9yIHByb3ZpbmNpYSwgcGVybyBkYWRvIHF1ZSBodWJpZXJvbiBwcm92aW5jaWFzIGRlIGxhcyBxdWUgbm8gb2J0dXZpbW9zIGluZm9ybWFjacOzbiwgY29tbyBTYW50aWFnbyBkZWwgRXN0ZXJvIHBvciBlamVtcGxvLCB5IGVuIGFsZ3Vub3MgY2Fzb3Mgc8OzbG8gcmVjaWJpbW9zIHVuYSBzb2xhIHJlc3B1ZXN0YSBjb21vIGVuIGVsIGNhc28gZGUgVGllcnJhIGRlbCBGdWVnbywgZGVjaWRpbW9zIHRvbWFyIGxvcyBkYXRvcyBkZSBmb3JtYSByZWdpb25hbC4NCg0KIyMgQ29uY2x1c2lvbmVzDQoNClNpIGJpZW4gZWwgYW7DoWxpc2lzIGVzIGltcGVyZmVjdG8gZGFkYSBsYSBkaXNwYXJpZGFkIGRlIHJlc3B1ZXN0YXMgcmVjaWJpZGFzIHBvciBwcm92aW5jaWFzLCB0aWVuZSBzZW50aWRvIHF1ZSBsb3Mgc3VlbGRvcyBtw6FzIGFsdG9zIHNlIGVuY3VlbnRyZW4gZW4gZWwgc3VyIGRlbCBwYcOtcywgcG9yIHVuIGxhZG8gcG9yIGxhIHByZXNlbmNpYSBkZSBlbXByZXNhcyBwZXRyb2xlcmFzIHkgbWluZXJhcywgeSBhZGVtw6FzIHF1ZSBhbCBzZXIgcHJvdmluY2lhcyB0YW4gcmVtb3RhcywgdGFtYmnDqW4gaGF5YSBpbmNlbnRpdm9zIHBhcmEgcmVsb2NhbGl6YXIgcHJvZmVzaW9uYWxlcy4NCg0KTGEgcmVnacOzbiBjZW50cmFsIG51Y2xlYSBhIHVuIGdyYW4gbsO6bWVybyBkZSBlbXByZXNhcywgY29uY2VudHJhIGFjdGl2aWRhZGVzIGNvbiBncmFuIHBlc28gZW4gbGEgZWNvbm9tw61hIGRlbCBwYcOtcywgeSBlcyBsYSByZWdpw7NuIHF1ZSBjb25jZW50cmEgbGEgbWF5b3LDrWEgZGUgbGEgYWN0aXZpZGFkIGVjb27Ds21pY2EgeSBwcm9kdWN0aXZhIGRlbCBwYcOtcywgbG8gY3VhbCBleHBsaWNhIHF1ZSBlc3TDqW4gbG9zIHN1ZWxkb3MgbcOhcyBhbHRvcyBhIG5pdmVsIG5hY2lvbmFsLg0KDQpFbiB1biBmdXR1cm8gYW7DoWxpc2lzIHNlIHBvZHLDrWEgaW5jb3Jwb3JhciBtw6FzIGluZm9ybWFjacOzbiBzb2JyZSBsYSBhY3RpdmlkYWQgZWNvbsOzbWljYSBkZSBsYXMgcmVnaW9uZXMsIGRlbCBwZXNvIGRlbCB0cmFiYWpvIGVuIMOhbWJpdG9zIHDDumJsaWNvcyB5IHByaXZhZG9zIGVuIGxhcyBwcm92aW5jaWFzLCB5IGxhIGRpdmVyc2lkYWQgZGUgYWN0aXZpZGFkZXMgcGFyYSBwb2RlciBidXNjYXIgY29ycmVsYXRvcyBlbnRyZSBsYSBhY3RpdmlkYWQgZWNvbsOzbWljYSB5IGxvcyBzdWVsZG9zIGRlIGxvcyBwcm9mZXNpb25hbGVzIGRlIFJlY3Vyc29zIEh1bWFub3MuDQoNCkh1YmllcmEgc2lkbyBpZGVhbCBjb250YXIgY29uIHVuYSBtYXlvciBob21vZ2VuZWlkYWQgZGUgcmVzcHVlc3RhcyBkZSB0b2RhcyBsYXMgcHJvdmluY2lhcyBwYXJhIHBvZGVyIHF1ZSBsYSBpbmZvcm1hY2nDs24gc2VhIG3DoXMgcmVwcmVzZW50YXRpdmEgZGUgbGEgc2l0dWFjacOzbiBkZSBsb3MgcHJvZmVzaW9uYWxlcyBkZSBSZWN1cnNvcyBIdW1hbm9zIGVuIGVsIHBhw61zIHBlcm8gYSBwcmlvcmkgZnVlIHVuYSBzb3JwcmVzYSBxdWUgbG9zIHN1ZWxkb3MgZW4gbGEgUGF0YWdvbmlhIHNlYW4gbcOhcyBhbHRvcyBxdWUgbG9zIGRlIGxhIHJlZ2nDs24gQ2VudHJhbCBkZWwgcGHDrXMuDQo=