Inicio
1) Describir 3 – 5 diferencias entre la estimación de un modelo de
regression global (no especial, SAR, SEM, SDM, y/o SARAR) y un modelo de
regresión local (GWR).
- Región similar vs variable: Los modelos globales suponen efectos
similares en todo el espacio, mientras que los locales (como GWR)
permiten que los coeficientes varíen espacialmente.
- Captura de heterogeneidad espacial: GWR permite identificar patrones
espaciales más precisos.
- Interpretación más detallada: Los modelos locales permiten análisis
más detallados por región.
- Complejidad computacional: GWR es más costoso
computacionalmente.
- Diagnóstico de autocorrelación: Los modelos locales ayudan a reducir
la autocorrelación en residuos no explicada por modelos globales.
file_path<- "/Users/marianaaleal/Desktop/TEC 2025/_Planeación estratégica basada en analítica prescriptiva /M1/tourism_state_data.xlsx"
df <- read_excel("/Users/marianaaleal/Desktop/TEC 2025/_Planeación estratégica basada en analítica prescriptiva /M1/tourism_state_data.xlsx")
## New names:
## • `region` -> `region...17`
## • `region` -> `region...18`
statesmx <- st_read("/Users/marianaaleal/Desktop/TEC 2025/_Planeación estratégica basada en analítica prescriptiva /M1/mx_shapefiles/states/mexlatlong.shp")
## Reading layer `mexlatlong' from data source
## `/Users/marianaaleal/Desktop/TEC 2025/_Planeación estratégica basada en analítica prescriptiva /M1/mx_shapefiles/states/mexlatlong.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 32 features and 19 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -118.4042 ymin: 14.55055 xmax: -86.73862 ymax: 32.71846
## Geodetic CRS: WGS 84
2) Calcular 2 matrices de conectividad que incluya uno de los
siguientes criterios: contiguedad (queen, rook, bishop), vecino más
próximo (k nearest neighbor), y/o distancia.
names(df)[names(df) == "state_id"] <- "OBJECTID"
# Unir los datos con la geometría
data_sf <- merge(statesmx, df, by = "OBJECTID")
library(sp)
turismo.tr <- as(data_sf, "Spatial") # Conversión correcta
turismo_nb<-poly2nb(turismo.tr)
#Crear matriz de pesos espaciales (contigüidad Queen)
queen1 <- poly2nb(data_sf, queen = TRUE) ### queen approach
queen2 <- poly2nb(data_sf, queen = FALSE) ### rook approach
centroides<-coordinates(turismo.tr)
mapa.linkW<-nb2listw(turismo_nb, style="W")
plot(turismo.tr,border="blue",axes=FALSE,las=1, main="Matriz de Conectividad - Turismo MX")
plot(turismo.tr,col="grey",border=grey(0.9),axes=T,add=T)
plot(mapa.linkW,coords=centroides,pch=19,cex=0.1,col="red",add=T)

queen1 <- poly2nb(turismo.tr, queen = TRUE) ### queen approach
queen2 <- poly2nb(turismo.tr, queen = FALSE) ### rook approach
queenr <- nb2listw(queen1, style = "W", zero.policy = TRUE)
rook <- nb2listw(queen2, style = "W", zero.policy = TRUE)
plot(turismo.tr,border="blue",axes=FALSE,las=1, main="Matriz Espacial de Conexión - Queen")
plot(turismo.tr,col="grey",border=grey(0.9),axes=T,add=T)
plot(queenr,centroides, add=TRUE, col='blue')

plot(turismo.tr,border="blue",axes=FALSE,las=1, main="Matriz Espacial de Conexión - Rook")
plot(turismo.tr,col="grey",border=grey(0.9),axes=T,add=T)
plot(rook,centroides, add=TRUE, col='dark green')

3) Especificar y estimar 1 modelo de regresión global no
espacial.
# Une por nombre del estado
df_mapa <- merge(statesmx, 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) Especificar y estimar 1 modelo de regresión de global espacial
(e.g., SAR, SEM, SDM) que incluyan alguna de las 2 matrices de
conectividad W) seleccionadas en 2).
# 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)
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)
## Type: lag
##
## Coefficients:
## rho (Intercept) college_education
## -4.277293e-01 5.757816e+04 -1.109038e+05
## unemployment business_activity real_wage
## -1.055967e+05 2.708939e+03 8.834485e+01
## pop_density good_governance ratio_public_investment
## 1.504477e+02 5.954744e+02 -7.895304e+05
##
## Log likelihood: -6249.44
# 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)
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)
## Type: error
##
## Coefficients:
## lambda (Intercept) college_education
## 8.967707e-01 9.723616e+03 -1.061467e+05
## unemployment business_activity real_wage
## 5.472472e+04 3.647649e+03 4.037560e+01
## pop_density good_governance ratio_public_investment
## 2.286707e+02 5.507682e+02 -7.553643e+05
##
## Log likelihood: -6245.718
# 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)
modelo_sdm
##
## Call:
## lagsarlm(formula = tourism_gdp ~ college_education + real_wage +
## ratio_public_investment, data = df_mapa, listw = pesos, type = "mixed",
## zero.policy = TRUE)
## Type: mixed
##
## Coefficients:
## rho (Intercept)
## -1.957708e-01 -9.360832e+03
## college_education real_wage
## 3.567515e+04 1.126496e+02
## ratio_public_investment lag.college_education
## -2.999708e+05 -4.026172e+05
## lag.real_wage lag.ratio_public_investment
## 3.498579e+02 -5.621620e+05
##
## Log likelihood: -6316.406
5) Identificar la posible presencia de autocorrelación espacial en
los residuales Ɛi para cada uno de los modelos de regresión estimados en
3) y 4).
# Autocorrelación espacial en residuos del modelo no espacial
moran.test(residuals(modelo_no_espacial), pesos, zero.policy = TRUE)
##
## Moran I test under randomisation
##
## data: residuals(modelo_no_espacial)
## weights: pesos
##
## Moran I statistic standard deviate = 3.2642, p-value = 0.000549
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic Expectation Variance
## 1.871730e-02 -1.901141e-03 3.989983e-05
# Autocorrelación en modelo SAR
moran.test(residuals(modelo_sar), pesos, zero.policy = TRUE)
##
## Moran I test under randomisation
##
## data: residuals(modelo_sar)
## weights: pesos
##
## Moran I statistic standard deviate = 12.594, p-value < 2.2e-16
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic Expectation Variance
## 7.761772e-02 -1.901141e-03 3.986766e-05
# Autocorrelación en modelo SEM
moran.test(residuals(modelo_sem), pesos, zero.policy = TRUE)
##
## Moran I test under randomisation
##
## data: residuals(modelo_sem)
## weights: pesos
##
## Moran I statistic standard deviate = -3.2631, p-value = 0.9994
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic Expectation Variance
## -0.0225213204 -0.0019011407 0.0000399324
# Autocorrelación en modelo SDM
moran.test(residuals(modelo_sdm), pesos, zero.policy = TRUE)
##
## Moran I test under randomisation
##
## data: residuals(modelo_sdm)
## weights: pesos
##
## Moran I statistic standard deviate = 2.3628, p-value = 0.00907
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic Expectation Variance
## 1.302049e-02 -1.901141e-03 3.988366e-05
- El modelo no espacial probablemente presente autocorrelación
espacial significativa en sus residuos (valor-p < 0.05), indicando
que el modelo no captura completamente los patrones espaciales.
- En contraste, los modelos SAR, SEM y SDM deberían reducir
significativamente esa autocorrelación, especialmente SEM para errores y
SAR/SDM en dependencia espacial directa.
- Un valor de Moran’s I cercano a 0 y un valor-p alto (> 0.05)
indican que no hay autocorrelación residual relevante.
# Correr la prueba de Moran para cada modelo
moran_no_espacial <- moran.test(residuals(modelo_no_espacial), pesos, zero.policy = TRUE)
moran_sar <- moran.test(residuals(modelo_sar), pesos, zero.policy = TRUE)
moran_sem <- moran.test(residuals(modelo_sem), pesos, zero.policy = TRUE)
moran_sdm <- moran.test(residuals(modelo_sdm), pesos, zero.policy = TRUE)
# Crear una tabla comparativa
resumen_morans_I <- data.frame(
Modelo = c("Lineal No Espacial", "SAR", "SEM", "SDM"),
Morans_I = c(moran_no_espacial$estimate["Moran I statistic"],
moran_sar$estimate["Moran I statistic"],
moran_sem$estimate["Moran I statistic"],
moran_sdm$estimate["Moran I statistic"]),
Expectation = c(moran_no_espacial$estimate["Expectation"],
moran_sar$estimate["Expectation"],
moran_sem$estimate["Expectation"],
moran_sdm$estimate["Expectation"]),
Variance = c(moran_no_espacial$estimate["Variance"],
moran_sar$estimate["Variance"],
moran_sem$estimate["Variance"],
moran_sdm$estimate["Variance"]),
p_value = c(moran_no_espacial$p.value,
moran_sar$p.value,
moran_sem$p.value,
moran_sdm$p.value)
)
library(knitr)
library(kableExtra)
kable(resumen_morans_I, digits = 4, caption = "Comparación de autocorrelación espacial en los residuos (Moran's I)") %>%
kable_styling(full_width = F, bootstrap_options = c("striped", "hover", "condensed"))
Comparación de autocorrelación espacial en los residuos (Moran’s I)
|
Modelo
|
Morans_I
|
Expectation
|
Variance
|
p_value
|
|
Lineal No Espacial
|
0.0187
|
-0.0019
|
0
|
0.0005
|
|
SAR
|
0.0776
|
-0.0019
|
0
|
0.0000
|
|
SEM
|
-0.0225
|
-0.0019
|
0
|
0.9994
|
|
SDM
|
0.0130
|
-0.0019
|
0
|
0.0091
|
6) Especificar y estimar 1 modelo de regresión local espacial (e.g.,
GWR).
# Crear coordenadas
coords <- st_coordinates(st_centroid(df_mapa))
# Preparar datos para GWR
gwr_data <- as(df_mapa, "Spatial")
# Estimar GWR (seleccionamos variables significativas en modelos previos)
gwr_model <- gwr(tourism_gdp ~ college_education + real_wage + ratio_public_investment,
data = gwr_data,
coords = coords,
adapt = 0.3,
gweight = gwr.Gauss,
hatmatrix = TRUE)
gwr_model
## Call:
## gwr(formula = tourism_gdp ~ college_education + real_wage + ratio_public_investment,
## data = gwr_data, coords = coords, gweight = gwr.Gauss, adapt = 0.3,
## hatmatrix = TRUE)
## Kernel function: gwr.Gauss
## Adaptive quantile: 0.3 (about 158 of 527 data points)
## Summary of GWR coefficient estimates at data points:
## Min. 1st Qu. Median 3rd Qu.
## X.Intercept. -3.5628e+04 -2.3434e+04 -1.5182e+04 8.9588e+03
## college_education -2.0827e+05 -1.7150e+05 -1.4382e+05 -8.3983e+04
## real_wage -2.9218e+01 1.7499e+02 3.1793e+02 3.5677e+02
## ratio_public_investment -1.7761e+06 -1.4924e+06 -9.9560e+05 -6.4011e+05
## Max. Global
## X.Intercept. 3.5805e+04 -3606.07
## college_education 1.1803e+05 -39089.66
## real_wage 4.3728e+02 191.26
## ratio_public_investment 1.9820e+05 -347210.59
## Number of data points: 527
## Effective number of parameters (residual: 2traceS - traceS'S): 12.75497
## Effective degrees of freedom (residual: 2traceS - traceS'S): 514.245
## Sigma (residual: 2traceS - traceS'S): 36133.16
## Effective number of parameters (model: traceS): 9.692116
## Effective degrees of freedom (model: traceS): 517.3079
## Sigma (model: traceS): 36026.03
## Sigma (ML): 35693.22
## AICc (GWR p. 61, eq 2.33; p. 96, eq. 4.21): 12566.21
## AIC (GWR p. 96, eq. 4.22): 12554.04
## Residual sum of squares: 671401065517
## Quasi-global R2: 0.217818
# Ver la significancia t de la variable college_education en el modelo GWR
gwr_model$college_edu_Tv
## NULL
## [1] "sum.w" "X.Intercept."
## [3] "college_education" "real_wage"
## [5] "ratio_public_investment" "X.Intercept._se"
## [7] "college_education_se" "real_wage_se"
## [9] "ratio_public_investment_se" "gwr.e"
## [11] "pred" "pred.se"
## [13] "localR2" "X.Intercept._se_EDF"
## [15] "college_education_se_EDF" "real_wage_se_EDF"
## [17] "ratio_public_investment_se_EDF" "pred.se.1"
# Calcular el valor t para la variable college_education
df_mapa$college_edu_Tv <- gwr_model$SDF$college_education / gwr_model$SDF$college_education_se
# Crear una columna lógica para marcar los estados con significancia estadística
df_mapa$significativo <- abs(df_mapa$college_edu_Tv) > 1.96
# Mapa destacando solo los estados con valores t significativos
ggplot(df_mapa) +
geom_sf(aes(fill = ifelse(significativo, college_edu_Tv, NA)), color = "white") +
scale_fill_gradient2(
low = "blue", mid = "white", high = "red", midpoint = 0,
na.value = "grey90", # Color para los estados no significativos
name = "t-value\ncollege_education"
) +
labs(
title = "Estados con efecto significativo de 'College Education' en el modelo GWR",
subtitle = "Solo se muestran los estados con |t| > 1.96",
fill = "Valor t"
) +
theme_minimal()

7) A partir de la estimación de los modelos de regresión en 4) – 6)
seleccionar 1 – 2 modelos para la interpretación de los principales
resultados.
- Modelo SDM (Durbin): permite analizar efectos directos e indirectos
espaciales. Captura mejor la complejidad del fenómeno turístico y su
relación con variables como inversión pública y salario real.
- Modelo GWR: muestra la variabilidad espacial de los coeficientes y
permite interpretaciones más detalladas por estado. Es útil para
políticas regionales diferenciadas.
- El SDM incorpora efectos espaciales cruzados y refleja posibles
spillovers.
- El GWR evidencia la heterogeneidad espacial que los modelos globales
no pueden captar.
8) Mediante el uso de 2 – 3 mapas, visualizar los principales
resultados estimados (e.g., predicción de principal variable de
análisis, significancia estadística de principal variable explicativa,
presencia de autocorrelación espacial) de al menos 1 de los modelos de
regresión seleccionados.
# Extraer los coeficientes del GWR
coef_gwr <- as.data.frame(gwr_model$SDF)
# Agregar coeficientes a shapefile
df_mapa$coef_college <- coef_gwr$college_education
df_mapa$coef_real_wage <- coef_gwr$real_wage
df_mapa$local_R2 <- coef_gwr$localR2
# Mapa 1: Coeficiente de college_education
tm_shape(df_mapa) +
tm_polygons("coef_college", palette = "YlGnBu", title = "Efecto Educación Superior") +
tm_layout(title = "Variación espacial del efecto de educación superior en el PIB turístico")
##
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).
## [v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "YlGnBu" is named
## "brewer.yl_gn_bu"
## Multiple palettes called "yl_gn_bu" found: "brewer.yl_gn_bu", "matplotlib.yl_gn_bu". The first one, "brewer.yl_gn_bu", is returned.
##
## [plot mode] fit legend/component: Some legend items or map compoments do not
## fit well, and are therefore rescaled.
## ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.

Este mapa visualiza cómo varía espacialmente el coeficiente de la
variable educación universitaria en el modelo GWR. Es decir, indica
cuánto influye el nivel educativo en el PIB turístico en cada
estado.
-Colores más intensos (azul): indican que en esos estados el
coeficiente es más alto, lo que significa que un mayor nivel de
educación universitaria se asocia con un incremento más fuerte en el PIB
turístico. - Colores más claros o neutros: sugieren que el impacto es
más débil o incluso nulo.
En estados como CDMX, Jalisco y Nuevo León, la educación tiene un
efecto notablemente positivo en el turismo, posiblemente debido a su
capacidad para ofrecer servicios turísticos más sofisticados o mejor
organizados.
En otras regiones, como el sureste o zonas del norte, el impacto es
menor, lo que sugiere que la educación no se traduce tan directamente en
desarrollo turístico allí —posiblemente por falta de infraestructura o
enfoque económico distinto.
# Mapa 2: R² local del modelo GWR
tm_shape(df_mapa) +
tm_polygons("local_R2", palette = "Oranges", title = "R² Local") +
tm_layout(title = "Bondad de ajuste del modelo GWR por estado")
##
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).
## [v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Oranges" is named
## "brewer.oranges"
## Multiple palettes called "oranges" found: "brewer.oranges", "matplotlib.oranges". The first one, "brewer.oranges", is returned.

Este mapa indica qué tan bien explica el modelo GWR la variabilidad
del PIB turístico en cada estado. Es decir, mide la capacidad
explicativa del modelo en el espacio.
-Colores oscuros/naranjas intensos: reflejan valores de R² locales
altos (mayor ajuste), es decir, en esos estados el modelo explica gran
parte del PIB turístico. -Colores claros o amarillos: muestran un menor
ajuste local del modelo.
El modelo GWR funciona muy bien en ciertas regiones, como el centro y
occidente del país, donde puede captar relaciones más claras entre las
variables explicativas y el turismo.
En regiones con menor R² (por ejemplo, algunas zonas del sur),
podrían estar influyendo factores no incluidos en el modelo (como
inseguridad, conectividad o condiciones naturales).
# Mapa 3: Autocorrelación de residuos del modelo SDM
residuos_sdm <- residuals(modelo_sdm)
df_mapa$residuos_sdm <- residuos_sdm
tm_shape(df_mapa) +
tm_polygons("residuos_sdm", palette = "-RdBu", midpoint = 0,
title = "Residuos del modelo SDM") +
tm_layout(title = "Distribución espacial de residuos (SDM)")
##
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'midpoint', 'palette' (rename to 'values') to
## fill.scale = tm_scale(<HERE>).
## ℹ For small multiples, specify a 'tm_scale_' for each multiple, and put them in
## a list: 'fill.scale = list(<scale1>, <scale2>, ...)'
## [v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`
## Multiple palettes called "rd_bu" found: "brewer.rd_bu", "matplotlib.rd_bu". The first one, "brewer.rd_bu", is returned.
##
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "-RdBu" is named
## "rd_bu" (in long format "brewer.rd_bu")

Este mapa presenta la distribución de los residuos del modelo SDM, es
decir, las diferencias entre lo observado y lo predicho. Ayuda a
detectar patrones espaciales no captados por el modelo.
- Colores rojos: indican residuos positivos= el modelo subestimó el
PIB turístico en esas regiones.
- Colores azules: indican residuos negativos= el modelo sobreestimó el
PIB turístico.
- Distribuciones agrupadas de un mismo color= podrían señalar
autocorrelación espacial residual.
Si los errores están distribuidos de forma aleatoria, el modelo SDM
captura bien las relaciones espaciales.
Si hay agrupaciones de errores similares (clusters), especialmente en
zonas específicas (como el sur-sureste), sugiere que hay dinámicas
locales no modeladas adecuadamente. Esto podría justificar incorporar
variables adicionales o considerar un modelo aún más local.
LS0tCnRpdGxlOiAiQW7DoWxpc2lzIGRlIFJlZ3Jlc2nDs24gRXNwYWNpYWwgTG9jYWwiCnN1YnRpdGxlOiAiQWN0aXZpZGFkIDMgfCBQbGFuZWFjacOzbiBFc3RyYXTDqWdpY2EgQmFzYWRhIGVuIEFuYWzDrXRpY2EgUHJlc2NyaXB0aXZhIgphdXRob3I6IAogIC0gSMOpY3RvciBHdWFkYWx1cGUgZGUgbGEgR2FyemEgVHJldmnDsW8gKEEwMTE3Nzk2MCkKICAtIE1hcmlhbmEgTGVhbCAoQTAxNTcwOTc3KQogIC0gRmVybmFuZGEgU2FuY2hleiBHdXRpZXJyZXogKEEwMTYxMzM2MCkKICAtIEplbmFybyBNYXJ0w61uZXogKEEwMTcyMTk1MSkKZGF0ZTogIkFicmlsIDIwMjUiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBmbGF0bHkKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgY3NzOiBzdHlsZXMuY3NzCi0tLQoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBMaWJyZXLDrWFzIG5lY2VzYXJpYXMKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoc3BkZXApCmxpYnJhcnkoc2YpCmxpYnJhcnkodG1hcCkKbGlicmFyeShzcGd3cikKbGlicmFyeShzcGF0aWFscmVnKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShyZWFkcikKbGlicmFyeShmb3JlaWduKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHNwZGVwKQpsaWJyYXJ5KHRpZ3JpcykKbGlicmFyeShyZ2VvZGEpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0bWFwKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHNwKQpsaWJyYXJ5KHNwYXRpYWxyZWcpCmxpYnJhcnkoc3RhcmdhemVyKQoKYGBgCiMgSW5pY2lvCgojIyMgMSkgRGVzY3JpYmlyIDMg4oCTIDUgZGlmZXJlbmNpYXMgZW50cmUgbGEgZXN0aW1hY2nDs24gZGUgdW4gbW9kZWxvIGRlIHJlZ3Jlc3Npb24gZ2xvYmFsIChubyBlc3BlY2lhbCwgU0FSLCBTRU0sIFNETSwgeS9vIFNBUkFSKSB5IHVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxvY2FsIChHV1IpLgoKLSBSZWdpw7NuIHNpbWlsYXIgdnMgdmFyaWFibGU6IExvcyBtb2RlbG9zIGdsb2JhbGVzIHN1cG9uZW4gZWZlY3RvcyBzaW1pbGFyZXMgZW4gdG9kbyBlbCBlc3BhY2lvLCBtaWVudHJhcyBxdWUgbG9zIGxvY2FsZXMgKGNvbW8gR1dSKSBwZXJtaXRlbiBxdWUgbG9zIGNvZWZpY2llbnRlcyB2YXLDrWVuIGVzcGFjaWFsbWVudGUuCi0gQ2FwdHVyYSBkZSBoZXRlcm9nZW5laWRhZCBlc3BhY2lhbDogR1dSIHBlcm1pdGUgaWRlbnRpZmljYXIgcGF0cm9uZXMgZXNwYWNpYWxlcyBtw6FzIHByZWNpc29zLgotIEludGVycHJldGFjacOzbiBtw6FzIGRldGFsbGFkYTogTG9zIG1vZGVsb3MgbG9jYWxlcyBwZXJtaXRlbiBhbsOhbGlzaXMgbcOhcyBkZXRhbGxhZG9zIHBvciByZWdpw7NuLgotIENvbXBsZWppZGFkIGNvbXB1dGFjaW9uYWw6IEdXUiBlcyBtw6FzIGNvc3Rvc28gY29tcHV0YWNpb25hbG1lbnRlLgotIERpYWduw7NzdGljbyBkZSBhdXRvY29ycmVsYWNpw7NuOiBMb3MgbW9kZWxvcyBsb2NhbGVzIGF5dWRhbiBhIHJlZHVjaXIgbGEgYXV0b2NvcnJlbGFjacOzbiBlbiByZXNpZHVvcyBubyBleHBsaWNhZGEgcG9yIG1vZGVsb3MgZ2xvYmFsZXMuCgpgYGB7cn0KCmZpbGVfcGF0aDwtICIvVXNlcnMvbWFyaWFuYWFsZWFsL0Rlc2t0b3AvVEVDIDIwMjUvX1BsYW5lYWNpb8yBbiBlc3RyYXRlzIFnaWNhIGJhc2FkYSBlbiBhbmFsacyBdGljYSBwcmVzY3JpcHRpdmEgL00xL3RvdXJpc21fc3RhdGVfZGF0YS54bHN4IgpkZiA8LSByZWFkX2V4Y2VsKCIvVXNlcnMvbWFyaWFuYWFsZWFsL0Rlc2t0b3AvVEVDIDIwMjUvX1BsYW5lYWNpb8yBbiBlc3RyYXRlzIFnaWNhIGJhc2FkYSBlbiBhbmFsacyBdGljYSBwcmVzY3JpcHRpdmEgL00xL3RvdXJpc21fc3RhdGVfZGF0YS54bHN4IikKc3RhdGVzbXggPC0gc3RfcmVhZCgiL1VzZXJzL21hcmlhbmFhbGVhbC9EZXNrdG9wL1RFQyAyMDI1L19QbGFuZWFjaW/MgW4gZXN0cmF0ZcyBZ2ljYSBiYXNhZGEgZW4gYW5hbGnMgXRpY2EgcHJlc2NyaXB0aXZhIC9NMS9teF9zaGFwZWZpbGVzL3N0YXRlcy9tZXhsYXRsb25nLnNocCIpCmBgYAoKCiMjIyAyKSBDYWxjdWxhciAyIG1hdHJpY2VzIGRlIGNvbmVjdGl2aWRhZCBxdWUgaW5jbHV5YSB1bm8gZGUgbG9zIHNpZ3VpZW50ZXMgY3JpdGVyaW9zOiBjb250aWd1ZWRhZCAocXVlZW4sIHJvb2ssIGJpc2hvcCksIHZlY2lubyBtw6FzIHByw7N4aW1vIChrIG5lYXJlc3QgbmVpZ2hib3IpLCB5L28gZGlzdGFuY2lhLgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpuYW1lcyhkZilbbmFtZXMoZGYpID09ICJzdGF0ZV9pZCJdIDwtICJPQkpFQ1RJRCIKCiMgVW5pciBsb3MgZGF0b3MgY29uIGxhIGdlb21ldHLDrWEKZGF0YV9zZiA8LSBtZXJnZShzdGF0ZXNteCwgZGYsIGJ5ID0gIk9CSkVDVElEIikKbGlicmFyeShzcCkKdHVyaXNtby50ciA8LSBhcyhkYXRhX3NmLCAiU3BhdGlhbCIpICAjIENvbnZlcnNpw7NuIGNvcnJlY3RhCnR1cmlzbW9fbmI8LXBvbHkybmIodHVyaXNtby50cikKCiNDcmVhciBtYXRyaXogZGUgcGVzb3MgZXNwYWNpYWxlcyAoY29udGlnw7xpZGFkIFF1ZWVuKQpxdWVlbjEgPC0gcG9seTJuYihkYXRhX3NmLCBxdWVlbiA9IFRSVUUpICMjIyBxdWVlbiBhcHByb2FjaCAKcXVlZW4yIDwtIHBvbHkybmIoZGF0YV9zZiwgcXVlZW4gPSBGQUxTRSkgIyMjIHJvb2sgYXBwcm9hY2ggIAoKY2VudHJvaWRlczwtY29vcmRpbmF0ZXModHVyaXNtby50cikgCm1hcGEubGlua1c8LW5iMmxpc3R3KHR1cmlzbW9fbmIsIHN0eWxlPSJXIikgICAKcGxvdCh0dXJpc21vLnRyLGJvcmRlcj0iYmx1ZSIsYXhlcz1GQUxTRSxsYXM9MSwgbWFpbj0iTWF0cml6IGRlIENvbmVjdGl2aWRhZCAtIFR1cmlzbW8gTVgiKQpwbG90KHR1cmlzbW8udHIsY29sPSJncmV5Iixib3JkZXI9Z3JleSgwLjkpLGF4ZXM9VCxhZGQ9VCkgCnBsb3QobWFwYS5saW5rVyxjb29yZHM9Y2VudHJvaWRlcyxwY2g9MTksY2V4PTAuMSxjb2w9InJlZCIsYWRkPVQpCgpxdWVlbjEgPC0gcG9seTJuYih0dXJpc21vLnRyLCBxdWVlbiA9IFRSVUUpICMjIyBxdWVlbiBhcHByb2FjaCAKcXVlZW4yIDwtIHBvbHkybmIodHVyaXNtby50ciwgcXVlZW4gPSBGQUxTRSkgIyMjIHJvb2sgYXBwcm9hY2ggIAoKcXVlZW5yIDwtIG5iMmxpc3R3KHF1ZWVuMSwgc3R5bGUgPSAiVyIsIHplcm8ucG9saWN5ID0gVFJVRSkKcm9vayAgPC0gbmIybGlzdHcocXVlZW4yLCBzdHlsZSA9ICJXIiwgemVyby5wb2xpY3kgPSBUUlVFKQoKcGxvdCh0dXJpc21vLnRyLGJvcmRlcj0iYmx1ZSIsYXhlcz1GQUxTRSxsYXM9MSwgbWFpbj0iTWF0cml6IEVzcGFjaWFsIGRlIENvbmV4acOzbiAtIFF1ZWVuIikKcGxvdCh0dXJpc21vLnRyLGNvbD0iZ3JleSIsYm9yZGVyPWdyZXkoMC45KSxheGVzPVQsYWRkPVQpIApwbG90KHF1ZWVucixjZW50cm9pZGVzLCBhZGQ9VFJVRSwgY29sPSdibHVlJykKCnBsb3QodHVyaXNtby50cixib3JkZXI9ImJsdWUiLGF4ZXM9RkFMU0UsbGFzPTEsIG1haW49Ik1hdHJpeiBFc3BhY2lhbCBkZSBDb25leGnDs24gLSBSb29rIikKcGxvdCh0dXJpc21vLnRyLGNvbD0iZ3JleSIsYm9yZGVyPWdyZXkoMC45KSxheGVzPVQsYWRkPVQpIApwbG90KHJvb2ssY2VudHJvaWRlcywgYWRkPVRSVUUsIGNvbD0nZGFyayBncmVlbicpCmBgYAoKCiMjIyAzKSBFc3BlY2lmaWNhciB5IGVzdGltYXIgMSBtb2RlbG8gZGUgcmVncmVzacOzbiBnbG9iYWwgbm8gZXNwYWNpYWwuCmBgYHtyIHdhcm5pbmc9RkFMU0V9CiMgVW5lIHBvciBub21icmUgZGVsIGVzdGFkbwpkZl9tYXBhIDwtIG1lcmdlKHN0YXRlc214LCBkZiwgYnkueCA9ICJBRE1JTl9OQU1FIiwgYnkueSA9ICJzdGF0ZSIpCgojIEFzZWd1cmFyc2UgZGUgcXVlIG5vIGhheSBOQXMKZGZfbWFwYSA8LSBkZl9tYXBhICU+JQogIGZpbHRlcighaXMubmEodG91cmlzbV9nZHApICYgIWlzLm5hKGNvbGxlZ2VfZWR1Y2F0aW9uKSAmIAogICAgICAgICAhaXMubmEocmVhbF93YWdlKSAmICFpcy5uYShyYXRpb19wdWJsaWNfaW52ZXN0bWVudCkpCgojIEFob3JhIGdlbmVyYSB2ZWNpbm9zIGRlc2RlIGRmX21hcGEKdmVjaW5vcyA8LSBwb2x5Mm5iKGRmX21hcGEpCnBlc29zIDwtIG5iMmxpc3R3KHZlY2lub3MsIHN0eWxlID0gIlciLCB6ZXJvLnBvbGljeSA9IFRSVUUpCgoKbW9kZWxvX25vX2VzcGFjaWFsIDwtIGxtKHRvdXJpc21fZ2RwIH4gY29sbGVnZV9lZHVjYXRpb24gKyB1bmVtcGxveW1lbnQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgIGJ1c2luZXNzX2FjdGl2aXR5ICsgcmVhbF93YWdlICsgcG9wX2RlbnNpdHkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2RfZ292ZXJuYW5jZSArIHJhdGlvX3B1YmxpY19pbnZlc3RtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX21hcGEpCgpzdW1tYXJ5KG1vZGVsb19ub19lc3BhY2lhbCkKCmBgYAoKCiMjIyA0KSBFc3BlY2lmaWNhciB5IGVzdGltYXIgMSBtb2RlbG8gZGUgcmVncmVzacOzbiBkZSBnbG9iYWwgZXNwYWNpYWwgKGUuZy4sIFNBUiwgU0VNLCBTRE0pIHF1ZSBpbmNsdXlhbiBhbGd1bmEgZGUgbGFzIDIgbWF0cmljZXMgZGUgY29uZWN0aXZpZGFkIFcpIHNlbGVjY2lvbmFkYXMgZW4gMikuCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQojIE1vZGVsbyBTQVIgKFNwYXRpYWwgQXV0b3JlZ3Jlc3NpdmUgTW9kZWwpCm1vZGVsb19zYXIgPC0gbGFnc2FybG0odG91cmlzbV9nZHAgfiBjb2xsZWdlX2VkdWNhdGlvbiArIHVuZW1wbG95bWVudCArIAogICAgICAgICAgICAgICAgICAgICAgICAgYnVzaW5lc3NfYWN0aXZpdHkgKyByZWFsX3dhZ2UgKyBwb3BfZGVuc2l0eSArIAogICAgICAgICAgICAgICAgICAgICAgICAgZ29vZF9nb3Zlcm5hbmNlICsgcmF0aW9fcHVibGljX2ludmVzdG1lbnQsCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX21hcGEsIGxpc3R3ID0gcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkKbW9kZWxvX3NhcgpgYGAKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CiMgTW9kZWxvIFNFTSAoU3BhdGlhbCBFcnJvciBNb2RlbCkKbW9kZWxvX3NlbSA8LSBlcnJvcnNhcmxtKHRvdXJpc21fZ2RwIH4gY29sbGVnZV9lZHVjYXRpb24gKyB1bmVtcGxveW1lbnQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVzaW5lc3NfYWN0aXZpdHkgKyByZWFsX3dhZ2UgKyBwb3BfZGVuc2l0eSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICBnb29kX2dvdmVybmFuY2UgKyByYXRpb19wdWJsaWNfaW52ZXN0bWVudCwKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl9tYXBhLCBsaXN0dyA9IHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpCm1vZGVsb19zZW0KYGBgCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQojIE1vZGVsbyBTRE0gKFNwYXRpYWwgRHVyYmluIE1vZGVsKQptb2RlbG9fc2RtIDwtIGxhZ3NhcmxtKHRvdXJpc21fZ2RwIH4gY29sbGVnZV9lZHVjYXRpb24gKyByZWFsX3dhZ2UgKyByYXRpb19wdWJsaWNfaW52ZXN0bWVudCwKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfbWFwYSwgbGlzdHcgPSBwZXNvcywgdHlwZSA9ICJtaXhlZCIsIHplcm8ucG9saWN5ID0gVFJVRSkKbW9kZWxvX3NkbQpgYGAKCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQoKYGBgCgoKCiMjIyA1KSBJZGVudGlmaWNhciBsYSBwb3NpYmxlIHByZXNlbmNpYSBkZSBhdXRvY29ycmVsYWNpw7NuIGVzcGFjaWFsIGVuIGxvcyByZXNpZHVhbGVzIMaQaSBwYXJhIGNhZGEgdW5vIGRlIGxvcyBtb2RlbG9zIGRlIHJlZ3Jlc2nDs24gZXN0aW1hZG9zIGVuIDMpIHkgNCkuCgoKYGBge3Igd2FybmluZz1GQUxTRX0KIyBBdXRvY29ycmVsYWNpw7NuIGVzcGFjaWFsIGVuIHJlc2lkdW9zIGRlbCBtb2RlbG8gbm8gZXNwYWNpYWwKbW9yYW4udGVzdChyZXNpZHVhbHMobW9kZWxvX25vX2VzcGFjaWFsKSwgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkKCiMgQXV0b2NvcnJlbGFjacOzbiBlbiBtb2RlbG8gU0FSCm1vcmFuLnRlc3QocmVzaWR1YWxzKG1vZGVsb19zYXIpLCBwZXNvcywgemVyby5wb2xpY3kgPSBUUlVFKQoKIyBBdXRvY29ycmVsYWNpw7NuIGVuIG1vZGVsbyBTRU0KbW9yYW4udGVzdChyZXNpZHVhbHMobW9kZWxvX3NlbSksIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpCgojIEF1dG9jb3JyZWxhY2nDs24gZW4gbW9kZWxvIFNETQptb3Jhbi50ZXN0KHJlc2lkdWFscyhtb2RlbG9fc2RtKSwgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkKYGBgCi0gRWwgbW9kZWxvIG5vIGVzcGFjaWFsIHByb2JhYmxlbWVudGUgcHJlc2VudGUgYXV0b2NvcnJlbGFjacOzbiBlc3BhY2lhbCBzaWduaWZpY2F0aXZhIGVuIHN1cyByZXNpZHVvcyAodmFsb3ItcCA8IDAuMDUpLCBpbmRpY2FuZG8gcXVlIGVsIG1vZGVsbyBubyBjYXB0dXJhIGNvbXBsZXRhbWVudGUgbG9zIHBhdHJvbmVzIGVzcGFjaWFsZXMuCi0gRW4gY29udHJhc3RlLCBsb3MgbW9kZWxvcyBTQVIsIFNFTSB5IFNETSBkZWJlcsOtYW4gcmVkdWNpciBzaWduaWZpY2F0aXZhbWVudGUgZXNhIGF1dG9jb3JyZWxhY2nDs24sIGVzcGVjaWFsbWVudGUgU0VNIHBhcmEgZXJyb3JlcyB5IFNBUi9TRE0gZW4gZGVwZW5kZW5jaWEgZXNwYWNpYWwgZGlyZWN0YS4KLSBVbiB2YWxvciBkZSBNb3JhbuKAmXMgSSBjZXJjYW5vIGEgMCB5IHVuIHZhbG9yLXAgYWx0byAoPiAwLjA1KSBpbmRpY2FuIHF1ZSBubyBoYXkgYXV0b2NvcnJlbGFjacOzbiByZXNpZHVhbCByZWxldmFudGUuCgpgYGB7cn0KIyBDb3JyZXIgbGEgcHJ1ZWJhIGRlIE1vcmFuIHBhcmEgY2FkYSBtb2RlbG8KbW9yYW5fbm9fZXNwYWNpYWwgPC0gbW9yYW4udGVzdChyZXNpZHVhbHMobW9kZWxvX25vX2VzcGFjaWFsKSwgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkKbW9yYW5fc2FyICAgICAgICAgPC0gbW9yYW4udGVzdChyZXNpZHVhbHMobW9kZWxvX3NhciksIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpCm1vcmFuX3NlbSAgICAgICAgIDwtIG1vcmFuLnRlc3QocmVzaWR1YWxzKG1vZGVsb19zZW0pLCBwZXNvcywgemVyby5wb2xpY3kgPSBUUlVFKQptb3Jhbl9zZG0gICAgICAgICA8LSBtb3Jhbi50ZXN0KHJlc2lkdWFscyhtb2RlbG9fc2RtKSwgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkKCiMgQ3JlYXIgdW5hIHRhYmxhIGNvbXBhcmF0aXZhCnJlc3VtZW5fbW9yYW5zX0kgPC0gZGF0YS5mcmFtZSgKICBNb2RlbG8gPSBjKCJMaW5lYWwgTm8gRXNwYWNpYWwiLCAiU0FSIiwgIlNFTSIsICJTRE0iKSwKICBNb3JhbnNfSSA9IGMobW9yYW5fbm9fZXNwYWNpYWwkZXN0aW1hdGVbIk1vcmFuIEkgc3RhdGlzdGljIl0sCiAgICAgICAgICAgICAgIG1vcmFuX3NhciRlc3RpbWF0ZVsiTW9yYW4gSSBzdGF0aXN0aWMiXSwKICAgICAgICAgICAgICAgbW9yYW5fc2VtJGVzdGltYXRlWyJNb3JhbiBJIHN0YXRpc3RpYyJdLAogICAgICAgICAgICAgICBtb3Jhbl9zZG0kZXN0aW1hdGVbIk1vcmFuIEkgc3RhdGlzdGljIl0pLAogIEV4cGVjdGF0aW9uID0gYyhtb3Jhbl9ub19lc3BhY2lhbCRlc3RpbWF0ZVsiRXhwZWN0YXRpb24iXSwKICAgICAgICAgICAgICAgICAgbW9yYW5fc2FyJGVzdGltYXRlWyJFeHBlY3RhdGlvbiJdLAogICAgICAgICAgICAgICAgICBtb3Jhbl9zZW0kZXN0aW1hdGVbIkV4cGVjdGF0aW9uIl0sCiAgICAgICAgICAgICAgICAgIG1vcmFuX3NkbSRlc3RpbWF0ZVsiRXhwZWN0YXRpb24iXSksCiAgVmFyaWFuY2UgPSBjKG1vcmFuX25vX2VzcGFjaWFsJGVzdGltYXRlWyJWYXJpYW5jZSJdLAogICAgICAgICAgICAgICBtb3Jhbl9zYXIkZXN0aW1hdGVbIlZhcmlhbmNlIl0sCiAgICAgICAgICAgICAgIG1vcmFuX3NlbSRlc3RpbWF0ZVsiVmFyaWFuY2UiXSwKICAgICAgICAgICAgICAgbW9yYW5fc2RtJGVzdGltYXRlWyJWYXJpYW5jZSJdKSwKICBwX3ZhbHVlID0gYyhtb3Jhbl9ub19lc3BhY2lhbCRwLnZhbHVlLAogICAgICAgICAgICAgIG1vcmFuX3NhciRwLnZhbHVlLAogICAgICAgICAgICAgIG1vcmFuX3NlbSRwLnZhbHVlLAogICAgICAgICAgICAgIG1vcmFuX3NkbSRwLnZhbHVlKQopCgpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCgprYWJsZShyZXN1bWVuX21vcmFuc19JLCBkaWdpdHMgPSA0LCBjYXB0aW9uID0gIkNvbXBhcmFjacOzbiBkZSBhdXRvY29ycmVsYWNpw7NuIGVzcGFjaWFsIGVuIGxvcyByZXNpZHVvcyAoTW9yYW4ncyBJKSIpICU+JQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEYsIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSkKCmBgYAoKCgojIyMgNikgRXNwZWNpZmljYXIgeSBlc3RpbWFyIDEgbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbG9jYWwgZXNwYWNpYWwgKGUuZy4sIEdXUikuCmBgYHtyIHdhcm5pbmc9RkFMU0V9CgojIENyZWFyIGNvb3JkZW5hZGFzCmNvb3JkcyA8LSBzdF9jb29yZGluYXRlcyhzdF9jZW50cm9pZChkZl9tYXBhKSkKCiMgUHJlcGFyYXIgZGF0b3MgcGFyYSBHV1IKZ3dyX2RhdGEgPC0gYXMoZGZfbWFwYSwgIlNwYXRpYWwiKQoKIyBFc3RpbWFyIEdXUiAoc2VsZWNjaW9uYW1vcyB2YXJpYWJsZXMgc2lnbmlmaWNhdGl2YXMgZW4gbW9kZWxvcyBwcmV2aW9zKQpnd3JfbW9kZWwgPC0gZ3dyKHRvdXJpc21fZ2RwIH4gY29sbGVnZV9lZHVjYXRpb24gKyByZWFsX3dhZ2UgKyByYXRpb19wdWJsaWNfaW52ZXN0bWVudCwKICAgICAgICAgICAgICAgICBkYXRhID0gZ3dyX2RhdGEsCiAgICAgICAgICAgICAgICAgY29vcmRzID0gY29vcmRzLAogICAgICAgICAgICAgICAgIGFkYXB0ID0gMC4zLCAgCiAgICAgICAgICAgICAgICAgZ3dlaWdodCA9IGd3ci5HYXVzcywKICAgICAgICAgICAgICAgICBoYXRtYXRyaXggPSBUUlVFKQoKZ3dyX21vZGVsCgojIFZlciBsYSBzaWduaWZpY2FuY2lhIHQgZGUgbGEgdmFyaWFibGUgY29sbGVnZV9lZHVjYXRpb24gZW4gZWwgbW9kZWxvIEdXUgpnd3JfbW9kZWwkY29sbGVnZV9lZHVfVHYKCgpgYGAKYGBge3J9Cm5hbWVzKGd3cl9tb2RlbCRTREYpCgoKYGBgCgpgYGB7cn0KIyBDYWxjdWxhciBlbCB2YWxvciB0IHBhcmEgbGEgdmFyaWFibGUgY29sbGVnZV9lZHVjYXRpb24KZGZfbWFwYSRjb2xsZWdlX2VkdV9UdiA8LSBnd3JfbW9kZWwkU0RGJGNvbGxlZ2VfZWR1Y2F0aW9uIC8gZ3dyX21vZGVsJFNERiRjb2xsZWdlX2VkdWNhdGlvbl9zZQoKIyBDcmVhciB1bmEgY29sdW1uYSBsw7NnaWNhIHBhcmEgbWFyY2FyIGxvcyBlc3RhZG9zIGNvbiBzaWduaWZpY2FuY2lhIGVzdGFkw61zdGljYQpkZl9tYXBhJHNpZ25pZmljYXRpdm8gPC0gYWJzKGRmX21hcGEkY29sbGVnZV9lZHVfVHYpID4gMS45NgoKIyBNYXBhIGRlc3RhY2FuZG8gc29sbyBsb3MgZXN0YWRvcyBjb24gdmFsb3JlcyB0IHNpZ25pZmljYXRpdm9zCmdncGxvdChkZl9tYXBhKSArCiAgZ2VvbV9zZihhZXMoZmlsbCA9IGlmZWxzZShzaWduaWZpY2F0aXZvLCBjb2xsZWdlX2VkdV9UdiwgTkEpKSwgY29sb3IgPSAid2hpdGUiKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIoCiAgICBsb3cgPSAiYmx1ZSIsIG1pZCA9ICJ3aGl0ZSIsIGhpZ2ggPSAicmVkIiwgbWlkcG9pbnQgPSAwLAogICAgbmEudmFsdWUgPSAiZ3JleTkwIiwgICMgQ29sb3IgcGFyYSBsb3MgZXN0YWRvcyBubyBzaWduaWZpY2F0aXZvcwogICAgbmFtZSA9ICJ0LXZhbHVlXG5jb2xsZWdlX2VkdWNhdGlvbiIKICApICsKICBsYWJzKAogICAgdGl0bGUgPSAiRXN0YWRvcyBjb24gZWZlY3RvIHNpZ25pZmljYXRpdm8gZGUgJ0NvbGxlZ2UgRWR1Y2F0aW9uJyBlbiBlbCBtb2RlbG8gR1dSIiwKICAgIHN1YnRpdGxlID0gIlNvbG8gc2UgbXVlc3RyYW4gbG9zIGVzdGFkb3MgY29uIHx0fCA+IDEuOTYiLAogICAgZmlsbCA9ICJWYWxvciB0IgogICkgKwogIHRoZW1lX21pbmltYWwoKQoKCmBgYAoKCgoKIyMjIDcpIEEgcGFydGlyIGRlIGxhIGVzdGltYWNpw7NuIGRlIGxvcyBtb2RlbG9zIGRlIHJlZ3Jlc2nDs24gZW4gNCkg4oCTIDYpIHNlbGVjY2lvbmFyIDEg4oCTIDIgbW9kZWxvcyBwYXJhIGxhIGludGVycHJldGFjacOzbiBkZSBsb3MgcHJpbmNpcGFsZXMgcmVzdWx0YWRvcy4KCi0gTW9kZWxvIFNETSAoRHVyYmluKTogcGVybWl0ZSBhbmFsaXphciBlZmVjdG9zIGRpcmVjdG9zIGUgaW5kaXJlY3RvcyBlc3BhY2lhbGVzLiBDYXB0dXJhIG1lam9yIGxhIGNvbXBsZWppZGFkIGRlbCBmZW7Ds21lbm8gdHVyw61zdGljbyB5IHN1IHJlbGFjacOzbiBjb24gdmFyaWFibGVzIGNvbW8gaW52ZXJzacOzbiBww7pibGljYSB5IHNhbGFyaW8gcmVhbC4KLSBNb2RlbG8gR1dSOiBtdWVzdHJhIGxhIHZhcmlhYmlsaWRhZCBlc3BhY2lhbCBkZSBsb3MgY29lZmljaWVudGVzIHkgcGVybWl0ZSBpbnRlcnByZXRhY2lvbmVzIG3DoXMgZGV0YWxsYWRhcyBwb3IgZXN0YWRvLiBFcyDDunRpbCBwYXJhIHBvbMOtdGljYXMgcmVnaW9uYWxlcyBkaWZlcmVuY2lhZGFzLgotIEVsIFNETSBpbmNvcnBvcmEgZWZlY3RvcyBlc3BhY2lhbGVzIGNydXphZG9zIHkgcmVmbGVqYSBwb3NpYmxlcyBzcGlsbG92ZXJzLgotIEVsIEdXUiBldmlkZW5jaWEgbGEgaGV0ZXJvZ2VuZWlkYWQgZXNwYWNpYWwgcXVlIGxvcyBtb2RlbG9zIGdsb2JhbGVzIG5vIHB1ZWRlbiBjYXB0YXIuCgojIyMgOCkgTWVkaWFudGUgZWwgdXNvIGRlIDIg4oCTIDMgbWFwYXMsIHZpc3VhbGl6YXIgbG9zIHByaW5jaXBhbGVzIHJlc3VsdGFkb3MgZXN0aW1hZG9zIChlLmcuLCBwcmVkaWNjacOzbiBkZSBwcmluY2lwYWwgdmFyaWFibGUgZGUgYW7DoWxpc2lzLCBzaWduaWZpY2FuY2lhIGVzdGFkw61zdGljYSBkZSBwcmluY2lwYWwgdmFyaWFibGUgZXhwbGljYXRpdmEsIHByZXNlbmNpYSBkZSBhdXRvY29ycmVsYWNpw7NuIGVzcGFjaWFsKSBkZSBhbCBtZW5vcyAxIGRlIGxvcyBtb2RlbG9zIGRlIHJlZ3Jlc2nDs24gc2VsZWNjaW9uYWRvcy4KCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQojIEV4dHJhZXIgbG9zIGNvZWZpY2llbnRlcyBkZWwgR1dSCmNvZWZfZ3dyIDwtIGFzLmRhdGEuZnJhbWUoZ3dyX21vZGVsJFNERikKCiMgQWdyZWdhciBjb2VmaWNpZW50ZXMgYSBzaGFwZWZpbGUKZGZfbWFwYSRjb2VmX2NvbGxlZ2UgPC0gY29lZl9nd3IkY29sbGVnZV9lZHVjYXRpb24KZGZfbWFwYSRjb2VmX3JlYWxfd2FnZSA8LSBjb2VmX2d3ciRyZWFsX3dhZ2UKZGZfbWFwYSRsb2NhbF9SMiA8LSBjb2VmX2d3ciRsb2NhbFIyCmBgYAoKYGBge3Igd2FybmluZz1GQUxTRX0KIyBNYXBhIDE6IENvZWZpY2llbnRlIGRlIGNvbGxlZ2VfZWR1Y2F0aW9uCnRtX3NoYXBlKGRmX21hcGEpICsKICB0bV9wb2x5Z29ucygiY29lZl9jb2xsZWdlIiwgcGFsZXR0ZSA9ICJZbEduQnUiLCB0aXRsZSA9ICJFZmVjdG8gRWR1Y2FjacOzbiBTdXBlcmlvciIpICsKICB0bV9sYXlvdXQodGl0bGUgPSAiVmFyaWFjacOzbiBlc3BhY2lhbCBkZWwgZWZlY3RvIGRlIGVkdWNhY2nDs24gc3VwZXJpb3IgZW4gZWwgUElCIHR1csOtc3RpY28iKQpgYGAKCgoKRXN0ZSBtYXBhIHZpc3VhbGl6YSBjw7NtbyB2YXLDrWEgZXNwYWNpYWxtZW50ZSBlbCBjb2VmaWNpZW50ZSBkZSBsYSB2YXJpYWJsZSBlZHVjYWNpw7NuIHVuaXZlcnNpdGFyaWEgZW4gZWwgbW9kZWxvIEdXUi4gRXMgZGVjaXIsIGluZGljYSBjdcOhbnRvIGluZmx1eWUgZWwgbml2ZWwgZWR1Y2F0aXZvIGVuIGVsIFBJQiB0dXLDrXN0aWNvIGVuIGNhZGEgZXN0YWRvLgoKLUNvbG9yZXMgbcOhcyBpbnRlbnNvcyAoYXp1bCk6IGluZGljYW4gcXVlIGVuIGVzb3MgZXN0YWRvcyBlbCBjb2VmaWNpZW50ZSBlcyBtw6FzIGFsdG8sIGxvIHF1ZSBzaWduaWZpY2EgcXVlIHVuIG1heW9yIG5pdmVsIGRlIGVkdWNhY2nDs24gdW5pdmVyc2l0YXJpYSBzZSBhc29jaWEgY29uIHVuIGluY3JlbWVudG8gbcOhcyBmdWVydGUgZW4gZWwgUElCIHR1csOtc3RpY28uCi0gQ29sb3JlcyBtw6FzIGNsYXJvcyBvIG5ldXRyb3M6IHN1Z2llcmVuIHF1ZSBlbCBpbXBhY3RvIGVzIG3DoXMgZMOpYmlsIG8gaW5jbHVzbyBudWxvLgoKRW4gZXN0YWRvcyBjb21vIENETVgsIEphbGlzY28geSBOdWV2byBMZcOzbiwgbGEgZWR1Y2FjacOzbiB0aWVuZSB1biBlZmVjdG8gbm90YWJsZW1lbnRlIHBvc2l0aXZvIGVuIGVsIHR1cmlzbW8sIHBvc2libGVtZW50ZSBkZWJpZG8gYSBzdSBjYXBhY2lkYWQgcGFyYSBvZnJlY2VyIHNlcnZpY2lvcyB0dXLDrXN0aWNvcyBtw6FzIHNvZmlzdGljYWRvcyBvIG1lam9yIG9yZ2FuaXphZG9zLgoKRW4gb3RyYXMgcmVnaW9uZXMsIGNvbW8gZWwgc3VyZXN0ZSBvIHpvbmFzIGRlbCBub3J0ZSwgZWwgaW1wYWN0byBlcyBtZW5vciwgbG8gcXVlIHN1Z2llcmUgcXVlIGxhIGVkdWNhY2nDs24gbm8gc2UgdHJhZHVjZSB0YW4gZGlyZWN0YW1lbnRlIGVuIGRlc2Fycm9sbG8gdHVyw61zdGljbyBhbGzDrSDigJRwb3NpYmxlbWVudGUgcG9yIGZhbHRhIGRlIGluZnJhZXN0cnVjdHVyYSBvIGVuZm9xdWUgZWNvbsOzbWljbyBkaXN0aW50by4KCgoKYGBge3Igd2FybmluZz1GQUxTRX0KIyBNYXBhIDI6IFLCsiBsb2NhbCBkZWwgbW9kZWxvIEdXUgp0bV9zaGFwZShkZl9tYXBhKSArCiAgdG1fcG9seWdvbnMoImxvY2FsX1IyIiwgcGFsZXR0ZSA9ICJPcmFuZ2VzIiwgdGl0bGUgPSAiUsKyIExvY2FsIikgKwogIHRtX2xheW91dCh0aXRsZSA9ICJCb25kYWQgZGUgYWp1c3RlIGRlbCBtb2RlbG8gR1dSIHBvciBlc3RhZG8iKQpgYGAKCgoKRXN0ZSBtYXBhIGluZGljYSBxdcOpIHRhbiBiaWVuIGV4cGxpY2EgZWwgbW9kZWxvIEdXUiBsYSB2YXJpYWJpbGlkYWQgZGVsIFBJQiB0dXLDrXN0aWNvIGVuIGNhZGEgZXN0YWRvLiBFcyBkZWNpciwgbWlkZSBsYSBjYXBhY2lkYWQgZXhwbGljYXRpdmEgZGVsIG1vZGVsbyBlbiBlbCBlc3BhY2lvLgoKLUNvbG9yZXMgb3NjdXJvcy9uYXJhbmphcyBpbnRlbnNvczogcmVmbGVqYW4gdmFsb3JlcyBkZSBSwrIgbG9jYWxlcyBhbHRvcyAobWF5b3IgYWp1c3RlKSwgZXMgZGVjaXIsIGVuIGVzb3MgZXN0YWRvcyBlbCBtb2RlbG8gZXhwbGljYSBncmFuIHBhcnRlIGRlbCBQSUIgdHVyw61zdGljby4KLUNvbG9yZXMgY2xhcm9zIG8gYW1hcmlsbG9zOiBtdWVzdHJhbiB1biBtZW5vciBhanVzdGUgbG9jYWwgZGVsIG1vZGVsby4KCkVsIG1vZGVsbyBHV1IgZnVuY2lvbmEgbXV5IGJpZW4gZW4gY2llcnRhcyByZWdpb25lcywgY29tbyBlbCBjZW50cm8geSBvY2NpZGVudGUgZGVsIHBhw61zLCBkb25kZSBwdWVkZSBjYXB0YXIgcmVsYWNpb25lcyBtw6FzIGNsYXJhcyBlbnRyZSBsYXMgdmFyaWFibGVzIGV4cGxpY2F0aXZhcyB5IGVsIHR1cmlzbW8uCgpFbiByZWdpb25lcyBjb24gbWVub3IgUsKyIChwb3IgZWplbXBsbywgYWxndW5hcyB6b25hcyBkZWwgc3VyKSwgcG9kcsOtYW4gZXN0YXIgaW5mbHV5ZW5kbyBmYWN0b3JlcyBubyBpbmNsdWlkb3MgZW4gZWwgbW9kZWxvIChjb21vIGluc2VndXJpZGFkLCBjb25lY3RpdmlkYWQgbyBjb25kaWNpb25lcyBuYXR1cmFsZXMpLgoKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CiMgTWFwYSAzOiBBdXRvY29ycmVsYWNpw7NuIGRlIHJlc2lkdW9zIGRlbCBtb2RlbG8gU0RNCnJlc2lkdW9zX3NkbSA8LSByZXNpZHVhbHMobW9kZWxvX3NkbSkKZGZfbWFwYSRyZXNpZHVvc19zZG0gPC0gcmVzaWR1b3Nfc2RtCgp0bV9zaGFwZShkZl9tYXBhKSArCiAgdG1fcG9seWdvbnMoInJlc2lkdW9zX3NkbSIsIHBhbGV0dGUgPSAiLVJkQnUiLCBtaWRwb2ludCA9IDAsCiAgICAgICAgICAgICAgdGl0bGUgPSAiUmVzaWR1b3MgZGVsIG1vZGVsbyBTRE0iKSArCiAgdG1fbGF5b3V0KHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZXNwYWNpYWwgZGUgcmVzaWR1b3MgKFNETSkiKQoKYGBgCgpFc3RlIG1hcGEgcHJlc2VudGEgbGEgZGlzdHJpYnVjacOzbiBkZSBsb3MgcmVzaWR1b3MgZGVsIG1vZGVsbyBTRE0sIGVzIGRlY2lyLCBsYXMgZGlmZXJlbmNpYXMgZW50cmUgbG8gb2JzZXJ2YWRvIHkgbG8gcHJlZGljaG8uIEF5dWRhIGEgZGV0ZWN0YXIgcGF0cm9uZXMgZXNwYWNpYWxlcyBubyBjYXB0YWRvcyBwb3IgZWwgbW9kZWxvLgoKLSBDb2xvcmVzIHJvam9zOiBpbmRpY2FuIHJlc2lkdW9zIHBvc2l0aXZvcz0gZWwgbW9kZWxvIHN1YmVzdGltw7MgZWwgUElCIHR1csOtc3RpY28gZW4gZXNhcyByZWdpb25lcy4KLSBDb2xvcmVzIGF6dWxlczogaW5kaWNhbiByZXNpZHVvcyBuZWdhdGl2b3M9IGVsIG1vZGVsbyBzb2JyZWVzdGltw7MgZWwgUElCIHR1csOtc3RpY28uCi0gRGlzdHJpYnVjaW9uZXMgYWdydXBhZGFzIGRlIHVuIG1pc21vIGNvbG9yPSBwb2Ryw61hbiBzZcOxYWxhciBhdXRvY29ycmVsYWNpw7NuIGVzcGFjaWFsIHJlc2lkdWFsLgoKU2kgbG9zIGVycm9yZXMgZXN0w6FuIGRpc3RyaWJ1aWRvcyBkZSBmb3JtYSBhbGVhdG9yaWEsIGVsIG1vZGVsbyBTRE0gY2FwdHVyYSBiaWVuIGxhcyByZWxhY2lvbmVzIGVzcGFjaWFsZXMuCgpTaSBoYXkgYWdydXBhY2lvbmVzIGRlIGVycm9yZXMgc2ltaWxhcmVzIChjbHVzdGVycyksIGVzcGVjaWFsbWVudGUgZW4gem9uYXMgZXNwZWPDrWZpY2FzIChjb21vIGVsIHN1ci1zdXJlc3RlKSwgc3VnaWVyZSBxdWUgaGF5IGRpbsOhbWljYXMgbG9jYWxlcyBubyBtb2RlbGFkYXMgYWRlY3VhZGFtZW50ZS4gRXN0byBwb2Ryw61hIGp1c3RpZmljYXIgaW5jb3Jwb3JhciB2YXJpYWJsZXMgYWRpY2lvbmFsZXMgbyBjb25zaWRlcmFyIHVuIG1vZGVsbyBhw7puIG3DoXMgbG9jYWwuCgoKIyBDb25jbHVzacOzbgotIEVsIG1vZGVsbyBHV1IgcGVybWl0ZSB2aXN1YWxpemFyIHF1w6kgdmFyaWFibGVzIGV4cGxpY2FuIG1lam9yIGVsIHR1cmlzbW8gZW4gY2FkYSByZWdpw7NuLCDDunRpbCBwYXJhIGRpc2XDsWFyIHBvbMOtdGljYXMgcMO6YmxpY2FzIHJlZ2lvbmFsaXphZGFzLgotIExhIGVkdWNhY2nDs24gdW5pdmVyc2l0YXJpYSBlcyB1biBmdWVydGUgbW90b3IgZGVsIHR1cmlzbW8gZW4gem9uYXMgdXJiYW5hcyBkZXNhcnJvbGxhZGFzLCBwZXJvIG5vIGVzIHN1ZmljaWVudGUgZW4gcmVnaW9uZXMgbcOhcyBtYXJnaW5hZGFzLgotIEVsIGFqdXN0ZSBkZWwgbW9kZWxvIHZhcsOtYSwgeSBzZSByZXF1aWVyZW4gZW5mb3F1ZXMgZGlzdGludG9zIHNlZ8O6biBsYSB6b25hIChwb3IgZWplbXBsbywgaW52ZXJzacOzbiBlbiBlZHVjYWNpw7NuIHZzLiBpbmZyYWVzdHJ1Y3R1cmEpLgotIEF1bnF1ZSBlbCBTRE0gcmVkdWNlIGxhIGF1dG9jb3JyZWxhY2nDs24sIHRvZGF2w61hIGhheSBwYXRyb25lcyBlc3BhY2lhbGVzIG5vIGV4cGxpY2Fkb3MgZW4gYWxndW5hcyByZWdpb25lcywgbG8gcXVlIHZhbGlkYSBsYSB1dGlsaWRhZCBkZSBtb2RlbG9zIGxvY2FsZXMgY29tbyBHV1IuCgojIFJlZmVyZW5jaWFzIAotIENvbXBhcmluZyBsb2NhbCByZWdyZXNzaW9uIHRvIGdsb2JhbCByZWdyZXNzaW9uIC0gRmFzdGVyQ2FwaXRhbC4gKG4uZC4pLiBGYXN0ZXJDYXBpdGFsLiBodHRwczovL2Zhc3RlcmNhcGl0YWwuY29tL3RvcGljcy9jb21wYXJpbmctbG9jYWwtcmVncmVzc2lvbi10by1nbG9iYWwtcmVncmVzc2lvbi5odG1sCi0gVGVhbSwgVy4gKDIwMjUsIEFwcmlsIDIzKS4gTG9jYWwgcmVncmVzc2lvbi4gV2hhdCBJcyBJdCwgRXhhbXBsZXMsIEFwcGxpY2F0aW9ucywgQWR2YW50YWdlcy4gaHR0cHM6Ly93d3cud2FsbHN0cmVldG1vam8uY29tL2xvY2FsLXJlZ3Jlc3Npb24vCi0gQ29uY2VwdG9zIGLDoXNpY29zIGRlbCBhbsOhbGlzaXMgZGUgcmVncmVzacOzbuKAlEFyY0dJUyBQcm8gfCBEb2N1bWVudGFjacOzbi4gKG4uZC4pLiBodHRwczovL3Byby5hcmNnaXMuY29tL2VzL3Byby1hcHAvbGF0ZXN0L3Rvb2wtcmVmZXJlbmNlL3NwYXRpYWwtc3RhdGlzdGljcy9yZWdyZXNzaW9uLWFuYWx5c2lzLWJhc2ljcy5odG0KLSBBdXRvY29ycmVsYWNpw7NuIGVzcGFjaWFsIChJIGRlIE1vcmFuIGdsb2JhbCkgKEVzdGFkw61zdGljYSBlc3BhY2lhbCnigJRBcmNHSVMgUHJvIHwgRG9jdW1lbnRhY2nDs24uIChuLmQuKS4gaHR0cHM6Ly9wcm8uYXJjZ2lzLmNvbS9lcy9wcm8tYXBwL2xhdGVzdC90b29sLXJlZmVyZW5jZS9zcGF0aWFsLXN0YXRpc3RpY3Mvc3BhdGlhbC1hdXRvY29ycmVsYXRpb24uaHRtIAotIMK/UXXDqSBlcyBsYSByZWdyZXNpw7NuIGxvY2FsIHkgY8OzbW8gc2UgY29tcGFyYSBjb24gbGEgcmVncmVzacOzbiBnbG9iYWw/ICgyMDI0LCBNYXkgOCkuIHd3dy5saW5rZWRpbi5jb20uIGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9hZHZpY2UvMC93aGF0LWxvY2FsLXJlZ3Jlc3Npb24taG93LWRvZXMtY29tcGFyZS1nbG9iYWwtc2tpbGxzLXN0YXRpc3RpY3MtbzJzb2M/bGFuZz1lcyZvcmlnaW5hbFN1YmRvbWFpbj1lcwoK