Introducción

El Club de R para RRHH es una comunidad de aprendizaje de programación de R, destinada a los profesionales y estudiantes que trabajan o quieren trabajar en el Ôrea.

Somos una comunidad que usa mayormente datos de ejemplo relacionados con RRHH, y que genera contenido en castellano para eliminar las barreras en el aprendizaje y facilitar que mƔs personas adopten las herramientas de anƔlisis de datos en sus trabajos.

Para saber mƔs de nosotros te invitamos a leer este post.

PodƩs acceder a los datos de la encuesta en este link.

library(tidyverse)      # Transformar y limpiar datos
library(googlesheets4)  # Leer datos desde Google Sheets
library(gargle)         # Corregir lectura de sĆ­mbolos especiales desde Google Sheets
library(gt)             # Dar formato a las tablas
library(extrafont)      # Permite utilizar otras fuentes en los grƔficos y salidas
library(ggthemes)       # Amplƭa las posibilidades estƩticas de ggplot2
library(scales)         # Permite cambiar los formatos de decimales, de porcentajes, etc.
library(ggalt)          # Nuevos tipos de geom para ggplot2. Para realizar el grƔfico de gap salarial
library(funModeling)    # Para explorar datos y modelos
library(forcats)
library(DT)

options(scipen = 999)   # Modifica la visualización de los ejes numérico a valores nominales

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 = "Roboto"))

# 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 = "Roboto"))

# 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 = "Roboto"))

genero <- c("#8624F5", "#1FC3AA", "#FFD129", "#75838F") #Violeta - Verde - Amarillo - Gris
genero3 <- c("#8624F5","#FFD129", "#1FC3AA")

colores <-  c("#8624F5", "#1FC3AA")

azul <- "#344D7E"
verde <-  "#4A9FC7"
rosa1 <- "#B95192"
rosa2 <- "#EE5777"
naranja <- "#FF764C"
amarillo <- "#FFA600"
gris <- "#75838F"
lila <- "#755395"
rojo <- "#943126"

col4 <- c(azul, lila, rosa1, rosa2)
col5 <- c(azul, lila, rosa1, rosa2, naranja)
col6 <- c(azul, lila, rosa1, rosa2, naranja, amarillo)

# Creo un objeto con un texto que se va a repetir mucho a lo largo del anƔlisis
fuente <- "Fuente: Encuesta KIWI de Sueldos de RRHH para Latam"

# 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 = ","))


# Carga de datos

original <- sheets_read("1aeuu9dVfN42EjyvbmhEcsf0ilSz2DiXU-0MpnF896ss")
tipo_cambio <- sheets_read("1tEc4-_gXJi4lJ_Bj_ysleC-O01jiVOumOQCxGQ1tShM") %>% 
  select(pais, tipo_cambio)


# Preprocesamiento 
kiwi <- original

limpios <- make.names(colnames(kiwi))
colnames(kiwi) <- limpios

rm(limpios)

kiwi <- kiwi %>% 
  select(-X.QuerƩs.contestar.mƔs.preguntas....31, 
         -X.QuerƩs.contestar.mƔs.preguntas....42) %>% 
  rename(genero = GƩnero,
         genero_diverso = X.Te.identificƔs.como.LGBT...lesbiana..gay..bisexual..transexual..otra.minorƭa.sexual..,
         edad = Edad,
         discapacidad = X.TenƩs.alguna.discapacidad.,
         nivel_formacion = `MÔximo.nivel.de.formación`,
         carrera_grado = X.QuƩ.carrera.de.grado.estudiaste.,
         tipo_universidad = X.En.quƩ.tipo.de.universidad.estudiaste.tu.carrera.de.grado.,
         pais = PaĆ­s.en.el.que.trabajas,
         provincia = Provincia.donde.trabajas,
         trabajo = Trabajo,
         rubro = Rubro.de.la.empresa,
         dotacion = X.CuƔntos.empleados.tiene.la.empresa.,
         origen_capital = Origen.del.capital,
         dotacion_rh = X.CuƔntas.personas.integran.el.Ɣrea.de.RRHH.,
         puesto = X.En.quƩ.puesto.trabajƔs.,
         tipo_contratacion = Tipo.de.contratación,
         funcion_rh = X.CuÔl.es.tu.función.principal.en.RRHH.,
         personas_a_cargo = "X.CuƔntas.personas.tenƩs.a.cargo...ponƩ.0.si.no.tenƩs.gente.a.cargo.",
         anios_en_empresa = "X.Hace.cuƔntos.aƱos.trabajas.en.la.empresa.donde.estƔs...0.para.menos.de.un.aƱo.",
         anios_en_puesto = "X.Hace.cuƔntos.aƱos.estƔs.en.tu.puesto.actual...0.para.menos.de.un.aƱo.",
         anios_experiencia = X.CuƔntos.aƱos.de.experiencia.tenƩs.en.RRHH.,
         sueldo_bruto = X.CuÔl.es.tu.remuneración.BRUTA.MENSUAL.en.tu.moneda.local...antes.de.impuestos.y.deducciones.,
         beneficios = X.QuƩ.beneficios.tenƩs.,
         bono = X.RecibĆ­s.bonos.,
         ajuste = X.Tuviste.ajustes.por.inflación.en.2020.,
         ajuste_porcentaje = X.CuƔl.fue.el.porcentaje.de.aumento.acumulado.que.tuviste.en.2020.,
         ajuste_mes = Mes.del.Ćŗltimo.ajuste,
         otros_proyectos = X.TrabajƔs.en.proyectos.independientes.ademƔs.de.tu.empleo.,
         erp = X.Qué.sistema.de.gestión.de.RRHH.usan.en.tu.empresa.,
         nombre_area = X.Cómo.se.llama.el.Ôrea.en.tu.empresa.,
         mate = X.Se.podĆ­a.tomar.mate.en.las.oficinas.de.tu.empresa...antes.del.COVID.19.,
         idioma_exigencia = X.Te.exigieron.saber.un.idioma.extranjero..inglƩs..portuguƩs..etc...para.entrar.a.trabajar.en.tu.empresa.,
         idioma_porcentaje = X.QuƩ.porcentaje.del.tiempo.usas.el.idioma.extranjero.en.tu.puesto.actual.,
         contactos_linkedin = "X.CuƔntos.contactos.tenƩs.en.LinkedIn...ponƩ.0.si.no.tenƩs.cuenta.de.LinkedIn.",
         satisfaccion = X.QuƩ.tan.satisfecho.estƔs.con.tu.empresa.,
         busqueda = X.EstƔs.buscando.trabajo.,
         beneficios_expectativa = X.QuƩ.beneficios.te.gustarƭa.tener.,
         rh_una_palabra = DefinĆ­.a.RRHH.con.una.sola.palabra,
         pregunta_bizarra = X.CuƔl.es.la.pregunta.mƔs.bizarra.que.te.han.hecho.has.hecho.en.una.entrevista.,
         teletrabajo = X.EstƔs.trabajando.desde.tu.casa.,
         elementos = X.Qué.elementos.te.proveyó.la.empresa.para.que.puedas.trabajar.desde.tu.casa.,
         valoracion_gestion_empresa = X.Cómo.valorarías.la.gestión.de.tu.empresa.en.este.nuevo.contexto.,
         registro_fiscal = X.Cómo.estÔs.registrado.a.fiscalmente.,
         anios_freelance = X.Hace.cuƔntos.aƱos.trabajƔs.como.freelance.,
         lugar_trabajo = X.Dónde.trabajÔs.habitualmente...sin.considerar.la.coyuntura.por.COVID.19.,
         exporta = X.ExportƔs.tus.servicios.,
         medio_pago_exterior = Si.exportƔs.servicios...a.travƩs.de.quƩ.medios.de.pago.recibƭs.los.pagos.del.exterior.,
         cuotas = X.AceptƔs.pagos.en.cuotas.,
         colaboracion_freelance = X.TrabajƔs.con.otros.freelancers.de.tu.mismo.rubro.,
         servicio_busqueda = X.Tu.servicio.principal.estÔ.relacionado.con.búsqueda.y.selección.,
         busqueda_it = X.Te.dedicÔs.principalmente.a.realizar.búsquedas.de.IT.Tecnología.,
         trabajo_a_riesgo =X.TrabajƔs.a.riesgo.,
         coeficiente = X.CuƔl.es.el.coeficiente.que.cobrƔs.por.tus.servicios.,
         base_coeficiente = El.coeficiente.lo.calculƔs.sobre.,
         garantia = X.OfrecƩs.garantƭa.,
         servicio_principal = X.CuƔl.es.el.servicio.principal.que.brindas...si.brindƔs.mƔs.de.un.servicio..elegƭ.el.que.mƔs.ingresos.genere.,
         valor_hora = X.CuƔl.es.el.valor.hora.promedio.que.ofrecƩs...moneda.local.)

# Base de freelancers
freelo <- kiwi %>% 
  filter(trabajo == "Freelance")

# Base de empleados en relación de dependencia
rh <- kiwi %>% 
  filter(trabajo == "Relación de Dependencia", 
         funcion_rh != "Ninguno",
         funcion_rh != "No me desempeƱo en el Ɣrea de RRHH.",
         funcion_rh != "Trabajo en el Ɣrea de Sistemas.",
         funcion_rh != "No trabajo en el area",
         funcion_rh != "No trabajo en recursos humanos",
         funcion_rh != "No trabajo en Rrhh",
         funcion_rh != "Trabajo en Administración y Finanzas",
         funcion_rh != "Aaa",
         funcion_rh != "IT") %>% 
  mutate(sueldo_bruto = as.numeric(unlist(sueldo_bruto)),
         puesto = factor(puesto))


rh <- rh %>% 
  filter(puesto != "Juzgado Civil y Comercial",
         puesto != "Programador",
         puesto != "Cuidado",
         puesto != "Asesor",
         puesto != "Jefe de Proyecto") %>% 
  mutate(puesto = str_trim(puesto, side = "both"), # Elimina espacios vacĆ­os
         puesto = fct_collapse(puesto, "Gerente" = "Superintendente"),
         puesto = fct_collapse(puesto, "Director" = "Director ( escalafón municipal)"),
         puesto = fct_collapse(puesto, "HRBP" = c("Senior ConsultorĆ­a", "specialist", "especialista",
                                                  "Especialista en selección IT", "Recruiter")),
         puesto = fct_collapse(puesto, "Responsable" = c("Coordinación", "Coordinador de Payroll",
                                                         "Encargado", "Supervisor")),
         puesto = fct_collapse(puesto, "Administrativo" = c("Asistente", "Asistente RRHH", "Aux", 
                                                            "Capacitador", "Consultor Ejecutivo",
                                                            "consultor jr")),
         puesto = fct_collapse(puesto, "Analista" = c("Asesoramiento", "Consultor", "Generalista", 
                                                      "Reclutadora", "Selectora", "Senior"))) %>% 
  select(Marca.temporal:valoracion_gestion_empresa)

# Pasa los campos de lista a numƩricos
rh <- rh %>% 
  mutate(anios_en_empresa  = as.numeric(unlist(anios_en_empresa)),
         anios_en_puesto   = as.numeric(unlist(anios_en_puesto)),
         anios_experiencia = as.numeric(unlist(anios_experiencia)),
         ajuste_porcentaje = as.numeric(unlist(ajuste_porcentaje)))

# Modifica los registros
rh$contactos_linkedin[[150]] <- 800
rh$contactos_linkedin[[214]] <- 500
rh$contactos_linkedin[[222]] <- 1000
rh$contactos_linkedin[[269]] <- 500
rh$contactos_linkedin[[282]] <- 1000
rh$contactos_linkedin[[339]] <- 1000
rh$contactos_linkedin[[382]] <- 30000
rh$contactos_linkedin[[385]] <- 500
rh$contactos_linkedin[[398]] <- 5000
rh$contactos_linkedin[[445]] <- 500
rh$contactos_linkedin[[459]] <- 500
rh$contactos_linkedin[[595]] <- 500
rh$contactos_linkedin[[598]] <- 500

rh <- unnest(data = rh, cols = c(anios_en_empresa, anios_en_puesto, anios_experiencia,
                                 ajuste_porcentaje, contactos_linkedin), keep_empty = TRUE)

# Corregir orden de puestos y simplificar gƩnero

rh <- rh %>% 
  mutate(puesto = factor(puesto, levels = c("Pasante", "Administrativo", "Analista",
                                            "HRBP", "Responsable","Jefe",
                                            "Gerente", "Director")),
         genero = fct_recode(genero, "GƩnero Diverso" = "GƩnero diverso (gƩnero diverso / gƩnero fluido /otras minorƭas)"))

rh <- rh %>% 
  filter(nivel_formacion != "Secundario en curso") %>% 
  mutate(nivel_formacion = fct_collapse(nivel_formacion, "Universitario completo" = c("MaestrĆ­a abandonada"),
                                        "Secundario completo" = c("Terciario abandonado", "Terciario en curso", 
                                                                  "Universitario abandonado"),
                                        "MaestrĆ­a completa" = c("Doctorado en curso")))


# Comparación de sueldos en dólares
rh <- rh %>% 
  left_join(tipo_cambio, by = "pais") %>% 
  mutate(multiplicador = if_else(tipo_contratacion == "Part time", 1.5, 1),
         sueldo_ft = sueldo_bruto * multiplicador,    # Hace la equivalencia de un sueldo part time a full time
         sueldo_dolar = sueldo_ft/tipo_cambio,  # Convierto los sueldos a dólares
         cuenta = 1)

rtas_pais <- rh %>% 
  select(pais) %>% 
  distinct(pais) %>% 
  count() %>% 
  pull()

Motivaciones

Como en RRHH trabajamos con datos sensibles, es complejo conseguir datos para practicar cuando estƔs aprendiendo sobre People Analytics, especialmente la parte prƔctica. Por eso, e inspirados en la Encuesta de SysArmy, una comunidad de tecnologƭa, que entre otras cosas, organiza eventos como Nerdearla.

Por esta razón hicimos nuestra propia encuesta, relevando datos de profesionales que trabajan tanto bajo relación de dependencia como de manera freelance. El relevamiento de datos lo hicimos entre el 1° y el 31 de octubre de 2020.

Recibimos en total 762 respuestas de 14 paĆ­ses diferentes.

# Respuestas por paĆ­ses
paises <- kiwi %>% 
  select(pais) %>% 
  mutate(cuenta = 1) %>% 
  group_by(pais) %>% 
  summarise(Cuenta = sum(cuenta)) %>% 
  arrange(-Cuenta)

gt(paises) %>% 
  tab_header(title = "Cantidad de respuestas por paĆ­s") %>% 
  tab_source_note(source_note = fuente) %>% 
  cols_label(pais = "PaĆ­s")
Cantidad de respuestas por paĆ­s
PaĆ­s Cuenta
Argentina 683
Bolivia 15
Chile 13
Paraguay 12
MƩxico 9
Uruguay 9
PerĆŗ 8
Ecuador 3
Estados Unidos 2
PanamĆ” 2
Venezuela 2
Colombia 1
Costa Rica 1
Guatemala 1
Otro Europa 1
Fuente: Encuesta KIWI de Sueldos de RRHH para Latam


Del total de respuestas, 661 son de personas que trabajan en relación de dependencia en RRHH, y 88 trabajan de manera freelance.

kiwi %>% 
  select(trabajo) %>% 
  group_by(trabajo) %>% 
  count() %>% 
  ggplot(aes(x = n, y = trabajo)) +
  geom_col(fill = azul) +
  estilov +
  labs(title = "Respuestas por tipo de trabajador", 
       x = "", y = "", 
       caption = fuente)

La participación según el género entre trabajadores en relación de dependencia:

div <- rh %>% 
select(genero) %>% 
  mutate(genero = factor(genero, 
                         levels = c("Femenino", "Masculino", "GƩnero Diverso",
                                    "Prefiero no responder"))) %>% 
  group_by(genero) %>% 
  summarise (n = n()) %>% 
  mutate(freq = n/sum(n)) %>% 
  arrange(-n)

# Compute the cumulative percentages (top of each rectangle)
div$ymax <- cumsum(div$freq)

# Compute the bottom of each rectangle
div$ymin <- c(0, head(div$ymax, n=-1))

# Compute label position
div$labelPosition <- (div$ymax + div$ymin) / 2

# Compute a good label
div$label <- paste0(div$genero, "\n Cant: ", div$n)

# Make the plot
ggplot(div, aes(ymax=ymax, ymin=ymin, xmax=4, xmin=3, fill=genero)) +
  geom_rect() +
  coord_polar(theta="y") + # Try to remove that to understand how the chart is built initially
  xlim(c(2, 4)) +# Try to remove that to see how to make a pie chart
  scale_fill_manual(values = c("#8624F5",  "#1FC3AA", "#FFD129","#75838F")) +
  theme_void() +
  theme(legend.position = "right",
        panel.background = element_blank(),
        text = element_text(family = "Roboto")) +
  labs(title = "Cantidad de respuestas según género",
       fill = "GƩnero", 
       caption = fuente)

AnƔlisis de remuneraciones

Remuneraciones por paĆ­s

En esta sección nos dedicaremos a comparar los sueldos entre los países. En primer lugar, hay que resaltar que los resultados no son representativos de los países, sino que lo son de los datos recolectados.

Por otra parte, la baja cantidad de respuestas recolectaas de otros paƭses fuera de la Argentina, nos hace imposible, hacer un anƔlisis comparado representativo de los puestos. Sin embargo, hay algunos datos intresantes para analizar.

Primero, analicemos los sueldos de los trabajadores en relación de dependencia, de cuyos países hayamos recibido al menos 5 respuestas.

sueldos_dolar <- rh %>% 
  select(puesto, sueldo_dolar, pais, tipo_contratacion) %>% 
  filter(puesto != "Pasante", tipo_contratacion != "Pasante")

# Eliminamos los sueldos que estƔn dentro del rango entre los percentiles 5 y 95
numericos <- profiling_num(sueldos_dolar)
poda_p05 <- numericos[1,6]
poda_p95 <- numericos[1,10]

# Dado que los percentiles 5 y 95 estƔn en U$400 y 2689 respectivamente, 
# podamos todo lo que estƩ fuera de ese rango

media_pais <- sueldos_dolar %>% 
  filter(pais %in% c("Argentina", "Bolivia", "Chile", "Paraguay", "Uruguay", "PerĆŗ"),
         between(sueldo_dolar,poda_p05,poda_p95)) %>% 
  group_by(pais) %>% 
  summarise(sueldop = list(mean_se(sueldo_dolar))) %>% 
  unnest(cols = c(sueldop)) 
 
sueldo_dolar_pais <- rh %>% 
  select(pais, sueldo_dolar) %>% 
  filter(between(sueldo_dolar, poda_p05, poda_p95),
         pais %in% c("Argentina", "Bolivia", "Chile", "Paraguay", "Uruguay", "PerĆŗ"))
  
# GrƔfico
ggplot(media_pais, aes(x = reorder(pais, -y), y =  y))+
  geom_col(fill = "#344D7E", alpha = 0.85) +
  geom_errorbar(aes(ymin = ymin,ymax = ymax), position = "dodge", color = "#75838F")+
  geom_point(data = sueldo_dolar_pais, aes(x = pais, y = sueldo_dolar), 
             alpha = 0.3, size = 2, color = "#75838F")+
  geom_text(aes(label = round(x=y, 0), vjust = 1.5, fontface = "bold"),size = 4, color = "white")+
  eje_y_n +
  labs(title = "Mediana salarial por paĆ­s",
       subtitle = "Sueldos de RRHH en U$S",
       caption = "Fuente: Encuesta KIWI de Sueldos de RRHH para Latam \n Paƭses con 5 respuestas o mƔs",
       x = "", y = "") + 
  estilo

AnƔlisis de sueldos por puestos en LatinoamƩrica

rh %>% 
  select(puesto, sueldo_dolar) %>% 
  filter(puesto != "Pasante") %>% 
  group_by(puesto) %>% 
  summarise(mediana_salarial = median(sueldo_dolar)) %>% 
  ggplot(aes(x = mediana_salarial, y = puesto)) +
  geom_col(fill = azul) +
  estilov +
  labs(title = "Mediana salarial por puesto", 
       subtitle = "Sueldos de RRHH en U$S", 
       x = "", y = "", 
       caption = fuente) +
  eje_x_n

La razón por la cual la mediana salarial de las personas en puesto de Dirección es menor a la de las personas en puestos de Gerente se explica por el tamaño de la muestra y las respuestas recibidas. En la tabla a continuación incorpora la cantidad de respuestas recibidas para cada uno de estas posiciones.

gt(rh %>% 
     select(puesto, sueldo_dolar) %>% 
     filter(puesto != "Pasante") %>% 
     mutate(puesto = factor(puesto, levels = c("Director", "Gerente", "Jefe", 
                                       "Responsable", "HRBP", "Analista", 
                                       "Administrativo"))) %>% 
     group_by(puesto) %>% 
     summarise(mediana_salarial = median(sueldo_dolar), 
               cant = n())
     ) %>% 
  tab_header(title = "Mediana salarial por puestos", 
             subtitle = "Sueldos en U$D") %>% 
  tab_source_note(source_note = fuente) %>% 
   fmt_currency(columns =  "mediana_salarial", decimals = 0,
               sep_mark = ".", dec_mark = ",") %>% 
  cols_label(puesto = "Posición",
             mediana_salarial = "Mediana Sueldo",
             cant = "Respuestas") 
Mediana salarial por puestos
Sueldos en U$D
Posición Mediana Sueldo Respuestas
Director $1.711 16
Gerente $2.217 55
Jefe $1.359 89
Responsable $894 145
HRBP $1.013 63
Analista $775 237
Administrativo $536 51
Fuente: Encuesta KIWI de Sueldos de RRHH para Latam

Sueldos segĆŗn el origen del capital

Si dividimos los grÔficos según el Origen del Capital, podemos apreciar que en líneas generales, la mediana salarial en empresas multinaciones es mayor que en las empresas nacionales.

rh %>% 
  select(origen_capital, puesto, sueldo_dolar) %>% 
  filter(puesto != "Pasante", 
         between(sueldo_dolar, poda_p05, poda_p95)) %>% 
  group_by(puesto, origen_capital) %>% 
  summarise(mediana_salarial = median(sueldo_dolar)) %>% 
  ggplot(aes(x = mediana_salarial, y = puesto, fill = origen_capital)) +
  geom_col() +
  geom_text(aes(label = round(x=mediana_salarial, 0), hjust = 1.2, fontface = "bold"),size = 3, color = "white") +
  scale_fill_manual(values = c(verde, azul)) +
  estilov +
  eje_x_n +
  facet_wrap(~origen_capital) +
  labs(title = "Mediana salarial por puesto segĆŗn origen del capital", 
       subtitle = "Sueldos de RRHH en U$S", 
       x = "", y = "", fill = "", 
       caption = fuente) +
  theme(legend.position = "bottom")

Veamos estos datos de otra manera:

library(CGPfunctions)

slope_df <- rh %>% 
  select(puesto, sueldo_dolar, origen_capital) %>% 
  filter(puesto != "Director", 
         between(sueldo_dolar, poda_p05, poda_p95)) %>% 
  group_by(puesto, origen_capital) %>% 
  summarise(mediana_salarial = round(median(sueldo_dolar)))

newggslopegraph(dataframe = slope_df,
                Times = origen_capital,
                Measurement = mediana_salarial,
                Grouping = puesto,
                Title = "Diferencias entre sueldos de RRHH en empresas nacionales y multinacionales",
                SubTitle = "Mediana Salarial. Sueldos en U$S",
                Caption = fuente, WiderLabels = T
                
                )

Para el anƔlisis de los rubros de la empresa, vamos a filtrar los 5 rubros que tienen mƔs respuestas. TambiƩn eliminaremos del anƔlisis el puesto de Director porque no se encuentra presente en todos los rubros.

top_5_rubros <- rh %>% 
  select(rubro) %>% 
  group_by(rubro) %>% 
  count(sort = TRUE) %>%
  filter(rubro != "Otros", n > 30) %>% 
  pull(var = rubro)


rh %>% 
  select(rubro, origen_capital, puesto, sueldo_dolar) %>% 
  filter(puesto != "Pasante", puesto != "Director",
         between(sueldo_dolar, poda_p05, poda_p95),
         rubro %in% top_5_rubros) %>% 
  group_by(rubro, puesto, origen_capital) %>% 
  summarise(mediana_salarial = median(sueldo_dolar)) %>% 
  ggplot(aes(x = mediana_salarial, y = puesto, fill = origen_capital)) +
  geom_col() +
  geom_text(aes(label = round(x=mediana_salarial, 0), hjust = 1.2, fontface = "bold"),size = 3, color = "white") +
  scale_fill_manual(values = c(verde, azul)) +
  estilo +
  eje_x_n +
  facet_grid(rubro~origen_capital) +
  labs(title = "Mediana salarial por puesto segĆŗn origen del capital", 
       subtitle = "Sueldos de RRHH en U$S", 
       x = "", y = "", fill = "", 
       caption = fuente) +
  theme(legend.position = "bottom")

rm(top_5_rubros)

Para ver las medianas salariales en dólares por rubros, puedes ver esta tabla.

datatable(
  rh %>% 
    select(rubro, sueldo_dolar) %>% 
    group_by(rubro) %>% 
    summarise(mediana_salarial = round(median(sueldo_dolar)),
              Respuestas = n()) %>% 
    arrange(-mediana_salarial),
  colnames = c("Rubro", "Mediana Salarial", "Respuestas"),
  caption = "Mediana salarial por rubro. En U$S"
)

Sueldos Argentina

Teniendo en cuenta que la cantidad mayoritaria de respuestas corresponde a personas de Argentina, vamos a realizar un anƔlisis detallado de los sueldos en este paƭs.

Como primeros pasos, vamos a filtrar los datos correspondientes a Argentina, y luego filtramos los sueldos que estƩn entre los percentiles 5 y 95, para eliminar valores espurios o extremos que ensucien el anƔlisis.

TambiƩn eliminamos el puesto de Director del anƔlisis y las respuestas con GƩnero diverso por la baja cantidad de respuestas.

Otra conversión que hicimos fue pasar los sueldos de las personas que trabajan part-time a una equivalencia full-time multiplicando por 1.5 el sueldo completado en la encuesta.

En esta instancia, tambiƩn simplificamos los nombres de algunos rubros para mejorar las visualizaciones de los resultados.

rh_ar <- rh %>% 
  filter(pais == "Argentina")


# Poda de sueldos entre percentiles 5 y 95
numericos2 <- rh_ar %>% 
  select_if(is.numeric) %>% 
  profiling_num()

p_05 <- numericos2[8,6]
p_95 <-numericos2[8,10]

rh_ar <- rh_ar %>% 
  filter(between(sueldo_bruto, p_05, p_95),
         puesto != "Director", puesto != "Pasante",
         genero != "GƩnero Diverso",
         anios_experiencia < 50) %>% 
  mutate(rubro = fct_recode(rubro, "Servicios financieros" = "Servicios financieros; seguros",
                             "Transporte" = "Transporte (incluyendo aviación civil; ferrocarriles por carretera)",
                            "Ind. Automotriz y Autopartistas" = "Terminales automotrices, fƔbricas autopartistas, y afines",
                            "Tecnología" = "Tecnologías de Información, Sistemas, y afines",
                            "Ind. Petrolera" = "Petróleo y producción de gas; refinación de petróleo"),
         multiplicador = if_else(tipo_contratacion == "Part time", 1.5, 1),
         sueldo_ft = sueldo_bruto * multiplicador)

Distribución de sueldos por puesto

En el siguiente grÔfico podemos ver la distribución de los sueldos por cada uno de los puestos. En los boxplots podemos ver:

  • Primer cuartil: La parte inferior de la caja.

  • Mediana: La lĆ­nea gruesa dentro de cada rectĆ”ngulo.

  • Tercer cuartil: La parte superior de la caja

  • Outliers: son los valores extremos identificados con puntos.

rh_ar %>% 
  ggplot(aes(x = puesto, y = sueldo_ft, fill = genero)) +
  geom_boxplot() +
  scale_fill_manual(values = genero) +
  eje_y_n +
  estiloh +
  labs(title = "Distribución de sueldos por género",
       subtitle = "Datos de Argentina - en AR$",
       x = "", y = "", fill = "GƩnero",
       caption = fuente) +
  theme(panel.grid.minor.y = element_line(color = "#AEB6BF"))

Hay varias cosas interesantes para analizar:

Si miramos las medianas de los puestos, en la mayorƭa de los puestos hay una paridad relativa, como por ejemplo en HRBP, Jefe y Gerentes. Tampoco hay mucha diferencia en la mediana de los Administrativos. En las posiciones de Analista, y Responsable los varones tienen una mediana salarial un poco mƔs alta.

Pero lo mƔs interesante son las distribuciones de los sueldos. Miremos por ejemplo los Jefes. La mediana es prƔcticamente la misma, pero el tamaƱo de la parte inferior de la caja es mucho mƔs amplia en el caso de las mujeres, mientras que la parte superior de la caja es mƔs amplia en el caso de los varones.

Esto nos da la pauta que si bien el valor que divide a la mitad la muestra de hombres y mujeres (la mediana) es muy parejo, el rango de los sueldos de las Jefas llega a valores mÔs bajos lo que implica que el piso es mÔs bajo para mujeres que para hombres. Mientras que de la mediana hacia arriba es mÔs amplia en el caso de los hombres en comparación con las mujeres.

En el único puesto que hay una distribución similar entre ambos géneros es en el caso de los HRBP, pero en el resto de los casos vemos que la asimetría que describimos anteriormente se repite.

Podemos visualizar el gap salarial en este grƔfico:

gap_salarial <- rh_ar %>% 
  select(genero, puesto, sueldo_ft)


gap_salarial <- gap_salarial %>% 
  filter(!is.na(puesto)) %>% 
  mutate(cuenta = 1) 


brecha <- gap_salarial %>% 
  filter(genero %in% c("Femenino", "Masculino"), 
         puesto %in% c("Director", "Gerente","Jefe", "HRBP","Responsable", "Analista", "Administrativo")) %>% 
  mutate(puesto = factor(puesto, levels = c("Administrativo","Analista", 
                                            "HRBP", "Responsable", "Jefe",
                                            "Gerente","Director" ))) %>% 
  group_by(genero, puesto) %>% 
  summarise(media_salarial = mean(sueldo_ft))



brecha_graf <- brecha %>% 
  pivot_wider(., names_from = genero, values_from = media_salarial) %>% 
  mutate(brecha = percent((Masculino-Femenino)/Masculino, 1),
         x = (Masculino + Femenino)/2)

ggplot(brecha_graf, 
       aes(x = Femenino, xend = Masculino, y = puesto, 
           group = puesto, label = brecha)) +
  geom_dumbbell(color = "#808080",
                size_x = 3, size_xend = 3,
                colour_x = colores[1],
                colour_xend = colores[2]) +
  geom_text(data = brecha_graf, 
            aes(x, puesto, label = brecha), nudge_y = .2) +
  labs(title = "Brecha salarial por puestos de RRHH",
       subtitle = "Sueldos promedios en Argentina",
       x = "",
       y = NULL, 
       caption = fuente) +
  eje_x_n +
  scale_color_manual(values = colores) +
  theme_minimal()+
  theme(plot.background = element_rect(fill = "#fbfcfc"),
        text = element_text(family = "Roboto"))

Veamos el sueldo promedio en cada uno de los rubros.

AnƔlisis por rubros

En el grÔfico a continuación podemos ver los sueldos promedios por rubro, teniendo en cuenta a los rubros con mÔs de 12 respuestas.

rubro_ar <- rh_ar %>% 
  select(rubro, sueldo_ft) %>% 
  group_by(rubro) %>% 
  summarise(media_sueldo = mean(sueldo_ft),
            respuestas = n()) %>% 
  arrange(-respuestas)

top_rubros <- rubro_ar %>% 
  filter(rubro != "Otros", respuestas > 15) %>% 
  pull(rubro)

rubro_ar %>% 
  filter(respuestas > 12) %>% 
  ggplot(aes(x = media_sueldo, y = reorder(rubro, media_sueldo))) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=media_sueldo, 0), hjust = 1.5),size = 3, color = "white") +
  labs(title = "Promedio salarial por rubro",
       subtitle = "Datos de Argentina - en AR$",
       x = "", y = "",
       caption = fuente) +
  estilov +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

Ahora comparemos los sueldos por rubros y gƩneros. Aquƭ podremos apreciar las diferencias entre los sueldos promedios de los hombres y mujeres en cada rubro.

rh_ar %>% 
  filter(rubro %in% top_rubros) %>% 
  select(rubro, sueldo_ft, genero) %>% 
  group_by(rubro, genero) %>% 
  summarise(media_sueldo = mean(sueldo_ft),
            respuestas = n()) %>% 
  arrange(-respuestas) %>% 
  ggplot(aes(x = media_sueldo, y = reorder(rubro, media_sueldo), fill = genero)) +
  geom_col(position = "dodge") +
  geom_text(aes(label = round(x=media_sueldo,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  scale_fill_manual(values = genero) +
  labs(title = "Promedio salarial por rubro y gƩnero",
       subtitle = "Datos de Argentina - en AR$",
       x = "", y = "", fill = "GƩnero",
       caption = fuente) +
  eje_x_n +
  estilov +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

Por último, analicemos los sueldos de los 6 rubros con mayor cantidad de respuestas, y visualicemos las distribuciones de los sueldos por puesto y género. En este grÔfico podemos ver los cuartiles delimitando las zonas sombreadas, y la mediana con el punto gris. Los puntos violetas y verdes representan a las mujeres y los hombres respectivamente en cada uno de los puestos.

library(ggeconodist)

rh_ar %>% 
  filter(genero != "GƩnero Diverso",
         puesto != "Director",
         rubro %in% c("TecnologĆ­a", "Servicios de salud", "Comercio",
                      "Alimentación; bebidas; tabaco",
                      "Servicios de consultoría", "Construcción"))  %>% 
  ggplot(aes(x = puesto, y = sueldo_bruto)) +
  geom_econodist(width = 0.5) +
  geom_point(aes(y = sueldo_bruto, color = genero), alpha = 0.3,
             position = position_jitter(width = 0.25)) +
  scale_color_manual(values = genero) +
  eje_y_n +
  coord_flip() +
  facet_wrap(~rubro, ncol = 2) +
  estilov +
  labs(title = "Distribución salarial por puesto y rubro",
       subtitle = "Datos de Argentina - en AR$",
       x = "", y = "", color = "GƩnero",
       caption = fuente)

Relaciones con Sueldo Bruto

En esta sección del anÔlisis buscamos identificar cuÔles son los factores que influyen en los ingresos (independientemente de la posición), así que empezamos a explorar los datos.

La primera pregunta que nos hicimos fue si los años de trayectoria influyen en el sueldo. Nuestra hipótesis es que a mayor cantidad de años de experiencia, mayor iba a ser el ingreso.

Lo que vamos a ver en el siguiente grÔfico de dispersión, es en el eje horizontal, los años de experiencia, y en el eje vertical, el sueldo bruto expresado en pesos argentinos. Luego, vamos a graficar una recta, que nos va a indicar la fuerza de esa relación.

Relación entre años de experiencia y sueldo bruto

lm_rh <- lm(sueldo_ft ~ anios_experiencia, data = rh_ar)

lm_hr_results <- summary(lm_rh)

lm_rh_r2 <- round(lm_hr_results[["r.squared"]],3)

ggplot(rh_ar, aes(x=anios_experiencia, y = sueldo_ft)) +
  geom_point(color = "#1FC3AA", alpha = 0.4, size = 2) + 
  geom_smooth(method = "lm") +
  theme_minimal() +
  theme(text = element_text(family = "Roboto")) +
  labs(title = "Relación entre sueldo y años de experiencia",
       x = "AƱos de Experiencia",
       y = "Sueldo bruto (AR$)", 
       caption = fuente) +
  eje_y_n +
  geom_text(aes(x=-Inf, y=Inf, hjust=0, vjust=1, label= paste0("R2 = ", lm_rh_r2))) 

En el grÔfico podemos apreciar una recta que va creciendo efectivamente: a medida que nos movemos mÔs hacia la derecha, la recta va subiendo. Pero el \(R^2\) = 0.179 nos indica cuÔnto explica los años de experiencia sobre el sueldo bruto, o dicho de otra manera, en qué medida influye la variable x (años de experiencia), sobre la variable y (sueldo bruto). Una definición mÔs precisa de este valor conocido como Coeficiente de Determinación es la proporción de la varianza total de la variable explicada por la regresión.

Este valor puede estar entre 0 y 1, mientras mÔs cerca de 0 estÔ menor es la relación, y mientras mÔs cerca de 1 esté el resultado, indica que la regresión explica la variabilidad de la variable de respuesta. Es por eso que este \(R^2\) = 0.179 nos indica que los años de experiencia no tienen mucha influencia en los sueldos.

Relación entre años de experiencia y sueldo bruto por puesto.

Dado que en el grÔfico anterior tenemos mezclados los sueldos de administrativos, analistas, jefes y gerentes, decidimos analizar la relación entre los años de experiencia y el sueldo bruto por cada uno de los puestos por separado.

library(ggpmisc)

mi.formula <- y ~ x

ggplot(rh_ar, aes(x=anios_experiencia, y = sueldo_ft)) +
  geom_point(color = "#1FC3AA", alpha = 0.4, size = 2) + 
  geom_smooth(method = "lm", formula = mi.formula, se = FALSE) +
  theme_minimal() +
  theme(text = element_text(family = "Roboto")) +
  labs(title = "Relación entre sueldo y años de experiencia",
       x = "AƱos de Experiencia",
       y = "", 
       caption = fuente) +
  eje_y_n +
  stat_poly_eq(formula = mi.formula, 
               aes(label = paste(..rr.label.., sep = "~~~")), 
               parse = TRUE) +
  facet_wrap(~puesto)

Como podemos apreciar en los \(R^2\) de cada grƔfico. Los aƱos de trayectoria influyen muy poco en los sueldos de cada uno de los puestos.

Ahora bien, la pregunta es, ¿cuÔl es la variable que mÔs influye en el sueldo en Recursos Humanos?. Tristemente, la respuesta no sorprende.

ggplot(rh_ar, aes(x = genero, y = sueldo_ft, fill = genero)) +
  geom_boxplot() +
  eje_y_n +
  scale_fill_manual(values = colores) +
  estiloh +
  labs(title = "Distribución salarial por género",
       x = "", y = "",
       fill = "GƩnero", 
       caption = fuente)

Educación

En esta sección queremos indagar si hay relación entre la formación y la remuneración, y si impacta también el tipo de universidad, pública o privada, en la remuneración y posición. Primero veamos entre los distintos países como se distribuye la muestra entre profesionales provenientes de universidades públicas y privadas.

Dado que tenemos relativamente pocas respuestas de otros países que no sean Argentina, no podemos sacar ninguna conclusión seria, sólo mencionar que en Argentina, hay una virtual paridad entre los estudiantes y graduados de universidades públicas y privadas. Posteriormente analizaremos la situación por regiones dentro del país.

Las proporciones de respuestas segĆŗn al tipo de universidad que asistieron los participantes de la encuesta es la siguiente:

rh %>% 
  select(pais, tipo_universidad) %>% 
  ggplot(aes(y = pais, fill = tipo_universidad)) +
           geom_bar(position = "fill") + 
  scale_fill_manual(values = c(gris, verde, azul)) +
  labs(title = "Distribución de respuestas por tipo de universidad por país",
       caption = fuente, 
       x = "", y = "") +
  estilo +
  theme(legend.position = "none")


educ <- rh %>% 
  select(tipo_universidad) %>%  
  group_by(tipo_universidad) %>% 
  summarise (n = n()) %>% 
  mutate(freq = n/sum(n)) %>% 
  arrange(-n)

# Compute the cumulative percentages (top of each rectangle)
educ$ymax <- cumsum(educ$freq)

# Compute the bottom of each rectangle
educ$ymin <- c(0, head(educ$ymax, n=-1))

# Compute label position
educ$labelPosition <- (educ$ymax + educ$ymin) / 2

# Compute a good label
educ$label <- paste0(educ$tipo_universidad, "\n Cant: ", educ$n)

# Make the plot
ggplot(educ, aes(ymax=ymax, ymin=ymin, xmax=4, xmin=3, fill=tipo_universidad)) +
  geom_rect() +
  coord_polar(theta="y") + # Try to remove that to understand how the chart is built initially
  xlim(c(2, 4)) +# Try to remove that to see how to make a pie chart
  scale_fill_manual(values = c(gris, verde, azul)) +
  theme_void() +
  theme(legend.position = "right",
        panel.background = element_blank(),
        text = element_text(family = "Roboto")) +
  labs(title = "Tipo de Universidad",
       fill = "Tipo de Universidad", 
       caption = fuente) +
  theme(legend.position = "left")

Las principales carreras de las personas que respondieron son:

carreras <- rh %>% 
  select(nivel_formacion, carrera_grado, tipo_universidad, trabajo, 
         sueldo_bruto, puesto, funcion_rh, pais, genero) %>% 
  mutate(carrera_grado = factor(carrera_grado))

carreras <- carreras %>% 
  mutate(carrera_grado = fct_collapse(carrera_grado, 
                                      "AbogacĆ­a" = c("AbogacĆ­a, EscribanĆ­a, Lic en RRHH")),
         carrera_grado = fct_collapse(carrera_grado, 
                                      "Administración de Empresas" = c("Lic en Administracion",
                                                                       "Administración y sistemas", "Lic Administracion - Contador Publico - Abogado en curso")),
         carrera_grado = fct_collapse(carrera_grado, 
                                      "Contador PĆŗblico" = c("Economia", "EconomĆ­a", "Contador PĆŗblico/Lic. En Letras", "Economia y RR.HH")),
         carrera_grado = fct_collapse(carrera_grado, 
                                      "Comunicación Social" = c("Caomunicacion social me especialice en RRHH",  "Comunicación","Comunicación social", "Lic. en Ciencias de la Comunicación")), 
         carrera_grado = fct_collapse(carrera_grado, 
                                      "RRHH / RRLL / RRTT" = c("EstudiƩ en la Universidad Analista en Recursos Humanos", "RRHH&Coaching ontologico profesional.", "Graduada en lic rrhh y abogacia")),
         carrera_grado = fct_collapse(carrera_grado, "Ingenierías" = c("Ing en sistemas", "Ing. Financiera", "Ingeniería Comercial", "ING.sistemas",  "Ingenieria Electrónica","Ingeniería Industrial")),
         carrera_grado = fct_collapse(carrera_grado, 
                                      "Psicología" = c("Psicologia","Psicología Industrial", "Psicología social",   "Psicología Social / Lic. en Dirección de las Organizaciones")),
         carrera_grado = fct_collapse(carrera_grado, "No estudiƩ en la Universidad" = "Ninguna"),
         carrera_grado = fct_lump(carrera_grado, 
                                  prop = 0.02, 
                                  other_level = "Otros"),
         carrera_grado = factor(carrera_grado,
                                levels = c("RRHH / RRLL / RRTT", "Psicología", "Administración de Empresas", "Contador Público", "Otros")))


ggplot(carreras, aes(x = carrera_grado)) + 
  geom_bar(position = "dodge", fill = azul) +
  theme(axis.text.x = element_text(angle = 90)) + 
  labs(x="",y="") +
  estiloh +
  labs(title = "Principales carreras estudiadas",
       subtitle = "Trabajadores en relación de dependencia",
       caption = fuente)

Dada la cantidad de respuestas por país, el anÔlisis que haremos desde aquí en adelante sólo serÔ para Argentina.

AnÔlisis de educación y puestos para Argentina

Luego, podemos analizar en qué tipo de universidad estudiaron las personas que respondieron la encuesta, según el puesto actual que ocupan.

recorte_educacion <- rh %>%
  filter(pais == "Argentina") %>% 
  select(nivel_formacion, carrera_grado,
         tipo_universidad, trabajo, sueldo_bruto, puesto, funcion_rh, pais, genero)

ggplot(recorte_educacion, (aes(x = puesto, fill = tipo_universidad))) + #Tipo de universidad y cargo
  geom_bar(position = "dodge") +
  theme(axis.text.x = element_text(angle = 90)) + 
  labs(x="",y="") +
    estilov +
  scale_fill_manual(values = c(gris, verde, azul)) +
  coord_flip() +
  labs(title = "Cantidad de respuestas segĆŗn puesto y universidad",
       subtitle = "Sólo respuestas de Argentina",
       x = "", fill = "Tipo de Universidad",
       caption = fuente)

Reiteremos el anÔlisis pero únicamente para las carreras relacionadas con Recursos Humanos y Relaciones del Trabajo.

recorte_educacion %>%
  filter(carrera_grado == "RRHH / RRLL / RRTT") %>% 
  ggplot(aes(x = puesto, fill = tipo_universidad)) + #Tipo de universidad y cargo
  geom_bar(position = "dodge") +
  theme(axis.text.x = element_text(angle = 90)) + 
  labs(x="",y="") +
    estilov +
  scale_fill_manual(values = c(gris, verde, azul)) +
  coord_flip() +
  labs(title = "Cantidad de respuestas segĆŗn puesto y universidad",
       subtitle = "Sólo respuestas de Argentina - Carreras de RH",
       x = "", fill = "Tipo de Universidad",
       caption = fuente)

Podemos apreciar que a partir de los puestos de jefatura, hay mayor presencia de graduados provenientes de universidades privadas.

En Argentina, podemos ver la siguiente distribución por género y nivel educativo.

ne_salario <- recorte_educacion 

ne_salario %>% 
  select(pais, nivel_formacion, genero, puesto) %>%
  filter(genero != "GƩnero Diverso") %>%
  mutate(nivel_formacion = factor(nivel_formacion,
                                  levels = c("Secundario completo", "Terciario completo",
                                             "Universitario en curso", "Universitario completo",
                                             "MaestrĆ­a en curso","MaestrĆ­a completa"))) %>% 
  group_by(nivel_formacion) %>% 
  ggplot(aes (y= nivel_formacion, fill = genero)) + 
  geom_bar(position = "fill") +
  theme(axis.text.x = element_text(angle = 90)) + 
  labs(x="",y="") +
  scale_fill_manual(values = colores) +
  estilo +
  theme(legend.position = "top") +
  labs(title = "MƔximo nivel educativo alcanzado por gƩnero",
       subtitle = "Distribución por frecuencias absolutas",
       caption = fuente, 
       fill = "GƩnero")

En términos absolutos, las mujeres graduadas representan cerca del 70% de la muestra. Analicemos estos datos en términos relativos. PrÔcticamente el patrón de nivel educativo entre hombres y mujeres es idéntico.

ne_fem <- ne_salario %>% 
  filter(genero == "Femenino") %>% 
  group_by(genero, nivel_formacion) %>% 
  mutate(nivel_formacion = factor(nivel_formacion,
                                  levels = c("MaestrĆ­a completa", "MaestrĆ­a en curso",
                                             "Universitario completo", "Universitario en curso",
                                             "Terciario completo", "Secundario completo"))) %>% 
  group_by(nivel_formacion) %>% 
  summarise(n = n()) %>% 
  mutate(frecuencia = round(n/sum(n),2),
         genero = "Femenino") 

ne_mas <- ne_salario %>% 
  filter(genero == "Masculino") %>% 
  group_by(genero, nivel_formacion) %>% 
  mutate(nivel_formacion = factor(nivel_formacion,
                                  levels = c("MaestrĆ­a completa", "MaestrĆ­a en curso",
                                             "Universitario completo", "Universitario en curso",
                                             "Terciario completo", "Secundario completo"))) %>% 
  group_by(nivel_formacion) %>% 
  summarise(n = n()) %>% 
  mutate(frecuencia = round(n/sum(n),2),
         genero = "Masculino") 

ne_total <- rbind(ne_fem, ne_mas)

ggplot(ne_total, aes(x = nivel_formacion, y = frecuencia, fill = genero)) +
  geom_col() +
  theme(axis.text.x = element_text(angle = 90), 
        legend.position = "none") + 
  labs(x="",y="") +
  scale_fill_manual(values = colores) +
  facet_wrap(~genero, ncol = 2) +
  estiloh +
  labs(title = "Proporción de nivel educativo mÔximo por género",
       x = "", y = "Proporción", 
       caption = fuente)

Ahora veamos como se distribuyen los puestos según el género y el nivel educativo.

ne_salario %>% 
  select(pais, nivel_formacion, genero, puesto) %>%
  filter(genero %in% c("Femenino", "Masculino"),
         puesto != "Pasante", puesto != "Director") %>%
  mutate(nivel_formacion = factor(nivel_formacion,
                                  levels = c("Secundario completo", "Terciario completo",
                                             "Universitario en curso", "Universitario completo",
                                             "MaestrĆ­a en curso","MaestrĆ­a completa")),
         puesto = factor(puesto, 
                         levels = c("Director", "Gerente", "Jefe", "Responsable", "HRBP",
                                    "Analista", "Administrativo"))) %>% 
  group_by(nivel_formacion) %>% 
  ggplot(aes (y= nivel_formacion, fill = genero)) + 
  geom_bar(position = "fill") +
  theme(axis.text.x = element_text(angle = 90)) + 
  labs(x="",y="") +
  scale_fill_manual(values = colores) +
  estilo +
  theme(legend.position = "bottom") +
  labs(title = "Nivel educativo por puesto y gƩnero",
       subtitle = "Distribución por frecuencias absolutas",
       caption = fuente, 
       fill = "GƩnero") +
  facet_wrap(~puesto, ncol = 3)

Algunas conclusiones que podemos extraer del grƔfico anterior:

  • Hay una fuerte predominancia de mujeres en puestos de baja jerarquĆ­a.
  • En los puestos de Gerencia y de Jefatura hay mayor predominancia de varones, pero aĆŗn asĆ­ hay una paridad entre los distintos niveles educativos.
  • Posiciones altamente especializadas, como la de HRBP, requiere una formación universitaria.

Analicemos las proporciones de hombres y de mujeres en puesto de liderazgo.

div <- rh %>%
  filter(pais == "Argentina") %>% 
select(genero) %>% 
  mutate(genero = factor(genero, 
                         levels = c("Femenino", "Masculino", 
                                    "No binario", "Prefiero no responder"))) %>% 
  group_by(genero) %>% 
  summarise (n = n()) %>% 
  mutate(freq = n/sum(n)) %>% 
  arrange(-n)

lideres <- rh %>% 
  filter(pais == "Argentina") %>% 
 select(genero, puesto) %>% 
  mutate(genero = fct_recode(genero,
                             "No binario" = "GƩnero diverso (gƩnero diverso / gƩnero fluido /otras minorƭas)"))

# Propoción de líderes hombres y mujeres
lideres_genero <- lideres %>% 
  filter(genero %in% c("Masculino","Femenino")) %>% 
  group_by(genero) %>%
  mutate(gente_a_cargo = if_else(puesto %in% c("Responsable", "Jefe", "Gerente", 
                                               "Supervisor", "Director"),1,0)) %>%
  summarise(lider = sum(gente_a_cargo)) %>% 
  left_join(div) %>% 
  select(genero, lider, n) %>% 
  mutate(proporcion = percent(lider/n))

# Test de hipótesis para validar diferencias de resultados
# Hay que verificar si la proporción de líderes hombres es mayor que la proporción de líderes mujeres
# Creo un dataframe para analizar proporciones de hombres y de mujeres en puestos de liderazgo y de no-liderazgo
test_lider <- lideres_genero %>% 
  mutate(no_lider = n - lider) %>%        # Columna de no lĆ­deres
  select(genero, lider, no_lider) %>%     # selecciono columnas de interƩs
  pivot_longer(cols = c(lider, no_lider), # Hago un dataset largo para analizar despuƩs
               names_to = "es_lider", values_to = "conteo")

# Del total de respuestas me interesa sólo ver cuÔles son los hombres con puesto de liderazgo
test_lider$cat <- c(0,0,1,0)

# Extraigo el mu para decidir si la diferencia es significativa y pasarlo a la fórmula del test.
prop_mujer_lid <- pull(lideres_genero[1,2]/lideres_genero[1,3])

# Realizo el test de hipótesis.
# H0 = Las proporciones de lĆ­deres hombres y mujeres son iguales
# H1 = La proporción de hombres líderes es mayor que la proporción de mujeres líderes.
resultados_test <- broom::tidy(t.test(test_lider$cat, mu = prop_mujer_lid, alternative = "greater"))

valor_test <- if(resultados_test[1,3] > 0.05) {
  print("la diferencia es estadísticamente significativa, y la proporción de hombres en puestos de liderazgo es mayor que el de las mujeres")
  } else {
    print("la diferencia no es estadísticamente significativa, y la proporción de hombres no es estadísticamente mayor que el de las mujeres en puestos de liderazgo")
  }
# GrƔfico
lideres_genero %>% 
  mutate(porc_lider = lider/n, 
         porc_no_lider = 1 - porc_lider) %>% 
  pivot_longer(cols = c(porc_lider, porc_no_lider),
               names_to = "es_lider", 
               values_to = "valores") %>% 
  mutate(es_lider = factor(es_lider, 
                           levels = c("porc_no_lider", "porc_lider"), 
                           labels = c("No LĆ­der", "LĆ­der"))) %>% 
  ggplot(aes(x= genero, y = valores, fill = es_lider))+
  geom_col(position = "fill")+
  estilo +
  scale_fill_manual(values = c("#75838F", "#344D7E")) +
  labs(title = "Proporción de Líderes según género",
       x = "", y = "", fill = "", 
       caption = fuente)

De acuerdo a las respuestas recolectadas 2 de cada 3 participantes son mujeres.

Para los puestos de liderazgo consideramos las personas en los puestos de Director, Gerente, Jefe, y Responsable.

Del total de mujeres, 409 respuestas, 174 ocupan un puesto de liderazgo (42.5%).

Del total de hombres, 186 respuestas, 92 ocupan un puesto de liderazgo (49.5%).

Con un p-value igual a 0.733 podemos afirmar que la diferencia es estadísticamente significativa, y la proporción de hombres en puestos de liderazgo es mayor que el de las mujeres.

AnÔlisis de sueldos y educación en Argentina

En esta sección analizaremos los sueldos en comparación con los distintos niveles educativos.

A diferencia de otras secciones, en este caso compararemos la media salarial para poder observar los desvƭos estƔndar en los anƔlisis. En primer lugar analicemos cuƔl es el sueldo promedio de acuerdo a los distintos niveles educativos.

Primero veamos cuÔl es el sueldo promedio en pesos argentinos, según el nivel educativo.

estudios <- rh %>% 
  filter(pais == "Argentina") %>% 
  select(genero, nivel_formacion, sueldo_bruto)
    
  
est_ar  <- profiling_num(estudios)
es_p05 <- 29320
es_p95 <- 210000

rh %>% 
  filter(pais == "Argentina", 
         between(sueldo_bruto, es_p05, es_p95)) %>% 
    mutate(nivel_formacion = factor(nivel_formacion,
                                  levels = c("Secundario completo", "Terciario completo",
                                             "Universitario en curso", "Universitario completo",
                                             "MaestrĆ­a en curso","MaestrĆ­a completa"))) %>% 
  group_by(nivel_formacion) %>% 
  summarise(sueldo_promedio = mean(sueldo_bruto)) %>% 
  ggplot(aes(x = sueldo_promedio, y = nivel_formacion))+
  geom_col(fill = azul)+
  estilov +
  eje_x_n +
  labs(title = "Sueldo promedio por nivel de formación",
       subtitle = "En AR$",
       x="", y="", caption = fuente)

Ahora veamos quƩ pasa si incluimos en el anƔlisis el gƩnero para analizar los sueldos promedios y sus desvƭos estƔndar.

rh %>% 
  filter(pais == "Argentina", 
         between(sueldo_bruto, es_p05, es_p95)) %>% 
    mutate(nivel_formacion = factor(nivel_formacion,
                                  levels = c("Secundario completo", "Terciario completo",
                                             "Universitario en curso", "Universitario completo",
                                             "MaestrĆ­a en curso","MaestrĆ­a completa"))) %>% 
  group_by(nivel_formacion, genero) %>% 
  summarise(salarios = list(mean_se(sueldo_bruto))) %>% 
  unnest(salarios) %>% 
  ggplot(aes(x = nivel_formacion, y = y, fill = genero)) +
  geom_col(position = "dodge")+
  geom_errorbar(aes(ymin = ymin,ymax = ymax), position = "dodge")+
  coord_flip()+
  theme(legend.position = "bottom") +
  eje_y_n +
  estilov +
  scale_fill_manual(values = genero3) +
  labs(title = "Sueldo promedio y desvío estÔndard por nivel de formación y género",
       subtitle = "En AR$", 
       x = "", y = "", 
       caption = fuente, 
       fill = "GƩnero")

Sueldos por función

En esta sección nos proponemos analizar los sueldos según las distintas funciones de Recursos Humanos.

Para realizar este anƔlisis tuvimos que unificar varias respuestas y eliminar algunas que no correspondƭan al Ɣrea de RRHH para poder quedarnos con estas Ɣreas de anƔlisis.

Los sueldos promedios y la cantidad de respuestas que recibimos de cada función son los siguientes:

# Limpieza de funciones
# Elimino los que no son de RRHH
rh_ar <- rh_ar %>% 
  filter(funcion_rh != "No me desempeƱo en el Ɣrea de RRHH. Trabajo en el Ɣrea de Sistemas.",
         funcion_rh != "No trabajo en el Ɣrea")

# Unifico las funciones de RH
rh_ar <- rh_ar %>% 
  mutate(funcion_rh = str_trim(funcion_rh, side = "both"),
    funcion_rh = fct_collapse(funcion_rh, "Adm. de personal" = 
                                c("Administración de personal", "Administrativa en Ôrea", 
                                  "Asistente")),
    funcion_rh = fct_collapse(funcion_rh, "Generalista" = c("Generalista", "Al ser HRBP un poco de todo payroll, capacitacion, comunicacion interna,",
                                                            "Area integral de RH", "General","HRBP",
                                                            "La mayorĆ­a de los nombrados con iguales condiciones de importancia y prioridad",
                                                            "RRHH", "Todas las anteriores", "Todo", "Todo lo anterior", "Todos ellos", "Todos, los descriptos")),
    funcion_rh = fct_collapse(funcion_rh, "Capacitación y desarrollo" = c("Capacitación y desarrollo",
                                                                          "Capacitación y Desarrollo + Bienestar + RSE",
                                                                          "Desarrollo laboral: procesos Sofi, capacitacion, evaluación, desarrollo",
                                                                          "Onboarding, clima, cultura, liderazgo")),
    funcion_rh = fct_collapse(funcion_rh, "Payroll" = c("Payroll / Liquidación de sueldos",
                                                        "payroll y adminsitracion de personal")),
    funcion_rh = fct_collapse(funcion_rh, "DiseƱo organizacional" = "DiseƱo organizacional",
                              "Mejora continua proyectos de innovación"),
    funcion_rh = fct_lump(funcion_rh, 
                          n = 10, 
                          other_level = "Otras funciones"))

gt(
  rh_ar %>% 
    group_by(funcion_rh) %>% 
    summarise("Sueldo Promedio" = round(mean(sueldo_ft)),
              Respuestas = n()),
  ) %>% 
  tab_header(title = "Sueldo promedio por función",
             subtitle = "En AR$") %>% 
  cols_label(funcion_rh = "Función") %>% 
  fmt_currency(columns =  "Sueldo Promedio", decimals = 0,
               sep_mark = ".", dec_mark = ",")
Sueldo promedio por función
En AR$
Función Sueldo Promedio Respuestas
Adm. de personal $66.531 106
Generalista $90.379 204
Capacitación y desarrollo $74.490 32
Compensaciones y beneficios $100.533 9
Comunicación interna $65.113 9
DiseƱo organizacional $101.543 11
Payroll $76.330 56
People Analytics $105.221 13
Reclutamiento y selección $69.729 69
Relaciones laborales $101.301 11
Otras funciones $124.467 6
rh_ar %>% 
  group_by(funcion_rh) %>% 
  filter(funcion_rh != "Otras funciones") %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(y = fct_reorder(funcion_rh, sueldo_promedio), 
             x = sueldo_promedio)) +
  geom_col(fill = azul) +
  labs(title = "Sueldo promedio por función",
       subtitle = "En AR$",
       x = "", y = "",
       caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh != "Otras funciones") %>% 
  group_by(funcion_rh, puesto) %>% 
  summarise(sueldo_medio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = funcion_rh, y = sueldo_medio)) +
  geom_col(fill = azul) +
  eje_y_n +
  estiloh +
  facet_wrap(~puesto) +
  labs(title = "Sueldo promedio por puesto y función",
       subtitle = "En AR$", 
       x = "", y = "",
       caption = fuente) +
  theme(axis.text.x = element_text(angle = 90))

funciones_top <- rh_ar %>% 
  filter(funcion_rh %in% c("People Analytics", "DiseƱo organizacional",
                           "Relaciones laborales", "Compensaciones y beneficios")) %>% 
  summarise(promedio = mean(sueldo_ft)) %>% 
  pull()

funciones_bottom <- rh_ar %>% 
  filter(funcion_rh %in% c("Payroll", "Reclutamiento y selección", 
                           "Capacitación y desarrollo", "Comunicación interna",
                           "Adm. de personal")) %>% 
  summarise(promedio = mean(sueldo_ft)) %>% 
  pull()

porcentaje_gap <- percent(funciones_top / funciones_bottom - 1)

Si bien la cantidad de respuestas influye en el sueldo promedio como para determinar significativamente si algunas funciones se pagan mejor que otras, no llama la atención que las funciones de People Analytics, Diseño Organizacional y Compensaciones y Beneficios estén dentro de las funciones mejores pagas dentro de Recursos Humanos ya que requieren de mayor especialización, anÔlisis, y manejo de información confidencial.

Completa el podio la función de Relaciones Laborales. En este caso creemos que en un país altamente sindicalizado como Argentina, esta función cobra mucha relevancia dado que son los que se encargan de las negociaciones de paritarias salariales y acuerdos colectivos, y son responsables de resolver los conflictos dentro de las organizaciones.

Si hacemos un promedio de los sueldos de las cuatro funciones con los sueldos mƔs altos, y luego hacemos lo mismo con el resto de las funciones mƔs bajas (exceptuando a los que estƔn en roles Generalistas), el gap salarial es de 46%, lo cual es llamativamente alto.

A continuación presentamos un anÔlisis mÔs detallado de los sueldos por funciones y puestos.

datatable(
  rh_ar %>% 
    group_by(funcion_rh, puesto) %>% 
    summarise("Sueldo Promedio" = round(mean(sueldo_ft))),
  colnames = c("Función", "Puesto", "Sueldo Promedio"),
  caption = "Sueldo promedio por función y puesto - En AR$"
)

En las siguientes secciones exploraremos un poco mÔs en detalle cada una de estas funciones. En función de la cantidad de respuestas recibidas para cada función, podremos profundizar un poco mÔs el anÔlisis, o bien hacer un anÔlisis superficial.

People Analytics

rh_ar <- rh_ar %>% 
  mutate(nivel_formacion = fct_relevel(nivel_formacion, c("MaestrĆ­a completa", 
                                                          "MaestrĆ­a en curso",
                                                          "Universitario completo",
                                                          "Universitario en curso",
                                                          "Terciario completo",
                                                          "Secundario completo")))

funcion_analisis <- "People Analytics"

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = funcion_rh, fill = genero))+
  geom_bar(position = "fill") +
  scale_fill_manual(values = colores) +
  estilo +
  labs(title = "Proporción de Género",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "GƩnero",
       caption = fuente)

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = sueldo_promedio, y = puesto)) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=sueldo_promedio,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "", 
       caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = puesto, fill = nivel_formacion)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = col4) +
  labs(title = "Nivel de formación por puesto",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "Nivel de Formación",
       caption = fuente) +
  estilo

DiseƱo Organizacional

funcion_analisis <- "DiseƱo organizacional"

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = funcion_rh, fill = genero))+
  geom_bar(position = "fill") +
  scale_fill_manual(values = c("#8624F5", "#1FC3AA","#FFD129")) +
  estilo +
  labs(title = "Proporción de Género",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "GƩnero",
       caption = fuente)

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = sueldo_promedio, y = puesto)) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=sueldo_promedio,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "", caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = puesto, fill = nivel_formacion)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = col4) +
  labs(title = "Nivel de formación por puesto",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "Nivel de Formación",
       caption = fuente) +
  estilo

Relaciones Laborales

funcion_analisis <- "Relaciones laborales"

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = funcion_rh, fill = genero))+
  geom_bar(position = "fill") +
  scale_fill_manual(values = colores) +
  estilo +
  labs(title = "Proporción de Género",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "GƩnero",
       caption = fuente)

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = sueldo_promedio, y = puesto)) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=sueldo_promedio,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = paste0(funcion_analisis, "- En AR$"),
       x = "", y = "", caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = puesto, fill = nivel_formacion)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = col6) +
  labs(title = "Nivel de formación por puesto",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "Nivel de Formación",
       caption = fuente) +
  estilo

Compensaciones y beneficios

funcion_analisis <- "Compensaciones y beneficios"

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = funcion_rh, fill = genero))+
  geom_bar(position = "fill") +
  scale_fill_manual(values = colores) +
  estilo +
  labs(title = "Proporción de Género",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "GƩnero",
       caption = fuente)

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = sueldo_promedio, y = puesto)) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=sueldo_promedio,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "", caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = puesto, fill = nivel_formacion)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = col4) +
  labs(title = "Nivel de formación por puesto",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "Nivel de Formación",
       caption = fuente) +
  estilo

Generalista

rh_ar <- rh_ar %>% 
  mutate(rango_ant_puesto = case_when(
    anios_en_puesto < 1 ~ "Menos de 1 aƱo",
    anios_en_puesto < 6 ~ "Entre 1 y 5 aƱos",
    anios_en_puesto < 11 ~ "Entre 6 y 10 aƱos",
    anios_en_puesto = T ~ "MƔs de 10 aƱos"),
    rango_ant_puesto = fct_relevel(rango_ant_puesto, c("Menos de 1 aƱo", "Entre 1 y 5 aƱos",
                                                       "Entre 6 y 10 aƱos", "MƔs de 10 aƱos")))

funcion_analisis <- "Generalista"

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = funcion_rh, fill = genero))+
  geom_bar(position = "fill") +
  scale_fill_manual(values = colores) +
  estilo +
  labs(title = "Proporción de Género",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "GƩnero",
       caption = fuente)

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = sueldo_promedio, y = puesto)) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=sueldo_promedio,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "", caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = puesto, fill = nivel_formacion)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = col6) +
  labs(title = "Nivel de formación por puesto",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "Nivel de Formación",
       caption = fuente) +
  estilo

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto, rango_ant_puesto) %>% 
  summarise(media_sueldo = mean(sueldo_ft)) %>% 
  ggplot(aes(x = rango_ant_puesto, y = media_sueldo)) +
  geom_col(fill = azul) +
  scale_x_discrete(guide = guide_axis(n.dodge = 2)) +
  facet_wrap(~puesto) +
  estiloh +
  eje_y_n +
  labs(title = "Sueldo promedio por puesto y antigüedad",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "",
       caption = fuente)

Payroll

funcion_analisis <- "Payroll"

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = funcion_rh, fill = genero))+
  geom_bar(position = "fill") +
  scale_fill_manual(values = colores) +
  estilo +
  labs(title = "Proporción de Género",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "GƩnero",
       caption = fuente)

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = sueldo_promedio, y = puesto)) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=sueldo_promedio,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "", caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = puesto, fill = nivel_formacion)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = col6) +
  labs(title = "Nivel de formación por puesto",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "Nivel de Formación",
       caption = fuente) +
  estilo

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto, rango_ant_puesto) %>% 
  summarise(media_sueldo = mean(sueldo_ft)) %>% 
  ggplot(aes(x = rango_ant_puesto, y = media_sueldo)) +
  geom_col(fill = azul) +
  scale_x_discrete(guide = guide_axis(n.dodge = 2)) +
  facet_wrap(~puesto) +
  estiloh +
  eje_y_n +
  labs(title = "Sueldo promedio por puesto y antigüedad",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "",
       caption = fuente)

Capacitación y Desarrollo

funcion_analisis <- "Capacitación y desarrollo"

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = funcion_rh, fill = genero))+
  geom_bar(position = "fill") +
  scale_fill_manual(values = colores) +
  estilo +
  labs(title = "Proporción de Género",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "GƩnero",
       caption = fuente)

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = sueldo_promedio, y = puesto)) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=sueldo_promedio,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "", caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = puesto, fill = nivel_formacion)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = col6) +
  labs(title = "Nivel de formación por puesto",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "Nivel de Formación",
       caption = fuente) +
  estilo

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto, rango_ant_puesto) %>% 
  summarise(media_sueldo = mean(sueldo_ft)) %>% 
  ggplot(aes(x = rango_ant_puesto, y = media_sueldo)) +
  geom_col(fill = azul) +
  scale_x_discrete(guide = guide_axis(n.dodge = 2)) +
  facet_wrap(~puesto) +
  estiloh +
  eje_y_n +
  labs(title = "Sueldo promedio por puesto y antigüedad",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "",
       caption = fuente)

Reclutamiento y Selección

funcion_analisis <- "Reclutamiento y selección"

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = funcion_rh, fill = genero))+
  geom_bar(position = "fill") +
  scale_fill_manual(values = colores) +
  estilo +
  labs(title = "Proporción de Género",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "GƩnero",
       caption = fuente)

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = sueldo_promedio, y = puesto)) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=sueldo_promedio,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "", caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = puesto, fill = nivel_formacion)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = col6) +
  labs(title = "Nivel de formación por puesto",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "Nivel de Formación",
       caption = fuente) +
  estilo

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto, rango_ant_puesto) %>% 
  summarise(media_sueldo = mean(sueldo_ft)) %>% 
  ggplot(aes(x = rango_ant_puesto, y = media_sueldo)) +
  geom_col(fill = azul) +
  scale_x_discrete(guide = guide_axis(n.dodge = 2)) +
  facet_wrap(~puesto) +
  estiloh +
  eje_y_n +
  labs(title = "Sueldo promedio por puesto y antigüedad",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "",
       caption = fuente)

Administración de Personal

funcion_analisis <- "Adm. de personal"

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = funcion_rh, fill = genero))+
  geom_bar(position = "fill") +
  scale_fill_manual(values = colores) +
  estilo +
  labs(title = "Proporción de Género",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "GƩnero",
       caption = fuente)

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = sueldo_promedio, y = puesto)) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=sueldo_promedio,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "", caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = puesto, fill = nivel_formacion)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = col6) +
  labs(title = "Nivel de formación por puesto",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "Nivel de Formación",
       caption = fuente) +
  estilo

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto, rango_ant_puesto) %>% 
  summarise(media_sueldo = mean(sueldo_ft)) %>% 
  ggplot(aes(x = rango_ant_puesto, y = media_sueldo)) +
  geom_col(fill = azul) +
  scale_x_discrete(guide = guide_axis(n.dodge = 2)) +
  facet_wrap(~puesto) +
  estiloh +
  eje_y_n +
  labs(title = "Sueldo promedio por puesto y antigüedad",
       subtitle = paste0(funcion_analisis, " - En AR$"),
       x = "", y = "",
       caption = fuente)

Comunicación Interna

funcion_analisis <- "Comunicación interna"

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = funcion_rh, fill = genero))+
  geom_bar(position = "fill") +
  scale_fill_manual(values = colores) +
  estilo +
  labs(title = "Proporción de Género",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "GƩnero",
       caption = fuente)

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  group_by(puesto) %>% 
  summarise(sueldo_promedio = mean(sueldo_ft)) %>% 
  ggplot(aes(x = sueldo_promedio, y = puesto)) +
  geom_col(fill = azul) +
  geom_text(aes(label = round(x=sueldo_promedio,0), hjust = 1.4, vjust = 0.3),
            size = 3, color = "white", position = position_dodge(width = .9)) +
  labs(title = "Sueldo promedio por puesto",
       subtitle = paste0(funcion_analisis, "- En AR$"),
       x = "", y = "", caption = fuente) +
  eje_x_n +
  estilov

rh_ar %>% 
  filter(funcion_rh == funcion_analisis) %>% 
  ggplot(aes(y = puesto, fill = nivel_formacion)) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = col4) +
  labs(title = "Nivel de formación por puesto",
       subtitle = funcion_analisis,
       x = "", y = "",
       fill = "Nivel de Formación",
       caption = fuente) +
  estilo

Otros AnƔlisis

Preguntas bizarras en entrevistas.

ā€œĀæPensĆ”s tener hijos?ā€/ā€œĀæPor quĆ© no estĆ”s casada?ā€

Cuando diseƱamos esta encuesta, nos pareció una buena idea preguntar sobre cuĆ”les fueron las preguntas mĆ”s desubicadas o bizarras realizadas en una entrevista laboral. Pero nunca nos imaginamos que Ć­bamos a necesitar filtrar por chongo (para saber a quĆ© llamamos ā€œchongoā€ en Argentina entra en este link).

preg <- kiwi[,c("genero","pregunta_bizarra")] 

names(preg) <- c("genero", "pregunta")

listado_preg <- preg %>% 
  filter(str_detect(pregunta, "hijo[s]")|
           str_detect(pregunta, "casad[ao]|casar")| 
           str_detect(pregunta,"novio")|
           str_detect(pregunta,"chongo"))

Al respecto quisimos saber a cuƔntas mujeres y hombres les habƭan hecho preguntas desubicadas sobre si tendrƭan hijos, o si tenƭan planes de casamiento. En 42 respuestas esto es lo que encontramos:

gt(preg %>% 
  filter(str_detect(pregunta, "hijo[s]")|
           str_detect(pregunta, "casad[ao]|casar")| 
           str_detect(pregunta,"novio")|
           str_detect(pregunta,"chongo")) %>% 
  group_by(genero) %>% 
  summarise (n = n()) %>% 
  mutate(freq = percent(n/sum(n)))) %>% 
  cols_label(genero = "GƩnero", 
             n = "Cantidad",
             freq = "Porcentaje")
GƩnero Cantidad Porcentaje
Femenino 33 79%
Masculino 9 21%
preg %>% 
  filter(str_detect(pregunta, "hijo[s]")|
           str_detect(pregunta, "casad[ao]|casar")| 
           str_detect(pregunta,"novio")|
           str_detect(pregunta,"chongo")) %>% 
  group_by(genero) %>% 
  summarise (n = n()) %>% 
  mutate(freq = percent(n/sum(n))) %>% 
  ggplot(aes(x = genero, y = n, fill = genero)) +
  geom_col() +
  scale_fill_manual(values = c("#8624F5", "#1FC3AA")) +
  estilo + theme(legend.position = "none") +
  labs(title = "Mujeres y hombres a los que les preguntaron si pensaban tener hijos \n o si planeaban casarse en una entrevista laboral",
       x = "", y= "", fill = "",
       caption = fuente) 

Relación entre satisfacción y sueldos

Para este anÔlisis nos preguntamos si hay relación entre el nivel salarial y la satisfacción.

Para responder a esta pregunta, cruzamos los sueldos brutos de Argentina, contra los niveles de satisfacción con la actual empresa donde trabajan las personas que respondieron la encuesta.

Los pasos que seguimos fueron los siguientes:

  • A los sueldos brutos los segmentamos en 4 partes con igual cantidad de registros (cuartiles). Es decir, en el 1° cuartil tenemos el 25% de los datos, en el segundo cuartil tenemos el 50% de los datos, y en el 3° cuartil tenemos el 75% de los datos.
  • En el primer cuartil estĆ”n los sueldos mĆ”s bajos, y el 4° los mĆ”s altos.
  • Los niveles de satisfacción van del 1 (Totalmente Insatisfecho), al 5, (Totalmente Satisfecho).
library(ggalluvial)

satisf <- rh %>% 
  filter(!is.na(satisfaccion),
         genero %in% c("Femenino", "Masculino"),
         pais == "Argentina") %>% 
  select(genero, sueldo_bruto, satisfaccion)


p25 <- profiling_num(satisf)[1,7]
p50 <- profiling_num(satisf)[1,8]
p75 <- profiling_num(satisf)[1,9]

satisf <- satisf %>% 
  mutate(cuartil = factor(case_when(
    sueldo_bruto  <   p25  ~ "1Q",
    sueldo_bruto > p25 & sueldo_bruto < p50 ~ "2Q",
    sueldo_bruto > p50 & sueldo_bruto < p75 ~ "3Q",
    TRUE   ~ "4Q")),
    satisfaccion = factor(satisfaccion, 
                             levels = c("1","2","3","4","5")), 
    cuenta = 1)


satisf <- satisf %>% 
  group_by(genero, satisfaccion, cuartil) %>% 
  summarise(cant = n())



ggplot(as.data.frame(satisf), aes(y = cant, axis1 = cuartil, axis2 = satisfaccion)) +
  geom_alluvium(aes(fill = genero), width = 1/12, alpha = 0.4) +
  geom_stratum(width = 1/12, fill = "#8882F7") +
  geom_label(stat = "stratum", aes(label = after_stat(stratum))) +
  scale_x_discrete(limits = c("Sueldo Bruto por Cuartil", "Nivel de Satisfacción"), expand = c(.05, .05)) +
  scale_fill_manual(values = colores) +
  estilo +
  labs(title = "Relación entre nivel salarial y satisfacción con la empresa",
       y = "", caption = fuente, fill = "GƩnero")

¿Cómo se llama el Ôrea?

Dentro de los diversos anÔlisis que podíamos hacer con los datos recolectados algo sobre lo que indagamos fue sobre cómo se llama el Ôrea.

nombres <- kiwi[ , "nombre_area"]

nombres <- nombres %>% 
  filter(!is.na(nombre_area))

distintos <- distinct(.data = nombres) %>% count() %>% pull()

nombres <- nombres %>% 
  mutate(nombre = str_to_title(nombre_area, locale = "es")) %>% 
  group_by(nombre) %>% 
  count(sort = T, name = "rtas") %>% 
  head(10) %>% 
  ungroup()


ggplot(nombres, aes(x = rtas, y = reorder(nombre,rtas))) +
  geom_col(fill = "#344D7E") +
  geom_text(aes(label = round(x=rtas, 0), 
                hjust = -.5, 
                fontface = "bold"),
            size = 4, 
            color = "darkgrey")+
  estilov +
  labs(title = "Top 10 de nombres para el Ɣrea de RRHH", 
       x = "", y = "", 
       caption = fuente) +
  scale_x_continuous(limits = c(0, 430), breaks = c(100, 200, 300, 400))

En total, encontramos 58 formas diferentes de llamar al Ôrea. Tristemente nos sorprende la cantidad de veces que encontramos que el Ôrea aún se llama Oficina De Personal.

LS0tDQp0aXRsZTogIlByZXNlbnRhY2nDs24gZGUgUmVzdWx0YWRvcyBFbmN1ZXN0YSBLSVdJIDIwMjAiDQphdXRob3I6ICJDbHViIGRlIFIgcGFyYSBSUkhIIg0KZGF0ZTogIjEyLzExLzIwMjAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOiBjb3Ntbw0KICAgIGhpZ2hsaWdodDogaGFkZG9jaw0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGZpZy5yZXRpbmEgPSAzLCBvdXQud2lkdGggPSAiNzAlIiwgZmlnLmFsaWduID0gImNlbnRlciIpDQpgYGANCg0KIyBJbnRyb2R1Y2Npw7NuDQoNCkVsIFtDbHViIGRlIFIgcGFyYSBSUkhIXShodHRwczovL3I0aHIuY2x1YikgZXMgdW5hIGNvbXVuaWRhZCBkZSBhcHJlbmRpemFqZSBkZSBwcm9ncmFtYWNpw7NuIGRlIFIsIGRlc3RpbmFkYSBhIGxvcyBwcm9mZXNpb25hbGVzIHkgZXN0dWRpYW50ZXMgcXVlIHRyYWJhamFuIG8gcXVpZXJlbiB0cmFiYWphciBlbiBlbCDDoXJlYS4NCg0KU29tb3MgdW5hIGNvbXVuaWRhZCBxdWUgdXNhIG1heW9ybWVudGUgZGF0b3MgZGUgZWplbXBsbyByZWxhY2lvbmFkb3MgY29uIFJSSEgsIHkgcXVlIGdlbmVyYSBjb250ZW5pZG8gZW4gY2FzdGVsbGFubyBwYXJhIGVsaW1pbmFyIGxhcyBiYXJyZXJhcyBlbiBlbCBhcHJlbmRpemFqZSB5IGZhY2lsaXRhciBxdWUgbcOhcyBwZXJzb25hcyBhZG9wdGVuIGxhcyBoZXJyYW1pZW50YXMgZGUgYW7DoWxpc2lzIGRlIGRhdG9zIGVuIHN1cyB0cmFiYWpvcy4NCg0KUGFyYSBzYWJlciBtw6FzIGRlIG5vc290cm9zIHRlIGludml0YW1vcyBhIGxlZXIgW2VzdGUgcG9zdF0oaHR0cHM6Ly9yNGhyLmNsdWIvMjAyMC8wOS8yMy9lbC1jbHViLWRlLXItcGFyYS1ycmhoLykuDQoNClBvZMOpcyBhY2NlZGVyIGEgbG9zIGRhdG9zIGRlIGxhIGVuY3Vlc3RhIFtlbiBlc3RlIGxpbmtdKGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzE4MzN4RWVSSXkxRExrZTRlSEtmRVRoampneDAxWUdYOXlRYVU2dnYxNUswL2VkaXQ/dXNwPXNoYXJpbmcpLg0KDQpgYGB7ciBwcmVwcm9jZXNvfQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkgICAgICAjIFRyYW5zZm9ybWFyIHkgbGltcGlhciBkYXRvcw0KbGlicmFyeShnb29nbGVzaGVldHM0KSAgIyBMZWVyIGRhdG9zIGRlc2RlIEdvb2dsZSBTaGVldHMNCmxpYnJhcnkoZ2FyZ2xlKSAgICAgICAgICMgQ29ycmVnaXIgbGVjdHVyYSBkZSBzw61tYm9sb3MgZXNwZWNpYWxlcyBkZXNkZSBHb29nbGUgU2hlZXRzDQpsaWJyYXJ5KGd0KSAgICAgICAgICAgICAjIERhciBmb3JtYXRvIGEgbGFzIHRhYmxhcw0KbGlicmFyeShleHRyYWZvbnQpICAgICAgIyBQZXJtaXRlIHV0aWxpemFyIG90cmFzIGZ1ZW50ZXMgZW4gbG9zIGdyw6FmaWNvcyB5IHNhbGlkYXMNCmxpYnJhcnkoZ2d0aGVtZXMpICAgICAgICMgQW1wbMOtYSBsYXMgcG9zaWJpbGlkYWRlcyBlc3TDqXRpY2FzIGRlIGdncGxvdDINCmxpYnJhcnkoc2NhbGVzKSAgICAgICAgICMgUGVybWl0ZSBjYW1iaWFyIGxvcyBmb3JtYXRvcyBkZSBkZWNpbWFsZXMsIGRlIHBvcmNlbnRhamVzLCBldGMuDQpsaWJyYXJ5KGdnYWx0KSAgICAgICAgICAjIE51ZXZvcyB0aXBvcyBkZSBnZW9tIHBhcmEgZ2dwbG90Mi4gUGFyYSByZWFsaXphciBlbCBncsOhZmljbyBkZSBnYXAgc2FsYXJpYWwNCmxpYnJhcnkoZnVuTW9kZWxpbmcpICAgICMgUGFyYSBleHBsb3JhciBkYXRvcyB5IG1vZGVsb3MNCmxpYnJhcnkoZm9yY2F0cykNCmxpYnJhcnkoRFQpDQoNCm9wdGlvbnMoc2NpcGVuID0gOTk5KSAgICMgTW9kaWZpY2EgbGEgdmlzdWFsaXphY2nDs24gZGUgbG9zIGVqZXMgbnVtw6lyaWNvIGEgdmFsb3JlcyBub21pbmFsZXMNCg0KbG9hZGZvbnRzKHF1aWV0ID0gVFJVRSkgIyBQZXJtaXRlIGNhcmdhciBlbiBSIG90cm9zIHRpcG9zIGRlIGZ1ZW50ZXMuDQoNCiMgRXN0aWxvIGxpbXBpbyBzaW4gbMOtbmVhcyBkZSBmb25kbw0KZXN0aWxvIDwtIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZCRkNGQyIpLA0KICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiUm9ib3RvIikpDQoNCiMgRXN0aWxvIGxpbXBpbyBjb24gbMOtbmVhcyBkZSByZWZlcmVuY2lhIHZlcnRpY2FsZXMgZW4gZ3JpcyBjbGFybw0KZXN0aWxvdiA8LSB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkJGQ0ZDIiksDQogICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICIjQUVCNkJGIiksDQogICAgICAgICAgICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIlJvYm90byIpKQ0KDQojIEVzdGlsbyBsaW1waW8gY29uIGzDrW5lYXMgZGUgcmVmZXJlbmNpYSBob3Jpem9udGFsZXMgZW4gZ3JpcyBjbGFybw0KZXN0aWxvaCA8LSB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkJGQ0ZDIiksDQogICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShjb2xvciA9ICIjQUVCNkJGIiksDQogICAgICAgICAgICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIlJvYm90byIpKQ0KDQpnZW5lcm8gPC0gYygiIzg2MjRGNSIsICIjMUZDM0FBIiwgIiNGRkQxMjkiLCAiIzc1ODM4RiIpICNWaW9sZXRhIC0gVmVyZGUgLSBBbWFyaWxsbyAtIEdyaXMNCmdlbmVybzMgPC0gYygiIzg2MjRGNSIsIiNGRkQxMjkiLCAiIzFGQzNBQSIpDQoNCmNvbG9yZXMgPC0gIGMoIiM4NjI0RjUiLCAiIzFGQzNBQSIpDQoNCmF6dWwgPC0gIiMzNDREN0UiDQp2ZXJkZSA8LSAgIiM0QTlGQzciDQpyb3NhMSA8LSAiI0I5NTE5MiINCnJvc2EyIDwtICIjRUU1Nzc3Ig0KbmFyYW5qYSA8LSAiI0ZGNzY0QyINCmFtYXJpbGxvIDwtICIjRkZBNjAwIg0KZ3JpcyA8LSAiIzc1ODM4RiINCmxpbGEgPC0gIiM3NTUzOTUiDQpyb2pvIDwtICIjOTQzMTI2Ig0KDQpjb2w0IDwtIGMoYXp1bCwgbGlsYSwgcm9zYTEsIHJvc2EyKQ0KY29sNSA8LSBjKGF6dWwsIGxpbGEsIHJvc2ExLCByb3NhMiwgbmFyYW5qYSkNCmNvbDYgPC0gYyhhenVsLCBsaWxhLCByb3NhMSwgcm9zYTIsIG5hcmFuamEsIGFtYXJpbGxvKQ0KDQojIENyZW8gdW4gb2JqZXRvIGNvbiB1biB0ZXh0byBxdWUgc2UgdmEgYSByZXBldGlyIG11Y2hvIGEgbG8gbGFyZ28gZGVsIGFuw6FsaXNpcw0KZnVlbnRlIDwtICJGdWVudGU6IEVuY3Vlc3RhIEtJV0kgZGUgU3VlbGRvcyBkZSBSUkhIIHBhcmEgTGF0YW0iDQoNCiMgQ3JlbyBvYmpldG9zIHBhcmEgZm9ybWF0ZWFyIGxhcyBldGlxdWV0YXMgbnVtw6lyaWNhcyBkZSBsb3MgZWplcyB4IGUgeQ0KZWplX3hfbiA8LSBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWFfZm9ybWF0KGJpZy5tYXJrID0gIi4iLCBkZWNpbWFsLm1hcmsgPSAiLCIpKQ0KDQplamVfeV9uIDwtIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBjb21tYV9mb3JtYXQoYmlnLm1hcmsgPSAiLiIsIGRlY2ltYWwubWFyayA9ICIsIikpDQoNCg0KIyBDYXJnYSBkZSBkYXRvcw0KDQpvcmlnaW5hbCA8LSBzaGVldHNfcmVhZCgiMWFldXU5ZFZmTjQyRWp5dmJtaEVjc2YwaWxTejJEaVhVLTBNcG5GODk2c3MiKQ0KdGlwb19jYW1iaW8gPC0gc2hlZXRzX3JlYWQoIjF0RWM0LV9nWEppNGxKX0JqX3lzbGVDLU8wMWppVk91bU9RQ3hHUTF0U2hNIikgJT4lIA0KICBzZWxlY3QocGFpcywgdGlwb19jYW1iaW8pDQoNCg0KIyBQcmVwcm9jZXNhbWllbnRvIA0Ka2l3aSA8LSBvcmlnaW5hbA0KDQpsaW1waW9zIDwtIG1ha2UubmFtZXMoY29sbmFtZXMoa2l3aSkpDQpjb2xuYW1lcyhraXdpKSA8LSBsaW1waW9zDQoNCnJtKGxpbXBpb3MpDQoNCmtpd2kgPC0ga2l3aSAlPiUgDQogIHNlbGVjdCgtWC5RdWVyw6lzLmNvbnRlc3Rhci5tw6FzLnByZWd1bnRhcy4uLi4zMSwgDQogICAgICAgICAtWC5RdWVyw6lzLmNvbnRlc3Rhci5tw6FzLnByZWd1bnRhcy4uLi40MikgJT4lIA0KICByZW5hbWUoZ2VuZXJvID0gR8OpbmVybywNCiAgICAgICAgIGdlbmVyb19kaXZlcnNvID0gWC5UZS5pZGVudGlmaWPDoXMuY29tby5MR0JULi4ubGVzYmlhbmEuLmdheS4uYmlzZXh1YWwuLnRyYW5zZXh1YWwuLm90cmEubWlub3LDrWEuc2V4dWFsLi4sDQogICAgICAgICBlZGFkID0gRWRhZCwNCiAgICAgICAgIGRpc2NhcGFjaWRhZCA9IFguVGVuw6lzLmFsZ3VuYS5kaXNjYXBhY2lkYWQuLA0KICAgICAgICAgbml2ZWxfZm9ybWFjaW9uID0gYE3DoXhpbW8ubml2ZWwuZGUuZm9ybWFjacOzbmAsDQogICAgICAgICBjYXJyZXJhX2dyYWRvID0gWC5RdcOpLmNhcnJlcmEuZGUuZ3JhZG8uZXN0dWRpYXN0ZS4sDQogICAgICAgICB0aXBvX3VuaXZlcnNpZGFkID0gWC5Fbi5xdcOpLnRpcG8uZGUudW5pdmVyc2lkYWQuZXN0dWRpYXN0ZS50dS5jYXJyZXJhLmRlLmdyYWRvLiwNCiAgICAgICAgIHBhaXMgPSBQYcOtcy5lbi5lbC5xdWUudHJhYmFqYXMsDQogICAgICAgICBwcm92aW5jaWEgPSBQcm92aW5jaWEuZG9uZGUudHJhYmFqYXMsDQogICAgICAgICB0cmFiYWpvID0gVHJhYmFqbywNCiAgICAgICAgIHJ1YnJvID0gUnVicm8uZGUubGEuZW1wcmVzYSwNCiAgICAgICAgIGRvdGFjaW9uID0gWC5DdcOhbnRvcy5lbXBsZWFkb3MudGllbmUubGEuZW1wcmVzYS4sDQogICAgICAgICBvcmlnZW5fY2FwaXRhbCA9IE9yaWdlbi5kZWwuY2FwaXRhbCwNCiAgICAgICAgIGRvdGFjaW9uX3JoID0gWC5DdcOhbnRhcy5wZXJzb25hcy5pbnRlZ3Jhbi5lbC7DoXJlYS5kZS5SUkhILiwNCiAgICAgICAgIHB1ZXN0byA9IFguRW4ucXXDqS5wdWVzdG8udHJhYmFqw6FzLiwNCiAgICAgICAgIHRpcG9fY29udHJhdGFjaW9uID0gVGlwby5kZS5jb250cmF0YWNpw7NuLA0KICAgICAgICAgZnVuY2lvbl9yaCA9IFguQ3XDoWwuZXMudHUuZnVuY2nDs24ucHJpbmNpcGFsLmVuLlJSSEguLA0KICAgICAgICAgcGVyc29uYXNfYV9jYXJnbyA9ICJYLkN1w6FudGFzLnBlcnNvbmFzLnRlbsOpcy5hLmNhcmdvLi4ucG9uw6kuMC5zaS5uby50ZW7DqXMuZ2VudGUuYS5jYXJnby4iLA0KICAgICAgICAgYW5pb3NfZW5fZW1wcmVzYSA9ICJYLkhhY2UuY3XDoW50b3MuYcOxb3MudHJhYmFqYXMuZW4ubGEuZW1wcmVzYS5kb25kZS5lc3TDoXMuLi4wLnBhcmEubWVub3MuZGUudW4uYcOxby4iLA0KICAgICAgICAgYW5pb3NfZW5fcHVlc3RvID0gIlguSGFjZS5jdcOhbnRvcy5hw7Fvcy5lc3TDoXMuZW4udHUucHVlc3RvLmFjdHVhbC4uLjAucGFyYS5tZW5vcy5kZS51bi5hw7FvLiIsDQogICAgICAgICBhbmlvc19leHBlcmllbmNpYSA9IFguQ3XDoW50b3MuYcOxb3MuZGUuZXhwZXJpZW5jaWEudGVuw6lzLmVuLlJSSEguLA0KICAgICAgICAgc3VlbGRvX2JydXRvID0gWC5DdcOhbC5lcy50dS5yZW11bmVyYWNpw7NuLkJSVVRBLk1FTlNVQUwuZW4udHUubW9uZWRhLmxvY2FsLi4uYW50ZXMuZGUuaW1wdWVzdG9zLnkuZGVkdWNjaW9uZXMuLA0KICAgICAgICAgYmVuZWZpY2lvcyA9IFguUXXDqS5iZW5lZmljaW9zLnRlbsOpcy4sDQogICAgICAgICBib25vID0gWC5SZWNpYsOtcy5ib25vcy4sDQogICAgICAgICBhanVzdGUgPSBYLlR1dmlzdGUuYWp1c3Rlcy5wb3IuaW5mbGFjacOzbi5lbi4yMDIwLiwNCiAgICAgICAgIGFqdXN0ZV9wb3JjZW50YWplID0gWC5DdcOhbC5mdWUuZWwucG9yY2VudGFqZS5kZS5hdW1lbnRvLmFjdW11bGFkby5xdWUudHV2aXN0ZS5lbi4yMDIwLiwNCiAgICAgICAgIGFqdXN0ZV9tZXMgPSBNZXMuZGVsLsO6bHRpbW8uYWp1c3RlLA0KICAgICAgICAgb3Ryb3NfcHJveWVjdG9zID0gWC5UcmFiYWrDoXMuZW4ucHJveWVjdG9zLmluZGVwZW5kaWVudGVzLmFkZW3DoXMuZGUudHUuZW1wbGVvLiwNCiAgICAgICAgIGVycCA9IFguUXXDqS5zaXN0ZW1hLmRlLmdlc3Rpw7NuLmRlLlJSSEgudXNhbi5lbi50dS5lbXByZXNhLiwNCiAgICAgICAgIG5vbWJyZV9hcmVhID0gWC5Dw7Ntby5zZS5sbGFtYS5lbC7DoXJlYS5lbi50dS5lbXByZXNhLiwNCiAgICAgICAgIG1hdGUgPSBYLlNlLnBvZMOtYS50b21hci5tYXRlLmVuLmxhcy5vZmljaW5hcy5kZS50dS5lbXByZXNhLi4uYW50ZXMuZGVsLkNPVklELjE5LiwNCiAgICAgICAgIGlkaW9tYV9leGlnZW5jaWEgPSBYLlRlLmV4aWdpZXJvbi5zYWJlci51bi5pZGlvbWEuZXh0cmFuamVyby4uaW5nbMOpcy4ucG9ydHVndcOpcy4uZXRjLi4ucGFyYS5lbnRyYXIuYS50cmFiYWphci5lbi50dS5lbXByZXNhLiwNCiAgICAgICAgIGlkaW9tYV9wb3JjZW50YWplID0gWC5RdcOpLnBvcmNlbnRhamUuZGVsLnRpZW1wby51c2FzLmVsLmlkaW9tYS5leHRyYW5qZXJvLmVuLnR1LnB1ZXN0by5hY3R1YWwuLA0KICAgICAgICAgY29udGFjdG9zX2xpbmtlZGluID0gIlguQ3XDoW50b3MuY29udGFjdG9zLnRlbsOpcy5lbi5MaW5rZWRJbi4uLnBvbsOpLjAuc2kubm8udGVuw6lzLmN1ZW50YS5kZS5MaW5rZWRJbi4iLA0KICAgICAgICAgc2F0aXNmYWNjaW9uID0gWC5RdcOpLnRhbi5zYXRpc2ZlY2hvLmVzdMOhcy5jb24udHUuZW1wcmVzYS4sDQogICAgICAgICBidXNxdWVkYSA9IFguRXN0w6FzLmJ1c2NhbmRvLnRyYWJham8uLA0KICAgICAgICAgYmVuZWZpY2lvc19leHBlY3RhdGl2YSA9IFguUXXDqS5iZW5lZmljaW9zLnRlLmd1c3RhcsOtYS50ZW5lci4sDQogICAgICAgICByaF91bmFfcGFsYWJyYSA9IERlZmluw60uYS5SUkhILmNvbi51bmEuc29sYS5wYWxhYnJhLA0KICAgICAgICAgcHJlZ3VudGFfYml6YXJyYSA9IFguQ3XDoWwuZXMubGEucHJlZ3VudGEubcOhcy5iaXphcnJhLnF1ZS50ZS5oYW4uaGVjaG8uaGFzLmhlY2hvLmVuLnVuYS5lbnRyZXZpc3RhLiwNCiAgICAgICAgIHRlbGV0cmFiYWpvID0gWC5Fc3TDoXMudHJhYmFqYW5kby5kZXNkZS50dS5jYXNhLiwNCiAgICAgICAgIGVsZW1lbnRvcyA9IFguUXXDqS5lbGVtZW50b3MudGUucHJvdmV5w7MubGEuZW1wcmVzYS5wYXJhLnF1ZS5wdWVkYXMudHJhYmFqYXIuZGVzZGUudHUuY2FzYS4sDQogICAgICAgICB2YWxvcmFjaW9uX2dlc3Rpb25fZW1wcmVzYSA9IFguQ8OzbW8udmFsb3JhcsOtYXMubGEuZ2VzdGnDs24uZGUudHUuZW1wcmVzYS5lbi5lc3RlLm51ZXZvLmNvbnRleHRvLiwNCiAgICAgICAgIHJlZ2lzdHJvX2Zpc2NhbCA9IFguQ8OzbW8uZXN0w6FzLnJlZ2lzdHJhZG8uYS5maXNjYWxtZW50ZS4sDQogICAgICAgICBhbmlvc19mcmVlbGFuY2UgPSBYLkhhY2UuY3XDoW50b3MuYcOxb3MudHJhYmFqw6FzLmNvbW8uZnJlZWxhbmNlLiwNCiAgICAgICAgIGx1Z2FyX3RyYWJham8gPSBYLkTDs25kZS50cmFiYWrDoXMuaGFiaXR1YWxtZW50ZS4uLnNpbi5jb25zaWRlcmFyLmxhLmNveXVudHVyYS5wb3IuQ09WSUQuMTkuLA0KICAgICAgICAgZXhwb3J0YSA9IFguRXhwb3J0w6FzLnR1cy5zZXJ2aWNpb3MuLA0KICAgICAgICAgbWVkaW9fcGFnb19leHRlcmlvciA9IFNpLmV4cG9ydMOhcy5zZXJ2aWNpb3MuLi5hLnRyYXbDqXMuZGUucXXDqS5tZWRpb3MuZGUucGFnby5yZWNpYsOtcy5sb3MucGFnb3MuZGVsLmV4dGVyaW9yLiwNCiAgICAgICAgIGN1b3RhcyA9IFguQWNlcHTDoXMucGFnb3MuZW4uY3VvdGFzLiwNCiAgICAgICAgIGNvbGFib3JhY2lvbl9mcmVlbGFuY2UgPSBYLlRyYWJhasOhcy5jb24ub3Ryb3MuZnJlZWxhbmNlcnMuZGUudHUubWlzbW8ucnVicm8uLA0KICAgICAgICAgc2VydmljaW9fYnVzcXVlZGEgPSBYLlR1LnNlcnZpY2lvLnByaW5jaXBhbC5lc3TDoS5yZWxhY2lvbmFkby5jb24uYsO6c3F1ZWRhLnkuc2VsZWNjacOzbi4sDQogICAgICAgICBidXNxdWVkYV9pdCA9IFguVGUuZGVkaWPDoXMucHJpbmNpcGFsbWVudGUuYS5yZWFsaXphci5iw7pzcXVlZGFzLmRlLklULlRlY25vbG9nw61hLiwNCiAgICAgICAgIHRyYWJham9fYV9yaWVzZ28gPVguVHJhYmFqw6FzLmEucmllc2dvLiwNCiAgICAgICAgIGNvZWZpY2llbnRlID0gWC5DdcOhbC5lcy5lbC5jb2VmaWNpZW50ZS5xdWUuY29icsOhcy5wb3IudHVzLnNlcnZpY2lvcy4sDQogICAgICAgICBiYXNlX2NvZWZpY2llbnRlID0gRWwuY29lZmljaWVudGUubG8uY2FsY3Vsw6FzLnNvYnJlLiwNCiAgICAgICAgIGdhcmFudGlhID0gWC5PZnJlY8Opcy5nYXJhbnTDrWEuLA0KICAgICAgICAgc2VydmljaW9fcHJpbmNpcGFsID0gWC5DdcOhbC5lcy5lbC5zZXJ2aWNpby5wcmluY2lwYWwucXVlLmJyaW5kYXMuLi5zaS5icmluZMOhcy5tw6FzLmRlLnVuLnNlcnZpY2lvLi5lbGVnw60uZWwucXVlLm3DoXMuaW5ncmVzb3MuZ2VuZXJlLiwNCiAgICAgICAgIHZhbG9yX2hvcmEgPSBYLkN1w6FsLmVzLmVsLnZhbG9yLmhvcmEucHJvbWVkaW8ucXVlLm9mcmVjw6lzLi4ubW9uZWRhLmxvY2FsLikNCg0KIyBCYXNlIGRlIGZyZWVsYW5jZXJzDQpmcmVlbG8gPC0ga2l3aSAlPiUgDQogIGZpbHRlcih0cmFiYWpvID09ICJGcmVlbGFuY2UiKQ0KDQojIEJhc2UgZGUgZW1wbGVhZG9zIGVuIHJlbGFjacOzbiBkZSBkZXBlbmRlbmNpYQ0KcmggPC0ga2l3aSAlPiUgDQogIGZpbHRlcih0cmFiYWpvID09ICJSZWxhY2nDs24gZGUgRGVwZW5kZW5jaWEiLCANCiAgICAgICAgIGZ1bmNpb25fcmggIT0gIk5pbmd1bm8iLA0KICAgICAgICAgZnVuY2lvbl9yaCAhPSAiTm8gbWUgZGVzZW1wZcOxbyBlbiBlbCDDoXJlYSBkZSBSUkhILiIsDQogICAgICAgICBmdW5jaW9uX3JoICE9ICJUcmFiYWpvIGVuIGVsIMOhcmVhIGRlIFNpc3RlbWFzLiIsDQogICAgICAgICBmdW5jaW9uX3JoICE9ICJObyB0cmFiYWpvIGVuIGVsIGFyZWEiLA0KICAgICAgICAgZnVuY2lvbl9yaCAhPSAiTm8gdHJhYmFqbyBlbiByZWN1cnNvcyBodW1hbm9zIiwNCiAgICAgICAgIGZ1bmNpb25fcmggIT0gIk5vIHRyYWJham8gZW4gUnJoaCIsDQogICAgICAgICBmdW5jaW9uX3JoICE9ICJUcmFiYWpvIGVuIEFkbWluaXN0cmFjacOzbiB5IEZpbmFuemFzIiwNCiAgICAgICAgIGZ1bmNpb25fcmggIT0gIkFhYSIsDQogICAgICAgICBmdW5jaW9uX3JoICE9ICJJVCIpICU+JSANCiAgbXV0YXRlKHN1ZWxkb19icnV0byA9IGFzLm51bWVyaWModW5saXN0KHN1ZWxkb19icnV0bykpLA0KICAgICAgICAgcHVlc3RvID0gZmFjdG9yKHB1ZXN0bykpDQoNCg0KcmggPC0gcmggJT4lIA0KICBmaWx0ZXIocHVlc3RvICE9ICJKdXpnYWRvIENpdmlsIHkgQ29tZXJjaWFsIiwNCiAgICAgICAgIHB1ZXN0byAhPSAiUHJvZ3JhbWFkb3IiLA0KICAgICAgICAgcHVlc3RvICE9ICJDdWlkYWRvIiwNCiAgICAgICAgIHB1ZXN0byAhPSAiQXNlc29yIiwNCiAgICAgICAgIHB1ZXN0byAhPSAiSmVmZSBkZSBQcm95ZWN0byIpICU+JSANCiAgbXV0YXRlKHB1ZXN0byA9IHN0cl90cmltKHB1ZXN0bywgc2lkZSA9ICJib3RoIiksICMgRWxpbWluYSBlc3BhY2lvcyB2YWPDrW9zDQogICAgICAgICBwdWVzdG8gPSBmY3RfY29sbGFwc2UocHVlc3RvLCAiR2VyZW50ZSIgPSAiU3VwZXJpbnRlbmRlbnRlIiksDQogICAgICAgICBwdWVzdG8gPSBmY3RfY29sbGFwc2UocHVlc3RvLCAiRGlyZWN0b3IiID0gIkRpcmVjdG9yICggZXNjYWxhZsOzbiBtdW5pY2lwYWwpIiksDQogICAgICAgICBwdWVzdG8gPSBmY3RfY29sbGFwc2UocHVlc3RvLCAiSFJCUCIgPSBjKCJTZW5pb3IgQ29uc3VsdG9yw61hIiwgInNwZWNpYWxpc3QiLCAiZXNwZWNpYWxpc3RhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkVzcGVjaWFsaXN0YSBlbiBzZWxlY2Npw7NuIElUIiwgIlJlY3J1aXRlciIpKSwNCiAgICAgICAgIHB1ZXN0byA9IGZjdF9jb2xsYXBzZShwdWVzdG8sICJSZXNwb25zYWJsZSIgPSBjKCJDb29yZGluYWNpw7NuIiwgIkNvb3JkaW5hZG9yIGRlIFBheXJvbGwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkVuY2FyZ2FkbyIsICJTdXBlcnZpc29yIikpLA0KICAgICAgICAgcHVlc3RvID0gZmN0X2NvbGxhcHNlKHB1ZXN0bywgIkFkbWluaXN0cmF0aXZvIiA9IGMoIkFzaXN0ZW50ZSIsICJBc2lzdGVudGUgUlJISCIsICJBdXgiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDYXBhY2l0YWRvciIsICJDb25zdWx0b3IgRWplY3V0aXZvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjb25zdWx0b3IganIiKSksDQogICAgICAgICBwdWVzdG8gPSBmY3RfY29sbGFwc2UocHVlc3RvLCAiQW5hbGlzdGEiID0gYygiQXNlc29yYW1pZW50byIsICJDb25zdWx0b3IiLCAiR2VuZXJhbGlzdGEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWNsdXRhZG9yYSIsICJTZWxlY3RvcmEiLCAiU2VuaW9yIikpKSAlPiUgDQogIHNlbGVjdChNYXJjYS50ZW1wb3JhbDp2YWxvcmFjaW9uX2dlc3Rpb25fZW1wcmVzYSkNCg0KIyBQYXNhIGxvcyBjYW1wb3MgZGUgbGlzdGEgYSBudW3DqXJpY29zDQpyaCA8LSByaCAlPiUgDQogIG11dGF0ZShhbmlvc19lbl9lbXByZXNhICA9IGFzLm51bWVyaWModW5saXN0KGFuaW9zX2VuX2VtcHJlc2EpKSwNCiAgICAgICAgIGFuaW9zX2VuX3B1ZXN0byAgID0gYXMubnVtZXJpYyh1bmxpc3QoYW5pb3NfZW5fcHVlc3RvKSksDQogICAgICAgICBhbmlvc19leHBlcmllbmNpYSA9IGFzLm51bWVyaWModW5saXN0KGFuaW9zX2V4cGVyaWVuY2lhKSksDQogICAgICAgICBhanVzdGVfcG9yY2VudGFqZSA9IGFzLm51bWVyaWModW5saXN0KGFqdXN0ZV9wb3JjZW50YWplKSkpDQoNCiMgTW9kaWZpY2EgbG9zIHJlZ2lzdHJvcw0KcmgkY29udGFjdG9zX2xpbmtlZGluW1sxNTBdXSA8LSA4MDANCnJoJGNvbnRhY3Rvc19saW5rZWRpbltbMjE0XV0gPC0gNTAwDQpyaCRjb250YWN0b3NfbGlua2VkaW5bWzIyMl1dIDwtIDEwMDANCnJoJGNvbnRhY3Rvc19saW5rZWRpbltbMjY5XV0gPC0gNTAwDQpyaCRjb250YWN0b3NfbGlua2VkaW5bWzI4Ml1dIDwtIDEwMDANCnJoJGNvbnRhY3Rvc19saW5rZWRpbltbMzM5XV0gPC0gMTAwMA0KcmgkY29udGFjdG9zX2xpbmtlZGluW1szODJdXSA8LSAzMDAwMA0KcmgkY29udGFjdG9zX2xpbmtlZGluW1szODVdXSA8LSA1MDANCnJoJGNvbnRhY3Rvc19saW5rZWRpbltbMzk4XV0gPC0gNTAwMA0KcmgkY29udGFjdG9zX2xpbmtlZGluW1s0NDVdXSA8LSA1MDANCnJoJGNvbnRhY3Rvc19saW5rZWRpbltbNDU5XV0gPC0gNTAwDQpyaCRjb250YWN0b3NfbGlua2VkaW5bWzU5NV1dIDwtIDUwMA0KcmgkY29udGFjdG9zX2xpbmtlZGluW1s1OThdXSA8LSA1MDANCg0KcmggPC0gdW5uZXN0KGRhdGEgPSByaCwgY29scyA9IGMoYW5pb3NfZW5fZW1wcmVzYSwgYW5pb3NfZW5fcHVlc3RvLCBhbmlvc19leHBlcmllbmNpYSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFqdXN0ZV9wb3JjZW50YWplLCBjb250YWN0b3NfbGlua2VkaW4pLCBrZWVwX2VtcHR5ID0gVFJVRSkNCg0KIyBDb3JyZWdpciBvcmRlbiBkZSBwdWVzdG9zIHkgc2ltcGxpZmljYXIgZ8OpbmVybw0KDQpyaCA8LSByaCAlPiUgDQogIG11dGF0ZShwdWVzdG8gPSBmYWN0b3IocHVlc3RvLCBsZXZlbHMgPSBjKCJQYXNhbnRlIiwgIkFkbWluaXN0cmF0aXZvIiwgIkFuYWxpc3RhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkhSQlAiLCAiUmVzcG9uc2FibGUiLCJKZWZlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdlcmVudGUiLCAiRGlyZWN0b3IiKSksDQogICAgICAgICBnZW5lcm8gPSBmY3RfcmVjb2RlKGdlbmVybywgIkfDqW5lcm8gRGl2ZXJzbyIgPSAiR8OpbmVybyBkaXZlcnNvIChnw6luZXJvIGRpdmVyc28gLyBnw6luZXJvIGZsdWlkbyAvb3RyYXMgbWlub3LDrWFzKSIpKQ0KDQpyaCA8LSByaCAlPiUgDQogIGZpbHRlcihuaXZlbF9mb3JtYWNpb24gIT0gIlNlY3VuZGFyaW8gZW4gY3Vyc28iKSAlPiUgDQogIG11dGF0ZShuaXZlbF9mb3JtYWNpb24gPSBmY3RfY29sbGFwc2Uobml2ZWxfZm9ybWFjaW9uLCAiVW5pdmVyc2l0YXJpbyBjb21wbGV0byIgPSBjKCJNYWVzdHLDrWEgYWJhbmRvbmFkYSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTZWN1bmRhcmlvIGNvbXBsZXRvIiA9IGMoIlRlcmNpYXJpbyBhYmFuZG9uYWRvIiwgIlRlcmNpYXJpbyBlbiBjdXJzbyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVuaXZlcnNpdGFyaW8gYWJhbmRvbmFkbyIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNYWVzdHLDrWEgY29tcGxldGEiID0gYygiRG9jdG9yYWRvIGVuIGN1cnNvIikpKQ0KDQoNCiMgQ29tcGFyYWNpw7NuIGRlIHN1ZWxkb3MgZW4gZMOzbGFyZXMNCnJoIDwtIHJoICU+JSANCiAgbGVmdF9qb2luKHRpcG9fY2FtYmlvLCBieSA9ICJwYWlzIikgJT4lIA0KICBtdXRhdGUobXVsdGlwbGljYWRvciA9IGlmX2Vsc2UodGlwb19jb250cmF0YWNpb24gPT0gIlBhcnQgdGltZSIsIDEuNSwgMSksDQogICAgICAgICBzdWVsZG9fZnQgPSBzdWVsZG9fYnJ1dG8gKiBtdWx0aXBsaWNhZG9yLCAgICAjIEhhY2UgbGEgZXF1aXZhbGVuY2lhIGRlIHVuIHN1ZWxkbyBwYXJ0IHRpbWUgYSBmdWxsIHRpbWUNCiAgICAgICAgIHN1ZWxkb19kb2xhciA9IHN1ZWxkb19mdC90aXBvX2NhbWJpbywgICMgQ29udmllcnRvIGxvcyBzdWVsZG9zIGEgZMOzbGFyZXMNCiAgICAgICAgIGN1ZW50YSA9IDEpDQoNCnJ0YXNfcGFpcyA8LSByaCAlPiUgDQogIHNlbGVjdChwYWlzKSAlPiUgDQogIGRpc3RpbmN0KHBhaXMpICU+JSANCiAgY291bnQoKSAlPiUgDQogIHB1bGwoKQ0KYGBgDQoNCiMjIE1vdGl2YWNpb25lcw0KDQpDb21vIGVuIFJSSEggdHJhYmFqYW1vcyBjb24gZGF0b3Mgc2Vuc2libGVzLCBlcyBjb21wbGVqbyBjb25zZWd1aXIgZGF0b3MgcGFyYSBwcmFjdGljYXIgY3VhbmRvIGVzdMOhcyBhcHJlbmRpZW5kbyBzb2JyZSBQZW9wbGUgQW5hbHl0aWNzLCBlc3BlY2lhbG1lbnRlIGxhIHBhcnRlIHByw6FjdGljYS4gUG9yIGVzbywgZSBpbnNwaXJhZG9zIGVuIGxhIEVuY3Vlc3RhIGRlIFtTeXNBcm15XShodHRwczovL3N5c2FybXkuY29tL2Jsb2cvcG9zdHMvcmVzdWx0YWRvcy1kZS1sYS1lbmN1ZXN0YS1kZS1zdWVsZG9zLTIwMjAtMi8pLCB1bmEgY29tdW5pZGFkIGRlIHRlY25vbG9nw61hLCBxdWUgZW50cmUgb3RyYXMgY29zYXMsIG9yZ2FuaXphIGV2ZW50b3MgY29tbyAqKk5lcmRlYXJsYSoqLg0KDQpQb3IgZXN0YSByYXrDs24gaGljaW1vcyBudWVzdHJhIHByb3BpYSBlbmN1ZXN0YSwgcmVsZXZhbmRvIGRhdG9zIGRlIHByb2Zlc2lvbmFsZXMgcXVlIHRyYWJhamFuIHRhbnRvIGJham8gcmVsYWNpw7NuIGRlIGRlcGVuZGVuY2lhIGNvbW8gZGUgbWFuZXJhIGZyZWVsYW5jZS4gRWwgcmVsZXZhbWllbnRvIGRlIGRhdG9zIGxvIGhpY2ltb3MgZW50cmUgZWwgMcKwIHkgZWwgMzEgZGUgb2N0dWJyZSBkZSAyMDIwLg0KDQpSZWNpYmltb3MgZW4gdG90YWwgYHIgbnJvdyhraXdpKWAgcmVzcHVlc3RhcyBkZSBgciBydGFzX3BhaXNgIHBhw61zZXMgZGlmZXJlbnRlcy4NCg0KYGBge3IgcGFpc2VzfQ0KDQojIFJlc3B1ZXN0YXMgcG9yIHBhw61zZXMNCnBhaXNlcyA8LSBraXdpICU+JSANCiAgc2VsZWN0KHBhaXMpICU+JSANCiAgbXV0YXRlKGN1ZW50YSA9IDEpICU+JSANCiAgZ3JvdXBfYnkocGFpcykgJT4lIA0KICBzdW1tYXJpc2UoQ3VlbnRhID0gc3VtKGN1ZW50YSkpICU+JSANCiAgYXJyYW5nZSgtQ3VlbnRhKQ0KDQpndChwYWlzZXMpICU+JSANCiAgdGFiX2hlYWRlcih0aXRsZSA9ICJDYW50aWRhZCBkZSByZXNwdWVzdGFzIHBvciBwYcOtcyIpICU+JSANCiAgdGFiX3NvdXJjZV9ub3RlKHNvdXJjZV9ub3RlID0gZnVlbnRlKSAlPiUgDQogIGNvbHNfbGFiZWwocGFpcyA9ICJQYcOtcyIpDQoNCmBgYA0KDQo8YnI+DQoNCkRlbCB0b3RhbCBkZSByZXNwdWVzdGFzLCBgciBucm93KHJoKWAgc29uIGRlIHBlcnNvbmFzIHF1ZSB0cmFiYWphbiBlbiByZWxhY2nDs24gZGUgZGVwZW5kZW5jaWEgZW4gUlJISCwgeSBgciBucm93KGZyZWVsbylgIHRyYWJhamFuIGRlIG1hbmVyYSBmcmVlbGFuY2UuDQoNCmBgYHtyIHRpcG9fdHJhYmFqb30NCmtpd2kgJT4lIA0KICBzZWxlY3QodHJhYmFqbykgJT4lIA0KICBncm91cF9ieSh0cmFiYWpvKSAlPiUgDQogIGNvdW50KCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBuLCB5ID0gdHJhYmFqbykpICsNCiAgZ2VvbV9jb2woZmlsbCA9IGF6dWwpICsNCiAgZXN0aWxvdiArDQogIGxhYnModGl0bGUgPSAiUmVzcHVlc3RhcyBwb3IgdGlwbyBkZSB0cmFiYWphZG9yIiwgDQogICAgICAgeCA9ICIiLCB5ID0gIiIsIA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpDQoNCmBgYA0KDQpMYSBwYXJ0aWNpcGFjacOzbiBzZWfDum4gZWwgZ8OpbmVybyBlbnRyZSB0cmFiYWphZG9yZXMgZW4gcmVsYWNpw7NuIGRlIGRlcGVuZGVuY2lhOg0KDQpgYGB7ciBnZW5lcm99DQpkaXYgPC0gcmggJT4lIA0Kc2VsZWN0KGdlbmVybykgJT4lIA0KICBtdXRhdGUoZ2VuZXJvID0gZmFjdG9yKGdlbmVybywgDQogICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiRmVtZW5pbm8iLCAiTWFzY3VsaW5vIiwgIkfDqW5lcm8gRGl2ZXJzbyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUHJlZmllcm8gbm8gcmVzcG9uZGVyIikpKSAlPiUgDQogIGdyb3VwX2J5KGdlbmVybykgJT4lIA0KICBzdW1tYXJpc2UgKG4gPSBuKCkpICU+JSANCiAgbXV0YXRlKGZyZXEgPSBuL3N1bShuKSkgJT4lIA0KICBhcnJhbmdlKC1uKQ0KDQojIENvbXB1dGUgdGhlIGN1bXVsYXRpdmUgcGVyY2VudGFnZXMgKHRvcCBvZiBlYWNoIHJlY3RhbmdsZSkNCmRpdiR5bWF4IDwtIGN1bXN1bShkaXYkZnJlcSkNCg0KIyBDb21wdXRlIHRoZSBib3R0b20gb2YgZWFjaCByZWN0YW5nbGUNCmRpdiR5bWluIDwtIGMoMCwgaGVhZChkaXYkeW1heCwgbj0tMSkpDQoNCiMgQ29tcHV0ZSBsYWJlbCBwb3NpdGlvbg0KZGl2JGxhYmVsUG9zaXRpb24gPC0gKGRpdiR5bWF4ICsgZGl2JHltaW4pIC8gMg0KDQojIENvbXB1dGUgYSBnb29kIGxhYmVsDQpkaXYkbGFiZWwgPC0gcGFzdGUwKGRpdiRnZW5lcm8sICJcbiBDYW50OiAiLCBkaXYkbikNCg0KIyBNYWtlIHRoZSBwbG90DQpnZ3Bsb3QoZGl2LCBhZXMoeW1heD15bWF4LCB5bWluPXltaW4sIHhtYXg9NCwgeG1pbj0zLCBmaWxsPWdlbmVybykpICsNCiAgZ2VvbV9yZWN0KCkgKw0KICBjb29yZF9wb2xhcih0aGV0YT0ieSIpICsgIyBUcnkgdG8gcmVtb3ZlIHRoYXQgdG8gdW5kZXJzdGFuZCBob3cgdGhlIGNoYXJ0IGlzIGJ1aWx0IGluaXRpYWxseQ0KICB4bGltKGMoMiwgNCkpICsjIFRyeSB0byByZW1vdmUgdGhhdCB0byBzZWUgaG93IHRvIG1ha2UgYSBwaWUgY2hhcnQNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzg2MjRGNSIsICAiIzFGQzNBQSIsICIjRkZEMTI5IiwiIzc1ODM4RiIpKSArDQogIHRoZW1lX3ZvaWQoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIlJvYm90byIpKSArDQogIGxhYnModGl0bGUgPSAiQ2FudGlkYWQgZGUgcmVzcHVlc3RhcyBzZWfDum4gZ8OpbmVybyIsDQogICAgICAgZmlsbCA9ICJHw6luZXJvIiwgDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkNCg0KYGBgDQoNCiMgQW7DoWxpc2lzIGRlIHJlbXVuZXJhY2lvbmVzDQoNCiMjIFJlbXVuZXJhY2lvbmVzIHBvciBwYcOtcw0KDQpFbiBlc3RhIHNlY2Npw7NuIG5vcyBkZWRpY2FyZW1vcyBhIGNvbXBhcmFyIGxvcyBzdWVsZG9zIGVudHJlIGxvcyBwYcOtc2VzLiBFbiBwcmltZXIgbHVnYXIsIGhheSBxdWUgcmVzYWx0YXIgcXVlIGxvcyByZXN1bHRhZG9zIG5vIHNvbiByZXByZXNlbnRhdGl2b3MgZGUgbG9zIHBhw61zZXMsIHNpbm8gcXVlIGxvIHNvbiBkZSBsb3MgZGF0b3MgcmVjb2xlY3RhZG9zLg0KDQpQb3Igb3RyYSBwYXJ0ZSwgbGEgYmFqYSBjYW50aWRhZCBkZSByZXNwdWVzdGFzIHJlY29sZWN0YWFzIGRlIG90cm9zIHBhw61zZXMgZnVlcmEgZGUgbGEgQXJnZW50aW5hLCBub3MgaGFjZSBpbXBvc2libGUsIGhhY2VyIHVuIGFuw6FsaXNpcyBjb21wYXJhZG8gcmVwcmVzZW50YXRpdm8gZGUgbG9zIHB1ZXN0b3MuIFNpbiBlbWJhcmdvLCBoYXkgYWxndW5vcyBkYXRvcyBpbnRyZXNhbnRlcyBwYXJhIGFuYWxpemFyLg0KDQpQcmltZXJvLCBhbmFsaWNlbW9zIGxvcyBzdWVsZG9zIGRlIGxvcyB0cmFiYWphZG9yZXMgZW4gcmVsYWNpw7NuIGRlIGRlcGVuZGVuY2lhLCBkZSBjdXlvcyBwYcOtc2VzIGhheWFtb3MgcmVjaWJpZG8gYWwgbWVub3MgNSByZXNwdWVzdGFzLg0KDQpgYGB7ciBkb2xhciwgb3V0LndpZHRoPSIxMDAlIn0NCg0Kc3VlbGRvc19kb2xhciA8LSByaCAlPiUgDQogIHNlbGVjdChwdWVzdG8sIHN1ZWxkb19kb2xhciwgcGFpcywgdGlwb19jb250cmF0YWNpb24pICU+JSANCiAgZmlsdGVyKHB1ZXN0byAhPSAiUGFzYW50ZSIsIHRpcG9fY29udHJhdGFjaW9uICE9ICJQYXNhbnRlIikNCg0KIyBFbGltaW5hbW9zIGxvcyBzdWVsZG9zIHF1ZSBlc3TDoW4gZGVudHJvIGRlbCByYW5nbyBlbnRyZSBsb3MgcGVyY2VudGlsZXMgNSB5IDk1DQpudW1lcmljb3MgPC0gcHJvZmlsaW5nX251bShzdWVsZG9zX2RvbGFyKQ0KcG9kYV9wMDUgPC0gbnVtZXJpY29zWzEsNl0NCnBvZGFfcDk1IDwtIG51bWVyaWNvc1sxLDEwXQ0KDQojIERhZG8gcXVlIGxvcyBwZXJjZW50aWxlcyA1IHkgOTUgZXN0w6FuIGVuIFUkNDAwIHkgMjY4OSByZXNwZWN0aXZhbWVudGUsIA0KIyBwb2RhbW9zIHRvZG8gbG8gcXVlIGVzdMOpIGZ1ZXJhIGRlIGVzZSByYW5nbw0KDQptZWRpYV9wYWlzIDwtIHN1ZWxkb3NfZG9sYXIgJT4lIA0KICBmaWx0ZXIocGFpcyAlaW4lIGMoIkFyZ2VudGluYSIsICJCb2xpdmlhIiwgIkNoaWxlIiwgIlBhcmFndWF5IiwgIlVydWd1YXkiLCAiUGVyw7oiKSwNCiAgICAgICAgIGJldHdlZW4oc3VlbGRvX2RvbGFyLHBvZGFfcDA1LHBvZGFfcDk1KSkgJT4lIA0KICBncm91cF9ieShwYWlzKSAlPiUgDQogIHN1bW1hcmlzZShzdWVsZG9wID0gbGlzdChtZWFuX3NlKHN1ZWxkb19kb2xhcikpKSAlPiUgDQogIHVubmVzdChjb2xzID0gYyhzdWVsZG9wKSkgDQogDQpzdWVsZG9fZG9sYXJfcGFpcyA8LSByaCAlPiUgDQogIHNlbGVjdChwYWlzLCBzdWVsZG9fZG9sYXIpICU+JSANCiAgZmlsdGVyKGJldHdlZW4oc3VlbGRvX2RvbGFyLCBwb2RhX3AwNSwgcG9kYV9wOTUpLA0KICAgICAgICAgcGFpcyAlaW4lIGMoIkFyZ2VudGluYSIsICJCb2xpdmlhIiwgIkNoaWxlIiwgIlBhcmFndWF5IiwgIlVydWd1YXkiLCAiUGVyw7oiKSkNCiAgDQojIEdyw6FmaWNvDQpnZ3Bsb3QobWVkaWFfcGFpcywgYWVzKHggPSByZW9yZGVyKHBhaXMsIC15KSwgeSA9ICB5KSkrDQogIGdlb21fY29sKGZpbGwgPSAiIzM0NEQ3RSIsIGFscGhhID0gMC44NSkgKw0KICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0geW1pbix5bWF4ID0geW1heCksIHBvc2l0aW9uID0gImRvZGdlIiwgY29sb3IgPSAiIzc1ODM4RiIpKw0KICBnZW9tX3BvaW50KGRhdGEgPSBzdWVsZG9fZG9sYXJfcGFpcywgYWVzKHggPSBwYWlzLCB5ID0gc3VlbGRvX2RvbGFyKSwgDQogICAgICAgICAgICAgYWxwaGEgPSAwLjMsIHNpemUgPSAyLCBjb2xvciA9ICIjNzU4MzhGIikrDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4PXksIDApLCB2anVzdCA9IDEuNSwgZm9udGZhY2UgPSAiYm9sZCIpLHNpemUgPSA0LCBjb2xvciA9ICJ3aGl0ZSIpKw0KICBlamVfeV9uICsNCiAgbGFicyh0aXRsZSA9ICJNZWRpYW5hIHNhbGFyaWFsIHBvciBwYcOtcyIsDQogICAgICAgc3VidGl0bGUgPSAiU3VlbGRvcyBkZSBSUkhIIGVuIFUkUyIsDQogICAgICAgY2FwdGlvbiA9ICJGdWVudGU6IEVuY3Vlc3RhIEtJV0kgZGUgU3VlbGRvcyBkZSBSUkhIIHBhcmEgTGF0YW0gXG4gUGHDrXNlcyBjb24gNSByZXNwdWVzdGFzIG8gbcOhcyIsDQogICAgICAgeCA9ICIiLCB5ID0gIiIpICsgDQogIGVzdGlsbw0KDQpgYGANCg0KIyMgQW7DoWxpc2lzIGRlIHN1ZWxkb3MgcG9yIHB1ZXN0b3MgZW4gTGF0aW5vYW3DqXJpY2ENCg0KYGBge3Igc3VlbGRvcy1wdWVzdG9zLWxhdGFtfQ0KDQpyaCAlPiUgDQogIHNlbGVjdChwdWVzdG8sIHN1ZWxkb19kb2xhcikgJT4lIA0KICBmaWx0ZXIocHVlc3RvICE9ICJQYXNhbnRlIikgJT4lIA0KICBncm91cF9ieShwdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKG1lZGlhbmFfc2FsYXJpYWwgPSBtZWRpYW4oc3VlbGRvX2RvbGFyKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBtZWRpYW5hX3NhbGFyaWFsLCB5ID0gcHVlc3RvKSkgKw0KICBnZW9tX2NvbChmaWxsID0gYXp1bCkgKw0KICBlc3RpbG92ICsNCiAgbGFicyh0aXRsZSA9ICJNZWRpYW5hIHNhbGFyaWFsIHBvciBwdWVzdG8iLCANCiAgICAgICBzdWJ0aXRsZSA9ICJTdWVsZG9zIGRlIFJSSEggZW4gVSRTIiwgDQogICAgICAgeCA9ICIiLCB5ID0gIiIsIA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZWplX3hfbg0KDQpgYGANCg0KTGEgcmF6w7NuIHBvciBsYSBjdWFsIGxhIG1lZGlhbmEgc2FsYXJpYWwgZGUgbGFzIHBlcnNvbmFzIGVuIHB1ZXN0byBkZSAqKkRpcmVjY2nDs24qKiBlcyBtZW5vciBhIGxhIGRlIGxhcyBwZXJzb25hcyBlbiBwdWVzdG9zIGRlICoqR2VyZW50ZSoqIHNlIGV4cGxpY2EgcG9yIGVsIHRhbWHDsW8gZGUgbGEgbXVlc3RyYSB5IGxhcyByZXNwdWVzdGFzIHJlY2liaWRhcy4gRW4gbGEgdGFibGEgYSBjb250aW51YWNpw7NuIGluY29ycG9yYSBsYSBjYW50aWRhZCBkZSByZXNwdWVzdGFzIHJlY2liaWRhcyBwYXJhIGNhZGEgdW5vIGRlIGVzdGFzIHBvc2ljaW9uZXMuDQoNCmBgYHtyIHRhYmxhLXB1ZXN0b3N9DQoNCmd0KHJoICU+JSANCiAgICAgc2VsZWN0KHB1ZXN0bywgc3VlbGRvX2RvbGFyKSAlPiUgDQogICAgIGZpbHRlcihwdWVzdG8gIT0gIlBhc2FudGUiKSAlPiUgDQogICAgIG11dGF0ZShwdWVzdG8gPSBmYWN0b3IocHVlc3RvLCBsZXZlbHMgPSBjKCJEaXJlY3RvciIsICJHZXJlbnRlIiwgIkplZmUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZXNwb25zYWJsZSIsICJIUkJQIiwgIkFuYWxpc3RhIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWRtaW5pc3RyYXRpdm8iKSkpICU+JSANCiAgICAgZ3JvdXBfYnkocHVlc3RvKSAlPiUgDQogICAgIHN1bW1hcmlzZShtZWRpYW5hX3NhbGFyaWFsID0gbWVkaWFuKHN1ZWxkb19kb2xhciksIA0KICAgICAgICAgICAgICAgY2FudCA9IG4oKSkNCiAgICAgKSAlPiUgDQogIHRhYl9oZWFkZXIodGl0bGUgPSAiTWVkaWFuYSBzYWxhcmlhbCBwb3IgcHVlc3RvcyIsIA0KICAgICAgICAgICAgIHN1YnRpdGxlID0gIlN1ZWxkb3MgZW4gVSREIikgJT4lIA0KICB0YWJfc291cmNlX25vdGUoc291cmNlX25vdGUgPSBmdWVudGUpICU+JSANCiAgIGZtdF9jdXJyZW5jeShjb2x1bW5zID0gICJtZWRpYW5hX3NhbGFyaWFsIiwgZGVjaW1hbHMgPSAwLA0KICAgICAgICAgICAgICAgc2VwX21hcmsgPSAiLiIsIGRlY19tYXJrID0gIiwiKSAlPiUgDQogIGNvbHNfbGFiZWwocHVlc3RvID0gIlBvc2ljacOzbiIsDQogICAgICAgICAgICAgbWVkaWFuYV9zYWxhcmlhbCA9ICJNZWRpYW5hIFN1ZWxkbyIsDQogICAgICAgICAgICAgY2FudCA9ICJSZXNwdWVzdGFzIikgDQogDQogIA0KDQpgYGANCg0KIyMgU3VlbGRvcyBzZWfDum4gZWwgb3JpZ2VuIGRlbCBjYXBpdGFsDQoNClNpIGRpdmlkaW1vcyBsb3MgZ3LDoWZpY29zIHNlZ8O6biBlbCAqT3JpZ2VuIGRlbCBDYXBpdGFsKiwgcG9kZW1vcyBhcHJlY2lhciBxdWUgZW4gbMOtbmVhcyBnZW5lcmFsZXMsIGxhIG1lZGlhbmEgc2FsYXJpYWwgZW4gZW1wcmVzYXMgbXVsdGluYWNpb25lcyBlcyBtYXlvciBxdWUgZW4gbGFzIGVtcHJlc2FzIG5hY2lvbmFsZXMuDQoNCmBgYHtyIG9yaWdlbl9jYXBpdGFsfQ0KDQpyaCAlPiUgDQogIHNlbGVjdChvcmlnZW5fY2FwaXRhbCwgcHVlc3RvLCBzdWVsZG9fZG9sYXIpICU+JSANCiAgZmlsdGVyKHB1ZXN0byAhPSAiUGFzYW50ZSIsIA0KICAgICAgICAgYmV0d2VlbihzdWVsZG9fZG9sYXIsIHBvZGFfcDA1LCBwb2RhX3A5NSkpICU+JSANCiAgZ3JvdXBfYnkocHVlc3RvLCBvcmlnZW5fY2FwaXRhbCkgJT4lIA0KICBzdW1tYXJpc2UobWVkaWFuYV9zYWxhcmlhbCA9IG1lZGlhbihzdWVsZG9fZG9sYXIpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IG1lZGlhbmFfc2FsYXJpYWwsIHkgPSBwdWVzdG8sIGZpbGwgPSBvcmlnZW5fY2FwaXRhbCkpICsNCiAgZ2VvbV9jb2woKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4PW1lZGlhbmFfc2FsYXJpYWwsIDApLCBoanVzdCA9IDEuMiwgZm9udGZhY2UgPSAiYm9sZCIpLHNpemUgPSAzLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyh2ZXJkZSwgYXp1bCkpICsNCiAgZXN0aWxvdiArDQogIGVqZV94X24gKw0KICBmYWNldF93cmFwKH5vcmlnZW5fY2FwaXRhbCkgKw0KICBsYWJzKHRpdGxlID0gIk1lZGlhbmEgc2FsYXJpYWwgcG9yIHB1ZXN0byBzZWfDum4gb3JpZ2VuIGRlbCBjYXBpdGFsIiwgDQogICAgICAgc3VidGl0bGUgPSAiU3VlbGRvcyBkZSBSUkhIIGVuIFUkUyIsIA0KICAgICAgIHggPSAiIiwgeSA9ICIiLCBmaWxsID0gIiIsIA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQoNCmBgYA0KDQpWZWFtb3MgZXN0b3MgZGF0b3MgZGUgb3RyYSBtYW5lcmE6DQoNCmBgYHtyIHNsb3BlLCAgZmlnLmhlaWdodD05fQ0KbGlicmFyeShDR1BmdW5jdGlvbnMpDQoNCnNsb3BlX2RmIDwtIHJoICU+JSANCiAgc2VsZWN0KHB1ZXN0bywgc3VlbGRvX2RvbGFyLCBvcmlnZW5fY2FwaXRhbCkgJT4lIA0KICBmaWx0ZXIocHVlc3RvICE9ICJEaXJlY3RvciIsIA0KICAgICAgICAgYmV0d2VlbihzdWVsZG9fZG9sYXIsIHBvZGFfcDA1LCBwb2RhX3A5NSkpICU+JSANCiAgZ3JvdXBfYnkocHVlc3RvLCBvcmlnZW5fY2FwaXRhbCkgJT4lIA0KICBzdW1tYXJpc2UobWVkaWFuYV9zYWxhcmlhbCA9IHJvdW5kKG1lZGlhbihzdWVsZG9fZG9sYXIpKSkNCg0KbmV3Z2dzbG9wZWdyYXBoKGRhdGFmcmFtZSA9IHNsb3BlX2RmLA0KICAgICAgICAgICAgICAgIFRpbWVzID0gb3JpZ2VuX2NhcGl0YWwsDQogICAgICAgICAgICAgICAgTWVhc3VyZW1lbnQgPSBtZWRpYW5hX3NhbGFyaWFsLA0KICAgICAgICAgICAgICAgIEdyb3VwaW5nID0gcHVlc3RvLA0KICAgICAgICAgICAgICAgIFRpdGxlID0gIkRpZmVyZW5jaWFzIGVudHJlIHN1ZWxkb3MgZGUgUlJISCBlbiBlbXByZXNhcyBuYWNpb25hbGVzIHkgbXVsdGluYWNpb25hbGVzIiwNCiAgICAgICAgICAgICAgICBTdWJUaXRsZSA9ICJNZWRpYW5hIFNhbGFyaWFsLiBTdWVsZG9zIGVuIFUkUyIsDQogICAgICAgICAgICAgICAgQ2FwdGlvbiA9IGZ1ZW50ZSwgV2lkZXJMYWJlbHMgPSBUDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgKQ0KDQpgYGANCg0KUGFyYSBlbCBhbsOhbGlzaXMgZGUgbG9zIHJ1YnJvcyBkZSBsYSBlbXByZXNhLCB2YW1vcyBhIGZpbHRyYXIgbG9zIDUgcnVicm9zIHF1ZSB0aWVuZW4gbcOhcyByZXNwdWVzdGFzLiBUYW1iacOpbiBlbGltaW5hcmVtb3MgZGVsIGFuw6FsaXNpcyBlbCBwdWVzdG8gZGUgKkRpcmVjdG9yKiBwb3JxdWUgbm8gc2UgZW5jdWVudHJhIHByZXNlbnRlIGVuIHRvZG9zIGxvcyBydWJyb3MuDQoNCmBgYHtyIHJ1YnJvLW9yaWdlbiwgZmlnLmhlaWdodD0xNX0NCnRvcF81X3J1YnJvcyA8LSByaCAlPiUgDQogIHNlbGVjdChydWJybykgJT4lIA0KICBncm91cF9ieShydWJybykgJT4lIA0KICBjb3VudChzb3J0ID0gVFJVRSkgJT4lDQogIGZpbHRlcihydWJybyAhPSAiT3Ryb3MiLCBuID4gMzApICU+JSANCiAgcHVsbCh2YXIgPSBydWJybykNCg0KDQpyaCAlPiUgDQogIHNlbGVjdChydWJybywgb3JpZ2VuX2NhcGl0YWwsIHB1ZXN0bywgc3VlbGRvX2RvbGFyKSAlPiUgDQogIGZpbHRlcihwdWVzdG8gIT0gIlBhc2FudGUiLCBwdWVzdG8gIT0gIkRpcmVjdG9yIiwNCiAgICAgICAgIGJldHdlZW4oc3VlbGRvX2RvbGFyLCBwb2RhX3AwNSwgcG9kYV9wOTUpLA0KICAgICAgICAgcnVicm8gJWluJSB0b3BfNV9ydWJyb3MpICU+JSANCiAgZ3JvdXBfYnkocnVicm8sIHB1ZXN0bywgb3JpZ2VuX2NhcGl0YWwpICU+JSANCiAgc3VtbWFyaXNlKG1lZGlhbmFfc2FsYXJpYWwgPSBtZWRpYW4oc3VlbGRvX2RvbGFyKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBtZWRpYW5hX3NhbGFyaWFsLCB5ID0gcHVlc3RvLCBmaWxsID0gb3JpZ2VuX2NhcGl0YWwpKSArDQogIGdlb21fY29sKCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoeD1tZWRpYW5hX3NhbGFyaWFsLCAwKSwgaGp1c3QgPSAxLjIsIGZvbnRmYWNlID0gImJvbGQiKSxzaXplID0gMywgY29sb3IgPSAid2hpdGUiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGModmVyZGUsIGF6dWwpKSArDQogIGVzdGlsbyArDQogIGVqZV94X24gKw0KICBmYWNldF9ncmlkKHJ1YnJvfm9yaWdlbl9jYXBpdGFsKSArDQogIGxhYnModGl0bGUgPSAiTWVkaWFuYSBzYWxhcmlhbCBwb3IgcHVlc3RvIHNlZ8O6biBvcmlnZW4gZGVsIGNhcGl0YWwiLCANCiAgICAgICBzdWJ0aXRsZSA9ICJTdWVsZG9zIGRlIFJSSEggZW4gVSRTIiwgDQogICAgICAgeCA9ICIiLCB5ID0gIiIsIGZpbGwgPSAiIiwgDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCg0Kcm0odG9wXzVfcnVicm9zKQ0KYGBgDQoNClBhcmEgdmVyIGxhcyBtZWRpYW5hcyBzYWxhcmlhbGVzIGVuIGTDs2xhcmVzIHBvciBydWJyb3MsIHB1ZWRlcyB2ZXIgZXN0YSB0YWJsYS4NCg0KYGBge3IgdGFibGEtcnVicm9zfQ0KDQpkYXRhdGFibGUoDQogIHJoICU+JSANCiAgICBzZWxlY3QocnVicm8sIHN1ZWxkb19kb2xhcikgJT4lIA0KICAgIGdyb3VwX2J5KHJ1YnJvKSAlPiUgDQogICAgc3VtbWFyaXNlKG1lZGlhbmFfc2FsYXJpYWwgPSByb3VuZChtZWRpYW4oc3VlbGRvX2RvbGFyKSksDQogICAgICAgICAgICAgIFJlc3B1ZXN0YXMgPSBuKCkpICU+JSANCiAgICBhcnJhbmdlKC1tZWRpYW5hX3NhbGFyaWFsKSwNCiAgY29sbmFtZXMgPSBjKCJSdWJybyIsICJNZWRpYW5hIFNhbGFyaWFsIiwgIlJlc3B1ZXN0YXMiKSwNCiAgY2FwdGlvbiA9ICJNZWRpYW5hIHNhbGFyaWFsIHBvciBydWJyby4gRW4gVSRTIg0KKQ0KDQpgYGANCg0KIyBTdWVsZG9zIEFyZ2VudGluYQ0KDQpUZW5pZW5kbyBlbiBjdWVudGEgcXVlIGxhIGNhbnRpZGFkIG1heW9yaXRhcmlhIGRlIHJlc3B1ZXN0YXMgY29ycmVzcG9uZGUgYSBwZXJzb25hcyBkZSBBcmdlbnRpbmEsIHZhbW9zIGEgcmVhbGl6YXIgdW4gYW7DoWxpc2lzIGRldGFsbGFkbyBkZSBsb3Mgc3VlbGRvcyBlbiBlc3RlIHBhw61zLg0KDQpDb21vIHByaW1lcm9zIHBhc29zLCB2YW1vcyBhIGZpbHRyYXIgbG9zIGRhdG9zIGNvcnJlc3BvbmRpZW50ZXMgYSBBcmdlbnRpbmEsIHkgbHVlZ28gZmlsdHJhbW9zIGxvcyBzdWVsZG9zIHF1ZSBlc3TDqW4gZW50cmUgbG9zIHBlcmNlbnRpbGVzIDUgeSA5NSwgcGFyYSBlbGltaW5hciB2YWxvcmVzIGVzcHVyaW9zIG8gZXh0cmVtb3MgcXVlIGVuc3VjaWVuIGVsIGFuw6FsaXNpcy4NCg0KVGFtYmnDqW4gZWxpbWluYW1vcyBlbCBwdWVzdG8gZGUgKkRpcmVjdG9yKiBkZWwgYW7DoWxpc2lzIHkgbGFzIHJlc3B1ZXN0YXMgY29uICpHw6luZXJvIGRpdmVyc28qIHBvciBsYSBiYWphIGNhbnRpZGFkIGRlIHJlc3B1ZXN0YXMuDQoNCk90cmEgY29udmVyc2nDs24gcXVlIGhpY2ltb3MgZnVlIHBhc2FyIGxvcyBzdWVsZG9zIGRlIGxhcyBwZXJzb25hcyBxdWUgdHJhYmFqYW4gKnBhcnQtdGltZSogYSB1bmEgZXF1aXZhbGVuY2lhIGZ1bGwtdGltZSBtdWx0aXBsaWNhbmRvIHBvciAxLjUgZWwgc3VlbGRvIGNvbXBsZXRhZG8gZW4gbGEgZW5jdWVzdGEuDQoNCkVuIGVzdGEgaW5zdGFuY2lhLCB0YW1iacOpbiBzaW1wbGlmaWNhbW9zIGxvcyBub21icmVzIGRlIGFsZ3Vub3MgcnVicm9zIHBhcmEgbWVqb3JhciBsYXMgdmlzdWFsaXphY2lvbmVzIGRlIGxvcyByZXN1bHRhZG9zLg0KDQpgYGB7ciBhcmdfcHJlcH0NCg0KcmhfYXIgPC0gcmggJT4lIA0KICBmaWx0ZXIocGFpcyA9PSAiQXJnZW50aW5hIikNCg0KDQojIFBvZGEgZGUgc3VlbGRvcyBlbnRyZSBwZXJjZW50aWxlcyA1IHkgOTUNCm51bWVyaWNvczIgPC0gcmhfYXIgJT4lIA0KICBzZWxlY3RfaWYoaXMubnVtZXJpYykgJT4lIA0KICBwcm9maWxpbmdfbnVtKCkNCg0KcF8wNSA8LSBudW1lcmljb3MyWzgsNl0NCnBfOTUgPC1udW1lcmljb3MyWzgsMTBdDQoNCnJoX2FyIDwtIHJoX2FyICU+JSANCiAgZmlsdGVyKGJldHdlZW4oc3VlbGRvX2JydXRvLCBwXzA1LCBwXzk1KSwNCiAgICAgICAgIHB1ZXN0byAhPSAiRGlyZWN0b3IiLCBwdWVzdG8gIT0gIlBhc2FudGUiLA0KICAgICAgICAgZ2VuZXJvICE9ICJHw6luZXJvIERpdmVyc28iLA0KICAgICAgICAgYW5pb3NfZXhwZXJpZW5jaWEgPCA1MCkgJT4lIA0KICBtdXRhdGUocnVicm8gPSBmY3RfcmVjb2RlKHJ1YnJvLCAiU2VydmljaW9zIGZpbmFuY2llcm9zIiA9ICJTZXJ2aWNpb3MgZmluYW5jaWVyb3M7IHNlZ3Vyb3MiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVHJhbnNwb3J0ZSIgPSAiVHJhbnNwb3J0ZSAoaW5jbHV5ZW5kbyBhdmlhY2nDs24gY2l2aWw7IGZlcnJvY2FycmlsZXMgcG9yIGNhcnJldGVyYSkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJbmQuIEF1dG9tb3RyaXogeSBBdXRvcGFydGlzdGFzIiA9ICJUZXJtaW5hbGVzIGF1dG9tb3RyaWNlcywgZsOhYnJpY2FzIGF1dG9wYXJ0aXN0YXMsIHkgYWZpbmVzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGVjbm9sb2fDrWEiID0gIlRlY25vbG9nw61hcyBkZSBJbmZvcm1hY2nDs24sIFNpc3RlbWFzLCB5IGFmaW5lcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkluZC4gUGV0cm9sZXJhIiA9ICJQZXRyw7NsZW8geSBwcm9kdWNjacOzbiBkZSBnYXM7IHJlZmluYWNpw7NuIGRlIHBldHLDs2xlbyIpLA0KICAgICAgICAgbXVsdGlwbGljYWRvciA9IGlmX2Vsc2UodGlwb19jb250cmF0YWNpb24gPT0gIlBhcnQgdGltZSIsIDEuNSwgMSksDQogICAgICAgICBzdWVsZG9fZnQgPSBzdWVsZG9fYnJ1dG8gKiBtdWx0aXBsaWNhZG9yKQ0KDQoNCmBgYA0KDQojIyBEaXN0cmlidWNpw7NuIGRlIHN1ZWxkb3MgcG9yIHB1ZXN0bw0KDQpFbiBlbCBzaWd1aWVudGUgZ3LDoWZpY28gcG9kZW1vcyB2ZXIgbGEgZGlzdHJpYnVjacOzbiBkZSBsb3Mgc3VlbGRvcyBwb3IgY2FkYSB1bm8gZGUgbG9zIHB1ZXN0b3MuIEVuIGxvcyAqYm94cGxvdHMqIHBvZGVtb3MgdmVyOg0KDQotICAgUHJpbWVyIGN1YXJ0aWw6IExhIHBhcnRlIGluZmVyaW9yIGRlIGxhIGNhamEuDQoNCi0gICBNZWRpYW5hOiBMYSBsw61uZWEgZ3J1ZXNhIGRlbnRybyBkZSBjYWRhIHJlY3TDoW5ndWxvLg0KDQotICAgVGVyY2VyIGN1YXJ0aWw6IExhIHBhcnRlIHN1cGVyaW9yIGRlIGxhIGNhamENCg0KLSAgIE91dGxpZXJzOiBzb24gbG9zIHZhbG9yZXMgZXh0cmVtb3MgaWRlbnRpZmljYWRvcyBjb24gcHVudG9zLg0KDQpgYGB7ciBib3hfcHVlc3Rvc19hcn0NCg0KcmhfYXIgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBwdWVzdG8sIHkgPSBzdWVsZG9fZnQsIGZpbGwgPSBnZW5lcm8pKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gZ2VuZXJvKSArDQogIGVqZV95X24gKw0KICBlc3RpbG9oICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIHN1ZWxkb3MgcG9yIGfDqW5lcm8iLA0KICAgICAgIHN1YnRpdGxlID0gIkRhdG9zIGRlIEFyZ2VudGluYSAtIGVuIEFSJCIsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsIGZpbGwgPSAiR8OpbmVybyIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiI0FFQjZCRiIpKQ0KYGBgDQoNCkhheSB2YXJpYXMgY29zYXMgaW50ZXJlc2FudGVzIHBhcmEgYW5hbGl6YXI6DQoNClNpIG1pcmFtb3MgbGFzIG1lZGlhbmFzIGRlIGxvcyBwdWVzdG9zLCBlbiBsYSBtYXlvcsOtYSBkZSBsb3MgcHVlc3RvcyBoYXkgdW5hIHBhcmlkYWQgcmVsYXRpdmEsIGNvbW8gcG9yIGVqZW1wbG8gZW4gKkhSQlAsIEplZmUqIHkgKkdlcmVudGVzLiogVGFtcG9jbyBoYXkgbXVjaGEgZGlmZXJlbmNpYSBlbiBsYSBtZWRpYW5hIGRlIGxvcyAqQWRtaW5pc3RyYXRpdm9zKi4gRW4gbGFzIHBvc2ljaW9uZXMgZGUgKkFuYWxpc3RhLCogeSAqUmVzcG9uc2FibGUqIGxvcyB2YXJvbmVzIHRpZW5lbiB1bmEgbWVkaWFuYSBzYWxhcmlhbCB1biBwb2NvIG3DoXMgYWx0YS4NCg0KUGVybyBsbyBtw6FzIGludGVyZXNhbnRlIHNvbiBsYXMgKipkaXN0cmlidWNpb25lcyBkZSBsb3Mgc3VlbGRvcyoqLiBNaXJlbW9zIHBvciBlamVtcGxvIGxvcyBKZWZlcy4gTGEgbWVkaWFuYSBlcyBwcsOhY3RpY2FtZW50ZSBsYSBtaXNtYSwgcGVybyAqZWwgdGFtYcOxbyBkZSBsYSBwYXJ0ZSBpbmZlcmlvciBkZSBsYSBjYWphIGVzIG11Y2hvIG3DoXMgYW1wbGlhIGVuIGVsIGNhc28gZGUgbGFzIG11amVyZXMsKiBtaWVudHJhcyBxdWUgbGEgcGFydGUgc3VwZXJpb3IgZGUgbGEgY2FqYSBlcyBtw6FzIGFtcGxpYSBlbiBlbCBjYXNvIGRlIGxvcyB2YXJvbmVzLg0KDQpFc3RvIG5vcyBkYSBsYSBwYXV0YSBxdWUgc2kgYmllbiBlbCB2YWxvciBxdWUgZGl2aWRlIGEgbGEgbWl0YWQgbGEgbXVlc3RyYSBkZSBob21icmVzIHkgbXVqZXJlcyAobGEgbWVkaWFuYSkgZXMgbXV5IHBhcmVqbywgZWwgcmFuZ28gZGUgbG9zIHN1ZWxkb3MgZGUgbGFzIEplZmFzIGxsZWdhIGEgdmFsb3JlcyBtw6FzIGJham9zIGxvIHF1ZSBpbXBsaWNhIHF1ZSBlbCBwaXNvIGVzIG3DoXMgYmFqbyBwYXJhIG11amVyZXMgcXVlIHBhcmEgaG9tYnJlcy4gTWllbnRyYXMgcXVlIGRlIGxhIG1lZGlhbmEgKmhhY2lhIGFycmliYSogZXMgbcOhcyBhbXBsaWEgZW4gZWwgY2FzbyBkZSBsb3MgaG9tYnJlcyBlbiBjb21wYXJhY2nDs24gY29uIGxhcyBtdWplcmVzLg0KDQpFbiBlbCDDum5pY28gcHVlc3RvIHF1ZSBoYXkgdW5hIGRpc3RyaWJ1Y2nDs24gc2ltaWxhciBlbnRyZSBhbWJvcyBnw6luZXJvcyBlcyBlbiBlbCBjYXNvIGRlIGxvcyBIUkJQLCBwZXJvIGVuIGVsIHJlc3RvIGRlIGxvcyBjYXNvcyB2ZW1vcyBxdWUgbGEgYXNpbWV0csOtYSBxdWUgZGVzY3JpYmltb3MgYW50ZXJpb3JtZW50ZSBzZSByZXBpdGUuDQoNClBvZGVtb3MgdmlzdWFsaXphciBlbCBnYXAgc2FsYXJpYWwgZW4gZXN0ZSBncsOhZmljbzoNCg0KYGBge3J9DQpnYXBfc2FsYXJpYWwgPC0gcmhfYXIgJT4lIA0KICBzZWxlY3QoZ2VuZXJvLCBwdWVzdG8sIHN1ZWxkb19mdCkNCg0KDQpnYXBfc2FsYXJpYWwgPC0gZ2FwX3NhbGFyaWFsICU+JSANCiAgZmlsdGVyKCFpcy5uYShwdWVzdG8pKSAlPiUgDQogIG11dGF0ZShjdWVudGEgPSAxKSANCg0KDQpicmVjaGEgPC0gZ2FwX3NhbGFyaWFsICU+JSANCiAgZmlsdGVyKGdlbmVybyAlaW4lIGMoIkZlbWVuaW5vIiwgIk1hc2N1bGlubyIpLCANCiAgICAgICAgIHB1ZXN0byAlaW4lIGMoIkRpcmVjdG9yIiwgIkdlcmVudGUiLCJKZWZlIiwgIkhSQlAiLCJSZXNwb25zYWJsZSIsICJBbmFsaXN0YSIsICJBZG1pbmlzdHJhdGl2byIpKSAlPiUgDQogIG11dGF0ZShwdWVzdG8gPSBmYWN0b3IocHVlc3RvLCBsZXZlbHMgPSBjKCJBZG1pbmlzdHJhdGl2byIsIkFuYWxpc3RhIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIUkJQIiwgIlJlc3BvbnNhYmxlIiwgIkplZmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR2VyZW50ZSIsIkRpcmVjdG9yIiApKSkgJT4lIA0KICBncm91cF9ieShnZW5lcm8sIHB1ZXN0bykgJT4lIA0KICBzdW1tYXJpc2UobWVkaWFfc2FsYXJpYWwgPSBtZWFuKHN1ZWxkb19mdCkpDQoNCg0KDQpicmVjaGFfZ3JhZiA8LSBicmVjaGEgJT4lIA0KICBwaXZvdF93aWRlciguLCBuYW1lc19mcm9tID0gZ2VuZXJvLCB2YWx1ZXNfZnJvbSA9IG1lZGlhX3NhbGFyaWFsKSAlPiUgDQogIG11dGF0ZShicmVjaGEgPSBwZXJjZW50KChNYXNjdWxpbm8tRmVtZW5pbm8pL01hc2N1bGlubywgMSksDQogICAgICAgICB4ID0gKE1hc2N1bGlubyArIEZlbWVuaW5vKS8yKQ0KDQpnZ3Bsb3QoYnJlY2hhX2dyYWYsIA0KICAgICAgIGFlcyh4ID0gRmVtZW5pbm8sIHhlbmQgPSBNYXNjdWxpbm8sIHkgPSBwdWVzdG8sIA0KICAgICAgICAgICBncm91cCA9IHB1ZXN0bywgbGFiZWwgPSBicmVjaGEpKSArDQogIGdlb21fZHVtYmJlbGwoY29sb3IgPSAiIzgwODA4MCIsDQogICAgICAgICAgICAgICAgc2l6ZV94ID0gMywgc2l6ZV94ZW5kID0gMywNCiAgICAgICAgICAgICAgICBjb2xvdXJfeCA9IGNvbG9yZXNbMV0sDQogICAgICAgICAgICAgICAgY29sb3VyX3hlbmQgPSBjb2xvcmVzWzJdKSArDQogIGdlb21fdGV4dChkYXRhID0gYnJlY2hhX2dyYWYsIA0KICAgICAgICAgICAgYWVzKHgsIHB1ZXN0bywgbGFiZWwgPSBicmVjaGEpLCBudWRnZV95ID0gLjIpICsNCiAgbGFicyh0aXRsZSA9ICJCcmVjaGEgc2FsYXJpYWwgcG9yIHB1ZXN0b3MgZGUgUlJISCIsDQogICAgICAgc3VidGl0bGUgPSAiU3VlbGRvcyBwcm9tZWRpb3MgZW4gQXJnZW50aW5hIiwNCiAgICAgICB4ID0gIiIsDQogICAgICAgeSA9IE5VTEwsIA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZWplX3hfbiArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcmVzKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUocGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI2ZiZmNmYyIpLA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJSb2JvdG8iKSkNCmBgYA0KDQpWZWFtb3MgZWwgc3VlbGRvIHByb21lZGlvIGVuIGNhZGEgdW5vIGRlIGxvcyBydWJyb3MuDQoNCiMjIEFuw6FsaXNpcyBwb3IgcnVicm9zDQoNCkVuIGVsIGdyw6FmaWNvIGEgY29udGludWFjacOzbiBwb2RlbW9zIHZlciBsb3Mgc3VlbGRvcyBwcm9tZWRpb3MgcG9yIHJ1YnJvLCB0ZW5pZW5kbyBlbiBjdWVudGEgYSBsb3MgcnVicm9zIGNvbiBtw6FzIGRlIDEyIHJlc3B1ZXN0YXMuDQoNCmBgYHtyIHJ1YnJvc19hcn0NCg0KcnVicm9fYXIgPC0gcmhfYXIgJT4lIA0KICBzZWxlY3QocnVicm8sIHN1ZWxkb19mdCkgJT4lIA0KICBncm91cF9ieShydWJybykgJT4lIA0KICBzdW1tYXJpc2UobWVkaWFfc3VlbGRvID0gbWVhbihzdWVsZG9fZnQpLA0KICAgICAgICAgICAgcmVzcHVlc3RhcyA9IG4oKSkgJT4lIA0KICBhcnJhbmdlKC1yZXNwdWVzdGFzKQ0KDQp0b3BfcnVicm9zIDwtIHJ1YnJvX2FyICU+JSANCiAgZmlsdGVyKHJ1YnJvICE9ICJPdHJvcyIsIHJlc3B1ZXN0YXMgPiAxNSkgJT4lIA0KICBwdWxsKHJ1YnJvKQ0KDQpydWJyb19hciAlPiUgDQogIGZpbHRlcihyZXNwdWVzdGFzID4gMTIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gbWVkaWFfc3VlbGRvLCB5ID0gcmVvcmRlcihydWJybywgbWVkaWFfc3VlbGRvKSkpICsNCiAgZ2VvbV9jb2woZmlsbCA9IGF6dWwpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKHg9bWVkaWFfc3VlbGRvLCAwKSwgaGp1c3QgPSAxLjUpLHNpemUgPSAzLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgbGFicyh0aXRsZSA9ICJQcm9tZWRpbyBzYWxhcmlhbCBwb3IgcnVicm8iLA0KICAgICAgIHN1YnRpdGxlID0gIkRhdG9zIGRlIEFyZ2VudGluYSAtIGVuIEFSJCIsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICBlc3RpbG92ICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KDQpgYGANCg0KQWhvcmEgY29tcGFyZW1vcyBsb3Mgc3VlbGRvcyBwb3IgcnVicm9zIHkgZ8OpbmVyb3MuIEFxdcOtIHBvZHJlbW9zIGFwcmVjaWFyIGxhcyBkaWZlcmVuY2lhcyBlbnRyZSBsb3Mgc3VlbGRvcyBwcm9tZWRpb3MgZGUgbG9zIGhvbWJyZXMgeSBtdWplcmVzIGVuIGNhZGEgcnVicm8uDQoNCmBgYHtyIHJ1YnJvX2dlbmVyb19hcn0NCg0KcmhfYXIgJT4lIA0KICBmaWx0ZXIocnVicm8gJWluJSB0b3BfcnVicm9zKSAlPiUgDQogIHNlbGVjdChydWJybywgc3VlbGRvX2Z0LCBnZW5lcm8pICU+JSANCiAgZ3JvdXBfYnkocnVicm8sIGdlbmVybykgJT4lIA0KICBzdW1tYXJpc2UobWVkaWFfc3VlbGRvID0gbWVhbihzdWVsZG9fZnQpLA0KICAgICAgICAgICAgcmVzcHVlc3RhcyA9IG4oKSkgJT4lIA0KICBhcnJhbmdlKC1yZXNwdWVzdGFzKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IG1lZGlhX3N1ZWxkbywgeSA9IHJlb3JkZXIocnVicm8sIG1lZGlhX3N1ZWxkbyksIGZpbGwgPSBnZW5lcm8pKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoeD1tZWRpYV9zdWVsZG8sMCksIGhqdXN0ID0gMS40LCB2anVzdCA9IDAuMyksDQogICAgICAgICAgICBzaXplID0gMywgY29sb3IgPSAid2hpdGUiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gLjkpKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGdlbmVybykgKw0KICBsYWJzKHRpdGxlID0gIlByb21lZGlvIHNhbGFyaWFsIHBvciBydWJybyB5IGfDqW5lcm8iLA0KICAgICAgIHN1YnRpdGxlID0gIkRhdG9zIGRlIEFyZ2VudGluYSAtIGVuIEFSJCIsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsIGZpbGwgPSAiR8OpbmVybyIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICBlamVfeF9uICsNCiAgZXN0aWxvdiArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCkpDQoNCmBgYA0KDQpQb3Igw7psdGltbywgYW5hbGljZW1vcyBsb3Mgc3VlbGRvcyBkZSBsb3MgNiBydWJyb3MgY29uIG1heW9yIGNhbnRpZGFkIGRlIHJlc3B1ZXN0YXMsIHkgdmlzdWFsaWNlbW9zIGxhcyBkaXN0cmlidWNpb25lcyBkZSBsb3Mgc3VlbGRvcyBwb3IgcHVlc3RvIHkgZ8OpbmVyby4gRW4gZXN0ZSBncsOhZmljbyBwb2RlbW9zIHZlciBsb3MgY3VhcnRpbGVzIGRlbGltaXRhbmRvIGxhcyB6b25hcyBzb21icmVhZGFzLCB5IGxhIG1lZGlhbmEgY29uIGVsIHB1bnRvIGdyaXMuIExvcyBwdW50b3MgdmlvbGV0YXMgeSB2ZXJkZXMgcmVwcmVzZW50YW4gYSBsYXMgbXVqZXJlcyB5IGxvcyBob21icmVzIHJlc3BlY3RpdmFtZW50ZSBlbiBjYWRhIHVubyBkZSBsb3MgcHVlc3Rvcy4NCg0KYGBge3IgZGlzdF9ydWJyb19nZW4sIG91dC53aWR0aD0iOTAlIiwgZmlnLmhlaWdodD03fQ0KbGlicmFyeShnZ2Vjb25vZGlzdCkNCg0KcmhfYXIgJT4lIA0KICBmaWx0ZXIoZ2VuZXJvICE9ICJHw6luZXJvIERpdmVyc28iLA0KICAgICAgICAgcHVlc3RvICE9ICJEaXJlY3RvciIsDQogICAgICAgICBydWJybyAlaW4lIGMoIlRlY25vbG9nw61hIiwgIlNlcnZpY2lvcyBkZSBzYWx1ZCIsICJDb21lcmNpbyIsDQogICAgICAgICAgICAgICAgICAgICAgIkFsaW1lbnRhY2nDs247IGJlYmlkYXM7IHRhYmFjbyIsDQogICAgICAgICAgICAgICAgICAgICAgIlNlcnZpY2lvcyBkZSBjb25zdWx0b3LDrWEiLCAiQ29uc3RydWNjacOzbiIpKSAgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBwdWVzdG8sIHkgPSBzdWVsZG9fYnJ1dG8pKSArDQogIGdlb21fZWNvbm9kaXN0KHdpZHRoID0gMC41KSArDQogIGdlb21fcG9pbnQoYWVzKHkgPSBzdWVsZG9fYnJ1dG8sIGNvbG9yID0gZ2VuZXJvKSwgYWxwaGEgPSAwLjMsDQogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjI1KSkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gZ2VuZXJvKSArDQogIGVqZV95X24gKw0KICBjb29yZF9mbGlwKCkgKw0KICBmYWNldF93cmFwKH5ydWJybywgbmNvbCA9IDIpICsNCiAgZXN0aWxvdiArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnVjacOzbiBzYWxhcmlhbCBwb3IgcHVlc3RvIHkgcnVicm8iLA0KICAgICAgIHN1YnRpdGxlID0gIkRhdG9zIGRlIEFyZ2VudGluYSAtIGVuIEFSJCIsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsIGNvbG9yID0gIkfDqW5lcm8iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpDQoNCmBgYA0KDQojIyBSZWxhY2lvbmVzIGNvbiBTdWVsZG8gQnJ1dG8NCg0KRW4gZXN0YSBzZWNjacOzbiBkZWwgYW7DoWxpc2lzIGJ1c2NhbW9zIGlkZW50aWZpY2FyIGN1w6FsZXMgc29uIGxvcyBmYWN0b3JlcyBxdWUgaW5mbHV5ZW4gZW4gbG9zIGluZ3Jlc29zIChpbmRlcGVuZGllbnRlbWVudGUgZGUgbGEgcG9zaWNpw7NuKSwgYXPDrSBxdWUgZW1wZXphbW9zIGEgZXhwbG9yYXIgbG9zIGRhdG9zLg0KDQpMYSBwcmltZXJhIHByZWd1bnRhIHF1ZSBub3MgaGljaW1vcyBmdWUgc2kgbG9zIGHDsW9zIGRlIHRyYXllY3RvcmlhIGluZmx1eWVuIGVuIGVsIHN1ZWxkby4gTnVlc3RyYSBoaXDDs3Rlc2lzIGVzIHF1ZSBhIG1heW9yIGNhbnRpZGFkIGRlIGHDsW9zIGRlIGV4cGVyaWVuY2lhLCBtYXlvciBpYmEgYSBzZXIgZWwgaW5ncmVzby4NCg0KTG8gcXVlIHZhbW9zIGEgdmVyIGVuIGVsIHNpZ3VpZW50ZSBncsOhZmljbyBkZSBkaXNwZXJzacOzbiwgZXMgZW4gZWwgZWplIGhvcml6b250YWwsIGxvcyBhw7FvcyBkZSBleHBlcmllbmNpYSwgeSBlbiBlbCBlamUgdmVydGljYWwsIGVsIHN1ZWxkbyBicnV0byBleHByZXNhZG8gZW4gcGVzb3MgYXJnZW50aW5vcy4gTHVlZ28sIHZhbW9zIGEgZ3JhZmljYXIgdW5hIHJlY3RhLCBxdWUgbm9zIHZhIGEgaW5kaWNhciBsYSAqZnVlcnphKiBkZSBlc2EgcmVsYWNpw7NuLg0KDQojIyMgUmVsYWNpw7NuIGVudHJlIGHDsW9zIGRlIGV4cGVyaWVuY2lhIHkgc3VlbGRvIGJydXRvDQoNCmBgYHtyIHJlZ19saW5lYWxfMX0NCmxtX3JoIDwtIGxtKHN1ZWxkb19mdCB+IGFuaW9zX2V4cGVyaWVuY2lhLCBkYXRhID0gcmhfYXIpDQoNCmxtX2hyX3Jlc3VsdHMgPC0gc3VtbWFyeShsbV9yaCkNCg0KbG1fcmhfcjIgPC0gcm91bmQobG1faHJfcmVzdWx0c1tbInIuc3F1YXJlZCJdXSwzKQ0KDQpnZ3Bsb3QocmhfYXIsIGFlcyh4PWFuaW9zX2V4cGVyaWVuY2lhLCB5ID0gc3VlbGRvX2Z0KSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gIiMxRkMzQUEiLCBhbHBoYSA9IDAuNCwgc2l6ZSA9IDIpICsgDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiUm9ib3RvIikpICsNCiAgbGFicyh0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgc3VlbGRvIHkgYcOxb3MgZGUgZXhwZXJpZW5jaWEiLA0KICAgICAgIHggPSAiQcOxb3MgZGUgRXhwZXJpZW5jaWEiLA0KICAgICAgIHkgPSAiU3VlbGRvIGJydXRvIChBUiQpIiwgDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICBlamVfeV9uICsNCiAgZ2VvbV90ZXh0KGFlcyh4PS1JbmYsIHk9SW5mLCBoanVzdD0wLCB2anVzdD0xLCBsYWJlbD0gcGFzdGUwKCJSMiA9ICIsIGxtX3JoX3IyKSkpIA0KDQpgYGANCg0KRW4gZWwgZ3LDoWZpY28gcG9kZW1vcyBhcHJlY2lhciB1bmEgcmVjdGEgcXVlIHZhIGNyZWNpZW5kbyBlZmVjdGl2YW1lbnRlOiBhIG1lZGlkYSBxdWUgbm9zIG1vdmVtb3MgbcOhcyBoYWNpYSBsYSBkZXJlY2hhLCBsYSByZWN0YSB2YSBzdWJpZW5kby4gUGVybyBlbCAkUl4yJCA9IGByIGxtX3JoX3IyYCBub3MgaW5kaWNhIGN1w6FudG8gZXhwbGljYSBsb3MgYcOxb3MgZGUgZXhwZXJpZW5jaWEgc29icmUgZWwgc3VlbGRvIGJydXRvLCBvIGRpY2hvIGRlIG90cmEgbWFuZXJhLCBlbiBxdcOpIG1lZGlkYSBpbmZsdXllIGxhIHZhcmlhYmxlIHggKGHDsW9zIGRlIGV4cGVyaWVuY2lhKSwgc29icmUgbGEgdmFyaWFibGUgeSAoc3VlbGRvIGJydXRvKS4gVW5hIGRlZmluaWNpw7NuIG3DoXMgcHJlY2lzYSBkZSBlc3RlIHZhbG9yIGNvbm9jaWRvIGNvbW8gKipDb2VmaWNpZW50ZSBkZSBEZXRlcm1pbmFjacOzbioqIGVzIGxhIHByb3BvcmNpw7NuIGRlIGxhIHZhcmlhbnphIHRvdGFsIGRlIGxhIHZhcmlhYmxlIGV4cGxpY2FkYSBwb3IgbGEgcmVncmVzacOzbi4NCg0KRXN0ZSB2YWxvciBwdWVkZSBlc3RhciBlbnRyZSAwIHkgMSwgbWllbnRyYXMgbcOhcyBjZXJjYSBkZSAwIGVzdMOhIG1lbm9yIGVzIGxhIHJlbGFjacOzbiwgeSBtaWVudHJhcyBtw6FzIGNlcmNhIGRlIDEgZXN0w6kgZWwgcmVzdWx0YWRvLCBpbmRpY2EgcXVlIGxhIHJlZ3Jlc2nDs24gZXhwbGljYSBsYSB2YXJpYWJpbGlkYWQgZGUgbGEgdmFyaWFibGUgZGUgcmVzcHVlc3RhLiBFcyBwb3IgZXNvIHF1ZSBlc3RlICRSXjIkID0gYHIgbG1fcmhfcjJgIG5vcyBpbmRpY2EgcXVlIGxvcyBhw7FvcyBkZSBleHBlcmllbmNpYSBubyB0aWVuZW4gbXVjaGEgaW5mbHVlbmNpYSBlbiBsb3Mgc3VlbGRvcy4NCg0KIyMjIFJlbGFjacOzbiBlbnRyZSBhw7FvcyBkZSBleHBlcmllbmNpYSB5IHN1ZWxkbyBicnV0byBwb3IgcHVlc3RvLg0KDQpEYWRvIHF1ZSBlbiBlbCBncsOhZmljbyBhbnRlcmlvciB0ZW5lbW9zIG1lemNsYWRvcyBsb3Mgc3VlbGRvcyBkZSBhZG1pbmlzdHJhdGl2b3MsIGFuYWxpc3RhcywgamVmZXMgeSBnZXJlbnRlcywgZGVjaWRpbW9zIGFuYWxpemFyIGxhIHJlbGFjacOzbiBlbnRyZSBsb3MgYcOxb3MgZGUgZXhwZXJpZW5jaWEgeSBlbCBzdWVsZG8gYnJ1dG8gcG9yIGNhZGEgdW5vIGRlIGxvcyBwdWVzdG9zIHBvciBzZXBhcmFkby4NCg0KYGBge3IgcmVnX2xpbmVhbF8yLCBvdXQud2lkdGg9IjkwJSJ9DQpsaWJyYXJ5KGdncG1pc2MpDQoNCm1pLmZvcm11bGEgPC0geSB+IHgNCg0KZ2dwbG90KHJoX2FyLCBhZXMoeD1hbmlvc19leHBlcmllbmNpYSwgeSA9IHN1ZWxkb19mdCkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICIjMUZDM0FBIiwgYWxwaGEgPSAwLjQsIHNpemUgPSAyKSArIA0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0gbWkuZm9ybXVsYSwgc2UgPSBGQUxTRSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJSb2JvdG8iKSkgKw0KICBsYWJzKHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBzdWVsZG8geSBhw7FvcyBkZSBleHBlcmllbmNpYSIsDQogICAgICAgeCA9ICJBw7FvcyBkZSBFeHBlcmllbmNpYSIsDQogICAgICAgeSA9ICIiLCANCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKSArDQogIGVqZV95X24gKw0KICBzdGF0X3BvbHlfZXEoZm9ybXVsYSA9IG1pLmZvcm11bGEsIA0KICAgICAgICAgICAgICAgYWVzKGxhYmVsID0gcGFzdGUoLi5yci5sYWJlbC4uLCBzZXAgPSAifn5+IikpLCANCiAgICAgICAgICAgICAgIHBhcnNlID0gVFJVRSkgKw0KICBmYWNldF93cmFwKH5wdWVzdG8pDQoNCmBgYA0KDQpDb21vIHBvZGVtb3MgYXByZWNpYXIgZW4gbG9zICRSXjIkIGRlIGNhZGEgZ3LDoWZpY28uIExvcyBhw7FvcyBkZSB0cmF5ZWN0b3JpYSBpbmZsdXllbiBtdXkgcG9jbyBlbiBsb3Mgc3VlbGRvcyBkZSBjYWRhIHVubyBkZSBsb3MgcHVlc3Rvcy4NCg0KQWhvcmEgYmllbiwgbGEgcHJlZ3VudGEgZXMsICrCv2N1w6FsIGVzIGxhIHZhcmlhYmxlIHF1ZSBtw6FzIGluZmx1eWUgZW4gZWwgc3VlbGRvIGVuIFJlY3Vyc29zIEh1bWFub3M/LiogVHJpc3RlbWVudGUsIGxhIHJlc3B1ZXN0YSBubyBzb3JwcmVuZGUuDQoNCmBgYHtyfQ0KZ2dwbG90KHJoX2FyLCBhZXMoeCA9IGdlbmVybywgeSA9IHN1ZWxkb19mdCwgZmlsbCA9IGdlbmVybykpICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICBlamVfeV9uICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG9oICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIHNhbGFyaWFsIHBvciBnw6luZXJvIiwNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIkfDqW5lcm8iLCANCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKQ0KYGBgDQoNCiMgRWR1Y2FjacOzbg0KDQpFbiBlc3RhIHNlY2Npw7NuIHF1ZXJlbW9zIGluZGFnYXIgc2kgaGF5IHJlbGFjacOzbiBlbnRyZSBsYSBmb3JtYWNpw7NuIHkgbGEgcmVtdW5lcmFjacOzbiwgeSBzaSBpbXBhY3RhIHRhbWJpw6luIGVsIHRpcG8gZGUgdW5pdmVyc2lkYWQsIHDDumJsaWNhIG8gcHJpdmFkYSwgZW4gbGEgcmVtdW5lcmFjacOzbiB5IHBvc2ljacOzbi4gUHJpbWVybyB2ZWFtb3MgZW50cmUgbG9zIGRpc3RpbnRvcyBwYcOtc2VzIGNvbW8gc2UgZGlzdHJpYnV5ZSBsYSBtdWVzdHJhIGVudHJlIHByb2Zlc2lvbmFsZXMgcHJvdmVuaWVudGVzIGRlIHVuaXZlcnNpZGFkZXMgcMO6YmxpY2FzIHkgcHJpdmFkYXMuDQoNCkRhZG8gcXVlIHRlbmVtb3MgcmVsYXRpdmFtZW50ZSBwb2NhcyByZXNwdWVzdGFzIGRlIG90cm9zIHBhw61zZXMgcXVlIG5vIHNlYW4gQXJnZW50aW5hLCBubyBwb2RlbW9zIHNhY2FyIG5pbmd1bmEgY29uY2x1c2nDs24gc2VyaWEsIHPDs2xvIG1lbmNpb25hciBxdWUgZW4gQXJnZW50aW5hLCBoYXkgdW5hIHZpcnR1YWwgcGFyaWRhZCBlbnRyZSBsb3MgZXN0dWRpYW50ZXMgeSBncmFkdWFkb3MgZGUgdW5pdmVyc2lkYWRlcyBww7pibGljYXMgeSBwcml2YWRhcy4gUG9zdGVyaW9ybWVudGUgYW5hbGl6YXJlbW9zIGxhIHNpdHVhY2nDs24gcG9yIHJlZ2lvbmVzIGRlbnRybyBkZWwgcGHDrXMuDQoNCkxhcyBwcm9wb3JjaW9uZXMgZGUgcmVzcHVlc3RhcyBzZWfDum4gYWwgdGlwbyBkZSB1bml2ZXJzaWRhZCBxdWUgYXNpc3RpZXJvbiBsb3MgcGFydGljaXBhbnRlcyBkZSBsYSBlbmN1ZXN0YSBlcyBsYSBzaWd1aWVudGU6DQoNCmBgYHtyIHRpcG9fdW5pdmVyc2lkYWQsIGZpZy5zaG93PSJob2xkIiwgb3V0LndpZHRoPSI1MCUiLCBmaWcuYWxpZ24gPSAiZGVmYXVsdCJ9DQpyaCAlPiUgDQogIHNlbGVjdChwYWlzLCB0aXBvX3VuaXZlcnNpZGFkKSAlPiUgDQogIGdncGxvdChhZXMoeSA9IHBhaXMsIGZpbGwgPSB0aXBvX3VuaXZlcnNpZGFkKSkgKw0KICAgICAgICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKyANCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyhncmlzLCB2ZXJkZSwgYXp1bCkpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIHJlc3B1ZXN0YXMgcG9yIHRpcG8gZGUgdW5pdmVyc2lkYWQgcG9yIHBhw61zIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlLCANCiAgICAgICB4ID0gIiIsIHkgPSAiIikgKw0KICBlc3RpbG8gKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCg0KZWR1YyA8LSByaCAlPiUgDQogIHNlbGVjdCh0aXBvX3VuaXZlcnNpZGFkKSAlPiUgIA0KICBncm91cF9ieSh0aXBvX3VuaXZlcnNpZGFkKSAlPiUgDQogIHN1bW1hcmlzZSAobiA9IG4oKSkgJT4lIA0KICBtdXRhdGUoZnJlcSA9IG4vc3VtKG4pKSAlPiUgDQogIGFycmFuZ2UoLW4pDQoNCiMgQ29tcHV0ZSB0aGUgY3VtdWxhdGl2ZSBwZXJjZW50YWdlcyAodG9wIG9mIGVhY2ggcmVjdGFuZ2xlKQ0KZWR1YyR5bWF4IDwtIGN1bXN1bShlZHVjJGZyZXEpDQoNCiMgQ29tcHV0ZSB0aGUgYm90dG9tIG9mIGVhY2ggcmVjdGFuZ2xlDQplZHVjJHltaW4gPC0gYygwLCBoZWFkKGVkdWMkeW1heCwgbj0tMSkpDQoNCiMgQ29tcHV0ZSBsYWJlbCBwb3NpdGlvbg0KZWR1YyRsYWJlbFBvc2l0aW9uIDwtIChlZHVjJHltYXggKyBlZHVjJHltaW4pIC8gMg0KDQojIENvbXB1dGUgYSBnb29kIGxhYmVsDQplZHVjJGxhYmVsIDwtIHBhc3RlMChlZHVjJHRpcG9fdW5pdmVyc2lkYWQsICJcbiBDYW50OiAiLCBlZHVjJG4pDQoNCiMgTWFrZSB0aGUgcGxvdA0KZ2dwbG90KGVkdWMsIGFlcyh5bWF4PXltYXgsIHltaW49eW1pbiwgeG1heD00LCB4bWluPTMsIGZpbGw9dGlwb191bml2ZXJzaWRhZCkpICsNCiAgZ2VvbV9yZWN0KCkgKw0KICBjb29yZF9wb2xhcih0aGV0YT0ieSIpICsgIyBUcnkgdG8gcmVtb3ZlIHRoYXQgdG8gdW5kZXJzdGFuZCBob3cgdGhlIGNoYXJ0IGlzIGJ1aWx0IGluaXRpYWxseQ0KICB4bGltKGMoMiwgNCkpICsjIFRyeSB0byByZW1vdmUgdGhhdCB0byBzZWUgaG93IHRvIG1ha2UgYSBwaWUgY2hhcnQNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyhncmlzLCB2ZXJkZSwgYXp1bCkpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiUm9ib3RvIikpICsNCiAgbGFicyh0aXRsZSA9ICJUaXBvIGRlIFVuaXZlcnNpZGFkIiwNCiAgICAgICBmaWxsID0gIlRpcG8gZGUgVW5pdmVyc2lkYWQiLCANCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJsZWZ0IikNCmBgYA0KDQpMYXMgcHJpbmNpcGFsZXMgY2FycmVyYXMgZGUgbGFzIHBlcnNvbmFzIHF1ZSByZXNwb25kaWVyb24gc29uOg0KDQpgYGB7ciBjYXJyZXJhc30NCmNhcnJlcmFzIDwtIHJoICU+JSANCiAgc2VsZWN0KG5pdmVsX2Zvcm1hY2lvbiwgY2FycmVyYV9ncmFkbywgdGlwb191bml2ZXJzaWRhZCwgdHJhYmFqbywgDQogICAgICAgICBzdWVsZG9fYnJ1dG8sIHB1ZXN0bywgZnVuY2lvbl9yaCwgcGFpcywgZ2VuZXJvKSAlPiUgDQogIG11dGF0ZShjYXJyZXJhX2dyYWRvID0gZmFjdG9yKGNhcnJlcmFfZ3JhZG8pKQ0KDQpjYXJyZXJhcyA8LSBjYXJyZXJhcyAlPiUgDQogIG11dGF0ZShjYXJyZXJhX2dyYWRvID0gZmN0X2NvbGxhcHNlKGNhcnJlcmFfZ3JhZG8sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWJvZ2Fjw61hIiA9IGMoIkFib2dhY8OtYSwgRXNjcmliYW7DrWEsIExpYyBlbiBSUkhIIikpLA0KICAgICAgICAgY2FycmVyYV9ncmFkbyA9IGZjdF9jb2xsYXBzZShjYXJyZXJhX2dyYWRvLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFkbWluaXN0cmFjacOzbiBkZSBFbXByZXNhcyIgPSBjKCJMaWMgZW4gQWRtaW5pc3RyYWNpb24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWRtaW5pc3RyYWNpw7NuIHkgc2lzdGVtYXMiLCAiTGljIEFkbWluaXN0cmFjaW9uIC0gQ29udGFkb3IgUHVibGljbyAtIEFib2dhZG8gZW4gY3Vyc28iKSksDQogICAgICAgICBjYXJyZXJhX2dyYWRvID0gZmN0X2NvbGxhcHNlKGNhcnJlcmFfZ3JhZG8sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29udGFkb3IgUMO6YmxpY28iID0gYygiRWNvbm9taWEiLCAiRWNvbm9tw61hIiwgIkNvbnRhZG9yIFDDumJsaWNvL0xpYy4gRW4gTGV0cmFzIiwgIkVjb25vbWlhIHkgUlIuSEgiKSksDQogICAgICAgICBjYXJyZXJhX2dyYWRvID0gZmN0X2NvbGxhcHNlKGNhcnJlcmFfZ3JhZG8sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29tdW5pY2FjacOzbiBTb2NpYWwiID0gYygiQ2FvbXVuaWNhY2lvbiBzb2NpYWwgbWUgZXNwZWNpYWxpY2UgZW4gUlJISCIsICAiQ29tdW5pY2FjacOzbiIsIkNvbXVuaWNhY2nDs24gc29jaWFsIiwgIkxpYy4gZW4gQ2llbmNpYXMgZGUgbGEgQ29tdW5pY2FjacOzbiIpKSwgDQogICAgICAgICBjYXJyZXJhX2dyYWRvID0gZmN0X2NvbGxhcHNlKGNhcnJlcmFfZ3JhZG8sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUlJISCAvIFJSTEwgLyBSUlRUIiA9IGMoIkVzdHVkacOpIGVuIGxhIFVuaXZlcnNpZGFkIEFuYWxpc3RhIGVuIFJlY3Vyc29zIEh1bWFub3MiLCAiUlJISCZDb2FjaGluZyBvbnRvbG9naWNvIHByb2Zlc2lvbmFsLiIsICJHcmFkdWFkYSBlbiBsaWMgcnJoaCB5IGFib2dhY2lhIikpLA0KICAgICAgICAgY2FycmVyYV9ncmFkbyA9IGZjdF9jb2xsYXBzZShjYXJyZXJhX2dyYWRvLCAiSW5nZW5pZXLDrWFzIiA9IGMoIkluZyBlbiBzaXN0ZW1hcyIsICJJbmcuIEZpbmFuY2llcmEiLCAiSW5nZW5pZXLDrWEgQ29tZXJjaWFsIiwgIklORy5zaXN0ZW1hcyIsICAiSW5nZW5pZXJpYSBFbGVjdHLDs25pY2EiLCJJbmdlbmllcsOtYSBJbmR1c3RyaWFsIikpLA0KICAgICAgICAgY2FycmVyYV9ncmFkbyA9IGZjdF9jb2xsYXBzZShjYXJyZXJhX2dyYWRvLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBzaWNvbG9nw61hIiA9IGMoIlBzaWNvbG9naWEiLCJQc2ljb2xvZ8OtYSBJbmR1c3RyaWFsIiwgIlBzaWNvbG9nw61hIHNvY2lhbCIsICAgIlBzaWNvbG9nw61hIFNvY2lhbCAvIExpYy4gZW4gRGlyZWNjacOzbiBkZSBsYXMgT3JnYW5pemFjaW9uZXMiKSksDQogICAgICAgICBjYXJyZXJhX2dyYWRvID0gZmN0X2NvbGxhcHNlKGNhcnJlcmFfZ3JhZG8sICJObyBlc3R1ZGnDqSBlbiBsYSBVbml2ZXJzaWRhZCIgPSAiTmluZ3VuYSIpLA0KICAgICAgICAgY2FycmVyYV9ncmFkbyA9IGZjdF9sdW1wKGNhcnJlcmFfZ3JhZG8sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3AgPSAwLjAyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdGhlcl9sZXZlbCA9ICJPdHJvcyIpLA0KICAgICAgICAgY2FycmVyYV9ncmFkbyA9IGZhY3RvcihjYXJyZXJhX2dyYWRvLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJSUkhIIC8gUlJMTCAvIFJSVFQiLCAiUHNpY29sb2fDrWEiLCAiQWRtaW5pc3RyYWNpw7NuIGRlIEVtcHJlc2FzIiwgIkNvbnRhZG9yIFDDumJsaWNvIiwgIk90cm9zIikpKQ0KDQoNCmdncGxvdChjYXJyZXJhcywgYWVzKHggPSBjYXJyZXJhX2dyYWRvKSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBmaWxsID0gYXp1bCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKyANCiAgbGFicyh4PSIiLHk9IiIpICsNCiAgZXN0aWxvaCArDQogIGxhYnModGl0bGUgPSAiUHJpbmNpcGFsZXMgY2FycmVyYXMgZXN0dWRpYWRhcyIsDQogICAgICAgc3VidGl0bGUgPSAiVHJhYmFqYWRvcmVzIGVuIHJlbGFjacOzbiBkZSBkZXBlbmRlbmNpYSIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkNCg0KYGBgDQoNCkRhZGEgbGEgY2FudGlkYWQgZGUgcmVzcHVlc3RhcyBwb3IgcGHDrXMsIGVsIGFuw6FsaXNpcyBxdWUgaGFyZW1vcyBkZXNkZSBhcXXDrSBlbiBhZGVsYW50ZSBzw7NsbyBzZXLDoSBwYXJhICoqQXJnZW50aW5hKiouDQoNCiMjIEFuw6FsaXNpcyBkZSBlZHVjYWNpw7NuIHkgcHVlc3RvcyBwYXJhIEFyZ2VudGluYQ0KDQpMdWVnbywgcG9kZW1vcyBhbmFsaXphciBlbiBxdcOpIHRpcG8gZGUgdW5pdmVyc2lkYWQgZXN0dWRpYXJvbiBsYXMgcGVyc29uYXMgcXVlIHJlc3BvbmRpZXJvbiBsYSBlbmN1ZXN0YSwgc2Vnw7puIGVsIHB1ZXN0byBhY3R1YWwgcXVlIG9jdXBhbi4NCg0KYGBge3IgcHVlc3RvLXVuaXZlcnNpZGFkfQ0KcmVjb3J0ZV9lZHVjYWNpb24gPC0gcmggJT4lDQogIGZpbHRlcihwYWlzID09ICJBcmdlbnRpbmEiKSAlPiUgDQogIHNlbGVjdChuaXZlbF9mb3JtYWNpb24sIGNhcnJlcmFfZ3JhZG8sDQogICAgICAgICB0aXBvX3VuaXZlcnNpZGFkLCB0cmFiYWpvLCBzdWVsZG9fYnJ1dG8sIHB1ZXN0bywgZnVuY2lvbl9yaCwgcGFpcywgZ2VuZXJvKQ0KDQpnZ3Bsb3QocmVjb3J0ZV9lZHVjYWNpb24sIChhZXMoeCA9IHB1ZXN0bywgZmlsbCA9IHRpcG9fdW5pdmVyc2lkYWQpKSkgKyAjVGlwbyBkZSB1bml2ZXJzaWRhZCB5IGNhcmdvDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKyANCiAgbGFicyh4PSIiLHk9IiIpICsNCiAgICBlc3RpbG92ICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyhncmlzLCB2ZXJkZSwgYXp1bCkpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgbGFicyh0aXRsZSA9ICJDYW50aWRhZCBkZSByZXNwdWVzdGFzIHNlZ8O6biBwdWVzdG8geSB1bml2ZXJzaWRhZCIsDQogICAgICAgc3VidGl0bGUgPSAiU8OzbG8gcmVzcHVlc3RhcyBkZSBBcmdlbnRpbmEiLA0KICAgICAgIHggPSAiIiwgZmlsbCA9ICJUaXBvIGRlIFVuaXZlcnNpZGFkIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKQ0KYGBgDQoNClJlaXRlcmVtb3MgZWwgYW7DoWxpc2lzIHBlcm8gw7puaWNhbWVudGUgcGFyYSBsYXMgY2FycmVyYXMgcmVsYWNpb25hZGFzIGNvbiBSZWN1cnNvcyBIdW1hbm9zIHkgUmVsYWNpb25lcyBkZWwgVHJhYmFqby4NCg0KYGBge3IgcmgtcHNpY299DQpyZWNvcnRlX2VkdWNhY2lvbiAlPiUNCiAgZmlsdGVyKGNhcnJlcmFfZ3JhZG8gPT0gIlJSSEggLyBSUkxMIC8gUlJUVCIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gcHVlc3RvLCBmaWxsID0gdGlwb191bml2ZXJzaWRhZCkpICsgI1RpcG8gZGUgdW5pdmVyc2lkYWQgeSBjYXJnbw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpICsgDQogIGxhYnMoeD0iIix5PSIiKSArDQogICAgZXN0aWxvdiArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoZ3JpcywgdmVyZGUsIGF6dWwpKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIGxhYnModGl0bGUgPSAiQ2FudGlkYWQgZGUgcmVzcHVlc3RhcyBzZWfDum4gcHVlc3RvIHkgdW5pdmVyc2lkYWQiLA0KICAgICAgIHN1YnRpdGxlID0gIlPDs2xvIHJlc3B1ZXN0YXMgZGUgQXJnZW50aW5hIC0gQ2FycmVyYXMgZGUgUkgiLA0KICAgICAgIHggPSAiIiwgZmlsbCA9ICJUaXBvIGRlIFVuaXZlcnNpZGFkIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKQ0KICANCg0KYGBgDQoNClBvZGVtb3MgYXByZWNpYXIgcXVlIGEgcGFydGlyIGRlIGxvcyBwdWVzdG9zIGRlIGplZmF0dXJhLCBoYXkgbWF5b3IgcHJlc2VuY2lhIGRlIGdyYWR1YWRvcyBwcm92ZW5pZW50ZXMgZGUgdW5pdmVyc2lkYWRlcyBwcml2YWRhcy4NCg0KRW4gQXJnZW50aW5hLCBwb2RlbW9zIHZlciBsYSBzaWd1aWVudGUgZGlzdHJpYnVjacOzbiBwb3IgZ8OpbmVybyB5IG5pdmVsIGVkdWNhdGl2by4NCg0KYGBge3Igbml2ZWwtZWQtZ2VuZXJvfQ0KDQpuZV9zYWxhcmlvIDwtIHJlY29ydGVfZWR1Y2FjaW9uIA0KDQpuZV9zYWxhcmlvICU+JSANCiAgc2VsZWN0KHBhaXMsIG5pdmVsX2Zvcm1hY2lvbiwgZ2VuZXJvLCBwdWVzdG8pICU+JQ0KICBmaWx0ZXIoZ2VuZXJvICE9ICJHw6luZXJvIERpdmVyc28iKSAlPiUNCiAgbXV0YXRlKG5pdmVsX2Zvcm1hY2lvbiA9IGZhY3RvcihuaXZlbF9mb3JtYWNpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiU2VjdW5kYXJpbyBjb21wbGV0byIsICJUZXJjaWFyaW8gY29tcGxldG8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVuaXZlcnNpdGFyaW8gZW4gY3Vyc28iLCAiVW5pdmVyc2l0YXJpbyBjb21wbGV0byIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWFlc3Ryw61hIGVuIGN1cnNvIiwiTWFlc3Ryw61hIGNvbXBsZXRhIikpKSAlPiUgDQogIGdyb3VwX2J5KG5pdmVsX2Zvcm1hY2lvbikgJT4lIA0KICBnZ3Bsb3QoYWVzICh5PSBuaXZlbF9mb3JtYWNpb24sIGZpbGwgPSBnZW5lcm8pKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKyANCiAgbGFicyh4PSIiLHk9IiIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG8gKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKw0KICBsYWJzKHRpdGxlID0gIk3DoXhpbW8gbml2ZWwgZWR1Y2F0aXZvIGFsY2FuemFkbyBwb3IgZ8OpbmVybyIsDQogICAgICAgc3VidGl0bGUgPSAiRGlzdHJpYnVjacOzbiBwb3IgZnJlY3VlbmNpYXMgYWJzb2x1dGFzIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlLCANCiAgICAgICBmaWxsID0gIkfDqW5lcm8iKQ0KDQpgYGANCg0KRW4gdMOpcm1pbm9zIGFic29sdXRvcywgbGFzIG11amVyZXMgZ3JhZHVhZGFzIHJlcHJlc2VudGFuIGNlcmNhIGRlbCA3MCUgZGUgbGEgbXVlc3RyYS4gQW5hbGljZW1vcyBlc3RvcyBkYXRvcyBlbiB0w6lybWlub3MgcmVsYXRpdm9zLiBQcsOhY3RpY2FtZW50ZSBlbCBwYXRyw7NuIGRlIG5pdmVsIGVkdWNhdGl2byBlbnRyZSBob21icmVzIHkgbXVqZXJlcyBlcyBpZMOpbnRpY28uDQoNCmBgYHtyIG5pdmVsLWVkLWdlbmVyby1yZWx9DQpuZV9mZW0gPC0gbmVfc2FsYXJpbyAlPiUgDQogIGZpbHRlcihnZW5lcm8gPT0gIkZlbWVuaW5vIikgJT4lIA0KICBncm91cF9ieShnZW5lcm8sIG5pdmVsX2Zvcm1hY2lvbikgJT4lIA0KICBtdXRhdGUobml2ZWxfZm9ybWFjaW9uID0gZmFjdG9yKG5pdmVsX2Zvcm1hY2lvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJNYWVzdHLDrWEgY29tcGxldGEiLCAiTWFlc3Ryw61hIGVuIGN1cnNvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVbml2ZXJzaXRhcmlvIGNvbXBsZXRvIiwgIlVuaXZlcnNpdGFyaW8gZW4gY3Vyc28iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRlcmNpYXJpbyBjb21wbGV0byIsICJTZWN1bmRhcmlvIGNvbXBsZXRvIikpKSAlPiUgDQogIGdyb3VwX2J5KG5pdmVsX2Zvcm1hY2lvbikgJT4lIA0KICBzdW1tYXJpc2UobiA9IG4oKSkgJT4lIA0KICBtdXRhdGUoZnJlY3VlbmNpYSA9IHJvdW5kKG4vc3VtKG4pLDIpLA0KICAgICAgICAgZ2VuZXJvID0gIkZlbWVuaW5vIikgDQoNCm5lX21hcyA8LSBuZV9zYWxhcmlvICU+JSANCiAgZmlsdGVyKGdlbmVybyA9PSAiTWFzY3VsaW5vIikgJT4lIA0KICBncm91cF9ieShnZW5lcm8sIG5pdmVsX2Zvcm1hY2lvbikgJT4lIA0KICBtdXRhdGUobml2ZWxfZm9ybWFjaW9uID0gZmFjdG9yKG5pdmVsX2Zvcm1hY2lvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJNYWVzdHLDrWEgY29tcGxldGEiLCAiTWFlc3Ryw61hIGVuIGN1cnNvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVbml2ZXJzaXRhcmlvIGNvbXBsZXRvIiwgIlVuaXZlcnNpdGFyaW8gZW4gY3Vyc28iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRlcmNpYXJpbyBjb21wbGV0byIsICJTZWN1bmRhcmlvIGNvbXBsZXRvIikpKSAlPiUgDQogIGdyb3VwX2J5KG5pdmVsX2Zvcm1hY2lvbikgJT4lIA0KICBzdW1tYXJpc2UobiA9IG4oKSkgJT4lIA0KICBtdXRhdGUoZnJlY3VlbmNpYSA9IHJvdW5kKG4vc3VtKG4pLDIpLA0KICAgICAgICAgZ2VuZXJvID0gIk1hc2N1bGlubyIpIA0KDQpuZV90b3RhbCA8LSByYmluZChuZV9mZW0sIG5lX21hcykNCg0KZ2dwbG90KG5lX3RvdGFsLCBhZXMoeCA9IG5pdmVsX2Zvcm1hY2lvbiwgeSA9IGZyZWN1ZW5jaWEsIGZpbGwgPSBnZW5lcm8pKSArDQogIGdlb21fY29sKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwgDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCiAgbGFicyh4PSIiLHk9IiIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBmYWNldF93cmFwKH5nZW5lcm8sIG5jb2wgPSAyKSArDQogIGVzdGlsb2ggKw0KICBsYWJzKHRpdGxlID0gIlByb3BvcmNpw7NuIGRlIG5pdmVsIGVkdWNhdGl2byBtw6F4aW1vIHBvciBnw6luZXJvIiwNCiAgICAgICB4ID0gIiIsIHkgPSAiUHJvcG9yY2nDs24iLCANCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKQ0KDQpgYGANCg0KQWhvcmEgdmVhbW9zIGNvbW8gc2UgZGlzdHJpYnV5ZW4gbG9zIHB1ZXN0b3Mgc2Vnw7puIGVsIGfDqW5lcm8geSBlbCBuaXZlbCBlZHVjYXRpdm8uDQoNCmBgYHtyIHB1ZXN0b3Mtbml2ZWwtZWQsIGZpZy5oZWlnaHQ9OH0NCm5lX3NhbGFyaW8gJT4lIA0KICBzZWxlY3QocGFpcywgbml2ZWxfZm9ybWFjaW9uLCBnZW5lcm8sIHB1ZXN0bykgJT4lDQogIGZpbHRlcihnZW5lcm8gJWluJSBjKCJGZW1lbmlubyIsICJNYXNjdWxpbm8iKSwNCiAgICAgICAgIHB1ZXN0byAhPSAiUGFzYW50ZSIsIHB1ZXN0byAhPSAiRGlyZWN0b3IiKSAlPiUNCiAgbXV0YXRlKG5pdmVsX2Zvcm1hY2lvbiA9IGZhY3RvcihuaXZlbF9mb3JtYWNpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiU2VjdW5kYXJpbyBjb21wbGV0byIsICJUZXJjaWFyaW8gY29tcGxldG8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVuaXZlcnNpdGFyaW8gZW4gY3Vyc28iLCAiVW5pdmVyc2l0YXJpbyBjb21wbGV0byIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWFlc3Ryw61hIGVuIGN1cnNvIiwiTWFlc3Ryw61hIGNvbXBsZXRhIikpLA0KICAgICAgICAgcHVlc3RvID0gZmFjdG9yKHB1ZXN0bywgDQogICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiRGlyZWN0b3IiLCAiR2VyZW50ZSIsICJKZWZlIiwgIlJlc3BvbnNhYmxlIiwgIkhSQlAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFuYWxpc3RhIiwgIkFkbWluaXN0cmF0aXZvIikpKSAlPiUgDQogIGdyb3VwX2J5KG5pdmVsX2Zvcm1hY2lvbikgJT4lIA0KICBnZ3Bsb3QoYWVzICh5PSBuaXZlbF9mb3JtYWNpb24sIGZpbGwgPSBnZW5lcm8pKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKyANCiAgbGFicyh4PSIiLHk9IiIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG8gKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KICBsYWJzKHRpdGxlID0gIk5pdmVsIGVkdWNhdGl2byBwb3IgcHVlc3RvIHkgZ8OpbmVybyIsDQogICAgICAgc3VidGl0bGUgPSAiRGlzdHJpYnVjacOzbiBwb3IgZnJlY3VlbmNpYXMgYWJzb2x1dGFzIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlLCANCiAgICAgICBmaWxsID0gIkfDqW5lcm8iKSArDQogIGZhY2V0X3dyYXAofnB1ZXN0bywgbmNvbCA9IDMpDQoNCmBgYA0KDQpBbGd1bmFzIGNvbmNsdXNpb25lcyBxdWUgcG9kZW1vcyBleHRyYWVyIGRlbCBncsOhZmljbyBhbnRlcmlvcjoNCg0KLSAgIEhheSB1bmEgZnVlcnRlIHByZWRvbWluYW5jaWEgZGUgbXVqZXJlcyBlbiBwdWVzdG9zIGRlIGJhamEgamVyYXJxdcOtYS4NCi0gICBFbiBsb3MgcHVlc3RvcyBkZSBHZXJlbmNpYSB5IGRlIEplZmF0dXJhIGhheSBtYXlvciBwcmVkb21pbmFuY2lhIGRlIHZhcm9uZXMsIHBlcm8gYcO6biBhc8OtIGhheSB1bmEgcGFyaWRhZCBlbnRyZSBsb3MgZGlzdGludG9zIG5pdmVsZXMgZWR1Y2F0aXZvcy4NCi0gICBQb3NpY2lvbmVzIGFsdGFtZW50ZSBlc3BlY2lhbGl6YWRhcywgY29tbyBsYSBkZSBIUkJQLCByZXF1aWVyZSB1bmEgZm9ybWFjacOzbiB1bml2ZXJzaXRhcmlhLg0KDQpBbmFsaWNlbW9zIGxhcyBwcm9wb3JjaW9uZXMgZGUgaG9tYnJlcyB5IGRlIG11amVyZXMgZW4gcHVlc3RvIGRlIGxpZGVyYXpnby4NCg0KYGBge3IgbGlkZXJhemdvLWdlbmVybywgcmVzdWx0cz0naGlkZSd9DQpkaXYgPC0gcmggJT4lDQogIGZpbHRlcihwYWlzID09ICJBcmdlbnRpbmEiKSAlPiUgDQpzZWxlY3QoZ2VuZXJvKSAlPiUgDQogIG11dGF0ZShnZW5lcm8gPSBmYWN0b3IoZ2VuZXJvLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJGZW1lbmlubyIsICJNYXNjdWxpbm8iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJObyBiaW5hcmlvIiwgIlByZWZpZXJvIG5vIHJlc3BvbmRlciIpKSkgJT4lIA0KICBncm91cF9ieShnZW5lcm8pICU+JSANCiAgc3VtbWFyaXNlIChuID0gbigpKSAlPiUgDQogIG11dGF0ZShmcmVxID0gbi9zdW0obikpICU+JSANCiAgYXJyYW5nZSgtbikNCg0KbGlkZXJlcyA8LSByaCAlPiUgDQogIGZpbHRlcihwYWlzID09ICJBcmdlbnRpbmEiKSAlPiUgDQogc2VsZWN0KGdlbmVybywgcHVlc3RvKSAlPiUgDQogIG11dGF0ZShnZW5lcm8gPSBmY3RfcmVjb2RlKGdlbmVybywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vIGJpbmFyaW8iID0gIkfDqW5lcm8gZGl2ZXJzbyAoZ8OpbmVybyBkaXZlcnNvIC8gZ8OpbmVybyBmbHVpZG8gL290cmFzIG1pbm9yw61hcykiKSkNCg0KIyBQcm9wb2Npw7NuIGRlIGzDrWRlcmVzIGhvbWJyZXMgeSBtdWplcmVzDQpsaWRlcmVzX2dlbmVybyA8LSBsaWRlcmVzICU+JSANCiAgZmlsdGVyKGdlbmVybyAlaW4lIGMoIk1hc2N1bGlubyIsIkZlbWVuaW5vIikpICU+JSANCiAgZ3JvdXBfYnkoZ2VuZXJvKSAlPiUNCiAgbXV0YXRlKGdlbnRlX2FfY2FyZ28gPSBpZl9lbHNlKHB1ZXN0byAlaW4lIGMoIlJlc3BvbnNhYmxlIiwgIkplZmUiLCAiR2VyZW50ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3VwZXJ2aXNvciIsICJEaXJlY3RvciIpLDEsMCkpICU+JQ0KICBzdW1tYXJpc2UobGlkZXIgPSBzdW0oZ2VudGVfYV9jYXJnbykpICU+JSANCiAgbGVmdF9qb2luKGRpdikgJT4lIA0KICBzZWxlY3QoZ2VuZXJvLCBsaWRlciwgbikgJT4lIA0KICBtdXRhdGUocHJvcG9yY2lvbiA9IHBlcmNlbnQobGlkZXIvbikpDQoNCiMgVGVzdCBkZSBoaXDDs3Rlc2lzIHBhcmEgdmFsaWRhciBkaWZlcmVuY2lhcyBkZSByZXN1bHRhZG9zDQojIEhheSBxdWUgdmVyaWZpY2FyIHNpIGxhIHByb3BvcmNpw7NuIGRlIGzDrWRlcmVzIGhvbWJyZXMgZXMgbWF5b3IgcXVlIGxhIHByb3BvcmNpw7NuIGRlIGzDrWRlcmVzIG11amVyZXMNCiMgQ3JlbyB1biBkYXRhZnJhbWUgcGFyYSBhbmFsaXphciBwcm9wb3JjaW9uZXMgZGUgaG9tYnJlcyB5IGRlIG11amVyZXMgZW4gcHVlc3RvcyBkZSBsaWRlcmF6Z28geSBkZSBuby1saWRlcmF6Z28NCnRlc3RfbGlkZXIgPC0gbGlkZXJlc19nZW5lcm8gJT4lIA0KICBtdXRhdGUobm9fbGlkZXIgPSBuIC0gbGlkZXIpICU+JSAgICAgICAgIyBDb2x1bW5hIGRlIG5vIGzDrWRlcmVzDQogIHNlbGVjdChnZW5lcm8sIGxpZGVyLCBub19saWRlcikgJT4lICAgICAjIHNlbGVjY2lvbm8gY29sdW1uYXMgZGUgaW50ZXLDqXMNCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKGxpZGVyLCBub19saWRlciksICMgSGFnbyB1biBkYXRhc2V0IGxhcmdvIHBhcmEgYW5hbGl6YXIgZGVzcHXDqXMNCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gImVzX2xpZGVyIiwgdmFsdWVzX3RvID0gImNvbnRlbyIpDQoNCiMgRGVsIHRvdGFsIGRlIHJlc3B1ZXN0YXMgbWUgaW50ZXJlc2Egc8OzbG8gdmVyIGN1w6FsZXMgc29uIGxvcyBob21icmVzIGNvbiBwdWVzdG8gZGUgbGlkZXJhemdvDQp0ZXN0X2xpZGVyJGNhdCA8LSBjKDAsMCwxLDApDQoNCiMgRXh0cmFpZ28gZWwgbXUgcGFyYSBkZWNpZGlyIHNpIGxhIGRpZmVyZW5jaWEgZXMgc2lnbmlmaWNhdGl2YSB5IHBhc2FybG8gYSBsYSBmw7NybXVsYSBkZWwgdGVzdC4NCnByb3BfbXVqZXJfbGlkIDwtIHB1bGwobGlkZXJlc19nZW5lcm9bMSwyXS9saWRlcmVzX2dlbmVyb1sxLDNdKQ0KDQojIFJlYWxpem8gZWwgdGVzdCBkZSBoaXDDs3Rlc2lzLg0KIyBIMCA9IExhcyBwcm9wb3JjaW9uZXMgZGUgbMOtZGVyZXMgaG9tYnJlcyB5IG11amVyZXMgc29uIGlndWFsZXMNCiMgSDEgPSBMYSBwcm9wb3JjacOzbiBkZSBob21icmVzIGzDrWRlcmVzIGVzIG1heW9yIHF1ZSBsYSBwcm9wb3JjacOzbiBkZSBtdWplcmVzIGzDrWRlcmVzLg0KcmVzdWx0YWRvc190ZXN0IDwtIGJyb29tOjp0aWR5KHQudGVzdCh0ZXN0X2xpZGVyJGNhdCwgbXUgPSBwcm9wX211amVyX2xpZCwgYWx0ZXJuYXRpdmUgPSAiZ3JlYXRlciIpKQ0KDQp2YWxvcl90ZXN0IDwtIGlmKHJlc3VsdGFkb3NfdGVzdFsxLDNdID4gMC4wNSkgew0KICBwcmludCgibGEgZGlmZXJlbmNpYSBlcyBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhLCB5IGxhIHByb3BvcmNpw7NuIGRlIGhvbWJyZXMgZW4gcHVlc3RvcyBkZSBsaWRlcmF6Z28gZXMgbWF5b3IgcXVlIGVsIGRlIGxhcyBtdWplcmVzIikNCiAgfSBlbHNlIHsNCiAgICBwcmludCgibGEgZGlmZXJlbmNpYSBubyBlcyBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhLCB5IGxhIHByb3BvcmNpw7NuIGRlIGhvbWJyZXMgbm8gZXMgZXN0YWTDrXN0aWNhbWVudGUgbWF5b3IgcXVlIGVsIGRlIGxhcyBtdWplcmVzIGVuIHB1ZXN0b3MgZGUgbGlkZXJhemdvIikNCiAgfQ0KYGBgDQoNCmBgYHtyIGdyYWZpY28tcHJvcC1saWQtZ2VuZXJvfQ0KIyBHcsOhZmljbw0KbGlkZXJlc19nZW5lcm8gJT4lIA0KICBtdXRhdGUocG9yY19saWRlciA9IGxpZGVyL24sIA0KICAgICAgICAgcG9yY19ub19saWRlciA9IDEgLSBwb3JjX2xpZGVyKSAlPiUgDQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhwb3JjX2xpZGVyLCBwb3JjX25vX2xpZGVyKSwNCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gImVzX2xpZGVyIiwgDQogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidmFsb3JlcyIpICU+JSANCiAgbXV0YXRlKGVzX2xpZGVyID0gZmFjdG9yKGVzX2xpZGVyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoInBvcmNfbm9fbGlkZXIiLCAicG9yY19saWRlciIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk5vIEzDrWRlciIsICJMw61kZXIiKSkpICU+JSANCiAgZ2dwbG90KGFlcyh4PSBnZW5lcm8sIHkgPSB2YWxvcmVzLCBmaWxsID0gZXNfbGlkZXIpKSsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpKw0KICBlc3RpbG8gKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjNzU4MzhGIiwgIiMzNDREN0UiKSkgKw0KICBsYWJzKHRpdGxlID0gIlByb3BvcmNpw7NuIGRlIEzDrWRlcmVzIHNlZ8O6biBnw6luZXJvIiwNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwgZmlsbCA9ICIiLCANCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKQ0KDQpgYGANCg0KRGUgYWN1ZXJkbyBhIGxhcyByZXNwdWVzdGFzIHJlY29sZWN0YWRhcyAqKjIgZGUgY2FkYSAzKiogcGFydGljaXBhbnRlcyBzb24gbXVqZXJlcy4NCg0KUGFyYSBsb3MgcHVlc3RvcyBkZSBsaWRlcmF6Z28gY29uc2lkZXJhbW9zIGxhcyBwZXJzb25hcyBlbiBsb3MgcHVlc3RvcyBkZSAqRGlyZWN0b3IsIEdlcmVudGUsIEplZmUsIHkgUmVzcG9uc2FibGUuKg0KDQpEZWwgdG90YWwgZGUgKiptdWplcmVzKiosIGByIGxpZGVyZXNfZ2VuZXJvWzEsM11gIHJlc3B1ZXN0YXMsIGByIGxpZGVyZXNfZ2VuZXJvWzEsMl1gIG9jdXBhbiB1biBwdWVzdG8gZGUgbGlkZXJhemdvIChgciBsaWRlcmVzX2dlbmVyb1sxLCA0XWApLg0KDQpEZWwgdG90YWwgZGUgKipob21icmVzKiosIGByIGxpZGVyZXNfZ2VuZXJvWzIsIDNdYCByZXNwdWVzdGFzLCBgciBsaWRlcmVzX2dlbmVyb1syLDJdYCBvY3VwYW4gdW4gcHVlc3RvIGRlIGxpZGVyYXpnbyAoYHIgbGlkZXJlc19nZW5lcm9bMiwgNF1gKS4NCg0KQ29uIHVuICpwLXZhbHVlKiBpZ3VhbCBhIGByIHJvdW5kKHJlc3VsdGFkb3NfdGVzdFsxLDNdLDMpYCBwb2RlbW9zIGFmaXJtYXIgcXVlICoqYHIgdmFsb3JfdGVzdGAqKi4NCg0KIyMgQW7DoWxpc2lzIGRlIHN1ZWxkb3MgeSBlZHVjYWNpw7NuIGVuIEFyZ2VudGluYQ0KDQpFbiBlc3RhIHNlY2Npw7NuIGFuYWxpemFyZW1vcyBsb3Mgc3VlbGRvcyBlbiBjb21wYXJhY2nDs24gY29uIGxvcyBkaXN0aW50b3Mgbml2ZWxlcyBlZHVjYXRpdm9zLg0KDQpBIGRpZmVyZW5jaWEgZGUgb3RyYXMgc2VjY2lvbmVzLCBlbiBlc3RlIGNhc28gY29tcGFyYXJlbW9zIGxhICptZWRpYSBzYWxhcmlhbCogcGFyYSBwb2RlciBvYnNlcnZhciBsb3MgZGVzdsOtb3MgZXN0w6FuZGFyIGVuIGxvcyBhbsOhbGlzaXMuIEVuIHByaW1lciBsdWdhciBhbmFsaWNlbW9zIGN1w6FsIGVzIGVsIHN1ZWxkbyBwcm9tZWRpbyBkZSBhY3VlcmRvIGEgbG9zIGRpc3RpbnRvcyBuaXZlbGVzIGVkdWNhdGl2b3MuDQoNClByaW1lcm8gdmVhbW9zIGN1w6FsIGVzIGVsIHN1ZWxkbyBwcm9tZWRpbyBlbiBwZXNvcyBhcmdlbnRpbm9zLCBzZWfDum4gZWwgbml2ZWwgZWR1Y2F0aXZvLg0KDQpgYGB7ciBzdWVsZG8tZWR1Y30NCmVzdHVkaW9zIDwtIHJoICU+JSANCiAgZmlsdGVyKHBhaXMgPT0gIkFyZ2VudGluYSIpICU+JSANCiAgc2VsZWN0KGdlbmVybywgbml2ZWxfZm9ybWFjaW9uLCBzdWVsZG9fYnJ1dG8pDQogICAgDQogIA0KZXN0X2FyICA8LSBwcm9maWxpbmdfbnVtKGVzdHVkaW9zKQ0KZXNfcDA1IDwtIDI5MzIwDQplc19wOTUgPC0gMjEwMDAwDQoNCnJoICU+JSANCiAgZmlsdGVyKHBhaXMgPT0gIkFyZ2VudGluYSIsIA0KICAgICAgICAgYmV0d2VlbihzdWVsZG9fYnJ1dG8sIGVzX3AwNSwgZXNfcDk1KSkgJT4lIA0KICAgIG11dGF0ZShuaXZlbF9mb3JtYWNpb24gPSBmYWN0b3Iobml2ZWxfZm9ybWFjaW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIlNlY3VuZGFyaW8gY29tcGxldG8iLCAiVGVyY2lhcmlvIGNvbXBsZXRvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVbml2ZXJzaXRhcmlvIGVuIGN1cnNvIiwgIlVuaXZlcnNpdGFyaW8gY29tcGxldG8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1hZXN0csOtYSBlbiBjdXJzbyIsIk1hZXN0csOtYSBjb21wbGV0YSIpKSkgJT4lIA0KICBncm91cF9ieShuaXZlbF9mb3JtYWNpb24pICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2JydXRvKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBzdWVsZG9fcHJvbWVkaW8sIHkgPSBuaXZlbF9mb3JtYWNpb24pKSsNCiAgZ2VvbV9jb2woZmlsbCA9IGF6dWwpKw0KICBlc3RpbG92ICsNCiAgZWplX3hfbiArDQogIGxhYnModGl0bGUgPSAiU3VlbGRvIHByb21lZGlvIHBvciBuaXZlbCBkZSBmb3JtYWNpw7NuIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJFbiBBUiQiLA0KICAgICAgIHg9IiIsIHk9IiIsIGNhcHRpb24gPSBmdWVudGUpDQoNCiAgDQoNCmBgYA0KDQpBaG9yYSB2ZWFtb3MgcXXDqSBwYXNhIHNpIGluY2x1aW1vcyBlbiBlbCBhbsOhbGlzaXMgZWwgZ8OpbmVybyBwYXJhIGFuYWxpemFyIGxvcyBzdWVsZG9zIHByb21lZGlvcyB5IHN1cyBkZXN2w61vcyBlc3TDoW5kYXIuDQoNCmBgYHtyIHN1ZWxkby1lZHVjLWdlbmVyb30NCnJoICU+JSANCiAgZmlsdGVyKHBhaXMgPT0gIkFyZ2VudGluYSIsIA0KICAgICAgICAgYmV0d2VlbihzdWVsZG9fYnJ1dG8sIGVzX3AwNSwgZXNfcDk1KSkgJT4lIA0KICAgIG11dGF0ZShuaXZlbF9mb3JtYWNpb24gPSBmYWN0b3Iobml2ZWxfZm9ybWFjaW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIlNlY3VuZGFyaW8gY29tcGxldG8iLCAiVGVyY2lhcmlvIGNvbXBsZXRvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVbml2ZXJzaXRhcmlvIGVuIGN1cnNvIiwgIlVuaXZlcnNpdGFyaW8gY29tcGxldG8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1hZXN0csOtYSBlbiBjdXJzbyIsIk1hZXN0csOtYSBjb21wbGV0YSIpKSkgJT4lIA0KICBncm91cF9ieShuaXZlbF9mb3JtYWNpb24sIGdlbmVybykgJT4lIA0KICBzdW1tYXJpc2Uoc2FsYXJpb3MgPSBsaXN0KG1lYW5fc2Uoc3VlbGRvX2JydXRvKSkpICU+JSANCiAgdW5uZXN0KHNhbGFyaW9zKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IG5pdmVsX2Zvcm1hY2lvbiwgeSA9IHksIGZpbGwgPSBnZW5lcm8pKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikrDQogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSB5bWluLHltYXggPSB5bWF4KSwgcG9zaXRpb24gPSAiZG9kZ2UiKSsNCiAgY29vcmRfZmxpcCgpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KICBlamVfeV9uICsNCiAgZXN0aWxvdiArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGdlbmVybzMpICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8geSBkZXN2w61vIGVzdMOhbmRhcmQgcG9yIG5pdmVsIGRlIGZvcm1hY2nDs24geSBnw6luZXJvIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJFbiBBUiQiLCANCiAgICAgICB4ID0gIiIsIHkgPSAiIiwgDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSwgDQogICAgICAgZmlsbCA9ICJHw6luZXJvIikNCmBgYA0KDQojIFN1ZWxkb3MgcG9yIGZ1bmNpw7NuDQoNCkVuIGVzdGEgc2VjY2nDs24gbm9zIHByb3BvbmVtb3MgYW5hbGl6YXIgbG9zIHN1ZWxkb3Mgc2Vnw7puIGxhcyBkaXN0aW50YXMgZnVuY2lvbmVzIGRlIFJlY3Vyc29zIEh1bWFub3MuDQoNClBhcmEgcmVhbGl6YXIgZXN0ZSBhbsOhbGlzaXMgdHV2aW1vcyBxdWUgdW5pZmljYXIgdmFyaWFzIHJlc3B1ZXN0YXMgeSBlbGltaW5hciBhbGd1bmFzIHF1ZSBubyBjb3JyZXNwb25kw61hbiBhbCDDoXJlYSBkZSBSUkhIIHBhcmEgcG9kZXIgcXVlZGFybm9zIGNvbiBlc3RhcyDDoXJlYXMgZGUgYW7DoWxpc2lzLg0KDQpMb3Mgc3VlbGRvcyBwcm9tZWRpb3MgeSBsYSBjYW50aWRhZCBkZSByZXNwdWVzdGFzIHF1ZSByZWNpYmltb3MgZGUgY2FkYSBmdW5jacOzbiBzb24gbG9zIHNpZ3VpZW50ZXM6DQoNCmBgYHtyIGZ1bmNpb25lc30NCiMgTGltcGllemEgZGUgZnVuY2lvbmVzDQojIEVsaW1pbm8gbG9zIHF1ZSBubyBzb24gZGUgUlJISA0KcmhfYXIgPC0gcmhfYXIgJT4lIA0KICBmaWx0ZXIoZnVuY2lvbl9yaCAhPSAiTm8gbWUgZGVzZW1wZcOxbyBlbiBlbCDDoXJlYSBkZSBSUkhILiBUcmFiYWpvIGVuIGVsIMOhcmVhIGRlIFNpc3RlbWFzLiIsDQogICAgICAgICBmdW5jaW9uX3JoICE9ICJObyB0cmFiYWpvIGVuIGVsIMOhcmVhIikNCg0KIyBVbmlmaWNvIGxhcyBmdW5jaW9uZXMgZGUgUkgNCnJoX2FyIDwtIHJoX2FyICU+JSANCiAgbXV0YXRlKGZ1bmNpb25fcmggPSBzdHJfdHJpbShmdW5jaW9uX3JoLCBzaWRlID0gImJvdGgiKSwNCiAgICBmdW5jaW9uX3JoID0gZmN0X2NvbGxhcHNlKGZ1bmNpb25fcmgsICJBZG0uIGRlIHBlcnNvbmFsIiA9IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCJBZG1pbmlzdHJhY2nDs24gZGUgcGVyc29uYWwiLCAiQWRtaW5pc3RyYXRpdmEgZW4gw6FyZWEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQXNpc3RlbnRlIikpLA0KICAgIGZ1bmNpb25fcmggPSBmY3RfY29sbGFwc2UoZnVuY2lvbl9yaCwgIkdlbmVyYWxpc3RhIiA9IGMoIkdlbmVyYWxpc3RhIiwgIkFsIHNlciBIUkJQIHVuIHBvY28gZGUgdG9kbyBwYXlyb2xsLCBjYXBhY2l0YWNpb24sIGNvbXVuaWNhY2lvbiBpbnRlcm5hLCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQXJlYSBpbnRlZ3JhbCBkZSBSSCIsICJHZW5lcmFsIiwiSFJCUCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGEgbWF5b3LDrWEgZGUgbG9zIG5vbWJyYWRvcyBjb24gaWd1YWxlcyBjb25kaWNpb25lcyBkZSBpbXBvcnRhbmNpYSB5IHByaW9yaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUlJISCIsICJUb2RhcyBsYXMgYW50ZXJpb3JlcyIsICJUb2RvIiwgIlRvZG8gbG8gYW50ZXJpb3IiLCAiVG9kb3MgZWxsb3MiLCAiVG9kb3MsIGxvcyBkZXNjcmlwdG9zIikpLA0KICAgIGZ1bmNpb25fcmggPSBmY3RfY29sbGFwc2UoZnVuY2lvbl9yaCwgIkNhcGFjaXRhY2nDs24geSBkZXNhcnJvbGxvIiA9IGMoIkNhcGFjaXRhY2nDs24geSBkZXNhcnJvbGxvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNhcGFjaXRhY2nDs24geSBEZXNhcnJvbGxvICsgQmllbmVzdGFyICsgUlNFIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRlc2Fycm9sbG8gbGFib3JhbDogcHJvY2Vzb3MgU29maSwgY2FwYWNpdGFjaW9uLCBldmFsdWFjacOzbiwgZGVzYXJyb2xsbyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPbmJvYXJkaW5nLCBjbGltYSwgY3VsdHVyYSwgbGlkZXJhemdvIikpLA0KICAgIGZ1bmNpb25fcmggPSBmY3RfY29sbGFwc2UoZnVuY2lvbl9yaCwgIlBheXJvbGwiID0gYygiUGF5cm9sbCAvIExpcXVpZGFjacOzbiBkZSBzdWVsZG9zIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBheXJvbGwgeSBhZG1pbnNpdHJhY2lvbiBkZSBwZXJzb25hbCIpKSwNCiAgICBmdW5jaW9uX3JoID0gZmN0X2NvbGxhcHNlKGZ1bmNpb25fcmgsICJEaXNlw7FvIG9yZ2FuaXphY2lvbmFsIiA9ICJEaXNlw7FvIG9yZ2FuaXphY2lvbmFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNZWpvcmEgY29udGludWEgcHJveWVjdG9zIGRlIGlubm92YWNpw7NuIiksDQogICAgZnVuY2lvbl9yaCA9IGZjdF9sdW1wKGZ1bmNpb25fcmgsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gMTAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBvdGhlcl9sZXZlbCA9ICJPdHJhcyBmdW5jaW9uZXMiKSkNCg0KZ3QoDQogIHJoX2FyICU+JSANCiAgICBncm91cF9ieShmdW5jaW9uX3JoKSAlPiUgDQogICAgc3VtbWFyaXNlKCJTdWVsZG8gUHJvbWVkaW8iID0gcm91bmQobWVhbihzdWVsZG9fZnQpKSwNCiAgICAgICAgICAgICAgUmVzcHVlc3RhcyA9IG4oKSksDQogICkgJT4lIA0KICB0YWJfaGVhZGVyKHRpdGxlID0gIlN1ZWxkbyBwcm9tZWRpbyBwb3IgZnVuY2nDs24iLA0KICAgICAgICAgICAgIHN1YnRpdGxlID0gIkVuIEFSJCIpICU+JSANCiAgY29sc19sYWJlbChmdW5jaW9uX3JoID0gIkZ1bmNpw7NuIikgJT4lIA0KICBmbXRfY3VycmVuY3koY29sdW1ucyA9ICAiU3VlbGRvIFByb21lZGlvIiwgZGVjaW1hbHMgPSAwLA0KICAgICAgICAgICAgICAgc2VwX21hcmsgPSAiLiIsIGRlY19tYXJrID0gIiwiKQ0KDQpyaF9hciAlPiUgDQogIGdyb3VwX2J5KGZ1bmNpb25fcmgpICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggIT0gIk90cmFzIGZ1bmNpb25lcyIpICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBmY3RfcmVvcmRlcihmdW5jaW9uX3JoLCBzdWVsZG9fcHJvbWVkaW8pLCANCiAgICAgICAgICAgICB4ID0gc3VlbGRvX3Byb21lZGlvKSkgKw0KICBnZW9tX2NvbChmaWxsID0gYXp1bCkgKw0KICBsYWJzKHRpdGxlID0gIlN1ZWxkbyBwcm9tZWRpbyBwb3IgZnVuY2nDs24iLA0KICAgICAgIHN1YnRpdGxlID0gIkVuIEFSJCIsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICBlamVfeF9uICsNCiAgZXN0aWxvdg0KDQpyaF9hciAlPiUgDQogIGZpbHRlcihmdW5jaW9uX3JoICE9ICJPdHJhcyBmdW5jaW9uZXMiKSAlPiUgDQogIGdyb3VwX2J5KGZ1bmNpb25fcmgsIHB1ZXN0bykgJT4lIA0KICBzdW1tYXJpc2Uoc3VlbGRvX21lZGlvID0gbWVhbihzdWVsZG9fZnQpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IGZ1bmNpb25fcmgsIHkgPSBzdWVsZG9fbWVkaW8pKSArDQogIGdlb21fY29sKGZpbGwgPSBhenVsKSArDQogIGVqZV95X24gKw0KICBlc3RpbG9oICsNCiAgZmFjZXRfd3JhcCh+cHVlc3RvKSArDQogIGxhYnModGl0bGUgPSAiU3VlbGRvIHByb21lZGlvIHBvciBwdWVzdG8geSBmdW5jacOzbiIsDQogICAgICAgc3VidGl0bGUgPSAiRW4gQVIkIiwgDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkNCmBgYA0KDQpgYGB7ciBnYXBfZnVuY2lvbmVzfQ0KZnVuY2lvbmVzX3RvcCA8LSByaF9hciAlPiUgDQogIGZpbHRlcihmdW5jaW9uX3JoICVpbiUgYygiUGVvcGxlIEFuYWx5dGljcyIsICJEaXNlw7FvIG9yZ2FuaXphY2lvbmFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWxhY2lvbmVzIGxhYm9yYWxlcyIsICJDb21wZW5zYWNpb25lcyB5IGJlbmVmaWNpb3MiKSkgJT4lIA0KICBzdW1tYXJpc2UocHJvbWVkaW8gPSBtZWFuKHN1ZWxkb19mdCkpICU+JSANCiAgcHVsbCgpDQoNCmZ1bmNpb25lc19ib3R0b20gPC0gcmhfYXIgJT4lIA0KICBmaWx0ZXIoZnVuY2lvbl9yaCAlaW4lIGMoIlBheXJvbGwiLCAiUmVjbHV0YW1pZW50byB5IHNlbGVjY2nDs24iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJDYXBhY2l0YWNpw7NuIHkgZGVzYXJyb2xsbyIsICJDb211bmljYWNpw7NuIGludGVybmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFkbS4gZGUgcGVyc29uYWwiKSkgJT4lIA0KICBzdW1tYXJpc2UocHJvbWVkaW8gPSBtZWFuKHN1ZWxkb19mdCkpICU+JSANCiAgcHVsbCgpDQoNCnBvcmNlbnRhamVfZ2FwIDwtIHBlcmNlbnQoZnVuY2lvbmVzX3RvcCAvIGZ1bmNpb25lc19ib3R0b20gLSAxKQ0KYGBgDQoNClNpIGJpZW4gbGEgY2FudGlkYWQgZGUgcmVzcHVlc3RhcyBpbmZsdXllIGVuIGVsIHN1ZWxkbyBwcm9tZWRpbyBjb21vIHBhcmEgZGV0ZXJtaW5hciBzaWduaWZpY2F0aXZhbWVudGUgc2kgYWxndW5hcyBmdW5jaW9uZXMgc2UgcGFnYW4gbWVqb3IgcXVlIG90cmFzLCBubyBsbGFtYSBsYSBhdGVuY2nDs24gcXVlIGxhcyBmdW5jaW9uZXMgZGUgKipQZW9wbGUgQW5hbHl0aWNzKiosICoqRGlzZcOxbyBPcmdhbml6YWNpb25hbCoqIHkgKipDb21wZW5zYWNpb25lcyB5IEJlbmVmaWNpb3MqKiBlc3TDqW4gZGVudHJvIGRlIGxhcyBmdW5jaW9uZXMgbWVqb3JlcyBwYWdhcyBkZW50cm8gZGUgUmVjdXJzb3MgSHVtYW5vcyB5YSBxdWUgcmVxdWllcmVuIGRlIG1heW9yIGVzcGVjaWFsaXphY2nDs24sIGFuw6FsaXNpcywgeSBtYW5lam8gZGUgaW5mb3JtYWNpw7NuIGNvbmZpZGVuY2lhbC4NCg0KQ29tcGxldGEgZWwgcG9kaW8gbGEgZnVuY2nDs24gZGUgKipSZWxhY2lvbmVzIExhYm9yYWxlcyoqLiBFbiBlc3RlIGNhc28gY3JlZW1vcyBxdWUgZW4gdW4gcGHDrXMgYWx0YW1lbnRlIHNpbmRpY2FsaXphZG8gY29tbyBBcmdlbnRpbmEsIGVzdGEgZnVuY2nDs24gY29icmEgbXVjaGEgcmVsZXZhbmNpYSBkYWRvIHF1ZSBzb24gbG9zIHF1ZSBzZSBlbmNhcmdhbiBkZSBsYXMgbmVnb2NpYWNpb25lcyBkZSBwYXJpdGFyaWFzIHNhbGFyaWFsZXMgeSBhY3VlcmRvcyBjb2xlY3Rpdm9zLCB5IHNvbiByZXNwb25zYWJsZXMgZGUgcmVzb2x2ZXIgbG9zIGNvbmZsaWN0b3MgZGVudHJvIGRlIGxhcyBvcmdhbml6YWNpb25lcy4NCg0KU2kgaGFjZW1vcyB1biBwcm9tZWRpbyBkZSBsb3Mgc3VlbGRvcyBkZSBsYXMgY3VhdHJvIGZ1bmNpb25lcyBjb24gbG9zIHN1ZWxkb3MgbcOhcyBhbHRvcywgeSBsdWVnbyBoYWNlbW9zIGxvIG1pc21vIGNvbiBlbCByZXN0byBkZSBsYXMgZnVuY2lvbmVzIG3DoXMgYmFqYXMgKGV4Y2VwdHVhbmRvIGEgbG9zIHF1ZSBlc3TDoW4gZW4gcm9sZXMgR2VuZXJhbGlzdGFzKSwgZWwgZ2FwIHNhbGFyaWFsIGVzIGRlIGByIHBvcmNlbnRhamVfZ2FwYCwgbG8gY3VhbCBlcyBsbGFtYXRpdmFtZW50ZSBhbHRvLg0KDQpBIGNvbnRpbnVhY2nDs24gcHJlc2VudGFtb3MgdW4gYW7DoWxpc2lzIG3DoXMgZGV0YWxsYWRvIGRlIGxvcyBzdWVsZG9zIHBvciBmdW5jaW9uZXMgeSBwdWVzdG9zLg0KDQpgYGB7ciBmdW5jaW9uZXNfcHVlc3Rvc30NCg0KZGF0YXRhYmxlKA0KICByaF9hciAlPiUgDQogICAgZ3JvdXBfYnkoZnVuY2lvbl9yaCwgcHVlc3RvKSAlPiUgDQogICAgc3VtbWFyaXNlKCJTdWVsZG8gUHJvbWVkaW8iID0gcm91bmQobWVhbihzdWVsZG9fZnQpKSksDQogIGNvbG5hbWVzID0gYygiRnVuY2nDs24iLCAiUHVlc3RvIiwgIlN1ZWxkbyBQcm9tZWRpbyIpLA0KICBjYXB0aW9uID0gIlN1ZWxkbyBwcm9tZWRpbyBwb3IgZnVuY2nDs24geSBwdWVzdG8gLSBFbiBBUiQiDQopDQoNCmBgYA0KDQpFbiBsYXMgc2lndWllbnRlcyBzZWNjaW9uZXMgZXhwbG9yYXJlbW9zIHVuIHBvY28gbcOhcyBlbiBkZXRhbGxlIGNhZGEgdW5hIGRlIGVzdGFzIGZ1bmNpb25lcy4gRW4gZnVuY2nDs24gZGUgbGEgY2FudGlkYWQgZGUgcmVzcHVlc3RhcyByZWNpYmlkYXMgcGFyYSBjYWRhIGZ1bmNpw7NuLCBwb2RyZW1vcyBwcm9mdW5kaXphciB1biBwb2NvIG3DoXMgZWwgYW7DoWxpc2lzLCBvIGJpZW4gaGFjZXIgdW4gYW7DoWxpc2lzIHN1cGVyZmljaWFsLg0KDQojIyBQZW9wbGUgQW5hbHl0aWNzDQoNCmBgYHtyIHBhXzF9DQoNCnJoX2FyIDwtIHJoX2FyICU+JSANCiAgbXV0YXRlKG5pdmVsX2Zvcm1hY2lvbiA9IGZjdF9yZWxldmVsKG5pdmVsX2Zvcm1hY2lvbiwgYygiTWFlc3Ryw61hIGNvbXBsZXRhIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1hZXN0csOtYSBlbiBjdXJzbyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVuaXZlcnNpdGFyaW8gY29tcGxldG8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVbml2ZXJzaXRhcmlvIGVuIGN1cnNvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGVyY2lhcmlvIGNvbXBsZXRvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2VjdW5kYXJpbyBjb21wbGV0byIpKSkNCg0KZnVuY2lvbl9hbmFsaXNpcyA8LSAiUGVvcGxlIEFuYWx5dGljcyINCg0KcmhfYXIgJT4lIA0KICBmaWx0ZXIoZnVuY2lvbl9yaCA9PSBmdW5jaW9uX2FuYWxpc2lzKSAlPiUgDQogIGdncGxvdChhZXMoeSA9IGZ1bmNpb25fcmgsIGZpbGwgPSBnZW5lcm8pKSsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG8gKw0KICBsYWJzKHRpdGxlID0gIlByb3BvcmNpw7NuIGRlIEfDqW5lcm8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIkfDqW5lcm8iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBzdWVsZG9fcHJvbWVkaW8sIHkgPSBwdWVzdG8pKSArDQogIGdlb21fY29sKGZpbGwgPSBhenVsKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4PXN1ZWxkb19wcm9tZWRpbywwKSwgaGp1c3QgPSAxLjQsIHZqdXN0ID0gMC4zKSwNCiAgICAgICAgICAgIHNpemUgPSAzLCBjb2xvciA9ICJ3aGl0ZSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAuOSkpICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoZnVuY2lvbl9hbmFsaXNpcywgIiAtIEVuIEFSJCIpLA0KICAgICAgIHggPSAiIiwgeSA9ICIiLCANCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKSArDQogIGVqZV94X24gKw0KICBlc3RpbG92DQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBwdWVzdG8sIGZpbGwgPSBuaXZlbF9mb3JtYWNpb24pKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbDQpICsNCiAgbGFicyh0aXRsZSA9ICJOaXZlbCBkZSBmb3JtYWNpw7NuIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIk5pdmVsIGRlIEZvcm1hY2nDs24iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZXN0aWxvDQogIA0KYGBgDQoNCiMjIERpc2XDsW8gT3JnYW5pemFjaW9uYWwNCg0KYGBge3IgZG99DQpmdW5jaW9uX2FuYWxpc2lzIDwtICJEaXNlw7FvIG9yZ2FuaXphY2lvbmFsIg0KDQpyaF9hciAlPiUgDQogIGZpbHRlcihmdW5jaW9uX3JoID09IGZ1bmNpb25fYW5hbGlzaXMpICU+JSANCiAgZ2dwbG90KGFlcyh5ID0gZnVuY2lvbl9yaCwgZmlsbCA9IGdlbmVybykpKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjODYyNEY1IiwgIiMxRkMzQUEiLCIjRkZEMTI5IikpICsNCiAgZXN0aWxvICsNCiAgbGFicyh0aXRsZSA9ICJQcm9wb3JjacOzbiBkZSBHw6luZXJvIiwNCiAgICAgICBzdWJ0aXRsZSA9IGZ1bmNpb25fYW5hbGlzaXMsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgZmlsbCA9ICJHw6luZXJvIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKQ0KDQpyaF9hciAlPiUgDQogIGZpbHRlcihmdW5jaW9uX3JoID09IGZ1bmNpb25fYW5hbGlzaXMpICU+JSANCiAgZ3JvdXBfYnkocHVlc3RvKSAlPiUgDQogIHN1bW1hcmlzZShzdWVsZG9fcHJvbWVkaW8gPSBtZWFuKHN1ZWxkb19mdCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gc3VlbGRvX3Byb21lZGlvLCB5ID0gcHVlc3RvKSkgKw0KICBnZW9tX2NvbChmaWxsID0gYXp1bCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoeD1zdWVsZG9fcHJvbWVkaW8sMCksIGhqdXN0ID0gMS40LCB2anVzdCA9IDAuMyksDQogICAgICAgICAgICBzaXplID0gMywgY29sb3IgPSAid2hpdGUiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gLjkpKSArDQogIGxhYnModGl0bGUgPSAiU3VlbGRvIHByb21lZGlvIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gcGFzdGUwKGZ1bmNpb25fYW5hbGlzaXMsICIgLSBFbiBBUiQiKSwNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICBlamVfeF9uICsNCiAgZXN0aWxvdg0KDQpyaF9hciAlPiUgDQogIGZpbHRlcihmdW5jaW9uX3JoID09IGZ1bmNpb25fYW5hbGlzaXMpICU+JSANCiAgZ2dwbG90KGFlcyh5ID0gcHVlc3RvLCBmaWxsID0gbml2ZWxfZm9ybWFjaW9uKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2w0KSArDQogIGxhYnModGl0bGUgPSAiTml2ZWwgZGUgZm9ybWFjacOzbiBwb3IgcHVlc3RvIiwNCiAgICAgICBzdWJ0aXRsZSA9IGZ1bmNpb25fYW5hbGlzaXMsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgZmlsbCA9ICJOaXZlbCBkZSBGb3JtYWNpw7NuIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKSArDQogIGVzdGlsbw0KDQpgYGANCg0KIyMgUmVsYWNpb25lcyBMYWJvcmFsZXMNCg0KYGBge3IgcnJsbH0NCg0KZnVuY2lvbl9hbmFsaXNpcyA8LSAiUmVsYWNpb25lcyBsYWJvcmFsZXMiDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBmdW5jaW9uX3JoLCBmaWxsID0gZ2VuZXJvKSkrDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXMpICsNCiAgZXN0aWxvICsNCiAgbGFicyh0aXRsZSA9ICJQcm9wb3JjacOzbiBkZSBHw6luZXJvIiwNCiAgICAgICBzdWJ0aXRsZSA9IGZ1bmNpb25fYW5hbGlzaXMsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgZmlsbCA9ICJHw6luZXJvIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKQ0KDQpyaF9hciAlPiUgDQogIGZpbHRlcihmdW5jaW9uX3JoID09IGZ1bmNpb25fYW5hbGlzaXMpICU+JSANCiAgZ3JvdXBfYnkocHVlc3RvKSAlPiUgDQogIHN1bW1hcmlzZShzdWVsZG9fcHJvbWVkaW8gPSBtZWFuKHN1ZWxkb19mdCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gc3VlbGRvX3Byb21lZGlvLCB5ID0gcHVlc3RvKSkgKw0KICBnZW9tX2NvbChmaWxsID0gYXp1bCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoeD1zdWVsZG9fcHJvbWVkaW8sMCksIGhqdXN0ID0gMS40LCB2anVzdCA9IDAuMyksDQogICAgICAgICAgICBzaXplID0gMywgY29sb3IgPSAid2hpdGUiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gLjkpKSArDQogIGxhYnModGl0bGUgPSAiU3VlbGRvIHByb21lZGlvIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gcGFzdGUwKGZ1bmNpb25fYW5hbGlzaXMsICItIEVuIEFSJCIpLA0KICAgICAgIHggPSAiIiwgeSA9ICIiLCBjYXB0aW9uID0gZnVlbnRlKSArDQogIGVqZV94X24gKw0KICBlc3RpbG92DQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBwdWVzdG8sIGZpbGwgPSBuaXZlbF9mb3JtYWNpb24pKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbDYpICsNCiAgbGFicyh0aXRsZSA9ICJOaXZlbCBkZSBmb3JtYWNpw7NuIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIk5pdmVsIGRlIEZvcm1hY2nDs24iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZXN0aWxvDQpgYGANCg0KIyMgQ29tcGVuc2FjaW9uZXMgeSBiZW5lZmljaW9zDQoNCmBgYHtyIGN5Yn0NCmZ1bmNpb25fYW5hbGlzaXMgPC0gIkNvbXBlbnNhY2lvbmVzIHkgYmVuZWZpY2lvcyINCg0KcmhfYXIgJT4lIA0KICBmaWx0ZXIoZnVuY2lvbl9yaCA9PSBmdW5jaW9uX2FuYWxpc2lzKSAlPiUgDQogIGdncGxvdChhZXMoeSA9IGZ1bmNpb25fcmgsIGZpbGwgPSBnZW5lcm8pKSsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG8gKw0KICBsYWJzKHRpdGxlID0gIlByb3BvcmNpw7NuIGRlIEfDqW5lcm8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIkfDqW5lcm8iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBzdWVsZG9fcHJvbWVkaW8sIHkgPSBwdWVzdG8pKSArDQogIGdlb21fY29sKGZpbGwgPSBhenVsKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4PXN1ZWxkb19wcm9tZWRpbywwKSwgaGp1c3QgPSAxLjQsIHZqdXN0ID0gMC4zKSwNCiAgICAgICAgICAgIHNpemUgPSAzLCBjb2xvciA9ICJ3aGl0ZSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAuOSkpICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoZnVuY2lvbl9hbmFsaXNpcywgIiAtIEVuIEFSJCIpLA0KICAgICAgIHggPSAiIiwgeSA9ICIiLCBjYXB0aW9uID0gZnVlbnRlKSArDQogIGVqZV94X24gKw0KICBlc3RpbG92DQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBwdWVzdG8sIGZpbGwgPSBuaXZlbF9mb3JtYWNpb24pKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbDQpICsNCiAgbGFicyh0aXRsZSA9ICJOaXZlbCBkZSBmb3JtYWNpw7NuIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIk5pdmVsIGRlIEZvcm1hY2nDs24iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZXN0aWxvDQpgYGANCg0KIyMgR2VuZXJhbGlzdGENCg0KYGBge3IgZ2VuZXJhbGlzdGF9DQpyaF9hciA8LSByaF9hciAlPiUgDQogIG11dGF0ZShyYW5nb19hbnRfcHVlc3RvID0gY2FzZV93aGVuKA0KICAgIGFuaW9zX2VuX3B1ZXN0byA8IDEgfiAiTWVub3MgZGUgMSBhw7FvIiwNCiAgICBhbmlvc19lbl9wdWVzdG8gPCA2IH4gIkVudHJlIDEgeSA1IGHDsW9zIiwNCiAgICBhbmlvc19lbl9wdWVzdG8gPCAxMSB+ICJFbnRyZSA2IHkgMTAgYcOxb3MiLA0KICAgIGFuaW9zX2VuX3B1ZXN0byA9IFQgfiAiTcOhcyBkZSAxMCBhw7FvcyIpLA0KICAgIHJhbmdvX2FudF9wdWVzdG8gPSBmY3RfcmVsZXZlbChyYW5nb19hbnRfcHVlc3RvLCBjKCJNZW5vcyBkZSAxIGHDsW8iLCAiRW50cmUgMSB5IDUgYcOxb3MiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFbnRyZSA2IHkgMTAgYcOxb3MiLCAiTcOhcyBkZSAxMCBhw7FvcyIpKSkNCg0KZnVuY2lvbl9hbmFsaXNpcyA8LSAiR2VuZXJhbGlzdGEiDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBmdW5jaW9uX3JoLCBmaWxsID0gZ2VuZXJvKSkrDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXMpICsNCiAgZXN0aWxvICsNCiAgbGFicyh0aXRsZSA9ICJQcm9wb3JjacOzbiBkZSBHw6luZXJvIiwNCiAgICAgICBzdWJ0aXRsZSA9IGZ1bmNpb25fYW5hbGlzaXMsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgZmlsbCA9ICJHw6luZXJvIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKQ0KDQpyaF9hciAlPiUgDQogIGZpbHRlcihmdW5jaW9uX3JoID09IGZ1bmNpb25fYW5hbGlzaXMpICU+JSANCiAgZ3JvdXBfYnkocHVlc3RvKSAlPiUgDQogIHN1bW1hcmlzZShzdWVsZG9fcHJvbWVkaW8gPSBtZWFuKHN1ZWxkb19mdCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gc3VlbGRvX3Byb21lZGlvLCB5ID0gcHVlc3RvKSkgKw0KICBnZW9tX2NvbChmaWxsID0gYXp1bCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoeD1zdWVsZG9fcHJvbWVkaW8sMCksIGhqdXN0ID0gMS40LCB2anVzdCA9IDAuMyksDQogICAgICAgICAgICBzaXplID0gMywgY29sb3IgPSAid2hpdGUiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gLjkpKSArDQogIGxhYnModGl0bGUgPSAiU3VlbGRvIHByb21lZGlvIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gcGFzdGUwKGZ1bmNpb25fYW5hbGlzaXMsICIgLSBFbiBBUiQiKSwNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICBlamVfeF9uICsNCiAgZXN0aWxvdg0KDQpyaF9hciAlPiUgDQogIGZpbHRlcihmdW5jaW9uX3JoID09IGZ1bmNpb25fYW5hbGlzaXMpICU+JSANCiAgZ2dwbG90KGFlcyh5ID0gcHVlc3RvLCBmaWxsID0gbml2ZWxfZm9ybWFjaW9uKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2w2KSArDQogIGxhYnModGl0bGUgPSAiTml2ZWwgZGUgZm9ybWFjacOzbiBwb3IgcHVlc3RvIiwNCiAgICAgICBzdWJ0aXRsZSA9IGZ1bmNpb25fYW5hbGlzaXMsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgZmlsbCA9ICJOaXZlbCBkZSBGb3JtYWNpw7NuIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKSArDQogIGVzdGlsbw0KDQpyaF9hciAlPiUgDQogIGZpbHRlcihmdW5jaW9uX3JoID09IGZ1bmNpb25fYW5hbGlzaXMpICU+JSANCiAgZ3JvdXBfYnkocHVlc3RvLCByYW5nb19hbnRfcHVlc3RvKSAlPiUgDQogIHN1bW1hcmlzZShtZWRpYV9zdWVsZG8gPSBtZWFuKHN1ZWxkb19mdCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gcmFuZ29fYW50X3B1ZXN0bywgeSA9IG1lZGlhX3N1ZWxkbykpICsNCiAgZ2VvbV9jb2woZmlsbCA9IGF6dWwpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShndWlkZSA9IGd1aWRlX2F4aXMobi5kb2RnZSA9IDIpKSArDQogIGZhY2V0X3dyYXAofnB1ZXN0bykgKw0KICBlc3RpbG9oICsNCiAgZWplX3lfbiArDQogIGxhYnModGl0bGUgPSAiU3VlbGRvIHByb21lZGlvIHBvciBwdWVzdG8geSBhbnRpZ8O8ZWRhZCIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoZnVuY2lvbl9hbmFsaXNpcywgIiAtIEVuIEFSJCIpLA0KICAgICAgIHggPSAiIiwgeSA9ICIiLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpDQpgYGANCg0KIyMgUGF5cm9sbA0KDQpgYGB7ciBwYXlyb2xsfQ0KZnVuY2lvbl9hbmFsaXNpcyA8LSAiUGF5cm9sbCINCg0KcmhfYXIgJT4lIA0KICBmaWx0ZXIoZnVuY2lvbl9yaCA9PSBmdW5jaW9uX2FuYWxpc2lzKSAlPiUgDQogIGdncGxvdChhZXMoeSA9IGZ1bmNpb25fcmgsIGZpbGwgPSBnZW5lcm8pKSsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG8gKw0KICBsYWJzKHRpdGxlID0gIlByb3BvcmNpw7NuIGRlIEfDqW5lcm8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIkfDqW5lcm8iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBzdWVsZG9fcHJvbWVkaW8sIHkgPSBwdWVzdG8pKSArDQogIGdlb21fY29sKGZpbGwgPSBhenVsKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4PXN1ZWxkb19wcm9tZWRpbywwKSwgaGp1c3QgPSAxLjQsIHZqdXN0ID0gMC4zKSwNCiAgICAgICAgICAgIHNpemUgPSAzLCBjb2xvciA9ICJ3aGl0ZSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAuOSkpICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoZnVuY2lvbl9hbmFsaXNpcywgIiAtIEVuIEFSJCIpLA0KICAgICAgIHggPSAiIiwgeSA9ICIiLCBjYXB0aW9uID0gZnVlbnRlKSArDQogIGVqZV94X24gKw0KICBlc3RpbG92DQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBwdWVzdG8sIGZpbGwgPSBuaXZlbF9mb3JtYWNpb24pKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbDYpICsNCiAgbGFicyh0aXRsZSA9ICJOaXZlbCBkZSBmb3JtYWNpw7NuIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIk5pdmVsIGRlIEZvcm1hY2nDs24iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZXN0aWxvDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8sIHJhbmdvX2FudF9wdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKG1lZGlhX3N1ZWxkbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSByYW5nb19hbnRfcHVlc3RvLCB5ID0gbWVkaWFfc3VlbGRvKSkgKw0KICBnZW9tX2NvbChmaWxsID0gYXp1bCkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGd1aWRlID0gZ3VpZGVfYXhpcyhuLmRvZGdlID0gMikpICsNCiAgZmFjZXRfd3JhcCh+cHVlc3RvKSArDQogIGVzdGlsb2ggKw0KICBlamVfeV9uICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byB5IGFudGlnw7xlZGFkIiwNCiAgICAgICBzdWJ0aXRsZSA9IHBhc3RlMChmdW5jaW9uX2FuYWxpc2lzLCAiIC0gRW4gQVIkIiksDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkNCmBgYA0KDQojIyBDYXBhY2l0YWNpw7NuIHkgRGVzYXJyb2xsbw0KDQpgYGB7ciBjYXBhX2Rlc2F9DQpmdW5jaW9uX2FuYWxpc2lzIDwtICJDYXBhY2l0YWNpw7NuIHkgZGVzYXJyb2xsbyINCg0KcmhfYXIgJT4lIA0KICBmaWx0ZXIoZnVuY2lvbl9yaCA9PSBmdW5jaW9uX2FuYWxpc2lzKSAlPiUgDQogIGdncGxvdChhZXMoeSA9IGZ1bmNpb25fcmgsIGZpbGwgPSBnZW5lcm8pKSsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG8gKw0KICBsYWJzKHRpdGxlID0gIlByb3BvcmNpw7NuIGRlIEfDqW5lcm8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIkfDqW5lcm8iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBzdWVsZG9fcHJvbWVkaW8sIHkgPSBwdWVzdG8pKSArDQogIGdlb21fY29sKGZpbGwgPSBhenVsKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4PXN1ZWxkb19wcm9tZWRpbywwKSwgaGp1c3QgPSAxLjQsIHZqdXN0ID0gMC4zKSwNCiAgICAgICAgICAgIHNpemUgPSAzLCBjb2xvciA9ICJ3aGl0ZSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAuOSkpICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoZnVuY2lvbl9hbmFsaXNpcywgIiAtIEVuIEFSJCIpLA0KICAgICAgIHggPSAiIiwgeSA9ICIiLCBjYXB0aW9uID0gZnVlbnRlKSArDQogIGVqZV94X24gKw0KICBlc3RpbG92DQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBwdWVzdG8sIGZpbGwgPSBuaXZlbF9mb3JtYWNpb24pKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbDYpICsNCiAgbGFicyh0aXRsZSA9ICJOaXZlbCBkZSBmb3JtYWNpw7NuIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIk5pdmVsIGRlIEZvcm1hY2nDs24iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZXN0aWxvDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8sIHJhbmdvX2FudF9wdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKG1lZGlhX3N1ZWxkbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSByYW5nb19hbnRfcHVlc3RvLCB5ID0gbWVkaWFfc3VlbGRvKSkgKw0KICBnZW9tX2NvbChmaWxsID0gYXp1bCkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGd1aWRlID0gZ3VpZGVfYXhpcyhuLmRvZGdlID0gMikpICsNCiAgZmFjZXRfd3JhcCh+cHVlc3RvKSArDQogIGVzdGlsb2ggKw0KICBlamVfeV9uICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byB5IGFudGlnw7xlZGFkIiwNCiAgICAgICBzdWJ0aXRsZSA9IHBhc3RlMChmdW5jaW9uX2FuYWxpc2lzLCAiIC0gRW4gQVIkIiksDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkNCg0KYGBgDQoNCiMjIFJlY2x1dGFtaWVudG8geSBTZWxlY2Npw7NuDQoNCmBgYHtyIHJlY3J1aXRpbmd9DQpmdW5jaW9uX2FuYWxpc2lzIDwtICJSZWNsdXRhbWllbnRvIHkgc2VsZWNjacOzbiINCg0KcmhfYXIgJT4lIA0KICBmaWx0ZXIoZnVuY2lvbl9yaCA9PSBmdW5jaW9uX2FuYWxpc2lzKSAlPiUgDQogIGdncGxvdChhZXMoeSA9IGZ1bmNpb25fcmgsIGZpbGwgPSBnZW5lcm8pKSsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG8gKw0KICBsYWJzKHRpdGxlID0gIlByb3BvcmNpw7NuIGRlIEfDqW5lcm8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIkfDqW5lcm8iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBzdWVsZG9fcHJvbWVkaW8sIHkgPSBwdWVzdG8pKSArDQogIGdlb21fY29sKGZpbGwgPSBhenVsKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4PXN1ZWxkb19wcm9tZWRpbywwKSwgaGp1c3QgPSAxLjQsIHZqdXN0ID0gMC4zKSwNCiAgICAgICAgICAgIHNpemUgPSAzLCBjb2xvciA9ICJ3aGl0ZSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAuOSkpICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoZnVuY2lvbl9hbmFsaXNpcywgIiAtIEVuIEFSJCIpLA0KICAgICAgIHggPSAiIiwgeSA9ICIiLCBjYXB0aW9uID0gZnVlbnRlKSArDQogIGVqZV94X24gKw0KICBlc3RpbG92DQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBwdWVzdG8sIGZpbGwgPSBuaXZlbF9mb3JtYWNpb24pKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbDYpICsNCiAgbGFicyh0aXRsZSA9ICJOaXZlbCBkZSBmb3JtYWNpw7NuIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIk5pdmVsIGRlIEZvcm1hY2nDs24iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZXN0aWxvDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8sIHJhbmdvX2FudF9wdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKG1lZGlhX3N1ZWxkbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSByYW5nb19hbnRfcHVlc3RvLCB5ID0gbWVkaWFfc3VlbGRvKSkgKw0KICBnZW9tX2NvbChmaWxsID0gYXp1bCkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGd1aWRlID0gZ3VpZGVfYXhpcyhuLmRvZGdlID0gMikpICsNCiAgZmFjZXRfd3JhcCh+cHVlc3RvKSArDQogIGVzdGlsb2ggKw0KICBlamVfeV9uICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byB5IGFudGlnw7xlZGFkIiwNCiAgICAgICBzdWJ0aXRsZSA9IHBhc3RlMChmdW5jaW9uX2FuYWxpc2lzLCAiIC0gRW4gQVIkIiksDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkNCmBgYA0KDQojIyBBZG1pbmlzdHJhY2nDs24gZGUgUGVyc29uYWwNCg0KYGBge3IgYWRwfQ0KZnVuY2lvbl9hbmFsaXNpcyA8LSAiQWRtLiBkZSBwZXJzb25hbCINCg0KcmhfYXIgJT4lIA0KICBmaWx0ZXIoZnVuY2lvbl9yaCA9PSBmdW5jaW9uX2FuYWxpc2lzKSAlPiUgDQogIGdncGxvdChhZXMoeSA9IGZ1bmNpb25fcmgsIGZpbGwgPSBnZW5lcm8pKSsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG8gKw0KICBsYWJzKHRpdGxlID0gIlByb3BvcmNpw7NuIGRlIEfDqW5lcm8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIkfDqW5lcm8iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBzdWVsZG9fcHJvbWVkaW8sIHkgPSBwdWVzdG8pKSArDQogIGdlb21fY29sKGZpbGwgPSBhenVsKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4PXN1ZWxkb19wcm9tZWRpbywwKSwgaGp1c3QgPSAxLjQsIHZqdXN0ID0gMC4zKSwNCiAgICAgICAgICAgIHNpemUgPSAzLCBjb2xvciA9ICJ3aGl0ZSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAuOSkpICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoZnVuY2lvbl9hbmFsaXNpcywgIiAtIEVuIEFSJCIpLA0KICAgICAgIHggPSAiIiwgeSA9ICIiLCBjYXB0aW9uID0gZnVlbnRlKSArDQogIGVqZV94X24gKw0KICBlc3RpbG92DQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBnZ3Bsb3QoYWVzKHkgPSBwdWVzdG8sIGZpbGwgPSBuaXZlbF9mb3JtYWNpb24pKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbDYpICsNCiAgbGFicyh0aXRsZSA9ICJOaXZlbCBkZSBmb3JtYWNpw7NuIHBvciBwdWVzdG8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIk5pdmVsIGRlIEZvcm1hY2nDs24iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZXN0aWxvDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8sIHJhbmdvX2FudF9wdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKG1lZGlhX3N1ZWxkbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSByYW5nb19hbnRfcHVlc3RvLCB5ID0gbWVkaWFfc3VlbGRvKSkgKw0KICBnZW9tX2NvbChmaWxsID0gYXp1bCkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGd1aWRlID0gZ3VpZGVfYXhpcyhuLmRvZGdlID0gMikpICsNCiAgZmFjZXRfd3JhcCh+cHVlc3RvKSArDQogIGVzdGlsb2ggKw0KICBlamVfeV9uICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byB5IGFudGlnw7xlZGFkIiwNCiAgICAgICBzdWJ0aXRsZSA9IHBhc3RlMChmdW5jaW9uX2FuYWxpc2lzLCAiIC0gRW4gQVIkIiksDQogICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkNCg0KYGBgDQoNCiMjIENvbXVuaWNhY2nDs24gSW50ZXJuYQ0KDQpgYGB7ciBjb21faW50ZXJuYX0NCmZ1bmNpb25fYW5hbGlzaXMgPC0gIkNvbXVuaWNhY2nDs24gaW50ZXJuYSINCg0KcmhfYXIgJT4lIA0KICBmaWx0ZXIoZnVuY2lvbl9yaCA9PSBmdW5jaW9uX2FuYWxpc2lzKSAlPiUgDQogIGdncGxvdChhZXMoeSA9IGZ1bmNpb25fcmgsIGZpbGwgPSBnZW5lcm8pKSsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG8gKw0KICBsYWJzKHRpdGxlID0gIlByb3BvcmNpw7NuIGRlIEfDqW5lcm8iLA0KICAgICAgIHN1YnRpdGxlID0gZnVuY2lvbl9hbmFsaXNpcywNCiAgICAgICB4ID0gIiIsIHkgPSAiIiwNCiAgICAgICBmaWxsID0gIkfDqW5lcm8iLA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpDQoNCnJoX2FyICU+JSANCiAgZmlsdGVyKGZ1bmNpb25fcmggPT0gZnVuY2lvbl9hbmFsaXNpcykgJT4lIA0KICBncm91cF9ieShwdWVzdG8pICU+JSANCiAgc3VtbWFyaXNlKHN1ZWxkb19wcm9tZWRpbyA9IG1lYW4oc3VlbGRvX2Z0KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBzdWVsZG9fcHJvbWVkaW8sIHkgPSBwdWVzdG8pKSArDQogIGdlb21fY29sKGZpbGwgPSBhenVsKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4PXN1ZWxkb19wcm9tZWRpbywwKSwgaGp1c3QgPSAxLjQsIHZqdXN0ID0gMC4zKSwNCiAgICAgICAgICAgIHNpemUgPSAzLCBjb2xvciA9ICJ3aGl0ZSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAuOSkpICsNCiAgbGFicyh0aXRsZSA9ICJTdWVsZG8gcHJvbWVkaW8gcG9yIHB1ZXN0byIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoZnVuY2lvbl9hbmFsaXNpcywgIi0gRW4gQVIkIiksDQogICAgICAgeCA9ICIiLCB5ID0gIiIsIGNhcHRpb24gPSBmdWVudGUpICsNCiAgZWplX3hfbiArDQogIGVzdGlsb3YNCg0KcmhfYXIgJT4lIA0KICBmaWx0ZXIoZnVuY2lvbl9yaCA9PSBmdW5jaW9uX2FuYWxpc2lzKSAlPiUgDQogIGdncGxvdChhZXMoeSA9IHB1ZXN0bywgZmlsbCA9IG5pdmVsX2Zvcm1hY2lvbikpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sNCkgKw0KICBsYWJzKHRpdGxlID0gIk5pdmVsIGRlIGZvcm1hY2nDs24gcG9yIHB1ZXN0byIsDQogICAgICAgc3VidGl0bGUgPSBmdW5jaW9uX2FuYWxpc2lzLA0KICAgICAgIHggPSAiIiwgeSA9ICIiLA0KICAgICAgIGZpbGwgPSAiTml2ZWwgZGUgRm9ybWFjacOzbiIsDQogICAgICAgY2FwdGlvbiA9IGZ1ZW50ZSkgKw0KICBlc3RpbG8NCg0KYGBgDQoNCiMgT3Ryb3MgQW7DoWxpc2lzDQoNCiMjIFByZWd1bnRhcyBiaXphcnJhcyBlbiBlbnRyZXZpc3Rhcy4NCg0KKioiwr9QZW5zw6FzIHRlbmVyIGhpam9zPyIvIsK/UG9yIHF1w6kgbm8gZXN0w6FzIGNhc2FkYT8iKioNCg0KQ3VhbmRvIGRpc2XDsWFtb3MgZXN0YSBlbmN1ZXN0YSwgbm9zIHBhcmVjacOzIHVuYSBidWVuYSBpZGVhIHByZWd1bnRhciBzb2JyZSBjdcOhbGVzIGZ1ZXJvbiBsYXMgcHJlZ3VudGFzIG3DoXMgZGVzdWJpY2FkYXMgbyBiaXphcnJhcyByZWFsaXphZGFzIGVuIHVuYSBlbnRyZXZpc3RhIGxhYm9yYWwuIFBlcm8gbnVuY2Egbm9zIGltYWdpbmFtb3MgcXVlIMOtYmFtb3MgYSBuZWNlc2l0YXIgZmlsdHJhciBwb3IgKipjaG9uZ28qKiAocGFyYSBzYWJlciBhIHF1w6kgbGxhbWFtb3MgKiJjaG9uZ28iKiBlbiBBcmdlbnRpbmEgW2VudHJhIGVuIGVzdGUgbGlua10oaHR0cHM6Ly93d3cuc2VyYXJnZW50aW5vLmNvbS9nZW50ZS9jb21vLWhhYmxhbW9zL3F1ZS1lcy11bi1jaG9uZ28pKS4NCg0KYGBge3IgYml6MSwgZWNobz1UUlVFfQ0KDQpwcmVnIDwtIGtpd2lbLGMoImdlbmVybyIsInByZWd1bnRhX2JpemFycmEiKV0gDQoNCm5hbWVzKHByZWcpIDwtIGMoImdlbmVybyIsICJwcmVndW50YSIpDQoNCmxpc3RhZG9fcHJlZyA8LSBwcmVnICU+JSANCiAgZmlsdGVyKHN0cl9kZXRlY3QocHJlZ3VudGEsICJoaWpvW3NdIil8DQogICAgICAgICAgIHN0cl9kZXRlY3QocHJlZ3VudGEsICJjYXNhZFthb118Y2FzYXIiKXwgDQogICAgICAgICAgIHN0cl9kZXRlY3QocHJlZ3VudGEsIm5vdmlvIil8DQogICAgICAgICAgIHN0cl9kZXRlY3QocHJlZ3VudGEsImNob25nbyIpKQ0KDQpgYGANCg0KQWwgcmVzcGVjdG8gcXVpc2ltb3Mgc2FiZXIgYSBjdcOhbnRhcyBtdWplcmVzIHkgaG9tYnJlcyBsZXMgaGFiw61hbiBoZWNobyBwcmVndW50YXMgZGVzdWJpY2FkYXMgc29icmUgc2kgdGVuZHLDrWFuIGhpam9zLCBvIHNpIHRlbsOtYW4gcGxhbmVzIGRlIGNhc2FtaWVudG8uIEVuIGByIG5yb3cobGlzdGFkb19wcmVnKWAgcmVzcHVlc3RhcyBlc3RvIGVzIGxvIHF1ZSBlbmNvbnRyYW1vczoNCg0KYGBge3IgYml6YXJyYX0NCg0KZ3QocHJlZyAlPiUgDQogIGZpbHRlcihzdHJfZGV0ZWN0KHByZWd1bnRhLCAiaGlqb1tzXSIpfA0KICAgICAgICAgICBzdHJfZGV0ZWN0KHByZWd1bnRhLCAiY2FzYWRbYW9dfGNhc2FyIil8IA0KICAgICAgICAgICBzdHJfZGV0ZWN0KHByZWd1bnRhLCJub3ZpbyIpfA0KICAgICAgICAgICBzdHJfZGV0ZWN0KHByZWd1bnRhLCJjaG9uZ28iKSkgJT4lIA0KICBncm91cF9ieShnZW5lcm8pICU+JSANCiAgc3VtbWFyaXNlIChuID0gbigpKSAlPiUgDQogIG11dGF0ZShmcmVxID0gcGVyY2VudChuL3N1bShuKSkpKSAlPiUgDQogIGNvbHNfbGFiZWwoZ2VuZXJvID0gIkfDqW5lcm8iLCANCiAgICAgICAgICAgICBuID0gIkNhbnRpZGFkIiwNCiAgICAgICAgICAgICBmcmVxID0gIlBvcmNlbnRhamUiKQ0KDQpwcmVnICU+JSANCiAgZmlsdGVyKHN0cl9kZXRlY3QocHJlZ3VudGEsICJoaWpvW3NdIil8DQogICAgICAgICAgIHN0cl9kZXRlY3QocHJlZ3VudGEsICJjYXNhZFthb118Y2FzYXIiKXwgDQogICAgICAgICAgIHN0cl9kZXRlY3QocHJlZ3VudGEsIm5vdmlvIil8DQogICAgICAgICAgIHN0cl9kZXRlY3QocHJlZ3VudGEsImNob25nbyIpKSAlPiUgDQogIGdyb3VwX2J5KGdlbmVybykgJT4lIA0KICBzdW1tYXJpc2UgKG4gPSBuKCkpICU+JSANCiAgbXV0YXRlKGZyZXEgPSBwZXJjZW50KG4vc3VtKG4pKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBnZW5lcm8sIHkgPSBuLCBmaWxsID0gZ2VuZXJvKSkgKw0KICBnZW9tX2NvbCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzg2MjRGNSIsICIjMUZDM0FBIikpICsNCiAgZXN0aWxvICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnModGl0bGUgPSAiTXVqZXJlcyB5IGhvbWJyZXMgYSBsb3MgcXVlIGxlcyBwcmVndW50YXJvbiBzaSBwZW5zYWJhbiB0ZW5lciBoaWpvcyBcbiBvIHNpIHBsYW5lYWJhbiBjYXNhcnNlIGVuIHVuYSBlbnRyZXZpc3RhIGxhYm9yYWwiLA0KICAgICAgIHggPSAiIiwgeT0gIiIsIGZpbGwgPSAiIiwNCiAgICAgICBjYXB0aW9uID0gZnVlbnRlKSANCmBgYA0KDQojIyBSZWxhY2nDs24gZW50cmUgc2F0aXNmYWNjacOzbiB5IHN1ZWxkb3MNCg0KUGFyYSBlc3RlIGFuw6FsaXNpcyBub3MgcHJlZ3VudGFtb3Mgc2kgaGF5IHJlbGFjacOzbiBlbnRyZSBlbCBuaXZlbCBzYWxhcmlhbCB5IGxhIHNhdGlzZmFjY2nDs24uDQoNClBhcmEgcmVzcG9uZGVyIGEgZXN0YSBwcmVndW50YSwgY3J1emFtb3MgbG9zIHN1ZWxkb3MgYnJ1dG9zIGRlIEFyZ2VudGluYSwgY29udHJhIGxvcyBuaXZlbGVzIGRlIHNhdGlzZmFjY2nDs24gY29uIGxhIGFjdHVhbCBlbXByZXNhIGRvbmRlIHRyYWJhamFuIGxhcyBwZXJzb25hcyBxdWUgcmVzcG9uZGllcm9uIGxhIGVuY3Vlc3RhLg0KDQpMb3MgcGFzb3MgcXVlIHNlZ3VpbW9zIGZ1ZXJvbiBsb3Mgc2lndWllbnRlczoNCg0KLSAgIEEgbG9zIHN1ZWxkb3MgYnJ1dG9zIGxvcyBzZWdtZW50YW1vcyBlbiA0IHBhcnRlcyBjb24gaWd1YWwgY2FudGlkYWQgZGUgcmVnaXN0cm9zIChjdWFydGlsZXMpLiBFcyBkZWNpciwgZW4gZWwgMcKwIGN1YXJ0aWwgdGVuZW1vcyBlbCAyNSUgZGUgbG9zIGRhdG9zLCBlbiBlbCBzZWd1bmRvIGN1YXJ0aWwgdGVuZW1vcyBlbCA1MCUgZGUgbG9zIGRhdG9zLCB5IGVuIGVsIDPCsCBjdWFydGlsIHRlbmVtb3MgZWwgNzUlIGRlIGxvcyBkYXRvcy4NCi0gICBFbiBlbCBwcmltZXIgY3VhcnRpbCBlc3TDoW4gbG9zIHN1ZWxkb3MgbcOhcyBiYWpvcywgeSBlbCA0wrAgbG9zIG3DoXMgYWx0b3MuDQotICAgTG9zIG5pdmVsZXMgZGUgc2F0aXNmYWNjacOzbiB2YW4gZGVsIDEgKFRvdGFsbWVudGUgSW5zYXRpc2ZlY2hvKSwgYWwgNSwgKFRvdGFsbWVudGUgU2F0aXNmZWNobykuDQoNCmBgYHtyIHNhdGlzZiwgb3V0LndpZHRoPSI4NSUifQ0KbGlicmFyeShnZ2FsbHV2aWFsKQ0KDQpzYXRpc2YgPC0gcmggJT4lIA0KICBmaWx0ZXIoIWlzLm5hKHNhdGlzZmFjY2lvbiksDQogICAgICAgICBnZW5lcm8gJWluJSBjKCJGZW1lbmlubyIsICJNYXNjdWxpbm8iKSwNCiAgICAgICAgIHBhaXMgPT0gIkFyZ2VudGluYSIpICU+JSANCiAgc2VsZWN0KGdlbmVybywgc3VlbGRvX2JydXRvLCBzYXRpc2ZhY2Npb24pDQoNCg0KcDI1IDwtIHByb2ZpbGluZ19udW0oc2F0aXNmKVsxLDddDQpwNTAgPC0gcHJvZmlsaW5nX251bShzYXRpc2YpWzEsOF0NCnA3NSA8LSBwcm9maWxpbmdfbnVtKHNhdGlzZilbMSw5XQ0KDQpzYXRpc2YgPC0gc2F0aXNmICU+JSANCiAgbXV0YXRlKGN1YXJ0aWwgPSBmYWN0b3IoY2FzZV93aGVuKA0KICAgIHN1ZWxkb19icnV0byAgPCAgIHAyNSAgfiAiMVEiLA0KICAgIHN1ZWxkb19icnV0byA+IHAyNSAmIHN1ZWxkb19icnV0byA8IHA1MCB+ICIyUSIsDQogICAgc3VlbGRvX2JydXRvID4gcDUwICYgc3VlbGRvX2JydXRvIDwgcDc1IH4gIjNRIiwNCiAgICBUUlVFICAgfiAiNFEiKSksDQogICAgc2F0aXNmYWNjaW9uID0gZmFjdG9yKHNhdGlzZmFjY2lvbiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIjEiLCIyIiwiMyIsIjQiLCI1IikpLCANCiAgICBjdWVudGEgPSAxKQ0KDQoNCnNhdGlzZiA8LSBzYXRpc2YgJT4lIA0KICBncm91cF9ieShnZW5lcm8sIHNhdGlzZmFjY2lvbiwgY3VhcnRpbCkgJT4lIA0KICBzdW1tYXJpc2UoY2FudCA9IG4oKSkNCg0KDQoNCmdncGxvdChhcy5kYXRhLmZyYW1lKHNhdGlzZiksIGFlcyh5ID0gY2FudCwgYXhpczEgPSBjdWFydGlsLCBheGlzMiA9IHNhdGlzZmFjY2lvbikpICsNCiAgZ2VvbV9hbGx1dml1bShhZXMoZmlsbCA9IGdlbmVybyksIHdpZHRoID0gMS8xMiwgYWxwaGEgPSAwLjQpICsNCiAgZ2VvbV9zdHJhdHVtKHdpZHRoID0gMS8xMiwgZmlsbCA9ICIjODg4MkY3IikgKw0KICBnZW9tX2xhYmVsKHN0YXQgPSAic3RyYXR1bSIsIGFlcyhsYWJlbCA9IGFmdGVyX3N0YXQoc3RyYXR1bSkpKSArDQogIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygiU3VlbGRvIEJydXRvIHBvciBDdWFydGlsIiwgIk5pdmVsIGRlIFNhdGlzZmFjY2nDs24iKSwgZXhwYW5kID0gYyguMDUsIC4wNSkpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBlc3RpbG8gKw0KICBsYWJzKHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBuaXZlbCBzYWxhcmlhbCB5IHNhdGlzZmFjY2nDs24gY29uIGxhIGVtcHJlc2EiLA0KICAgICAgIHkgPSAiIiwgY2FwdGlvbiA9IGZ1ZW50ZSwgZmlsbCA9ICJHw6luZXJvIikNCg0KYGBgDQoNCiMjIMK/Q8OzbW8gc2UgbGxhbWEgZWwgw6FyZWE/DQoNCkRlbnRybyBkZSBsb3MgZGl2ZXJzb3MgYW7DoWxpc2lzIHF1ZSBwb2TDrWFtb3MgaGFjZXIgY29uIGxvcyBkYXRvcyByZWNvbGVjdGFkb3MgYWxnbyBzb2JyZSBsbyBxdWUgaW5kYWdhbW9zIGZ1ZSBzb2JyZSBjw7NtbyBzZSBsbGFtYSBlbCDDoXJlYS4NCg0KYGBge3Igbm9tYnJlLWFyZWF9DQpub21icmVzIDwtIGtpd2lbICwgIm5vbWJyZV9hcmVhIl0NCg0Kbm9tYnJlcyA8LSBub21icmVzICU+JSANCiAgZmlsdGVyKCFpcy5uYShub21icmVfYXJlYSkpDQoNCmRpc3RpbnRvcyA8LSBkaXN0aW5jdCguZGF0YSA9IG5vbWJyZXMpICU+JSBjb3VudCgpICU+JSBwdWxsKCkNCg0Kbm9tYnJlcyA8LSBub21icmVzICU+JSANCiAgbXV0YXRlKG5vbWJyZSA9IHN0cl90b190aXRsZShub21icmVfYXJlYSwgbG9jYWxlID0gImVzIikpICU+JSANCiAgZ3JvdXBfYnkobm9tYnJlKSAlPiUgDQogIGNvdW50KHNvcnQgPSBULCBuYW1lID0gInJ0YXMiKSAlPiUgDQogIGhlYWQoMTApICU+JSANCiAgdW5ncm91cCgpDQoNCg0KZ2dwbG90KG5vbWJyZXMsIGFlcyh4ID0gcnRhcywgeSA9IHJlb3JkZXIobm9tYnJlLHJ0YXMpKSkgKw0KICBnZW9tX2NvbChmaWxsID0gIiMzNDREN0UiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4PXJ0YXMsIDApLCANCiAgICAgICAgICAgICAgICBoanVzdCA9IC0uNSwgDQogICAgICAgICAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICAgICAgc2l6ZSA9IDQsIA0KICAgICAgICAgICAgY29sb3IgPSAiZGFya2dyZXkiKSsNCiAgZXN0aWxvdiArDQogIGxhYnModGl0bGUgPSAiVG9wIDEwIGRlIG5vbWJyZXMgcGFyYSBlbCDDoXJlYSBkZSBSUkhIIiwgDQogICAgICAgeCA9ICIiLCB5ID0gIiIsIA0KICAgICAgIGNhcHRpb24gPSBmdWVudGUpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNDMwKSwgYnJlYWtzID0gYygxMDAsIDIwMCwgMzAwLCA0MDApKQ0KYGBgDQoNCkVuIHRvdGFsLCBlbmNvbnRyYW1vcyBgciBkaXN0aW50b3NgIGZvcm1hcyBkaWZlcmVudGVzIGRlIGxsYW1hciBhbCDDoXJlYS4gVHJpc3RlbWVudGUgbm9zIHNvcnByZW5kZSBsYSBjYW50aWRhZCBkZSB2ZWNlcyBxdWUgZW5jb250cmFtb3MgcXVlIGVsIMOhcmVhIGHDum4gc2UgbGxhbWEgKipPZmljaW5hIERlIFBlcnNvbmFsKiouDQo=