Desarrollo
Exploración y preparación del dataset
# Instalacion de librerías
install.packages(c("devtools", "Dplyr", "factoextra", "ggplot2", "ggfortify", "FactoMineR", "corrplot"))
Error in install.packages : Updating loaded packages
library(devtools)
library(dplyr)
library(factoextra)
library(ggplot2)
library(ggfortify)
library(FactoMineR)
library(corrplot)
Se realiza una exploracion y limpieza del Dataset original
viviendas_faltantes que contiene 8330 observaciones y 13 variables
(dimensiones)
data(vivienda_faltantes)
head(vivienda_faltantes)
summary(vivienda_faltantes)
id zona piso estrato preciom
Min. : 1 Length:8330 Min. : 1.000 Min. :3.000 Min. : 58.0
1st Qu.:2082 Class :character 1st Qu.: 2.000 1st Qu.:4.000 1st Qu.: 220.0
Median :4164 Mode :character Median : 3.000 Median :5.000 Median : 330.0
Mean :4164 Mean : 3.772 Mean :4.634 Mean : 434.2
3rd Qu.:6246 3rd Qu.: 5.000 3rd Qu.:5.000 3rd Qu.: 540.0
Max. :8319 Max. :12.000 Max. :6.000 Max. :1999.0
NA's :3 NA's :2641 NA's :3 NA's :2
areaconst parquea banios habitac tipo
Min. : 30 Min. : 1.000 Min. : 0.000 Min. : 0.000 Length:8330
1st Qu.: 80 1st Qu.: 1.000 1st Qu.: 2.000 1st Qu.: 3.000 Class :character
Median : 123 Median : 2.000 Median : 3.000 Median : 3.000 Mode :character
Mean : 175 Mean : 1.836 Mean : 3.112 Mean : 3.605
3rd Qu.: 229 3rd Qu.: 2.000 3rd Qu.: 4.000 3rd Qu.: 4.000
Max. :1745 Max. :10.000 Max. :10.000 Max. :10.000
NA's :3 NA's :1606 NA's :3 NA's :3
barrio longitud latitud
Length:8330 Min. :-76576.00 Min. : 3.333
Class :character 1st Qu.:-76506.00 1st Qu.: 3.390
Mode :character Median : -76.54 Median : 3.450
Mean :-21845.13 Mean : 970.370
3rd Qu.: -76.52 3rd Qu.:3367.000
Max. : -76.46 Max. :3497.000
NA's :3 NA's :3
Se procede a reemplazar valores NA de las columnas Piso (2641) y
Parqueadero (1606) por valores 0.
vivienda$piso[is.na(vivienda$piso)] <- 0
vivienda$parquea[is.na(vivienda$parquea)] <- 0
head(vivienda)
NA
La variable “tipo” tiene un problema con las mayusculas y
minisculas, se incluyen todas las variantes en: apartamento y casa.
vivienda$tipo <- tolower(vivienda$tipo)
vivienda$tipo <- gsub("apto", "apartamento", vivienda$tipo, ignore.case = TRUE)
unique(vivienda$tipo)
[1] "apartamento" "casa" NA
table(vivienda$tipo)
apartamento casa
5106 3221
Eliminamos filas con valores faltantes “NA”
vivienda_clean <- na.omit(vivienda)
sum(is.na(vivienda_clean)) # Debe devolver 0 si no hay NA
[1] 0
dim(vivienda_clean) #Nueva dimension (filas / columnas)
[1] 8327 12
nrow(vivienda) - nrow(vivienda_clean) # Número de filas eliminadas
[1] 3
summary(vivienda_clean) #Comprobamos
zona piso estrato preciom areaconst
Length:8327 Min. : 0.000 Min. :3.000 Min. : 58.0 Min. : 30
Class :character 1st Qu.: 0.000 1st Qu.:4.000 1st Qu.: 220.0 1st Qu.: 80
Mode :character Median : 2.000 Median :5.000 Median : 330.0 Median : 123
Mean : 2.577 Mean :4.634 Mean : 434.3 Mean : 175
3rd Qu.: 4.000 3rd Qu.:5.000 3rd Qu.: 540.0 3rd Qu.: 229
Max. :12.000 Max. :6.000 Max. :1999.0 Max. :1745
parquea banios habitac tipo barrio
Min. : 0.000 Min. : 0.000 Min. : 0.000 Length:8327 Length:8327
1st Qu.: 1.000 1st Qu.: 2.000 1st Qu.: 3.000 Class :character Class :character
Median : 1.000 Median : 3.000 Median : 3.000 Mode :character Mode :character
Mean : 1.483 Mean : 3.112 Mean : 3.605
3rd Qu.: 2.000 3rd Qu.: 4.000 3rd Qu.: 4.000
Max. :10.000 Max. :10.000 Max. :10.000
longitud latitud
Min. :-76576.00 Min. : 3.333
1st Qu.:-76506.00 1st Qu.: 3.390
Median : -76.54 Median : 3.450
Mean :-21845.13 Mean : 970.370
3rd Qu.: -76.52 3rd Qu.:3367.000
Max. : -76.46 Max. :3497.000
Calculamos la matriz de correlacion para descartar variables
redundantes, seleccionamos las variables numéricas relevantes:
vrb_num_table <- vivienda_clean[, c('preciom', 'areaconst', 'habitac', 'banios')]
correlation_matrix <- cor(vrb_num_table, use = "complete.obs")
print(correlation_matrix)
preciom areaconst habitac banios
preciom 1.0000000 0.6872452 0.2633645 0.6691775
areaconst 0.6872452 1.0000000 0.5166996 0.6486675
habitac 0.2633645 0.5166996 1.0000000 0.5896911
banios 0.6691775 0.6486675 0.5896911 1.0000000
Visualizamos la matriz de correlación
install.packages("corrplot")
Error in install.packages : Updating loaded packages
library(corrplot)
corrplot(correlation_matrix, method = "circle", type = "lower",
col = colorRampPalette(c("blue", "white", "red"))(200),
tl.col = "black", tl.srt = 45, addCoef.col = "black")

ANÁLISIS DE COMPONENTES PRINCIPALES (PCA)
vivienda_pca <- vivienda_clean
numericas <- vivienda_pca[sapply(vivienda_pca, is.numeric)] # Seleccionamos solo variables numéricas para el PCA
numericas_scaled <- scale(numericas) # Estandarizar datos (media = 0, varianza = 1) para PCA
pca_result <- prcomp(numericas_scaled, center = TRUE, scale. = TRUE)
# Visualizar la importancia de cada componente
summary(pca_result)
Importance of components:
PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9
Standard deviation 1.8538 1.3646 1.1782 0.91890 0.67666 0.65159 0.49055 0.43498 0.39550
Proportion of Variance 0.3819 0.2069 0.1542 0.09382 0.05087 0.04717 0.02674 0.02102 0.01738
Cumulative Proportion 0.3819 0.5887 0.7430 0.83681 0.88768 0.93486 0.96160 0.98262 1.00000
library(ggplot2)
library(ggfortify)
# Gráfico de varianza explicada (Scree Plot)
fviz_eig(pca_result, addlabels = TRUE, ylim = c(0, 100))

La gráfica que muestra es un Scree Plot (gráfico de sedimentación)
que representa el porcentaje de varianza explicada por cada componente
principal en el análisis de componentes Principales (PCA).
Interpretación de la gráfica eje X (Dimensions): Representa los
componentes principales (PC1, PC2, PC3, etc.).
Eje Y (Percentage of Explained Variance): Muestra el porcentaje de
variabilidad de los datos explicada por cada componente.
Barras azules: Indican cuánta varianza explica cada componente.
Línea negra con puntos: Ayuda a visualizar la disminución progresiva
de la varianza explicada.
fviz_pca_var(pca_result,
col.var = "contrib", # Color by contributions to the PC
gradient.cols = c("#17becf", "#7f7f7f"),
repel = TRUE # Avoid text overlapping
)

El biplot de PCA muestra cómo las variables del mercado inmobiliario
urbano se agrupan y contribuyen a la variabilidad de los datos. El
primer componente (Dim1, 38.2%) está principalmente influenciado por
variables económicas y estructurales como precio por metro cuadrado,
área construida, baños y parqueaderos, mientras que el segundo
componente (Dim2, 20.7%) está dominado por factores geográficos (latitud
y longitud). Las variables altamente contribuyentes (en verde) tienen
mayor impacto en la estructura de los datos, mientras que otras, como
piso y estrato, tienen menor relevancia. Este análisis permite
identificar patrones clave en el mercado inmobiliario y la relación
entre sus variables principales.
Conclusión
Este gráfico sugiere que los primeros 3-4 componentes principales
capturan la mayor parte de la variabilidad del dataset y pueden usarse
para reducir la dimensionalidad sin perder demasiada información.
ANÁLISIS DE CONGLOMERADOS (CLUSTERING)
Estandarizamos las variables numéricas para evitar que variables con
escalas grandes dominen el análisis:
vivienda_scaled <- scale(vivienda_clean[, c("preciom", "areaconst", "banios", "habitac", "estrato", "piso", "latitud", "longitud")])
head(vivienda_scaled)
preciom areaconst banios habitac estrato piso latitud longitud
[1,] 2.6311816 1.0004376 0.6216667 -1.1000930 1.3267681 0.5109872 1.613631 -1.586223
[2,] 0.1390340 0.8745193 0.6216667 0.2706199 1.3267681 -0.5664983 1.613631 -1.586078
[3,] 2.3272612 4.3722495 2.7219989 0.9559764 0.3552593 -0.9256602 1.614281 -1.585991
[4,] -0.6511591 -0.1747998 -0.7785548 0.2706199 -1.5877582 -0.2073365 1.589592 -1.585904
[5,] -0.3168466 -0.4406273 0.6216667 -0.4147365 0.3552593 -0.9256602 1.583745 -1.585904
[6,] 2.7831419 1.5041107 4.8223312 4.3827586 0.3552593 -0.9256602 1.584394 -1.585904
Método de codo para agrupamiento
#Para determinar el número óptimo de clusters, se puede usar el método del codo (elbow method):
fviz_nbclust(vivienda_scaled, kmeans, method = "wss")
install.packages("corrplot")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:
https://cran.rstudio.com/bin/windows/Rtools/
Warning in install.packages :
package ‘corrplot’ is in use and will not be installed
install.packages(c("devtools", "Dplyr", "factoextra", "ggplot2", "ggfortify", "FactoMineR", "corrplot"))
Error in install.packages : Updating loaded packages

El Método nos indica que el codo (número de clusters) es de 3.
Método de la silueta
library(cluster)
fviz_nbclust(vivienda_scaled, kmeans, method = "silhouette") + labs (subtitle="silhouette method")

En este método se confirma que el número de clúster optimo es de
3.
Visualizamos asignación de clusters
set.seed(123)
kmeans_result <- kmeans(vivienda_scaled, centers = 3, nstart = 25)
vivienda_clean$cluster <- as.factor(kmeans_result$cluster)
silhouette_plot <- silhouette(kmeans_result$cluster, dist(vivienda_scaled))
fviz_silhouette(silhouette_plot)

La imagen muestra el análisis de silhouette para evaluar la calidad
de la segmentación en tres clusters. El valor promedio de silhouette es
0.3, lo que indica una estructura de clustering moderada pero no óptima.
El Cluster 1 (rojo) tiene la mejor cohesión y separación con un promedio
de 0.41, lo que sugiere que sus puntos están relativamente bien
agrupados. En contraste, el Cluster 2 (verde) tiene el menor valor
promedio (0.11), lo que indica una pobre separación y posible
solapamiento con otros clusters. El Cluster 3 (azul) tiene un valor
intermedio (0.27), lo que sugiere una agrupación débil. En general, la
segmentación podría mejorarse ajustando el número de clusters o
utilizando otros métodos de agrupamiento.
Clustering Jerárquico
d <- dist(vivienda_scaled, method = "euclidean")
hc <- hclust(d, method = "ward.D2")
install.packages(c("devtools", "Dplyr", "factoextra", "ggplot2", "ggfortify", "FactoMineR", "corrplot"))
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:
https://cran.rstudio.com/bin/windows/Rtools/
Warning in install.packages :
packages ‘devtools’, ‘factoextra’, ‘ggplot2’, ‘ggfortify’, ‘FactoMineR’, ‘corrplot’ are in use and will not be installed
Installing package into ‘C:/Users/Fabio/AppData/Local/R/win-library/4.4’
(as ‘lib’ is unspecified)
Warning in install.packages :
package ‘Dplyr’ is not available for this version of R
A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
Warning in install.packages :
Perhaps you meant ‘dplyr’ ?
plot(hc)
rect.hclust(hc, k = 3, border = "red")

Distribución del clúster
fviz_cluster(kmeans_result, data = vivienda_scaled, ellipse.type = "convex")

Conclusión
El análisis de conglomerados permitió identificar tres segmentos
diferenciados dentro del mercado inmobiliario urbano. El primer grupo
agrupa propiedades de alto valor con mayor área construida, más baños y
parqueaderos, generalmente ubicadas en zonas de mayor estrato
socioeconómico. El segundo grupo representa viviendas de gama media, con
precios y características equilibradas, dirigidas a compradores de clase
media que buscan una combinación de accesibilidad y comodidad. El tercer
grupo, por su parte, se compone de propiedades más económicas, con menor
área construida y ubicadas en sectores de estrato más bajo, lo que
sugiere una oferta orientada a compradores con menor capacidad
adquisitiva. Estos resultados son clave para el desarrollo de
estrategias de inversión, fijación de precios y planificación urbana,
permitiendo a desarrolladores y compradores comprender mejor la
segmentación del mercado y optimizar la toma de decisiones en función de
sus objetivos.
ANÁLISIS DE CORRESPONDIENCIA
tabla <- table(vivienda_clean$tipo, vivienda_clean$zona, vivienda_clean$estrato, vivienda_clean$barrio)
summary(tabla)
Number of cases in table: 8327
Number of factors: 4
Test for independence of all factors:
Chisq = 228752, df = 16996, p-value = 0
Chi-squared approximation may be incorrect
summary(vivienda_clean$barrio)
Length Class Mode
8327 character character
#Se omite la variable categorica barrio debido a la alta cantidad de registros y baja relevancia para el analisis
Se omite la variable categorica barrio debido a la alta cantidad de
registros y baja relevancia para el analisis
#Se realiza histograma de precio y se realiza una conversion a variable cantegorica empleando rangos de 250 Millones de COP
hist(vivienda_clean$preciom, xlab = 'Precio')

El histograma muestra la distribución de precios de vivienda a
partir de la variable vivienda_clean$preciom. Se observa una
distribución sesgada a la derecha, lo que indica que la mayoría de las
viviendas tienen precios más bajos, concentrándose principalmente por
debajo de los 500. A medida que el precio aumenta, la frecuencia de
viviendas disminuye progresivamente, con pocos valores superiores a
1500. Esta asimetría sugiere que los precios elevados son menos comunes
en la muestra analizada.
vivienda_CA <- vivienda_clean
# Crear los cortes para los intervalos de 250, comenzando desde 0
breaks <- seq(0, max(vivienda_CA$preciom, na.rm = TRUE) + 250, by = 250)
# Crear etiquetas de manera dinámica asegurando que coincidan en número con los intervalos
labels <- paste0("[", head(breaks, -1), "-", tail(breaks, -1), ")")
# Convertir `preciom` en una variable categórica con los intervalos corregidos
vivienda_CA$preciom_cat <- cut(vivienda_CA$preciom,
breaks = breaks,
include.lowest = TRUE,
right = FALSE, # Intervalos cerrados a la izquierda [)
labels = labels)
# Verificar la nueva variable
table(vivienda_CA$preciom_cat)
[0-250) [250-500) [500-750) [750-1000) [1000-1250) [1250-1500) [1500-1750) [1750-2000)
2664 3313 1175 586 234 190 108 57
install.packages("gridExtra")
Error in install.packages : Updating loaded packages
library(gridExtra)
# Crea los gráficos de barras con las etiquetas del eje x giradas
G1 <- ggplot(vivienda_CA, aes(x=zona)) + geom_bar(fill= "#17becf") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
G2 <- ggplot(vivienda_CA, aes(x=estrato)) + geom_bar(fill= "#7f7f7f")
G3 <- ggplot(vivienda_CA, aes(x=tipo)) + geom_bar(fill= "#7f7f7f")
G4 <- ggplot(vivienda_CA, aes(x=preciom_cat)) + geom_bar(fill= "#17becf") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
# Organiza los gráficos en una cuadrícula
grid.arrange(G1, G2, G3, G4, nrow = 2)

Las gráficas muestran la distribución de viviendas según diferentes
variables. La mayoría se encuentra en la Zona Sur, seguida por la Zona
Norte y la Zona Oeste, mientras que la Zona Centro y la Zona Oriente
tienen menos presencia. En cuanto a estrato, predominan los niveles 4 y
5, con menor representación en los estratos 3 y 6. En tipo de vivienda,
los apartamentos son más comunes que las casas. Finalmente, la mayoría
de las viviendas tienen precios en los rangos más bajos (0-500), con una
disminución progresiva en frecuencia a medida que el precio aumenta,
evidenciando una distribución sesgada a la derecha.
Análisis Zona/Estrato
tabla1 <- table(vivienda_CA$zona, vivienda_CA$estrato)
colnames(tabla1) <- c("Estrato3", "Estrato4", "Estrato5", "Estrato6" )
tabla1
Estrato3 Estrato4 Estrato5 Estrato6
Zona Centro 105 14 4 1
Zona Norte 572 408 770 172
Zona Oeste 54 85 290 775
Zona Oriente 340 8 2 1
Zona Sur 382 1616 1685 1043
chisq.test(tabla1)
Pearson's Chi-squared test
data: tabla1
X-squared = 3840.4, df = 12, p-value < 2.2e-16
Este análisis indica que las variables en Zona-Estrato no son
independientes, es decir, existe una asociación estadísticamente
significativa entre ellas.
library(FactoMineR)
resultados_zona_estrato <- CA(tabla1)

Conclusión:
- Existen patrones claros de asociación entre las zonas y los estratos
socioeconómicos.
- Zonas como Oriente y Centro parecen estar relacionadas con los
estratos más bajos o medios.
- Zonas como Oeste están más vinculadas con los estratos más
altos.
- El análisis de correspondencia ha sido efectivo para identificar la
relación entre la ubicación geográfica y el nivel socioeconómico.
Análisis Precio/Tipo
tabla2 <- table(vivienda_CA$preciom_cat, vivienda_CA$tipo)
colnames(tabla2) <- c("Casa", "Apartamento")
tabla2
Casa Apartamento
[0-250) 2179 485
[250-500) 1875 1438
[500-750) 565 610
[750-1000) 239 347
[1000-1250) 110 124
[1250-1500) 86 104
[1500-1750) 29 79
[1750-2000) 23 34
chisq.test(tabla2)
Pearson's Chi-squared test
data: tabla2
X-squared = 798.48, df = 7, p-value < 2.2e-16
Este análisis indica que las variables en Zona-Estrato no son
independientes, es decir, existe una asociación estadísticamente
significativa entre ellas.
# Cargar librerías necesarias
library(ggplot2)
library(reshape2)
# Convertir la tabla en un dataframe
tabla2_df <- as.data.frame.matrix(tabla2)
# Agregar la columna de rangos de precios
tabla2_df$Rango <- rownames(tabla2_df)
# Convertir a formato largo (melt)
tabla2_melt <- melt(tabla2_df, id.vars = "Rango")
# Crear el gráfico en un plano cartesiano
ggplot(tabla2_melt, aes(x = Rango, y = value, fill = variable)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Distribución de Viviendas por Precio y Tipo",
x = "Rango de Precio",
y = "Cantidad de Viviendas") +
theme_minimal() +
scale_fill_manual(values = c("blue", "red")) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

NA
NA
NA
La distribución de viviendas por rango de precio y tipo muestra que
la mayoría de las casas se encuentran en los rangos de precios más
bajos, especialmente en el intervalo [0-250), mientras que los
apartamentos tienen una distribución más uniforme en los distintos
rangos de precios. Se observa que en el rango [250-500) hay una alta
concentración de viviendas de ambos tipos, lo que sugiere que este
segmento de precio es clave en el mercado. A medida que el precio
aumenta, la cantidad de viviendas disminuye, pero los apartamentos
mantienen una presencia relativamente mayor en los rangos superiores.
Esto podría indicar que las viviendas más costosas tienden a ser
apartamentos en lugar de casas.
Análisis Precio Zona
tabla3 <- table(vivienda_CA$preciom_cat, vivienda_CA$zona)
colnames(tabla3) <- c("Zona_Centro", "Zona_Norte", "Zona_Oeste", "Zona_Oriente", "Zona_Sur")
tabla3
Zona_Centro Zona_Norte Zona_Oeste Zona_Oriente Zona_Sur
[0-250) 46 765 95 219 1539
[250-500) 65 806 396 124 1922
[500-750) 10 215 311 6 633
[750-1000) 1 92 159 1 333
[1000-1250) 2 22 110 0 100
[1250-1500) 0 12 80 1 97
[1500-1750) 0 8 28 0 72
[1750-2000) 0 2 25 0 30
chisq.test(tabla3)
Aviso: Chi-squared approximation may be incorrect
Pearson's Chi-squared test
data: tabla3
X-squared = 1082, df = 28, p-value < 2.2e-16
Este análisis indica que las variables en Zona-Precio no son
independientes, es decir, existe una asociación estadísticamente
significativa entre ellas.
library(FactoMineR)
resultados_zona_estrato <- CA(tabla3)

Conclusión
Las zonas Oriente, Norte y Centro están más relacionadas con precios
bajos (0-250), mientras que las zonas Oeste y Sur se asocian con precios
más altos, reflejando una posible segmentación del mercado inmobiliario.
Además, la dispersión de los precios en la zona Oeste sugiere una mayor
variabilidad en los valores de los inmuebles dentro de esta área.
RESULTADOS
1. Distribución de Precios
El análisis de la distribución de precios muestra que la mayoría de
las viviendas tienen precios concentrados en rangos bajos a medios, con
una disminución progresiva en la frecuencia a medida que el precio
aumenta. Esto sugiere que el mercado inmobiliario está dominado por
propiedades económicas y de costo medio, con una menor representación de
viviendas de lujo.
Gráfico: Histograma de precios de vivienda mostrando la distribución
de frecuencia.
2. Segmentación por Zonas y Estratos
El análisis por zonas revela que la “Zona Sur” concentra el mayor
número de propiedades, mientras que “Zona Oriente” tiene la menor
cantidad. En términos de estrato socioeconómico, la mayor parte de las
viviendas pertenecen a los estratos 4 y 5, indicando un mercado
inmobiliario dirigido principalmente a la clase media-alta.
Gráfico: Gráficos de barras comparando la distribución de viviendas
por zona y estrato.
3. Relación entre Tipo de Vivienda y Precio
Se observa que los apartamentos tienen mayor representación en el
mercado en comparación con las casas. Además, los precios más bajos
tienden a concentrarse en apartamentos, mientras que las casas tienden a
ubicarse en segmentos de precios más altos.
Gráfico: Gráfico de barras que compara la cantidad de apartamentos y
casas.
4. Análisis de Correspondencia
La correspondencia entre zonas y precios muestra que las viviendas
de menor costo se concentran en ciertas zonas específicas, mientras que
las propiedades más costosas se distribuyen en ubicaciones más
exclusivas. Esta información es clave para la toma de decisiones en
estrategias de comercialización.
Gráfico: Mapa de correspondencias entre zonas y rangos de
precios.
5. Análisis Geoespacial
Si se consideran datos geoespaciales como latitud y longitud, se
pueden visualizar patrones específicos de distribución inmobiliaria en
un mapa. Esto ayuda a identificar áreas de alta y baja demanda,
facilitando la toma de decisiones estratégicas.
Gráfico: Mapa de calor mostrando la distribución geográfica de
precios de vivienda.
Conclusión General
El estudio inmobiliario revela una distribución desigual de
propiedades, con una mayor concentración de viviendas en zonas
específicas y un mercado dominado por apartamentos a precios bajos y
medios. El análisis geoespacial y de correspondencia brinda información
valiosa para la planeación y comercialización efectiva en el sector
inmobiliario.
LS0tDQp0aXRsZTogIkFjdGl2aWRhZCAxLiBFdmFsdWFjacOzbiBkZSBsYSBvZmVydGEgaW5tb2JpbGlhcmlhIHVyYmFuYSINCmF1dG9yOiBGYWJpbyBBbmRyw6lzIFBhdGVybmluYSBNaXJhbmRhDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KIyMjIEZhYmlvIEFuZHLDqXMgUGF0ZXJuaW5hIE1pcmFuZGENCg0KIyMjIyAxMC8wMi8yMDI1DQoNCiMjIyMgXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfDQoNCiMjIyMgUHJvYmxlbWENCg0KVW5hIGVtcHJlc2EgaW5tb2JpbGlhcmlhIGzDrWRlciBlbiB1bmEgZ3JhbiBjaXVkYWQgZXN0w6EgYnVzY2FuZG8gY29tcHJlbmRlciBlbiBwcm9mdW5kaWRhZCBlbCBtZXJjYWRvIGRlIHZpdmllbmRhcyB1cmJhbmFzIHBhcmEgdG9tYXIgZGVjaXNpb25lcyBlc3RyYXTDqWdpY2FzIG3DoXMgaW5mb3JtYWRhcy4gTGEgZW1wcmVzYSBwb3NlZSB1bmEgYmFzZSBkZSBkYXRvcyBleHRlbnNhIHF1ZSBjb250aWVuZSBpbmZvcm1hY2nDs24gZGV0YWxsYWRhIHNvYnJlIGRpdmVyc2FzIHByb3BpZWRhZGVzIHJlc2lkZW5jaWFsZXMgZGlzcG9uaWJsZXMgZW4gZWwgbWVyY2Fkby4gU2UgcmVxdWllcmUgcmVhbGl6YXIgdW4gYW7DoWxpc2lzIGhvbMOtc3RpY28gZGUgZXN0b3MgZGF0b3MgcGFyYSBpZGVudGlmaWNhciBwYXRyb25lcywgcmVsYWNpb25lcyB5IHNlZ21lbnRhY2lvbmVzIHJlbGV2YW50ZXMgcXVlIHBlcm1pdGFuIG1lam9yYXIgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGVuIGN1YW50byBhIGxhIGNvbXByYSwgdmVudGEgeSB2YWxvcmFjacOzbiBkZSBwcm9waWVkYWRlcy4NCg0KUmV0b3M6DQoNCkVsIHJldG8gcHJpbmNpcGFsIGNvbnNpc3RlbiBlbiByZWFsaXphciB1biBhbsOhbGlzaXMgaW50ZWdyYWwgeSBtdWx0aWRpbWVuc2lvbmFsIGRlIGxhIGJhc2UgZGUgZGF0b3MgcGFyYSBvYnRlbmVyIHVuYSBjb21wcmVuc2nDs24gZGVsIG1lcmNhZG8gaW5tb2JpbGlhcmlvIHVyYmFuby4gU2UgcmVxdWllcmUgYXBsaWNhciBkaXZlcnNhcyB0w6ljbmljYXMgZGUgYW7DoWxpc2lzIGRlIGRhdG9zLCBpbmNsdXllbmRvOg0KDQoxLiAgQW7DoWxpc2lzIGRlIENvbXBvbmVudGVzIFByaW5jaXBhbGVzOiBSZWR1Y2lyIGxhIGRpbWVuc2lvbmFsaWRhZCBkZWwgY29uanVudG8gZGUgZGF0b3MgeSB2aXN1YWxpemFyIGxhIGVzdHJ1Y3R1cmEgZGUgbGFzIHZhcmlhYmxlcyBlbiBjb21wb25lbnRlcyBwcmluY2lwYWxlcyBwYXJhIGlkZW50aWZpY2FyIGNhcmFjdGVyw61zdGljYXMgY2xhdmUgcXVlIGluZmx1eWVuIGVuIGxhIHZhcmlhY2nDs24gZGUgcHJlY2lvcyB5IHByZWZlcmVuY2lhcyBkZWwgbWVyY2Fkby4NCg0KMi4gIEFuw6FsaXNpcyBkZSBDb25nbG9tZXJhZG9zOiBBZ3J1cGFyIGxhcyBwcm9waWVkYWRlcyByZXNpZGVuY2lhbGVzIGVuIHNlZ21lbnRvcyBob21vZ8OpbmVvcyBjb24gY2FyYWN0ZXLDrXN0aWNhcyBzaW1pbGFyZXMgcGFyYSBlbnRlbmRlciBsYXMgZGluw6FtaWNhcyB5IGRlbWFuZGFzIGVzcGVjw61maWNhcyBlbiBkaWZlcmVudGVzIHBhcnRlcyBkZSBsYSBjaXVkYWQgeSBlbiBkaWZlcmVudGVzIGVzdHJhdG9zIHNvY2lvZWNvbsOzbWljb3MuDQoNCjMuICBBbsOhbGlzaXMgZGUgQ29ycmVzcG9uZGVuY2lhIDogRXhhbWluYXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyB2YXJpYWJsZXMgY2F0ZWfDs3JpY2FzICh0aXBvIGRlIHZpdmllbmRhLCB6b25hIHkgYmFycmlvKSB5IGxhcyB2YXJpYWJsZXMgbnVtw6lyaWNhcyAocHJlY2lvLCDDoXJlYSBjb25zdHJ1aWRhLCBuw7ptZXJvIGRlIHBhcnF1ZWFkZXJvcywgYmHDsW9zLCBoYWJpdGFjaW9uZXMpIHBhcmEgaWRlbnRpZmljYXIgcGF0cm9uZXMgZGUgY29tcG9ydGFtaWVudG8gZGVsIG1lcmNhZG8gaW5tb2JpbGlhcmlvLg0KDQo0LiAgVmlzdWFsaXphY2nDs24gZGUgcmVzdWx0YWRvczogUHJlc2VudGFyIGdyw6FmaWNvcywgbWFwYXMgeSBvdHJvcyByZWN1cnNvcyB2aXN1YWxlcyBwYXJhIGNvbXVuaWNhciBsb3MgaGFsbGF6Z29zIGRlIG1hbmVyYSBjbGFyYSB5IGVmZWN0aXZhIGEgbGEgZGlyZWNjacOzbiBkZSBsYSBlbXByZXNhLg0KDQpDb25jbHVzaW9uZXMgY2xhdmUgeSBsYXMgcmVjb21lbmRhY2lvbmVzIGVzcGVjw61maWNhcyBwYXJhIGd1aWFyIGxhcyBkZWNpc2lvbmVzIGVzdHJhdMOpZ2ljYXMgZGUgbGEgZW1wcmVzYSBpbm1vYmlsaWFyaWENCg0KIyMgRGVzYXJyb2xsbw0KDQojIyMjIEV4cGxvcmFjacOzbiB5IHByZXBhcmFjacOzbiBkZWwgZGF0YXNldA0KDQpgYGB7ciBlY2hvPVRSVUV9DQojIEluc3RhbGFjaW9uIGRlIGxpYnJlcsOtYXMNCg0KaW5zdGFsbC5wYWNrYWdlcyhjKCJkZXZ0b29scyIsICJEcGx5ciIsICJmYWN0b2V4dHJhIiwgImdncGxvdDIiLCAiZ2dmb3J0aWZ5IiwgIkZhY3RvTWluZVIiLCAiY29ycnBsb3QiKSkNCmxpYnJhcnkoZGV2dG9vbHMpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShmYWN0b2V4dHJhKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShnZ2ZvcnRpZnkpDQpsaWJyYXJ5KEZhY3RvTWluZVIpDQpsaWJyYXJ5KGNvcnJwbG90KQ0KDQpgYGANCg0KIyMjIyBTZSByZWFsaXphIHVuYSBleHBsb3JhY2lvbiB5IGxpbXBpZXphIGRlbCBEYXRhc2V0IG9yaWdpbmFsIHZpdmllbmRhc19mYWx0YW50ZXMgcXVlIGNvbnRpZW5lIDgzMzAgb2JzZXJ2YWNpb25lcyB5IDEzIHZhcmlhYmxlcyAoZGltZW5zaW9uZXMpDQoNCmBgYHtyfQ0KZGF0YSh2aXZpZW5kYV9mYWx0YW50ZXMpDQpoZWFkKHZpdmllbmRhX2ZhbHRhbnRlcykNCmBgYA0KDQpgYGB7cn0NCg0Kc3VtbWFyeSh2aXZpZW5kYV9mYWx0YW50ZXMpDQpgYGANCg0KIyMjIyBTZSBlbGltaW5hIGNvbHVtbmEgaWQsIHlhIHF1ZSBlcyB1biBpZGVudGlmaWNhZG9yIMO6bmljbyB5IG5vIGNvbnRpZW5lIGluZm9ybWFjacOzbiBhbmFsw610aWNhLg0KDQpgYGB7cn0NCg0KIyBFbGltaW5hciBsYSBjb2x1bW5hICdpZCcgKHN1cG9uaWVuZG8gcXVlIHNlIGxsYW1hIGV4YWN0YW1lbnRlICdpZCcpDQp2aXZpZW5kYSA8LSB2aXZpZW5kYV9mYWx0YW50ZXNbICwgLTFdDQoNCiMgVmVyaWZpY2FyIGVzdHJ1Y3R1cmEgZGVzcHXDqXMgZGUgbGEgbGltcGllemENCg0Kc3VtbWFyeSh2aXZpZW5kYSkNCg0KYGBgDQoNCiMjIyMgU2UgcHJvY2VkZSBhIHJlZW1wbGF6YXIgdmFsb3JlcyBOQSBkZSBsYXMgY29sdW1uYXMgUGlzbyAoMjY0MSkgeSBQYXJxdWVhZGVybyAoMTYwNikgcG9yIHZhbG9yZXMgMC4NCg0KYGBge3J9DQoNCnZpdmllbmRhJHBpc29baXMubmEodml2aWVuZGEkcGlzbyldIDwtIDANCg0Kdml2aWVuZGEkcGFycXVlYVtpcy5uYSh2aXZpZW5kYSRwYXJxdWVhKV0gPC0gMA0KDQoNCmBgYA0KDQpgYGB7cn0NCmhlYWQodml2aWVuZGEpDQoNCmBgYA0KDQojIyMjIExhIHZhcmlhYmxlICJ0aXBvIiB0aWVuZSB1biBwcm9ibGVtYSBjb24gbGFzIG1heXVzY3VsYXMgeSBtaW5pc2N1bGFzLCBzZSBpbmNsdXllbiB0b2RhcyBsYXMgdmFyaWFudGVzIGVuOiBhcGFydGFtZW50byB5IGNhc2EuDQoNCmBgYHtyfQ0Kdml2aWVuZGEkdGlwbyA8LSB0b2xvd2VyKHZpdmllbmRhJHRpcG8pDQoNCnZpdmllbmRhJHRpcG8gPC0gZ3N1YigiYXB0byIsICJhcGFydGFtZW50byIsIHZpdmllbmRhJHRpcG8sIGlnbm9yZS5jYXNlID0gVFJVRSkNCnVuaXF1ZSh2aXZpZW5kYSR0aXBvKQ0KdGFibGUodml2aWVuZGEkdGlwbykNCg0KYGBgDQoNCiMjIyMgRWxpbWluYW1vcyBmaWxhcyBjb24gdmFsb3JlcyBmYWx0YW50ZXMgIk5BIg0KDQpgYGB7cn0NCnZpdmllbmRhX2NsZWFuIDwtIG5hLm9taXQodml2aWVuZGEpDQoNCnN1bShpcy5uYSh2aXZpZW5kYV9jbGVhbikpICMgRGViZSBkZXZvbHZlciAwIHNpIG5vIGhheSBOQQ0KDQpkaW0odml2aWVuZGFfY2xlYW4pICNOdWV2YSBkaW1lbnNpb24gKGZpbGFzIC8gY29sdW1uYXMpDQoNCm5yb3codml2aWVuZGEpIC0gbnJvdyh2aXZpZW5kYV9jbGVhbikgICMgTsO6bWVybyBkZSBmaWxhcyBlbGltaW5hZGFzDQoNCnN1bW1hcnkodml2aWVuZGFfY2xlYW4pICNDb21wcm9iYW1vcw0KYGBgDQoNCiMjIyMgQ2FsY3VsYW1vcyBsYSBtYXRyaXogZGUgY29ycmVsYWNpb24gcGFyYSBkZXNjYXJ0YXIgdmFyaWFibGVzIHJlZHVuZGFudGVzLCBzZWxlY2Npb25hbW9zIGxhcyB2YXJpYWJsZXMgbnVtw6lyaWNhcyByZWxldmFudGVzOg0KDQpgYGB7cn0NCnZyYl9udW1fdGFibGUgIDwtIHZpdmllbmRhX2NsZWFuWywgYygncHJlY2lvbScsICdhcmVhY29uc3QnLCAnaGFiaXRhYycsICdiYW5pb3MnKV0NCg0KY29ycmVsYXRpb25fbWF0cml4IDwtIGNvcih2cmJfbnVtX3RhYmxlLCB1c2UgPSAiY29tcGxldGUub2JzIikNCnByaW50KGNvcnJlbGF0aW9uX21hdHJpeCkNCmBgYA0KDQojIyMjIFZpc3VhbGl6YW1vcyBsYSBtYXRyaXogZGUgY29ycmVsYWNpw7NuDQoNCmBgYHtyfQ0KaW5zdGFsbC5wYWNrYWdlcygiY29ycnBsb3QiKQ0KbGlicmFyeShjb3JycGxvdCkNCg0KY29ycnBsb3QoY29ycmVsYXRpb25fbWF0cml4LCBtZXRob2QgPSAiY2lyY2xlIiwgdHlwZSA9ICJsb3dlciIsDQogICAgICAgICBjb2wgPSBjb2xvclJhbXBQYWxldHRlKGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpKDIwMCksDQogICAgICAgICB0bC5jb2wgPSAiYmxhY2siLCB0bC5zcnQgPSA0NSwgYWRkQ29lZi5jb2wgPSAiYmxhY2siKQ0KYGBgDQoNCiMgQU7DgUxJU0lTIERFIENPTVBPTkVOVEVTIFBSSU5DSVBBTEVTIChQQ0EpDQoNCmBgYHtyfQ0Kdml2aWVuZGFfcGNhIDwtIHZpdmllbmRhX2NsZWFuDQoNCm51bWVyaWNhcyA8LSB2aXZpZW5kYV9wY2Fbc2FwcGx5KHZpdmllbmRhX3BjYSwgaXMubnVtZXJpYyldICMgU2VsZWNjaW9uYW1vcyBzb2xvIHZhcmlhYmxlcyBudW3DqXJpY2FzIHBhcmEgZWwgUENBDQoNCg0KbnVtZXJpY2FzX3NjYWxlZCA8LSBzY2FsZShudW1lcmljYXMpICMgRXN0YW5kYXJpemFyIGRhdG9zIChtZWRpYSA9IDAsIHZhcmlhbnphID0gMSkgcGFyYSBQQ0ENCmBgYA0KDQpgYGB7cn0NCnBjYV9yZXN1bHQgPC0gcHJjb21wKG51bWVyaWNhc19zY2FsZWQsIGNlbnRlciA9IFRSVUUsIHNjYWxlLiA9IFRSVUUpDQoNCiMgVmlzdWFsaXphciBsYSBpbXBvcnRhbmNpYSBkZSBjYWRhIGNvbXBvbmVudGUNCnN1bW1hcnkocGNhX3Jlc3VsdCkNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ2dmb3J0aWZ5KQ0KDQojIEdyw6FmaWNvIGRlIHZhcmlhbnphIGV4cGxpY2FkYSAoU2NyZWUgUGxvdCkNCmZ2aXpfZWlnKHBjYV9yZXN1bHQsIGFkZGxhYmVscyA9IFRSVUUsIHlsaW0gPSBjKDAsIDEwMCkpDQoNCmBgYA0KDQojIyMjIExhIGdyw6FmaWNhIHF1ZSBtdWVzdHJhIGVzIHVuIFNjcmVlIFBsb3QgKGdyw6FmaWNvIGRlIHNlZGltZW50YWNpw7NuKSBxdWUgcmVwcmVzZW50YSBlbCBwb3JjZW50YWplIGRlIHZhcmlhbnphIGV4cGxpY2FkYSBwb3IgY2FkYSBjb21wb25lbnRlIHByaW5jaXBhbCBlbiBlbCBhbsOhbGlzaXMgZGUgY29tcG9uZW50ZXMgUHJpbmNpcGFsZXMgKFBDQSkuDQoNCiMjIyMgSW50ZXJwcmV0YWNpw7NuIGRlIGxhIGdyw6FmaWNhIGVqZSBYIChEaW1lbnNpb25zKTogUmVwcmVzZW50YSBsb3MgY29tcG9uZW50ZXMgcHJpbmNpcGFsZXMgKFBDMSwgUEMyLCBQQzMsIGV0Yy4pLg0KDQojIyMjIEVqZSBZIChQZXJjZW50YWdlIG9mIEV4cGxhaW5lZCBWYXJpYW5jZSk6IE11ZXN0cmEgZWwgcG9yY2VudGFqZSBkZSB2YXJpYWJpbGlkYWQgZGUgbG9zIGRhdG9zIGV4cGxpY2FkYSBwb3IgY2FkYSBjb21wb25lbnRlLg0KDQojIyMjIEJhcnJhcyBhenVsZXM6IEluZGljYW4gY3XDoW50YSB2YXJpYW56YSBleHBsaWNhIGNhZGEgY29tcG9uZW50ZS4NCg0KIyMjIyBMw61uZWEgbmVncmEgY29uIHB1bnRvczogQXl1ZGEgYSB2aXN1YWxpemFyIGxhIGRpc21pbnVjacOzbiBwcm9ncmVzaXZhIGRlIGxhIHZhcmlhbnphIGV4cGxpY2FkYS4NCg0KYGBge3J9DQpmdml6X3BjYV92YXIocGNhX3Jlc3VsdCwNCmNvbC52YXIgPSAiY29udHJpYiIsICMgQ29sb3IgYnkgY29udHJpYnV0aW9ucyB0byB0aGUgUEMNCmdyYWRpZW50LmNvbHMgPSBjKCIjMTdiZWNmIiwgICIjN2Y3ZjdmIiksDQpyZXBlbCA9IFRSVUUgICAgICMgQXZvaWQgdGV4dCBvdmVybGFwcGluZw0KKSANCg0KYGBgDQoNCiMjIyMgRWwgYmlwbG90IGRlIFBDQSBtdWVzdHJhIGPDs21vIGxhcyB2YXJpYWJsZXMgZGVsIG1lcmNhZG8gaW5tb2JpbGlhcmlvIHVyYmFubyBzZSBhZ3J1cGFuIHkgY29udHJpYnV5ZW4gYSBsYSB2YXJpYWJpbGlkYWQgZGUgbG9zIGRhdG9zLiBFbCBwcmltZXIgY29tcG9uZW50ZSAoRGltMSwgMzguMiUpIGVzdMOhIHByaW5jaXBhbG1lbnRlIGluZmx1ZW5jaWFkbyBwb3IgdmFyaWFibGVzIGVjb27Ds21pY2FzIHkgZXN0cnVjdHVyYWxlcyBjb21vIHByZWNpbyBwb3IgbWV0cm8gY3VhZHJhZG8sIMOhcmVhIGNvbnN0cnVpZGEsIGJhw7FvcyB5IHBhcnF1ZWFkZXJvcywgbWllbnRyYXMgcXVlIGVsIHNlZ3VuZG8gY29tcG9uZW50ZSAoRGltMiwgMjAuNyUpIGVzdMOhIGRvbWluYWRvIHBvciBmYWN0b3JlcyBnZW9ncsOhZmljb3MgKGxhdGl0dWQgeSBsb25naXR1ZCkuIExhcyB2YXJpYWJsZXMgYWx0YW1lbnRlIGNvbnRyaWJ1eWVudGVzIChlbiB2ZXJkZSkgdGllbmVuIG1heW9yIGltcGFjdG8gZW4gbGEgZXN0cnVjdHVyYSBkZSBsb3MgZGF0b3MsIG1pZW50cmFzIHF1ZSBvdHJhcywgY29tbyBwaXNvIHkgZXN0cmF0bywgdGllbmVuIG1lbm9yIHJlbGV2YW5jaWEuIEVzdGUgYW7DoWxpc2lzIHBlcm1pdGUgaWRlbnRpZmljYXIgcGF0cm9uZXMgY2xhdmUgZW4gZWwgbWVyY2FkbyBpbm1vYmlsaWFyaW8geSBsYSByZWxhY2nDs24gZW50cmUgc3VzIHZhcmlhYmxlcyBwcmluY2lwYWxlcy4NCg0KIyMjIENvbmNsdXNpw7NuDQoNCiMjIyMgRXN0ZSBncsOhZmljbyBzdWdpZXJlIHF1ZSBsb3MgcHJpbWVyb3MgMy00IGNvbXBvbmVudGVzIHByaW5jaXBhbGVzIGNhcHR1cmFuIGxhIG1heW9yIHBhcnRlIGRlIGxhIHZhcmlhYmlsaWRhZCBkZWwgZGF0YXNldCB5IHB1ZWRlbiB1c2Fyc2UgcGFyYSByZWR1Y2lyIGxhIGRpbWVuc2lvbmFsaWRhZCBzaW4gcGVyZGVyIGRlbWFzaWFkYSBpbmZvcm1hY2nDs24uDQoNCiMgQU7DgUxJU0lTIERFIENPTkdMT01FUkFET1MgKENMVVNURVJJTkcpDQoNCiMjIyMgRXN0YW5kYXJpemFtb3MgbGFzIHZhcmlhYmxlcyBudW3DqXJpY2FzIHBhcmEgZXZpdGFyIHF1ZSB2YXJpYWJsZXMgY29uIGVzY2FsYXMgZ3JhbmRlcyBkb21pbmVuIGVsIGFuw6FsaXNpczoNCg0KYGBge3J9DQp2aXZpZW5kYV9zY2FsZWQgPC0gc2NhbGUodml2aWVuZGFfY2xlYW5bLCBjKCJwcmVjaW9tIiwgImFyZWFjb25zdCIsICJiYW5pb3MiLCAiaGFiaXRhYyIsICJlc3RyYXRvIiwgInBpc28iLCAibGF0aXR1ZCIsICJsb25naXR1ZCIpXSkNCmhlYWQodml2aWVuZGFfc2NhbGVkKQ0KYGBgDQoNCiMjIE3DqXRvZG8gZGUgY29kbyBwYXJhIGFncnVwYW1pZW50bw0KDQpgYGB7cn0NCiNQYXJhIGRldGVybWluYXIgZWwgbsO6bWVybyDDs3B0aW1vIGRlIGNsdXN0ZXJzLCBzZSBwdWVkZSB1c2FyIGVsIG3DqXRvZG8gZGVsIGNvZG8gKGVsYm93IG1ldGhvZCk6DQoNCmZ2aXpfbmJjbHVzdCh2aXZpZW5kYV9zY2FsZWQsIGttZWFucywgbWV0aG9kID0gIndzcyIpDQoNCmBgYA0KDQojIyMjIEVsIE3DqXRvZG8gbm9zIGluZGljYSBxdWUgZWwgY29kbyAobsO6bWVybyBkZSBjbHVzdGVycykgZXMgZGUgMy4NCg0KIyMgTcOpdG9kbyBkZSBsYSBzaWx1ZXRhDQoNCmBgYHtyfQ0KbGlicmFyeShjbHVzdGVyKQ0KDQpmdml6X25iY2x1c3Qodml2aWVuZGFfc2NhbGVkLCBrbWVhbnMsIG1ldGhvZCA9ICJzaWxob3VldHRlIikgKyBsYWJzIChzdWJ0aXRsZT0ic2lsaG91ZXR0ZSBtZXRob2QiKQ0KYGBgDQoNCiMjIyMgRW4gZXN0ZSBtw6l0b2RvIHNlIGNvbmZpcm1hIHF1ZSBlbCBuw7ptZXJvIGRlIGNsw7pzdGVyIG9wdGltbyBlcyBkZSAzLg0KDQojIyMgVmlzdWFsaXphbW9zIGFzaWduYWNpw7NuIGRlIGNsdXN0ZXJzDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKSAgDQprbWVhbnNfcmVzdWx0IDwtIGttZWFucyh2aXZpZW5kYV9zY2FsZWQsIGNlbnRlcnMgPSAzLCBuc3RhcnQgPSAyNSkNCnZpdmllbmRhX2NsZWFuJGNsdXN0ZXIgPC0gYXMuZmFjdG9yKGttZWFuc19yZXN1bHQkY2x1c3RlcikNCg0Kc2lsaG91ZXR0ZV9wbG90IDwtIHNpbGhvdWV0dGUoa21lYW5zX3Jlc3VsdCRjbHVzdGVyLCBkaXN0KHZpdmllbmRhX3NjYWxlZCkpDQpmdml6X3NpbGhvdWV0dGUoc2lsaG91ZXR0ZV9wbG90KQ0KYGBgDQoNCiMjIyMgTGEgaW1hZ2VuIG11ZXN0cmEgZWwgYW7DoWxpc2lzIGRlIHNpbGhvdWV0dGUgcGFyYSBldmFsdWFyIGxhIGNhbGlkYWQgZGUgbGEgc2VnbWVudGFjacOzbiBlbiB0cmVzIGNsdXN0ZXJzLiBFbCB2YWxvciBwcm9tZWRpbyBkZSBzaWxob3VldHRlIGVzIDAuMywgbG8gcXVlIGluZGljYSB1bmEgZXN0cnVjdHVyYSBkZSBjbHVzdGVyaW5nIG1vZGVyYWRhIHBlcm8gbm8gw7NwdGltYS4gRWwgQ2x1c3RlciAxIChyb2pvKSB0aWVuZSBsYSBtZWpvciBjb2hlc2nDs24geSBzZXBhcmFjacOzbiBjb24gdW4gcHJvbWVkaW8gZGUgMC40MSwgbG8gcXVlIHN1Z2llcmUgcXVlIHN1cyBwdW50b3MgZXN0w6FuIHJlbGF0aXZhbWVudGUgYmllbiBhZ3J1cGFkb3MuIEVuIGNvbnRyYXN0ZSwgZWwgQ2x1c3RlciAyICh2ZXJkZSkgdGllbmUgZWwgbWVub3IgdmFsb3IgcHJvbWVkaW8gKDAuMTEpLCBsbyBxdWUgaW5kaWNhIHVuYSBwb2JyZSBzZXBhcmFjacOzbiB5IHBvc2libGUgc29sYXBhbWllbnRvIGNvbiBvdHJvcyBjbHVzdGVycy4gRWwgQ2x1c3RlciAzIChhenVsKSB0aWVuZSB1biB2YWxvciBpbnRlcm1lZGlvICgwLjI3KSwgbG8gcXVlIHN1Z2llcmUgdW5hIGFncnVwYWNpw7NuIGTDqWJpbC4gRW4gZ2VuZXJhbCwgbGEgc2VnbWVudGFjacOzbiBwb2Ryw61hIG1lam9yYXJzZSBhanVzdGFuZG8gZWwgbsO6bWVybyBkZSBjbHVzdGVycyBvIHV0aWxpemFuZG8gb3Ryb3MgbcOpdG9kb3MgZGUgYWdydXBhbWllbnRvLg0KDQojIyBDbHVzdGVyaW5nIEplcsOhcnF1aWNvDQoNCmBgYHtyfQ0KZCA8LSBkaXN0KHZpdmllbmRhX3NjYWxlZCwgbWV0aG9kID0gImV1Y2xpZGVhbiIpDQpoYyA8LSBoY2x1c3QoZCwgbWV0aG9kID0gIndhcmQuRDIiKQ0KcGxvdChoYykNCnJlY3QuaGNsdXN0KGhjLCBrID0gMywgYm9yZGVyID0gInJlZCIpDQoNCmBgYA0KDQojIyMgRGlzdHJpYnVjacOzbiBkZWwgY2zDunN0ZXINCg0KYGBge3J9DQpmdml6X2NsdXN0ZXIoa21lYW5zX3Jlc3VsdCwgZGF0YSA9IHZpdmllbmRhX3NjYWxlZCwgZWxsaXBzZS50eXBlID0gImNvbnZleCIpDQoNCmBgYA0KDQojIyMgQ29uY2x1c2nDs24NCg0KIyMjIyBFbCBhbsOhbGlzaXMgZGUgY29uZ2xvbWVyYWRvcyBwZXJtaXRpw7MgaWRlbnRpZmljYXIgdHJlcyBzZWdtZW50b3MgZGlmZXJlbmNpYWRvcyBkZW50cm8gZGVsIG1lcmNhZG8gaW5tb2JpbGlhcmlvIHVyYmFuby4gRWwgcHJpbWVyIGdydXBvIGFncnVwYSBwcm9waWVkYWRlcyBkZSBhbHRvIHZhbG9yIGNvbiBtYXlvciDDoXJlYSBjb25zdHJ1aWRhLCBtw6FzIGJhw7FvcyB5IHBhcnF1ZWFkZXJvcywgZ2VuZXJhbG1lbnRlIHViaWNhZGFzIGVuIHpvbmFzIGRlIG1heW9yIGVzdHJhdG8gc29jaW9lY29uw7NtaWNvLiBFbCBzZWd1bmRvIGdydXBvIHJlcHJlc2VudGEgdml2aWVuZGFzIGRlIGdhbWEgbWVkaWEsIGNvbiBwcmVjaW9zIHkgY2FyYWN0ZXLDrXN0aWNhcyBlcXVpbGlicmFkYXMsIGRpcmlnaWRhcyBhIGNvbXByYWRvcmVzIGRlIGNsYXNlIG1lZGlhIHF1ZSBidXNjYW4gdW5hIGNvbWJpbmFjacOzbiBkZSBhY2Nlc2liaWxpZGFkIHkgY29tb2RpZGFkLiBFbCB0ZXJjZXIgZ3J1cG8sIHBvciBzdSBwYXJ0ZSwgc2UgY29tcG9uZSBkZSBwcm9waWVkYWRlcyBtw6FzIGVjb27Ds21pY2FzLCBjb24gbWVub3Igw6FyZWEgY29uc3RydWlkYSB5IHViaWNhZGFzIGVuIHNlY3RvcmVzIGRlIGVzdHJhdG8gbcOhcyBiYWpvLCBsbyBxdWUgc3VnaWVyZSB1bmEgb2ZlcnRhIG9yaWVudGFkYSBhIGNvbXByYWRvcmVzIGNvbiBtZW5vciBjYXBhY2lkYWQgYWRxdWlzaXRpdmEuIEVzdG9zIHJlc3VsdGFkb3Mgc29uIGNsYXZlIHBhcmEgZWwgZGVzYXJyb2xsbyBkZSBlc3RyYXRlZ2lhcyBkZSBpbnZlcnNpw7NuLCBmaWphY2nDs24gZGUgcHJlY2lvcyB5IHBsYW5pZmljYWNpw7NuIHVyYmFuYSwgcGVybWl0aWVuZG8gYSBkZXNhcnJvbGxhZG9yZXMgeSBjb21wcmFkb3JlcyBjb21wcmVuZGVyIG1lam9yIGxhIHNlZ21lbnRhY2nDs24gZGVsIG1lcmNhZG8geSBvcHRpbWl6YXIgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGVuIGZ1bmNpw7NuIGRlIHN1cyBvYmpldGl2b3MuDQoNCiMgQU7DgUxJU0lTIERFIENPUlJFU1BPTkRJRU5DSUENCg0KYGBge3J9DQoNCnRhYmxhIDwtIHRhYmxlKHZpdmllbmRhX2NsZWFuJHRpcG8sIHZpdmllbmRhX2NsZWFuJHpvbmEsIHZpdmllbmRhX2NsZWFuJGVzdHJhdG8sIHZpdmllbmRhX2NsZWFuJGJhcnJpbykNCnN1bW1hcnkodGFibGEpDQpzdW1tYXJ5KHZpdmllbmRhX2NsZWFuJGJhcnJpbykNCg0KYGBgDQoNCiMjIyMgU2Ugb21pdGUgbGEgdmFyaWFibGUgY2F0ZWdvcmljYSBiYXJyaW8gZGViaWRvIGEgbGEgYWx0YSBjYW50aWRhZCBkZSByZWdpc3Ryb3MgeSBiYWphIHJlbGV2YW5jaWEgcGFyYSBlbCBhbmFsaXNpcw0KDQpgYGB7cn0NCiNTZSByZWFsaXphIGhpc3RvZ3JhbWEgZGUgcHJlY2lvIHkgc2UgcmVhbGl6YSB1bmEgY29udmVyc2lvbiBhIHZhcmlhYmxlIGNhbnRlZ29yaWNhIGVtcGxlYW5kbyByYW5nb3MgZGUgMjUwIE1pbGxvbmVzIGRlIENPUA0KaGlzdCh2aXZpZW5kYV9jbGVhbiRwcmVjaW9tLCB4bGFiID0gJ1ByZWNpbycpDQpgYGANCg0KIyMjIyBFbCBoaXN0b2dyYW1hIG11ZXN0cmEgbGEgZGlzdHJpYnVjacOzbiBkZSBwcmVjaW9zIGRlIHZpdmllbmRhIGEgcGFydGlyIGRlIGxhIHZhcmlhYmxlIHZpdmllbmRhX2NsZWFuXCRwcmVjaW9tLiBTZSBvYnNlcnZhIHVuYSBkaXN0cmlidWNpw7NuIHNlc2dhZGEgYSBsYSBkZXJlY2hhLCBsbyBxdWUgaW5kaWNhIHF1ZSBsYSBtYXlvcsOtYSBkZSBsYXMgdml2aWVuZGFzIHRpZW5lbiBwcmVjaW9zIG3DoXMgYmFqb3MsIGNvbmNlbnRyw6FuZG9zZSBwcmluY2lwYWxtZW50ZSBwb3IgZGViYWpvIGRlIGxvcyA1MDAuIEEgbWVkaWRhIHF1ZSBlbCBwcmVjaW8gYXVtZW50YSwgbGEgZnJlY3VlbmNpYSBkZSB2aXZpZW5kYXMgZGlzbWludXllIHByb2dyZXNpdmFtZW50ZSwgY29uIHBvY29zIHZhbG9yZXMgc3VwZXJpb3JlcyBhIDE1MDAuIEVzdGEgYXNpbWV0csOtYSBzdWdpZXJlIHF1ZSBsb3MgcHJlY2lvcyBlbGV2YWRvcyBzb24gbWVub3MgY29tdW5lcyBlbiBsYSBtdWVzdHJhIGFuYWxpemFkYS4NCg0KYGBge3J9DQp2aXZpZW5kYV9DQSA8LSB2aXZpZW5kYV9jbGVhbg0KIyBDcmVhciBsb3MgY29ydGVzIHBhcmEgbG9zIGludGVydmFsb3MgZGUgMjUwLCBjb21lbnphbmRvIGRlc2RlIDANCmJyZWFrcyA8LSBzZXEoMCwgbWF4KHZpdmllbmRhX0NBJHByZWNpb20sIG5hLnJtID0gVFJVRSkgKyAyNTAsIGJ5ID0gMjUwKQ0KDQojIENyZWFyIGV0aXF1ZXRhcyBkZSBtYW5lcmEgZGluw6FtaWNhIGFzZWd1cmFuZG8gcXVlIGNvaW5jaWRhbiBlbiBuw7ptZXJvIGNvbiBsb3MgaW50ZXJ2YWxvcw0KbGFiZWxzIDwtIHBhc3RlMCgiWyIsIGhlYWQoYnJlYWtzLCAtMSksICItIiwgdGFpbChicmVha3MsIC0xKSwgIikiKQ0KDQojIENvbnZlcnRpciBgcHJlY2lvbWAgZW4gdW5hIHZhcmlhYmxlIGNhdGVnw7NyaWNhIGNvbiBsb3MgaW50ZXJ2YWxvcyBjb3JyZWdpZG9zDQp2aXZpZW5kYV9DQSRwcmVjaW9tX2NhdCA8LSBjdXQodml2aWVuZGFfQ0EkcHJlY2lvbSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYnJlYWtzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gRkFMU0UsICAjIEludGVydmFsb3MgY2VycmFkb3MgYSBsYSBpenF1aWVyZGEgWykNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBsYWJlbHMpDQoNCiMgVmVyaWZpY2FyIGxhIG51ZXZhIHZhcmlhYmxlDQp0YWJsZSh2aXZpZW5kYV9DQSRwcmVjaW9tX2NhdCkNCg0KYGBgDQoNCmBgYHtyfQ0KaW5zdGFsbC5wYWNrYWdlcygiZ3JpZEV4dHJhIikNCmxpYnJhcnkoZ3JpZEV4dHJhKQ0KDQojIENyZWEgbG9zIGdyw6FmaWNvcyBkZSBiYXJyYXMgY29uIGxhcyBldGlxdWV0YXMgZGVsIGVqZSB4IGdpcmFkYXMNCkcxIDwtIGdncGxvdCh2aXZpZW5kYV9DQSwgYWVzKHg9em9uYSkpICsgZ2VvbV9iYXIoZmlsbD0gIiMxN2JlY2YiKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSkNCkcyIDwtIGdncGxvdCh2aXZpZW5kYV9DQSwgYWVzKHg9ZXN0cmF0bykpICsgZ2VvbV9iYXIoZmlsbD0gIiM3ZjdmN2YiKQ0KRzMgPC0gZ2dwbG90KHZpdmllbmRhX0NBLCBhZXMoeD10aXBvKSkgKyBnZW9tX2JhcihmaWxsPSAiIzdmN2Y3ZiIpDQpHNCA8LSBnZ3Bsb3Qodml2aWVuZGFfQ0EsIGFlcyh4PXByZWNpb21fY2F0KSkgKyBnZW9tX2JhcihmaWxsPSAiIzE3YmVjZiIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpKQ0KDQojIE9yZ2FuaXphIGxvcyBncsOhZmljb3MgZW4gdW5hIGN1YWRyw61jdWxhDQpncmlkLmFycmFuZ2UoRzEsIEcyLCBHMywgRzQsIG5yb3cgPSAyKQ0KYGBgDQoNCiMjIyMgTGFzIGdyw6FmaWNhcyBtdWVzdHJhbiBsYSBkaXN0cmlidWNpw7NuIGRlIHZpdmllbmRhcyBzZWfDum4gZGlmZXJlbnRlcyB2YXJpYWJsZXMuIExhIG1heW9yw61hIHNlIGVuY3VlbnRyYSBlbiBsYSBab25hIFN1ciwgc2VndWlkYSBwb3IgbGEgWm9uYSBOb3J0ZSB5IGxhIFpvbmEgT2VzdGUsIG1pZW50cmFzIHF1ZSBsYSBab25hIENlbnRybyB5IGxhIFpvbmEgT3JpZW50ZSB0aWVuZW4gbWVub3MgcHJlc2VuY2lhLiBFbiBjdWFudG8gYSBlc3RyYXRvLCBwcmVkb21pbmFuIGxvcyBuaXZlbGVzIDQgeSA1LCBjb24gbWVub3IgcmVwcmVzZW50YWNpw7NuIGVuIGxvcyBlc3RyYXRvcyAzIHkgNi4gRW4gdGlwbyBkZSB2aXZpZW5kYSwgbG9zIGFwYXJ0YW1lbnRvcyBzb24gbcOhcyBjb211bmVzIHF1ZSBsYXMgY2FzYXMuIEZpbmFsbWVudGUsIGxhIG1heW9yw61hIGRlIGxhcyB2aXZpZW5kYXMgdGllbmVuIHByZWNpb3MgZW4gbG9zIHJhbmdvcyBtw6FzIGJham9zICgwLTUwMCksIGNvbiB1bmEgZGlzbWludWNpw7NuIHByb2dyZXNpdmEgZW4gZnJlY3VlbmNpYSBhIG1lZGlkYSBxdWUgZWwgcHJlY2lvIGF1bWVudGEsIGV2aWRlbmNpYW5kbyB1bmEgZGlzdHJpYnVjacOzbiBzZXNnYWRhIGEgbGEgZGVyZWNoYS4NCg0KIyMjIEFuw6FsaXNpcyBab25hL0VzdHJhdG8NCg0KYGBge3J9DQoNCnRhYmxhMSA8LSB0YWJsZSh2aXZpZW5kYV9DQSR6b25hLCB2aXZpZW5kYV9DQSRlc3RyYXRvKQ0KY29sbmFtZXModGFibGExKSA8LSBjKCJFc3RyYXRvMyIsICJFc3RyYXRvNCIsICJFc3RyYXRvNSIsICJFc3RyYXRvNiIgKQ0KdGFibGExDQpgYGANCg0KYGBge3J9DQpjaGlzcS50ZXN0KHRhYmxhMSkNCmBgYA0KDQojIyMjIEVzdGUgYW7DoWxpc2lzIGluZGljYSBxdWUgbGFzIHZhcmlhYmxlcyBlbiBab25hLUVzdHJhdG8gbm8gc29uIGluZGVwZW5kaWVudGVzLCBlcyBkZWNpciwgZXhpc3RlIHVuYSBhc29jaWFjacOzbiBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhIGVudHJlIGVsbGFzLg0KDQpgYGB7cn0NCmxpYnJhcnkoRmFjdG9NaW5lUikNCnJlc3VsdGFkb3Nfem9uYV9lc3RyYXRvIDwtIENBKHRhYmxhMSkNCmBgYA0KDQojIyMgQ29uY2x1c2nDs246DQoNCi0gICBFeGlzdGVuIHBhdHJvbmVzIGNsYXJvcyBkZSBhc29jaWFjacOzbiBlbnRyZSBsYXMgem9uYXMgeSBsb3MgZXN0cmF0b3Mgc29jaW9lY29uw7NtaWNvcy4NCi0gICBab25hcyBjb21vIE9yaWVudGUgeSBDZW50cm8gcGFyZWNlbiBlc3RhciByZWxhY2lvbmFkYXMgY29uIGxvcyBlc3RyYXRvcyBtw6FzIGJham9zIG8gbWVkaW9zLg0KLSAgIFpvbmFzIGNvbW8gT2VzdGUgZXN0w6FuIG3DoXMgdmluY3VsYWRhcyBjb24gbG9zIGVzdHJhdG9zIG3DoXMgYWx0b3MuDQotICAgRWwgYW7DoWxpc2lzIGRlIGNvcnJlc3BvbmRlbmNpYSBoYSBzaWRvIGVmZWN0aXZvIHBhcmEgaWRlbnRpZmljYXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhIHViaWNhY2nDs24gZ2VvZ3LDoWZpY2EgeSBlbCBuaXZlbCBzb2Npb2Vjb27Ds21pY28uDQoNCiMjIyBBbsOhbGlzaXMgUHJlY2lvL1RpcG8NCg0KYGBge3J9DQp0YWJsYTIgPC0gdGFibGUodml2aWVuZGFfQ0EkcHJlY2lvbV9jYXQsIHZpdmllbmRhX0NBJHRpcG8pDQpjb2xuYW1lcyh0YWJsYTIpIDwtIGMoIkNhc2EiLCAiQXBhcnRhbWVudG8iKQ0KdGFibGEyDQpgYGANCg0KYGBge3J9DQpjaGlzcS50ZXN0KHRhYmxhMikNCmBgYA0KDQpFc3RlIGFuw6FsaXNpcyBpbmRpY2EgcXVlIGxhcyB2YXJpYWJsZXMgZW4gWm9uYS1Fc3RyYXRvIG5vIHNvbiBpbmRlcGVuZGllbnRlcywgZXMgZGVjaXIsIGV4aXN0ZSB1bmEgYXNvY2lhY2nDs24gZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YSBlbnRyZSBlbGxhcy4NCg0KYGBge3J9DQojIENhcmdhciBsaWJyZXLDrWFzIG5lY2VzYXJpYXMNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocmVzaGFwZTIpDQoNCiMgQ29udmVydGlyIGxhIHRhYmxhIGVuIHVuIGRhdGFmcmFtZQ0KdGFibGEyX2RmIDwtIGFzLmRhdGEuZnJhbWUubWF0cml4KHRhYmxhMikNCg0KIyBBZ3JlZ2FyIGxhIGNvbHVtbmEgZGUgcmFuZ29zIGRlIHByZWNpb3MNCnRhYmxhMl9kZiRSYW5nbyA8LSByb3duYW1lcyh0YWJsYTJfZGYpDQoNCiMgQ29udmVydGlyIGEgZm9ybWF0byBsYXJnbyAobWVsdCkNCnRhYmxhMl9tZWx0IDwtIG1lbHQodGFibGEyX2RmLCBpZC52YXJzID0gIlJhbmdvIikNCg0KIyBDcmVhciBlbCBncsOhZmljbyBlbiB1biBwbGFubyBjYXJ0ZXNpYW5vDQpnZ3Bsb3QodGFibGEyX21lbHQsIGFlcyh4ID0gUmFuZ28sIHkgPSB2YWx1ZSwgZmlsbCA9IHZhcmlhYmxlKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBWaXZpZW5kYXMgcG9yIFByZWNpbyB5IFRpcG8iLA0KICAgICAgIHggPSAiUmFuZ28gZGUgUHJlY2lvIiwNCiAgICAgICB5ID0gIkNhbnRpZGFkIGRlIFZpdmllbmRhcyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiYmx1ZSIsICJyZWQiKSkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KDQoNCg0KYGBgDQoNCiMjIyMgTGEgZGlzdHJpYnVjacOzbiBkZSB2aXZpZW5kYXMgcG9yIHJhbmdvIGRlIHByZWNpbyB5IHRpcG8gbXVlc3RyYSBxdWUgbGEgbWF5b3LDrWEgZGUgbGFzIGNhc2FzIHNlIGVuY3VlbnRyYW4gZW4gbG9zIHJhbmdvcyBkZSBwcmVjaW9zIG3DoXMgYmFqb3MsIGVzcGVjaWFsbWVudGUgZW4gZWwgaW50ZXJ2YWxvIFswLTI1MCksIG1pZW50cmFzIHF1ZSBsb3MgYXBhcnRhbWVudG9zIHRpZW5lbiB1bmEgZGlzdHJpYnVjacOzbiBtw6FzIHVuaWZvcm1lIGVuIGxvcyBkaXN0aW50b3MgcmFuZ29zIGRlIHByZWNpb3MuIFNlIG9ic2VydmEgcXVlIGVuIGVsIHJhbmdvIFsyNTAtNTAwKSBoYXkgdW5hIGFsdGEgY29uY2VudHJhY2nDs24gZGUgdml2aWVuZGFzIGRlIGFtYm9zIHRpcG9zLCBsbyBxdWUgc3VnaWVyZSBxdWUgZXN0ZSBzZWdtZW50byBkZSBwcmVjaW8gZXMgY2xhdmUgZW4gZWwgbWVyY2Fkby4gQSBtZWRpZGEgcXVlIGVsIHByZWNpbyBhdW1lbnRhLCBsYSBjYW50aWRhZCBkZSB2aXZpZW5kYXMgZGlzbWludXllLCBwZXJvIGxvcyBhcGFydGFtZW50b3MgbWFudGllbmVuIHVuYSBwcmVzZW5jaWEgcmVsYXRpdmFtZW50ZSBtYXlvciBlbiBsb3MgcmFuZ29zIHN1cGVyaW9yZXMuIEVzdG8gcG9kcsOtYSBpbmRpY2FyIHF1ZSBsYXMgdml2aWVuZGFzIG3DoXMgY29zdG9zYXMgdGllbmRlbiBhIHNlciBhcGFydGFtZW50b3MgZW4gbHVnYXIgZGUgY2FzYXMuDQoNCiMjIyBBbsOhbGlzaXMgUHJlY2lvIFpvbmENCg0KYGBge3J9DQp0YWJsYTMgPC0gdGFibGUodml2aWVuZGFfQ0EkcHJlY2lvbV9jYXQsIHZpdmllbmRhX0NBJHpvbmEpDQpjb2xuYW1lcyh0YWJsYTMpIDwtIGMoIlpvbmFfQ2VudHJvIiwgIlpvbmFfTm9ydGUiLCAiWm9uYV9PZXN0ZSIsICJab25hX09yaWVudGUiLCAiWm9uYV9TdXIiKQ0KdGFibGEzDQpgYGANCg0KYGBge3J9DQpjaGlzcS50ZXN0KHRhYmxhMykNCmBgYA0KDQpFc3RlIGFuw6FsaXNpcyBpbmRpY2EgcXVlIGxhcyB2YXJpYWJsZXMgZW4gWm9uYS1QcmVjaW8gbm8gc29uIGluZGVwZW5kaWVudGVzLCBlcyBkZWNpciwgZXhpc3RlIHVuYSBhc29jaWFjacOzbiBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhIGVudHJlIGVsbGFzLg0KDQpgYGB7cn0NCmxpYnJhcnkoRmFjdG9NaW5lUikNCnJlc3VsdGFkb3Nfem9uYV9lc3RyYXRvIDwtIENBKHRhYmxhMykNCg0KYGBgDQoNCiMjIyBDb25jbHVzacOzbg0KDQpMYXMgem9uYXMgT3JpZW50ZSwgTm9ydGUgeSBDZW50cm8gZXN0w6FuIG3DoXMgcmVsYWNpb25hZGFzIGNvbiBwcmVjaW9zIGJham9zICgwLTI1MCksIG1pZW50cmFzIHF1ZSBsYXMgem9uYXMgT2VzdGUgeSBTdXIgc2UgYXNvY2lhbiBjb24gcHJlY2lvcyBtw6FzIGFsdG9zLCByZWZsZWphbmRvIHVuYSBwb3NpYmxlIHNlZ21lbnRhY2nDs24gZGVsIG1lcmNhZG8gaW5tb2JpbGlhcmlvLiBBZGVtw6FzLCBsYSBkaXNwZXJzacOzbiBkZSBsb3MgcHJlY2lvcyBlbiBsYSB6b25hIE9lc3RlIHN1Z2llcmUgdW5hIG1heW9yIHZhcmlhYmlsaWRhZCBlbiBsb3MgdmFsb3JlcyBkZSBsb3MgaW5tdWVibGVzIGRlbnRybyBkZSBlc3RhIMOhcmVhLg0KDQojIyBSRVNVTFRBRE9TDQoNCiMjIyAxLiBEaXN0cmlidWNpw7NuIGRlIFByZWNpb3MNCg0KIyMjIyBFbCBhbsOhbGlzaXMgZGUgbGEgZGlzdHJpYnVjacOzbiBkZSBwcmVjaW9zIG11ZXN0cmEgcXVlIGxhIG1heW9yw61hIGRlIGxhcyB2aXZpZW5kYXMgdGllbmVuIHByZWNpb3MgY29uY2VudHJhZG9zIGVuIHJhbmdvcyBiYWpvcyBhIG1lZGlvcywgY29uIHVuYSBkaXNtaW51Y2nDs24gcHJvZ3Jlc2l2YSBlbiBsYSBmcmVjdWVuY2lhIGEgbWVkaWRhIHF1ZSBlbCBwcmVjaW8gYXVtZW50YS4gRXN0byBzdWdpZXJlIHF1ZSBlbCBtZXJjYWRvIGlubW9iaWxpYXJpbyBlc3TDoSBkb21pbmFkbyBwb3IgcHJvcGllZGFkZXMgZWNvbsOzbWljYXMgeSBkZSBjb3N0byBtZWRpbywgY29uIHVuYSBtZW5vciByZXByZXNlbnRhY2nDs24gZGUgdml2aWVuZGFzIGRlIGx1am8uDQoNCiMjIyMgR3LDoWZpY286IEhpc3RvZ3JhbWEgZGUgcHJlY2lvcyBkZSB2aXZpZW5kYSBtb3N0cmFuZG8gbGEgZGlzdHJpYnVjacOzbiBkZSBmcmVjdWVuY2lhLg0KDQojIyMgMi4gU2VnbWVudGFjacOzbiBwb3IgWm9uYXMgeSBFc3RyYXRvcw0KDQojIyMjIEVsIGFuw6FsaXNpcyBwb3Igem9uYXMgcmV2ZWxhIHF1ZSBsYSAiWm9uYSBTdXIiIGNvbmNlbnRyYSBlbCBtYXlvciBuw7ptZXJvIGRlIHByb3BpZWRhZGVzLCBtaWVudHJhcyBxdWUgIlpvbmEgT3JpZW50ZSIgdGllbmUgbGEgbWVub3IgY2FudGlkYWQuIEVuIHTDqXJtaW5vcyBkZSBlc3RyYXRvIHNvY2lvZWNvbsOzbWljbywgbGEgbWF5b3IgcGFydGUgZGUgbGFzIHZpdmllbmRhcyBwZXJ0ZW5lY2VuIGEgbG9zIGVzdHJhdG9zIDQgeSA1LCBpbmRpY2FuZG8gdW4gbWVyY2FkbyBpbm1vYmlsaWFyaW8gZGlyaWdpZG8gcHJpbmNpcGFsbWVudGUgYSBsYSBjbGFzZSBtZWRpYS1hbHRhLg0KDQojIyMjIEdyw6FmaWNvOiBHcsOhZmljb3MgZGUgYmFycmFzIGNvbXBhcmFuZG8gbGEgZGlzdHJpYnVjacOzbiBkZSB2aXZpZW5kYXMgcG9yIHpvbmEgeSBlc3RyYXRvLg0KDQojIyMgMy4gUmVsYWNpw7NuIGVudHJlIFRpcG8gZGUgVml2aWVuZGEgeSBQcmVjaW8NCg0KIyMjIyBTZSBvYnNlcnZhIHF1ZSBsb3MgYXBhcnRhbWVudG9zIHRpZW5lbiBtYXlvciByZXByZXNlbnRhY2nDs24gZW4gZWwgbWVyY2FkbyBlbiBjb21wYXJhY2nDs24gY29uIGxhcyBjYXNhcy4gQWRlbcOhcywgbG9zIHByZWNpb3MgbcOhcyBiYWpvcyB0aWVuZGVuIGEgY29uY2VudHJhcnNlIGVuIGFwYXJ0YW1lbnRvcywgbWllbnRyYXMgcXVlIGxhcyBjYXNhcyB0aWVuZGVuIGEgdWJpY2Fyc2UgZW4gc2VnbWVudG9zIGRlIHByZWNpb3MgbcOhcyBhbHRvcy4NCg0KIyMjIyBHcsOhZmljbzogR3LDoWZpY28gZGUgYmFycmFzIHF1ZSBjb21wYXJhIGxhIGNhbnRpZGFkIGRlIGFwYXJ0YW1lbnRvcyB5IGNhc2FzLg0KDQojIyMgNC4gQW7DoWxpc2lzIGRlIENvcnJlc3BvbmRlbmNpYQ0KDQojIyMjIExhIGNvcnJlc3BvbmRlbmNpYSBlbnRyZSB6b25hcyB5IHByZWNpb3MgbXVlc3RyYSBxdWUgbGFzIHZpdmllbmRhcyBkZSBtZW5vciBjb3N0byBzZSBjb25jZW50cmFuIGVuIGNpZXJ0YXMgem9uYXMgZXNwZWPDrWZpY2FzLCBtaWVudHJhcyBxdWUgbGFzIHByb3BpZWRhZGVzIG3DoXMgY29zdG9zYXMgc2UgZGlzdHJpYnV5ZW4gZW4gdWJpY2FjaW9uZXMgbcOhcyBleGNsdXNpdmFzLiBFc3RhIGluZm9ybWFjacOzbiBlcyBjbGF2ZSBwYXJhIGxhIHRvbWEgZGUgZGVjaXNpb25lcyBlbiBlc3RyYXRlZ2lhcyBkZSBjb21lcmNpYWxpemFjacOzbi4NCg0KIyMjIyBHcsOhZmljbzogTWFwYSBkZSBjb3JyZXNwb25kZW5jaWFzIGVudHJlIHpvbmFzIHkgcmFuZ29zIGRlIHByZWNpb3MuDQoNCiMjIyA1LiBBbsOhbGlzaXMgR2VvZXNwYWNpYWwNCg0KIyMjIyBTaSBzZSBjb25zaWRlcmFuIGRhdG9zIGdlb2VzcGFjaWFsZXMgY29tbyBsYXRpdHVkIHkgbG9uZ2l0dWQsIHNlIHB1ZWRlbiB2aXN1YWxpemFyIHBhdHJvbmVzIGVzcGVjw61maWNvcyBkZSBkaXN0cmlidWNpw7NuIGlubW9iaWxpYXJpYSBlbiB1biBtYXBhLiBFc3RvIGF5dWRhIGEgaWRlbnRpZmljYXIgw6FyZWFzIGRlIGFsdGEgeSBiYWphIGRlbWFuZGEsIGZhY2lsaXRhbmRvIGxhIHRvbWEgZGUgZGVjaXNpb25lcyBlc3RyYXTDqWdpY2FzLg0KDQojIyMjIEdyw6FmaWNvOiBNYXBhIGRlIGNhbG9yIG1vc3RyYW5kbyBsYSBkaXN0cmlidWNpw7NuIGdlb2dyw6FmaWNhIGRlIHByZWNpb3MgZGUgdml2aWVuZGEuDQoNCiMjIyBDb25jbHVzacOzbiBHZW5lcmFsDQoNCiMjIyMgRWwgZXN0dWRpbyBpbm1vYmlsaWFyaW8gcmV2ZWxhIHVuYSBkaXN0cmlidWNpw7NuIGRlc2lndWFsIGRlIHByb3BpZWRhZGVzLCBjb24gdW5hIG1heW9yIGNvbmNlbnRyYWNpw7NuIGRlIHZpdmllbmRhcyBlbiB6b25hcyBlc3BlY8OtZmljYXMgeSB1biBtZXJjYWRvIGRvbWluYWRvIHBvciBhcGFydGFtZW50b3MgYSBwcmVjaW9zIGJham9zIHkgbWVkaW9zLiBFbCBhbsOhbGlzaXMgZ2VvZXNwYWNpYWwgeSBkZSBjb3JyZXNwb25kZW5jaWEgYnJpbmRhIGluZm9ybWFjacOzbiB2YWxpb3NhIHBhcmEgbGEgcGxhbmVhY2nDs24geSBjb21lcmNpYWxpemFjacOzbiBlZmVjdGl2YSBlbiBlbCBzZWN0b3IgaW5tb2JpbGlhcmlvLg0K