library(tidyverse)
library(gargle)
library(googlesheets4)
library(funModeling)
library(gt)
library(scales)
library(extrafont)
loadfonts(quiet = TRUE)

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


fuente <- "Fuente: Encuesta KIWI de Sueldos de RRHH"

col_genero <- c("#8624F5", "#1FC3AA")
col_graf <- "#5DADE2"


sueldos <- sheets_read("1f3MCA81NnjI48C03GxxGu69i2hKZLrpxf4tHzKkXL_k")

resumen_numerico <- profiling_num(sueldos)
percentil_05 <- resumen_numerico[6,6]
percentil_95 <- resumen_numerico[6,10]

sueldos <- sueldos %>% 
  filter(between(sueldo_bruto, percentil_05, percentil_95), 
         aumento < 100,
         anios_rh < 40,
         puesto != "Director") 

Este es un ejercicio de práctica, realizado durante el curso “Introducción a R para RRHH” de Data 4HR. Si quieren saber más, pueden contactarme en mi perfil en LinkedIn o por Twitter.

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))

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

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) +
  estilo +
  theme(panel.grid.major.y = element_line(colour = "#CACFD2"))

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.




LS0tDQp0aXRsZTogIlJlbGV2YW1pZW50byBQYXJjaWFsIFN1ZWxkb3MgZGUgUlJISCBBcmdlbnRpbmEiDQpzdWJ0aXRsZTogIkN1cnNvIEludHJvZHVjY2nDs24gYSBSIHBhcmEgUlJISCINCmF1dGhvcjogIlNlcmdpbyBkZSBEYXRhIDRIUiINCmRhdGU6ICJPY3R1YnJlIDIwMjAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOiBzcGFjZWxhYg0KICAgIGhpZ2hsaWdodDogcHlnbWVudHMNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGRwaT0zMDApDQpgYGANCg0KYGBge3IgbGlicmVyaWFzLWRhdG9zfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGdhcmdsZSkNCmxpYnJhcnkoZ29vZ2xlc2hlZXRzNCkNCmxpYnJhcnkoZnVuTW9kZWxpbmcpDQpsaWJyYXJ5KGd0KQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KGV4dHJhZm9udCkNCmxvYWRmb250cyhxdWlldCA9IFRSVUUpDQoNCiMgRXN0aWxvIGRlIGxvcyBncsOhZmljb3MNCmVzdGlsbyA8LSB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNmYmZjZmMiKSwNCiAgICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIk11c2VvTW9kZXJubyIpKQ0KDQoNCmZ1ZW50ZSA8LSAiRnVlbnRlOiBFbmN1ZXN0YSBLSVdJIGRlIFN1ZWxkb3MgZGUgUlJISCINCg0KY29sX2dlbmVybyA8LSBjKCIjODYyNEY1IiwgIiMxRkMzQUEiKQ0KY29sX2dyYWYgPC0gIiM1REFERTIiDQoNCg0Kc3VlbGRvcyA8LSBzaGVldHNfcmVhZCgiMWYzTUNBODFObmpJNDhDMDNHeHhHdTY5aTJoS1pMcnB4ZjR0SHpLa1hMX2siKQ0KDQpyZXN1bWVuX251bWVyaWNvIDwtIHByb2ZpbGluZ19udW0oc3VlbGRvcykNCnBlcmNlbnRpbF8wNSA8LSByZXN1bWVuX251bWVyaWNvWzYsNl0NCnBlcmNlbnRpbF85NSA8LSByZXN1bWVuX251bWVyaWNvWzYsMTBdDQoNCnN1ZWxkb3MgPC0gc3VlbGRvcyAlPiUgDQogIGZpbHRlcihiZXR3ZWVuKHN1ZWxkb19icnV0bywgcGVyY2VudGlsXzA1LCBwZXJjZW50aWxfOTUpLCANCiAgICAgICAgIGF1bWVudG8gPCAxMDAsDQogICAgICAgICBhbmlvc19yaCA8IDQwLA0KICAgICAgICAgcHVlc3RvICE9ICJEaXJlY3RvciIpIA0KYGBgDQoNCkVzdGUgZXMgdW4gZWplcmNpY2lvIGRlIHByw6FjdGljYSwgcmVhbGl6YWRvIGR1cmFudGUgZWwgY3Vyc28gKioiSW50cm9kdWNjacOzbiBhIFIgcGFyYSBSUkhIIioqIGRlIFtEYXRhIDRIUl0oaHR0cHM6Ly9kYXRhLTRoci5jb20pLiBTaSBxdWllcmVuIHNhYmVyIG3DoXMsIHB1ZWRlbiBjb250YWN0YXJtZSBlbiBbbWkgcGVyZmlsIGVuIExpbmtlZEluXShodHRwczovL3d3dy5saW5rZWRpbi5jb20vaW4vc2VyZ2lvZ2FyY2lhbW9yYS8pIG8gcG9yIFtUd2l0dGVyXShodHRwczovL3R3aXR0ZXIuY29tL3Nlcmdpb2dhcmNpYW1vcikuDQoNCkxvcyBkYXRvcyB1dGlsaXphZG9zIHNvbiB1bmEgbXVlc3RyYSBkZSBsYSBFbmN1ZXN0YSBLSVdJIGRlIFN1ZWxkb3MgZGUgUlJISCBkZSBMYXRhbSByZWFsaXphZG8gcG9yIGVsIFtDbHViIGRlIFIgcGFyYSBSUkhIXShodHRwczovL3I0aHIuY2x1YikuDQoNCkVzdGUgZXMgdW4gZWplbXBsbyBkZSByZXBvcnRlIHF1ZSBzZSBwdWVkZSBoYWNlciB1dGlsaXphbmRvIFIsIGNvbiBlbCBwYXF1ZXRlIGBSTWFya2Rvd25gLg0KDQojIEFuw6FsaXNpcyBkZSBzdWVsZG9zIGRlIFJSSEggcG9yIHB1ZXN0bw0KDQpgYGB7ciBwdWVzdG9zfQ0Kc3VlbGRvcyA8LSBzdWVsZG9zICU+JSANCiAgbXV0YXRlKHB1ZXN0byA9IGZhY3RvcihwdWVzdG8sIA0KICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkFkbWluaXN0cmF0aXZvIiwgIkFuYWxpc3RhIiwgIkhSQlAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZXNwb25zYWJsZSIsICJKZWZlIiwgIkdlcmVudGUiKSkpIA0KDQpwdWVzdG9zIDwtIHN1ZWxkb3MgJT4lIA0KICBncm91cF9ieShwdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2JydXRvKSkNCg0KZ2dwbG90KHB1ZXN0b3MsIGFlcyh4ID0gc3VlbGRvX3Byb21lZGlvLCANCiAgICAgICAgICAgICAgICAgICAgeSA9IHJlb3JkZXIocHVlc3RvLCBzdWVsZG9fcHJvbWVkaW8pKSkgKw0KICBnZW9tX2NvbChmaWxsID0gIiM1REFERTIiKSArDQogIGxhYnModGl0bGUgPSAiU3VlbGRvIHByb21lZGlvIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gIkVuIEFSJCIsDQogICAgICAgeCA9ICIiLCB5PSIiLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZXN0aWxvICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hX2Zvcm1hdChiaWcubWFyayA9ICIuIiwgZGVjaW1hbC5tYXJrID0gIjsiKSkgKw0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIiNDQUNGRDIiKSkNCmBgYA0KDQpQYXJhIHJlYWxpemFyIGVzdGUgZ3LDoWZpY28gZmlsdHJhbW9zIGxvcyBzdWVsZG9zIHBvciBlbmNpbWEgZGUgIGByIHBhc3RlMCgiQVIkICIsY29tbWEocGVyY2VudGlsXzA1LCBiaWcubWFyayA9ICIuIiwgZGVjaW1hbC5tYXJrID0gIjsiKSlgIChwZXJjZW50aWwgNSksIHkgcG9yIGRlYmFqbyBkZSBgciBwYXN0ZTAoIkFSJCAiLGNvbW1hKHBlcmNlbnRpbF85NSwgYmlnLm1hcmsgPSAiLiIsIGRlY2ltYWwubWFyayA9ICI7IikpYCAocGVyY2VudGlsIDk1KS4NCg0KDQoNCg0KIyMgVGFibGEgZGUgU3VlbGRvcw0KDQpgYGB7cn0NCnNhbGFyaW9zIDwtIHN1ZWxkb3MgJT4lIA0KICBtdXRhdGUocHVlc3RvID0gZmFjdG9yKHB1ZXN0bywgDQogICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiR2VyZW50ZSIsICJKZWZlIiwgIlJlc3BvbnNhYmxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSFJCUCIsICJBbmFsaXN0YSIsICJBZG1pbmlzdHJhdGl2byIpKSkgDQoNCnB1ZXN0b3MyIDwtIHNhbGFyaW9zICU+JSANCiAgZ3JvdXBfYnkocHVlc3RvKSAlPiUgDQogIHN1bW1hcmlzZShzdWVsZG9fcHJvbWVkaW8gPSBtZWFuKHN1ZWxkb19icnV0bykpDQoNCmd0KHB1ZXN0b3MyKSAlPiUgDQogIHRhYl9oZWFkZXIodGl0bGUgPSAiU3VlbGRvIHByb21lZGlvIHBvciBwdWVzdG8iKSAlPiUgDQogIGNvbHNfbGFiZWwocHVlc3RvID0gIlB1ZXN0byIsIA0KICAgICAgICAgICAgIHN1ZWxkb19wcm9tZWRpbyA9ICJTdWVsZG8gUHJvbWVkaW8iKSAlPiUgDQogIGZtdF9jdXJyZW5jeShjb2x1bW5zID0gYygic3VlbGRvX3Byb21lZGlvIiksDQogICAgICAgICAgICAgICBjdXJyZW5jeSA9ICJBUlMiLA0KICAgICAgICAgICAgICAgZGVjaW1hbHMgPSAwKQ0KICANCmBgYA0KDQojIyBEaXNwZXJzacOzbiBkZSBzdWVsZG9zIHBvciBwdWVzdG8geSBnw6luZXJvDQoNCkVuIGVzdGUgKmJveHBsb3QqIHBvZGVtb3MgYXByZWNpYXIgbGFzIGFtcGxpdHVkZXMgZW4gbG9zIHN1ZWxkb3MgZGUgY2FkYSBwdWVzdG8gcG9yIGfDqW5lcm8uIE1pZW50cmFzIG3DoXMgbGFyZ2Egc2VhIGxhIGNhamEsIG3DoXMgYW1wbGlhIGVzIGxhIHZhcmlhY2nDs24gZGUgbG9zIHN1ZWxkb3MsIHkgYWwgY29udHJhcmlvLCBtaWVudHJhcyBtw6FzIGNoaWNhIHNlYSBsYSBjYWphLCBoYXkgdW5hIG1heW9yIGNvbmNlbnRyYWNpw7NuIGRlIGxvcyBzdWVsZG9zLg0KDQpBIGxvcyBwdW50b3MgcXVlIGFwYXJlY2VuIHBvciBlbmNpbWEgZGUgY2FkYSB1bm8gZGUgbG9zIGdyw6FmaWNvcywgc2UgbG9zIGRlbm9taW5hIGBvdXRsaWVyYCwgeSBzb24gdmFsb3JlcyBleHRyZW1vcy4NCg0KYGBge3J9DQpnZ3Bsb3Qoc2FsYXJpb3MsIGFlcyh4ID0gcHVlc3RvLCB5ID0gc3VlbGRvX2JydXRvLCBmaWxsID0gZ2VuZXJvKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnModGl0bGUgPSAiRGlzcGVyc2nDs24gZGUgc3VlbGRvcyBwb3IgcHVlc3RvIHkgZ8OpbmVybyIsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSwgDQogICAgICAgZmlsbCA9ICJHw6luZXJvIikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWFfZm9ybWF0KGJpZy5tYXJrID0gIi4iLCBkZWNpbWFsLm1hcmsgPSAiLCIpKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbF9nZW5lcm8pICsNCiAgZXN0aWxvICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICIjQ0FDRkQyIikpDQoNCmBgYA0KDQpFc3RlIHRpcG8gZGUgZ3LDoWZpY29zLCBsb3MgKmJveHBsb3RzKiwgcHJvdmVlbiBkZSBtdWNoYSBpbmZvcm1hY2nDs24gZXN0YWTDrXN0aWNhLiANCg0KKiBFbCBsw61taXRlIGluZmVyaW9yIGRlIGxhIGNhamEgZXMgZWwgMcKwIGN1YXJ0aWwgKDFRKS4NCiogTGEgbMOtbmVhIGRlbnRybyBkZSBsYSBjYWphLCBlcyBsYSBtZWRpYW5hLg0KKiBFbCBsw61taXRlIHN1cGVyaW9yIGRlIGxhIGNhamEgZXMgZWwgM8KwIGN1YXJ0aWwgKDNRKS4NCiogTGFzIGzDrW5lYXMgcXVlIHNhbGVuIGRlIGxhIGNhamEgc29uIGxvcyBsw61taXRlcyBwYXJhIGluZGljYXIgbG9zIHZhbG9yZXMgb3V0bGllcnMgeSBzZSBjYWxjdWxhbiAqKjEsNSBwb3IgZWwgUmFuZ28gSW50ZXJjdWFydGlsICgzUSAtIDFRKSoqLg0KKiBMb3MgcHVudG9zIHF1ZSB2ZW1vcyBtw6FzIGFsbMOhIGRlIGxhcyBsw61uZWFzIHNvbiAqb3V0bGllcnMqLg0KDQpQb3IgZWplbXBsbywgZXN0ZSBncsOhZmljbyBub3MgcGVybWl0ZSB2ZXIgcXVlIGVuIGVsIGNhc28gZGUgbG9zIGdlcmVudGVzLCBubyBoYXkgdW5hIGRpZmVyZW5jaWEgbXV5IGFtcGxpYSBlbiBsYSAqKm1lZGlhbmEqKiBkZSBsb3Mgc3VlbGRvcyBkZSBob21icmVzIHkgbXVqZXJlcy4gRW4gY2FtYmlvIHZlbW9zIHF1ZSBsYSBjYWphIGRlbCBncsOhZmljbyBkZSBsYXMgbXVqZXJlcyBlcyBtw6FzIGFtcGxpYSBxdWUgbGEgZGUgbG9zIHZhcm9uZXMuIEVzdG8gcXVpZXJlIGRlY2lyIHF1ZSBoYXkgdW5hIHBvcmNpw7NuIGRlIG11amVyZXMgY29tbyBHZXJlbnRlIGRlIFJSSEggcXVlIGNvYnJhbiBtZW5vcyBxdWUgc3VzIHBhcmVzIGhvbWJyZXMsIHkgcXVlIHRhbWJpw6luIGhheSB1bmEgcG9yY2nDs24gZGUgbXVqZXJlcyBxdWUgY29icmFuIG3DoXMgcXVlIGxvcyB2YXJvbmVzLg0KDQojIyBSZWxhY2nDs24gZW50cmUgYcOxb3MgZGUgZXhwZXJpZW5jaWEgeSBzdWVsZG8NCg0KQ29uIGVsIHNpZ3VpZW50ZSBncsOhZmljbyBxdWVyZW1vcyB2ZXIgY3XDoWwgZXMgbGEgcmVsYWNpw7NuIGVudHJlIGxvcyBhw7FvcyBkZSBleHBlcmllbmNpYSB5IGVsIHN1ZWxkbyBicnV0by4NCg0KDQpgYGB7cn0NCm1vZGVsb19saW5lYWwgPC0gYnJvb206OnRpZHkobG0oZGF0YSA9IHN1ZWxkb3MsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWVsZG9fYnJ1dG8gfiBhbmlvc19yaCkpDQoNCm1vZGVsb19saW5lYWwkZXN0aW1hdGUgPC0gZG9sbGFyKG1vZGVsb19saW5lYWwkZXN0aW1hdGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVmaXggPSAiQVIkICIsICAgICMgUG9kZW1vcyBjb250cm9sYXIgZWwgc8OtbWJvbG8gdXRpbGl6YWRvDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaWcubWFyayA9ICIuIiwgICAgICMgQ2FtYmlhIGVsIHNlcGFyYWRvciBkZSBtaWxlcw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjaW1hbC5tYXJrID0gIiwiKSAjIENhbWJpYSBlbCBzZXBhcmFkb3IgZGVjaW1hbA0KDQoNCmdncGxvdChzdWVsZG9zLCBhZXMoeCA9IGFuaW9zX3JoLCB5ID0gc3VlbGRvX2JydXRvKSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gLjcsIHNpemUgPSAxLjUsIGNvbG9yID0gY29sX2dyYWYpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKw0KICBsYWJzKHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBhw7FvcyBkZSBleHBlcmllbmNpYSB5IHN1ZWxkb3MgZGUgUlJISCIsDQogICAgICAgc3VidGl0bGUgPSAiRW4gcGVzb3MgYXJnZW50aW5vcyIsDQogICAgICAgeCA9ICJBw7FvcyBkZSBFeHBlcmllbmNpYSIsDQogICAgICAgeSA9ICJTdWVsZG8gQnJ1dG8iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hX2Zvcm1hdChiaWcubWFyayA9ICIuIiwgZGVjaW1hbC5tYXJrID0gIiwiKSkgKw0KICBlc3RpbG8NCmBgYA0KDQpQb2RlbW9zIHZlciB1bmEgcmVsYWNpw7NuIHBvc2l0aXZhIGVudHJlIGxvcyBhw7FvcyBkZSBleHBlcmllbmNpYSB5IGVsIHN1ZWxkbywgZXMgZGVjaXIgcXVlIGEgbWVkaWRhIHF1ZSBhdW1lbnRhbiBsb3MgYcOxb3MgZGUgZXhwZXJpZW5jaWEgKG5vcyBtb3ZlbW9zIGhhY2lhIGxhIGRlcmVjaGEgZW4gZWwgZWplIGhvcml6b250YWwpLCBzdWJlIGVsIHN1ZWxkbyBicnV0byAoZW4gZWwgZWplIHZlcnRpY2FsKS4gDQoNCkVuIHByb21lZGlvLCB1bmEgcGVyc29uYSBjb24gY2VybyBhw7FvcyBkZSBleHBlcmllbmNpYSBlbiBSUkhIIGNvYnJhIHVuIHN1ZWxkbyBicnV0byBkZSBgciBtb2RlbG9fbGluZWFsWzEsMl1gLiBZIGNvbiBjYWRhIGHDsW8gZGUgZXhwZXJpZW5jaWEsIGVsIHN1ZWxkbyBhdW1lbnRhIGVuIGByIG1vZGVsb19saW5lYWxbMiwyXWAuDQoNCiMgUmF0aW8gZGUgRW1wbGVhZG9zIGRlIFJSSEggcG9yIERvdGFjacOzbg0KDQpDb24gZXN0ZSBpbmRpY2Fkb3IgcXVlcmVtb3MgYW5hbGl6YXIgbGEgY2FudGlkYWQgZGUgZW1wbGVhZG9zIHF1ZSBoYXkgZW4gZWwgw6FyZWEgZGUgUlJISCBlbiByZWxhY2nDs24gYSBsYSBkb3RhY2nDs24gZGUgbGEgZW1wcmVzYS4NCg0KYGBge3IgcmF0aW99DQoNCiByYXRpbyA8LSBzdWVsZG9zICU+JSANCiAgc2VsZWN0KHJ1YnJvLCBlbXBsZWFkb3MsIGVtcGxlYWRvc19yaCkgJT4lIA0KICBtdXRhdGUocmF0aW9fcmhfZG90YWNpb24gPSBlbXBsZWFkb3MvZW1wbGVhZG9zX3JoKSAlPiUgDQogIGdyb3VwX2J5KHJ1YnJvKSAlPiUgDQogIHN1bW1hcmlzZShyYXRpb19wcm9tZWRpbyA9IHJvdW5kKG1lYW4ocmF0aW9fcmhfZG90YWNpb24pKSkgJT4lIA0KICBmaWx0ZXIocmF0aW9fcHJvbWVkaW8gIT0gSW5mKSANCg0KZ2dwbG90KHJhdGlvLCBhZXMoeD1yYXRpb19wcm9tZWRpbywgDQogICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHJlb3JkZXIocnVicm8sIHJhdGlvX3Byb21lZGlvKSkpKw0KICBnZW9tX3BvaW50KGNvbG9yID0gY29sX2dyYWYsIHNpemUgPSA0KSsNCiAgZ2VvbV9zZWdtZW50KGFlcyh5ID0gcnVicm8sIHllbmQ9IHJ1YnJvLCB4PTAsIHhlbmQ9cmF0aW9fcHJvbWVkaW8pLA0KICAgICAgICAgICAgICAgY29sb3I9IiM1RDZEN0UiKSArDQogIGVzdGlsbyArDQogIGxhYnModGl0bGU9IlJhdGlvIGRlIEVtcGxlYWRvcyBkZSBSSCBcbiBwb3IgRG90YWNpw7NuIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJEZXRhbGxhZG8gcG9yIHJ1YnJvIGRlIGxhIGVtcHJlc2EiLCANCiAgICAgICBjYXB0aW9uID0gZnVlbnRlLCANCiAgICAgICB4PSIiLCB5PSAiIikgKw0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIiNDQUNGRDIiKSkNCmBgYA0KDQojIEFncmFkZWNpbWllbnRvcw0KDQpBZ3JhZGV6Y28gYSB0b2RvcyBsb3MgcGFydGljaXBhbnRlcyBkZWwgY3Vyc28gKioiSW50cm9kdWNjacOzbiBhIFIgcGFyYSBSUkhIIioqIHF1ZSBkaWN0YW1vcyBlbiBbRGF0YSA0SFJdKGh0dHBzOi8vZGF0YS00aHIuY29tKS4gUGFyYSBjb25vY2VyIG51ZXN0cmFzIHByw7N4aW1hcyBmZWNoYXMsIHkgdG9kYXMgbnVlc3RyYXMgYWN0aXZpZGFkZXMgZGUgZm9ybWFjacOzbiBwb2TDqXMgZW50cmFyIGVuIFtlc3RlIGxpbmtdKGh0dHBzOi8vd3d3LmN1cnNlbG8uY29tLmFyL2RhdGE0aHIpIG8gcG9yIG1haWwgYSBbc2VyZ2lvQGQ0aHIuY29tXShtYWlsdG86c2VyZ2lvQGQ0aHIuY29tKS4gDQoNCkVzdGUgZXMgdW4gY3Vyc28gZW4gY2FzdGVsbGFubywgcXVlIHV0aWxpemEgZGF0b3MgZGUgUlJISCwgcGFyYSBmYWNpbGl0YXIgZWwgYXByZW5kaXphamUgZGVsIHVzbyBkZSBlc3RlIGxlbmd1YWplIGRlIGFuw6FsaXNpcyBkZSBkYXRvcy4NCg0KWSBzaSB5YSBzYWLDqXMgYWxnbyBkZSBSIHkgdGUgaW50ZXJlc2Egc2VyIHBhcnRlIGRlIHVuYSBjb211bmlkYWQgZGUgUiBlbmZvY2FkYSBlbiBSUkhILCB0ZSBpbnZpdGFtb3MgYSBzZWd1aXJub3MgZW4gZWwgW0NsdWIgZGUgUiBwYXJhIFJSSEhdKGh0dHBzOi8vcjRoci5jbHViKS4NCg0KPGJyPjxicj48YnI+DQo=