Instalacion de paquetes

library(plyr)
library(tidyverse)
library(knitr)
library(foreign)
library(dplyr)        # data manipulation 
library(forcats)      # to work with categorical variables
library(ggplot2)      # data visualization 
library(janitor)      # data exploration and cleaning 
#install.packages("Hmisc")
library(Hmisc)        # several useful functions for data analysis 
#install.packages("psych")
library(psych)        # functions for multivariate analysis 
#install.packages("naniar")
library(naniar)       # summaries and visualization of missing values NAs
#install.packages("dlookr")
library(dlookr)  # summaries and visualization of missing values NAs
#install.packages("corrplot")
library(corrplot)     # correlation plots
#install.packages("jtools")
library(jtools)       # presentation of regression analysis 
#install.packages("lmtest")
library(lmtest)       # diagnostic checks - linear regression analysis 
#install.packages("car")
library(car)          # diagnostic checks - linear regression analysis
#install.packages("olsrr")
library(olsrr)        # diagnostic checks - linear regression analysis 
#install.packages("kableExtra")
library(kableExtra)   # HTML table attributes

Importar la base de datos

#file.choose()
MERMA<- read.csv("/Users/emilioolvera/Downloads/FORM - Merma.csv")
SCRAP<- read.csv("/Users/emilioolvera/Downloads/Scrap.csv")
PRODUCCION<- read.csv("/Users/emilioolvera/Downloads/FORM - Producción Carton.csv")

¿Cuántas variables y cuantos registros tienen las base de datos?

La base de datos de Merma tiene 60 registros Y 3 variables.

describe(MERMA)
## # A tibble: 0 × 9
## # … with 9 variables: described_variables <chr>, n <int>, na <int>, mean <dbl>,
## #   sd <dbl>, se_mean <dbl>, IQR <dbl>, skewness <dbl>, kurtosis <dbl>
dim(MERMA)
## [1] 60  3

La base de datos de Scrap tiene 251 registros Y 9 variables.

describe(SCRAP)
## # 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       251     0  13.3  106.    6.68     6    15.6    245.     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
dim(SCRAP)
## [1] 251   8

La base de datos de Producción tiene 2469 registros y 17 variables

describe(PRODUCCION)
## # A tibble: 5 × 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 No.         2469     0 1.24e3 713.    14.3    1234    0      -1.2      1 25.7 
## 2 PIEZAS.P.…  2468     1 1.83e2 150.     3.02    108    2.11    7.49     1  8.67
## 3 Laminas.P…  1908   561 1.09e2 134.     3.08    200    2.34    8.68     0  0   
## 4 TIEMPO.MA…   321  2148 2.32e0   5.93   0.331     1    3.94   20.1      0  0   
## 5 MERMAS.Ma…   107  2362 1.63e0   5.02   0.485     1    8.70   83.2      0  0   
## # … 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
dim(PRODUCCION)
## [1] 2469   17

Clasificacion de las variables.

Tipos de Variable: Merma

Variable Type escalas
Fecha Cualitativa nominal
Mes Cualitativa nominal
Kilos Cuantitativa (discreta) ordinal

Tipos de Variable: Scrap

Variable Type
Referencia Cualitativa
Fecha Cualitativa
Hora Cuantitativa (continua)
Producto Cualitativa
Cantidad Cuantitativa (discreta)
Unidad de medidad Cualitativa
Ubicación de origen Cualitativa
Ubicación de desecho Cualitativa
Estado Cualitativa

Tipos de Variable: Producción

Variable<-c("`Cliente`","`ID Form`", "`Producto`","`Piezas programadas`", "`Tiempo minutos`", "`Hora fin`", "`Estacion arranque`", "`Laminas procesadas`", "`Inicio set up`", "`Fin inicio set up`", "`Inicio de proceso`", "`Fin de proceso`", "`Tiempo calidad`")
Type<-c("Cualitativa","Cualitativa", "Cualitativa","Cuantitativa (discreta)", "Cuantitativa (discreta)", "Cuantitativa (continua)", "Cualitativa", "Cuantitativa (discreta)", "Cuantitativa (continua)", "Cuantitativa (continua)", "Cuantitativa (continua)", "Cuantitativa (continua)", "Cuantitativa (discreta)" )
Escalas<-c("Nominal", "Nominal","Nominal", "Intervalo", "Intervalo", "Intervalo", "Intervalo","Intervalo","Intervalo","Intervalo","Intervalo","Intervalo","Intervalo" ) 
table<-data.frame(Variable,Type,Escalas)
knitr::kable(table)
Variable Type Escalas
Cliente Cualitativa Nominal
ID Form Cualitativa Nominal
Producto Cualitativa Nominal
Piezas programadas Cuantitativa (discreta) Intervalo
Tiempo minutos Cuantitativa (discreta) Intervalo
Hora fin Cuantitativa (continua) Intervalo
Estacion arranque Cualitativa Intervalo
Laminas procesadas Cuantitativa (discreta) Intervalo
Inicio set up Cuantitativa (continua) Intervalo
Fin inicio set up Cuantitativa (continua) Intervalo
Inicio de proceso Cuantitativa (continua) Intervalo
Fin de proceso Cuantitativa (continua) Intervalo
Tiempo calidad Cuantitativa (discreta) Intervalo

Limpieza de las bases de datos

Limpieza de Datos para la base de datos de merma .

Cambio de tipo de Variable:

La variable de Kilos estaba en formato de carácter y se paso a numérica.

str(MERMA)
## 'data.frame':    60 obs. of  3 variables:
##  $ Fecha: chr  "1/11/22" "1/11/22" "1/22/22" "1/22/22" ...
##  $ Mes  : chr  "ENERO" "ENERO" "ENERO" "ENERO" ...
##  $ Kilos: chr  "5080" "3810" "2990" "2680" ...
MERMA$Kilos <- as.numeric(MERMA$Kilos)
## Warning: NAs introduced by coercion

Despues de cambiar la variante que estaba de caracter a numerica se quizo hacer que se mostraran solamente el total de kilos por mes por lo cual despues de ver esta informacion pude ver que el mes con mayor cantidad de merma fue agosto

MERMA1<-aggregate(Kilos ~ Mes , data = MERMA, sum)

Limpieza de Datos para la base de datos de scrap .

Eliminar columnas que no agreguen valor o que sean datos repetitivos

SCRAP1 <- SCRAP
SCRAP1 <- select(SCRAP1, Fecha, Cantidad, Ubicación.de.origen)

Eliminar renglón de Unidades totales de scrap

SCRAP1 <- SCRAP1 [- c(1),]

Borrar todos los registros NA de una tabla para tener una base de datos mas eficiente, se quiso hacer esto para no tomar en cuenta el dia que no hubo produccion

SCRAP2 <- SCRAP1
SCRAP2 <- na.omit(SCRAP2)    
str(SCRAP2)
## 'data.frame':    250 obs. of  3 variables:
##  $ Fecha              : chr  "2022-08-31 14:55:40" "2022-08-31 14:49:25" "2022-08-31 13:49:29" "2022-08-31 09:30:07" ...
##  $ Cantidad           : num  2 1 1 31 1 1 1 9 2 1 ...
##  $ Ubicación.de.origen: chr  "SAB/Calidad/Entrega de PT" "SAB/Calidad/Entrega de PT" "SAB/Calidad/Entrega de PT" "SAB/Pre-Production" ...

Limpieza de Datos para la base de datos de Producción.

Reemplazar NA con ceros

PRODUCCION[is.na(PRODUCCION)]<-0
summary(PRODUCCION)
##       No.         CLIENTE            ID.FORM            P..DUCTO        
##  Min.   :   1   Length:2469        Length:2469        Length:2469       
##  1st Qu.: 618   Class :character   Class :character   Class :character  
##  Median :1235   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :1235                                                           
##  3rd Qu.:1852                                                           
##  Max.   :2469                                                           
##   PIEZAS.P..G.     TMO..MIN.           HR..FIN          ESTACION.AR..NQUE 
##  Min.   :   0.0   Length:2469        Length:2469        Length:2469       
##  1st Qu.: 100.0   Class :character   Class :character   Class :character  
##  Median : 160.0   Mode  :character   Mode  :character   Mode  :character  
##  Mean   : 182.7                                                           
##  3rd Qu.: 208.0                                                           
##  Max.   :1280.0                                                           
##  Laminas.Procesadas INICIO.SEP.UP      FIN.INICIO.DE.SEP.UP INICIO.de.P....SO 
##  Min.   :   0.00    Length:2469        Length:2469          Length:2469       
##  1st Qu.:   0.00    Class :character   Class :character     Class :character  
##  Median :  29.00    Mode  :character   Mode  :character     Mode  :character  
##  Mean   :  83.87                                                              
##  3rd Qu.: 122.00                                                              
##  Max.   :1125.00                                                              
##  FIN.de.P....SO     TIEMPO..CALIDAD    TIEMPO.MATERIALES MERMAS.Maquinas.  
##  Length:2469        Length:2469        Min.   : 0.0000   Min.   : 0.00000  
##  Class :character   Class :character   1st Qu.: 0.0000   1st Qu.: 0.00000  
##  Mode  :character   Mode  :character   Median : 0.0000   Median : 0.00000  
##                                        Mean   : 0.3017   Mean   : 0.07047  
##                                        3rd Qu.: 0.0000   3rd Qu.: 0.00000  
##                                        Max.   :48.0000   Max.   :50.00000  
##      Date          
##  Length:2469       
##  Class :character  
##  Mode  :character  
##                    
##                    
## 

Eliminar columnas no relevantes

PRODUCCION1 <- PRODUCCION
PRODUCCION1<-subset(PRODUCCION1,select=-c(No.,ID.FORM,P..DUCTO,HR..FIN, ESTACION.AR..NQUE,INICIO.SEP.UP,FIN.INICIO.DE.SEP.UP,INICIO.de.P....SO,FIN.de.P....SO,TIEMPO..CALIDAD,TIEMPO.MATERIALES,MERMAS.Maquinas.))
str(PRODUCCION1)
## 'data.frame':    2469 obs. of  5 variables:
##  $ CLIENTE           : chr  "VARROC" "VARROC" "VARROC" "DENSO" ...
##  $ PIEZAS.P..G.      : num  199 57 68 192 192 400 80 104 104 160 ...
##  $ TMO..MIN.         : chr  "15" "10" "10" "15" ...
##  $ Laminas.Procesadas: num  201 116 69 49 49 801 41 53 53 55 ...
##  $ Date              : chr  "01/08/22" "01/08/22" "01/08/22" "01/08/22" ...

Pasar fila a nombres de columna

PRODUCCION2 <- PRODUCCION
colnames(PRODUCCION2) <- PRODUCCION[1,]
colnames(PRODUCCION2)
##  [1] "1"               "VARROC"          "VL-017-13938"    "763 . KIT.  JA."
##  [5] "199"             "15"              "9:15"            "C1"             
##  [9] "201"             "9:00"            "9:12"            "9:13"           
## [13] "9:26"            "1"               "0"               "0"              
## [17] "01/08/22"

Eliminar primer fila

PRODUCCION2 <- PRODUCCION2[-1,]

Análisis estadístico descriptivo.

Tabla de frecuencia para merma

table(MERMA1$Mes, MERMA1$Kilos)
##             
##              13586 14560 18280 18820 19370 22470 22830 23410 32100
##   ABRIL          0     0     0     1     0     0     0     0     0
##   AGOSTO         0     0     0     0     0     0     0     0     1
##   ENERO          0     1     0     0     0     0     0     0     0
##   FEBRERO        0     0     0     0     0     0     1     0     0
##   JULIO          0     0     0     0     1     0     0     0     0
##   JUNIO          0     0     1     0     0     0     0     0     0
##   MARZO          0     0     0     0     0     1     0     0     0
##   MAYO           0     0     0     0     0     0     0     1     0
##   SEPTIEMBRE     1     0     0     0     0     0     0     0     0
prop.table(table(MERMA1$Mes, MERMA1$Kilos))
##             
##                  13586     14560     18280     18820     19370     22470
##   ABRIL      0.0000000 0.0000000 0.0000000 0.1111111 0.0000000 0.0000000
##   AGOSTO     0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000
##   ENERO      0.0000000 0.1111111 0.0000000 0.0000000 0.0000000 0.0000000
##   FEBRERO    0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000
##   JULIO      0.0000000 0.0000000 0.0000000 0.0000000 0.1111111 0.0000000
##   JUNIO      0.0000000 0.0000000 0.1111111 0.0000000 0.0000000 0.0000000
##   MARZO      0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.1111111
##   MAYO       0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000
##   SEPTIEMBRE 0.1111111 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000
##             
##                  22830     23410     32100
##   ABRIL      0.0000000 0.0000000 0.0000000
##   AGOSTO     0.0000000 0.0000000 0.1111111
##   ENERO      0.0000000 0.0000000 0.0000000
##   FEBRERO    0.1111111 0.0000000 0.0000000
##   JULIO      0.0000000 0.0000000 0.0000000
##   JUNIO      0.0000000 0.0000000 0.0000000
##   MARZO      0.0000000 0.0000000 0.0000000
##   MAYO       0.0000000 0.1111111 0.0000000
##   SEPTIEMBRE 0.0000000 0.0000000 0.0000000

La tabla de frecuencia se hizo de los Kilos y esta me sirvio para ver que nunca tienen el mismo monto de merma

Tabla de frecuencia de Scrap

FREC_SCRAP<-SCRAP1 %>% group_by(Cantidad) %>% tally()
FREC_SCRAP
## # A tibble: 33 × 2
##    Cantidad     n
##       <dbl> <int>
##  1      0       1
##  2      1      76
##  3      2      59
##  4      2.5     2
##  5      3      14
##  6      4      18
##  7      5       4
##  8      6      11
##  9      7       4
## 10      8      10
## # … with 23 more rows

La tabla de frecuencia de scrap se hizo de cantidad y esta me sirvio para ver como varia la cantidad de scrap la cual se ve reflejada yendo a varias ubicaciones la cual es 1

Tabla de frecuencia de Produccion

FREC_PROD<-PRODUCCION1 %>% group_by(PIEZAS.P..G.) %>% tally()
FREC_PROD
## # A tibble: 155 × 2
##    PIEZAS.P..G.     n
##           <dbl> <int>
##  1            0     1
##  2            1     2
##  3            2     3
##  4            3     1
##  5            4     4
##  6            5     3
##  7            6     3
##  8            7     2
##  9            8     7
## 10            9     1
## # … with 145 more rows

La tabla de frecuencia de produccion se hizo de piezas, esta me sirvio para ver como es que las piezas de produccion se van vendiendo

Grafica de dispersion para merma.

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

En esta grafica podemos apreciar los datos de lo que son los kilos que tienen de merma por mes en donde se puede ver que en agosto es cuando se tiene el mayor numero de merma, dato que ya habia mencionado antes en el apartado de cuando se hizo la limpieza de datos

Grafica de dispersion de scrap

ggplot(data=SCRAP2, mapping = aes(Cantidad, Ubicación.de.origen)) + geom_point(aes()) + theme_bw()

Gráfica de Dispersión para Scrap

ggplot(data=SCRAP1, mapping =
aes(Cantidad, Ubicación.de.origen)) +
  geom_point(aes()) + theme_bw()

En esta grafica de dispersion se puede apreciar visualmente la cantidad que se produce en cada ubicacion, tal fue de ayuda para ver que en SAB/Pre-Production es la que mas tiene Scrap.

Gráfica de Dispersión para Producción

ggplot(PRODUCCION1, aes(x=`PIEZAS.P..G.`, y=CLIENTE)) + 
    geom_point() 

En esta grafica de dispersion se puede apreciar visualmente la cantidad de piezas que se demandan para los diferentes clientes.

Grafico de barras de los kilos de MERMA que se producen por mes

ggplot(MERMA1, aes(x=Mes, y=Kilos)) +
  geom_bar(stat="identity", fill="yellow") + scale_fill_grey() + 
  labs(title = "Grafica de Barras de los kilos de merma que hay por mes.", 
       x = "Mes", y = "Kilos")

Visualmente podemos ver que Agosto tiene el mayor numero de merma a comparacion de los otros meses

Grafico de barras de SCRAP de la cantidad de las piezas por la ubicación

ggplot(SCRAP2, aes(x=Ubicación.de.origen, y=Cantidad)) +
  geom_bar(stat="identity", fill="BLUE") + scale_fill_grey() + 
  labs(title = "Grafico de barras de las unidades de Scrap por ubicacion de origen", 
       x = "Unidades", y = "Ubicación")

En esta grafica de barras es visualmente claro que como se menciono anteriormente, el area de pre-production es la que mas scrap lleva.

PROPUESTAS

PROPUESTA PARA MERMA

Como propuesta para la merma, se tiene que implementar un plan que minimice la cantidad de merma generada, la cual se ve que fue alta en los meses de de Agosto y Septiembre donde se requiere determinar la causa del alto nivel de estos desechos, para asi poder prevenir futuros gastos extra y asi no volver a tener este problema.

PROPUESTA PARA SCRAP

Como propuesta para scrap, puedo decir que en el area de Pre-production siendo el area que mas scrap lleva se tiene que implementar un plan para disminuir esto ya que se podria decir que se reflajan gastos extra que son innecesarios.

PROPUESTA PARA PRODUCCION

Como primera propuesta para produccion puedo decir que se sigan adaptando a las necesidades de los cientes pero que tambien traten de implementar otras maneras ya que se quiere llegar a todos los clientes posibles y no estar segmentando, por lo cual es importante de tratar de abrirse mas hacia los clientes que no les llegan a pedir las mismas demandas.

Reflexion de la actividad

Realizar el análisis de FORM fue muy interesante porque eso me permitió darme cuenta del gran potencial que puede llegar a tener una empresa y que muchas veces no se tiene en cuenta el alcance al que se puede llegar y aprovechar los recursos o bien, las oportunidades que se tienen para mejorar la situación de la empresa y que en este caso, FORM teniendo diferentes puntos a ver puede hacer de esta situación una oportunidad para hacer un cambio positivo. El haber analizado las bases de datos tambien me dio una percepción muy amplia y clara sobre la posición que tiene FORM y en base a ello poder tomar mejores decisiones que lleven a la organización a ser más competitiva y tener la oportunidad de expandir el mercado en el que se encuentre en ese momento la empresa, evitando siempre todos los riesgos que se puedan presentar, o al menos saber responder con mayor certeza ante ellos.

LS0tCnRpdGxlOiAiRU5UUkVHQUJMRSBFTUlMSU8gMi40IgphdXRob3I6ICJFbWlsaW8gT2x2ZXJhIgpkYXRlOiAiMjAyMi0wOS0yOCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICB0b2M6IHRydWUKICAgdG9jX2Zsb2F0OiB0cnVlCiAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCiMgPGltZyBzcmM9Ii9Vc2Vycy9lbWlsaW9vbHZlcmEvRGVza3RvcC9Qb3J0YWZvbGlvIGRlbCBtb2R1bG8vRk9STS5wbmciPiAKCiMjIEluc3RhbGFjaW9uIGRlIHBhcXVldGVzIAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShwbHlyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShrbml0cikKbGlicmFyeShmb3JlaWduKQpsaWJyYXJ5KGRwbHlyKSAgICAgICAgIyBkYXRhIG1hbmlwdWxhdGlvbiAKbGlicmFyeShmb3JjYXRzKSAgICAgICMgdG8gd29yayB3aXRoIGNhdGVnb3JpY2FsIHZhcmlhYmxlcwpsaWJyYXJ5KGdncGxvdDIpICAgICAgIyBkYXRhIHZpc3VhbGl6YXRpb24gCmxpYnJhcnkoamFuaXRvcikgICAgICAjIGRhdGEgZXhwbG9yYXRpb24gYW5kIGNsZWFuaW5nIAojaW5zdGFsbC5wYWNrYWdlcygiSG1pc2MiKQpsaWJyYXJ5KEhtaXNjKSAgICAgICAgIyBzZXZlcmFsIHVzZWZ1bCBmdW5jdGlvbnMgZm9yIGRhdGEgYW5hbHlzaXMgCiNpbnN0YWxsLnBhY2thZ2VzKCJwc3ljaCIpCmxpYnJhcnkocHN5Y2gpICAgICAgICAjIGZ1bmN0aW9ucyBmb3IgbXVsdGl2YXJpYXRlIGFuYWx5c2lzIAojaW5zdGFsbC5wYWNrYWdlcygibmFuaWFyIikKbGlicmFyeShuYW5pYXIpICAgICAgICMgc3VtbWFyaWVzIGFuZCB2aXN1YWxpemF0aW9uIG9mIG1pc3NpbmcgdmFsdWVzIE5BcwojaW5zdGFsbC5wYWNrYWdlcygiZGxvb2tyIikKbGlicmFyeShkbG9va3IpICAjIHN1bW1hcmllcyBhbmQgdmlzdWFsaXphdGlvbiBvZiBtaXNzaW5nIHZhbHVlcyBOQXMKI2luc3RhbGwucGFja2FnZXMoImNvcnJwbG90IikKbGlicmFyeShjb3JycGxvdCkgICAgICMgY29ycmVsYXRpb24gcGxvdHMKI2luc3RhbGwucGFja2FnZXMoImp0b29scyIpCmxpYnJhcnkoanRvb2xzKSAgICAgICAjIHByZXNlbnRhdGlvbiBvZiByZWdyZXNzaW9uIGFuYWx5c2lzIAojaW5zdGFsbC5wYWNrYWdlcygibG10ZXN0IikKbGlicmFyeShsbXRlc3QpICAgICAgICMgZGlhZ25vc3RpYyBjaGVja3MgLSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcyAKI2luc3RhbGwucGFja2FnZXMoImNhciIpCmxpYnJhcnkoY2FyKSAgICAgICAgICAjIGRpYWdub3N0aWMgY2hlY2tzIC0gbGluZWFyIHJlZ3Jlc3Npb24gYW5hbHlzaXMKI2luc3RhbGwucGFja2FnZXMoIm9sc3JyIikKbGlicmFyeShvbHNycikgICAgICAgICMgZGlhZ25vc3RpYyBjaGVja3MgLSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcyAKI2luc3RhbGwucGFja2FnZXMoImthYmxlRXh0cmEiKQpsaWJyYXJ5KGthYmxlRXh0cmEpICAgIyBIVE1MIHRhYmxlIGF0dHJpYnV0ZXMKYGBgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWUiPiBJbXBvcnRhciBsYSBiYXNlIGRlIGRhdG9zIDwvc3Bhbj4KYGBge3J9CiNmaWxlLmNob29zZSgpCk1FUk1BPC0gcmVhZC5jc3YoIi9Vc2Vycy9lbWlsaW9vbHZlcmEvRG93bmxvYWRzL0ZPUk0gLSBNZXJtYS5jc3YiKQpTQ1JBUDwtIHJlYWQuY3N2KCIvVXNlcnMvZW1pbGlvb2x2ZXJhL0Rvd25sb2Fkcy9TY3JhcC5jc3YiKQpQUk9EVUNDSU9OPC0gcmVhZC5jc3YoIi9Vc2Vycy9lbWlsaW9vbHZlcmEvRG93bmxvYWRzL0ZPUk0gLSBQcm9kdWNjaW/MgW4gQ2FydG9uLmNzdiIpCmBgYAoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZSI+IMK/Q3XDoW50YXMgdmFyaWFibGVzIHkgY3VhbnRvcyByZWdpc3Ryb3MgdGllbmVuIGxhcyBiYXNlIGRlIGRhdG9zPzwvc3Bhbj4KKipMYSBiYXNlIGRlIGRhdG9zIGRlIE1lcm1hKiogdGllbmUgNjAgcmVnaXN0cm9zIFkgMyB2YXJpYWJsZXMuCgpgYGB7cn0KZGVzY3JpYmUoTUVSTUEpCmRpbShNRVJNQSkKYGBgCgoqKkxhIGJhc2UgZGUgZGF0b3MgZGUgU2NyYXAqKiB0aWVuZSAyNTEgcmVnaXN0cm9zIFkgOSB2YXJpYWJsZXMuCgpgYGB7cn0KZGVzY3JpYmUoU0NSQVApCmRpbShTQ1JBUCkKYGBgCgoqKkxhIGJhc2UgZGUgZGF0b3MgZGUgUHJvZHVjY2nDs24qKiB0aWVuZSAyNDY5IHJlZ2lzdHJvcyB5IDE3IHZhcmlhYmxlcwoKYGBge3J9CmRlc2NyaWJlKFBST0RVQ0NJT04pCmRpbShQUk9EVUNDSU9OKQpgYGAKCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlIj4gQ2xhc2lmaWNhY2lvbiBkZSBsYXMgdmFyaWFibGVzLiAgPC9zcGFuPgoKIyMjIFRpcG9zIGRlIFZhcmlhYmxlOiBNZXJtYQpgYGB7ciBlY2hvID0gRkFMU0UsIHJlc3VsdHMgPSBUUlVFfQpWYXJpYWJsZTwtYygiYEZlY2hhYCIsImBNZXNgIiwgImBLaWxvc2AiKQpUeXBlPC1jKCJDdWFsaXRhdGl2YSIsICJDdWFsaXRhdGl2YSIsICJDdWFudGl0YXRpdmEgKGRpc2NyZXRhKSIpCmVzY2FsYXMgPC0gYygibm9taW5hbCIsICJub21pbmFsIiwgIm9yZGluYWwiKQp0YWJsZTwtZGF0YS5mcmFtZShWYXJpYWJsZSxUeXBlLCBlc2NhbGFzKQprbml0cjo6a2FibGUodGFibGUpCmBgYAoKIyMjIFRpcG9zIGRlIFZhcmlhYmxlOiBTY3JhcApgYGB7ciBlY2hvID0gRkFMU0UsIHJlc3VsdHMgPSBUUlVFfQpWYXJpYWJsZTwtYygiYFJlZmVyZW5jaWFgIiwiYEZlY2hhYCIsICJgSG9yYWAiLCJgUHJvZHVjdG9gIiwgImBDYW50aWRhZGAiLCAiYFVuaWRhZCBkZSBtZWRpZGFkYCIsICJgVWJpY2FjacOzbiBkZSBvcmlnZW5gIiwgImBVYmljYWNpw7NuIGRlIGRlc2VjaG9gIiwgImBFc3RhZG9gIikKVHlwZTwtYygiQ3VhbGl0YXRpdmEiLCAiQ3VhbGl0YXRpdmEiLCAiQ3VhbnRpdGF0aXZhIChjb250aW51YSkiLCAiQ3VhbGl0YXRpdmEiLCJDdWFudGl0YXRpdmEgKGRpc2NyZXRhKSIsICJDdWFsaXRhdGl2YSIsICJDdWFsaXRhdGl2YSIsICJDdWFsaXRhdGl2YSIsICJDdWFsaXRhdGl2YSIpCnRhYmxlPC1kYXRhLmZyYW1lKFZhcmlhYmxlLFR5cGUpCmtuaXRyOjprYWJsZSh0YWJsZSkKYGBgCgojIyMgVGlwb3MgZGUgVmFyaWFibGU6IFByb2R1Y2Npw7NuCmBgYHtyfQpWYXJpYWJsZTwtYygiYENsaWVudGVgIiwiYElEIEZvcm1gIiwgImBQcm9kdWN0b2AiLCJgUGllemFzIHByb2dyYW1hZGFzYCIsICJgVGllbXBvIG1pbnV0b3NgIiwgImBIb3JhIGZpbmAiLCAiYEVzdGFjaW9uIGFycmFucXVlYCIsICJgTGFtaW5hcyBwcm9jZXNhZGFzYCIsICJgSW5pY2lvIHNldCB1cGAiLCAiYEZpbiBpbmljaW8gc2V0IHVwYCIsICJgSW5pY2lvIGRlIHByb2Nlc29gIiwgImBGaW4gZGUgcHJvY2Vzb2AiLCAiYFRpZW1wbyBjYWxpZGFkYCIpClR5cGU8LWMoIkN1YWxpdGF0aXZhIiwiQ3VhbGl0YXRpdmEiLCAiQ3VhbGl0YXRpdmEiLCJDdWFudGl0YXRpdmEgKGRpc2NyZXRhKSIsICJDdWFudGl0YXRpdmEgKGRpc2NyZXRhKSIsICJDdWFudGl0YXRpdmEgKGNvbnRpbnVhKSIsICJDdWFsaXRhdGl2YSIsICJDdWFudGl0YXRpdmEgKGRpc2NyZXRhKSIsICJDdWFudGl0YXRpdmEgKGNvbnRpbnVhKSIsICJDdWFudGl0YXRpdmEgKGNvbnRpbnVhKSIsICJDdWFudGl0YXRpdmEgKGNvbnRpbnVhKSIsICJDdWFudGl0YXRpdmEgKGNvbnRpbnVhKSIsICJDdWFudGl0YXRpdmEgKGRpc2NyZXRhKSIgKQpFc2NhbGFzPC1jKCJOb21pbmFsIiwgIk5vbWluYWwiLCJOb21pbmFsIiwgIkludGVydmFsbyIsICJJbnRlcnZhbG8iLCAiSW50ZXJ2YWxvIiwgIkludGVydmFsbyIsIkludGVydmFsbyIsIkludGVydmFsbyIsIkludGVydmFsbyIsIkludGVydmFsbyIsIkludGVydmFsbyIsIkludGVydmFsbyIgKSAKdGFibGU8LWRhdGEuZnJhbWUoVmFyaWFibGUsVHlwZSxFc2NhbGFzKQprbml0cjo6a2FibGUodGFibGUpCmBgYAoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogUkVEIj4gTGltcGllemEgZGUgbGFzIGJhc2VzIGRlIGRhdG9zICA8L3NwYW4+CgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBSRUQiID4gKkxpbXBpZXphIGRlIERhdG9zIHBhcmEgbGEgYmFzZSBkZSBkYXRvcyBkZSBtZXJtYSAuKiA8L3NwYW4+IAoKIyMjIENhbWJpbyBkZSB0aXBvIGRlIFZhcmlhYmxlOgoKKipMYSB2YXJpYWJsZSBkZSBLaWxvcyBlc3RhYmEgZW4gZm9ybWF0byBkZSBjYXLDoWN0ZXIgeSBzZSBwYXNvIGEgbnVtw6lyaWNhLioqIApgYGB7cn0Kc3RyKE1FUk1BKQpNRVJNQSRLaWxvcyA8LSBhcy5udW1lcmljKE1FUk1BJEtpbG9zKQpgYGAKCioqRGVzcHVlcyBkZSBjYW1iaWFyIGxhIHZhcmlhbnRlIHF1ZSBlc3RhYmEgZGUgY2FyYWN0ZXIgYSBudW1lcmljYSBzZSBxdWl6byBoYWNlciBxdWUgc2UgbW9zdHJhcmFuIHNvbGFtZW50ZSBlbCB0b3RhbCBkZSBraWxvcyBwb3IgbWVzIHBvciBsbyBjdWFsIGRlc3B1ZXMgZGUgdmVyIGVzdGEgaW5mb3JtYWNpb24gcHVkZSB2ZXIgcXVlIGVsIG1lcyBjb24gbWF5b3IgY2FudGlkYWQgZGUgbWVybWEgZnVlIGFnb3N0byoqCmBgYHtyfQpNRVJNQTE8LWFnZ3JlZ2F0ZShLaWxvcyB+IE1lcyAsIGRhdGEgPSBNRVJNQSwgc3VtKQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IFJFRCIgPiAqTGltcGllemEgZGUgRGF0b3MgcGFyYSBsYSBiYXNlIGRlIGRhdG9zIGRlIHNjcmFwIC4qIDwvc3Bhbj4gCgojIyMgRWxpbWluYXIgY29sdW1uYXMgcXVlIG5vIGFncmVndWVuIHZhbG9yIG8gcXVlIHNlYW4gZGF0b3MgcmVwZXRpdGl2b3MKYGBge3J9ClNDUkFQMSA8LSBTQ1JBUApTQ1JBUDEgPC0gc2VsZWN0KFNDUkFQMSwgRmVjaGEsIENhbnRpZGFkLCBVYmljYWNpw7NuLmRlLm9yaWdlbikKYGBgCgojIyMgRWxpbWluYXIgcmVuZ2zDs24gZGUgVW5pZGFkZXMgdG90YWxlcyBkZSBzY3JhcApgYGB7cn0KU0NSQVAxIDwtIFNDUkFQMSBbLSBjKDEpLF0KYGBgCgoqKkJvcnJhciB0b2RvcyBsb3MgcmVnaXN0cm9zIE5BIGRlIHVuYSB0YWJsYSBwYXJhIHRlbmVyIHVuYSBiYXNlIGRlIGRhdG9zIG1hcyBlZmljaWVudGUsIHNlIHF1aXNvIGhhY2VyIGVzdG8gcGFyYSBubyB0b21hciBlbiBjdWVudGEgZWwgZGlhIHF1ZSBubyBodWJvIHByb2R1Y2Npb24qKgpgYGB7cn0KU0NSQVAyIDwtIFNDUkFQMQpTQ1JBUDIgPC0gbmEub21pdChTQ1JBUDIpICAgIApzdHIoU0NSQVAyKQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IFJFRCIgPiAqTGltcGllemEgZGUgRGF0b3MgcGFyYSBsYSBiYXNlIGRlIGRhdG9zIGRlIFByb2R1Y2Npw7NuLiogPC9zcGFuPgoKIyMjIFJlZW1wbGF6YXIgTkEgY29uIGNlcm9zCmBgYHtyfQpQUk9EVUNDSU9OW2lzLm5hKFBST0RVQ0NJT04pXTwtMApzdW1tYXJ5KFBST0RVQ0NJT04pCmBgYAoKIyMjIEVsaW1pbmFyIGNvbHVtbmFzIG5vIHJlbGV2YW50ZXMKYGBge3J9ClBST0RVQ0NJT04xIDwtIFBST0RVQ0NJT04KUFJPRFVDQ0lPTjE8LXN1YnNldChQUk9EVUNDSU9OMSxzZWxlY3Q9LWMoTm8uLElELkZPUk0sUC4uRFVDVE8sSFIuLkZJTiwgRVNUQUNJT04uQVIuLk5RVUUsSU5JQ0lPLlNFUC5VUCxGSU4uSU5JQ0lPLkRFLlNFUC5VUCxJTklDSU8uZGUuUC4uLi5TTyxGSU4uZGUuUC4uLi5TTyxUSUVNUE8uLkNBTElEQUQsVElFTVBPLk1BVEVSSUFMRVMsTUVSTUFTLk1hcXVpbmFzLikpCnN0cihQUk9EVUNDSU9OMSkKYGBgCgojIyMgUGFzYXIgZmlsYSBhIG5vbWJyZXMgZGUgY29sdW1uYQpgYGB7cn0KUFJPRFVDQ0lPTjIgPC0gUFJPRFVDQ0lPTgpjb2xuYW1lcyhQUk9EVUNDSU9OMikgPC0gUFJPRFVDQ0lPTlsxLF0KY29sbmFtZXMoUFJPRFVDQ0lPTjIpCgpgYGAKCiMjIyBFbGltaW5hciBwcmltZXIgZmlsYQpgYGB7cn0KUFJPRFVDQ0lPTjIgPC0gUFJPRFVDQ0lPTjJbLTEsXQpgYGAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JleSIgPiBBbsOhbGlzaXMgZXN0YWTDrXN0aWNvIGRlc2NyaXB0aXZvLiA8L3NwYW4+IAoKIyMjIFRhYmxhIGRlIGZyZWN1ZW5jaWEgcGFyYSBtZXJtYSAKCmBgYHtyfQp0YWJsZShNRVJNQTEkTWVzLCBNRVJNQTEkS2lsb3MpCnByb3AudGFibGUodGFibGUoTUVSTUExJE1lcywgTUVSTUExJEtpbG9zKSkKYGBgCioqTGEgdGFibGEgZGUgZnJlY3VlbmNpYSBzZSBoaXpvIGRlIGxvcyBLaWxvcyB5IGVzdGEgbWUgc2lydmlvIHBhcmEgdmVyIHF1ZSBudW5jYSB0aWVuZW4gZWwgbWlzbW8gbW9udG8gZGUgbWVybWEqKgoKIyMjIFRhYmxhIGRlIGZyZWN1ZW5jaWEgZGUgU2NyYXAKYGBge3J9CkZSRUNfU0NSQVA8LVNDUkFQMSAlPiUgZ3JvdXBfYnkoQ2FudGlkYWQpICU+JSB0YWxseSgpCkZSRUNfU0NSQVAKYGBgCioqTGEgdGFibGEgZGUgZnJlY3VlbmNpYSBkZSBzY3JhcCBzZSBoaXpvIGRlIGNhbnRpZGFkIHkgZXN0YSBtZSBzaXJ2aW8gcGFyYSB2ZXIgY29tbyB2YXJpYSBsYSBjYW50aWRhZCBkZSBzY3JhcCBsYSBjdWFsIHNlIHZlIHJlZmxlamFkYSB5ZW5kbyBhIHZhcmlhcyB1YmljYWNpb25lcyBsYSBjdWFsIGVzIDEqKgoKIyMjIFRhYmxhIGRlIGZyZWN1ZW5jaWEgZGUgUHJvZHVjY2lvbgpgYGB7cn0KRlJFQ19QUk9EPC1QUk9EVUNDSU9OMSAlPiUgZ3JvdXBfYnkoUElFWkFTLlAuLkcuKSAlPiUgdGFsbHkoKQpGUkVDX1BST0QKYGBgCioqTGEgdGFibGEgZGUgZnJlY3VlbmNpYSBkZSBwcm9kdWNjaW9uIHNlIGhpem8gZGUgcGllemFzLCBlc3RhIG1lIHNpcnZpbyBwYXJhIHZlciBjb21vIGVzIHF1ZSBsYXMgcGllemFzIGRlIHByb2R1Y2Npb24gc2UgdmFuIHZlbmRpZW5kbyoqCgojIyMgR3JhZmljYSBkZSBkaXNwZXJzaW9uIHBhcmEgbWVybWEuCgpgYGB7cn0KZ2dwbG90KGRhdGE9TUVSTUExLCBtYXBwaW5nID0gYWVzKE1lcywgS2lsb3MpKSArIGdlb21fcG9pbnQoYWVzKCkpICsgdGhlbWVfYncoKQoKYGBgCioqRW4gZXN0YSBncmFmaWNhIHBvZGVtb3MgYXByZWNpYXIgbG9zIGRhdG9zIGRlIGxvIHF1ZSBzb24gbG9zIGtpbG9zIHF1ZSB0aWVuZW4gZGUgbWVybWEgcG9yIG1lcyBlbiBkb25kZSBzZSBwdWVkZSB2ZXIgcXVlIGVuIGFnb3N0byBlcyBjdWFuZG8gc2UgdGllbmUgZWwgbWF5b3IgbnVtZXJvIGRlIG1lcm1hLCBkYXRvIHF1ZSB5YSBoYWJpYSBtZW5jaW9uYWRvIGFudGVzIGVuIGVsIGFwYXJ0YWRvIGRlIGN1YW5kbyBzZSBoaXpvIGxhIGxpbXBpZXphIGRlIGRhdG9zKioKCiMjIyBHcmFmaWNhIGRlIGRpc3BlcnNpb24gZGUgc2NyYXAKYGBge3J9CmdncGxvdChkYXRhPVNDUkFQMiwgbWFwcGluZyA9IGFlcyhDYW50aWRhZCwgVWJpY2FjacOzbi5kZS5vcmlnZW4pKSArIGdlb21fcG9pbnQoYWVzKCkpICsgdGhlbWVfYncoKQpgYGAKCiMjIyBHcsOhZmljYSBkZSBEaXNwZXJzacOzbiBwYXJhIFNjcmFwCmBgYHtyfQpnZ3Bsb3QoZGF0YT1TQ1JBUDEsIG1hcHBpbmcgPQphZXMoQ2FudGlkYWQsIFViaWNhY2nDs24uZGUub3JpZ2VuKSkgKwogIGdlb21fcG9pbnQoYWVzKCkpICsgdGhlbWVfYncoKQpgYGAKKipFbiBlc3RhIGdyYWZpY2EgZGUgZGlzcGVyc2lvbiBzZSBwdWVkZSBhcHJlY2lhciB2aXN1YWxtZW50ZSBsYSBjYW50aWRhZCBxdWUgc2UgcHJvZHVjZSBlbiBjYWRhIHViaWNhY2lvbiwgdGFsIGZ1ZSBkZSBheXVkYSBwYXJhIHZlciBxdWUgZW4gU0FCL1ByZS1Qcm9kdWN0aW9uIGVzIGxhIHF1ZSBtYXMgdGllbmUgU2NyYXAuKioKCiMjIyBHcsOhZmljYSBkZSBEaXNwZXJzacOzbiBwYXJhIFByb2R1Y2Npw7NuCgpgYGB7cn0KZ2dwbG90KFBST0RVQ0NJT04xLCBhZXMoeD1gUElFWkFTLlAuLkcuYCwgeT1DTElFTlRFKSkgKyAKICAgIGdlb21fcG9pbnQoKSAKYGBgCioqRW4gZXN0YSBncmFmaWNhIGRlIGRpc3BlcnNpb24gc2UgcHVlZGUgYXByZWNpYXIgdmlzdWFsbWVudGUgbGEgY2FudGlkYWQgZGUgcGllemFzIHF1ZSBzZSBkZW1hbmRhbiBwYXJhIGxvcyBkaWZlcmVudGVzIGNsaWVudGVzLioqCgoKKkdyYWZpY28gZGUgYmFycmFzIGRlIGxvcyBraWxvcyBkZSBNRVJNQSBxdWUgc2UgcHJvZHVjZW4gcG9yIG1lcyoKYGBge3J9CmdncGxvdChNRVJNQTEsIGFlcyh4PU1lcywgeT1LaWxvcykpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIGZpbGw9InllbGxvdyIpICsgc2NhbGVfZmlsbF9ncmV5KCkgKyAKICBsYWJzKHRpdGxlID0gIkdyYWZpY2EgZGUgQmFycmFzIGRlIGxvcyBraWxvcyBkZSBtZXJtYSBxdWUgaGF5IHBvciBtZXMuIiwgCiAgICAgICB4ID0gIk1lcyIsIHkgPSAiS2lsb3MiKQpgYGAKKipWaXN1YWxtZW50ZSBwb2RlbW9zIHZlciBxdWUgQWdvc3RvIHRpZW5lIGVsIG1heW9yIG51bWVybyBkZSBtZXJtYSBhIGNvbXBhcmFjaW9uIGRlIGxvcyBvdHJvcyBtZXNlcyoqCgoqR3JhZmljbyBkZSBiYXJyYXMgZGUgU0NSQVAgZGUgbGEgY2FudGlkYWQgZGUgbGFzIHBpZXphcyBwb3IgbGEgdWJpY2FjacOzbioKYGBge3J9CmdncGxvdChTQ1JBUDIsIGFlcyh4PVViaWNhY2nDs24uZGUub3JpZ2VuLCB5PUNhbnRpZGFkKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0iQkxVRSIpICsgc2NhbGVfZmlsbF9ncmV5KCkgKyAKICBsYWJzKHRpdGxlID0gIkdyYWZpY28gZGUgYmFycmFzIGRlIGxhcyB1bmlkYWRlcyBkZSBTY3JhcCBwb3IgdWJpY2FjaW9uIGRlIG9yaWdlbiIsIAogICAgICAgeCA9ICJVbmlkYWRlcyIsIHkgPSAiVWJpY2FjacOzbiIpCgpgYGAKCioqRW4gZXN0YSBncmFmaWNhIGRlIGJhcnJhcyBlcyB2aXN1YWxtZW50ZSBjbGFybyBxdWUgY29tbyBzZSBtZW5jaW9ubyBhbnRlcmlvcm1lbnRlLCBlbCBhcmVhIGRlIHByZS1wcm9kdWN0aW9uIGVzIGxhIHF1ZSBtYXMgc2NyYXAgbGxldmEuKioKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjpnb2xkIiA+ICoqUFJPUFVFU1RBUyoqIDwvc3Bhbj4KCiMjIyBQUk9QVUVTVEEgUEFSQSBNRVJNQQoqKkNvbW8gcHJvcHVlc3RhIHBhcmEgbGEgbWVybWEsIHNlIHRpZW5lIHF1ZSBpbXBsZW1lbnRhciB1biBwbGFuIHF1ZSBtaW5pbWljZSBsYSBjYW50aWRhZCBkZSBtZXJtYSBnZW5lcmFkYSwgbGEgY3VhbCBzZSB2ZSBxdWUgZnVlIGFsdGEgZW4gbG9zIG1lc2VzIGRlIGRlIEFnb3N0byB5IFNlcHRpZW1icmUgZG9uZGUgc2UgcmVxdWllcmUgZGV0ZXJtaW5hciBsYSBjYXVzYSBkZWwgYWx0byBuaXZlbCBkZSBlc3RvcyBkZXNlY2hvcywgcGFyYSBhc2kgcG9kZXIgcHJldmVuaXIgZnV0dXJvcyBnYXN0b3MgZXh0cmEgeSBhc2kgbm8gdm9sdmVyIGEgdGVuZXIgZXN0ZSBwcm9ibGVtYS4qKgoKIyMjIFBST1BVRVNUQSBQQVJBIFNDUkFQCioqQ29tbyBwcm9wdWVzdGEgcGFyYSBzY3JhcCwgcHVlZG8gZGVjaXIgcXVlIGVuIGVsIGFyZWEgZGUgUHJlLXByb2R1Y3Rpb24gc2llbmRvIGVsIGFyZWEgcXVlIG1hcyBzY3JhcCBsbGV2YSBzZSB0aWVuZSBxdWUgaW1wbGVtZW50YXIgdW4gcGxhbiBwYXJhIGRpc21pbnVpciBlc3RvIHlhIHF1ZSBzZSBwb2RyaWEgZGVjaXIgcXVlIHNlIHJlZmxhamFuIGdhc3RvcyBleHRyYSBxdWUgc29uIGlubmVjZXNhcmlvcy4gKioKCiMjIyBQUk9QVUVTVEEgUEFSQSBQUk9EVUNDSU9OCgoqKkNvbW8gcHJpbWVyYSBwcm9wdWVzdGEgcGFyYSBwcm9kdWNjaW9uIHB1ZWRvIGRlY2lyIHF1ZSBzZSBzaWdhbiBhZGFwdGFuZG8gYSBsYXMgbmVjZXNpZGFkZXMgZGUgbG9zIGNpZW50ZXMgcGVybyBxdWUgdGFtYmllbiB0cmF0ZW4gZGUgaW1wbGVtZW50YXIgb3RyYXMgbWFuZXJhcyB5YSBxdWUgc2UgcXVpZXJlIGxsZWdhciBhIHRvZG9zIGxvcyBjbGllbnRlcyBwb3NpYmxlcyB5IG5vIGVzdGFyIHNlZ21lbnRhbmRvLCBwb3IgbG8gY3VhbCBlcyBpbXBvcnRhbnRlIGRlIHRyYXRhciBkZSBhYnJpcnNlIG1hcyBoYWNpYSBsb3MgY2xpZW50ZXMgcXVlIG5vIGxlcyBsbGVnYW4gYSBwZWRpciBsYXMgbWlzbWFzIGRlbWFuZGFzLioqCgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjpnb2xkIiA+ICoqUmVmbGV4aW9uIGRlIGxhIGFjdGl2aWRhZCoqIDwvc3Bhbj4gCgoqKlJlYWxpemFyIGVsIGFuw6FsaXNpcyBkZSBGT1JNIGZ1ZSBtdXkgaW50ZXJlc2FudGUgcG9ycXVlIGVzbyBtZSBwZXJtaXRpw7MgZGFybWUgY3VlbnRhIGRlbCBncmFuIHBvdGVuY2lhbCBxdWUgcHVlZGUgbGxlZ2FyIGEgdGVuZXIgdW5hIGVtcHJlc2EgeSBxdWUgbXVjaGFzIHZlY2VzIG5vIHNlIHRpZW5lIGVuIGN1ZW50YSBlbCBhbGNhbmNlIGFsIHF1ZSBzZSBwdWVkZSBsbGVnYXIgeSBhcHJvdmVjaGFyIGxvcyByZWN1cnNvcyBvIGJpZW4sIGxhcyBvcG9ydHVuaWRhZGVzIHF1ZSBzZSB0aWVuZW4gcGFyYSBtZWpvcmFyIGxhIHNpdHVhY2nDs24gZGUgbGEgZW1wcmVzYSB5IHF1ZSBlbiBlc3RlIGNhc28sIEZPUk0gdGVuaWVuZG8gZGlmZXJlbnRlcyBwdW50b3MgYSB2ZXIgcHVlZGUgaGFjZXIgZGUgZXN0YSBzaXR1YWNpw7NuIHVuYSBvcG9ydHVuaWRhZCBwYXJhIGhhY2VyIHVuIGNhbWJpbyBwb3NpdGl2by4gRWwgaGFiZXIgYW5hbGl6YWRvIGxhcyBiYXNlcyBkZSBkYXRvcyB0YW1iaWVuIG1lIGRpbyB1bmEgcGVyY2VwY2nDs24gbXV5IGFtcGxpYSB5IGNsYXJhIHNvYnJlIGxhIHBvc2ljacOzbiBxdWUgdGllbmUgRk9STSB5IGVuIGJhc2UgYSBlbGxvIHBvZGVyIHRvbWFyIG1lam9yZXMgZGVjaXNpb25lcyBxdWUgbGxldmVuIGEgbGEgb3JnYW5pemFjacOzbiBhIHNlciBtw6FzIGNvbXBldGl0aXZhIHkgdGVuZXIgbGEgb3BvcnR1bmlkYWQgZGUgZXhwYW5kaXIgZWwgbWVyY2FkbyBlbiBlbCBxdWUgc2UgZW5jdWVudHJlIGVuIGVzZSBtb21lbnRvIGxhIGVtcHJlc2EsIGV2aXRhbmRvIHNpZW1wcmUgdG9kb3MgbG9zIHJpZXNnb3MgcXVlIHNlIHB1ZWRhbiBwcmVzZW50YXIsIG8gYWwgbWVub3Mgc2FiZXIgcmVzcG9uZGVyIGNvbiBtYXlvciBjZXJ0ZXphIGFudGUgZWxsb3MuICoqCgoK