Inicio

Cargamos librerias

Recursos Humanos

rh<-read.csv("C:\\Users\\chema\\Downloads\\recursoshumanos.csv")
summary(rh)
##  No..De.Empleado   APELLIDOS            NOMBRE          FECHA.DE.NACIMIENTO
##  Min.   :  1.00   Length:112         Length:112         Length:112         
##  1st Qu.: 24.50   Class :character   Class :character   Class :character   
##  Median : 48.00   Mode  :character   Mode  :character   Mode  :character   
##  Mean   : 56.78                                                            
##  3rd Qu.: 83.00                                                            
##  Max.   :148.00                                                            
##  NA's   :21                                                                
##     GENERO              RFC            FECHA.DE.ALTA       Primer.mes       
##  Length:112         Length:112         Length:112         Length:112        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##    X4to.mes              BAJA       PUESTO          DEPARTAMENTO      
##  Length:112         Min.   :3    Length:112         Length:112        
##  Class :character   1st Qu.:3    Class :character   Class :character  
##  Mode  :character   Median :3    Mode  :character   Mode  :character  
##                     Mean   :3                                         
##                     3rd Qu.:3                                         
##                     Max.   :3                                         
##                     NA's   :99                                        
##  NO.SEGURO.SOCIAL   SALARIO.DIARIO.IMSS FACTOR.CRED.INFONAVIT
##  Length:112         Min.   :144.4       Length:112           
##  Class :character   1st Qu.:176.7       Class :character     
##  Mode  :character   Median :180.7       Mode  :character     
##                     Mean   :179.0                            
##                     3rd Qu.:180.7                            
##                     Max.   :337.1                            
##                                                              
##  No..CREDITO.INFONAVIT LUGAR.DE.NACIMIENTO     CURP          
##  Length:112            Length:112          Length:112        
##  Class :character      Class :character    Class :character  
##  Mode  :character      Mode  :character    Mode  :character  
##                                                              
##                                                              
##                                                              
##                                                              
##     CALLE           NUMERO.INTERNO       COLONIA           MUNICIPIO        
##  Length:112         Length:112         Length:112         Length:112        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##     ESTADO          CODIGO.POSTAL   ESTADO.CIVIL       TARJETA....CUENTA 
##  Length:112         Min.   :25016   Length:112         Length:112        
##  Class :character   1st Qu.:66640   Class :character   Class :character  
##  Mode  :character   Median :66646   Mode  :character   Mode  :character  
##                     Mean   :63331                                        
##                     3rd Qu.:66649                                        
##                     Max.   :67493                                        
## 
str(rh)
## 'data.frame':    112 obs. of  26 variables:
##  $ No..De.Empleado      : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ APELLIDOS            : chr  "MARTINEZ DE LOERA" "DE LEON MORENO" "HERNANDEZ CERVANTES" "CAZARES MORALES" ...
##  $ NOMBRE               : chr  "NICOLAS" "MARIANA" "JOSE LUIS" "MARIA" ...
##  $ FECHA.DE.NACIMIENTO  : chr  "10/09/1955" "14/05/1979" "21/11/1949" "01/05/1990" ...
##  $ GENERO               : chr  "MASCULINO" "FEMENINO" "MASCULINO" "FEMENINO" ...
##  $ RFC                  : chr  "MALN550910338" "LEMM7905148GA" "HECL4911213X3" "CAMM9005019S8" ...
##  $ FECHA.DE.ALTA        : chr  "01/07/2010" "01/07/2011" "22/11/2011" "30/01/2013" ...
##  $ Primer.mes           : chr  "7/31/2010" "7/31/2011" "" "3/1/2013" ...
##  $ X4to.mes             : chr  "10/29/2010" "10/29/2011" "" "5/30/2013" ...
##  $ BAJA                 : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ PUESTO               : chr  "Supervisor de M\xe1quin" "Supervisor de pegado" "Externo" "SUPERVISORA" ...
##  $ DEPARTAMENTO         : chr  "Produccion Cart\xf3n MDL" "Produccion Cart\xf3n MDL" "Externo" "Produccion Cart\xf3n MC" ...
##  $ NO.SEGURO.SOCIAL     : chr  "43745527937" "43127902955" "2184909675" "43089001317" ...
##  $ SALARIO.DIARIO.IMSS  : num  177 177 177 337 177 ...
##  $ FACTOR.CRED.INFONAVIT: chr  "" "" "" "" ...
##  $ No..CREDITO.INFONAVIT: chr  "" "" "" "" ...
##  $ LUGAR.DE.NACIMIENTO  : chr  "" "" "" "" ...
##  $ CURP                 : chr  "MALN550910HZSRRC09" "LEMM790514MCLNRR09" "HECL491121HJCRRS04" "CAMM900501MVZZRR00" ...
##  $ CALLE                : chr  "JOSE I LUGO" "44682" "HACIENDA SAN CRISTOBAL" "RIO ACAPONETA" ...
##  $ NUMERO.INTERNO       : chr  "" "115" "" "" ...
##  $ COLONIA              : chr  "UNIDAD LABORAL" "SANTA TERESITA" "VILLAS DE HUINALA" "PUEBLO NUEVO" ...
##  $ MUNICIPIO            : chr  "SAN NICOLAS DE LOS G" "APODACA" "APODACA" "APODACA" ...
##  $ ESTADO               : chr  "Nuevo Le\xf3n" "Nuevo Le\xf3n" "Nuevo Le\xf3n" "Nuevo Le\xf3n" ...
##  $ CODIGO.POSTAL        : int  66440 66605 66634 66649 66620 25016 66633 66649 25290 66473 ...
##  $ ESTADO.CIVIL         : chr  "Soltero" "Soltero" "Soltero" "Casado" ...
##  $ TARJETA....CUENTA    : chr  "BANORTE" "BANORTE" "BANORTE" "BANORTE" ...
dim(rh)
## [1] 112  26
apply(is.na(rh), 2, sum)
##       No..De.Empleado             APELLIDOS                NOMBRE 
##                    21                     0                     0 
##   FECHA.DE.NACIMIENTO                GENERO                   RFC 
##                     0                     0                     0 
##         FECHA.DE.ALTA            Primer.mes              X4to.mes 
##                     0                     0                     0 
##                  BAJA                PUESTO          DEPARTAMENTO 
##                    99                     0                     0 
##      NO.SEGURO.SOCIAL   SALARIO.DIARIO.IMSS FACTOR.CRED.INFONAVIT 
##                     0                     0                     0 
## No..CREDITO.INFONAVIT   LUGAR.DE.NACIMIENTO                  CURP 
##                     0                     0                     0 
##                 CALLE        NUMERO.INTERNO               COLONIA 
##                     0                     0                     0 
##             MUNICIPIO                ESTADO         CODIGO.POSTAL 
##                     0                     0                     0 
##          ESTADO.CIVIL     TARJETA....CUENTA 
##                     0                     0
rh <- clean_names(rh)
colnames(rh)
##  [1] "no_de_empleado"        "apellidos"             "nombre"               
##  [4] "fecha_de_nacimiento"   "genero"                "rfc"                  
##  [7] "fecha_de_alta"         "primer_mes"            "x4to_mes"             
## [10] "baja"                  "puesto"                "departamento"         
## [13] "no_seguro_social"      "salario_diario_imss"   "factor_cred_infonavit"
## [16] "no_credito_infonavit"  "lugar_de_nacimiento"   "curp"                 
## [19] "calle"                 "numero_interno"        "colonia"              
## [22] "municipio"             "estado"                "codigo_postal"        
## [25] "estado_civil"          "tarjeta_cuenta"

Podemos notar en esta base de datos al usar la función de summary, que existen varias variables que no serán necesarias para trabajar en esta base de datos. Al igual que existen variables que necesitan ser cambiadas de tipo de variable.Por ultimo, algunos de los colaboradores no cuentan con Numero de empleado, lo cual omitiré ya que no será necesario de esa información.

Las variables inecesarias para realizar proximos analisis son: RFC, Baja, Numero de seguro social, Factor credito infonavit, curp, todas las variables relacionadas con el nacimiento de la persona y su ubicación y por ultimo su cuenta bancaria.

Limpieza de datos

En esta base de datos se aplicaron 4 tecnicas de limpieza: 1. Se creó una nueva columna para Nombre Completo 2. Se eliminaron y ordenaron columnas que no eran necesarias. 3. Se corrigieron nombres de variables, al mismo tiempo que se estandarizaron algunos registros

rh<-mutate(rh,nombre_completo = paste(rh$nombre, rh$apellidos, sep=" "))

rh<-dplyr::select(rh,-c(rfc,baja,no_credito_infonavit,factor_cred_infonavit,curp,tarjeta_cuenta,apellidos,nombre,calle,numero_interno,colonia,municipio,estado,codigo_postal,x4to_mes,primer_mes,no_de_empleado,lugar_de_nacimiento,no_seguro_social))

rh<-rh[,c(8,1,2,3,4,5,6,7)]

Cambiar fechas de caractér a tipo de variable correcta

rh$fecha_de_nacimiento<-as.Date(rh$fecha_de_nacimiento, format = "%d/%m/%Y")
rh$fecha_de_alta<-as.Date(rh$fecha_de_alta, format = "%d/%m/%Y")

Estandarizar registros de puesto y departamento

Puesto

unique(rh$puesto)
##  [1] "Supervisor de M\xe1quin"         "Supervisor de pegado"           
##  [3] "Externo"                         "SUPERVISORA"                    
##  [5] "CUSTOMER SERVICE INF"            "COSTURERA"                      
##  [7] "AYUDANTE GENERAL"                "Ayudante general"               
##  [9] "GESTOR"                          "CHOFER"                         
## [11] "LIDER"                           "MANTENIMIENTO"                  
## [13] "RESIDENTE"                       "LIMPIEZA"                       
## [15] "INSPECTOR DE CALIDAD"            "EXTERNO"                        
## [17] "PINTOR"                          "SOLDADOR"                       
## [19] "AY. GENERAL"                     "RECIBO"                         
## [21] "ENFERMERA"                       "OP. FLEXO-RANURADORA-REFILADORA"
## [23] "GUARDIA DE SEGURIDAD"            "MOZO"                           
## [25] "INSPECTORA DE CALIDAD"           "CHOFER GESTOR"                  
## [27] "OPERADOR SIERRA"                 "AYUDANTE DE MANTENIMIENTO"      
## [29] "MONTACARGUISTA"
rh$puesto <- replace(rh$puesto,rh$puesto=="Supervisor de M\xe1quin","SUPERVISOR(A)")
rh$puesto <- replace(rh$puesto,rh$puesto=="SUPERVISORA","SUPERVISOR(A)")
rh$puesto <- replace(rh$puesto,rh$puesto== "Supervisor de pegado","SUPERVISOR(A)")
rh$puesto <- replace(rh$puesto,rh$puesto== "Ayudante general" ,"AYUDANTE GENERAL")
rh$puesto <- replace(rh$puesto,rh$puesto== "AY. GENERAL","AYUDANTE GENERAL")
rh$puesto <- replace(rh$puesto,rh$puesto== "AYUDANTE DE MANTENIMIENTO","AYUDANTE GENERAL")
rh$puesto <- replace(rh$puesto,rh$puesto== "INSPECTOR DE CALIDAD","INSPECTOR(A)")
rh$puesto <- replace(rh$puesto,rh$puesto== "INSPECTORA DE CALIDAD","INSPECTOR(A)")
rh$puesto <- replace(rh$puesto,rh$puesto== "CHOFER GESTOR","CHOFER")
rh$puesto <- toupper(rh$puesto)
unique(rh$puesto)
##  [1] "SUPERVISOR(A)"                   "EXTERNO"                        
##  [3] "CUSTOMER SERVICE INF"            "COSTURERA"                      
##  [5] "AYUDANTE GENERAL"                "GESTOR"                         
##  [7] "CHOFER"                          "LIDER"                          
##  [9] "MANTENIMIENTO"                   "RESIDENTE"                      
## [11] "LIMPIEZA"                        "INSPECTOR(A)"                   
## [13] "PINTOR"                          "SOLDADOR"                       
## [15] "RECIBO"                          "ENFERMERA"                      
## [17] "OP. FLEXO-RANURADORA-REFILADORA" "GUARDIA DE SEGURIDAD"           
## [19] "MOZO"                            "OPERADOR SIERRA"                
## [21] "MONTACARGUISTA"

Departamento

unique(rh$departamento)
##  [1] "Produccion Cart\xf3n MDL" "Externo"                 
##  [3] "Produccion Cart\xf3n MC"  "Costura"                 
##  [5] "Cedis"                    "Producci\xf3n Retorn"    
##  [7] "Costura T2"               "Embarques"               
##  [9] "EHS"                      "Limpieza"                
## [11] "Calidad"                  "Paileria"                
## [13] "Materiales"               "COSTURA"                 
## [15] ""                         "Rotativa"                
## [17] "Stabilus"                 "Troquel"                 
## [19] "Celdas"                   "Ay.flexo"                
## [21] "CEDIS"                    "CORTADORAS"
rh$departamento <- replace(rh$departamento,rh$departamento=="Produccion Cart\xf3n MDL","Producción Cartón MDL")
rh$departamento <- replace(rh$departamento,rh$departamento=="Producci\xf3n Retorn","Producción Retorn")
rh$departamento <- replace(rh$departamento,rh$departamento=="Produccion Cart\xf3n MC","Producción Cartón MC")
rh$departamento <- replace(rh$departamento,rh$departamento=="Costura T2","COSTURA")
rh$departamento <- replace(rh$departamento,rh$departamento=="Costura","COSTURA")

Salario Diario IMSS

Cambiaremos a numero el salario diario de los colaboradores.

rh$salario_diario_imss<-as.numeric(rh$salario_diario_imss)
unique(rh$salario_diario_imss)
##  [1] 176.72 337.05 260.01 240.75 152.86 175.79 144.45 279.61 151.67 208.65
## [11] 240.71 151.61 180.68 181.68 184.68 185.68
summary(rh)
##  nombre_completo    fecha_de_nacimiento     genero         
##  Length:112         Min.   :1949-11-21   Length:112        
##  Class :character   1st Qu.:1977-04-20   Class :character  
##  Mode  :character   Median :1989-01-22   Mode  :character  
##                     Mean   :1986-08-21                     
##                     3rd Qu.:1997-01-03                     
##                     Max.   :2022-02-23                     
##  fecha_de_alta           puesto          departamento       salario_diario_imss
##  Min.   :2010-07-01   Length:112         Length:112         Min.   :144.4      
##  1st Qu.:2020-08-27   Class :character   Class :character   1st Qu.:176.7      
##  Median :2022-02-20   Mode  :character   Mode  :character   Median :180.7      
##  Mean   :2021-01-12                                         Mean   :179.0      
##  3rd Qu.:2022-07-05                                         3rd Qu.:180.7      
##  Max.   :2022-08-23                                         Max.   :337.1      
##  estado_civil      
##  Length:112        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 

Estado Civil

unique(rh$estado_civil)
##  [1] "Soltero"        "Casado"         "Uni\xf3n libre" "Union Libre"   
##  [5] "CASADA"         "UNION LIBRE"    "CASADO"         "SOLTERA"       
##  [9] "DIVORCIADO"     "SOLTERO"        "DIVORCIADA"
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="Soltero","SOLTERO(A)")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="SOLTERA","SOLTERO(A)")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="SOLTERO","SOLTERO(A)")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="Uni\xf3n libre","UNIÓN LIBRE")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="Uni<f3>n libre","UNIÓN LIBRE")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="UNION LIBRE","UNIÓN LIBRE")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="Union Libre","UNIÓN LIBRE")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="Casado","CASADO(A)")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="CASADO","CASADO(A)")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="CASADA","CASADO(A)")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="Casado","CASADO(A)")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="DIVORCIADA","DIVORCIADO(A)")
rh$estado_civil <- replace(rh$estado_civil,rh$estado_civil=="DIVORCIADO","DIVORCIADO(A)")

La base de datos de Recursos Humanos cuenta con 112 registros y 8 variables.

dim(rh)
## [1] 112   8
Variable<-c("Nombre Completo", "Fecha de Nacimiento", "Genero", "Fecha de Alta", "Puesto", "Departamento","Salario Diario IMSS", "Estado Civil")
Tipo<-c("Cualitativa", "Cualitativa", "Cualitativa", "Cualitativa", "Cualitativa","Cualitativa", "Cuantitativa (continua)","Cualitativa")
Escala_Medicion <-c("NA", "Fecha", "NA","Fecha","NA","NA","Pesos","NA")
tabla<-data.frame(Variable, Tipo, Escala_Medicion)
knitr::kable(tabla)
Variable Tipo Escala_Medicion
Nombre Completo Cualitativa NA
Fecha de Nacimiento Cualitativa Fecha
Genero Cualitativa NA
Fecha de Alta Cualitativa Fecha
Puesto Cualitativa NA
Departamento Cualitativa NA
Salario Diario IMSS Cuantitativa (continua) Pesos
Estado Civil Cualitativa NA

Análisis Exploratorio de las Bases de Datos

Estadísticos descrptivos

Para concer los estadisticos de cada una de las variables, se utilizará la función describe. En el caso de esta base de datos, la unica variable que se pudo utilizar es Salario Diario IMSS

mea2 <- mean(rh$salario_diario_imss)
med2 <- median(rh$salario_diario_imss)
moda2<- mfv(rh$salario_diario_imss)
sd2 <- sd(rh$salario_diario_imss, na.rm = TRUE)


Variables <-c("Salario Diario Imss")
Media <-c(mea2)
Mediana <-c(med2)
Moda <-c(moda2)
Desviacion <-c(sd2)
tabla2 <-data.frame(Variables, Media, Mediana, Moda,Desviacion)
knitr::kable(tabla2)
Variables Media Mediana Moda Desviacion
Salario Diario Imss 179.0415 180.68 180.68 24.39491

Esta tabla nos ayuda a identificar que el salario promedio de FORM es de 179.04 pesos, mientras que el salario mas repetido es de 180 pesos. Se cuenta con una desviación estandart de 24, la cual nos indica que la disperción entre los salarios es moderada.

Graficas

Primera Grafica (Barplot #1)

ggplot(rh, aes(x=genero, y=mean(salario_diario_imss), fill=genero)) + 
  geom_col() + 
  facet_grid(~estado_civil) + scale_fill_brewer(palette = "Set3")

Esta grafica nos muestra la relación que existe entre tres de nuestra variables, siendo estas genero, salario diario y estado civil. Logramos percibir que los salarios de las mujeres solteras es mayor al de los hombres en todos los estados civiles. Sin embargo los hombres casados perciben mayor salario que las mujeres casados. Esto puede ser por los puestos que estos ocupan o por el rol economico que juega el hombre dentro de la mayoria de las familias.

Segunda Grafica (Barplot #2)

hist(rh$salario_diario_imss)

Bajas

Limpieza de Datos

Importamos Bajas

rhb <-  read.csv("C:\\Users\\chema\\Downloads\\BaseD_Limpia RH_ Bajas .csv")

Entendemos la base de datos

summary(rhb)
##     nombre               edad          genero          fecha_de_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                                        
##  motivo_de_baja     dias_de_trabajo       baja           puesto_que_desempena
##  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                                          
##   salario_imss     colonia           municipio            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                                                           
##  estado_civil      
##  Length:237        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 
str(rhb)
## '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  "3/9/2020" "11/9/2021" "11/10/2021" "11/10/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" "1/8/2022" "1/8/2022" "1/8/2022" ...
##  $ puesto_que_desempena: chr  "DISE\xd1O" "AYUDANTE GENERAL" "AYUDANTE GENERAL" "AYUDANTE GENERAL" ...
##  $ salario_imss        : num  500 152 152 152 152 ...
##  $ colonia             : chr  "SAN NICOLAS DE LOS G" "COLINAS DEL AEROP\xd1UERTO" "PUEBLO NUEVO" "PUEBLO NUEVO" ...
##  $ municipio           : chr  "SAN NICOLAS DE LOS G" "PESQUERIA" "APODACA" "APODACA" ...
##  $ estado              : chr  "NUEVO LE\xd3N" "NUEVO LE\xd3N" "NUEVO LE\xd3N" "NUEVO LE\xd3N" ...
##  $ estado_civil        : chr  "SOLTERO" "UNI\xd3N LIBRE" "CASADO" "SOLTERO" ...
dim(rhb)
## [1] 237  13
apply(is.na(rhb), 2, sum)
##               nombre                 edad               genero 
##                    0                    0                    0 
##        fecha_de_alta       motivo_de_baja      dias_de_trabajo 
##                    0                    0                    0 
##                 baja puesto_que_desempena         salario_imss 
##                    0                    0                    0 
##              colonia            municipio               estado 
##                    0                    0                    0 
##         estado_civil 
##                    0
rh <- clean_names(rhb)
colnames(rhb)
##  [1] "nombre"               "edad"                 "genero"              
##  [4] "fecha_de_alta"        "motivo_de_baja"       "dias_de_trabajo"     
##  [7] "baja"                 "puesto_que_desempena" "salario_imss"        
## [10] "colonia"              "municipio"            "estado"              
## [13] "estado_civil"

Cambio de nombres de variables

names(rhb)<-c("nomb", "edad", "gen", "fecha_alta", "mb", "dias_trab", "baja", "puesto", "sal_imss", "col", "mun", "estado", "estciv")

Cambiar tipo de variables

rhb$edad<-as.numeric(rhb$edad)
rhb$fecha_alta<-as.Date(rhb$fecha_alta, format = "%y/%m/%d")
rhb$baja<-as.Date(rhb$baja, format = "%y/%m/%d")
rhb$dias_trab<-as.numeric(rhb$edad)

Estandarizar Variables

unique(rhb$estciv)
## [1] "SOLTERO"        "UNI\xd3N LIBRE" "CASADO"         "DIVORCIADO"    
## [5] "Uni\xf3n libre"
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="Soltero","SOLTERO(A)")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="SOLTERA","SOLTERO(A)")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="SOLTERO","SOLTERO(A)")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="Uni\xf3n libre","UNIÓN LIBRE")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="UNI\xd3N LIBRE","UNIÓN LIBRE")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="UNION LIBRE","UNIÓN LIBRE")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="Union Libre","UNIÓN LIBRE")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="Casado","CASADO(A)")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="CASADO","CASADO(A)")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="CASADA","CASADO(A)")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="Casado","CASADO(A)")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="DIVORCIADA","DIVORCIADO(A)")
rhb$estciv <- replace(rhb$estciv,rhb$estciv=="DIVORCIADO","DIVORCIADO(A)")

unique(rhb$mun)
##  [1] "SAN NICOLAS DE LOS G"     "PESQUERIA"               
##  [3] "APODACA"                  "JUAREZ"                  
##  [5] "GUADALUPE"                "RAMOS ARIZPE"            
##  [7] "MONTERREY"                "SAN PDRO COAH"           
##  [9] "CADEREYTA"                "SAN NICOLAS DE LOS GARZA"
## [11] "SALTILLO"                 "ZUAZUA"                  
## [13] "CIENEGA DE FLORES"
rhb$mun <- replace(rhb$mun,rhb$mun=="SAN NICOLAS DE LOS G","SAN NICOLAS DE LOS GARZA")
rhb$mun <- replace(rhb$mun,rhb$mun=="SAN PDRO COAH","COAHUILA")

unique(rhb$estado)
## [1] "NUEVO LE\xd3N" "SALTILLO"      "COAHUILA"
rhb$estado <- replace(rhb$estado,rhb$estado=="NUEVO LE\xd3N","Nuevo León")

summary(rhb)
##      nomb                edad           gen              fecha_alta        
##  Length:237         Min.   : 0.00   Length:237         Min.   :2001-04-20  
##  Class :character   1st Qu.:23.00   Class :character   1st Qu.:2008-06-20  
##  Mode  :character   Median :29.00   Mode  :character   Median :2015-06-20  
##                     Mean   :30.52                      Mean   :2015-06-12  
##                     3rd Qu.:37.00                      3rd Qu.:2021-12-20  
##                     Max.   :61.00                      Max.   :2031-05-20  
##       mb              dias_trab          baja               puesto         
##  Length:237         Min.   : 0.00   Min.   :2001-08-20   Length:237        
##  Class :character   1st Qu.:23.00   1st Qu.:2007-06-20   Class :character  
##  Mode  :character   Median :29.00   Median :2017-08-20   Mode  :character  
##                     Mean   :30.52   Mean   :2016-08-23                     
##                     3rd Qu.:37.00   3rd Qu.:2025-04-20                     
##                     Max.   :61.00   Max.   :2031-01-20                     
##     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  
##                    
##                    
## 

Se identificó que existen 2 registros con edad 0. Se utilizará la edad promedio del grupo, la cual es 31 años para remplazar los valores de dichos registros.

Remplazar valores invalidos por la media

rhb$edad<-replace(rhb$edad,rhb$edad==0,31)

summary(rhb)
##      nomb                edad           gen              fecha_alta        
##  Length:237         Min.   :18.00   Length:237         Min.   :2001-04-20  
##  Class :character   1st Qu.:23.00   Class :character   1st Qu.:2008-06-20  
##  Mode  :character   Median :29.00   Mode  :character   Median :2015-06-20  
##                     Mean   :30.78                      Mean   :2015-06-12  
##                     3rd Qu.:37.00                      3rd Qu.:2021-12-20  
##                     Max.   :61.00                      Max.   :2031-05-20  
##       mb              dias_trab          baja               puesto         
##  Length:237         Min.   : 0.00   Min.   :2001-08-20   Length:237        
##  Class :character   1st Qu.:23.00   1st Qu.:2007-06-20   Class :character  
##  Mode  :character   Median :29.00   Median :2017-08-20   Mode  :character  
##                     Mean   :30.52   Mean   :2016-08-23                     
##                     3rd Qu.:37.00   3rd Qu.:2025-04-20                     
##                     Max.   :61.00   Max.   :2031-01-20                     
##     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  
##                    
##                    
## 

La base de datos de Recursos Humanos Bajas cuenta con 237 registros y 13 variables.

dim(rhb)
## [1] 237  13

Tipos de variables y medición

Variable<-c("Nombre", "Edad", "Genero", "Fecha de Alta", "Motivo de baja", "Días Trabajados","Baja", "Puesto","Salario IMMS","Colonia","Municipio","Estado","Estado Civil")
Tipo<-c("Cualitativa", "Cuantitativa", "Cualitativa", "Cualitativa", "Cualitativa","Cuantitativa", "Cualitativa","Cualitativa","Cuantitativa","Cualitativa","Cualitativa","Cualitativa","Cualitativa")
Escala_Medicion <-c("NA", "Años", "NA","Fecha","NA","Días","NA","NA","Pesos","NA","NA","NA","NA")
tabla<-data.frame(Variable, Tipo, Escala_Medicion)
knitr::kable(tabla)
Variable Tipo Escala_Medicion
Nombre Cualitativa NA
Edad Cuantitativa Años
Genero Cualitativa NA
Fecha de Alta Cualitativa Fecha
Motivo de baja Cualitativa NA
Días Trabajados Cuantitativa Días
Baja Cualitativa NA
Puesto Cualitativa NA
Salario IMMS Cuantitativa Pesos
Colonia Cualitativa NA
Municipio Cualitativa NA
Estado Cualitativa NA
Estado Civil Cualitativa NA

Análisis Exploratorio de las Bases de Datos

Estadísticos descrptivos

mea <- mean(rhb$sal_imss)
med <- median(rhb$sal_imss)
moda <- mfv(rhb$sal_imss)
sd <- sd(rhb$sal_imss, na.rm = TRUE)

mea1 <- mean(rhb$edad)
med1 <- median(rhb$edad)
moda1 <- mfv(rhb$edad)
sd1 <- sd(rhb$edad, na.rm = TRUE)

mea2 <- mean(rhb$dias_trab)
med2 <- median(rhb$dias_trab)
moda2 <- mfv(rhb$dias_trab)
sd2 <- sd(rhb$dias_trab, na.rm = TRUE)

Variables <-c("Salario Diario Imss","Edad", "Dias Trabajados")
Media <-c(mea,mea1,mea2)
Mediana <-c(med,med1,med2)
Moda <-c(moda,moda1,moda2)
Desviacion <-c(sd,sd1,sd2)
tabla2 <-data.frame(Variables, Media, Mediana, Moda,Desviacion)
knitr::kable(tabla2)
Variables Media Mediana Moda Desviacion
Salario Diario Imss 178.63945 180.68 180.68 25.441128
Edad 30.78059 29.00 21.00 9.612975
Dias Trabajados 30.51899 29.00 21.00 10.018450

Podemos ver que en esta tabla, que el trabajador promedio dentro de la base de datos RH Bajas tiene 31 años, llevaba 31 dias trabajando y ganaba un sueldo promedio de 178.63 pesos. La desviación mas alta dentro de las variables cuantitativas es de 25.44, siendo esta la desviación del salario diario. Esto nos indica que existe bastante disperción entre los registros maximos y minimos de la variable.

Graficas

Primera Grafica (Barplot #3)

ggplot(rhb, aes(x=gen, y=edad, fill=mb)) + 
  geom_bar(stat="identity") + 
  facet_grid(~estciv) + scale_fill_brewer(palette = "Set3")

Esta grafica nos muestra la relación que existe entre tres de nuestra variables, siendo estas Genero, Edad, Motivo de baja y Estado civil. Podemos notar que

Segunda Grafica (Scatter plot #1)

Para la realización de este scatter plot, se eliminaron 2 registros que cesgaban la muestra al momento de graficarla, dichos registros eran los 2 salarios mas altos, siendo uno de $500 y otro de 338.36.

rhb1<-rhb
rhb1 <- rhb1[rhb1$sal_imss<183.68,]

library(hrbrthemes)
## NOTE: Either Arial Narrow or Roboto Condensed fonts are required to use these themes.
##       Please use hrbrthemes::import_roboto_condensed() to install Roboto Condensed and
##       if Arial Narrow is not on your system, please see https://bit.ly/arialnarrow
ggplot(rhb1, aes(x=edad, y=sal_imss, color=estciv)) + 
    geom_point(size=2) +
    theme_dark()

Delivery Plan

Limpieza de datos

Importamos Delivery Plan

  dpl <- read.csv("C:\\Users\\chema\\Downloads\\Delivery Plan BD Final (1).csv")

Entendemos la base de datos

summary(dpl)
##  CLIENTE.PLANTA       PROYECTO           ID.ODOO              ITEM          
##  Length:231         Length:231         Length:231         Length:231        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##      JUNIO             JULIO             AGOSTO          SEPTIEMBRE  
##  Min.   :   0.00   Min.   :    0.0   Min.   :   0.00   Min.   :   0  
##  1st Qu.:   0.00   1st Qu.:    0.0   1st Qu.:   0.00   1st Qu.:   0  
##  Median :   0.00   Median :    0.0   Median :   0.00   Median :   0  
##  Mean   :  29.06   Mean   :  135.9   Mean   :  77.45   Mean   :  81  
##  3rd Qu.:   0.00   3rd Qu.:    0.0   3rd Qu.:   0.00   3rd Qu.:   0  
##  Max.   :1280.00   Max.   :13120.0   Max.   :3200.00   Max.   :3200  
##     OCTUBRE         NOVIEMBRE         DICIEMBRE          ene.22       
##  Min.   :   0.0   Min.   :   0.00   Min.   :   0.0   Min.   :   0.00  
##  1st Qu.:   0.0   1st Qu.:   0.00   1st Qu.:   0.0   1st Qu.:   0.00  
##  Median :   0.0   Median :   0.00   Median :   0.0   Median :   0.00  
##  Mean   :  62.0   Mean   :  89.69   Mean   : 100.4   Mean   :  82.37  
##  3rd Qu.:  11.5   3rd Qu.:   4.00   3rd Qu.:   1.5   3rd Qu.:  26.50  
##  Max.   :3200.0   Max.   :6400.00   Max.   :6400.0   Max.   :3200.00  
##      Feb.22           Mar.22           abr.22            May.22       
##  Min.   :   0.0   Min.   :   0.0   Min.   :    0.0   Min.   :    0.0  
##  1st Qu.:   0.0   1st Qu.:   0.0   1st Qu.:    0.0   1st Qu.:    0.0  
##  Median :   0.0   Median :   0.0   Median :    0.0   Median :    0.0  
##  Mean   : 103.5   Mean   : 153.9   Mean   :  186.5   Mean   :  187.6  
##  3rd Qu.:   0.0   3rd Qu.:  20.0   3rd Qu.:   24.0   3rd Qu.:   22.0  
##  Max.   :9600.0   Max.   :9600.0   Max.   :16354.0   Max.   :17665.0  
##      Jun.22            Jul.22            ago.22            Sep.22       
##  Min.   :    0.0   Min.   :    0.0   Min.   :    0.0   Min.   :    0.0  
##  1st Qu.:    0.0   1st Qu.:    0.0   1st Qu.:    0.0   1st Qu.:    0.0  
##  Median :    0.0   Median :    0.0   Median :    0.0   Median :    0.0  
##  Mean   :  171.2   Mean   :  316.9   Mean   :  131.5   Mean   :  272.3  
##  3rd Qu.:    1.0   3rd Qu.:   15.5   3rd Qu.:    0.0   3rd Qu.:    0.0  
##  Max.   :11050.0   Max.   :25900.0   Max.   :13200.0   Max.   :29379.0  
##    OCTUBRE.22          Nov.22            dic.22            ene.23        
##  Min.   :    0.0   Min.   :  0.000   Min.   :  0.000   Min.   :  0.0000  
##  1st Qu.:    0.0   1st Qu.:  0.000   1st Qu.:  0.000   1st Qu.:  0.0000  
##  Median :    0.0   Median :  0.000   Median :  0.000   Median :  0.0000  
##  Mean   :  120.9   Mean   :  2.113   Mean   :  1.225   Mean   :  0.5974  
##  3rd Qu.:    0.0   3rd Qu.:  0.000   3rd Qu.:  0.000   3rd Qu.:  0.0000  
##  Max.   :16421.0   Max.   :324.000   Max.   :276.000   Max.   :138.0000  
##      Feb.23      Mar.23   TOTAL.MESES    
##  Min.   :0   Min.   :0   Min.   :     0  
##  1st Qu.:0   1st Qu.:0   1st Qu.:    16  
##  Median :0   Median :0   Median :   115  
##  Mean   :0   Mean   :0   Mean   :  2306  
##  3rd Qu.:0   3rd Qu.:0   3rd Qu.:   724  
##  Max.   :0   Max.   :0   Max.   :136754
str(dpl)
## 'data.frame':    231 obs. of  27 variables:
##  $ CLIENTE.PLANTA: chr  "STB3" "STB4" "STB5" "STB6" ...
##  $ PROYECTO      : chr  "CANASTILLA GRIS" "Caja inter chica" "CHAROLA G09" "" ...
##  $ ID.ODOO       : chr  "15.785" "" "19.12" "19.211" ...
##  $ ITEM          : chr  "CABLE SET CAJA BACK UP CANASTILLA" "Caja intercompañía chica" "CHAROLA G09 915898  " "MOTOR GEAR BOX" ...
##  $ JUNIO         : int  0 0 0 0 0 0 0 0 0 192 ...
##  $ JULIO         : int  140 0 0 0 0 300 0 0 0 463 ...
##  $ AGOSTO        : int  530 0 0 0 0 0 0 50 0 226 ...
##  $ SEPTIEMBRE    : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ OCTUBRE       : int  200 0 0 0 0 0 0 0 0 0 ...
##  $ NOVIEMBRE     : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ DICIEMBRE     : int  150 184 75 1 0 0 9 0 0 0 ...
##  $ ene.22        : int  230 125 126 0 0 0 0 0 0 0 ...
##  $ Feb.22        : int  500 55 10 1 0 0 0 0 0 0 ...
##  $ Mar.22        : int  0 55 5 0 0 0 0 0 0 0 ...
##  $ abr.22        : int  0 0 0 1 0 400 0 0 0 0 ...
##  $ May.22        : int  0 0 15 3 0 0 0 0 0 0 ...
##  $ Jun.22        : int  200 0 5 2 100 0 0 0 0 0 ...
##  $ Jul.22        : int  900 0 10 5 100 0 0 0 0 0 ...
##  $ ago.22        : int  1000 0 0 3 0 0 0 0 0 0 ...
##  $ Sep.22        : int  0 0 5 4 0 0 0 0 0 0 ...
##  $ OCTUBRE.22    : int  0 0 50 6 0 0 0 0 0 0 ...
##  $ Nov.22        : int  0 0 125 7 0 0 0 0 0 0 ...
##  $ dic.22        : int  0 0 0 7 0 0 0 0 0 0 ...
##  $ ene.23        : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Feb.23        : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Mar.23        : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ TOTAL.MESES   : int  3850 419 426 40 200 700 9 50 0 881 ...
dim(dpl)
## [1] 231  27
apply(is.na(dpl), 2, sum)
## CLIENTE.PLANTA       PROYECTO        ID.ODOO           ITEM          JUNIO 
##              0              0              0              0              0 
##          JULIO         AGOSTO     SEPTIEMBRE        OCTUBRE      NOVIEMBRE 
##              0              0              0              0              0 
##      DICIEMBRE         ene.22         Feb.22         Mar.22         abr.22 
##              0              0              0              0              0 
##         May.22         Jun.22         Jul.22         ago.22         Sep.22 
##              0              0              0              0              0 
##     OCTUBRE.22         Nov.22         dic.22         ene.23         Feb.23 
##              0              0              0              0              0 
##         Mar.23    TOTAL.MESES 
##              0              0
colnames(dpl)
##  [1] "CLIENTE.PLANTA" "PROYECTO"       "ID.ODOO"        "ITEM"          
##  [5] "JUNIO"          "JULIO"          "AGOSTO"         "SEPTIEMBRE"    
##  [9] "OCTUBRE"        "NOVIEMBRE"      "DICIEMBRE"      "ene.22"        
## [13] "Feb.22"         "Mar.22"         "abr.22"         "May.22"        
## [17] "Jun.22"         "Jul.22"         "ago.22"         "Sep.22"        
## [21] "OCTUBRE.22"     "Nov.22"         "dic.22"         "ene.23"        
## [25] "Feb.23"         "Mar.23"         "TOTAL.MESES"

Cambiamos el nombre de las variables

colnames(dpl)<- c("cliente","proyecto","id_odoo","item","A_jun_21","B_jul_21","C_ago_21","D_sep_21","E_oct_21","F_nov_21","G_dic_21","H_ene_22","I_feb_22","J_mar_22","K_abr_22","L_may_22","M_jun_22","N_jul_22","O_ago_22","P_sep_22","Q_oct_22","R_nov_22","S_dic_22","T_ene_23","U_feb_23","V_mar_23","total_meses")

Agregamos nuevas columnas y valores para unir los pedidos programados

dpl <- pivot_longer(dpl, cols=5:14, names_to = "Mes", values_to = "Unidades")

Eliminamos columnas innecesarias

dpl <- filter(dpl, Unidades>0)

dpl1 <- dpl         
dpl1 <- subset (dpl, select = -c (proyecto, id_odoo, item, K_abr_22, L_may_22, M_jun_22,N_jul_22,O_ago_22, P_sep_22, Q_oct_22, R_nov_22,  S_dic_22, T_ene_23,U_feb_23, V_mar_23, total_meses))

Cambiamos tipo de variable

dpl1$Unidades <- as.numeric(dpl1$Unidades)

Analisis Descriptivo

La base de datos de Delivery Plan cuenta con 590 registros y 19 variables.

dim(dpl)
## [1] 590  19

Estadísticos descrptivos

mea21 <- mean(dpl1$Unidades)
med21 <- median(dpl1$Unidades)
moda21<- mfv(dpl1$Unidades)
sd21 <- sd(dpl1$Unidades, na.rm = TRUE)


Variables <-c("Unidades")
Media <-c(mea21)
Mediana <-c(med21)
Moda <-c(moda21)
Desviacion <-c(sd21)
tabla3 <-data.frame(Variables, Media, Mediana, Moda,Desviacion)
knitr::kable(tabla3)
Variables Media Mediana Moda Desviacion
Unidades 358.3729 80 60 1002.834

En FORM el promedio de unidades programadas por cliente es de 358 unidades.

Variable<-c("Cliente", "Mes", "Unidades")
Tipo<-c("Cualitativa", "Cualitativa", "Cuantitativa continua")
Medición<-c("NA", "NA", "Unidades")
tabla8<-data.frame(Variable,Tipo, Medición)
tabla8
##   Variable                  Tipo Medición
## 1  Cliente           Cualitativa       NA
## 2      Mes           Cualitativa       NA
## 3 Unidades Cuantitativa continua Unidades

Graficas

Time Series Plot

Para poder realizar un time series plot es necesario convertir nuestras variables a fecha.

dpl1$Mes <- replace(dpl1$Mes,dpl1$Mes=="B_jul_21","2021/07/01")
dpl1$Mes <- replace(dpl1$Mes,dpl1$Mes=="C_ago_21","2021/08/01")
dpl1$Mes <- replace(dpl1$Mes,dpl1$Mes=="E_oct_21","2021/10/01")
dpl1$Mes <- replace(dpl1$Mes,dpl1$Mes=="G_dic_21","2021/12/01")
dpl1$Mes <- replace(dpl1$Mes,dpl1$Mes=="H_ene_22","2022/01/01")
dpl1$Mes <- replace(dpl1$Mes,dpl1$Mes=="I_feb_22","2022/02/01")
dpl1$Mes <- replace(dpl1$Mes,dpl1$Mes=="J_mar_22","2022/03/01")
dpl1$Mes <- replace(dpl1$Mes,dpl1$Mes=="A_jun_21","2021/06/01")
dpl1$Mes <- replace(dpl1$Mes,dpl1$Mes=="F_nov_21","2021/11/01")
dpl1$Mes <- replace(dpl1$Mes,dpl1$Mes=="D_sep_21","2021/09/01")

dpl1$Mes <- as.Date(dpl1$Mes, format = "%d/%m/%y")



p <- ggplot(dpl1, aes(x=Mes, y=Unidades)) +
  geom_line( color="steelblue") + 
  geom_point() +
  xlab("") +
  theme(axis.text.x=element_text(angle=60, hjust=1)) +
  scale_x_date(limit=c(as.Date("2021-06-01"),as.Date("2022-03-01"))) +
  ylim(0,13120)

p
## Warning: Removed 590 row(s) containing missing values (geom_path).
## Warning: Removed 590 rows containing missing values (geom_point).

Esta grafica nos ayuda a visualizar los picos de pedidos en distintos meses, siendo el de Julio del 2021 el mayor pico de Unidades programadas en el año.

Grafica Datos cualitativos

library(treemap)
treemap(dpl1,
            index="cliente",
            vSize="Unidades",
            type="index"
            )

Esta grafica, nos ayuda a visualizar los clientes mas grandes de FORM, los cuales son Hella, TRMX y VARROC

Delivery Performance

***Importamos la base de datos

dpe <- read.csv("C:\\Users\\chema\\Downloads\\FORM - Delivery Performance (1).csv")

Entendemos la base de datos

summary(dpe) 
##      Target    Cliente             Vueltas      Plan.arrival   
##  Min.   :1   Length:1440        Min.   :1.00   Min.   : 0.000  
##  1st Qu.:1   Class :character   1st Qu.:1.00   1st Qu.: 0.000  
##  Median :1   Mode  :character   Median :1.50   Median : 4.000  
##  Mean   :1                      Mean   :1.75   Mean   : 6.625  
##  3rd Qu.:1                      3rd Qu.:2.25   3rd Qu.:10.750  
##  Max.   :1                      Max.   :3.00   Max.   :20.000  
##   Real.arrival    Real.departure     Diference            Date          
##  Min.   : 0.000   Min.   : 0.000   Min.   :-14.3500   Length:1440       
##  1st Qu.: 0.000   1st Qu.: 0.000   1st Qu.:  0.0000   Class :character  
##  Median : 0.000   Median : 0.000   Median :  0.0000   Mode  :character  
##  Mean   : 3.823   Mean   : 4.142   Mean   :  0.3155                     
##  3rd Qu.: 8.000   3rd Qu.: 9.000   3rd Qu.:  0.8000                     
##  Max.   :23.500   Max.   :24.500   Max.   : 20.0000
str(dpe)
## 'data.frame':    1440 obs. of  8 variables:
##  $ Target        : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Cliente       : chr  "PRINTEL " "MAHLE" "MAHLE" "MAHLE" ...
##  $ Vueltas       : int  1 1 2 3 1 1 2 3 1 1 ...
##  $ Plan.arrival  : int  16 8 9 20 0 0 0 0 16 8 ...
##  $ Real.arrival  : num  16 8 9 20 0 0 0 0 16 8 ...
##  $ Real.departure: num  19.3 8.55 10 21 0 0 0 0 18.1 9 ...
##  $ Diference     : num  3.3 0.55 1 1 0 0 0 0 2.1 1 ...
##  $ Date          : chr  "02/01/2022" "02/01/2022" "02/01/2022" "02/01/2022" ...
dim(dpe)
## [1] 1440    8
apply(is.na(dpe), 2, sum)
##         Target        Cliente        Vueltas   Plan.arrival   Real.arrival 
##              0              0              0              0              0 
## Real.departure      Diference           Date 
##              0              0              0
colnames(dpe)
## [1] "Target"         "Cliente"        "Vueltas"        "Plan.arrival"  
## [5] "Real.arrival"   "Real.departure" "Diference"      "Date"

Limpieza de datos

Esta base de datos anteriormente fue limpiada atraves de excel, por lo que no será necesario realizar mucho codigo para limpiarla. Lo unico que es necesario hacer confines de graficación de datos, es convertir en fecha la variable de Date.

Cambiar tipo de Variable

  dpe$Date <-as.Date(dpe$Date,format ="%m/%d/%Y")

Analisis Descriptivos

La base de datos de Delivery Performance cuenta con 1440 registros y 8 variables.

dim(dpe)
## [1] 1440    8

Tipos de variable

Variable <- c("`Target`","`Cliente`","`Vueltas`","`Plan.arrival`","`Real.arrival`","`Plan.departure`","`Diference`","`Date`")
Tipo <- c("cuantitativo (discreto)  ", "cualitativo  ", "cuantitativo (discreto)  ", "cuantitativo (continuo)  ", "cuantitativo (continuo)  ", "cuantitativo (continuo)  ", "cuantitativo (continuo)  ", "cualitativo  ")
Medición <- c("Entregas", "NA", "Vueltas", "Tiempo", "Tiempo", "Tiempo", "Tiempo", "FECHA")
table8 <- data.frame (Variable, Tipo, Medición)
knitr::kable(table8)
Variable Tipo Medición
Target cuantitativo (discreto) Entregas
Cliente cualitativo NA
Vueltas cuantitativo (discreto) Vueltas
Plan.arrival cuantitativo (continuo) Tiempo
Real.arrival cuantitativo (continuo) Tiempo
Plan.departure cuantitativo (continuo) Tiempo
Diference cuantitativo (continuo) Tiempo
Date cualitativo FECHA

Analisis Exploratorio

Medidas Estadisticas

mea <- mean(dpe$Target)
med <- median(dpe$Target)
moda <- mfv(dpe$Target)
sd <- sd(dpe$Target, na.rm = TRUE)

mea1 <- mean(dpe$Vueltas)
med1 <- median(dpe$Vueltas)
moda1 <- mfv(dpe$Vueltas)
sd1 <- sd(dpe$Vueltas, na.rm = TRUE)

mea2 <- mean(dpe$Plan.arrival)
med2 <- median(dpe$Plan.arrival)
moda2 <- mfv(dpe$Plan.arrival)
sd2 <- sd(dpe$Plan.arrival, na.rm = TRUE)

mea3 <- mean(dpe$Real.arrival)
med3 <- median(dpe$Real.arrival)
moda3 <- mfv(dpe$Real.arrival)
sd3 <- sd(dpe$Real.arrival, na.rm = TRUE)

mea4 <- mean(dpe$Real.departure)
med4 <- median(dpe$Real.departure)
moda4 <- mfv(dpe$Real.departure)
sd4 <- sd(dpe$Real.departure, na.rm = TRUE)

mea5 <- mean(dpe$Diference)
med5 <- median(dpe$Diference)
moda5 <- mfv(dpe$Diference)
sd5 <- sd(dpe$Diference, na.rm = TRUE)

Variables <-c("Target","Vueltas","Plan Arrival", "Real Arrival", "Real Departure", "Diference")
Media <-c(mea,mea1,mea2,mea3,mea4,mea5)
Mediana <-c(med,med1,med2,med3,med4, med5)
Moda <-c(moda,moda1,moda2,moda3,moda4,moda5)
Desviacion <-c(sd,sd1,sd2,sd3,sd4,sd5)
tabla5 <-data.frame(Variables, Media, Mediana,Moda,Desviacion)
knitr::kable(tabla5)
Variables Media Mediana Moda Desviacion
Target 1.000000 1.0 1 0.0000000
Vueltas 1.750000 1.5 1 0.8294442
Plan Arrival 6.625000 4.0 0 7.5015634
Real Arrival 3.822792 0.0 0 6.5059024
Real Departure 4.141972 0.0 0 6.9486646
Diference 0.315500 0.0 0 0.9218758

Graficas

p <- ggplot(dpe, aes(x=Date, y=Vueltas)) +
  geom_line( color="steelblue") + 
  geom_point() +
  xlab("") +
  theme_ipsum() +
  theme(axis.text.x=element_text(angle=60, hjust=1)) +
  scale_x_date(limit=c(as.Date("2022-01-02"),as.Date("2022-01-12"))) 
p
## Warning: Removed 1392 row(s) containing missing values (geom_path).
## Warning: Removed 1392 rows containing missing values (geom_point).
## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## 'Arial Narrow' not found, will use 'sans' instead
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family 'Arial Narrow' not found, will use 'sans' instead
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family 'Arial Narrow' not found, will use 'sans' instead

Esta grafica se puede utilizar con cualquiera de las variables de Delivery Performance, para conocer el comportamiento que estas tienen con el pasar del tiempo, en este caso se seleccionó Vueltas en el periodo del primero de enero de esta año, hasta el 12, en este periodo de tiempo podemos ver distintos picos.

Barplot

boxplot(Real.arrival ~ Plan.arrival, data = dpe,
        main = "Real Arrival vs Planed Arrival",
        col = rainbow(ncol(trees)))

Esta grafica nos muestra la disperción que existe entre el tiempo llegada real de las entregas y el tiempo de llegada planeada.

Producción

pr <- read.csv("C:\\Users\\chema\\Desktop\\produccion.csv")

Analizamos la base de datos

Limpieza de datos

En esta base de datos existen algunas variables que no serán necesarias para realizar un analisis estadistico, es por eso que se decidió borrarlas.

Eliminamos Columnas que no se utilizarán

pr <- subset(pr,select = -c (no, id_form, producto, hora_fin, inicio_setup, fin_inicio_su, inicio_proceso, fin_proceso, tiempo_materiales, merma))

Cambiamos valores de NA´s por la MEDIANA

pr<-pr %>% mutate(piezas_prog=ifelse(is.na(piezas_prog),median(piezas_prog,na.rm=T),piezas_prog))
pr<-pr %>% mutate(tiempo_minutos=ifelse(is.na(tiempo_minutos),median(tiempo_minutos,na.rm=T),tiempo_minutos))
pr<-pr %>% mutate(laminas_procesadas=ifelse(is.na(laminas_procesadas),median(laminas_procesadas,na.rm=T),laminas_procesadas))
pr<-pr %>% mutate(tiempo_calidad=ifelse(is.na(tiempo_calidad),median(tiempo_calidad,na.rm=T),tiempo_calidad))

Convertimos variables

pr$fecha<-as.Date(pr$fecha,format="%d/%m/%Y")
pr$piezas_prog<-as.numeric(pr$piezas_prog)
## Warning: NAs introduced by coercion
pr$tiempo_minutos<-as.numeric(pr$tiempo_minutos)
## Warning: NAs introduced by coercion
pr$laminas_procesadas<-as.numeric(pr$laminas_procesadas)
## Warning: NAs introduced by coercion

Subsituir NA´s por la media

pr$tiempo_minutos[is.na(pr$tiempo_minutos)]<-median(pr$tiempo_minutos, na.rm = TRUE)
pr$tiempo_calidad[is.na(pr$tiempo_calidad)]<-median(pr$tiempo_calidad, na.rm = TRUE)
pr$laminas_procesadas[is.na(pr$laminas_procesadas)]<-median(pr$laminas_procesadas, na.rm = TRUE)

Analisis Exploratorio

mea2 <- mean(pr$piezas_prog)
med2 <- median(pr$piezas_prog)
moda2<- mfv(pr$piezas_prog)
sd2 <- sd(pr$piezas_prog, na.rm = TRUE)

mea3 <- mean(pr$tiempo_minutos)
med3 <- median(pr$tiempo_minutos)
moda3 <- mfv(pr$tiempo_minutos)
sd3 <- sd(pr$tiempo_minutos, na.rm = TRUE)

mea4 <- mean(pr$laminas_procesadas)
med4 <- median(pr$laminas_procesadas)
moda4 <- mfv(pr$laminas_prog)
sd4 <- sd(pr$laminas_procesadas, na.rm = TRUE)

mea5 <- mean(pr$tiempo_calidad)
## Warning in mean.default(pr$tiempo_calidad): argument is not numeric or logical:
## returning NA
med5 <- median(pr$tiempo_calidad)
moda5 <- mfv(pr$tiempo_calidad)
sd5 <- sd(pr$tiempo_calidad, na.rm = TRUE)
## Warning in var(if (is.vector(x) || is.factor(x)) x else as.double(x), na.rm =
## na.rm): NAs introduced by coercion
moda6 <-  mfv(pr$cliente)
moda <- mfv(pr$fecha) 
moda1 <- mfv(pr$estacion_arranque)

Variables <-c("Piezas_prog","Tiempo Minutos", "Laminas procesadas", "Tiempo Calidad", "Cliente","Fecha","Estación de Arranque")
Media <-c(mea2,mea3,mea4,mea5,"NA","NA","NA")
Mediana <-c(med2,med3,med4,med5,"NA","NA","NA")
Moda <-c(moda2,moda3,moda4,moda5,moda6,moda,moda1)
Desviacion <-c(sd2,sd3,sd4,sd5,"NA","NA","NA")
tabla2 <-data.frame(Variables, Media, Mediana, Moda,Desviacion)
knitr::kable(tabla2)
Variables Media Mediana Moda Desviacion
Piezas_prog NA NA NA 153.96601715546
Tiempo Minutos 21.183497351075 20 20 9.44792242800397
Laminas procesadas 47.9842101223844 11 NaN 100.830331569012
Tiempo Calidad NA 2.51228375075327
Cliente NA NA STABILUS 1 NA
Fecha NA NA NA NA
Estación de Arranque NA NA NA

Tabla de variables y medición

Variable<-c("Fecha", "Cliente", "Piezas Programadas", "Tiempo Mínimo", "Estación Arranque", "Láminas Procesadas", "Tiempo de Calidad")
Tipo <-c("Cualitativa", "Cualitativa", "Cuantitativa continua", "Cuantitativa continua", "Cualitativa", "Cuantitativa continua", "Cuantitativa continua")
Medición <-c("NA", "NA", "Unidades", "Minutos", "Na", "Unidades", "Minutos")
tab<-data.frame(Variable,Tipo,Medición)
tab
##             Variable                  Tipo Medición
## 1              Fecha           Cualitativa       NA
## 2            Cliente           Cualitativa       NA
## 3 Piezas Programadas Cuantitativa continua Unidades
## 4      Tiempo Mínimo Cuantitativa continua  Minutos
## 5  Estación Arranque           Cualitativa       Na
## 6 Láminas Procesadas Cuantitativa continua Unidades
## 7  Tiempo de Calidad Cuantitativa continua  Minutos

Graficas

hist(pr$piezas_prog, main = "Laminas Procesadas", ylab = "Frecuencia", xlab = "Piezas Programadas", col = "red")

Merma

me <- read.csv("C:\\Users\\chema\\Downloads\\FORM1 - Merma.csv")

Limpieza

Eliminamos filas de totales

me1<-me[-c(5,12,19,25,31,36,42,54,59,60),]

Convertimos Variables

me1$Fecha<-as.Date(me1$Fecha, format = "%m/%d/%Y")
me1$Kilos<-as.numeric(me1$Kilos)

Analisis Exploratorio

mea20<- mean(me1$Kilos)
med20<- median(me1$Kilos)
moda20<- mfv(me1$Kilos)
sd20<- sd(me1$Kilos, na.rm = TRUE)

Variables1 <-c("Kilos")
Media1 <-c(mea20)
Mediana1 <-c(med20)
Moda1 <-c(moda20)
Desviacion1 <-c(sd20)
tabla20 <-data.frame(Variables1, Media1, Mediana1, Moda1,Desviacion1)
knitr::kable(tabla20)
Variables1 Media1 Mediana1 Moda1 Desviacion1
Kilos 3708.52 3925 3140 1023.99
Kilos 3708.52 3925 3810 1023.99
Kilos 3708.52 3925 4190 1023.99
Kilos 3708.52 3925 4200 1023.99

Tabla de variables y medición

Variable<-c("Fecha", "Mes", "Kilos")
Tipo<-c("Cualitativa", "Cualitativa", "Cuantitativa continua")
Medición <-c("NA", "NA", "Kilogramos")
tab<-data.frame(Variable,Tipo, Medición)
tab
##   Variable                  Tipo   Medición
## 1    Fecha           Cualitativa         NA
## 2      Mes           Cualitativa         NA
## 3    Kilos Cuantitativa continua Kilogramos

Graficas

library(ggplot2)

ggplot(me1, aes(x=as.factor(Mes), fill=as.factor(Kilos) )) + 
  geom_bar( ) +
  scale_fill_grey(start = 0.25, end = 0.75) +
  theme(legend.position="none")

En esta grafica podemos ver cual es el mes que mas merma genera, el cual es el mes de Agosto.

Scrap

sc <- read.csv("C:\\Users\\chema\\Downloads\\FORM1 - Scrap (1).csv")

Limpieza

Cambiamos el tipo de variable

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

Media, Moda, Mediana y Desviación Estandar

mea22<- mean(sc$Cant)
med22<- median(sc$Cant)
moda22<- mfv(sc$Cant)
sd22<- sd(sc$Cant, na.rm = TRUE)

Variables8 <-c("Cantidad")
Media8 <-c(mea22)
Mediana8 <-c(med22)
Moda8 <-c(moda22)
Desviacion8 <-c(sd22)
tabla22 <-data.frame(Variables8, Media8, Mediana8, Moda8,Desviacion8)
knitr::kable(tabla22)
Variables8 Media8 Mediana8 Moda8 Desviacion8
Cantidad 6.726908 2 1 11.86371

Tabla de variables y medición

Variable<-c("Fecha", "Cantidad", "Ubicación de Origen")
Tipo<-c("Cualitativa", "Cuantitativa continua", "Cualitativa")
Medición <-c("NA", "Kilogramos", "NA")
tabla8<-data.frame(Variable,Tipo, Medición)
tabla8
##              Variable                  Tipo   Medición
## 1               Fecha           Cualitativa         NA
## 2            Cantidad Cuantitativa continua Kilogramos
## 3 Ubicación de Origen           Cualitativa         NA

Graficas

ggplot(sc, aes(x=as.factor(Ubi.origen), fill=as.factor(Cant) )) + 
  geom_bar( ) +
  scale_fill_grey(start = 0.25, end = 0.75) +
  theme(legend.position="none")

Sección 2

Importamos base de datos externa

Sección 3

1. Conceptos Claves

K- Vecinos Más Cercanos y/o K-Means Clustering:
KNN y Kmeans clustering, son funciones las cuales ambas contribuyen a la identificación de clusters ya que KMC es un algoritmo el cual se utilizaa para agrupar, sin embargo KNN se utiliza mas que nada para la clasificación de variables. (Harrison, 2018) En la función de K-means clustering se divide un conjunto de n observaciones en k grupos, esta función se usa cuando no se tienen etiquetas de grupo existentes y desea asignar puntos de datos similares a la cantidad de grupos que especifique (K). (Jim Frost, 2022)

Aprendizaje No Supervisado y/o Unsupervised Learning:
El objetivo que tiene el unsupervised learning es el de descubrir grupos de ejemplos similares dentro de los datos, lo que se denomina “clustering”, o determinar cómo se distribuyen los datos en el espacio, lo que se conoce como estimación de densidad Esta función contribuye a la identificación de clusters ya que la agrupación en “clusters” es un método de “unsupervissed learning” que funciona en conjuntos de datos en los que no hay una variable de resultado (objetivo) ni se sabe nada sobre la relación entre las observaciones, es decir, datos sin etiquetar. (Frontiersin, 2019)

Distancia Euclidiana / Eucliedean Distance:
Al momento de usar “Euclidean distance” las observaciones con valores altos de características se “agruparán” juntas. Lo mismo se aplica a las observaciones con valores bajos de características. La correlación de Pearson mide el grado de una relación lineal entre dos perfiles. (Waref, 2020) En otras palabras, la distancia euclidiana es la distancia que hay entre dos datos en un espacio.

2. K-means Clustering

# descargar y llamar librerías
#install.packages("tidyverse")
library(tidyverse)
#install.packages("foreign")
#install.packages("dplyr")
library(ggplot2)
#install.packages("psych")
library(psych)
#install.packages("corrplot")
library(corrplot)
#install.packages("jtools")
library(jtools)
#install.packages("lmtest")
library(lmtest)
#install.packages("car")
library(car)
#install.packages("factoextra")
library(factoextra)
#install.packages("janitor")
library(janitor)
#install.packages("readr")
library(readr)
#install.packages("plotrix")
library(plotrix)

Limpiar base de datos

rh <- read.csv("/Users/chema/Downloads/recursos_humanos_base_limpia.csv")
# Limpiar nombre
library(janitor)
rh1 <- clean_names(rh)
# Visualizar base de datos
summary(rh1)
##   apellidos            nombre               edad       fecha_de_nacimiento
##  Length:233         Length:233         Min.   :19.00   Length:233         
##  Class :character   Class :character   1st Qu.:23.00   Class :character   
##  Mode  :character   Mode  :character   Median :29.00   Mode  :character   
##                                        Mean   :31.08                      
##                                        3rd Qu.:37.00                      
##                                        Max.   :61.00                      
##     genero              rfc            fecha_de_alta      motivo_de_baja    
##  Length:233         Length:233         Length:233         Length:233        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  dias_laborados        baja              puesto          departamento      
##  Min.   :   0.00   Length:233         Length:233         Length:233        
##  1st Qu.:   6.00   Class :character   Class :character   Class :character  
##  Median :  15.00   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :  72.73                                                           
##  3rd Qu.:  47.00                                                           
##  Max.   :1966.00                                                           
##  no_seguro_social   salario_diario_imss factor_cred_infonavit
##  Length:233         Min.   :144.4       Length:233           
##  Class :character   1st Qu.:180.7       Class :character     
##  Mode  :character   Median :180.7       Mode  :character     
##                     Mean   :177.9                            
##                     3rd Qu.:180.7                            
##                     Max.   :500.0                            
##  n_credito_infonavit lugar_de_nacimiento     curp              calle          
##  Length:233          Length:233          Length:233         Length:233        
##  Class :character    Class :character    Class :character   Class :character  
##  Mode  :character    Mode  :character    Mode  :character   Mode  :character  
##                                                                               
##                                                                               
##                                                                               
##  numero_interno       colonia          codigo_postal       municipio        
##  Length:233         Length:233         Length:233         Length:233        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##     estado          estado_civil       tarjeta_o_cuenta  
##  Length:233         Length:233         Length:233        
##  Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character  
##                                                          
##                                                          
## 
# Eliminar columnas que no se necesitan
rh2 <- subset(rh1,select = -c (apellidos, nombre, fecha_de_nacimiento, rfc, fecha_de_alta, baja, departamento, 
                               no_seguro_social, factor_cred_infonavit, n_credito_infonavit, lugar_de_nacimiento,
                               curp, calle, numero_interno, colonia, codigo_postal, municipio, estado, tarjeta_o_cuenta))
summary(rh2)
##       edad          genero          motivo_de_baja     dias_laborados   
##  Min.   :19.00   Length:233         Length:233         Min.   :   0.00  
##  1st Qu.:23.00   Class :character   Class :character   1st Qu.:   6.00  
##  Median :29.00   Mode  :character   Mode  :character   Median :  15.00  
##  Mean   :31.08                                         Mean   :  72.73  
##  3rd Qu.:37.00                                         3rd Qu.:  47.00  
##  Max.   :61.00                                         Max.   :1966.00  
##     puesto          salario_diario_imss estado_civil      
##  Length:233         Min.   :144.4       Length:233        
##  Class :character   1st Qu.:180.7       Class :character  
##  Mode  :character   Median :180.7       Mode  :character  
##                     Mean   :177.9                         
##                     3rd Qu.:180.7                         
##                     Max.   :500.0
# na's en la base de datos
sum(is.na(rh2))
## [1] 0
sapply(rh2, function(x) sum(is.na(x)))
##                edad              genero      motivo_de_baja      dias_laborados 
##                   0                   0                   0                   0 
##              puesto salario_diario_imss        estado_civil 
##                   0                   0                   0
# no se encuentran NA's en la base de datos 

# Convertir tipos de datos
rh2$edad <- as.numeric(rh2$edad)
rh2$genero <- as.factor(rh2$genero)
rh2$motivo_de_baja <- as.factor(rh2$motivo_de_baja)
rh2$dias_laborados <- as.numeric(rh2$dias_laborados)
rh2$puesto <- as.factor(rh2$puesto)
rh2$salario_diario_imss <- as.numeric(rh2$salario_diario_imss)
rh2$estado_civil <- as.factor(rh2$estado_civil)
summary(rh2)
##       edad             genero                motivo_de_baja dias_laborados   
##  Min.   :19.00   FEMENINO :137   ABANDONO           :  1    Min.   :   0.00  
##  1st Qu.:23.00   MASCULINO: 96   BAJA POR FALTAS    :139    1st Qu.:   6.00  
##  Median :29.00                   JUBILACION         :  1    Median :  15.00  
##  Mean   :31.08                   RENUNCIA VOLUNTARIA: 84    Mean   :  72.73  
##  3rd Qu.:37.00                   TERMINO DE CONTRATO:  8    3rd Qu.:  47.00  
##  Max.   :61.00                                              Max.   :1966.00  
##                                                                              
##                    puesto    salario_diario_imss      estado_civil
##  AYUDANTE GENERAL     :171   Min.   :144.4       divorcio   :  3  
##  COSTURERA            : 10   1st Qu.:180.7       matrimonio : 63  
##  SOLDADOR             : 10   Median :180.7       Sin Conocer:  1  
##  MONTACARGUISTA       :  5   Mean   :177.9       Soltero    :107  
##  AY. GENERAL          :  4   3rd Qu.:180.7       Unión libre: 59  
##  AUXILIAR DE EMBARQUES:  3   Max.   :500.0                        
##  (Other)              : 30

Crear clusters

Cluster 1: Edad y Número de días laborados

# Normalizar Variables
rh_edad_dias <-rh2 %>% dplyr::select(salario_diario_imss, edad, dias_laborados)
rh_edad_dias_norm<-scale(rh_edad_dias[2:3]) 
plot(rh_edad_dias_norm)

# Número óptimo de clústers con "Elbow Plot"
fviz_nbclust(rh_edad_dias_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=6, linetype=2)+           
  labs(subtitle = "Elbow method")  

De acuerdo al elbow method, el numero óptimo de clusters son 6 pero al momento de visualizarlo se determinó que es una elevada cantidad de clusters y no sería tan sencillo el interpretar y nombrar tantos clusters por lo que se llegó a la conclusión que se elaborarán 5 clusters.

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

Interpretación: Cluster número 1 y 4 son de edades diferentes pero tienen días laborados similares, igual que el cluster 3 y 5 . Por otro lado, el cluster 2 son datos que no tienen días laborados similares pero tienen más días que los otros clusters y tiene un rango diferente de edades. Por lo que se concluye que los días laborados no tienen tanta relación con la edad.

Cluster 2: Edad y Salario Diario

# Normalizar Variables
rh_edad_sal <-rh2 %>% dplyr::select(salario_diario_imss, edad, dias_laborados)
rh_edad_sal_norm<-scale(rh_edad_dias[1:2]) 
plot(rh_edad_sal_norm)

# Número óptimo de clústers con "Elbow Plot"
fviz_nbclust(rh_edad_sal_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=5, linetype=2)+           
  labs(subtitle = "Elbow method")  

Se determinó que el número óptimo es de 5 clusters

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

Interpretación: Todos tienen un salario similar sin importar la edad pero en el cluster 1 (que solo es un punto) nos indica que hay alguien que gana más que los demás colaboradores y tienen una edad relativamente joven a comparación de los demás datos

Cluster 3: Número de días laborados y Salario Diario

# Normalizar Variables
rh_dias_sal <-rh2 %>% dplyr::select(salario_diario_imss, dias_laborados, edad)
rh_dias_sal_norm<-scale(rh_dias_sal[1:2]) 
plot(rh_dias_sal_norm)

# Número óptimo de clústers con "Elbow Plot"
fviz_nbclust(rh_dias_sal_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=5, linetype=2)+           
  labs(subtitle = "Elbow method")  

Se determinó que el número óptimo es de 5 clusters

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

Interpretación: Los días laborados no tienen influencia en el salario porque hay datos que indican colaboradores que trabajan más días pero tienen un salario similar a los que no tienen tantos días laborados. En el cluster 2 podemos observar que es el que tiene un mayor salario pero no es el que tiene una cantidad alta de días laborados como es en el cluster 1. Por lo tanto, los días laborados no tienen relación con el salario.

Creación de segmmentos usando el cluster 2: Edad y Salario Diario

# Incluir columna que indique el cluster de cada registro
rh3 <- rh2
rh3$Clusters<-cluster2$cluster

# visualizar la máxima edad de cada cluster
rh4 <- rh3 %>% dplyr::group_by(Clusters) %>% dplyr::summarise(edad=max(edad)) %>% dplyr::arrange(desc(edad))

# Nombrar cada cluster 
rh3$nombres_clusters <- factor(rh3$Clusters,levels = c(1,2,3,4,5), 
                              labels=c("Excepcion", "Jubilados", "Mayores", "Adultos", "Jovenes"))

# Agrupar los datos por nombre de clusters 
library(dplyr)
rh5 <- rh3 %>% dplyr::group_by(nombres_clusters) %>% dplyr::summarize(edad_años=max(edad), 
                                                             salario_imss=mean(salario_diario_imss),
                                                             Count=n())

clusters<-as.data.frame(rh5)
clusters
##   nombres_clusters edad_años salario_imss Count
## 1        Excepcion        32     500.0000     1
## 2        Jubilados        61     175.2329    34
## 3          Mayores        43     180.5810    40
## 4          Adultos        36     175.1773    63
## 5          Jovenes        26     176.2086    95

Gráficos complementarios

Gráfico por nombre de cluster

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

Interpretación: Los jóvenes adultos son los que representan más número de bajas y se visualiza que el orden de número de bajas esta en el mismo orden de edad, esto significa que después de los jóvenes adultos el grupo que más representa bajas es el de los adultos y de ahí siguen los mayores, y por último los jubilados. En conclusión, la edad puede ser un factor importante en el número de bajas.

Gráfico del máximo de edad de cada cluster

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

Interpretación: Aquí se observa la máxima de edad de cada cluster y también muestra la razón por la que se dieron los nombres a cada cluster. Los jóvenes tienen un rango de edad de 19-26, Adultos 27-36, Mayores 37-43 y Jubilados 44-61.

Género de ex-colaboradores

library(ggplot2)
ggplot(rh3, aes(fill=genero, y=genero, x=nombres_clusters)) + 
  geom_bar(position="stack", stat="identity") 

Interpretación: En la gráfica se aprecia un número alto de género masculino en todos los clusters. En Jubilados y Mayores el género Femenino es mayor que el masculino.

Motivo de baja de ex-colaboradores

ggplot(rh3, aes(factor(nombres_clusters), fill = factor(motivo_de_baja))) +
  geom_bar(position = position_dodge2(preserve = "single"))

Interpretación: Se puede observar que el motivo de baja mas grande en todos los grupos de edades es la baja por faltas, seguido de renuncia voluntaria. En jóvenes se puede observar que hay baja por abandono, mientras que en los otros clusters no hubo ninguna baja por abandono.

Puesto de de ex-colaboradores

library(plyr)
count(rh3$puesto)
##                                   x freq
## 1  ANALISTA DE NOMINAS /AUX DE R.H.    1
## 2             AUXILIAR DE EMBARQUES    3
## 3                       AY. GENERAL    4
## 4           AY.GENERAL (MATERIALES)    1
## 5                    AYUD.EMBARQUES    1
## 6             AYUDANTE DE EMBARQUES    3
## 7                  AYUDANTE DE MTTO    1
## 8              AYUDANTE DE SOLDADOR    1
## 9                  AYUDANTE GENERAL  171
## 10    AYUDANTE GENERAL DE EMBARQUES    1
## 11                           CHOFER    1
## 12                         CORTADOR    1
## 13                        COSTURERA   10
## 14                        COSTURERO    1
## 15                           DISEÑO    1
## 16             ENCARGADA DE CALIDAD    1
## 17                      FACTURACION    1
## 18             GUARDIA DE SEGURIDAD    2
## 19                INSPECTOR CALIDAD    1
## 20             INSPECTOR DE CALIDAD    2
## 21            INSPECTORA DE CALIDAD    1
## 22                         LIMPIEZA    1
## 23                        MARCADORA    1
## 24                     MATERIALISTA    2
## 25                   MONTACARGUISTA    5
## 26              PRACTICANTE DE MTTO    1
## 27                        RESIDENTE    2
## 28                Residente Yanfeng    1
## 29              SERVICIO AL CLIENTE    1
## 30                         SOLDADOR   10
proporciones <- c(176, 11, 11, 8, 26)
eti <- c("ayudante general", "ayu. soldador/soldador", "costurera", "ayu. embarque", "otros" )
pct <- round(proporciones/sum(proporciones)*100)
eti <- paste(eti, pct)
eti <- paste(eti,"%",sep="")
pie3D(proporciones,labels = eti,
    col=rainbow(length(eti)),
    main="Puestos de bajas")

Interpretación: el puesto en el que más se presentan bajas es en ayudante general, seguido de ayudante soldador/soldador, costurera, etc. Una de las posibles razones por la que haya más bajas en ayudante general, es porque en ese puesto se necesitan más colaboradores, por lo que el número de bajas en ese puesto puede ser mayor o también puede ser el ambiente general que se crea en ese puesto, estás hipotésis se comprobarían con un análisis más profundo de RH.

Estado civil de ex-colaboradores

ggplot(rh3, aes(factor(nombres_clusters), fill = factor(estado_civil))) +
  geom_bar(position = position_dodge2(preserve = "single"))

proporciones1 <- c(107, 3, 59, 63)
etiquetas <- c("soltero", "divorcio", "union libre", "matrimonio")
pct <- round(proporciones1/sum(proporciones1)*100)
etiquetas <- paste(etiquetas, pct)
etiquetas <- paste(etiquetas,"%",sep="")
pie3D(proporciones1,labels = etiquetas,
      col=rainbow(length(etiquetas)),
      main="Estado civil de bajas")

Interpretación: En el total de bajas el estado civil más común es “soltero”, siendo los jóvenes los que tienen una mayor cantidad de este atributo, seguido de los adultos. Después, está el matrimonio siendo este el más presente en el grupo de adultos, seguido de los jóvenes. El divorcio no es tán común en los grupos.

En conclusión, se puede deducir que la mayoría de los ex-colaboradores son solteros, por lo que es más fácil renunciar al no tener una extensa y/o propia familia. Ya que los solteros son la mayoría, por ende los jóvenes son los más propensos en darse de baja en FORM.

3. Principales hallazgos

  • Si bien, la empresa hace mención de incentivos salariales a los colaboradores, los datos capturados y compartidos por parte de la organización unicamente muestran los salarios fijos (es decir, independientemente de horas extra) y por consiguiente, se puede correlacionar que no necesariamente la edad tiene una relación o impacto directo al nivel de salario otorgado a los colaboradores, con excepción de una persona: tratandose del dueño/director, quien posee un salario mayor, siendo este menor que muchos colaboradores presentes en la estructura organizacional.

  • Primeramente, se demuestra que si bien, el salario de los colaboradores corresponde correctamente de acuerdo a su contrato; estrictamente refiriendose al salario IMSS, no se muestra una diferencia en los salarios con la excepción de una persona quien se infiere es el director/dueño de la empresa quien debido a su posición jerárquica, goza de mejor salario/beneficios del IMSS.

  • Entre más jóven se es, mayor la probabilidad de darse de baja de la empresa.

  • Existen grupos de edad, los cuales constan de: Adultos jóvenes, Adultos, Adultos mayores y Jubilados, que forman parte de la organización.

  • El genero femenino tiene mayor presencia en el grupo de edad de jubilados y adultos mayores, en comparación con los grupos de Adultos y Jovenes, donde se tiene mayor presencia por parte del genero masculino. Con esto, se puede inferir con sustento que la presencia de mujeres en grupos de edad mas avanzada es debido a que son madres solteras y/o recurren a lineas de trabajo de este tipo para dar sustento y contribuir a la economía familiar.

  • El grupo con más bajas en todas las categorías de dicha actividad es el de Jóvenes, con la peculiaridad de que existen personas que simplemente dejan de asistir a sus labores.

  • Respecto a las bajas en función de los diferentes puestos existentes en la planta, se puede sustentar que donde existen más bajas es en el puesto de “Ayudante general” (representa el 76% de las bajas totales) por lo que se puede inferir que al ser el puesto con mayor demanda, vacantes ofrecidas y colaboradores quienes participan en dicha area, tiene sentido que destaquen las bajas con respecto a los otros puestas. En otras palabras, el número de bajas es proporcional al número de colaboradores presentes en cada puesto.

Propuestas

  • Elevar niveles salariales y/o prestaciones de acuerdo a la antigüedad y experiencia previa del colaborador.

  • Dada la correlación de la edad jóven y la concentración de colaboradores que se dan de baja, se propone un programa de retención de talento, el cual en conjunto con areas afines a cultura organizacional (RR.HH), que se encargue desde un inicio de atraer el mejor talento, desarrollarlo, retenerlo y dar seguimiento a su “employee journey” para evitar esas bajas.

  • Diseñar un programa de apoyo a madres solteras y/o con necesidad económica, donde se den prestaciones adicionales (no necesariamente de contexto salarial) enfocadas hacia los hijos/as de las colaboradores como por ejemplo, apoyo en material escolar, comida preparada para lunches, entre otras prestaciones que contribuyan a la retención de la colaboradora, y se apoye a la necesidad, y por consiguiente razón de trabajar en Form.

  • Instaurar una política y/o proceso institucional donde el colaborador deba indicar su baja de la empresa con 1 – 2 semanas de antelación, ya que de esta manera tienen la posibilidad de ser acreedores a una indemnización, y por otra parte, la empresa puede comenzar un nuevo proceso de atracción de talento sin afectar la productividad de la planta.

  • Programa de retención de talento #2: Como se estableció previamente, el número de bajas es proporcional al número de colaboradores presentes en cada puesto, por lo que específicamente para el ayudante general, donde hay mayor número de colaboradores, es importante ofrecer mayores beneficios para el colaborador, mejores condiciones de trabajo, integración con el equipo, entre otras acciones que apunten a mitigar en lo posible, la baja de estas personas en este puesto.

Sección 4

  1. El mes con mas merma producida de FORM es el mes de agosto, al mismo tiempo que es el mes con mayor producción de piezas

  2. Julio del 2021 es el mes con mas Unidades programadas en el año.

  3. Gran parte del scrap de form se encuentra en su pre-producción

Bibliografía Frost, J. (2022, August 31). What is K means clustering? with an example. Statistics By Jim. Retrieved October 9, 2022, from https://statisticsbyjim.com/basics/k-means-clustering/#:~:text=The%20K%20means%20clustering%20algorithm,groups%20you%20specify%20(K). Harrison, O. (2019, July 14). Machine learning basics with the K-nearest neighbors algorithm. Medium. Retrieved October 9, 2022, from https://towardsdatascience.com/machine-learning-basics-with-the-k-nearest-neighbors-algorithm-6a6e71d01761 Mishra, S. (2017, May 21). Unsupervised learning and data clustering. Medium. Retrieved October 9, 2022, from https://towardsdatascience.com/unsupervised-learning-and-data-clustering-eeecb78b422a#:~:text=Clustering%20can%20be%20considered%20the,are%20similar%20in%20some%20way%E2%80%9D. Modifications. euclidean_cluster. (n.d.). Retrieved October 9, 2022, from https://autowarefoundation.gitlab.io/autoware.auto/AutowareAuto/euclidean-cluster-design.html

LS0tDQp0aXRsZTogPHNwYW4gc3R5bGU9IkNvbG9yOk9yYW5nZSIgPiAiRXZpZGVuY2lhIDIiDQphdXRob3I6ICJKb3PDqSBNYXLDrWEgRHVyYXpvIER1cmF6byINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KLS0tDQo8aW1nIHNyYz0iQzpcXFVzZXJzXFxjaGVtYVxcRG93bmxvYWRzXFx0ZWMtZGUtbW9udGVycmV5LWxvZ28ucG5nIj4NCg0KDQojICoqSW5pY2lvKioNCiMjICoqQ2FyZ2Ftb3MgbGlicmVyaWFzKioNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkocG9sbHN0ZXIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwbHlyKQ0KbGlicmFyeShqYW5pdG9yKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShhcnVsZXMpDQpsaWJyYXJ5KGZhY3RvZXh0cmEpDQpsaWJyYXJ5KEhtaXNjKQ0KbGlicmFyeShtb2RlZXN0KQ0KbGlicmFyeShmb3JlaWduKQ0KbGlicmFyeShmb3JjYXRzKSAgICAgIA0KbGlicmFyeShkbG9va3IpICAgICAgIA0KbGlicmFyeShjb3JycGxvdCkgICAgIA0KbGlicmFyeShqdG9vbHMpICAgICAgIA0KbGlicmFyeShsbXRlc3QpICAgICAgIA0KbGlicmFyeShjYXIpICAgICAgICAgIA0KbGlicmFyeShvbHNycikgICAgICAgIA0KbGlicmFyeShrYWJsZUV4dHJhKSANCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KYGBgDQoNCiMgKipSZWN1cnNvcyBIdW1hbm9zKioNCg0KYGBge3J9DQpyaDwtcmVhZC5jc3YoIkM6XFxVc2Vyc1xcY2hlbWFcXERvd25sb2Fkc1xccmVjdXJzb3NodW1hbm9zLmNzdiIpDQpzdW1tYXJ5KHJoKQ0Kc3RyKHJoKQ0KZGltKHJoKQ0KYXBwbHkoaXMubmEocmgpLCAyLCBzdW0pDQpyaCA8LSBjbGVhbl9uYW1lcyhyaCkNCmNvbG5hbWVzKHJoKQ0KYGBgDQoNClBvZGVtb3Mgbm90YXIgZW4gZXN0YSBiYXNlIGRlIGRhdG9zIGFsIHVzYXIgbGEgZnVuY2nDs24gZGUgc3VtbWFyeSwgcXVlIGV4aXN0ZW4gdmFyaWFzIHZhcmlhYmxlcyBxdWUgbm8gc2Vyw6FuIG5lY2VzYXJpYXMgcGFyYSB0cmFiYWphciBlbiBlc3RhIGJhc2UgZGUgZGF0b3MuIEFsIGlndWFsIHF1ZSBleGlzdGVuIHZhcmlhYmxlcyBxdWUgbmVjZXNpdGFuIHNlciBjYW1iaWFkYXMgZGUgdGlwbyBkZSB2YXJpYWJsZS5Qb3IgdWx0aW1vLCBhbGd1bm9zIGRlIGxvcyBjb2xhYm9yYWRvcmVzIG5vIGN1ZW50YW4gY29uIE51bWVybyBkZSBlbXBsZWFkbywgbG8gY3VhbCBvbWl0aXLDqSB5YSBxdWUgbm8gc2Vyw6EgbmVjZXNhcmlvIGRlIGVzYSBpbmZvcm1hY2nDs24uDQoNCkxhcyB2YXJpYWJsZXMgKmluZWNlc2FyaWFzKiBwYXJhIHJlYWxpemFyIHByb3hpbW9zIGFuYWxpc2lzIHNvbjogUkZDLCBCYWphLCBOdW1lcm8gZGUgc2VndXJvIHNvY2lhbCwgRmFjdG9yIGNyZWRpdG8gaW5mb25hdml0LCBjdXJwLCB0b2RhcyBsYXMgdmFyaWFibGVzIHJlbGFjaW9uYWRhcyBjb24gZWwgbmFjaW1pZW50byBkZSBsYSBwZXJzb25hIHkgc3UgdWJpY2FjacOzbiB5IHBvciB1bHRpbW8gc3UgY3VlbnRhIGJhbmNhcmlhLg0KDQojIyAqKkxpbXBpZXphIGRlIGRhdG9zKioNCg0KRW4gZXN0YSBiYXNlIGRlIGRhdG9zIHNlIGFwbGljYXJvbiA0IHRlY25pY2FzIGRlIGxpbXBpZXphOg0KMS4gU2UgY3Jlw7MgdW5hIG51ZXZhIGNvbHVtbmEgcGFyYSBOb21icmUgQ29tcGxldG8NCjIuIFNlIGVsaW1pbmFyb24geSBvcmRlbmFyb24gY29sdW1uYXMgcXVlIG5vIGVyYW4gbmVjZXNhcmlhcy4NCjMuIFNlIGNvcnJpZ2llcm9uIG5vbWJyZXMgZGUgdmFyaWFibGVzLCBhbCBtaXNtbyB0aWVtcG8gcXVlIHNlIGVzdGFuZGFyaXphcm9uIGFsZ3Vub3MgcmVnaXN0cm9zDQoNCg0KYGBge3J9DQpyaDwtbXV0YXRlKHJoLG5vbWJyZV9jb21wbGV0byA9IHBhc3RlKHJoJG5vbWJyZSwgcmgkYXBlbGxpZG9zLCBzZXA9IiAiKSkNCg0Kcmg8LWRwbHlyOjpzZWxlY3QocmgsLWMocmZjLGJhamEsbm9fY3JlZGl0b19pbmZvbmF2aXQsZmFjdG9yX2NyZWRfaW5mb25hdml0LGN1cnAsdGFyamV0YV9jdWVudGEsYXBlbGxpZG9zLG5vbWJyZSxjYWxsZSxudW1lcm9faW50ZXJubyxjb2xvbmlhLG11bmljaXBpbyxlc3RhZG8sY29kaWdvX3Bvc3RhbCx4NHRvX21lcyxwcmltZXJfbWVzLG5vX2RlX2VtcGxlYWRvLGx1Z2FyX2RlX25hY2ltaWVudG8sbm9fc2VndXJvX3NvY2lhbCkpDQoNCnJoPC1yaFssYyg4LDEsMiwzLDQsNSw2LDcpXQ0KDQpgYGANCg0KDQoqKipDYW1iaWFyIGZlY2hhcyBkZSBjYXJhY3TDqXIgYSB0aXBvIGRlIHZhcmlhYmxlIGNvcnJlY3RhKioqDQoNCg0KYGBge3J9DQpyaCRmZWNoYV9kZV9uYWNpbWllbnRvPC1hcy5EYXRlKHJoJGZlY2hhX2RlX25hY2ltaWVudG8sIGZvcm1hdCA9ICIlZC8lbS8lWSIpDQpyaCRmZWNoYV9kZV9hbHRhPC1hcy5EYXRlKHJoJGZlY2hhX2RlX2FsdGEsIGZvcm1hdCA9ICIlZC8lbS8lWSIpDQpgYGANCg0KDQoqKipFc3RhbmRhcml6YXIgcmVnaXN0cm9zIGRlIHB1ZXN0byB5IGRlcGFydGFtZW50byoqKg0KDQoNCg0KKioqUHVlc3RvKioqDQpgYGB7cn0NCnVuaXF1ZShyaCRwdWVzdG8pDQpyaCRwdWVzdG8gPC0gcmVwbGFjZShyaCRwdWVzdG8scmgkcHVlc3RvPT0iU3VwZXJ2aXNvciBkZSBNXHhlMXF1aW4iLCJTVVBFUlZJU09SKEEpIikNCnJoJHB1ZXN0byA8LSByZXBsYWNlKHJoJHB1ZXN0byxyaCRwdWVzdG89PSJTVVBFUlZJU09SQSIsIlNVUEVSVklTT1IoQSkiKQ0KcmgkcHVlc3RvIDwtIHJlcGxhY2UocmgkcHVlc3RvLHJoJHB1ZXN0bz09ICJTdXBlcnZpc29yIGRlIHBlZ2FkbyIsIlNVUEVSVklTT1IoQSkiKQ0KcmgkcHVlc3RvIDwtIHJlcGxhY2UocmgkcHVlc3RvLHJoJHB1ZXN0bz09ICJBeXVkYW50ZSBnZW5lcmFsIiAsIkFZVURBTlRFIEdFTkVSQUwiKQ0KcmgkcHVlc3RvIDwtIHJlcGxhY2UocmgkcHVlc3RvLHJoJHB1ZXN0bz09ICJBWS4gR0VORVJBTCIsIkFZVURBTlRFIEdFTkVSQUwiKQ0KcmgkcHVlc3RvIDwtIHJlcGxhY2UocmgkcHVlc3RvLHJoJHB1ZXN0bz09ICJBWVVEQU5URSBERSBNQU5URU5JTUlFTlRPIiwiQVlVREFOVEUgR0VORVJBTCIpDQpyaCRwdWVzdG8gPC0gcmVwbGFjZShyaCRwdWVzdG8scmgkcHVlc3RvPT0gIklOU1BFQ1RPUiBERSBDQUxJREFEIiwiSU5TUEVDVE9SKEEpIikNCnJoJHB1ZXN0byA8LSByZXBsYWNlKHJoJHB1ZXN0byxyaCRwdWVzdG89PSAiSU5TUEVDVE9SQSBERSBDQUxJREFEIiwiSU5TUEVDVE9SKEEpIikNCnJoJHB1ZXN0byA8LSByZXBsYWNlKHJoJHB1ZXN0byxyaCRwdWVzdG89PSAiQ0hPRkVSIEdFU1RPUiIsIkNIT0ZFUiIpDQpyaCRwdWVzdG8gPC0gdG91cHBlcihyaCRwdWVzdG8pDQp1bmlxdWUocmgkcHVlc3RvKQ0KYGBgDQoNCioqKkRlcGFydGFtZW50byoqKg0KYGBge3J9DQp1bmlxdWUocmgkZGVwYXJ0YW1lbnRvKQ0KDQpyaCRkZXBhcnRhbWVudG8gPC0gcmVwbGFjZShyaCRkZXBhcnRhbWVudG8scmgkZGVwYXJ0YW1lbnRvPT0iUHJvZHVjY2lvbiBDYXJ0XHhmM24gTURMIiwiUHJvZHVjY2nDs24gQ2FydMOzbiBNREwiKQ0KcmgkZGVwYXJ0YW1lbnRvIDwtIHJlcGxhY2UocmgkZGVwYXJ0YW1lbnRvLHJoJGRlcGFydGFtZW50bz09IlByb2R1Y2NpXHhmM24gUmV0b3JuIiwiUHJvZHVjY2nDs24gUmV0b3JuIikNCnJoJGRlcGFydGFtZW50byA8LSByZXBsYWNlKHJoJGRlcGFydGFtZW50byxyaCRkZXBhcnRhbWVudG89PSJQcm9kdWNjaW9uIENhcnRceGYzbiBNQyIsIlByb2R1Y2Npw7NuIENhcnTDs24gTUMiKQ0KcmgkZGVwYXJ0YW1lbnRvIDwtIHJlcGxhY2UocmgkZGVwYXJ0YW1lbnRvLHJoJGRlcGFydGFtZW50bz09IkNvc3R1cmEgVDIiLCJDT1NUVVJBIikNCnJoJGRlcGFydGFtZW50byA8LSByZXBsYWNlKHJoJGRlcGFydGFtZW50byxyaCRkZXBhcnRhbWVudG89PSJDb3N0dXJhIiwiQ09TVFVSQSIpDQoNCmBgYA0KKioqU2FsYXJpbyBEaWFyaW8gSU1TUyoqKg0KDQpDYW1iaWFyZW1vcyBhIG51bWVybyBlbCBzYWxhcmlvIGRpYXJpbyBkZSBsb3MgY29sYWJvcmFkb3Jlcy4NCg0KYGBge3J9DQpyaCRzYWxhcmlvX2RpYXJpb19pbXNzPC1hcy5udW1lcmljKHJoJHNhbGFyaW9fZGlhcmlvX2ltc3MpDQp1bmlxdWUocmgkc2FsYXJpb19kaWFyaW9faW1zcykNCnN1bW1hcnkocmgpDQpgYGANCg0KKioqRXN0YWRvIENpdmlsKioqDQpgYGB7cn0NCnVuaXF1ZShyaCRlc3RhZG9fY2l2aWwpDQpyaCRlc3RhZG9fY2l2aWwgPC0gcmVwbGFjZShyaCRlc3RhZG9fY2l2aWwscmgkZXN0YWRvX2NpdmlsPT0iU29sdGVybyIsIlNPTFRFUk8oQSkiKQ0KcmgkZXN0YWRvX2NpdmlsIDwtIHJlcGxhY2UocmgkZXN0YWRvX2NpdmlsLHJoJGVzdGFkb19jaXZpbD09IlNPTFRFUkEiLCJTT0xURVJPKEEpIikNCnJoJGVzdGFkb19jaXZpbCA8LSByZXBsYWNlKHJoJGVzdGFkb19jaXZpbCxyaCRlc3RhZG9fY2l2aWw9PSJTT0xURVJPIiwiU09MVEVSTyhBKSIpDQpyaCRlc3RhZG9fY2l2aWwgPC0gcmVwbGFjZShyaCRlc3RhZG9fY2l2aWwscmgkZXN0YWRvX2NpdmlsPT0iVW5pXHhmM24gbGlicmUiLCJVTknDk04gTElCUkUiKQ0KcmgkZXN0YWRvX2NpdmlsIDwtIHJlcGxhY2UocmgkZXN0YWRvX2NpdmlsLHJoJGVzdGFkb19jaXZpbD09IlVuaTxmMz5uIGxpYnJlIiwiVU5Jw5NOIExJQlJFIikNCnJoJGVzdGFkb19jaXZpbCA8LSByZXBsYWNlKHJoJGVzdGFkb19jaXZpbCxyaCRlc3RhZG9fY2l2aWw9PSJVTklPTiBMSUJSRSIsIlVOScOTTiBMSUJSRSIpDQpyaCRlc3RhZG9fY2l2aWwgPC0gcmVwbGFjZShyaCRlc3RhZG9fY2l2aWwscmgkZXN0YWRvX2NpdmlsPT0iVW5pb24gTGlicmUiLCJVTknDk04gTElCUkUiKQ0KcmgkZXN0YWRvX2NpdmlsIDwtIHJlcGxhY2UocmgkZXN0YWRvX2NpdmlsLHJoJGVzdGFkb19jaXZpbD09IkNhc2FkbyIsIkNBU0FETyhBKSIpDQpyaCRlc3RhZG9fY2l2aWwgPC0gcmVwbGFjZShyaCRlc3RhZG9fY2l2aWwscmgkZXN0YWRvX2NpdmlsPT0iQ0FTQURPIiwiQ0FTQURPKEEpIikNCnJoJGVzdGFkb19jaXZpbCA8LSByZXBsYWNlKHJoJGVzdGFkb19jaXZpbCxyaCRlc3RhZG9fY2l2aWw9PSJDQVNBREEiLCJDQVNBRE8oQSkiKQ0KcmgkZXN0YWRvX2NpdmlsIDwtIHJlcGxhY2UocmgkZXN0YWRvX2NpdmlsLHJoJGVzdGFkb19jaXZpbD09IkNhc2FkbyIsIkNBU0FETyhBKSIpDQpyaCRlc3RhZG9fY2l2aWwgPC0gcmVwbGFjZShyaCRlc3RhZG9fY2l2aWwscmgkZXN0YWRvX2NpdmlsPT0iRElWT1JDSUFEQSIsIkRJVk9SQ0lBRE8oQSkiKQ0KcmgkZXN0YWRvX2NpdmlsIDwtIHJlcGxhY2UocmgkZXN0YWRvX2NpdmlsLHJoJGVzdGFkb19jaXZpbD09IkRJVk9SQ0lBRE8iLCJESVZPUkNJQURPKEEpIikNCg0KYGBgDQoNCkxhIGJhc2UgZGUgZGF0b3MgZGUgUmVjdXJzb3MgSHVtYW5vcyBjdWVudGEgY29uICoxMTIqIHJlZ2lzdHJvcyB5ICo4KiB2YXJpYWJsZXMuDQpgYGB7cn0NCmRpbShyaCkNCmBgYA0KYGBge3J9DQpWYXJpYWJsZTwtYygiTm9tYnJlIENvbXBsZXRvIiwgIkZlY2hhIGRlIE5hY2ltaWVudG8iLCAiR2VuZXJvIiwgIkZlY2hhIGRlIEFsdGEiLCAiUHVlc3RvIiwgIkRlcGFydGFtZW50byIsIlNhbGFyaW8gRGlhcmlvIElNU1MiLCAiRXN0YWRvIENpdmlsIikNClRpcG88LWMoIkN1YWxpdGF0aXZhIiwgIkN1YWxpdGF0aXZhIiwgIkN1YWxpdGF0aXZhIiwgIkN1YWxpdGF0aXZhIiwgIkN1YWxpdGF0aXZhIiwiQ3VhbGl0YXRpdmEiLCAiQ3VhbnRpdGF0aXZhIChjb250aW51YSkiLCJDdWFsaXRhdGl2YSIpDQpFc2NhbGFfTWVkaWNpb24gPC1jKCJOQSIsICJGZWNoYSIsICJOQSIsIkZlY2hhIiwiTkEiLCJOQSIsIlBlc29zIiwiTkEiKQ0KdGFibGE8LWRhdGEuZnJhbWUoVmFyaWFibGUsIFRpcG8sIEVzY2FsYV9NZWRpY2lvbikNCmtuaXRyOjprYWJsZSh0YWJsYSkNCmBgYA0KIyMgKipBbsOhbGlzaXMgRXhwbG9yYXRvcmlvIGRlIGxhcyBCYXNlcyBkZSBEYXRvcyoqDQoNCioqKkVzdGFkw61zdGljb3MgZGVzY3JwdGl2b3MqKioNCg0KUGFyYSBjb25jZXIgbG9zIGVzdGFkaXN0aWNvcyBkZSBjYWRhIHVuYSBkZSBsYXMgdmFyaWFibGVzLCBzZSB1dGlsaXphcsOhIGxhIGZ1bmNpw7NuIGRlc2NyaWJlLiBFbiBlbCBjYXNvIGRlIGVzdGEgYmFzZSBkZSBkYXRvcywgbGEgdW5pY2EgdmFyaWFibGUgcXVlIHNlIHB1ZG8gdXRpbGl6YXIgZXMgU2FsYXJpbyBEaWFyaW8gSU1TUw0KDQoNCmBgYHtyfQ0KDQptZWEyIDwtIG1lYW4ocmgkc2FsYXJpb19kaWFyaW9faW1zcykNCm1lZDIgPC0gbWVkaWFuKHJoJHNhbGFyaW9fZGlhcmlvX2ltc3MpDQptb2RhMjwtIG1mdihyaCRzYWxhcmlvX2RpYXJpb19pbXNzKQ0Kc2QyIDwtIHNkKHJoJHNhbGFyaW9fZGlhcmlvX2ltc3MsIG5hLnJtID0gVFJVRSkNCg0KDQpWYXJpYWJsZXMgPC1jKCJTYWxhcmlvIERpYXJpbyBJbXNzIikNCk1lZGlhIDwtYyhtZWEyKQ0KTWVkaWFuYSA8LWMobWVkMikNCk1vZGEgPC1jKG1vZGEyKQ0KRGVzdmlhY2lvbiA8LWMoc2QyKQ0KdGFibGEyIDwtZGF0YS5mcmFtZShWYXJpYWJsZXMsIE1lZGlhLCBNZWRpYW5hLCBNb2RhLERlc3ZpYWNpb24pDQprbml0cjo6a2FibGUodGFibGEyKQ0KYGBgDQoNCkVzdGEgdGFibGEgbm9zIGF5dWRhIGEgaWRlbnRpZmljYXIgcXVlIGVsIHNhbGFyaW8gcHJvbWVkaW8gZGUgRk9STSBlcyBkZSAxNzkuMDQgcGVzb3MsIG1pZW50cmFzIHF1ZSBlbCBzYWxhcmlvIG1hcyByZXBldGlkbyBlcyBkZSAxODAgcGVzb3MuIFNlIGN1ZW50YSBjb24gdW5hIGRlc3ZpYWNpw7NuIGVzdGFuZGFydCBkZSAyNCwgbGEgY3VhbCBub3MgaW5kaWNhIHF1ZSBsYSBkaXNwZXJjacOzbiBlbnRyZSBsb3Mgc2FsYXJpb3MgZXMgbW9kZXJhZGEuDQoNCioqKkdyYWZpY2FzKioqDQoNCioqKlByaW1lcmEgR3JhZmljYSAoQmFycGxvdCAjMSkqKioNCmBgYHtyfQ0KZ2dwbG90KHJoLCBhZXMoeD1nZW5lcm8sIHk9bWVhbihzYWxhcmlvX2RpYXJpb19pbXNzKSwgZmlsbD1nZW5lcm8pKSArIA0KICBnZW9tX2NvbCgpICsgDQogIGZhY2V0X2dyaWQofmVzdGFkb19jaXZpbCkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDMiKQ0KYGBgDQpFc3RhIGdyYWZpY2Egbm9zIG11ZXN0cmEgbGEgcmVsYWNpw7NuIHF1ZSBleGlzdGUgZW50cmUgdHJlcyBkZSBudWVzdHJhIHZhcmlhYmxlcywgc2llbmRvIGVzdGFzIGdlbmVybywgc2FsYXJpbyBkaWFyaW8geSBlc3RhZG8gY2l2aWwuICBMb2dyYW1vcyBwZXJjaWJpciBxdWUgbG9zIHNhbGFyaW9zIGRlIGxhcyBtdWplcmVzIHNvbHRlcmFzIGVzIG1heW9yIGFsIGRlIGxvcyBob21icmVzIGVuIHRvZG9zIGxvcyBlc3RhZG9zIGNpdmlsZXMuIFNpbiBlbWJhcmdvIGxvcyBob21icmVzIGNhc2Fkb3MgcGVyY2liZW4gbWF5b3Igc2FsYXJpbyBxdWUgbGFzIG11amVyZXMgY2FzYWRvcy4gRXN0byBwdWVkZSBzZXIgcG9yIGxvcyBwdWVzdG9zIHF1ZSBlc3RvcyBvY3VwYW4gbyBwb3IgZWwgcm9sIGVjb25vbWljbyBxdWUganVlZ2EgZWwgaG9tYnJlIGRlbnRybyBkZSBsYSBtYXlvcmlhIGRlIGxhcyBmYW1pbGlhcy4NCg0KKioqU2VndW5kYSBHcmFmaWNhIChCYXJwbG90ICMyKSoqKg0KYGBge3J9DQpoaXN0KHJoJHNhbGFyaW9fZGlhcmlvX2ltc3MpDQpgYGANCg0KDQojICoqQmFqYXMqKg0KDQojIyAqKkxpbXBpZXphIGRlIERhdG9zKioNCg0KKioqSW1wb3J0YW1vcyBCYWphcyoqKg0KYGBge3J9DQpyaGIgPC0gIHJlYWQuY3N2KCJDOlxcVXNlcnNcXGNoZW1hXFxEb3dubG9hZHNcXEJhc2VEX0xpbXBpYSBSSF8gQmFqYXMgLmNzdiIpDQpgYGANCg0KDQoqKipFbnRlbmRlbW9zIGxhIGJhc2UgZGUgZGF0b3MqKioNCg0KDQpgYGB7cn0NCnN1bW1hcnkocmhiKQ0Kc3RyKHJoYikNCmRpbShyaGIpDQphcHBseShpcy5uYShyaGIpLCAyLCBzdW0pDQpyaCA8LSBjbGVhbl9uYW1lcyhyaGIpDQpjb2xuYW1lcyhyaGIpDQpgYGANCg0KKkNhbWJpbyBkZSBub21icmVzIGRlIHZhcmlhYmxlcyoNCmBgYHtyfQ0KbmFtZXMocmhiKTwtYygibm9tYiIsICJlZGFkIiwgImdlbiIsICJmZWNoYV9hbHRhIiwgIm1iIiwgImRpYXNfdHJhYiIsICJiYWphIiwgInB1ZXN0byIsICJzYWxfaW1zcyIsICJjb2wiLCAibXVuIiwgImVzdGFkbyIsICJlc3RjaXYiKQ0KYGBgDQoNCioqKkNhbWJpYXIgdGlwbyBkZSB2YXJpYWJsZXMqKioNCmBgYHtyfQ0KcmhiJGVkYWQ8LWFzLm51bWVyaWMocmhiJGVkYWQpDQpyaGIkZmVjaGFfYWx0YTwtYXMuRGF0ZShyaGIkZmVjaGFfYWx0YSwgZm9ybWF0ID0gIiV5LyVtLyVkIikNCnJoYiRiYWphPC1hcy5EYXRlKHJoYiRiYWphLCBmb3JtYXQgPSAiJXkvJW0vJWQiKQ0KcmhiJGRpYXNfdHJhYjwtYXMubnVtZXJpYyhyaGIkZWRhZCkNCg0KYGBgDQoqKipFc3RhbmRhcml6YXIgVmFyaWFibGVzKioqDQpgYGB7cn0NCnVuaXF1ZShyaGIkZXN0Y2l2KQ0KcmhiJGVzdGNpdiA8LSByZXBsYWNlKHJoYiRlc3RjaXYscmhiJGVzdGNpdj09IlNvbHRlcm8iLCJTT0xURVJPKEEpIikNCnJoYiRlc3RjaXYgPC0gcmVwbGFjZShyaGIkZXN0Y2l2LHJoYiRlc3RjaXY9PSJTT0xURVJBIiwiU09MVEVSTyhBKSIpDQpyaGIkZXN0Y2l2IDwtIHJlcGxhY2UocmhiJGVzdGNpdixyaGIkZXN0Y2l2PT0iU09MVEVSTyIsIlNPTFRFUk8oQSkiKQ0KcmhiJGVzdGNpdiA8LSByZXBsYWNlKHJoYiRlc3RjaXYscmhiJGVzdGNpdj09IlVuaVx4ZjNuIGxpYnJlIiwiVU5Jw5NOIExJQlJFIikNCnJoYiRlc3RjaXYgPC0gcmVwbGFjZShyaGIkZXN0Y2l2LHJoYiRlc3RjaXY9PSJVTklceGQzTiBMSUJSRSIsIlVOScOTTiBMSUJSRSIpDQpyaGIkZXN0Y2l2IDwtIHJlcGxhY2UocmhiJGVzdGNpdixyaGIkZXN0Y2l2PT0iVU5JT04gTElCUkUiLCJVTknDk04gTElCUkUiKQ0KcmhiJGVzdGNpdiA8LSByZXBsYWNlKHJoYiRlc3RjaXYscmhiJGVzdGNpdj09IlVuaW9uIExpYnJlIiwiVU5Jw5NOIExJQlJFIikNCnJoYiRlc3RjaXYgPC0gcmVwbGFjZShyaGIkZXN0Y2l2LHJoYiRlc3RjaXY9PSJDYXNhZG8iLCJDQVNBRE8oQSkiKQ0KcmhiJGVzdGNpdiA8LSByZXBsYWNlKHJoYiRlc3RjaXYscmhiJGVzdGNpdj09IkNBU0FETyIsIkNBU0FETyhBKSIpDQpyaGIkZXN0Y2l2IDwtIHJlcGxhY2UocmhiJGVzdGNpdixyaGIkZXN0Y2l2PT0iQ0FTQURBIiwiQ0FTQURPKEEpIikNCnJoYiRlc3RjaXYgPC0gcmVwbGFjZShyaGIkZXN0Y2l2LHJoYiRlc3RjaXY9PSJDYXNhZG8iLCJDQVNBRE8oQSkiKQ0KcmhiJGVzdGNpdiA8LSByZXBsYWNlKHJoYiRlc3RjaXYscmhiJGVzdGNpdj09IkRJVk9SQ0lBREEiLCJESVZPUkNJQURPKEEpIikNCnJoYiRlc3RjaXYgPC0gcmVwbGFjZShyaGIkZXN0Y2l2LHJoYiRlc3RjaXY9PSJESVZPUkNJQURPIiwiRElWT1JDSUFETyhBKSIpDQoNCnVuaXF1ZShyaGIkbXVuKQ0KDQpyaGIkbXVuIDwtIHJlcGxhY2UocmhiJG11bixyaGIkbXVuPT0iU0FOIE5JQ09MQVMgREUgTE9TIEciLCJTQU4gTklDT0xBUyBERSBMT1MgR0FSWkEiKQ0KcmhiJG11biA8LSByZXBsYWNlKHJoYiRtdW4scmhiJG11bj09IlNBTiBQRFJPIENPQUgiLCJDT0FIVUlMQSIpDQoNCnVuaXF1ZShyaGIkZXN0YWRvKQ0KDQpyaGIkZXN0YWRvIDwtIHJlcGxhY2UocmhiJGVzdGFkbyxyaGIkZXN0YWRvPT0iTlVFVk8gTEVceGQzTiIsIk51ZXZvIExlw7NuIikNCg0Kc3VtbWFyeShyaGIpDQoNCmBgYA0KDQpTZSBpZGVudGlmaWPDsyBxdWUgZXhpc3RlbiAyIHJlZ2lzdHJvcyBjb24gZWRhZCAwLiBTZSB1dGlsaXphcsOhIGxhIGVkYWQgcHJvbWVkaW8gZGVsIGdydXBvLCBsYSBjdWFsIGVzIDMxIGHDsW9zIHBhcmEgcmVtcGxhemFyIGxvcyB2YWxvcmVzIGRlIGRpY2hvcyByZWdpc3Ryb3MuDQoNCioqKlJlbXBsYXphciB2YWxvcmVzIGludmFsaWRvcyBwb3IgbGEgbWVkaWEqKioNCg0KYGBge3J9DQpyaGIkZWRhZDwtcmVwbGFjZShyaGIkZWRhZCxyaGIkZWRhZD09MCwzMSkNCg0Kc3VtbWFyeShyaGIpDQpgYGANCg0KDQpMYSBiYXNlIGRlIGRhdG9zIGRlIFJlY3Vyc29zIEh1bWFub3MgQmFqYXMgY3VlbnRhIGNvbiAqMjM3KiByZWdpc3Ryb3MgeSAqMTMqIHZhcmlhYmxlcy4NCg0KDQpgYGB7cn0NCmRpbShyaGIpDQpgYGANCg0KKioqVGlwb3MgZGUgdmFyaWFibGVzIHkgbWVkaWNpw7NuKioqDQoNCmBgYHtyfQ0KVmFyaWFibGU8LWMoIk5vbWJyZSIsICJFZGFkIiwgIkdlbmVybyIsICJGZWNoYSBkZSBBbHRhIiwgIk1vdGl2byBkZSBiYWphIiwgIkTDrWFzIFRyYWJhamFkb3MiLCJCYWphIiwgIlB1ZXN0byIsIlNhbGFyaW8gSU1NUyIsIkNvbG9uaWEiLCJNdW5pY2lwaW8iLCJFc3RhZG8iLCJFc3RhZG8gQ2l2aWwiKQ0KVGlwbzwtYygiQ3VhbGl0YXRpdmEiLCAiQ3VhbnRpdGF0aXZhIiwgIkN1YWxpdGF0aXZhIiwgIkN1YWxpdGF0aXZhIiwgIkN1YWxpdGF0aXZhIiwiQ3VhbnRpdGF0aXZhIiwgIkN1YWxpdGF0aXZhIiwiQ3VhbGl0YXRpdmEiLCJDdWFudGl0YXRpdmEiLCJDdWFsaXRhdGl2YSIsIkN1YWxpdGF0aXZhIiwiQ3VhbGl0YXRpdmEiLCJDdWFsaXRhdGl2YSIpDQpFc2NhbGFfTWVkaWNpb24gPC1jKCJOQSIsICJBw7FvcyIsICJOQSIsIkZlY2hhIiwiTkEiLCJEw61hcyIsIk5BIiwiTkEiLCJQZXNvcyIsIk5BIiwiTkEiLCJOQSIsIk5BIikNCnRhYmxhPC1kYXRhLmZyYW1lKFZhcmlhYmxlLCBUaXBvLCBFc2NhbGFfTWVkaWNpb24pDQprbml0cjo6a2FibGUodGFibGEpDQoNCmBgYA0KDQoNCiMjICoqQW7DoWxpc2lzIEV4cGxvcmF0b3JpbyBkZSBsYXMgQmFzZXMgZGUgRGF0b3MqKg0KDQoqKipFc3RhZMOtc3RpY29zIGRlc2NycHRpdm9zKioqDQoNCmBgYHtyfQ0KbWVhIDwtIG1lYW4ocmhiJHNhbF9pbXNzKQ0KbWVkIDwtIG1lZGlhbihyaGIkc2FsX2ltc3MpDQptb2RhIDwtIG1mdihyaGIkc2FsX2ltc3MpDQpzZCA8LSBzZChyaGIkc2FsX2ltc3MsIG5hLnJtID0gVFJVRSkNCg0KbWVhMSA8LSBtZWFuKHJoYiRlZGFkKQ0KbWVkMSA8LSBtZWRpYW4ocmhiJGVkYWQpDQptb2RhMSA8LSBtZnYocmhiJGVkYWQpDQpzZDEgPC0gc2QocmhiJGVkYWQsIG5hLnJtID0gVFJVRSkNCg0KbWVhMiA8LSBtZWFuKHJoYiRkaWFzX3RyYWIpDQptZWQyIDwtIG1lZGlhbihyaGIkZGlhc190cmFiKQ0KbW9kYTIgPC0gbWZ2KHJoYiRkaWFzX3RyYWIpDQpzZDIgPC0gc2QocmhiJGRpYXNfdHJhYiwgbmEucm0gPSBUUlVFKQ0KDQpWYXJpYWJsZXMgPC1jKCJTYWxhcmlvIERpYXJpbyBJbXNzIiwiRWRhZCIsICJEaWFzIFRyYWJhamFkb3MiKQ0KTWVkaWEgPC1jKG1lYSxtZWExLG1lYTIpDQpNZWRpYW5hIDwtYyhtZWQsbWVkMSxtZWQyKQ0KTW9kYSA8LWMobW9kYSxtb2RhMSxtb2RhMikNCkRlc3ZpYWNpb24gPC1jKHNkLHNkMSxzZDIpDQp0YWJsYTIgPC1kYXRhLmZyYW1lKFZhcmlhYmxlcywgTWVkaWEsIE1lZGlhbmEsIE1vZGEsRGVzdmlhY2lvbikNCmtuaXRyOjprYWJsZSh0YWJsYTIpDQoNCmBgYA0KUG9kZW1vcyB2ZXIgcXVlIGVuIGVzdGEgdGFibGEsIHF1ZSBlbCB0cmFiYWphZG9yIHByb21lZGlvIGRlbnRybyBkZSBsYSBiYXNlIGRlIGRhdG9zIFJIIEJhamFzIHRpZW5lICozMSogYcOxb3MsIGxsZXZhYmEgKjMxKiBkaWFzIHRyYWJhamFuZG8geSBnYW5hYmEgdW4gc3VlbGRvIHByb21lZGlvIGRlICoxNzguNjMqIHBlc29zLiBMYSBkZXN2aWFjacOzbiBtYXMgYWx0YSBkZW50cm8gZGUgbGFzIHZhcmlhYmxlcyBjdWFudGl0YXRpdmFzIGVzIGRlIDI1LjQ0LCBzaWVuZG8gZXN0YSBsYSBkZXN2aWFjacOzbiBkZWwgc2FsYXJpbyBkaWFyaW8uIEVzdG8gbm9zIGluZGljYSBxdWUgZXhpc3RlIGJhc3RhbnRlIGRpc3BlcmNpw7NuIGVudHJlIGxvcyByZWdpc3Ryb3MgbWF4aW1vcyB5IG1pbmltb3MgZGUgbGEgdmFyaWFibGUuDQoNCioqKkdyYWZpY2FzKioqDQoNCioqKlByaW1lcmEgR3JhZmljYSAoQmFycGxvdCAjMykqKioNCg0KYGBge3J9DQpnZ3Bsb3QocmhiLCBhZXMoeD1nZW4sIHk9ZWRhZCwgZmlsbD1tYikpICsgDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyANCiAgZmFjZXRfZ3JpZCh+ZXN0Y2l2KSArIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MyIpDQpgYGANCkVzdGEgZ3JhZmljYSBub3MgbXVlc3RyYSBsYSByZWxhY2nDs24gcXVlIGV4aXN0ZSBlbnRyZSB0cmVzIGRlIG51ZXN0cmEgdmFyaWFibGVzLCBzaWVuZG8gZXN0YXMgR2VuZXJvLCBFZGFkLCBNb3Rpdm8gZGUgYmFqYSB5IEVzdGFkbyBjaXZpbC4gUG9kZW1vcyBub3RhciBxdWUgDQoNCioqKlNlZ3VuZGEgR3JhZmljYSAoU2NhdHRlciBwbG90ICMxKSoqKg0KDQpQYXJhIGxhIHJlYWxpemFjacOzbiBkZSBlc3RlIHNjYXR0ZXIgcGxvdCwgc2UgZWxpbWluYXJvbiAyIHJlZ2lzdHJvcyBxdWUgY2VzZ2FiYW4gbGEgbXVlc3RyYSBhbCBtb21lbnRvIGRlIGdyYWZpY2FybGEsIGRpY2hvcyByZWdpc3Ryb3MgZXJhbiBsb3MgMiBzYWxhcmlvcyBtYXMgYWx0b3MsIHNpZW5kbyB1bm8gZGUgJDUwMCB5IG90cm8gZGUgMzM4LjM2Lg0KDQpgYGB7cn0NCnJoYjE8LXJoYg0KcmhiMSA8LSByaGIxW3JoYjEkc2FsX2ltc3M8MTgzLjY4LF0NCg0KbGlicmFyeShocmJydGhlbWVzKQ0KDQpnZ3Bsb3QocmhiMSwgYWVzKHg9ZWRhZCwgeT1zYWxfaW1zcywgY29sb3I9ZXN0Y2l2KSkgKyANCiAgICBnZW9tX3BvaW50KHNpemU9MikgKw0KICAgIHRoZW1lX2RhcmsoKQ0KDQpgYGANCg0KDQoNCg0KIyAqKkRlbGl2ZXJ5IFBsYW4qKiANCg0KDQojIyAqKkxpbXBpZXphIGRlIGRhdG9zKioNCg0KDQoqKipJbXBvcnRhbW9zIERlbGl2ZXJ5IFBsYW4qKioNCmBgYHtyfQ0KICBkcGwgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcY2hlbWFcXERvd25sb2Fkc1xcRGVsaXZlcnkgUGxhbiBCRCBGaW5hbCAoMSkuY3N2IikNCmBgYA0KIA0KKioqRW50ZW5kZW1vcyBsYSBiYXNlIGRlIGRhdG9zKioqDQoNCmBgYHtyfQ0Kc3VtbWFyeShkcGwpDQpzdHIoZHBsKQ0KZGltKGRwbCkNCmFwcGx5KGlzLm5hKGRwbCksIDIsIHN1bSkNCmNvbG5hbWVzKGRwbCkNCmBgYA0KDQoNCioqKkNhbWJpYW1vcyBlbCBub21icmUgZGUgbGFzIHZhcmlhYmxlcyoqKg0KDQpgYGB7cn0NCg0KY29sbmFtZXMoZHBsKTwtIGMoImNsaWVudGUiLCJwcm95ZWN0byIsImlkX29kb28iLCJpdGVtIiwiQV9qdW5fMjEiLCJCX2p1bF8yMSIsIkNfYWdvXzIxIiwiRF9zZXBfMjEiLCJFX29jdF8yMSIsIkZfbm92XzIxIiwiR19kaWNfMjEiLCJIX2VuZV8yMiIsIklfZmViXzIyIiwiSl9tYXJfMjIiLCJLX2Ficl8yMiIsIkxfbWF5XzIyIiwiTV9qdW5fMjIiLCJOX2p1bF8yMiIsIk9fYWdvXzIyIiwiUF9zZXBfMjIiLCJRX29jdF8yMiIsIlJfbm92XzIyIiwiU19kaWNfMjIiLCJUX2VuZV8yMyIsIlVfZmViXzIzIiwiVl9tYXJfMjMiLCJ0b3RhbF9tZXNlcyIpDQoNCg0KYGBgDQoNCioqKkFncmVnYW1vcyBudWV2YXMgY29sdW1uYXMgeSB2YWxvcmVzIHBhcmEgdW5pciBsb3MgcGVkaWRvcyBwcm9ncmFtYWRvcyoqKg0KDQpgYGB7cn0NCmRwbCA8LSBwaXZvdF9sb25nZXIoZHBsLCBjb2xzPTU6MTQsIG5hbWVzX3RvID0gIk1lcyIsIHZhbHVlc190byA9ICJVbmlkYWRlcyIpDQpgYGANCg0KKioqRWxpbWluYW1vcyBjb2x1bW5hcyBpbm5lY2VzYXJpYXMqKioNCmBgYHtyfQ0KZHBsIDwtIGZpbHRlcihkcGwsIFVuaWRhZGVzPjApDQoNCmRwbDEgPC0gZHBsICAgICAgICAgDQpkcGwxIDwtIHN1YnNldCAoZHBsLCBzZWxlY3QgPSAtYyAocHJveWVjdG8sIGlkX29kb28sIGl0ZW0sIEtfYWJyXzIyLCBMX21heV8yMiwgTV9qdW5fMjIsTl9qdWxfMjIsT19hZ29fMjIsIFBfc2VwXzIyLCBRX29jdF8yMiwgUl9ub3ZfMjIsICBTX2RpY18yMiwgVF9lbmVfMjMsVV9mZWJfMjMsIFZfbWFyXzIzLCB0b3RhbF9tZXNlcykpDQoNCmBgYA0KDQoqKipDYW1iaWFtb3MgdGlwbyBkZSB2YXJpYWJsZSoqKg0KYGBge3J9DQpkcGwxJFVuaWRhZGVzIDwtIGFzLm51bWVyaWMoZHBsMSRVbmlkYWRlcykNCmBgYA0KDQojIyAqKkFuYWxpc2lzIERlc2NyaXB0aXZvKioNCg0KTGEgYmFzZSBkZSBkYXRvcyBkZSBEZWxpdmVyeSBQbGFuIGN1ZW50YSBjb24gKjU5MCogcmVnaXN0cm9zIHkgKjE5KiB2YXJpYWJsZXMuDQpgYGB7cn0NCg0KZGltKGRwbCkNCg0KYGBgDQoNCioqKkVzdGFkw61zdGljb3MgZGVzY3JwdGl2b3MqKioNCmBgYHtyfQ0KbWVhMjEgPC0gbWVhbihkcGwxJFVuaWRhZGVzKQ0KbWVkMjEgPC0gbWVkaWFuKGRwbDEkVW5pZGFkZXMpDQptb2RhMjE8LSBtZnYoZHBsMSRVbmlkYWRlcykNCnNkMjEgPC0gc2QoZHBsMSRVbmlkYWRlcywgbmEucm0gPSBUUlVFKQ0KDQoNClZhcmlhYmxlcyA8LWMoIlVuaWRhZGVzIikNCk1lZGlhIDwtYyhtZWEyMSkNCk1lZGlhbmEgPC1jKG1lZDIxKQ0KTW9kYSA8LWMobW9kYTIxKQ0KRGVzdmlhY2lvbiA8LWMoc2QyMSkNCnRhYmxhMyA8LWRhdGEuZnJhbWUoVmFyaWFibGVzLCBNZWRpYSwgTWVkaWFuYSwgTW9kYSxEZXN2aWFjaW9uKQ0Ka25pdHI6OmthYmxlKHRhYmxhMykNCmBgYA0KDQpFbiBGT1JNIGVsIHByb21lZGlvIGRlIHVuaWRhZGVzIHByb2dyYW1hZGFzIHBvciBjbGllbnRlIGVzIGRlIDM1OCB1bmlkYWRlcy4NCg0KYGBge3J9DQoNClZhcmlhYmxlPC1jKCJDbGllbnRlIiwgIk1lcyIsICJVbmlkYWRlcyIpDQpUaXBvPC1jKCJDdWFsaXRhdGl2YSIsICJDdWFsaXRhdGl2YSIsICJDdWFudGl0YXRpdmEgY29udGludWEiKQ0KTWVkaWNpw7NuPC1jKCJOQSIsICJOQSIsICJVbmlkYWRlcyIpDQp0YWJsYTg8LWRhdGEuZnJhbWUoVmFyaWFibGUsVGlwbywgTWVkaWNpw7NuKQ0KdGFibGE4DQoNCmBgYA0KDQoNCioqKkdyYWZpY2FzKioqDQoNCg0KKioqVGltZSBTZXJpZXMgUGxvdCoqKg0KDQpQYXJhIHBvZGVyIHJlYWxpemFyIHVuIHRpbWUgc2VyaWVzIHBsb3QgZXMgbmVjZXNhcmlvIGNvbnZlcnRpciBudWVzdHJhcyB2YXJpYWJsZXMgYSBmZWNoYS4NCmBgYHtyfQ0KDQpkcGwxJE1lcyA8LSByZXBsYWNlKGRwbDEkTWVzLGRwbDEkTWVzPT0iQl9qdWxfMjEiLCIyMDIxLzA3LzAxIikNCmRwbDEkTWVzIDwtIHJlcGxhY2UoZHBsMSRNZXMsZHBsMSRNZXM9PSJDX2Fnb18yMSIsIjIwMjEvMDgvMDEiKQ0KZHBsMSRNZXMgPC0gcmVwbGFjZShkcGwxJE1lcyxkcGwxJE1lcz09IkVfb2N0XzIxIiwiMjAyMS8xMC8wMSIpDQpkcGwxJE1lcyA8LSByZXBsYWNlKGRwbDEkTWVzLGRwbDEkTWVzPT0iR19kaWNfMjEiLCIyMDIxLzEyLzAxIikNCmRwbDEkTWVzIDwtIHJlcGxhY2UoZHBsMSRNZXMsZHBsMSRNZXM9PSJIX2VuZV8yMiIsIjIwMjIvMDEvMDEiKQ0KZHBsMSRNZXMgPC0gcmVwbGFjZShkcGwxJE1lcyxkcGwxJE1lcz09IklfZmViXzIyIiwiMjAyMi8wMi8wMSIpDQpkcGwxJE1lcyA8LSByZXBsYWNlKGRwbDEkTWVzLGRwbDEkTWVzPT0iSl9tYXJfMjIiLCIyMDIyLzAzLzAxIikNCmRwbDEkTWVzIDwtIHJlcGxhY2UoZHBsMSRNZXMsZHBsMSRNZXM9PSJBX2p1bl8yMSIsIjIwMjEvMDYvMDEiKQ0KZHBsMSRNZXMgPC0gcmVwbGFjZShkcGwxJE1lcyxkcGwxJE1lcz09IkZfbm92XzIxIiwiMjAyMS8xMS8wMSIpDQpkcGwxJE1lcyA8LSByZXBsYWNlKGRwbDEkTWVzLGRwbDEkTWVzPT0iRF9zZXBfMjEiLCIyMDIxLzA5LzAxIikNCg0KZHBsMSRNZXMgPC0gYXMuRGF0ZShkcGwxJE1lcywgZm9ybWF0ID0gIiVkLyVtLyV5IikNCg0KDQoNCnAgPC0gZ2dwbG90KGRwbDEsIGFlcyh4PU1lcywgeT1VbmlkYWRlcykpICsNCiAgZ2VvbV9saW5lKCBjb2xvcj0ic3RlZWxibHVlIikgKyANCiAgZ2VvbV9wb2ludCgpICsNCiAgeGxhYigiIikgKw0KICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NjAsIGhqdXN0PTEpKSArDQogIHNjYWxlX3hfZGF0ZShsaW1pdD1jKGFzLkRhdGUoIjIwMjEtMDYtMDEiKSxhcy5EYXRlKCIyMDIyLTAzLTAxIikpKSArDQogIHlsaW0oMCwxMzEyMCkNCg0KcA0KDQoNCmBgYA0KRXN0YSBncmFmaWNhIG5vcyBheXVkYSBhIHZpc3VhbGl6YXIgbG9zIHBpY29zIGRlIHBlZGlkb3MgZW4gZGlzdGludG9zIG1lc2VzLCBzaWVuZG8gZWwgZGUgKkp1bGlvIGRlbCAyMDIxKiBlbCBtYXlvciBwaWNvIGRlIFVuaWRhZGVzIHByb2dyYW1hZGFzIGVuIGVsIGHDsW8uDQoNCg0KDQoqKipHcmFmaWNhIERhdG9zIGN1YWxpdGF0aXZvcyoqKg0KDQpgYGB7cn0NCmxpYnJhcnkodHJlZW1hcCkNCnRyZWVtYXAoZHBsMSwNCiAgICAgICAgICAgIGluZGV4PSJjbGllbnRlIiwNCiAgICAgICAgICAgIHZTaXplPSJVbmlkYWRlcyIsDQogICAgICAgICAgICB0eXBlPSJpbmRleCINCiAgICAgICAgICAgICkNCmBgYA0KDQpFc3RhIGdyYWZpY2EsIG5vcyBheXVkYSBhIHZpc3VhbGl6YXIgbG9zIGNsaWVudGVzIG1hcyBncmFuZGVzIGRlIEZPUk0sIGxvcyBjdWFsZXMgc29uICpIZWxsYSwgVFJNWCB5IFZBUlJPQyoNCg0KDQojICoqRGVsaXZlcnkgUGVyZm9ybWFuY2UqKg0KDQoqKipJbXBvcnRhbW9zIGxhIGJhc2UgZGUgZGF0b3MNCmBgYHtyfQ0KZHBlIDwtIHJlYWQuY3N2KCJDOlxcVXNlcnNcXGNoZW1hXFxEb3dubG9hZHNcXEZPUk0gLSBEZWxpdmVyeSBQZXJmb3JtYW5jZSAoMSkuY3N2IikNCmBgYA0KDQoNCg0KKioqRW50ZW5kZW1vcyBsYSBiYXNlIGRlIGRhdG9zKioqDQoNCg0KYGBge3J9DQpzdW1tYXJ5KGRwZSkgDQpzdHIoZHBlKQ0KZGltKGRwZSkNCmFwcGx5KGlzLm5hKGRwZSksIDIsIHN1bSkNCmNvbG5hbWVzKGRwZSkNCmBgYA0KDQojIyAqKkxpbXBpZXphIGRlIGRhdG9zKioNCg0KRXN0YSBiYXNlIGRlIGRhdG9zIGFudGVyaW9ybWVudGUgZnVlIGxpbXBpYWRhIGF0cmF2ZXMgZGUgZXhjZWwsIHBvciBsbyBxdWUgbm8gc2Vyw6EgbmVjZXNhcmlvIHJlYWxpemFyIG11Y2hvIGNvZGlnbyBwYXJhIGxpbXBpYXJsYS4gTG8gdW5pY28gcXVlIGVzIG5lY2VzYXJpbyBoYWNlciBjb25maW5lcyBkZSBncmFmaWNhY2nDs24gZGUgZGF0b3MsIGVzIGNvbnZlcnRpciBlbiBmZWNoYSBsYSB2YXJpYWJsZSBkZSBEYXRlLiANCg0KKioqQ2FtYmlhciB0aXBvIGRlIFZhcmlhYmxlKioqDQpgYGB7cn0NCiAgZHBlJERhdGUgPC1hcy5EYXRlKGRwZSREYXRlLGZvcm1hdCA9IiVtLyVkLyVZIikNCmBgYA0KDQojIyAqKkFuYWxpc2lzIERlc2NyaXB0aXZvcyoqDQoNCkxhIGJhc2UgZGUgZGF0b3MgZGUgRGVsaXZlcnkgUGVyZm9ybWFuY2UgY3VlbnRhIGNvbiAqMTQ0MCogcmVnaXN0cm9zIHkgKjgqIHZhcmlhYmxlcy4NCmBgYHtyfQ0KZGltKGRwZSkNCmBgYA0KDQoqKipUaXBvcyBkZSB2YXJpYWJsZSoqKg0KDQpgYGB7cn0NClZhcmlhYmxlIDwtIGMoImBUYXJnZXRgIiwiYENsaWVudGVgIiwiYFZ1ZWx0YXNgIiwiYFBsYW4uYXJyaXZhbGAiLCJgUmVhbC5hcnJpdmFsYCIsImBQbGFuLmRlcGFydHVyZWAiLCJgRGlmZXJlbmNlYCIsImBEYXRlYCIpDQpUaXBvIDwtIGMoImN1YW50aXRhdGl2byAoZGlzY3JldG8pICAiLCAiY3VhbGl0YXRpdm8gICIsICJjdWFudGl0YXRpdm8gKGRpc2NyZXRvKSAgIiwgImN1YW50aXRhdGl2byAoY29udGludW8pICAiLCAiY3VhbnRpdGF0aXZvIChjb250aW51bykgICIsICJjdWFudGl0YXRpdm8gKGNvbnRpbnVvKSAgIiwgImN1YW50aXRhdGl2byAoY29udGludW8pICAiLCAiY3VhbGl0YXRpdm8gICIpDQpNZWRpY2nDs24gPC0gYygiRW50cmVnYXMiLCAiTkEiLCAiVnVlbHRhcyIsICJUaWVtcG8iLCAiVGllbXBvIiwgIlRpZW1wbyIsICJUaWVtcG8iLCAiRkVDSEEiKQ0KdGFibGU4IDwtIGRhdGEuZnJhbWUgKFZhcmlhYmxlLCBUaXBvLCBNZWRpY2nDs24pDQprbml0cjo6a2FibGUodGFibGU4KQ0KYGBgDQoqKipBbmFsaXNpcyBFeHBsb3JhdG9yaW8qKioNCg0KKioqTWVkaWRhcyBFc3RhZGlzdGljYXMqKioNCg0KYGBge3J9DQptZWEgPC0gbWVhbihkcGUkVGFyZ2V0KQ0KbWVkIDwtIG1lZGlhbihkcGUkVGFyZ2V0KQ0KbW9kYSA8LSBtZnYoZHBlJFRhcmdldCkNCnNkIDwtIHNkKGRwZSRUYXJnZXQsIG5hLnJtID0gVFJVRSkNCg0KbWVhMSA8LSBtZWFuKGRwZSRWdWVsdGFzKQ0KbWVkMSA8LSBtZWRpYW4oZHBlJFZ1ZWx0YXMpDQptb2RhMSA8LSBtZnYoZHBlJFZ1ZWx0YXMpDQpzZDEgPC0gc2QoZHBlJFZ1ZWx0YXMsIG5hLnJtID0gVFJVRSkNCg0KbWVhMiA8LSBtZWFuKGRwZSRQbGFuLmFycml2YWwpDQptZWQyIDwtIG1lZGlhbihkcGUkUGxhbi5hcnJpdmFsKQ0KbW9kYTIgPC0gbWZ2KGRwZSRQbGFuLmFycml2YWwpDQpzZDIgPC0gc2QoZHBlJFBsYW4uYXJyaXZhbCwgbmEucm0gPSBUUlVFKQ0KDQptZWEzIDwtIG1lYW4oZHBlJFJlYWwuYXJyaXZhbCkNCm1lZDMgPC0gbWVkaWFuKGRwZSRSZWFsLmFycml2YWwpDQptb2RhMyA8LSBtZnYoZHBlJFJlYWwuYXJyaXZhbCkNCnNkMyA8LSBzZChkcGUkUmVhbC5hcnJpdmFsLCBuYS5ybSA9IFRSVUUpDQoNCm1lYTQgPC0gbWVhbihkcGUkUmVhbC5kZXBhcnR1cmUpDQptZWQ0IDwtIG1lZGlhbihkcGUkUmVhbC5kZXBhcnR1cmUpDQptb2RhNCA8LSBtZnYoZHBlJFJlYWwuZGVwYXJ0dXJlKQ0Kc2Q0IDwtIHNkKGRwZSRSZWFsLmRlcGFydHVyZSwgbmEucm0gPSBUUlVFKQ0KDQptZWE1IDwtIG1lYW4oZHBlJERpZmVyZW5jZSkNCm1lZDUgPC0gbWVkaWFuKGRwZSREaWZlcmVuY2UpDQptb2RhNSA8LSBtZnYoZHBlJERpZmVyZW5jZSkNCnNkNSA8LSBzZChkcGUkRGlmZXJlbmNlLCBuYS5ybSA9IFRSVUUpDQoNClZhcmlhYmxlcyA8LWMoIlRhcmdldCIsIlZ1ZWx0YXMiLCJQbGFuIEFycml2YWwiLCAiUmVhbCBBcnJpdmFsIiwgIlJlYWwgRGVwYXJ0dXJlIiwgIkRpZmVyZW5jZSIpDQpNZWRpYSA8LWMobWVhLG1lYTEsbWVhMixtZWEzLG1lYTQsbWVhNSkNCk1lZGlhbmEgPC1jKG1lZCxtZWQxLG1lZDIsbWVkMyxtZWQ0LCBtZWQ1KQ0KTW9kYSA8LWMobW9kYSxtb2RhMSxtb2RhMixtb2RhMyxtb2RhNCxtb2RhNSkNCkRlc3ZpYWNpb24gPC1jKHNkLHNkMSxzZDIsc2QzLHNkNCxzZDUpDQp0YWJsYTUgPC1kYXRhLmZyYW1lKFZhcmlhYmxlcywgTWVkaWEsIE1lZGlhbmEsTW9kYSxEZXN2aWFjaW9uKQ0Ka25pdHI6OmthYmxlKHRhYmxhNSkNCg0KYGBgDQoNCioqKkdyYWZpY2FzKioqDQoNCmBgYHtyfQ0KcCA8LSBnZ3Bsb3QoZHBlLCBhZXMoeD1EYXRlLCB5PVZ1ZWx0YXMpKSArDQogIGdlb21fbGluZSggY29sb3I9InN0ZWVsYmx1ZSIpICsgDQogIGdlb21fcG9pbnQoKSArDQogIHhsYWIoIiIpICsNCiAgdGhlbWVfaXBzdW0oKSArDQogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT02MCwgaGp1c3Q9MSkpICsNCiAgc2NhbGVfeF9kYXRlKGxpbWl0PWMoYXMuRGF0ZSgiMjAyMi0wMS0wMiIpLGFzLkRhdGUoIjIwMjItMDEtMTIiKSkpIA0KcA0KYGBgDQoNCkVzdGEgZ3JhZmljYSBzZSBwdWVkZSB1dGlsaXphciBjb24gY3VhbHF1aWVyYSBkZSBsYXMgdmFyaWFibGVzIGRlIERlbGl2ZXJ5IFBlcmZvcm1hbmNlLCBwYXJhIGNvbm9jZXIgZWwgY29tcG9ydGFtaWVudG8gcXVlIGVzdGFzIHRpZW5lbiBjb24gZWwgcGFzYXIgZGVsIHRpZW1wbywgZW4gZXN0ZSBjYXNvIHNlIHNlbGVjY2lvbsOzIFZ1ZWx0YXMgZW4gZWwgcGVyaW9kbyBkZWwgcHJpbWVybyBkZSBlbmVybyBkZSBlc3RhIGHDsW8sIGhhc3RhIGVsIDEyLCBlbiBlc3RlIHBlcmlvZG8gZGUgdGllbXBvIHBvZGVtb3MgdmVyIGRpc3RpbnRvcyBwaWNvcy4NCg0KKioqQmFycGxvdCoqKg0KYGBge3J9DQpib3hwbG90KFJlYWwuYXJyaXZhbCB+IFBsYW4uYXJyaXZhbCwgZGF0YSA9IGRwZSwNCiAgICAgICAgbWFpbiA9ICJSZWFsIEFycml2YWwgdnMgUGxhbmVkIEFycml2YWwiLA0KICAgICAgICBjb2wgPSByYWluYm93KG5jb2wodHJlZXMpKSkNCmBgYA0KRXN0YSBncmFmaWNhIG5vcyBtdWVzdHJhIGxhIGRpc3BlcmNpw7NuIHF1ZSBleGlzdGUgZW50cmUgZWwgdGllbXBvIGxsZWdhZGEgcmVhbCBkZSBsYXMgZW50cmVnYXMgeSBlbCB0aWVtcG8gZGUgbGxlZ2FkYSBwbGFuZWFkYS4NCg0KDQoqKipQcm9kdWNjacOzbioqKg0KYGBge3J9DQpwciA8LSByZWFkLmNzdigiQzpcXFVzZXJzXFxjaGVtYVxcRGVza3RvcFxccHJvZHVjY2lvbi5jc3YiKQ0KYGBgDQoNCioqKkFuYWxpemFtb3MgbGEgYmFzZSBkZSBkYXRvcyoqKg0KDQoNCiMjICoqTGltcGllemEgZGUgZGF0b3MqKg0KDQpFbiBlc3RhIGJhc2UgZGUgZGF0b3MgZXhpc3RlbiBhbGd1bmFzIHZhcmlhYmxlcyBxdWUgbm8gc2Vyw6FuIG5lY2VzYXJpYXMgcGFyYSByZWFsaXphciB1biBhbmFsaXNpcyBlc3RhZGlzdGljbywgZXMgcG9yIGVzbyBxdWUgc2UgZGVjaWRpw7MgYm9ycmFybGFzLg0KDQoqKipFbGltaW5hbW9zIENvbHVtbmFzIHF1ZSBubyBzZSB1dGlsaXphcsOhbioqKg0KDQpgYGB7cn0NCnByIDwtIHN1YnNldChwcixzZWxlY3QgPSAtYyAobm8sIGlkX2Zvcm0sIHByb2R1Y3RvLCBob3JhX2ZpbiwgaW5pY2lvX3NldHVwLCBmaW5faW5pY2lvX3N1LCBpbmljaW9fcHJvY2VzbywgZmluX3Byb2Nlc28sIHRpZW1wb19tYXRlcmlhbGVzLCBtZXJtYSkpDQpgYGANCg0KDQoqKipDYW1iaWFtb3MgdmFsb3JlcyBkZSBOQcK0cyBwb3IgbGEgTUVESUFOQSoqKg0KYGBge3J9DQpwcjwtcHIgJT4lIG11dGF0ZShwaWV6YXNfcHJvZz1pZmVsc2UoaXMubmEocGllemFzX3Byb2cpLG1lZGlhbihwaWV6YXNfcHJvZyxuYS5ybT1UKSxwaWV6YXNfcHJvZykpDQpwcjwtcHIgJT4lIG11dGF0ZSh0aWVtcG9fbWludXRvcz1pZmVsc2UoaXMubmEodGllbXBvX21pbnV0b3MpLG1lZGlhbih0aWVtcG9fbWludXRvcyxuYS5ybT1UKSx0aWVtcG9fbWludXRvcykpDQpwcjwtcHIgJT4lIG11dGF0ZShsYW1pbmFzX3Byb2Nlc2FkYXM9aWZlbHNlKGlzLm5hKGxhbWluYXNfcHJvY2VzYWRhcyksbWVkaWFuKGxhbWluYXNfcHJvY2VzYWRhcyxuYS5ybT1UKSxsYW1pbmFzX3Byb2Nlc2FkYXMpKQ0KcHI8LXByICU+JSBtdXRhdGUodGllbXBvX2NhbGlkYWQ9aWZlbHNlKGlzLm5hKHRpZW1wb19jYWxpZGFkKSxtZWRpYW4odGllbXBvX2NhbGlkYWQsbmEucm09VCksdGllbXBvX2NhbGlkYWQpKQ0KYGBgDQoNCioqKkNvbnZlcnRpbW9zIHZhcmlhYmxlcyoqKg0KDQpgYGB7cn0NCnByJGZlY2hhPC1hcy5EYXRlKHByJGZlY2hhLGZvcm1hdD0iJWQvJW0vJVkiKQ0KcHIkcGllemFzX3Byb2c8LWFzLm51bWVyaWMocHIkcGllemFzX3Byb2cpDQpwciR0aWVtcG9fbWludXRvczwtYXMubnVtZXJpYyhwciR0aWVtcG9fbWludXRvcykNCnByJGxhbWluYXNfcHJvY2VzYWRhczwtYXMubnVtZXJpYyhwciRsYW1pbmFzX3Byb2Nlc2FkYXMpDQoNCmBgYA0KKioqU3Vic2l0dWlyIE5BwrRzIHBvciBsYSBtZWRpYSoqKg0KYGBge3J9DQoNCnByJHRpZW1wb19taW51dG9zW2lzLm5hKHByJHRpZW1wb19taW51dG9zKV08LW1lZGlhbihwciR0aWVtcG9fbWludXRvcywgbmEucm0gPSBUUlVFKQ0KcHIkdGllbXBvX2NhbGlkYWRbaXMubmEocHIkdGllbXBvX2NhbGlkYWQpXTwtbWVkaWFuKHByJHRpZW1wb19jYWxpZGFkLCBuYS5ybSA9IFRSVUUpDQpwciRsYW1pbmFzX3Byb2Nlc2FkYXNbaXMubmEocHIkbGFtaW5hc19wcm9jZXNhZGFzKV08LW1lZGlhbihwciRsYW1pbmFzX3Byb2Nlc2FkYXMsIG5hLnJtID0gVFJVRSkNCg0KYGBgDQoNCiMjICoqQW5hbGlzaXMgRXhwbG9yYXRvcmlvKioNCg0KYGBge3J9DQptZWEyIDwtIG1lYW4ocHIkcGllemFzX3Byb2cpDQptZWQyIDwtIG1lZGlhbihwciRwaWV6YXNfcHJvZykNCm1vZGEyPC0gbWZ2KHByJHBpZXphc19wcm9nKQ0Kc2QyIDwtIHNkKHByJHBpZXphc19wcm9nLCBuYS5ybSA9IFRSVUUpDQoNCm1lYTMgPC0gbWVhbihwciR0aWVtcG9fbWludXRvcykNCm1lZDMgPC0gbWVkaWFuKHByJHRpZW1wb19taW51dG9zKQ0KbW9kYTMgPC0gbWZ2KHByJHRpZW1wb19taW51dG9zKQ0Kc2QzIDwtIHNkKHByJHRpZW1wb19taW51dG9zLCBuYS5ybSA9IFRSVUUpDQoNCm1lYTQgPC0gbWVhbihwciRsYW1pbmFzX3Byb2Nlc2FkYXMpDQptZWQ0IDwtIG1lZGlhbihwciRsYW1pbmFzX3Byb2Nlc2FkYXMpDQptb2RhNCA8LSBtZnYocHIkbGFtaW5hc19wcm9nKQ0Kc2Q0IDwtIHNkKHByJGxhbWluYXNfcHJvY2VzYWRhcywgbmEucm0gPSBUUlVFKQ0KDQptZWE1IDwtIG1lYW4ocHIkdGllbXBvX2NhbGlkYWQpDQptZWQ1IDwtIG1lZGlhbihwciR0aWVtcG9fY2FsaWRhZCkNCm1vZGE1IDwtIG1mdihwciR0aWVtcG9fY2FsaWRhZCkNCnNkNSA8LSBzZChwciR0aWVtcG9fY2FsaWRhZCwgbmEucm0gPSBUUlVFKQ0KDQptb2RhNiA8LSAgbWZ2KHByJGNsaWVudGUpDQptb2RhIDwtIG1mdihwciRmZWNoYSkgDQptb2RhMSA8LSBtZnYocHIkZXN0YWNpb25fYXJyYW5xdWUpDQoNClZhcmlhYmxlcyA8LWMoIlBpZXphc19wcm9nIiwiVGllbXBvIE1pbnV0b3MiLCAiTGFtaW5hcyBwcm9jZXNhZGFzIiwgIlRpZW1wbyBDYWxpZGFkIiwgIkNsaWVudGUiLCJGZWNoYSIsIkVzdGFjacOzbiBkZSBBcnJhbnF1ZSIpDQpNZWRpYSA8LWMobWVhMixtZWEzLG1lYTQsbWVhNSwiTkEiLCJOQSIsIk5BIikNCk1lZGlhbmEgPC1jKG1lZDIsbWVkMyxtZWQ0LG1lZDUsIk5BIiwiTkEiLCJOQSIpDQpNb2RhIDwtYyhtb2RhMixtb2RhMyxtb2RhNCxtb2RhNSxtb2RhNixtb2RhLG1vZGExKQ0KRGVzdmlhY2lvbiA8LWMoc2QyLHNkMyxzZDQsc2Q1LCJOQSIsIk5BIiwiTkEiKQ0KdGFibGEyIDwtZGF0YS5mcmFtZShWYXJpYWJsZXMsIE1lZGlhLCBNZWRpYW5hLCBNb2RhLERlc3ZpYWNpb24pDQprbml0cjo6a2FibGUodGFibGEyKQ0KYGBgDQoNCioqKlRhYmxhIGRlIHZhcmlhYmxlcyB5IG1lZGljacOzbioqKg0KDQpgYGB7cn0NClZhcmlhYmxlPC1jKCJGZWNoYSIsICJDbGllbnRlIiwgIlBpZXphcyBQcm9ncmFtYWRhcyIsICJUaWVtcG8gTcOtbmltbyIsICJFc3RhY2nDs24gQXJyYW5xdWUiLCAiTMOhbWluYXMgUHJvY2VzYWRhcyIsICJUaWVtcG8gZGUgQ2FsaWRhZCIpDQpUaXBvIDwtYygiQ3VhbGl0YXRpdmEiLCAiQ3VhbGl0YXRpdmEiLCAiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwgIkN1YW50aXRhdGl2YSBjb250aW51YSIsICJDdWFsaXRhdGl2YSIsICJDdWFudGl0YXRpdmEgY29udGludWEiLCAiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIikNCk1lZGljacOzbiA8LWMoIk5BIiwgIk5BIiwgIlVuaWRhZGVzIiwgIk1pbnV0b3MiLCAiTmEiLCAiVW5pZGFkZXMiLCAiTWludXRvcyIpDQp0YWI8LWRhdGEuZnJhbWUoVmFyaWFibGUsVGlwbyxNZWRpY2nDs24pDQp0YWINCmBgYA0KKioqR3JhZmljYXMqKioNCg0KYGBge3J9DQpoaXN0KHByJHBpZXphc19wcm9nLCBtYWluID0gIkxhbWluYXMgUHJvY2VzYWRhcyIsIHlsYWIgPSAiRnJlY3VlbmNpYSIsIHhsYWIgPSAiUGllemFzIFByb2dyYW1hZGFzIiwgY29sID0gInJlZCIpDQpgYGANCg0KDQoNCiMgKipNZXJtYSoqDQpgYGB7cn0NCm1lIDwtIHJlYWQuY3N2KCJDOlxcVXNlcnNcXGNoZW1hXFxEb3dubG9hZHNcXEZPUk0xIC0gTWVybWEuY3N2IikNCmBgYA0KDQojIyAqKkxpbXBpZXphKioNCg0KKioqRWxpbWluYW1vcyBmaWxhcyBkZSB0b3RhbGVzKioqDQpgYGB7cn0NCm1lMTwtbWVbLWMoNSwxMiwxOSwyNSwzMSwzNiw0Miw1NCw1OSw2MCksXQ0KYGBgDQoNCioqKkNvbnZlcnRpbW9zIFZhcmlhYmxlcyoqKg0KYGBge3J9DQptZTEkRmVjaGE8LWFzLkRhdGUobWUxJEZlY2hhLCBmb3JtYXQgPSAiJW0vJWQvJVkiKQ0KbWUxJEtpbG9zPC1hcy5udW1lcmljKG1lMSRLaWxvcykNCmBgYA0KDQoNCiMjICoqQW5hbGlzaXMgRXhwbG9yYXRvcmlvKioNCg0KYGBge3J9DQoNCm1lYTIwPC0gbWVhbihtZTEkS2lsb3MpDQptZWQyMDwtIG1lZGlhbihtZTEkS2lsb3MpDQptb2RhMjA8LSBtZnYobWUxJEtpbG9zKQ0Kc2QyMDwtIHNkKG1lMSRLaWxvcywgbmEucm0gPSBUUlVFKQ0KDQpWYXJpYWJsZXMxIDwtYygiS2lsb3MiKQ0KTWVkaWExIDwtYyhtZWEyMCkNCk1lZGlhbmExIDwtYyhtZWQyMCkNCk1vZGExIDwtYyhtb2RhMjApDQpEZXN2aWFjaW9uMSA8LWMoc2QyMCkNCnRhYmxhMjAgPC1kYXRhLmZyYW1lKFZhcmlhYmxlczEsIE1lZGlhMSwgTWVkaWFuYTEsIE1vZGExLERlc3ZpYWNpb24xKQ0Ka25pdHI6OmthYmxlKHRhYmxhMjApDQpgYGANCg0KKioqVGFibGEgZGUgdmFyaWFibGVzIHkgbWVkaWNpw7NuKioqDQoNCmBgYHtyfQ0KVmFyaWFibGU8LWMoIkZlY2hhIiwgIk1lcyIsICJLaWxvcyIpDQpUaXBvPC1jKCJDdWFsaXRhdGl2YSIsICJDdWFsaXRhdGl2YSIsICJDdWFudGl0YXRpdmEgY29udGludWEiKQ0KTWVkaWNpw7NuIDwtYygiTkEiLCAiTkEiLCAiS2lsb2dyYW1vcyIpDQp0YWI8LWRhdGEuZnJhbWUoVmFyaWFibGUsVGlwbywgTWVkaWNpw7NuKQ0KdGFiDQpgYGANCioqKkdyYWZpY2FzKioqDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQpnZ3Bsb3QobWUxLCBhZXMoeD1hcy5mYWN0b3IoTWVzKSwgZmlsbD1hcy5mYWN0b3IoS2lsb3MpICkpICsgDQogIGdlb21fYmFyKCApICsNCiAgc2NhbGVfZmlsbF9ncmV5KHN0YXJ0ID0gMC4yNSwgZW5kID0gMC43NSkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQ0KDQoNCmBgYA0KRW4gZXN0YSBncmFmaWNhIHBvZGVtb3MgdmVyIGN1YWwgZXMgZWwgbWVzIHF1ZSBtYXMgbWVybWEgZ2VuZXJhLCBlbCBjdWFsIGVzIGVsIG1lcyBkZSBBZ29zdG8uDQoNCiMgKipTY3JhcCoqDQoNCg0KYGBge3J9DQpzYyA8LSByZWFkLmNzdigiQzpcXFVzZXJzXFxjaGVtYVxcRG93bmxvYWRzXFxGT1JNMSAtIFNjcmFwICgxKS5jc3YiKQ0KYGBgDQoNCiMjICoqTGltcGllemEqKg0KDQoqKipDYW1iaWFtb3MgZWwgdGlwbyBkZSB2YXJpYWJsZSoqKg0KYGBge3J9DQpzYyRGZWNoYSA8LSBhcy5EYXRlKHNjJEZlY2hhLCBmb3JtYXQgPSAiJWQvJW0vJVkiKQ0KYGBgDQoNCioqKk1lZGlhLCBNb2RhLCBNZWRpYW5hIHkgRGVzdmlhY2nDs24gRXN0YW5kYXIqKioNCg0KYGBge3J9DQptZWEyMjwtIG1lYW4oc2MkQ2FudCkNCm1lZDIyPC0gbWVkaWFuKHNjJENhbnQpDQptb2RhMjI8LSBtZnYoc2MkQ2FudCkNCnNkMjI8LSBzZChzYyRDYW50LCBuYS5ybSA9IFRSVUUpDQoNClZhcmlhYmxlczggPC1jKCJDYW50aWRhZCIpDQpNZWRpYTggPC1jKG1lYTIyKQ0KTWVkaWFuYTggPC1jKG1lZDIyKQ0KTW9kYTggPC1jKG1vZGEyMikNCkRlc3ZpYWNpb244IDwtYyhzZDIyKQ0KdGFibGEyMiA8LWRhdGEuZnJhbWUoVmFyaWFibGVzOCwgTWVkaWE4LCBNZWRpYW5hOCwgTW9kYTgsRGVzdmlhY2lvbjgpDQprbml0cjo6a2FibGUodGFibGEyMikNCmBgYA0KDQoqKipUYWJsYSBkZSB2YXJpYWJsZXMgeSBtZWRpY2nDs24qKioNCg0KYGBge3J9DQpWYXJpYWJsZTwtYygiRmVjaGEiLCAiQ2FudGlkYWQiLCAiVWJpY2FjacOzbiBkZSBPcmlnZW4iKQ0KVGlwbzwtYygiQ3VhbGl0YXRpdmEiLCAiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwgIkN1YWxpdGF0aXZhIikNCk1lZGljacOzbiA8LWMoIk5BIiwgIktpbG9ncmFtb3MiLCAiTkEiKQ0KdGFibGE4PC1kYXRhLmZyYW1lKFZhcmlhYmxlLFRpcG8sIE1lZGljacOzbikNCnRhYmxhOA0KYGBgDQoNCioqKkdyYWZpY2FzKioqDQoNCmBgYHtyfQ0KZ2dwbG90KHNjLCBhZXMoeD1hcy5mYWN0b3IoVWJpLm9yaWdlbiksIGZpbGw9YXMuZmFjdG9yKENhbnQpICkpICsgDQogIGdlb21fYmFyKCApICsNCiAgc2NhbGVfZmlsbF9ncmV5KHN0YXJ0ID0gMC4yNSwgZW5kID0gMC43NSkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQ0KDQpgYGANCg0KIyAqKlNlY2Npw7NuIDIqKg0KDQoqKipJbXBvcnRhbW9zIGJhc2UgZGUgZGF0b3MgZXh0ZXJuYSoqKg0KYGBge3J9DQoNCmBgYA0KIyAqKlNlY2Npw7NuIDMqKg0KDQojICoqMS4gQ29uY2VwdG9zIENsYXZlcyoqDQoqKkstIFZlY2lub3MgTcOhcyBDZXJjYW5vcyB5L28gSy1NZWFucyBDbHVzdGVyaW5nOioqICANCktOTiB5IEttZWFucyBjbHVzdGVyaW5nLCBzb24gZnVuY2lvbmVzIGxhcyBjdWFsZXMgYW1iYXMgY29udHJpYnV5ZW4gYSBsYSBpZGVudGlmaWNhY2nDs24gZGUgY2x1c3RlcnMgeWEgcXVlIEtNQyBlcyB1biBhbGdvcml0bW8gZWwgY3VhbCBzZSB1dGlsaXphYSBwYXJhIGFncnVwYXIsIHNpbiBlbWJhcmdvIEtOTiBzZSB1dGlsaXphIG1hcyBxdWUgbmFkYSBwYXJhIGxhIGNsYXNpZmljYWNpw7NuIGRlIHZhcmlhYmxlcy4gKEhhcnJpc29uLCAyMDE4KQ0KRW4gbGEgZnVuY2nDs24gZGUgSy1tZWFucyBjbHVzdGVyaW5nIHNlIGRpdmlkZSB1biBjb25qdW50byBkZSBuIG9ic2VydmFjaW9uZXMgZW4gayBncnVwb3MsIGVzdGEgZnVuY2nDs24gc2UgdXNhIGN1YW5kbyBubyBzZSB0aWVuZW4gZXRpcXVldGFzIGRlIGdydXBvIGV4aXN0ZW50ZXMgeSBkZXNlYSBhc2lnbmFyIHB1bnRvcyBkZSBkYXRvcyBzaW1pbGFyZXMgYSBsYSBjYW50aWRhZCBkZSBncnVwb3MgcXVlIGVzcGVjaWZpcXVlIChLKS4gKEppbSBGcm9zdCwgMjAyMikgIA0KDQoqKkFwcmVuZGl6YWplIE5vIFN1cGVydmlzYWRvIHkvbyBVbnN1cGVydmlzZWQgTGVhcm5pbmc6KiogIA0KRWwgb2JqZXRpdm8gcXVlIHRpZW5lIGVsIHVuc3VwZXJ2aXNlZCBsZWFybmluZyBlcyBlbCBkZSBkZXNjdWJyaXIgZ3J1cG9zIGRlIGVqZW1wbG9zIHNpbWlsYXJlcyBkZW50cm8gZGUgbG9zIGRhdG9zLCBsbyBxdWUgc2UgZGVub21pbmEg4oCcY2x1c3RlcmluZ+KAnSwgbyBkZXRlcm1pbmFyIGPDs21vIHNlIGRpc3RyaWJ1eWVuIGxvcyBkYXRvcyBlbiBlbCBlc3BhY2lvLCBsbyBxdWUgc2UgY29ub2NlIGNvbW8gZXN0aW1hY2nDs24gZGUgZGVuc2lkYWQNCkVzdGEgZnVuY2nDs24gY29udHJpYnV5ZSBhIGxhIGlkZW50aWZpY2FjacOzbiBkZSBjbHVzdGVycyB5YSBxdWUgbGEgYWdydXBhY2nDs24gZW4g4oCcY2x1c3RlcnPigJ0gZXMgdW4gbcOpdG9kbyBkZSDigJx1bnN1cGVydmlzc2VkIGxlYXJuaW5n4oCdICBxdWUgZnVuY2lvbmEgZW4gY29uanVudG9zIGRlIGRhdG9zIGVuIGxvcyBxdWUgbm8gaGF5IHVuYSB2YXJpYWJsZSBkZSByZXN1bHRhZG8gKG9iamV0aXZvKSBuaSBzZSBzYWJlIG5hZGEgc29icmUgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBvYnNlcnZhY2lvbmVzLCBlcyBkZWNpciwgZGF0b3Mgc2luIGV0aXF1ZXRhci4gIChGcm9udGllcnNpbiwgMjAxOSkgIA0KDQoqKkRpc3RhbmNpYSBFdWNsaWRpYW5hIC8gRXVjbGllZGVhbiBEaXN0YW5jZToqKiAgDQpBbCBtb21lbnRvIGRlIHVzYXIg4oCcRXVjbGlkZWFuIGRpc3RhbmNl4oCdIGxhcyBvYnNlcnZhY2lvbmVzIGNvbiB2YWxvcmVzIGFsdG9zIGRlIGNhcmFjdGVyw61zdGljYXMgc2Ug4oCcYWdydXBhcsOhbuKAnSBqdW50YXMuIExvIG1pc21vIHNlIGFwbGljYSBhIGxhcyBvYnNlcnZhY2lvbmVzIGNvbiB2YWxvcmVzIGJham9zIGRlIGNhcmFjdGVyw61zdGljYXMuIExhIGNvcnJlbGFjacOzbiBkZSBQZWFyc29uIG1pZGUgZWwgZ3JhZG8gZGUgdW5hIHJlbGFjacOzbiBsaW5lYWwgZW50cmUgZG9zIHBlcmZpbGVzLiAoV2FyZWYsIDIwMjApIEVuIG90cmFzIHBhbGFicmFzLCBsYSBkaXN0YW5jaWEgDQpldWNsaWRpYW5hIGVzIGxhIGRpc3RhbmNpYSBxdWUgaGF5IGVudHJlIGRvcyBkYXRvcyBlbiB1biBlc3BhY2lvLiANCg0KIyMgKioyLiBLLW1lYW5zIENsdXN0ZXJpbmcqKg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgZGVzY2FyZ2FyIHkgbGxhbWFyIGxpYnJlcsOtYXMNCiNpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQojaW5zdGFsbC5wYWNrYWdlcygiZm9yZWlnbiIpDQojaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KI2luc3RhbGwucGFja2FnZXMoInBzeWNoIikNCmxpYnJhcnkocHN5Y2gpDQojaW5zdGFsbC5wYWNrYWdlcygiY29ycnBsb3QiKQ0KbGlicmFyeShjb3JycGxvdCkNCiNpbnN0YWxsLnBhY2thZ2VzKCJqdG9vbHMiKQ0KbGlicmFyeShqdG9vbHMpDQojaW5zdGFsbC5wYWNrYWdlcygibG10ZXN0IikNCmxpYnJhcnkobG10ZXN0KQ0KI2luc3RhbGwucGFja2FnZXMoImNhciIpDQpsaWJyYXJ5KGNhcikNCiNpbnN0YWxsLnBhY2thZ2VzKCJmYWN0b2V4dHJhIikNCmxpYnJhcnkoZmFjdG9leHRyYSkNCiNpbnN0YWxsLnBhY2thZ2VzKCJqYW5pdG9yIikNCmxpYnJhcnkoamFuaXRvcikNCiNpbnN0YWxsLnBhY2thZ2VzKCJyZWFkciIpDQpsaWJyYXJ5KHJlYWRyKQ0KI2luc3RhbGwucGFja2FnZXMoInBsb3RyaXgiKQ0KbGlicmFyeShwbG90cml4KQ0KYGBgDQoNCiMjICpMaW1waWFyIGJhc2UgZGUgZGF0b3MqDQpgYGB7cn0NCnJoIDwtIHJlYWQuY3N2KCIvVXNlcnMvY2hlbWEvRG93bmxvYWRzL3JlY3Vyc29zX2h1bWFub3NfYmFzZV9saW1waWEuY3N2IikNCiMgTGltcGlhciBub21icmUNCmxpYnJhcnkoamFuaXRvcikNCnJoMSA8LSBjbGVhbl9uYW1lcyhyaCkNCiMgVmlzdWFsaXphciBiYXNlIGRlIGRhdG9zDQpzdW1tYXJ5KHJoMSkNCiMgRWxpbWluYXIgY29sdW1uYXMgcXVlIG5vIHNlIG5lY2VzaXRhbg0KcmgyIDwtIHN1YnNldChyaDEsc2VsZWN0ID0gLWMgKGFwZWxsaWRvcywgbm9tYnJlLCBmZWNoYV9kZV9uYWNpbWllbnRvLCByZmMsIGZlY2hhX2RlX2FsdGEsIGJhamEsIGRlcGFydGFtZW50bywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9fc2VndXJvX3NvY2lhbCwgZmFjdG9yX2NyZWRfaW5mb25hdml0LCBuX2NyZWRpdG9faW5mb25hdml0LCBsdWdhcl9kZV9uYWNpbWllbnRvLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnAsIGNhbGxlLCBudW1lcm9faW50ZXJubywgY29sb25pYSwgY29kaWdvX3Bvc3RhbCwgbXVuaWNpcGlvLCBlc3RhZG8sIHRhcmpldGFfb19jdWVudGEpKQ0Kc3VtbWFyeShyaDIpDQoNCiMgbmEncyBlbiBsYSBiYXNlIGRlIGRhdG9zDQpzdW0oaXMubmEocmgyKSkNCnNhcHBseShyaDIsIGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpDQojIG5vIHNlIGVuY3VlbnRyYW4gTkEncyBlbiBsYSBiYXNlIGRlIGRhdG9zIA0KDQojIENvbnZlcnRpciB0aXBvcyBkZSBkYXRvcw0KcmgyJGVkYWQgPC0gYXMubnVtZXJpYyhyaDIkZWRhZCkNCnJoMiRnZW5lcm8gPC0gYXMuZmFjdG9yKHJoMiRnZW5lcm8pDQpyaDIkbW90aXZvX2RlX2JhamEgPC0gYXMuZmFjdG9yKHJoMiRtb3Rpdm9fZGVfYmFqYSkNCnJoMiRkaWFzX2xhYm9yYWRvcyA8LSBhcy5udW1lcmljKHJoMiRkaWFzX2xhYm9yYWRvcykNCnJoMiRwdWVzdG8gPC0gYXMuZmFjdG9yKHJoMiRwdWVzdG8pDQpyaDIkc2FsYXJpb19kaWFyaW9faW1zcyA8LSBhcy5udW1lcmljKHJoMiRzYWxhcmlvX2RpYXJpb19pbXNzKQ0KcmgyJGVzdGFkb19jaXZpbCA8LSBhcy5mYWN0b3IocmgyJGVzdGFkb19jaXZpbCkNCnN1bW1hcnkocmgyKQ0KYGBgDQoNCiMjICpDcmVhciBjbHVzdGVycyoNCiMjIyBDbHVzdGVyIDE6IEVkYWQgeSBOw7ptZXJvIGRlIGTDrWFzIGxhYm9yYWRvcw0KYGBge3J9DQojIE5vcm1hbGl6YXIgVmFyaWFibGVzDQpyaF9lZGFkX2RpYXMgPC1yaDIgJT4lIGRwbHlyOjpzZWxlY3Qoc2FsYXJpb19kaWFyaW9faW1zcywgZWRhZCwgZGlhc19sYWJvcmFkb3MpDQpyaF9lZGFkX2RpYXNfbm9ybTwtc2NhbGUocmhfZWRhZF9kaWFzWzI6M10pIA0KcGxvdChyaF9lZGFkX2RpYXNfbm9ybSkNCiMgTsO6bWVybyDDs3B0aW1vIGRlIGNsw7pzdGVycyBjb24gIkVsYm93IFBsb3QiDQpmdml6X25iY2x1c3QocmhfZWRhZF9kaWFzX25vcm0sIGttZWFucywgbWV0aG9kPSJ3c3MiKSsgDQogIGdlb21fdmxpbmUoeGludGVyY2VwdD02LCBsaW5ldHlwZT0yKSsgICAgICAgICAgIA0KICBsYWJzKHN1YnRpdGxlID0gIkVsYm93IG1ldGhvZCIpICANCmBgYA0KDQpEZSBhY3VlcmRvIGFsIGVsYm93IG1ldGhvZCwgZWwgbnVtZXJvIMOzcHRpbW8gZGUgY2x1c3RlcnMgc29uIDYgcGVybyBhbCBtb21lbnRvIGRlIHZpc3VhbGl6YXJsbyBzZSBkZXRlcm1pbsOzIHF1ZSBlcyB1bmEgZWxldmFkYSBjYW50aWRhZCBkZSBjbHVzdGVycyB5IG5vIHNlcsOtYSB0YW4gc2VuY2lsbG8gZWwgaW50ZXJwcmV0YXIgeSBub21icmFyIHRhbnRvcyBjbHVzdGVycyBwb3IgbG8gcXVlIHNlIGxsZWfDsyBhIGxhIGNvbmNsdXNpw7NuIHF1ZSBzZSBlbGFib3JhcsOhbiA1IGNsdXN0ZXJzLg0KDQpgYGB7cn0NCiMgVmlzdWFsaXphciBDbHVzdGVycw0KY2x1c3RlcjEgPC1rbWVhbnMocmhfZWRhZF9kaWFzX25vcm0sNSkNCmNsdXN0ZXIxDQpmdml6X2NsdXN0ZXIoY2x1c3RlcjEsZGF0YT1yaF9lZGFkX2RpYXNfbm9ybSkNCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCkludGVycHJldGFjacOzbjogQ2x1c3RlciBuw7ptZXJvIDEgeSA0IHNvbiBkZSBlZGFkZXMgZGlmZXJlbnRlcyBwZXJvIHRpZW5lbiBkw61hcyBsYWJvcmFkb3Mgc2ltaWxhcmVzLCBpZ3VhbCBxdWUgZWwgY2x1c3RlciAzIHkgNSAuIFBvciBvdHJvIGxhZG8sIGVsIGNsdXN0ZXIgMiBzb24gZGF0b3MgcXVlIG5vIHRpZW5lbiBkw61hcyBsYWJvcmFkb3Mgc2ltaWxhcmVzIHBlcm8gdGllbmVuIG3DoXMgZMOtYXMgcXVlIGxvcyBvdHJvcyBjbHVzdGVycyB5IHRpZW5lIHVuIHJhbmdvIGRpZmVyZW50ZSBkZSBlZGFkZXMuIFBvciBsbyBxdWUgc2UgY29uY2x1eWUgcXVlIGxvcyBkw61hcyBsYWJvcmFkb3Mgbm8gdGllbmVuIHRhbnRhIHJlbGFjacOzbiBjb24gbGEgZWRhZC4gDQoNCiMjIyBDbHVzdGVyIDI6IEVkYWQgeSBTYWxhcmlvIERpYXJpbw0KYGBge3J9DQojIE5vcm1hbGl6YXIgVmFyaWFibGVzDQpyaF9lZGFkX3NhbCA8LXJoMiAlPiUgZHBseXI6OnNlbGVjdChzYWxhcmlvX2RpYXJpb19pbXNzLCBlZGFkLCBkaWFzX2xhYm9yYWRvcykNCnJoX2VkYWRfc2FsX25vcm08LXNjYWxlKHJoX2VkYWRfZGlhc1sxOjJdKSANCnBsb3QocmhfZWRhZF9zYWxfbm9ybSkNCiMgTsO6bWVybyDDs3B0aW1vIGRlIGNsw7pzdGVycyBjb24gIkVsYm93IFBsb3QiDQpmdml6X25iY2x1c3QocmhfZWRhZF9zYWxfbm9ybSwga21lYW5zLCBtZXRob2Q9IndzcyIpKyANCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTUsIGxpbmV0eXBlPTIpKyAgICAgICAgICAgDQogIGxhYnMoc3VidGl0bGUgPSAiRWxib3cgbWV0aG9kIikgIA0KYGBgDQpTZSBkZXRlcm1pbsOzIHF1ZSBlbCBuw7ptZXJvIMOzcHRpbW8gZXMgZGUgNSBjbHVzdGVycw0KDQpgYGB7cn0NCiMgVmlzdWFsaXphciBDbHVzdGVycw0KY2x1c3RlcjIgPC1rbWVhbnMocmhfZWRhZF9zYWxfbm9ybSw1KQ0KY2x1c3RlcjINCmZ2aXpfY2x1c3RlcihjbHVzdGVyMixkYXRhPXJoX2VkYWRfc2FsX25vcm0pDQpgYGANCg0KSW50ZXJwcmV0YWNpw7NuOiBUb2RvcyB0aWVuZW4gdW4gc2FsYXJpbyBzaW1pbGFyIHNpbiBpbXBvcnRhciBsYSBlZGFkIHBlcm8gZW4gZWwgY2x1c3RlciAxIChxdWUgc29sbyBlcyB1biBwdW50bykgbm9zIGluZGljYSBxdWUgaGF5IGFsZ3VpZW4gcXVlIGdhbmEgbcOhcyBxdWUgbG9zIGRlbcOhcyBjb2xhYm9yYWRvcmVzIHkgdGllbmVuIHVuYSBlZGFkIHJlbGF0aXZhbWVudGUgam92ZW4gYSBjb21wYXJhY2nDs24gZGUgbG9zIGRlbcOhcyBkYXRvcw0KDQojIyMgQ2x1c3RlciAzOiBOw7ptZXJvIGRlIGTDrWFzIGxhYm9yYWRvcyB5IFNhbGFyaW8gRGlhcmlvDQpgYGB7cn0NCiMgTm9ybWFsaXphciBWYXJpYWJsZXMNCnJoX2RpYXNfc2FsIDwtcmgyICU+JSBkcGx5cjo6c2VsZWN0KHNhbGFyaW9fZGlhcmlvX2ltc3MsIGRpYXNfbGFib3JhZG9zLCBlZGFkKQ0KcmhfZGlhc19zYWxfbm9ybTwtc2NhbGUocmhfZGlhc19zYWxbMToyXSkgDQpwbG90KHJoX2RpYXNfc2FsX25vcm0pDQojIE7Dum1lcm8gw7NwdGltbyBkZSBjbMO6c3RlcnMgY29uICJFbGJvdyBQbG90Ig0KZnZpel9uYmNsdXN0KHJoX2RpYXNfc2FsX25vcm0sIGttZWFucywgbWV0aG9kPSJ3c3MiKSsgDQogIGdlb21fdmxpbmUoeGludGVyY2VwdD01LCBsaW5ldHlwZT0yKSsgICAgICAgICAgIA0KICBsYWJzKHN1YnRpdGxlID0gIkVsYm93IG1ldGhvZCIpICANCmBgYA0KDQpTZSBkZXRlcm1pbsOzIHF1ZSBlbCBuw7ptZXJvIMOzcHRpbW8gZXMgZGUgNSBjbHVzdGVycw0KDQpgYGB7cn0NCiMgVmlzdWFsaXphciBDbHVzdGVycw0KY2x1c3RlcjMgPC1rbWVhbnMocmhfZGlhc19zYWxfbm9ybSw1KQ0KY2x1c3RlcjMNCmZ2aXpfY2x1c3RlcihjbHVzdGVyMyxkYXRhPXJoX2RpYXNfc2FsX25vcm0pDQpgYGANCg0KSW50ZXJwcmV0YWNpw7NuOiBMb3MgZMOtYXMgbGFib3JhZG9zIG5vIHRpZW5lbiBpbmZsdWVuY2lhIGVuIGVsIHNhbGFyaW8gcG9ycXVlIGhheSBkYXRvcyBxdWUgaW5kaWNhbiBjb2xhYm9yYWRvcmVzIHF1ZSB0cmFiYWphbiBtw6FzIGTDrWFzIHBlcm8gdGllbmVuIHVuIHNhbGFyaW8gc2ltaWxhciBhIGxvcyBxdWUgbm8gdGllbmVuIHRhbnRvcyBkw61hcyBsYWJvcmFkb3MuIEVuIGVsIGNsdXN0ZXIgMiBwb2RlbW9zIG9ic2VydmFyIHF1ZSBlcyBlbCBxdWUgdGllbmUgdW4gbWF5b3Igc2FsYXJpbyBwZXJvIG5vIGVzIGVsIHF1ZSB0aWVuZSB1bmEgY2FudGlkYWQgYWx0YSBkZSBkw61hcyBsYWJvcmFkb3MgY29tbyBlcyBlbiBlbCBjbHVzdGVyIDEuIFBvciBsbyB0YW50bywgbG9zIGTDrWFzIGxhYm9yYWRvcyBubyB0aWVuZW4gcmVsYWNpw7NuIGNvbiBlbCBzYWxhcmlvLiANCg0KIyMgKkNyZWFjacOzbiBkZSBzZWdtbWVudG9zIHVzYW5kbyBlbCBjbHVzdGVyIDI6IEVkYWQgeSBTYWxhcmlvIERpYXJpbyoNCmBgYHtyfQ0KDQoNCiMgSW5jbHVpciBjb2x1bW5hIHF1ZSBpbmRpcXVlIGVsIGNsdXN0ZXIgZGUgY2FkYSByZWdpc3Rybw0KcmgzIDwtIHJoMg0KcmgzJENsdXN0ZXJzPC1jbHVzdGVyMiRjbHVzdGVyDQoNCiMgdmlzdWFsaXphciBsYSBtw6F4aW1hIGVkYWQgZGUgY2FkYSBjbHVzdGVyDQpyaDQgPC0gcmgzICU+JSBkcGx5cjo6Z3JvdXBfYnkoQ2x1c3RlcnMpICU+JSBkcGx5cjo6c3VtbWFyaXNlKGVkYWQ9bWF4KGVkYWQpKSAlPiUgZHBseXI6OmFycmFuZ2UoZGVzYyhlZGFkKSkNCg0KIyBOb21icmFyIGNhZGEgY2x1c3RlciANCnJoMyRub21icmVzX2NsdXN0ZXJzIDwtIGZhY3RvcihyaDMkQ2x1c3RlcnMsbGV2ZWxzID0gYygxLDIsMyw0LDUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJFeGNlcGNpb24iLCAiSnViaWxhZG9zIiwgIk1heW9yZXMiLCAiQWR1bHRvcyIsICJKb3ZlbmVzIikpDQoNCiMgQWdydXBhciBsb3MgZGF0b3MgcG9yIG5vbWJyZSBkZSBjbHVzdGVycyANCmxpYnJhcnkoZHBseXIpDQpyaDUgPC0gcmgzICU+JSBkcGx5cjo6Z3JvdXBfYnkobm9tYnJlc19jbHVzdGVycykgJT4lIGRwbHlyOjpzdW1tYXJpemUoZWRhZF9hw7Fvcz1tYXgoZWRhZCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbGFyaW9faW1zcz1tZWFuKHNhbGFyaW9fZGlhcmlvX2ltc3MpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENvdW50PW4oKSkNCg0KY2x1c3RlcnM8LWFzLmRhdGEuZnJhbWUocmg1KQ0KY2x1c3RlcnMNCmBgYA0KDQojIyAqR3LDoWZpY29zIGNvbXBsZW1lbnRhcmlvcyogDQojIyMgR3LDoWZpY28gcG9yIG5vbWJyZSBkZSBjbHVzdGVyIA0KYGBge3J9DQpnZ3Bsb3Qocmg1LGFlcyh4PXJlb3JkZXIobm9tYnJlc19jbHVzdGVycyxDb3VudCkseT1Db3VudCxmaWxsPW5vbWJyZXNfY2x1c3RlcnMpKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikNCmBgYA0KDQpJbnRlcnByZXRhY2nDs246IExvcyBqw7N2ZW5lcyBhZHVsdG9zIHNvbiBsb3MgcXVlIHJlcHJlc2VudGFuIG3DoXMgbsO6bWVybyBkZSBiYWphcyB5IHNlIHZpc3VhbGl6YSBxdWUgZWwgb3JkZW4gZGUgbsO6bWVybyBkZSBiYWphcyBlc3RhIGVuIGVsIG1pc21vIG9yZGVuIGRlIGVkYWQsIGVzdG8gc2lnbmlmaWNhIHF1ZSBkZXNwdcOpcyBkZSBsb3MgasOzdmVuZXMgYWR1bHRvcyBlbCBncnVwbyBxdWUgbcOhcyByZXByZXNlbnRhIGJhamFzIGVzIGVsIGRlIGxvcyBhZHVsdG9zIHkgZGUgYWjDrSBzaWd1ZW4gbG9zIG1heW9yZXMsIHkgcG9yIMO6bHRpbW8gbG9zIGp1YmlsYWRvcy4gRW4gY29uY2x1c2nDs24sIGxhIGVkYWQgcHVlZGUgc2VyIHVuIGZhY3RvciBpbXBvcnRhbnRlIGVuIGVsIG7Dum1lcm8gZGUgYmFqYXMuDQoNCiMjIyBHcsOhZmljbyBkZWwgbcOheGltbyBkZSBlZGFkIGRlIGNhZGEgY2x1c3Rlcg0KYGBge3J9DQpnZ3Bsb3Qocmg1LCBhZXMoeD1ub21icmVzX2NsdXN0ZXJzLHk9ZWRhZF9hw7FvcyxmaWxsPSBub21icmVzX2NsdXN0ZXJzLGxhYmVsPXJvdW5kKGVkYWRfYcOxb3MsZGlnaXRzPTIpKSkgKyANCiAgZ2VvbV9jb2woKSArIA0KICBnZW9tX3RleHQoKQ0KYGBgDQoNCkludGVycHJldGFjacOzbjogQXF1w60gc2Ugb2JzZXJ2YSBsYSBtw6F4aW1hIGRlIGVkYWQgZGUgY2FkYSBjbHVzdGVyIHkgdGFtYmnDqW4gbXVlc3RyYSBsYSByYXrDs24gcG9yIGxhIHF1ZSBzZSBkaWVyb24gbG9zIG5vbWJyZXMgYSBjYWRhIGNsdXN0ZXIuIExvcyBqw7N2ZW5lcyB0aWVuZW4gdW4gcmFuZ28gZGUgZWRhZCBkZSAxOS0yNiwgQWR1bHRvcyAyNy0zNiwgTWF5b3JlcyAzNy00MyB5IEp1YmlsYWRvcyA0NC02MS4NCg0KIyMjIEfDqW5lcm8gZGUgZXgtY29sYWJvcmFkb3Jlcw0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpnZ3Bsb3QocmgzLCBhZXMoZmlsbD1nZW5lcm8sIHk9Z2VuZXJvLCB4PW5vbWJyZXNfY2x1c3RlcnMpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbj0ic3RhY2siLCBzdGF0PSJpZGVudGl0eSIpIA0KYGBgDQoNCkludGVycHJldGFjacOzbjogRW4gbGEgZ3LDoWZpY2Egc2UgYXByZWNpYSB1biBuw7ptZXJvIGFsdG8gZGUgZ8OpbmVybyBtYXNjdWxpbm8gZW4gdG9kb3MgbG9zIGNsdXN0ZXJzLiBFbiBKdWJpbGFkb3MgeSBNYXlvcmVzIGVsIGfDqW5lcm8gRmVtZW5pbm8gZXMgbWF5b3IgcXVlIGVsIG1hc2N1bGluby4gDQoNCiMjIyBNb3Rpdm8gZGUgYmFqYSBkZSBleC1jb2xhYm9yYWRvcmVzDQpgYGB7cn0NCmdncGxvdChyaDMsIGFlcyhmYWN0b3Iobm9tYnJlc19jbHVzdGVycyksIGZpbGwgPSBmYWN0b3IobW90aXZvX2RlX2JhamEpKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlMihwcmVzZXJ2ZSA9ICJzaW5nbGUiKSkNCmBgYA0KDQpJbnRlcnByZXRhY2nDs246ICBTZSBwdWVkZSBvYnNlcnZhciBxdWUgZWwgbW90aXZvIGRlIGJhamEgbWFzIGdyYW5kZSBlbiB0b2RvcyBsb3MgZ3J1cG9zIGRlIGVkYWRlcyBlcyBsYSBiYWphIHBvciBmYWx0YXMsIHNlZ3VpZG8gZGUgcmVudW5jaWEgdm9sdW50YXJpYS4gRW4gasOzdmVuZXMgc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIGhheSBiYWphIHBvciBhYmFuZG9ubywgbWllbnRyYXMgcXVlIGVuIGxvcyBvdHJvcyBjbHVzdGVycyBubyBodWJvIG5pbmd1bmEgYmFqYSBwb3IgYWJhbmRvbm8uIA0KDQojIyMgUHVlc3RvIGRlIGRlIGV4LWNvbGFib3JhZG9yZXMgIA0KYGBge3J9DQpsaWJyYXJ5KHBseXIpDQpjb3VudChyaDMkcHVlc3RvKQ0KcHJvcG9yY2lvbmVzIDwtIGMoMTc2LCAxMSwgMTEsIDgsIDI2KQ0KZXRpIDwtIGMoImF5dWRhbnRlIGdlbmVyYWwiLCAiYXl1LiBzb2xkYWRvci9zb2xkYWRvciIsICJjb3N0dXJlcmEiLCAiYXl1LiBlbWJhcnF1ZSIsICJvdHJvcyIgKQ0KcGN0IDwtIHJvdW5kKHByb3BvcmNpb25lcy9zdW0ocHJvcG9yY2lvbmVzKSoxMDApDQpldGkgPC0gcGFzdGUoZXRpLCBwY3QpDQpldGkgPC0gcGFzdGUoZXRpLCIlIixzZXA9IiIpDQpwaWUzRChwcm9wb3JjaW9uZXMsbGFiZWxzID0gZXRpLA0KICAgIGNvbD1yYWluYm93KGxlbmd0aChldGkpKSwNCiAgICBtYWluPSJQdWVzdG9zIGRlIGJhamFzIikNCmBgYA0KDQpJbnRlcnByZXRhY2nDs246IGVsIHB1ZXN0byBlbiBlbCBxdWUgbcOhcyBzZSBwcmVzZW50YW4gYmFqYXMgZXMgZW4gYXl1ZGFudGUgZ2VuZXJhbCwgc2VndWlkbyBkZSBheXVkYW50ZSBzb2xkYWRvci9zb2xkYWRvciwgY29zdHVyZXJhLCBldGMuIFVuYSBkZSBsYXMgcG9zaWJsZXMgcmF6b25lcyBwb3IgbGEgcXVlIGhheWEgbcOhcyBiYWphcyBlbiBheXVkYW50ZSBnZW5lcmFsLCBlcyBwb3JxdWUgZW4gZXNlIHB1ZXN0byBzZSBuZWNlc2l0YW4gbcOhcyBjb2xhYm9yYWRvcmVzLCBwb3IgbG8gcXVlIGVsIG7Dum1lcm8gZGUgYmFqYXMgZW4gZXNlIHB1ZXN0byBwdWVkZSBzZXIgbWF5b3IgbyB0YW1iacOpbiBwdWVkZSBzZXIgZWwgYW1iaWVudGUgZ2VuZXJhbCBxdWUgc2UgY3JlYSBlbiBlc2UgcHVlc3RvLCBlc3TDoXMgaGlwb3TDqXNpcyBzZSBjb21wcm9iYXLDrWFuIGNvbiB1biBhbsOhbGlzaXMgbcOhcyBwcm9mdW5kbyBkZSBSSC4gDQoNCiMjIyBFc3RhZG8gY2l2aWwgZGUgZXgtY29sYWJvcmFkb3JlcyANCmBgYHtyfQ0KZ2dwbG90KHJoMywgYWVzKGZhY3Rvcihub21icmVzX2NsdXN0ZXJzKSwgZmlsbCA9IGZhY3Rvcihlc3RhZG9fY2l2aWwpKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlMihwcmVzZXJ2ZSA9ICJzaW5nbGUiKSkNCg0KcHJvcG9yY2lvbmVzMSA8LSBjKDEwNywgMywgNTksIDYzKQ0KZXRpcXVldGFzIDwtIGMoInNvbHRlcm8iLCAiZGl2b3JjaW8iLCAidW5pb24gbGlicmUiLCAibWF0cmltb25pbyIpDQpwY3QgPC0gcm91bmQocHJvcG9yY2lvbmVzMS9zdW0ocHJvcG9yY2lvbmVzMSkqMTAwKQ0KZXRpcXVldGFzIDwtIHBhc3RlKGV0aXF1ZXRhcywgcGN0KQ0KZXRpcXVldGFzIDwtIHBhc3RlKGV0aXF1ZXRhcywiJSIsc2VwPSIiKQ0KcGllM0QocHJvcG9yY2lvbmVzMSxsYWJlbHMgPSBldGlxdWV0YXMsDQogICAgICBjb2w9cmFpbmJvdyhsZW5ndGgoZXRpcXVldGFzKSksDQogICAgICBtYWluPSJFc3RhZG8gY2l2aWwgZGUgYmFqYXMiKQ0KYGBgDQoNCkludGVycHJldGFjacOzbjogRW4gZWwgdG90YWwgZGUgYmFqYXMgZWwgZXN0YWRvIGNpdmlsIG3DoXMgY29tw7puIGVzICJzb2x0ZXJvIiwgc2llbmRvIGxvcyBqw7N2ZW5lcyBsb3MgcXVlIHRpZW5lbiB1bmEgbWF5b3IgY2FudGlkYWQgZGUgZXN0ZSBhdHJpYnV0bywgc2VndWlkbyBkZSAgbG9zIGFkdWx0b3MuIERlc3B1w6lzLCBlc3TDoSBlbCBtYXRyaW1vbmlvIHNpZW5kbyBlc3RlIGVsIG3DoXMgcHJlc2VudGUgZW4gZWwgZ3J1cG8gZGUgYWR1bHRvcywgc2VndWlkbyBkZSBsb3MgasOzdmVuZXMuIEVsIGRpdm9yY2lvIG5vIGVzIHTDoW4gY29tw7puIGVuIGxvcyBncnVwb3MuIA0KDQpFbiBjb25jbHVzacOzbiwgc2UgcHVlZGUgZGVkdWNpciBxdWUgbGEgbWF5b3LDrWEgZGUgbG9zIGV4LWNvbGFib3JhZG9yZXMgc29uIHNvbHRlcm9zLCBwb3IgbG8gcXVlIGVzIG3DoXMgZsOhY2lsIHJlbnVuY2lhciBhbCBubyB0ZW5lciB1bmEgZXh0ZW5zYSB5L28gcHJvcGlhIGZhbWlsaWEuIFlhIHF1ZSBsb3Mgc29sdGVyb3Mgc29uIGxhIG1heW9yw61hLCBwb3IgZW5kZSBsb3MgasOzdmVuZXMgc29uIGxvcyBtw6FzIHByb3BlbnNvcw0KZW4gZGFyc2UgZGUgYmFqYSBlbiBGT1JNLiANCg0KIyMgKiozLiBQcmluY2lwYWxlcyBoYWxsYXpnb3MqKg0KDQotIFNpIGJpZW4sIGxhIGVtcHJlc2EgaGFjZSBtZW5jacOzbiBkZSBpbmNlbnRpdm9zIHNhbGFyaWFsZXMgYSBsb3MgY29sYWJvcmFkb3JlcywgbG9zIGRhdG9zIGNhcHR1cmFkb3MgeSBjb21wYXJ0aWRvcyBwb3IgcGFydGUgZGUgbGEgb3JnYW5pemFjacOzbiB1bmljYW1lbnRlIG11ZXN0cmFuIGxvcyBzYWxhcmlvcyBmaWpvcyAoZXMgZGVjaXIsIGluZGVwZW5kaWVudGVtZW50ZSBkZSBob3JhcyBleHRyYSkgeSBwb3IgY29uc2lndWllbnRlLCBzZSBwdWVkZSBjb3JyZWxhY2lvbmFyIHF1ZSBubyBuZWNlc2FyaWFtZW50ZSBsYSBlZGFkIHRpZW5lIHVuYSByZWxhY2nDs24gbyBpbXBhY3RvIGRpcmVjdG8gYWwgbml2ZWwgZGUgc2FsYXJpbyBvdG9yZ2FkbyBhIGxvcyBjb2xhYm9yYWRvcmVzLCBjb24gZXhjZXBjacOzbiBkZSB1bmEgcGVyc29uYTogdHJhdGFuZG9zZSBkZWwgZHVlw7FvL2RpcmVjdG9yLCBxdWllbiBwb3NlZSB1biBzYWxhcmlvIG1heW9yLCBzaWVuZG8gZXN0ZSBtZW5vciBxdWUgbXVjaG9zIGNvbGFib3JhZG9yZXMgcHJlc2VudGVzIGVuIGxhIGVzdHJ1Y3R1cmEgb3JnYW5pemFjaW9uYWwuICANCg0KLSBQcmltZXJhbWVudGUsIHNlIGRlbXVlc3RyYSBxdWUgc2kgYmllbiwgZWwgc2FsYXJpbyBkZSBsb3MgY29sYWJvcmFkb3JlcyBjb3JyZXNwb25kZSBjb3JyZWN0YW1lbnRlIGRlIGFjdWVyZG8gYSBzdSBjb250cmF0bzsgZXN0cmljdGFtZW50ZSByZWZpcmllbmRvc2UgYWwgc2FsYXJpbyBJTVNTLCBubyBzZSBtdWVzdHJhIHVuYSBkaWZlcmVuY2lhIGVuIGxvcyBzYWxhcmlvcyBjb24gbGEgZXhjZXBjacOzbiBkZSB1bmEgcGVyc29uYSBxdWllbiBzZSBpbmZpZXJlIGVzIGVsIGRpcmVjdG9yL2R1ZcOxbyBkZSBsYSBlbXByZXNhIHF1aWVuIGRlYmlkbyBhIHN1IHBvc2ljacOzbiBqZXLDoXJxdWljYSwgZ296YSBkZSBtZWpvciBzYWxhcmlvL2JlbmVmaWNpb3MgZGVsIElNU1MuIA0KDQotIEVudHJlIG3DoXMgasOzdmVuIHNlIGVzLCBtYXlvciBsYSBwcm9iYWJpbGlkYWQgZGUgZGFyc2UgZGUgYmFqYSBkZSBsYSBlbXByZXNhLiAgDQoNCi0gRXhpc3RlbiBncnVwb3MgZGUgZWRhZCwgbG9zIGN1YWxlcyBjb25zdGFuIGRlOiBBZHVsdG9zIGrDs3ZlbmVzLCBBZHVsdG9zLCBBZHVsdG9zIG1heW9yZXMgeSBKdWJpbGFkb3MsIHF1ZSBmb3JtYW4gcGFydGUgZGUgbGEgb3JnYW5pemFjacOzbi4gICAgDQoNCi0gRWwgZ2VuZXJvIGZlbWVuaW5vIHRpZW5lIG1heW9yIHByZXNlbmNpYSBlbiBlbCBncnVwbyBkZSBlZGFkIGRlIGp1YmlsYWRvcyB5IGFkdWx0b3MgbWF5b3JlcywgZW4gY29tcGFyYWNpw7NuIGNvbiBsb3MgZ3J1cG9zIGRlIEFkdWx0b3MgeSBKb3ZlbmVzLCBkb25kZSBzZSB0aWVuZSBtYXlvciBwcmVzZW5jaWEgcG9yIHBhcnRlIGRlbCBnZW5lcm8gbWFzY3VsaW5vLiBDb24gZXN0bywgc2UgcHVlZGUgaW5mZXJpciBjb24gc3VzdGVudG8gcXVlIGxhIHByZXNlbmNpYSBkZSBtdWplcmVzIGVuIGdydXBvcyBkZSBlZGFkIG1hcyBhdmFuemFkYSBlcyBkZWJpZG8gYSBxdWUgc29uIG1hZHJlcyBzb2x0ZXJhcyB5L28gcmVjdXJyZW4gYSBsaW5lYXMgZGUgdHJhYmFqbyBkZSBlc3RlIHRpcG8gcGFyYSBkYXIgc3VzdGVudG8geSBjb250cmlidWlyIGEgbGEgZWNvbm9tw61hIGZhbWlsaWFyLiAgDQoNCi0gRWwgZ3J1cG8gY29uIG3DoXMgYmFqYXMgZW4gdG9kYXMgbGFzIGNhdGVnb3LDrWFzIGRlIGRpY2hhIGFjdGl2aWRhZCBlcyBlbCBkZSBKw7N2ZW5lcywgY29uIGxhIHBlY3VsaWFyaWRhZCBkZSBxdWUgZXhpc3RlbiBwZXJzb25hcyBxdWUgc2ltcGxlbWVudGUgZGVqYW4gZGUgYXNpc3RpciBhIHN1cyBsYWJvcmVzLiAgIA0KDQotIFJlc3BlY3RvIGEgbGFzIGJhamFzIGVuIGZ1bmNpw7NuIGRlIGxvcyBkaWZlcmVudGVzIHB1ZXN0b3MgZXhpc3RlbnRlcyBlbiBsYSBwbGFudGEsIHNlIHB1ZWRlIHN1c3RlbnRhciBxdWUgZG9uZGUgZXhpc3RlbiBtw6FzIGJhamFzIGVzIGVuIGVsIHB1ZXN0byBkZSDigJxBeXVkYW50ZSBnZW5lcmFs4oCdIChyZXByZXNlbnRhIGVsIDc2JSBkZSBsYXMgYmFqYXMgdG90YWxlcykgcG9yIGxvIHF1ZSBzZSBwdWVkZSBpbmZlcmlyIHF1ZSBhbCBzZXIgZWwgcHVlc3RvIGNvbiBtYXlvciBkZW1hbmRhLCB2YWNhbnRlcyBvZnJlY2lkYXMgeSBjb2xhYm9yYWRvcmVzIHF1aWVuZXMgcGFydGljaXBhbiBlbiBkaWNoYSBhcmVhLCB0aWVuZSBzZW50aWRvIHF1ZSBkZXN0YXF1ZW4gbGFzIGJhamFzIGNvbiByZXNwZWN0byBhIGxvcyBvdHJvcyBwdWVzdGFzLiBFbiBvdHJhcyBwYWxhYnJhcywgZWwgbsO6bWVybyBkZSBiYWphcyBlcyBwcm9wb3JjaW9uYWwgYWwgbsO6bWVybyBkZSBjb2xhYm9yYWRvcmVzIHByZXNlbnRlcyBlbiBjYWRhIHB1ZXN0by4gIA0KDQojIyAqKlByb3B1ZXN0YXMqKiANCg0KLSBFbGV2YXIgbml2ZWxlcyBzYWxhcmlhbGVzIHkvbyBwcmVzdGFjaW9uZXMgZGUgYWN1ZXJkbyBhIGxhIGFudGlnw7xlZGFkIHkgZXhwZXJpZW5jaWEgcHJldmlhIGRlbCBjb2xhYm9yYWRvci4gDQoNCi0gRGFkYSBsYSBjb3JyZWxhY2nDs24gZGUgbGEgZWRhZCBqw7N2ZW4geSBsYSBjb25jZW50cmFjacOzbiBkZSBjb2xhYm9yYWRvcmVzIHF1ZSBzZSBkYW4gZGUgYmFqYSwgc2UgcHJvcG9uZSB1biBwcm9ncmFtYSBkZSByZXRlbmNpw7NuIGRlIHRhbGVudG8sIGVsIGN1YWwgZW4gY29uanVudG8gY29uIGFyZWFzIGFmaW5lcyBhIGN1bHR1cmEgb3JnYW5pemFjaW9uYWwgKFJSLkhIKSwgcXVlIHNlIGVuY2FyZ3VlIGRlc2RlIHVuIGluaWNpbyBkZSBhdHJhZXIgZWwgbWVqb3IgdGFsZW50bywgZGVzYXJyb2xsYXJsbywgcmV0ZW5lcmxvIHkgZGFyIHNlZ3VpbWllbnRvIGEgc3Ug4oCcZW1wbG95ZWUgam91cm5leeKAnSBwYXJhIGV2aXRhciBlc2FzIGJhamFzLiAgIA0KDQotIERpc2XDsWFyIHVuIHByb2dyYW1hIGRlIGFwb3lvIGEgbWFkcmVzIHNvbHRlcmFzIHkvbyBjb24gbmVjZXNpZGFkIGVjb27Ds21pY2EsIGRvbmRlIHNlIGRlbiBwcmVzdGFjaW9uZXMgYWRpY2lvbmFsZXMgKG5vIG5lY2VzYXJpYW1lbnRlIGRlIGNvbnRleHRvIHNhbGFyaWFsKSBlbmZvY2FkYXMgaGFjaWEgbG9zIGhpam9zL2FzIGRlIGxhcyBjb2xhYm9yYWRvcmVzIGNvbW8gcG9yIGVqZW1wbG8sIGFwb3lvIGVuIG1hdGVyaWFsIGVzY29sYXIsIGNvbWlkYSBwcmVwYXJhZGEgcGFyYSBsdW5jaGVzLCBlbnRyZSBvdHJhcyBwcmVzdGFjaW9uZXMgcXVlIGNvbnRyaWJ1eWFuIGEgbGEgcmV0ZW5jacOzbiBkZSBsYSBjb2xhYm9yYWRvcmEsIHkgc2UgYXBveWUgYSBsYSBuZWNlc2lkYWQsIHkgcG9yIGNvbnNpZ3VpZW50ZSByYXrDs24gZGUgdHJhYmFqYXIgZW4gRm9ybS4gIA0KDQotIEluc3RhdXJhciB1bmEgcG9sw610aWNhIHkvbyBwcm9jZXNvIGluc3RpdHVjaW9uYWwgZG9uZGUgZWwgY29sYWJvcmFkb3IgZGViYSBpbmRpY2FyIHN1IGJhamEgZGUgbGEgZW1wcmVzYSBjb24gMSDigJMgMiBzZW1hbmFzIGRlIGFudGVsYWNpw7NuLCB5YSBxdWUgZGUgZXN0YSBtYW5lcmEgdGllbmVuIGxhIHBvc2liaWxpZGFkIGRlIHNlciBhY3JlZWRvcmVzIGEgdW5hIGluZGVtbml6YWNpw7NuLCB5IHBvciBvdHJhIHBhcnRlLCBsYSBlbXByZXNhIHB1ZWRlIGNvbWVuemFyIHVuIG51ZXZvIHByb2Nlc28gZGUgYXRyYWNjacOzbiBkZSB0YWxlbnRvIHNpbiBhZmVjdGFyIGxhIHByb2R1Y3RpdmlkYWQgZGUgbGEgcGxhbnRhLiAgDQoNCi0gUHJvZ3JhbWEgZGUgcmV0ZW5jacOzbiBkZSB0YWxlbnRvICMyOiBDb21vIHNlIGVzdGFibGVjacOzIHByZXZpYW1lbnRlLCBlbCBuw7ptZXJvIGRlIGJhamFzIGVzIHByb3BvcmNpb25hbCBhbCBuw7ptZXJvIGRlIGNvbGFib3JhZG9yZXMgcHJlc2VudGVzIGVuIGNhZGEgcHVlc3RvLCBwb3IgbG8gcXVlIGVzcGVjw61maWNhbWVudGUgcGFyYSBlbCBheXVkYW50ZSBnZW5lcmFsLCBkb25kZSBoYXkgbWF5b3IgbsO6bWVybyBkZSBjb2xhYm9yYWRvcmVzLCBlcyBpbXBvcnRhbnRlIG9mcmVjZXIgbWF5b3JlcyBiZW5lZmljaW9zIHBhcmEgZWwgY29sYWJvcmFkb3IsIG1lam9yZXMgY29uZGljaW9uZXMgZGUgdHJhYmFqbywgaW50ZWdyYWNpw7NuIGNvbiBlbCBlcXVpcG8sIGVudHJlIG90cmFzIGFjY2lvbmVzIHF1ZSBhcHVudGVuIGEgbWl0aWdhciBlbiBsbyBwb3NpYmxlLCBsYSBiYWphIGRlIGVzdGFzIHBlcnNvbmFzIGVuIGVzdGUgcHVlc3RvLiAgIA0KDQojICoqU2VjY2nDs24gNCoqDQoNCg0KMS4gRWwgbWVzIGNvbiBtYXMgbWVybWEgcHJvZHVjaWRhIGRlIEZPUk0gZXMgZWwgbWVzIGRlIGFnb3N0bywgYWwgbWlzbW8gdGllbXBvIHF1ZSBlcyBlbCBtZXMgY29uIG1heW9yIHByb2R1Y2Npw7NuIGRlIHBpZXphcw0KDQoyLiAqSnVsaW8gZGVsIDIwMjEqIGVzIGVsIG1lcyBjb24gbWFzIFVuaWRhZGVzIHByb2dyYW1hZGFzIGVuIGVsIGHDsW8uDQoNCjMuIEdyYW4gcGFydGUgZGVsIHNjcmFwIGRlIGZvcm0gc2UgZW5jdWVudHJhIGVuIHN1IHByZS1wcm9kdWNjacOzbg0KDQoNCg0KDQoqKkJpYmxpb2dyYWbDrWEqKg0KRnJvc3QsIEouICgyMDIyLCBBdWd1c3QgMzEpLiBXaGF0IGlzIEsgbWVhbnMgY2x1c3RlcmluZz8gd2l0aCBhbiBleGFtcGxlLiBTdGF0aXN0aWNzIEJ5IEppbS4gUmV0cmlldmVkIE9jdG9iZXIgOSwgMjAyMiwgZnJvbSBodHRwczovL3N0YXRpc3RpY3NieWppbS5jb20vYmFzaWNzL2stbWVhbnMtY2x1c3RlcmluZy8jOn46dGV4dD1UaGUlMjBLJTIwbWVhbnMlMjBjbHVzdGVyaW5nJTIwYWxnb3JpdGhtLGdyb3VwcyUyMHlvdSUyMHNwZWNpZnklMjAoSykuIA0KSGFycmlzb24sIE8uICgyMDE5LCBKdWx5IDE0KS4gTWFjaGluZSBsZWFybmluZyBiYXNpY3Mgd2l0aCB0aGUgSy1uZWFyZXN0IG5laWdoYm9ycyBhbGdvcml0aG0uIE1lZGl1bS4gUmV0cmlldmVkIE9jdG9iZXIgOSwgMjAyMiwgZnJvbSBodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vbWFjaGluZS1sZWFybmluZy1iYXNpY3Mtd2l0aC10aGUtay1uZWFyZXN0LW5laWdoYm9ycy1hbGdvcml0aG0tNmE2ZTcxZDAxNzYxIA0KTWlzaHJhLCBTLiAoMjAxNywgTWF5IDIxKS4gVW5zdXBlcnZpc2VkIGxlYXJuaW5nIGFuZCBkYXRhIGNsdXN0ZXJpbmcuIE1lZGl1bS4gUmV0cmlldmVkIE9jdG9iZXIgOSwgMjAyMiwgZnJvbSBodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdW5zdXBlcnZpc2VkLWxlYXJuaW5nLWFuZC1kYXRhLWNsdXN0ZXJpbmctZWVlY2I3OGI0MjJhIzp+OnRleHQ9Q2x1c3RlcmluZyUyMGNhbiUyMGJlJTIwY29uc2lkZXJlZCUyMHRoZSxhcmUlMjBzaW1pbGFyJTIwaW4lMjBzb21lJTIwd2F5JUUyJTgwJTlELiANCk1vZGlmaWNhdGlvbnMuIGV1Y2xpZGVhbl9jbHVzdGVyLiAobi5kLikuIFJldHJpZXZlZCBPY3RvYmVyIDksIDIwMjIsIGZyb20gaHR0cHM6Ly9hdXRvd2FyZWZvdW5kYXRpb24uZ2l0bGFiLmlvL2F1dG93YXJlLmF1dG8vQXV0b3dhcmVBdXRvL2V1Y2xpZGVhbi1jbHVzdGVyLWRlc2lnbi5odG1sDQoNCg0KDQoNCg==