Recursos Humanos Colaboradores

Importar las bases de datos

# file.choose()
bd <- read.csv( "/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/Reto/FORM - Recursos Humanos - colaboradores.csv")
library(plyr)
# install.packages("dplyr")
library(dplyr)
# install.packages("janitor")
library(janitor)
library(data.table)
library(ggplot2)
library(naniar)
library(Hmisc)         
library(psych)
library(tidyverse)
library(knitr)
# install.packages("pollster")
library(pollster)
library(epiDisplay)
library(descr)
library(tidyr)

colaboradores <- clean_names(bd)
summary(colaboradores)
##   no_empleado  nombre_completo         edad          genero         
##  Min.   :  1   Length:113         Min.   :18.00   Length:113        
##  1st Qu.: 29   Class :character   1st Qu.:26.00   Class :character  
##  Median : 57   Mode  :character   Median :34.00   Mode  :character  
##  Mean   : 57                      Mean   :36.06                     
##  3rd Qu.: 85                      3rd Qu.:45.00                     
##  Max.   :113                      Max.   :73.00                     
##                                                                     
##   fecha_alta          antiguedad        puesto          mano_de_obra      
##  Length:113         Min.   : 0.000   Length:113         Length:113        
##  Class :character   1st Qu.: 0.000   Class :character   Class :character  
##  Mode  :character   Median : 0.000   Mode  :character   Mode  :character  
##                     Mean   : 1.425                                        
##                     3rd Qu.: 2.000                                        
##                     Max.   :12.000                                        
##                                                                           
##  salario_diario  estado_civil      
##  Min.   :144.4   Length:113        
##  1st Qu.:176.7   Class :character  
##  Median :180.7   Mode  :character  
##  Mean   :179.1                     
##  3rd Qu.:180.7                     
##  Max.   :337.1                     
##  NA's   :2

Limpieza, Transformación, y Organización de Bases de Datos

¿Cuántas variables y cuantos registros tiene la base de datos?

describeData(colaboradores,head=1,tail=1)
## n.obs =  113 of which  111   are complete cases.   Number of variables =  10  of which all are numeric  FALSE  
##                  variable # n.obs type                        H1
## no_empleado               1   113    1                         1
## nombre_completo*          2   113    3 NICOLAS MARTINEZ DE LOERA
## edad                      3   113    1                        67
## genero*                   4   113    3                 MASCULINO
## fecha_alta*               5   113    3                01/07/2010
## antiguedad                6   113    1                        12
## puesto*                   7   113    3     SUPERVISOR DE MAQUINA
## mano_de_obra*             8   113    3                 Indirecto
## salario_diario            9   111    1                    176.72
## estado_civil*            10   113    3                   Soltero
##                                    T1
## no_empleado                       113
## nombre_completo* SOFIA VAZQUEZ GAYTAN
## edad                               50
## genero*                      FEMENINO
## fecha_alta*                23/08/2022
## antiguedad                          0
## puesto*              AYUDANTE GENERAL
## mano_de_obra*                 Directo
## salario_diario                 180.68
## estado_civil*                  Casado
Existen 10 variables y 113 registros en la base de datos.

Aplica técnicas de limpieza de bases de datos y explícalas brevemente, ¿por qué realizaste esas técnicas?

Técnica 1. Borrar columnas.

colaboradores <- subset(colaboradores, select = -c(no_empleado, nombre_completo, fecha_alta, mano_de_obra))
Esta técnica se realizó ya que no se consideraron importantes las columnas de variables.

Técnica 2. Reemplezar NAs con el promedio en la columna de “Salario Diario”

colaboradores$salario_diario[is.na(colaboradores$salario_diario)]<-mean(colaboradores$salario_diario, na.rm = TRUE)
summary (colaboradores)
##       edad          genero            antiguedad        puesto         
##  Min.   :18.00   Length:113         Min.   : 0.000   Length:113        
##  1st Qu.:26.00   Class :character   1st Qu.: 0.000   Class :character  
##  Median :34.00   Mode  :character   Median : 0.000   Mode  :character  
##  Mean   :36.06                      Mean   : 1.425                     
##  3rd Qu.:45.00                      3rd Qu.: 2.000                     
##  Max.   :73.00                      Max.   :12.000                     
##  salario_diario  estado_civil      
##  Min.   :144.4   Length:113        
##  1st Qu.:176.7   Class :character  
##  Median :180.7   Mode  :character  
##  Mean   :179.1                     
##  3rd Qu.:180.7                     
##  Max.   :337.1
Al reemplazar los NA ’s con el promedio nos ayuda para no contar con registros nulos y contar con los valores más acertados posibles al tiempo de analizarlos.

Exportar base de datos limpia

write.csv(colaboradores, file="colaboradores_bd_limpia.csv", row.names = FALSE)

Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua

Elige la escala de medición de cada variable.

Variable <-c("Edad","Genero", "Antiguedad","Puesto", "Salario Diario", "Estado Civil")
Type<-c("quantitative (discreta)", "qualitative", "quantitative (discreta)","qualitative", "quantitative (continua)", "qualitative")
Measurement<-c("Años","NA","Meses trabajados","NA", "Cantidad de dinero","NA")
table<-data.frame(Variable,Type,Measurement)
knitr::kable(table)
Variable Type Measurement
Edad quantitative (discreta) Años
Genero qualitative NA
Antiguedad quantitative (discreta) Meses trabajados
Puesto qualitative NA
Salario Diario quantitative (continua) Cantidad de dinero
Estado Civil qualitative NA

Análisis Exploratorio de las Bases de Datos

Análisis Estadístico

Media

media_edad <- mean(colaboradores$edad)
media_edad
## [1] 36.06195
media_antiguedad <- mean(colaboradores$antiguedad)
media_antiguedad
## [1] 1.424779
media_salario <- mean(colaboradores$salario_diario)
media_salario
## [1] 179.0981

Mediana

mediana_edad <- median(colaboradores$edad)
mediana_edad
## [1] 34
mediana_antiguedad <- median(colaboradores$antiguedad)
mediana_antiguedad
## [1] 0
mediana_salario <- median(colaboradores$salario_diario)
mediana_salario 
## [1] 180.68

Moda

mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}
moda_edad <- mode(colaboradores$edad)
moda_edad
## [1] 32
moda_antiguedad <- mode(colaboradores$antiguedad)
moda_antiguedad
## [1] 0
moda_salario <- mode(colaboradores$salario_diario)
moda_salario 
## [1] 180.68

Varianza

varianza_edad <-var(colaboradores$edad)
varianza_edad
## [1] 165.0051
varianza_antiguedad <-var(colaboradores$antiguedad)
varianza_antiguedad
## [1] 6.353666
varianza_salario <-var(colaboradores$salario_diario)
varianza_salario
## [1] 589.7227

Desviación Estándar

desviacion_edad <- sqrt(varianza_edad)
desviacion_edad
## [1] 12.84543
desviacion_antiguedad <- sqrt(varianza_antiguedad)
desviacion_antiguedad
## [1] 2.520648
desviacion_salario <- sqrt(varianza_salario)
desviacion_salario
## [1] 24.28421

Tabla

Variable <-c("Edad","Antiguedad","Salario Diario")
Promedio <-c("36", "1.42","179.098")
Moda <-c("32","0","180.68")
Mediana <-c("34","0","180.68")
Varianza <-c("165.005","6.353","589.722")
Desviación_Estándar <-c ("12.845","2.520","24.284")
tabla1 <-data.frame(Variable,Promedio, Moda, Mediana, Varianza, Desviación_Estándar)
tabla1
##         Variable Promedio   Moda Mediana Varianza Desviación_Estándar
## 1           Edad       36     32      34  165.005              12.845
## 2     Antiguedad     1.42      0       0    6.353               2.520
## 3 Salario Diario  179.098 180.68  180.68  589.722              24.284
knitr::kable(tabla1)
Variable Promedio Moda Mediana Varianza Desviación_Estándar
Edad 36 32 34 165.005 12.845
Antiguedad 1.42 0 0 6.353 2.520
Salario Diario 179.098 180.68 180.68 589.722 24.284

Gráfico cuantitativo: (Histograma):

Sueldo <-  colaboradores$salario_diario   
hist(Sueldo, main = "Sueldo de los empleados", ylab = "# de empleados", col = "lightblue")

En esta gráfica podemos observar fácilmente como la mayor parte de los empleados ganan menos de 200 MXN pesos al día.

Bar Plots

hist(colaboradores$edad, freq=TRUE, col="purple", main="Edad en años de los Colaboradores actuales")

Con estas gràfica podemos observar que los colaboradores actuales en promedio tienen entre 20-40 años.
ggplot(colaboradores, aes(x=genero, y=salario_diario, fill=genero)) + 
  geom_bar(stat="identity") + 
  facet_grid(~estado_civil) + scale_fill_brewer(palette = "Set2")

Con este gràfico podemos observar que los que estan casados y solteros suelen ganar màs de los que estan divorciados y en uniòn libre. Ademàs, los hombres casados y las mujeres solteras son los que ganan màs.

Dispersion plot

ggplot(data=colaboradores, mapping = aes(edad, salario_diario)) + geom_point(aes(color = genero)) + theme_bw()

Con estas gràficas podemos observar que el colaborador que gana màs es mujer y las que ganan menos tambièn. Sin embargo, el promedio de salario ganado por los colaboradores de todas las edades es de aproximadamente 170 pesos diarios.

Recursos Humanos Bajas

Importar las bases de datos

# file.choose()
bajas <- read.csv("/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/FORM - Recursos Humanos - BAJAS evidencia).csv")
bajas <- clean_names(bajas)
summary(bajas)
##   apellidos            nombre          fecha_de_nacimiento      edad      
##  Length:237         Length:237         Length:237          Min.   :19.00  
##  Class :character   Class :character   Class :character    1st Qu.:23.00  
##  Mode  :character   Mode  :character   Mode  :character    Median :29.00  
##                                                            Mean   :31.09  
##                                                            3rd Qu.:37.00  
##                                                            Max.   :61.00  
##                                                            NA's   :3      
##     genero              rfc            fecha_de_alta      motivo_de_baja    
##  Length:237         Length:237         Length:237         Length:237        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##     no_dias            baja              puesto          departamento      
##  Min.   :   0.00   Length:237         Length:237         Length:237        
##  1st Qu.:   9.00   Class :character   Class :character   Class :character  
##  Median :  19.00   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :  79.47                                                           
##  3rd Qu.:  48.75                                                           
##  Max.   :1966.00                                                           
##  NA's   :23                                                                
##  no_seguro_social   salario_diario_imss factor_cred_infonavit
##  Length:237         Min.   :144.4       Length:237           
##  Class :character   1st Qu.:180.7       Class :character     
##  Mode  :character   Median :180.7       Mode  :character     
##                     Mean   :178.0                            
##                     3rd Qu.:180.7                            
##                     Max.   :500.0                            
##                     NA's   :1                                
##  n_credito_infonavit lugar_de_nacimiento     curp              calle          
##  Length:237          Length:237          Length:237         Length:237        
##  Class :character    Class :character    Class :character   Class :character  
##  Mode  :character    Mode  :character    Mode  :character   Mode  :character  
##                                                                               
##                                                                               
##                                                                               
##                                                                               
##  numero_interno       colonia          codigo_postal       municipio        
##  Length:237         Length:237         Length:237         Length:237        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##     estado          estado_civil       tarjeta_cuenta    
##  Length:237         Length:237         Length:237        
##  Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character  
##                                                          
##                                                          
##                                                          
## 

Limpieza, Transformación, y Organización de Bases de Datos

¿Cuántas variables y cuantos registros tiene la base de datos?

describeData(bajas,head=1,tail=1)
## n.obs =  237 of which  210   are complete cases.   Number of variables =  26  of which all are numeric  FALSE  
##                        variable # n.obs type                   H1
## apellidos*                      1   237    3         VALDEZ ORTIZ
## nombre*                         2   237    3                MARIO
## fecha_de_nacimiento*            3   237    3             24/06/90
## edad                            4   234    1                   32
## genero*                         5   237    3            MASCULINO
## rfc*                            6   237    3        VAOM900624HG8
## fecha_de_alta*                  7   237    3             09/03/20
## motivo_de_baja*                 8   237    3  RENUNCIA VOLUNTARIA
## no_dias                         9   214    1                  628
## baja*                          10   237    3             27/11/21
## puesto*                        11   237    3               DISEÑO
## departamento*                  12   237    3       ADMINISTRATIVO
## no_seguro_social*              13   237    3          43139026090
## salario_diario_imss            14   236    1                  500
## factor_cred_infonavit*         15   237    3                  N/A
## n_credito_infonavit*           16   237    3                  N/A
## lugar_de_nacimiento*           17   237    3  AVENIDA DEL COLEGIO
## curp*                          18   237    3   VAOM900624HCLLRR09
## calle*                         19   237    3           LAS FLORES
## numero_interno*                20   237    3                66438
## colonia*                       21   237    3 SAN NICOLAS DE LOS G
## codigo_postal*                 22   237    3                66438
## municipio*                     23   237    3 SAN NICOLAS DE LOS G
## estado*                        24   237    3           Nuevo León
## estado_civil*                  25   237    3              SOLTERO
## tarjeta_cuenta*                26   237    3              BANORTE
##                                                          T1
## apellidos*                                    MUÑOZ BOLAÑOS
## nombre*                                    LIZETH GUADALUPE
## fecha_de_nacimiento*                               30/09/99
## edad                                                     23
## genero*                                            FEMENINO
## rfc*                                          MUBL9909302Z9
## fecha_de_alta*                                     12/08/22
## motivo_de_baja*                             BAJA POR FALTAS
## no_dias                                                   6
## baja*                                              18/08/22
## puesto*                                    AYUDANTE GENERAL
## departamento*                                              
## no_seguro_social*                               17159986540
## salario_diario_imss                                  180.68
## factor_cred_infonavit*                                  N/A
## n_credito_infonavit*                                    N/A
## lugar_de_nacimiento*   SAN NICOLAS DE LOS GARZA, NUEVO LEON
## curp*                                    MUBL990930MNLXLZ09
## calle*                                            RIO CAURA
## numero_interno*                                         629
## colonia*                                         SAN ISIDRO
## codigo_postal*                                      APODACA
## municipio*                                       NUEVO LEON
## estado*                                               66646
## estado_civil*                                   UNION LIBRE
## tarjeta_cuenta*                                     BANORTE
Existen 26 variables y 327 registros en la base de datos.

Aplica técnicas de limpieza de bases de datos y explícalas brevemente, ¿por qué realizaste esas técnicas?

Técnica 1.Borrar columnas.

bajas <- subset(bajas, 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_cuenta))
Esta técnica se realizó ya que no se consideraron importantes las columnas de variables.

Técnica 2. Convertir las variables como factor o numero

bajas$edad<-as.numeric(bajas$edad)
bajas$genero<-as.factor(bajas$genero)
bajas$motivo_de_baja<-as.factor(bajas$motivo_de_baja)
bajas$no_dias<-as.numeric(bajas$no_dias)
bajas$puesto<-as.factor(bajas$puesto)
bajas$salario_diario_imss<-as.numeric(bajas$salario_diario_imss)
bajas$estado_civil<-as.factor(bajas$estado_civil)
summary (bajas)
##       edad                 genero                motivo_de_baja
##  Min.   :19.00   CAPJ000926597:  1   ABANDONO           :  1   
##  1st Qu.:23.00   FEMENINO     :139   BAJA POR FALTAS    :141   
##  Median :29.00   MASCULINO    : 97   JUBILACION         :  1   
##  Mean   :31.09                       RENUNCIA VOLUNTARIA: 86   
##  3rd Qu.:37.00                       TERMINO DE CONTRATO:  8   
##  Max.   :61.00                                                 
##  NA's   :3                                                     
##     no_dias                          puesto    salario_diario_imss
##  Min.   :   0.00   AYUDANTE GENERAL     :179   Min.   :144.4      
##  1st Qu.:   9.00   COSTURERA            : 11   1st Qu.:180.7      
##  Median :  19.00   SOLDADOR             : 11   Median :180.7      
##  Mean   :  79.47   AYUDANTE DE EMBARQUES:  7   Mean   :178.0      
##  3rd Qu.:  48.75   MONTACARGUISTA       :  5   3rd Qu.:180.7      
##  Max.   :1966.00   INSPECTOR CALIDAD    :  4   Max.   :500.0      
##  NA's   :23        (Other)              : 20   NA's   :1          
##       estado_civil
##             :  2  
##  CASADO     : 64  
##  DIVORCIADO :  3  
##  SOLTERO    :108  
##  UNION LIBRE: 60  
##                   
## 
En esta técnica de limpieza se vuelven a factor o números las variables para generar un estandarizar y generar un formato para que se vuelva más sencillo al realizar gráficos y manipular datos.

Técnica 3. Reemplezar NAs con el promedio en la columna de “Edad”, “Salario Diario” y “Número de días”

bajas$edad[is.na(bajas$edad)]<-mean(bajas$edad, na.rm = TRUE)
bajas$salario_diario_imss[is.na(bajas$salario_diario_imss)]<-mean(bajas$salario_diario_imss, na.rm = TRUE)
bajas$no_dias[is.na(bajas$no_dias)]<-mean(bajas$no_dias, na.rm = TRUE)
summary (bajas)
##       edad                 genero                motivo_de_baja
##  Min.   :19.00   CAPJ000926597:  1   ABANDONO           :  1   
##  1st Qu.:23.00   FEMENINO     :139   BAJA POR FALTAS    :141   
##  Median :29.00   MASCULINO    : 97   JUBILACION         :  1   
##  Mean   :31.09                       RENUNCIA VOLUNTARIA: 86   
##  3rd Qu.:37.00                       TERMINO DE CONTRATO:  8   
##  Max.   :61.00                                                 
##                                                                
##     no_dias                          puesto    salario_diario_imss
##  Min.   :   0.00   AYUDANTE GENERAL     :179   Min.   :144.4      
##  1st Qu.:   9.00   COSTURERA            : 11   1st Qu.:180.7      
##  Median :  23.00   SOLDADOR             : 11   Median :180.7      
##  Mean   :  79.47   AYUDANTE DE EMBARQUES:  7   Mean   :178.0      
##  3rd Qu.:  79.47   MONTACARGUISTA       :  5   3rd Qu.:180.7      
##  Max.   :1966.00   INSPECTOR CALIDAD    :  4   Max.   :500.0      
##                    (Other)              : 20                      
##       estado_civil
##             :  2  
##  CASADO     : 64  
##  DIVORCIADO :  3  
##  SOLTERO    :108  
##  UNION LIBRE: 60  
##                   
## 
Al reemplazar los NA ’s con el promedio nos ayuda para no contar con registros nulos y contar con los valores más acertados posibles al tiempo de analizarlos.

Exportar base de datos limpia

write.csv(bajas, file="rh_bajas_bd_limpia.csv", row.names = FALSE)

Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua

Elige la escala de medición de cada variable.

Variable_rhb <-c("Edad","Genero", "motivo_de baja", "no_dias", "Puesto", "Salario Diario", "Estado Civil")
Type_rhb <-c( "quantitative (discreta)", "qualitative","qualitative", "quantitative (discreta)","qualitative", "quantitative (continua)", "qualitative")
Measurement_rhb <-c("Años","NA", "NA", "Dias trabajados","NA", "Cantidad de dinero","NA")
table_rhb <-data.frame(Variable_rhb ,Type_rhb ,Measurement_rhb )
knitr::kable(table_rhb)
Variable_rhb Type_rhb Measurement_rhb
Edad quantitative (discreta) Años
Genero qualitative NA
motivo_de baja qualitative NA
no_dias quantitative (discreta) Dias trabajados
Puesto qualitative NA
Salario Diario quantitative (continua) Cantidad de dinero
Estado Civil qualitative NA

Análisis Exploratorio de las Bases de Datos

Análisis Estadístico

Media

media_edad1 <- mean(bajas$edad)
media_edad1
## [1] 31.08974
media_antiguedad1 <- mean(bajas$no_dias)
media_antiguedad1
## [1] 79.47196
media_salario1 <- mean(bajas$salario_diario)
media_salario1
## [1] 177.9627

Mediana

mediana_edad1 <- median(bajas$edad)
mediana_edad1
## [1] 29
mediana_antiguedad1 <- median(bajas$no_dias)
mediana_antiguedad1
## [1] 23
mediana_salario1 <- median(bajas$salario_diario)
mediana_salario1
## [1] 180.68

Moda

mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}
moda_edad1 <- mode(bajas$edad)
moda_edad1
## [1] 22
moda_antiguedad1 <- mode(bajas$no_dias)
moda_antiguedad1
## [1] 79.47196
moda_salario1 <- mode(bajas$salario_diario)
moda_salario1 
## [1] 180.68

Varianza

varianza_edad1 <-var(bajas$edad)
varianza_edad1
## [1] 91.5132
varianza_antiguedad1 <-var(bajas$no_dias)
varianza_antiguedad1
## [1] 45479.59
varianza_salario1 <-var(bajas$salario_diario)
varianza_salario1
## [1] 538.6969

Desviación Estándar

desviacion_edad1 <- sqrt(varianza_edad1)
desviacion_edad1
## [1] 9.566253
desviacion_antiguedad1 <- sqrt(varianza_antiguedad1)
desviacion_antiguedad1
## [1] 213.2594
desviacion_salario1 <- sqrt(varianza_salario1)
desviacion_salario1
## [1] 23.20985

Tabla

Variable_rhb1 <-c("Edad","Antiguedad","Salario Diario")
Promedio_rhb1 <-c("31.05","79.47","177.985")
Moda_rhb1 <-c("22","79","180.68")
Mediana_rhb1 <-c("29","23","180.68")
Varianza_rhb1 <-c("91.513","45479.59","538.6969")
Desviación_Estándar_rhb1 <-c ("9.566","213.2594","23.20")
tabla_rhb1 <-data.frame (Variable_rhb1,Promedio_rhb1,Moda_rhb1, Mediana_rhb1, Varianza_rhb1,Desviación_Estándar_rhb1 )
tabla_rhb1
##    Variable_rhb1 Promedio_rhb1 Moda_rhb1 Mediana_rhb1 Varianza_rhb1
## 1           Edad         31.05        22           29        91.513
## 2     Antiguedad         79.47        79           23      45479.59
## 3 Salario Diario       177.985    180.68       180.68      538.6969
##   Desviación_Estándar_rhb1
## 1                    9.566
## 2                 213.2594
## 3                    23.20
knitr::kable(tabla_rhb1)
Variable_rhb1 Promedio_rhb1 Moda_rhb1 Mediana_rhb1 Varianza_rhb1 Desviación_Estándar_rhb1
Edad 31.05 22 29 91.513 9.566
Antiguedad 79.47 79 23 45479.59 213.2594
Salario Diario 177.985 180.68 180.68 538.6969 23.20

Gráfico cualitativo

table(bajas$motivo_baja)
## < table of extent 0 >
proporciones <- c(1, 141, 1, 87, 8)
etiquetas <- c("Abandono", "Baja por Faltas", "Jubilaciòn", "Renuncia Voluntaria", "Termino de Contrato")
pct <- round(proporciones/sum(proporciones)*100)
etiquetas <- paste(etiquetas, pct)
etiquetas <- paste(etiquetas,"%",sep="")
pie(proporciones,labels = etiquetas,
    col=rainbow(length(etiquetas)),
    main="Motivo de bajas de los Colaboradores")

Con esta gràfica podemos observar que el motivo màs comùn de baja de los colaboradores han sido por despidos por faltas con un 59% y por renuncia voluntaria por un 37%.

Bar Plots

hist(bajas$edad, freq=TRUE, col="pink", main="Edad en años de los Ex-Colaboradores")

Los colaboradores que se han dado de baja en su mayoria tienen entre 20 y 30 años, siendo asì los que se van màs jòvenes.

Delivery Plan

Importar las bases de datos

library(data.table)
library(dplyr)
library(plyr)
library(ggplot2)
library(naniar)
library(Hmisc)         
library(psych)
library(tidyverse)
library(janitor)
library(knitr)
library(pollster)
library(epiDisplay)
library(descr)
library(tidyr)
library(ggeasy)
library(stringr)
library(patchwork)

# file.choose()
delivery_plan<- read.csv("/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/Delivery Plan FINAL - EQUIPO 4 .csv")

Limpieza, Transformación, y Organización de Bases de Datos

¿Cuántas variables y cuantos registros tiene la base de datos?

describeData(delivery_plan,head=1,tail=1)
## n.obs =  231 of which  231   are complete cases.   Number of variables =  27  of which all are numeric  FALSE  
##                 variable # n.obs type                                H1
## CLIENTE.PLANTA*          1   231    3                              STB3
## PROYECTO*                2   231    3                   CANASTILLA GRIS
## ID.ODOO*                 3   231    3                            15.785
## ITEM*                    4   231    3 CABLE SET CAJA BACK UP CANASTILLA
## JUNIO                    5   231    1                                 0
## JULIO                    6   231    1                               140
## AGOSTO                   7   231    1                               530
## SEPTIEMBRE               8   231    1                                 0
## OCTUBRE                  9   231    1                               200
## NOVIEMBRE               10   231    1                                 0
## DICIEMBRE               11   231    1                               150
## ene.22                  12   231    1                               230
## feb.22                  13   231    1                               500
## mar.22                  14   231    1                                 0
## abr.22                  15   231    1                                 0
## may.22                  16   231    1                                 0
## jun.22                  17   231    1                               200
## jul.22                  18   231    1                               900
## ago.22                  19   231    1                              1000
## sep.22                  20   231    1                                 0
## OCTUBRE.22              21   231    1                                 0
## nov.22                  22   231    1                                 0
## dic.22                  23   231    1                                 0
## ene.23                  24   231    1                                 0
## feb.23                  25   231    1                                 0
## mar.23                  26   231    1                                 0
## TOTAL.MESES             27   231    1                              3850
##                       T1
## CLIENTE.PLANTA*   VARROC
## PROYECTO*        CURRENT
## ID.ODOO*                
## ITEM*           U553 KIT
## JUNIO                  0
## JULIO                  0
## AGOSTO                 0
## SEPTIEMBRE             0
## OCTUBRE               30
## NOVIEMBRE            200
## DICIEMBRE              0
## ene.22                 0
## feb.22                 0
## mar.22                 0
## abr.22                 0
## may.22                 0
## jun.22                 0
## jul.22                 0
## ago.22                 0
## sep.22                 0
## OCTUBRE.22             0
## nov.22                 0
## dic.22                 0
## ene.23                 0
## feb.23                 0
## mar.23                 0
## TOTAL.MESES          230
La base de datos cuenta con 27 variables y 231 registros.

Aplica técnicas de limpieza de bases de datos y explícalas brevemente, ¿por qué realizaste esas técnicas?

Técnica 1. Acondicionar nombres a formato óptimo para R

delivery_plan <- clean_names(delivery_plan)
Se optimizan las variables para R, generando un estándar.

Técnica 2. Unir los pedidos programados en una sola columna.

delivery_plan <- delivery_plan %>% dplyr::rename(cliente=cliente_planta,
                             A_jun_21=junio,
                             B_jul_21=julio,
                             C_ago_21=agosto,
                             D_sep_21=septiembre,
                             E_oct_21=octubre,
                             F_nov_21=noviembre,
                             G_dic_21=diciembre,
                             H_ene_22=ene_22,
                             I_feb_22=feb_22,
                            J_mar_22=mar_22,
                            K_abr_22=abr_22,
                            L_may_22=may_22,
                            M_jun_22=jun_22,
                            N_jul_22=jul_22,
                            O_ago_22=ago_22,
                            P_sep_22=sep_22,
                            Q_oct_22=octubre_22,
                            R_nov_22=nov_22,
                            S_dic_22=dic_22,
                            T_ene_23=ene_23,
                            U_feb_23=feb_23,
                            V_mar_23=feb_23
                          
                           )
colnames(delivery_plan)
##  [1] "cliente"     "proyecto"    "id_odoo"     "item"        "A_jun_21"   
##  [6] "B_jul_21"    "C_ago_21"    "D_sep_21"    "E_oct_21"    "F_nov_21"   
## [11] "G_dic_21"    "H_ene_22"    "I_feb_22"    "J_mar_22"    "K_abr_22"   
## [16] "L_may_22"    "M_jun_22"    "N_jul_22"    "O_ago_22"    "P_sep_22"   
## [21] "Q_oct_22"    "R_nov_22"    "S_dic_22"    "T_ene_23"    "V_mar_23"   
## [26] "mar_23"      "total_meses"
delivery_plan <- pivot_longer(delivery_plan, cols=5:14, names_to = "Mes", values_to = "Unidades")
En este caso se decidió unir todos los pedidos en una columna para generar un orden de los meses y cerrar una base de datos estructurada.

Técnica 3.Eliminación de NA’s

deliveryplan1 <- filter(delivery_plan, Unidades>0)
Se eliminan los NA’s en la base de datos para eliminar rengoles/clientes sin registros.

Técnica 4.Eliminación de variables irrelevantes.

deliveryplan2 <- deliveryplan1         
deliveryplan2 <- subset (deliveryplan1, 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, V_mar_23, mar_23, total_meses))
summary(deliveryplan2)
##    cliente              Mes               Unidades      
##  Length:590         Length:590         Min.   :    1.0  
##  Class :character   Class :character   1st Qu.:   30.0  
##  Mode  :character   Mode  :character   Median :   80.0  
##                                        Mean   :  358.4  
##                                        3rd Qu.:  300.0  
##                                        Max.   :13120.0
En este caso, dado que previamente se unieron (merge) las variables de mes, solo se considera necesaria la variables de cliente, fecha y Unidades.

Exportar base de datos limpia

Delivery_Plan <- deliveryplan2
write.csv(Delivery_Plan, file = "Ddeliveryplan_bd_limpia.csv", row.names = FALSE)

Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua

Elige la escala de medición de cada variable.

Variable_dplan<-c("Unidades", "Mes", "cliente")
Type_dplan <-c("quantitative (discreta)", "qualitative","qualitative")
Measurement_dplan <-c("piezas que se entregan", "NA", "NA")
table_dplan <-data.frame(Variable_dplan,Type_dplan,Measurement_dplan)
knitr::kable(table_dplan)
Variable_dplan Type_dplan Measurement_dplan
Unidades quantitative (discreta) piezas que se entregan
Mes qualitative NA
cliente qualitative NA

Análisis Exploratorio de las Bases de Datos

Análisis Estadístico

Media

Media <- mean(deliveryplan2$Unidades)
Media
## [1] 358.3729

Mediana

Mediana <- median(deliveryplan2$Unidades)
Mediana
## [1] 80

Moda

mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}

Moda_clientes <- mode(deliveryplan2$cliente)  
Moda_clientes
## [1] "VARROC"
Moda_mes <- mode(deliveryplan2$Mes)  
Moda_mes
## [1] "H_ene_22"
Moda_unidades <- mode(deliveryplan2$Unidades)  
Moda_unidades
## [1] 60

Varianza

varianza_unidades_prog <- var(deliveryplan2$Unidades)
varianza_unidades_prog
## [1] 1005677

Desviación Estándar

desviacion_unidades_prog<- sqrt(varianza_unidades_prog)
desviacion_unidades_prog
## [1] 1002.834

Tabla

Variable_dplan<-c("Unidades", "Mes", "cliente")
Media_dplan<-c("358.3729", "NA", "NA")
Mediana_dplan<-c("80", "NA", "NA")
Moda_dplan<-c(Moda_unidades, Moda_mes, Moda_clientes)
Varianza_dplan<-c("1005677", "NA", "NA")
Desviacion_Estandar_dplan<-c("1002.834", "NA", "NA")
table_dplan <- data.frame(Variable_dplan, Media_dplan, Mediana_dplan, Moda_dplan,Varianza_dplan, Desviacion_Estandar_dplan)
knitr::kable(table_dplan)
Variable_dplan Media_dplan Mediana_dplan Moda_dplan Varianza_dplan Desviacion_Estandar_dplan
Unidades 358.3729 80 60 1005677 1002.834
Mes NA NA H_ene_22 NA NA
cliente NA NA VARROC NA NA

Dispersion plots

ggplot(deliveryplan2, aes(x = Mes, y = Unidades)) + 
  geom_point(shape=19, size=3) + 
  labs(title = "Relación entre Unidades y Meses",caption ="FORM Merma",x="Mes", y="Unidades") + 
  theme_classic()

Gráfica de los años 2021 y 2022 estableciendo cuantas unidades se vendieron por mes, podemos ver que en Junio 2021 tuvieron un aumento disminuyendo en los proximos meses y volvio a subir en el año 2022 Esta gráfica nos ayuda ver la relacion que tienen las unidades y los meses de año, para asi poder encontrar patrones en la base de datos para ver en que meses se hacen mas pedidos.

Bar Plots

ggplot(deliveryplan2,aes(x= Unidades, y=Mes,fill=cliente)) +
  geom_bar(stat="identity")

En gráfica agregando que se observan las unidades planeadas por entregar, se observa de una manera más clara las entregas por cliente. Donde se observa que Hella es el cliente con mayor entrega de pedidos en FORM.

Delivery Performance

Importar las bases de datos

# file.choose()
deliveryperf <- read.csv("/Users/mayracampoyramos/Downloads/FORM - Delivery Performance BD BUENA.csv")
library(dplyr)
library(janitor)
performance <- clean_names(deliveryperf)
summary(performance)
##     fecha              printel           mahle             magna   
##  Length:324         Min.   :0.0000   Min.   :-11.650   Min.   :0   
##  Class :character   1st Qu.:0.0000   1st Qu.:  1.800   1st Qu.:0   
##  Mode  :character   Median :0.0000   Median :  3.000   Median :0   
##                     Mean   :0.4418   Mean   :  2.364   Mean   :0   
##                     3rd Qu.:1.0000   3rd Qu.:  3.150   3rd Qu.:0   
##                     Max.   :4.4000   Max.   : 20.000   Max.   :0   
##                     NA's   :25       NA's   :25        NA's   :25  
##      varroc      x             x_1            x_2            x_3         
##  Min.   :0    Mode:logical   Mode:logical   Mode:logical   Mode:logical  
##  1st Qu.:0    NA's:324       NA's:324       NA's:324       NA's:324      
##  Median :0                                                               
##  Mean   :0                                                               
##  3rd Qu.:0                                                               
##  Max.   :0                                                               
##  NA's   :25

Limpieza, Transformación, y Organización de Bases de Datos

¿Cuántas variables y cuantos registros tiene la base de datos?

describeData(performance,head=1,tail=1)
## n.obs =  324 of which  0   are complete cases.   Number of variables =  9  of which all are numeric  FALSE  
##         variable # n.obs type         H1   T1
## fecha*           1   324    3 22/07/2021     
## printel          2   299    1          0 <NA>
## mahle            3   299    1       2.65 <NA>
## magna            4   299    1          0 <NA>
## varroc           5   299    1          0 <NA>
## x*               6     0    2       <NA> <NA>
## x_1*             7     0    2       <NA> <NA>
## x_2*             8     0    2       <NA> <NA>
## x_3*             9     0    2       <NA> <NA>

La base de datos cuenta con 9 variables y 324 registros

Aplica técnicas de limpieza de bases de datos y explícalas brevemente, ¿por qué realizaste esas técnicas?

Técnica 1.Borrar columnas.

performance <- subset(performance, select = -c(x, x_1, x_2, x_3))
summary(performance)
##     fecha              printel           mahle             magna   
##  Length:324         Min.   :0.0000   Min.   :-11.650   Min.   :0   
##  Class :character   1st Qu.:0.0000   1st Qu.:  1.800   1st Qu.:0   
##  Mode  :character   Median :0.0000   Median :  3.000   Median :0   
##                     Mean   :0.4418   Mean   :  2.364   Mean   :0   
##                     3rd Qu.:1.0000   3rd Qu.:  3.150   3rd Qu.:0   
##                     Max.   :4.4000   Max.   : 20.000   Max.   :0   
##                     NA's   :25       NA's   :25        NA's   :25  
##      varroc  
##  Min.   :0   
##  1st Qu.:0   
##  Median :0   
##  Mean   :0   
##  3rd Qu.:0   
##  Max.   :0   
##  NA's   :25
Esta técnica se realizó ya que no se consideraron importantes las columnas de variables.

Técnica 2.Convertir de caracter a fecha

performance$fecha <- as.Date(performance$fecha, format = "%d/%m/%Y")
tibble(performance)
## # A tibble: 324 × 5
##    fecha      printel mahle magna varroc
##    <date>       <dbl> <dbl> <dbl>  <dbl>
##  1 2021-07-22     0    2.65     0      0
##  2 2021-07-25     1.8  2.85     0      0
##  3 2021-07-26     1.1  2.5      0      0
##  4 2021-07-27     0.5  2.5      0      0
##  5 2021-07-28     0.5  2.55     0      0
##  6 2021-07-29     1    2.65     0      0
##  7 2021-08-01     1    2.51     0      0
##  8 2021-08-02     1    3        0      0
##  9 2021-08-03     0    3        0      0
## 10 2021-08-04     1.2  3.05     0      0
## # … with 314 more rows

Técnica 3.Convertir de caracter a entero

performance$printel <- substr(performance$printel, start = 1, stop = 2)
tibble(performance)
## # A tibble: 324 × 5
##    fecha      printel mahle magna varroc
##    <date>     <chr>   <dbl> <dbl>  <dbl>
##  1 2021-07-22 0        2.65     0      0
##  2 2021-07-25 1.       2.85     0      0
##  3 2021-07-26 1.       2.5      0      0
##  4 2021-07-27 0.       2.5      0      0
##  5 2021-07-28 0.       2.55     0      0
##  6 2021-07-29 1        2.65     0      0
##  7 2021-08-01 1        2.51     0      0
##  8 2021-08-02 1        3        0      0
##  9 2021-08-03 0        3        0      0
## 10 2021-08-04 1.       3.05     0      0
## # … with 314 more rows
performance$printel <- as.numeric(performance$printel)
str(performance)
## 'data.frame':    324 obs. of  5 variables:
##  $ fecha  : Date, format: "2021-07-22" "2021-07-25" ...
##  $ printel: num  0 1 1 0 0 1 1 1 0 1 ...
##  $ mahle  : num  2.65 2.85 2.5 2.5 2.55 2.65 2.51 3 3 3.05 ...
##  $ magna  : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ varroc : num  0 0 0 0 0 0 0 0 0 0 ...
performance$mahle <- substr(performance$mahle, start = 1, stop = 2)
performance$mahle <- as.numeric(performance$mahle)

performance$magna <- substr(performance$magna, start = 1, stop = 2)
performance$magna <- as.numeric(performance$magna)
str(performance)
## 'data.frame':    324 obs. of  5 variables:
##  $ fecha  : Date, format: "2021-07-22" "2021-07-25" ...
##  $ printel: num  0 1 1 0 0 1 1 1 0 1 ...
##  $ mahle  : num  2 2 2 2 2 2 2 3 3 3 ...
##  $ magna  : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ varroc : num  0 0 0 0 0 0 0 0 0 0 ...
performance$varroc <- substr(performance$varroc, start = 1, stop = 2)
performance$varroc <- as.numeric(performance$varroc)
str(performance)
## 'data.frame':    324 obs. of  5 variables:
##  $ fecha  : Date, format: "2021-07-22" "2021-07-25" ...
##  $ printel: num  0 1 1 0 0 1 1 1 0 1 ...
##  $ mahle  : num  2 2 2 2 2 2 2 3 3 3 ...
##  $ magna  : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ varroc : num  0 0 0 0 0 0 0 0 0 0 ...
En estas dos técnicas de limpieza se vuelven a factor o números las variables para generar un estandarizar y generar un formato para que se vuelva más sencillo al realizar gráficos y manipular datos.

Técnica 4.Reemplazar NAs con la mediana de cada variable

sapply(performance, function(x) sum(is.na(x)))
##   fecha printel   mahle   magna  varroc 
##      25      25      25      25      25
performance$fecha[is.na(performance$fecha)]<-median(performance$fecha, na.rm = TRUE)
performance$printel[is.na(performance$printel)]<-median(performance$printel, na.rm = TRUE)
performance$mahle[is.na(performance$mahle)]<-median(performance$mahle, na.rm = TRUE)
performance$magna[is.na(performance$magna)]<-median(performance$magna, na.rm = TRUE)
performance$varroc[is.na(performance$varroc)]<-median(performance$varroc, na.rm = TRUE)
summary(performance)
##      fecha               printel           mahle           magna       varroc 
##  Min.   :2021-07-22   Min.   :0.0000   Min.   :-9.00   Min.   :0   Min.   :0  
##  1st Qu.:2021-10-20   1st Qu.:0.0000   1st Qu.: 2.00   1st Qu.:0   1st Qu.:0  
##  Median :2022-02-07   Median :0.0000   Median : 3.00   Median :0   Median :0  
##  Mean   :2022-01-30   Mean   :0.3395   Mean   : 2.21   Mean   :0   Mean   :0  
##  3rd Qu.:2022-04-27   3rd Qu.:0.2500   3rd Qu.: 3.00   3rd Qu.:0   3rd Qu.:0  
##  Max.   :2022-07-23   Max.   :4.0000   Max.   :20.00   Max.   :0   Max.   :0
Al reemplazar los NA ’s con la mediana nos ayuda para no contar con registros nulos y contar con los valores más acertados posibles al tiempo de analizarlos.

Exportar base de datos limpia

write.csv(performance, file="performance_bd_limpia.csv", row.names = FALSE)

Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua

Elige la escala de medición de cada variable.

Variable_performance<-c("Fecha"," Printel","Mahle", "Magna", "Varroc")
Type_performance<-c("qualitative", "quantiative (continous)", "quantitative (continous)", "quantitative (continous)", "quantitative (continous)")
escalas_performance <- c("NA", "Piezas Entregadas","Piezas Entregadas","Piezas Entregadas","Piezas Entregadas")
table_performance <- data.frame (Variable_performance, Type_performance, escalas_performance)
knitr::kable(table_performance)
Variable_performance Type_performance escalas_performance
Fecha qualitative NA
Printel quantiative (continous) Piezas Entregadas
Mahle quantitative (continous) Piezas Entregadas
Magna quantitative (continous) Piezas Entregadas
Varroc quantitative (continous) Piezas Entregadas

Análisis Exploratorio de las Bases de Datos

Análisis Estadístico

Media

media_printel <- mean(performance$printel)
media_printel
## [1] 0.3395062
media_mahle <- mean(performance$mahle)
media_mahle
## [1] 2.209877
media_magna <- mean(performance$magna)
media_magna
## [1] 0
media_varroc <- mean(performance$varroc)
media_varroc
## [1] 0

Mediana

mediana_printel <- median(performance$printel)
mediana_printel
## [1] 0
mediana_mahle <- median(performance$mahle)
mediana_mahle
## [1] 3
mediana_magna <- median(performance$magna)
mediana_magna
## [1] 0
mediana_varroc <- median(performance$varroc)
mediana_varroc
## [1] 0

Moda

mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}
moda_printel <- mode(performance$printel)
moda_printel
## [1] 0
moda_mahle <- mode(performance$mahle)
moda_mahle
## [1] 3
moda_magna <- mode(performance$magna)
moda_magna
## [1] 0
moda_varroc <- mode(performance$varroc)
moda_varroc
## [1] 0

Varianza

varianza_printel <-var(performance$printel)
varianza_printel
## [1] 0.4416542
varianza_mahle <-var(performance$mahle)
varianza_mahle
## [1] 2.909376
varianza_magna <-var(performance$magna)
varianza_magna
## [1] 0
varianza_varroc <-var(performance$varroc)
varianza_varroc
## [1] 0

Desviación Estándar

desviacion_printel <- sqrt(varianza_printel)
desviacion_printel
## [1] 0.6645707
desviacion_mahle <- sqrt(varianza_mahle)
desviacion_mahle
## [1] 1.705689
desviacion_magna <- sqrt(varianza_magna)
desviacion_magna
## [1] 0
desviacion_varroc <- sqrt(varianza_varroc)
desviacion_varroc
## [1] 0

Tabla

Variable_performance<-c("Fecha"," Printel","Mahle", "Magna", "Varroc")
Promedio_performance <-c("NA","0.339", "2.209","0", "0")
Moda_performance <-c("NA","3","0","0", "0")
Mediana_performance <-c("NA","0","3","0", "0")
Varianza_performance <-c("NA","0.441","2.909","0", "0")
Desviación_Estándar_performance <-c ("NA","0.664","1.705","0", "0")
tabla_performance <-data.frame(Variable_performance,Promedio_performance, Moda_performance, Mediana_performance, Varianza_performance, Desviación_Estándar_performance)
knitr::kable(tabla_performance)
Variable_performance Promedio_performance Moda_performance Mediana_performance Varianza_performance Desviación_Estándar_performance
Fecha NA NA NA NA NA
Printel 0.339 3 0 0.441 0.664
Mahle 2.209 0 3 2.909 1.705
Magna 0 0 0 0 0
Varroc 0 0 0 0 0

Dispersion plot

ggplot(performance,aes(x=fecha))+
  geom_line(aes(y=printel),color="blue")+
  geom_line(aes(y=mahle),color="orange")+
  geom_line(aes(y=magna),color="green")+
  geom_line(aes(y=varroc),color="green")+
  labs(x="Fecha",y="Retraso en horas", color="Legend")+
  ggtitle("Retrasos de entrega por cliente")

En esta gráfica podemos observar que FORM con los clientes Magna y Varroc no presentan horas de retraso en sus pedidos, sin embargo, con Mahle y Printel si han presentado retrasos considerables prinicipalmente dentro del primer trimestre del 2022. Teniendo retrasos de hasta 20 horas.

Producción

Antes de importar la base de datos, se optó por:

1. Se integraron los datos de Julio, Agosto y Septiembre.
2. Se incorporó una nueva columna de “Fecha”.
3. Solo se dejaron los datos de “Tiempo de Maquinas”
4. Se eliminaron los NAs y variables no numéricas de las columnas de: “Láminas procesadas”.

Importar las bases de datos

#file.choose()
bd4 <- read.csv("/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/EMI_CARTON.csv")
library(janitor)
produccion <- clean_names(bd4)
summary(produccion)
##     fecha             cliente            id_form            producto        
##  Length:3988        Length:3988        Length:3988        Length:3988       
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##  piezas_prog          tmo_min             hr_fin          estacion_arranque 
##  Length:3988        Length:3988        Length:3988        Length:3988       
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##  laminas_procesadas inicio_sep_up      fin_inicio_de_sep_up inicio_de_proceso 
##  Min.   :   0       Length:3988        Length:3988          Length:3988       
##  1st Qu.:   0       Class :character   Class :character     Class :character  
##  Median :  51       Mode  :character   Mode  :character     Mode  :character  
##  Mean   : 102                                                                 
##  3rd Qu.: 184                                                                 
##  Max.   :1263                                                                 
##                                                                               
##  fin_de_proceso     tiempo_calidad     tiempo_materiales
##  Length:3988        Length:3988        Min.   : 0.000   
##  Class :character   Class :character   1st Qu.: 0.000   
##  Mode  :character   Mode  :character   Median : 0.000   
##                                        Mean   : 3.187   
##                                        3rd Qu.: 1.000   
##                                        Max.   :60.000   
##                                        NA's   :3491
produccion <- subset(produccion,select = -c (id_form, producto, hr_fin, inicio_sep_up, fin_inicio_de_sep_up, inicio_de_proceso, fin_de_proceso, tiempo_materiales))
summary(produccion)
##     fecha             cliente          piezas_prog          tmo_min         
##  Length:3988        Length:3988        Length:3988        Length:3988       
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  estacion_arranque  laminas_procesadas tiempo_calidad    
##  Length:3988        Min.   :   0       Length:3988       
##  Class :character   1st Qu.:   0       Class :character  
##  Mode  :character   Median :  51       Mode  :character  
##                     Mean   : 102                         
##                     3rd Qu.: 184                         
##                     Max.   :1263
library(data.table)
library(plyr)
library(dplyr)
library(ggplot2)
library(naniar)
library(Hmisc)         
library(psych)
library(tidyverse)
library(knitr)
# install.packages("pollster")
library(pollster)
library(epiDisplay)
library(descr)
library(tidyr)

Limpieza, Transformación, y Organización de Bases de Datos

¿Cuántas variables y cuantos registros tiene la base de datos?

describeData(produccion,head=1,tail=1)
## n.obs =  3988 of which  3987   are complete cases.   Number of variables =  7  of which all are numeric  FALSE  
##                    variable # n.obs type         H1         T1
## fecha*                      1  3988    3 16/07/2022 07/09/2022
## cliente*                    2  3987    3       TRMX           
## piezas_prog*                3  3988    3          1           
## tmo_min*                    4  3988    3         10         20
## estacion_arranque*          5  3988    3       C1Y2   ROTATIVA
## laminas_procesadas          6  3988    1          3          0
## tiempo_calidad*             7  3988    3          1
Existen 15 variables y 1614 registros en la base de datos.

Aplica técnicas de limpieza de bases de datos y explícalas brevemente, ¿por qué realizaste esas técnicas?

Técnica 1.Convertir a caracter a numerico y de fecha

produccion$piezas_prog<-as.numeric(produccion$piezas_prog)                 
produccion$tmo_min<-as.numeric(produccion$tmo_min)                  
produccion$laminas_procesadas<-as.numeric(produccion$laminas_procesadas)   
produccion$tiempo_calidad<-as.numeric(produccion$tiempo_calidad) 
produccion$fecha <- as.Date(produccion$fecha, format = "%d/%m/%Y")
summary(produccion)
##      fecha              cliente           piezas_prog        tmo_min      
##  Min.   :2022-07-15   Length:3988        Min.   :   1.0   Min.   :  0.00  
##  1st Qu.:2022-08-03   Class :character   1st Qu.: 100.0   1st Qu.: 15.00  
##  Median :2022-08-20   Mode  :character   Median : 153.5   Median : 20.00  
##  Mean   :2022-08-19                      Mean   : 180.3   Mean   : 22.37  
##  3rd Qu.:2022-09-06                      3rd Qu.: 200.0   3rd Qu.: 25.00  
##  Max.   :2022-09-21                      Max.   :2000.0   Max.   :150.00  
##                                          NA's   :180      NA's   :824     
##  estacion_arranque  laminas_procesadas tiempo_calidad   
##  Length:3988        Min.   :   0       Min.   : 0.0000  
##  Class :character   1st Qu.:   0       1st Qu.: 0.0000  
##  Mode  :character   Median :  51       Median : 1.0000  
##                     Mean   : 102       Mean   : 0.8631  
##                     3rd Qu.: 184       3rd Qu.: 1.0000  
##                     Max.   :1263       Max.   :22.0000  
##                                        NA's   :346
En esta técnica de limpieza se vuelven a factor o números las variables para generar un estandarizar y generar un formato para que se vuelva más sencillo al realizar gráficos y manipular datos.

Técnica 2.Reemplazar por el promedio los NA´s de tmo_min, tiempo_calidad, piezas_prog

produccion$tmo_min[is.na(produccion$tmo_min)]<-mean(produccion$tmo_min, na.rm = TRUE)
produccion$tiempo_calidad[is.na(produccion$tiempo_calidad)]<-mean(produccion$tiempo_calidad, na.rm = TRUE)
produccion$piezas_prog[is.na(produccion$piezas_prog)]<-mean(produccion$piezas_prog, na.rm = TRUE)
summary(produccion)
##      fecha              cliente           piezas_prog        tmo_min      
##  Min.   :2022-07-15   Length:3988        Min.   :   1.0   Min.   :  0.00  
##  1st Qu.:2022-08-03   Class :character   1st Qu.: 100.0   1st Qu.: 15.00  
##  Median :2022-08-20   Mode  :character   Median : 180.3   Median : 22.37  
##  Mean   :2022-08-19                      Mean   : 180.3   Mean   : 22.37  
##  3rd Qu.:2022-09-06                      3rd Qu.: 200.0   3rd Qu.: 25.00  
##  Max.   :2022-09-21                      Max.   :2000.0   Max.   :150.00  
##  estacion_arranque  laminas_procesadas tiempo_calidad   
##  Length:3988        Min.   :   0       Min.   : 0.0000  
##  Class :character   1st Qu.:   0       1st Qu.: 0.8631  
##  Mode  :character   Median :  51       Median : 1.0000  
##                     Mean   : 102       Mean   : 0.8631  
##                     3rd Qu.: 184       3rd Qu.: 1.0000  
##                     Max.   :1263       Max.   :22.0000
Al reemplazar los NA ’s con el promedio nos ayuda para no contar con registros nulos y contar con los valores más acertados posibles al tiempo de analizarlos.

Técnica 3. Borrar las letras de algunos registros de “Pieza_Prog”.

produccion$piezas_prog <- str_replace(produccion$piezas_prog, "[aeiouLAM=NbBsS]", "")
produccion$piezas_prog <- as.integer(produccion$laminas_procesadas)
Esta técnica se realizó ya que no los registros de la variable piezas programadas contenian errores de dedo.

Exportar la base de datos limpia

bd_Produccion_limpia <- produccion
write.csv(bd_Produccion_limpia, file="bd_produccion_limpia.csv", row.names = FALSE)

Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua

Elige la escala de medición de cada variable.

Variablep <-c("Fecha", "Cliente", "piezas_prog","tmo_min ","estacion_arranque", "laminas_procesadas", "tiempo_calidad")
Typep<-c("qualitative", "qualitative", "quantitative (discreta)", "quantitative (continua)", "qualitative", "quantitative (discreta)", "quantitative (continuo)")
escalasp <- c("NA", "NA", "piezas asignadas", "Minutos", "NA", "piezas terminadas", "horas" )
tablep <- data.frame (Variablep, Typep, escalasp)
knitr::kable(tablep)
Variablep Typep escalasp
Fecha qualitative NA
Cliente qualitative NA
piezas_prog quantitative (discreta) piezas asignadas
tmo_min quantitative (continua) Minutos
estacion_arranque qualitative NA
laminas_procesadas quantitative (discreta) piezas terminadas
tiempo_calidad quantitative (continuo) horas

Análisis Exploratorio de las Bases de Datos

Análisis Estadístico

Media

media_piezas_prog<- mean(produccion$piezas_prog)
media_piezas_prog
## [1] 102.0105
media_tmo_min<- mean(produccion$tmo_min)
media_tmo_min 
## [1] 22.37042
media_laminas_procesadas <- mean(produccion$laminas_procesadas)
media_laminas_procesadas
## [1] 102.0105
media_tiempo_calidad<- mean(produccion$tiempo_calidad)
media_tiempo_calidad
## [1] 0.8630972

Mediana

median_piezas_prog<- median(produccion$piezas_prog)
median_piezas_prog
## [1] 51
median_tmo_min<- median(produccion$tmo_min)
median_tmo_min 
## [1] 22.37042
median_laminas_procesadas <- median(produccion$laminas_procesadas)
media_laminas_procesadas
## [1] 102.0105
median_tiempo_calidad<- median(produccion$tiempo_calidad)
median_tiempo_calidad
## [1] 1

Moda

mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}
moda_piezas_prog <- mode(produccion$piezas_prog)
moda_piezas_prog
## [1] 0
moda_tmo_min <- mode(produccion$tmo_min)
moda_tmo_min
## [1] 25
moda_laminas_procesadas<- mode(produccion$laminas_procesadas)
moda_laminas_procesadas
## [1] 0
moda_tiempo_calidad <- mode(produccion$tiempo_calidad)
moda_tiempo_calidad
## [1] 1

Varianza

varianza_piezas_prog <-var(produccion$piezas_prog)
varianza_piezas_prog
## [1] 18056.03
varianza_tmo_min <-var(produccion$tmo_min)
varianza_tmo_min
## [1] 142.3682
varianza_laminas_procesadas<-var(produccion$laminas_procesadas)
varianza_laminas_procesadas
## [1] 18056.03
varianza_tiempo_calidad <-var(produccion$tiempo_calidad)
varianza_tiempo_calidad
## [1] 0.9819163

Desviación Estándar

desviacion_piezas_prog<- sqrt(varianza_piezas_prog)
desviacion_piezas_prog
## [1] 134.3727
desviacion_tmo_min <- sqrt(varianza_tmo_min)
desviacion_tmo_min
## [1] 11.93181
desviacion_laminas_procesadas <- sqrt(varianza_laminas_procesadas)
desviacion_laminas_procesadas
## [1] 134.3727
desviacion_tiempo_calidad <- sqrt(varianza_tiempo_calidad)
desviacion_tiempo_calidad
## [1] 0.9909169

Tabla

Variable2 <-c("piezas_prog","tmo_min ", "laminas_procesadas", "tiempo_calidad")
Promedio2 <-c("180.323", "22.370","102.01", "0.86")
Moda2 <-c("200", "25","0", "1")
Mediana2 <-c("180.23","22.37","102.0105", "1")
Varianza2 <-c("21940.88","142.3682","18056.03", "0.9819163")
Desviación_Estándar2 <-c ("148.1245","11.93181","134.3727", "0.9909169")
tabla2 <-data.frame(Variable2,Promedio2, Moda2, Mediana2, Varianza2, Desviación_Estándar2)
tabla2
##            Variable2 Promedio2 Moda2 Mediana2 Varianza2 Desviación_Estándar2
## 1        piezas_prog   180.323   200   180.23  21940.88             148.1245
## 2           tmo_min     22.370    25    22.37  142.3682             11.93181
## 3 laminas_procesadas    102.01     0 102.0105  18056.03             134.3727
## 4     tiempo_calidad      0.86     1        1 0.9819163            0.9909169
knitr::kable(tabla2)
Variable2 Promedio2 Moda2 Mediana2 Varianza2 Desviación_Estándar2
piezas_prog 180.323 200 180.23 21940.88 148.1245
tmo_min 22.370 25 22.37 142.3682 11.93181
laminas_procesadas 102.01 0 102.0105 18056.03 134.3727
tiempo_calidad 0.86 1 1 0.9819163 0.9909169

Gráfico cuantitativo

ggplot(produccion,aes(x=fecha))+
  geom_line(aes(y=piezas_prog),color="blue")+
  labs(x="Fecha",y="piezas programadas", color="blue")+
  ggtitle("Grafica de las piezas programadas por fecha")

En este gráfico se muestran los 3 diferentes meses (julio, agosto, sept), donde se puede ver que hubo mayor produccion de piezas programadas en lo que fue de julio hacia agosto.

Bar plots

ggplot(produccion, aes(x=tmo_min, y=laminas_procesadas)) +
  geom_bar(stat="identity", fill="grey") + scale_fill_grey() + 
  labs(title = "Grafico de barras de las piezas programadas dentro del tiempo minimo", 
       x = "tiempo minimo", y = "laminas procesadas")

En esta gráfico se puede ver que el tiempo mínimo dentro de las láminas procesadas no sobrepasa los 50 lo cual es una buena señal de que no hay mucho tiempo de espera.
ggplot(produccion,aes(x=reorder(tmo_min, piezas_prog), y=piezas_prog,fill=cliente)) +
  geom_bar(stat="identity")

Esta gráfica se puede visualizar los datos obtenidos de lo que fueron las piezas programadas dentro del tiempo mínimo dentro de la produccion, donde estas variables se ven dentro de los clientes.

Dispersion plots

ggplot(produccion, aes(x=piezas_prog, y=cliente)) + 
  geom_point() 

En esta gráfica de dispersion se puede apreciar visualmente la cantidad de piezas que se demandan para los diferentes clientes que tiene la empresa, donde se aprecia que Stabilus 1 toma la delantera.

Merma

Importar las bases de datos

# file.choose()
merma<- read.csv("/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/Reto/FORM - Merma 1.csv")

Limpieza, Transformación, y Organización de Bases de Datos

¿Cuántas variables y cuantos registros tiene la base de datos?

describeData(merma,head=1,tail=1)
## n.obs =  60 of which  60   are complete cases.   Number of variables =  3  of which all are numeric  FALSE  
##        variable # n.obs type       H1            T1
## Fecha*          1    60    3 11/01/22              
## Mes*            2    60    3    ENERO Total general
## Kilos*          3    60    3     5080       185,426
Existen 3 variables y 60 registros en la base de datos.

Aplica técnicas de limpieza de bases de datos y explícalas brevemente, ¿por qué realizaste esas técnicas?

Observaciones

No estan en enteros los kilos de merma
Existen filas inecesarias

Técnica 1: Eliminar totales

merma1<- merma[-c(5,12,19,25,31,36,42,54,59,60),]
Esta técnica se realizó ya que no se consideraron importantes las filas de los totales.

Técnica 2: Convertir caracter a entero.

merma1$Kilos <- as.integer(merma1$Kilos)
str(merma1)
## 'data.frame':    50 obs. of  3 variables:
##  $ Fecha: chr  "11/01/22" "11/01/22" "22/01/22" "22/01/22" ...
##  $ Mes  : chr  "ENERO" "ENERO" "ENERO" "ENERO" ...
##  $ Kilos: int  5080 3810 2990 2680 3650 4380 3870 3590 3410 3930 ...
Se optimizan las variables para R, generando un estándar.

Exportar la base de datos limpia

merma_limpia <- merma1
write.csv(merma_limpia, file ="merma_bd_limpia.csv", row.names = FALSE)

Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua

Elige la escala de medición de cada variable.

Variable_merma<-c("Fecha", "Mes", "Kilos")
Type_merma<-c("cualitativa ", "cualitativa", "cuantitativa discreta")
Measurement_merma <-c("dia", "NA", "cantidad")
table_merma<-data.frame(Variable_merma,Type_merma, Measurement_merma)
knitr::kable(table_merma)
Variable_merma Type_merma Measurement_merma
Fecha cualitativa dia
Mes cualitativa NA
Kilos cuantitativa discreta cantidad

Análisis Exploratorio de las Bases de Datos

Análisis Estadístico

Media

media_kilos <- mean(merma1$Kilos)
media_kilos
## [1] 3708.52
Las variables de fecha y el mes no puede tener media

Mediana

mediana_kilos <- median(merma1$Kilos)
mediana_kilos
## [1] 3925
Las variables de fecha y el mes no puede tener mediana

Moda

mode <- function (x) {
  ux <- unique(x)
  ux [which.max(tabulate(match(x,ux)))]
}

mode_fecha <- mode(merma1$Fecha)
mode_fecha
## [1] "18/02/22"
mode_mes <- mode(merma1$Mes)
mode_mes
## [1] "AGOSTO"
mode_kilos <- mode(merma1$Kilos)
mode_kilos
## [1] 3810

Varianza

varianza_kilos <- var(merma1$Kilos)
varianza_kilos 
## [1] 1048555

Desviación Estándar

desviacionestandar_kilos <- sqrt(varianza_kilos)
desviacionestandar_kilos
## [1] 1023.99

Tabla

Variable_merma<-c("Fecha", "Mes", "Kilos")
Media_merma<-c("NA", "NA", media_kilos)
Mediana_merma<-c("NA", "NA", mediana_kilos)
Moda_merma<-c(mode_fecha, mode_mes, mode_kilos)
Varianza_merma<-c("NA", "NA",varianza_kilos )
Desviacion_Estandar_merma<-c("NA", "NA", desviacionestandar_kilos)
table_merma<-data.frame(Variable_merma,Media_merma,Mediana_merma,Moda_merma,Varianza_merma,Desviacion_Estandar_merma)
knitr::kable(table_merma)
Variable_merma Media_merma Mediana_merma Moda_merma Varianza_merma Desviacion_Estandar_merma
Fecha NA NA 18/02/22 NA NA
Mes NA NA AGOSTO NA NA
Kilos 3708.52 3925 3810 1048554.70367347 1023.98960135026

Gráfico de dispersion

# install.packages("ggplot2")
library(ggplot2)

ggplot(data=merma1, mapping = aes(Mes, Kilos)) + geom_point() + theme_bw()

En esta gráfica podemos observar que la generacion de merma de la empresa FORM separa en los meses del 2022. Se observa que el mes que mas se genero merma fue en Agosto continuando con Febrero y Mayo. El mes que menos genero merma es Septiembre y Enero.

Dispersion plots

boxplot(merma1$Kilos)

En esta gráfica podemos observar que la merma generada en FORM se encuentra en una gran distribución. El promedio entra dentro de los 3000 y los 4000 kilos. De la misma manera, se ha llegado a generar menos de 1000 kilos contra la maxima que son arriba de los 6000 kilos.

Scrap

Limpieza, Transformación, y Organización de Bases de Datos

Importar las bases de datos

# file.choose()
scrap<- read.csv("/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/Reto/FORM - Scrap.csv")
# install.packages("dplyr")
library(dplyr)
# install.packages("psych")
library(psych)

¿Cuántas variables y cuantos registros tiene la base de datos?

describeData(scrap,head=1,tail=1)
## n.obs =  251 of which  251   are complete cases.   Number of variables =  9  of which all are numeric  FALSE  
##                       variable # n.obs type                H1
## Referencia*                    1   251    3 agosto 2022 (250)
## Fecha*                         2   251    3                  
## Producto*                      3   251    3                  
## Cantidad                       4   251    1          1674.002
## Unidad.de.medida*              5   251    3                  
## Ubicación.de.origen*           6   251    3                  
## Ubicación.de.desecho*          7   251    3                  
## Estado*                        8   251    3                  
## Hora*                          9   251    3                  
##                                                           T1
## Referencia*                                         SP/08479
## Fecha*                                              01/08/22
## Producto*             [N61506747 TAPA] N61506747. Kit. Tapa.
## Cantidad                                                   1
## Unidad.de.medida*                                 Unidad(es)
## Ubicación.de.origen*               SAB/Calidad/Entrega de PT
## Ubicación.de.desecho*             Virtual Locations/Scrapped
## Estado*                                                Hecho
## Hora*                                               13:59:47
Existen 9 variables y 251 registros en la base de datos.

Aplica técnicas de limpieza de bases de datos y explícalas brevemente, ¿por qué realizaste esas técnicas?

Observaciones

Se cuenta con una fila al inecesaria
Se cuentan con variables inecesarias

Técnica 1: Eliminar columna.

scrap1<- scrap [-1,]
Esta técnica se realizó ya que se contaba con una columna en blanco extra.

Técnica 2: Eliminar variables

scrap1 <- subset(scrap1, select = -c ( Referencia, Producto,Unidad.de.medida, Ubicación.de.desecho, Estado, Hora))

summary(scrap1)
##     Fecha              Cantidad      Ubicación.de.origen
##  Length:250         Min.   : 0.000   Length:250         
##  Class :character   1st Qu.: 1.000   Class :character   
##  Mode  :character   Median : 2.000   Mode  :character   
##                     Mean   : 6.696                      
##                     3rd Qu.: 7.000                      
##                     Max.   :96.000
Esta técnica se realizó ya que no se consideraron importantes las columnas de variables.

Técnica 3: Convertir caracter a entero.

scrap1$Cantidad <- as.integer(scrap1$Cantidad)
str(scrap1)
## 'data.frame':    250 obs. of  3 variables:
##  $ Fecha              : chr  "31/08/22" "31/08/22" "31/08/22" "31/08/22" ...
##  $ Cantidad           : int  2 1 1 31 1 1 1 9 2 1 ...
##  $ Ubicación.de.origen: chr  "SAB/Calidad/Entrega de PT" "SAB/Calidad/Entrega de PT" "SAB/Calidad/Entrega de PT" "SAB/Pre-Production" ...
En esta técnica de limpieza se vuelven a factor o números las variables para generar un estandarizar y generar un formato para que se vuelva más sencillo al realizar gráficos y manipular datos.

Exportar la base de datos limpia

scrap_limpia <- scrap1
write.csv(scrap_limpia, file ="scrap_bd_limpia.csv", row.names = FALSE)

Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua

Elige la escala de medición de cada variable.

Variable_scrap<-c("Fecha", "Cantidad", "Ubicación_de_origen")
Type_scrap<-c("cualitativa", "cuantitativa discreta", "cualitativa")
Measurement_scrap <-c("NA", "cantidad generada", "NA")
table_scrap<-data.frame(Variable_scrap,Type_scrap, Measurement_scrap)
knitr::kable(table_scrap)
Variable_scrap Type_scrap Measurement_scrap
Fecha cualitativa NA
Cantidad cuantitativa discreta cantidad generada
Ubicación_de_origen cualitativa NA

Análisis Exploratorio de las Bases de Datos

Análisis Estadístico

Media

media_cantidad <- mean(scrap1$Cantidad)
media_cantidad
## [1] 6.692
Las variables de fecha y ubicación de origen no puede tener media

Mediana

mediana_cantidad <- median(scrap1$Cantidad)
mediana_cantidad
## [1] 2
Las variables de fecha y ubicación de origen no puede tener mediana

Moda

Moda

mode <- function (x) {
  ux <- unique(x)
  ux [which.max(tabulate(match(x,ux)))]
}

mode_fecha1 <- mode(scrap1$Fecha)
mode_fecha1
## [1] "16/08/22"
mode_cantidad <- mode(scrap1$Cantidad)
mode_cantidad
## [1] 1
mode_ubicacion <- mode(scrap1$Ubicación.de.origen)
mode_ubicacion
## [1] "SAB/Pre-Production"

Varianza

varianza_cantidad <- var(scrap1$Cantidad)
varianza_cantidad
## [1] 140.4309

Desviación Estándar

desviacionestandar_cantidad <- sqrt(varianza_cantidad)
desviacionestandar_cantidad
## [1] 11.85035

Tabla

Variable_scrap<-c("Fecha", "Cantidad", "Ubicación_de_origen")
Media_scrap<-c("NA", media_cantidad, "NA")
Mediana_scrap<-c("NA",mediana_cantidad, "NA")
Moda_scrap<-c(mode_fecha1, mode_cantidad, mode_ubicacion)
Varianza_scrap<-c("NA",varianza_cantidad, "NA")
Desviacion_Estandar_scrap<-c("NA", desviacionestandar_cantidad, "NA")
table_scrap<-data.frame(Variable_scrap,Media_scrap,Mediana_scrap,Moda_scrap,Varianza_scrap,Desviacion_Estandar_scrap)
knitr::kable(table_scrap)
Variable_scrap Media_scrap Mediana_scrap Moda_scrap Varianza_scrap Desviacion_Estandar_scrap
Fecha NA NA 16/08/22 NA NA
Cantidad 6.692 2 1 140.430859437751 11.8503527136432
Ubicación_de_origen NA NA SAB/Pre-Production NA NA

Gráfico cualitativo (Pay):

pie(table(scrap1$Ubicación.de.origen))

Bar Plots

# install.packages("ggplot2")
library(ggplot2)

ggplot(scrap1, aes(x=Ubicación.de.origen, y=Cantidad)) +
  geom_bar(stat="identity", fill="brown") + scale_fill_grey() + # Add bars to the plot
  labs(title = "Donde se genera el scrap", # Add a title
       subtitle = "RH empresa FORM", # Add a subtitle
       caption = "Relación", # Add a caption
       x = "Ubicación de origen")

En estas gráficas podemos observar que en la manera de como esta distribuida la generacion de el scrap de la empresa FORM. Se observa de una manera por mucha diferencia en se genera la mayor cantidad en la pre-producción y en la que menos se produce el scrap es en la etapa de la post-producción.

Base de Datos Externa

Importar base de datos

# file.choose()
bd_externa <-read.csv("/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/Reto/Producción de cartón en México 1.csv")

Limpieza, Transformación, y Organización de Bases de Datos

Técnica 1: Remover valores irrelevantes, columna inecesaria “Industry.Group.ID” no me aporta datos importantes

externa <- bd_externa
externa <- subset (externa,select = -c(Industry.Group.ID))

summary(externa)
##     State.ID        State               Region      Industry.Group    
##  Min.   : 1.00   Length:999         Min.   :1.000   Length:999        
##  1st Qu.:10.75   Class :character   1st Qu.:1.000   Class :character  
##  Median :18.00   Mode  :character   Median :2.000   Mode  :character  
##  Mean   :17.62                      Mean   :2.333                     
##  3rd Qu.:25.25                      3rd Qu.:3.000                     
##  Max.   :31.00                      Max.   :4.000                     
##  NA's   :975                        NA's   :975                       
##  Economic.Unit   
##  Min.   :  1.00  
##  1st Qu.:  1.75  
##  Median :  5.00  
##  Mean   : 13.17  
##  3rd Qu.:  8.75  
##  Max.   :151.00  
##  NA's   :975
Esta técnica se realizó ya que se considero inecesaria la columna “Industry.Group.ID”,no me aporta datos importantes.

Técnica 2: Remover NA’s

#?Cuantos NA tengo en la base de datos?
sum(is.na(externa))
## [1] 2925
#?Cuantos NA tengo por variable?
sapply(externa, function(x) sum (is.na(x)))
##       State.ID          State         Region Industry.Group  Economic.Unit 
##            975              0            975              0            975
#Borrar todos los registros NA de una tabla
externa1 <- externa
externa1 <- na.omit(externa1)

summary(externa1)
##     State.ID        State               Region      Industry.Group    
##  Min.   : 1.00   Length:24          Min.   :1.000   Length:24         
##  1st Qu.:10.75   Class :character   1st Qu.:1.000   Class :character  
##  Median :18.00   Mode  :character   Median :2.000   Mode  :character  
##  Mean   :17.62                      Mean   :2.333                     
##  3rd Qu.:25.25                      3rd Qu.:3.000                     
##  Max.   :31.00                      Max.   :4.000                     
##  Economic.Unit   
##  Min.   :  1.00  
##  1st Qu.:  1.75  
##  Median :  5.00  
##  Mean   : 13.17  
##  3rd Qu.:  8.75  
##  Max.   :151.00
Se eliminaron los NA ’s de la base de datos ya que viene con espacios vacios.

Análisis Estadístico

Media

media_region <- mean(externa1$Region)
media_region
## [1] 2.333333
media_economic <- mean(externa1$Economic.Unit)
media_economic
## [1] 13.16667
Las variables de fecha y ubicación de origen no puede tener media

Mediana

mediana_region <- median(externa1$Region)
mediana_region
## [1] 2
mediana_economic <- median(externa1$Economic.Unit)
mediana_economic
## [1] 5
Las variables de fecha y ubicación de origen no puede tener mediana

Moda

mode <- function (x) {
  ux <- unique(x)
  ux [which.max(tabulate(match(x,ux)))]
}

mode_state <- mode(externa1$State.ID)
mode_state
## [1] 1
mode_region <- mode(externa1$Region)
mode_region
## [1] 1
mode_economic <- mode(externa1$Economic.Unit)
mode_economic
## [1] 1

Varianza

varianza_region <- var(externa1$Region)
varianza_region
## [1] 1.188406
varianza_economic <- var(externa1$Economic.Unit)
varianza_economic
## [1] 946.1449

Desviación Estándar

desviacionestandar_region <- sqrt(varianza_region)
desviacionestandar_region
## [1] 1.09014
desviacionestandar_economic <- sqrt(varianza_economic)
desviacionestandar_economic
## [1] 30.75947

Tabla

Variable_externa<-c("State.ID", "Region", "Economic.Unit")
Media_externa<-c("NA", media_region, media_economic)
Mediana_externa<-c("NA",mediana_region, mediana_economic)
Moda_externa<-c(mode_state, mode_region, mode_economic)
Varianza_externa<-c("NA",varianza_region, varianza_economic)
Desviacion_Estandar_externa<-c("NA", desviacionestandar_region, desviacionestandar_economic)
table_externa<-data.frame(Variable_externa,Media_externa,Mediana_externa,Moda_externa,Varianza_externa,Desviacion_Estandar_externa)
knitr::kable(table_externa)
Variable_externa Media_externa Mediana_externa Moda_externa Varianza_externa Desviacion_Estandar_externa
State.ID NA NA 1 NA NA
Region 2.33333333333333 2 1 1.18840579710145 1.09014026487487
Economic.Unit 13.1666666666667 5 1 946.144927536232 30.7594689085529

Dispersion plots

ggplot(externa1, aes(x =Region, y =Economic.Unit)) + 
  geom_point(shape=19, size=3) + 
  labs(title = "Relación entre Unidades Economicas y Region de Mexico",caption ="Base de Externa",x="Region", y="Economic Unit") + 
  theme_classic()

En esta gráfica podemos observar que la región no.3 de México es donde se genera con mayor unidades de cartón esto según la base de datos externa tomada de la INEGI.

Bar Plot

ggplot(externa1 ,aes(x=reorder(Region, Economic.Unit), y=Economic.Unit ,fill=State)) +
  geom_bar(stat="identity")

En esta gráfica, se volvió a analizar la producción d e carton por región de mexico, agregando que se puede observar de una manera visual y clara de los estados de la república que forman parte de la regiones. Se observa que el mayor productor de cartón es Puebla.

Pronóstico del Desempeño de la Industria Automotriz y la empresa FORM

Importar bases de datos

#file.choose()
bd_prediccion <- read.csv("/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/encoded-bd_prediccion.csv")
vehiculos_circulacion <- read.csv("/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/encoded-vehiculos_en_circulacion (2).csv")
produccion <- read.csv("/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/bd_produccion_limpia (1).csv")

Instalar paquetes y llamar librerías

#install.packages("tseries")
library(tseries)
#install.packages("forecast")
library(forecast)
#install.packages("astsa")
library(astsa)
#install.packages("dplyr")
library(dplyr)
#install.packages("jtools")
library(jtools)
#install.packages("lmtest")
library(lmtest)
#install.packages("car")
library(car)
#install.packages("olsrr")
library(olsrr)
#install.packages("corrplot")
library(corrplot)

Pronósticos

Desempeño de la industria automotriz para los siguientes 3 periodos de tiempo

Vehículos de motor registrados en circulación

Entender la base de datos

summary(vehiculos_circulacion)
##      Año                Total           Automóviles      
##  Length:47          Min.   : 4010430   Min.   : 3950042  
##  Class :character   1st Qu.: 6748523   1st Qu.: 6654340  
##  Mode  :character   Median :11002046   Median :10764080  
##                     Mean   :14899354   Mean   :14673142  
##                     3rd Qu.:22392796   3rd Qu.:22068938  
##                     Max.   :35913468   Max.   :35460804  
##                     NA's   :5          NA's   :5         
##  Camiones.para.pasajeros Camiones.y.camionetas.para.carga  Motocicletas    
##  Min.   : 60388          Min.   : 1470816                 Min.   : 128960  
##  1st Qu.: 90931          1st Qu.: 3046906                 1st Qu.: 248248  
##  Median :233490          Median : 5166812                 Median : 295262  
##  Mean   :226212          Mean   : 5920971                 Mean   :1156467  
##  3rd Qu.:336420          3rd Qu.: 9199181                 3rd Qu.:1284405  
##  Max.   :461089          Max.   :11262666                 Max.   :5939262  
##  NA's   :5               NA's   :5                        NA's   :5        
##     X             X.1         
##  Mode:logical   Mode:logical  
##  NA's:47        NA's:47       
##                               
##                               
##                               
##                               
## 
str(vehiculos_circulacion)
## 'data.frame':    47 obs. of  8 variables:
##  $ Año                             : chr  "1980" "1981" "1982" "1983" ...
##  $ Total                           : int  4010430 4406336 4686130 4797562 5047043 5360870 5286295 5420592 5682964 6093682 ...
##  $ Automóviles                     : int  3950042 4341363 4616897 4726236 4970526 5281842 5202922 5336228 5597735 6003532 ...
##  $ Camiones.para.pasajeros         : int  60388 64973 69233 71326 76517 79028 83373 84364 85229 90150 ...
##  $ Camiones.y.camionetas.para.carga: int  1470816 1636899 1751799 1893206 2009875 2114395 2213025 2292078 2424025 2691551 ...
##  $ Motocicletas                    : int  277084 296601 257235 250484 248148 250358 232692 221059 217898 223815 ...
##  $ X                               : logi  NA NA NA NA NA NA ...
##  $ X.1                             : logi  NA NA NA NA NA NA ...

Limpieza de datos

Eliminar variables (Camiones.y.camionetas.para.carga, Motocicletas, X y X.1)

vehiculos_circulacion1 <- subset(vehiculos_circulacion, select = -c (Camiones.y.camionetas.para.carga, Motocicletas, X, X.1))
vehiculos_circulacion1
##                                                                              Año
## 1                                                                           1980
## 2                                                                           1981
## 3                                                                           1982
## 4                                                                           1983
## 5                                                                           1984
## 6                                                                           1985
## 7                                                                           1986
## 8                                                                           1987
## 9                                                                           1988
## 10                                                                          1989
## 11                                                                          1990
## 12                                                                          1991
## 13                                                                          1992
## 14                                                                          1993
## 15                                                                          1994
## 16                                                                          1995
## 17                                                                          1996
## 18                                                                          1997
## 19                                                                          1998
## 20                                                                          1999
## 21                                                                          2000
## 22                                                                          2001
## 23                                                                          2002
## 24                                                                          2003
## 25                                                                          2004
## 26                                                                          2005
## 27                                                                          2006
## 28                                                                          2007
## 29                                                                          2008
## 30                                                                          2009
## 31                                                                          2010
## 32                                                                          2011
## 33                                                                          2012
## 34                                                                          2013
## 35                                                                          2014
## 36                                                                          2015
## 37                                                                          2016
## 38                                                                          2017
## 39                                                                          2018
## 40                                                                          2019
## 41                                                                          2020
## 42                                                                          2021
## 43                                                                              
## 44                                                                              
## 45                                                                              
## 46 FUENTE: INEGI. Estadísticas de vehículos de motor registrados en circulación.
## 47                                                                              
##       Total Automóviles Camiones.para.pasajeros
## 1   4010430     3950042                   60388
## 2   4406336     4341363                   64973
## 3   4686130     4616897                   69233
## 4   4797562     4726236                   71326
## 5   5047043     4970526                   76517
## 6   5360870     5281842                   79028
## 7   5286295     5202922                   83373
## 8   5420592     5336228                   84364
## 9   5682964     5597735                   85229
## 10  6093682     6003532                   90150
## 11  6648825     6555550                   93275
## 12  7047618     6950708                   96910
## 13  7494357     7399178                   95179
## 14  7801892     7715951                   85941
## 15  7332309     7217732                  114577
## 16  7590001     7469504                  120497
## 17  7927797     7830864                   96933
## 18  8528440     8402995                  125445
## 19  9262652     9086209                  176443
## 20  9783153     9582796                  200357
## 21 10378575    10176179                  202396
## 22 11625518    11351982                  273536
## 23 12554275    12254910                  299365
## 24 13050150    12742049                  308101
## 25 13652596    13388011                  264585
## 26 14569197    14300380                  268817
## 27 16722002    16411813                  310189
## 28 18018701    17696623                  322078
## 29 19754229    19420942                  333287
## 30 20856689    20519224                  337465
## 31 21465511    21152773                  312738
## 32 22701891    22374326                  327565
## 33 23908143    23569623                  338520
## 34 25167066    24819922                  347144
## 35 25891628    25543908                  347720
## 36 27265446    26907994                  357452
## 37 29032067    28664295                  367772
## 38 31359162    30958042                  401120
## 39 32733646    32290067                  443579
## 40 34057197    33603591                  453606
## 41 34886784    34425695                  461089
## 42 35913468    35460804                  452664
## 43       NA          NA                      NA
## 44       NA          NA                      NA
## 45       NA          NA                      NA
## 46       NA          NA                      NA
## 47       NA          NA                      NA
Estas variables se eliminan, ya que, camiones y camionetas para carga y motocicletas no son el principal mercado de FORM, además de que los datos de sus variables no son significativas para el pronóstico porque sus valores son muy pequeños a comparación con las demás variables, por lo tanto, sus datos no impactan al análisis, de igual forma, se elimina la variable X y X.1 porque no tienen información relevante.

Eliminar renglones irrelevantes

vehiculos_circulacion2 <- vehiculos_circulacion1[-c(43,44,45,46,47),]
vehiculos_circulacion2
##     Año    Total Automóviles Camiones.para.pasajeros
## 1  1980  4010430     3950042                   60388
## 2  1981  4406336     4341363                   64973
## 3  1982  4686130     4616897                   69233
## 4  1983  4797562     4726236                   71326
## 5  1984  5047043     4970526                   76517
## 6  1985  5360870     5281842                   79028
## 7  1986  5286295     5202922                   83373
## 8  1987  5420592     5336228                   84364
## 9  1988  5682964     5597735                   85229
## 10 1989  6093682     6003532                   90150
## 11 1990  6648825     6555550                   93275
## 12 1991  7047618     6950708                   96910
## 13 1992  7494357     7399178                   95179
## 14 1993  7801892     7715951                   85941
## 15 1994  7332309     7217732                  114577
## 16 1995  7590001     7469504                  120497
## 17 1996  7927797     7830864                   96933
## 18 1997  8528440     8402995                  125445
## 19 1998  9262652     9086209                  176443
## 20 1999  9783153     9582796                  200357
## 21 2000 10378575    10176179                  202396
## 22 2001 11625518    11351982                  273536
## 23 2002 12554275    12254910                  299365
## 24 2003 13050150    12742049                  308101
## 25 2004 13652596    13388011                  264585
## 26 2005 14569197    14300380                  268817
## 27 2006 16722002    16411813                  310189
## 28 2007 18018701    17696623                  322078
## 29 2008 19754229    19420942                  333287
## 30 2009 20856689    20519224                  337465
## 31 2010 21465511    21152773                  312738
## 32 2011 22701891    22374326                  327565
## 33 2012 23908143    23569623                  338520
## 34 2013 25167066    24819922                  347144
## 35 2014 25891628    25543908                  347720
## 36 2015 27265446    26907994                  357452
## 37 2016 29032067    28664295                  367772
## 38 2017 31359162    30958042                  401120
## 39 2018 32733646    32290067                  443579
## 40 2019 34057197    33603591                  453606
## 41 2020 34886784    34425695                  461089
## 42 2021 35913468    35460804                  452664
summary(vehiculos_circulacion2)
##      Año                Total           Automóviles      
##  Length:42          Min.   : 4010430   Min.   : 3950042  
##  Class :character   1st Qu.: 6748523   1st Qu.: 6654340  
##  Mode  :character   Median :11002046   Median :10764080  
##                     Mean   :14899354   Mean   :14673142  
##                     3rd Qu.:22392796   3rd Qu.:22068938  
##                     Max.   :35913468   Max.   :35460804  
##  Camiones.para.pasajeros
##  Min.   : 60388         
##  1st Qu.: 90931         
##  Median :233490         
##  Mean   :226212         
##  3rd Qu.:336420         
##  Max.   :461089

Se eliminan estos renglones, debido a que no tenían contenido, es decir, eran considerados NA´s.

Gráfica

plot(vehiculos_circulacion2$Año,vehiculos_circulacion2$Total, type="l",col="blue", lwd=1.5, xlab ="Año",ylab ="Unidades", main = "Vehiculos de motor en circulación registrados anualmente")
lines(vehiculos_circulacion2$Año,vehiculos_circulacion2$Automóviles,col="red",lty=3)
legend("topleft", legend=c("Total de vehiculos en circulación", "Automóviles en circulación"),
       col=c("blue", "red"), lty = 1:2, cex=0.8)

Con este plot, se puede observar el comportamiento de las variables y la comparación a través de los años del total de vehiculos que están en circulación y de los automoviles.
También, se percibe que ambas líneas son muy similares, y están muy cerca una de la otra, por lo que se puede deducir que Automóviles ocupa el mayor porcentaje del total.
Por otro lado, la gráfica tiene una tendencia en su mayoría creciente y positiva, es decir, que cada año hay más automóviles en circulación.

Forecasting usando el Modelo autoregresivo

autoregressive_model <- arma(vehiculos_circulacion2$Total, order = c(1,0))
summary(autoregressive_model <- arma(vehiculos_circulacion2$Total, order = c(1,0)))
## 
## Call:
## arma(x = vehiculos_circulacion2$Total, order = c(1, 0))
## 
## Model:
## ARMA(1,0)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -964598 -203485  -37324  133579 1366807 
## 
## Coefficient(s):
##            Estimate  Std. Error  t value Pr(>|t|)    
## ar1       1.043e+00   3.792e-03      275   <2e-16 ***
## intercept 1.595e+05         NaN      NaN      NaN    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Fit:
## sigma^2 estimated as 1.852e+11,  Conditional Sum-of-Squares = 7.406257e+12,  AIC = 1212.86
autoregressive_model_forecast<-forecast(autoregressive_model$fitted,h=5,level=c(95))
autoregressive_model_forecast
##    Point Forecast    Lo 95    Hi 95
## 43       37884281 35240406 40528155
## 44       39222087 34802632 43641541
## 45       40559893 34284299 46835486
## 46       41897698 33625820 50169577
## 47       43235504 32811356 53659653
Lo que se observa en el modelo autoregresivo de los vehículos de motor en circulación y al pronóstico para los siguientes años, es que como se explico anteriormente, tiene una tendencia positiva, por ejemplo, en el siguiente año se esperan 37,884,281 vehículos en circulación con un 95% de confianza, y los rangos pueden ir de 35,240,406 hasta 40,528,155.
En el segundo año, se pronostican 39,222,087, de igual manera con un 95% de confianza, y por último, en el tercer año, se preveen 40,559,893 vehículos en circulación.

Gráfica

plot(autoregressive_model_forecast)

Con este plot, se puede interpretar de manera más visual lo que se explico anteriormente, y para explicarlo con mayor precisión, es necesario saber que la línea negra corresponde a los datos que se tienen en la base de datos, mientras que la línea azul significa el resultado de los datos obtenidos a través del modelo autoregresivo, y se puede observar que va hacia arriba la tendencia.
Por otro lado, la línea azul tiene un sombreado gris que indica los valores de “low” y “high” ante el 95% de confianza.

Forecasting usando Moving Average Model

mam_circulacion <- arma(vehiculos_circulacion2$Total,order = c(1,1))
summary(mam_circulacion <- arma(vehiculos_circulacion2$Total,order = c(1,1)))
## 
## Call:
## arma(x = vehiculos_circulacion2$Total, order = c(1, 1))
## 
## Model:
## ARMA(1,1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -907766 -184323  -41323  113291 1305470 
## 
## Coefficient(s):
##            Estimate  Std. Error  t value Pr(>|t|)    
## ar1       1.042e+00   4.680e-03  222.585  < 2e-16 ***
## ma1       3.442e-01   1.237e-01    2.783  0.00539 ** 
## intercept 1.767e+05         NaN      NaN      NaN    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Fit:
## sigma^2 estimated as 1.598e+11,  Conditional Sum-of-Squares = 6.391897e+12,  AIC = 1208.67
mam_circulacion_forecast <- forecast(mam_circulacion$fitted,h=5,level=c(95))
mam_circulacion_forecast
##    Point Forecast    Lo 95    Hi 95
## 43       37635019 34318781 40951258
## 44       38948870 33832084 44065655
## 45       40262720 33315250 47210190
## 46       41576570 32704146 50448994
## 47       42890421 31977035 53803806
A través de este código, podemos deducir, que buscamos un modelo no estacionario, y que esta en constante movimiento, y al igual que el modelo autoregresivo, se puede observar una tendencia positiva, y muy similar a ella, así mismo, cuenta con un 95% de confianza.
Por otro lado, los vehículos circulando durante el primer periodo de tiempo se calcula que son 37,635,019, seguido por 38,948,870 y 40,262,720.

Gráfica

plot(mam_circulacion_forecast)

Aquí se puede interpretar gráficamente lo explicado en el punto anterior, y se obseva como la tendencia es positiva, de igual forma, tiene “lows” y “highs”.

Desempeño de 1 de las áreas de la empresa FORM para los siguientes 3 periodos de tiempo

Producción FORM

Entender la base de datos

summary(produccion)
##     fecha             cliente           piezas_prog        tmo_min      
##  Length:3985        Length:3985        Min.   :   0.0   Min.   :  0.00  
##  Class :character   Class :character   1st Qu.:   0.0   1st Qu.: 15.00  
##  Mode  :character   Mode  :character   Median :  51.0   Median : 20.00  
##                                        Mean   : 102.1   Mean   : 21.89  
##                                        3rd Qu.: 184.0   3rd Qu.: 25.00  
##                                        Max.   :1263.0   Max.   :150.00  
##  estacion_arranque  laminas_procesadas tiempo_calidad   
##  Length:3985        Min.   :   0.0     Min.   : 0.0000  
##  Class :character   1st Qu.:   0.0     1st Qu.: 1.0000  
##  Mode  :character   Median :  51.0     Median : 1.0000  
##                     Mean   : 102.1     Mean   : 0.8754  
##                     3rd Qu.: 184.0     3rd Qu.: 1.0000  
##                     Max.   :1263.0     Max.   :22.0000
str(produccion)
## 'data.frame':    3985 obs. of  7 variables:
##  $ fecha             : chr  "16/07/2022" "22/07/2022" "28/07/2022" "12/08/2022" ...
##  $ cliente           : chr  "TRMX" "STABILUS 3" "STABILUS 3" "TRMX" ...
##  $ piezas_prog       : int  3 2 2 1 1 1 0 2 5 5 ...
##  $ tmo_min           : int  10 10 10 10 10 10 10 10 10 10 ...
##  $ estacion_arranque : chr  "C1Y2" "C1Y2" "C1Y2" "C1" ...
##  $ laminas_procesadas: int  3 2 2 1 1 1 0 2 5 5 ...
##  $ tiempo_calidad    : num  1 1 2 1 1 1 0 0 1 1 ...

Limpieza de datos

Eliminar NA´s

produccion$cliente <- as.factor(produccion$cliente)
str(produccion)
## 'data.frame':    3985 obs. of  7 variables:
##  $ fecha             : chr  "16/07/2022" "22/07/2022" "28/07/2022" "12/08/2022" ...
##  $ cliente           : Factor w/ 13 levels "DENSO","HANON SYSTEMS",..: 9 7 7 9 9 1 3 10 10 6 ...
##  $ piezas_prog       : int  3 2 2 1 1 1 0 2 5 5 ...
##  $ tmo_min           : int  10 10 10 10 10 10 10 10 10 10 ...
##  $ estacion_arranque : chr  "C1Y2" "C1Y2" "C1Y2" "C1" ...
##  $ laminas_procesadas: int  3 2 2 1 1 1 0 2 5 5 ...
##  $ tiempo_calidad    : num  1 1 2 1 1 1 0 0 1 1 ...
summary(produccion)
##     fecha                 cliente      piezas_prog        tmo_min      
##  Length:3985        STABILUS 1:1343   Min.   :   0.0   Min.   :  0.00  
##  Class :character   TRMX      : 686   1st Qu.:   0.0   1st Qu.: 15.00  
##  Mode  :character   STABILUS 3: 599   Median :  51.0   Median : 20.00  
##                     YANFENG   : 431   Mean   : 102.1   Mean   : 21.89  
##                     DENSO     : 399   3rd Qu.: 184.0   3rd Qu.: 25.00  
##                     (Other)   : 526   Max.   :1263.0   Max.   :150.00  
##                     NA's      :   1                                    
##  estacion_arranque  laminas_procesadas tiempo_calidad   
##  Length:3985        Min.   :   0.0     Min.   : 0.0000  
##  Class :character   1st Qu.:   0.0     1st Qu.: 1.0000  
##  Mode  :character   Median :  51.0     Median : 1.0000  
##                     Mean   : 102.1     Mean   : 0.8754  
##                     3rd Qu.: 184.0     3rd Qu.: 1.0000  
##                     Max.   :1263.0     Max.   :22.0000  
## 
produccion1 <- produccion 
produccion1<-  produccion1[-c(624),] 
summary (produccion1)
##     fecha                 cliente      piezas_prog        tmo_min      
##  Length:3984        STABILUS 1:1343   Min.   :   0.0   Min.   :  0.00  
##  Class :character   TRMX      : 686   1st Qu.:   0.0   1st Qu.: 15.00  
##  Mode  :character   STABILUS 3: 599   Median :  51.0   Median : 20.00  
##                     YANFENG   : 431   Mean   : 102.1   Mean   : 21.89  
##                     DENSO     : 399   3rd Qu.: 184.0   3rd Qu.: 25.00  
##                     VARROC    : 269   Max.   :1263.0   Max.   :150.00  
##                     (Other)   : 257                                    
##  estacion_arranque  laminas_procesadas tiempo_calidad   
##  Length:3984        Min.   :   0.0     Min.   : 0.0000  
##  Class :character   1st Qu.:   0.0     1st Qu.: 1.0000  
##  Mode  :character   Median :  51.0     Median : 1.0000  
##                     Mean   : 102.1     Mean   : 0.8754  
##                     3rd Qu.: 184.0     3rd Qu.: 1.0000  
##                     Max.   :1263.0     Max.   :22.0000  
## 
Se eliminaron los NA´s que no tenían relevancia, y se reemplazaron otros desde la base de datos con el nombre “sin registro”, ya que, se consideró que era importante quedarse con estos datos para visualizar mejor los datos.

Forecasting usando el Modelo autoregresivo

autoregressive_model_produccion <- arma(produccion1$piezas_prog, order = c(1,0))
summary(autoregressive_model_produccion <- arma(produccion1$piezas_prog, order = c(1,0)))
## 
## Call:
## arma(x = produccion1$piezas_prog, order = c(1, 0))
## 
## Model:
## ARMA(1,0)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -645.89  -52.84  -30.07   50.72 1191.16 
## 
## Coefficient(s):
##            Estimate  Std. Error  t value Pr(>|t|)    
## ar1         0.48255     0.01388    34.77   <2e-16 ***
## intercept  52.84244     2.34226    22.56   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Fit:
## sigma^2 estimated as 13861,  Conditional Sum-of-Squares = 55195736,  AIC = 49304.94
autoregressive_model_produccion_forecast<-forecast(autoregressive_model_produccion$fitted,h=5,level=c(95))
autoregressive_model_produccion_forecast
##      Point Forecast    Lo 95    Hi 95
## 3985       82.70478 3.234460 162.1751
## 3986       82.70478 3.191276 162.2183
## 3987       82.70478 3.148106 162.2614
## 3988       82.70478 3.104950 162.3046
## 3989       82.70478 3.061809 162.3477
En el caso de este modelo autoregresivo, ambos coeficientes son de gran relevancia para la base de datos, ya que ambas tienen los 3 asteriscos, por otro lado, a la hora de hacer el pronóstico, es notorio que se estima que quedará de la misma forma, es decir, con las mismas piezas programadas, sin embargo se puede ver como mientras “Low” disminuye, “high” aumenta.

Gráfica

plot(autoregressive_model_produccion_forecast)

Como se puede ver en el plot, no se espera una mejora para este modelo, y se pueden ver los forecast, el low y el high, con 95% de confianza.

Forecasting usando Moving Average Model

mam_produccion <- arma(produccion1$piezas_prog,order = c(1,1))
summary(mam_produccion <- arma(produccion1$piezas_prog,order = c(1,1)))
## 
## Call:
## arma(x = produccion1$piezas_prog, order = c(1, 1))
## 
## Model:
## ARMA(1,1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -791.67  -53.47  -22.33   37.73 1208.91 
## 
## Coefficient(s):
##            Estimate  Std. Error  t value Pr(>|t|)    
## ar1         0.83882     0.02370   35.400  < 2e-16 ***
## ma1        -0.51985     0.04204  -12.365  < 2e-16 ***
## intercept  16.48077     2.57279    6.406  1.5e-10 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Fit:
## sigma^2 estimated as 13444,  Conditional Sum-of-Squares = 53534365,  AIC = 49185.18
mam_produccion_forecast <- forecast(mam_produccion$fitted,h=5,level=c(95))
mam_produccion_forecast
##      Point Forecast     Lo 95    Hi 95
## 3985       165.7268 90.147513 241.3062
## 3986       165.7268 59.600542 271.8531
## 3987       165.7268 36.060547 295.3931
## 3988       165.7268 16.181181 315.2725
## 3989       165.7268 -1.349372 332.8031
El comportamiento de este modelo indica que no se pronostican cambios a lo largo de los proximos años, con un 95% de confianza, pero si se observa en lows, el cambio de un periodo de tiempo a otro es algo drastico, y va decreciendo, mientras que en high, el comportamiento es variado, ya que, a veces sube y a veces baja sin una tendencia a seguir.

Gráfica

plot(mam_produccion_forecast)

Tendencia del desempeño durante el periodo de análisis y los siguientes 3 periodos de tiempo: En cuanto a los datos externos, es decir, a la industria automotriz, el modelo de estimación de pronóstico indica que la tendencia es positiva, lo cual quiere decir, que cada año se pronóstica que haya más vehículos en circulación con una confianza del 95%. Los datos anteriores, benefician a FORM, deduciendo que si hay más autos en circulación, hay más producción, y por lo tanto, más pedidos y clientes, sin embargo, en la base de datos directamente de FORM, se observa que en algunos casos, no existe una tendencia, y que se esperan como pronóstico las mismas piezas programadas, por lo tanto, habría que tener una estrategia para que más gente llegue a conocer y a ser parte de los clientes de la empresa.

Predicción del Desempeño de la Industria Automotriz

Exportación y ventas de vehículos ligeros

Entender la base de datos

summary(bd_prediccion)
##       Año            Mes            Venta          Producción    
##  Min.   :2006   Min.   : 1.00   Min.   : 34927   Min.   :  3722  
##  1st Qu.:2010   1st Qu.: 3.00   1st Qu.: 78543   1st Qu.:189031  
##  Median :2014   Median : 6.00   Median : 88580   Median :248433  
##  Mean   :2014   Mean   : 6.42   Mean   : 94178   Mean   :241511  
##  3rd Qu.:2018   3rd Qu.: 9.00   3rd Qu.:110134   3rd Qu.:292709  
##  Max.   :2022   Max.   :12.00   Max.   :192741   Max.   :382110  
##  NA's   :2      NA's   :2       NA's   :2        NA's   :2       
##   Exportación     Tipo.de.cambio    Inflación      porcentaje_ocu 
##  Min.   : 15139   Min.   :10.09   Min.   :-0.250   Min.   :93.58  
##  1st Qu.:153219   1st Qu.:12.66   1st Qu.: 0.815   1st Qu.:95.06  
##  Median :209160   Median :13.56   Median : 1.480   Median :95.88  
##  Mean   :201664   Mean   :15.48   Mean   : 1.951   Mean   :95.76  
##  3rd Qu.:243900   3rd Qu.:19.10   3rd Qu.: 2.895   3rd Qu.:96.47  
##  Max.   :327454   Max.   :24.24   Max.   : 7.360   Max.   :97.16  
##  NA's   :2        NA's   :2       NA's   :2        NA's   :2      
##  porcentaje_desocu conf_consumidor
##  Min.   :2.840     Min.   :28.67  
##  1st Qu.:3.527     1st Qu.:36.69  
##  Median :4.125     Median :38.47  
##  Mean   :4.244     Mean   :39.15  
##  3rd Qu.:4.940     3rd Qu.:42.59  
##  Max.   :6.420     Max.   :47.83  
##  NA's   :2         NA's   :2
str(bd_prediccion)
## 'data.frame':    202 obs. of  10 variables:
##  $ Año              : int  2006 2006 2006 2006 2006 2006 2006 2006 2006 2006 ...
##  $ Mes              : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Venta            : int  96227 89079 96871 77879 86462 87084 83069 90937 92083 97469 ...
##  $ Producción       : int  155291 166830 192643 132212 171557 194327 118602 179527 164577 179897 ...
##  $ Exportación      : int  112165 121001 153877 115798 131578 156008 85752 136114 125918 132470 ...
##  $ Tipo.de.cambio   : num  10.6 10.5 10.7 11 11.1 ...
##  $ Inflación        : num  0.59 0.74 0.87 1.01 0.56 0.65 0.93 1.44 2.47 2.91 ...
##  $ porcentaje_ocu   : num  96.5 96.2 96.7 96.8 97.2 ...
##  $ porcentaje_desocu: num  3.48 3.75 3.31 3.2 2.84 3.26 4.01 3.87 4 3.82 ...
##  $ conf_consumidor  : num  43.9 43.9 45.6 44.8 44.7 ...

Limpieza de datos

Eliminar columnas irrelevantes (Producción)

bd_prediccion1 <- subset(bd_prediccion, select = -c (Producción))
bd_prediccion1
##      Año Mes  Venta Exportación Tipo.de.cambio Inflación porcentaje_ocu
## 1   2006   1  96227      112165       10.56964      0.59          96.52
## 2   2006   2  89079      121001       10.48426      0.74          96.25
## 3   2006   3  96871      153877       10.69772      0.87          96.69
## 4   2006   4  77879      115798       11.02994      1.01          96.80
## 5   2006   5  86462      131578       11.07152      0.56          97.16
## 6   2006   6  87084      156008       11.38702      0.65          96.74
## 7   2006   7  83069       85752       11.03922      0.93          95.99
## 8   2006   8  90937      136114       10.87617      1.44          96.13
## 9   2006   9  92083      125918       10.97558      2.47          96.00
## 10  2006  10  97469      132470       10.91245      2.91          96.18
## 11  2006  11 102201      152396       10.87905      3.45          96.50
## 12  2006  12 140375      113718       10.87084      4.05          96.68
## 13  2007   1  97675       88915       10.93192      0.52          95.95
## 14  2007   2  86060      111084       10.98198      0.80          95.95
## 15  2007   3  96487      138877       11.12237      1.02          96.27
## 16  2007   4  75020      110462       10.99081      0.96          96.49
## 17  2007   5  84756      140387       10.83582      0.46          96.85
## 18  2007   6  80462      153243       10.83519      0.58          96.72
## 19  2007   7  83105      129581       10.79959      1.01          96.21
## 20  2007   8  88573      168210       11.04243      1.42          96.17
## 21  2007   9  86547      156237       11.03762      2.21          96.24
## 22  2007  10  97182      144970       10.84063      2.61          96.23
## 23  2007  11  97694      149964       10.85821      3.33          96.65
## 24  2007  12 126329      121383       10.85206      3.76          96.89
## 25  2008   1  96846      118416       10.91741      0.46          95.88
## 26  2008   2  86997      140501       10.78461      0.76          96.11
## 27  2008   3  80119      129405       10.73085      1.49          96.39
## 28  2008   4  83106      144234       10.52556      1.72          96.52
## 29  2008   5  85827      150514       10.45804      1.61          96.71
## 30  2008   6  81424      153345       10.32862      2.03          96.63
## 31  2008   7  85324      122144       10.23761      2.60          95.87
## 32  2008   8  86119      143464       10.09196      3.20          95.94
## 33  2008   9  76620      144454       10.60434      3.90          95.86
## 34  2008  10  83307      167497       12.48947      4.61          95.83
## 35  2008  11  78555      138439       13.09469      5.80          95.68
## 36  2008  12 101300      109206       13.37363      6.53          95.98
## 37  2009   1  69664       51061       13.86394      0.23          94.99
## 38  2009   2  61579       77833       14.50219      0.45          94.76
## 39  2009   3  64242      101830       14.72083      1.03          95.34
## 40  2009   4  51395       85121       13.47903      1.38          94.94
## 41  2009   5  53440       83910       13.25065      1.09          94.77
## 42  2009   6  55974       84934       13.34374      1.28          95.02
## 43  2009   7  56443       90872       13.36679      1.55          94.18
## 44  2009   8  58926      111273       13.01394      1.79          93.85
## 45  2009   9  58505      117433       13.40757      2.30          93.58
## 46  2009  10  67882      145761       13.25259      2.61          94.33
## 47  2009  11  64914      134873       13.13145      3.15          94.89
## 48  2009  12  91961      138432       12.85556      3.57          95.27
## 49  2010   1  64064      114193       12.83263      1.09          94.24
## 50  2010   2  59518      153148       12.96185      1.67          94.72
## 51  2010   3  65414      163641       12.60465      2.39          95.26
## 52  2010   4  60432      133406       12.26208      2.07          94.65
## 53  2010   5  61632      145909       12.68247      1.42          95.00
## 54  2010   6  59910      177575       12.71818      1.39          95.08
## 55  2010   7  61960      143521       12.83341      1.61          94.41
## 56  2010   8  66931      175904       12.72952      1.89          94.58
## 57  2010   9  65934      169507       12.86421      2.43          94.34
## 58  2010  10  74095      166931       12.45569      3.06          94.52
## 59  2010  11  75582      168226       12.31381      3.89          94.83
## 60  2010  12 104941      147551       12.40058      4.40          95.06
## 61  2011   1  68767      165045       12.15321      0.49          94.66
## 62  2011   2  66990      155808       12.07712      0.86          94.66
## 63  2011   3  75125      192783       12.01917      1.06          95.36
## 64  2011   4  65246      141334       11.75536      1.05          94.87
## 65  2011   5  68634      176951       11.65234      0.30          94.82
## 66  2011   6  68366      188223       11.80157      0.30          94.60
## 67  2011   7  68533      196835       11.67069      0.78          94.52
## 68  2011   8  75681      170086       12.20000      0.94          94.29
## 69  2011   9  73998      193590       13.08912      1.19          94.57
## 70  2011  10  75748      192244       13.46868      1.87          95.01
## 71  2011  11  83107      199665       13.63712      2.97          95.04
## 72  2011  12 115698      171319       13.74813      3.82          95.49
## 73  2012   1  75297      156417       13.48802      0.71          95.12
## 74  2012   2  74704      197600       12.80356      0.91          94.72
## 75  2012   3  83574      226555       12.75781      0.97          95.48
## 76  2012   4  69890      180545       13.02576      0.65          95.14
## 77  2012   5  80268      184302       13.53816      0.34          95.33
## 78  2012   6  78508      229089       13.97611      0.80          95.25
## 79  2012   7  76378      208151       13.39195      1.36          95.01
## 80  2012   8  83326      188392       13.18333      1.67          94.67
## 81  2012   9  79961      193350       13.00449      2.12          95.09
## 82  2012  10  83172      216576       12.86915      2.63          94.97
## 83  2012  11  91966      219864       12.86915      3.33          94.95
## 84  2012  12 110998      154724       12.87298      3.57          95.60
## 85  2013   1  84403      178562       12.71282      0.40          94.59
## 86  2013   2  80285      175338       12.71638      0.90          95.25
## 87  2013   3  82860      204475       12.40242      1.64          95.52
## 88  2013   4  83647      185548       12.21560      1.70          95.04
## 89  2013   5  87638      191205       12.23945      1.37          95.09
## 90  2013   6  83858      225753       12.95020      1.30          95.00
## 91  2013   7  86760      192940       12.76920      1.27          94.87
## 92  2013   8  88586      226893       12.88348      1.56          94.82
## 93  2013   9  78555      215962       13.08974      1.94          94.69
## 94  2013  10  88416      240316       13.02170      2.43          94.99
## 95  2013  11 100571      224873       13.06409      3.38          95.52
## 96  2013  12 119519      161208       13.00105      3.97          95.73
## 97  2014   1  85614      177928       13.20104      0.89          94.93
## 98  2014   2  80037      197504       13.29067      1.15          95.34
## 99  2014   3  85767      230772       13.21485      1.43          95.20
## 100 2014   4  76941      202328       13.07712      1.24          95.15
## 101 2014   5  88388      234629       12.95623      0.91          95.06
## 102 2014   6  84207      230410       12.97570      1.09          95.18
## 103 2014   7  96366      231934       12.97300      1.37          94.53
## 104 2014   8 103994      226757       13.15002      1.73          94.81
## 105 2014   9  89313      220239       13.21131      2.18          94.91
## 106 2014  10 101090      257382       13.47454      2.74          95.22
## 107 2014  11 111837      237923       13.59030      3.57          95.47
## 108 2014  12 133411      195091       14.45304      4.08          96.24
## 109 2015   1 103805      204907       14.67395     -0.09          95.49
## 110 2015   2  97659      222351       14.90437      0.10          95.67
## 111 2015   3 105034      261256       15.20997      0.51          96.14
## 112 2015   4  94953      233515       15.22746      0.25          95.69
## 113 2015   5 102156      240709       15.25361     -0.25          95.55
## 114 2015   6 107097      242720       15.45056     -0.09          95.59
## 115 2015   7 111863      226511       15.87623      0.06          95.28
## 116 2015   8 112307      234668       16.50888      0.27          95.32
## 117 2015   9 111705      216587       16.83229      0.65          95.50
## 118 2015  10 120214      245224       16.59932      1.16          95.45
## 119 2015  11 126750      223797       16.63219      1.72          96.04
## 120 2015  12 160901      206651       17.01278      2.13          96.04
## 121 2016   1 119833      213244       17.94565      0.38          95.74
## 122 2016   2 111126      219670       18.45920      0.82          95.86
## 123 2016   3 117252      224184       17.67208      0.97          96.25
## 124 2016   4 118754      197020       17.48096      0.65          96.20
## 125 2016   5 121879      226240       18.05380      0.20          95.99
## 126 2016   6 134913      247005       18.62127      0.31          96.08
## 127 2016   7 132109      225530       18.58811      0.57          96.00
## 128 2016   8 134388      262673       18.46011      0.86          96.02
## 129 2016   9 131888      235612       19.11921      1.47          95.88
## 130 2016  10 137503      255115       18.97319      2.09          96.33
## 131 2016  11 154779      245330       19.96946      2.89          96.50
## 132 2016  12 192741      216645       20.54282      3.36          96.62
## 133 2017   1 123447      219061       21.39550      1.70          96.40
## 134 2017   2 118193      248288       20.35246      2.29          96.66
## 135 2017   3 137245      305403       19.41648      2.92          96.81
## 136 2017   4 114938      240141       18.78122      3.04          96.53
## 137 2017   5 123429      269067       18.79971      2.92          96.45
## 138 2017   6 127752      287979       18.20815      3.18          96.71
## 139 2017   7 122678      258557       17.85459      3.57          96.58
## 140 2017   8 125985      276108       17.80650      4.08          96.48
## 141 2017   9 116716      286400       17.80554      4.41          96.41
## 142 2017  10 123602      303514       18.71362      5.06          96.49
## 143 2017  11 141724      290569       18.98973      6.15          96.59
## 144 2017  12 159234      268772       19.10129      6.77          96.85
## 145 2018   1 109445      231088       19.02896      0.53          96.64
## 146 2018   2 109846      271228       18.61594      0.91          96.83
## 147 2018   3 119127      317398       18.65489      1.24          97.06
## 148 2018   4 109748      271048       18.34659      0.90          96.61
## 149 2018   5 115155      288659       19.45515      0.73          96.78
## 150 2018   6 120298      315130       20.31281      1.12          96.63
## 151 2018   7 115047      247367       19.09664      1.66          96.53
## 152 2018   8 119487      322779       18.80423      2.26          96.54
## 153 2018   9 114888      306009       19.03592      2.69          96.42
## 154 2018  10 117602      313471       19.09212      3.22          96.73
## 155 2018  11 134143      291018       20.25495      4.10          96.75
## 156 2018  12 142300      275962       20.15294      4.83          96.64
## 157 2019   1 111514      243652       19.22744      0.09          96.44
## 158 2019   2 104009      273173       19.18334      0.06          96.71
## 159 2019   3 117529      325703       19.24878      0.44          96.78
## 160 2019   4  98366      288756       19.01630      0.50          96.50
## 161 2019   5 102422      309017       19.09191      0.21          96.50
## 162 2019   6 106782      327454       19.26678      0.27          96.43
## 163 2019   7 106104      276818       19.06189      0.65          96.26
## 164 2019   8 108074      286075       19.58659      0.63          96.29
## 165 2019   9 100757      286806       19.60990      0.89          96.22
## 166 2019  10 107110      259158       19.36886      1.44          96.31
## 167 2019  11 124804      274845       19.30748      2.26          96.58
## 168 2019  12 130460      236848       19.16932      2.83          97.09
## 169 2020   1 104852      238749       18.81445      0.48          96.22
## 170 2020   2 104338      273634       18.77705      0.90          96.47
## 171 2020   3  87541      295199       21.97384      0.85          97.09
## 172 2020   4  34927       31183       24.23988     -0.17          95.31
## 173 2020   5  42034       15139       23.58032      0.22          95.81
## 174 2020   6  62861      198084       22.26918      0.76          94.51
## 175 2020   7  72921      264520       22.48030      1.43          94.65
## 176 2020   8  77120      264478       22.23107      1.82          94.74
## 177 2020   9  77808      257562       21.60516      2.06          94.87
## 178 2020  10  84351      280474       21.38085      2.68          95.29
## 179 2020  11  95707      287703       20.53330      2.76          95.65
## 180 2020  12 105603      275081       19.97817      3.15          96.21
## 181 2021   1  81657      223533       19.90262      0.86          95.30
## 182 2021   2  82863      213987       20.29248      1.50          95.60
## 183 2021   3  96319      256119       20.76205      2.34          96.13
## 184 2021   4  84287      234584       20.10944      2.67          95.35
## 185 2021   5  86710      242020       20.05320      2.88          96.01
## 186 2021   6  88688      234394       20.04272      3.43          95.98
## 187 2021   7  82157      202021       19.98552      4.04          95.62
## 188 2021   8  78235      212687       20.05125      4.24          95.67
## 189 2021   9  76930      195294       19.99092      4.88          95.82
## 190 2021  10  76640      224535       20.47244      5.76          96.05
## 191 2021  11  82829      240341       20.78256      6.97          96.34
## 192 2021  12  97420      227465       20.98530      7.36          96.49
## 193 2022   1  78585      216630       20.48354      0.59          96.29
## 194 2022   2  79598      201868       20.48437      1.43          96.26
## 195 2022   3  95199      262494       20.60089      2.43          97.03
## 196 2022   4  83459      241286       20.04452      2.98          96.97
## 197 2022   5  91215      244643       20.11331      3.17          96.73
## 198 2022   6  90368      237674       19.96650      4.04          96.65
## 199 2022   7  83137      210170       20.53081      4.81          96.57
## 200 2022   8  91124      248704       20.12613      5.54          96.47
## 201   NA  NA     NA          NA             NA        NA             NA
## 202   NA  NA     NA          NA             NA        NA             NA
##     porcentaje_desocu conf_consumidor
## 1                3.48         43.9415
## 2                3.75         43.9100
## 3                3.31         45.6029
## 4                3.20         44.7854
## 5                2.84         44.6508
## 6                3.26         44.2339
## 7                4.01         44.8674
## 8                3.87         45.0383
## 9                4.00         45.0604
## 10               3.82         44.3016
## 11               3.50         43.1883
## 12               3.32         44.7871
## 13               4.05         42.7412
## 14               4.05         42.3778
## 15               3.73         43.5677
## 16               3.51         43.4415
## 17               3.15         43.7534
## 18               3.28         43.0694
## 19               3.79         42.9629
## 20               3.83         43.9863
## 21               3.76         43.0238
## 22               3.77         41.2666
## 23               3.35         40.8568
## 24               3.11         42.8202
## 25               4.12         42.1822
## 26               3.89         41.2208
## 27               3.61         41.8964
## 28               3.48         40.1531
## 29               3.29         38.9120
## 30               3.37         37.6903
## 31               4.13         36.7035
## 32               4.06         37.2616
## 33               4.14         36.6558
## 34               4.17         34.2078
## 35               4.32         34.9500
## 36               4.02         34.9987
## 37               5.01         34.4084
## 38               5.24         33.4023
## 39               4.66         33.4728
## 40               5.06         34.6003
## 41               5.23         33.1933
## 42               4.98         34.2256
## 43               5.82         36.0502
## 44               6.15         34.5306
## 45               6.42         34.4993
## 46               5.67         32.6096
## 47               5.11         33.1707
## 48               4.73         33.9865
## 49               5.76         34.8020
## 50               5.28         34.2586
## 51               4.74         34.6691
## 52               5.35         35.0361
## 53               5.00         35.5938
## 54               4.92         36.7799
## 55               5.59         36.9279
## 56               5.42         37.2006
## 57               5.66         38.3303
## 58               5.48         37.4086
## 59               5.17         37.1774
## 60               4.94         38.1767
## 61               5.34         38.4624
## 62               5.34         38.4413
## 63               4.64         38.3233
## 64               5.13         37.6265
## 65               5.18         37.3597
## 66               5.40         38.7674
## 67               5.48         39.7537
## 68               5.71         38.9023
## 69               5.43         38.4823
## 70               4.99         37.7094
## 71               4.96         37.4238
## 72               4.51         37.7149
## 73               4.88         39.3604
## 74               5.28         38.9804
## 75               4.52         38.8750
## 76               4.86         40.2245
## 77               4.67         39.7323
## 78               4.75         39.7133
## 79               4.99         41.1478
## 80               5.33         40.7832
## 81               4.91         39.3550
## 82               5.03         39.6293
## 83               5.05         39.1214
## 84               4.40         41.1395
## 85               5.41         41.6134
## 86               4.75         39.6882
## 87               4.48         39.9339
## 88               4.96         39.8361
## 89               4.91         39.4471
## 90               5.00         38.7706
## 91               5.13         40.6562
## 92               5.18         40.5308
## 93               5.31         39.1825
## 94               5.01         38.0775
## 95               4.48         36.9465
## 96               4.27         37.3707
## 97               5.07         35.5508
## 98               4.66         35.7346
## 99               4.80         37.1351
## 100              4.85         37.6101
## 101              4.94         37.7513
## 102              4.82         37.9049
## 103              5.47         37.5518
## 104              5.19         37.4502
## 105              5.09         38.2199
## 106              4.78         37.6935
## 107              4.53         38.4760
## 108              3.76         38.6914
## 109              4.51         38.0625
## 110              4.33         37.4911
## 111              3.86         38.5052
## 112              4.31         37.8429
## 113              4.45         38.0317
## 114              4.41         39.1119
## 115              4.72         38.1319
## 116              4.68         37.3836
## 117              4.50         37.4490
## 118              4.55         37.8131
## 119              3.96         38.1829
## 120              3.96         38.3685
## 121              4.26         38.1815
## 122              4.14         36.7321
## 123              3.75         36.8144
## 124              3.80         36.7139
## 125              4.01         37.4848
## 126              3.92         38.3491
## 127              4.00         36.5060
## 128              3.98         35.6554
## 129              4.12         34.7550
## 130              3.67         35.0319
## 131              3.50         34.8752
## 132              3.38         35.4784
## 133              3.60         28.6679
## 134              3.34         31.5156
## 135              3.19         33.7951
## 136              3.47         34.9345
## 137              3.55         35.8733
## 138              3.29         36.0104
## 139              3.42         36.4886
## 140              3.52         36.5055
## 141              3.59         36.7879
## 142              3.51         36.4370
## 143              3.41         36.7168
## 144              3.15         36.3155
## 145              3.36         34.8018
## 146              3.17         34.1893
## 147              2.94         34.3367
## 148              3.39         35.6116
## 149              3.22         36.6479
## 150              3.37         37.1483
## 151              3.47         43.3411
## 152              3.46         43.0057
## 153              3.58         42.1327
## 154              3.27         42.5330
## 155              3.25         41.6750
## 156              3.36         44.8654
## 157              3.56         45.9299
## 158              3.29         47.8261
## 159              3.22         46.3411
## 160              3.50         45.4850
## 161              3.50         44.3235
## 162              3.57         43.6658
## 163              3.74         43.3177
## 164              3.71         43.8192
## 165              3.78         45.2995
## 166              3.69         44.0597
## 167              3.42         43.8407
## 168              2.91         43.7574
## 169              3.78         44.1205
## 170              3.53         43.3299
## 171              2.91         42.0593
## 172              4.69         32.2235
## 173              4.19         31.0682
## 174              5.49         31.9572
## 175              5.35         34.4173
## 176              5.26         35.0648
## 177              5.13         36.2820
## 178              4.71         37.8912
## 179              4.35         37.0767
## 180              3.79         38.7487
## 181              4.70         39.2114
## 182              4.40         38.6401
## 183              3.87         40.5816
## 184              4.65         42.5091
## 185              3.99         42.4227
## 186              4.02         44.3477
## 187              4.38         44.2934
## 188              4.33         42.4746
## 189              4.18         43.3421
## 190              3.95         43.8431
## 191              3.66         45.9354
## 192              3.51         44.8964
## 193              3.71         43.5909
## 194              3.74         42.9401
## 195              2.97         43.5603
## 196              3.03         44.3017
## 197              3.27         43.7823
## 198              3.35         43.2086
## 199              3.43         41.2699
## 200              3.53         40.2979
## 201                NA              NA
## 202                NA              NA
Esta columna se eliminará porque solo se usarán como variables dependientes Ventas y Exportación, y como variables independientes la confianza del consumidor, el tipo de cambio, la inflación, el porcentaje de personas ocupadas, y el porcentaje de personas desocupadas, es decir, sin trabajo.

Eliminar renglones irrelevantes

bd_prediccion2 <- bd_prediccion1[-c(201, 202),]
bd_prediccion2
##      Año Mes  Venta Exportación Tipo.de.cambio Inflación porcentaje_ocu
## 1   2006   1  96227      112165       10.56964      0.59          96.52
## 2   2006   2  89079      121001       10.48426      0.74          96.25
## 3   2006   3  96871      153877       10.69772      0.87          96.69
## 4   2006   4  77879      115798       11.02994      1.01          96.80
## 5   2006   5  86462      131578       11.07152      0.56          97.16
## 6   2006   6  87084      156008       11.38702      0.65          96.74
## 7   2006   7  83069       85752       11.03922      0.93          95.99
## 8   2006   8  90937      136114       10.87617      1.44          96.13
## 9   2006   9  92083      125918       10.97558      2.47          96.00
## 10  2006  10  97469      132470       10.91245      2.91          96.18
## 11  2006  11 102201      152396       10.87905      3.45          96.50
## 12  2006  12 140375      113718       10.87084      4.05          96.68
## 13  2007   1  97675       88915       10.93192      0.52          95.95
## 14  2007   2  86060      111084       10.98198      0.80          95.95
## 15  2007   3  96487      138877       11.12237      1.02          96.27
## 16  2007   4  75020      110462       10.99081      0.96          96.49
## 17  2007   5  84756      140387       10.83582      0.46          96.85
## 18  2007   6  80462      153243       10.83519      0.58          96.72
## 19  2007   7  83105      129581       10.79959      1.01          96.21
## 20  2007   8  88573      168210       11.04243      1.42          96.17
## 21  2007   9  86547      156237       11.03762      2.21          96.24
## 22  2007  10  97182      144970       10.84063      2.61          96.23
## 23  2007  11  97694      149964       10.85821      3.33          96.65
## 24  2007  12 126329      121383       10.85206      3.76          96.89
## 25  2008   1  96846      118416       10.91741      0.46          95.88
## 26  2008   2  86997      140501       10.78461      0.76          96.11
## 27  2008   3  80119      129405       10.73085      1.49          96.39
## 28  2008   4  83106      144234       10.52556      1.72          96.52
## 29  2008   5  85827      150514       10.45804      1.61          96.71
## 30  2008   6  81424      153345       10.32862      2.03          96.63
## 31  2008   7  85324      122144       10.23761      2.60          95.87
## 32  2008   8  86119      143464       10.09196      3.20          95.94
## 33  2008   9  76620      144454       10.60434      3.90          95.86
## 34  2008  10  83307      167497       12.48947      4.61          95.83
## 35  2008  11  78555      138439       13.09469      5.80          95.68
## 36  2008  12 101300      109206       13.37363      6.53          95.98
## 37  2009   1  69664       51061       13.86394      0.23          94.99
## 38  2009   2  61579       77833       14.50219      0.45          94.76
## 39  2009   3  64242      101830       14.72083      1.03          95.34
## 40  2009   4  51395       85121       13.47903      1.38          94.94
## 41  2009   5  53440       83910       13.25065      1.09          94.77
## 42  2009   6  55974       84934       13.34374      1.28          95.02
## 43  2009   7  56443       90872       13.36679      1.55          94.18
## 44  2009   8  58926      111273       13.01394      1.79          93.85
## 45  2009   9  58505      117433       13.40757      2.30          93.58
## 46  2009  10  67882      145761       13.25259      2.61          94.33
## 47  2009  11  64914      134873       13.13145      3.15          94.89
## 48  2009  12  91961      138432       12.85556      3.57          95.27
## 49  2010   1  64064      114193       12.83263      1.09          94.24
## 50  2010   2  59518      153148       12.96185      1.67          94.72
## 51  2010   3  65414      163641       12.60465      2.39          95.26
## 52  2010   4  60432      133406       12.26208      2.07          94.65
## 53  2010   5  61632      145909       12.68247      1.42          95.00
## 54  2010   6  59910      177575       12.71818      1.39          95.08
## 55  2010   7  61960      143521       12.83341      1.61          94.41
## 56  2010   8  66931      175904       12.72952      1.89          94.58
## 57  2010   9  65934      169507       12.86421      2.43          94.34
## 58  2010  10  74095      166931       12.45569      3.06          94.52
## 59  2010  11  75582      168226       12.31381      3.89          94.83
## 60  2010  12 104941      147551       12.40058      4.40          95.06
## 61  2011   1  68767      165045       12.15321      0.49          94.66
## 62  2011   2  66990      155808       12.07712      0.86          94.66
## 63  2011   3  75125      192783       12.01917      1.06          95.36
## 64  2011   4  65246      141334       11.75536      1.05          94.87
## 65  2011   5  68634      176951       11.65234      0.30          94.82
## 66  2011   6  68366      188223       11.80157      0.30          94.60
## 67  2011   7  68533      196835       11.67069      0.78          94.52
## 68  2011   8  75681      170086       12.20000      0.94          94.29
## 69  2011   9  73998      193590       13.08912      1.19          94.57
## 70  2011  10  75748      192244       13.46868      1.87          95.01
## 71  2011  11  83107      199665       13.63712      2.97          95.04
## 72  2011  12 115698      171319       13.74813      3.82          95.49
## 73  2012   1  75297      156417       13.48802      0.71          95.12
## 74  2012   2  74704      197600       12.80356      0.91          94.72
## 75  2012   3  83574      226555       12.75781      0.97          95.48
## 76  2012   4  69890      180545       13.02576      0.65          95.14
## 77  2012   5  80268      184302       13.53816      0.34          95.33
## 78  2012   6  78508      229089       13.97611      0.80          95.25
## 79  2012   7  76378      208151       13.39195      1.36          95.01
## 80  2012   8  83326      188392       13.18333      1.67          94.67
## 81  2012   9  79961      193350       13.00449      2.12          95.09
## 82  2012  10  83172      216576       12.86915      2.63          94.97
## 83  2012  11  91966      219864       12.86915      3.33          94.95
## 84  2012  12 110998      154724       12.87298      3.57          95.60
## 85  2013   1  84403      178562       12.71282      0.40          94.59
## 86  2013   2  80285      175338       12.71638      0.90          95.25
## 87  2013   3  82860      204475       12.40242      1.64          95.52
## 88  2013   4  83647      185548       12.21560      1.70          95.04
## 89  2013   5  87638      191205       12.23945      1.37          95.09
## 90  2013   6  83858      225753       12.95020      1.30          95.00
## 91  2013   7  86760      192940       12.76920      1.27          94.87
## 92  2013   8  88586      226893       12.88348      1.56          94.82
## 93  2013   9  78555      215962       13.08974      1.94          94.69
## 94  2013  10  88416      240316       13.02170      2.43          94.99
## 95  2013  11 100571      224873       13.06409      3.38          95.52
## 96  2013  12 119519      161208       13.00105      3.97          95.73
## 97  2014   1  85614      177928       13.20104      0.89          94.93
## 98  2014   2  80037      197504       13.29067      1.15          95.34
## 99  2014   3  85767      230772       13.21485      1.43          95.20
## 100 2014   4  76941      202328       13.07712      1.24          95.15
## 101 2014   5  88388      234629       12.95623      0.91          95.06
## 102 2014   6  84207      230410       12.97570      1.09          95.18
## 103 2014   7  96366      231934       12.97300      1.37          94.53
## 104 2014   8 103994      226757       13.15002      1.73          94.81
## 105 2014   9  89313      220239       13.21131      2.18          94.91
## 106 2014  10 101090      257382       13.47454      2.74          95.22
## 107 2014  11 111837      237923       13.59030      3.57          95.47
## 108 2014  12 133411      195091       14.45304      4.08          96.24
## 109 2015   1 103805      204907       14.67395     -0.09          95.49
## 110 2015   2  97659      222351       14.90437      0.10          95.67
## 111 2015   3 105034      261256       15.20997      0.51          96.14
## 112 2015   4  94953      233515       15.22746      0.25          95.69
## 113 2015   5 102156      240709       15.25361     -0.25          95.55
## 114 2015   6 107097      242720       15.45056     -0.09          95.59
## 115 2015   7 111863      226511       15.87623      0.06          95.28
## 116 2015   8 112307      234668       16.50888      0.27          95.32
## 117 2015   9 111705      216587       16.83229      0.65          95.50
## 118 2015  10 120214      245224       16.59932      1.16          95.45
## 119 2015  11 126750      223797       16.63219      1.72          96.04
## 120 2015  12 160901      206651       17.01278      2.13          96.04
## 121 2016   1 119833      213244       17.94565      0.38          95.74
## 122 2016   2 111126      219670       18.45920      0.82          95.86
## 123 2016   3 117252      224184       17.67208      0.97          96.25
## 124 2016   4 118754      197020       17.48096      0.65          96.20
## 125 2016   5 121879      226240       18.05380      0.20          95.99
## 126 2016   6 134913      247005       18.62127      0.31          96.08
## 127 2016   7 132109      225530       18.58811      0.57          96.00
## 128 2016   8 134388      262673       18.46011      0.86          96.02
## 129 2016   9 131888      235612       19.11921      1.47          95.88
## 130 2016  10 137503      255115       18.97319      2.09          96.33
## 131 2016  11 154779      245330       19.96946      2.89          96.50
## 132 2016  12 192741      216645       20.54282      3.36          96.62
## 133 2017   1 123447      219061       21.39550      1.70          96.40
## 134 2017   2 118193      248288       20.35246      2.29          96.66
## 135 2017   3 137245      305403       19.41648      2.92          96.81
## 136 2017   4 114938      240141       18.78122      3.04          96.53
## 137 2017   5 123429      269067       18.79971      2.92          96.45
## 138 2017   6 127752      287979       18.20815      3.18          96.71
## 139 2017   7 122678      258557       17.85459      3.57          96.58
## 140 2017   8 125985      276108       17.80650      4.08          96.48
## 141 2017   9 116716      286400       17.80554      4.41          96.41
## 142 2017  10 123602      303514       18.71362      5.06          96.49
## 143 2017  11 141724      290569       18.98973      6.15          96.59
## 144 2017  12 159234      268772       19.10129      6.77          96.85
## 145 2018   1 109445      231088       19.02896      0.53          96.64
## 146 2018   2 109846      271228       18.61594      0.91          96.83
## 147 2018   3 119127      317398       18.65489      1.24          97.06
## 148 2018   4 109748      271048       18.34659      0.90          96.61
## 149 2018   5 115155      288659       19.45515      0.73          96.78
## 150 2018   6 120298      315130       20.31281      1.12          96.63
## 151 2018   7 115047      247367       19.09664      1.66          96.53
## 152 2018   8 119487      322779       18.80423      2.26          96.54
## 153 2018   9 114888      306009       19.03592      2.69          96.42
## 154 2018  10 117602      313471       19.09212      3.22          96.73
## 155 2018  11 134143      291018       20.25495      4.10          96.75
## 156 2018  12 142300      275962       20.15294      4.83          96.64
## 157 2019   1 111514      243652       19.22744      0.09          96.44
## 158 2019   2 104009      273173       19.18334      0.06          96.71
## 159 2019   3 117529      325703       19.24878      0.44          96.78
## 160 2019   4  98366      288756       19.01630      0.50          96.50
## 161 2019   5 102422      309017       19.09191      0.21          96.50
## 162 2019   6 106782      327454       19.26678      0.27          96.43
## 163 2019   7 106104      276818       19.06189      0.65          96.26
## 164 2019   8 108074      286075       19.58659      0.63          96.29
## 165 2019   9 100757      286806       19.60990      0.89          96.22
## 166 2019  10 107110      259158       19.36886      1.44          96.31
## 167 2019  11 124804      274845       19.30748      2.26          96.58
## 168 2019  12 130460      236848       19.16932      2.83          97.09
## 169 2020   1 104852      238749       18.81445      0.48          96.22
## 170 2020   2 104338      273634       18.77705      0.90          96.47
## 171 2020   3  87541      295199       21.97384      0.85          97.09
## 172 2020   4  34927       31183       24.23988     -0.17          95.31
## 173 2020   5  42034       15139       23.58032      0.22          95.81
## 174 2020   6  62861      198084       22.26918      0.76          94.51
## 175 2020   7  72921      264520       22.48030      1.43          94.65
## 176 2020   8  77120      264478       22.23107      1.82          94.74
## 177 2020   9  77808      257562       21.60516      2.06          94.87
## 178 2020  10  84351      280474       21.38085      2.68          95.29
## 179 2020  11  95707      287703       20.53330      2.76          95.65
## 180 2020  12 105603      275081       19.97817      3.15          96.21
## 181 2021   1  81657      223533       19.90262      0.86          95.30
## 182 2021   2  82863      213987       20.29248      1.50          95.60
## 183 2021   3  96319      256119       20.76205      2.34          96.13
## 184 2021   4  84287      234584       20.10944      2.67          95.35
## 185 2021   5  86710      242020       20.05320      2.88          96.01
## 186 2021   6  88688      234394       20.04272      3.43          95.98
## 187 2021   7  82157      202021       19.98552      4.04          95.62
## 188 2021   8  78235      212687       20.05125      4.24          95.67
## 189 2021   9  76930      195294       19.99092      4.88          95.82
## 190 2021  10  76640      224535       20.47244      5.76          96.05
## 191 2021  11  82829      240341       20.78256      6.97          96.34
## 192 2021  12  97420      227465       20.98530      7.36          96.49
## 193 2022   1  78585      216630       20.48354      0.59          96.29
## 194 2022   2  79598      201868       20.48437      1.43          96.26
## 195 2022   3  95199      262494       20.60089      2.43          97.03
## 196 2022   4  83459      241286       20.04452      2.98          96.97
## 197 2022   5  91215      244643       20.11331      3.17          96.73
## 198 2022   6  90368      237674       19.96650      4.04          96.65
## 199 2022   7  83137      210170       20.53081      4.81          96.57
## 200 2022   8  91124      248704       20.12613      5.54          96.47
##     porcentaje_desocu conf_consumidor
## 1                3.48         43.9415
## 2                3.75         43.9100
## 3                3.31         45.6029
## 4                3.20         44.7854
## 5                2.84         44.6508
## 6                3.26         44.2339
## 7                4.01         44.8674
## 8                3.87         45.0383
## 9                4.00         45.0604
## 10               3.82         44.3016
## 11               3.50         43.1883
## 12               3.32         44.7871
## 13               4.05         42.7412
## 14               4.05         42.3778
## 15               3.73         43.5677
## 16               3.51         43.4415
## 17               3.15         43.7534
## 18               3.28         43.0694
## 19               3.79         42.9629
## 20               3.83         43.9863
## 21               3.76         43.0238
## 22               3.77         41.2666
## 23               3.35         40.8568
## 24               3.11         42.8202
## 25               4.12         42.1822
## 26               3.89         41.2208
## 27               3.61         41.8964
## 28               3.48         40.1531
## 29               3.29         38.9120
## 30               3.37         37.6903
## 31               4.13         36.7035
## 32               4.06         37.2616
## 33               4.14         36.6558
## 34               4.17         34.2078
## 35               4.32         34.9500
## 36               4.02         34.9987
## 37               5.01         34.4084
## 38               5.24         33.4023
## 39               4.66         33.4728
## 40               5.06         34.6003
## 41               5.23         33.1933
## 42               4.98         34.2256
## 43               5.82         36.0502
## 44               6.15         34.5306
## 45               6.42         34.4993
## 46               5.67         32.6096
## 47               5.11         33.1707
## 48               4.73         33.9865
## 49               5.76         34.8020
## 50               5.28         34.2586
## 51               4.74         34.6691
## 52               5.35         35.0361
## 53               5.00         35.5938
## 54               4.92         36.7799
## 55               5.59         36.9279
## 56               5.42         37.2006
## 57               5.66         38.3303
## 58               5.48         37.4086
## 59               5.17         37.1774
## 60               4.94         38.1767
## 61               5.34         38.4624
## 62               5.34         38.4413
## 63               4.64         38.3233
## 64               5.13         37.6265
## 65               5.18         37.3597
## 66               5.40         38.7674
## 67               5.48         39.7537
## 68               5.71         38.9023
## 69               5.43         38.4823
## 70               4.99         37.7094
## 71               4.96         37.4238
## 72               4.51         37.7149
## 73               4.88         39.3604
## 74               5.28         38.9804
## 75               4.52         38.8750
## 76               4.86         40.2245
## 77               4.67         39.7323
## 78               4.75         39.7133
## 79               4.99         41.1478
## 80               5.33         40.7832
## 81               4.91         39.3550
## 82               5.03         39.6293
## 83               5.05         39.1214
## 84               4.40         41.1395
## 85               5.41         41.6134
## 86               4.75         39.6882
## 87               4.48         39.9339
## 88               4.96         39.8361
## 89               4.91         39.4471
## 90               5.00         38.7706
## 91               5.13         40.6562
## 92               5.18         40.5308
## 93               5.31         39.1825
## 94               5.01         38.0775
## 95               4.48         36.9465
## 96               4.27         37.3707
## 97               5.07         35.5508
## 98               4.66         35.7346
## 99               4.80         37.1351
## 100              4.85         37.6101
## 101              4.94         37.7513
## 102              4.82         37.9049
## 103              5.47         37.5518
## 104              5.19         37.4502
## 105              5.09         38.2199
## 106              4.78         37.6935
## 107              4.53         38.4760
## 108              3.76         38.6914
## 109              4.51         38.0625
## 110              4.33         37.4911
## 111              3.86         38.5052
## 112              4.31         37.8429
## 113              4.45         38.0317
## 114              4.41         39.1119
## 115              4.72         38.1319
## 116              4.68         37.3836
## 117              4.50         37.4490
## 118              4.55         37.8131
## 119              3.96         38.1829
## 120              3.96         38.3685
## 121              4.26         38.1815
## 122              4.14         36.7321
## 123              3.75         36.8144
## 124              3.80         36.7139
## 125              4.01         37.4848
## 126              3.92         38.3491
## 127              4.00         36.5060
## 128              3.98         35.6554
## 129              4.12         34.7550
## 130              3.67         35.0319
## 131              3.50         34.8752
## 132              3.38         35.4784
## 133              3.60         28.6679
## 134              3.34         31.5156
## 135              3.19         33.7951
## 136              3.47         34.9345
## 137              3.55         35.8733
## 138              3.29         36.0104
## 139              3.42         36.4886
## 140              3.52         36.5055
## 141              3.59         36.7879
## 142              3.51         36.4370
## 143              3.41         36.7168
## 144              3.15         36.3155
## 145              3.36         34.8018
## 146              3.17         34.1893
## 147              2.94         34.3367
## 148              3.39         35.6116
## 149              3.22         36.6479
## 150              3.37         37.1483
## 151              3.47         43.3411
## 152              3.46         43.0057
## 153              3.58         42.1327
## 154              3.27         42.5330
## 155              3.25         41.6750
## 156              3.36         44.8654
## 157              3.56         45.9299
## 158              3.29         47.8261
## 159              3.22         46.3411
## 160              3.50         45.4850
## 161              3.50         44.3235
## 162              3.57         43.6658
## 163              3.74         43.3177
## 164              3.71         43.8192
## 165              3.78         45.2995
## 166              3.69         44.0597
## 167              3.42         43.8407
## 168              2.91         43.7574
## 169              3.78         44.1205
## 170              3.53         43.3299
## 171              2.91         42.0593
## 172              4.69         32.2235
## 173              4.19         31.0682
## 174              5.49         31.9572
## 175              5.35         34.4173
## 176              5.26         35.0648
## 177              5.13         36.2820
## 178              4.71         37.8912
## 179              4.35         37.0767
## 180              3.79         38.7487
## 181              4.70         39.2114
## 182              4.40         38.6401
## 183              3.87         40.5816
## 184              4.65         42.5091
## 185              3.99         42.4227
## 186              4.02         44.3477
## 187              4.38         44.2934
## 188              4.33         42.4746
## 189              4.18         43.3421
## 190              3.95         43.8431
## 191              3.66         45.9354
## 192              3.51         44.8964
## 193              3.71         43.5909
## 194              3.74         42.9401
## 195              2.97         43.5603
## 196              3.03         44.3017
## 197              3.27         43.7823
## 198              3.35         43.2086
## 199              3.43         41.2699
## 200              3.53         40.2979

Dentro de la base de datos había dos renglones sin contenido, por lo tanto, se decicdió eliminarlo.

2 modelos diferentes de regresión lineal múltiple para predecir el desempeño de la industria automotriz

Correlación

corrplot(cor(bd_prediccion2), type="upper",order="hclust",addcoef.col="black")

summary(bd_prediccion2)
##       Año            Mes            Venta         Exportación    
##  Min.   :2006   Min.   : 1.00   Min.   : 34927   Min.   : 15139  
##  1st Qu.:2010   1st Qu.: 3.00   1st Qu.: 78543   1st Qu.:153219  
##  Median :2014   Median : 6.00   Median : 88580   Median :209160  
##  Mean   :2014   Mean   : 6.42   Mean   : 94178   Mean   :201664  
##  3rd Qu.:2018   3rd Qu.: 9.00   3rd Qu.:110134   3rd Qu.:243900  
##  Max.   :2022   Max.   :12.00   Max.   :192741   Max.   :327454  
##  Tipo.de.cambio    Inflación      porcentaje_ocu  porcentaje_desocu
##  Min.   :10.09   Min.   :-0.250   Min.   :93.58   Min.   :2.840    
##  1st Qu.:12.66   1st Qu.: 0.815   1st Qu.:95.06   1st Qu.:3.527    
##  Median :13.56   Median : 1.480   Median :95.88   Median :4.125    
##  Mean   :15.48   Mean   : 1.951   Mean   :95.76   Mean   :4.244    
##  3rd Qu.:19.10   3rd Qu.: 2.895   3rd Qu.:96.47   3rd Qu.:4.940    
##  Max.   :24.24   Max.   : 7.360   Max.   :97.16   Max.   :6.420    
##  conf_consumidor
##  Min.   :28.67  
##  1st Qu.:36.69  
##  Median :38.47  
##  Mean   :39.15  
##  3rd Qu.:42.59  
##  Max.   :47.83
Primeramente, se realizo un plot de correlación, con el fin de observar si las variables podrían tener relación entre las mismas variables y las demás, y lo que se puede notar, es que todos tienen el 100% de relación, y también se puede analizar que año y tipo de cambio también es relevante, así como, mes e inflación, venta y porcentaje de personas ocupadas, la exportación y el año, seguido por el tipo de cambio y de la expotación, entre otros.

Modelo de regresión 1

modelo_regresion1 <- lm(Exportación~Año+Mes+Tipo.de.cambio+Inflación+porcentaje_ocu+porcentaje_desocu+conf_consumidor,data=bd_prediccion2) 
summary(modelo_regresion1)
## 
## Call:
## lm(formula = Exportación ~ Año + Mes + Tipo.de.cambio + Inflación + 
##     porcentaje_ocu + porcentaje_desocu + conf_consumidor, data = bd_prediccion2)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -223340  -17123    3169   21264   87133 
## 
## Coefficients: (1 not defined because of singularities)
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -3.913e+07  3.447e+06 -11.352  < 2e-16 ***
## Año                1.835e+04  1.645e+03  11.151  < 2e-16 ***
## Mes                6.334e+03  1.054e+03   6.007 9.25e-09 ***
## Tipo.de.cambio    -1.280e+04  2.212e+03  -5.785 2.89e-08 ***
## Inflación         -1.022e+04  2.390e+03  -4.275 3.01e-05 ***
## porcentaje_ocu     2.763e+04  4.394e+03   6.289 2.09e-09 ***
## porcentaje_desocu         NA         NA      NA       NA    
## conf_consumidor   -2.142e+03  8.735e+02  -2.452   0.0151 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 36390 on 193 degrees of freedom
## Multiple R-squared:  0.6723, Adjusted R-squared:  0.6621 
## F-statistic: 65.99 on 6 and 193 DF,  p-value: < 2.2e-16
En este modelo, primero se realizó sin la variable año y mes, y se pudo observar que el tipo de cambio era la variable que más impactaba a la exportación, lo cual tiene sentido sabiendo que el tipo de cambio afecta a México y de igual manera al mundo, al devaluarse la moneda mexicana, es por eso que México es un gran exportador.
Por otro lado, al agregarle la variable año y mes, la mayoría de las variables, con excepción de porcentaje de personas desocupadas tenían los 3 asteriscos, por lo tanto se consideran variables impactantes.

Gráfica

effect_plot(modelo_regresion1,pred=Tipo.de.cambio,interval=TRUE)

Como se puede observar en la gráfica, la tendencia que sigue es negativa, esto quiere decir, que entre más cueste un dolar en pesos Méxicanos o que el tipo de cambio sea más bajo, menos se exporta.

Modelo de regresión 2

modelo_regresion2 <- lm(Venta~Año+Mes+Tipo.de.cambio+Inflación+porcentaje_ocu+porcentaje_desocu+conf_consumidor,data=bd_prediccion2)
summary(modelo_regresion2)
## 
## Call:
## lm(formula = Venta ~ Año + Mes + Tipo.de.cambio + Inflación + 
##     porcentaje_ocu + porcentaje_desocu + conf_consumidor, data = bd_prediccion2)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -66653  -9529   -696   9350  64461 
## 
## Coefficients: (1 not defined because of singularities)
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -7208005.1  1525100.0  -4.726 4.40e-06 ***
## Año                   2561.8      727.9   3.519 0.000539 ***
## Mes                   3468.4      466.5   7.434 3.34e-12 ***
## Tipo.de.cambio       -2373.5      978.9  -2.425 0.016241 *  
## Inflación            -3991.3     1057.4  -3.775 0.000213 ***
## porcentaje_ocu       23358.2     1943.9  12.016  < 2e-16 ***
## porcentaje_desocu         NA         NA      NA       NA    
## conf_consumidor      -1822.0      386.5  -4.714 4.63e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 16100 on 193 degrees of freedom
## Multiple R-squared:  0.5586, Adjusted R-squared:  0.5449 
## F-statistic: 40.71 on 6 and 193 DF,  p-value: < 2.2e-16
En este modelo de regresión, en lugar de exportaciones, se tomaron en cuenta las ventas de vehiculos, y de igual forma se grafico dos veces, la primera sin año y mes, lo cual nos daba como variable significativa la de porcentaje de población ocupada, y después agregando las variables año y mes, la mayoría de las variables tuvieron sentido con los 3 asteriscos, a excepción del porcentaje de población desocupada y el tipo de cambio.

Gráfica

effect_plot(modelo_regresion2,pred=porcentaje_ocu,interval=TRUE)

Aquí se observa que la tendencia de la gráfica es positiva, y lo que se graficó fueron las ventas y la variable significativa que fue porcentaje de población ocupada. Para interpretar de forma general, la gráfica quiere decir que entre más porcentaje de población cuente con trabajo, más ventas habrá.

Descripción de variables

Año - Año en el que se efectúo la exportación o venta.

Mes - Mes correspondiente al año en el que se efectúo la exportación o venta.

Venta (variable dependiente) - Venta en México de vehículos ligeros en unidades.

Exportación (variable dependiente) - Exportación en México de vehículos ligeros en unidades.

Tipo de cambio (variable independiente) - Registros historicos del dolar en México.

Inflación (variable independiente)- Inflación durante los años definidos.

porcentaje_ocu (variable independiente) - Porcentaje de la población ocupada.

porcentaje_desocu (variable independiente) - Porcentaje de la población desocupada.

conf_consumidor (variable independiente) - Confianza del consumidor en la industria automotriz en México.

Interpretación de los modelos de regresión:

Después de analizar ambos modelos de regresión, se puede destacar que para la variable dependiente de exportaciones, la variable independiente que más impacta es la de tipo.de.cambio, esta impacta de manera que la tendencia se vuelve negativa, dando a conocer que entre más aumente el peso mexicano con respecto al dolar, las exportaciones bajan.
Por otro lado, la variable dependiente de ventas, se ve afectada principalmente por la variable independiente de porcentaje de población ocupada, es decir, la que cuenta con vida laboral, esto hace sentido, ya que, si hay ingresos, es más probable que haya más ventas.
Por último, la tendencia de la gráfica es positiva, lo cual significa, que entre más grande el porcentaje de población ocupada, más elevadas ñas ventas.

K-Means Clustering

Identificar y visualizar las características de clústers

Paso 1. Instalar librerías

library(foreign)
library(dplyr)        
library(ggplot2)      
library(psych)        
library(corrplot)     
library(jtools)       
library(lmtest)       
library(car)          
library(factoextra)  
library(janitor)

Paso 2. Creación de Clústers

Cluster 1: Relación de variables de Edad y Número de días.

edad <-bajas 
edad<- subset(bajas,select = -c(genero, motivo_de_baja, puesto, salario_diario_imss, estado_civil))

#Normalizar variables
edad_norm<-scale(edad[1:2]) 

#Función fviz para la visualización de un Elbow Plot y así determinar el número de clusters.
fviz_nbclust(edad_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=4, linetype=2)+            
  labs(subtitle = "Elbow method")

Con esta gráfica podemos visualizar que el número óptimo de clústers son 4 (optimización).
#Visualizar clusters
edad_cluster<-kmeans(edad_norm,4)
edad_cluster
## K-means clustering with 4 clusters of sizes 80, 4, 45, 108
## 
## Cluster means:
##         edad     no_dias
## 1  0.1895854 -0.06199477
## 2  1.0620936  6.70675123
## 3  1.6004444 -0.10126073
## 4 -0.8466223 -0.16028417
## 
## Clustering vector:
##   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20 
##   1   1   4   4   1   3   1   1   3   4   4   1   4   1   1   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 
##   1   2   4   1   3   4   1   4   4   4   1   4   4   4   1   4   4   1   1   4 
##  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60 
##   4   1   4   4   4   4   4   4   3   3   3   2   4   3   4   4   3   4   4   4 
##  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80 
##   4   4   1   4   4   3   4   3   1   4   4   4   1   4   1   4   3   4   4   3 
##  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 
##   2   1   3   4   4   4   3   4   4   4   1   3   3   4   4   4   1   3   1   4 
## 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 
##   1   4   4   3   1   4   4   1   2   1   1   4   1   1   4   1   1   1   3   3 
## 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 
##   3   4   4   4   4   4   1   4   1   3   4   1   4   3   4   1   1   1   3   1 
## 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 
##   3   1   1   3   3   3   4   1   1   1   1   4   4   4   1   3   3   4   1   4 
## 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 
##   1   3   3   3   3   1   3   4   4   1   4   4   3   1   3   4   3   1   1   3 
## 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 
##   1   1   4   4   4   1   3   1   1   4   4   1   1   1   1   1   1   1   4   1 
## 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 
##   1   1   1   4   1   3   1   4   4   4   3   4   4   4   1   1   4   4   1   1 
## 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 
##   1   3   4   4   1   4   4   4   4   3   1   3   4   4   4   4   4 
## 
## Within cluster sum of squares by cluster:
## [1] 34.04210 16.13273 21.75900 16.53795
##  (between_SS / total_SS =  81.3 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"
#Visualizar resultados:
fviz_cluster(edad_cluster,data=edad_norm)

Los más jóvenes son los que menos días de trabajo laboran. Así como que los que más días laborales tienen, son los adultos desde los 27 años hasta los 61.

Cluster 2: Relación de variables de Edad y Salario Diario.

edad_salario <-bajas 
edad_salario<- subset(bajas,select = -c(genero,estado_civil,motivo_de_baja, puesto, no_dias))

#Normalizar variables
edad_salario_norm<-scale(edad_salario[1:2]) 

#Función fviz para la visualización de un Elbow Plot y así determinar el número de clusters.
fviz_nbclust(edad_salario_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=4, linetype=2)+            
  labs(subtitle = "Elbow method") 

Con esta gráfica podemos visualizar que el número óptimo de clústers son 4 (optimización).

Visualizar clusters y resultados:

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

La edad no tiene mucha influencia en el salario. Pues los colaboradores que se han dado de baja tienen un salario muy similar independientemente de su edad.

Cluster 3: Relación de variables de Salario Diario y Número de días.

dias_salario <-bajas 
dias_salario<- subset(bajas,select = -c(genero,estado_civil,motivo_de_baja, puesto, edad))

#Normalizar variables:
dias_salario_norm<-scale(dias_salario[1:2]) 

#Función fviz para la visualización de un Elbow Plot y así determinar el número de clusters.
fviz_nbclust(dias_salario_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=4, linetype=2)+            
  labs(subtitle = "Elbow method") 

Con esta gráfica podemos visualizar que el número óptimo de clústers son 4 (optimización).

Visualizar clusters y resultados:

dias_salario_cluster<-kmeans(dias_salario_norm,4)
dias_salario_cluster
## K-means clustering with 4 clusters of sizes 159, 5, 43, 30
## 
## Cluster means:
##      no_dias salario_diario_imss
## 1 -0.2906680          0.11501794
## 2  5.8798242          2.45410205
## 3  0.2579630          0.08136604
## 4  0.1908225         -1.13523673
## 
## 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   1   1   4   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   2   4   4   1   1   1   1   1   1   1   1   1   1   1   1   4   3   1   1 
##  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60 
##   3   3   1   1   1   1   1   1   1   1   1   2   3   1   1   1   1   1   1   4 
##  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80 
##   1   1   1   1   1   1   1   4   3   4   1   1   1   1   1   1   1   1   1   1 
##  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 
##   2   4   4   4   4   3   1   1   1   1   1   1   1   1   1   1   1   4   4   3 
## 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 
##   3   1   1   1   1   1   1   1   2   1   1   1   1   1   1   1   1   1   1   1 
## 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 
##   1   1   3   1   1   1   1   1   1   1   1   1   1   4   3   3   3   3   1   1 
## 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 
##   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   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   1   3   3   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1 
## 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 
##   3   3   3   3   3   3   3   3   3   3   3   3   3   1   3   3   3   3   3   3 
## 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 
##   3   3   3   3   1   1   1   1   3   1   1   1   1   1   1   1   1   1   1   1 
## 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 
##   1   3   3   1   1   1   1   1   1   1   1   1   1   1   1   1   1 
## 
## Within cluster sum of squares by cluster:
## [1]   1.009803 184.768864  12.851574  11.956632
##  (between_SS / total_SS =  55.4 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"
fviz_cluster(dias_salario_cluster,data=dias_salario_norm)

promedio_dias <- mean(bajas$no_dias)
promedio_dias
## [1] 79.47196
En este clúster podemos observar que por más antigüedad o días que labores en FORM, no hay mucha posibilidad de crecimiento laboral (económicamente hablando), pues según el cluster realizado, no influyen los días laborados con el salario diario.

Paso 3.Creación de Segmentos apartir de los Clústers:

Decidimos usar el Cluster 2 para generar la clasificación de variables y poder comparar con datos cualitativos.
#Añadir a la base de datos la columna de Clusters y su clasificación:
bajas1<-bajas
bajas1$Clusters<-edad_salario_cluster$cluster

library(dplyr)
library(factoextra) 

#Identificamos la clasificación de las distintas edades de los colaboradores.
bajas2<-bajas1 %>% group_by(Clusters) %>% dplyr::summarise(edad=max(edad)) %>% arrange(desc(edad))
bajas1$Cluster_Names<-factor(bajas1$Clusters,levels = c(1,2,3,4), 
                              labels=c("Outlier", "Joven", "Avanzada", "Adulta"))
bajas3 <- bajas1 %>% group_by(Cluster_Names) %>% dplyr::summarize(edad_años=max(edad), salario_imss=mean(salario_diario_imss),Count=n())
clusters<-as.data.frame(bajas3)
clusters
##   Cluster_Names edad_años salario_imss Count
## 1       Outlier        40     177.0462    76
## 2         Joven        32     500.0000     1
## 3      Avanzada        61     176.5644    45
## 4        Adulta        28     176.3151   115

Paso 5. Generación de gráficos:

Gráficos cuantitativos:

#Se realizó una gráfica para analizar el número de registros por cada segmento: 
ggplot(bajas3,aes(x=reorder(Cluster_Names,Count),y=Count,fill=Cluster_Names)) +
  geom_bar(stat="identity")

Los colaboradores que más bajas han presentado según la gráfica anterior son jóvenes, seguido por los adultos y después los colaboradores de edad avanzada.

Visualizar la edad por cada segmento:

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

Visualización de los máximos de cada segmento: Jóvenes (hasta los 28), Avanzada (Hasta los 61), Adulta (Hasta los 40) y el Outlier de 32.

Gráficas mixtas (Datos Cualitativos y Cuantitativos):

Gráfica de barras: (Clusters y Género)

ggplot(bajas1, aes(factor(Cluster_Names), fill = factor(genero))) +
  geom_bar(position = position_dodge2(preserve = "single")) 

Este gráfico nos dice que de cada segmento, hay más mujeres que se han dado de baja.

Gráfica de barras: (Clusters y Estado Civil)

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

Podemos visualizar que de de los jóvenes, la mayoría eran solteros, de los adultos había la misma cantidad de casados, soleros y en unión libre y en avanzados eran más solteros y casados. Más sin embargo, hay muy pocos colaboradores que se han dado de baja divorciados.

Gráfica de barras: (Clusters y Motivo de Baja)

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

Podemos observar que en el segmento de colaboradores jovenes, adultos y de edad avanzada, la mayor parte se ha dado de baja por faltas, siguiendo así por renuncia voluntaria.

Gráfica de pay: (Puesto)

table(bajas1$puesto)
## 
## ANALISTA DE NOMINAS /AUX DE R.H.            AYUDANTE DE EMBARQUES 
##                                1                                7 
##                 AYUDANTE DE MTTO             AYUDANTE DE SOLDADOR 
##                                1                                1 
##                 AYUDANTE GENERAL                           CHOFER 
##                              179                                1 
##                         CORTADOR                        COSTURERA 
##                                1                               11 
##                           DISEÑO             ENCARGADA DE CALIDAD 
##                                1                                1 
##                      FACTURACION             GUARDIA DE SEGURIDAD 
##                                1                                2 
##                INSPECTOR CALIDAD      JEFE DE SEGURIDAD E HIGIENE 
##                                4                                1 
##                         LIMPIEZA                        MARCADORA 
##                                1                                1 
##                     MATERIALISTA                   MONTACARGUISTA 
##                                2                                5 
##              PRACTICANTE DE MTTO                        RESIDENTE 
##                                1                                3 
##              SERVICIO AL CLIENTE                         SOLDADOR 
##                                1                               11
proporciones <- c(23, 179, 11, 11, 7, 5)
etiquetas <- c("Otros","Ayudante General", "Costurera", "Soldador", "Ayudante Embarques", "Montacarguista")
pct <- round(proporciones/sum(proporciones)*100)
etiquetas <- paste(etiquetas, pct)
etiquetas <- paste(etiquetas,"%",sep="")
pie(proporciones,labels = etiquetas,
    col=rainbow(length(etiquetas)),
    main="Puesto de los Ex-Colaboradores")

Gglluvial

bajas4 <-bajas1 %>% filter(Clusters==1 | Clusters==3) %>% arrange(Clusters)
library(ggalluvial)

ggplot(as.data.frame(bajas4),
       aes(y=no_dias, axis1= genero, axis2=estado_civil)) +
  geom_alluvium(aes(fill=Cluster_Names), width = 1/12) +
  geom_stratum(width = 1/12, fill = "black", color = "grey") +
  geom_label(stat = "stratum", aes(label = after_stat(stratum))) +
  scale_x_discrete(limits = c("Gender", "Marital Status"), expand = c(.05, .05)) +
  scale_fill_brewer(type = "qual", palette = "Set1") +
  ggtitle("FORM's Antigüedad de bajas por Genero y Estado Civil")

bajas5 <-bajas1 %>% filter(Clusters==2 | Clusters==4) %>% arrange(Clusters)
library(ggalluvial)

ggplot(as.data.frame(bajas5),
       aes(y=no_dias, axis1= genero, axis2=estado_civil)) +
  geom_alluvium(aes(fill=Cluster_Names), width = 1/12) +
  geom_stratum(width = 1/12, fill = "black", color = "grey") +
  geom_label(stat = "stratum", aes(label = after_stat(stratum))) +
  scale_x_discrete(limits = c("Gender", "Marital Status"), expand = c(.05, .05)) +
  scale_fill_brewer(type = "qual", palette = "Set1") +
  ggtitle("FORM's Antigüedad de bajas por Genero y Estado Civil")

Identificar y describir los hallazgos de los clústers:

1. La edad de los colaboradores que se han dado de baja, no tiene influencia en su salario.
2. El salario influye mucho en las bajas, pues todos los que se han dado de baja tienen un salario promedio menor a $180 diarios. Solamente un colaborador con un salario mayor ($500) se ha dado de baja.
3. Los días laborales (antigüedad) de un colaborador, no influyen con el salario, al menos con los que se han dado de baja. Lo que puede significar que la oportunidad de crecer económicamente en FORM de acuerdo a tu antigüedad es mínima.
4. La mayoría de los colaboradores que se han dado de baja, no han trabajado más de 3 meses (79 días) en FORM.
5. Los colaboradores que más bajas han presentado son jóvenes (de edades de los 18-28 años).
6. Independientemente de si los ex-colaboradores son jóvenes, adultos o mayores, de cada segmento las mujeres son las que han presentado más bajas.
7. FORM ha despedido más colaboradores de los que han renunciado, siendo la principal causa la “Baja por faltas”. Lo que puede significar que su proceso de contratación no es el más óptimo ya que terminan contratando personal que no era el adecuado para el puesto.

Identificación de Resultados Relevantes

A partir del análisis de las bases de datos de las diferentes áreas de la empresa FORM, identificar y describir los principales 6-8 hallazgos (meaningful insights).

FORM produce en promedio 3708.52 kilos de merma por mes.
Se produjo una mayor cantidad de piezas en el mes de agosto.
A un tiempo mayor de producción, FORM le invierte menos horas de calidad en las unidades producidas FORM tiene ubicada la mayor parte de su scrap en pre-producción.
Las unidades vendidas de carros aumentaron los últimos 5-10 años y se pronostica que haya un crecimiento positivo de los vehículos en circulación con el paso del tiempo.
Si incrementa el empleo en México, se predice que las ventas de vehículos ligeros incrementarán también.
El salario influye mucho en las bajas, pues todos los que se han dado de baja tienen un salario promedio menor a $180 diarios. Solamente un colaborador con un salario mayor ($500) se ha dado de baja.
FORM ha despedido más colaboradores de los que han renunciado, siendo la principal causa la “Baja por faltas”. Lo que puede significar que su proceso de contratación no es el más óptimo ya que terminan contratando personal que no era el adecuado para el puesto.

A partir del análisis de las bases de datos de las diferentes áreas de la empresa FORM, describir 3 sugerencias que le permitan al socio formador mejorar su proceso de captura, organización, y analítica de datos.

Se sugiere un data analysts, si no se tiene el presupuesto, se podría buscar un curso para empleados para poder llegar a crear bases de datos limpias y estandarizadas para cuando se necesite analizar o simplemente la búsqueda de la información.
Para la captura de datos, no se conoce cuantas personas son las que registran pero sería más sencillo y más organizado si se creara un equipo en los cuales se ocupen que los datos se registren de la manera correcta.
En el caso que no se pueda contratar un data analyst, agregarlo como meta de mediano plazo (dependiendo del presupuesto de FORM) para así poder llegar a ser una pyme pensando en su futuro y generar estrategias de crecimiento.

Business Intelligence

El Business Analytics es el método de análisis que las empresas utilizan para poder crear estrategias en torno al crecimiento e innovación tomando en cuenta su información interna y externa. Es una combinación de los campos de la gestión, los negocios y la ciencia de los datos.

Algunos de los principales objetivos del Business Analytics son determinar qué conjuntos de datos son útiles (organizarlos, filtrarlos y limpiarlos), examinarlos (establecer relaciones y clasificarlos) y ver cómo estos pueden aumentar los ingresos, la productividad, la eficiencia y el rendimiento organizacional. Asimismo, el Business Analytics ayuda a que los colaboradores puedan tomar decisiones más inteligentes (Business Intelligence) basadas en los datos analizados al utilizar diferentes herramientas como el análisis estadístico y predictivo.

La relación entre el “Business Intelligence” y el “Business Analytics” es que un experto en Business Intelligence, toma y procesa la información generada por los expertos en Business Analytics y la convierte en decisiones estratégicas para su negocio.

KPI

Según mis estudios en mercadotecnia, KPI, es técnicamente un tipo de indicador o métrica para poder medir diferentes estrategias o técnicas implementadas en un área del negocio o servicio, dependiendo del caso.

KPI’S para FORM

Colaboradores en crecimiento, en el área de negocio de Recursos Humanos de FORM, contando con todo este análisis e hallazgos implementar con precisión una estrategia para retener y evitar tanta rotación de personal. Siendo más específicos en los jóvenes, que son los que más se dan de baja.
Desperdicio cero, en el área de negocios de producción, se genera mucha scrap en la pre producción donde se puede realizar la estrategia de utilizarla o encontrar una maneras de reciclar generando un valor monetario como llegar a conectar con una empresa ecológica.
100% calidad, en el área de negocios de comercial y servicio a cliente, se comentó que FORM se especializa en personificar sus pedidos pero es importante crear esto con todos sus clientes para generar la retención de todos sus clientes y el poder conseguir más.

Propuestas

FORM genera cierta cantidad de merma creando un punto de oportunidad, oportunidades de negocios en el area de reciclaje, donde se obtenga un beneficio monetario a cambio.
Puebla es el estado donde más se produce cartón, se puede contactar empresas de Puebla productoras de cartón, al haber tanta oferta, lo más probable es que el precio de la materia prima disminuya.
Si se busca expandir y crear bodegas FORM tiene que buscar invertir en aquellas que se puedan situar en los estados o cerca de los estados situados en la región Norte y la región centro, ya que, es donde más producción de cartón existe.
“Tres principales líneas de negocio” Desarrollo de ingeniería de empaque, producción de empaques a la medida y administración 360 del empaque.
Debido a la gran cantidad de merma de cartón desechada por FORM se busca eliminar los desperdicios de tal manera que la empresa pueda disminuir sus gastos al aprovechar al máximo la materia prima adquirida, así como el impactar positivamente el medio ambiente al disminuir los desechos generados.

Estimación de Modelo de Regresión Logística Múltiple

Especificar y estimar 2 especificaciones diferentes de modelos de regresión logística mútiple.

Importar base de datos

library(foreign)
library(dplyr)        # data manipulation 
library(ggplot2)      # data visualization 
library(psych)        # functions for multivariate analysis 
library(corrplot)     # correlation plots
library(jtools)       # presentation of regression analysis 
library(lmtest)       # diagnostic checks - linear regression analysis 
library(car)          # diagnostic checks - linear regression analysis
library(factoextra)   # provides functions to extract and visualize the output of exploratory multivariate data analyses
library(ggfortify)    # data visualization tools for statistical analysis results
library(tidyverse)    # data manipulation and visualization
library(janitor)      # examining and cleaning datasets 
library(viridis)      
library(scales)       
library(lubridate) 

# file.choose()
rh_regresion <- read.csv("/Users/mayracampoyramos/Desktop/Analisis de Datos Concentracion/Reto/rh_regresion.csv")
summary(rh_regresion)
##       edad          genero            antiguedad         puesto         
##  Min.   :18.00   Length:349         Min.   : 0.0000   Length:349        
##  1st Qu.:24.00   Class :character   1st Qu.: 0.0000   Class :character  
##  Median :30.00   Mode  :character   Median : 0.0000   Mode  :character  
##  Mean   :32.69                      Mean   : 0.5501                     
##  3rd Qu.:40.00                      3rd Qu.: 0.0000                     
##  Max.   :73.00                      Max.   :12.0000                     
##  salario_diario  estado_civil       motivo_de_baja         bajas       
##  Min.   :144.4   Length:349         Length:349         Min.   :0.0000  
##  1st Qu.:176.7   Class :character   Class :character   1st Qu.:0.0000  
##  Median :180.7   Mode  :character   Mode  :character   Median :1.0000  
##  Mean   :178.3                                         Mean   :0.6762  
##  3rd Qu.:180.7                                         3rd Qu.:1.0000  
##  Max.   :500.0                                         Max.   :1.0000

Limpieza de datos

Técnica 1. Convertir las variables como factor o numero

rh_regresion$edad <- as.numeric(rh_regresion$edad)
rh_regresion$genero <- as.factor(rh_regresion$genero)
rh_regresion$antiguedad <- as.numeric(rh_regresion$antiguedad)
rh_regresion$puesto<- as.factor(rh_regresion$puesto)
rh_regresion$salario_diario <- as.numeric(rh_regresion$salario_diario)
rh_regresion$estado_civil<- as.factor(rh_regresion$estado_civil)
rh_regresion$bajas <- as.numeric(rh_regresion$bajas)
rh_regresion$motivo_de_baja<- as.factor(rh_regresion$motivo_de_baja)
summary(rh_regresion)
##       edad             genero      antiguedad                        puesto   
##  Min.   :18.00   FEMENINO :200   Min.   : 0.0000   AYUDANTE GENERAL     :246  
##  1st Qu.:24.00   MASCULINO:149   1st Qu.: 0.0000   COSTURERA            : 21  
##  Median :30.00                   Median : 0.0000   SOLDADOR             : 16  
##  Mean   :32.69                   Mean   : 0.5501   AYUDANTE DE EMBARQUES:  7  
##  3rd Qu.:40.00                   3rd Qu.: 0.0000   RESIDENTE            :  7  
##  Max.   :73.00                   Max.   :12.0000   CHOFER               :  6  
##                                                    (Other)              : 46  
##  salario_diario       estado_civil             motivo_de_baja     bajas       
##  Min.   :144.4   CASADO     :108   ABANDONO           :  1    Min.   :0.0000  
##  1st Qu.:176.7   DIVORCIADO :  6   BAJA POR FALTAS    :141    1st Qu.:0.0000  
##  Median :180.7   SOLTERO    :154   JUBILACION         :  1    Median :1.0000  
##  Mean   :178.3   UNION LIBRE: 81   RENUNCIA VOLUNTARIA: 85    Mean   :0.6762  
##  3rd Qu.:180.7                     TERMINO DE CONTRATO:  8    3rd Qu.:1.0000  
##  Max.   :500.0                     NA's               :113    Max.   :1.0000  
## 
En esta técnica de limpieza se vuelven a factor o números las variables para generar un estandarizar y generar un formato para que se vuelva más sencillo al realizar gráficos y manipular datos.

Técnica 2. Crear una categoría de referencia para la variable “bajas”:

rh_regresion$bajas<-as.factor(rh_regresion$bajas)
rh_regresion$bajas<-fct_recode(rh_regresion$bajas, "BAJA"="1","NO BAJA"="0")

replace the “outlier” of salario_diario with the median

rh_regresion$salario_diario<-replace(rh_regresion$salario_diario,rh_regresion$salario_diario>1000000,181)
rh_regresion$salario_diario[is.na(rh_regresion$salario_diario)]<-median(rh_regresion$salario_diario,na.rm=TRUE)

lets display data visualization plots so we can identify relevant insights from our rh_alt dataset

tapply(rh_regresion$salario_diario,
       list(rh_regresion$genero,rh_regresion$estado_civil), mean)
##             CASADO DIVORCIADO  SOLTERO UNION LIBRE
## FEMENINO  179.1338     180.68 175.5099    177.2578
## MASCULINO 180.2972     178.70 180.7174    177.3359

It is worth mentioning that k-means clustering analysis can only include quantitative variables

rh_edad_regresion<-rh_regresion 
rh_edad_regresion<- subset(rh_edad_regresion, select = -c(genero, estado_civil, antiguedad, puesto, motivo_de_baja, bajas))

The normalizing of a dataset (quantitative variables) using the mean value and standard deviation is performed by scale()

rh_edad_regresion_norm<-scale(rh_edad_regresion[1:2]) 

fviz_nbclust() helps to determine and visualize the optimal number of clusters

fviz_nbclust(rh_edad_regresion_norm, kmeans, method="wss")+ # wss method considers total within sum of square
  geom_vline(xintercept=5, linetype=2)+           # optimal number of clusters is computed with the default method = "euclidean"
  labs(subtitle = "Elbow method")  

visualize the clusters’ information. Briefly, you can detect how each dataset’s observation corresponds to a specific cluster.

edad_cluster1<-kmeans(rh_edad_regresion_norm,5)

the selection of 5 clusters approximately explains 85% of dataset’s variability.

visualize clustering results

fviz_cluster(edad_cluster1,data=rh_edad_regresion_norm)

lets add the estimated clusters’ information to the original dataset so we can interpret the results

rh_regresion1 <- rh_regresion
rh_regresion1$Clusters<-edad_cluster1$cluster

lets create a dataset so we can identify some characteristics of “edad” by cluster

rh_regresion2<-rh_regresion1 %>% group_by(Clusters) %>% summarise(edad=max(edad)) %>% arrange(desc(edad))

group the clusters by name

rh_regresion1$Cluster_Names<-factor(rh_regresion1$Clusters,levels = c(1,2,3,4,5), 
                              labels=c("Jóven","Adulta II","Jubilación","Avanzada","Adulta I"))

group the clusters by cluster names and Summarize the Columns

rh_regresion3<-rh_regresion1 %>% group_by(Cluster_Names) %>% dplyr::summarize(edad_años=max(edad), 
                                                             salario_imss=mean(salario_diario),
                                                             Count=n())

use table format to display the clusters information

clusters<-as.data.frame(rh_regresion3)
clusters
##   Cluster_Names edad_años salario_imss Count
## 1         Jóven        55     191.3548    73
## 2     Adulta II        29     151.0615    26
## 3    Jubilación        46     150.8006    16
## 4      Avanzada        33     180.3526   172
## 5      Adulta I        73     175.9756    62

Estimating Logistic Regression

No me deja descargar el paquete de “caret” por eso nos fuimos directo a la regresion

simple logistic regression

model specification

logit_model1<-glm(bajas~salario_diario, data=rh_regresion1, family=binomial(link='logit'))
summary(logit_model1)
## 
## Call:
## glm(formula = bajas ~ salario_diario, family = binomial(link = "logit"), 
##     data = rh_regresion1)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.5324  -1.4998   0.8862   0.8862   1.1371  
## 
## Coefficients:
##                 Estimate Std. Error z value Pr(>|z|)
## (Intercept)     1.092219   0.839733   1.301    0.193
## salario_diario -0.001993   0.004657  -0.428    0.669
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 439.52  on 348  degrees of freedom
## Residual deviance: 439.34  on 347  degrees of freedom
## AIC: 443.34
## 
## Number of Fisher Scoring iterations: 4

make predictions based in the regression results

# Which groups / categories do these probabilities refer to?
contrasts(rh_regresion1$bajas) 
##         BAJA
## NO BAJA    0
## BAJA       1
probabilities<-logit_model1 %>% predict(rh_regresion1,type="response")
predicted.classes<-ifelse(probabilities > 0.5, "bajas", "no_bajas")
# display the probabilities of dataset observations related to "bajas" & "no bajas"
head(probabilities) 
##         1         2         3         4         5         6 
## 0.6769964 0.6769964 0.6769964 0.6035916 0.6752681 0.6769964
# display the probabilities associated with "bajas"
head(predicted.classes) 
##       1       2       3       4       5       6 
## "bajas" "bajas" "bajas" "bajas" "bajas" "bajas"

lets assess the accuracy of the estimated logistic regression model1

rh_regresion1$logit_model1_prob <- predict(logit_model1, rh_regresion1, type="response")

rh_regresion1 <- rh_regresion1  %>% mutate(logit_model1_pred = 1*(logit_model1_prob > .50) + 0,
                         bajas_binary_1 = 1*(bajas == "BAJA") + 0)

rh_regresion1 <- rh_regresion1 %>% mutate(accurate_1=1*(logit_model1_pred == bajas_binary_1))
sum(rh_regresion1$accurate_1)/nrow(rh_regresion1) 
## [1] 0.6762178
# the calculated R2 indicates that approximately 73% of variation in the dependent variable is explained by the logit model specification. 

logistic regression plot displaying a S shaped curve

ggplot(rh_regresion1,aes(x=salario_diario, y=as.numeric(bajas)-1)) + 
  geom_point(alpha=.5) +
  stat_smooth(method="glm", se=FALSE, fullrange=TRUE, method.args=list(family=binomial)) + 
  ylab("Probability") + xlim(100,500)+
  labs(
    title = "Logistic Regression Model", 
    x = "Salario Diario",
    y = "Probability of Bajas"
  )

En este caso se puede observar que la probabilidad de bajas va disminuyendo mientras aumenta el salario. Indica que entre aumente el salario de los colaboradores, menor probabilidad que se den de baja.

multiple logistic regression

logit_model2<-glm(bajas~salario_diario+edad, data=rh_regresion1, family=binomial(link='logit'))
summary(logit_model2)
## 
## Call:
## glm(formula = bajas ~ salario_diario + edad, family = binomial(link = "logit"), 
##     data = rh_regresion1)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.7868  -1.2640   0.7392   0.8647   1.3440  
## 
## Coefficients:
##                 Estimate Std. Error z value Pr(>|z|)    
## (Intercept)     2.399657   0.917194   2.616 0.008889 ** 
## salario_diario -0.001686   0.004697  -0.359 0.719540    
## edad           -0.040739   0.010520  -3.872 0.000108 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 439.52  on 348  degrees of freedom
## Residual deviance: 423.90  on 346  degrees of freedom
## AIC: 429.9
## 
## Number of Fisher Scoring iterations: 4

lets assess the accuracy of the estimated logistic regression model2

rh_regresion1$logit_model2_prob <- predict(logit_model2, rh_regresion1, type="response")

rh_regresion1 <- rh_regresion1  %>% mutate(logit_model2_pred = 1*(logit_model2_prob > .50) + 0,
                                   bajas_binary_2 = 1*(bajas == "BAJA") + 0)

rh_regresion1 <- rh_regresion1 %>% mutate(accurate_2=1*(logit_model2_pred == bajas_binary_2))
sum(rh_regresion1$accurate_2)/nrow(rh_regresion1) 
## [1] 0.7106017
# the calculated R2 indicates that approximately 73% of variation in the dependent variable is explained by the logit model specification.  

logistic regression plot displaying a S shaped curve

ggplot(rh_regresion1,aes(x=edad, y=as.numeric(bajas)-1)) + 
  geom_point(alpha=.5) +
  stat_smooth(method="glm", se=FALSE, fullrange=TRUE, method.args = list(family=binomial)) + 
  ylab("Probability") + xlim(18,75)+
  labs(
    title = "Logistic Regression Model", 
    x = "Edad",
    y = "Probability of Bajas"
  )
## `geom_smooth()` using formula 'y ~ x'

En este caso se puede observar que la probabilidad de bajas va disminuyendo mientras sea mayor de edad. Se puede deducir que las personas que mas se dan de baja son los jovenes.

lets consider our estimated results from K-Means clustering analysis

logit_model3<-glm(bajas~salario_diario+Cluster_Names, data=rh_regresion1, family=binomial(link='logit'))
summary(logit_model3)
## 
## Call:
## glm(formula = bajas ~ salario_diario + Cluster_Names, family = binomial(link = "logit"), 
##     data = rh_regresion1)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.6848  -1.1777   0.7486   0.9225   1.3771  
## 
## Coefficients:
##                          Estimate Std. Error z value Pr(>|z|)  
## (Intercept)              1.246172   1.047794   1.189   0.2343  
## salario_diario          -0.003409   0.005306  -0.642   0.5206  
## Cluster_NamesAdulta II  -0.095257   0.526479  -0.181   0.8564  
## Cluster_NamesJubilación  0.056329   0.631468   0.089   0.9289  
## Cluster_NamesAvanzada    0.498461   0.308869   1.614   0.1066  
## Cluster_NamesAdulta I   -0.646322   0.363093  -1.780   0.0751 .
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 439.52  on 348  degrees of freedom
## Residual deviance: 425.23  on 343  degrees of freedom
## AIC: 437.23
## 
## Number of Fisher Scoring iterations: 4
rh_regresion1$logit_model3_prob <- predict(logit_model3, rh_regresion1, type="response")

rh_regresion1<- rh_regresion1  %>% mutate(logit_model3_pred = 1*(logit_model3_prob > .50) + 0,
                                   bajas_binary_3 = 1*(bajas == "BAJA") + 0)

rh_regresion1 <- rh_regresion1 %>% mutate(accurate_3=1*(logit_model3_pred == bajas_binary_3))
sum(rh_regresion1$accurate_3)/nrow(rh_regresion1) 
## [1] 0.6647564

Recomendaciones

Esto es un problema ya mencionado anteriormente sobre las bajas de los empleados de FORM, donde se recomienda implementar una estrategia para los colaboradores jóvenes, hablando con los de recursos humanos para poder identificar qué es lo que puede retener a los jóvenes.
Hablando de salario, entre más crezca el salario es menor la probabilidad de bajas, lo que se recomienda aquí no es subir de salarios para evitar bajas si no, crear un tipo de especie de rifa entre empleados,algo que tenga como un premio algo que los motive y será como un extra.

Referencias

(LEDU), E. E. (2018, September 12). Understanding K-means clustering in machine learning. Medium. Retrieved October 8, 2022, from https://towardsdatascience.com/understanding-k-means-clustering-in-machine-learning-6a6e67336aa1
K-means clustering in R programming. GeeksforGeeks. (2020, July 2). Retrieved October 9, 2022, from https://www.geeksforgeeks.org/k-means-clustering-in-r-programming/
Supervised and unsupervised learning in R programming. GeeksforGeeks. (2021, November 29). Retrieved October 9, 2022, from https://www.geeksforgeeks.org/supervised-and-unsupervised-clustering-in-r-programming/
Shadan, M. (n.d.). Unsupervised learning in R. R. Retrieved October 9, 2022, from https://rstudio-pubs-static.s3.amazonaws.com/273129_453610ca694541e1a2c5664bf7ccba1a.html
How to compute the euclidean distance between two arrays in R -. ProjectPro. (n.d.). Retrieved October 9, 2022, from https://www.projectpro.io/recipes/compute-euclidean-distance-between-two-arrays-r
LS0tCnRpdGxlOiA8c3BhbiBzdHlsZSA9ICJjb2xvcjpvcmFuZ2UiPiAiRXZpZGVuY2lhIDIiCmF1dGhvcjogIk1heXJhIENhbXBveSBSYW1vcyIKZGF0ZTogIjIwMjItMTAtMjEiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKPGltZyBzcmM9ICIvVXNlcnMvbWF5cmFjYW1wb3lyYW1vcy9Eb3dubG9hZHMvMTg3NjQ0NS5qcGVnIj4KCiMgKipSZWN1cnNvcyBIdW1hbm9zIENvbGFib3JhZG9yZXMqKiAKCiMjIyMgSW1wb3J0YXIgbGFzIGJhc2VzIGRlIGRhdG9zCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgZmlsZS5jaG9vc2UoKQpiZCA8LSByZWFkLmNzdiggIi9Vc2Vycy9tYXlyYWNhbXBveXJhbW9zL0Rlc2t0b3AvQW5hbGlzaXMgZGUgRGF0b3MgQ29uY2VudHJhY2lvbi9SZXRvL0ZPUk0gLSBSZWN1cnNvcyBIdW1hbm9zIC0gY29sYWJvcmFkb3Jlcy5jc3YiKQpsaWJyYXJ5KHBseXIpCiMgaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQpsaWJyYXJ5KGRwbHlyKQojIGluc3RhbGwucGFja2FnZXMoImphbml0b3IiKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KG5hbmlhcikKbGlicmFyeShIbWlzYykgICAgICAgICAKbGlicmFyeShwc3ljaCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoa25pdHIpCiMgaW5zdGFsbC5wYWNrYWdlcygicG9sbHN0ZXIiKQpsaWJyYXJ5KHBvbGxzdGVyKQpsaWJyYXJ5KGVwaURpc3BsYXkpCmxpYnJhcnkoZGVzY3IpCmxpYnJhcnkodGlkeXIpCgpjb2xhYm9yYWRvcmVzIDwtIGNsZWFuX25hbWVzKGJkKQpzdW1tYXJ5KGNvbGFib3JhZG9yZXMpCmBgYAoKIyMgKipMaW1waWV6YSwgVHJhbnNmb3JtYWNpw7NuLCB5IE9yZ2FuaXphY2nDs24gZGUgQmFzZXMgZGUgRGF0b3MqKgoKIyMjICrCv0N1w6FudGFzIHZhcmlhYmxlcyB5IGN1YW50b3MgcmVnaXN0cm9zIHRpZW5lIGxhIGJhc2UgZGUgZGF0b3M/KgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkZXNjcmliZURhdGEoY29sYWJvcmFkb3JlcyxoZWFkPTEsdGFpbD0xKQpgYGAKCiMjIyMjIEV4aXN0ZW4gMTAgdmFyaWFibGVzIHkgMTEzIHJlZ2lzdHJvcyBlbiBsYSBiYXNlIGRlIGRhdG9zLgoKIyMjICpBcGxpY2EgdMOpY25pY2FzIGRlIGxpbXBpZXphIGRlIGJhc2VzIGRlIGRhdG9zIHkgZXhwbMOtY2FsYXMgYnJldmVtZW50ZSwgwr9wb3IgcXXDqSByZWFsaXphc3RlIGVzYXMgdMOpY25pY2FzPyoKCiMjIyMgVMOpY25pY2EgMS4gQm9ycmFyIGNvbHVtbmFzLgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjb2xhYm9yYWRvcmVzIDwtIHN1YnNldChjb2xhYm9yYWRvcmVzLCBzZWxlY3QgPSAtYyhub19lbXBsZWFkbywgbm9tYnJlX2NvbXBsZXRvLCBmZWNoYV9hbHRhLCBtYW5vX2RlX29icmEpKQpgYGAKCiMjIyMjIEVzdGEgdMOpY25pY2Egc2UgcmVhbGl6w7MgeWEgcXVlIG5vIHNlIGNvbnNpZGVyYXJvbiBpbXBvcnRhbnRlcyBsYXMgY29sdW1uYXMgZGUgdmFyaWFibGVzLgoKIyMjIyBUw6ljbmljYSAyLiBSZWVtcGxlemFyIE5BcyBjb24gZWwgcHJvbWVkaW8gZW4gbGEgY29sdW1uYSBkZSAiU2FsYXJpbyBEaWFyaW8iCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNvbGFib3JhZG9yZXMkc2FsYXJpb19kaWFyaW9baXMubmEoY29sYWJvcmFkb3JlcyRzYWxhcmlvX2RpYXJpbyldPC1tZWFuKGNvbGFib3JhZG9yZXMkc2FsYXJpb19kaWFyaW8sIG5hLnJtID0gVFJVRSkKc3VtbWFyeSAoY29sYWJvcmFkb3JlcykKYGBgCgojIyMjIyBBbCByZWVtcGxhemFyIGxvcyBOQSAncyBjb24gZWwgcHJvbWVkaW8gbm9zIGF5dWRhIHBhcmEgbm8gY29udGFyIGNvbiByZWdpc3Ryb3MgbnVsb3MgeSBjb250YXIgY29uIGxvcyB2YWxvcmVzIG3DoXMgYWNlcnRhZG9zIHBvc2libGVzIGFsIHRpZW1wbyBkZSBhbmFsaXphcmxvcy4gCgojIyMjIEV4cG9ydGFyIGJhc2UgZGUgZGF0b3MgbGltcGlhCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CndyaXRlLmNzdihjb2xhYm9yYWRvcmVzLCBmaWxlPSJjb2xhYm9yYWRvcmVzX2JkX2xpbXBpYS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIyMgKkNsYXNpZmljYSBjYWRhIHZhcmlhYmxlIGVuIGN1YWxpdGF0aXZhLCBjdWFudGl0YXRpdmEgZGlzY3JldGEgbyBjdWFudGl0YXRpdmEgY29udGludWEqCiMjIyAqRWxpZ2UgbGEgZXNjYWxhIGRlIG1lZGljacOzbiBkZSBjYWRhIHZhcmlhYmxlLioKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KClZhcmlhYmxlIDwtYygiRWRhZCIsIkdlbmVybyIsICJBbnRpZ3VlZGFkIiwiUHVlc3RvIiwgIlNhbGFyaW8gRGlhcmlvIiwgIkVzdGFkbyBDaXZpbCIpClR5cGU8LWMoInF1YW50aXRhdGl2ZSAoZGlzY3JldGEpIiwgInF1YWxpdGF0aXZlIiwgInF1YW50aXRhdGl2ZSAoZGlzY3JldGEpIiwicXVhbGl0YXRpdmUiLCAicXVhbnRpdGF0aXZlIChjb250aW51YSkiLCAicXVhbGl0YXRpdmUiKQpNZWFzdXJlbWVudDwtYygiQcOxb3MiLCJOQSIsIk1lc2VzIHRyYWJhamFkb3MiLCJOQSIsICJDYW50aWRhZCBkZSBkaW5lcm8iLCJOQSIpCnRhYmxlPC1kYXRhLmZyYW1lKFZhcmlhYmxlLFR5cGUsTWVhc3VyZW1lbnQpCmtuaXRyOjprYWJsZSh0YWJsZSkKYGBgCgojIyAqKkFuw6FsaXNpcyBFeHBsb3JhdG9yaW8gZGUgbGFzIEJhc2VzIGRlIERhdG9zKioKCiMjIyAqQW7DoWxpc2lzIEVzdGFkw61zdGljbyoKCiMjIyMgKk1lZGlhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptZWRpYV9lZGFkIDwtIG1lYW4oY29sYWJvcmFkb3JlcyRlZGFkKQptZWRpYV9lZGFkCgptZWRpYV9hbnRpZ3VlZGFkIDwtIG1lYW4oY29sYWJvcmFkb3JlcyRhbnRpZ3VlZGFkKQptZWRpYV9hbnRpZ3VlZGFkCgptZWRpYV9zYWxhcmlvIDwtIG1lYW4oY29sYWJvcmFkb3JlcyRzYWxhcmlvX2RpYXJpbykKbWVkaWFfc2FsYXJpbwpgYGAKCiMjIyMgKk1lZGlhbmEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1lZGlhbmFfZWRhZCA8LSBtZWRpYW4oY29sYWJvcmFkb3JlcyRlZGFkKQptZWRpYW5hX2VkYWQKCm1lZGlhbmFfYW50aWd1ZWRhZCA8LSBtZWRpYW4oY29sYWJvcmFkb3JlcyRhbnRpZ3VlZGFkKQptZWRpYW5hX2FudGlndWVkYWQKCm1lZGlhbmFfc2FsYXJpbyA8LSBtZWRpYW4oY29sYWJvcmFkb3JlcyRzYWxhcmlvX2RpYXJpbykKbWVkaWFuYV9zYWxhcmlvIApgYGAKCiMjIyMgKk1vZGEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1vZGUgPC0gZnVuY3Rpb24oeCkgewogIHV4IDwtIHVuaXF1ZSh4KQogIHV4W3doaWNoLm1heCh0YWJ1bGF0ZShtYXRjaCh4LCB1eCkpKV0KfQptb2RhX2VkYWQgPC0gbW9kZShjb2xhYm9yYWRvcmVzJGVkYWQpCm1vZGFfZWRhZAoKbW9kYV9hbnRpZ3VlZGFkIDwtIG1vZGUoY29sYWJvcmFkb3JlcyRhbnRpZ3VlZGFkKQptb2RhX2FudGlndWVkYWQKCm1vZGFfc2FsYXJpbyA8LSBtb2RlKGNvbGFib3JhZG9yZXMkc2FsYXJpb19kaWFyaW8pCm1vZGFfc2FsYXJpbyAKYGBgCgojIyMjICpWYXJpYW56YSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdmFyaWFuemFfZWRhZCA8LXZhcihjb2xhYm9yYWRvcmVzJGVkYWQpCnZhcmlhbnphX2VkYWQKCnZhcmlhbnphX2FudGlndWVkYWQgPC12YXIoY29sYWJvcmFkb3JlcyRhbnRpZ3VlZGFkKQp2YXJpYW56YV9hbnRpZ3VlZGFkCgp2YXJpYW56YV9zYWxhcmlvIDwtdmFyKGNvbGFib3JhZG9yZXMkc2FsYXJpb19kaWFyaW8pCnZhcmlhbnphX3NhbGFyaW8KYGBgCgojIyMjICpEZXN2aWFjacOzbiBFc3TDoW5kYXIqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRlc3ZpYWNpb25fZWRhZCA8LSBzcXJ0KHZhcmlhbnphX2VkYWQpCmRlc3ZpYWNpb25fZWRhZAoKZGVzdmlhY2lvbl9hbnRpZ3VlZGFkIDwtIHNxcnQodmFyaWFuemFfYW50aWd1ZWRhZCkKZGVzdmlhY2lvbl9hbnRpZ3VlZGFkCgpkZXN2aWFjaW9uX3NhbGFyaW8gPC0gc3FydCh2YXJpYW56YV9zYWxhcmlvKQpkZXN2aWFjaW9uX3NhbGFyaW8KCmBgYAoKIyMjIyAqVGFibGEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClZhcmlhYmxlIDwtYygiRWRhZCIsIkFudGlndWVkYWQiLCJTYWxhcmlvIERpYXJpbyIpClByb21lZGlvIDwtYygiMzYiLCAiMS40MiIsIjE3OS4wOTgiKQpNb2RhIDwtYygiMzIiLCIwIiwiMTgwLjY4IikKTWVkaWFuYSA8LWMoIjM0IiwiMCIsIjE4MC42OCIpClZhcmlhbnphIDwtYygiMTY1LjAwNSIsIjYuMzUzIiwiNTg5LjcyMiIpCkRlc3ZpYWNpw7NuX0VzdMOhbmRhciA8LWMgKCIxMi44NDUiLCIyLjUyMCIsIjI0LjI4NCIpCnRhYmxhMSA8LWRhdGEuZnJhbWUoVmFyaWFibGUsUHJvbWVkaW8sIE1vZGEsIE1lZGlhbmEsIFZhcmlhbnphLCBEZXN2aWFjacOzbl9Fc3TDoW5kYXIpCnRhYmxhMQprbml0cjo6a2FibGUodGFibGExKQpgYGAKCiMjIyAqR3LDoWZpY28gY3VhbnRpdGF0aXZvOiAoSGlzdG9ncmFtYSk6KgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KU3VlbGRvIDwtICBjb2xhYm9yYWRvcmVzJHNhbGFyaW9fZGlhcmlvICAgCmhpc3QoU3VlbGRvLCBtYWluID0gIlN1ZWxkbyBkZSBsb3MgZW1wbGVhZG9zIiwgeWxhYiA9ICIjIGRlIGVtcGxlYWRvcyIsIGNvbCA9ICJsaWdodGJsdWUiKQpgYGAKCiMjIyMjIEVuIGVzdGEgZ3LDoWZpY2EgcG9kZW1vcyBvYnNlcnZhciBmw6FjaWxtZW50ZSBjb21vICoqbGEgbWF5b3IgcGFydGUgZGUgbG9zIGVtcGxlYWRvcyBnYW5hbiBtZW5vcyBkZSAyMDAgTVhOIHBlc29zIGFsIGTDrWEuKioKCiMjIyAqQmFyIFBsb3RzKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpoaXN0KGNvbGFib3JhZG9yZXMkZWRhZCwgZnJlcT1UUlVFLCBjb2w9InB1cnBsZSIsIG1haW49IkVkYWQgZW4gYcOxb3MgZGUgbG9zIENvbGFib3JhZG9yZXMgYWN0dWFsZXMiKQpgYGAKCiMjIyMjIENvbiBlc3RhcyBncsOgZmljYSBwb2RlbW9zIG9ic2VydmFyIHF1ZSBsb3MgY29sYWJvcmFkb3JlcyBhY3R1YWxlcyBlbiBwcm9tZWRpbyB0aWVuZW4gZW50cmUgMjAtNDAgYcOxb3MuIAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KGNvbGFib3JhZG9yZXMsIGFlcyh4PWdlbmVybywgeT1zYWxhcmlvX2RpYXJpbywgZmlsbD1nZW5lcm8pKSArIAogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyAKICBmYWNldF9ncmlkKH5lc3RhZG9fY2l2aWwpICsgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikKYGBgCgojIyMjIyBDb24gZXN0ZSBncsOgZmljbyBwb2RlbW9zIG9ic2VydmFyIHF1ZSBsb3MgcXVlIGVzdGFuIGNhc2Fkb3MgeSBzb2x0ZXJvcyBzdWVsZW4gZ2FuYXIgbcOgcyBkZSBsb3MgcXVlIGVzdGFuIGRpdm9yY2lhZG9zIHkgZW4gdW5pw7JuIGxpYnJlLiBBZGVtw6BzLCAqKmxvcyBob21icmVzIGNhc2Fkb3MgeSBsYXMgbXVqZXJlcyBzb2x0ZXJhcyBzb24gbG9zIHF1ZSBnYW5hbiBtw6BzLioqCgojIyMgKkRpc3BlcnNpb24gcGxvdCoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KGRhdGE9Y29sYWJvcmFkb3JlcywgbWFwcGluZyA9IGFlcyhlZGFkLCBzYWxhcmlvX2RpYXJpbykpICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBnZW5lcm8pKSArIHRoZW1lX2J3KCkKYGBgCgojIyMjIyBDb24gZXN0YXMgZ3LDoGZpY2FzIHBvZGVtb3Mgb2JzZXJ2YXIgcXVlIGVsIGNvbGFib3JhZG9yIHF1ZSBnYW5hIG3DoHMgZXMgbXVqZXIgeSBsYXMgcXVlIGdhbmFuIG1lbm9zIHRhbWJpw6huLiBTaW4gZW1iYXJnbywgKiplbCBwcm9tZWRpbyBkZSBzYWxhcmlvIGdhbmFkbyBwb3IgbG9zIGNvbGFib3JhZG9yZXMgZGUgdG9kYXMgbGFzIGVkYWRlcyBlcyBkZSBhcHJveGltYWRhbWVudGUgMTcwIHBlc29zIGRpYXJpb3MuKioKCiMgKipSZWN1cnNvcyBIdW1hbm9zIEJhamFzKiogCgojIyMjIEltcG9ydGFyIGxhcyBiYXNlcyBkZSBkYXRvcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIGZpbGUuY2hvb3NlKCkKYmFqYXMgPC0gcmVhZC5jc3YoIi9Vc2Vycy9tYXlyYWNhbXBveXJhbW9zL0Rlc2t0b3AvQW5hbGlzaXMgZGUgRGF0b3MgQ29uY2VudHJhY2lvbi9GT1JNIC0gUmVjdXJzb3MgSHVtYW5vcyAtIEJBSkFTIGV2aWRlbmNpYSkuY3N2IikKYmFqYXMgPC0gY2xlYW5fbmFtZXMoYmFqYXMpCnN1bW1hcnkoYmFqYXMpCmBgYAoKIyMgKipMaW1waWV6YSwgVHJhbnNmb3JtYWNpw7NuLCB5IE9yZ2FuaXphY2nDs24gZGUgQmFzZXMgZGUgRGF0b3MqKgoKIyMjICrCv0N1w6FudGFzIHZhcmlhYmxlcyB5IGN1YW50b3MgcmVnaXN0cm9zIHRpZW5lIGxhIGJhc2UgZGUgZGF0b3M/KgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkZXNjcmliZURhdGEoYmFqYXMsaGVhZD0xLHRhaWw9MSkKYGBgCgojIyMjIyBFeGlzdGVuIDI2IHZhcmlhYmxlcyB5IDMyNyByZWdpc3Ryb3MgZW4gbGEgYmFzZSBkZSBkYXRvcy4KCiMjIyAqQXBsaWNhIHTDqWNuaWNhcyBkZSBsaW1waWV6YSBkZSBiYXNlcyBkZSBkYXRvcyB5IGV4cGzDrWNhbGFzIGJyZXZlbWVudGUsIMK/cG9yIHF1w6kgcmVhbGl6YXN0ZSBlc2FzIHTDqWNuaWNhcz8qCgojIyMjIFTDqWNuaWNhIDEuQm9ycmFyIGNvbHVtbmFzLgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpiYWphcyA8LSBzdWJzZXQoYmFqYXMsIHNlbGVjdCA9IC1jKGFwZWxsaWRvcywgbm9tYnJlLCBmZWNoYV9kZV9uYWNpbWllbnRvLHJmYywgZmVjaGFfZGVfYWx0YSwgYmFqYSwgZGVwYXJ0YW1lbnRvLCBub19zZWd1cm9fc29jaWFsLCBmYWN0b3JfY3JlZF9pbmZvbmF2aXQsIG5fY3JlZGl0b19pbmZvbmF2aXQsIGx1Z2FyX2RlX25hY2ltaWVudG8sIGN1cnAsIGNhbGxlLCBudW1lcm9faW50ZXJubywgY29sb25pYSwgY29kaWdvX3Bvc3RhbCwgbXVuaWNpcGlvLCBlc3RhZG8sIHRhcmpldGFfY3VlbnRhKSkKYGBgCgojIyMjIyBFc3RhIHTDqWNuaWNhIHNlIHJlYWxpesOzIHlhIHF1ZSBubyBzZSBjb25zaWRlcmFyb24gaW1wb3J0YW50ZXMgbGFzIGNvbHVtbmFzIGRlIHZhcmlhYmxlcy4KCiMjIyMgVMOpY25pY2EgMi4gQ29udmVydGlyIGxhcyB2YXJpYWJsZXMgY29tbyBmYWN0b3IgbyBudW1lcm8KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KYmFqYXMkZWRhZDwtYXMubnVtZXJpYyhiYWphcyRlZGFkKQpiYWphcyRnZW5lcm88LWFzLmZhY3RvcihiYWphcyRnZW5lcm8pCmJhamFzJG1vdGl2b19kZV9iYWphPC1hcy5mYWN0b3IoYmFqYXMkbW90aXZvX2RlX2JhamEpCmJhamFzJG5vX2RpYXM8LWFzLm51bWVyaWMoYmFqYXMkbm9fZGlhcykKYmFqYXMkcHVlc3RvPC1hcy5mYWN0b3IoYmFqYXMkcHVlc3RvKQpiYWphcyRzYWxhcmlvX2RpYXJpb19pbXNzPC1hcy5udW1lcmljKGJhamFzJHNhbGFyaW9fZGlhcmlvX2ltc3MpCmJhamFzJGVzdGFkb19jaXZpbDwtYXMuZmFjdG9yKGJhamFzJGVzdGFkb19jaXZpbCkKc3VtbWFyeSAoYmFqYXMpCmBgYAoKIyMjIyMgRW4gZXN0YSB0w6ljbmljYSBkZSBsaW1waWV6YSBzZSB2dWVsdmVuIGEgZmFjdG9yIG8gbsO6bWVyb3MgbGFzIHZhcmlhYmxlcyBwYXJhIGdlbmVyYXIgdW4gZXN0YW5kYXJpemFyIHkgZ2VuZXJhciB1biBmb3JtYXRvIHBhcmEgcXVlIHNlIHZ1ZWx2YSBtw6FzIHNlbmNpbGxvIGFsIHJlYWxpemFyIGdyw6FmaWNvcyB5IG1hbmlwdWxhciBkYXRvcy4gCgojIyMjIFTDqWNuaWNhIDMuIFJlZW1wbGV6YXIgTkFzIGNvbiBlbCBwcm9tZWRpbyBlbiBsYSBjb2x1bW5hIGRlICJFZGFkIiwgIlNhbGFyaW8gRGlhcmlvIiB5ICJOw7ptZXJvIGRlIGTDrWFzIgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpiYWphcyRlZGFkW2lzLm5hKGJhamFzJGVkYWQpXTwtbWVhbihiYWphcyRlZGFkLCBuYS5ybSA9IFRSVUUpCmJhamFzJHNhbGFyaW9fZGlhcmlvX2ltc3NbaXMubmEoYmFqYXMkc2FsYXJpb19kaWFyaW9faW1zcyldPC1tZWFuKGJhamFzJHNhbGFyaW9fZGlhcmlvX2ltc3MsIG5hLnJtID0gVFJVRSkKYmFqYXMkbm9fZGlhc1tpcy5uYShiYWphcyRub19kaWFzKV08LW1lYW4oYmFqYXMkbm9fZGlhcywgbmEucm0gPSBUUlVFKQpzdW1tYXJ5IChiYWphcykKYGBgCgojIyMjIyBBbCByZWVtcGxhemFyIGxvcyBOQSAncyBjb24gZWwgcHJvbWVkaW8gbm9zIGF5dWRhIHBhcmEgbm8gY29udGFyIGNvbiByZWdpc3Ryb3MgbnVsb3MgeSBjb250YXIgY29uIGxvcyB2YWxvcmVzIG3DoXMgYWNlcnRhZG9zIHBvc2libGVzIGFsIHRpZW1wbyBkZSBhbmFsaXphcmxvcy4gCgojIyMgRXhwb3J0YXIgYmFzZSBkZSBkYXRvcyBsaW1waWEKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kd3JpdGUuY3N2KGJhamFzLCBmaWxlPSJyaF9iYWphc19iZF9saW1waWEuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKIyMjICpDbGFzaWZpY2EgY2FkYSB2YXJpYWJsZSBlbiBjdWFsaXRhdGl2YSwgY3VhbnRpdGF0aXZhIGRpc2NyZXRhIG8gY3VhbnRpdGF0aXZhIGNvbnRpbnVhKgojIyMgKkVsaWdlIGxhIGVzY2FsYSBkZSBtZWRpY2nDs24gZGUgY2FkYSB2YXJpYWJsZS4qCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpWYXJpYWJsZV9yaGIgPC1jKCJFZGFkIiwiR2VuZXJvIiwgIm1vdGl2b19kZSBiYWphIiwgIm5vX2RpYXMiLCAiUHVlc3RvIiwgIlNhbGFyaW8gRGlhcmlvIiwgIkVzdGFkbyBDaXZpbCIpClR5cGVfcmhiIDwtYyggInF1YW50aXRhdGl2ZSAoZGlzY3JldGEpIiwgInF1YWxpdGF0aXZlIiwicXVhbGl0YXRpdmUiLCAicXVhbnRpdGF0aXZlIChkaXNjcmV0YSkiLCJxdWFsaXRhdGl2ZSIsICJxdWFudGl0YXRpdmUgKGNvbnRpbnVhKSIsICJxdWFsaXRhdGl2ZSIpCk1lYXN1cmVtZW50X3JoYiA8LWMoIkHDsW9zIiwiTkEiLCAiTkEiLCAiRGlhcyB0cmFiYWphZG9zIiwiTkEiLCAiQ2FudGlkYWQgZGUgZGluZXJvIiwiTkEiKQp0YWJsZV9yaGIgPC1kYXRhLmZyYW1lKFZhcmlhYmxlX3JoYiAsVHlwZV9yaGIgLE1lYXN1cmVtZW50X3JoYiApCmtuaXRyOjprYWJsZSh0YWJsZV9yaGIpCmBgYAoKIyMgKipBbsOhbGlzaXMgRXhwbG9yYXRvcmlvIGRlIGxhcyBCYXNlcyBkZSBEYXRvcyoqCgojIyMgKkFuw6FsaXNpcyBFc3RhZMOtc3RpY28qCgojIyMjICpNZWRpYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWVkaWFfZWRhZDEgPC0gbWVhbihiYWphcyRlZGFkKQptZWRpYV9lZGFkMQoKbWVkaWFfYW50aWd1ZWRhZDEgPC0gbWVhbihiYWphcyRub19kaWFzKQptZWRpYV9hbnRpZ3VlZGFkMQoKbWVkaWFfc2FsYXJpbzEgPC0gbWVhbihiYWphcyRzYWxhcmlvX2RpYXJpbykKbWVkaWFfc2FsYXJpbzEKYGBgCgojIyMjICpNZWRpYW5hKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptZWRpYW5hX2VkYWQxIDwtIG1lZGlhbihiYWphcyRlZGFkKQptZWRpYW5hX2VkYWQxCgptZWRpYW5hX2FudGlndWVkYWQxIDwtIG1lZGlhbihiYWphcyRub19kaWFzKQptZWRpYW5hX2FudGlndWVkYWQxCgptZWRpYW5hX3NhbGFyaW8xIDwtIG1lZGlhbihiYWphcyRzYWxhcmlvX2RpYXJpbykKbWVkaWFuYV9zYWxhcmlvMQpgYGAKCiMjIyMgKk1vZGEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1vZGUgPC0gZnVuY3Rpb24oeCkgewogIHV4IDwtIHVuaXF1ZSh4KQogIHV4W3doaWNoLm1heCh0YWJ1bGF0ZShtYXRjaCh4LCB1eCkpKV0KfQptb2RhX2VkYWQxIDwtIG1vZGUoYmFqYXMkZWRhZCkKbW9kYV9lZGFkMQoKbW9kYV9hbnRpZ3VlZGFkMSA8LSBtb2RlKGJhamFzJG5vX2RpYXMpCm1vZGFfYW50aWd1ZWRhZDEKCm1vZGFfc2FsYXJpbzEgPC0gbW9kZShiYWphcyRzYWxhcmlvX2RpYXJpbykKbW9kYV9zYWxhcmlvMSAKYGBgCgojIyMjICpWYXJpYW56YSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdmFyaWFuemFfZWRhZDEgPC12YXIoYmFqYXMkZWRhZCkKdmFyaWFuemFfZWRhZDEKCnZhcmlhbnphX2FudGlndWVkYWQxIDwtdmFyKGJhamFzJG5vX2RpYXMpCnZhcmlhbnphX2FudGlndWVkYWQxCgp2YXJpYW56YV9zYWxhcmlvMSA8LXZhcihiYWphcyRzYWxhcmlvX2RpYXJpbykKdmFyaWFuemFfc2FsYXJpbzEKYGBgCgojIyMjICpEZXN2aWFjacOzbiBFc3TDoW5kYXIqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRlc3ZpYWNpb25fZWRhZDEgPC0gc3FydCh2YXJpYW56YV9lZGFkMSkKZGVzdmlhY2lvbl9lZGFkMQoKZGVzdmlhY2lvbl9hbnRpZ3VlZGFkMSA8LSBzcXJ0KHZhcmlhbnphX2FudGlndWVkYWQxKQpkZXN2aWFjaW9uX2FudGlndWVkYWQxCgpkZXN2aWFjaW9uX3NhbGFyaW8xIDwtIHNxcnQodmFyaWFuemFfc2FsYXJpbzEpCmRlc3ZpYWNpb25fc2FsYXJpbzEKYGBgCgojIyMjICpUYWJsYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KVmFyaWFibGVfcmhiMSA8LWMoIkVkYWQiLCJBbnRpZ3VlZGFkIiwiU2FsYXJpbyBEaWFyaW8iKQpQcm9tZWRpb19yaGIxIDwtYygiMzEuMDUiLCI3OS40NyIsIjE3Ny45ODUiKQpNb2RhX3JoYjEgPC1jKCIyMiIsIjc5IiwiMTgwLjY4IikKTWVkaWFuYV9yaGIxIDwtYygiMjkiLCIyMyIsIjE4MC42OCIpClZhcmlhbnphX3JoYjEgPC1jKCI5MS41MTMiLCI0NTQ3OS41OSIsIjUzOC42OTY5IikKRGVzdmlhY2nDs25fRXN0w6FuZGFyX3JoYjEgPC1jICgiOS41NjYiLCIyMTMuMjU5NCIsIjIzLjIwIikKdGFibGFfcmhiMSA8LWRhdGEuZnJhbWUgKFZhcmlhYmxlX3JoYjEsUHJvbWVkaW9fcmhiMSxNb2RhX3JoYjEsIE1lZGlhbmFfcmhiMSwgVmFyaWFuemFfcmhiMSxEZXN2aWFjacOzbl9Fc3TDoW5kYXJfcmhiMSApCnRhYmxhX3JoYjEKa25pdHI6OmthYmxlKHRhYmxhX3JoYjEpCmBgYAoKIyMjICpHcsOhZmljbyBjdWFsaXRhdGl2byoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdGFibGUoYmFqYXMkbW90aXZvX2JhamEpCnByb3BvcmNpb25lcyA8LSBjKDEsIDE0MSwgMSwgODcsIDgpCmV0aXF1ZXRhcyA8LSBjKCJBYmFuZG9ubyIsICJCYWphIHBvciBGYWx0YXMiLCAiSnViaWxhY2nDsm4iLCAiUmVudW5jaWEgVm9sdW50YXJpYSIsICJUZXJtaW5vIGRlIENvbnRyYXRvIikKcGN0IDwtIHJvdW5kKHByb3BvcmNpb25lcy9zdW0ocHJvcG9yY2lvbmVzKSoxMDApCmV0aXF1ZXRhcyA8LSBwYXN0ZShldGlxdWV0YXMsIHBjdCkKZXRpcXVldGFzIDwtIHBhc3RlKGV0aXF1ZXRhcywiJSIsc2VwPSIiKQpwaWUocHJvcG9yY2lvbmVzLGxhYmVscyA9IGV0aXF1ZXRhcywKICAgIGNvbD1yYWluYm93KGxlbmd0aChldGlxdWV0YXMpKSwKICAgIG1haW49Ik1vdGl2byBkZSBiYWphcyBkZSBsb3MgQ29sYWJvcmFkb3JlcyIpCmBgYAoKIyMjIyMgQ29uIGVzdGEgZ3LDoGZpY2EgcG9kZW1vcyBvYnNlcnZhciBxdWUgZWwgKiptb3Rpdm8gbcOgcyBjb23DuW4gZGUgYmFqYSBkZSBsb3MgY29sYWJvcmFkb3JlcyBoYW4gc2lkbyBwb3IgZGVzcGlkb3MgcG9yIGZhbHRhcyBjb24gdW4gNTklKiogeSBwb3IgcmVudW5jaWEgdm9sdW50YXJpYSBwb3IgdW4gMzclLgoKIyMjICpCYXIgUGxvdHMqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cmhpc3QoYmFqYXMkZWRhZCwgZnJlcT1UUlVFLCBjb2w9InBpbmsiLCBtYWluPSJFZGFkIGVuIGHDsW9zIGRlIGxvcyBFeC1Db2xhYm9yYWRvcmVzIikKYGBgCgojIyMjIyAqKkxvcyBjb2xhYm9yYWRvcmVzIHF1ZSBzZSBoYW4gZGFkbyBkZSBiYWphIGVuIHN1IG1heW9yaWEgdGllbmVuIGVudHJlIDIwIHkgMzAgYcOxb3MqKiwgc2llbmRvIGFzw6wgbG9zIHF1ZSBzZSB2YW4gbcOgcyBqw7J2ZW5lcy4KCiMgKipEZWxpdmVyeSBQbGFuKiogCgojIyMjIEltcG9ydGFyIGxhcyBiYXNlcyBkZSBkYXRvcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KG5hbmlhcikKbGlicmFyeShIbWlzYykgICAgICAgICAKbGlicmFyeShwc3ljaCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoamFuaXRvcikKbGlicmFyeShrbml0cikKbGlicmFyeShwb2xsc3RlcikKbGlicmFyeShlcGlEaXNwbGF5KQpsaWJyYXJ5KGRlc2NyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdnZWFzeSkKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHBhdGNod29yaykKCiMgZmlsZS5jaG9vc2UoKQpkZWxpdmVyeV9wbGFuPC0gcmVhZC5jc3YoIi9Vc2Vycy9tYXlyYWNhbXBveXJhbW9zL0Rlc2t0b3AvQW5hbGlzaXMgZGUgRGF0b3MgQ29uY2VudHJhY2lvbi9EZWxpdmVyeSBQbGFuIEZJTkFMIC0gRVFVSVBPIDQgLmNzdiIpCmBgYAoKIyMgKipMaW1waWV6YSwgVHJhbnNmb3JtYWNpw7NuLCB5IE9yZ2FuaXphY2nDs24gZGUgQmFzZXMgZGUgRGF0b3MqKgoKIyMjICrCv0N1w6FudGFzIHZhcmlhYmxlcyB5IGN1YW50b3MgcmVnaXN0cm9zIHRpZW5lIGxhIGJhc2UgZGUgZGF0b3M/KgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkZXNjcmliZURhdGEoZGVsaXZlcnlfcGxhbixoZWFkPTEsdGFpbD0xKQpgYGAKCiMjIyMjIExhIGJhc2UgZGUgZGF0b3MgY3VlbnRhIGNvbiAyNyB2YXJpYWJsZXMgeSAyMzEgcmVnaXN0cm9zLgoKIyMjICpBcGxpY2EgdMOpY25pY2FzIGRlIGxpbXBpZXphIGRlIGJhc2VzIGRlIGRhdG9zIHkgZXhwbMOtY2FsYXMgYnJldmVtZW50ZSwgwr9wb3IgcXXDqSByZWFsaXphc3RlIGVzYXMgdMOpY25pY2FzPyoKCiMjIyMgVMOpY25pY2EgMS4gQWNvbmRpY2lvbmFyIG5vbWJyZXMgYSBmb3JtYXRvIMOzcHRpbW8gcGFyYSBSCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRlbGl2ZXJ5X3BsYW4gPC0gY2xlYW5fbmFtZXMoZGVsaXZlcnlfcGxhbikKYGBgCgojIyMjIyBTZSBvcHRpbWl6YW4gbGFzIHZhcmlhYmxlcyBwYXJhIFIsIGdlbmVyYW5kbyB1biBlc3TDoW5kYXIuIAoKIyMjIyBUw6ljbmljYSAyLiBVbmlyIGxvcyBwZWRpZG9zIHByb2dyYW1hZG9zIGVuIHVuYSBzb2xhIGNvbHVtbmEuCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRlbGl2ZXJ5X3BsYW4gPC0gZGVsaXZlcnlfcGxhbiAlPiUgZHBseXI6OnJlbmFtZShjbGllbnRlPWNsaWVudGVfcGxhbnRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfanVuXzIxPWp1bmlvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJfanVsXzIxPWp1bGlvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIENfYWdvXzIxPWFnb3N0bywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEX3NlcF8yMT1zZXB0aWVtYnJlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVfb2N0XzIxPW9jdHVicmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl9ub3ZfMjE9bm92aWVtYnJlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdfZGljXzIxPWRpY2llbWJyZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBIX2VuZV8yMj1lbmVfMjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSV9mZWJfMjI9ZmViXzIyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSl9tYXJfMjI9bWFyXzIyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgS19hYnJfMjI9YWJyXzIyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgTF9tYXlfMjI9bWF5XzIyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgTV9qdW5fMjI9anVuXzIyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgTl9qdWxfMjI9anVsXzIyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgT19hZ29fMjI9YWdvXzIyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUF9zZXBfMjI9c2VwXzIyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUV9vY3RfMjI9b2N0dWJyZV8yMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJfbm92XzIyPW5vdl8yMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNfZGljXzIyPWRpY18yMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRfZW5lXzIzPWVuZV8yMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVfZmViXzIzPWZlYl8yMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZfbWFyXzIzPWZlYl8yMwogICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICApCmNvbG5hbWVzKGRlbGl2ZXJ5X3BsYW4pCmRlbGl2ZXJ5X3BsYW4gPC0gcGl2b3RfbG9uZ2VyKGRlbGl2ZXJ5X3BsYW4sIGNvbHM9NToxNCwgbmFtZXNfdG8gPSAiTWVzIiwgdmFsdWVzX3RvID0gIlVuaWRhZGVzIikKYGBgCgojIyMjIyBFbiBlc3RlIGNhc28gc2UgZGVjaWRpw7MgdW5pciB0b2RvcyBsb3MgcGVkaWRvcyBlbiB1bmEgY29sdW1uYSBwYXJhIGdlbmVyYXIgdW4gb3JkZW4gZGUgbG9zIG1lc2VzIHkgY2VycmFyIHVuYSBiYXNlIGRlIGRhdG9zIGVzdHJ1Y3R1cmFkYS4KCiMjIyMgVMOpY25pY2EgMy5FbGltaW5hY2nDs24gZGUgTkEncyAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGVsaXZlcnlwbGFuMSA8LSBmaWx0ZXIoZGVsaXZlcnlfcGxhbiwgVW5pZGFkZXM+MCkKYGBgCgojIyMjIyBTZSBlbGltaW5hbiBsb3MgTkEncyBlbiBsYSBiYXNlIGRlIGRhdG9zIHBhcmEgZWxpbWluYXIgcmVuZ29sZXMvY2xpZW50ZXMgc2luIHJlZ2lzdHJvcy4gIAoKIyMjIyBUw6ljbmljYSA0LkVsaW1pbmFjacOzbiBkZSB2YXJpYWJsZXMgaXJyZWxldmFudGVzLiAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGVsaXZlcnlwbGFuMiA8LSBkZWxpdmVyeXBsYW4xICAgICAgICAgCmRlbGl2ZXJ5cGxhbjIgPC0gc3Vic2V0IChkZWxpdmVyeXBsYW4xLCBzZWxlY3QgPSAtYyAocHJveWVjdG8sIGlkX29kb28sIGl0ZW0sIEtfYWJyXzIyLCBMX21heV8yMiwgTV9qdW5fMjIsTl9qdWxfMjIsT19hZ29fMjIsIFBfc2VwXzIyLCBRX29jdF8yMiwgUl9ub3ZfMjIsICBTX2RpY18yMiwgVF9lbmVfMjMsIFZfbWFyXzIzLCBtYXJfMjMsIHRvdGFsX21lc2VzKSkKc3VtbWFyeShkZWxpdmVyeXBsYW4yKQpgYGAKCiMjIyMjIEVuIGVzdGUgY2FzbywgZGFkbyBxdWUgcHJldmlhbWVudGUgc2UgdW5pZXJvbiAobWVyZ2UpIGxhcyB2YXJpYWJsZXMgZGUgbWVzLCBzb2xvIHNlIGNvbnNpZGVyYSBuZWNlc2FyaWEgbGEgdmFyaWFibGVzIGRlIGNsaWVudGUsIGZlY2hhIHkgVW5pZGFkZXMuCgojIyMgRXhwb3J0YXIgYmFzZSBkZSBkYXRvcyBsaW1waWEKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KRGVsaXZlcnlfUGxhbiA8LSBkZWxpdmVyeXBsYW4yCndyaXRlLmNzdihEZWxpdmVyeV9QbGFuLCBmaWxlID0gIkRkZWxpdmVyeXBsYW5fYmRfbGltcGlhLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIyAqQ2xhc2lmaWNhIGNhZGEgdmFyaWFibGUgZW4gY3VhbGl0YXRpdmEsIGN1YW50aXRhdGl2YSBkaXNjcmV0YSBvIGN1YW50aXRhdGl2YSBjb250aW51YSoKIyMjICpFbGlnZSBsYSBlc2NhbGEgZGUgbWVkaWNpw7NuIGRlIGNhZGEgdmFyaWFibGUuKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpWYXJpYWJsZV9kcGxhbjwtYygiVW5pZGFkZXMiLCAiTWVzIiwgImNsaWVudGUiKQpUeXBlX2RwbGFuIDwtYygicXVhbnRpdGF0aXZlIChkaXNjcmV0YSkiLCAicXVhbGl0YXRpdmUiLCJxdWFsaXRhdGl2ZSIpCk1lYXN1cmVtZW50X2RwbGFuIDwtYygicGllemFzIHF1ZSBzZSBlbnRyZWdhbiIsICJOQSIsICJOQSIpCnRhYmxlX2RwbGFuIDwtZGF0YS5mcmFtZShWYXJpYWJsZV9kcGxhbixUeXBlX2RwbGFuLE1lYXN1cmVtZW50X2RwbGFuKQprbml0cjo6a2FibGUodGFibGVfZHBsYW4pCmBgYAoKIyMgKipBbsOhbGlzaXMgRXhwbG9yYXRvcmlvIGRlIGxhcyBCYXNlcyBkZSBEYXRvcyoqCgojIyMgKkFuw6FsaXNpcyBFc3RhZMOtc3RpY28qCgojIyMjICpNZWRpYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KTWVkaWEgPC0gbWVhbihkZWxpdmVyeXBsYW4yJFVuaWRhZGVzKQpNZWRpYQpgYGAKCiMjIyMgKk1lZGlhbmEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Ck1lZGlhbmEgPC0gbWVkaWFuKGRlbGl2ZXJ5cGxhbjIkVW5pZGFkZXMpCk1lZGlhbmEKYGBgCgojIyMjICpNb2RhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptb2RlIDwtIGZ1bmN0aW9uKHgpIHsKICB1eCA8LSB1bmlxdWUoeCkKICB1eFt3aGljaC5tYXgodGFidWxhdGUobWF0Y2goeCwgdXgpKSldCn0KCk1vZGFfY2xpZW50ZXMgPC0gbW9kZShkZWxpdmVyeXBsYW4yJGNsaWVudGUpICAKTW9kYV9jbGllbnRlcwoKTW9kYV9tZXMgPC0gbW9kZShkZWxpdmVyeXBsYW4yJE1lcykgIApNb2RhX21lcwoKTW9kYV91bmlkYWRlcyA8LSBtb2RlKGRlbGl2ZXJ5cGxhbjIkVW5pZGFkZXMpICAKTW9kYV91bmlkYWRlcwpgYGAKCiMjIyMgKlZhcmlhbnphKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp2YXJpYW56YV91bmlkYWRlc19wcm9nIDwtIHZhcihkZWxpdmVyeXBsYW4yJFVuaWRhZGVzKQp2YXJpYW56YV91bmlkYWRlc19wcm9nCmBgYAoKIyMjIyAqRGVzdmlhY2nDs24gRXN0w6FuZGFyKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkZXN2aWFjaW9uX3VuaWRhZGVzX3Byb2c8LSBzcXJ0KHZhcmlhbnphX3VuaWRhZGVzX3Byb2cpCmRlc3ZpYWNpb25fdW5pZGFkZXNfcHJvZwpgYGAKCiMjIyMgKlRhYmxhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpWYXJpYWJsZV9kcGxhbjwtYygiVW5pZGFkZXMiLCAiTWVzIiwgImNsaWVudGUiKQpNZWRpYV9kcGxhbjwtYygiMzU4LjM3MjkiLCAiTkEiLCAiTkEiKQpNZWRpYW5hX2RwbGFuPC1jKCI4MCIsICJOQSIsICJOQSIpCk1vZGFfZHBsYW48LWMoTW9kYV91bmlkYWRlcywgTW9kYV9tZXMsIE1vZGFfY2xpZW50ZXMpClZhcmlhbnphX2RwbGFuPC1jKCIxMDA1Njc3IiwgIk5BIiwgIk5BIikKRGVzdmlhY2lvbl9Fc3RhbmRhcl9kcGxhbjwtYygiMTAwMi44MzQiLCAiTkEiLCAiTkEiKQp0YWJsZV9kcGxhbiA8LSBkYXRhLmZyYW1lKFZhcmlhYmxlX2RwbGFuLCBNZWRpYV9kcGxhbiwgTWVkaWFuYV9kcGxhbiwgTW9kYV9kcGxhbixWYXJpYW56YV9kcGxhbiwgRGVzdmlhY2lvbl9Fc3RhbmRhcl9kcGxhbikKa25pdHI6OmthYmxlKHRhYmxlX2RwbGFuKQpgYGAKCiMjIyAqRGlzcGVyc2lvbiBwbG90cyoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KGRlbGl2ZXJ5cGxhbjIsIGFlcyh4ID0gTWVzLCB5ID0gVW5pZGFkZXMpKSArIAogIGdlb21fcG9pbnQoc2hhcGU9MTksIHNpemU9MykgKyAKICBsYWJzKHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBVbmlkYWRlcyB5IE1lc2VzIixjYXB0aW9uID0iRk9STSBNZXJtYSIseD0iTWVzIiwgeT0iVW5pZGFkZXMiKSArIAogIHRoZW1lX2NsYXNzaWMoKQpgYGAKCiMjIyMjIEdyw6FmaWNhIGRlIGxvcyBhw7FvcyAyMDIxIHkgMjAyMiBlc3RhYmxlY2llbmRvIGN1YW50YXMgdW5pZGFkZXMgc2UgdmVuZGllcm9uIHBvciBtZXMsIHBvZGVtb3MgdmVyIHF1ZSBlbiAqKkp1bmlvIDIwMjEgdHV2aWVyb24gdW4gYXVtZW50byBkaXNtaW51eWVuZG8gZW4gbG9zIHByb3hpbW9zIG1lc2VzKiogeSB2b2x2aW8gYSBzdWJpciBlbiBlbCBhw7FvIDIwMjIgRXN0YSBncsOhZmljYSBub3MgYXl1ZGEgdmVyIGxhIHJlbGFjaW9uIHF1ZSB0aWVuZW4gbGFzIHVuaWRhZGVzIHkgbG9zIG1lc2VzIGRlIGHDsW8sIHBhcmEgYXNpIHBvZGVyIGVuY29udHJhciBwYXRyb25lcyBlbiBsYSBiYXNlIGRlIGRhdG9zIHBhcmEgdmVyIGVuIHF1ZSBtZXNlcyBzZSBoYWNlbiBtYXMgcGVkaWRvcy4KCiMjIyAqQmFyIFBsb3RzKgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KGRlbGl2ZXJ5cGxhbjIsYWVzKHg9IFVuaWRhZGVzLCB5PU1lcyxmaWxsPWNsaWVudGUpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKQpgYGAKCiMjIyMjIEVuIGdyw6FmaWNhIGFncmVnYW5kbyBxdWUgc2Ugb2JzZXJ2YW4gbGFzIHVuaWRhZGVzIHBsYW5lYWRhcyBwb3IgZW50cmVnYXIsIHNlIG9ic2VydmEgZGUgdW5hIG1hbmVyYSBtw6FzIGNsYXJhIGxhcyBlbnRyZWdhcyBwb3IgY2xpZW50ZS4gRG9uZGUgc2Ugb2JzZXJ2YSBxdWUgSGVsbGEgZXMgZWwgY2xpZW50ZSBjb24gbWF5b3IgZW50cmVnYSBkZSBwZWRpZG9zIGVuIEZPUk0uCgojICoqRGVsaXZlcnkgUGVyZm9ybWFuY2UqKiAKCgojIyMjIEltcG9ydGFyIGxhcyBiYXNlcyBkZSBkYXRvcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIGZpbGUuY2hvb3NlKCkKZGVsaXZlcnlwZXJmIDwtIHJlYWQuY3N2KCIvVXNlcnMvbWF5cmFjYW1wb3lyYW1vcy9Eb3dubG9hZHMvRk9STSAtIERlbGl2ZXJ5IFBlcmZvcm1hbmNlIEJEIEJVRU5BLmNzdiIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoamFuaXRvcikKcGVyZm9ybWFuY2UgPC0gY2xlYW5fbmFtZXMoZGVsaXZlcnlwZXJmKQpzdW1tYXJ5KHBlcmZvcm1hbmNlKQpgYGAKCiMjICoqTGltcGllemEsIFRyYW5zZm9ybWFjacOzbiwgeSBPcmdhbml6YWNpw7NuIGRlIEJhc2VzIGRlIERhdG9zKioKCiMjIyAqwr9DdcOhbnRhcyB2YXJpYWJsZXMgeSBjdWFudG9zIHJlZ2lzdHJvcyB0aWVuZSBsYSBiYXNlIGRlIGRhdG9zPyoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGVzY3JpYmVEYXRhKHBlcmZvcm1hbmNlLGhlYWQ9MSx0YWlsPTEpCmBgYAoKIyMjIyBMYSBiYXNlIGRlIGRhdG9zIGN1ZW50YSBjb24gOSB2YXJpYWJsZXMgeSAzMjQgcmVnaXN0cm9zCgojIyMgKkFwbGljYSB0w6ljbmljYXMgZGUgbGltcGllemEgZGUgYmFzZXMgZGUgZGF0b3MgeSBleHBsw61jYWxhcyBicmV2ZW1lbnRlLCDCv3BvciBxdcOpIHJlYWxpemFzdGUgZXNhcyB0w6ljbmljYXM/KgoKIyMjIyBUw6ljbmljYSAxLkJvcnJhciBjb2x1bW5hcy4KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGVyZm9ybWFuY2UgPC0gc3Vic2V0KHBlcmZvcm1hbmNlLCBzZWxlY3QgPSAtYyh4LCB4XzEsIHhfMiwgeF8zKSkKc3VtbWFyeShwZXJmb3JtYW5jZSkKYGBgCgojIyMjIyBFc3RhIHTDqWNuaWNhIHNlIHJlYWxpesOzIHlhIHF1ZSBubyBzZSBjb25zaWRlcmFyb24gaW1wb3J0YW50ZXMgbGFzIGNvbHVtbmFzIGRlIHZhcmlhYmxlcy4KCiMjIyMgVMOpY25pY2EgMi5Db252ZXJ0aXIgZGUgY2FyYWN0ZXIgYSBmZWNoYQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwZXJmb3JtYW5jZSRmZWNoYSA8LSBhcy5EYXRlKHBlcmZvcm1hbmNlJGZlY2hhLCBmb3JtYXQgPSAiJWQvJW0vJVkiKQp0aWJibGUocGVyZm9ybWFuY2UpCmBgYAoKIyMjIFTDqWNuaWNhIDMuQ29udmVydGlyIGRlIGNhcmFjdGVyIGEgZW50ZXJvIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwZXJmb3JtYW5jZSRwcmludGVsIDwtIHN1YnN0cihwZXJmb3JtYW5jZSRwcmludGVsLCBzdGFydCA9IDEsIHN0b3AgPSAyKQp0aWJibGUocGVyZm9ybWFuY2UpCnBlcmZvcm1hbmNlJHByaW50ZWwgPC0gYXMubnVtZXJpYyhwZXJmb3JtYW5jZSRwcmludGVsKQpzdHIocGVyZm9ybWFuY2UpCgpwZXJmb3JtYW5jZSRtYWhsZSA8LSBzdWJzdHIocGVyZm9ybWFuY2UkbWFobGUsIHN0YXJ0ID0gMSwgc3RvcCA9IDIpCnBlcmZvcm1hbmNlJG1haGxlIDwtIGFzLm51bWVyaWMocGVyZm9ybWFuY2UkbWFobGUpCgpwZXJmb3JtYW5jZSRtYWduYSA8LSBzdWJzdHIocGVyZm9ybWFuY2UkbWFnbmEsIHN0YXJ0ID0gMSwgc3RvcCA9IDIpCnBlcmZvcm1hbmNlJG1hZ25hIDwtIGFzLm51bWVyaWMocGVyZm9ybWFuY2UkbWFnbmEpCnN0cihwZXJmb3JtYW5jZSkKCnBlcmZvcm1hbmNlJHZhcnJvYyA8LSBzdWJzdHIocGVyZm9ybWFuY2UkdmFycm9jLCBzdGFydCA9IDEsIHN0b3AgPSAyKQpwZXJmb3JtYW5jZSR2YXJyb2MgPC0gYXMubnVtZXJpYyhwZXJmb3JtYW5jZSR2YXJyb2MpCnN0cihwZXJmb3JtYW5jZSkKYGBgCgojIyMjIyBFbiBlc3RhcyBkb3MgdMOpY25pY2FzIGRlIGxpbXBpZXphIHNlIHZ1ZWx2ZW4gYSBmYWN0b3IgbyBuw7ptZXJvcyBsYXMgdmFyaWFibGVzIHBhcmEgZ2VuZXJhciB1biBlc3RhbmRhcml6YXIgeSBnZW5lcmFyIHVuIGZvcm1hdG8gcGFyYSBxdWUgc2UgdnVlbHZhIG3DoXMgc2VuY2lsbG8gYWwgcmVhbGl6YXIgZ3LDoWZpY29zIHkgbWFuaXB1bGFyIGRhdG9zLiAKCiMjIyBUw6ljbmljYSA0LlJlZW1wbGF6YXIgTkFzIGNvbiBsYSBtZWRpYW5hIGRlIGNhZGEgdmFyaWFibGUKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc2FwcGx5KHBlcmZvcm1hbmNlLCBmdW5jdGlvbih4KSBzdW0oaXMubmEoeCkpKQoKcGVyZm9ybWFuY2UkZmVjaGFbaXMubmEocGVyZm9ybWFuY2UkZmVjaGEpXTwtbWVkaWFuKHBlcmZvcm1hbmNlJGZlY2hhLCBuYS5ybSA9IFRSVUUpCnBlcmZvcm1hbmNlJHByaW50ZWxbaXMubmEocGVyZm9ybWFuY2UkcHJpbnRlbCldPC1tZWRpYW4ocGVyZm9ybWFuY2UkcHJpbnRlbCwgbmEucm0gPSBUUlVFKQpwZXJmb3JtYW5jZSRtYWhsZVtpcy5uYShwZXJmb3JtYW5jZSRtYWhsZSldPC1tZWRpYW4ocGVyZm9ybWFuY2UkbWFobGUsIG5hLnJtID0gVFJVRSkKcGVyZm9ybWFuY2UkbWFnbmFbaXMubmEocGVyZm9ybWFuY2UkbWFnbmEpXTwtbWVkaWFuKHBlcmZvcm1hbmNlJG1hZ25hLCBuYS5ybSA9IFRSVUUpCnBlcmZvcm1hbmNlJHZhcnJvY1tpcy5uYShwZXJmb3JtYW5jZSR2YXJyb2MpXTwtbWVkaWFuKHBlcmZvcm1hbmNlJHZhcnJvYywgbmEucm0gPSBUUlVFKQpzdW1tYXJ5KHBlcmZvcm1hbmNlKQpgYGAKCiMjIyMjIEFsIHJlZW1wbGF6YXIgbG9zIE5BICdzIGNvbiBsYSBtZWRpYW5hIG5vcyBheXVkYSBwYXJhIG5vIGNvbnRhciBjb24gcmVnaXN0cm9zIG51bG9zIHkgY29udGFyIGNvbiBsb3MgdmFsb3JlcyBtw6FzIGFjZXJ0YWRvcyBwb3NpYmxlcyBhbCB0aWVtcG8gZGUgYW5hbGl6YXJsb3MuIAoKIyMjIEV4cG9ydGFyIGJhc2UgZGUgZGF0b3MgbGltcGlhCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CndyaXRlLmNzdihwZXJmb3JtYW5jZSwgZmlsZT0icGVyZm9ybWFuY2VfYmRfbGltcGlhLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIyAqQ2xhc2lmaWNhIGNhZGEgdmFyaWFibGUgZW4gY3VhbGl0YXRpdmEsIGN1YW50aXRhdGl2YSBkaXNjcmV0YSBvIGN1YW50aXRhdGl2YSBjb250aW51YSoKIyMjICpFbGlnZSBsYSBlc2NhbGEgZGUgbWVkaWNpw7NuIGRlIGNhZGEgdmFyaWFibGUuKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKVmFyaWFibGVfcGVyZm9ybWFuY2U8LWMoIkZlY2hhIiwiIFByaW50ZWwiLCJNYWhsZSIsICJNYWduYSIsICJWYXJyb2MiKQpUeXBlX3BlcmZvcm1hbmNlPC1jKCJxdWFsaXRhdGl2ZSIsICJxdWFudGlhdGl2ZSAoY29udGlub3VzKSIsICJxdWFudGl0YXRpdmUgKGNvbnRpbm91cykiLCAicXVhbnRpdGF0aXZlIChjb250aW5vdXMpIiwgInF1YW50aXRhdGl2ZSAoY29udGlub3VzKSIpCmVzY2FsYXNfcGVyZm9ybWFuY2UgPC0gYygiTkEiLCAiUGllemFzIEVudHJlZ2FkYXMiLCJQaWV6YXMgRW50cmVnYWRhcyIsIlBpZXphcyBFbnRyZWdhZGFzIiwiUGllemFzIEVudHJlZ2FkYXMiKQp0YWJsZV9wZXJmb3JtYW5jZSA8LSBkYXRhLmZyYW1lIChWYXJpYWJsZV9wZXJmb3JtYW5jZSwgVHlwZV9wZXJmb3JtYW5jZSwgZXNjYWxhc19wZXJmb3JtYW5jZSkKa25pdHI6OmthYmxlKHRhYmxlX3BlcmZvcm1hbmNlKQpgYGAKCiMjICoqQW7DoWxpc2lzIEV4cGxvcmF0b3JpbyBkZSBsYXMgQmFzZXMgZGUgRGF0b3MqKgoKIyMjICpBbsOhbGlzaXMgRXN0YWTDrXN0aWNvKgoKIyMjIyAqTWVkaWEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1lZGlhX3ByaW50ZWwgPC0gbWVhbihwZXJmb3JtYW5jZSRwcmludGVsKQptZWRpYV9wcmludGVsCgptZWRpYV9tYWhsZSA8LSBtZWFuKHBlcmZvcm1hbmNlJG1haGxlKQptZWRpYV9tYWhsZQoKbWVkaWFfbWFnbmEgPC0gbWVhbihwZXJmb3JtYW5jZSRtYWduYSkKbWVkaWFfbWFnbmEKCm1lZGlhX3ZhcnJvYyA8LSBtZWFuKHBlcmZvcm1hbmNlJHZhcnJvYykKbWVkaWFfdmFycm9jCmBgYAoKIyMjIyAqTWVkaWFuYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWVkaWFuYV9wcmludGVsIDwtIG1lZGlhbihwZXJmb3JtYW5jZSRwcmludGVsKQptZWRpYW5hX3ByaW50ZWwKCm1lZGlhbmFfbWFobGUgPC0gbWVkaWFuKHBlcmZvcm1hbmNlJG1haGxlKQptZWRpYW5hX21haGxlCgptZWRpYW5hX21hZ25hIDwtIG1lZGlhbihwZXJmb3JtYW5jZSRtYWduYSkKbWVkaWFuYV9tYWduYQoKbWVkaWFuYV92YXJyb2MgPC0gbWVkaWFuKHBlcmZvcm1hbmNlJHZhcnJvYykKbWVkaWFuYV92YXJyb2MKYGBgCgojIyMjICpNb2RhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptb2RlIDwtIGZ1bmN0aW9uKHgpIHsKICB1eCA8LSB1bmlxdWUoeCkKICB1eFt3aGljaC5tYXgodGFidWxhdGUobWF0Y2goeCwgdXgpKSldCn0KbW9kYV9wcmludGVsIDwtIG1vZGUocGVyZm9ybWFuY2UkcHJpbnRlbCkKbW9kYV9wcmludGVsCgptb2RhX21haGxlIDwtIG1vZGUocGVyZm9ybWFuY2UkbWFobGUpCm1vZGFfbWFobGUKCm1vZGFfbWFnbmEgPC0gbW9kZShwZXJmb3JtYW5jZSRtYWduYSkKbW9kYV9tYWduYQoKbW9kYV92YXJyb2MgPC0gbW9kZShwZXJmb3JtYW5jZSR2YXJyb2MpCm1vZGFfdmFycm9jCmBgYAoKIyMjIyAqVmFyaWFuemEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnZhcmlhbnphX3ByaW50ZWwgPC12YXIocGVyZm9ybWFuY2UkcHJpbnRlbCkKdmFyaWFuemFfcHJpbnRlbAoKdmFyaWFuemFfbWFobGUgPC12YXIocGVyZm9ybWFuY2UkbWFobGUpCnZhcmlhbnphX21haGxlCgp2YXJpYW56YV9tYWduYSA8LXZhcihwZXJmb3JtYW5jZSRtYWduYSkKdmFyaWFuemFfbWFnbmEKCnZhcmlhbnphX3ZhcnJvYyA8LXZhcihwZXJmb3JtYW5jZSR2YXJyb2MpCnZhcmlhbnphX3ZhcnJvYwpgYGAKCiMjIyMgKkRlc3ZpYWNpw7NuIEVzdMOhbmRhcioKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGVzdmlhY2lvbl9wcmludGVsIDwtIHNxcnQodmFyaWFuemFfcHJpbnRlbCkKZGVzdmlhY2lvbl9wcmludGVsCgpkZXN2aWFjaW9uX21haGxlIDwtIHNxcnQodmFyaWFuemFfbWFobGUpCmRlc3ZpYWNpb25fbWFobGUKCmRlc3ZpYWNpb25fbWFnbmEgPC0gc3FydCh2YXJpYW56YV9tYWduYSkKZGVzdmlhY2lvbl9tYWduYQoKZGVzdmlhY2lvbl92YXJyb2MgPC0gc3FydCh2YXJpYW56YV92YXJyb2MpCmRlc3ZpYWNpb25fdmFycm9jCmBgYAoKIyMjIyAqVGFibGEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClZhcmlhYmxlX3BlcmZvcm1hbmNlPC1jKCJGZWNoYSIsIiBQcmludGVsIiwiTWFobGUiLCAiTWFnbmEiLCAiVmFycm9jIikKUHJvbWVkaW9fcGVyZm9ybWFuY2UgPC1jKCJOQSIsIjAuMzM5IiwgIjIuMjA5IiwiMCIsICIwIikKTW9kYV9wZXJmb3JtYW5jZSA8LWMoIk5BIiwiMyIsIjAiLCIwIiwgIjAiKQpNZWRpYW5hX3BlcmZvcm1hbmNlIDwtYygiTkEiLCIwIiwiMyIsIjAiLCAiMCIpClZhcmlhbnphX3BlcmZvcm1hbmNlIDwtYygiTkEiLCIwLjQ0MSIsIjIuOTA5IiwiMCIsICIwIikKRGVzdmlhY2nDs25fRXN0w6FuZGFyX3BlcmZvcm1hbmNlIDwtYyAoIk5BIiwiMC42NjQiLCIxLjcwNSIsIjAiLCAiMCIpCnRhYmxhX3BlcmZvcm1hbmNlIDwtZGF0YS5mcmFtZShWYXJpYWJsZV9wZXJmb3JtYW5jZSxQcm9tZWRpb19wZXJmb3JtYW5jZSwgTW9kYV9wZXJmb3JtYW5jZSwgTWVkaWFuYV9wZXJmb3JtYW5jZSwgVmFyaWFuemFfcGVyZm9ybWFuY2UsIERlc3ZpYWNpw7NuX0VzdMOhbmRhcl9wZXJmb3JtYW5jZSkKa25pdHI6OmthYmxlKHRhYmxhX3BlcmZvcm1hbmNlKQpgYGAKCiMjIyAqRGlzcGVyc2lvbiBwbG90KgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QocGVyZm9ybWFuY2UsYWVzKHg9ZmVjaGEpKSsKICBnZW9tX2xpbmUoYWVzKHk9cHJpbnRlbCksY29sb3I9ImJsdWUiKSsKICBnZW9tX2xpbmUoYWVzKHk9bWFobGUpLGNvbG9yPSJvcmFuZ2UiKSsKICBnZW9tX2xpbmUoYWVzKHk9bWFnbmEpLGNvbG9yPSJncmVlbiIpKwogIGdlb21fbGluZShhZXMoeT12YXJyb2MpLGNvbG9yPSJncmVlbiIpKwogIGxhYnMoeD0iRmVjaGEiLHk9IlJldHJhc28gZW4gaG9yYXMiLCBjb2xvcj0iTGVnZW5kIikrCiAgZ2d0aXRsZSgiUmV0cmFzb3MgZGUgZW50cmVnYSBwb3IgY2xpZW50ZSIpCmBgYAoKIyMjIyMgRW4gZXN0YSBncsOhZmljYSBwb2RlbW9zIG9ic2VydmFyIHF1ZSBGT1JNIGNvbiAqKmxvcyBjbGllbnRlcyBNYWduYSB5IFZhcnJvYyBubyBwcmVzZW50YW4gaG9yYXMgZGUgcmV0cmFzbyBlbiBzdXMgcGVkaWRvcyoqLCBzaW4gZW1iYXJnbywgY29uICoqTWFobGUgeSBQcmludGVsIHNpIGhhbiBwcmVzZW50YWRvIHJldHJhc29zIGNvbnNpZGVyYWJsZXMgcHJpbmljaXBhbG1lbnRlIGRlbnRybyBkZWwgcHJpbWVyIHRyaW1lc3RyZSBkZWwgMjAyMioqLiBUZW5pZW5kbyByZXRyYXNvcyBkZSBoYXN0YSAyMCBob3Jhcy4KCiMgKipQcm9kdWNjacOzbioqIAoKIyMjIyBBbnRlcyBkZSBpbXBvcnRhciBsYSBiYXNlIGRlIGRhdG9zLCBzZSBvcHTDsyBwb3I6CiMjIyMjIDEuIFNlIGludGVncmFyb24gbG9zIGRhdG9zIGRlIEp1bGlvLCBBZ29zdG8geSBTZXB0aWVtYnJlLgojIyMjIyAyLiBTZSBpbmNvcnBvcsOzIHVuYSBudWV2YSBjb2x1bW5hIGRlICJGZWNoYSIuCiMjIyMjIDMuIFNvbG8gc2UgZGVqYXJvbiBsb3MgZGF0b3MgZGUgIlRpZW1wbyBkZSBNYXF1aW5hcyIKIyMjIyMgNC4gU2UgZWxpbWluYXJvbiBsb3MgTkFzIHkgdmFyaWFibGVzIG5vIG51bcOpcmljYXMgZGUgbGFzIGNvbHVtbmFzIGRlOiAiTMOhbWluYXMgcHJvY2VzYWRhcyIuCgojIyMjIEltcG9ydGFyIGxhcyBiYXNlcyBkZSBkYXRvcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojZmlsZS5jaG9vc2UoKQpiZDQgPC0gcmVhZC5jc3YoIi9Vc2Vycy9tYXlyYWNhbXBveXJhbW9zL0Rlc2t0b3AvQW5hbGlzaXMgZGUgRGF0b3MgQ29uY2VudHJhY2lvbi9FTUlfQ0FSVE9OLmNzdiIpCmxpYnJhcnkoamFuaXRvcikKcHJvZHVjY2lvbiA8LSBjbGVhbl9uYW1lcyhiZDQpCnN1bW1hcnkocHJvZHVjY2lvbikKCnByb2R1Y2Npb24gPC0gc3Vic2V0KHByb2R1Y2Npb24sc2VsZWN0ID0gLWMgKGlkX2Zvcm0sIHByb2R1Y3RvLCBocl9maW4sIGluaWNpb19zZXBfdXAsIGZpbl9pbmljaW9fZGVfc2VwX3VwLCBpbmljaW9fZGVfcHJvY2VzbywgZmluX2RlX3Byb2Nlc28sIHRpZW1wb19tYXRlcmlhbGVzKSkKc3VtbWFyeShwcm9kdWNjaW9uKQoKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KHBseXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShuYW5pYXIpCmxpYnJhcnkoSG1pc2MpICAgICAgICAgCmxpYnJhcnkocHN5Y2gpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGtuaXRyKQojIGluc3RhbGwucGFja2FnZXMoInBvbGxzdGVyIikKbGlicmFyeShwb2xsc3RlcikKbGlicmFyeShlcGlEaXNwbGF5KQpsaWJyYXJ5KGRlc2NyKQpsaWJyYXJ5KHRpZHlyKQpgYGAKCiMjICoqTGltcGllemEsIFRyYW5zZm9ybWFjacOzbiwgeSBPcmdhbml6YWNpw7NuIGRlIEJhc2VzIGRlIERhdG9zKioKCiMjIyAqwr9DdcOhbnRhcyB2YXJpYWJsZXMgeSBjdWFudG9zIHJlZ2lzdHJvcyB0aWVuZSBsYSBiYXNlIGRlIGRhdG9zPyoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGVzY3JpYmVEYXRhKHByb2R1Y2Npb24saGVhZD0xLHRhaWw9MSkKYGBgCgojIyMjIyBFeGlzdGVuIDE1IHZhcmlhYmxlcyB5IDE2MTQgcmVnaXN0cm9zIGVuIGxhIGJhc2UgZGUgZGF0b3MuCgojIyMgKkFwbGljYSB0w6ljbmljYXMgZGUgbGltcGllemEgZGUgYmFzZXMgZGUgZGF0b3MgeSBleHBsw61jYWxhcyBicmV2ZW1lbnRlLCDCv3BvciBxdcOpIHJlYWxpemFzdGUgZXNhcyB0w6ljbmljYXM/KgoKIyMjIyBUw6ljbmljYSAxLkNvbnZlcnRpciBhIGNhcmFjdGVyIGEgbnVtZXJpY28geSBkZSBmZWNoYQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwcm9kdWNjaW9uJHBpZXphc19wcm9nPC1hcy5udW1lcmljKHByb2R1Y2Npb24kcGllemFzX3Byb2cpICAgICAgICAgICAgICAgICAKcHJvZHVjY2lvbiR0bW9fbWluPC1hcy5udW1lcmljKHByb2R1Y2Npb24kdG1vX21pbikgICAgICAgICAgICAgICAgICAKcHJvZHVjY2lvbiRsYW1pbmFzX3Byb2Nlc2FkYXM8LWFzLm51bWVyaWMocHJvZHVjY2lvbiRsYW1pbmFzX3Byb2Nlc2FkYXMpICAgCnByb2R1Y2Npb24kdGllbXBvX2NhbGlkYWQ8LWFzLm51bWVyaWMocHJvZHVjY2lvbiR0aWVtcG9fY2FsaWRhZCkgCnByb2R1Y2Npb24kZmVjaGEgPC0gYXMuRGF0ZShwcm9kdWNjaW9uJGZlY2hhLCBmb3JtYXQgPSAiJWQvJW0vJVkiKQpzdW1tYXJ5KHByb2R1Y2Npb24pCmBgYAoKIyMjIyMgRW4gZXN0YSB0w6ljbmljYSBkZSBsaW1waWV6YSBzZSB2dWVsdmVuIGEgZmFjdG9yIG8gbsO6bWVyb3MgbGFzIHZhcmlhYmxlcyBwYXJhIGdlbmVyYXIgdW4gZXN0YW5kYXJpemFyIHkgZ2VuZXJhciB1biBmb3JtYXRvIHBhcmEgcXVlIHNlIHZ1ZWx2YSBtw6FzIHNlbmNpbGxvIGFsIHJlYWxpemFyIGdyw6FmaWNvcyB5IG1hbmlwdWxhciBkYXRvcy4gCgojIyMjIFTDqWNuaWNhIDIuUmVlbXBsYXphciBwb3IgZWwgcHJvbWVkaW8gbG9zIE5BwrRzIGRlIHRtb19taW4sIHRpZW1wb19jYWxpZGFkLCBwaWV6YXNfcHJvZwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwcm9kdWNjaW9uJHRtb19taW5baXMubmEocHJvZHVjY2lvbiR0bW9fbWluKV08LW1lYW4ocHJvZHVjY2lvbiR0bW9fbWluLCBuYS5ybSA9IFRSVUUpCnByb2R1Y2Npb24kdGllbXBvX2NhbGlkYWRbaXMubmEocHJvZHVjY2lvbiR0aWVtcG9fY2FsaWRhZCldPC1tZWFuKHByb2R1Y2Npb24kdGllbXBvX2NhbGlkYWQsIG5hLnJtID0gVFJVRSkKcHJvZHVjY2lvbiRwaWV6YXNfcHJvZ1tpcy5uYShwcm9kdWNjaW9uJHBpZXphc19wcm9nKV08LW1lYW4ocHJvZHVjY2lvbiRwaWV6YXNfcHJvZywgbmEucm0gPSBUUlVFKQpzdW1tYXJ5KHByb2R1Y2Npb24pCmBgYAoKIyMjIyMgQWwgcmVlbXBsYXphciBsb3MgTkEgJ3MgY29uIGVsIHByb21lZGlvIG5vcyBheXVkYSBwYXJhIG5vIGNvbnRhciBjb24gcmVnaXN0cm9zIG51bG9zIHkgY29udGFyIGNvbiBsb3MgdmFsb3JlcyBtw6FzIGFjZXJ0YWRvcyBwb3NpYmxlcyBhbCB0aWVtcG8gZGUgYW5hbGl6YXJsb3MuIAoKIyMjIyBUw6ljbmljYSAzLiBCb3JyYXIgbGFzIGxldHJhcyBkZSBhbGd1bm9zIHJlZ2lzdHJvcyBkZSAiUGllemFfUHJvZyIuCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnByb2R1Y2Npb24kcGllemFzX3Byb2cgPC0gc3RyX3JlcGxhY2UocHJvZHVjY2lvbiRwaWV6YXNfcHJvZywgIlthZWlvdUxBTT1OYkJzU10iLCAiIikKcHJvZHVjY2lvbiRwaWV6YXNfcHJvZyA8LSBhcy5pbnRlZ2VyKHByb2R1Y2Npb24kbGFtaW5hc19wcm9jZXNhZGFzKQpgYGAKCiMjIyMjIEVzdGEgdMOpY25pY2Egc2UgcmVhbGl6w7MgeWEgcXVlIG5vIGxvcyByZWdpc3Ryb3MgZGUgbGEgdmFyaWFibGUgcGllemFzIHByb2dyYW1hZGFzIGNvbnRlbmlhbiBlcnJvcmVzIGRlIGRlZG8uCgojIyMjIEV4cG9ydGFyIGxhIGJhc2UgZGUgZGF0b3MgbGltcGlhIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpiZF9Qcm9kdWNjaW9uX2xpbXBpYSA8LSBwcm9kdWNjaW9uCndyaXRlLmNzdihiZF9Qcm9kdWNjaW9uX2xpbXBpYSwgZmlsZT0iYmRfcHJvZHVjY2lvbl9saW1waWEuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgpgYGAKCiMjIyAqQ2xhc2lmaWNhIGNhZGEgdmFyaWFibGUgZW4gY3VhbGl0YXRpdmEsIGN1YW50aXRhdGl2YSBkaXNjcmV0YSBvIGN1YW50aXRhdGl2YSBjb250aW51YSoKIyMjICpFbGlnZSBsYSBlc2NhbGEgZGUgbWVkaWNpw7NuIGRlIGNhZGEgdmFyaWFibGUuKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKVmFyaWFibGVwIDwtYygiRmVjaGEiLCAiQ2xpZW50ZSIsICJwaWV6YXNfcHJvZyIsInRtb19taW4gIiwiZXN0YWNpb25fYXJyYW5xdWUiLCAibGFtaW5hc19wcm9jZXNhZGFzIiwgInRpZW1wb19jYWxpZGFkIikKVHlwZXA8LWMoInF1YWxpdGF0aXZlIiwgInF1YWxpdGF0aXZlIiwgInF1YW50aXRhdGl2ZSAoZGlzY3JldGEpIiwgInF1YW50aXRhdGl2ZSAoY29udGludWEpIiwgInF1YWxpdGF0aXZlIiwgInF1YW50aXRhdGl2ZSAoZGlzY3JldGEpIiwgInF1YW50aXRhdGl2ZSAoY29udGludW8pIikKZXNjYWxhc3AgPC0gYygiTkEiLCAiTkEiLCAicGllemFzIGFzaWduYWRhcyIsICJNaW51dG9zIiwgIk5BIiwgInBpZXphcyB0ZXJtaW5hZGFzIiwgImhvcmFzIiApCnRhYmxlcCA8LSBkYXRhLmZyYW1lIChWYXJpYWJsZXAsIFR5cGVwLCBlc2NhbGFzcCkKa25pdHI6OmthYmxlKHRhYmxlcCkKYGBgCgojIyAqKkFuw6FsaXNpcyBFeHBsb3JhdG9yaW8gZGUgbGFzIEJhc2VzIGRlIERhdG9zKioKCiMjIyAqQW7DoWxpc2lzIEVzdGFkw61zdGljbyoKCiMjIyMgKk1lZGlhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptZWRpYV9waWV6YXNfcHJvZzwtIG1lYW4ocHJvZHVjY2lvbiRwaWV6YXNfcHJvZykKbWVkaWFfcGllemFzX3Byb2cKCm1lZGlhX3Rtb19taW48LSBtZWFuKHByb2R1Y2Npb24kdG1vX21pbikKbWVkaWFfdG1vX21pbiAKCm1lZGlhX2xhbWluYXNfcHJvY2VzYWRhcyA8LSBtZWFuKHByb2R1Y2Npb24kbGFtaW5hc19wcm9jZXNhZGFzKQptZWRpYV9sYW1pbmFzX3Byb2Nlc2FkYXMKCm1lZGlhX3RpZW1wb19jYWxpZGFkPC0gbWVhbihwcm9kdWNjaW9uJHRpZW1wb19jYWxpZGFkKQptZWRpYV90aWVtcG9fY2FsaWRhZApgYGAKCiMjIyMgKk1lZGlhbmEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1lZGlhbl9waWV6YXNfcHJvZzwtIG1lZGlhbihwcm9kdWNjaW9uJHBpZXphc19wcm9nKQptZWRpYW5fcGllemFzX3Byb2cKCm1lZGlhbl90bW9fbWluPC0gbWVkaWFuKHByb2R1Y2Npb24kdG1vX21pbikKbWVkaWFuX3Rtb19taW4gCgptZWRpYW5fbGFtaW5hc19wcm9jZXNhZGFzIDwtIG1lZGlhbihwcm9kdWNjaW9uJGxhbWluYXNfcHJvY2VzYWRhcykKbWVkaWFfbGFtaW5hc19wcm9jZXNhZGFzCgptZWRpYW5fdGllbXBvX2NhbGlkYWQ8LSBtZWRpYW4ocHJvZHVjY2lvbiR0aWVtcG9fY2FsaWRhZCkKbWVkaWFuX3RpZW1wb19jYWxpZGFkCmBgYAoKIyMjIyAqTW9kYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbW9kZSA8LSBmdW5jdGlvbih4KSB7CiAgdXggPC0gdW5pcXVlKHgpCiAgdXhbd2hpY2gubWF4KHRhYnVsYXRlKG1hdGNoKHgsIHV4KSkpXQp9Cm1vZGFfcGllemFzX3Byb2cgPC0gbW9kZShwcm9kdWNjaW9uJHBpZXphc19wcm9nKQptb2RhX3BpZXphc19wcm9nCgptb2RhX3Rtb19taW4gPC0gbW9kZShwcm9kdWNjaW9uJHRtb19taW4pCm1vZGFfdG1vX21pbgoKbW9kYV9sYW1pbmFzX3Byb2Nlc2FkYXM8LSBtb2RlKHByb2R1Y2Npb24kbGFtaW5hc19wcm9jZXNhZGFzKQptb2RhX2xhbWluYXNfcHJvY2VzYWRhcwoKbW9kYV90aWVtcG9fY2FsaWRhZCA8LSBtb2RlKHByb2R1Y2Npb24kdGllbXBvX2NhbGlkYWQpCm1vZGFfdGllbXBvX2NhbGlkYWQKYGBgCgojIyMjICpWYXJpYW56YSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdmFyaWFuemFfcGllemFzX3Byb2cgPC12YXIocHJvZHVjY2lvbiRwaWV6YXNfcHJvZykKdmFyaWFuemFfcGllemFzX3Byb2cKCnZhcmlhbnphX3Rtb19taW4gPC12YXIocHJvZHVjY2lvbiR0bW9fbWluKQp2YXJpYW56YV90bW9fbWluCgp2YXJpYW56YV9sYW1pbmFzX3Byb2Nlc2FkYXM8LXZhcihwcm9kdWNjaW9uJGxhbWluYXNfcHJvY2VzYWRhcykKdmFyaWFuemFfbGFtaW5hc19wcm9jZXNhZGFzCgp2YXJpYW56YV90aWVtcG9fY2FsaWRhZCA8LXZhcihwcm9kdWNjaW9uJHRpZW1wb19jYWxpZGFkKQp2YXJpYW56YV90aWVtcG9fY2FsaWRhZApgYGAKCiMjIyMgKkRlc3ZpYWNpw7NuIEVzdMOhbmRhcioKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGVzdmlhY2lvbl9waWV6YXNfcHJvZzwtIHNxcnQodmFyaWFuemFfcGllemFzX3Byb2cpCmRlc3ZpYWNpb25fcGllemFzX3Byb2cKCmRlc3ZpYWNpb25fdG1vX21pbiA8LSBzcXJ0KHZhcmlhbnphX3Rtb19taW4pCmRlc3ZpYWNpb25fdG1vX21pbgoKZGVzdmlhY2lvbl9sYW1pbmFzX3Byb2Nlc2FkYXMgPC0gc3FydCh2YXJpYW56YV9sYW1pbmFzX3Byb2Nlc2FkYXMpCmRlc3ZpYWNpb25fbGFtaW5hc19wcm9jZXNhZGFzCgpkZXN2aWFjaW9uX3RpZW1wb19jYWxpZGFkIDwtIHNxcnQodmFyaWFuemFfdGllbXBvX2NhbGlkYWQpCmRlc3ZpYWNpb25fdGllbXBvX2NhbGlkYWQKYGBgCgojIyMgKlRhYmxhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpWYXJpYWJsZTIgPC1jKCJwaWV6YXNfcHJvZyIsInRtb19taW4gIiwgImxhbWluYXNfcHJvY2VzYWRhcyIsICJ0aWVtcG9fY2FsaWRhZCIpClByb21lZGlvMiA8LWMoIjE4MC4zMjMiLCAiMjIuMzcwIiwiMTAyLjAxIiwgIjAuODYiKQpNb2RhMiA8LWMoIjIwMCIsICIyNSIsIjAiLCAiMSIpCk1lZGlhbmEyIDwtYygiMTgwLjIzIiwiMjIuMzciLCIxMDIuMDEwNSIsICIxIikKVmFyaWFuemEyIDwtYygiMjE5NDAuODgiLCIxNDIuMzY4MiIsIjE4MDU2LjAzIiwgIjAuOTgxOTE2MyIpCkRlc3ZpYWNpw7NuX0VzdMOhbmRhcjIgPC1jICgiMTQ4LjEyNDUiLCIxMS45MzE4MSIsIjEzNC4zNzI3IiwgIjAuOTkwOTE2OSIpCnRhYmxhMiA8LWRhdGEuZnJhbWUoVmFyaWFibGUyLFByb21lZGlvMiwgTW9kYTIsIE1lZGlhbmEyLCBWYXJpYW56YTIsIERlc3ZpYWNpw7NuX0VzdMOhbmRhcjIpCnRhYmxhMgprbml0cjo6a2FibGUodGFibGEyKQpgYGAKCiMjIyAqR3LDoWZpY28gY3VhbnRpdGF0aXZvKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QocHJvZHVjY2lvbixhZXMoeD1mZWNoYSkpKwogIGdlb21fbGluZShhZXMoeT1waWV6YXNfcHJvZyksY29sb3I9ImJsdWUiKSsKICBsYWJzKHg9IkZlY2hhIix5PSJwaWV6YXMgcHJvZ3JhbWFkYXMiLCBjb2xvcj0iYmx1ZSIpKwogIGdndGl0bGUoIkdyYWZpY2EgZGUgbGFzIHBpZXphcyBwcm9ncmFtYWRhcyBwb3IgZmVjaGEiKQpgYGAKCiMjIyMjIEVuIGVzdGUgZ3LDoWZpY28gc2UgbXVlc3RyYW4gbG9zIDMgZGlmZXJlbnRlcyBtZXNlcyAoanVsaW8sIGFnb3N0bywgc2VwdCksIGRvbmRlIHNlIHB1ZWRlIHZlciBxdWUgaHVibyAqKm1heW9yIHByb2R1Y2Npb24gZGUgcGllemFzIHByb2dyYW1hZGFzIGVuIGxvIHF1ZSBmdWUgZGUganVsaW8gaGFjaWEgYWdvc3RvLioqCiAgCiMjIyAqQmFyIHBsb3RzKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QocHJvZHVjY2lvbiwgYWVzKHg9dG1vX21pbiwgeT1sYW1pbmFzX3Byb2Nlc2FkYXMpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBmaWxsPSJncmV5IikgKyBzY2FsZV9maWxsX2dyZXkoKSArIAogIGxhYnModGl0bGUgPSAiR3JhZmljbyBkZSBiYXJyYXMgZGUgbGFzIHBpZXphcyBwcm9ncmFtYWRhcyBkZW50cm8gZGVsIHRpZW1wbyBtaW5pbW8iLCAKICAgICAgIHggPSAidGllbXBvIG1pbmltbyIsIHkgPSAibGFtaW5hcyBwcm9jZXNhZGFzIikKYGBgCgojIyMjIyBFbiBlc3RhIGdyw6FmaWNvIHNlIHB1ZWRlIHZlciBxdWUgKiplbCB0aWVtcG8gbcOtbmltbyBkZW50cm8gZGUgbGFzIGzDoW1pbmFzIHByb2Nlc2FkYXMgbm8gc29icmVwYXNhIGxvcyA1MCoqIGxvIGN1YWwgZXMgdW5hIGJ1ZW5hIHNlw7FhbCBkZSBxdWUgbm8gaGF5IG11Y2hvIHRpZW1wbyBkZSBlc3BlcmEuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QocHJvZHVjY2lvbixhZXMoeD1yZW9yZGVyKHRtb19taW4sIHBpZXphc19wcm9nKSwgeT1waWV6YXNfcHJvZyxmaWxsPWNsaWVudGUpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKQpgYGAKCiMjIyMjIEVzdGEgZ3LDoWZpY2Egc2UgcHVlZGUgIHZpc3VhbGl6YXIgbG9zIGRhdG9zIG9idGVuaWRvcyBkZSBsbyBxdWUgZnVlcm9uIGxhcyBwaWV6YXMgcHJvZ3JhbWFkYXMgZGVudHJvIGRlbCB0aWVtcG8gbcOtbmltbyBkZW50cm8gZGUgbGEgcHJvZHVjY2lvbiwgZG9uZGUgZXN0YXMgdmFyaWFibGVzIHNlIHZlbiBkZW50cm8gZGUgbG9zIGNsaWVudGVzLiAgCgojIyMgKkRpc3BlcnNpb24gcGxvdHMqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdChwcm9kdWNjaW9uLCBhZXMoeD1waWV6YXNfcHJvZywgeT1jbGllbnRlKSkgKyAKICBnZW9tX3BvaW50KCkgCmBgYAoKIyMjIyBFbiBlc3RhIGdyw6FmaWNhIGRlIGRpc3BlcnNpb24gc2UgcHVlZGUgYXByZWNpYXIgdmlzdWFsbWVudGUgbGEgY2FudGlkYWQgZGUgcGllemFzIHF1ZSBzZSBkZW1hbmRhbiBwYXJhIGxvcyBkaWZlcmVudGVzIGNsaWVudGVzIHF1ZSB0aWVuZSBsYSBlbXByZXNhLCBkb25kZSBzZSBhcHJlY2lhIHF1ZSAqKlN0YWJpbHVzIDEgdG9tYSBsYSBkZWxhbnRlcmEuKiogCgojICoqTWVybWEqKiAKCiMjIyMgSW1wb3J0YXIgbGFzIGJhc2VzIGRlIGRhdG9zCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgZmlsZS5jaG9vc2UoKQptZXJtYTwtIHJlYWQuY3N2KCIvVXNlcnMvbWF5cmFjYW1wb3lyYW1vcy9EZXNrdG9wL0FuYWxpc2lzIGRlIERhdG9zIENvbmNlbnRyYWNpb24vUmV0by9GT1JNIC0gTWVybWEgMS5jc3YiKQoKYGBgCgojIyAqKkxpbXBpZXphLCBUcmFuc2Zvcm1hY2nDs24sIHkgT3JnYW5pemFjacOzbiBkZSBCYXNlcyBkZSBEYXRvcyoqCgojIyMgKsK/Q3XDoW50YXMgdmFyaWFibGVzIHkgY3VhbnRvcyByZWdpc3Ryb3MgdGllbmUgbGEgYmFzZSBkZSBkYXRvcz8qCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRlc2NyaWJlRGF0YShtZXJtYSxoZWFkPTEsdGFpbD0xKQpgYGAKIyMjIyMgRXhpc3RlbiAzIHZhcmlhYmxlcyB5IDYwIHJlZ2lzdHJvcyBlbiBsYSBiYXNlIGRlIGRhdG9zLgoKIyMjICpBcGxpY2EgdMOpY25pY2FzIGRlIGxpbXBpZXphIGRlIGJhc2VzIGRlIGRhdG9zIHkgZXhwbMOtY2FsYXMgYnJldmVtZW50ZSwgwr9wb3IgcXXDqSByZWFsaXphc3RlIGVzYXMgdMOpY25pY2FzPyoKCiMjIyMgT2JzZXJ2YWNpb25lcwojIyMjIyBObyBlc3RhbiBlbiBlbnRlcm9zIGxvcyBraWxvcyBkZSBtZXJtYQojIyMjIyBFeGlzdGVuIGZpbGFzIGluZWNlc2FyaWFzCgojIyMjIFTDqWNuaWNhIDE6IEVsaW1pbmFyIHRvdGFsZXMKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWVybWExPC0gbWVybWFbLWMoNSwxMiwxOSwyNSwzMSwzNiw0Miw1NCw1OSw2MCksXQpgYGAKCiMjIyMjIEVzdGEgdMOpY25pY2Egc2UgcmVhbGl6w7MgeWEgcXVlIG5vIHNlIGNvbnNpZGVyYXJvbiBpbXBvcnRhbnRlcyBsYXMgZmlsYXMgZGUgbG9zIHRvdGFsZXMuCgojIyMjIFTDqWNuaWNhIDI6IENvbnZlcnRpciBjYXJhY3RlciBhIGVudGVyby4KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWVybWExJEtpbG9zIDwtIGFzLmludGVnZXIobWVybWExJEtpbG9zKQpzdHIobWVybWExKQpgYGAKCiMjIyMjIFNlIG9wdGltaXphbiBsYXMgdmFyaWFibGVzIHBhcmEgUiwgZ2VuZXJhbmRvIHVuIGVzdMOhbmRhci4gCgojIyMjIEV4cG9ydGFyIGxhIGJhc2UgZGUgZGF0b3MgbGltcGlhIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptZXJtYV9saW1waWEgPC0gbWVybWExCndyaXRlLmNzdihtZXJtYV9saW1waWEsIGZpbGUgPSJtZXJtYV9iZF9saW1waWEuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKIyMjICpDbGFzaWZpY2EgY2FkYSB2YXJpYWJsZSBlbiBjdWFsaXRhdGl2YSwgY3VhbnRpdGF0aXZhIGRpc2NyZXRhIG8gY3VhbnRpdGF0aXZhIGNvbnRpbnVhKgojIyMgKkVsaWdlIGxhIGVzY2FsYSBkZSBtZWRpY2nDs24gZGUgY2FkYSB2YXJpYWJsZS4qCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClZhcmlhYmxlX21lcm1hPC1jKCJGZWNoYSIsICJNZXMiLCAiS2lsb3MiKQpUeXBlX21lcm1hPC1jKCJjdWFsaXRhdGl2YSAiLCAiY3VhbGl0YXRpdmEiLCAiY3VhbnRpdGF0aXZhIGRpc2NyZXRhIikKTWVhc3VyZW1lbnRfbWVybWEgPC1jKCJkaWEiLCAiTkEiLCAiY2FudGlkYWQiKQp0YWJsZV9tZXJtYTwtZGF0YS5mcmFtZShWYXJpYWJsZV9tZXJtYSxUeXBlX21lcm1hLCBNZWFzdXJlbWVudF9tZXJtYSkKa25pdHI6OmthYmxlKHRhYmxlX21lcm1hKQpgYGAKCiMjICoqQW7DoWxpc2lzIEV4cGxvcmF0b3JpbyBkZSBsYXMgQmFzZXMgZGUgRGF0b3MqKgoKIyMjICpBbsOhbGlzaXMgRXN0YWTDrXN0aWNvKgoKIyMjIyAqTWVkaWEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1lZGlhX2tpbG9zIDwtIG1lYW4obWVybWExJEtpbG9zKQptZWRpYV9raWxvcwpgYGAKIyMjIyMgTGFzIHZhcmlhYmxlcyBkZSBmZWNoYSB5IGVsIG1lcyBubyBwdWVkZSB0ZW5lciBtZWRpYQoKIyMjIyAqTWVkaWFuYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWVkaWFuYV9raWxvcyA8LSBtZWRpYW4obWVybWExJEtpbG9zKQptZWRpYW5hX2tpbG9zCmBgYAojIyMjIyBMYXMgdmFyaWFibGVzIGRlIGZlY2hhIHkgZWwgbWVzIG5vIHB1ZWRlIHRlbmVyIG1lZGlhbmEKCiMjIyMgKk1vZGEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1vZGUgPC0gZnVuY3Rpb24gKHgpIHsKICB1eCA8LSB1bmlxdWUoeCkKICB1eCBbd2hpY2gubWF4KHRhYnVsYXRlKG1hdGNoKHgsdXgpKSldCn0KCm1vZGVfZmVjaGEgPC0gbW9kZShtZXJtYTEkRmVjaGEpCm1vZGVfZmVjaGEKCm1vZGVfbWVzIDwtIG1vZGUobWVybWExJE1lcykKbW9kZV9tZXMKCm1vZGVfa2lsb3MgPC0gbW9kZShtZXJtYTEkS2lsb3MpCm1vZGVfa2lsb3MKYGBgCgojIyMjICpWYXJpYW56YSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdmFyaWFuemFfa2lsb3MgPC0gdmFyKG1lcm1hMSRLaWxvcykKdmFyaWFuemFfa2lsb3MgCmBgYAoKIyMjIyAqRGVzdmlhY2nDs24gRXN0w6FuZGFyKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkZXN2aWFjaW9uZXN0YW5kYXJfa2lsb3MgPC0gc3FydCh2YXJpYW56YV9raWxvcykKZGVzdmlhY2lvbmVzdGFuZGFyX2tpbG9zCmBgYAoKIyMjICpUYWJsYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KVmFyaWFibGVfbWVybWE8LWMoIkZlY2hhIiwgIk1lcyIsICJLaWxvcyIpCk1lZGlhX21lcm1hPC1jKCJOQSIsICJOQSIsIG1lZGlhX2tpbG9zKQpNZWRpYW5hX21lcm1hPC1jKCJOQSIsICJOQSIsIG1lZGlhbmFfa2lsb3MpCk1vZGFfbWVybWE8LWMobW9kZV9mZWNoYSwgbW9kZV9tZXMsIG1vZGVfa2lsb3MpClZhcmlhbnphX21lcm1hPC1jKCJOQSIsICJOQSIsdmFyaWFuemFfa2lsb3MgKQpEZXN2aWFjaW9uX0VzdGFuZGFyX21lcm1hPC1jKCJOQSIsICJOQSIsIGRlc3ZpYWNpb25lc3RhbmRhcl9raWxvcykKdGFibGVfbWVybWE8LWRhdGEuZnJhbWUoVmFyaWFibGVfbWVybWEsTWVkaWFfbWVybWEsTWVkaWFuYV9tZXJtYSxNb2RhX21lcm1hLFZhcmlhbnphX21lcm1hLERlc3ZpYWNpb25fRXN0YW5kYXJfbWVybWEpCmtuaXRyOjprYWJsZSh0YWJsZV9tZXJtYSkKYGBgCgojIyMgKkdyw6FmaWNvIGRlIGRpc3BlcnNpb24qCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpCmxpYnJhcnkoZ2dwbG90MikKCmdncGxvdChkYXRhPW1lcm1hMSwgbWFwcGluZyA9IGFlcyhNZXMsIEtpbG9zKSkgKyBnZW9tX3BvaW50KCkgKyB0aGVtZV9idygpCmBgYAoKIyMjIyMgRW4gZXN0YSBncsOhZmljYSBwb2RlbW9zIG9ic2VydmFyIHF1ZSBsYSBnZW5lcmFjaW9uIGRlIG1lcm1hIGRlIGxhIGVtcHJlc2EgRk9STSBzZXBhcmEgZW4gbG9zIG1lc2VzIGRlbCAyMDIyLiBTZSBvYnNlcnZhIHF1ZSAqKmVsIG1lcyBxdWUgbWFzIHNlIGdlbmVybyBtZXJtYSBmdWUgZW4gQWdvc3RvIGNvbnRpbnVhbmRvIGNvbiBGZWJyZXJvIHkgTWF5by4qKiBFbCBtZXMgcXVlIG1lbm9zIGdlbmVybyBtZXJtYSBlcyBTZXB0aWVtYnJlIHkgRW5lcm8uCgojIyMgKkRpc3BlcnNpb24gcGxvdHMqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJveHBsb3QobWVybWExJEtpbG9zKQpgYGAKCiMjIyMjIEVuIGVzdGEgZ3LDoWZpY2EgcG9kZW1vcyBvYnNlcnZhciBxdWUgbGEgbWVybWEgZ2VuZXJhZGEgZW4gRk9STSBzZSBlbmN1ZW50cmEgZW4gdW5hIGdyYW4gZGlzdHJpYnVjacOzbi4gKipFbCBwcm9tZWRpbyBlbnRyYSBkZW50cm8gZGUgbG9zIDMwMDAgeSBsb3MgNDAwMCBraWxvcy4qKiBEZSBsYSBtaXNtYSBtYW5lcmEsIHNlIGhhIGxsZWdhZG8gYSBnZW5lcmFyIG1lbm9zIGRlIDEwMDAga2lsb3MgY29udHJhIGxhIG1heGltYSBxdWUgc29uIGFycmliYSBkZSBsb3MgNjAwMCBraWxvcy4gCgojICoqU2NyYXAqKiAKCiMjICoqTGltcGllemEsIFRyYW5zZm9ybWFjacOzbiwgeSBPcmdhbml6YWNpw7NuIGRlIEJhc2VzIGRlIERhdG9zKioKCiMjIyMgSW1wb3J0YXIgbGFzIGJhc2VzIGRlIGRhdG9zCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgZmlsZS5jaG9vc2UoKQpzY3JhcDwtIHJlYWQuY3N2KCIvVXNlcnMvbWF5cmFjYW1wb3lyYW1vcy9EZXNrdG9wL0FuYWxpc2lzIGRlIERhdG9zIENvbmNlbnRyYWNpb24vUmV0by9GT1JNIC0gU2NyYXAuY3N2IikKIyBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCmxpYnJhcnkoZHBseXIpCiMgaW5zdGFsbC5wYWNrYWdlcygicHN5Y2giKQpsaWJyYXJ5KHBzeWNoKQpgYGAKCiMjIyAqwr9DdcOhbnRhcyB2YXJpYWJsZXMgeSBjdWFudG9zIHJlZ2lzdHJvcyB0aWVuZSBsYSBiYXNlIGRlIGRhdG9zPyoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGVzY3JpYmVEYXRhKHNjcmFwLGhlYWQ9MSx0YWlsPTEpCmBgYAojIyMjIyBFeGlzdGVuIDkgdmFyaWFibGVzIHkgMjUxIHJlZ2lzdHJvcyBlbiBsYSBiYXNlIGRlIGRhdG9zLgoKIyMjICpBcGxpY2EgdMOpY25pY2FzIGRlIGxpbXBpZXphIGRlIGJhc2VzIGRlIGRhdG9zIHkgZXhwbMOtY2FsYXMgYnJldmVtZW50ZSwgwr9wb3IgcXXDqSByZWFsaXphc3RlIGVzYXMgdMOpY25pY2FzPyoKCiMjIyMgT2JzZXJ2YWNpb25lcwojIyMjIyBTZSBjdWVudGEgY29uIHVuYSBmaWxhIGFsIGluZWNlc2FyaWEKIyMjIyMgU2UgY3VlbnRhbiBjb24gdmFyaWFibGVzIGluZWNlc2FyaWFzIAoKIyMjIyBUw6ljbmljYSAxOiBFbGltaW5hciBjb2x1bW5hLgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzY3JhcDE8LSBzY3JhcCBbLTEsXQpgYGAKCiMjIyMjIEVzdGEgdMOpY25pY2Egc2UgcmVhbGl6w7MgeWEgcXVlIHNlIGNvbnRhYmEgY29uIHVuYSBjb2x1bW5hIGVuIGJsYW5jbyBleHRyYS4KCiMjIyMgVMOpY25pY2EgMjogRWxpbWluYXIgdmFyaWFibGVzCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNjcmFwMSA8LSBzdWJzZXQoc2NyYXAxLCBzZWxlY3QgPSAtYyAoIFJlZmVyZW5jaWEsIFByb2R1Y3RvLFVuaWRhZC5kZS5tZWRpZGEsIFViaWNhY2nDs24uZGUuZGVzZWNobywgRXN0YWRvLCBIb3JhKSkKCnN1bW1hcnkoc2NyYXAxKQpgYGAKCiMjIyMjIEVzdGEgdMOpY25pY2Egc2UgcmVhbGl6w7MgeWEgcXVlIG5vIHNlIGNvbnNpZGVyYXJvbiBpbXBvcnRhbnRlcyBsYXMgY29sdW1uYXMgZGUgdmFyaWFibGVzLgoKIyMjIyBUw6ljbmljYSAzOiBDb252ZXJ0aXIgY2FyYWN0ZXIgYSBlbnRlcm8uCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNjcmFwMSRDYW50aWRhZCA8LSBhcy5pbnRlZ2VyKHNjcmFwMSRDYW50aWRhZCkKc3RyKHNjcmFwMSkKCmBgYAoKIyMjIyMgRW4gZXN0YSB0w6ljbmljYSBkZSBsaW1waWV6YSBzZSB2dWVsdmVuIGEgZmFjdG9yIG8gbsO6bWVyb3MgbGFzIHZhcmlhYmxlcyBwYXJhIGdlbmVyYXIgdW4gZXN0YW5kYXJpemFyIHkgZ2VuZXJhciB1biBmb3JtYXRvIHBhcmEgcXVlIHNlIHZ1ZWx2YSBtw6FzIHNlbmNpbGxvIGFsIHJlYWxpemFyIGdyw6FmaWNvcyB5IG1hbmlwdWxhciBkYXRvcy4gCgojIyMgRXhwb3J0YXIgbGEgYmFzZSBkZSBkYXRvcyBsaW1waWEgCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNjcmFwX2xpbXBpYSA8LSBzY3JhcDEKd3JpdGUuY3N2KHNjcmFwX2xpbXBpYSwgZmlsZSA9InNjcmFwX2JkX2xpbXBpYS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgoKIyMjICpDbGFzaWZpY2EgY2FkYSB2YXJpYWJsZSBlbiBjdWFsaXRhdGl2YSwgY3VhbnRpdGF0aXZhIGRpc2NyZXRhIG8gY3VhbnRpdGF0aXZhIGNvbnRpbnVhKgojIyMgKkVsaWdlIGxhIGVzY2FsYSBkZSBtZWRpY2nDs24gZGUgY2FkYSB2YXJpYWJsZS4qCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClZhcmlhYmxlX3NjcmFwPC1jKCJGZWNoYSIsICJDYW50aWRhZCIsICJVYmljYWNpw7NuX2RlX29yaWdlbiIpClR5cGVfc2NyYXA8LWMoImN1YWxpdGF0aXZhIiwgImN1YW50aXRhdGl2YSBkaXNjcmV0YSIsICJjdWFsaXRhdGl2YSIpCk1lYXN1cmVtZW50X3NjcmFwIDwtYygiTkEiLCAiY2FudGlkYWQgZ2VuZXJhZGEiLCAiTkEiKQp0YWJsZV9zY3JhcDwtZGF0YS5mcmFtZShWYXJpYWJsZV9zY3JhcCxUeXBlX3NjcmFwLCBNZWFzdXJlbWVudF9zY3JhcCkKa25pdHI6OmthYmxlKHRhYmxlX3NjcmFwKQpgYGAKCiMjICoqQW7DoWxpc2lzIEV4cGxvcmF0b3JpbyBkZSBsYXMgQmFzZXMgZGUgRGF0b3MqKgoKIyMjICpBbsOhbGlzaXMgRXN0YWTDrXN0aWNvKgoKIyMjIyAqTWVkaWEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1lZGlhX2NhbnRpZGFkIDwtIG1lYW4oc2NyYXAxJENhbnRpZGFkKQptZWRpYV9jYW50aWRhZApgYGAKIyMjIyMgTGFzIHZhcmlhYmxlcyBkZSBmZWNoYSB5IHViaWNhY2nDs24gZGUgb3JpZ2VuIG5vIHB1ZWRlIHRlbmVyIG1lZGlhCgojIyMjICpNZWRpYW5hKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptZWRpYW5hX2NhbnRpZGFkIDwtIG1lZGlhbihzY3JhcDEkQ2FudGlkYWQpCm1lZGlhbmFfY2FudGlkYWQKYGBgCiMjIyMjIExhcyB2YXJpYWJsZXMgZGUgZmVjaGEgeSB1YmljYWNpw7NuIGRlIG9yaWdlbiBubyBwdWVkZSB0ZW5lciBtZWRpYW5hCgojIyMjICpNb2RhKgojIyMgKk1vZGEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1vZGUgPC0gZnVuY3Rpb24gKHgpIHsKICB1eCA8LSB1bmlxdWUoeCkKICB1eCBbd2hpY2gubWF4KHRhYnVsYXRlKG1hdGNoKHgsdXgpKSldCn0KCm1vZGVfZmVjaGExIDwtIG1vZGUoc2NyYXAxJEZlY2hhKQptb2RlX2ZlY2hhMQoKbW9kZV9jYW50aWRhZCA8LSBtb2RlKHNjcmFwMSRDYW50aWRhZCkKbW9kZV9jYW50aWRhZAoKbW9kZV91YmljYWNpb24gPC0gbW9kZShzY3JhcDEkVWJpY2FjacOzbi5kZS5vcmlnZW4pCm1vZGVfdWJpY2FjaW9uCmBgYAoKIyMjIyAqVmFyaWFuemEqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnZhcmlhbnphX2NhbnRpZGFkIDwtIHZhcihzY3JhcDEkQ2FudGlkYWQpCnZhcmlhbnphX2NhbnRpZGFkCmBgYAoKIyMjIyAqRGVzdmlhY2nDs24gRXN0w6FuZGFyKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkZXN2aWFjaW9uZXN0YW5kYXJfY2FudGlkYWQgPC0gc3FydCh2YXJpYW56YV9jYW50aWRhZCkKZGVzdmlhY2lvbmVzdGFuZGFyX2NhbnRpZGFkCmBgYAoKCiMjIyMgKlRhYmxhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpWYXJpYWJsZV9zY3JhcDwtYygiRmVjaGEiLCAiQ2FudGlkYWQiLCAiVWJpY2FjacOzbl9kZV9vcmlnZW4iKQpNZWRpYV9zY3JhcDwtYygiTkEiLCBtZWRpYV9jYW50aWRhZCwgIk5BIikKTWVkaWFuYV9zY3JhcDwtYygiTkEiLG1lZGlhbmFfY2FudGlkYWQsICJOQSIpCk1vZGFfc2NyYXA8LWMobW9kZV9mZWNoYTEsIG1vZGVfY2FudGlkYWQsIG1vZGVfdWJpY2FjaW9uKQpWYXJpYW56YV9zY3JhcDwtYygiTkEiLHZhcmlhbnphX2NhbnRpZGFkLCAiTkEiKQpEZXN2aWFjaW9uX0VzdGFuZGFyX3NjcmFwPC1jKCJOQSIsIGRlc3ZpYWNpb25lc3RhbmRhcl9jYW50aWRhZCwgIk5BIikKdGFibGVfc2NyYXA8LWRhdGEuZnJhbWUoVmFyaWFibGVfc2NyYXAsTWVkaWFfc2NyYXAsTWVkaWFuYV9zY3JhcCxNb2RhX3NjcmFwLFZhcmlhbnphX3NjcmFwLERlc3ZpYWNpb25fRXN0YW5kYXJfc2NyYXApCmtuaXRyOjprYWJsZSh0YWJsZV9zY3JhcCkKYGBgCgojIyMgKkdyw6FmaWNvIGN1YWxpdGF0aXZvIChQYXkpOioKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGllKHRhYmxlKHNjcmFwMSRVYmljYWNpw7NuLmRlLm9yaWdlbikpCmBgYAoKIyMjICpCYXIgUGxvdHMqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpCmxpYnJhcnkoZ2dwbG90MikKCmdncGxvdChzY3JhcDEsIGFlcyh4PVViaWNhY2nDs24uZGUub3JpZ2VuLCB5PUNhbnRpZGFkKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0iYnJvd24iKSArIHNjYWxlX2ZpbGxfZ3JleSgpICsgIyBBZGQgYmFycyB0byB0aGUgcGxvdAogIGxhYnModGl0bGUgPSAiRG9uZGUgc2UgZ2VuZXJhIGVsIHNjcmFwIiwgIyBBZGQgYSB0aXRsZQogICAgICAgc3VidGl0bGUgPSAiUkggZW1wcmVzYSBGT1JNIiwgIyBBZGQgYSBzdWJ0aXRsZQogICAgICAgY2FwdGlvbiA9ICJSZWxhY2nDs24iLCAjIEFkZCBhIGNhcHRpb24KICAgICAgIHggPSAiVWJpY2FjacOzbiBkZSBvcmlnZW4iKQpgYGAKCiMjIyMjIEVuIGVzdGFzIGdyw6FmaWNhcyBwb2RlbW9zIG9ic2VydmFyIHF1ZSBlbiBsYSBtYW5lcmEgZGUgY29tbyBlc3RhIGRpc3RyaWJ1aWRhIGxhIGdlbmVyYWNpb24gZGUgZWwgc2NyYXAgZGUgbGEgZW1wcmVzYSBGT1JNLiBTZSBvYnNlcnZhIGRlIHVuYSBtYW5lcmEgcG9yIG11Y2hhIGRpZmVyZW5jaWEgZW4gKipzZSBnZW5lcmEgbGEgbWF5b3IgY2FudGlkYWQgZW4gbGEgcHJlLXByb2R1Y2Npw7NuKiogeSBlbiBsYSBxdWUgbWVub3Mgc2UgcHJvZHVjZSBlbCBzY3JhcCBlcyBlbiBsYSBldGFwYSBkZSBsYSBwb3N0LXByb2R1Y2Npw7NuLiAKCiMgKipCYXNlIGRlIERhdG9zIEV4dGVybmEqKiAKCiMjIyMgSW1wb3J0YXIgYmFzZSBkZSBkYXRvcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIGZpbGUuY2hvb3NlKCkKYmRfZXh0ZXJuYSA8LXJlYWQuY3N2KCIvVXNlcnMvbWF5cmFjYW1wb3lyYW1vcy9EZXNrdG9wL0FuYWxpc2lzIGRlIERhdG9zIENvbmNlbnRyYWNpb24vUmV0by9Qcm9kdWNjaW/MgW4gZGUgY2FydG/MgW4gZW4gTWXMgXhpY28gMS5jc3YiKQpgYGAKCiMjICoqTGltcGllemEsIFRyYW5zZm9ybWFjacOzbiwgeSBPcmdhbml6YWNpw7NuIGRlIEJhc2VzIGRlIERhdG9zKioKCiMjIyMgVMOpY25pY2EgMTogUmVtb3ZlciB2YWxvcmVzIGlycmVsZXZhbnRlcywgY29sdW1uYSBpbmVjZXNhcmlhICJJbmR1c3RyeS5Hcm91cC5JRCIgbm8gbWUgYXBvcnRhIGRhdG9zIGltcG9ydGFudGVzCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmV4dGVybmEgPC0gYmRfZXh0ZXJuYQpleHRlcm5hIDwtIHN1YnNldCAoZXh0ZXJuYSxzZWxlY3QgPSAtYyhJbmR1c3RyeS5Hcm91cC5JRCkpCgpzdW1tYXJ5KGV4dGVybmEpCmBgYAoKIyMjIyMgRXN0YSB0w6ljbmljYSBzZSByZWFsaXrDsyB5YSBxdWUgc2UgY29uc2lkZXJvIGluZWNlc2FyaWEgbGEgY29sdW1uYSAgIkluZHVzdHJ5Lkdyb3VwLklEIixubyBtZSBhcG9ydGEgZGF0b3MgaW1wb3J0YW50ZXMuCgojIyMjIFTDqWNuaWNhIDI6IFJlbW92ZXIgTkEncwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojP0N1YW50b3MgTkEgdGVuZ28gZW4gbGEgYmFzZSBkZSBkYXRvcz8Kc3VtKGlzLm5hKGV4dGVybmEpKQoKIz9DdWFudG9zIE5BIHRlbmdvIHBvciB2YXJpYWJsZT8Kc2FwcGx5KGV4dGVybmEsIGZ1bmN0aW9uKHgpIHN1bSAoaXMubmEoeCkpKQoKI0JvcnJhciB0b2RvcyBsb3MgcmVnaXN0cm9zIE5BIGRlIHVuYSB0YWJsYQpleHRlcm5hMSA8LSBleHRlcm5hCmV4dGVybmExIDwtIG5hLm9taXQoZXh0ZXJuYTEpCgpzdW1tYXJ5KGV4dGVybmExKQpgYGAKCiMjIyMjIFNlIGVsaW1pbmFyb24gbG9zIE5BICdzIGRlIGxhIGJhc2UgZGUgZGF0b3MgeWEgcXVlIHZpZW5lIGNvbiBlc3BhY2lvcyB2YWNpb3MuCgojIyMgKkFuw6FsaXNpcyBFc3RhZMOtc3RpY28qCgojIyMjICpNZWRpYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWVkaWFfcmVnaW9uIDwtIG1lYW4oZXh0ZXJuYTEkUmVnaW9uKQptZWRpYV9yZWdpb24KCm1lZGlhX2Vjb25vbWljIDwtIG1lYW4oZXh0ZXJuYTEkRWNvbm9taWMuVW5pdCkKbWVkaWFfZWNvbm9taWMKYGBgCiMjIyMjIExhcyB2YXJpYWJsZXMgZGUgZmVjaGEgeSB1YmljYWNpw7NuIGRlIG9yaWdlbiBubyBwdWVkZSB0ZW5lciBtZWRpYQoKIyMjIyAqTWVkaWFuYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWVkaWFuYV9yZWdpb24gPC0gbWVkaWFuKGV4dGVybmExJFJlZ2lvbikKbWVkaWFuYV9yZWdpb24KCm1lZGlhbmFfZWNvbm9taWMgPC0gbWVkaWFuKGV4dGVybmExJEVjb25vbWljLlVuaXQpCm1lZGlhbmFfZWNvbm9taWMKYGBgCiMjIyMjIExhcyB2YXJpYWJsZXMgZGUgZmVjaGEgeSB1YmljYWNpw7NuIGRlIG9yaWdlbiBubyBwdWVkZSB0ZW5lciBtZWRpYW5hCgojIyMjICpNb2RhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptb2RlIDwtIGZ1bmN0aW9uICh4KSB7CiAgdXggPC0gdW5pcXVlKHgpCiAgdXggW3doaWNoLm1heCh0YWJ1bGF0ZShtYXRjaCh4LHV4KSkpXQp9Cgptb2RlX3N0YXRlIDwtIG1vZGUoZXh0ZXJuYTEkU3RhdGUuSUQpCm1vZGVfc3RhdGUKCm1vZGVfcmVnaW9uIDwtIG1vZGUoZXh0ZXJuYTEkUmVnaW9uKQptb2RlX3JlZ2lvbgoKbW9kZV9lY29ub21pYyA8LSBtb2RlKGV4dGVybmExJEVjb25vbWljLlVuaXQpCm1vZGVfZWNvbm9taWMKYGBgCgojIyMjICpWYXJpYW56YSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdmFyaWFuemFfcmVnaW9uIDwtIHZhcihleHRlcm5hMSRSZWdpb24pCnZhcmlhbnphX3JlZ2lvbgoKdmFyaWFuemFfZWNvbm9taWMgPC0gdmFyKGV4dGVybmExJEVjb25vbWljLlVuaXQpCnZhcmlhbnphX2Vjb25vbWljCmBgYAoKIyMjIyAqRGVzdmlhY2nDs24gRXN0w6FuZGFyKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkZXN2aWFjaW9uZXN0YW5kYXJfcmVnaW9uIDwtIHNxcnQodmFyaWFuemFfcmVnaW9uKQpkZXN2aWFjaW9uZXN0YW5kYXJfcmVnaW9uCgpkZXN2aWFjaW9uZXN0YW5kYXJfZWNvbm9taWMgPC0gc3FydCh2YXJpYW56YV9lY29ub21pYykKZGVzdmlhY2lvbmVzdGFuZGFyX2Vjb25vbWljCmBgYAoKCiMjIyMgKlRhYmxhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpWYXJpYWJsZV9leHRlcm5hPC1jKCJTdGF0ZS5JRCIsICJSZWdpb24iLCAiRWNvbm9taWMuVW5pdCIpCk1lZGlhX2V4dGVybmE8LWMoIk5BIiwgbWVkaWFfcmVnaW9uLCBtZWRpYV9lY29ub21pYykKTWVkaWFuYV9leHRlcm5hPC1jKCJOQSIsbWVkaWFuYV9yZWdpb24sIG1lZGlhbmFfZWNvbm9taWMpCk1vZGFfZXh0ZXJuYTwtYyhtb2RlX3N0YXRlLCBtb2RlX3JlZ2lvbiwgbW9kZV9lY29ub21pYykKVmFyaWFuemFfZXh0ZXJuYTwtYygiTkEiLHZhcmlhbnphX3JlZ2lvbiwgdmFyaWFuemFfZWNvbm9taWMpCkRlc3ZpYWNpb25fRXN0YW5kYXJfZXh0ZXJuYTwtYygiTkEiLCBkZXN2aWFjaW9uZXN0YW5kYXJfcmVnaW9uLCBkZXN2aWFjaW9uZXN0YW5kYXJfZWNvbm9taWMpCnRhYmxlX2V4dGVybmE8LWRhdGEuZnJhbWUoVmFyaWFibGVfZXh0ZXJuYSxNZWRpYV9leHRlcm5hLE1lZGlhbmFfZXh0ZXJuYSxNb2RhX2V4dGVybmEsVmFyaWFuemFfZXh0ZXJuYSxEZXN2aWFjaW9uX0VzdGFuZGFyX2V4dGVybmEpCmtuaXRyOjprYWJsZSh0YWJsZV9leHRlcm5hKQpgYGAKCiMjIyAqRGlzcGVyc2lvbiBwbG90cyoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KGV4dGVybmExLCBhZXMoeCA9UmVnaW9uLCB5ID1FY29ub21pYy5Vbml0KSkgKyAKICBnZW9tX3BvaW50KHNoYXBlPTE5LCBzaXplPTMpICsgCiAgbGFicyh0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgVW5pZGFkZXMgRWNvbm9taWNhcyB5IFJlZ2lvbiBkZSBNZXhpY28iLGNhcHRpb24gPSJCYXNlIGRlIEV4dGVybmEiLHg9IlJlZ2lvbiIsIHk9IkVjb25vbWljIFVuaXQiKSArIAogIHRoZW1lX2NsYXNzaWMoKQpgYGAKCiMjIyMjIEVuIGVzdGEgZ3LDoWZpY2EgcG9kZW1vcyBvYnNlcnZhciBxdWUgbGEgcmVnacOzbiBuby4zIGRlIE3DqXhpY28gZXMgZG9uZGUgc2UgZ2VuZXJhIGNvbiBtYXlvciB1bmlkYWRlcyBkZSBjYXJ0w7NuIGVzdG8gc2Vnw7puIGxhIGJhc2UgZGUgZGF0b3MgZXh0ZXJuYSB0b21hZGEgZGUgbGEgSU5FR0kuIAoKIyMjICpCYXIgUGxvdCoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdChleHRlcm5hMSAsYWVzKHg9cmVvcmRlcihSZWdpb24sIEVjb25vbWljLlVuaXQpLCB5PUVjb25vbWljLlVuaXQgLGZpbGw9U3RhdGUpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKQpgYGAKCiMjIyMjIyBFbiBlc3RhIGdyw6FmaWNhLCBzZSB2b2x2acOzIGEgYW5hbGl6YXIgbGEgcHJvZHVjY2nDs24gZCBlIGNhcnRvbiBwb3IgcmVnacOzbiBkZSBtZXhpY28sIGFncmVnYW5kbyBxdWUgc2UgcHVlZGUgb2JzZXJ2YXIgZGUgdW5hIG1hbmVyYSB2aXN1YWwgeSBjbGFyYSBkZSBsb3MgZXN0YWRvcyBkZSBsYSByZXDDumJsaWNhIHF1ZSBmb3JtYW4gcGFydGUgZGUgbGEgcmVnaW9uZXMuIFNlIG9ic2VydmEgcXVlIGVsIG1heW9yIHByb2R1Y3RvciBkZSBjYXJ0w7NuIGVzIFB1ZWJsYS4gCgojICoqUHJvbsOzc3RpY28gZGVsIERlc2VtcGXDsW8gZGUgbGEgSW5kdXN0cmlhIEF1dG9tb3RyaXogeSBsYSBlbXByZXNhIEZPUk0qKgoKIyMjIyBJbXBvcnRhciBiYXNlcyBkZSBkYXRvcyAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI2ZpbGUuY2hvb3NlKCkKYmRfcHJlZGljY2lvbiA8LSByZWFkLmNzdigiL1VzZXJzL21heXJhY2FtcG95cmFtb3MvRGVza3RvcC9BbmFsaXNpcyBkZSBEYXRvcyBDb25jZW50cmFjaW9uL2VuY29kZWQtYmRfcHJlZGljY2lvbi5jc3YiKQp2ZWhpY3Vsb3NfY2lyY3VsYWNpb24gPC0gcmVhZC5jc3YoIi9Vc2Vycy9tYXlyYWNhbXBveXJhbW9zL0Rlc2t0b3AvQW5hbGlzaXMgZGUgRGF0b3MgQ29uY2VudHJhY2lvbi9lbmNvZGVkLXZlaGljdWxvc19lbl9jaXJjdWxhY2lvbiAoMikuY3N2IikKcHJvZHVjY2lvbiA8LSByZWFkLmNzdigiL1VzZXJzL21heXJhY2FtcG95cmFtb3MvRGVza3RvcC9BbmFsaXNpcyBkZSBEYXRvcyBDb25jZW50cmFjaW9uL2JkX3Byb2R1Y2Npb25fbGltcGlhICgxKS5jc3YiKQpgYGAKCiMjIyMgSW5zdGFsYXIgcGFxdWV0ZXMgeSBsbGFtYXIgbGlicmVyw61hcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojaW5zdGFsbC5wYWNrYWdlcygidHNlcmllcyIpCmxpYnJhcnkodHNlcmllcykKI2luc3RhbGwucGFja2FnZXMoImZvcmVjYXN0IikKbGlicmFyeShmb3JlY2FzdCkKI2luc3RhbGwucGFja2FnZXMoImFzdHNhIikKbGlicmFyeShhc3RzYSkKI2luc3RhbGwucGFja2FnZXMoImRwbHlyIikKbGlicmFyeShkcGx5cikKI2luc3RhbGwucGFja2FnZXMoImp0b29scyIpCmxpYnJhcnkoanRvb2xzKQojaW5zdGFsbC5wYWNrYWdlcygibG10ZXN0IikKbGlicmFyeShsbXRlc3QpCiNpbnN0YWxsLnBhY2thZ2VzKCJjYXIiKQpsaWJyYXJ5KGNhcikKI2luc3RhbGwucGFja2FnZXMoIm9sc3JyIikKbGlicmFyeShvbHNycikKI2luc3RhbGwucGFja2FnZXMoImNvcnJwbG90IikKbGlicmFyeShjb3JycGxvdCkKYGBgCgojIyAqKlByb27Ds3N0aWNvcyoqCgojIyMgKkRlc2VtcGXDsW8gZGUgbGEgaW5kdXN0cmlhIGF1dG9tb3RyaXogcGFyYSBsb3Mgc2lndWllbnRlcyAzIHBlcmlvZG9zIGRlIHRpZW1wbyoKIyMjIyBWZWjDrWN1bG9zIGRlIG1vdG9yIHJlZ2lzdHJhZG9zIGVuIGNpcmN1bGFjacOzbiAKCiMjIyMgRW50ZW5kZXIgbGEgYmFzZSBkZSBkYXRvcyAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc3VtbWFyeSh2ZWhpY3Vsb3NfY2lyY3VsYWNpb24pCnN0cih2ZWhpY3Vsb3NfY2lyY3VsYWNpb24pCmBgYAoKIyMjICpMaW1waWV6YSBkZSBkYXRvcyoKIyMjIyBFbGltaW5hciB2YXJpYWJsZXMgKENhbWlvbmVzLnkuY2FtaW9uZXRhcy5wYXJhLmNhcmdhLCBNb3RvY2ljbGV0YXMsIFggeSBYLjEpIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp2ZWhpY3Vsb3NfY2lyY3VsYWNpb24xIDwtIHN1YnNldCh2ZWhpY3Vsb3NfY2lyY3VsYWNpb24sIHNlbGVjdCA9IC1jIChDYW1pb25lcy55LmNhbWlvbmV0YXMucGFyYS5jYXJnYSwgTW90b2NpY2xldGFzLCBYLCBYLjEpKQp2ZWhpY3Vsb3NfY2lyY3VsYWNpb24xCmBgYAoKIyMjIyMgRXN0YXMgdmFyaWFibGVzIHNlIGVsaW1pbmFuLCB5YSBxdWUsIGNhbWlvbmVzIHkgY2FtaW9uZXRhcyBwYXJhIGNhcmdhIHkgbW90b2NpY2xldGFzIG5vIHNvbiBlbCBwcmluY2lwYWwgbWVyY2FkbyBkZSBGT1JNLCBhZGVtw6FzIGRlIHF1ZSBsb3MgZGF0b3MgZGUgc3VzIHZhcmlhYmxlcyBubyBzb24gc2lnbmlmaWNhdGl2YXMgcGFyYSBlbCBwcm9uw7NzdGljbyBwb3JxdWUgc3VzIHZhbG9yZXMgc29uIG11eSBwZXF1ZcOxb3MgYSBjb21wYXJhY2nDs24gY29uIGxhcyBkZW3DoXMgdmFyaWFibGVzLCBwb3IgbG8gdGFudG8sIHN1cyBkYXRvcyBubyBpbXBhY3RhbiBhbCBhbsOhbGlzaXMsIGRlIGlndWFsIGZvcm1hLCBzZSBlbGltaW5hIGxhIHZhcmlhYmxlIFggeSBYLjEgcG9ycXVlIG5vIHRpZW5lbiBpbmZvcm1hY2nDs24gcmVsZXZhbnRlLiAKCiMjIyBFbGltaW5hciByZW5nbG9uZXMgaXJyZWxldmFudGVzCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnZlaGljdWxvc19jaXJjdWxhY2lvbjIgPC0gdmVoaWN1bG9zX2NpcmN1bGFjaW9uMVstYyg0Myw0NCw0NSw0Niw0NyksXQp2ZWhpY3Vsb3NfY2lyY3VsYWNpb24yCnN1bW1hcnkodmVoaWN1bG9zX2NpcmN1bGFjaW9uMikKYGBgCgojIyMjIFNlIGVsaW1pbmFuIGVzdG9zIHJlbmdsb25lcywgZGViaWRvIGEgcXVlIG5vIHRlbsOtYW4gY29udGVuaWRvLCBlcyBkZWNpciwgZXJhbiBjb25zaWRlcmFkb3MgTkHCtHMuCgojIyMgKkdyw6FmaWNhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90KHZlaGljdWxvc19jaXJjdWxhY2lvbjIkQcOxbyx2ZWhpY3Vsb3NfY2lyY3VsYWNpb24yJFRvdGFsLCB0eXBlPSJsIixjb2w9ImJsdWUiLCBsd2Q9MS41LCB4bGFiID0iQcOxbyIseWxhYiA9IlVuaWRhZGVzIiwgbWFpbiA9ICJWZWhpY3Vsb3MgZGUgbW90b3IgZW4gY2lyY3VsYWNpw7NuIHJlZ2lzdHJhZG9zIGFudWFsbWVudGUiKQpsaW5lcyh2ZWhpY3Vsb3NfY2lyY3VsYWNpb24yJEHDsW8sdmVoaWN1bG9zX2NpcmN1bGFjaW9uMiRBdXRvbcOzdmlsZXMsY29sPSJyZWQiLGx0eT0zKQpsZWdlbmQoInRvcGxlZnQiLCBsZWdlbmQ9YygiVG90YWwgZGUgdmVoaWN1bG9zIGVuIGNpcmN1bGFjacOzbiIsICJBdXRvbcOzdmlsZXMgZW4gY2lyY3VsYWNpw7NuIiksCiAgICAgICBjb2w9YygiYmx1ZSIsICJyZWQiKSwgbHR5ID0gMToyLCBjZXg9MC44KQpgYGAKCiMjIyMjIENvbiBlc3RlIHBsb3QsIHNlIHB1ZWRlIG9ic2VydmFyIGVsIGNvbXBvcnRhbWllbnRvIGRlIGxhcyB2YXJpYWJsZXMgeSBsYSBjb21wYXJhY2nDs24gYSB0cmF2w6lzIGRlIGxvcyBhw7FvcyBkZWwgdG90YWwgZGUgdmVoaWN1bG9zIHF1ZSBlc3TDoW4gZW4gY2lyY3VsYWNpw7NuIHkgZGUgbG9zIGF1dG9tb3ZpbGVzLiAKCiMjIyMjIFRhbWJpw6luLCBzZSBwZXJjaWJlIHF1ZSBhbWJhcyBsw61uZWFzIHNvbiBtdXkgc2ltaWxhcmVzLCB5IGVzdMOhbiBtdXkgY2VyY2EgdW5hIGRlIGxhIG90cmEsIHBvciBsbyBxdWUgc2UgcHVlZGUgZGVkdWNpciBxdWUgQXV0b23Ds3ZpbGVzIG9jdXBhIGVsIG1heW9yIHBvcmNlbnRhamUgZGVsIHRvdGFsLgoKIyMjIyMgUG9yIG90cm8gbGFkbywgbGEgZ3LDoWZpY2EgdGllbmUgdW5hIHRlbmRlbmNpYSBlbiBzdSBtYXlvcsOtYSBjcmVjaWVudGUgeSBwb3NpdGl2YSwgZXMgZGVjaXIsIHF1ZSBjYWRhIGHDsW8gaGF5IG3DoXMgYXV0b23Ds3ZpbGVzIGVuIGNpcmN1bGFjacOzbi4KCiMjICoqRm9yZWNhc3RpbmcgdXNhbmRvIGVsIE1vZGVsbyBhdXRvcmVncmVzaXZvKioKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KYXV0b3JlZ3Jlc3NpdmVfbW9kZWwgPC0gYXJtYSh2ZWhpY3Vsb3NfY2lyY3VsYWNpb24yJFRvdGFsLCBvcmRlciA9IGMoMSwwKSkKc3VtbWFyeShhdXRvcmVncmVzc2l2ZV9tb2RlbCA8LSBhcm1hKHZlaGljdWxvc19jaXJjdWxhY2lvbjIkVG90YWwsIG9yZGVyID0gYygxLDApKSkKCmF1dG9yZWdyZXNzaXZlX21vZGVsX2ZvcmVjYXN0PC1mb3JlY2FzdChhdXRvcmVncmVzc2l2ZV9tb2RlbCRmaXR0ZWQsaD01LGxldmVsPWMoOTUpKQphdXRvcmVncmVzc2l2ZV9tb2RlbF9mb3JlY2FzdApgYGAKCiMjIyMjIExvIHF1ZSBzZSBvYnNlcnZhIGVuIGVsIG1vZGVsbyBhdXRvcmVncmVzaXZvIGRlIGxvcyB2ZWjDrWN1bG9zIGRlIG1vdG9yIGVuIGNpcmN1bGFjacOzbiB5IGFsIHByb27Ds3N0aWNvIHBhcmEgbG9zIHNpZ3VpZW50ZXMgYcOxb3MsIGVzIHF1ZSBjb21vIHNlIGV4cGxpY28gYW50ZXJpb3JtZW50ZSwgdGllbmUgdW5hIHRlbmRlbmNpYSBwb3NpdGl2YSwgcG9yIGVqZW1wbG8sIGVuIGVsIHNpZ3VpZW50ZSBhw7FvIHNlIGVzcGVyYW4gMzcsODg0LDI4MSB2ZWjDrWN1bG9zIGVuIGNpcmN1bGFjacOzbiBjb24gdW4gOTUlIGRlIGNvbmZpYW56YSwgeSBsb3MgcmFuZ29zIHB1ZWRlbiBpciBkZSAzNSwyNDAsNDA2IGhhc3RhIDQwLDUyOCwxNTUuIAoKIyMjIyMgRW4gZWwgc2VndW5kbyBhw7FvLCBzZSBwcm9ub3N0aWNhbiAzOSwyMjIsMDg3LCBkZSBpZ3VhbCBtYW5lcmEgY29uIHVuIDk1JSBkZSBjb25maWFuemEsIHkgcG9yIMO6bHRpbW8sIGVuIGVsIHRlcmNlciBhw7FvLCBzZSBwcmV2ZWVuIDQwLDU1OSw4OTMgdmVow61jdWxvcyBlbiBjaXJjdWxhY2nDs24uCgojIyMgKkdyw6FmaWNhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90KGF1dG9yZWdyZXNzaXZlX21vZGVsX2ZvcmVjYXN0KQpgYGAKCiMjIyMjIENvbiBlc3RlIHBsb3QsIHNlIHB1ZWRlIGludGVycHJldGFyIGRlIG1hbmVyYSBtw6FzIHZpc3VhbCBsbyBxdWUgc2UgZXhwbGljbyBhbnRlcmlvcm1lbnRlLCB5IHBhcmEgZXhwbGljYXJsbyBjb24gbWF5b3IgcHJlY2lzacOzbiwgZXMgbmVjZXNhcmlvIHNhYmVyIHF1ZSBsYSBsw61uZWEgbmVncmEgY29ycmVzcG9uZGUgYSBsb3MgZGF0b3MgcXVlIHNlIHRpZW5lbiBlbiBsYSBiYXNlIGRlIGRhdG9zLCBtaWVudHJhcyBxdWUgbGEgbMOtbmVhIGF6dWwgc2lnbmlmaWNhIGVsIHJlc3VsdGFkbyBkZSBsb3MgZGF0b3Mgb2J0ZW5pZG9zIGEgdHJhdsOpcyBkZWwgbW9kZWxvIGF1dG9yZWdyZXNpdm8sIHkgc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIHZhIGhhY2lhIGFycmliYSBsYSB0ZW5kZW5jaWEuCgojIyMjIyBQb3Igb3RybyBsYWRvLCBsYSBsw61uZWEgYXp1bCB0aWVuZSB1biBzb21icmVhZG8gZ3JpcyBxdWUgaW5kaWNhIGxvcyB2YWxvcmVzIGRlICJsb3ciIHkgImhpZ2giIGFudGUgZWwgOTUlIGRlIGNvbmZpYW56YS4KCiMjIyAqRm9yZWNhc3RpbmcgdXNhbmRvIE1vdmluZyBBdmVyYWdlIE1vZGVsKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptYW1fY2lyY3VsYWNpb24gPC0gYXJtYSh2ZWhpY3Vsb3NfY2lyY3VsYWNpb24yJFRvdGFsLG9yZGVyID0gYygxLDEpKQpzdW1tYXJ5KG1hbV9jaXJjdWxhY2lvbiA8LSBhcm1hKHZlaGljdWxvc19jaXJjdWxhY2lvbjIkVG90YWwsb3JkZXIgPSBjKDEsMSkpKQoKbWFtX2NpcmN1bGFjaW9uX2ZvcmVjYXN0IDwtIGZvcmVjYXN0KG1hbV9jaXJjdWxhY2lvbiRmaXR0ZWQsaD01LGxldmVsPWMoOTUpKQptYW1fY2lyY3VsYWNpb25fZm9yZWNhc3QKYGBgCgojIyMjIyBBIHRyYXbDqXMgZGUgZXN0ZSBjw7NkaWdvLCBwb2RlbW9zIGRlZHVjaXIsIHF1ZSBidXNjYW1vcyB1biBtb2RlbG8gbm8gZXN0YWNpb25hcmlvLCB5IHF1ZSBlc3RhIGVuIGNvbnN0YW50ZSBtb3ZpbWllbnRvLCB5IGFsIGlndWFsIHF1ZSBlbCBtb2RlbG8gYXV0b3JlZ3Jlc2l2bywgc2UgcHVlZGUgb2JzZXJ2YXIgdW5hIHRlbmRlbmNpYSBwb3NpdGl2YSwgeSBtdXkgc2ltaWxhciBhIGVsbGEsIGFzw60gbWlzbW8sIGN1ZW50YSBjb24gdW4gOTUlIGRlIGNvbmZpYW56YS4gCgojIyMjIyBQb3Igb3RybyBsYWRvLCBsb3MgdmVow61jdWxvcyBjaXJjdWxhbmRvIGR1cmFudGUgZWwgcHJpbWVyIHBlcmlvZG8gZGUgdGllbXBvIHNlIGNhbGN1bGEgcXVlIHNvbiAzNyw2MzUsMDE5LCBzZWd1aWRvIHBvciAzOCw5NDgsODcwIHkgNDAsMjYyLDcyMC4KCiMjIyAqR3LDoWZpY2EqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBsb3QobWFtX2NpcmN1bGFjaW9uX2ZvcmVjYXN0KQpgYGAKCiMjIyMjIEFxdcOtIHNlIHB1ZWRlIGludGVycHJldGFyIGdyw6FmaWNhbWVudGUgbG8gZXhwbGljYWRvIGVuIGVsIHB1bnRvIGFudGVyaW9yLCB5IHNlIG9ic2V2YSBjb21vIGxhIHRlbmRlbmNpYSBlcyBwb3NpdGl2YSwgZGUgaWd1YWwgZm9ybWEsIHRpZW5lICJsb3dzIiB5ICJoaWdocyIuCgojIyAqKkRlc2VtcGXDsW8gZGUgMSBkZSBsYXMgw6FyZWFzIGRlIGxhIGVtcHJlc2EgRk9STSBwYXJhIGxvcyBzaWd1aWVudGVzIDMgcGVyaW9kb3MgZGUgdGllbXBvKioKCiMjIyAqUHJvZHVjY2nDs24gRk9STSoKCiMjIyBFbnRlbmRlciBsYSBiYXNlIGRlIGRhdG9zIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzdW1tYXJ5KHByb2R1Y2Npb24pCnN0cihwcm9kdWNjaW9uKQpgYGAKCiMjICpMaW1waWV6YSBkZSBkYXRvcyogCgojIyMgRWxpbWluYXIgTkHCtHMKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcHJvZHVjY2lvbiRjbGllbnRlIDwtIGFzLmZhY3Rvcihwcm9kdWNjaW9uJGNsaWVudGUpCnN0cihwcm9kdWNjaW9uKQpzdW1tYXJ5KHByb2R1Y2Npb24pCgpwcm9kdWNjaW9uMSA8LSBwcm9kdWNjaW9uIApwcm9kdWNjaW9uMTwtICBwcm9kdWNjaW9uMVstYyg2MjQpLF0gCnN1bW1hcnkgKHByb2R1Y2Npb24xKQpgYGAKCiMjIyMjIFNlIGVsaW1pbmFyb24gbG9zIE5BwrRzIHF1ZSBubyB0ZW7DrWFuIHJlbGV2YW5jaWEsIHkgc2UgcmVlbXBsYXphcm9uIG90cm9zIGRlc2RlIGxhIGJhc2UgZGUgZGF0b3MgY29uIGVsIG5vbWJyZSAic2luIHJlZ2lzdHJvIiwgeWEgcXVlLCBzZSBjb25zaWRlcsOzIHF1ZSBlcmEgaW1wb3J0YW50ZSBxdWVkYXJzZSBjb24gZXN0b3MgZGF0b3MgcGFyYSB2aXN1YWxpemFyIG1lam9yIGxvcyBkYXRvcy4KCiMjIyAqRm9yZWNhc3RpbmcgdXNhbmRvIGVsIE1vZGVsbyBhdXRvcmVncmVzaXZvKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQphdXRvcmVncmVzc2l2ZV9tb2RlbF9wcm9kdWNjaW9uIDwtIGFybWEocHJvZHVjY2lvbjEkcGllemFzX3Byb2csIG9yZGVyID0gYygxLDApKQpzdW1tYXJ5KGF1dG9yZWdyZXNzaXZlX21vZGVsX3Byb2R1Y2Npb24gPC0gYXJtYShwcm9kdWNjaW9uMSRwaWV6YXNfcHJvZywgb3JkZXIgPSBjKDEsMCkpKQoKYXV0b3JlZ3Jlc3NpdmVfbW9kZWxfcHJvZHVjY2lvbl9mb3JlY2FzdDwtZm9yZWNhc3QoYXV0b3JlZ3Jlc3NpdmVfbW9kZWxfcHJvZHVjY2lvbiRmaXR0ZWQsaD01LGxldmVsPWMoOTUpKQphdXRvcmVncmVzc2l2ZV9tb2RlbF9wcm9kdWNjaW9uX2ZvcmVjYXN0CmBgYAoKIyMjIyMgRW4gZWwgY2FzbyBkZSBlc3RlIG1vZGVsbyBhdXRvcmVncmVzaXZvLCBhbWJvcyBjb2VmaWNpZW50ZXMgc29uIGRlIGdyYW4gcmVsZXZhbmNpYSBwYXJhIGxhIGJhc2UgZGUgZGF0b3MsIHlhIHF1ZSBhbWJhcyB0aWVuZW4gbG9zIDMgYXN0ZXJpc2NvcywgcG9yIG90cm8gbGFkbywgYSBsYSBob3JhIGRlIGhhY2VyIGVsIHByb27Ds3N0aWNvLCBlcyBub3RvcmlvIHF1ZSBzZSBlc3RpbWEgcXVlIHF1ZWRhcsOhIGRlIGxhIG1pc21hIGZvcm1hLCBlcyBkZWNpciwgY29uIGxhcyBtaXNtYXMgcGllemFzIHByb2dyYW1hZGFzLCBzaW4gZW1iYXJnbyBzZSBwdWVkZSB2ZXIgY29tbyBtaWVudHJhcyAiTG93IiBkaXNtaW51eWUsICJoaWdoIiBhdW1lbnRhLgoKIyMjICpHcsOhZmljYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdChhdXRvcmVncmVzc2l2ZV9tb2RlbF9wcm9kdWNjaW9uX2ZvcmVjYXN0KQpgYGAKCiMjIyMjIENvbW8gc2UgcHVlZGUgdmVyIGVuIGVsIHBsb3QsIG5vIHNlIGVzcGVyYSB1bmEgbWVqb3JhIHBhcmEgZXN0ZSBtb2RlbG8sIHkgc2UgcHVlZGVuIHZlciBsb3MgZm9yZWNhc3QsIGVsIGxvdyB5IGVsIGhpZ2gsIGNvbiA5NSUgZGUgY29uZmlhbnphLgoKIyMjICpGb3JlY2FzdGluZyB1c2FuZG8gTW92aW5nIEF2ZXJhZ2UgTW9kZWwqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1hbV9wcm9kdWNjaW9uIDwtIGFybWEocHJvZHVjY2lvbjEkcGllemFzX3Byb2csb3JkZXIgPSBjKDEsMSkpCnN1bW1hcnkobWFtX3Byb2R1Y2Npb24gPC0gYXJtYShwcm9kdWNjaW9uMSRwaWV6YXNfcHJvZyxvcmRlciA9IGMoMSwxKSkpCgptYW1fcHJvZHVjY2lvbl9mb3JlY2FzdCA8LSBmb3JlY2FzdChtYW1fcHJvZHVjY2lvbiRmaXR0ZWQsaD01LGxldmVsPWMoOTUpKQptYW1fcHJvZHVjY2lvbl9mb3JlY2FzdApgYGAKCiMjIyMjIEVsIGNvbXBvcnRhbWllbnRvIGRlIGVzdGUgbW9kZWxvIGluZGljYSBxdWUgbm8gc2UgcHJvbm9zdGljYW4gY2FtYmlvcyBhIGxvIGxhcmdvIGRlIGxvcyBwcm94aW1vcyBhw7FvcywgY29uIHVuIDk1JSBkZSBjb25maWFuemEsIHBlcm8gc2kgc2Ugb2JzZXJ2YSBlbiBsb3dzLCBlbCBjYW1iaW8gZGUgdW4gcGVyaW9kbyBkZSB0aWVtcG8gYSBvdHJvIGVzIGFsZ28gZHJhc3RpY28sIHkgdmEgZGVjcmVjaWVuZG8sIG1pZW50cmFzIHF1ZSBlbiBoaWdoLCBlbCBjb21wb3J0YW1pZW50byBlcyB2YXJpYWRvLCB5YSBxdWUsIGEgdmVjZXMgc3ViZSB5IGEgdmVjZXMgYmFqYSBzaW4gdW5hIHRlbmRlbmNpYSBhIHNlZ3Vpci4KCiMjIyAqR3LDoWZpY2EqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBsb3QobWFtX3Byb2R1Y2Npb25fZm9yZWNhc3QpCmBgYAoKIyMjIyMgVGVuZGVuY2lhIGRlbCBkZXNlbXBlw7FvIGR1cmFudGUgZWwgcGVyaW9kbyBkZSBhbsOhbGlzaXMgeSBsb3Mgc2lndWllbnRlcyAzIHBlcmlvZG9zIGRlIHRpZW1wbzogRW4gY3VhbnRvIGEgbG9zIGRhdG9zIGV4dGVybm9zLCBlcyBkZWNpciwgYSBsYSBpbmR1c3RyaWEgYXV0b21vdHJpeiwgZWwgbW9kZWxvIGRlIGVzdGltYWNpw7NuIGRlIHByb27Ds3N0aWNvIGluZGljYSBxdWUgbGEgdGVuZGVuY2lhIGVzIHBvc2l0aXZhLCBsbyBjdWFsIHF1aWVyZSBkZWNpciwgcXVlIGNhZGEgYcOxbyBzZSBwcm9uw7NzdGljYSBxdWUgaGF5YSBtw6FzIHZlaMOtY3Vsb3MgZW4gY2lyY3VsYWNpw7NuIGNvbiB1bmEgY29uZmlhbnphIGRlbCA5NSUuIExvcyBkYXRvcyBhbnRlcmlvcmVzLCBiZW5lZmljaWFuIGEgRk9STSwgZGVkdWNpZW5kbyBxdWUgc2kgaGF5IG3DoXMgYXV0b3MgZW4gY2lyY3VsYWNpw7NuLCBoYXkgbcOhcyBwcm9kdWNjacOzbiwgeSBwb3IgbG8gdGFudG8sIG3DoXMgcGVkaWRvcyB5IGNsaWVudGVzLCBzaW4gZW1iYXJnbywgZW4gbGEgYmFzZSBkZSBkYXRvcyBkaXJlY3RhbWVudGUgZGUgRk9STSwgc2Ugb2JzZXJ2YSBxdWUgZW4gYWxndW5vcyBjYXNvcywgbm8gZXhpc3RlIHVuYSB0ZW5kZW5jaWEsIHkgcXVlIHNlIGVzcGVyYW4gY29tbyBwcm9uw7NzdGljbyBsYXMgbWlzbWFzIHBpZXphcyBwcm9ncmFtYWRhcywgcG9yIGxvIHRhbnRvLCBoYWJyw61hIHF1ZSB0ZW5lciB1bmEgZXN0cmF0ZWdpYSBwYXJhIHF1ZSBtw6FzIGdlbnRlIGxsZWd1ZSBhIGNvbm9jZXIgeSBhIHNlciBwYXJ0ZSBkZSBsb3MgY2xpZW50ZXMgZGUgbGEgZW1wcmVzYS4KCiMgKipQcmVkaWNjacOzbiBkZWwgRGVzZW1wZcOxbyBkZSBsYSBJbmR1c3RyaWEgQXV0b21vdHJpeioqCgojIyMgRXhwb3J0YWNpw7NuIHkgdmVudGFzIGRlIHZlaMOtY3Vsb3MgbGlnZXJvcyAKCiMjIyBFbnRlbmRlciBsYSBiYXNlIGRlIGRhdG9zCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnN1bW1hcnkoYmRfcHJlZGljY2lvbikKc3RyKGJkX3ByZWRpY2Npb24pCmBgYAoKIyMgKkxpbXBpZXphIGRlIGRhdG9zKgoKIyMjIEVsaW1pbmFyIGNvbHVtbmFzIGlycmVsZXZhbnRlcyAoUHJvZHVjY2nDs24pCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJkX3ByZWRpY2Npb24xIDwtIHN1YnNldChiZF9wcmVkaWNjaW9uLCBzZWxlY3QgPSAtYyAoUHJvZHVjY2nDs24pKQpiZF9wcmVkaWNjaW9uMQpgYGAKCiMjIyMjIEVzdGEgY29sdW1uYSBzZSBlbGltaW5hcsOhIHBvcnF1ZSBzb2xvIHNlIHVzYXLDoW4gY29tbyB2YXJpYWJsZXMgZGVwZW5kaWVudGVzIFZlbnRhcyB5IEV4cG9ydGFjacOzbiwgeSBjb21vIHZhcmlhYmxlcyBpbmRlcGVuZGllbnRlcyBsYSBjb25maWFuemEgZGVsIGNvbnN1bWlkb3IsIGVsIHRpcG8gZGUgY2FtYmlvLCBsYSBpbmZsYWNpw7NuLCBlbCBwb3JjZW50YWplIGRlIHBlcnNvbmFzIG9jdXBhZGFzLCB5IGVsIHBvcmNlbnRhamUgZGUgcGVyc29uYXMgZGVzb2N1cGFkYXMsIGVzIGRlY2lyLCBzaW4gdHJhYmFqby4KCiMjIyBFbGltaW5hciByZW5nbG9uZXMgaXJyZWxldmFudGVzCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJkX3ByZWRpY2Npb24yIDwtIGJkX3ByZWRpY2Npb24xWy1jKDIwMSwgMjAyKSxdCmJkX3ByZWRpY2Npb24yCmBgYAoKIyMjIyBEZW50cm8gZGUgbGEgYmFzZSBkZSBkYXRvcyBoYWLDrWEgZG9zIHJlbmdsb25lcyBzaW4gY29udGVuaWRvLCBwb3IgbG8gdGFudG8sIHNlIGRlY2ljZGnDsyBlbGltaW5hcmxvLgoKIyMgKioyIG1vZGVsb3MgZGlmZXJlbnRlcyBkZSByZWdyZXNpw7NuIGxpbmVhbCBtw7psdGlwbGUgcGFyYSBwcmVkZWNpciBlbCBkZXNlbXBlw7FvIGRlIGxhIGluZHVzdHJpYSBhdXRvbW90cml6KiogCgojIyMgKkNvcnJlbGFjacOzbioKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KY29ycnBsb3QoY29yKGJkX3ByZWRpY2Npb24yKSwgdHlwZT0idXBwZXIiLG9yZGVyPSJoY2x1c3QiLGFkZGNvZWYuY29sPSJibGFjayIpCnN1bW1hcnkoYmRfcHJlZGljY2lvbjIpCmBgYAoKIyMjIyMgUHJpbWVyYW1lbnRlLCBzZSByZWFsaXpvIHVuIHBsb3QgZGUgY29ycmVsYWNpw7NuLCBjb24gZWwgZmluIGRlIG9ic2VydmFyIHNpIGxhcyB2YXJpYWJsZXMgcG9kcsOtYW4gdGVuZXIgcmVsYWNpw7NuIGVudHJlIGxhcyBtaXNtYXMgdmFyaWFibGVzIHkgbGFzIGRlbcOhcywgeSBsbyBxdWUgc2UgcHVlZGUgbm90YXIsIGVzIHF1ZSB0b2RvcyB0aWVuZW4gZWwgMTAwJSBkZSByZWxhY2nDs24sIHkgdGFtYmnDqW4gc2UgcHVlZGUgYW5hbGl6YXIgcXVlIGHDsW8geSB0aXBvIGRlIGNhbWJpbyB0YW1iacOpbiBlcyByZWxldmFudGUsIGFzw60gY29tbywgbWVzIGUgaW5mbGFjacOzbiwgdmVudGEgeSBwb3JjZW50YWplIGRlIHBlcnNvbmFzIG9jdXBhZGFzLCBsYSBleHBvcnRhY2nDs24geSBlbCBhw7FvLCBzZWd1aWRvIHBvciBlbCB0aXBvIGRlIGNhbWJpbyB5IGRlIGxhIGV4cG90YWNpw7NuLCBlbnRyZSBvdHJvcy4KCiMjICoqTW9kZWxvIGRlIHJlZ3Jlc2nDs24gMSoqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1vZGVsb19yZWdyZXNpb24xIDwtIGxtKEV4cG9ydGFjacOzbn5Bw7FvK01lcytUaXBvLmRlLmNhbWJpbytJbmZsYWNpw7NuK3BvcmNlbnRhamVfb2N1K3BvcmNlbnRhamVfZGVzb2N1K2NvbmZfY29uc3VtaWRvcixkYXRhPWJkX3ByZWRpY2Npb24yKSAKc3VtbWFyeShtb2RlbG9fcmVncmVzaW9uMSkKYGBgCgojIyMjIyBFbiBlc3RlIG1vZGVsbywgcHJpbWVybyBzZSByZWFsaXrDsyBzaW4gbGEgdmFyaWFibGUgYcOxbyB5IG1lcywgeSBzZSBwdWRvIG9ic2VydmFyIHF1ZSBlbCB0aXBvIGRlIGNhbWJpbyBlcmEgbGEgdmFyaWFibGUgcXVlIG3DoXMgaW1wYWN0YWJhIGEgbGEgZXhwb3J0YWNpw7NuLCBsbyBjdWFsIHRpZW5lIHNlbnRpZG8gc2FiaWVuZG8gcXVlIGVsIHRpcG8gZGUgY2FtYmlvIGFmZWN0YSBhIE3DqXhpY28geSBkZSBpZ3VhbCBtYW5lcmEgYWwgbXVuZG8sIGFsIGRldmFsdWFyc2UgbGEgbW9uZWRhIG1leGljYW5hLCBlcyBwb3IgZXNvIHF1ZSBNw6l4aWNvIGVzIHVuIGdyYW4gZXhwb3J0YWRvci4KIyMjIyMgUG9yIG90cm8gbGFkbywgYWwgYWdyZWdhcmxlIGxhIHZhcmlhYmxlIGHDsW8geSBtZXMsIGxhIG1heW9yw61hIGRlIGxhcyB2YXJpYWJsZXMsIGNvbiBleGNlcGNpw7NuIGRlIHBvcmNlbnRhamUgZGUgcGVyc29uYXMgZGVzb2N1cGFkYXMgdGVuw61hbiBsb3MgMyBhc3RlcmlzY29zLCBwb3IgbG8gdGFudG8gc2UgY29uc2lkZXJhbiB2YXJpYWJsZXMgaW1wYWN0YW50ZXMuCgojIyMgKkdyw6FmaWNhKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQplZmZlY3RfcGxvdChtb2RlbG9fcmVncmVzaW9uMSxwcmVkPVRpcG8uZGUuY2FtYmlvLGludGVydmFsPVRSVUUpCmBgYAoKIyMjIyMgQ29tbyBzZSBwdWVkZSBvYnNlcnZhciBlbiBsYSBncsOhZmljYSwgbGEgdGVuZGVuY2lhIHF1ZSBzaWd1ZSBlcyBuZWdhdGl2YSwgZXN0byBxdWllcmUgZGVjaXIsIHF1ZSBlbnRyZSBtw6FzIGN1ZXN0ZSB1biBkb2xhciBlbiBwZXNvcyBNw6l4aWNhbm9zIG8gcXVlIGVsIHRpcG8gZGUgY2FtYmlvIHNlYSBtw6FzIGJham8sIG1lbm9zIHNlIGV4cG9ydGEuCgojIyAqKk1vZGVsbyBkZSByZWdyZXNpw7NuIDIqKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptb2RlbG9fcmVncmVzaW9uMiA8LSBsbShWZW50YX5Bw7FvK01lcytUaXBvLmRlLmNhbWJpbytJbmZsYWNpw7NuK3BvcmNlbnRhamVfb2N1K3BvcmNlbnRhamVfZGVzb2N1K2NvbmZfY29uc3VtaWRvcixkYXRhPWJkX3ByZWRpY2Npb24yKQpzdW1tYXJ5KG1vZGVsb19yZWdyZXNpb24yKQpgYGAKCiMjIyMjIEVuIGVzdGUgbW9kZWxvIGRlIHJlZ3Jlc2nDs24sIGVuIGx1Z2FyIGRlIGV4cG9ydGFjaW9uZXMsIHNlIHRvbWFyb24gZW4gY3VlbnRhIGxhcyB2ZW50YXMgZGUgdmVoaWN1bG9zLCB5IGRlIGlndWFsIGZvcm1hIHNlIGdyYWZpY28gZG9zIHZlY2VzLCBsYSBwcmltZXJhIHNpbiBhw7FvIHkgbWVzLCBsbyBjdWFsIG5vcyBkYWJhIGNvbW8gdmFyaWFibGUgc2lnbmlmaWNhdGl2YSBsYSBkZSBwb3JjZW50YWplIGRlIHBvYmxhY2nDs24gb2N1cGFkYSwgeSBkZXNwdcOpcyBhZ3JlZ2FuZG8gbGFzIHZhcmlhYmxlcyBhw7FvIHkgbWVzLCBsYSBtYXlvcsOtYSBkZSBsYXMgdmFyaWFibGVzIHR1dmllcm9uIHNlbnRpZG8gY29uIGxvcyAzIGFzdGVyaXNjb3MsIGEgZXhjZXBjacOzbiBkZWwgcG9yY2VudGFqZSBkZSBwb2JsYWNpw7NuIGRlc29jdXBhZGEgeSBlbCB0aXBvIGRlIGNhbWJpby4gIAoKIyMjICpHcsOhZmljYSoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZWZmZWN0X3Bsb3QobW9kZWxvX3JlZ3Jlc2lvbjIscHJlZD1wb3JjZW50YWplX29jdSxpbnRlcnZhbD1UUlVFKQpgYGAKCiMjIyMjIEFxdcOtIHNlIG9ic2VydmEgcXVlIGxhIHRlbmRlbmNpYSBkZSBsYSBncsOhZmljYSBlcyBwb3NpdGl2YSwgeSBsbyBxdWUgc2UgZ3JhZmljw7MgZnVlcm9uIGxhcyB2ZW50YXMgeSBsYSB2YXJpYWJsZSBzaWduaWZpY2F0aXZhIHF1ZSBmdWUgcG9yY2VudGFqZSBkZSBwb2JsYWNpw7NuIG9jdXBhZGEuIFBhcmEgaW50ZXJwcmV0YXIgZGUgZm9ybWEgZ2VuZXJhbCwgbGEgZ3LDoWZpY2EgcXVpZXJlIGRlY2lyIHF1ZSBlbnRyZSBtw6FzIHBvcmNlbnRhamUgZGUgcG9ibGFjacOzbiBjdWVudGUgY29uIHRyYWJham8sIG3DoXMgdmVudGFzIGhhYnLDoS4KCiMjICpEZXNjcmlwY2nDs24gZGUgdmFyaWFibGVzKgojIyMjIEHDsW8gLSBBw7FvIGVuIGVsIHF1ZSBzZSBlZmVjdMO6byBsYSBleHBvcnRhY2nDs24gbyB2ZW50YS4KIyMjIyBNZXMgLSBNZXMgY29ycmVzcG9uZGllbnRlIGFsIGHDsW8gZW4gZWwgcXVlIHNlIGVmZWN0w7pvIGxhIGV4cG9ydGFjacOzbiBvIHZlbnRhLiAKIyMjIyBWZW50YSAodmFyaWFibGUgZGVwZW5kaWVudGUpIC0gVmVudGEgZW4gTcOpeGljbyBkZSB2ZWjDrWN1bG9zIGxpZ2Vyb3MgZW4gdW5pZGFkZXMuCiMjIyMgRXhwb3J0YWNpw7NuICh2YXJpYWJsZSBkZXBlbmRpZW50ZSkgLSBFeHBvcnRhY2nDs24gZW4gTcOpeGljbyBkZSB2ZWjDrWN1bG9zIGxpZ2Vyb3MgZW4gdW5pZGFkZXMuCiMjIyMgVGlwbyBkZSBjYW1iaW8gKHZhcmlhYmxlIGluZGVwZW5kaWVudGUpIC0gUmVnaXN0cm9zIGhpc3Rvcmljb3MgZGVsIGRvbGFyIGVuIE3DqXhpY28uCiMjIyMgSW5mbGFjacOzbiAodmFyaWFibGUgaW5kZXBlbmRpZW50ZSktIEluZmxhY2nDs24gZHVyYW50ZSBsb3MgYcOxb3MgZGVmaW5pZG9zLgojIyMjIHBvcmNlbnRhamVfb2N1ICh2YXJpYWJsZSBpbmRlcGVuZGllbnRlKSAtIFBvcmNlbnRhamUgZGUgbGEgcG9ibGFjacOzbiBvY3VwYWRhLgojIyMjIHBvcmNlbnRhamVfZGVzb2N1ICh2YXJpYWJsZSBpbmRlcGVuZGllbnRlKSAtIFBvcmNlbnRhamUgZGUgbGEgcG9ibGFjacOzbiBkZXNvY3VwYWRhLgojIyMjIGNvbmZfY29uc3VtaWRvciAodmFyaWFibGUgaW5kZXBlbmRpZW50ZSkgLSBDb25maWFuemEgZGVsIGNvbnN1bWlkb3IgZW4gbGEgaW5kdXN0cmlhIGF1dG9tb3RyaXogZW4gTcOpeGljby4KCiMjICpJbnRlcnByZXRhY2nDs24gZGUgbG9zIG1vZGVsb3MgZGUgcmVncmVzacOzbjoqCgojIyMjIyBEZXNwdcOpcyBkZSBhbmFsaXphciBhbWJvcyBtb2RlbG9zIGRlIHJlZ3Jlc2nDs24sIHNlIHB1ZWRlIGRlc3RhY2FyIHF1ZSBwYXJhIGxhIHZhcmlhYmxlIGRlcGVuZGllbnRlIGRlIGV4cG9ydGFjaW9uZXMsIGxhIHZhcmlhYmxlIGluZGVwZW5kaWVudGUgcXVlIG3DoXMgaW1wYWN0YSBlcyBsYSBkZSB0aXBvLmRlLmNhbWJpbywgZXN0YSBpbXBhY3RhIGRlIG1hbmVyYSBxdWUgbGEgdGVuZGVuY2lhIHNlIHZ1ZWx2ZSBuZWdhdGl2YSwgZGFuZG8gYSBjb25vY2VyIHF1ZSBlbnRyZSBtw6FzIGF1bWVudGUgZWwgcGVzbyBtZXhpY2FubyBjb24gcmVzcGVjdG8gYWwgZG9sYXIsIGxhcyBleHBvcnRhY2lvbmVzIGJhamFuLiAKCiMjIyMjIFBvciBvdHJvIGxhZG8sIGxhIHZhcmlhYmxlIGRlcGVuZGllbnRlIGRlIHZlbnRhcywgc2UgdmUgYWZlY3RhZGEgcHJpbmNpcGFsbWVudGUgcG9yIGxhIHZhcmlhYmxlIGluZGVwZW5kaWVudGUgZGUgcG9yY2VudGFqZSBkZSBwb2JsYWNpw7NuIG9jdXBhZGEsIGVzIGRlY2lyLCBsYSBxdWUgY3VlbnRhIGNvbiB2aWRhIGxhYm9yYWwsIGVzdG8gaGFjZSBzZW50aWRvLCB5YSBxdWUsIHNpIGhheSBpbmdyZXNvcywgZXMgbcOhcyBwcm9iYWJsZSBxdWUgaGF5YSBtw6FzIHZlbnRhcy4gCgojIyMjIyBQb3Igw7psdGltbywgbGEgdGVuZGVuY2lhIGRlIGxhIGdyw6FmaWNhIGVzIHBvc2l0aXZhLCBsbyBjdWFsIHNpZ25pZmljYSwgcXVlIGVudHJlIG3DoXMgZ3JhbmRlIGVsIHBvcmNlbnRhamUgZGUgcG9ibGFjacOzbiBvY3VwYWRhLCBtw6FzIGVsZXZhZGFzIMOxYXMgdmVudGFzLgoKIyAqKkstTWVhbnMgQ2x1c3RlcmluZyoqCgojIyMgKklkZW50aWZpY2FyIHkgdmlzdWFsaXphciBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBjbMO6c3RlcnMqCgojIyMgKlBhc28gMS4gSW5zdGFsYXIgbGlicmVyw61hcyoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShmb3JlaWduKQpsaWJyYXJ5KGRwbHlyKSAgICAgICAgCmxpYnJhcnkoZ2dwbG90MikgICAgICAKbGlicmFyeShwc3ljaCkgICAgICAgIApsaWJyYXJ5KGNvcnJwbG90KSAgICAgCmxpYnJhcnkoanRvb2xzKSAgICAgICAKbGlicmFyeShsbXRlc3QpICAgICAgIApsaWJyYXJ5KGNhcikgICAgICAgICAgCmxpYnJhcnkoZmFjdG9leHRyYSkgIApsaWJyYXJ5KGphbml0b3IpCmBgYAoKIyMjICpQYXNvIDIuIENyZWFjacOzbiBkZSBDbMO6c3RlcnMqCgojIyAqKkNsdXN0ZXIgMTogUmVsYWNpw7NuIGRlIHZhcmlhYmxlcyBkZSBFZGFkIHkgTsO6bWVybyBkZSBkw61hcy4qKgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQplZGFkIDwtYmFqYXMgCmVkYWQ8LSBzdWJzZXQoYmFqYXMsc2VsZWN0ID0gLWMoZ2VuZXJvLCBtb3Rpdm9fZGVfYmFqYSwgcHVlc3RvLCBzYWxhcmlvX2RpYXJpb19pbXNzLCBlc3RhZG9fY2l2aWwpKQoKI05vcm1hbGl6YXIgdmFyaWFibGVzCmVkYWRfbm9ybTwtc2NhbGUoZWRhZFsxOjJdKSAKCiNGdW5jacOzbiBmdml6IHBhcmEgbGEgdmlzdWFsaXphY2nDs24gZGUgdW4gRWxib3cgUGxvdCB5IGFzw60gZGV0ZXJtaW5hciBlbCBuw7ptZXJvIGRlIGNsdXN0ZXJzLgpmdml6X25iY2x1c3QoZWRhZF9ub3JtLCBrbWVhbnMsIG1ldGhvZD0id3NzIikrIAogIGdlb21fdmxpbmUoeGludGVyY2VwdD00LCBsaW5ldHlwZT0yKSsgICAgICAgICAgICAKICBsYWJzKHN1YnRpdGxlID0gIkVsYm93IG1ldGhvZCIpCgpgYGAKCiMjIyMjIENvbiBlc3RhIGdyw6FmaWNhIHBvZGVtb3MgdmlzdWFsaXphciBxdWUgZWwgKipuw7ptZXJvIMOzcHRpbW8gZGUgY2zDunN0ZXJzIHNvbiA0IChvcHRpbWl6YWNpw7NuKS4qKgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI1Zpc3VhbGl6YXIgY2x1c3RlcnMKZWRhZF9jbHVzdGVyPC1rbWVhbnMoZWRhZF9ub3JtLDQpCmVkYWRfY2x1c3RlcgoKI1Zpc3VhbGl6YXIgcmVzdWx0YWRvczoKZnZpel9jbHVzdGVyKGVkYWRfY2x1c3RlcixkYXRhPWVkYWRfbm9ybSkKYGBgCgojIyMjIyBMb3MgKiptw6FzIGrDs3ZlbmVzIHNvbiBsb3MgcXVlIG1lbm9zIGTDrWFzIGRlIHRyYWJham8gbGFib3Jhbi4qKiBBc8OtIGNvbW8gcXVlICoqbG9zIHF1ZSBtw6FzIGTDrWFzIGxhYm9yYWxlcyB0aWVuZW4sIHNvbiBsb3MgYWR1bHRvcyoqIGRlc2RlIGxvcyAyNyBhw7FvcyBoYXN0YSBsb3MgNjEuCgojIyAqQ2x1c3RlciAyOiBSZWxhY2nDs24gZGUgdmFyaWFibGVzIGRlIEVkYWQgeSBTYWxhcmlvIERpYXJpby4qCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmVkYWRfc2FsYXJpbyA8LWJhamFzIAplZGFkX3NhbGFyaW88LSBzdWJzZXQoYmFqYXMsc2VsZWN0ID0gLWMoZ2VuZXJvLGVzdGFkb19jaXZpbCxtb3Rpdm9fZGVfYmFqYSwgcHVlc3RvLCBub19kaWFzKSkKCiNOb3JtYWxpemFyIHZhcmlhYmxlcwplZGFkX3NhbGFyaW9fbm9ybTwtc2NhbGUoZWRhZF9zYWxhcmlvWzE6Ml0pIAoKI0Z1bmNpw7NuIGZ2aXogcGFyYSBsYSB2aXN1YWxpemFjacOzbiBkZSB1biBFbGJvdyBQbG90IHkgYXPDrSBkZXRlcm1pbmFyIGVsIG7Dum1lcm8gZGUgY2x1c3RlcnMuCmZ2aXpfbmJjbHVzdChlZGFkX3NhbGFyaW9fbm9ybSwga21lYW5zLCBtZXRob2Q9IndzcyIpKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9NCwgbGluZXR5cGU9MikrICAgICAgICAgICAgCiAgbGFicyhzdWJ0aXRsZSA9ICJFbGJvdyBtZXRob2QiKSAKYGBgCgojIyMjIyBDb24gZXN0YSBncsOhZmljYSBwb2RlbW9zIHZpc3VhbGl6YXIgcXVlIGVsICoqbsO6bWVybyDDs3B0aW1vIGRlIGNsw7pzdGVycyBzb24gNCAob3B0aW1pemFjacOzbikuKioKCiMjIyAqVmlzdWFsaXphciBjbHVzdGVycyB5IHJlc3VsdGFkb3M6KgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQplZGFkX3NhbGFyaW9fY2x1c3Rlcjwta21lYW5zKGVkYWRfc2FsYXJpb19ub3JtLDQpCmVkYWRfc2FsYXJpb19jbHVzdGVyCgpmdml6X2NsdXN0ZXIoZWRhZF9zYWxhcmlvX2NsdXN0ZXIsZGF0YT1lZGFkX3NhbGFyaW9fbm9ybSkKYGBgCgojIyMjIyBMYSAqKmVkYWQgbm8gdGllbmUgbXVjaGEgaW5mbHVlbmNpYSBlbiBlbCBzYWxhcmlvLioqIFB1ZXMgbG9zIGNvbGFib3JhZG9yZXMgcXVlIHNlIGhhbiBkYWRvIGRlIGJhamEgdGllbmVuIHVuIHNhbGFyaW8gbXV5IHNpbWlsYXIgaW5kZXBlbmRpZW50ZW1lbnRlIGRlIHN1IGVkYWQuCgojIyAqQ2x1c3RlciAzOiBSZWxhY2nDs24gZGUgdmFyaWFibGVzIGRlIFNhbGFyaW8gRGlhcmlvIHkgTsO6bWVybyBkZSBkw61hcy4qCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRpYXNfc2FsYXJpbyA8LWJhamFzIApkaWFzX3NhbGFyaW88LSBzdWJzZXQoYmFqYXMsc2VsZWN0ID0gLWMoZ2VuZXJvLGVzdGFkb19jaXZpbCxtb3Rpdm9fZGVfYmFqYSwgcHVlc3RvLCBlZGFkKSkKCiNOb3JtYWxpemFyIHZhcmlhYmxlczoKZGlhc19zYWxhcmlvX25vcm08LXNjYWxlKGRpYXNfc2FsYXJpb1sxOjJdKSAKCiNGdW5jacOzbiBmdml6IHBhcmEgbGEgdmlzdWFsaXphY2nDs24gZGUgdW4gRWxib3cgUGxvdCB5IGFzw60gZGV0ZXJtaW5hciBlbCBuw7ptZXJvIGRlIGNsdXN0ZXJzLgpmdml6X25iY2x1c3QoZGlhc19zYWxhcmlvX25vcm0sIGttZWFucywgbWV0aG9kPSJ3c3MiKSsgCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTQsIGxpbmV0eXBlPTIpKyAgICAgICAgICAgIAogIGxhYnMoc3VidGl0bGUgPSAiRWxib3cgbWV0aG9kIikgCgpgYGAKCiMjIyMjIENvbiBlc3RhIGdyw6FmaWNhIHBvZGVtb3MgdmlzdWFsaXphciBxdWUgZWwgKipuw7ptZXJvIMOzcHRpbW8gZGUgY2zDunN0ZXJzIHNvbiA0IChvcHRpbWl6YWNpw7NuKS4qKgoKIyMjICpWaXN1YWxpemFyIGNsdXN0ZXJzIHkgcmVzdWx0YWRvczoqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRpYXNfc2FsYXJpb19jbHVzdGVyPC1rbWVhbnMoZGlhc19zYWxhcmlvX25vcm0sNCkKZGlhc19zYWxhcmlvX2NsdXN0ZXIKCmZ2aXpfY2x1c3RlcihkaWFzX3NhbGFyaW9fY2x1c3RlcixkYXRhPWRpYXNfc2FsYXJpb19ub3JtKQoKcHJvbWVkaW9fZGlhcyA8LSBtZWFuKGJhamFzJG5vX2RpYXMpCnByb21lZGlvX2RpYXMKYGBgCgojIyMjIyBFbiBlc3RlIGNsw7pzdGVyIHBvZGVtb3Mgb2JzZXJ2YXIgcXVlIHBvciBtw6FzIGFudGlnw7xlZGFkIG8gZMOtYXMgcXVlIGxhYm9yZXMgZW4gRk9STSwgKipubyBoYXkgbXVjaGEgcG9zaWJpbGlkYWQgZGUgY3JlY2ltaWVudG8gbGFib3JhbCAoZWNvbsOzbWljYW1lbnRlIGhhYmxhbmRvKSoqLCBwdWVzIHNlZ8O6biBlbCBjbHVzdGVyIHJlYWxpemFkbywgKipubyBpbmZsdXllbiBsb3MgZMOtYXMgbGFib3JhZG9zIGNvbiBlbCBzYWxhcmlvIGRpYXJpby4qKgoKIyMjICpQYXNvIDMuQ3JlYWNpw7NuIGRlIFNlZ21lbnRvcyBhcGFydGlyIGRlIGxvcyBDbMO6c3RlcnM6KgojIyMjIyBEZWNpZGltb3MgdXNhciBlbCBDbHVzdGVyIDIgcGFyYSBnZW5lcmFyIGxhIGNsYXNpZmljYWNpw7NuIGRlIHZhcmlhYmxlcyB5IHBvZGVyIGNvbXBhcmFyIGNvbiBkYXRvcyBjdWFsaXRhdGl2b3MuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojQcOxYWRpciBhIGxhIGJhc2UgZGUgZGF0b3MgbGEgY29sdW1uYSBkZSBDbHVzdGVycyB5IHN1IGNsYXNpZmljYWNpw7NuOgpiYWphczE8LWJhamFzCmJhamFzMSRDbHVzdGVyczwtZWRhZF9zYWxhcmlvX2NsdXN0ZXIkY2x1c3RlcgoKbGlicmFyeShkcGx5cikKbGlicmFyeShmYWN0b2V4dHJhKSAKCiNJZGVudGlmaWNhbW9zIGxhIGNsYXNpZmljYWNpw7NuIGRlIGxhcyBkaXN0aW50YXMgZWRhZGVzIGRlIGxvcyBjb2xhYm9yYWRvcmVzLgpiYWphczI8LWJhamFzMSAlPiUgZ3JvdXBfYnkoQ2x1c3RlcnMpICU+JSBkcGx5cjo6c3VtbWFyaXNlKGVkYWQ9bWF4KGVkYWQpKSAlPiUgYXJyYW5nZShkZXNjKGVkYWQpKQpiYWphczEkQ2x1c3Rlcl9OYW1lczwtZmFjdG9yKGJhamFzMSRDbHVzdGVycyxsZXZlbHMgPSBjKDEsMiwzLDQpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk91dGxpZXIiLCAiSm92ZW4iLCAiQXZhbnphZGEiLCAiQWR1bHRhIikpCmJhamFzMyA8LSBiYWphczEgJT4lIGdyb3VwX2J5KENsdXN0ZXJfTmFtZXMpICU+JSBkcGx5cjo6c3VtbWFyaXplKGVkYWRfYcOxb3M9bWF4KGVkYWQpLCBzYWxhcmlvX2ltc3M9bWVhbihzYWxhcmlvX2RpYXJpb19pbXNzKSxDb3VudD1uKCkpCmNsdXN0ZXJzPC1hcy5kYXRhLmZyYW1lKGJhamFzMykKY2x1c3RlcnMKCmBgYAoKIyMjICpQYXNvIDUuIEdlbmVyYWNpw7NuIGRlIGdyw6FmaWNvczoqCiMjIyAqR3LDoWZpY29zIGN1YW50aXRhdGl2b3M6KgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojU2UgcmVhbGl6w7MgdW5hIGdyw6FmaWNhIHBhcmEgYW5hbGl6YXIgZWwgbsO6bWVybyBkZSByZWdpc3Ryb3MgcG9yIGNhZGEgc2VnbWVudG86IApnZ3Bsb3QoYmFqYXMzLGFlcyh4PXJlb3JkZXIoQ2x1c3Rlcl9OYW1lcyxDb3VudCkseT1Db3VudCxmaWxsPUNsdXN0ZXJfTmFtZXMpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKQoKYGBgCgojIyMjIyMgTG9zICoqY29sYWJvcmFkb3JlcyBxdWUgbcOhcyBiYWphcyBoYW4gcHJlc2VudGFkbyoqIHNlZ8O6biBsYSBncsOhZmljYSBhbnRlcmlvciBzb24gKipqw7N2ZW5lcyoqLCBzZWd1aWRvIHBvciBsb3MgYWR1bHRvcyB5IGRlc3B1w6lzIGxvcyBjb2xhYm9yYWRvcmVzIGRlIGVkYWQgYXZhbnphZGEuCgojIyMgVmlzdWFsaXphciBsYSBlZGFkIHBvciBjYWRhIHNlZ21lbnRvOgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoYmFqYXMzLCBhZXMoeD1DbHVzdGVyX05hbWVzLHk9ZWRhZF9hw7FvcyxmaWxsPSBDbHVzdGVyX05hbWVzLGxhYmVsPXJvdW5kKGVkYWRfYcOxb3MsZGlnaXRzPTIpKSkgKyAKICBnZW9tX2NvbCgpICsgCiAgZ2VvbV90ZXh0KCkKYGBgCgojIyMjIyBWaXN1YWxpemFjacOzbiBkZSBsb3MgbcOheGltb3MgZGUgY2FkYSBzZWdtZW50bzogKkrDs3ZlbmVzIChoYXN0YSBsb3MgMjgpLCBBdmFuemFkYSAoSGFzdGEgbG9zIDYxKSwgQWR1bHRhIChIYXN0YSBsb3MgNDApIHkgZWwgT3V0bGllciBkZSAzMi4qCgojIyMgKkdyw6FmaWNhcyBtaXh0YXMgKERhdG9zIEN1YWxpdGF0aXZvcyB5IEN1YW50aXRhdGl2b3MpOioKCiMjIyBHcsOhZmljYSBkZSBiYXJyYXM6IChDbHVzdGVycyB5IEfDqW5lcm8pCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdChiYWphczEsIGFlcyhmYWN0b3IoQ2x1c3Rlcl9OYW1lcyksIGZpbGwgPSBmYWN0b3IoZ2VuZXJvKSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlMihwcmVzZXJ2ZSA9ICJzaW5nbGUiKSkgCmBgYAoKIyMjIyMgRXN0ZSBncsOhZmljbyBub3MgZGljZSBxdWUgZGUgY2FkYSBzZWdtZW50bywgKipoYXkgbcOhcyBtdWplcmVzIHF1ZSBzZSBoYW4gZGFkbyBkZSBiYWphLioqCgojIyMgR3LDoWZpY2EgZGUgYmFycmFzOiAoQ2x1c3RlcnMgeSBFc3RhZG8gQ2l2aWwpCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdChiYWphczEsIGFlcyhmYWN0b3IoQ2x1c3Rlcl9OYW1lcyksIGZpbGwgPSBmYWN0b3IoZXN0YWRvX2NpdmlsKSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlMihwcmVzZXJ2ZSA9ICJzaW5nbGUiKSkgCmBgYAoKIyMjIyMgUG9kZW1vcyB2aXN1YWxpemFyIHF1ZSBkZSBkZSBsb3MgasOzdmVuZXMsIGxhIG1heW9yw61hIGVyYW4gc29sdGVyb3MsIGRlIGxvcyBhZHVsdG9zIGhhYsOtYSBsYSBtaXNtYSBjYW50aWRhZCBkZSBjYXNhZG9zLCBzb2xlcm9zIHkgZW4gdW5pw7NuIGxpYnJlIHkgZW4gYXZhbnphZG9zIGVyYW4gbcOhcyBzb2x0ZXJvcyB5IGNhc2Fkb3MuIE3DoXMgc2luIGVtYmFyZ28sICoqaGF5IG11eSBwb2NvcyBjb2xhYm9yYWRvcmVzIHF1ZSBzZSBoYW4gZGFkbyBkZSBiYWphIGRpdm9yY2lhZG9zLioqCgojIyMgR3LDoWZpY2EgZGUgYmFycmFzOiAoQ2x1c3RlcnMgeSBNb3Rpdm8gZGUgQmFqYSkKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KGJhamFzMSwgYWVzKGZhY3RvcihDbHVzdGVyX05hbWVzKSwgZmlsbCA9IGZhY3Rvcihtb3Rpdm9fZGVfYmFqYSkpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZTIocHJlc2VydmUgPSAic2luZ2xlIikpIApgYGAKCiMjIyMjIFBvZGVtb3Mgb2JzZXJ2YXIgcXVlIGVuIGVsIHNlZ21lbnRvIGRlIGNvbGFib3JhZG9yZXMgam92ZW5lcywgYWR1bHRvcyB5IGRlIGVkYWQgYXZhbnphZGEsICoqbGEgbWF5b3IgcGFydGUgc2UgaGEgZGFkbyBkZSBiYWphIHBvciBmYWx0YXMsIHNpZ3VpZW5kbyBhc8OtIHBvciByZW51bmNpYSB2b2x1bnRhcmlhLioqCgojIyMgR3LDoWZpY2EgZGUgcGF5OiAoUHVlc3RvKQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp0YWJsZShiYWphczEkcHVlc3RvKQpwcm9wb3JjaW9uZXMgPC0gYygyMywgMTc5LCAxMSwgMTEsIDcsIDUpCmV0aXF1ZXRhcyA8LSBjKCJPdHJvcyIsIkF5dWRhbnRlIEdlbmVyYWwiLCAiQ29zdHVyZXJhIiwgIlNvbGRhZG9yIiwgIkF5dWRhbnRlIEVtYmFycXVlcyIsICJNb250YWNhcmd1aXN0YSIpCnBjdCA8LSByb3VuZChwcm9wb3JjaW9uZXMvc3VtKHByb3BvcmNpb25lcykqMTAwKQpldGlxdWV0YXMgPC0gcGFzdGUoZXRpcXVldGFzLCBwY3QpCmV0aXF1ZXRhcyA8LSBwYXN0ZShldGlxdWV0YXMsIiUiLHNlcD0iIikKcGllKHByb3BvcmNpb25lcyxsYWJlbHMgPSBldGlxdWV0YXMsCiAgICBjb2w9cmFpbmJvdyhsZW5ndGgoZXRpcXVldGFzKSksCiAgICBtYWluPSJQdWVzdG8gZGUgbG9zIEV4LUNvbGFib3JhZG9yZXMiKQoKYGBgCgojIyMgR2dsbHV2aWFsCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpiYWphczQgPC1iYWphczEgJT4lIGZpbHRlcihDbHVzdGVycz09MSB8IENsdXN0ZXJzPT0zKSAlPiUgYXJyYW5nZShDbHVzdGVycykKbGlicmFyeShnZ2FsbHV2aWFsKQoKZ2dwbG90KGFzLmRhdGEuZnJhbWUoYmFqYXM0KSwKICAgICAgIGFlcyh5PW5vX2RpYXMsIGF4aXMxPSBnZW5lcm8sIGF4aXMyPWVzdGFkb19jaXZpbCkpICsKICBnZW9tX2FsbHV2aXVtKGFlcyhmaWxsPUNsdXN0ZXJfTmFtZXMpLCB3aWR0aCA9IDEvMTIpICsKICBnZW9tX3N0cmF0dW0od2lkdGggPSAxLzEyLCBmaWxsID0gImJsYWNrIiwgY29sb3IgPSAiZ3JleSIpICsKICBnZW9tX2xhYmVsKHN0YXQgPSAic3RyYXR1bSIsIGFlcyhsYWJlbCA9IGFmdGVyX3N0YXQoc3RyYXR1bSkpKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKCJHZW5kZXIiLCAiTWFyaXRhbCBTdGF0dXMiKSwgZXhwYW5kID0gYyguMDUsIC4wNSkpICsKICBzY2FsZV9maWxsX2JyZXdlcih0eXBlID0gInF1YWwiLCBwYWxldHRlID0gIlNldDEiKSArCiAgZ2d0aXRsZSgiRk9STSdzIEFudGlnw7xlZGFkIGRlIGJhamFzIHBvciBHZW5lcm8geSBFc3RhZG8gQ2l2aWwiKQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJhamFzNSA8LWJhamFzMSAlPiUgZmlsdGVyKENsdXN0ZXJzPT0yIHwgQ2x1c3RlcnM9PTQpICU+JSBhcnJhbmdlKENsdXN0ZXJzKQpsaWJyYXJ5KGdnYWxsdXZpYWwpCgpnZ3Bsb3QoYXMuZGF0YS5mcmFtZShiYWphczUpLAogICAgICAgYWVzKHk9bm9fZGlhcywgYXhpczE9IGdlbmVybywgYXhpczI9ZXN0YWRvX2NpdmlsKSkgKwogIGdlb21fYWxsdXZpdW0oYWVzKGZpbGw9Q2x1c3Rlcl9OYW1lcyksIHdpZHRoID0gMS8xMikgKwogIGdlb21fc3RyYXR1bSh3aWR0aCA9IDEvMTIsIGZpbGwgPSAiYmxhY2siLCBjb2xvciA9ICJncmV5IikgKwogIGdlb21fbGFiZWwoc3RhdCA9ICJzdHJhdHVtIiwgYWVzKGxhYmVsID0gYWZ0ZXJfc3RhdChzdHJhdHVtKSkpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IGMoIkdlbmRlciIsICJNYXJpdGFsIFN0YXR1cyIpLCBleHBhbmQgPSBjKC4wNSwgLjA1KSkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHR5cGUgPSAicXVhbCIsIHBhbGV0dGUgPSAiU2V0MSIpICsKICBnZ3RpdGxlKCJGT1JNJ3MgQW50aWfDvGVkYWQgZGUgYmFqYXMgcG9yIEdlbmVybyB5IEVzdGFkbyBDaXZpbCIpCmBgYAoKIyMgKklkZW50aWZpY2FyIHkgZGVzY3JpYmlyIGxvcyBoYWxsYXpnb3MgZGUgbG9zIGNsw7pzdGVyczoqCgojIyMjIyAxLiBMYSBlZGFkIGRlIGxvcyBjb2xhYm9yYWRvcmVzIHF1ZSBzZSBoYW4gZGFkbyBkZSBiYWphLCBubyB0aWVuZSBpbmZsdWVuY2lhIGVuIHN1IHNhbGFyaW8uCgojIyMjIyAyLiBFbCBzYWxhcmlvIGluZmx1eWUgbXVjaG8gZW4gbGFzIGJhamFzLCBwdWVzIHRvZG9zIGxvcyBxdWUgc2UgaGFuIGRhZG8gZGUgYmFqYSB0aWVuZW4gdW4gc2FsYXJpbyBwcm9tZWRpbyBtZW5vciBhICQxODAgZGlhcmlvcy4gU29sYW1lbnRlIHVuIGNvbGFib3JhZG9yIGNvbiB1biBzYWxhcmlvIG1heW9yICgkNTAwKSBzZSBoYSBkYWRvIGRlIGJhamEuCgojIyMjIyAzLiBMb3MgZMOtYXMgbGFib3JhbGVzIChhbnRpZ8O8ZWRhZCkgZGUgdW4gY29sYWJvcmFkb3IsIG5vIGluZmx1eWVuIGNvbiBlbCBzYWxhcmlvLCBhbCBtZW5vcyBjb24gbG9zIHF1ZSBzZSBoYW4gZGFkbyBkZSBiYWphLiBMbyBxdWUgcHVlZGUgc2lnbmlmaWNhciBxdWUgbGEgb3BvcnR1bmlkYWQgZGUgY3JlY2VyIGVjb27Ds21pY2FtZW50ZSBlbiBGT1JNIGRlIGFjdWVyZG8gYSB0dSBhbnRpZ8O8ZWRhZCBlcyBtw61uaW1hLgoKIyMjIyMgNC4gTGEgbWF5b3LDrWEgZGUgbG9zIGNvbGFib3JhZG9yZXMgcXVlIHNlIGhhbiBkYWRvIGRlIGJhamEsIG5vIGhhbiB0cmFiYWphZG8gbcOhcyBkZSAzIG1lc2VzICg3OSBkw61hcykgZW4gRk9STS4KCiMjIyMjIDUuIExvcyBjb2xhYm9yYWRvcmVzIHF1ZSBtw6FzIGJhamFzIGhhbiBwcmVzZW50YWRvIHNvbiBqw7N2ZW5lcyAoZGUgZWRhZGVzIGRlIGxvcyAxOC0yOCBhw7FvcykuCgojIyMjIyA2LiBJbmRlcGVuZGllbnRlbWVudGUgZGUgc2kgbG9zIGV4LWNvbGFib3JhZG9yZXMgc29uIGrDs3ZlbmVzLCBhZHVsdG9zIG8gbWF5b3JlcywgZGUgY2FkYSBzZWdtZW50byBsYXMgbXVqZXJlcyBzb24gbGFzIHF1ZSBoYW4gcHJlc2VudGFkbyBtw6FzIGJhamFzLgoKIyMjIyMgNy4gRk9STSBoYSBkZXNwZWRpZG8gbcOhcyBjb2xhYm9yYWRvcmVzIGRlIGxvcyBxdWUgaGFuIHJlbnVuY2lhZG8sIHNpZW5kbyBsYSBwcmluY2lwYWwgY2F1c2EgbGEg4oCcQmFqYSBwb3IgZmFsdGFz4oCdLiBMbyBxdWUgcHVlZGUgc2lnbmlmaWNhciBxdWUgc3UgcHJvY2VzbyBkZSBjb250cmF0YWNpw7NuIG5vIGVzIGVsIG3DoXMgw7NwdGltbyB5YSBxdWUgdGVybWluYW4gY29udHJhdGFuZG8gcGVyc29uYWwgcXVlIG5vIGVyYSBlbCBhZGVjdWFkbyBwYXJhIGVsIHB1ZXN0by4KCiMgKipJZGVudGlmaWNhY2nDs24gZGUgUmVzdWx0YWRvcyBSZWxldmFudGVzKioKCiMjICoqQSBwYXJ0aXIgZGVsIGFuw6FsaXNpcyBkZSBsYXMgYmFzZXMgZGUgZGF0b3MgZGUgbGFzIGRpZmVyZW50ZXMgw6FyZWFzIGRlIGxhIGVtcHJlc2EgRk9STSwgaWRlbnRpZmljYXIgeSBkZXNjcmliaXIgbG9zIHByaW5jaXBhbGVzIDYtOCBoYWxsYXpnb3MgKG1lYW5pbmdmdWwgaW5zaWdodHMpLioqCgojIyMjIyBGT1JNIHByb2R1Y2UgZW4gcHJvbWVkaW8gMzcwOC41MiBraWxvcyBkZSBtZXJtYSBwb3IgbWVzLiAKCiMjIyMjIFNlIHByb2R1am8gdW5hIG1heW9yIGNhbnRpZGFkIGRlIHBpZXphcyBlbiBlbCBtZXMgZGUgYWdvc3RvLgoKIyMjIyMgQSB1biB0aWVtcG8gbWF5b3IgZGUgcHJvZHVjY2nDs24sIEZPUk0gbGUgaW52aWVydGUgbWVub3MgaG9yYXMgZGUgY2FsaWRhZCBlbiBsYXMgdW5pZGFkZXMgcHJvZHVjaWRhcyBGT1JNIHRpZW5lIHViaWNhZGEgbGEgbWF5b3IgcGFydGUgZGUgc3Ugc2NyYXAgZW4gcHJlLXByb2R1Y2Npw7NuLgoKIyMjIyMgTGFzIHVuaWRhZGVzIHZlbmRpZGFzIGRlIGNhcnJvcyBhdW1lbnRhcm9uIGxvcyDDumx0aW1vcyA1LTEwIGHDsW9zIHkgc2UgcHJvbm9zdGljYSBxdWUgaGF5YSB1biBjcmVjaW1pZW50byBwb3NpdGl2byBkZSBsb3MgdmVow61jdWxvcyBlbiBjaXJjdWxhY2nDs24gY29uIGVsIHBhc28gZGVsIHRpZW1wby4KCiMjIyMjIFNpIGluY3JlbWVudGEgZWwgZW1wbGVvIGVuIE3DqXhpY28sIHNlIHByZWRpY2UgcXVlIGxhcyB2ZW50YXMgZGUgdmVow61jdWxvcyBsaWdlcm9zIGluY3JlbWVudGFyw6FuIHRhbWJpw6luLgoKIyMjIyMgRWwgc2FsYXJpbyBpbmZsdXllIG11Y2hvIGVuIGxhcyBiYWphcywgcHVlcyB0b2RvcyBsb3MgcXVlIHNlIGhhbiBkYWRvIGRlIGJhamEgdGllbmVuIHVuIHNhbGFyaW8gcHJvbWVkaW8gbWVub3IgYSAkMTgwIGRpYXJpb3MuIFNvbGFtZW50ZSB1biBjb2xhYm9yYWRvciBjb24gdW4gc2FsYXJpbyBtYXlvciAoJDUwMCkgc2UgaGEgZGFkbyBkZSBiYWphLgoKIyMjIyMgRk9STSBoYSBkZXNwZWRpZG8gbcOhcyBjb2xhYm9yYWRvcmVzIGRlIGxvcyBxdWUgaGFuIHJlbnVuY2lhZG8sIHNpZW5kbyBsYSBwcmluY2lwYWwgY2F1c2EgbGEg4oCcQmFqYSBwb3IgZmFsdGFz4oCdLiBMbyBxdWUgcHVlZGUgc2lnbmlmaWNhciBxdWUgc3UgcHJvY2VzbyBkZSBjb250cmF0YWNpw7NuIG5vIGVzIGVsIG3DoXMgw7NwdGltbyB5YSBxdWUgdGVybWluYW4gY29udHJhdGFuZG8gcGVyc29uYWwgcXVlIG5vIGVyYSBlbCBhZGVjdWFkbyBwYXJhIGVsIHB1ZXN0by4KCiMjICoqQSBwYXJ0aXIgZGVsIGFuw6FsaXNpcyBkZSBsYXMgYmFzZXMgZGUgZGF0b3MgZGUgbGFzIGRpZmVyZW50ZXMgw6FyZWFzIGRlIGxhIGVtcHJlc2EgRk9STSwgZGVzY3JpYmlyIDMgc3VnZXJlbmNpYXMgcXVlIGxlIHBlcm1pdGFuIGFsIHNvY2lvIGZvcm1hZG9yIG1lam9yYXIgc3UgcHJvY2VzbyBkZSBjYXB0dXJhLCBvcmdhbml6YWNpw7NuLCB5IGFuYWzDrXRpY2EgZGUgZGF0b3MuKioKCiMjIyMjIFNlIHN1Z2llcmUgdW4gZGF0YSBhbmFseXN0cywgc2kgbm8gc2UgdGllbmUgZWwgcHJlc3VwdWVzdG8sIHNlIHBvZHLDrWEgYnVzY2FyIHVuIGN1cnNvIHBhcmEgZW1wbGVhZG9zIHBhcmEgcG9kZXIgbGxlZ2FyIGEgY3JlYXIgYmFzZXMgZGUgZGF0b3MgbGltcGlhcyB5IGVzdGFuZGFyaXphZGFzIHBhcmEgY3VhbmRvIHNlIG5lY2VzaXRlIGFuYWxpemFyIG8gc2ltcGxlbWVudGUgbGEgYsO6c3F1ZWRhIGRlIGxhIGluZm9ybWFjacOzbi4gCgojIyMjIyBQYXJhIGxhIGNhcHR1cmEgZGUgZGF0b3MsIG5vIHNlIGNvbm9jZSBjdWFudGFzIHBlcnNvbmFzIHNvbiBsYXMgcXVlIHJlZ2lzdHJhbiBwZXJvIHNlcsOtYSBtw6FzIHNlbmNpbGxvIHkgbcOhcyBvcmdhbml6YWRvIHNpIHNlIGNyZWFyYSB1biBlcXVpcG8gZW4gbG9zIGN1YWxlcyBzZSBvY3VwZW4gcXVlIGxvcyBkYXRvcyBzZSByZWdpc3RyZW4gZGUgbGEgbWFuZXJhIGNvcnJlY3RhLiAKCiMjIyMjIEVuIGVsIGNhc28gcXVlIG5vIHNlIHB1ZWRhIGNvbnRyYXRhciB1biBkYXRhIGFuYWx5c3QsIGFncmVnYXJsbyBjb21vIG1ldGEgZGUgbWVkaWFubyBwbGF6byAoZGVwZW5kaWVuZG8gZGVsIHByZXN1cHVlc3RvIGRlIEZPUk0pIHBhcmEgYXPDrSBwb2RlciBsbGVnYXIgYSBzZXIgdW5hIHB5bWUgcGVuc2FuZG8gZW4gc3UgZnV0dXJvIHkgZ2VuZXJhciBlc3RyYXRlZ2lhcyBkZSBjcmVjaW1pZW50by4gCgojIyAqKkJ1c2luZXNzIEludGVsbGlnZW5jZSoqCgojIyMjIyMgRWwgKkJ1c2luZXNzIEFuYWx5dGljcyBlcyBlbCBtw6l0b2RvIGRlIGFuw6FsaXNpcyBxdWUgbGFzIGVtcHJlc2FzIHV0aWxpemFuIHBhcmEgcG9kZXIgY3JlYXIgZXN0cmF0ZWdpYXMgZW4gdG9ybm8gYWwgY3JlY2ltaWVudG8gZSBpbm5vdmFjacOzbiB0b21hbmRvIGVuIGN1ZW50YSBzdSBpbmZvcm1hY2nDs24gaW50ZXJuYSB5IGV4dGVybmEqLiBFcyB1bmEgY29tYmluYWNpw7NuIGRlIGxvcyBjYW1wb3MgZGUgbGEgZ2VzdGnDs24sIGxvcyBuZWdvY2lvcyB5IGxhIGNpZW5jaWEgZGUgbG9zIGRhdG9zLgoKIyMjIyBBbGd1bm9zIGRlIGxvcyBwcmluY2lwYWxlcyBvYmpldGl2b3MgZGVsIEJ1c2luZXNzIEFuYWx5dGljcyBzb24gKmRldGVybWluYXIgcXXDqSBjb25qdW50b3MgZGUgZGF0b3Mgc29uIMO6dGlsZXMqIChvcmdhbml6YXJsb3MsIGZpbHRyYXJsb3MgeSBsaW1waWFybG9zKSwgKmV4YW1pbmFybG9zKiAoZXN0YWJsZWNlciByZWxhY2lvbmVzIHkgY2xhc2lmaWNhcmxvcykgeSB2ZXIgY8OzbW8gZXN0b3MgcHVlZGVuICphdW1lbnRhciBsb3MgaW5ncmVzb3MsIGxhIHByb2R1Y3RpdmlkYWQsIGxhIGVmaWNpZW5jaWEgeSBlbCByZW5kaW1pZW50byBvcmdhbml6YWNpb25hbC4qIEFzaW1pc21vLCBlbCBCdXNpbmVzcyBBbmFseXRpY3MgYXl1ZGEgYSBxdWUgbG9zIGNvbGFib3JhZG9yZXMgcHVlZGFuICp0b21hciBkZWNpc2lvbmVzIG3DoXMgaW50ZWxpZ2VudGVzIChCdXNpbmVzcyBJbnRlbGxpZ2VuY2UpIGJhc2FkYXMgZW4gbG9zIGRhdG9zIGFuYWxpemFkb3MgYWwgdXRpbGl6YXIgZGlmZXJlbnRlcyBoZXJyYW1pZW50YXMgY29tbyBlbCBhbsOhbGlzaXMgZXN0YWTDrXN0aWNvIHkgcHJlZGljdGl2by4qCgojIyMjIyBMYSByZWxhY2nDs24gZW50cmUgZWwg4oCcQnVzaW5lc3MgSW50ZWxsaWdlbmNl4oCdIHkgZWwg4oCcQnVzaW5lc3MgQW5hbHl0aWNz4oCdIGVzIHF1ZSB1biBleHBlcnRvIGVuIEJ1c2luZXNzIEludGVsbGlnZW5jZSwgdG9tYSB5IHByb2Nlc2EgbGEgaW5mb3JtYWNpw7NuIGdlbmVyYWRhIHBvciBsb3MgZXhwZXJ0b3MgZW4gQnVzaW5lc3MgQW5hbHl0aWNzIHkgbGEgY29udmllcnRlIGVuIGRlY2lzaW9uZXMgZXN0cmF0w6lnaWNhcyBwYXJhIHN1IG5lZ29jaW8uCgojIyAqKktQSSoqCgojIyMjIyBTZWfDum4gbWlzIGVzdHVkaW9zIGVuIG1lcmNhZG90ZWNuaWEsIEtQSSwgZXMgdMOpY25pY2FtZW50ZSB1biB0aXBvIGRlIGluZGljYWRvciBvIG3DqXRyaWNhIHBhcmEgcG9kZXIgbWVkaXIgZGlmZXJlbnRlcyBlc3RyYXRlZ2lhcyBvIHTDqWNuaWNhcyBpbXBsZW1lbnRhZGFzIGVuIHVuIMOhcmVhIGRlbCBuZWdvY2lvIG8gc2VydmljaW8sIGRlcGVuZGllbmRvIGRlbCBjYXNvLiAKCiMjICoqS1BJJ1MgcGFyYSBGT1JNKiogCgojIyMjIyBDb2xhYm9yYWRvcmVzIGVuIGNyZWNpbWllbnRvLCBlbiBlbCDDoXJlYSBkZSBuZWdvY2lvIGRlIFJlY3Vyc29zIEh1bWFub3MgZGUgRk9STSwgY29udGFuZG8gY29uIHRvZG8gZXN0ZSBhbsOhbGlzaXMgZSBoYWxsYXpnb3MgaW1wbGVtZW50YXIgY29uIHByZWNpc2nDs24gdW5hIGVzdHJhdGVnaWEgcGFyYSByZXRlbmVyIHkgZXZpdGFyIHRhbnRhIHJvdGFjacOzbiBkZSBwZXJzb25hbC4gU2llbmRvIG3DoXMgZXNwZWPDrWZpY29zIGVuIGxvcyBqw7N2ZW5lcywgcXVlIHNvbiBsb3MgcXVlIG3DoXMgc2UgZGFuIGRlIGJhamEuIAoKIyMjIyMgRGVzcGVyZGljaW8gY2VybywgZW4gZWwgw6FyZWEgZGUgbmVnb2Npb3MgZGUgcHJvZHVjY2nDs24sIHNlIGdlbmVyYSBtdWNoYSBzY3JhcCBlbiBsYSBwcmUgcHJvZHVjY2nDs24gZG9uZGUgc2UgcHVlZGUgcmVhbGl6YXIgbGEgZXN0cmF0ZWdpYSBkZSB1dGlsaXphcmxhIG8gZW5jb250cmFyIHVuYSBtYW5lcmFzIGRlIHJlY2ljbGFyIGdlbmVyYW5kbyB1biB2YWxvciBtb25ldGFyaW8gY29tbyBsbGVnYXIgYSBjb25lY3RhciBjb24gdW5hIGVtcHJlc2EgZWNvbMOzZ2ljYS4gCgojIyMjIyAxMDAlIGNhbGlkYWQsIGVuIGVsIMOhcmVhIGRlIG5lZ29jaW9zIGRlIGNvbWVyY2lhbCB5IHNlcnZpY2lvIGEgY2xpZW50ZSwgc2UgY29tZW50w7MgcXVlIEZPUk0gc2UgZXNwZWNpYWxpemEgZW4gcGVyc29uaWZpY2FyIHN1cyBwZWRpZG9zIHBlcm8gZXMgaW1wb3J0YW50ZSBjcmVhciBlc3RvIGNvbiB0b2RvcyBzdXMgY2xpZW50ZXMgcGFyYSBnZW5lcmFyIGxhIHJldGVuY2nDs24gZGUgdG9kb3Mgc3VzIGNsaWVudGVzIHkgZWwgcG9kZXIgY29uc2VndWlyIG3DoXMuIAoKIyMgKipQcm9wdWVzdGFzKioKCiMjIyMjIEZPUk0gZ2VuZXJhIGNpZXJ0YSBjYW50aWRhZCBkZSBtZXJtYSBjcmVhbmRvIHVuIHB1bnRvIGRlIG9wb3J0dW5pZGFkLCBvcG9ydHVuaWRhZGVzIGRlIG5lZ29jaW9zIGVuIGVsIGFyZWEgZGUgcmVjaWNsYWplLCBkb25kZSBzZSBvYnRlbmdhIHVuIGJlbmVmaWNpbyBtb25ldGFyaW8gYSBjYW1iaW8uCgojIyMjIyMgUHVlYmxhIGVzIGVsIGVzdGFkbyBkb25kZSBtw6FzIHNlIHByb2R1Y2UgY2FydMOzbiwgc2UgcHVlZGUgY29udGFjdGFyIGVtcHJlc2FzIGRlIFB1ZWJsYSBwcm9kdWN0b3JhcyBkZSBjYXJ0w7NuLCBhbCBoYWJlciB0YW50YSBvZmVydGEsIGxvIG3DoXMgcHJvYmFibGUgZXMgcXVlIGVsIHByZWNpbyBkZSBsYSBtYXRlcmlhIHByaW1hIGRpc21pbnV5YS4KCiMjIyMjIFNpIHNlIGJ1c2NhIGV4cGFuZGlyIHkgY3JlYXIgYm9kZWdhcyBGT1JNIHRpZW5lIHF1ZSBidXNjYXIgaW52ZXJ0aXIgZW4gYXF1ZWxsYXMgcXVlIHNlIHB1ZWRhbiBzaXR1YXIgZW4gbG9zIGVzdGFkb3MgbyBjZXJjYSBkZSBsb3MgZXN0YWRvcyBzaXR1YWRvcyBlbiBsYSByZWdpw7NuIE5vcnRlIHkgbGEgcmVnacOzbiBjZW50cm8sIHlhIHF1ZSwgZXMgZG9uZGUgbcOhcyBwcm9kdWNjacOzbiBkZSBjYXJ0w7NuIGV4aXN0ZS4KCiMjIyMjICJUcmVzIHByaW5jaXBhbGVzIGxpzIFuZWFzIGRlIG5lZ29jaW8iIERlc2Fycm9sbG8gZGUgaW5nZW5pZXJpzIFhIGRlIGVtcGFxdWUsIHByb2R1Y2Npb8yBbiBkZSBlbXBhcXVlcyBhIGxhIG1lZGlkYSB5IGFkbWluaXN0cmFjaW/MgW4gMzYwIGRlbCBlbXBhcXVlLgoKIyMjIyMgRGViaWRvIGEgbGEgZ3JhbiBjYW50aWRhZCBkZSBtZXJtYSBkZSBjYXJ0b8yBbiBkZXNlY2hhZGEgcG9yIEZPUk0gc2UgYnVzY2EgZWxpbWluYXIgbG9zIGRlc3BlcmRpY2lvcyBkZSB0YWwgbWFuZXJhIHF1ZSBsYSBlbXByZXNhIHB1ZWRhIGRpc21pbnVpciBzdXMgZ2FzdG9zIGFsIGFwcm92ZWNoYXIgYWwgbWHMgXhpbW8gbGEgbWF0ZXJpYSBwcmltYSBhZHF1aXJpZGEsIGFzacyBIGNvbW8gZWwgaW1wYWN0YXIgcG9zaXRpdmFtZW50ZSBlbCBtZWRpbyBhbWJpZW50ZSBhbCBkaXNtaW51aXIgbG9zIGRlc2VjaG9zIGdlbmVyYWRvcy4KCiMgKipFc3RpbWFjacOzbiBkZSBNb2RlbG8gZGUgUmVncmVzacOzbiBMb2fDrXN0aWNhIE3Dumx0aXBsZSoqCgojIyAqKkVzcGVjaWZpY2FyIHkgZXN0aW1hciAyIGVzcGVjaWZpY2FjaW9uZXMgZGlmZXJlbnRlcyBkZSBtb2RlbG9zIGRlIHJlZ3Jlc2nDs24gbG9nw61zdGljYSBtw7p0aXBsZS4qKgoKIyMjIyBJbXBvcnRhciBiYXNlIGRlIGRhdG9zCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZm9yZWlnbikKbGlicmFyeShkcGx5cikgICAgICAgICMgZGF0YSBtYW5pcHVsYXRpb24gCmxpYnJhcnkoZ2dwbG90MikgICAgICAjIGRhdGEgdmlzdWFsaXphdGlvbiAKbGlicmFyeShwc3ljaCkgICAgICAgICMgZnVuY3Rpb25zIGZvciBtdWx0aXZhcmlhdGUgYW5hbHlzaXMgCmxpYnJhcnkoY29ycnBsb3QpICAgICAjIGNvcnJlbGF0aW9uIHBsb3RzCmxpYnJhcnkoanRvb2xzKSAgICAgICAjIHByZXNlbnRhdGlvbiBvZiByZWdyZXNzaW9uIGFuYWx5c2lzIApsaWJyYXJ5KGxtdGVzdCkgICAgICAgIyBkaWFnbm9zdGljIGNoZWNrcyAtIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzIApsaWJyYXJ5KGNhcikgICAgICAgICAgIyBkaWFnbm9zdGljIGNoZWNrcyAtIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzCmxpYnJhcnkoZmFjdG9leHRyYSkgICAjIHByb3ZpZGVzIGZ1bmN0aW9ucyB0byBleHRyYWN0IGFuZCB2aXN1YWxpemUgdGhlIG91dHB1dCBvZiBleHBsb3JhdG9yeSBtdWx0aXZhcmlhdGUgZGF0YSBhbmFseXNlcwpsaWJyYXJ5KGdnZm9ydGlmeSkgICAgIyBkYXRhIHZpc3VhbGl6YXRpb24gdG9vbHMgZm9yIHN0YXRpc3RpY2FsIGFuYWx5c2lzIHJlc3VsdHMKbGlicmFyeSh0aWR5dmVyc2UpICAgICMgZGF0YSBtYW5pcHVsYXRpb24gYW5kIHZpc3VhbGl6YXRpb24KbGlicmFyeShqYW5pdG9yKSAgICAgICMgZXhhbWluaW5nIGFuZCBjbGVhbmluZyBkYXRhc2V0cyAKbGlicmFyeSh2aXJpZGlzKSAgICAgIApsaWJyYXJ5KHNjYWxlcykgICAgICAgCmxpYnJhcnkobHVicmlkYXRlKSAKCiMgZmlsZS5jaG9vc2UoKQpyaF9yZWdyZXNpb24gPC0gcmVhZC5jc3YoIi9Vc2Vycy9tYXlyYWNhbXBveXJhbW9zL0Rlc2t0b3AvQW5hbGlzaXMgZGUgRGF0b3MgQ29uY2VudHJhY2lvbi9SZXRvL3JoX3JlZ3Jlc2lvbi5jc3YiKQpzdW1tYXJ5KHJoX3JlZ3Jlc2lvbikKYGBgCgojIyMgTGltcGllemEgZGUgZGF0b3MKCiMjIyMgVMOpY25pY2EgMS4gQ29udmVydGlyIGxhcyB2YXJpYWJsZXMgY29tbyBmYWN0b3IgbyBudW1lcm8KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcmhfcmVncmVzaW9uJGVkYWQgPC0gYXMubnVtZXJpYyhyaF9yZWdyZXNpb24kZWRhZCkKcmhfcmVncmVzaW9uJGdlbmVybyA8LSBhcy5mYWN0b3IocmhfcmVncmVzaW9uJGdlbmVybykKcmhfcmVncmVzaW9uJGFudGlndWVkYWQgPC0gYXMubnVtZXJpYyhyaF9yZWdyZXNpb24kYW50aWd1ZWRhZCkKcmhfcmVncmVzaW9uJHB1ZXN0bzwtIGFzLmZhY3RvcihyaF9yZWdyZXNpb24kcHVlc3RvKQpyaF9yZWdyZXNpb24kc2FsYXJpb19kaWFyaW8gPC0gYXMubnVtZXJpYyhyaF9yZWdyZXNpb24kc2FsYXJpb19kaWFyaW8pCnJoX3JlZ3Jlc2lvbiRlc3RhZG9fY2l2aWw8LSBhcy5mYWN0b3IocmhfcmVncmVzaW9uJGVzdGFkb19jaXZpbCkKcmhfcmVncmVzaW9uJGJhamFzIDwtIGFzLm51bWVyaWMocmhfcmVncmVzaW9uJGJhamFzKQpyaF9yZWdyZXNpb24kbW90aXZvX2RlX2JhamE8LSBhcy5mYWN0b3IocmhfcmVncmVzaW9uJG1vdGl2b19kZV9iYWphKQpzdW1tYXJ5KHJoX3JlZ3Jlc2lvbikKYGBgCgojIyMjIyBFbiBlc3RhIHTDqWNuaWNhIGRlIGxpbXBpZXphIHNlIHZ1ZWx2ZW4gYSBmYWN0b3IgbyBuw7ptZXJvcyBsYXMgdmFyaWFibGVzIHBhcmEgZ2VuZXJhciB1biBlc3RhbmRhcml6YXIgeSBnZW5lcmFyIHVuIGZvcm1hdG8gcGFyYSBxdWUgc2UgdnVlbHZhIG3DoXMgc2VuY2lsbG8gYWwgcmVhbGl6YXIgZ3LDoWZpY29zIHkgbWFuaXB1bGFyIGRhdG9zLgoKIyMjIyBUw6ljbmljYSAyLiBDcmVhciB1bmEgY2F0ZWdvcsOtYSBkZSByZWZlcmVuY2lhIHBhcmEgbGEgdmFyaWFibGUgImJhamFzIjoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcmhfcmVncmVzaW9uJGJhamFzPC1hcy5mYWN0b3IocmhfcmVncmVzaW9uJGJhamFzKQpyaF9yZWdyZXNpb24kYmFqYXM8LWZjdF9yZWNvZGUocmhfcmVncmVzaW9uJGJhamFzLCAiQkFKQSI9IjEiLCJOTyBCQUpBIj0iMCIpCmBgYAoKIyMjIyByZXBsYWNlIHRoZSAib3V0bGllciIgb2Ygc2FsYXJpb19kaWFyaW8gd2l0aCB0aGUgbWVkaWFuCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJoX3JlZ3Jlc2lvbiRzYWxhcmlvX2RpYXJpbzwtcmVwbGFjZShyaF9yZWdyZXNpb24kc2FsYXJpb19kaWFyaW8scmhfcmVncmVzaW9uJHNhbGFyaW9fZGlhcmlvPjEwMDAwMDAsMTgxKQpyaF9yZWdyZXNpb24kc2FsYXJpb19kaWFyaW9baXMubmEocmhfcmVncmVzaW9uJHNhbGFyaW9fZGlhcmlvKV08LW1lZGlhbihyaF9yZWdyZXNpb24kc2FsYXJpb19kaWFyaW8sbmEucm09VFJVRSkKYGBgCgojIyMjIGxldHMgZGlzcGxheSBkYXRhIHZpc3VhbGl6YXRpb24gcGxvdHMgc28gd2UgY2FuIGlkZW50aWZ5IHJlbGV2YW50IGluc2lnaHRzIGZyb20gb3VyIHJoX2FsdCBkYXRhc2V0CmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnRhcHBseShyaF9yZWdyZXNpb24kc2FsYXJpb19kaWFyaW8sCiAgICAgICBsaXN0KHJoX3JlZ3Jlc2lvbiRnZW5lcm8scmhfcmVncmVzaW9uJGVzdGFkb19jaXZpbCksIG1lYW4pCmBgYAoKIyMjIyBJdCBpcyB3b3J0aCBtZW50aW9uaW5nIHRoYXQgay1tZWFucyBjbHVzdGVyaW5nIGFuYWx5c2lzIGNhbiBvbmx5IGluY2x1ZGUgcXVhbnRpdGF0aXZlIHZhcmlhYmxlcyAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcmhfZWRhZF9yZWdyZXNpb248LXJoX3JlZ3Jlc2lvbiAKcmhfZWRhZF9yZWdyZXNpb248LSBzdWJzZXQocmhfZWRhZF9yZWdyZXNpb24sIHNlbGVjdCA9IC1jKGdlbmVybywgZXN0YWRvX2NpdmlsLCBhbnRpZ3VlZGFkLCBwdWVzdG8sIG1vdGl2b19kZV9iYWphLCBiYWphcykpCmBgYAoKCiMjIyMgVGhlIG5vcm1hbGl6aW5nIG9mIGEgZGF0YXNldCAocXVhbnRpdGF0aXZlIHZhcmlhYmxlcykgdXNpbmcgdGhlIG1lYW4gdmFsdWUgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBpcyBwZXJmb3JtZWQgYnkgc2NhbGUoKQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpyaF9lZGFkX3JlZ3Jlc2lvbl9ub3JtPC1zY2FsZShyaF9lZGFkX3JlZ3Jlc2lvblsxOjJdKSAKYGBgCgojIyMjIGZ2aXpfbmJjbHVzdCgpIGhlbHBzIHRvIGRldGVybWluZSBhbmQgdmlzdWFsaXplIHRoZSBvcHRpbWFsIG51bWJlciBvZiBjbHVzdGVycwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpmdml6X25iY2x1c3QocmhfZWRhZF9yZWdyZXNpb25fbm9ybSwga21lYW5zLCBtZXRob2Q9IndzcyIpKyAjIHdzcyBtZXRob2QgY29uc2lkZXJzIHRvdGFsIHdpdGhpbiBzdW0gb2Ygc3F1YXJlCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTUsIGxpbmV0eXBlPTIpKyAgICAgICAgICAgIyBvcHRpbWFsIG51bWJlciBvZiBjbHVzdGVycyBpcyBjb21wdXRlZCB3aXRoIHRoZSBkZWZhdWx0IG1ldGhvZCA9ICJldWNsaWRlYW4iCiAgbGFicyhzdWJ0aXRsZSA9ICJFbGJvdyBtZXRob2QiKSAgCmBgYAoKCiMjIyMgdmlzdWFsaXplIHRoZSBjbHVzdGVycycgaW5mb3JtYXRpb24uIEJyaWVmbHksIHlvdSBjYW4gZGV0ZWN0IGhvdyBlYWNoIGRhdGFzZXQncyBvYnNlcnZhdGlvbiBjb3JyZXNwb25kcyB0byBhIHNwZWNpZmljIGNsdXN0ZXIuIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQplZGFkX2NsdXN0ZXIxPC1rbWVhbnMocmhfZWRhZF9yZWdyZXNpb25fbm9ybSw1KQpgYGAKIyMjIyB0aGUgc2VsZWN0aW9uIG9mIDUgY2x1c3RlcnMgYXBwcm94aW1hdGVseSBleHBsYWlucyA4NSUgb2YgZGF0YXNldCdzIHZhcmlhYmlsaXR5LiAKCiMjIyMgdmlzdWFsaXplIGNsdXN0ZXJpbmcgcmVzdWx0cyAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZnZpel9jbHVzdGVyKGVkYWRfY2x1c3RlcjEsZGF0YT1yaF9lZGFkX3JlZ3Jlc2lvbl9ub3JtKQpgYGAKCiMjIyMgbGV0cyBhZGQgdGhlIGVzdGltYXRlZCBjbHVzdGVycycgaW5mb3JtYXRpb24gdG8gdGhlIG9yaWdpbmFsIGRhdGFzZXQgc28gd2UgY2FuIGludGVycHJldCB0aGUgcmVzdWx0cyAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcmhfcmVncmVzaW9uMSA8LSByaF9yZWdyZXNpb24KcmhfcmVncmVzaW9uMSRDbHVzdGVyczwtZWRhZF9jbHVzdGVyMSRjbHVzdGVyCmBgYAoKIyMjIyBsZXRzIGNyZWF0ZSBhIGRhdGFzZXQgc28gd2UgY2FuIGlkZW50aWZ5IHNvbWUgY2hhcmFjdGVyaXN0aWNzIG9mICJlZGFkIiBieSBjbHVzdGVyIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpyaF9yZWdyZXNpb24yPC1yaF9yZWdyZXNpb24xICU+JSBncm91cF9ieShDbHVzdGVycykgJT4lIHN1bW1hcmlzZShlZGFkPW1heChlZGFkKSkgJT4lIGFycmFuZ2UoZGVzYyhlZGFkKSkKYGBgCgojIyMjIGdyb3VwIHRoZSBjbHVzdGVycyBieSBuYW1lCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJoX3JlZ3Jlc2lvbjEkQ2x1c3Rlcl9OYW1lczwtZmFjdG9yKHJoX3JlZ3Jlc2lvbjEkQ2x1c3RlcnMsbGV2ZWxzID0gYygxLDIsMyw0LDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkrDs3ZlbiIsIkFkdWx0YSBJSSIsIkp1YmlsYWNpw7NuIiwiQXZhbnphZGEiLCJBZHVsdGEgSSIpKQpgYGAKCiMjIyMgZ3JvdXAgdGhlIGNsdXN0ZXJzIGJ5IGNsdXN0ZXIgbmFtZXMgYW5kIFN1bW1hcml6ZSB0aGUgQ29sdW1ucwpgYGB7cn0KcmhfcmVncmVzaW9uMzwtcmhfcmVncmVzaW9uMSAlPiUgZ3JvdXBfYnkoQ2x1c3Rlcl9OYW1lcykgJT4lIGRwbHlyOjpzdW1tYXJpemUoZWRhZF9hw7Fvcz1tYXgoZWRhZCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FsYXJpb19pbXNzPW1lYW4oc2FsYXJpb19kaWFyaW8pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ291bnQ9bigpKQpgYGAKCiMjIyMgdXNlIHRhYmxlIGZvcm1hdCB0byBkaXNwbGF5IHRoZSBjbHVzdGVycyBpbmZvcm1hdGlvbgpgYGB7cn0KY2x1c3RlcnM8LWFzLmRhdGEuZnJhbWUocmhfcmVncmVzaW9uMykKY2x1c3RlcnMKYGBgCgojIyBFc3RpbWF0aW5nIExvZ2lzdGljIFJlZ3Jlc3Npb24KCiMjIyMjIE5vIG1lIGRlamEgZGVzY2FyZ2FyIGVsIHBhcXVldGUgZGUgImNhcmV0IiBwb3IgZXNvIG5vcyBmdWltb3MgZGlyZWN0byBhIGxhIHJlZ3Jlc2lvbgoKCiMjIyBzaW1wbGUgbG9naXN0aWMgcmVncmVzc2lvbgojIyMjICBtb2RlbCBzcGVjaWZpY2F0aW9uCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxvZ2l0X21vZGVsMTwtZ2xtKGJhamFzfnNhbGFyaW9fZGlhcmlvLCBkYXRhPXJoX3JlZ3Jlc2lvbjEsIGZhbWlseT1iaW5vbWlhbChsaW5rPSdsb2dpdCcpKQpzdW1tYXJ5KGxvZ2l0X21vZGVsMSkKYGBgCgojIyMjIG1ha2UgcHJlZGljdGlvbnMgYmFzZWQgaW4gdGhlIHJlZ3Jlc3Npb24gcmVzdWx0cwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIFdoaWNoIGdyb3VwcyAvIGNhdGVnb3JpZXMgZG8gdGhlc2UgcHJvYmFiaWxpdGllcyByZWZlciB0bz8KY29udHJhc3RzKHJoX3JlZ3Jlc2lvbjEkYmFqYXMpIApwcm9iYWJpbGl0aWVzPC1sb2dpdF9tb2RlbDEgJT4lIHByZWRpY3QocmhfcmVncmVzaW9uMSx0eXBlPSJyZXNwb25zZSIpCnByZWRpY3RlZC5jbGFzc2VzPC1pZmVsc2UocHJvYmFiaWxpdGllcyA+IDAuNSwgImJhamFzIiwgIm5vX2JhamFzIikKIyBkaXNwbGF5IHRoZSBwcm9iYWJpbGl0aWVzIG9mIGRhdGFzZXQgb2JzZXJ2YXRpb25zIHJlbGF0ZWQgdG8gImJhamFzIiAmICJubyBiYWphcyIKaGVhZChwcm9iYWJpbGl0aWVzKSAKIyBkaXNwbGF5IHRoZSBwcm9iYWJpbGl0aWVzIGFzc29jaWF0ZWQgd2l0aCAiYmFqYXMiCmhlYWQocHJlZGljdGVkLmNsYXNzZXMpIApgYGAKCiMjIyMgbGV0cyBhc3Nlc3MgdGhlIGFjY3VyYWN5IG9mIHRoZSBlc3RpbWF0ZWQgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbDEKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcmhfcmVncmVzaW9uMSRsb2dpdF9tb2RlbDFfcHJvYiA8LSBwcmVkaWN0KGxvZ2l0X21vZGVsMSwgcmhfcmVncmVzaW9uMSwgdHlwZT0icmVzcG9uc2UiKQoKcmhfcmVncmVzaW9uMSA8LSByaF9yZWdyZXNpb24xICAlPiUgbXV0YXRlKGxvZ2l0X21vZGVsMV9wcmVkID0gMSoobG9naXRfbW9kZWwxX3Byb2IgPiAuNTApICsgMCwKICAgICAgICAgICAgICAgICAgICAgICAgIGJhamFzX2JpbmFyeV8xID0gMSooYmFqYXMgPT0gIkJBSkEiKSArIDApCgpyaF9yZWdyZXNpb24xIDwtIHJoX3JlZ3Jlc2lvbjEgJT4lIG11dGF0ZShhY2N1cmF0ZV8xPTEqKGxvZ2l0X21vZGVsMV9wcmVkID09IGJhamFzX2JpbmFyeV8xKSkKc3VtKHJoX3JlZ3Jlc2lvbjEkYWNjdXJhdGVfMSkvbnJvdyhyaF9yZWdyZXNpb24xKSAKIyB0aGUgY2FsY3VsYXRlZCBSMiBpbmRpY2F0ZXMgdGhhdCBhcHByb3hpbWF0ZWx5IDczJSBvZiB2YXJpYXRpb24gaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBpcyBleHBsYWluZWQgYnkgdGhlIGxvZ2l0IG1vZGVsIHNwZWNpZmljYXRpb24uIApgYGAKCiMjIyMgbG9naXN0aWMgcmVncmVzc2lvbiBwbG90IGRpc3BsYXlpbmcgYSBTIHNoYXBlZCBjdXJ2ZQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QocmhfcmVncmVzaW9uMSxhZXMoeD1zYWxhcmlvX2RpYXJpbywgeT1hcy5udW1lcmljKGJhamFzKS0xKSkgKyAKICBnZW9tX3BvaW50KGFscGhhPS41KSArCiAgc3RhdF9zbW9vdGgobWV0aG9kPSJnbG0iLCBzZT1GQUxTRSwgZnVsbHJhbmdlPVRSVUUsIG1ldGhvZC5hcmdzPWxpc3QoZmFtaWx5PWJpbm9taWFsKSkgKyAKICB5bGFiKCJQcm9iYWJpbGl0eSIpICsgeGxpbSgxMDAsNTAwKSsKICBsYWJzKAogICAgdGl0bGUgPSAiTG9naXN0aWMgUmVncmVzc2lvbiBNb2RlbCIsIAogICAgeCA9ICJTYWxhcmlvIERpYXJpbyIsCiAgICB5ID0gIlByb2JhYmlsaXR5IG9mIEJhamFzIgogICkKYGBgCgojIyMjIyBFbiBlc3RlIGNhc28gc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIGxhIHByb2JhYmlsaWRhZCBkZSBiYWphcyB2YSBkaXNtaW51eWVuZG8gbWllbnRyYXMgYXVtZW50YSBlbCBzYWxhcmlvLiBJbmRpY2EgcXVlIGVudHJlIGF1bWVudGUgZWwgc2FsYXJpbyBkZSBsb3MgY29sYWJvcmFkb3JlcywgbWVub3IgcHJvYmFiaWxpZGFkIHF1ZSBzZSBkZW4gZGUgYmFqYS4gCgojIyMjIG11bHRpcGxlIGxvZ2lzdGljIHJlZ3Jlc3Npb24KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbG9naXRfbW9kZWwyPC1nbG0oYmFqYXN+c2FsYXJpb19kaWFyaW8rZWRhZCwgZGF0YT1yaF9yZWdyZXNpb24xLCBmYW1pbHk9Ymlub21pYWwobGluaz0nbG9naXQnKSkKc3VtbWFyeShsb2dpdF9tb2RlbDIpCmBgYAoKIyMjIyBsZXRzIGFzc2VzcyB0aGUgYWNjdXJhY3kgb2YgdGhlIGVzdGltYXRlZCBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsMgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpyaF9yZWdyZXNpb24xJGxvZ2l0X21vZGVsMl9wcm9iIDwtIHByZWRpY3QobG9naXRfbW9kZWwyLCByaF9yZWdyZXNpb24xLCB0eXBlPSJyZXNwb25zZSIpCgpyaF9yZWdyZXNpb24xIDwtIHJoX3JlZ3Jlc2lvbjEgICU+JSBtdXRhdGUobG9naXRfbW9kZWwyX3ByZWQgPSAxKihsb2dpdF9tb2RlbDJfcHJvYiA+IC41MCkgKyAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhamFzX2JpbmFyeV8yID0gMSooYmFqYXMgPT0gIkJBSkEiKSArIDApCgpyaF9yZWdyZXNpb24xIDwtIHJoX3JlZ3Jlc2lvbjEgJT4lIG11dGF0ZShhY2N1cmF0ZV8yPTEqKGxvZ2l0X21vZGVsMl9wcmVkID09IGJhamFzX2JpbmFyeV8yKSkKc3VtKHJoX3JlZ3Jlc2lvbjEkYWNjdXJhdGVfMikvbnJvdyhyaF9yZWdyZXNpb24xKSAKIyB0aGUgY2FsY3VsYXRlZCBSMiBpbmRpY2F0ZXMgdGhhdCBhcHByb3hpbWF0ZWx5IDczJSBvZiB2YXJpYXRpb24gaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBpcyBleHBsYWluZWQgYnkgdGhlIGxvZ2l0IG1vZGVsIHNwZWNpZmljYXRpb24uICAKYGBgCgojIyMjIGxvZ2lzdGljIHJlZ3Jlc3Npb24gcGxvdCBkaXNwbGF5aW5nIGEgUyBzaGFwZWQgY3VydmUKYGBge3J9CmdncGxvdChyaF9yZWdyZXNpb24xLGFlcyh4PWVkYWQsIHk9YXMubnVtZXJpYyhiYWphcyktMSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYT0uNSkgKwogIHN0YXRfc21vb3RoKG1ldGhvZD0iZ2xtIiwgc2U9RkFMU0UsIGZ1bGxyYW5nZT1UUlVFLCBtZXRob2QuYXJncyA9IGxpc3QoZmFtaWx5PWJpbm9taWFsKSkgKyAKICB5bGFiKCJQcm9iYWJpbGl0eSIpICsgeGxpbSgxOCw3NSkrCiAgbGFicygKICAgIHRpdGxlID0gIkxvZ2lzdGljIFJlZ3Jlc3Npb24gTW9kZWwiLCAKICAgIHggPSAiRWRhZCIsCiAgICB5ID0gIlByb2JhYmlsaXR5IG9mIEJhamFzIgogICkKYGBgCgojIyMjIyBFbiBlc3RlIGNhc28gc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIGxhIHByb2JhYmlsaWRhZCBkZSBiYWphcyB2YSBkaXNtaW51eWVuZG8gbWllbnRyYXMgc2VhIG1heW9yIGRlIGVkYWQuIFNlIHB1ZWRlIGRlZHVjaXIgcXVlIGxhcyBwZXJzb25hcyBxdWUgbWFzIHNlIGRhbiBkZSBiYWphIHNvbiBsb3Mgam92ZW5lcy4gCgojIyMgbGV0cyBjb25zaWRlciBvdXIgZXN0aW1hdGVkIHJlc3VsdHMgZnJvbSBLLU1lYW5zIGNsdXN0ZXJpbmcgYW5hbHlzaXMKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbG9naXRfbW9kZWwzPC1nbG0oYmFqYXN+c2FsYXJpb19kaWFyaW8rQ2x1c3Rlcl9OYW1lcywgZGF0YT1yaF9yZWdyZXNpb24xLCBmYW1pbHk9Ymlub21pYWwobGluaz0nbG9naXQnKSkKc3VtbWFyeShsb2dpdF9tb2RlbDMpCmBgYAoKYGBge3J9CnJoX3JlZ3Jlc2lvbjEkbG9naXRfbW9kZWwzX3Byb2IgPC0gcHJlZGljdChsb2dpdF9tb2RlbDMsIHJoX3JlZ3Jlc2lvbjEsIHR5cGU9InJlc3BvbnNlIikKCnJoX3JlZ3Jlc2lvbjE8LSByaF9yZWdyZXNpb24xICAlPiUgbXV0YXRlKGxvZ2l0X21vZGVsM19wcmVkID0gMSoobG9naXRfbW9kZWwzX3Byb2IgPiAuNTApICsgMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWphc19iaW5hcnlfMyA9IDEqKGJhamFzID09ICJCQUpBIikgKyAwKQoKcmhfcmVncmVzaW9uMSA8LSByaF9yZWdyZXNpb24xICU+JSBtdXRhdGUoYWNjdXJhdGVfMz0xKihsb2dpdF9tb2RlbDNfcHJlZCA9PSBiYWphc19iaW5hcnlfMykpCnN1bShyaF9yZWdyZXNpb24xJGFjY3VyYXRlXzMpL25yb3cocmhfcmVncmVzaW9uMSkgCgpgYGAKCiMjICpSZWNvbWVuZGFjaW9uZXMqCgojIyMjIyBFc3RvIGVzIHVuIHByb2JsZW1hIHlhIG1lbmNpb25hZG8gYW50ZXJpb3JtZW50ZSBzb2JyZSBsYXMgYmFqYXMgZGUgbG9zIGVtcGxlYWRvcyBkZSBGT1JNLCBkb25kZSBzZSByZWNvbWllbmRhIGltcGxlbWVudGFyIHVuYSBlc3RyYXRlZ2lhIHBhcmEgbG9zIGNvbGFib3JhZG9yZXMgasOzdmVuZXMsIGhhYmxhbmRvIGNvbiBsb3MgZGUgcmVjdXJzb3MgaHVtYW5vcyBwYXJhIHBvZGVyIGlkZW50aWZpY2FyIHF1w6kgZXMgbG8gcXVlIHB1ZWRlIHJldGVuZXIgYSBsb3MgasOzdmVuZXMuIAoKIyMjIyMgSGFibGFuZG8gZGUgc2FsYXJpbywgZW50cmUgbcOhcyBjcmV6Y2EgZWwgc2FsYXJpbyBlcyBtZW5vciBsYSBwcm9iYWJpbGlkYWQgZGUgYmFqYXMsIGxvIHF1ZSBzZSByZWNvbWllbmRhIGFxdcOtIG5vIGVzIHN1YmlyIGRlIHNhbGFyaW9zIHBhcmEgZXZpdGFyIGJhamFzIHNpIG5vLCBjcmVhciB1biB0aXBvIGRlIGVzcGVjaWUgZGUgcmlmYSBlbnRyZSBlbXBsZWFkb3MsYWxnbyBxdWUgdGVuZ2EgY29tbyB1biBwcmVtaW8gYWxnbyBxdWUgbG9zIG1vdGl2ZSB5IHNlcsOhIGNvbW8gdW4gZXh0cmEuCgoKIyAqKlJlZmVyZW5jaWFzKioKCiMjIyMjIChMRURVKSwgRS4gRS4gKDIwMTgsIFNlcHRlbWJlciAxMikuIFVuZGVyc3RhbmRpbmcgSy1tZWFucyBjbHVzdGVyaW5nIGluIG1hY2hpbmUgbGVhcm5pbmcuIE1lZGl1bS4gUmV0cmlldmVkIE9jdG9iZXIgOCwgMjAyMiwgZnJvbSBodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdW5kZXJzdGFuZGluZy1rLW1lYW5zLWNsdXN0ZXJpbmctaW4tbWFjaGluZS1sZWFybmluZy02YTZlNjczMzZhYTEKCiMjIyMjIEstbWVhbnMgY2x1c3RlcmluZyBpbiBSIHByb2dyYW1taW5nLiBHZWVrc2ZvckdlZWtzLiAoMjAyMCwgSnVseSAyKS4gUmV0cmlldmVkIE9jdG9iZXIgOSwgMjAyMiwgZnJvbSBodHRwczovL3d3dy5nZWVrc2ZvcmdlZWtzLm9yZy9rLW1lYW5zLWNsdXN0ZXJpbmctaW4tci1wcm9ncmFtbWluZy8KCiMjIyMjIFN1cGVydmlzZWQgYW5kIHVuc3VwZXJ2aXNlZCBsZWFybmluZyBpbiBSIHByb2dyYW1taW5nLiBHZWVrc2ZvckdlZWtzLiAoMjAyMSwgTm92ZW1iZXIgMjkpLiBSZXRyaWV2ZWQgT2N0b2JlciA5LCAyMDIyLCBmcm9tIGh0dHBzOi8vd3d3LmdlZWtzZm9yZ2Vla3Mub3JnL3N1cGVydmlzZWQtYW5kLXVuc3VwZXJ2aXNlZC1jbHVzdGVyaW5nLWluLXItcHJvZ3JhbW1pbmcvCgojIyMjIyBTaGFkYW4sIE0uIChuLmQuKS4gVW5zdXBlcnZpc2VkIGxlYXJuaW5nIGluIFIuIFIuIFJldHJpZXZlZCBPY3RvYmVyIDksIDIwMjIsIGZyb20gaHR0cHM6Ly9yc3R1ZGlvLXB1YnMtc3RhdGljLnMzLmFtYXpvbmF3cy5jb20vMjczMTI5XzQ1MzYxMGNhNjk0NTQxZTFhMmM1NjY0YmY3Y2NiYTFhLmh0bWwKCiMjIyMjIEhvdyB0byBjb21wdXRlIHRoZSBldWNsaWRlYW4gZGlzdGFuY2UgYmV0d2VlbiB0d28gYXJyYXlzIGluIFIgLS4gUHJvamVjdFByby4gKG4uZC4pLiBSZXRyaWV2ZWQgT2N0b2JlciA5LCAyMDIyLCBmcm9tIGh0dHBzOi8vd3d3LnByb2plY3Rwcm8uaW8vcmVjaXBlcy9jb21wdXRlLWV1Y2xpZGVhbi1kaXN0YW5jZS1iZXR3ZWVuLXR3by1hcnJheXMtcg==