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

  1. 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.

  2. 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ó.

  3. Pensamiento Estadístico Primr contacto con estadística en el Tec.

  4. Comunicación que Inspira Aprender el método IKIGAI y a cómo comunicar

  5. Estategias de mercado y diferenciación Mala experiencia con socio formador, nada abiertos al cambio. Buen equipo de trabajo.

  6. Evaluación de proyectos de inversión No recuerdo mucho de mi experiencia de esa materia

  7. Manipulación de datos Primer contacto con R, primeras consultas y proyecto básico.

  8. Minería de datos Materia que debería de ser un bloque y durar más debido a lo importante y extenso del contenido.

  9. Bootcamp de programación Buen refuerzo de R.

  10. 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