# Instalar paquetes y llamar librerías
#install.packages("plm", repos = "https://cloud.r-project.org")
#install.packages("gplots", repos = "https://cloud.r-project.org")
#install.packages("dplyr", repos = "https://cloud.r-project.org")

library(plm)
library(gplots)
library(dplyr)

Ejercicio 1 - PATENTES

Genera el mejor modelo de la Base de Datos “Patentes” y genera predicciones. Incluye conclusiones.

# Cargamos la base de datos (ajusta la ruta a donde la tengas guardada)
df_patentes <- read.csv("/Users/sharontorres/Downloads/Actividad1/PATENT3.csv")

# Convertimos a formato de panel: identificador = cusip, tiempo = year
df_patentes <- pdata.frame(df_patentes, index = c("cusip", "year"))


modelo_regresion_stckpr <- lm(stckpr ~ patents, df_patentes)
summary(modelo_regresion_stckpr)
## 
## Call:
## lm(formula = stckpr ~ patents, data = df_patentes)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -126.556  -12.190   -4.857    6.143  301.143 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 18.856675   0.502270   37.54   <2e-16 ***
## patents      0.166508   0.006838   24.35   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 22.68 on 2256 degrees of freedom
##   (2 observations deleted due to missingness)
## Multiple R-squared:  0.2081, Adjusted R-squared:  0.2078 
## F-statistic:   593 on 1 and 2256 DF,  p-value: < 2.2e-16
# Prueba de Heterogeneidad (agrupamos por empresa, cusip)
plotmeans(stckpr ~ cusip, data = df_patentes)

# INTERPRETACIÓN: Buscamos línea quebrada que una los promedios (Hay heterogeneidad)
# para elegir entre Modelo de Efectos Fijos o Aleatorios. Si sale una línea horizontal
# no hay heterogeneidad, probablemente la mejor opción sea el Modelo Agrupado.

# Opción 1 - Modelo de Regresión Agrupada (Pooled)
modelo_pooled_stckpr <- plm(stckpr ~ patents, data = df_patentes, model = "pooling")
summary(modelo_pooled_stckpr)
## Pooling Model
## 
## Call:
## plm(formula = stckpr ~ patents, data = df_patentes, model = "pooling")
## 
## Unbalanced Panel: n = 226, T = 8-10, N = 2258
## 
## Residuals:
##    Min. 1st Qu.  Median 3rd Qu.    Max. 
## -126.56  -12.19   -4.86    6.14  301.14 
## 
## Coefficients:
##               Estimate Std. Error t-value  Pr(>|t|)    
## (Intercept) 18.8566751  0.5022700  37.543 < 2.2e-16 ***
## patents      0.1665081  0.0068377  24.352 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    1464800
## Residual Sum of Squares: 1159900
## R-Squared:      0.20814
## Adj. R-Squared: 0.20779
## F-statistic: 593.001 on 1 and 2256 DF, p-value: < 2.22e-16
# Opción 2 - Modelo de Efectos Fijos (within)
modelo_within_stckpr <- plm(stckpr ~ patents, data = df_patentes, model = "within")
summary(modelo_within_stckpr)
## Oneway (individual) effect Within Model
## 
## Call:
## plm(formula = stckpr ~ patents, data = df_patentes, model = "within")
## 
## Unbalanced Panel: n = 226, T = 8-10, N = 2258
## 
## Residuals:
##    Min. 1st Qu.  Median 3rd Qu.    Max. 
## -150.27   -5.32   -1.16    3.55  186.59 
## 
## Coefficients:
##         Estimate Std. Error t-value  Pr(>|t|)    
## patents 0.063251   0.014058  4.4994 7.199e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    442430
## Residual Sum of Squares: 438060
## R-Squared:      0.0098695
## Adj. R-Squared: -0.10031
## F-statistic: 20.2448 on 1 and 2031 DF, p-value: 7.1991e-06
# Prueba F
# INTERPRETACIÓN: Si p< 0.05 No usar POOLED. Si p> 0.05 Usar POOLED.
pFtest(modelo_within_stckpr, modelo_pooled_stckpr) #Siempre va primero within, NO POOLED.
## 
##  F test for individual effects
## 
## data:  stckpr ~ patents
## F = 14.875, df1 = 225, df2 = 2031, p-value < 2.2e-16
## alternative hypothesis: significant effects
# Opción 3 - Modelo de Efectos Aleatorios (Random)
modelo_random_stckpr <- plm(stckpr ~ patents, data = df_patentes, model = "random")
summary(modelo_random_stckpr)
## Oneway (individual) effect Random Effect Model 
##    (Swamy-Arora's transformation)
## 
## Call:
## plm(formula = stckpr ~ patents, data = df_patentes, model = "random")
## 
## Unbalanced Panel: n = 226, T = 8-10, N = 2258
## 
## Effects:
##                  var std.dev share
## idiosyncratic 215.69   14.69 0.422
## individual    295.20   17.18 0.578
## theta:
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.7107  0.7391  0.7391  0.7390  0.7391  0.7391 
## 
## Residuals:
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -1.17e+02 -6.48e+00 -2.96e+00  1.89e-03  3.06e+00  2.19e+02 
## 
## Coefficients:
##              Estimate Std. Error z-value  Pr(>|z|)    
## (Intercept) 20.205603   1.217228 16.5997 < 2.2e-16 ***
## patents      0.107063   0.011111  9.6358 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    512040
## Residual Sum of Squares: 491850
## R-Squared:      0.039427
## Adj. R-Squared: 0.039001
## Chisq: 92.848 on 1 DF, p-value: < 2.22e-16
# Prueba de Hausman
# INTERPRETACIÓN: Si p< 0.05 Usar Efectos Fijos. Si p> 0.05 Usar Efectos Aleatorios.
phtest(modelo_random_stckpr, modelo_within_stckpr) #Siempre va primero random, NO WITHIN
## 
##  Hausman Test
## 
## data:  stckpr ~ patents
## chisq = 25.881, df = 1, p-value = 3.631e-07
## alternative hypothesis: one model is inconsistent

CONCLUSIÓN MEJOR MODELO:

Afirmación: El modelo más adecuado para este análisis es el de Efectos Fijos.

Razón: Las pruebas estadísticas diseñadas para esta decisión —la Prueba F y la Prueba de Hausman— descartaron tanto el Modelo Agrupado como el de Efectos Aleatorios.

Evidencia: Ambas pruebas arrojaron un p-value prácticamente igual a cero, muy por debajo del umbral de 0.05, lo que confirma con claridad la elección del Modelo de Efectos Fijos.

ultimo_anio <- as.data.frame(df_patentes)
ultimo_anio <- ultimo_anio[ultimo_anio$year == 2021, ]

pendiente_fe <- coef(modelo_within_stckpr)["patents"]
efectos_fijos <- fixef(modelo_within_stckpr)

patents_2022 <- 1.1 * ultimo_anio$patents   # +10% respecto a 2021
nombres_empresas <- as.character(ultimo_anio$cusip)

pronostico_fe <- efectos_fijos[nombres_empresas] + pendiente_fe * patents_2022

df_pronostico_fe <- data.frame(
  cusip = nombres_empresas,
  stckpr_pronostico = as.numeric(pronostico_fe)
)

head(df_pronostico_fe, 10)
##    cusip stckpr_pronostico
## 1    800         37.643130
## 2   4626         15.734344
## 3   4671          6.911448
## 4   7500          3.249399
## 5   7603          1.474699
## 6  20753          8.662049
## 7  21367          3.149399
## 8  23519         17.946107
## 9  29069          7.618975
## 10 38213          7.567172

CONCLUSIÓN:

Afirmación: Si las empresas logran 10% más patentes en 2022, el precio de sus acciones va a subir, pero no todas van a subir lo mismo.

Razón: Porque cada empresa ya arranca desde un lugar distinto. El modelo capta dos cosas: el “boost” que dan las patentes nuevas, y el punto de partida que ya trae cada empresa por su propia historia.

Evidencia: Lo vemos clarito en los números: con el mismo aumento del 10% en patentes para todas, unas terminan en 1.47 y otras en 37.64. O sea, el efecto de innovar sí jala el precio para arriba en todos los casos, pero el resultado final depende de dónde estaba parada cada empresa antes — no es que todas lleguen al mismo lugar solo por hacer el mismo esfuerzo.

Ejercicio 2 - CUIDADO DE LA PIEL

INSTRUCCIONES: Genera el mejor modelo de la Base de Datos “Market sizes” y genera predicciones. Incluye conclusiones. Si tuvieras que invertir en alguna sub-categoría, ¿en cuál lo harías? Justifica ampliamente tu respuesta.

# Instalar paquetes si es necesario
# install.packages(c("dplyr", "tidyr", "plm", "ggplot2"))

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

# Cargar la base original
df_market <- read.csv(
  "/Users/sharontorres/Downloads/Actividad1/Market_sizes_clean.csv",
  stringsAsFactors = FALSE
)

# Categorías que vamos a analizar
cats <- c(
  "Bath and Shower",
  "Deodorants",
  "Depilatories",
  "Fragrances",
  "Hair Care",
  "Men's Grooming",
  "Skin Care",
  "Sun Care"
)
df_long <- df_market %>%
  filter(Category %in% cats) %>%
  select(Category, X2011:X2025) %>%
  mutate(
    across(X2011:X2025, ~ as.numeric(gsub(",", "", .)))
  ) %>%
  pivot_longer(
    cols = X2011:X2025,
    names_to = "Año",
    values_to = "Valor"
  ) %>%
  mutate(
    Año_num = as.numeric(gsub("X", "", Año)),
    Año_centrado = Año_num - 2011
  ) %>%
  arrange(Category, Año_num)

head(df_long)
## # A tibble: 6 × 5
##   Category        Año    Valor Año_num Año_centrado
##   <chr>           <chr>  <dbl>   <dbl>        <dbl>
## 1 Bath and Shower X2011  8410.    2011            0
## 2 Bath and Shower X2012  9085     2012            1
## 3 Bath and Shower X2013  9711.    2013            2
## 4 Bath and Shower X2014 10227.    2014            3
## 5 Bath and Shower X2015 10815.    2015            4
## 6 Bath and Shower X2016 11482.    2016            5
df_panel <- pdata.frame(
  df_long,
  index = c("Category", "Año_num")
)

pdim(df_panel)
## Balanced Panel: n = 8, T = 15, N = 120
str(df_long$Año_num)
##  num [1:120] 2011 2012 2013 2014 2015 ...
str(df_long$Año_centrado)
##  num [1:120] 0 1 2 3 4 5 6 7 8 9 ...
modelo_pooled <- plm(
  log(Valor) ~ Año_centrado,
  data = df_panel,
  model = "pooling"
)

summary(modelo_pooled)
## Pooling Model
## 
## Call:
## plm(formula = log(Valor) ~ Año_centrado, data = df_panel, model = "pooling")
## 
## Balanced Panel: n = 8, T = 15, N = 120
## 
## Residuals:
##    Min. 1st Qu.  Median 3rd Qu.    Max. 
##  -2.386  -0.416   0.395   0.937   1.282 
## 
## Coefficients:
##              Estimate Std. Error t-value Pr(>|t|)    
## (Intercept)  8.977539   0.215534 41.6525  < 2e-16 ***
## Año_centrado 0.067392   0.026202  2.5721  0.01135 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    191.64
## Residual Sum of Squares: 181.46
## R-Squared:      0.053087
## Adj. R-Squared: 0.045063
## F-statistic: 6.6155 on 1 and 118 DF, p-value: 0.01135
modelo_fixed <- plm(
  log(Valor) ~ Año_centrado,
  data = df_panel,
  model = "within"
)

summary(modelo_fixed)
## Oneway (individual) effect Within Model
## 
## Call:
## plm(formula = log(Valor) ~ Año_centrado, data = df_panel, model = "within")
## 
## Balanced Panel: n = 8, T = 15, N = 120
## 
## Residuals:
##     Min.  1st Qu.   Median  3rd Qu.     Max. 
## -0.25125 -0.04400  0.00802  0.04081  0.24915 
## 
## Coefficients:
##               Estimate Std. Error t-value  Pr(>|t|)    
## Año_centrado 0.0673923  0.0018042  37.353 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    10.983
## Residual Sum of Squares: 0.80937
## R-Squared:      0.92631
## Adj. R-Squared: 0.92099
## F-statistic: 1395.23 on 1 and 111 DF, p-value: < 2.22e-16
modelo_random <- plm(
  log(Valor) ~ Año_centrado,
  data = df_panel,
  model = "random"
)

summary(modelo_random)
## Oneway (individual) effect Random Effect Model 
##    (Swamy-Arora's transformation)
## 
## Call:
## plm(formula = log(Valor) ~ Año_centrado, data = df_panel, model = "random")
## 
## Balanced Panel: n = 8, T = 15, N = 120
## 
## Effects:
##                    var  std.dev share
## idiosyncratic 0.007292 0.085391 0.004
## individual    1.720022 1.311496 0.996
## theta: 0.9832
## 
## Residuals:
##     Min.  1st Qu.   Median  3rd Qu.     Max. 
## -0.23757 -0.03954  0.00409  0.04301  0.22468 
## 
## Coefficients:
##               Estimate Std. Error z-value  Pr(>|z|)    
## (Intercept)  8.9775395  0.4639214  19.351 < 2.2e-16 ***
## Año_centrado 0.0673923  0.0018042  37.353 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    11.034
## Residual Sum of Squares: 0.86041
## R-Squared:      0.92202
## Adj. R-Squared: 0.92136
## Chisq: 1395.23 on 1 DF, p-value: < 2.22e-16
pFtest(
  modelo_fixed,
  modelo_pooled
)
## 
##  F test for individual effects
## 
## data:  log(Valor) ~ Año_centrado
## F = 3539.4, df1 = 7, df2 = 111, p-value < 2.2e-16
## alternative hypothesis: significant effects
phtest(
  modelo_random,
  modelo_fixed
)
## 
##  Hausman Test
## 
## data:  log(Valor) ~ Año_centrado
## chisq = 2.4253e-13, df = 1, p-value = 1
## alternative hypothesis: one model is inconsistent
# Seleccionamos el modelo final según las pruebas
modelo_final <- modelo_random

summary(modelo_final)
## Oneway (individual) effect Random Effect Model 
##    (Swamy-Arora's transformation)
## 
## Call:
## plm(formula = log(Valor) ~ Año_centrado, data = df_panel, model = "random")
## 
## Balanced Panel: n = 8, T = 15, N = 120
## 
## Effects:
##                    var  std.dev share
## idiosyncratic 0.007292 0.085391 0.004
## individual    1.720022 1.311496 0.996
## theta: 0.9832
## 
## Residuals:
##     Min.  1st Qu.   Median  3rd Qu.     Max. 
## -0.23757 -0.03954  0.00409  0.04301  0.22468 
## 
## Coefficients:
##               Estimate Std. Error z-value  Pr(>|z|)    
## (Intercept)  8.9775395  0.4639214  19.351 < 2.2e-16 ***
## Año_centrado 0.0673923  0.0018042  37.353 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    11.034
## Residual Sum of Squares: 0.86041
## R-Squared:      0.92202
## Adj. R-Squared: 0.92136
## Chisq: 1395.23 on 1 DF, p-value: < 2.22e-16

CONCLUSIÓN MEJOR MODELO:

A : Afirmación

El modelo de efectos aleatorios (Random Effects) es el modelo más adecuado para analizar la relación entre el valor de mercado y el tiempo.

R : Razón

Se selecciona porque el Hausman Test no encontró diferencias sistemáticas entre los estimadores de efectos fijos y aleatorios. Al obtener un p-value = 1, no se rechaza la hipótesis nula, por lo que es válido utilizar el modelo de efectos aleatorios. Además, este modelo presenta un R² de 92.20%, indicando un alto poder explicativo.

E : Evidencia Hausman Test: p-value = 1 R² Random Effects: 0.9220 R² Fixed Effects: 0.9263 Variable Año_centrado: p-value < 2.2e-16 Coeficiente de Año_centrado: 0.06739

Aunque el modelo de efectos fijos tiene un R² ligeramente mayor, el Hausman Test indica que no hay evidencia para preferir efectos fijos, por lo que se elige Random Effects como modelo final.

nuevo <- data.frame(
  Año_centrado = 15
)

prediccion_log <- predict(modelo_final, newdata = nuevo)
prediccion_log
##        1 
## 9.988424
nuevo_2026 <- data.frame(
  Category = unique(df_panel$Category),
  Año_centrado = 15
)

nuevo_2026$Category <- factor(
  nuevo_2026$Category,
  levels = levels(df_panel$Category)
)

prediccion_2026 <- predict(
  modelo_final,
  newdata = nuevo_2026
)

nuevo_2026$Prediccion_2026 <- exp(prediccion_2026)

nuevo_2026
##          Category Año_centrado Prediccion_2026
## 1 Bath and Shower           15        21772.95
## 2      Deodorants           15        21772.95
## 3    Depilatories           15        21772.95
## 4      Fragrances           15        21772.95
## 5       Hair Care           15        21772.95
## 6  Men's Grooming           15        21772.95
## 7       Skin Care           15        21772.95
## 8        Sun Care           15        21772.95
efectos_categoria <- ranef(modelo_final)

efectos_categoria
## Bath and Shower      Deodorants    Depilatories      Fragrances       Hair Care 
##      0.03145824      0.12990868     -2.26023173      0.81401791      1.03776410 
##  Men's Grooming       Skin Care        Sun Care 
##      0.86382624      1.14666744     -1.76341088
nuevo_2026 <- data.frame(
  Category = names(efectos_categoria),
  Año_centrado = 15,
  efecto = as.numeric(efectos_categoria)
)

nuevo_2026$Prediccion_log <- 
  coef(modelo_final)["Año_centrado"] * nuevo_2026$Año_centrado +
  nuevo_2026$efecto

nuevo_2026$Prediccion_2026 <- 
  exp(nuevo_2026$Prediccion_log)

nuevo_2026
##          Category Año_centrado      efecto Prediccion_log Prediccion_2026
## 1 Bath and Shower           15  0.03145824      1.0423426       2.8358524
## 2      Deodorants           15  0.12990868      1.1407930       3.1292488
## 3    Depilatories           15 -2.26023173     -1.2493474       0.2866918
## 4      Fragrances           15  0.81401791      1.8249022       6.2021886
## 5       Hair Care           15  1.03776410      2.0486484       7.7574092
## 6  Men's Grooming           15  0.86382624      1.8747106       6.5189320
## 7       Skin Care           15  1.14666744      2.1575518       8.6499346
## 8        Sun Care           15 -1.76341088     -0.7525266       0.4711746
nuevo_2026$Prediccion_2025 <- exp(
  coef(modelo_final)["Año_centrado"] * 14 +
  nuevo_2026$efecto
)

nuevo_2026$Crecimiento <- 
  nuevo_2026$Prediccion_2026 - nuevo_2026$Prediccion_2025

nuevo_2026$Crecimiento_pct <- 
  (nuevo_2026$Prediccion_2026 / nuevo_2026$Prediccion_2025 - 1) * 100

nuevo_2026
##          Category Año_centrado      efecto Prediccion_log Prediccion_2026
## 1 Bath and Shower           15  0.03145824      1.0423426       2.8358524
## 2      Deodorants           15  0.12990868      1.1407930       3.1292488
## 3    Depilatories           15 -2.26023173     -1.2493474       0.2866918
## 4      Fragrances           15  0.81401791      1.8249022       6.2021886
## 5       Hair Care           15  1.03776410      2.0486484       7.7574092
## 6  Men's Grooming           15  0.86382624      1.8747106       6.5189320
## 7       Skin Care           15  1.14666744      2.1575518       8.6499346
## 8        Sun Care           15 -1.76341088     -0.7525266       0.4711746
##   Prediccion_2025 Crecimiento Crecimiento_pct
## 1       2.6510354  0.18481701        6.971503
## 2       2.9253107  0.20393813        6.971503
## 3       0.2680077  0.01868416        6.971503
## 4       5.7979821  0.40420651        6.971503
## 5       7.2518465  0.50556271        6.971503
## 6       6.0940828  0.42484918        6.971503
## 7       8.0862046  0.56373001        6.971503
## 8       0.4404674  0.03070720        6.971503
nuevo_2026$Crecimiento <- 
  nuevo_2026$Prediccion_2026 - nuevo_2026$Prediccion_2025

nuevo_2026$Crecimiento_pct <- 
  (nuevo_2026$Prediccion_2026 / nuevo_2026$Prediccion_2025 - 1) * 100

nuevo_2026
##          Category Año_centrado      efecto Prediccion_log Prediccion_2026
## 1 Bath and Shower           15  0.03145824      1.0423426       2.8358524
## 2      Deodorants           15  0.12990868      1.1407930       3.1292488
## 3    Depilatories           15 -2.26023173     -1.2493474       0.2866918
## 4      Fragrances           15  0.81401791      1.8249022       6.2021886
## 5       Hair Care           15  1.03776410      2.0486484       7.7574092
## 6  Men's Grooming           15  0.86382624      1.8747106       6.5189320
## 7       Skin Care           15  1.14666744      2.1575518       8.6499346
## 8        Sun Care           15 -1.76341088     -0.7525266       0.4711746
##   Prediccion_2025 Crecimiento Crecimiento_pct
## 1       2.6510354  0.18481701        6.971503
## 2       2.9253107  0.20393813        6.971503
## 3       0.2680077  0.01868416        6.971503
## 4       5.7979821  0.40420651        6.971503
## 5       7.2518465  0.50556271        6.971503
## 6       6.0940828  0.42484918        6.971503
## 7       8.0862046  0.56373001        6.971503
## 8       0.4404674  0.03070720        6.971503
tabla_final <- nuevo_2026[, c(
  "Category",
  "Prediccion_2025",
  "Prediccion_2026",
  "Crecimiento",
  "Crecimiento_pct"
)]

tabla_final
##          Category Prediccion_2025 Prediccion_2026 Crecimiento Crecimiento_pct
## 1 Bath and Shower       2.6510354       2.8358524  0.18481701        6.971503
## 2      Deodorants       2.9253107       3.1292488  0.20393813        6.971503
## 3    Depilatories       0.2680077       0.2866918  0.01868416        6.971503
## 4      Fragrances       5.7979821       6.2021886  0.40420651        6.971503
## 5       Hair Care       7.2518465       7.7574092  0.50556271        6.971503
## 6  Men's Grooming       6.0940828       6.5189320  0.42484918        6.971503
## 7       Skin Care       8.0862046       8.6499346  0.56373001        6.971503
## 8        Sun Care       0.4404674       0.4711746  0.03070720        6.971503

CONCLUSIÓN — ¿En qué subcategoría invertiría?

Si tuvieramos que invertir en una subcategoría, elegiriamos Skin Care.

De acuerdo con el modelo de efectos aleatorios, Skin Care presenta la mayor predicción para 2026, con un valor estimado de 8.65, frente a 8.09 en 2025. Esto representa un crecimiento aproximado de 6.97%, igual que el resto de las categorías debido a la estructura del modelo, pero Skin Care parte del nivel de ventas proyectado más alto. Por lo tanto, aunque el porcentaje de crecimiento sea similar, el incremento absoluto esperado es el mayor, de aproximadamente 0.56 unidades, lo que representa un mayor potencial de generación de valor.

Esta elección también está respaldada por la situación actual de la industria. McKinsey señala que Skin Care representa aproximadamente 40% del valor del mercado de belleza, y se espera que el sector de belleza continúe creciendo alrededor de 5% anual hasta 2030. Además, los consumidores muestran una mayor disposición a gastar en productos de cuidado de la piel que ofrecen beneficios claros y resultados visibles.

La tendencia también es relevante en México: Euromonitor identifica que el cuidado facial mantiene su liderazgo mientras los consumidores adoptan rutinas cada vez más enfocadas en el cuidado de la piel, además de observar mayor interés por productos con fórmulas funcionales y respaldo científico.

Por lo tanto, Skin Care representa la alternativa de inversión más atractiva, ya que combina el mejor nivel de ventas proyectado en nuestro modelo con una categoría que actualmente tiene una posición sólida y perspectivas favorables dentro de la industria de belleza. La inversión podría enfocarse especialmente en productos diferenciados, con ingredientes activos, beneficios comprobables y estrategias de personalización, aprovechando la tendencia hacia rutinas de cuidado más especializadas.

En conclusión, invertiriamos en Skin Care porque no solo presenta la mayor predicción de ventas para 2026 y el mayor incremento absoluto estimado dentro de nuestra base, sino que además coincide con una tendencia real del mercado, donde el cuidado de la piel continúa siendo uno de los principales motores de crecimiento de la industria de belleza.

Ejercicio 3 - BANCO MUNDIAL

INSTRUCCIONES: Importa datos del banco mundial y genera el mejor modelo, incluyendo predicciones. Incluye conclusiones y gráficas.

#install.packages("jsonlite", repos = "https://cloud.r-project.org")
#install.packages("dplyr", repos = "https://cloud.r-project.org")
#install.packages("plm", repos = "https://cloud.r-project.org")
#install.packages("ggplot2", repos = "https://cloud.r-project.org")

library(jsonlite)
library(dplyr)
library(plm)
library(ggplot2)
# Importar datos del banco mundial

obtener_WB <- function(indicador, nombre) {
  
  url <- paste0(
    "https://api.worldbank.org/v2/country/MEX;USA;CAN;BRA/indicator/",
    indicador,
    "?format=json&per_page=1000"
  )
  
  datos <- fromJSON(url, flatten = TRUE)
  
  datos[[2]] %>%
    select(
      country.value,
      countryiso3code,
      date,
      value
    ) %>%
    rename(
      country = country.value,
      iso3c = countryiso3code,
      year = date,
      !!nombre := value
    ) %>%
    mutate(year = as.numeric(year))
}
# Importar los Inidcadores

PIB <- obtener_WB(
  "NY.GDP.PCAP.CD",
  "PIB_pc"
)

Desempleo <- obtener_WB(
  "SL.UEM.TOTL.ZS",
  "Desempleo"
)

IED <- obtener_WB(
  "BX.KLT.DINV.CD.WD",
  "IED"
)

Exportaciones <- obtener_WB(
  "NE.EXP.GNFS.CD",
  "Exportaciones"
)

Esperanza <- obtener_WB(
  "SP.DYN.LE00.IN",
  "Esperanza_vida"
)
df <- PIB %>%
  select(country, iso3c, year, PIB_pc) %>%
  left_join(
    Desempleo %>% select(iso3c, year, Desempleo),
    by = c("iso3c", "year")
  ) %>%
  left_join(
    IED %>% select(iso3c, year, IED),
    by = c("iso3c", "year")
  ) %>%
  left_join(
    Exportaciones %>% select(iso3c, year, Exportaciones),
    by = c("iso3c", "year")
  ) %>%
  left_join(
    Esperanza %>% select(iso3c, year, Esperanza_vida),
    by = c("iso3c", "year")
  ) %>%
  filter(year >= 2010 & year <= 2024)
head(df)
##   country iso3c year    PIB_pc Desempleo         IED Exportaciones
## 1  Brazil   BRA 2024 10310.549     6.801 74090786050  392105346047
## 2  Brazil   BRA 2023 10377.589     7.947 62750364285  393731572888
## 3  Brazil   BRA 2022  9281.333     9.231 75501038733  383177602116
## 4  Brazil   BRA 2021  7972.537    13.158 46440503520  319251201403
## 5  Brazil   BRA 2020  7074.194    13.697 38270116307  242872071018
## 6  Brazil   BRA 2019  9029.833    11.936 69174411753  264562979421
##   Esperanza_vida
## 1         76.023
## 2         75.848
## 3         74.872
## 4         73.038
## 5         74.506
## 6         75.809
summary(df)
##       country         iso3c         year          PIB_pc        Desempleo     
##  Length   :60   Length   :60   Min.   :2010   Min.   : 7074   Min.   : 2.678  
##  N.unique : 4   N.unique : 4   1st Qu.:2013   1st Qu.:10313   1st Qu.: 4.419  
##  N.blank  : 0   N.blank  : 0   Median :2017   Median :28151   Median : 6.388  
##  Min.nchar: 6   Min.nchar: 3   Mean   :2017   Mean   :33364   Mean   : 6.603  
##  Max.nchar:13   Max.nchar: 3   3rd Qu.:2021   3rd Qu.:52989   3rd Qu.: 7.974  
##                                Max.   :2024   Max.   :86170   Max.   :13.697  
##       IED            Exportaciones       Esperanza_vida 
##  Min.   :1.823e+10   Min.   :2.239e+11   Min.   :69.75  
##  1st Qu.:3.817e+10   1st Qu.:3.899e+11   1st Qu.:74.42  
##  Median :6.290e+10   Median :5.106e+11   Median :76.18  
##  Mean   :1.203e+11   Mean   :9.510e+11   Mean   :77.16  
##  3rd Qu.:1.111e+11   3rd Qu.:1.021e+12   3rd Qu.:79.44  
##  Max.   :5.114e+11   Max.   :3.215e+12   Max.   :82.16
colSums(is.na(df))
##        country          iso3c           year         PIB_pc      Desempleo 
##              0              0              0              0              0 
##            IED  Exportaciones Esperanza_vida 
##              0              0              0
df_panel <- pdata.frame(
  df,
  index = c("country", "year")
)

head(df_panel)
##             country iso3c year    PIB_pc Desempleo          IED Exportaciones
## Brazil-2010  Brazil   BRA 2010 11403.282     8.420  82389932468  240003137742
## Brazil-2011  Brazil   BRA 2011 13396.624     7.578 102427228231  303016626326
## Brazil-2012  Brazil   BRA 2012 12521.721     7.251  92568388321  292808395454
## Brazil-2013  Brazil   BRA 2013 12458.891     7.071  75211029129  290364173325
## Brazil-2014  Brazil   BRA 2014 12274.994     6.755  87713983217  270458130850
## Brazil-2015  Brazil   BRA 2015  8936.197     8.538  64738153494  232488824445
##             Esperanza_vida
## Brazil-2010         73.779
## Brazil-2011         74.047
## Brazil-2012         74.335
## Brazil-2013         74.609
## Brazil-2014         74.823
## Brazil-2015         75.106
pdim(df_panel)
## Balanced Panel: n = 4, T = 15, N = 60
ggplot(df, aes(x = year, y = PIB_pc, color = country)) +
  geom_line(linewidth = 1) +
  geom_point() +
  labs(
    title = "PIB per cápita por país",
    x = "Año",
    y = "PIB per cápita (USD)",
    color = "País"
  ) +
  theme_minimal()

ggplot(df, aes(x = Desempleo, y = PIB_pc, color = country)) +
  geom_point(size = 2) +
  geom_smooth(method = "lm", se = FALSE) +
  labs(
    title = "Relación entre desempleo y PIB per cápita",
    x = "Desempleo (%)",
    y = "PIB per cápita (USD)"
  ) +
  theme_minimal()

ggplot(df, aes(x = IED, y = PIB_pc, color = country)) +
  geom_point(size = 2) +
  labs(
    title = "Relación entre inversión extranjera y PIB per cápita",
    x = "Inversión extranjera directa (USD)",
    y = "PIB per cápita (USD)"
  ) +
  theme_minimal()

modelo_pooled <- plm(
  PIB_pc ~ Desempleo + Esperanza_vida,
  data = df_panel,
  model = "pooling"
)

summary(modelo_pooled)
## Pooling Model
## 
## Call:
## plm(formula = PIB_pc ~ Desempleo + Esperanza_vida, data = df_panel, 
##     model = "pooling")
## 
## Balanced Panel: n = 4, T = 15, N = 60
## 
## Residuals:
##    Min. 1st Qu.  Median 3rd Qu.    Max. 
##  -17236  -10475   -5263   12026   40074 
## 
## Coefficients:
##                  Estimate Std. Error t-value  Pr(>|t|)    
## (Intercept)    -388632.51   47330.57 -8.2110 3.070e-11 ***
## Desempleo        -2169.84     736.95 -2.9444  0.004677 ** 
## Esperanza_vida    5654.54     612.28  9.2351 6.391e-13 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    3.5106e+10
## Residual Sum of Squares: 1.3447e+10
## R-Squared:      0.61694
## Adj. R-Squared: 0.6035
## F-statistic: 45.9017 on 2 and 57 DF, p-value: 1.3273e-12
modelo_fixed <- plm(
  PIB_pc ~ Desempleo + Esperanza_vida,
  data = df_panel,
  model = "within"
)

summary(modelo_fixed)
## Oneway (individual) effect Within Model
## 
## Call:
## plm(formula = PIB_pc ~ Desempleo + Esperanza_vida, data = df_panel, 
##     model = "within")
## 
## Balanced Panel: n = 4, T = 15, N = 60
## 
## Residuals:
##    Min. 1st Qu.  Median 3rd Qu.    Max. 
##   -6959   -4195    -870    2844   20428 
## 
## Coefficients:
##                Estimate Std. Error t-value  Pr(>|t|)    
## Desempleo      -1865.28     412.57 -4.5211 3.401e-05 ***
## Esperanza_vida  -932.82     769.12 -1.2128    0.2305    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    2344800000
## Residual Sum of Squares: 1.684e+09
## R-Squared:      0.28181
## Adj. R-Squared: 0.21531
## F-statistic: 10.5945 on 2 and 54 DF, p-value: 0.00013136
modelo_random <- plm(
  PIB_pc ~ Desempleo + Esperanza_vida,
  data = df_panel,
  model = "random"
)

summary(modelo_random)
## Oneway (individual) effect Random Effect Model 
##    (Swamy-Arora's transformation)
## 
## Call:
## plm(formula = PIB_pc ~ Desempleo + Esperanza_vida, data = df_panel, 
##     model = "random")
## 
## Balanced Panel: n = 4, T = 15, N = 60
## 
## Effects:
##                     var   std.dev share
## idiosyncratic  31184972      5584 0.049
## individual    607081936     24639 0.951
## theta: 0.9416
## 
## Residuals:
##    Min. 1st Qu.  Median 3rd Qu.    Max. 
##   -5629   -3967   -1622    2906   21986 
## 
## Coefficients:
##                Estimate Std. Error z-value  Pr(>|z|)    
## (Intercept)    97624.66   60421.86  1.6157    0.1062    
## Desempleo      -1854.45     415.70 -4.4611 8.155e-06 ***
## Esperanza_vida  -674.09     762.70 -0.8838    0.3768    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    2456600000
## Residual Sum of Squares: 1813700000
## R-Squared:      0.26171
## Adj. R-Squared: 0.2358
## Chisq: 20.2051 on 2 DF, p-value: 4.0975e-05
pFtest(modelo_fixed, modelo_pooled)
## 
##  F test for individual effects
## 
## data:  PIB_pc ~ Desempleo + Esperanza_vida
## F = 125.74, df1 = 3, df2 = 54, p-value < 2.2e-16
## alternative hypothesis: significant effects
phtest(modelo_random, modelo_fixed)
## 
##  Hausman Test
## 
## data:  PIB_pc ~ Desempleo + Esperanza_vida
## chisq = 6.7613, df = 2, p-value = 0.03402
## alternative hypothesis: one model is inconsistent

CONCLUSIÓN MEJOR MODELO: A – Afirmación: El modelo de Efectos Fijos fue el modelo ganador para analizar y predecir el PIB per cápita de los países seleccionados, ya que permite tomar en cuenta las características particulares de cada economía y entender cómo los cambios en variables como el desempleo pueden impactar su desempeño económico.

R – Razón: Para una empresa, inversionista o gobierno, no sería adecuado analizar a todos los países como si fueran iguales. Cada economía tiene condiciones estructurales diferentes que influyen en sus resultados. El modelo de Efectos Fijos permite considerar estas diferencias y enfocarse en cómo los cambios dentro de cada país se relacionan con su PIB per cápita. Esto hace que el análisis sea más útil para identificar señales económicas y apoyar la toma de decisiones.

E – Evidencia: Las pruebas estadísticas respaldaron esta elección: la prueba F descartó el modelo Pooled y la prueba de Hausman descartó los Efectos Aleatorios, por lo que los Efectos Fijos fueron la alternativa más adecuada. Además, el modelo mostró que el desempleo tiene una relación negativa con el PIB per cápita, lo que refuerza la importancia de mantener niveles saludables de empleo para favorecer el desempeño económico.

modelo_final <- plm(
  PIB_pc ~ Desempleo + Esperanza_vida,
  data = df_panel,
  model = "within"
)

summary(modelo_final)
## Oneway (individual) effect Within Model
## 
## Call:
## plm(formula = PIB_pc ~ Desempleo + Esperanza_vida, data = df_panel, 
##     model = "within")
## 
## Balanced Panel: n = 4, T = 15, N = 60
## 
## Residuals:
##    Min. 1st Qu.  Median 3rd Qu.    Max. 
##   -6959   -4195    -870    2844   20428 
## 
## Coefficients:
##                Estimate Std. Error t-value  Pr(>|t|)    
## Desempleo      -1865.28     412.57 -4.5211 3.401e-05 ***
## Esperanza_vida  -932.82     769.12 -1.2128    0.2305    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    2344800000
## Residual Sum of Squares: 1.684e+09
## R-Squared:      0.28181
## Adj. R-Squared: 0.21531
## F-statistic: 10.5945 on 2 and 54 DF, p-value: 0.00013136
df_train <- subset(df, year <= 2023)
df_test <- subset(df, year == 2024)
df_train_panel <- pdata.frame(
  df_train,
  index = c("country", "year")
)
modelo_final <- plm(
  PIB_pc ~ Desempleo + Esperanza_vida,
  data = df_train_panel,
  model = "within"
)

summary(modelo_final)
## Oneway (individual) effect Within Model
## 
## Call:
## plm(formula = PIB_pc ~ Desempleo + Esperanza_vida, data = df_train_panel, 
##     model = "within")
## 
## Balanced Panel: n = 4, T = 14, N = 56
## 
## Residuals:
##    Min. 1st Qu.  Median 3rd Qu.    Max. 
##   -6315   -3751    -669    2888   17574 
## 
## Coefficients:
##                Estimate Std. Error t-value Pr(>|t|)    
## Desempleo      -1678.19     372.68 -4.5031 4.03e-05 ***
## Esperanza_vida -1193.82     695.73 -1.7159  0.09236 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    1724300000
## Residual Sum of Squares: 1.179e+09
## R-Squared:      0.31623
## Adj. R-Squared: 0.24785
## F-statistic: 11.5618 on 2 and 50 DF, p-value: 7.4611e-05
df_test_panel <- pdata.frame(
  df_test,
  index = c("country", "year")
)
df_test$PIB_predicho <- predict(
  modelo_final,
  newdata = df_test_panel
)

df_test[, c(
  "country",
  "year",
  "PIB_pc",
  "PIB_predicho"
)]
##          country year   PIB_pc PIB_predicho
## 1         Brazil 2024 10310.55     13884.79
## 16        Canada 2024 55015.71     49581.70
## 31        Mexico 2024 13988.04     11090.87
## 46 United States 2024 86169.66     63765.73
df_test$Error <- df_test$PIB_pc - df_test$PIB_predicho

df_test$Error_Porcentual <- 
  abs(df_test$Error / df_test$PIB_pc) * 100

df_test[, c(
  "country",
  "PIB_pc",
  "PIB_predicho",
  "Error",
  "Error_Porcentual"
)]
##          country   PIB_pc PIB_predicho     Error Error_Porcentual
## 1         Brazil 10310.55     13884.79 -3574.237        34.665832
## 16        Canada 55015.71     49581.70  5434.003         9.877184
## 31        Mexico 13988.04     11090.87  2897.172        20.711774
## 46 United States 86169.66     63765.73 22403.933        25.999791
df_comparacion <- rbind(
  data.frame(
    country = df_test$country,
    PIB = df_test$PIB_pc,
    Tipo = "Real"
  ),
  data.frame(
    country = df_test$country,
    PIB = df_test$PIB_predicho,
    Tipo = "Predicho"
  )
)

ggplot(
  df_comparacion,
  aes(x = country, y = PIB, fill = Tipo)
) +
  geom_col(
    position = position_dodge(width = 0.8),
    width = 0.7
  ) +
  labs(
    title = "PIB per cápita real vs. predicho para 2024",
    x = "País",
    y = "PIB per cápita (USD)",
    fill = "Valor"
  ) +
  theme_minimal()

ggplot(df, aes(x = year, y = PIB_pc, color = country)) +
  geom_line(linewidth = 1) +
  geom_point() +
  labs(
    title = "Evolución del PIB per cápita, 2010–2024",
    x = "Año",
    y = "PIB per cápita (USD)",
    color = "País"
  ) +
  theme_minimal()

df_test[, c(
  "country",
  "PIB_pc",
  "PIB_predicho",
  "Error_Porcentual"
)]
##          country   PIB_pc PIB_predicho Error_Porcentual
## 1         Brazil 10310.55     13884.79        34.665832
## 16        Canada 55015.71     49581.70         9.877184
## 31        Mexico 13988.04     11090.87        20.711774
## 46 United States 86169.66     63765.73        25.999791
summary(modelo_final)
## Oneway (individual) effect Within Model
## 
## Call:
## plm(formula = PIB_pc ~ Desempleo + Esperanza_vida, data = df_train_panel, 
##     model = "within")
## 
## Balanced Panel: n = 4, T = 14, N = 56
## 
## Residuals:
##    Min. 1st Qu.  Median 3rd Qu.    Max. 
##   -6315   -3751    -669    2888   17574 
## 
## Coefficients:
##                Estimate Std. Error t-value Pr(>|t|)    
## Desempleo      -1678.19     372.68 -4.5031 4.03e-05 ***
## Esperanza_vida -1193.82     695.73 -1.7159  0.09236 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    1724300000
## Residual Sum of Squares: 1.179e+09
## R-Squared:      0.31623
## Adj. R-Squared: 0.24785
## F-statistic: 11.5618 on 2 and 50 DF, p-value: 7.4611e-05

PREDICCIÓN : ¿Cuál sería el PIB per cápita esperado para cada país en 2024, considerando su nivel de desempleo y esperanza de vida?

CONCLUSIÓN:

A – Afirmación: El modelo de Efectos Fijos permitió estimar el PIB per cápita de 2024 para los cuatro países analizados y, aunque las predicciones no fueron exactas en todos los casos, sí permitieron identificar diferencias importantes entre los mercados y evaluar qué tan bien el modelo logra representar su comportamiento económico.

R – Razón: Las predicciones permiten comparar el valor que el modelo esperaba obtener con el valor que realmente se observó en 2024. Esta comparación es útil porque no solo nos indica qué tan preciso es el modelo, sino que también permite identificar mercados donde existen factores económicos adicionales que el modelo no está capturando. Desde una perspectiva empresarial, estas diferencias son relevantes porque muestran que las condiciones de cada mercado pueden requerir un análisis más profundo antes de tomar decisiones de inversión o expansión.

E – Evidencia: Para 2024, el modelo pronosticó un PIB per cápita de $13,884.79 USD para Brasil, frente a un valor real de $10,310.55 USD, generando un error de 34.67%. Para Canadá, la predicción fue de $49,581.70 USD frente a $55,015.71 USD reales, con el menor error de la muestra (9.88%). En México, el modelo estimó $11,090.87 USD frente a $13,988.04 USD reales, con un error de 20.71%, mientras que para Estados Unidos estimó $63,765.73 USD frente a $86,169.66 USD reales, con un error de 26.00%.

A partir de estos resultados, el principal hallazgo es que Canadá fue el mercado donde el modelo tuvo mayor precisión, mientras que Brasil presentó la mayor diferencia entre lo esperado y lo observado. También se observa que el modelo tendió a subestimar el PIB per cápita de Canadá, México y Estados Unidos, mientras que sobreestimó el de Brasil. Esto indica que existen características económicas particulares de cada país que no están siendo capturadas completamente por las variables utilizadas.

Desde una perspectiva empresarial, esto significa que el modelo puede funcionar como una herramienta inicial para comparar mercados y detectar tendencias, pero no debería utilizarse como único criterio para tomar decisiones de inversión. Las diferencias entre las predicciones y los valores reales sugieren que sería conveniente incorporar variables adicionales, como inversión, exportaciones, inflación, consumo o crecimiento económico, para obtener un análisis más completo y mejorar la precisión de futuras predicciones.

LS0tCnRpdGxlOiAiRGF0b3MgZGUgUGFuZWwiCmF1dGhvcjogIlNoYXJvbiBTZXJyYW5vIC0gQTAwODM3Mjc0IC8gVsOtY3RvciBSYW3DrXJleiAtIEEwMTE3ODE2OSIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiBUUlVFCiAgICB0b2NfZmxvYXQ6IFRydWUKICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUKZGF0ZTogIjIwMjYtMDgtMjIiCi0tLQoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBJbnN0YWxhciBwYXF1ZXRlcyB5IGxsYW1hciBsaWJyZXLDrWFzCiNpbnN0YWxsLnBhY2thZ2VzKCJwbG0iLCByZXBvcyA9ICJodHRwczovL2Nsb3VkLnItcHJvamVjdC5vcmciKQojaW5zdGFsbC5wYWNrYWdlcygiZ3Bsb3RzIiwgcmVwb3MgPSAiaHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnIikKI2luc3RhbGwucGFja2FnZXMoImRwbHlyIiwgcmVwb3MgPSAiaHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnIikKCmxpYnJhcnkocGxtKQpsaWJyYXJ5KGdwbG90cykKbGlicmFyeShkcGx5cikKYGBgCgojIEVqZXJjaWNpbyAxIC0gUEFURU5URVMKR2VuZXJhIGVsIG1lam9yIG1vZGVsbyBkZSBsYSBCYXNlIGRlIERhdG9zICJQYXRlbnRlcyIgeSBnZW5lcmEgcHJlZGljY2lvbmVzLiBJbmNsdXllIGNvbmNsdXNpb25lcy4KCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIENhcmdhbW9zIGxhIGJhc2UgZGUgZGF0b3MgKGFqdXN0YSBsYSBydXRhIGEgZG9uZGUgbGEgdGVuZ2FzIGd1YXJkYWRhKQpkZl9wYXRlbnRlcyA8LSByZWFkLmNzdigiL1VzZXJzL3NoYXJvbnRvcnJlcy9Eb3dubG9hZHMvQWN0aXZpZGFkMS9QQVRFTlQzLmNzdiIpCgojIENvbnZlcnRpbW9zIGEgZm9ybWF0byBkZSBwYW5lbDogaWRlbnRpZmljYWRvciA9IGN1c2lwLCB0aWVtcG8gPSB5ZWFyCmRmX3BhdGVudGVzIDwtIHBkYXRhLmZyYW1lKGRmX3BhdGVudGVzLCBpbmRleCA9IGMoImN1c2lwIiwgInllYXIiKSkKCgptb2RlbG9fcmVncmVzaW9uX3N0Y2twciA8LSBsbShzdGNrcHIgfiBwYXRlbnRzLCBkZl9wYXRlbnRlcykKc3VtbWFyeShtb2RlbG9fcmVncmVzaW9uX3N0Y2twcikKCgojIFBydWViYSBkZSBIZXRlcm9nZW5laWRhZCAoYWdydXBhbW9zIHBvciBlbXByZXNhLCBjdXNpcCkKcGxvdG1lYW5zKHN0Y2twciB+IGN1c2lwLCBkYXRhID0gZGZfcGF0ZW50ZXMpCiMgSU5URVJQUkVUQUNJw5NOOiBCdXNjYW1vcyBsw61uZWEgcXVlYnJhZGEgcXVlIHVuYSBsb3MgcHJvbWVkaW9zIChIYXkgaGV0ZXJvZ2VuZWlkYWQpCiMgcGFyYSBlbGVnaXIgZW50cmUgTW9kZWxvIGRlIEVmZWN0b3MgRmlqb3MgbyBBbGVhdG9yaW9zLiBTaSBzYWxlIHVuYSBsw61uZWEgaG9yaXpvbnRhbAojIG5vIGhheSBoZXRlcm9nZW5laWRhZCwgcHJvYmFibGVtZW50ZSBsYSBtZWpvciBvcGNpw7NuIHNlYSBlbCBNb2RlbG8gQWdydXBhZG8uCgojIE9wY2nDs24gMSAtIE1vZGVsbyBkZSBSZWdyZXNpw7NuIEFncnVwYWRhIChQb29sZWQpCm1vZGVsb19wb29sZWRfc3Rja3ByIDwtIHBsbShzdGNrcHIgfiBwYXRlbnRzLCBkYXRhID0gZGZfcGF0ZW50ZXMsIG1vZGVsID0gInBvb2xpbmciKQpzdW1tYXJ5KG1vZGVsb19wb29sZWRfc3Rja3ByKQoKIyBPcGNpw7NuIDIgLSBNb2RlbG8gZGUgRWZlY3RvcyBGaWpvcyAod2l0aGluKQptb2RlbG9fd2l0aGluX3N0Y2twciA8LSBwbG0oc3Rja3ByIH4gcGF0ZW50cywgZGF0YSA9IGRmX3BhdGVudGVzLCBtb2RlbCA9ICJ3aXRoaW4iKQpzdW1tYXJ5KG1vZGVsb193aXRoaW5fc3Rja3ByKQoKIyBQcnVlYmEgRgojIElOVEVSUFJFVEFDScOTTjogU2kgcDwgMC4wNSBObyB1c2FyIFBPT0xFRC4gU2kgcD4gMC4wNSBVc2FyIFBPT0xFRC4KcEZ0ZXN0KG1vZGVsb193aXRoaW5fc3Rja3ByLCBtb2RlbG9fcG9vbGVkX3N0Y2twcikgI1NpZW1wcmUgdmEgcHJpbWVybyB3aXRoaW4sIE5PIFBPT0xFRC4KCiMgT3BjacOzbiAzIC0gTW9kZWxvIGRlIEVmZWN0b3MgQWxlYXRvcmlvcyAoUmFuZG9tKQptb2RlbG9fcmFuZG9tX3N0Y2twciA8LSBwbG0oc3Rja3ByIH4gcGF0ZW50cywgZGF0YSA9IGRmX3BhdGVudGVzLCBtb2RlbCA9ICJyYW5kb20iKQpzdW1tYXJ5KG1vZGVsb19yYW5kb21fc3Rja3ByKQoKIyBQcnVlYmEgZGUgSGF1c21hbgojIElOVEVSUFJFVEFDScOTTjogU2kgcDwgMC4wNSBVc2FyIEVmZWN0b3MgRmlqb3MuIFNpIHA+IDAuMDUgVXNhciBFZmVjdG9zIEFsZWF0b3Jpb3MuCnBodGVzdChtb2RlbG9fcmFuZG9tX3N0Y2twciwgbW9kZWxvX3dpdGhpbl9zdGNrcHIpICNTaWVtcHJlIHZhIHByaW1lcm8gcmFuZG9tLCBOTyBXSVRISU4KYGBgCkNPTkNMVVNJw5NOIE1FSk9SIE1PREVMTzoKCkFmaXJtYWNpw7NuOiBFbCBtb2RlbG8gbcOhcyBhZGVjdWFkbyBwYXJhIGVzdGUgYW7DoWxpc2lzIGVzIGVsIGRlIEVmZWN0b3MgRmlqb3MuCgpSYXrDs246IExhcyBwcnVlYmFzIGVzdGFkw61zdGljYXMgZGlzZcOxYWRhcyBwYXJhIGVzdGEgZGVjaXNpw7NuIOKAlGxhIFBydWViYSBGIHkgbGEgUHJ1ZWJhIGRlIEhhdXNtYW7igJQgZGVzY2FydGFyb24gdGFudG8gZWwgTW9kZWxvIEFncnVwYWRvIGNvbW8gZWwgZGUgRWZlY3RvcyBBbGVhdG9yaW9zLgoKRXZpZGVuY2lhOiBBbWJhcyBwcnVlYmFzIGFycm9qYXJvbiB1biBwLXZhbHVlIHByw6FjdGljYW1lbnRlIGlndWFsIGEgY2VybywgbXV5IHBvciBkZWJham8gZGVsIHVtYnJhbCBkZSAwLjA1LCBsbyBxdWUgY29uZmlybWEgY29uIGNsYXJpZGFkIGxhIGVsZWNjacOzbiBkZWwgTW9kZWxvIGRlIEVmZWN0b3MgRmlqb3MuCgpgYGB7cn0KdWx0aW1vX2FuaW8gPC0gYXMuZGF0YS5mcmFtZShkZl9wYXRlbnRlcykKdWx0aW1vX2FuaW8gPC0gdWx0aW1vX2FuaW9bdWx0aW1vX2FuaW8keWVhciA9PSAyMDIxLCBdCgpwZW5kaWVudGVfZmUgPC0gY29lZihtb2RlbG9fd2l0aGluX3N0Y2twcilbInBhdGVudHMiXQplZmVjdG9zX2Zpam9zIDwtIGZpeGVmKG1vZGVsb193aXRoaW5fc3Rja3ByKQoKcGF0ZW50c18yMDIyIDwtIDEuMSAqIHVsdGltb19hbmlvJHBhdGVudHMgICAjICsxMCUgcmVzcGVjdG8gYSAyMDIxCm5vbWJyZXNfZW1wcmVzYXMgPC0gYXMuY2hhcmFjdGVyKHVsdGltb19hbmlvJGN1c2lwKQoKcHJvbm9zdGljb19mZSA8LSBlZmVjdG9zX2Zpam9zW25vbWJyZXNfZW1wcmVzYXNdICsgcGVuZGllbnRlX2ZlICogcGF0ZW50c18yMDIyCgpkZl9wcm9ub3N0aWNvX2ZlIDwtIGRhdGEuZnJhbWUoCiAgY3VzaXAgPSBub21icmVzX2VtcHJlc2FzLAogIHN0Y2twcl9wcm9ub3N0aWNvID0gYXMubnVtZXJpYyhwcm9ub3N0aWNvX2ZlKQopCgpoZWFkKGRmX3Byb25vc3RpY29fZmUsIDEwKQpgYGAKQ09OQ0xVU0nDk046IAoKQWZpcm1hY2nDs246IFNpIGxhcyBlbXByZXNhcyBsb2dyYW4gMTAlIG3DoXMgcGF0ZW50ZXMgZW4gMjAyMiwgZWwgcHJlY2lvIGRlIHN1cyBhY2Npb25lcyB2YSBhIHN1YmlyLCBwZXJvIG5vIHRvZGFzIHZhbiBhIHN1YmlyIGxvIG1pc21vLgoKUmF6w7NuOiBQb3JxdWUgY2FkYSBlbXByZXNhIHlhIGFycmFuY2EgZGVzZGUgdW4gbHVnYXIgZGlzdGludG8uIEVsIG1vZGVsbyBjYXB0YSBkb3MgY29zYXM6IGVsICJib29zdCIgcXVlIGRhbiBsYXMgcGF0ZW50ZXMgbnVldmFzLCB5IGVsIHB1bnRvIGRlIHBhcnRpZGEgcXVlIHlhIHRyYWUgY2FkYSBlbXByZXNhIHBvciBzdSBwcm9waWEgaGlzdG9yaWEuCgpFdmlkZW5jaWE6IExvIHZlbW9zIGNsYXJpdG8gZW4gbG9zIG7Dum1lcm9zOiBjb24gZWwgbWlzbW8gYXVtZW50byBkZWwgMTAlIGVuIHBhdGVudGVzIHBhcmEgdG9kYXMsIHVuYXMgdGVybWluYW4gZW4gMS40NyB5IG90cmFzIGVuIDM3LjY0LiBPIHNlYSwgZWwgZWZlY3RvIGRlIGlubm92YXIgc8OtIGphbGEgZWwgcHJlY2lvIHBhcmEgYXJyaWJhIGVuIHRvZG9zIGxvcyBjYXNvcywgcGVybyBlbCByZXN1bHRhZG8gZmluYWwgZGVwZW5kZSBkZSBkw7NuZGUgZXN0YWJhIHBhcmFkYSBjYWRhIGVtcHJlc2EgYW50ZXMg4oCUIG5vIGVzIHF1ZSB0b2RhcyBsbGVndWVuIGFsIG1pc21vIGx1Z2FyIHNvbG8gcG9yIGhhY2VyIGVsIG1pc21vIGVzZnVlcnpvLgoKIyBFamVyY2ljaW8gMiAtIENVSURBRE8gREUgTEEgUElFTApJTlNUUlVDQ0lPTkVTOiBHZW5lcmEgZWwgbWVqb3IgbW9kZWxvIGRlIGxhIEJhc2UgZGUgRGF0b3MgIk1hcmtldCBzaXplcyIgeSBnZW5lcmEgcHJlZGljY2lvbmVzLiBJbmNsdXllIGNvbmNsdXNpb25lcy4gU2kgdHV2aWVyYXMgcXVlIGludmVydGlyIGVuIGFsZ3VuYSBzdWItY2F0ZWdvcsOtYSwgwr9lbiBjdcOhbCBsbyBoYXLDrWFzPyBKdXN0aWZpY2EgYW1wbGlhbWVudGUgdHUgcmVzcHVlc3RhLgoKYGBge3J9CiMgSW5zdGFsYXIgcGFxdWV0ZXMgc2kgZXMgbmVjZXNhcmlvCiMgaW5zdGFsbC5wYWNrYWdlcyhjKCJkcGx5ciIsICJ0aWR5ciIsICJwbG0iLCAiZ2dwbG90MiIpKQoKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShwbG0pCmxpYnJhcnkoZ2dwbG90MikKCiMgQ2FyZ2FyIGxhIGJhc2Ugb3JpZ2luYWwKZGZfbWFya2V0IDwtIHJlYWQuY3N2KAogICIvVXNlcnMvc2hhcm9udG9ycmVzL0Rvd25sb2Fkcy9BY3RpdmlkYWQxL01hcmtldF9zaXplc19jbGVhbi5jc3YiLAogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQopCgojIENhdGVnb3LDrWFzIHF1ZSB2YW1vcyBhIGFuYWxpemFyCmNhdHMgPC0gYygKICAiQmF0aCBhbmQgU2hvd2VyIiwKICAiRGVvZG9yYW50cyIsCiAgIkRlcGlsYXRvcmllcyIsCiAgIkZyYWdyYW5jZXMiLAogICJIYWlyIENhcmUiLAogICJNZW4ncyBHcm9vbWluZyIsCiAgIlNraW4gQ2FyZSIsCiAgIlN1biBDYXJlIgopCmBgYAoKYGBge3J9CmRmX2xvbmcgPC0gZGZfbWFya2V0ICU+JQogIGZpbHRlcihDYXRlZ29yeSAlaW4lIGNhdHMpICU+JQogIHNlbGVjdChDYXRlZ29yeSwgWDIwMTE6WDIwMjUpICU+JQogIG11dGF0ZSgKICAgIGFjcm9zcyhYMjAxMTpYMjAyNSwgfiBhcy5udW1lcmljKGdzdWIoIiwiLCAiIiwgLikpKQogICkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IFgyMDExOlgyMDI1LAogICAgbmFtZXNfdG8gPSAiQcOxbyIsCiAgICB2YWx1ZXNfdG8gPSAiVmFsb3IiCiAgKSAlPiUKICBtdXRhdGUoCiAgICBBw7FvX251bSA9IGFzLm51bWVyaWMoZ3N1YigiWCIsICIiLCBBw7FvKSksCiAgICBBw7FvX2NlbnRyYWRvID0gQcOxb19udW0gLSAyMDExCiAgKSAlPiUKICBhcnJhbmdlKENhdGVnb3J5LCBBw7FvX251bSkKCmhlYWQoZGZfbG9uZykKYGBgCmBgYHtyfQpkZl9wYW5lbCA8LSBwZGF0YS5mcmFtZSgKICBkZl9sb25nLAogIGluZGV4ID0gYygiQ2F0ZWdvcnkiLCAiQcOxb19udW0iKQopCgpwZGltKGRmX3BhbmVsKQoKYGBgCgpgYGB7cn0Kc3RyKGRmX2xvbmckQcOxb19udW0pCnN0cihkZl9sb25nJEHDsW9fY2VudHJhZG8pCmBgYAoKCmBgYHtyfQptb2RlbG9fcG9vbGVkIDwtIHBsbSgKICBsb2coVmFsb3IpIH4gQcOxb19jZW50cmFkbywKICBkYXRhID0gZGZfcGFuZWwsCiAgbW9kZWwgPSAicG9vbGluZyIKKQoKc3VtbWFyeShtb2RlbG9fcG9vbGVkKQpgYGAKYGBge3J9Cm1vZGVsb19maXhlZCA8LSBwbG0oCiAgbG9nKFZhbG9yKSB+IEHDsW9fY2VudHJhZG8sCiAgZGF0YSA9IGRmX3BhbmVsLAogIG1vZGVsID0gIndpdGhpbiIKKQoKc3VtbWFyeShtb2RlbG9fZml4ZWQpCmBgYApgYGB7cn0KbW9kZWxvX3JhbmRvbSA8LSBwbG0oCiAgbG9nKFZhbG9yKSB+IEHDsW9fY2VudHJhZG8sCiAgZGF0YSA9IGRmX3BhbmVsLAogIG1vZGVsID0gInJhbmRvbSIKKQoKc3VtbWFyeShtb2RlbG9fcmFuZG9tKQpgYGAKYGBge3J9CnBGdGVzdCgKICBtb2RlbG9fZml4ZWQsCiAgbW9kZWxvX3Bvb2xlZAopCmBgYApgYGB7cn0KcGh0ZXN0KAogIG1vZGVsb19yYW5kb20sCiAgbW9kZWxvX2ZpeGVkCikKYGBgCmBgYHtyfQojIFNlbGVjY2lvbmFtb3MgZWwgbW9kZWxvIGZpbmFsIHNlZ8O6biBsYXMgcHJ1ZWJhcwptb2RlbG9fZmluYWwgPC0gbW9kZWxvX3JhbmRvbQoKc3VtbWFyeShtb2RlbG9fZmluYWwpCmBgYApDT05DTFVTScOTTiBNRUpPUiBNT0RFTE86IAoKQSA6IEFmaXJtYWNpw7NuCgpFbCBtb2RlbG8gZGUgZWZlY3RvcyBhbGVhdG9yaW9zIChSYW5kb20gRWZmZWN0cykgZXMgZWwgbW9kZWxvIG3DoXMgYWRlY3VhZG8gcGFyYSBhbmFsaXphciBsYSByZWxhY2nDs24gZW50cmUgZWwgdmFsb3IgZGUgbWVyY2FkbyB5IGVsIHRpZW1wby4KClIgOiBSYXrDs24KClNlIHNlbGVjY2lvbmEgcG9ycXVlIGVsIEhhdXNtYW4gVGVzdCBubyBlbmNvbnRyw7MgZGlmZXJlbmNpYXMgc2lzdGVtw6F0aWNhcyBlbnRyZSBsb3MgZXN0aW1hZG9yZXMgZGUgZWZlY3RvcyBmaWpvcyB5IGFsZWF0b3Jpb3MuIEFsIG9idGVuZXIgdW4gcC12YWx1ZSA9IDEsIG5vIHNlIHJlY2hhemEgbGEgaGlww7N0ZXNpcyBudWxhLCBwb3IgbG8gcXVlIGVzIHbDoWxpZG8gdXRpbGl6YXIgZWwgbW9kZWxvIGRlIGVmZWN0b3MgYWxlYXRvcmlvcy4gQWRlbcOhcywgZXN0ZSBtb2RlbG8gcHJlc2VudGEgdW4gUsKyIGRlIDkyLjIwJSwgaW5kaWNhbmRvIHVuIGFsdG8gcG9kZXIgZXhwbGljYXRpdm8uCgpFIDogRXZpZGVuY2lhCkhhdXNtYW4gVGVzdDogcC12YWx1ZSA9IDEKUsKyIFJhbmRvbSBFZmZlY3RzOiAwLjkyMjAKUsKyIEZpeGVkIEVmZmVjdHM6IDAuOTI2MwpWYXJpYWJsZSBBw7FvX2NlbnRyYWRvOiBwLXZhbHVlIDwgMi4yZS0xNgpDb2VmaWNpZW50ZSBkZSBBw7FvX2NlbnRyYWRvOiAwLjA2NzM5CgpBdW5xdWUgZWwgbW9kZWxvIGRlIGVmZWN0b3MgZmlqb3MgdGllbmUgdW4gUsKyIGxpZ2VyYW1lbnRlIG1heW9yLCBlbCBIYXVzbWFuIFRlc3QgaW5kaWNhIHF1ZSBubyBoYXkgZXZpZGVuY2lhIHBhcmEgcHJlZmVyaXIgZWZlY3RvcyBmaWpvcywgcG9yIGxvIHF1ZSBzZSBlbGlnZSBSYW5kb20gRWZmZWN0cyBjb21vIG1vZGVsbyBmaW5hbC4KCmBgYHtyfQpudWV2byA8LSBkYXRhLmZyYW1lKAogIEHDsW9fY2VudHJhZG8gPSAxNQopCgpwcmVkaWNjaW9uX2xvZyA8LSBwcmVkaWN0KG1vZGVsb19maW5hbCwgbmV3ZGF0YSA9IG51ZXZvKQpwcmVkaWNjaW9uX2xvZwpgYGAKYGBge3J9Cm51ZXZvXzIwMjYgPC0gZGF0YS5mcmFtZSgKICBDYXRlZ29yeSA9IHVuaXF1ZShkZl9wYW5lbCRDYXRlZ29yeSksCiAgQcOxb19jZW50cmFkbyA9IDE1CikKCm51ZXZvXzIwMjYkQ2F0ZWdvcnkgPC0gZmFjdG9yKAogIG51ZXZvXzIwMjYkQ2F0ZWdvcnksCiAgbGV2ZWxzID0gbGV2ZWxzKGRmX3BhbmVsJENhdGVnb3J5KQopCgpwcmVkaWNjaW9uXzIwMjYgPC0gcHJlZGljdCgKICBtb2RlbG9fZmluYWwsCiAgbmV3ZGF0YSA9IG51ZXZvXzIwMjYKKQoKbnVldm9fMjAyNiRQcmVkaWNjaW9uXzIwMjYgPC0gZXhwKHByZWRpY2Npb25fMjAyNikKCm51ZXZvXzIwMjYKYGBgCmBgYHtyfQplZmVjdG9zX2NhdGVnb3JpYSA8LSByYW5lZihtb2RlbG9fZmluYWwpCgplZmVjdG9zX2NhdGVnb3JpYQpgYGAKYGBge3J9Cm51ZXZvXzIwMjYgPC0gZGF0YS5mcmFtZSgKICBDYXRlZ29yeSA9IG5hbWVzKGVmZWN0b3NfY2F0ZWdvcmlhKSwKICBBw7FvX2NlbnRyYWRvID0gMTUsCiAgZWZlY3RvID0gYXMubnVtZXJpYyhlZmVjdG9zX2NhdGVnb3JpYSkKKQoKbnVldm9fMjAyNiRQcmVkaWNjaW9uX2xvZyA8LSAKICBjb2VmKG1vZGVsb19maW5hbClbIkHDsW9fY2VudHJhZG8iXSAqIG51ZXZvXzIwMjYkQcOxb19jZW50cmFkbyArCiAgbnVldm9fMjAyNiRlZmVjdG8KCm51ZXZvXzIwMjYkUHJlZGljY2lvbl8yMDI2IDwtIAogIGV4cChudWV2b18yMDI2JFByZWRpY2Npb25fbG9nKQoKbnVldm9fMjAyNgpgYGAKYGBge3J9Cm51ZXZvXzIwMjYkUHJlZGljY2lvbl8yMDI1IDwtIGV4cCgKICBjb2VmKG1vZGVsb19maW5hbClbIkHDsW9fY2VudHJhZG8iXSAqIDE0ICsKICBudWV2b18yMDI2JGVmZWN0bwopCgpudWV2b18yMDI2JENyZWNpbWllbnRvIDwtIAogIG51ZXZvXzIwMjYkUHJlZGljY2lvbl8yMDI2IC0gbnVldm9fMjAyNiRQcmVkaWNjaW9uXzIwMjUKCm51ZXZvXzIwMjYkQ3JlY2ltaWVudG9fcGN0IDwtIAogIChudWV2b18yMDI2JFByZWRpY2Npb25fMjAyNiAvIG51ZXZvXzIwMjYkUHJlZGljY2lvbl8yMDI1IC0gMSkgKiAxMDAKCm51ZXZvXzIwMjYKYGBgCmBgYHtyfQpudWV2b18yMDI2JENyZWNpbWllbnRvIDwtIAogIG51ZXZvXzIwMjYkUHJlZGljY2lvbl8yMDI2IC0gbnVldm9fMjAyNiRQcmVkaWNjaW9uXzIwMjUKCm51ZXZvXzIwMjYkQ3JlY2ltaWVudG9fcGN0IDwtIAogIChudWV2b18yMDI2JFByZWRpY2Npb25fMjAyNiAvIG51ZXZvXzIwMjYkUHJlZGljY2lvbl8yMDI1IC0gMSkgKiAxMDAKCm51ZXZvXzIwMjYKYGBgCmBgYHtyfQp0YWJsYV9maW5hbCA8LSBudWV2b18yMDI2WywgYygKICAiQ2F0ZWdvcnkiLAogICJQcmVkaWNjaW9uXzIwMjUiLAogICJQcmVkaWNjaW9uXzIwMjYiLAogICJDcmVjaW1pZW50byIsCiAgIkNyZWNpbWllbnRvX3BjdCIKKV0KCnRhYmxhX2ZpbmFsCmBgYApDT05DTFVTScOTTiDigJQgwr9FbiBxdcOpIHN1YmNhdGVnb3LDrWEgaW52ZXJ0aXLDrWE/CgpTaSB0dXZpZXJhbW9zIHF1ZSBpbnZlcnRpciBlbiB1bmEgc3ViY2F0ZWdvcsOtYSwgZWxlZ2lyaWFtb3MgU2tpbiBDYXJlLgoKRGUgYWN1ZXJkbyBjb24gZWwgbW9kZWxvIGRlIGVmZWN0b3MgYWxlYXRvcmlvcywgU2tpbiBDYXJlIHByZXNlbnRhIGxhIG1heW9yIHByZWRpY2Npw7NuIHBhcmEgMjAyNiwgY29uIHVuIHZhbG9yIGVzdGltYWRvIGRlIDguNjUsIGZyZW50ZSBhIDguMDkgZW4gMjAyNS4gRXN0byByZXByZXNlbnRhIHVuIGNyZWNpbWllbnRvIGFwcm94aW1hZG8gZGUgNi45NyUsIGlndWFsIHF1ZSBlbCByZXN0byBkZSBsYXMgY2F0ZWdvcsOtYXMgZGViaWRvIGEgbGEgZXN0cnVjdHVyYSBkZWwgbW9kZWxvLCBwZXJvIFNraW4gQ2FyZSBwYXJ0ZSBkZWwgbml2ZWwgZGUgdmVudGFzIHByb3llY3RhZG8gbcOhcyBhbHRvLiBQb3IgbG8gdGFudG8sIGF1bnF1ZSBlbCBwb3JjZW50YWplIGRlIGNyZWNpbWllbnRvIHNlYSBzaW1pbGFyLCBlbCBpbmNyZW1lbnRvIGFic29sdXRvIGVzcGVyYWRvIGVzIGVsIG1heW9yLCBkZSBhcHJveGltYWRhbWVudGUgMC41NiB1bmlkYWRlcywgbG8gcXVlIHJlcHJlc2VudGEgdW4gbWF5b3IgcG90ZW5jaWFsIGRlIGdlbmVyYWNpw7NuIGRlIHZhbG9yLgoKRXN0YSBlbGVjY2nDs24gdGFtYmnDqW4gZXN0w6EgcmVzcGFsZGFkYSBwb3IgbGEgc2l0dWFjacOzbiBhY3R1YWwgZGUgbGEgaW5kdXN0cmlhLiBNY0tpbnNleSBzZcOxYWxhIHF1ZSBTa2luIENhcmUgcmVwcmVzZW50YSBhcHJveGltYWRhbWVudGUgNDAlIGRlbCB2YWxvciBkZWwgbWVyY2FkbyBkZSBiZWxsZXphLCB5IHNlIGVzcGVyYSBxdWUgZWwgc2VjdG9yIGRlIGJlbGxlemEgY29udGluw7plIGNyZWNpZW5kbyBhbHJlZGVkb3IgZGUgNSUgYW51YWwgaGFzdGEgMjAzMC4gQWRlbcOhcywgbG9zIGNvbnN1bWlkb3JlcyBtdWVzdHJhbiB1bmEgbWF5b3IgZGlzcG9zaWNpw7NuIGEgZ2FzdGFyIGVuIHByb2R1Y3RvcyBkZSBjdWlkYWRvIGRlIGxhIHBpZWwgcXVlIG9mcmVjZW4gYmVuZWZpY2lvcyBjbGFyb3MgeSByZXN1bHRhZG9zIHZpc2libGVzLgoKTGEgdGVuZGVuY2lhIHRhbWJpw6luIGVzIHJlbGV2YW50ZSBlbiBNw6l4aWNvOiBFdXJvbW9uaXRvciBpZGVudGlmaWNhIHF1ZSBlbCBjdWlkYWRvIGZhY2lhbCBtYW50aWVuZSBzdSBsaWRlcmF6Z28gbWllbnRyYXMgbG9zIGNvbnN1bWlkb3JlcyBhZG9wdGFuIHJ1dGluYXMgY2FkYSB2ZXogbcOhcyBlbmZvY2FkYXMgZW4gZWwgY3VpZGFkbyBkZSBsYSBwaWVsLCBhZGVtw6FzIGRlIG9ic2VydmFyIG1heW9yIGludGVyw6lzIHBvciBwcm9kdWN0b3MgY29uIGbDs3JtdWxhcyBmdW5jaW9uYWxlcyB5IHJlc3BhbGRvIGNpZW50w61maWNvLgoKUG9yIGxvIHRhbnRvLCBTa2luIENhcmUgcmVwcmVzZW50YSBsYSBhbHRlcm5hdGl2YSBkZSBpbnZlcnNpw7NuIG3DoXMgYXRyYWN0aXZhLCB5YSBxdWUgY29tYmluYSBlbCBtZWpvciBuaXZlbCBkZSB2ZW50YXMgcHJveWVjdGFkbyBlbiBudWVzdHJvIG1vZGVsbyBjb24gdW5hIGNhdGVnb3LDrWEgcXVlIGFjdHVhbG1lbnRlIHRpZW5lIHVuYSBwb3NpY2nDs24gc8OzbGlkYSB5IHBlcnNwZWN0aXZhcyBmYXZvcmFibGVzIGRlbnRybyBkZSBsYSBpbmR1c3RyaWEgZGUgYmVsbGV6YS4gTGEgaW52ZXJzacOzbiBwb2Ryw61hIGVuZm9jYXJzZSBlc3BlY2lhbG1lbnRlIGVuIHByb2R1Y3RvcyBkaWZlcmVuY2lhZG9zLCBjb24gaW5ncmVkaWVudGVzIGFjdGl2b3MsIGJlbmVmaWNpb3MgY29tcHJvYmFibGVzIHkgZXN0cmF0ZWdpYXMgZGUgcGVyc29uYWxpemFjacOzbiwgYXByb3ZlY2hhbmRvIGxhIHRlbmRlbmNpYSBoYWNpYSBydXRpbmFzIGRlIGN1aWRhZG8gbcOhcyBlc3BlY2lhbGl6YWRhcy4KCkVuIGNvbmNsdXNpw7NuLCBpbnZlcnRpcmlhbW9zIGVuIFNraW4gQ2FyZSBwb3JxdWUgbm8gc29sbyBwcmVzZW50YSBsYSBtYXlvciBwcmVkaWNjacOzbiBkZSB2ZW50YXMgcGFyYSAyMDI2IHkgZWwgbWF5b3IgaW5jcmVtZW50byBhYnNvbHV0byBlc3RpbWFkbyBkZW50cm8gZGUgbnVlc3RyYSBiYXNlLCBzaW5vIHF1ZSBhZGVtw6FzIGNvaW5jaWRlIGNvbiB1bmEgdGVuZGVuY2lhIHJlYWwgZGVsIG1lcmNhZG8sIGRvbmRlIGVsIGN1aWRhZG8gZGUgbGEgcGllbCBjb250aW7DumEgc2llbmRvIHVubyBkZSBsb3MgcHJpbmNpcGFsZXMgbW90b3JlcyBkZSBjcmVjaW1pZW50byBkZSBsYSBpbmR1c3RyaWEgZGUgYmVsbGV6YS4KCiMgRWplcmNpY2lvIDMgLSBCQU5DTyBNVU5ESUFMCklOU1RSVUNDSU9ORVM6IEltcG9ydGEgZGF0b3MgZGVsIGJhbmNvIG11bmRpYWwgeSBnZW5lcmEgZWwgbWVqb3IgbW9kZWxvLCBpbmNsdXllbmRvIHByZWRpY2Npb25lcy4gSW5jbHV5ZSBjb25jbHVzaW9uZXMgeSBncsOhZmljYXMuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojaW5zdGFsbC5wYWNrYWdlcygianNvbmxpdGUiLCByZXBvcyA9ICJodHRwczovL2Nsb3VkLnItcHJvamVjdC5vcmciKQojaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiLCByZXBvcyA9ICJodHRwczovL2Nsb3VkLnItcHJvamVjdC5vcmciKQojaW5zdGFsbC5wYWNrYWdlcygicGxtIiwgcmVwb3MgPSAiaHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnIikKI2luc3RhbGwucGFja2FnZXMoImdncGxvdDIiLCByZXBvcyA9ICJodHRwczovL2Nsb3VkLnItcHJvamVjdC5vcmciKQoKbGlicmFyeShqc29ubGl0ZSkKbGlicmFyeShkcGx5cikKbGlicmFyeShwbG0pCmxpYnJhcnkoZ2dwbG90MikKYGBgCgoKCmBgYHtyfQojIEltcG9ydGFyIGRhdG9zIGRlbCBiYW5jbyBtdW5kaWFsCgpvYnRlbmVyX1dCIDwtIGZ1bmN0aW9uKGluZGljYWRvciwgbm9tYnJlKSB7CiAgCiAgdXJsIDwtIHBhc3RlMCgKICAgICJodHRwczovL2FwaS53b3JsZGJhbmsub3JnL3YyL2NvdW50cnkvTUVYO1VTQTtDQU47QlJBL2luZGljYXRvci8iLAogICAgaW5kaWNhZG9yLAogICAgIj9mb3JtYXQ9anNvbiZwZXJfcGFnZT0xMDAwIgogICkKICAKICBkYXRvcyA8LSBmcm9tSlNPTih1cmwsIGZsYXR0ZW4gPSBUUlVFKQogIAogIGRhdG9zW1syXV0gJT4lCiAgICBzZWxlY3QoCiAgICAgIGNvdW50cnkudmFsdWUsCiAgICAgIGNvdW50cnlpc28zY29kZSwKICAgICAgZGF0ZSwKICAgICAgdmFsdWUKICAgICkgJT4lCiAgICByZW5hbWUoCiAgICAgIGNvdW50cnkgPSBjb3VudHJ5LnZhbHVlLAogICAgICBpc28zYyA9IGNvdW50cnlpc28zY29kZSwKICAgICAgeWVhciA9IGRhdGUsCiAgICAgICEhbm9tYnJlIDo9IHZhbHVlCiAgICApICU+JQogICAgbXV0YXRlKHllYXIgPSBhcy5udW1lcmljKHllYXIpKQp9CgpgYGAKCmBgYHtyfQojIEltcG9ydGFyIGxvcyBJbmlkY2Fkb3JlcwoKUElCIDwtIG9idGVuZXJfV0IoCiAgIk5ZLkdEUC5QQ0FQLkNEIiwKICAiUElCX3BjIgopCgpEZXNlbXBsZW8gPC0gb2J0ZW5lcl9XQigKICAiU0wuVUVNLlRPVEwuWlMiLAogICJEZXNlbXBsZW8iCikKCklFRCA8LSBvYnRlbmVyX1dCKAogICJCWC5LTFQuRElOVi5DRC5XRCIsCiAgIklFRCIKKQoKRXhwb3J0YWNpb25lcyA8LSBvYnRlbmVyX1dCKAogICJORS5FWFAuR05GUy5DRCIsCiAgIkV4cG9ydGFjaW9uZXMiCikKCkVzcGVyYW56YSA8LSBvYnRlbmVyX1dCKAogICJTUC5EWU4uTEUwMC5JTiIsCiAgIkVzcGVyYW56YV92aWRhIgopCmBgYAoKYGBge3J9CmRmIDwtIFBJQiAlPiUKICBzZWxlY3QoY291bnRyeSwgaXNvM2MsIHllYXIsIFBJQl9wYykgJT4lCiAgbGVmdF9qb2luKAogICAgRGVzZW1wbGVvICU+JSBzZWxlY3QoaXNvM2MsIHllYXIsIERlc2VtcGxlbyksCiAgICBieSA9IGMoImlzbzNjIiwgInllYXIiKQogICkgJT4lCiAgbGVmdF9qb2luKAogICAgSUVEICU+JSBzZWxlY3QoaXNvM2MsIHllYXIsIElFRCksCiAgICBieSA9IGMoImlzbzNjIiwgInllYXIiKQogICkgJT4lCiAgbGVmdF9qb2luKAogICAgRXhwb3J0YWNpb25lcyAlPiUgc2VsZWN0KGlzbzNjLCB5ZWFyLCBFeHBvcnRhY2lvbmVzKSwKICAgIGJ5ID0gYygiaXNvM2MiLCAieWVhciIpCiAgKSAlPiUKICBsZWZ0X2pvaW4oCiAgICBFc3BlcmFuemEgJT4lIHNlbGVjdChpc28zYywgeWVhciwgRXNwZXJhbnphX3ZpZGEpLAogICAgYnkgPSBjKCJpc28zYyIsICJ5ZWFyIikKICApICU+JQogIGZpbHRlcih5ZWFyID49IDIwMTAgJiB5ZWFyIDw9IDIwMjQpCmBgYAoKYGBge3J9CmhlYWQoZGYpCnN1bW1hcnkoZGYpCmNvbFN1bXMoaXMubmEoZGYpKQpgYGAKYGBge3J9CmRmX3BhbmVsIDwtIHBkYXRhLmZyYW1lKAogIGRmLAogIGluZGV4ID0gYygiY291bnRyeSIsICJ5ZWFyIikKKQoKaGVhZChkZl9wYW5lbCkKYGBgCmBgYHtyfQpwZGltKGRmX3BhbmVsKQpgYGAKYGBge3J9CmdncGxvdChkZiwgYWVzKHggPSB5ZWFyLCB5ID0gUElCX3BjLCBjb2xvciA9IGNvdW50cnkpKSArCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJQSUIgcGVyIGPDoXBpdGEgcG9yIHBhw61zIiwKICAgIHggPSAiQcOxbyIsCiAgICB5ID0gIlBJQiBwZXIgY8OhcGl0YSAoVVNEKSIsCiAgICBjb2xvciA9ICJQYcOtcyIKICApICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdChkZiwgYWVzKHggPSBEZXNlbXBsZW8sIHkgPSBQSUJfcGMsIGNvbG9yID0gY291bnRyeSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgZGVzZW1wbGVvIHkgUElCIHBlciBjw6FwaXRhIiwKICAgIHggPSAiRGVzZW1wbGVvICglKSIsCiAgICB5ID0gIlBJQiBwZXIgY8OhcGl0YSAoVVNEKSIKICApICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCmBgYHtyfQpnZ3Bsb3QoZGYsIGFlcyh4ID0gSUVELCB5ID0gUElCX3BjLCBjb2xvciA9IGNvdW50cnkpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgaW52ZXJzacOzbiBleHRyYW5qZXJhIHkgUElCIHBlciBjw6FwaXRhIiwKICAgIHggPSAiSW52ZXJzacOzbiBleHRyYW5qZXJhIGRpcmVjdGEgKFVTRCkiLAogICAgeSA9ICJQSUIgcGVyIGPDoXBpdGEgKFVTRCkiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYApgYGB7cn0KbW9kZWxvX3Bvb2xlZCA8LSBwbG0oCiAgUElCX3BjIH4gRGVzZW1wbGVvICsgRXNwZXJhbnphX3ZpZGEsCiAgZGF0YSA9IGRmX3BhbmVsLAogIG1vZGVsID0gInBvb2xpbmciCikKCnN1bW1hcnkobW9kZWxvX3Bvb2xlZCkKYGBgCmBgYHtyfQptb2RlbG9fZml4ZWQgPC0gcGxtKAogIFBJQl9wYyB+IERlc2VtcGxlbyArIEVzcGVyYW56YV92aWRhLAogIGRhdGEgPSBkZl9wYW5lbCwKICBtb2RlbCA9ICJ3aXRoaW4iCikKCnN1bW1hcnkobW9kZWxvX2ZpeGVkKQpgYGAKYGBge3J9Cm1vZGVsb19yYW5kb20gPC0gcGxtKAogIFBJQl9wYyB+IERlc2VtcGxlbyArIEVzcGVyYW56YV92aWRhLAogIGRhdGEgPSBkZl9wYW5lbCwKICBtb2RlbCA9ICJyYW5kb20iCikKCnN1bW1hcnkobW9kZWxvX3JhbmRvbSkKYGBgCmBgYHtyfQpwRnRlc3QobW9kZWxvX2ZpeGVkLCBtb2RlbG9fcG9vbGVkKQpgYGAKYGBge3J9CnBodGVzdChtb2RlbG9fcmFuZG9tLCBtb2RlbG9fZml4ZWQpCmBgYApDT05DTFVTScOTTiBNRUpPUiBNT0RFTE86IApBIOKAkyBBZmlybWFjacOzbjoKRWwgbW9kZWxvIGRlIEVmZWN0b3MgRmlqb3MgZnVlIGVsIG1vZGVsbyBnYW5hZG9yIHBhcmEgYW5hbGl6YXIgeSBwcmVkZWNpciBlbCBQSUIgcGVyIGPDoXBpdGEgZGUgbG9zIHBhw61zZXMgc2VsZWNjaW9uYWRvcywgeWEgcXVlIHBlcm1pdGUgdG9tYXIgZW4gY3VlbnRhIGxhcyBjYXJhY3RlcsOtc3RpY2FzIHBhcnRpY3VsYXJlcyBkZSBjYWRhIGVjb25vbcOtYSB5IGVudGVuZGVyIGPDs21vIGxvcyBjYW1iaW9zIGVuIHZhcmlhYmxlcyBjb21vIGVsIGRlc2VtcGxlbyBwdWVkZW4gaW1wYWN0YXIgc3UgZGVzZW1wZcOxbyBlY29uw7NtaWNvLgoKUiDigJMgUmF6w7NuOgpQYXJhIHVuYSBlbXByZXNhLCBpbnZlcnNpb25pc3RhIG8gZ29iaWVybm8sIG5vIHNlcsOtYSBhZGVjdWFkbyBhbmFsaXphciBhIHRvZG9zIGxvcyBwYcOtc2VzIGNvbW8gc2kgZnVlcmFuIGlndWFsZXMuIENhZGEgZWNvbm9tw61hIHRpZW5lIGNvbmRpY2lvbmVzIGVzdHJ1Y3R1cmFsZXMgZGlmZXJlbnRlcyBxdWUgaW5mbHV5ZW4gZW4gc3VzIHJlc3VsdGFkb3MuIEVsIG1vZGVsbyBkZSBFZmVjdG9zIEZpam9zIHBlcm1pdGUgY29uc2lkZXJhciBlc3RhcyBkaWZlcmVuY2lhcyB5IGVuZm9jYXJzZSBlbiBjw7NtbyBsb3MgY2FtYmlvcyBkZW50cm8gZGUgY2FkYSBwYcOtcyBzZSByZWxhY2lvbmFuIGNvbiBzdSBQSUIgcGVyIGPDoXBpdGEuIEVzdG8gaGFjZSBxdWUgZWwgYW7DoWxpc2lzIHNlYSBtw6FzIMO6dGlsIHBhcmEgaWRlbnRpZmljYXIgc2XDsWFsZXMgZWNvbsOzbWljYXMgeSBhcG95YXIgbGEgdG9tYSBkZSBkZWNpc2lvbmVzLgoKRSDigJMgRXZpZGVuY2lhOgpMYXMgcHJ1ZWJhcyBlc3RhZMOtc3RpY2FzIHJlc3BhbGRhcm9uIGVzdGEgZWxlY2Npw7NuOiBsYSBwcnVlYmEgRiBkZXNjYXJ0w7MgZWwgbW9kZWxvIFBvb2xlZCB5IGxhIHBydWViYSBkZSBIYXVzbWFuIGRlc2NhcnTDsyBsb3MgRWZlY3RvcyBBbGVhdG9yaW9zLCBwb3IgbG8gcXVlIGxvcyBFZmVjdG9zIEZpam9zIGZ1ZXJvbiBsYSBhbHRlcm5hdGl2YSBtw6FzIGFkZWN1YWRhLiBBZGVtw6FzLCBlbCBtb2RlbG8gbW9zdHLDsyBxdWUgZWwgZGVzZW1wbGVvIHRpZW5lIHVuYSByZWxhY2nDs24gbmVnYXRpdmEgY29uIGVsIFBJQiBwZXIgY8OhcGl0YSwgbG8gcXVlIHJlZnVlcnphIGxhIGltcG9ydGFuY2lhIGRlIG1hbnRlbmVyIG5pdmVsZXMgc2FsdWRhYmxlcyBkZSBlbXBsZW8gcGFyYSBmYXZvcmVjZXIgZWwgZGVzZW1wZcOxbyBlY29uw7NtaWNvLgoKYGBge3J9Cm1vZGVsb19maW5hbCA8LSBwbG0oCiAgUElCX3BjIH4gRGVzZW1wbGVvICsgRXNwZXJhbnphX3ZpZGEsCiAgZGF0YSA9IGRmX3BhbmVsLAogIG1vZGVsID0gIndpdGhpbiIKKQoKc3VtbWFyeShtb2RlbG9fZmluYWwpCmBgYAoKYGBge3J9CmRmX3RyYWluIDwtIHN1YnNldChkZiwgeWVhciA8PSAyMDIzKQpkZl90ZXN0IDwtIHN1YnNldChkZiwgeWVhciA9PSAyMDI0KQpgYGAKCmBgYHtyfQpkZl90cmFpbl9wYW5lbCA8LSBwZGF0YS5mcmFtZSgKICBkZl90cmFpbiwKICBpbmRleCA9IGMoImNvdW50cnkiLCAieWVhciIpCikKYGBgCgpgYGB7cn0KbW9kZWxvX2ZpbmFsIDwtIHBsbSgKICBQSUJfcGMgfiBEZXNlbXBsZW8gKyBFc3BlcmFuemFfdmlkYSwKICBkYXRhID0gZGZfdHJhaW5fcGFuZWwsCiAgbW9kZWwgPSAid2l0aGluIgopCgpzdW1tYXJ5KG1vZGVsb19maW5hbCkKYGBgCmBgYHtyfQpkZl90ZXN0X3BhbmVsIDwtIHBkYXRhLmZyYW1lKAogIGRmX3Rlc3QsCiAgaW5kZXggPSBjKCJjb3VudHJ5IiwgInllYXIiKQopCmBgYAoKYGBge3J9CmRmX3Rlc3QkUElCX3ByZWRpY2hvIDwtIHByZWRpY3QoCiAgbW9kZWxvX2ZpbmFsLAogIG5ld2RhdGEgPSBkZl90ZXN0X3BhbmVsCikKCmRmX3Rlc3RbLCBjKAogICJjb3VudHJ5IiwKICAieWVhciIsCiAgIlBJQl9wYyIsCiAgIlBJQl9wcmVkaWNobyIKKV0KYGBgCmBgYHtyfQpkZl90ZXN0JEVycm9yIDwtIGRmX3Rlc3QkUElCX3BjIC0gZGZfdGVzdCRQSUJfcHJlZGljaG8KCmRmX3Rlc3QkRXJyb3JfUG9yY2VudHVhbCA8LSAKICBhYnMoZGZfdGVzdCRFcnJvciAvIGRmX3Rlc3QkUElCX3BjKSAqIDEwMAoKZGZfdGVzdFssIGMoCiAgImNvdW50cnkiLAogICJQSUJfcGMiLAogICJQSUJfcHJlZGljaG8iLAogICJFcnJvciIsCiAgIkVycm9yX1BvcmNlbnR1YWwiCildCmBgYApgYGB7cn0KZGZfY29tcGFyYWNpb24gPC0gcmJpbmQoCiAgZGF0YS5mcmFtZSgKICAgIGNvdW50cnkgPSBkZl90ZXN0JGNvdW50cnksCiAgICBQSUIgPSBkZl90ZXN0JFBJQl9wYywKICAgIFRpcG8gPSAiUmVhbCIKICApLAogIGRhdGEuZnJhbWUoCiAgICBjb3VudHJ5ID0gZGZfdGVzdCRjb3VudHJ5LAogICAgUElCID0gZGZfdGVzdCRQSUJfcHJlZGljaG8sCiAgICBUaXBvID0gIlByZWRpY2hvIgogICkKKQoKZ2dwbG90KAogIGRmX2NvbXBhcmFjaW9uLAogIGFlcyh4ID0gY291bnRyeSwgeSA9IFBJQiwgZmlsbCA9IFRpcG8pCikgKwogIGdlb21fY29sKAogICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksCiAgICB3aWR0aCA9IDAuNwogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJQSUIgcGVyIGPDoXBpdGEgcmVhbCB2cy4gcHJlZGljaG8gcGFyYSAyMDI0IiwKICAgIHggPSAiUGHDrXMiLAogICAgeSA9ICJQSUIgcGVyIGPDoXBpdGEgKFVTRCkiLAogICAgZmlsbCA9ICJWYWxvciIKICApICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCmBgYHtyfQpnZ3Bsb3QoZGYsIGFlcyh4ID0geWVhciwgeSA9IFBJQl9wYywgY29sb3IgPSBjb3VudHJ5KSkgKwogIGdlb21fbGluZShsaW5ld2lkdGggPSAxKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRXZvbHVjacOzbiBkZWwgUElCIHBlciBjw6FwaXRhLCAyMDEw4oCTMjAyNCIsCiAgICB4ID0gIkHDsW8iLAogICAgeSA9ICJQSUIgcGVyIGPDoXBpdGEgKFVTRCkiLAogICAgY29sb3IgPSAiUGHDrXMiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYApgYGB7cn0KZGZfdGVzdFssIGMoCiAgImNvdW50cnkiLAogICJQSUJfcGMiLAogICJQSUJfcHJlZGljaG8iLAogICJFcnJvcl9Qb3JjZW50dWFsIgopXQpgYGAKYGBge3J9CnN1bW1hcnkobW9kZWxvX2ZpbmFsKQpgYGAKUFJFRElDQ0nDk04gOiDCv0N1w6FsIHNlcsOtYSBlbCBQSUIgcGVyIGPDoXBpdGEgZXNwZXJhZG8gcGFyYSBjYWRhIHBhw61zIGVuIDIwMjQsIGNvbnNpZGVyYW5kbyBzdSBuaXZlbCBkZSBkZXNlbXBsZW8geSBlc3BlcmFuemEgZGUgdmlkYT8KCkNPTkNMVVNJw5NOOiAKCkEg4oCTIEFmaXJtYWNpw7NuOgpFbCBtb2RlbG8gZGUgRWZlY3RvcyBGaWpvcyBwZXJtaXRpw7MgZXN0aW1hciBlbCBQSUIgcGVyIGPDoXBpdGEgZGUgMjAyNCBwYXJhIGxvcyBjdWF0cm8gcGHDrXNlcyBhbmFsaXphZG9zIHksIGF1bnF1ZSBsYXMgcHJlZGljY2lvbmVzIG5vIGZ1ZXJvbiBleGFjdGFzIGVuIHRvZG9zIGxvcyBjYXNvcywgc8OtIHBlcm1pdGllcm9uIGlkZW50aWZpY2FyIGRpZmVyZW5jaWFzIGltcG9ydGFudGVzIGVudHJlIGxvcyBtZXJjYWRvcyB5IGV2YWx1YXIgcXXDqSB0YW4gYmllbiBlbCBtb2RlbG8gbG9ncmEgcmVwcmVzZW50YXIgc3UgY29tcG9ydGFtaWVudG8gZWNvbsOzbWljby4KClIg4oCTIFJhesOzbjoKTGFzIHByZWRpY2Npb25lcyBwZXJtaXRlbiBjb21wYXJhciBlbCB2YWxvciBxdWUgZWwgbW9kZWxvIGVzcGVyYWJhIG9idGVuZXIgY29uIGVsIHZhbG9yIHF1ZSByZWFsbWVudGUgc2Ugb2JzZXJ2w7MgZW4gMjAyNC4gRXN0YSBjb21wYXJhY2nDs24gZXMgw7p0aWwgcG9ycXVlIG5vIHNvbG8gbm9zIGluZGljYSBxdcOpIHRhbiBwcmVjaXNvIGVzIGVsIG1vZGVsbywgc2lubyBxdWUgdGFtYmnDqW4gcGVybWl0ZSBpZGVudGlmaWNhciBtZXJjYWRvcyBkb25kZSBleGlzdGVuIGZhY3RvcmVzIGVjb27Ds21pY29zIGFkaWNpb25hbGVzIHF1ZSBlbCBtb2RlbG8gbm8gZXN0w6EgY2FwdHVyYW5kby4gRGVzZGUgdW5hIHBlcnNwZWN0aXZhIGVtcHJlc2FyaWFsLCBlc3RhcyBkaWZlcmVuY2lhcyBzb24gcmVsZXZhbnRlcyBwb3JxdWUgbXVlc3RyYW4gcXVlIGxhcyBjb25kaWNpb25lcyBkZSBjYWRhIG1lcmNhZG8gcHVlZGVuIHJlcXVlcmlyIHVuIGFuw6FsaXNpcyBtw6FzIHByb2Z1bmRvIGFudGVzIGRlIHRvbWFyIGRlY2lzaW9uZXMgZGUgaW52ZXJzacOzbiBvIGV4cGFuc2nDs24uCgpFIOKAkyBFdmlkZW5jaWE6ClBhcmEgMjAyNCwgZWwgbW9kZWxvIHByb25vc3RpY8OzIHVuIFBJQiBwZXIgY8OhcGl0YSBkZSAkMTMsODg0Ljc5IFVTRCBwYXJhIEJyYXNpbCwgZnJlbnRlIGEgdW4gdmFsb3IgcmVhbCBkZSAkMTAsMzEwLjU1IFVTRCwgZ2VuZXJhbmRvIHVuIGVycm9yIGRlIDM0LjY3JS4gUGFyYSBDYW5hZMOhLCBsYSBwcmVkaWNjacOzbiBmdWUgZGUgJDQ5LDU4MS43MCBVU0QgZnJlbnRlIGEgJDU1LDAxNS43MSBVU0QgcmVhbGVzLCBjb24gZWwgbWVub3IgZXJyb3IgZGUgbGEgbXVlc3RyYSAoOS44OCUpLiBFbiBNw6l4aWNvLCBlbCBtb2RlbG8gZXN0aW3DsyAkMTEsMDkwLjg3IFVTRCBmcmVudGUgYSAkMTMsOTg4LjA0IFVTRCByZWFsZXMsIGNvbiB1biBlcnJvciBkZSAyMC43MSUsIG1pZW50cmFzIHF1ZSBwYXJhIEVzdGFkb3MgVW5pZG9zIGVzdGltw7MgJDYzLDc2NS43MyBVU0QgZnJlbnRlIGEgJDg2LDE2OS42NiBVU0QgcmVhbGVzLCBjb24gdW4gZXJyb3IgZGUgMjYuMDAlLgoKQSBwYXJ0aXIgZGUgZXN0b3MgcmVzdWx0YWRvcywgZWwgcHJpbmNpcGFsIGhhbGxhemdvIGVzIHF1ZSBDYW5hZMOhIGZ1ZSBlbCBtZXJjYWRvIGRvbmRlIGVsIG1vZGVsbyB0dXZvIG1heW9yIHByZWNpc2nDs24sIG1pZW50cmFzIHF1ZSBCcmFzaWwgcHJlc2VudMOzIGxhIG1heW9yIGRpZmVyZW5jaWEgZW50cmUgbG8gZXNwZXJhZG8geSBsbyBvYnNlcnZhZG8uIFRhbWJpw6luIHNlIG9ic2VydmEgcXVlIGVsIG1vZGVsbyB0ZW5kacOzIGEgc3ViZXN0aW1hciBlbCBQSUIgcGVyIGPDoXBpdGEgZGUgQ2FuYWTDoSwgTcOpeGljbyB5IEVzdGFkb3MgVW5pZG9zLCBtaWVudHJhcyBxdWUgc29icmVlc3RpbcOzIGVsIGRlIEJyYXNpbC4gRXN0byBpbmRpY2EgcXVlIGV4aXN0ZW4gY2FyYWN0ZXLDrXN0aWNhcyBlY29uw7NtaWNhcyBwYXJ0aWN1bGFyZXMgZGUgY2FkYSBwYcOtcyBxdWUgbm8gZXN0w6FuIHNpZW5kbyBjYXB0dXJhZGFzIGNvbXBsZXRhbWVudGUgcG9yIGxhcyB2YXJpYWJsZXMgdXRpbGl6YWRhcy4KCkRlc2RlIHVuYSBwZXJzcGVjdGl2YSBlbXByZXNhcmlhbCwgZXN0byBzaWduaWZpY2EgcXVlIGVsIG1vZGVsbyBwdWVkZSBmdW5jaW9uYXIgY29tbyB1bmEgaGVycmFtaWVudGEgaW5pY2lhbCBwYXJhIGNvbXBhcmFyIG1lcmNhZG9zIHkgZGV0ZWN0YXIgdGVuZGVuY2lhcywgcGVybyBubyBkZWJlcsOtYSB1dGlsaXphcnNlIGNvbW8gw7puaWNvIGNyaXRlcmlvIHBhcmEgdG9tYXIgZGVjaXNpb25lcyBkZSBpbnZlcnNpw7NuLiBMYXMgZGlmZXJlbmNpYXMgZW50cmUgbGFzIHByZWRpY2Npb25lcyB5IGxvcyB2YWxvcmVzIHJlYWxlcyBzdWdpZXJlbiBxdWUgc2Vyw61hIGNvbnZlbmllbnRlIGluY29ycG9yYXIgdmFyaWFibGVzIGFkaWNpb25hbGVzLCBjb21vIGludmVyc2nDs24sIGV4cG9ydGFjaW9uZXMsIGluZmxhY2nDs24sIGNvbnN1bW8gbyBjcmVjaW1pZW50byBlY29uw7NtaWNvLCBwYXJhIG9idGVuZXIgdW4gYW7DoWxpc2lzIG3DoXMgY29tcGxldG8geSBtZWpvcmFyIGxhIHByZWNpc2nDs24gZGUgZnV0dXJhcyBwcmVkaWNjaW9uZXMuCg==