Ejercicio en clase_ Población

Instalar paquetes y llamar librerías

#install.packages("forecast")
library(forecast)
#install.packages("tidyverse")
library(tidyverse)
#install.packages("ggplot2")
library(ggplot2)

Importar base de datos

#file.choose()
poblacion<- read.csv("D:\\Descargas\\population.csv")

Entender un poco la base de datos

summary(poblacion)
##     state                year        population      
##  Length:6020        Min.   :1900   Min.   :   43000  
##  Class :character   1st Qu.:1930   1st Qu.:  901483  
##  Mode  :character   Median :1960   Median : 2359000  
##                     Mean   :1960   Mean   : 3726003  
##                     3rd Qu.:1990   3rd Qu.: 4541883  
##                     Max.   :2019   Max.   :39512223
str(poblacion)
## 'data.frame':    6020 obs. of  3 variables:
##  $ state     : chr  "AK" "AK" "AK" "AK" ...
##  $ year      : int  1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 ...
##  $ population: int  135000 158000 189000 205000 215000 222000 224000 231000 224000 224000 ...
head(poblacion)
##   state year population
## 1    AK 1950     135000
## 2    AK 1951     158000
## 3    AK 1952     189000
## 4    AK 1953     205000
## 5    AK 1954     215000
## 6    AK 1955     222000

Serie de tiempo TEXAS

poblacion_texas <- poblacion %>% filter(state=="TX")
ggplot(poblacion_texas, aes(x=year, y=population)) + 
  geom_line()+
  labs(title= "poblacion de Texas", x= "Año", y="Población")

ts_texas <- ts(poblacion_texas$population, start = 1950, frequency=1) 
#SERIE DE TIEMPO ANUAL (CADA AÑO TENEMOS UN REGISTRO DE LA POBLACIÓN)

#TS_TEXAS <- ts(poblacion_texas$population, start = C(1900, 4), frequency=4) 
#SERIE DE TIEMPO TRIMESRTAL COMENZANDO EN EL TRIMESTRE 4 (OCT-NOV-DIC)

arima_texas <- auto.arima(ts_texas)
summary(arima_texas)
## Series: ts_texas 
## ARIMA(0,2,2) 
## 
## Coefficients:
##           ma1      ma2
##       -0.5950  -0.1798
## s.e.   0.0913   0.0951
## 
## sigma^2 = 1.031e+10:  log likelihood = -1527.14
## AIC=3060.28   AICc=3060.5   BIC=3068.6
## 
## Training set error measures:
##                    ME     RMSE      MAE       MPE      MAPE      MASE
## Training set 12147.62 99818.31 59257.39 0.1046163 0.5686743 0.2672197
##                     ACF1
## Training set -0.02136734
pronostico_texas <- forecast(arima_texas , level=95, h=10)
plot(pronostico_texas, main="Población en Texas")

Actividad Crear un Mapa

Crear un mapa de EUA por década, con un gradiente verde-rojo de la población por estado, desde 1950 hasta 2050

Instalar y cargar las librerías necesarias para análisis y visualización

# install.packages(c("dplyr", "ggplot2", "forecast", "maps"))
library(dplyr)
library(ggplot2)
library(forecast)
library(maps)

Importar la base de datos de población

poblacion <- read.csv("D:\\Descargas\\population.csv")

Proyectar la población estatal hasta 2050 y combinar con datos originales

# Integración de pronósticos con la base de datos inicial
# Crear un dataset ampliado que parte de la base de datos original
poblacion_extendida <- poblacion

# Extraer la lista de estados únicos presentes en los datos
estados <- unique(poblacion$state)
# Modelar y pronosticar la población de cada estado hasta el año 2050
for(st in estados){
  
  # Filtrar y organizar los datos por año para cada estado
  datos_st <- poblacion %>%
    filter(state == st) %>%
    arrange(year)
  
  # Identificar el último año disponible en la serie histórica
  ultimo_anio <- max(datos_st$year)
  
  # Generar la serie de tiempo anual para la población del estado
  ts_st <- ts(datos_st$population,
              start = min(datos_st$year),
              end   = ultimo_anio,
              frequency = 1)  # Datos anuales
  
  # Ajustar un modelo ARIMA de manera automática para el estado
  modelo_st <- auto.arima(ts_st)
  
  # Calcular el horizonte de pronóstico necesario
  # (se genera forecast solo si faltan años para llegar a 2050)
  h_years <- 2050 - ultimo_anio
  
  if(h_years > 0){
    # Generar el pronóstico para el periodo faltante
    pronostico <- forecast(modelo_st, h = h_years)
    
    # Crear un dataframe con las proyecciones generadas
    anios_pronostico <- (ultimo_anio + 1):2050
    poblacion_pronosticada <- as.numeric(pronostico$mean)
    
    df_forecast <- data.frame(
      state = st,
      year  = anios_pronostico,
      population = poblacion_pronosticada
    )
    
    # Incorporar las proyecciones al dataset extendido
    poblacion_extendida <- rbind(poblacion_extendida, df_forecast)
  }
}

Definir una función para visualizar el mapa de población por año

plot_map <- function(year) {
  
  # Filtrar el dataset para el año especificado
  data_year <- poblacion_extendida %>%
    filter(year == !!year)
  
  # Cargar la información geográfica de los estados de EE.UU.
  states_map <- map_data("state")
  
  # Relacionar las abreviaturas estatales con los nombres completos en minúsculas
  # Utilizando los vectores auxiliares state.abb y state.name
  data_year <- data_year %>%
    mutate(region = tolower(state.name[match(state, state.abb)])) %>%
    right_join(states_map, by = "region")
  
  # Generar el mapa temático por población
  ggplot(data_year, aes(x = long, y = lat, group = group, fill = population)) +
    geom_polygon(color = "black") +
    # Aplicar un gradiente de color verde (bajo) a rojo (alto)
    scale_fill_gradient(
      low = "green",   # Representa la menor población
      high = "red",    # Indica la mayor población
      name = "Población"
    ) +
    labs(
      title = paste("Población por Estado en", year)
    ) +
    theme_void() +
    theme(
      legend.position = "right",
      plot.title = element_text(size = 16, face = "bold")
    )
}

Visualizar la evolución demográfica cada década (1950 - 2050)

for(year in seq(1950, 2050, by = 10)) {
  print(plot_map(year))
}

Actividad 2. Leche saborizada Hershey’s

## Instalar paquetes y llamar librerías

#install.packages("forecast")
library(forecast)
#install.packages("tidyverse")
library(tidyverse)
#install.packages("ggplot2")
library(ggplot2)

Importar la base de datos

ventas <- read.csv("C:\\Users\\LuisD\\Documents\\OCTAVO SEMESTRE\\Generación de escenarios\\Módulo 1\\Ventas_Históricas_Lechitas.csv")
#file.choose()

1. Modelo AUTO.ARIMA

ts_ventas <- ts(ventas$Ventas, start = c(2017, 1), frequency = 12)
autoplot(ts_ventas) + labs(title= "Ventas de Leche Saborizada Hershey's", x="Tiempo", y="Miles de Dólares")

arima_ventas <- auto.arima(ts_ventas)
summary(arima_ventas)
## Series: ts_ventas 
## ARIMA(1,0,0)(1,1,0)[12] with drift 
## 
## Coefficients:
##          ar1     sar1     drift
##       0.6383  -0.5517  288.8980
## s.e.  0.1551   0.2047   14.5026
## 
## sigma^2 = 202700:  log likelihood = -181.5
## AIC=371   AICc=373.11   BIC=375.72
## 
## Training set error measures:
##                    ME    RMSE      MAE        MPE      MAPE       MASE
## Training set 25.22163 343.863 227.1699 0.08059942 0.7069541 0.06491041
##                   ACF1
## Training set 0.2081043
pronostico_ventas <- forecast(arima_ventas, level=95, h=12)
pronostico_ventas
##          Point Forecast    Lo 95    Hi 95
## Jan 2020       35498.90 34616.48 36381.32
## Feb 2020       34202.17 33155.29 35249.05
## Mar 2020       36703.01 35596.10 37809.92
## Apr 2020       36271.90 35141.44 37402.36
## May 2020       37121.98 35982.07 38261.90
## Jun 2020       37102.65 35958.91 38246.40
## Jul 2020       37151.04 36005.74 38296.35
## Aug 2020       38564.65 37418.71 39710.59
## Sep 2020       38755.23 37609.03 39901.42
## Oct 2020       39779.03 38632.73 40925.33
## Nov 2020       38741.63 37595.29 39887.97
## Dec 2020       38645.86 37499.50 39792.22
autoplot(pronostico_ventas)+ labs(title="Pronóstico de ventas 2020 de Leche Saborizada Hershey's", x="Tiempo", y="Niles de Dólares")

2. Modelo de Regresión Lineal

ventas$mes <- 1:36
regresion_ventas <- lm(Ventas ~ mes, data=ventas )
summary(regresion_ventas)
## 
## Call:
## lm(formula = Ventas ~ mes, data = ventas)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2075.79  -326.41    33.74   458.41  1537.04 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 24894.67     275.03   90.52   <2e-16 ***
## mes           298.37      12.96   23.02   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 808 on 34 degrees of freedom
## Multiple R-squared:  0.9397, Adjusted R-squared:  0.9379 
## F-statistic: 529.8 on 1 and 34 DF,  p-value: < 2.2e-16
siguiente_año <- data.frame(mes = 37:48)
prediccion_regresion <- predict(regresion_ventas, siguiente_año)
prediccion_regresion
##        1        2        3        4        5        6        7        8 
## 35934.49 36232.86 36531.23 36829.61 37127.98 37426.35 37724.73 38023.10 
##        9       10       11       12 
## 38321.47 38619.85 38918.22 39216.59
plot(ventas$mes, ventas$Ventas, main = "Pronóstico de Ventas 2020 de Leche Saborizada Hershey's", xlab = "Tiempo", ylab = "Miles de Dólares") + abline(regresion_ventas, col="blue") + points(prediccion_regresion, col="red")

## integer(0)
predicciones_reales<- predict(regresion_ventas, ventas)
MAPE<- mean(abs((ventas$Ventas - 
predicciones_reales)/ventas$Ventas))*100
MAPE
## [1] 2.011298

3. Conclusiones

El mejor modelo que se adapta a la serie es el SARIMA con unMAPE de 0.71%, comparado con la Regersión Lineal que su MAPE es de 2.01%.

Para el siguiente año, la proyección de ventas es la siguiente: | Mes y Año | Escenario Esperado | Escenario Pesimista | Escenario Optimista | |———–|——————–|———————|———————| |Jan 2020 | 35498.90 | 34616.48 | 36381.32 | |Feb 2020 | 34202.17 | 33155.29 | 35249.05 | |Mar 2020 | 36703.01 | 35596.10 | 37809.92 | |Apr 2020 | 36271.90 | 35141.44 | 37402.36 | |May 2020 | 37121.98 | 35982.07 | 38261.90 | |Jun 2020 | 37102.65 | 35958.91 | 38246.40 | |Jul 2020 | 37151.04 | 36005.74 | 38296.35 | |Aug 2020 | 38564.65 | 37418.71 | 39710.59 | |Sep 2020 | 38755.23 | 37609.03 | 39901.42 | |Oct 2020 | 39779.03 | 38632.73 | 40925.33 |

ventas_por_anio <- read.csv("C:\\Users\\LuisD\\Documents\\OCTAVO SEMESTRE\\Generación de escenarios\\Módulo 1\\ventas_por_anio.csv")
ggplot(ventas_por_anio, aes(x=mes, y=ventas,
                            col=as.factor(anio), group=anio)) + geom_line() + labs(title="Ventas de Leche Saborizada Hershey's por año", x="Mes", y="Miles de Dólares")

Nuestra reocmentación sería realiar campañas publicitarias para aumentar el comsumo de leche daborizada Hershey’s en el primer semestre del año

LS0tDQp0aXRsZTogIkFDVElWSURBRCAyIg0KYXV0aG9yOiAiQTAxMjc1NjU1Ig0KZGF0ZTogIjIwMjUtMDItMTciDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCiAgICB0aGVtZTogY2VydWxlYW4NCi0tLQ0KIyBFamVyY2ljaW8gZW4gY2xhc2VfIFBvYmxhY2nDs24NCg0KIVtdKEM6XFxVc2Vyc1xcTHVpc0RcXERvY3VtZW50c1xcT0NUQVZPIFNFTUVTVFJFXFxHZW5lcmFjacOzbiBkZSBlc2NlbmFyaW9zXFxNw7NkdWxvIDFcXHBvYmxhY2lvbi5qZmlmKQ0KDQojIyBJbnN0YWxhciBwYXF1ZXRlcyB5IGxsYW1hciBsaWJyZXLDrWFzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KI2luc3RhbGwucGFja2FnZXMoImZvcmVjYXN0IikNCmxpYnJhcnkoZm9yZWNhc3QpDQojaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KI2luc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KYGBgDQoNCiMjIEltcG9ydGFyIGJhc2UgZGUgZGF0b3MNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojZmlsZS5jaG9vc2UoKQ0KcG9ibGFjaW9uPC0gcmVhZC5jc3YoIkQ6XFxEZXNjYXJnYXNcXHBvcHVsYXRpb24uY3N2IikNCmBgYA0KDQojIyBFbnRlbmRlciB1biBwb2NvIGxhIGJhc2UgZGUgZGF0b3MNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpzdW1tYXJ5KHBvYmxhY2lvbikNCnN0cihwb2JsYWNpb24pDQpoZWFkKHBvYmxhY2lvbikNCmBgYA0KDQojIyBTZXJpZSBkZSB0aWVtcG8gVEVYQVMNCmBgYHtyfQ0KcG9ibGFjaW9uX3RleGFzIDwtIHBvYmxhY2lvbiAlPiUgZmlsdGVyKHN0YXRlPT0iVFgiKQ0KZ2dwbG90KHBvYmxhY2lvbl90ZXhhcywgYWVzKHg9eWVhciwgeT1wb3B1bGF0aW9uKSkgKyANCiAgZ2VvbV9saW5lKCkrDQogIGxhYnModGl0bGU9ICJwb2JsYWNpb24gZGUgVGV4YXMiLCB4PSAiQcOxbyIsIHk9IlBvYmxhY2nDs24iKQ0KDQp0c190ZXhhcyA8LSB0cyhwb2JsYWNpb25fdGV4YXMkcG9wdWxhdGlvbiwgc3RhcnQgPSAxOTUwLCBmcmVxdWVuY3k9MSkgDQojU0VSSUUgREUgVElFTVBPIEFOVUFMIChDQURBIEHDkU8gVEVORU1PUyBVTiBSRUdJU1RSTyBERSBMQSBQT0JMQUNJw5NOKQ0KDQojVFNfVEVYQVMgPC0gdHMocG9ibGFjaW9uX3RleGFzJHBvcHVsYXRpb24sIHN0YXJ0ID0gQygxOTAwLCA0KSwgZnJlcXVlbmN5PTQpIA0KI1NFUklFIERFIFRJRU1QTyBUUklNRVNSVEFMIENPTUVOWkFORE8gRU4gRUwgVFJJTUVTVFJFIDQgKE9DVC1OT1YtRElDKQ0KDQphcmltYV90ZXhhcyA8LSBhdXRvLmFyaW1hKHRzX3RleGFzKQ0Kc3VtbWFyeShhcmltYV90ZXhhcykNCg0KcHJvbm9zdGljb190ZXhhcyA8LSBmb3JlY2FzdChhcmltYV90ZXhhcyAsIGxldmVsPTk1LCBoPTEwKQ0KcGxvdChwcm9ub3N0aWNvX3RleGFzLCBtYWluPSJQb2JsYWNpw7NuIGVuIFRleGFzIikNCmBgYA0KDQoNCg0KIyBBY3RpdmlkYWQgQ3JlYXIgdW4gTWFwYSANCiFbXShDOlxcVXNlcnNcXEx1aXNEXFxEb2N1bWVudHNcXE9DVEFWTyBTRU1FU1RSRVxcR2VuZXJhY2nDs24gZGUgZXNjZW5hcmlvc1xcTcOzZHVsbyAxXFxtYXBhLmpmaWYpDQoNCkNyZWFyIHVuIG1hcGEgZGUgRVVBIHBvciBkw6ljYWRhLCBjb24gdW4gZ3JhZGllbnRlIHZlcmRlLXJvam8gZGUgbGEgcG9ibGFjacOzbiBwb3IgZXN0YWRvLCBkZXNkZSAxOTUwIGhhc3RhIDIwNTANCg0KIyMgSW5zdGFsYXIgeSBjYXJnYXIgbGFzIGxpYnJlcsOtYXMgbmVjZXNhcmlhcyBwYXJhIGFuw6FsaXNpcyB5IHZpc3VhbGl6YWNpw7NuDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKGMoImRwbHlyIiwgImdncGxvdDIiLCAiZm9yZWNhc3QiLCAibWFwcyIpKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZm9yZWNhc3QpDQpsaWJyYXJ5KG1hcHMpDQpgYGANCg0KIyMgSW1wb3J0YXIgbGEgYmFzZSBkZSBkYXRvcyBkZSBwb2JsYWNpw7NuIA0KYGBge3J9DQpwb2JsYWNpb24gPC0gcmVhZC5jc3YoIkQ6XFxEZXNjYXJnYXNcXHBvcHVsYXRpb24uY3N2IikNCmBgYA0KDQojIyBQcm95ZWN0YXIgbGEgcG9ibGFjacOzbiBlc3RhdGFsIGhhc3RhIDIwNTAgeSBjb21iaW5hciBjb24gZGF0b3Mgb3JpZ2luYWxlcw0KYGBge3J9DQojIEludGVncmFjacOzbiBkZSBwcm9uw7NzdGljb3MgY29uIGxhIGJhc2UgZGUgZGF0b3MgaW5pY2lhbA0KIyBDcmVhciB1biBkYXRhc2V0IGFtcGxpYWRvIHF1ZSBwYXJ0ZSBkZSBsYSBiYXNlIGRlIGRhdG9zIG9yaWdpbmFsDQpwb2JsYWNpb25fZXh0ZW5kaWRhIDwtIHBvYmxhY2lvbg0KDQojIEV4dHJhZXIgbGEgbGlzdGEgZGUgZXN0YWRvcyDDum5pY29zIHByZXNlbnRlcyBlbiBsb3MgZGF0b3MNCmVzdGFkb3MgPC0gdW5pcXVlKHBvYmxhY2lvbiRzdGF0ZSkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBNb2RlbGFyIHkgcHJvbm9zdGljYXIgbGEgcG9ibGFjacOzbiBkZSBjYWRhIGVzdGFkbyBoYXN0YSBlbCBhw7FvIDIwNTANCmZvcihzdCBpbiBlc3RhZG9zKXsNCiAgDQogICMgRmlsdHJhciB5IG9yZ2FuaXphciBsb3MgZGF0b3MgcG9yIGHDsW8gcGFyYSBjYWRhIGVzdGFkbw0KICBkYXRvc19zdCA8LSBwb2JsYWNpb24gJT4lDQogICAgZmlsdGVyKHN0YXRlID09IHN0KSAlPiUNCiAgICBhcnJhbmdlKHllYXIpDQogIA0KICAjIElkZW50aWZpY2FyIGVsIMO6bHRpbW8gYcOxbyBkaXNwb25pYmxlIGVuIGxhIHNlcmllIGhpc3TDs3JpY2ENCiAgdWx0aW1vX2FuaW8gPC0gbWF4KGRhdG9zX3N0JHllYXIpDQogIA0KICAjIEdlbmVyYXIgbGEgc2VyaWUgZGUgdGllbXBvIGFudWFsIHBhcmEgbGEgcG9ibGFjacOzbiBkZWwgZXN0YWRvDQogIHRzX3N0IDwtIHRzKGRhdG9zX3N0JHBvcHVsYXRpb24sDQogICAgICAgICAgICAgIHN0YXJ0ID0gbWluKGRhdG9zX3N0JHllYXIpLA0KICAgICAgICAgICAgICBlbmQgICA9IHVsdGltb19hbmlvLA0KICAgICAgICAgICAgICBmcmVxdWVuY3kgPSAxKSAgIyBEYXRvcyBhbnVhbGVzDQogIA0KICAjIEFqdXN0YXIgdW4gbW9kZWxvIEFSSU1BIGRlIG1hbmVyYSBhdXRvbcOhdGljYSBwYXJhIGVsIGVzdGFkbw0KICBtb2RlbG9fc3QgPC0gYXV0by5hcmltYSh0c19zdCkNCiAgDQogICMgQ2FsY3VsYXIgZWwgaG9yaXpvbnRlIGRlIHByb27Ds3N0aWNvIG5lY2VzYXJpbw0KICAjIChzZSBnZW5lcmEgZm9yZWNhc3Qgc29sbyBzaSBmYWx0YW4gYcOxb3MgcGFyYSBsbGVnYXIgYSAyMDUwKQ0KICBoX3llYXJzIDwtIDIwNTAgLSB1bHRpbW9fYW5pbw0KICANCiAgaWYoaF95ZWFycyA+IDApew0KICAgICMgR2VuZXJhciBlbCBwcm9uw7NzdGljbyBwYXJhIGVsIHBlcmlvZG8gZmFsdGFudGUNCiAgICBwcm9ub3N0aWNvIDwtIGZvcmVjYXN0KG1vZGVsb19zdCwgaCA9IGhfeWVhcnMpDQogICAgDQogICAgIyBDcmVhciB1biBkYXRhZnJhbWUgY29uIGxhcyBwcm95ZWNjaW9uZXMgZ2VuZXJhZGFzDQogICAgYW5pb3NfcHJvbm9zdGljbyA8LSAodWx0aW1vX2FuaW8gKyAxKToyMDUwDQogICAgcG9ibGFjaW9uX3Byb25vc3RpY2FkYSA8LSBhcy5udW1lcmljKHByb25vc3RpY28kbWVhbikNCiAgICANCiAgICBkZl9mb3JlY2FzdCA8LSBkYXRhLmZyYW1lKA0KICAgICAgc3RhdGUgPSBzdCwNCiAgICAgIHllYXIgID0gYW5pb3NfcHJvbm9zdGljbywNCiAgICAgIHBvcHVsYXRpb24gPSBwb2JsYWNpb25fcHJvbm9zdGljYWRhDQogICAgKQ0KICAgIA0KICAgICMgSW5jb3Jwb3JhciBsYXMgcHJveWVjY2lvbmVzIGFsIGRhdGFzZXQgZXh0ZW5kaWRvDQogICAgcG9ibGFjaW9uX2V4dGVuZGlkYSA8LSByYmluZChwb2JsYWNpb25fZXh0ZW5kaWRhLCBkZl9mb3JlY2FzdCkNCiAgfQ0KfQ0KYGBgDQoNCiMjIERlZmluaXIgdW5hIGZ1bmNpw7NuIHBhcmEgdmlzdWFsaXphciBlbCBtYXBhIGRlIHBvYmxhY2nDs24gcG9yIGHDsW8gDQpgYGB7cn0NCnBsb3RfbWFwIDwtIGZ1bmN0aW9uKHllYXIpIHsNCiAgDQogICMgRmlsdHJhciBlbCBkYXRhc2V0IHBhcmEgZWwgYcOxbyBlc3BlY2lmaWNhZG8NCiAgZGF0YV95ZWFyIDwtIHBvYmxhY2lvbl9leHRlbmRpZGEgJT4lDQogICAgZmlsdGVyKHllYXIgPT0gISF5ZWFyKQ0KICANCiAgIyBDYXJnYXIgbGEgaW5mb3JtYWNpw7NuIGdlb2dyw6FmaWNhIGRlIGxvcyBlc3RhZG9zIGRlIEVFLlVVLg0KICBzdGF0ZXNfbWFwIDwtIG1hcF9kYXRhKCJzdGF0ZSIpDQogIA0KICAjIFJlbGFjaW9uYXIgbGFzIGFicmV2aWF0dXJhcyBlc3RhdGFsZXMgY29uIGxvcyBub21icmVzIGNvbXBsZXRvcyBlbiBtaW7DunNjdWxhcw0KICAjIFV0aWxpemFuZG8gbG9zIHZlY3RvcmVzIGF1eGlsaWFyZXMgc3RhdGUuYWJiIHkgc3RhdGUubmFtZQ0KICBkYXRhX3llYXIgPC0gZGF0YV95ZWFyICU+JQ0KICAgIG11dGF0ZShyZWdpb24gPSB0b2xvd2VyKHN0YXRlLm5hbWVbbWF0Y2goc3RhdGUsIHN0YXRlLmFiYildKSkgJT4lDQogICAgcmlnaHRfam9pbihzdGF0ZXNfbWFwLCBieSA9ICJyZWdpb24iKQ0KICANCiAgIyBHZW5lcmFyIGVsIG1hcGEgdGVtw6F0aWNvIHBvciBwb2JsYWNpw7NuDQogIGdncGxvdChkYXRhX3llYXIsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IHBvcHVsYXRpb24pKSArDQogICAgZ2VvbV9wb2x5Z29uKGNvbG9yID0gImJsYWNrIikgKw0KICAgICMgQXBsaWNhciB1biBncmFkaWVudGUgZGUgY29sb3IgdmVyZGUgKGJham8pIGEgcm9qbyAoYWx0bykNCiAgICBzY2FsZV9maWxsX2dyYWRpZW50KA0KICAgICAgbG93ID0gImdyZWVuIiwgICAjIFJlcHJlc2VudGEgbGEgbWVub3IgcG9ibGFjacOzbg0KICAgICAgaGlnaCA9ICJyZWQiLCAgICAjIEluZGljYSBsYSBtYXlvciBwb2JsYWNpw7NuDQogICAgICBuYW1lID0gIlBvYmxhY2nDs24iDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gcGFzdGUoIlBvYmxhY2nDs24gcG9yIEVzdGFkbyBlbiIsIHllYXIpDQogICAgKSArDQogICAgdGhlbWVfdm9pZCgpICsNCiAgICB0aGVtZSgNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsDQogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIikNCiAgICApDQp9DQpgYGANCg0KIyMgVmlzdWFsaXphciBsYSBldm9sdWNpw7NuIGRlbW9ncsOhZmljYSBjYWRhIGTDqWNhZGEgKDE5NTAgLSAyMDUwKSANCmBgYHtyfQ0KZm9yKHllYXIgaW4gc2VxKDE5NTAsIDIwNTAsIGJ5ID0gMTApKSB7DQogIHByaW50KHBsb3RfbWFwKHllYXIpKQ0KfQ0KDQpgYGANCg0KDQoNCiMgPHNwYW4gc3R5bGU9ICJjb2xvcjpicm93bjsiPiBBY3RpdmlkYWQgMi4gTGVjaGUgc2Fib3JpemFkYSBIZXJzaGV5J3MgPC9zcGFuPg0KDQohW10oIkM6XFxVc2Vyc1xcTHVpc0RcXERvY3VtZW50c1xcT0NUQVZPIFNFTUVTVFJFXFxHZW5lcmFjacOzbiBkZSBlc2NlbmFyaW9zXFxNw7NkdWxvIDFcXGhlcnNoZXkncy5qZmlmIikNCg0KIyMgPHNwYW4gc3R5bGU9ICJjb2xvcjpicm93bjsiPiAjIyBJbnN0YWxhciBwYXF1ZXRlcyB5IGxsYW1hciBsaWJyZXLDrWFzIDwvc3Bhbj4NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiNpbnN0YWxsLnBhY2thZ2VzKCJmb3JlY2FzdCIpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KI2luc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCiNpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCmxpYnJhcnkoZ2dwbG90MikNCmBgYA0KIyMgPHNwYW4gc3R5bGU9ICJjb2xvcjpicm93bjsiPiBJbXBvcnRhciBsYSBiYXNlIGRlIGRhdG9zIDwvc3Bhbj4NCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQp2ZW50YXMgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcTHVpc0RcXERvY3VtZW50c1xcT0NUQVZPIFNFTUVTVFJFXFxHZW5lcmFjacOzbiBkZSBlc2NlbmFyaW9zXFxNw7NkdWxvIDFcXFZlbnRhc19IaXN0w7NyaWNhc19MZWNoaXRhcy5jc3YiKQ0KI2ZpbGUuY2hvb3NlKCkNCmBgYA0KDQojIyA8c3BhbiBzdHlsZT0gImNvbG9yOmJyb3duOyI+IDEuIE1vZGVsbyBBVVRPLkFSSU1BIDwvc3Bhbj4NCmBgYHtyfQ0KdHNfdmVudGFzIDwtIHRzKHZlbnRhcyRWZW50YXMsIHN0YXJ0ID0gYygyMDE3LCAxKSwgZnJlcXVlbmN5ID0gMTIpDQphdXRvcGxvdCh0c192ZW50YXMpICsgbGFicyh0aXRsZT0gIlZlbnRhcyBkZSBMZWNoZSBTYWJvcml6YWRhIEhlcnNoZXkncyIsIHg9IlRpZW1wbyIsIHk9Ik1pbGVzIGRlIETDs2xhcmVzIikNCmFyaW1hX3ZlbnRhcyA8LSBhdXRvLmFyaW1hKHRzX3ZlbnRhcykNCnN1bW1hcnkoYXJpbWFfdmVudGFzKQ0KcHJvbm9zdGljb192ZW50YXMgPC0gZm9yZWNhc3QoYXJpbWFfdmVudGFzLCBsZXZlbD05NSwgaD0xMikNCnByb25vc3RpY29fdmVudGFzDQphdXRvcGxvdChwcm9ub3N0aWNvX3ZlbnRhcykrIGxhYnModGl0bGU9IlByb27Ds3N0aWNvIGRlIHZlbnRhcyAyMDIwIGRlIExlY2hlIFNhYm9yaXphZGEgSGVyc2hleSdzIiwgeD0iVGllbXBvIiwgeT0iTmlsZXMgZGUgRMOzbGFyZXMiKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6YnJvd247Ij4yLiBNb2RlbG8gZGUgUmVncmVzacOzbiBMaW5lYWwgPC9zcGFuPg0KDQpgYGB7cn0NCnZlbnRhcyRtZXMgPC0gMTozNg0KcmVncmVzaW9uX3ZlbnRhcyA8LSBsbShWZW50YXMgfiBtZXMsIGRhdGE9dmVudGFzICkNCnN1bW1hcnkocmVncmVzaW9uX3ZlbnRhcykNCnNpZ3VpZW50ZV9hw7FvIDwtIGRhdGEuZnJhbWUobWVzID0gMzc6NDgpDQpwcmVkaWNjaW9uX3JlZ3Jlc2lvbiA8LSBwcmVkaWN0KHJlZ3Jlc2lvbl92ZW50YXMsIHNpZ3VpZW50ZV9hw7FvKQ0KcHJlZGljY2lvbl9yZWdyZXNpb24NCnBsb3QodmVudGFzJG1lcywgdmVudGFzJFZlbnRhcywgbWFpbiA9ICJQcm9uw7NzdGljbyBkZSBWZW50YXMgMjAyMCBkZSBMZWNoZSBTYWJvcml6YWRhIEhlcnNoZXkncyIsIHhsYWIgPSAiVGllbXBvIiwgeWxhYiA9ICJNaWxlcyBkZSBEw7NsYXJlcyIpICsgYWJsaW5lKHJlZ3Jlc2lvbl92ZW50YXMsIGNvbD0iYmx1ZSIpICsgcG9pbnRzKHByZWRpY2Npb25fcmVncmVzaW9uLCBjb2w9InJlZCIpDQoNCnByZWRpY2Npb25lc19yZWFsZXM8LSBwcmVkaWN0KHJlZ3Jlc2lvbl92ZW50YXMsIHZlbnRhcykNCk1BUEU8LSBtZWFuKGFicygodmVudGFzJFZlbnRhcyAtIA0KcHJlZGljY2lvbmVzX3JlYWxlcykvdmVudGFzJFZlbnRhcykpKjEwMA0KTUFQRQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6YnJvd247Ij4gMy4gQ29uY2x1c2lvbmVzIDwvc3Bhbj4NCg0KRWwgbWVqb3IgbW9kZWxvIHF1ZSBzZSBhZGFwdGEgYSBsYSBzZXJpZSBlcyBlbCAqKlNBUklNQSoqIGNvbiB1bk1BUEUgZGUgMC43MSUsIGNvbXBhcmFkbyBjb24gbGEgUmVnZXJzacOzbiBMaW5lYWwgcXVlIHN1IE1BUEUgZXMgZGUgMi4wMSUuDQoNClBhcmEgZWwgc2lndWllbnRlIGHDsW8sIGxhIHByb3llY2Npw7NuIGRlIHZlbnRhcyBlcyBsYSBzaWd1aWVudGU6DQp8IE1lcyB5IEHDsW8gfCBFc2NlbmFyaW8gRXNwZXJhZG8gfCBFc2NlbmFyaW8gUGVzaW1pc3RhIHwgRXNjZW5hcmlvIE9wdGltaXN0YSB8DQp8LS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLXwNCnxKYW4gMjAyMAkgIHwgICAgICAzNTQ5OC45MAkgICAgIHwgICAgICAgMzQ2MTYuNDgJICAgICB8ICAgICAgIDM2MzgxLjMyCSAgICAgfA0KfEZlYiAyMDIwCSAgfCAgICAgIDM0MjAyLjE3CSAgICAgfCAgICAgICAzMzE1NS4yOQkgICAgIHwgICAgICAgMzUyNDkuMDUJICAgICB8DQp8TWFyIDIwMjAJICB8ICAgICAgMzY3MDMuMDEJICAgICB8ICAgICAgIDM1NTk2LjEwCSAgICAgfCAgICAgICAzNzgwOS45MgkgICAgIHwNCnxBcHIgMjAyMAkgIHwgICAgICAzNjI3MS45MAkgICAgIHwgICAgICAgMzUxNDEuNDQJICAgICB8ICAgICAgIDM3NDAyLjM2CSAgICAgfA0KfE1heSAyMDIwCSAgfCAgICAgIDM3MTIxLjk4CSAgICAgfCAgICAgICAzNTk4Mi4wNwkgICAgIHwgICAgICAgMzgyNjEuOTAJICAgICB8DQp8SnVuIDIwMjAJICB8ICAgICAgMzcxMDIuNjUJICAgICB8ICAgICAgIDM1OTU4LjkxCSAgICAgfCAgICAgICAzODI0Ni40MAkgICAgIHwNCnxKdWwgMjAyMAkgIHwgICAgICAzNzE1MS4wNAkgICAgIHwgICAgICAgMzYwMDUuNzQJICAgICB8ICAgICAgIDM4Mjk2LjM1CSAgICAgfA0KfEF1ZyAyMDIwCSAgfCAgICAgIDM4NTY0LjY1CSAgICAgfCAgICAgICAzNzQxOC43MQkgICAgIHwgICAgICAgMzk3MTAuNTkJICAgICB8DQp8U2VwIDIwMjAJICB8ICAgICAgMzg3NTUuMjMJICAgICB8ICAgICAgIDM3NjA5LjAzCSAgICAgfCAgICAgICAzOTkwMS40MgkgICAgIHwNCnxPY3QgMjAyMAkgIHwgICAgICAzOTc3OS4wMwkgICAgIHwgICAgICAgMzg2MzIuNzMJICAgICB8ICAgICAgIDQwOTI1LjMzCSAgICAgfA0KDQpgYGB7cn0NCnZlbnRhc19wb3JfYW5pbyA8LSByZWFkLmNzdigiQzpcXFVzZXJzXFxMdWlzRFxcRG9jdW1lbnRzXFxPQ1RBVk8gU0VNRVNUUkVcXEdlbmVyYWNpw7NuIGRlIGVzY2VuYXJpb3NcXE3Ds2R1bG8gMVxcdmVudGFzX3Bvcl9hbmlvLmNzdiIpDQpnZ3Bsb3QodmVudGFzX3Bvcl9hbmlvLCBhZXMoeD1tZXMsIHk9dmVudGFzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbD1hcy5mYWN0b3IoYW5pbyksIGdyb3VwPWFuaW8pKSArIGdlb21fbGluZSgpICsgbGFicyh0aXRsZT0iVmVudGFzIGRlIExlY2hlIFNhYm9yaXphZGEgSGVyc2hleSdzIHBvciBhw7FvIiwgeD0iTWVzIiwgeT0iTWlsZXMgZGUgRMOzbGFyZXMiKQ0KYGBgDQoNCk51ZXN0cmEgcmVvY21lbnRhY2nDs24gc2Vyw61hIHJlYWxpYXIgY2FtcGHDsWFzIHB1YmxpY2l0YXJpYXMgcGFyYSBhdW1lbnRhciBlbCBjb21zdW1vIGRlIGxlY2hlIGRhYm9yaXphZGEgSGVyc2hleSdzIGVuIGVsIHByaW1lciBzZW1lc3RyZSBkZWwgYcOxbw0K