Introducción

Se busca a través de este EDA responder algunas preguntas que consideramos importantes y relevantes para FORM. Y así tener información útil para tomar decisiones estratégicas en la administración y operación de la empresa.

Las preguntas se mostraran a continuación.

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.2     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.2     ✔ tibble    3.2.1
## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggplot2)
library(stringr)
library(readr)
library(dplyr)
library(tidyr)
library(grid)
library(psych)
## 
## Attaching package: 'psych'
## 
## The following objects are masked from 'package:ggplot2':
## 
##     %+%, alpha
library(gplots)
## 
## Attaching package: 'gplots'
## 
## The following object is masked from 'package:stats':
## 
##     lowess

Pregunta 1

¿Que estado civil estan lo que se dan de baja?

Abrir base de datos

# file.choose()
BDD_FORM_BAJAS_2023 <- read_csv("/Users/davidcavazos/Desktop/BDD_FORM_BAJAS_2023.csv")
## Rows: 279 Columns: 28
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (24): Apellidos, Nombre, Fecha de Nacimiento, Género, RFC, Fecha de Alta...
## dbl  (4): No., SD, CP, Número de Télefono
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Seleccionar las variables de Motivo de baja y Estado Civil en un nuevo data frame.

mbaja <- select(BDD_FORM_BAJAS_2023,`Motivo de Baja`,`Estado Civil`) %>% na.omit(mbaja)

Agrupar la categoría con diferentes nombres cambiando a el mismo nombre

mbaja$"Motivo de Baja"[mbaja$"Motivo de Baja" == "Inducida."] <- "Inducida"

mbaja$"Motivo de Baja"[mbaja$"Motivo de Baja" == "Inducida (Faltas)"] <- "Inducida por faltas"

mbaja$"Motivo de Baja"[mbaja$"Motivo de Baja" == "Inducida (Faltas no dio los tiempos)"] <- "Inducida"

Calcular los porcentajes por categoría y estado civil

porcentajes <- mbaja %>%
  group_by(`Estado Civil`, `Motivo de Baja`) %>%
  summarise(Frecuencia = n()) %>%
  group_by(`Estado Civil`) %>%
  mutate(Pct = scales::percent(Frecuencia / sum(Frecuencia)))
## `summarise()` has grouped output by 'Estado Civil'. You can override using the
## `.groups` argument.

Gráfica de barras apliadas

plot <- ggplot(porcentajes, aes(x = `Estado Civil`, y = Frecuencia, fill = `Motivo de Baja`)) +
  geom_bar(stat = "identity") +
  theme_minimal() +
  theme(
    panel.grid.major = element_line(color = "grey", linewidth = 0.4, linetype = "dotted"),  # Líneas verticales
    panel.grid.minor = element_line(color = "grey", linewidth = 0.4, linetype = "dotted")  # Líneas horizontales
  )+
  ggtitle("Relación entre Motivo de Baja y Estado Civil")

Agregar etiquetas de porcentaje

plot + geom_text(aes(label = Pct), position = position_stack(vjust = 0.5),size=2)

Interpretación 1

Por lo que podemos ver en la gráfica, la gran mayoría de las bajas en todas las categorías son por separación voluntaria y realmente no se logra ver una correlación entre el estado civil de la persona y el motivo de baja, lo que podría indicar una alta rotación de empleados en los trabajos de maquila en general o podría ser un indicador de que hay varias áreas de oportunidad en cuestión de amenidades, salarios, bonos, oportunidades de crecimiento en la empresa, traslado o prestaciones que la empresa ofrece además de las básicas dictadas por la ley.

Pregunta 2

¿Cual es la relacion entre la edad y las bajas?

Carga de datos

#file.choose()
bajas<-read_csv("/Users/davidcavazos/Desktop/form_bajas_22.csv")
## Rows: 238 Columns: 25
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (23): APELLIDOS, NOMBRE, FECHA DE NACIMIENTO, GENERO, RFC, FECHA DE ALTA...
## dbl  (2): DIAS LABORADOS, SALARIO DIARIO IMSS
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#view(bajas)

Modificación de base de datos

#Estoy creando un data frame nuevo con las columnas necesarias para hacer la gráfica

bajas1 <- select(bajas,"NOMBRE","APELLIDOS","FECHA DE NACIMIENTO","DIAS LABORADOS","SALARIO DIARIO IMSS") %>% na.omit(bajas1)
#view(bajas1)

Estadísiticos Descriptivos

Dias Laborados

summary(bajas1$`DIAS LABORADOS`)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    0.00    8.75   19.00   80.00   49.25 1966.00

Salario

summary(bajas1$`SALARIO DIARIO IMSS`)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   144.4   180.7   180.7   177.7   180.7   500.0

Edad de colaboradores

#Aquí reviso que formato tienen las columnas 

str(bajas1)
## tibble [212 × 5] (S3: tbl_df/tbl/data.frame)
##  $ NOMBRE             : chr [1:212] "MARIA FERNANDA" "EMANUEL" "TRINIDAD" "WILMAR" ...
##  $ APELLIDOS          : chr [1:212] "JIMENEZ ALANIS" "JAUREGUI SANCHEZ" "GARCIA CAZARES" "LOPEZ ROMERO" ...
##  $ FECHA DE NACIMIENTO: chr [1:212] "7/10/1998" "10/3/1998" "5/25/1997" "9/4/2001" ...
##  $ DIAS LABORADOS     : num [1:212] 423 35 102 63 34 23 30 6 0 141 ...
##  $ SALARIO DIARIO IMSS: num [1:212] 177 181 181 177 181 ...
##  - attr(*, "na.action")= 'omit' Named int [1:26] 8 27 28 58 67 110 135 136 137 141 ...
##   ..- attr(*, "names")= chr [1:26] "8" "27" "28" "58" ...
#Aquí estoy haciendo una extracción del año de nacimiento excluyendo los días y meses. 

#Decidí hacer esto porque hay filas en las que está escrito M/D/A y otras D/M/A


bajas1$ANIO<-str_sub(bajas1$`FECHA DE NACIMIENTO`,-4,-1)

#Convirtiendo la columna de "ANIO" en integer

bajas1$ANIO <- as.integer(bajas1$ANIO)

str(bajas1)
## tibble [212 × 6] (S3: tbl_df/tbl/data.frame)
##  $ NOMBRE             : chr [1:212] "MARIA FERNANDA" "EMANUEL" "TRINIDAD" "WILMAR" ...
##  $ APELLIDOS          : chr [1:212] "JIMENEZ ALANIS" "JAUREGUI SANCHEZ" "GARCIA CAZARES" "LOPEZ ROMERO" ...
##  $ FECHA DE NACIMIENTO: chr [1:212] "7/10/1998" "10/3/1998" "5/25/1997" "9/4/2001" ...
##  $ DIAS LABORADOS     : num [1:212] 423 35 102 63 34 23 30 6 0 141 ...
##  $ SALARIO DIARIO IMSS: num [1:212] 177 181 181 177 181 ...
##  $ ANIO               : int [1:212] 1998 1998 1997 2001 2002 2000 2000 1999 2002 1994 ...
##  - attr(*, "na.action")= 'omit' Named int [1:26] 8 27 28 58 67 110 135 136 137 141 ...
##   ..- attr(*, "names")= chr [1:26] "8" "27" "28" "58" ...
#Aquí creó una nueva columna llamada "EDAD" restando el año actual con el de "ANIO

bajas1$EDAD <- 2023-bajas1$ANIO

#Había un error en el cual existían tres filas que tenían edad de 1 por lo cual le pedí que solo mostrara los que son mayor a 18.

bajas1 <- bajas1[bajas1$EDAD >18,]

Histograma de frecuencias

hist(bajas1$EDAD,col = blues9,xlab = "Edad",ylab ="Frecuencia" ,main = "Bajas por Edad")

Interpretación 2

Nos damos cuenta de que la rotación de personal se ve más alta en los colaboradores más jóvenes. Esto es información útil ya que nos permite tomar decisiones adecuadas para mejorar la satisfacción laboral en específico para estos rangos de edades. Con esta gráfica podemos entrar más a detalle en el área de oportunidad y así entender las razones de la alta rotación. Nos damos cuenta de que se tiene que hacer un esfuerzo por mejorar la relación con las nuevas generaciones o contratar a personas mayores.

Pregunta 3

¿A que edad ingresan a trabajar nuevos empleados a FORM y que genero son?

Carga de datos

rh <- read.csv("/Users/davidcavazos/Desktop/form_rh_datos.csv")

#View(rh)

edad <- select(rh,"FECHA.DE.ALTA", "FECHA.DE.NACIMIENTO") 

#str(rh)

Modificacion de Datos

rh$año_alta <- str_sub(rh$FECHA.DE.ALTA, -4, -1) 
rh$año_nac <- str_sub(rh$FECHA.DE.NACIMIENTO, -4, -1)
rh$año_alta <- as.integer(rh$año_alta)
rh$año_nac <- as.integer(rh$año_nac)

rh <- rh[rh$año_alta > 2013,]
rh <- rh[-30,]

Calcular la edad de ingreso y Medidas de Dispersion

rh$edad_ingreso <- rh$año_alta - rh$año_nac
rh <- rh[rh$edad_ingreso > 18,]

edad_de_ingreso_max <- max(rh$edad_ingreso)
print(edad_de_ingreso_max)
## [1] 60
edad_de_ingreso_min <- min(rh$edad_ingreso)
print(edad_de_ingreso_min)
## [1] 19
edad_de_ingreso_mean <- mean(rh$edad_ingreso)
print(edad_de_ingreso_mean)
## [1] 34.92308

Histograma de Edad

hist(rh$edad_ingreso,col = "#009E73" ,xlab = "Edad",main = "Alta por Edad")

Histograma Genero

ggplot(rh, aes(edad_ingreso, fill = GENERO)) + 
  geom_histogram(bins=10) + 
  labs(y="") 

Interpretacion 3

Podemos analizar en las graficas que la edad mas comun para ingresar a trabajar a FORM es entre los 25 - 30 lo que nos puede ayudar a crear campañas de reclutamiento enfocadas en el mercado de edad al que los empleados de FORM estan enfocados, FORM cuenta con un gran rango de edades comenzando desde los 19 y llegando hasta los 60. Este ultimo siendo el grupo mas pequeño dentro de la empresa mientras que los jovenes de 18 - 20 tienden a ser un porcentaje mas alto de hombres. Nos damos cuenta con la grafica que FORM le abre las puertas a muchas personas y ofrece oportunidades de trabajo para nuevas generaciones y personas con experiencia

Tabla de frecuencia/contingencia

Importar datasets

bajas = read.csv("/Users/davidcavazos/Desktop/form_bajas_22.csv")
dfbajas = bajas 
#View(bajas)
empleados = read.csv("/Users/davidcavazos/Desktop/form_rh_datos.csv")
empleadosdf = empleados
#View(empleados)

LIMPIEZA BASE DE DATOS

bajas$ESTADO.CIVIL = gsub("MATRIOMONIO", "MATRIMONIO", bajas$ESTADO.CIVIL)

MOTIVO DE BAJA

motivo_bajas = ggplot(bajas, aes(x = MOTIVO.DE.BAJA)) +
  geom_bar() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))
estado_civil = ggplot(bajas, aes(x = ESTADO.CIVIL)) +
  geom_bar() 

FRECUENCIA DE DÍAS LABORADOS

hist(bajas$DIAS.LABORADOS,col = blues9,xlab = "DIAS LABORADOS",ylab ="Frecuencia" ,main = "Días Laborados")

SEPARACION DE FECHAS - BAJAS

df_rotacion = bajas %>% select(GENERO, FECHA.DE.ALTA,BAJA, MOTIVO.DE.BAJA, DIAS.LABORADOS, PUESTO)
df_rotacion = df_rotacion %>% separate(BAJA, into = c("MONTH_BAJA", "DAY_BAJA", "YEAR_BAJA"), sep = "/")
## Warning: Expected 3 pieces. Missing pieces filled with `NA` in 15 rows [27, 28, 58, 135,
## 137, 141, 151, 178, 179, 198, 203, 205, 207, 212, 238].

SEPARACION DE FECHAS - ALTAS

df_rotacion = df_rotacion %>% separate(FECHA.DE.ALTA, into = c("MONTH_ALTA", "DAY_ALTA", "YEAR_ALTA"), sep = "/")
## Warning: Expected 3 pieces. Missing pieces filled with `NA` in 1 rows [238].

HISTOGRAMAS MESES EN LOS QUE DAN BAJAS

df_rotacion$MONTH_BAJA = as.numeric(df_rotacion$MONTH_BAJA)
hist(df_rotacion$MONTH_BAJA,col = blues9,xlab = "MONTH_BAJA",ylab ="Frecuencia" ,main = "Bajas por Mes")

ASIGNACIÓN DE MESES

df_months <- df_rotacion %>%
  mutate(NAME_MONTH = case_when(
    MONTH_BAJA == 1 ~ "Enero",
    MONTH_BAJA == 2 ~ "Febrero",
    MONTH_BAJA == 3 ~ "Marzo",
    MONTH_BAJA == 4 ~ "Abril",
    MONTH_BAJA == 5 ~ "Mayo",
    MONTH_BAJA == 6 ~ "Junio",
    MONTH_BAJA == 7 ~ "Julio",
    MONTH_BAJA == 8 ~ "Agosto",
    MONTH_BAJA == 9 ~ "Septiembre",
    MONTH_BAJA == 10 ~ "Octubre",
    MONTH_BAJA == 11 ~ "Noviembre",
    MONTH_BAJA == 12 ~ "Diciembre"
  )) %>%
  filter(NAME_MONTH %in% c("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")) %>%
  select(GENERO, MONTH_BAJA, DAY_ALTA, YEAR_ALTA, MOTIVO.DE.BAJA, NAME_MONTH, PUESTO)
#View(df_months)

GRAFICO DE BARRAS

barplot_subcategory <- ggplot(df_months, aes(x = NAME_MONTH)) +
  geom_bar(fill = "#F46C22", width = 0.5) +
  ggtitle("Bajas por Mes")
barplot_subcategory 

TABLA DE FRECUENCIAS

month_frecuencias = table(df_months$NAME_MONTH)
meses_cronologicos <- c("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")

Datos adicionales requeridos

Para llevar a cabo un análisis más completo y una comprensión más profunda del clima organizacional en Form, resulta fundamental la implementación de encuestas cualitativas. Estas encuestas abordarán aspectos clave, tales como la satisfacción con las instalaciones laborales, las condiciones de trabajo, los horarios, el transporte al lugar de trabajo, la remuneración, la dinámica de liderazgo en Form, la comodidad en el entorno de trabajo y su posible correlación con las tasas de rotación, tanto voluntaria como involuntaria, y otras relaciones y respuestas relevantes que podrían identificarse.

LS0tCnRpdGxlOiAiRW50cmVnYWJsZSAyIgphdXRob3I6ICJSb2dlaXJvLERhdmlkLFJvZ2VsaW8sTWFyaWFuYSxMeW5ldHRlIgpkYXRlOiAiMjAyMy0wOS0wNSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IFRSVUUKICAgIHRvY19mbG9hdDogVFJVRQogICAgY29kZV9kb3dubG9hZDogVFJVRQogICAgdGhlbWU6ICJ1bml0ZWQiCi0tLQoKIyMgPHNwYW4gc3R5bGUgPSJjb2xvcjpkYXJrb3JhbmdlIj4gSW50cm9kdWNjacOzbgoKU2UgYnVzY2EgYSB0cmF2w6lzIGRlIGVzdGUgRURBIHJlc3BvbmRlciBhbGd1bmFzIHByZWd1bnRhcyBxdWUgY29uc2lkZXJhbW9zIGltcG9ydGFudGVzIHkgcmVsZXZhbnRlcyBwYXJhIEZPUk0uIFkgYXPDrSB0ZW5lciBpbmZvcm1hY2nDs24gw7p0aWwgcGFyYSB0b21hciBkZWNpc2lvbmVzIGVzdHJhdMOpZ2ljYXMgZW4gbGEgYWRtaW5pc3RyYWNpw7NuIHkgb3BlcmFjacOzbiBkZSBsYSBlbXByZXNhLgoKTGFzIHByZWd1bnRhcyBzZSBtb3N0cmFyYW4gYSBjb250aW51YWNpw7NuLgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShncmlkKQpsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KGdwbG90cykKYGBgCgojIyA8c3BhbiBzdHlsZSA9ImNvbG9yOmRhcmtvcmFuZ2UiPiAqKlByZWd1bnRhIDEqKiAKCioqwr9RdWUgZXN0YWRvIGNpdmlsIGVzdGFuIGxvIHF1ZSBzZSBkYW4gZGUgYmFqYT8qKgoKIyMjIEFicmlyIGJhc2UgZGUgZGF0b3MKCmBgYHtyfQojIGZpbGUuY2hvb3NlKCkKQkREX0ZPUk1fQkFKQVNfMjAyMyA8LSByZWFkX2NzdigiL1VzZXJzL2RhdmlkY2F2YXpvcy9EZXNrdG9wL0JERF9GT1JNX0JBSkFTXzIwMjMuY3N2IikKYGBgCgojIyMgU2VsZWNjaW9uYXIgbGFzIHZhcmlhYmxlcyBkZSBNb3Rpdm8gZGUgYmFqYSB5IEVzdGFkbyBDaXZpbCBlbiB1biBudWV2byBkYXRhIGZyYW1lLgoKYGBge3J9Cm1iYWphIDwtIHNlbGVjdChCRERfRk9STV9CQUpBU18yMDIzLGBNb3Rpdm8gZGUgQmFqYWAsYEVzdGFkbyBDaXZpbGApICU+JSBuYS5vbWl0KG1iYWphKQpgYGAKCiMjIyBBZ3J1cGFyIGxhIGNhdGVnb3LDrWEgY29uIGRpZmVyZW50ZXMgbm9tYnJlcyBjYW1iaWFuZG8gYSBlbCBtaXNtbyBub21icmUKYGBge3J9CgptYmFqYSQiTW90aXZvIGRlIEJhamEiW21iYWphJCJNb3Rpdm8gZGUgQmFqYSIgPT0gIkluZHVjaWRhLiJdIDwtICJJbmR1Y2lkYSIKCm1iYWphJCJNb3Rpdm8gZGUgQmFqYSJbbWJhamEkIk1vdGl2byBkZSBCYWphIiA9PSAiSW5kdWNpZGEgKEZhbHRhcykiXSA8LSAiSW5kdWNpZGEgcG9yIGZhbHRhcyIKCm1iYWphJCJNb3Rpdm8gZGUgQmFqYSJbbWJhamEkIk1vdGl2byBkZSBCYWphIiA9PSAiSW5kdWNpZGEgKEZhbHRhcyBubyBkaW8gbG9zIHRpZW1wb3MpIl0gPC0gIkluZHVjaWRhIgpgYGAKCiMjIyBDYWxjdWxhciBsb3MgcG9yY2VudGFqZXMgcG9yIGNhdGVnb3LDrWEgeSBlc3RhZG8gY2l2aWwKYGBge3J9CnBvcmNlbnRhamVzIDwtIG1iYWphICU+JQogIGdyb3VwX2J5KGBFc3RhZG8gQ2l2aWxgLCBgTW90aXZvIGRlIEJhamFgKSAlPiUKICBzdW1tYXJpc2UoRnJlY3VlbmNpYSA9IG4oKSkgJT4lCiAgZ3JvdXBfYnkoYEVzdGFkbyBDaXZpbGApICU+JQogIG11dGF0ZShQY3QgPSBzY2FsZXM6OnBlcmNlbnQoRnJlY3VlbmNpYSAvIHN1bShGcmVjdWVuY2lhKSkpCmBgYAoKIyMgPHNwYW4gc3R5bGUgPSJjb2xvcjpkYXJrb3JhbmdlIj4gKipHcsOhZmljYSBkZSBiYXJyYXMgYXBsaWFkYXMqKgpgYGB7cn0KcGxvdCA8LSBnZ3Bsb3QocG9yY2VudGFqZXMsIGFlcyh4ID0gYEVzdGFkbyBDaXZpbGAsIHkgPSBGcmVjdWVuY2lhLCBmaWxsID0gYE1vdGl2byBkZSBCYWphYCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyZXkiLCBsaW5ld2lkdGggPSAwLjQsIGxpbmV0eXBlID0gImRvdHRlZCIpLCAgIyBMw61uZWFzIHZlcnRpY2FsZXMKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JleSIsIGxpbmV3aWR0aCA9IDAuNCwgbGluZXR5cGUgPSAiZG90dGVkIikgICMgTMOtbmVhcyBob3Jpem9udGFsZXMKICApKwogIGdndGl0bGUoIlJlbGFjacOzbiBlbnRyZSBNb3Rpdm8gZGUgQmFqYSB5IEVzdGFkbyBDaXZpbCIpCgpgYGAKCiMjIyBBZ3JlZ2FyIGV0aXF1ZXRhcyBkZSBwb3JjZW50YWplCmBgYHtyfQpwbG90ICsgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFBjdCksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLHNpemU9MikKYGBgCgojIyA8c3BhbiBzdHlsZSA9ImNvbG9yOmRhcmtvcmFuZ2UiPiBJbnRlcnByZXRhY2nDs24gMSAKClBvciBsbyBxdWUgcG9kZW1vcyB2ZXIgZW4gbGEgZ3LDoWZpY2EsIGxhIGdyYW4gbWF5b3LDrWEgZGUgbGFzIGJhamFzIGVuIHRvZGFzIGxhcyBjYXRlZ29yw61hcyBzb24gcG9yIHNlcGFyYWNpw7NuIHZvbHVudGFyaWEgeSByZWFsbWVudGUgbm8gc2UgbG9ncmEgdmVyIHVuYSBjb3JyZWxhY2nDs24gZW50cmUgZWwgZXN0YWRvIGNpdmlsIGRlIGxhIHBlcnNvbmEgeSBlbCBtb3Rpdm8gZGUgYmFqYSwgbG8gcXVlIHBvZHLDrWEgaW5kaWNhciB1bmEgYWx0YSByb3RhY2nDs24gZGUgZW1wbGVhZG9zIGVuIGxvcyB0cmFiYWpvcyBkZSBtYXF1aWxhIGVuIGdlbmVyYWwgbyBwb2Ryw61hIHNlciB1biBpbmRpY2Fkb3IgZGUgcXVlIGhheSB2YXJpYXMgw6FyZWFzIGRlIG9wb3J0dW5pZGFkIGVuIGN1ZXN0acOzbiBkZSBhbWVuaWRhZGVzLCBzYWxhcmlvcywgYm9ub3MsIG9wb3J0dW5pZGFkZXMgZGUgY3JlY2ltaWVudG8gZW4gbGEgZW1wcmVzYSwgdHJhc2xhZG8gbyBwcmVzdGFjaW9uZXMgcXVlIGxhIGVtcHJlc2Egb2ZyZWNlIGFkZW3DoXMgZGUgbGFzIGLDoXNpY2FzIGRpY3RhZGFzIHBvciBsYSBsZXkuCgojIyA8c3BhbiBzdHlsZSA9ImNvbG9yOmRhcmtvcmFuZ2UiPiAqKlByZWd1bnRhIDIqKgoKKirCv0N1YWwgZXMgbGEgcmVsYWNpb24gZW50cmUgbGEgZWRhZCB5IGxhcyBiYWphcz8qKgoKIyMjIENhcmdhIGRlIGRhdG9zCgpgYGB7cn0KI2ZpbGUuY2hvb3NlKCkKYmFqYXM8LXJlYWRfY3N2KCIvVXNlcnMvZGF2aWRjYXZhem9zL0Rlc2t0b3AvZm9ybV9iYWphc18yMi5jc3YiKQojdmlldyhiYWphcykKYGBgCgoKIyMjICoqTW9kaWZpY2FjacOzbiBkZSBiYXNlIGRlIGRhdG9zKioKCmBgYHtyfQoKI0VzdG95IGNyZWFuZG8gdW4gZGF0YSBmcmFtZSBudWV2byBjb24gbGFzIGNvbHVtbmFzIG5lY2VzYXJpYXMgcGFyYSBoYWNlciBsYSBncsOhZmljYQoKYmFqYXMxIDwtIHNlbGVjdChiYWphcywiTk9NQlJFIiwiQVBFTExJRE9TIiwiRkVDSEEgREUgTkFDSU1JRU5UTyIsIkRJQVMgTEFCT1JBRE9TIiwiU0FMQVJJTyBESUFSSU8gSU1TUyIpICU+JSBuYS5vbWl0KGJhamFzMSkKI3ZpZXcoYmFqYXMxKQpgYGAKCiMjIDxzcGFuIHN0eWxlID0iY29sb3I6ZGFya29yYW5nZSI+ICoqRXN0YWTDrXNpdGljb3MgRGVzY3JpcHRpdm9zKioKCiMjIyBEaWFzIExhYm9yYWRvcwpgYGB7cn0Kc3VtbWFyeShiYWphczEkYERJQVMgTEFCT1JBRE9TYCkKYGBgCiMjIyBTYWxhcmlvCmBgYHtyfQpzdW1tYXJ5KGJhamFzMSRgU0FMQVJJTyBESUFSSU8gSU1TU2ApCmBgYAoKIyMjIEVkYWQgZGUgY29sYWJvcmFkb3JlcwoKYGBge3J9CgojQXF1w60gcmV2aXNvIHF1ZSBmb3JtYXRvIHRpZW5lbiBsYXMgY29sdW1uYXMgCgpzdHIoYmFqYXMxKQpgYGAKYGBge3J9CgojQXF1w60gZXN0b3kgaGFjaWVuZG8gdW5hIGV4dHJhY2Npw7NuIGRlbCBhw7FvIGRlIG5hY2ltaWVudG8gZXhjbHV5ZW5kbyBsb3MgZMOtYXMgeSBtZXNlcy4gCgojRGVjaWTDrSBoYWNlciBlc3RvIHBvcnF1ZSBoYXkgZmlsYXMgZW4gbGFzIHF1ZSBlc3TDoSBlc2NyaXRvIE0vRC9BIHkgb3RyYXMgRC9NL0EKCgpiYWphczEkQU5JTzwtc3RyX3N1YihiYWphczEkYEZFQ0hBIERFIE5BQ0lNSUVOVE9gLC00LC0xKQoKI0NvbnZpcnRpZW5kbyBsYSBjb2x1bW5hIGRlICJBTklPIiBlbiBpbnRlZ2VyCgpiYWphczEkQU5JTyA8LSBhcy5pbnRlZ2VyKGJhamFzMSRBTklPKQoKc3RyKGJhamFzMSkKYGBgCmBgYHtyfQoKCiNBcXXDrSBjcmXDsyB1bmEgbnVldmEgY29sdW1uYSBsbGFtYWRhICJFREFEIiByZXN0YW5kbyBlbCBhw7FvIGFjdHVhbCBjb24gZWwgZGUgIkFOSU8KCmJhamFzMSRFREFEIDwtIDIwMjMtYmFqYXMxJEFOSU8KCiNIYWLDrWEgdW4gZXJyb3IgZW4gZWwgY3VhbCBleGlzdMOtYW4gdHJlcyBmaWxhcyBxdWUgdGVuw61hbiBlZGFkIGRlIDEgcG9yIGxvIGN1YWwgbGUgcGVkw60gcXVlIHNvbG8gbW9zdHJhcmEgbG9zIHF1ZSBzb24gbWF5b3IgYSAxOC4KCmJhamFzMSA8LSBiYWphczFbYmFqYXMxJEVEQUQgPjE4LF0KYGBgCgojIyA8c3BhbiBzdHlsZSA9ImNvbG9yOmRhcmtvcmFuZ2UiPiAqKkhpc3RvZ3JhbWEgZGUgZnJlY3VlbmNpYXMqKgoKYGBge3J9Cmhpc3QoYmFqYXMxJEVEQUQsY29sID0gYmx1ZXM5LHhsYWIgPSAiRWRhZCIseWxhYiA9IkZyZWN1ZW5jaWEiICxtYWluID0gIkJhamFzIHBvciBFZGFkIikKYGBgCgojIyA8c3BhbiBzdHlsZSA9ImNvbG9yOmRhcmtvcmFuZ2UiPiAqKkludGVycHJldGFjacOzbiAyKioKCk5vcyBkYW1vcyBjdWVudGEgZGUgcXVlIGxhIHJvdGFjacOzbiBkZSBwZXJzb25hbCBzZSB2ZSBtw6FzIGFsdGEgZW4gbG9zIGNvbGFib3JhZG9yZXMgbcOhcyBqw7N2ZW5lcy4gRXN0byBlcyBpbmZvcm1hY2nDs24gw7p0aWwgeWEgcXVlIG5vcyBwZXJtaXRlIHRvbWFyIGRlY2lzaW9uZXMgYWRlY3VhZGFzIHBhcmEgbWVqb3JhciBsYSBzYXRpc2ZhY2Npw7NuIGxhYm9yYWwgZW4gZXNwZWPDrWZpY28gcGFyYSBlc3RvcyByYW5nb3MgZGUgZWRhZGVzLiBDb24gZXN0YSBncsOhZmljYSBwb2RlbW9zIGVudHJhciBtw6FzIGEgZGV0YWxsZSBlbiBlbCDDoXJlYSBkZSBvcG9ydHVuaWRhZCB5IGFzw60gZW50ZW5kZXIgbGFzIHJhem9uZXMgZGUgbGEgYWx0YSByb3RhY2nDs24uIE5vcyBkYW1vcyBjdWVudGEgZGUgcXVlIHNlIHRpZW5lIHF1ZSBoYWNlciB1biBlc2Z1ZXJ6byBwb3IgbWVqb3JhciBsYSByZWxhY2nDs24gY29uIGxhcyBudWV2YXMgZ2VuZXJhY2lvbmVzIG8gY29udHJhdGFyIGEgcGVyc29uYXMgbWF5b3Jlcy4gCgojIyA8c3BhbiBzdHlsZSA9ImNvbG9yOmRhcmtvcmFuZ2UiPiAqKlByZWd1bnRhIDMqKgoKKirCv0EgcXVlIGVkYWQgaW5ncmVzYW4gYSB0cmFiYWphciBudWV2b3MgZW1wbGVhZG9zIGEgRk9STSB5IHF1ZSBnZW5lcm8gc29uPyoqCgojIyMgQ2FyZ2EgZGUgZGF0b3MKYGBge3J9CgpyaCA8LSByZWFkLmNzdigiL1VzZXJzL2RhdmlkY2F2YXpvcy9EZXNrdG9wL2Zvcm1fcmhfZGF0b3MuY3N2IikKCiNWaWV3KHJoKQoKZWRhZCA8LSBzZWxlY3QocmgsIkZFQ0hBLkRFLkFMVEEiLCAiRkVDSEEuREUuTkFDSU1JRU5UTyIpIAoKI3N0cihyaCkKYGBgCgojIyMgTW9kaWZpY2FjaW9uIGRlIERhdG9zCgpgYGB7cn0KcmgkYcOxb19hbHRhIDwtIHN0cl9zdWIocmgkRkVDSEEuREUuQUxUQSwgLTQsIC0xKSAKcmgkYcOxb19uYWMgPC0gc3RyX3N1YihyaCRGRUNIQS5ERS5OQUNJTUlFTlRPLCAtNCwgLTEpCnJoJGHDsW9fYWx0YSA8LSBhcy5pbnRlZ2VyKHJoJGHDsW9fYWx0YSkKcmgkYcOxb19uYWMgPC0gYXMuaW50ZWdlcihyaCRhw7FvX25hYykKCnJoIDwtIHJoW3JoJGHDsW9fYWx0YSA+IDIwMTMsXQpyaCA8LSByaFstMzAsXQoKYGBgCgojIyMgQ2FsY3VsYXIgbGEgZWRhZCBkZSBpbmdyZXNvIHkgTWVkaWRhcyBkZSBEaXNwZXJzaW9uCgpgYGB7cn0KcmgkZWRhZF9pbmdyZXNvIDwtIHJoJGHDsW9fYWx0YSAtIHJoJGHDsW9fbmFjCnJoIDwtIHJoW3JoJGVkYWRfaW5ncmVzbyA+IDE4LF0KCmVkYWRfZGVfaW5ncmVzb19tYXggPC0gbWF4KHJoJGVkYWRfaW5ncmVzbykKcHJpbnQoZWRhZF9kZV9pbmdyZXNvX21heCkKCmVkYWRfZGVfaW5ncmVzb19taW4gPC0gbWluKHJoJGVkYWRfaW5ncmVzbykKcHJpbnQoZWRhZF9kZV9pbmdyZXNvX21pbikKCmVkYWRfZGVfaW5ncmVzb19tZWFuIDwtIG1lYW4ocmgkZWRhZF9pbmdyZXNvKQpwcmludChlZGFkX2RlX2luZ3Jlc29fbWVhbikKCmBgYAoKIyMgPHNwYW4gc3R5bGUgPSJjb2xvcjpkYXJrb3JhbmdlIj4gKipIaXN0b2dyYW1hIGRlIEVkYWQqKgpgYGB7cn0KaGlzdChyaCRlZGFkX2luZ3Jlc28sY29sID0gIiMwMDlFNzMiICx4bGFiID0gIkVkYWQiLG1haW4gPSAiQWx0YSBwb3IgRWRhZCIpCmBgYAoKIyMgPHNwYW4gc3R5bGUgPSJjb2xvcjpkYXJrb3JhbmdlIj4gKipIaXN0b2dyYW1hIEdlbmVybyoqCmBgYHtyfQpnZ3Bsb3QocmgsIGFlcyhlZGFkX2luZ3Jlc28sIGZpbGwgPSBHRU5FUk8pKSArIAogIGdlb21faGlzdG9ncmFtKGJpbnM9MTApICsgCiAgbGFicyh5PSIiKSAKYGBgCgojIyA8c3BhbiBzdHlsZSA9ImNvbG9yOmRhcmtvcmFuZ2UiPiAqKkludGVycHJldGFjaW9uIDMqKgoKUG9kZW1vcyBhbmFsaXphciBlbiBsYXMgZ3JhZmljYXMgcXVlIGxhIGVkYWQgbWFzIGNvbXVuIHBhcmEgaW5ncmVzYXIgYSB0cmFiYWphciBhIEZPUk0gZXMgZW50cmUgbG9zIDI1IC0gMzAgbG8gcXVlIG5vcyBwdWVkZSBheXVkYXIgYSBjcmVhciBjYW1wYcOxYXMgZGUgcmVjbHV0YW1pZW50byBlbmZvY2FkYXMgZW4gZWwgbWVyY2FkbyBkZSBlZGFkIGFsIHF1ZSBsb3MgZW1wbGVhZG9zIGRlIEZPUk0gZXN0YW4gZW5mb2NhZG9zLCBGT1JNIGN1ZW50YSBjb24gdW4gZ3JhbiByYW5nbyBkZSBlZGFkZXMgY29tZW56YW5kbyBkZXNkZSBsb3MgMTkgeSBsbGVnYW5kbyBoYXN0YSBsb3MgNjAuIEVzdGUgdWx0aW1vIHNpZW5kbyBlbCBncnVwbyBtYXMgcGVxdWXDsW8gZGVudHJvIGRlIGxhIGVtcHJlc2EgbWllbnRyYXMgcXVlIGxvcyBqb3ZlbmVzIGRlIDE4IC0gMjAgdGllbmRlbiBhIHNlciB1biBwb3JjZW50YWplIG1hcyBhbHRvIGRlIGhvbWJyZXMuIE5vcyBkYW1vcyBjdWVudGEgY29uIGxhIGdyYWZpY2EgcXVlIEZPUk0gbGUgYWJyZSBsYXMgcHVlcnRhcyBhIG11Y2hhcyBwZXJzb25hcyB5IG9mcmVjZSBvcG9ydHVuaWRhZGVzIGRlIHRyYWJham8gcGFyYSBudWV2YXMgZ2VuZXJhY2lvbmVzIHkgcGVyc29uYXMgY29uIGV4cGVyaWVuY2lhICAKCiMjIDxzcGFuIHN0eWxlID0iY29sb3I6ZGFya29yYW5nZSI+ICoqVGFibGEgZGUgZnJlY3VlbmNpYS9jb250aW5nZW5jaWEqKgoKIyMjIEltcG9ydGFyIGRhdGFzZXRzCmBgYHtyfQpiYWphcyA9IHJlYWQuY3N2KCIvVXNlcnMvZGF2aWRjYXZhem9zL0Rlc2t0b3AvZm9ybV9iYWphc18yMi5jc3YiKQpkZmJhamFzID0gYmFqYXMgCiNWaWV3KGJhamFzKQplbXBsZWFkb3MgPSByZWFkLmNzdigiL1VzZXJzL2RhdmlkY2F2YXpvcy9EZXNrdG9wL2Zvcm1fcmhfZGF0b3MuY3N2IikKZW1wbGVhZG9zZGYgPSBlbXBsZWFkb3MKI1ZpZXcoZW1wbGVhZG9zKQpgYGAKCiMjIyBMSU1QSUVaQSBCQVNFIERFIERBVE9TCmBgYHtyfQpiYWphcyRFU1RBRE8uQ0lWSUwgPSBnc3ViKCJNQVRSSU9NT05JTyIsICJNQVRSSU1PTklPIiwgYmFqYXMkRVNUQURPLkNJVklMKQpgYGAKCiMjIyBNT1RJVk8gREUgQkFKQQpgYGB7cn0KbW90aXZvX2JhamFzID0gZ2dwbG90KGJhamFzLCBhZXMoeCA9IE1PVElWTy5ERS5CQUpBKSkgKwogIGdlb21fYmFyKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpCmVzdGFkb19jaXZpbCA9IGdncGxvdChiYWphcywgYWVzKHggPSBFU1RBRE8uQ0lWSUwpKSArCiAgZ2VvbV9iYXIoKSAKYGBgCgojIyMgRlJFQ1VFTkNJQSBERSBEw41BUyBMQUJPUkFET1MKYGBge3J9Cmhpc3QoYmFqYXMkRElBUy5MQUJPUkFET1MsY29sID0gYmx1ZXM5LHhsYWIgPSAiRElBUyBMQUJPUkFET1MiLHlsYWIgPSJGcmVjdWVuY2lhIiAsbWFpbiA9ICJEw61hcyBMYWJvcmFkb3MiKQpgYGAKCiMjIyBTRVBBUkFDSU9OIERFIEZFQ0hBUyAtIEJBSkFTCmBgYHtyfQpkZl9yb3RhY2lvbiA9IGJhamFzICU+JSBzZWxlY3QoR0VORVJPLCBGRUNIQS5ERS5BTFRBLEJBSkEsIE1PVElWTy5ERS5CQUpBLCBESUFTLkxBQk9SQURPUywgUFVFU1RPKQpkZl9yb3RhY2lvbiA9IGRmX3JvdGFjaW9uICU+JSBzZXBhcmF0ZShCQUpBLCBpbnRvID0gYygiTU9OVEhfQkFKQSIsICJEQVlfQkFKQSIsICJZRUFSX0JBSkEiKSwgc2VwID0gIi8iKQpgYGAKCiMjIyBTRVBBUkFDSU9OIERFIEZFQ0hBUyAtIEFMVEFTCmBgYHtyfQpkZl9yb3RhY2lvbiA9IGRmX3JvdGFjaW9uICU+JSBzZXBhcmF0ZShGRUNIQS5ERS5BTFRBLCBpbnRvID0gYygiTU9OVEhfQUxUQSIsICJEQVlfQUxUQSIsICJZRUFSX0FMVEEiKSwgc2VwID0gIi8iKQpgYGAKCiMjIyBISVNUT0dSQU1BUyBNRVNFUyBFTiBMT1MgUVVFIERBTiBCQUpBUwpgYGB7cn0KZGZfcm90YWNpb24kTU9OVEhfQkFKQSA9IGFzLm51bWVyaWMoZGZfcm90YWNpb24kTU9OVEhfQkFKQSkKaGlzdChkZl9yb3RhY2lvbiRNT05USF9CQUpBLGNvbCA9IGJsdWVzOSx4bGFiID0gIk1PTlRIX0JBSkEiLHlsYWIgPSJGcmVjdWVuY2lhIiAsbWFpbiA9ICJCYWphcyBwb3IgTWVzIikKYGBgCgojIyMgQVNJR05BQ0nDk04gREUgTUVTRVMKYGBge3J9CmRmX21vbnRocyA8LSBkZl9yb3RhY2lvbiAlPiUKICBtdXRhdGUoTkFNRV9NT05USCA9IGNhc2Vfd2hlbigKICAgIE1PTlRIX0JBSkEgPT0gMSB+ICJFbmVybyIsCiAgICBNT05USF9CQUpBID09IDIgfiAiRmVicmVybyIsCiAgICBNT05USF9CQUpBID09IDMgfiAiTWFyem8iLAogICAgTU9OVEhfQkFKQSA9PSA0IH4gIkFicmlsIiwKICAgIE1PTlRIX0JBSkEgPT0gNSB+ICJNYXlvIiwKICAgIE1PTlRIX0JBSkEgPT0gNiB+ICJKdW5pbyIsCiAgICBNT05USF9CQUpBID09IDcgfiAiSnVsaW8iLAogICAgTU9OVEhfQkFKQSA9PSA4IH4gIkFnb3N0byIsCiAgICBNT05USF9CQUpBID09IDkgfiAiU2VwdGllbWJyZSIsCiAgICBNT05USF9CQUpBID09IDEwIH4gIk9jdHVicmUiLAogICAgTU9OVEhfQkFKQSA9PSAxMSB+ICJOb3ZpZW1icmUiLAogICAgTU9OVEhfQkFKQSA9PSAxMiB+ICJEaWNpZW1icmUiCiAgKSkgJT4lCiAgZmlsdGVyKE5BTUVfTU9OVEggJWluJSBjKCJFbmVybyIsICJGZWJyZXJvIiwgIk1hcnpvIiwgIkFicmlsIiwgIk1heW8iLCAiSnVuaW8iLCAiSnVsaW8iLCAiQWdvc3RvIiwgIlNlcHRpZW1icmUiLCAiT2N0dWJyZSIsICJOb3ZpZW1icmUiLCAiRGljaWVtYnJlIikpICU+JQogIHNlbGVjdChHRU5FUk8sIE1PTlRIX0JBSkEsIERBWV9BTFRBLCBZRUFSX0FMVEEsIE1PVElWTy5ERS5CQUpBLCBOQU1FX01PTlRILCBQVUVTVE8pCiNWaWV3KGRmX21vbnRocykKYGBgCgojIyMgR1JBRklDTyBERSBCQVJSQVMgCmBgYHtyfQpiYXJwbG90X3N1YmNhdGVnb3J5IDwtIGdncGxvdChkZl9tb250aHMsIGFlcyh4ID0gTkFNRV9NT05USCkpICsKICBnZW9tX2JhcihmaWxsID0gIiNGNDZDMjIiLCB3aWR0aCA9IDAuNSkgKwogIGdndGl0bGUoIkJhamFzIHBvciBNZXMiKQpiYXJwbG90X3N1YmNhdGVnb3J5IApgYGAKCiMjIyBUQUJMQSBERSBGUkVDVUVOQ0lBUwpgYGB7cn0KbW9udGhfZnJlY3VlbmNpYXMgPSB0YWJsZShkZl9tb250aHMkTkFNRV9NT05USCkKbWVzZXNfY3Jvbm9sb2dpY29zIDwtIGMoIkVuZXJvIiwgIkZlYnJlcm8iLCAiTWFyem8iLCAiQWJyaWwiLCAiTWF5byIsICJKdW5pbyIsICJKdWxpbyIsICJBZ29zdG8iLCAiU2VwdGllbWJyZSIsICJPY3R1YnJlIiwgIk5vdmllbWJyZSIsICJEaWNpZW1icmUiKQpgYGAKCiMjIDxzcGFuIHN0eWxlID0iY29sb3I6ZGFya29yYW5nZSI+ICoqRGF0b3MgYWRpY2lvbmFsZXMgcmVxdWVyaWRvcyoqCgpQYXJhIGxsZXZhciBhIGNhYm8gdW4gYW7DoWxpc2lzIG3DoXMgY29tcGxldG8geSB1bmEgY29tcHJlbnNpw7NuIG3DoXMgcHJvZnVuZGEgZGVsIGNsaW1hIG9yZ2FuaXphY2lvbmFsIGVuIEZvcm0sIHJlc3VsdGEgZnVuZGFtZW50YWwgbGEgaW1wbGVtZW50YWNpw7NuIGRlIGVuY3Vlc3RhcyBjdWFsaXRhdGl2YXMuIEVzdGFzIGVuY3Vlc3RhcyBhYm9yZGFyw6FuIGFzcGVjdG9zIGNsYXZlLCB0YWxlcyBjb21vIGxhIHNhdGlzZmFjY2nDs24gY29uIGxhcyBpbnN0YWxhY2lvbmVzIGxhYm9yYWxlcywgbGFzIGNvbmRpY2lvbmVzIGRlIHRyYWJham8sIGxvcyBob3JhcmlvcywgZWwgdHJhbnNwb3J0ZSBhbCBsdWdhciBkZSB0cmFiYWpvLCBsYSByZW11bmVyYWNpw7NuLCBsYSBkaW7DoW1pY2EgZGUgbGlkZXJhemdvIGVuIEZvcm0sIGxhIGNvbW9kaWRhZCBlbiBlbCBlbnRvcm5vIGRlIHRyYWJham8geSBzdSBwb3NpYmxlIGNvcnJlbGFjacOzbiBjb24gbGFzIHRhc2FzIGRlIHJvdGFjacOzbiwgdGFudG8gdm9sdW50YXJpYSBjb21vIGludm9sdW50YXJpYSwgeSBvdHJhcyByZWxhY2lvbmVzIHkgcmVzcHVlc3RhcyByZWxldmFudGVzIHF1ZSBwb2Ryw61hbiBpZGVudGlmaWNhcnNlLgoK