Instalar paquetes y llamar a librerias

library(ggplot2) #hacer gráficos
library(dplyr)
library(tidyr)
library(readxl) #leer el excel
library(forecast) #generar series de tiempo

Actividad Individual 2

Importar la base de datos

df <- read_excel('/Users/angiezeron/Documents/R things/Datos Arca Continental Original.xlsx')
df
## # A tibble: 466,509 × 25
##       ID   Año Territorio  `Sub Territorio` CEDI         Cliente Nombre
##    <dbl> <dbl> <chr>       <chr>            <chr>        <chr>   <chr> 
##  1     1  2016 Guadalajara Belenes          Suc. Belenes 77737   ABARR 
##  2     2  2016 Guadalajara Belenes          Suc. Belenes 77737   ABARR 
##  3     3  2016 Guadalajara Belenes          Suc. Belenes 77737   ABARR 
##  4     4  2016 Guadalajara Belenes          Suc. Belenes 77737   ABARR 
##  5     5  2016 Guadalajara Belenes          Suc. Belenes 77737   ABARR 
##  6     6  2016 Guadalajara Belenes          Suc. Belenes 77737   ABARR 
##  7     7  2016 Guadalajara Belenes          Suc. Belenes 77737   ABARR 
##  8     8  2016 Guadalajara Belenes          Suc. Belenes 77737   ABARR 
##  9     9  2016 Guadalajara Belenes          Suc. Belenes 77737   ABARR 
## 10    10  2016 Guadalajara Belenes          Suc. Belenes 77737   ABARR 
## # ℹ 466,499 more rows
## # ℹ 18 more variables: `Tamaño Cte Industria` <chr>, `Segmento Det` <chr>,
## #   Marca <chr>, Presentacion <chr>, Tamaño <chr>, Retornable_NR <chr>,
## #   Enero <dbl>, Febrero <dbl>, Marzo <dbl>, Abril <dbl>, Mayo <dbl>,
## #   Junio <dbl>, Julio <dbl>, Agosto <dbl>, Septiembre <dbl>, Octubre <dbl>,
## #   Noviembre <dbl>, Diciembre <dbl>

Revisar la estructura de datos

str(df)
## tibble [466,509 × 25] (S3: tbl_df/tbl/data.frame)
##  $ ID                  : num [1:466509] 1 2 3 4 5 6 7 8 9 10 ...
##  $ Año                 : num [1:466509] 2016 2016 2016 2016 2016 ...
##  $ Territorio          : chr [1:466509] "Guadalajara" "Guadalajara" "Guadalajara" "Guadalajara" ...
##  $ Sub Territorio      : chr [1:466509] "Belenes" "Belenes" "Belenes" "Belenes" ...
##  $ CEDI                : chr [1:466509] "Suc. Belenes" "Suc. Belenes" "Suc. Belenes" "Suc. Belenes" ...
##  $ Cliente             : chr [1:466509] "77737" "77737" "77737" "77737" ...
##  $ Nombre              : chr [1:466509] "ABARR" "ABARR" "ABARR" "ABARR" ...
##  $ Tamaño Cte Industria: chr [1:466509] "Extra Grande" "Extra Grande" "Extra Grande" "Extra Grande" ...
##  $ Segmento Det        : chr [1:466509] "Agua Mineral" "Agua Purificada" "Agua Purificada" "Agua Saborizada" ...
##  $ Marca               : chr [1:466509] "Topo Chico A.M." "Ciel Agua Purificada" "Ciel Agua Purificada" "Ciel Exprim" ...
##  $ Presentacion        : chr [1:466509] "600 ml NR" "1 Ltro. N.R." "1.5 Lts. NR" "600 ml NR" ...
##  $ Tamaño              : chr [1:466509] "Individual" "Individual" "Individual" "Individual" ...
##  $ Retornable_NR       : chr [1:466509] "No Retornable" "No Retornable" "No Retornable" "No Retornable" ...
##  $ Enero               : num [1:466509] NA NA NA NA NA NA 1 NA 3 NA ...
##  $ Febrero             : num [1:466509] NA 2 NA NA NA NA NA 1 3 NA ...
##  $ Marzo               : num [1:466509] NA 8 3 NA NA 1 NA NA 4 NA ...
##  $ Abril               : num [1:466509] NA 4 6 NA NA NA NA 1 4 NA ...
##  $ Mayo                : num [1:466509] NA 4 3 NA NA NA 0 NA 4 NA ...
##  $ Junio               : num [1:466509] NA 2 3 NA NA NA NA 1 4 0 ...
##  $ Julio               : num [1:466509] NA 2 3 NA NA NA 0 NA 4 NA ...
##  $ Agosto              : num [1:466509] NA 2 3 NA NA NA NA 1 7 NA ...
##  $ Septiembre          : num [1:466509] NA 2 3 NA NA NA NA 1 4 NA ...
##  $ Octubre             : num [1:466509] NA 2 3 NA NA NA 0 NA 3 NA ...
##  $ Noviembre           : num [1:466509] NA 4 3 NA 0 NA NA NA 1 NA ...
##  $ Diciembre           : num [1:466509] 1 2 3 1 NA NA NA NA 3 NA ...

Revisar NAs en la el df

#Cuantos NAs tengo en la base de datos?
sum(is.na(df))
## [1] 3148501
#cuantos NAs tengo por variable
sapply(df, function(x) sum(is.na(x)))
##                   ID                  Año           Territorio 
##                    0                    0                    0 
##       Sub Territorio                 CEDI              Cliente 
##                    0                    0                    0 
##               Nombre Tamaño Cte Industria         Segmento Det 
##                    0                    0                    0 
##                Marca         Presentacion               Tamaño 
##                    0                    0                    0 
##        Retornable_NR                Enero              Febrero 
##                    0               233480               231213 
##                Marzo                Abril                 Mayo 
##               227420               224057               216910 
##                Junio                Julio               Agosto 
##               215753               223411               220242 
##           Septiembre              Octubre            Noviembre 
##               337314               338386               338460 
##            Diciembre 
##               341855
#Opcion 1. eliminar NAs
# df1 <- na.omit(df)

#Opcion 2. Reemplazar con ceros
df1 <- df
df1[is.na(df1)] <- 0

#Opcion 3. Reeemplazar NAs con promedio
#df1<-df
#df1$Enero[is.na(df1$enero)] <- mean(df1$enero, na.rm=TRUE)

Detectar valores atípicos

boxplot(df1$Enero)

#Eliminar remglon de los totales
df1 <- df1[df1$Enero <6000,]

Funciones del Paquete Dplyr

# Adecuar nombres con gsub
names(df1) <- gsub(" ","_", names (df1))

# Muestra las ventas de Enero a Junio por CEDI:
df2 <- select(df1,c(CEDI,Enero:Junio))

# Muestra los movimientos por Cedi y tamaño de tienda grande
df3 <- df1 %>% filter(Tamaño_Cte_Industria == "Grande")

# Ordena la base de datos por CEDI, por marca y por presentación
df4 <- df1 %>% arrange(CEDI,Marca,Presentacion)

# Agrega un campo calculado con las ventas del primer semestre y muestra las ventas del primer semestre por marca.
df5 <- df1 %>% 
  mutate(Ventas_Sem1 = Enero + Febrero + Marzo + Abril + Mayo + Junio)

ventas_sem1_por_marca <- df5 %>% 
  group_by(Marca) %>% 
  summarise(Ventas_Sem1= sum(Ventas_Sem1))

# Obtén la media de las ventas del primer semestre agrupado por marca, presentación y tamaño.
df6 <- df5 %>%
  group_by(Marca,Presentacion,Tamaño) %>%
  summarise(Ventas_Sem1= mean(Ventas_Sem1))
## `summarise()` has grouped output by 'Marca', 'Presentacion'. You can override
## using the `.groups` argument.
#Calcular medidas de tendencia central
summary(df1)
##        ID              Año        Territorio        Sub_Territorio    
##  Min.   :     1   Min.   :2016   Length:466508      Length:466508     
##  1st Qu.:116628   1st Qu.:2017   Class :character   Class :character  
##  Median :233256   Median :2018   Mode  :character   Mode  :character  
##  Mean   :233255   Mean   :2018                                        
##  3rd Qu.:349882   3rd Qu.:2019                                        
##  Max.   :466509   Max.   :2019                                        
##      CEDI             Cliente             Nombre          Tamaño_Cte_Industria
##  Length:466508      Length:466508      Length:466508      Length:466508       
##  Class :character   Class :character   Class :character   Class :character    
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character    
##                                                                               
##                                                                               
##                                                                               
##  Segmento_Det          Marca           Presentacion          Tamaño         
##  Length:466508      Length:466508      Length:466508      Length:466508     
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  Retornable_NR          Enero             Febrero             Marzo         
##  Length:466508      Min.   : -19.000   Min.   : -11.000   Min.   : -32.000  
##  Class :character   1st Qu.:   0.000   1st Qu.:   0.000   1st Qu.:   0.000  
##  Mode  :character   Median :   0.000   Median :   0.000   Median :   0.000  
##                     Mean   :   4.951   Mean   :   4.829   Mean   :   5.729  
##                     3rd Qu.:   2.000   3rd Qu.:   2.000   3rd Qu.:   3.000  
##                     Max.   :5333.000   Max.   :4995.000   Max.   :5636.000  
##      Abril               Mayo             Junio              Julio         
##  Min.   : -70.000   Min.   :-106.00   Min.   :-211.000   Min.   : -60.000  
##  1st Qu.:   0.000   1st Qu.:   0.00   1st Qu.:   0.000   1st Qu.:   0.000  
##  Median :   0.000   Median :   0.00   Median :   0.000   Median :   0.000  
##  Mean   :   5.992   Mean   :   6.73   Mean   :   6.464   Mean   :   6.033  
##  3rd Qu.:   3.000   3rd Qu.:   3.00   3rd Qu.:   3.000   3rd Qu.:   3.000  
##  Max.   :6164.000   Max.   :6759.00   Max.   :6033.000   Max.   :6735.000  
##      Agosto           Septiembre          Octubre           Noviembre      
##  Min.   :-211.000   Min.   :-527.000   Min.   : -38.000   Min.   : -25.00  
##  1st Qu.:   0.000   1st Qu.:   0.000   1st Qu.:   0.000   1st Qu.:   0.00  
##  Median :   0.000   Median :   0.000   Median :   0.000   Median :   0.00  
##  Mean   :   6.235   Mean   :   3.625   Mean   :   3.674   Mean   :   3.57  
##  3rd Qu.:   3.000   3rd Qu.:   1.000   3rd Qu.:   1.000   3rd Qu.:   1.00  
##  Max.   :6065.000   Max.   :6509.000   Max.   :6326.000   Max.   :5319.00  
##    Diciembre       
##  Min.   : -28.000  
##  1st Qu.:   0.000  
##  Median :   0.000  
##  Mean   :   3.858  
##  3rd Qu.:   0.000  
##  Max.   :6182.000
#Colapsar meses en una comlumna
df7 <- gather(df1, Mes, Ventas, Enero:Diciembre)
df7
## # A tibble: 5,598,096 × 15
##       ID   Año Territorio  Sub_Territorio CEDI         Cliente Nombre
##    <dbl> <dbl> <chr>       <chr>          <chr>        <chr>   <chr> 
##  1     1  2016 Guadalajara Belenes        Suc. Belenes 77737   ABARR 
##  2     2  2016 Guadalajara Belenes        Suc. Belenes 77737   ABARR 
##  3     3  2016 Guadalajara Belenes        Suc. Belenes 77737   ABARR 
##  4     4  2016 Guadalajara Belenes        Suc. Belenes 77737   ABARR 
##  5     5  2016 Guadalajara Belenes        Suc. Belenes 77737   ABARR 
##  6     6  2016 Guadalajara Belenes        Suc. Belenes 77737   ABARR 
##  7     7  2016 Guadalajara Belenes        Suc. Belenes 77737   ABARR 
##  8     8  2016 Guadalajara Belenes        Suc. Belenes 77737   ABARR 
##  9     9  2016 Guadalajara Belenes        Suc. Belenes 77737   ABARR 
## 10    10  2016 Guadalajara Belenes        Suc. Belenes 77737   ABARR 
## # ℹ 5,598,086 more rows
## # ℹ 8 more variables: Tamaño_Cte_Industria <chr>, Segmento_Det <chr>,
## #   Marca <chr>, Presentacion <chr>, Tamaño <chr>, Retornable_NR <chr>,
## #   Mes <chr>, Ventas <dbl>

Actividad Colaborativa 2

Angie Zeron A00834060 Antonio Kuri A01722016 Isaac Perez A01252923

## Muestra las ventas anuales totales por tamaño... 
#Se nota que el tamaño familiar es el más vendido con un total de venta de 15787181:
df7_tarea <- select(df1,c(Tamaño,Enero:Diciembre))

df7_tarea$total = rowSums(df7_tarea[, c("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")])

df7_agrupado = df7_tarea %>%
  group_by(Tamaño) %>%
  summarize(Total_Grupo = sum(total))

print(df7_agrupado)
## # A tibble: 2 × 2
##   Tamaño     Total_Grupo
##   <chr>            <dbl>
## 1 Familiar      15787181
## 2 Individual    12992631
## Muestra los movimientos por sub territorio en especifico Belenes... 
#Se identifico que en el sub territorio de Belenes hubo un total de venta de 9176279 
df8 <- df1 %>% filter(Sub_Territorio == "Belenes")

df8$total = rowSums(df8[, c("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")])

df8_agrupado = df8 %>%
  group_by(Sub_Territorio) %>%
  summarize(Total_Grupo = sum(total))

print(df8_agrupado)
## # A tibble: 1 × 2
##   Sub_Territorio Total_Grupo
##   <chr>                <dbl>
## 1 Belenes            9176279
##  base de datos ordenada por Retornable o no retonable, por marca y por presentación... 
#Se notó que los refrescos retornables tienen mayor frecuencia de venta, ya que ocupan los primeros 5 lugares
df9 <- df1 %>% arrange(Retornable_NR,Marca,Presentacion)

df9$total = rowSums(df9[, c("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")])


## Campo calculado con las ventas anuales y muestra las                   ventas anuales por presentación... 
#Se identificó que la presentación de 2.5 Lts. Ret Pet fue la más exitosa con un total de venta de 5829946
df10 <- df1 %>% 
  mutate(Ventas_Anuales = Enero + Febrero + Marzo + Abril + Mayo + Junio + Julio + Agosto + Septiembre + Octubre + Noviembre + Diciembre)

ventas_anuales_por_presentacion <- df10 %>% 
  group_by(Presentacion) %>% 
  summarise(Ventas_Anuales= sum(Ventas_Anuales))

## Media de las ventas del primer semestre agrupado por presentación y tamaño... 
#Se identificó que en promedio la presentación de 2.5 Lts. Ret Pet se vendió en promedio 814.1245636

df11 <- df10 %>%
  group_by(Presentacion,Tamaño) %>%
  summarise(Ventas_Anuales= mean(Ventas_Anuales))
## `summarise()` has grouped output by 'Presentacion'. You can override using the
## `.groups` argument.

Actividad Individual 3

#Agregar una columna con el número del mes
meses <- c("Enero"="01", "Febrero"="02", "Marzo"="03", "Abril"="04", "Mayo"="05", "Junio"="06", "Julio"="07", "Agosto"="08", "Septiembre"="09", "Octubre"="10", "Noviembre"="11", "Diciembre"="12")

df7$Número_de_Mes <- meses[df7$Mes]

#Gráfica promedio de ventas por mes y añ0

ventas_totales <- df7 %>%
  group_by(Año, Número_de_Mes) %>%
  summarise(Ventas_Totales = sum(Ventas)) %>%
  arrange(Número_de_Mes)
## `summarise()` has grouped output by 'Año'. You can override using the `.groups`
## argument.
ggplot(ventas_totales, aes(x=Número_de_Mes, y=Ventas_Totales, group=Año, color=as.factor(Año))) +
  geom_line() + 
  geom_point() +
  labs(x="Mes", y="Ventas Totales (Qty)", color= "Año")

Actividad Colaborativa 3

Ventas Totales por Marca

# Se identificó que las marcas con mayor cantidad de ventas fueron Coca Cola, Agua purificada ciel, Coca Cola Light, Sprite

ventas_totales_por_marca <- df7 %>%
  group_by(Marca) %>%
  summarise(ventas_totales_por_marca = sum(Ventas)) %>%
  arrange(ventas_totales_por_marca)

ggplot(ventas_totales_por_marca, aes(x=ventas_totales_por_marca, y=Marca, group=Marca, color=as.factor(Marca))) +
  geom_line() +
  geom_point() +
  labs(x="Ventas Totales (Qty)", y="Marca", color= "Marca")
## `geom_line()`: Each group consists of only one observation.
## ℹ Do you need to adjust the group aesthetic?

Ventas Totales por Tamaño

# Se identificó que el tamaño mas vendido es el familiar por mucho

ventas_totales_por_tamaño <- df7 %>%
  group_by(Tamaño) %>%
  summarise(ventas_totales_por_tamaño = sum(Ventas)) %>%
  arrange(ventas_totales_por_tamaño)

ggplot(ventas_totales_por_tamaño, aes(x=Tamaño, y=ventas_totales_por_tamaño, group=Tamaño, color=as.factor(Tamaño))) +
  geom_line() +
  geom_point() +
  labs(x="Tamaño", y="Ventas Totales (Qty)", color= "Tamaño")
## `geom_line()`: Each group consists of only one observation.
## ℹ Do you need to adjust the group aesthetic?

Ventas totales por Sub-Territorio

# Se identificó que el orden de mayor a menor venta por territorio es Toluquilla, Belenes, Huentitán

ventas_totales_por_subt <- df7 %>%
  group_by(Sub_Territorio) %>%
  summarise(ventas_totales_por_subt = sum(Ventas)) %>%
  arrange(ventas_totales_por_subt)

ggplot(ventas_totales_por_subt, aes(x=Sub_Territorio, y=ventas_totales_por_subt, group=Sub_Territorio, color=as.factor(Sub_Territorio))) +
  geom_line() +
  geom_point() +
  labs(x="Sub_Territorio", y="Ventas Totales (Qty)", color= "Sub_Territorio")
## `geom_line()`: Each group consists of only one observation.
## ℹ Do you need to adjust the group aesthetic?

Ventas totales por Año

# Se identificó que el año con mayor cantidad de ventas fue el 2019 seguido por el 2017, 2018 y 2016

ventas_totales_por_año <- df7%>%
  group_by(Año) %>%
  summarise(ventas_totales_por_año = sum(Ventas)) %>%
  arrange(ventas_totales_por_año)

ggplot(ventas_totales_por_año, aes(x=Año, y=ventas_totales_por_año, group=Año, color=as.factor(Año))) +
  geom_bar(stat = "identity", fill = "white") +
  theme_minimal() +
  labs(x="Año", y="Ventas Totales (Qty)", color= "Año")

Ventas Totales por Retornable y No Retornable

# Se identificó que la cantidad de ventas de los productos retornables y no retornables es muy similar, sin embargo se nota una ligera diferencia a favor de lo retornable

ventas_totales_por_retonoret <- df7 %>%
  group_by(Retornable_NR) %>%
  summarise(ventas_totales_por_retonoret = sum(Ventas)) %>%
  arrange(ventas_totales_por_retonoret)

ggplot(ventas_totales_por_retonoret, aes(x=Retornable_NR, y=ventas_totales_por_retonoret, group=Retornable_NR, color=as.factor(Retornable_NR))) +
  geom_bar(stat = "identity", fill = "transparent") +
  theme_minimal() +
  labs(x="Retornable_NR", y="Ventas Totales (Qty)", color= "Retornable_NR")

Actividad Individual 4

#Elaborar regresión lineal

ventas_4567 <- df7 %>%
  filter(Cliente == "4567") %>%
  group_by(Año) %>%
  summarise(Ventas_totales = sum(Ventas)) %>%
  filter(Ventas_totales !=0) #para quitar los renglones con 0

#ventas_mayores$Secuencia <- 1:nrow(ventas_mayores) # es una secuencia por si lo ocupamos en algo mas
#cuando hago regreson ocupo que el eje x sea un rumero, asi que se cambia a una secuencia de meses para que no se confunda al graficarlo

ggplot(ventas_4567, aes(x=Año, y=Ventas_totales)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Ventas totales del cliente 4567")

regresion <- lm(Ventas_totales ~ Año, data=ventas_4567)
summary(regresion)
## 
## Call:
## lm(formula = Ventas_totales ~ Año, data = ventas_4567)
## 
## Residuals:
##     1     2     3 
## -5092 10185 -5092 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)
## (Intercept) 48918677   17799125   2.748    0.222
## Año           -24174       8820  -2.741    0.223
## 
## Residual standard error: 12470 on 1 degrees of freedom
## Multiple R-squared:  0.8825, Adjusted R-squared:  0.765 
## F-statistic: 7.512 on 1 and 1 DF,  p-value: 0.2227
#Ecuacion
#y=48918677 + ( -24174 )

#R cuadrada ajustada
#0.765 

datos <- data.frame(Año=2020:2025)
prediccion <-predict(regresion,datos)
prediccion
##          1          2          3          4          5          6 
##  87197.333  63023.333  38849.333  14675.333  -9498.667 -33672.667
ventas_4567$Tipo_de_Dato <- "Datos Reales"
datos$Ventas_totales <- prediccion
datos$Tipo_de_Dato <- "Prediccion"

datos_combinados <- rbind(ventas_4567, datos)

ggplot(datos_combinados, aes(x=Año, y=Ventas_totales, color=Tipo_de_Dato)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Pronóstico a 5 años de ventas del cliente 4567")

Análisis: Según este pronóstico a 5 años, la ventas del cliente 4567 van a decrecer

Actividad Colaborativa 4

Angie Zeron A00834060 Antonio Kuri A01722016 Isaac Perez A01252923

#¿A cuánto ascienden las ventas esperadas para el 2020 en la Coca Cola de 500 ml NR Vidrio?

ventas_esperadas <- df7 %>%
  filter(Marca == "Coca-Cola" & Presentacion =="500 ml NR Vidrio") %>%
  group_by(Año) %>%
  summarise(Ventas_Totales = sum(Ventas)) %>%
  filter(Ventas_Totales !=0) %>% #para quitar los renglones con 0
  filter(Año !=2016)

ggplot(ventas_esperadas, aes(x=Año, y=Ventas_Totales)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Ventas Anuales de Coca Cola")

regresion1 <- lm(Ventas_Totales ~ Año, data=ventas_esperadas)
summary(regresion1)
## 
## Call:
## lm(formula = Ventas_Totales ~ Año, data = ventas_esperadas)
## 
## Residuals:
##     1     2     3 
##  1732 -3465  1732 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)
## (Intercept) -5303404    6054988  -0.876    0.542
## Año             2833       3000   0.944    0.518
## 
## Residual standard error: 4243 on 1 degrees of freedom
## Multiple R-squared:  0.4713, Adjusted R-squared:  -0.05738 
## F-statistic: 0.8915 on 1 and 1 DF,  p-value: 0.5183
#Ecuacion
#y= -5303404 +  2833

#R cuadrada ajustada
# -0.05738 

datos <- data.frame(Año=2020:2025)
prediccion <-predict(regresion1,datos)
prediccion
##        1        2        3        4        5        6 
## 419255.7 422088.7 424921.7 427754.7 430587.7 433420.7
ventas_esperadas$Tipo_de_Dato <- "Datos Reales"
datos$Ventas_Totales <- prediccion
datos$Tipo_de_Dato <- "Prediccion"

datos_combinados <- rbind(ventas_esperadas, datos)

ggplot(datos_combinados, aes(x=Año, y=Ventas_Totales, color=Tipo_de_Dato)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Pronóstico de ventas esperadas para el 2020", subtitle = "Coca Cola de 500 ml NR Vidrio")

Análisis: Para el año 2020, se espera que las ventas de COCA COLA de 500 ml NR Vidrio tenddra ventas esperadas de 419,000

#Ventas totales del cliente 6626

ventas_6626 <- df7 %>%
  filter(Cliente == "6626") %>%
  group_by(Año) %>%
  summarise(Ventas_totales = sum(Ventas)) %>%
  filter(Ventas_totales !=0) #para quitar los renglones con 0

#ventas_mayores$Secuencia <- 1:nrow(ventas_mayores) # es una secuencia por si lo ocupamos en algo mas
#cuando hago regreson ocupo que el eje x sea un rumero, asi que se cambia a una secuencia de meses para que no se confunda al graficarlo

ggplot(ventas_6626, aes(x=Año, y=Ventas_totales)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Ventas totales del cliente 0948")

regresion <- lm(Ventas_totales ~ Año, data=ventas_6626)
summary(regresion)
## 
## Call:
## lm(formula = Ventas_totales ~ Año, data = ventas_6626)
## 
## Residuals:
##     1     2     3 
## -2811  5622 -2811 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)
## (Intercept) 55208195    9825229   5.619    0.112
## Año           -27316       4869  -5.610    0.112
## 
## Residual standard error: 6886 on 1 degrees of freedom
## Multiple R-squared:  0.9692, Adjusted R-squared:  0.9384 
## F-statistic: 31.48 on 1 and 1 DF,  p-value: 0.1123
#Ecuacion
#y= 55208195 + (  -27316 )
# este es el intercepto  este es la correlacion (en este caso negativa)

#R cuadrada ajustada
# 0.9384  

datos <- data.frame(Año=2020:2025)
prediccion <-predict(regresion,datos)
prediccion
##       1       2       3       4       5       6 
##   29875    2559  -24757  -52073  -79389 -106705
ventas_6626$Tipo_de_Dato <- "Datos Reales"
datos$Ventas_totales <- prediccion
datos$Tipo_de_Dato <- "Prediccion"

datos_combinados <- rbind(ventas_6626, datos)

ggplot(datos_combinados, aes(x=Año, y=Ventas_totales, color=Tipo_de_Dato)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Pronóstico a 5 años de ventas del cliente 6626")

Análisis: Las ventas del cliente 6626 tienen tendencia a caer a los proximos años. Se puede deber a cambios en la preferencia de los consumidores, tendencias del mercado, etc.

#Ventas totales de Guadalajara

ventas_gdl <- df7 %>%
  group_by(Año) %>%
  summarise(Ventas_totales = sum(Ventas)) %>%
  filter(Ventas_totales !=0) #para quitar los renglones con 0

#ventas_mayores$Secuencia <- 1:nrow(ventas_mayores) # es una secuencia por si lo ocupamos en algo mas
#cuando hago regreson ocupo que el eje x sea un rumero, asi que se cambia a una secuencia de meses para que no se confunda al graficarlo

ggplot(ventas_gdl, aes(x=Año, y=Ventas_totales)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Ventas totales del cliente 0948")

regresion <- lm(Ventas_totales ~ Año, data=ventas_gdl)
summary(regresion)
## 
## Call:
## lm(formula = Ventas_totales ~ Año, data = ventas_gdl)
## 
## Residuals:
##       1       2       3       4 
##   98787  151376 -599113  348950 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)  
## (Intercept) -1.398e+09  4.571e+08  -3.058   0.0924 .
## Año          6.964e+05  2.266e+05   3.073   0.0916 .
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 506600 on 2 degrees of freedom
## Multiple R-squared:  0.8253, Adjusted R-squared:  0.7379 
## F-statistic: 9.446 on 1 and 2 DF,  p-value: 0.09156
#Ecuacion
#y= -1.398e+09 + (6.964e+05)


#R cuadrada ajustada
# 0.7379   

datos <- data.frame(Año=2020:2025)
prediccion <-predict(regresion,datos)
prediccion
##        1        2        3        4        5        6 
##  8935914  9632299 10328684 11025068 11721453 12417837
ventas_gdl$Tipo_de_Dato <- "Datos Reales"
datos$Ventas_totales <- prediccion
datos$Tipo_de_Dato <- "Prediccion"

datos_combinados <- rbind(ventas_gdl, datos)

ggplot(datos_combinados, aes(x=Año, y=Ventas_totales, color=Tipo_de_Dato)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Pronóstico a 5 años de ventas en GDL")

Análisis: Se pronostica que las ventas van a crecer en el territorio de Guadalajara en los próximos ańos

#Ventas esperadas en el sub territorio de BELENES del producto AGUA PURIFICADA

ventas_segmento <- df7 %>%
  filter(Sub_Territorio == "Belenes" & Segmento_Det =="Agua Purificada") %>%
  group_by(Año) %>%
  summarise(Ventas_Totales = sum(Ventas)) %>%
  filter(Ventas_Totales !=0) %>% #para quitar los renglones con 0
  filter(Año !=2016)

ggplot(ventas_segmento, aes(x=Año, y=Ventas_Totales)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Ventas Anuales de Coca Cola")

regresion1 <- lm(Ventas_Totales ~ Año, data=ventas_segmento)
summary(regresion1)
## 
## Call:
## lm(formula = Ventas_Totales ~ Año, data = ventas_segmento)
## 
## Residuals:
##      1      2      3 
##  15616 -31232  15616 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)
## (Intercept) -156230141   54582274  -2.862    0.214
## Año              77493      27048   2.865    0.214
## 
## Residual standard error: 38250 on 1 degrees of freedom
## Multiple R-squared:  0.8914, Adjusted R-squared:  0.7828 
## F-statistic: 8.209 on 1 and 1 DF,  p-value: 0.2138
#Ecuacion
#y= -5303404 +  2833

#R cuadrada ajustada
# -0.05738 

datos <- data.frame(Año=2020:2025)
prediccion <-predict(regresion1,datos)
prediccion
##      1      2      3      4      5      6 
## 305719 383212 460705 538198 615691 693184
ventas_segmento$Tipo_de_Dato <- "Datos Reales"
datos$Ventas_Totales <- prediccion
datos$Tipo_de_Dato <- "Prediccion"

datos_combinados <- rbind(ventas_segmento, datos)

ggplot(datos_combinados, aes(x=Año, y=Ventas_Totales, color=Tipo_de_Dato)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Pronóstico de ventas esperadas para Belenes", subtitle = "En Agua Purificada")

Análisis: Las ventas en el sub territorio Belenes en tanto Agua purificada va a tener una tendencia de crecimiento para los próximos 4 años.

#Ventas en el sub segmento de toluquilla para las bebidas de fruta 

ventas_segmento1 <- df7 %>%
  filter(Sub_Territorio == "Toluquilla" & Segmento_Det =="Bebidas de Fruta") %>%
  group_by(Año) %>%
  summarise(Ventas_Totales = sum(Ventas)) %>%
  filter(Ventas_Totales !=0) %>% #para quitar los renglones con 0
  filter(Año !=2016)

ggplot(ventas_segmento1, aes(x=Año, y=Ventas_Totales)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Ventas Anuales de Coca Cola")

regresion1 <- lm(Ventas_Totales ~ Año, data=ventas_segmento1)
summary(regresion1)
## 
## Call:
## lm(formula = Ventas_Totales ~ Año, data = ventas_segmento1)
## 
## Residuals:
##     1     2     3 
## -3357  6715 -3357 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)
## (Intercept) 11498348   11734816   0.980    0.506
## Año            -5676       5815  -0.976    0.508
## 
## Residual standard error: 8224 on 1 degrees of freedom
## Multiple R-squared:  0.4879, Adjusted R-squared:  -0.0242 
## F-statistic: 0.9527 on 1 and 1 DF,  p-value: 0.5077
#Ecuacion
#y= -5303404 +  2833

#R cuadrada ajustada
# -0.05738 

datos <- data.frame(Año=2020:2025)
prediccion <-predict(regresion1,datos)
prediccion
##         1         2         3         4         5         6 
## 32828.333 27152.333 21476.333 15800.333 10124.333  4448.333
ventas_segmento1$Tipo_de_Dato <- "Datos Reales"
datos$Ventas_Totales <- prediccion
datos$Tipo_de_Dato <- "Prediccion"

datos_combinados <- rbind(ventas_segmento1, datos)

ggplot(datos_combinados, aes(x=Año, y=Ventas_Totales, color=Tipo_de_Dato)) +
  geom_point() +
  labs(x="Año", y="Ventas Totales (Qty)", title = "Pronóstico de ventas esperadas para Toluquilla", subtitle = "En Bebidas de Fruta")

Análisis: Según el pronóstico, se espera que para el sub territorio de Toluquilla en cuanto a las bebidas de fruta, las ventas decrezcan.

top_10_clientes <- df7 %>%
  group_by(Cliente) %>%
  summarise(Ventas_Totales = sum(Ventas)) %>%
  arrange(desc(Ventas_Totales)) %>%
  top_n(10, Ventas_Totales)

top_10_clientes
## # A tibble: 10 × 2
##    Cliente Ventas_Totales
##    <chr>            <dbl>
##  1 4567            406636
##  2 6626            253521
##  3 5420            238048
##  4 9745            190233
##  5 2539            181847
##  6 6190            172311
##  7 1859            159890
##  8 6114            158145
##  9 8682            155956
## 10 8283            145717

Actividad Individual 5

#ventas mesuales del cliente 4567

ventas_mensuales_4567 <- df7 %>%
  filter(Cliente == "4567") %>%
  group_by(Año, Número_de_Mes) %>%
  summarise(Ventas_totales = sum(Ventas)) %>%
  filter(Ventas_totales !=0) #para quitar los renglones con 0
## `summarise()` has grouped output by 'Año'. You can override using the `.groups`
## argument.
ventas_mensuales_4567
## # A tibble: 32 × 3
## # Groups:   Año [3]
##      Año Número_de_Mes Ventas_totales
##    <dbl> <chr>                  <dbl>
##  1  2017 01                     11665
##  2  2017 02                     11395
##  3  2017 03                      9529
##  4  2017 04                     11701
##  5  2017 05                     15021
##  6  2017 06                     14567
##  7  2017 07                     15717
##  8  2017 08                     15371
##  9  2017 09                     15876
## 10  2017 10                     16451
## # ℹ 22 more rows
#para hacer series de tiempo R que los datos esten en orden cronológico (si no estuvieran le pones un arrange)
#solo ocupa una columna con los datos

#estas se pueden usar mensualmente, anual o trimestral

#Función serie de tiempo MENSUAL, que inicia en enero 2017
ts <-ts(data= ventas_mensuales_4567$Ventas_totales, start = c(2017, 1), frequency = 12) #el 1 es el periodo NO mes #el 12 son el total de periodos que hay en un año y como es mensual son 12

#Función serie de tiempo MENSUAL, que inicia en Abril 2017
#ts <-ts(data= ventas_mensuales_4567$Ventas_totales, start = c(2017, 4), frequency = 12) 

#Función serie de tiempo TRIMESTRAL, que inicia en Enero 2017
#ts <-ts(data= ventas_mensuales_4567$Ventas_totales, start = c(2017, 1), frequency = 4) 
#frecuencia = 4 pq hay 4 trimestres en un año

#Función serie de tiempo TRIMESTRAL, que inicia en Octubre 2017
#ts <-ts(data= ventas_mensuales_4567$Ventas_totales, start = c(2017, 4), frequency = 4) 

#Función serie de tiempo ANUAL, que inicia en Enero 2017
#ts <-ts(data= ventas_mensuales_4567$Ventas_totales, start = 2017, frequency = 1) 

#Función serie de tiempo SEMESTRAL, que inicia en Enero 2017
#ts <-ts(data= ventas_mensuales_4567$Ventas_totales, start = c(2017, 1), frequency = 2) #aqui el periodo solo puede ser 1 o 2

#crear moelo ARIMA(Modelo Autoregresivo Integrado de Promedio Movil)

arima <- auto.arima(ts, D=1) #D=1 por la temporalidad, si no lo ponemos te sale una predicción plana
arima
## Series: ts 
## ARIMA(0,0,0)(0,1,0)[12] 
## 
## sigma^2 = 10383172:  log likelihood = -189.94
## AIC=381.87   AICc=382.09   BIC=382.87
summary(arima) #debemos de enfocarnos en los números de error, donde el número por si solo no te dice si es mejor o peor, esto solo se sabra si se compara con otro modelo. Pero nos podemos enfocar en el MAPE este es el que tiene mas ventajas. si hacemos dos modelos comparamos los mapes
## Series: ts 
## ARIMA(0,0,0)(0,1,0)[12] 
## 
## sigma^2 = 10383172:  log likelihood = -189.94
## AIC=381.87   AICc=382.09   BIC=382.87
## 
## Training set error measures:
##                     ME     RMSE     MAE       MPE     MAPE      MASE      ACF1
## Training set -36.98041 2547.446 1572.02 -1.811657 13.08459 0.6269271 0.2519497
#generar el pronóstico de ventas
pronostico <- forecast(arima,level=95, h=36) #level=nivel de confianza h=periodos de pronóstico
pronostico
##          Point Forecast      Lo 95    Hi 95
## Sep 2019          12086  5770.4219 18401.58
## Oct 2019          11427  5111.4219 17742.58
## Nov 2019          11270  4954.4219 17585.58
## Dec 2019          12227  5911.4219 18542.58
## Jan 2020           9430  3114.4219 15745.58
## Feb 2020          11312  4996.4219 17627.58
## Mar 2020          12515  6199.4219 18830.58
## Apr 2020          13334  7018.4219 19649.58
## May 2020          16286  9970.4219 22601.58
## Jun 2020          15347  9031.4219 21662.58
## Jul 2020          14005  7689.4219 20320.58
## Aug 2020          14050  7734.4219 20365.58
## Sep 2020          12086  3154.4238 21017.58
## Oct 2020          11427  2495.4238 20358.58
## Nov 2020          11270  2338.4238 20201.58
## Dec 2020          12227  3295.4238 21158.58
## Jan 2021           9430   498.4238 18361.58
## Feb 2021          11312  2380.4238 20243.58
## Mar 2021          12515  3583.4238 21446.58
## Apr 2021          13334  4402.4238 22265.58
## May 2021          16286  7354.4238 25217.58
## Jun 2021          15347  6415.4238 24278.58
## Jul 2021          14005  5073.4238 22936.58
## Aug 2021          14050  5118.4238 22981.58
## Sep 2021          12086  1147.0979 23024.90
## Oct 2021          11427   488.0979 22365.90
## Nov 2021          11270   331.0979 22208.90
## Dec 2021          12227  1288.0979 23165.90
## Jan 2022           9430 -1508.9021 20368.90
## Feb 2022          11312   373.0979 22250.90
## Mar 2022          12515  1576.0979 23453.90
## Apr 2022          13334  2395.0979 24272.90
## May 2022          16286  5347.0979 27224.90
## Jun 2022          15347  4408.0979 26285.90
## Jul 2022          14005  3066.0979 24943.90
## Aug 2022          14050  3111.0979 24988.90
plot(pronostico, main = "Ventas Mensuales y Pronóstico a 3 Años del Cliente 4567",  xlab = "Año", ylab = "Ventas(qty)") 

#plot es la grafica mas sencilla, lo gris representa el 95 de confianza que le pusimos

EVIDENCIA

Preguntas Detonantes

1.

¿Puede observarse un crecimiento en las ventas de algunos de los segmentos de productos de la familia Coca Cola en las tiendas en las que se implementó el Proyecto Siglo XXI de Arca Continental?

ventas_totatles_seg <- df7 %>%
  filter(Segmento_Det %in% c("Agua Purificada", "Isotónicos Regular", "Colas Regular")) %>%
           filter(Año == 2018) %>%
           group_by(Segmento_Det, Número_de_Mes) %>%
           summarise(Ventas_Totales= sum(Ventas), .groups = "drop") %>%
           arrange(Número_de_Mes)

ggplot(ventas_totatles_seg, aes(x=Número_de_Mes, y=Ventas_Totales, group=Segmento_Det, color=as.factor(Segmento_Det))) +
  geom_line() + 
  geom_point() +
  labs(x="Mes", y="Ventas Totales (Qty)", title="Ventas Totales por Segmentos", subtitle = "Proyecto Siglo XXI (2018)", color= "Tamaño de Cliente") +
  theme(axis.text.x = element_text(angle=90, vjust=0.5, hjust=1))

Respuesta: En general las ventas aumentaron en 2019, pero cada segmento se comoporto diferente. El incremento de ventas se puede lograr ya sea a mejores campañas de mercadotecnia, lanzamiento de nuevos productos o cambios en las preferencias de los consumidores. En 2028 la venta de Coca Cola entre febrero y Diciembre aumentó en 100,000 unidades, mientras que en las aguas isotónicas no tuvieron cambios

2.

¿El incremento en las ventas es similar entre los diferentes tamaños de clientes?

ventas_totales_tamaño_cliente <- df7 %>%
  filter(Año=="2019") %>%
  group_by(Número_de_Mes, Tamaño_Cte_Industria) %>%
  summarise(Ventas_Totales = sum(Ventas), .groups = "drop") %>%
  arrange(Número_de_Mes) %>%
   filter(Ventas_Totales !=0)

ggplot(ventas_totales_tamaño_cliente, aes(x=Número_de_Mes, y=Ventas_Totales, group=Tamaño_Cte_Industria, color=as.factor(Tamaño_Cte_Industria))) +
  geom_line() + 
  geom_point() +
  labs(x="Mes", y="Ventas Totales (Qty)", title="Ventas Totales por Tamaño de Cliente", subtitle = "(2019)", color= "Tamaño de Cliente") +
  theme(axis.text.x = element_text(angle=90, vjust=0.5, hjust=1))

Respuesta: Independientemente del tamaño del cliente, el incremento en las ventas es similar. Como todos los negocios están abiertos los mismo días, y están ubícados en la misma ciudad (Guadalajara), los factores externos de las ventas afectan casi igual a todos. El mes de mayo fue el de mayo ventas para todos los tamaños de clientes, y el primer bimestre fue el mas bajo para todos los clientes.

3.

¿Cuál es el comportamiento observado de las unidades vendidas por mes de cada una de las marcas, independientemente de sus respectivas presentaciones?

ventas_totales_por_marca <- df7 %>%
  filter(Año ==2019) %>%
  filter(Marca %in% c("Coca-Cola", "Valle Frut", "Coca-Cola Light", "Agua purificada Ciel", "Joya", "Fresca")) %>%
  group_by(Marca, Número_de_Mes) %>%
  summarise(Ventas_Totales = sum(Ventas)) %>%
  arrange(Número_de_Mes) %>%
  filter(Ventas_Totales !=0)
## `summarise()` has grouped output by 'Marca'. You can override using the
## `.groups` argument.
ggplot(ventas_totales_por_marca, aes(x=Número_de_Mes, y=Ventas_Totales, group=Marca, color=as.factor(Marca))) +
  geom_line() + 
  geom_point() +
  labs(x="Mes", y="Ventas Totales (Qty)", title="Ventas Totales", subtitle="Top 5 Marcas (2019)", color= "Marca")

Respuesta: El comportamiento de ventas es similar entre las marcas a través de los meses, pero hay marcas que venden mucho más que otras. Los meses de las ventas de bebidas son los meses e que la temperatura es mayor, y las marcas más conocidas son las que estan que estan en la mente del consumidor. El mes de mayo 2019 es para todas las marcas el de mayores ventas, pero la marca Coca-Cola es la que vende más que todas

4.

¿Se ha incrementado la venta de productos en envases retornables en los últimos dos años?

ventas_envases_retornables<- df7 %>%
  filter(Retornable_NR == "Retornable" & Año==c(2018,2019)) %>%
  group_by(Año) %>%
  summarise(Ventas_Totales = sum(Ventas)) %>%
  filter(Ventas_Totales !=0) #para quitar los renglones con 0
  
ggplot(ventas_envases_retornables, aes(x=Año, y=Ventas_Totales)) +
  geom_line() +
  geom_point() +
  labs(title="Ventas de Productos en Envases Retornables en los Últimos Dos Años",
       x="Año",
       y="Ventas Totales")

Respuesta: La venta de productos en envases retornables ha incrementado en los últimos dos años de 3,400,000 en el 2018 a aproximadamente 4,320,000 en el 2019. Creciendo aproximadamente un 27.06%. Las campañas de conciencia ambiental han vuelto populares las opciones menos dañinas al ecosistema.

notas:

5.

¿El comportamiento de la venta de agua ha incrementado en relación al de los refrescos o las bebidas isotónicas?

ventas_aguas_refrescos <-df7 %>%
  filter(Segmento_Det %in% c("Agua Mineral", "Agua Purificada","Agua Saborizada", "Isotónicos Light", "Isotónicos Regular", "Colas Light", "Colas Regular")) %>%
  group_by(Año, Segmento_Det) %>%
  summarise(Ventas_Totales = sum(Ventas)) %>%
  filter(Ventas_Totales !=0) 
## `summarise()` has grouped output by 'Año'. You can override using the `.groups`
## argument.
ggplot(ventas_aguas_refrescos, aes(x = Año, y = Ventas_Totales, color = Segmento_Det)) +
  geom_line() +
  geom_point() +
  labs(title = "Comparación de Ventas: Agua vs. Refrescos vs. Bebidas Isotónicas",
       x = "Año",
       y = "Ventas Totales")

*Respuesta: las ventas de agua purificada no han aumentado en relacio2n a refrescos o bebidas isotónicas. Puede ser por la persepción que el agua no tiene valor agregado en la preparación y el azúcar en la receta hace de los refrescos la opción preferida de los consumidores mexicanos. En 2019 las ventas totales de agua purificada no superan 50,000 unidades, mientras que la Coca-Cola vendio en su mes más alto 630,000 unidades (11 veces más que el agua)

6.

¿Puede decirse que la venta mensual de agua está relacionada con la venta mensual de refrescos en los últimos 4 años?

ventas_totales_ayr <- df7 %>%
  filter(Segmento_Det == c("Agua Purificada", "Colas Regular")) %>%
  group_by(Segmento_Det, Año) %>%
  summarise(Ventas_Totales = sum(Ventas))
## `summarise()` has grouped output by 'Segmento_Det'. You can override using the
## `.groups` argument.
ggplot(ventas_totales_ayr, aes(x = Año, y = Ventas_Totales, group= Segmento_Det, color = Segmento_Det)) +
  geom_line() +
  geom_point() +
  labs(title = "Centas Totales por Segmento",
       x = "Año",
       y = "Ventas Totales (qty)",
       color="Segmento")

Respuesta:La venta de agua y refrescos se incrementan en los mismos meses, y a través de los años, pero no se puede concluir que un incremento cause el otro. Los meses calurosos y el crecimiento de ;a poblacio2n hace que las ventas se incrementen en en las bebidas, sean agua o refresco. En la gráfica obtenida se observa un incremento año con año en la venta de agua y también de refrescos.

6.1

¿Puede decirse que la venta mensual de agua está relacionada con la venta mensual de refrescos en los últimos 4 años?

ventas_relacion <- df7 %>%
  filter(Segmento_Det == c("Agua Mineral", "Agua Purificada","Colas Light", "Colas Regular")) %>%
  group_by(Año, Número_de_Mes, Segmento_Det) %>%
  summarise(Ventas_Relacion = sum(Ventas))
## `summarise()` has grouped output by 'Año', 'Número_de_Mes'. You can override
## using the `.groups` argument.
ggplot(ventas_relacion, aes(x = Número_de_Mes, y = Ventas_Relacion, color = Segmento_Det, group = interaction(Segmento_Det, Año))) +
  geom_point() +
  geom_line() + # Añadido para conectar los puntos
  facet_wrap(~ Año, ncol = 1, scales = "free_y") + # Usar facet_wrap para separar por Año
  labs(title = "Relación entre Ventas Mensuales de Agua y Refrescos en los Últimos 4 Años",
       x = "Número de Mes",
       y = "Ventas") +
  theme_minimal()

7.

¿A cuánto ascienden las ventas esperadas para el 2020 en la Coca Cola de 500 ml NR Vidrio?

ventas_coca_vidirio <- df7 %>%
  filter(Marca == "Coca-Cola" & Presentacion =="500 ml NR Vidrio") %>%
  group_by(Año, Número_de_Mes) %>%
  summarise(Ventas_Totales = sum(Ventas)) %>%
  filter(Ventas_Totales !=0) %>% #para quitar los renglones con 0
  filter(Año !=2016)
## `summarise()` has grouped output by 'Año'. You can override using the `.groups`
## argument.
ts <- ts(data=ventas_coca_vidirio$Ventas_Totales, start=c(2016,1), frequency=12)

arima <- auto.arima(ts, D=1)
arima
## Series: ts 
## ARIMA(1,1,0)(0,1,0)[12] 
## 
## Coefficients:
##           ar1
##       -0.4027
## s.e.   0.2049
## 
## sigma^2 = 57408996:  log likelihood = -196.26
## AIC=396.52   AICc=397.27   BIC=398.41
summary(arima)
## Series: ts 
## ARIMA(1,1,0)(0,1,0)[12] 
## 
## Coefficients:
##           ar1
##       -0.4027
## s.e.   0.2049
## 
## sigma^2 = 57408996:  log likelihood = -196.26
## AIC=396.52   AICc=397.27   BIC=398.41
## 
## Training set error measures:
##                    ME     RMSE      MAE      MPE     MAPE      MASE        ACF1
## Training set 949.7101 5682.654 3153.896 1.188503 7.536496 0.3461426 -0.09295723
pronostico <- forecast(arima, level=95, h=16)
pronostico
##          Point Forecast    Lo 95     Hi 95
## Sep 2018       59483.15 44632.75  74333.55
## Oct 2018       54715.84 37417.93  72013.74
## Nov 2018       53121.36 32471.41  73771.32
## Dec 2018       61192.28 38112.18  84272.37
## Jan 2019       65066.26 39626.84  90505.68
## Feb 2019       72468.65 44931.45 100005.85
## Mar 2019       77199.62 47690.81 106708.43
## Apr 2019       60376.06 29027.99  91724.14
## May 2019       92662.27 59573.73 125750.81
## Jun 2019       81915.99 47175.33 116656.65
## Jul 2019       80265.70 43947.52 116583.89
## Aug 2019       81752.82 43923.02 119582.62
## Sep 2019       83678.92 38092.03 129265.82
## Oct 2019       78911.63 29345.94 128477.32
## Nov 2019       77317.15 23142.80 131491.50
## Dec 2019       85388.07 27323.47 143452.66
plot(pronostico, main="Pronóstico de Ventas para el 2020 de Coca Cola 500 ml NR Vidrio", xlab="Año", ylab="Ventas (QTY)")

Respuesta: Las ventas esperadas de Coca-Cola de 500 ml NR Vidrio para 2020 oscilan mensualmente entre 45,000 y 65,000 unidades, con una confiabilidad del 95%

Extra

ventas_mensuales <- df7 %>%
  group_by(Año, Mes, Segmento_Det) %>%
  summarise(Ventas_Totales = sum(Ventas), .groups = 'drop')

# Separar las ventas de agua y refrescos en dos dataframes 
ventas_agua <- ventas_mensuales %>% filter(Segmento_Det %in% c("Agua Mineral", "Agua Purificada"))
ventas_refrescos <- ventas_mensuales %>% filter(Segmento_Det %in% c("Colas Light", "Colas Regular"))

correlacion <- cor(ventas_agua$Ventas_Totales, ventas_refrescos$Ventas_Totales)

ggplot() +
  geom_line(data = ventas_agua, aes(x = interaction(Año, Mes), y = Ventas_Totales, group = 1, colour = "Agua")) +
  geom_line(data = ventas_refrescos, aes(x = interaction(Año, Mes), y = Ventas_Totales, group = 1, colour = "Refrescos")) +
  labs(title = "Comparación de Ventas Mensuales: Agua vs. Refrescos",
       x = "Tiempo",
       y = "Ventas Totales") +
  theme_minimal() +
  scale_colour_manual(values = c("Agua" = "blue", "Refrescos" = "red"))

print(correlacion)
## [1] 0.9495664
LS0tCnRpdGxlOiAiQXJjYSBDb250aW5lbnRhbCBQcm95ZWN0byBTaWdsbyBYWEkiCmF1dGhvcjogIkFuZ2llIFplcsOzbiIKZGF0ZTogIjIwMjQtMDMtMjAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFCiAgICB0aGVtZTogY29zbW8KLS0tCgohW10oL1VzZXJzL2FuZ2llemVyb24vRG9jdW1lbnRzL1IgdGhpbmdzL0FyY2FfQ29udGluZW50YWxfbG9nby5zdmcucG5nKQoKIyBJbnN0YWxhciBwYXF1ZXRlcyB5IGxsYW1hciBhIGxpYnJlcmlhcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpICNoYWNlciBncsOhZmljb3MKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShyZWFkeGwpICNsZWVyIGVsIGV4Y2VsCmxpYnJhcnkoZm9yZWNhc3QpICNnZW5lcmFyIHNlcmllcyBkZSB0aWVtcG8KYGBgCgojIDxTcGFuIHN0eWxlPSJjb2xvcjogcmVkOyI+QWN0aXZpZGFkIEluZGl2aWR1YWwgMjwvc3Bhbj4KCiMjIEltcG9ydGFyIGxhIGJhc2UgZGUgZGF0b3MKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGYgPC0gcmVhZF9leGNlbCgnL1VzZXJzL2FuZ2llemVyb24vRG9jdW1lbnRzL1IgdGhpbmdzL0RhdG9zIEFyY2EgQ29udGluZW50YWwgT3JpZ2luYWwueGxzeCcpCmRmCmBgYAojIyBSZXZpc2FyIGxhIGVzdHJ1Y3R1cmEgZGUgZGF0b3MKYGBge3J9CnN0cihkZikKYGBgCiMjIFJldmlzYXIgTkFzIGVuIGxhIGVsIGRmCmBgYHtyfQojQ3VhbnRvcyBOQXMgdGVuZ28gZW4gbGEgYmFzZSBkZSBkYXRvcz8Kc3VtKGlzLm5hKGRmKSkKYGBgCgpgYGB7cn0KI2N1YW50b3MgTkFzIHRlbmdvIHBvciB2YXJpYWJsZQpzYXBwbHkoZGYsIGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpCmBgYApgYGB7cn0KI09wY2lvbiAxLiBlbGltaW5hciBOQXMKIyBkZjEgPC0gbmEub21pdChkZikKCiNPcGNpb24gMi4gUmVlbXBsYXphciBjb24gY2Vyb3MKZGYxIDwtIGRmCmRmMVtpcy5uYShkZjEpXSA8LSAwCgojT3BjaW9uIDMuIFJlZWVtcGxhemFyIE5BcyBjb24gcHJvbWVkaW8KI2RmMTwtZGYKI2RmMSRFbmVyb1tpcy5uYShkZjEkZW5lcm8pXSA8LSBtZWFuKGRmMSRlbmVybywgbmEucm09VFJVRSkKYGBgCgojIyBEZXRlY3RhciB2YWxvcmVzIGF0w61waWNvcwpgYGB7cn0KYm94cGxvdChkZjEkRW5lcm8pCmBgYApgYGB7cn0KI0VsaW1pbmFyIHJlbWdsb24gZGUgbG9zIHRvdGFsZXMKZGYxIDwtIGRmMVtkZjEkRW5lcm8gPDYwMDAsXQpgYGAKCgojIyBGdW5jaW9uZXMgZGVsIFBhcXVldGUgRHBseXIKYGBge3J9CiMgQWRlY3VhciBub21icmVzIGNvbiBnc3ViCm5hbWVzKGRmMSkgPC0gZ3N1YigiICIsIl8iLCBuYW1lcyAoZGYxKSkKCiMgTXVlc3RyYSBsYXMgdmVudGFzIGRlIEVuZXJvIGEgSnVuaW8gcG9yIENFREk6CmRmMiA8LSBzZWxlY3QoZGYxLGMoQ0VESSxFbmVybzpKdW5pbykpCgojIE11ZXN0cmEgbG9zIG1vdmltaWVudG9zIHBvciBDZWRpIHkgdGFtYcOxbyBkZSB0aWVuZGEgZ3JhbmRlCmRmMyA8LSBkZjEgJT4lIGZpbHRlcihUYW1hw7FvX0N0ZV9JbmR1c3RyaWEgPT0gIkdyYW5kZSIpCgojIE9yZGVuYSBsYSBiYXNlIGRlIGRhdG9zIHBvciBDRURJLCBwb3IgbWFyY2EgeSBwb3IgcHJlc2VudGFjacOzbgpkZjQgPC0gZGYxICU+JSBhcnJhbmdlKENFREksTWFyY2EsUHJlc2VudGFjaW9uKQoKIyBBZ3JlZ2EgdW4gY2FtcG8gY2FsY3VsYWRvIGNvbiBsYXMgdmVudGFzIGRlbCBwcmltZXIgc2VtZXN0cmUgeSBtdWVzdHJhIGxhcyB2ZW50YXMgZGVsIHByaW1lciBzZW1lc3RyZSBwb3IgbWFyY2EuCmRmNSA8LSBkZjEgJT4lIAogIG11dGF0ZShWZW50YXNfU2VtMSA9IEVuZXJvICsgRmVicmVybyArIE1hcnpvICsgQWJyaWwgKyBNYXlvICsgSnVuaW8pCgp2ZW50YXNfc2VtMV9wb3JfbWFyY2EgPC0gZGY1ICU+JSAKICBncm91cF9ieShNYXJjYSkgJT4lIAogIHN1bW1hcmlzZShWZW50YXNfU2VtMT0gc3VtKFZlbnRhc19TZW0xKSkKCiMgT2J0w6luIGxhIG1lZGlhIGRlIGxhcyB2ZW50YXMgZGVsIHByaW1lciBzZW1lc3RyZSBhZ3J1cGFkbyBwb3IgbWFyY2EsIHByZXNlbnRhY2nDs24geSB0YW1hw7FvLgpkZjYgPC0gZGY1ICU+JQogIGdyb3VwX2J5KE1hcmNhLFByZXNlbnRhY2lvbixUYW1hw7FvKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX1NlbTE9IG1lYW4oVmVudGFzX1NlbTEpKQoKI0NhbGN1bGFyIG1lZGlkYXMgZGUgdGVuZGVuY2lhIGNlbnRyYWwKc3VtbWFyeShkZjEpCgojQ29sYXBzYXIgbWVzZXMgZW4gdW5hIGNvbWx1bW5hCmRmNyA8LSBnYXRoZXIoZGYxLCBNZXMsIFZlbnRhcywgRW5lcm86RGljaWVtYnJlKQpkZjcKYGBgCiMgPFNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5BY3RpdmlkYWQgQ29sYWJvcmF0aXZhIDI8L3NwYW4+CkFuZ2llIFplcm9uIEEwMDgzNDA2MApBbnRvbmlvIEt1cmkgQTAxNzIyMDE2CklzYWFjIFBlcmV6IEEwMTI1MjkyMwoKYGBge3J9CiMjIE11ZXN0cmEgbGFzIHZlbnRhcyBhbnVhbGVzIHRvdGFsZXMgcG9yIHRhbWHDsW8uLi4gCiNTZSBub3RhIHF1ZSBlbCB0YW1hw7FvIGZhbWlsaWFyIGVzIGVsIG3DoXMgdmVuZGlkbyBjb24gdW4gdG90YWwgZGUgdmVudGEgZGUgMTU3ODcxODE6CmRmN190YXJlYSA8LSBzZWxlY3QoZGYxLGMoVGFtYcOxbyxFbmVybzpEaWNpZW1icmUpKQoKZGY3X3RhcmVhJHRvdGFsID0gcm93U3VtcyhkZjdfdGFyZWFbLCBjKCJFbmVybyIsICJGZWJyZXJvIiwgIk1hcnpvIiwgIkFicmlsIiwgIk1heW8iLCAiSnVuaW8iLCAiSnVsaW8iLCAiQWdvc3RvIiwgIlNlcHRpZW1icmUiLCAiT2N0dWJyZSIsICJOb3ZpZW1icmUiLCAiRGljaWVtYnJlIildKQoKZGY3X2FncnVwYWRvID0gZGY3X3RhcmVhICU+JQogIGdyb3VwX2J5KFRhbWHDsW8pICU+JQogIHN1bW1hcml6ZShUb3RhbF9HcnVwbyA9IHN1bSh0b3RhbCkpCgpwcmludChkZjdfYWdydXBhZG8pCmBgYAoKYGBge3J9CiMjIE11ZXN0cmEgbG9zIG1vdmltaWVudG9zIHBvciBzdWIgdGVycml0b3JpbyBlbiBlc3BlY2lmaWNvIEJlbGVuZXMuLi4gCiNTZSBpZGVudGlmaWNvIHF1ZSBlbiBlbCBzdWIgdGVycml0b3JpbyBkZSBCZWxlbmVzIGh1Ym8gdW4gdG90YWwgZGUgdmVudGEgZGUgOTE3NjI3OSAKZGY4IDwtIGRmMSAlPiUgZmlsdGVyKFN1Yl9UZXJyaXRvcmlvID09ICJCZWxlbmVzIikKCmRmOCR0b3RhbCA9IHJvd1N1bXMoZGY4WywgYygiRW5lcm8iLCAiRmVicmVybyIsICJNYXJ6byIsICJBYnJpbCIsICJNYXlvIiwgIkp1bmlvIiwgIkp1bGlvIiwgIkFnb3N0byIsICJTZXB0aWVtYnJlIiwgIk9jdHVicmUiLCAiTm92aWVtYnJlIiwgIkRpY2llbWJyZSIpXSkKCmRmOF9hZ3J1cGFkbyA9IGRmOCAlPiUKICBncm91cF9ieShTdWJfVGVycml0b3JpbykgJT4lCiAgc3VtbWFyaXplKFRvdGFsX0dydXBvID0gc3VtKHRvdGFsKSkKCnByaW50KGRmOF9hZ3J1cGFkbykKYGBgCgpgYGB7cn0KIyMgIGJhc2UgZGUgZGF0b3Mgb3JkZW5hZGEgcG9yIFJldG9ybmFibGUgbyBubyByZXRvbmFibGUsIHBvciBtYXJjYSB5IHBvciBwcmVzZW50YWNpw7NuLi4uIAojU2Ugbm90w7MgcXVlIGxvcyByZWZyZXNjb3MgcmV0b3JuYWJsZXMgdGllbmVuIG1heW9yIGZyZWN1ZW5jaWEgZGUgdmVudGEsIHlhIHF1ZSBvY3VwYW4gbG9zIHByaW1lcm9zIDUgbHVnYXJlcwpkZjkgPC0gZGYxICU+JSBhcnJhbmdlKFJldG9ybmFibGVfTlIsTWFyY2EsUHJlc2VudGFjaW9uKQoKZGY5JHRvdGFsID0gcm93U3VtcyhkZjlbLCBjKCJFbmVybyIsICJGZWJyZXJvIiwgIk1hcnpvIiwgIkFicmlsIiwgIk1heW8iLCAiSnVuaW8iLCAiSnVsaW8iLCAiQWdvc3RvIiwgIlNlcHRpZW1icmUiLCAiT2N0dWJyZSIsICJOb3ZpZW1icmUiLCAiRGljaWVtYnJlIildKQoKCiMjIENhbXBvIGNhbGN1bGFkbyBjb24gbGFzIHZlbnRhcyBhbnVhbGVzIHkgbXVlc3RyYSBsYXMgICAgICAgICAgICAgICAgICAgdmVudGFzIGFudWFsZXMgcG9yIHByZXNlbnRhY2nDs24uLi4gCiNTZSBpZGVudGlmaWPDsyBxdWUgbGEgcHJlc2VudGFjacOzbiBkZSAyLjUgTHRzLiBSZXQgUGV0IGZ1ZSBsYSBtw6FzIGV4aXRvc2EgY29uIHVuIHRvdGFsIGRlIHZlbnRhIGRlIDU4Mjk5NDYKZGYxMCA8LSBkZjEgJT4lIAogIG11dGF0ZShWZW50YXNfQW51YWxlcyA9IEVuZXJvICsgRmVicmVybyArIE1hcnpvICsgQWJyaWwgKyBNYXlvICsgSnVuaW8gKyBKdWxpbyArIEFnb3N0byArIFNlcHRpZW1icmUgKyBPY3R1YnJlICsgTm92aWVtYnJlICsgRGljaWVtYnJlKQoKdmVudGFzX2FudWFsZXNfcG9yX3ByZXNlbnRhY2lvbiA8LSBkZjEwICU+JSAKICBncm91cF9ieShQcmVzZW50YWNpb24pICU+JSAKICBzdW1tYXJpc2UoVmVudGFzX0FudWFsZXM9IHN1bShWZW50YXNfQW51YWxlcykpCgojIyBNZWRpYSBkZSBsYXMgdmVudGFzIGRlbCBwcmltZXIgc2VtZXN0cmUgYWdydXBhZG8gcG9yIHByZXNlbnRhY2nDs24geSB0YW1hw7FvLi4uIAojU2UgaWRlbnRpZmljw7MgcXVlIGVuIHByb21lZGlvIGxhIHByZXNlbnRhY2nDs24gZGUgMi41IEx0cy4gUmV0IFBldCBzZSB2ZW5kacOzIGVuIHByb21lZGlvIDgxNC4xMjQ1NjM2CgpkZjExIDwtIGRmMTAgJT4lCiAgZ3JvdXBfYnkoUHJlc2VudGFjaW9uLFRhbWHDsW8pICU+JQogIHN1bW1hcmlzZShWZW50YXNfQW51YWxlcz0gbWVhbihWZW50YXNfQW51YWxlcykpCmBgYAoKCiMgPFNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5BY3RpdmlkYWQgSW5kaXZpZHVhbCAzPC9zcGFuPgpgYGB7cn0KI0FncmVnYXIgdW5hIGNvbHVtbmEgY29uIGVsIG7Dum1lcm8gZGVsIG1lcwptZXNlcyA8LSBjKCJFbmVybyI9IjAxIiwgIkZlYnJlcm8iPSIwMiIsICJNYXJ6byI9IjAzIiwgIkFicmlsIj0iMDQiLCAiTWF5byI9IjA1IiwgIkp1bmlvIj0iMDYiLCAiSnVsaW8iPSIwNyIsICJBZ29zdG8iPSIwOCIsICJTZXB0aWVtYnJlIj0iMDkiLCAiT2N0dWJyZSI9IjEwIiwgIk5vdmllbWJyZSI9IjExIiwgIkRpY2llbWJyZSI9IjEyIikKCmRmNyROw7ptZXJvX2RlX01lcyA8LSBtZXNlc1tkZjckTWVzXQoKI0dyw6FmaWNhIHByb21lZGlvIGRlIHZlbnRhcyBwb3IgbWVzIHkgYcOxMAoKdmVudGFzX3RvdGFsZXMgPC0gZGY3ICU+JQogIGdyb3VwX2J5KEHDsW8sIE7Dum1lcm9fZGVfTWVzKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX1RvdGFsZXMgPSBzdW0oVmVudGFzKSkgJT4lCiAgYXJyYW5nZShOw7ptZXJvX2RlX01lcykKCmdncGxvdCh2ZW50YXNfdG90YWxlcywgYWVzKHg9TsO6bWVyb19kZV9NZXMsIHk9VmVudGFzX1RvdGFsZXMsIGdyb3VwPUHDsW8sIGNvbG9yPWFzLmZhY3RvcihBw7FvKSkpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSJNZXMiLCB5PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIGNvbG9yPSAiQcOxbyIpCmBgYAoKCiMgPFNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5BY3RpdmlkYWQgQ29sYWJvcmF0aXZhIDM8L3NwYW4+CiMjIFZlbnRhcyBUb3RhbGVzIHBvciBNYXJjYQpgYGB7cn0KIyBTZSBpZGVudGlmaWPDsyBxdWUgbGFzIG1hcmNhcyBjb24gbWF5b3IgY2FudGlkYWQgZGUgdmVudGFzIGZ1ZXJvbiBDb2NhIENvbGEsIEFndWEgcHVyaWZpY2FkYSBjaWVsLCBDb2NhIENvbGEgTGlnaHQsIFNwcml0ZQoKdmVudGFzX3RvdGFsZXNfcG9yX21hcmNhIDwtIGRmNyAlPiUKICBncm91cF9ieShNYXJjYSkgJT4lCiAgc3VtbWFyaXNlKHZlbnRhc190b3RhbGVzX3Bvcl9tYXJjYSA9IHN1bShWZW50YXMpKSAlPiUKICBhcnJhbmdlKHZlbnRhc190b3RhbGVzX3Bvcl9tYXJjYSkKCmdncGxvdCh2ZW50YXNfdG90YWxlc19wb3JfbWFyY2EsIGFlcyh4PXZlbnRhc190b3RhbGVzX3Bvcl9tYXJjYSwgeT1NYXJjYSwgZ3JvdXA9TWFyY2EsIGNvbG9yPWFzLmZhY3RvcihNYXJjYSkpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIHk9Ik1hcmNhIiwgY29sb3I9ICJNYXJjYSIpCmBgYAoKIyMgVmVudGFzIFRvdGFsZXMgcG9yIFRhbWHDsW8KYGBge3J9CiMgU2UgaWRlbnRpZmljw7MgcXVlIGVsIHRhbWHDsW8gbWFzIHZlbmRpZG8gZXMgZWwgZmFtaWxpYXIgcG9yIG11Y2hvCgp2ZW50YXNfdG90YWxlc19wb3JfdGFtYcOxbyA8LSBkZjcgJT4lCiAgZ3JvdXBfYnkoVGFtYcOxbykgJT4lCiAgc3VtbWFyaXNlKHZlbnRhc190b3RhbGVzX3Bvcl90YW1hw7FvID0gc3VtKFZlbnRhcykpICU+JQogIGFycmFuZ2UodmVudGFzX3RvdGFsZXNfcG9yX3RhbWHDsW8pCgpnZ3Bsb3QodmVudGFzX3RvdGFsZXNfcG9yX3RhbWHDsW8sIGFlcyh4PVRhbWHDsW8sIHk9dmVudGFzX3RvdGFsZXNfcG9yX3RhbWHDsW8sIGdyb3VwPVRhbWHDsW8sIGNvbG9yPWFzLmZhY3RvcihUYW1hw7FvKSkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHg9IlRhbWHDsW8iLCB5PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIGNvbG9yPSAiVGFtYcOxbyIpCgpgYGAKCiMjIFZlbnRhcyB0b3RhbGVzIHBvciBTdWItVGVycml0b3JpbwpgYGB7cn0KIyBTZSBpZGVudGlmaWPDsyBxdWUgZWwgb3JkZW4gZGUgbWF5b3IgYSBtZW5vciB2ZW50YSBwb3IgdGVycml0b3JpbyBlcyBUb2x1cXVpbGxhLCBCZWxlbmVzLCBIdWVudGl0w6FuCgp2ZW50YXNfdG90YWxlc19wb3Jfc3VidCA8LSBkZjcgJT4lCiAgZ3JvdXBfYnkoU3ViX1RlcnJpdG9yaW8pICU+JQogIHN1bW1hcmlzZSh2ZW50YXNfdG90YWxlc19wb3Jfc3VidCA9IHN1bShWZW50YXMpKSAlPiUKICBhcnJhbmdlKHZlbnRhc190b3RhbGVzX3Bvcl9zdWJ0KQoKZ2dwbG90KHZlbnRhc190b3RhbGVzX3Bvcl9zdWJ0LCBhZXMoeD1TdWJfVGVycml0b3JpbywgeT12ZW50YXNfdG90YWxlc19wb3Jfc3VidCwgZ3JvdXA9U3ViX1RlcnJpdG9yaW8sIGNvbG9yPWFzLmZhY3RvcihTdWJfVGVycml0b3JpbykpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSJTdWJfVGVycml0b3JpbyIsIHk9IlZlbnRhcyBUb3RhbGVzIChRdHkpIiwgY29sb3I9ICJTdWJfVGVycml0b3JpbyIpCmBgYAogCiMjIFZlbnRhcyB0b3RhbGVzIHBvciBBw7FvCmBgYHtyfQojIFNlIGlkZW50aWZpY8OzIHF1ZSBlbCBhw7FvIGNvbiBtYXlvciBjYW50aWRhZCBkZSB2ZW50YXMgZnVlIGVsIDIwMTkgc2VndWlkbyBwb3IgZWwgMjAxNywgMjAxOCB5IDIwMTYKCnZlbnRhc190b3RhbGVzX3Bvcl9hw7FvIDwtIGRmNyU+JQogIGdyb3VwX2J5KEHDsW8pICU+JQogIHN1bW1hcmlzZSh2ZW50YXNfdG90YWxlc19wb3JfYcOxbyA9IHN1bShWZW50YXMpKSAlPiUKICBhcnJhbmdlKHZlbnRhc190b3RhbGVzX3Bvcl9hw7FvKQoKZ2dwbG90KHZlbnRhc190b3RhbGVzX3Bvcl9hw7FvLCBhZXMoeD1Bw7FvLCB5PXZlbnRhc190b3RhbGVzX3Bvcl9hw7FvLCBncm91cD1Bw7FvLCBjb2xvcj1hcy5mYWN0b3IoQcOxbykpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAid2hpdGUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHg9IkHDsW8iLCB5PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIGNvbG9yPSAiQcOxbyIpCmBgYAoKIyMgVmVudGFzIFRvdGFsZXMgcG9yIFJldG9ybmFibGUgeSBObyBSZXRvcm5hYmxlCmBgYHtyfQojIFNlIGlkZW50aWZpY8OzIHF1ZSBsYSBjYW50aWRhZCBkZSB2ZW50YXMgZGUgbG9zIHByb2R1Y3RvcyByZXRvcm5hYmxlcyB5IG5vIHJldG9ybmFibGVzIGVzIG11eSBzaW1pbGFyLCBzaW4gZW1iYXJnbyBzZSBub3RhIHVuYSBsaWdlcmEgZGlmZXJlbmNpYSBhIGZhdm9yIGRlIGxvIHJldG9ybmFibGUKCnZlbnRhc190b3RhbGVzX3Bvcl9yZXRvbm9yZXQgPC0gZGY3ICU+JQogIGdyb3VwX2J5KFJldG9ybmFibGVfTlIpICU+JQogIHN1bW1hcmlzZSh2ZW50YXNfdG90YWxlc19wb3JfcmV0b25vcmV0ID0gc3VtKFZlbnRhcykpICU+JQogIGFycmFuZ2UodmVudGFzX3RvdGFsZXNfcG9yX3JldG9ub3JldCkKCmdncGxvdCh2ZW50YXNfdG90YWxlc19wb3JfcmV0b25vcmV0LCBhZXMoeD1SZXRvcm5hYmxlX05SLCB5PXZlbnRhc190b3RhbGVzX3Bvcl9yZXRvbm9yZXQsIGdyb3VwPVJldG9ybmFibGVfTlIsIGNvbG9yPWFzLmZhY3RvcihSZXRvcm5hYmxlX05SKSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJ0cmFuc3BhcmVudCIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoeD0iUmV0b3JuYWJsZV9OUiIsIHk9IlZlbnRhcyBUb3RhbGVzIChRdHkpIiwgY29sb3I9ICJSZXRvcm5hYmxlX05SIikKYGBgCgoKCiMgPFNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5BY3RpdmlkYWQgSW5kaXZpZHVhbCA0PC9zcGFuPgpgYGB7cn0KI0VsYWJvcmFyIHJlZ3Jlc2nDs24gbGluZWFsCgp2ZW50YXNfNDU2NyA8LSBkZjcgJT4lCiAgZmlsdGVyKENsaWVudGUgPT0gIjQ1NjciKSAlPiUKICBncm91cF9ieShBw7FvKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX3RvdGFsZXMgPSBzdW0oVmVudGFzKSkgJT4lCiAgZmlsdGVyKFZlbnRhc190b3RhbGVzICE9MCkgI3BhcmEgcXVpdGFyIGxvcyByZW5nbG9uZXMgY29uIDAKCiN2ZW50YXNfbWF5b3JlcyRTZWN1ZW5jaWEgPC0gMTpucm93KHZlbnRhc19tYXlvcmVzKSAjIGVzIHVuYSBzZWN1ZW5jaWEgcG9yIHNpIGxvIG9jdXBhbW9zIGVuIGFsZ28gbWFzCiNjdWFuZG8gaGFnbyByZWdyZXNvbiBvY3VwbyBxdWUgZWwgZWplIHggc2VhIHVuIHJ1bWVybywgYXNpIHF1ZSBzZSBjYW1iaWEgYSB1bmEgc2VjdWVuY2lhIGRlIG1lc2VzIHBhcmEgcXVlIG5vIHNlIGNvbmZ1bmRhIGFsIGdyYWZpY2FybG8KCmdncGxvdCh2ZW50YXNfNDU2NywgYWVzKHg9QcOxbywgeT1WZW50YXNfdG90YWxlcykpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeD0iQcOxbyIsIHk9IlZlbnRhcyBUb3RhbGVzIChRdHkpIiwgdGl0bGUgPSAiVmVudGFzIHRvdGFsZXMgZGVsIGNsaWVudGUgNDU2NyIpCgpyZWdyZXNpb24gPC0gbG0oVmVudGFzX3RvdGFsZXMgfiBBw7FvLCBkYXRhPXZlbnRhc180NTY3KQpzdW1tYXJ5KHJlZ3Jlc2lvbikKCiNFY3VhY2lvbgojeT00ODkxODY3NyArICggLTI0MTc0ICkKCiNSIGN1YWRyYWRhIGFqdXN0YWRhCiMwLjc2NSAKCmRhdG9zIDwtIGRhdGEuZnJhbWUoQcOxbz0yMDIwOjIwMjUpCnByZWRpY2Npb24gPC1wcmVkaWN0KHJlZ3Jlc2lvbixkYXRvcykKcHJlZGljY2lvbgoKdmVudGFzXzQ1NjckVGlwb19kZV9EYXRvIDwtICJEYXRvcyBSZWFsZXMiCmRhdG9zJFZlbnRhc190b3RhbGVzIDwtIHByZWRpY2Npb24KZGF0b3MkVGlwb19kZV9EYXRvIDwtICJQcmVkaWNjaW9uIgoKZGF0b3NfY29tYmluYWRvcyA8LSByYmluZCh2ZW50YXNfNDU2NywgZGF0b3MpCgpnZ3Bsb3QoZGF0b3NfY29tYmluYWRvcywgYWVzKHg9QcOxbywgeT1WZW50YXNfdG90YWxlcywgY29sb3I9VGlwb19kZV9EYXRvKSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSJBw7FvIiwgeT0iVmVudGFzIFRvdGFsZXMgKFF0eSkiLCB0aXRsZSA9ICJQcm9uw7NzdGljbyBhIDUgYcOxb3MgZGUgdmVudGFzIGRlbCBjbGllbnRlIDQ1NjciKQoKYGBgCioqQW7DoWxpc2lzOiBTZWfDum4gZXN0ZSBwcm9uw7NzdGljbyBhIDUgYcOxb3MsIGxhIHZlbnRhcyBkZWwgY2xpZW50ZSA0NTY3IHZhbiBhIGRlY3JlY2VyKioKCiMgPFNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5BY3RpdmlkYWQgQ29sYWJvcmF0aXZhIDQ8L3NwYW4+CkFuZ2llIFplcm9uIEEwMDgzNDA2MApBbnRvbmlvIEt1cmkgQTAxNzIyMDE2CklzYWFjIFBlcmV6IEEwMTI1MjkyMwpgYGB7cn0KI8K/QSBjdcOhbnRvIGFzY2llbmRlbiBsYXMgdmVudGFzIGVzcGVyYWRhcyBwYXJhIGVsIDIwMjAgZW4gbGEgQ29jYSBDb2xhIGRlIDUwMCBtbCBOUiBWaWRyaW8/Cgp2ZW50YXNfZXNwZXJhZGFzIDwtIGRmNyAlPiUKICBmaWx0ZXIoTWFyY2EgPT0gIkNvY2EtQ29sYSIgJiBQcmVzZW50YWNpb24gPT0iNTAwIG1sIE5SIFZpZHJpbyIpICU+JQogIGdyb3VwX2J5KEHDsW8pICU+JQogIHN1bW1hcmlzZShWZW50YXNfVG90YWxlcyA9IHN1bShWZW50YXMpKSAlPiUKICBmaWx0ZXIoVmVudGFzX1RvdGFsZXMgIT0wKSAlPiUgI3BhcmEgcXVpdGFyIGxvcyByZW5nbG9uZXMgY29uIDAKICBmaWx0ZXIoQcOxbyAhPTIwMTYpCgpnZ3Bsb3QodmVudGFzX2VzcGVyYWRhcywgYWVzKHg9QcOxbywgeT1WZW50YXNfVG90YWxlcykpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeD0iQcOxbyIsIHk9IlZlbnRhcyBUb3RhbGVzIChRdHkpIiwgdGl0bGUgPSAiVmVudGFzIEFudWFsZXMgZGUgQ29jYSBDb2xhIikKCnJlZ3Jlc2lvbjEgPC0gbG0oVmVudGFzX1RvdGFsZXMgfiBBw7FvLCBkYXRhPXZlbnRhc19lc3BlcmFkYXMpCnN1bW1hcnkocmVncmVzaW9uMSkKCiNFY3VhY2lvbgojeT0gLTUzMDM0MDQgKyAgMjgzMwoKI1IgY3VhZHJhZGEgYWp1c3RhZGEKIyAtMC4wNTczOCAKCmRhdG9zIDwtIGRhdGEuZnJhbWUoQcOxbz0yMDIwOjIwMjUpCnByZWRpY2Npb24gPC1wcmVkaWN0KHJlZ3Jlc2lvbjEsZGF0b3MpCnByZWRpY2Npb24KCnZlbnRhc19lc3BlcmFkYXMkVGlwb19kZV9EYXRvIDwtICJEYXRvcyBSZWFsZXMiCmRhdG9zJFZlbnRhc19Ub3RhbGVzIDwtIHByZWRpY2Npb24KZGF0b3MkVGlwb19kZV9EYXRvIDwtICJQcmVkaWNjaW9uIgoKZGF0b3NfY29tYmluYWRvcyA8LSByYmluZCh2ZW50YXNfZXNwZXJhZGFzLCBkYXRvcykKCmdncGxvdChkYXRvc19jb21iaW5hZG9zLCBhZXMoeD1Bw7FvLCB5PVZlbnRhc19Ub3RhbGVzLCBjb2xvcj1UaXBvX2RlX0RhdG8pKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHg9IkHDsW8iLCB5PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIHRpdGxlID0gIlByb27Ds3N0aWNvIGRlIHZlbnRhcyBlc3BlcmFkYXMgcGFyYSBlbCAyMDIwIiwgc3VidGl0bGUgPSAiQ29jYSBDb2xhIGRlIDUwMCBtbCBOUiBWaWRyaW8iKQpgYGAKKipBbsOhbGlzaXM6IFBhcmEgZWwgYcOxbyAyMDIwLCBzZSBlc3BlcmEgcXVlIGxhcyB2ZW50YXMgZGUgQ09DQSBDT0xBIGRlIDUwMCBtbCBOUiBWaWRyaW8gdGVuZGRyYSB2ZW50YXMgZXNwZXJhZGFzIGRlIDQxOSwwMDAqKgoKYGBge3J9CiNWZW50YXMgdG90YWxlcyBkZWwgY2xpZW50ZSA2NjI2Cgp2ZW50YXNfNjYyNiA8LSBkZjcgJT4lCiAgZmlsdGVyKENsaWVudGUgPT0gIjY2MjYiKSAlPiUKICBncm91cF9ieShBw7FvKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX3RvdGFsZXMgPSBzdW0oVmVudGFzKSkgJT4lCiAgZmlsdGVyKFZlbnRhc190b3RhbGVzICE9MCkgI3BhcmEgcXVpdGFyIGxvcyByZW5nbG9uZXMgY29uIDAKCiN2ZW50YXNfbWF5b3JlcyRTZWN1ZW5jaWEgPC0gMTpucm93KHZlbnRhc19tYXlvcmVzKSAjIGVzIHVuYSBzZWN1ZW5jaWEgcG9yIHNpIGxvIG9jdXBhbW9zIGVuIGFsZ28gbWFzCiNjdWFuZG8gaGFnbyByZWdyZXNvbiBvY3VwbyBxdWUgZWwgZWplIHggc2VhIHVuIHJ1bWVybywgYXNpIHF1ZSBzZSBjYW1iaWEgYSB1bmEgc2VjdWVuY2lhIGRlIG1lc2VzIHBhcmEgcXVlIG5vIHNlIGNvbmZ1bmRhIGFsIGdyYWZpY2FybG8KCmdncGxvdCh2ZW50YXNfNjYyNiwgYWVzKHg9QcOxbywgeT1WZW50YXNfdG90YWxlcykpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeD0iQcOxbyIsIHk9IlZlbnRhcyBUb3RhbGVzIChRdHkpIiwgdGl0bGUgPSAiVmVudGFzIHRvdGFsZXMgZGVsIGNsaWVudGUgMDk0OCIpCgpyZWdyZXNpb24gPC0gbG0oVmVudGFzX3RvdGFsZXMgfiBBw7FvLCBkYXRhPXZlbnRhc182NjI2KQpzdW1tYXJ5KHJlZ3Jlc2lvbikKCiNFY3VhY2lvbgojeT0gNTUyMDgxOTUgKyAoICAtMjczMTYgKQojIGVzdGUgZXMgZWwgaW50ZXJjZXB0byAgZXN0ZSBlcyBsYSBjb3JyZWxhY2lvbiAoZW4gZXN0ZSBjYXNvIG5lZ2F0aXZhKQoKI1IgY3VhZHJhZGEgYWp1c3RhZGEKIyAwLjkzODQgIAoKZGF0b3MgPC0gZGF0YS5mcmFtZShBw7FvPTIwMjA6MjAyNSkKcHJlZGljY2lvbiA8LXByZWRpY3QocmVncmVzaW9uLGRhdG9zKQpwcmVkaWNjaW9uCgp2ZW50YXNfNjYyNiRUaXBvX2RlX0RhdG8gPC0gIkRhdG9zIFJlYWxlcyIKZGF0b3MkVmVudGFzX3RvdGFsZXMgPC0gcHJlZGljY2lvbgpkYXRvcyRUaXBvX2RlX0RhdG8gPC0gIlByZWRpY2Npb24iCgpkYXRvc19jb21iaW5hZG9zIDwtIHJiaW5kKHZlbnRhc182NjI2LCBkYXRvcykKCmdncGxvdChkYXRvc19jb21iaW5hZG9zLCBhZXMoeD1Bw7FvLCB5PVZlbnRhc190b3RhbGVzLCBjb2xvcj1UaXBvX2RlX0RhdG8pKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHg9IkHDsW8iLCB5PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIHRpdGxlID0gIlByb27Ds3N0aWNvIGEgNSBhw7FvcyBkZSB2ZW50YXMgZGVsIGNsaWVudGUgNjYyNiIpCmBgYAoqKkFuw6FsaXNpczogTGFzIHZlbnRhcyBkZWwgY2xpZW50ZSA2NjI2IHRpZW5lbiB0ZW5kZW5jaWEgYSBjYWVyIGEgbG9zIHByb3hpbW9zIGHDsW9zLiBTZSBwdWVkZSBkZWJlciBhIGNhbWJpb3MgZW4gbGEgcHJlZmVyZW5jaWEgZGUgbG9zIGNvbnN1bWlkb3JlcywgdGVuZGVuY2lhcyBkZWwgbWVyY2FkbywgZXRjLioqCgpgYGB7cn0KI1ZlbnRhcyB0b3RhbGVzIGRlIEd1YWRhbGFqYXJhCgp2ZW50YXNfZ2RsIDwtIGRmNyAlPiUKICBncm91cF9ieShBw7FvKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX3RvdGFsZXMgPSBzdW0oVmVudGFzKSkgJT4lCiAgZmlsdGVyKFZlbnRhc190b3RhbGVzICE9MCkgI3BhcmEgcXVpdGFyIGxvcyByZW5nbG9uZXMgY29uIDAKCiN2ZW50YXNfbWF5b3JlcyRTZWN1ZW5jaWEgPC0gMTpucm93KHZlbnRhc19tYXlvcmVzKSAjIGVzIHVuYSBzZWN1ZW5jaWEgcG9yIHNpIGxvIG9jdXBhbW9zIGVuIGFsZ28gbWFzCiNjdWFuZG8gaGFnbyByZWdyZXNvbiBvY3VwbyBxdWUgZWwgZWplIHggc2VhIHVuIHJ1bWVybywgYXNpIHF1ZSBzZSBjYW1iaWEgYSB1bmEgc2VjdWVuY2lhIGRlIG1lc2VzIHBhcmEgcXVlIG5vIHNlIGNvbmZ1bmRhIGFsIGdyYWZpY2FybG8KCmdncGxvdCh2ZW50YXNfZ2RsLCBhZXMoeD1Bw7FvLCB5PVZlbnRhc190b3RhbGVzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSJBw7FvIiwgeT0iVmVudGFzIFRvdGFsZXMgKFF0eSkiLCB0aXRsZSA9ICJWZW50YXMgdG90YWxlcyBkZWwgY2xpZW50ZSAwOTQ4IikKCnJlZ3Jlc2lvbiA8LSBsbShWZW50YXNfdG90YWxlcyB+IEHDsW8sIGRhdGE9dmVudGFzX2dkbCkKc3VtbWFyeShyZWdyZXNpb24pCgojRWN1YWNpb24KI3k9IC0xLjM5OGUrMDkgKyAoNi45NjRlKzA1KQoKCiNSIGN1YWRyYWRhIGFqdXN0YWRhCiMgMC43Mzc5ICAgCgpkYXRvcyA8LSBkYXRhLmZyYW1lKEHDsW89MjAyMDoyMDI1KQpwcmVkaWNjaW9uIDwtcHJlZGljdChyZWdyZXNpb24sZGF0b3MpCnByZWRpY2Npb24KCnZlbnRhc19nZGwkVGlwb19kZV9EYXRvIDwtICJEYXRvcyBSZWFsZXMiCmRhdG9zJFZlbnRhc190b3RhbGVzIDwtIHByZWRpY2Npb24KZGF0b3MkVGlwb19kZV9EYXRvIDwtICJQcmVkaWNjaW9uIgoKZGF0b3NfY29tYmluYWRvcyA8LSByYmluZCh2ZW50YXNfZ2RsLCBkYXRvcykKCmdncGxvdChkYXRvc19jb21iaW5hZG9zLCBhZXMoeD1Bw7FvLCB5PVZlbnRhc190b3RhbGVzLCBjb2xvcj1UaXBvX2RlX0RhdG8pKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHg9IkHDsW8iLCB5PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIHRpdGxlID0gIlByb27Ds3N0aWNvIGEgNSBhw7FvcyBkZSB2ZW50YXMgZW4gR0RMIikKYGBgCioqQW7DoWxpc2lzOiBTZSBwcm9ub3N0aWNhIHF1ZSBsYXMgdmVudGFzIHZhbiBhIGNyZWNlciBlbiBlbCB0ZXJyaXRvcmlvIGRlIEd1YWRhbGFqYXJhIGVuIGxvcyBwcsOzeGltb3MgYcWEb3MqKgoKYGBge3J9CiNWZW50YXMgZXNwZXJhZGFzIGVuIGVsIHN1YiB0ZXJyaXRvcmlvIGRlIEJFTEVORVMgZGVsIHByb2R1Y3RvIEFHVUEgUFVSSUZJQ0FEQQoKdmVudGFzX3NlZ21lbnRvIDwtIGRmNyAlPiUKICBmaWx0ZXIoU3ViX1RlcnJpdG9yaW8gPT0gIkJlbGVuZXMiICYgU2VnbWVudG9fRGV0ID09IkFndWEgUHVyaWZpY2FkYSIpICU+JQogIGdyb3VwX2J5KEHDsW8pICU+JQogIHN1bW1hcmlzZShWZW50YXNfVG90YWxlcyA9IHN1bShWZW50YXMpKSAlPiUKICBmaWx0ZXIoVmVudGFzX1RvdGFsZXMgIT0wKSAlPiUgI3BhcmEgcXVpdGFyIGxvcyByZW5nbG9uZXMgY29uIDAKICBmaWx0ZXIoQcOxbyAhPTIwMTYpCgpnZ3Bsb3QodmVudGFzX3NlZ21lbnRvLCBhZXMoeD1Bw7FvLCB5PVZlbnRhc19Ub3RhbGVzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSJBw7FvIiwgeT0iVmVudGFzIFRvdGFsZXMgKFF0eSkiLCB0aXRsZSA9ICJWZW50YXMgQW51YWxlcyBkZSBDb2NhIENvbGEiKQoKcmVncmVzaW9uMSA8LSBsbShWZW50YXNfVG90YWxlcyB+IEHDsW8sIGRhdGE9dmVudGFzX3NlZ21lbnRvKQpzdW1tYXJ5KHJlZ3Jlc2lvbjEpCgojRWN1YWNpb24KI3k9IC01MzAzNDA0ICsgIDI4MzMKCiNSIGN1YWRyYWRhIGFqdXN0YWRhCiMgLTAuMDU3MzggCgpkYXRvcyA8LSBkYXRhLmZyYW1lKEHDsW89MjAyMDoyMDI1KQpwcmVkaWNjaW9uIDwtcHJlZGljdChyZWdyZXNpb24xLGRhdG9zKQpwcmVkaWNjaW9uCgp2ZW50YXNfc2VnbWVudG8kVGlwb19kZV9EYXRvIDwtICJEYXRvcyBSZWFsZXMiCmRhdG9zJFZlbnRhc19Ub3RhbGVzIDwtIHByZWRpY2Npb24KZGF0b3MkVGlwb19kZV9EYXRvIDwtICJQcmVkaWNjaW9uIgoKZGF0b3NfY29tYmluYWRvcyA8LSByYmluZCh2ZW50YXNfc2VnbWVudG8sIGRhdG9zKQoKZ2dwbG90KGRhdG9zX2NvbWJpbmFkb3MsIGFlcyh4PUHDsW8sIHk9VmVudGFzX1RvdGFsZXMsIGNvbG9yPVRpcG9fZGVfRGF0bykpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeD0iQcOxbyIsIHk9IlZlbnRhcyBUb3RhbGVzIChRdHkpIiwgdGl0bGUgPSAiUHJvbsOzc3RpY28gZGUgdmVudGFzIGVzcGVyYWRhcyBwYXJhIEJlbGVuZXMiLCBzdWJ0aXRsZSA9ICJFbiBBZ3VhIFB1cmlmaWNhZGEiKQpgYGAKKipBbsOhbGlzaXM6IExhcyB2ZW50YXMgZW4gZWwgc3ViIHRlcnJpdG9yaW8gQmVsZW5lcyBlbiB0YW50byBBZ3VhIHB1cmlmaWNhZGEgdmEgYSB0ZW5lciB1bmEgdGVuZGVuY2lhIGRlIGNyZWNpbWllbnRvIHBhcmEgbG9zIHByw7N4aW1vcyA0IGHDsW9zLioqCgpgYGB7cn0KI1ZlbnRhcyBlbiBlbCBzdWIgc2VnbWVudG8gZGUgdG9sdXF1aWxsYSBwYXJhIGxhcyBiZWJpZGFzIGRlIGZydXRhIAoKdmVudGFzX3NlZ21lbnRvMSA8LSBkZjcgJT4lCiAgZmlsdGVyKFN1Yl9UZXJyaXRvcmlvID09ICJUb2x1cXVpbGxhIiAmIFNlZ21lbnRvX0RldCA9PSJCZWJpZGFzIGRlIEZydXRhIikgJT4lCiAgZ3JvdXBfYnkoQcOxbykgJT4lCiAgc3VtbWFyaXNlKFZlbnRhc19Ub3RhbGVzID0gc3VtKFZlbnRhcykpICU+JQogIGZpbHRlcihWZW50YXNfVG90YWxlcyAhPTApICU+JSAjcGFyYSBxdWl0YXIgbG9zIHJlbmdsb25lcyBjb24gMAogIGZpbHRlcihBw7FvICE9MjAxNikKCmdncGxvdCh2ZW50YXNfc2VnbWVudG8xLCBhZXMoeD1Bw7FvLCB5PVZlbnRhc19Ub3RhbGVzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSJBw7FvIiwgeT0iVmVudGFzIFRvdGFsZXMgKFF0eSkiLCB0aXRsZSA9ICJWZW50YXMgQW51YWxlcyBkZSBDb2NhIENvbGEiKQoKcmVncmVzaW9uMSA8LSBsbShWZW50YXNfVG90YWxlcyB+IEHDsW8sIGRhdGE9dmVudGFzX3NlZ21lbnRvMSkKc3VtbWFyeShyZWdyZXNpb24xKQoKI0VjdWFjaW9uCiN5PSAtNTMwMzQwNCArICAyODMzCgojUiBjdWFkcmFkYSBhanVzdGFkYQojIC0wLjA1NzM4IAoKZGF0b3MgPC0gZGF0YS5mcmFtZShBw7FvPTIwMjA6MjAyNSkKcHJlZGljY2lvbiA8LXByZWRpY3QocmVncmVzaW9uMSxkYXRvcykKcHJlZGljY2lvbgoKdmVudGFzX3NlZ21lbnRvMSRUaXBvX2RlX0RhdG8gPC0gIkRhdG9zIFJlYWxlcyIKZGF0b3MkVmVudGFzX1RvdGFsZXMgPC0gcHJlZGljY2lvbgpkYXRvcyRUaXBvX2RlX0RhdG8gPC0gIlByZWRpY2Npb24iCgpkYXRvc19jb21iaW5hZG9zIDwtIHJiaW5kKHZlbnRhc19zZWdtZW50bzEsIGRhdG9zKQoKZ2dwbG90KGRhdG9zX2NvbWJpbmFkb3MsIGFlcyh4PUHDsW8sIHk9VmVudGFzX1RvdGFsZXMsIGNvbG9yPVRpcG9fZGVfRGF0bykpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeD0iQcOxbyIsIHk9IlZlbnRhcyBUb3RhbGVzIChRdHkpIiwgdGl0bGUgPSAiUHJvbsOzc3RpY28gZGUgdmVudGFzIGVzcGVyYWRhcyBwYXJhIFRvbHVxdWlsbGEiLCBzdWJ0aXRsZSA9ICJFbiBCZWJpZGFzIGRlIEZydXRhIikKYGBgCioqQW7DoWxpc2lzOiBTZWfDum4gZWwgcHJvbsOzc3RpY28sIHNlIGVzcGVyYSBxdWUgcGFyYSBlbCBzdWIgdGVycml0b3JpbyBkZSBUb2x1cXVpbGxhIGVuIGN1YW50byBhIGxhcyBiZWJpZGFzIGRlIGZydXRhLCBsYXMgdmVudGFzIGRlY3JlemNhbi4qKgoKYGBge3J9CnRvcF8xMF9jbGllbnRlcyA8LSBkZjcgJT4lCiAgZ3JvdXBfYnkoQ2xpZW50ZSkgJT4lCiAgc3VtbWFyaXNlKFZlbnRhc19Ub3RhbGVzID0gc3VtKFZlbnRhcykpICU+JQogIGFycmFuZ2UoZGVzYyhWZW50YXNfVG90YWxlcykpICU+JQogIHRvcF9uKDEwLCBWZW50YXNfVG90YWxlcykKCnRvcF8xMF9jbGllbnRlcwpgYGAKCiMgPFNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5BY3RpdmlkYWQgSW5kaXZpZHVhbCA1PC9zcGFuPgpgYGB7cn0KI3ZlbnRhcyBtZXN1YWxlcyBkZWwgY2xpZW50ZSA0NTY3Cgp2ZW50YXNfbWVuc3VhbGVzXzQ1NjcgPC0gZGY3ICU+JQogIGZpbHRlcihDbGllbnRlID09ICI0NTY3IikgJT4lCiAgZ3JvdXBfYnkoQcOxbywgTsO6bWVyb19kZV9NZXMpICU+JQogIHN1bW1hcmlzZShWZW50YXNfdG90YWxlcyA9IHN1bShWZW50YXMpKSAlPiUKICBmaWx0ZXIoVmVudGFzX3RvdGFsZXMgIT0wKSAjcGFyYSBxdWl0YXIgbG9zIHJlbmdsb25lcyBjb24gMAoKdmVudGFzX21lbnN1YWxlc180NTY3CgojcGFyYSBoYWNlciBzZXJpZXMgZGUgdGllbXBvIFIgcXVlIGxvcyBkYXRvcyBlc3RlbiBlbiBvcmRlbiBjcm9ub2zDs2dpY28gKHNpIG5vIGVzdHV2aWVyYW4gbGUgcG9uZXMgdW4gYXJyYW5nZSkKI3NvbG8gb2N1cGEgdW5hIGNvbHVtbmEgY29uIGxvcyBkYXRvcwoKI2VzdGFzIHNlIHB1ZWRlbiB1c2FyIG1lbnN1YWxtZW50ZSwgYW51YWwgbyB0cmltZXN0cmFsCgojRnVuY2nDs24gc2VyaWUgZGUgdGllbXBvIE1FTlNVQUwsIHF1ZSBpbmljaWEgZW4gZW5lcm8gMjAxNwp0cyA8LXRzKGRhdGE9IHZlbnRhc19tZW5zdWFsZXNfNDU2NyRWZW50YXNfdG90YWxlcywgc3RhcnQgPSBjKDIwMTcsIDEpLCBmcmVxdWVuY3kgPSAxMikgI2VsIDEgZXMgZWwgcGVyaW9kbyBOTyBtZXMgI2VsIDEyIHNvbiBlbCB0b3RhbCBkZSBwZXJpb2RvcyBxdWUgaGF5IGVuIHVuIGHDsW8geSBjb21vIGVzIG1lbnN1YWwgc29uIDEyCgojRnVuY2nDs24gc2VyaWUgZGUgdGllbXBvIE1FTlNVQUwsIHF1ZSBpbmljaWEgZW4gQWJyaWwgMjAxNwojdHMgPC10cyhkYXRhPSB2ZW50YXNfbWVuc3VhbGVzXzQ1NjckVmVudGFzX3RvdGFsZXMsIHN0YXJ0ID0gYygyMDE3LCA0KSwgZnJlcXVlbmN5ID0gMTIpIAoKI0Z1bmNpw7NuIHNlcmllIGRlIHRpZW1wbyBUUklNRVNUUkFMLCBxdWUgaW5pY2lhIGVuIEVuZXJvIDIwMTcKI3RzIDwtdHMoZGF0YT0gdmVudGFzX21lbnN1YWxlc180NTY3JFZlbnRhc190b3RhbGVzLCBzdGFydCA9IGMoMjAxNywgMSksIGZyZXF1ZW5jeSA9IDQpIAojZnJlY3VlbmNpYSA9IDQgcHEgaGF5IDQgdHJpbWVzdHJlcyBlbiB1biBhw7FvCgojRnVuY2nDs24gc2VyaWUgZGUgdGllbXBvIFRSSU1FU1RSQUwsIHF1ZSBpbmljaWEgZW4gT2N0dWJyZSAyMDE3CiN0cyA8LXRzKGRhdGE9IHZlbnRhc19tZW5zdWFsZXNfNDU2NyRWZW50YXNfdG90YWxlcywgc3RhcnQgPSBjKDIwMTcsIDQpLCBmcmVxdWVuY3kgPSA0KSAKCiNGdW5jacOzbiBzZXJpZSBkZSB0aWVtcG8gQU5VQUwsIHF1ZSBpbmljaWEgZW4gRW5lcm8gMjAxNwojdHMgPC10cyhkYXRhPSB2ZW50YXNfbWVuc3VhbGVzXzQ1NjckVmVudGFzX3RvdGFsZXMsIHN0YXJ0ID0gMjAxNywgZnJlcXVlbmN5ID0gMSkgCgojRnVuY2nDs24gc2VyaWUgZGUgdGllbXBvIFNFTUVTVFJBTCwgcXVlIGluaWNpYSBlbiBFbmVybyAyMDE3CiN0cyA8LXRzKGRhdGE9IHZlbnRhc19tZW5zdWFsZXNfNDU2NyRWZW50YXNfdG90YWxlcywgc3RhcnQgPSBjKDIwMTcsIDEpLCBmcmVxdWVuY3kgPSAyKSAjYXF1aSBlbCBwZXJpb2RvIHNvbG8gcHVlZGUgc2VyIDEgbyAyCgojY3JlYXIgbW9lbG8gQVJJTUEoTW9kZWxvIEF1dG9yZWdyZXNpdm8gSW50ZWdyYWRvIGRlIFByb21lZGlvIE1vdmlsKQoKYXJpbWEgPC0gYXV0by5hcmltYSh0cywgRD0xKSAjRD0xIHBvciBsYSB0ZW1wb3JhbGlkYWQsIHNpIG5vIGxvIHBvbmVtb3MgdGUgc2FsZSB1bmEgcHJlZGljY2nDs24gcGxhbmEKYXJpbWEKc3VtbWFyeShhcmltYSkgI2RlYmVtb3MgZGUgZW5mb2Nhcm5vcyBlbiBsb3MgbsO6bWVyb3MgZGUgZXJyb3IsIGRvbmRlIGVsIG7Dum1lcm8gcG9yIHNpIHNvbG8gbm8gdGUgZGljZSBzaSBlcyBtZWpvciBvIHBlb3IsIGVzdG8gc29sbyBzZSBzYWJyYSBzaSBzZSBjb21wYXJhIGNvbiBvdHJvIG1vZGVsby4gUGVybyBub3MgcG9kZW1vcyBlbmZvY2FyIGVuIGVsIE1BUEUgZXN0ZSBlcyBlbCBxdWUgdGllbmUgbWFzIHZlbnRhamFzLiBzaSBoYWNlbW9zIGRvcyBtb2RlbG9zIGNvbXBhcmFtb3MgbG9zIG1hcGVzCgojZ2VuZXJhciBlbCBwcm9uw7NzdGljbyBkZSB2ZW50YXMKcHJvbm9zdGljbyA8LSBmb3JlY2FzdChhcmltYSxsZXZlbD05NSwgaD0zNikgI2xldmVsPW5pdmVsIGRlIGNvbmZpYW56YSBoPXBlcmlvZG9zIGRlIHByb27Ds3N0aWNvCnByb25vc3RpY28KcGxvdChwcm9ub3N0aWNvLCBtYWluID0gIlZlbnRhcyBNZW5zdWFsZXMgeSBQcm9uw7NzdGljbyBhIDMgQcOxb3MgZGVsIENsaWVudGUgNDU2NyIsICB4bGFiID0gIkHDsW8iLCB5bGFiID0gIlZlbnRhcyhxdHkpIikgCiNwbG90IGVzIGxhIGdyYWZpY2EgbWFzIHNlbmNpbGxhLCBsbyBncmlzIHJlcHJlc2VudGEgZWwgOTUgZGUgY29uZmlhbnphIHF1ZSBsZSBwdXNpbW9zCmBgYAoKIyA8U3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPkVWSURFTkNJQTwvc3Bhbj4KCiMjIFByZWd1bnRhcyBEZXRvbmFudGVzCiMjIyAxLiAKwr9QdWVkZSBvYnNlcnZhcnNlIHVuIGNyZWNpbWllbnRvIGVuIGxhcyB2ZW50YXMgZGUgYWxndW5vcyBkZSBsb3Mgc2VnbWVudG9zIGRlIHByb2R1Y3RvcyBkZSBsYSBmYW1pbGlhIENvY2EgQ29sYSBlbiBsYXMgdGllbmRhcyBlbiBsYXMgcXVlIHNlIGltcGxlbWVudMOzIGVsIFByb3llY3RvIFNpZ2xvIFhYSSBkZSBBcmNhIENvbnRpbmVudGFsPwpgYGB7cn0KdmVudGFzX3RvdGF0bGVzX3NlZyA8LSBkZjcgJT4lCiAgZmlsdGVyKFNlZ21lbnRvX0RldCAlaW4lIGMoIkFndWEgUHVyaWZpY2FkYSIsICJJc290w7NuaWNvcyBSZWd1bGFyIiwgIkNvbGFzIFJlZ3VsYXIiKSkgJT4lCiAgICAgICAgICAgZmlsdGVyKEHDsW8gPT0gMjAxOCkgJT4lCiAgICAgICAgICAgZ3JvdXBfYnkoU2VnbWVudG9fRGV0LCBOw7ptZXJvX2RlX01lcykgJT4lCiAgICAgICAgICAgc3VtbWFyaXNlKFZlbnRhc19Ub3RhbGVzPSBzdW0oVmVudGFzKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgICAgICAgICAgYXJyYW5nZShOw7ptZXJvX2RlX01lcykKCmdncGxvdCh2ZW50YXNfdG90YXRsZXNfc2VnLCBhZXMoeD1Ow7ptZXJvX2RlX01lcywgeT1WZW50YXNfVG90YWxlcywgZ3JvdXA9U2VnbWVudG9fRGV0LCBjb2xvcj1hcy5mYWN0b3IoU2VnbWVudG9fRGV0KSkpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSJNZXMiLCB5PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIHRpdGxlPSJWZW50YXMgVG90YWxlcyBwb3IgU2VnbWVudG9zIiwgc3VidGl0bGUgPSAiUHJveWVjdG8gU2lnbG8gWFhJICgyMDE4KSIsIGNvbG9yPSAiVGFtYcOxbyBkZSBDbGllbnRlIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwLCB2anVzdD0wLjUsIGhqdXN0PTEpKQpgYGAKKipSZXNwdWVzdGE6ICBFbiBnZW5lcmFsIGxhcyB2ZW50YXMgYXVtZW50YXJvbiBlbiAyMDE5LCBwZXJvIGNhZGEgc2VnbWVudG8gc2UgY29tb3BvcnRvIGRpZmVyZW50ZS4gRWwgaW5jcmVtZW50byBkZSB2ZW50YXMgc2UgcHVlZGUgbG9ncmFyIHlhIHNlYSBhIG1lam9yZXMgY2FtcGHDsWFzIGRlIG1lcmNhZG90ZWNuaWEsIGxhbnphbWllbnRvIGRlIG51ZXZvcyBwcm9kdWN0b3MgbyBjYW1iaW9zIGVuIGxhcyBwcmVmZXJlbmNpYXMgZGUgbG9zIGNvbnN1bWlkb3Jlcy4gRW4gMjAyOCBsYSB2ZW50YSBkZSBDb2NhIENvbGEgZW50cmUgZmVicmVybyB5IERpY2llbWJyZSBhdW1lbnTDsyBlbiAxMDAsMDAwIHVuaWRhZGVzLCBtaWVudHJhcyBxdWUgZW4gbGFzIGFndWFzIGlzb3TDs25pY2FzIG5vIHR1dmllcm9uIGNhbWJpb3MqKgoKIyMjIDIuIArCv0VsIGluY3JlbWVudG8gZW4gbGFzIHZlbnRhcyBlcyBzaW1pbGFyIGVudHJlIGxvcyBkaWZlcmVudGVzIHRhbWHDsW9zIGRlIGNsaWVudGVzPwpgYGB7cn0KdmVudGFzX3RvdGFsZXNfdGFtYcOxb19jbGllbnRlIDwtIGRmNyAlPiUKICBmaWx0ZXIoQcOxbz09IjIwMTkiKSAlPiUKICBncm91cF9ieShOw7ptZXJvX2RlX01lcywgVGFtYcOxb19DdGVfSW5kdXN0cmlhKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX1RvdGFsZXMgPSBzdW0oVmVudGFzKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgYXJyYW5nZShOw7ptZXJvX2RlX01lcykgJT4lCiAgIGZpbHRlcihWZW50YXNfVG90YWxlcyAhPTApCgpnZ3Bsb3QodmVudGFzX3RvdGFsZXNfdGFtYcOxb19jbGllbnRlLCBhZXMoeD1Ow7ptZXJvX2RlX01lcywgeT1WZW50YXNfVG90YWxlcywgZ3JvdXA9VGFtYcOxb19DdGVfSW5kdXN0cmlhLCBjb2xvcj1hcy5mYWN0b3IoVGFtYcOxb19DdGVfSW5kdXN0cmlhKSkpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSJNZXMiLCB5PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIHRpdGxlPSJWZW50YXMgVG90YWxlcyBwb3IgVGFtYcOxbyBkZSBDbGllbnRlIiwgc3VidGl0bGUgPSAiKDIwMTkpIiwgY29sb3I9ICJUYW1hw7FvIGRlIENsaWVudGUiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsIHZqdXN0PTAuNSwgaGp1c3Q9MSkpCmBgYAoqKlJlc3B1ZXN0YTogSW5kZXBlbmRpZW50ZW1lbnRlIGRlbCB0YW1hw7FvIGRlbCBjbGllbnRlLCBlbCBpbmNyZW1lbnRvIGVuIGxhcyB2ZW50YXMgZXMgc2ltaWxhci4gQ29tbyB0b2RvcyBsb3MgbmVnb2Npb3MgZXN0w6FuIGFiaWVydG9zIGxvcyBtaXNtbyBkw61hcywgeSBlc3TDoW4gdWLDrWNhZG9zIGVuIGxhIG1pc21hIGNpdWRhZCAoR3VhZGFsYWphcmEpLCBsb3MgZmFjdG9yZXMgZXh0ZXJub3MgZGUgbGFzIHZlbnRhcyBhZmVjdGFuIGNhc2kgaWd1YWwgYSB0b2Rvcy4gRWwgbWVzIGRlIG1heW8gZnVlIGVsIGRlIG1heW8gdmVudGFzIHBhcmEgdG9kb3MgbG9zIHRhbWHDsW9zIGRlIGNsaWVudGVzLCB5IGVsIHByaW1lciBiaW1lc3RyZSBmdWUgZWwgbWFzIGJham8gcGFyYSB0b2RvcyBsb3MgY2xpZW50ZXMuKioKCiMjIyAzLiAKwr9DdcOhbCBlcyBlbCBjb21wb3J0YW1pZW50byBvYnNlcnZhZG8gZGUgbGFzIHVuaWRhZGVzIHZlbmRpZGFzIHBvciBtZXMgZGUgY2FkYSB1bmEgZGUgbGFzIG1hcmNhcywgaW5kZXBlbmRpZW50ZW1lbnRlIGRlIHN1cyByZXNwZWN0aXZhcyBwcmVzZW50YWNpb25lcz8KYGBge3J9CnZlbnRhc190b3RhbGVzX3Bvcl9tYXJjYSA8LSBkZjcgJT4lCiAgZmlsdGVyKEHDsW8gPT0yMDE5KSAlPiUKICBmaWx0ZXIoTWFyY2EgJWluJSBjKCJDb2NhLUNvbGEiLCAiVmFsbGUgRnJ1dCIsICJDb2NhLUNvbGEgTGlnaHQiLCAiQWd1YSBwdXJpZmljYWRhIENpZWwiLCAiSm95YSIsICJGcmVzY2EiKSkgJT4lCiAgZ3JvdXBfYnkoTWFyY2EsIE7Dum1lcm9fZGVfTWVzKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX1RvdGFsZXMgPSBzdW0oVmVudGFzKSkgJT4lCiAgYXJyYW5nZShOw7ptZXJvX2RlX01lcykgJT4lCiAgZmlsdGVyKFZlbnRhc19Ub3RhbGVzICE9MCkKCmdncGxvdCh2ZW50YXNfdG90YWxlc19wb3JfbWFyY2EsIGFlcyh4PU7Dum1lcm9fZGVfTWVzLCB5PVZlbnRhc19Ub3RhbGVzLCBncm91cD1NYXJjYSwgY29sb3I9YXMuZmFjdG9yKE1hcmNhKSkpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4PSJNZXMiLCB5PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIHRpdGxlPSJWZW50YXMgVG90YWxlcyIsIHN1YnRpdGxlPSJUb3AgNSBNYXJjYXMgKDIwMTkpIiwgY29sb3I9ICJNYXJjYSIpCmBgYAoqKlJlc3B1ZXN0YTogRWwgY29tcG9ydGFtaWVudG8gZGUgdmVudGFzIGVzIHNpbWlsYXIgZW50cmUgbGFzIG1hcmNhcyBhIHRyYXbDqXMgZGUgbG9zIG1lc2VzLCBwZXJvIGhheSBtYXJjYXMgcXVlIHZlbmRlbiBtdWNobyBtw6FzIHF1ZSBvdHJhcy4gTG9zIG1lc2VzIGRlIGxhcyB2ZW50YXMgZGUgYmViaWRhcyBzb24gbG9zIG1lc2VzIGUgcXVlIGxhIHRlbXBlcmF0dXJhIGVzIG1heW9yLCB5IGxhcyBtYXJjYXMgbcOhcyBjb25vY2lkYXMgc29uIGxhcyBxdWUgZXN0YW4gcXVlIGVzdGFuIGVuIGxhIG1lbnRlIGRlbCBjb25zdW1pZG9yLiBFbCBtZXMgZGUgbWF5byAyMDE5IGVzIHBhcmEgdG9kYXMgbGFzIG1hcmNhcyBlbCBkZSBtYXlvcmVzIHZlbnRhcywgcGVybyBsYSBtYXJjYSBDb2NhLUNvbGEgZXMgbGEgcXVlIHZlbmRlIG3DoXMgcXVlIHRvZGFzKioKCiMjIyA0LgrCv1NlIGhhIGluY3JlbWVudGFkbyBsYSB2ZW50YSBkZSBwcm9kdWN0b3MgZW4gZW52YXNlcyByZXRvcm5hYmxlcyBlbiBsb3Mgw7psdGltb3MgZG9zIGHDsW9zPwpgYGB7cn0KdmVudGFzX2VudmFzZXNfcmV0b3JuYWJsZXM8LSBkZjcgJT4lCiAgZmlsdGVyKFJldG9ybmFibGVfTlIgPT0gIlJldG9ybmFibGUiICYgQcOxbz09YygyMDE4LDIwMTkpKSAlPiUKICBncm91cF9ieShBw7FvKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX1RvdGFsZXMgPSBzdW0oVmVudGFzKSkgJT4lCiAgZmlsdGVyKFZlbnRhc19Ub3RhbGVzICE9MCkgI3BhcmEgcXVpdGFyIGxvcyByZW5nbG9uZXMgY29uIDAKICAKZ2dwbG90KHZlbnRhc19lbnZhc2VzX3JldG9ybmFibGVzLCBhZXMoeD1Bw7FvLCB5PVZlbnRhc19Ub3RhbGVzKSkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnModGl0bGU9IlZlbnRhcyBkZSBQcm9kdWN0b3MgZW4gRW52YXNlcyBSZXRvcm5hYmxlcyBlbiBsb3Mgw5psdGltb3MgRG9zIEHDsW9zIiwKICAgICAgIHg9IkHDsW8iLAogICAgICAgeT0iVmVudGFzIFRvdGFsZXMiKQpgYGAKKipSZXNwdWVzdGE6IExhIHZlbnRhIGRlIHByb2R1Y3RvcyBlbiBlbnZhc2VzIHJldG9ybmFibGVzIGhhIGluY3JlbWVudGFkbyBlbiBsb3Mgw7psdGltb3MgZG9zIGHDsW9zIGRlIDMsNDAwLDAwMCBlbiBlbCAyMDE4IGEgYXByb3hpbWFkYW1lbnRlIDQsMzIwLDAwMCBlbiBlbCAyMDE5LiBDcmVjaWVuZG8gYXByb3hpbWFkYW1lbnRlIHVuIDI3LjA2JS4gTGFzIGNhbXBhw7FhcyBkZSBjb25jaWVuY2lhIGFtYmllbnRhbCBoYW4gdnVlbHRvIHBvcHVsYXJlcyBsYXMgb3BjaW9uZXMgbWVub3MgZGHDsWluYXMgYWwgZWNvc2lzdGVtYS4qKgoKKipub3RhczogKioKCiMjIyA1LiAKwr9FbCBjb21wb3J0YW1pZW50byBkZSBsYSB2ZW50YSBkZSBhZ3VhIGhhIGluY3JlbWVudGFkbyBlbiByZWxhY2nDs24gYWwgZGUgbG9zIHJlZnJlc2NvcyBvIGxhcyBiZWJpZGFzIGlzb3TDs25pY2FzPwpgYGB7cn0KdmVudGFzX2FndWFzX3JlZnJlc2NvcyA8LWRmNyAlPiUKICBmaWx0ZXIoU2VnbWVudG9fRGV0ICVpbiUgYygiQWd1YSBNaW5lcmFsIiwgIkFndWEgUHVyaWZpY2FkYSIsIkFndWEgU2Fib3JpemFkYSIsICJJc290w7NuaWNvcyBMaWdodCIsICJJc290w7NuaWNvcyBSZWd1bGFyIiwgIkNvbGFzIExpZ2h0IiwgIkNvbGFzIFJlZ3VsYXIiKSkgJT4lCiAgZ3JvdXBfYnkoQcOxbywgU2VnbWVudG9fRGV0KSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX1RvdGFsZXMgPSBzdW0oVmVudGFzKSkgJT4lCiAgZmlsdGVyKFZlbnRhc19Ub3RhbGVzICE9MCkgCgpnZ3Bsb3QodmVudGFzX2FndWFzX3JlZnJlc2NvcywgYWVzKHggPSBBw7FvLCB5ID0gVmVudGFzX1RvdGFsZXMsIGNvbG9yID0gU2VnbWVudG9fRGV0KSkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnModGl0bGUgPSAiQ29tcGFyYWNpw7NuIGRlIFZlbnRhczogQWd1YSB2cy4gUmVmcmVzY29zIHZzLiBCZWJpZGFzIElzb3TDs25pY2FzIiwKICAgICAgIHggPSAiQcOxbyIsCiAgICAgICB5ID0gIlZlbnRhcyBUb3RhbGVzIikKCmBgYAoqKipSZXNwdWVzdGE6IGxhcyB2ZW50YXMgZGUgYWd1YSBwdXJpZmljYWRhIG5vIGhhbiBhdW1lbnRhZG8gZW4gcmVsYWNpbzJuIGEgcmVmcmVzY29zIG8gYmViaWRhcyBpc290w7NuaWNhcy4gUHVlZGUgc2VyIHBvciBsYSBwZXJzZXBjacOzbiBxdWUgZWwgYWd1YSBubyB0aWVuZSB2YWxvciBhZ3JlZ2FkbyBlbiBsYSBwcmVwYXJhY2nDs24geSBlbCBhesO6Y2FyIGVuIGxhIHJlY2V0YSBoYWNlIGRlIGxvcyByZWZyZXNjb3MgbGEgb3BjacOzbiBwcmVmZXJpZGEgZGUgbG9zIGNvbnN1bWlkb3JlcyBtZXhpY2Fub3MuIEVuIDIwMTkgbGFzIHZlbnRhcyB0b3RhbGVzIGRlIGFndWEgcHVyaWZpY2FkYSBubyBzdXBlcmFuIDUwLDAwMCB1bmlkYWRlcywgbWllbnRyYXMgcXVlIGxhIENvY2EtQ29sYSB2ZW5kaW8gZW4gc3UgbWVzIG3DoXMgYWx0byA2MzAsMDAwIHVuaWRhZGVzICgxMSB2ZWNlcyBtw6FzIHF1ZSBlbCBhZ3VhKSoqCgojIyMgNi4Kwr9QdWVkZSBkZWNpcnNlIHF1ZSBsYSB2ZW50YSBtZW5zdWFsIGRlIGFndWEgZXN0w6EgcmVsYWNpb25hZGEgY29uIGxhIHZlbnRhIG1lbnN1YWwgZGUgcmVmcmVzY29zIGVuIGxvcyDDumx0aW1vcyA0IGHDsW9zPwpgYGB7cn0KdmVudGFzX3RvdGFsZXNfYXlyIDwtIGRmNyAlPiUKICBmaWx0ZXIoU2VnbWVudG9fRGV0ID09IGMoIkFndWEgUHVyaWZpY2FkYSIsICJDb2xhcyBSZWd1bGFyIikpICU+JQogIGdyb3VwX2J5KFNlZ21lbnRvX0RldCwgQcOxbykgJT4lCiAgc3VtbWFyaXNlKFZlbnRhc19Ub3RhbGVzID0gc3VtKFZlbnRhcykpCgpnZ3Bsb3QodmVudGFzX3RvdGFsZXNfYXlyLCBhZXMoeCA9IEHDsW8sIHkgPSBWZW50YXNfVG90YWxlcywgZ3JvdXA9IFNlZ21lbnRvX0RldCwgY29sb3IgPSBTZWdtZW50b19EZXQpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh0aXRsZSA9ICJDZW50YXMgVG90YWxlcyBwb3IgU2VnbWVudG8iLAogICAgICAgeCA9ICJBw7FvIiwKICAgICAgIHkgPSAiVmVudGFzIFRvdGFsZXMgKHF0eSkiLAogICAgICAgY29sb3I9IlNlZ21lbnRvIikKYGBgCioqUmVzcHVlc3RhOkxhIHZlbnRhIGRlIGFndWEgeSByZWZyZXNjb3Mgc2UgaW5jcmVtZW50YW4gZW4gbG9zIG1pc21vcyBtZXNlcywgeSBhIHRyYXbDqXMgZGUgbG9zIGHDsW9zLCBwZXJvIG5vIHNlIHB1ZWRlIGNvbmNsdWlyIHF1ZSB1biBpbmNyZW1lbnRvIGNhdXNlIGVsIG90cm8uIExvcyBtZXNlcyBjYWx1cm9zb3MgeSBlbCBjcmVjaW1pZW50byBkZSA7YSBwb2JsYWNpbzJuIGhhY2UgcXVlIGxhcyB2ZW50YXMgc2UgaW5jcmVtZW50ZW4gZW4gZW4gbGFzIGJlYmlkYXMsIHNlYW4gYWd1YSBvIHJlZnJlc2NvLiBFbiBsYSBncsOhZmljYSBvYnRlbmlkYSBzZSBvYnNlcnZhIHVuIGluY3JlbWVudG8gYcOxbyBjb24gYcOxbyBlbiBsYSB2ZW50YSBkZSBhZ3VhIHkgdGFtYmnDqW4gZGUgcmVmcmVzY29zLioqCgojIyMgNi4xCsK/UHVlZGUgZGVjaXJzZSBxdWUgbGEgdmVudGEgbWVuc3VhbCBkZSBhZ3VhIGVzdMOhIHJlbGFjaW9uYWRhIGNvbiBsYSB2ZW50YSBtZW5zdWFsIGRlIHJlZnJlc2NvcyBlbiBsb3Mgw7psdGltb3MgNCBhw7Fvcz8KYGBge3J9CnZlbnRhc19yZWxhY2lvbiA8LSBkZjcgJT4lCiAgZmlsdGVyKFNlZ21lbnRvX0RldCA9PSBjKCJBZ3VhIE1pbmVyYWwiLCAiQWd1YSBQdXJpZmljYWRhIiwiQ29sYXMgTGlnaHQiLCAiQ29sYXMgUmVndWxhciIpKSAlPiUKICBncm91cF9ieShBw7FvLCBOw7ptZXJvX2RlX01lcywgU2VnbWVudG9fRGV0KSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX1JlbGFjaW9uID0gc3VtKFZlbnRhcykpCgpnZ3Bsb3QodmVudGFzX3JlbGFjaW9uLCBhZXMoeCA9IE7Dum1lcm9fZGVfTWVzLCB5ID0gVmVudGFzX1JlbGFjaW9uLCBjb2xvciA9IFNlZ21lbnRvX0RldCwgZ3JvdXAgPSBpbnRlcmFjdGlvbihTZWdtZW50b19EZXQsIEHDsW8pKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9saW5lKCkgKyAjIEHDsWFkaWRvIHBhcmEgY29uZWN0YXIgbG9zIHB1bnRvcwogIGZhY2V0X3dyYXAofiBBw7FvLCBuY29sID0gMSwgc2NhbGVzID0gImZyZWVfeSIpICsgIyBVc2FyIGZhY2V0X3dyYXAgcGFyYSBzZXBhcmFyIHBvciBBw7FvCiAgbGFicyh0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgVmVudGFzIE1lbnN1YWxlcyBkZSBBZ3VhIHkgUmVmcmVzY29zIGVuIGxvcyDDmmx0aW1vcyA0IEHDsW9zIiwKICAgICAgIHggPSAiTsO6bWVybyBkZSBNZXMiLAogICAgICAgeSA9ICJWZW50YXMiKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKIyMjIDcuIArCv0EgY3XDoW50byBhc2NpZW5kZW4gbGFzIHZlbnRhcyBlc3BlcmFkYXMgcGFyYSBlbCAyMDIwIGVuIGxhIENvY2EgQ29sYSBkZSA1MDAgbWwgTlIgVmlkcmlvPwpgYGB7cn0KdmVudGFzX2NvY2FfdmlkaXJpbyA8LSBkZjcgJT4lCiAgZmlsdGVyKE1hcmNhID09ICJDb2NhLUNvbGEiICYgUHJlc2VudGFjaW9uID09IjUwMCBtbCBOUiBWaWRyaW8iKSAlPiUKICBncm91cF9ieShBw7FvLCBOw7ptZXJvX2RlX01lcykgJT4lCiAgc3VtbWFyaXNlKFZlbnRhc19Ub3RhbGVzID0gc3VtKFZlbnRhcykpICU+JQogIGZpbHRlcihWZW50YXNfVG90YWxlcyAhPTApICU+JSAjcGFyYSBxdWl0YXIgbG9zIHJlbmdsb25lcyBjb24gMAogIGZpbHRlcihBw7FvICE9MjAxNikKCnRzIDwtIHRzKGRhdGE9dmVudGFzX2NvY2FfdmlkaXJpbyRWZW50YXNfVG90YWxlcywgc3RhcnQ9YygyMDE2LDEpLCBmcmVxdWVuY3k9MTIpCgphcmltYSA8LSBhdXRvLmFyaW1hKHRzLCBEPTEpCmFyaW1hCnN1bW1hcnkoYXJpbWEpCgpwcm9ub3N0aWNvIDwtIGZvcmVjYXN0KGFyaW1hLCBsZXZlbD05NSwgaD0xNikKcHJvbm9zdGljbwpwbG90KHByb25vc3RpY28sIG1haW49IlByb27Ds3N0aWNvIGRlIFZlbnRhcyBwYXJhIGVsIDIwMjAgZGUgQ29jYSBDb2xhIDUwMCBtbCBOUiBWaWRyaW8iLCB4bGFiPSJBw7FvIiwgeWxhYj0iVmVudGFzIChRVFkpIikKCmBgYAoqKlJlc3B1ZXN0YTogTGFzIHZlbnRhcyBlc3BlcmFkYXMgIGRlIENvY2EtQ29sYSBkZSA1MDAgbWwgTlIgVmlkcmlvIHBhcmEgMjAyMCBvc2NpbGFuIG1lbnN1YWxtZW50ZSBlbnRyZSA0NSwwMDAgeSA2NSwwMDAgdW5pZGFkZXMsIGNvbiB1bmEgY29uZmlhYmlsaWRhZCBkZWwgOTUlKioKCiMjIyBFeHRyYQpgYGB7cn0KdmVudGFzX21lbnN1YWxlcyA8LSBkZjcgJT4lCiAgZ3JvdXBfYnkoQcOxbywgTWVzLCBTZWdtZW50b19EZXQpICU+JQogIHN1bW1hcmlzZShWZW50YXNfVG90YWxlcyA9IHN1bShWZW50YXMpLCAuZ3JvdXBzID0gJ2Ryb3AnKQoKIyBTZXBhcmFyIGxhcyB2ZW50YXMgZGUgYWd1YSB5IHJlZnJlc2NvcyBlbiBkb3MgZGF0YWZyYW1lcyAKdmVudGFzX2FndWEgPC0gdmVudGFzX21lbnN1YWxlcyAlPiUgZmlsdGVyKFNlZ21lbnRvX0RldCAlaW4lIGMoIkFndWEgTWluZXJhbCIsICJBZ3VhIFB1cmlmaWNhZGEiKSkKdmVudGFzX3JlZnJlc2NvcyA8LSB2ZW50YXNfbWVuc3VhbGVzICU+JSBmaWx0ZXIoU2VnbWVudG9fRGV0ICVpbiUgYygiQ29sYXMgTGlnaHQiLCAiQ29sYXMgUmVndWxhciIpKQoKY29ycmVsYWNpb24gPC0gY29yKHZlbnRhc19hZ3VhJFZlbnRhc19Ub3RhbGVzLCB2ZW50YXNfcmVmcmVzY29zJFZlbnRhc19Ub3RhbGVzKQoKZ2dwbG90KCkgKwogIGdlb21fbGluZShkYXRhID0gdmVudGFzX2FndWEsIGFlcyh4ID0gaW50ZXJhY3Rpb24oQcOxbywgTWVzKSwgeSA9IFZlbnRhc19Ub3RhbGVzLCBncm91cCA9IDEsIGNvbG91ciA9ICJBZ3VhIikpICsKICBnZW9tX2xpbmUoZGF0YSA9IHZlbnRhc19yZWZyZXNjb3MsIGFlcyh4ID0gaW50ZXJhY3Rpb24oQcOxbywgTWVzKSwgeSA9IFZlbnRhc19Ub3RhbGVzLCBncm91cCA9IDEsIGNvbG91ciA9ICJSZWZyZXNjb3MiKSkgKwogIGxhYnModGl0bGUgPSAiQ29tcGFyYWNpw7NuIGRlIFZlbnRhcyBNZW5zdWFsZXM6IEFndWEgdnMuIFJlZnJlc2NvcyIsCiAgICAgICB4ID0gIlRpZW1wbyIsCiAgICAgICB5ID0gIlZlbnRhcyBUb3RhbGVzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCJBZ3VhIiA9ICJibHVlIiwgIlJlZnJlc2NvcyIgPSAicmVkIikpCgpwcmludChjb3JyZWxhY2lvbikKYGBgCgoK