Analisis de Evidencia 1

Cargar librerias y base de datos

# Cargar librerías
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.2     ✔ tibble    3.3.0
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.1.0     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(readxl)
library(scales)
## 
## Attaching package: 'scales'
## 
## The following object is masked from 'package:purrr':
## 
##     discard
## 
## The following object is masked from 'package:readr':
## 
##     col_factor
library(stringr)
library(corrplot)
## corrplot 0.92 loaded
# Cargar bases de datos

# base de datos tipos de tarjetas
tipos <- read_excel("/Users/sebastianespi/Downloads/T base de datos RETO/Tipos de tarjetas.xls")

# base de datos Población bancarizada.xls
participacion <- read_excel("/Users/sebastianespi/Downloads/T base de datos RETO/PoblacionB.xls")

# base de datos Características de tarjetas por grupo bancario.xlsx
tarjetas <- read_excel("/Users/sebastianespi/Downloads/T base de datos RETO/NuevabaseCaracteristicas.xlsx")

# base de datos transacciones moviles
transacciones <- read_excel("/Users/sebastianespi/Downloads/T base de datos RETO/Transacciones moviles.xls")

# base de datos Participación de tarjetas
redes <- read_excel("/Users/sebastianespi/Downloads/T base de datos RETO/Participacion de redes de tarjetas.xls")

# base de datos Participación de grupos bancarios
bancos <- read_excel("/Users/sebastianespi/Downloads/T base de datos RETO/Participacion de grupos bancarios.xlsx")

Aquí se cargaron las librerías y seis bases de datos en Excel sobre tarjetas, población bancarizada, transacciones y participación bancaria para preparar la información del análisis.

Evidencia 1

Analisis Exploratorio de las 6 bases de Datos del Caso

tarjetas_clean <- tarjetas %>%
  mutate(
    `Regular APR` = as.numeric(str_replace_all(`Regular APR`, "%|\\s", "")),
    `Annual Fee` = as.numeric(str_replace_all(`Annual Fee`, "MXN|,|\\s", "")),
    `Rewards Rate` = as.numeric(str_replace_all(`Rewards Rate`, "[^0-9\\.]", "")),
    Contactless = ifelse(str_detect(`Key Features`, "Contactless"), "Sí", "No")
  )
## Warning: There were 2 warnings in `mutate()`.
## The first warning was:
## ℹ In argument: `Annual Fee = as.numeric(str_replace_all(`Annual Fee`,
##   "MXN|,|\\s", ""))`.
## Caused by warning:
## ! NAs introduced by coercion
## ℹ Run `dplyr::last_dplyr_warnings()` to see the 1 remaining warning.
bancos_clean <- bancos %>%
  mutate(across(starts_with("20"), ~as.numeric(ifelse(. == "-", NA, .))))

El código limpió y estandarizó los datos, convirtiendo tasas, cuotas y recompensas a formato numérico, y marcando si las tarjetas son Contactless. Esto facilita análisis estadístico y comparación de productos.

Estadísticos básicos

# ESTADÍSTICOS DE TARJETA
cat("Estadísticos numéricos:\n")
## Estadísticos numéricos:
print(summary(tarjetas_clean %>% select(`Regular APR`, `Annual Fee`, `Rewards Rate`)))
##   Regular APR       Annual Fee      Rewards Rate   
##  Min.   :0.2112   Min.   : 640.0   Min.   :  1.00  
##  1st Qu.:0.4177   1st Qu.: 845.5   1st Qu.:  1.25  
##  Median :0.5500   Median :1187.4   Median : 10.00  
##  Mean   :0.4959   Mean   :1930.7   Mean   : 19.70  
##  3rd Qu.:0.5911   3rd Qu.:2544.2   3rd Qu.: 16.50  
##  Max.   :0.6809   Max.   :5800.0   Max.   :110.00  
##  NA's   :103      NA's   :104      NA's   :108
# Top 5 emisores por número de tarjetas
print(tarjetas_clean %>% count(Issuer) %>% arrange(desc(n)) %>% head(5))
## # A tibble: 5 × 2
##   Issuer                                 n
##   <chr>                              <int>
## 1 <NA>                                  76
## 2 None                                   7
## 3 American Express Co                    3
## 4 Banco Bilbao Vizcaya Argentaria SA     3
## 5 Citigroup Inc                          3
# Participación por red
print(tarjetas_clean %>% count(Network) %>% mutate(porcentaje = n/sum(n)*100))
## # A tibble: 4 × 3
##   Network              n porcentaje
##   <chr>            <int>      <dbl>
## 1 American Express     3       2.54
## 2 Mastercard           6       5.08
## 3 Visa                 6       5.08
## 4 <NA>               103      87.3
# Distribución por nivel de tarjeta
print(tarjetas_clean %>% count(`Card Level`) %>% mutate(porcentaje = n/sum(n)*100))
## # A tibble: 4 × 3
##   `Card Level`     n porcentaje
##   <chr>        <int>      <dbl>
## 1 Premium          5       4.24
## 2 Premium Plus     5       4.24
## 3 Standard         5       4.24
## 4 <NA>           103      87.3

La base muestra tarjetas por nivel, emisor y red, con la mayoría de datos faltantes. APR va de 21.12% a 68.09%, cuota anual de $640 a $5,800 MXN y recompensas de 1% a 110%, reflejando diversidad de productos y segmentación del mercado.

# 2. ESTADÍSTICOS DE TIPOS DE TARJETAS
cat("Estructura de la base:\n")
## Estructura de la base:
print(str(tipos))
## tibble [15 × 5] (S3: tbl_df/tbl/data.frame)
##  $ Year                   : num [1:15] 2010 2011 2012 2013 2014 ...
##  $ Contact Smart Cards    : num [1:15] 24.9 36.5 42.2 44.1 44.6 40.5 41.7 41.9 42.2 42.5 ...
##  $ Contactless Smart Cards: num [1:15] 0.9 1.2 1.4 1.6 1.8 2 2.1 2.1 2.3 2.7 ...
##  $ Non-Smart Cards        : num [1:15] 74.2 62.3 56.4 54.3 53.6 57.6 56.2 56 55.5 54.9 ...
##  $ Total                  : num [1:15] 100 100 100 100 100 100 100 100 100 100 ...
## NULL
cat("\nPrimeras filas:\n")
## 
## Primeras filas:
print(head(tipos))
## # A tibble: 6 × 5
##    Year `Contact Smart Cards` `Contactless Smart Cards` `Non-Smart Cards` Total
##   <dbl>                 <dbl>                     <dbl>             <dbl> <dbl>
## 1  2010                  24.9                       0.9              74.2   100
## 2  2011                  36.5                       1.2              62.3   100
## 3  2012                  42.2                       1.4              56.4   100
## 4  2013                  44.1                       1.6              54.3   100
## 5  2014                  44.6                       1.8              53.6   100
## 6  2015                  40.5                       2                57.6   100
cat("\nResumen de tipos:\n")
## 
## Resumen de tipos:
print(summary(tipos))
##       Year      Contact Smart Cards Contactless Smart Cards Non-Smart Cards
##  Min.   :2010   Min.   :24.90       Min.   :0.900           Min.   :51.00  
##  1st Qu.:2014   1st Qu.:41.80       1st Qu.:1.700           1st Qu.:53.70  
##  Median :2017   Median :42.50       Median :2.100           Median :54.90  
##  Mean   :2017   Mean   :41.32       Mean   :2.333           Mean   :56.36  
##  3rd Qu.:2020   3rd Qu.:43.80       3rd Qu.:3.000           3rd Qu.:56.30  
##  Max.   :2024   Max.   :44.80       Max.   :4.200           Max.   :74.20  
##      Total    
##  Min.   :100  
##  1st Qu.:100  
##  Median :100  
##  Mean   :100  
##  3rd Qu.:100  
##  Max.   :100

Esta base clasifica las tarjetas por categoría y características, mostrando la diversificación del mercado. Nos permite identificar tendencias, analizar la estrategia de producto de cada emisor y seguir la evolución del sector.

# 3. ESTADÍSTICOS DE POBLACIÓN BANCARIZADA
cat("\n\n=== ESTADÍSTICOS DE POBLACIÓN BANCARIZADA ===\n")
## 
## 
## === ESTADÍSTICOS DE POBLACIÓN BANCARIZADA ===
cat("Estructura de la base:\n")
## Estructura de la base:
print(str(participacion))
## tibble [102 × 18] (S3: tbl_df/tbl/data.frame)
##  $ Geography: chr [1:102] "Brazil" "Brazil" "Brazil" "Brazil" ...
##  $ Category : chr [1:102] "Payments and Lending" "Payments and Lending" "Payments and Lending" "Payments and Lending" ...
##  $ Title    : chr [1:102] "Population (000s)" "Banked population (000s)" "Unbanked Population (000s)" "Underserved population (000s)" ...
##  $ 2010     : chr [1:102] "193702" "115302" "30362" "18517" ...
##  $ 2011     : num [1:102] 195187 120275 27378 20519 58496 ...
##  $ 2012     : num [1:102] 196679 126588 23074 22938 59694 ...
##  $ 2013     : num [1:102] 198181 132585 19133 25655 60919 ...
##  $ 2014     : num [1:102] 199686 137132 16591 27440 62170 ...
##  $ 2015     : num [1:102] 201173 143347 12285 29243 63443 ...
##  $ 2016     : num [1:102] 202610 146270 11243 30205 64729 ...
##  $ 2017     : num [1:102] 203990 148208 11060 29375 66025 ...
##  $ 2018     : num [1:102] 205286 150113 10737 29422 67324 ...
##  $ 2019     : num [1:102] 206526 150912 11467 28975 68637 ...
##  $ 2020     : num [1:102] 207667 155968 7936 26515 69948 ...
##  $ 2021     : num [1:102] 208539 156514 8713 24651 71203 ...
##  $ 2022     : num [1:102] 209310 156905 9535 23536 72456 ...
##  $ 2023     : num [1:102] 210148 166649 1177 24981 73720 ...
##  $ 2024     : num [1:102] 210971 160651 8520 23246 74952 ...
## NULL
cat("\nPrimeras filas:\n")
## 
## Primeras filas:
print(head(participacion))
## # A tibble: 6 × 18
##   Geography Category      Title `2010` `2011` `2012` `2013` `2014` `2015` `2016`
##   <chr>     <chr>         <chr> <chr>   <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
## 1 Brazil    Payments and… Popu… 193702 1.95e5 1.97e5 1.98e5 2.00e5 2.01e5 2.03e5
## 2 Brazil    Payments and… Bank… 115302 1.20e5 1.27e5 1.33e5 1.37e5 1.43e5 1.46e5
## 3 Brazil    Payments and… Unba… 30362  2.74e4 2.31e4 1.91e4 1.66e4 1.23e4 1.12e4
## 4 Brazil    Payments and… Unde… 18517  2.05e4 2.29e4 2.57e4 2.74e4 2.92e4 3.02e4
## 5 Brazil    Payments and… Hous… 57324  5.85e4 5.97e4 6.09e4 6.22e4 6.34e4 6.47e4
## 6 Brazil    Payments and… Infl… -      6.64e0 5.4 e0 6.2 e0 6.33e0 9.03e0 8.74e0
## # ℹ 8 more variables: `2017` <dbl>, `2018` <dbl>, `2019` <dbl>, `2020` <dbl>,
## #   `2021` <dbl>, `2022` <dbl>, `2023` <dbl>, `2024` <dbl>
cat("\nResumen de participación:\n")
## 
## Resumen de participación:
print(summary(participacion))
##   Geography           Category            Title               2010          
##  Length:102         Length:102         Length:102         Length:102        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##       2011                2012                2013               2014         
##  Min.   :     0.01   Min.   :     0.01   Min.   :     0.0   Min.   :     0.0  
##  1st Qu.:     1.71   1st Qu.:     1.69   1st Qu.:     1.6   1st Qu.:     1.8  
##  Median :    22.71   Median :    22.39   Median :    21.1   Median :    22.1  
##  Mean   : 17136.22   Mean   : 17376.52   Mean   : 17620.0   Mean   : 17870.2  
##  3rd Qu.:  8590.50   3rd Qu.:  8953.75   3rd Qu.:  9335.2   3rd Qu.:  9648.0  
##  Max.   :311795.00   Max.   :314311.00   Max.   :316686.0   Max.   :319209.0  
##  NA's   :6           NA's   :6           NA's   :6          NA's   :6         
##       2015               2016               2017               2018         
##  Min.   :     0.0   Min.   :     0.0   Min.   :     0.0   Min.   :     0.0  
##  1st Qu.:     1.7   1st Qu.:     1.7   1st Qu.:     1.7   1st Qu.:     2.1  
##  Median :    23.5   Median :    26.0   Median :    25.3   Median :    26.2  
##  Mean   : 18118.3   Mean   : 18318.5   Mean   : 18511.2   Mean   : 18728.3  
##  3rd Qu.:  9834.5   3rd Qu.: 10270.8   3rd Qu.: 10698.8   3rd Qu.: 10408.5  
##  Max.   :321761.0   Max.   :324295.0   Max.   :326549.0   Max.   :328470.0  
##  NA's   :6          NA's   :6          NA's   :6          NA's   :6         
##       2019               2020               2021               2022         
##  Min.   :     0.0   Min.   :     0.0   Min.   :     0.0   Min.   :     0.0  
##  1st Qu.:     1.8   1st Qu.:     1.7   1st Qu.:     3.0   1st Qu.:     4.3  
##  Median :    25.7   Median :    27.2   Median :    27.4   Median :    25.8  
##  Mean   : 18963.3   Mean   : 19121.5   Mean   : 19184.5   Mean   : 19398.2  
##  3rd Qu.: 10616.8   3rd Qu.:  8399.5   3rd Qu.:  6673.8   3rd Qu.:  6911.5  
##  Max.   :330167.0   Max.   :331527.0   Max.   :332049.0   Max.   :333271.0  
##  NA's   :6          NA's   :6          NA's   :6          NA's   :6         
##       2023               2024         
##  Min.   :     0.0   Min.   :     0.0  
##  1st Qu.:     3.3   1st Qu.:     2.3  
##  Median :    24.6   Median :    24.6  
##  Mean   : 19588.4   Mean   : 19730.7  
##  3rd Qu.:  5552.9   3rd Qu.:  6720.8  
##  Max.   :334915.0   Max.   :336175.0  
##  NA's   :6          NA's   :6

Esta base muestra información demográfica y financiera de la población, indicando el nivel de bancarización por región, edad y grupo socioeconómico. Permite identificar oportunidades de mercado, segmentos subatendidos y evaluar el impacto de políticas de inclusión financiera.

# 4. ESTADÍSTICOS DE TRANSACCIONES MÓVILES
cat("\n\n=== ESTADÍSTICOS DE TRANSACCIONES MÓVILES ===\n")
## 
## 
## === ESTADÍSTICOS DE TRANSACCIONES MÓVILES ===
cat("Estructura de la base:\n")
## Estructura de la base:
print(str(transacciones))
## tibble [3 × 20] (S3: tbl_df/tbl/data.frame)
##  $ Geography       : chr [1:3] "Mexico" "Mexico" "Mexico"
##  $ Category        : chr [1:3] "Financial Cards in Circulation" "Total Card Transactions" "Mobile Payments"
##  $ Data Type       : chr [1:3] "Number of Cards" "Retail Value RSP" "Retail Value RSP"
##  $ Unit            : chr [1:3] "000 cards" "MXN million" "MXN million"
##  $ Current Constant: chr [1:3] "-" "Current Prices" "Current Prices"
##  $ 2010            : chr [1:3] "145997.70000000001" "2791579.2000000002" "-"
##  $ 2011            : chr [1:3] "162007.70000000001" "3141399.1000000001" "-"
##  $ 2012            : chr [1:3] "197265.79999999999" "3465861.7999999998" "-"
##  $ 2013            : chr [1:3] "217481.79999999999" "3808804.5" "-"
##  $ 2014            : num [1:3] 233835 4004976 42484
##  $ 2015            : num [1:3] 247335 4631218 62438
##  $ 2016            : num [1:3] 250646 5161186 88892
##  $ 2017            : num [1:3] 266037 5588399 122279
##  $ 2018            : num [1:3] 275662 6157864 170501
##  $ 2019            : num [1:3] 277407 6969281 234141
##  $ 2020            : num [1:3] 285579 6846228 367388
##  $ 2021            : num [1:3] 282202 7594266 517184
##  $ 2022            : num [1:3] 306685 7566223 662105
##  $ 2023            : num [1:3] 347243 7758785 811298
##  $ 2024            : num [1:3] 370175 8088846 943554
## NULL
cat("\nPrimeras filas:\n")
## 
## Primeras filas:
print(head(transacciones))
## # A tibble: 3 × 20
##   Geography Category   `Data Type` Unit  `Current Constant` `2010` `2011` `2012`
##   <chr>     <chr>      <chr>       <chr> <chr>              <chr>  <chr>  <chr> 
## 1 Mexico    Financial… Number of … 000 … -                  14599… 16200… 19726…
## 2 Mexico    Total Car… Retail Val… MXN … Current Prices     27915… 31413… 34658…
## 3 Mexico    Mobile Pa… Retail Val… MXN … Current Prices     -      -      -     
## # ℹ 12 more variables: `2013` <chr>, `2014` <dbl>, `2015` <dbl>, `2016` <dbl>,
## #   `2017` <dbl>, `2018` <dbl>, `2019` <dbl>, `2020` <dbl>, `2021` <dbl>,
## #   `2022` <dbl>, `2023` <dbl>, `2024` <dbl>
cat("\nResumen de transacciones:\n")
## 
## Resumen de transacciones:
print(summary(transacciones))
##   Geography           Category          Data Type             Unit          
##  Length:3           Length:3           Length:3           Length:3          
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  Current Constant       2010               2011               2012          
##  Length:3           Length:3           Length:3           Length:3          
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##      2013                2014              2015              2016        
##  Length:3           Min.   :  42484   Min.   :  62438   Min.   :  88892  
##  Class :character   1st Qu.: 138159   1st Qu.: 154886   1st Qu.: 169769  
##  Mode  :character   Median : 233835   Median : 247335   Median : 250646  
##                     Mean   :1427098   Mean   :1646997   Mean   :1833575  
##                     3rd Qu.:2119405   3rd Qu.:2439276   3rd Qu.:2705916  
##                     Max.   :4004976   Max.   :4631218   Max.   :5161186  
##       2017              2018              2019              2020        
##  Min.   : 122279   Min.   : 170501   Min.   : 234141   Min.   : 285579  
##  1st Qu.: 194158   1st Qu.: 223081   1st Qu.: 255774   1st Qu.: 326484  
##  Median : 266037   Median : 275662   Median : 277407   Median : 367388  
##  Mean   :1992238   Mean   :2201342   Mean   :2493610   Mean   :2499732  
##  3rd Qu.:2927218   3rd Qu.:3216763   3rd Qu.:3623344   3rd Qu.:3606808  
##  Max.   :5588399   Max.   :6157864   Max.   :6969281   Max.   :6846228  
##       2021              2022              2023              2024        
##  Min.   : 282202   Min.   : 306685   Min.   : 347243   Min.   : 370175  
##  1st Qu.: 399693   1st Qu.: 484395   1st Qu.: 579271   1st Qu.: 656864  
##  Median : 517184   Median : 662105   Median : 811298   Median : 943554  
##  Mean   :2797884   Mean   :2845004   Mean   :2972442   Mean   :3134192  
##  3rd Qu.:4055725   3rd Qu.:4114164   3rd Qu.:4285042   3rd Qu.:4516200  
##  Max.   :7594266   Max.   :7566223   Max.   :7758785   Max.   :8088846

La base de transacciones moviles refleja el comportamiento de pago digital de los usuarios a través de dispositivos móviles. Indica la adopción de tecnología móvil en pagos, mostrando tendencias en mé

# 5. ESTADÍSTICOS DE PARTICIPACIÓN DE REDES

cat("Estructura de la base:\n")
## Estructura de la base:
print(str(redes))
## tibble [4 × 19] (S3: tbl_df/tbl/data.frame)
##  $ Geography          : chr [1:4] "Mexico" "Mexico" "Mexico" "Mexico"
##  $ Category           : chr [1:4] "Financial Cards in Circulation" "Financial Cards in Circulation" "Financial Cards in Circulation" "Financial Cards in Circulation"
##  $ Categorization Type: chr [1:4] "American Express" "Discover Global Network" "Mastercard" "Visa"
##  $ Unit               : chr [1:4] "%" "%" "%" "%"
##  $ 2010               : num [1:4] 18 12.6 43 43
##  $ 2011               : num [1:4] 20 15.8 53 53
##  $ 2012               : num [1:4] 21.5 18.5 56 56
##  $ 2013               : num [1:4] 22 20.1 58.1 57.8
##  $ 2014               : num [1:4] 22.3 24.1 60.3 60.2
##  $ 2015               : num [1:4] 22.7 26.2 60.9 60.7
##  $ 2016               : num [1:4] 23.1 27 62.4 62.2
##  $ 2017               : num [1:4] 23.1 27.1 62.5 62.3
##  $ 2018               : num [1:4] 23.2 28.2 62.5 62.4
##  $ 2019               : num [1:4] 23.3 37.7 63.2 62
##  $ 2020               : num [1:4] 24 40.1 64.9 63.9
##  $ 2021               : num [1:4] 24.8 43.3 66.8 65.9
##  $ 2022               : num [1:4] 25.6 43.9 69 68.3
##  $ 2023               : num [1:4] 26.3 44.8 70.8 70.2
##  $ 2024               : num [1:4] 27.1 45.3 72.8 72.1
## NULL
cat("\nPrimeras filas:\n")
## 
## Primeras filas:
print(head(redes))
## # A tibble: 4 × 19
##   Geography Category     `Categorization Type` Unit  `2010` `2011` `2012` `2013`
##   <chr>     <chr>        <chr>                 <chr>  <dbl>  <dbl>  <dbl>  <dbl>
## 1 Mexico    Financial C… American Express      %       18     20     21.5   22  
## 2 Mexico    Financial C… Discover Global Netw… %       12.6   15.8   18.5   20.1
## 3 Mexico    Financial C… Mastercard            %       43     53     56     58.1
## 4 Mexico    Financial C… Visa                  %       43     53     56     57.8
## # ℹ 11 more variables: `2014` <dbl>, `2015` <dbl>, `2016` <dbl>, `2017` <dbl>,
## #   `2018` <dbl>, `2019` <dbl>, `2020` <dbl>, `2021` <dbl>, `2022` <dbl>,
## #   `2023` <dbl>, `2024` <dbl>
cat("\nResumen de redes:\n")
## 
## Resumen de redes:
print(summary(redes))
##   Geography           Category         Categorization Type     Unit          
##  Length:4           Length:4           Length:4            Length:4          
##  Class :character   Class :character   Class :character    Class :character  
##  Mode  :character   Mode  :character   Mode  :character    Mode  :character  
##                                                                              
##                                                                              
##                                                                              
##       2010            2011            2012            2013      
##  Min.   :12.60   Min.   :15.80   Min.   :18.50   Min.   :20.10  
##  1st Qu.:16.65   1st Qu.:18.95   1st Qu.:20.75   1st Qu.:21.52  
##  Median :30.50   Median :36.50   Median :38.75   Median :39.90  
##  Mean   :29.15   Mean   :35.45   Mean   :38.00   Mean   :39.50  
##  3rd Qu.:43.00   3rd Qu.:53.00   3rd Qu.:56.00   3rd Qu.:57.88  
##  Max.   :43.00   Max.   :53.00   Max.   :56.00   Max.   :58.10  
##       2014            2015            2016            2017      
##  Min.   :22.30   Min.   :22.70   Min.   :23.10   Min.   :23.10  
##  1st Qu.:23.65   1st Qu.:25.32   1st Qu.:26.02   1st Qu.:26.10  
##  Median :42.15   Median :43.45   Median :44.60   Median :44.70  
##  Mean   :41.73   Mean   :42.62   Mean   :43.67   Mean   :43.75  
##  3rd Qu.:60.23   3rd Qu.:60.75   3rd Qu.:62.25   3rd Qu.:62.35  
##  Max.   :60.30   Max.   :60.90   Max.   :62.40   Max.   :62.50  
##       2018            2019            2020            2021      
##  Min.   :23.20   Min.   :23.30   Min.   :24.00   Min.   :24.80  
##  1st Qu.:26.95   1st Qu.:34.10   1st Qu.:36.08   1st Qu.:38.67  
##  Median :45.30   Median :49.85   Median :52.00   Median :54.60  
##  Mean   :44.08   Mean   :46.55   Mean   :48.23   Mean   :50.20  
##  3rd Qu.:62.42   3rd Qu.:62.30   3rd Qu.:64.15   3rd Qu.:66.12  
##  Max.   :62.50   Max.   :63.20   Max.   :64.90   Max.   :66.80  
##       2022            2023            2024      
##  Min.   :25.60   Min.   :26.30   Min.   :27.10  
##  1st Qu.:39.33   1st Qu.:40.17   1st Qu.:40.75  
##  Median :56.10   Median :57.50   Median :58.70  
##  Mean   :51.70   Mean   :53.02   Mean   :54.33  
##  3rd Qu.:68.47   3rd Qu.:70.35   3rd Qu.:72.28  
##  Max.   :69.00   Max.   :70.80   Max.   :72.80

Se muestra la distribución del mercado entre diferentes redes de tarjetas como Visa, Mastercard, American Express, etc. Indica la dominancia de ciertas redes en el mercado mexicano, mostrando la evolución de la participación de mercado a lo largo del tiempo

# 6. ESTADÍSTICOS DE GRUPOS BANCARIOS
cat("\n\n=== ESTADÍSTICOS DE GRUPOS BANCARIOS ===\n")
## 
## 
## === ESTADÍSTICOS DE GRUPOS BANCARIOS ===
cat("Estructura de la base:\n")
## Estructura de la base:
print(str(bancos_clean))
## tibble [25 × 14] (S3: tbl_df/tbl/data.frame)
##  $ Geography: chr [1:25] "Mexico" "Mexico" "Mexico" "Mexico" ...
##  $ Category : chr [1:25] "Financial Cards in Circulation" "Financial Cards in Circulation" "Financial Cards in Circulation" "Financial Cards in Circulation" ...
##  $ Name     : chr [1:25] "Banco Bilbao Vizcaya Argentaria SA" "Almacenes Coppel SA de CV" "Citigroup Inc" "Bancoppel SA" ...
##  $ Data Type: chr [1:25] "Number of Cards" "Number of Cards" "Number of Cards" "Number of Cards" ...
##  $ 2014     : num [1:25] 18.6 10.5 11.3 8.4 2.9 6.6 5.9 3.6 0.5 1.4 ...
##  $ 2015     : num [1:25] 17 10.6 12 9.5 2.9 6.1 6.3 3.2 0.7 1.4 ...
##  $ 2016     : num [1:25] 16.5 11.3 12 8.4 3 6.2 5.6 2.8 1.1 1.5 ...
##  $ 2017     : num [1:25] 15 11.4 12.1 9.2 3.4 5.6 5.3 2.6 1.3 1.6 ...
##  $ 2018     : num [1:25] 11 11.6 15.5 9.8 3.4 5 4.1 2.7 1.4 1.5 ...
##  $ 2019     : num [1:25] 12.4 11.9 11.5 9.8 3.5 4.9 5.3 2.9 1.6 1.5 ...
##  $ 2020     : num [1:25] 13.4 11.7 11.6 9.3 3.5 4.5 5.3 2.9 1.6 1.5 ...
##  $ 2021     : num [1:25] 15.1 12 10.5 7.1 4.2 4.5 5.5 3 2.1 2.2 ...
##  $ 2022     : num [1:25] 13.5 12 8.9 6.5 5.6 4.6 5 3 2.3 2.2 ...
##  $ 2023     : num [1:25] 14.7 11.1 7.2 6.1 5.6 4.9 4 3 2.3 2.1 ...
## NULL
cat("\nPrimeras filas:\n")
## 
## Primeras filas:
print(head(bancos_clean))
## # A tibble: 6 × 14
##   Geography Category Name  `Data Type` `2014` `2015` `2016` `2017` `2018` `2019`
##   <chr>     <chr>    <chr> <chr>        <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
## 1 Mexico    Financi… Banc… Number of …   18.6   17     16.5   15     11     12.4
## 2 Mexico    Financi… Alma… Number of …   10.5   10.6   11.3   11.4   11.6   11.9
## 3 Mexico    Financi… Citi… Number of …   11.3   12     12     12.1   15.5   11.5
## 4 Mexico    Financi… Banc… Number of …    8.4    9.5    8.4    9.2    9.8    9.8
## 5 Mexico    Financi… Metr… Number of …    2.9    2.9    3      3.4    3.4    3.5
## 6 Mexico    Financi… Grup… Number of …    6.6    6.1    6.2    5.6    5      4.9
## # ℹ 4 more variables: `2020` <dbl>, `2021` <dbl>, `2022` <dbl>, `2023` <dbl>
cat("\nTop 5 grupos bancarios (2023):\n")
## 
## Top 5 grupos bancarios (2023):
participacion_bancos <- bancos_clean %>%
  group_by(`Name`) %>%
  summarise(
    participacion_2023 = ifelse(all(is.na(`2023`)), NA, max(`2023`, na.rm = TRUE)),
    .groups = 'drop'
  ) %>%
  filter(!is.na(participacion_2023)) %>%
  arrange(desc(participacion_2023))

print(head(participacion_bancos, 5))
## # A tibble: 5 × 2
##   Name                               participacion_2023
##   <chr>                                           <dbl>
## 1 Total                                           100  
## 2 Others                                           26.5
## 3 Banco Bilbao Vizcaya Argentaria SA               14.7
## 4 Almacenes Coppel SA de CV                        11.1
## 5 Citigroup Inc                                     7.2

Esta base revela la concentración del mercado bancario mexicano, mostrando los principales actores y su evolución temporal. Se logra ver la evolución de la participación de cada grupo bancario en el mercado, permitiendonos identificar tendencias de consolidación, competencia o expansión

DISTRIBUCIÓN POR EMISOR Y NIVEL DE TARJETA

ggplot(tarjetas_clean, aes(x = Issuer, fill = `Card Level`)) +
  geom_bar(position = "dodge") +
  theme_minimal() +
  labs(
    title = "Distribución de Tarjetas por Emisor y Nivel",
    x = "Emisor Bancario",
    y = "Número de Tarjetas",
    fill = "Nivel de Tarjeta"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_fill_brewer(palette = "Set2")

Participacion de Mercados grafica de PIE

network_share <- tarjetas_clean %>% 
  count(Network) %>% 
  mutate(porcentaje = n/sum(n)*100)

ggplot(network_share, aes(x = "", y = porcentaje, fill = Network)) +
  geom_col() + 
  coord_polar(theta = "y") + 
  theme_void() +
  labs(title = "Participación de Mercado por Red de Tarjetas") +
  scale_fill_brewer(palette = "Set1") +
  geom_text(aes(label = paste0(round(porcentaje, 1), "%")), 
            position = position_stack(vjust = 0.5), color = "white", size = 4)

TOP 10 GRUPOS BANCARIOS POR PARTICIPACIÓN

ggplot(participacion_bancos %>% head(10), 
       aes(x = reorder(`Name`, participacion_2023), y = participacion_2023, 
           fill = participacion_2023 > 20)) +
  geom_col() + 
  coord_flip() + 
  theme_minimal() +
  labs(
    title = "Top 10 Grupos Bancarios por Participación de Mercado (2023)",
    x = "Grupo Bancario",
    y = "Participación (%)",
    fill = "Participación > 20%"
  ) +
  scale_fill_manual(values = c("FALSE" = "lightcoral", "TRUE" = "steelblue")) +
  geom_text(aes(label = paste0(round(participacion_2023, 1), "%")), 
            hjust = -0.2, size = 3)

Se creo una gráfica de pastel para mostrar la participación de mercado por red de tarjetas y una gráfica de barras con el top 10 de grupos bancarios en 2023, destacando a los que superan el 20% de participación.

ADOPCIÓN DE TECNOLOGÍA CONTACTLESS

contactless_share <- tarjetas_clean %>% 
  count(Contactless) %>% 
  mutate(porcentaje = n/sum(n)*100)

ggplot(contactless_share, aes(x = "", y = porcentaje, fill = Contactless)) +
  geom_col() + 
  coord_polar(theta = "y") + 
  theme_void() +
  labs(title = "Adopción de Tecnología Contactless") +
  scale_fill_manual(values = c("No" = "lightcoral", "Sí" = "lightgreen")) +
  geom_text(aes(label = paste0(round(porcentaje, 1), "%")), 
            position = position_stack(vjust = 0.5), color = "white", size = 5)

RELACIÓN FEE ANUAL vs APR REGULAR

ggplot(tarjetas_clean, aes(x = `Annual Fee`, y = `Regular APR`, color = `Card Level`)) +
  geom_point(alpha = 0.7, size = 2) + 
  theme_minimal() +
  labs(
    title = "Relación entre Fee Anual y APR Regular",
    x = "Fee Anual (MXN)",
    y = "APR Regular (%)",
    color = "Nivel de Tarjeta"
  ) +
  scale_color_brewer(palette = "Set1") +
  geom_smooth(method = "lm", se = FALSE, color = "red", linetype = "dashed")
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 104 rows containing non-finite outside the scale range
## (`stat_smooth()`).
## Warning: Removed 104 rows containing missing values or values outside the scale range
## (`geom_point()`).

LA EVOLUCIÓN DE TIPOS DE TARJETA del 2010-2024

tipos_long <- tipos %>%
  pivot_longer(cols = -Year, names_to = "Tipo", values_to = "Porcentaje")

ggplot(tipos_long, aes(x = Year, y = Porcentaje, fill = Tipo)) +
  geom_area(position = "stack", alpha = 0.8) +
  theme_minimal() +
  labs(
    title = "Evolución de Tipos de Tarjeta en México (2010-2024)",
    x = "Año",
    y = "Porcentaje (%)",
    fill = "Tipo de Tarjeta"
  ) +
  scale_fill_brewer(palette = "Set3") +
  theme(legend.position = "bottom")

LA EVOLUCIÓN DE LA POBLACIÓN BANCARIZADA

mexico_banked <- participacion %>%
  filter(Geography == "Mexico", Title == "Banked population (000s)")

years <- grep("^20", names(mexico_banked), value = TRUE)
mexico_banked[years] <- lapply(mexico_banked[years], function(x) as.numeric(gsub(",", "", x)))

mexico_long <- mexico_banked %>%
  pivot_longer(cols = all_of(years), names_to = "Año", values_to = "Clientes")

ggplot(mexico_long, aes(x = Año, y = Clientes, group = 1)) +
  geom_line(color = "steelblue", size = 1.5) +
  geom_point(color = "red", size = 3) +
  theme_minimal() +
  labs(
    title = "Evolución de Población Bancarizada en México",
    x = "Año",
    y = "Número de Clientes (000s)"
  ) +
  scale_x_discrete(guide = guide_axis(angle = 45))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

#  Limpieza previa de trasancacciones
transacciones_clean <- transacciones %>%
  mutate(across(starts_with("20"), ~as.numeric(ifelse(. == "-", NA, .))))
trans_long <- transacciones_clean %>%
  pivot_longer(
    cols = starts_with("20"),
    names_to = "Año",
    values_to = "Valor"
  ) %>%
  mutate(
    Año = as.numeric(Año),
    Valor = as.numeric(Valor)
  ) %>%
  filter(!is.na(Valor))

cat("trans_long creado exitosamente con", nrow(trans_long), "filas\n")
## trans_long creado exitosamente con 41 filas
# Verificar que trans_long existe y tiene datos
cat("=== VERIFICACIÓN DE TRANS_LONG ===\n")
## === VERIFICACIÓN DE TRANS_LONG ===
cat("Número de filas:", nrow(trans_long), "\n")
## Número de filas: 41
cat("Estructura:\n")
## Estructura:
str(trans_long)
## tibble [41 × 7] (S3: tbl_df/tbl/data.frame)
##  $ Geography       : chr [1:41] "Mexico" "Mexico" "Mexico" "Mexico" ...
##  $ Category        : chr [1:41] "Financial Cards in Circulation" "Financial Cards in Circulation" "Financial Cards in Circulation" "Financial Cards in Circulation" ...
##  $ Data Type       : chr [1:41] "Number of Cards" "Number of Cards" "Number of Cards" "Number of Cards" ...
##  $ Unit            : chr [1:41] "000 cards" "000 cards" "000 cards" "000 cards" ...
##  $ Current Constant: chr [1:41] "-" "-" "-" "-" ...
##  $ Año             : num [1:41] 2010 2011 2012 2013 2014 ...
##  $ Valor           : num [1:41] 145998 162008 197266 217482 233835 ...
cat("\nPrimeras filas:\n")
## 
## Primeras filas:
print(head(trans_long))
## # A tibble: 6 × 7
##   Geography Category           `Data Type` Unit  `Current Constant`   Año  Valor
##   <chr>     <chr>              <chr>       <chr> <chr>              <dbl>  <dbl>
## 1 Mexico    Financial Cards i… Number of … 000 … -                   2010 1.46e5
## 2 Mexico    Financial Cards i… Number of … 000 … -                   2011 1.62e5
## 3 Mexico    Financial Cards i… Number of … 000 … -                   2012 1.97e5
## 4 Mexico    Financial Cards i… Number of … 000 … -                   2013 2.17e5
## 5 Mexico    Financial Cards i… Number of … 000 … -                   2014 2.34e5
## 6 Mexico    Financial Cards i… Number of … 000 … -                   2015 2.47e5

LA EVOLUCIÓN DE TRANSACCIONES MÓVILES

ggplot(trans_long, aes(x = Año, y = Valor, color = Category)) +
  geom_line(size = 1.2) +
  geom_point(size = 2) +
  theme_minimal() +
  labs(
    title = "Evolución de Transacciones Financieras en México",
    x = "Año",
    y = "Valor (MXN millones o miles de tarjetas)",
    color = "Categoría"
  ) +
  scale_color_brewer(palette = "Set1")

EL CRECIMIENTO POR CATEGORÍA (2010-2024)

crecimiento_categoria <- trans_long %>%
  group_by(Category) %>%
  summarise(
    Crecimiento = (last(Valor) - first(Valor)) / first(Valor) * 100
  )

cat("\nCrecimiento por categoría:\n")
## 
## Crecimiento por categoría:
print(crecimiento_categoria)
## # A tibble: 3 × 2
##   Category                       Crecimiento
##   <chr>                                <dbl>
## 1 Financial Cards in Circulation        154.
## 2 Mobile Payments                      2121.
## 3 Total Card Transactions               190.
ggplot(crecimiento_categoria, aes(x = reorder(Category, Crecimiento), y = Crecimiento, 
                                 fill = Crecimiento > 0)) +
  geom_col() +
  theme_minimal() +
  labs(
    title = "Crecimiento % de 2010 a 2024 por Categoría",
    x = "Categoría",
    y = "Crecimiento (%)"
  ) +
  scale_fill_manual(values = c("FALSE" = "lightcoral", "TRUE" = "lightgreen")) +
  coord_flip() +
  geom_text(aes(label = paste0(round(Crecimiento, 1), "%")), 
            hjust = ifelse(crecimiento_categoria$Crecimiento > 0, -0.2, 1.2), size = 3)

COMPARACIÓN entre VISA vs MASTERCARD

visa_mastercard <- tarjetas_clean %>%
  filter(Network %in% c("Visa", "Mastercard")) %>%
  group_by(Network) %>%
  summarise(
    total_tarjetas = n(),
    promedio_APR = mean(`Regular APR`, na.rm = TRUE),
    promedio_fee = mean(`Annual Fee`, na.rm = TRUE),
    promedio_rewards = mean(`Rewards Rate`, na.rm = TRUE),
    porcentaje_premium = mean(`Card Level` %in% c("Premium", "Premium Plus"), na.rm = TRUE) * 100,
    porcentaje_contactless = mean(Contactless == "Sí", na.rm = TRUE) * 100
  )

visa_mastercard_long <- visa_mastercard %>%
  pivot_longer(
    cols = c(promedio_APR, promedio_fee, promedio_rewards, porcentaje_premium, porcentaje_contactless),
    names_to = "Metrica",
    values_to = "Valor"
  )

ggplot(visa_mastercard_long, aes(x = Metrica, y = Valor, fill = Network)) +
  geom_col(position = "dodge") +
  theme_minimal() +
  labs(
    title = "Comparación Visa vs Mastercard en el Mercado Mexicano",
    x = "Métrica",
    y = "Valor",
    fill = "Red de Tarjetas"
  ) +
  scale_fill_manual(values = c("Visa" = "gold", "Mastercard" = "red")) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  geom_text(aes(label = round(Valor, 1)), position = position_dodge(width = 0.9), 
            vjust = -0.5, size = 3)

Correlación entre características de tarjetas

correlation_data <- tarjetas_clean %>%
  select(`Regular APR`, `Annual Fee`, `Rewards Rate`) %>%
  cor(use = "complete.obs")

# heatmap de correlacion
corrplot(correlation_data, method = "color", type = "upper", 
         addCoef.col = "black", tl.col = "black", tl.srt = 45,
         title = "Matriz de Correlación entre Características de Tarjetas")

Evolución temporal de redes

redes_long <- redes %>%
  pivot_longer(cols = starts_with("20"), names_to = "Año", values_to = "Participacion") %>%
  mutate(Año = as.numeric(Año))

ggplot(redes_long, aes(x = Año, y = Participacion, color = `Categorization Type`)) +
  geom_line(size = 1.5) +
  geom_point(size = 3) +
  theme_minimal() +
  labs(
    title = "Evolución de Participación de Redes de Tarjetas (2010-2024)",
    x = "Año",
    y = "Participación (%)",
    color = "Red"
  ) +
  scale_color_brewer(palette = "Set1")

### Crecimiento Anual Compuesto Población Bancarizada

cagr_calculo <- function(valor_inicial, valor_final, años) {
  (valor_final / valor_inicial)^(1/años) - 1
}

years <- grep("^20", names(mexico_banked), value = TRUE)

# Convertir columnas de años a numérico y eliminar NAs
mexico_banked_clean <- mexico_banked %>%
  mutate(across(all_of(years), ~as.numeric(gsub(",", "", .))))

cagr_poblacion <- mexico_banked_clean %>%
  summarise(
    cagr = cagr_calculo(
      first(na.omit(unlist(select(., all_of(years))))), 
      last(na.omit(unlist(select(., all_of(years))))), 
      length(years)
    ) * 100
  )

cat("Crecimiento Anual Compuesto Población Bancarizada:", 
    round(as.numeric(cagr_poblacion$cagr), 2), "%\n")
## Crecimiento Anual Compuesto Población Bancarizada: 5.44 %

Finalidad del estudio

La finalidad de este análisis fue aplicar los conceptos aprendidos a lo largo de la carrera de Inteligencia de Negocios en el Tecnológico de Monterrey para entender, limpiar y manipular seis bases de datos diferentes. Esto permitió explorar la información disponible, generar insights relevantes y preparar visualizaciones y tableros que faciliten la interpretación de los datos.

Los resultados obtenidos sirven como base para la siguiente evidencia y pueden ser utilizados para presentar hallazgos de manera clara a compañeros, profesores y directivos, apoyando la mejora en la toma de decisiones estratégicas.

LS0tCnRpdGxlOiAiQW5hbGlzaXMgRXZpZGVuY2lhIDEgUkVUTyIKYXV0aG9yOiAiU2ViYXN0aWFuIEVzcGlub3phIEEwMDgzMzcwNCIKZGF0ZTogIjIwMjUtMDgtMjUiCm91dHB1dDogCiBodG1sX2RvY3VtZW50OiAKICB0b2M6IFRSVUUKICB0b2NfZmxvYXQ6IFRSVUUKICBjb2RlX2Rvd25sb2FkOiBUUlVFCiAgdGhlbWU6IHlldGkKLS0tCgojIDxzcGFuIHN0eWxlPSdjb2xvcjpCbHVlOyc+ICBBbmFsaXNpcyBkZSBFdmlkZW5jaWEgMSA8L3NwYW4+IAoKIVtdKGh0dHBzOi8vbGVhZHNhbGVzLmlvL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDIxLzA5L0dpZi1iYW5jby1kaWdpdGFsLmdpZikKCiMjIDxzcGFuIHN0eWxlPSdjb2xvcjpyZWQ7Jz4gIENhcmdhciBsaWJyZXJpYXMgeSBiYXNlIGRlIGRhdG9zIDwvc3Bhbj4gCgpgYGB7cn0KIyBDYXJnYXIgbGlicmVyw61hcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoY29ycnBsb3QpCgojIENhcmdhciBiYXNlcyBkZSBkYXRvcwoKIyBiYXNlIGRlIGRhdG9zIHRpcG9zIGRlIHRhcmpldGFzCnRpcG9zIDwtIHJlYWRfZXhjZWwoIi9Vc2Vycy9zZWJhc3RpYW5lc3BpL0Rvd25sb2Fkcy9UIGJhc2UgZGUgZGF0b3MgUkVUTy9UaXBvcyBkZSB0YXJqZXRhcy54bHMiKQoKIyBiYXNlIGRlIGRhdG9zIFBvYmxhY2nDs24gYmFuY2FyaXphZGEueGxzCnBhcnRpY2lwYWNpb24gPC0gcmVhZF9leGNlbCgiL1VzZXJzL3NlYmFzdGlhbmVzcGkvRG93bmxvYWRzL1QgYmFzZSBkZSBkYXRvcyBSRVRPL1BvYmxhY2lvbkIueGxzIikKCiMgYmFzZSBkZSBkYXRvcyBDYXJhY3RlcsOtc3RpY2FzIGRlIHRhcmpldGFzIHBvciBncnVwbyBiYW5jYXJpby54bHN4CnRhcmpldGFzIDwtIHJlYWRfZXhjZWwoIi9Vc2Vycy9zZWJhc3RpYW5lc3BpL0Rvd25sb2Fkcy9UIGJhc2UgZGUgZGF0b3MgUkVUTy9OdWV2YWJhc2VDYXJhY3RlcmlzdGljYXMueGxzeCIpCgojIGJhc2UgZGUgZGF0b3MgdHJhbnNhY2Npb25lcyBtb3ZpbGVzCnRyYW5zYWNjaW9uZXMgPC0gcmVhZF9leGNlbCgiL1VzZXJzL3NlYmFzdGlhbmVzcGkvRG93bmxvYWRzL1QgYmFzZSBkZSBkYXRvcyBSRVRPL1RyYW5zYWNjaW9uZXMgbW92aWxlcy54bHMiKQoKIyBiYXNlIGRlIGRhdG9zIFBhcnRpY2lwYWNpw7NuIGRlIHRhcmpldGFzCnJlZGVzIDwtIHJlYWRfZXhjZWwoIi9Vc2Vycy9zZWJhc3RpYW5lc3BpL0Rvd25sb2Fkcy9UIGJhc2UgZGUgZGF0b3MgUkVUTy9QYXJ0aWNpcGFjaW9uIGRlIHJlZGVzIGRlIHRhcmpldGFzLnhscyIpCgojIGJhc2UgZGUgZGF0b3MgUGFydGljaXBhY2nDs24gZGUgZ3J1cG9zIGJhbmNhcmlvcwpiYW5jb3MgPC0gcmVhZF9leGNlbCgiL1VzZXJzL3NlYmFzdGlhbmVzcGkvRG93bmxvYWRzL1QgYmFzZSBkZSBkYXRvcyBSRVRPL1BhcnRpY2lwYWNpb24gZGUgZ3J1cG9zIGJhbmNhcmlvcy54bHN4IikKCmBgYAoKQXF1w60gc2UgY2FyZ2Fyb24gbGFzIGxpYnJlcsOtYXMgeSBzZWlzIGJhc2VzIGRlIGRhdG9zIGVuIEV4Y2VsIHNvYnJlIHRhcmpldGFzLCBwb2JsYWNpw7NuIGJhbmNhcml6YWRhLCB0cmFuc2FjY2lvbmVzIHkgcGFydGljaXBhY2nDs24gYmFuY2FyaWEgcGFyYSBwcmVwYXJhciBsYSBpbmZvcm1hY2nDs24gZGVsIGFuw6FsaXNpcy4KCiMjIDxzcGFuIHN0eWxlPSdjb2xvcjpyZWQ7Jz4gIEV2aWRlbmNpYSAxIDwvc3Bhbj4gCgojIyMgPHNwYW4gc3R5bGU9J2NvbG9yOnJlZDsnPiAgQW5hbGlzaXMgRXhwbG9yYXRvcmlvIGRlIGxhcyA2IGJhc2VzIGRlIERhdG9zIGRlbCBDYXNvIDwvc3Bhbj4gCmBgYHtyfQp0YXJqZXRhc19jbGVhbiA8LSB0YXJqZXRhcyAlPiUKICBtdXRhdGUoCiAgICBgUmVndWxhciBBUFJgID0gYXMubnVtZXJpYyhzdHJfcmVwbGFjZV9hbGwoYFJlZ3VsYXIgQVBSYCwgIiV8XFxzIiwgIiIpKSwKICAgIGBBbm51YWwgRmVlYCA9IGFzLm51bWVyaWMoc3RyX3JlcGxhY2VfYWxsKGBBbm51YWwgRmVlYCwgIk1YTnwsfFxccyIsICIiKSksCiAgICBgUmV3YXJkcyBSYXRlYCA9IGFzLm51bWVyaWMoc3RyX3JlcGxhY2VfYWxsKGBSZXdhcmRzIFJhdGVgLCAiW14wLTlcXC5dIiwgIiIpKSwKICAgIENvbnRhY3RsZXNzID0gaWZlbHNlKHN0cl9kZXRlY3QoYEtleSBGZWF0dXJlc2AsICJDb250YWN0bGVzcyIpLCAiU8OtIiwgIk5vIikKICApCgpiYW5jb3NfY2xlYW4gPC0gYmFuY29zICU+JQogIG11dGF0ZShhY3Jvc3Moc3RhcnRzX3dpdGgoIjIwIiksIH5hcy5udW1lcmljKGlmZWxzZSguID09ICItIiwgTkEsIC4pKSkpCgpgYGAKRWwgY8OzZGlnbyBsaW1wacOzIHkgZXN0YW5kYXJpesOzIGxvcyBkYXRvcywgY29udmlydGllbmRvIHRhc2FzLCBjdW90YXMgeSByZWNvbXBlbnNhcyBhIGZvcm1hdG8gbnVtw6lyaWNvLCB5IG1hcmNhbmRvIHNpIGxhcyB0YXJqZXRhcyBzb24gQ29udGFjdGxlc3MuIEVzdG8gZmFjaWxpdGEgYW7DoWxpc2lzIGVzdGFkw61zdGljbyB5IGNvbXBhcmFjacOzbiBkZSBwcm9kdWN0b3MuIAoKIyMjIDxzcGFuIHN0eWxlPSdjb2xvcjpyZWQ7Jz4gRXN0YWTDrXN0aWNvcyBiw6FzaWNvcyA8L3NwYW4+CgpgYGB7cn0KIyBFU1RBRMONU1RJQ09TIERFIFRBUkpFVEEKY2F0KCJFc3RhZMOtc3RpY29zIG51bcOpcmljb3M6XG4iKQpwcmludChzdW1tYXJ5KHRhcmpldGFzX2NsZWFuICU+JSBzZWxlY3QoYFJlZ3VsYXIgQVBSYCwgYEFubnVhbCBGZWVgLCBgUmV3YXJkcyBSYXRlYCkpKQoKIyBUb3AgNSBlbWlzb3JlcyBwb3IgbsO6bWVybyBkZSB0YXJqZXRhcwpwcmludCh0YXJqZXRhc19jbGVhbiAlPiUgY291bnQoSXNzdWVyKSAlPiUgYXJyYW5nZShkZXNjKG4pKSAlPiUgaGVhZCg1KSkKCiMgUGFydGljaXBhY2nDs24gcG9yIHJlZApwcmludCh0YXJqZXRhc19jbGVhbiAlPiUgY291bnQoTmV0d29yaykgJT4lIG11dGF0ZShwb3JjZW50YWplID0gbi9zdW0obikqMTAwKSkKCiMgRGlzdHJpYnVjacOzbiBwb3Igbml2ZWwgZGUgdGFyamV0YQpwcmludCh0YXJqZXRhc19jbGVhbiAlPiUgY291bnQoYENhcmQgTGV2ZWxgKSAlPiUgbXV0YXRlKHBvcmNlbnRhamUgPSBuL3N1bShuKSoxMDApKQoKYGBgCgpMYSBiYXNlIG11ZXN0cmEgdGFyamV0YXMgcG9yIG5pdmVsLCBlbWlzb3IgeSByZWQsIGNvbiBsYSBtYXlvcsOtYSBkZSBkYXRvcyBmYWx0YW50ZXMuIEFQUiB2YSBkZSAyMS4xMiUgYSA2OC4wOSUsIGN1b3RhIGFudWFsIGRlICQ2NDAgYSAkNSw4MDAgTVhOIHkgcmVjb21wZW5zYXMgZGUgMSUgYSAxMTAlLCByZWZsZWphbmRvIGRpdmVyc2lkYWQgZGUgcHJvZHVjdG9zIHkgc2VnbWVudGFjacOzbiBkZWwgbWVyY2Fkby4KCmBgYHtyfQojIDIuIEVTVEFEw41TVElDT1MgREUgVElQT1MgREUgVEFSSkVUQVMKY2F0KCJFc3RydWN0dXJhIGRlIGxhIGJhc2U6XG4iKQpwcmludChzdHIodGlwb3MpKQoKY2F0KCJcblByaW1lcmFzIGZpbGFzOlxuIikKcHJpbnQoaGVhZCh0aXBvcykpCgpjYXQoIlxuUmVzdW1lbiBkZSB0aXBvczpcbiIpCnByaW50KHN1bW1hcnkodGlwb3MpKQpgYGAKCkVzdGEgYmFzZSBjbGFzaWZpY2EgbGFzIHRhcmpldGFzIHBvciBjYXRlZ29yw61hIHkgY2FyYWN0ZXLDrXN0aWNhcywgbW9zdHJhbmRvIGxhIGRpdmVyc2lmaWNhY2nDs24gZGVsIG1lcmNhZG8uIE5vcyBwZXJtaXRlIGlkZW50aWZpY2FyIHRlbmRlbmNpYXMsIGFuYWxpemFyIGxhIGVzdHJhdGVnaWEgZGUgcHJvZHVjdG8gZGUgY2FkYSBlbWlzb3IgeSBzZWd1aXIgbGEgZXZvbHVjacOzbiBkZWwgc2VjdG9yLgoKYGBge3J9CiMgMy4gRVNUQUTDjVNUSUNPUyBERSBQT0JMQUNJw5NOIEJBTkNBUklaQURBCmNhdCgiXG5cbj09PSBFU1RBRMONU1RJQ09TIERFIFBPQkxBQ0nDk04gQkFOQ0FSSVpBREEgPT09XG4iKQpjYXQoIkVzdHJ1Y3R1cmEgZGUgbGEgYmFzZTpcbiIpCnByaW50KHN0cihwYXJ0aWNpcGFjaW9uKSkKCmNhdCgiXG5QcmltZXJhcyBmaWxhczpcbiIpCnByaW50KGhlYWQocGFydGljaXBhY2lvbikpCgpjYXQoIlxuUmVzdW1lbiBkZSBwYXJ0aWNpcGFjacOzbjpcbiIpCnByaW50KHN1bW1hcnkocGFydGljaXBhY2lvbikpCmBgYAoKRXN0YSBiYXNlIG11ZXN0cmEgaW5mb3JtYWNpw7NuIGRlbW9ncsOhZmljYSB5IGZpbmFuY2llcmEgZGUgbGEgcG9ibGFjacOzbiwgaW5kaWNhbmRvIGVsIG5pdmVsIGRlIGJhbmNhcml6YWNpw7NuIHBvciByZWdpw7NuLCBlZGFkIHkgZ3J1cG8gc29jaW9lY29uw7NtaWNvLiBQZXJtaXRlIGlkZW50aWZpY2FyIG9wb3J0dW5pZGFkZXMgZGUgbWVyY2Fkbywgc2VnbWVudG9zIHN1YmF0ZW5kaWRvcyB5IGV2YWx1YXIgZWwgaW1wYWN0byBkZSBwb2zDrXRpY2FzIGRlIGluY2x1c2nDs24gZmluYW5jaWVyYS4KCmBgYHtyfQojIDQuIEVTVEFEw41TVElDT1MgREUgVFJBTlNBQ0NJT05FUyBNw5NWSUxFUwpjYXQoIlxuXG49PT0gRVNUQUTDjVNUSUNPUyBERSBUUkFOU0FDQ0lPTkVTIE3Dk1ZJTEVTID09PVxuIikKY2F0KCJFc3RydWN0dXJhIGRlIGxhIGJhc2U6XG4iKQpwcmludChzdHIodHJhbnNhY2Npb25lcykpCgpjYXQoIlxuUHJpbWVyYXMgZmlsYXM6XG4iKQpwcmludChoZWFkKHRyYW5zYWNjaW9uZXMpKQoKY2F0KCJcblJlc3VtZW4gZGUgdHJhbnNhY2Npb25lczpcbiIpCnByaW50KHN1bW1hcnkodHJhbnNhY2Npb25lcykpCmBgYAoKTGEgYmFzZSBkZSB0cmFuc2FjY2lvbmVzIG1vdmlsZXMgcmVmbGVqYSBlbCBjb21wb3J0YW1pZW50byBkZSBwYWdvIGRpZ2l0YWwgZGUgbG9zIHVzdWFyaW9zIGEgdHJhdsOpcyBkZSBkaXNwb3NpdGl2b3MgbcOzdmlsZXMuIEluZGljYSBsYSBhZG9wY2nDs24gZGUgdGVjbm9sb2fDrWEgbcOzdmlsIGVuIHBhZ29zLCBtb3N0cmFuZG8gdGVuZGVuY2lhcyBlbiBtw6kKCmBgYHtyfQojIDUuIEVTVEFEw41TVElDT1MgREUgUEFSVElDSVBBQ0nDk04gREUgUkVERVMKCmNhdCgiRXN0cnVjdHVyYSBkZSBsYSBiYXNlOlxuIikKcHJpbnQoc3RyKHJlZGVzKSkKCmNhdCgiXG5QcmltZXJhcyBmaWxhczpcbiIpCnByaW50KGhlYWQocmVkZXMpKQoKY2F0KCJcblJlc3VtZW4gZGUgcmVkZXM6XG4iKQpwcmludChzdW1tYXJ5KHJlZGVzKSkKCmBgYAoKU2UgbXVlc3RyYSBsYSBkaXN0cmlidWNpw7NuIGRlbCBtZXJjYWRvIGVudHJlIGRpZmVyZW50ZXMgcmVkZXMgZGUgdGFyamV0YXMgY29tbyBWaXNhLCBNYXN0ZXJjYXJkLCBBbWVyaWNhbiBFeHByZXNzLCBldGMuIEluZGljYSBsYSBkb21pbmFuY2lhIGRlIGNpZXJ0YXMgcmVkZXMgZW4gZWwgbWVyY2FkbyBtZXhpY2FubywgbW9zdHJhbmRvIGxhIGV2b2x1Y2nDs24gZGUgbGEgcGFydGljaXBhY2nDs24gZGUgbWVyY2FkbyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8KCmBgYHtyfQojIDYuIEVTVEFEw41TVElDT1MgREUgR1JVUE9TIEJBTkNBUklPUwpjYXQoIlxuXG49PT0gRVNUQUTDjVNUSUNPUyBERSBHUlVQT1MgQkFOQ0FSSU9TID09PVxuIikKY2F0KCJFc3RydWN0dXJhIGRlIGxhIGJhc2U6XG4iKQpwcmludChzdHIoYmFuY29zX2NsZWFuKSkKCmNhdCgiXG5QcmltZXJhcyBmaWxhczpcbiIpCnByaW50KGhlYWQoYmFuY29zX2NsZWFuKSkKCmNhdCgiXG5Ub3AgNSBncnVwb3MgYmFuY2FyaW9zICgyMDIzKTpcbiIpCnBhcnRpY2lwYWNpb25fYmFuY29zIDwtIGJhbmNvc19jbGVhbiAlPiUKICBncm91cF9ieShgTmFtZWApICU+JQogIHN1bW1hcmlzZSgKICAgIHBhcnRpY2lwYWNpb25fMjAyMyA9IGlmZWxzZShhbGwoaXMubmEoYDIwMjNgKSksIE5BLCBtYXgoYDIwMjNgLCBuYS5ybSA9IFRSVUUpKSwKICAgIC5ncm91cHMgPSAnZHJvcCcKICApICU+JQogIGZpbHRlcighaXMubmEocGFydGljaXBhY2lvbl8yMDIzKSkgJT4lCiAgYXJyYW5nZShkZXNjKHBhcnRpY2lwYWNpb25fMjAyMykpCgpwcmludChoZWFkKHBhcnRpY2lwYWNpb25fYmFuY29zLCA1KSkKYGBgCkVzdGEgYmFzZSByZXZlbGEgbGEgY29uY2VudHJhY2nDs24gZGVsIG1lcmNhZG8gYmFuY2FyaW8gbWV4aWNhbm8sIG1vc3RyYW5kbyBsb3MgcHJpbmNpcGFsZXMgYWN0b3JlcyB5IHN1IGV2b2x1Y2nDs24gdGVtcG9yYWwuIFNlIGxvZ3JhIHZlciBsYSBldm9sdWNpw7NuIGRlIGxhIHBhcnRpY2lwYWNpw7NuIGRlIGNhZGEgZ3J1cG8gYmFuY2FyaW8gZW4gZWwgbWVyY2FkbywgcGVybWl0aWVuZG9ub3MgaWRlbnRpZmljYXIgdGVuZGVuY2lhcyBkZSBjb25zb2xpZGFjacOzbiwgY29tcGV0ZW5jaWEgbyBleHBhbnNpw7NuCgoKIyMjIDxzcGFuIHN0eWxlPSdjb2xvcjpyZWQ7Jz4gRElTVFJJQlVDScOTTiBQT1IgRU1JU09SIFkgTklWRUwgREUgVEFSSkVUQSAgPC9zcGFuPiAKCmBgYHtyfQpnZ3Bsb3QodGFyamV0YXNfY2xlYW4sIGFlcyh4ID0gSXNzdWVyLCBmaWxsID0gYENhcmQgTGV2ZWxgKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgVGFyamV0YXMgcG9yIEVtaXNvciB5IE5pdmVsIiwKICAgIHggPSAiRW1pc29yIEJhbmNhcmlvIiwKICAgIHkgPSAiTsO6bWVybyBkZSBUYXJqZXRhcyIsCiAgICBmaWxsID0gIk5pdmVsIGRlIFRhcmpldGEiCiAgKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpCmBgYAoKCiMjIyA8c3BhbiBzdHlsZT0nY29sb3I6cmVkOyc+IFBhcnRpY2lwYWNpb24gZGUgTWVyY2Fkb3MgZ3JhZmljYSBkZSBQSUUgPC9zcGFuPiAKCmBgYHtyfQpuZXR3b3JrX3NoYXJlIDwtIHRhcmpldGFzX2NsZWFuICU+JSAKICBjb3VudChOZXR3b3JrKSAlPiUgCiAgbXV0YXRlKHBvcmNlbnRhamUgPSBuL3N1bShuKSoxMDApCgpnZ3Bsb3QobmV0d29ya19zaGFyZSwgYWVzKHggPSAiIiwgeSA9IHBvcmNlbnRhamUsIGZpbGwgPSBOZXR3b3JrKSkgKwogIGdlb21fY29sKCkgKyAKICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKyAKICB0aGVtZV92b2lkKCkgKwogIGxhYnModGl0bGUgPSAiUGFydGljaXBhY2nDs24gZGUgTWVyY2FkbyBwb3IgUmVkIGRlIFRhcmpldGFzIikgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHJvdW5kKHBvcmNlbnRhamUsIDEpLCAiJSIpKSwgCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSA0KQpgYGAKCgojIyMgPHNwYW4gc3R5bGU9J2NvbG9yOnJlZDsnPiAgVE9QIDEwIEdSVVBPUyBCQU5DQVJJT1MgUE9SIFBBUlRJQ0lQQUNJw5NOIDwvc3Bhbj4gCmBgYHtyfQpnZ3Bsb3QocGFydGljaXBhY2lvbl9iYW5jb3MgJT4lIGhlYWQoMTApLCAKICAgICAgIGFlcyh4ID0gcmVvcmRlcihgTmFtZWAsIHBhcnRpY2lwYWNpb25fMjAyMyksIHkgPSBwYXJ0aWNpcGFjaW9uXzIwMjMsIAogICAgICAgICAgIGZpbGwgPSBwYXJ0aWNpcGFjaW9uXzIwMjMgPiAyMCkpICsKICBnZW9tX2NvbCgpICsgCiAgY29vcmRfZmxpcCgpICsgCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiVG9wIDEwIEdydXBvcyBCYW5jYXJpb3MgcG9yIFBhcnRpY2lwYWNpw7NuIGRlIE1lcmNhZG8gKDIwMjMpIiwKICAgIHggPSAiR3J1cG8gQmFuY2FyaW8iLAogICAgeSA9ICJQYXJ0aWNpcGFjacOzbiAoJSkiLAogICAgZmlsbCA9ICJQYXJ0aWNpcGFjacOzbiA+IDIwJSIKICApICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJGQUxTRSIgPSAibGlnaHRjb3JhbCIsICJUUlVFIiA9ICJzdGVlbGJsdWUiKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAocm91bmQocGFydGljaXBhY2lvbl8yMDIzLCAxKSwgIiUiKSksIAogICAgICAgICAgICBoanVzdCA9IC0wLjIsIHNpemUgPSAzKQpgYGAKCgpTZSBjcmVvIHVuYSBncsOhZmljYSBkZSBwYXN0ZWwgcGFyYSBtb3N0cmFyIGxhIHBhcnRpY2lwYWNpw7NuIGRlIG1lcmNhZG8gcG9yIHJlZCBkZSB0YXJqZXRhcyB5IHVuYSBncsOhZmljYSBkZSBiYXJyYXMgY29uIGVsIHRvcCAxMCBkZSBncnVwb3MgYmFuY2FyaW9zIGVuIDIwMjMsIGRlc3RhY2FuZG8gYSBsb3MgcXVlIHN1cGVyYW4gZWwgMjAlIGRlIHBhcnRpY2lwYWNpw7NuLgoKIyMjIDxzcGFuIHN0eWxlPSdjb2xvcjpyZWQ7Jz4gIEFET1BDScOTTiBERSBURUNOT0xPR8ONQSBDT05UQUNUTEVTUyA8L3NwYW4+CgpgYGB7cn0KY29udGFjdGxlc3Nfc2hhcmUgPC0gdGFyamV0YXNfY2xlYW4gJT4lIAogIGNvdW50KENvbnRhY3RsZXNzKSAlPiUgCiAgbXV0YXRlKHBvcmNlbnRhamUgPSBuL3N1bShuKSoxMDApCgpnZ3Bsb3QoY29udGFjdGxlc3Nfc2hhcmUsIGFlcyh4ID0gIiIsIHkgPSBwb3JjZW50YWplLCBmaWxsID0gQ29udGFjdGxlc3MpKSArCiAgZ2VvbV9jb2woKSArIAogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArIAogIHRoZW1lX3ZvaWQoKSArCiAgbGFicyh0aXRsZSA9ICJBZG9wY2nDs24gZGUgVGVjbm9sb2fDrWEgQ29udGFjdGxlc3MiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTm8iID0gImxpZ2h0Y29yYWwiLCAiU8OtIiA9ICJsaWdodGdyZWVuIikpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHJvdW5kKHBvcmNlbnRhamUsIDEpLCAiJSIpKSwgCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSA1KQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0nY29sb3I6cmVkOyc+ICBSRUxBQ0nDk04gRkVFIEFOVUFMIHZzIEFQUiBSRUdVTEFSIDwvc3Bhbj4KCmBgYHtyfQpnZ3Bsb3QodGFyamV0YXNfY2xlYW4sIGFlcyh4ID0gYEFubnVhbCBGZWVgLCB5ID0gYFJlZ3VsYXIgQVBSYCwgY29sb3IgPSBgQ2FyZCBMZXZlbGApKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNywgc2l6ZSA9IDIpICsgCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiUmVsYWNpw7NuIGVudHJlIEZlZSBBbnVhbCB5IEFQUiBSZWd1bGFyIiwKICAgIHggPSAiRmVlIEFudWFsIChNWE4pIiwKICAgIHkgPSAiQVBSIFJlZ3VsYXIgKCUpIiwKICAgIGNvbG9yID0gIk5pdmVsIGRlIFRhcmpldGEiCiAgKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0nY29sb3I6cmVkOyc+ICBMQSAgRVZPTFVDScOTTiBERSBUSVBPUyBERSBUQVJKRVRBIGRlbCAyMDEwLTIwMjQgPC9zcGFuPgoKYGBge3J9CnRpcG9zX2xvbmcgPC0gdGlwb3MgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtWWVhciwgbmFtZXNfdG8gPSAiVGlwbyIsIHZhbHVlc190byA9ICJQb3JjZW50YWplIikKCmdncGxvdCh0aXBvc19sb25nLCBhZXMoeCA9IFllYXIsIHkgPSBQb3JjZW50YWplLCBmaWxsID0gVGlwbykpICsKICBnZW9tX2FyZWEocG9zaXRpb24gPSAic3RhY2siLCBhbHBoYSA9IDAuOCkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHRpdGxlID0gIkV2b2x1Y2nDs24gZGUgVGlwb3MgZGUgVGFyamV0YSBlbiBNw6l4aWNvICgyMDEwLTIwMjQpIiwKICAgIHggPSAiQcOxbyIsCiAgICB5ID0gIlBvcmNlbnRhamUgKCUpIiwKICAgIGZpbGwgPSAiVGlwbyBkZSBUYXJqZXRhIgogICkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MyIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKCmBgYAoKIyMjIDxzcGFuIHN0eWxlPSdjb2xvcjpyZWQ7Jz4gIExBICBFVk9MVUNJw5NOIERFIExBIFBPQkxBQ0nDk04gQkFOQ0FSSVpBREEgPC9zcGFuPgoKYGBge3J9Cm1leGljb19iYW5rZWQgPC0gcGFydGljaXBhY2lvbiAlPiUKICBmaWx0ZXIoR2VvZ3JhcGh5ID09ICJNZXhpY28iLCBUaXRsZSA9PSAiQmFua2VkIHBvcHVsYXRpb24gKDAwMHMpIikKCnllYXJzIDwtIGdyZXAoIl4yMCIsIG5hbWVzKG1leGljb19iYW5rZWQpLCB2YWx1ZSA9IFRSVUUpCm1leGljb19iYW5rZWRbeWVhcnNdIDwtIGxhcHBseShtZXhpY29fYmFua2VkW3llYXJzXSwgZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhnc3ViKCIsIiwgIiIsIHgpKSkKCm1leGljb19sb25nIDwtIG1leGljb19iYW5rZWQgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBhbGxfb2YoeWVhcnMpLCBuYW1lc190byA9ICJBw7FvIiwgdmFsdWVzX3RvID0gIkNsaWVudGVzIikKCmdncGxvdChtZXhpY29fbG9uZywgYWVzKHggPSBBw7FvLCB5ID0gQ2xpZW50ZXMsIGdyb3VwID0gMSkpICsKICBnZW9tX2xpbmUoY29sb3IgPSAic3RlZWxibHVlIiwgc2l6ZSA9IDEuNSkgKwogIGdlb21fcG9pbnQoY29sb3IgPSAicmVkIiwgc2l6ZSA9IDMpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJFdm9sdWNpw7NuIGRlIFBvYmxhY2nDs24gQmFuY2FyaXphZGEgZW4gTcOpeGljbyIsCiAgICB4ID0gIkHDsW8iLAogICAgeSA9ICJOw7ptZXJvIGRlIENsaWVudGVzICgwMDBzKSIKICApICsKICBzY2FsZV94X2Rpc2NyZXRlKGd1aWRlID0gZ3VpZGVfYXhpcyhhbmdsZSA9IDQ1KSkKYGBgCgoKCmBgYHtyfQojICBMaW1waWV6YSBwcmV2aWEgZGUgdHJhc2FuY2FjY2lvbmVzCnRyYW5zYWNjaW9uZXNfY2xlYW4gPC0gdHJhbnNhY2Npb25lcyAlPiUKICBtdXRhdGUoYWNyb3NzKHN0YXJ0c193aXRoKCIyMCIpLCB+YXMubnVtZXJpYyhpZmVsc2UoLiA9PSAiLSIsIE5BLCAuKSkpKQp0cmFuc19sb25nIDwtIHRyYW5zYWNjaW9uZXNfY2xlYW4gJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IHN0YXJ0c193aXRoKCIyMCIpLAogICAgbmFtZXNfdG8gPSAiQcOxbyIsCiAgICB2YWx1ZXNfdG8gPSAiVmFsb3IiCiAgKSAlPiUKICBtdXRhdGUoCiAgICBBw7FvID0gYXMubnVtZXJpYyhBw7FvKSwKICAgIFZhbG9yID0gYXMubnVtZXJpYyhWYWxvcikKICApICU+JQogIGZpbHRlcighaXMubmEoVmFsb3IpKQoKY2F0KCJ0cmFuc19sb25nIGNyZWFkbyBleGl0b3NhbWVudGUgY29uIiwgbnJvdyh0cmFuc19sb25nKSwgImZpbGFzXG4iKQpgYGAKCmBgYHtyfQojIFZlcmlmaWNhciBxdWUgdHJhbnNfbG9uZyBleGlzdGUgeSB0aWVuZSBkYXRvcwpjYXQoIj09PSBWRVJJRklDQUNJw5NOIERFIFRSQU5TX0xPTkcgPT09XG4iKQpjYXQoIk7Dum1lcm8gZGUgZmlsYXM6IiwgbnJvdyh0cmFuc19sb25nKSwgIlxuIikKY2F0KCJFc3RydWN0dXJhOlxuIikKc3RyKHRyYW5zX2xvbmcpCmNhdCgiXG5QcmltZXJhcyBmaWxhczpcbiIpCnByaW50KGhlYWQodHJhbnNfbG9uZykpCmBgYAoKIyMjIDxzcGFuIHN0eWxlPSdjb2xvcjpyZWQ7Jz4gTEEgRVZPTFVDScOTTiBERSBUUkFOU0FDQ0lPTkVTIE3Dk1ZJTEVTIDwvc3Bhbj4KCmBgYHtyfQpnZ3Bsb3QodHJhbnNfbG9uZywgYWVzKHggPSBBw7FvLCB5ID0gVmFsb3IsIGNvbG9yID0gQ2F0ZWdvcnkpKSArCiAgZ2VvbV9saW5lKHNpemUgPSAxLjIpICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRXZvbHVjacOzbiBkZSBUcmFuc2FjY2lvbmVzIEZpbmFuY2llcmFzIGVuIE3DqXhpY28iLAogICAgeCA9ICJBw7FvIiwKICAgIHkgPSAiVmFsb3IgKE1YTiBtaWxsb25lcyBvIG1pbGVzIGRlIHRhcmpldGFzKSIsCiAgICBjb2xvciA9ICJDYXRlZ29yw61hIgogICkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKQoKYGBgCgojIyMgPHNwYW4gc3R5bGU9J2NvbG9yOnJlZDsnPiAgRUwgQ1JFQ0lNSUVOVE8gUE9SIENBVEVHT1LDjUEgKDIwMTAtMjAyNCkgPC9zcGFuPgoKYGBge3J9CgpjcmVjaW1pZW50b19jYXRlZ29yaWEgPC0gdHJhbnNfbG9uZyAlPiUKICBncm91cF9ieShDYXRlZ29yeSkgJT4lCiAgc3VtbWFyaXNlKAogICAgQ3JlY2ltaWVudG8gPSAobGFzdChWYWxvcikgLSBmaXJzdChWYWxvcikpIC8gZmlyc3QoVmFsb3IpICogMTAwCiAgKQoKY2F0KCJcbkNyZWNpbWllbnRvIHBvciBjYXRlZ29yw61hOlxuIikKcHJpbnQoY3JlY2ltaWVudG9fY2F0ZWdvcmlhKQoKZ2dwbG90KGNyZWNpbWllbnRvX2NhdGVnb3JpYSwgYWVzKHggPSByZW9yZGVyKENhdGVnb3J5LCBDcmVjaW1pZW50byksIHkgPSBDcmVjaW1pZW50bywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBDcmVjaW1pZW50byA+IDApKSArCiAgZ2VvbV9jb2woKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiQ3JlY2ltaWVudG8gJSBkZSAyMDEwIGEgMjAyNCBwb3IgQ2F0ZWdvcsOtYSIsCiAgICB4ID0gIkNhdGVnb3LDrWEiLAogICAgeSA9ICJDcmVjaW1pZW50byAoJSkiCiAgKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiRkFMU0UiID0gImxpZ2h0Y29yYWwiLCAiVFJVRSIgPSAibGlnaHRncmVlbiIpKSArCiAgY29vcmRfZmxpcCgpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHJvdW5kKENyZWNpbWllbnRvLCAxKSwgIiUiKSksIAogICAgICAgICAgICBoanVzdCA9IGlmZWxzZShjcmVjaW1pZW50b19jYXRlZ29yaWEkQ3JlY2ltaWVudG8gPiAwLCAtMC4yLCAxLjIpLCBzaXplID0gMykKYGBgCgojIyMgPHNwYW4gc3R5bGU9J2NvbG9yOnJlZDsnPiBDT01QQVJBQ0nDk04gZW50cmUgVklTQSB2cyBNQVNURVJDQVJEIDwvc3Bhbj4KCmBgYHtyfQp2aXNhX21hc3RlcmNhcmQgPC0gdGFyamV0YXNfY2xlYW4gJT4lCiAgZmlsdGVyKE5ldHdvcmsgJWluJSBjKCJWaXNhIiwgIk1hc3RlcmNhcmQiKSkgJT4lCiAgZ3JvdXBfYnkoTmV0d29yaykgJT4lCiAgc3VtbWFyaXNlKAogICAgdG90YWxfdGFyamV0YXMgPSBuKCksCiAgICBwcm9tZWRpb19BUFIgPSBtZWFuKGBSZWd1bGFyIEFQUmAsIG5hLnJtID0gVFJVRSksCiAgICBwcm9tZWRpb19mZWUgPSBtZWFuKGBBbm51YWwgRmVlYCwgbmEucm0gPSBUUlVFKSwKICAgIHByb21lZGlvX3Jld2FyZHMgPSBtZWFuKGBSZXdhcmRzIFJhdGVgLCBuYS5ybSA9IFRSVUUpLAogICAgcG9yY2VudGFqZV9wcmVtaXVtID0gbWVhbihgQ2FyZCBMZXZlbGAgJWluJSBjKCJQcmVtaXVtIiwgIlByZW1pdW0gUGx1cyIpLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgcG9yY2VudGFqZV9jb250YWN0bGVzcyA9IG1lYW4oQ29udGFjdGxlc3MgPT0gIlPDrSIsIG5hLnJtID0gVFJVRSkgKiAxMDAKICApCgp2aXNhX21hc3RlcmNhcmRfbG9uZyA8LSB2aXNhX21hc3RlcmNhcmQgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IGMocHJvbWVkaW9fQVBSLCBwcm9tZWRpb19mZWUsIHByb21lZGlvX3Jld2FyZHMsIHBvcmNlbnRhamVfcHJlbWl1bSwgcG9yY2VudGFqZV9jb250YWN0bGVzcyksCiAgICBuYW1lc190byA9ICJNZXRyaWNhIiwKICAgIHZhbHVlc190byA9ICJWYWxvciIKICApCgpnZ3Bsb3QodmlzYV9tYXN0ZXJjYXJkX2xvbmcsIGFlcyh4ID0gTWV0cmljYSwgeSA9IFZhbG9yLCBmaWxsID0gTmV0d29yaykpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDb21wYXJhY2nDs24gVmlzYSB2cyBNYXN0ZXJjYXJkIGVuIGVsIE1lcmNhZG8gTWV4aWNhbm8iLAogICAgeCA9ICJNw6l0cmljYSIsCiAgICB5ID0gIlZhbG9yIiwKICAgIGZpbGwgPSAiUmVkIGRlIFRhcmpldGFzIgogICkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIlZpc2EiID0gImdvbGQiLCAiTWFzdGVyY2FyZCIgPSAicmVkIikpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKFZhbG9yLCAxKSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpLCAKICAgICAgICAgICAgdmp1c3QgPSAtMC41LCBzaXplID0gMykKYGBgCgojIyMgPHNwYW4gc3R5bGU9J2NvbG9yOnJlZDsnPiBDb3JyZWxhY2nDs24gZW50cmUgY2FyYWN0ZXLDrXN0aWNhcyBkZSB0YXJqZXRhcyA8L3NwYW4+CmBgYHtyfQpjb3JyZWxhdGlvbl9kYXRhIDwtIHRhcmpldGFzX2NsZWFuICU+JQogIHNlbGVjdChgUmVndWxhciBBUFJgLCBgQW5udWFsIEZlZWAsIGBSZXdhcmRzIFJhdGVgKSAlPiUKICBjb3IodXNlID0gImNvbXBsZXRlLm9icyIpCgojIGhlYXRtYXAgZGUgY29ycmVsYWNpb24KY29ycnBsb3QoY29ycmVsYXRpb25fZGF0YSwgbWV0aG9kID0gImNvbG9yIiwgdHlwZSA9ICJ1cHBlciIsIAogICAgICAgICBhZGRDb2VmLmNvbCA9ICJibGFjayIsIHRsLmNvbCA9ICJibGFjayIsIHRsLnNydCA9IDQ1LAogICAgICAgICB0aXRsZSA9ICJNYXRyaXogZGUgQ29ycmVsYWNpw7NuIGVudHJlIENhcmFjdGVyw61zdGljYXMgZGUgVGFyamV0YXMiKQpgYGAKCgojIyMgPHNwYW4gc3R5bGU9J2NvbG9yOnJlZDsnPiBFdm9sdWNpw7NuIHRlbXBvcmFsIGRlIHJlZGVzIDwvc3Bhbj4KYGBge3J9CnJlZGVzX2xvbmcgPC0gcmVkZXMgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBzdGFydHNfd2l0aCgiMjAiKSwgbmFtZXNfdG8gPSAiQcOxbyIsIHZhbHVlc190byA9ICJQYXJ0aWNpcGFjaW9uIikgJT4lCiAgbXV0YXRlKEHDsW8gPSBhcy5udW1lcmljKEHDsW8pKQoKZ2dwbG90KHJlZGVzX2xvbmcsIGFlcyh4ID0gQcOxbywgeSA9IFBhcnRpY2lwYWNpb24sIGNvbG9yID0gYENhdGVnb3JpemF0aW9uIFR5cGVgKSkgKwogIGdlb21fbGluZShzaXplID0gMS41KSArCiAgZ2VvbV9wb2ludChzaXplID0gMykgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHRpdGxlID0gIkV2b2x1Y2nDs24gZGUgUGFydGljaXBhY2nDs24gZGUgUmVkZXMgZGUgVGFyamV0YXMgKDIwMTAtMjAyNCkiLAogICAgeCA9ICJBw7FvIiwKICAgIHkgPSAiUGFydGljaXBhY2nDs24gKCUpIiwKICAgIGNvbG9yID0gIlJlZCIKICApICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikKCmBgYAojIyMgPHNwYW4gc3R5bGU9J2NvbG9yOnJlZDsnPiBDcmVjaW1pZW50byBBbnVhbCBDb21wdWVzdG8gUG9ibGFjacOzbiBCYW5jYXJpemFkYSA8L3NwYW4+CmBgYHtyfQpjYWdyX2NhbGN1bG8gPC0gZnVuY3Rpb24odmFsb3JfaW5pY2lhbCwgdmFsb3JfZmluYWwsIGHDsW9zKSB7CiAgKHZhbG9yX2ZpbmFsIC8gdmFsb3JfaW5pY2lhbCleKDEvYcOxb3MpIC0gMQp9Cgp5ZWFycyA8LSBncmVwKCJeMjAiLCBuYW1lcyhtZXhpY29fYmFua2VkKSwgdmFsdWUgPSBUUlVFKQoKIyBDb252ZXJ0aXIgY29sdW1uYXMgZGUgYcOxb3MgYSBudW3DqXJpY28geSBlbGltaW5hciBOQXMKbWV4aWNvX2JhbmtlZF9jbGVhbiA8LSBtZXhpY29fYmFua2VkICU+JQogIG11dGF0ZShhY3Jvc3MoYWxsX29mKHllYXJzKSwgfmFzLm51bWVyaWMoZ3N1YigiLCIsICIiLCAuKSkpKQoKY2Fncl9wb2JsYWNpb24gPC0gbWV4aWNvX2JhbmtlZF9jbGVhbiAlPiUKICBzdW1tYXJpc2UoCiAgICBjYWdyID0gY2Fncl9jYWxjdWxvKAogICAgICBmaXJzdChuYS5vbWl0KHVubGlzdChzZWxlY3QoLiwgYWxsX29mKHllYXJzKSkpKSksIAogICAgICBsYXN0KG5hLm9taXQodW5saXN0KHNlbGVjdCguLCBhbGxfb2YoeWVhcnMpKSkpKSwgCiAgICAgIGxlbmd0aCh5ZWFycykKICAgICkgKiAxMDAKICApCgpjYXQoIkNyZWNpbWllbnRvIEFudWFsIENvbXB1ZXN0byBQb2JsYWNpw7NuIEJhbmNhcml6YWRhOiIsIAogICAgcm91bmQoYXMubnVtZXJpYyhjYWdyX3BvYmxhY2lvbiRjYWdyKSwgMiksICIlXG4iKQpgYGAKCgojIyA8c3BhbiBzdHlsZT0nY29sb3I6cmVkOyc+IEZpbmFsaWRhZCBkZWwgZXN0dWRpbyA8L3NwYW4+CgpMYSBmaW5hbGlkYWQgZGUgZXN0ZSBhbsOhbGlzaXMgZnVlIGFwbGljYXIgbG9zIGNvbmNlcHRvcyBhcHJlbmRpZG9zIGEgbG8gbGFyZ28gZGUgbGEgY2FycmVyYSBkZSBJbnRlbGlnZW5jaWEgZGUgTmVnb2Npb3MgZW4gZWwgVGVjbm9sw7NnaWNvIGRlIE1vbnRlcnJleSBwYXJhIGVudGVuZGVyLCBsaW1waWFyIHkgbWFuaXB1bGFyIHNlaXMgYmFzZXMgZGUgZGF0b3MgZGlmZXJlbnRlcy4gRXN0byBwZXJtaXRpw7MgZXhwbG9yYXIgbGEgaW5mb3JtYWNpw7NuIGRpc3BvbmlibGUsIGdlbmVyYXIgaW5zaWdodHMgcmVsZXZhbnRlcyB5IHByZXBhcmFyIHZpc3VhbGl6YWNpb25lcyB5IHRhYmxlcm9zIHF1ZSBmYWNpbGl0ZW4gbGEgaW50ZXJwcmV0YWNpw7NuIGRlIGxvcyBkYXRvcy4gCgpMb3MgcmVzdWx0YWRvcyBvYnRlbmlkb3Mgc2lydmVuIGNvbW8gYmFzZSBwYXJhIGxhIHNpZ3VpZW50ZSBldmlkZW5jaWEgeSBwdWVkZW4gc2VyIHV0aWxpemFkb3MgcGFyYSBwcmVzZW50YXIgaGFsbGF6Z29zIGRlIG1hbmVyYSBjbGFyYSBhIGNvbXBhw7Flcm9zLCBwcm9mZXNvcmVzIHkgZGlyZWN0aXZvcywgYXBveWFuZG8gbGEgbWVqb3JhIGVuIGxhIHRvbWEgZGUgZGVjaXNpb25lcyBlc3RyYXTDqWdpY2FzLgoKIVtdKGh0dHBzOi8vd3d3LmdpZnNzLmNvbS9lY29ub21pYS9iYW5jb3MvaW1hZ2VzL2JhbmNvLTAzLmdpZikKCg==