EJERCICIO 5

“GASTO EN SALUD (% del PIB) y ESPERANZA DE VIDA AL NACER en países de América Latina”

Instrucciones: Genera el mejor modelo de predicción usando datos reales del Banco Mundial (World Bank / World Development Indicators). ¿Cuál es el pronóstico de esperanza de vida para cada país si en 2024 aumentaran 10% su gasto en salud (como % del PIB) respecto a 2020? Discute si conviene limpiar los datos nulos (NA) o dejarlos, y qué tan honesto es el pronóstico resultante.

Indicadores usados (códigos oficiales del Banco Mundial):

  • Y = Esperanza de vida al nacer, total (años) -> SP.DYN.LE00.IN
  • X = Gasto corriente en salud (% del PIB) -> SH.XPD.CHEX.GD.ZS

Países: México, Brasil, Argentina, Colombia, Chile, Perú.

PAQUETES

#install.packages("plm")
#install.packages("gplots")
#install.packages("WDI")     # paquete oficial para importar datos del Banco Mundial
#install.packages("ggplot2")
library(plm)
library(gplots)
library(WDI)
library(ggplot2)

OPCIÓN A (recomendada): IMPORTAR LA BASE DE DATOS EN VIVO DESDE EL BANCO MUNDIAL

Esto descarga la serie MÁS ACTUALIZADA directamente de la API del Banco Mundial. Como el Banco Mundial suele publicar el gasto en salud con 2-3 años de rezago, es NORMAL que los años más recientes vengan con NA - eso es justamente parte de la honestidad de los datos que se pide analizar (ver conclusión al final).

paises <- c("MX","BR","AR","CO","CL","PE")

panel_wdi <- WDI(
  country   = paises,
  indicator = c(Esperanza = "SP.DYN.LE00.IN",
                GastoSalud = "SH.XPD.CHEX.GD.ZS"),
  start = 2010, end = 2023
)

# Revisa cuántos NA trae cada columna (importante para la discusión de limpieza)
colSums(is.na(panel_wdi[, c("Esperanza","GastoSalud")]))
##  Esperanza GastoSalud 
##          0          0
head(panel_wdi)
##     country iso2c iso3c year Esperanza GastoSalud
## 1 Argentina    AR   ARG 2010    75.680   9.485244
## 2 Argentina    AR   ARG 2011    76.100   9.510424
## 3 Argentina    AR   ARG 2012    75.802   9.885188
## 4 Argentina    AR   ARG 2013    75.829   9.920915
## 5 Argentina    AR   ARG 2014    76.268   9.797730
## 6 Argentina    AR   ARG 2015    76.600  10.273642

OPCIÓN B (respaldo offline): mismos datos, verificados manualmente

Por si no hay internet en el salón, o para comparar contra la descarga en vivo. Estos valores 2019-2020 fueron verificados contra el Banco Mundial (vía FRED, Federal Reserve Bank of St. Louis, que replica la serie WDI tal cual). A partir de 2021 el indicador de gasto en salud aún no estaba público al momento de preparar este ejercicio -> se deja como NA a propósito.

df5 <- data.frame(
  Pais = rep(c("Mexico","Brasil","Argentina","Colombia","Chile","Peru"), each = 5),
  Anio = rep(2019:2023, times = 6),
  GastoSalud = c(
    5.5, 6.2, NA, NA, NA,      # Mexico
    9.6, 10.3, NA, NA, NA,     # Brasil
    9.5, 10.0, NA, NA, NA,     # Argentina
    7.7, 9.0, NA, NA, NA,      # Colombia
    9.3, 9.8, NA, NA, NA,      # Chile
    5.2, 6.4, NA, NA, NA       # Peru
  ),
  Esperanza = c(
    74.530, 70.449, 69.750, 73.973, 75.069,  # Mexico
    75.809, 74.506, 73.038, 74.872, 75.848,  # Brasil
    76.847, 75.878, 73.948, 75.806, 77.395,  # Argentina
    76.793, 74.757, 72.698, 76.508, 77.725,  # Colombia
    80.324, 79.349, 78.876, 79.176, 81.167,  # Chile
    76.275, 73.832, 71.596, 76.834, 77.740   # Peru
  )
)

df5 <- pdata.frame(df5, index = c("Pais","Anio"))

VISUALIZACIÓN DE LA BASE DE DATOS

ggplot(as.data.frame(df5), aes(x = as.numeric(as.character(Anio)), y = Esperanza,
                                 color = Pais, group = Pais)) +
  geom_line(linewidth = 1) + geom_point() +
  labs(title = "Esperanza de vida al nacer, 2019-2023",
       x = "Año", y = "Años de esperanza de vida") +
  theme_minimal()

INTERPRETACIÓN: se observa una caída generalizada en 2020-2021 (pandemia COVID-19) y una recuperación posterior. Esto es una señal de que hay un choque temporal común a todos los países, algo que hay que tener en cuenta al interpretar el modelo.

PRUEBA DE HETEROGENEIDAD

plotmeans(Esperanza ~ Pais, data = df5)

INTERPRETACIÓN: los promedios por país están muy lejos entre sí (Chile ~79-80 años vs México/Perú ~73-74 años) -> hay heterogeneidad clara entre países, por lo que NO conviene usar regresión simple agrupada; hay que comparar Pooled, Efectos Fijos y Efectos Aleatorios.

MODELOS DE DATOS PANEL

Nota: plm excluye automáticamente las filas con NA en las variables usadas, así que el panel queda “no balanceado” (2 años por país en vez de 5) sin que tengamos que borrar manualmente esas filas del data frame.

# Opcion 1 ~ Modelo de regresion Agrupada (Pooled)
pooled5 <- plm(Esperanza ~ GastoSalud, data = df5, model = "pooling")
summary(pooled5)
## Pooling Model
## 
## Call:
## plm(formula = Esperanza ~ GastoSalud, data = df5, model = "pooling")
## 
## Balanced Panel: n = 6, T = 2, N = 12
## 
## Residuals:
##    Min. 1st Qu.  Median 3rd Qu.    Max. 
## -4.0906 -1.1328 -0.2791  1.5839  3.8712 
## 
## Coefficients:
##             Estimate Std. Error t-value Pr(>|t|)    
## (Intercept) 70.71324    3.19972 22.0998 8.07e-10 ***
## GastoSalud   0.61716    0.38063  1.6214    0.136    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    72.252
## Residual Sum of Squares: 57.211
## R-Squared:      0.20817
## Adj. R-Squared: 0.12899
## F-statistic: 2.629 on 1 and 10 DF, p-value: 0.13599
# Opcion 2 ~ Modelo de Efectos Fijos (Within)
within5 <- plm(Esperanza ~ GastoSalud, data = df5, model = "within")
summary(within5)
## Oneway (individual) effect Within Model
## 
## Call:
## plm(formula = Esperanza ~ GastoSalud, data = df5, model = "within")
## 
## Balanced Panel: n = 6, T = 2, N = 12
## 
## Residuals:
## Argentina-2019 Argentina-2020    Brasil-2019    Brasil-2020     Chile-2019 
##       -0.07511        0.07511       -0.13195        0.13195       -0.07211 
##     Chile-2020  Colombia-2019  Colombia-2020    Mexico-2019    Mexico-2020 
##        0.07211       -0.43698        0.43698        1.25705       -1.25705 
##      Peru-2019      Peru-2020 
##       -0.12156        0.12156 
## 
## Coefficients:
##            Estimate Std. Error t-value Pr(>|t|)  
## GastoSalud -2.23844    0.56109 -3.9895  0.01043 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    15.178
## Residual Sum of Squares: 3.6283
## R-Squared:      0.76095
## Adj. R-Squared: 0.47408
## F-statistic: 15.9158 on 1 and 5 DF, p-value: 0.010432
# Prueba F (Pooled vs Within)
pFtest(within5, pooled5)
## 
##  F test for individual effects
## 
## data:  Esperanza ~ GastoSalud
## F = 14.768, df1 = 5, df2 = 5, p-value = 0.005133
## alternative hypothesis: significant effects
# Opcion 3 ~ Modelo de Efectos Aleatorios (Random)
random5 <- plm(Esperanza ~ GastoSalud, data = df5, model = "random")
summary(random5)
## Oneway (individual) effect Random Effect Model 
##    (Swamy-Arora's transformation)
## 
## Call:
## plm(formula = Esperanza ~ GastoSalud, data = df5, model = "random")
## 
## Balanced Panel: n = 6, T = 2, N = 12
## 
## Effects:
##                  var std.dev share
## idiosyncratic 0.7257  0.8519 0.159
## individual    3.8399  1.9596 0.841
## theta: 0.7062
## 
## Residuals:
##     Min.  1st Qu.   Median  3rd Qu.     Max. 
## -3.16935 -0.49269  0.46743  0.73465  1.74791 
## 
## Coefficients:
##             Estimate Std. Error z-value Pr(>|z|)    
## (Intercept) 79.66383    4.98737 15.9731   <2e-16 ***
## GastoSalud  -0.47327    0.58493 -0.8091   0.4185    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    20.105
## Residual Sum of Squares: 18.87
## R-Squared:      0.061442
## Adj. R-Squared: -0.032413
## Chisq: 0.654648 on 1 DF, p-value: 0.41846
# Prueba de Hausman
# INTERPRETACION: Si p<0.05, usar efectos fijos; si p>0.05, usar efectos aleatorios
phtest(random5, within5)
## 
##  Hausman Test
## 
## data:  Esperanza ~ GastoSalud
## chisq = 114.04, df = 1, p-value < 2.2e-16
## alternative hypothesis: one model is inconsistent

CONCLUSIÓN DE SELECCIÓN DE MODELO: La prueba F rechaza el modelo Pooled (p ≈ 0.005), confirmando que sí existen efectos específicos de cada país que el modelo agrupado ignora. Con solo 2 años disponibles por país (T=2) la prueba de Hausman puede volverse numéricamente inestable (problema típico de muestras muy cortas) — en ese caso, la recomendación técnica es usar Efectos Fijos, porque es razonable pensar que el nivel de gasto en salud de un país está correlacionado con características propias no observadas del país (calidad del sistema de salud, nivel de ingreso, geografía), lo cual violaría el supuesto clave de Efectos Aleatorios.

ADVERTENCIA IMPORTANTE SOBRE CAUSALIDAD (léelo antes de reportar el coeficiente)

Con solo 2019 y 2020 disponibles, la única “variación dentro de cada país” que el modelo de Efectos Fijos puede usar es el cambio 2019→2020, es decir, el choque de la pandemia: la esperanza de vida CAYÓ en casi todos los países en 2020 mientras que el gasto en salud como % del PIB SUBIÓ (porque el PIB se contrajo y el gasto en salud aumentó). Esto genera una correlación negativa que refleja el choque de COVID, no una relación causal real entre gastar más en salud y vivir menos. Es el mismo tipo de trampa que el Ejercicio 3 mostraba con la regresión simple de publicidad y ventas: el resultado “ingenuo” puede tener el signo equivocado si no se controla bien la fuente de variación. La solución correcta es ampliar el panel (más años, ya sin el choque de un único evento dominando la muestra) — ver Opción A.

PREDICCIÓN: +10% de gasto en salud en 2024 respecto a 2020

intercepto5 <- coef(within5)  # within no tiene intercepto comun; se usan efectos individuales
efectos5 <- fixef(within5)

df5_pronostico <- data.frame(
  Pais = c("Mexico","Brasil","Argentina","Colombia","Chile","Peru"),
  GastoSalud = c(6.2,10.3,10.0,9.0,9.8,6.4) * 1.10  # +10% respecto a 2020
)

df5_pronostico$Esperanza_pred <- efectos5[df5_pronostico$Pais] +
  coef(within5)["GastoSalud"] * df5_pronostico$GastoSalud

df5_pronostico
##        Pais GastoSalud Esperanza_pred
## 1    Mexico       6.82       70.31821
## 2    Brasil      11.33       72.06846
## 3 Argentina      11.00       73.56445
## 4  Colombia       9.90       72.30542
## 5     Chile      10.78       77.08322
## 6      Peru       7.04       72.27784

CONCLUSIÓN: Con los datos actualmente públicos (2019-2020), el modelo de Efectos Fijos es estadísticamente el más adecuado (la prueba F rechaza el modelo agrupado con p ≈ 0.005), pero el coeficiente obtenido está dominado por el choque de la pandemia y no debe interpretarse como el efecto causal real del gasto en salud sobre la esperanza de vida. Por eso el pronóstico de este bloque debe tomarse como un ejercicio metodológico, no como una predicción confiable para política pública. En cuanto el Banco Mundial publique 2021-2023 de gasto en salud (usando la Opción A de este documento), hay que volver a correr el modelo con el panel completo: al tener más años, el “ruido” de un solo choque (COVID) pesará mucho menos y el coeficiente estimado será más representativo de la relación de largo plazo.


¿HAY QUE LIMPIAR LOS DATOS NULOS (NA) O DEJARLOS?

Esta es la pregunta central que se planteó, y la respuesta corta es: no los limpies (no los imputes ni los borres a la fuerza) — déjalos como NA y usa plm, que maneja paneles no balanceados de forma nativa.

Por qué:

  1. Los NA aquí no son “datos sucios”, son datos que todavía no existen. El Banco Mundial publica el gasto en salud con 2-3 años de rezago (depende de que la OMS consolide la Global Health Expenditure Database). Faltan porque aún no se han medido, no porque haya un error de captura.

  2. Imputar (rellenar con la media, interpolar, etc.) inventaría información que no existe y haría que el modelo pareciera más preciso de lo que realmente es — eso es precisamente lo contrario de la “honestidad de los datos en las predicciones” que se pidió cuidar. Un profesional de datos que rellena huecos de esta forma sin dejarlo clarísimo en el reporte está maquillando la incertidumbre real del pronóstico.

  3. plm ya resuelve el problema técnico: al construir el pdata.frame con filas en NA, plm() simplemente usa las observaciones disponibles para cada país (panel no balanceado). No es necesario ni recomendable hacer na.omit() a mano antes de tiempo — sólo hazlo si vas a comparar el mismo número de observaciones entre modelos.

  4. Cuándo SÍ conviene limpiar/tratar los datos:

    • Si un NA es en realidad un error de captura (ej. “-999” o un texto donde debería ir un número): eso sí se corrige.
    • Si te interesa un país con demasiados años faltantes (ej. solo 1 de 10 años), considera excluir ese país en vez de imputarlo, porque su contribución al modelo sería casi puro ruido.
    • Si necesitas un panel estrictamente balanceado por requisito del método (poco común en plm, pero pasa en otras técnicas), documenta explícitamente qué filas quitaste y por qué.
  5. Repórtalo siempre: cualquier tabla o gráfica que muestres debe dejar claro cuántas observaciones tiene cada país y qué años faltan (como se hizo arriba con colSums(is.na(...))). Un pronóstico sin esa nota es un pronóstico que parece más sólido de lo que en realidad es.

LS0tDQp0aXRsZTogIkVKRVJDSUNJTyAzIC0gREFUT1MgUEFORUwgQ09OIEJBU0UgREUgREFUT1MgUkVBTCBERUwgQkFOQ08gTVVORElBTCINCmF1dGhvcjogIkx1Y2Vyb19TYWxhemFyX0EwMDgzNDg5MyINCmRhdGU6ICIyMDI2LTA4LTIwIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQ0KYGBgDQoNCiMgRUpFUkNJQ0lPIDUNCioqIkdBU1RPIEVOIFNBTFVEICglIGRlbCBQSUIpIHkgRVNQRVJBTlpBIERFIFZJREEgQUwgTkFDRVIgZW4gcGHDrXNlcyBkZSBBbcOpcmljYSBMYXRpbmEiKioNCg0KSW5zdHJ1Y2Npb25lczogR2VuZXJhIGVsIG1lam9yIG1vZGVsbyBkZSBwcmVkaWNjacOzbiB1c2FuZG8gZGF0b3MgcmVhbGVzIGRlbCBCYW5jbw0KTXVuZGlhbCAoV29ybGQgQmFuayAvIFdvcmxkIERldmVsb3BtZW50IEluZGljYXRvcnMpLiDCv0N1w6FsIGVzIGVsIHByb27Ds3N0aWNvIGRlDQplc3BlcmFuemEgZGUgdmlkYSBwYXJhIGNhZGEgcGHDrXMgc2kgZW4gMjAyNCBhdW1lbnRhcmFuIDEwJSBzdSBnYXN0byBlbiBzYWx1ZA0KKGNvbW8gJSBkZWwgUElCKSByZXNwZWN0byBhIDIwMjA/IERpc2N1dGUgc2kgY29udmllbmUgbGltcGlhciBsb3MgZGF0b3MgbnVsb3MgKE5BKQ0KbyBkZWphcmxvcywgeSBxdcOpIHRhbiBob25lc3RvIGVzIGVsIHByb27Ds3N0aWNvIHJlc3VsdGFudGUuDQoNCkluZGljYWRvcmVzIHVzYWRvcyAoY8OzZGlnb3Mgb2ZpY2lhbGVzIGRlbCBCYW5jbyBNdW5kaWFsKToNCg0KLSAqKlkgPSBFc3BlcmFuemEgZGUgdmlkYSBhbCBuYWNlciwgdG90YWwgKGHDsW9zKSoqIC0+IGBTUC5EWU4uTEUwMC5JTmANCi0gKipYID0gR2FzdG8gY29ycmllbnRlIGVuIHNhbHVkICglIGRlbCBQSUIpKiogLT4gYFNILlhQRC5DSEVYLkdELlpTYA0KDQpQYcOtc2VzOiBNw6l4aWNvLCBCcmFzaWwsIEFyZ2VudGluYSwgQ29sb21iaWEsIENoaWxlLCBQZXLDui4NCg0KIyMgUEFRVUVURVMNCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoInBsbSIpDQojaW5zdGFsbC5wYWNrYWdlcygiZ3Bsb3RzIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJXREkiKSAgICAgIyBwYXF1ZXRlIG9maWNpYWwgcGFyYSBpbXBvcnRhciBkYXRvcyBkZWwgQmFuY28gTXVuZGlhbA0KI2luc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KbGlicmFyeShwbG0pDQpsaWJyYXJ5KGdwbG90cykNCmxpYnJhcnkoV0RJKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KYGBgDQoNCiMjIE9QQ0nDk04gQSAocmVjb21lbmRhZGEpOiBJTVBPUlRBUiBMQSBCQVNFIERFIERBVE9TIEVOIFZJVk8gREVTREUgRUwgQkFOQ08gTVVORElBTA0KRXN0byBkZXNjYXJnYSBsYSBzZXJpZSBNw4FTIEFDVFVBTElaQURBIGRpcmVjdGFtZW50ZSBkZSBsYSBBUEkgZGVsIEJhbmNvIE11bmRpYWwuDQpDb21vIGVsIEJhbmNvIE11bmRpYWwgc3VlbGUgcHVibGljYXIgZWwgZ2FzdG8gZW4gc2FsdWQgY29uIDItMyBhw7FvcyBkZSByZXphZ28sDQplcyBOT1JNQUwgcXVlIGxvcyBhw7FvcyBtw6FzIHJlY2llbnRlcyB2ZW5nYW4gY29uIE5BIC0gZXNvIGVzIGp1c3RhbWVudGUgcGFydGUgZGUNCmxhIGhvbmVzdGlkYWQgZGUgbG9zIGRhdG9zIHF1ZSBzZSBwaWRlIGFuYWxpemFyICh2ZXIgY29uY2x1c2nDs24gYWwgZmluYWwpLg0KDQpgYGB7cn0NCnBhaXNlcyA8LSBjKCJNWCIsIkJSIiwiQVIiLCJDTyIsIkNMIiwiUEUiKQ0KDQpwYW5lbF93ZGkgPC0gV0RJKA0KICBjb3VudHJ5ICAgPSBwYWlzZXMsDQogIGluZGljYXRvciA9IGMoRXNwZXJhbnphID0gIlNQLkRZTi5MRTAwLklOIiwNCiAgICAgICAgICAgICAgICBHYXN0b1NhbHVkID0gIlNILlhQRC5DSEVYLkdELlpTIiksDQogIHN0YXJ0ID0gMjAxMCwgZW5kID0gMjAyMw0KKQ0KDQojIFJldmlzYSBjdcOhbnRvcyBOQSB0cmFlIGNhZGEgY29sdW1uYSAoaW1wb3J0YW50ZSBwYXJhIGxhIGRpc2N1c2nDs24gZGUgbGltcGllemEpDQpjb2xTdW1zKGlzLm5hKHBhbmVsX3dkaVssIGMoIkVzcGVyYW56YSIsIkdhc3RvU2FsdWQiKV0pKQ0KaGVhZChwYW5lbF93ZGkpDQpgYGANCg0KIyMgT1BDScOTTiBCIChyZXNwYWxkbyBvZmZsaW5lKTogbWlzbW9zIGRhdG9zLCB2ZXJpZmljYWRvcyBtYW51YWxtZW50ZQ0KUG9yIHNpIG5vIGhheSBpbnRlcm5ldCBlbiBlbCBzYWzDs24sIG8gcGFyYSBjb21wYXJhciBjb250cmEgbGEgZGVzY2FyZ2EgZW4gdml2by4NCkVzdG9zIHZhbG9yZXMgMjAxOS0yMDIwIGZ1ZXJvbiB2ZXJpZmljYWRvcyBjb250cmEgZWwgQmFuY28gTXVuZGlhbCAodsOtYSBGUkVELA0KRmVkZXJhbCBSZXNlcnZlIEJhbmsgb2YgU3QuIExvdWlzLCBxdWUgcmVwbGljYSBsYSBzZXJpZSBXREkgdGFsIGN1YWwpLiBBIHBhcnRpcg0KZGUgMjAyMSBlbCBpbmRpY2Fkb3IgZGUgZ2FzdG8gZW4gc2FsdWQgYcO6biBubyBlc3RhYmEgcMO6YmxpY28gYWwgbW9tZW50byBkZQ0KcHJlcGFyYXIgZXN0ZSBlamVyY2ljaW8gLT4gc2UgZGVqYSBjb21vIE5BIGEgcHJvcMOzc2l0by4NCg0KYGBge3J9DQpkZjUgPC0gZGF0YS5mcmFtZSgNCiAgUGFpcyA9IHJlcChjKCJNZXhpY28iLCJCcmFzaWwiLCJBcmdlbnRpbmEiLCJDb2xvbWJpYSIsIkNoaWxlIiwiUGVydSIpLCBlYWNoID0gNSksDQogIEFuaW8gPSByZXAoMjAxOToyMDIzLCB0aW1lcyA9IDYpLA0KICBHYXN0b1NhbHVkID0gYygNCiAgICA1LjUsIDYuMiwgTkEsIE5BLCBOQSwgICAgICAjIE1leGljbw0KICAgIDkuNiwgMTAuMywgTkEsIE5BLCBOQSwgICAgICMgQnJhc2lsDQogICAgOS41LCAxMC4wLCBOQSwgTkEsIE5BLCAgICAgIyBBcmdlbnRpbmENCiAgICA3LjcsIDkuMCwgTkEsIE5BLCBOQSwgICAgICAjIENvbG9tYmlhDQogICAgOS4zLCA5LjgsIE5BLCBOQSwgTkEsICAgICAgIyBDaGlsZQ0KICAgIDUuMiwgNi40LCBOQSwgTkEsIE5BICAgICAgICMgUGVydQ0KICApLA0KICBFc3BlcmFuemEgPSBjKA0KICAgIDc0LjUzMCwgNzAuNDQ5LCA2OS43NTAsIDczLjk3MywgNzUuMDY5LCAgIyBNZXhpY28NCiAgICA3NS44MDksIDc0LjUwNiwgNzMuMDM4LCA3NC44NzIsIDc1Ljg0OCwgICMgQnJhc2lsDQogICAgNzYuODQ3LCA3NS44NzgsIDczLjk0OCwgNzUuODA2LCA3Ny4zOTUsICAjIEFyZ2VudGluYQ0KICAgIDc2Ljc5MywgNzQuNzU3LCA3Mi42OTgsIDc2LjUwOCwgNzcuNzI1LCAgIyBDb2xvbWJpYQ0KICAgIDgwLjMyNCwgNzkuMzQ5LCA3OC44NzYsIDc5LjE3NiwgODEuMTY3LCAgIyBDaGlsZQ0KICAgIDc2LjI3NSwgNzMuODMyLCA3MS41OTYsIDc2LjgzNCwgNzcuNzQwICAgIyBQZXJ1DQogICkNCikNCg0KZGY1IDwtIHBkYXRhLmZyYW1lKGRmNSwgaW5kZXggPSBjKCJQYWlzIiwiQW5pbyIpKQ0KYGBgDQoNCiMjIFZJU1VBTElaQUNJw5NOIERFIExBIEJBU0UgREUgREFUT1MNCmBgYHtyfQ0KZ2dwbG90KGFzLmRhdGEuZnJhbWUoZGY1KSwgYWVzKHggPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihBbmlvKSksIHkgPSBFc3BlcmFuemEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IFBhaXMsIGdyb3VwID0gUGFpcykpICsNCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsgZ2VvbV9wb2ludCgpICsNCiAgbGFicyh0aXRsZSA9ICJFc3BlcmFuemEgZGUgdmlkYSBhbCBuYWNlciwgMjAxOS0yMDIzIiwNCiAgICAgICB4ID0gIkHDsW8iLCB5ID0gIkHDsW9zIGRlIGVzcGVyYW56YSBkZSB2aWRhIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KSU5URVJQUkVUQUNJw5NOOiBzZSBvYnNlcnZhIHVuYSBjYcOtZGEgZ2VuZXJhbGl6YWRhIGVuIDIwMjAtMjAyMSAocGFuZGVtaWEgQ09WSUQtMTkpDQp5IHVuYSByZWN1cGVyYWNpw7NuIHBvc3Rlcmlvci4gRXN0byBlcyB1bmEgc2XDsWFsIGRlIHF1ZSBoYXkgdW4gY2hvcXVlIHRlbXBvcmFsIGNvbcO6bg0KYSB0b2RvcyBsb3MgcGHDrXNlcywgYWxnbyBxdWUgaGF5IHF1ZSB0ZW5lciBlbiBjdWVudGEgYWwgaW50ZXJwcmV0YXIgZWwgbW9kZWxvLg0KDQojIyBQUlVFQkEgREUgSEVURVJPR0VORUlEQUQNCmBgYHtyfQ0KcGxvdG1lYW5zKEVzcGVyYW56YSB+IFBhaXMsIGRhdGEgPSBkZjUpDQpgYGANCklOVEVSUFJFVEFDScOTTjogbG9zIHByb21lZGlvcyBwb3IgcGHDrXMgZXN0w6FuIG11eSBsZWpvcyBlbnRyZSBzw60gKENoaWxlIH43OS04MCBhw7Fvcw0KdnMgTcOpeGljby9QZXLDuiB+NzMtNzQgYcOxb3MpIC0+IGhheSBoZXRlcm9nZW5laWRhZCBjbGFyYSBlbnRyZSBwYcOtc2VzLCBwb3IgbG8gcXVlDQpOTyBjb252aWVuZSB1c2FyIHJlZ3Jlc2nDs24gc2ltcGxlIGFncnVwYWRhOyBoYXkgcXVlIGNvbXBhcmFyIFBvb2xlZCwgRWZlY3RvcyBGaWpvcw0KeSBFZmVjdG9zIEFsZWF0b3Jpb3MuDQoNCiMjIE1PREVMT1MgREUgREFUT1MgUEFORUwNCk5vdGE6IGBwbG1gIGV4Y2x1eWUgYXV0b23DoXRpY2FtZW50ZSBsYXMgZmlsYXMgY29uIE5BIGVuIGxhcyB2YXJpYWJsZXMgdXNhZGFzLCBhc8OtDQpxdWUgZWwgcGFuZWwgcXVlZGEgIm5vIGJhbGFuY2VhZG8iICgyIGHDsW9zIHBvciBwYcOtcyBlbiB2ZXogZGUgNSkgc2luIHF1ZSB0ZW5nYW1vcw0KcXVlIGJvcnJhciBtYW51YWxtZW50ZSBlc2FzIGZpbGFzIGRlbCBkYXRhIGZyYW1lLg0KDQpgYGB7cn0NCiMgT3BjaW9uIDEgfiBNb2RlbG8gZGUgcmVncmVzaW9uIEFncnVwYWRhIChQb29sZWQpDQpwb29sZWQ1IDwtIHBsbShFc3BlcmFuemEgfiBHYXN0b1NhbHVkLCBkYXRhID0gZGY1LCBtb2RlbCA9ICJwb29saW5nIikNCnN1bW1hcnkocG9vbGVkNSkNCg0KIyBPcGNpb24gMiB+IE1vZGVsbyBkZSBFZmVjdG9zIEZpam9zIChXaXRoaW4pDQp3aXRoaW41IDwtIHBsbShFc3BlcmFuemEgfiBHYXN0b1NhbHVkLCBkYXRhID0gZGY1LCBtb2RlbCA9ICJ3aXRoaW4iKQ0Kc3VtbWFyeSh3aXRoaW41KQ0KDQojIFBydWViYSBGIChQb29sZWQgdnMgV2l0aGluKQ0KcEZ0ZXN0KHdpdGhpbjUsIHBvb2xlZDUpDQoNCiMgT3BjaW9uIDMgfiBNb2RlbG8gZGUgRWZlY3RvcyBBbGVhdG9yaW9zIChSYW5kb20pDQpyYW5kb201IDwtIHBsbShFc3BlcmFuemEgfiBHYXN0b1NhbHVkLCBkYXRhID0gZGY1LCBtb2RlbCA9ICJyYW5kb20iKQ0Kc3VtbWFyeShyYW5kb201KQ0KDQojIFBydWViYSBkZSBIYXVzbWFuDQojIElOVEVSUFJFVEFDSU9OOiBTaSBwPDAuMDUsIHVzYXIgZWZlY3RvcyBmaWpvczsgc2kgcD4wLjA1LCB1c2FyIGVmZWN0b3MgYWxlYXRvcmlvcw0KcGh0ZXN0KHJhbmRvbTUsIHdpdGhpbjUpDQpgYGANCg0KQ09OQ0xVU0nDk04gREUgU0VMRUNDScOTTiBERSBNT0RFTE86IExhIHBydWViYSBGIHJlY2hhemEgZWwgbW9kZWxvIFBvb2xlZA0KKHAg4omIIDAuMDA1KSwgY29uZmlybWFuZG8gcXVlIHPDrSBleGlzdGVuIGVmZWN0b3MgZXNwZWPDrWZpY29zIGRlIGNhZGEgcGHDrXMgcXVlDQplbCBtb2RlbG8gYWdydXBhZG8gaWdub3JhLiBDb24gc29sbyAyIGHDsW9zIGRpc3BvbmlibGVzIHBvciBwYcOtcyAoVD0yKSBsYSBwcnVlYmENCmRlIEhhdXNtYW4gcHVlZGUgdm9sdmVyc2UgbnVtw6lyaWNhbWVudGUgaW5lc3RhYmxlIChwcm9ibGVtYSB0w61waWNvIGRlIG11ZXN0cmFzDQptdXkgY29ydGFzKSDigJQgZW4gZXNlIGNhc28sIGxhIHJlY29tZW5kYWNpw7NuIHTDqWNuaWNhIGVzIHVzYXIgKipFZmVjdG9zIEZpam9zKiosDQpwb3JxdWUgZXMgcmF6b25hYmxlIHBlbnNhciBxdWUgZWwgbml2ZWwgZGUgZ2FzdG8gZW4gc2FsdWQgZGUgdW4gcGHDrXMgZXN0w6ENCmNvcnJlbGFjaW9uYWRvIGNvbiBjYXJhY3RlcsOtc3RpY2FzIHByb3BpYXMgbm8gb2JzZXJ2YWRhcyBkZWwgcGHDrXMgKGNhbGlkYWQgZGVsDQpzaXN0ZW1hIGRlIHNhbHVkLCBuaXZlbCBkZSBpbmdyZXNvLCBnZW9ncmFmw61hKSwgbG8gY3VhbCB2aW9sYXLDrWEgZWwgc3VwdWVzdG8NCmNsYXZlIGRlIEVmZWN0b3MgQWxlYXRvcmlvcy4NCg0KIyMgQURWRVJURU5DSUEgSU1QT1JUQU5URSBTT0JSRSBDQVVTQUxJREFEIChsw6llbG8gYW50ZXMgZGUgcmVwb3J0YXIgZWwgY29lZmljaWVudGUpDQpDb24gc29sbyAyMDE5IHkgMjAyMCBkaXNwb25pYmxlcywgbGEgw7puaWNhICJ2YXJpYWNpw7NuIGRlbnRybyBkZSBjYWRhIHBhw61zIiBxdWUgZWwNCm1vZGVsbyBkZSBFZmVjdG9zIEZpam9zIHB1ZWRlIHVzYXIgZXMgZWwgY2FtYmlvIDIwMTnihpIyMDIwLCBlcyBkZWNpciwgZWwgY2hvcXVlIGRlDQpsYSBwYW5kZW1pYTogbGEgZXNwZXJhbnphIGRlIHZpZGEgQ0FZw5MgZW4gY2FzaSB0b2RvcyBsb3MgcGHDrXNlcyBlbiAyMDIwIG1pZW50cmFzDQpxdWUgZWwgZ2FzdG8gZW4gc2FsdWQgY29tbyAlIGRlbCBQSUIgU1VCScOTIChwb3JxdWUgZWwgUElCIHNlIGNvbnRyYWpvIHkgZWwgZ2FzdG8NCmVuIHNhbHVkIGF1bWVudMOzKS4gRXN0byBnZW5lcmEgdW5hIGNvcnJlbGFjacOzbiBuZWdhdGl2YSBxdWUgcmVmbGVqYSBlbCBjaG9xdWUgZGUNCkNPVklELCAqKm5vIHVuYSByZWxhY2nDs24gY2F1c2FsIHJlYWwqKiBlbnRyZSBnYXN0YXIgbcOhcyBlbiBzYWx1ZCB5IHZpdmlyIG1lbm9zLg0KRXMgZWwgbWlzbW8gdGlwbyBkZSB0cmFtcGEgcXVlIGVsIEVqZXJjaWNpbyAzIG1vc3RyYWJhIGNvbiBsYSByZWdyZXNpw7NuIHNpbXBsZSBkZQ0KcHVibGljaWRhZCB5IHZlbnRhczogZWwgcmVzdWx0YWRvICJpbmdlbnVvIiBwdWVkZSB0ZW5lciBlbCBzaWdubyBlcXVpdm9jYWRvIHNpIG5vDQpzZSBjb250cm9sYSBiaWVuIGxhIGZ1ZW50ZSBkZSB2YXJpYWNpw7NuLiBMYSBzb2x1Y2nDs24gY29ycmVjdGEgZXMgYW1wbGlhciBlbCBwYW5lbA0KKG3DoXMgYcOxb3MsIHlhIHNpbiBlbCBjaG9xdWUgZGUgdW4gw7puaWNvIGV2ZW50byBkb21pbmFuZG8gbGEgbXVlc3RyYSkg4oCUIHZlciBPcGNpw7NuIEEuDQoNCiMjIFBSRURJQ0NJw5NOOiArMTAlIGRlIGdhc3RvIGVuIHNhbHVkIGVuIDIwMjQgcmVzcGVjdG8gYSAyMDIwDQpgYGB7cn0NCmludGVyY2VwdG81IDwtIGNvZWYod2l0aGluNSkgICMgd2l0aGluIG5vIHRpZW5lIGludGVyY2VwdG8gY29tdW47IHNlIHVzYW4gZWZlY3RvcyBpbmRpdmlkdWFsZXMNCmVmZWN0b3M1IDwtIGZpeGVmKHdpdGhpbjUpDQoNCmRmNV9wcm9ub3N0aWNvIDwtIGRhdGEuZnJhbWUoDQogIFBhaXMgPSBjKCJNZXhpY28iLCJCcmFzaWwiLCJBcmdlbnRpbmEiLCJDb2xvbWJpYSIsIkNoaWxlIiwiUGVydSIpLA0KICBHYXN0b1NhbHVkID0gYyg2LjIsMTAuMywxMC4wLDkuMCw5LjgsNi40KSAqIDEuMTAgICMgKzEwJSByZXNwZWN0byBhIDIwMjANCikNCg0KZGY1X3Byb25vc3RpY28kRXNwZXJhbnphX3ByZWQgPC0gZWZlY3RvczVbZGY1X3Byb25vc3RpY28kUGFpc10gKw0KICBjb2VmKHdpdGhpbjUpWyJHYXN0b1NhbHVkIl0gKiBkZjVfcHJvbm9zdGljbyRHYXN0b1NhbHVkDQoNCmRmNV9wcm9ub3N0aWNvDQpgYGANCg0KQ09OQ0xVU0nDk046IENvbiBsb3MgZGF0b3MgYWN0dWFsbWVudGUgcMO6YmxpY29zICgyMDE5LTIwMjApLCBlbCBtb2RlbG8gZGUgRWZlY3Rvcw0KRmlqb3MgZXMgZXN0YWTDrXN0aWNhbWVudGUgZWwgbcOhcyBhZGVjdWFkbyAobGEgcHJ1ZWJhIEYgcmVjaGF6YSBlbCBtb2RlbG8gYWdydXBhZG8NCmNvbiBwIOKJiCAwLjAwNSksIHBlcm8gZWwgY29lZmljaWVudGUgb2J0ZW5pZG8gZXN0w6EgZG9taW5hZG8gcG9yIGVsIGNob3F1ZSBkZSBsYQ0KcGFuZGVtaWEgeSAqKm5vIGRlYmUgaW50ZXJwcmV0YXJzZSBjb21vIGVsIGVmZWN0byBjYXVzYWwgcmVhbCoqIGRlbCBnYXN0byBlbiBzYWx1ZA0Kc29icmUgbGEgZXNwZXJhbnphIGRlIHZpZGEuIFBvciBlc28gZWwgcHJvbsOzc3RpY28gZGUgZXN0ZSBibG9xdWUgZGViZSB0b21hcnNlIGNvbW8NCnVuIGVqZXJjaWNpbyBtZXRvZG9sw7NnaWNvLCBubyBjb21vIHVuYSBwcmVkaWNjacOzbiBjb25maWFibGUgcGFyYSBwb2zDrXRpY2EgcMO6YmxpY2EuDQpFbiBjdWFudG8gZWwgQmFuY28gTXVuZGlhbCBwdWJsaXF1ZSAyMDIxLTIwMjMgZGUgZ2FzdG8gZW4gc2FsdWQgKHVzYW5kbyBsYSBPcGNpw7NuDQpBIGRlIGVzdGUgZG9jdW1lbnRvKSwgaGF5IHF1ZSB2b2x2ZXIgYSBjb3JyZXIgZWwgbW9kZWxvIGNvbiBlbCBwYW5lbCBjb21wbGV0bzogYWwNCnRlbmVyIG3DoXMgYcOxb3MsIGVsICJydWlkbyIgZGUgdW4gc29sbyBjaG9xdWUgKENPVklEKSBwZXNhcsOhIG11Y2hvIG1lbm9zIHkgZWwNCmNvZWZpY2llbnRlIGVzdGltYWRvIHNlcsOhIG3DoXMgcmVwcmVzZW50YXRpdm8gZGUgbGEgcmVsYWNpw7NuIGRlIGxhcmdvIHBsYXpvLg0KDQotLS0NCg0KIyDCv0hBWSBRVUUgTElNUElBUiBMT1MgREFUT1MgTlVMT1MgKE5BKSBPIERFSkFSTE9TPw0KDQpFc3RhIGVzIGxhIHByZWd1bnRhIGNlbnRyYWwgcXVlIHNlIHBsYW50ZcOzLCB5IGxhIHJlc3B1ZXN0YSBjb3J0YSBlczoNCioqbm8gbG9zIGxpbXBpZXMgKG5vIGxvcyBpbXB1dGVzIG5pIGxvcyBib3JyZXMgYSBsYSBmdWVyemEpIOKAlCBkw6lqYWxvcyBjb21vIE5BIHkNCnVzYSBgcGxtYCwgcXVlIG1hbmVqYSBwYW5lbGVzIG5vIGJhbGFuY2VhZG9zIGRlIGZvcm1hIG5hdGl2YS4qKg0KDQpQb3IgcXXDqToNCg0KMS4gKipMb3MgTkEgYXF1w60gbm8gc29uICJkYXRvcyBzdWNpb3MiLCBzb24gZGF0b3MgcXVlIHRvZGF2w61hIG5vIGV4aXN0ZW4uKiogRWwNCiAgIEJhbmNvIE11bmRpYWwgcHVibGljYSBlbCBnYXN0byBlbiBzYWx1ZCBjb24gMi0zIGHDsW9zIGRlIHJlemFnbyAoZGVwZW5kZSBkZSBxdWUNCiAgIGxhIE9NUyBjb25zb2xpZGUgbGEgR2xvYmFsIEhlYWx0aCBFeHBlbmRpdHVyZSBEYXRhYmFzZSkuIEZhbHRhbiBwb3JxdWUgYcO6biBubw0KICAgc2UgaGFuIG1lZGlkbywgbm8gcG9ycXVlIGhheWEgdW4gZXJyb3IgZGUgY2FwdHVyYS4NCg0KMi4gKipJbXB1dGFyIChyZWxsZW5hciBjb24gbGEgbWVkaWEsIGludGVycG9sYXIsIGV0Yy4pIGludmVudGFyw61hIGluZm9ybWFjacOzbg0KICAgcXVlIG5vIGV4aXN0ZSoqIHkgaGFyw61hIHF1ZSBlbCBtb2RlbG8gcGFyZWNpZXJhIG3DoXMgcHJlY2lzbyBkZSBsbyBxdWUNCiAgIHJlYWxtZW50ZSBlcyDigJQgZXNvIGVzIHByZWNpc2FtZW50ZSBsbyBjb250cmFyaW8gZGUgbGEgImhvbmVzdGlkYWQgZGUgbG9zDQogICBkYXRvcyBlbiBsYXMgcHJlZGljY2lvbmVzIiBxdWUgc2UgcGlkacOzIGN1aWRhci4gVW4gcHJvZmVzaW9uYWwgZGUgZGF0b3MgcXVlDQogICByZWxsZW5hIGh1ZWNvcyBkZSBlc3RhIGZvcm1hIHNpbiBkZWphcmxvIGNsYXLDrXNpbW8gZW4gZWwgcmVwb3J0ZSBlc3TDoQ0KICAgbWFxdWlsbGFuZG8gbGEgaW5jZXJ0aWR1bWJyZSByZWFsIGRlbCBwcm9uw7NzdGljby4NCg0KMy4gKipgcGxtYCB5YSByZXN1ZWx2ZSBlbCBwcm9ibGVtYSB0w6ljbmljbzoqKiBhbCBjb25zdHJ1aXIgZWwgYHBkYXRhLmZyYW1lYCBjb24NCiAgIGZpbGFzIGVuIE5BLCBgcGxtKClgIHNpbXBsZW1lbnRlIHVzYSBsYXMgb2JzZXJ2YWNpb25lcyBkaXNwb25pYmxlcyBwYXJhIGNhZGENCiAgIHBhw61zIChwYW5lbCBubyBiYWxhbmNlYWRvKS4gTm8gZXMgbmVjZXNhcmlvIG5pIHJlY29tZW5kYWJsZSBoYWNlcg0KICAgYG5hLm9taXQoKWAgYSBtYW5vIGFudGVzIGRlIHRpZW1wbyDigJQgc8OzbG8gaGF6bG8gc2kgdmFzIGEgY29tcGFyYXIgZWwgbWlzbW8NCiAgIG7Dum1lcm8gZGUgb2JzZXJ2YWNpb25lcyBlbnRyZSBtb2RlbG9zLg0KDQo0LiAqKkN1w6FuZG8gU8ONIGNvbnZpZW5lIGxpbXBpYXIvdHJhdGFyIGxvcyBkYXRvczoqKg0KICAgLSBTaSB1biBOQSBlcyBlbiByZWFsaWRhZCB1biBlcnJvciBkZSBjYXB0dXJhIChlai4gIi05OTkiIG8gdW4gdGV4dG8gZG9uZGUNCiAgICAgZGViZXLDrWEgaXIgdW4gbsO6bWVybyk6IGVzbyBzw60gc2UgY29ycmlnZS4NCiAgIC0gU2kgdGUgaW50ZXJlc2EgdW4gcGHDrXMgY29uIGRlbWFzaWFkb3MgYcOxb3MgZmFsdGFudGVzIChlai4gc29sbyAxIGRlIDEwDQogICAgIGHDsW9zKSwgY29uc2lkZXJhIGV4Y2x1aXIgZXNlIHBhw61zIGVuIHZleiBkZSBpbXB1dGFybG8sIHBvcnF1ZSBzdQ0KICAgICBjb250cmlidWNpw7NuIGFsIG1vZGVsbyBzZXLDrWEgY2FzaSBwdXJvIHJ1aWRvLg0KICAgLSBTaSBuZWNlc2l0YXMgdW4gcGFuZWwgZXN0cmljdGFtZW50ZSBiYWxhbmNlYWRvIHBvciByZXF1aXNpdG8gZGVsIG3DqXRvZG8NCiAgICAgKHBvY28gY29tw7puIGVuIGBwbG1gLCBwZXJvIHBhc2EgZW4gb3RyYXMgdMOpY25pY2FzKSwgZG9jdW1lbnRhIGV4cGzDrWNpdGFtZW50ZQ0KICAgICBxdcOpIGZpbGFzIHF1aXRhc3RlIHkgcG9yIHF1w6kuDQoNCjUuICoqUmVww7NydGFsbyBzaWVtcHJlOioqIGN1YWxxdWllciB0YWJsYSBvIGdyw6FmaWNhIHF1ZSBtdWVzdHJlcyBkZWJlIGRlamFyDQogICBjbGFybyBjdcOhbnRhcyBvYnNlcnZhY2lvbmVzIHRpZW5lIGNhZGEgcGHDrXMgeSBxdcOpIGHDsW9zIGZhbHRhbiAoY29tbyBzZSBoaXpvDQogICBhcnJpYmEgY29uIGBjb2xTdW1zKGlzLm5hKC4uLikpYCkuIFVuIHByb27Ds3N0aWNvIHNpbiBlc2Egbm90YSBlcyB1bg0KICAgcHJvbsOzc3RpY28gcXVlIHBhcmVjZSBtw6FzIHPDs2xpZG8gZGUgbG8gcXVlIGVuIHJlYWxpZGFkIGVzLg0K