JuveYell

Parte 1

## Descargar librerías
library(foreign)
library(dplyr)        # data manipulation 
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(forcats)      # to work with categorical variables
library(ggplot2)      # data visualization
library(readr)        # read specific csv files
library(janitor)      # data exploration and cleaning 
## 
## Attaching package: 'janitor'
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
library(Hmisc)        # several useful functions for data analysis 
## Loading required package: lattice
## Loading required package: survival
## Loading required package: Formula
## 
## Attaching package: 'Hmisc'
## The following objects are masked from 'package:dplyr':
## 
##     src, summarize
## The following objects are masked from 'package:base':
## 
##     format.pval, units
library(psych)        # functions for multivariate analysis 
## 
## Attaching package: 'psych'
## The following object is masked from 'package:Hmisc':
## 
##     describe
## The following objects are masked from 'package:ggplot2':
## 
##     %+%, alpha
library(naniar)       # summaries and visualization of missing values NAs
library(dlookr)       # summaries and visualization of missing values NAs
## 
## Attaching package: 'dlookr'
## The following object is masked from 'package:psych':
## 
##     describe
## The following object is masked from 'package:Hmisc':
## 
##     describe
## The following object is masked from 'package:base':
## 
##     transform
library(corrplot)     # correlation plots
## corrplot 0.92 loaded
library(jtools)       # presentation of regression analysis 
## 
## Attaching package: 'jtools'
## The following object is masked from 'package:Hmisc':
## 
##     %nin%
library(lmtest)       # diagnostic checks - linear regression analysis 
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(car)          # diagnostic checks - linear regression analysis
## Loading required package: carData
## 
## Attaching package: 'car'
## The following object is masked from 'package:psych':
## 
##     logit
## The following object is masked from 'package:dplyr':
## 
##     recode
library(olsrr)        # diagnostic checks - linear regression analysis 
## 
## Attaching package: 'olsrr'
## The following object is masked from 'package:datasets':
## 
##     rivers
library(kableExtra)   # HTML table attributes
## 
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
## 
##     group_rows
library(gmodels)
library(openxlsx)
library(crosstable)

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

### Importar base de datos
df1 <-read.csv(file.choose())
summary(df1)
##   Referencia           Fecha             Producto            Cantidad     
##  Length:251         Length:251         Length:251         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  
##                                                           NA's   :1       
##  Unidad.de.medida   Ubicación.de.origen Ubicación.de.desecho    Estado         
##  Length:251         Length:251          Length:251           Length:251        
##  Class :character   Class :character    Class :character     Class :character  
##  Mode  :character   Mode  :character    Mode  :character     Mode  :character  
##                                                                                
##                                                                                
##                                                                                
## 
describe(df1)
## # A tibble: 1 × 26
##   described_…¹     n    na  mean    sd se_mean   IQR skewn…² kurto…³   p00   p01
##   <chr>        <int> <int> <dbl> <dbl>   <dbl> <dbl>   <dbl>   <dbl> <dbl> <dbl>
## 1 Cantidad       250     1  6.70  11.8   0.749     6    4.17    21.8     0     1
## # … with 15 more variables: p05 <dbl>, p10 <dbl>, p20 <dbl>, p25 <dbl>,
## #   p30 <dbl>, p40 <dbl>, p50 <dbl>, p60 <dbl>, p70 <dbl>, p75 <dbl>,
## #   p80 <dbl>, p90 <dbl>, p95 <dbl>, p99 <dbl>, p100 <dbl>, and abbreviated
## #   variable names ¹​described_variables, ²​skewness, ³​kurtosis

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

### Referencia: Valor de referencia para identificar el producto.
### Fecha: Fecha de cuando se registró.
### Producto: Producto específico tirado.
### Cantidad: Cantidad de productos tirados.
### Unidad de medida: Unidad de medición para cada producto.
### Ubicación de origen: Ubicación dentro de almacén de donde proviene el producto.
### Ubicación de desecho: Ubicación donde es desechado el producto.
### Estado: Estado en el que se encuentra el desecho del producto ("En proceso", "Sin terminar", "Hecho").

variable<- c("Referencia","Fecha","Producto","Cantidad","Unidad.de.medida","Ubicación.de.origen","Ubicación.de.desecho","Estado")
type<- c("quantitative (continous)", "qualitative (discrete)","qualitative (continous)","quantitative (discrete)","qualitative (continous)","qualitative (continous)","qualitative (continous)","qualitative (continous)")
table1<-data.frame(variable,type)
knitr::kable(table1)
variable type
Referencia quantitative (continous)
Fecha qualitative (discrete)
Producto qualitative (continous)
Cantidad quantitative (discrete)
Unidad.de.medida qualitative (continous)
Ubicación.de.origen qualitative (continous)
Ubicación.de.desecho qualitative (continous)
Estado qualitative (continous)

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

variables1<- c("Referencia","Fecha","Producto","Cantidad","Unidad.de.medida","Ubicación.de.origen","Ubicación.de.desecho","Estado")
types2<- c("cuantitativo", "cualitativo", "cualitativo","cuantitativo","cualitativo","cualitativo","cualitativo","cualitativo")
scales2<- c("(nominal)", "(ordinal)","(nominal)","(razón)","(nominal)","(nominal)","(nominal)","(nominal)")
table2<- data.frame (variables1, types2, scales2)
knitr::kable(table2)
variables1 types2 scales2
Referencia cuantitativo (nominal)
Fecha cualitativo (ordinal)
Producto cualitativo (nominal)
Cantidad cuantitativo (razón)
Unidad.de.medida cualitativo (nominal)
Ubicación.de.origen cualitativo (nominal)
Ubicación.de.desecho cualitativo (nominal)
Estado cualitativo (nominal)

4. Aplica al menos 2 técnicas de limpieza de bases de datos y explícalas brevemente. ¿Por qué realizaste esas técnicas?

### Conversión de caracter a fecha
df2<-df1
df2$Fecha<-as.Date(df2$Fecha, format= "%d/%m/%Y")
summary(df2)
##   Referencia            Fecha              Producto            Cantidad     
##  Length:251         Min.   :2022-08-01   Length:251         Min.   : 0.000  
##  Class :character   1st Qu.:2022-08-11   Class :character   1st Qu.: 1.000  
##  Mode  :character   Median :2022-08-19   Mode  :character   Median : 2.000  
##                     Mean   :2022-08-17                      Mean   : 6.696  
##                     3rd Qu.:2022-08-25                      3rd Qu.: 7.000  
##                     Max.   :2022-08-31                      Max.   :96.000  
##                     NA's   :1                               NA's   :1       
##  Unidad.de.medida   Ubicación.de.origen Ubicación.de.desecho    Estado         
##  Length:251         Length:251          Length:251           Length:251        
##  Class :character   Class :character    Class :character     Class :character  
##  Mode  :character   Mode  :character    Mode  :character     Mode  :character  
##                                                                                
##                                                                                
##                                                                                
## 
### Eliminar renglones duplicados
df3<-df2
df3<-distinct(df3)

### ¿Cuántos NA's tengo en la base de datos? Primera limpieza
sum(is.na(df3))
## [1] 8
### Borrar todos los registros NA's de una tabla
df4<-df3
df4<-na.omit(df4)
summary(df4)
##   Referencia            Fecha              Producto            Cantidad     
##  Length:250         Min.   :2022-08-01   Length:250         Min.   : 0.000  
##  Class :character   1st Qu.:2022-08-11   Class :character   1st Qu.: 1.000  
##  Mode  :character   Median :2022-08-19   Mode  :character   Median : 2.000  
##                     Mean   :2022-08-17                      Mean   : 6.696  
##                     3rd Qu.:2022-08-25                      3rd Qu.: 7.000  
##                     Max.   :2022-08-31                      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  
##                                                                                
##                                                                                
## 
### ¿Cuántos NA's tengo en la base de datos? Segunda limpieza
sum(is.na(df4))
## [1] 0

5. Incluye una breve reflexión de la actividad.

### De acuerdo a la limpieza de datos realizada, vemos que es importante considerar los alcances y dificultades que pueden traer una base de datos sucia. Por esto, ahora logramos ver un análisis limpio con la información necesaria, sin datos duplicados, sin información irrelevante y con una mayor facilidad de interpretación.

Parte 2

6. Análisis estadístico descriptivo

describe(df4)
## # A tibble: 1 × 26
##   described_…¹     n    na  mean    sd se_mean   IQR skewn…² kurto…³   p00   p01
##   <chr>        <int> <int> <dbl> <dbl>   <dbl> <dbl>   <dbl>   <dbl> <dbl> <dbl>
## 1 Cantidad       250     0  6.70  11.8   0.749     6    4.17    21.8     0     1
## # … with 15 more variables: p05 <dbl>, p10 <dbl>, p20 <dbl>, p25 <dbl>,
## #   p30 <dbl>, p40 <dbl>, p50 <dbl>, p60 <dbl>, p70 <dbl>, p75 <dbl>,
## #   p80 <dbl>, p90 <dbl>, p95 <dbl>, p99 <dbl>, p100 <dbl>, and abbreviated
## #   variable names ¹​described_variables, ²​skewness, ³​kurtosis
count(df4, Fecha, sort = TRUE)
##         Fecha  n
## 1  2022-08-16 24
## 2  2022-08-24 21
## 3  2022-08-19 17
## 4  2022-08-30 17
## 5  2022-08-03 13
## 6  2022-08-10 13
## 7  2022-08-12 12
## 8  2022-08-26 12
## 9  2022-08-27 12
## 10 2022-08-22 11
## 11 2022-08-25 11
## 12 2022-08-31 10
## 13 2022-08-17  9
## 14 2022-08-20  9
## 15 2022-08-29  8
## 16 2022-08-05  7
## 17 2022-08-06  7
## 18 2022-08-04  6
## 19 2022-08-15  6
## 20 2022-08-02  5
## 21 2022-08-09  5
## 22 2022-08-13  5
## 23 2022-08-08  4
## 24 2022-08-11  3
## 25 2022-08-01  2
## 26 2022-08-23  1
count(df4, Cantidad, sort = TRUE)
##    Cantidad  n
## 1       1.0 76
## 2       2.0 59
## 3       4.0 18
## 4       3.0 14
## 5       6.0 11
## 6       8.0 10
## 7      10.0  8
## 8       9.0  6
## 9      20.0  5
## 10      5.0  4
## 11      7.0  4
## 12     12.0  4
## 13     24.0  4
## 14     15.0  3
## 15      2.5  2
## 16     13.0  2
## 17     16.0  2
## 18     19.0  2
## 19     36.0  2
## 20      0.0  1
## 21     11.0  1
## 22     14.0  1
## 23     18.0  1
## 24     28.0  1
## 25     31.0  1
## 26     40.0  1
## 27     43.0  1
## 28     48.0  1
## 29     51.0  1
## 30     56.0  1
## 31     60.0  1
## 32     80.0  1
## 33     96.0  1
count(df4, Unidad.de.medida, sort = TRUE)
##   Unidad.de.medida   n
## 1       Unidad(es) 250
count(df4, Ubicación.de.origen, sort = TRUE)
##         Ubicación.de.origen   n
## 1        SAB/Pre-Production 179
## 2 SAB/Calidad/Entrega de PT  58
## 3       SAB/Post-Production  13
count(df4, Ubicación.de.desecho, sort = TRUE)
##         Ubicación.de.desecho   n
## 1 Virtual Locations/Scrapped 250
count(df4, Estado, sort = TRUE)
##   Estado   n
## 1  Hecho 250
### Importar base de datos
df5<-df4

df5 <-read.csv(file.choose())
summary(df5)
##  Ubicación.de.origen    Cantidad       Producto         X          
##  Length:5            Min.   :1108   Min.   : 13.00   Mode:logical  
##  Class :character    1st Qu.:1379   1st Qu.: 35.50   NA's:5        
##  Mode  :character    Median :1650   Median : 58.00                 
##                      Mean   :1477   Mean   : 83.33                 
##                      3rd Qu.:1662   3rd Qu.:118.50                 
##                      Max.   :1674   Max.   :179.00                 
##                      NA's   :2      NA's   :2                      
##    X.1            X.2         
##  Mode:logical   Mode:logical  
##  NA's:5         NA's:5        
##                               
##                               
##                               
##                               
## 
describe(df5)
## # A tibble: 2 × 26
##   describe…¹     n    na   mean    sd se_mean   IQR skewn…² kurto…³   p00    p01
##   <chr>      <int> <int>  <dbl> <dbl>   <dbl> <dbl>   <dbl>   <dbl> <dbl>  <dbl>
## 1 Cantidad       3     2 1477.  320.    185.    283   -1.72      NA  1108 1119. 
## 2 Producto       3     2   83.3  85.9    49.6    83    1.21      NA    13   13.9
## # … with 15 more variables: p05 <dbl>, p10 <dbl>, p20 <dbl>, p25 <dbl>,
## #   p30 <dbl>, p40 <dbl>, p50 <dbl>, p60 <dbl>, p70 <dbl>, p75 <dbl>,
## #   p80 <dbl>, p90 <dbl>, p95 <dbl>, p99 <dbl>, p100 <dbl>, and abbreviated
## #   variable names ¹​described_variables, ²​skewness, ³​kurtosis
## 6.1 Tabla de frecuencia (1)

df5<-data.frame(df5$Ubicación.de.origen)
df5
##     df5.Ubicación.de.origen
## 1        SAB/Pre-Production
## 2 SAB/Calidad/Entrega de PT
## 3       SAB/Post-Production
## 4                          
## 5
df6<-
  data.frame(
    Ubicación.de.origen = c(
      "SAB/Pre-Production",
      "SAB/Calidad/Entrega de PT",
      "SAB/Post-Production"
    ),
    Cantidad = c(
      "1650",
      "1674",
      "1108"
    )
  )
df6
##         Ubicación.de.origen Cantidad
## 1        SAB/Pre-Production     1650
## 2 SAB/Calidad/Entrega de PT     1674
## 3       SAB/Post-Production     1108
## 6.2 Tabla cruzada (1)

table(df6$Ubicación.de.origen, df6$Cantidad)
##                            
##                             1108 1650 1674
##   SAB/Calidad/Entrega de PT    0    0    1
##   SAB/Post-Production          1    0    0
##   SAB/Pre-Production           0    1    0
## 6.3 Gráficos de datos cuantitativos y cualitativos (2)

## 6.3.1 Gráfica de barras

### Gráfica de barras: Cantidad de scrap generado VS. la ubicación de origen (Agosto 2022)

df6<- tapply(df6$Ubicación.de.origen, df6$Cantidad)

barplot(df6,
        main="Cantidad de scrap generado VS. la ubicación de origen (Agosto 2022)",
        xlab="Cantidad de scrap generado",
        ylab="y",
        col="orange",
        legend= rownames(df6), las=3
        )

### 6.3.2 Pie chart

### Importar base de datos
df7<-read.csv(file.choose())
summary(df7)
##  Ubicación.de.origen    Cantidad       Producto         X          
##  Length:5            Min.   :1108   Min.   : 13.00   Mode:logical  
##  Class :character    1st Qu.:1379   1st Qu.: 35.50   NA's:5        
##  Mode  :character    Median :1650   Median : 58.00                 
##                      Mean   :1477   Mean   : 83.33                 
##                      3rd Qu.:1662   3rd Qu.:118.50                 
##                      Max.   :1674   Max.   :179.00                 
##                      NA's   :2      NA's   :2                      
##    X.1            X.2         
##  Mode:logical   Mode:logical  
##  NA's:5         NA's:5        
##                               
##                               
##                               
##                               
## 
describe(df7)
## # A tibble: 2 × 26
##   describe…¹     n    na   mean    sd se_mean   IQR skewn…² kurto…³   p00    p01
##   <chr>      <int> <int>  <dbl> <dbl>   <dbl> <dbl>   <dbl>   <dbl> <dbl>  <dbl>
## 1 Cantidad       3     2 1477.  320.    185.    283   -1.72      NA  1108 1119. 
## 2 Producto       3     2   83.3  85.9    49.6    83    1.21      NA    13   13.9
## # … with 15 more variables: p05 <dbl>, p10 <dbl>, p20 <dbl>, p25 <dbl>,
## #   p30 <dbl>, p40 <dbl>, p50 <dbl>, p60 <dbl>, p70 <dbl>, p75 <dbl>,
## #   p80 <dbl>, p90 <dbl>, p95 <dbl>, p99 <dbl>, p100 <dbl>, and abbreviated
## #   variable names ¹​described_variables, ²​skewness, ³​kurtosis
### Eliminar columnas
df8<-df7
df8 <- subset(df8, select =-c (X))
df8 <- subset(df8, select =-c (X.1))
df8 <- subset(df8, select =-c (X.2))

### ¿Cuántos NA's tengo en la base de datos?
sum(is.na(df8))
## [1] 4
### Borrar todos los registros NA's de una tabla
df9<-df8
df9<-na.omit(df9)
summary(df9)
##  Ubicación.de.origen    Cantidad       Producto     
##  Length:3            Min.   :1108   Min.   : 13.00  
##  Class :character    1st Qu.:1379   1st Qu.: 35.50  
##  Mode  :character    Median :1650   Median : 58.00  
##                      Mean   :1477   Mean   : 83.33  
##                      3rd Qu.:1662   3rd Qu.:118.50  
##                      Max.   :1674   Max.   :179.00
### ¿Cuántos NA's tengo en la base de datos?
sum(is.na(df9))
## [1] 0
### Pie chart: "Total de productos individuales desechados en Agosto"
pie(table(df9$Producto), col=c("lightsalmon2","orange","coral1"),
    label = c("Post-Production (13)","Pre-Production (179)","Entrega de PT (58)"),
    main="Total de productos individuales desechados en Agosto")

## 6.4 Gráficos de dispersión (2)

### Gráfica de dispersión: Total de scrap generado
plot(df4$Cantidad, horizontal= TRUE,
     ylim= c(0, 100),
     xlim= c(0, 250),
     col= c("orange"),
     main= "Total de scrap generado")
## Warning in plot.window(...): "horizontal" is not a graphical parameter
## Warning in plot.xy(xy, type, ...): "horizontal" is not a graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "horizontal" is not
## a graphical parameter

## Warning in axis(side = side, at = at, labels = labels, ...): "horizontal" is not
## a graphical parameter
## Warning in box(...): "horizontal" is not a graphical parameter
## Warning in title(...): "horizontal" is not a graphical parameter

### Gráfica de dispersión: Scrap generado a lo largo de las 5 semanas de Agosto 2022
plot(x= df4$Fecha, y=df4$Cantidad,
     col= c("lightsalmon2"),
     main= "Scrap generado a lo largo de Agosto 2022")

7. Propuestas

Propuesta 1: Con la intención de reducir los errores de mano de obra al mínimo, se recomienda implementar un manual de capacitación para los empleados del área de producción y calidad con el objetivo de evitar descuidos, negligencias, usos incorrectos o irresponsabilidades, para reducir eficazmente el desperdicio de materia prima. Esto le dará a FORM una mejor estrategia de costos, así como relación con el capital humano, pues tendrán mejores herramientas para tratar errores productivos e incrementar su productividad a través de capacitación más especializada.

Propuesta 2: Para evitar el desperdicio, se recomienda replantear el almacenamiento de stock, esto con la intención de mejorar el espacio en piso para el orden de los materiales y optimizar el proceso de producción completo.

8. Conclusiones

Como se muestra en la información anterior, el área que mayor cantidad de ‘scrap’ total genera es “SAB/Calidad/Entrega de PT” aunque de manera individual. Los datos analizados muestran que en Agosto generó un total de 1,674 productos desechados, contra “SAB/Pre-Production” que tuvo 1,650 productos desechados y “SAB/Post-Production” que generó 1,108 productos desechados (el área con menor desecho). De forma individual, se muestra que hubo un desecho de 250 productos en las tres áreas a lo largo de Agosto. De esos 250 productos, “Pre-Production” desechó 179 productos. Esto pone en perspectiva no sólo la cantidad de desechos totales generados por área sino que también deja ver el desecho que genera cada producto. Sería importante evaluar no sólo el área con mayor generación de scrap sino también cuáles son las razones de que haya tanta generación de scrap y cuál es la eficiencia productiva de cada área. Reafirmando lo mencionado anteriormente, los datos muestran que hay un alto nivel de chatarra generada por parte del área de Calidad/Entrega de Producto Terminado. Sería necesario identificar las razones de este desperdicio y la manera de reducir este desecho al mínimo.

9. Referencias

Angelo Santana & Carmen Nieves Hernández, U. (2022). Gráficos en R: Diagramas de barras (barplots). Retrieved 26 September 2022, from https://estadistica-dma.ulpgc.es/cursoR4ULPGC/9b-grafBarplot.html

Packages, O., Power, S., Output, A., Examples, D., Questions, F., & Examples, T. et al. (2022). How can I add features or dimensions to my bar plot? | R FAQ. Retrieved 26 September 2022, from https://stats.oarc.ucla.edu/r/faq/how-can-i-add-features-or-dimensions-to-my-bar-plot/

RPubs - Función ggplot() de ggplot2. (2018). Retrieved 26 September 2022, from https://rpubs.com/daniballari/ggplot

Vega, J. (2022). R para principiantes. Retrieved 26 September 2022, from https://bookdown.org/jboscomendoza/r-principiantes4/matrices-y-arrays.html

LS0tDQp0aXRsZTogIkVudHJlZ2FibGUgMi40IHwgQW7DoWxpc2lzIGRlIGJhc2UgZGUgZGF0b3MgRk9STTogU0NSQVAiDQphdXRob3I6ICJKaW1lbmEgTWlndWVsIEEwMTM2NTgxOSINCmRhdGU6ICIyMDIyLTA5LTI2Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCi0tLQ0KDQo8ZGl2Pg0KPHAgc3R5bGUgPSAndGV4dC1hbGlnbjpjZW50ZXI7Jz4NCjxpbWcgc3JjPSJodHRwczovL21lZGlhLWV4cDEubGljZG4uY29tL2Rtcy9pbWFnZS9DNEQxNkFRRzM3dkZ0MmJpMTdRL3Byb2ZpbGUtZGlzcGxheWJhY2tncm91bmRpbWFnZS1zaHJpbmtfMjAwXzgwMC8wLzE2MzUxNzUwNTg2Njc/ZT0yMTQ3NDgzNjQ3JnY9YmV0YSZ0PVpYSG54eGYzWWVxeHY1X0xTYTlXMHhXakJZMXpVeXljUWY2b0dBR0l5RFEiIGFsdD0iSnV2ZVllbGwiIHdpZHRoPSIzMDBweCI+DQo8L3A+DQo8L2Rpdj4NCg0KIyMgUGFydGUgMQ0KYGBge3J9DQoNCiMjIERlc2NhcmdhciBsaWJyZXLDrWFzDQpsaWJyYXJ5KGZvcmVpZ24pDQpsaWJyYXJ5KGRwbHlyKSAgICAgICAgIyBkYXRhIG1hbmlwdWxhdGlvbiANCmxpYnJhcnkoZm9yY2F0cykgICAgICAjIHRvIHdvcmsgd2l0aCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMNCmxpYnJhcnkoZ2dwbG90MikgICAgICAjIGRhdGEgdmlzdWFsaXphdGlvbg0KbGlicmFyeShyZWFkcikgICAgICAgICMgcmVhZCBzcGVjaWZpYyBjc3YgZmlsZXMNCmxpYnJhcnkoamFuaXRvcikgICAgICAjIGRhdGEgZXhwbG9yYXRpb24gYW5kIGNsZWFuaW5nIA0KbGlicmFyeShIbWlzYykgICAgICAgICMgc2V2ZXJhbCB1c2VmdWwgZnVuY3Rpb25zIGZvciBkYXRhIGFuYWx5c2lzIA0KbGlicmFyeShwc3ljaCkgICAgICAgICMgZnVuY3Rpb25zIGZvciBtdWx0aXZhcmlhdGUgYW5hbHlzaXMgDQpsaWJyYXJ5KG5hbmlhcikgICAgICAgIyBzdW1tYXJpZXMgYW5kIHZpc3VhbGl6YXRpb24gb2YgbWlzc2luZyB2YWx1ZXMgTkFzDQpsaWJyYXJ5KGRsb29rcikgICAgICAgIyBzdW1tYXJpZXMgYW5kIHZpc3VhbGl6YXRpb24gb2YgbWlzc2luZyB2YWx1ZXMgTkFzDQpsaWJyYXJ5KGNvcnJwbG90KSAgICAgIyBjb3JyZWxhdGlvbiBwbG90cw0KbGlicmFyeShqdG9vbHMpICAgICAgICMgcHJlc2VudGF0aW9uIG9mIHJlZ3Jlc3Npb24gYW5hbHlzaXMgDQpsaWJyYXJ5KGxtdGVzdCkgICAgICAgIyBkaWFnbm9zdGljIGNoZWNrcyAtIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzIA0KbGlicmFyeShjYXIpICAgICAgICAgICMgZGlhZ25vc3RpYyBjaGVja3MgLSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcw0KbGlicmFyeShvbHNycikgICAgICAgICMgZGlhZ25vc3RpYyBjaGVja3MgLSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcyANCmxpYnJhcnkoa2FibGVFeHRyYSkgICAjIEhUTUwgdGFibGUgYXR0cmlidXRlcw0KbGlicmFyeShnbW9kZWxzKQ0KbGlicmFyeShvcGVueGxzeCkNCmxpYnJhcnkoY3Jvc3N0YWJsZSkNCmBgYA0KDQojIyAxLiDCv0N1w6FudGFzIHZhcmlhYmxlcyB5IGN1w6FudG9zIHJlZ2lzdHJvcyB0aWVuZSBsYSBiYXNlIGRlIGRhdG9zPw0KYGBge3J9DQoNCiMjIyBJbXBvcnRhciBiYXNlIGRlIGRhdG9zDQpkZjEgPC1yZWFkLmNzdihmaWxlLmNob29zZSgpKQ0Kc3VtbWFyeShkZjEpDQpkZXNjcmliZShkZjEpDQpgYGANCg0KIyMgMi4gQ2xhc2lmaWNhIGNhZGEgdmFyaWFibGUgZW4gY3VhbGl0YXRpdmEsIGN1YW50aXRhdGl2YSBkaXNjcmV0YSBvIGN1YW50aXRhdGl2YSBjb250aW51YS4NCmBgYHtyfQ0KDQojIyMgUmVmZXJlbmNpYTogVmFsb3IgZGUgcmVmZXJlbmNpYSBwYXJhIGlkZW50aWZpY2FyIGVsIHByb2R1Y3RvLg0KIyMjIEZlY2hhOiBGZWNoYSBkZSBjdWFuZG8gc2UgcmVnaXN0csOzLg0KIyMjIFByb2R1Y3RvOiBQcm9kdWN0byBlc3BlY8OtZmljbyB0aXJhZG8uDQojIyMgQ2FudGlkYWQ6IENhbnRpZGFkIGRlIHByb2R1Y3RvcyB0aXJhZG9zLg0KIyMjIFVuaWRhZCBkZSBtZWRpZGE6IFVuaWRhZCBkZSBtZWRpY2nDs24gcGFyYSBjYWRhIHByb2R1Y3RvLg0KIyMjIFViaWNhY2nDs24gZGUgb3JpZ2VuOiBVYmljYWNpw7NuIGRlbnRybyBkZSBhbG1hY8OpbiBkZSBkb25kZSBwcm92aWVuZSBlbCBwcm9kdWN0by4NCiMjIyBVYmljYWNpw7NuIGRlIGRlc2VjaG86IFViaWNhY2nDs24gZG9uZGUgZXMgZGVzZWNoYWRvIGVsIHByb2R1Y3RvLg0KIyMjIEVzdGFkbzogRXN0YWRvIGVuIGVsIHF1ZSBzZSBlbmN1ZW50cmEgZWwgZGVzZWNobyBkZWwgcHJvZHVjdG8gKCJFbiBwcm9jZXNvIiwgIlNpbiB0ZXJtaW5hciIsICJIZWNobyIpLg0KDQp2YXJpYWJsZTwtIGMoIlJlZmVyZW5jaWEiLCJGZWNoYSIsIlByb2R1Y3RvIiwiQ2FudGlkYWQiLCJVbmlkYWQuZGUubWVkaWRhIiwiVWJpY2FjacOzbi5kZS5vcmlnZW4iLCJVYmljYWNpw7NuLmRlLmRlc2VjaG8iLCJFc3RhZG8iKQ0KdHlwZTwtIGMoInF1YW50aXRhdGl2ZSAoY29udGlub3VzKSIsICJxdWFsaXRhdGl2ZSAoZGlzY3JldGUpIiwicXVhbGl0YXRpdmUgKGNvbnRpbm91cykiLCJxdWFudGl0YXRpdmUgKGRpc2NyZXRlKSIsInF1YWxpdGF0aXZlIChjb250aW5vdXMpIiwicXVhbGl0YXRpdmUgKGNvbnRpbm91cykiLCJxdWFsaXRhdGl2ZSAoY29udGlub3VzKSIsInF1YWxpdGF0aXZlIChjb250aW5vdXMpIikNCnRhYmxlMTwtZGF0YS5mcmFtZSh2YXJpYWJsZSx0eXBlKQ0Ka25pdHI6OmthYmxlKHRhYmxlMSkNCmBgYA0KDQojIyAzLiBFbGlnZSBsYSBlc2NhbGEgZGUgbWVkaWNpw7NuIGRlIGNhZGEgdmFyaWFibGUuDQpgYGB7cn0NCg0KdmFyaWFibGVzMTwtIGMoIlJlZmVyZW5jaWEiLCJGZWNoYSIsIlByb2R1Y3RvIiwiQ2FudGlkYWQiLCJVbmlkYWQuZGUubWVkaWRhIiwiVWJpY2FjacOzbi5kZS5vcmlnZW4iLCJVYmljYWNpw7NuLmRlLmRlc2VjaG8iLCJFc3RhZG8iKQ0KdHlwZXMyPC0gYygiY3VhbnRpdGF0aXZvIiwgImN1YWxpdGF0aXZvIiwgImN1YWxpdGF0aXZvIiwiY3VhbnRpdGF0aXZvIiwiY3VhbGl0YXRpdm8iLCJjdWFsaXRhdGl2byIsImN1YWxpdGF0aXZvIiwiY3VhbGl0YXRpdm8iKQ0Kc2NhbGVzMjwtIGMoIihub21pbmFsKSIsICIob3JkaW5hbCkiLCIobm9taW5hbCkiLCIocmF6w7NuKSIsIihub21pbmFsKSIsIihub21pbmFsKSIsIihub21pbmFsKSIsIihub21pbmFsKSIpDQp0YWJsZTI8LSBkYXRhLmZyYW1lICh2YXJpYWJsZXMxLCB0eXBlczIsIHNjYWxlczIpDQprbml0cjo6a2FibGUodGFibGUyKQ0KYGBgDQoNCiMjIDQuIEFwbGljYSBhbCBtZW5vcyAyIHTDqWNuaWNhcyBkZSBsaW1waWV6YSBkZSBiYXNlcyBkZSBkYXRvcyB5IGV4cGzDrWNhbGFzIGJyZXZlbWVudGUuIMK/UG9yIHF1w6kgcmVhbGl6YXN0ZSBlc2FzIHTDqWNuaWNhcz8NCmBgYHtyfQ0KDQojIyMgQ29udmVyc2nDs24gZGUgY2FyYWN0ZXIgYSBmZWNoYQ0KZGYyPC1kZjENCmRmMiRGZWNoYTwtYXMuRGF0ZShkZjIkRmVjaGEsIGZvcm1hdD0gIiVkLyVtLyVZIikNCnN1bW1hcnkoZGYyKQ0KDQojIyMgRWxpbWluYXIgcmVuZ2xvbmVzIGR1cGxpY2Fkb3MNCmRmMzwtZGYyDQpkZjM8LWRpc3RpbmN0KGRmMykNCg0KIyMjIMK/Q3XDoW50b3MgTkEncyB0ZW5nbyBlbiBsYSBiYXNlIGRlIGRhdG9zPyBQcmltZXJhIGxpbXBpZXphDQpzdW0oaXMubmEoZGYzKSkNCg0KIyMjIEJvcnJhciB0b2RvcyBsb3MgcmVnaXN0cm9zIE5BJ3MgZGUgdW5hIHRhYmxhDQpkZjQ8LWRmMw0KZGY0PC1uYS5vbWl0KGRmNCkNCnN1bW1hcnkoZGY0KQ0KDQojIyMgwr9DdcOhbnRvcyBOQSdzIHRlbmdvIGVuIGxhIGJhc2UgZGUgZGF0b3M/IFNlZ3VuZGEgbGltcGllemENCnN1bShpcy5uYShkZjQpKQ0KYGBgDQoNCiMjIDUuIEluY2x1eWUgdW5hIGJyZXZlIHJlZmxleGnDs24gZGUgbGEgYWN0aXZpZGFkLg0KYGBge3J9DQoNCiMjIyBEZSBhY3VlcmRvIGEgbGEgbGltcGllemEgZGUgZGF0b3MgcmVhbGl6YWRhLCB2ZW1vcyBxdWUgZXMgaW1wb3J0YW50ZSBjb25zaWRlcmFyIGxvcyBhbGNhbmNlcyB5IGRpZmljdWx0YWRlcyBxdWUgcHVlZGVuIHRyYWVyIHVuYSBiYXNlIGRlIGRhdG9zIHN1Y2lhLiBQb3IgZXN0bywgYWhvcmEgbG9ncmFtb3MgdmVyIHVuIGFuw6FsaXNpcyBsaW1waW8gY29uIGxhIGluZm9ybWFjacOzbiBuZWNlc2FyaWEsIHNpbiBkYXRvcyBkdXBsaWNhZG9zLCBzaW4gaW5mb3JtYWNpw7NuIGlycmVsZXZhbnRlIHkgY29uIHVuYSBtYXlvciBmYWNpbGlkYWQgZGUgaW50ZXJwcmV0YWNpw7NuLg0KYGBgDQoNCg0KIyMgUGFydGUgMg0KDQojIyA2LiBBbsOhbGlzaXMgZXN0YWTDrXN0aWNvIGRlc2NyaXB0aXZvDQpgYGB7cn0NCg0KZGVzY3JpYmUoZGY0KQ0KDQpjb3VudChkZjQsIEZlY2hhLCBzb3J0ID0gVFJVRSkNCmNvdW50KGRmNCwgQ2FudGlkYWQsIHNvcnQgPSBUUlVFKQ0KY291bnQoZGY0LCBVbmlkYWQuZGUubWVkaWRhLCBzb3J0ID0gVFJVRSkNCmNvdW50KGRmNCwgVWJpY2FjacOzbi5kZS5vcmlnZW4sIHNvcnQgPSBUUlVFKQ0KY291bnQoZGY0LCBVYmljYWNpw7NuLmRlLmRlc2VjaG8sIHNvcnQgPSBUUlVFKQ0KY291bnQoZGY0LCBFc3RhZG8sIHNvcnQgPSBUUlVFKQ0KDQojIyMgSW1wb3J0YXIgYmFzZSBkZSBkYXRvcw0KZGY1PC1kZjQNCg0KZGY1IDwtcmVhZC5jc3YoZmlsZS5jaG9vc2UoKSkNCnN1bW1hcnkoZGY1KQ0KZGVzY3JpYmUoZGY1KQ0KDQojIyA2LjEgVGFibGEgZGUgZnJlY3VlbmNpYSAoMSkNCg0KZGY1PC1kYXRhLmZyYW1lKGRmNSRVYmljYWNpw7NuLmRlLm9yaWdlbikNCmRmNQ0KDQpkZjY8LQ0KICBkYXRhLmZyYW1lKA0KICAgIFViaWNhY2nDs24uZGUub3JpZ2VuID0gYygNCiAgICAgICJTQUIvUHJlLVByb2R1Y3Rpb24iLA0KICAgICAgIlNBQi9DYWxpZGFkL0VudHJlZ2EgZGUgUFQiLA0KICAgICAgIlNBQi9Qb3N0LVByb2R1Y3Rpb24iDQogICAgKSwNCiAgICBDYW50aWRhZCA9IGMoDQogICAgICAiMTY1MCIsDQogICAgICAiMTY3NCIsDQogICAgICAiMTEwOCINCiAgICApDQogICkNCmRmNg0KDQojIyA2LjIgVGFibGEgY3J1emFkYSAoMSkNCg0KdGFibGUoZGY2JFViaWNhY2nDs24uZGUub3JpZ2VuLCBkZjYkQ2FudGlkYWQpDQoNCiMjIDYuMyBHcsOhZmljb3MgZGUgZGF0b3MgY3VhbnRpdGF0aXZvcyB5IGN1YWxpdGF0aXZvcyAoMikNCg0KIyMgNi4zLjEgR3LDoWZpY2EgZGUgYmFycmFzDQoNCiMjIyBHcsOhZmljYSBkZSBiYXJyYXM6IENhbnRpZGFkIGRlIHNjcmFwIGdlbmVyYWRvIFZTLiBsYSB1YmljYWNpw7NuIGRlIG9yaWdlbiAoQWdvc3RvIDIwMjIpDQoNCmRmNjwtIHRhcHBseShkZjYkVWJpY2FjacOzbi5kZS5vcmlnZW4sIGRmNiRDYW50aWRhZCkNCg0KYmFycGxvdChkZjYsDQogICAgICAgIG1haW49IkNhbnRpZGFkIGRlIHNjcmFwIGdlbmVyYWRvIFZTLiBsYSB1YmljYWNpw7NuIGRlIG9yaWdlbiAoQWdvc3RvIDIwMjIpIiwNCiAgICAgICAgeGxhYj0iQ2FudGlkYWQgZGUgc2NyYXAgZ2VuZXJhZG8iLA0KICAgICAgICB5bGFiPSJ5IiwNCiAgICAgICAgY29sPSJvcmFuZ2UiLA0KICAgICAgICBsZWdlbmQ9IHJvd25hbWVzKGRmNiksIGxhcz0zDQogICAgICAgICkNCg0KIyMjIDYuMy4yIFBpZSBjaGFydA0KDQojIyMgSW1wb3J0YXIgYmFzZSBkZSBkYXRvcw0KZGY3PC1yZWFkLmNzdihmaWxlLmNob29zZSgpKQ0Kc3VtbWFyeShkZjcpDQpkZXNjcmliZShkZjcpDQoNCiMjIyBFbGltaW5hciBjb2x1bW5hcw0KZGY4PC1kZjcNCmRmOCA8LSBzdWJzZXQoZGY4LCBzZWxlY3QgPS1jIChYKSkNCmRmOCA8LSBzdWJzZXQoZGY4LCBzZWxlY3QgPS1jIChYLjEpKQ0KZGY4IDwtIHN1YnNldChkZjgsIHNlbGVjdCA9LWMgKFguMikpDQoNCiMjIyDCv0N1w6FudG9zIE5BJ3MgdGVuZ28gZW4gbGEgYmFzZSBkZSBkYXRvcz8NCnN1bShpcy5uYShkZjgpKQ0KDQojIyMgQm9ycmFyIHRvZG9zIGxvcyByZWdpc3Ryb3MgTkEncyBkZSB1bmEgdGFibGENCmRmOTwtZGY4DQpkZjk8LW5hLm9taXQoZGY5KQ0Kc3VtbWFyeShkZjkpDQoNCiMjIyDCv0N1w6FudG9zIE5BJ3MgdGVuZ28gZW4gbGEgYmFzZSBkZSBkYXRvcz8NCnN1bShpcy5uYShkZjkpKQ0KDQojIyMgUGllIGNoYXJ0OiAiVG90YWwgZGUgcHJvZHVjdG9zIGluZGl2aWR1YWxlcyBkZXNlY2hhZG9zIGVuIEFnb3N0byINCnBpZSh0YWJsZShkZjkkUHJvZHVjdG8pLCBjb2w9YygibGlnaHRzYWxtb24yIiwib3JhbmdlIiwiY29yYWwxIiksDQogICAgbGFiZWwgPSBjKCJQb3N0LVByb2R1Y3Rpb24gKDEzKSIsIlByZS1Qcm9kdWN0aW9uICgxNzkpIiwiRW50cmVnYSBkZSBQVCAoNTgpIiksDQogICAgbWFpbj0iVG90YWwgZGUgcHJvZHVjdG9zIGluZGl2aWR1YWxlcyBkZXNlY2hhZG9zIGVuIEFnb3N0byIpDQoNCiMjIDYuNCBHcsOhZmljb3MgZGUgZGlzcGVyc2nDs24gKDIpDQoNCiMjIyBHcsOhZmljYSBkZSBkaXNwZXJzacOzbjogVG90YWwgZGUgc2NyYXAgZ2VuZXJhZG8NCnBsb3QoZGY0JENhbnRpZGFkLCBob3Jpem9udGFsPSBUUlVFLA0KICAgICB5bGltPSBjKDAsIDEwMCksDQogICAgIHhsaW09IGMoMCwgMjUwKSwNCiAgICAgY29sPSBjKCJvcmFuZ2UiKSwNCiAgICAgbWFpbj0gIlRvdGFsIGRlIHNjcmFwIGdlbmVyYWRvIikNCg0KIyMjIEdyw6FmaWNhIGRlIGRpc3BlcnNpw7NuOiBTY3JhcCBnZW5lcmFkbyBhIGxvIGxhcmdvIGRlIGxhcyA1IHNlbWFuYXMgZGUgQWdvc3RvIDIwMjINCnBsb3QoeD0gZGY0JEZlY2hhLCB5PWRmNCRDYW50aWRhZCwNCiAgICAgY29sPSBjKCJsaWdodHNhbG1vbjIiKSwNCiAgICAgbWFpbj0gIlNjcmFwIGdlbmVyYWRvIGEgbG8gbGFyZ28gZGUgQWdvc3RvIDIwMjIiKQ0KYGBgDQoNCiMjIDcuIFByb3B1ZXN0YXMNCg0KUHJvcHVlc3RhIDE6IENvbiBsYSBpbnRlbmNpw7NuIGRlIHJlZHVjaXIgbG9zIGVycm9yZXMgZGUgbWFubyBkZSBvYnJhIGFsIG3DrW5pbW8sIHNlIHJlY29taWVuZGEgaW1wbGVtZW50YXIgdW4gbWFudWFsIGRlIGNhcGFjaXRhY2nDs24gcGFyYSBsb3MgZW1wbGVhZG9zIGRlbCDDoXJlYSBkZSBwcm9kdWNjacOzbiB5IGNhbGlkYWQgY29uIGVsIG9iamV0aXZvIGRlIGV2aXRhciBkZXNjdWlkb3MsIG5lZ2xpZ2VuY2lhcywgdXNvcyBpbmNvcnJlY3RvcyBvIGlycmVzcG9uc2FiaWxpZGFkZXMsIHBhcmEgcmVkdWNpciBlZmljYXptZW50ZSBlbCBkZXNwZXJkaWNpbyBkZSBtYXRlcmlhIHByaW1hLiBFc3RvIGxlIGRhcsOhIGEgRk9STSB1bmEgbWVqb3IgZXN0cmF0ZWdpYSBkZSBjb3N0b3MsIGFzw60gY29tbyByZWxhY2nDs24gY29uIGVsIGNhcGl0YWwgaHVtYW5vLCBwdWVzIHRlbmRyw6FuIG1lam9yZXMgaGVycmFtaWVudGFzIHBhcmEgdHJhdGFyIGVycm9yZXMgcHJvZHVjdGl2b3MgZSBpbmNyZW1lbnRhciBzdSBwcm9kdWN0aXZpZGFkIGEgdHJhdsOpcyBkZSBjYXBhY2l0YWNpw7NuIG3DoXMgZXNwZWNpYWxpemFkYS4NCg0KUHJvcHVlc3RhIDI6IFBhcmEgZXZpdGFyIGVsIGRlc3BlcmRpY2lvLCBzZSByZWNvbWllbmRhIHJlcGxhbnRlYXIgZWwgYWxtYWNlbmFtaWVudG8gZGUgc3RvY2ssIGVzdG8gY29uIGxhIGludGVuY2nDs24gZGUgbWVqb3JhciBlbCBlc3BhY2lvIGVuIHBpc28gcGFyYSBlbCBvcmRlbiBkZSBsb3MgbWF0ZXJpYWxlcyB5IG9wdGltaXphciBlbCBwcm9jZXNvIGRlIHByb2R1Y2Npw7NuIGNvbXBsZXRvLg0KDQojIyA4LiBDb25jbHVzaW9uZXMNCkNvbW8gc2UgbXVlc3RyYSBlbiBsYSBpbmZvcm1hY2nDs24gYW50ZXJpb3IsIGVsIMOhcmVhIHF1ZSBtYXlvciBjYW50aWRhZCBkZSAnc2NyYXAnIHRvdGFsIGdlbmVyYSBlcyAiU0FCL0NhbGlkYWQvRW50cmVnYSBkZSBQVCIgYXVucXVlIGRlIG1hbmVyYSBpbmRpdmlkdWFsLiBMb3MgZGF0b3MgYW5hbGl6YWRvcyBtdWVzdHJhbiBxdWUgZW4gQWdvc3RvIGdlbmVyw7MgdW4gdG90YWwgZGUgMSw2NzQgcHJvZHVjdG9zIGRlc2VjaGFkb3MsIGNvbnRyYSAiU0FCL1ByZS1Qcm9kdWN0aW9uIiBxdWUgdHV2byAxLDY1MCBwcm9kdWN0b3MgZGVzZWNoYWRvcyB5ICJTQUIvUG9zdC1Qcm9kdWN0aW9uIiBxdWUgZ2VuZXLDsyAxLDEwOCBwcm9kdWN0b3MgZGVzZWNoYWRvcyAoZWwgw6FyZWEgY29uIG1lbm9yIGRlc2VjaG8pLiBEZSBmb3JtYSBpbmRpdmlkdWFsLCBzZSBtdWVzdHJhIHF1ZSBodWJvIHVuIGRlc2VjaG8gZGUgMjUwIHByb2R1Y3RvcyBlbiBsYXMgdHJlcyDDoXJlYXMgYSBsbyBsYXJnbyBkZSBBZ29zdG8uIERlIGVzb3MgMjUwIHByb2R1Y3RvcywgIlByZS1Qcm9kdWN0aW9uIiBkZXNlY2jDsyAxNzkgcHJvZHVjdG9zLiBFc3RvIHBvbmUgZW4gcGVyc3BlY3RpdmEgbm8gc8OzbG8gbGEgY2FudGlkYWQgZGUgZGVzZWNob3MgdG90YWxlcyBnZW5lcmFkb3MgcG9yIMOhcmVhIHNpbm8gcXVlIHRhbWJpw6luIGRlamEgdmVyIGVsIGRlc2VjaG8gcXVlIGdlbmVyYSBjYWRhIHByb2R1Y3RvLiBTZXLDrWEgaW1wb3J0YW50ZSBldmFsdWFyIG5vIHPDs2xvIGVsIMOhcmVhIGNvbiBtYXlvciBnZW5lcmFjacOzbiBkZSBzY3JhcCBzaW5vIHRhbWJpw6luIGN1w6FsZXMgc29uIGxhcyByYXpvbmVzIGRlIHF1ZSBoYXlhIHRhbnRhIGdlbmVyYWNpw7NuIGRlIHNjcmFwIHkgY3XDoWwgZXMgbGEgZWZpY2llbmNpYSBwcm9kdWN0aXZhIGRlIGNhZGEgw6FyZWEuIFJlYWZpcm1hbmRvIGxvIG1lbmNpb25hZG8gYW50ZXJpb3JtZW50ZSwgbG9zIGRhdG9zIG11ZXN0cmFuIHF1ZSBoYXkgdW4gYWx0byBuaXZlbCBkZSBjaGF0YXJyYSBnZW5lcmFkYSBwb3IgcGFydGUgZGVsIMOhcmVhIGRlIENhbGlkYWQvRW50cmVnYSBkZSBQcm9kdWN0byBUZXJtaW5hZG8uIFNlcsOtYSBuZWNlc2FyaW8gaWRlbnRpZmljYXIgbGFzIHJhem9uZXMgZGUgZXN0ZSBkZXNwZXJkaWNpbyB5IGxhIG1hbmVyYSBkZSByZWR1Y2lyIGVzdGUgZGVzZWNobyBhbCBtw61uaW1vLg0KDQojIyA5LiBSZWZlcmVuY2lhcw0KICBBbmdlbG8gU2FudGFuYSAmYW1wOyBDYXJtZW4gTmlldmVzIEhlcm7DoW5kZXosIFUuICgyMDIyKS4gR3LDoWZpY29zIGVuIFI6IERpYWdyYW1hcyBkZSBiYXJyYXMgKGJhcnBsb3RzKS4gUmV0cmlldmVkIDI2IFNlcHRlbWJlciAyMDIyLCBmcm9tIGh0dHBzOi8vZXN0YWRpc3RpY2EtZG1hLnVscGdjLmVzL2N1cnNvUjRVTFBHQy85Yi1ncmFmQmFycGxvdC5odG1sDQoNCiAgUGFja2FnZXMsIE8uLCBQb3dlciwgUy4sIE91dHB1dCwgQS4sIEV4YW1wbGVzLCBELiwgUXVlc3Rpb25zLCBGLiwgJiBFeGFtcGxlcywgVC4gZXQgYWwuICgyMDIyKS4gSG93IGNhbiBJIGFkZCBmZWF0dXJlcyBvciBkaW1lbnNpb25zIHRvIG15IGJhciBwbG90PyB8IFIgRkFRLiBSZXRyaWV2ZWQgMjYgU2VwdGVtYmVyIDIwMjIsIGZyb20gaHR0cHM6Ly9zdGF0cy5vYXJjLnVjbGEuZWR1L3IvZmFxL2hvdy1jYW4taS1hZGQtZmVhdHVyZXMtb3ItZGltZW5zaW9ucy10by1teS1iYXItcGxvdC8NCg0KICBSUHVicyAtIEZ1bmNpw7NuIGdncGxvdCgpIGRlIGdncGxvdDIuICgyMDE4KS4gUmV0cmlldmVkIDI2IFNlcHRlbWJlciAyMDIyLCBmcm9tIGh0dHBzOi8vcnB1YnMuY29tL2RhbmliYWxsYXJpL2dncGxvdA0KDQogIFZlZ2EsIEouICgyMDIyKS4gUiBwYXJhIHByaW5jaXBpYW50ZXMuIFJldHJpZXZlZCAyNiBTZXB0ZW1iZXIgMjAyMiwgZnJvbSBodHRwczovL2Jvb2tkb3duLm9yZy9qYm9zY29tZW5kb3phL3ItcHJpbmNpcGlhbnRlczQvbWF0cmljZXMteS1hcnJheXMuaHRtbA==