
Instalar paquetes y librerías
#install.packages("forecast")
library(forecast)
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
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: 1. Precio de acciones 2. Niveles de
inveentario 3. Rotación de personal 4. Ventas 5. PIB (GDP)
Crear la serie de tiempo
Ejemplo: Los siguientes datos de producción trimestral inician en el
primer trimestre de 2020. Se busca pronosticar la producción de los
siguientes 5 trimestres.
produccion <- c(50,53,55,57,55,60)
# En "start" el primer argumento es el año, y el segundo la cantidad de periodos en 1 año.
st_produccion <- ts(data=produccion, start= c(2020,1), frequency=4)
#En este caso, la serie de tiempo inicia en 2020, en el 1er trimestre.
#MENSUAL: st_produccion <- ts(data=produccion, start= c(2020,8))
#frequency=4 En este caso, la serie de tiempo inicia en 2020, en el 8vo mes.
Crear el modeo ARIMA
ARIMA significa Modelo Autorregresivo Integrado de
Promedio Móvil, en inglés.
modelo_produccion <- auto.arima(st_produccion, D=1) # 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)
## 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 (Porcentaje de Error Promedio Absoluto)
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. México rumbo al 2050
En equipos de 2 o 3, seleccionar un estado de México, obtener los
datos históricos de su población, generar un pronoóstico hasta 2050.
Instalar paquetes y librerías
library(readxl)
Cargar archivo
pob_sonora <- read_excel("C:\\Users\\serva\\Downloads\\pob_sonora_1990_2020.xlsx")
Crear la serie de tiempo
st_pob_sonora <- ts(data=pob_sonora$Poblacion, 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)

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.
Aplicación
de Shiny
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 3.
Reflexión de mis materias
El Rol de los Negocios en la Sociedad Fue mi primer experiencia
en el Tec con el nuevo modelo de estudio. No fue la materia más
entretenida, pero la disfruté porque fue la primer entrando.
Decisiones financieras Sinceramente no recuerdo mucho de esa
materia, ni al profesor, por lo tanto no tengo una opinión, la tuve en
línea y eso no ayudó.
Pensamiento Estadístico Primr contacto con estadística en el
Tec.
Comunicación que Inspira Aprender el método IKIGAI y a cómo
comunicar
Estategias de mercado y diferenciación Mala experiencia con socio
formador, nada abiertos al cambio. Buen equipo de trabajo.
Evaluación de proyectos de inversión No recuerdo mucho de mi
experiencia de esa materia
Manipulación de datos Primer contacto con R, primeras consultas y
proyecto básico.
Minería de datos Materia que debería de ser un bloque y durar más
debido a lo importante y extenso del contenido.
Bootcamp de programación Buen refuerzo de R.
Semestre TEC (Estancia en CEMEX) Buena experiencia laboral
enfocada en análisis de datos. Mucho uso de Power BI.
Actividad 2. Hershey’s.

Crear la serie de tiempo
ventas <- read_excel("C:\\Users\\serva\\Downloads\\Ventaslechitas.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 modelo 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.8979
## s.e. 0.1551 0.2047 14.5026
##
## sigma^2 = 202701: 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.8979
## s.e. 0.1551 0.2047 14.5026
##
## sigma^2 = 202701: log likelihood = -181.5
## AIC=371 AICc=373.11 BIC=375.72
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 25.22158 343.864 227.17 0.08059932 0.7069542 0.06491044 0.2081026
Generar 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.28 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.90 38246.40
## Jul 2020 37151.04 36005.73 38296.34
## Aug 2020 38564.64 37418.70 39710.58
## Sep 2020 38755.22 37609.03 39901.42
## Oct 2020 39779.02 38632.72 40925.32
## Nov 2020 38741.63 37595.28 39887.97
## Dec 2020 38645.86 37499.50 39792.22
plot(pronostico_ventas)

#Aplicación de Shiny. Hershey’s
Aplicación
de Shiny
LS0tDQp0aXRsZTogIkFjdGl2aWRhZCAyIg0KYXV0aG9yOiAiU2VydmFuZG8gQmFjYSBEw61heiINCmRhdGU6ICIyMDI1LTA4LTE0Ig0KZW5jb2Rpbmc6IFVURi04DQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KLS0tDQoNCg0KIVtdKGh0dHBzOi8vc3VwcG9ydC5taW5pdGFiLmNvbS9lcy1teC9taW5pdGFiL21lZGlhL25vdHJhbnNsYXRlL3RzZGVjX2EuZ2lmKQ0KDQojIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+IEluc3RhbGFyIHBhcXVldGVzIHkgbGlicmVyw61hcyA8L3NwYW4+DQpgYGB7cn0NCiNpbnN0YWxsLnBhY2thZ2VzKCJmb3JlY2FzdCIpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KYGBgDQoNCiMgPHNwYW4gc3R5bGU9ICJjb2xvcjpibHVlOyI+IEVqZW1wbG8uIFByb2R1Y2Npw7NuIDwvc3Bhbj4NCg0KIyMgPHNwYW4gc3R5bGU9ICJjb2xvcjpibHVlOyI+IENvbnRleHRvIDwvc3Bhbj4NClVuYSAqKnNlcmllIGRlIHRpZW1wbyoqIGVzIHVuYSBjb2xlY2Npw7NuIGRlIG9ic2VydmFjaW9uZXMgc29icmUgdW4gZGV0ZXJtaW5hZG8gZmVuw7NtZW5vIGVmZWN0dWFkYXMgZW4gbW9tZW50b3MgZGUgdGllbXBvIHN1Y2VzaXZvcywgdXN1YWxtZW50ZSBlcXVpZXNwYWNpYWRvcy4NCg0KRWplbXBsb3MgZGUgc2VyaWVzIGRlIHRpZW1wbzoNCjEuIFByZWNpbyBkZSBhY2Npb25lcw0KMi4gTml2ZWxlcyBkZSBpbnZlZW50YXJpbw0KMy4gUm90YWNpw7NuIGRlIHBlcnNvbmFsDQo0LiBWZW50YXMNCjUuIFBJQiAoR0RQKQ0KDQoNCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6Ymx1ZTsiPiBDcmVhciBsYSBzZXJpZSBkZSB0aWVtcG8gPC9zcGFuPg0KRWplbXBsbzogTG9zIHNpZ3VpZW50ZXMgZGF0b3MgZGUgcHJvZHVjY2nDs24gdHJpbWVzdHJhbCBpbmljaWFuIGVuIGVsIHByaW1lciB0cmltZXN0cmUgZGUgMjAyMC4gU2UgYnVzY2EgcHJvbm9zdGljYXIgbGEgcHJvZHVjY2nDs24gZGUgbG9zIHNpZ3VpZW50ZXMgNSB0cmltZXN0cmVzLg0KYGBge3J9DQpwcm9kdWNjaW9uIDwtIGMoNTAsNTMsNTUsNTcsNTUsNjApDQojIEVuICJzdGFydCIgZWwgcHJpbWVyIGFyZ3VtZW50byBlcyBlbCBhw7FvLCB5IGVsIHNlZ3VuZG8gbGEgY2FudGlkYWQgZGUgcGVyaW9kb3MgZW4gMSBhw7FvLg0KDQpzdF9wcm9kdWNjaW9uIDwtIHRzKGRhdGE9cHJvZHVjY2lvbiwgc3RhcnQ9IGMoMjAyMCwxKSwgZnJlcXVlbmN5PTQpDQojRW4gZXN0ZSBjYXNvLCBsYSBzZXJpZSBkZSB0aWVtcG8gaW5pY2lhIGVuIDIwMjAsIGVuIGVsIDFlciB0cmltZXN0cmUuDQojTUVOU1VBTDogc3RfcHJvZHVjY2lvbiA8LSB0cyhkYXRhPXByb2R1Y2Npb24sIHN0YXJ0PSBjKDIwMjAsOCkpDQojZnJlcXVlbmN5PTQgRW4gZXN0ZSBjYXNvLCBsYSBzZXJpZSBkZSB0aWVtcG8gaW5pY2lhIGVuIDIwMjAsIGVuIGVsIDh2byBtZXMuDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9ICJjb2xvcjpibHVlOyI+IENyZWFyIGVsIG1vZGVvIEFSSU1BIDwvc3Bhbj4NCioqQVJJTUEqKiBzaWduaWZpY2EgTW9kZWxvIEF1dG9ycmVncmVzaXZvIEludGVncmFkbyBkZSBQcm9tZWRpbyBNw7N2aWwsIGVuIGluZ2zDqXMuDQpgYGB7cn0NCm1vZGVsb19wcm9kdWNjaW9uIDwtIGF1dG8uYXJpbWEoc3RfcHJvZHVjY2lvbiwgRD0xKSAjIERpZmVyZW5jaWFjacOzbiBFc3RhY2lvbmFsDQptb2RlbG9fcHJvZHVjY2lvbg0Kc3VtbWFyeShtb2RlbG9fcHJvZHVjY2lvbikNCiMgQWwgY29tcGFyYXIgbW9kZWxvcywgc2VsZWNjaW9uYW1vcyBlbCBxdWUgdGVuZ2EgZWwgbWVub3IgTUFQRSAoUG9yY2VudGFqZSBkZSBFcnJvciBQcm9tZWRpbyBBYnNvbHV0bykNCmBgYA0KDQojIyA8c3BhbiBzdHlsZT0gImNvbG9yOmJsdWU7Ij4gR2VuZXJhciBlbCBwcm9uw7NzdGljbyA8L3NwYW4+DQpgYGB7cn0NCnByb25vc3RpY29fcHJvZHVjY2lvbiA8LSBmb3JlY2FzdChtb2RlbG9fcHJvZHVjY2lvbiwgbGV2ZWw9Yyg5NSksIGg9NSkNCiNTaSBubyBub3MgZGljZW4gb3RyYSBjb3NhLCBlbCBuaXZlbCBkZSBjb25maWFiaWxpZGFkIGVzIDk1JS4gTG9zIHBlcmlvZG9zIGEgcHJvbm9zdGljYXIgZXMgaC4NCnByb25vc3RpY29fcHJvZHVjY2lvbg0KcGxvdChwcm9ub3N0aWNvX3Byb2R1Y2Npb24pDQpgYGANCg0KIyA8c3BhbiBzdHlsZT0gImNvbG9yOmJsdWU7Ij4gRWplcmNpY2lvIDEuIE3DqXhpY28gcnVtYm8gYWwgMjA1MCA8L3NwYW4+DQpFbiBlcXVpcG9zIGRlIDIgbyAzLCBzZWxlY2Npb25hciB1biBlc3RhZG8gZGUgTcOpeGljbywgb2J0ZW5lciBsb3MgZGF0b3MgaGlzdMOzcmljb3MgZGUgc3UgcG9ibGFjacOzbiwgZ2VuZXJhciB1biBwcm9ub8Ozc3RpY28gaGFzdGEgMjA1MC4NCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij4gSW5zdGFsYXIgcGFxdWV0ZXMgeSBsaWJyZXLDrWFzIDwvc3Bhbj4NCmBgYHtyfQ0KbGlicmFyeShyZWFkeGwpDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij4gQ2FyZ2FyIGFyY2hpdm8gPC9zcGFuPg0KYGBge3J9DQpwb2Jfc29ub3JhIDwtIHJlYWRfZXhjZWwoIkM6XFxVc2Vyc1xcc2VydmFcXERvd25sb2Fkc1xccG9iX3Nvbm9yYV8xOTkwXzIwMjAueGxzeCIpDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij4gQ3JlYXIgbGEgc2VyaWUgZGUgdGllbXBvIDwvc3Bhbj4NCmBgYHtyfQ0Kc3RfcG9iX3Nvbm9yYSA8LSB0cyhkYXRhPXBvYl9zb25vcmEkUG9ibGFjaW9uLCBzdGFydD0gYygxOTkwKSwgZnJlcXVlbmN5PS4yKQ0KI0VuIGVzdGUgY2FzbywgbGEgc2VyaWUgZGUgdGllbXBvIGluaWNpYSBlbiAyMDIwLCBlbiBlbCAxZXIgdHJpbWVzdHJlLg0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6Ymx1ZTsiPiBDcmVhciBlbCBtb2RlbyBBUklNQSA8L3NwYW4+DQoqKkFSSU1BKiogc2lnbmlmaWNhIE1vZGVsbyBBdXRvcnJlZ3Jlc2l2byBJbnRlZ3JhZG8gZGUgUHJvbWVkaW8gTcOzdmlsLCBlbiBpbmdsw6lzLg0KYGBge3J9DQptb2RlbG9fcGJzb25vcmEgPC0gYXV0by5hcmltYShzdF9wb2Jfc29ub3JhKSAjIERpZmVyZW5jaWFjacOzbiBFc3RhY2lvbmFsDQptb2RlbG9fcGJzb25vcmENCnN1bW1hcnkobW9kZWxvX3Bic29ub3JhKQ0KIyBBbCBjb21wYXJhciBtb2RlbG9zLCBzZWxlY2Npb25hbW9zIGVsIHF1ZSB0ZW5nYSBlbCBtZW5vciBNQVBFIChQb3JjZW50YWplIGRlIEVycm9yIFByb21lZGlvIEFic29sdXRvKQ0KYGBgDQojIyA8c3BhbiBzdHlsZT0gImNvbG9yOmJsdWU7Ij4gR2VuZXJhciBlbCBwcm9uw7NzdGljbyA8L3NwYW4+DQpgYGB7cn0NCnByb25vc3RpY29fcGJzb25vcmEgPC0gZm9yZWNhc3QobW9kZWxvX3Bic29ub3JhLCBsZXZlbD1jKDk1KSwgaD03KQ0KI1NpIG5vIG5vcyBkaWNlbiBvdHJhIGNvc2EsIGVsIG5pdmVsIGRlIGNvbmZpYWJpbGlkYWQgZXMgOTUlLiBMb3MgcGVyaW9kb3MgYSBwcm9ub3N0aWNhciBlcyBoLg0KcHJvbm9zdGljb19wYnNvbm9yYQ0KcGxvdChwcm9ub3N0aWNvX3Bic29ub3JhKQ0KYGBgDQoNCiMgPHNwYW4gc3R5bGU9ICJjb2xvcjpibHVlOyI+IEVqZXJjaWNpbyAyLiBBcGxpY2FjacOzbiBkZSBTaGlueSA8L3NwYW4+DQpBZ3JlZ2FyIHVuYSBwZXN0YcOxYSBlbiBsYSBhcGxpY2FjacOzbiBkZSBTaGlueSBjb24gZWwgZWplcmNpY2lvIE3DqXhpY28gcnVtYm8gYWwgMjA1MC4gRW4gZWwgbWVuw7ogc2UgZGViZSBzZWxlY2Npb25hciBsYSBjYW50aWRhZCBkZSBhw7FvcyBhIHByb25vc3RpY2FyLg0KDQpbQXBsaWNhY2nDs24gZGUgU2hpbnldKGh0dHBzOi8vcGgxZWQwLXNlcnZhLWJhY2Euc2hpbnlhcHBzLmlvL0VzdGFkaXN0aWNhTXVsdGl2YXJpYW50ZS8pDQoNCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6Ymx1ZTsiPiBDb25jbHVzacOzbiA8L3NwYW4+DQpFbiBudWVzdHJvIHByb27Ds3N0aWNvIHNlIHJlZmxlamEgdW4gY29uc3RhbnRlIGNyZWNpbWllbnRvIGVuIGxhIHBvYmxhY2nDs24gZGUgU29ub3JhLiBFbCDDumx0aW1vIGNlbnNvIHJlYWxpemFkbyBwb3IgSU5FR0kgZW4gMjAyMCByZWdpc3Ryw7MgdW5hIHBvYmxhY2nDs24gZGUgMiw5NDQsODQwIGVuIFNvbm9yYSwgbWllbnRyYXMgcXVlIG51ZXN0cm8gcHJvbsOzc3RpY28gcmVmbGVqYSB1bmEgcG9ibGFjacOzbiBsaWdlcmFtZW50ZSBtYXlvciBhIGxvcyA0IG1pbGxvbmVzIGRlIGhhYml0YW50ZXMuDQoNCg0KIyA8c3BhbiBzdHlsZT0gImNvbG9yOmJsdWU7Ij4gRWplcmNpY2lvIDMuIDwvc3Bhbj4NClJlZmxleGnDs24gZGUgbWlzIG1hdGVyaWFzDQoNCjEuIEVsIFJvbCBkZSBsb3MgTmVnb2Npb3MgZW4gbGEgU29jaWVkYWQNCkZ1ZSBtaSBwcmltZXIgZXhwZXJpZW5jaWEgZW4gZWwgVGVjIGNvbiBlbCBudWV2byBtb2RlbG8gZGUgZXN0dWRpby4gTm8gZnVlIGxhIG1hdGVyaWEgbcOhcyBlbnRyZXRlbmlkYSwgcGVybyBsYSBkaXNmcnV0w6kgcG9ycXVlIGZ1ZSBsYSBwcmltZXIgZW50cmFuZG8uDQoNCjIuIERlY2lzaW9uZXMgZmluYW5jaWVyYXMNClNpbmNlcmFtZW50ZSBubyByZWN1ZXJkbyBtdWNobyBkZSBlc2EgbWF0ZXJpYSwgbmkgYWwgcHJvZmVzb3IsIHBvciBsbyB0YW50byBubyB0ZW5nbyB1bmEgb3BpbmnDs24sIGxhIHR1dmUgZW4gbMOtbmVhIHkgZXNvIG5vIGF5dWTDsy4NCg0KMy4gUGVuc2FtaWVudG8gRXN0YWTDrXN0aWNvDQpQcmltciBjb250YWN0byBjb24gZXN0YWTDrXN0aWNhIGVuIGVsIFRlYy4NCg0KNC4gQ29tdW5pY2FjacOzbiBxdWUgSW5zcGlyYQ0KQXByZW5kZXIgZWwgbcOpdG9kbyBJS0lHQUkgeSBhIGPDs21vIGNvbXVuaWNhcg0KDQo1LiBFc3RhdGVnaWFzIGRlIG1lcmNhZG8geSBkaWZlcmVuY2lhY2nDs24NCk1hbGEgZXhwZXJpZW5jaWEgY29uIHNvY2lvIGZvcm1hZG9yLCBuYWRhIGFiaWVydG9zIGFsIGNhbWJpby4gQnVlbiBlcXVpcG8gZGUgdHJhYmFqby4NCg0KNi4gRXZhbHVhY2nDs24gZGUgcHJveWVjdG9zIGRlIGludmVyc2nDs24NCk5vIHJlY3VlcmRvIG11Y2hvIGRlIG1pIGV4cGVyaWVuY2lhIGRlIGVzYSBtYXRlcmlhDQoNCjcuIE1hbmlwdWxhY2nDs24gZGUgZGF0b3MNClByaW1lciBjb250YWN0byBjb24gUiwgcHJpbWVyYXMgY29uc3VsdGFzIHkgcHJveWVjdG8gYsOhc2ljby4NCg0KOC4gTWluZXLDrWEgZGUgZGF0b3MNCk1hdGVyaWEgcXVlIGRlYmVyw61hIGRlIHNlciB1biBibG9xdWUgeSBkdXJhciBtw6FzIGRlYmlkbyBhIGxvIGltcG9ydGFudGUgeSBleHRlbnNvIGRlbCBjb250ZW5pZG8uDQoNCjkuIEJvb3RjYW1wIGRlIHByb2dyYW1hY2nDs24NCkJ1ZW4gcmVmdWVyem8gZGUgUi4NCg0KMTAuIFNlbWVzdHJlIFRFQyAoRXN0YW5jaWEgZW4gQ0VNRVgpDQpCdWVuYSBleHBlcmllbmNpYSBsYWJvcmFsIGVuZm9jYWRhIGVuIGFuw6FsaXNpcyBkZSBkYXRvcy4gTXVjaG8gdXNvIGRlIFBvd2VyIEJJLg0KDQojIDxzcGFuIHN0eWxlPSAiY29sb3I6Ymx1ZTsiPiBBY3RpdmlkYWQgMi4gSGVyc2hleSdzLiA8L3NwYW4+DQohW10oaHR0cHM6Ly9tZWRpYS5naXBoeS5jb20vYXZhdGFycy9IQ1dTb2NpYWwvZnRJTWRvelBJTGRsLmdpZikNCg0KIyA8c3BhbiBzdHlsZT0gImNvbG9yOmJsdWU7Ij4gQ3JlYXIgbGEgc2VyaWUgZGUgdGllbXBvIDwvc3Bhbj4NCmBgYHtyfQ0KdmVudGFzIDwtIHJlYWRfZXhjZWwoIkM6XFxVc2Vyc1xcc2VydmFcXERvd25sb2Fkc1xcVmVudGFzbGVjaGl0YXMueGxzeCIpDQpzdHIodmVudGFzKQ0Kc3RfdmVudGFzIDwtIHRzKGRhdGE9dmVudGFzLCBzdGFydD1jKDIwMTcsMSksIGZyZXF1ZW5jeT0xMikNCmBgYA0KDQojIzxzcGFuIHN0eWxlPSAiY29sb3I6Ymx1ZTsiPiBDcmVhciBlbCBtb2RlbG8gQVJJTUEgPC9zcGFuPg0KYGBge3J9DQptb2RlbG9fdmVudGFzIDwtIGF1dG8uYXJpbWEoc3RfdmVudGFzKQ0KbW9kZWxvX3ZlbnRhcw0Kc3VtbWFyeShtb2RlbG9fdmVudGFzKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6Ymx1ZTsiPiBHZW5lcmFyIHByb27Ds3N0aWNvIDwvc3Bhbj4NCmBgYHtyfQ0KcHJvbm9zdGljb192ZW50YXMgPC0gZm9yZWNhc3QobW9kZWxvX3ZlbnRhcywgbGV2ZWwgPSBjKDk1KSwgaCA9IDEyKQ0KcHJvbm9zdGljb192ZW50YXMNCnBsb3QocHJvbm9zdGljb192ZW50YXMpDQpgYGANCg0KI0FwbGljYWNpw7NuIGRlIFNoaW55LiBIZXJzaGV5J3MNCg0KW0FwbGljYWNpw7NuIGRlIFNoaW55XShodHRwczovL3BoMWVkMC1zZXJ2YS1iYWNhLnNoaW55YXBwcy5pby9Fc3RhZGlzdGljYU11bHRpdmFyaWFudGUvKQ0K