R Markdown

Instalar paquetes y llamar librerias

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
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2
## ──
## ✔ ggplot2 3.4.1     ✔ purrr   1.0.1
## ✔ tibble  3.2.1     ✔ stringr 1.5.0
## ✔ tidyr   1.3.0     ✔ forcats 1.0.0
## ✔ readr   2.1.4     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(readxl)
library(ggplot2)

Actividad Individual 2

Identificar en el dataframe de la Situación Problema 2 las estructuras de datos que investigaste en tu tarea colaborativa 1 (Vectores, Listas, Factores, Matrices)

ArcaContinentalDatos <- read_excel("Downloads/ArcaContinentalDatos.xlsx")
View(ArcaContinentalDatos)
str(ArcaContinentalDatos)
## 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 ...

¿El dataframe tiene NAs?

nas_por_columna <- colSums(is.na(ArcaContinentalDatos))
print(nas_por_columna)
##                   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

¿El dataframe tiene datos perdidos?

ArcaContinentalDatos <- replace(ArcaContinentalDatos, is.na(ArcaContinentalDatos), 0)
nas_por_columna <- colSums(is.na(ArcaContinentalDatos))
print(nas_por_columna)
##                   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                    0                    0 
##                Marzo                Abril                 Mayo 
##                    0                    0                    0 
##                Junio                Julio               Agosto 
##                    0                    0                    0 
##           Septiembre              Octubre            Noviembre 
##                    0                    0                    0 
##            Diciembre 
##                    0

detectar valores atípicos

boxplot(ArcaContinentalDatos$Enero)

#eliminar renglón de totales
ArcaContinentalDatos<- ArcaContinentalDatos[ArcaContinentalDatos$Enero <6000, ]
library(dplyr)

ventas_enero_a_junio <- ArcaContinentalDatos %>%
  select(CEDI, Enero:Junio)


print(ventas_enero_a_junio)
## # A tibble: 466,508 × 7
##    CEDI         Enero Febrero Marzo Abril  Mayo Junio
##    <chr>        <dbl>   <dbl> <dbl> <dbl> <dbl> <dbl>
##  1 Suc. Belenes     0       0     0     0     0     0
##  2 Suc. Belenes     0       2     8     4     4     2
##  3 Suc. Belenes     0       0     3     6     3     3
##  4 Suc. Belenes     0       0     0     0     0     0
##  5 Suc. Belenes     0       0     0     0     0     0
##  6 Suc. Belenes     0       0     1     0     0     0
##  7 Suc. Belenes     1       0     0     0     0     0
##  8 Suc. Belenes     0       1     0     1     0     1
##  9 Suc. Belenes     3       3     4     4     4     4
## 10 Suc. Belenes     0       0     0     0     0     0
## # ℹ 466,498 more rows
movimientos_grandes <- ArcaContinentalDatos %>%
  filter(`Tamaño Cte Industria` == "Grande")

print(movimientos_grandes)
## # A tibble: 41,333 × 25
##        ID   Año Territorio  `Sub Territorio` CEDI         Cliente Nombre
##     <dbl> <dbl> <chr>       <chr>            <chr>        <chr>   <chr> 
##  1 374960  2019 Guadalajara Belenes          Suc. Belenes 7657    FROYL 
##  2 374961  2019 Guadalajara Belenes          Suc. Belenes 7657    FROYL 
##  3 374962  2019 Guadalajara Belenes          Suc. Belenes 7657    FROYL 
##  4 374963  2019 Guadalajara Belenes          Suc. Belenes 7657    FROYL 
##  5 374964  2019 Guadalajara Belenes          Suc. Belenes 7657    FROYL 
##  6 374965  2019 Guadalajara Belenes          Suc. Belenes 7657    FROYL 
##  7 374966  2019 Guadalajara Belenes          Suc. Belenes 7657    FROYL 
##  8 374967  2019 Guadalajara Belenes          Suc. Belenes 7657    FROYL 
##  9 374968  2019 Guadalajara Belenes          Suc. Belenes 7657    FROYL 
## 10 374969  2019 Guadalajara Belenes          Suc. Belenes 7657    FROYL 
## # ℹ 41,323 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>
ArcaContinentalDatos_ordenado <- ArcaContinentalDatos %>%
  arrange(CEDI, Marca, Presentacion)

print(ArcaContinentalDatos_ordenado)
## # A tibble: 466,508 × 25
##        ID   Año Territorio  `Sub Territorio` CEDI         Cliente Nombre
##     <dbl> <dbl> <chr>       <chr>            <chr>        <chr>   <chr> 
##  1 200110  2018 Guadalajara Belenes          Suc. Belenes 7800    SAN I 
##  2 200224  2018 Guadalajara Belenes          Suc. Belenes 7875    ABARR 
##  3 200461  2018 Guadalajara Belenes          Suc. Belenes 7917    ABARR 
##  4 200576  2018 Guadalajara Belenes          Suc. Belenes 8010    ABARR 
##  5 200682  2018 Guadalajara Belenes          Suc. Belenes 8186    SUPER 
##  6 200783  2018 Guadalajara Belenes          Suc. Belenes 8201    MIGUE 
##  7 200968  2018 Guadalajara Belenes          Suc. Belenes 8678    FERNA 
##  8 201041  2018 Guadalajara Belenes          Suc. Belenes 8689    ABARR 
##  9 201313  2018 Guadalajara Belenes          Suc. Belenes 8795    ABARR 
## 10 201415  2018 Guadalajara Belenes          Suc. Belenes 8842    ABARR 
## # ℹ 466,498 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>
library(dplyr)

ArcaContinentalDatos <- ArcaContinentalDatos %>%
  rename(Sub_territorio = `Sub Territorio`)

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

ventas_por_marca_primer_semestre <- ArcaContinentalDatos %>%
  group_by(Marca) %>%
  summarize(Ventas_Primer_Semestre = sum(Ventas_Primer_Semestre))

print(ventas_por_marca_primer_semestre)
## # A tibble: 55 × 2
##    Marca                Ventas_Primer_Semestre
##    <chr>                                 <dbl>
##  1 AdeS Frutal                            8126
##  2 AdeS Lácteo                            4413
##  3 Barista Bros                            334
##  4 Bebere                                 1034
##  5 Burn                                   5070
##  6 Café Blak                                79
##  7 Ciel Agua Purificada                 864686
##  8 Ciel Exprim                           33959
##  9 Ciel Mineralizada                     18043
## 10 Ciel Mini                              4942
## # ℹ 45 more rows
media_ventas <- ArcaContinentalDatos %>%
  group_by(Marca, Presentacion, Tamaño) %>%
  summarise(Media_Ventas_Primer_Semestre = mean(Enero + Febrero + Marzo + Abril + Mayo + Junio))
## `summarise()` has grouped output by 'Marca', 'Presentacion'. You can override
## using the `.groups` argument.
print(media_ventas)
## # A tibble: 273 × 4
## # Groups:   Marca, Presentacion [272]
##    Marca        Presentacion    Tamaño     Media_Ventas_Primer_Semestre
##    <chr>        <chr>           <chr>                             <dbl>
##  1 AdeS Frutal  200 ml Tetra    Individual                       1.22  
##  2 AdeS Frutal  946 ml NR Tetra Familiar                         4.17  
##  3 AdeS Lácteo  200 ml Tetra    Individual                       0.0857
##  4 AdeS Lácteo  946 ml NR Tetra Familiar                         3.30  
##  5 Barista Bros 250 ml. NR PET  Individual                       0.343 
##  6 Bebere       473 ml NR       Individual                       3.23  
##  7 Burn         Lata 235 ml     Individual                       0.558 
##  8 Burn         Lata 237 ml     Individual                       0.182 
##  9 Burn         Lata 310 ml     Individual                       0     
## 10 Burn         Lata 450 ml     Individual                       2.60  
## # ℹ 263 more rows
media_ventas <- mean(ArcaContinentalDatos$Enero + ArcaContinentalDatos$Febrero + 
                     ArcaContinentalDatos$Marzo + ArcaContinentalDatos$Abril + 
                     ArcaContinentalDatos$Mayo + ArcaContinentalDatos$Junio)

#  mediana 
mediana_ventas <- median(ArcaContinentalDatos$Enero + ArcaContinentalDatos$Febrero + 
                         ArcaContinentalDatos$Marzo + ArcaContinentalDatos$Abril + 
                         ArcaContinentalDatos$Mayo + ArcaContinentalDatos$Junio)

# Mode
Mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}
moda_ventas <- Mode(ArcaContinentalDatos$Enero + ArcaContinentalDatos$Febrero + 
                    ArcaContinentalDatos$Marzo + ArcaContinentalDatos$Abril + 
                    ArcaContinentalDatos$Mayo + ArcaContinentalDatos$Junio)

print(paste("Media de las ventas del primer semestre:", media_ventas))
## [1] "Media de las ventas del primer semestre: 34.6962045666975"
print(paste("Mediana de las ventas del primer semestre:", mediana_ventas))
## [1] "Mediana de las ventas del primer semestre: 4"
print(paste("Moda de las ventas del primer semestre:", moda_ventas))
## [1] "Moda de las ventas del primer semestre: 0"

Tarea Colaborativa 2

Hallazgo 1: Ventas totales por CEDI y año

library(dplyr)


ArcaContinentalDatos <- ArcaContinentalDatos %>%
  mutate(Ventas_totales = rowSums(select(., Enero:Diciembre), na.rm = TRUE))


print(ArcaContinentalDatos)
## # A tibble: 466,508 × 27
##       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,498 more rows
## # ℹ 20 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>, Ventas_Primer_Semestre <dbl>,
## #   Ventas_totales <dbl>
ventas_totales_por_cedi_y_anio <- ArcaContinentalDatos %>%
  group_by(CEDI, Año) %>%
  summarise(Ventas_totales = sum(Enero + Febrero + Marzo + Abril + Mayo + Junio + Julio + Agosto + Septiembre + Octubre + Noviembre + Diciembre), .groups = 'drop') %>%
  arrange(desc(Ventas_totales))

df_hallazgo_1 <- as.data.frame(ventas_totales_por_cedi_y_anio)

Hallazgo 2: Mes con mayores ventas

mes_mayor_ventas <- ArcaContinentalDatos %>%
  summarise_at(vars(Enero:Diciembre), sum, na.rm = TRUE) %>%
  pivot_longer(cols = Enero:Diciembre, names_to = "Mes", values_to = "Ventas_totales") %>%
  top_n(1, Ventas_totales)

print(mes_mayor_ventas)
## # A tibble: 1 × 2
##   Mes   Ventas_totales
##   <chr>          <dbl>
## 1 Mayo         3139421
df_hallazgo_2 <- as.data.frame(mes_mayor_ventas)

Hallazgo 3: Tamaño de tienda con las mayores ventas promedio

ventas_promedio_por_tamanio <- ArcaContinentalDatos %>%
  group_by(Tamaño) %>%
  summarise(Ventas_promedio = mean(Ventas_totales, na.rm = TRUE)) %>%
  arrange(desc(Ventas_promedio)) %>%
  top_n(1, Ventas_promedio)

print(ventas_promedio_por_tamanio)
## # A tibble: 1 × 2
##   Tamaño   Ventas_promedio
##   <chr>              <dbl>
## 1 Familiar            114.
df_hallazgo_3 <- as.data.frame(ventas_promedio_por_tamanio)

Hallazgo 4: Comparación de ventas entre diferentes tipos de presentación de productos

ventas_por_presentacion <- ArcaContinentalDatos %>%
  group_by(Presentacion) %>%
  summarise(Ventas_totales = sum(Ventas_totales, na.rm = TRUE)) %>%
  arrange(desc(Ventas_totales))


print(ventas_por_presentacion)
## # A tibble: 56 × 2
##    Presentacion     Ventas_totales
##    <chr>                     <dbl>
##  1 2.5 Lts. Ret Pet        5829946
##  2 500 ml Ret              5633520
##  3 2.5 Lts. NR             2732352
##  4 1.5 Lts. Ret            2192569
##  5 500 ml NR Vidrio        2072196
##  6 2 Lts. NR               1628744
##  7 1.5 Lts. NR             1546595
##  8 1 Ltro. N.R.            1542171
##  9 600 ml NR               1151493
## 10 1.250 Lts NR             672038
## # ℹ 46 more rows
df_hallazgo_4 <- as.data.frame(ventas_por_presentacion)

Hallazgo 5: Marca mas vendida

top_Marca <- ArcaContinentalDatos %>%
  group_by(Marca) %>%
  summarise(Ventas_totales = sum(Ventas_totales, na.rm = TRUE)) %>%
  arrange(desc(Ventas_totales)) %>%
  slice(1)

print(top_Marca)
## # A tibble: 1 × 2
##   Marca     Ventas_totales
##   <chr>              <dbl>
## 1 Coca-Cola       21611127
df_Marca_mas_vendida <- data.frame(Marca = top_Marca$Marca, 
                                      Ventas_totales = top_Marca$Ventas_totales)

print(df_Marca_mas_vendida)
##       Marca Ventas_totales
## 1 Coca-Cola       21611127

Hallazgo 6: Tendencia de ventas a lo largo del año

ventas_por_mes <- ArcaContinentalDatos %>%
  summarise_at(vars(Enero:Diciembre), sum, na.rm = TRUE) %>%
  pivot_longer(cols = Enero:Diciembre, names_to = "Mes", values_to = "Ventas_totales")

print(ventas_por_mes)
## # A tibble: 12 × 2
##    Mes        Ventas_totales
##    <chr>               <dbl>
##  1 Enero             2309875
##  2 Febrero           2252870
##  3 Marzo             2672846
##  4 Abril             2795401
##  5 Mayo              3139421
##  6 Junio             3015644
##  7 Julio             2814366
##  8 Agosto            2908448
##  9 Septiembre        1691288
## 10 Octubre           1714075
## 11 Noviembre         1665560
## 12 Diciembre         1800018
df_hallazgo_6 <- as.data.frame(ventas_por_mes)

actividad individual 3

library(ggplot2)
library(tidyr)
library(dplyr)

Gráfico de barras para visualizar el total de ventas por mes y año

ArcaContinentalDatos_long <- ArcaContinentalDatos %>%
  pivot_longer(cols = Enero:Diciembre, names_to = "Mes", values_to = "Ventas_mes")

meses_ordenados <- c("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")
ArcaContinentalDatos_long$Mes <- factor(ArcaContinentalDatos_long$Mes, levels = meses_ordenados)

ventas_por_mes_y_anio <- ArcaContinentalDatos_long %>%
  group_by(Año, Mes) %>%
  summarise(Total_Ventas = sum(Ventas_mes))
## `summarise()` has grouped output by 'Año'. You can override using the `.groups`
## argument.
ggplot(ventas_por_mes_y_anio, aes(x = Mes, y = Total_Ventas, fill = factor(Año))) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(title = "Total de Ventas por Mes y Año",
       x = "Mes",
       y = "Total de Ventas",
       fill = "Año") +
  facet_wrap(~Año, nrow = 2) +  # Dividir el gráfico en múltiples paneles para cada año
  theme_minimal() +  # Utilizar un tema minimalista
  theme(axis.text.x = element_text(angle = 45, hjust = 1),  # Rotar etiquetas del eje x
        legend.position = "bottom")  # Mover la leyenda a la parte inferior

Tarea colaborativa 3

#Sebastián Fajardo A01412035 #André Castillo Pacheco A01552200 #Ana Cristina Treviño Sáenz A01233898

top 10 de marcas con mayor cantidad de ventas

top_10_marcas <- ArcaContinentalDatos %>%
  group_by(Marca) %>%
  summarise(Ventas_totales = sum(Ventas_totales)) %>%
  top_n(10, Ventas_totales) %>%
  arrange(desc(Ventas_totales))

colores <- rainbow(nrow(top_10_marcas))

ggplot(top_10_marcas, aes(x = reorder(Marca, Ventas_totales), y = Ventas_totales, fill = as.factor(Marca))) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = colores) +
  labs(title = "Top 10 de Ventas por Marca",
       x = "Marca",
       y = "Ventas totales",
       fill = "Marca") +
  facet_wrap(~ Marca, scales = "free") +  
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),  
        legend.position = "none")  

Gráfico de dispersión para mostrar la relación entre las ventas y el tamaño de la tienda

ggplot(ArcaContinentalDatos, aes(x = Tamaño, y = Ventas_totales)) +
  geom_point(color = "darkgreen") +
  labs(title = "Relación entre Ventas y Tamaño de Tienda",
       x = "Tamaño de Tienda",
       y = "Ventas_totales") +
  facet_wrap(~ Año, scales = "free") +  
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  

Gráfico de barras para mostrar las ventas totales por tamaño de cliente en la industria

ggplot(ArcaContinentalDatos, aes(x = `Tamaño Cte Industria`, y = Ventas_totales, fill = `Tamaño Cte Industria`)) +
  geom_bar(stat = "identity") +
  labs(title = "Ventas Totales por Tamaño de Cliente en la Industria",
       x = "Tamaño de Cliente en la Industria",
       y = "Ventas Totales") +
  facet_wrap(~ Año, scales = "free") +  
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  

Ventas por marca a traves de los años

ArcaContinentalDatos <- ArcaContinentalDatos %>%
  group_by(Año, Marca) %>%
  summarise(Ventas_totales = sum(Ventas_totales)) %>%
  arrange(Año, desc(Ventas_totales)) %>%
  mutate(Ventas_acumuladas = cumsum(Ventas_totales))
## `summarise()` has grouped output by 'Año'. You can override using the `.groups`
## argument.
top_marcas <- ArcaContinentalDatos %>%
  group_by(Marca) %>%
  summarise(Ventas_acumuladas = last(Ventas_acumuladas)) %>%
  arrange(desc(Ventas_acumuladas)) %>%
  top_n(10)
## Selecting by Ventas_acumuladas
ArcaContinentalDatos_filtrado <- ArcaContinentalDatos %>%
  filter(Marca %in% top_marcas$Marca)

ggplot(ArcaContinentalDatos_filtrado, aes(x = Año, y = Ventas_acumuladas, fill = Marca)) +
  geom_area() +
  labs(title = "Tendencia de Ventas por Marca a lo largo de los Años",
       x = "Año",
       y = "Ventas Acumuladas",
       fill = "Marca") +
  facet_wrap(~ Marca, scales = "free_y", nrow = 2) +  
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  

Ventas por cliente

ArcaContinentalDatos <- read_excel("Downloads/ArcaContinentalDatos.xlsx")
ArcaContinentalDatos <- replace(ArcaContinentalDatos, is.na(ArcaContinentalDatos), 0)
nas_por_columna <- colSums(is.na(ArcaContinentalDatos))
ArcaContinentalDatos <- ArcaContinentalDatos %>%
  mutate(Ventas_totales = rowSums(select(., Enero:Diciembre), na.rm = TRUE))
ventas_por_cliente <- ArcaContinentalDatos %>%
  group_by(Cliente) %>%
  summarise(Ventas_totales = sum(Ventas_totales)) %>%
  arrange(desc(Ventas_totales)) %>%
  top_n(10)
## Selecting by Ventas_totales
colores <- c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
              "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf")

ggplot(ventas_por_cliente, aes(x = reorder(Cliente, Ventas_totales), y = Ventas_totales, fill = Cliente)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = colores) +
  labs(title = "Top 10 Clientes por Ventas Totales",
       x = "Cliente",
       y = "Ventas Totales") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Actividad individual 4

ArcaContinentalDatos <- read_excel("Downloads/ArcaContinentalDatos.xlsx")
ArcaContinentalDatos <- replace(ArcaContinentalDatos, is.na(ArcaContinentalDatos), 0)
nas_por_columna <- colSums(is.na(ArcaContinentalDatos))
ArcaContinentalDatos <- ArcaContinentalDatos %>%
  mutate(Ventas_totales = rowSums(select(., Enero:Diciembre), na.rm = TRUE))

ventas_4567 <- ArcaContinentalDatos %>%
  filter(Cliente == "4567") %>%
  group_by(Año) %>%
  summarise(ventas_totales = sum(Ventas_totales))

ggplot(ventas_4567, aes(x = Año, y = ventas_totales)) +
  geom_point() +  
  labs(title = "Ventas totales del Cliente 4567 por Año", 
       x = "Año", 
       y = "Ventas totales") + 
  theme_minimal() 

modelo <- lm(ventas_totales ~ Año, data = ventas_4567)

summary(modelo)
## 
## 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
# Ecuación
# y - 48918677 - 24174 * Año

#R cuadrada ajustada
# 77%

nuevos_datos <- data.frame(Año = 2020:2025)

predicciones <- predict(modelo, nuevos_datos)

datos_completos <- rbind(
  cbind(ventas_4567, Tipo = "Datos reales"),
  cbind(data.frame(Año = 2020:2025, ventas_totales = predicciones), Tipo = "Predicciones")
)

ggplot(datos_completos, aes(x = Año, y = ventas_totales, color = Tipo)) +
  geom_line() +  
  geom_point() +  
  labs(title = "Ventas Totales (2017-2025)", x = "Año", y = "Ventas Totales", color = "Tipo")

Tarea colaborativa 4

Sebastián Fajardo André Castillo Pacheco Ana Cristina Treviño Sáenz

ventas_6626 <- ArcaContinentalDatos %>%
  filter(Cliente == "6626") %>%
  group_by(Año) %>%
  summarise(ventas_totales = sum(Ventas_totales))

modelo_6626 <- lm(ventas_totales ~ Año, data = ventas_6626)

summary(modelo_6626)
## 
## 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
# Ecuación
# y - 55208195 - 27316 * Año
#R cuadrada ajustada
# 93%
nuevos_datos_6626 <- data.frame(Año = 2020:2025)
predicciones_6626 <- predict(modelo_6626, nuevos_datos_6626)

datos_completos_6626 <- rbind(
  cbind(ventas_6626, Tipo = "Datos reales"),
  cbind(data.frame(Año = 2020:2025, ventas_totales = predicciones_6626), Tipo = "Predicciones")
)

ggplot(datos_completos_6626, aes(x = Año, y = ventas_totales, color = Tipo)) +
  geom_line() +  
  geom_point() +  
  labs(title = "Ventas Totales (2017-2025) - Cliente 6626", x = "Año", y = "Ventas Totales", color = "Tipo") +
  theme_minimal()

ventas_por_anio <- ArcaContinentalDatos %>%
  group_by(Año) %>%
  summarise(Ventas_totales = sum(Ventas_totales))


modelo_regresion <- lm(Ventas_totales ~ Año, data = ventas_por_anio)

summary(modelo_regresion)
## 
## Call:
## lm(formula = Ventas_totales ~ Año, data = ventas_por_anio)
## 
## Residuals:
##       1       2       3       4 
##   47304   48410 -238732  143018 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)  
## (Intercept) -1.501e+09  1.827e+08  -8.217   0.0145 *
## Año          7.479e+05  9.057e+04   8.257   0.0144 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 202500 on 2 degrees of freedom
## Multiple R-squared:  0.9715, Adjusted R-squared:  0.9573 
## F-statistic: 68.18 on 1 and 2 DF,  p-value: 0.01435
# Ecuación
# y + 1501000000 - 747900 * Año
#R cuadrada ajustada
# 96%

nuevos_anios <- data.frame(Año = 2020:2025)
predicciones <- predict(modelo_regresion, nuevos_anios)


predicciones_df <- data.frame(Año = nuevos_anios$Año, Ventas_totales = predicciones)


datos_completos <- rbind(
  cbind(ventas_por_anio, Tipo = "Datos reales"),
  cbind(predicciones_df, Tipo = "Predicciones")
)


ggplot(datos_completos, aes(x = Año, y = Ventas_totales, color = Tipo)) +
  geom_line() +
  geom_point() +
  labs(title = "Ventas Totales por Año",
       x = "Año",
       y = "Ventas Totales",
       color = "Tipo") +
  theme_minimal()

ventas_por_anio <- ArcaContinentalDatos %>%
  filter(CEDI == "Suc. Belenes") %>%
  group_by(Año) %>%
  summarise(Ventas_totales = sum(Ventas_totales))


modelo_regresion <- lm(Ventas_totales ~ Año, data = ventas_por_anio)


summary(modelo_regresion)
## 
## Call:
## lm(formula = Ventas_totales ~ Año, data = ventas_por_anio)
## 
## Residuals:
##       1       2       3       4 
##  211552   89252 -813160  512356 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.647e+09  6.304e+08  -2.612    0.121
## Año          8.174e+05  3.125e+05   2.616    0.120
## 
## Residual standard error: 698700 on 2 degrees of freedom
## Multiple R-squared:  0.7738, Adjusted R-squared:  0.6607 
## F-statistic: 6.842 on 1 and 2 DF,  p-value: 0.1203
# Ecuación
# y - 1647000000 - 817400 * Año
#R cuadrada ajustada
# 66%
nuevos_datos
##    Año
## 1 2020
## 2 2021
## 3 2022
## 4 2023
## 5 2024
## 6 2025
predicciones <- predict(modelo_regresion)


ggplot(ventas_por_anio, aes(x = Año, y = Ventas_totales)) +
  geom_point() +
  geom_line(aes(y = predicciones), color = "red") +
  labs(title = "Ventas de la Sucursal Belenes por Año",
       x = "Año",
       y = "Ventas Totales")

ventas_por_anio_ABARR <- ArcaContinentalDatos %>%
  filter(Nombre == "ABARR") %>%
  group_by(Año) %>%
  summarise(Ventas_totales = sum(Ventas_totales))

modelo_regresion_ABARR <- lm(Ventas_totales ~ Año, data = ventas_por_anio_ABARR)


summary(modelo_regresion_ABARR)
## 
## Call:
## lm(formula = Ventas_totales ~ Año, data = ventas_por_anio_ABARR)
## 
## Residuals:
##       1       2       3       4 
##  108267  -39727 -245346  176806 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)
## (Intercept) -428874922  206491069  -2.077    0.173
## Año             213083     102350   2.082    0.173
## 
## Residual standard error: 228900 on 2 degrees of freedom
## Multiple R-squared:  0.6843, Adjusted R-squared:  0.5264 
## F-statistic: 4.334 on 1 and 2 DF,  p-value: 0.1728
# Ecuación
# y - 428874922 - 213083 * Año
#R cuadrada ajustada
#53%
predicciones_ABARR <- predict(modelo_regresion_ABARR, newdata = data.frame(Año = 2020:2025))


pronostico_df <- data.frame(Año = 2020:2025, Ventas_totales = predicciones_ABARR)

ggplot() +
  geom_point(data = ventas_por_anio_ABARR, aes(x = Año, y = Ventas_totales)) +
  geom_line(data = pronostico_df, aes(x = Año, y = Ventas_totales, color = "Pronóstico")) +
  geom_smooth(data = ventas_por_anio_ABARR, aes(x = Año, y = Ventas_totales), method = "lm", se = FALSE, color = "blue") +
  labs(title = "Ventas de ABARR por Año",
       x = "Año",
       y = "Ventas Totales",
       color = "Tipo")
## `geom_smooth()` using formula = 'y ~ x'

      ventas_por_anio_MARTI <- ArcaContinentalDatos %>%
  filter(Nombre == "MARTI") %>%
  group_by(Año) %>%
  summarise(Ventas_totales = sum(Ventas_totales))

modelo_regresion <- lm(Ventas_totales ~ Año, data = ventas_por_anio_MARTI)

summary(modelo_regresion)
## 
## Call:
## lm(formula = Ventas_totales ~ Año, data = ventas_por_anio_MARTI)
## 
## Residuals:
##     1     2     3     4 
## -4843  5009  4510 -4677 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)
## (Intercept) -11017842    6077974  -1.813    0.212
## Año              5494       3013   1.824    0.210
## 
## Residual standard error: 6736 on 2 degrees of freedom
## Multiple R-squared:  0.6245, Adjusted R-squared:  0.4367 
## F-statistic: 3.326 on 1 and 2 DF,  p-value: 0.2098
# Ecuación
# y - 11017842 - 5494 * Año
#R cuadrada ajustada
#44%
nuevos_anios <- data.frame(Año = 2020:2025)
predicciones <- predict(modelo_regresion, nuevos_anios)


pronostico_df <- data.frame(Año = nuevos_anios$Año, Ventas_totales = predicciones)

ggplot() +
  geom_point(data = ventas_por_anio_MARTI, aes(x = Año, y = Ventas_totales, color = "Datos reales")) +
  geom_point(data = pronostico_df, aes(x = Año, y = Ventas_totales, color = "Pronóstico"), shape = 16, size = 3) +
  geom_smooth(data = ventas_por_anio_MARTI, aes(x = Año, y = Ventas_totales), method = "lm", se = FALSE, color = "blue") +
  labs(title = "Ventas de MARTI por Año",
       x = "Año",
       y = "Ventas Totales",
       color = "Tipo") +
  scale_color_manual(values = c("blue", "red")) 
## `geom_smooth()` using formula = 'y ~ x'

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 

#En términos generales, las ventas experimentaron un aumento en el año 2019, aunque cada segmento mostró un comportamiento diferente. Este incremento en las ventas puede atribuirse a estrategias de marketing mejoradas y al lanzamiento de nuevos productos. En el año 2018, las ventas de Coca-Cola aumentaron en 100,000 unidades entre los meses de febrero y diciembre, mientras que las ventas de aguas isotónicas permanecieron estables, sin registrar cambios significativos.
ventas_totales_tam_cliente <- ArcaContinentalDatos %>%
  filter(Año == 2019) %>%
  group_by(`Tamaño Cte Industria`) %>%
  summarise(Ventas_totales = sum(Ventas_totales)) %>%
  filter(Ventas_totales != 0)

ggplot(ventas_totales_tam_cliente, aes(x=`Tamaño Cte Industria`, y=Ventas_totales)) +
  geom_bar(stat="identity", fill="skyblue") +
  labs(x="Tamaño de Cliente", y="Ventas Totales (Qty)", title="Ventas totales por tamaño de cliente")

#El incremento en las ventas es similar independientemente de los tamaños de los clientes. Dado que todos los negocios operan los mismos días y están ubicados en la misma ciudad (Guadalajara), los factores externos que afectan las ventas tienen un impacto casi idéntico en todos. Se observa que el mes de mayo de 2019 fue el de mayor venta en todos los tamaños de cliente, mientras que el primer bimestre fue el periodo más bajo, también para todos los tamaños de cliente.
ArcaContinentalDatos_long <- ArcaContinentalDatos %>%
  gather(key = "Mes", value = "Ventas", Enero:Diciembre) %>%
  mutate(Mes = factor(Mes, levels = month.name))  # Reordena los meses para que aparezcan en el orden correcto

# Ahora calcula las ventas totales por marca y mes
ventas_totales_marca_mes <- ArcaContinentalDatos_long %>%
  filter(Año == 2019) %>%
  filter(Marca %in% c("Coca-Cola", "Valle Frut", "Ciel Agua Purificada", "Coca-Cola Light")) %>%
  group_by(Marca, Mes) %>%
  summarise(Ventas_Totales = sum(Ventas))
## `summarise()` has grouped output by 'Marca'. You can override using the
## `.groups` argument.
# Graficar las ventas totales por marca y mes
ggplot(ventas_totales_marca_mes, aes(x = Mes, y = Ventas_Totales, fill = Marca)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(x = "Mes", y = "Ventas Totales (QTY)", title = "Ventas totales por marca y mes")

#El patrón de ventas es consistente entre las diversas marcas a lo largo de los meses, sin embargo, algunas marcas superan significativamente a otras en términos de volumen de ventas. Los meses con temperaturas más altas tienden a registrar mayores ventas de bebidas, y las marcas más reconocidas son las preferidas por los consumidores. En general, mayo de 2019 destaca como el mes con mayores ventas para todas las marcas, siendo Coca-Cola la marca líder en ventas durante este período.
# Verificar si la columna "Segmento_Det" existe en tus datos
if ("Segmento_Det" %in% colnames(ArcaContinentalDatos)) {
  print("La columna 'Segmento_Det' existe en tus datos.")
} else {
  print("La columna 'Segmento_Det' NO existe en tus datos.")
}
## [1] "La columna 'Segmento_Det' NO existe en tus datos."
ventas_totales_envase <- ArcaContinentalDatos %>%
  filter(Retornable_NR == "Retornable") %>%
  filter(Año %in% c(2018, 2019)) %>%
  pivot_longer(cols = c(Enero:Diciembre),
               names_to = "Mes",
               values_to = "Ventas_Totales") %>%
  group_by(Año, Mes) %>%
  summarise(Ventas_Totales = sum(Ventas_Totales)) %>%
  ungroup()
## `summarise()` has grouped output by 'Año'. You can override using the `.groups`
## argument.
ggplot(ventas_totales_envase, aes(x = Mes, y = Ventas_Totales, group = Año, color = as.factor(Año))) +
  geom_line() +
  geom_point() +
  labs(x = "Mes", y = "Ventas Totales (QTY)", title = "Ventas totales de Envases Retornables por Mes", color = "Año")

#La venta de productos en envase retornable ha experimentado un notable aumento en los últimos dos años. Este incremento puede atribuirse en parte a las exitosas campañas de conciencia ambiental que han generado una mayor aceptación y preferencia por opciones menos dañinas para el ecosistema. Desde 2017 hasta 2018, se observó un ligero incremento en las ventas de envases retornables, lo cual sugiere una creciente tendencia hacia la sostenibilidad. Sin embargo, el aumento fue aún más significativo entre 2018 y 2019, lo cual puede ser indicativo de un mayor número de tiendas adoptando el proyecto Siglo XXI de Arca Continental o de un incremento general en las ventas de productos, tanto retornables como no retornables, en todas las tiendas. Este fenómeno refleja una creciente conciencia ambiental y una preferencia del consumidor por opciones que promuevan la conservación del medio ambiente
#En 2018, las ventas de agua purificada no aumentaron en comparación con las de refrescos o bebidas isotónicas. La preferencia por los refrescos puede atribuirse a su sabor dulce y a la percepción de un mayor valor agregado. Por ejemplo, Coca-Cola vendió hasta 450,000 unidades en su mes más alto, mientras que las ventas totales de agua purificada no superaron las 50,000 unidades en el mismo período.
#¿Puede decirse que la venta mensual de agua está relacionada con la venta mensual de refrescos en los últimos 4 años?

#Las ventas de agua y refrescos muestran un aumento constante durante los mismos meses y a lo largo de los años. Sin embargo, no podemos concluir que el aumento en las ventas de uno cause el incremento en las ventas del otro. Factores como los meses cálidos y el crecimiento poblacional pueden contribuir a este aumento en la demanda de bebidas. La gráfica revela un incremento año tras año en las ventas de agua y refrescos, reflejando posibles cambios en las preferencias del consumidor y en el mercado.
#¿A cuánto ascienden las ventas esperadas para el 2020 en la Coca Cola de 500 ml NR Vidrio?
library(forecast)
## Warning: package 'forecast' was built under R version 4.2.3
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
ventas_coca_vidrio <- ArcaContinentalDatos %>%
  filter(Marca == "Coca-Cola" & Presentacion == "500 ml NR Vidrio") %>%
  group_by(Año) %>%
  summarise(Ventas_totales = sum(Ventas_totales)) %>%
  filter(Ventas_totales != 0)

ts_ventas <- ts(data = ventas_coca_vidrio$Ventas_totales, start = c(2017, 1), frequency = 12)


arima_model <- arima(ts_ventas, order = c(1, 1, 1))


pronostico_2020 <- forecast(arima_model, h = 12)


ventas_esperadas_2020 <- sum(pronostico_2020$mean)
ventas_esperadas_2020
## [1] 4964632
plot(pronostico_2020, main = "Pronóstico de Ventas de Coca-Cola 500 ml NR Vidrio hasta 2020",
     xlab = "Año", ylab = "Ventas (Qty)", xlim = c(2017, 2020))
lines(ts_ventas, col = "blue")  # Agregar datos históricos
legend("topright", legend = c("Datos Históricos", "Pronóstico"), col = c("blue", "red"), lty = 1)

LS0tCnRpdGxlOiAiRXZpZGVuY2lhIgphdXRob3I6ICJTZWJhc3Rpw6FuIEZhamFyZG8iCmRhdGU6ICIyMDI0LTAzLTE5IgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgIHRvYzogVFJVRQogICB0b2NfZmxvYXQ6IFRSVUUKICAgY29kZV9kb3dubG9hZDogVFJVRQogICB0aGVtZTogY29zbW8KLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMjIFIgTWFya2Rvd24KCiFbXSgpCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpyZWQ7Ij5JbnN0YWxhciBwYXF1ZXRlcyB5IGxsYW1hciBsaWJyZXJpYXM8L3NwYW4+CmBgYHtyIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShnZ3Bsb3QyKQpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOnJlZDsiPkFjdGl2aWRhZCBJbmRpdmlkdWFsIDI8L3NwYW4+CgojIElkZW50aWZpY2FyIGVuIGVsIGRhdGFmcmFtZSBkZSBsYSBTaXR1YWNpw7NuIFByb2JsZW1hIDIgbGFzIGVzdHJ1Y3R1cmFzIGRlIGRhdG9zIHF1ZSBpbnZlc3RpZ2FzdGUgZW4gdHUgdGFyZWEgY29sYWJvcmF0aXZhIDEgKFZlY3RvcmVzLCBMaXN0YXMsIEZhY3RvcmVzLCBNYXRyaWNlcykKYGBge3Igd2FybmluZz1GQUxTRX0KQXJjYUNvbnRpbmVudGFsRGF0b3MgPC0gcmVhZF9leGNlbCgiRG93bmxvYWRzL0FyY2FDb250aW5lbnRhbERhdG9zLnhsc3giKQpWaWV3KEFyY2FDb250aW5lbnRhbERhdG9zKQpzdHIoQXJjYUNvbnRpbmVudGFsRGF0b3MpCgpgYGAKIyDCv0VsIGRhdGFmcmFtZSB0aWVuZSBOQXM/CmBgYHtyfQpuYXNfcG9yX2NvbHVtbmEgPC0gY29sU3Vtcyhpcy5uYShBcmNhQ29udGluZW50YWxEYXRvcykpCnByaW50KG5hc19wb3JfY29sdW1uYSkKYGBgCiMgwr9FbCBkYXRhZnJhbWUgdGllbmUgZGF0b3MgcGVyZGlkb3M/CmBgYHtyfQpBcmNhQ29udGluZW50YWxEYXRvcyA8LSByZXBsYWNlKEFyY2FDb250aW5lbnRhbERhdG9zLCBpcy5uYShBcmNhQ29udGluZW50YWxEYXRvcyksIDApCm5hc19wb3JfY29sdW1uYSA8LSBjb2xTdW1zKGlzLm5hKEFyY2FDb250aW5lbnRhbERhdG9zKSkKcHJpbnQobmFzX3Bvcl9jb2x1bW5hKQpgYGAKIyBkZXRlY3RhciB2YWxvcmVzIGF0w61waWNvcwpgYGB7cn0KYm94cGxvdChBcmNhQ29udGluZW50YWxEYXRvcyRFbmVybykKCiNlbGltaW5hciByZW5nbMOzbiBkZSB0b3RhbGVzCkFyY2FDb250aW5lbnRhbERhdG9zPC0gQXJjYUNvbnRpbmVudGFsRGF0b3NbQXJjYUNvbnRpbmVudGFsRGF0b3MkRW5lcm8gPDYwMDAsIF0KYGBgCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQoKdmVudGFzX2VuZXJvX2FfanVuaW8gPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgc2VsZWN0KENFREksIEVuZXJvOkp1bmlvKQoKCnByaW50KHZlbnRhc19lbmVyb19hX2p1bmlvKQpgYGAKYGBge3J9Cm1vdmltaWVudG9zX2dyYW5kZXMgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgZmlsdGVyKGBUYW1hw7FvIEN0ZSBJbmR1c3RyaWFgID09ICJHcmFuZGUiKQoKcHJpbnQobW92aW1pZW50b3NfZ3JhbmRlcykKCgpgYGAKYGBge3J9CkFyY2FDb250aW5lbnRhbERhdG9zX29yZGVuYWRvIDwtIEFyY2FDb250aW5lbnRhbERhdG9zICU+JQogIGFycmFuZ2UoQ0VESSwgTWFyY2EsIFByZXNlbnRhY2lvbikKCnByaW50KEFyY2FDb250aW5lbnRhbERhdG9zX29yZGVuYWRvKQoKYGBgCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQoKQXJjYUNvbnRpbmVudGFsRGF0b3MgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgcmVuYW1lKFN1Yl90ZXJyaXRvcmlvID0gYFN1YiBUZXJyaXRvcmlvYCkKCnN0cihBcmNhQ29udGluZW50YWxEYXRvcykKYGBgCmBgYHtyfQpBcmNhQ29udGluZW50YWxEYXRvcyA8LSBBcmNhQ29udGluZW50YWxEYXRvcyAlPiUKICBtdXRhdGUoVmVudGFzX1ByaW1lcl9TZW1lc3RyZSA9IEVuZXJvICsgRmVicmVybyArIE1hcnpvICsgQWJyaWwgKyBNYXlvICsgSnVuaW8pCgp2ZW50YXNfcG9yX21hcmNhX3ByaW1lcl9zZW1lc3RyZSA8LSBBcmNhQ29udGluZW50YWxEYXRvcyAlPiUKICBncm91cF9ieShNYXJjYSkgJT4lCiAgc3VtbWFyaXplKFZlbnRhc19QcmltZXJfU2VtZXN0cmUgPSBzdW0oVmVudGFzX1ByaW1lcl9TZW1lc3RyZSkpCgpwcmludCh2ZW50YXNfcG9yX21hcmNhX3ByaW1lcl9zZW1lc3RyZSkKYGBgCmBgYHtyfQptZWRpYV92ZW50YXMgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgZ3JvdXBfYnkoTWFyY2EsIFByZXNlbnRhY2lvbiwgVGFtYcOxbykgJT4lCiAgc3VtbWFyaXNlKE1lZGlhX1ZlbnRhc19QcmltZXJfU2VtZXN0cmUgPSBtZWFuKEVuZXJvICsgRmVicmVybyArIE1hcnpvICsgQWJyaWwgKyBNYXlvICsgSnVuaW8pKQoKcHJpbnQobWVkaWFfdmVudGFzKQpgYGAKYGBge3J9Cm1lZGlhX3ZlbnRhcyA8LSBtZWFuKEFyY2FDb250aW5lbnRhbERhdG9zJEVuZXJvICsgQXJjYUNvbnRpbmVudGFsRGF0b3MkRmVicmVybyArIAogICAgICAgICAgICAgICAgICAgICBBcmNhQ29udGluZW50YWxEYXRvcyRNYXJ6byArIEFyY2FDb250aW5lbnRhbERhdG9zJEFicmlsICsgCiAgICAgICAgICAgICAgICAgICAgIEFyY2FDb250aW5lbnRhbERhdG9zJE1heW8gKyBBcmNhQ29udGluZW50YWxEYXRvcyRKdW5pbykKCiMgIG1lZGlhbmEgCm1lZGlhbmFfdmVudGFzIDwtIG1lZGlhbihBcmNhQ29udGluZW50YWxEYXRvcyRFbmVybyArIEFyY2FDb250aW5lbnRhbERhdG9zJEZlYnJlcm8gKyAKICAgICAgICAgICAgICAgICAgICAgICAgIEFyY2FDb250aW5lbnRhbERhdG9zJE1hcnpvICsgQXJjYUNvbnRpbmVudGFsRGF0b3MkQWJyaWwgKyAKICAgICAgICAgICAgICAgICAgICAgICAgIEFyY2FDb250aW5lbnRhbERhdG9zJE1heW8gKyBBcmNhQ29udGluZW50YWxEYXRvcyRKdW5pbykKCiMgTW9kZQpNb2RlIDwtIGZ1bmN0aW9uKHgpIHsKICB1eCA8LSB1bmlxdWUoeCkKICB1eFt3aGljaC5tYXgodGFidWxhdGUobWF0Y2goeCwgdXgpKSldCn0KbW9kYV92ZW50YXMgPC0gTW9kZShBcmNhQ29udGluZW50YWxEYXRvcyRFbmVybyArIEFyY2FDb250aW5lbnRhbERhdG9zJEZlYnJlcm8gKyAKICAgICAgICAgICAgICAgICAgICBBcmNhQ29udGluZW50YWxEYXRvcyRNYXJ6byArIEFyY2FDb250aW5lbnRhbERhdG9zJEFicmlsICsgCiAgICAgICAgICAgICAgICAgICAgQXJjYUNvbnRpbmVudGFsRGF0b3MkTWF5byArIEFyY2FDb250aW5lbnRhbERhdG9zJEp1bmlvKQoKcHJpbnQocGFzdGUoIk1lZGlhIGRlIGxhcyB2ZW50YXMgZGVsIHByaW1lciBzZW1lc3RyZToiLCBtZWRpYV92ZW50YXMpKQpwcmludChwYXN0ZSgiTWVkaWFuYSBkZSBsYXMgdmVudGFzIGRlbCBwcmltZXIgc2VtZXN0cmU6IiwgbWVkaWFuYV92ZW50YXMpKQpwcmludChwYXN0ZSgiTW9kYSBkZSBsYXMgdmVudGFzIGRlbCBwcmltZXIgc2VtZXN0cmU6IiwgbW9kYV92ZW50YXMpKQpgYGAKIyA8c3BhbiBzdHlsZT0iY29sb3I6cmVkOyI+VGFyZWEgQ29sYWJvcmF0aXZhIDI8L3NwYW4+CiMgSGFsbGF6Z28gMTogVmVudGFzIHRvdGFsZXMgcG9yIENFREkgeSBhw7FvCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQoKCkFyY2FDb250aW5lbnRhbERhdG9zIDwtIEFyY2FDb250aW5lbnRhbERhdG9zICU+JQogIG11dGF0ZShWZW50YXNfdG90YWxlcyA9IHJvd1N1bXMoc2VsZWN0KC4sIEVuZXJvOkRpY2llbWJyZSksIG5hLnJtID0gVFJVRSkpCgoKcHJpbnQoQXJjYUNvbnRpbmVudGFsRGF0b3MpCmBgYAoKYGBge3J9CnZlbnRhc190b3RhbGVzX3Bvcl9jZWRpX3lfYW5pbyA8LSBBcmNhQ29udGluZW50YWxEYXRvcyAlPiUKICBncm91cF9ieShDRURJLCBBw7FvKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX3RvdGFsZXMgPSBzdW0oRW5lcm8gKyBGZWJyZXJvICsgTWFyem8gKyBBYnJpbCArIE1heW8gKyBKdW5pbyArIEp1bGlvICsgQWdvc3RvICsgU2VwdGllbWJyZSArIE9jdHVicmUgKyBOb3ZpZW1icmUgKyBEaWNpZW1icmUpLCAuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUKICBhcnJhbmdlKGRlc2MoVmVudGFzX3RvdGFsZXMpKQoKZGZfaGFsbGF6Z29fMSA8LSBhcy5kYXRhLmZyYW1lKHZlbnRhc190b3RhbGVzX3Bvcl9jZWRpX3lfYW5pbykKYGBgCiMgSGFsbGF6Z28gMjogTWVzIGNvbiBtYXlvcmVzIHZlbnRhcwpgYGB7cn0KCm1lc19tYXlvcl92ZW50YXMgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgc3VtbWFyaXNlX2F0KHZhcnMoRW5lcm86RGljaWVtYnJlKSwgc3VtLCBuYS5ybSA9IFRSVUUpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gRW5lcm86RGljaWVtYnJlLCBuYW1lc190byA9ICJNZXMiLCB2YWx1ZXNfdG8gPSAiVmVudGFzX3RvdGFsZXMiKSAlPiUKICB0b3BfbigxLCBWZW50YXNfdG90YWxlcykKCnByaW50KG1lc19tYXlvcl92ZW50YXMpCgoKZGZfaGFsbGF6Z29fMiA8LSBhcy5kYXRhLmZyYW1lKG1lc19tYXlvcl92ZW50YXMpCmBgYAoKIyBIYWxsYXpnbyAzOiBUYW1hw7FvIGRlIHRpZW5kYSBjb24gbGFzIG1heW9yZXMgdmVudGFzIHByb21lZGlvCgpgYGB7cn0KCnZlbnRhc19wcm9tZWRpb19wb3JfdGFtYW5pbyA8LSBBcmNhQ29udGluZW50YWxEYXRvcyAlPiUKICBncm91cF9ieShUYW1hw7FvKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX3Byb21lZGlvID0gbWVhbihWZW50YXNfdG90YWxlcywgbmEucm0gPSBUUlVFKSkgJT4lCiAgYXJyYW5nZShkZXNjKFZlbnRhc19wcm9tZWRpbykpICU+JQogIHRvcF9uKDEsIFZlbnRhc19wcm9tZWRpbykKCnByaW50KHZlbnRhc19wcm9tZWRpb19wb3JfdGFtYW5pbykKCmRmX2hhbGxhemdvXzMgPC0gYXMuZGF0YS5mcmFtZSh2ZW50YXNfcHJvbWVkaW9fcG9yX3RhbWFuaW8pCmBgYAojIEhhbGxhemdvIDQ6IENvbXBhcmFjacOzbiBkZSB2ZW50YXMgZW50cmUgZGlmZXJlbnRlcyB0aXBvcyBkZSBwcmVzZW50YWNpw7NuIGRlIHByb2R1Y3RvcwpgYGB7cn0KCnZlbnRhc19wb3JfcHJlc2VudGFjaW9uIDwtIEFyY2FDb250aW5lbnRhbERhdG9zICU+JQogIGdyb3VwX2J5KFByZXNlbnRhY2lvbikgJT4lCiAgc3VtbWFyaXNlKFZlbnRhc190b3RhbGVzID0gc3VtKFZlbnRhc190b3RhbGVzLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBhcnJhbmdlKGRlc2MoVmVudGFzX3RvdGFsZXMpKQoKCnByaW50KHZlbnRhc19wb3JfcHJlc2VudGFjaW9uKQoKCmRmX2hhbGxhemdvXzQgPC0gYXMuZGF0YS5mcmFtZSh2ZW50YXNfcG9yX3ByZXNlbnRhY2lvbikKYGBgCiMgSGFsbGF6Z28gNTogTWFyY2EgbWFzIHZlbmRpZGEKYGBge3J9CnRvcF9NYXJjYSA8LSBBcmNhQ29udGluZW50YWxEYXRvcyAlPiUKICBncm91cF9ieShNYXJjYSkgJT4lCiAgc3VtbWFyaXNlKFZlbnRhc190b3RhbGVzID0gc3VtKFZlbnRhc190b3RhbGVzLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBhcnJhbmdlKGRlc2MoVmVudGFzX3RvdGFsZXMpKSAlPiUKICBzbGljZSgxKQoKcHJpbnQodG9wX01hcmNhKQoKZGZfTWFyY2FfbWFzX3ZlbmRpZGEgPC0gZGF0YS5mcmFtZShNYXJjYSA9IHRvcF9NYXJjYSRNYXJjYSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVmVudGFzX3RvdGFsZXMgPSB0b3BfTWFyY2EkVmVudGFzX3RvdGFsZXMpCgpwcmludChkZl9NYXJjYV9tYXNfdmVuZGlkYSkKYGBgCgoKIyBIYWxsYXpnbyA2OiBUZW5kZW5jaWEgZGUgdmVudGFzIGEgbG8gbGFyZ28gZGVsIGHDsW8KYGBge3J9CnZlbnRhc19wb3JfbWVzIDwtIEFyY2FDb250aW5lbnRhbERhdG9zICU+JQogIHN1bW1hcmlzZV9hdCh2YXJzKEVuZXJvOkRpY2llbWJyZSksIHN1bSwgbmEucm0gPSBUUlVFKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IEVuZXJvOkRpY2llbWJyZSwgbmFtZXNfdG8gPSAiTWVzIiwgdmFsdWVzX3RvID0gIlZlbnRhc190b3RhbGVzIikKCnByaW50KHZlbnRhc19wb3JfbWVzKQoKZGZfaGFsbGF6Z29fNiA8LSBhcy5kYXRhLmZyYW1lKHZlbnRhc19wb3JfbWVzKQpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOnJlZDsiPmFjdGl2aWRhZCBpbmRpdmlkdWFsIDM8L3NwYW4+CmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZHBseXIpCmBgYAojIEdyw6FmaWNvIGRlIGJhcnJhcyBwYXJhIHZpc3VhbGl6YXIgZWwgdG90YWwgZGUgdmVudGFzIHBvciBtZXMgeSBhw7FvCmBgYHtyfQpBcmNhQ29udGluZW50YWxEYXRvc19sb25nIDwtIEFyY2FDb250aW5lbnRhbERhdG9zICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gRW5lcm86RGljaWVtYnJlLCBuYW1lc190byA9ICJNZXMiLCB2YWx1ZXNfdG8gPSAiVmVudGFzX21lcyIpCgptZXNlc19vcmRlbmFkb3MgPC0gYygiRW5lcm8iLCAiRmVicmVybyIsICJNYXJ6byIsICJBYnJpbCIsICJNYXlvIiwgIkp1bmlvIiwgIkp1bGlvIiwgIkFnb3N0byIsICJTZXB0aWVtYnJlIiwgIk9jdHVicmUiLCAiTm92aWVtYnJlIiwgIkRpY2llbWJyZSIpCkFyY2FDb250aW5lbnRhbERhdG9zX2xvbmckTWVzIDwtIGZhY3RvcihBcmNhQ29udGluZW50YWxEYXRvc19sb25nJE1lcywgbGV2ZWxzID0gbWVzZXNfb3JkZW5hZG9zKQoKdmVudGFzX3Bvcl9tZXNfeV9hbmlvIDwtIEFyY2FDb250aW5lbnRhbERhdG9zX2xvbmcgJT4lCiAgZ3JvdXBfYnkoQcOxbywgTWVzKSAlPiUKICBzdW1tYXJpc2UoVG90YWxfVmVudGFzID0gc3VtKFZlbnRhc19tZXMpKQpnZ3Bsb3QodmVudGFzX3Bvcl9tZXNfeV9hbmlvLCBhZXMoeCA9IE1lcywgeSA9IFRvdGFsX1ZlbnRhcywgZmlsbCA9IGZhY3RvcihBw7FvKSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBkZSBWZW50YXMgcG9yIE1lcyB5IEHDsW8iLAogICAgICAgeCA9ICJNZXMiLAogICAgICAgeSA9ICJUb3RhbCBkZSBWZW50YXMiLAogICAgICAgZmlsbCA9ICJBw7FvIikgKwogIGZhY2V0X3dyYXAofkHDsW8sIG5yb3cgPSAyKSArICAjIERpdmlkaXIgZWwgZ3LDoWZpY28gZW4gbcO6bHRpcGxlcyBwYW5lbGVzIHBhcmEgY2FkYSBhw7FvCiAgdGhlbWVfbWluaW1hbCgpICsgICMgVXRpbGl6YXIgdW4gdGVtYSBtaW5pbWFsaXN0YQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksICAjIFJvdGFyIGV0aXF1ZXRhcyBkZWwgZWplIHgKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgICMgTW92ZXIgbGEgbGV5ZW5kYSBhIGxhIHBhcnRlIGluZmVyaW9yCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6cmVkOyI+VGFyZWEgY29sYWJvcmF0aXZhIDM8L3NwYW4+CiNTZWJhc3Rpw6FuIEZhamFyZG8gQTAxNDEyMDM1CiNBbmRyw6kgQ2FzdGlsbG8gUGFjaGVjbyBBMDE1NTIyMDAKI0FuYSBDcmlzdGluYSBUcmV2acOxbyBTw6FlbnogQTAxMjMzODk4CgojICB0b3AgMTAgZGUgbWFyY2FzIGNvbiBtYXlvciBjYW50aWRhZCBkZSB2ZW50YXMKYGBge3J9Cgp0b3BfMTBfbWFyY2FzIDwtIEFyY2FDb250aW5lbnRhbERhdG9zICU+JQogIGdyb3VwX2J5KE1hcmNhKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX3RvdGFsZXMgPSBzdW0oVmVudGFzX3RvdGFsZXMpKSAlPiUKICB0b3BfbigxMCwgVmVudGFzX3RvdGFsZXMpICU+JQogIGFycmFuZ2UoZGVzYyhWZW50YXNfdG90YWxlcykpCgpjb2xvcmVzIDwtIHJhaW5ib3cobnJvdyh0b3BfMTBfbWFyY2FzKSkKCmdncGxvdCh0b3BfMTBfbWFyY2FzLCBhZXMoeCA9IHJlb3JkZXIoTWFyY2EsIFZlbnRhc190b3RhbGVzKSwgeSA9IFZlbnRhc190b3RhbGVzLCBmaWxsID0gYXMuZmFjdG9yKE1hcmNhKSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXMpICsKICBsYWJzKHRpdGxlID0gIlRvcCAxMCBkZSBWZW50YXMgcG9yIE1hcmNhIiwKICAgICAgIHggPSAiTWFyY2EiLAogICAgICAgeSA9ICJWZW50YXMgdG90YWxlcyIsCiAgICAgICBmaWxsID0gIk1hcmNhIikgKwogIGZhY2V0X3dyYXAofiBNYXJjYSwgc2NhbGVzID0gImZyZWUiKSArICAKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksICAKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICAKYGBgCgoKIyAgR3LDoWZpY28gZGUgZGlzcGVyc2nDs24gcGFyYSBtb3N0cmFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgdmVudGFzIHkgZWwgdGFtYcOxbyBkZSBsYSB0aWVuZGEKYGBge3J9CmdncGxvdChBcmNhQ29udGluZW50YWxEYXRvcywgYWVzKHggPSBUYW1hw7FvLCB5ID0gVmVudGFzX3RvdGFsZXMpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJkYXJrZ3JlZW4iKSArCiAgbGFicyh0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgVmVudGFzIHkgVGFtYcOxbyBkZSBUaWVuZGEiLAogICAgICAgeCA9ICJUYW1hw7FvIGRlIFRpZW5kYSIsCiAgICAgICB5ID0gIlZlbnRhc190b3RhbGVzIikgKwogIGZhY2V0X3dyYXAofiBBw7FvLCBzY2FsZXMgPSAiZnJlZSIpICsgIAogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgIApgYGAKCgojICBHcsOhZmljbyBkZSBiYXJyYXMgcGFyYSBtb3N0cmFyIGxhcyB2ZW50YXMgdG90YWxlcyBwb3IgdGFtYcOxbyBkZSBjbGllbnRlIGVuIGxhIGluZHVzdHJpYQpgYGB7cn0KCmdncGxvdChBcmNhQ29udGluZW50YWxEYXRvcywgYWVzKHggPSBgVGFtYcOxbyBDdGUgSW5kdXN0cmlhYCwgeSA9IFZlbnRhc190b3RhbGVzLCBmaWxsID0gYFRhbWHDsW8gQ3RlIEluZHVzdHJpYWApKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBsYWJzKHRpdGxlID0gIlZlbnRhcyBUb3RhbGVzIHBvciBUYW1hw7FvIGRlIENsaWVudGUgZW4gbGEgSW5kdXN0cmlhIiwKICAgICAgIHggPSAiVGFtYcOxbyBkZSBDbGllbnRlIGVuIGxhIEluZHVzdHJpYSIsCiAgICAgICB5ID0gIlZlbnRhcyBUb3RhbGVzIikgKwogIGZhY2V0X3dyYXAofiBBw7FvLCBzY2FsZXMgPSAiZnJlZSIpICsgIAogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgIApgYGAKCgojICBWZW50YXMgcG9yIG1hcmNhIGEgdHJhdmVzIGRlIGxvcyBhw7FvcwpgYGB7cn0KQXJjYUNvbnRpbmVudGFsRGF0b3MgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgZ3JvdXBfYnkoQcOxbywgTWFyY2EpICU+JQogIHN1bW1hcmlzZShWZW50YXNfdG90YWxlcyA9IHN1bShWZW50YXNfdG90YWxlcykpICU+JQogIGFycmFuZ2UoQcOxbywgZGVzYyhWZW50YXNfdG90YWxlcykpICU+JQogIG11dGF0ZShWZW50YXNfYWN1bXVsYWRhcyA9IGN1bXN1bShWZW50YXNfdG90YWxlcykpCgp0b3BfbWFyY2FzIDwtIEFyY2FDb250aW5lbnRhbERhdG9zICU+JQogIGdyb3VwX2J5KE1hcmNhKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX2FjdW11bGFkYXMgPSBsYXN0KFZlbnRhc19hY3VtdWxhZGFzKSkgJT4lCiAgYXJyYW5nZShkZXNjKFZlbnRhc19hY3VtdWxhZGFzKSkgJT4lCiAgdG9wX24oMTApCgpBcmNhQ29udGluZW50YWxEYXRvc19maWx0cmFkbyA8LSBBcmNhQ29udGluZW50YWxEYXRvcyAlPiUKICBmaWx0ZXIoTWFyY2EgJWluJSB0b3BfbWFyY2FzJE1hcmNhKQoKZ2dwbG90KEFyY2FDb250aW5lbnRhbERhdG9zX2ZpbHRyYWRvLCBhZXMoeCA9IEHDsW8sIHkgPSBWZW50YXNfYWN1bXVsYWRhcywgZmlsbCA9IE1hcmNhKSkgKwogIGdlb21fYXJlYSgpICsKICBsYWJzKHRpdGxlID0gIlRlbmRlbmNpYSBkZSBWZW50YXMgcG9yIE1hcmNhIGEgbG8gbGFyZ28gZGUgbG9zIEHDsW9zIiwKICAgICAgIHggPSAiQcOxbyIsCiAgICAgICB5ID0gIlZlbnRhcyBBY3VtdWxhZGFzIiwKICAgICAgIGZpbGwgPSAiTWFyY2EiKSArCiAgZmFjZXRfd3JhcCh+IE1hcmNhLCBzY2FsZXMgPSAiZnJlZV95IiwgbnJvdyA9IDIpICsgIAogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgIApgYGAKCgojICBWZW50YXMgcG9yIGNsaWVudGUKYGBge3Igd2FybmluZz1GQUxTRX0KQXJjYUNvbnRpbmVudGFsRGF0b3MgPC0gcmVhZF9leGNlbCgiRG93bmxvYWRzL0FyY2FDb250aW5lbnRhbERhdG9zLnhsc3giKQpBcmNhQ29udGluZW50YWxEYXRvcyA8LSByZXBsYWNlKEFyY2FDb250aW5lbnRhbERhdG9zLCBpcy5uYShBcmNhQ29udGluZW50YWxEYXRvcyksIDApCm5hc19wb3JfY29sdW1uYSA8LSBjb2xTdW1zKGlzLm5hKEFyY2FDb250aW5lbnRhbERhdG9zKSkKQXJjYUNvbnRpbmVudGFsRGF0b3MgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgbXV0YXRlKFZlbnRhc190b3RhbGVzID0gcm93U3VtcyhzZWxlY3QoLiwgRW5lcm86RGljaWVtYnJlKSwgbmEucm0gPSBUUlVFKSkKdmVudGFzX3Bvcl9jbGllbnRlIDwtIEFyY2FDb250aW5lbnRhbERhdG9zICU+JQogIGdyb3VwX2J5KENsaWVudGUpICU+JQogIHN1bW1hcmlzZShWZW50YXNfdG90YWxlcyA9IHN1bShWZW50YXNfdG90YWxlcykpICU+JQogIGFycmFuZ2UoZGVzYyhWZW50YXNfdG90YWxlcykpICU+JQogIHRvcF9uKDEwKQoKY29sb3JlcyA8LSBjKCIjMWY3N2I0IiwgIiNmZjdmMGUiLCAiIzJjYTAyYyIsICIjZDYyNzI4IiwgIiM5NDY3YmQiLAogICAgICAgICAgICAgICIjOGM1NjRiIiwgIiNlMzc3YzIiLCAiIzdmN2Y3ZiIsICIjYmNiZDIyIiwgIiMxN2JlY2YiKQoKZ2dwbG90KHZlbnRhc19wb3JfY2xpZW50ZSwgYWVzKHggPSByZW9yZGVyKENsaWVudGUsIFZlbnRhc190b3RhbGVzKSwgeSA9IFZlbnRhc190b3RhbGVzLCBmaWxsID0gQ2xpZW50ZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXMpICsKICBsYWJzKHRpdGxlID0gIlRvcCAxMCBDbGllbnRlcyBwb3IgVmVudGFzIFRvdGFsZXMiLAogICAgICAgeCA9ICJDbGllbnRlIiwKICAgICAgIHkgPSAiVmVudGFzIFRvdGFsZXMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQpgYGAKCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpyZWQ7Ij5BY3RpdmlkYWQgaW5kaXZpZHVhbCA0PC9zcGFuPgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpBcmNhQ29udGluZW50YWxEYXRvcyA8LSByZWFkX2V4Y2VsKCJEb3dubG9hZHMvQXJjYUNvbnRpbmVudGFsRGF0b3MueGxzeCIpCkFyY2FDb250aW5lbnRhbERhdG9zIDwtIHJlcGxhY2UoQXJjYUNvbnRpbmVudGFsRGF0b3MsIGlzLm5hKEFyY2FDb250aW5lbnRhbERhdG9zKSwgMCkKbmFzX3Bvcl9jb2x1bW5hIDwtIGNvbFN1bXMoaXMubmEoQXJjYUNvbnRpbmVudGFsRGF0b3MpKQpBcmNhQ29udGluZW50YWxEYXRvcyA8LSBBcmNhQ29udGluZW50YWxEYXRvcyAlPiUKICBtdXRhdGUoVmVudGFzX3RvdGFsZXMgPSByb3dTdW1zKHNlbGVjdCguLCBFbmVybzpEaWNpZW1icmUpLCBuYS5ybSA9IFRSVUUpKQoKdmVudGFzXzQ1NjcgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgZmlsdGVyKENsaWVudGUgPT0gIjQ1NjciKSAlPiUKICBncm91cF9ieShBw7FvKSAlPiUKICBzdW1tYXJpc2UodmVudGFzX3RvdGFsZXMgPSBzdW0oVmVudGFzX3RvdGFsZXMpKQoKZ2dwbG90KHZlbnRhc180NTY3LCBhZXMoeCA9IEHDsW8sIHkgPSB2ZW50YXNfdG90YWxlcykpICsKICBnZW9tX3BvaW50KCkgKyAgCiAgbGFicyh0aXRsZSA9ICJWZW50YXMgdG90YWxlcyBkZWwgQ2xpZW50ZSA0NTY3IHBvciBBw7FvIiwgCiAgICAgICB4ID0gIkHDsW8iLCAKICAgICAgIHkgPSAiVmVudGFzIHRvdGFsZXMiKSArIAogIHRoZW1lX21pbmltYWwoKSAKYGBgCgpgYGB7cn0KbW9kZWxvIDwtIGxtKHZlbnRhc190b3RhbGVzIH4gQcOxbywgZGF0YSA9IHZlbnRhc180NTY3KQoKc3VtbWFyeShtb2RlbG8pCiMgRWN1YWNpw7NuCiMgeSAtIDQ4OTE4Njc3IC0gMjQxNzQgKiBBw7FvCgojUiBjdWFkcmFkYSBhanVzdGFkYQojIDc3JQoKbnVldm9zX2RhdG9zIDwtIGRhdGEuZnJhbWUoQcOxbyA9IDIwMjA6MjAyNSkKCnByZWRpY2Npb25lcyA8LSBwcmVkaWN0KG1vZGVsbywgbnVldm9zX2RhdG9zKQoKZGF0b3NfY29tcGxldG9zIDwtIHJiaW5kKAogIGNiaW5kKHZlbnRhc180NTY3LCBUaXBvID0gIkRhdG9zIHJlYWxlcyIpLAogIGNiaW5kKGRhdGEuZnJhbWUoQcOxbyA9IDIwMjA6MjAyNSwgdmVudGFzX3RvdGFsZXMgPSBwcmVkaWNjaW9uZXMpLCBUaXBvID0gIlByZWRpY2Npb25lcyIpCikKCmdncGxvdChkYXRvc19jb21wbGV0b3MsIGFlcyh4ID0gQcOxbywgeSA9IHZlbnRhc190b3RhbGVzLCBjb2xvciA9IFRpcG8pKSArCiAgZ2VvbV9saW5lKCkgKyAgCiAgZ2VvbV9wb2ludCgpICsgIAogIGxhYnModGl0bGUgPSAiVmVudGFzIFRvdGFsZXMgKDIwMTctMjAyNSkiLCB4ID0gIkHDsW8iLCB5ID0gIlZlbnRhcyBUb3RhbGVzIiwgY29sb3IgPSAiVGlwbyIpCmBgYAoKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOnJlZDsiPlRhcmVhIGNvbGFib3JhdGl2YSA0PC9zcGFuPgojIFNlYmFzdGnDoW4gRmFqYXJkbyBBbmRyw6kgQ2FzdGlsbG8gUGFjaGVjbyBBbmEgQ3Jpc3RpbmEgVHJldmnDsW8gU8OhZW56IApgYGB7cn0KdmVudGFzXzY2MjYgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgZmlsdGVyKENsaWVudGUgPT0gIjY2MjYiKSAlPiUKICBncm91cF9ieShBw7FvKSAlPiUKICBzdW1tYXJpc2UodmVudGFzX3RvdGFsZXMgPSBzdW0oVmVudGFzX3RvdGFsZXMpKQoKbW9kZWxvXzY2MjYgPC0gbG0odmVudGFzX3RvdGFsZXMgfiBBw7FvLCBkYXRhID0gdmVudGFzXzY2MjYpCgpzdW1tYXJ5KG1vZGVsb182NjI2KQojIEVjdWFjacOzbgojIHkgLSA1NTIwODE5NSAtIDI3MzE2ICogQcOxbwojUiBjdWFkcmFkYSBhanVzdGFkYQojIDkzJQpudWV2b3NfZGF0b3NfNjYyNiA8LSBkYXRhLmZyYW1lKEHDsW8gPSAyMDIwOjIwMjUpCnByZWRpY2Npb25lc182NjI2IDwtIHByZWRpY3QobW9kZWxvXzY2MjYsIG51ZXZvc19kYXRvc182NjI2KQoKZGF0b3NfY29tcGxldG9zXzY2MjYgPC0gcmJpbmQoCiAgY2JpbmQodmVudGFzXzY2MjYsIFRpcG8gPSAiRGF0b3MgcmVhbGVzIiksCiAgY2JpbmQoZGF0YS5mcmFtZShBw7FvID0gMjAyMDoyMDI1LCB2ZW50YXNfdG90YWxlcyA9IHByZWRpY2Npb25lc182NjI2KSwgVGlwbyA9ICJQcmVkaWNjaW9uZXMiKQopCgpnZ3Bsb3QoZGF0b3NfY29tcGxldG9zXzY2MjYsIGFlcyh4ID0gQcOxbywgeSA9IHZlbnRhc190b3RhbGVzLCBjb2xvciA9IFRpcG8pKSArCiAgZ2VvbV9saW5lKCkgKyAgCiAgZ2VvbV9wb2ludCgpICsgIAogIGxhYnModGl0bGUgPSAiVmVudGFzIFRvdGFsZXMgKDIwMTctMjAyNSkgLSBDbGllbnRlIDY2MjYiLCB4ID0gIkHDsW8iLCB5ID0gIlZlbnRhcyBUb3RhbGVzIiwgY29sb3IgPSAiVGlwbyIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpgYGB7cn0KdmVudGFzX3Bvcl9hbmlvIDwtIEFyY2FDb250aW5lbnRhbERhdG9zICU+JQogIGdyb3VwX2J5KEHDsW8pICU+JQogIHN1bW1hcmlzZShWZW50YXNfdG90YWxlcyA9IHN1bShWZW50YXNfdG90YWxlcykpCgoKbW9kZWxvX3JlZ3Jlc2lvbiA8LSBsbShWZW50YXNfdG90YWxlcyB+IEHDsW8sIGRhdGEgPSB2ZW50YXNfcG9yX2FuaW8pCgpzdW1tYXJ5KG1vZGVsb19yZWdyZXNpb24pCiMgRWN1YWNpw7NuCiMgeSArIDE1MDEwMDAwMDAgLSA3NDc5MDAgKiBBw7FvCiNSIGN1YWRyYWRhIGFqdXN0YWRhCiMgOTYlCgpudWV2b3NfYW5pb3MgPC0gZGF0YS5mcmFtZShBw7FvID0gMjAyMDoyMDI1KQpwcmVkaWNjaW9uZXMgPC0gcHJlZGljdChtb2RlbG9fcmVncmVzaW9uLCBudWV2b3NfYW5pb3MpCgoKcHJlZGljY2lvbmVzX2RmIDwtIGRhdGEuZnJhbWUoQcOxbyA9IG51ZXZvc19hbmlvcyRBw7FvLCBWZW50YXNfdG90YWxlcyA9IHByZWRpY2Npb25lcykKCgpkYXRvc19jb21wbGV0b3MgPC0gcmJpbmQoCiAgY2JpbmQodmVudGFzX3Bvcl9hbmlvLCBUaXBvID0gIkRhdG9zIHJlYWxlcyIpLAogIGNiaW5kKHByZWRpY2Npb25lc19kZiwgVGlwbyA9ICJQcmVkaWNjaW9uZXMiKQopCgoKZ2dwbG90KGRhdG9zX2NvbXBsZXRvcywgYWVzKHggPSBBw7FvLCB5ID0gVmVudGFzX3RvdGFsZXMsIGNvbG9yID0gVGlwbykpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHRpdGxlID0gIlZlbnRhcyBUb3RhbGVzIHBvciBBw7FvIiwKICAgICAgIHggPSAiQcOxbyIsCiAgICAgICB5ID0gIlZlbnRhcyBUb3RhbGVzIiwKICAgICAgIGNvbG9yID0gIlRpcG8iKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKYGBge3J9CnZlbnRhc19wb3JfYW5pbyA8LSBBcmNhQ29udGluZW50YWxEYXRvcyAlPiUKICBmaWx0ZXIoQ0VESSA9PSAiU3VjLiBCZWxlbmVzIikgJT4lCiAgZ3JvdXBfYnkoQcOxbykgJT4lCiAgc3VtbWFyaXNlKFZlbnRhc190b3RhbGVzID0gc3VtKFZlbnRhc190b3RhbGVzKSkKCgptb2RlbG9fcmVncmVzaW9uIDwtIGxtKFZlbnRhc190b3RhbGVzIH4gQcOxbywgZGF0YSA9IHZlbnRhc19wb3JfYW5pbykKCgpzdW1tYXJ5KG1vZGVsb19yZWdyZXNpb24pCiMgRWN1YWNpw7NuCiMgeSAtIDE2NDcwMDAwMDAgLSA4MTc0MDAgKiBBw7FvCiNSIGN1YWRyYWRhIGFqdXN0YWRhCiMgNjYlCm51ZXZvc19kYXRvcwoKcHJlZGljY2lvbmVzIDwtIHByZWRpY3QobW9kZWxvX3JlZ3Jlc2lvbikKCgpnZ3Bsb3QodmVudGFzX3Bvcl9hbmlvLCBhZXMoeCA9IEHDsW8sIHkgPSBWZW50YXNfdG90YWxlcykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZShhZXMoeSA9IHByZWRpY2Npb25lcyksIGNvbG9yID0gInJlZCIpICsKICBsYWJzKHRpdGxlID0gIlZlbnRhcyBkZSBsYSBTdWN1cnNhbCBCZWxlbmVzIHBvciBBw7FvIiwKICAgICAgIHggPSAiQcOxbyIsCiAgICAgICB5ID0gIlZlbnRhcyBUb3RhbGVzIikKYGBgCmBgYHtyfQp2ZW50YXNfcG9yX2FuaW9fQUJBUlIgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgZmlsdGVyKE5vbWJyZSA9PSAiQUJBUlIiKSAlPiUKICBncm91cF9ieShBw7FvKSAlPiUKICBzdW1tYXJpc2UoVmVudGFzX3RvdGFsZXMgPSBzdW0oVmVudGFzX3RvdGFsZXMpKQoKbW9kZWxvX3JlZ3Jlc2lvbl9BQkFSUiA8LSBsbShWZW50YXNfdG90YWxlcyB+IEHDsW8sIGRhdGEgPSB2ZW50YXNfcG9yX2FuaW9fQUJBUlIpCgoKc3VtbWFyeShtb2RlbG9fcmVncmVzaW9uX0FCQVJSKQojIEVjdWFjacOzbgojIHkgLSA0Mjg4NzQ5MjIgLSAyMTMwODMgKiBBw7FvCiNSIGN1YWRyYWRhIGFqdXN0YWRhCiM1MyUKcHJlZGljY2lvbmVzX0FCQVJSIDwtIHByZWRpY3QobW9kZWxvX3JlZ3Jlc2lvbl9BQkFSUiwgbmV3ZGF0YSA9IGRhdGEuZnJhbWUoQcOxbyA9IDIwMjA6MjAyNSkpCgoKcHJvbm9zdGljb19kZiA8LSBkYXRhLmZyYW1lKEHDsW8gPSAyMDIwOjIwMjUsIFZlbnRhc190b3RhbGVzID0gcHJlZGljY2lvbmVzX0FCQVJSKQoKZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHZlbnRhc19wb3JfYW5pb19BQkFSUiwgYWVzKHggPSBBw7FvLCB5ID0gVmVudGFzX3RvdGFsZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBwcm9ub3N0aWNvX2RmLCBhZXMoeCA9IEHDsW8sIHkgPSBWZW50YXNfdG90YWxlcywgY29sb3IgPSAiUHJvbsOzc3RpY28iKSkgKwogIGdlb21fc21vb3RoKGRhdGEgPSB2ZW50YXNfcG9yX2FuaW9fQUJBUlIsIGFlcyh4ID0gQcOxbywgeSA9IFZlbnRhc190b3RhbGVzKSwgbWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAiYmx1ZSIpICsKICBsYWJzKHRpdGxlID0gIlZlbnRhcyBkZSBBQkFSUiBwb3IgQcOxbyIsCiAgICAgICB4ID0gIkHDsW8iLAogICAgICAgeSA9ICJWZW50YXMgVG90YWxlcyIsCiAgICAgICBjb2xvciA9ICJUaXBvIikKYGBgCgpgYGB7cn0KCiAgICAgIHZlbnRhc19wb3JfYW5pb19NQVJUSSA8LSBBcmNhQ29udGluZW50YWxEYXRvcyAlPiUKICBmaWx0ZXIoTm9tYnJlID09ICJNQVJUSSIpICU+JQogIGdyb3VwX2J5KEHDsW8pICU+JQogIHN1bW1hcmlzZShWZW50YXNfdG90YWxlcyA9IHN1bShWZW50YXNfdG90YWxlcykpCgptb2RlbG9fcmVncmVzaW9uIDwtIGxtKFZlbnRhc190b3RhbGVzIH4gQcOxbywgZGF0YSA9IHZlbnRhc19wb3JfYW5pb19NQVJUSSkKCnN1bW1hcnkobW9kZWxvX3JlZ3Jlc2lvbikKIyBFY3VhY2nDs24KIyB5IC0gMTEwMTc4NDIgLSA1NDk0ICogQcOxbwojUiBjdWFkcmFkYSBhanVzdGFkYQojNDQlCm51ZXZvc19hbmlvcyA8LSBkYXRhLmZyYW1lKEHDsW8gPSAyMDIwOjIwMjUpCnByZWRpY2Npb25lcyA8LSBwcmVkaWN0KG1vZGVsb19yZWdyZXNpb24sIG51ZXZvc19hbmlvcykKCgpwcm9ub3N0aWNvX2RmIDwtIGRhdGEuZnJhbWUoQcOxbyA9IG51ZXZvc19hbmlvcyRBw7FvLCBWZW50YXNfdG90YWxlcyA9IHByZWRpY2Npb25lcykKCmdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSB2ZW50YXNfcG9yX2FuaW9fTUFSVEksIGFlcyh4ID0gQcOxbywgeSA9IFZlbnRhc190b3RhbGVzLCBjb2xvciA9ICJEYXRvcyByZWFsZXMiKSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHByb25vc3RpY29fZGYsIGFlcyh4ID0gQcOxbywgeSA9IFZlbnRhc190b3RhbGVzLCBjb2xvciA9ICJQcm9uw7NzdGljbyIpLCBzaGFwZSA9IDE2LCBzaXplID0gMykgKwogIGdlb21fc21vb3RoKGRhdGEgPSB2ZW50YXNfcG9yX2FuaW9fTUFSVEksIGFlcyh4ID0gQcOxbywgeSA9IFZlbnRhc190b3RhbGVzKSwgbWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAiYmx1ZSIpICsKICBsYWJzKHRpdGxlID0gIlZlbnRhcyBkZSBNQVJUSSBwb3IgQcOxbyIsCiAgICAgICB4ID0gIkHDsW8iLAogICAgICAgeSA9ICJWZW50YXMgVG90YWxlcyIsCiAgICAgICBjb2xvciA9ICJUaXBvIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibHVlIiwgInJlZCIpKSAKYGBgCgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6cmVkOyI+RXZpZGVuY2lhPC9zcGFuPgpgYGB7cn0KCmBgYAoKYGBge3J9CiMjIHByZWd1bnRhcyBkZXRvbmFudGVzIDEuIMK/UHVlZGUgb2JzZXJ2YXJzZSB1biBjcmVjaW1pZW50byBlbiBsYXMgdmVudGFzIGRlIGFsZ3Vub3MgZGUgbG9zIHNlZ21lbnRvcyBkZSBwcm9kdWN0b3MgZGUgbGEgZmFtaWxpYSBDb2NhIENvbGEgZW4gbGFzIHRpZW5kYXMgZW4gbGFzIHF1ZSBzZSBpbXBsZW1lbnTDsyBlbCBQcm95ZWN0byBTaWdsbyBYWEkgZGUgQXJjYSAKCiNFbiB0w6lybWlub3MgZ2VuZXJhbGVzLCBsYXMgdmVudGFzIGV4cGVyaW1lbnRhcm9uIHVuIGF1bWVudG8gZW4gZWwgYcOxbyAyMDE5LCBhdW5xdWUgY2FkYSBzZWdtZW50byBtb3N0csOzIHVuIGNvbXBvcnRhbWllbnRvIGRpZmVyZW50ZS4gRXN0ZSBpbmNyZW1lbnRvIGVuIGxhcyB2ZW50YXMgcHVlZGUgYXRyaWJ1aXJzZSBhIGVzdHJhdGVnaWFzIGRlIG1hcmtldGluZyBtZWpvcmFkYXMgeSBhbCBsYW56YW1pZW50byBkZSBudWV2b3MgcHJvZHVjdG9zLiBFbiBlbCBhw7FvIDIwMTgsIGxhcyB2ZW50YXMgZGUgQ29jYS1Db2xhIGF1bWVudGFyb24gZW4gMTAwLDAwMCB1bmlkYWRlcyBlbnRyZSBsb3MgbWVzZXMgZGUgZmVicmVybyB5IGRpY2llbWJyZSwgbWllbnRyYXMgcXVlIGxhcyB2ZW50YXMgZGUgYWd1YXMgaXNvdMOzbmljYXMgcGVybWFuZWNpZXJvbiBlc3RhYmxlcywgc2luIHJlZ2lzdHJhciBjYW1iaW9zIHNpZ25pZmljYXRpdm9zLgpgYGAKCgpgYGB7cn0KdmVudGFzX3RvdGFsZXNfdGFtX2NsaWVudGUgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgZmlsdGVyKEHDsW8gPT0gMjAxOSkgJT4lCiAgZ3JvdXBfYnkoYFRhbWHDsW8gQ3RlIEluZHVzdHJpYWApICU+JQogIHN1bW1hcmlzZShWZW50YXNfdG90YWxlcyA9IHN1bShWZW50YXNfdG90YWxlcykpICU+JQogIGZpbHRlcihWZW50YXNfdG90YWxlcyAhPSAwKQoKZ2dwbG90KHZlbnRhc190b3RhbGVzX3RhbV9jbGllbnRlLCBhZXMoeD1gVGFtYcOxbyBDdGUgSW5kdXN0cmlhYCwgeT1WZW50YXNfdG90YWxlcykpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIGZpbGw9InNreWJsdWUiKSArCiAgbGFicyh4PSJUYW1hw7FvIGRlIENsaWVudGUiLCB5PSJWZW50YXMgVG90YWxlcyAoUXR5KSIsIHRpdGxlPSJWZW50YXMgdG90YWxlcyBwb3IgdGFtYcOxbyBkZSBjbGllbnRlIikKCiNFbCBpbmNyZW1lbnRvIGVuIGxhcyB2ZW50YXMgZXMgc2ltaWxhciBpbmRlcGVuZGllbnRlbWVudGUgZGUgbG9zIHRhbWHDsW9zIGRlIGxvcyBjbGllbnRlcy4gRGFkbyBxdWUgdG9kb3MgbG9zIG5lZ29jaW9zIG9wZXJhbiBsb3MgbWlzbW9zIGTDrWFzIHkgZXN0w6FuIHViaWNhZG9zIGVuIGxhIG1pc21hIGNpdWRhZCAoR3VhZGFsYWphcmEpLCBsb3MgZmFjdG9yZXMgZXh0ZXJub3MgcXVlIGFmZWN0YW4gbGFzIHZlbnRhcyB0aWVuZW4gdW4gaW1wYWN0byBjYXNpIGlkw6ludGljbyBlbiB0b2Rvcy4gU2Ugb2JzZXJ2YSBxdWUgZWwgbWVzIGRlIG1heW8gZGUgMjAxOSBmdWUgZWwgZGUgbWF5b3IgdmVudGEgZW4gdG9kb3MgbG9zIHRhbWHDsW9zIGRlIGNsaWVudGUsIG1pZW50cmFzIHF1ZSBlbCBwcmltZXIgYmltZXN0cmUgZnVlIGVsIHBlcmlvZG8gbcOhcyBiYWpvLCB0YW1iacOpbiBwYXJhIHRvZG9zIGxvcyB0YW1hw7FvcyBkZSBjbGllbnRlLgpgYGAKCgpgYGB7cn0KQXJjYUNvbnRpbmVudGFsRGF0b3NfbG9uZyA8LSBBcmNhQ29udGluZW50YWxEYXRvcyAlPiUKICBnYXRoZXIoa2V5ID0gIk1lcyIsIHZhbHVlID0gIlZlbnRhcyIsIEVuZXJvOkRpY2llbWJyZSkgJT4lCiAgbXV0YXRlKE1lcyA9IGZhY3RvcihNZXMsIGxldmVscyA9IG1vbnRoLm5hbWUpKSAgIyBSZW9yZGVuYSBsb3MgbWVzZXMgcGFyYSBxdWUgYXBhcmV6Y2FuIGVuIGVsIG9yZGVuIGNvcnJlY3RvCgojIEFob3JhIGNhbGN1bGEgbGFzIHZlbnRhcyB0b3RhbGVzIHBvciBtYXJjYSB5IG1lcwp2ZW50YXNfdG90YWxlc19tYXJjYV9tZXMgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3NfbG9uZyAlPiUKICBmaWx0ZXIoQcOxbyA9PSAyMDE5KSAlPiUKICBmaWx0ZXIoTWFyY2EgJWluJSBjKCJDb2NhLUNvbGEiLCAiVmFsbGUgRnJ1dCIsICJDaWVsIEFndWEgUHVyaWZpY2FkYSIsICJDb2NhLUNvbGEgTGlnaHQiKSkgJT4lCiAgZ3JvdXBfYnkoTWFyY2EsIE1lcykgJT4lCiAgc3VtbWFyaXNlKFZlbnRhc19Ub3RhbGVzID0gc3VtKFZlbnRhcykpCgojIEdyYWZpY2FyIGxhcyB2ZW50YXMgdG90YWxlcyBwb3IgbWFyY2EgeSBtZXMKZ2dwbG90KHZlbnRhc190b3RhbGVzX21hcmNhX21lcywgYWVzKHggPSBNZXMsIHkgPSBWZW50YXNfVG90YWxlcywgZmlsbCA9IE1hcmNhKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBsYWJzKHggPSAiTWVzIiwgeSA9ICJWZW50YXMgVG90YWxlcyAoUVRZKSIsIHRpdGxlID0gIlZlbnRhcyB0b3RhbGVzIHBvciBtYXJjYSB5IG1lcyIpCiNFbCBwYXRyw7NuIGRlIHZlbnRhcyBlcyBjb25zaXN0ZW50ZSBlbnRyZSBsYXMgZGl2ZXJzYXMgbWFyY2FzIGEgbG8gbGFyZ28gZGUgbG9zIG1lc2VzLCBzaW4gZW1iYXJnbywgYWxndW5hcyBtYXJjYXMgc3VwZXJhbiBzaWduaWZpY2F0aXZhbWVudGUgYSBvdHJhcyBlbiB0w6lybWlub3MgZGUgdm9sdW1lbiBkZSB2ZW50YXMuIExvcyBtZXNlcyBjb24gdGVtcGVyYXR1cmFzIG3DoXMgYWx0YXMgdGllbmRlbiBhIHJlZ2lzdHJhciBtYXlvcmVzIHZlbnRhcyBkZSBiZWJpZGFzLCB5IGxhcyBtYXJjYXMgbcOhcyByZWNvbm9jaWRhcyBzb24gbGFzIHByZWZlcmlkYXMgcG9yIGxvcyBjb25zdW1pZG9yZXMuIEVuIGdlbmVyYWwsIG1heW8gZGUgMjAxOSBkZXN0YWNhIGNvbW8gZWwgbWVzIGNvbiBtYXlvcmVzIHZlbnRhcyBwYXJhIHRvZGFzIGxhcyBtYXJjYXMsIHNpZW5kbyBDb2NhLUNvbGEgbGEgbWFyY2EgbMOtZGVyIGVuIHZlbnRhcyBkdXJhbnRlIGVzdGUgcGVyw61vZG8uCmBgYAoKCmBgYHtyfQojIFZlcmlmaWNhciBzaSBsYSBjb2x1bW5hICJTZWdtZW50b19EZXQiIGV4aXN0ZSBlbiB0dXMgZGF0b3MKaWYgKCJTZWdtZW50b19EZXQiICVpbiUgY29sbmFtZXMoQXJjYUNvbnRpbmVudGFsRGF0b3MpKSB7CiAgcHJpbnQoIkxhIGNvbHVtbmEgJ1NlZ21lbnRvX0RldCcgZXhpc3RlIGVuIHR1cyBkYXRvcy4iKQp9IGVsc2UgewogIHByaW50KCJMYSBjb2x1bW5hICdTZWdtZW50b19EZXQnIE5PIGV4aXN0ZSBlbiB0dXMgZGF0b3MuIikKfQp2ZW50YXNfdG90YWxlc19lbnZhc2UgPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgZmlsdGVyKFJldG9ybmFibGVfTlIgPT0gIlJldG9ybmFibGUiKSAlPiUKICBmaWx0ZXIoQcOxbyAlaW4lIGMoMjAxOCwgMjAxOSkpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhFbmVybzpEaWNpZW1icmUpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJNZXMiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiVmVudGFzX1RvdGFsZXMiKSAlPiUKICBncm91cF9ieShBw7FvLCBNZXMpICU+JQogIHN1bW1hcmlzZShWZW50YXNfVG90YWxlcyA9IHN1bShWZW50YXNfVG90YWxlcykpICU+JQogIHVuZ3JvdXAoKQoKZ2dwbG90KHZlbnRhc190b3RhbGVzX2VudmFzZSwgYWVzKHggPSBNZXMsIHkgPSBWZW50YXNfVG90YWxlcywgZ3JvdXAgPSBBw7FvLCBjb2xvciA9IGFzLmZhY3RvcihBw7FvKSkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHggPSAiTWVzIiwgeSA9ICJWZW50YXMgVG90YWxlcyAoUVRZKSIsIHRpdGxlID0gIlZlbnRhcyB0b3RhbGVzIGRlIEVudmFzZXMgUmV0b3JuYWJsZXMgcG9yIE1lcyIsIGNvbG9yID0gIkHDsW8iKQojTGEgdmVudGEgZGUgcHJvZHVjdG9zIGVuIGVudmFzZSByZXRvcm5hYmxlIGhhIGV4cGVyaW1lbnRhZG8gdW4gbm90YWJsZSBhdW1lbnRvIGVuIGxvcyDDumx0aW1vcyBkb3MgYcOxb3MuIEVzdGUgaW5jcmVtZW50byBwdWVkZSBhdHJpYnVpcnNlIGVuIHBhcnRlIGEgbGFzIGV4aXRvc2FzIGNhbXBhw7FhcyBkZSBjb25jaWVuY2lhIGFtYmllbnRhbCBxdWUgaGFuIGdlbmVyYWRvIHVuYSBtYXlvciBhY2VwdGFjacOzbiB5IHByZWZlcmVuY2lhIHBvciBvcGNpb25lcyBtZW5vcyBkYcOxaW5hcyBwYXJhIGVsIGVjb3Npc3RlbWEuIERlc2RlIDIwMTcgaGFzdGEgMjAxOCwgc2Ugb2JzZXJ2w7MgdW4gbGlnZXJvIGluY3JlbWVudG8gZW4gbGFzIHZlbnRhcyBkZSBlbnZhc2VzIHJldG9ybmFibGVzLCBsbyBjdWFsIHN1Z2llcmUgdW5hIGNyZWNpZW50ZSB0ZW5kZW5jaWEgaGFjaWEgbGEgc29zdGVuaWJpbGlkYWQuIFNpbiBlbWJhcmdvLCBlbCBhdW1lbnRvIGZ1ZSBhw7puIG3DoXMgc2lnbmlmaWNhdGl2byBlbnRyZSAyMDE4IHkgMjAxOSwgbG8gY3VhbCBwdWVkZSBzZXIgaW5kaWNhdGl2byBkZSB1biBtYXlvciBuw7ptZXJvIGRlIHRpZW5kYXMgYWRvcHRhbmRvIGVsIHByb3llY3RvIFNpZ2xvIFhYSSBkZSBBcmNhIENvbnRpbmVudGFsIG8gZGUgdW4gaW5jcmVtZW50byBnZW5lcmFsIGVuIGxhcyB2ZW50YXMgZGUgcHJvZHVjdG9zLCB0YW50byByZXRvcm5hYmxlcyBjb21vIG5vIHJldG9ybmFibGVzLCBlbiB0b2RhcyBsYXMgdGllbmRhcy4gRXN0ZSBmZW7Ds21lbm8gcmVmbGVqYSB1bmEgY3JlY2llbnRlIGNvbmNpZW5jaWEgYW1iaWVudGFsIHkgdW5hIHByZWZlcmVuY2lhIGRlbCBjb25zdW1pZG9yIHBvciBvcGNpb25lcyBxdWUgcHJvbXVldmFuIGxhIGNvbnNlcnZhY2nDs24gZGVsIG1lZGlvIGFtYmllbnRlCmBgYApgYGB7cn0KCiNFbiAyMDE4LCBsYXMgdmVudGFzIGRlIGFndWEgcHVyaWZpY2FkYSBubyBhdW1lbnRhcm9uIGVuIGNvbXBhcmFjacOzbiBjb24gbGFzIGRlIHJlZnJlc2NvcyBvIGJlYmlkYXMgaXNvdMOzbmljYXMuIExhIHByZWZlcmVuY2lhIHBvciBsb3MgcmVmcmVzY29zIHB1ZWRlIGF0cmlidWlyc2UgYSBzdSBzYWJvciBkdWxjZSB5IGEgbGEgcGVyY2VwY2nDs24gZGUgdW4gbWF5b3IgdmFsb3IgYWdyZWdhZG8uIFBvciBlamVtcGxvLCBDb2NhLUNvbGEgdmVuZGnDsyBoYXN0YSA0NTAsMDAwIHVuaWRhZGVzIGVuIHN1IG1lcyBtw6FzIGFsdG8sIG1pZW50cmFzIHF1ZSBsYXMgdmVudGFzIHRvdGFsZXMgZGUgYWd1YSBwdXJpZmljYWRhIG5vIHN1cGVyYXJvbiBsYXMgNTAsMDAwIHVuaWRhZGVzIGVuIGVsIG1pc21vIHBlcsOtb2RvLgpgYGAKYGBge3J9CiPCv1B1ZWRlIGRlY2lyc2UgcXVlIGxhIHZlbnRhIG1lbnN1YWwgZGUgYWd1YSBlc3TDoSByZWxhY2lvbmFkYSBjb24gbGEgdmVudGEgbWVuc3VhbCBkZSByZWZyZXNjb3MgZW4gbG9zIMO6bHRpbW9zIDQgYcOxb3M/CgojTGFzIHZlbnRhcyBkZSBhZ3VhIHkgcmVmcmVzY29zIG11ZXN0cmFuIHVuIGF1bWVudG8gY29uc3RhbnRlIGR1cmFudGUgbG9zIG1pc21vcyBtZXNlcyB5IGEgbG8gbGFyZ28gZGUgbG9zIGHDsW9zLiBTaW4gZW1iYXJnbywgbm8gcG9kZW1vcyBjb25jbHVpciBxdWUgZWwgYXVtZW50byBlbiBsYXMgdmVudGFzIGRlIHVubyBjYXVzZSBlbCBpbmNyZW1lbnRvIGVuIGxhcyB2ZW50YXMgZGVsIG90cm8uIEZhY3RvcmVzIGNvbW8gbG9zIG1lc2VzIGPDoWxpZG9zIHkgZWwgY3JlY2ltaWVudG8gcG9ibGFjaW9uYWwgcHVlZGVuIGNvbnRyaWJ1aXIgYSBlc3RlIGF1bWVudG8gZW4gbGEgZGVtYW5kYSBkZSBiZWJpZGFzLiBMYSBncsOhZmljYSByZXZlbGEgdW4gaW5jcmVtZW50byBhw7FvIHRyYXMgYcOxbyBlbiBsYXMgdmVudGFzIGRlIGFndWEgeSByZWZyZXNjb3MsIHJlZmxlamFuZG8gcG9zaWJsZXMgY2FtYmlvcyBlbiBsYXMgcHJlZmVyZW5jaWFzIGRlbCBjb25zdW1pZG9yIHkgZW4gZWwgbWVyY2Fkby4KYGBgCgoKYGBge3J9CiPCv0EgY3XDoW50byBhc2NpZW5kZW4gbGFzIHZlbnRhcyBlc3BlcmFkYXMgcGFyYSBlbCAyMDIwIGVuIGxhIENvY2EgQ29sYSBkZSA1MDAgbWwgTlIgVmlkcmlvPwpsaWJyYXJ5KGZvcmVjYXN0KQp2ZW50YXNfY29jYV92aWRyaW8gPC0gQXJjYUNvbnRpbmVudGFsRGF0b3MgJT4lCiAgZmlsdGVyKE1hcmNhID09ICJDb2NhLUNvbGEiICYgUHJlc2VudGFjaW9uID09ICI1MDAgbWwgTlIgVmlkcmlvIikgJT4lCiAgZ3JvdXBfYnkoQcOxbykgJT4lCiAgc3VtbWFyaXNlKFZlbnRhc190b3RhbGVzID0gc3VtKFZlbnRhc190b3RhbGVzKSkgJT4lCiAgZmlsdGVyKFZlbnRhc190b3RhbGVzICE9IDApCgp0c192ZW50YXMgPC0gdHMoZGF0YSA9IHZlbnRhc19jb2NhX3ZpZHJpbyRWZW50YXNfdG90YWxlcywgc3RhcnQgPSBjKDIwMTcsIDEpLCBmcmVxdWVuY3kgPSAxMikKCgphcmltYV9tb2RlbCA8LSBhcmltYSh0c192ZW50YXMsIG9yZGVyID0gYygxLCAxLCAxKSkKCgpwcm9ub3N0aWNvXzIwMjAgPC0gZm9yZWNhc3QoYXJpbWFfbW9kZWwsIGggPSAxMikKCgp2ZW50YXNfZXNwZXJhZGFzXzIwMjAgPC0gc3VtKHByb25vc3RpY29fMjAyMCRtZWFuKQp2ZW50YXNfZXNwZXJhZGFzXzIwMjAKcGxvdChwcm9ub3N0aWNvXzIwMjAsIG1haW4gPSAiUHJvbsOzc3RpY28gZGUgVmVudGFzIGRlIENvY2EtQ29sYSA1MDAgbWwgTlIgVmlkcmlvIGhhc3RhIDIwMjAiLAogICAgIHhsYWIgPSAiQcOxbyIsIHlsYWIgPSAiVmVudGFzIChRdHkpIiwgeGxpbSA9IGMoMjAxNywgMjAyMCkpCmxpbmVzKHRzX3ZlbnRhcywgY29sID0gImJsdWUiKSAgIyBBZ3JlZ2FyIGRhdG9zIGhpc3TDs3JpY29zCmxlZ2VuZCgidG9wcmlnaHQiLCBsZWdlbmQgPSBjKCJEYXRvcyBIaXN0w7NyaWNvcyIsICJQcm9uw7NzdGljbyIpLCBjb2wgPSBjKCJibHVlIiwgInJlZCIpLCBsdHkgPSAxKQpgYGAKCg==