Librerias requeridas

library(foreign)
library(dplyr)        # data manipulation 
library(forcats)      # to work with categorical variables
library(ggplot2)      # data visualization 
library(janitor)      # data exploration and cleaning 
library(Hmisc)        # several useful functions for data analysis 
library(naniar) 
library(dlookr) 
library(pollster)
library(descr)
library(data.table)
library(epiDisplay)
library(tidyr)
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(olsrr)        # diagnostic checks - linear regression analysis 
library(kableExtra)   # HTML table attributes
library(tseries)   # time series analysis and computational finance 
library(forecast)  # provides methods and tools for displaying and analyzing univariate time series forecast
library(astsa)     # applied statistical time series analysis
library(plyr) 
library(factoextra)   # provides functions to extract and visualize the output of exploratory multivariate data analyses
#install.packages("ggfortify")
library(ggfortify)    # data visualization tools for statistical analysis results

SECCION 1. Limpieza, Transformación, y Organización de Bases de Datos

RECURSOS HUMANOS

Escoger la base datos

# file.choose()
colab <- read.csv("C:\\Users\\sofia\\Downloads\\colab_final (1).csv")
bajas <- read.csv("C:\\Users\\sofia\\Downloads\\bajas_final (2).csv")

Entendemos la base de datos

resumen1 <- summary(colab)
resumen1
##       edad          genero               alta         puesto         
##  Min.   :19.00   Length:104         Min.   :2010   Length:104        
##  1st Qu.:25.75   Class :character   1st Qu.:2021   Class :character  
##  Median :33.00   Mode  :character   Median :2022   Mode  :character  
##  Mean   :35.48                      Mean   :2021                     
##  3rd Qu.:44.25                      3rd Qu.:2022                     
##  Max.   :67.00                      Max.   :2022                     
##  salario_diario  lugar.nacim.           mpio              estado         
##  Min.   :144.4   Length:104         Length:104         Length:104        
##  1st Qu.:176.7   Class :character   Class :character   Class :character  
##  Median :180.7   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :179.3                                                           
##  3rd Qu.:180.7                                                           
##  Max.   :337.1                                                           
##     civil          
##  Length:104        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 
resumen2 <- summary(bajas)
resumen2
##     nombre               edad          genero              alta          
##  Length:233         Min.   :18.00   Length:233         Length:233        
##  Class :character   1st Qu.:23.00   Class :character   Class :character  
##  Mode  :character   Median :29.00   Mode  :character   Mode  :character  
##                     Mean   :30.77                                        
##                     3rd Qu.:37.00                                        
##                     Max.   :61.00                                        
##  motivo_baja           duracion          puesto          salario_diario 
##  Length:233         Min.   :   0.00   Length:233         Min.   :144.4  
##  Class :character   1st Qu.:   9.00   Class :character   1st Qu.:180.7  
##  Mode  :character   Median :  20.50   Mode  :character   Median :180.7  
##                     Mean   :  75.59                      Mean   :177.9  
##                     3rd Qu.:  47.00                      3rd Qu.:180.7  
##                     Max.   :1966.00                      Max.   :500.0  
##     estado            e.civil.        
##  Length:233         Length:233        
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
## 

COLABORADORES

1.¿Cuántas variables y cuántos registros tiene la base de datos?

R= 104 registros y 9 variables
# install.packages("psych")
str(colab)
## 'data.frame':    104 obs. of  9 variables:
##  $ edad          : int  32 38 38 37 38 60 56 46 59 43 ...
##  $ genero        : chr  "FEMENINO" "MASCULINO" "FEMENINO" "MASCULINO" ...
##  $ alta          : int  2013 2018 2015 2016 2020 2020 2022 2022 2022 2022 ...
##  $ puesto        : chr  "SUPERVISORA" "MANTENIMIENTO" "COSTURERA" "AYUDANTE GENERAL" ...
##  $ salario_diario: num  337 280 260 241 241 ...
##  $ lugar.nacim.  : chr  "" "" "" "" ...
##  $ mpio          : chr  "APODACA" "APODACA" "APODACA" "APODACA" ...
##  $ estado        : chr  "Nuevo Leon" "Nuevo Leon" "Nuevo Leon" "Nuevo Leon" ...
##  $ civil         : chr  "Casado" "Soltero" "Casado" "Casado" ...
library(psych)
describe(colab)
##                vars   n    mean    sd  median trimmed   mad     min     max
## edad              1 104   35.48 12.20   33.00   34.68 13.34   19.00   67.00
## genero*           2 104    1.43  0.50    1.00    1.42  0.00    1.00    2.00
## alta              3 104 2020.69  2.34 2022.00 2021.25  0.00 2010.00 2022.00
## puesto*           4 104    7.01  6.75    3.00    5.69  0.00    1.00   25.00
## salario_diario    5 104  179.35 25.17  180.68  176.88  0.00  144.45  337.05
## lugar.nacim.*     6 104   15.38 13.49   14.50   14.46 20.02    1.00   42.00
## mpio*             7 104    2.58  2.41    1.00    2.13  0.00    1.00    9.00
## estado*           8 104    1.91  0.28    2.00    2.00  0.00    1.00    2.00
## civil*            9 104    2.41  1.18    3.00    2.39  1.48    1.00    4.00
##                range  skew kurtosis   se
## edad            48.0  0.51    -0.80 1.20
## genero*          1.0  0.27    -1.95 0.05
## alta            12.0 -2.49     6.57 0.23
## puesto*         24.0  1.46     0.55 0.66
## salario_diario 192.6  3.31    16.26 2.47
## lugar.nacim.*   41.0  0.30    -1.38 1.32
## mpio*            8.0  1.21     0.05 0.24
## estado*          1.0 -2.90     6.47 0.03
## civil*           3.0 -0.13    -1.57 0.12

2.¿Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua.?

Variable<-c("edad","genero","alta","puesto","salario_diario","lugar.nacim.","mpio","estado","civil")
Type<-c("cuantitativa continua","cualitativa","cuantitativa continua","cualitativa","cuantitativa continua","cualitativa","cualitativa","cualitativa","cualitativa")
table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
edad cuantitativa continua
genero cualitativa
alta cuantitativa continua
puesto cualitativa
salario_diario cuantitativa continua
lugar.nacim. cualitativa
mpio cualitativa
estado cualitativa
civil cualitativa

3. Elige la escala de medición de cada variable.

Variable<-c("edad","genero","alta","puesto","salario_diario","lugar.nacim.","mpio","estado","civil")
Type<-c("cuantitativa continua","cualitativa","cuantitativa continua","cualitativa","cuantitativa continua","cualitativa","cualitativa","cualitativa","cualitativa")
Escala_de_Medición <- c("Razon","Nominal","Razon","Nominal","Razon","Nominal","Nominal","Nominal","Nominal")
table<-data.frame(Variable,Type,Escala_de_Medición)
knitr::kable(table)
Variable Type Escala_de_Medición
edad cuantitativa continua Razon
genero cualitativa Nominal
alta cuantitativa continua Razon
puesto cualitativa Nominal
salario_diario cuantitativa continua Razon
lugar.nacim. cualitativa Nominal
mpio cualitativa Nominal
estado cualitativa Nominal
civil cualitativa Nominal

BAJAS

1.¿Cuántas variables y cuántos registros tiene la base de datos?

R= 233 registros y 10 variables
# install.packages("psych")
str(bajas)
## 'data.frame':    233 obs. of  10 variables:
##  $ nombre        : chr  "MARIO VALDEZ ORTIZ" "ISABEL BARRIOS MENDEZ" "MARIA ELIZABETH GOMEZ HERNANDEZ" "ALONDRA ABIGAIL ESCARCIA GOMEZ" ...
##  $ edad          : int  32 36 23 21 29 46 29 31 50 19 ...
##  $ genero        : chr  "MASCULINO" "FEMENINO" "FEMENINO" "FEMENINO" ...
##  $ alta          : chr  "09/03/20" "09/11/21" "10/11/21" "10/11/21" ...
##  $ motivo_baja   : chr  "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" ...
##  $ duracion      : num  628 60 59 59 51 37 37 31 18 224 ...
##  $ puesto        : chr  "DISENO" "AYUDANTE GENERAL" "AYUDANTE GENERAL" "AYUDANTE GENERAL" ...
##  $ salario_diario: num  500 152 152 152 152 ...
##  $ estado        : chr  "Nuevo Leon" "Nuevo Leon" "Nuevo Leon" "Nuevo Leon" ...
##  $ e.civil.      : chr  "Soltero" "Union libre" "Matrimonio" "Soltero" ...
library(psych)
describe(bajas)
##                vars   n   mean     sd median trimmed   mad    min  max   range
## nombre*           1 233 115.04  66.32 114.00  114.93 84.51   1.00  230  229.00
## edad              2 233  30.77   9.69  29.00   29.76 10.38  18.00   61   43.00
## genero*           3 233   1.41   0.49   1.00    1.39  0.00   1.00    2    1.00
## alta*             4 233  72.08  36.06  75.00   72.28 41.51   1.00  140  139.00
## motivo_baja*      5 233   2.82   1.04   2.00    2.74  0.00   1.00    5    4.00
## duracion          6 233  75.59 215.50  20.50   30.36 20.02   0.00 1966 1966.00
## puesto*           7 233   9.18   5.62   7.00    7.76  0.00   1.00   27   26.00
## salario_diario    8 233 177.93  23.41 180.68  179.12  0.00 144.45  500  355.55
## estado*           9 233   1.97   0.18   2.00    2.00  0.00   1.00    2    1.00
## e.civil.*        10 233   3.94   0.78   4.00    3.96  1.48   1.00    5    4.00
##                 skew kurtosis    se
## nombre*         0.01    -1.21  4.34
## edad            0.79    -0.26  0.64
## genero*         0.36    -1.88  0.03
## alta*          -0.07    -0.98  2.36
## motivo_baja*    0.51    -1.49  0.07
## duracion        5.93    39.66 14.12
## puesto*         2.16     3.56  0.37
## salario_diario 10.99   151.07  1.53
## estado*        -5.08    23.93  0.01
## e.civil.*      -0.28    -0.25  0.05

2.¿Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua.?

Variable<-c("nombre","edad","genero","alta","motivo_baja","duracion","puesto","salario_diario","estado","e.civil.")
Type<-c("cualitativa","cuantitativa continua","cualitativa","cuantitativa continua","cualitativa","cuantitativa continua","cualitativa","cuantitativa continua","cualitativa","cualitativa")
table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
nombre cualitativa
edad cuantitativa continua
genero cualitativa
alta cuantitativa continua
motivo_baja cualitativa
duracion cuantitativa continua
puesto cualitativa
salario_diario cuantitativa continua
estado cualitativa
e.civil. cualitativa

3. Elige la escala de medición de cada variable.

Variable<-c("nombre","edad","genero","alta","motivo_baja","duracion","puesto","salario_diario","estado","e.civil.")
Type<-c("cualitativa","cuantitativa continua","cualitativa","cuantitativa continua","cualitativa","cuantitativa continua","cualitativa","cuantitativa continua","cualitativa","cualitativa")
Escala_de_Medición <- c("Nominal","Intervalo","Nominal","Intervalo","Nominal","Intervalo","Nominal","Intervalo","Nominal","Nominal")
table<-data.frame(Variable,Type,Escala_de_Medición)
knitr::kable(table)
Variable Type Escala_de_Medición
nombre cualitativa Nominal
edad cuantitativa continua Intervalo
genero cualitativa Nominal
alta cuantitativa continua Intervalo
motivo_baja cualitativa Nominal
duracion cuantitativa continua Intervalo
puesto cualitativa Nominal
salario_diario cuantitativa continua Intervalo
estado cualitativa Nominal
e.civil. cualitativa Nominal

DELIVERY PLAN

Escoger la base datos

# file.choose()
devplan <- read.csv("C:\\Users\\sofia\\Downloads\\DELIVERY PLAN bdf_Prueba.csv")

Entendemos la base de datos

resumen <- summary(devplan)
resumen
##     ID_Fecha        Fecha             CLIENTE             Pedidos       
##  Min.   : 1.00   Length:228         Length:228         Min.   :    0.0  
##  1st Qu.: 3.75   Class :character   Class :character   1st Qu.:    0.0  
##  Median : 6.50   Mode  :character   Mode  :character   Median :    0.0  
##  Mean   : 6.50                                         Mean   : 1703.1  
##  3rd Qu.: 9.25                                         3rd Qu.:  233.8  
##  Max.   :12.00                                         Max.   :52779.0

SECCION 1. Limpieza, Transformación, y Organización de Bases de Datos

Técnica 1. Convertir tipos de datos

Convertir de caracter a fecha

La limpieza y modificación de filas y columnas respecto a las variables se realizó directamente en Excel por cuestiones de facilidad ya que la base estaba ordenada de una manera en donde R resultaría mucho más complicado.

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

1.¿Cuántas variables y cuántos registros tiene la base de datos?

R= 228 registros y 4 variables
# install.packages("psych")
str(devplan1)
## 'data.frame':    228 obs. of  4 variables:
##  $ ID_Fecha: int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Fecha   : Date, format: "2022-01-31" "2022-01-31" ...
##  $ CLIENTE : chr  "STB3" "STB 1" "YF RAMOS" "INOAC POLYTEC" ...
##  $ Pedidos : int  481 0 227 0 400 328 393 0 8975 449 ...
library(psych)
describe(devplan1)
## Warning in FUN(newX[, i], ...): ningún argumento finito para min; retornando Inf
## Warning in FUN(newX[, i], ...): ningun argumento finito para max; retornando
## -Inf
##          vars   n    mean      sd median trimmed  mad min   max range skew
## ID_Fecha    1 228    6.50    3.46    6.5    6.50 4.45   1    12    11 0.00
## Fecha       2 228     NaN      NA     NA     NaN   NA Inf  -Inf  -Inf   NA
## CLIENTE*    3 228   10.00    5.49   10.0   10.00 7.41   1    19    18 0.00
## Pedidos     4 228 1703.14 6164.04    0.0  251.26 0.00   0 52779 52779 5.69
##          kurtosis     se
## ID_Fecha    -1.23   0.23
## Fecha          NA     NA
## CLIENTE*    -1.22   0.36
## Pedidos     37.14 408.22

2.¿Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua.?

Variable<-c("ID_Fecha","Fecha","CLIENTE","Pedidos")
Type<-c("cuantitativa continua","cuantitativa continua","cualitativa","cuantitativa continua")
table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
ID_Fecha cuantitativa continua
Fecha cuantitativa continua
CLIENTE cualitativa
Pedidos cuantitativa continua

3. Elige la escala de medición de cada variable.

Variable<-c("ID_Fecha","Fecha","CLIENTE","Pedidos")
Type<-c("cuantitativa continua","cuantitativa continua","cualitativa","cuantitativa continua")
Escala_de_Medición <- c("Razon","Razon","Nominal","Razon")
table<-data.frame(Variable,Type,Escala_de_Medición)
knitr::kable(table)
Variable Type Escala_de_Medición
ID_Fecha cuantitativa continua Razon
Fecha cuantitativa continua Razon
CLIENTE cualitativa Nominal
Pedidos cuantitativa continua Razon

Análisis Exploratorio de las Bases de Datos

Tabla con los principales estadísticos descriptivos

Estadísticos descriptivos Delivery Plan

mediana <- median(devplan1$Pedidos, na.rm = TRUE)
mediana
## [1] 0
describe(devplan1)
## Warning in FUN(newX[, i], ...): ningún argumento finito para min; retornando Inf
## Warning in FUN(newX[, i], ...): ningun argumento finito para max; retornando
## -Inf
##          vars   n    mean      sd median trimmed  mad min   max range skew
## ID_Fecha    1 228    6.50    3.46    6.5    6.50 4.45   1    12    11 0.00
## Fecha       2 228     NaN      NA     NA     NaN   NA Inf  -Inf  -Inf   NA
## CLIENTE*    3 228   10.00    5.49   10.0   10.00 7.41   1    19    18 0.00
## Pedidos     4 228 1703.14 6164.04    0.0  251.26 0.00   0 52779 52779 5.69
##          kurtosis     se
## ID_Fecha    -1.23   0.23
## Fecha          NA     NA
## CLIENTE*    -1.22   0.36
## Pedidos     37.14 408.22

Para conocer estas funciones estadísticas realizamos una descripción de la base de datos, donde podemos ver que la mediana es 0. Hay un total de 228 registros y utilizamos 4 variables para acomodo de las gráficas en donde contabilizamos el número de pedidos por mes y cliente.

Histograma general

hist(devplan1$Pedidos) 

DELIVERY PERFORMANCE

Escoger la base datos

# file.choose()
devper <- read.csv("C:\\Users\\sofia\\Downloads\\FORM - Delivery Performance C.csv")

Entendemos la base de datos

resumen <- summary(devper)
resumen
##     fecha             cliente               dif       
##  Length:52          Length:52          Min.   : 0.00  
##  Class :character   Class :character   1st Qu.: 0.00  
##  Mode  :character   Mode  :character   Median : 0.00  
##                                        Mean   :16.07  
##                                        3rd Qu.:29.38  
##                                        Max.   :71.25

SECCION 1. Limpieza, Transformación, y Organización de Bases de Datos

Técnica 1. Convertir tipos de datos

Se realizó una limpia previa a la base de datos debido a que no se podía manejar en R, ya que el formato en que se encontraba no permitía que R pudiera entender cuales eran las variables de nuestra base de datos, por lo tanto las modificaciones y limpiezas que se realizaron fue la técnica de ‘Remover valores irrelevantes’ en este caso quitamos la conclusión porque no tendría valor en la base de datos, eliminamos target (horas) y tomamos el valor de cada inicio de mes para comparar principio de mes con mes, después en R se trabajo con la técnica de convertir tipos de datos en este caso de caracter a fecha y caracter a hora.

Convertir de caracter a fecha
devper2 <- devper
devper2$fecha <- as.Date(devper2$fecha, format ="%d/%m/%y")
library(tibble)
tibble(devper2)  
## # A tibble: 52 × 3
##    fecha      cliente      dif
##    <date>     <chr>      <dbl>
##  1 2021-07-31 "PRINTEL "   4.9
##  2 2021-07-31 "MAHLE"     15.7
##  3 2021-07-31 "MAGNA"      0  
##  4 2021-07-31 "VARROC"     0  
##  5 2021-08-31 "PRINTEL "  27.7
##  6 2021-08-31 "MAHLE"     67.3
##  7 2021-08-31 "MAGNA"      0  
##  8 2021-08-31 "VARROC"     0  
##  9 2021-09-30 "PRINTEL "   8.6
## 10 2021-09-30 "MAHLE"     56.8
## # … with 42 more rows
Cambiar los nombres de las variables más cortas y específicas
names(devper2) [3] = "delay_performance"
names(devper2)
## [1] "fecha"             "cliente"           "delay_performance"

1.¿Cuántas variables y cuántos registros tiene la base de datos?

R= 52 registros y 3 variables
# install.packages("psych")
str(devper2)
## 'data.frame':    52 obs. of  3 variables:
##  $ fecha            : Date, format: "2021-07-31" "2021-07-31" ...
##  $ cliente          : chr  "PRINTEL " "MAHLE" "MAGNA" "VARROC" ...
##  $ delay_performance: num  4.9 15.7 0 0 27.7 ...
library(psych)
describe(devper2)
## Warning in FUN(newX[, i], ...): ningún argumento finito para min; retornando Inf
## Warning in FUN(newX[, i], ...): ningun argumento finito para max; retornando
## -Inf
##                   vars  n  mean    sd median trimmed  mad min   max range skew
## fecha                1 52   NaN    NA     NA     NaN   NA Inf  -Inf  -Inf   NA
## cliente*             2 52  2.50  1.13    2.5    2.50 1.48   1  4.00  3.00 0.00
## delay_performance    3 52 16.07 24.63    0.0   11.88 0.00   0 71.25 71.25 1.15
##                   kurtosis   se
## fecha                   NA   NA
## cliente*             -1.42 0.16
## delay_performance    -0.33 3.42

2.¿Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua.?

Variable<-c("fecha","cliente","dif")
Type<-c("cuantitativa continua","cualitativa","cuantitativa continua")
table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
fecha cuantitativa continua
cliente cualitativa
dif cuantitativa continua

3. Elige la escala de medición de cada variable.

Variable<-c("fecha","cliente","dif")
Type<-c("cuantitativa continua","cualitativa","cuantitativa continua")
Escala_de_Medición <- c("Razon","Nominal","Razon")
table<-data.frame(Variable,Type,Escala_de_Medición)
knitr::kable(table)
Variable Type Escala_de_Medición
fecha cuantitativa continua Razon
cliente cualitativa Nominal
dif cuantitativa continua Razon

Análisis Exploratorio de las Bases de Datos

Tabla con los principales estadísticos descriptivos

Estadísticos descriptivos Delivery Performance

# install.packages("psych")
library(psych)
describe(devper2)
##                   vars  n  mean    sd median trimmed  mad min   max range skew
## fecha                1 52   NaN    NA     NA     NaN   NA Inf  -Inf  -Inf   NA
## cliente*             2 52  2.50  1.13    2.5    2.50 1.48   1  4.00  3.00 0.00
## delay_performance    3 52 16.07 24.63    0.0   11.88 0.00   0 71.25 71.25 1.15
##                   kurtosis   se
## fecha                   NA   NA
## cliente*             -1.42 0.16
## delay_performance    -0.33 3.42
Variables <-c("Diferencia Delivery")
Media <-c("16.07")
Mediana <-c("0")
Desviacion_estandar <-c("24.63")
table3 <-data.frame(Variables, Media, Mediana, Desviacion_estandar)
knitr::kable(table3)
Variables Media Mediana Desviacion_estandar
Diferencia Delivery 16.07 0 24.63

PRODUCCION

Escoger la base datos

# file.choose()
prod <- read.csv("C:\\Users\\sofia\\OneDrive\\Documentos\\RETO\\Produccion Carton.csv")

Entendemos la base de datos

resumen <- summary(prod)
resumen
##       DIA           FECHA             CLIENTE             IDFORM         
##  Min.   : 1.00   Length:2678        Length:2678        Length:2678       
##  1st Qu.: 7.00   Class :character   Class :character   Class :character  
##  Median :14.00   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :13.99                                                           
##  3rd Qu.:21.00                                                           
##  Max.   :27.00                                                           
##    PRODUCTO           PZA_PROG           TMO_MIN             HR_FIN         
##  Length:2678        Length:2678        Length:2678        Length:2678       
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  ESTACION_ARRANQUE  LAMINAS_PROCESADAS    SEP_UP          INICIO.DE.PROCESO 
##  Length:2678        Length:2678        Length:2678        Length:2678       
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  FIN_DE_PROCESO     TIEMPO_CALIDAD    
##  Length:2678        Length:2678       
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
## 

SECCION 1. Limpieza, Transformación, y Organización de Bases de Datos

Técnica 1. Remover datos irrelevantes.

Eliminar columnas

La base de datos de Produccion tenía varias variables que para nuestro analisis no lo ocupabamos por lo que las eliminamos con la función subset

prod1 <- prod
prod1 <- subset (prod1, select = -c (IDFORM,HR_FIN,ESTACION_ARRANQUE,INICIO.DE.PROCESO,FIN_DE_PROCESO))
summary (prod1)
##       DIA           FECHA             CLIENTE            PRODUCTO        
##  Min.   : 1.00   Length:2678        Length:2678        Length:2678       
##  1st Qu.: 7.00   Class :character   Class :character   Class :character  
##  Median :14.00   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :13.99                                                           
##  3rd Qu.:21.00                                                           
##  Max.   :27.00                                                           
##    PZA_PROG           TMO_MIN          LAMINAS_PROCESADAS    SEP_UP         
##  Length:2678        Length:2678        Length:2678        Length:2678       
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  TIEMPO_CALIDAD    
##  Length:2678       
##  Class :character  
##  Mode  :character  
##                    
##                    
## 

Técnica 2. Convertir tipos de datos.

Convertir de caracter a fecha

La base de datos no contenía ningun formato, por lo que en el analisis los datos podían tener errores por se convirtió la fecha a formato.

library(tibble)
prod2 <- prod1
prod2$FECHA <- as.Date(prod2$FECHA, format = "%d/%m/%Y")
tibble (prod2)
## # A tibble: 2,678 × 9
##      DIA FECHA      CLIENTE PRODUCTO      PZA_P…¹ TMO_MIN LAMIN…² SEP_UP TIEMP…³
##    <int> <date>     <chr>   <chr>         <chr>   <chr>   <chr>   <chr>  <chr>  
##  1     1 2022-08-01 VARROC  763 . KIT. C… 199     15      201     00:12  1      
##  2     1 2022-08-01 VARROC  747 KIT. CAJ… 57      10      116     00:05  1      
##  3     1 2022-08-01 VARROC  747 KIT. TAP… 68      10      69      00:07  1      
##  4     1 2022-08-01 DENSO   TOYOTA. MCV.… 192     15      49      00:05  1      
##  5     1 2022-08-01 DENSO   TOYOTA. MCV.… 192     15      49      00:06  1      
##  6     1 2022-08-01 YANFENG MODELO Y. TM… 400     30      801     00:02  1      
##  7     1 2022-08-01 YANFENG MODELO Y. TM… 80      15      41      00:10  1      
##  8     1 2022-08-01 YANFENG MODELO Y. TM… 104     15      53      00:00  1      
##  9     1 2022-08-01 YANFENG MODELO Y. TM… 104     15      53      00:00  1      
## 10     1 2022-08-01 YANFENG MODELO Y. TM… 160     20      55      00:08  1      
## # … with 2,668 more rows, and abbreviated variable names ¹​PZA_PROG,
## #   ²​LAMINAS_PROCESADAS, ³​TIEMPO_CALIDAD
Convertir de caracter a entero

En este caso, se habla de laminas que se trabajaron por lo que necesitamos las cantidades en entero.

prod3 <- prod2
prod3$PZA_PROG <- substr(prod3$PZA_PROG, start = 1, stop = 2) 
prod3$TMO_MIN <- substr(prod3$TMO_MIN, start = 1, stop = 2) 
prod3$LAMINAS_PROCESADAS <- substr(prod3$LAMINAS_PROCESADAS, start = 1, stop = 2) 

tibble(prod3)
## # A tibble: 2,678 × 9
##      DIA FECHA      CLIENTE PRODUCTO      PZA_P…¹ TMO_MIN LAMIN…² SEP_UP TIEMP…³
##    <int> <date>     <chr>   <chr>         <chr>   <chr>   <chr>   <chr>  <chr>  
##  1     1 2022-08-01 VARROC  763 . KIT. C… 19      15      20      00:12  1      
##  2     1 2022-08-01 VARROC  747 KIT. CAJ… 57      10      11      00:05  1      
##  3     1 2022-08-01 VARROC  747 KIT. TAP… 68      10      69      00:07  1      
##  4     1 2022-08-01 DENSO   TOYOTA. MCV.… 19      15      49      00:05  1      
##  5     1 2022-08-01 DENSO   TOYOTA. MCV.… 19      15      49      00:06  1      
##  6     1 2022-08-01 YANFENG MODELO Y. TM… 40      30      80      00:02  1      
##  7     1 2022-08-01 YANFENG MODELO Y. TM… 80      15      41      00:10  1      
##  8     1 2022-08-01 YANFENG MODELO Y. TM… 10      15      53      00:00  1      
##  9     1 2022-08-01 YANFENG MODELO Y. TM… 10      15      53      00:00  1      
## 10     1 2022-08-01 YANFENG MODELO Y. TM… 16      20      55      00:08  1      
## # … with 2,668 more rows, and abbreviated variable names ¹​PZA_PROG,
## #   ²​LAMINAS_PROCESADAS, ³​TIEMPO_CALIDAD
prod3$PZA_PROG <- as.integer(prod3$PZA_PROG)
prod3$TMO_MIN <- as.integer(prod3$TMO_MIN)
## Warning: NAs introducidos por coerción
prod3$LAMINAS_PROCESADAS <- as.integer(prod3$LAMINAS_PROCESADAS)
## Warning: NAs introducidos por coerción
str(prod3)      
## 'data.frame':    2678 obs. of  9 variables:
##  $ DIA               : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ FECHA             : Date, format: "2022-08-01" "2022-08-01" ...
##  $ CLIENTE           : chr  "VARROC" "VARROC" "VARROC" "DENSO" ...
##  $ PRODUCTO          : chr  "763 . KIT. CAJA." "747 KIT. CAJA HSC. ( 2 Partes)" "747 KIT. TAPA." "TOYOTA. MCV. Insterto D 2R. CORTE. 1 Golpe = 12 piezas. ( 9 Pza. / Celda)." ...
##  $ PZA_PROG          : int  19 57 68 19 19 40 80 10 10 16 ...
##  $ TMO_MIN           : int  15 10 10 15 15 30 15 15 15 20 ...
##  $ LAMINAS_PROCESADAS: int  20 11 69 49 49 80 41 53 53 55 ...
##  $ SEP_UP            : chr  "00:12" "00:05" "00:07" "00:05" ...
##  $ TIEMPO_CALIDAD    : chr  "1" "1" "1" "1" ...

Técnica 3. Valores faltantes.

¿Cuántos NA tengo en la base de datos?
sum(is.na(prod3))
## [1] 1363
sum(is.na(prod))
## [1] 0
¿Cuántos NA tengo por variable?
sapply(prod3, function(x)sum(is.na(x)))
##                DIA              FECHA            CLIENTE           PRODUCTO 
##                  0                  0                  0                  0 
##           PZA_PROG            TMO_MIN LAMINAS_PROCESADAS             SEP_UP 
##                  0                737                626                  0 
##     TIEMPO_CALIDAD 
##                  0
Reemplazar NA con ceros
prod4 <-prod3
prod4 [is.na(prod4)]<-0
summary(prod4) 
##       DIA            FECHA              CLIENTE            PRODUCTO        
##  Min.   : 1.00   Min.   :2022-08-01   Length:2678        Length:2678       
##  1st Qu.: 7.00   1st Qu.:2022-08-08   Class :character   Class :character  
##  Median :14.00   Median :2022-08-16   Mode  :character   Mode  :character  
##  Mean   :13.99   Mean   :2022-08-15                                        
##  3rd Qu.:21.00   3rd Qu.:2022-08-24                                        
##  Max.   :27.00   Max.   :2022-08-31                                        
##     PZA_PROG        TMO_MIN      LAMINAS_PROCESADAS    SEP_UP         
##  Min.   : 1.00   Min.   : 0.00   Min.   : 0.00      Length:2678       
##  1st Qu.:14.00   1st Qu.: 0.00   1st Qu.: 0.00      Class :character  
##  Median :20.00   Median :15.00   Median :11.00      Mode  :character  
##  Mean   :27.45   Mean   :16.03   Mean   :18.11                        
##  3rd Qu.:40.00   3rd Qu.:25.00   3rd Qu.:27.00                        
##  Max.   :99.00   Max.   :90.00   Max.   :98.00                        
##  TIEMPO_CALIDAD    
##  Length:2678       
##  Class :character  
##  Mode  :character  
##                    
##                    
## 

1.¿Cuántas variables y cuántos registros tiene la base de datos?

R= 2678 registros y 9 variables
# install.packages("psych")
str(prod4)
## 'data.frame':    2678 obs. of  9 variables:
##  $ DIA               : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ FECHA             : Date, format: "2022-08-01" "2022-08-01" ...
##  $ CLIENTE           : chr  "VARROC" "VARROC" "VARROC" "DENSO" ...
##  $ PRODUCTO          : chr  "763 . KIT. CAJA." "747 KIT. CAJA HSC. ( 2 Partes)" "747 KIT. TAPA." "TOYOTA. MCV. Insterto D 2R. CORTE. 1 Golpe = 12 piezas. ( 9 Pza. / Celda)." ...
##  $ PZA_PROG          : int  19 57 68 19 19 40 80 10 10 16 ...
##  $ TMO_MIN           : num  15 10 10 15 15 30 15 15 15 20 ...
##  $ LAMINAS_PROCESADAS: num  20 11 69 49 49 80 41 53 53 55 ...
##  $ SEP_UP            : chr  "00:12" "00:05" "00:07" "00:05" ...
##  $ TIEMPO_CALIDAD    : chr  "1" "1" "1" "1" ...
library(psych)
describe(prod4)
## Warning in FUN(newX[, i], ...): ningún argumento finito para min; retornando Inf
## Warning in FUN(newX[, i], ...): ningun argumento finito para max; retornando
## -Inf
##                    vars    n   mean    sd median trimmed    mad min  max range
## DIA                   1 2678  13.99  7.94     14   13.99  10.38   1   27    26
## FECHA                 2 2678    NaN    NA     NA     NaN     NA Inf -Inf  -Inf
## CLIENTE*              3 2678   6.49  2.71      6    6.49   2.97   1   11    10
## PRODUCTO*             4 2678 164.57 94.58    161  165.76 114.16   1  321   320
## PZA_PROG              5 2678  27.45 18.21     20   24.66  14.83   1   99    98
## TMO_MIN               6 2678  16.03 14.71     15   14.08  14.83   0   90    90
## LAMINAS_PROCESADAS    7 2678  18.11 22.15     11   14.23  16.31   0   98    98
## SEP_UP*               8 2678   7.02  8.94      3    5.00   0.00   1   76    75
## TIEMPO_CALIDAD*       9 2678   8.12  6.39     12    7.81   0.00   1   36    35
##                     skew kurtosis   se
## DIA                 0.01    -1.21 0.15
## FECHA                 NA       NA   NA
## CLIENTE*            0.16    -0.76 0.05
## PRODUCTO*          -0.03    -1.17 1.83
## PZA_PROG            1.38     1.70 0.35
## TMO_MIN             1.11     1.79 0.28
## LAMINAS_PROCESADAS  1.30     1.02 0.43
## SEP_UP*             3.72    18.40 0.17
## TIEMPO_CALIDAD*     0.70     1.03 0.12

2.¿Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua.?

Variable<-c("DIA","FECHA","CLIENTE","PRODUCTO","PZA_PROG","TMO_MIN","LAMINAS_PROCESADAS","SEP_UP","TIEMPO_CALIDAD")
Type<-c("Cuantitativa continua","Cuantitativa continua","Cualitativa","Cualitativa","Cuantitativa discreta","Cualitativa","Cuantitativa discreta","Cuantitativa continua","Cualitativa")
table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
DIA Cuantitativa continua
FECHA Cuantitativa continua
CLIENTE Cualitativa
PRODUCTO Cualitativa
PZA_PROG Cuantitativa discreta
TMO_MIN Cualitativa
LAMINAS_PROCESADAS Cuantitativa discreta
SEP_UP Cuantitativa continua
TIEMPO_CALIDAD Cualitativa

3. Elige la escala de medición de cada variable.

Variable<-c("DIA","FECHA","CLIENTE","PRODUCTO","PZA_PROG","TMO_MIN","LAMINAS_PROCESADAS","SEP_UP","TIEMPO_CALIDAD")
Type<-c("Cuantitativa continua","Cuantitativa continua","Cualitativa","Cualitativa","Cuantitativa discreta","Cualitativa","Cuantitativa discreta","Cuantitativa continua","Cualitativa")
Escala_de_Medición <- c("Razon","Razon","Nominal","Nominal","Razon","Intervalo","Razon","Intervalo","Ordinal")
table<-data.frame(Variable,Type,Escala_de_Medición)
knitr::kable(table)
Variable Type Escala_de_Medición
DIA Cuantitativa continua Razon
FECHA Cuantitativa continua Razon
CLIENTE Cualitativa Nominal
PRODUCTO Cualitativa Nominal
PZA_PROG Cuantitativa discreta Razon
TMO_MIN Cualitativa Intervalo
LAMINAS_PROCESADAS Cuantitativa discreta Razon
SEP_UP Cuantitativa continua Intervalo
TIEMPO_CALIDAD Cualitativa Ordinal

Análisis Exploratorio de las Bases de Datos

Tabla con los principales estadísticos descrptivos

Estadísticos descriptivos Producción
cruzada1<-table(prod4$FECHA,prod4$PZA_PROG)
knitr::kable(cruzada1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 62 64 65 66 68 69 70 72 75 76 77 78 79 80 88 94 96 99
2022-08-01 0 0 0 0 0 0 0 0 0 15 0 1 0 0 0 5 0 0 17 29 1 0 0 1 0 2 0 0 0 2 0 5 0 0 0 0 0 0 0 12 1 0 0 0 0 0 0 1 0 4 0 0 0 0 0 1 2 0 0 2 1 0 0 0 1 2 1 0 0 0 0 0 0 4 0 0 0 1
2022-08-02 0 0 0 0 0 0 0 1 0 30 1 0 1 15 5 5 4 0 0 17 0 0 0 6 0 3 0 0 0 2 0 2 0 0 1 0 0 1 0 11 0 0 0 1 2 0 0 0 0 9 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0
2022-08-03 0 0 0 0 0 0 0 1 0 24 2 4 0 9 4 3 4 0 3 20 2 0 0 1 0 1 0 0 0 6 0 0 0 0 1 0 0 1 0 7 0 0 0 2 4 0 0 2 0 4 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0
2022-08-04 0 0 0 0 0 0 0 0 0 11 1 0 0 0 4 3 0 0 5 20 1 1 0 8 1 0 0 2 0 2 0 2 0 0 2 0 0 0 0 7 0 0 0 0 1 0 0 0 0 6 2 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
2022-08-05 0 3 0 0 1 0 0 1 0 14 0 1 0 0 3 7 0 0 8 14 1 0 0 5 0 0 0 0 0 2 0 1 0 0 0 0 0 2 0 7 0 0 0 0 0 1 0 1 0 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 1 0 1 0 0 0 0
2022-08-06 0 0 1 0 1 0 0 1 0 8 0 6 0 0 1 0 1 0 0 13 0 0 0 4 0 2 0 0 0 4 1 0 0 0 0 0 1 3 0 8 0 0 0 1 0 0 0 1 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0
2022-08-08 0 0 0 0 0 0 0 1 0 19 3 2 2 1 3 6 2 3 12 28 4 0 0 0 0 0 3 0 0 2 0 1 0 1 2 4 2 1 0 7 0 0 0 1 1 1 1 0 0 3 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 3 0 1 2 0 0 0 0 0 0 1 0 0
2022-08-09 0 0 0 0 0 0 0 1 0 10 0 0 1 0 0 1 0 3 10 25 2 0 0 0 1 0 2 0 0 2 0 1 2 1 2 3 2 0 1 14 0 0 0 1 0 1 1 0 0 12 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0 1 0 0
2022-08-10 0 0 0 0 0 0 0 1 0 32 2 3 0 1 2 0 1 5 9 18 1 0 0 0 0 0 0 0 0 4 0 0 0 1 0 2 1 1 0 9 0 0 0 2 0 1 1 0 0 2 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 2 1 0
2022-08-11 0 0 0 0 0 1 0 0 0 25 2 0 0 11 5 0 0 1 0 22 2 0 1 0 0 0 1 0 0 5 0 0 0 2 0 1 2 0 0 11 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0
2022-08-12 2 0 0 0 0 1 0 0 0 13 1 0 1 11 0 2 0 1 0 26 1 0 2 0 0 0 1 1 0 1 0 0 0 2 0 3 1 0 0 9 0 0 0 0 0 0 0 1 1 2 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 6 0 0 0 1 0 0 0 3 0 0 0 0
2022-08-13 0 0 0 0 0 0 0 0 0 18 1 2 1 2 1 2 0 0 1 24 2 0 1 0 0 0 1 0 0 6 0 0 0 0 0 1 0 1 0 8 0 0 1 0 0 0 0 2 0 5 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 4 0 2 0 1 0 0 0 0 1 0 0 0
2022-08-15 0 0 0 0 1 0 0 0 0 23 1 2 1 1 2 1 0 0 1 20 1 0 1 0 0 0 1 0 0 8 0 0 0 0 0 0 1 1 0 11 0 0 0 0 0 0 0 1 0 18 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 3 0 1 0 1 0 0 0 0 1 0 0 0
2022-08-16 0 0 0 1 0 0 0 0 0 19 0 0 1 0 1 0 3 0 0 21 1 0 0 0 1 1 1 0 0 4 0 0 0 0 1 0 0 1 0 14 0 0 0 1 0 0 0 0 0 13 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 3 0 0 0 1 0 0 1 5 0 0 1 0
2022-08-17 0 0 0 0 0 0 0 1 0 30 1 0 1 12 1 1 2 1 0 15 2 1 0 2 0 0 0 0 0 3 0 0 0 0 0 2 2 1 0 8 0 0 0 0 3 0 0 0 0 7 0 0 0 0 0 0 3 0 1 2 0 0 0 0 0 1 0 0 2 0 0 0 0 4 0 1 0 0
2022-08-18 0 0 0 0 0 0 0 0 0 19 2 0 1 1 1 0 1 1 0 17 1 0 0 12 0 0 0 0 0 6 0 0 0 0 0 3 0 0 0 9 0 0 0 0 0 1 1 0 0 8 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 1 0 0 0 3 0 0 0 2
2022-08-19 0 0 0 0 0 0 1 0 0 21 0 0 1 0 1 0 1 2 0 28 1 0 1 11 1 0 0 1 0 4 0 1 0 0 0 2 0 0 0 13 1 0 0 0 0 0 0 0 0 14 0 0 0 0 0 0 3 0 0 4 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0
2022-08-20 0 0 0 0 0 0 0 0 0 13 0 2 0 1 2 0 0 0 0 17 0 0 3 12 0 0 0 1 1 5 0 0 0 0 0 2 0 0 0 4 1 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 1 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1
2022-08-22 0 0 0 0 0 0 0 0 0 12 0 0 0 0 0 0 0 1 0 26 0 0 3 0 0 0 0 0 0 5 0 0 0 0 0 2 0 0 0 9 1 0 0 0 0 0 0 0 0 12 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1
2022-08-23 0 0 0 0 0 0 0 0 0 19 0 1 1 0 2 6 0 0 2 28 0 1 1 10 1 0 0 0 0 3 0 1 0 0 0 0 0 1 0 12 0 0 0 0 0 0 0 0 0 4 0 1 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 2 0
2022-08-24 0 0 0 0 0 0 0 0 0 16 3 1 1 0 2 4 0 0 1 32 0 1 0 12 0 0 0 0 0 5 0 1 0 0 0 1 0 1 0 7 1 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0
2022-08-25 0 0 0 0 0 0 1 0 0 21 0 0 1 0 1 2 0 0 0 37 0 1 0 10 0 0 0 0 0 3 0 2 0 0 0 0 0 1 0 9 1 0 0 0 1 0 0 0 0 7 0 1 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0
2022-08-26 0 0 0 0 0 0 0 0 0 30 4 0 1 0 1 1 0 0 2 14 2 0 0 10 0 0 0 0 0 10 0 4 0 0 0 0 0 0 0 3 1 0 0 0 1 0 0 0 0 9 0 0 0 0 0 1 2 0 0 4 0 0 4 0 0 0 0 1 0 1 0 0 0 1 0 0 2 0
2022-08-27 0 0 0 0 0 0 0 1 0 16 0 2 0 0 1 0 0 0 0 25 0 0 0 0 0 1 0 0 0 5 0 0 0 0 0 0 0 0 0 9 1 1 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2022-08-29 0 0 0 0 0 0 0 0 0 15 1 0 1 0 1 0 0 0 0 25 0 2 0 15 1 0 0 0 0 10 0 2 0 0 2 0 1 1 0 12 0 0 0 0 0 0 0 0 0 9 0 0 2 0 1 2 0 0 0 2 1 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0
2022-08-30 0 0 0 0 1 1 0 0 0 26 3 1 1 0 1 2 0 0 2 24 0 0 0 12 0 0 0 1 0 2 0 2 0 0 2 0 0 1 0 9 0 0 0 0 0 0 0 0 0 8 0 0 2 0 0 2 0 0 0 3 0 1 3 0 0 0 1 1 0 0 0 0 0 4 0 0 1 0
2022-08-31 0 0 0 3 0 0 0 0 1 24 1 1 1 0 0 2 0 2 0 24 8 2 0 4 0 0 0 0 0 4 0 2 0 0 0 3 0 0 0 8 0 0 0 0 0 0 0 0 0 5 0 0 1 0 0 0 0 0 0 6 0 0 3 0 0 0 0 0 0 0 0 0 0 3 0 0 3 0
cruzada2<-table(prod4$LAMINAS_PROCESADAS,prod4$TMO_MIN)
knitr::kable(cruzada2)
0 5 10 12 15 20 25 30 35 40 45 50 60 65 70 75 80 90
0 719 0 90 0 74 68 141 9 8 7 0 14 9 0 4 0 0 1
1 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 0 0 4 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
6 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
8 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
9 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10 4 0 22 0 22 52 50 4 1 1 2 8 0 0 0 0 0 0
11 1 0 22 0 14 3 0 2 0 0 0 0 4 0 0 0 0 0
12 0 0 5 1 5 13 4 0 0 1 0 0 4 0 0 0 1 0
13 1 0 12 0 3 8 3 1 0 1 0 0 0 0 3 0 0 0
14 2 0 1 0 1 11 3 1 0 4 0 0 0 0 0 0 0 0
15 0 0 4 0 4 10 2 1 2 4 0 5 0 0 0 3 0 0
16 2 0 9 0 2 9 2 0 0 0 0 0 0 1 0 0 0 0
17 0 0 9 1 0 1 1 0 0 2 0 1 0 0 1 0 0 0
18 1 0 2 0 1 1 1 1 0 2 7 14 0 0 0 0 0 0
19 0 0 1 0 1 3 6 2 0 1 0 3 0 0 0 0 0 0
20 5 0 6 0 10 10 226 7 1 5 2 9 2 0 0 0 1 0
21 0 0 19 1 1 2 4 0 0 2 0 5 0 0 0 0 0 0
22 0 0 2 0 2 3 5 1 0 0 0 0 0 0 0 0 0 0
23 0 0 1 0 1 2 1 0 0 0 0 0 1 0 0 0 0 0
24 1 0 2 0 1 5 13 0 0 0 0 0 0 0 0 0 0 0
25 0 0 3 0 7 3 4 0 0 0 0 0 1 0 0 0 0 0
26 0 0 8 0 7 1 0 0 0 0 0 0 1 0 0 0 0 0
27 0 0 12 0 7 1 1 0 0 0 0 0 0 0 0 0 0 0
28 0 0 1 0 3 0 2 0 1 0 0 0 0 0 0 0 0 0
29 0 0 3 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0
30 2 0 3 0 4 1 2 2 20 0 0 3 1 0 0 0 0 0
31 0 0 6 0 2 2 0 1 1 0 0 0 0 0 0 0 0 0
32 1 0 7 0 8 3 1 0 4 0 0 0 0 0 0 0 0 0
33 0 0 5 0 0 0 0 0 4 0 0 1 0 0 0 0 0 0
34 0 0 3 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0
35 1 0 3 0 3 4 1 0 4 0 0 0 0 0 0 0 0 1
36 0 0 4 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0
37 1 0 7 0 9 1 3 1 4 0 0 0 1 0 0 1 0 0
38 0 0 1 0 0 0 0 0 3 0 0 0 0 0 1 0 0 0
39 1 0 10 0 1 1 1 1 2 1 0 0 0 0 0 0 0 0
40 4 0 2 0 5 4 9 3 0 24 0 2 2 0 2 1 0 0
41 1 0 9 0 3 2 2 1 0 3 0 0 0 0 0 0 0 0
42 2 0 3 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0
43 1 0 1 0 1 0 4 0 0 0 0 0 0 0 0 0 0 0
44 1 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0
45 0 0 5 0 4 0 2 0 0 1 0 0 0 0 0 0 0 0
47 1 0 6 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
48 0 0 2 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0
49 0 0 1 0 12 5 0 0 0 0 0 0 0 0 0 0 0 0
50 12 0 8 0 20 0 3 0 0 1 0 3 0 0 0 0 0 0
51 0 0 29 0 20 0 4 2 0 2 0 0 2 0 0 0 0 0
52 0 0 7 0 11 3 4 0 0 0 0 0 0 0 0 0 0 0
53 0 1 3 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0
54 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
55 0 0 1 0 1 3 0 0 0 1 0 0 0 0 0 0 0 0
56 0 0 1 0 1 0 2 0 0 0 0 0 0 0 0 0 0 0
57 0 0 1 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0
58 0 0 2 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0
59 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
60 3 0 1 1 2 2 0 0 0 2 0 1 3 0 0 0 0 0
61 0 0 7 0 11 12 2 0 0 0 0 0 0 0 0 0 0 0
62 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
64 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
65 1 0 1 0 2 6 0 1 0 1 0 0 0 0 0 0 0 0
66 0 0 5 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0
67 0 0 1 0 3 2 1 0 0 0 0 0 0 0 0 0 0 0
68 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0
69 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
70 0 0 6 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
71 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
73 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0
74 0 0 0 0 1 1 1 0 0 0 0 0 2 0 0 0 0 0
75 1 0 0 0 1 1 0 0 0 2 0 0 0 0 0 0 0 0
76 0 0 0 0 3 0 0 0 1 0 0 0 0 0 0 0 0 0
77 0 0 0 0 0 4 0 0 1 0 0 0 0 0 0 0 0 0
78 0 0 2 0 3 1 3 0 0 2 0 0 0 0 1 0 0 0
79 0 0 0 0 0 0 1 0 0 3 0 0 0 0 0 0 0 0
80 3 0 1 0 0 0 1 1 0 2 0 0 0 0 0 0 0 0
81 0 0 0 0 1 13 3 0 0 0 0 0 0 0 0 0 0 0
82 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0
83 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
84 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0
85 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0
86 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0
89 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
90 0 0 1 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0
91 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
92 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
93 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
95 0 0 3 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
96 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
97 0 0 1 0 0 4 1 0 0 0 0 0 0 0 0 0 0 0
98 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# install.packages("psych")
library(psych)
describe(prod)
##                     vars    n   mean     sd median trimmed    mad min max range
## DIA                    1 2678  13.99   7.94     14   13.99  10.38   1  27    26
## FECHA*                 2 2678  13.99   7.94     14   13.99  10.38   1  27    26
## CLIENTE*               3 2678   6.49   2.71      6    6.49   2.97   1  11    10
## IDFORM*                4 2678 115.19  73.34    120  113.04  94.89   1 257   256
## PRODUCTO*              5 2678 164.57  94.58    161  165.76 114.16   1 321   320
## PZA_PROG*              6 2678  92.37  68.74     70   87.88  87.47   1 245   244
## TMO_MIN*               7 2678   6.51   4.56      7    6.15   4.45   1  23    22
## HR_FIN*                8 2678  70.58  59.09     69   69.26  91.92   1 158   157
## ESTACION_ARRANQUE*     9 2678  16.90   8.31     18   17.34  11.86   1  27    26
## LAMINAS_PROCESADAS*   10 2678  92.26 107.18     34   77.54  48.93   1 342   341
## SEP_UP*               11 2678   7.02   8.94      3    5.00   0.00   1  76    75
## INICIO.DE.PROCESO*    12 2678 185.17 200.63    103  162.63 151.23   1 622   621
## FIN_DE_PROCESO*       13 2678 193.98 210.15    105  171.56 154.19   1 630   629
## TIEMPO_CALIDAD*       14 2678   8.12   6.39     12    7.81   0.00   1  36    35
##                      skew kurtosis   se
## DIA                  0.01    -1.21 0.15
## FECHA*               0.01    -1.21 0.15
## CLIENTE*             0.16    -0.76 0.05
## IDFORM*              0.12    -1.10 1.42
## PRODUCTO*           -0.03    -1.17 1.83
## PZA_PROG*            0.41    -0.86 1.33
## TMO_MIN*             0.38    -0.53 0.09
## HR_FIN*              0.00    -1.72 1.14
## ESTACION_ARRANQUE*  -0.24    -1.40 0.16
## LAMINAS_PROCESADAS*  0.83    -0.72 2.07
## SEP_UP*              3.72    18.40 0.17
## INICIO.DE.PROCESO*   0.59    -1.14 3.88
## FIN_DE_PROCESO*      0.57    -1.23 4.06
## TIEMPO_CALIDAD*      0.70     1.03 0.12
Variables <-c("Cantidad" )
Media <-c("6.70" )
Mediana <-c("2" )
Desviacion_estandar <-c("11.85" )

table1 <- describe(prod)
knitr::kable(table1)
vars n mean sd median trimmed mad min max range skew kurtosis se
DIA 1 2678 13.991785 7.935437 14 13.991604 10.3782 1 27 26 0.0055451 -1.2146133 0.1533436
FECHA* 2 2678 13.991785 7.935437 14 13.991604 10.3782 1 27 26 0.0055451 -1.2146133 0.1533436
CLIENTE* 3 2678 6.488051 2.714336 6 6.494403 2.9652 1 11 10 0.1641304 -0.7644564 0.0524515
IDFORM* 4 2678 115.187827 73.343809 120 113.038246 94.8864 1 257 256 0.1168419 -1.1043278 1.4172882
PRODUCTO* 5 2678 164.572442 94.579970 161 165.757463 114.1602 1 321 320 -0.0334915 -1.1716116 1.8276536
PZA_PROG* 6 2678 92.371173 68.737320 70 87.882463 87.4734 1 245 244 0.4130128 -0.8627556 1.3282729
TMO_MIN* 7 2678 6.506348 4.558317 7 6.151586 4.4478 1 23 22 0.3812195 -0.5317357 0.0880845
HR_FIN* 8 2678 70.578043 59.089200 69 69.263993 91.9212 1 158 157 -0.0012525 -1.7150896 1.1418336
ESTACION_ARRANQUE* 9 2678 16.899925 8.310405 18 17.341884 11.8608 1 27 26 -0.2376414 -1.3960407 0.1605894
LAMINAS_PROCESADAS* 10 2678 92.256535 107.182504 34 77.539179 48.9258 1 342 341 0.8250050 -0.7230473 2.0711837
SEP_UP* 11 2678 7.020164 8.940197 3 4.995802 0.0000 1 76 75 3.7182375 18.3957175 0.1727594
INICIO.DE.PROCESO* 12 2678 185.165422 200.625976 103 162.630131 151.2252 1 622 621 0.5933001 -1.1378681 3.8768757
FIN_DE_PROCESO* 13 2678 193.981703 210.147590 105 171.555504 154.1904 1 630 629 0.5664325 -1.2277725 4.0608704
TIEMPO_CALIDAD* 14 2678 8.116505 6.390530 12 7.809235 0.0000 1 36 35 0.6964316 1.0294590 0.1234899

MERMA

Escoger la base datos

# file.choose()
merma <- read.csv("C:\\Users\\sofia\\OneDrive\\Documentos\\RETO\\FORM - Merma.csv")

Entendemos la base de datos

resumen <- summary(merma)
resumen
##     Fecha               Mes                Kilos     
##  Length:50          Length:50          Min.   : 790  
##  Class :character   Class :character   1st Qu.:3178  
##  Mode  :character   Mode  :character   Median :3925  
##                                        Mean   :3709  
##                                        3rd Qu.:4232  
##                                        Max.   :6140

SECCION 1. Limpieza, Transformación, y Organización de Bases de Datos

Técnica 1. Convertir tipos de datos.

Convertir de caracter a fecha

La base de datos no contenía ningun formato, por lo que en el analisis los datos podían tener errores por se convirtió la fecha a formato.

library(tibble)
merma1 <- merma
merma1$Fecha <- as.Date(merma1$Fecha, format = "%d/%m/%Y")
tibble (merma1)
## # A tibble: 50 × 3
##    Fecha      Mes     Kilos
##    <date>     <chr>   <int>
##  1 2022-01-11 ENERO    5080
##  2 2022-01-11 ENERO    3810
##  3 2022-01-22 ENERO    2990
##  4 2022-01-22 ENERO    2680
##  5 2022-02-18 FEBRERO  3650
##  6 2022-02-18 FEBRERO  4380
##  7 2022-02-18 FEBRERO  3870
##  8 2022-02-18 FEBRERO  3590
##  9 2022-02-18 FEBRERO  3410
## 10 2022-02-24 FEBRERO  3930
## # … with 40 more rows

Técnica 2. Remover valores irrelevantes.

Eliminar columnas

En la base de datos se contenía la fecha y el mes, por lo que consideramos que el mes no es necesario ya que tenemos la fecha, asi que lo eliminamos con la función de subset.

merma2 <- merma1
merma2 <- subset (merma2, select = -c (Mes))
summary (merma2)
##      Fecha                Kilos     
##  Min.   :2022-01-11   Min.   : 790  
##  1st Qu.:2022-03-12   1st Qu.:3178  
##  Median :2022-05-24   Median :3925  
##  Mean   :2022-05-25   Mean   :3709  
##  3rd Qu.:2022-08-10   3rd Qu.:4232  
##  Max.   :2022-09-21   Max.   :6140

1.¿Cuántas variables y cuántos registros tiene la base de datos?

R= 60 registros y 3 variables
# install.packages("psych")
str(merma2)
## 'data.frame':    50 obs. of  2 variables:
##  $ Fecha: Date, format: "2022-01-11" "2022-01-11" ...
##  $ Kilos: int  5080 3810 2990 2680 3650 4380 3870 3590 3410 3930 ...
library(psych)
describe(merma2)
## Warning in FUN(newX[, i], ...): ningún argumento finito para min; retornando Inf
## Warning in FUN(newX[, i], ...): ningun argumento finito para max; retornando
## -Inf
##       vars  n    mean      sd median trimmed    mad min  max range  skew
## Fecha    1 50     NaN      NA     NA     NaN     NA Inf -Inf  -Inf    NA
## Kilos    2 50 3708.52 1023.99   3925 3798.65 541.15 790 6140  5350 -0.94
##       kurtosis     se
## Fecha       NA     NA
## Kilos     1.65 144.81

2.¿Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua.?

Variable<-c("Fecha","Kilos")
Type<-c("Cuantitativa continua","Cuantitativa continua")
table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
Fecha Cuantitativa continua
Kilos Cuantitativa continua

3. Elige la escala de medición de cada variable.

Variable<-c("Fecha","Kilos")
Type<-c("Cuantitativa continua", "Cuantitativa continua")
Escala_de_Medición <- c("Razon","Razon")
table<-data.frame(Variable,Type,Escala_de_Medición)
knitr::kable(table)
Variable Type Escala_de_Medición
Fecha Cuantitativa continua Razon
Kilos Cuantitativa continua Razon

Análisis Exploratorio de las Bases de Datos

Tabla con los principales estadísticos descriptivos

Estadísticos descriptivos Merma

# install.packages("psych")
library(psych)
describe(merma2)
##       vars  n    mean      sd median trimmed    mad min  max range  skew
## Fecha    1 50     NaN      NA     NA     NaN     NA Inf -Inf  -Inf    NA
## Kilos    2 50 3708.52 1023.99   3925 3798.65 541.15 790 6140  5350 -0.94
##       kurtosis     se
## Fecha       NA     NA
## Kilos     1.65 144.81
Variables <-c("Kilos")
Media <-c("3709.52")
Mediana <-c("3925")
Desviacion_estandar <-c("1023.99")
table2 <-data.frame(Variables, Media, Mediana, Desviacion_estandar)
knitr::kable(table2)
Variables Media Mediana Desviacion_estandar
Kilos 3709.52 3925 1023.99

SCRAP

Escoger la base datos

# file.choose()
scrap <- read.csv("C:\\Users\\sofia\\OneDrive\\Documentos\\RETO\\FORM - Scrap.csv")

Entendemos la base de datos

resumen <- summary(scrap)
resumen
##   Referencia           Fecha             Producto            Cantidad     
##  Length:250         Length:250         Length:250         Min.   : 0.000  
##  Class :character   Class :character   Class :character   1st Qu.: 1.000  
##  Mode  :character   Mode  :character   Mode  :character   Median : 2.000  
##                                                           Mean   : 6.696  
##                                                           3rd Qu.: 7.000  
##                                                           Max.   :96.000  
##  Unidad.de.medida   Ubicación.de.origen Ubicación.de.desecho    Estado         
##  Length:250         Length:250          Length:250           Length:250        
##  Class :character   Class :character    Class :character     Class :character  
##  Mode  :character   Mode  :character    Mode  :character     Mode  :character  
##                                                                                
##                                                                                
## 

SECCION 1. Limpieza, Transformación, y Organización de Bases de Datos

Técnica 1. Remover valores irrelevantes

Eliminar columnas

La base de datos contenía Referencia de Form, sin embargo, para nuestro análisis que estamos realizando no es importante por lo que utilizamos la función de subset para eliminar la columna.

scrap1 <- scrap
scrap1<-subset(scrap1,select=-c(Referencia))
str(scrap1)
## 'data.frame':    250 obs. of  7 variables:
##  $ Fecha               : chr  "31/08/2022 14:55" "31/08/2022 14:49" "31/08/2022 13:49" "31/08/2022 09:30" ...
##  $ Producto            : chr  "[BACKFRAME 60% CUELLO ARMADO] 18805. 60% Backframe. Cuello Armado." "[N61506747 CAJA] N61506747. Kit. Caja." "[N61506729 SEPARADOR] N61506729. Kit. Separador." "[341332 DIVISOR - U611 & U625] 341332. U611. U625. Divisor Troquelado." ...
##  $ Cantidad            : num  2 1 1 31 1 1 1 9 2 1 ...
##  $ Unidad.de.medida    : chr  "Unidad(es)" "Unidad(es)" "Unidad(es)" "Unidad(es)" ...
##  $ Ubicación.de.origen : chr  "SAB/Calidad/Entrega de PT" "SAB/Calidad/Entrega de PT" "SAB/Calidad/Entrega de PT" "SAB/Pre-Production" ...
##  $ Ubicación.de.desecho: chr  "Virtual Locations/Scrapped" "Virtual Locations/Scrapped" "Virtual Locations/Scrapped" "Virtual Locations/Scrapped" ...
##  $ Estado              : chr  "Hecho" "Hecho" "Hecho" "Hecho" ...

Técnica 2. Errores tipográficos y errores similares

Cantidades en enteros

Es importante para nuestro análisis que la base de datos las cantidades estuvieran enteros ya que se tratan de cantidad de piezas de cierto producto por lo que para que el análisis sea congruente se deben tener enteros.

scrap2 <- scrap1
scrap2$Cantidad <- ceiling (scrap2$Cantidad)  
summary(scrap2)   
##     Fecha             Producto            Cantidad    Unidad.de.medida  
##  Length:250         Length:250         Min.   : 0.0   Length:250        
##  Class :character   Class :character   1st Qu.: 1.0   Class :character  
##  Mode  :character   Mode  :character   Median : 2.0   Mode  :character  
##                                        Mean   : 6.7                     
##                                        3rd Qu.: 7.0                     
##                                        Max.   :96.0                     
##  Ubicación.de.origen Ubicación.de.desecho    Estado         
##  Length:250          Length:250           Length:250        
##  Class :character    Class :character     Class :character  
##  Mode  :character    Mode  :character     Mode  :character  
##                                                             
##                                                             
## 

1.¿Cuántas variables y cuántos registros tiene la base de datos?

R= 251 registros y 7 variables
# install.packages("psych")
str(scrap2)
## 'data.frame':    250 obs. of  7 variables:
##  $ Fecha               : chr  "31/08/2022 14:55" "31/08/2022 14:49" "31/08/2022 13:49" "31/08/2022 09:30" ...
##  $ Producto            : chr  "[BACKFRAME 60% CUELLO ARMADO] 18805. 60% Backframe. Cuello Armado." "[N61506747 CAJA] N61506747. Kit. Caja." "[N61506729 SEPARADOR] N61506729. Kit. Separador." "[341332 DIVISOR - U611 & U625] 341332. U611. U625. Divisor Troquelado." ...
##  $ Cantidad            : num  2 1 1 31 1 1 1 9 2 1 ...
##  $ Unidad.de.medida    : chr  "Unidad(es)" "Unidad(es)" "Unidad(es)" "Unidad(es)" ...
##  $ Ubicación.de.origen : chr  "SAB/Calidad/Entrega de PT" "SAB/Calidad/Entrega de PT" "SAB/Calidad/Entrega de PT" "SAB/Pre-Production" ...
##  $ Ubicación.de.desecho: chr  "Virtual Locations/Scrapped" "Virtual Locations/Scrapped" "Virtual Locations/Scrapped" "Virtual Locations/Scrapped" ...
##  $ Estado              : chr  "Hecho" "Hecho" "Hecho" "Hecho" ...
library(psych)
describe(scrap2)
##                       vars   n   mean    sd median trimmed   mad min max range
## Fecha*                   1 250 101.26 59.55    102  100.72 77.10   1 206   205
## Producto*                2 250  44.38 24.72     45   44.12 25.95   1  95    94
## Cantidad                 3 250   6.70 11.85      2    3.89  1.48   0  96    96
## Unidad.de.medida*        4 250   1.00  0.00      1    1.00  0.00   1   1     0
## Ubicación.de.origen*     5 250   2.48  0.85      3    2.60  0.00   1   3     2
## Ubicación.de.desecho*    6 250   1.00  0.00      1    1.00  0.00   1   1     0
## Estado*                  7 250   1.00  0.00      1    1.00  0.00   1   1     0
##                        skew kurtosis   se
## Fecha*                 0.04    -1.21 3.77
## Producto*              0.01    -0.79 1.56
## Cantidad               4.12    21.14 0.75
## Unidad.de.medida*       NaN      NaN 0.00
## Ubicación.de.origen*  -1.10    -0.70 0.05
## Ubicación.de.desecho*   NaN      NaN 0.00
## Estado*                 NaN      NaN 0.00

3.¿Clasifica cada variable en cualitativa, cuantitativa discreta o cuantitativa continua.?

Variable<-c("Fecha","Producto","Cantidad","Unidad.de.medida", "Ubicación.de.origen","Ubicación.de.desecho","Estado")
Type<-c("Cuantitativa continua", "Cualitativa", "Cuantitativa continua", "Cualitativa", "Cualitativa","Cualitativa","Cualitativa")
table<-data.frame(Variable,Type)
knitr::kable(table)
Variable Type
Fecha Cuantitativa continua
Producto Cualitativa
Cantidad Cuantitativa continua
Unidad.de.medida Cualitativa
Ubicación.de.origen Cualitativa
Ubicación.de.desecho Cualitativa
Estado Cualitativa

4. Elige la escala de medición de cada variable.

Variable<-c("Fecha","Producto","Cantidad","Unidad.de.medida", "Ubicación.de.origen","Ubicación.de.desecho","Estado")
Type<-c("Cuantitativa continua", "Cualitativa", "Cuantitativa continua", "Cualitativa", "Cualitativa","Cualitativa","Cualitativa")
Escala_de_Medición <- c("Intervalo","Nominal","Discreta","Nominal", "Nominal","Nominal", "Nominal")
table<-data.frame(Variable,Type,Escala_de_Medición)
knitr::kable(table)
Variable Type Escala_de_Medición
Fecha Cuantitativa continua Intervalo
Producto Cualitativa Nominal
Cantidad Cuantitativa continua Discreta
Unidad.de.medida Cualitativa Nominal
Ubicación.de.origen Cualitativa Nominal
Ubicación.de.desecho Cualitativa Nominal
Estado Cualitativa Nominal

Análisis Exploratorio de las Bases de Datos

Tabla con los principales estadísticos descriptivos

Estadísticos descriptivos Scrap

# install.packages("psych")
library(psych)
describe(scrap2)
##                       vars   n   mean    sd median trimmed   mad min max range
## Fecha*                   1 250 101.26 59.55    102  100.72 77.10   1 206   205
## Producto*                2 250  44.38 24.72     45   44.12 25.95   1  95    94
## Cantidad                 3 250   6.70 11.85      2    3.89  1.48   0  96    96
## Unidad.de.medida*        4 250   1.00  0.00      1    1.00  0.00   1   1     0
## Ubicación.de.origen*     5 250   2.48  0.85      3    2.60  0.00   1   3     2
## Ubicación.de.desecho*    6 250   1.00  0.00      1    1.00  0.00   1   1     0
## Estado*                  7 250   1.00  0.00      1    1.00  0.00   1   1     0
##                        skew kurtosis   se
## Fecha*                 0.04    -1.21 3.77
## Producto*              0.01    -0.79 1.56
## Cantidad               4.12    21.14 0.75
## Unidad.de.medida*       NaN      NaN 0.00
## Ubicación.de.origen*  -1.10    -0.70 0.05
## Ubicación.de.desecho*   NaN      NaN 0.00
## Estado*                 NaN      NaN 0.00
Variables <-c("Cantidad" )
Media <-c("6.70" )
Mediana <-c("2" )
Desviacion_estandar <-c("11.85" )

table1 <-data.frame(Variables, Media , Mediana , Desviacion_estandar)
knitr::kable(table1)
Variables Media Mediana Desviacion_estandar
Cantidad 6.70 2 11.85

SECCION 2. Análisis Exploratorio de las Bases de Datos

Bar plots

PRODUCCIÓN

barplot(prop.table(table(prod4$LAMINAS_PROCESADAS)),col=c("orange"),main="Laminas procesadas",xlab = "Laminas", ylab ="Frecuencias",las=1)

SCRAP

library(plyr)
pie(prop.table(table(scrap2$Ubicación.de.origen)),col=c("lightgreen","blue","red"),main="Ubicación de origen",las=1)

DELIVERY PLAN: PRINCIPALES CLIENTES: PRINCIPALES CLIENTES

Con la siguiente función podremos identificar los principales clientes para generar un análisis con la información relevante, pues hay clientes con pocos o sin pedidos por lo que generar un diagnóstico respecto a delivery plan con esos datos no es necesario.

ggplot(devplan1, aes(x=reorder(CLIENTE,Pedidos), y=Pedidos)) +
  geom_bar(stat="identity")+
  coord_flip()

RECURSOS HUMANOS: COLABORADORES ACTUALES

# as.data.frame(bajas)
# as.data.frame(colab)
colab<-colab %>% dplyr::select(genero,edad,salario_diario) %>%  dplyr::group_by(genero) %>%
  dplyr::summarise(across(everything(),mean,na.rm=TRUE)) %>% arrange(desc(edad))
ggplot(colab, aes(x=reorder(genero,edad), y=edad, fill=(salario_diario))) +
  geom_bar(stat="identity",col=c("black"))+
  coord_flip()+
  guides(fill=guide_legend(reverse=FALSE))

La primera gráfica de barras nos da a conocer sobre el salario diario de las personas de Form, segmentado por edad y por género. Lo que nos da a conocer es que en la empresa existe un mayor rango de edad entre las mujeres de Form, llegando a ser casi 40 lo mayor; por otra parte, los hombres presentan un menor rango, con un máximo de (aprox) 33. Igualmente, vemos que en promedio las mujeres ganan 60 centavos más que los hombres.

RECURSOS HUMANOS: BAJAS

bajas<-bajas %>% dplyr::select(motivo_baja,edad,duracion) %>% group_by(motivo_baja) %>%
  dplyr::summarise(across(everything(),mean,na.rm=TRUE)) %>% arrange(desc(edad))
ggplot(bajas, aes(x=reorder(motivo_baja,edad), y=edad, fill=(duracion))) +
  geom_bar(stat="identity",col=c("black"))+
  coord_flip()+
  guides(fill=guide_legend(reverse=FALSE))

Viendo ahora los colaboradores que han sido dados de baja en la empresa, vemos que la gran parte de los que se han salido de Form tienen menos de 30 años. Pocos casos han sido de jubilación, llegando a más de 60 en rango. Igualmente, a partir de la gráfica vemos que las razones principales son por abandono y baja por faltas; durando menos de 500 días en su trabajo.

Dispersion plots

PRODUCCIÓN

plot(prod4$TMO_MIN, xlab = "Proceso de lamina", ylab = "Tiempo", main = "Tiempo por Lamina" )

MERMA

ggplot(merma2, aes(x= Fecha, y= Kilos)) + geom_bar(stat="identity", fill="red") + scale_fill_grey() + labs(title = "Kilos de merma", x = "Fecha")

Podemos ver como en inicios de Febrero a Abril tenemos la mayor cantidad de kilos de merma, que incluso pasa del promedio de los demas meses, por lo que es importante analizar que factor hizo que durante ese periodo hubiera más merma.

merma2$Fecha <- as.Date(merma2$Fecha, format = "%d/%m/%Y")
plot(merma2$Fecha, merma2$Kilos, main = "Kilos de merma",
     xlab = "Fecha", ylab = "Kilos",
     pch = 19, frame = FALSE)

Como podemos observar hay mas dispersión en septiembre, los demás meses ha tenido en promedio la misma cantidad de merma.

SCRAP

hist(scrap2$Cantidad, main = "Cantidad de Material reciclado", xlab = "Cantidad", ylab = "Frecuencia",col = "blue")

Con este histograma nos muestra que entre 0 a 10 Toneladas es lo que mas se frecuenta a reciclar el material.

DELIVERY PLAN

Pedidos

plot(devplan1$Fecha, devplan1$Pedidos, main = "Pedidos por fecha",
     xlab = "Fecha", ylab = "Pedidos",
     pch = 1, frame = FALSE)

boxplot(devplan1$Pedidos, main = "Pedidos")

Como primer boxplot vimos los pedidos y la gran dispersión que hay entre pedidos, pues detectamos una frecuencia en donde hay clientes que generan pedidos obviamente diferentes como para tener una mediana o una dispersión positiva.

Clientes

devplan2 <- devplan1
devplan2$CLIENTE<-as.factor(devplan2$CLIENTE)
ggplot(devplan2, aes(x=CLIENTE, y=Pedidos)) + 
  geom_boxplot(color="red", fill="orange", alpha=0.2)

En el gráfico anterior podemos observar a los 6 clientes con mayor presencia en FORM en cuanto a Delivery Plan en donde el objetivo es ver la dispersión y la distribución entre cada uno y respecto a los pronósticos individuales.

Time series plots

DISTRIBUCIÓN

ggplot(devper2,aes(x=fecha, y=delay_performance,color=cliente))+
  geom_line()+
  labs(x="Fecha",y="Retraso en Minutos", color="Legend")+
  ggtitle("Retrasos en el desempeño por parte del cliente")

devper2 <- devper2[devper2$cliente!="Magna",]
devper2 <- devper2[devper2$cliente!="Varroc",]

ggplot(devper2,aes(x=fecha, y=delay_performance,fill=cliente))+
  geom_bar(stat="identity")+
  geom_hline(yintercept=33,linetype="dashed",color="black")+
  labs(x="Fecha",y="Retraso en minutos", color="Legend")+
  ggtitle("Retrasos en el desempeño por parte del cliente")

A pesar de que esta diminutendo el retraso con el cliente Mahle seguimos viendo que se encuentra por arriba del promedio.

Hallazgos

  1. Nuestro top 3 clientes de producción son STABILUS 1, STABILUS 3 y TRMX.

  2. Traemos un retraso mayor en distribución con el cliente Mahle, arriba del promedio llegando incluso a tiempos de 1 hora con 40 minutos.

  3. Se tienen sobrepedidos (arriba del promedio) y esto puede afectar si no se tienen la capacidad para recibir pedidos de más.

  4. Dentro de RH tenemos más bajas por distintos motivos: en primer lugar esta por Jubilación, en segundo lugar Renuncia voluntaria y en tercer lugar Baja por Faltas.

Predicción del Desempeño de la Industria Automotriz

Escoger la base datos

# file.choose()
bdex <- read.csv("C:\\Users\\sofia\\Downloads\\us_motor_production_and_domestic_sales1.csv")

Entendemos la base de datos

resumen1 <- summary(bdex)
resumen1
##       Year      Total_Production Production_Passenger_Cars
##  Min.   :2007   Min.   : 5710    Min.   :1924             
##  1st Qu.:2010   1st Qu.: 8709    1st Qu.:2745             
##  Median :2014   Median :10823    Median :3382             
##  Mean   :2014   Mean   :10077    Mean   :3326             
##  3rd Qu.:2017   3rd Qu.:11268    3rd Qu.:4061             
##  Max.   :2020   Max.   :12179    Max.   :4369             
##  Production_Commercial_Vehicles Domestic_Sales  Sales_Passenger_Cars
##  Min.   :3514                   Min.   : 7868   Min.   :2560        
##  1st Qu.:5820                   1st Qu.:10474   1st Qu.:3865        
##  Median :6891                   Median :12583   Median :4542        
##  Mean   :6751                   Mean   :11996   Mean   :4491        
##  3rd Qu.:8095                   3rd Qu.:13669   3rd Qu.:5184        
##  Max.   :8512                   Max.   :14128   Max.   :5610        
##  Sales_Commercial_Vehicles US_Unemployment US_Consumer_Confidence
##  Min.   : 4309             Min.   :3.680   Min.   :63.75         
##  1st Qu.: 6088             1st Qu.:4.685   1st Qu.:73.02         
##  Median : 7634             Median :5.980   Median :82.83         
##  Mean   : 7505             Mean   :6.430   Mean   :82.29         
##  3rd Qu.: 8964             3rd Qu.:8.088   3rd Qu.:92.67         
##  Max.   :10133             Max.   :9.610   Max.   :98.37         
##  US_Min_Hour_Wage
##  Min.   :5.500   
##  1st Qu.:7.250   
##  Median :7.250   
##  Mean   :7.025   
##  3rd Qu.:7.250   
##  Max.   :7.250

Se cambian los nombres de las columnas.

names (bdex) = c("año", "prod_total", "prod_passenger", "prod_veh_comerciales", "ventas_domesticas", "ventas_passenger","ventas_comerciales","desempleo_usa","confianza_cons_usa","salario_hora_min_usa")
names (bdex)
##  [1] "año"                  "prod_total"           "prod_passenger"      
##  [4] "prod_veh_comerciales" "ventas_domesticas"    "ventas_passenger"    
##  [7] "ventas_comerciales"   "desempleo_usa"        "confianza_cons_usa"  
## [10] "salario_hora_min_usa"
str(bdex)
## 'data.frame':    14 obs. of  10 variables:
##  $ año                 : int  2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 ...
##  $ prod_total          : num  10752 8672 5710 7744 8662 ...
##  $ prod_passenger      : num  3867 3731 2196 2732 2978 ...
##  $ prod_veh_comerciales: num  6885 4941 3514 5012 5685 ...
##  $ ventas_domesticas   : num  12687 10108 7868 9020 10109 ...
##  $ ventas_passenger    : num  5197 4491 3558 3792 4146 ...
##  $ ventas_comerciales  : num  7490 5617 4309 5229 5963 ...
##  $ desempleo_usa       : num  4.62 5.8 9.28 9.61 8.93 8.08 7.36 6.16 5.28 4.88 ...
##  $ confianza_cons_usa  : num  85.6 63.8 66.3 71.8 67.3 ...
##  $ salario_hora_min_usa: num  5.5 6.2 6.9 7.25 7.25 7.25 7.25 7.25 7.25 7.25 ...

Primer modelo de regresión

En este caso, se escoge como variable dependiente las ventas de los carros passenger, por ello entiéndase los automóviles de uso cotidiano en Estados Unidos. Para esta variable dependiente, se han tomado las siguientes variables independientes, con el fin de notar su efecto en las ventas. Estas son:

  1. Desempleo USA: este índice es calculado anualmente con la formula. (Unemployed ÷ Labor Force) x 100. Entre menor mejor.

  2. Confianza del consumidor de USA: índice que mide, a partir de una encuesta que tan optimistas o pesimistas se encuentran los consumidores sobre su situación financiera. Entre mayor, mejor.

  3. Salario mínimo por hora: se mide en dólares. Está establecido a nivel federal.

  4. Año: los años que se tienen de los datos, 2007-2020.

regresion1 <- lm (ventas_passenger ~ desempleo_usa + confianza_cons_usa + salario_hora_min_usa + año, data=bdex)
summary (regresion1)
## 
## Call:
## lm(formula = ventas_passenger ~ desempleo_usa + confianza_cons_usa + 
##     salario_hora_min_usa + año, data = bdex)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -850.29 -560.86   88.28  446.55  847.47 
## 
## Coefficients:
##                       Estimate Std. Error t value Pr(>|t|)   
## (Intercept)          646180.04  197959.50   3.264  0.00977 **
## desempleo_usa          -255.04     217.62  -1.172  0.27129   
## confianza_cons_usa       46.68      41.57   1.123  0.29062   
## salario_hora_min_usa   1394.06     697.08   2.000  0.07657 . 
## año                    -324.65     100.49  -3.231  0.01031 * 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 712.5 on 9 degrees of freedom
## Multiple R-squared:  0.5831, Adjusted R-squared:  0.3978 
## F-statistic: 3.147 on 4 and 9 DF,  p-value: 0.0707

Para la tasa de desempleo y el índice de confianza del consumidor, se ha decidido tomar el promedio del 2007 al 2020, para poder predecir. Con el salario mínimo por hora, al ser establecido a nivel federal, se toma en cuenta la última cantidad: $7.25 dólares. Se quieren las predicciones para los siguientes cinco años, a partir del último año con datos (2020).

datos_nuevos1 <- data.frame(desempleo_usa=6.43,confianza_cons_usa=82.3,salario_hora_min_usa=7.25,año=2021:2025)
predict(regresion1,datos_nuevos1)
##        1        2        3        4        5 
## 2369.905 2045.254 1720.604 1395.954 1071.303

¿Qué observamos?

primer <- plot(predict(regresion1,datos_nuevos1), type = "l", xlab = "Año",  ylab ="Ventas Passenger",  main="Predicción de Ventas")

En esta predicción de ventas de automóviles passenger, observamos que es hacia abajo. Es decir, tomando en cuenta una tasa de desempleo de 6.43, un índice de confianza de 82.3 y el salario mínimo por hora de $7.25, se espera que las ventas de estos automóviles bajen en EUA del 2021 hasta 2025. Igualmente, resulta destacable mencionar que las variables que más impactan en las ventas de automóviles passenger son el año y el salario mínimo.

effect_plot(regresion1,pred=desempleo_usa,interval=TRUE)

Si tomamos en cuenta la tasa de desempleo de EUA, y su relación con las ventas de los automóviles passenger, observamos que esta es negativa. Debido a que al crecer la tasa de desempleo, bajan las ventas.

effect_plot(regresion1,pred=confianza_cons_usa,interval=TRUE)

> Mientras que el índice de confianza del consumidor de EUA, y su relación con las ventas de los automóviles passenger, observamos que esta es positiva. Debido a que al crecer la confianza, incrementan las ventas.

effect_plot(regresion1,pred=salario_hora_min_usa,interval=TRUE)

Igualmente, al subir el salario mínimo por hora, las ventas de los automóviles passenger incrementan.

effect_plot(regresion1,pred=año,interval=TRUE)

Con el pasar de los años las ventas han decrecido.

Segundo modelo de regresión

En este caso, se escoge como variable dependiente las ventas de los carros comerciales, por ello entiéndase los cualquier tipo de vehículo de motor utilizado para transportar mercancías o pasajeros en Estados Unidos. Para esta variable dependiente, se han tomado las siguientes variables independientes, con el fin de notar su efecto en las ventas. Estas son:
1. Desempleo USA: este índice es calculado anualmente con la formula. (Unemployed ÷ Labor Force) x 100. Entre menor mejor.
2. Confianza del consumidor de USA: índice que mide, a partir de una encuesta que tan optimistas o pesimistas se encuentran los consumidores sobre su situación financiera. Entre mayor, mejor.
3. Salario mínimo por hora: se mide en dólares. Está establecido a nivel federal.
4. Año: los años que se tienen de los datos, 2007-2020.

regresion2 <- lm (ventas_comerciales ~ desempleo_usa + confianza_cons_usa + salario_hora_min_usa + año, data=bdex)
summary (regresion2)
## 
## Call:
## lm(formula = ventas_comerciales ~ desempleo_usa + confianza_cons_usa + 
##     salario_hora_min_usa + año, data = bdex)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -731.58  -87.12   57.56  160.03  513.82 
## 
## Coefficients:
##                        Estimate Std. Error t value Pr(>|t|)    
## (Intercept)          -588817.41   97672.75  -6.028 0.000196 ***
## desempleo_usa           -147.24     107.37  -1.371 0.203504    
## confianza_cons_usa        50.55      20.51   2.464 0.035896 *  
## salario_hora_min_usa    -839.15     343.94  -2.440 0.037374 *  
## año                      297.49      49.58   6.000 0.000203 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 351.6 on 9 degrees of freedom
## Multiple R-squared:  0.9732, Adjusted R-squared:  0.9613 
## F-statistic: 81.82 on 4 and 9 DF,  p-value: 4.516e-07

Para la tasa de desempleo y el índice de confianza del consumidor, se ha decidido tomar el promedio del 2007 al 2020, para poder predecir. Con el salario mínimo por hora, al ser establecido a nivel federal, se toma en cuenta la última cantidad: $7.25 dólares. Se quieren las predicciones para los siguientes cinco años, a partir del último año con datos (2020).

datos_nuevos2 <- data.frame(desempleo_usa=6.43,confianza_cons_usa=82.3,salario_hora_min_usa=7.25,año=2021:2025)
predict(regresion2,datos_nuevos2)
##         1         2         3         4         5 
##  9547.780  9845.274 10142.768 10440.262 10737.756

¿Qué observamos?

segundo <- plot(predict(regresion2,datos_nuevos2), type = "l", xlab = "Año",  ylab ="Ventas Comerciales",  main="Predicción de Ventas")

En esta predicción de ventas de automóviles comerciales, observamos que es hacia arriba Es decir, tomando en cuenta una tasa de desempleo de 6.43, un índice de confianza de 82.3 y el salario mínimo por hora de $7.25, se espera que las ventas de estos automóviles suban en EUA del 2021 hasta 2025. En el caso de las ventas de automóviles comerciales, notamos que el pasar de los años es la variable que más impacta, siguiendo por el nivel de confianza del consumidor y el salario mínimo por hora; mientras que el que menos afecta es la tasa de desempleo.

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

Si tomamos en cuenta la tasa de desempleo de EUA, y su relación con las ventas de los automóviles comerciales, observamos que esta es negativa. Debido a que al crecer la tasa de desempleo, bajan las ventas.

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

Mientras que el índice de confianza del consumidor de EUA, y su relación con las ventas de los automóviles comerciales, observamos que esta es positiva. Debido a que al crecer la confianza, incrementan las ventas. A comparación de la gráfica de ventas passenger con el nivel de confianza, observamos que en este caso la pendiente es más pronunciada, por lo que vemos un mayor impacto.

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

Igualmente, al subir el salario mínimo por hora, las ventas de los automóviles comerciales disminuyen. Este podría ser un tema interesante a investigar.

effect_plot(regresion2,pred=año,interval=TRUE)

Con el pasar de los años las ventas han incrementado.

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

Pronóstico Producción FORM

plot(prod4$FECHA,prod4$PZA_PROG, type="l",col="blue", lwd=1.5, xlab ="Fecha",ylab ="Piezas programadas", main = "Piezas programadas por fecha")
lines(prod4$FECHA,prod4$LAMINAS_PROCESADAS,col="red",lty=3)
legend("topleft", legend=c("Piezas programadas", "Laminas procesadas"),
       col=c("blue", "red"), lty = 1:2, cex=0.8)

(ma_model<-arma(prod4$PZA_PROG,order=c(0,1)))
## 
## Call:
## arma(x = prod4$PZA_PROG, order = c(0, 1))
## 
## Coefficient(s):
##       ma1  intercept  
##    0.1806    27.4574
ma_model_forecast<-forecast(ma_model$fitted,h=3,level=c(95))
ma_model_forecast
##      Point Forecast    Lo 95    Hi 95
## 2679       27.57363 21.20879 33.93847
## 2680       27.57363 21.20877 33.93848
## 2681       27.57363 21.20876 33.93849

Pronóstico Merma FORM

# Sumar el Total de KilosxMes
merma3 <- c(14560,22830,22470,18820,23410,18280,19370,32100,13586)

merma_st <- ts(data = merma3, start = c(2022,1), frequency = 12)
merma_st
##        Jan   Feb   Mar   Apr   May   Jun   Jul   Aug   Sep
## 2022 14560 22830 22470 18820 23410 18280 19370 32100 13586
modelo <- auto.arima(merma_st)
modelo
## Series: merma_st 
## ARIMA(0,0,0) with non-zero mean 
## 
## Coefficients:
##            mean
##       20602.889
## s.e.   1736.893
## 
## sigma^2 = 30544665:  log likelihood = -89.8
## AIC=183.59   AICc=185.59   BIC=183.99
pronostico <- forecast(modelo, level=c(95), h=3)
pronostico
##          Point Forecast    Lo 95    Hi 95
## Oct 2022       20602.89 9770.711 31435.07
## Nov 2022       20602.89 9770.711 31435.07
## Dec 2022       20602.89 9770.711 31435.07
plot(pronostico)

Resultados: ¿Cuál es la tendencia?

Podemos ver que en la industria Automotriz de USA, específicamente en ventas de motores, tenemos una tendencia continua y que nuestros intervalos de confianza ban disminuyendo, pero las predicciones se encuentran entre 8315.732-12595.61 de ventas anuales de motores en USA para los próximos años.

Para Form al desarrollar el pronóstico de Merma vemos que tenemos que para los próximos periodos de octubre, noviembre y diciembre tendremos una cantidad constante de 20602.89 kilos de merma y que nuestro intervalo de confianza cae entre 9770.711 a 31435.07.Interpretando la información vemos que a comparación del último mes de septiembre, los kilos crecerán.

Sección 3. K-means Clustering

library(foreign)
library(dplyr)        # data manipulation 
library(ggplot2)      # data visualization 
# install.packages("psych")
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
# install.packages("ggfortify")
library(ggfortify)    # data visualization tools for statistical analysis results
# file.choose
bd <- read.csv("C:\\Users\\sofia\\Downloads\\bajas_final (2).csv")
sapply(bd,function(x) sum(is.na(x)))
##         nombre           edad         genero           alta    motivo_baja 
##              0              0              0              0              0 
##       duracion         puesto salario_diario         estado       e.civil. 
##              0              0              0              0              0

1. Edad y duración - 4 Clusters

bajas1 <-bd
bajas1 <-subset(bajas1,select = -c(genero,alta,motivo_baja,puesto,estado,nombre))
summary(bajas1)
##       edad          duracion       salario_diario    e.civil.        
##  Min.   :18.00   Min.   :   0.00   Min.   :144.4   Length:233        
##  1st Qu.:23.00   1st Qu.:   9.00   1st Qu.:180.7   Class :character  
##  Median :29.00   Median :  20.50   Median :180.7   Mode  :character  
##  Mean   :30.77   Mean   :  75.59   Mean   :177.9                     
##  3rd Qu.:37.00   3rd Qu.:  47.00   3rd Qu.:180.7                     
##  Max.   :61.00   Max.   :1966.00   Max.   :500.0
bajas_edaddur_norm<-scale(bajas1[1:2])
fviz_nbclust(bajas_edaddur_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=4, linetype=2)+         
  labs(subtitle = "Elbow method")  
## Registered S3 methods overwritten by 'broom':
##   method            from  
##   tidy.glht         jtools
##   tidy.summary.glht jtools

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

Al observar vemos cuatro clusters que toman en cuenta la edad y la duración:
1. El rojo (será llamado “Senior”) es un cluster que observamos que son personas de edad mediana-alta y que durán relativamente poco tiempo, entran dentro del 25% con menor duración.
2. El verde (“Expert”) es el cluster que más se aparta de los demás; son personas con un mayor rango de edad pero que se alejan de los más jóvenes, y que han durado mucho má tiempo. Se encuentran en el 50% superior del tiempo de duración.
3. El azul (“junior”) resulta el cluster intermedio de los de menor duración. Son personas en un rango de edad medio que también son parte del 25% inferior que más han durado.
4. El morado (“beginner”) es el segmento más joven y que de las personas (en general) menos han durado. Se puede considerar que los jóvenes son los que menos duran en Form a partir de este cluster.

bajas_new2<-bajas1
bajas_new2$Clusters<-edad_cluster1$cluster
bajas_new3<-bajas_new2 %>% group_by(Clusters) %>% summarise(edad=max(edad)) %>% arrange(desc(edad))
bajas_new2$Cluster_Names<-factor(bajas_new2$Clusters,levels = c(1,2,3,4), 
                                 labels=c("Senior", "Expert", "Junior", "Beginner"))

2. Edad y duración - 5 Clusters

Debido a quee una gráfica anterior indicaba la posibilidad de tener otro clúster que describa a otro grupo, hacemos lo mismo con 5 segmentos, en vez de 4.

bajas_edaddur_norm2<-scale(bajas1[1:2])
fviz_nbclust(bajas_edaddur_norm2, kmeans, method="wss")+ 
  geom_vline(xintercept=5, linetype=2)+         
  labs(subtitle = "Elbow method")  

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

Comparando esta gráfica de 5 segmentos contra la anteriormente vista de 4. En esta observamos que separa un segmento que deja un “espacio” que antes no existía; separa y crea un segmento que han durado aprox un 10% más de tieempo que las tres menores, y que se encuentra en rangos de edad parecidos. A continuación se comparan los clusters:
1. El rojo (llamado “Senior”): es el nuevo, el cual tiene de baja a mediana duración y un rango de edad mediana. Después de los que han durado mucho, ellos van después.

  1. El verde superior (llamado “Expert”): es el cluster que más se aparta de los demás; son personas con un mayor rango de edad pero que se alejan de los más jóvenes, y que han durado mucho má tiempo. Se encuentran en el 50% superior del tiempo de duración.

  2. El verde inferior (llamado “Junior”) son personas adultas que han durado poco tiempo en la empresa, parte del 17% inferior de duración.

  3. El morado (llamado “Middle”): al hacer el nuevo clúster nos damos cuenta de que existe un grupo de personas de mediana edad que duran muy poco, aún más poco que los jóvenes. Investigar estado civil.

  4. El azul (llamado “Beginner”): son las personas más jóvenes y que también han durado poco tiempo. Se quedan aproximadamente por el 10% inferior.

bajas_new6<-bajas1
bajas_new6$Clusters<-edad_cluster2$cluster
bajas_new7<-bajas_new6 %>% group_by(Clusters) %>% summarise(edad=max(edad)) %>% arrange(desc(edad))
bajas_new6$Cluster_Names<-factor(bajas_new6$Clusters,levels = c(1,2,3,4,5), 
                                 labels=c("Senior", "Expert", "Junior", "Middle","Beginner"))

Al analizar el estado civil de los 5 clústers, llegamos a las siguientes conclusiones:
1. Del segmento “Senior”, el 75% son solteros. Este es el nuevo clúster descubierto.
2. El 55% de las personas en el cluster “Middle” (menor duración) son solteras, el 26% viven en unión libre, y un 19% que viven en matrimonio.
3. De los expertos, el 75% son solteros.

3. Duración y salario

Importar base de datos

bajas2 <-read.csv("C:\\Users\\sofia\\Downloads\\bajas_final (2).csv") 
sapply(bajas2,function(x) sum(is.na(x)))
##         nombre           edad         genero           alta    motivo_baja 
##              0              0              0              0              0 
##       duracion         puesto salario_diario         estado       e.civil. 
##              0              0              0              0              0
rh_bajas2<-bajas2
rh_bajas2<-subset(rh_bajas2,select = -c(genero,alta,motivo_baja,puesto,estado,nombre))
summary(rh_bajas2)
##       edad          duracion       salario_diario    e.civil.        
##  Min.   :18.00   Min.   :   0.00   Min.   :144.4   Length:233        
##  1st Qu.:23.00   1st Qu.:   9.00   1st Qu.:180.7   Class :character  
##  Median :29.00   Median :  20.50   Median :180.7   Mode  :character  
##  Mean   :30.77   Mean   :  75.59   Mean   :177.9                     
##  3rd Qu.:37.00   3rd Qu.:  47.00   3rd Qu.:180.7                     
##  Max.   :61.00   Max.   :1966.00   Max.   :500.0
bajas_duracion_norm<-scale(rh_bajas2[2:3]) 
fviz_nbclust(bajas_duracion_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=5, linetype=2)+         
  labs(subtitle = "Elbow method") 

duracion_cluster1<-kmeans(bajas_duracion_norm,5)
duracion_cluster1
## K-means clustering with 5 clusters of sizes 191, 10, 4, 27, 1
## 
## Cluster means:
##      duracion salario_diario
## 1 -0.23462767      0.1147221
## 2  1.49983327     -0.3729089
## 3  6.65505218     -0.3962566
## 4  0.02340506     -1.1243505
## 5  2.56340604     13.7596523
## 
## Clustering vector:
##   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20 
##   5   4   4   4   4   4   4   4   4   2   4   4   1   1   2   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   3   4   4   1   1   1   1   1   1   1   1   1   1   1   1   4   2   1   1 
##  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60 
##   2   2   1   1   1   1   1   1   1   1   1   3   2   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   2   2   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 
##   3   4   4   4   4   1   1   1   1   1   1   1   1   1   1   1   4   4   1   1 
## 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 
##   1   1   1   1   1   1   1   3   1   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   1   1   1   1   1   1   1   1   1   2   1   1   1   1   1   1   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   1   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   1   1   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 
##   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1 
## 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 
##   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   2   1   1 
## 221 222 223 224 225 226 227 228 229 230 231 232 233 
##   1   1   1   1   1   1   1   1   1   1   1   1   1 
## 
## Within cluster sum of squares by cluster:
## [1] 3.281687 6.437305 7.884909 1.648877 0.000000
##  (between_SS / total_SS =  95.9 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"
fviz_cluster(duracion_cluster1,data=bajas_duracion_norm)

Al observar vemos 5 clusters que toman en cuenta la duración y el salario:

  1. Primero vemos nuestro cluster 1 (será llamado “Rehenes”) es un cluster que observamos que son personas que solo entran y salen muy pronto de la empresa (141 días) y tienen un salario diario que es arriba del promedio, alrededor de $180 pesos.

  2. El cluster 2 (“Duraderos”) son los colaboradores que tienen una duración regular, pero que aun así no se encuentran satisfechos por lo que se salen de la empresa al rededor después de 1 año y medio (646 días) y su salario es de $169.

  3. Como cluster 3 tenemos a los colaboradores que son leales a la empresa (“Fieles”) es el segmento donde ya tienen más de 4-5 años trabajando y cuentan con un salario de $168 pesos.

  4. El cluster 4 (“Costosos”) es el cluster que nos cuesta a la empresa porque se invierte en capacitaciones para ellos y terminan saliendo de la empresa; son personas con un poco mas de duración pero no la suficiente (197 días) y su salario es de $151 por debajo promedio.

  5. Por último tenemos el cluster 5 (“Extra”) que tuvo duración corto plazo con un salario muy alto ($500 pesos).

rh_bajas3<- bajas2
rh_bajas3$Clusters<-duracion_cluster1$cluster
rh_bajas4<-rh_bajas3 %>% group_by(Clusters) %>% summarise(duracion=max(duracion)) %>% arrange(desc(duracion))
rh_bajas3$Cluster_Names<-factor(rh_bajas3$Clusters,levels = c(1,2,3,4,5), 
                                labels=c("Rehenes", "Duraderos","Fieles", "Costosos","Extra"))
  • “Rehenes” tiene el segmento con más colaboradores y tiene un total de 191. En porcentaje se puede decir que es el 81.97% total de bajas.

  • “Costosos” esta en segundo lugar teniendo 27 colaboradores (11.57%).

  • “Duraderos” tercer lugar con un total de 10 colaboradores (4.29%).

  • “Fieles” cuarto lugar con 4 colaboradores (1.71%).

  • Por último esta el “Extra” que fue solo un colaborador que se encuentra fuera de lo normal (0.43%).

4. Edad y salario

#file.choose
bajas3 <-read.csv("C:\\Users\\sofia\\Downloads\\bajas_final (2).csv")
str(bajas3)
## 'data.frame':    233 obs. of  10 variables:
##  $ nombre        : chr  "MARIO VALDEZ ORTIZ" "ISABEL BARRIOS MENDEZ" "MARIA ELIZABETH GOMEZ HERNANDEZ" "ALONDRA ABIGAIL ESCARCIA GOMEZ" ...
##  $ edad          : int  32 36 23 21 29 46 29 31 50 19 ...
##  $ genero        : chr  "MASCULINO" "FEMENINO" "FEMENINO" "FEMENINO" ...
##  $ alta          : chr  "09/03/20" "09/11/21" "10/11/21" "10/11/21" ...
##  $ motivo_baja   : chr  "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" "RENUNCIA VOLUNTARIA" ...
##  $ duracion      : num  628 60 59 59 51 37 37 31 18 224 ...
##  $ puesto        : chr  "DISENO" "AYUDANTE GENERAL" "AYUDANTE GENERAL" "AYUDANTE GENERAL" ...
##  $ salario_diario: num  500 152 152 152 152 ...
##  $ estado        : chr  "Nuevo Leon" "Nuevo Leon" "Nuevo Leon" "Nuevo Leon" ...
##  $ e.civil.      : chr  "Soltero" "Union libre" "Matrimonio" "Soltero" ...
sapply(bajas3,function(x) sum(is.na(x)))
##         nombre           edad         genero           alta    motivo_baja 
##              0              0              0              0              0 
##       duracion         puesto salario_diario         estado       e.civil. 
##              0              0              0              0              0
bdr2 <- bajas3
bdr2<-subset(bdr2,select = -c(genero,alta,motivo_baja,puesto,estado,nombre,duracion))
summary(bdr2)
##       edad       salario_diario    e.civil.        
##  Min.   :18.00   Min.   :144.4   Length:233        
##  1st Qu.:23.00   1st Qu.:180.7   Class :character  
##  Median :29.00   Median :180.7   Mode  :character  
##  Mean   :30.77   Mean   :177.9                     
##  3rd Qu.:37.00   3rd Qu.:180.7                     
##  Max.   :61.00   Max.   :500.0
bdr3 <- scale(bdr2[1:2])
fviz_nbclust(bdr3, kmeans, method="wss")+ 
  geom_vline(xintercept=4, linetype=2)+         
  labs(subtitle = "Elbow method") 

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

Vemos que el número óptimo de klusters para las variables edad y salario diario son 4 según el método de Elbow.

Como dato disparado y posible warning vemos que hay un trabajador con un salario diario de 500 pesos lo que podría resultar como un error, sin embargo los otros 3 grupos varían bastante en edad más no en salario pues el rango es muy cercano.

  1. Alto El dato es único en el conteo con un trabajador de 32 años que tiene un salario diario de 500 pesos y es soltero. Su punto en el mapeo es único (color rojo).

  2. Verde Es el cluster con el registro de personas con mayor edad y cuentan con el salario diario más alto 183.68.

  3. Azul Es el cluster con el registro de personas con edad promedio y salario de 180.68.

  4. Morado Es el cluster con mayor registro de personas con edad jóven y salario de 182.68.

bdr5<-bdr2
bdr5$Cluster <- bdr4$cluster
bdr6<-bdr5 %>% group_by(Cluster) %>% summarize(salario_diario=max(salario_diario)) %>% arrange(desc(salario_diario))
bdr5$Cluster_Names<-factor(bdr5$Cluster,levels = c(1,2,3,4), 
                           labels=c("Alto", "Medio","Bajo", "Regular"))

Tercer punto: Insights.

  • Con la base de datos de bajas se realizó el clúster de edad y duración, en la cual se tomaron en cuenta las variables de la edad de los colaboradores y la duración que han tenido en la empresa. Se buscó el número óptimo de clúster y se tomaron en cuenta los primeros 4. En este podemos observar que las personas con edad mediana-alta no tienen una duración de largo tiempo en la empresa ya que forman parte del 25% con menor duración; otro dato que observamos que las personas con mayor edad han durado más tiempo en Form y forman parte del superior 50%, y por último observamos que existe una mayor rotación de personal en los colaboradores jóvenes.
  • En el análisis que se realizó mediante gráficas, obtuvimos que en los clúster, que la persona con mayor edad en los expert tiene 61, en senior tiene 57, en junior tiene 39 y en beginnner 27, también que en la empresa la mayoría de los colaboradores corresponden al clúster de beginner.
  • En cuanto al análisis de la duración de los colaboradores en la empresa y su salario encontramos estos puntos mas importantes; a) la mayoría de los empleados ganan arriba del salario diario promedio establecido por el gobierno, este oscila entre $150-$2000 pesos diarios, b) los colaboradores que tienen un tiempo medio en la empresa aproximadamente de un año tiene un salario promedio de $169, mientras los que duran menos tiempo (alrededor de 141 días) tienen un salario promedio de alrededor de $180.
  • El clúster mas grande es el llamado “Rehnes” tiene un total de colaboradores de 191, y en porcentaje de bajas se puede decir que es el 81.97% total de bajas, estos tiene la característica de son las personas que entran y salen muy pronto y tienen un salario por arriba de todos los demás clúster de $180 pesos, por lo que, en este clúster se necesita aplicar una estrategia de fidelización de los colaboradores de otra forma que no sea con un aumento de salario, es decir, Form puede implementar estrategias con recompensas que sean a largo plazo.
  • Como se puede observar en el analisis que se realizó de edad y salario se pueden destacar los siguientes puntos:
  1. el cluster que tiene una mayor frecuencia es el de 48 años de edad,
  2. el cluster que mas chico es de 22 años o menos por lo que podemos decir que en Form, la mayoría son mayores de 23 años,
  3. en cuanto al salario tienen un promedio de 180.68, pero existe un dato único el cual ganaba 500.
    En conclusión para Form podemos plantear una estrategia de estandarización de salarios de acuerdo al tiempo que llevan en la empresa y su edad, para poder así tener un mejor control de gastos de la empresa y aplicar nuevas a estrategias a cada uno de los cluster.

SECCION 4. Identificación de Resultados Relevantes y Sugerencias

INSIGHTS *Como podemos observar en la base de datos de Producción, el mayor cliente de Form, en cuestión de laminas procesadas, es Stabilus 1, así se muestra en la grafica de pastel de empresa, mientras que también cuenta con algunos clientes con muy poca producción como es el caso de VL-017-14989.

*En la base de datos Scrap, con las graficas que elaboramos, podemos observar que el mayor numero de desecho se origina en el área de la empresa de Pre-Producción, por lo que podemos enforcarnos en proponer estrategias que reduzcan el numero de desecho significativamente en esta área, así como también en el área donde menos hay desecho es en Post-producción.

En el área de recursos humanos podemos interpretar con las graficas que en Form, hay un mayor rango de edad entre las mujeres, así como también podemos observar que las mujeres en promedio ganan más que los hombres.
En cuestión a las bajas, el análisis de la base de datos nos arroja que existe una gran rotación de personal, y la mayoría de ellos no han alcanzado el grado de jubilación, las razones principales de este son abandono y baja por faltas. En base a la grafica de barras explicada en la parte de bajas, se menciona que la mayoría de las personas que abandonan su trabajo son solteras, así como también algunas de ellas no se conoce su estado civil.

*En las predicciones de desempeño de la industria automotriz se pudo observar que el automóvil de modelo Passenger se encuentra en decremento, tomando como base los datos de la tasa de desempleo de 6.43 y un índice de confianza de 82.3, se espera que siga el decremento de estos automóviles en EUA del 2021 al 2025. Mientras que en el segundo modelo de regresión con la misma base de datos se espera una predicción de ventas positiva en los automóviles comerciales, tomando en cuenta datos como tasa de desempleo de 6.43, un índice de confianza de 82.3, es incremento se espera del 2021 al 2025.

SUGERENCIAS *La estrategia planteada para Form,basada en el analisis de la base de datos de bajas, consiste en crear programas de fidelización de los colaboradores a largo plazo, donde ellos se sientan comprometidos con la empresa y sigan la visión de la misma, ya que esto lo identificamos porque existe una gran rotación en la empresa la cual es por falta de compromiso de los colaboradores hacia la empresa, por lo que tambien se le propone hacer juntas estrategicas con los colaboradores de las areas en la que se den temas de integración, trabajo en equipo entre otros.

  • Otra estrategia planteada es que exista un departamento dentro de la empresa en el cual se conforme por personas capacitadas para la recopilación de datos de cada una de las áreas y tomen decisiones en cada una de ellas en base a los datos que se obtengan, y tambien que se lleven acabo junta con los directivos para hacer una planeación de recursos.

Business Analytics y Business Intelligence.

Business Analytics es un enfoque de análisis de datos dentro de alguna empresa, consiste en llevar a cabo soluciones para satisfacer las necesidades de un negocio, lograr metas y alcanzar los objetivos planteados. BA se compone de obtener datos, analizar y mostrar datos de manera visual, ayuda en tomar decisiones basado en tendencias y lo que está pasando en el mercado en general. • Business Analytics ayuda a alcanzar los objetivos empresariales a partir de un análisis de grandes volúmenes de datos mediante herramientas como los es RStudio, Phyton, entre otros. • BA detecta tendencias conforme al tiempo y puede realizar pronósticos a partir de modelos predictivos. • BA utiliza modelos predictivos para optimizar los procesos de una empresa en cualquier área como producción, logística, recursos humanos entre otros. Business Intelligence se utiliza para evaluar, optimizar y coordinar las operaciones internas de una empresa, mientras que Business Analytics es obtener datos, analizarlos y mostrarlos. Existe diferencias entres estos dos, la mayor diferencia es en la poractica de utilizar los datos de una empresa para anticipar tendencias y resultados. Business Analytics ayuda en tomar decisiones basado en tendencias y lo que está pasando en el mercado en general.

KPI’S
Los kpi’s nos permiten medir en tiempo real el funcionamiento de las estrategias de alguna empresa como lo es Form, marketing o ventas brindando una información valiosa para tomar decisiones estratégicas que permitan a la empresa optimizar sus recursos para alcanzar los objetivos.

Los KPIs también desempeñan una importante función comunicativa ya que informan a directivos, colaboradores e inversores sobre la evolución de la empresa respecto a los objetivos establecidos, para que todos puedan trabajar con una visión y una meta común.

LS0tDQp0aXRsZTogPHNwYW4gc3R5bGU9IkNvbG9yOk9SQU5HRSI+ICoqRVZJREVOQ0lBIDIqKg0KYXV0aG9yOiA8c3BhbiBzdHlsZT0iQ29sb3I6R1JBWSI+IEFuYSBBcnZpenUtIEEwMTQxMjIyMCANCmRhdGU6IDxzcGFuIHN0eWxlPSJDb2xvcjpHUkFZIiA+IDIwMjItMTAtMTMNCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIHRoZW1lOiB1bml0ZWQNCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KLS0tDQoNCg0KIyMjIyBMaWJyZXJpYXMgcmVxdWVyaWRhcyAgDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShmb3JlaWduKQ0KbGlicmFyeShkcGx5cikgICAgICAgICMgZGF0YSBtYW5pcHVsYXRpb24gDQpsaWJyYXJ5KGZvcmNhdHMpICAgICAgIyB0byB3b3JrIHdpdGggY2F0ZWdvcmljYWwgdmFyaWFibGVzDQpsaWJyYXJ5KGdncGxvdDIpICAgICAgIyBkYXRhIHZpc3VhbGl6YXRpb24gDQpsaWJyYXJ5KGphbml0b3IpICAgICAgIyBkYXRhIGV4cGxvcmF0aW9uIGFuZCBjbGVhbmluZyANCmxpYnJhcnkoSG1pc2MpICAgICAgICAjIHNldmVyYWwgdXNlZnVsIGZ1bmN0aW9ucyBmb3IgZGF0YSBhbmFseXNpcyANCmxpYnJhcnkobmFuaWFyKSANCmxpYnJhcnkoZGxvb2tyKSANCmxpYnJhcnkocG9sbHN0ZXIpDQpsaWJyYXJ5KGRlc2NyKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShlcGlEaXNwbGF5KQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkocHN5Y2gpICAgICAgICAjIGZ1bmN0aW9ucyBmb3IgbXVsdGl2YXJpYXRlIGFuYWx5c2lzIA0KbGlicmFyeShjb3JycGxvdCkgICAgICMgY29ycmVsYXRpb24gcGxvdHMNCmxpYnJhcnkoanRvb2xzKSAgICAgICAjIHByZXNlbnRhdGlvbiBvZiByZWdyZXNzaW9uIGFuYWx5c2lzIA0KbGlicmFyeShsbXRlc3QpICAgICAgICMgZGlhZ25vc3RpYyBjaGVja3MgLSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcyANCmxpYnJhcnkoY2FyKSAgICAgICAgICAjIGRpYWdub3N0aWMgY2hlY2tzIC0gbGluZWFyIHJlZ3Jlc3Npb24gYW5hbHlzaXMNCmxpYnJhcnkob2xzcnIpICAgICAgICAjIGRpYWdub3N0aWMgY2hlY2tzIC0gbGluZWFyIHJlZ3Jlc3Npb24gYW5hbHlzaXMgDQpsaWJyYXJ5KGthYmxlRXh0cmEpICAgIyBIVE1MIHRhYmxlIGF0dHJpYnV0ZXMNCmxpYnJhcnkodHNlcmllcykgICAjIHRpbWUgc2VyaWVzIGFuYWx5c2lzIGFuZCBjb21wdXRhdGlvbmFsIGZpbmFuY2UgDQpsaWJyYXJ5KGZvcmVjYXN0KSAgIyBwcm92aWRlcyBtZXRob2RzIGFuZCB0b29scyBmb3IgZGlzcGxheWluZyBhbmQgYW5hbHl6aW5nIHVuaXZhcmlhdGUgdGltZSBzZXJpZXMgZm9yZWNhc3QNCmxpYnJhcnkoYXN0c2EpICAgICAjIGFwcGxpZWQgc3RhdGlzdGljYWwgdGltZSBzZXJpZXMgYW5hbHlzaXMNCmxpYnJhcnkocGx5cikgDQpsaWJyYXJ5KGZhY3RvZXh0cmEpICAgIyBwcm92aWRlcyBmdW5jdGlvbnMgdG8gZXh0cmFjdCBhbmQgdmlzdWFsaXplIHRoZSBvdXRwdXQgb2YgZXhwbG9yYXRvcnkgbXVsdGl2YXJpYXRlIGRhdGEgYW5hbHlzZXMNCiNpbnN0YWxsLnBhY2thZ2VzKCJnZ2ZvcnRpZnkiKQ0KbGlicmFyeShnZ2ZvcnRpZnkpICAgICMgZGF0YSB2aXN1YWxpemF0aW9uIHRvb2xzIGZvciBzdGF0aXN0aWNhbCBhbmFseXNpcyByZXN1bHRzDQpgYGANCg0KDQojIDxzcGFuIHN0eWxlPSJDb2xvcjpPUkFOR0UiPiAqKlNFQ0NJT04gMS4gTGltcGllemEsIFRyYW5zZm9ybWFjacOzbiwgeSBPcmdhbml6YWNpw7NuIGRlIEJhc2VzIGRlIERhdG9zKioNCg0KIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiAjMTk0MUU0Ij4gKipSRUNVUlNPUyBIVU1BTk9TKioNCg0KIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjogIzE5NDFFNCI+ICoqRXNjb2dlciBsYSBiYXNlIGRhdG9zKioNCg0KYGBge3J9DQojIGZpbGUuY2hvb3NlKCkNCmNvbGFiIDwtIHJlYWQuY3N2KCJDOlxcVXNlcnNcXHNvZmlhXFxEb3dubG9hZHNcXGNvbGFiX2ZpbmFsICgxKS5jc3YiKQ0KYmFqYXMgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcc29maWFcXERvd25sb2Fkc1xcYmFqYXNfZmluYWwgKDIpLmNzdiIpDQpgYGANCg0KPiBFbnRlbmRlbW9zIGxhIGJhc2UgZGUgZGF0b3MNCg0KYGBge3J9DQpyZXN1bWVuMSA8LSBzdW1tYXJ5KGNvbGFiKQ0KcmVzdW1lbjENCg0KcmVzdW1lbjIgPC0gc3VtbWFyeShiYWphcykNCnJlc3VtZW4yDQpgYGANCg0KIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6IzVDNzVEQyI+ICoqQ09MQUJPUkFET1JFUyoqDQoNCiMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiM1Qzc1REMiPiAqKjEuwr9DdcOhbnRhcyB2YXJpYWJsZXMgeSBjdcOhbnRvcyByZWdpc3Ryb3MgdGllbmUgbGEgYmFzZSBkZSBkYXRvcz8qKg0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6IzVDNzVEQyI+IFI9IDEwNCByZWdpc3Ryb3MgeSA5IHZhcmlhYmxlcyA8L2NlbnRlcj4NCg0KYGBge3J9DQojIGluc3RhbGwucGFja2FnZXMoInBzeWNoIikNCnN0cihjb2xhYikNCmxpYnJhcnkocHN5Y2gpDQpkZXNjcmliZShjb2xhYikNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojNUM3NURDIj4gKioyLsK/Q2xhc2lmaWNhIGNhZGEgdmFyaWFibGUgZW4gY3VhbGl0YXRpdmEsIGN1YW50aXRhdGl2YSBkaXNjcmV0YSBvIGN1YW50aXRhdGl2YSBjb250aW51YS4/KioNCg0KYGBge3J9DQpWYXJpYWJsZTwtYygiZWRhZCIsImdlbmVybyIsImFsdGEiLCJwdWVzdG8iLCJzYWxhcmlvX2RpYXJpbyIsImx1Z2FyLm5hY2ltLiIsIm1waW8iLCJlc3RhZG8iLCJjaXZpbCIpDQpUeXBlPC1jKCJjdWFudGl0YXRpdmEgY29udGludWEiLCJjdWFsaXRhdGl2YSIsImN1YW50aXRhdGl2YSBjb250aW51YSIsImN1YWxpdGF0aXZhIiwiY3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwiY3VhbGl0YXRpdmEiLCJjdWFsaXRhdGl2YSIsImN1YWxpdGF0aXZhIiwiY3VhbGl0YXRpdmEiKQ0KdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSkNCmtuaXRyOjprYWJsZSh0YWJsZSkNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojNUM3NURDIj4gKiozLiBFbGlnZSBsYSBlc2NhbGEgZGUgbWVkaWNpw7NuIGRlIGNhZGEgdmFyaWFibGUuKioNCg0KYGBge3J9DQpWYXJpYWJsZTwtYygiZWRhZCIsImdlbmVybyIsImFsdGEiLCJwdWVzdG8iLCJzYWxhcmlvX2RpYXJpbyIsImx1Z2FyLm5hY2ltLiIsIm1waW8iLCJlc3RhZG8iLCJjaXZpbCIpDQpUeXBlPC1jKCJjdWFudGl0YXRpdmEgY29udGludWEiLCJjdWFsaXRhdGl2YSIsImN1YW50aXRhdGl2YSBjb250aW51YSIsImN1YWxpdGF0aXZhIiwiY3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwiY3VhbGl0YXRpdmEiLCJjdWFsaXRhdGl2YSIsImN1YWxpdGF0aXZhIiwiY3VhbGl0YXRpdmEiKQ0KRXNjYWxhX2RlX01lZGljacOzbiA8LSBjKCJSYXpvbiIsIk5vbWluYWwiLCJSYXpvbiIsIk5vbWluYWwiLCJSYXpvbiIsIk5vbWluYWwiLCJOb21pbmFsIiwiTm9taW5hbCIsIk5vbWluYWwiKQ0KdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSxFc2NhbGFfZGVfTWVkaWNpw7NuKQ0Ka25pdHI6OmthYmxlKHRhYmxlKQ0KYGBgDQoNCiMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiM1Qzc1REMiPiAqKkJBSkFTKioNCg0KIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6IzVDNzVEQyI+ICoqMS7Cv0N1w6FudGFzIHZhcmlhYmxlcyB5IGN1w6FudG9zIHJlZ2lzdHJvcyB0aWVuZSBsYSBiYXNlIGRlIGRhdG9zPyoqDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjojNUM3NURDIj4gUj0gMjMzIHJlZ2lzdHJvcyB5IDEwIHZhcmlhYmxlcyA8L2NlbnRlcj4NCg0KYGBge3J9DQojIGluc3RhbGwucGFja2FnZXMoInBzeWNoIikNCnN0cihiYWphcykNCmxpYnJhcnkocHN5Y2gpDQpkZXNjcmliZShiYWphcykNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojNUM3NURDIj4gKioyLsK/Q2xhc2lmaWNhIGNhZGEgdmFyaWFibGUgZW4gY3VhbGl0YXRpdmEsIGN1YW50aXRhdGl2YSBkaXNjcmV0YSBvIGN1YW50aXRhdGl2YSBjb250aW51YS4/KioNCg0KYGBge3J9DQpWYXJpYWJsZTwtYygibm9tYnJlIiwiZWRhZCIsImdlbmVybyIsImFsdGEiLCJtb3Rpdm9fYmFqYSIsImR1cmFjaW9uIiwicHVlc3RvIiwic2FsYXJpb19kaWFyaW8iLCJlc3RhZG8iLCJlLmNpdmlsLiIpDQpUeXBlPC1jKCJjdWFsaXRhdGl2YSIsImN1YW50aXRhdGl2YSBjb250aW51YSIsImN1YWxpdGF0aXZhIiwiY3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwiY3VhbGl0YXRpdmEiLCJjdWFudGl0YXRpdmEgY29udGludWEiLCJjdWFsaXRhdGl2YSIsImN1YW50aXRhdGl2YSBjb250aW51YSIsImN1YWxpdGF0aXZhIiwiY3VhbGl0YXRpdmEiKQ0KdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSkNCmtuaXRyOjprYWJsZSh0YWJsZSkNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojNUM3NURDIj4gKiozLiBFbGlnZSBsYSBlc2NhbGEgZGUgbWVkaWNpw7NuIGRlIGNhZGEgdmFyaWFibGUuKioNCg0KYGBge3J9DQpWYXJpYWJsZTwtYygibm9tYnJlIiwiZWRhZCIsImdlbmVybyIsImFsdGEiLCJtb3Rpdm9fYmFqYSIsImR1cmFjaW9uIiwicHVlc3RvIiwic2FsYXJpb19kaWFyaW8iLCJlc3RhZG8iLCJlLmNpdmlsLiIpDQpUeXBlPC1jKCJjdWFsaXRhdGl2YSIsImN1YW50aXRhdGl2YSBjb250aW51YSIsImN1YWxpdGF0aXZhIiwiY3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwiY3VhbGl0YXRpdmEiLCJjdWFudGl0YXRpdmEgY29udGludWEiLCJjdWFsaXRhdGl2YSIsImN1YW50aXRhdGl2YSBjb250aW51YSIsImN1YWxpdGF0aXZhIiwiY3VhbGl0YXRpdmEiKQ0KRXNjYWxhX2RlX01lZGljacOzbiA8LSBjKCJOb21pbmFsIiwiSW50ZXJ2YWxvIiwiTm9taW5hbCIsIkludGVydmFsbyIsIk5vbWluYWwiLCJJbnRlcnZhbG8iLCJOb21pbmFsIiwiSW50ZXJ2YWxvIiwiTm9taW5hbCIsIk5vbWluYWwiKQ0KdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSxFc2NhbGFfZGVfTWVkaWNpw7NuKQ0Ka25pdHI6OmthYmxlKHRhYmxlKQ0KYGBgDQoNCg0KIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiAjMTlFNDI4Ij4gKipERUxJVkVSWSBQTEFOKiogDQoNCiMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6ICMxOUU0MjgiPiAqKkVzY29nZXIgbGEgYmFzZSBkYXRvcyoqDQoNCmBgYHtyfQ0KIyBmaWxlLmNob29zZSgpDQpkZXZwbGFuIDwtIHJlYWQuY3N2KCJDOlxcVXNlcnNcXHNvZmlhXFxEb3dubG9hZHNcXERFTElWRVJZIFBMQU4gYmRmX1BydWViYS5jc3YiKQ0KYGBgDQoNCj4gRW50ZW5kZW1vcyBsYSBiYXNlIGRlIGRhdG9zDQoNCmBgYHtyfQ0KcmVzdW1lbiA8LSBzdW1tYXJ5KGRldnBsYW4pDQpyZXN1bWVuDQpgYGANCg0KIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojMTlFNDI4Ij4gKipTRUNDSU9OIDEuIExpbXBpZXphLCBUcmFuc2Zvcm1hY2nDs24sIHkgT3JnYW5pemFjacOzbiBkZSBCYXNlcyBkZSBEYXRvcyoqDQoNCiMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiAjODVFNThDIj4gKipUw6ljbmljYSAxLiBDb252ZXJ0aXIgdGlwb3MgZGUgZGF0b3MqKg0KDQojIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6Izg1RTU4QyI+ICoqQ29udmVydGlyIGRlIGNhcmFjdGVyIGEgZmVjaGEqKg0KDQo+IExhIGxpbXBpZXphIHkgbW9kaWZpY2FjacOzbiBkZSBmaWxhcyB5IGNvbHVtbmFzIHJlc3BlY3RvIGEgbGFzIHZhcmlhYmxlcyBzZSByZWFsaXrDsyBkaXJlY3RhbWVudGUgZW4gRXhjZWwgcG9yIGN1ZXN0aW9uZXMgZGUgZmFjaWxpZGFkIHlhIHF1ZSBsYSBiYXNlIGVzdGFiYSBvcmRlbmFkYSBkZSB1bmEgbWFuZXJhIGVuIGRvbmRlIFIgcmVzdWx0YXLDrWEgbXVjaG8gbcOhcyBjb21wbGljYWRvLg0KDQoNCmBgYHtyfQ0KZGV2cGxhbjEgPC0gZGV2cGxhbg0KZGV2cGxhbjEkRmVjaGE8LWFzLkRhdGUoZGV2cGxhbjEkRmVjaGEsZm9ybWF0PSIlbS8lZC8lWSIpIA0KYGBgDQoNCiMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiM4NUU1OEMiPiAqKjEuwr9DdcOhbnRhcyB2YXJpYWJsZXMgeSBjdcOhbnRvcyByZWdpc3Ryb3MgdGllbmUgbGEgYmFzZSBkZSBkYXRvcz8qKg0KDQo8Y2VudGVyPiA8c3BhbiBzdHlsZT0iY29sb3I6Izg1RTU4QyI+IFI9IDIyOCByZWdpc3Ryb3MgeSA0IHZhcmlhYmxlcyA8L2NlbnRlcj4NCg0KYGBge3J9DQojIGluc3RhbGwucGFja2FnZXMoInBzeWNoIikNCnN0cihkZXZwbGFuMSkNCmxpYnJhcnkocHN5Y2gpDQpkZXNjcmliZShkZXZwbGFuMSkNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojODVFNThDIj4gKioyLsK/Q2xhc2lmaWNhIGNhZGEgdmFyaWFibGUgZW4gY3VhbGl0YXRpdmEsIGN1YW50aXRhdGl2YSBkaXNjcmV0YSBvIGN1YW50aXRhdGl2YSBjb250aW51YS4/KioNCg0KYGBge3J9DQpWYXJpYWJsZTwtYygiSURfRmVjaGEiLCJGZWNoYSIsIkNMSUVOVEUiLCJQZWRpZG9zIikNClR5cGU8LWMoImN1YW50aXRhdGl2YSBjb250aW51YSIsImN1YW50aXRhdGl2YSBjb250aW51YSIsImN1YWxpdGF0aXZhIiwiY3VhbnRpdGF0aXZhIGNvbnRpbnVhIikNCnRhYmxlPC1kYXRhLmZyYW1lKFZhcmlhYmxlLFR5cGUpDQprbml0cjo6a2FibGUodGFibGUpDQpgYGANCg0KIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6Izg1RTU4QyI+ICoqMy4gRWxpZ2UgbGEgZXNjYWxhIGRlIG1lZGljacOzbiBkZSBjYWRhIHZhcmlhYmxlLioqDQoNCmBgYHtyfQ0KVmFyaWFibGU8LWMoIklEX0ZlY2hhIiwiRmVjaGEiLCJDTElFTlRFIiwiUGVkaWRvcyIpDQpUeXBlPC1jKCJjdWFudGl0YXRpdmEgY29udGludWEiLCJjdWFudGl0YXRpdmEgY29udGludWEiLCJjdWFsaXRhdGl2YSIsImN1YW50aXRhdGl2YSBjb250aW51YSIpDQpFc2NhbGFfZGVfTWVkaWNpw7NuIDwtIGMoIlJhem9uIiwiUmF6b24iLCJOb21pbmFsIiwiUmF6b24iKQ0KdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSxFc2NhbGFfZGVfTWVkaWNpw7NuKQ0Ka25pdHI6OmthYmxlKHRhYmxlKQ0KYGBgDQoNCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IzE5RTQyOCI+KipBbsOhbGlzaXMgRXhwbG9yYXRvcmlvIGRlIGxhcyBCYXNlcyBkZSBEYXRvcyoqDQoNCiMjIyMgVGFibGEgY29uIGxvcyBwcmluY2lwYWxlcyBlc3RhZMOtc3RpY29zIGRlc2NyaXB0aXZvcw0KDQojIyMjICoqRXN0YWTDrXN0aWNvcyBkZXNjcmlwdGl2b3MgRGVsaXZlcnkgUGxhbioqDQpgYGB7cn0NCm1lZGlhbmEgPC0gbWVkaWFuKGRldnBsYW4xJFBlZGlkb3MsIG5hLnJtID0gVFJVRSkNCm1lZGlhbmENCg0KZGVzY3JpYmUoZGV2cGxhbjEpDQpgYGANCj4gUGFyYSBjb25vY2VyIGVzdGFzIGZ1bmNpb25lcyBlc3RhZMOtc3RpY2FzIHJlYWxpemFtb3MgdW5hIGRlc2NyaXBjacOzbiBkZSBsYSBiYXNlIGRlIGRhdG9zLCBkb25kZSBwb2RlbW9zIHZlciBxdWUgbGEgbWVkaWFuYSBlcyAwLiBIYXkgdW4gdG90YWwgZGUgMjI4IHJlZ2lzdHJvcyB5IHV0aWxpemFtb3MgNCB2YXJpYWJsZXMgcGFyYSBhY29tb2RvIGRlIGxhcyBncsOhZmljYXMgZW4gZG9uZGUgY29udGFiaWxpemFtb3MgZWwgbsO6bWVybyBkZSBwZWRpZG9zIHBvciBtZXMgeSBjbGllbnRlLiAgICANCg0KIyMjIyBIaXN0b2dyYW1hIGdlbmVyYWwgDQpgYGB7cn0NCmhpc3QoZGV2cGxhbjEkUGVkaWRvcykgDQpgYGANCg0KDQojIyA8c3BhbiBzdHlsZT0iQ29sb3I6ICNFNEUxMTkiPiAqKkRFTElWRVJZIFBFUkZPUk1BTkNFKioNCg0KIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjogI0U0RTExOSI+ICoqRXNjb2dlciBsYSBiYXNlIGRhdG9zKioNCg0KYGBge3J9DQojIGZpbGUuY2hvb3NlKCkNCmRldnBlciA8LSByZWFkLmNzdigiQzpcXFVzZXJzXFxzb2ZpYVxcRG93bmxvYWRzXFxGT1JNIC0gRGVsaXZlcnkgUGVyZm9ybWFuY2UgQy5jc3YiKQ0KYGBgDQoNCj4gRW50ZW5kZW1vcyBsYSBiYXNlIGRlIGRhdG9zDQoNCmBgYHtyfQ0KcmVzdW1lbiA8LSBzdW1tYXJ5KGRldnBlcikNCnJlc3VtZW4NCmBgYA0KDQojIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiNFNEUxMTkiPiAqKlNFQ0NJT04gMS4gTGltcGllemEsIFRyYW5zZm9ybWFjacOzbiwgeSBPcmdhbml6YWNpw7NuIGRlIEJhc2VzIGRlIERhdG9zKioNCg0KIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6ICNFQUU5ODEiPiAqKlTDqWNuaWNhIDEuIENvbnZlcnRpciB0aXBvcyBkZSBkYXRvcyoqDQoNCj4gU2UgcmVhbGl6w7MgdW5hIGxpbXBpYSBwcmV2aWEgYSBsYSBiYXNlIGRlIGRhdG9zIGRlYmlkbyBhIHF1ZSBubyBzZSBwb2TDrWEgbWFuZWphciBlbiBSLCB5YSBxdWUgZWwgZm9ybWF0byBlbiBxdWUgc2UgZW5jb250cmFiYSAgbm8gcGVybWl0w61hIHF1ZSBSIHB1ZGllcmEgZW50ZW5kZXIgY3VhbGVzIGVyYW4gbGFzIHZhcmlhYmxlcyBkZSBudWVzdHJhIGJhc2UgZGUgZGF0b3MsIHBvciBsbyB0YW50byBsYXMgbW9kaWZpY2FjaW9uZXMgeSBsaW1waWV6YXMgcXVlIHNlIHJlYWxpemFyb24gZnVlIGxhIHTDqWNuaWNhIGRlICdSZW1vdmVyIHZhbG9yZXMgaXJyZWxldmFudGVzJyBlbiBlc3RlIGNhc28gcXVpdGFtb3MgbGEgY29uY2x1c2nDs24gcG9ycXVlIG5vIHRlbmRyw61hIHZhbG9yIGVuIGxhIGJhc2UgZGUgZGF0b3MsIGVsaW1pbmFtb3MgdGFyZ2V0IChob3JhcykgeSB0b21hbW9zIGVsIHZhbG9yIGRlIGNhZGEgaW5pY2lvIGRlIG1lcyBwYXJhIGNvbXBhcmFyIHByaW5jaXBpbyBkZSBtZXMgY29uIG1lcywgZGVzcHXDqXMgZW4gUiBzZSB0cmFiYWpvIGNvbiBsYSAqKnTDqWNuaWNhIGRlIGNvbnZlcnRpciB0aXBvcyBkZSBkYXRvcyoqIGVuIGVzdGUgY2FzbyBkZSBjYXJhY3RlciBhIGZlY2hhIHkgY2FyYWN0ZXIgYSBob3JhLiANCg0KDQojIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6I0VBRTk4MSI+ICoqQ29udmVydGlyIGRlIGNhcmFjdGVyIGEgZmVjaGEqKg0KDQpgYGB7cn0NCmRldnBlcjIgPC0gZGV2cGVyDQpkZXZwZXIyJGZlY2hhIDwtIGFzLkRhdGUoZGV2cGVyMiRmZWNoYSwgZm9ybWF0ID0iJWQvJW0vJXkiKQ0KbGlicmFyeSh0aWJibGUpDQp0aWJibGUoZGV2cGVyMikgIA0KYGBgDQoNCiMjIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojRUFFOTgxIj4gKipDYW1iaWFyIGxvcyBub21icmVzIGRlIGxhcyB2YXJpYWJsZXMgbcOhcyBjb3J0YXMgeSBlc3BlY8OtZmljYXMqKg0KDQpgYGB7cn0NCm5hbWVzKGRldnBlcjIpIFszXSA9ICJkZWxheV9wZXJmb3JtYW5jZSINCm5hbWVzKGRldnBlcjIpDQpgYGANCg0KIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6I0VBRTk4MSI+ICoqMS7Cv0N1w6FudGFzIHZhcmlhYmxlcyB5IGN1w6FudG9zIHJlZ2lzdHJvcyB0aWVuZSBsYSBiYXNlIGRlIGRhdG9zPyoqDQoNCjxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjojRUFFOTgxIj4gUj0gNTIgcmVnaXN0cm9zIHkgMyB2YXJpYWJsZXMgPC9jZW50ZXI+DQoNCmBgYHtyfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJwc3ljaCIpDQpzdHIoZGV2cGVyMikNCmxpYnJhcnkocHN5Y2gpDQpkZXNjcmliZShkZXZwZXIyKQ0KYGBgDQoNCiMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiNFQUU5ODEiPiAqKjIuwr9DbGFzaWZpY2EgY2FkYSB2YXJpYWJsZSBlbiBjdWFsaXRhdGl2YSwgY3VhbnRpdGF0aXZhIGRpc2NyZXRhIG8gY3VhbnRpdGF0aXZhIGNvbnRpbnVhLj8qKg0KDQpgYGB7cn0NClZhcmlhYmxlPC1jKCJmZWNoYSIsImNsaWVudGUiLCJkaWYiKQ0KVHlwZTwtYygiY3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwiY3VhbGl0YXRpdmEiLCJjdWFudGl0YXRpdmEgY29udGludWEiKQ0KdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSkNCmtuaXRyOjprYWJsZSh0YWJsZSkNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojRUFFOTgxIj4gKiozLiBFbGlnZSBsYSBlc2NhbGEgZGUgbWVkaWNpw7NuIGRlIGNhZGEgdmFyaWFibGUuKioNCg0KYGBge3J9DQpWYXJpYWJsZTwtYygiZmVjaGEiLCJjbGllbnRlIiwiZGlmIikNClR5cGU8LWMoImN1YW50aXRhdGl2YSBjb250aW51YSIsImN1YWxpdGF0aXZhIiwiY3VhbnRpdGF0aXZhIGNvbnRpbnVhIikNCkVzY2FsYV9kZV9NZWRpY2nDs24gPC0gYygiUmF6b24iLCJOb21pbmFsIiwiUmF6b24iKQ0KdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSxFc2NhbGFfZGVfTWVkaWNpw7NuKQ0Ka25pdHI6OmthYmxlKHRhYmxlKQ0KYGBgDQoNCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6I0U0RTExOSI+KipBbsOhbGlzaXMgRXhwbG9yYXRvcmlvIGRlIGxhcyBCYXNlcyBkZSBEYXRvcyoqDQoNCiMjIyMgVGFibGEgY29uIGxvcyBwcmluY2lwYWxlcyBlc3RhZMOtc3RpY29zIGRlc2NyaXB0aXZvcw0KDQojIyMjICoqRXN0YWTDrXN0aWNvcyBkZXNjcmlwdGl2b3MgRGVsaXZlcnkgUGVyZm9ybWFuY2UqKg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgaW5zdGFsbC5wYWNrYWdlcygicHN5Y2giKQ0KbGlicmFyeShwc3ljaCkNCmRlc2NyaWJlKGRldnBlcjIpDQoNClZhcmlhYmxlcyA8LWMoIkRpZmVyZW5jaWEgRGVsaXZlcnkiKQ0KTWVkaWEgPC1jKCIxNi4wNyIpDQpNZWRpYW5hIDwtYygiMCIpDQpEZXN2aWFjaW9uX2VzdGFuZGFyIDwtYygiMjQuNjMiKQ0KYGBgDQoNCmBgYHtyfQ0KdGFibGUzIDwtZGF0YS5mcmFtZShWYXJpYWJsZXMsIE1lZGlhLCBNZWRpYW5hLCBEZXN2aWFjaW9uX2VzdGFuZGFyKQ0Ka25pdHI6OmthYmxlKHRhYmxlMykNCmBgYA0KDQoNCiMjIDxzcGFuIHN0eWxlPSJDb2xvcjogIzZDMTlFNCI+ICoqUFJPRFVDQ0lPTioqDQoNCiMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6IzZDMTlFNCI+ICoqRXNjb2dlciBsYSBiYXNlIGRhdG9zKioNCg0KYGBge3J9DQojIGZpbGUuY2hvb3NlKCkNCnByb2QgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcc29maWFcXE9uZURyaXZlXFxEb2N1bWVudG9zXFxSRVRPXFxQcm9kdWNjaW9uIENhcnRvbi5jc3YiKQ0KYGBgDQoNCj4gRW50ZW5kZW1vcyBsYSBiYXNlIGRlIGRhdG9zDQoNCmBgYHtyfQ0KcmVzdW1lbiA8LSBzdW1tYXJ5KHByb2QpDQpyZXN1bWVuDQpgYGANCg0KIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjogIzZDMTlFNCI+ICoqU0VDQ0lPTiAxLiBMaW1waWV6YSwgVHJhbnNmb3JtYWNpw7NuLCB5IE9yZ2FuaXphY2nDs24gZGUgQmFzZXMgZGUgRGF0b3MqKg0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojOTk2OERGIj4gKipUw6ljbmljYSAxLiBSZW1vdmVyIGRhdG9zIGlycmVsZXZhbnRlcy4qKg0KDQojIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6Izk5NjhERiI+ICoqRWxpbWluYXIgY29sdW1uYXMqKg0KDQo+IExhIGJhc2UgZGUgZGF0b3MgZGUgUHJvZHVjY2lvbiB0ZW7DrWEgdmFyaWFzIHZhcmlhYmxlcyBxdWUgcGFyYSBudWVzdHJvIGFuYWxpc2lzIG5vIGxvIG9jdXBhYmFtb3MgcG9yIGxvIHF1ZSBsYXMgZWxpbWluYW1vcyBjb24gbGEgZnVuY2nDs24gKnN1YnNldCoNCg0KYGBge3J9DQpwcm9kMSA8LSBwcm9kDQpwcm9kMSA8LSBzdWJzZXQgKHByb2QxLCBzZWxlY3QgPSAtYyAoSURGT1JNLEhSX0ZJTixFU1RBQ0lPTl9BUlJBTlFVRSxJTklDSU8uREUuUFJPQ0VTTyxGSU5fREVfUFJPQ0VTTykpDQpzdW1tYXJ5IChwcm9kMSkNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojOTk2OERGIj4gKipUw6ljbmljYSAyLiBDb252ZXJ0aXIgdGlwb3MgZGUgZGF0b3MuKioNCg0KIyMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiM5OTY4REYiPiAqKkNvbnZlcnRpciBkZSBjYXJhY3RlciBhIGZlY2hhKioNCg0KPiBMYSBiYXNlIGRlIGRhdG9zIG5vIGNvbnRlbsOtYSBuaW5ndW4gZm9ybWF0bywgcG9yIGxvIHF1ZSBlbiBlbCBhbmFsaXNpcyBsb3MgZGF0b3MgcG9kw61hbiB0ZW5lciBlcnJvcmVzIHBvciBzZSBjb252aXJ0acOzIGxhIGZlY2hhIGEgZm9ybWF0by4NCg0KYGBge3J9DQpsaWJyYXJ5KHRpYmJsZSkNCnByb2QyIDwtIHByb2QxDQpwcm9kMiRGRUNIQSA8LSBhcy5EYXRlKHByb2QyJEZFQ0hBLCBmb3JtYXQgPSAiJWQvJW0vJVkiKQ0KdGliYmxlIChwcm9kMikNCmBgYA0KDQojIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6Izk5NjhERiI+ICoqQ29udmVydGlyIGRlIGNhcmFjdGVyIGEgZW50ZXJvKioNCg0KPiBFbiBlc3RlIGNhc28sIHNlIGhhYmxhIGRlIGxhbWluYXMgcXVlIHNlIHRyYWJhamFyb24gcG9yIGxvIHF1ZSBuZWNlc2l0YW1vcyBsYXMgY2FudGlkYWRlcyBlbiBlbnRlcm8uDQoNCmBgYHtyfQ0KcHJvZDMgPC0gcHJvZDINCnByb2QzJFBaQV9QUk9HIDwtIHN1YnN0cihwcm9kMyRQWkFfUFJPRywgc3RhcnQgPSAxLCBzdG9wID0gMikgDQpwcm9kMyRUTU9fTUlOIDwtIHN1YnN0cihwcm9kMyRUTU9fTUlOLCBzdGFydCA9IDEsIHN0b3AgPSAyKSANCnByb2QzJExBTUlOQVNfUFJPQ0VTQURBUyA8LSBzdWJzdHIocHJvZDMkTEFNSU5BU19QUk9DRVNBREFTLCBzdGFydCA9IDEsIHN0b3AgPSAyKSANCg0KdGliYmxlKHByb2QzKQ0KDQpwcm9kMyRQWkFfUFJPRyA8LSBhcy5pbnRlZ2VyKHByb2QzJFBaQV9QUk9HKQ0KcHJvZDMkVE1PX01JTiA8LSBhcy5pbnRlZ2VyKHByb2QzJFRNT19NSU4pDQpwcm9kMyRMQU1JTkFTX1BST0NFU0FEQVMgPC0gYXMuaW50ZWdlcihwcm9kMyRMQU1JTkFTX1BST0NFU0FEQVMpDQoNCnN0cihwcm9kMykgICAgICANCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojOTk2OERGIj4gKipUw6ljbmljYSAzLiBWYWxvcmVzIGZhbHRhbnRlcy4qKg0KDQojIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6Izk5NjhERiI+ICoqwr9DdcOhbnRvcyBOQSB0ZW5nbyBlbiBsYSBiYXNlIGRlIGRhdG9zPyoqDQoNCmBgYHtyfQ0Kc3VtKGlzLm5hKHByb2QzKSkNCnN1bShpcy5uYShwcm9kKSkNCmBgYA0KDQojIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6Izk5NjhERiI+ICoqwr9DdcOhbnRvcyBOQSB0ZW5nbyBwb3IgdmFyaWFibGU/KioNCg0KYGBge3J9DQpzYXBwbHkocHJvZDMsIGZ1bmN0aW9uKHgpc3VtKGlzLm5hKHgpKSkNCmBgYA0KDQojIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6Izk5NjhERiI+ICoqUmVlbXBsYXphciBOQSBjb24gY2Vyb3MqKg0KDQpgYGB7cn0NCnByb2Q0IDwtcHJvZDMNCnByb2Q0IFtpcy5uYShwcm9kNCldPC0wDQpzdW1tYXJ5KHByb2Q0KSANCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojOTk2OERGIj4gKioxLsK/Q3XDoW50YXMgdmFyaWFibGVzIHkgY3XDoW50b3MgcmVnaXN0cm9zIHRpZW5lIGxhIGJhc2UgZGUgZGF0b3M/KioNCg0KPGNlbnRlcj4gPHNwYW4gc3R5bGU9ImNvbG9yOiM5OTY4REYiPiBSPSAyNjc4IHJlZ2lzdHJvcyB5IDkgdmFyaWFibGVzIDwvY2VudGVyPg0KDQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygicHN5Y2giKQ0Kc3RyKHByb2Q0KQ0KbGlicmFyeShwc3ljaCkNCmRlc2NyaWJlKHByb2Q0KQ0KYGBgDQoNCiMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiM5OTY4REYiPiAqKjIuwr9DbGFzaWZpY2EgY2FkYSB2YXJpYWJsZSBlbiBjdWFsaXRhdGl2YSwgY3VhbnRpdGF0aXZhIGRpc2NyZXRhIG8gY3VhbnRpdGF0aXZhIGNvbnRpbnVhLj8qKg0KDQpgYGB7cn0NClZhcmlhYmxlPC1jKCJESUEiLCJGRUNIQSIsIkNMSUVOVEUiLCJQUk9EVUNUTyIsIlBaQV9QUk9HIiwiVE1PX01JTiIsIkxBTUlOQVNfUFJPQ0VTQURBUyIsIlNFUF9VUCIsIlRJRU1QT19DQUxJREFEIikNClR5cGU8LWMoIkN1YW50aXRhdGl2YSBjb250aW51YSIsIkN1YW50aXRhdGl2YSBjb250aW51YSIsIkN1YWxpdGF0aXZhIiwiQ3VhbGl0YXRpdmEiLCJDdWFudGl0YXRpdmEgZGlzY3JldGEiLCJDdWFsaXRhdGl2YSIsIkN1YW50aXRhdGl2YSBkaXNjcmV0YSIsIkN1YW50aXRhdGl2YSBjb250aW51YSIsIkN1YWxpdGF0aXZhIikNCnRhYmxlPC1kYXRhLmZyYW1lKFZhcmlhYmxlLFR5cGUpDQprbml0cjo6a2FibGUodGFibGUpDQpgYGANCg0KIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6Izk5NjhERiI+ICoqMy4gRWxpZ2UgbGEgZXNjYWxhIGRlIG1lZGljacOzbiBkZSBjYWRhIHZhcmlhYmxlLioqDQoNCmBgYHtyfQ0KVmFyaWFibGU8LWMoIkRJQSIsIkZFQ0hBIiwiQ0xJRU5URSIsIlBST0RVQ1RPIiwiUFpBX1BST0ciLCJUTU9fTUlOIiwiTEFNSU5BU19QUk9DRVNBREFTIiwiU0VQX1VQIiwiVElFTVBPX0NBTElEQUQiKQ0KVHlwZTwtYygiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwiQ3VhbGl0YXRpdmEiLCJDdWFsaXRhdGl2YSIsIkN1YW50aXRhdGl2YSBkaXNjcmV0YSIsIkN1YWxpdGF0aXZhIiwiQ3VhbnRpdGF0aXZhIGRpc2NyZXRhIiwiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwiQ3VhbGl0YXRpdmEiKQ0KRXNjYWxhX2RlX01lZGljacOzbiA8LSBjKCJSYXpvbiIsIlJhem9uIiwiTm9taW5hbCIsIk5vbWluYWwiLCJSYXpvbiIsIkludGVydmFsbyIsIlJhem9uIiwiSW50ZXJ2YWxvIiwiT3JkaW5hbCIpDQp0YWJsZTwtZGF0YS5mcmFtZShWYXJpYWJsZSxUeXBlLEVzY2FsYV9kZV9NZWRpY2nDs24pDQprbml0cjo6a2FibGUodGFibGUpDQpgYGANCg0KIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjojNkMxOUU0Ij4qKkFuw6FsaXNpcyBFeHBsb3JhdG9yaW8gZGUgbGFzIEJhc2VzIGRlIERhdG9zKioNCg0KIyMjIyBUYWJsYSBjb24gbG9zIHByaW5jaXBhbGVzIGVzdGFkw61zdGljb3MgZGVzY3JwdGl2b3MNCg0KIyMjIyMgKipFc3RhZMOtc3RpY29zIGRlc2NyaXB0aXZvcyBQcm9kdWNjacOzbioqDQoNCmBgYHtyfQ0KY3J1emFkYTE8LXRhYmxlKHByb2Q0JEZFQ0hBLHByb2Q0JFBaQV9QUk9HKQ0Ka25pdHI6OmthYmxlKGNydXphZGExKQ0KDQpjcnV6YWRhMjwtdGFibGUocHJvZDQkTEFNSU5BU19QUk9DRVNBREFTLHByb2Q0JFRNT19NSU4pDQprbml0cjo6a2FibGUoY3J1emFkYTIpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgaW5zdGFsbC5wYWNrYWdlcygicHN5Y2giKQ0KbGlicmFyeShwc3ljaCkNCmRlc2NyaWJlKHByb2QpDQoNClZhcmlhYmxlcyA8LWMoIkNhbnRpZGFkIiApDQpNZWRpYSA8LWMoIjYuNzAiICkNCk1lZGlhbmEgPC1jKCIyIiApDQpEZXN2aWFjaW9uX2VzdGFuZGFyIDwtYygiMTEuODUiICkNCg0KdGFibGUxIDwtIGRlc2NyaWJlKHByb2QpDQprbml0cjo6a2FibGUodGFibGUxKQ0KYGBgDQoNCg0KIyA8c3BhbiBzdHlsZT0iQ29sb3I6ICNFNDE5NjkiPiAqKk1FUk1BKioNCg0KIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojRTQxOTY5Ij4gKipFc2NvZ2VyIGxhIGJhc2UgZGF0b3MqKg0KDQpgYGB7cn0NCiMgZmlsZS5jaG9vc2UoKQ0KbWVybWEgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcc29maWFcXE9uZURyaXZlXFxEb2N1bWVudG9zXFxSRVRPXFxGT1JNIC0gTWVybWEuY3N2IikNCmBgYA0KDQo+IEVudGVuZGVtb3MgbGEgYmFzZSBkZSBkYXRvcw0KDQpgYGB7cn0NCnJlc3VtZW4gPC0gc3VtbWFyeShtZXJtYSkNCnJlc3VtZW4NCmBgYA0KDQojIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiAjRTQxOTY5Ij4gKipTRUNDSU9OIDEuIExpbXBpZXphLCBUcmFuc2Zvcm1hY2nDs24sIHkgT3JnYW5pemFjacOzbiBkZSBCYXNlcyBkZSBEYXRvcyoqDQoNCiMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiNERjcyOUQiPiAqKlTDqWNuaWNhIDEuIENvbnZlcnRpciB0aXBvcyBkZSBkYXRvcy4qKg0KDQojIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6I0RGNzI5RCI+ICoqQ29udmVydGlyIGRlIGNhcmFjdGVyIGEgZmVjaGEqKg0KDQo+IExhIGJhc2UgZGUgZGF0b3Mgbm8gY29udGVuw61hIG5pbmd1biBmb3JtYXRvLCBwb3IgbG8gcXVlIGVuIGVsIGFuYWxpc2lzIGxvcyBkYXRvcyBwb2TDrWFuIHRlbmVyIGVycm9yZXMgcG9yIHNlIGNvbnZpcnRpw7MgbGEgZmVjaGEgYSBmb3JtYXRvLg0KDQpgYGB7cn0NCmxpYnJhcnkodGliYmxlKQ0KbWVybWExIDwtIG1lcm1hDQptZXJtYTEkRmVjaGEgPC0gYXMuRGF0ZShtZXJtYTEkRmVjaGEsIGZvcm1hdCA9ICIlZC8lbS8lWSIpDQp0aWJibGUgKG1lcm1hMSkNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojREY3MjlEIj4gKipUw6ljbmljYSAyLiBSZW1vdmVyIHZhbG9yZXMgaXJyZWxldmFudGVzLioqDQoNCiMjIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojREY3MjlEIj4gKipFbGltaW5hciBjb2x1bW5hcyoqDQoNCj4gRW4gbGEgYmFzZSBkZSBkYXRvcyBzZSBjb250ZW7DrWEgbGEgZmVjaGEgeSBlbCBtZXMsIHBvciBsbyBxdWUgY29uc2lkZXJhbW9zIHF1ZSBlbCBtZXMgbm8gZXMgbmVjZXNhcmlvIHlhIHF1ZSB0ZW5lbW9zIGxhIGZlY2hhLCBhc2kgcXVlIGxvIGVsaW1pbmFtb3MgY29uIGxhIGZ1bmNpw7NuIGRlICpzdWJzZXQqLg0KDQpgYGB7cn0NCm1lcm1hMiA8LSBtZXJtYTENCm1lcm1hMiA8LSBzdWJzZXQgKG1lcm1hMiwgc2VsZWN0ID0gLWMgKE1lcykpDQpzdW1tYXJ5IChtZXJtYTIpDQpgYGANCiANCiMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiNERjcyOUQiPiAqKjEuwr9DdcOhbnRhcyB2YXJpYWJsZXMgeSBjdcOhbnRvcyByZWdpc3Ryb3MgdGllbmUgbGEgYmFzZSBkZSBkYXRvcz8qKg0KDQo+IDxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjojRTQxOTY5Ij4gUj0gNjAgcmVnaXN0cm9zIHkgMyB2YXJpYWJsZXMgPC9jZW50ZXI+DQoNCmBgYHtyfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJwc3ljaCIpDQpzdHIobWVybWEyKQ0KbGlicmFyeShwc3ljaCkNCmRlc2NyaWJlKG1lcm1hMikNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojREY3MjlEIj4gKioyLsK/Q2xhc2lmaWNhIGNhZGEgdmFyaWFibGUgZW4gY3VhbGl0YXRpdmEsIGN1YW50aXRhdGl2YSBkaXNjcmV0YSBvIGN1YW50aXRhdGl2YSBjb250aW51YS4/KioNCmBgYHtyfQ0KVmFyaWFibGU8LWMoIkZlY2hhIiwiS2lsb3MiKQ0KVHlwZTwtYygiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIikNCnRhYmxlPC1kYXRhLmZyYW1lKFZhcmlhYmxlLFR5cGUpDQprbml0cjo6a2FibGUodGFibGUpDQpgYGANCg0KIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6I0RGNzI5RCI+ICoqMy4gRWxpZ2UgbGEgZXNjYWxhIGRlIG1lZGljacOzbiBkZSBjYWRhIHZhcmlhYmxlLioqDQpgYGB7cn0NClZhcmlhYmxlPC1jKCJGZWNoYSIsIktpbG9zIikNClR5cGU8LWMoIkN1YW50aXRhdGl2YSBjb250aW51YSIsICJDdWFudGl0YXRpdmEgY29udGludWEiKQ0KRXNjYWxhX2RlX01lZGljacOzbiA8LSBjKCJSYXpvbiIsIlJhem9uIikNCnRhYmxlPC1kYXRhLmZyYW1lKFZhcmlhYmxlLFR5cGUsRXNjYWxhX2RlX01lZGljacOzbikNCmtuaXRyOjprYWJsZSh0YWJsZSkNCmBgYA0KDQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOkU0MTk2OSI+KipBbsOhbGlzaXMgRXhwbG9yYXRvcmlvIGRlIGxhcyBCYXNlcyBkZSBEYXRvcyoqDQoNCiMjIyMgVGFibGEgY29uIGxvcyBwcmluY2lwYWxlcyBlc3RhZMOtc3RpY29zIGRlc2NyaXB0aXZvcw0KDQojIyMjICoqRXN0YWTDrXN0aWNvcyBkZXNjcmlwdGl2b3MgTWVybWEqKg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgaW5zdGFsbC5wYWNrYWdlcygicHN5Y2giKQ0KbGlicmFyeShwc3ljaCkNCmRlc2NyaWJlKG1lcm1hMikNCg0KVmFyaWFibGVzIDwtYygiS2lsb3MiKQ0KTWVkaWEgPC1jKCIzNzA5LjUyIikNCk1lZGlhbmEgPC1jKCIzOTI1IikNCkRlc3ZpYWNpb25fZXN0YW5kYXIgPC1jKCIxMDIzLjk5IikNCmBgYA0KDQpgYGB7cn0NCnRhYmxlMiA8LWRhdGEuZnJhbWUoVmFyaWFibGVzLCBNZWRpYSwgTWVkaWFuYSwgRGVzdmlhY2lvbl9lc3RhbmRhcikNCmtuaXRyOjprYWJsZSh0YWJsZTIpDQpgYGANCg0KDQojIDxzcGFuIHN0eWxlPSJDb2xvcjpSRUQiPiAqKlNDUkFQKioNCg0KIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjpSRUQiPiAqKkVzY29nZXIgbGEgYmFzZSBkYXRvcyoqDQoNCmBgYHtyfQ0KIyBmaWxlLmNob29zZSgpDQpzY3JhcCA8LSByZWFkLmNzdigiQzpcXFVzZXJzXFxzb2ZpYVxcT25lRHJpdmVcXERvY3VtZW50b3NcXFJFVE9cXEZPUk0gLSBTY3JhcC5jc3YiKQ0KYGBgDQoNCj4gRW50ZW5kZW1vcyBsYSBiYXNlIGRlIGRhdG9zDQoNCmBgYHtyfQ0KcmVzdW1lbiA8LSBzdW1tYXJ5KHNjcmFwKQ0KcmVzdW1lbg0KYGBgDQoNCiMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6UkVEIj4gKipTRUNDSU9OIDEuIExpbXBpZXphLCBUcmFuc2Zvcm1hY2nDs24sIHkgT3JnYW5pemFjacOzbiBkZSBCYXNlcyBkZSBEYXRvcyoqDQoNCiMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiNGMTQzNDMiPiAqKlTDqWNuaWNhIDEuICBSZW1vdmVyIHZhbG9yZXMgaXJyZWxldmFudGVzKioNCg0KIyMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiNGMTQzNDMiPiAqKkVsaW1pbmFyIGNvbHVtbmFzKioNCg0KPiBMYSBiYXNlIGRlIGRhdG9zIGNvbnRlbsOtYSBSZWZlcmVuY2lhIGRlIEZvcm0sIHNpbiBlbWJhcmdvLCBwYXJhIG51ZXN0cm8gYW7DoWxpc2lzIHF1ZSBlc3RhbW9zIHJlYWxpemFuZG8gbm8gZXMgaW1wb3J0YW50ZSBwb3IgbG8gcXVlIHV0aWxpemFtb3MgbGEgZnVuY2nDs24gZGUgKnN1YnNldCogcGFyYSBlbGltaW5hciBsYSBjb2x1bW5hLg0KDQpgYGB7cn0NCnNjcmFwMSA8LSBzY3JhcA0Kc2NyYXAxPC1zdWJzZXQoc2NyYXAxLHNlbGVjdD0tYyhSZWZlcmVuY2lhKSkNCnN0cihzY3JhcDEpDQpgYGANCg0KIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6I0YxNDM0MyI+ICoqVMOpY25pY2EgMi4gRXJyb3JlcyB0aXBvZ3LDoWZpY29zIHkgZXJyb3JlcyBzaW1pbGFyZXMqKg0KDQojIyMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6I0YxNDM0MyI+ICoqQ2FudGlkYWRlcyBlbiBlbnRlcm9zKioNCg0KPiBFcyBpbXBvcnRhbnRlIHBhcmEgbnVlc3RybyBhbsOhbGlzaXMgcXVlIGxhIGJhc2UgZGUgZGF0b3MgbGFzIGNhbnRpZGFkZXMgZXN0dXZpZXJhbiBlbnRlcm9zIHlhIHF1ZSBzZSB0cmF0YW4gZGUgY2FudGlkYWQgZGUgcGllemFzIGRlIGNpZXJ0byBwcm9kdWN0byBwb3IgbG8gcXVlIHBhcmEgcXVlIGVsIGFuw6FsaXNpcyBzZWEgY29uZ3J1ZW50ZSBzZSBkZWJlbiB0ZW5lciBlbnRlcm9zLg0KDQpgYGB7cn0NCnNjcmFwMiA8LSBzY3JhcDENCnNjcmFwMiRDYW50aWRhZCA8LSBjZWlsaW5nIChzY3JhcDIkQ2FudGlkYWQpICANCnN1bW1hcnkoc2NyYXAyKSAgIA0KYGBgDQoNCiMjIyMgPHNwYW4gc3R5bGU9IkNvbG9yOiNGMTQzNDMiPiAqKjEuwr9DdcOhbnRhcyB2YXJpYWJsZXMgeSBjdcOhbnRvcyByZWdpc3Ryb3MgdGllbmUgbGEgYmFzZSBkZSBkYXRvcz8qKg0KDQo+IDxjZW50ZXI+IDxzcGFuIHN0eWxlPSJjb2xvcjpSRUQiPiBSPSAyNTEgcmVnaXN0cm9zIHkgNyB2YXJpYWJsZXMgPC9jZW50ZXI+DQoNCmBgYHtyfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJwc3ljaCIpDQpzdHIoc2NyYXAyKQ0KbGlicmFyeShwc3ljaCkNCmRlc2NyaWJlKHNjcmFwMikNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojRjE0MzQzIj4gKiozLsK/Q2xhc2lmaWNhIGNhZGEgdmFyaWFibGUgZW4gY3VhbGl0YXRpdmEsIGN1YW50aXRhdGl2YSBkaXNjcmV0YSBvIGN1YW50aXRhdGl2YSBjb250aW51YS4/KioNCmBgYHtyfQ0KVmFyaWFibGU8LWMoIkZlY2hhIiwiUHJvZHVjdG8iLCJDYW50aWRhZCIsIlVuaWRhZC5kZS5tZWRpZGEiLCAiVWJpY2FjacOzbi5kZS5vcmlnZW4iLCJVYmljYWNpw7NuLmRlLmRlc2VjaG8iLCJFc3RhZG8iKQ0KVHlwZTwtYygiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwgIkN1YWxpdGF0aXZhIiwgIkN1YW50aXRhdGl2YSBjb250aW51YSIsICJDdWFsaXRhdGl2YSIsICJDdWFsaXRhdGl2YSIsIkN1YWxpdGF0aXZhIiwiQ3VhbGl0YXRpdmEiKQ0KdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSkNCmtuaXRyOjprYWJsZSh0YWJsZSkNCmBgYA0KDQojIyMjIDxzcGFuIHN0eWxlPSJDb2xvcjojRjE0MzQzIj4gKio0LiBFbGlnZSBsYSBlc2NhbGEgZGUgbWVkaWNpw7NuIGRlIGNhZGEgdmFyaWFibGUuKioNCmBgYHtyfQ0KVmFyaWFibGU8LWMoIkZlY2hhIiwiUHJvZHVjdG8iLCJDYW50aWRhZCIsIlVuaWRhZC5kZS5tZWRpZGEiLCAiVWJpY2FjacOzbi5kZS5vcmlnZW4iLCJVYmljYWNpw7NuLmRlLmRlc2VjaG8iLCJFc3RhZG8iKQ0KVHlwZTwtYygiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwgIkN1YWxpdGF0aXZhIiwgIkN1YW50aXRhdGl2YSBjb250aW51YSIsICJDdWFsaXRhdGl2YSIsICJDdWFsaXRhdGl2YSIsIkN1YWxpdGF0aXZhIiwiQ3VhbGl0YXRpdmEiKQ0KRXNjYWxhX2RlX01lZGljacOzbiA8LSBjKCJJbnRlcnZhbG8iLCJOb21pbmFsIiwiRGlzY3JldGEiLCJOb21pbmFsIiwgIk5vbWluYWwiLCJOb21pbmFsIiwgIk5vbWluYWwiKQ0KdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSxFc2NhbGFfZGVfTWVkaWNpw7NuKQ0Ka25pdHI6OmthYmxlKHRhYmxlKQ0KYGBgDQoNCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6UkVEIj4qKkFuw6FsaXNpcyBFeHBsb3JhdG9yaW8gZGUgbGFzIEJhc2VzIGRlIERhdG9zKioNCg0KIyMjIyBUYWJsYSBjb24gbG9zIHByaW5jaXBhbGVzIGVzdGFkw61zdGljb3MgZGVzY3JpcHRpdm9zDQoNCiMjIyMgKipFc3RhZMOtc3RpY29zIGRlc2NyaXB0aXZvcyBTY3JhcCoqDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIGluc3RhbGwucGFja2FnZXMoInBzeWNoIikNCmxpYnJhcnkocHN5Y2gpDQpkZXNjcmliZShzY3JhcDIpDQoNClZhcmlhYmxlcyA8LWMoIkNhbnRpZGFkIiApDQpNZWRpYSA8LWMoIjYuNzAiICkNCk1lZGlhbmEgPC1jKCIyIiApDQpEZXN2aWFjaW9uX2VzdGFuZGFyIDwtYygiMTEuODUiICkNCg0KdGFibGUxIDwtZGF0YS5mcmFtZShWYXJpYWJsZXMsIE1lZGlhICwgTWVkaWFuYSAsIERlc3ZpYWNpb25fZXN0YW5kYXIpDQprbml0cjo6a2FibGUodGFibGUxKQ0KYGBgDQoNCg0KIyA8c3BhbiBzdHlsZT0iQ29sb3I6T1JBTkdFIj4gKipTRUNDSU9OIDIuIEFuw6FsaXNpcyBFeHBsb3JhdG9yaW8gZGUgbGFzIEJhc2VzIGRlIERhdG9zKioNCg0KIyMjIEJhciBwbG90cw0KDQojIyMjICoqUFJPRFVDQ0nDk04qKiANCmBgYHtyfQ0KYmFycGxvdChwcm9wLnRhYmxlKHRhYmxlKHByb2Q0JExBTUlOQVNfUFJPQ0VTQURBUykpLGNvbD1jKCJvcmFuZ2UiKSxtYWluPSJMYW1pbmFzIHByb2Nlc2FkYXMiLHhsYWIgPSAiTGFtaW5hcyIsIHlsYWIgPSJGcmVjdWVuY2lhcyIsbGFzPTEpDQpgYGANCg0KIyMjIyAqKlNDUkFQKiogDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShwbHlyKQ0KcGllKHByb3AudGFibGUodGFibGUoc2NyYXAyJFViaWNhY2nDs24uZGUub3JpZ2VuKSksY29sPWMoImxpZ2h0Z3JlZW4iLCJibHVlIiwicmVkIiksbWFpbj0iVWJpY2FjacOzbiBkZSBvcmlnZW4iLGxhcz0xKQ0KYGBgDQoNCiMjIyMgKipERUxJVkVSWSBQTEFOOiBQUklOQ0lQQUxFUyBDTElFTlRFUzogUFJJTkNJUEFMRVMgQ0xJRU5URVMqKg0KPiBDb24gbGEgc2lndWllbnRlIGZ1bmNpw7NuIHBvZHJlbW9zIGlkZW50aWZpY2FyIGxvcyBwcmluY2lwYWxlcyBjbGllbnRlcyBwYXJhIGdlbmVyYXIgdW4gYW7DoWxpc2lzIGNvbiBsYSBpbmZvcm1hY2nDs24gcmVsZXZhbnRlLCBwdWVzIGhheSBjbGllbnRlcyBjb24gcG9jb3MgbyBzaW4gcGVkaWRvcyBwb3IgbG8gcXVlIGdlbmVyYXIgdW4gZGlhZ27Ds3N0aWNvIHJlc3BlY3RvIGEgZGVsaXZlcnkgcGxhbiBjb24gZXNvcyBkYXRvcyBubyBlcyBuZWNlc2FyaW8uIA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KZ2dwbG90KGRldnBsYW4xLCBhZXMoeD1yZW9yZGVyKENMSUVOVEUsUGVkaWRvcyksIHk9UGVkaWRvcykpICsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsNCiAgY29vcmRfZmxpcCgpDQpgYGANCg0KIyMjIyAqKlJFQ1VSU09TIEhVTUFOT1M6IENPTEFCT1JBRE9SRVMgQUNUVUFMRVMqKg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBhcy5kYXRhLmZyYW1lKGJhamFzKQ0KIyBhcy5kYXRhLmZyYW1lKGNvbGFiKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCmNvbGFiPC1jb2xhYiAlPiUgZHBseXI6OnNlbGVjdChnZW5lcm8sZWRhZCxzYWxhcmlvX2RpYXJpbykgJT4lICBkcGx5cjo6Z3JvdXBfYnkoZ2VuZXJvKSAlPiUNCiAgZHBseXI6OnN1bW1hcmlzZShhY3Jvc3MoZXZlcnl0aGluZygpLG1lYW4sbmEucm09VFJVRSkpICU+JSBhcnJhbmdlKGRlc2MoZWRhZCkpDQpnZ3Bsb3QoY29sYWIsIGFlcyh4PXJlb3JkZXIoZ2VuZXJvLGVkYWQpLCB5PWVkYWQsIGZpbGw9KHNhbGFyaW9fZGlhcmlvKSkpICsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLGNvbD1jKCJibGFjayIpKSsNCiAgY29vcmRfZmxpcCgpKw0KICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQocmV2ZXJzZT1GQUxTRSkpDQpgYGANCg0KPiBMYSBwcmltZXJhIGdyw6FmaWNhIGRlIGJhcnJhcyBub3MgZGEgYSBjb25vY2VyIHNvYnJlIGVsIHNhbGFyaW8gZGlhcmlvIGRlIGxhcyBwZXJzb25hcyBkZSBGb3JtLCBzZWdtZW50YWRvIHBvciBlZGFkIHkgcG9yIGfDqW5lcm8uIExvIHF1ZSBub3MgZGEgYSBjb25vY2VyIGVzIHF1ZSBlbiBsYSBlbXByZXNhIGV4aXN0ZSB1biBtYXlvciByYW5nbyBkZSBlZGFkIGVudHJlIGxhcyBtdWplcmVzIGRlIEZvcm0sIGxsZWdhbmRvIGEgc2VyIGNhc2kgNDAgbG8gbWF5b3I7IHBvciBvdHJhIHBhcnRlLCBsb3MgIGhvbWJyZXMgcHJlc2VudGFuIHVuIG1lbm9yIHJhbmdvLCBjb24gdW4gbcOheGltbyBkZSAoYXByb3gpIDMzLiBJZ3VhbG1lbnRlLCB2ZW1vcyBxdWUgZW4gcHJvbWVkaW8gbGFzIG11amVyZXMgZ2FuYW4gNjAgY2VudGF2b3MgbcOhcyBxdWUgbG9zIGhvbWJyZXMuDQoNCg0KIyMjIyAqKlJFQ1VSU09TIEhVTUFOT1M6IEJBSkFTKioNCg0KYGBge3J9DQoNCmJhamFzPC1iYWphcyAlPiUgZHBseXI6OnNlbGVjdChtb3Rpdm9fYmFqYSxlZGFkLGR1cmFjaW9uKSAlPiUgZ3JvdXBfYnkobW90aXZvX2JhamEpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXNlKGFjcm9zcyhldmVyeXRoaW5nKCksbWVhbixuYS5ybT1UUlVFKSkgJT4lIGFycmFuZ2UoZGVzYyhlZGFkKSkNCmdncGxvdChiYWphcywgYWVzKHg9cmVvcmRlcihtb3Rpdm9fYmFqYSxlZGFkKSwgeT1lZGFkLCBmaWxsPShkdXJhY2lvbikpKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixjb2w9YygiYmxhY2siKSkrDQogIGNvb3JkX2ZsaXAoKSsNCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHJldmVyc2U9RkFMU0UpKQ0KYGBgDQoNCj4gVmllbmRvIGFob3JhIGxvcyBjb2xhYm9yYWRvcmVzIHF1ZSBoYW4gc2lkbyBkYWRvcyBkZSBiYWphIGVuIGxhIGVtcHJlc2EsIHZlbW9zIHF1ZSBsYSBncmFuIHBhcnRlIGRlIGxvcyBxdWUgc2UgaGFuIHNhbGlkbyBkZSBGb3JtIHRpZW5lbiBtZW5vcyBkZSAzMCBhw7Fvcy4gUG9jb3MgY2Fzb3MgaGFuIHNpZG8gZGUganViaWxhY2nDs24sIGxsZWdhbmRvIGEgbcOhcyBkZSA2MCBlbiByYW5nby4gSWd1YWxtZW50ZSwgYSBwYXJ0aXIgZGUgbGEgZ3LDoWZpY2EgdmVtb3MgcXVlIGxhcyByYXpvbmVzIHByaW5jaXBhbGVzIHNvbiBwb3IgYWJhbmRvbm8geSAgYmFqYSBwb3IgZmFsdGFzOyBkdXJhbmRvIG1lbm9zIGRlIDUwMCBkw61hcyBlbiBzdSB0cmFiYWpvLiANCg0KIyMjIERpc3BlcnNpb24gcGxvdHMgIA0KDQojIyMjICoqUFJPRFVDQ0nDk04qKiANCmBgYHtyfQ0KcGxvdChwcm9kNCRUTU9fTUlOLCB4bGFiID0gIlByb2Nlc28gZGUgbGFtaW5hIiwgeWxhYiA9ICJUaWVtcG8iLCBtYWluID0gIlRpZW1wbyBwb3IgTGFtaW5hIiApDQpgYGANCg0KIyMjIyAqKk1FUk1BKioNCmBgYHtyfQ0KZ2dwbG90KG1lcm1hMiwgYWVzKHg9IEZlY2hhLCB5PSBLaWxvcykpICsgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBmaWxsPSJyZWQiKSArIHNjYWxlX2ZpbGxfZ3JleSgpICsgbGFicyh0aXRsZSA9ICJLaWxvcyBkZSBtZXJtYSIsIHggPSAiRmVjaGEiKQ0KYGBgDQoNCj4gUG9kZW1vcyB2ZXIgY29tbyBlbiBpbmljaW9zIGRlIEZlYnJlcm8gYSBBYnJpbCB0ZW5lbW9zIGxhIG1heW9yIGNhbnRpZGFkIGRlIGtpbG9zIGRlIG1lcm1hLCBxdWUgaW5jbHVzbyBwYXNhIGRlbCBwcm9tZWRpbyBkZSBsb3MgZGVtYXMgbWVzZXMsIHBvciBsbyBxdWUgZXMgaW1wb3J0YW50ZSBhbmFsaXphciBxdWUgZmFjdG9yIGhpem8gcXVlIGR1cmFudGUgZXNlIHBlcmlvZG8gaHViaWVyYSBtw6FzIG1lcm1hLiAgDQoNCmBgYHtyfQ0KbWVybWEyJEZlY2hhIDwtIGFzLkRhdGUobWVybWEyJEZlY2hhLCBmb3JtYXQgPSAiJWQvJW0vJVkiKQ0KcGxvdChtZXJtYTIkRmVjaGEsIG1lcm1hMiRLaWxvcywgbWFpbiA9ICJLaWxvcyBkZSBtZXJtYSIsDQogICAgIHhsYWIgPSAiRmVjaGEiLCB5bGFiID0gIktpbG9zIiwNCiAgICAgcGNoID0gMTksIGZyYW1lID0gRkFMU0UpDQpgYGANCg0KPiBDb21vIHBvZGVtb3Mgb2JzZXJ2YXIgaGF5IG1hcyBkaXNwZXJzacOzbiBlbiBzZXB0aWVtYnJlLCBsb3MgZGVtw6FzIG1lc2VzIGhhIHRlbmlkbyBlbiBwcm9tZWRpbyBsYSBtaXNtYSBjYW50aWRhZCBkZSBtZXJtYS4gIA0KDQojIyMjICoqU0NSQVAqKiANCmBgYHtyfQ0KaGlzdChzY3JhcDIkQ2FudGlkYWQsIG1haW4gPSAiQ2FudGlkYWQgZGUgTWF0ZXJpYWwgcmVjaWNsYWRvIiwgeGxhYiA9ICJDYW50aWRhZCIsIHlsYWIgPSAiRnJlY3VlbmNpYSIsY29sID0gImJsdWUiKQ0KYGBgDQoNCj4gQ29uIGVzdGUgaGlzdG9ncmFtYSBub3MgbXVlc3RyYSBxdWUgZW50cmUgMCBhIDEwIFRvbmVsYWRhcyBlcyBsbyBxdWUgbWFzIHNlIGZyZWN1ZW50YSBhIHJlY2ljbGFyIGVsIG1hdGVyaWFsLiANCg0KDQojIyMjICoqREVMSVZFUlkgUExBTioqDQoNCiMjIyMgKlBlZGlkb3MqDQpgYGB7cn0NCnBsb3QoZGV2cGxhbjEkRmVjaGEsIGRldnBsYW4xJFBlZGlkb3MsIG1haW4gPSAiUGVkaWRvcyBwb3IgZmVjaGEiLA0KICAgICB4bGFiID0gIkZlY2hhIiwgeWxhYiA9ICJQZWRpZG9zIiwNCiAgICAgcGNoID0gMSwgZnJhbWUgPSBGQUxTRSkNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QoZGV2cGxhbjEkUGVkaWRvcywgbWFpbiA9ICJQZWRpZG9zIikNCmBgYA0KDQo+IENvbW8gcHJpbWVyIGJveHBsb3Qgdmltb3MgbG9zIHBlZGlkb3MgeSBsYSBncmFuIGRpc3BlcnNpw7NuIHF1ZSBoYXkgZW50cmUgcGVkaWRvcywgcHVlcyBkZXRlY3RhbW9zIHVuYSBmcmVjdWVuY2lhIGVuIGRvbmRlIGhheSBjbGllbnRlcyBxdWUgZ2VuZXJhbiBwZWRpZG9zIG9idmlhbWVudGUgZGlmZXJlbnRlcyBjb21vIHBhcmEgdGVuZXIgdW5hIG1lZGlhbmEgbyB1bmEgZGlzcGVyc2nDs24gcG9zaXRpdmEuICANCg0KIyMjIyAqQ2xpZW50ZXMqDQoNCmBgYHtyfQ0KZGV2cGxhbjIgPC0gZGV2cGxhbjENCmRldnBsYW4yJENMSUVOVEU8LWFzLmZhY3RvcihkZXZwbGFuMiRDTElFTlRFKQ0KZ2dwbG90KGRldnBsYW4yLCBhZXMoeD1DTElFTlRFLCB5PVBlZGlkb3MpKSArIA0KICBnZW9tX2JveHBsb3QoY29sb3I9InJlZCIsIGZpbGw9Im9yYW5nZSIsIGFscGhhPTAuMikNCmBgYA0KDQo+IEVuIGVsIGdyw6FmaWNvIGFudGVyaW9yIHBvZGVtb3Mgb2JzZXJ2YXIgYSBsb3MgNiBjbGllbnRlcyBjb24gbWF5b3IgcHJlc2VuY2lhIGVuIEZPUk0gZW4gY3VhbnRvIGEgRGVsaXZlcnkgUGxhbiBlbiBkb25kZSBlbCBvYmpldGl2byBlcyB2ZXIgbGEgZGlzcGVyc2nDs24geSBsYSBkaXN0cmlidWNpw7NuIGVudHJlIGNhZGEgdW5vIHkgcmVzcGVjdG8gYSBsb3MgcHJvbsOzc3RpY29zIGluZGl2aWR1YWxlcy4gIA0KDQojIyMgVGltZSBzZXJpZXMgcGxvdHMgDQoNCiMjIyMgKipESVNUUklCVUNJw5NOKiogDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpnZ3Bsb3QoZGV2cGVyMixhZXMoeD1mZWNoYSwgeT1kZWxheV9wZXJmb3JtYW5jZSxjb2xvcj1jbGllbnRlKSkrDQogIGdlb21fbGluZSgpKw0KICBsYWJzKHg9IkZlY2hhIix5PSJSZXRyYXNvIGVuIE1pbnV0b3MiLCBjb2xvcj0iTGVnZW5kIikrDQogIGdndGl0bGUoIlJldHJhc29zIGVuIGVsIGRlc2VtcGXDsW8gcG9yIHBhcnRlIGRlbCBjbGllbnRlIikNCmBgYA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KZGV2cGVyMiA8LSBkZXZwZXIyW2RldnBlcjIkY2xpZW50ZSE9Ik1hZ25hIixdDQpkZXZwZXIyIDwtIGRldnBlcjJbZGV2cGVyMiRjbGllbnRlIT0iVmFycm9jIixdDQoNCmdncGxvdChkZXZwZXIyLGFlcyh4PWZlY2hhLCB5PWRlbGF5X3BlcmZvcm1hbmNlLGZpbGw9Y2xpZW50ZSkpKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MzMsbGluZXR5cGU9ImRhc2hlZCIsY29sb3I9ImJsYWNrIikrDQogIGxhYnMoeD0iRmVjaGEiLHk9IlJldHJhc28gZW4gbWludXRvcyIsIGNvbG9yPSJMZWdlbmQiKSsNCiAgZ2d0aXRsZSgiUmV0cmFzb3MgZW4gZWwgZGVzZW1wZcOxbyBwb3IgcGFydGUgZGVsIGNsaWVudGUiKQ0KYGBgDQoNCj4gQSBwZXNhciBkZSBxdWUgZXN0YSBkaW1pbnV0ZW5kbyBlbCByZXRyYXNvIGNvbiBlbCBjbGllbnRlIE1haGxlIHNlZ3VpbW9zIHZpZW5kbyBxdWUgc2UgZW5jdWVudHJhIHBvciBhcnJpYmEgZGVsIHByb21lZGlvLg0KDQojIyMgSGFsbGF6Z29zDQoNCjEuIE51ZXN0cm8gdG9wIDMgY2xpZW50ZXMgZGUgcHJvZHVjY2nDs24gc29uIFNUQUJJTFVTIDEsIFNUQUJJTFVTIDMgeSBUUk1YLg0KDQoyLiBUcmFlbW9zIHVuIHJldHJhc28gbWF5b3IgZW4gZGlzdHJpYnVjacOzbiBjb24gZWwgY2xpZW50ZSBNYWhsZSwgYXJyaWJhIGRlbCBwcm9tZWRpbyBsbGVnYW5kbyBpbmNsdXNvIGEgdGllbXBvcyBkZSAxIGhvcmEgY29uIDQwIG1pbnV0b3MuDQoNCjMuIFNlIHRpZW5lbiBzb2JyZXBlZGlkb3MgKGFycmliYSBkZWwgcHJvbWVkaW8pIHkgZXN0byBwdWVkZSBhZmVjdGFyIHNpIG5vIHNlIHRpZW5lbiBsYSBjYXBhY2lkYWQgcGFyYSByZWNpYmlyIHBlZGlkb3MgZGUgbcOhcy4gIA0KDQo0LiBEZW50cm8gZGUgUkggdGVuZW1vcyBtw6FzIGJhamFzIHBvciBkaXN0aW50b3MgbW90aXZvczogZW4gcHJpbWVyIGx1Z2FyIGVzdGEgcG9yIEp1YmlsYWNpw7NuLCBlbiBzZWd1bmRvIGx1Z2FyIFJlbnVuY2lhIHZvbHVudGFyaWEgeSBlbiB0ZXJjZXIgbHVnYXIgQmFqYSBwb3IgRmFsdGFzLg0KDQojIDxzcGFuIHN0eWxlPSJDb2xvcjpPUkFOR0UiPiAqKlByZWRpY2Npw7NuIGRlbCBEZXNlbXBlw7FvIGRlIGxhIEluZHVzdHJpYSBBdXRvbW90cml6ICoqDQoNCiMjIyA8c3BhbiBzdHlsZT0iQ29sb3I6ICMxOTQxRTQiPiAqKkVzY29nZXIgbGEgYmFzZSBkYXRvcyoqDQoNCmBgYHtyfQ0KIyBmaWxlLmNob29zZSgpDQpiZGV4IDwtIHJlYWQuY3N2KCJDOlxcVXNlcnNcXHNvZmlhXFxEb3dubG9hZHNcXHVzX21vdG9yX3Byb2R1Y3Rpb25fYW5kX2RvbWVzdGljX3NhbGVzMS5jc3YiKQ0KYGBgDQoNCj4gRW50ZW5kZW1vcyBsYSBiYXNlIGRlIGRhdG9zDQoNCmBgYHtyfQ0KcmVzdW1lbjEgPC0gc3VtbWFyeShiZGV4KQ0KcmVzdW1lbjENCmBgYA0KDQpTZSBjYW1iaWFuIGxvcyBub21icmVzIGRlIGxhcyBjb2x1bW5hcy4gDQpgYGB7cn0NCm5hbWVzIChiZGV4KSA9IGMoImHDsW8iLCAicHJvZF90b3RhbCIsICJwcm9kX3Bhc3NlbmdlciIsICJwcm9kX3ZlaF9jb21lcmNpYWxlcyIsICJ2ZW50YXNfZG9tZXN0aWNhcyIsICJ2ZW50YXNfcGFzc2VuZ2VyIiwidmVudGFzX2NvbWVyY2lhbGVzIiwiZGVzZW1wbGVvX3VzYSIsImNvbmZpYW56YV9jb25zX3VzYSIsInNhbGFyaW9faG9yYV9taW5fdXNhIikNCm5hbWVzIChiZGV4KQ0Kc3RyKGJkZXgpDQpgYGANCg0KIyMjICoqUHJpbWVyIG1vZGVsbyBkZSByZWdyZXNpw7NuKioNCkVuIGVzdGUgY2Fzbywgc2UgZXNjb2dlIGNvbW8gdmFyaWFibGUgZGVwZW5kaWVudGUgbGFzIHZlbnRhcyBkZSBsb3MgY2Fycm9zICpwYXNzZW5nZXIqLCBwb3IgZWxsbyBlbnRpw6luZGFzZSBsb3MgYXV0b23Ds3ZpbGVzIGRlIHVzbyBjb3RpZGlhbm8gZW4gRXN0YWRvcyBVbmlkb3MuIFBhcmEgZXN0YSB2YXJpYWJsZSBkZXBlbmRpZW50ZSwgc2UgaGFuIHRvbWFkbyBsYXMgc2lndWllbnRlcyB2YXJpYWJsZXMgaW5kZXBlbmRpZW50ZXMsIGNvbiBlbCBmaW4gZGUgbm90YXIgc3UgZWZlY3RvIGVuIGxhcyB2ZW50YXMuIEVzdGFzIHNvbjogIA0KDQoxLiBEZXNlbXBsZW8gVVNBOiBlc3RlIMOtbmRpY2UgZXMgY2FsY3VsYWRvIGFudWFsbWVudGUgY29uIGxhIGZvcm11bGEuIChVbmVtcGxveWVkIMO3IExhYm9yIEZvcmNlKSB4IDEwMC4gRW50cmUgbWVub3IgbWVqb3IuIA0KDQoyLiBDb25maWFuemEgZGVsIGNvbnN1bWlkb3IgZGUgVVNBOiDDrW5kaWNlIHF1ZSBtaWRlLCBhIHBhcnRpciBkZSB1bmEgZW5jdWVzdGEgcXVlIHRhbiBvcHRpbWlzdGFzIG8gcGVzaW1pc3RhcyBzZSBlbmN1ZW50cmFuIGxvcyBjb25zdW1pZG9yZXMgc29icmUgc3Ugc2l0dWFjacOzbiBmaW5hbmNpZXJhLiBFbnRyZSBtYXlvciwgbWVqb3IuIA0KDQozLiBTYWxhcmlvIG3DrW5pbW8gcG9yIGhvcmE6IHNlIG1pZGUgZW4gZMOzbGFyZXMuIEVzdMOhIGVzdGFibGVjaWRvIGEgbml2ZWwgZmVkZXJhbC4gDQoNCjQuIEHDsW86IGxvcyBhw7FvcyBxdWUgc2UgdGllbmVuIGRlIGxvcyBkYXRvcywgMjAwNy0yMDIwLiANCg0KDQpgYGB7cn0NCnJlZ3Jlc2lvbjEgPC0gbG0gKHZlbnRhc19wYXNzZW5nZXIgfiBkZXNlbXBsZW9fdXNhICsgY29uZmlhbnphX2NvbnNfdXNhICsgc2FsYXJpb19ob3JhX21pbl91c2EgKyBhw7FvLCBkYXRhPWJkZXgpDQpzdW1tYXJ5IChyZWdyZXNpb24xKQ0KYGBgDQo+ICBQYXJhIGxhIHRhc2EgZGUgZGVzZW1wbGVvIHkgZWwgw61uZGljZSBkZSBjb25maWFuemEgZGVsIGNvbnN1bWlkb3IsIHNlIGhhIGRlY2lkaWRvIHRvbWFyIGVsICpwcm9tZWRpbyogZGVsIDIwMDcgYWwgMjAyMCwgcGFyYSBwb2RlciBwcmVkZWNpci4gQ29uIGVsIHNhbGFyaW8gbcOtbmltbyBwb3IgaG9yYSwgYWwgc2VyIGVzdGFibGVjaWRvIGEgbml2ZWwgZmVkZXJhbCwgc2UgdG9tYSBlbiBjdWVudGEgbGEgw7psdGltYSBjYW50aWRhZDogJDcuMjUgZMOzbGFyZXMuIFNlIHF1aWVyZW4gbGFzIHByZWRpY2Npb25lcyBwYXJhIGxvcyBzaWd1aWVudGVzIGNpbmNvIGHDsW9zLCBhIHBhcnRpciBkZWwgw7psdGltbyBhw7FvIGNvbiBkYXRvcyAoMjAyMCkuDQoNCmBgYHtyfQ0KZGF0b3NfbnVldm9zMSA8LSBkYXRhLmZyYW1lKGRlc2VtcGxlb191c2E9Ni40Myxjb25maWFuemFfY29uc191c2E9ODIuMyxzYWxhcmlvX2hvcmFfbWluX3VzYT03LjI1LGHDsW89MjAyMToyMDI1KQ0KcHJlZGljdChyZWdyZXNpb24xLGRhdG9zX251ZXZvczEpDQpgYGANCg0KKirCv1F1w6kgb2JzZXJ2YW1vcz8qKg0KDQpgYGB7cn0NCnByaW1lciA8LSBwbG90KHByZWRpY3QocmVncmVzaW9uMSxkYXRvc19udWV2b3MxKSwgdHlwZSA9ICJsIiwgeGxhYiA9ICJBw7FvIiwgIHlsYWIgPSJWZW50YXMgUGFzc2VuZ2VyIiwgIG1haW49IlByZWRpY2Npw7NuIGRlIFZlbnRhcyIpDQpgYGANCg0KPiBFbiBlc3RhIHByZWRpY2Npw7NuIGRlIHZlbnRhcyBkZSBhdXRvbcOzdmlsZXMgKnBhc3NlbmdlciosIG9ic2VydmFtb3MgcXVlIGVzIGhhY2lhIGFiYWpvLiBFcyBkZWNpciwgdG9tYW5kbyBlbiBjdWVudGEgdW5hIHRhc2EgZGUgZGVzZW1wbGVvICBkZSA2LjQzLCB1biDDrW5kaWNlIGRlIGNvbmZpYW56YSBkZSA4Mi4zIHkgZWwgc2FsYXJpbyBtw61uaW1vIHBvciBob3JhIGRlICQ3LjI1LCBzZSBlc3BlcmEgcXVlIGxhcyB2ZW50YXMgZGUgZXN0b3MgYXV0b23Ds3ZpbGVzICoqYmFqZW4qKiBlbiBFVUEgZGVsIDIwMjEgaGFzdGEgMjAyNS4gSWd1YWxtZW50ZSwgcmVzdWx0YSBkZXN0YWNhYmxlIG1lbmNpb25hciBxdWUgbGFzICB2YXJpYWJsZXMgcXVlIG3DoXMgaW1wYWN0YW4gZW4gbGFzIHZlbnRhcyBkZSBhdXRvbcOzdmlsZXMgKnBhc3Nlbmdlciogc29uIGVsIGHDsW8geSBlbCBzYWxhcmlvIG3DrW5pbW8uDQoNCmBgYHtyfQ0KZWZmZWN0X3Bsb3QocmVncmVzaW9uMSxwcmVkPWRlc2VtcGxlb191c2EsaW50ZXJ2YWw9VFJVRSkNCmBgYA0KDQo+IFNpIHRvbWFtb3MgZW4gY3VlbnRhIGxhIHRhc2EgZGUgZGVzZW1wbGVvIGRlIEVVQSwgeSBzdSByZWxhY2nDs24gY29uIGxhcyB2ZW50YXMgZGUgbG9zIGF1dG9tw7N2aWxlcyAqcGFzc2VuZ2VyKiwgb2JzZXJ2YW1vcyBxdWUgZXN0YSBlcyBuZWdhdGl2YS4gRGViaWRvIGEgcXVlIGFsIGNyZWNlciBsYSB0YXNhIGRlIGRlc2VtcGxlbywgYmFqYW4gbGFzIHZlbnRhcy4gDQoNCg0KYGBge3J9DQplZmZlY3RfcGxvdChyZWdyZXNpb24xLHByZWQ9Y29uZmlhbnphX2NvbnNfdXNhLGludGVydmFsPVRSVUUpDQpgYGANCj4gTWllbnRyYXMgcXVlIGVsIMOtbmRpY2UgZGUgY29uZmlhbnphIGRlbCBjb25zdW1pZG9yIGRlIEVVQSwgeSBzdSByZWxhY2nDs24gY29uIGxhcyB2ZW50YXMgZGUgbG9zIGF1dG9tw7N2aWxlcyAqcGFzc2VuZ2VyKiwgb2JzZXJ2YW1vcyBxdWUgZXN0YSBlcyBwb3NpdGl2YS4gRGViaWRvIGEgcXVlIGFsIGNyZWNlciBsYSBjb25maWFuemEsIGluY3JlbWVudGFuIGxhcyB2ZW50YXMuIA0KDQoNCmBgYHtyfQ0KZWZmZWN0X3Bsb3QocmVncmVzaW9uMSxwcmVkPXNhbGFyaW9faG9yYV9taW5fdXNhLGludGVydmFsPVRSVUUpDQpgYGANCg0KPiBJZ3VhbG1lbnRlLCBhbCBzdWJpciBlbCBzYWxhcmlvIG3DrW5pbW8gcG9yIGhvcmEsIGxhcyB2ZW50YXMgZGUgbG9zIGF1dG9tw7N2aWxlcyAqcGFzc2VuZ2VyKiBpbmNyZW1lbnRhbi4gDQoNCmBgYHtyfQ0KZWZmZWN0X3Bsb3QocmVncmVzaW9uMSxwcmVkPWHDsW8saW50ZXJ2YWw9VFJVRSkNCmBgYA0KDQo+IENvbiBlbCBwYXNhciBkZSBsb3MgYcOxb3MgbGFzIHZlbnRhcyBoYW4gZGVjcmVjaWRvLiANCg0KIyMjICoqU2VndW5kbyBtb2RlbG8gZGUgcmVncmVzacOzbioqDQpFbiBlc3RlIGNhc28sIHNlIGVzY29nZSBjb21vIHZhcmlhYmxlIGRlcGVuZGllbnRlIGxhcyB2ZW50YXMgZGUgbG9zIGNhcnJvcyAqY29tZXJjaWFsZXMqLCBwb3IgZWxsbyBlbnRpw6luZGFzZSBsb3MgY3VhbHF1aWVyIHRpcG8gZGUgdmVow61jdWxvIGRlIG1vdG9yIHV0aWxpemFkbyBwYXJhIHRyYW5zcG9ydGFyIG1lcmNhbmPDrWFzIG8gcGFzYWplcm9zIGVuIEVzdGFkb3MgVW5pZG9zLiBQYXJhIGVzdGEgdmFyaWFibGUgZGVwZW5kaWVudGUsIHNlIGhhbiB0b21hZG8gbGFzIHNpZ3VpZW50ZXMgdmFyaWFibGVzIGluZGVwZW5kaWVudGVzLCBjb24gZWwgZmluIGRlIG5vdGFyIHN1IGVmZWN0byBlbiBsYXMgdmVudGFzLiBFc3RhcyBzb246ICANCjEuIERlc2VtcGxlbyBVU0E6IGVzdGUgw61uZGljZSBlcyBjYWxjdWxhZG8gYW51YWxtZW50ZSBjb24gbGEgZm9ybXVsYS4gKFVuZW1wbG95ZWQgw7cgTGFib3IgRm9yY2UpIHggMTAwLiBFbnRyZSBtZW5vciBtZWpvci4gIA0KMi4gQ29uZmlhbnphIGRlbCBjb25zdW1pZG9yIGRlIFVTQTogw61uZGljZSBxdWUgbWlkZSwgYSBwYXJ0aXIgZGUgdW5hIGVuY3Vlc3RhIHF1ZSB0YW4gb3B0aW1pc3RhcyBvIHBlc2ltaXN0YXMgc2UgZW5jdWVudHJhbiBsb3MgY29uc3VtaWRvcmVzIHNvYnJlIHN1IHNpdHVhY2nDs24gZmluYW5jaWVyYS4gRW50cmUgbWF5b3IsIG1lam9yLiAgDQozLiBTYWxhcmlvIG3DrW5pbW8gcG9yIGhvcmE6IHNlIG1pZGUgZW4gZMOzbGFyZXMuIEVzdMOhIGVzdGFibGVjaWRvIGEgbml2ZWwgZmVkZXJhbC4gIA0KNC4gQcOxbzogbG9zIGHDsW9zIHF1ZSBzZSB0aWVuZW4gZGUgbG9zIGRhdG9zLCAyMDA3LTIwMjAuDQoNCg0KYGBge3J9DQpyZWdyZXNpb24yIDwtIGxtICh2ZW50YXNfY29tZXJjaWFsZXMgfiBkZXNlbXBsZW9fdXNhICsgY29uZmlhbnphX2NvbnNfdXNhICsgc2FsYXJpb19ob3JhX21pbl91c2EgKyBhw7FvLCBkYXRhPWJkZXgpDQpzdW1tYXJ5IChyZWdyZXNpb24yKQ0KYGBgDQoNCj4gUGFyYSBsYSB0YXNhIGRlIGRlc2VtcGxlbyB5IGVsIMOtbmRpY2UgZGUgY29uZmlhbnphIGRlbCBjb25zdW1pZG9yLCBzZSBoYSBkZWNpZGlkbyB0b21hciBlbCAqcHJvbWVkaW8qIGRlbCAyMDA3IGFsIDIwMjAsIHBhcmEgcG9kZXIgcHJlZGVjaXIuIENvbiBlbCBzYWxhcmlvIG3DrW5pbW8gcG9yIGhvcmEsIGFsIHNlciBlc3RhYmxlY2lkbyBhIG5pdmVsIGZlZGVyYWwsIHNlIHRvbWEgZW4gY3VlbnRhIGxhIMO6bHRpbWEgY2FudGlkYWQ6ICQ3LjI1IGTDs2xhcmVzLiBTZSBxdWllcmVuIGxhcyBwcmVkaWNjaW9uZXMgcGFyYSBsb3Mgc2lndWllbnRlcyBjaW5jbyBhw7FvcywgYSBwYXJ0aXIgZGVsIMO6bHRpbW8gYcOxbyBjb24gZGF0b3MgKDIwMjApLg0KDQpgYGB7cn0NCmRhdG9zX251ZXZvczIgPC0gZGF0YS5mcmFtZShkZXNlbXBsZW9fdXNhPTYuNDMsY29uZmlhbnphX2NvbnNfdXNhPTgyLjMsc2FsYXJpb19ob3JhX21pbl91c2E9Ny4yNSxhw7FvPTIwMjE6MjAyNSkNCnByZWRpY3QocmVncmVzaW9uMixkYXRvc19udWV2b3MyKQ0KYGBgDQoNCioqwr9RdcOpIG9ic2VydmFtb3M/KioNCg0KYGBge3J9DQpzZWd1bmRvIDwtIHBsb3QocHJlZGljdChyZWdyZXNpb24yLGRhdG9zX251ZXZvczIpLCB0eXBlID0gImwiLCB4bGFiID0gIkHDsW8iLCAgeWxhYiA9IlZlbnRhcyBDb21lcmNpYWxlcyIsICBtYWluPSJQcmVkaWNjacOzbiBkZSBWZW50YXMiKQ0KYGBgDQoNCj4gRW4gZXN0YSBwcmVkaWNjacOzbiBkZSB2ZW50YXMgZGUgYXV0b23Ds3ZpbGVzICpjb21lcmNpYWxlcyosIG9ic2VydmFtb3MgcXVlIGVzIGhhY2lhIGFycmliYSBFcyBkZWNpciwgdG9tYW5kbyBlbiBjdWVudGEgdW5hIHRhc2EgZGUgZGVzZW1wbGVvICBkZSA2LjQzLCB1biDDrW5kaWNlIGRlIGNvbmZpYW56YSBkZSA4Mi4zIHkgZWwgc2FsYXJpbyBtw61uaW1vIHBvciBob3JhIGRlICQ3LjI1LCBzZSBlc3BlcmEgcXVlIGxhcyB2ZW50YXMgZGUgZXN0b3MgYXV0b23Ds3ZpbGVzICoqc3ViYW4qKiBlbiBFVUEgZGVsIDIwMjEgaGFzdGEgMjAyNS4gRW4gZWwgY2FzbyBkZSBsYXMgdmVudGFzIGRlIGF1dG9tw7N2aWxlcyAqY29tZXJjaWFsZXMqLCBub3RhbW9zIHF1ZSBlbCBwYXNhciBkZSBsb3MgYcOxb3MgZXMgbGEgdmFyaWFibGUgcXVlIG3DoXMgaW1wYWN0YSwgc2lndWllbmRvIHBvciBlbCBuaXZlbCBkZSBjb25maWFuemEgZGVsIGNvbnN1bWlkb3IgeSBlbCBzYWxhcmlvIG3DrW5pbW8gcG9yIGhvcmE7IG1pZW50cmFzIHF1ZSBlbCBxdWUgbWVub3MgYWZlY3RhIGVzIGxhIHRhc2EgZGUgZGVzZW1wbGVvLiANCg0KYGBge3J9DQplZmZlY3RfcGxvdChyZWdyZXNpb24yLHByZWQ9ZGVzZW1wbGVvX3VzYSxpbnRlcnZhbD1UUlVFKQ0KYGBgDQoNCj4gU2kgdG9tYW1vcyBlbiBjdWVudGEgbGEgdGFzYSBkZSBkZXNlbXBsZW8gZGUgRVVBLCB5IHN1IHJlbGFjacOzbiBjb24gbGFzIHZlbnRhcyBkZSBsb3MgYXV0b23Ds3ZpbGVzICpjb21lcmNpYWxlcyosIG9ic2VydmFtb3MgcXVlIGVzdGEgZXMgbmVnYXRpdmEuIERlYmlkbyBhIHF1ZSBhbCBjcmVjZXIgbGEgdGFzYSBkZSBkZXNlbXBsZW8sIGJhamFuIGxhcyB2ZW50YXMuIA0KDQpgYGB7cn0NCmVmZmVjdF9wbG90KHJlZ3Jlc2lvbjIscHJlZD1jb25maWFuemFfY29uc191c2EsaW50ZXJ2YWw9VFJVRSkNCmBgYA0KDQo+IE1pZW50cmFzIHF1ZSBlbCDDrW5kaWNlIGRlIGNvbmZpYW56YSBkZWwgY29uc3VtaWRvciBkZSBFVUEsIHkgc3UgcmVsYWNpw7NuIGNvbiBsYXMgdmVudGFzIGRlIGxvcyBhdXRvbcOzdmlsZXMgKmNvbWVyY2lhbGVzKiwgb2JzZXJ2YW1vcyBxdWUgZXN0YSBlcyBwb3NpdGl2YS4gRGViaWRvIGEgcXVlIGFsIGNyZWNlciBsYSBjb25maWFuemEsIGluY3JlbWVudGFuIGxhcyB2ZW50YXMuIEEgY29tcGFyYWNpw7NuIGRlIGxhIGdyw6FmaWNhIGRlIHZlbnRhcyAqcGFzc2VuZ2VyKiBjb24gZWwgbml2ZWwgZGUgY29uZmlhbnphLCBvYnNlcnZhbW9zIHF1ZSBlbiBlc3RlIGNhc28gbGEgcGVuZGllbnRlIGVzIG3DoXMgcHJvbnVuY2lhZGEsIHBvciBsbyBxdWUgdmVtb3MgdW4gbWF5b3IgaW1wYWN0by4gDQoNCmBgYHtyfQ0KZWZmZWN0X3Bsb3QocmVncmVzaW9uMixwcmVkPXNhbGFyaW9faG9yYV9taW5fdXNhLGludGVydmFsPVRSVUUpDQpgYGANCg0KPiBJZ3VhbG1lbnRlLCBhbCBzdWJpciBlbCBzYWxhcmlvIG3DrW5pbW8gcG9yIGhvcmEsIGxhcyB2ZW50YXMgZGUgbG9zIGF1dG9tw7N2aWxlcyAqY29tZXJjaWFsZXMqIGRpc21pbnV5ZW4uIEVzdGUgcG9kcsOtYSBzZXIgdW4gdGVtYSBpbnRlcmVzYW50ZSBhIGludmVzdGlnYXIuIA0KDQpgYGB7cn0NCmVmZmVjdF9wbG90KHJlZ3Jlc2lvbjIscHJlZD1hw7FvLGludGVydmFsPVRSVUUpDQpgYGANCg0KPiBDb24gZWwgcGFzYXIgZGUgbG9zIGHDsW9zIGxhcyB2ZW50YXMgaGFuIGluY3JlbWVudGFkby4gDQoNCiMgPHNwYW4gc3R5bGU9ImNvbG9yOm9yYW5nZSI+KipQcm9uw7NzdGljbyBkZWwgRGVzZW1wZcOxbyBkZSBsYSBJbmR1c3RyaWEgQXV0b21vdHJpeiB5IGxhIGVtcHJlc2EgRk9STSoqDQoNCiMjIyAqKlByb27Ds3N0aWNvIFByb2R1Y2Npw7NuIEZPUk0qKg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnBsb3QocHJvZDQkRkVDSEEscHJvZDQkUFpBX1BST0csIHR5cGU9ImwiLGNvbD0iYmx1ZSIsIGx3ZD0xLjUsIHhsYWIgPSJGZWNoYSIseWxhYiA9IlBpZXphcyBwcm9ncmFtYWRhcyIsIG1haW4gPSAiUGllemFzIHByb2dyYW1hZGFzIHBvciBmZWNoYSIpDQpsaW5lcyhwcm9kNCRGRUNIQSxwcm9kNCRMQU1JTkFTX1BST0NFU0FEQVMsY29sPSJyZWQiLGx0eT0zKQ0KbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kPWMoIlBpZXphcyBwcm9ncmFtYWRhcyIsICJMYW1pbmFzIHByb2Nlc2FkYXMiKSwNCiAgICAgICBjb2w9YygiYmx1ZSIsICJyZWQiKSwgbHR5ID0gMToyLCBjZXg9MC44KQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoobWFfbW9kZWw8LWFybWEocHJvZDQkUFpBX1BST0csb3JkZXI9YygwLDEpKSkNCm1hX21vZGVsX2ZvcmVjYXN0PC1mb3JlY2FzdChtYV9tb2RlbCRmaXR0ZWQsaD0zLGxldmVsPWMoOTUpKQ0KbWFfbW9kZWxfZm9yZWNhc3QNCmBgYA0KDQojIyMgKipQcm9uw7NzdGljbyBNZXJtYSBGT1JNKioNCg0KYGBge3J9DQojIFN1bWFyIGVsIFRvdGFsIGRlIEtpbG9zeE1lcw0KbWVybWEzIDwtIGMoMTQ1NjAsMjI4MzAsMjI0NzAsMTg4MjAsMjM0MTAsMTgyODAsMTkzNzAsMzIxMDAsMTM1ODYpDQoNCm1lcm1hX3N0IDwtIHRzKGRhdGEgPSBtZXJtYTMsIHN0YXJ0ID0gYygyMDIyLDEpLCBmcmVxdWVuY3kgPSAxMikNCm1lcm1hX3N0DQpgYGANCg0KYGBge3J9DQptb2RlbG8gPC0gYXV0by5hcmltYShtZXJtYV9zdCkNCm1vZGVsbw0KDQpwcm9ub3N0aWNvIDwtIGZvcmVjYXN0KG1vZGVsbywgbGV2ZWw9Yyg5NSksIGg9MykNCnByb25vc3RpY28NCnBsb3QocHJvbm9zdGljbykNCmBgYA0KDQojIyMgUmVzdWx0YWRvczogwr9DdcOhbCBlcyBsYSB0ZW5kZW5jaWE/DQoNClBvZGVtb3MgdmVyIHF1ZSBlbiBsYSBpbmR1c3RyaWEgQXV0b21vdHJpeiBkZSBVU0EsIGVzcGVjw61maWNhbWVudGUgZW4gdmVudGFzIGRlIG1vdG9yZXMsIHRlbmVtb3MgdW5hIHRlbmRlbmNpYSBjb250aW51YSB5IHF1ZSBudWVzdHJvcyBpbnRlcnZhbG9zIGRlIGNvbmZpYW56YSBiYW4gZGlzbWludXllbmRvLCBwZXJvIGxhcyBwcmVkaWNjaW9uZXMgc2UgZW5jdWVudHJhbiBlbnRyZSA4MzE1LjczMi0xMjU5NS42MSBkZSB2ZW50YXMgYW51YWxlcyBkZSBtb3RvcmVzIGVuIFVTQSBwYXJhIGxvcyBwcsOzeGltb3MgYcOxb3MuDQoNClBhcmEgRm9ybSBhbCBkZXNhcnJvbGxhciBlbCBwcm9uw7NzdGljbyBkZSBNZXJtYSB2ZW1vcyBxdWUgdGVuZW1vcyBxdWUgcGFyYSBsb3MgcHLDs3hpbW9zIHBlcmlvZG9zIGRlIG9jdHVicmUsIG5vdmllbWJyZSB5IGRpY2llbWJyZSB0ZW5kcmVtb3MgdW5hIGNhbnRpZGFkIGNvbnN0YW50ZSBkZSAyMDYwMi44OSBraWxvcyBkZSBtZXJtYSB5IHF1ZSBudWVzdHJvIGludGVydmFsbyBkZSBjb25maWFuemEgY2FlIGVudHJlIDk3NzAuNzExIGEgMzE0MzUuMDcuSW50ZXJwcmV0YW5kbyBsYSBpbmZvcm1hY2nDs24gdmVtb3MgcXVlIGEgY29tcGFyYWNpw7NuIGRlbCDDumx0aW1vIG1lcyBkZSBzZXB0aWVtYnJlLCBsb3Mga2lsb3MgY3JlY2Vyw6FuLg0KDQojIDxzcGFuIHN0eWxlPSJjb2xvcjpvcmFuZ2UiPioqU2VjY2nDs24gMy4gSy1tZWFucyBDbHVzdGVyaW5nKioNCg0KYGBge3J9DQpsaWJyYXJ5KGZvcmVpZ24pDQpsaWJyYXJ5KGRwbHlyKSAgICAgICAgIyBkYXRhIG1hbmlwdWxhdGlvbiANCmxpYnJhcnkoZ2dwbG90MikgICAgICAjIGRhdGEgdmlzdWFsaXphdGlvbiANCiMgaW5zdGFsbC5wYWNrYWdlcygicHN5Y2giKQ0KbGlicmFyeShwc3ljaCkgICAgICAgICMgZnVuY3Rpb25zIGZvciBtdWx0aXZhcmlhdGUgYW5hbHlzaXMgDQpsaWJyYXJ5KGNvcnJwbG90KSAgICAgIyBjb3JyZWxhdGlvbiBwbG90cw0KbGlicmFyeShqdG9vbHMpICAgICAgICMgcHJlc2VudGF0aW9uIG9mIHJlZ3Jlc3Npb24gYW5hbHlzaXMgDQpsaWJyYXJ5KGxtdGVzdCkgICAgICAgIyBkaWFnbm9zdGljIGNoZWNrcyAtIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzIA0KbGlicmFyeShjYXIpICAgICAgICAgICMgZGlhZ25vc3RpYyBjaGVja3MgLSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcw0KbGlicmFyeShmYWN0b2V4dHJhKSAgICMgcHJvdmlkZXMgZnVuY3Rpb25zIHRvIGV4dHJhY3QgYW5kIHZpc3VhbGl6ZSB0aGUgb3V0cHV0IG9mIGV4cGxvcmF0b3J5IG11bHRpdmFyaWF0ZSBkYXRhIGFuYWx5c2VzDQojIGluc3RhbGwucGFja2FnZXMoImdnZm9ydGlmeSIpDQpsaWJyYXJ5KGdnZm9ydGlmeSkgICAgIyBkYXRhIHZpc3VhbGl6YXRpb24gdG9vbHMgZm9yIHN0YXRpc3RpY2FsIGFuYWx5c2lzIHJlc3VsdHMNCg0KYGBgDQoNCmBgYHtyfQ0KIyBmaWxlLmNob29zZQ0KYmQgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcc29maWFcXERvd25sb2Fkc1xcYmFqYXNfZmluYWwgKDIpLmNzdiIpDQpgYGANCg0KYGBge3J9DQpzYXBwbHkoYmQsZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkNCmBgYA0KDQojIyMjICoqMS4gRWRhZCB5ICBkdXJhY2nDs24gLSA0IENsdXN0ZXJzKioNCg0KYGBge3J9DQpiYWphczEgPC1iZA0KYmFqYXMxIDwtc3Vic2V0KGJhamFzMSxzZWxlY3QgPSAtYyhnZW5lcm8sYWx0YSxtb3Rpdm9fYmFqYSxwdWVzdG8sZXN0YWRvLG5vbWJyZSkpDQpzdW1tYXJ5KGJhamFzMSkNCmBgYA0KDQpgYGB7cn0NCmJhamFzX2VkYWRkdXJfbm9ybTwtc2NhbGUoYmFqYXMxWzE6Ml0pDQpgYGANCg0KYGBge3J9DQpmdml6X25iY2x1c3QoYmFqYXNfZWRhZGR1cl9ub3JtLCBrbWVhbnMsIG1ldGhvZD0id3NzIikrIA0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9NCwgbGluZXR5cGU9MikrICAgICAgICAgDQogIGxhYnMoc3VidGl0bGUgPSAiRWxib3cgbWV0aG9kIikgIA0KYGBgDQoNCmBgYHtyfQ0KZWRhZF9jbHVzdGVyMTwta21lYW5zKGJhamFzX2VkYWRkdXJfbm9ybSw0KQ0KZWRhZF9jbHVzdGVyMQ0KYGBgDQoNCmBgYHtyfQ0KZnZpel9jbHVzdGVyKGVkYWRfY2x1c3RlcjEsZGF0YT1iYWphc19lZGFkZHVyX25vcm0pDQpgYGANCg0KQWwgb2JzZXJ2YXIgdmVtb3MgY3VhdHJvIGNsdXN0ZXJzIHF1ZSB0b21hbiBlbiBjdWVudGEgbGEgZWRhZCB5IGxhIGR1cmFjacOzbjogIA0KMS4gRWwgcm9qbyAoc2Vyw6EgbGxhbWFkbyAiU2VuaW9yIikgZXMgdW4gY2x1c3RlciBxdWUgb2JzZXJ2YW1vcyBxdWUgc29uIHBlcnNvbmFzIGRlIGVkYWQgbWVkaWFuYS1hbHRhIHkgcXVlIGR1csOhbiByZWxhdGl2YW1lbnRlIHBvY28gdGllbXBvLCBlbnRyYW4gZGVudHJvIGRlbCAyNSUgY29uIG1lbm9yIGR1cmFjacOzbi4gICANCjIuIEVsIHZlcmRlICgiRXhwZXJ0IikgZXMgZWwgY2x1c3RlciBxdWUgbcOhcyBzZSBhcGFydGEgZGUgbG9zIGRlbcOhczsgc29uIHBlcnNvbmFzIGNvbiB1biBtYXlvciByYW5nbyBkZSBlZGFkIHBlcm8gcXVlIHNlIGFsZWphbiBkZSBsb3MgbcOhcyBqw7N2ZW5lcywgeSAgcXVlIGhhbiBkdXJhZG8gbXVjaG8gbcOhIHRpZW1wby4gU2UgZW5jdWVudHJhbiBlbiBlbCA1MCUgc3VwZXJpb3IgZGVsIHRpZW1wbyBkZSBkdXJhY2nDs24uICANCjMuIEVsIGF6dWwgKCJqdW5pb3IiKSByZXN1bHRhIGVsIGNsdXN0ZXIgaW50ZXJtZWRpbyBkZSBsb3MgZGUgbWVub3IgZHVyYWNpw7NuLiBTb24gcGVyc29uYXMgZW4gIHVuIHJhbmdvIGRlIGVkYWQgbWVkaW8gcXVlIHRhbWJpw6luIHNvbiBwYXJ0ZSBkZWwgMjUlIGluZmVyaW9yIHF1ZSBtw6FzIGhhbiBkdXJhZG8uICANCjQuIEVsIG1vcmFkbyAoImJlZ2lubmVyIikgZXMgZWwgc2VnbWVudG8gbcOhcyBqb3ZlbiB5IHF1ZSBkZSBsYXMgcGVyc29uYXMgKGVuIGdlbmVyYWwpIG1lbm9zIGhhbiBkdXJhZG8uIFNlIHB1ZWRlIGNvbnNpZGVyYXIgcXVlIGxvcyBqw7N2ZW5lcyBzb24gbG9zIHF1ZSBtZW5vcyBkdXJhbiBlbiBGb3JtIGEgcGFydGlyIGRlIGVzdGUgY2x1c3Rlci4gDQoNCg0KYGBge3J9DQpiYWphc19uZXcyPC1iYWphczENCmJhamFzX25ldzIkQ2x1c3RlcnM8LWVkYWRfY2x1c3RlcjEkY2x1c3Rlcg0KYmFqYXNfbmV3MzwtYmFqYXNfbmV3MiAlPiUgZ3JvdXBfYnkoQ2x1c3RlcnMpICU+JSBzdW1tYXJpc2UoZWRhZD1tYXgoZWRhZCkpICU+JSBhcnJhbmdlKGRlc2MoZWRhZCkpDQpiYWphc19uZXcyJENsdXN0ZXJfTmFtZXM8LWZhY3RvcihiYWphc19uZXcyJENsdXN0ZXJzLGxldmVscyA9IGMoMSwyLDMsNCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIlNlbmlvciIsICJFeHBlcnQiLCAiSnVuaW9yIiwgIkJlZ2lubmVyIikpDQpgYGANCg0KDQojIyMjICoqMi4gRWRhZCB5ICBkdXJhY2nDs24gLSA1IENsdXN0ZXJzKioNCg0KRGViaWRvIGEgcXVlZSB1bmEgZ3LDoWZpY2EgYW50ZXJpb3IgaW5kaWNhYmEgbGEgcG9zaWJpbGlkYWQgZGUgdGVuZXIgb3RybyBjbMO6c3RlciBxdWUgZGVzY3JpYmEgYSBvdHJvIGdydXBvLCBoYWNlbW9zIGxvIG1pc21vIGNvbiA1IHNlZ21lbnRvcywgZW4gdmV6IGRlIDQuIA0KDQpgYGB7cn0NCmJhamFzX2VkYWRkdXJfbm9ybTI8LXNjYWxlKGJhamFzMVsxOjJdKQ0KYGBgDQoNCmBgYHtyfQ0KZnZpel9uYmNsdXN0KGJhamFzX2VkYWRkdXJfbm9ybTIsIGttZWFucywgbWV0aG9kPSJ3c3MiKSsgDQogIGdlb21fdmxpbmUoeGludGVyY2VwdD01LCBsaW5ldHlwZT0yKSsgICAgICAgICANCiAgbGFicyhzdWJ0aXRsZSA9ICJFbGJvdyBtZXRob2QiKSAgDQpgYGANCg0KYGBge3J9DQplZGFkX2NsdXN0ZXIyPC1rbWVhbnMoYmFqYXNfZWRhZGR1cl9ub3JtLDUpDQplZGFkX2NsdXN0ZXIyDQpgYGANCg0KYGBge3J9DQpmdml6X2NsdXN0ZXIoZWRhZF9jbHVzdGVyMixkYXRhPWJhamFzX2VkYWRkdXJfbm9ybTIpDQpgYGANCkNvbXBhcmFuZG8gZXN0YSAgZ3LDoWZpY2EgZGUgNSBzZWdtZW50b3MgY29udHJhIGxhIGFudGVyaW9ybWVudGUgdmlzdGEgZGUgNC4gRW4gZXN0YSBvYnNlcnZhbW9zIHF1ZSBzZXBhcmEgdW4gc2VnbWVudG8gcXVlIGRlamEgdW4gImVzcGFjaW8iIHF1ZSBhbnRlcyBubyBleGlzdMOtYTsgc2VwYXJhIHkgY3JlYSB1biBzZWdtZW50byBxdWUgaGFuIGR1cmFkbyBhcHJveCB1biAxMCUgbcOhcyBkZSB0aWVlbXBvIHF1ZSBsYXMgdHJlcyBtZW5vcmVzLCB5IHF1ZSBzZSBlbmN1ZW50cmEgZW4gcmFuZ29zIGRlIGVkYWQgcGFyZWNpZG9zLiBBIGNvbnRpbnVhY2nDs24gc2UgY29tcGFyYW4gbG9zIGNsdXN0ZXJzOiAgDQoxLiBFbCByb2pvIChsbGFtYWRvICJTZW5pb3IiKTogZXMgZWwgbnVldm8sIGVsIGN1YWwgdGllbmUgZGUgYmFqYSBhIG1lZGlhbmEgZHVyYWNpw7NuIHkgdW4gcmFuZ28gZGUgZWRhZCBtZWRpYW5hLiBEZXNwdcOpcyBkZSBsb3MgcXVlIGhhbiBkdXJhZG8gbXVjaG8sIGVsbG9zIHZhbiBkZXNwdcOpcy4gIA0KICANCjIuIEVsIHZlcmRlIHN1cGVyaW9yIChsbGFtYWRvICJFeHBlcnQiKTogZXMgZWwgY2x1c3RlciBxdWUgbcOhcyBzZSBhcGFydGEgZGUgbG9zIGRlbcOhczsgc29uIHBlcnNvbmFzIGNvbiB1biBtYXlvciByYW5nbyBkZSBlZGFkIHBlcm8gcXVlIHNlIGFsZWphbiBkZSBsb3MgbcOhcyBqw7N2ZW5lcywgeSAgcXVlIGhhbiBkdXJhZG8gbXVjaG8gbcOhIHRpZW1wby4gU2UgZW5jdWVudHJhbiBlbiBlbCA1MCUgc3VwZXJpb3IgZGVsIHRpZW1wbyBkZSBkdXJhY2nDs24uICANCiAgDQozLiBFbCB2ZXJkZSBpbmZlcmlvciAobGxhbWFkbyAiSnVuaW9yIikgc29uIHBlcnNvbmFzIGFkdWx0YXMgcXVlIGhhbiBkdXJhZG8gcG9jbyB0aWVtcG8gZW4gbGEgZW1wcmVzYSwgcGFydGUgZGVsIDE3JSBpbmZlcmlvciBkZSBkdXJhY2nDs24uICAgDQogICAgDQo0LiBFbCBtb3JhZG8gKGxsYW1hZG8gIk1pZGRsZSIpOiBhbCBoYWNlciBlbCBudWV2byBjbMO6c3RlciBub3MgZGFtb3MgY3VlbnRhIGRlIHF1ZSBleGlzdGUgdW4gZ3J1cG8gZGUgcGVyc29uYXMgZGUgbWVkaWFuYSBlZGFkIHF1ZSBkdXJhbiAqKm11eSoqIHBvY28sIGHDum4gbcOhcyBwb2NvIHF1ZSBsb3MgasOzdmVuZXMuICpJbnZlc3RpZ2FyIGVzdGFkbyBjaXZpbCouICANCiAgDQo1LiBFbCBhenVsIChsbGFtYWRvICJCZWdpbm5lciIpOiBzb24gbGFzIHBlcnNvbmFzIG3DoXMgasOzdmVuZXMgeSBxdWUgdGFtYmnDqW4gaGFuIGR1cmFkbyBwb2NvIHRpZW1wby4gU2UgcXVlZGFuIGFwcm94aW1hZGFtZW50ZSBwb3IgZWwgMTAlIGluZmVyaW9yLiANCg0KYGBge3J9DQpiYWphc19uZXc2PC1iYWphczENCmJhamFzX25ldzYkQ2x1c3RlcnM8LWVkYWRfY2x1c3RlcjIkY2x1c3Rlcg0KYmFqYXNfbmV3NzwtYmFqYXNfbmV3NiAlPiUgZ3JvdXBfYnkoQ2x1c3RlcnMpICU+JSBzdW1tYXJpc2UoZWRhZD1tYXgoZWRhZCkpICU+JSBhcnJhbmdlKGRlc2MoZWRhZCkpDQpiYWphc19uZXc2JENsdXN0ZXJfTmFtZXM8LWZhY3RvcihiYWphc19uZXc2JENsdXN0ZXJzLGxldmVscyA9IGMoMSwyLDMsNCw1KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiU2VuaW9yIiwgIkV4cGVydCIsICJKdW5pb3IiLCAiTWlkZGxlIiwiQmVnaW5uZXIiKSkNCmBgYA0KDQpBbCBhbmFsaXphciBlbCBlc3RhZG8gY2l2aWwgZGUgbG9zIDUgY2zDunN0ZXJzLCBsbGVnYW1vcyBhIGxhcyBzaWd1aWVudGVzIGNvbmNsdXNpb25lczogIA0KMS4gRGVsIHNlZ21lbnRvICJTZW5pb3IiLCBlbCA3NSUgc29uIHNvbHRlcm9zLiBFc3RlIGVzIGVsIG51ZXZvIGNsw7pzdGVyIGRlc2N1YmllcnRvLiAgDQoyLiBFbCA1NSUgZGUgbGFzIHBlcnNvbmFzIGVuIGVsIGNsdXN0ZXIgIk1pZGRsZSIgKG1lbm9yIGR1cmFjacOzbikgc29uIHNvbHRlcmFzLCBlbCAyNiUgdml2ZW4gZW4gdW5pw7NuIGxpYnJlLCB5IHVuIDE5JSBxdWUgdml2ZW4gZW4gbWF0cmltb25pby4gIA0KMy4gRGUgbG9zIGV4cGVydG9zLCBlbCA3NSUgc29uIHNvbHRlcm9zLiANCg0KIyMjIyAqKjMuIER1cmFjacOzbiB5IHNhbGFyaW8qKg0KDQoqSW1wb3J0YXIgYmFzZSBkZSBkYXRvcyoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpiYWphczIgPC1yZWFkLmNzdigiQzpcXFVzZXJzXFxzb2ZpYVxcRG93bmxvYWRzXFxiYWphc19maW5hbCAoMikuY3N2IikgDQpgYGANCg0KYGBge3J9DQpzYXBwbHkoYmFqYXMyLGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpDQpgYGANCg0KYGBge3J9DQpyaF9iYWphczI8LWJhamFzMg0KcmhfYmFqYXMyPC1zdWJzZXQocmhfYmFqYXMyLHNlbGVjdCA9IC1jKGdlbmVybyxhbHRhLG1vdGl2b19iYWphLHB1ZXN0byxlc3RhZG8sbm9tYnJlKSkNCnN1bW1hcnkocmhfYmFqYXMyKQ0KYGBgDQoNCmBgYHtyfQ0KYmFqYXNfZHVyYWNpb25fbm9ybTwtc2NhbGUocmhfYmFqYXMyWzI6M10pIA0KYGBgDQoNCmBgYHtyfQ0KZnZpel9uYmNsdXN0KGJhamFzX2R1cmFjaW9uX25vcm0sIGttZWFucywgbWV0aG9kPSJ3c3MiKSsgDQogIGdlb21fdmxpbmUoeGludGVyY2VwdD01LCBsaW5ldHlwZT0yKSsgICAgICAgICANCiAgbGFicyhzdWJ0aXRsZSA9ICJFbGJvdyBtZXRob2QiKSANCmBgYA0KDQpgYGB7cn0NCmR1cmFjaW9uX2NsdXN0ZXIxPC1rbWVhbnMoYmFqYXNfZHVyYWNpb25fbm9ybSw1KQ0KZHVyYWNpb25fY2x1c3RlcjENCmBgYA0KDQpgYGB7cn0NCmZ2aXpfY2x1c3RlcihkdXJhY2lvbl9jbHVzdGVyMSxkYXRhPWJhamFzX2R1cmFjaW9uX25vcm0pDQpgYGANCg0KQWwgb2JzZXJ2YXIgdmVtb3MgNSBjbHVzdGVycyBxdWUgdG9tYW4gZW4gY3VlbnRhIGxhIGR1cmFjacOzbiB5IGVsIHNhbGFyaW86ICANCg0KMS4gUHJpbWVybyB2ZW1vcyBudWVzdHJvIGNsdXN0ZXIgMSAoc2Vyw6EgbGxhbWFkbyAiUmVoZW5lcyIpIGVzIHVuIGNsdXN0ZXIgcXVlIG9ic2VydmFtb3MgcXVlIHNvbiBwZXJzb25hcyBxdWUgc29sbyBlbnRyYW4geSBzYWxlbiBtdXkgcHJvbnRvIGRlIGxhIGVtcHJlc2EgKDE0MSBkw61hcykgeSB0aWVuZW4gdW4gc2FsYXJpbyBkaWFyaW8gcXVlIGVzIGFycmliYSBkZWwgcHJvbWVkaW8sIGFscmVkZWRvciBkZSAkMTgwIHBlc29zLiAgIA0KDQoyLiBFbCBjbHVzdGVyIDIgKCJEdXJhZGVyb3MiKSBzb24gbG9zIGNvbGFib3JhZG9yZXMgcXVlIHRpZW5lbiB1bmEgZHVyYWNpw7NuIHJlZ3VsYXIsIHBlcm8gcXVlIGF1biBhc8OtIG5vIHNlIGVuY3VlbnRyYW4gc2F0aXNmZWNob3MgcG9yIGxvIHF1ZSBzZSBzYWxlbiBkZSBsYSBlbXByZXNhIGFsIHJlZGVkb3IgZGVzcHXDqXMgZGUgMSBhw7FvIHkgbWVkaW8gKDY0NiBkw61hcykgeSBzdSBzYWxhcmlvIGVzIGRlICQxNjkuICANCg0KMy4gQ29tbyBjbHVzdGVyIDMgdGVuZW1vcyBhIGxvcyBjb2xhYm9yYWRvcmVzIHF1ZSBzb24gbGVhbGVzIGEgbGEgZW1wcmVzYSAoIkZpZWxlcyIpIGVzIGVsIHNlZ21lbnRvIGRvbmRlIHlhIHRpZW5lbiBtw6FzIGRlIDQtNSBhw7FvcyB0cmFiYWphbmRvIHkgY3VlbnRhbiBjb24gdW4gc2FsYXJpbyBkZSAkMTY4IHBlc29zLiAgDQoNCjQuIEVsIGNsdXN0ZXIgNCAoIkNvc3Rvc29zIikgZXMgZWwgY2x1c3RlciBxdWUgbm9zIGN1ZXN0YSBhIGxhIGVtcHJlc2EgcG9ycXVlIHNlIGludmllcnRlIGVuIGNhcGFjaXRhY2lvbmVzIHBhcmEgZWxsb3MgeSB0ZXJtaW5hbiBzYWxpZW5kbyBkZSBsYSBlbXByZXNhOyBzb24gcGVyc29uYXMgY29uIHVuIHBvY28gbWFzIGRlIGR1cmFjacOzbiBwZXJvIG5vIGxhIHN1ZmljaWVudGUgKDE5NyBkw61hcykgeSBzdSBzYWxhcmlvIGVzIGRlICQxNTEgcG9yIGRlYmFqbyBwcm9tZWRpby4gIA0KDQo1LiBQb3Igw7psdGltbyB0ZW5lbW9zIGVsIGNsdXN0ZXIgNSAoIkV4dHJhIikgcXVlIHR1dm8gZHVyYWNpw7NuIGNvcnRvIHBsYXpvIGNvbiB1biBzYWxhcmlvIG11eSBhbHRvICgkNTAwIHBlc29zKS4gDQoNCmBgYHtyfQ0KcmhfYmFqYXMzPC0gYmFqYXMyDQpyaF9iYWphczMkQ2x1c3RlcnM8LWR1cmFjaW9uX2NsdXN0ZXIxJGNsdXN0ZXINCnJoX2JhamFzNDwtcmhfYmFqYXMzICU+JSBncm91cF9ieShDbHVzdGVycykgJT4lIHN1bW1hcmlzZShkdXJhY2lvbj1tYXgoZHVyYWNpb24pKSAlPiUgYXJyYW5nZShkZXNjKGR1cmFjaW9uKSkNCnJoX2JhamFzMyRDbHVzdGVyX05hbWVzPC1mYWN0b3IocmhfYmFqYXMzJENsdXN0ZXJzLGxldmVscyA9IGMoMSwyLDMsNCw1KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJSZWhlbmVzIiwgIkR1cmFkZXJvcyIsIkZpZWxlcyIsICJDb3N0b3NvcyIsIkV4dHJhIikpDQpgYGANCg0KDQoNCg0KKiAqKiJSZWhlbmVzIioqIHRpZW5lIGVsIHNlZ21lbnRvIGNvbiBtw6FzIGNvbGFib3JhZG9yZXMgeSB0aWVuZSB1biB0b3RhbCBkZSAxOTEuIEVuIHBvcmNlbnRhamUgc2UgcHVlZGUgZGVjaXIgcXVlIGVzIGVsIDgxLjk3JSB0b3RhbCBkZSBiYWphcy4gIA0KDQoqICoqIkNvc3Rvc29zIioqIGVzdGEgZW4gc2VndW5kbyBsdWdhciB0ZW5pZW5kbyAyNyBjb2xhYm9yYWRvcmVzICgxMS41NyUpLiAgICANCg0KKiAqKiJEdXJhZGVyb3MiKiogdGVyY2VyIGx1Z2FyIGNvbiB1biB0b3RhbCBkZSAxMCBjb2xhYm9yYWRvcmVzICg0LjI5JSkuICANCg0KKiAqKiJGaWVsZXMiKiogY3VhcnRvIGx1Z2FyIGNvbiA0IGNvbGFib3JhZG9yZXMgKDEuNzElKS4gIA0KDQoqIFBvciDDumx0aW1vIGVzdGEgZWwgKioiRXh0cmEiKiogcXVlIGZ1ZSBzb2xvIHVuIGNvbGFib3JhZG9yIHF1ZSBzZSBlbmN1ZW50cmEgZnVlcmEgZGUgbG8gbm9ybWFsICgwLjQzJSkuDQoNCiMjIyMgKio0LiBFZGFkIHkgc2FsYXJpbyoqDQoNCmBgYHtyfQ0KI2ZpbGUuY2hvb3NlDQpiYWphczMgPC1yZWFkLmNzdigiQzpcXFVzZXJzXFxzb2ZpYVxcRG93bmxvYWRzXFxiYWphc19maW5hbCAoMikuY3N2IikNCmBgYA0KDQpgYGB7cn0NCnN0cihiYWphczMpDQpgYGANCg0KYGBge3J9DQpzYXBwbHkoYmFqYXMzLGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpDQpgYGANCg0KYGBge3J9DQpiZHIyIDwtIGJhamFzMw0KYmRyMjwtc3Vic2V0KGJkcjIsc2VsZWN0ID0gLWMoZ2VuZXJvLGFsdGEsbW90aXZvX2JhamEscHVlc3RvLGVzdGFkbyxub21icmUsZHVyYWNpb24pKQ0Kc3VtbWFyeShiZHIyKQ0KYGBgDQoNCmBgYHtyfQ0KYmRyMyA8LSBzY2FsZShiZHIyWzE6Ml0pDQpgYGANCg0KYGBge3J9DQpmdml6X25iY2x1c3QoYmRyMywga21lYW5zLCBtZXRob2Q9IndzcyIpKyANCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTQsIGxpbmV0eXBlPTIpKyAgICAgICAgIA0KICBsYWJzKHN1YnRpdGxlID0gIkVsYm93IG1ldGhvZCIpIA0KYGBgDQoNCmBgYHtyfQ0KYmRyNDwta21lYW5zKGJkcjMsNCkNCmJkcjQNCmBgYA0KDQpgYGB7cn0NCmZ2aXpfY2x1c3RlcihiZHI0LGRhdGE9YmRyMykNCmBgYA0KDQpWZW1vcyBxdWUgZWwgbsO6bWVybyDDs3B0aW1vIGRlIGtsdXN0ZXJzIHBhcmEgbGFzIHZhcmlhYmxlcyBlZGFkIHkgc2FsYXJpbyBkaWFyaW8gc29uIDQgc2Vnw7puIGVsIG3DqXRvZG8gZGUgRWxib3cuDQoNCkNvbW8gZGF0byBkaXNwYXJhZG8geSBwb3NpYmxlIHdhcm5pbmcgdmVtb3MgcXVlIGhheSB1biB0cmFiYWphZG9yIGNvbiB1biBzYWxhcmlvIGRpYXJpbyBkZSA1MDAgcGVzb3MgbG8gcXVlIHBvZHLDrWEgcmVzdWx0YXIgY29tbyB1biBlcnJvciwgc2luIGVtYmFyZ28gbG9zIG90cm9zIDMgZ3J1cG9zIHZhcsOtYW4gYmFzdGFudGUgZW4gZWRhZCBtw6FzIG5vIGVuIHNhbGFyaW8gcHVlcyBlbCByYW5nbyBlcyBtdXkgY2VyY2Fuby4NCg0KMS4gKipBbHRvKiogRWwgZGF0byBlcyDDum5pY28gZW4gZWwgY29udGVvIGNvbiB1biB0cmFiYWphZG9yIGRlIDMyIGHDsW9zIHF1ZSB0aWVuZSB1biBzYWxhcmlvIGRpYXJpbyBkZSA1MDAgcGVzb3MgeSBlcyBzb2x0ZXJvLiBTdSBwdW50byBlbiBlbCBtYXBlbyBlcyDDum5pY28gKGNvbG9yIHJvam8pLiAgDQogIA0KMi4gKipWZXJkZSoqIEVzIGVsIGNsdXN0ZXIgY29uIGVsIHJlZ2lzdHJvIGRlIHBlcnNvbmFzIGNvbiBtYXlvciBlZGFkIHkgY3VlbnRhbiBjb24gZWwgc2FsYXJpbyBkaWFyaW8gbcOhcyBhbHRvIDE4My42OC4gIA0KICANCjMuICoqQXp1bCoqIEVzIGVsIGNsdXN0ZXIgY29uIGVsIHJlZ2lzdHJvIGRlIHBlcnNvbmFzIGNvbiBlZGFkIHByb21lZGlvIHkgc2FsYXJpbyBkZSAxODAuNjguICANCiAgDQo0LiAqKk1vcmFkbyoqIEVzIGVsIGNsdXN0ZXIgY29uIG1heW9yIHJlZ2lzdHJvIGRlIHBlcnNvbmFzIGNvbiBlZGFkIGrDs3ZlbiB5IHNhbGFyaW8gZGUgMTgyLjY4Lg0KDQpgYGB7cn0NCmJkcjU8LWJkcjINCmJkcjUkQ2x1c3RlciA8LSBiZHI0JGNsdXN0ZXINCmJkcjY8LWJkcjUgJT4lIGdyb3VwX2J5KENsdXN0ZXIpICU+JSBzdW1tYXJpemUoc2FsYXJpb19kaWFyaW89bWF4KHNhbGFyaW9fZGlhcmlvKSkgJT4lIGFycmFuZ2UoZGVzYyhzYWxhcmlvX2RpYXJpbykpDQpiZHI1JENsdXN0ZXJfTmFtZXM8LWZhY3RvcihiZHI1JENsdXN0ZXIsbGV2ZWxzID0gYygxLDIsMyw0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiQWx0byIsICJNZWRpbyIsIkJham8iLCAiUmVndWxhciIpKQ0KYGBgDQoNCg0KDQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmRhcmtyZWQiPioqVGVyY2VyIHB1bnRvOiBJbnNpZ2h0cy4qKg0KDQoqIENvbiBsYSBiYXNlIGRlIGRhdG9zIGRlIGJhamFzIHNlIHJlYWxpesOzIGVsIGNsw7pzdGVyIGRlIGVkYWQgeSBkdXJhY2nDs24sIGVuIGxhIGN1YWwgc2UgdG9tYXJvbiBlbiBjdWVudGEgbGFzIHZhcmlhYmxlcyBkZSBsYSBlZGFkIGRlIGxvcyBjb2xhYm9yYWRvcmVzIHkgbGEgZHVyYWNpw7NuIHF1ZSBoYW4gdGVuaWRvIGVuIGxhIGVtcHJlc2EuIFNlIGJ1c2PDsyBlbCBuw7ptZXJvIMOzcHRpbW8gZGUgY2zDunN0ZXIgeSBzZSB0b21hcm9uIGVuIGN1ZW50YSBsb3MgcHJpbWVyb3MgNC4gRW4gZXN0ZSBwb2RlbW9zIG9ic2VydmFyIHF1ZSBsYXMgcGVyc29uYXMgY29uIGVkYWQgbWVkaWFuYS1hbHRhIG5vIHRpZW5lbiB1bmEgZHVyYWNpw7NuIGRlIGxhcmdvIHRpZW1wbyBlbiBsYSBlbXByZXNhIHlhIHF1ZSBmb3JtYW4gcGFydGUgZGVsIDI1JSBjb24gbWVub3IgZHVyYWNpw7NuOyBvdHJvIGRhdG8gcXVlIG9ic2VydmFtb3MgcXVlIGxhcyBwZXJzb25hcyBjb24gbWF5b3IgZWRhZCBoYW4gZHVyYWRvIG3DoXMgdGllbXBvIGVuIEZvcm0geSBmb3JtYW4gcGFydGUgZGVsIHN1cGVyaW9yIDUwJSwgeSBwb3Igw7psdGltbyBvYnNlcnZhbW9zIHF1ZSBleGlzdGUgdW5hIG1heW9yIHJvdGFjacOzbiBkZSBwZXJzb25hbCBlbiBsb3MgY29sYWJvcmFkb3JlcyBqw7N2ZW5lcy4gIA0KKiBFbiBlbCBhbsOhbGlzaXMgcXVlIHNlIHJlYWxpesOzIG1lZGlhbnRlIGdyw6FmaWNhcywgb2J0dXZpbW9zIHF1ZSBlbiBsb3MgY2zDunN0ZXIsIHF1ZSBsYSBwZXJzb25hIGNvbiBtYXlvciBlZGFkIGVuIGxvcyBleHBlcnQgdGllbmUgNjEsIGVuIHNlbmlvciB0aWVuZSA1NywgZW4ganVuaW9yIHRpZW5lIDM5IHkgZW4gYmVnaW5ubmVyIDI3LCB0YW1iacOpbiBxdWUgZW4gbGEgZW1wcmVzYSBsYSBtYXlvcsOtYSBkZSBsb3MgY29sYWJvcmFkb3JlcyBjb3JyZXNwb25kZW4gYWwgY2zDunN0ZXIgZGUgYmVnaW5uZXIuICAgDQoqIEVuIGN1YW50byBhbCBhbsOhbGlzaXMgZGUgbGEgZHVyYWNpw7NuIGRlIGxvcyBjb2xhYm9yYWRvcmVzIGVuIGxhIGVtcHJlc2EgeSBzdSBzYWxhcmlvIGVuY29udHJhbW9zIGVzdG9zIHB1bnRvcyBtYXMgaW1wb3J0YW50ZXM7IGEpIGxhIG1heW9yw61hIGRlIGxvcyBlbXBsZWFkb3MgZ2FuYW4gYXJyaWJhIGRlbCBzYWxhcmlvIGRpYXJpbyBwcm9tZWRpbyBlc3RhYmxlY2lkbyBwb3IgZWwgZ29iaWVybm8sIGVzdGUgb3NjaWxhIGVudHJlICQxNTAtJDIwMDAgcGVzb3MgZGlhcmlvcywgYikgbG9zIGNvbGFib3JhZG9yZXMgcXVlIHRpZW5lbiB1biB0aWVtcG8gbWVkaW8gZW4gbGEgZW1wcmVzYSBhcHJveGltYWRhbWVudGUgZGUgdW4gYcOxbyB0aWVuZSB1biBzYWxhcmlvIHByb21lZGlvIGRlICQxNjksIG1pZW50cmFzIGxvcyBxdWUgZHVyYW4gbWVub3MgdGllbXBvIChhbHJlZGVkb3IgZGUgMTQxIGTDrWFzKSB0aWVuZW4gdW4gc2FsYXJpbyBwcm9tZWRpbyBkZSBhbHJlZGVkb3IgZGUgJDE4MC4gIA0KKiBFbCBjbMO6c3RlciBtYXMgZ3JhbmRlIGVzIGVsIGxsYW1hZG8g4oCcUmVobmVz4oCdIHRpZW5lIHVuIHRvdGFsIGRlIGNvbGFib3JhZG9yZXMgZGUgMTkxLCB5IGVuIHBvcmNlbnRhamUgZGUgYmFqYXMgc2UgcHVlZGUgZGVjaXIgcXVlIGVzIGVsIDgxLjk3JSB0b3RhbCBkZSBiYWphcywgZXN0b3MgdGllbmUgbGEgY2FyYWN0ZXLDrXN0aWNhIGRlIHNvbiBsYXMgcGVyc29uYXMgcXVlIGVudHJhbiB5IHNhbGVuIG11eSBwcm9udG8geSB0aWVuZW4gdW4gc2FsYXJpbyBwb3IgYXJyaWJhIGRlIHRvZG9zIGxvcyBkZW3DoXMgY2zDunN0ZXIgZGUgJDE4MCBwZXNvcywgcG9yIGxvIHF1ZSwgZW4gZXN0ZSBjbMO6c3RlciBzZSBuZWNlc2l0YSBhcGxpY2FyIHVuYSBlc3RyYXRlZ2lhIGRlIGZpZGVsaXphY2nDs24gZGUgbG9zIGNvbGFib3JhZG9yZXMgZGUgb3RyYSBmb3JtYSBxdWUgbm8gc2VhIGNvbiB1biBhdW1lbnRvIGRlIHNhbGFyaW8sIGVzIGRlY2lyLCBGb3JtIHB1ZWRlIGltcGxlbWVudGFyIGVzdHJhdGVnaWFzIGNvbiByZWNvbXBlbnNhcyBxdWUgc2VhbiBhIGxhcmdvIHBsYXpvLiAgDQoqIENvbW8gc2UgcHVlZGUgb2JzZXJ2YXIgZW4gZWwgYW5hbGlzaXMgcXVlIHNlIHJlYWxpesOzIGRlIGVkYWQgeSBzYWxhcmlvIHNlIHB1ZWRlbiBkZXN0YWNhciBsb3Mgc2lndWllbnRlcyBwdW50b3M6ICANCmEpIGVsIGNsdXN0ZXIgcXVlIHRpZW5lIHVuYSBtYXlvciBmcmVjdWVuY2lhIGVzIGVsIGRlIDQ4IGHDsW9zIGRlIGVkYWQsICANCmIpIGVsIGNsdXN0ZXIgcXVlIG1hcyBjaGljbyBlcyBkZSAyMiBhw7FvcyBvIG1lbm9zIHBvciBsbyBxdWUgcG9kZW1vcyBkZWNpciBxdWUgZW4gRm9ybSwgbGEgbWF5b3LDrWEgc29uIG1heW9yZXMgZGUgMjMgYcOxb3MsDQogIGMpIGVuIGN1YW50byBhbCBzYWxhcmlvIHRpZW5lbiB1biBwcm9tZWRpbyBkZSAxODAuNjgsIHBlcm8gZXhpc3RlIHVuIGRhdG8gw7puaWNvIGVsIGN1YWwgZ2FuYWJhIDUwMC4gICANCiAgRW4gY29uY2x1c2nDs24gcGFyYSBGb3JtIHBvZGVtb3MgcGxhbnRlYXIgdW5hIGVzdHJhdGVnaWEgZGUgZXN0YW5kYXJpemFjacOzbiBkZSBzYWxhcmlvcyBkZSBhY3VlcmRvIGFsIHRpZW1wbyBxdWUgbGxldmFuIGVuIGxhIGVtcHJlc2EgeSBzdSBlZGFkLCBwYXJhIHBvZGVyIGFzw60gdGVuZXIgdW4gbWVqb3IgY29udHJvbCBkZSBnYXN0b3MgZGUgbGEgZW1wcmVzYSB5IGFwbGljYXIgbnVldmFzIGEgZXN0cmF0ZWdpYXMgYSBjYWRhIHVubyBkZSBsb3MgY2x1c3Rlci4NCg0KIyA8c3BhbiBzdHlsZT0iQ29sb3I6T1JBTkdFIj4gKipTRUNDSU9OIDQuIElkZW50aWZpY2FjacOzbiBkZSBSZXN1bHRhZG9zIFJlbGV2YW50ZXMgeSBTdWdlcmVuY2lhcyoqDQoNCioqSU5TSUdIVFMqKg0KKkNvbW8gcG9kZW1vcyBvYnNlcnZhciBlbiBsYSBiYXNlIGRlIGRhdG9zIGRlIFByb2R1Y2Npw7NuLCBlbCBtYXlvciBjbGllbnRlIGRlIEZvcm0sIGVuIGN1ZXN0acOzbiBkZSBsYW1pbmFzIHByb2Nlc2FkYXMsIGVzIFN0YWJpbHVzIDEsIGFzw60gc2UgbXVlc3RyYSBlbiBsYSBncmFmaWNhIGRlIHBhc3RlbCBkZSBlbXByZXNhLCBtaWVudHJhcyBxdWUgdGFtYmnDqW4gY3VlbnRhIGNvbiBhbGd1bm9zIGNsaWVudGVzIGNvbiBtdXkgcG9jYSBwcm9kdWNjacOzbiBjb21vIGVzIGVsIGNhc28gZGUgVkwtMDE3LTE0OTg5LiAgDQoNCipFbiBsYSBiYXNlIGRlIGRhdG9zIFNjcmFwLCBjb24gbGFzIGdyYWZpY2FzIHF1ZSBlbGFib3JhbW9zLCBwb2RlbW9zIG9ic2VydmFyIHF1ZSBlbCBtYXlvciBudW1lcm8gZGUgZGVzZWNobyBzZSBvcmlnaW5hIGVuIGVsIMOhcmVhIGRlIGxhIGVtcHJlc2EgZGUgUHJlLVByb2R1Y2Npw7NuLCBwb3IgbG8gcXVlIHBvZGVtb3MgZW5mb3JjYXJub3MgZW4gcHJvcG9uZXIgZXN0cmF0ZWdpYXMgcXVlIHJlZHV6Y2FuIGVsIG51bWVybyBkZSBkZXNlY2hvIHNpZ25pZmljYXRpdmFtZW50ZSBlbiBlc3RhIMOhcmVhLCBhc8OtIGNvbW8gdGFtYmnDqW4gZW4gZWwgw6FyZWEgZG9uZGUgbWVub3MgaGF5IGRlc2VjaG8gZXMgZW4gUG9zdC1wcm9kdWNjacOzbi4gIA0KDQoqRW4gZWwgw6FyZWEgZGUgcmVjdXJzb3MgaHVtYW5vcyBwb2RlbW9zIGludGVycHJldGFyIGNvbiBsYXMgZ3JhZmljYXMgcXVlIGVuIEZvcm0sIGhheSB1biBtYXlvciByYW5nbyBkZSBlZGFkIGVudHJlIGxhcyBtdWplcmVzLCBhc8OtIGNvbW8gdGFtYmnDqW4gcG9kZW1vcyBvYnNlcnZhciBxdWUgbGFzIG11amVyZXMgZW4gcHJvbWVkaW8gZ2FuYW4gbcOhcyBxdWUgbG9zIGhvbWJyZXMuICAgDQoqRW4gY3Vlc3Rpw7NuIGEgbGFzIGJhamFzLCBlbCBhbsOhbGlzaXMgZGUgbGEgYmFzZSBkZSBkYXRvcyBub3MgYXJyb2phIHF1ZSBleGlzdGUgdW5hIGdyYW4gcm90YWNpw7NuIGRlIHBlcnNvbmFsLCB5IGxhIG1heW9yw61hIGRlIGVsbG9zIG5vIGhhbiBhbGNhbnphZG8gZWwgZ3JhZG8gZGUganViaWxhY2nDs24sIGxhcyByYXpvbmVzIHByaW5jaXBhbGVzIGRlIGVzdGUgc29uIGFiYW5kb25vIHkgYmFqYSBwb3IgZmFsdGFzLiBFbiBiYXNlIGEgbGEgZ3JhZmljYSBkZSBiYXJyYXMgZXhwbGljYWRhIGVuIGxhIHBhcnRlIGRlIGJhamFzLCBzZSBtZW5jaW9uYSBxdWUgbGEgbWF5b3LDrWEgZGUgbGFzIHBlcnNvbmFzIHF1ZSBhYmFuZG9uYW4gc3UgdHJhYmFqbyBzb24gc29sdGVyYXMsIGFzw60gY29tbyB0YW1iacOpbiBhbGd1bmFzIGRlIGVsbGFzIG5vIHNlIGNvbm9jZSBzdSBlc3RhZG8gY2l2aWwuICANCg0KKkVuIGxhcyBwcmVkaWNjaW9uZXMgZGUgZGVzZW1wZcOxbyBkZSBsYSBpbmR1c3RyaWEgYXV0b21vdHJpeiBzZSBwdWRvIG9ic2VydmFyIHF1ZSBlbCBhdXRvbcOzdmlsIGRlIG1vZGVsbyBQYXNzZW5nZXIgc2UgZW5jdWVudHJhIGVuIGRlY3JlbWVudG8sIHRvbWFuZG8gY29tbyBiYXNlIGxvcyBkYXRvcyBkZSBsYSB0YXNhIGRlIGRlc2VtcGxlbyBkZSA2LjQzIHkgdW4gw61uZGljZSBkZSBjb25maWFuemEgZGUgODIuMywgc2UgZXNwZXJhIHF1ZSBzaWdhIGVsIGRlY3JlbWVudG8gZGUgZXN0b3MgYXV0b23Ds3ZpbGVzIGVuIEVVQSBkZWwgMjAyMSBhbCAyMDI1LiBNaWVudHJhcyBxdWUgZW4gZWwgc2VndW5kbyBtb2RlbG8gZGUgcmVncmVzacOzbiBjb24gbGEgbWlzbWEgYmFzZSBkZSBkYXRvcyBzZSBlc3BlcmEgdW5hIHByZWRpY2Npw7NuIGRlIHZlbnRhcyBwb3NpdGl2YSBlbiBsb3MgYXV0b23Ds3ZpbGVzIGNvbWVyY2lhbGVzLCB0b21hbmRvIGVuIGN1ZW50YSBkYXRvcyBjb21vIHRhc2EgZGUgZGVzZW1wbGVvIGRlIDYuNDMsIHVuIMOtbmRpY2UgZGUgY29uZmlhbnphIGRlIDgyLjMsIGVzIGluY3JlbWVudG8gc2UgZXNwZXJhIGRlbCAyMDIxIGFsIDIwMjUuDQoNCioqU1VHRVJFTkNJQVMqKg0KKkxhIGVzdHJhdGVnaWEgcGxhbnRlYWRhIHBhcmEgRm9ybSxiYXNhZGEgZW4gZWwgYW5hbGlzaXMgZGUgbGEgYmFzZSBkZSBkYXRvcyBkZSBiYWphcywgY29uc2lzdGUgZW4gY3JlYXIgcHJvZ3JhbWFzIGRlIGZpZGVsaXphY2nDs24gZGUgbG9zIGNvbGFib3JhZG9yZXMgYSBsYXJnbyBwbGF6bywgZG9uZGUgZWxsb3Mgc2Ugc2llbnRhbiBjb21wcm9tZXRpZG9zIGNvbiBsYSBlbXByZXNhIHkgc2lnYW4gbGEgdmlzacOzbiBkZSBsYSBtaXNtYSwgeWEgcXVlIGVzdG8gbG8gaWRlbnRpZmljYW1vcyBwb3JxdWUgZXhpc3RlIHVuYSBncmFuIHJvdGFjacOzbiBlbiBsYSBlbXByZXNhIGxhIGN1YWwgZXMgcG9yIGZhbHRhIGRlIGNvbXByb21pc28gZGUgbG9zIGNvbGFib3JhZG9yZXMgaGFjaWEgbGEgZW1wcmVzYSwgcG9yIGxvIHF1ZSB0YW1iaWVuIHNlIGxlIHByb3BvbmUgaGFjZXIganVudGFzIGVzdHJhdGVnaWNhcyBjb24gbG9zIGNvbGFib3JhZG9yZXMgZGUgbGFzIGFyZWFzIGVuIGxhIHF1ZSBzZSBkZW4gdGVtYXMgZGUgaW50ZWdyYWNpw7NuLCB0cmFiYWpvIGVuIGVxdWlwbyBlbnRyZSBvdHJvcy4gIA0KDQoqIE90cmEgZXN0cmF0ZWdpYSBwbGFudGVhZGEgZXMgcXVlIGV4aXN0YSB1biBkZXBhcnRhbWVudG8gZGVudHJvIGRlIGxhIGVtcHJlc2EgZW4gZWwgY3VhbCBzZSBjb25mb3JtZSBwb3IgcGVyc29uYXMgY2FwYWNpdGFkYXMgcGFyYSBsYSByZWNvcGlsYWNpw7NuIGRlIGRhdG9zIGRlIGNhZGEgdW5hIGRlIGxhcyDDoXJlYXMgeSB0b21lbiBkZWNpc2lvbmVzIGVuIGNhZGEgdW5hIGRlIGVsbGFzIGVuIGJhc2UgYSBsb3MgZGF0b3MgcXVlIHNlIG9idGVuZ2FuLCB5IHRhbWJpZW4gcXVlIHNlIGxsZXZlbiBhY2FibyBqdW50YSBjb24gbG9zIGRpcmVjdGl2b3MgcGFyYSBoYWNlciAgdW5hIHBsYW5lYWNpw7NuIGRlIHJlY3Vyc29zLg0KDQoNCioqQnVzaW5lc3MgQW5hbHl0aWNzIHkgQnVzaW5lc3MgSW50ZWxsaWdlbmNlLioqDQoNCkJ1c2luZXNzIEFuYWx5dGljcyBlcyB1biBlbmZvcXVlIGRlIGFuw6FsaXNpcyBkZSBkYXRvcyBkZW50cm8gZGUgYWxndW5hIGVtcHJlc2EsIGNvbnNpc3RlIGVuIGxsZXZhciBhIGNhYm8gc29sdWNpb25lcyBwYXJhIHNhdGlzZmFjZXIgbGFzIG5lY2VzaWRhZGVzIGRlIHVuIG5lZ29jaW8sIGxvZ3JhciBtZXRhcyB5IGFsY2FuemFyIGxvcyBvYmpldGl2b3MgcGxhbnRlYWRvcy4gQkEgc2UgY29tcG9uZSBkZSBvYnRlbmVyIGRhdG9zLCBhbmFsaXphciB5IG1vc3RyYXIgZGF0b3MgZGUgbWFuZXJhIHZpc3VhbCwgYXl1ZGEgZW4gdG9tYXIgZGVjaXNpb25lcyBiYXNhZG8gZW4gdGVuZGVuY2lhcyB5IGxvIHF1ZSBlc3TDoSBwYXNhbmRvIGVuIGVsIG1lcmNhZG8gZW4gZ2VuZXJhbC4NCuKAoglCdXNpbmVzcyBBbmFseXRpY3MgYXl1ZGEgYSBhbGNhbnphciBsb3Mgb2JqZXRpdm9zIGVtcHJlc2FyaWFsZXMgYSBwYXJ0aXIgZGUgdW4gYW7DoWxpc2lzIGRlIGdyYW5kZXMgdm9sw7ptZW5lcyBkZSBkYXRvcyBtZWRpYW50ZSBoZXJyYW1pZW50YXMgY29tbyBsb3MgZXMgUlN0dWRpbywgUGh5dG9uLCBlbnRyZSBvdHJvcy4NCuKAoglCQSBkZXRlY3RhIHRlbmRlbmNpYXMgY29uZm9ybWUgYWwgdGllbXBvIHkgcHVlZGUgcmVhbGl6YXIgcHJvbsOzc3RpY29zIGEgcGFydGlyIGRlIG1vZGVsb3MgcHJlZGljdGl2b3MuDQrigKIJQkEgdXRpbGl6YSBtb2RlbG9zIHByZWRpY3Rpdm9zIHBhcmEgb3B0aW1pemFyIGxvcyBwcm9jZXNvcyBkZSB1bmEgZW1wcmVzYSBlbiBjdWFscXVpZXIgw6FyZWEgY29tbyBwcm9kdWNjacOzbiwgbG9nw61zdGljYSwgcmVjdXJzb3MgaHVtYW5vcyBlbnRyZSBvdHJvcy4gDQpCdXNpbmVzcyBJbnRlbGxpZ2VuY2Ugc2UgdXRpbGl6YSBwYXJhIGV2YWx1YXIsIG9wdGltaXphciB5IGNvb3JkaW5hciBsYXMgb3BlcmFjaW9uZXMgaW50ZXJuYXMgZGUgdW5hIGVtcHJlc2EsIG1pZW50cmFzIHF1ZSBCdXNpbmVzcyBBbmFseXRpY3MgZXMgb2J0ZW5lciBkYXRvcywgYW5hbGl6YXJsb3MgeSBtb3N0cmFybG9zLiBFeGlzdGUgZGlmZXJlbmNpYXMgZW50cmVzIGVzdG9zIGRvcywgbGEgbWF5b3IgZGlmZXJlbmNpYSBlcyBlbiBsYSBwb3JhY3RpY2EgZGUgdXRpbGl6YXIgbG9zIGRhdG9zIGRlIHVuYSBlbXByZXNhIHBhcmEgYW50aWNpcGFyIHRlbmRlbmNpYXMgeSByZXN1bHRhZG9zLiBCdXNpbmVzcyBBbmFseXRpY3MgYXl1ZGEgZW4gdG9tYXIgZGVjaXNpb25lcyBiYXNhZG8gZW4gdGVuZGVuY2lhcyB5IGxvIHF1ZSBlc3TDoSBwYXNhbmRvIGVuIGVsIG1lcmNhZG8gZW4gZ2VuZXJhbC4NCg0KKipLUEknUyoqICANCkxvcyBrcGkncyBub3MgcGVybWl0ZW4gbWVkaXIgZW4gdGllbXBvIHJlYWwgZWwgZnVuY2lvbmFtaWVudG8gZGUgbGFzIGVzdHJhdGVnaWFzIGRlIGFsZ3VuYSBlbXByZXNhIGNvbW8gbG8gZXMgRm9ybSwgbWFya2V0aW5nIG8gdmVudGFzIGJyaW5kYW5kbyB1bmEgaW5mb3JtYWNpw7NuIHZhbGlvc2EgcGFyYSB0b21hciBkZWNpc2lvbmVzIGVzdHJhdMOpZ2ljYXMgcXVlIHBlcm1pdGFuIGEgbGEgZW1wcmVzYSBvcHRpbWl6YXIgc3VzIHJlY3Vyc29zIHBhcmEgYWxjYW56YXIgbG9zIG9iamV0aXZvcy4NCg0KTG9zIEtQSXMgdGFtYmnDqW4gZGVzZW1wZcOxYW4gdW5hIGltcG9ydGFudGUgZnVuY2nDs24gY29tdW5pY2F0aXZhIHlhIHF1ZSBpbmZvcm1hbiBhIGRpcmVjdGl2b3MsIGNvbGFib3JhZG9yZXMgZSBpbnZlcnNvcmVzIHNvYnJlIGxhIGV2b2x1Y2nDs24gZGUgbGEgZW1wcmVzYSByZXNwZWN0byBhIGxvcyBvYmpldGl2b3MgZXN0YWJsZWNpZG9zLCBwYXJhIHF1ZSB0b2RvcyBwdWVkYW4gdHJhYmFqYXIgY29uIHVuYSB2aXNpw7NuIHkgdW5hIG1ldGEgY29tw7puLg0KDQoNCg0K