Instalar paquetes y llamar librerías

#install.packages("forecast")
library(forecast)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(readxl)

Ejemplo. Producción

Contexto

Una serie de tiempo es una colección de observaciones sobre un determinado fenómeno efectuadas en momentos de tiempo sucesivos, usualmente equiespaciados.

Ejemplos de series de tiempo son:
1. Precio de acciones 2. Niveles de inventario 3. Rotación de personal 4. Ventas 5. PIB (GDP).

Crear la serie de tiempo

Ejemplo: Los siguientes datos de producción trimestral inician el primer trimestre de 2020. Se busca pronosticar la producción de los siguientes 5 trimestres.

produccion <- c(50,53,55,57,55,60)
st_produccion <- ts(data=produccion, start= c(2020, 1), frequency=4) # En este caso, la serie de tiempo inicia en 2020, en el 1º trimestre

# Mensual primer mes : st_produccion <- ts(data=produccion, start= c(2020, 1), frequency=12) # En este caso, la serie de tiempo inicia en 2020, en el 1º mes

# Mensual otro mes :  : st_produccion <- ts(data=produccion, start= c(2020, 8), frequency=12) # En este caso, la serie de tiempo inicia en 2020, en el 8vo mes

# Anual : st_produccion <- ts(data=produccion, start= c(2020), frequency=1) # En este caso, la serie de tiempo inicia en 2020

Crear el modelo ARIMA

ARIMA significa Modelo Autorregresivo Integrado de Promedio Móvil, en inglés.

modelo_produccion <- auto.arima(st_produccion, D=1) # D: Diferenciación estacional
modelo_produccion
## Series: st_produccion 
## ARIMA(0,0,0)(0,1,0)[4] with drift 
## 
## Coefficients:
##        drift
##       1.5000
## s.e.  0.1768
## 
## sigma^2 = 2.01:  log likelihood = -2.84
## AIC=9.68   AICc=-2.32   BIC=7.06
summary(modelo_produccion) #MAPE : Median Absolute Porcentage Error / Porcentaje de Error Promedio Absoluto
## Series: st_produccion 
## ARIMA(0,0,0)(0,1,0)[4] with drift 
## 
## Coefficients:
##        drift
##       1.5000
## s.e.  0.1768
## 
## sigma^2 = 2.01:  log likelihood = -2.84
## AIC=9.68   AICc=-2.32   BIC=7.06
## 
## Training set error measures:
##                      ME      RMSE       MAE        MPE      MAPE       MASE
## Training set 0.03333332 0.5787923 0.3666667 0.03685269 0.6429133 0.06111111
##                    ACF1
## Training set -0.5073047
# Al comparar modelos, seleccionamos el que tenga el menor MAPE.

Generar el pronóstico

pronostico_produccion <- forecast(modelo_produccion, level = c(95), h=5)
# Si no nos dicen otra cosa, el nivel de confiabilidad es 95%. Los periodos a pronosticar es h
pronostico_produccion
##         Point Forecast    Lo 95    Hi 95
## 2021 Q3             61 58.22127 63.77873
## 2021 Q4             63 60.22127 65.77873
## 2022 Q1             61 58.22127 63.77873
## 2022 Q2             66 63.22127 68.77873
## 2022 Q3             67 63.07028 70.92972
plot(pronostico_produccion)

Ejercicio 1. Mexico rumbo al 2050

En equipos de 2 o 3, seleccionar un estado de México, obtener los datos históricos de su poblacón, generar un pronóstico hasta 2050

Cargar archivo

pob_sonora <- read_excel("/Users/hugoenrique/Desktop/Universidad/8vo\ Semestre/Generación\ de\ Escenarios/M1/Act2/pob_sonora_1990_2020.xlsx")
pob_sonora
## # A tibble: 7 × 3
##   Entidad   Año Población
##   <chr>   <dbl>     <dbl>
## 1 Sonora   1990   1823606
## 2 Sonora   1995   2085536
## 3 Sonora   2000   2216969
## 4 Sonora   2005   2394861
## 5 Sonora   2010   2662480
## 6 Sonora   2015   2850330
## 7 Sonora   2020   2944840

Crear la serie de tiempo

st_pob_sonora <- ts(data=pob_sonora$Población, start= c(1990), frequency=.2)
#En este caso, la serie de tiempo inicia en 2020, en el 1er trimestre.

Crear el modeo ARIMA

ARIMA significa Modelo Autorregresivo Integrado de Promedio Móvil, en inglés.

modelo_pbsonora <- auto.arima(st_pob_sonora) # Diferenciación Estacional
modelo_pbsonora
## Series: st_pob_sonora 
## ARIMA(0,1,0) with drift 
## 
## Coefficients:
##           drift
##       186872.33
## s.e.   25733.79
## 
## sigma^2 = 4.768e+09:  log likelihood = -74.82
## AIC=153.64   AICc=157.64   BIC=153.23
summary(modelo_pbsonora)
## Series: st_pob_sonora 
## ARIMA(0,1,0) with drift 
## 
## Coefficients:
##           drift
##       186872.33
## s.e.   25733.79
## 
## sigma^2 = 4.768e+09:  log likelihood = -74.82
## AIC=153.64   AICc=157.64   BIC=153.23
## 
## Training set error measures:
##                   ME     RMSE      MAE       MPE     MAPE       MASE       ACF1
## Training set 233.819 58361.29 45028.68 0.1062428 1.823979 0.01856457 -0.1802949
# Al comparar modelos, seleccionamos el que tenga el menor MAPE (Porcentaje de Error Promedio Absoluto)

Generar el pronóstico

pronostico_pbsonora <- forecast(modelo_pbsonora, level=c(95), h=7)
#Si no nos dicen otra cosa, el nivel de confiabilidad es 95%. Los periodos a pronosticar es h.
pronostico_pbsonora
##      Point Forecast   Lo 95   Hi 95
## 2025        3131712 2996369 3267056
## 2030        3318585 3127180 3509989
## 2035        3505457 3271035 3739879
## 2040        3692329 3421643 3963016
## 2045        3879202 3576565 4181839
## 2050        4066074 3734552 4397596
## 2055        4252946 3894861 4611031
plot(pronostico_pbsonora)

Conclusión

En nuestro pronóstico se refleja un constante crecimiento en la población de Sonora. El último censo realizado por INEGI en 2020 registró una población de 2,944,840 en Sonora, mientras que nuestro pronóstico refleja una población ligeramente mayor a los 4 millones de habitantes.

Ejercicio 2. Aplicación de Shiny

Agregar una pestaña en la aplicación de Shiny con el ejercicio México rumbo al 2050. En el menú se debe seleccionar la cantidad de años a pronosticar y el nivel de confiabilidad.

Aplicación de Shiny

Ejercicio 3. Reflexión de mis materias en LIT

  1. El rol de los Negocios en la Sociedad: Aprendí a realizar el análisis PESTEL, FODA y creación de KPI’s al mismo tiempo aprendimos a realizar propuestas de valor para una empresa
  2. Decisiones Financieras: Aprendimos a hacer los Estados de resultados, Balance general, entre otros documentos contables.
  3. Pensamiento Estadístico: No recuerdo que vi en esta materia.
  4. Comunicación que inspira: Vimos el IKIGAI para encontrar nuestro proposito, la intención era aprender a desenvolverte para generar un negocio que llenara tu pasión.
  5. Estrategias de Mercado y Diferenciación: Aprendimos a hacer costeo de un plan de marketing para el socio formador y presentamos un tablero interactivo en excel.
  6. Evaluación de Proyectos de inversión: Aprendimos a sacar el WACC, Costo de Capital, cosas así para poder evaluar empresas y saber si serían rentables.
  7. Manipulación de Datos: Aprendimos a hacer limpieza, y utilización de datos en R para poder generar insights y entender el funcionamiento de tablas.
  8. Minería de datos: Aprendimos muchos modelos de Machine Learning, la relación entre explanibilidad y dificultad de un modelo y como entre más sencillo el modelo más fácil de leerlo.
  9. Bootcamp de programación: Aprendimos a hacer ShinyApps, programación en R y utilizamos mucho esto para trabajar con datos de Arca Continental
  10. Semestre Tec: Reforcé en España diversos temas de Recursos humanos, Finanzas y aprendi a hacer impuestos en España debido a una materia de Fiscabilidad.

Actividad 2. Hershey’s

Crear la serie de tiempo

ventas <- read_excel("/Users/hugoenrique/Desktop/Universidad/8vo\ Semestre/Generación\ de\ Escenarios/M1/Act2/Ventas_Históricas_Lechitas.xlsx")
str(ventas)
## tibble [36 × 1] (S3: tbl_df/tbl/data.frame)
##  $ Ventas: num [1:36] 25521 23740 26254 25868 27073 ...
st_ventas <- ts(data=ventas, start=c(2017, 1), frequency = 12)

Crear el modeo ARIMA

modelo_ventas <- auto.arima(st_ventas)
modelo_ventas
## Series: st_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
summary(modelo_ventas)
## Series: st_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

Generar el pronóstico

pronostico_ventas <- forecast(modelo_ventas, level = c(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
plot(pronostico_ventas)

LS0tCnRpdGxlOiAiQWN0aXZpZGFkIDIiCmF1dGhvcjogIkh1Z28gRW5yaXF1ZSBFc3Byb25jZWRhIEFuYXlhIC8gQTAxMjg0ODI3IgpkYXRlOiAiMjAyNS0wOC0xMiIKb3V0cHV0OiAKIGh0bWxfZG9jdW1lbnQ6CiAgIHRvYzogVFJVRQogICB0b2NfZmxvYXQ6IFRydWUKICAgY29kZV9kb3dubG9hZDogVHJ1ZQogICB0aGVtZTogY2VydWxlYW4KLS0tCgohW10oaHR0cHM6Ly93d3c1LnV2YS5lcy9lc3RhZG1lZC9kYXRvcy9zZXJpZXMvZ3JhZjE1LmdpZikKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij4gSW5zdGFsYXIgcGFxdWV0ZXMgeSBsbGFtYXIgbGlicmVyw61hcyA8L3NwYW4+CmBgYHtyfQojaW5zdGFsbC5wYWNrYWdlcygiZm9yZWNhc3QiKQpsaWJyYXJ5KGZvcmVjYXN0KQpsaWJyYXJ5KHJlYWR4bCkKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+IEVqZW1wbG8uIFByb2R1Y2Npw7NuIDwvc3Bhbj4KCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+IENvbnRleHRvIDwvc3Bhbj4KVW5hICoqc2VyaWUgZGUgdGllbXBvKiogZXMgdW5hIGNvbGVjY2nDs24gZGUgb2JzZXJ2YWNpb25lcyBzb2JyZSB1biBkZXRlcm1pbmFkbyBmZW7Ds21lbm8gZWZlY3R1YWRhcyBlbiBtb21lbnRvcyBkZSB0aWVtcG8gc3VjZXNpdm9zLCB1c3VhbG1lbnRlIGVxdWllc3BhY2lhZG9zLiAgCgpFamVtcGxvcyBkZSBzZXJpZXMgZGUgdGllbXBvIHNvbjogIAoxLiBQcmVjaW8gZGUgYWNjaW9uZXMKMi4gTml2ZWxlcyBkZSBpbnZlbnRhcmlvCjMuIFJvdGFjacOzbiBkZSBwZXJzb25hbAo0LiBWZW50YXMKNS4gUElCIChHRFApLiAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+IENyZWFyIGxhIHNlcmllIGRlIHRpZW1wbyA8L3NwYW4+CkVqZW1wbG86IExvcyBzaWd1aWVudGVzIGRhdG9zIGRlIHByb2R1Y2Npw7NuIHRyaW1lc3RyYWwgaW5pY2lhbiBlbCBwcmltZXIgdHJpbWVzdHJlIGRlIDIwMjAuIFNlIGJ1c2NhIHByb25vc3RpY2FyIGxhIHByb2R1Y2Npw7NuIGRlIGxvcyBzaWd1aWVudGVzIDUgdHJpbWVzdHJlcy4KYGBge3J9CnByb2R1Y2Npb24gPC0gYyg1MCw1Myw1NSw1Nyw1NSw2MCkKc3RfcHJvZHVjY2lvbiA8LSB0cyhkYXRhPXByb2R1Y2Npb24sIHN0YXJ0PSBjKDIwMjAsIDEpLCBmcmVxdWVuY3k9NCkgIyBFbiBlc3RlIGNhc28sIGxhIHNlcmllIGRlIHRpZW1wbyBpbmljaWEgZW4gMjAyMCwgZW4gZWwgMcK6IHRyaW1lc3RyZQoKIyBNZW5zdWFsIHByaW1lciBtZXMgOiBzdF9wcm9kdWNjaW9uIDwtIHRzKGRhdGE9cHJvZHVjY2lvbiwgc3RhcnQ9IGMoMjAyMCwgMSksIGZyZXF1ZW5jeT0xMikgIyBFbiBlc3RlIGNhc28sIGxhIHNlcmllIGRlIHRpZW1wbyBpbmljaWEgZW4gMjAyMCwgZW4gZWwgMcK6IG1lcwoKIyBNZW5zdWFsIG90cm8gbWVzIDogIDogc3RfcHJvZHVjY2lvbiA8LSB0cyhkYXRhPXByb2R1Y2Npb24sIHN0YXJ0PSBjKDIwMjAsIDgpLCBmcmVxdWVuY3k9MTIpICMgRW4gZXN0ZSBjYXNvLCBsYSBzZXJpZSBkZSB0aWVtcG8gaW5pY2lhIGVuIDIwMjAsIGVuIGVsIDh2byBtZXMKCiMgQW51YWwgOiBzdF9wcm9kdWNjaW9uIDwtIHRzKGRhdGE9cHJvZHVjY2lvbiwgc3RhcnQ9IGMoMjAyMCksIGZyZXF1ZW5jeT0xKSAjIEVuIGVzdGUgY2FzbywgbGEgc2VyaWUgZGUgdGllbXBvIGluaWNpYSBlbiAyMDIwCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij4gQ3JlYXIgZWwgbW9kZWxvIEFSSU1BIDwvc3Bhbj4KKipBUklNQSoqIHNpZ25pZmljYSBNb2RlbG8gQXV0b3JyZWdyZXNpdm8gSW50ZWdyYWRvIGRlIFByb21lZGlvIE3Ds3ZpbCwgZW4gaW5nbMOpcy4KYGBge3J9Cm1vZGVsb19wcm9kdWNjaW9uIDwtIGF1dG8uYXJpbWEoc3RfcHJvZHVjY2lvbiwgRD0xKSAjIEQ6IERpZmVyZW5jaWFjacOzbiBlc3RhY2lvbmFsCm1vZGVsb19wcm9kdWNjaW9uCnN1bW1hcnkobW9kZWxvX3Byb2R1Y2Npb24pICNNQVBFIDogTWVkaWFuIEFic29sdXRlIFBvcmNlbnRhZ2UgRXJyb3IgLyBQb3JjZW50YWplIGRlIEVycm9yIFByb21lZGlvIEFic29sdXRvCiMgQWwgY29tcGFyYXIgbW9kZWxvcywgc2VsZWNjaW9uYW1vcyBlbCBxdWUgdGVuZ2EgZWwgbWVub3IgTUFQRS4KYGBgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6Ymx1ZTsiPiBHZW5lcmFyIGVsIHByb27Ds3N0aWNvIDwvc3Bhbj4KYGBge3J9CnByb25vc3RpY29fcHJvZHVjY2lvbiA8LSBmb3JlY2FzdChtb2RlbG9fcHJvZHVjY2lvbiwgbGV2ZWwgPSBjKDk1KSwgaD01KQojIFNpIG5vIG5vcyBkaWNlbiBvdHJhIGNvc2EsIGVsIG5pdmVsIGRlIGNvbmZpYWJpbGlkYWQgZXMgOTUlLiBMb3MgcGVyaW9kb3MgYSBwcm9ub3N0aWNhciBlcyBoCnByb25vc3RpY29fcHJvZHVjY2lvbgpwbG90KHByb25vc3RpY29fcHJvZHVjY2lvbikKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+IEVqZXJjaWNpbyAxLiBNZXhpY28gcnVtYm8gYWwgMjA1MCA8L3NwYW4+CkVuIGVxdWlwb3MgZGUgMiBvIDMsIHNlbGVjY2lvbmFyIHVuIGVzdGFkbyBkZSBNw6l4aWNvLCBvYnRlbmVyIGxvcyBkYXRvcyBoaXN0w7NyaWNvcyBkZSBzdSBwb2JsYWPDs24sIGdlbmVyYXIgdW4gcHJvbsOzc3RpY28gaGFzdGEgMjA1MCAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+IENhcmdhciBhcmNoaXZvIDwvc3Bhbj4KYGBge3J9CnBvYl9zb25vcmEgPC0gcmVhZF9leGNlbCgiL1VzZXJzL2h1Z29lbnJpcXVlL0Rlc2t0b3AvVW5pdmVyc2lkYWQvOHZvXCBTZW1lc3RyZS9HZW5lcmFjaW/MgW5cIGRlXCBFc2NlbmFyaW9zL00xL0FjdDIvcG9iX3Nvbm9yYV8xOTkwXzIwMjAueGxzeCIpCnBvYl9zb25vcmEKYGBgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6Ymx1ZTsiPiBDcmVhciBsYSBzZXJpZSBkZSB0aWVtcG8gPC9zcGFuPgpgYGB7cn0Kc3RfcG9iX3Nvbm9yYSA8LSB0cyhkYXRhPXBvYl9zb25vcmEkUG9ibGFjacOzbiwgc3RhcnQ9IGMoMTk5MCksIGZyZXF1ZW5jeT0uMikKI0VuIGVzdGUgY2FzbywgbGEgc2VyaWUgZGUgdGllbXBvIGluaWNpYSBlbiAyMDIwLCBlbiBlbCAxZXIgdHJpbWVzdHJlLgpgYGAKCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6Ymx1ZTsiPiBDcmVhciBlbCBtb2RlbyBBUklNQSA8L3NwYW4+CipBUklNQSogc2lnbmlmaWNhIE1vZGVsbyBBdXRvcnJlZ3Jlc2l2byBJbnRlZ3JhZG8gZGUgUHJvbWVkaW8gTcOzdmlsLCBlbiBpbmdsw6lzLgpgYGB7cn0KbW9kZWxvX3Bic29ub3JhIDwtIGF1dG8uYXJpbWEoc3RfcG9iX3Nvbm9yYSkgIyBEaWZlcmVuY2lhY2nDs24gRXN0YWNpb25hbAptb2RlbG9fcGJzb25vcmEKc3VtbWFyeShtb2RlbG9fcGJzb25vcmEpCiMgQWwgY29tcGFyYXIgbW9kZWxvcywgc2VsZWNjaW9uYW1vcyBlbCBxdWUgdGVuZ2EgZWwgbWVub3IgTUFQRSAoUG9yY2VudGFqZSBkZSBFcnJvciBQcm9tZWRpbyBBYnNvbHV0bykKYGBgCgojIyA8c3BhbiBzdHlsZT0gImNvbG9yOmJsdWU7Ij4gR2VuZXJhciBlbCBwcm9uw7NzdGljbyA8L3NwYW4+CmBgYHtyfQpwcm9ub3N0aWNvX3Bic29ub3JhIDwtIGZvcmVjYXN0KG1vZGVsb19wYnNvbm9yYSwgbGV2ZWw9Yyg5NSksIGg9NykKI1NpIG5vIG5vcyBkaWNlbiBvdHJhIGNvc2EsIGVsIG5pdmVsIGRlIGNvbmZpYWJpbGlkYWQgZXMgOTUlLiBMb3MgcGVyaW9kb3MgYSBwcm9ub3N0aWNhciBlcyBoLgpwcm9ub3N0aWNvX3Bic29ub3JhCnBsb3QocHJvbm9zdGljb19wYnNvbm9yYSkKYGBgCgojIyA8c3BhbiBzdHlsZT0gImNvbG9yOmJsdWU7Ij4gQ29uY2x1c2nDs24gPC9zcGFuPgpFbiBudWVzdHJvIHByb27Ds3N0aWNvIHNlIHJlZmxlamEgdW4gY29uc3RhbnRlIGNyZWNpbWllbnRvIGVuIGxhIHBvYmxhY2nDs24gZGUgU29ub3JhLiBFbCDDumx0aW1vIGNlbnNvIHJlYWxpemFkbyBwb3IgSU5FR0kgZW4gMjAyMCByZWdpc3Ryw7MgdW5hIHBvYmxhY2nDs24gZGUgMiw5NDQsODQwIGVuIFNvbm9yYSwgbWllbnRyYXMgcXVlIG51ZXN0cm8gcHJvbsOzc3RpY28gcmVmbGVqYSB1bmEgcG9ibGFjacOzbiBsaWdlcmFtZW50ZSBtYXlvciBhIGxvcyA0IG1pbGxvbmVzIGRlIGhhYml0YW50ZXMuCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+IEVqZXJjaWNpbyAyLiBBcGxpY2FjacOzbiBkZSBTaGlueTwvc3Bhbj4KQWdyZWdhciB1bmEgcGVzdGHDsWEgZW4gbGEgYXBsaWNhY2nDs24gZGUgU2hpbnkgY29uIGVsIGVqZXJjaWNpbyBNw6l4aWNvIHJ1bWJvIGFsIDIwNTAuIEVuIGVsIG1lbsO6IHNlIGRlYmUgc2VsZWNjaW9uYXIgbGEgY2FudGlkYWQgZGUgYcOxb3MgYSBwcm9ub3N0aWNhciB5IGVsIG5pdmVsIGRlIGNvbmZpYWJpbGlkYWQuCgpbQXBsaWNhY2nDs24gZGUgU2hpbnldKGh0dHBzOi8vYTAxMjg0ODI3LnNoaW55YXBwcy5pby9NMV9HRUZBX0ExLykKCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+IEVqZXJjaWNpbyAzLiBSZWZsZXhpw7NuIGRlIG1pcyBtYXRlcmlhcyBlbiBMSVQ8L3NwYW4+CjEuICoqRWwgcm9sIGRlIGxvcyBOZWdvY2lvcyBlbiBsYSBTb2NpZWRhZDoqKiBBcHJlbmTDrSBhIHJlYWxpemFyIGVsIGFuw6FsaXNpcyBQRVNURUwsIEZPREEgeSBjcmVhY2nDs24gZGUgS1BJJ3MgYWwgbWlzbW8gdGllbXBvIGFwcmVuZGltb3MgYSByZWFsaXphciBwcm9wdWVzdGFzIGRlIHZhbG9yIHBhcmEgdW5hIGVtcHJlc2EKMi4gKipEZWNpc2lvbmVzIEZpbmFuY2llcmFzOioqIEFwcmVuZGltb3MgYSBoYWNlciBsb3MgRXN0YWRvcyBkZSByZXN1bHRhZG9zLCBCYWxhbmNlIGdlbmVyYWwsIGVudHJlIG90cm9zIGRvY3VtZW50b3MgY29udGFibGVzLgozLiAqKlBlbnNhbWllbnRvIEVzdGFkw61zdGljbzoqKiBObyByZWN1ZXJkbyBxdWUgdmkgZW4gZXN0YSBtYXRlcmlhLiAKNC4gKipDb211bmljYWNpw7NuIHF1ZSBpbnNwaXJhOioqIFZpbW9zIGVsIElLSUdBSSBwYXJhIGVuY29udHJhciBudWVzdHJvIHByb3Bvc2l0bywgbGEgaW50ZW5jacOzbiBlcmEgYXByZW5kZXIgYSBkZXNlbnZvbHZlcnRlIHBhcmEgZ2VuZXJhciB1biBuZWdvY2lvIHF1ZSBsbGVuYXJhIHR1IHBhc2nDs24uCjUuICoqRXN0cmF0ZWdpYXMgZGUgTWVyY2FkbyB5IERpZmVyZW5jaWFjacOzbjoqKiBBcHJlbmRpbW9zIGEgaGFjZXIgY29zdGVvIGRlIHVuIHBsYW4gZGUgbWFya2V0aW5nIHBhcmEgZWwgc29jaW8gZm9ybWFkb3IgeSBwcmVzZW50YW1vcyB1biB0YWJsZXJvIGludGVyYWN0aXZvIGVuIGV4Y2VsLgo2LiAqKkV2YWx1YWNpw7NuIGRlIFByb3llY3RvcyBkZSBpbnZlcnNpw7NuOioqIEFwcmVuZGltb3MgYSBzYWNhciBlbCBXQUNDLCBDb3N0byBkZSBDYXBpdGFsLCBjb3NhcyBhc8OtIHBhcmEgcG9kZXIgZXZhbHVhciBlbXByZXNhcyB5IHNhYmVyIHNpIHNlcsOtYW4gcmVudGFibGVzLiAKNy4gKipNYW5pcHVsYWNpw7NuIGRlIERhdG9zOioqIEFwcmVuZGltb3MgYSBoYWNlciBsaW1waWV6YSwgeSB1dGlsaXphY2nDs24gZGUgZGF0b3MgZW4gUiBwYXJhIHBvZGVyIGdlbmVyYXIgaW5zaWdodHMgeSBlbnRlbmRlciBlbCBmdW5jaW9uYW1pZW50byBkZSB0YWJsYXMuCjguICoqTWluZXLDrWEgZGUgZGF0b3M6KiogQXByZW5kaW1vcyBtdWNob3MgbW9kZWxvcyBkZSBNYWNoaW5lIExlYXJuaW5nLCBsYSByZWxhY2nDs24gZW50cmUgZXhwbGFuaWJpbGlkYWQgeSBkaWZpY3VsdGFkIGRlIHVuIG1vZGVsbyB5IGNvbW8gZW50cmUgbcOhcyBzZW5jaWxsbyBlbCBtb2RlbG8gbcOhcyBmw6FjaWwgZGUgbGVlcmxvLgo5LiAqKkJvb3RjYW1wIGRlIHByb2dyYW1hY2nDs246KiogQXByZW5kaW1vcyBhIGhhY2VyIFNoaW55QXBwcywgcHJvZ3JhbWFjacOzbiBlbiBSIHkgdXRpbGl6YW1vcyBtdWNobyBlc3RvIHBhcmEgdHJhYmFqYXIgY29uIGRhdG9zIGRlIEFyY2EgQ29udGluZW50YWwKMTAuICoqU2VtZXN0cmUgVGVjOioqIFJlZm9yY8OpIGVuIEVzcGHDsWEgZGl2ZXJzb3MgdGVtYXMgZGUgUmVjdXJzb3MgaHVtYW5vcywgRmluYW56YXMgeSBhcHJlbmRpIGEgaGFjZXIgaW1wdWVzdG9zIGVuIEVzcGHDsWEgZGViaWRvIGEgdW5hIG1hdGVyaWEgZGUgRmlzY2FiaWxpZGFkLgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6Ymx1ZTsiPiBBY3RpdmlkYWQgMi4gSGVyc2hleSdzIDwvc3Bhbj4KCiFbXShodHRwczovL2kwLndwLmNvbS9nZWVrYW5kbGlmZS5jb20ubXgvd3AtY29udGVudC91cGxvYWRzLzIwMjMvMDkvSGVyc2hleS1NZXhpY28tcHJlc2VudGEtbGEtbnVldmEtYmFycmEtSGVyc2hleXMtQ29jb2EtQ3JlYXRpb25zLWhlY2hhLWNvbi1jYWNhby0xMDAtZGUtb3JpZ2VuLW1leGljYW5vLmpwZz9maXQ9MTIwMCUyQzYxMSZzc2w9MSkKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+IENyZWFyIGxhIHNlcmllIGRlIHRpZW1wbyA8L3NwYW4+CmBgYHtyfQp2ZW50YXMgPC0gcmVhZF9leGNlbCgiL1VzZXJzL2h1Z29lbnJpcXVlL0Rlc2t0b3AvVW5pdmVyc2lkYWQvOHZvXCBTZW1lc3RyZS9HZW5lcmFjaW/MgW5cIGRlXCBFc2NlbmFyaW9zL00xL0FjdDIvVmVudGFzX0hpc3TDs3JpY2FzX0xlY2hpdGFzLnhsc3giKQpzdHIodmVudGFzKQpzdF92ZW50YXMgPC0gdHMoZGF0YT12ZW50YXMsIHN0YXJ0PWMoMjAxNywgMSksIGZyZXF1ZW5jeSA9IDEyKQpgYGAKCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6Ymx1ZTsiPiBDcmVhciBlbCBtb2RlbyBBUklNQSA8L3NwYW4+CmBgYHtyfQptb2RlbG9fdmVudGFzIDwtIGF1dG8uYXJpbWEoc3RfdmVudGFzKQptb2RlbG9fdmVudGFzCnN1bW1hcnkobW9kZWxvX3ZlbnRhcykKYGBgCgojIyA8c3BhbiBzdHlsZT0gImNvbG9yOmJsdWU7Ij4gR2VuZXJhciBlbCBwcm9uw7NzdGljbyA8L3NwYW4+CmBgYHtyfQpwcm9ub3N0aWNvX3ZlbnRhcyA8LSBmb3JlY2FzdChtb2RlbG9fdmVudGFzLCBsZXZlbCA9IGMoOTUpLCBoID0gMTIpCnByb25vc3RpY29fdmVudGFzCnBsb3QocHJvbm9zdGljb192ZW50YXMpCmBgYAoKCgo=