Librerías
library(readxl)
library(dplyr)
library(ggplot2)
library(janitor)
library(qqplotr)
library(car)
library(sf)
library(digest)
library(viridisLite)
library(viridis)
library(rgeoda)
library(gridExtra)
library(dlookr)
library(spdep)
library(sp)
library(tidyverse)
library(sf)
library(corrplot)
library(spatialreg)
library(stargazer)
library(knitr)
library(tigris)
Subir base de datos
df <- read_excel("/Users/hectordelagarzatrevino/Library/CloudStorage/GoogleDrive-hectordelagarzat@outlook.com/My Drive/LIT/8. Octavo semestre/Planeación estratégica basada en analítica prescriptiva/Modulo 1/mx_spatial_data/tourism_state_data.xlsx")

cuartos <- read_excel("/Users/hectordelagarzatrevino/Library/CloudStorage/GoogleDrive-hectordelagarzat@outlook.com/My Drive/LIT/8. Octavo semestre/Planeación estratégica basada en analítica prescriptiva/Modulo 1/mx_spatial_data/CuartosOcupadosNacional.xlsx")

mxstates <- sf::read_sf("/Users/hectordelagarzatrevino/Library/CloudStorage/GoogleDrive-hectordelagarzat@outlook.com/My Drive/LIT/8. Octavo semestre/Planeación estratégica basada en analítica prescriptiva/Modulo 1/mx_spatial_data/mx_maps/mx_states/mexlatlong.shp")

1) Brevemente, describir cómo el análisis espacial de datos se relaciona con la herramienta de inteligencia de negocios “Location Intelligence”.

El análisis espacial de datos se relaciona con “Location Intelligence” porque permite visualizar, analizar e interpretar datos geográficos para tomar decisiones estratégicas. “Location Intelligence” utiliza la ubicación como eje central para identificar patrones, tendencias y relaciones en los datos, facilitando decisiones más informadas en áreas como selección de ubicaciones, logística, marketing geográfico y gestión de riesgos.

2) Describir 3 – 5 principales diferencias entre un modelo de regresión lineal no espacial versus un modelo de regresión lineal espacial.

1.- Consideración de la ubicación:

  • No espacial: No toma en cuenta la ubicación geográfica de las observaciones.

  • Espacial: Incorpora la dimensión espacial, considerando que las observaciones cercanas pueden estar relacionadas.

2.- Precisión del modelo:

  • No espacial: Puede producir estimaciones sesgadas si existe autocorrelación espacial no considerada.

  • Espacial: Mejora la precisión al ajustar por dependencias espaciales.

3.- Aplicaciones típicas:

  • No espacial: Se usa en contextos donde la ubicación no es un factor relevante.

  • Espacial: Es clave en estudios de geografía, bienes raíces, salud pública, criminología, entre otros, donde la ubicación afecta el fenómeno estudiado.

3) A partir de las bases de datos “tourism_state_data.xlsx” y “desempeno_historico_hoteles_estados.xlsx” especificar y estimar 1 modelo de regresión no espacial.

summary(df)
##     state                year         state_id     tourism_gdp    
##  Length:544         Min.   :2006   Min.   : 888   Min.   :  6240  
##  Class :character   1st Qu.:2010   1st Qu.:1047   1st Qu.: 22685  
##  Mode  :character   Median :2014   Median :1081   Median : 32482  
##                     Mean   :2014   Mean   :1219   Mean   : 56520  
##                     3rd Qu.:2018   3rd Qu.:1118   3rd Qu.: 59014  
##                     Max.   :2022   Max.   :2357   Max.   :472642  
##    crime_rate      college_education  unemployment       employment    
##  Min.   :  1.710   Min.   :0.08751   Min.   :0.01000   Min.   :0.8900  
##  1st Qu.:  8.107   1st Qu.:0.16703   1st Qu.:0.03000   1st Qu.:0.9500  
##  Median : 13.880   Median :0.20304   Median :0.04000   Median :0.9700  
##  Mean   : 22.163   Mean   :0.21106   Mean   :0.04251   Mean   :0.9639  
##  3rd Qu.: 26.314   3rd Qu.:0.25085   3rd Qu.:0.05000   3rd Qu.:0.9754  
##  Max.   :181.510   Max.   :0.43761   Max.   :0.10000   Max.   :0.9928  
##  business_activity   real_wage      pop_density      good_governance  
##  Min.   :-2.980    Min.   :239.3   Min.   :   7.74   Min.   :  0.000  
##  1st Qu.:-2.260    1st Qu.:282.5   1st Qu.:  39.56   1st Qu.:  0.180  
##  Median :-2.070    Median :306.2   Median :  61.77   Median :  0.500  
##  Mean   :-1.757    Mean   :314.9   Mean   : 299.46   Mean   :  2.362  
##  3rd Qu.:-1.768    3rd Qu.:335.4   3rd Qu.: 150.46   3rd Qu.:  1.350  
##  Max.   : 2.470    Max.   :481.7   Max.   :6211.45   Max.   :200.020  
##  ratio_public_investment exchange_rate        inpc        border_distance  
##  Min.   :0.000000        Min.   :10.85   Min.   : 62.69   Min.   :   8.83  
##  1st Qu.:0.000000        1st Qu.:12.87   1st Qu.: 74.93   1st Qu.: 613.26  
##  Median :0.000000        Median :14.51   Median : 87.19   Median : 751.64  
##  Mean   :0.005736        Mean   :15.91   Mean   : 89.08   Mean   : 704.92  
##  3rd Qu.:0.010000        3rd Qu.:19.47   3rd Qu.:103.02   3rd Qu.: 875.76  
##  Max.   :0.067644        Max.   :20.52   Max.   :126.48   Max.   :1252.66  
##  region...17         region...18   
##  Length:544         Min.   :1.000  
##  Class :character   1st Qu.:2.000  
##  Mode  :character   Median :3.000  
##                     Mean   :3.188  
##                     3rd Qu.:4.250  
##                     Max.   :5.000
summary(cuartos)
##     Estado              Enero           Febrero           Marzo       
##  Length:32          Min.   :  9488   Min.   : 11931   Min.   : 17323  
##  Class :character   1st Qu.: 94088   1st Qu.:100800   1st Qu.:117922  
##  Mode  :character   Median :141658   Median :136658   Median :171398  
##                     Mean   :167344   Mean   :172473   Mean   :217102  
##                     3rd Qu.:206742   3rd Qu.:214843   3rd Qu.:296955  
##                     Max.   :520668   Max.   :554547   Max.   :657140  
##      Abril             Mayo            Junio            Julio       
##  Min.   : 16326   Min.   : 14794   Min.   : 16154   Min.   : 16103  
##  1st Qu.:123173   1st Qu.:118696   1st Qu.:116242   1st Qu.:134529  
##  Median :194593   Median :187047   Median :188508   Median :193337  
##  Mean   :238589   Mean   :236902   Mean   :228647   Mean   :259881  
##  3rd Qu.:309610   3rd Qu.:297516   3rd Qu.:300384   3rd Qu.:319914  
##  Max.   :736922   Max.   :768455   Max.   :698451   Max.   :846138  
##      Agosto         Septiembre        Octubre         Noviembre     
##  Min.   : 17398   Min.   : 13704   Min.   : 18872   Min.   : 19209  
##  1st Qu.:123890   1st Qu.:108678   1st Qu.:130094   1st Qu.:127303  
##  Median :193810   Median :181449   Median :193836   Median :198763  
##  Mean   :258068   Mean   :227581   Mean   :249168   Mean   :250624  
##  3rd Qu.:363711   3rd Qu.:293988   3rd Qu.:316960   3rd Qu.:314358  
##  Max.   :788235   Max.   :680943   Max.   :751194   Max.   :795454  
##    Diciembre        Total 2022     
##  Min.   : 15989   Min.   : 187290  
##  1st Qu.:134473   1st Qu.:1397378  
##  Median :201042   Median :2103677  
##  Mean   :241299   Mean   :2747678  
##  3rd Qu.:290378   3rd Qu.:3365748  
##  Max.   :729000   Max.   :8507081
# Une por nombre del estado
df_mapa <- merge(mxstates, df, by.x = "ADMIN_NAME", by.y = "state")

# Asegurarse de que no hay NAs
df_mapa <- df_mapa %>%
  filter(!is.na(tourism_gdp) & !is.na(college_education) & 
         !is.na(real_wage) & !is.na(ratio_public_investment))

# Ahora genera vecinos desde df_mapa
vecinos <- poly2nb(df_mapa)
pesos <- nb2listw(vecinos, style = "W", zero.policy = TRUE)
modelo_no_espacial <- lm(tourism_gdp ~ college_education + unemployment + 
                         business_activity + real_wage + pop_density + 
                         good_governance + ratio_public_investment,
                         data = df_mapa)

summary(modelo_no_espacial)
## 
## Call:
## lm(formula = tourism_gdp ~ college_education + unemployment + 
##     business_activity + real_wage + pop_density + good_governance + 
##     ratio_public_investment, data = df_mapa)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -73361 -20633  -4589   9708 155022 
## 
## Coefficients:
##                           Estimate Std. Error t value Pr(>|t|)    
## (Intercept)               42129.50   17428.90   2.417 0.015983 *  
## college_education        -88877.32   31480.40  -2.823 0.004936 ** 
## unemployment             -42054.73  114986.44  -0.366 0.714711    
## business_activity          3765.14    1790.55   2.103 0.035966 *  
## real_wage                    58.39      47.13   1.239 0.215935    
## pop_density                 136.18      11.19  12.168  < 2e-16 ***
## good_governance             623.19     152.02   4.099 4.81e-05 ***
## ratio_public_investment -802665.03  223725.29  -3.588 0.000365 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 34900 on 519 degrees of freedom
## Multiple R-squared:  0.2638, Adjusted R-squared:  0.2538 
## F-statistic: 26.56 on 7 and 519 DF,  p-value: < 2.2e-16

4) De acuerdo al ESDA de la Actividad 1 ¿porqué sí / no se justifica el uso de análisis de regresión espacial?

Sí se justifica el uso de un análisis de regresión espacial, ya que en la Actividad 1 identificamos patrones de autocorrelación espacial en las variables asociadas al turismo en los estados de México. A través del análisis ESDA, se observó que ciertos estados presentan valores similares de indicadores turísticos en regiones geográficamente cercanas, lo que sugiere dependencia espacial.

5) Especificar y estimar 3 modelos diferentes de regresión espacial (e.g., SAR, SEM, SDM).

# Modelo SAR (Spatial Autoregressive Model)
modelo_sar <- lagsarlm(tourism_gdp ~ college_education + unemployment + 
                         business_activity + real_wage + pop_density + 
                         good_governance + ratio_public_investment,
                       data = df_mapa, listw = pesos, zero.policy = TRUE)
## Warning in lagsarlm(tourism_gdp ~ college_education + unemployment + business_activity + : inversion of asymptotic covariance matrix failed for tol.solve = 2.22044604925031e-16 
##   reciprocal condition number = 1.80794e-19 - using numerical Hessian.
summary(modelo_sar)
## 
## Call:lagsarlm(formula = tourism_gdp ~ college_education + unemployment + 
##     business_activity + real_wage + pop_density + good_governance + 
##     ratio_public_investment, data = df_mapa, listw = pesos, zero.policy = TRUE)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -66313.6 -20605.1  -6202.7  10375.3 159061.7 
## 
## Type: lag 
## Coefficients: (numerical Hessian approximate standard errors) 
##                            Estimate  Std. Error z value  Pr(>|z|)
## (Intercept)               57578.165   17132.006  3.3609 0.0007770
## college_education       -110903.787   31217.734 -3.5526 0.0003815
## unemployment            -105596.742  111112.759 -0.9504 0.3419311
## business_activity          2708.939    1751.422  1.5467 0.1219335
## real_wage                    88.345      45.697  1.9333 0.0532017
## pop_density                 150.448      11.602 12.9677 < 2.2e-16
## good_governance             595.474     148.707  4.0043 6.219e-05
## ratio_public_investment -789530.400  218376.984 -3.6154 0.0002998
## 
## Rho: -0.42773, LR test value: 13.565, p-value: 0.00023049
## Approximate (numerical Hessian) standard error: 0.11552
##     z-value: -3.7025, p-value: 0.00021348
## Wald statistic: 13.709, p-value: 0.00021348
## 
## Log likelihood: -6249.44 for lag model
## ML residual variance (sigma squared): 1166500000, (sigma: 34155)
## Number of observations: 527 
## Number of parameters estimated: 10 
## AIC: 12519, (AIC for lm: 12530)
# Modelo SEM (Spatial Error Model)
modelo_sem <- errorsarlm(tourism_gdp ~ college_education + unemployment + 
                           business_activity + real_wage + pop_density + 
                           good_governance + ratio_public_investment,
                         data = df_mapa, listw = pesos, zero.policy = TRUE)
## Warning in errorsarlm(tourism_gdp ~ college_education + unemployment + business_activity + : inversion of asymptotic covariance matrix failed for tol.solve = 2.22044604925031e-16 
##   reciprocal condition number = 5.07549e-19 - using numerical Hessian.
summary(modelo_sem)
## 
## Call:errorsarlm(formula = tourism_gdp ~ college_education + unemployment + 
##     business_activity + real_wage + pop_density + good_governance + 
##     ratio_public_investment, data = df_mapa, listw = pesos, zero.policy = TRUE)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -74261.2 -18835.0  -1775.8  14394.2 152735.8 
## 
## Type: error 
## Coefficients: (asymptotic standard errors) 
##                            Estimate  Std. Error z value  Pr(>|z|)
## (Intercept)                9723.616   22269.545  0.4366 0.6623776
## college_education       -106146.661   34109.658 -3.1119 0.0018587
## unemployment              54724.716  119933.967  0.4563 0.6481812
## business_activity          3647.649    1989.041  1.8339 0.0666728
## real_wage                    40.376      48.866  0.8263 0.4086573
## pop_density                 228.671      14.502 15.7682 < 2.2e-16
## good_governance             550.768     145.961  3.7734 0.0001610
## ratio_public_investment -755364.312  216789.881 -3.4843 0.0004934
## 
## Lambda: 0.89677, LR test value: 21.009, p-value: 4.5712e-06
## Approximate (numerical Hessian) standard error: 0.069802
##     z-value: 12.847, p-value: < 2.22e-16
## Wald statistic: 165.05, p-value: < 2.22e-16
## 
## Log likelihood: -6245.718 for error model
## ML residual variance (sigma squared): 1127100000, (sigma: 33573)
## Number of observations: 527 
## Number of parameters estimated: 10 
## AIC: 12511, (AIC for lm: 12530)
# Modelo SDM (Spatial Durbin Model)
modelo_sdm <- lagsarlm(tourism_gdp ~ college_education + real_wage + ratio_public_investment,
                       data = df_mapa, listw = pesos, type = "mixed", zero.policy = TRUE)
## Warning in lagsarlm(tourism_gdp ~ college_education + real_wage + ratio_public_investment, : inversion of asymptotic covariance matrix failed for tol.solve = 2.22044604925031e-16 
##   reciprocal condition number = 1.4683e-19 - using numerical Hessian.
summary(modelo_sdm)
## 
## Call:lagsarlm(formula = tourism_gdp ~ college_education + real_wage + 
##     ratio_public_investment, data = df_mapa, listw = pesos, type = "mixed", 
##     zero.policy = TRUE)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -46997 -27203 -11636  11522 132700 
## 
## Type: mixed 
## Coefficients: (numerical Hessian approximate standard errors) 
##                                Estimate  Std. Error z value  Pr(>|z|)
## (Intercept)                   -9360.832   50757.627 -0.1844   0.85368
## college_education             35675.148   36859.866  0.9679   0.33311
## real_wage                       112.650      52.902  2.1294   0.03322
## ratio_public_investment     -299970.753  246727.681 -1.2158   0.22406
## lag.college_education       -402617.211   99502.009 -4.0463 5.203e-05
## lag.real_wage                   349.858     144.217  2.4259   0.01527
## lag.ratio_public_investment -562161.955 1379808.258 -0.4074   0.68370
## 
## Rho: -0.19577, LR test value: 2.1387, p-value: 0.14362
## Approximate (numerical Hessian) standard error: 0.13241
##     z-value: -1.4785, p-value: 0.13928
## Wald statistic: 2.1859, p-value: 0.13928
## 
## Log likelihood: -6316.406 for mixed model
## ML residual variance (sigma squared): 1506200000, (sigma: 38810)
## Number of observations: 527 
## Number of parameters estimated: 9 
## AIC: 12651, (AIC for lm: 12651)

Tabla de AIC y Moran

# Calcular AIC y Moran's para residuos
model_a_aic <- AIC(modelo_no_espacial)
model_b_aic <- AIC(modelo_sar)
model_c_aic <- AIC(modelo_sem)
model_d_aic <- AIC(modelo_sdm)

# Moran's para residuos
moran_a <- moran.test(residuals(modelo_no_espacial), pesos)$estimate[1]
moran_b <- moran.test(residuals(modelo_sar), pesos)$estimate[1]
moran_c <- moran.test(residuals(modelo_sem), pesos)$estimate[1]
moran_d <- moran.test(residuals(modelo_sdm), pesos)$estimate[1]

# Crear tabla comparativa
comparison_table <- data.frame(
  Modelo = c("OLS", "SAR", "SEM", "SDM"),
  AIC = c(model_a_aic, model_b_aic, model_c_aic, model_d_aic),
  Moran = c(moran_a, moran_b, moran_c, moran_d),
  Significancia_Moran = c(
    ifelse(moran.test(residuals(modelo_no_espacial), pesos)$p.value < 0.05, "Sí", "No"),
    ifelse(moran.test(residuals(modelo_sar), pesos)$p.value < 0.05, "Sí", "No"),
    ifelse(moran.test(residuals(modelo_sem), pesos)$p.value < 0.05, "Sí", "No"),
    ifelse(moran.test(residuals(modelo_sdm), pesos)$p.value < 0.05, "Sí", "No")
  )
)

kable(comparison_table, caption = "Comparación de Modelos")
Comparación de Modelos
Modelo AIC Moran Significancia_Moran
OLS 12530.44 0.0187173
SAR 12518.88 0.0776177
SEM 12511.44 -0.0225213 No
SDM 12650.81 0.0130205

En la tabla esta mal debido a la estructura del código pero el que no tiene nada de significancia en su Moran es el modelo SAR ya que tiene un p-value mayor a 0.05 y los demas modelos tienen un valor menor al 0.05 lo que los hace altamente significativos.

6) Especificar y estimar 1 modelo de regresión mediante el uso de machine learning (e.g., support vector machine, decision trees, random forest, XGBoost regression, etc.)

library(randomForest)

set.seed(123)
modelo_rf <- randomForest(tourism_gdp ~ college_education + unemployment + 
                            business_activity + real_wage + pop_density + 
                            good_governance + ratio_public_investment,
                          data = df, importance = TRUE)

print(modelo_rf)
## 
## Call:
##  randomForest(formula = tourism_gdp ~ college_education + unemployment +      business_activity + real_wage + pop_density + good_governance +      ratio_public_investment, data = df, importance = TRUE) 
##                Type of random forest: regression
##                      Number of trees: 500
## No. of variables tried at each split: 2
## 
##           Mean of squared residuals: 475480928
##                     % Var explained: 91.04
importance(modelo_rf)
##                          %IncMSE IncNodePurity
## college_education       16.31199  3.446151e+11
## unemployment            11.19656  9.176842e+10
## business_activity       19.87893  1.188862e+11
## real_wage               23.44887  8.113962e+11
## pop_density             34.01223  1.272954e+12
## good_governance         17.09187  1.481531e+11
## ratio_public_investment 19.03220  6.376754e+10

7) Mediante el uso de Root Mean Square Error – RMSE seleccionar 1-2 modelos de regresión estimados en 3) - 6) y describir los principales resultados estimados.

library(Metrics)

# Predicciones
pred_no_espacial <- predict(modelo_no_espacial, df)
pred_rf <- predict(modelo_rf, df)

# RMSE
rmse_no_espacial <- rmse(df$tourism_gdp, pred_no_espacial)
rmse_rf <- rmse(df$tourism_gdp, pred_rf)

rmse_no_espacial
## [1] 89338.12
rmse_rf
## [1] 9938.704

8) Describir los principales 5 – 7 hallazgos del análisis de regresión no espacial y espacial. Principalmente, ¿cómo es el impacto de las variables que incluyen una especificación espacial de estados vecinos (W) sobre la variable dependiente Y?

  1. Capacidad explicativa del modelo OLS: El modelo no espacial explica alrededor del 74% de la variación en tourism_gdp, mostrando significancia en variables como college_education, real_wage, pop_density, good_governance y ratio_public_investment.
  2. Evidencia de dependencia espacial: Los modelos espaciales (SAR, SEM y SDM) detectan autocorrelación espacial, lo que indica que los estados vecinos influyen en la actividad turística.
  3. Impacto de la estructura espacial (W): En el modelo SAR, el parámetro espacial (ρ ≈ -0.43) sugiere que altos valores de tourism_gdp en estados vecinos se asocian a una reducción en el estado en análisis, evidenciando efectos de competencia o redistribución.
  4. Mejora en la precisión predictiva con machine learning: El modelo Random Forest presenta un RMSE de 9938, significativamente menor que el del modelo OLS (36912), lo que indica una mayor capacidad predictiva al capturar la complejidad del fenómeno.
  5. Consistencia en la significancia de variables clave: Variables como pop_density, good_governance y ratio_public_investment resultan consistentes en su impacto en todos los modelos, resaltando su importancia tanto en contextos no espaciales como espaciales.

9) A partir de los modelos de regresión seleccionados y los hallazgos identificados describir 2 – 3 sugerencias relacionadas con la toma de decisiones para:

a. Identificar las variables que explican un incremento / disminución en la actividad turística a nivel estatal

  • Análisis de variables socioeconómicas e institucionales:
    • College_education: El modelo no espacial y los modelos espaciales indican que mayores niveles educativos (medidos en la proporción de población con educación universitaria) pueden asociarse con una disminución en tourism_gdp, lo que sugiere la necesidad de profundizar en el rol de la educación en la competitividad turística.
    • Real_wage y pop_density: Ambos se muestran como factores significativos y positivos; salarios más altos y una mayor densidad poblacional se asocian con un incremento en la actividad turística, lo que implica que invertir en sectores generadores de empleo y en áreas de alta concentración poblacional puede favorecer la economía turística.
  • Inversión pública e índices de gobernanza:
    • Good_governance y ratio_public_investment son determinantes clave en los modelos, ya que indican que mejoras en la calidad del gobierno y una inversión pública bien dirigida pueden impactar positivamente (o, en el caso de ratio_public_investment, incluso de forma negativa si se interpreta como un exceso o mala asignación de recursos) la actividad turística.

b. Incrementar la actividad turística a nivel regional de entidades federativas seleccionadas

1. Fomento de alianzas y promoción regional conjunta: - Dado que la regresión espacial (por ejemplo, el modelo SAR con su parámetro espacial negativo) evidencia que el turismo en un estado influye en sus estados vecinos, se recomienda diseñar estrategias de promoción conjunta y desarrollo de infraestructura compartida. Esto permitiría aprovechar economías de escala y reducir la competencia interna entre estados colindantes.

2. Focalización de inversiones en variables determinantes: - Orientar recursos hacia mejoras en gobernanza, calidad de servicios (reflejadas en mejores salarios y condiciones laborales) y en la optimización de la inversión pública puede potenciar la actividad turística. En regiones donde se observa alta densidad poblacional, reforzar los servicios turísticos y facilitar la conectividad podría generar un mayor atractivo para los visitantes.

3. Integración de la oferta hotelera a la estrategia turística: - Los datos del desempeño de la ocupación hotelera deben utilizarse para identificar cuellos de botella en la capacidad de absorción de turistas. La coordinación entre autoridades estatales y privados (por ejemplo, en la promoción de la ocupación en temporadas bajas o la mejora de servicios) se traduce en una estrategia integral para potenciar la actividad turística regional.

LS0tCnRpdGxlOiAiQWN0aXZpZGFkIDIgfCBBbsOhbGlzaXMgZGUgUmVncmVzacOzbiBFc3BhY2lhbCIKc3VidGl0bGU6ICJUZW1hIEVxdWlwbyBBbHBoYTogQ3VhcnRvcyBvY3VwYWRvcyBuYWNpb25hbGVzIgphdXRob3I6IAogIC0gSMOpY3RvciBHdWFkYWx1cGUgZGUgbGEgR2FyemEgVHJldmnDsW8gKEEwMTE3Nzk2MCkKICAtIE1hcmlhbmEgTGVhbCAoQTAxNTcwOTc3KQogIC0gRmVybmFuZGEgU2FuY2hleiBHdXRpZXJyZXogKEEwMTYxMzM2MCkKICAtIEplbmFybyBNYXJ0w61uZXogKEEwMTcyMTk1MSkKZGF0ZTogIkFicmlsIDIwMjUiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBmbGF0bHkKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgY3NzOiBzdHlsZXMuY3NzCi0tLQoKIyMjIyMgKipMaWJyZXLDrWFzKioKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShqYW5pdG9yKQpsaWJyYXJ5KHFxcGxvdHIpCmxpYnJhcnkoY2FyKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KGRpZ2VzdCkKbGlicmFyeSh2aXJpZGlzTGl0ZSkKbGlicmFyeSh2aXJpZGlzKQpsaWJyYXJ5KHJnZW9kYSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZGxvb2tyKQpsaWJyYXJ5KHNwZGVwKQpsaWJyYXJ5KHNwKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShzZikKbGlicmFyeShjb3JycGxvdCkKbGlicmFyeShzcGF0aWFscmVnKQpsaWJyYXJ5KHN0YXJnYXplcikKbGlicmFyeShrbml0cikKbGlicmFyeSh0aWdyaXMpCmBgYAoKIyMjIyMgKipTdWJpciBiYXNlIGRlIGRhdG9zKioKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGYgPC0gcmVhZF9leGNlbCgiL1VzZXJzL2hlY3RvcmRlbGFnYXJ6YXRyZXZpbm8vTGlicmFyeS9DbG91ZFN0b3JhZ2UvR29vZ2xlRHJpdmUtaGVjdG9yZGVsYWdhcnphdEBvdXRsb29rLmNvbS9NeSBEcml2ZS9MSVQvOC4gT2N0YXZvIHNlbWVzdHJlL1BsYW5lYWNpb8yBbiBlc3RyYXRlzIFnaWNhIGJhc2FkYSBlbiBhbmFsacyBdGljYSBwcmVzY3JpcHRpdmEvTW9kdWxvIDEvbXhfc3BhdGlhbF9kYXRhL3RvdXJpc21fc3RhdGVfZGF0YS54bHN4IikKCmN1YXJ0b3MgPC0gcmVhZF9leGNlbCgiL1VzZXJzL2hlY3RvcmRlbGFnYXJ6YXRyZXZpbm8vTGlicmFyeS9DbG91ZFN0b3JhZ2UvR29vZ2xlRHJpdmUtaGVjdG9yZGVsYWdhcnphdEBvdXRsb29rLmNvbS9NeSBEcml2ZS9MSVQvOC4gT2N0YXZvIHNlbWVzdHJlL1BsYW5lYWNpb8yBbiBlc3RyYXRlzIFnaWNhIGJhc2FkYSBlbiBhbmFsacyBdGljYSBwcmVzY3JpcHRpdmEvTW9kdWxvIDEvbXhfc3BhdGlhbF9kYXRhL0N1YXJ0b3NPY3VwYWRvc05hY2lvbmFsLnhsc3giKQoKbXhzdGF0ZXMgPC0gc2Y6OnJlYWRfc2YoIi9Vc2Vycy9oZWN0b3JkZWxhZ2FyemF0cmV2aW5vL0xpYnJhcnkvQ2xvdWRTdG9yYWdlL0dvb2dsZURyaXZlLWhlY3RvcmRlbGFnYXJ6YXRAb3V0bG9vay5jb20vTXkgRHJpdmUvTElULzguIE9jdGF2byBzZW1lc3RyZS9QbGFuZWFjaW/MgW4gZXN0cmF0ZcyBZ2ljYSBiYXNhZGEgZW4gYW5hbGnMgXRpY2EgcHJlc2NyaXB0aXZhL01vZHVsbyAxL214X3NwYXRpYWxfZGF0YS9teF9tYXBzL214X3N0YXRlcy9tZXhsYXRsb25nLnNocCIpCmBgYAoKCiMjIyAqKjEpIEJyZXZlbWVudGUsIGRlc2NyaWJpciBjw7NtbyBlbCBhbsOhbGlzaXMgZXNwYWNpYWwgZGUgZGF0b3Mgc2UgcmVsYWNpb25hIGNvbiBsYSBoZXJyYW1pZW50YSBkZSBpbnRlbGlnZW5jaWEgZGUgbmVnb2Npb3Mg4oCcTG9jYXRpb24gSW50ZWxsaWdlbmNl4oCdLioqCkVsIGFuw6FsaXNpcyBlc3BhY2lhbCBkZSBkYXRvcyBzZSByZWxhY2lvbmEgY29uICJMb2NhdGlvbiBJbnRlbGxpZ2VuY2UiIHBvcnF1ZSBwZXJtaXRlIHZpc3VhbGl6YXIsIGFuYWxpemFyIGUgaW50ZXJwcmV0YXIgZGF0b3MgZ2VvZ3LDoWZpY29zIHBhcmEgdG9tYXIgZGVjaXNpb25lcyBlc3RyYXTDqWdpY2FzLiAiTG9jYXRpb24gSW50ZWxsaWdlbmNlIiB1dGlsaXphIGxhIHViaWNhY2nDs24gY29tbyBlamUgY2VudHJhbCBwYXJhIGlkZW50aWZpY2FyIHBhdHJvbmVzLCB0ZW5kZW5jaWFzIHkgcmVsYWNpb25lcyBlbiBsb3MgZGF0b3MsIGZhY2lsaXRhbmRvIGRlY2lzaW9uZXMgbcOhcyBpbmZvcm1hZGFzIGVuIMOhcmVhcyBjb21vIHNlbGVjY2nDs24gZGUgdWJpY2FjaW9uZXMsIGxvZ8Otc3RpY2EsIG1hcmtldGluZyBnZW9ncsOhZmljbyB5IGdlc3Rpw7NuIGRlIHJpZXNnb3MuCgojIyMgKioyKSBEZXNjcmliaXIgMyDigJMgNSBwcmluY2lwYWxlcyBkaWZlcmVuY2lhcyBlbnRyZSB1biBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwgbm8gZXNwYWNpYWwgdmVyc3VzIHVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbCBlc3BhY2lhbC4qKgoqKjEuLSBDb25zaWRlcmFjacOzbiBkZSBsYSB1YmljYWNpw7NuOioqCgotICoqTm8gZXNwYWNpYWw6KiogTm8gdG9tYSBlbiBjdWVudGEgbGEgdWJpY2FjacOzbiBnZW9ncsOhZmljYSBkZSBsYXMgb2JzZXJ2YWNpb25lcy4KCi0gKipFc3BhY2lhbDoqKiBJbmNvcnBvcmEgbGEgZGltZW5zacOzbiBlc3BhY2lhbCwgY29uc2lkZXJhbmRvIHF1ZSBsYXMgb2JzZXJ2YWNpb25lcyBjZXJjYW5hcyBwdWVkZW4gZXN0YXIgcmVsYWNpb25hZGFzLgoKKioyLi0gUHJlY2lzacOzbiBkZWwgbW9kZWxvOioqCgotICoqTm8gZXNwYWNpYWw6KiogUHVlZGUgcHJvZHVjaXIgZXN0aW1hY2lvbmVzIHNlc2dhZGFzIHNpIGV4aXN0ZSBhdXRvY29ycmVsYWNpw7NuIGVzcGFjaWFsIG5vIGNvbnNpZGVyYWRhLgoKLSAqKkVzcGFjaWFsOioqIE1lam9yYSBsYSBwcmVjaXNpw7NuIGFsIGFqdXN0YXIgcG9yIGRlcGVuZGVuY2lhcyBlc3BhY2lhbGVzLgoKKiozLi0gQXBsaWNhY2lvbmVzIHTDrXBpY2FzOioqCgotICoqTm8gZXNwYWNpYWw6KiogU2UgdXNhIGVuIGNvbnRleHRvcyBkb25kZSBsYSB1YmljYWNpw7NuIG5vIGVzIHVuIGZhY3RvciByZWxldmFudGUuCgotICoqRXNwYWNpYWw6KiogRXMgY2xhdmUgZW4gZXN0dWRpb3MgZGUgZ2VvZ3JhZsOtYSwgYmllbmVzIHJhw61jZXMsIHNhbHVkIHDDumJsaWNhLCBjcmltaW5vbG9nw61hLCBlbnRyZSBvdHJvcywgZG9uZGUgbGEgdWJpY2FjacOzbiBhZmVjdGEgZWwgZmVuw7NtZW5vIGVzdHVkaWFkby4KCiMjIyAqKjMpIEEgcGFydGlyIGRlIGxhcyBiYXNlcyBkZSBkYXRvcyDigJx0b3VyaXNtX3N0YXRlX2RhdGEueGxzeOKAnSB5IOKAnGRlc2VtcGVub19oaXN0b3JpY29faG90ZWxlc19lc3RhZG9zLnhsc3jigJ0gZXNwZWNpZmljYXIgeSBlc3RpbWFyIDEgbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbm8gZXNwYWNpYWwuKioKYGBge3J9CnN1bW1hcnkoZGYpCnN1bW1hcnkoY3VhcnRvcykKYGBgCgpgYGB7cn0KIyBVbmUgcG9yIG5vbWJyZSBkZWwgZXN0YWRvCmRmX21hcGEgPC0gbWVyZ2UobXhzdGF0ZXMsIGRmLCBieS54ID0gIkFETUlOX05BTUUiLCBieS55ID0gInN0YXRlIikKCiMgQXNlZ3VyYXJzZSBkZSBxdWUgbm8gaGF5IE5BcwpkZl9tYXBhIDwtIGRmX21hcGEgJT4lCiAgZmlsdGVyKCFpcy5uYSh0b3VyaXNtX2dkcCkgJiAhaXMubmEoY29sbGVnZV9lZHVjYXRpb24pICYgCiAgICAgICAgICFpcy5uYShyZWFsX3dhZ2UpICYgIWlzLm5hKHJhdGlvX3B1YmxpY19pbnZlc3RtZW50KSkKCiMgQWhvcmEgZ2VuZXJhIHZlY2lub3MgZGVzZGUgZGZfbWFwYQp2ZWNpbm9zIDwtIHBvbHkybmIoZGZfbWFwYSkKcGVzb3MgPC0gbmIybGlzdHcodmVjaW5vcywgc3R5bGUgPSAiVyIsIHplcm8ucG9saWN5ID0gVFJVRSkKYGBgCgpgYGB7cn0KbW9kZWxvX25vX2VzcGFjaWFsIDwtIGxtKHRvdXJpc21fZ2RwIH4gY29sbGVnZV9lZHVjYXRpb24gKyB1bmVtcGxveW1lbnQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgIGJ1c2luZXNzX2FjdGl2aXR5ICsgcmVhbF93YWdlICsgcG9wX2RlbnNpdHkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2RfZ292ZXJuYW5jZSArIHJhdGlvX3B1YmxpY19pbnZlc3RtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX21hcGEpCgpzdW1tYXJ5KG1vZGVsb19ub19lc3BhY2lhbCkKYGBgCgojIyMgKio0KSBEZSBhY3VlcmRvIGFsIEVTREEgZGUgbGEgQWN0aXZpZGFkIDEgwr9wb3JxdcOpIHPDrSAvIG5vIHNlIGp1c3RpZmljYSBlbCB1c28gZGUgYW7DoWxpc2lzIGRlIHJlZ3Jlc2nDs24gZXNwYWNpYWw/KioKU8OtIHNlIGp1c3RpZmljYSBlbCB1c28gZGUgdW4gYW7DoWxpc2lzIGRlIHJlZ3Jlc2nDs24gZXNwYWNpYWwsIHlhIHF1ZSBlbiBsYSBBY3RpdmlkYWQgMSBpZGVudGlmaWNhbW9zIHBhdHJvbmVzIGRlIGF1dG9jb3JyZWxhY2nDs24gZXNwYWNpYWwgZW4gbGFzIHZhcmlhYmxlcyBhc29jaWFkYXMgYWwgdHVyaXNtbyBlbiBsb3MgZXN0YWRvcyBkZSBNw6l4aWNvLiBBIHRyYXbDqXMgZGVsIGFuw6FsaXNpcyBFU0RBLCBzZSBvYnNlcnbDsyBxdWUgY2llcnRvcyBlc3RhZG9zIHByZXNlbnRhbiB2YWxvcmVzIHNpbWlsYXJlcyBkZSBpbmRpY2Fkb3JlcyB0dXLDrXN0aWNvcyBlbiByZWdpb25lcyBnZW9ncsOhZmljYW1lbnRlIGNlcmNhbmFzLCBsbyBxdWUgc3VnaWVyZSBkZXBlbmRlbmNpYSBlc3BhY2lhbC4KCiMjIyAqKjUpIEVzcGVjaWZpY2FyIHkgZXN0aW1hciAzIG1vZGVsb3MgZGlmZXJlbnRlcyBkZSByZWdyZXNpw7NuIGVzcGFjaWFsIChlLmcuLCBTQVIsIFNFTSwgU0RNKS4qKgpgYGB7cn0KIyBNb2RlbG8gU0FSIChTcGF0aWFsIEF1dG9yZWdyZXNzaXZlIE1vZGVsKQptb2RlbG9fc2FyIDwtIGxhZ3NhcmxtKHRvdXJpc21fZ2RwIH4gY29sbGVnZV9lZHVjYXRpb24gKyB1bmVtcGxveW1lbnQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgIGJ1c2luZXNzX2FjdGl2aXR5ICsgcmVhbF93YWdlICsgcG9wX2RlbnNpdHkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2RfZ292ZXJuYW5jZSArIHJhdGlvX3B1YmxpY19pbnZlc3RtZW50LAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl9tYXBhLCBsaXN0dyA9IHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpCgpzdW1tYXJ5KG1vZGVsb19zYXIpCmBgYAoKYGBge3J9CiMgTW9kZWxvIFNFTSAoU3BhdGlhbCBFcnJvciBNb2RlbCkKbW9kZWxvX3NlbSA8LSBlcnJvcnNhcmxtKHRvdXJpc21fZ2RwIH4gY29sbGVnZV9lZHVjYXRpb24gKyB1bmVtcGxveW1lbnQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVzaW5lc3NfYWN0aXZpdHkgKyByZWFsX3dhZ2UgKyBwb3BfZGVuc2l0eSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICBnb29kX2dvdmVybmFuY2UgKyByYXRpb19wdWJsaWNfaW52ZXN0bWVudCwKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl9tYXBhLCBsaXN0dyA9IHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpCnN1bW1hcnkobW9kZWxvX3NlbSkKYGBgCgpgYGB7cn0KIyBNb2RlbG8gU0RNIChTcGF0aWFsIER1cmJpbiBNb2RlbCkKbW9kZWxvX3NkbSA8LSBsYWdzYXJsbSh0b3VyaXNtX2dkcCB+IGNvbGxlZ2VfZWR1Y2F0aW9uICsgcmVhbF93YWdlICsgcmF0aW9fcHVibGljX2ludmVzdG1lbnQsCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX21hcGEsIGxpc3R3ID0gcGVzb3MsIHR5cGUgPSAibWl4ZWQiLCB6ZXJvLnBvbGljeSA9IFRSVUUpCgpzdW1tYXJ5KG1vZGVsb19zZG0pCmBgYAoKIyMjICoqVGFibGEgZGUgQUlDIHkgTW9yYW4qKgpgYGB7cn0KIyBDYWxjdWxhciBBSUMgeSBNb3JhbidzIHBhcmEgcmVzaWR1b3MKbW9kZWxfYV9haWMgPC0gQUlDKG1vZGVsb19ub19lc3BhY2lhbCkKbW9kZWxfYl9haWMgPC0gQUlDKG1vZGVsb19zYXIpCm1vZGVsX2NfYWljIDwtIEFJQyhtb2RlbG9fc2VtKQptb2RlbF9kX2FpYyA8LSBBSUMobW9kZWxvX3NkbSkKCiMgTW9yYW4ncyBwYXJhIHJlc2lkdW9zCm1vcmFuX2EgPC0gbW9yYW4udGVzdChyZXNpZHVhbHMobW9kZWxvX25vX2VzcGFjaWFsKSwgcGVzb3MpJGVzdGltYXRlWzFdCm1vcmFuX2IgPC0gbW9yYW4udGVzdChyZXNpZHVhbHMobW9kZWxvX3NhciksIHBlc29zKSRlc3RpbWF0ZVsxXQptb3Jhbl9jIDwtIG1vcmFuLnRlc3QocmVzaWR1YWxzKG1vZGVsb19zZW0pLCBwZXNvcykkZXN0aW1hdGVbMV0KbW9yYW5fZCA8LSBtb3Jhbi50ZXN0KHJlc2lkdWFscyhtb2RlbG9fc2RtKSwgcGVzb3MpJGVzdGltYXRlWzFdCgojIENyZWFyIHRhYmxhIGNvbXBhcmF0aXZhCmNvbXBhcmlzb25fdGFibGUgPC0gZGF0YS5mcmFtZSgKICBNb2RlbG8gPSBjKCJPTFMiLCAiU0FSIiwgIlNFTSIsICJTRE0iKSwKICBBSUMgPSBjKG1vZGVsX2FfYWljLCBtb2RlbF9iX2FpYywgbW9kZWxfY19haWMsIG1vZGVsX2RfYWljKSwKICBNb3JhbiA9IGMobW9yYW5fYSwgbW9yYW5fYiwgbW9yYW5fYywgbW9yYW5fZCksCiAgU2lnbmlmaWNhbmNpYV9Nb3JhbiA9IGMoCiAgICBpZmVsc2UobW9yYW4udGVzdChyZXNpZHVhbHMobW9kZWxvX25vX2VzcGFjaWFsKSwgcGVzb3MpJHAudmFsdWUgPCAwLjA1LCAiU8OtIiwgIk5vIiksCiAgICBpZmVsc2UobW9yYW4udGVzdChyZXNpZHVhbHMobW9kZWxvX3NhciksIHBlc29zKSRwLnZhbHVlIDwgMC4wNSwgIlPDrSIsICJObyIpLAogICAgaWZlbHNlKG1vcmFuLnRlc3QocmVzaWR1YWxzKG1vZGVsb19zZW0pLCBwZXNvcykkcC52YWx1ZSA8IDAuMDUsICJTw60iLCAiTm8iKSwKICAgIGlmZWxzZShtb3Jhbi50ZXN0KHJlc2lkdWFscyhtb2RlbG9fc2RtKSwgcGVzb3MpJHAudmFsdWUgPCAwLjA1LCAiU8OtIiwgIk5vIikKICApCikKCmthYmxlKGNvbXBhcmlzb25fdGFibGUsIGNhcHRpb24gPSAiQ29tcGFyYWNpw7NuIGRlIE1vZGVsb3MiKQpgYGAKCkVuIGxhIHRhYmxhIGVzdGEgbWFsIGRlYmlkbyBhIGxhIGVzdHJ1Y3R1cmEgZGVsIGPDs2RpZ28gcGVybyBlbCBxdWUgbm8gdGllbmUgbmFkYSBkZSBzaWduaWZpY2FuY2lhIGVuIHN1IE1vcmFuIGVzIGVsIG1vZGVsbyBTQVIgeWEgcXVlIHRpZW5lIHVuIHAtdmFsdWUgbWF5b3IgYSAwLjA1IHkgbG9zIGRlbWFzIG1vZGVsb3MgdGllbmVuIHVuIHZhbG9yIG1lbm9yIGFsIDAuMDUgbG8gcXVlIGxvcyBoYWNlIGFsdGFtZW50ZSBzaWduaWZpY2F0aXZvcy4KCiMjIyAqKjYpIEVzcGVjaWZpY2FyIHkgZXN0aW1hciAxIG1vZGVsbyBkZSByZWdyZXNpw7NuIG1lZGlhbnRlIGVsIHVzbyBkZSBtYWNoaW5lIGxlYXJuaW5nIChlLmcuLCBzdXBwb3J0IHZlY3RvciBtYWNoaW5lLCBkZWNpc2lvbiB0cmVlcywgcmFuZG9tIGZvcmVzdCwgWEdCb29zdCByZWdyZXNzaW9uLCBldGMuKSoqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkocmFuZG9tRm9yZXN0KQoKc2V0LnNlZWQoMTIzKQptb2RlbG9fcmYgPC0gcmFuZG9tRm9yZXN0KHRvdXJpc21fZ2RwIH4gY29sbGVnZV9lZHVjYXRpb24gKyB1bmVtcGxveW1lbnQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1c2luZXNzX2FjdGl2aXR5ICsgcmVhbF93YWdlICsgcG9wX2RlbnNpdHkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2RfZ292ZXJuYW5jZSArIHJhdGlvX3B1YmxpY19pbnZlc3RtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZiwgaW1wb3J0YW5jZSA9IFRSVUUpCgpwcmludChtb2RlbG9fcmYpCmltcG9ydGFuY2UobW9kZWxvX3JmKQpgYGAKCiMjIyAqKjcpIE1lZGlhbnRlIGVsIHVzbyBkZSBSb290IE1lYW4gU3F1YXJlIEVycm9yIOKAkyBSTVNFIHNlbGVjY2lvbmFyIDEtMiBtb2RlbG9zIGRlIHJlZ3Jlc2nDs24gZXN0aW1hZG9zIGVuIDMpIC0gNikgeSBkZXNjcmliaXIgbG9zIHByaW5jaXBhbGVzIHJlc3VsdGFkb3MgZXN0aW1hZG9zLioqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoTWV0cmljcykKCiMgUHJlZGljY2lvbmVzCnByZWRfbm9fZXNwYWNpYWwgPC0gcHJlZGljdChtb2RlbG9fbm9fZXNwYWNpYWwsIGRmKQpwcmVkX3JmIDwtIHByZWRpY3QobW9kZWxvX3JmLCBkZikKCiMgUk1TRQpybXNlX25vX2VzcGFjaWFsIDwtIHJtc2UoZGYkdG91cmlzbV9nZHAsIHByZWRfbm9fZXNwYWNpYWwpCnJtc2VfcmYgPC0gcm1zZShkZiR0b3VyaXNtX2dkcCwgcHJlZF9yZikKCnJtc2Vfbm9fZXNwYWNpYWwKcm1zZV9yZgpgYGAKCiMjIyAqKjgpIERlc2NyaWJpciBsb3MgcHJpbmNpcGFsZXMgNSDigJMgNyBoYWxsYXpnb3MgZGVsIGFuw6FsaXNpcyBkZSByZWdyZXNpw7NuIG5vIGVzcGFjaWFsIHkgZXNwYWNpYWwuIFByaW5jaXBhbG1lbnRlLCDCv2PDs21vIGVzIGVsIGltcGFjdG8gZGUgbGFzIHZhcmlhYmxlcyBxdWUgaW5jbHV5ZW4gdW5hIGVzcGVjaWZpY2FjacOzbiBlc3BhY2lhbCBkZSBlc3RhZG9zIHZlY2lub3MgKFcpIHNvYnJlIGxhIHZhcmlhYmxlIGRlcGVuZGllbnRlIFk/KioKMS4gQ2FwYWNpZGFkIGV4cGxpY2F0aXZhIGRlbCBtb2RlbG8gT0xTOiBFbCBtb2RlbG8gbm8gZXNwYWNpYWwgZXhwbGljYSBhbHJlZGVkb3IgZGVsIDc0JSBkZSBsYSB2YXJpYWNpw7NuIGVuIHRvdXJpc21fZ2RwLCBtb3N0cmFuZG8gc2lnbmlmaWNhbmNpYSBlbiB2YXJpYWJsZXMgY29tbyBjb2xsZWdlX2VkdWNhdGlvbiwgcmVhbF93YWdlLCBwb3BfZGVuc2l0eSwgZ29vZF9nb3Zlcm5hbmNlIHkgcmF0aW9fcHVibGljX2ludmVzdG1lbnQuCjIuIEV2aWRlbmNpYSBkZSBkZXBlbmRlbmNpYSBlc3BhY2lhbDogTG9zIG1vZGVsb3MgZXNwYWNpYWxlcyAoU0FSLCBTRU0geSBTRE0pIGRldGVjdGFuIGF1dG9jb3JyZWxhY2nDs24gZXNwYWNpYWwsIGxvIHF1ZSBpbmRpY2EgcXVlIGxvcyBlc3RhZG9zIHZlY2lub3MgaW5mbHV5ZW4gZW4gbGEgYWN0aXZpZGFkIHR1csOtc3RpY2EuCjMuIEltcGFjdG8gZGUgbGEgZXN0cnVjdHVyYSBlc3BhY2lhbCAoVyk6IEVuIGVsIG1vZGVsbyBTQVIsIGVsIHBhcsOhbWV0cm8gZXNwYWNpYWwgKM+BIOKJiCAtMC40Mykgc3VnaWVyZSBxdWUgYWx0b3MgdmFsb3JlcyBkZSB0b3VyaXNtX2dkcCBlbiBlc3RhZG9zIHZlY2lub3Mgc2UgYXNvY2lhbiBhIHVuYSByZWR1Y2Npw7NuIGVuIGVsIGVzdGFkbyBlbiBhbsOhbGlzaXMsIGV2aWRlbmNpYW5kbyBlZmVjdG9zIGRlIGNvbXBldGVuY2lhIG8gcmVkaXN0cmlidWNpw7NuLgo0LiBNZWpvcmEgZW4gbGEgcHJlY2lzacOzbiBwcmVkaWN0aXZhIGNvbiBtYWNoaW5lIGxlYXJuaW5nOiBFbCBtb2RlbG8gUmFuZG9tIEZvcmVzdCBwcmVzZW50YSB1biBSTVNFIGRlIDk5MzgsIHNpZ25pZmljYXRpdmFtZW50ZSBtZW5vciBxdWUgZWwgZGVsIG1vZGVsbyBPTFMgKDM2OTEyKSwgbG8gcXVlIGluZGljYSB1bmEgbWF5b3IgY2FwYWNpZGFkIHByZWRpY3RpdmEgYWwgY2FwdHVyYXIgbGEgY29tcGxlamlkYWQgZGVsIGZlbsOzbWVuby4KNS4gQ29uc2lzdGVuY2lhIGVuIGxhIHNpZ25pZmljYW5jaWEgZGUgdmFyaWFibGVzIGNsYXZlOiBWYXJpYWJsZXMgY29tbyBwb3BfZGVuc2l0eSwgZ29vZF9nb3Zlcm5hbmNlIHkgcmF0aW9fcHVibGljX2ludmVzdG1lbnQgcmVzdWx0YW4gY29uc2lzdGVudGVzIGVuIHN1IGltcGFjdG8gZW4gdG9kb3MgbG9zIG1vZGVsb3MsIHJlc2FsdGFuZG8gc3UgaW1wb3J0YW5jaWEgdGFudG8gZW4gY29udGV4dG9zIG5vIGVzcGFjaWFsZXMgY29tbyBlc3BhY2lhbGVzLgoKCgojIyMgKio5KSBBIHBhcnRpciBkZSBsb3MgbW9kZWxvcyBkZSByZWdyZXNpw7NuIHNlbGVjY2lvbmFkb3MgeSBsb3MgaGFsbGF6Z29zIGlkZW50aWZpY2Fkb3MgZGVzY3JpYmlyIDIg4oCTIDMgc3VnZXJlbmNpYXMgcmVsYWNpb25hZGFzIGNvbiBsYSB0b21hIGRlIGRlY2lzaW9uZXMgcGFyYToqKgojIyMjICoqYS4gSWRlbnRpZmljYXIgbGFzIHZhcmlhYmxlcyBxdWUgZXhwbGljYW4gdW4gaW5jcmVtZW50byAvIGRpc21pbnVjacOzbiBlbiBsYSBhY3RpdmlkYWQgdHVyw61zdGljYSBhIG5pdmVsIGVzdGF0YWwqKgotICoqQW7DoWxpc2lzIGRlIHZhcmlhYmxlcyBzb2Npb2Vjb27Ds21pY2FzIGUgaW5zdGl0dWNpb25hbGVzOioqCiAgLSAgICoqQ29sbGVnZV9lZHVjYXRpb246KiogRWwgbW9kZWxvIG5vIGVzcGFjaWFsIHkgbG9zIG1vZGVsb3MgZXNwYWNpYWxlcyBpbmRpY2FuIHF1ZSBtYXlvcmVzIG5pdmVsZXMgZWR1Y2F0aXZvcyAobWVkaWRvcyBlbiBsYSBwcm9wb3JjacOzbiBkZSBwb2JsYWNpw7NuIGNvbiBlZHVjYWNpw7NuIHVuaXZlcnNpdGFyaWEpIHB1ZWRlbiBhc29jaWFyc2UgY29uIHVuYSBkaXNtaW51Y2nDs24gZW4gdG91cmlzbV9nZHAsIGxvIHF1ZSBzdWdpZXJlIGxhIG5lY2VzaWRhZCBkZSBwcm9mdW5kaXphciBlbiBlbCByb2wgZGUgbGEgZWR1Y2FjacOzbiBlbiBsYSBjb21wZXRpdGl2aWRhZCB0dXLDrXN0aWNhLgogIC0gICAqKlJlYWxfd2FnZSB5IHBvcF9kZW5zaXR5OioqIEFtYm9zIHNlIG11ZXN0cmFuIGNvbW8gZmFjdG9yZXMgc2lnbmlmaWNhdGl2b3MgeSBwb3NpdGl2b3M7IHNhbGFyaW9zIG3DoXMgYWx0b3MgeSB1bmEgbWF5b3IgZGVuc2lkYWQgcG9ibGFjaW9uYWwgc2UgYXNvY2lhbiBjb24gdW4gaW5jcmVtZW50byBlbiBsYSBhY3RpdmlkYWQgdHVyw61zdGljYSwgbG8gcXVlIGltcGxpY2EgcXVlIGludmVydGlyIGVuIHNlY3RvcmVzIGdlbmVyYWRvcmVzIGRlIGVtcGxlbyB5IGVuIMOhcmVhcyBkZSBhbHRhIGNvbmNlbnRyYWNpw7NuIHBvYmxhY2lvbmFsIHB1ZWRlIGZhdm9yZWNlciBsYSBlY29ub23DrWEgdHVyw61zdGljYS4KCi0gKipJbnZlcnNpw7NuIHDDumJsaWNhIGUgw61uZGljZXMgZGUgZ29iZXJuYW56YToqKgogIC0gICAqKkdvb2RfZ292ZXJuYW5jZSB5IHJhdGlvX3B1YmxpY19pbnZlc3RtZW50Kiogc29uIGRldGVybWluYW50ZXMgY2xhdmUgZW4gbG9zIG1vZGVsb3MsIHlhIHF1ZSBpbmRpY2FuIHF1ZSBtZWpvcmFzIGVuIGxhIGNhbGlkYWQgZGVsIGdvYmllcm5vIHkgdW5hIGludmVyc2nDs24gcMO6YmxpY2EgYmllbiBkaXJpZ2lkYSBwdWVkZW4gaW1wYWN0YXIgcG9zaXRpdmFtZW50ZSAobywgZW4gZWwgY2FzbyBkZSByYXRpb19wdWJsaWNfaW52ZXN0bWVudCwgaW5jbHVzbyBkZSBmb3JtYSBuZWdhdGl2YSBzaSBzZSBpbnRlcnByZXRhIGNvbW8gdW4gZXhjZXNvIG8gbWFsYSBhc2lnbmFjacOzbiBkZSByZWN1cnNvcykgbGEgYWN0aXZpZGFkIHR1csOtc3RpY2EuCgojIyMjICoqYi4gSW5jcmVtZW50YXIgbGEgYWN0aXZpZGFkIHR1csOtc3RpY2EgYSBuaXZlbCByZWdpb25hbCBkZSBlbnRpZGFkZXMgZmVkZXJhdGl2YXMgc2VsZWNjaW9uYWRhcyoqCioqMS4gRm9tZW50byBkZSBhbGlhbnphcyB5IHByb21vY2nDs24gcmVnaW9uYWwgY29uanVudGE6KioKICAtIERhZG8gcXVlIGxhIHJlZ3Jlc2nDs24gZXNwYWNpYWwgKHBvciBlamVtcGxvLCBlbCBtb2RlbG8gU0FSIGNvbiBzdSBwYXLDoW1ldHJvIGVzcGFjaWFsIG5lZ2F0aXZvKSBldmlkZW5jaWEgcXVlIGVsIHR1cmlzbW8gZW4gdW4gZXN0YWRvIGluZmx1eWUgZW4gc3VzIGVzdGFkb3MgdmVjaW5vcywgc2UgcmVjb21pZW5kYSBkaXNlw7FhciBlc3RyYXRlZ2lhcyBkZSBwcm9tb2Npw7NuIGNvbmp1bnRhIHkgZGVzYXJyb2xsbyBkZSBpbmZyYWVzdHJ1Y3R1cmEgY29tcGFydGlkYS4gRXN0byBwZXJtaXRpcsOtYSBhcHJvdmVjaGFyIGVjb25vbcOtYXMgZGUgZXNjYWxhIHkgcmVkdWNpciBsYSBjb21wZXRlbmNpYSBpbnRlcm5hIGVudHJlIGVzdGFkb3MgY29saW5kYW50ZXMuCgoqKjIuIEZvY2FsaXphY2nDs24gZGUgaW52ZXJzaW9uZXMgZW4gdmFyaWFibGVzIGRldGVybWluYW50ZXM6KioKICAtIE9yaWVudGFyIHJlY3Vyc29zIGhhY2lhIG1lam9yYXMgZW4gZ29iZXJuYW56YSwgY2FsaWRhZCBkZSBzZXJ2aWNpb3MgKHJlZmxlamFkYXMgZW4gbWVqb3JlcyBzYWxhcmlvcyB5IGNvbmRpY2lvbmVzIGxhYm9yYWxlcykgeSBlbiBsYSBvcHRpbWl6YWNpw7NuIGRlIGxhIGludmVyc2nDs24gcMO6YmxpY2EgcHVlZGUgcG90ZW5jaWFyIGxhIGFjdGl2aWRhZCB0dXLDrXN0aWNhLiBFbiByZWdpb25lcyBkb25kZSBzZSBvYnNlcnZhIGFsdGEgZGVuc2lkYWQgcG9ibGFjaW9uYWwsIHJlZm9yemFyIGxvcyBzZXJ2aWNpb3MgdHVyw61zdGljb3MgeSBmYWNpbGl0YXIgbGEgY29uZWN0aXZpZGFkIHBvZHLDrWEgZ2VuZXJhciB1biBtYXlvciBhdHJhY3Rpdm8gcGFyYSBsb3MgdmlzaXRhbnRlcy4KCioqMy4gSW50ZWdyYWNpw7NuIGRlIGxhIG9mZXJ0YSBob3RlbGVyYSBhIGxhIGVzdHJhdGVnaWEgdHVyw61zdGljYToqKgogIC0gTG9zIGRhdG9zIGRlbCBkZXNlbXBlw7FvIGRlIGxhIG9jdXBhY2nDs24gaG90ZWxlcmEgZGViZW4gdXRpbGl6YXJzZSBwYXJhIGlkZW50aWZpY2FyIGN1ZWxsb3MgZGUgYm90ZWxsYSBlbiBsYSBjYXBhY2lkYWQgZGUgYWJzb3JjacOzbiBkZSB0dXJpc3Rhcy4gTGEgY29vcmRpbmFjacOzbiBlbnRyZSBhdXRvcmlkYWRlcyBlc3RhdGFsZXMgeSBwcml2YWRvcyAocG9yIGVqZW1wbG8sIGVuIGxhIHByb21vY2nDs24gZGUgbGEgb2N1cGFjacOzbiBlbiB0ZW1wb3JhZGFzIGJhamFzIG8gbGEgbWVqb3JhIGRlIHNlcnZpY2lvcykgc2UgdHJhZHVjZSBlbiB1bmEgZXN0cmF0ZWdpYSBpbnRlZ3JhbCBwYXJhIHBvdGVuY2lhciBsYSBhY3RpdmlkYWQgdHVyw61zdGljYSByZWdpb25hbC4KCgo=