Importar bases de datos

stores <- read.csv("/Users/Karen/Documents/stores.csv")
features <- read.csv("/Users/Karen/Documents/features (1).csv")
train <- read.csv("/Users/Karen/Documents/train.csv")
test <- read.csv("/Users/Karen/Documents/test.csv")

Instalar paquetes y llamar librerias

#install.packages("dplyr")
library(dplyr)
## 
## 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

Entender las bases de datos

summary(stores)
##      Store        Type                Size       
##  Min.   : 1   Length:45          Min.   : 34875  
##  1st Qu.:12   Class :character   1st Qu.: 70713  
##  Median :23   Mode  :character   Median :126512  
##  Mean   :23                      Mean   :130288  
##  3rd Qu.:34                      3rd Qu.:202307  
##  Max.   :45                      Max.   :219622
count (stores, Type, sort = TRUE)
##   Type  n
## 1    A 22
## 2    B 17
## 3    C  6
str(stores)
## 'data.frame':    45 obs. of  3 variables:
##  $ Store: int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Type : chr  "A" "A" "B" "A" ...
##  $ Size : int  151315 202307 37392 205863 34875 202505 70713 155078 125833 126512 ...
summary(features)
##      Store        Date            Temperature       Fuel_Price   
##  Min.   : 1   Length:8190        Min.   : -7.29   Min.   :2.472  
##  1st Qu.:12   Class :character   1st Qu.: 45.90   1st Qu.:3.041  
##  Median :23   Mode  :character   Median : 60.71   Median :3.513  
##  Mean   :23                      Mean   : 59.36   Mean   :3.406  
##  3rd Qu.:34                      3rd Qu.: 73.88   3rd Qu.:3.743  
##  Max.   :45                      Max.   :101.95   Max.   :4.468  
##                                                                  
##    MarkDown1        MarkDown2           MarkDown3           MarkDown4       
##  Min.   : -2781   Min.   :  -265.76   Min.   :  -179.26   Min.   :    0.22  
##  1st Qu.:  1578   1st Qu.:    68.88   1st Qu.:     6.60   1st Qu.:  304.69  
##  Median :  4744   Median :   364.57   Median :    36.26   Median : 1176.42  
##  Mean   :  7032   Mean   :  3384.18   Mean   :  1760.10   Mean   : 3292.94  
##  3rd Qu.:  8923   3rd Qu.:  2153.35   3rd Qu.:   163.15   3rd Qu.: 3310.01  
##  Max.   :103185   Max.   :104519.54   Max.   :149483.31   Max.   :67474.85  
##  NA's   :4158     NA's   :5269        NA's   :4577        NA's   :4726      
##    MarkDown5             CPI         Unemployment    IsHoliday      
##  Min.   :  -185.2   Min.   :126.1   Min.   : 3.684   Mode :logical  
##  1st Qu.:  1440.8   1st Qu.:132.4   1st Qu.: 6.634   FALSE:7605     
##  Median :  2727.1   Median :182.8   Median : 7.806   TRUE :585      
##  Mean   :  4132.2   Mean   :172.5   Mean   : 7.827                  
##  3rd Qu.:  4832.6   3rd Qu.:213.9   3rd Qu.: 8.567                  
##  Max.   :771448.1   Max.   :229.0   Max.   :14.313                  
##  NA's   :4140       NA's   :585     NA's   :585
str(features)
## 'data.frame':    8190 obs. of  12 variables:
##  $ Store       : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Date        : chr  "05/02/2010" "12/02/2010" "19/02/2010" "26/02/2010" ...
##  $ Temperature : num  42.3 38.5 39.9 46.6 46.5 ...
##  $ Fuel_Price  : num  2.57 2.55 2.51 2.56 2.62 ...
##  $ MarkDown1   : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ MarkDown2   : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ MarkDown3   : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ MarkDown4   : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ MarkDown5   : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ CPI         : num  211 211 211 211 211 ...
##  $ Unemployment: num  8.11 8.11 8.11 8.11 8.11 ...
##  $ IsHoliday   : logi  FALSE TRUE FALSE FALSE FALSE FALSE ...
summary(test)
##      Store            Dept           Date           IsHoliday      
##  Min.   : 1.00   Min.   : 1.00   Length:115064      Mode :logical  
##  1st Qu.:11.00   1st Qu.:18.00   Class :character   FALSE:106136   
##  Median :22.00   Median :37.00   Mode  :character   TRUE :8928     
##  Mean   :22.24   Mean   :44.34                                     
##  3rd Qu.:33.00   3rd Qu.:74.00                                     
##  Max.   :45.00   Max.   :99.00
str(test)
## 'data.frame':    115064 obs. of  4 variables:
##  $ Store    : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Dept     : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Date     : chr  "02/11/2012" "09/11/2012" "16/11/2012" "23/11/2012" ...
##  $ IsHoliday: logi  FALSE FALSE FALSE TRUE FALSE FALSE ...
summary(train)
##      Store           Dept           Date            Weekly_Sales   
##  Min.   : 1.0   Min.   : 1.00   Length:421570      Min.   : -4989  
##  1st Qu.:11.0   1st Qu.:18.00   Class :character   1st Qu.:  2080  
##  Median :22.0   Median :37.00   Mode  :character   Median :  7612  
##  Mean   :22.2   Mean   :44.26                      Mean   : 15981  
##  3rd Qu.:33.0   3rd Qu.:74.00                      3rd Qu.: 20206  
##  Max.   :45.0   Max.   :99.00                      Max.   :693099  
##  IsHoliday      
##  Mode :logical  
##  FALSE:391909   
##  TRUE :29661    
##                 
##                 
## 
str(train)
## 'data.frame':    421570 obs. of  5 variables:
##  $ Store       : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Dept        : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Date        : chr  "05/02/2010" "12/02/2010" "19/02/2010" "26/02/2010" ...
##  $ Weekly_Sales: num  24924 46039 41596 19404 21828 ...
##  $ IsHoliday   : logi  FALSE TRUE FALSE FALSE FALSE FALSE ...
#Observaciones 
#1. En features hay NA's en mas de la mitad de los registros de Markdown (Del 1 al 5)
#2. En features hay 585 NAs en CPI, Uneyployment y hay 585 registros de isholiday = TRUE. Tiene relacion? R: Sin Relacion 
#3. En features y en test, Date tiene formato de caracter 
#4. En train hay ventas negativas 

Herramienta el generador de valor de datos

Paso 1. Definir el area del negocio que buscamos impactar o mejorar y su KPI

El departamento de mercadotecnia de EUA (con muestra de 45 tiendas) en el indicador de ventas semanales

Paso 2. Seleccionar plantilla (-s) para crear valor a partir de los datos de los clientes

Vision / Segmentacion / Personalizacion / Contextualizacion

Paso 3. Generar ideas o conceptos especificos

Elaborar un modelo predicitivo de ventas semanales

Paso 4. Reunir los datos requeridos

Elaborar una base de datos con la variable dependiente (ventas semanales) y las variables independientes

Paso 5. Plan de ejecucion

Mercadotecnia elaborar el plan para despegar modelo predictivo en fases:

Fase 1. Piloto (San Antonio Tx)

Fase 2. Texas

Fase 3. EUA

Sistemas asegurara la captura del markdown en las bases de datos

Creación de la base de datos consolidada

#Agregar "STORES" a "TRAIN"

bd <- merge(train, stores, by= "Store")

#Agregar FEATURES a bd
bd1 <- merge(bd, features)

#Eliminar columnas 
bd2 <- bd1
bd2 <- subset(bd2, select = -c(MarkDown1, MarkDown2, MarkDown3, MarkDown4, MarkDown5))
summary(bd2)
##      Store          Date           IsHoliday            Dept      
##  Min.   : 1.0   Length:421570      Mode :logical   Min.   : 1.00  
##  1st Qu.:11.0   Class :character   FALSE:391909    1st Qu.:18.00  
##  Median :22.0   Mode  :character   TRUE :29661     Median :37.00  
##  Mean   :22.2                                      Mean   :44.26  
##  3rd Qu.:33.0                                      3rd Qu.:74.00  
##  Max.   :45.0                                      Max.   :99.00  
##   Weekly_Sales        Type                Size         Temperature    
##  Min.   : -4989   Length:421570      Min.   : 34875   Min.   : -2.06  
##  1st Qu.:  2080   Class :character   1st Qu.: 93638   1st Qu.: 46.68  
##  Median :  7612   Mode  :character   Median :140167   Median : 62.09  
##  Mean   : 15981                      Mean   :136728   Mean   : 60.09  
##  3rd Qu.: 20206                      3rd Qu.:202505   3rd Qu.: 74.28  
##  Max.   :693099                      Max.   :219622   Max.   :100.14  
##    Fuel_Price         CPI         Unemployment   
##  Min.   :2.472   Min.   :126.1   Min.   : 3.879  
##  1st Qu.:2.933   1st Qu.:132.0   1st Qu.: 6.891  
##  Median :3.452   Median :182.3   Median : 7.866  
##  Mean   :3.361   Mean   :171.2   Mean   : 7.960  
##  3rd Qu.:3.738   3rd Qu.:212.4   3rd Qu.: 8.572  
##  Max.   :4.468   Max.   :227.2   Max.   :14.313
#Cambiar formato de fecha
bd2$Date <- as.Date(bd2$Date, format = "%d/%m/%Y")
str(bd2)
## 'data.frame':    421570 obs. of  11 variables:
##  $ Store       : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Date        : Date, format: "2011-04-01" "2011-04-01" ...
##  $ IsHoliday   : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ Dept        : int  49 26 81 34 59 30 7 85 8 28 ...
##  $ Weekly_Sales: num  13168 5947 28545 9950 317 ...
##  $ Type        : chr  "A" "A" "A" "A" ...
##  $ Size        : int  151315 151315 151315 151315 151315 151315 151315 151315 151315 151315 ...
##  $ Temperature : num  59.2 59.2 59.2 59.2 59.2 ...
##  $ Fuel_Price  : num  3.52 3.52 3.52 3.52 3.52 ...
##  $ CPI         : num  215 215 215 215 215 ...
##  $ Unemployment: num  7.68 7.68 7.68 7.68 7.68 ...
#install.packages("wordspace")
library(wordspace)
## Loading required package: Matrix
signcount(bd2$Weekly_Sales)
##    pos   zero    neg 
## 420212     73   1285
#Eliminar ventas menores que 0 
bd3 <- bd2
bd3 <- bd3[bd3$Weekly > 0, ]
summary (bd3)
##      Store           Date            IsHoliday            Dept      
##  Min.   : 1.0   Min.   :2010-02-05   Mode :logical   Min.   : 1.00  
##  1st Qu.:11.0   1st Qu.:2010-10-08   FALSE:390652    1st Qu.:18.00  
##  Median :22.0   Median :2011-06-17   TRUE :29560     Median :37.00  
##  Mean   :22.2   Mean   :2011-06-18                   Mean   :44.24  
##  3rd Qu.:33.0   3rd Qu.:2012-02-24                   3rd Qu.:74.00  
##  Max.   :45.0   Max.   :2012-10-26                   Max.   :99.00  
##   Weekly_Sales        Type                Size         Temperature    
##  Min.   :     0   Length:420212      Min.   : 34875   Min.   : -2.06  
##  1st Qu.:  2120   Class :character   1st Qu.: 93638   1st Qu.: 46.68  
##  Median :  7662   Mode  :character   Median :140167   Median : 62.09  
##  Mean   : 16033                      Mean   :136750   Mean   : 60.09  
##  3rd Qu.: 20271                      3rd Qu.:202505   3rd Qu.: 74.28  
##  Max.   :693099                      Max.   :219622   Max.   :100.14  
##    Fuel_Price         CPI         Unemployment   
##  Min.   :2.472   Min.   :126.1   Min.   : 3.879  
##  1st Qu.:2.933   1st Qu.:132.0   1st Qu.: 6.891  
##  Median :3.452   Median :182.4   Median : 7.866  
##  Mean   :3.361   Mean   :171.2   Mean   : 7.960  
##  3rd Qu.:3.738   3rd Qu.:212.4   3rd Qu.: 8.567  
##  Max.   :4.468   Max.   :227.2   Max.   :14.313
#Agregar numero de la semana 
bd4 <- bd3
bd4$week_number <- strftime(bd4$Date, format = "%V")
str(bd4)
## 'data.frame':    420212 obs. of  12 variables:
##  $ Store       : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Date        : Date, format: "2011-04-01" "2011-04-01" ...
##  $ IsHoliday   : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ Dept        : int  49 26 81 34 59 30 7 85 8 28 ...
##  $ Weekly_Sales: num  13168 5947 28545 9950 317 ...
##  $ Type        : chr  "A" "A" "A" "A" ...
##  $ Size        : int  151315 151315 151315 151315 151315 151315 151315 151315 151315 151315 ...
##  $ Temperature : num  59.2 59.2 59.2 59.2 59.2 ...
##  $ Fuel_Price  : num  3.52 3.52 3.52 3.52 3.52 ...
##  $ CPI         : num  215 215 215 215 215 ...
##  $ Unemployment: num  7.68 7.68 7.68 7.68 7.68 ...
##  $ week_number : chr  "13" "13" "13" "13" ...
bd4$week_number <- as.integer(bd4$week_number)
str(bd4)
## 'data.frame':    420212 obs. of  12 variables:
##  $ Store       : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Date        : Date, format: "2011-04-01" "2011-04-01" ...
##  $ IsHoliday   : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ Dept        : int  49 26 81 34 59 30 7 85 8 28 ...
##  $ Weekly_Sales: num  13168 5947 28545 9950 317 ...
##  $ Type        : chr  "A" "A" "A" "A" ...
##  $ Size        : int  151315 151315 151315 151315 151315 151315 151315 151315 151315 151315 ...
##  $ Temperature : num  59.2 59.2 59.2 59.2 59.2 ...
##  $ Fuel_Price  : num  3.52 3.52 3.52 3.52 3.52 ...
##  $ CPI         : num  215 215 215 215 215 ...
##  $ Unemployment: num  7.68 7.68 7.68 7.68 7.68 ...
##  $ week_number : int  13 13 13 13 13 13 13 13 13 13 ...
summary(bd4)
##      Store           Date            IsHoliday            Dept      
##  Min.   : 1.0   Min.   :2010-02-05   Mode :logical   Min.   : 1.00  
##  1st Qu.:11.0   1st Qu.:2010-10-08   FALSE:390652    1st Qu.:18.00  
##  Median :22.0   Median :2011-06-17   TRUE :29560     Median :37.00  
##  Mean   :22.2   Mean   :2011-06-18                   Mean   :44.24  
##  3rd Qu.:33.0   3rd Qu.:2012-02-24                   3rd Qu.:74.00  
##  Max.   :45.0   Max.   :2012-10-26                   Max.   :99.00  
##   Weekly_Sales        Type                Size         Temperature    
##  Min.   :     0   Length:420212      Min.   : 34875   Min.   : -2.06  
##  1st Qu.:  2120   Class :character   1st Qu.: 93638   1st Qu.: 46.68  
##  Median :  7662   Mode  :character   Median :140167   Median : 62.09  
##  Mean   : 16033                      Mean   :136750   Mean   : 60.09  
##  3rd Qu.: 20271                      3rd Qu.:202505   3rd Qu.: 74.28  
##  Max.   :693099                      Max.   :219622   Max.   :100.14  
##    Fuel_Price         CPI         Unemployment     week_number   
##  Min.   :2.472   Min.   :126.1   Min.   : 3.879   Min.   : 1.00  
##  1st Qu.:2.933   1st Qu.:132.0   1st Qu.: 6.891   1st Qu.:14.00  
##  Median :3.452   Median :182.4   Median : 7.866   Median :26.00  
##  Mean   :3.361   Mean   :171.2   Mean   : 7.960   Mean   :25.83  
##  3rd Qu.:3.738   3rd Qu.:212.4   3rd Qu.: 8.567   3rd Qu.:38.00  
##  Max.   :4.468   Max.   :227.2   Max.   :14.313   Max.   :52.00
#Separar año, mes y dia
bd5 <- bd4
bd5 <- bd5 %>%
    dplyr::mutate(year = lubridate::year(Date),
                  month = lubridate::month(Date),
                  day = lubridate::day(Date))

summary (bd5)
##      Store           Date            IsHoliday            Dept      
##  Min.   : 1.0   Min.   :2010-02-05   Mode :logical   Min.   : 1.00  
##  1st Qu.:11.0   1st Qu.:2010-10-08   FALSE:390652    1st Qu.:18.00  
##  Median :22.0   Median :2011-06-17   TRUE :29560     Median :37.00  
##  Mean   :22.2   Mean   :2011-06-18                   Mean   :44.24  
##  3rd Qu.:33.0   3rd Qu.:2012-02-24                   3rd Qu.:74.00  
##  Max.   :45.0   Max.   :2012-10-26                   Max.   :99.00  
##   Weekly_Sales        Type                Size         Temperature    
##  Min.   :     0   Length:420212      Min.   : 34875   Min.   : -2.06  
##  1st Qu.:  2120   Class :character   1st Qu.: 93638   1st Qu.: 46.68  
##  Median :  7662   Mode  :character   Median :140167   Median : 62.09  
##  Mean   : 16033                      Mean   :136750   Mean   : 60.09  
##  3rd Qu.: 20271                      3rd Qu.:202505   3rd Qu.: 74.28  
##  Max.   :693099                      Max.   :219622   Max.   :100.14  
##    Fuel_Price         CPI         Unemployment     week_number   
##  Min.   :2.472   Min.   :126.1   Min.   : 3.879   Min.   : 1.00  
##  1st Qu.:2.933   1st Qu.:132.0   1st Qu.: 6.891   1st Qu.:14.00  
##  Median :3.452   Median :182.4   Median : 7.866   Median :26.00  
##  Mean   :3.361   Mean   :171.2   Mean   : 7.960   Mean   :25.83  
##  3rd Qu.:3.738   3rd Qu.:212.4   3rd Qu.: 8.567   3rd Qu.:38.00  
##  Max.   :4.468   Max.   :227.2   Max.   :14.313   Max.   :52.00  
##       year          month            day       
##  Min.   :2010   Min.   : 1.00   Min.   : 1.00  
##  1st Qu.:2010   1st Qu.: 4.00   1st Qu.: 8.00  
##  Median :2011   Median : 6.00   Median :16.00  
##  Mean   :2011   Mean   : 6.45   Mean   :15.67  
##  3rd Qu.:2012   3rd Qu.: 9.00   3rd Qu.:23.00  
##  Max.   :2012   Max.   :12.00   Max.   :31.00

Generar regresión

regresion <- lm(Weekly_Sales ~ Store + Dept + IsHoliday + Type + Size + Temperature + Fuel_Price + CPI + Unemployment + week_number + year + month + day, data=bd5)

summary (regresion)
## 
## Call:
## lm(formula = Weekly_Sales ~ Store + Dept + IsHoliday + Type + 
##     Size + Temperature + Fuel_Price + CPI + Unemployment + week_number + 
##     year + month + day, data = bd5)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -34331 -12895  -5852   5626 671540 
## 
## Coefficients:
##                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    1.110e+06  2.999e+05   3.701 0.000214 ***
## Store         -1.426e+02  3.087e+00 -46.198  < 2e-16 ***
## Dept           1.108e+02  1.097e+00 101.013  < 2e-16 ***
## IsHolidayTRUE  8.511e+02  1.391e+02   6.119 9.45e-10 ***
## TypeB         -3.133e+02  1.078e+02  -2.908 0.003642 ** 
## TypeC          5.836e+03  1.840e+02  31.709  < 2e-16 ***
## Size           9.920e-02  9.584e-04 103.511  < 2e-16 ***
## Temperature    3.701e+00  2.133e+00   1.735 0.082688 .  
## Fuel_Price     4.791e+02  1.480e+02   3.237 0.001207 ** 
## CPI           -2.340e+01  9.996e-01 -23.409  < 2e-16 ***
## Unemployment  -2.538e+02  2.062e+01 -12.308  < 2e-16 ***
## week_number    7.678e+02  4.566e+02   1.682 0.092648 .  
## year          -5.485e+02  1.485e+02  -3.695 0.000220 ***
## month         -3.167e+03  1.988e+03  -1.594 0.111036    
## day           -1.281e+02  6.539e+01  -1.959 0.050115 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 21690 on 420197 degrees of freedom
## Multiple R-squared:  0.08982,    Adjusted R-squared:  0.08979 
## F-statistic:  2962 on 14 and 420197 DF,  p-value: < 2.2e-16
#Ventas semanales
#library(shiny)

#ui <- fluidPage(
  #selectInput("Variables","Variables",choices = names(bd5)),
  #plotOutput("myplot"))

#server <- function(input, output, session) {

  #output$myplot <- renderPlot({
    #plot(Weekly_Sales ~ get(input$Variables) , data=bd5)
  #})
#}

#shinyApp(ui, server)

Construir un modelo de predicción

datos_nuevos <- data.frame(Store=1, Dept=1, IsHoliday = TRUE, Type = "A", Size = 151315, Temperature = 59.17, Fuel_Price = 3.5524, CPI = 214.8372, Unemployment = 7.682, week_number = 1, year = 2012, month = 1, day = 1)

predict (regresion, datos_nuevos)
##        1 
## 14681.54

Propuestas

  1. La primer propuesta es dado que las ventas estan estrechamente relacionadas con las semanas en las cuales hay festividades, sería óptimo crear e implementar material POP en PDV (Puntos de Venta) que ayude a generar awareness sobre los productos mostrados en festividades (Ej. Navidad) e incrementen el atractivo visual en la tienda para mantener el engagement con los consumidores.

  2. La segunda propuesta se enfocaría en centrarse en el resto de las semanas sin festividades, para mantener las semanas con temporada alta en el mismo nivel, y contrarestar con las nuevas ventas añadidas. Para este caso, se realizarían en un periodo óptimo analizado en la base de datos, diseñando una serie de promociones y descuentos exclusivos en productos que se encuentren ubicados en las zonas calientes dentro del planograma de la tienda Walmart.

Conclusiones

Al finalizar este caso, pudimos observar como a través de una limpieza de datos y una combinación de bases específicas para Walmart, desarrollamos una regresión para las ventas semanales, que se asociaran con diversas variables como las festividades, la temperatura, el año, entre otras, y con base en esto, un modelo predictivo que arrojara un resultado futuro de las ventas con base en la regresión histórica resultante.

De esta forma, se visualizaron las variables que mayor afectarón las ventas semanales (Tienda, departamento, festividad, tamaño, CPI, año), y con ello, se realizaron dos propuestas para el departamento de mercadotecnia que ayudaran a despegar el modelo predictivo en las 3 fases: Piloto (San Antonio), Texas, y EUA. Se espera que el departamento las analice, sistemas ayude a corroborar las bases de datos, y al final se obtenga un resultado estrechamente similar al modelo predictivo de las ventas semanales.

LS0tCnRpdGxlOiA8c3BhbiBzdHlsZT0iQ29sb3I6cm95YWxibHVlIj4gV2FsbWFydAphdXRob3I6ICJLYXJlbiBOZXJpIC0gQTAxNjU3OTc0IgpkYXRlOiAiMjAyMi0wOS0wOSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQoKLS0tCiFbXShodHRwczovL2Nkbi5jb3Jwb3JhdGUud2FsbWFydC5jb20vZGltczQvV01ULzVmMjU1ZjMvMjE0NzQ4MzY0Ny9zdHJpcC90cnVlL2Nyb3AvMTIwMHg4MDArMCswL3Jlc2l6ZS82MDB4NDAwIS9xdWFsaXR5LzkwLz91cmw9aHR0cHMlM0ElMkYlMkZjZG4uY29ycG9yYXRlLndhbG1hcnQuY29tJTJGYTglMkZjNSUyRjY5MDBiYjNjNDFhYjg5MjU3NWI1OGNlMzZmMTglMkZmb3RvLWRpcmVjdG9yaW8tZGUtdGllbmRhcy5qcGcpe3dpZHRoPSc2MDBweCd9CgojIyA8c3BhbiBzdHlsZT0iQ29sb3I6cm95YWxibHVlIj4gSW1wb3J0YXIgYmFzZXMgZGUgZGF0b3MgCmBgYHtyfQpzdG9yZXMgPC0gcmVhZC5jc3YoIi9Vc2Vycy9LYXJlbi9Eb2N1bWVudHMvc3RvcmVzLmNzdiIpCmZlYXR1cmVzIDwtIHJlYWQuY3N2KCIvVXNlcnMvS2FyZW4vRG9jdW1lbnRzL2ZlYXR1cmVzICgxKS5jc3YiKQp0cmFpbiA8LSByZWFkLmNzdigiL1VzZXJzL0thcmVuL0RvY3VtZW50cy90cmFpbi5jc3YiKQp0ZXN0IDwtIHJlYWQuY3N2KCIvVXNlcnMvS2FyZW4vRG9jdW1lbnRzL3Rlc3QuY3N2IikKYGBgCgojIyA8c3BhbiBzdHlsZT0iQ29sb3I6cm95YWxibHVlIj4gSW5zdGFsYXIgcGFxdWV0ZXMgeSBsbGFtYXIgbGlicmVyaWFzIApgYGB7cn0KI2luc3RhbGwucGFja2FnZXMoImRwbHlyIikKbGlicmFyeShkcGx5cikKYGBgCgojIyA8c3BhbiBzdHlsZT0iQ29sb3I6cm95YWxibHVlIj4gRW50ZW5kZXIgbGFzIGJhc2VzIGRlIGRhdG9zCmBgYHtyfQpzdW1tYXJ5KHN0b3JlcykKY291bnQgKHN0b3JlcywgVHlwZSwgc29ydCA9IFRSVUUpCnN0cihzdG9yZXMpCgpzdW1tYXJ5KGZlYXR1cmVzKQpzdHIoZmVhdHVyZXMpCgpzdW1tYXJ5KHRlc3QpCnN0cih0ZXN0KQoKc3VtbWFyeSh0cmFpbikKc3RyKHRyYWluKQoKI09ic2VydmFjaW9uZXMgCiMxLiBFbiBmZWF0dXJlcyBoYXkgTkEncyBlbiBtYXMgZGUgbGEgbWl0YWQgZGUgbG9zIHJlZ2lzdHJvcyBkZSBNYXJrZG93biAoRGVsIDEgYWwgNSkKIzIuIEVuIGZlYXR1cmVzIGhheSA1ODUgTkFzIGVuIENQSSwgVW5leXBsb3ltZW50IHkgaGF5IDU4NSByZWdpc3Ryb3MgZGUgaXNob2xpZGF5ID0gVFJVRS4gVGllbmUgcmVsYWNpb24/IFI6IFNpbiBSZWxhY2lvbiAKIzMuIEVuIGZlYXR1cmVzIHkgZW4gdGVzdCwgRGF0ZSB0aWVuZSBmb3JtYXRvIGRlIGNhcmFjdGVyIAojNC4gRW4gdHJhaW4gaGF5IHZlbnRhcyBuZWdhdGl2YXMgCmBgYAoKIyMgPHNwYW4gc3R5bGU9IkNvbG9yOnJveWFsYmx1ZSI+IEhlcnJhbWllbnRhIGVsIGdlbmVyYWRvciBkZSB2YWxvciBkZSBkYXRvcyAKCioqUGFzbyAxLiBEZWZpbmlyIGVsIGFyZWEgZGVsIG5lZ29jaW8gcXVlIGJ1c2NhbW9zIGltcGFjdGFyIG8gbWVqb3JhciB5IHN1IEtQSSoqCgpFbCBkZXBhcnRhbWVudG8gZGUgbWVyY2Fkb3RlY25pYSBkZSBFVUEgKGNvbiBtdWVzdHJhIGRlIDQ1IHRpZW5kYXMpIGVuIGVsIGluZGljYWRvciBkZSB2ZW50YXMgc2VtYW5hbGVzIAoKKipQYXNvIDIuIFNlbGVjY2lvbmFyIHBsYW50aWxsYSAoLXMpIHBhcmEgY3JlYXIgdmFsb3IgYSBwYXJ0aXIgZGUgbG9zIGRhdG9zIGRlIGxvcyBjbGllbnRlcyoqCgoqKlZpc2lvbioqIC8gU2VnbWVudGFjaW9uIC8gUGVyc29uYWxpemFjaW9uIC8gQ29udGV4dHVhbGl6YWNpb24gCgoqKlBhc28gMy4gR2VuZXJhciBpZGVhcyBvIGNvbmNlcHRvcyBlc3BlY2lmaWNvcyoqCgpFbGFib3JhciB1biBtb2RlbG8gcHJlZGljaXRpdm8gZGUgdmVudGFzIHNlbWFuYWxlcyAKCioqUGFzbyA0LiBSZXVuaXIgbG9zIGRhdG9zIHJlcXVlcmlkb3MgKioKCkVsYWJvcmFyIHVuYSBiYXNlIGRlIGRhdG9zIGNvbiBsYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSAodmVudGFzIHNlbWFuYWxlcykgeSBsYXMgdmFyaWFibGVzIGluZGVwZW5kaWVudGVzIAoKKipQYXNvIDUuIFBsYW4gZGUgZWplY3VjaW9uICoqCgpNZXJjYWRvdGVjbmlhIGVsYWJvcmFyIGVsIHBsYW4gcGFyYSBkZXNwZWdhciBtb2RlbG8gcHJlZGljdGl2byBlbiBmYXNlczoKCiAgKipGYXNlIDEuKiogUGlsb3RvIChTYW4gQW50b25pbyBUeCkKCiAgKipGYXNlIDIuKiogVGV4YXMKCiAgKipGYXNlIDMuKiogRVVBCgpTaXN0ZW1hcyBhc2VndXJhcmEgbGEgY2FwdHVyYSBkZWwgbWFya2Rvd24gZW4gbGFzIGJhc2VzIGRlIGRhdG9zIAoKIyMgPHNwYW4gc3R5bGU9IkNvbG9yOnJveWFsYmx1ZSI+IENyZWFjacOzbiBkZSBsYSBiYXNlIGRlIGRhdG9zIGNvbnNvbGlkYWRhCmBgYHtyfQojQWdyZWdhciAiU1RPUkVTIiBhICJUUkFJTiIKCmJkIDwtIG1lcmdlKHRyYWluLCBzdG9yZXMsIGJ5PSAiU3RvcmUiKQoKI0FncmVnYXIgRkVBVFVSRVMgYSBiZApiZDEgPC0gbWVyZ2UoYmQsIGZlYXR1cmVzKQoKI0VsaW1pbmFyIGNvbHVtbmFzIApiZDIgPC0gYmQxCmJkMiA8LSBzdWJzZXQoYmQyLCBzZWxlY3QgPSAtYyhNYXJrRG93bjEsIE1hcmtEb3duMiwgTWFya0Rvd24zLCBNYXJrRG93bjQsIE1hcmtEb3duNSkpCnN1bW1hcnkoYmQyKQoKI0NhbWJpYXIgZm9ybWF0byBkZSBmZWNoYQpiZDIkRGF0ZSA8LSBhcy5EYXRlKGJkMiREYXRlLCBmb3JtYXQgPSAiJWQvJW0vJVkiKQpzdHIoYmQyKQoKI2luc3RhbGwucGFja2FnZXMoIndvcmRzcGFjZSIpCmxpYnJhcnkod29yZHNwYWNlKQoKc2lnbmNvdW50KGJkMiRXZWVrbHlfU2FsZXMpCgojRWxpbWluYXIgdmVudGFzIG1lbm9yZXMgcXVlIDAgCmJkMyA8LSBiZDIKYmQzIDwtIGJkM1tiZDMkV2Vla2x5ID4gMCwgXQpzdW1tYXJ5IChiZDMpCgojQWdyZWdhciBudW1lcm8gZGUgbGEgc2VtYW5hIApiZDQgPC0gYmQzCmJkNCR3ZWVrX251bWJlciA8LSBzdHJmdGltZShiZDQkRGF0ZSwgZm9ybWF0ID0gIiVWIikKc3RyKGJkNCkKYmQ0JHdlZWtfbnVtYmVyIDwtIGFzLmludGVnZXIoYmQ0JHdlZWtfbnVtYmVyKQpzdHIoYmQ0KQpzdW1tYXJ5KGJkNCkKCiNTZXBhcmFyIGHDsW8sIG1lcyB5IGRpYQpiZDUgPC0gYmQ0CmJkNSA8LSBiZDUgJT4lCiAgICBkcGx5cjo6bXV0YXRlKHllYXIgPSBsdWJyaWRhdGU6OnllYXIoRGF0ZSksCiAgICAgICAgICAgICAgICAgIG1vbnRoID0gbHVicmlkYXRlOjptb250aChEYXRlKSwKICAgICAgICAgICAgICAgICAgZGF5ID0gbHVicmlkYXRlOjpkYXkoRGF0ZSkpCgpzdW1tYXJ5IChiZDUpCmBgYAoKIyMgPHNwYW4gc3R5bGU9IkNvbG9yOnJveWFsYmx1ZSI+IEdlbmVyYXIgcmVncmVzacOzbgpgYGB7cn0KcmVncmVzaW9uIDwtIGxtKFdlZWtseV9TYWxlcyB+IFN0b3JlICsgRGVwdCArIElzSG9saWRheSArIFR5cGUgKyBTaXplICsgVGVtcGVyYXR1cmUgKyBGdWVsX1ByaWNlICsgQ1BJICsgVW5lbXBsb3ltZW50ICsgd2Vla19udW1iZXIgKyB5ZWFyICsgbW9udGggKyBkYXksIGRhdGE9YmQ1KQoKc3VtbWFyeSAocmVncmVzaW9uKQoKI1ZlbnRhcyBzZW1hbmFsZXMKI2xpYnJhcnkoc2hpbnkpCgojdWkgPC0gZmx1aWRQYWdlKAogICNzZWxlY3RJbnB1dCgiVmFyaWFibGVzIiwiVmFyaWFibGVzIixjaG9pY2VzID0gbmFtZXMoYmQ1KSksCiAgI3Bsb3RPdXRwdXQoIm15cGxvdCIpKQoKI3NlcnZlciA8LSBmdW5jdGlvbihpbnB1dCwgb3V0cHV0LCBzZXNzaW9uKSB7CgogICNvdXRwdXQkbXlwbG90IDwtIHJlbmRlclBsb3QoewogICAgI3Bsb3QoV2Vla2x5X1NhbGVzIH4gZ2V0KGlucHV0JFZhcmlhYmxlcykgLCBkYXRhPWJkNSkKICAjfSkKI30KCiNzaGlueUFwcCh1aSwgc2VydmVyKQpgYGAKCiMjIDxzcGFuIHN0eWxlPSJDb2xvcjpyb3lhbGJsdWUiPiBDb25zdHJ1aXIgdW4gbW9kZWxvIGRlIHByZWRpY2Npw7NuIApgYGB7cn0KZGF0b3NfbnVldm9zIDwtIGRhdGEuZnJhbWUoU3RvcmU9MSwgRGVwdD0xLCBJc0hvbGlkYXkgPSBUUlVFLCBUeXBlID0gIkEiLCBTaXplID0gMTUxMzE1LCBUZW1wZXJhdHVyZSA9IDU5LjE3LCBGdWVsX1ByaWNlID0gMy41NTI0LCBDUEkgPSAyMTQuODM3MiwgVW5lbXBsb3ltZW50ID0gNy42ODIsIHdlZWtfbnVtYmVyID0gMSwgeWVhciA9IDIwMTIsIG1vbnRoID0gMSwgZGF5ID0gMSkKCnByZWRpY3QgKHJlZ3Jlc2lvbiwgZGF0b3NfbnVldm9zKQpgYGAKCiMjIDxzcGFuIHN0eWxlPSJDb2xvcjpyb3lhbGJsdWUiPiBQcm9wdWVzdGFzIAoxLiBMYSBwcmltZXIgcHJvcHVlc3RhIGVzIGRhZG8gcXVlIGxhcyB2ZW50YXMgZXN0YW4gZXN0cmVjaGFtZW50ZSByZWxhY2lvbmFkYXMgY29uIGxhcyBzZW1hbmFzIGVuIGxhcyBjdWFsZXMgaGF5IGZlc3RpdmlkYWRlcywgc2Vyw61hIMOzcHRpbW8gY3JlYXIgZSBpbXBsZW1lbnRhciAqKm1hdGVyaWFsIFBPUCBlbiBQRFYgKFB1bnRvcyBkZSBWZW50YSkqKiBxdWUgYXl1ZGUgYSBnZW5lcmFyICoqYXdhcmVuZXNzKiogc29icmUgbG9zIHByb2R1Y3RvcyBtb3N0cmFkb3MgZW4gZmVzdGl2aWRhZGVzIChFai4gTmF2aWRhZCkgZSBpbmNyZW1lbnRlbiBlbCBhdHJhY3Rpdm8gdmlzdWFsIGVuIGxhIHRpZW5kYSBwYXJhIG1hbnRlbmVyIGVsICoqZW5nYWdlbWVudCoqIGNvbiBsb3MgY29uc3VtaWRvcmVzLiAKCjIuIExhIHNlZ3VuZGEgcHJvcHVlc3RhIHNlIGVuZm9jYXLDrWEgZW4gY2VudHJhcnNlIGVuIGVsIHJlc3RvIGRlIGxhcyBzZW1hbmFzIHNpbiBmZXN0aXZpZGFkZXMsIHBhcmEgbWFudGVuZXIgbGFzIHNlbWFuYXMgY29uIHRlbXBvcmFkYSBhbHRhIGVuIGVsIG1pc21vIG5pdmVsLCB5IGNvbnRyYXJlc3RhciBjb24gbGFzIG51ZXZhcyB2ZW50YXMgYcOxYWRpZGFzLiBQYXJhIGVzdGUgY2Fzbywgc2UgcmVhbGl6YXLDrWFuIGVuIHVuIHBlcmlvZG8gw7NwdGltbyBhbmFsaXphZG8gZW4gbGEgYmFzZSBkZSBkYXRvcywgZGlzZcOxYW5kbyB1bmEgc2VyaWUgZGUgKipwcm9tb2Npb25lcyB5IGRlc2N1ZW50b3MgZXhjbHVzaXZvcyBlbiBwcm9kdWN0b3MqKiBxdWUgc2UgZW5jdWVudHJlbiB1YmljYWRvcyBlbiBsYXMgem9uYXMgY2FsaWVudGVzIGRlbnRybyBkZWwgKipwbGFub2dyYW1hKiogZGUgbGEgdGllbmRhIFdhbG1hcnQuIAoKIyMgPHNwYW4gc3R5bGU9IkNvbG9yOnJveWFsYmx1ZSI+IENvbmNsdXNpb25lcyAKQWwgZmluYWxpemFyIGVzdGUgY2FzbywgcHVkaW1vcyBvYnNlcnZhciBjb21vIGEgdHJhdsOpcyBkZSB1bmEgbGltcGllemEgZGUgZGF0b3MgeSB1bmEgY29tYmluYWNpw7NuIGRlIGJhc2VzIGVzcGVjw61maWNhcyBwYXJhIFdhbG1hcnQsIGRlc2Fycm9sbGFtb3MgdW5hIHJlZ3Jlc2nDs24gcGFyYSBsYXMgdmVudGFzIHNlbWFuYWxlcywgcXVlIHNlIGFzb2NpYXJhbiBjb24gZGl2ZXJzYXMgdmFyaWFibGVzIGNvbW8gbGFzIGZlc3RpdmlkYWRlcywgbGEgdGVtcGVyYXR1cmEsIGVsIGHDsW8sIGVudHJlIG90cmFzLCB5IGNvbiBiYXNlIGVuIGVzdG8sIHVuIG1vZGVsbyBwcmVkaWN0aXZvIHF1ZSBhcnJvamFyYSB1biByZXN1bHRhZG8gZnV0dXJvIGRlIGxhcyB2ZW50YXMgY29uIGJhc2UgZW4gbGEgcmVncmVzacOzbiBoaXN0w7NyaWNhIHJlc3VsdGFudGUuIAoKRGUgZXN0YSBmb3JtYSwgc2UgdmlzdWFsaXphcm9uIGxhcyB2YXJpYWJsZXMgcXVlIG1heW9yIGFmZWN0YXLDs24gbGFzIHZlbnRhcyBzZW1hbmFsZXMgKiooVGllbmRhLCBkZXBhcnRhbWVudG8sIGZlc3RpdmlkYWQsIHRhbWHDsW8sIENQSSwgYcOxbykqKiwgeSBjb24gZWxsbywgc2UgcmVhbGl6YXJvbiBkb3MgcHJvcHVlc3RhcyBwYXJhIGVsIGRlcGFydGFtZW50byBkZSBtZXJjYWRvdGVjbmlhIHF1ZSBheXVkYXJhbiBhIGRlc3BlZ2FyIGVsIG1vZGVsbyBwcmVkaWN0aXZvIGVuIGxhcyAzIGZhc2VzOiAqKlBpbG90byAoU2FuIEFudG9uaW8pLCBUZXhhcywgeSBFVUEuKiogU2UgZXNwZXJhIHF1ZSBlbCBkZXBhcnRhbWVudG8gbGFzIGFuYWxpY2UsIHNpc3RlbWFzIGF5dWRlIGEgY29ycm9ib3JhciBsYXMgYmFzZXMgZGUgZGF0b3MsIHkgYWwgZmluYWwgc2Ugb2J0ZW5nYSB1biByZXN1bHRhZG8gZXN0cmVjaGFtZW50ZSBzaW1pbGFyIGFsIG1vZGVsbyBwcmVkaWN0aXZvIGRlIGxhcyB2ZW50YXMgc2VtYW5hbGVzLiAKCiFbXShodHRwczovL3Bicy50d2ltZy5jb20vbWVkaWEvRHJUOTctV1hjQUFYWkxNLmpwZyApe3dpZHRoPSc2MDBweCd9IAo=