library(tidyverse)
library(gargle)
library(googlesheets4)
library(funModeling)
library(gt)
library(scales)

# Estilo de los gráficos
estilo <- theme(panel.grid = element_blank(),
                plot.background = element_rect(fill = "#FBFCFC"),
                panel.background = element_blank())

# Este es un objeto que vamos a utilizar para no tener que tipear siempre lo mismo
fuente <- "Fuente: Encuesta KIWI de Sueldos de RRHH"

# Colores predefinidos de los gráficos
col_genero <- c("#8624F5", "#1FC3AA")
col_graf <- "#943126"

# Carga de los sueldos
sueldos <- sheets_read("1f3MCA81NnjI48C03GxxGu69i2hKZLrpxf4tHzKkXL_k")

# Filtramos los sueldos entre los percentiles 5 y 95
resumen_numerico <- profiling_num(sueldos)
percentil_05 <- resumen_numerico[6,6]
percentil_95 <- resumen_numerico[6,10]

# Limpiamos un poco más el dataset
sueldos <- sueldos %>% 
  filter(between(sueldo_bruto, percentil_05, percentil_95), 
         aumento < 100,
         anios_rh < 40,
         puesto != "Director") 

Introducción

Este es un ejercicio de práctica, realizado durante la sesión abierta de Noviembre del Club de R para RRHH. Si quieren saber más, pueden contactarme en mi perfil en LinkedIn. 🥝

Los datos utilizados son una muestra de la Encuesta KIWI de Sueldos de RRHH de Latam realizado por el Club de R para RRHH.

Este es un ejemplo de reporte que se puede hacer utilizando R, con el paquete RMarkdown.

Análisis de sueldos de RRHH por puesto

sueldos <- sueldos %>% 
  mutate(puesto = factor(puesto, 
                         levels = c("Administrativo", "Analista", "HRBP", 
                                    "Responsable", "Jefe", "Gerente"))) 
puestos <- sueldos %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_bruto))

# Hacemos el gráfico
ggplot(puestos, aes(x = sueldo_promedio, 
                    y = reorder(puesto, sueldo_promedio))) +
  geom_col(fill = col_graf) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = "En AR$",
       caption = fuente) +
  scale_x_continuous(labels = comma_format(big.mark = ".", decimal.mark = ";")) +
  theme(panel.grid.major.x = element_line(colour = "#CACFD2")) +
  estilo

Para realizar este gráfico filtramos los sueldos por encima de AR$ 30.000 (percentil 5), y por debajo de AR$ 220.000 (percentil 95).

Tabla de Sueldos

salarios <- sueldos %>% 
  mutate(puesto = factor(puesto, 
                         levels = c("Gerente", "Jefe", "Responsable",
                                     "HRBP", "Analista", "Administrativo"))) 
puestos2 <- salarios %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_bruto))
gt(puestos2) %>% 
  tab_header(title = "Sueldo promedio por puesto") %>% 
  cols_label(puesto = "Puesto", 
             sueldo_promedio = "Sueldo Promedio") %>% 
  fmt_currency(columns = c("sueldo_promedio"),
               currency = "ARS",
               decimals = 0)
Sueldo promedio por puesto
Puesto Sueldo Promedio
Gerente $150,777
Jefe $107,026
Responsable $76,715
HRBP $97,824
Analista $66,883
Administrativo $49,781

Dispersión de sueldos por puesto y género

En este boxplot podemos apreciar las amplitudes en los sueldos de cada puesto por género. Mientras más larga sea la caja, más amplia es la variación de los sueldos, y al contrario, mientras más chica sea la caja, hay una mayor concentración de los sueldos.

A los puntos que aparecen por encima de cada uno de los gráficos, se los denomina outlier, y son valores extremos.

ggplot(salarios, aes(x = puesto, y = sueldo_bruto, fill = genero)) +
  geom_boxplot() +
  labs(title = "Dispersión de sueldos por puesto y género",
       x = "", y = "",
       caption = fuente, 
       fill = "Género") +
  scale_y_continuous(labels = comma_format(big.mark = ".", decimal.mark = ","))  +
  scale_fill_manual(values = col_genero) +
  theme(panel.grid.major.y = element_line(colour = "#CACFD2")) +
  estilo

Este tipo de gráficos, los boxplots, proveen de mucha información estadística.

  • El límite inferior de la caja es el 1° cuartil (1Q).
  • La línea dentro de la caja, es la mediana.
  • El límite superior de la caja es el 3° cuartil (3Q).
  • Las líneas que salen de la caja son los límites para indicar los valores outliers y se calculan 1,5 por el Rango Intercuartil (3Q - 1Q).
  • Los puntos que vemos más allá de las líneas son outliers.

Por ejemplo, este gráfico nos permite ver que en el caso de los gerentes, no hay una diferencia muy amplia en la mediana de los sueldos de hombres y mujeres. En cambio vemos que la caja del gráfico de las mujeres es más amplia que la de los varones. Esto quiere decir que hay una porción de mujeres como Gerente de RRHH que cobran menos que sus pares hombres, y que también hay una porción de mujeres que cobran más que los varones.

Relación entre años de experiencia y sueldo

Con el siguiente gráfico queremos ver cuál es la relación entre los años de experiencia y el sueldo bruto.

modelo_lineal <- broom::tidy(lm(data = sueldos, 
                                sueldo_bruto ~ anios_rh))
modelo_lineal$estimate <- dollar(modelo_lineal$estimate,
                                 prefix = "AR$ ",    # Podemos controlar el símbolo utilizado
                                 big.mark = ".",     # Cambia el separador de miles
                                 decimal.mark = ",") # Cambia el separador decimal
ggplot(sueldos, aes(x = anios_rh, y = sueldo_bruto)) +
  geom_point(alpha = .7, size = 1.5, color = col_graf) +
  geom_smooth(method = "lm") +
  labs(title = "Relación entre años de experiencia y sueldos de RRHH",
       subtitle = "En pesos argentinos",
       x = "Años de Experiencia",
       y = "Sueldo Bruto",
       caption = fuente) +
  scale_y_continuous(labels = comma_format(big.mark = ".", decimal.mark = ","))+
  estilo

Podemos ver una relación positiva entre los años de experiencia y el sueldo, es decir que a medida que aumentan los años de experiencia (nos movemos hacia la derecha en el eje horizontal), sube el sueldo bruto (en el eje vertical).

En promedio, una persona con cero años de experiencia en RRHH cobra un sueldo bruto de AR$ 58.393,91. Y con cada año de experiencia, el sueldo aumenta en AR$ 2.860,21.

Ratio de Empleados de RRHH por Dotación

Con este indicador queremos analizar la cantidad de empleados que hay en el área de RRHH en relación a la dotación de la empresa.

 ratio <- sueldos %>% 
  select(rubro, empleados, empleados_rh) %>% 
  mutate(ratio_rh_dotacion = empleados/empleados_rh) %>% 
  group_by(rubro) %>% 
  summarise(ratio_promedio = round(mean(ratio_rh_dotacion))) %>% 
  filter(ratio_promedio != Inf) 
ggplot(ratio, aes(x=ratio_promedio, 
                         y = reorder(rubro, ratio_promedio)))+
  geom_point(color = col_graf, size = 4)+
  geom_segment(aes(y = rubro, yend= rubro, x=0, xend=ratio_promedio),
               color="#5D6D7E") +
  estilo +
  labs(title="Ratio de Empleados de RH \n por Dotación",
       subtitle = "Detallado por rubro de la empresa", 
       caption = fuente, 
       x="", y= "") +
  theme(panel.grid.major.x = element_line(colour = "#CACFD2"))

Agradecimientos

Agradezco a todos los participantes del curso “Introducción a R para RRHH” que dictamos en Data 4HR. Para conocer nuestras próximas fechas, y todas nuestras actividades de formación podés entrar en este link o por mail a sergio@d4hr.com.

Este es un curso en castellano, que utiliza datos de RRHH, para facilitar el aprendizaje del uso de este lenguaje de análisis de datos.

Y si ya sabés algo de R y te interesa ser parte de una comunidad de R enfocada en RRHH, te invitamos a seguirnos en el Club de R para RRHH.




# The Wall

Disco 1

Lado 1

  1. In the Flesh?

  2. The Thin Ice

  3. Another Brick in the Wall (Part I)

  4. The Happiest Days of Our Lives

  5. Another Brick in the Wall (Part II)

  6. Mother

adicion <- 26 + 144

El resultado de la suma es 170

library(tidyverse)
LS0tDQp0aXRsZTogIkNsdWIgZGUgUiINCmF1dGhvcjogIlNlcmdpbyINCmRhdGU6ICI3LzExLzIwMjAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOiBzaW1wbGV4DQogICAgaGlnaGxpZ2h0OiBicmVlemVkYXJrDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkNCmBgYA0KDQpgYGB7ciBsaWJyZXJpYXMtZGF0b3N9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ2FyZ2xlKQ0KbGlicmFyeShnb29nbGVzaGVldHM0KQ0KbGlicmFyeShmdW5Nb2RlbGluZykNCmxpYnJhcnkoZ3QpDQpsaWJyYXJ5KHNjYWxlcykNCg0KIyBFc3RpbG8gZGUgbG9zIGdyw6FmaWNvcw0KZXN0aWxvIDwtIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZCRkNGQyIpLA0KICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpDQoNCiMgRXN0ZSBlcyB1biBvYmpldG8gcXVlIHZhbW9zIGEgdXRpbGl6YXIgcGFyYSBubyB0ZW5lciBxdWUgdGlwZWFyIHNpZW1wcmUgbG8gbWlzbW8NCmZ1ZW50ZSA8LSAiRnVlbnRlOiBFbmN1ZXN0YSBLSVdJIGRlIFN1ZWxkb3MgZGUgUlJISCINCg0KIyBDb2xvcmVzIHByZWRlZmluaWRvcyBkZSBsb3MgZ3LDoWZpY29zDQpjb2xfZ2VuZXJvIDwtIGMoIiM4NjI0RjUiLCAiIzFGQzNBQSIpDQpjb2xfZ3JhZiA8LSAiIzk0MzEyNiINCg0KIyBDYXJnYSBkZSBsb3Mgc3VlbGRvcw0Kc3VlbGRvcyA8LSBzaGVldHNfcmVhZCgiMWYzTUNBODFObmpJNDhDMDNHeHhHdTY5aTJoS1pMcnB4ZjR0SHpLa1hMX2siKQ0KDQojIEZpbHRyYW1vcyBsb3Mgc3VlbGRvcyBlbnRyZSBsb3MgcGVyY2VudGlsZXMgNSB5IDk1DQpyZXN1bWVuX251bWVyaWNvIDwtIHByb2ZpbGluZ19udW0oc3VlbGRvcykNCnBlcmNlbnRpbF8wNSA8LSByZXN1bWVuX251bWVyaWNvWzYsNl0NCnBlcmNlbnRpbF85NSA8LSByZXN1bWVuX251bWVyaWNvWzYsMTBdDQoNCiMgTGltcGlhbW9zIHVuIHBvY28gbcOhcyBlbCBkYXRhc2V0DQpzdWVsZG9zIDwtIHN1ZWxkb3MgJT4lIA0KICBmaWx0ZXIoYmV0d2VlbihzdWVsZG9fYnJ1dG8sIHBlcmNlbnRpbF8wNSwgcGVyY2VudGlsXzk1KSwgDQogICAgICAgICBhdW1lbnRvIDwgMTAwLA0KICAgICAgICAgYW5pb3NfcmggPCA0MCwNCiAgICAgICAgIHB1ZXN0byAhPSAiRGlyZWN0b3IiKSANCmBgYA0KDQojIEludHJvZHVjY2nDs24NCg0KRXN0ZSBlcyB1biBlamVyY2ljaW8gZGUgcHLDoWN0aWNhLCByZWFsaXphZG8gZHVyYW50ZSBsYSBzZXNpw7NuIGFiaWVydGEgZGUgTm92aWVtYnJlIGRlbCBbQ2x1YiBkZSBSIHBhcmEgUlJISF0oaHR0cHM6Ly9yNGhyLmNsdWIpLiBTaSBxdWllcmVuIHNhYmVyIG3DoXMsIHB1ZWRlbiBjb250YWN0YXJtZSBlbiBtaSBbcGVyZmlsIGVuIExpbmtlZEluXShodHRwczovL3d3dy5saW5rZWRpbi5jb20vaW4vc2VyZ2lvZ2FyY2lhbW9yYS8pLiDwn6WdDQoNCkxvcyBkYXRvcyB1dGlsaXphZG9zIHNvbiB1bmEgbXVlc3RyYSBkZSBsYSBFbmN1ZXN0YSBLSVdJIGRlIFN1ZWxkb3MgZGUgUlJISCBkZSBMYXRhbSByZWFsaXphZG8gcG9yIGVsIFtDbHViIGRlIFIgcGFyYSBSUkhIXShodHRwczovL3I0aHIuY2x1YikuDQoNCkVzdGUgZXMgdW4gZWplbXBsbyBkZSByZXBvcnRlIHF1ZSBzZSBwdWVkZSBoYWNlciB1dGlsaXphbmRvIFIsIGNvbiBlbCBwYXF1ZXRlIGBSTWFya2Rvd25gLg0KDQojIEFuw6FsaXNpcyBkZSBzdWVsZG9zIGRlIFJSSEggcG9yIHB1ZXN0bw0KDQpgYGB7ciBwdWVzdG9zfQ0Kc3VlbGRvcyA8LSBzdWVsZG9zICU+JSANCiAgbXV0YXRlKHB1ZXN0byA9IGZhY3RvcihwdWVzdG8sIA0KICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkFkbWluaXN0cmF0aXZvIiwgIkFuYWxpc3RhIiwgIkhSQlAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZXNwb25zYWJsZSIsICJKZWZlIiwgIkdlcmVudGUiKSkpIA0KcHVlc3RvcyA8LSBzdWVsZG9zICU+JSANCiAgZ3JvdXBfYnkocHVlc3RvKSAlPiUgDQogIHN1bW1hcmlzZShzdWVsZG9fcHJvbWVkaW8gPSBtZWFuKHN1ZWxkb19icnV0bykpDQoNCiMgSGFjZW1vcyBlbCBncsOhZmljbw0KZ2dwbG90KHB1ZXN0b3MsIGFlcyh4ID0gc3VlbGRvX3Byb21lZGlvLCANCiAgICAgICAgICAgICAgICAgICAgeSA9IHJlb3JkZXIocHVlc3RvLCBzdWVsZG9fcHJvbWVkaW8pKSkgKw0KICBnZW9tX2NvbChmaWxsID0gY29sX2dyYWYpICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byIsDQogICAgICAgc3VidGl0bGUgPSAiRW4gQVIkIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBjb21tYV9mb3JtYXQoYmlnLm1hcmsgPSAiLiIsIGRlY2ltYWwubWFyayA9ICI7IikpICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICIjQ0FDRkQyIikpICsNCiAgZXN0aWxvDQpgYGANCg0KUGFyYSByZWFsaXphciBlc3RlIGdyw6FmaWNvIGZpbHRyYW1vcyBsb3Mgc3VlbGRvcyBwb3IgZW5jaW1hIGRlIGByIHBhc3RlMCgiQVIkICIsY29tbWEocGVyY2VudGlsXzA1LCBiaWcubWFyayA9ICIuIiwgZGVjaW1hbC5tYXJrID0gIjsiKSlgIChwZXJjZW50aWwgNSksIHkgcG9yIGRlYmFqbyBkZSBgciBwYXN0ZTAoIkFSJCAiLGNvbW1hKHBlcmNlbnRpbF85NSwgYmlnLm1hcmsgPSAiLiIsIGRlY2ltYWwubWFyayA9ICI7IikpYCAocGVyY2VudGlsIDk1KS4NCg0KIyMgVGFibGEgZGUgU3VlbGRvcw0KDQpgYGB7cn0NCnNhbGFyaW9zIDwtIHN1ZWxkb3MgJT4lIA0KICBtdXRhdGUocHVlc3RvID0gZmFjdG9yKHB1ZXN0bywgDQogICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiR2VyZW50ZSIsICJKZWZlIiwgIlJlc3BvbnNhYmxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSFJCUCIsICJBbmFsaXN0YSIsICJBZG1pbmlzdHJhdGl2byIpKSkgDQpwdWVzdG9zMiA8LSBzYWxhcmlvcyAlPiUgDQogIGdyb3VwX2J5KHB1ZXN0bykgJT4lIA0KICBzdW1tYXJpc2Uoc3VlbGRvX3Byb21lZGlvID0gbWVhbihzdWVsZG9fYnJ1dG8pKQ0KZ3QocHVlc3RvczIpICU+JSANCiAgdGFiX2hlYWRlcih0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byIpICU+JSANCiAgY29sc19sYWJlbChwdWVzdG8gPSAiUHVlc3RvIiwgDQogICAgICAgICAgICAgc3VlbGRvX3Byb21lZGlvID0gIlN1ZWxkbyBQcm9tZWRpbyIpICU+JSANCiAgZm10X2N1cnJlbmN5KGNvbHVtbnMgPSBjKCJzdWVsZG9fcHJvbWVkaW8iKSwNCiAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIkFSUyIsDQogICAgICAgICAgICAgICBkZWNpbWFscyA9IDApDQogIA0KYGBgDQoNCiMjIERpc3BlcnNpw7NuIGRlIHN1ZWxkb3MgcG9yIHB1ZXN0byB5IGfDqW5lcm8NCg0KRW4gZXN0ZSAqYm94cGxvdCogcG9kZW1vcyBhcHJlY2lhciBsYXMgYW1wbGl0dWRlcyBlbiBsb3Mgc3VlbGRvcyBkZSBjYWRhIHB1ZXN0byBwb3IgZ8OpbmVyby4gTWllbnRyYXMgbcOhcyBsYXJnYSBzZWEgbGEgY2FqYSwgbcOhcyBhbXBsaWEgZXMgbGEgdmFyaWFjacOzbiBkZSBsb3Mgc3VlbGRvcywgeSBhbCBjb250cmFyaW8sIG1pZW50cmFzIG3DoXMgY2hpY2Egc2VhIGxhIGNhamEsIGhheSB1bmEgbWF5b3IgY29uY2VudHJhY2nDs24gZGUgbG9zIHN1ZWxkb3MuDQoNCkEgbG9zIHB1bnRvcyBxdWUgYXBhcmVjZW4gcG9yIGVuY2ltYSBkZSBjYWRhIHVubyBkZSBsb3MgZ3LDoWZpY29zLCBzZSBsb3MgZGVub21pbmEgYG91dGxpZXJgLCB5IHNvbiB2YWxvcmVzIGV4dHJlbW9zLg0KDQpgYGB7cn0NCmdncGxvdChzYWxhcmlvcywgYWVzKHggPSBwdWVzdG8sIHkgPSBzdWVsZG9fYnJ1dG8sIGZpbGwgPSBnZW5lcm8pKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgbGFicyh0aXRsZSA9ICJEaXNwZXJzacOzbiBkZSBzdWVsZG9zIHBvciBwdWVzdG8geSBnw6luZXJvIiwNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlLCANCiAgICAgICBmaWxsID0gIkfDqW5lcm8iKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBjb21tYV9mb3JtYXQoYmlnLm1hcmsgPSAiLiIsIGRlY2ltYWwubWFyayA9ICIsIikpICArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbF9nZW5lcm8pICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICIjQ0FDRkQyIikpICsNCiAgZXN0aWxvDQpgYGANCg0KRXN0ZSB0aXBvIGRlIGdyw6FmaWNvcywgbG9zICpib3hwbG90cyosIHByb3ZlZW4gZGUgbXVjaGEgaW5mb3JtYWNpw7NuIGVzdGFkw61zdGljYS4NCg0KLSAgIEVsIGzDrW1pdGUgaW5mZXJpb3IgZGUgbGEgY2FqYSBlcyBlbCAxwrAgY3VhcnRpbCAoMVEpLg0KLSAgIExhIGzDrW5lYSBkZW50cm8gZGUgbGEgY2FqYSwgZXMgbGEgbWVkaWFuYS4NCi0gICBFbCBsw61taXRlIHN1cGVyaW9yIGRlIGxhIGNhamEgZXMgZWwgM8KwIGN1YXJ0aWwgKDNRKS4NCi0gICBMYXMgbMOtbmVhcyBxdWUgc2FsZW4gZGUgbGEgY2FqYSBzb24gbG9zIGzDrW1pdGVzIHBhcmEgaW5kaWNhciBsb3MgdmFsb3JlcyBvdXRsaWVycyB5IHNlIGNhbGN1bGFuICoqMSw1IHBvciBlbCBSYW5nbyBJbnRlcmN1YXJ0aWwgKDNRIC0gMVEpKiouDQotICAgTG9zIHB1bnRvcyBxdWUgdmVtb3MgbcOhcyBhbGzDoSBkZSBsYXMgbMOtbmVhcyBzb24gKm91dGxpZXJzKi4NCg0KUG9yIGVqZW1wbG8sIGVzdGUgZ3LDoWZpY28gbm9zIHBlcm1pdGUgdmVyIHF1ZSBlbiBlbCBjYXNvIGRlIGxvcyBnZXJlbnRlcywgbm8gaGF5IHVuYSBkaWZlcmVuY2lhIG11eSBhbXBsaWEgZW4gbGEgKiptZWRpYW5hKiogZGUgbG9zIHN1ZWxkb3MgZGUgaG9tYnJlcyB5IG11amVyZXMuIEVuIGNhbWJpbyB2ZW1vcyBxdWUgbGEgY2FqYSBkZWwgZ3LDoWZpY28gZGUgbGFzIG11amVyZXMgZXMgbcOhcyBhbXBsaWEgcXVlIGxhIGRlIGxvcyB2YXJvbmVzLiBFc3RvIHF1aWVyZSBkZWNpciBxdWUgaGF5IHVuYSBwb3JjacOzbiBkZSBtdWplcmVzIGNvbW8gR2VyZW50ZSBkZSBSUkhIIHF1ZSBjb2JyYW4gbWVub3MgcXVlIHN1cyBwYXJlcyBob21icmVzLCB5IHF1ZSB0YW1iacOpbiBoYXkgdW5hIHBvcmNpw7NuIGRlIG11amVyZXMgcXVlIGNvYnJhbiBtw6FzIHF1ZSBsb3MgdmFyb25lcy4NCg0KIyMgUmVsYWNpw7NuIGVudHJlIGHDsW9zIGRlIGV4cGVyaWVuY2lhIHkgc3VlbGRvDQoNCkNvbiBlbCBzaWd1aWVudGUgZ3LDoWZpY28gcXVlcmVtb3MgdmVyIGN1w6FsIGVzIGxhIHJlbGFjacOzbiBlbnRyZSBsb3MgYcOxb3MgZGUgZXhwZXJpZW5jaWEgeSBlbCBzdWVsZG8gYnJ1dG8uDQoNCmBgYHtyfQ0KbW9kZWxvX2xpbmVhbCA8LSBicm9vbTo6dGlkeShsbShkYXRhID0gc3VlbGRvcywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1ZWxkb19icnV0byB+IGFuaW9zX3JoKSkNCm1vZGVsb19saW5lYWwkZXN0aW1hdGUgPC0gZG9sbGFyKG1vZGVsb19saW5lYWwkZXN0aW1hdGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVmaXggPSAiQVIkICIsICAgICMgUG9kZW1vcyBjb250cm9sYXIgZWwgc8OtbWJvbG8gdXRpbGl6YWRvDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaWcubWFyayA9ICIuIiwgICAgICMgQ2FtYmlhIGVsIHNlcGFyYWRvciBkZSBtaWxlcw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjaW1hbC5tYXJrID0gIiwiKSAjIENhbWJpYSBlbCBzZXBhcmFkb3IgZGVjaW1hbA0KZ2dwbG90KHN1ZWxkb3MsIGFlcyh4ID0gYW5pb3NfcmgsIHkgPSBzdWVsZG9fYnJ1dG8pKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAuNywgc2l6ZSA9IDEuNSwgY29sb3IgPSBjb2xfZ3JhZikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArDQogIGxhYnModGl0bGUgPSAiUmVsYWNpw7NuIGVudHJlIGHDsW9zIGRlIGV4cGVyaWVuY2lhIHkgc3VlbGRvcyBkZSBSUkhIIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJFbiBwZXNvcyBhcmdlbnRpbm9zIiwNCiAgICAgICB4ID0gIkHDsW9zIGRlIEV4cGVyaWVuY2lhIiwNCiAgICAgICB5ID0gIlN1ZWxkbyBCcnV0byIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWFfZm9ybWF0KGJpZy5tYXJrID0gIi4iLCBkZWNpbWFsLm1hcmsgPSAiLCIpKSsNCiAgZXN0aWxvDQpgYGANCg0KUG9kZW1vcyB2ZXIgdW5hIHJlbGFjacOzbiBwb3NpdGl2YSBlbnRyZSBsb3MgYcOxb3MgZGUgZXhwZXJpZW5jaWEgeSBlbCBzdWVsZG8sIGVzIGRlY2lyIHF1ZSBhIG1lZGlkYSBxdWUgYXVtZW50YW4gbG9zIGHDsW9zIGRlIGV4cGVyaWVuY2lhIChub3MgbW92ZW1vcyBoYWNpYSBsYSBkZXJlY2hhIGVuIGVsIGVqZSBob3Jpem9udGFsKSwgc3ViZSBlbCBzdWVsZG8gYnJ1dG8gKGVuIGVsIGVqZSB2ZXJ0aWNhbCkuDQoNCkVuIHByb21lZGlvLCB1bmEgcGVyc29uYSBjb24gY2VybyBhw7FvcyBkZSBleHBlcmllbmNpYSBlbiBSUkhIIGNvYnJhIHVuIHN1ZWxkbyBicnV0byBkZSBgciBtb2RlbG9fbGluZWFsWzEsMl1gLiBZIGNvbiBjYWRhIGHDsW8gZGUgZXhwZXJpZW5jaWEsIGVsIHN1ZWxkbyBhdW1lbnRhIGVuIGByIG1vZGVsb19saW5lYWxbMiwyXWAuDQoNCiMgUmF0aW8gZGUgRW1wbGVhZG9zIGRlIFJSSEggcG9yIERvdGFjacOzbg0KDQpDb24gZXN0ZSBpbmRpY2Fkb3IgcXVlcmVtb3MgYW5hbGl6YXIgbGEgY2FudGlkYWQgZGUgZW1wbGVhZG9zIHF1ZSBoYXkgZW4gZWwgw6FyZWEgZGUgUlJISCBlbiByZWxhY2nDs24gYSBsYSBkb3RhY2nDs24gZGUgbGEgZW1wcmVzYS4NCg0KYGBge3IgcmF0aW99DQogcmF0aW8gPC0gc3VlbGRvcyAlPiUgDQogIHNlbGVjdChydWJybywgZW1wbGVhZG9zLCBlbXBsZWFkb3NfcmgpICU+JSANCiAgbXV0YXRlKHJhdGlvX3JoX2RvdGFjaW9uID0gZW1wbGVhZG9zL2VtcGxlYWRvc19yaCkgJT4lIA0KICBncm91cF9ieShydWJybykgJT4lIA0KICBzdW1tYXJpc2UocmF0aW9fcHJvbWVkaW8gPSByb3VuZChtZWFuKHJhdGlvX3JoX2RvdGFjaW9uKSkpICU+JSANCiAgZmlsdGVyKHJhdGlvX3Byb21lZGlvICE9IEluZikgDQpnZ3Bsb3QocmF0aW8sIGFlcyh4PXJhdGlvX3Byb21lZGlvLCANCiAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gcmVvcmRlcihydWJybywgcmF0aW9fcHJvbWVkaW8pKSkrDQogIGdlb21fcG9pbnQoY29sb3IgPSBjb2xfZ3JhZiwgc2l6ZSA9IDQpKw0KICBnZW9tX3NlZ21lbnQoYWVzKHkgPSBydWJybywgeWVuZD0gcnVicm8sIHg9MCwgeGVuZD1yYXRpb19wcm9tZWRpbyksDQogICAgICAgICAgICAgICBjb2xvcj0iIzVENkQ3RSIpICsNCiAgZXN0aWxvICsNCiAgbGFicyh0aXRsZT0iUmF0aW8gZGUgRW1wbGVhZG9zIGRlIFJIIFxuIHBvciBEb3RhY2nDs24iLA0KICAgICAgIHN1YnRpdGxlID0gIkRldGFsbGFkbyBwb3IgcnVicm8gZGUgbGEgZW1wcmVzYSIsIA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUsIA0KICAgICAgIHg9IiIsIHk9ICIiKSArDQogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiI0NBQ0ZEMiIpKQ0KYGBgDQoNCiMgQWdyYWRlY2ltaWVudG9zDQoNCkFncmFkZXpjbyBhIHRvZG9zIGxvcyBwYXJ0aWNpcGFudGVzIGRlbCBjdXJzbyAqKiJJbnRyb2R1Y2Npw7NuIGEgUiBwYXJhIFJSSEgiKiogcXVlIGRpY3RhbW9zIGVuIFtEYXRhIDRIUl0oaHR0cHM6Ly9kYXRhLTRoci5jb20pLiBQYXJhIGNvbm9jZXIgbnVlc3RyYXMgcHLDs3hpbWFzIGZlY2hhcywgeSB0b2RhcyBudWVzdHJhcyBhY3RpdmlkYWRlcyBkZSBmb3JtYWNpw7NuIHBvZMOpcyBlbnRyYXIgZW4gW2VzdGUgbGlua10oaHR0cHM6Ly93d3cuY3Vyc2Vsby5jb20uYXIvZGF0YTRocikgbyBwb3IgbWFpbCBhIFtzZXJnaW9cQGQ0aHIuY29tXShtYWlsdG86c2VyZ2lvQGQ0aHIuY29tKS4NCg0KRXN0ZSBlcyB1biBjdXJzbyBlbiBjYXN0ZWxsYW5vLCBxdWUgdXRpbGl6YSBkYXRvcyBkZSBSUkhILCBwYXJhIGZhY2lsaXRhciBlbCBhcHJlbmRpemFqZSBkZWwgdXNvIGRlIGVzdGUgbGVuZ3VhamUgZGUgYW7DoWxpc2lzIGRlIGRhdG9zLg0KDQpZIHNpIHlhIHNhYsOpcyBhbGdvIGRlIFIgeSB0ZSBpbnRlcmVzYSBzZXIgcGFydGUgZGUgdW5hIGNvbXVuaWRhZCBkZSBSIGVuZm9jYWRhIGVuIFJSSEgsIHRlIGludml0YW1vcyBhIHNlZ3Vpcm5vcyBlbiBlbCBbQ2x1YiBkZSBSIHBhcmEgUlJISF0oaHR0cHM6Ly9yNGhyLmNsdWIpLg0KDQo8YnI+PGJyPjxicj4gXCMgVGhlIFdhbGwNCg0KIyMgRGlzY28gMQ0KDQojIyMgTGFkbyAxDQoNCjEuICBJbiB0aGUgRmxlc2g/DQoNCjIuICBUaGUgVGhpbiBJY2UNCg0KMy4gIEFub3RoZXIgKipCcmljayBpbiB0aGUgV2FsbCoqIChQYXJ0IEkpDQoNCjQuICBUaGUgSGFwcGllc3QgRGF5cyBvZiBPdXIgTGl2ZXMNCg0KNS4gIEFub3RoZXIgQnJpY2sgaW4gdGhlIFdhbGwgKFBhcnQgSUkpDQoNCjYuICBNb3RoZXINCg0KYGBge3IgYmxvcXVlMX0NCg0KYWRpY2lvbiA8LSAyNiArIDE0NA0KYGBgDQoNCkVsIHJlc3VsdGFkbyBkZSBsYSBzdW1hIGVzIGByIGFkaWNpb25gDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmBgYA0K