Importar bases de datos

#file.choose()
produccion <- read.csv("/Users/dannaperez/Desktop/Reto Evidencia 2/Base de datos/Producción FORM csv.csv")
scrap <- read.csv("/Users/dannaperez/Desktop/Reto Evidencia 2/Base de datos/FORM - Scrap.csv")
merma <- read.csv("/Users/dannaperez/Desktop/Reto Evidencia 2/Base de datos/FORM - Merma.csv")

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

str(produccion)
## 'data.frame':    2568 obs. of  17 variables:
##  $ Fecha               : chr  "01/08/22" "01/08/22" "01/08/22" "01/08/22" ...
##  $ No.                 : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ CLIENTE             : chr  "VARROC" "VARROC" "VARROC" "DENSO" ...
##  $ ID.FORM             : chr  "VL-017-13938" "VL-017-13936" "VL-017-14729" "" ...
##  $ 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)." ...
##  $ PIEZAS.PROG.        : chr  "199" "57" "68" "192" ...
##  $ TMO..MIN.           : num  15 10 10 15 15 30 15 15 15 20 ...
##  $ HR..FIN             : num  0.385 0.392 0.399 0.41 0.42 ...
##  $ ESTACION.ARRANQUE   : chr  "C1" "C1Y2" "C1Y2" "C1" ...
##  $ Laminas.procesadas  : chr  "201" "116" "69" "49" ...
##  $ INICIO.SEP.UP       : chr  "0.375" "0.393055556" "0.418055556" "0.425" ...
##  $ FIN.INICIO.DE.SEP.UP: chr  "0.383333333" "0.396527778" "0.422916667" "10.17" ...
##  $ INICIO.de.PROCESO   : chr  "0.384027778" "0.397222222" "0.422916667" "0.429166667" ...
##  $ FIN.de.PROCESO      : chr  "0.393055556" "0.411805556" "44905" "0.430555556" ...
##  $ TIEMPO.CALIDAD      : num  1 1 1 1 1 1 1 1 1 1 ...
##  $ TIEMPO.MATERIALES   : int  NA NA NA NA NA 3 NA NA NA NA ...
##  $ MERMAS.Maquinas.    : int  NA NA NA NA NA NA NA NA NA NA ...
str(scrap)
## 'data.frame':    250 obs. of  9 variables:
##  $ Referencia          : chr  "SP/08512" "SP/08511" "SP/08676" "SP/08700" ...
##  $ Fecha               : chr  "06/08/22" "05/08/22" "26/08/22" "29/08/22" ...
##  $ ID_Producto         : int  1 1 2 3 3 3 3 3 3 3 ...
##  $ Producto            : chr  "[2065WY AS 30 99 0000 00 000 TAPA - BOX 2064WY] BOX  2064WY" "[2065WY AS 30 99 0000 00 000 TAPA - BOX 2064WY] BOX  2064WY" "[241B EXPORT CAJA] 241B. Export. Caja." "[341332 CELDA - U611 & U625] 341332. U611. U625. Celda Troquelada." ...
##  $ Cantidad            : num  43 6 2 51 12 19 6 12 20 11 ...
##  $ Unidad.de.medida    : chr  "Unidad(es)" "Unidad(es)" "Unidad(es)" "Unidad(es)" ...
##  $ Ubicación.de.origen : chr  "SAB/Pre-Production" "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" ...
str(merma)
## 'data.frame':    10 obs. of  2 variables:
##  $ Mes  : chr  "Total ENERO" "Total FEBRERO" "Total MARZO" "Total ABRIL" ...
##  $ Kilos: int  14560 22830 22470 18820 23410 18280 19370 32100 13586 185426
base_de_datos <- c("producción", "scrap", "merma")
Numero_de_variables <- c("17", "9", "2")
Numero_de_observaciones <- c("2568", "250", "10")
variables_y_registros <- data.frame(base_de_datos, Numero_de_observaciones, Numero_de_variables)
variables_y_registros
##   base_de_datos Numero_de_observaciones Numero_de_variables
## 1    producción                    2568                  17
## 2         scrap                     250                   9
## 3         merma                      10                   2

Limpieza 1 (producción): Eliminar variables que no necesitamos.

Todas las variables que tenemos en la base de datos de producción no las necesitamos por lo que nomás se conservaron las variables de utilidad para nuestro análisis de datos.

summary(produccion)
##     Fecha                No.           CLIENTE            ID.FORM         
##  Length:2568        Min.   :  1.00   Length:2568        Length:2568       
##  Class :character   1st Qu.: 24.00   Class :character   Class :character  
##  Mode  :character   Median : 55.00   Mode  :character   Mode  :character  
##                     Mean   : 53.17                                        
##                     3rd Qu.: 79.00                                        
##                     Max.   :121.00                                        
##                     NA's   :537                                           
##    PRODUCTO         PIEZAS.PROG.         TMO..MIN.         HR..FIN      
##  Length:2568        Length:2568        Min.   :  0.00   Min.   :0.0417  
##  Class :character   Class :character   1st Qu.: 15.00   1st Qu.:0.2049  
##  Mode  :character   Mode  :character   Median : 20.00   Median :0.4062  
##                                        Mean   : 22.02   Mean   :0.3480  
##                                        3rd Qu.: 25.00   3rd Qu.:0.4618  
##                                        Max.   :120.00   Max.   :0.6632  
##                                        NA's   :816      NA's   :837     
##  ESTACION.ARRANQUE  Laminas.procesadas INICIO.SEP.UP      FIN.INICIO.DE.SEP.UP
##  Length:2568        Length:2568        Length:2568        Length:2568         
##  Class :character   Class :character   Class :character   Class :character    
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character    
##                                                                               
##                                                                               
##                                                                               
##                                                                               
##  INICIO.de.PROCESO  FIN.de.PROCESO     TIEMPO.CALIDAD   TIEMPO.MATERIALES
##  Length:2568        Length:2568        Min.   : 0.000   Min.   : 0.000   
##  Class :character   Class :character   1st Qu.: 1.000   1st Qu.: 0.000   
##  Mode  :character   Mode  :character   Median : 1.000   Median : 1.000   
##                                        Mean   : 1.091   Mean   : 5.171   
##                                        3rd Qu.: 1.000   3rd Qu.: 9.000   
##                                        Max.   :22.000   Max.   :48.000   
##                                        NA's   :1029     NA's   :2422     
##  MERMAS.Maquinas.
##  Min.   : 0.000  
##  1st Qu.: 1.000  
##  Median : 1.000  
##  Mean   : 2.112  
##  3rd Qu.: 2.000  
##  Max.   :50.000  
##  NA's   :2488
produccion1 <- produccion
borrar <- c("No.", "ID.FORM", "PRODUCTO", "HR..FIN", "ESTACION.ARRANQUE", "INICIO.de.PROCESO", "INICIO.SEP.UP", "FIN.INICIO.DE.SEP.UP", "NICIO.de.PROCESO", "FIN.de.PROCESO", "TIEMPO.MATERIALES", "MERMAS.Maquinas.")
prod2 <- produccion1[ , !(names(produccion1) %in% borrar)]
summary(prod2)
##     Fecha             CLIENTE          PIEZAS.PROG.         TMO..MIN.     
##  Length:2568        Length:2568        Length:2568        Min.   :  0.00  
##  Class :character   Class :character   Class :character   1st Qu.: 15.00  
##  Mode  :character   Mode  :character   Mode  :character   Median : 20.00  
##                                                           Mean   : 22.02  
##                                                           3rd Qu.: 25.00  
##                                                           Max.   :120.00  
##                                                           NA's   :816     
##  Laminas.procesadas TIEMPO.CALIDAD  
##  Length:2568        Min.   : 0.000  
##  Class :character   1st Qu.: 1.000  
##  Mode  :character   Median : 1.000  
##                     Mean   : 1.091  
##                     3rd Qu.: 1.000  
##                     Max.   :22.000  
##                     NA's   :1029

Limpieza 2 (producción): Eliminar NA´s.

En las variables que nos quedaron después de la limpieza #1, se encontraron que existían NA´s en la variable “tiempo calidad” y se descubrió que era mejor eliminarlos porque esas observaciones no tenían registros en otras variables. Si se promediaban podían alterar el resultado final ya que son una gran cantidad de observaciones con NA´s.

prod3 <- prod2
sapply(prod3, function(x) sum(is.na(x)))
##              Fecha            CLIENTE       PIEZAS.PROG.          TMO..MIN. 
##                  0                  0                  0                816 
## Laminas.procesadas     TIEMPO.CALIDAD 
##                  0               1029
prod3 <- na.omit(prod3)
sapply(prod3, function(x) sum(is.na(x)))
##              Fecha            CLIENTE       PIEZAS.PROG.          TMO..MIN. 
##                  0                  0                  0                  0 
## Laminas.procesadas     TIEMPO.CALIDAD 
##                  0                  0

Limpieza 3 (produccion): Convertir de caracter a fecha

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.3.6      ✔ purrr   0.3.4 
## ✔ tibble  3.1.8      ✔ dplyr   1.0.10
## ✔ tidyr   1.2.0      ✔ stringr 1.4.1 
## ✔ readr   2.1.2      ✔ forcats 0.5.2 
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
prod4 <- prod3
prod4$Fecha <- as.Date(prod4$Fecha, format = "%d/%m/%Y")
tibble(prod4)
## # A tibble: 1,525 × 6
##    Fecha      CLIENTE PIEZAS.PROG. TMO..MIN. Laminas.procesadas TIEMPO.CALIDAD
##    <date>     <chr>   <chr>            <dbl> <chr>                       <dbl>
##  1 0022-08-01 VARROC  199                 15 201                             1
##  2 0022-08-01 VARROC  57                  10 116                             1
##  3 0022-08-01 VARROC  68                  10 69                              1
##  4 0022-08-01 DENSO   192                 15 49                              1
##  5 0022-08-01 DENSO   192                 15 49                              1
##  6 0022-08-01 YANFENG 400                 30 801                             1
##  7 0022-08-01 YANFENG 80                  15 41                              1
##  8 0022-08-01 YANFENG 104                 15 53                              1
##  9 0022-08-01 YANFENG 104                 15 53                              1
## 10 0022-08-01 YANFENG 160                 20 55                              1
## # … with 1,515 more rows

Limpieza 4 (Scrap): ELiminar variables

ELiminar las variables que no me den información de utilidad.

summary(scrap)
##   Referencia           Fecha            ID_Producto     Producto        
##  Length:250         Length:250         Min.   : 1.0   Length:250        
##  Class :character   Class :character   1st Qu.:21.0   Class :character  
##  Mode  :character   Mode  :character   Median :39.0   Mode  :character  
##                                        Mean   :38.6                     
##                                        3rd Qu.:54.0                     
##                                        Max.   :85.0                     
##     Cantidad      Unidad.de.medida   Ubicación.de.origen Ubicación.de.desecho
##  Min.   : 0.000   Length:250         Length:250          Length:250          
##  1st Qu.: 1.000   Class :character   Class :character    Class :character    
##  Median : 2.000   Mode  :character   Mode  :character    Mode  :character    
##  Mean   : 6.696                                                              
##  3rd Qu.: 7.000                                                              
##  Max.   :96.000                                                              
##     Estado         
##  Length:250        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 
scr1 <- scrap
borrar <- c("Referencia", "ID_Producto", "Producto", "Unidad.de.medida", "Ubicación.de.desecho", "Estado")
scr1 <- scr1[ , !(names(scr1) %in% borrar)]
summary(scr1)
##     Fecha              Cantidad      Ubicación.de.origen
##  Length:250         Min.   : 0.000   Length:250         
##  Class :character   1st Qu.: 1.000   Class :character   
##  Mode  :character   Median : 2.000   Mode  :character   
##                     Mean   : 6.696                      
##                     3rd Qu.: 7.000                      
##                     Max.   :96.000

Limpieza 5 (Scrap): Convertir de caracter a fecha

scr2 <- scr1
scr2$Fecha <- as.Date(scr2$Fecha, format = "%d/%m/%Y")
tibble(scr2)
## # A tibble: 250 × 3
##    Fecha      Cantidad Ubicación.de.origen      
##    <date>        <dbl> <chr>                    
##  1 0022-08-06       43 SAB/Pre-Production       
##  2 0022-08-05        6 SAB/Calidad/Entrega de PT
##  3 0022-08-26        2 SAB/Calidad/Entrega de PT
##  4 0022-08-29       51 SAB/Pre-Production       
##  5 0022-08-27       12 SAB/Pre-Production       
##  6 0022-08-25       19 SAB/Pre-Production       
##  7 0022-08-22        6 SAB/Pre-Production       
##  8 0022-08-20       12 SAB/Pre-Production       
##  9 0022-08-20       20 SAB/Pre-Production       
## 10 0022-08-19       11 SAB/Pre-Production       
## # … with 240 more rows

Clasificación de variables y medición

Produccion

Variable <- c("Fecha", "CLIENTE", "PIEZAS.PROG.", "TMO..MIN.", "Laminas.procesadas", "Tiempo de calidad")
Clasificacion <- c("Cuantitativa discreta", "Cualitativa", "Cuantitativa discreta", "Cuantitativa continua", "Cuantitativa continua", "Cuantitariva discreta")
medicion <- c("día", "NA", "Número de piezas", "minutos", "Número de láminas", "minutos")
tabla <- data.frame (Variable, Clasificacion, medicion)
tabla
##             Variable         Clasificacion          medicion
## 1              Fecha Cuantitativa discreta               día
## 2            CLIENTE           Cualitativa                NA
## 3       PIEZAS.PROG. Cuantitativa discreta  Número de piezas
## 4          TMO..MIN. Cuantitativa continua           minutos
## 5 Laminas.procesadas Cuantitativa continua Número de láminas
## 6  Tiempo de calidad Cuantitariva discreta           minutos

Scrap

VariableS <- c("Fecha", "Cantidad", "Ubicacion.de.origen")
ClasifS <- c("Cuantitativa discreta", "Cuantitativa continua", "Cualitativa")
medS <- c("día", "Cantidad de producto", "NA")
tablaS <- data.frame (VariableS, ClasifS, medS)
tablaS
##             VariableS               ClasifS                 medS
## 1               Fecha Cuantitativa discreta                  día
## 2            Cantidad Cuantitativa continua Cantidad de producto
## 3 Ubicacion.de.origen           Cualitativa                   NA

Merma

summary(merma)
##      Mes                Kilos       
##  Length:10          Min.   : 13586  
##  Class :character   1st Qu.: 18415  
##  Mode  :character   Median : 20920  
##                     Mean   : 37085  
##                     3rd Qu.: 23265  
##                     Max.   :185426
VariableM <- c("Mes", "Kilos")
ClasifM <- c("Cualitativa", "Cuantitativa discreta")
MedM <- c("NA", "Kilos")
tablaM <- data.frame(VariableM, ClasifM, MedM)
tablaM
##   VariableM               ClasifM  MedM
## 1       Mes           Cualitativa    NA
## 2     Kilos Cuantitativa discreta Kilos

Gráficas

Tabla de frecuencia para mostrar número de registros de un cliente en una base de datos (1)

library(dplyr)
library(plyr)
## ------------------------------------------------------------------------------
## You have loaded plyr after dplyr - this is likely to cause problems.
## If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
## library(plyr); library(dplyr)
## ------------------------------------------------------------------------------
## 
## Attaching package: 'plyr'
## The following objects are masked from 'package:dplyr':
## 
##     arrange, count, desc, failwith, id, mutate, rename, summarise,
##     summarize
## The following object is masked from 'package:purrr':
## 
##     compact
prod4 %>% 
  group_by(CLIENTE) %>% 
  dplyr::summarize(frequency = n())
## # A tibble: 9 × 2
##   CLIENTE              frequency
##   <chr>                    <int>
## 1 DENSO                      165
## 2 HELLA                       63
## 3 MERIDIAN LIGHTWEIGHT        30
## 4 STABILUS 1                 516
## 5 STABILUS 3                 220
## 6 STABILUS 3.                 17
## 7 TRMX                       214
## 8 VARROC                     136
## 9 YANFENG                    164

Gráficos de datos cualitativos y datos cuantitativos (2-3)

Gráfica para analizar como varía la merma por mes

summary(merma)
##      Mes                Kilos       
##  Length:10          Min.   : 13586  
##  Class :character   1st Qu.: 18415  
##  Mode  :character   Median : 20920  
##                     Mean   : 37085  
##                     3rd Qu.: 23265  
##                     Max.   :185426
plot(merma$Kilos, type = "l")

Gráfico de pie para analizar cuanto tiempo de calidad se le dedica a cada cliente

#install.packages("plyr")
library(plyr)
proporciones <- c(148, 50, 32, 98, 73, 227, 156, 205)
etiquetas <- c("DENSO", "HELLA", "MERIDIAN LIGHT", "STABILUS 1", "STABILUS 3", "TRMX", "VARROC", "YANFENG")
pct <- round(proporciones/sum(proporciones)*100)
etiquetas <- paste(etiquetas, pct)
etiquetas <- paste(etiquetas,"%",sep="")
pie(proporciones,labels = etiquetas,
    col=rainbow(length(etiquetas)),
    main="Diagrama de tarta")

producción por cliente

df1 <- data.frame(Cliente = c("DENSO", "HELLA", "MERIDIAN LIGHT", "STABILUS 1", "STABILUS 3", "TRMX", "VARROC", "YANFENG"),
                 num = c(33520, 9162, 1118, 82210, 50020, 27908, 10665, 44635))
barplot(height = df1$num, names = df1$Cliente,
        col = c("red", "green", "white", "blue", "purple", "pink", "yellow", "brown"))

Gráficos de dispersión (2-3)

summary(prod4)
##      Fecha              CLIENTE          PIEZAS.PROG.         TMO..MIN.     
##  Min.   :0022-08-01   Length:1525        Length:1525        Min.   :  5.00  
##  1st Qu.:0022-08-09   Class :character   Class :character   1st Qu.: 15.00  
##  Median :0022-08-16   Mode  :character   Mode  :character   Median : 20.00  
##  Mean   :0022-08-15                                         Mean   : 22.39  
##  3rd Qu.:0022-08-24                                         3rd Qu.: 25.00  
##  Max.   :0022-08-31                                         Max.   :120.00  
##  NA's   :1                                                                  
##  Laminas.procesadas TIEMPO.CALIDAD  
##  Length:1525        Min.   : 0.000  
##  Class :character   1st Qu.: 1.000  
##  Mode  :character   Median : 1.000  
##                     Mean   : 1.099  
##                     3rd Qu.: 1.000  
##                     Max.   :22.000  
## 
plot(prod4$TIEMPO.CALIDAD, prod4$TMO..MIN., main = "Tiempo de calidad invertido por tiempo de producción", 
     xlab = "Tiempo de Calidad", ylab = "Tiempo de Producción", col= "purple")

ggplot(data=prod4, mapping = aes(PIEZAS.PROG., Laminas.procesadas)) + geom_point(aes(color =  TMO..MIN.)) + theme_bw()

Propuestas

  1. En la gráfica de producción por cliente podemos ver la cantidad de piezas que se producen por cliente, por lo que podemos concluir que STABILUS 1 es el cliente con más pedidos por lo que es un cliente leal y FORM puede organizar estrategias para retener ese cliente junto a los otros top 3 clientes más leales que serían STABILUS 3 y YANFENG

  2. A pesar de que STABILUS 1 es el cliente con más pedidos, el cliente a que más se le dedica tiempo de calidad es a TRMX. En este caso hay 2 estrategias: le invierten más tiempo a aquellos clientes con menos pedidos para atraerlos y retenerlos o invertir más tiempo al cliente con más producción para retenerlos.

Conclusión

Para empezar, es muy importante tener una base de datos limpia para poder tener resultados más confiables por lo que analizar las bases de datos es un paso muy importante. A partir de las gráficas podemos tener un apoyo visual y así se puede tener conclusiones más claras. Al tener 3 bases de datos con variables diferentes se pueden complementar entre sí y así tener una sola base de datos más completa.

LS0tCnRpdGxlOiAiRW50cmVnYWJsZV9JbmQiCmF1dGhvcjogIkRhbmEgUGVyZXogLSBBMDAyMjcwNDEiCmRhdGU6ICI5LzI3LzIwMjIiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDogCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KIyBJbXBvcnRhciBiYXNlcyBkZSBkYXRvcyAKYGBge3J9CiNmaWxlLmNob29zZSgpCnByb2R1Y2Npb24gPC0gcmVhZC5jc3YoIi9Vc2Vycy9kYW5uYXBlcmV6L0Rlc2t0b3AvUmV0byBFdmlkZW5jaWEgMi9CYXNlIGRlIGRhdG9zL1Byb2R1Y2Npb8yBbiBGT1JNIGNzdi5jc3YiKQpzY3JhcCA8LSByZWFkLmNzdigiL1VzZXJzL2Rhbm5hcGVyZXovRGVza3RvcC9SZXRvIEV2aWRlbmNpYSAyL0Jhc2UgZGUgZGF0b3MvRk9STSAtIFNjcmFwLmNzdiIpCm1lcm1hIDwtIHJlYWQuY3N2KCIvVXNlcnMvZGFubmFwZXJlei9EZXNrdG9wL1JldG8gRXZpZGVuY2lhIDIvQmFzZSBkZSBkYXRvcy9GT1JNIC0gTWVybWEuY3N2IikKYGBgCgojIMK/Q3XDoW50YXMgdmFyaWFibGVzIHkgY3VhbnRvcyByZWdpc3Ryb3MgdGllbmUgY2FkYSBiYXNlIGRlIGRhdG9zPwpgYGB7cn0Kc3RyKHByb2R1Y2Npb24pCnN0cihzY3JhcCkKc3RyKG1lcm1hKQpiYXNlX2RlX2RhdG9zIDwtIGMoInByb2R1Y2Npw7NuIiwgInNjcmFwIiwgIm1lcm1hIikKTnVtZXJvX2RlX3ZhcmlhYmxlcyA8LSBjKCIxNyIsICI5IiwgIjIiKQpOdW1lcm9fZGVfb2JzZXJ2YWNpb25lcyA8LSBjKCIyNTY4IiwgIjI1MCIsICIxMCIpCnZhcmlhYmxlc195X3JlZ2lzdHJvcyA8LSBkYXRhLmZyYW1lKGJhc2VfZGVfZGF0b3MsIE51bWVyb19kZV9vYnNlcnZhY2lvbmVzLCBOdW1lcm9fZGVfdmFyaWFibGVzKQp2YXJpYWJsZXNfeV9yZWdpc3Ryb3MKYGBgCgojIyAqTGltcGllemEgMSAocHJvZHVjY2nDs24pOiogRWxpbWluYXIgdmFyaWFibGVzIHF1ZSBubyBuZWNlc2l0YW1vcy4gIApUb2RhcyBsYXMgdmFyaWFibGVzIHF1ZSB0ZW5lbW9zIGVuIGxhIGJhc2UgZGUgZGF0b3MgZGUgcHJvZHVjY2nDs24gbm8gbGFzCm5lY2VzaXRhbW9zIHBvciBsbyBxdWUgbm9tw6FzIHNlIGNvbnNlcnZhcm9uIGxhcyB2YXJpYWJsZXMgZGUgdXRpbGlkYWQgcGFyYSBudWVzdHJvCmFuw6FsaXNpcyBkZSBkYXRvcy4gCmBgYHtyfQpzdW1tYXJ5KHByb2R1Y2Npb24pCnByb2R1Y2Npb24xIDwtIHByb2R1Y2Npb24KYm9ycmFyIDwtIGMoIk5vLiIsICJJRC5GT1JNIiwgIlBST0RVQ1RPIiwgIkhSLi5GSU4iLCAiRVNUQUNJT04uQVJSQU5RVUUiLCAiSU5JQ0lPLmRlLlBST0NFU08iLCAiSU5JQ0lPLlNFUC5VUCIsICJGSU4uSU5JQ0lPLkRFLlNFUC5VUCIsICJOSUNJTy5kZS5QUk9DRVNPIiwgIkZJTi5kZS5QUk9DRVNPIiwgIlRJRU1QTy5NQVRFUklBTEVTIiwgIk1FUk1BUy5NYXF1aW5hcy4iKQpwcm9kMiA8LSBwcm9kdWNjaW9uMVsgLCAhKG5hbWVzKHByb2R1Y2Npb24xKSAlaW4lIGJvcnJhcildCnN1bW1hcnkocHJvZDIpCmBgYAoKIyMgKkxpbXBpZXphIDIgKHByb2R1Y2Npw7NuKToqIEVsaW1pbmFyIE5BwrRzLiAgCkVuIGxhcyB2YXJpYWJsZXMgcXVlIG5vcyBxdWVkYXJvbiBkZXNwdcOpcyBkZSBsYSBsaW1waWV6YSAjMSwgc2UgZW5jb250cmFyb24gCnF1ZSBleGlzdMOtYW4gTkHCtHMgZW4gbGEgdmFyaWFibGUgInRpZW1wbyBjYWxpZGFkIiB5IHNlIGRlc2N1YnJpw7MgcXVlIGVyYSBtZWpvciAKZWxpbWluYXJsb3MgcG9ycXVlIGVzYXMgb2JzZXJ2YWNpb25lcyBubyB0ZW7DrWFuIHJlZ2lzdHJvcyBlbiBvdHJhcyB2YXJpYWJsZXMuIFNpIHNlIHByb21lZGlhYmFuCnBvZMOtYW4gYWx0ZXJhciBlbCByZXN1bHRhZG8gZmluYWwgeWEgcXVlIHNvbiB1bmEgZ3JhbiBjYW50aWRhZCBkZSBvYnNlcnZhY2lvbmVzIGNvbiBOQcK0cy4KYGBge3J9CnByb2QzIDwtIHByb2QyCnNhcHBseShwcm9kMywgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkKcHJvZDMgPC0gbmEub21pdChwcm9kMykKc2FwcGx5KHByb2QzLCBmdW5jdGlvbih4KSBzdW0oaXMubmEoeCkpKQpgYGAKCiMjICpMaW1waWV6YSAzIChwcm9kdWNjaW9uKToqICBDb252ZXJ0aXIgZGUgY2FyYWN0ZXIgYSBmZWNoYQpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCnByb2Q0IDwtIHByb2QzCnByb2Q0JEZlY2hhIDwtIGFzLkRhdGUocHJvZDQkRmVjaGEsIGZvcm1hdCA9ICIlZC8lbS8lWSIpCnRpYmJsZShwcm9kNCkKYGBgCgojIyAqTGltcGllemEgNCAoU2NyYXApKjogRUxpbWluYXIgdmFyaWFibGVzCkVMaW1pbmFyIGxhcyB2YXJpYWJsZXMgcXVlIG5vIG1lIGRlbiBpbmZvcm1hY2nDs24gZGUgdXRpbGlkYWQuCmBgYHtyfQpzdW1tYXJ5KHNjcmFwKQpzY3IxIDwtIHNjcmFwCmJvcnJhciA8LSBjKCJSZWZlcmVuY2lhIiwgIklEX1Byb2R1Y3RvIiwgIlByb2R1Y3RvIiwgIlVuaWRhZC5kZS5tZWRpZGEiLCAiVWJpY2FjacOzbi5kZS5kZXNlY2hvIiwgIkVzdGFkbyIpCnNjcjEgPC0gc2NyMVsgLCAhKG5hbWVzKHNjcjEpICVpbiUgYm9ycmFyKV0Kc3VtbWFyeShzY3IxKQpgYGAKCiMjICpMaW1waWV6YSA1IChTY3JhcCkqOiBDb252ZXJ0aXIgZGUgY2FyYWN0ZXIgYSBmZWNoYQpgYGB7cn0Kc2NyMiA8LSBzY3IxCnNjcjIkRmVjaGEgPC0gYXMuRGF0ZShzY3IyJEZlY2hhLCBmb3JtYXQgPSAiJWQvJW0vJVkiKQp0aWJibGUoc2NyMikKYGBgCgojIyBDbGFzaWZpY2FjacOzbiBkZSB2YXJpYWJsZXMgeSBtZWRpY2nDs24gCiMjIyBQcm9kdWNjaW9uCmBgYHtyfQpWYXJpYWJsZSA8LSBjKCJGZWNoYSIsICJDTElFTlRFIiwgIlBJRVpBUy5QUk9HLiIsICJUTU8uLk1JTi4iLCAiTGFtaW5hcy5wcm9jZXNhZGFzIiwgIlRpZW1wbyBkZSBjYWxpZGFkIikKQ2xhc2lmaWNhY2lvbiA8LSBjKCJDdWFudGl0YXRpdmEgZGlzY3JldGEiLCAiQ3VhbGl0YXRpdmEiLCAiQ3VhbnRpdGF0aXZhIGRpc2NyZXRhIiwgIkN1YW50aXRhdGl2YSBjb250aW51YSIsICJDdWFudGl0YXRpdmEgY29udGludWEiLCAiQ3VhbnRpdGFyaXZhIGRpc2NyZXRhIikKbWVkaWNpb24gPC0gYygiZMOtYSIsICJOQSIsICJOw7ptZXJvIGRlIHBpZXphcyIsICJtaW51dG9zIiwgIk7Dum1lcm8gZGUgbMOhbWluYXMiLCAibWludXRvcyIpCnRhYmxhIDwtIGRhdGEuZnJhbWUgKFZhcmlhYmxlLCBDbGFzaWZpY2FjaW9uLCBtZWRpY2lvbikKdGFibGEKYGBgCgojIyMgU2NyYXAKYGBge3J9ClZhcmlhYmxlUyA8LSBjKCJGZWNoYSIsICJDYW50aWRhZCIsICJVYmljYWNpb24uZGUub3JpZ2VuIikKQ2xhc2lmUyA8LSBjKCJDdWFudGl0YXRpdmEgZGlzY3JldGEiLCAiQ3VhbnRpdGF0aXZhIGNvbnRpbnVhIiwgIkN1YWxpdGF0aXZhIikKbWVkUyA8LSBjKCJkw61hIiwgIkNhbnRpZGFkIGRlIHByb2R1Y3RvIiwgIk5BIikKdGFibGFTIDwtIGRhdGEuZnJhbWUgKFZhcmlhYmxlUywgQ2xhc2lmUywgbWVkUykKdGFibGFTCmBgYAoKIyMjIE1lcm1hCmBgYHtyfQpzdW1tYXJ5KG1lcm1hKQpWYXJpYWJsZU0gPC0gYygiTWVzIiwgIktpbG9zIikKQ2xhc2lmTSA8LSBjKCJDdWFsaXRhdGl2YSIsICJDdWFudGl0YXRpdmEgZGlzY3JldGEiKQpNZWRNIDwtIGMoIk5BIiwgIktpbG9zIikKdGFibGFNIDwtIGRhdGEuZnJhbWUoVmFyaWFibGVNLCBDbGFzaWZNLCBNZWRNKQp0YWJsYU0KYGBgCgojIEdyw6FmaWNhcwojIyBUYWJsYSBkZSBmcmVjdWVuY2lhIHBhcmEgbW9zdHJhciBuw7ptZXJvIGRlIHJlZ2lzdHJvcyBkZSB1biBjbGllbnRlIGVuIHVuYSBiYXNlIGRlIGRhdG9zICgxKQpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeShwbHlyKQpwcm9kNCAlPiUgCiAgZ3JvdXBfYnkoQ0xJRU5URSkgJT4lIAogIGRwbHlyOjpzdW1tYXJpemUoZnJlcXVlbmN5ID0gbigpKQpgYGAKCiMjIEdyw6FmaWNvcyBkZSBkYXRvcyBjdWFsaXRhdGl2b3MgeSBkYXRvcyBjdWFudGl0YXRpdm9zICgyLTMpCiMjIyBHcsOhZmljYSBwYXJhIGFuYWxpemFyIGNvbW8gdmFyw61hIGxhIG1lcm1hIHBvciBtZXMKYGBge3J9CnN1bW1hcnkobWVybWEpCnBsb3QobWVybWEkS2lsb3MsIHR5cGUgPSAibCIpCmBgYAoKIyMjIEdyw6FmaWNvIGRlIHBpZSBwYXJhIGFuYWxpemFyIGN1YW50byB0aWVtcG8gZGUgY2FsaWRhZCBzZSBsZSBkZWRpY2EgYSBjYWRhIGNsaWVudGUKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJwbHlyIikKbGlicmFyeShwbHlyKQpwcm9wb3JjaW9uZXMgPC0gYygxNDgsIDUwLCAzMiwgOTgsIDczLCAyMjcsIDE1NiwgMjA1KQpldGlxdWV0YXMgPC0gYygiREVOU08iLCAiSEVMTEEiLCAiTUVSSURJQU4gTElHSFQiLCAiU1RBQklMVVMgMSIsICJTVEFCSUxVUyAzIiwgIlRSTVgiLCAiVkFSUk9DIiwgIllBTkZFTkciKQpwY3QgPC0gcm91bmQocHJvcG9yY2lvbmVzL3N1bShwcm9wb3JjaW9uZXMpKjEwMCkKZXRpcXVldGFzIDwtIHBhc3RlKGV0aXF1ZXRhcywgcGN0KQpldGlxdWV0YXMgPC0gcGFzdGUoZXRpcXVldGFzLCIlIixzZXA9IiIpCnBpZShwcm9wb3JjaW9uZXMsbGFiZWxzID0gZXRpcXVldGFzLAogICAgY29sPXJhaW5ib3cobGVuZ3RoKGV0aXF1ZXRhcykpLAogICAgbWFpbj0iRGlhZ3JhbWEgZGUgdGFydGEiKQpgYGAKCiMjIyBwcm9kdWNjacOzbiBwb3IgY2xpZW50ZQpgYGB7cn0KZGYxIDwtIGRhdGEuZnJhbWUoQ2xpZW50ZSA9IGMoIkRFTlNPIiwgIkhFTExBIiwgIk1FUklESUFOIExJR0hUIiwgIlNUQUJJTFVTIDEiLCAiU1RBQklMVVMgMyIsICJUUk1YIiwgIlZBUlJPQyIsICJZQU5GRU5HIiksCiAgICAgICAgICAgICAgICAgbnVtID0gYygzMzUyMCwgOTE2MiwgMTExOCwgODIyMTAsIDUwMDIwLCAyNzkwOCwgMTA2NjUsIDQ0NjM1KSkKYmFycGxvdChoZWlnaHQgPSBkZjEkbnVtLCBuYW1lcyA9IGRmMSRDbGllbnRlLAogICAgICAgIGNvbCA9IGMoInJlZCIsICJncmVlbiIsICJ3aGl0ZSIsICJibHVlIiwgInB1cnBsZSIsICJwaW5rIiwgInllbGxvdyIsICJicm93biIpKQpgYGAKCiMjIEdyw6FmaWNvcyBkZSBkaXNwZXJzacOzbiAoMi0zKQpgYGB7cn0Kc3VtbWFyeShwcm9kNCkKcGxvdChwcm9kNCRUSUVNUE8uQ0FMSURBRCwgcHJvZDQkVE1PLi5NSU4uLCBtYWluID0gIlRpZW1wbyBkZSBjYWxpZGFkIGludmVydGlkbyBwb3IgdGllbXBvIGRlIHByb2R1Y2Npw7NuIiwgCiAgICAgeGxhYiA9ICJUaWVtcG8gZGUgQ2FsaWRhZCIsIHlsYWIgPSAiVGllbXBvIGRlIFByb2R1Y2Npw7NuIiwgY29sPSAicHVycGxlIikKCmdncGxvdChkYXRhPXByb2Q0LCBtYXBwaW5nID0gYWVzKFBJRVpBUy5QUk9HLiwgTGFtaW5hcy5wcm9jZXNhZGFzKSkgKyBnZW9tX3BvaW50KGFlcyhjb2xvciA9ICBUTU8uLk1JTi4pKSArIHRoZW1lX2J3KCkKYGBgCgojIFByb3B1ZXN0YXMKMS4gRW4gbGEgZ3LDoWZpY2EgZGUgcHJvZHVjY2nDs24gcG9yIGNsaWVudGUgcG9kZW1vcyB2ZXIgbGEgY2FudGlkYWQgZGUgcGllemFzIHF1ZSBzZSBwcm9kdWNlbiBwb3IgY2xpZW50ZSwgcG9yIGxvIHF1ZSBwb2RlbW9zIGNvbmNsdWlyIHF1ZSBTVEFCSUxVUyAxIGVzIGVsIGNsaWVudGUgY29uIG3DoXMgcGVkaWRvcyBwb3IgbG8gcXVlIGVzIHVuIGNsaWVudGUgbGVhbCB5IEZPUk0gcHVlZGUgb3JnYW5pemFyIGVzdHJhdGVnaWFzIHBhcmEgcmV0ZW5lciBlc2UgY2xpZW50ZSBqdW50byBhIGxvcyBvdHJvcyB0b3AgMyBjbGllbnRlcyBtw6FzIGxlYWxlcyBxdWUgc2Vyw61hbiBTVEFCSUxVUyAzIHkgWUFORkVORwoKMi4gQSBwZXNhciBkZSBxdWUgU1RBQklMVVMgMSBlcyBlbCBjbGllbnRlIGNvbiBtw6FzIHBlZGlkb3MsIGVsIGNsaWVudGUgYSBxdWUgbcOhcyBzZSBsZSBkZWRpY2EgdGllbXBvIGRlIGNhbGlkYWQgZXMgYSBUUk1YLiBFbiBlc3RlIGNhc28gaGF5IDIgZXN0cmF0ZWdpYXM6IGxlIGludmllcnRlbiBtw6FzIHRpZW1wbyBhIGFxdWVsbG9zIGNsaWVudGVzIGNvbiBtZW5vcyBwZWRpZG9zIHBhcmEgYXRyYWVybG9zIHkgcmV0ZW5lcmxvcyBvIGludmVydGlyIG3DoXMgdGllbXBvIGFsIGNsaWVudGUgY29uIG3DoXMgcHJvZHVjY2nDs24gcGFyYSByZXRlbmVybG9zLiAKCiMgQ29uY2x1c2nDs24KUGFyYSBlbXBlemFyLCBlcyBtdXkgaW1wb3J0YW50ZSB0ZW5lciB1bmEgYmFzZSBkZSBkYXRvcyBsaW1waWEgcGFyYSBwb2RlciB0ZW5lciByZXN1bHRhZG9zIG3DoXMgY29uZmlhYmxlcyBwb3IgbG8gcXVlIGFuYWxpemFyIGxhcyBiYXNlcyBkZSBkYXRvcyBlcyB1biBwYXNvIG11eSBpbXBvcnRhbnRlLiBBIHBhcnRpciBkZSBsYXMgZ3LDoWZpY2FzIHBvZGVtb3MgdGVuZXIgdW4gYXBveW8gdmlzdWFsIHkgYXPDrSBzZSBwdWVkZSB0ZW5lciBjb25jbHVzaW9uZXMgbcOhcyBjbGFyYXMuIEFsIHRlbmVyIDMgYmFzZXMgZGUgZGF0b3MgY29uIHZhcmlhYmxlcyBkaWZlcmVudGVzIHNlIHB1ZWRlbiBjb21wbGVtZW50YXIgZW50cmUgc8OtIHkgYXPDrSB0ZW5lciB1bmEgc29sYSBiYXNlIGRlIGRhdG9zIG3DoXMgY29tcGxldGEuIAoK