Cargar librerias

library(foreign)
library(dplyr)        # data manipulation 
library(forcats)      # to work with categorical variables
library(ggplot2)      # data visualization 
library(janitor)      # data exploration and cleaning 
library(Hmisc)        # several useful functions for data analysis 
library(psych)        # functions for multivariate analysis 
library(naniar)       # summaries and visualization of missing values NAs
library(dlookr)       # summaries and visualization of missing values NAs
library(corrplot)     # correlation plots
library(jtools)       # presentation of regression analysis 
library(lmtest)       # diagnostic checks - linear regression analysis 
library(car)          # diagnostic checks - linear regression analysis
library(olsrr)        # diagnostic checks - linear regression analysis 
library(kableExtra)   # HTML table attributes
library(factoextra)   # provides functions to extract and visualize the output of exploratory multivariate data analyses
### Instalar librerias necesarias
# install.packages("tibble")
library(tibble)
# install.packages("tidyverse")
library(tidyverse)
library(ggfortify)    # data visualization tools for statistical analysis 
library(plyr)
library(base)

RH Colaboradores/Bajas

Limpieza de Datos

Las bases de datos fueron divididas en dos ya que en una se toman en cuenta a los colaboradores de la empresa y en otra las bajas que se tuvieron por distintas razones, esto con la intención de poder obtener mejores resultados e interpretaciones más claras.

Importar la base de datos RH de la empresa FORM

#file.choose()
RhColab<-read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos (limpias) CSV /BaseDatosL RH_Colaboradores.csv")
RhBajas<-read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos (limpias) CSV /BaseD_Limpia RH_ Bajas .csv")

Verifiquemos la estructura de la base de datos

str(RhColab)
## 'data.frame':    999 obs. of  13 variables:
##  $ numero_de_empleado: int  1 2 3 4 5 6 7 8 9 10 ...
##  $ nombre_completo   : chr  "NICOLAS MARTINEZ DE LOERA" "MARIANA DE LEON MORENO" "JOSE LUIS HERNANDEZ CERVANTES" "MARIA CAZARES MORALES" ...
##  $ edad              : int  67 43 73 32 57 38 55 26 27 37 ...
##  $ genero            : chr  "MASCULINO" "FEMENINO" "MASCULINO" "FEMENINO" ...
##  $ fecha_de_alta     : chr  "1/7/2010" "1/7/2011" "22/11/2011" "30/1/2013" ...
##  $ antiguedad        : int  12 11 11 9 8 8 7 6 5 5 ...
##  $ BAJA              : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ puesto            : chr  "Supervisor de Máquin" "Supervisor de pegado" "Externo" "SUPERVISORA" ...
##  $ departamento      : chr  "Produccion Cartón MDL" "Produccion Cartón MDL" "Externo" "Produccion Cartón MC" ...
##  $ mano_de_obra      : chr  "Indirecto" "Indirecto" "Indirecto" "Indirecto" ...
##  $ salario_diario    : num  177 177 177 337 441 ...
##  $ colonia           : chr  "UNIDAD LABORAL" "SANTA TERESITA" "VILLAS DE HUINALA" "PUEBLO NUEVO" ...
##  $ municipio         : chr  "SAN NICOLAS DE LOS G" "APODACA" "APODACA" "APODACA" ...
str(RhBajas)
## 'data.frame':    237 obs. of  13 variables:
##  $ nombre              : chr  "MARIO VALDEZ ORTIZ" "ISABEL BARRIOS MENDEZ" "MARIA ELIZABETH GOMEZ HERNANDEZ" "ALONDRA ABIGAIL ESCARCIA GOMEZ" ...
##  $ edad                : int  32 36 23 21 29 46 29 31 50 19 ...
##  $ genero              : chr  "MASCULINO" "FEMENINO" "FEMENINO" "FEMENINO" ...
##  $ fecha_de_alta       : chr  "9/3/2020" "9/11/2021" "10/11/2021" "10/11/2021" ...
##  $ motivo_de_baja      : chr  "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" ...
##  $ dias_de_trabajo     : int  628 60 59 59 51 37 37 31 18 224 ...
##  $ baja                : chr  "27/11/2021" "8/1/2022" "8/1/2022" "8/1/2022" ...
##  $ puesto_que_desempeña: chr  "DISEÑO" "AYUDANTE GENERAL" "AYUDANTE GENERAL" "AYUDANTE GENERAL" ...
##  $ salario_imss        : num  500 152 152 152 152 ...
##  $ colonia             : chr  "SAN NICOLAS DE LOS G" "COLINAS DEL AEROPÑUERTO" "PUEBLO NUEVO" "PUEBLO NUEVO" ...
##  $ municipio           : chr  "SAN NICOLAS DE LOS G" "PESQUERIA" "APODACA" "APODACA" ...
##  $ estado              : chr  "NUEVO LEÓN" "NUEVO LEÓN" "NUEVO LEÓN" "NUEVO LEÓN" ...
##  $ estado_civil        : chr  "SOLTERO" "UNIÓN LIBRE" "CASADO" "SOLTERO" ...

Tipos de Variables

Variable<-c("Nombre","Edad", "Genero", "Fecha de alta", "Motivo de baja", "Días de trbajo","Baja", "Puesto que desempeña", "Salario IMSS", "Colonia", "Municipio", "Estado", "Estado Civil", "Número de empleado", "Nombre completo ", "Antiguedad", "Departamento", "Mano de obra","Salario diario")

Type<-c("qualitative (nominal)", "quantitative (discrete)", "qualitative (nominal)","qualiitative (ordinal)","qualitative (nominal)","qualitative (nominal)","quantitative (contonua)","qualitative (nominal)","qualitative (nominal)","qualitative (nominal)","qualitative (nominal)","quantitative (discrete)","qualitative (nominal)","qualitative (nominal)","qualitative (discrete)","qualitative (nominal)","quantitative (continua)","quantitative (continua)","quantitative (continua)")

table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
Nombre qualitative (nominal)
Edad quantitative (discrete)
Genero qualitative (nominal)
Fecha de alta qualiitative (ordinal)
Motivo de baja qualitative (nominal)
Días de trbajo qualitative (nominal)
Baja quantitative (contonua)
Puesto que desempeña qualitative (nominal)
Salario IMSS qualitative (nominal)
Colonia qualitative (nominal)
Municipio qualitative (nominal)
Estado quantitative (discrete)
Estado Civil qualitative (nominal)
Número de empleado qualitative (nominal)
Nombre completo qualitative (discrete)
Antiguedad qualitative (nominal)
Departamento quantitative (continua)
Mano de obra quantitative (continua)
Salario diario quantitative (continua)

Contamos con 13 variables y 999 observaciones en total

Seleccionar columnas / variables

RhColab1<-RhColab 
RhBajas1<-RhBajas 

Limpieza de datos

RhColab1<-RhColab %>% select(-one_of('numero_de_empleado', 'BAJA', 'edad'))

Renombramos las columnas / variables seleccionadas

Se renombraron las columnas y variables seleccionadas para poder tener conceptos más cortos para a la hora de visualizar tener una mejor y más clara interpretación de la información.

summary(RhColab1)
##  nombre_completo       genero          fecha_de_alta        antiguedad    
##  Length:999         Length:999         Length:999         Min.   : 0.000  
##  Class :character   Class :character   Class :character   1st Qu.: 0.000  
##  Mode  :character   Mode  :character   Mode  :character   Median : 0.000  
##                                                           Mean   : 1.425  
##                                                           3rd Qu.: 2.000  
##                                                           Max.   :12.000  
##                                                           NA's   :886     
##     puesto          departamento       mano_de_obra       salario_diario 
##  Length:999         Length:999         Length:999         Min.   :144.4  
##  Class :character   Class :character   Class :character   1st Qu.:176.7  
##  Mode  :character   Mode  :character   Mode  :character   Median :180.7  
##                                                           Mean   :181.4  
##                                                           3rd Qu.:180.7  
##                                                           Max.   :441.4  
##                                                           NA's   :886    
##    colonia           municipio        
##  Length:999         Length:999        
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
##                                       
## 
names(RhColab1)<-c('Nom_Comp', 'Gen', 'Fecha_alta', 'Ant', 'Puesto', 'Dep', 'MDO', 'Sal_Diario', 'Col', 'Mun')
names(RhBajas1)<-c('Nom', 'Edad', 'Gen', 'Fecha_alta', 'MB', 'Días_trab', 'Baja', 'PuestDes', 'Sal_IMSS', 'Col', 'Mun', 'Estado', 'EstCiv')

Convertimos “fecha_nacimiento” a formato de fecha

Se convirtió a formato de fecha la variable de fecha_nacimiento para su correcta interpretación dentro de los códigos.

RhColab1$Fecha_alta<-as.Date(RhColab$fecha_de_alta,format="%d/%m/%Y")
RhBajas1$Fecha_alta<-as.Date(RhBajas1$Fecha_alta,format="%d/%m/%Y")
RhBajas1$Baja<-as.Date(RhBajas1$Baja,format="%d/%m/%Y") 

Eliminar NA’s y sustituir con 0’s

Esto para evitar errores a la hora de utilizar la base para generar un análisis más certero.

sum(is.na(RhColab1))
## [1] 2658
sum(is.na(RhBajas1))
## [1] 0
RhBajas1[is.na(RhBajas1)]<-0


summary(RhColab1)
##    Nom_Comp             Gen              Fecha_alta              Ant        
##  Length:999         Length:999         Min.   :2010-07-01   Min.   : 0.000  
##  Class :character   Class :character   1st Qu.:2020-08-28   1st Qu.: 0.000  
##  Mode  :character   Mode  :character   Median :2022-02-23   Median : 0.000  
##                                        Mean   :2021-01-16   Mean   : 1.425  
##                                        3rd Qu.:2022-07-05   3rd Qu.: 2.000  
##                                        Max.   :2022-08-23   Max.   :12.000  
##                                        NA's   :886          NA's   :886     
##     Puesto              Dep                MDO              Sal_Diario   
##  Length:999         Length:999         Length:999         Min.   :144.4  
##  Class :character   Class :character   Class :character   1st Qu.:176.7  
##  Mode  :character   Mode  :character   Mode  :character   Median :180.7  
##                                                           Mean   :181.4  
##                                                           3rd Qu.:180.7  
##                                                           Max.   :441.4  
##                                                           NA's   :886    
##      Col                Mun           
##  Length:999         Length:999        
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
##                                       
## 
summary(RhBajas1)
##      Nom                 Edad           Gen              Fecha_alta        
##  Length:237         Min.   : 0.00   Length:237         Min.   :2016-10-12  
##  Class :character   1st Qu.:23.00   Class :character   1st Qu.:2022-01-19  
##  Mode  :character   Median :29.00   Mode  :character   Median :2022-04-04  
##                     Mean   :30.52                      Mean   :2022-02-10  
##                     3rd Qu.:37.00                      3rd Qu.:2022-06-14  
##                     Max.   :61.00                      Max.   :2022-08-17  
##       MB              Días_trab            Baja              PuestDes        
##  Length:237         Min.   :   0.00   Min.   :2021-11-27   Length:237        
##  Class :character   1st Qu.:   9.00   1st Qu.:2022-03-01   Class :character  
##  Mode  :character   Median :  21.00   Median :2022-05-06   Mode  :character  
##                     Mean   :  83.42   Mean   :2022-05-05                     
##                     3rd Qu.:  49.00   3rd Qu.:2022-07-07                     
##                     Max.   :1966.00   Max.   :2022-08-25                     
##     Sal_IMSS         Col                Mun               Estado         
##  Min.   :144.4   Length:237         Length:237         Length:237        
##  1st Qu.:180.7   Class :character   Class :character   Class :character  
##  Median :180.7   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :178.6                                                           
##  3rd Qu.:180.7                                                           
##  Max.   :500.0                                                           
##     EstCiv         
##  Length:237        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 
RhColab1 <- na.omit(RhColab1)
RhBajas1 <- na.omit(RhBajas1)


summary(RhColab1)
##    Nom_Comp             Gen              Fecha_alta              Ant        
##  Length:113         Length:113         Min.   :2010-07-01   Min.   : 0.000  
##  Class :character   Class :character   1st Qu.:2020-08-28   1st Qu.: 0.000  
##  Mode  :character   Mode  :character   Median :2022-02-23   Median : 0.000  
##                                        Mean   :2021-01-16   Mean   : 1.425  
##                                        3rd Qu.:2022-07-05   3rd Qu.: 2.000  
##                                        Max.   :2022-08-23   Max.   :12.000  
##     Puesto              Dep                MDO              Sal_Diario   
##  Length:113         Length:113         Length:113         Min.   :144.4  
##  Class :character   Class :character   Class :character   1st Qu.:176.7  
##  Mode  :character   Mode  :character   Mode  :character   Median :180.7  
##                                                           Mean   :181.4  
##                                                           3rd Qu.:180.7  
##                                                           Max.   :441.4  
##      Col                Mun           
##  Length:113         Length:113        
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
## 
summary(RhBajas1)  
##      Nom                 Edad           Gen              Fecha_alta        
##  Length:237         Min.   : 0.00   Length:237         Min.   :2016-10-12  
##  Class :character   1st Qu.:23.00   Class :character   1st Qu.:2022-01-19  
##  Mode  :character   Median :29.00   Mode  :character   Median :2022-04-04  
##                     Mean   :30.52                      Mean   :2022-02-10  
##                     3rd Qu.:37.00                      3rd Qu.:2022-06-14  
##                     Max.   :61.00                      Max.   :2022-08-17  
##       MB              Días_trab            Baja              PuestDes        
##  Length:237         Min.   :   0.00   Min.   :2021-11-27   Length:237        
##  Class :character   1st Qu.:   9.00   1st Qu.:2022-03-01   Class :character  
##  Mode  :character   Median :  21.00   Median :2022-05-06   Mode  :character  
##                     Mean   :  83.42   Mean   :2022-05-05                     
##                     3rd Qu.:  49.00   3rd Qu.:2022-07-07                     
##                     Max.   :1966.00   Max.   :2022-08-25                     
##     Sal_IMSS         Col                Mun               Estado         
##  Min.   :144.4   Length:237         Length:237         Length:237        
##  1st Qu.:180.7   Class :character   Class :character   Class :character  
##  Median :180.7   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :178.6                                                           
##  3rd Qu.:180.7                                                           
##  Max.   :500.0                                                           
##     EstCiv         
##  Length:237        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 
str(RhColab1)
## 'data.frame':    113 obs. of  10 variables:
##  $ Nom_Comp  : chr  "NICOLAS MARTINEZ DE LOERA" "MARIANA DE LEON MORENO" "JOSE LUIS HERNANDEZ CERVANTES" "MARIA CAZARES MORALES" ...
##  $ Gen       : chr  "MASCULINO" "FEMENINO" "MASCULINO" "FEMENINO" ...
##  $ Fecha_alta: Date, format: "2010-07-01" "2011-07-01" ...
##  $ Ant       : int  12 11 11 9 8 8 7 6 5 5 ...
##  $ Puesto    : chr  "Supervisor de Máquin" "Supervisor de pegado" "Externo" "SUPERVISORA" ...
##  $ Dep       : chr  "Produccion Cartón MDL" "Produccion Cartón MDL" "Externo" "Produccion Cartón MC" ...
##  $ MDO       : chr  "Indirecto" "Indirecto" "Indirecto" "Indirecto" ...
##  $ Sal_Diario: num  177 177 177 337 441 ...
##  $ Col       : chr  "UNIDAD LABORAL" "SANTA TERESITA" "VILLAS DE HUINALA" "PUEBLO NUEVO" ...
##  $ Mun       : chr  "SAN NICOLAS DE LOS G" "APODACA" "APODACA" "APODACA" ...
##  - attr(*, "na.action")= 'omit' Named int [1:886] 114 115 116 117 118 119 120 121 122 123 ...
##   ..- attr(*, "names")= chr [1:886] "114" "115" "116" "117" ...
str(RhBajas1)
## 'data.frame':    237 obs. of  13 variables:
##  $ Nom       : chr  "MARIO VALDEZ ORTIZ" "ISABEL BARRIOS MENDEZ" "MARIA ELIZABETH GOMEZ HERNANDEZ" "ALONDRA ABIGAIL ESCARCIA GOMEZ" ...
##  $ Edad      : int  32 36 23 21 29 46 29 31 50 19 ...
##  $ Gen       : chr  "MASCULINO" "FEMENINO" "FEMENINO" "FEMENINO" ...
##  $ Fecha_alta: Date, format: "2020-03-09" "2021-11-09" ...
##  $ MB        : chr  "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" ...
##  $ Días_trab : int  628 60 59 59 51 37 37 31 18 224 ...
##  $ Baja      : Date, format: "2021-11-27" "2022-01-08" ...
##  $ PuestDes  : chr  "DISEÑO" "AYUDANTE GENERAL" "AYUDANTE GENERAL" "AYUDANTE GENERAL" ...
##  $ Sal_IMSS  : num  500 152 152 152 152 ...
##  $ Col       : chr  "SAN NICOLAS DE LOS G" "COLINAS DEL AEROPÑUERTO" "PUEBLO NUEVO" "PUEBLO NUEVO" ...
##  $ Mun       : chr  "SAN NICOLAS DE LOS G" "PESQUERIA" "APODACA" "APODACA" ...
##  $ Estado    : chr  "NUEVO LEÓN" "NUEVO LEÓN" "NUEVO LEÓN" "NUEVO LEÓN" ...
##  $ EstCiv    : chr  "SOLTERO" "UNIÓN LIBRE" "CASADO" "SOLTERO" ...

Calculemos la variable “age” en años

Esto para poder realizar caracterisitcas adicionales de “colabradores”.

library(lubridate)


edad<-trunc((RhColab1$Fecha_alta %--% RhColab1$Fecha_alta) / years(1)) # %--% creates a time interval based on as.date() format
RhColab1$edad<-edad

edad<-trunc((RhBajas1$Fecha_alta %--% RhBajas1$Fecha_alta) / years(1))
edad<-trunc((RhBajas1$Baja %--% RhBajas1$Baja) / years(1))

Convertir a caracter variables a factor

Esto para poder crear estadisticos descriptivos

###  Colab1
RhColab1$Gen<-as.factor(RhColab1$Gen)
RhColab1$Puesto<-as.factor(RhColab1$Puesto)
RhColab1$Dep<-as.factor(RhColab1$Dep)
RhColab1$Mun<-as.factor(RhColab1$Mun)
RhColab1$Col<-as.factor(RhColab1$Col)


###  Bajas1 

RhBajas1$Gen<-as.factor(RhBajas1$Gen)
RhBajas1$MB<-as.factor(RhBajas1$MB)
RhBajas1$Días_trab<-as.factor(RhBajas1$Días_trab)
RhBajas1$PuestDes<-as.factor(RhBajas1$PuestDes)
RhBajas1$Col<-as.factor(RhBajas1$Col)
RhBajas1$Mun<-as.factor(RhBajas1$Mun)
RhBajas1$Estado<-as.factor(RhBajas1$Estado)
RhBajas1$EstCiv<-as.factor(RhBajas1$EstCiv)

Verificamos la estructura de RhColab1 y RhBajas1

str(RhColab1)
## 'data.frame':    113 obs. of  11 variables:
##  $ Nom_Comp  : chr  "NICOLAS MARTINEZ DE LOERA" "MARIANA DE LEON MORENO" "JOSE LUIS HERNANDEZ CERVANTES" "MARIA CAZARES MORALES" ...
##  $ Gen       : Factor w/ 2 levels "FEMENINO","MASCULINO": 2 1 2 1 1 2 1 2 2 1 ...
##  $ Fecha_alta: Date, format: "2010-07-01" "2011-07-01" ...
##  $ Ant       : int  12 11 11 9 8 8 7 6 5 5 ...
##  $ Puesto    : Factor w/ 29 levels "AY. GENERAL",..: 27 28 10 29 29 8 7 4 3 7 ...
##  $ Dep       : Factor w/ 22 levels "","Ay.flexo",..: 18 18 13 17 8 4 8 19 4 10 ...
##  $ MDO       : chr  "Indirecto" "Indirecto" "Indirecto" "Indirecto" ...
##  $ Sal_Diario: num  177 177 177 337 441 ...
##  $ Col       : Factor w/ 73 levels "ALAMOS DEL PARQUE",..: 64 61 69 51 56 18 1 52 14 5 ...
##  $ Mun       : Factor w/ 9 levels "APODACA","CAÑADA BLANCA",..: 9 1 1 1 1 8 1 1 8 9 ...
##  $ edad      : num  0 0 0 0 0 0 0 0 0 0 ...
##  - attr(*, "na.action")= 'omit' Named int [1:886] 114 115 116 117 118 119 120 121 122 123 ...
##   ..- attr(*, "names")= chr [1:886] "114" "115" "116" "117" ...
summary(RhColab1)
##    Nom_Comp                Gen       Fecha_alta              Ant        
##  Length:113         FEMENINO :61   Min.   :2010-07-01   Min.   : 0.000  
##  Class :character   MASCULINO:52   1st Qu.:2020-08-28   1st Qu.: 0.000  
##  Mode  :character                  Median :2022-02-23   Median : 0.000  
##                                    Mean   :2021-01-16   Mean   : 1.425  
##                                    3rd Qu.:2022-07-05   3rd Qu.: 2.000  
##                                    Max.   :2022-08-23   Max.   :12.000  
##                                                                         
##               Puesto                      Dep         MDO           
##  AYUDANTE GENERAL:59                        :40   Length:113        
##  COSTURERA       :10   Producción Retorn    :10   Class :character  
##  AY. GENERAL     : 7   Costura              : 7   Mode  :character  
##  SOLDADOR        : 5   Produccion Cartón MDL: 7                     
##  CHOFER          : 4   Stabilus             : 7                     
##  RESIDENTE       : 4   Cedis                : 6                     
##  (Other)         :24   (Other)              :36                     
##    Sal_Diario                      Col            Mun          edad  
##  Min.   :144.4   PUEBLO NUEVO        :27   APODACA  :72   Min.   :0  
##  1st Qu.:176.7   CANTORAL            : 4   JUAREZ   :10   1st Qu.:0  
##  Median :180.7   CAÑADA BLANCA       : 3   PESQUERIA: 9   Median :0  
##  Mean   :181.4   MISION SAN PABLO    : 3   GUADALUPE: 6   Mean   :0  
##  3rd Qu.:180.7   PORTAL DE HUINALA   : 3   SALTILLO : 5   3rd Qu.:0  
##  Max.   :441.4   VALLE DE SANTA MARIA: 3   MONTERREY: 4   Max.   :0  
##                  (Other)             :70   (Other)  : 7
str(RhBajas1)
## 'data.frame':    237 obs. of  13 variables:
##  $ Nom       : chr  "MARIO VALDEZ ORTIZ" "ISABEL BARRIOS MENDEZ" "MARIA ELIZABETH GOMEZ HERNANDEZ" "ALONDRA ABIGAIL ESCARCIA GOMEZ" ...
##  $ Edad      : int  32 36 23 21 29 46 29 31 50 19 ...
##  $ Gen       : Factor w/ 2 levels "FEMENINO","MASCULINO": 2 1 1 1 1 1 1 2 2 2 ...
##  $ Fecha_alta: Date, format: "2020-03-09" "2021-11-09" ...
##  $ MB        : Factor w/ 5 levels "ABANDONO","BAJA POR FALTAS",..: 4 4 4 4 4 2 2 2 2 4 ...
##  $ Días_trab : Factor w/ 95 levels "0","1","2","3",..: 88 53 52 52 48 37 37 31 19 79 ...
##  $ Baja      : Date, format: "2021-11-27" "2022-01-08" ...
##  $ PuestDes  : Factor w/ 31 levels "ANALISTA DE NOMINAS /AUX DE R.H.",..: 15 9 9 9 9 9 9 9 9 4 ...
##  $ Sal_IMSS  : num  500 152 152 152 152 ...
##  $ Col       : Factor w/ 98 levels "ACANTO RESIDENCIAL",..: 82 18 72 72 73 28 72 48 15 80 ...
##  $ Mun       : Factor w/ 13 levels "APODACA","CADEREYTA",..: 10 7 1 1 1 1 1 5 4 1 ...
##  $ Estado    : Factor w/ 3 levels "COAHUILA","NUEVO LEÓN",..: 2 2 2 2 2 2 2 2 2 2 ...
##  $ EstCiv    : Factor w/ 5 levels "CASADO","DIVORCIADO",..: 3 5 1 3 3 3 5 5 3 3 ...
summary(RhBajas1)
##      Nom                 Edad              Gen        Fecha_alta        
##  Length:237         Min.   : 0.00   FEMENINO :140   Min.   :2016-10-12  
##  Class :character   1st Qu.:23.00   MASCULINO: 97   1st Qu.:2022-01-19  
##  Mode  :character   Median :29.00                   Median :2022-04-04  
##                     Mean   :30.52                   Mean   :2022-02-10  
##                     3rd Qu.:37.00                   3rd Qu.:2022-06-14  
##                     Max.   :61.00                   Max.   :2022-08-17  
##                                                                         
##                    MB        Días_trab        Baja           
##  ABANDONO           :  1   15     : 11   Min.   :2021-11-27  
##  BAJA POR FALTAS    :141   1      :  9   1st Qu.:2022-03-01  
##  JUBILACION         :  1   6      :  9   Median :2022-05-06  
##  RENUNCIA VOLUNTARIA: 86   9      :  8   Mean   :2022-05-05  
##  TERMINO DE CONTRATO:  8   0      :  7   3rd Qu.:2022-07-07  
##                            8      :  7   Max.   :2022-08-25  
##                            (Other):186                       
##                   PuestDes      Sal_IMSS                       Col     
##  AYUDANTE GENERAL     :173   Min.   :144.4   PUEBLO NUEVO        : 67  
##  SOLDADOR             : 11   1st Qu.:180.7   VALLE DE SANTA MARIA: 15  
##  COSTURERA            : 10   Median :180.7   CANTORAL            : 10  
##  MONTACARGUISTA       :  5   Mean   :178.6   PORTAL DE HUINALA   :  6  
##  AY. GENERAL          :  4   3rd Qu.:180.7   SAN ISIDRO          :  6  
##  AUXILIAR DE EMBARQUES:  3   Max.   :500.0   BOSQUES DE HUINALA  :  4  
##  (Other)              : 31                   (Other)             :129  
##                        Mun             Estado            EstCiv   
##  APODACA                 :162   COAHUILA  :  9   CASADO     : 64  
##  PESQUERIA               : 32   NUEVO LEÓN:227   DIVORCIADO :  3  
##  JUAREZ                  : 15   SALTILLO  :  1   SOLTERO    :110  
##  GUADALUPE               : 10                    Unión libre:  1  
##  RAMOS ARIZPE            :  8                    UNIÓN LIBRE: 59  
##  SAN NICOLAS DE LOS GARZA:  3                                     
##  (Other)                 :  7

Visualizasión de Datos

Mostrar graficos de visualización para identificar hallazgos relevantes de nuestras bases de datos RhColab1 y RhBajas1

## Colaboradores

tapply(RhColab1$Sal_Diario,
       list(RhColab1$Gen,RhColab1$Puesto), mean)
##           AY. GENERAL AYUDANTE DE MANTENIMIENTO Ayudante general
## FEMENINO       151.61                        NA               NA
## MASCULINO      151.61                    180.68           176.72
##           AYUDANTE GENERAL CHOFER CHOFER GESTOR COSTURERA CUSTOMER SERVICE INF
## FEMENINO          177.4222     NA            NA  191.7533                   NA
## MASCULINO         176.2268 177.71        180.68  176.7200               176.72
##           ENFERMERA Externo EXTERNO GESTOR GUARDIA DE SEGURIDAD
## FEMENINO     176.72      NA      NA     NA                   NA
## MASCULINO        NA  176.72  151.67 176.72               180.68
##           INSPECTOR DE CALIDAD INSPECTORA DE CALIDAD  LIDER LIMPIEZA
## FEMENINO                208.65                180.68 144.45   176.72
## MASCULINO                   NA                    NA     NA       NA
##           MANTENIMIENTO MONTACARGUISTA   MOZO OP. FLEXO-RANURADORA-REFILADORA
## FEMENINO             NA             NA     NA                              NA
## MASCULINO        279.61         180.68 180.68                          176.72
##           OPERADOR SIERRA PINTOR RECIBO RESIDENTE SOLDADOR Supervisor de Máquin
## FEMENINO               NA     NA 176.72        NA       NA                   NA
## MASCULINO          180.68 176.72     NA    177.71  179.888               176.72
##           Supervisor de pegado SUPERVISORA
## FEMENINO                176.72      389.21
## MASCULINO                   NA          NA
tapply(RhColab1$Sal_Diario,
       list(RhColab1$Gen,RhColab1$Dep), mean)
##                    Ay.flexo Calidad  Cedis  CEDIS Celdas CORTADORAS Costura
## FEMENINO  178.7544       NA 194.665     NA     NA 180.68         NA 245.375
## MASCULINO 176.5400   180.68      NA 176.72 180.68     NA     180.68 176.720
##           COSTURA Costura T2     EHS Embarques Externo Limpieza Materiales
## FEMENINO   151.61     152.86 176.720        NA      NA   176.72     176.72
## MASCULINO      NA         NA 230.145    177.71 164.195       NA         NA
##           Paileria Produccion Cartón MC Produccion Cartón MDL Producción Retorn
## FEMENINO        NA              194.405              156.0975          161.3000
## MASCULINO    178.7              151.670              168.3700          183.8443
##           Rotativa Stabilus Troquel
## FEMENINO        NA   180.68  180.68
## MASCULINO   151.61   180.68  180.68
## Bajas

tapply(RhBajas1$Sal_IMSS,RhBajas1$Gen,mean)
##  FEMENINO MASCULINO 
##  177.3126  180.5544

Reubicamos el “outlier” de salario_diario con la mediana

RhColab1$Sal_Diario<-replace(RhColab1$Sal_Diario,RhColab1$Sal_Diario>1000000,181)

Mostramos la visualización grafica de datos para poder identificar hallazgos importantes de rh_alt base de datos.

tapply(RhColab1$Sal_Diario,
       list(RhColab1$Gen,RhColab1$Dep), mean)
##                    Ay.flexo Calidad  Cedis  CEDIS Celdas CORTADORAS Costura
## FEMENINO  178.7544       NA 194.665     NA     NA 180.68         NA 245.375
## MASCULINO 176.5400   180.68      NA 176.72 180.68     NA     180.68 176.720
##           COSTURA Costura T2     EHS Embarques Externo Limpieza Materiales
## FEMENINO   151.61     152.86 176.720        NA      NA   176.72     176.72
## MASCULINO      NA         NA 230.145    177.71 164.195       NA         NA
##           Paileria Produccion Cartón MC Produccion Cartón MDL Producción Retorn
## FEMENINO        NA              194.405              156.0975          161.3000
## MASCULINO    178.7              151.670              168.3700          183.8443
##           Rotativa Stabilus Troquel
## FEMENINO        NA   180.68  180.68
## MASCULINO   151.61   180.68  180.68
hist(RhBajas1$Edad, freq=TRUE, col='orange', main="Histograma de Edad",xlab="Edad en Años")

Podemos observar que hay una mayor cantidad de empleados en el rango de edad de 20 a 25 años, después le sigue el rango de 25 a 30 y de 30 a 35, siendo la mayor parte de los empleados jóvenes, pero habiendo empleados que sobre pasan incluso la edad de 60 años.

ggplot(RhBajas1, aes(x=Gen, y=Edad, fill=Gen)) + 
  geom_boxplot() 

La mayor parte de empleados aglomerada en el rango de 20 a 40 años y observamos como hay unos pocos fuera de rango en edades que pasan de 50 a 60 años,siendo estos pocos casos.

ggplot(RhColab1, aes(x=Gen, y=Sal_Diario, fill=Gen)) + 
  geom_boxplot() 

Aquí en el salario diario se destaca la observación de que la mayor parte de los empleados tienen un salario que ronda entre los 170 pesos; habiendo casos muy espesificos que estan en rangos mucho menores o llegando a los 300 pesos, pero habiendo un salario que llega a los 450 pesos siendo el salario más elevado de toda la base de datos.

ggplot(RhColab1, aes(Gen,Sal_Diario,fill=Gen)) +                                    
  geom_bar(stat = "identity") +
  scale_fill_brewer(palette = "Set2") + ggtitle("Salario Diario por Genero")

En la gráfica anterior podemos observar la correlación entre el género y el salario diario de los empleados; podemos concluir que el género femenino tiene un salario total en promedio más alto el género masculino.

ggplot(RhBajas1, aes(x=Gen, y=Sal_IMSS, fill=Gen)) + 
  geom_bar(stat="identity") + 
  facet_grid(~EstCiv) + scale_fill_brewer(palette = "Set1")

Aquí podemos observar el salario del IMSS en cuanto al género de los empleados y dependiendo de si son casados, divoricados, solteros o estan en unión libre. Se puede concluir que las mujeres tienen en promedio en estas cuatro categorías un salario mayor al de los hombres y los solteros tienen un mayor salario comparado con las otras categorias.

Producción

Limpieza de Datos

Se comenzó realizando una limpieza en excel, para después empezar a limpiar dentro de R dejando finalmente los valores más relevantes.

Importar la base de datos producción de la empresa FORM

producciontotal <- read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/PRODUCCIÓN/BD Producción csv (1).csv")

Entender la base de datos

str(producciontotal)
## 'data.frame':    5256 obs. of  16 variables:
##  $ Fecha               : chr  "15/07/22" "15/07/22" "15/07/22" "15/07/22" ...
##  $ No.                 : chr  "1" "2" "3" "4" ...
##  $ CLIENTE             : chr  "STABILUS 1" "STABILUS 1" "STABILUS 1" "STABILUS 1" ...
##  $ ID.FORM             : chr  "" "N.A." "CORTE." "ST-026-13892" ...
##  $ PIEZAS.PROG.        : int  200 100 216 100 20 200 100 12 32 500 ...
##  $ TMO..MIN.           : chr  "20" "15" "20" "10" ...
##  $ HR..FIN             : chr  "9:20" "9:35" "9:55" "10:05" ...
##  $ ESTACION.ARRANQUE   : chr  "C1" "C1" "C1" "C1" ...
##  $ Laminas.procesadas  : chr  "402" "134" "110" "100" ...
##  $ INICIO.SEP.UP       : chr  "9:05" "10:05" "9:40" "11.2" ...
##  $ FIN.INICIO.DE.SEP.UP: chr  "9.1" "10:16" "9:43" "11:26" ...
##  $ INICIO.de.PROCESO   : chr  "9:12" "10.17" "9:45" "11:30" ...
##  $ FIN.de.PROCESO      : chr  "10:04" "11:05" "9.57" "11:49" ...
##  $ TIEMPO.CALIDAD      : chr  "1" "1" "1" "1" ...
##  $ TIEMPO.MATERIALES   : int  NA NA NA 7 NA NA NA NA NA NA ...
##  $ MERMAS.Maquinas.    : chr  "" "" "" "" ...

Tipos de Variables

Variable<-c("Fecha", "Número", "Cliente","Id Form", "Producto", "Piezas programadas", "Tiempo en minutos", "Hora fin ", "Estación de arranque", "Laminas procesadas", "Inicio Set Up", "Fin Set up", "Inicio porceso", "Fin proceso", "  Tiempo calidad")

Type<-c("qualitative (nominal)", "quantitative (discrete)", "qualitative (nominal)","qualiitative (ordinal)","qualitative (nominal)","quantitative (discrete)","quantitative (contonua)","quantitative (contonua)","qualitative (nominal)","quantitative (dis rete)","quantitative (contonua)","quantitative (Continua)","quantitative (contonua)","quantitative (contonua)","quantitative (discrete)")

table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
Fecha qualitative (nominal)
Número quantitative (discrete)
Cliente qualitative (nominal)
Id Form qualiitative (ordinal)
Producto qualitative (nominal)
Piezas programadas quantitative (discrete)
Tiempo en minutos quantitative (contonua)
Hora fin quantitative (contonua)
Estación de arranque qualitative (nominal)
Laminas procesadas quantitative (dis rete)
Inicio Set Up quantitative (contonua)
Fin Set up quantitative (Continua)
Inicio porceso quantitative (contonua)
Fin proceso quantitative (contonua)
Tiempo calidad quantitative (discrete)

Eliminar columnas irrelevantes para el análisis

Se eliminaron las columnas que no generaban valor al análisis.

producciontotal <- subset (producciontotal,select = -c( No., ID.FORM ,  HR..FIN , ESTACION.ARRANQUE , INICIO.SEP.UP ,FIN.INICIO.DE.SEP.UP , INICIO.de.PROCESO , TIEMPO.MATERIALES , MERMAS.Maquinas. ))


summary (producciontotal)
##     Fecha             CLIENTE           PIEZAS.PROG.     TMO..MIN.        
##  Length:5256        Length:5256        Min.   :   1.0   Length:5256       
##  Class :character   Class :character   1st Qu.:  78.0   Class :character  
##  Mode  :character   Mode  :character   Median : 144.0   Mode  :character  
##                                        Mean   : 181.3                     
##                                        3rd Qu.: 200.0                     
##                                        Max.   :2000.0                     
##                                        NA's   :2                          
##  Laminas.procesadas FIN.de.PROCESO     TIEMPO.CALIDAD    
##  Length:5256        Length:5256        Length:5256       
##  Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character  
##                                                          
##                                                          
##                                                          
## 

Cambiar a entero las variables cuantitativas

producciontotal$PIEZAS.PROG. <- substr(producciontotal$PIEZAS.PROG., start = 1, stop = 2)
tibble (producciontotal)
## # A tibble: 5,256 × 7
##    Fecha    CLIENTE    PIEZAS.PROG. TMO..MIN. Laminas.procesadas FIN.d…¹ TIEMP…²
##    <chr>    <chr>      <chr>        <chr>     <chr>              <chr>   <chr>  
##  1 15/07/22 STABILUS 1 20           20        402                10:04   1      
##  2 15/07/22 STABILUS 1 10           15        134                11:05   1      
##  3 15/07/22 STABILUS 1 21           20        110                9.57    1      
##  4 15/07/22 STABILUS 1 10           10        100                11:49   1      
##  5 15/07/22 YANFENG    20           10        51                 12:31   1      
##  6 15/07/22 TRMX       20           20        402                2:00    1      
##  7 15/07/22 STABILUS 1 10           10        22                 2.44    1      
##  8 15/07/22 YANFENG    12           10        13                 3:00    1      
##  9 15/07/22 YANFENG    32           10        33                 2:12    1      
## 10 15/07/22 YANFENG    50           60        501/501            10:59   2      
## # … with 5,246 more rows, and abbreviated variable names ¹​FIN.de.PROCESO,
## #   ²​TIEMPO.CALIDAD
producciontotal$PIEZAS.PROG. <- as.integer(producciontotal$PIEZAS.PROG.)
str(producciontotal)    
## 'data.frame':    5256 obs. of  7 variables:
##  $ Fecha             : chr  "15/07/22" "15/07/22" "15/07/22" "15/07/22" ...
##  $ CLIENTE           : chr  "STABILUS 1" "STABILUS 1" "STABILUS 1" "STABILUS 1" ...
##  $ PIEZAS.PROG.      : int  20 10 21 10 20 20 10 12 32 50 ...
##  $ TMO..MIN.         : chr  "20" "15" "20" "10" ...
##  $ Laminas.procesadas: chr  "402" "134" "110" "100" ...
##  $ FIN.de.PROCESO    : chr  "10:04" "11:05" "9.57" "11:49" ...
##  $ TIEMPO.CALIDAD    : chr  "1" "1" "1" "1" ...
producciontotal$TMO..MIN. <- substr(producciontotal$TMO..MIN., start = 1, stop = 2)
tibble (producciontotal)
## # A tibble: 5,256 × 7
##    Fecha    CLIENTE    PIEZAS.PROG. TMO..MIN. Laminas.procesadas FIN.d…¹ TIEMP…²
##    <chr>    <chr>             <int> <chr>     <chr>              <chr>   <chr>  
##  1 15/07/22 STABILUS 1           20 20        402                10:04   1      
##  2 15/07/22 STABILUS 1           10 15        134                11:05   1      
##  3 15/07/22 STABILUS 1           21 20        110                9.57    1      
##  4 15/07/22 STABILUS 1           10 10        100                11:49   1      
##  5 15/07/22 YANFENG              20 10        51                 12:31   1      
##  6 15/07/22 TRMX                 20 20        402                2:00    1      
##  7 15/07/22 STABILUS 1           10 10        22                 2.44    1      
##  8 15/07/22 YANFENG              12 10        13                 3:00    1      
##  9 15/07/22 YANFENG              32 10        33                 2:12    1      
## 10 15/07/22 YANFENG              50 60        501/501            10:59   2      
## # … with 5,246 more rows, and abbreviated variable names ¹​FIN.de.PROCESO,
## #   ²​TIEMPO.CALIDAD
producciontotal$TMO..MIN. <- as.integer(producciontotal$TMO..MIN.)
str(producciontotal)  
## 'data.frame':    5256 obs. of  7 variables:
##  $ Fecha             : chr  "15/07/22" "15/07/22" "15/07/22" "15/07/22" ...
##  $ CLIENTE           : chr  "STABILUS 1" "STABILUS 1" "STABILUS 1" "STABILUS 1" ...
##  $ PIEZAS.PROG.      : int  20 10 21 10 20 20 10 12 32 50 ...
##  $ TMO..MIN.         : int  20 15 20 10 10 20 10 10 10 60 ...
##  $ Laminas.procesadas: chr  "402" "134" "110" "100" ...
##  $ FIN.de.PROCESO    : chr  "10:04" "11:05" "9.57" "11:49" ...
##  $ TIEMPO.CALIDAD    : chr  "1" "1" "1" "1" ...
producciontotal$Laminas.procesadas <- substr(producciontotal$Laminas.procesadas, start = 1, stop = 2)
tibble (producciontotal)
## # A tibble: 5,256 × 7
##    Fecha    CLIENTE    PIEZAS.PROG. TMO..MIN. Laminas.procesadas FIN.d…¹ TIEMP…²
##    <chr>    <chr>             <int>     <int> <chr>              <chr>   <chr>  
##  1 15/07/22 STABILUS 1           20        20 40                 10:04   1      
##  2 15/07/22 STABILUS 1           10        15 13                 11:05   1      
##  3 15/07/22 STABILUS 1           21        20 11                 9.57    1      
##  4 15/07/22 STABILUS 1           10        10 10                 11:49   1      
##  5 15/07/22 YANFENG              20        10 51                 12:31   1      
##  6 15/07/22 TRMX                 20        20 40                 2:00    1      
##  7 15/07/22 STABILUS 1           10        10 22                 2.44    1      
##  8 15/07/22 YANFENG              12        10 13                 3:00    1      
##  9 15/07/22 YANFENG              32        10 33                 2:12    1      
## 10 15/07/22 YANFENG              50        60 50                 10:59   2      
## # … with 5,246 more rows, and abbreviated variable names ¹​FIN.de.PROCESO,
## #   ²​TIEMPO.CALIDAD
producciontotal$Laminas.procesadas <- as.integer(producciontotal$Laminas.procesadas)
str(producciontotal) 
## 'data.frame':    5256 obs. of  7 variables:
##  $ Fecha             : chr  "15/07/22" "15/07/22" "15/07/22" "15/07/22" ...
##  $ CLIENTE           : chr  "STABILUS 1" "STABILUS 1" "STABILUS 1" "STABILUS 1" ...
##  $ PIEZAS.PROG.      : int  20 10 21 10 20 20 10 12 32 50 ...
##  $ TMO..MIN.         : int  20 15 20 10 10 20 10 10 10 60 ...
##  $ Laminas.procesadas: int  40 13 11 10 51 40 22 13 33 50 ...
##  $ FIN.de.PROCESO    : chr  "10:04" "11:05" "9.57" "11:49" ...
##  $ TIEMPO.CALIDAD    : chr  "1" "1" "1" "1" ...
producciontotal$TIEMPO.CALIDAD <- substr(producciontotal$TIEMPO.CALIDAD, start = 1, stop = 2)
tibble (producciontotal)
## # A tibble: 5,256 × 7
##    Fecha    CLIENTE    PIEZAS.PROG. TMO..MIN. Laminas.procesadas FIN.d…¹ TIEMP…²
##    <chr>    <chr>             <int>     <int>              <int> <chr>   <chr>  
##  1 15/07/22 STABILUS 1           20        20                 40 10:04   1      
##  2 15/07/22 STABILUS 1           10        15                 13 11:05   1      
##  3 15/07/22 STABILUS 1           21        20                 11 9.57    1      
##  4 15/07/22 STABILUS 1           10        10                 10 11:49   1      
##  5 15/07/22 YANFENG              20        10                 51 12:31   1      
##  6 15/07/22 TRMX                 20        20                 40 2:00    1      
##  7 15/07/22 STABILUS 1           10        10                 22 2.44    1      
##  8 15/07/22 YANFENG              12        10                 13 3:00    1      
##  9 15/07/22 YANFENG              32        10                 33 2:12    1      
## 10 15/07/22 YANFENG              50        60                 50 10:59   2      
## # … with 5,246 more rows, and abbreviated variable names ¹​FIN.de.PROCESO,
## #   ²​TIEMPO.CALIDAD
producciontotal$TIEMPO.CALIDAD <- as.integer(producciontotal$TIEMPO.CALIDAD)
str(producciontotal) 
## 'data.frame':    5256 obs. of  7 variables:
##  $ Fecha             : chr  "15/07/22" "15/07/22" "15/07/22" "15/07/22" ...
##  $ CLIENTE           : chr  "STABILUS 1" "STABILUS 1" "STABILUS 1" "STABILUS 1" ...
##  $ PIEZAS.PROG.      : int  20 10 21 10 20 20 10 12 32 50 ...
##  $ TMO..MIN.         : int  20 15 20 10 10 20 10 10 10 60 ...
##  $ Laminas.procesadas: int  40 13 11 10 51 40 22 13 33 50 ...
##  $ FIN.de.PROCESO    : chr  "10:04" "11:05" "9.57" "11:49" ...
##  $ TIEMPO.CALIDAD    : int  1 1 1 1 1 1 1 1 1 2 ...

Convertir formato de la fecha

Esto para poder tener las interpretaciones y resultados esperados de la manera correcra.

producciontotal$Fecha <- as.Date(producciontotal$Fecha, format = "%d/%m/%Y")
tibble(producciontotal)
## # A tibble: 5,256 × 7
##    Fecha      CLIENTE    PIEZAS.PROG. TMO..MIN. Laminas.proces…¹ FIN.d…² TIEMP…³
##    <date>     <chr>             <int>     <int>            <int> <chr>     <int>
##  1 0022-07-15 STABILUS 1           20        20               40 10:04         1
##  2 0022-07-15 STABILUS 1           10        15               13 11:05         1
##  3 0022-07-15 STABILUS 1           21        20               11 9.57          1
##  4 0022-07-15 STABILUS 1           10        10               10 11:49         1
##  5 0022-07-15 YANFENG              20        10               51 12:31         1
##  6 0022-07-15 TRMX                 20        20               40 2:00          1
##  7 0022-07-15 STABILUS 1           10        10               22 2.44          1
##  8 0022-07-15 YANFENG              12        10               13 3:00          1
##  9 0022-07-15 YANFENG              32        10               33 2:12          1
## 10 0022-07-15 YANFENG              50        60               50 10:59         2
## # … with 5,246 more rows, and abbreviated variable names ¹​Laminas.procesadas,
## #   ²​FIN.de.PROCESO, ³​TIEMPO.CALIDAD

Convertir variable “Cliente” para análisis descriptivo

producciontotal$CLIENTE<-as.factor(producciontotal$CLIENTE)  
str(producciontotal)
## 'data.frame':    5256 obs. of  7 variables:
##  $ Fecha             : Date, format: "0022-07-15" "0022-07-15" ...
##  $ CLIENTE           : Factor w/ 11 levels "DENSO","HANON SYSTEMS",..: 5 5 5 5 11 7 5 11 11 11 ...
##  $ PIEZAS.PROG.      : int  20 10 21 10 20 20 10 12 32 50 ...
##  $ TMO..MIN.         : int  20 15 20 10 10 20 10 10 10 60 ...
##  $ Laminas.procesadas: int  40 13 11 10 51 40 22 13 33 50 ...
##  $ FIN.de.PROCESO    : chr  "10:04" "11:05" "9.57" "11:49" ...
##  $ TIEMPO.CALIDAD    : int  1 1 1 1 1 1 1 1 1 2 ...

Identificar valores faltantes

sum(is.na(producciontotal))
## [1] 3928

¿Cuántos NA tengo por variable?

sapply(producciontotal, function(x) sum (is.na(x)))
##              Fecha            CLIENTE       PIEZAS.PROG.          TMO..MIN. 
##                  0                  1                  2               1489 
## Laminas.procesadas     FIN.de.PROCESO     TIEMPO.CALIDAD 
##               1101                  0               1335

Reemplazar NA

Se reemplazarón los registros NA de la tabla con la mediana

producciontotal<-producciontotal %>% mutate(PIEZAS.PROG.=ifelse(is.na(PIEZAS.PROG.),median(PIEZAS.PROG.,na.rm=T),PIEZAS.PROG.))
producciontotal<-producciontotal %>% mutate(TMO..MIN.=ifelse(is.na(TMO..MIN.),median(TMO..MIN.,na.rm=T),TMO..MIN.))
producciontotal<-producciontotal %>% mutate(laminas_procesadas=ifelse(is.na(Laminas.procesadas),median(Laminas.procesadas,na.rm=T),Laminas.procesadas))
producciontotal<-producciontotal %>% mutate(TIEMPO.CALIDAD=ifelse(is.na(TIEMPO.CALIDAD),median(TIEMPO.CALIDAD,na.rm=T),TIEMPO.CALIDAD))

Verificar la suma de NAs

sum(is.na(producciontotal))
## [1] 1102
sapply(producciontotal, function(x) sum (is.na(x)))
##              Fecha            CLIENTE       PIEZAS.PROG.          TMO..MIN. 
##                  0                  1                  0                  0 
## Laminas.procesadas     FIN.de.PROCESO     TIEMPO.CALIDAD laminas_procesadas 
##               1101                  0                  0                  0

Omitir los valores irrelevantes identificados

producciontotal <- na.omit(producciontotal)
summary(producciontotal)   
##      Fecha                  CLIENTE      PIEZAS.PROG.     TMO..MIN.    
##  Min.   :0022-07-15   STABILUS 1:1354   Min.   : 1.00   Min.   : 0.00  
##  1st Qu.:0022-08-03   TRMX      : 704   1st Qu.:14.00   1st Qu.:15.00  
##  Median :0022-08-19   STABILUS 3: 642   Median :20.00   Median :20.00  
##  Mean   :0022-08-19   YANFENG   : 506   Mean   :27.83   Mean   :22.01  
##  3rd Qu.:0022-09-06   DENSO     : 414   3rd Qu.:40.00   3rd Qu.:25.00  
##  Max.   :0022-09-21   VARROC    : 314   Max.   :99.00   Max.   :90.00  
##                       (Other)   : 220                                  
##  Laminas.procesadas FIN.de.PROCESO     TIEMPO.CALIDAD    laminas_procesadas
##  Min.   : 0.00      Length:4154        Min.   : 0.0000   Min.   : 0.00     
##  1st Qu.: 0.00      Class :character   1st Qu.: 1.0000   1st Qu.: 0.00     
##  Median :20.00      Mode  :character   Median : 1.0000   Median :20.00     
##  Mean   :21.98                         Mean   : 0.9215   Mean   :21.98     
##  3rd Qu.:34.00                         3rd Qu.: 1.0000   3rd Qu.:34.00     
##  Max.   :98.00                         Max.   :25.0000   Max.   :98.00     
## 
sum(is.na(producciontotal))
## [1] 0
summary (producciontotal)
##      Fecha                  CLIENTE      PIEZAS.PROG.     TMO..MIN.    
##  Min.   :0022-07-15   STABILUS 1:1354   Min.   : 1.00   Min.   : 0.00  
##  1st Qu.:0022-08-03   TRMX      : 704   1st Qu.:14.00   1st Qu.:15.00  
##  Median :0022-08-19   STABILUS 3: 642   Median :20.00   Median :20.00  
##  Mean   :0022-08-19   YANFENG   : 506   Mean   :27.83   Mean   :22.01  
##  3rd Qu.:0022-09-06   DENSO     : 414   3rd Qu.:40.00   3rd Qu.:25.00  
##  Max.   :0022-09-21   VARROC    : 314   Max.   :99.00   Max.   :90.00  
##                       (Other)   : 220                                  
##  Laminas.procesadas FIN.de.PROCESO     TIEMPO.CALIDAD    laminas_procesadas
##  Min.   : 0.00      Length:4154        Min.   : 0.0000   Min.   : 0.00     
##  1st Qu.: 0.00      Class :character   1st Qu.: 1.0000   1st Qu.: 0.00     
##  Median :20.00      Mode  :character   Median : 1.0000   Median :20.00     
##  Mean   :21.98                         Mean   : 0.9215   Mean   :21.98     
##  3rd Qu.:34.00                         3rd Qu.: 1.0000   3rd Qu.:34.00     
##  Max.   :98.00                         Max.   :25.0000   Max.   :98.00     
## 

Visualización

¿Cuál es el cliente con mayor tiempo de calidad?

producciontotal2<-producciontotal %>% dplyr::select(CLIENTE,PIEZAS.PROG.,TIEMPO.CALIDAD) %>% group_by(CLIENTE) %>% arrange(desc(PIEZAS.PROG.))

summary(producciontotal2$CLIENTE)
##                DENSO        HANON SYSTEMS                HELLA 
##                  414                   12                   95 
## MERIDIAN LIGHTWEIGHT           STABILUS 1           STABILUS 3 
##                  105                 1354                  642 
##                 TRMX               VARROC         VL-017-13939 
##                  704                  314                    4 
##         VL-017-14086              YANFENG 
##                    4                  506
producciontotal3<- producciontotal2[-c(10),]
library (ggplot2)
ggplot(producciontotal3, aes(x=reorder(CLIENTE,PIEZAS.PROG.), y=PIEZAS.PROG., fill=(TIEMPO.CALIDAD))) +
  geom_bar(stat="identity")+
  coord_flip()+
  guides(fill=guide_legend(reverse=FALSE))

Podemos ver que uno de los clientes con el que se producen mayor número de piezas programadas y que es en un lapzo de tiempo menor es STABILUS 1, seguido de YANFENG.

¿Cuál es el cliente que más piezas programadas tiene en la empresa?

producciontotal3 %>% select(CLIENTE,PIEZAS.PROG.) %>% group_by(CLIENTE) %>% summarise(PIEZAS.PROG.=sum(PIEZAS.PROG.)) %>% arrange(desc(PIEZAS.PROG.))
##   PIEZAS.PROG.
## 1       115525
ggplot(producciontotal3, aes(x=reorder(CLIENTE,PIEZAS.PROG.), y=PIEZAS.PROG.)) +
  geom_bar(stat="identity")+
  coord_flip()

Se puede ver que el cliente que más piezas programadas tiene es YANFENG dedicandosele un tiempo de calidad de 1.1 minuto, mientras que el cliente VL-017-1486 es el cliente que tiene casi la mitad de piezas programadas y es al que más tiempo se le dedica tiempo.

Esto puede indicar que sus piezas pudieran ser de mucho márgen de error.

Delivery Plan

Importar base de datos

del_plan <- read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/DELIVERY PLAN/CLEANDBDeliveryPlan.csv")

Tipos de Variables

Variable<-c("Cliente planta","Mes", "Unidades")

Type<-c("qualitative (nominal)", "qualitative (ordinal)", "quiantitative (discreta)")

table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
Cliente planta qualitative (nominal)
Mes qualitative (ordinal)
Unidades quiantitative (discreta)

Convertir meses en una columna

Para mejorar el manejo de las unidades de produccion mensuales ya que originalmente en la base de datos estas eran registradas diariamente.

del_plan<- clean_names(del_plan)
summary(del_plan$mes)
##    Length     Class      Mode 
##       733 character character
del_plan$mes<-recode_factor(del_plan$mes,jun_21="junio",jul_21="julio",ago_21="agosto",sep_21="septiembre", 
                                     oct_21="octubre",nov_21="noviembre",dic_21="diciembre",oct_22="octubre_22")

function(pivot_longer)
del_plan<-pivot_longer(del_plan, cols=5:16, names_to = "mes", values_to = "unidades")
## function(pivot_longer)
## del_plan<-pivot_longer(del_plan, cols=5:16, names_to = "mes", values_to = "unidades")

Eliminar columnas no necesarias

Eliminar columnas no necesarias como ID ODOO, Proyecto e ITEM que eran irrelebantes para el análisis.

Formato de las variables

str(del_plan)
## 'data.frame':    733 obs. of  3 variables:
##  $ cliente_planta: chr  "STB3" "STB3" "STB3" "STB3" ...
##  $ mes           : Factor w/ 12 levels "junio","julio",..: 2 3 5 7 8 9 7 8 9 10 ...
##  $ unidades      : int  140 530 200 150 230 500 184 125 55 55 ...

NA’s y valores atipicos

En la base de datos no se hay NA, solo eliminamos los registros que tienen 0 unidades programadas.

del_plan <- filter(del_plan, unidades>0)
sum(is.na(del_plan))
## [1] 0

Graficas

Tabla estadisticas

tabla_estadisticos <- describe(del_plan)
tabla_estadisticos
## # A tibble: 1 × 26
##   described_…¹     n    na  mean    sd se_mean   IQR skewn…² kurto…³   p00   p01
##   <chr>        <int> <int> <dbl> <dbl>   <dbl> <dbl>   <dbl>   <dbl> <dbl> <dbl>
## 1 unidades       733     0  406. 1337.    49.4   270    8.38    85.8     1     1
## # … with 15 more variables: p05 <dbl>, p10 <dbl>, p20 <dbl>, p25 <dbl>,
## #   p30 <dbl>, p40 <dbl>, p50 <dbl>, p60 <dbl>, p70 <dbl>, p75 <dbl>,
## #   p80 <dbl>, p90 <dbl>, p95 <dbl>, p99 <dbl>, p100 <dbl>, and abbreviated
## #   variable names ¹​described_variables, ²​skewness, ³​kurtosis

Al realizar una tabla estadistica, R nos arroja diferentes metodos como la media, la mediana, la moda y la desviacion estandar que son importantes al momento de realizar este análisis.

Bar plots

str(del_plan)
## 'data.frame':    733 obs. of  3 variables:
##  $ cliente_planta: chr  "STB3" "STB3" "STB3" "STB3" ...
##  $ mes           : Factor w/ 12 levels "junio","julio",..: 2 3 5 7 8 9 7 8 9 10 ...
##  $ unidades      : int  140 530 200 150 230 500 184 125 55 55 ...
del_plan$cliente_planta<-as.factor(del_plan$cliente_planta)
del_plan$unidades<-as.numeric(del_plan$unidades) 

del_plan2<-aggregate(unidades~cliente_planta, data = del_plan,sum)%>% arrange(desc(unidades))
del_plan3<-filter(del_plan2, unidades>4000)

ggplot(del_plan3, aes(x=reorder(cliente_planta,unidades), y=unidades)) +
  geom_bar(stat="identity")+
  coord_flip()

Se realizó un proceso en el cual primero se convirtieron las variables mediante las funciones as.factor y as.numeric para hacer los datos cualitativos / cuantitativos.

Se muestran valores mayores a 4000, lo cuál nos resultó en una gráfica donde se podían observar los Clientes con mayor número de unidades en orden descendiente.

Dispersion

del_plan2$unidades<-as.numeric(del_plan2$unidades)

ggplot(del_plan, aes(x=cliente_planta, y=unidades, fill=cliente_planta)) + 
  geom_boxplot() 

boxplot(del_plan3$cliente_planta,del_plan3$unidades)

class(del_plan2$unidades)
## [1] "numeric"

Hella es el cliente con mayor cantidad de unidades y además de eso cuenta con algunos outliers muy por encima de la median, seguido por TRMX el cual no cuenta con outliers.

Time series plot

del_plan4<-aggregate(unidades~cliente_planta+mes, data = del_plan,sum)%>% arrange(desc(unidades))
del_plan5<-filter(del_plan4, cliente_planta=="HELLA" & cliente_planta=="TRMX" & cliente_planta=="VARROC" & cliente_planta=="DENSO")
ggplot(del_plan,aes(x=mes, y=unidades,color=cliente_planta))+
  geom_line()+
  labs(x="Fecha",y="Delay in Minutes", color="Legend")+
  ggtitle("Delays in Performance by Client")

Se observa en la segunda mitad del periodo anual que hay un incremento notorio, además de un decremento justo por finales del segundo semestre.

Merma

Importar base de datos

#file.choose()
bd <-read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/MERMA/FORM - Merma limpia2 (1).csv")

En el caso de las variables cuantitativas, considerar la posibilidad de reemplazar la presencia de “missing values” con estadísticos descriptivos por ejemplo, media, mediana, moda.

Analizar base de datos

summary(bd)
##     Fecha              ENERO             KilosEnero      Fecha1         
##  Length:10          Length:10          Min.   :2680   Length:10         
##  Class :character   Class :character   1st Qu.:2912   Class :character  
##  Mode  :character   Mode  :character   Median :3400   Mode  :character  
##                                        Mean   :3640                     
##                                        3rd Qu.:4128                     
##                                        Max.   :5080                     
##                                        NA's   :6                        
##    FEBRERO           KilosFebrero     Fecha2             MARZO          
##  Length:10          Min.   :3410   Length:10          Length:10         
##  Class :character   1st Qu.:3605   Class :character   Class :character  
##  Mode  :character   Median :3760   Mode  :character   Mode  :character  
##                     Mean   :3805                                        
##                     3rd Qu.:3915                                        
##                     Max.   :4380                                        
##                     NA's   :4                                           
##    KilosMarzo      Fecha3             ABRIL             KilosAbril  
##  Min.   :2980   Length:10          Length:10          Min.   :2950  
##  1st Qu.:3420   Class :character   Class :character   1st Qu.:3690  
##  Median :3905   Mode  :character   Mode  :character   Median :3940  
##  Mean   :3745                                         Mean   :3764  
##  3rd Qu.:4142                                         3rd Qu.:4050  
##  Max.   :4200                                         Max.   :4190  
##  NA's   :4                                            NA's   :5     
##     Fecha4              MAYO             KilosMayo       Fecha5         
##  Length:10          Length:10          Min.   :3680   Length:10         
##  Class :character   Class :character   1st Qu.:4310   Class :character  
##  Mode  :character   Mode  :character   Median :4510   Mode  :character  
##                                        Mean   :4682                     
##                                        3rd Qu.:4770                     
##                                        Max.   :6140                     
##                                        NA's   :5                        
##     JUNIO             KilosJunio      Fecha6             JULIO          
##  Length:10          Min.   :4260   Length:10          Length:10         
##  Class :character   1st Qu.:4312   Class :character   Class :character  
##  Mode  :character   Median :4505   Mode  :character   Mode  :character  
##                     Mean   :4570                                        
##                     3rd Qu.:4762                                        
##                     Max.   :5010                                        
##                     NA's   :6                                           
##    KilosJulio      Fecha7             AGOSTO           KilosAgosto  
##  Min.   :2130   Length:10          Length:10          Min.   :1040  
##  1st Qu.:3920   Class :character   Class :character   1st Qu.:3140  
##  Median :3960   Mode  :character   Mode  :character   Median :3780  
##  Mean   :3874                                         Mean   :3567  
##  3rd Qu.:4130                                         3rd Qu.:4210  
##  Max.   :5230                                         Max.   :5080  
##  NA's   :5                                            NA's   :1     
##     Fecha8           SEPTIEMBRE        KilosSeptiembre
##  Length:10          Length:10          Min.   :2830   
##  Class :character   Class :character   1st Qu.:2995   
##  Mode  :character   Mode  :character   Median :3394   
##                                        Mean   :3396   
##                                        3rd Qu.:3796   
##                                        Max.   :3967   
##                                        NA's   :6
str(bd)
## 'data.frame':    10 obs. of  27 variables:
##  $ Fecha          : chr  "11/01/22" "11/01/22" "22/01/22" "22/01/22" ...
##  $ ENERO          : chr  "Enero" "Enero" "Enero" "Enero" ...
##  $ KilosEnero     : int  5080 3810 2990 2680 NA NA NA NA NA NA
##  $ Fecha1         : chr  "18/02/22" "18/02/22" "18/02/22" "18/02/22" ...
##  $ FEBRERO        : chr  "Febrero" "Febrero" "Febrero" "Febrero" ...
##  $ KilosFebrero   : int  3650 4380 3870 3590 3410 3930 NA NA NA NA
##  $ Fecha2         : chr  "03/03/22" "08/03/22" "11/03/22" "16/03/22" ...
##  $ MARZO          : chr  "Marzo" "Marzo" "Marzo" "Marzo" ...
##  $ KilosMarzo     : int  4000 4190 2980 3290 4200 3810 NA NA NA NA
##  $ Fecha3         : chr  "04/04/22" "11/04/22" "14/04/22" "21/04/22" ...
##  $ ABRIL          : chr  "Abril" "Abril" "Abril" "Abril" ...
##  $ KilosAbril     : int  3940 4190 2950 3690 4050 NA NA NA NA NA
##  $ Fecha4         : chr  "02/05/22" "09/05/22" "14/05/22" "24/05/22" ...
##  $ MAYO           : chr  "Mayo" "Mayo" "Mayo" "Mayo" ...
##  $ KilosMayo      : int  4310 4770 3680 6140 4510 NA NA NA NA NA
##  $ Fecha5         : chr  "07/06/22" "15/06/22" "20/06/22" "27/06/22" ...
##  $ JUNIO          : chr  "Junio" "Junio" "Junio" "Junio" ...
##  $ KilosJunio     : int  4680 4330 5010 4260 NA NA NA NA NA NA
##  $ Fecha6         : chr  "04/07/22" "11/07/22" "16/07/22" "21/07/22" ...
##  $ JULIO          : chr  "Julio" "Julio" "Julio" "Julio" ...
##  $ KilosJulio     : int  5230 2130 4130 3920 3960 NA NA NA NA NA
##  $ Fecha7         : chr  "08/08/22" "10/08/22" "11/08/22" "13/08/22" ...
##  $ AGOSTO         : chr  "Agosto" "Agosto" "Agosto" "Agosto" ...
##  $ KilosAgosto    : int  3140 4210 3140 3780 4240 4200 5080 1040 3270 NA
##  $ Fecha8         : chr  "05/09/22" "07/09/22" "15/09/22" "21/09/22" ...
##  $ SEPTIEMBRE     : chr  "Septiembre" "Septiembre" "Septiembre" "Septiembre" ...
##  $ KilosSeptiembre: int  3050 2830 3967 3739 NA NA NA NA NA NA

Tipos de Variables

Variable<-c("Fecha","ENERO","KilosEnero","Fecha1","FEBRERO","KilosFebrero","Fecha2","MARZO","KilosMarzo","Fecha3","ABRIL","KilosAbril","Fecha4","MAYO","KilosMayo","Fecha5","JUNIO","KilosJunio","Fecha6","JULIO","KilosJulio","Fecha7","AGOSTO","KilosAgosto","Fecha8","SEPTIEMBRE","KilosSeptiembre")
Type<-c("qualitative (ordinal)", "qualitative (ordinal)", "quantitative (discrete)","qualitative (nominal)","qualitative (ordinal)","quantitative (discrete)","qualitative (nominal)","qualitative (ordinal)","quantitative (discrete)","qualitative (nominal)","qualitative (ordinal)","quantitative (discrete)","qualitative (nominal)","qualitative (ordinal)","quantitative (discrete)","qualitative (nominal)","qualitative (ordinal)","quantitative (discrete)","qualitative (nominal)","qualitative (ordinal)","quantitative (discrete)","qualitative (nominal)","qualitative (ordinal)","quantitative (discrete)","qualitative (nominal)","qualitative (ordinal)","quantitative (discrete)")
table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
Fecha qualitative (ordinal)
ENERO qualitative (ordinal)
KilosEnero quantitative (discrete)
Fecha1 qualitative (nominal)
FEBRERO qualitative (ordinal)
KilosFebrero quantitative (discrete)
Fecha2 qualitative (nominal)
MARZO qualitative (ordinal)
KilosMarzo quantitative (discrete)
Fecha3 qualitative (nominal)
ABRIL qualitative (ordinal)
KilosAbril quantitative (discrete)
Fecha4 qualitative (nominal)
MAYO qualitative (ordinal)
KilosMayo quantitative (discrete)
Fecha5 qualitative (nominal)
JUNIO qualitative (ordinal)
KilosJunio quantitative (discrete)
Fecha6 qualitative (nominal)
JULIO qualitative (ordinal)
KilosJulio quantitative (discrete)
Fecha7 qualitative (nominal)
AGOSTO qualitative (ordinal)
KilosAgosto quantitative (discrete)
Fecha8 qualitative (nominal)
SEPTIEMBRE qualitative (ordinal)
KilosSeptiembre quantitative (discrete)

Eliminar NA’s y sustituir con 0’s

sum(is.na(bd))
## [1] 42
bd[is.na(bd)]<-0

Eliminar duplicados

bd[duplicated(bd), ]
##  [1] Fecha           ENERO           KilosEnero      Fecha1         
##  [5] FEBRERO         KilosFebrero    Fecha2          MARZO          
##  [9] KilosMarzo      Fecha3          ABRIL           KilosAbril     
## [13] Fecha4          MAYO            KilosMayo       Fecha5         
## [17] JUNIO           KilosJunio      Fecha6          JULIO          
## [21] KilosJulio      Fecha7          AGOSTO          KilosAgosto    
## [25] Fecha8          SEPTIEMBRE      KilosSeptiembre
## <0 rows> (or 0-length row.names)
sum(duplicated(bd))
## [1] 0

Eliminar negativos con cero

bd1<-bd
bd1[bd1 <0] <-0
summary(bd1)
##     Fecha              ENERO             KilosEnero      Fecha1         
##  Length:10          Length:10          Min.   :   0   Length:10         
##  Class :character   Class :character   1st Qu.:   0   Class :character  
##  Mode  :character   Mode  :character   Median :   0   Mode  :character  
##                                        Mean   :1456                     
##                                        3rd Qu.:2912                     
##                                        Max.   :5080                     
##    FEBRERO           KilosFebrero     Fecha2             MARZO          
##  Length:10          Min.   :   0   Length:10          Length:10         
##  Class :character   1st Qu.:   0   Class :character   Class :character  
##  Mode  :character   Median :3500   Mode  :character   Mode  :character  
##                     Mean   :2283                                        
##                     3rd Qu.:3815                                        
##                     Max.   :4380                                        
##    KilosMarzo      Fecha3             ABRIL             KilosAbril  
##  Min.   :   0   Length:10          Length:10          Min.   :   0  
##  1st Qu.:   0   Class :character   Class :character   1st Qu.:   0  
##  Median :3135   Mode  :character   Mode  :character   Median :1475  
##  Mean   :2247                                         Mean   :1882  
##  3rd Qu.:3952                                         3rd Qu.:3878  
##  Max.   :4200                                         Max.   :4190  
##     Fecha4              MAYO             KilosMayo       Fecha5         
##  Length:10          Length:10          Min.   :   0   Length:10         
##  Class :character   Class :character   1st Qu.:   0   Class :character  
##  Mode  :character   Mode  :character   Median :1840   Mode  :character  
##                                        Mean   :2341                     
##                                        3rd Qu.:4460                     
##                                        Max.   :6140                     
##     JUNIO             KilosJunio      Fecha6             JULIO          
##  Length:10          Min.   :   0   Length:10          Length:10         
##  Class :character   1st Qu.:   0   Class :character   Class :character  
##  Mode  :character   Median :   0   Mode  :character   Mode  :character  
##                     Mean   :1828                                        
##                     3rd Qu.:4312                                        
##                     Max.   :5010                                        
##    KilosJulio      Fecha7             AGOSTO           KilosAgosto  
##  Min.   :   0   Length:10          Length:10          Min.   :   0  
##  1st Qu.:   0   Class :character   Class :character   1st Qu.:3140  
##  Median :1065   Mode  :character   Mode  :character   Median :3525  
##  Mean   :1937                                         Mean   :3210  
##  3rd Qu.:3950                                         3rd Qu.:4208  
##  Max.   :5230                                         Max.   :5080  
##     Fecha8           SEPTIEMBRE        KilosSeptiembre
##  Length:10          Length:10          Min.   :   0   
##  Class :character   Class :character   1st Qu.:   0   
##  Mode  :character   Mode  :character   Median :   0   
##                                        Mean   :1359   
##                                        3rd Qu.:2995   
##                                        Max.   :3967

Análisis Profundo de la Base de datos

media_bd5 <- mean(bd$KilosMayo)
media_bd5
## [1] 2341
median_bd5 <- median(bd$KilosMayo)
median_bd5
## [1] 1840
mode_bd5 <- mode(bd$KilosMayo)
mode_bd5
## [1] "numeric"
media_bd8 <- mean(bd$KilosAgosto)
media_bd8
## [1] 3210
median_bd8 <- median(bd$KilosAgosto)
median_bd8
## [1] 3525
mode_bd8 <- mode(bd$KilosAgosto)
mode_bd8
## [1] "numeric"

Grafica Frecuencia (Fecha)

bd$Fecha7<- as.Date(bd$Fecha7,format = "%d/%m/%Y")
plot(bd$Fecha7, bd$KilosAgosto)

Se movieron alrededor de 3000 a 5000 mil kilos en el lapso de Agosto de este año.

Grafica de Mayo & Agosto (Mayor cantidad de merma y registros)

ggplot(bd, aes(x= Fecha4, y= KilosMayo)) + geom_bar(stat="identity", fill="blue") + scale_fill_grey() + labs(title = "Kilos de merma Agosto", x = "Fecha")

ggplot(bd, aes(x= Fecha7, y= KilosAgosto)) + geom_bar(stat="identity", fill="blue") + scale_fill_grey() + labs(title = "Kilos de merma Agosto", x = "Fecha")
## Warning: Removed 1 rows containing missing values (position_stack).

Podemos ver como en Agosto se tuvo un promedio de merma por día sobrepasando los 3000 kilos, siendo esta gráfica relevante para poder identificar factores importantes y reducir estas cantidades aplicando KPI’s

Delivery Performance

Importar base de datos

#file.choose()
bd_totaldiferencias<-read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/DELIVERY PERFORMANCDE/FORM Delivery Performance Bd Clientes.csv")
bd_totalmes<-read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/DELIVERY PERFORMANCDE/DEL PERF TOTALES.csv")

Entender la base de datos

summary (bd_totaldiferencias)
##     FECHA              PRINTEL           MAHLE             MAGNA    
##  Length:997         Min.   :0.0000   Min.   :-11.650   Min.   :0    
##  Class :character   1st Qu.:0.0000   1st Qu.:  1.800   1st Qu.:0    
##  Mode  :character   Median :0.0000   Median :  3.000   Median :0    
##                     Mean   :0.4418   Mean   :  2.364   Mean   :0    
##                     3rd Qu.:1.0000   3rd Qu.:  3.150   3rd Qu.:0    
##                     Max.   :4.4000   Max.   : 20.000   Max.   :0    
##                     NA's   :698      NA's   :698       NA's   :698  
##      VARROC       X             X.1            X.2            X.3         
##  Min.   :0     Mode:logical   Mode:logical   Mode:logical   Mode:logical  
##  1st Qu.:0     NA's:997       NA's:997       NA's:997       NA's:997      
##  Median :0                                                                
##  Mean   :0                                                                
##  3rd Qu.:0                                                                
##  Max.   :0                                                                
##  NA's   :698                                                              
##    X.4            X.5            X.6            X.7            X.8         
##  Mode:logical   Mode:logical   Mode:logical   Mode:logical   Mode:logical  
##  NA's:997       NA's:997       NA's:997       NA's:997       NA's:997      
##                                                                            
##                                                                            
##                                                                            
##                                                                            
##                                                                            
##    X.9            X.10           X.11           X.12           X.13        
##  Mode:logical   Mode:logical   Mode:logical   Mode:logical   Mode:logical  
##  NA's:997       NA's:997       NA's:997       NA's:997       NA's:997      
##                                                                            
##                                                                            
##                                                                            
##                                                                            
##                                                                            
##    X.14           X.15           X.16           X.17           X.18        
##  Mode:logical   Mode:logical   Mode:logical   Mode:logical   Mode:logical  
##  NA's:997       NA's:997       NA's:997       NA's:997       NA's:997      
##                                                                            
##                                                                            
##                                                                            
##                                                                            
##                                                                            
##    X.19           X.20        
##  Mode:logical   Mode:logical  
##  NA's:997       NA's:997      
##                               
##                               
##                               
##                               
## 
summary(bd_totalmes)
##     FECHA              PRINTEL          MAHLE           MAGNA         VARROC   
##  Length:999         Min.   : 0.00   Min.   :15.70   Min.   :0     Min.   :0    
##  Class :character   1st Qu.: 0.00   1st Qu.:46.27   1st Qu.:0     1st Qu.:0    
##  Mode  :character   Median : 4.90   Median :60.10   Median :0     Median :0    
##                     Mean   :10.16   Mean   :54.13   Mean   :0     Mean   :0    
##                     3rd Qu.:18.41   3rd Qu.:66.44   3rd Qu.:0     3rd Qu.:0    
##                     Max.   :31.21   Max.   :71.25   Max.   :0     Max.   :0    
##                     NA's   :986     NA's   :986     NA's   :986   NA's   :986

Técnicas de Limpieza

BASE DE DATOS 1

Técnica 1. Remover columna irrelevante

Eliminar columnas: Se realizó esta técnica ya que al momento de entender la base de datos se identificaron columnas sin valor y sin relevancia relacionadas con lo que se quería interpretar y visualizar.

bd_totaldiferencias <- subset (bd_totaldiferencias,select = -c(X, X.1, X.2, X.3, X.4, X.5, X.6, X.7, X.8, X.9, X.10, X.11, X.12, X.13, X.14, X.15, X.16, X.17, X.18, X.19, X.20 ))
summary (bd_totaldiferencias)
##     FECHA              PRINTEL           MAHLE             MAGNA    
##  Length:997         Min.   :0.0000   Min.   :-11.650   Min.   :0    
##  Class :character   1st Qu.:0.0000   1st Qu.:  1.800   1st Qu.:0    
##  Mode  :character   Median :0.0000   Median :  3.000   Median :0    
##                     Mean   :0.4418   Mean   :  2.364   Mean   :0    
##                     3rd Qu.:1.0000   3rd Qu.:  3.150   3rd Qu.:0    
##                     Max.   :4.4000   Max.   : 20.000   Max.   :0    
##                     NA's   :698      NA's   :698       NA's   :698  
##      VARROC   
##  Min.   :0    
##  1st Qu.:0    
##  Median :0    
##  Mean   :0    
##  3rd Qu.:0    
##  Max.   :0    
##  NA's   :698
### Técnica 2. Identificar NA's
sum(is.na(bd_totaldiferencias))
## [1] 2792
sapply(bd_totaldiferencias, function(x) sum (is.na(x)))
##   FECHA PRINTEL   MAHLE   MAGNA  VARROC 
##       0     698     698     698     698
##*Eliminar filas las cuales no cuentan con valores*
bd_totaldiferencias<-bd_totaldiferencias[-c(300:997),]


### Técnica 3. Cambiar formatos 
bd_totaldiferencias$PRINTEL<-as.integer(bd_totaldiferencias$PRINTEL) 
bd_totaldiferencias$MAHLE<-as.integer(bd_totaldiferencias$MAHLE) 
bd_totaldiferencias$MAGNA<-as.integer(bd_totaldiferencias$MAGNA) 
bd_totaldiferencias$VARROC<-as.integer(bd_totaldiferencias$VARROC) 

BASE DE DATOS 2

Técnica 1. Eliminar NA’s

Eliminar filas las cuales no cuentan con valores

bd_totalmes<-bd_totalmes[-c(14:999),]


### Técnica 2. Cambiar formato 
bd_totalmes$PRINTEL<-as.integer(bd_totalmes$PRINTEL) 
bd_totalmes$MAHLE<-as.integer(bd_totalmes$MAHLE) 
bd_totalmes$MAGNA<-as.integer(bd_totalmes$MAGNA) 
bd_totalmes$VARROC<-as.integer(bd_totalmes$VARROC) 

Analizar base de datos

str (bd_totaldiferencias)
## 'data.frame':    299 obs. of  5 variables:
##  $ FECHA  : chr  "July 22 th " "July 25th " "July 26th " "July 27th " ...
##  $ PRINTEL: int  0 1 1 0 0 1 1 1 0 1 ...
##  $ MAHLE  : int  2 2 2 2 2 2 2 3 3 3 ...
##  $ MAGNA  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ VARROC : int  0 0 0 0 0 0 0 0 0 0 ...
str (bd_totalmes)
## 'data.frame':    13 obs. of  5 variables:
##  $ FECHA  : chr  "jul-21" "ago-21" "sep-21" "oct-21" ...
##  $ PRINTEL: int  4 27 8 0 10 18 28 31 0 0 ...
##  $ MAHLE  : int  15 67 56 67 60 46 66 71 63 50 ...
##  $ MAGNA  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ VARROC : int  0 0 0 0 0 0 0 0 0 0 ...
summary(bd_totaldiferencias)
##     FECHA              PRINTEL           MAHLE            MAGNA       VARROC 
##  Length:299         Min.   :0.0000   Min.   :-11.00   Min.   :0   Min.   :0  
##  Class :character   1st Qu.:0.0000   1st Qu.:  1.00   1st Qu.:0   1st Qu.:0  
##  Mode  :character   Median :0.0000   Median :  3.00   Median :0   Median :0  
##                     Mean   :0.3679   Mean   :  2.11   Mean   :0   Mean   :0  
##                     3rd Qu.:1.0000   3rd Qu.:  3.00   3rd Qu.:0   3rd Qu.:0  
##                     Max.   :4.0000   Max.   : 20.00   Max.   :0   Max.   :0
summary(bd_totalmes)
##     FECHA              PRINTEL           MAHLE           MAGNA       VARROC 
##  Length:13          Min.   : 0.000   Min.   :15.00   Min.   :0   Min.   :0  
##  Class :character   1st Qu.: 0.000   1st Qu.:46.00   1st Qu.:0   1st Qu.:0  
##  Mode  :character   Median : 4.000   Median :60.00   Median :0   Median :0  
##                     Mean   : 9.769   Mean   :53.62   Mean   :0   Mean   :0  
##                     3rd Qu.:18.000   3rd Qu.:66.00   3rd Qu.:0   3rd Qu.:0  
##                     Max.   :31.000   Max.   :71.00   Max.   :0   Max.   :0

La base de datos total diferenicas cuenta con 299 observaciones y 5 variables mientra que la base de datos total mensual cuenta con 13 observaciones y 5 variables.

Tipos de Variables Existentes

Variable<-c("FECHA")
Type<-c("Cualitativa (Ordinal)")  
table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
FECHA Cualitativa (Ordinal)

Escala de medición

Variable<-c("PRINTEL", "MAHLE", "MAGNA", "VARROC")
Type<-c("Horas", "Horas", "Horas", "Horas")  
table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
PRINTEL Horas
MAHLE Horas
MAGNA Horas
VARROC Horas

Describir la base de datos

str(bd_totaldiferencias)
## 'data.frame':    299 obs. of  5 variables:
##  $ FECHA  : chr  "July 22 th " "July 25th " "July 26th " "July 27th " ...
##  $ PRINTEL: int  0 1 1 0 0 1 1 1 0 1 ...
##  $ MAHLE  : int  2 2 2 2 2 2 2 3 3 3 ...
##  $ MAGNA  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ VARROC : int  0 0 0 0 0 0 0 0 0 0 ...
str(bd_totalmes)
## 'data.frame':    13 obs. of  5 variables:
##  $ FECHA  : chr  "jul-21" "ago-21" "sep-21" "oct-21" ...
##  $ PRINTEL: int  4 27 8 0 10 18 28 31 0 0 ...
##  $ MAHLE  : int  15 67 56 67 60 46 66 71 63 50 ...
##  $ MAGNA  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ VARROC : int  0 0 0 0 0 0 0 0 0 0 ...

Análisis Profundo de la Base de datos

media_bd <- mean(bd_totaldiferencias$DIFERENCIA)
## Warning in mean.default(bd_totaldiferencias$DIFERENCIA): argument is not numeric
## or logical: returning NA
media_bd
## [1] NA
median_bd <- median(bd_totaldiferencias$DIFERENCIA)
median_bd
## NULL
mode <- function (x) {
  ux <- unique(x)
  ux [which.max(tabulate(match(x,ux)))]
}
mode_bd <- mode(bd_totaldiferencias$DIFERENCIA)
mode_bd
## NULL
hist(bd_totaldiferencias$MAHLE) 

hist(bd_totaldiferencias$PRINTEL)

Análisis Profundo de la Base de datos BDCLIENTES

media_bdclientes <- mean(bd_totalmes$PRINTEL)
media_bdclientes
## [1] 9.769231
median_bdclientes <- median(bd_totalmes$PRINTEL)
median_bdclientes
## [1] 4
mode_bdclientes <- mode(bd_totalmes$PRINTEL)
mode_bdclientes
## [1] 0
media_bdclientes <- mean(bd_totalmes$MAHLE)
media_bdclientes
## [1] 53.61538
median_bdclientes <- median(bd_totalmes$MAHLE)
median_bdclientes
## [1] 60
mode_bdclientes <- mode(bd_totalmes$MAHLE)
mode_bdclientes
## [1] 67
bdclientes3 <-bd_totalmes
bdclientes3 <- subset (bdclientes3, select = -c (MAGNA,VARROC))

Histograma Printel

hist(bdclientes3$PRINTEL)

Histograma Mahle

hist(bdclientes3$MAHLE)

PERINTEL

En la clase de 0 a 5 se encuentra que se tuvo mayor frecuencia, siendo la clase que más se repite, esto quiere decir que… De los 12 meses, en 7 se tuvo una diferencia de tiempo de entre 0 y 5 minutos, siendo esta baja pero con un sesgo a la izquierda.

MAHLE

Este histograma tiene un sesgo hacia la derecha, se tiene una tendencia a tener un mayor retraso en la clase de 60 a 70 minutos aproximadamente con este cliente, esto en un aproximado de 6 meses de los 12 tomados en cuenta.

Gráfica PRINTEL

ggplot(bd_totalmes,aes(x=FECHA, y=PRINTEL,fill=PRINTEL))+
  geom_bar(stat="identity")+
  geom_hline(yintercept=33,linetype="dashed",color="black")+
  labs(x="Fecha",y="Retraso en Minutos", color="Legend")+
  ggtitle("Retraso en Desempeño de los Clientes")

Gráfica MAHLE

ggplot(bd_totalmes,aes(x=FECHA, y=MAHLE,fill=MAHLE))+
  geom_bar(stat="identity")+
  geom_hline(yintercept=33,linetype="dashed",color="black")+
  labs(x="Fecha",y="Retraso en Minutos", color="Legend")+
  ggtitle("Retraso en Desempeño de los Clientes")

Se puede concluir En estos dos gráfico se demuestra el retraso en desempeño de los clientes Mahle y Printel, también se observa la media siendo la línea horizontal de color negro.

Se pede concluir que Mahle es el cliente con mayor retraso sobre pasando los 60 minutos de retraso, mientras que Printel siempre se mantiene por debajo de los 30 minutos.

Scrap

Llamar a la base de datos

#file.choose()
bd <- read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos (limpias) CSV /FORM - Scrap Limpia .csv")

Cantidad de productos por día

bd$Fecha<- as.Date(bd$Fecha,format = "%d/%m/%Y")
plot(bd$Fecha, bd$Cantidad)

summary(bd)
##   Referencia            Fecha                Hora             Producto        
##  Length:250         Min.   :2022-08-01   Length:250         Length:250        
##  Class :character   1st Qu.:2022-08-11   Class :character   Class :character  
##  Mode  :character   Median :2022-08-19   Mode  :character   Mode  :character  
##                     Mean   :2022-08-17                                        
##                     3rd Qu.:2022-08-25                                        
##                     Max.   :2022-08-31                                        
##     Cantidad      Unidad.de.medida   Ubicación.de.origen Ubicación.de.desecho
##  Min.   : 0.000   Length:250         Length:250          Length:250          
##  1st Qu.: 1.000   Class :character   Class :character    Class :character    
##  Median : 2.000   Mode  :character   Mode  :character    Mode  :character    
##  Mean   : 6.696                                                              
##  3rd Qu.: 7.000                                                              
##  Max.   :96.000                                                              
##     Estado         
##  Length:250        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 

Número de variables y registros en base de datos

describe(bd)
## # A tibble: 1 × 26
##   described_…¹     n    na  mean    sd se_mean   IQR skewn…² kurto…³   p00   p01
##   <chr>        <int> <int> <dbl> <dbl>   <dbl> <dbl>   <dbl>   <dbl> <dbl> <dbl>
## 1 Cantidad       250     0  6.70  11.8   0.749     6    4.17    21.8     0     1
## # … with 15 more variables: p05 <dbl>, p10 <dbl>, p20 <dbl>, p25 <dbl>,
## #   p30 <dbl>, p40 <dbl>, p50 <dbl>, p60 <dbl>, p70 <dbl>, p75 <dbl>,
## #   p80 <dbl>, p90 <dbl>, p95 <dbl>, p99 <dbl>, p100 <dbl>, and abbreviated
## #   variable names ¹​described_variables, ²​skewness, ³​kurtosis
str(bd)
## 'data.frame':    250 obs. of  9 variables:
##  $ Referencia          : chr  "SP/08731" "SP/08730" "SP/08729" "SP/08728" ...
##  $ Fecha               : Date, format: "2022-08-31" "2022-08-31" ...
##  $ Hora                : chr  "14:55:40" "14:49:25" "13:49:29" "09:30:07" ...
##  $ Producto            : chr  "[BACKFRAME 60% CUELLO ARMADO] 18805. 60% Backframe. Cuello Armado." "[N61506747 CAJA] N61506747. Kit. Caja." "[N61506729 SEPARADOR] N61506729. Kit. Separador." "[341332 DIVISOR - U611 & U625] 341332. U611. U625. Divisor Troquelado." ...
##  $ Cantidad            : num  2 1 1 31 1 1 1 9 2 1 ...
##  $ Unidad.de.medida    : chr  "Unidad(es)" "Unidad(es)" "Unidad(es)" "Unidad(es)" ...
##  $ Ubicación.de.origen : chr  "SAB/Calidad/Entrega de PT" "SAB/Calidad/Entrega de PT" "SAB/Calidad/Entrega de PT" "SAB/Pre-Production" ...
##  $ Ubicación.de.desecho: chr  "Virtual Locations/Scrapped" "Virtual Locations/Scrapped" "Virtual Locations/Scrapped" "Virtual Locations/Scrapped" ...
##  $ Estado              : chr  "Hecho" "Hecho" "Hecho" "Hecho" ...
tabyl(bd, Producto, Ubicación.de.origen)
##                                                                                               Producto
##                                            [2065WY AS 30 99 0000 00 000 TAPA - BOX 2064WY] BOX  2064WY
##                                                                 [241B EXPORT CAJA] 241B. Export. Caja.
##                                     [341332 CELDA - U611 & U625] 341332. U611. U625. Celda Troquelada.
##                                 [341332 CHAROLA - U611 & U625] 341332. U611. U625. Charola Troquelada.
##                                 [341332 DIVISOR - U611 & U625] 341332. U611. U625. Divisor Troquelado.
##                                                                            [357790-TAPA] 357790. Tapa.
##                                                                              [358268-CAJA] 358268-CAJA
##                                                                              [358268-TAPA] 358268-TAPA
##                    [428579 AS 30 99 0000 00 000 INSERTO- FORD DAMPER] 14306. Damper Ford DTP. Inserto.
##              [428818 AS 30 99 0000 00 000 INSERTO - CHRYSLER INSERT DJ] CHRYSLER INSERT DJ PART 694087
##                   [429296 AS 30 99 0000 00 000 INSERTO - INSERT TMC 150 TESLA] 14783. TMC150. Inserto.
##           [446265 AS  30 99 0000 00 000 CAPA INTERMEDIA- PAD 43X36 DAIMLER] 14454. Daimler Pad 43 X 36
##                        [467.416-24 COMPARTIMENT INSERT 535X335X221MM CC ESD] Refacciones. P1. Celdado.
##                                         [496455 FS 30 99 0000 00 000 CARTÓN - BOX 0371813] BOX 0371813
##  [500033 AS 30 99 0000 00 000 INSERTO - Inserto FORD China 500033] 17397. 500033. FORD China. Inserto.
##                                 [642762 PACKING, SHEET, 565.2X742.9 - INSERT 642762] 642762. Pad. S.M.
##        [643920 CART, SOM, 746.8X569.0X292.1, RSC - BOX 643920 STABOMAT] 13891. 643920. Stabomat. Caja.
##                                                                                 [647713] 647713. Caja.
##                                   [938830 FS 30 99 0000 00 000 CARTÓN - SIZE 24"] 24". Caja Terminada.
##                              [939069 FS 30 99 0000 00 000 CARTÓN -BOX 939069 34"] 34". Caja Terminada.
##                                                 [A - CELDA SUDAFRICA BMW G01 LCI] Sudafrica. A. Pieza.
##                                                 [B - CELDA SUDAFRICA BMW G01 LCI] Sudáfrica. B. Pieza.
##                                     [BACKFRAME 60% CUELLO ARMADO] 18805. 60% Backframe. Cuello Armado.
##                                             [BACKFRAME 60% TAPA BASE] 18271. 60% Backframe. Tapa Base.
##                                                [BOX 143907 - CELDA] 143907. Solares. Celda Troquelada.
##                                                  [BOX 143907 - TAPA] 143907. Solares. Tapa Troquelada.
##                                                 [C - CELDA SUDAFRICA BMW G01 LCI] Sudáfrica. C. Pieza.
##    [CAJA ( ARMREST / HR REAR) TMC 110 MODEL Y] 19148. Modelo Y. TMC0110. Armrest & Rear & Center. Caja
##                                                                            [CAJA 695] N61506695. Caja.
##                                                                              [CAJA 726] N61506726 CAJA
##                                                                              [CAJA 734949] CAJA 734949
##                                                                             [CAJA 784] 784. Kit. Caja.
##                                                                  [CAJA 95161] 19079. 95161. Kit. Caja.
##                               [Caja backup canastilla gris] CAJA DE CARTÓN BACK UP CANASTILLA GRIS- P3
##                                                 [CAJA INDUSTRIAL 16" ROTATIVA] 16". Lamina Troquelada.
##                                        [CAJA INDUSTRIAL 24" ROTATIVA COMPLETA] 24". Lamina Troquelada.
##                                                 [CAJA INDUSTRIAL 34" ROTATIVA] 34". Lamina Troquelada.
##                                           [CAJA INDUSTRIAL 48" CON SELLO (PP)] 48". Lamina Troquelada.
##                                                               [CAJA MCV] Toyota. MCV. Caja Troquelada.
##                                                            [CAJA RSC DE KIT REFLEX] 857. Reflex. Caja.
##                                                              [CAJA RSC SHOCK TOWER] Shock Tower. Caja.
##                                                                        [CAJA RSC TGTX] TGTX. Caja RSC.
##                                                               [CELDA 955061] 955061. Celda Troquelada.
##                                                     [Celda Audi coupe] 18892. Coupe. Celda Troquelada.
##                                                      [CELDA AUDI Q5] 14096. Audi Q5. Celda Troquelada.
##                       [CELDA CON MICRO CORUUGAD O EN 32 PORTA ETIQUETA] TR13777 KIT TGTX. Caja + Celda
##                                                          [CELDA GM177] 14100. GM177. Celda Troquelada.
##                                             [CELDA VW CHATTANOOGA] Chattanooga. St3. Celda Troquelada.
##                                                          [CELL C] 60% Backframe. Separador con Doblez.
##                                                           [CHAROLA 955061] 955061. Charola Troquelada.
##                                                 [Charola audi coupe] 18890. Coupe. Charola Troquelada.
##                                                  [CHAROLA AUDI Q5] 14128. Audi Q5. Charola Troquelada.
##                                                      [CHAROLA GM177] 14131. GM177. Charola Troquelada.
##                                   [CHAROLA VW CHATTANOOGA] Chattanooga. St1 y St3. Charola Troquelada.
##                                                            [Console cell] Console Lower. Celda Armada.
##                                                 [D - CELDA SUDAFRICA BMW G01 LCI] Sudáfrica. D. Pieza.
##                                                  [DIVISOR AUDI Q5] 14234. Audi Q5. Divisor Troquelado.
##                        [DIVISOR CON DOBLEZ VW CHATTANOOGA] Chattanooga. St1 y St3. Divisor Troquelado.
##                                                                 [DIVISOR GM177] 14238. GM177. Divisor.
##                                                                 [DIVISOR REFLEX] 857. Reflex. Divisor.
##                            [DIVISOR ZIGZAG VW CHATTANOOGA] Chattanooga. St1 y St3. Zig Zag Troquelado.
##                                                 [E - CELDA SUDAFRICA BMW G01 LCI] Sudáfrica. E. Pieza.
##                                                 [F - CELDA SUDAFRICA BMW G01 LCI] Sudáfrica. F. Pieza.
##                                         [HSC P702 ICP] 17215. P558. P702. CD539. ICP. Caja HSC. Pieza.
##                                                    [INSERTO 241B EXPORT] 14308. 241B. Export. Inserto.
##                                             [Inserto Nextracker 3.0] Nextracker. 2.0. Damper. Inserto.
##                                                 [INSERTO SOLARES] 143907. Solares. Inserto Troquelada.
##                                               [MITAD DE CUELLO SHOCK TOWER] Shock Tower. Mitad Cuello.
##                                                              [MQ4A-Dunnage-part2] Kia. Inserto. Pieza.
##                                                               [MQ4A-Dunnage-tray] Kia. Charola. Pieza.
##                                                                      [N61506396 CAJA] N61506396. Caja.
##                                                            [N61506396 SEPARADOR] N61506396. Separador.
##                                                       [N61506729 SEPARADOR] N61506729. Kit. Separador.
##                                                                 [N61506747 CAJA] N61506747. Kit. Caja.
##                                                                 [N61506747 TAPA] N61506747. Kit. Tapa.
##                                 [NEXTRACKER 2.0 DAMPER CUELLO] 18976. Nextracker. 2.0. Damper. Cuello,
##                  [NEXTRACKER 2.0 DAMPER TAPA DE COROPLAST] Nextracker. 2.0. Damper. Tapa de Coroplast.
##                                                 [PTN.WS IP 60 CELL IBT] Y0199489 PTN.WS IP 60 CELL IBT
##      [REJILLA DE 16X PARA PIVOT DE TESLA PARA PROCESO DE MTM A PPG] CELDA PIVOTE CONTENEDOR RETORNABLE
##                                                               [SEAT BACK CAJA] Seat Back. Caja HSC 1/2
##                                                           [SEAT BACK CELDADO] Seat Back. Celda Armada.
##      [SEPARADOR 41" X 44" PARA PIVOTE Y SEAT BACK DE MTM A PPG] SEPARADOR PIVOTE CONTENEDOR RETORNABLE
##                                                [SEPARADOR MOTORGEAR] Motorgear. Separador para Celdas.
##                                                                            [TAPA 695] N61506695. Tapa.
##                                                                  [TAPA AVANAZAR] Avanzar. Tapa. Pieza.
##                                                                 [TESLA XDA90 CELDA A] XDA90. A. Pieza.
##                                                                 [TESLA XDA90 CELDA B] XDA90. B. Pieza.
##                                                   [TESLA XDA90 CHAROLA SUAJADA] XDA90. Charola. Pieza.
##                                                                [TMC 050 - RSC] Console lower - TMC 050
##                                                        [TMC 095] 19162. Modelo Y. TMC095. Front. Caja.
##                                                                           [TMC XXX] Armrest. Caja RSC.
##          [TR11910 CHAROLA C/2 DIV #20 SMOOTH C/32 CAVIDADES] TR11910. U725. DMS. ITB. Charola con ITB.
##                   [TR12438 TAPA ICP 539 TAPA 2415-2 EN CPARTÓN SENCILLO CORRUGADO] 18840. CD539. Tapa.
##                                                                 [TR12440 TAPA P558] 18842. P558. Tapa.
##                       [TR13776 CAJA RSC CK 44 ECT C/ PORTA ETIQUETA] TR13776. Caja con Porta Etiqueta.
##  SAB/Calidad/Entrega de PT SAB/Post-Production SAB/Pre-Production
##                          1                   0                  1
##                          1                   0                  0
##                          0                   0                 10
##                          0                   0                  5
##                          0                   0                  5
##                          2                   0                  1
##                          2                   0                  0
##                          2                   0                  0
##                          1                   0                  0
##                          1                   0                  2
##                          1                   0                  0
##                          2                   0                  0
##                          1                   0                  0
##                          0                   1                  0
##                          1                   0                  0
##                          3                   0                  0
##                          1                   0                  1
##                          1                   0                  2
##                          1                   0                  0
##                          1                   0                  0
##                          0                   0                  3
##                          0                   0                  3
##                          1                   0                  0
##                          1                   0                  0
##                          0                   0                  3
##                          0                   0                  1
##                          0                   0                  3
##                          0                   0                  1
##                          0                   1                  0
##                          0                   1                  0
##                          0                   0                  1
##                          0                   2                  0
##                          0                   0                  1
##                          0                   1                  0
##                          0                   0                 12
##                          0                   0                  3
##                          0                   0                 11
##                          0                   0                  7
##                          0                   0                  2
##                          0                   1                  0
##                          2                   0                  0
##                          0                   0                  1
##                          0                   0                  6
##                          0                   0                  3
##                          0                   0                 10
##                          1                   0                  0
##                          0                   0                  9
##                          0                   0                  1
##                          1                   0                  0
##                          0                   0                  5
##                          0                   0                  2
##                          0                   0                  5
##                          0                   0                  5
##                          0                   0                  5
##                          2                   0                  0
##                          0                   0                  3
##                          0                   0                  4
##                          0                   0                  4
##                          0                   0                  5
##                          0                   1                  0
##                          0                   0                  4
##                          0                   0                  2
##                          0                   0                  3
##                          0                   0                  4
##                          2                   0                  0
##                          3                   0                  1
##                          0                   0                  1
##                          0                   0                  1
##                          0                   0                  3
##                          0                   0                  3
##                          1                   1                  0
##                          0                   1                  0
##                          1                   0                  0
##                          3                   0                  0
##                          2                   0                  0
##                          2                   0                  0
##                          2                   0                  0
##                          1                   0                  0
##                          1                   0                  0
##                          2                   0                  0
##                          1                   0                  0
##                          1                   0                  0
##                          1                   0                  0
##                          0                   1                  0
##                          0                   0                  2
##                          0                   0                  3
##                          0                   0                  1
##                          0                   0                  2
##                          0                   0                  1
##                          1                   0                  1
##                          0                   0                  1
##                          3                   0                  0
##                          0                   1                  0
##                          1                   0                  0
##                          0                   1                  0

Tipos de Variables Existentes

variable<-c("Referencia","Fecha", "Hora", "Producto", "Cantidad", "Unidad.de.medida", "Ubicación.de.origen", "Ubicación.de.desecho")

type<-c("Cualitativo (nominal)","Cualitativo (nominal)", "Cuantitativo (discreta)", "Cualitativo (nominal)","Cuantitativo (Continua)", "Cualitativo (nominal)", "Cualitativo (nominal)","Cualitativo (nominal)")

table<-data.frame(variable,type)
knitr::kable(table)
variable type
Referencia Cualitativo (nominal)
Fecha Cualitativo (nominal)
Hora Cuantitativo (discreta)
Producto Cualitativo (nominal)
Cantidad Cuantitativo (Continua)
Unidad.de.medida Cualitativo (nominal)
Ubicación.de.origen Cualitativo (nominal)
Ubicación.de.desecho Cualitativo (nominal)

Limpieza Base de datos

La base de datos contaba con algunas variables que no eran tan relevantes para analizar la base de scrap y se decidió eliminarlas para contar con menos variables y así poder realizar un mejor análisis.

sum(is.na(bd))
## [1] 0
sapply(bd, function(x) sum(is.na(x)))
##           Referencia                Fecha                 Hora 
##                    0                    0                    0 
##             Producto             Cantidad     Unidad.de.medida 
##                    0                    0                    0 
##  Ubicación.de.origen Ubicación.de.desecho               Estado 
##                    0                    0                    0
bd2 <- bd
bd2 <- subset (bd2, select = -c (Hora))
bd2 <- subset (bd2, select = -c (Producto))
bd2 <- subset (bd2, select = -c (Ubicación.de.desecho))
bd2 <- subset (bd2, select = -c (Unidad.de.medida ))
bd2 <- subset (bd2, select = -c (Referencia ))
bd2 <- subset (bd2, select = -c (Estado ))

summary(bd2)
##      Fecha               Cantidad      Ubicación.de.origen
##  Min.   :2022-08-01   Min.   : 0.000   Length:250         
##  1st Qu.:2022-08-11   1st Qu.: 1.000   Class :character   
##  Median :2022-08-19   Median : 2.000   Mode  :character   
##  Mean   :2022-08-17   Mean   : 6.696                      
##  3rd Qu.:2022-08-25   3rd Qu.: 7.000                      
##  Max.   :2022-08-31   Max.   :96.000
#seleccionar columnas / variables.
#scrap2<-scrap %>% select(one_of('Fecha','Cantidad','Ubicación.de.origen'))

Renombrar las columnas /variables seleccionadas.

colnames(bd2) <-c ('Fecha','Cant.','Origen')
summary(bd2)
##      Fecha                Cant.           Origen         
##  Min.   :2022-08-01   Min.   : 0.000   Length:250        
##  1st Qu.:2022-08-11   1st Qu.: 1.000   Class :character  
##  Median :2022-08-19   Median : 2.000   Mode  :character  
##  Mean   :2022-08-17   Mean   : 6.696                     
##  3rd Qu.:2022-08-25   3rd Qu.: 7.000                     
##  Max.   :2022-08-31   Max.   :96.000

Análisis Estadístico

Tabla de Media, Moda y Mediana

summary(bd2)
##      Fecha                Cant.           Origen         
##  Min.   :2022-08-01   Min.   : 0.000   Length:250        
##  1st Qu.:2022-08-11   1st Qu.: 1.000   Class :character  
##  Median :2022-08-19   Median : 2.000   Mode  :character  
##  Mean   :2022-08-17   Mean   : 6.696                     
##  3rd Qu.:2022-08-25   3rd Qu.: 7.000                     
##  Max.   :2022-08-31   Max.   :96.000
sd(bd2$Cant., na.rm= TRUE)
## [1] 11.84885
hist(bd2$Cant.)

Gráfica de Relacion de SAB

ggplot(bd2, aes(x=Fecha, y= Origen)) +
  geom_bar(stat="identity", fill="orange") + scale_fill_grey() + # Add bars to the plot
  labs(title = "Relación SAB", # Add a title
       subtitle = "Scrap empresa FORM", # Add a subtitle
       caption = "Relación", # Add a caption
       x = "x")

Gráfica Scrap por origen

ggplot(bd2,aes(x=Cant.))+
  geom_line(aes(y=Origen),color="orange")+
  labs(x="Cant",y="Origen", color="Legend")+
   ggtitle("Mayores catidades de Scrap por origen")

Gráfica Cualitativa

pie(table(bd2$Origen))

Gráfica Cuantitativa

barplot(table(bd2$Cant.,bd2$Origen), col="orange", main = "Kilos de Scrap", xlab = "Origen", ylab = "Kilos" )

Aquí podemos observar como la mayor cantidad de scrap es generada en el área de SAB / Pre producción de la empresa, concluyendo que se tienen que tomar medidas para poder reducir estas cantidades lo máximo posible quizá usando el material de manera optima para evitar tanto Scrap.

Tabla de frecuencia por distribución de origen

#install.packages('epiDisplay')
library(epiDisplay)
## Loading required package: MASS
## 
## Attaching package: 'MASS'
## The following object is masked from 'package:olsrr':
## 
##     cement
## The following object is masked from 'package:dplyr':
## 
##     select
## Loading required package: nnet
## 
## Attaching package: 'epiDisplay'
## The following object is masked from 'package:lmtest':
## 
##     lrtest
## The following object is masked from 'package:jtools':
## 
##     summ
## The following objects are masked from 'package:psych':
## 
##     alpha, cs, lookup
## The following object is masked from 'package:lattice':
## 
##     dotplot
## The following object is masked from 'package:ggplot2':
## 
##     alpha
tab1(bd2$Origen, sort.group = "decreasing", cum.percent = TRUE)

## bd2$Origen : 
##                           Frequency Percent Cum. percent
## SAB/Pre-Production              179    71.6         71.6
## SAB/Calidad/Entrega de PT        58    23.2         94.8
## SAB/Post-Production              13     5.2        100.0
##   Total                         250   100.0        100.0

Se puede concluir de estos gráficos que se tiene mucho scrap en la empresa principalmente en la etapa de pre-producción, aquí lo que se recomienda es medier exactamente la cantidad que se requiere de material para poder evitar tener esos desperdicios. Analizando estas variables se confirma que en el área de pre-producción es donde se genera la mayor parte del scrap en su mayoría que es casi el 85% de scrap que se genera dentro de la empresa.

Sección 2.2

Modélo Predictivo

Importar la base de datos

externa<- read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/Base externa /us_motor_production_and_domestic_sales.csv")
summary(externa)
##       Year      Total_Production Production_Passenger_Cars
##  Min.   :2007   Min.   : 5710    Min.   :1924             
##  1st Qu.:2010   1st Qu.: 8709    1st Qu.:2745             
##  Median :2014   Median :10823    Median :3382             
##  Mean   :2014   Mean   :10077    Mean   :3326             
##  3rd Qu.:2017   3rd Qu.:11268    3rd Qu.:4061             
##  Max.   :2020   Max.   :12179    Max.   :4369             
##  NA's   :8      NA's   :8        NA's   :8                
##  Production_Commercial_Vehicles Domestic_Sales  Sales_Passenger_Cars
##  Min.   :3514                   Min.   : 7868   Min.   :2560        
##  1st Qu.:5820                   1st Qu.:10474   1st Qu.:3865        
##  Median :6891                   Median :12583   Median :4542        
##  Mean   :6751                   Mean   :11996   Mean   :4491        
##  3rd Qu.:8095                   3rd Qu.:13669   3rd Qu.:5184        
##  Max.   :8512                   Max.   :14128   Max.   :5610        
##  NA's   :8                      NA's   :8       NA's   :8           
##  Sales_Commercial_Vehicles US_Unemployment US_Consumer_Confidence
##  Min.   : 4309             Min.   :3.680   Min.   :63.75         
##  1st Qu.: 6088             1st Qu.:4.685   1st Qu.:73.02         
##  Median : 7634             Median :5.980   Median :82.83         
##  Mean   : 7505             Mean   :6.430   Mean   :82.29         
##  3rd Qu.: 8964             3rd Qu.:8.088   3rd Qu.:92.67         
##  Max.   :10133             Max.   :9.610   Max.   :98.37         
##  NA's   :8                 NA's   :8       NA's   :8             
##  US_Min_Hour_Wage
##  Min.   :5.500   
##  1st Qu.:7.250   
##  Median :7.250   
##  Mean   :7.025   
##  3rd Qu.:7.250   
##  Max.   :7.250   
##  NA's   :8

Realizar regresión 1

regresion <- lm(Production_Commercial_Vehicles ~ US_Unemployment + US_Consumer_Confidence + US_Min_Hour_Wage , data=externa)
summary(regresion)
## 
## Call:
## lm(formula = Production_Commercial_Vehicles ~ US_Unemployment + 
##     US_Consumer_Confidence + US_Min_Hour_Wage, data = externa)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -1198.1  -257.4   109.0   286.7   623.0 
## 
## Coefficients:
##                        Estimate Std. Error t value Pr(>|t|)  
## (Intercept)            -2217.25    2387.79  -0.929   0.3750  
## US_Unemployment         -226.91     159.03  -1.427   0.1841  
## US_Consumer_Confidence    82.82      28.06   2.952   0.0145 *
## US_Min_Hour_Wage         514.11     387.30   1.327   0.2139  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 525.3 on 10 degrees of freedom
##   (8 observations deleted due to missingness)
## Multiple R-squared:  0.9082, Adjusted R-squared:  0.8807 
## F-statistic: 32.99 on 3 and 10 DF,  p-value: 1.692e-05

Analizar el comportamiento de las variables independientes en la regresión

effect_plot(regresion,pred=US_Consumer_Confidence,interval=TRUE)

effect_plot(regresion,pred=US_Unemployment,interval=TRUE)

effect_plot(regresion,pred=US_Min_Hour_Wage,interval=TRUE)

Al ser la Producción de Autos Comerciales la variable dependiente, observamos como el salario, la confianza del consumidor y el desempleo generan cambios en ella. Podemos ver que el que mayor impacto que tiene es la confianza del consumidor. También podemos ver su comportamiento en la gráfica como si la producción sube, igualmente la confianza del consumidor.

Realizar regresión 2

regresion2 <- lm(Production_Passenger_Cars ~ US_Unemployment + US_Consumer_Confidence + US_Min_Hour_Wage , data=externa)
summary(regresion2)
## 
## Call:
## lm(formula = Production_Passenger_Cars ~ US_Unemployment + US_Consumer_Confidence + 
##     US_Min_Hour_Wage, data = externa)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -1096.8  -600.5  -162.9   763.0  1154.1 
## 
## Coefficients:
##                        Estimate Std. Error t value Pr(>|t|)
## (Intercept)            6399.886   4071.397   1.572    0.147
## US_Unemployment        -194.101    271.160  -0.716    0.490
## US_Consumer_Confidence  -22.272     47.840  -0.466    0.652
## US_Min_Hour_Wage          1.058    660.387   0.002    0.999
## 
## Residual standard error: 895.7 on 10 degrees of freedom
##   (8 observations deleted due to missingness)
## Multiple R-squared:  0.09057,    Adjusted R-squared:  -0.1823 
## F-statistic: 0.3319 on 3 and 10 DF,  p-value: 0.8026

Analizar el comportamiento de las variables independientes en la regresión

effect_plot(regresion2,pred=US_Consumer_Confidence,interval=TRUE)

effect_plot(regresion2,pred=US_Unemployment,interval=TRUE)

effect_plot(regresion2,pred=US_Min_Hour_Wage,interval=TRUE)

La producción de autos de pasajero tiene estimados negativos en las variables independientes del desempleo y confianza del consumidor, por esta razón su comportamiento en las gráficas a pesar de que exista una producción alta su tendencia va para abajo.

Pronóstico

Pronóstico MEX

#file.choose("/Users/mac/Downloads/mexico externa.csv")
Mexico<- read_csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/Base externa /mexico externa.csv")
## Rows: 7 Columns: 8
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (8): Fecha, Conf_Consumidor, tasa_inflación, % Pob Desocu, % Pob Ocu, Ve...
## 
## ℹ 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.

Llamar Librerias

library(forecast)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
## Registered S3 methods overwritten by 'forecast':
##   method                 from     
##   autoplot.Arima         ggfortify
##   autoplot.acf           ggfortify
##   autoplot.ar            ggfortify
##   autoplot.bats          ggfortify
##   autoplot.decomposed.ts ggfortify
##   autoplot.ets           ggfortify
##   autoplot.forecast      ggfortify
##   autoplot.stl           ggfortify
##   autoplot.ts            ggfortify
##   fitted.ar              ggfortify
##   fortify.ts             ggfortify
##   residuals.ar           ggfortify

Crear serie de tiempo

Mexico <- c(3399076,3465615,3933154,3918603,3811068,3040178,3028481)

produccion_st <- ts(data = Mexico, start = c(2015,1), frequency = 1)
produccion_st
## Time Series:
## Start = 2015 
## End = 2021 
## Frequency = 1 
## [1] 3399076 3465615 3933154 3918603 3811068 3040178 3028481

Graficar Pronostico

modelo <- auto.arima(produccion_st)
modelo
## Series: produccion_st 
## ARIMA(0,0,0) with non-zero mean 
## 
## Coefficients:
##            mean
##       3513739.3
## s.e.   135784.5
## 
## sigma^2 = 1.506e+11:  log likelihood = -99.47
## AIC=202.95   AICc=205.95   BIC=202.84
pronostico <- forecast(modelo, level=c(95), h=3)
pronostico
##      Point Forecast   Lo 95   Hi 95
## 2022        3513739 2753205 4274274
## 2023        3513739 2753205 4274274
## 2024        3513739 2753205 4274274
plot(pronostico)

Aquí podemos observar que para los próximos tres años tenemos un aumento en la prdoducción de autos dentro del país, ésta tuvo un decremento por causa de la pandemia en los tres años pasados pero se pronostica que esta aumente.

Pronóstico EUA TOTAL PRODUCTION

#file.choose("/Users/mac/Downloads/us_motor_production_and_domestic_sales (2).csv")
EUA<- read_csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/Base externa /us_motor_production_and_domestic_sales.csv")
## Rows: 22 Columns: 10
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (10): Year, Total_Production, Production_Passenger_Cars, Production_Comm...
## 
## ℹ 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.

Llamar Librerias

library(forecast)

Crear serie de tiempo

EUA <- c(10752,8672,5710,7744,8662,10336,11067,11611,12106,12179,11179,11297,10893,8821)

produccion_st1 <- ts(data = EUA, start = c(2007,1), frequency = 1)
produccion_st1
## Time Series:
## Start = 2007 
## End = 2020 
## Frequency = 1 
##  [1] 10752  8672  5710  7744  8662 10336 11067 11611 12106 12179 11179 11297
## [13] 10893  8821

Graficar Pronostico

modelo1 <- auto.arima(produccion_st1)
modelo1
## Series: produccion_st1 
## ARIMA(0,1,0) 
## 
## sigma^2 = 2110238:  log likelihood = -113.1
## AIC=228.2   AICc=228.57   BIC=228.77
pronostico1 <- forecast(modelo1, level=c(95), h=3)
pronostico1
##      Point Forecast    Lo 95    Hi 95
## 2021           8821 5973.827 11668.17
## 2022           8821 4794.490 12847.51
## 2023           8821 3889.553 13752.45
plot(pronostico1)

En cuanto a la producción total de autos en Estados Unidos podemos obsevar que del 2010 al 2019 tuvieron un aumento significativo en su producción, y para 2020 tuvo una caída a causa de la pandemia, se pronostica que para 2023 esta producción siga baja pero que después esta ya empiece a aumnetar.

Pronóstico EUA DOMESTIC SALES

#file.choose("/Users/mac/Downloads/us_motor_production_and_domestic_sales (2).csv")
EUA1<- read_csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/Base externa /us_motor_production_and_domestic_sales.csv")
## Rows: 22 Columns: 10
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (10): Year, Total_Production, Production_Passenger_Cars, Production_Comm...
## 
## ℹ 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.

Llamar Librerias

library(forecast)

Crear serie de tiempo

EUA1 <- c(12687,10108,7868,9020,10109,11582,12479,13389,14128,13969,13644,13711,13677,11571)

produccion_st2 <- ts(data = EUA1, start = c(2007,1), frequency = 1)
produccion_st2
## Time Series:
## Start = 2007 
## End = 2020 
## Frequency = 1 
##  [1] 12687 10108  7868  9020 10109 11582 12479 13389 14128 13969 13644 13711
## [13] 13677 11571

Graficar Pronostico

modelo2 <- auto.arima(produccion_st2)
modelo2
## Series: produccion_st2 
## ARIMA(0,1,0) 
## 
## sigma^2 = 1777106:  log likelihood = -111.98
## AIC=225.97   AICc=226.33   BIC=226.53
pronostico2 <- forecast(modelo2, level=c(95), h=3)
pronostico2
##      Point Forecast    Lo 95    Hi 95
## 2021          11571 8958.209 14183.79
## 2022          11571 7875.955 15266.04
## 2023          11571 7045.513 16096.49
plot(pronostico2)

Pronóstico MERMA

Sumar el Total de KilosxMes

sum(bd$KilosEnero)
## [1] 0
sum(bd$KilosFebrero)
## [1] 0
sum(bd$KilosMarzo)
## [1] 0
sum(bd$KilosAbril)
## [1] 0
sum(bd$KilosMayo)
## [1] 0
sum(bd$KilosJunio)
## [1] 0
sum(bd$KilosJulio)
## [1] 0
sum(bd$KilosAgosto)
## [1] 0
sum(bd$KilosSeptiembre)
## [1] 0

Crear serie de tiempo

merma <- c(14560,22830,22470,18820,23410,18280,19370,32100,13586)

produccion_st <- ts(data = merma, start = c(2022,1), frequency = 12)
produccion_st
##        Jan   Feb   Mar   Apr   May   Jun   Jul   Aug   Sep
## 2022 14560 22830 22470 18820 23410 18280 19370 32100 13586

Graficar Pronostico

library(forecast)
modelo <- auto.arima(produccion_st)
modelo
## Series: produccion_st 
## ARIMA(0,0,0) with non-zero mean 
## 
## Coefficients:
##            mean
##       20602.889
## s.e.   1736.893
## 
## sigma^2 = 30544665:  log likelihood = -89.8
## AIC=183.59   AICc=185.59   BIC=183.99
pronostico <- forecast(modelo, level=c(95), h=3)
pronostico
##          Point Forecast    Lo 95    Hi 95
## Oct 2022       20602.89 9770.711 31435.07
## Nov 2022       20602.89 9770.711 31435.07
## Dec 2022       20602.89 9770.711 31435.07
plot(pronostico)

Se pronostica que en octubre la merma acumulada se mantenga en alrededor 2000 kilos aproximadamente, siendo más bajo que meses anteriores. Por lo que se propone reducir la merma todavía un 15 % más o 20% para reducirla a 1500 kilos para próximo mes.

Sección 3

K-means Clusters

Definición de conceptos

Conceptos que contribuyen a la identificación de clusters usando analítica de datos.

I. K- Means Clustering
K- means clustering tiene como objetivo agrupar datos con características similares en el mismo cluster. Uno de los beneficios más grandes de la herramienta es que se pueden resumir datos de gran dimensión.

II. Unsupervised Learning
No se asignan etiquetas al algoritmo de aprendizaje, dejándolo solo para encontrar la estructura en su entrada. El aprendizaje no supervisado puede ser un fin en sí mismo (descubrir patrones ocultos en los datos) o un medio para un fin (aprendizaje de funciones).

III. Eucliedean Distance
La distancia Euclidiana es el cálculo de distancia comúnmente utilizado para medir la distancia entre dos puntos de datos.

Cluster edad y salario diario

Leer la base de datos

bajasdata <-read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/RH/RHBAJASLIMPIA1.csv")
summary(bajasdata)
##      Nom                 Edad           Gen             Fecha_alta       
##  Length:237         Min.   : 0.00   Length:237         Length:237        
##  Class :character   1st Qu.:23.00   Class :character   Class :character  
##  Mode  :character   Median :29.00   Mode  :character   Mode  :character  
##                     Mean   :30.52                                        
##                     3rd Qu.:37.00                                        
##                     Max.   :61.00                                        
##       MB              Días_trab           Baja             PuestDes        
##  Length:237         Min.   :   0.00   Length:237         Length:237        
##  Class :character   1st Qu.:   9.00   Class :character   Class :character  
##  Mode  :character   Median :  21.00   Mode  :character   Mode  :character  
##                     Mean   :  83.42                                        
##                     3rd Qu.:  49.00                                        
##                     Max.   :1966.00                                        
##     Sal_IMSS         Col                Mun               Estado         
##  Min.   :144.4   Length:237         Length:237         Length:237        
##  1st Qu.:180.7   Class :character   Class :character   Class :character  
##  Median :180.7   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :178.6                                                           
##  3rd Qu.:180.7                                                           
##  Max.   :500.0                                                           
##     EstCiv         
##  Length:237        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 

Limpieza. Seleccionar variables relevantes

bajasdata1<-bajasdata
bajasdata1<-subset(bajasdata,select = -c(Gen,Fecha_alta,MB,PuestDes,Estado,Nom,Col,Mun,Baja, EstCiv, Días_trab))
summary(bajasdata1)
##       Edad          Sal_IMSS    
##  Min.   : 0.00   Min.   :144.4  
##  1st Qu.:23.00   1st Qu.:180.7  
##  Median :29.00   Median :180.7  
##  Mean   :30.52   Mean   :178.6  
##  3rd Qu.:37.00   3rd Qu.:180.7  
##  Max.   :61.00   Max.   :500.0

Limpieza. Eliminar edad 0

bajasdata2 <- bajasdata1
bajasdata2 <- bajasdata2 [bajasdata2$Edad> min(1), ]
summary(bajasdata2)
##       Edad          Sal_IMSS    
##  Min.   :18.00   Min.   :144.4  
##  1st Qu.:23.00   1st Qu.:180.7  
##  Median :29.00   Median :180.7  
##  Mean   :30.78   Mean   :178.6  
##  3rd Qu.:37.00   3rd Qu.:180.7  
##  Max.   :61.00   Max.   :500.0

Normalizar la base de datos

bajas_data_norm <- scale(bajasdata2[1:2])

Identificar número de clusters

fviz_nbclust(bajas_data_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=4, linetype=2)+           
  labs(subtitle = "Elbow method")  

Visualizar el cluster

edad_cluster1<-kmeans(bajas_data_norm,3)
edad_cluster1
## K-means clustering with 3 clusters of sizes 69, 121, 45
## 
## Cluster means:
##         Edad   Sal_IMSS
## 1  0.2811317  0.2784633
## 2 -0.7792176 -0.1288413
## 3  1.6641609 -0.0805373
## 
## Clustering vector:
##   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20 
##   1   1   2   2   2   3   2   2   3   2   2   1   2   1   1   2   2   2   2   2 
##  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40 
##   2   3   2   1   3   2   1   2   2   2   1   2   2   2   1   2   2   2   1   2 
##  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60 
##   2   2   2   2   2   2   2   2   3   3   3   3   1   3   2   2   3   2   2   3 
##  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80 
##   2   2   1   2   2   3   2   2   2   2   2   2   1   2   1   2   1   2   2   3 
##  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  98  99 100 101 
##   2   2   2   2   3   2   3   2   2   2   1   3   3   2   2   2   3   2   2   1 
## 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 
##   2   2   3   1   2   2   1   2   1   1   2   1   1   2   1   1   1   3   3   3 
## 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 
##   2   2   2   2   2   1   2   1   3   2   1   2   3   2   2   2   1   3   1   3 
## 142 143 144 145 146 147 148 150 151 152 153 154 155 156 157 158 159 160 161 162 
##   1   1   1   3   3   2   1   1   1   2   2   2   1   3   3   2   1   2   1   3 
## 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 
##   3   3   3   1   3   2   2   1   2   2   3   1   3   2   3   1   1   3   1   1 
## 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 
##   2   2   2   1   3   3   1   2   2   1   1   1   1   1   1   1   1   2   1   2 
## 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 
##   1   1   2   1   3   1   2   2   2   3   2   2   2   1   1   2   2   1   1   1 
## 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 
##   2   2   1   2   2   2   2   3   1   3   2   2   2   2   2 
## 
## Within cluster sum of squares by cluster:
## [1] 204.19421  35.55499  17.05330
##  (between_SS / total_SS =  45.1 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"
fviz_cluster(edad_cluster1,data=bajas_data_norm)

Análisis de clusters

bajasdata3<- bajasdata2
bajasdata3$Clusters<-edad_cluster1$cluster
bajasdata4<-bajasdata3 %>% group_by(Clusters) %>% summarise(Edad=max(Edad)) %>% arrange(desc(Edad))
bajasdata3$Cluster_Names<-factor(bajasdata3$Clusters,levels = c(1,2,3), 
                                 labels=c("Adulto", "Joven", "Jubilación"))
bajasdata5 <- bajasdata3 %>% dplyr:: group_by(Cluster_Names) %>% dplyr:: summarize(edad_años=max(Edad), 
                                                             Sal_IMSS=mean(Sal_IMSS),
                                                             count=n())
clusters<-as.data.frame(bajasdata5)
clusters
##   Cluster_Names edad_años Sal_IMSS count
## 1        Adulto        40 185.7365    69
## 2         Joven        32 175.3303   121
## 3    Jubilación        61 176.5644    45

Gráfico de barras de las bajas con edad máxima de cluster

ggplot(bajasdata5, aes(x=Cluster_Names,y=edad_años,fill= Cluster_Names,label=round(edad_años,digits=2))) + 
  geom_col() + 
  geom_text()

Gráfico de barras de las bajas con su salario

ggplot(bajasdata5,aes(x=Cluster_Names,y=Sal_IMSS ,fill= Cluster_Names,label=round(Sal_IMSS,digits=2))) + 
  geom_col() +  
  geom_text()

Dispersión de la edad

ggplot(bajasdata3, aes(x=Cluster_Names, y=Edad, fill=Cluster_Names)) +
  geom_boxplot()+
  ggtitle("Dispersion of 'Edad' by Clusters Names")

Dispersión del salario diario

ggplot(bajasdata3, aes(x=Cluster_Names, y=Sal_IMSS, fill=Cluster_Names)) +
  geom_boxplot()+
  ggtitle("Dispersion of 'Salario_Diario' by Clusters Names")

Cluster edad y días laborados

RHBAJAS <-read.csv("/Users/joseramonvazquezguzman/Documents/Tecnológico de Monterrey/Septimo semestre/Analítica de datos /RETO/Bases de datos finales/RH/RHBAJASLIMPIA1.csv")

Analizar base de datos.

summary(RHBAJAS)
##      Nom                 Edad           Gen             Fecha_alta       
##  Length:237         Min.   : 0.00   Length:237         Length:237        
##  Class :character   1st Qu.:23.00   Class :character   Class :character  
##  Mode  :character   Median :29.00   Mode  :character   Mode  :character  
##                     Mean   :30.52                                        
##                     3rd Qu.:37.00                                        
##                     Max.   :61.00                                        
##       MB              Días_trab           Baja             PuestDes        
##  Length:237         Min.   :   0.00   Length:237         Length:237        
##  Class :character   1st Qu.:   9.00   Class :character   Class :character  
##  Mode  :character   Median :  21.00   Mode  :character   Mode  :character  
##                     Mean   :  83.42                                        
##                     3rd Qu.:  49.00                                        
##                     Max.   :1966.00                                        
##     Sal_IMSS         Col                Mun               Estado         
##  Min.   :144.4   Length:237         Length:237         Length:237        
##  1st Qu.:180.7   Class :character   Class :character   Class :character  
##  Median :180.7   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :178.6                                                           
##  3rd Qu.:180.7                                                           
##  Max.   :500.0                                                           
##     EstCiv         
##  Length:237        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 
str(RHBAJAS)
## 'data.frame':    237 obs. of  13 variables:
##  $ Nom       : chr  "MARIO VALDEZ ORTIZ" "ISABEL BARRIOS MENDEZ" "MARIA ELIZABETH GOMEZ HERNANDEZ" "ALONDRA ABIGAIL ESCARCIA GOMEZ" ...
##  $ Edad      : int  32 36 23 21 29 46 29 31 50 19 ...
##  $ Gen       : chr  "MASCULINO" "FEMENINO" "FEMENINO" "FEMENINO" ...
##  $ Fecha_alta: chr  "2020-03-09" "2021-11-09" "2021-11-10" "2021-11-10" ...
##  $ MB        : chr  "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" ...
##  $ Días_trab : int  628 60 59 59 51 37 37 31 18 224 ...
##  $ Baja      : chr  "2021-11-27" "2022-01-08" "2022-01-08" "2022-01-08" ...
##  $ PuestDes  : chr  "DISEÑO" "AYUDANTE GENERAL" "AYUDANTE GENERAL" "AYUDANTE GENERAL" ...
##  $ Sal_IMSS  : num  500 152 152 152 152 ...
##  $ Col       : chr  "SAN NICOLAS DE LOS G" "COLINAS DEL AEROPÑUERTO" "PUEBLO NUEVO" "PUEBLO NUEVO" ...
##  $ Mun       : chr  "SAN NICOLAS DE LOS G" "PESQUERIA" "APODACA" "APODACA" ...
##  $ Estado    : chr  "NUEVO LEÓN" "NUEVO LEÓN" "NUEVO LEÓN" "NUEVO LEÓN" ...
##  $ EstCiv    : chr  "SOLTERO" "UNIÓN LIBRE" "CASADO" "SOLTERO" ...
describe(RHBAJAS)
## # A tibble: 3 × 26
##   described_…¹     n    na  mean    sd se_mean   IQR skewn…² kurto…³   p00   p01
##   <chr>        <int> <int> <dbl> <dbl>   <dbl> <dbl>   <dbl>   <dbl> <dbl> <dbl>
## 1 Edad           237     0  30.5  10.0   0.651    14   0.541   0.216    0    18 
## 2 Días_trab      237     0  83.4 227.   14.7      40   5.40   33.2      0     0 
## 3 Sal_IMSS       237     0 179.   25.4   1.65      0   9.51  115.     144.  152.
## # … with 15 more variables: p05 <dbl>, p10 <dbl>, p20 <dbl>, p25 <dbl>,
## #   p30 <dbl>, p40 <dbl>, p50 <dbl>, p60 <dbl>, p70 <dbl>, p75 <dbl>,
## #   p80 <dbl>, p90 <dbl>, p95 <dbl>, p99 <dbl>, p100 <dbl>, and abbreviated
## #   variable names ¹​described_variables, ²​skewness, ³​kurtosis

Edad vs dias laborados-Clusters

RHBAJAS1<-RHBAJAS
RHBAJAS1<-subset(RHBAJAS1,select = -c(Gen,Fecha_alta,MB,PuestDes,Estado,Nom,Col,Mun,Baja))
summary(RHBAJAS1)
##       Edad         Días_trab          Sal_IMSS        EstCiv         
##  Min.   : 0.00   Min.   :   0.00   Min.   :144.4   Length:237        
##  1st Qu.:23.00   1st Qu.:   9.00   1st Qu.:180.7   Class :character  
##  Median :29.00   Median :  21.00   Median :180.7   Mode  :character  
##  Mean   :30.52   Mean   :  83.42   Mean   :178.6                     
##  3rd Qu.:37.00   3rd Qu.:  49.00   3rd Qu.:180.7                     
##  Max.   :61.00   Max.   :1966.00   Max.   :500.0

Eliminar renglones

Eliminamos dos reglones que tenian como edad (0)

RHBAJAS2 <- RHBAJAS1
RHBAJAS2 <- RHBAJAS2 [RHBAJAS2$Edad> min(1), ]
summary(RHBAJAS2)
##       Edad         Días_trab          Sal_IMSS        EstCiv         
##  Min.   :18.00   Min.   :   0.00   Min.   :144.4   Length:235        
##  1st Qu.:23.00   1st Qu.:   9.50   1st Qu.:180.7   Class :character  
##  Median :29.00   Median :  21.00   Median :180.7   Mode  :character  
##  Mean   :30.78   Mean   :  84.07   Mean   :178.6                     
##  3rd Qu.:37.00   3rd Qu.:  49.50   3rd Qu.:180.7                     
##  Max.   :61.00   Max.   :1966.00   Max.   :500.0

Normalizar la base de datos

RH_EDAD_NORM<-scale(RHBAJAS2[1:2])

Se visualizan el # correcto de clusters a realizar

fviz_nbclust(RH_EDAD_NORM, kmeans, method="wss")+ 
  geom_vline(xintercept=4, linetype=2)+         
  labs(subtitle = "Elbow method")  

RHEDAD_Cluster1<-kmeans(RH_EDAD_NORM,4)
RHEDAD_Cluster1
## K-means clustering with 4 clusters of sizes 43, 107, 5, 80
## 
## Cluster means:
##         Edad   Días_trab
## 1  1.6031879 -0.11611923
## 2 -0.8512555 -0.17238996
## 3  1.2245019  5.86438920
## 4  0.2003094 -0.07353867
## 
## Clustering vector:
##   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20 
##   4   4   2   2   4   1   4   4   1   2   2   4   2   4   4   2   2   2   2   2 
##  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40 
##   4   3   2   4   1   2   4   2   2   2   4   2   2   2   4   2   2   4   4   2 
##  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60 
##   2   2   2   2   2   2   2   2   1   1   1   1   4   1   2   2   1   2   2   3 
##  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80 
##   2   2   4   2   2   1   2   2   4   2   2   2   4   2   4   2   4   2   2   1 
##  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  98  99 100 101 
##   3   2   2   4   1   2   1   2   2   2   4   1   1   2   2   4   1   4   2   4 
## 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 
##   2   2   1   4   2   2   4   3   4   4   2   4   4   2   4   4   4   1   1   1 
## 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 
##   2   2   2   2   2   4   2   4   1   2   4   2   1   2   4   2   4   1   4   1 
## 142 143 144 145 146 147 148 150 151 152 153 154 155 156 157 158 159 160 161 162 
##   4   4   1   1   1   2   4   4   4   2   2   2   4   1   1   2   4   2   4   1 
## 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 
##   1   1   1   4   1   2   2   4   2   2   1   4   1   2   1   4   4   1   4   4 
## 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 
##   2   2   2   4   1   3   4   2   2   4   4   4   4   4   4   4   4   2   4   4 
## 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 
##   4   4   2   4   1   4   2   2   2   1   2   2   2   4   4   2   2   4   4   4 
## 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 
##   2   2   4   2   2   2   4   1   4   1   2   2   2   2   2 
## 
## Within cluster sum of squares by cluster:
## [1] 19.40753 15.18543 18.67351 39.82387
##  (between_SS / total_SS =  80.1 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"

Visualizar el cluster

fviz_cluster(RHEDAD_Cluster1,data=RH_EDAD_NORM)

Análisis profundo del Cluster

RHBAJAS3 <- RHBAJAS2
RHBAJAS3$Clusters<-RHEDAD_Cluster1$cluster
RHBAJAS4<-RHBAJAS3 %>% group_by(Clusters) %>% summarise(Edad=max(Edad)) %>% arrange(desc(Edad))
RHBAJAS3$Cluster_Names<-factor(RHBAJAS3$Clusters,levels = c(1,2,3,4), 
                                 labels=c("Adulto", "Principiante", "Mayor", "Juvenil"))
RHBAJAS6 <- RHBAJAS3 %>% group_by(Cluster_Names) %>% dplyr:: summarize(edad_años=max(Edad), 
Días_trab=mean(Días_trab),
Count=n())
clusters<-as.data.frame(RHBAJAS6)
clusters
##   Cluster_Names edad_años  Días_trab Count
## 1        Adulto        57   57.62791    43
## 2  Principiante        27   44.81308   107
## 3         Mayor        61 1419.60000     5
## 4       Juvenil        39   67.32500    80

Análisis de datos del cluster expresados por gráficas

ggplot(RHBAJAS6,aes(x=reorder(Cluster_Names,Count),y=Count,fill=Cluster_Names)) +
  geom_bar(stat="identity")

Edades (máximas), al igual se puede realizar con un barplot

ggplot(RHBAJAS6, aes(x=Cluster_Names,y=edad_años,fill= Cluster_Names,label=round(edad_años,digits=2))) + 
  geom_col() + 
  geom_text()

Días laborados (Máximos)

ggplot(RHBAJAS6,aes(x=Cluster_Names,y=Días_trab,fill= Cluster_Names,label=round(Días_trab,digits=2))) + 
  geom_col() + 
  geom_text()

Gráfica de Boxplot (Análisis de las edades de los 4 grupos.)

ggplot(RHBAJAS3, aes(x=Cluster_Names, y=Edad, fill=Cluster_Names)) +
  geom_boxplot()+
  ggtitle("Edad (Dispersion)")

Hallazgos identificacos

Durante esta actividad realizamos un análisis en la base de datos de Recursos Humanos, enfocados en las variables de Edad, Salario y Días Trabajados, por lo que se decidió definir varios pasos a seguir para llegar al objetivo deseado que era finalmente llegar a la construcción de los clusters.

Tomando en cuenta los hallazgos de la edad y el salario diario, se llego a la conclusión de lo siguiente:

  1. Hay más bajas de adultos con el rango de edades de 41 a 61, el cuál se identifico como jubilación.

  2. Los adultos de 33-40 años ganan más con un sueldo diario de 186.16 en promedio.

De igual manera podemos observar cuatro Clusters que toman en cuenta la edad y los días laborados:

  1. El Cluster Rojo “Adulto” es un grupo en el cual se observa que son las personas de edad alta y con una característica en común que es que duran poco tiempo laborando en la empresa.
  2. El Cluster Azul “Mayor” es el Cluster que más se aparta de los demás Clusters debido a que son personas con mayor rango de edad y la mayor parte de los empleados cuentan con esta edad.
  3. El Cluster Morado “Juvenil” donde se encuentran las personas con un rango de edad de entre 30 y 36 años, habiendo más personas en el rango de los 30 a 32 años,
  4. El Cluster Verde “Principiante” es el grupo de personas más jóvenes en la empresa, con un rango de entre 20 y 30 años.

El grupo que cuenta con más días laborados es el de edad máxima, siendo los adultos, de igual manera estos cuentan con un salario mayor.
Por último podemos observar que en los gráficos que se analizan con estas variables tenemos los siguientes puntos a consideración:

  • Edad Máxima

  • Días Laborados Máximos

  • Recuento de los grupos que presentan mayor actividad en la empresa.

  • La dispersión de edad que existe entre cada uno de los grupos.

Sección 4

Identificación de resultados relevantes y sugerencias

Principales hallazgos

  1. RH: En cuanto al salario del IMSS en el género de los empleados y dependiendo de si son casados, divoricados, solteros o estan en unión libre. Se puede concluir que las mujeres tienen en promedio en estas cuatro categorías un salario mayor al de los hombres y los solteros tienen un mayor salario comparado con las otras categorias.

  2. Producción: Se puede ver que el cliente que más piezas programadas tiene es YANFENG dedicandosele un tiempo de calidad de 1.1 minuto, mientras que el cliente VL-017-1486 es el cliente que tiene casi la mitad de piezas programadas y es al que más tiempo se le dedica tiempo. Esto puede indicar que sus piezas pudieran ser de mucho márgen de error.

  3. Delivery Plan: Hella es el cliente con mayor cantidad de unidades y además de eso cuenta con algunos outliers muy por encima de la median, seguido por TRMX el cual no cuenta con outliers.

4.Merma: Podemos ver como en Agosto se tuvo un promedio de merma por día sobrepasando los 3000 kilos, siendo esta gráfica relevante para poder identificar factores importantes y reducir estas cantidades aplicando KPI’s

  1. Delivery Performance: Mahle es el cliente con mayor retraso sobre pasando los 60 minutos de retraso, mientras que Printel siempre se mantiene por debajo de los 30 minutos.

  2. Scrap: Se tiene mucho scrap en la empresa principalmente en la etapa de pre-producción, la mayor cantidad de scrap es generada en el área de SAB / Pre producción de la empresa, por lo que se tienen que tomar medidas para poder reducir estas cantidades lo máximo posible quizá usando el material de manera optima para evitar tanto Scrap.

Propuestas para FORM

  1. Mejorar los tiempos de set up, siendo estos ya cortos entre pausa y pausa puede ser más complicado bajar el porcentaje, pero de igual manera se puede hacer más efectivo el aprovecahamiento del tiempo por lo que se propone reducir un 15%-20% más el tiempo que hay entre este set up mediante el mantenimiento y cuidado de la maquinaria y compromiso y atención de los colaboradores.

2.Scrap: Aquí lo que se propone es medier exactamente la cantidad que se requiere de material para poder evitar tener esos desperdicios. Analizando estas variables se confirma que en el área de pre-producción es donde se genera la mayor parte del scrap en su mayoría que es casi el 85% de scrap que se genera dentro de la empresa.

  1. Implementar KPI’s específicos con los colaboradores que se encargan de la producción con una medida de tiempo mes con mes donde se reduzca la merma producida y esta baje en un 15% a 20% ala termino del primer mes de establecer los KPI´s. También se sugiere mantener el nivel de calidad siempre en ese estándar de excelencia para no tener productos regresados, contratiempos con esas entregas o que se retrasen otras por culpa de tener que producir o arreglar cierto empaque.

Responder a las siguientes preguntas

Describir con tus propias palabras los términos Business Analytics y Business Intelligence. Así también, identificar y describir 3 principales diferencias entre Business Analytics y Business Intelligence.

  1. Business Analytics: Es una combinación de habilidades, tecnologías y prácticas que se utilizan para examinar los datos y el rendimiento de una organización. Es una forma de obtener información y tomar decisiones basadas en datos en el futuro utilizando el análisis estadístico, se puede traducir como análisis empresarial y este se enfoca en datos históricos y actuales. Su objetivo es identificar patrones o problemas, identificar los posibles riesgos y tomar acciones para disminuirlos.

  2. Business Inteligence: Se enfoca principalmente en lo que es la toma de decisiones utilizando los datos recabados en el proceso de business analytics, también es el conjunto de herramientas que permiten que los datos se transformen en informacón y que esta pase a ser conocimiento. Se usa para evaluar, optimizar y coordinar las operaciones internas de una empresa.

Diferencias:

  1. Eventos actuales frente a posibilidades futuras: Con esto nos referimos al enfoque en el momento en que ocurren estos eventos.

  2. La form a en la que se utilizan, por ejemplo BI es una analítica descriptiva ya que esta diseñado para decirle lo que ha sucedido, mientras que por otra parte BA es un tipo de analítica predictiva ya que identifica tendencias en los datos.

  3. Las herramientas que presenta BI son más utilizadas por especialistas en marketing, contabilidad, y su visualización es más digerible, o facil de entender mientras que en las herramientas de BA se becesita más trabajo para analizar la información e interpretarla y quienes la usan son más analístas

Describir con tus propias palabras el concepto de Indicador Clave de Rendimiento / Key Performance Indicators (KPI).

Key Performance Indicators (KPI): Los indicadores de desempeño o medidor de desempeño se refiere a una serie de métricas que se utilizan para sintetizar la información. El objetivo final de un KPI es ayudar tomar mejores decisiones respecto al estado actual de un proceso, proyecto o estrategia.

Los KPI son utilizados por diversas ventajas:

  1. Permiten obtener información valiosa y útil.

  2. Medir determinadas variables y resultados a partir de dicha información.

  3. Analizar la información y efectos de unas determinadas estrategias (así como las tareas que se utilizaron para llevar a cabo las mismas).

  4. Comparar la información y determinar las estrategias y tareas efectivas.

  5. Tomar las decisiones oportunas.

A partir del análisis de las bases de datos de las diferentes áreas de la empresa FORM, proponer y describir 3 posibles KPIs que permitan evaluar el desempeño de algunas de sus áreas.

  1. Reducir la merma producida y que esta baje en un 15% a 20% al termino del primer mes de establecer el KPI.

  2. Rotación de nnventario para conocer la efectividad de los recursos con los que cuenta la empresa y que FORM pueda crear asegurar que sus gastos le darán un retorno de inversión lo más pronto posible. Esto ayudara a que la empresa también pueda tener más libre el almacen.

  3. Número de unidades producidas al mes, ya que estás podran ayudar a medir la productividad de FORM y tener más control dentro de sus operaciones.

Referencias

Colaboración (no date) KPI’s ¿Qué son, para qué sirven y por qué y cómo utilizarlos?, Tips de Logicalis. Available at: https://blog.es.logicalis.com/analytics/kpis-qu%C3%A9-son-para-qu%C3%A9-sirven-y-por-qu%C3%A9-y-c%C3%B3mo-utilizarlos (Accessed: October 21, 2022).

Biblioteca - Tec de Monterrey: Biblioteca Tec - Escuela de Negocios: Inicio (no date) Tecnológico de Monterrey. Available at: https://biblioteca.tec.mx/edn (Accessed: October 21, 2022).

LS0tCnRpdGxlOiAiRXRhcGEgMiBFdmlkZW5jaWEiCmF1dGhvcjogIkpvc8OpIFJhbcOzbiBWw6F6cXVleiBHdXptw6FuIEEwMTYyNTIwMyIKZGF0ZTogIjIxIGRlIE9jdHVicmUgMjAyMiIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRoZW1lOiByZWFkYWJsZQogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KCjxpbWcgc3JjPSAiL1VzZXJzL2pvc2VyYW1vbnZhenF1ZXpndXptYW4vRGVza3RvcC9DYXB0dXJhIGRlIFBhbnRhbGxhIDIwMjItMTAtMjEgYSBsYShzKSAyLjA4LjA5LnBuZyI+CgpDYXJnYXIgbGlicmVyaWFzIAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmxpYnJhcnkoZm9yZWlnbikKbGlicmFyeShkcGx5cikgICAgICAgICMgZGF0YSBtYW5pcHVsYXRpb24gCmxpYnJhcnkoZm9yY2F0cykgICAgICAjIHRvIHdvcmsgd2l0aCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMKbGlicmFyeShnZ3Bsb3QyKSAgICAgICMgZGF0YSB2aXN1YWxpemF0aW9uIApsaWJyYXJ5KGphbml0b3IpICAgICAgIyBkYXRhIGV4cGxvcmF0aW9uIGFuZCBjbGVhbmluZyAKbGlicmFyeShIbWlzYykgICAgICAgICMgc2V2ZXJhbCB1c2VmdWwgZnVuY3Rpb25zIGZvciBkYXRhIGFuYWx5c2lzIApsaWJyYXJ5KHBzeWNoKSAgICAgICAgIyBmdW5jdGlvbnMgZm9yIG11bHRpdmFyaWF0ZSBhbmFseXNpcyAKbGlicmFyeShuYW5pYXIpICAgICAgICMgc3VtbWFyaWVzIGFuZCB2aXN1YWxpemF0aW9uIG9mIG1pc3NpbmcgdmFsdWVzIE5BcwpsaWJyYXJ5KGRsb29rcikgICAgICAgIyBzdW1tYXJpZXMgYW5kIHZpc3VhbGl6YXRpb24gb2YgbWlzc2luZyB2YWx1ZXMgTkFzCmxpYnJhcnkoY29ycnBsb3QpICAgICAjIGNvcnJlbGF0aW9uIHBsb3RzCmxpYnJhcnkoanRvb2xzKSAgICAgICAjIHByZXNlbnRhdGlvbiBvZiByZWdyZXNzaW9uIGFuYWx5c2lzIApsaWJyYXJ5KGxtdGVzdCkgICAgICAgIyBkaWFnbm9zdGljIGNoZWNrcyAtIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzIApsaWJyYXJ5KGNhcikgICAgICAgICAgIyBkaWFnbm9zdGljIGNoZWNrcyAtIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzCmxpYnJhcnkob2xzcnIpICAgICAgICAjIGRpYWdub3N0aWMgY2hlY2tzIC0gbGluZWFyIHJlZ3Jlc3Npb24gYW5hbHlzaXMgCmxpYnJhcnkoa2FibGVFeHRyYSkgICAjIEhUTUwgdGFibGUgYXR0cmlidXRlcwpsaWJyYXJ5KGZhY3RvZXh0cmEpICAgIyBwcm92aWRlcyBmdW5jdGlvbnMgdG8gZXh0cmFjdCBhbmQgdmlzdWFsaXplIHRoZSBvdXRwdXQgb2YgZXhwbG9yYXRvcnkgbXVsdGl2YXJpYXRlIGRhdGEgYW5hbHlzZXMKIyMjIEluc3RhbGFyIGxpYnJlcmlhcyBuZWNlc2FyaWFzCiMgaW5zdGFsbC5wYWNrYWdlcygidGliYmxlIikKbGlicmFyeSh0aWJibGUpCiMgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dmb3J0aWZ5KSAgICAjIGRhdGEgdmlzdWFsaXphdGlvbiB0b29scyBmb3Igc3RhdGlzdGljYWwgYW5hbHlzaXMgCmxpYnJhcnkocGx5cikKbGlicmFyeShiYXNlKQoKYGBgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IG9yYW5nZSIgPiBSSCBDb2xhYm9yYWRvcmVzL0JhamFzIDwvc3Bhbj4gCgojIyMgTGltcGllemEgZGUgRGF0b3MKCkxhcyBiYXNlcyBkZSBkYXRvcyBmdWVyb24gZGl2aWRpZGFzIGVuIGRvcyB5YSBxdWUgZW4gdW5hIHNlIHRvbWFuIGVuIGN1ZW50YSBhIGxvcyBjb2xhYm9yYWRvcmVzIGRlIGxhIGVtcHJlc2EgeSBlbiBvdHJhIGxhcyBiYWphcyBxdWUgc2UgdHV2aWVyb24gcG9yIGRpc3RpbnRhcyByYXpvbmVzLCBlc3RvIGNvbiBsYSBpbnRlbmNpw7NuIGRlIHBvZGVyIG9idGVuZXIgbWVqb3JlcyByZXN1bHRhZG9zIGUgaW50ZXJwcmV0YWNpb25lcyBtw6FzIGNsYXJhcy4KCiMjIyBJbXBvcnRhciBsYSAgYmFzZSBkZSBkYXRvcyBSSCBkZSBsYSBlbXByZXNhIEZPUk0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI2ZpbGUuY2hvb3NlKCkKUmhDb2xhYjwtcmVhZC5jc3YoIi9Vc2Vycy9qb3NlcmFtb252YXpxdWV6Z3V6bWFuL0RvY3VtZW50cy9UZWNub2xvzIFnaWNvIGRlIE1vbnRlcnJleS9TZXB0aW1vIHNlbWVzdHJlL0FuYWxpzIF0aWNhIGRlIGRhdG9zIC9SRVRPL0Jhc2VzIGRlIGRhdG9zIChsaW1waWFzKSBDU1YgL0Jhc2VEYXRvc0wgUkhfQ29sYWJvcmFkb3Jlcy5jc3YiKQpSaEJhamFzPC1yZWFkLmNzdigiL1VzZXJzL2pvc2VyYW1vbnZhenF1ZXpndXptYW4vRG9jdW1lbnRzL1RlY25vbG/MgWdpY28gZGUgTW9udGVycmV5L1NlcHRpbW8gc2VtZXN0cmUvQW5hbGnMgXRpY2EgZGUgZGF0b3MgL1JFVE8vQmFzZXMgZGUgZGF0b3MgKGxpbXBpYXMpIENTViAvQmFzZURfTGltcGlhIFJIXyBCYWphcyAuY3N2IikKCmBgYAoKIyMjIFZlcmlmaXF1ZW1vcyBsYSBlc3RydWN0dXJhIGRlIGxhIGJhc2UgZGUgZGF0b3MgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKc3RyKFJoQ29sYWIpCnN0cihSaEJhamFzKQoKYGBgCgoKIyMjICBUaXBvcyBkZSBWYXJpYWJsZXMgCgpgYGB7cn0KVmFyaWFibGU8LWMoIk5vbWJyZSIsIkVkYWQiLCAiR2VuZXJvIiwgIkZlY2hhIGRlIGFsdGEiLCAiTW90aXZvIGRlIGJhamEiLCAiRMOtYXMgZGUgdHJiYWpvIiwiQmFqYSIsICJQdWVzdG8gcXVlIGRlc2VtcGXDsWEiLCAiU2FsYXJpbyBJTVNTIiwgIkNvbG9uaWEiLCAiTXVuaWNpcGlvIiwgIkVzdGFkbyIsICJFc3RhZG8gQ2l2aWwiLCAiTsO6bWVybyBkZSBlbXBsZWFkbyIsICJOb21icmUgY29tcGxldG8gIiwgIkFudGlndWVkYWQiLCAiRGVwYXJ0YW1lbnRvIiwgIk1hbm8gZGUgb2JyYSIsIlNhbGFyaW8gZGlhcmlvIikKClR5cGU8LWMoInF1YWxpdGF0aXZlIChub21pbmFsKSIsICJxdWFudGl0YXRpdmUgKGRpc2NyZXRlKSIsICJxdWFsaXRhdGl2ZSAobm9taW5hbCkiLCJxdWFsaWl0YXRpdmUgKG9yZGluYWwpIiwicXVhbGl0YXRpdmUgKG5vbWluYWwpIiwicXVhbGl0YXRpdmUgKG5vbWluYWwpIiwicXVhbnRpdGF0aXZlIChjb250b251YSkiLCJxdWFsaXRhdGl2ZSAobm9taW5hbCkiLCJxdWFsaXRhdGl2ZSAobm9taW5hbCkiLCJxdWFsaXRhdGl2ZSAobm9taW5hbCkiLCJxdWFsaXRhdGl2ZSAobm9taW5hbCkiLCJxdWFudGl0YXRpdmUgKGRpc2NyZXRlKSIsInF1YWxpdGF0aXZlIChub21pbmFsKSIsInF1YWxpdGF0aXZlIChub21pbmFsKSIsInF1YWxpdGF0aXZlIChkaXNjcmV0ZSkiLCJxdWFsaXRhdGl2ZSAobm9taW5hbCkiLCJxdWFudGl0YXRpdmUgKGNvbnRpbnVhKSIsInF1YW50aXRhdGl2ZSAoY29udGludWEpIiwicXVhbnRpdGF0aXZlIChjb250aW51YSkiKQoKdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSkKa25pdHI6OmthYmxlKHRhYmxlKQpgYGAKCgoKQ29udGFtb3MgY29uIDEzIHZhcmlhYmxlcyB5IDk5OSBvYnNlcnZhY2lvbmVzIGVuIHRvdGFsCgojIyMgU2VsZWNjaW9uYXIgY29sdW1uYXMgLyB2YXJpYWJsZXMgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpSaENvbGFiMTwtUmhDb2xhYiAKUmhCYWphczE8LVJoQmFqYXMgCmBgYAoKIyMjIExpbXBpZXphIGRlIGRhdG9zIAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KUmhDb2xhYjE8LVJoQ29sYWIgJT4lIHNlbGVjdCgtb25lX29mKCdudW1lcm9fZGVfZW1wbGVhZG8nLCAnQkFKQScsICdlZGFkJykpCmBgYAoKIyMjICBSZW5vbWJyYW1vcyBsYXMgY29sdW1uYXMgLyB2YXJpYWJsZXMgc2VsZWNjaW9uYWRhcwoKU2UgcmVub21icmFyb24gbGFzIGNvbHVtbmFzIHkgdmFyaWFibGVzIHNlbGVjY2lvbmFkYXMgcGFyYSBwb2RlciB0ZW5lciBjb25jZXB0b3MgbcOhcyBjb3J0b3MgcGFyYSBhIGxhIGhvcmEgZGUgdmlzdWFsaXphciB0ZW5lciB1bmEgbWVqb3IgeSBtw6FzIGNsYXJhIGludGVycHJldGFjacOzbiBkZSBsYSBpbmZvcm1hY2nDs24uIAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCnN1bW1hcnkoUmhDb2xhYjEpCm5hbWVzKFJoQ29sYWIxKTwtYygnTm9tX0NvbXAnLCAnR2VuJywgJ0ZlY2hhX2FsdGEnLCAnQW50JywgJ1B1ZXN0bycsICdEZXAnLCAnTURPJywgJ1NhbF9EaWFyaW8nLCAnQ29sJywgJ011bicpCm5hbWVzKFJoQmFqYXMxKTwtYygnTm9tJywgJ0VkYWQnLCAnR2VuJywgJ0ZlY2hhX2FsdGEnLCAnTUInLCAnRMOtYXNfdHJhYicsICdCYWphJywgJ1B1ZXN0RGVzJywgJ1NhbF9JTVNTJywgJ0NvbCcsICdNdW4nLCAnRXN0YWRvJywgJ0VzdENpdicpCmBgYAoKIyMjICBDb252ZXJ0aW1vcyAiZmVjaGFfbmFjaW1pZW50byIgIGEgZm9ybWF0byBkZSBmZWNoYSAKClNlIGNvbnZpcnRpw7MgYSBmb3JtYXRvIGRlIGZlY2hhIGxhIHZhcmlhYmxlIGRlIGZlY2hhX25hY2ltaWVudG8gcGFyYSBzdSBjb3JyZWN0YSBpbnRlcnByZXRhY2nDs24gZGVudHJvIGRlIGxvcyBjw7NkaWdvcy4gCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpSaENvbGFiMSRGZWNoYV9hbHRhPC1hcy5EYXRlKFJoQ29sYWIkZmVjaGFfZGVfYWx0YSxmb3JtYXQ9IiVkLyVtLyVZIikKUmhCYWphczEkRmVjaGFfYWx0YTwtYXMuRGF0ZShSaEJhamFzMSRGZWNoYV9hbHRhLGZvcm1hdD0iJWQvJW0vJVkiKQpSaEJhamFzMSRCYWphPC1hcy5EYXRlKFJoQmFqYXMxJEJhamEsZm9ybWF0PSIlZC8lbS8lWSIpIApgYGAKCiMjIyAgRWxpbWluYXIgTkEncyB5IHN1c3RpdHVpciBjb24gMCdzCgpFc3RvIHBhcmEgZXZpdGFyIGVycm9yZXMgYSBsYSBob3JhIGRlIHV0aWxpemFyIGxhIGJhc2UgcGFyYSBnZW5lcmFyIHVuIGFuw6FsaXNpcyBtw6FzIGNlcnRlcm8uCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKc3VtKGlzLm5hKFJoQ29sYWIxKSkKc3VtKGlzLm5hKFJoQmFqYXMxKSkKCgpSaEJhamFzMVtpcy5uYShSaEJhamFzMSldPC0wCgoKc3VtbWFyeShSaENvbGFiMSkKc3VtbWFyeShSaEJhamFzMSkKClJoQ29sYWIxIDwtIG5hLm9taXQoUmhDb2xhYjEpClJoQmFqYXMxIDwtIG5hLm9taXQoUmhCYWphczEpCgoKc3VtbWFyeShSaENvbGFiMSkKc3VtbWFyeShSaEJhamFzMSkgIAoKc3RyKFJoQ29sYWIxKQpzdHIoUmhCYWphczEpCmBgYAoKIyMjICBDYWxjdWxlbW9zIGxhIHZhcmlhYmxlICJhZ2UiIGVuIGHDsW9zCgpFc3RvIHBhcmEgcG9kZXIgcmVhbGl6YXIgY2FyYWN0ZXJpc2l0Y2FzIGFkaWNpb25hbGVzIGRlICJjb2xhYnJhZG9yZXMiLgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmxpYnJhcnkobHVicmlkYXRlKQoKCmVkYWQ8LXRydW5jKChSaENvbGFiMSRGZWNoYV9hbHRhICUtLSUgUmhDb2xhYjEkRmVjaGFfYWx0YSkgLyB5ZWFycygxKSkgIyAlLS0lIGNyZWF0ZXMgYSB0aW1lIGludGVydmFsIGJhc2VkIG9uIGFzLmRhdGUoKSBmb3JtYXQKUmhDb2xhYjEkZWRhZDwtZWRhZAoKZWRhZDwtdHJ1bmMoKFJoQmFqYXMxJEZlY2hhX2FsdGEgJS0tJSBSaEJhamFzMSRGZWNoYV9hbHRhKSAvIHllYXJzKDEpKQplZGFkPC10cnVuYygoUmhCYWphczEkQmFqYSAlLS0lIFJoQmFqYXMxJEJhamEpIC8geWVhcnMoMSkpCgpgYGAKCiMjIyAgQ29udmVydGlyIGEgY2FyYWN0ZXIgdmFyaWFibGVzIGEgZmFjdG9yIAoKRXN0byBwYXJhIHBvZGVyICBjcmVhciBlc3RhZGlzdGljb3MgZGVzY3JpcHRpdm9zCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyMjICBDb2xhYjEKUmhDb2xhYjEkR2VuPC1hcy5mYWN0b3IoUmhDb2xhYjEkR2VuKQpSaENvbGFiMSRQdWVzdG88LWFzLmZhY3RvcihSaENvbGFiMSRQdWVzdG8pClJoQ29sYWIxJERlcDwtYXMuZmFjdG9yKFJoQ29sYWIxJERlcCkKUmhDb2xhYjEkTXVuPC1hcy5mYWN0b3IoUmhDb2xhYjEkTXVuKQpSaENvbGFiMSRDb2w8LWFzLmZhY3RvcihSaENvbGFiMSRDb2wpCgoKIyMjICBCYWphczEgCgpSaEJhamFzMSRHZW48LWFzLmZhY3RvcihSaEJhamFzMSRHZW4pClJoQmFqYXMxJE1CPC1hcy5mYWN0b3IoUmhCYWphczEkTUIpClJoQmFqYXMxJETDrWFzX3RyYWI8LWFzLmZhY3RvcihSaEJhamFzMSREw61hc190cmFiKQpSaEJhamFzMSRQdWVzdERlczwtYXMuZmFjdG9yKFJoQmFqYXMxJFB1ZXN0RGVzKQpSaEJhamFzMSRDb2w8LWFzLmZhY3RvcihSaEJhamFzMSRDb2wpClJoQmFqYXMxJE11bjwtYXMuZmFjdG9yKFJoQmFqYXMxJE11bikKUmhCYWphczEkRXN0YWRvPC1hcy5mYWN0b3IoUmhCYWphczEkRXN0YWRvKQpSaEJhamFzMSRFc3RDaXY8LWFzLmZhY3RvcihSaEJhamFzMSRFc3RDaXYpCgpgYGAKCiMjIyAgVmVyaWZpY2Ftb3MgbGEgZXN0cnVjdHVyYSBkZSBSaENvbGFiMSB5ICBSaEJhamFzMSAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnN0cihSaENvbGFiMSkKc3VtbWFyeShSaENvbGFiMSkKCnN0cihSaEJhamFzMSkKc3VtbWFyeShSaEJhamFzMSkKYGBgCgojIyMgVmlzdWFsaXphc2nDs24gZGUgRGF0b3MgCgpNb3N0cmFyIGdyYWZpY29zIGRlIHZpc3VhbGl6YWNpw7NuIHBhcmEgaWRlbnRpZmljYXIgaGFsbGF6Z29zIHJlbGV2YW50ZXMgZGUgbnVlc3RyYXMgYmFzZXMgZGUgZGF0b3MgUmhDb2xhYjEgeSBSaEJhamFzMSAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMjIENvbGFib3JhZG9yZXMKCnRhcHBseShSaENvbGFiMSRTYWxfRGlhcmlvLAogICAgICAgbGlzdChSaENvbGFiMSRHZW4sUmhDb2xhYjEkUHVlc3RvKSwgbWVhbikKCnRhcHBseShSaENvbGFiMSRTYWxfRGlhcmlvLAogICAgICAgbGlzdChSaENvbGFiMSRHZW4sUmhDb2xhYjEkRGVwKSwgbWVhbikKCiMjIEJhamFzCgp0YXBwbHkoUmhCYWphczEkU2FsX0lNU1MsUmhCYWphczEkR2VuLG1lYW4pCmBgYAoKIyMjICBSZXViaWNhbW9zIGVsICJvdXRsaWVyIiBkZSBzYWxhcmlvX2RpYXJpbyBjb24gbGEgbWVkaWFuYQoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KUmhDb2xhYjEkU2FsX0RpYXJpbzwtcmVwbGFjZShSaENvbGFiMSRTYWxfRGlhcmlvLFJoQ29sYWIxJFNhbF9EaWFyaW8+MTAwMDAwMCwxODEpCmBgYAoKTW9zdHJhbW9zIGxhIHZpc3VhbGl6YWNpw7NuIGdyYWZpY2EgZGUgZGF0b3MgcGFyYSBwb2RlciBpZGVudGlmaWNhciBoYWxsYXpnb3MgaW1wb3J0YW50ZXMgZGUgIHJoX2FsdCBiYXNlIGRlIGRhdG9zLiAKCmBgYHtyfQp0YXBwbHkoUmhDb2xhYjEkU2FsX0RpYXJpbywKICAgICAgIGxpc3QoUmhDb2xhYjEkR2VuLFJoQ29sYWIxJERlcCksIG1lYW4pCmBgYAoKYGBge3J9Cmhpc3QoUmhCYWphczEkRWRhZCwgZnJlcT1UUlVFLCBjb2w9J29yYW5nZScsIG1haW49Ikhpc3RvZ3JhbWEgZGUgRWRhZCIseGxhYj0iRWRhZCBlbiBBw7FvcyIpCmBgYAoKUG9kZW1vcyBvYnNlcnZhciBxdWUgaGF5IHVuYSBtYXlvciBjYW50aWRhZCBkZSBlbXBsZWFkb3MgZW4gZWwgcmFuZ28gZGUgZWRhZCBkZSAyMCBhIDI1IGHDsW9zLCBkZXNwdcOpcyBsZSBzaWd1ZSBlbCByYW5nbyBkZSAyNSBhIDMwIHkgZGUgMzAgYSAzNSwgc2llbmRvIGxhIG1heW9yIHBhcnRlIGRlIGxvcyBlbXBsZWFkb3MgasOzdmVuZXMsIHBlcm8gaGFiaWVuZG8gZW1wbGVhZG9zIHF1ZSBzb2JyZSBwYXNhbiBpbmNsdXNvIGxhIGVkYWQgZGUgNjAgYcOxb3MuIAoKYGBge3J9CmdncGxvdChSaEJhamFzMSwgYWVzKHg9R2VuLCB5PUVkYWQsIGZpbGw9R2VuKSkgKyAKICBnZW9tX2JveHBsb3QoKSAKYGBgCgpMYSBtYXlvciBwYXJ0ZSBkZSBlbXBsZWFkb3MgYWdsb21lcmFkYSBlbiBlbCByYW5nbyBkZSAyMCBhIDQwIGHDsW9zIHkgb2JzZXJ2YW1vcyBjb21vIGhheSB1bm9zIHBvY29zIGZ1ZXJhIGRlIHJhbmdvIGVuIGVkYWRlcyBxdWUgcGFzYW4gZGUgNTAgYSA2MCBhw7FvcyxzaWVuZG8gZXN0b3MgcG9jb3MgY2Fzb3MuIAoKYGBge3J9CmdncGxvdChSaENvbGFiMSwgYWVzKHg9R2VuLCB5PVNhbF9EaWFyaW8sIGZpbGw9R2VuKSkgKyAKICBnZW9tX2JveHBsb3QoKSAKCmBgYAoKQXF1w60gZW4gZWwgc2FsYXJpbyBkaWFyaW8gc2UgZGVzdGFjYSBsYSBvYnNlcnZhY2nDs24gZGUgcXVlIGxhIG1heW9yIHBhcnRlIGRlIGxvcyBlbXBsZWFkb3MgdGllbmVuIHVuIHNhbGFyaW8gcXVlIHJvbmRhIGVudHJlIGxvcyAxNzAgcGVzb3M7IGhhYmllbmRvIGNhc29zIG11eSBlc3Blc2lmaWNvcyBxdWUgZXN0YW4gZW4gcmFuZ29zIG11Y2hvIG1lbm9yZXMgbyBsbGVnYW5kbyBhIGxvcyAzMDAgcGVzb3MsIHBlcm8gaGFiaWVuZG8gdW4gc2FsYXJpbyBxdWUgbGxlZ2EgYSBsb3MgNDUwIHBlc29zIHNpZW5kbyBlbCBzYWxhcmlvIG3DoXMgZWxldmFkbyBkZSB0b2RhIGxhIGJhc2UgZGUgZGF0b3MuIAoKYGBge3J9CmdncGxvdChSaENvbGFiMSwgYWVzKEdlbixTYWxfRGlhcmlvLGZpbGw9R2VuKSkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikgKyBnZ3RpdGxlKCJTYWxhcmlvIERpYXJpbyBwb3IgR2VuZXJvIikKYGBgCkVuIGxhIGdyw6FmaWNhIGFudGVyaW9yIHBvZGVtb3Mgb2JzZXJ2YXIgbGEgY29ycmVsYWNpw7NuIGVudHJlIGVsIGfDqW5lcm8geSBlbCBzYWxhcmlvIGRpYXJpbyBkZSBsb3MgZW1wbGVhZG9zOyBwb2RlbW9zIGNvbmNsdWlyIHF1ZSBlbCBnw6luZXJvIGZlbWVuaW5vIHRpZW5lIHVuIHNhbGFyaW8gdG90YWwgZW4gcHJvbWVkaW8gbcOhcyBhbHRvIGVsIGfDqW5lcm8gbWFzY3VsaW5vLgoKYGBge3J9CmdncGxvdChSaEJhamFzMSwgYWVzKHg9R2VuLCB5PVNhbF9JTVNTLCBmaWxsPUdlbikpICsgCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArIAogIGZhY2V0X2dyaWQofkVzdENpdikgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDEiKQpgYGAKCkFxdcOtIHBvZGVtb3Mgb2JzZXJ2YXIgZWwgc2FsYXJpbyBkZWwgSU1TUyBlbiBjdWFudG8gYWwgZ8OpbmVybyBkZSBsb3MgZW1wbGVhZG9zIHkgZGVwZW5kaWVuZG8gZGUgc2kgc29uIGNhc2Fkb3MsIGRpdm9yaWNhZG9zLCBzb2x0ZXJvcyBvIGVzdGFuIGVuIHVuacOzbiBsaWJyZS4gU2UgcHVlZGUgY29uY2x1aXIgcXVlIGxhcyBtdWplcmVzIHRpZW5lbiBlbiBwcm9tZWRpbyBlbiBlc3RhcyBjdWF0cm8gY2F0ZWdvcsOtYXMgdW4gc2FsYXJpbyBtYXlvciBhbCBkZSBsb3MgaG9tYnJlcyB5IGxvcyBzb2x0ZXJvcyB0aWVuZW4gdW4gbWF5b3Igc2FsYXJpbyBjb21wYXJhZG8gY29uIGxhcyBvdHJhcyBjYXRlZ29yaWFzLiAKCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IG9yYW5nZSIgPiBQcm9kdWNjacOzbiA8L3NwYW4+IAoKIyMjICBMaW1waWV6YSBkZSBEYXRvcwoKU2UgY29tZW56w7MgcmVhbGl6YW5kbyB1bmEgbGltcGllemEgZW4gZXhjZWwsIHBhcmEgZGVzcHXDqXMgZW1wZXphciBhIGxpbXBpYXIgZGVudHJvIGRlIFIgZGVqYW5kbyBmaW5hbG1lbnRlIGxvcyB2YWxvcmVzIG3DoXMgcmVsZXZhbnRlcy4gCgojIyMgIEltcG9ydGFyIGxhICBiYXNlIGRlIGRhdG9zIHByb2R1Y2Npw7NuIGRlIGxhIGVtcHJlc2EgRk9STQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcHJvZHVjY2lvbnRvdGFsIDwtIHJlYWQuY3N2KCIvVXNlcnMvam9zZXJhbW9udmF6cXVlemd1em1hbi9Eb2N1bWVudHMvVGVjbm9sb8yBZ2ljbyBkZSBNb250ZXJyZXkvU2VwdGltbyBzZW1lc3RyZS9BbmFsacyBdGljYSBkZSBkYXRvcyAvUkVUTy9CYXNlcyBkZSBkYXRvcyBmaW5hbGVzL1BST0RVQ0NJT8yBTi9CRCBQcm9kdWNjaW/MgW4gY3N2ICgxKS5jc3YiKQpgYGAKCiMjIyAgRW50ZW5kZXIgbGEgYmFzZSBkZSBkYXRvcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzdHIocHJvZHVjY2lvbnRvdGFsKQpgYGAKCiMjIyAgVGlwb3MgZGUgVmFyaWFibGVzIApgYGB7cn0KVmFyaWFibGU8LWMoIkZlY2hhIiwgIk7Dum1lcm8iLCAiQ2xpZW50ZSIsIklkIEZvcm0iLCAiUHJvZHVjdG8iLCAiUGllemFzIHByb2dyYW1hZGFzIiwgIlRpZW1wbyBlbiBtaW51dG9zIiwgIkhvcmEgZmluICIsICJFc3RhY2nDs24gZGUgYXJyYW5xdWUiLCAiTGFtaW5hcyBwcm9jZXNhZGFzIiwgIkluaWNpbyBTZXQgVXAiLCAiRmluIFNldCB1cCIsICJJbmljaW8gcG9yY2VzbyIsICJGaW4gcHJvY2VzbyIsICIgIFRpZW1wbyBjYWxpZGFkIikKClR5cGU8LWMoInF1YWxpdGF0aXZlIChub21pbmFsKSIsICJxdWFudGl0YXRpdmUgKGRpc2NyZXRlKSIsICJxdWFsaXRhdGl2ZSAobm9taW5hbCkiLCJxdWFsaWl0YXRpdmUgKG9yZGluYWwpIiwicXVhbGl0YXRpdmUgKG5vbWluYWwpIiwicXVhbnRpdGF0aXZlIChkaXNjcmV0ZSkiLCJxdWFudGl0YXRpdmUgKGNvbnRvbnVhKSIsInF1YW50aXRhdGl2ZSAoY29udG9udWEpIiwicXVhbGl0YXRpdmUgKG5vbWluYWwpIiwicXVhbnRpdGF0aXZlIChkaXMgcmV0ZSkiLCJxdWFudGl0YXRpdmUgKGNvbnRvbnVhKSIsInF1YW50aXRhdGl2ZSAoQ29udGludWEpIiwicXVhbnRpdGF0aXZlIChjb250b251YSkiLCJxdWFudGl0YXRpdmUgKGNvbnRvbnVhKSIsInF1YW50aXRhdGl2ZSAoZGlzY3JldGUpIikKCnRhYmxlPC1kYXRhLmZyYW1lKFZhcmlhYmxlLFR5cGUpCmtuaXRyOjprYWJsZSh0YWJsZSkKYGBgCgojIyMgIEVsaW1pbmFyIGNvbHVtbmFzIGlycmVsZXZhbnRlcyBwYXJhIGVsIGFuw6FsaXNpcwpTZSBlbGltaW5hcm9uIGxhcyBjb2x1bW5hcyBxdWUgbm8gZ2VuZXJhYmFuIHZhbG9yIGFsIGFuw6FsaXNpcy4gCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwcm9kdWNjaW9udG90YWwgPC0gc3Vic2V0IChwcm9kdWNjaW9udG90YWwsc2VsZWN0ID0gLWMoIE5vLiwgSUQuRk9STSAsICBIUi4uRklOICwgRVNUQUNJT04uQVJSQU5RVUUgLCBJTklDSU8uU0VQLlVQICxGSU4uSU5JQ0lPLkRFLlNFUC5VUCAsIElOSUNJTy5kZS5QUk9DRVNPICwgVElFTVBPLk1BVEVSSUFMRVMgLCBNRVJNQVMuTWFxdWluYXMuICkpCgoKc3VtbWFyeSAocHJvZHVjY2lvbnRvdGFsKQpgYGAKCiMjIyAgQ2FtYmlhciBhIGVudGVybyBsYXMgdmFyaWFibGVzIGN1YW50aXRhdGl2YXMgCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnByb2R1Y2Npb250b3RhbCRQSUVaQVMuUFJPRy4gPC0gc3Vic3RyKHByb2R1Y2Npb250b3RhbCRQSUVaQVMuUFJPRy4sIHN0YXJ0ID0gMSwgc3RvcCA9IDIpCnRpYmJsZSAocHJvZHVjY2lvbnRvdGFsKQpwcm9kdWNjaW9udG90YWwkUElFWkFTLlBST0cuIDwtIGFzLmludGVnZXIocHJvZHVjY2lvbnRvdGFsJFBJRVpBUy5QUk9HLikKc3RyKHByb2R1Y2Npb250b3RhbCkgICAgCgpwcm9kdWNjaW9udG90YWwkVE1PLi5NSU4uIDwtIHN1YnN0cihwcm9kdWNjaW9udG90YWwkVE1PLi5NSU4uLCBzdGFydCA9IDEsIHN0b3AgPSAyKQp0aWJibGUgKHByb2R1Y2Npb250b3RhbCkKcHJvZHVjY2lvbnRvdGFsJFRNTy4uTUlOLiA8LSBhcy5pbnRlZ2VyKHByb2R1Y2Npb250b3RhbCRUTU8uLk1JTi4pCnN0cihwcm9kdWNjaW9udG90YWwpICAKCnByb2R1Y2Npb250b3RhbCRMYW1pbmFzLnByb2Nlc2FkYXMgPC0gc3Vic3RyKHByb2R1Y2Npb250b3RhbCRMYW1pbmFzLnByb2Nlc2FkYXMsIHN0YXJ0ID0gMSwgc3RvcCA9IDIpCnRpYmJsZSAocHJvZHVjY2lvbnRvdGFsKQpwcm9kdWNjaW9udG90YWwkTGFtaW5hcy5wcm9jZXNhZGFzIDwtIGFzLmludGVnZXIocHJvZHVjY2lvbnRvdGFsJExhbWluYXMucHJvY2VzYWRhcykKc3RyKHByb2R1Y2Npb250b3RhbCkgCgpwcm9kdWNjaW9udG90YWwkVElFTVBPLkNBTElEQUQgPC0gc3Vic3RyKHByb2R1Y2Npb250b3RhbCRUSUVNUE8uQ0FMSURBRCwgc3RhcnQgPSAxLCBzdG9wID0gMikKdGliYmxlIChwcm9kdWNjaW9udG90YWwpCnByb2R1Y2Npb250b3RhbCRUSUVNUE8uQ0FMSURBRCA8LSBhcy5pbnRlZ2VyKHByb2R1Y2Npb250b3RhbCRUSUVNUE8uQ0FMSURBRCkKc3RyKHByb2R1Y2Npb250b3RhbCkgCmBgYAoKIyMjICBDb252ZXJ0aXIgZm9ybWF0byBkZSBsYSBmZWNoYSAKCkVzdG8gcGFyYSBwb2RlciB0ZW5lciBsYXMgaW50ZXJwcmV0YWNpb25lcyB5IHJlc3VsdGFkb3MgZXNwZXJhZG9zIGRlIGxhIG1hbmVyYSBjb3JyZWNyYS4gCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwcm9kdWNjaW9udG90YWwkRmVjaGEgPC0gYXMuRGF0ZShwcm9kdWNjaW9udG90YWwkRmVjaGEsIGZvcm1hdCA9ICIlZC8lbS8lWSIpCnRpYmJsZShwcm9kdWNjaW9udG90YWwpCmBgYAoKIyMjICBDb252ZXJ0aXIgdmFyaWFibGUgIkNsaWVudGUiIHBhcmEgYW7DoWxpc2lzIGRlc2NyaXB0aXZvIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwcm9kdWNjaW9udG90YWwkQ0xJRU5URTwtYXMuZmFjdG9yKHByb2R1Y2Npb250b3RhbCRDTElFTlRFKSAgCnN0cihwcm9kdWNjaW9udG90YWwpCmBgYAoKIyMjICBJZGVudGlmaWNhciB2YWxvcmVzIGZhbHRhbnRlcyAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc3VtKGlzLm5hKHByb2R1Y2Npb250b3RhbCkpCmBgYAoKIyMjICDCv0N1w6FudG9zIE5BIHRlbmdvIHBvciB2YXJpYWJsZT8KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc2FwcGx5KHByb2R1Y2Npb250b3RhbCwgZnVuY3Rpb24oeCkgc3VtIChpcy5uYSh4KSkpCmBgYAoKIyMjIFJlZW1wbGF6YXIgTkEgClNlIHJlZW1wbGF6YXLDs24gbG9zIHJlZ2lzdHJvcyBOQSBkZSBsYSB0YWJsYSBjb24gbGEgbWVkaWFuYQoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcHJvZHVjY2lvbnRvdGFsPC1wcm9kdWNjaW9udG90YWwgJT4lIG11dGF0ZShQSUVaQVMuUFJPRy49aWZlbHNlKGlzLm5hKFBJRVpBUy5QUk9HLiksbWVkaWFuKFBJRVpBUy5QUk9HLixuYS5ybT1UKSxQSUVaQVMuUFJPRy4pKQpwcm9kdWNjaW9udG90YWw8LXByb2R1Y2Npb250b3RhbCAlPiUgbXV0YXRlKFRNTy4uTUlOLj1pZmVsc2UoaXMubmEoVE1PLi5NSU4uKSxtZWRpYW4oVE1PLi5NSU4uLG5hLnJtPVQpLFRNTy4uTUlOLikpCnByb2R1Y2Npb250b3RhbDwtcHJvZHVjY2lvbnRvdGFsICU+JSBtdXRhdGUobGFtaW5hc19wcm9jZXNhZGFzPWlmZWxzZShpcy5uYShMYW1pbmFzLnByb2Nlc2FkYXMpLG1lZGlhbihMYW1pbmFzLnByb2Nlc2FkYXMsbmEucm09VCksTGFtaW5hcy5wcm9jZXNhZGFzKSkKcHJvZHVjY2lvbnRvdGFsPC1wcm9kdWNjaW9udG90YWwgJT4lIG11dGF0ZShUSUVNUE8uQ0FMSURBRD1pZmVsc2UoaXMubmEoVElFTVBPLkNBTElEQUQpLG1lZGlhbihUSUVNUE8uQ0FMSURBRCxuYS5ybT1UKSxUSUVNUE8uQ0FMSURBRCkpCmBgYAoKIyMjICBWZXJpZmljYXIgbGEgc3VtYSBkZSBOQXMKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc3VtKGlzLm5hKHByb2R1Y2Npb250b3RhbCkpCnNhcHBseShwcm9kdWNjaW9udG90YWwsIGZ1bmN0aW9uKHgpIHN1bSAoaXMubmEoeCkpKQpgYGAKCiMjIyAgT21pdGlyIGxvcyB2YWxvcmVzIGlycmVsZXZhbnRlcyBpZGVudGlmaWNhZG9zCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnByb2R1Y2Npb250b3RhbCA8LSBuYS5vbWl0KHByb2R1Y2Npb250b3RhbCkKc3VtbWFyeShwcm9kdWNjaW9udG90YWwpICAgCnN1bShpcy5uYShwcm9kdWNjaW9udG90YWwpKQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnN1bW1hcnkgKHByb2R1Y2Npb250b3RhbCkKYGBgCgojIyAgVmlzdWFsaXphY2nDs24KCiMjIyAgwr9DdcOhbCBlcyBlbCBjbGllbnRlIGNvbiBtYXlvciB0aWVtcG8gZGUgY2FsaWRhZD8KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCgpwcm9kdWNjaW9udG90YWwyPC1wcm9kdWNjaW9udG90YWwgJT4lIGRwbHlyOjpzZWxlY3QoQ0xJRU5URSxQSUVaQVMuUFJPRy4sVElFTVBPLkNBTElEQUQpICU+JSBncm91cF9ieShDTElFTlRFKSAlPiUgYXJyYW5nZShkZXNjKFBJRVpBUy5QUk9HLikpCgpzdW1tYXJ5KHByb2R1Y2Npb250b3RhbDIkQ0xJRU5URSkKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwcm9kdWNjaW9udG90YWwzPC0gcHJvZHVjY2lvbnRvdGFsMlstYygxMCksXQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkgKGdncGxvdDIpCmdncGxvdChwcm9kdWNjaW9udG90YWwzLCBhZXMoeD1yZW9yZGVyKENMSUVOVEUsUElFWkFTLlBST0cuKSwgeT1QSUVaQVMuUFJPRy4sIGZpbGw9KFRJRU1QTy5DQUxJREFEKSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpKwogIGNvb3JkX2ZsaXAoKSsKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQocmV2ZXJzZT1GQUxTRSkpCmBgYAoKUG9kZW1vcyB2ZXIgcXVlIHVubyBkZSBsb3MgY2xpZW50ZXMgY29uIGVsIHF1ZSBzZSBwcm9kdWNlbiBtYXlvciBuw7ptZXJvIGRlIHBpZXphcyBwcm9ncmFtYWRhcyB5IHF1ZSBlcyBlbiB1biBsYXB6byBkZSB0aWVtcG8gbWVub3IgZXMgU1RBQklMVVMgMSwgc2VndWlkbyBkZSBZQU5GRU5HLiAKCiMjIyAgwr9DdcOhbCBlcyBlbCBjbGllbnRlIHF1ZSBtw6FzIHBpZXphcyBwcm9ncmFtYWRhcyB0aWVuZSBlbiBsYSBlbXByZXNhPyAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnByb2R1Y2Npb250b3RhbDMgJT4lIHNlbGVjdChDTElFTlRFLFBJRVpBUy5QUk9HLikgJT4lIGdyb3VwX2J5KENMSUVOVEUpICU+JSBzdW1tYXJpc2UoUElFWkFTLlBST0cuPXN1bShQSUVaQVMuUFJPRy4pKSAlPiUgYXJyYW5nZShkZXNjKFBJRVpBUy5QUk9HLikpCgpnZ3Bsb3QocHJvZHVjY2lvbnRvdGFsMywgYWVzKHg9cmVvcmRlcihDTElFTlRFLFBJRVpBUy5QUk9HLiksIHk9UElFWkFTLlBST0cuKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikrCiAgY29vcmRfZmxpcCgpCmBgYAoKU2UgcHVlZGUgdmVyIHF1ZSBlbCBjbGllbnRlIHF1ZSBtw6FzIHBpZXphcyBwcm9ncmFtYWRhcyB0aWVuZSBlcyBZQU5GRU5HIGRlZGljYW5kb3NlbGUgdW4gdGllbXBvIGRlIGNhbGlkYWQgZGUgMS4xIG1pbnV0bywgbWllbnRyYXMgcXVlIGVsIGNsaWVudGUgVkwtMDE3LTE0ODYgZXMgZWwgY2xpZW50ZSBxdWUgdGllbmUgY2FzaSBsYSBtaXRhZCBkZSBwaWV6YXMgcHJvZ3JhbWFkYXMgeSBlcyBhbCBxdWUgbcOhcyB0aWVtcG8gc2UgbGUgZGVkaWNhIHRpZW1wby4KCkVzdG8gcHVlZGUgaW5kaWNhciBxdWUgc3VzIHBpZXphcyBwdWRpZXJhbiBzZXIgZGUgbXVjaG8gbcOhcmdlbiBkZSBlcnJvci4KCgoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBvcmFuZ2UiID4gRGVsaXZlcnkgUGxhbiA8L3NwYW4+IAoKCiMjIyBJbXBvcnRhciBiYXNlIGRlIGRhdG9zCgpgYGB7cn0KZGVsX3BsYW4gPC0gcmVhZC5jc3YoIi9Vc2Vycy9qb3NlcmFtb252YXpxdWV6Z3V6bWFuL0RvY3VtZW50cy9UZWNub2xvzIFnaWNvIGRlIE1vbnRlcnJleS9TZXB0aW1vIHNlbWVzdHJlL0FuYWxpzIF0aWNhIGRlIGRhdG9zIC9SRVRPL0Jhc2VzIGRlIGRhdG9zIGZpbmFsZXMvREVMSVZFUlkgUExBTi9DTEVBTkRCRGVsaXZlcnlQbGFuLmNzdiIpCmBgYAoKCiMjIyAgVGlwb3MgZGUgVmFyaWFibGVzCgpgYGB7cn0KClZhcmlhYmxlPC1jKCJDbGllbnRlIHBsYW50YSIsIk1lcyIsICJVbmlkYWRlcyIpCgpUeXBlPC1jKCJxdWFsaXRhdGl2ZSAobm9taW5hbCkiLCAicXVhbGl0YXRpdmUgKG9yZGluYWwpIiwgInF1aWFudGl0YXRpdmUgKGRpc2NyZXRhKSIpCgp0YWJsZTwtZGF0YS5mcmFtZShWYXJpYWJsZSxUeXBlKQprbml0cjo6a2FibGUodGFibGUpCmBgYAoKIyMjIENvbnZlcnRpciBtZXNlcyBlbiB1bmEgY29sdW1uYQoKUGFyYSBtZWpvcmFyIGVsIG1hbmVqbyBkZSBsYXMgdW5pZGFkZXMgZGUgcHJvZHVjY2lvbiBtZW5zdWFsZXMgeWEgcXVlIG9yaWdpbmFsbWVudGUgZW4gbGEgYmFzZSBkZSBkYXRvcyBlc3RhcyBlcmFuIHJlZ2lzdHJhZGFzIGRpYXJpYW1lbnRlLgoKYGBge3J9CmRlbF9wbGFuPC0gY2xlYW5fbmFtZXMoZGVsX3BsYW4pCnN1bW1hcnkoZGVsX3BsYW4kbWVzKQoKZGVsX3BsYW4kbWVzPC1yZWNvZGVfZmFjdG9yKGRlbF9wbGFuJG1lcyxqdW5fMjE9Imp1bmlvIixqdWxfMjE9Imp1bGlvIixhZ29fMjE9ImFnb3N0byIsc2VwXzIxPSJzZXB0aWVtYnJlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvY3RfMjE9Im9jdHVicmUiLG5vdl8yMT0ibm92aWVtYnJlIixkaWNfMjE9ImRpY2llbWJyZSIsb2N0XzIyPSJvY3R1YnJlXzIyIikKCmZ1bmN0aW9uKHBpdm90X2xvbmdlcikKZGVsX3BsYW48LXBpdm90X2xvbmdlcihkZWxfcGxhbiwgY29scz01OjE2LCBuYW1lc190byA9ICJtZXMiLCB2YWx1ZXNfdG8gPSAidW5pZGFkZXMiKQoKYGBgCgojIyMgRWxpbWluYXIgY29sdW1uYXMgbm8gbmVjZXNhcmlhcwoKRWxpbWluYXIgY29sdW1uYXMgbm8gbmVjZXNhcmlhcyBjb21vIElEIE9ET08sIFByb3llY3RvIGUgSVRFTSBxdWUgZXJhbiBpcnJlbGViYW50ZXMgcGFyYSBlbCBhbsOhbGlzaXMuCgojIyMgRm9ybWF0byBkZSBsYXMgdmFyaWFibGVzCgpgYGB7cn0Kc3RyKGRlbF9wbGFuKQpgYGAKCiMjIyBOQSdzIHkgdmFsb3JlcyBhdGlwaWNvcwoKRW4gbGEgYmFzZSBkZSBkYXRvcyBubyBzZSBoYXkgTkEsIHNvbG8gZWxpbWluYW1vcyBsb3MgcmVnaXN0cm9zIHF1ZSB0aWVuZW4gMCB1bmlkYWRlcyBwcm9ncmFtYWRhcy4KCmBgYHtyfQpkZWxfcGxhbiA8LSBmaWx0ZXIoZGVsX3BsYW4sIHVuaWRhZGVzPjApCnN1bShpcy5uYShkZWxfcGxhbikpCmBgYAoKIyMgR3JhZmljYXMKCiMjIyBUYWJsYSBlc3RhZGlzdGljYXMgCgpgYGB7cn0KdGFibGFfZXN0YWRpc3RpY29zIDwtIGRlc2NyaWJlKGRlbF9wbGFuKQp0YWJsYV9lc3RhZGlzdGljb3MKYGBgCgoKQWwgcmVhbGl6YXIgIHVuYSB0YWJsYSBlc3RhZGlzdGljYSwgUiBub3MgYXJyb2phIGRpZmVyZW50ZXMgbWV0b2RvcyBjb21vIGxhIG1lZGlhLCBsYSBtZWRpYW5hLCBsYSBtb2RhIHkgbGEgZGVzdmlhY2lvbiBlc3RhbmRhciBxdWUgc29uIGltcG9ydGFudGVzIGFsIG1vbWVudG8gZGUgcmVhbGl6YXIgZXN0ZSBhbsOhbGlzaXMuCgojIyMgQmFyIHBsb3RzCgpgYGB7cn0Kc3RyKGRlbF9wbGFuKQpkZWxfcGxhbiRjbGllbnRlX3BsYW50YTwtYXMuZmFjdG9yKGRlbF9wbGFuJGNsaWVudGVfcGxhbnRhKQpkZWxfcGxhbiR1bmlkYWRlczwtYXMubnVtZXJpYyhkZWxfcGxhbiR1bmlkYWRlcykgCgpkZWxfcGxhbjI8LWFnZ3JlZ2F0ZSh1bmlkYWRlc35jbGllbnRlX3BsYW50YSwgZGF0YSA9IGRlbF9wbGFuLHN1bSklPiUgYXJyYW5nZShkZXNjKHVuaWRhZGVzKSkKZGVsX3BsYW4zPC1maWx0ZXIoZGVsX3BsYW4yLCB1bmlkYWRlcz40MDAwKQoKZ2dwbG90KGRlbF9wbGFuMywgYWVzKHg9cmVvcmRlcihjbGllbnRlX3BsYW50YSx1bmlkYWRlcyksIHk9dW5pZGFkZXMpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsKICBjb29yZF9mbGlwKCkKYGBgCgoKU2UgcmVhbGl6w7MgdW4gcHJvY2VzbyBlbiBlbCBjdWFsIHByaW1lcm8gc2UgY29udmlydGllcm9uIGxhcyB2YXJpYWJsZXMgbWVkaWFudGUgbGFzIGZ1bmNpb25lcyBhcy5mYWN0b3IgeSBhcy5udW1lcmljIHBhcmEgaGFjZXIgbG9zIGRhdG9zIGN1YWxpdGF0aXZvcyAvIGN1YW50aXRhdGl2b3MuCgpTZSBtdWVzdHJhbiB2YWxvcmVzIG1heW9yZXMgYSA0MDAwLCBsbyBjdcOhbCBub3MgcmVzdWx0w7MgZW4gdW5hIGdyw6FmaWNhIGRvbmRlIHNlIHBvZMOtYW4gb2JzZXJ2YXIgbG9zIENsaWVudGVzIGNvbiBtYXlvciBuw7ptZXJvIGRlIHVuaWRhZGVzIGVuIG9yZGVuIGRlc2NlbmRpZW50ZS4KCiMjIyBEaXNwZXJzaW9uCgpgYGB7cn0KZGVsX3BsYW4yJHVuaWRhZGVzPC1hcy5udW1lcmljKGRlbF9wbGFuMiR1bmlkYWRlcykKCmdncGxvdChkZWxfcGxhbiwgYWVzKHg9Y2xpZW50ZV9wbGFudGEsIHk9dW5pZGFkZXMsIGZpbGw9Y2xpZW50ZV9wbGFudGEpKSArIAogIGdlb21fYm94cGxvdCgpIAoKYm94cGxvdChkZWxfcGxhbjMkY2xpZW50ZV9wbGFudGEsZGVsX3BsYW4zJHVuaWRhZGVzKQpjbGFzcyhkZWxfcGxhbjIkdW5pZGFkZXMpCmBgYAoKCkhlbGxhIGVzIGVsIGNsaWVudGUgY29uIG1heW9yIGNhbnRpZGFkIGRlIHVuaWRhZGVzIHkgYWRlbcOhcyBkZSBlc28gY3VlbnRhIGNvbiBhbGd1bm9zIG91dGxpZXJzIG11eSBwb3IgZW5jaW1hIGRlIGxhIG1lZGlhbiwgc2VndWlkbyBwb3IgVFJNWCBlbCBjdWFsIG5vIGN1ZW50YSBjb24gb3V0bGllcnMuCgoKCiMjIyBUaW1lIHNlcmllcyBwbG90CgpgYGB7cn0KZGVsX3BsYW40PC1hZ2dyZWdhdGUodW5pZGFkZXN+Y2xpZW50ZV9wbGFudGErbWVzLCBkYXRhID0gZGVsX3BsYW4sc3VtKSU+JSBhcnJhbmdlKGRlc2ModW5pZGFkZXMpKQpkZWxfcGxhbjU8LWZpbHRlcihkZWxfcGxhbjQsIGNsaWVudGVfcGxhbnRhPT0iSEVMTEEiICYgY2xpZW50ZV9wbGFudGE9PSJUUk1YIiAmIGNsaWVudGVfcGxhbnRhPT0iVkFSUk9DIiAmIGNsaWVudGVfcGxhbnRhPT0iREVOU08iKQpnZ3Bsb3QoZGVsX3BsYW4sYWVzKHg9bWVzLCB5PXVuaWRhZGVzLGNvbG9yPWNsaWVudGVfcGxhbnRhKSkrCiAgZ2VvbV9saW5lKCkrCiAgbGFicyh4PSJGZWNoYSIseT0iRGVsYXkgaW4gTWludXRlcyIsIGNvbG9yPSJMZWdlbmQiKSsKICBnZ3RpdGxlKCJEZWxheXMgaW4gUGVyZm9ybWFuY2UgYnkgQ2xpZW50IikKYGBgCgpTZSBvYnNlcnZhIGVuIGxhIHNlZ3VuZGEgbWl0YWQgZGVsIHBlcmlvZG8gYW51YWwgcXVlIGhheSB1biBpbmNyZW1lbnRvIG5vdG9yaW8sIGFkZW3DoXMgZGUgdW4gZGVjcmVtZW50byBqdXN0byBwb3IgZmluYWxlcyBkZWwgc2VndW5kbyBzZW1lc3RyZS4KCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogb3JhbmdlIiA+IE1lcm1hICA8L3NwYW4+IAoKIyMjICBJbXBvcnRhciBiYXNlIGRlIGRhdG9zCmBgYHtyfQoKI2ZpbGUuY2hvb3NlKCkKYmQgPC1yZWFkLmNzdigiL1VzZXJzL2pvc2VyYW1vbnZhenF1ZXpndXptYW4vRG9jdW1lbnRzL1RlY25vbG/MgWdpY28gZGUgTW9udGVycmV5L1NlcHRpbW8gc2VtZXN0cmUvQW5hbGnMgXRpY2EgZGUgZGF0b3MgL1JFVE8vQmFzZXMgZGUgZGF0b3MgZmluYWxlcy9NRVJNQS9GT1JNIC0gTWVybWEgbGltcGlhMiAoMSkuY3N2IikKYGBgCkVuIGVsIGNhc28gZGUgbGFzIHZhcmlhYmxlcyBjdWFudGl0YXRpdmFzLCBjb25zaWRlcmFyIGxhIHBvc2liaWxpZGFkIGRlIHJlZW1wbGF6YXIgbGEgcHJlc2VuY2lhIGRlIOKAnG1pc3NpbmcgdmFsdWVz4oCdIGNvbiBlc3RhZMOtc3RpY29zIGRlc2NyaXB0aXZvcyBwb3IgZWplbXBsbywgbWVkaWEsIG1lZGlhbmEsIG1vZGEuCgojIyMgIEFuYWxpemFyIGJhc2UgZGUgZGF0b3MKYGBge3J9CnN1bW1hcnkoYmQpCnN0cihiZCkKYGBgCgojIyMgIFRpcG9zIGRlIFZhcmlhYmxlcyAKYGBge3J9ClZhcmlhYmxlPC1jKCJGZWNoYSIsIkVORVJPIiwiS2lsb3NFbmVybyIsIkZlY2hhMSIsIkZFQlJFUk8iLCJLaWxvc0ZlYnJlcm8iLCJGZWNoYTIiLCJNQVJaTyIsIktpbG9zTWFyem8iLCJGZWNoYTMiLCJBQlJJTCIsIktpbG9zQWJyaWwiLCJGZWNoYTQiLCJNQVlPIiwiS2lsb3NNYXlvIiwiRmVjaGE1IiwiSlVOSU8iLCJLaWxvc0p1bmlvIiwiRmVjaGE2IiwiSlVMSU8iLCJLaWxvc0p1bGlvIiwiRmVjaGE3IiwiQUdPU1RPIiwiS2lsb3NBZ29zdG8iLCJGZWNoYTgiLCJTRVBUSUVNQlJFIiwiS2lsb3NTZXB0aWVtYnJlIikKVHlwZTwtYygicXVhbGl0YXRpdmUgKG9yZGluYWwpIiwgInF1YWxpdGF0aXZlIChvcmRpbmFsKSIsICJxdWFudGl0YXRpdmUgKGRpc2NyZXRlKSIsInF1YWxpdGF0aXZlIChub21pbmFsKSIsInF1YWxpdGF0aXZlIChvcmRpbmFsKSIsInF1YW50aXRhdGl2ZSAoZGlzY3JldGUpIiwicXVhbGl0YXRpdmUgKG5vbWluYWwpIiwicXVhbGl0YXRpdmUgKG9yZGluYWwpIiwicXVhbnRpdGF0aXZlIChkaXNjcmV0ZSkiLCJxdWFsaXRhdGl2ZSAobm9taW5hbCkiLCJxdWFsaXRhdGl2ZSAob3JkaW5hbCkiLCJxdWFudGl0YXRpdmUgKGRpc2NyZXRlKSIsInF1YWxpdGF0aXZlIChub21pbmFsKSIsInF1YWxpdGF0aXZlIChvcmRpbmFsKSIsInF1YW50aXRhdGl2ZSAoZGlzY3JldGUpIiwicXVhbGl0YXRpdmUgKG5vbWluYWwpIiwicXVhbGl0YXRpdmUgKG9yZGluYWwpIiwicXVhbnRpdGF0aXZlIChkaXNjcmV0ZSkiLCJxdWFsaXRhdGl2ZSAobm9taW5hbCkiLCJxdWFsaXRhdGl2ZSAob3JkaW5hbCkiLCJxdWFudGl0YXRpdmUgKGRpc2NyZXRlKSIsInF1YWxpdGF0aXZlIChub21pbmFsKSIsInF1YWxpdGF0aXZlIChvcmRpbmFsKSIsInF1YW50aXRhdGl2ZSAoZGlzY3JldGUpIiwicXVhbGl0YXRpdmUgKG5vbWluYWwpIiwicXVhbGl0YXRpdmUgKG9yZGluYWwpIiwicXVhbnRpdGF0aXZlIChkaXNjcmV0ZSkiKQp0YWJsZTwtZGF0YS5mcmFtZShWYXJpYWJsZSxUeXBlKQprbml0cjo6a2FibGUodGFibGUpCmBgYAoKCiMjIyAgRWxpbWluYXIgTkEncyB5IHN1c3RpdHVpciBjb24gMCdzCmBgYHtyfQpzdW0oaXMubmEoYmQpKQpiZFtpcy5uYShiZCldPC0wCmBgYAoKCiMjIyAgRWxpbWluYXIgZHVwbGljYWRvcwpgYGB7cn0KYmRbZHVwbGljYXRlZChiZCksIF0Kc3VtKGR1cGxpY2F0ZWQoYmQpKQpgYGAKCgojIyMgIEVsaW1pbmFyIG5lZ2F0aXZvcyBjb24gY2VybwpgYGB7cn0KYmQxPC1iZApiZDFbYmQxIDwwXSA8LTAKc3VtbWFyeShiZDEpCmBgYAoKCiMjIyAgQW7DoWxpc2lzIFByb2Z1bmRvIGRlIGxhIEJhc2UgZGUgZGF0b3MKYGBge3J9Cm1lZGlhX2JkNSA8LSBtZWFuKGJkJEtpbG9zTWF5bykKbWVkaWFfYmQ1Cm1lZGlhbl9iZDUgPC0gbWVkaWFuKGJkJEtpbG9zTWF5bykKbWVkaWFuX2JkNQptb2RlX2JkNSA8LSBtb2RlKGJkJEtpbG9zTWF5bykKbW9kZV9iZDUKCm1lZGlhX2JkOCA8LSBtZWFuKGJkJEtpbG9zQWdvc3RvKQptZWRpYV9iZDgKbWVkaWFuX2JkOCA8LSBtZWRpYW4oYmQkS2lsb3NBZ29zdG8pCm1lZGlhbl9iZDgKbW9kZV9iZDggPC0gbW9kZShiZCRLaWxvc0Fnb3N0bykKbW9kZV9iZDgKCmBgYAoKCiMjIyAgR3JhZmljYSBGcmVjdWVuY2lhIChGZWNoYSkKYGBge3J9CmJkJEZlY2hhNzwtIGFzLkRhdGUoYmQkRmVjaGE3LGZvcm1hdCA9ICIlZC8lbS8lWSIpCnBsb3QoYmQkRmVjaGE3LCBiZCRLaWxvc0Fnb3N0bykKYGBgCgpTZSBtb3ZpZXJvbiBhbHJlZGVkb3IgZGUgMzAwMCBhIDUwMDAgbWlsIGtpbG9zIGVuIGVsIGxhcHNvIGRlIEFnb3N0byBkZSBlc3RlIGHDsW8uIAoKIyMjICBHcmFmaWNhIGRlIE1heW8gJiBBZ29zdG8gKE1heW9yIGNhbnRpZGFkIGRlIG1lcm1hIHkgcmVnaXN0cm9zKQpgYGB7cn0KZ2dwbG90KGJkLCBhZXMoeD0gRmVjaGE0LCB5PSBLaWxvc01heW8pKSArIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0iYmx1ZSIpICsgc2NhbGVfZmlsbF9ncmV5KCkgKyBsYWJzKHRpdGxlID0gIktpbG9zIGRlIG1lcm1hIEFnb3N0byIsIHggPSAiRmVjaGEiKQoKZ2dwbG90KGJkLCBhZXMoeD0gRmVjaGE3LCB5PSBLaWxvc0Fnb3N0bykpICsgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBmaWxsPSJibHVlIikgKyBzY2FsZV9maWxsX2dyZXkoKSArIGxhYnModGl0bGUgPSAiS2lsb3MgZGUgbWVybWEgQWdvc3RvIiwgeCA9ICJGZWNoYSIpCmBgYAoKClBvZGVtb3MgdmVyIGNvbW8gZW4gQWdvc3RvIHNlIHR1dm8gdW4gcHJvbWVkaW8gZGUgbWVybWEgcG9yIGTDrWEgc29icmVwYXNhbmRvIGxvcyAzMDAwIGtpbG9zLCBzaWVuZG8gZXN0YSBncsOhZmljYSByZWxldmFudGUgcGFyYSBwb2RlciBpZGVudGlmaWNhciBmYWN0b3JlcyBpbXBvcnRhbnRlcyB5IHJlZHVjaXIgZXN0YXMgY2FudGlkYWRlcyBhcGxpY2FuZG8gS1BJJ3MgCgoKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogb3JhbmdlIiA+IERlbGl2ZXJ5IFBlcmZvcm1hbmNlIDwvc3Bhbj4gCgojIyMgSW1wb3J0YXIgYmFzZSBkZSBkYXRvcwoKYGBge3J9CiNmaWxlLmNob29zZSgpCmJkX3RvdGFsZGlmZXJlbmNpYXM8LXJlYWQuY3N2KCIvVXNlcnMvam9zZXJhbW9udmF6cXVlemd1em1hbi9Eb2N1bWVudHMvVGVjbm9sb8yBZ2ljbyBkZSBNb250ZXJyZXkvU2VwdGltbyBzZW1lc3RyZS9BbmFsacyBdGljYSBkZSBkYXRvcyAvUkVUTy9CYXNlcyBkZSBkYXRvcyBmaW5hbGVzL0RFTElWRVJZIFBFUkZPUk1BTkNERS9GT1JNIERlbGl2ZXJ5IFBlcmZvcm1hbmNlIEJkIENsaWVudGVzLmNzdiIpCmJkX3RvdGFsbWVzPC1yZWFkLmNzdigiL1VzZXJzL2pvc2VyYW1vbnZhenF1ZXpndXptYW4vRG9jdW1lbnRzL1RlY25vbG/MgWdpY28gZGUgTW9udGVycmV5L1NlcHRpbW8gc2VtZXN0cmUvQW5hbGnMgXRpY2EgZGUgZGF0b3MgL1JFVE8vQmFzZXMgZGUgZGF0b3MgZmluYWxlcy9ERUxJVkVSWSBQRVJGT1JNQU5DREUvREVMIFBFUkYgVE9UQUxFUy5jc3YiKQpgYGAKCiMjIyBFbnRlbmRlciBsYSBiYXNlIGRlIGRhdG9zCgpgYGB7cn0Kc3VtbWFyeSAoYmRfdG90YWxkaWZlcmVuY2lhcykKc3VtbWFyeShiZF90b3RhbG1lcykKCmBgYAoKIyMjIFTDqWNuaWNhcyBkZSBMaW1waWV6YQoKIyMgIEJBU0UgREUgREFUT1MgMQoKIyMjIFTDqWNuaWNhIDEuIFJlbW92ZXIgY29sdW1uYSBpcnJlbGV2YW50ZQogIApFbGltaW5hciBjb2x1bW5hczogU2UgcmVhbGl6w7MgZXN0YSB0w6ljbmljYSB5YSBxdWUgYWwgbW9tZW50byBkZSBlbnRlbmRlciBsYSBiYXNlIGRlIGRhdG9zIHNlIGlkZW50aWZpY2Fyb24gY29sdW1uYXMgc2luIHZhbG9yIHkgc2luIHJlbGV2YW5jaWEgcmVsYWNpb25hZGFzIGNvbiBsbyBxdWUgc2UgcXVlcsOtYSBpbnRlcnByZXRhciB5IHZpc3VhbGl6YXIuIAogIApgYGB7cn0KCmJkX3RvdGFsZGlmZXJlbmNpYXMgPC0gc3Vic2V0IChiZF90b3RhbGRpZmVyZW5jaWFzLHNlbGVjdCA9IC1jKFgsIFguMSwgWC4yLCBYLjMsIFguNCwgWC41LCBYLjYsIFguNywgWC44LCBYLjksIFguMTAsIFguMTEsIFguMTIsIFguMTMsIFguMTQsIFguMTUsIFguMTYsIFguMTcsIFguMTgsIFguMTksIFguMjAgKSkKc3VtbWFyeSAoYmRfdG90YWxkaWZlcmVuY2lhcykKCgojIyMgVMOpY25pY2EgMi4gSWRlbnRpZmljYXIgTkEncwpzdW0oaXMubmEoYmRfdG90YWxkaWZlcmVuY2lhcykpCnNhcHBseShiZF90b3RhbGRpZmVyZW5jaWFzLCBmdW5jdGlvbih4KSBzdW0gKGlzLm5hKHgpKSkKCgojIypFbGltaW5hciBmaWxhcyBsYXMgY3VhbGVzIG5vIGN1ZW50YW4gY29uIHZhbG9yZXMqCmJkX3RvdGFsZGlmZXJlbmNpYXM8LWJkX3RvdGFsZGlmZXJlbmNpYXNbLWMoMzAwOjk5NyksXQoKCiMjIyBUw6ljbmljYSAzLiBDYW1iaWFyIGZvcm1hdG9zIApiZF90b3RhbGRpZmVyZW5jaWFzJFBSSU5URUw8LWFzLmludGVnZXIoYmRfdG90YWxkaWZlcmVuY2lhcyRQUklOVEVMKSAKYmRfdG90YWxkaWZlcmVuY2lhcyRNQUhMRTwtYXMuaW50ZWdlcihiZF90b3RhbGRpZmVyZW5jaWFzJE1BSExFKSAKYmRfdG90YWxkaWZlcmVuY2lhcyRNQUdOQTwtYXMuaW50ZWdlcihiZF90b3RhbGRpZmVyZW5jaWFzJE1BR05BKSAKYmRfdG90YWxkaWZlcmVuY2lhcyRWQVJST0M8LWFzLmludGVnZXIoYmRfdG90YWxkaWZlcmVuY2lhcyRWQVJST0MpIApgYGAKCiMjIEJBU0UgREUgREFUT1MgMgoKCiMjIFTDqWNuaWNhIDEuIEVsaW1pbmFyIE5BJ3MKCkVsaW1pbmFyIGZpbGFzIGxhcyBjdWFsZXMgbm8gY3VlbnRhbiBjb24gdmFsb3JlcwoKYGBge3J9CgpiZF90b3RhbG1lczwtYmRfdG90YWxtZXNbLWMoMTQ6OTk5KSxdCgoKIyMjIFTDqWNuaWNhIDIuIENhbWJpYXIgZm9ybWF0byAKYmRfdG90YWxtZXMkUFJJTlRFTDwtYXMuaW50ZWdlcihiZF90b3RhbG1lcyRQUklOVEVMKSAKYmRfdG90YWxtZXMkTUFITEU8LWFzLmludGVnZXIoYmRfdG90YWxtZXMkTUFITEUpIApiZF90b3RhbG1lcyRNQUdOQTwtYXMuaW50ZWdlcihiZF90b3RhbG1lcyRNQUdOQSkgCmJkX3RvdGFsbWVzJFZBUlJPQzwtYXMuaW50ZWdlcihiZF90b3RhbG1lcyRWQVJST0MpIApgYGAKCiMjIyBBbmFsaXphciBiYXNlIGRlIGRhdG9zCgpgYGB7cn0Kc3RyIChiZF90b3RhbGRpZmVyZW5jaWFzKQpzdHIgKGJkX3RvdGFsbWVzKQoKc3VtbWFyeShiZF90b3RhbGRpZmVyZW5jaWFzKQpzdW1tYXJ5KGJkX3RvdGFsbWVzKQoKYGBgCgpMYSBiYXNlIGRlIGRhdG9zICp0b3RhbCBkaWZlcmVuaWNhcyogY3VlbnRhIGNvbiAyOTkgb2JzZXJ2YWNpb25lcyB5IDUgdmFyaWFibGVzIG1pZW50cmEgcXVlIGxhIGJhc2UgZGUgZGF0b3MgKnRvdGFsIG1lbnN1YWwqIGN1ZW50YSBjb24gMTMgb2JzZXJ2YWNpb25lcyB5IDUgdmFyaWFibGVzLgoKIAojIyMgIFRpcG9zIGRlIFZhcmlhYmxlcyBFeGlzdGVudGVzIAoKYGBge3J9CgpWYXJpYWJsZTwtYygiRkVDSEEiKQpUeXBlPC1jKCJDdWFsaXRhdGl2YSAoT3JkaW5hbCkiKSAgCnRhYmxlPC1kYXRhLmZyYW1lKFZhcmlhYmxlLFR5cGUpCmtuaXRyOjprYWJsZSh0YWJsZSkKCmBgYAoKIyMjICBFc2NhbGEgZGUgbWVkaWNpw7NuIAoKYGBge3J9CgpWYXJpYWJsZTwtYygiUFJJTlRFTCIsICJNQUhMRSIsICJNQUdOQSIsICJWQVJST0MiKQpUeXBlPC1jKCJIb3JhcyIsICJIb3JhcyIsICJIb3JhcyIsICJIb3JhcyIpICAKdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSkKa25pdHI6OmthYmxlKHRhYmxlKQoKCmBgYAoKIyMjIERlc2NyaWJpciBsYSBiYXNlIGRlIGRhdG9zCmBgYHtyfQoKc3RyKGJkX3RvdGFsZGlmZXJlbmNpYXMpCnN0cihiZF90b3RhbG1lcykKCmBgYAoKIyMjICBBbsOhbGlzaXMgUHJvZnVuZG8gZGUgbGEgQmFzZSBkZSBkYXRvcwogCmBgYHtyfQoKbWVkaWFfYmQgPC0gbWVhbihiZF90b3RhbGRpZmVyZW5jaWFzJERJRkVSRU5DSUEpCm1lZGlhX2JkCgptZWRpYW5fYmQgPC0gbWVkaWFuKGJkX3RvdGFsZGlmZXJlbmNpYXMkRElGRVJFTkNJQSkKbWVkaWFuX2JkCgptb2RlIDwtIGZ1bmN0aW9uICh4KSB7CiAgdXggPC0gdW5pcXVlKHgpCiAgdXggW3doaWNoLm1heCh0YWJ1bGF0ZShtYXRjaCh4LHV4KSkpXQp9Cm1vZGVfYmQgPC0gbW9kZShiZF90b3RhbGRpZmVyZW5jaWFzJERJRkVSRU5DSUEpCm1vZGVfYmQKCgoKaGlzdChiZF90b3RhbGRpZmVyZW5jaWFzJE1BSExFKSAKaGlzdChiZF90b3RhbGRpZmVyZW5jaWFzJFBSSU5URUwpCmBgYAoKIyMjIEFuw6FsaXNpcyBQcm9mdW5kbyBkZSBsYSBCYXNlIGRlIGRhdG9zIEJEQ0xJRU5URVMKYGBge3J9CgptZWRpYV9iZGNsaWVudGVzIDwtIG1lYW4oYmRfdG90YWxtZXMkUFJJTlRFTCkKbWVkaWFfYmRjbGllbnRlcwoKbWVkaWFuX2JkY2xpZW50ZXMgPC0gbWVkaWFuKGJkX3RvdGFsbWVzJFBSSU5URUwpCm1lZGlhbl9iZGNsaWVudGVzCgptb2RlX2JkY2xpZW50ZXMgPC0gbW9kZShiZF90b3RhbG1lcyRQUklOVEVMKQptb2RlX2JkY2xpZW50ZXMKCm1lZGlhX2JkY2xpZW50ZXMgPC0gbWVhbihiZF90b3RhbG1lcyRNQUhMRSkKbWVkaWFfYmRjbGllbnRlcwoKbWVkaWFuX2JkY2xpZW50ZXMgPC0gbWVkaWFuKGJkX3RvdGFsbWVzJE1BSExFKQptZWRpYW5fYmRjbGllbnRlcwoKbW9kZV9iZGNsaWVudGVzIDwtIG1vZGUoYmRfdG90YWxtZXMkTUFITEUpCm1vZGVfYmRjbGllbnRlcwoKYmRjbGllbnRlczMgPC1iZF90b3RhbG1lcwpiZGNsaWVudGVzMyA8LSBzdWJzZXQgKGJkY2xpZW50ZXMzLCBzZWxlY3QgPSAtYyAoTUFHTkEsVkFSUk9DKSkKCmBgYAoKCiMjIyAgSGlzdG9ncmFtYSBQcmludGVsIAoKYGBge3J9Cmhpc3QoYmRjbGllbnRlczMkUFJJTlRFTCkKYGBgCgojIyMgIEhpc3RvZ3JhbWEgTWFobGUgCgpgYGB7cn0KaGlzdChiZGNsaWVudGVzMyRNQUhMRSkKYGBgCgpQRVJJTlRFTAoKRW4gbGEgY2xhc2UgZGUgMCBhIDUgc2UgZW5jdWVudHJhIHF1ZSBzZSB0dXZvIG1heW9yIGZyZWN1ZW5jaWEsIHNpZW5kbyBsYSBjbGFzZSBxdWUgbcOhcyBzZSByZXBpdGUsIGVzdG8gcXVpZXJlIGRlY2lyIHF1ZeKApiAKRGUgbG9zIDEyIG1lc2VzLCBlbiA3IHNlIHR1dm8gdW5hIGRpZmVyZW5jaWEgZGUgdGllbXBvIGRlIGVudHJlIDAgeSA1IG1pbnV0b3MsIHNpZW5kbyBlc3RhIGJhamEgcGVybyBjb24gdW4gc2VzZ28gYSBsYSBpenF1aWVyZGEuIAoKTUFITEUKCkVzdGUgaGlzdG9ncmFtYSB0aWVuZSB1biBzZXNnbyBoYWNpYSBsYSBkZXJlY2hhLCBzZSB0aWVuZSB1bmEgdGVuZGVuY2lhIGEgdGVuZXIgdW4gbWF5b3IgcmV0cmFzbyBlbiBsYSBjbGFzZSBkZSA2MCBhIDcwIG1pbnV0b3MgYXByb3hpbWFkYW1lbnRlIGNvbiBlc3RlIGNsaWVudGUsIGVzdG8gZW4gdW4gYXByb3hpbWFkbyBkZSA2IG1lc2VzIGRlIGxvcyAxMiB0b21hZG9zIGVuIGN1ZW50YS4KCiMjIyBHcsOhZmljYSBQUklOVEVMCmBgYHtyfQpnZ3Bsb3QoYmRfdG90YWxtZXMsYWVzKHg9RkVDSEEsIHk9UFJJTlRFTCxmaWxsPVBSSU5URUwpKSsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0zMyxsaW5ldHlwZT0iZGFzaGVkIixjb2xvcj0iYmxhY2siKSsKICBsYWJzKHg9IkZlY2hhIix5PSJSZXRyYXNvIGVuIE1pbnV0b3MiLCBjb2xvcj0iTGVnZW5kIikrCiAgZ2d0aXRsZSgiUmV0cmFzbyBlbiBEZXNlbXBlw7FvIGRlIGxvcyBDbGllbnRlcyIpCmBgYAoKIyMjIEdyw6FmaWNhIE1BSExFIAoKYGBge3J9CmdncGxvdChiZF90b3RhbG1lcyxhZXMoeD1GRUNIQSwgeT1NQUhMRSxmaWxsPU1BSExFKSkrCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MzMsbGluZXR5cGU9ImRhc2hlZCIsY29sb3I9ImJsYWNrIikrCiAgbGFicyh4PSJGZWNoYSIseT0iUmV0cmFzbyBlbiBNaW51dG9zIiwgY29sb3I9IkxlZ2VuZCIpKwogIGdndGl0bGUoIlJldHJhc28gZW4gRGVzZW1wZcOxbyBkZSBsb3MgQ2xpZW50ZXMiKQpgYGAKCgpTZSBwdWVkZSBjb25jbHVpcgpFbiBlc3RvcyBkb3MgZ3LDoWZpY28gc2UgZGVtdWVzdHJhIGVsIHJldHJhc28gZW4gZGVzZW1wZcOxbyBkZSBsb3MgY2xpZW50ZXMgTWFobGUgeSBQcmludGVsLCB0YW1iacOpbiBzZSBvYnNlcnZhIGxhIG1lZGlhIHNpZW5kbyBsYSBsw61uZWEgaG9yaXpvbnRhbCBkZSBjb2xvciBuZWdyby4KClNlIHBlZGUgY29uY2x1aXIgcXVlIE1haGxlIGVzIGVsIGNsaWVudGUgY29uIG1heW9yIHJldHJhc28gc29icmUgcGFzYW5kbyBsb3MgNjAgbWludXRvcyBkZSByZXRyYXNvLCBtaWVudHJhcyBxdWUgUHJpbnRlbCBzaWVtcHJlIHNlIG1hbnRpZW5lIHBvciBkZWJham8gZGUgbG9zIDMwIG1pbnV0b3MuIAoKCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IG9yYW5nZSIgPiBTY3JhcCAgPC9zcGFuPgoKCiMjIyAgTGxhbWFyIGEgbGEgYmFzZSBkZSBkYXRvcyAgCgpgYGB7cn0KI2ZpbGUuY2hvb3NlKCkKYmQgPC0gcmVhZC5jc3YoIi9Vc2Vycy9qb3NlcmFtb252YXpxdWV6Z3V6bWFuL0RvY3VtZW50cy9UZWNub2xvzIFnaWNvIGRlIE1vbnRlcnJleS9TZXB0aW1vIHNlbWVzdHJlL0FuYWxpzIF0aWNhIGRlIGRhdG9zIC9SRVRPL0Jhc2VzIGRlIGRhdG9zIChsaW1waWFzKSBDU1YgL0ZPUk0gLSBTY3JhcCBMaW1waWEgLmNzdiIpCmBgYAoKIyMjICBDYW50aWRhZCBkZSBwcm9kdWN0b3MgcG9yIGTDrWEgCgpgYGB7cn0KCmJkJEZlY2hhPC0gYXMuRGF0ZShiZCRGZWNoYSxmb3JtYXQgPSAiJWQvJW0vJVkiKQpwbG90KGJkJEZlY2hhLCBiZCRDYW50aWRhZCkKCnN1bW1hcnkoYmQpCmBgYAoKIyMjICBOw7ptZXJvIGRlIHZhcmlhYmxlcyB5IHJlZ2lzdHJvcyBlbiBiYXNlIGRlIGRhdG9zCgpgYGB7cn0KCmRlc2NyaWJlKGJkKQpzdHIoYmQpCgp0YWJ5bChiZCwgUHJvZHVjdG8sIFViaWNhY2nDs24uZGUub3JpZ2VuKQoKYGBgCgojIyMgIFRpcG9zIGRlIFZhcmlhYmxlcyBFeGlzdGVudGVzCgpgYGB7cn0KCnZhcmlhYmxlPC1jKCJSZWZlcmVuY2lhIiwiRmVjaGEiLCAiSG9yYSIsICJQcm9kdWN0byIsICJDYW50aWRhZCIsICJVbmlkYWQuZGUubWVkaWRhIiwgIlViaWNhY2nDs24uZGUub3JpZ2VuIiwgIlViaWNhY2nDs24uZGUuZGVzZWNobyIpCgp0eXBlPC1jKCJDdWFsaXRhdGl2byAobm9taW5hbCkiLCJDdWFsaXRhdGl2byAobm9taW5hbCkiLCAiQ3VhbnRpdGF0aXZvIChkaXNjcmV0YSkiLCAiQ3VhbGl0YXRpdm8gKG5vbWluYWwpIiwiQ3VhbnRpdGF0aXZvIChDb250aW51YSkiLCAiQ3VhbGl0YXRpdm8gKG5vbWluYWwpIiwgIkN1YWxpdGF0aXZvIChub21pbmFsKSIsIkN1YWxpdGF0aXZvIChub21pbmFsKSIpCgp0YWJsZTwtZGF0YS5mcmFtZSh2YXJpYWJsZSx0eXBlKQprbml0cjo6a2FibGUodGFibGUpCgoKYGBgCgojIyMgIExpbXBpZXphIEJhc2UgZGUgZGF0b3MKCkxhIGJhc2UgZGUgZGF0b3MgY29udGFiYSBjb24gYWxndW5hcyB2YXJpYWJsZXMgcXVlIG5vIGVyYW4gdGFuIHJlbGV2YW50ZXMgcGFyYSBhbmFsaXphciBsYSBiYXNlIGRlIHNjcmFwIHkgc2UgIGRlY2lkacOzIGVsaW1pbmFybGFzIHBhcmEgY29udGFyIGNvbiBtZW5vcyB2YXJpYWJsZXMgeSBhc8OtIHBvZGVyIHJlYWxpemFyIHVuIG1lam9yIGFuw6FsaXNpcy4KCgpgYGB7cn0KCnN1bShpcy5uYShiZCkpCgpzYXBwbHkoYmQsIGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpCgpiZDIgPC0gYmQKYmQyIDwtIHN1YnNldCAoYmQyLCBzZWxlY3QgPSAtYyAoSG9yYSkpCmJkMiA8LSBzdWJzZXQgKGJkMiwgc2VsZWN0ID0gLWMgKFByb2R1Y3RvKSkKYmQyIDwtIHN1YnNldCAoYmQyLCBzZWxlY3QgPSAtYyAoVWJpY2FjacOzbi5kZS5kZXNlY2hvKSkKYmQyIDwtIHN1YnNldCAoYmQyLCBzZWxlY3QgPSAtYyAoVW5pZGFkLmRlLm1lZGlkYSApKQpiZDIgPC0gc3Vic2V0IChiZDIsIHNlbGVjdCA9IC1jIChSZWZlcmVuY2lhICkpCmJkMiA8LSBzdWJzZXQgKGJkMiwgc2VsZWN0ID0gLWMgKEVzdGFkbyApKQoKc3VtbWFyeShiZDIpCgojc2VsZWNjaW9uYXIgY29sdW1uYXMgLyB2YXJpYWJsZXMuCiNzY3JhcDI8LXNjcmFwICU+JSBzZWxlY3Qob25lX29mKCdGZWNoYScsJ0NhbnRpZGFkJywnVWJpY2FjacOzbi5kZS5vcmlnZW4nKSkKYGBgCgojIyMgIFJlbm9tYnJhciBsYXMgY29sdW1uYXMgL3ZhcmlhYmxlcyBzZWxlY2Npb25hZGFzLgoKYGBge3J9Cgpjb2xuYW1lcyhiZDIpIDwtYyAoJ0ZlY2hhJywnQ2FudC4nLCdPcmlnZW4nKQpzdW1tYXJ5KGJkMikKYGBgCgojIyAgQW7DoWxpc2lzIEVzdGFkw61zdGljbwoKIyMjICBUYWJsYSBkZSBNZWRpYSwgTW9kYSB5IE1lZGlhbmEKCmBgYHtyfQoKc3VtbWFyeShiZDIpCgpzZChiZDIkQ2FudC4sIG5hLnJtPSBUUlVFKQoKCmhpc3QoYmQyJENhbnQuKQoKYGBgCgojIyMgIEdyw6FmaWNhIGRlIFJlbGFjaW9uIGRlIFNBQgoKYGBge3J9CgpnZ3Bsb3QoYmQyLCBhZXMoeD1GZWNoYSwgeT0gT3JpZ2VuKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0ib3JhbmdlIikgKyBzY2FsZV9maWxsX2dyZXkoKSArICMgQWRkIGJhcnMgdG8gdGhlIHBsb3QKICBsYWJzKHRpdGxlID0gIlJlbGFjacOzbiBTQUIiLCAjIEFkZCBhIHRpdGxlCiAgICAgICBzdWJ0aXRsZSA9ICJTY3JhcCBlbXByZXNhIEZPUk0iLCAjIEFkZCBhIHN1YnRpdGxlCiAgICAgICBjYXB0aW9uID0gIlJlbGFjacOzbiIsICMgQWRkIGEgY2FwdGlvbgogICAgICAgeCA9ICJ4IikKYGBgCgojIyMgIEdyw6FmaWNhIFNjcmFwIHBvciBvcmlnZW4KYGBge3J9CmdncGxvdChiZDIsYWVzKHg9Q2FudC4pKSsKICBnZW9tX2xpbmUoYWVzKHk9T3JpZ2VuKSxjb2xvcj0ib3JhbmdlIikrCiAgbGFicyh4PSJDYW50Iix5PSJPcmlnZW4iLCBjb2xvcj0iTGVnZW5kIikrCiAgIGdndGl0bGUoIk1heW9yZXMgY2F0aWRhZGVzIGRlIFNjcmFwIHBvciBvcmlnZW4iKQpgYGAKCgojIyMgIEdyw6FmaWNhIEN1YWxpdGF0aXZhCgpgYGB7cn0KCnBpZSh0YWJsZShiZDIkT3JpZ2VuKSkKCmBgYAoKIyMjICBHcsOhZmljYSBDdWFudGl0YXRpdmEKCmBgYHtyfQoKYmFycGxvdCh0YWJsZShiZDIkQ2FudC4sYmQyJE9yaWdlbiksIGNvbD0ib3JhbmdlIiwgbWFpbiA9ICJLaWxvcyBkZSBTY3JhcCIsIHhsYWIgPSAiT3JpZ2VuIiwgeWxhYiA9ICJLaWxvcyIgKQoKYGBgCgoKQXF1w60gcG9kZW1vcyBvYnNlcnZhciBjb21vIGxhIG1heW9yIGNhbnRpZGFkIGRlIHNjcmFwIGVzIGdlbmVyYWRhIGVuIGVsIMOhcmVhIGRlIFNBQiAvIFByZSBwcm9kdWNjacOzbiBkZSBsYSBlbXByZXNhLCBjb25jbHV5ZW5kbyBxdWUgc2UgdGllbmVuIHF1ZSB0b21hciBtZWRpZGFzIHBhcmEgcG9kZXIgcmVkdWNpciBlc3RhcyBjYW50aWRhZGVzIGxvIG3DoXhpbW8gcG9zaWJsZSBxdWl6w6EgdXNhbmRvIGVsIG1hdGVyaWFsIGRlIG1hbmVyYSBvcHRpbWEgcGFyYSBldml0YXIgdGFudG8gU2NyYXAuCgojIyMgIFRhYmxhIGRlIGZyZWN1ZW5jaWEgcG9yIGRpc3RyaWJ1Y2nDs24gZGUgb3JpZ2VuIApgYGB7cn0KCiNpbnN0YWxsLnBhY2thZ2VzKCdlcGlEaXNwbGF5JykKbGlicmFyeShlcGlEaXNwbGF5KQoKdGFiMShiZDIkT3JpZ2VuLCBzb3J0Lmdyb3VwID0gImRlY3JlYXNpbmciLCBjdW0ucGVyY2VudCA9IFRSVUUpCmBgYAoKClNlIHB1ZWRlIGNvbmNsdWlyIGRlIGVzdG9zIGdyw6FmaWNvcyBxdWUgc2UgdGllbmUgbXVjaG8gc2NyYXAgZW4gbGEgZW1wcmVzYSBwcmluY2lwYWxtZW50ZSBlbiBsYSBldGFwYSBkZSBwcmUtcHJvZHVjY2nDs24sIGFxdcOtIGxvIHF1ZSBzZSByZWNvbWllbmRhIGVzIG1lZGllciBleGFjdGFtZW50ZSBsYSBjYW50aWRhZCBxdWUgc2UgcmVxdWllcmUgZGUgbWF0ZXJpYWwgcGFyYSBwb2RlciBldml0YXIgdGVuZXIgZXNvcyBkZXNwZXJkaWNpb3MuIEFuYWxpemFuZG8gZXN0YXMgdmFyaWFibGVzIHNlIGNvbmZpcm1hIHF1ZSBlbiBlbCDDoXJlYSBkZSBwcmUtcHJvZHVjY2nDs24gZXMgZG9uZGUgc2UgZ2VuZXJhIGxhIG1heW9yIHBhcnRlIGRlbCBzY3JhcCBlbiBzdSBtYXlvcsOtYSBxdWUgZXMgY2FzaSBlbCA4NSUgZGUgc2NyYXAgcXVlIHNlIGdlbmVyYSBkZW50cm8gZGUgbGEgZW1wcmVzYS4gCgojIyAgU2VjY2nDs24gMi4yIAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBvcmFuZ2UiID4gTW9kw6lsbyBQcmVkaWN0aXZvIDwvc3Bhbj4KCgojIyMgSW1wb3J0YXIgbGEgYmFzZSBkZSBkYXRvcwoKYGBge3J9CgpleHRlcm5hPC0gcmVhZC5jc3YoIi9Vc2Vycy9qb3NlcmFtb252YXpxdWV6Z3V6bWFuL0RvY3VtZW50cy9UZWNub2xvzIFnaWNvIGRlIE1vbnRlcnJleS9TZXB0aW1vIHNlbWVzdHJlL0FuYWxpzIF0aWNhIGRlIGRhdG9zIC9SRVRPL0Jhc2VzIGRlIGRhdG9zIGZpbmFsZXMvQmFzZSBleHRlcm5hIC91c19tb3Rvcl9wcm9kdWN0aW9uX2FuZF9kb21lc3RpY19zYWxlcy5jc3YiKQpzdW1tYXJ5KGV4dGVybmEpCmBgYAoKIyMgUmVhbGl6YXIgcmVncmVzacOzbiAxCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJlZ3Jlc2lvbiA8LSBsbShQcm9kdWN0aW9uX0NvbW1lcmNpYWxfVmVoaWNsZXMgfiBVU19VbmVtcGxveW1lbnQgKyBVU19Db25zdW1lcl9Db25maWRlbmNlICsgVVNfTWluX0hvdXJfV2FnZSAsIGRhdGE9ZXh0ZXJuYSkKc3VtbWFyeShyZWdyZXNpb24pCmBgYAoKKipBbmFsaXphciBlbCBjb21wb3J0YW1pZW50byBkZSBsYXMgdmFyaWFibGVzIGluZGVwZW5kaWVudGVzIGVuIGxhIHJlZ3Jlc2nDs24qKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQplZmZlY3RfcGxvdChyZWdyZXNpb24scHJlZD1VU19Db25zdW1lcl9Db25maWRlbmNlLGludGVydmFsPVRSVUUpCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZWZmZWN0X3Bsb3QocmVncmVzaW9uLHByZWQ9VVNfVW5lbXBsb3ltZW50LGludGVydmFsPVRSVUUpCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZWZmZWN0X3Bsb3QocmVncmVzaW9uLHByZWQ9VVNfTWluX0hvdXJfV2FnZSxpbnRlcnZhbD1UUlVFKQpgYGAKCgoqKkFsIHNlciBsYSBQcm9kdWNjacOzbiBkZSBBdXRvcyBDb21lcmNpYWxlcyBsYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSwgb2JzZXJ2YW1vcyBjb21vIGVsIHNhbGFyaW8sIGxhIGNvbmZpYW56YSBkZWwgY29uc3VtaWRvciB5IGVsIGRlc2VtcGxlbyBnZW5lcmFuIGNhbWJpb3MgZW4gZWxsYS4gUG9kZW1vcyB2ZXIgcXVlIGVsIHF1ZSBtYXlvciBpbXBhY3RvIHF1ZSB0aWVuZSBlcyBsYSBjb25maWFuemEgZGVsIGNvbnN1bWlkb3IuIFRhbWJpw6luIHBvZGVtb3MgdmVyIHN1IGNvbXBvcnRhbWllbnRvIGVuIGxhIGdyw6FmaWNhIGNvbW8gc2kgbGEgcHJvZHVjY2nDs24gc3ViZSwgaWd1YWxtZW50ZSBsYSBjb25maWFuemEgZGVsIGNvbnN1bWlkb3IuKiogIAoKIyMgUmVhbGl6YXIgcmVncmVzacOzbiAyIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpyZWdyZXNpb24yIDwtIGxtKFByb2R1Y3Rpb25fUGFzc2VuZ2VyX0NhcnMgfiBVU19VbmVtcGxveW1lbnQgKyBVU19Db25zdW1lcl9Db25maWRlbmNlICsgVVNfTWluX0hvdXJfV2FnZSAsIGRhdGE9ZXh0ZXJuYSkKc3VtbWFyeShyZWdyZXNpb24yKQpgYGAKCioqQW5hbGl6YXIgZWwgY29tcG9ydGFtaWVudG8gZGUgbGFzIHZhcmlhYmxlcyBpbmRlcGVuZGllbnRlcyBlbiBsYSByZWdyZXNpw7NuKioKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZWZmZWN0X3Bsb3QocmVncmVzaW9uMixwcmVkPVVTX0NvbnN1bWVyX0NvbmZpZGVuY2UsaW50ZXJ2YWw9VFJVRSkKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQplZmZlY3RfcGxvdChyZWdyZXNpb24yLHByZWQ9VVNfVW5lbXBsb3ltZW50LGludGVydmFsPVRSVUUpCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZWZmZWN0X3Bsb3QocmVncmVzaW9uMixwcmVkPVVTX01pbl9Ib3VyX1dhZ2UsaW50ZXJ2YWw9VFJVRSkKYGBgCgogICoqTGEgcHJvZHVjY2nDs24gZGUgYXV0b3MgZGUgcGFzYWplcm8gdGllbmUgZXN0aW1hZG9zIG5lZ2F0aXZvcyBlbiBsYXMgdmFyaWFibGVzIGluZGVwZW5kaWVudGVzIGRlbCBkZXNlbXBsZW8geSBjb25maWFuemEgZGVsIGNvbnN1bWlkb3IsIHBvciBlc3RhIHJhesOzbiBzdSBjb21wb3J0YW1pZW50byBlbiBsYXMgZ3LDoWZpY2FzIGEgcGVzYXIgZGUgcXVlIGV4aXN0YSB1bmEgcHJvZHVjY2nDs24gYWx0YSBzdSB0ZW5kZW5jaWEgdmEgcGFyYSBhYmFqby4qKgogIAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBvcmFuZ2UiID4gIFByb27Ds3N0aWNvIDwvc3Bhbj4gCgojIyMgIFByb27Ds3N0aWNvIE1FWCAKCmBgYHtyfQojZmlsZS5jaG9vc2UoIi9Vc2Vycy9tYWMvRG93bmxvYWRzL21leGljbyBleHRlcm5hLmNzdiIpCk1leGljbzwtIHJlYWRfY3N2KCIvVXNlcnMvam9zZXJhbW9udmF6cXVlemd1em1hbi9Eb2N1bWVudHMvVGVjbm9sb8yBZ2ljbyBkZSBNb250ZXJyZXkvU2VwdGltbyBzZW1lc3RyZS9BbmFsacyBdGljYSBkZSBkYXRvcyAvUkVUTy9CYXNlcyBkZSBkYXRvcyBmaW5hbGVzL0Jhc2UgZXh0ZXJuYSAvbWV4aWNvIGV4dGVybmEuY3N2IikKYGBgCgojIyMgTGxhbWFyIExpYnJlcmlhcwpgYGB7cn0KbGlicmFyeShmb3JlY2FzdCkKYGBgCgojIyMjIENyZWFyIHNlcmllIGRlIHRpZW1wbwoKYGBge3J9Ck1leGljbyA8LSBjKDMzOTkwNzYsMzQ2NTYxNSwzOTMzMTU0LDM5MTg2MDMsMzgxMTA2OCwzMDQwMTc4LDMwMjg0ODEpCgpwcm9kdWNjaW9uX3N0IDwtIHRzKGRhdGEgPSBNZXhpY28sIHN0YXJ0ID0gYygyMDE1LDEpLCBmcmVxdWVuY3kgPSAxKQpwcm9kdWNjaW9uX3N0CmBgYAoKCiMjIyMgR3JhZmljYXIgUHJvbm9zdGljbwoKYGBge3J9Cm1vZGVsbyA8LSBhdXRvLmFyaW1hKHByb2R1Y2Npb25fc3QpCm1vZGVsbwoKcHJvbm9zdGljbyA8LSBmb3JlY2FzdChtb2RlbG8sIGxldmVsPWMoOTUpLCBoPTMpCnByb25vc3RpY28KCnBsb3QocHJvbm9zdGljbykKYGBgCgpBcXXDrSBwb2RlbW9zIG9ic2VydmFyIHF1ZSBwYXJhIGxvcyBwcsOzeGltb3MgdHJlcyBhw7FvcyB0ZW5lbW9zIHVuIGF1bWVudG8gZW4gbGEgcHJkb2R1Y2Npw7NuIGRlIGF1dG9zIGRlbnRybyBkZWwgcGHDrXMsIMOpc3RhIHR1dm8gdW4gZGVjcmVtZW50byBwb3IgY2F1c2EgZGUgbGEgcGFuZGVtaWEgZW4gbG9zIHRyZXMgYcOxb3MgcGFzYWRvcyBwZXJvIHNlIHByb25vc3RpY2EgcXVlIGVzdGEgYXVtZW50ZS4gCgojIyMgIFByb27Ds3N0aWNvIEVVQSBUT1RBTCBQUk9EVUNUSU9OCgpgYGB7cn0KI2ZpbGUuY2hvb3NlKCIvVXNlcnMvbWFjL0Rvd25sb2Fkcy91c19tb3Rvcl9wcm9kdWN0aW9uX2FuZF9kb21lc3RpY19zYWxlcyAoMikuY3N2IikKRVVBPC0gcmVhZF9jc3YoIi9Vc2Vycy9qb3NlcmFtb252YXpxdWV6Z3V6bWFuL0RvY3VtZW50cy9UZWNub2xvzIFnaWNvIGRlIE1vbnRlcnJleS9TZXB0aW1vIHNlbWVzdHJlL0FuYWxpzIF0aWNhIGRlIGRhdG9zIC9SRVRPL0Jhc2VzIGRlIGRhdG9zIGZpbmFsZXMvQmFzZSBleHRlcm5hIC91c19tb3Rvcl9wcm9kdWN0aW9uX2FuZF9kb21lc3RpY19zYWxlcy5jc3YiKQpgYGAKCiMjIyMgTGxhbWFyIExpYnJlcmlhcwpgYGB7cn0KbGlicmFyeShmb3JlY2FzdCkKYGBgCgoKIyMjIyBDcmVhciBzZXJpZSBkZSB0aWVtcG8KYGBge3J9CkVVQSA8LSBjKDEwNzUyLDg2NzIsNTcxMCw3NzQ0LDg2NjIsMTAzMzYsMTEwNjcsMTE2MTEsMTIxMDYsMTIxNzksMTExNzksMTEyOTcsMTA4OTMsODgyMSkKCnByb2R1Y2Npb25fc3QxIDwtIHRzKGRhdGEgPSBFVUEsIHN0YXJ0ID0gYygyMDA3LDEpLCBmcmVxdWVuY3kgPSAxKQpwcm9kdWNjaW9uX3N0MQpgYGAKCgojIyMjIEdyYWZpY2FyIFByb25vc3RpY28KYGBge3J9Cm1vZGVsbzEgPC0gYXV0by5hcmltYShwcm9kdWNjaW9uX3N0MSkKbW9kZWxvMQoKcHJvbm9zdGljbzEgPC0gZm9yZWNhc3QobW9kZWxvMSwgbGV2ZWw9Yyg5NSksIGg9MykKcHJvbm9zdGljbzEKCnBsb3QocHJvbm9zdGljbzEpCmBgYAoKRW4gY3VhbnRvIGEgbGEgcHJvZHVjY2nDs24gdG90YWwgZGUgYXV0b3MgZW4gRXN0YWRvcyBVbmlkb3MgcG9kZW1vcyBvYnNldmFyIHF1ZSBkZWwgMjAxMCBhbCAyMDE5IHR1dmllcm9uIHVuIGF1bWVudG8gc2lnbmlmaWNhdGl2byBlbiBzdSBwcm9kdWNjacOzbiwgeSBwYXJhIDIwMjAgdHV2byB1bmEgY2HDrWRhIGEgY2F1c2EgZGUgbGEgcGFuZGVtaWEsIHNlIHByb25vc3RpY2EgcXVlIHBhcmEgMjAyMyAgZXN0YSBwcm9kdWNjacOzbiBzaWdhIGJhamEgcGVybyBxdWUgZGVzcHXDqXMgZXN0YSB5YSBlbXBpZWNlIGEgYXVtbmV0YXIuCgojIyMgUHJvbsOzc3RpY28gRVVBIERPTUVTVElDIFNBTEVTCgpgYGB7cn0KCiNmaWxlLmNob29zZSgiL1VzZXJzL21hYy9Eb3dubG9hZHMvdXNfbW90b3JfcHJvZHVjdGlvbl9hbmRfZG9tZXN0aWNfc2FsZXMgKDIpLmNzdiIpCkVVQTE8LSByZWFkX2NzdigiL1VzZXJzL2pvc2VyYW1vbnZhenF1ZXpndXptYW4vRG9jdW1lbnRzL1RlY25vbG/MgWdpY28gZGUgTW9udGVycmV5L1NlcHRpbW8gc2VtZXN0cmUvQW5hbGnMgXRpY2EgZGUgZGF0b3MgL1JFVE8vQmFzZXMgZGUgZGF0b3MgZmluYWxlcy9CYXNlIGV4dGVybmEgL3VzX21vdG9yX3Byb2R1Y3Rpb25fYW5kX2RvbWVzdGljX3NhbGVzLmNzdiIpCgpgYGAKCgojIyMjIExsYW1hciBMaWJyZXJpYXMKYGBge3J9CmxpYnJhcnkoZm9yZWNhc3QpCmBgYAoKCiMjIyMgQ3JlYXIgc2VyaWUgZGUgdGllbXBvCmBgYHtyfQpFVUExIDwtIGMoMTI2ODcsMTAxMDgsNzg2OCw5MDIwLDEwMTA5LDExNTgyLDEyNDc5LDEzMzg5LDE0MTI4LDEzOTY5LDEzNjQ0LDEzNzExLDEzNjc3LDExNTcxKQoKcHJvZHVjY2lvbl9zdDIgPC0gdHMoZGF0YSA9IEVVQTEsIHN0YXJ0ID0gYygyMDA3LDEpLCBmcmVxdWVuY3kgPSAxKQpwcm9kdWNjaW9uX3N0MgpgYGAKCgojIyMjIEdyYWZpY2FyIFByb25vc3RpY28KYGBge3J9Cm1vZGVsbzIgPC0gYXV0by5hcmltYShwcm9kdWNjaW9uX3N0MikKbW9kZWxvMgoKcHJvbm9zdGljbzIgPC0gZm9yZWNhc3QobW9kZWxvMiwgbGV2ZWw9Yyg5NSksIGg9MykKcHJvbm9zdGljbzIKCnBsb3QocHJvbm9zdGljbzIpCmBgYAoKCiMjIyAgUHJvbsOzc3RpY28gTUVSTUEgCgojIyMgIFN1bWFyIGVsIFRvdGFsIGRlIEtpbG9zeE1lcwpgYGB7cn0Kc3VtKGJkJEtpbG9zRW5lcm8pCnN1bShiZCRLaWxvc0ZlYnJlcm8pCnN1bShiZCRLaWxvc01hcnpvKQpzdW0oYmQkS2lsb3NBYnJpbCkKc3VtKGJkJEtpbG9zTWF5bykKc3VtKGJkJEtpbG9zSnVuaW8pCnN1bShiZCRLaWxvc0p1bGlvKQpzdW0oYmQkS2lsb3NBZ29zdG8pCnN1bShiZCRLaWxvc1NlcHRpZW1icmUpCmBgYAoKIyMjICBDcmVhciBzZXJpZSBkZSB0aWVtcG8KYGBge3J9Cm1lcm1hIDwtIGMoMTQ1NjAsMjI4MzAsMjI0NzAsMTg4MjAsMjM0MTAsMTgyODAsMTkzNzAsMzIxMDAsMTM1ODYpCgpwcm9kdWNjaW9uX3N0IDwtIHRzKGRhdGEgPSBtZXJtYSwgc3RhcnQgPSBjKDIwMjIsMSksIGZyZXF1ZW5jeSA9IDEyKQpwcm9kdWNjaW9uX3N0CmBgYAoKIyMjICBHcmFmaWNhciBQcm9ub3N0aWNvCmBgYHtyfQpsaWJyYXJ5KGZvcmVjYXN0KQptb2RlbG8gPC0gYXV0by5hcmltYShwcm9kdWNjaW9uX3N0KQptb2RlbG8KCnByb25vc3RpY28gPC0gZm9yZWNhc3QobW9kZWxvLCBsZXZlbD1jKDk1KSwgaD0zKQpwcm9ub3N0aWNvCgpwbG90KHByb25vc3RpY28pCmBgYAoKU2UgcHJvbm9zdGljYSBxdWUgZW4gb2N0dWJyZSBsYSBtZXJtYSBhY3VtdWxhZGEgc2UgbWFudGVuZ2EgZW4gYWxyZWRlZG9yIDIwMDAga2lsb3MgYXByb3hpbWFkYW1lbnRlLCBzaWVuZG8gbcOhcyBiYWpvIHF1ZSBtZXNlcyBhbnRlcmlvcmVzLiBQb3IgbG8gcXVlIHNlIHByb3BvbmUgcmVkdWNpciBsYSBtZXJtYSB0b2RhdsOtYSB1biAxNSAlIG3DoXMgbyAyMCUgcGFyYSByZWR1Y2lybGEgYSAxNTAwIGtpbG9zIHBhcmEgcHLDs3hpbW8gbWVzLgoKCgoKCgoKIyMgIFNlY2Npw7NuIDMgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IG9yYW5nZSIgPiBLLW1lYW5zIENsdXN0ZXJzICA8L3NwYW4+CiAKIAojIyBEZWZpbmljacOzbiBkZSBjb25jZXB0b3MgCgpDb25jZXB0b3MgcXVlIGNvbnRyaWJ1eWVuIGEgbGEgaWRlbnRpZmljYWNpw7NuIGRlIGNsdXN0ZXJzIHVzYW5kbyBhbmFsw610aWNhIGRlIGRhdG9zLiAKCioqSS4gSy0gTWVhbnMgQ2x1c3RlcmluZyoqICAKSy0gbWVhbnMgY2x1c3RlcmluZyB0aWVuZSBjb21vIG9iamV0aXZvIGFncnVwYXIgZGF0b3MgY29uIGNhcmFjdGVyw61zdGljYXMgc2ltaWxhcmVzIGVuIGVsIG1pc21vIGNsdXN0ZXIuIFVubyBkZSBsb3MgYmVuZWZpY2lvcyBtw6FzIGdyYW5kZXMgZGUgbGEgaGVycmFtaWVudGEgZXMgcXVlIHNlIHB1ZWRlbiByZXN1bWlyIGRhdG9zIGRlIGdyYW4gZGltZW5zacOzbi4gIAoKCioqSUkuIFVuc3VwZXJ2aXNlZCBMZWFybmluZyoqICAKTm8gc2UgYXNpZ25hbiBldGlxdWV0YXMgYWwgYWxnb3JpdG1vIGRlIGFwcmVuZGl6YWplLCBkZWrDoW5kb2xvIHNvbG8gcGFyYSBlbmNvbnRyYXIgbGEgZXN0cnVjdHVyYSBlbiBzdSBlbnRyYWRhLiAgRWwgYXByZW5kaXphamUgbm8gc3VwZXJ2aXNhZG8gcHVlZGUgc2VyIHVuIGZpbiBlbiBzw60gbWlzbW8gKGRlc2N1YnJpciBwYXRyb25lcyBvY3VsdG9zIGVuIGxvcyBkYXRvcykgbyB1biBtZWRpbyBwYXJhIHVuIGZpbiAoYXByZW5kaXphamUgZGUgZnVuY2lvbmVzKS4gIAoKKipJSUkuIEV1Y2xpZWRlYW4gRGlzdGFuY2UqKiAgCkxhIGRpc3RhbmNpYSBFdWNsaWRpYW5hIGVzIGVsIGPDoWxjdWxvIGRlIGRpc3RhbmNpYSBjb23Dum5tZW50ZSB1dGlsaXphZG8gcGFyYSBtZWRpciBsYSBkaXN0YW5jaWEgZW50cmUgZG9zIHB1bnRvcyBkZSBkYXRvcy4gICAKCgojIyBDbHVzdGVyIGVkYWQgeSBzYWxhcmlvIGRpYXJpbwoKIyMjICBMZWVyIGxhIGJhc2UgZGUgZGF0b3MgCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJhamFzZGF0YSA8LXJlYWQuY3N2KCIvVXNlcnMvam9zZXJhbW9udmF6cXVlemd1em1hbi9Eb2N1bWVudHMvVGVjbm9sb8yBZ2ljbyBkZSBNb250ZXJyZXkvU2VwdGltbyBzZW1lc3RyZS9BbmFsacyBdGljYSBkZSBkYXRvcyAvUkVUTy9CYXNlcyBkZSBkYXRvcyBmaW5hbGVzL1JIL1JIQkFKQVNMSU1QSUExLmNzdiIpCnN1bW1hcnkoYmFqYXNkYXRhKQpgYGAKCiMjIyAgTGltcGllemEuIFNlbGVjY2lvbmFyIHZhcmlhYmxlcyByZWxldmFudGVzCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJhamFzZGF0YTE8LWJhamFzZGF0YQpiYWphc2RhdGExPC1zdWJzZXQoYmFqYXNkYXRhLHNlbGVjdCA9IC1jKEdlbixGZWNoYV9hbHRhLE1CLFB1ZXN0RGVzLEVzdGFkbyxOb20sQ29sLE11bixCYWphLCBFc3RDaXYsIETDrWFzX3RyYWIpKQpzdW1tYXJ5KGJhamFzZGF0YTEpCmBgYAoKIyMjICBMaW1waWV6YS4gRWxpbWluYXIgZWRhZCAwCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJhamFzZGF0YTIgPC0gYmFqYXNkYXRhMQpiYWphc2RhdGEyIDwtIGJhamFzZGF0YTIgW2JhamFzZGF0YTIkRWRhZD4gbWluKDEpLCBdCnN1bW1hcnkoYmFqYXNkYXRhMikKYGBgCgojIyMgIE5vcm1hbGl6YXIgbGEgYmFzZSBkZSBkYXRvcyAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KYmFqYXNfZGF0YV9ub3JtIDwtIHNjYWxlKGJhamFzZGF0YTJbMToyXSkKYGBgCgojIyMgIElkZW50aWZpY2FyIG7Dum1lcm8gZGUgY2x1c3RlcnMKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZnZpel9uYmNsdXN0KGJhamFzX2RhdGFfbm9ybSwga21lYW5zLCBtZXRob2Q9IndzcyIpKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9NCwgbGluZXR5cGU9MikrICAgICAgICAgICAKICBsYWJzKHN1YnRpdGxlID0gIkVsYm93IG1ldGhvZCIpICAKYGBgCgojIyMgIFZpc3VhbGl6YXIgZWwgY2x1c3RlcgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQplZGFkX2NsdXN0ZXIxPC1rbWVhbnMoYmFqYXNfZGF0YV9ub3JtLDMpCmVkYWRfY2x1c3RlcjEKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpmdml6X2NsdXN0ZXIoZWRhZF9jbHVzdGVyMSxkYXRhPWJhamFzX2RhdGFfbm9ybSkKYGBgCgojIyMgIEFuw6FsaXNpcyBkZSBjbHVzdGVycwpgYGB7ciB3YXJuaW5nPUZBTFNFfQoKYmFqYXNkYXRhMzwtIGJhamFzZGF0YTIKYmFqYXNkYXRhMyRDbHVzdGVyczwtZWRhZF9jbHVzdGVyMSRjbHVzdGVyCmJhamFzZGF0YTQ8LWJhamFzZGF0YTMgJT4lIGdyb3VwX2J5KENsdXN0ZXJzKSAlPiUgc3VtbWFyaXNlKEVkYWQ9bWF4KEVkYWQpKSAlPiUgYXJyYW5nZShkZXNjKEVkYWQpKQpiYWphc2RhdGEzJENsdXN0ZXJfTmFtZXM8LWZhY3RvcihiYWphc2RhdGEzJENsdXN0ZXJzLGxldmVscyA9IGMoMSwyLDMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkFkdWx0byIsICJKb3ZlbiIsICJKdWJpbGFjacOzbiIpKQoKCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KYmFqYXNkYXRhNSA8LSBiYWphc2RhdGEzICU+JSBkcGx5cjo6IGdyb3VwX2J5KENsdXN0ZXJfTmFtZXMpICU+JSBkcGx5cjo6IHN1bW1hcml6ZShlZGFkX2HDsW9zPW1heChFZGFkKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTYWxfSU1TUz1tZWFuKFNhbF9JTVNTKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50PW4oKSkKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjbHVzdGVyczwtYXMuZGF0YS5mcmFtZShiYWphc2RhdGE1KQpjbHVzdGVycwpgYGAKCiMjIyAgR3LDoWZpY28gZGUgYmFycmFzIGRlIGxhcyBiYWphcyBjb24gZWRhZCBtw6F4aW1hIGRlIGNsdXN0ZXIKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KGJhamFzZGF0YTUsIGFlcyh4PUNsdXN0ZXJfTmFtZXMseT1lZGFkX2HDsW9zLGZpbGw9IENsdXN0ZXJfTmFtZXMsbGFiZWw9cm91bmQoZWRhZF9hw7FvcyxkaWdpdHM9MikpKSArIAogIGdlb21fY29sKCkgKyAKICBnZW9tX3RleHQoKQpgYGAKCiMjIyAgR3LDoWZpY28gZGUgYmFycmFzIGRlIGxhcyBiYWphcyBjb24gc3Ugc2FsYXJpbwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoYmFqYXNkYXRhNSxhZXMoeD1DbHVzdGVyX05hbWVzLHk9U2FsX0lNU1MgLGZpbGw9IENsdXN0ZXJfTmFtZXMsbGFiZWw9cm91bmQoU2FsX0lNU1MsZGlnaXRzPTIpKSkgKyAKICBnZW9tX2NvbCgpICsgIAogIGdlb21fdGV4dCgpCmBgYAoKIyMgRGlzcGVyc2nDs24gZGUgbGEgZWRhZApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoYmFqYXNkYXRhMywgYWVzKHg9Q2x1c3Rlcl9OYW1lcywgeT1FZGFkLCBmaWxsPUNsdXN0ZXJfTmFtZXMpKSArCiAgZ2VvbV9ib3hwbG90KCkrCiAgZ2d0aXRsZSgiRGlzcGVyc2lvbiBvZiAnRWRhZCcgYnkgQ2x1c3RlcnMgTmFtZXMiKQpgYGAKCiMjIyAgRGlzcGVyc2nDs24gZGVsIHNhbGFyaW8gZGlhcmlvCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdChiYWphc2RhdGEzLCBhZXMoeD1DbHVzdGVyX05hbWVzLCB5PVNhbF9JTVNTLCBmaWxsPUNsdXN0ZXJfTmFtZXMpKSArCiAgZ2VvbV9ib3hwbG90KCkrCiAgZ2d0aXRsZSgiRGlzcGVyc2lvbiBvZiAnU2FsYXJpb19EaWFyaW8nIGJ5IENsdXN0ZXJzIE5hbWVzIikKYGBgCgojIyAgQ2x1c3RlciBlZGFkIHkgZMOtYXMgbGFib3JhZG9zCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpSSEJBSkFTIDwtcmVhZC5jc3YoIi9Vc2Vycy9qb3NlcmFtb252YXpxdWV6Z3V6bWFuL0RvY3VtZW50cy9UZWNub2xvzIFnaWNvIGRlIE1vbnRlcnJleS9TZXB0aW1vIHNlbWVzdHJlL0FuYWxpzIF0aWNhIGRlIGRhdG9zIC9SRVRPL0Jhc2VzIGRlIGRhdG9zIGZpbmFsZXMvUkgvUkhCQUpBU0xJTVBJQTEuY3N2IikKYGBgCgojIyMgIEFuYWxpemFyIGJhc2UgZGUgZGF0b3MuCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnN1bW1hcnkoUkhCQUpBUykKc3RyKFJIQkFKQVMpCmRlc2NyaWJlKFJIQkFKQVMpCmBgYAoKIyMjICBFZGFkIHZzIGRpYXMgbGFib3JhZG9zLUNsdXN0ZXJzCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClJIQkFKQVMxPC1SSEJBSkFTClJIQkFKQVMxPC1zdWJzZXQoUkhCQUpBUzEsc2VsZWN0ID0gLWMoR2VuLEZlY2hhX2FsdGEsTUIsUHVlc3REZXMsRXN0YWRvLE5vbSxDb2wsTXVuLEJhamEpKQpzdW1tYXJ5KFJIQkFKQVMxKQpgYGAKCiMjIyAgRWxpbWluYXIgcmVuZ2xvbmVzIApFbGltaW5hbW9zIGRvcyByZWdsb25lcyBxdWUgdGVuaWFuIGNvbW8gZWRhZCAoMCkKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KUkhCQUpBUzIgPC0gUkhCQUpBUzEKUkhCQUpBUzIgPC0gUkhCQUpBUzIgW1JIQkFKQVMyJEVkYWQ+IG1pbigxKSwgXQpzdW1tYXJ5KFJIQkFKQVMyKQpgYGAKCiMjIyAgTm9ybWFsaXphciBsYSBiYXNlIGRlIGRhdG9zCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClJIX0VEQURfTk9STTwtc2NhbGUoUkhCQUpBUzJbMToyXSkKYGBgCgojIyMgIFNlIHZpc3VhbGl6YW4gZWwgIyBjb3JyZWN0byBkZSBjbHVzdGVycyBhIHJlYWxpemFyCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmZ2aXpfbmJjbHVzdChSSF9FREFEX05PUk0sIGttZWFucywgbWV0aG9kPSJ3c3MiKSsgCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTQsIGxpbmV0eXBlPTIpKyAgICAgICAgIAogIGxhYnMoc3VidGl0bGUgPSAiRWxib3cgbWV0aG9kIikgIAoKUkhFREFEX0NsdXN0ZXIxPC1rbWVhbnMoUkhfRURBRF9OT1JNLDQpClJIRURBRF9DbHVzdGVyMQpgYGAKCiMjIyAgVmlzdWFsaXphciBlbCBjbHVzdGVyCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmZ2aXpfY2x1c3RlcihSSEVEQURfQ2x1c3RlcjEsZGF0YT1SSF9FREFEX05PUk0pCmBgYAoKIyMjICBBbsOhbGlzaXMgcHJvZnVuZG8gZGVsIENsdXN0ZXIKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KUkhCQUpBUzMgPC0gUkhCQUpBUzIKUkhCQUpBUzMkQ2x1c3RlcnM8LVJIRURBRF9DbHVzdGVyMSRjbHVzdGVyClJIQkFKQVM0PC1SSEJBSkFTMyAlPiUgZ3JvdXBfYnkoQ2x1c3RlcnMpICU+JSBzdW1tYXJpc2UoRWRhZD1tYXgoRWRhZCkpICU+JSBhcnJhbmdlKGRlc2MoRWRhZCkpClJIQkFKQVMzJENsdXN0ZXJfTmFtZXM8LWZhY3RvcihSSEJBSkFTMyRDbHVzdGVycyxsZXZlbHMgPSBjKDEsMiwzLDQpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkFkdWx0byIsICJQcmluY2lwaWFudGUiLCAiTWF5b3IiLCAiSnV2ZW5pbCIpKQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClJIQkFKQVM2IDwtIFJIQkFKQVMzICU+JSBncm91cF9ieShDbHVzdGVyX05hbWVzKSAlPiUgZHBseXI6OiBzdW1tYXJpemUoZWRhZF9hw7Fvcz1tYXgoRWRhZCksIApEw61hc190cmFiPW1lYW4oRMOtYXNfdHJhYiksCkNvdW50PW4oKSkKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjbHVzdGVyczwtYXMuZGF0YS5mcmFtZShSSEJBSkFTNikKY2x1c3RlcnMKYGBgCgoKIyMjICBBbsOhbGlzaXMgZGUgZGF0b3MgZGVsIGNsdXN0ZXIgZXhwcmVzYWRvcyBwb3IgZ3LDoWZpY2FzCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoUkhCQUpBUzYsYWVzKHg9cmVvcmRlcihDbHVzdGVyX05hbWVzLENvdW50KSx5PUNvdW50LGZpbGw9Q2x1c3Rlcl9OYW1lcykpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpCmBgYAoKIyMjICBFZGFkZXMgKG3DoXhpbWFzKSwgYWwgaWd1YWwgc2UgcHVlZGUgcmVhbGl6YXIgY29uIHVuIGJhcnBsb3QKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KFJIQkFKQVM2LCBhZXMoeD1DbHVzdGVyX05hbWVzLHk9ZWRhZF9hw7FvcyxmaWxsPSBDbHVzdGVyX05hbWVzLGxhYmVsPXJvdW5kKGVkYWRfYcOxb3MsZGlnaXRzPTIpKSkgKyAKICBnZW9tX2NvbCgpICsgCiAgZ2VvbV90ZXh0KCkKYGBgCgojIyMgIETDrWFzIGxhYm9yYWRvcyAoTcOheGltb3MpCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdChSSEJBSkFTNixhZXMoeD1DbHVzdGVyX05hbWVzLHk9RMOtYXNfdHJhYixmaWxsPSBDbHVzdGVyX05hbWVzLGxhYmVsPXJvdW5kKETDrWFzX3RyYWIsZGlnaXRzPTIpKSkgKyAKICBnZW9tX2NvbCgpICsgCiAgZ2VvbV90ZXh0KCkKYGBgCgojIyMgIEdyw6FmaWNhIGRlIEJveHBsb3QgKEFuw6FsaXNpcyBkZSBsYXMgZWRhZGVzIGRlIGxvcyA0IGdydXBvcy4pCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdChSSEJBSkFTMywgYWVzKHg9Q2x1c3Rlcl9OYW1lcywgeT1FZGFkLCBmaWxsPUNsdXN0ZXJfTmFtZXMpKSArCiAgZ2VvbV9ib3hwbG90KCkrCiAgZ2d0aXRsZSgiRWRhZCAoRGlzcGVyc2lvbikiKQpgYGAKCiMjICBIYWxsYXpnb3MgaWRlbnRpZmljYWNvcyAKCkR1cmFudGUgZXN0YSBhY3RpdmlkYWQgcmVhbGl6YW1vcyB1biBhbsOhbGlzaXMgZW4gbGEgYmFzZSBkZSBkYXRvcyBkZSBSZWN1cnNvcyBIdW1hbm9zLCBlbmZvY2Fkb3MgZW4gbGFzIHZhcmlhYmxlcyBkZSBFZGFkLCBTYWxhcmlvIHkgRMOtYXMgVHJhYmFqYWRvcywgcG9yIGxvIHF1ZSBzZSBkZWNpZGnDsyBkZWZpbmlyIHZhcmlvcyBwYXNvcyBhIHNlZ3VpciBwYXJhIGxsZWdhciBhbCBvYmpldGl2byBkZXNlYWRvIHF1ZSBlcmEgZmluYWxtZW50ZSBsbGVnYXIgYSBsYSBjb25zdHJ1Y2Npw7NuIGRlIGxvcyBjbHVzdGVycy4gIAoKVG9tYW5kbyBlbiBjdWVudGEgbG9zIGhhbGxhemdvcyBkZSBsYSBlZGFkIHkgZWwgc2FsYXJpbyBkaWFyaW8sIHNlIGxsZWdvIGEgbGEgY29uY2x1c2nDs24gZGUgbG8gc2lndWllbnRlOiAgIAoKCjEuIEhheSBtw6FzIGJhamFzIGRlIGFkdWx0b3MgY29uIGVsIHJhbmdvIGRlIGVkYWRlcyBkZSA0MSBhIDYxLCBlbCBjdcOhbCBzZSBpZGVudGlmaWNvIGNvbW8ganViaWxhY2nDs24uICAgCgoyLiBMb3MgYWR1bHRvcyBkZSAzMy00MCBhw7FvcyBnYW5hbiBtw6FzIGNvbiB1biBzdWVsZG8gZGlhcmlvIGRlIDE4Ni4xNiBlbiBwcm9tZWRpby4gIAoKCkRlIGlndWFsIG1hbmVyYSBwb2RlbW9zIG9ic2VydmFyIGN1YXRybyBDbHVzdGVycyBxdWUgdG9tYW4gZW4gY3VlbnRhIGxhIGVkYWQgeSBsb3MgZMOtYXMgbGFib3JhZG9zOiAgCgoxLiBFbCBDbHVzdGVyIFJvam8gIkFkdWx0byIgZXMgdW4gZ3J1cG8gZW4gZWwgY3VhbCBzZSBvYnNlcnZhIHF1ZSBzb24gbGFzIHBlcnNvbmFzIGRlIGVkYWQgYWx0YSB5IGNvbiB1bmEgY2FyYWN0ZXLDrXN0aWNhIGVuIGNvbcO6biBxdWUgZXMgcXVlIGR1cmFuIHBvY28gdGllbXBvIGxhYm9yYW5kbyBlbiBsYSBlbXByZXNhLiAgCjIuIEVsIENsdXN0ZXIgQXp1bCAiTWF5b3IiIGVzIGVsIENsdXN0ZXIgcXVlIG3DoXMgc2UgYXBhcnRhIGRlIGxvcyBkZW3DoXMgQ2x1c3RlcnMgZGViaWRvIGEgcXVlIHNvbiBwZXJzb25hcyBjb24gbWF5b3IgcmFuZ28gZGUgZWRhZCB5IGxhIG1heW9yIHBhcnRlIGRlIGxvcyBlbXBsZWFkb3MgY3VlbnRhbiBjb24gZXN0YSBlZGFkLiAgCjMuIEVsIENsdXN0ZXIgTW9yYWRvICJKdXZlbmlsIiBkb25kZSBzZSBlbmN1ZW50cmFuIGxhcyBwZXJzb25hcyBjb24gdW4gcmFuZ28gZGUgZWRhZCBkZSBlbnRyZSAzMCB5IDM2IGHDsW9zLCBoYWJpZW5kbyBtw6FzIHBlcnNvbmFzIGVuIGVsIHJhbmdvIGRlIGxvcyAzMCBhIDMyIGHDsW9zLCAgCjQuIEVsIENsdXN0ZXIgVmVyZGUgIlByaW5jaXBpYW50ZSIgZXMgZWwgZ3J1cG8gZGUgcGVyc29uYXMgbcOhcyBqw7N2ZW5lcyBlbiBsYSBlbXByZXNhLCBjb24gdW4gcmFuZ28gZGUgZW50cmUgMjAgeSAzMCBhw7Fvcy4gIAoKCkVsIGdydXBvIHF1ZSBjdWVudGEgY29uIG3DoXMgZMOtYXMgbGFib3JhZG9zIGVzIGVsIGRlIGVkYWQgbcOheGltYSwgc2llbmRvIGxvcyBhZHVsdG9zLCBkZSBpZ3VhbCBtYW5lcmEgZXN0b3MgY3VlbnRhbiBjb24gdW4gc2FsYXJpbyBtYXlvci4gIApQb3Igw7psdGltbyBwb2RlbW9zIG9ic2VydmFyIHF1ZSBlbiBsb3MgZ3LDoWZpY29zIHF1ZSBzZSBhbmFsaXphbiBjb24gZXN0YXMgdmFyaWFibGVzIHRlbmVtb3MgbG9zIHNpZ3VpZW50ZXMgcHVudG9zIGEgY29uc2lkZXJhY2nDs246IAoKLSBFZGFkIE3DoXhpbWEgICAKCi0gRMOtYXMgTGFib3JhZG9zIE3DoXhpbW9zCgotIFJlY3VlbnRvIGRlIGxvcyBncnVwb3MgcXVlIHByZXNlbnRhbiBtYXlvciBhY3RpdmlkYWQgZW4gbGEgZW1wcmVzYS4KCi0gTGEgZGlzcGVyc2nDs24gZGUgZWRhZCBxdWUgZXhpc3RlIGVudHJlIGNhZGEgdW5vIGRlIGxvcyBncnVwb3MuIAoKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogb3JhbmdlIiA+IFNlY2Npw7NuIDQgIDwvc3Bhbj4KCiMjICBJZGVudGlmaWNhY2nDs24gZGUgcmVzdWx0YWRvcyByZWxldmFudGVzIHkgc3VnZXJlbmNpYXMgCgojIyMgICoqKlByaW5jaXBhbGVzIGhhbGxhemdvcyAqKioKCjEuICAqKlJIKio6IEVuIGN1YW50byBhbCBzYWxhcmlvIGRlbCBJTVNTIGVuIGVsIGfDqW5lcm8gZGUgbG9zIGVtcGxlYWRvcyB5IGRlcGVuZGllbmRvIGRlIHNpIHNvbiBjYXNhZG9zLCBkaXZvcmljYWRvcywgc29sdGVyb3MgbyBlc3RhbiBlbiB1bmnDs24gbGlicmUuIFNlIHB1ZWRlIGNvbmNsdWlyIHF1ZSBsYXMgbXVqZXJlcyB0aWVuZW4gZW4gcHJvbWVkaW8gZW4gZXN0YXMgY3VhdHJvIGNhdGVnb3LDrWFzIHVuIHNhbGFyaW8gbWF5b3IgYWwgZGUgbG9zIGhvbWJyZXMgeSBsb3Mgc29sdGVyb3MgdGllbmVuIHVuIG1heW9yIHNhbGFyaW8gY29tcGFyYWRvIGNvbiBsYXMgb3RyYXMgY2F0ZWdvcmlhcy4KCjIuICoqUHJvZHVjY2nDs24qKjogU2UgcHVlZGUgdmVyIHF1ZSBlbCBjbGllbnRlIHF1ZSBtw6FzIHBpZXphcyBwcm9ncmFtYWRhcyB0aWVuZSBlcyBZQU5GRU5HIGRlZGljYW5kb3NlbGUgdW4gdGllbXBvIGRlIGNhbGlkYWQgZGUgMS4xIG1pbnV0bywgbWllbnRyYXMgcXVlIGVsIGNsaWVudGUgVkwtMDE3LTE0ODYgZXMgZWwgY2xpZW50ZSBxdWUgdGllbmUgY2FzaSBsYSBtaXRhZCBkZSBwaWV6YXMgcHJvZ3JhbWFkYXMgeSBlcyBhbCBxdWUgbcOhcyB0aWVtcG8gc2UgbGUgZGVkaWNhIHRpZW1wby4gRXN0byBwdWVkZSBpbmRpY2FyIHF1ZSBzdXMgcGllemFzIHB1ZGllcmFuIHNlciBkZSBtdWNobyBtw6FyZ2VuIGRlIGVycm9yLgoKMy4gKipEZWxpdmVyeSBQbGFuOioqIEhlbGxhIGVzIGVsIGNsaWVudGUgY29uIG1heW9yIGNhbnRpZGFkIGRlIHVuaWRhZGVzIHkgYWRlbcOhcyBkZSBlc28gY3VlbnRhIGNvbiBhbGd1bm9zIG91dGxpZXJzIG11eSBwb3IgZW5jaW1hIGRlIGxhIG1lZGlhbiwgc2VndWlkbyBwb3IgVFJNWCBlbCBjdWFsIG5vIGN1ZW50YSBjb24gb3V0bGllcnMuCgo0LioqTWVybWE6KiogUG9kZW1vcyB2ZXIgY29tbyBlbiBBZ29zdG8gc2UgdHV2byB1biBwcm9tZWRpbyBkZSBtZXJtYSBwb3IgZMOtYSBzb2JyZXBhc2FuZG8gbG9zIDMwMDAga2lsb3MsIHNpZW5kbyBlc3RhIGdyw6FmaWNhIHJlbGV2YW50ZSBwYXJhIHBvZGVyIGlkZW50aWZpY2FyIGZhY3RvcmVzIGltcG9ydGFudGVzIHkgcmVkdWNpciBlc3RhcyBjYW50aWRhZGVzIGFwbGljYW5kbyBLUEnigJlzCgo1LiAqKkRlbGl2ZXJ5IFBlcmZvcm1hbmNlKio6IE1haGxlIGVzIGVsIGNsaWVudGUgY29uIG1heW9yIHJldHJhc28gc29icmUgcGFzYW5kbyBsb3MgNjAgbWludXRvcyBkZSByZXRyYXNvLCBtaWVudHJhcyBxdWUgUHJpbnRlbCBzaWVtcHJlIHNlIG1hbnRpZW5lIHBvciBkZWJham8gZGUgbG9zIDMwIG1pbnV0b3MuCgo2LiAqKlNjcmFwOioqIFNlIHRpZW5lIG11Y2hvIHNjcmFwIGVuIGxhIGVtcHJlc2EgcHJpbmNpcGFsbWVudGUgZW4gbGEgZXRhcGEgZGUgcHJlLXByb2R1Y2Npw7NuLCBsYSBtYXlvciBjYW50aWRhZCBkZSBzY3JhcCBlcyBnZW5lcmFkYSBlbiBlbCDDoXJlYSBkZSBTQUIgLyBQcmUgcHJvZHVjY2nDs24gZGUgbGEgZW1wcmVzYSwgcG9yIGxvIHF1ZSBzZSB0aWVuZW4gcXVlIHRvbWFyIG1lZGlkYXMgcGFyYSBwb2RlciByZWR1Y2lyIGVzdGFzIGNhbnRpZGFkZXMgbG8gbcOheGltbyBwb3NpYmxlIHF1aXrDoSB1c2FuZG8gZWwgbWF0ZXJpYWwgZGUgbWFuZXJhIG9wdGltYSBwYXJhIGV2aXRhciB0YW50byBTY3JhcC4KCgojIyMgIFByb3B1ZXN0YXMgcGFyYSBGT1JNCgoxLiBNZWpvcmFyIGxvcyB0aWVtcG9zIGRlIHNldCB1cCwgc2llbmRvIGVzdG9zIHlhIGNvcnRvcyBlbnRyZSBwYXVzYSB5IHBhdXNhIHB1ZWRlIHNlciBtw6FzIGNvbXBsaWNhZG8gYmFqYXIgZWwgcG9yY2VudGFqZSwgcGVybyBkZSBpZ3VhbCBtYW5lcmEgc2UgcHVlZGUgaGFjZXIgbcOhcyBlZmVjdGl2byBlbCBhcHJvdmVjYWhhbWllbnRvIGRlbCB0aWVtcG8gcG9yIGxvIHF1ZSBzZSBwcm9wb25lIHJlZHVjaXIgdW4gMTUlLTIwJSBtw6FzIGVsIHRpZW1wbyBxdWUgaGF5IGVudHJlIGVzdGUgc2V0IHVwIG1lZGlhbnRlIGVsIG1hbnRlbmltaWVudG8geSBjdWlkYWRvIGRlIGxhIG1hcXVpbmFyaWEgeSBjb21wcm9taXNvIHkgYXRlbmNpw7NuIGRlIGxvcyBjb2xhYm9yYWRvcmVzLgoKMi5TY3JhcDogQXF1w60gbG8gcXVlIHNlIHByb3BvbmUgZXMgbWVkaWVyIGV4YWN0YW1lbnRlIGxhIGNhbnRpZGFkIHF1ZSBzZSByZXF1aWVyZSBkZSBtYXRlcmlhbCBwYXJhIHBvZGVyIGV2aXRhciB0ZW5lciBlc29zIGRlc3BlcmRpY2lvcy4gQW5hbGl6YW5kbyBlc3RhcyB2YXJpYWJsZXMgc2UgY29uZmlybWEgcXVlIGVuIGVsIMOhcmVhIGRlIHByZS1wcm9kdWNjacOzbiBlcyBkb25kZSBzZSBnZW5lcmEgbGEgbWF5b3IgcGFydGUgZGVsIHNjcmFwIGVuIHN1IG1heW9yw61hIHF1ZSBlcyBjYXNpIGVsIDg1JSBkZSBzY3JhcCBxdWUgc2UgZ2VuZXJhIGRlbnRybyBkZSBsYSBlbXByZXNhLgoKMy4gSW1wbGVtZW50YXIgS1BJ4oCZcyBlc3BlY8OtZmljb3MgY29uIGxvcyBjb2xhYm9yYWRvcmVzIHF1ZSBzZSBlbmNhcmdhbiBkZSBsYSBwcm9kdWNjacOzbiBjb24gdW5hIG1lZGlkYSBkZSB0aWVtcG8gbWVzIGNvbiBtZXMgZG9uZGUgc2UgcmVkdXpjYSBsYSBtZXJtYSBwcm9kdWNpZGEgeSBlc3RhIGJhamUgZW4gdW4gMTUlIGEgMjAlIGFsYSB0ZXJtaW5vIGRlbCBwcmltZXIgbWVzIGRlIGVzdGFibGVjZXIgbG9zIEtQScK0cy4KVGFtYmnDqW4gc2Ugc3VnaWVyZSBtYW50ZW5lciBlbCBuaXZlbCBkZSBjYWxpZGFkIHNpZW1wcmUgZW4gZXNlIGVzdMOhbmRhciBkZSBleGNlbGVuY2lhIHBhcmEgbm8gdGVuZXIgcHJvZHVjdG9zIHJlZ3Jlc2Fkb3MsIGNvbnRyYXRpZW1wb3MgY29uIGVzYXMgZW50cmVnYXMgbyBxdWUgc2UgcmV0cmFzZW4gb3RyYXMgcG9yIGN1bHBhIGRlIHRlbmVyIHF1ZSBwcm9kdWNpciBvIGFycmVnbGFyIGNpZXJ0byBlbXBhcXVlLgoKIyMgIFJlc3BvbmRlciBhIGxhcyBzaWd1aWVudGVzIHByZWd1bnRhcwoKKipEZXNjcmliaXIgY29uIHR1cyBwcm9waWFzIHBhbGFicmFzIGxvcyB0w6lybWlub3MgQnVzaW5lc3MgQW5hbHl0aWNzIHkgQnVzaW5lc3MKSW50ZWxsaWdlbmNlLiBBc8OtIHRhbWJpw6luLCBpZGVudGlmaWNhciB5IGRlc2NyaWJpciAzIHByaW5jaXBhbGVzIGRpZmVyZW5jaWFzIGVudHJlCkJ1c2luZXNzIEFuYWx5dGljcyB5IEJ1c2luZXNzIEludGVsbGlnZW5jZS4qKgoKMS4gKipCdXNpbmVzcyBBbmFseXRpY3MqKjogRXMgdW5hIGNvbWJpbmFjacOzbiBkZSBoYWJpbGlkYWRlcywgdGVjbm9sb2fDrWFzIHkgcHLDoWN0aWNhcyBxdWUgc2UgdXRpbGl6YW4gcGFyYSBleGFtaW5hciBsb3MgZGF0b3MgeSBlbCByZW5kaW1pZW50byBkZSB1bmEgb3JnYW5pemFjacOzbi4gRXMgdW5hIGZvcm1hIGRlIG9idGVuZXIgaW5mb3JtYWNpw7NuIHkgdG9tYXIgZGVjaXNpb25lcyBiYXNhZGFzIGVuIGRhdG9zIGVuIGVsIGZ1dHVybyB1dGlsaXphbmRvIGVsIGFuw6FsaXNpcyBlc3RhZMOtc3RpY28sIHNlIHB1ZWRlIHRyYWR1Y2lyIGNvbW8gYW7DoWxpc2lzIGVtcHJlc2FyaWFsIHkgZXN0ZSBzZSBlbmZvY2EgZW4gZGF0b3MgaGlzdMOzcmljb3MgeSBhY3R1YWxlcy4gU3Ugb2JqZXRpdm8gZXMgaWRlbnRpZmljYXIgcGF0cm9uZXMgbyBwcm9ibGVtYXMsIGlkZW50aWZpY2FyIGxvcyBwb3NpYmxlcyByaWVzZ29zIHkgdG9tYXIgYWNjaW9uZXMgcGFyYSBkaXNtaW51aXJsb3MuIAoKMi4gKioqQnVzaW5lc3MgSW50ZWxpZ2VuY2UqKio6IFNlIGVuZm9jYSBwcmluY2lwYWxtZW50ZSBlbiBsbyBxdWUgZXMgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIHV0aWxpemFuZG8gbG9zIGRhdG9zIHJlY2FiYWRvcyBlbiBlbCBwcm9jZXNvIGRlIGJ1c2luZXNzIGFuYWx5dGljcywgdGFtYmnDqW4gZXMgZWwgY29uanVudG8gZGUgaGVycmFtaWVudGFzIHF1ZSBwZXJtaXRlbiBxdWUgbG9zIGRhdG9zIHNlIHRyYW5zZm9ybWVuIGVuIGluZm9ybWFjw7NuIHkgcXVlIGVzdGEgcGFzZSBhIHNlciBjb25vY2ltaWVudG8uIFNlIHVzYSBwYXJhIGV2YWx1YXIsIG9wdGltaXphciB5IGNvb3JkaW5hciBsYXMgb3BlcmFjaW9uZXMgaW50ZXJuYXMgZGUgdW5hIGVtcHJlc2EuIAoKKioqRGlmZXJlbmNpYXM6KioqCgoxLiBFdmVudG9zIGFjdHVhbGVzIGZyZW50ZSBhIHBvc2liaWxpZGFkZXMgZnV0dXJhczogQ29uIGVzdG8gbm9zIHJlZmVyaW1vcyBhbCBlbmZvcXVlIGVuIGVsIG1vbWVudG8gZW4gcXVlIG9jdXJyZW4gZXN0b3MgZXZlbnRvcy4KCjIuIExhIGZvcm0gYSBlbiBsYSBxdWUgc2UgdXRpbGl6YW4sIHBvciBlamVtcGxvIEJJIGVzIHVuYSBhbmFsw610aWNhIGRlc2NyaXB0aXZhIHlhIHF1ZSBlc3RhIGRpc2XDsWFkbyBwYXJhIGRlY2lybGUgbG8gcXVlIGhhIHN1Y2VkaWRvLCBtaWVudHJhcyBxdWUgcG9yIG90cmEgcGFydGUgQkEgZXMgdW4gdGlwbyBkZSBhbmFsw610aWNhIHByZWRpY3RpdmEgeWEgcXVlIGlkZW50aWZpY2EgdGVuZGVuY2lhcyBlbiBsb3MgZGF0b3MuIAoKMy4gTGFzIGhlcnJhbWllbnRhcyBxdWUgcHJlc2VudGEgQkkgc29uIG3DoXMgdXRpbGl6YWRhcyBwb3IgZXNwZWNpYWxpc3RhcyBlbiBtYXJrZXRpbmcsIGNvbnRhYmlsaWRhZCwgeSBzdSB2aXN1YWxpemFjacOzbiBlcyBtw6FzIGRpZ2VyaWJsZSwgbyBmYWNpbCBkZSBlbnRlbmRlciBtaWVudHJhcyBxdWUgZW4gbGFzIGhlcnJhbWllbnRhcyBkZSBCQSBzZSBiZWNlc2l0YSBtw6FzIHRyYWJham8gcGFyYSBhbmFsaXphciBsYSBpbmZvcm1hY2nDs24gZSBpbnRlcnByZXRhcmxhIHkgcXVpZW5lcyBsYSB1c2FuIHNvbiBtw6FzIGFuYWzDrXN0YXMgCgoqKkRlc2NyaWJpciBjb24gdHVzIHByb3BpYXMgcGFsYWJyYXMgZWwgY29uY2VwdG8gZGUgSW5kaWNhZG9yIENsYXZlIGRlIFJlbmRpbWllbnRvIC8gS2V5IFBlcmZvcm1hbmNlIEluZGljYXRvcnMgKEtQSSkuKioKCioqS2V5IFBlcmZvcm1hbmNlIEluZGljYXRvcnMgKEtQSSkqKjogTG9zIGluZGljYWRvcmVzIGRlIGRlc2VtcGXDsW8gbyBtZWRpZG9yIGRlIGRlc2VtcGXDsW8gc2UgcmVmaWVyZSBhIHVuYSBzZXJpZSBkZSAgbcOpdHJpY2FzIHF1ZSBzZSB1dGlsaXphbiBwYXJhIHNpbnRldGl6YXIgbGEgaW5mb3JtYWNpw7NuLiBFbCBvYmpldGl2byBmaW5hbCBkZSB1biBLUEkgZXMgYXl1ZGFyICB0b21hciBtZWpvcmVzIGRlY2lzaW9uZXMgcmVzcGVjdG8gYWwgZXN0YWRvIGFjdHVhbCBkZSB1biBwcm9jZXNvLCBwcm95ZWN0byBvIGVzdHJhdGVnaWEuCgoqKkxvcyBLUEkgc29uIHV0aWxpemFkb3MgcG9yIGRpdmVyc2FzIHZlbnRhamFzKio6IAoKMS4gUGVybWl0ZW4gb2J0ZW5lciBpbmZvcm1hY2nDs24gdmFsaW9zYSB5IMO6dGlsLgoKMi4gTWVkaXIgZGV0ZXJtaW5hZGFzIHZhcmlhYmxlcyB5IHJlc3VsdGFkb3MgYSBwYXJ0aXIgZGUgZGljaGEgaW5mb3JtYWNpw7NuLgoKMy4gQW5hbGl6YXIgbGEgaW5mb3JtYWNpw7NuIHkgZWZlY3RvcyBkZSB1bmFzIGRldGVybWluYWRhcyBlc3RyYXRlZ2lhcyAoYXPDrSBjb21vIGxhcyB0YXJlYXMgcXVlIHNlIHV0aWxpemFyb24gcGFyYSBsbGV2YXIgYSBjYWJvIGxhcyBtaXNtYXMpLgoKNC4gQ29tcGFyYXIgbGEgaW5mb3JtYWNpw7NuIHkgZGV0ZXJtaW5hciBsYXMgZXN0cmF0ZWdpYXMgeSB0YXJlYXMgZWZlY3RpdmFzLgoKNS4gVG9tYXIgbGFzIGRlY2lzaW9uZXMgb3BvcnR1bmFzLgoKKipBIHBhcnRpciBkZWwgYW7DoWxpc2lzIGRlIGxhcyBiYXNlcyBkZSBkYXRvcyBkZSBsYXMgZGlmZXJlbnRlcyDDoXJlYXMgZGUgbGEKZW1wcmVzYSBGT1JNLCBwcm9wb25lciB5IGRlc2NyaWJpciAzIHBvc2libGVzIEtQSXMgcXVlIHBlcm1pdGFuIGV2YWx1YXIKZWwgZGVzZW1wZcOxbyBkZSBhbGd1bmFzIGRlIHN1cyDDoXJlYXMuKioKCjEuIFJlZHVjaXIgbGEgbWVybWEgcHJvZHVjaWRhIHkgcXVlIGVzdGEgYmFqZSBlbiB1biAxNSUgYSAyMCUgYWwgdGVybWlubyBkZWwgcHJpbWVyIG1lcyBkZSBlc3RhYmxlY2VyIGVsIEtQSS4KCjIuIFJvdGFjacOzbiBkZSBubnZlbnRhcmlvIHBhcmEgY29ub2NlciBsYSBlZmVjdGl2aWRhZCBkZSBsb3MgcmVjdXJzb3MgY29uIGxvcyBxdWUgY3VlbnRhIGxhIGVtcHJlc2EgeSBxdWUgRk9STSBwdWVkYSBjcmVhciBhc2VndXJhciBxdWUgc3VzIGdhc3RvcyBsZSBkYXLDoW4gdW4gcmV0b3JubyBkZSBpbnZlcnNpw7NuIGxvIG3DoXMgcHJvbnRvIHBvc2libGUuIEVzdG8gYXl1ZGFyYSBhIHF1ZSBsYSBlbXByZXNhIHRhbWJpw6luIHB1ZWRhIHRlbmVyIG3DoXMgbGlicmUgZWwgYWxtYWNlbi4KCjMuIE7Dum1lcm8gZGUgdW5pZGFkZXMgcHJvZHVjaWRhcyBhbCBtZXMsIHlhIHF1ZSBlc3TDoXMgcG9kcmFuIGF5dWRhciBhIG1lZGlyIGxhIHByb2R1Y3RpdmlkYWQgZGUgRk9STSB5IHRlbmVyIG3DoXMgY29udHJvbCBkZW50cm8gZGUgc3VzIG9wZXJhY2lvbmVzLiAKCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IG9yYW5nZSIgPiAgUmVmZXJlbmNpYXMgIDwvc3Bhbj4KCkNvbGFib3JhY2nDs24gKG5vIGRhdGUpIEtQSSdzIMK/UXXDqSBzb24sIHBhcmEgcXXDqSBzaXJ2ZW4geSBwb3IgcXXDqSB5IGPDs21vIHV0aWxpemFybG9zPywgVGlwcyBkZSBMb2dpY2FsaXMuIEF2YWlsYWJsZSBhdDogaHR0cHM6Ly9ibG9nLmVzLmxvZ2ljYWxpcy5jb20vYW5hbHl0aWNzL2twaXMtcXUlQzMlQTktc29uLXBhcmEtcXUlQzMlQTktc2lydmVuLXktcG9yLXF1JUMzJUE5LXktYyVDMyVCM21vLXV0aWxpemFybG9zIChBY2Nlc3NlZDogT2N0b2JlciAyMSwgMjAyMikuIAoKQmlibGlvdGVjYSAtIFRlYyBkZSBNb250ZXJyZXk6IEJpYmxpb3RlY2EgVGVjIC0gRXNjdWVsYSBkZSBOZWdvY2lvczogSW5pY2lvIChubyBkYXRlKSBUZWNub2zDs2dpY28gZGUgTW9udGVycmV5LiBBdmFpbGFibGUgYXQ6IGh0dHBzOi8vYmlibGlvdGVjYS50ZWMubXgvZWRuIChBY2Nlc3NlZDogT2N0b2JlciAyMSwgMjAyMikuIAoKCgoKCgoK