Resumen Ejecutivo

Introducción

El mercado de Bienes Raíces ha crecido significativamente en los últimos años en la ciudad de Cali. Para el año 2022 las ventas de inmuebles alcanzaron los $6.700 millones de pesos y para el año 2023 las ventas fueron de $6.100 millones. Buscando aprovechar este crecimiento, se pretende, a partir de un conjunto de datos de los inmuebles en venta en la ciudad, brindar información basada en la estadística que sirva como base para la toma de decisiones estratégicas que orienten a Bienes y Casas (B&C) para aprovechar este crecimiento del sector.

El informe estadístico proporcionará información sobre:

  • Caracterización de los precios de las viviendas en diferentes zonas de la ciudad
  • El tipo de vivienda más ofertada en Cali
  • Características más relevantes de la oferta de vivienda en Cali

Metodología

Para llegar a los resultados e este análisis descriptivo se siguieron los siguientes pasos:

  • Carga y revisión general de la información
  • Ordenamiento y limpieza del conjunto de datos
  • Transformación del conjunto de datos y visualización
  • Presentación de los Resultados y Conclusiones

Resumen de Resultados

  • Zonas y tipos de Inmuebles con mejores precios

Como se puede ver en la gráfica, la zona con mejores precios es la zona Oeste, seguida por la Sur y la norte. En cuanto al tipo de inmueble, las casas presentan mejores promedios que los apartamentos en todas las zonas, y en general, los tipos y zonas mejores clasificados en cuanto al valor, son, en este orden: Casas en el Oeste, Apartamentos en el Oeste, Casas en el Sur, Casas en el Norte.

  • Tipo de inmueble más ofertado

Los apartamentos son el tipo de inmueble con mayor cantidad de ofertas en la ciudad de Cali superando en cantidad a las casas en la zona Norte, Oeste y Sur. En las zonas Centro y Oriente, hay más casas ofertadas, en una proporción aproximada de 6 a 1.

##          Apartamentos Casas
## Cantidad         3704  3166
  • Mejor tipo de Vivienda

Aunque hay más apartamentos que casas, las casas presentan mayores valores en su precio, lo que las hace más atractivas. Las zonas organizadas por su promedio de venta son: la Oeste, la Sur, la Norte, la Centro y la Oriente.

Sugerencias a modo de Conclusiones

El conjunto de datos tiene muchas irregularidades. Esto, no solo alarga el proceso de procesamiento de la información, sino que también siembre una duda sobre los resultados obtenidos. Para una siguiente opotunidad, se sugiere conseguir datos de las ventas efectivas realizadas en la ciudad de Cali, de donde se pueden sacar datos concretos de precios de venta y características de las viviendas, como su ubicación y otros datos que están probablemente ya verificados o con mejor calidad.

Por otro lado, se sugiere que en el proceso de entendimiento y procesamiento de los datos, esté vinculado alguien de la empresa, pues esto haría que las decisiones que se tomaran sobre los datos pudieran tener más sentido desde el punto de vista estratégico y de conocimiento de negocio.

También, es positivo para el análisis que se conozcan detalles sobre la operación de la empresa, tales como volumen de ventas, cantidad de agentes inmobiliarios, utilidades anteriores, y si hay metas ya planteadas para los periodos futuros. Esto facilitaría el trabajo conjunto y aumentaría las probabilidades de éxito del proyecto. importante hacerlo.

Se presenta a continuación todo el proceso de análisis que se llevó a cabo para la Inmobiliaria B&C.


1. Introducción

Para los próximos años, se espera que el mercado inmobiliario en la Ciudad de Cali siga subiendo como en años anteriores, brindando oportunidades para los actores que logren identificar las características más relevantes de su comportamiento. Para aprovechar esta oportunidad, se entrega el presente informe a la junta directiva de la agencia inmobiliaria B&C. En este informe se explica de manera general el proceso de ordenamiento y limpieza de datos, y se presenta un análisis descriptivo de los datos resultantes. Para esto, después de importar el conjunto de datos, y de realizar su limpieza, fusionando, eliminando, normalizando, estandarizando o imputando datos, según fuese necesario, se realizó un análisis de los datos para presentarlos en distintos gráficos y tablas que permitirán entender mejor las características del conjunto.

Posteriormente, se presentarán los resultados de dicho análisis y se realizará una discusión sobre los descubrimientos y dificultades encontradas en los datos, para finalmente, entregar las conclusiones de todo el ejercicio. Como anexo, se podrá ver todo el codigo ejecutado en todas las partes del proceso.

A continuación, se presentan los objetivos que se buscaron con la realización de este estudio.


2. Objetivos

La inmobiliaria B&C desea tomar decisiones importantes sobre su negocio, tales como definir un nicho de mercado, desarrollar la estrategia de marketing, establecer precios de ventas y ofrecer servicios personalizados a sus clientes. Para poder lograr esto, el presente proyecto ha definido los siguientes objetivos:

  • Analizar la información del conjunto de datos de la venta de viviendas en la ciudad de Cali
  • Depurar el conjunto de datos para su posterior utilización
  • Realizar un análisis descriptivo de los datos
  • Proporcionar información sobre:
    • Precio de las viviendas en diferentes zonas de Cali
    • Tipo de viviendas más ofertadas
    • Características más relevantes de la oferta de vivienda en Cali

3. Métodos

3.1. Análisis inicial

Luego de importar los paquetes requeridos y de cargar la librería y los datos con los que vamos a trabajar, se dio una primera mirada al conjunto de datos.

Podemos observar que hay variables como id, zona, piso, estrato, preciom, areaconst, parquea, banios, habitac, tipo, barrio, latitud y longitud. Cada línea proporciona información sobre un inmueble en particular. Ahora veamos cuantos datos faltantes hay en el dataset.

3.2. Limpieza de datos

3.2.1. Eliminación de registros vacíos

Eliminemos los registros con datos faltantes en la columna id, y volvamos a revisar los datos faltantes del conjunto de datos.

df <- filter(df,!is.na(df$id)) 
df
missing_data <- colSums(is.na(df)) %>%
                 as.data.frame() 

missing_data 

La columna id no aporta información valiosa al estudio, así que la eliminaremos. De igual forma, las variables longitud y latitud no se hacen relevantes para este estudio, dado que se trata de inmuebles en una sola ciudad y que además se tiene la variable del barrio y de la zona en el conjunto de datos. Tampoco se va a hacer una visualización de la distribución de las casas en un mapa, aunque para un análisis de otro tipo, esto si podría ser relevante. Estas también se eliminarán del conjunto.

df$latitud <- NULL
df$longitud <- NULL
df$id <- NULL
df

3.2.2. Análisis de columnas con datos faltantes

Vemos que ahora en las únicas variables en las que faltan datos son piso y parquea. Veamos qué características tienen esas variables, primero lo hacemos para piso

summary(df$piso)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   1.000   2.000   3.000   3.772   5.000  12.000    2638
table(df$piso)
## 
##    1    2    3    4    5    6    7    8    9   10   11   12 
##  861 1450 1097  607  568  245  207  211  146  130   84   83

Podemos observar algunas cosas importantes. Lo primero es que hay 2638 registros sin dato en la columna piso. Lo segundo, que el menor valor es 1 y el mayor es 12, con un buen número de registros con valores altos. Por el nombre de la variable no sabemos si el valor corresponde al número del piso en el que queda el inmueble en un edificio, o el número de pisos que tiene el inmueble. Si fuera lo segundo, querría decir que hay inmuebles que tienen 12 pisos, lo que tendría sentido si fueran edificios. Si fuera lo primero, significa que hay inmuebles en el doceavo piso de un edificio, al igual que en el décimo, el noveno, y así sucesivamente, Lo que tiene mucho más sentido, dado lo extremadamente raro que sería que una casa o un apartamento tuviera 12 pisos. Para tratar de entender a que se refiere, vamos a ver primero a que tipo de inmueble corresponden los registros que tienen un número alto.

pisona <- subset(df, is.na(df$piso)) #subset pisona contains the records without value in column piso
table(pisona$tipo)
## 
## Apartamento APARTAMENTO        apto        casa        Casa        CASA 
##        1354          25           4           7        1243           5

Pero antes, vemos que los registros corresponden tanto a casas como a apartamentos, y que hay diferencia en la escritura de los valores que corresponden a un mismo tipo de inmueble. También vemos que no hay edificios, luego no tendría sentido la segunda hipótesis de que la variable piso se refiere al número de pisos del inmueble. Se trata por lo tanto del piso en el que se ubica el inmueble. A continuación, voy a homogenizar los nombres de los tipos de inmueble en Apartamento y Casa solamente. En el caso de los valores apto, tendré que reemplazarlos por Apartamento.

df$tipo <- tolower(df$tipo)
table(df$tipo)
## 
## apartamento        apto        casa 
##        5093          13        3221
df$tipo <- ifelse(df$tipo == "apto", "Apartamento", ifelse(df$tipo == "apartamento", "Apartamento", ifelse(df$tipo == "casa",  "Casa", df$tipo)))
table(df$tipo)
## 
## Apartamento        Casa 
##        5106        3221

Ahora veamos nuevamente a que tipo de inmueble corresponden los registros sin piso:

pisona <- subset(df, is.na(df$piso)) #subset pisona contains the records without value in column piso
table(pisona$tipo)
## 
## Apartamento        Casa 
##        1383        1255

Se puede observar que hay suficientes registros sin valor en la variable piso (+30%). Esto puede tener sentido para las casas, por su naturaleza, pues ellas no “están” en ningún piso, al menos diferente al 1ro, pero eso no se menciona de esta manera. Lo común es que un apartamento si tenga un piso en donde esté ubicado dentro de un edificio, aunque existen apartamentos en casas que se subdividen, los cuales están por lo general en el primer piso (piso = 1) Ahora veamos la cantidad de registros con piso según su tipo:

withpiso <- subset(df, !is.na(df$piso)) #subset withpiso contains the records with value in column piso
table(withpiso$tipo)
## 
## Apartamento        Casa 
##        3723        1966

Como era de esperarse, esta cantidad está cerca al 70%. Ahora veamos como se cruza el Tipo con la los valores en la columna piso.

table(df$piso,df$tipo)
##     
##      Apartamento Casa
##   1          431  430
##   2          512  938
##   3          573  524
##   4          545   62
##   5          564    4
##   6          243    2
##   7          203    4
##   8          211    0
##   9          146    0
##   10         128    2
##   11          84    0
##   12          83    0

Ahora, retomando el análisis sobre el significado de la variable piso, si fuera el piso en el que se encuentra, tendría sentido para los Apartamentos, pero no para las casas. Si fuera la cantidad de pisos, tendría sentido para las Casas de 1, 2 y hasta 3 pisos, pues, aunque posible, existe muy poca probabilidad de casas de 10, 7, 6 y 5 pisos, e inclusive las de 4 pisos son muy escasas. Me atrevería entonces a decir que para los registros de tipo Apartamento, el valor entre 1 y 12 tiene sentido. Para los de tipo Casa, los valores altos, mayores o iguales a 4 no tienen sentido o son muy poco probables.

En estos casos entonces lo que haremos es modificar o completar la variable piso con el valor 1, para todas las casa con piso > 3 y dejaremos los de valor igual o menor que 3 como están, pues existe mayor probabilidad de que si existan. En cuanto a los Apartamentos sin valor en piso, los eliminaremos del conjunto de datos. En cuanto a los números altos de la variable piso en los registros de tipo Apartamento, no tenemos razón para dudar de ellos, luego los dejaremos como están.

Veamos como queda el dataset en estas dos variables después de hacer el cambio:

df$piso <- ifelse((df$piso > 3 | is.na(df$piso))  & df$tipo == "Casa", 1, df$piso)
df <- filter(df,!is.na(df$piso))
missing_data <- colSums(is.na(df)) %>%
                 as.data.frame() 

missing_data

Ahora, analicemos los valores de la variable parquea, que ofrece los valores de la cantidad de parqueaderos de un inmueble. Esta es la otra variable que tiene valores en NA.

table(df$parquea,df$estrato,df$tipo )
## , ,  = Apartamento
## 
##     
##        3   4   5   6
##   1  204 701 759  85
##   2    7 102 495 595
##   3    2   3  19 148
##   4    0   2  13  45
##   5    0   0   0   3
##   6    0   0   0   2
##   7    0   0   1   0
##   8    0   0   0   0
##   9    0   0   0   0
##   10   0   0   0   0
## 
## , ,  = Casa
## 
##     
##        3   4   5   6
##   1  277 317 235  28
##   2   79 198 390 225
##   3   17  47 106  98
##   4   10  21  84 181
##   5    1   4  27  32
##   6    3   4  13  46
##   7    0   2   4  11
##   8    0   0   3  14
##   9    0   1   1   2
##   10   1   1   0   4

Según esto, hay varios inmuebles que tienen desde 5 hasta 10 parqueaderos, valores que nos hacen dudar de su veracidad. Para ciertos tipos casas, es más posible que tengan muchos “lugares donde parquear” aunque técnicamente no sean parqueaderos cubiertos. Yo desconfiaría de los valores mayores de 4 inclusive para las casas. Vemos en las tablas que para los apartamentos, solo hay 6 que tienen valores mayores a 4. Se van a eliminar. En cuanto a las casas, hay muchos más registros con valores altos (parquea > 4). Para eliminar los valores atípicos, vamos a asignarles el valor de 4 a dichos registros. En cuanto a los que no tienen dato, vamos a asumir que no tienen parqueadero, por lo tanto les pondremos el valor de cero.

df$parquea <- ifelse(df$parquea > 4, 4,  df$parquea)
df$parquea <- ifelse(is.na(df$parquea), 0, df$parquea)
table(df$parquea,df$estrato,df$tipo )
## , ,  = Apartamento
## 
##    
##       3   4   5   6
##   0 228 248  42  19
##   1 204 701 759  85
##   2   7 102 495 595
##   3   2   3  19 148
##   4   0   2  14  50
## 
## , ,  = Casa
## 
##    
##       3   4   5   6
##   0 426 132 121  55
##   1 277 317 235  28
##   2  79 198 390 225
##   3  17  47 106  98
##   4  15  33 132 290
sum(is.na(df$parquea))
## [1] 0

Ahora veamos si el conjunto tiene datos faltantes.

VIM::aggr(df, cex.axis = 0.5, cex.lab= 0.8) 

Se puede verificar que ya no tiene datos faltantes en las variables.

3.2.3. Análisis y limpieza de registros con valores atípicos

Habiendo eliminado del dataset todos los registros con datos vacíos, ahora vamos a analizar las otras variables del conjunto. Visualizaremos en gráficos de cajas y bigotes la distribución de las variables numéricas.

numeric_columns <- names(df)[sapply(df, is.numeric)]
no_columns <- c("piso","estrato","parquea")
numeric_columns <- setdiff(numeric_columns, no_columns)
lapply(numeric_columns, function(variable) {
  ggplot(df, aes_string(x = variable)) +
    geom_boxplot() +
    labs(title = paste0("Boxplot para la columna: ", variable))
})
## [[1]]

## 
## [[2]]

## 
## [[3]]

## 
## [[4]]

Podemos ver que las variables preciom y areaconst tienen una gran cantidad de valores atípicos, y también que según los datos, hay inmuebles con 8, 9 y 10 baños, así como también con 0 habitaciones o con hasta 10 habitaciones. En cuanto a las variables longitud y latitud, se recuerda que estas fueron eliminadas del conjunto de datos, pues al parecer había errores en los datos, pues su distribución, al ser los datos de inmuebles en una misma ciudad, deberían ser muy similares y no con diferencias tan grandes entre sus valores.

Vamos entonces a revisar si los valores de estas variables para esos registros son coherentes, por ejemplo, las casas con muchos baños o muchas habitaciones deberían ser las casas con un área construida mayor y también con más altos precios.

Antes de profundizar en el análisis, eliminaremos los registros con datos no lógicos, como areaconst = 0, habitac = 0 o baños = 0.

df <- filter(df, df$banios != 0)
df <- filter(df, df$habitac != 0)
df <- filter(df, df$areaconst != 0)
numeric_columns <- names(df)[sapply(df, is.numeric)]
exclude_columns <- c("piso","estrato","parquea") #,"longitud", "latitud")
numeric_columns <- setdiff(numeric_columns, exclude_columns)
cov_matrix <- cov(df[, numeric_columns])
atipicos <- mahalanobis(df[, numeric_columns], center = TRUE, cov = cov_matrix)
length(atipicos)
## [1] 6875

Veamos la relación entre las variables preciom, banios, areaconst y habitac. Se espera que entre más área construida, el valor sea más alto, o que entre más habitaciones existan, hayan más baños, y de igual manera, que entre más habitaciones y baños, más área construida tenga, al igual que mayor sea el precio. Comportamientos diferentes a estos, si bien pueden ser posibles en la práctica, son poco probables y alteran la homogeneidad de los datos. Para este estudio, si son pocos estos valores atípicos, se eliminarán.

Se representarán gráficamente las distancias de Mahalanobis, que es una medida de la distancia entre un punto y una distribución multivariante. Es una medida útil para detectar valores atípicos en un conjunto de datos multidimensional. La distancia es una medida de la distancia en unidades de desviaciones estándar, por lo tanto, un valor alto de la distancia indica que el punto esta lejos de la distribución multivariante. Típicamente, los puntos con una distancia mayor a 3 se consideran atípicos. La distancia Mahalanobis no se afecta por la escala de las variables y es sensible a la correlación entre las variables.

#ggplot(df, aes_string(x = "preciom", y = "areaconst", color = "atipicos")) +
#  geom_point() +
#  scale_color_continuous(low = "white", high = "blue") +
#  labs(x = "Precio", y = "Área construida", color = "Distancia de Mahalanobis")

ggplot(df, aes_string(x = 'preciom', y = 'areaconst', color = 'atipicos')) +
  geom_point() +
  scale_color_continuous(low = "white", high = "blue") +
  labs(x = "Precio", y = "Area construida", color = "Distancia de Mahalanobis")

En el gráfico anterior se pueden ver algunos datos que no son lógicos pues se asume una relación directamente proporcional entre el precio y el área construida de una casa. Por ejemplo, hay un registro de 1750 metros cuadrados construidos con un valor de 250 millones. Se esperaría que para un área tan grande, el precio estuviera entre los más altos y por el contrario está entre los más bajos. También se ve el caso contrario, en el que el precio es muy alto para tan poca área construida. Aunque no se están teniendo en cuenta otras variables, como por ejemplo el estrato o el barrio, siempre hay una relación directa entre el tamaño y el valor que debe considerarse. En un estudio más detallado se podrían tener en cuenta los cruces entre estas cuatro variables mencionadas, o inclusive también con la cantidad de baños y de habitaciones.

ggplot(df, aes_string(x = "banios", y = "areaconst", color = "atipicos")) +
  geom_point() +
  scale_color_continuous(low = "white", high = "blue") +
  labs(x = "Baños", y = "Área construida", color = "Distancia de Mahalanobis")

Se observa que hay unos registros con mucha área construida y pocos baños, como es el caso del registro que indica 1750 metros construidos y 3 baños. Se elminará este registro.

df <- filter(df, df$areaconst != 1750)

Veamos la relación entre la cantidad de habitaciones y la cantidad de baños. Se espera que entre más habitaciones, más baños haya en el inmueble.

ggplot(df, aes_string(x = "habitac", y = "banios", color = "atipicos")) +
  geom_point() +
  scale_color_continuous(low = "white", high = "blue") +
  labs(x = "Habitaciones", y = "Baños", color = "Distancia de Mahalanobis")

ggplot(df, aes_string(x = "habitac", y = "areaconst", color = "atipicos")) +
  geom_point() +
  scale_color_continuous(low = "white", high = "blue") +
  labs(x = "Habitaciones", y = "Area", color = "Distancia de Mahalanobis")

Aparece un caso donde hay 3 habitaciones y 10 baños. También, en el gráfico anterior, inmuebles con 10 baños y menos de 400 metros de área construida. Estos se eliminarán.

df <- filter(df, !(df$banios == 10 & df$areaconst <= 400))
table(df$banios,df$habitac)
##     
##         1    2    3    4    5    6    7    8    9   10
##   1    20   98  225   20    5    1    2    0    0    0
##   2    18  503 1509  163   56   23   10    5    1    0
##   3     4   78  889  460  105   55   34   24   14    3
##   4     0   15  379  510  188   78   36   38   12   10
##   5     0    3  138  312  176   68   42   34   22   11
##   6     1    0   14   90   82   57   25   18    9    7
##   7     0    0    2    6   42   24   14    6    7    4
##   8     0    0    0    2    3    9    8    9    9    6
##   9     0    0    0    0    1    0    1    4    7    2
##   10    0    0    0    0    0    0    0    0    1    3

De igual manera, se observa una aparente disparidad entre la cantidad de baños y el área construida. Aunque es posible que haya pocos baños en una casa grande, esto es poco probable. Tal vez una mayor relación la tienen las variables que representan las cantidades de baños y de habitaciones, pues las habitaciones dan una idea de la cantidad de personas que viven o usan la casa, lo cual muestra la necesidad de más o menos baños.

En un gráfico anterior se ve también que hay casas de 0 metros construidos con varias habitaciones, lo cual no es posible. Estos registros se eliminarán. Y también hay registros de inmuebles en el conjunto con muchos más baños que habitaciones, en una proporción de 2 a 1 e inclusive de 3 a 1. Eliminaremos estos registros problemáticos dado que no es mucha la cantidad de ellos.

3.2.4. Homogenización de variables cualitativas

Se revisaron los valores de las variables barrio y zona. Se notó que los nombres de las zonas están todos bien escritos, pero que en los nombres de los barrios hay algunos registros que se refieren al mismo barrio pero que están escritos de manera diferente, como por ejemplo: “alfonso lopez” y “alfonzo López”. También se nota que hay muchos barrios donde solo hay un inmueble a la venta. Con tan baja representatividad, no es posible hacer inferencias en cuanto a la situación de los inmuebles en los barrios. Habría que usar la zona que al ser solo 5, tienen más inmuebles en ellas.

Corregimos los nombres de algunos de los barrios para ver sus efectos en el dataset, sin embargo, se nota que sigue habiendo muchos barrios con tan solo un inmueble y que además son alrededor de 350 y algunos están posiblemente mal referenciados, como el que dice “cali” o el que hace referencia al nombre de un edificio. También se ve que están referenciadas las zonas en los barrios. En definitiva, esta variable requeriría de mucha limpieza e investigación para ser depurada, y teniendo también errores en la longitud y latitud, no se puede imputar a partir de los datos existentes.

unique(df$zona)
## [1] "Zona Oeste"   "Zona Sur"     "Zona Norte"   "Zona Centro"  "Zona Oriente"
df$barrio <- tolower(df$barrio)
barrios = unique(df$barrio, decreasing = TRUE)
#table(df$barrio, sort = TRUE)
#barrios

df$barrio <- ifelse(df$barrio == "alf√©rez real", "alferez real", ifelse(df$barrio == "alfonso lópez", "alfonso lopez", ifelse(df$barrio == "base a√©rea",  "base aerea", ifelse(df$barrio == "mel√©ndez",  "melendez", ifelse(df$barrio == "mel√©ndez",  "melendez", ifelse(df$barrio == "mel√©ndez",  "melendez", ifelse(df$barrio == "la arboleda",  "arboleda", ifelse(df$barrio == "los alcázares",  "los alcazares", ifelse(df$barrio == "la rivera i",  "la riverita", ifelse(df$barrio == "laflora",  "la flora", ifelse(df$barrio == "la rivera ii",  "la riverita", ifelse(df$barrio == "la rivera",  "la riverita", ifelse(df$barrio == "ciudadela paso ancho",  "ciudadela pasoancho", ifelse(df$barrio == "caney especial",  "caney", ifelse(df$barrio == "el ingenio i",  "ingenio", ifelse(df$barrio == "el ingenio ii",  "ingenio", ifelse(df$barrio == "el ingenio",  "ingenio", ifelse(df$barrio == "el ingenio iii",  "el ingenio", ifelse(df$barrio == "jamundi alfaguara",  "alfaguara", ifelse(df$barrio == "cali canto viii",  "calicanto", ifelse(df$barrio == "cali canto",  "calicanto", ifelse(df$barrio == "chiminangos 1 etapa",  "chiminangos", ifelse(df$barrio == "chiminangos 2 etapa",  "chiminangos", ifelse(df$barrio == "cristóbal colón",  "cristobal colón", ifelse(df$barrio == "marroquin iii",  "marroquin", ifelse(df$barrio == "el ingenio 3",  "el ingenio", df$barrio))))))))))))))))))))))))))

table(df$barrio)
## 
##                   20 de julio                    3 de julio 
##                             3                             1 
##                         acopi                   agua blanca 
##                            75                             1 
##                    aguablanca                     aguacatal 
##                             2                            76 
##                       alameda               alameda del río 
##                            13                             1 
##                        alamos                      alborada 
##                             7                             1 
##                     alfaguara                  alferez real 
##                             1                             4 
##                 alfonso lopez               alfonso lópez i 
##                            21                             1 
##                   alto jordán            altos de guadalupe 
##                             1                             4 
##                altos de menga                antonio nariño 
##                             3                             2 
##                      aranjuez                      arboleda 
##                            15                             9 
## arboleda campestre candelaria                     arboledas 
##                             1                            31 
##             atanasio girardot                 autopista sur 
##                             9                             1 
##                  barranquilla             barrio 7de agosto 
##                             5                             1 
##            barrio eucarístico                 barrio obrero 
##                             1                             1 
##            barrio tranquilo y                    base aerea 
##                             1                             2 
##                    belalcazar             belisario caicedo 
##                             4                             2 
##                   bella suiza              bella suiza alta 
##                            17                             2 
##                    bellavista              benjamín herrera 
##                            28                             8 
##                        berlin           bloques del limonar 
##                             1                             1 
##                     bochalema           bosques del limonar 
##                            12                            21 
##                        boyacá                       bretaña 
##                             1                            14 
##           brisas de guadalupe                 brisas de los 
##                             1                            61 
##            brisas del guabito            brisas del limonar 
##                             1                             1 
##                  buenos aires                        caldas 
##                             6                             1 
##                          cali                     calibella 
##                            13                             1 
##                     calicanto                calicanto viii 
##                             9                             1 
##                        calima                 calimio norte 
##                             6                             5 
##                       calipso                      cambulos 
##                             9                             3 
##                   camino real                         caney 
##                            31                            69 
##                   cañasgordas                  cañaveralejo 
##                             7                            11 
##                   cañaverales       cañaverales los samanes 
##                            20                             1 
##                         capri                      cascajal 
##                            47                             1 
##                        ceibas                    centenario 
##                             1                            10 
##                        centro               cerro cristales 
##                             3                            19 
##           cerros de guadalupe                    champagnat 
##                             1                            14 
##                     chapinero                   chiminangos 
##                             7                            12 
##                    chipichape                   ciudad 2000 
##                            23                            91 
##             ciudad antejardin              ciudad bochalema 
##                             1                            44 
##                  ciudad capri                ciudad cordoba 
##                            12                            20 
##                ciudad córdoba      ciudad córdoba reservado 
##                            14                             1 
##                ciudad country              ciudad del campo 
##                             1                             1 
##                 ciudad jardin                 ciudad jardín 
##                            14                           471 
##           ciudad jardin pance             ciudad los álamos 
##                             1                            22 
##                 ciudad modelo               ciudad pacifica 
##                             7                             1 
##                   ciudad real                ciudad talanga 
##                             3                             1 
##          ciudad universitaria            ciudadela comfandi 
##                             1                            17 
##             ciudadela del río           ciudadela pasoancho 
##                             1                            22 
##            colinas del bosque               colinas del sur 
##                             1                             5 
##                         colon                    colseguros 
##                             1                            39 
##              colseguros andes                     compartir 
##                             5                             1 
##                     cristales               cristobal colón 
##                            53                            15 
##               cuarto de legua                 departamental 
##                            37                            26 
##           ed benjamin herrera                     el bosque 
##                             1                            49 
##                      el caney                   el castillo 
##                           188                             6 
##                      el cedro                   el diamante 
##                             8                             2 
##                     el dorado               el gran limonar 
##                             5                             7 
##                     el guabal                    el guabito 
##                            18                             1 
##                    el ingenio                     el jardín 
##                            18                            13 
##                       el lido                    el limonar 
##                            52                           120 
##                   el nacional                    el paraíso 
##                             1                             3 
##                      el peñon                      el prado 
##                            40                             1 
##                    el refugio                      el rodeo 
##                            99                             1 
##                       el sena                    el trébol 
##                             1                             5 
##                    el troncal                    el vallado 
##                            16                             1 
##                   eucarístico               evaristo garcía 
##                             2                             1 
##          farrallones de pance               fenalco kennedy 
##                             1                             1 
##                       fepicol              flora industrial 
##                             1                             9 
##                      floralia                  fonaviemcali 
##                             5                             1 
##      francisco eladio ramirez                 fuentes de la 
##                             1                             1 
##                  gran limonar                       granada 
##                            24                            13 
##                     guadalupe                     guayaquil 
##                            19                            15 
##         hacienda alferez real                       ingenio 
##                             1                           210 
##                     ingenio i                    ingenio ii 
##                             1                             1 
##                       jamundi          jorge eliecer gaitán 
##                             4                             1 
##                  jorge isaacs                     juanamb√∫ 
##                             1                            35 
##                      juanambu                         junin 
##                             1                            18 
##                         junín                   la alborada 
##                             6                             2 
##                    la alianza                       la base 
##                             4                            15 
##                   la buitrera                    la campiña 
##                             3                            11 
##                    la cascada                     la ceibas 
##                             6                             1 
##                  la esmeralda                      la flora 
##                             1                           316 
##                   la floresta                  la fortaleza 
##                            18                             4 
##              la gran colombia                   la hacienda 
##                             1                           148 
##              la independencia                   la libertad 
##                            12                             2 
##                     la merced                     la morada 
##                            23                             1 
##                 la nueva base                      la playa 
##                             8                             1 
##                 la portada al                  la primavera 
##                             1                             1 
##                    la reforma                   la riverita 
##                             1                            15 
##                    la riviera                      la selva 
##                             1                            10 
##                  la villa del                   las acacias 
##                             1                            12 
##                 las américas                  las camelias 
##                             2                             1 
##                    las ceibas                  las delicias 
##                            21                             3 
##                   las granjas                las quintas de 
##                             9                             1 
##                     las vegas                  las vegas de 
##                             1                             1 
##                  libertadores                 los alcazares 
##                             3                            12 
##                     los andes                  los cambulos 
##                            21                            22 
##                  los cámbulos                 los cristales 
##                             5                           123 
##            los cristales club                los farallones 
##                             1                             4 
##                 los guaduales                los guayacanes 
##                            20                             2 
##                   los jockeys              los libertadores 
##                             1                             4 
##      los parques barranquilla                       lourdes 
##                             3                             2 
##                      mamellan                    manzanares 
##                             1                             5 
##                 marroquín iii             mayapan las vegas 
##                             1                            41 
##                      melendez                         menga 
##                            59                            18 
##       metropolitano del norte         miradol del aguacatal 
##                            14                             1 
##                    miraflores          morichal de comfandi 
##                            26                             3 
##                   multicentro                     municipal 
##                            23                             3 
##                       napoles                       nápoles 
##                             1                            26 
##                     normandia                     normandía 
##                             3                           106 
##                         norte                norte la flora 
##                             1                             1 
##                    nueva base                nueva floresta 
##                             1                            15 
##              nueva tequendama             oasis de comfandi 
##                            70                             4 
##                     occidente                        pacara 
##                             1                            14 
##                        pacará            palmas del ingenio 
##                             4                             1 
##                   pampa linda                    pampalinda 
##                            22                            10 
##                  panamericano                         pance 
##                             9                           357 
##           parcelaciones pance         parque residencial el 
##                            55                             1 
##                  paseo de los             paso del comercio 
##                             2                             5 
##                     pasoancho             poblado campestre 
##                             4                             2 
##                         ponce                       popular 
##                             1                             6 
##           portada de comfandi          portales de comfandi 
##                             2                             1 
##                      porvenir             prados de oriente 
##                             3                             6 
##            prados del limonar              prados del norte 
##                            21                           104 
##                prados del sur                     primavera 
##                             2                             2 
##               primero de mayo              primitivo crespo 
##                            32                             3 
##           puente del comercio                  puente palma 
##                             6                             1 
##                quintas de don            quintas de salomia 
##                            64                             4 
##            rafael uribe uribe          rep√∫blica de israel 
##                             1                             1 
##             rincón de salomia             riveras del valle 
##                             1                             1 
##                 rozo la torre              saavedra galindo 
##                             1                             3 
##                       salomia                       samanes 
##                            35                             1 
##          samanes de guadalupe                        sameco 
##                             1                             1 
##                   san antonio                     san bosco 
##                            21                             7 
##                    san carlos                  san cayetano 
##                             4                             9 
##                  san fernando            san fernando nuevo 
##                            47                             9 
##            san fernando viejo                   san joaquin 
##                            14                             3 
##                   san joaquín                san juan bosco 
##                            16                             7 
##                     san judas               san judas tadeo 
##                             1                             2 
##                      san luis                      san luís 
##                             2                             1 
##                   san nicolas                   san nicolás 
##                             1                             1 
##                     san pedro                   san vicente 
##                             1                            47 
##                   santa anita               santa anita sur 
##                            44                             1 
##                 santa bárbara                   santa elena 
##                             3                             9 
##                      santa fe               santa helena de 
##                             8                             1 
##                  santa isabel                  santa monica 
##                            55                            47 
##                  santa mónica            santa monica norte 
##                             3                             1 
##          santa monica popular          santa mónica popular 
##                             1                             6 
##      santa monica residencial      santa mónica residencial 
##                             5                            32 
##                    santa rita                santa teresita 
##                            40                           173 
##                       santafe                     santander 
##                             1                             1 
##                 santo domingo sector cañaveralejo guadalupe 
##                             6                             1 
##                     seminario          sierras de normandía 
##                            24                             1 
##               siete de agosto                 simón bolivar 
##                             8                             1 
##             tejares cristales                tejares de san 
##                             4                            13 
##                      templete                    tequendama 
##                             4                            40 
##                    tequendema               terrón colorado 
##                             1                             1 
##            torres de comfandi             unión de vivienda 
##                            41                             3 
##     urbanización barranquilla           urbanización boyacá 
##                             3                             1 
##       urbanización colseguros         urbanizacion el saman 
##                             3                             1 
##         urbanización la flora        urbanización la merced 
##                            59                             4 
##         urbanización la nueva     urbanización las cascadas 
##                             4                             1 
##             urbanizacion lili    urbanización nueva granada 
##                             2                             3 
##         urbanización río lili      urbanización san joaquin 
##                             5                             4 
##       urbanización tequendama                 valle de lili 
##                             5                             1 
##                valle del lili                  valle grande 
##                           817                             1 
##                     versalles                villa colombia 
##                            57                             6 
##             villa de veracruz                villa del lago 
##                             4                            10 
##               villa del prado                 villa del sol 
##                            50                            21 
##                 villa del sur            villas de veracruz 
##                             2                             9 
##                        vipasa                   zona centro 
##                            30                             1 
##                    zona norte                zona norte los 
##                            28                             1 
##                    zona oeste                  zona oriente 
##                            24                            17 
##                      zona sur 
##                            71

Veo que a pesar de que se han estandarizado algunos nombres, estos y otros siguen teniendo pocos inmuebles. Aunque en un análisis más profundo o diferente el barrio podría ser necesario, para esta ocasión, usaremos para cualquier análisis la variable zona con la siguiente distribución. El barrio se eliminará del dataset.

df$barrio <- NULL

3.2.5. Resumen de Variables y datos eliminados

Tal como hemos visto en el análisis, algunas de las variables no se utilizarán como parte del estudio. Estas variables son:

  • id
  • latitud
  • longitud
  • barrio

Las razones que se tuvieron en cuenta para su eliminación son:

  • Información improcedente para un análisis estadístico, como en el caso del id.
  • Información con muchos errores, valores atípicos o con distribuciones muy particulares que dan señal de estar equivocadas, como por ejemplo los valores en la latitud y la longitud.
  • Datos con muy poca representatividad en variables que segmentan los valores, como es el caso de la variable barrio, en donde había muchos barrios con solo un inmueble.
  • Variables completas que no aportan al objetivo del estudio (Definir su nicho, desarrollar estrategias de marketing, etc.) tal como se presenta en la descripción del trabajo.

También se eliminaron algunos registros con datos no lógicos, como los que tiene valores en cero para las variables área construida, habitaciones o baños, o casas de más 4 pisos, tal como se explicó durante el análisis.

3.3. Análisis descriptivo de los Datos

3.3.1. Precio de las Viviendas en diferentes zonas en Cali

Empecemos por ver los datos estadísticos de las variables

describe(df)

Se puede observar, entre otras cosas, lo siguiente:

  • La cantidad de registros es de 6870, lo que indica la gran cantidad de ofertas inmobiliarias que existen en la ciudad de Cali.
  • Solo hay viviendas del estrato 3 al 6
  • El precio más bajo de una vivienda es de 58 millones de pesos. El más alto es de 1.999 millones de pesos. Esta es la variable con mayor desviación estándar y rango.
  • El precio presenta una asimetría a la derecha, lo que quiere decir que es positiva, o que su valor es mayor que cero, y que muchos valores son altos.
  • Características similares tiene la variable que representa el Área Construida, pues tiene un rango cercano al del precio (1715) y una alta desviación estándar (149.86)
  • La media del precio de los inmuebles es de 441.6 millones. La Mediana es de 340 millones.
  • El área construida también tiene una asimetría positiva, es decir que los inmuebles con áreas grandes son más que sus contrarios.

Esta es la cantidad de inmuebles que hay por zona:

table(df$zona)
## 
##  Zona Centro   Zona Norte   Zona Oeste Zona Oriente     Zona Sur 
##          112         1481          868          329         4080

La zona con mayor cantidad de inmuebles es la zona sur, seguida por la zona norte, la oeste, la oriente y por último la centro. Veamos ahora la combinación de la zona y el tipo de inmueble.

table(df$zona,df$tipo)
##               
##                Apartamento Casa
##   Zona Centro           15   97
##   Zona Norte           781  700
##   Zona Oeste           704  164
##   Zona Oriente          46  283
##   Zona Sur            2158 1922

En las dos zonas donde más inmuebles hay (Sur y Norte), la cantidad de apartamentos es ligeramente mayor que la de las casas. En la zona Oeste es mucho mayor para apartamentos, y en las zonas centro y Oriente hay más casas que apartamentos. Veamos los promedios y la mediana de la variable precio para cada combinación de tipo y zona:

meds <- aggregate ( df$preciom ~ df$tipo + df$zona, data = df, FUN = function(x) c( round(as.numeric(mean(x)),2), round(as.numeric(median(x)),1), round(as.numeric(length(x)),0)))
meds <- data.frame(as.matrix(meds))
colnames(meds) <- c("Tipo","Zona","Media_Precio","Mediana_Precio","Cantidad")

meds$Media_Precio <- as.numeric(meds$Media_Precio)
meds$Mediana_Precio <- as.numeric(meds$Mediana_Precio)
meds$Cantidad <- as.numeric(meds$Cantidad)
meds
ggplot(meds, aes(x = Tipo, y = Cantidad, fill = Tipo)) +
  geom_bar(stat = "identity", show.legend = TRUE) +
  labs(x = "Tipo", y = "Cantidad") +
  theme(text = element_text(size  = 10),
        plot.margin = unit(c(0.5,0.5,0.5,0.5), "cm")) +
  facet_wrap(~Zona ) +
  geom_text(aes(label = Cantidad), size = 3, vjust = 0.2)

means <- aggregate (df$preciom ~ df$tipo + df$zona, data = df, FUN = function(x) c(round(as.numeric(mean(x)),2)))
means <- data.frame(as.matrix(means))
#means
colnames(means) <- c("Tipo","Zona","Media_Precio")

ggplot(means, aes(x = Tipo, y = Media_Precio, fill = Tipo, width = 0.7)) +
  geom_bar(stat = "identity", show.legend = TRUE) +
  labs(x = "Tipo", y = "Media Precio") +
  theme(text = element_text(size  = 10),
        plot.margin = unit(c(0.5,0.5,0.5,0.5), "cm")) +
  facet_wrap(~Zona ) +
  geom_text(aes(label = Media_Precio),size = 3,  vjust = 1)

medians <- aggregate (df$preciom ~ df$tipo + df$zona, data = df, FUN = function(x) c(round(as.numeric(median(x)),0)))
medians <- data.frame(as.matrix(medians))
#medians
colnames(medians) <- c("Tipo","Zona","Mediana_Precio")

ggplot(medians, aes(x = Tipo, y = Mediana_Precio, fill = Tipo, width = 0.7)) +
  geom_bar(stat = "identity", show.legend = TRUE) +
  labs(x = "Tipo", y = "Mediana Precio") +
  theme(text = element_text(size  = 10),
        plot.margin = unit(c(0.5,0.5,0.5,0.5), "cm")) +
  facet_wrap(~Zona ) +
  geom_text(aes(label = Mediana_Precio),size = 3,  vjust = 1)

Se puede ver en el primer gráfico que la cantidad de Casas y Apartamentos en la Zona Sur supera a todas las demás Zonas, seguida por la Zona Norte, la Zona Oeste, la Oriente y por último la Centro.

En cuanto al precio de venta, los gráficos que muestran la media y la mediana muestran que los inmuebles con el mayor precio están en la Zona Oeste, lo que, siendo una Zona con poca oferta, la hace muy atractiva, pues no hay tanta competencia y la posibilidad de mejores comisiones es más alta. Bajo este mismo criterio, le seguiría la Zona Norte y la Zona Sur. También las Casas en la Zona Centro. La Zona Oriente no parece ser muy atractiva porque hay pocos inmuebles y es poco su valor.

3.3.2. Tipo de viviendas más ofertadas en Cali

El tipo de vivienda más ofertada en Cali son los apartamentos.

table(df$tipo)
## 
## Apartamento        Casa 
##        3704        3166
types <- aggregate (df$preciom ~ df$tipo, data = df, FUN = function(x) c(round(as.numeric(length(x)),0)))
types <- data.frame(as.matrix(types))
colnames(types) <- c("Tipo","Cantidad")

ggplot(types, aes(x = Tipo, y = Cantidad, fill = Tipo)) +
  geom_bar(stat = "identity", show.legend = TRUE) +
  labs(x = "Tipo", y = "Cantidad") +
  geom_text(aes(label = Cantidad), vjust = -0.5) + 
  coord_polar()

De acuerdo a los gráficos anteriores en donde se muestra la cantidad de viviendas segmentado por zona y tipo, y el precio promedio también segmentado por zona y tipo, los 5 con mayor cantidad serían los siguientes:

  1. Apartamentos en Zona Sur
  2. Casas en Zona Sur
  3. Apartamentos en Zona Norte
  4. Apartamentos en Zona Oeste
  5. Casas en Zona Norte

En cuanto al precio de venta, estos son los 5 primeros promedios:

  1. Casas en Zona Oeste
  2. Apartamentos en Zona Oeste
  3. Casas en Zona Sur
  4. Casas en Zona Norte
  5. Casas en Zona Centro

Si se tiene en cuenta la Mediana, el orden sería el mismo de los promedios.

3.3.3. Características más relevantes de la oferta de vivienda en Cali.

Las viviendas en venta en Cali se encuentran distribuidas en toda la ciudad, siendo la de mayor cantidad la Zona Sur. Esto no ha de sorprender, pues es una de las zonas más grandes y de mayor movimiento en la ciudad para vivir por los atractivos que tiene, tales como variedad de opciones en vivienda (Edificios, conjuntos residenciales, condominios campestres, etc.), multiplicidad de opciones de lugares de comercio, existencia de parques, clubes, cercanía a zona de colegios y universidades, entre muchas otras ventajas.

Si bien el tipo de vivienda que más se oferta son los apartamentos, son las casas las que mejor promedio de precio tienen. Esto es lógico, porque normalmente son más grandes, luego es natural que sean más caras, sin embargo, en todas las zonas las casas tienen un promedio de precio más alto, y como las inmobiliarias ganan por comisión por el precio de venta, esto se hace muy relevante a la hora de escoger la estrategia y el nicho al que se le ofrecerán los inmuebles.

table(df$estrato,df$tipo)
##    
##     Apartamento Casa
##   3         440  793
##   4        1051  711
##   5        1318  972
##   6         895  690
table(df$estrato,df$zona)
##    
##     Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
##   3          99        445         43          320      326
##   4          11        297         71            7     1376
##   5           1        620        213            2     1454
##   6           1        119        541            0      924

Si analizamos la distribución del estrato por tipo y por zona, vemos que en el estrato 3, que es el más bajo, hay mayor cantidad de casas frente a la oferta de apartamentos, en una relación casi de 2:1 para las casas. Este fenómeno no se repite en ningún otro estrato, siendo la cantidad de apartamentos mayor a la de casas.

estratos <- aggregate (df$preciom ~ df$estrato, data = df, FUN = function(x) c(round(as.numeric(length(x)),0)))
estratos <- data.frame(as.matrix(estratos))
colnames(estratos) <- c("Estrato","Cantidad")

ggplot(estratos, aes(x = Estrato, y = Cantidad, fill = Estrato)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  labs(x = "Tipo", y = "Cantidad") +
  theme(text = element_text(size  = 10),
        plot.margin = unit(c(0.5,0.5,0.5,0.5), "cm")) +
  geom_text(aes(label = Cantidad), size = 3, vjust = -0.5) 

El Estrato 5 es el estrato con mayor cantidad de inmuebles a la venta, seguido por el 4, el 6 y el 3. En la Zona Sur, donde hay mayor cantidad de inmuebles, en el estrato en que más inmuebles hay es el 5, seguido del 4, después el 6 y cerrando el 3. Esto es coherente con la distribución de la ciudad en dicha zona.


4. Resultados

A partir del análisis descriptivo del conjunto de datos, se presentan los siguientes resultados del estudio, con el objetivo de brindar información relevante y suficiente para que la Junta Directiva de la Inmobiliaria B&C pueda decidir su nicho de mercado, desarrollar estrategias de marketing, establecer precios de venta y ofrecer servicios personalizados a sus clientes.

  • Zonas con mejor promedio de precios

La Zona Oeste presenta un mejor promedio de precios tanto para las casas como para los apartamentos, constituyéndose en una zona de mucho interés, dado que las inmobiliarias ganan por comisión, y entre mayor sea el valor de la propiedad, más dinero se ganará. La siguen la zona sur y la zona norte. El caso de la zona centro es particular, pues hay pocas casas, pero su promedio de precio no es el más bajito.

  • Tipo de inmueble más ofertado

Los apartamentos son el tipo de inmueble con mayor cantidad de ofertas en la ciudad de Cali superando en cantidad a las casas en la zona Norte, Oeste y Sur. En las zonas Centro y Oriente, hay más casas ofertadas, en una proporción aproximada de 6 a 1.

  • Mejor tipo de Vivienda

Aunque hay más apartamentos que casas, las casas presentan mayores valores en su precio, lo que las hace más atractivas. Las zonas con más alto promedio de venta son la Oeste, la Sur, a Norte, la Centro y la Oriente. Nótese que la Centro tiene pocas ofertas, pero sus casas tienen mejor promedio que las de la zona Oriente.

  • Estrato con mayor cantidad de inmuebles

El estrato 5 es el estrato con mayor cantidad de oferta de venta de inmuebles. Si bien, esto no es en si información contundente, si es una muestra de que las casas que más se comercializan son las de valores medio-altos, y esto puede dar un indicio de la clase de compradores que se deben buscar.

5. Discusión

Los objetivos planteados en esta investigación, que buscan ofrecer información relevante a la Inmobiliaria B&C para que tome decisiones estratégicas para su futuro se ven empeñados por la pobre calidad del conjunto de datos entregado. No solo el proceso de depuración, limpieza y normalización o estandarización de los datos se hace muy largo, sino que también se queda corto porque no es suficiente la información de la oferta de inmuebles en la ciudad, sino también información sobre las ventas, pues en aras de tomar decisiones estratégicas sobre nichos de mercado no es suficiente saber que hay muchos inmuebles en una zona especifica siendo ofertados, sino que sería más conveniente saber, por ejemplo, los datos reales de los precios de venta de las viviendas, o el tiempo que toma vender una casa o un apartamento en las zonas de la ciudad.

Desde el punto de vista estratégico, y para establecer servicios personalizados a sus clientes, hay mucha diferencia entre la cantidad de ofertas sean muy alta, a que la cantidad de ventas sea alta. Lo uno no lleva necesariamente a lo otros. De hecho, la cantidad de bienes ofertados en una zona, puedes ser una muestra de la dificultad que hay en venderlos, y por eso se “acumulan” sin venderse en el listado de ofertas.

De igual manera, hay variables en el conjunto de datos que pueden ser relevantes para ciertos objetivos y que tienen relación con los inmuebles que se ofertan, pero que pueden estar faltando para los bienes que efectivamente se venden. Esta dificultad de encontrar esos datos en la fuente de donde se extrajeron los datos, indica que tal vez sea mucho mejor buscar datos en otras fuentes más relevantes, por ejemplo, en vez de buscar los datos de las ofertas en internet, buscar los datos de las ventas efectivas en las notarías o en las oficinas de catastro o inclusive de la DIAN, pues estos “lugares” son los que reciben ese tipo de información, y si el objetivo es definir un plan estratégico para orientar a la compañía, es mucho mejor enfocarse en las ventas que SI se logran, que en las ofertas que no lo hacen.


6. Conclusiones

  • Se pudo ver que el conjunto de datos tiene muchas irregularidades, datos atípicos, valores nulos o que claramente parecen erróneos. Esto causa mucha dificultad en su procesamiento, pero sobre todo mina la confianza en el conjunto de datos. Si bien no hay como corroborar los datos de las variables en las que no sabemos a ciencia cierta si hay datos erróneos, la cantidad que si podemos determinar como erróneos es tan alta que nos hace desconfiar del conjunto. Por ejemplo, se puede constatar que hay errores en los valores de las variables latitud y longitud, pero no podemos saber si hay errores en la variable precio o área construida, salvo unos muy contados registros que pueden ser eliminados.

  • Lo anterior hace sospechar de los valores presentes en otras variables a las que no se les pueda comprobar que tienen valores equivocados no puedan ser confiables. De todos modos, al eliminar los registros con datos claramente erróneos, se está disminuyendo la probabilidad de error en los análisis y conclusiones.

  • Es muy importante trabajar con los datos de la mejor calidad posible, incluso si hay que sacrificar y disminuir la cantidad de datos presentes con los que se puede trabajar.

  • Para mantener la calidad de los datos, es necesario llevar a cabo una revisión de los mismos y una eliminación de los datos con valores claramente equivocados, como áreas iguales a 0, o viviendas sin habitaciones o baños.

  • Al ser los datos recogidos de publicaciones en internet, no se pueden corroborar ni mejorar sustancialmente, salvo en cuestiones contadas, como por ejemplo cruzando las coordenadas con el barrio. Sin embargo, el desorden de estas dos variables no indica que ese análisis sea importante hacerlo.


7. Anexos

Todo este documento y código esta disponible Aquí

Consigna de la Actividad 1

La empresa B&C (Bienes y Casas) es una agencia de bienes raíces que opera en la ciudad de Cali, Colombia. La empresa fue fundada por Sandra Milena hace 10 años y actualmente cuenta con ocho agentes de bienes raíces.

El mercado de bienes raíces en Cali ha crecido significativamente en los últimos años, impulsado por el crecimiento de la población, la inversión extranjera directa y el desarrollo de nuevos proyectos inmobiliarios. En 2022, las ventas del sector en Cali llegaron a $6700 millones y en 2023 a $6100 mil millones. Se espera que este sector continue creciendo durante los próximos años, permitiendo un desarrollo dinámico en la economía regional.

La empresa B&C ha recogido información sobre viviendas que incluye información sobre el precio, la ubicación, las características y la venta de viviendas en Cali. Esta base de datos puede ser utilizada para realizar un informe estadístico que sería de gran interés para la empresa.

El informe estadístico podría proporcionar información sobre los siguientes temas:

  • Precio de las viviendas en diferentes zonas de Cali.
  • Tipo de viviendas más ofertadas en Cali.
  • Características más relevantes de la oferta de vivienda en Cali.

Esta información sería útil para la empresa B&C para tomar decisiones sobre su negocio, tales como:

  • Definir su nicho de mercado.
  • Desarrollar estrategias de marketing.
  • Establecer precios de venta.
  • Ofrecer servicios personalizados a sus clientes.

La empresa solicita un análisis descriptivo de los datos, para identificar las tendencias y patrones en los datos.

El informe debe incluir los siguientes elementos:

  1. Introducción
  2. Objetivos
  3. Métodos
  4. Resultados
  5. Discusión
  6. Conclusiones
  7. Anexos

El informe debe ser redactado en un lenguaje claro y conciso, y debe estar dirigido a los directivos de la empresa B&C.

Solicitud de entrega del informe Se debe entregar enlace de la plataforma RPubs que contenga el documento final, utilizando el formato Markdown.

El informe debe estar organizado en un único documento que contenga la introducción, los objetivos, los métodos, los resultados, la discusión y las conclusiones. Cada sección del informe debe estar numerada y debe tener un encabezado descriptivo.

Entregable Enlace del informe en RPubs, copiado en Actividad1 del curso en Bs

Conjunto de Datos

Descripción

Estos datos han sido extraídos mediante webscraping. El dataset contiene características de viviendas de Cali.

¿Cómo se usa?: Solo hay que escribir “vivienda_faltantes” sin las comillas.

Registros: Conjunto con 8322 registros y 13 variables

Variables/Columnas

  • id: Identificador único de la vivienda

  • zona: Zona de la ciudad (Una de cinco: Norte, Sur, Oriente, Oeste y Centro)

  • piso: Piso en la que está ubicada la vivienda

  • estrato: Estrato donde esta la vivienda

  • preciom: Precio en millones de pesos

  • areaconst: Área construida en metros cuadrados

  • parqueaderos: Número de parqueaderos

  • banios: Número de baños

  • habitaciones: Número de habitaciones

  • tipo: Tipo de vivienda

  • barrio: Barrio

  • longitud: Coordenada de longitud

  • latitud: Coordenada de latitud

LS0tDQp0aXRsZTogIkFuw6FsaXNpcyBEZXNjcmlwdGl2byBTZWN0b3IgSW5tb2JpbGlhcmlvIGVuIGxhIENpdWRhZCBkZSBDYWxpIg0KYXV0aG9yOiAiRW5yaXF1ZSBKb3PDqSBQZcOxYSINCnN1YnRpdGxlOiAiQWN0aXZpZGFkIDEgLSBNw6l0b2RvcyB5IFNpbXVsYWNpb24gRXN0YWTDrXN0aWNhIC0gUFVKIENhbGkiDQpkYXRlOiAiMjAyNC0wMi0xMiINCm51bWJlci1zZWN0aW9uczogVFJVRQ0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICAgIHRoZW1lOiBmbGF0bHkNCiAgICBoaWdobGlnaHQ6IGthdGUNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFDQotLS0NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UsIGZpZy53aWR0aCA9IDUsIGZpZy5oZWlnaHQgPSA1KQ0KUi52ZXJzaW9uDQppZighcmVxdWlyZU5hbWVzcGFjZSgiZ2dwbG90MiIsIHF1aWV0bHkgPSBUUlVFKSl7DQogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KfQ0KaWYoIXJlcXVpcmVOYW1lc3BhY2UoImRldnRvb2xzIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKQ0KfQ0KDQppZighcmVxdWlyZU5hbWVzcGFjZSgib3V0bGllcnMiLCBxdWlldGx5ID0gVFJVRSkpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJvdXRsaWVycyIpDQp9DQppZighcmVxdWlyZU5hbWVzcGFjZSgiZHBseXIiLCBxdWlldGx5ID0gVFJVRSkpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpDQp9DQppZighcmVxdWlyZU5hbWVzcGFjZSgidGlkeXZlcnNlIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCn0NCmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJsZXNzUiIsIHF1aWV0bHkgPSBUUlVFKSl7DQogIGluc3RhbGwucGFja2FnZXMoImxlc3NSIikNCn0NCmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJWSU0iLCBxdWlldGx5ID0gVFJVRSkpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJWSU0iKQ0KfQ0KDQpsaWJyYXJ5KG91dGxpZXJzKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsZXNzUikNCmxpYnJhcnkoVklNKQ0KI2RldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiZGdvbnhhbGV4ODAvcGFxdWV0ZU1FVE9ET1MiKSAjIEluc3RhbGxzIHBhY2thZ2UgcGFxdWV0ZU1FVE9ET1MgLSBBbHJlYWR5IGluc3RhbGxlZA0KbGlicmFyeShwYXF1ZXRlTUVUT0RPUykgIyBDYXJnYSBwYXF1ZXRlIHBhcXVldGVNRVRPRE9TDQpkYXRhKCJ2aXZpZW5kYV9mYWx0YW50ZXMiKSAjIGxvYWQgZGF0YSAnVml2aWVuZGFfZmFsdGFudGVzJyAgZnJvbSAgcGFxdWV0ZU1FVE9ET1MNCnNldC5zZWVkKDY4OSkgIyBGaXggdGhlIHNlZWQgZm9yIHJhbmRvbSBudW1iZXJzDQpkZiA8LSB2aXZpZW5kYV9mYWx0YW50ZXMNCmRmDQpgYGANCg0KIyAqKlJlc3VtZW4gRWplY3V0aXZvKioNCg0KKipJbnRyb2R1Y2Npw7NuKioNCg0KRWwgbWVyY2FkbyBkZSBCaWVuZXMgUmHDrWNlcyBoYSBjcmVjaWRvIHNpZ25pZmljYXRpdmFtZW50ZSBlbiBsb3Mgw7psdGltb3MgYcOxb3MgZW4gbGEgY2l1ZGFkIGRlIENhbGkuIFBhcmEgZWwgYcOxbyAyMDIyIGxhcyB2ZW50YXMgZGUgaW5tdWVibGVzIGFsY2FuemFyb24gbG9zIFwkNi43MDAgbWlsbG9uZXMgZGUgcGVzb3MgeSBwYXJhIGVsIGHDsW8gMjAyMyBsYXMgdmVudGFzIGZ1ZXJvbiBkZSBcJDYuMTAwIG1pbGxvbmVzLiAgQnVzY2FuZG8gYXByb3ZlY2hhciBlc3RlIGNyZWNpbWllbnRvLCBzZSBwcmV0ZW5kZSwgYSBwYXJ0aXIgZGUgdW4gY29uanVudG8gZGUgZGF0b3MgZGUgbG9zIGlubXVlYmxlcyBlbiB2ZW50YSBlbiBsYSBjaXVkYWQsIGJyaW5kYXIgaW5mb3JtYWNpw7NuIGJhc2FkYSBlbiBsYSBlc3RhZMOtc3RpY2EgcXVlIHNpcnZhIGNvbW8gYmFzZSBwYXJhIGxhIHRvbWEgZGUgZGVjaXNpb25lcyBlc3RyYXTDqWdpY2FzIHF1ZSBvcmllbnRlbiBhICoqQmllbmVzIHkgQ2FzYXMgKEImQykqKiBwYXJhIGFwcm92ZWNoYXIgZXN0ZSBjcmVjaW1pZW50byBkZWwgc2VjdG9yLiANCg0KRWwgaW5mb3JtZSBlc3RhZMOtc3RpY28gcHJvcG9yY2lvbmFyw6EgaW5mb3JtYWNpw7NuIHNvYnJlOg0KDQotIENhcmFjdGVyaXphY2nDs24gZGUgbG9zIHByZWNpb3MgZGUgbGFzIHZpdmllbmRhcyBlbiBkaWZlcmVudGVzIHpvbmFzIGRlIGxhIGNpdWRhZA0KLSBFbCB0aXBvIGRlIHZpdmllbmRhIG3DoXMgb2ZlcnRhZGEgZW4gQ2FsaQ0KLSBDYXJhY3RlcsOtc3RpY2FzIG3DoXMgcmVsZXZhbnRlcyBkZSBsYSBvZmVydGEgZGUgdml2aWVuZGEgZW4gQ2FsaQ0KDQoqKk1ldG9kb2xvZ8OtYSoqDQoNClBhcmEgbGxlZ2FyIGEgbG9zIHJlc3VsdGFkb3MgZSBlc3RlIGFuw6FsaXNpcyBkZXNjcmlwdGl2byBzZSBzaWd1aWVyb24gbG9zIHNpZ3VpZW50ZXMgcGFzb3M6DQoNCi0gQ2FyZ2EgeSByZXZpc2nDs24gZ2VuZXJhbCBkZSBsYSBpbmZvcm1hY2nDs24NCi0gT3JkZW5hbWllbnRvIHkgbGltcGllemEgZGVsIGNvbmp1bnRvIGRlIGRhdG9zDQotIFRyYW5zZm9ybWFjacOzbiBkZWwgY29uanVudG8gZGUgZGF0b3MgeSB2aXN1YWxpemFjacOzbg0KLSBQcmVzZW50YWNpw7NuIGRlIGxvcyBSZXN1bHRhZG9zIHkgQ29uY2x1c2lvbmVzDQoNCioqUmVzdW1lbiBkZSBSZXN1bHRhZG9zKioNCg0KKiBab25hcyB5IHRpcG9zIGRlIElubXVlYmxlcyBjb24gbWVqb3JlcyBwcmVjaW9zDQoNCmBgYHtyIHpvbmVzX3R5cGVzLCBpbmNsdWRlID0gVFJVRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIk1lZGlhbmFQcmVjaW9zLnBuZyIpDQpgYGANCg0KQ29tbyBzZSBwdWVkZSB2ZXIgZW4gbGEgZ3LDoWZpY2EsIGxhIHpvbmEgY29uIG1lam9yZXMgcHJlY2lvcyBlcyBsYSB6b25hIE9lc3RlLCBzZWd1aWRhIHBvciBsYSBTdXIgeSBsYSBub3J0ZS4gRW4gY3VhbnRvIGFsIHRpcG8gZGUgaW5tdWVibGUsIGxhcyBjYXNhcyBwcmVzZW50YW4gbWVqb3JlcyBwcm9tZWRpb3MgcXVlIGxvcyBhcGFydGFtZW50b3MgZW4gdG9kYXMgbGFzIHpvbmFzLCB5IGVuIGdlbmVyYWwsIGxvcyB0aXBvcyB5IHpvbmFzIG1lam9yZXMgY2xhc2lmaWNhZG9zIGVuIGN1YW50byBhbCB2YWxvciwgc29uLCBlbiBlc3RlIG9yZGVuOiBDYXNhcyBlbiBlbCBPZXN0ZSwgQXBhcnRhbWVudG9zIGVuIGVsIE9lc3RlLCBDYXNhcyBlbiBlbCBTdXIsIENhc2FzIGVuIGVsIE5vcnRlLg0KDQoqIFRpcG8gZGUgaW5tdWVibGUgbcOhcyBvZmVydGFkbw0KDQpMb3MgYXBhcnRhbWVudG9zIHNvbiBlbCB0aXBvIGRlIGlubXVlYmxlIGNvbiBtYXlvciBjYW50aWRhZCBkZSBvZmVydGFzDQplbiBsYSBjaXVkYWQgZGUgQ2FsaSBzdXBlcmFuZG8gZW4gY2FudGlkYWQgYSBsYXMgY2FzYXMgZW4gbGEgem9uYSBOb3J0ZSwNCk9lc3RlIHkgU3VyLiBFbiBsYXMgem9uYXMgQ2VudHJvIHkgT3JpZW50ZSwgaGF5IG3DoXMgY2FzYXMgb2ZlcnRhZGFzLCBlbg0KdW5hIHByb3BvcmNpw7NuIGFwcm94aW1hZGEgZGUgNiBhIDEuDQoNCmBgYHtyIHRhYmxlX3F1YW50aXR5LCBpbmNsdWRlID0gVFJVRSwgZWNobyA9IEZBTFNFfQ0KI2NvbF9uYW1lcyA8LSBjKCJBcGFydGFtZW50b3MiLCAiQ2FzYXMiKQ0KY29sX3ZhbHVlcyA8LSBjKDM3MDQsMzE2NikNCm1hdHJpeiA8LSBtYXRyaXgoY29sX3ZhbHVlcywgbnJvdyA9IDEsIG5jb2wgPSAyLCBieXJvdyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICBkaW1uYW1lcyA9IGxpc3QoYygiQ2FudGlkYWQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCJBcGFydGFtZW50b3MiLCJDYXNhcyIpKSkNCnByaW50KG1hdHJpeikNCmBgYA0KDQotICAgTWVqb3IgdGlwbyBkZSBWaXZpZW5kYQ0KDQpBdW5xdWUgaGF5IG3DoXMgYXBhcnRhbWVudG9zIHF1ZSBjYXNhcywgbGFzIGNhc2FzIHByZXNlbnRhbiBtYXlvcmVzIHZhbG9yZXMgZW4gc3UgcHJlY2lvLCBsbyBxdWUgbGFzIGhhY2UgbcOhcyBhdHJhY3RpdmFzLiBMYXMgem9uYXMgb3JnYW5pemFkYXMgcG9yIHN1IHByb21lZGlvIGRlIHZlbnRhIHNvbjogbGEgT2VzdGUsIGxhIFN1ciwgbGEgTm9ydGUsIGxhIENlbnRybyB5IGxhIE9yaWVudGUuIA0KDQoNCioqU3VnZXJlbmNpYXMgYSBtb2RvIGRlIENvbmNsdXNpb25lcyoqDQoNCkVsIGNvbmp1bnRvIGRlIGRhdG9zIHRpZW5lIG11Y2hhcyBpcnJlZ3VsYXJpZGFkZXMuIEVzdG8sIG5vIHNvbG8gYWxhcmdhIGVsIHByb2Nlc28gZGUgcHJvY2VzYW1pZW50byBkZSBsYSBpbmZvcm1hY2nDs24sIHNpbm8gcXVlIHRhbWJpw6luIHNpZW1icmUgdW5hIGR1ZGEgc29icmUgbG9zIHJlc3VsdGFkb3Mgb2J0ZW5pZG9zLiBQYXJhIHVuYSBzaWd1aWVudGUgb3BvdHVuaWRhZCwgc2Ugc3VnaWVyZSBjb25zZWd1aXIgZGF0b3MgZGUgbGFzIHZlbnRhcyBlZmVjdGl2YXMgcmVhbGl6YWRhcyBlbiBsYSBjaXVkYWQgZGUgQ2FsaSwgZGUgZG9uZGUgc2UgcHVlZGVuIHNhY2FyIGRhdG9zIGNvbmNyZXRvcyBkZSBwcmVjaW9zIGRlIHZlbnRhIHkgY2FyYWN0ZXLDrXN0aWNhcyBkZSBsYXMgdml2aWVuZGFzLCBjb21vIHN1IHViaWNhY2nDs24geSBvdHJvcyBkYXRvcyBxdWUgZXN0w6FuIHByb2JhYmxlbWVudGUgeWEgdmVyaWZpY2Fkb3MgbyBjb24gbWVqb3IgY2FsaWRhZC4NCg0KUG9yIG90cm8gbGFkbywgc2Ugc3VnaWVyZSBxdWUgZW4gZWwgcHJvY2VzbyBkZSBlbnRlbmRpbWllbnRvIHkgcHJvY2VzYW1pZW50byBkZSBsb3MgZGF0b3MsIGVzdMOpIHZpbmN1bGFkbyBhbGd1aWVuIGRlIGxhIGVtcHJlc2EsIHB1ZXMgZXN0byBoYXLDrWEgcXVlIGxhcyBkZWNpc2lvbmVzIHF1ZSBzZSB0b21hcmFuIHNvYnJlIGxvcyBkYXRvcyBwdWRpZXJhbiB0ZW5lciBtw6FzIHNlbnRpZG8gZGVzZGUgZWwgcHVudG8gZGUgdmlzdGEgZXN0cmF0w6lnaWNvIHkgZGUgY29ub2NpbWllbnRvIGRlIG5lZ29jaW8uDQoNClRhbWJpw6luLCBlcyBwb3NpdGl2byBwYXJhIGVsIGFuw6FsaXNpcyBxdWUgc2UgY29ub3pjYW4gZGV0YWxsZXMgc29icmUgbGEgb3BlcmFjacOzbiBkZSBsYSBlbXByZXNhLCB0YWxlcyBjb21vIHZvbHVtZW4gZGUgdmVudGFzLCBjYW50aWRhZCBkZSBhZ2VudGVzIGlubW9iaWxpYXJpb3MsIHV0aWxpZGFkZXMgYW50ZXJpb3JlcywgeSBzaSBoYXkgbWV0YXMgeWEgcGxhbnRlYWRhcyBwYXJhIGxvcyBwZXJpb2RvcyBmdXR1cm9zLiBFc3RvIGZhY2lsaXRhcsOtYSBlbCB0cmFiYWpvIGNvbmp1bnRvIHkgYXVtZW50YXLDrWEgbGFzIHByb2JhYmlsaWRhZGVzIGRlIMOpeGl0byBkZWwgcHJveWVjdG8uIGltcG9ydGFudGUgaGFjZXJsby4NCg0KU2UgcHJlc2VudGEgYSBjb250aW51YWNpw7NuIHRvZG8gZWwgcHJvY2VzbyBkZSBhbsOhbGlzaXMgcXVlIHNlIGxsZXbDsyBhIGNhYm8gcGFyYSBsYSBJbm1vYmlsaWFyaWEgQiZDLg0KDQotLS0NCg0KIyAxLiBJbnRyb2R1Y2Npw7NuDQoNClBhcmEgbG9zIHByw7N4aW1vcyBhw7Fvcywgc2UgZXNwZXJhIHF1ZSBlbCBtZXJjYWRvIGlubW9iaWxpYXJpbyBlbiBsYQ0KQ2l1ZGFkIGRlIENhbGkgc2lnYSBzdWJpZW5kbyBjb21vIGVuIGHDsW9zIGFudGVyaW9yZXMsIGJyaW5kYW5kbw0Kb3BvcnR1bmlkYWRlcyBwYXJhIGxvcyBhY3RvcmVzIHF1ZSBsb2dyZW4gaWRlbnRpZmljYXIgbGFzDQpjYXJhY3RlcsOtc3RpY2FzIG3DoXMgcmVsZXZhbnRlcyBkZSBzdSBjb21wb3J0YW1pZW50by4gUGFyYSBhcHJvdmVjaGFyDQplc3RhIG9wb3J0dW5pZGFkLCBzZSBlbnRyZWdhIGVsIHByZXNlbnRlIGluZm9ybWUgYSBsYSBqdW50YSBkaXJlY3RpdmEgZGUNCmxhIGFnZW5jaWEgKippbm1vYmlsaWFyaWEgQiZDKiouIEVuIGVzdGUgaW5mb3JtZSBzZSBleHBsaWNhIGRlIG1hbmVyYQ0KZ2VuZXJhbCBlbCAqcHJvY2VzbyBkZSBvcmRlbmFtaWVudG8qIHkgKmxpbXBpZXphIGRlIGRhdG9zKiwgeSBzZSBwcmVzZW50YSB1bg0KKmFuw6FsaXNpcyBkZXNjcmlwdGl2byogZGUgbG9zIGRhdG9zIHJlc3VsdGFudGVzLiBQYXJhIGVzdG8sIGRlc3B1w6lzIGRlDQoqaW1wb3J0YXIgZWwgY29uanVudG8gZGUgZGF0b3MqLCB5IGRlIHJlYWxpemFyIHN1ICpsaW1waWV6YSosIGZ1c2lvbmFuZG8sDQplbGltaW5hbmRvLCBub3JtYWxpemFuZG8sIGVzdGFuZGFyaXphbmRvIG8gaW1wdXRhbmRvIGRhdG9zLCBzZWfDum4gZnVlc2UNCm5lY2VzYXJpbywgc2UgcmVhbGl6w7MgdW4gKmFuw6FsaXNpcyBkZSBsb3MgZGF0b3MqIHBhcmEgcHJlc2VudGFybG9zIGVuDQpkaXN0aW50b3MgZ3LDoWZpY29zIHkgdGFibGFzIHF1ZSBwZXJtaXRpcsOhbiBlbnRlbmRlciBtZWpvciBsYXMNCmNhcmFjdGVyw61zdGljYXMgZGVsIGNvbmp1bnRvLg0KDQpQb3N0ZXJpb3JtZW50ZSwgc2UgcHJlc2VudGFyw6FuIGxvcyByZXN1bHRhZG9zIGRlIGRpY2hvIGFuw6FsaXNpcyB5IHNlDQpyZWFsaXphcsOhIHVuYSBkaXNjdXNpw7NuIHNvYnJlIGxvcyBkZXNjdWJyaW1pZW50b3MgeSBkaWZpY3VsdGFkZXMNCmVuY29udHJhZGFzIGVuIGxvcyBkYXRvcywgcGFyYSBmaW5hbG1lbnRlLCBlbnRyZWdhciBsYXMgY29uY2x1c2lvbmVzIGRlDQp0b2RvIGVsIGVqZXJjaWNpby4gKipDb21vIGFuZXhvLCBzZSBwb2Ryw6EgdmVyIHRvZG8gZWwgY29kaWdvIGVqZWN1dGFkbyBlbg0KdG9kYXMgbGFzIHBhcnRlcyBkZWwgcHJvY2Vzby4qKg0KDQpBIGNvbnRpbnVhY2nDs24sIHNlIHByZXNlbnRhbiBsb3Mgb2JqZXRpdm9zIHF1ZSBzZSBidXNjYXJvbiBjb24gbGENCnJlYWxpemFjacOzbiBkZSBlc3RlIGVzdHVkaW8uDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDIuIE9iamV0aXZvcw0KDQpMYSBpbm1vYmlsaWFyaWEgKipCJkMqKiBkZXNlYSB0b21hciBkZWNpc2lvbmVzIGltcG9ydGFudGVzIHNvYnJlIHN1DQpuZWdvY2lvLCB0YWxlcyBjb21vIGRlZmluaXIgdW4gbmljaG8gZGUgbWVyY2FkbywgZGVzYXJyb2xsYXIgbGENCmVzdHJhdGVnaWEgZGUgbWFya2V0aW5nLCBlc3RhYmxlY2VyIHByZWNpb3MgZGUgdmVudGFzIHkgb2ZyZWNlcg0Kc2VydmljaW9zIHBlcnNvbmFsaXphZG9zIGEgc3VzIGNsaWVudGVzLiBQYXJhIHBvZGVyIGxvZ3JhciBlc3RvLCBlbA0KcHJlc2VudGUgcHJveWVjdG8gaGEgZGVmaW5pZG8gbG9zIHNpZ3VpZW50ZXMgb2JqZXRpdm9zOg0KDQotICAgQW5hbGl6YXIgbGEgaW5mb3JtYWNpw7NuIGRlbCBjb25qdW50byBkZSBkYXRvcyBkZSBsYSB2ZW50YSBkZQ0KICAgIHZpdmllbmRhcyBlbiBsYSBjaXVkYWQgZGUgQ2FsaQ0KLSAgIERlcHVyYXIgZWwgY29uanVudG8gZGUgZGF0b3MgcGFyYSBzdSBwb3N0ZXJpb3IgdXRpbGl6YWNpw7NuDQotICAgUmVhbGl6YXIgdW4gYW7DoWxpc2lzIGRlc2NyaXB0aXZvIGRlIGxvcyBkYXRvcw0KLSAgIFByb3BvcmNpb25hciBpbmZvcm1hY2nDs24gc29icmU6DQogICAgLSAgIFByZWNpbyBkZSBsYXMgdml2aWVuZGFzIGVuIGRpZmVyZW50ZXMgem9uYXMgZGUgQ2FsaQ0KICAgIC0gICBUaXBvIGRlIHZpdmllbmRhcyBtw6FzIG9mZXJ0YWRhcw0KICAgIC0gICBDYXJhY3RlcsOtc3RpY2FzIG3DoXMgcmVsZXZhbnRlcyBkZSBsYSBvZmVydGEgZGUgdml2aWVuZGEgZW4gQ2FsaQ0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyAzLiBNw6l0b2RvcyANCg0KIyMgMy4xLiBBbsOhbGlzaXMgaW5pY2lhbA0KDQpMdWVnbyBkZSBpbXBvcnRhciBsb3MgcGFxdWV0ZXMgcmVxdWVyaWRvcyB5IGRlIGNhcmdhciBsYSBsaWJyZXLDrWEgeSBsb3MgZGF0b3MgY29uIGxvcyBxdWUgdmFtb3MgYSB0cmFiYWphciwgc2UgZGlvIHVuYSBwcmltZXJhIG1pcmFkYSBhbCBjb25qdW50byBkZSBkYXRvcy4NCg0KYGBge3Igc2V0dXAyLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSkNClIudmVyc2lvbg0KaWYoIXJlcXVpcmVOYW1lc3BhY2UoImdncGxvdDIiLCBxdWlldGx5ID0gVFJVRSkpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCn0NCmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJkZXZ0b29scyIsIHF1aWV0bHkgPSBUUlVFKSl7DQogIGluc3RhbGwucGFja2FnZXMoImRldnRvb2xzIikNCn0NCg0KaWYoIXJlcXVpcmVOYW1lc3BhY2UoIm91dGxpZXJzIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygib3V0bGllcnMiKQ0KfQ0KaWYoIXJlcXVpcmVOYW1lc3BhY2UoImRwbHlyIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQ0KfQ0KaWYoIXJlcXVpcmVOYW1lc3BhY2UoInRpZHl2ZXJzZSIsIHF1aWV0bHkgPSBUUlVFKSl7DQogIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQp9DQppZighcmVxdWlyZU5hbWVzcGFjZSgibGVzc1IiLCBxdWlldGx5ID0gVFJVRSkpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJsZXNzUiIpDQp9DQpsaWJyYXJ5KG91dGxpZXJzKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsZXNzUikNCiNkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImRnb254YWxleDgwL3BhcXVldGVNRVRPRE9TIikgIyBJbnN0YWxscyBwYWNrYWdlIHBhcXVldGVNRVRPRE9TIC0gQWxyZWFkeSBpbnN0YWxsZWQNCmBgYA0KDQpgYGB7ciBtYWluX2xpYnJhcnksIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KHBhcXVldGVNRVRPRE9TKSAjIENhcmdhIHBhcXVldGUgcGFxdWV0ZU1FVE9ET1MNCmBgYA0KDQpgYGB7ciBsb2FkX2RhdGF9DQpkYXRhKCJ2aXZpZW5kYV9mYWx0YW50ZXMiKSAjIGxvYWQgZGF0YSAnVml2aWVuZGFfZmFsdGFudGVzJyAgZnJvbSAgcGFxdWV0ZU1FVE9ET1MNCnNldC5zZWVkKDY4OSkgIyBGaXggdGhlIHNlZWQgZm9yIHJhbmRvbSBudW1iZXJzDQpkZiA8LSB2aXZpZW5kYV9mYWx0YW50ZXMNCmRmDQpgYGANCg0KUG9kZW1vcyBvYnNlcnZhciBxdWUgaGF5IHZhcmlhYmxlcyBjb21vIGlkLCB6b25hLCBwaXNvLCBlc3RyYXRvLA0KcHJlY2lvbSwgYXJlYWNvbnN0LCBwYXJxdWVhLCBiYW5pb3MsIGhhYml0YWMsIHRpcG8sIGJhcnJpbywgbGF0aXR1ZCB5IGxvbmdpdHVkLg0KQ2FkYSBsw61uZWEgcHJvcG9yY2lvbmEgaW5mb3JtYWNpw7NuIHNvYnJlIHVuIGlubXVlYmxlIGVuIHBhcnRpY3VsYXIuDQpBaG9yYSB2ZWFtb3MgY3VhbnRvcyBkYXRvcyBmYWx0YW50ZXMgaGF5IGVuIGVsIGRhdGFzZXQuDQoNCmBgYHtyIG1pc3NpbmdfZGF0YX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCm1pc3NpbmdfZGF0YSA8LSBjb2xTdW1zKGlzLm5hKGRmKSkgJT4lDQogICAgICAgICAgICAgICAgIGFzLmRhdGEuZnJhbWUoKSANCg0KbWlzc2luZ19kYXRhDQoNClZJTTo6YWdncihkZiwgY2V4LmF4aXMgPSAwLjUsIGNleC5sYWI9IDAuOCkgIA0KYGBgDQoNCiMjIDMuMi4gTGltcGllemEgZGUgZGF0b3Mgey50YWJzZXR9DQoNCiMjIyAzLjIuMS4gRWxpbWluYWNpw7NuIGRlIHJlZ2lzdHJvcyB2YWPDrW9zDQoNCkVsaW1pbmVtb3MgbG9zIHJlZ2lzdHJvcyBjb24gZGF0b3MgZmFsdGFudGVzIGVuIGxhIGNvbHVtbmEgaWQsIHkNCnZvbHZhbW9zIGEgcmV2aXNhciBsb3MgZGF0b3MgZmFsdGFudGVzIGRlbCBjb25qdW50byBkZSBkYXRvcy4NCg0KYGBge3IgZGVsZXRlX25hfQ0KZGYgPC0gZmlsdGVyKGRmLCFpcy5uYShkZiRpZCkpIA0KZGYNCm1pc3NpbmdfZGF0YSA8LSBjb2xTdW1zKGlzLm5hKGRmKSkgJT4lDQogICAgICAgICAgICAgICAgIGFzLmRhdGEuZnJhbWUoKSANCg0KbWlzc2luZ19kYXRhIA0KYGBgDQoNCkxhIGNvbHVtbmEgaWQgbm8gYXBvcnRhIGluZm9ybWFjacOzbiB2YWxpb3NhIGFsIGVzdHVkaW8sIGFzw60gcXVlIGxhDQplbGltaW5hcmVtb3MuIERlIGlndWFsIGZvcm1hLCBsYXMgdmFyaWFibGVzICoqbG9uZ2l0dWQqKiB5ICoqbGF0aXR1ZCoqDQpubyBzZSBoYWNlbiByZWxldmFudGVzIHBhcmEgZXN0ZSBlc3R1ZGlvLCBkYWRvIHF1ZSBzZSB0cmF0YSBkZSBpbm11ZWJsZXMNCmVuIHVuYSBzb2xhIGNpdWRhZCB5IHF1ZSBhZGVtw6FzIHNlIHRpZW5lIGxhIHZhcmlhYmxlIGRlbCBiYXJyaW8geSBkZSBsYQ0Kem9uYSBlbiBlbCBjb25qdW50byBkZSBkYXRvcy4gVGFtcG9jbyBzZSB2YSBhIGhhY2VyIHVuYSB2aXN1YWxpemFjacOzbiBkZQ0KbGEgZGlzdHJpYnVjacOzbiBkZSBsYXMgY2FzYXMgZW4gdW4gbWFwYSwgYXVucXVlIHBhcmEgdW4gYW7DoWxpc2lzIGRlIG90cm8NCnRpcG8sIGVzdG8gc2kgcG9kcsOtYSBzZXIgcmVsZXZhbnRlLiBFc3RhcyB0YW1iacOpbiBzZSBlbGltaW5hcsOhbiBkZWwNCmNvbmp1bnRvLg0KDQpgYGB7ciBkZWxfaWR9DQpkZiRsYXRpdHVkIDwtIE5VTEwNCmRmJGxvbmdpdHVkIDwtIE5VTEwNCmRmJGlkIDwtIE5VTEwNCmRmDQpgYGANCg0KIyMjIDMuMi4yLiBBbsOhbGlzaXMgZGUgY29sdW1uYXMgY29uIGRhdG9zIGZhbHRhbnRlcw0KDQpWZW1vcyBxdWUgYWhvcmEgZW4gbGFzIMO6bmljYXMgdmFyaWFibGVzIGVuIGxhcyBxdWUgZmFsdGFuIGRhdG9zIHNvbg0KKipwaXNvKiogeSAqKnBhcnF1ZWEuKiogVmVhbW9zIHF1w6kgY2FyYWN0ZXLDrXN0aWNhcyB0aWVuZW4gZXNhcw0KdmFyaWFibGVzLCBwcmltZXJvIGxvIGhhY2Vtb3MgcGFyYSAqKnBpc28qKg0KDQpgYGB7ciBzdW1tYXJ5fQ0Kc3VtbWFyeShkZiRwaXNvKQ0KdGFibGUoZGYkcGlzbykNCmBgYA0KDQpQb2RlbW9zIG9ic2VydmFyIGFsZ3VuYXMgY29zYXMgaW1wb3J0YW50ZXMuIExvIHByaW1lcm8gZXMgcXVlIGhheSAyNjM4DQpyZWdpc3Ryb3Mgc2luIGRhdG8gZW4gbGEgY29sdW1uYSAqKnBpc28qKi4gTG8gc2VndW5kbywgcXVlIGVsIG1lbm9yIHZhbG9yDQplcyAxIHkgZWwgbWF5b3IgZXMgMTIsIGNvbiB1biBidWVuIG7Dum1lcm8gZGUgcmVnaXN0cm9zIGNvbiB2YWxvcmVzDQphbHRvcy4gUG9yIGVsIG5vbWJyZSBkZSBsYSB2YXJpYWJsZSBubyBzYWJlbW9zIHNpIGVsIHZhbG9yIGNvcnJlc3BvbmRlDQphbCBuw7ptZXJvIGRlbCBwaXNvIGVuIGVsIHF1ZSBxdWVkYSBlbCBpbm11ZWJsZSBlbiB1biBlZGlmaWNpbywgbyBlbA0KbsO6bWVybyBkZSBwaXNvcyBxdWUgdGllbmUgZWwgaW5tdWVibGUuIFNpIGZ1ZXJhIGxvIHNlZ3VuZG8sIHF1ZXJyw61hDQpkZWNpciBxdWUgaGF5IGlubXVlYmxlcyBxdWUgdGllbmVuIDEyIHBpc29zLCBsbyBxdWUgdGVuZHLDrWEgc2VudGlkbyBzaQ0KZnVlcmFuIGVkaWZpY2lvcy4gU2kgZnVlcmEgbG8gcHJpbWVybywgc2lnbmlmaWNhIHF1ZSBoYXkgaW5tdWVibGVzIGVuIGVsDQpkb2NlYXZvIHBpc28gZGUgdW4gZWRpZmljaW8sIGFsIGlndWFsIHF1ZSBlbiBlbCBkw6ljaW1vLCBlbCBub3Zlbm8sIHkgYXPDrQ0Kc3VjZXNpdmFtZW50ZSwgTG8gcXVlIHRpZW5lIG11Y2hvIG3DoXMgc2VudGlkbywgZGFkbyBsbyBleHRyZW1hZGFtZW50ZQ0KcmFybyBxdWUgc2Vyw61hIHF1ZSB1bmEgY2FzYSBvIHVuIGFwYXJ0YW1lbnRvIHR1dmllcmEgMTIgcGlzb3MuIFBhcmENCnRyYXRhciBkZSBlbnRlbmRlciBhIHF1ZSBzZSByZWZpZXJlLCB2YW1vcyBhIHZlciBwcmltZXJvIGEgcXVlIHRpcG8gZGUNCmlubXVlYmxlIGNvcnJlc3BvbmRlbiBsb3MgcmVnaXN0cm9zIHF1ZSB0aWVuZW4gdW4gbsO6bWVybyBhbHRvLg0KDQpgYGB7ciBwaXNvX25hfQ0KcGlzb25hIDwtIHN1YnNldChkZiwgaXMubmEoZGYkcGlzbykpICNzdWJzZXQgcGlzb25hIGNvbnRhaW5zIHRoZSByZWNvcmRzIHdpdGhvdXQgdmFsdWUgaW4gY29sdW1uIHBpc28NCnRhYmxlKHBpc29uYSR0aXBvKQ0KYGBgDQoNClBlcm8gYW50ZXMsIHZlbW9zIHF1ZSBsb3MgcmVnaXN0cm9zIGNvcnJlc3BvbmRlbiB0YW50byBhIGNhc2FzIGNvbW8gYSBhcGFydGFtZW50b3MsIHkgcXVlIGhheSBkaWZlcmVuY2lhIGVuIGxhIGVzY3JpdHVyYSBkZSBsb3MgdmFsb3JlcyBxdWUgY29ycmVzcG9uZGVuIGEgdW4gbWlzbW8gdGlwbyBkZSBpbm11ZWJsZS4gVGFtYmnDqW4gdmVtb3MgcXVlIG5vIGhheSBlZGlmaWNpb3MsIGx1ZWdvIG5vIHRlbmRyw61hIHNlbnRpZG8gbGEgc2VndW5kYSBoaXDDs3Rlc2lzIGRlIHF1ZSBsYSB2YXJpYWJsZSAqcGlzbyogc2UgcmVmaWVyZSBhbCBuw7ptZXJvIGRlIHBpc29zIGRlbCBpbm11ZWJsZS4gU2UgdHJhdGEgcG9yIGxvIHRhbnRvIGRlbCBwaXNvIGVuIGVsIHF1ZSBzZSB1YmljYSBlbCBpbm11ZWJsZS4gQSBjb250aW51YWNpw7NuLCB2b3kgYSBob21vZ2VuaXphciBsb3Mgbm9tYnJlcyBkZSBsb3MgdGlwb3MgZGUgaW5tdWVibGUgZW4gKipBcGFydGFtZW50byoqIHkgKipDYXNhKiogc29sYW1lbnRlLiBFbiBlbCBjYXNvIGRlIGxvcyB2YWxvcmVzICoqYXB0byoqLCB0ZW5kcsOpIHF1ZSByZWVtcGxhemFybG9zDQpwb3IgKipBcGFydGFtZW50byoqLg0KDQpgYGB7ciBob21vZ2VuaXphdGlvbn0NCmRmJHRpcG8gPC0gdG9sb3dlcihkZiR0aXBvKQ0KdGFibGUoZGYkdGlwbykNCmRmJHRpcG8gPC0gaWZlbHNlKGRmJHRpcG8gPT0gImFwdG8iLCAiQXBhcnRhbWVudG8iLCBpZmVsc2UoZGYkdGlwbyA9PSAiYXBhcnRhbWVudG8iLCAiQXBhcnRhbWVudG8iLCBpZmVsc2UoZGYkdGlwbyA9PSAiY2FzYSIsICAiQ2FzYSIsIGRmJHRpcG8pKSkNCnRhYmxlKGRmJHRpcG8pDQpgYGANCg0KQWhvcmEgdmVhbW9zIG51ZXZhbWVudGUgYSBxdWUgdGlwbyBkZSBpbm11ZWJsZSBjb3JyZXNwb25kZW4gbG9zDQpyZWdpc3Ryb3Mgc2luICoqcGlzbyoqOg0KDQpgYGB7ciBwaXNvX25hX2FnYWlufQ0KcGlzb25hIDwtIHN1YnNldChkZiwgaXMubmEoZGYkcGlzbykpICNzdWJzZXQgcGlzb25hIGNvbnRhaW5zIHRoZSByZWNvcmRzIHdpdGhvdXQgdmFsdWUgaW4gY29sdW1uIHBpc28NCnRhYmxlKHBpc29uYSR0aXBvKQ0KYGBgDQoNClNlIHB1ZWRlIG9ic2VydmFyIHF1ZSBoYXkgc3VmaWNpZW50ZXMgcmVnaXN0cm9zIHNpbiB2YWxvciBlbiBsYSB2YXJpYWJsZQ0KKipwaXNvKiogKCszMCUpLiBFc3RvIHB1ZWRlIHRlbmVyIHNlbnRpZG8gcGFyYSBsYXMgY2FzYXMsIHBvciBzdQ0KbmF0dXJhbGV6YSwgcHVlcyBlbGxhcyBubyAiZXN0w6FuIiBlbiBuaW5nw7puIHBpc28sIGFsIG1lbm9zIGRpZmVyZW50ZSBhbA0KMXJvLCBwZXJvIGVzbyBubyBzZSBtZW5jaW9uYSBkZSBlc3RhIG1hbmVyYS4gTG8gY29tw7puIGVzIHF1ZSB1bg0KYXBhcnRhbWVudG8gc2kgdGVuZ2EgdW4gcGlzbyBlbiBkb25kZSBlc3TDqSB1YmljYWRvIGRlbnRybyBkZSB1bg0KZWRpZmljaW8sIGF1bnF1ZSBleGlzdGVuIGFwYXJ0YW1lbnRvcyBlbiBjYXNhcyBxdWUgc2Ugc3ViZGl2aWRlbiwgbG9zDQpjdWFsZXMgZXN0w6FuIHBvciBsbyBnZW5lcmFsIGVuIGVsIHByaW1lciBwaXNvICgqKnBpc28gPSAxKiopIEFob3JhDQp2ZWFtb3MgbGEgY2FudGlkYWQgZGUgcmVnaXN0cm9zIGNvbiAqKnBpc28qKiBzZWfDum4gc3UgdGlwbzoNCg0KYGBge3IgcGlzb19jb3VudH0NCndpdGhwaXNvIDwtIHN1YnNldChkZiwgIWlzLm5hKGRmJHBpc28pKSAjc3Vic2V0IHdpdGhwaXNvIGNvbnRhaW5zIHRoZSByZWNvcmRzIHdpdGggdmFsdWUgaW4gY29sdW1uIHBpc28NCnRhYmxlKHdpdGhwaXNvJHRpcG8pDQpgYGANCg0KQ29tbyBlcmEgZGUgZXNwZXJhcnNlLCBlc3RhIGNhbnRpZGFkIGVzdMOhIGNlcmNhIGFsIDcwJS4gQWhvcmEgdmVhbW9zDQpjb21vIHNlIGNydXphIGVsIFRpcG8gY29uIGxhIGxvcyB2YWxvcmVzIGVuIGxhIGNvbHVtbmEgcGlzby4NCg0KYGBge3IgcGlzb19uYV9tYXRyaXh9DQp0YWJsZShkZiRwaXNvLGRmJHRpcG8pDQpgYGANCg0KQWhvcmEsIHJldG9tYW5kbyBlbCBhbsOhbGlzaXMgc29icmUgZWwgc2lnbmlmaWNhZG8gZGUgbGEgdmFyaWFibGUgcGlzbywNCnNpIGZ1ZXJhIGVsIHBpc28gZW4gZWwgcXVlIHNlIGVuY3VlbnRyYSwgdGVuZHLDrWEgc2VudGlkbyBwYXJhIGxvcw0KQXBhcnRhbWVudG9zLCBwZXJvIG5vIHBhcmEgbGFzIGNhc2FzLiBTaSBmdWVyYSBsYSBjYW50aWRhZCBkZSBwaXNvcywNCnRlbmRyw61hIHNlbnRpZG8gcGFyYSBsYXMgQ2FzYXMgZGUgMSwgMiB5IGhhc3RhIDMgcGlzb3MsIHB1ZXMsIGF1bnF1ZQ0KcG9zaWJsZSwgZXhpc3RlIG11eSBwb2NhIHByb2JhYmlsaWRhZCBkZSBjYXNhcyBkZSAxMCwgNywgNiB5IDUgcGlzb3MsIGUNCmluY2x1c2l2ZSBsYXMgZGUgNCBwaXNvcyBzb24gbXV5IGVzY2FzYXMuIE1lIGF0cmV2ZXLDrWEgZW50b25jZXMgYSBkZWNpcg0KcXVlIHBhcmEgbG9zIHJlZ2lzdHJvcyBkZSB0aXBvIEFwYXJ0YW1lbnRvLCBlbCB2YWxvciBlbnRyZSAxIHkgMTIgdGllbmUNCnNlbnRpZG8uIFBhcmEgbG9zIGRlIHRpcG8gQ2FzYSwgbG9zIHZhbG9yZXMgYWx0b3MsIG1heW9yZXMgbyBpZ3VhbGVzIGEgNA0Kbm8gdGllbmVuIHNlbnRpZG8gbyBzb24gbXV5IHBvY28gcHJvYmFibGVzLg0KDQpFbiBlc3RvcyBjYXNvcyBlbnRvbmNlcyBsbyBxdWUgaGFyZW1vcyBlcyBtb2RpZmljYXIgbyBjb21wbGV0YXIgbGENCnZhcmlhYmxlIHBpc28gY29uIGVsIHZhbG9yIDEsIHBhcmEgdG9kYXMgbGFzIGNhc2EgY29uIHBpc28gXD4gMyB5DQpkZWphcmVtb3MgbG9zIGRlIHZhbG9yIGlndWFsIG8gbWVub3IgcXVlIDMgY29tbyBlc3TDoW4sIHB1ZXMgZXhpc3RlIG1heW9yDQpwcm9iYWJpbGlkYWQgZGUgcXVlIHNpIGV4aXN0YW4uIEVuIGN1YW50byBhIGxvcyAqQXBhcnRhbWVudG9zKiBzaW4gdmFsb3INCmVuIHBpc28sIGxvcyBlbGltaW5hcmVtb3MgZGVsIGNvbmp1bnRvIGRlIGRhdG9zLiBFbiBjdWFudG8gYSBsb3MgbsO6bWVyb3MNCmFsdG9zIGRlIGxhIHZhcmlhYmxlIHBpc28gZW4gbG9zIHJlZ2lzdHJvcyBkZSB0aXBvICpBcGFydGFtZW50byosIG5vDQp0ZW5lbW9zIHJhesOzbiBwYXJhIGR1ZGFyIGRlIGVsbG9zLCBsdWVnbyBsb3MgZGVqYXJlbW9zIGNvbW8gZXN0w6FuLg0KDQpWZWFtb3MgY29tbyBxdWVkYSBlbCBkYXRhc2V0IGVuIGVzdGFzIGRvcyB2YXJpYWJsZXMgZGVzcHXDqXMgZGUgaGFjZXIgZWwNCmNhbWJpbzoNCg0KYGBge3IgcGlzb19ncmVhdGVyX3RoYW5fM30NCmRmJHBpc28gPC0gaWZlbHNlKChkZiRwaXNvID4gMyB8IGlzLm5hKGRmJHBpc28pKSAgJiBkZiR0aXBvID09ICJDYXNhIiwgMSwgZGYkcGlzbykNCmRmIDwtIGZpbHRlcihkZiwhaXMubmEoZGYkcGlzbykpDQptaXNzaW5nX2RhdGEgPC0gY29sU3Vtcyhpcy5uYShkZikpICU+JQ0KICAgICAgICAgICAgICAgICBhcy5kYXRhLmZyYW1lKCkgDQoNCm1pc3NpbmdfZGF0YQ0KYGBgDQoNCkFob3JhLCBhbmFsaWNlbW9zIGxvcyB2YWxvcmVzIGRlIGxhIHZhcmlhYmxlICoqcGFycXVlYSoqLCBxdWUgb2ZyZWNlIGxvcw0KdmFsb3JlcyBkZSBsYSBjYW50aWRhZCBkZSBwYXJxdWVhZGVyb3MgZGUgdW4gaW5tdWVibGUuIEVzdGEgZXMgbGEgb3RyYQ0KdmFyaWFibGUgcXVlIHRpZW5lIHZhbG9yZXMgZW4gTkEuDQoNCmBgYHtyIHBhcnF1ZWF9DQp0YWJsZShkZiRwYXJxdWVhLGRmJGVzdHJhdG8sZGYkdGlwbyApDQpgYGANCg0KU2Vnw7puIGVzdG8sIGhheSB2YXJpb3MgaW5tdWVibGVzIHF1ZSB0aWVuZW4gZGVzZGUgNSBoYXN0YSAxMA0KcGFycXVlYWRlcm9zLCB2YWxvcmVzIHF1ZSBub3MgaGFjZW4gZHVkYXIgZGUgc3UgdmVyYWNpZGFkLiBQYXJhIGNpZXJ0b3MNCnRpcG9zIGNhc2FzLCBlcyBtw6FzIHBvc2libGUgcXVlIHRlbmdhbiBtdWNob3MgImx1Z2FyZXMgZG9uZGUgcGFycXVlYXIiDQphdW5xdWUgdMOpY25pY2FtZW50ZSBubyBzZWFuIHBhcnF1ZWFkZXJvcyBjdWJpZXJ0b3MuIFlvIGRlc2NvbmZpYXLDrWEgZGUNCmxvcyB2YWxvcmVzIG1heW9yZXMgZGUgNCBpbmNsdXNpdmUgcGFyYSBsYXMgY2FzYXMuIFZlbW9zIGVuIGxhcyB0YWJsYXMNCnF1ZSBwYXJhIGxvcyBhcGFydGFtZW50b3MsIHNvbG8gaGF5IDYgcXVlIHRpZW5lbiB2YWxvcmVzIG1heW9yZXMgYSA0LiBTZQ0KdmFuIGEgZWxpbWluYXIuIEVuIGN1YW50byBhIGxhcyBjYXNhcywgaGF5IG11Y2hvcyBtw6FzIHJlZ2lzdHJvcyBjb24NCnZhbG9yZXMgYWx0b3MgKCoqcGFycXVlYSoqIFw+IDQpLiBQYXJhIGVsaW1pbmFyIGxvcyB2YWxvcmVzIGF0w61waWNvcywNCnZhbW9zIGEgYXNpZ25hcmxlcyBlbCB2YWxvciBkZSA0IGEgZGljaG9zIHJlZ2lzdHJvcy4gRW4gY3VhbnRvIGEgbG9zIHF1ZQ0Kbm8gdGllbmVuIGRhdG8sIHZhbW9zIGEgYXN1bWlyIHF1ZSBubyB0aWVuZW4gcGFycXVlYWRlcm8sIHBvciBsbyB0YW50bw0KbGVzIHBvbmRyZW1vcyBlbCB2YWxvciBkZSBjZXJvLg0KDQpgYGB7ciBwYXJxdWVhX2dyZWF0ZXJfdGhhbl80fQ0KZGYkcGFycXVlYSA8LSBpZmVsc2UoZGYkcGFycXVlYSA+IDQsIDQsICBkZiRwYXJxdWVhKQ0KZGYkcGFycXVlYSA8LSBpZmVsc2UoaXMubmEoZGYkcGFycXVlYSksIDAsIGRmJHBhcnF1ZWEpDQp0YWJsZShkZiRwYXJxdWVhLGRmJGVzdHJhdG8sZGYkdGlwbyApDQpzdW0oaXMubmEoZGYkcGFycXVlYSkpDQpgYGANCg0KQWhvcmEgdmVhbW9zIHNpIGVsIGNvbmp1bnRvIHRpZW5lIGRhdG9zIGZhbHRhbnRlcy4NCg0KYGBge3IgbWlzc2luZ19kYXRhX2FmdGVyfQ0KVklNOjphZ2dyKGRmLCBjZXguYXhpcyA9IDAuNSwgY2V4LmxhYj0gMC44KSANCmBgYA0KDQpTZSBwdWVkZSB2ZXJpZmljYXIgcXVlIHlhIG5vIHRpZW5lIGRhdG9zIGZhbHRhbnRlcyBlbiBsYXMgdmFyaWFibGVzLg0KDQojIyMgMy4yLjMuIEFuw6FsaXNpcyB5IGxpbXBpZXphIGRlIHJlZ2lzdHJvcyBjb24gdmFsb3JlcyBhdMOtcGljb3MNCg0KSGFiaWVuZG8gZWxpbWluYWRvIGRlbCBkYXRhc2V0IHRvZG9zIGxvcyByZWdpc3Ryb3MgY29uIGRhdG9zIHZhY8Otb3MsDQphaG9yYSB2YW1vcyBhIGFuYWxpemFyIGxhcyBvdHJhcyB2YXJpYWJsZXMgZGVsIGNvbmp1bnRvLiBWaXN1YWxpemFyZW1vcw0KZW4gZ3LDoWZpY29zIGRlIGNhamFzIHkgYmlnb3RlcyBsYSBkaXN0cmlidWNpw7NuIGRlIGxhcyB2YXJpYWJsZXMNCm51bcOpcmljYXMuDQoNCmBgYHtyIGJsb3hfcGxvdH0NCm51bWVyaWNfY29sdW1ucyA8LSBuYW1lcyhkZilbc2FwcGx5KGRmLCBpcy5udW1lcmljKV0NCm5vX2NvbHVtbnMgPC0gYygicGlzbyIsImVzdHJhdG8iLCJwYXJxdWVhIikNCm51bWVyaWNfY29sdW1ucyA8LSBzZXRkaWZmKG51bWVyaWNfY29sdW1ucywgbm9fY29sdW1ucykNCmxhcHBseShudW1lcmljX2NvbHVtbnMsIGZ1bmN0aW9uKHZhcmlhYmxlKSB7DQogIGdncGxvdChkZiwgYWVzX3N0cmluZyh4ID0gdmFyaWFibGUpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIGxhYnModGl0bGUgPSBwYXN0ZTAoIkJveHBsb3QgcGFyYSBsYSBjb2x1bW5hOiAiLCB2YXJpYWJsZSkpDQp9KQ0KYGBgDQoNClBvZGVtb3MgdmVyIHF1ZSBsYXMgdmFyaWFibGVzICoqcHJlY2lvbSoqIHkgKiphcmVhY29uc3QqKiB0aWVuZW4gdW5hDQpncmFuIGNhbnRpZGFkIGRlIHZhbG9yZXMgYXTDrXBpY29zLCB5IHRhbWJpw6luIHF1ZSBzZWfDum4gbG9zIGRhdG9zLCBoYXkNCmlubXVlYmxlcyBjb24gOCwgOSB5IDEwIGJhw7FvcywgYXPDrSBjb21vIHRhbWJpw6luIGNvbiAwIGhhYml0YWNpb25lcyBvIGNvbg0KaGFzdGEgMTAgaGFiaXRhY2lvbmVzLiBFbiBjdWFudG8gYSBsYXMgdmFyaWFibGVzICoqbG9uZ2l0dWQqKiB5DQoqKmxhdGl0dWQqKiwgc2UgcmVjdWVyZGEgcXVlIGVzdGFzIGZ1ZXJvbiBlbGltaW5hZGFzIGRlbCBjb25qdW50byBkZSBkYXRvcywgcHVlcyBhbCBwYXJlY2VyIGhhYsOtYSBlcnJvcmVzIGVuIGxvcyBkYXRvcywgcHVlcyBzdQ0KZGlzdHJpYnVjacOzbiwgYWwgc2VyIGxvcyBkYXRvcyBkZSBpbm11ZWJsZXMgZW4gdW5hIG1pc21hIGNpdWRhZCwNCmRlYmVyw61hbiBzZXIgbXV5IHNpbWlsYXJlcyB5IG5vIGNvbiBkaWZlcmVuY2lhcyB0YW4gZ3JhbmRlcyBlbnRyZSBzdXMNCnZhbG9yZXMuDQoNClZhbW9zIGVudG9uY2VzIGEgcmV2aXNhciBzaSBsb3MgdmFsb3JlcyBkZSBlc3RhcyB2YXJpYWJsZXMgcGFyYSBlc29zDQpyZWdpc3Ryb3Mgc29uIGNvaGVyZW50ZXMsIHBvciBlamVtcGxvLCBsYXMgY2FzYXMgY29uIG11Y2hvcyBiYcOxb3Mgbw0KbXVjaGFzIGhhYml0YWNpb25lcyBkZWJlcsOtYW4gc2VyIGxhcyBjYXNhcyBjb24gdW4gw6FyZWEgY29uc3RydWlkYSBtYXlvcg0KeSB0YW1iacOpbiBjb24gbcOhcyBhbHRvcyBwcmVjaW9zLg0KDQpBbnRlcyBkZSBwcm9mdW5kaXphciBlbiBlbCBhbsOhbGlzaXMsIGVsaW1pbmFyZW1vcyBsb3MgcmVnaXN0cm9zIGNvbg0KZGF0b3Mgbm8gbMOzZ2ljb3MsIGNvbW8gYXJlYWNvbnN0ID0gMCwgaGFiaXRhYyA9IDAgbyBiYcOxb3MgPSAwLg0KDQpgYGB7ciBkZWxldGVfaWxvZ2ljYWxfcmVjb3Jkc30NCmRmIDwtIGZpbHRlcihkZiwgZGYkYmFuaW9zICE9IDApDQpkZiA8LSBmaWx0ZXIoZGYsIGRmJGhhYml0YWMgIT0gMCkNCmRmIDwtIGZpbHRlcihkZiwgZGYkYXJlYWNvbnN0ICE9IDApDQpgYGANCg0KYGBge3Igb3V0bGllcnNffQ0KbnVtZXJpY19jb2x1bW5zIDwtIG5hbWVzKGRmKVtzYXBwbHkoZGYsIGlzLm51bWVyaWMpXQ0KZXhjbHVkZV9jb2x1bW5zIDwtIGMoInBpc28iLCJlc3RyYXRvIiwicGFycXVlYSIpICMsImxvbmdpdHVkIiwgImxhdGl0dWQiKQ0KbnVtZXJpY19jb2x1bW5zIDwtIHNldGRpZmYobnVtZXJpY19jb2x1bW5zLCBleGNsdWRlX2NvbHVtbnMpDQpjb3ZfbWF0cml4IDwtIGNvdihkZlssIG51bWVyaWNfY29sdW1uc10pDQphdGlwaWNvcyA8LSBtYWhhbGFub2JpcyhkZlssIG51bWVyaWNfY29sdW1uc10sIGNlbnRlciA9IFRSVUUsIGNvdiA9IGNvdl9tYXRyaXgpDQpsZW5ndGgoYXRpcGljb3MpDQoNCmBgYA0KDQpWZWFtb3MgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyB2YXJpYWJsZXMgKipwcmVjaW9tKiosICoqYmFuaW9zKiosDQoqKmFyZWFjb25zdCoqIHkgKipoYWJpdGFjKiouIFNlIGVzcGVyYSBxdWUgZW50cmUgbcOhcyDDoXJlYSBjb25zdHJ1aWRhLCBlbA0KdmFsb3Igc2VhIG3DoXMgYWx0bywgbyBxdWUgZW50cmUgbcOhcyBoYWJpdGFjaW9uZXMgZXhpc3RhbiwgaGF5YW4gbcOhcw0KYmHDsW9zLCB5IGRlIGlndWFsIG1hbmVyYSwgcXVlIGVudHJlIG3DoXMgaGFiaXRhY2lvbmVzIHkgYmHDsW9zLCBtw6FzIMOhcmVhDQpjb25zdHJ1aWRhIHRlbmdhLCBhbCBpZ3VhbCBxdWUgbWF5b3Igc2VhIGVsIHByZWNpby4gQ29tcG9ydGFtaWVudG9zDQpkaWZlcmVudGVzIGEgZXN0b3MsIHNpIGJpZW4gcHVlZGVuIHNlciBwb3NpYmxlcyBlbiBsYSBwcsOhY3RpY2EsIHNvbiBwb2NvDQpwcm9iYWJsZXMgeSBhbHRlcmFuIGxhIGhvbW9nZW5laWRhZCBkZSBsb3MgZGF0b3MuIFBhcmEgZXN0ZSBlc3R1ZGlvLCBzaQ0Kc29uIHBvY29zIGVzdG9zIHZhbG9yZXMgYXTDrXBpY29zLCBzZSBlbGltaW5hcsOhbi4NCg0KU2UgcmVwcmVzZW50YXLDoW4gZ3LDoWZpY2FtZW50ZSBsYXMgKipkaXN0YW5jaWFzIGRlIE1haGFsYW5vYmlzLCoqIHF1ZSBlcyB1bmENCiptZWRpZGEgZGUgbGEgZGlzdGFuY2lhIGVudHJlIHVuIHB1bnRvIHkgdW5hIGRpc3RyaWJ1Y2nDs24gbXVsdGl2YXJpYW50ZS4qDQpFcyB1bmEgbWVkaWRhIMO6dGlsIHBhcmEgZGV0ZWN0YXIgdmFsb3JlcyBhdMOtcGljb3MgZW4gdW4gY29uanVudG8gZGUNCmRhdG9zIG11bHRpZGltZW5zaW9uYWwuIExhIGRpc3RhbmNpYSBlcyB1bmEgbWVkaWRhIGRlIGxhIGRpc3RhbmNpYSBlbg0KdW5pZGFkZXMgZGUgZGVzdmlhY2lvbmVzIGVzdMOhbmRhciwgcG9yIGxvIHRhbnRvLCB1biB2YWxvciBhbHRvIGRlIGxhDQpkaXN0YW5jaWEgaW5kaWNhIHF1ZSBlbCBwdW50byBlc3RhIGxlam9zIGRlIGxhIGRpc3RyaWJ1Y2nDs24NCm11bHRpdmFyaWFudGUuIFTDrXBpY2FtZW50ZSwgbG9zIHB1bnRvcyBjb24gdW5hIGRpc3RhbmNpYSBtYXlvciBhIDMgc2UNCmNvbnNpZGVyYW4gYXTDrXBpY29zLiBMYSBkaXN0YW5jaWEgTWFoYWxhbm9iaXMgbm8gc2UgYWZlY3RhIHBvciBsYSBlc2NhbGENCmRlIGxhcyB2YXJpYWJsZXMgeSBlcyBzZW5zaWJsZSBhIGxhIGNvcnJlbGFjacOzbiBlbnRyZSBsYXMgdmFyaWFibGVzLg0KDQpgYGB7ciBNYWhhbGFub2Jpc19kaXN0YW5jZV9wcmljZV9hcmVhfQ0KDQojZ2dwbG90KGRmLCBhZXNfc3RyaW5nKHggPSAicHJlY2lvbSIsIHkgPSAiYXJlYWNvbnN0IiwgY29sb3IgPSAiYXRpcGljb3MiKSkgKw0KIyAgZ2VvbV9wb2ludCgpICsNCiMgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXMobG93ID0gIndoaXRlIiwgaGlnaCA9ICJibHVlIikgKw0KIyAgbGFicyh4ID0gIlByZWNpbyIsIHkgPSAiw4FyZWEgY29uc3RydWlkYSIsIGNvbG9yID0gIkRpc3RhbmNpYSBkZSBNYWhhbGFub2JpcyIpDQoNCmdncGxvdChkZiwgYWVzX3N0cmluZyh4ID0gJ3ByZWNpb20nLCB5ID0gJ2FyZWFjb25zdCcsIGNvbG9yID0gJ2F0aXBpY29zJykpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgc2NhbGVfY29sb3JfY29udGludW91cyhsb3cgPSAid2hpdGUiLCBoaWdoID0gImJsdWUiKSArDQogIGxhYnMoeCA9ICJQcmVjaW8iLCB5ID0gIkFyZWEgY29uc3RydWlkYSIsIGNvbG9yID0gIkRpc3RhbmNpYSBkZSBNYWhhbGFub2JpcyIpDQoNCg0KYGBgDQoNCkVuIGVsIGdyw6FmaWNvIGFudGVyaW9yIHNlIHB1ZWRlbiB2ZXIgYWxndW5vcyBkYXRvcyBxdWUgbm8gc29uIGzDs2dpY29zDQpwdWVzIHNlIGFzdW1lIHVuYSByZWxhY2nDs24gZGlyZWN0YW1lbnRlIHByb3BvcmNpb25hbCBlbnRyZSBlbCBwcmVjaW8geQ0KZWwgw6FyZWEgY29uc3RydWlkYSBkZSB1bmEgY2FzYS4gUG9yIGVqZW1wbG8sIGhheSB1biByZWdpc3RybyBkZSAxNzUwDQptZXRyb3MgY3VhZHJhZG9zIGNvbnN0cnVpZG9zIGNvbiB1biB2YWxvciBkZSAyNTAgbWlsbG9uZXMuIFNlIGVzcGVyYXLDrWENCnF1ZSBwYXJhIHVuIMOhcmVhIHRhbiBncmFuZGUsIGVsIHByZWNpbyBlc3R1dmllcmEgZW50cmUgbG9zIG3DoXMgYWx0b3MgeQ0KcG9yIGVsIGNvbnRyYXJpbyBlc3TDoSBlbnRyZSBsb3MgbcOhcyBiYWpvcy4gVGFtYmnDqW4gc2UgdmUgZWwgY2Fzbw0KY29udHJhcmlvLCBlbiBlbCBxdWUgZWwgcHJlY2lvIGVzIG11eSBhbHRvIHBhcmEgdGFuIHBvY2Egw6FyZWENCmNvbnN0cnVpZGEuIEF1bnF1ZSBubyBzZSBlc3TDoW4gdGVuaWVuZG8gZW4gY3VlbnRhIG90cmFzIHZhcmlhYmxlcywgY29tbw0KcG9yIGVqZW1wbG8gZWwgZXN0cmF0byBvIGVsIGJhcnJpbywgc2llbXByZSBoYXkgdW5hIHJlbGFjacOzbiBkaXJlY3RhDQplbnRyZSBlbCB0YW1hw7FvIHkgZWwgdmFsb3IgcXVlIGRlYmUgY29uc2lkZXJhcnNlLiBFbiB1biBlc3R1ZGlvIG3DoXMNCmRldGFsbGFkbyBzZSBwb2Ryw61hbiB0ZW5lciBlbiBjdWVudGEgbG9zIGNydWNlcyBlbnRyZSBlc3RhcyBjdWF0cm8NCnZhcmlhYmxlcyBtZW5jaW9uYWRhcywgbyBpbmNsdXNpdmUgdGFtYmnDqW4gY29uIGxhIGNhbnRpZGFkIGRlIGJhw7FvcyB5IGRlDQpoYWJpdGFjaW9uZXMuDQoNCmBgYHtyIE1haGFsYW5vYmlzX2Rpc3RhbmNlX2JhdGhyb29tc19hcmVhfQ0KDQoNCmdncGxvdChkZiwgYWVzX3N0cmluZyh4ID0gImJhbmlvcyIsIHkgPSAiYXJlYWNvbnN0IiwgY29sb3IgPSAiYXRpcGljb3MiKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvcl9jb250aW51b3VzKGxvdyA9ICJ3aGl0ZSIsIGhpZ2ggPSAiYmx1ZSIpICsNCiAgbGFicyh4ID0gIkJhw7FvcyIsIHkgPSAiw4FyZWEgY29uc3RydWlkYSIsIGNvbG9yID0gIkRpc3RhbmNpYSBkZSBNYWhhbGFub2JpcyIpDQoNCmBgYA0KDQpTZSBvYnNlcnZhIHF1ZSBoYXkgdW5vcyByZWdpc3Ryb3MgY29uIG11Y2hhIMOhcmVhIGNvbnN0cnVpZGEgeSBwb2Nvcw0KYmHDsW9zLCBjb21vIGVzIGVsIGNhc28gZGVsIHJlZ2lzdHJvIHF1ZSBpbmRpY2EgMTc1MCBtZXRyb3MgY29uc3RydWlkb3MgeQ0KMyBiYcOxb3MuIFNlIGVsbWluYXLDoSBlc3RlIHJlZ2lzdHJvLg0KDQpgYGB7ciBkZWxldGVfMTc1MH0NCmRmIDwtIGZpbHRlcihkZiwgZGYkYXJlYWNvbnN0ICE9IDE3NTApDQpgYGANCg0KVmVhbW9zIGxhIHJlbGFjacOzbiBlbnRyZSBsYSBjYW50aWRhZCBkZSBoYWJpdGFjaW9uZXMgeSBsYSBjYW50aWRhZCBkZQ0KYmHDsW9zLiBTZSBlc3BlcmEgcXVlIGVudHJlIG3DoXMgaGFiaXRhY2lvbmVzLCBtw6FzIGJhw7FvcyBoYXlhIGVuIGVsDQppbm11ZWJsZS4NCg0KYGBge3IgTWFoYWxhbm9iaXNfZGlzdGFuY2Vfcm9vbXNfYmF0aHJvb21zfQ0KZ2dwbG90KGRmLCBhZXNfc3RyaW5nKHggPSAiaGFiaXRhYyIsIHkgPSAiYmFuaW9zIiwgY29sb3IgPSAiYXRpcGljb3MiKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvcl9jb250aW51b3VzKGxvdyA9ICJ3aGl0ZSIsIGhpZ2ggPSAiYmx1ZSIpICsNCiAgbGFicyh4ID0gIkhhYml0YWNpb25lcyIsIHkgPSAiQmHDsW9zIiwgY29sb3IgPSAiRGlzdGFuY2lhIGRlIE1haGFsYW5vYmlzIikNCg0KZ2dwbG90KGRmLCBhZXNfc3RyaW5nKHggPSAiaGFiaXRhYyIsIHkgPSAiYXJlYWNvbnN0IiwgY29sb3IgPSAiYXRpcGljb3MiKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvcl9jb250aW51b3VzKGxvdyA9ICJ3aGl0ZSIsIGhpZ2ggPSAiYmx1ZSIpICsNCiAgbGFicyh4ID0gIkhhYml0YWNpb25lcyIsIHkgPSAiQXJlYSIsIGNvbG9yID0gIkRpc3RhbmNpYSBkZSBNYWhhbGFub2JpcyIpDQpgYGANCg0KQXBhcmVjZSB1biBjYXNvIGRvbmRlIGhheSAzIGhhYml0YWNpb25lcyB5IDEwIGJhw7Fvcy4gVGFtYmnDqW4sIGVuIGVsDQpncsOhZmljbyBhbnRlcmlvciwgaW5tdWVibGVzIGNvbiAxMCBiYcOxb3MgeSBtZW5vcyBkZSA0MDAgbWV0cm9zIGRlIMOhcmVhDQpjb25zdHJ1aWRhLiBFc3RvcyBzZSBlbGltaW5hcsOhbi4NCg0KYGBge3IgZGVsX3Rvb19tYW55X2JhdGhyb29tc19mZXdfb3RoZXJzfQ0KZGYgPC0gZmlsdGVyKGRmLCAhKGRmJGJhbmlvcyA9PSAxMCAmIGRmJGFyZWFjb25zdCA8PSA0MDApKQ0KYGBgDQoNCmBgYHtyIHJlbGF0aW9uc30NCnRhYmxlKGRmJGJhbmlvcyxkZiRoYWJpdGFjKQ0KYGBgDQoNCkRlIGlndWFsIG1hbmVyYSwgc2Ugb2JzZXJ2YSB1bmEgYXBhcmVudGUgZGlzcGFyaWRhZCBlbnRyZSBsYSBjYW50aWRhZCBkZQ0KYmHDsW9zIHkgZWwgw6FyZWEgY29uc3RydWlkYS4gQXVucXVlIGVzIHBvc2libGUgcXVlIGhheWEgcG9jb3MgYmHDsW9zIGVuDQp1bmEgY2FzYSBncmFuZGUsIGVzdG8gZXMgcG9jbyBwcm9iYWJsZS4gVGFsIHZleiB1bmEgbWF5b3IgcmVsYWNpw7NuIGxhDQp0aWVuZW4gbGFzIHZhcmlhYmxlcyBxdWUgcmVwcmVzZW50YW4gbGFzIGNhbnRpZGFkZXMgZGUgYmHDsW9zIHkgZGUNCmhhYml0YWNpb25lcywgcHVlcyBsYXMgaGFiaXRhY2lvbmVzIGRhbiB1bmEgaWRlYSBkZSBsYSBjYW50aWRhZCBkZQ0KcGVyc29uYXMgcXVlIHZpdmVuIG8gdXNhbiBsYSBjYXNhLCBsbyBjdWFsIG11ZXN0cmEgbGEgbmVjZXNpZGFkIGRlIG3DoXMgbw0KbWVub3MgYmHDsW9zLg0KDQpFbiB1biBncsOhZmljbyBhbnRlcmlvciBzZSB2ZSB0YW1iacOpbiBxdWUgaGF5IGNhc2FzIGRlIDAgbWV0cm9zIGNvbnN0cnVpZG9zIGNvbg0KdmFyaWFzIGhhYml0YWNpb25lcywgbG8gY3VhbCBubyBlcyBwb3NpYmxlLiBFc3RvcyByZWdpc3Ryb3Mgc2UNCmVsaW1pbmFyw6FuLiBZIHRhbWJpw6luIGhheSByZWdpc3Ryb3MgZGUgaW5tdWVibGVzIGVuIGVsIGNvbmp1bnRvIGNvbg0KbXVjaG9zIG3DoXMgYmHDsW9zIHF1ZSBoYWJpdGFjaW9uZXMsIGVuIHVuYSBwcm9wb3JjacOzbiBkZSAyIGEgMSBlDQppbmNsdXNpdmUgZGUgMyBhIDEuIEVsaW1pbmFyZW1vcyBlc3RvcyByZWdpc3Ryb3MgcHJvYmxlbcOhdGljb3MgZGFkbyBxdWUNCm5vIGVzIG11Y2hhIGxhIGNhbnRpZGFkIGRlIGVsbG9zLg0KDQojIyMgMy4yLjQuIEhvbW9nZW5pemFjacOzbiBkZSB2YXJpYWJsZXMgY3VhbGl0YXRpdmFzDQoNClNlIHJldmlzYXJvbiBsb3MgdmFsb3JlcyBkZSBsYXMgdmFyaWFibGVzICoqYmFycmlvKiogeSAqKnpvbmEqKi4gU2Ugbm90w7MNCnF1ZSBsb3Mgbm9tYnJlcyBkZSBsYXMgem9uYXMgZXN0w6FuIHRvZG9zIGJpZW4gZXNjcml0b3MsIHBlcm8gcXVlIGVuIGxvcw0Kbm9tYnJlcyBkZSBsb3MgYmFycmlvcyBoYXkgYWxndW5vcyByZWdpc3Ryb3MgcXVlIHNlIHJlZmllcmVuIGFsIG1pc21vDQpiYXJyaW8gcGVybyBxdWUgZXN0w6FuIGVzY3JpdG9zIGRlIG1hbmVyYSBkaWZlcmVudGUsIGNvbW8gcG9yIGVqZW1wbG86DQoiYWxmb25zbyBsb3BleiIgeSAiYWxmb256byBMw7NwZXoiLiBUYW1iacOpbiBzZSBub3RhIHF1ZSBoYXkgbXVjaG9zDQpiYXJyaW9zIGRvbmRlIHNvbG8gaGF5IHVuIGlubXVlYmxlIGEgbGEgdmVudGEuIENvbiB0YW4gYmFqYQ0KcmVwcmVzZW50YXRpdmlkYWQsIG5vIGVzIHBvc2libGUgaGFjZXIgaW5mZXJlbmNpYXMgZW4gY3VhbnRvIGEgbGENCnNpdHVhY2nDs24gZGUgbG9zIGlubXVlYmxlcyBlbiBsb3MgYmFycmlvcy4gSGFicsOtYSBxdWUgdXNhciBsYSB6b25hIHF1ZQ0KYWwgc2VyIHNvbG8gNSwgdGllbmVuIG3DoXMgaW5tdWVibGVzIGVuIGVsbGFzLg0KDQpDb3JyZWdpbW9zIGxvcyBub21icmVzIGRlIGFsZ3Vub3MgZGUgbG9zIGJhcnJpb3MgcGFyYSB2ZXIgc3VzIGVmZWN0b3MgZW4NCmVsIGRhdGFzZXQsIHNpbiBlbWJhcmdvLCBzZSBub3RhIHF1ZSBzaWd1ZSBoYWJpZW5kbyBtdWNob3MgYmFycmlvcyBjb24NCnRhbiBzb2xvIHVuIGlubXVlYmxlIHkgcXVlIGFkZW3DoXMgc29uIGFscmVkZWRvciBkZSAzNTAgeSBhbGd1bm9zIGVzdMOhbg0KcG9zaWJsZW1lbnRlIG1hbCByZWZlcmVuY2lhZG9zLCBjb21vIGVsIHF1ZSBkaWNlICJjYWxpIiBvIGVsIHF1ZSBoYWNlDQpyZWZlcmVuY2lhIGFsIG5vbWJyZSBkZSB1biBlZGlmaWNpby4gVGFtYmnDqW4gc2UgdmUgcXVlIGVzdMOhbg0KcmVmZXJlbmNpYWRhcyBsYXMgem9uYXMgZW4gbG9zIGJhcnJpb3MuIEVuIGRlZmluaXRpdmEsIGVzdGEgdmFyaWFibGUNCnJlcXVlcmlyw61hIGRlIG11Y2hhIGxpbXBpZXphIGUgaW52ZXN0aWdhY2nDs24gcGFyYSBzZXIgZGVwdXJhZGEsIHkNCnRlbmllbmRvIHRhbWJpw6luIGVycm9yZXMgZW4gbGEgbG9uZ2l0dWQgeSBsYXRpdHVkLCBubyBzZSBwdWVkZSBpbXB1dGFyIGENCnBhcnRpciBkZSBsb3MgZGF0b3MgZXhpc3RlbnRlcy4NCg0KYGBge3IgbmVpZ2hib3Job29kc30NCnVuaXF1ZShkZiR6b25hKQ0KZGYkYmFycmlvIDwtIHRvbG93ZXIoZGYkYmFycmlvKQ0KYmFycmlvcyA9IHVuaXF1ZShkZiRiYXJyaW8sIGRlY3JlYXNpbmcgPSBUUlVFKQ0KI3RhYmxlKGRmJGJhcnJpbywgc29ydCA9IFRSVUUpDQojYmFycmlvcw0KDQpkZiRiYXJyaW8gPC0gaWZlbHNlKGRmJGJhcnJpbyA9PSAiYWxm4oiawqlyZXogcmVhbCIsICJhbGZlcmV6IHJlYWwiLCBpZmVsc2UoZGYkYmFycmlvID09ICJhbGZvbnNvIGzDs3BleiIsICJhbGZvbnNvIGxvcGV6IiwgaWZlbHNlKGRmJGJhcnJpbyA9PSAiYmFzZSBh4oiawqlyZWEiLCAgImJhc2UgYWVyZWEiLCBpZmVsc2UoZGYkYmFycmlvID09ICJtZWziiJrCqW5kZXoiLCAgIm1lbGVuZGV6IiwgaWZlbHNlKGRmJGJhcnJpbyA9PSAibWVs4oiawqluZGV6IiwgICJtZWxlbmRleiIsIGlmZWxzZShkZiRiYXJyaW8gPT0gIm1lbOKImsKpbmRleiIsICAibWVsZW5kZXoiLCBpZmVsc2UoZGYkYmFycmlvID09ICJsYSBhcmJvbGVkYSIsICAiYXJib2xlZGEiLCBpZmVsc2UoZGYkYmFycmlvID09ICJsb3MgYWxjw6F6YXJlcyIsICAibG9zIGFsY2F6YXJlcyIsIGlmZWxzZShkZiRiYXJyaW8gPT0gImxhIHJpdmVyYSBpIiwgICJsYSByaXZlcml0YSIsIGlmZWxzZShkZiRiYXJyaW8gPT0gImxhZmxvcmEiLCAgImxhIGZsb3JhIiwgaWZlbHNlKGRmJGJhcnJpbyA9PSAibGEgcml2ZXJhIGlpIiwgICJsYSByaXZlcml0YSIsIGlmZWxzZShkZiRiYXJyaW8gPT0gImxhIHJpdmVyYSIsICAibGEgcml2ZXJpdGEiLCBpZmVsc2UoZGYkYmFycmlvID09ICJjaXVkYWRlbGEgcGFzbyBhbmNobyIsICAiY2l1ZGFkZWxhIHBhc29hbmNobyIsIGlmZWxzZShkZiRiYXJyaW8gPT0gImNhbmV5IGVzcGVjaWFsIiwgICJjYW5leSIsIGlmZWxzZShkZiRiYXJyaW8gPT0gImVsIGluZ2VuaW8gaSIsICAiaW5nZW5pbyIsIGlmZWxzZShkZiRiYXJyaW8gPT0gImVsIGluZ2VuaW8gaWkiLCAgImluZ2VuaW8iLCBpZmVsc2UoZGYkYmFycmlvID09ICJlbCBpbmdlbmlvIiwgICJpbmdlbmlvIiwgaWZlbHNlKGRmJGJhcnJpbyA9PSAiZWwgaW5nZW5pbyBpaWkiLCAgImVsIGluZ2VuaW8iLCBpZmVsc2UoZGYkYmFycmlvID09ICJqYW11bmRpIGFsZmFndWFyYSIsICAiYWxmYWd1YXJhIiwgaWZlbHNlKGRmJGJhcnJpbyA9PSAiY2FsaSBjYW50byB2aWlpIiwgICJjYWxpY2FudG8iLCBpZmVsc2UoZGYkYmFycmlvID09ICJjYWxpIGNhbnRvIiwgICJjYWxpY2FudG8iLCBpZmVsc2UoZGYkYmFycmlvID09ICJjaGltaW5hbmdvcyAxIGV0YXBhIiwgICJjaGltaW5hbmdvcyIsIGlmZWxzZShkZiRiYXJyaW8gPT0gImNoaW1pbmFuZ29zIDIgZXRhcGEiLCAgImNoaW1pbmFuZ29zIiwgaWZlbHNlKGRmJGJhcnJpbyA9PSAiY3Jpc3TDs2JhbCBjb2zDs24iLCAgImNyaXN0b2JhbCBjb2zDs24iLCBpZmVsc2UoZGYkYmFycmlvID09ICJtYXJyb3F1aW4gaWlpIiwgICJtYXJyb3F1aW4iLCBpZmVsc2UoZGYkYmFycmlvID09ICJlbCBpbmdlbmlvIDMiLCAgImVsIGluZ2VuaW8iLCBkZiRiYXJyaW8pKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKQ0KDQp0YWJsZShkZiRiYXJyaW8pDQpgYGANCg0KVmVvIHF1ZSBhIHBlc2FyIGRlIHF1ZSBzZSBoYW4gZXN0YW5kYXJpemFkbyBhbGd1bm9zIG5vbWJyZXMsIGVzdG9zIHkNCm90cm9zIHNpZ3VlbiB0ZW5pZW5kbyBwb2NvcyBpbm11ZWJsZXMuIEF1bnF1ZSBlbiB1biBhbsOhbGlzaXMgbcOhcw0KcHJvZnVuZG8gbyBkaWZlcmVudGUgZWwgYmFycmlvIHBvZHLDrWEgc2VyIG5lY2VzYXJpbywgcGFyYSBlc3RhIG9jYXNpw7NuLA0KdXNhcmVtb3MgcGFyYSBjdWFscXVpZXIgYW7DoWxpc2lzIGxhIHZhcmlhYmxlIHpvbmEgY29uIGxhIHNpZ3VpZW50ZQ0KZGlzdHJpYnVjacOzbi4gRWwgYmFycmlvIHNlIGVsaW1pbmFyw6EgZGVsIGRhdGFzZXQuDQoNCmBgYHtyIGRlbGV0ZV9uZWlnaGJvcn0NCmRmJGJhcnJpbyA8LSBOVUxMDQpgYGANCg0KIyMjIDMuMi41LiBSZXN1bWVuIGRlIFZhcmlhYmxlcyB5IGRhdG9zIGVsaW1pbmFkb3MNCg0KVGFsIGNvbW8gaGVtb3MgdmlzdG8gZW4gZWwgYW7DoWxpc2lzLCBhbGd1bmFzIGRlIGxhcyB2YXJpYWJsZXMgbm8gc2UNCnV0aWxpemFyw6FuIGNvbW8gcGFydGUgZGVsIGVzdHVkaW8uIEVzdGFzIHZhcmlhYmxlcyBzb246DQoNCi0gaWQgDQotIGxhdGl0dWQgDQotIGxvbmdpdHVkIA0KLSBiYXJyaW8gDQoNCkxhcyByYXpvbmVzIHF1ZSBzZSB0dXZpZXJvbiBlbiBjdWVudGEgcGFyYSBzdSBlbGltaW5hY2nDs24gc29uOiANCg0KLSBJbmZvcm1hY2nDs24gaW1wcm9jZWRlbnRlIHBhcmEgdW4gYW7DoWxpc2lzIGVzdGFkw61zdGljbywgY29tbyBlbiBlbCBjYXNvIGRlbCBpZC4gDQotIEluZm9ybWFjacOzbiBjb24gbXVjaG9zIGVycm9yZXMsIHZhbG9yZXMgYXTDrXBpY29zIG8gY29uIGRpc3RyaWJ1Y2lvbmVzIG11eSBwYXJ0aWN1bGFyZXMgcXVlIGRhbiBzZcOxYWwgZGUgZXN0YXIgZXF1aXZvY2FkYXMsIGNvbW8gcG9yIGVqZW1wbG8gbG9zIHZhbG9yZXMgZW4gbGEgbGF0aXR1ZCB5IGxhIGxvbmdpdHVkLiANCi0gRGF0b3MgY29uIG11eSBwb2NhIHJlcHJlc2VudGF0aXZpZGFkIGVuIHZhcmlhYmxlcyBxdWUgc2VnbWVudGFuIGxvcyB2YWxvcmVzLCBjb21vIGVzIGVsIGNhc28gZGUgbGEgdmFyaWFibGUgYmFycmlvLCBlbiBkb25kZSBoYWLDrWEgbXVjaG9zIGJhcnJpb3MgY29uIHNvbG8gdW4gaW5tdWVibGUuIA0KLSBWYXJpYWJsZXMgY29tcGxldGFzIHF1ZSBubyBhcG9ydGFuIGFsIG9iamV0aXZvIGRlbCBlc3R1ZGlvIChEZWZpbmlyIHN1IG5pY2hvLCBkZXNhcnJvbGxhciBlc3RyYXRlZ2lhcyBkZSBtYXJrZXRpbmcsIGV0Yy4pIHRhbCBjb21vIHNlIHByZXNlbnRhIGVuIGxhIGRlc2NyaXBjacOzbiBkZWwgdHJhYmFqby4NCg0KVGFtYmnDqW4gc2UgZWxpbWluYXJvbiBhbGd1bm9zIHJlZ2lzdHJvcyBjb24gZGF0b3Mgbm8gbMOzZ2ljb3MsIGNvbW8gbG9zIHF1ZSB0aWVuZSB2YWxvcmVzIGVuIGNlcm8gcGFyYSBsYXMgdmFyaWFibGVzIMOhcmVhIGNvbnN0cnVpZGEsIGhhYml0YWNpb25lcyBvIGJhw7FvcywgbyBjYXNhcyBkZSBtw6FzIDQgcGlzb3MsIHRhbCBjb21vIHNlIGV4cGxpY8OzIGR1cmFudGUgZWwgYW7DoWxpc2lzLg0KDQoNCiMjIDMuMy4gQW7DoWxpc2lzIGRlc2NyaXB0aXZvIGRlIGxvcyBEYXRvcyB7LnRhYnNldH0NCg0KIyMjIDMuMy4xLiBQcmVjaW8gZGUgbGFzIFZpdmllbmRhcyBlbiBkaWZlcmVudGVzIHpvbmFzIGVuIENhbGkNCg0KRW1wZWNlbW9zIHBvciB2ZXIgbG9zIGRhdG9zIGVzdGFkw61zdGljb3MgZGUgbGFzIHZhcmlhYmxlcw0KDQpgYGB7ciBTdW1tYXJ5fQ0KZGVzY3JpYmUoZGYpDQpgYGANCg0KU2UgcHVlZGUgb2JzZXJ2YXIsIGVudHJlIG90cmFzIGNvc2FzLCBsbyBzaWd1aWVudGU6DQoNCi0gICBMYSBjYW50aWRhZCBkZSByZWdpc3Ryb3MgZXMgZGUgNjg3MCwgbG8gcXVlIGluZGljYSBsYSBncmFuIGNhbnRpZGFkDQogICAgZGUgb2ZlcnRhcyBpbm1vYmlsaWFyaWFzIHF1ZSBleGlzdGVuIGVuIGxhIGNpdWRhZCBkZSBDYWxpLg0KLSAgIFNvbG8gaGF5IHZpdmllbmRhcyBkZWwgZXN0cmF0byAzIGFsIDYNCi0gICBFbCBwcmVjaW8gbcOhcyBiYWpvIGRlIHVuYSB2aXZpZW5kYSBlcyBkZSA1OCBtaWxsb25lcyBkZSBwZXNvcy4gRWwNCiAgICBtw6FzIGFsdG8gZXMgZGUgMS45OTkgbWlsbG9uZXMgZGUgcGVzb3MuIEVzdGEgZXMgbGEgdmFyaWFibGUgY29uDQogICAgbWF5b3IgZGVzdmlhY2nDs24gZXN0w6FuZGFyIHkgcmFuZ28uDQotICAgRWwgcHJlY2lvIHByZXNlbnRhIHVuYSBhc2ltZXRyw61hIGEgbGEgZGVyZWNoYSwgbG8gcXVlIHF1aWVyZSBkZWNpcg0KICAgIHF1ZSBlcyBwb3NpdGl2YSwgbyBxdWUgc3UgdmFsb3IgZXMgbWF5b3IgcXVlIGNlcm8sIHkgcXVlIG11Y2hvcw0KICAgIHZhbG9yZXMgc29uIGFsdG9zLg0KLSAgIENhcmFjdGVyw61zdGljYXMgc2ltaWxhcmVzIHRpZW5lIGxhIHZhcmlhYmxlIHF1ZSByZXByZXNlbnRhIGVsIMOBcmVhDQogICAgQ29uc3RydWlkYSwgcHVlcyB0aWVuZSB1biByYW5nbyBjZXJjYW5vIGFsIGRlbCBwcmVjaW8gKDE3MTUpIHkgdW5hDQogICAgYWx0YSBkZXN2aWFjacOzbiBlc3TDoW5kYXIgKDE0OS44NikNCi0gICBMYSBtZWRpYSBkZWwgcHJlY2lvIGRlIGxvcyBpbm11ZWJsZXMgZXMgZGUgNDQxLjYgbWlsbG9uZXMuIExhDQogICAgTWVkaWFuYSBlcyBkZSAzNDAgbWlsbG9uZXMuDQotICAgRWwgw6FyZWEgY29uc3RydWlkYSB0YW1iacOpbiB0aWVuZSB1bmEgYXNpbWV0csOtYSBwb3NpdGl2YSwgZXMgZGVjaXINCiAgICBxdWUgbG9zIGlubXVlYmxlcyBjb24gw6FyZWFzIGdyYW5kZXMgc29uIG3DoXMgcXVlIHN1cyBjb250cmFyaW9zLg0KDQpFc3RhIGVzIGxhIGNhbnRpZGFkIGRlIGlubXVlYmxlcyBxdWUgaGF5IHBvciB6b25hOg0KDQpgYGB7ciB6b25lfQ0KdGFibGUoZGYkem9uYSkNCmBgYA0KDQpMYSB6b25hIGNvbiBtYXlvciBjYW50aWRhZCBkZSBpbm11ZWJsZXMgZXMgbGEgem9uYSBzdXIsIHNlZ3VpZGEgcG9yIGxhDQp6b25hIG5vcnRlLCBsYSBvZXN0ZSwgbGEgb3JpZW50ZSB5IHBvciDDumx0aW1vIGxhIGNlbnRyby4gVmVhbW9zIGFob3JhIGxhDQpjb21iaW5hY2nDs24gZGUgbGEgem9uYSB5IGVsIHRpcG8gZGUgaW5tdWVibGUuDQoNCmBgYHtyIHpvbmVfdHlwZX0NCnRhYmxlKGRmJHpvbmEsZGYkdGlwbykNCmBgYA0KDQpFbiBsYXMgZG9zIHpvbmFzIGRvbmRlIG3DoXMgaW5tdWVibGVzIGhheSAoU3VyIHkgTm9ydGUpLCBsYSBjYW50aWRhZCBkZQ0KYXBhcnRhbWVudG9zIGVzIGxpZ2VyYW1lbnRlIG1heW9yIHF1ZSBsYSBkZSBsYXMgY2FzYXMuIEVuIGxhIHpvbmEgT2VzdGUNCmVzIG11Y2hvIG1heW9yIHBhcmEgYXBhcnRhbWVudG9zLCB5IGVuIGxhcyB6b25hcyBjZW50cm8geSBPcmllbnRlIGhheQ0KbcOhcyBjYXNhcyBxdWUgYXBhcnRhbWVudG9zLiBWZWFtb3MgbG9zIHByb21lZGlvcyB5IGxhIG1lZGlhbmEgZGUgbGENCnZhcmlhYmxlIHByZWNpbyBwYXJhIGNhZGEgY29tYmluYWNpw7NuIGRlIHRpcG8geSB6b25hOg0KDQpgYGB7ciBtZWRzLCBpbmNsdWRlPVRSVUV9DQptZWRzIDwtIGFnZ3JlZ2F0ZSAoIGRmJHByZWNpb20gfiBkZiR0aXBvICsgZGYkem9uYSwgZGF0YSA9IGRmLCBGVU4gPSBmdW5jdGlvbih4KSBjKCByb3VuZChhcy5udW1lcmljKG1lYW4oeCkpLDIpLCByb3VuZChhcy5udW1lcmljKG1lZGlhbih4KSksMSksIHJvdW5kKGFzLm51bWVyaWMobGVuZ3RoKHgpKSwwKSkpDQptZWRzIDwtIGRhdGEuZnJhbWUoYXMubWF0cml4KG1lZHMpKQ0KY29sbmFtZXMobWVkcykgPC0gYygiVGlwbyIsIlpvbmEiLCJNZWRpYV9QcmVjaW8iLCJNZWRpYW5hX1ByZWNpbyIsIkNhbnRpZGFkIikNCg0KbWVkcyRNZWRpYV9QcmVjaW8gPC0gYXMubnVtZXJpYyhtZWRzJE1lZGlhX1ByZWNpbykNCm1lZHMkTWVkaWFuYV9QcmVjaW8gPC0gYXMubnVtZXJpYyhtZWRzJE1lZGlhbmFfUHJlY2lvKQ0KbWVkcyRDYW50aWRhZCA8LSBhcy5udW1lcmljKG1lZHMkQ2FudGlkYWQpDQptZWRzDQoNCg0KZ2dwbG90KG1lZHMsIGFlcyh4ID0gVGlwbywgeSA9IENhbnRpZGFkLCBmaWxsID0gVGlwbykpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHNob3cubGVnZW5kID0gVFJVRSkgKw0KICBsYWJzKHggPSAiVGlwbyIsIHkgPSAiQ2FudGlkYWQiKSArDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSAgPSAxMCksDQogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAuNSwwLjUsMC41LDAuNSksICJjbSIpKSArDQogIGZhY2V0X3dyYXAoflpvbmEgKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBDYW50aWRhZCksIHNpemUgPSAzLCB2anVzdCA9IDAuMikNCg0KYGBgDQoNCmBgYHtyIG1lYW5zLCBpbmNsdWRlPVRSVUV9DQptZWFucyA8LSBhZ2dyZWdhdGUgKGRmJHByZWNpb20gfiBkZiR0aXBvICsgZGYkem9uYSwgZGF0YSA9IGRmLCBGVU4gPSBmdW5jdGlvbih4KSBjKHJvdW5kKGFzLm51bWVyaWMobWVhbih4KSksMikpKQ0KbWVhbnMgPC0gZGF0YS5mcmFtZShhcy5tYXRyaXgobWVhbnMpKQ0KI21lYW5zDQpjb2xuYW1lcyhtZWFucykgPC0gYygiVGlwbyIsIlpvbmEiLCJNZWRpYV9QcmVjaW8iKQ0KDQpnZ3Bsb3QobWVhbnMsIGFlcyh4ID0gVGlwbywgeSA9IE1lZGlhX1ByZWNpbywgZmlsbCA9IFRpcG8sIHdpZHRoID0gMC43KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgc2hvdy5sZWdlbmQgPSBUUlVFKSArDQogIGxhYnMoeCA9ICJUaXBvIiwgeSA9ICJNZWRpYSBQcmVjaW8iKSArDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSAgPSAxMCksDQogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAuNSwwLjUsMC41LDAuNSksICJjbSIpKSArDQogIGZhY2V0X3dyYXAoflpvbmEgKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBNZWRpYV9QcmVjaW8pLHNpemUgPSAzLCAgdmp1c3QgPSAxKQ0KDQpgYGANCg0KYGBge3IgbWVkaWFucywgaW5jbHVkZT1UUlVFfQ0KbWVkaWFucyA8LSBhZ2dyZWdhdGUgKGRmJHByZWNpb20gfiBkZiR0aXBvICsgZGYkem9uYSwgZGF0YSA9IGRmLCBGVU4gPSBmdW5jdGlvbih4KSBjKHJvdW5kKGFzLm51bWVyaWMobWVkaWFuKHgpKSwwKSkpDQptZWRpYW5zIDwtIGRhdGEuZnJhbWUoYXMubWF0cml4KG1lZGlhbnMpKQ0KI21lZGlhbnMNCmNvbG5hbWVzKG1lZGlhbnMpIDwtIGMoIlRpcG8iLCJab25hIiwiTWVkaWFuYV9QcmVjaW8iKQ0KDQpnZ3Bsb3QobWVkaWFucywgYWVzKHggPSBUaXBvLCB5ID0gTWVkaWFuYV9QcmVjaW8sIGZpbGwgPSBUaXBvLCB3aWR0aCA9IDAuNykpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHNob3cubGVnZW5kID0gVFJVRSkgKw0KICBsYWJzKHggPSAiVGlwbyIsIHkgPSAiTWVkaWFuYSBQcmVjaW8iKSArDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSAgPSAxMCksDQogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAuNSwwLjUsMC41LDAuNSksICJjbSIpKSArDQogIGZhY2V0X3dyYXAoflpvbmEgKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBNZWRpYW5hX1ByZWNpbyksc2l6ZSA9IDMsICB2anVzdCA9IDEpDQoNCmBgYA0KDQpTZSBwdWVkZSB2ZXIgZW4gZWwgcHJpbWVyIGdyw6FmaWNvIHF1ZSBsYSBjYW50aWRhZCBkZSBDYXNhcyB5DQpBcGFydGFtZW50b3MgZW4gbGEgWm9uYSBTdXIgc3VwZXJhIGEgdG9kYXMgbGFzIGRlbcOhcyBab25hcywgc2VndWlkYSBwb3INCmxhIFpvbmEgTm9ydGUsIGxhIFpvbmEgT2VzdGUsIGxhIE9yaWVudGUgeSBwb3Igw7psdGltbyBsYSBDZW50cm8uDQoNCkVuIGN1YW50byBhbCBwcmVjaW8gZGUgdmVudGEsIGxvcyBncsOhZmljb3MgcXVlIG11ZXN0cmFuIGxhIG1lZGlhIHkgbGENCm1lZGlhbmEgbXVlc3RyYW4gcXVlIGxvcyBpbm11ZWJsZXMgY29uIGVsIG1heW9yIHByZWNpbyBlc3TDoW4gZW4gbGEgWm9uYQ0KT2VzdGUsIGxvIHF1ZSwgc2llbmRvIHVuYSBab25hIGNvbiBwb2NhIG9mZXJ0YSwgbGEgaGFjZSBtdXkgYXRyYWN0aXZhLA0KcHVlcyBubyBoYXkgdGFudGEgY29tcGV0ZW5jaWEgeSBsYSBwb3NpYmlsaWRhZCBkZSBtZWpvcmVzIGNvbWlzaW9uZXMgZXMNCm3DoXMgYWx0YS4gQmFqbyBlc3RlIG1pc21vIGNyaXRlcmlvLCBsZSBzZWd1aXLDrWEgbGEgWm9uYSBOb3J0ZSB5IGxhIFpvbmENClN1ci4gVGFtYmnDqW4gbGFzIENhc2FzIGVuIGxhIFpvbmEgQ2VudHJvLiBMYSBab25hIE9yaWVudGUgbm8gcGFyZWNlIHNlcg0KbXV5IGF0cmFjdGl2YSBwb3JxdWUgaGF5IHBvY29zIGlubXVlYmxlcyB5IGVzIHBvY28gc3UgdmFsb3IuDQoNCiMjIyAzLjMuMi4gVGlwbyBkZSB2aXZpZW5kYXMgbcOhcyBvZmVydGFkYXMgZW4gQ2FsaQ0KDQpFbCB0aXBvIGRlIHZpdmllbmRhIG3DoXMgb2ZlcnRhZGEgZW4gQ2FsaSBzb24gbG9zIGFwYXJ0YW1lbnRvcy4NCg0KYGBge3IgdHlwZXN9DQp0YWJsZShkZiR0aXBvKQ0KDQp0eXBlcyA8LSBhZ2dyZWdhdGUgKGRmJHByZWNpb20gfiBkZiR0aXBvLCBkYXRhID0gZGYsIEZVTiA9IGZ1bmN0aW9uKHgpIGMocm91bmQoYXMubnVtZXJpYyhsZW5ndGgoeCkpLDApKSkNCnR5cGVzIDwtIGRhdGEuZnJhbWUoYXMubWF0cml4KHR5cGVzKSkNCmNvbG5hbWVzKHR5cGVzKSA8LSBjKCJUaXBvIiwiQ2FudGlkYWQiKQ0KDQpnZ3Bsb3QodHlwZXMsIGFlcyh4ID0gVGlwbywgeSA9IENhbnRpZGFkLCBmaWxsID0gVGlwbykpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHNob3cubGVnZW5kID0gVFJVRSkgKw0KICBsYWJzKHggPSAiVGlwbyIsIHkgPSAiQ2FudGlkYWQiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBDYW50aWRhZCksIHZqdXN0ID0gLTAuNSkgKyANCiAgY29vcmRfcG9sYXIoKQ0KDQoNCmBgYA0KDQpEZSBhY3VlcmRvIGEgbG9zIGdyw6FmaWNvcyBhbnRlcmlvcmVzIGVuIGRvbmRlIHNlIG11ZXN0cmEgbGEgY2FudGlkYWQgZGUNCnZpdmllbmRhcyBzZWdtZW50YWRvIHBvciB6b25hIHkgdGlwbywgeSBlbCBwcmVjaW8gcHJvbWVkaW8gdGFtYmnDqW4NCnNlZ21lbnRhZG8gcG9yIHpvbmEgeSB0aXBvLCBsb3MgNSBjb24gbWF5b3IgY2FudGlkYWQgc2Vyw61hbiBsb3MNCnNpZ3VpZW50ZXM6DQoNCjEuICBBcGFydGFtZW50b3MgZW4gWm9uYSBTdXINCjIuICBDYXNhcyBlbiBab25hIFN1cg0KMy4gIEFwYXJ0YW1lbnRvcyBlbiBab25hIE5vcnRlDQo0LiAgQXBhcnRhbWVudG9zIGVuIFpvbmEgT2VzdGUNCjUuICBDYXNhcyBlbiBab25hIE5vcnRlDQoNCkVuIGN1YW50byBhbCBwcmVjaW8gZGUgdmVudGEsIGVzdG9zIHNvbiBsb3MgNSBwcmltZXJvcyBwcm9tZWRpb3M6DQoNCjEuICBDYXNhcyBlbiBab25hIE9lc3RlDQoyLiAgQXBhcnRhbWVudG9zIGVuIFpvbmEgT2VzdGUNCjMuICBDYXNhcyBlbiBab25hIFN1cg0KNC4gIENhc2FzIGVuIFpvbmEgTm9ydGUNCjUuICBDYXNhcyBlbiBab25hIENlbnRybw0KDQpTaSBzZSB0aWVuZSBlbiBjdWVudGEgbGEgTWVkaWFuYSwgZWwgb3JkZW4gc2Vyw61hIGVsIG1pc21vIGRlIGxvcw0KcHJvbWVkaW9zLg0KDQojIyMgMy4zLjMuIENhcmFjdGVyw61zdGljYXMgbcOhcyByZWxldmFudGVzIGRlIGxhIG9mZXJ0YSBkZSB2aXZpZW5kYSBlbiBDYWxpLg0KDQpMYXMgdml2aWVuZGFzIGVuIHZlbnRhIGVuIENhbGkgc2UgZW5jdWVudHJhbiBkaXN0cmlidWlkYXMgZW4gdG9kYSBsYQ0KY2l1ZGFkLCBzaWVuZG8gbGEgZGUgbWF5b3IgY2FudGlkYWQgbGEgWm9uYSBTdXIuIEVzdG8gbm8gaGEgZGUNCnNvcnByZW5kZXIsIHB1ZXMgZXMgdW5hIGRlIGxhcyB6b25hcyBtw6FzIGdyYW5kZXMgeSBkZSBtYXlvciBtb3ZpbWllbnRvDQplbiBsYSBjaXVkYWQgcGFyYSB2aXZpciBwb3IgbG9zIGF0cmFjdGl2b3MgcXVlIHRpZW5lLCB0YWxlcyBjb21vDQp2YXJpZWRhZCBkZSBvcGNpb25lcyBlbiB2aXZpZW5kYSAoRWRpZmljaW9zLCBjb25qdW50b3MgcmVzaWRlbmNpYWxlcywNCmNvbmRvbWluaW9zIGNhbXBlc3RyZXMsIGV0Yy4pLCBtdWx0aXBsaWNpZGFkIGRlIG9wY2lvbmVzIGRlIGx1Z2FyZXMgZGUNCmNvbWVyY2lvLCBleGlzdGVuY2lhIGRlIHBhcnF1ZXMsIGNsdWJlcywgY2VyY2Fuw61hIGEgem9uYSBkZSBjb2xlZ2lvcyB5DQp1bml2ZXJzaWRhZGVzLCBlbnRyZSBtdWNoYXMgb3RyYXMgdmVudGFqYXMuDQoNClNpIGJpZW4gZWwgdGlwbyBkZSB2aXZpZW5kYSBxdWUgbcOhcyBzZSBvZmVydGEgc29uIGxvcyBhcGFydGFtZW50b3MsIHNvbg0KbGFzIGNhc2FzIGxhcyBxdWUgbWVqb3IgcHJvbWVkaW8gZGUgcHJlY2lvIHRpZW5lbi4gRXN0byBlcyBsw7NnaWNvLA0KcG9ycXVlIG5vcm1hbG1lbnRlIHNvbiBtw6FzIGdyYW5kZXMsIGx1ZWdvIGVzIG5hdHVyYWwgcXVlIHNlYW4gbcOhcyBjYXJhcywNCnNpbiBlbWJhcmdvLCBlbiB0b2RhcyBsYXMgem9uYXMgbGFzIGNhc2FzIHRpZW5lbiB1biBwcm9tZWRpbyBkZSBwcmVjaW8NCm3DoXMgYWx0bywgeSBjb21vIGxhcyBpbm1vYmlsaWFyaWFzIGdhbmFuIHBvciBjb21pc2nDs24gcG9yIGVsIHByZWNpbyBkZQ0KdmVudGEsIGVzdG8gc2UgaGFjZSBtdXkgcmVsZXZhbnRlIGEgbGEgaG9yYSBkZSBlc2NvZ2VyIGxhIGVzdHJhdGVnaWEgeQ0KZWwgbmljaG8gYWwgcXVlIHNlIGxlIG9mcmVjZXLDoW4gbG9zIGlubXVlYmxlcy4NCg0KYGBge3IgZXN0cmF0b190eXBlX3pvbmV9DQp0YWJsZShkZiRlc3RyYXRvLGRmJHRpcG8pDQp0YWJsZShkZiRlc3RyYXRvLGRmJHpvbmEpDQpgYGANCg0KU2kgYW5hbGl6YW1vcyBsYSBkaXN0cmlidWNpw7NuIGRlbCBlc3RyYXRvIHBvciB0aXBvIHkgcG9yIHpvbmEsIHZlbW9zIHF1ZQ0KZW4gZWwgZXN0cmF0byAzLCBxdWUgZXMgZWwgbcOhcyBiYWpvLCBoYXkgbWF5b3IgY2FudGlkYWQgZGUgY2FzYXMgZnJlbnRlDQphIGxhIG9mZXJ0YSBkZSBhcGFydGFtZW50b3MsIGVuIHVuYSByZWxhY2nDs24gY2FzaSBkZSAyOjEgcGFyYSBsYXMgY2FzYXMuDQpFc3RlIGZlbsOzbWVubyBubyBzZSByZXBpdGUgZW4gbmluZ8O6biBvdHJvIGVzdHJhdG8sIHNpZW5kbyBsYSBjYW50aWRhZCBkZQ0KYXBhcnRhbWVudG9zIG1heW9yIGEgbGEgZGUgY2FzYXMuDQoNCmBgYHtyIGVzdHJhdG99DQplc3RyYXRvcyA8LSBhZ2dyZWdhdGUgKGRmJHByZWNpb20gfiBkZiRlc3RyYXRvLCBkYXRhID0gZGYsIEZVTiA9IGZ1bmN0aW9uKHgpIGMocm91bmQoYXMubnVtZXJpYyhsZW5ndGgoeCkpLDApKSkNCmVzdHJhdG9zIDwtIGRhdGEuZnJhbWUoYXMubWF0cml4KGVzdHJhdG9zKSkNCmNvbG5hbWVzKGVzdHJhdG9zKSA8LSBjKCJFc3RyYXRvIiwiQ2FudGlkYWQiKQ0KDQpnZ3Bsb3QoZXN0cmF0b3MsIGFlcyh4ID0gRXN0cmF0bywgeSA9IENhbnRpZGFkLCBmaWxsID0gRXN0cmF0bykpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgbGFicyh4ID0gIlRpcG8iLCB5ID0gIkNhbnRpZGFkIikgKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgID0gMTApLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLjUsMC41LDAuNSwwLjUpLCAiY20iKSkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gQ2FudGlkYWQpLCBzaXplID0gMywgdmp1c3QgPSAtMC41KSANCg0KDQoNCmBgYA0KDQpFbCBFc3RyYXRvIDUgZXMgZWwgZXN0cmF0byBjb24gbWF5b3IgY2FudGlkYWQgZGUgaW5tdWVibGVzIGEgbGEgdmVudGEsDQpzZWd1aWRvIHBvciBlbCA0LCBlbCA2IHkgZWwgMy4gRW4gbGEgWm9uYSBTdXIsIGRvbmRlIGhheSBtYXlvciBjYW50aWRhZA0KZGUgaW5tdWVibGVzLCBlbiBlbCBlc3RyYXRvIGVuIHF1ZSBtw6FzIGlubXVlYmxlcyBoYXkgZXMgZWwgNSwgc2VndWlkbw0KZGVsIDQsIGRlc3B1w6lzIGVsIDYgeSBjZXJyYW5kbyBlbCAzLiBFc3RvIGVzIGNvaGVyZW50ZSBjb24gbGENCmRpc3RyaWJ1Y2nDs24gZGUgbGEgY2l1ZGFkIGVuIGRpY2hhIHpvbmEuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDQuIFJlc3VsdGFkb3MNCg0KQSBwYXJ0aXIgZGVsIGFuw6FsaXNpcyBkZXNjcmlwdGl2byBkZWwgY29uanVudG8gZGUgZGF0b3MsIHNlIHByZXNlbnRhbg0KbG9zIHNpZ3VpZW50ZXMgcmVzdWx0YWRvcyBkZWwgZXN0dWRpbywgY29uIGVsIG9iamV0aXZvIGRlIGJyaW5kYXINCmluZm9ybWFjacOzbiByZWxldmFudGUgeSBzdWZpY2llbnRlIHBhcmEgcXVlIGxhIEp1bnRhIERpcmVjdGl2YSBkZSBsYQ0KSW5tb2JpbGlhcmlhIEImQyBwdWVkYSBkZWNpZGlyIHN1IG5pY2hvIGRlIG1lcmNhZG8sIGRlc2Fycm9sbGFyDQplc3RyYXRlZ2lhcyBkZSBtYXJrZXRpbmcsIGVzdGFibGVjZXIgcHJlY2lvcyBkZSB2ZW50YSB5IG9mcmVjZXINCnNlcnZpY2lvcyBwZXJzb25hbGl6YWRvcyBhIHN1cyBjbGllbnRlcy4NCg0KLSAgIFpvbmFzIGNvbiBtZWpvciBwcm9tZWRpbyBkZSBwcmVjaW9zDQoNCkxhIFpvbmEgT2VzdGUgcHJlc2VudGEgdW4gbWVqb3IgcHJvbWVkaW8gZGUgcHJlY2lvcyB0YW50byBwYXJhIGxhcyBjYXNhcw0KY29tbyBwYXJhIGxvcyBhcGFydGFtZW50b3MsIGNvbnN0aXR1ecOpbmRvc2UgZW4gdW5hIHpvbmEgZGUgbXVjaG8NCmludGVyw6lzLCBkYWRvIHF1ZSBsYXMgaW5tb2JpbGlhcmlhcyBnYW5hbiBwb3IgY29taXNpw7NuLCB5IGVudHJlIG1heW9yDQpzZWEgZWwgdmFsb3IgZGUgbGEgcHJvcGllZGFkLCBtw6FzIGRpbmVybyBzZSBnYW5hcsOhLiBMYSBzaWd1ZW4gbGEgem9uYQ0Kc3VyIHkgbGEgem9uYSBub3J0ZS4gRWwgY2FzbyBkZSBsYSB6b25hIGNlbnRybyBlcyBwYXJ0aWN1bGFyLCBwdWVzIGhheQ0KcG9jYXMgY2FzYXMsIHBlcm8gc3UgcHJvbWVkaW8gZGUgcHJlY2lvIG5vIGVzIGVsIG3DoXMgYmFqaXRvLg0KDQotICAgVGlwbyBkZSBpbm11ZWJsZSBtw6FzIG9mZXJ0YWRvDQoNCkxvcyBhcGFydGFtZW50b3Mgc29uIGVsIHRpcG8gZGUgaW5tdWVibGUgY29uIG1heW9yIGNhbnRpZGFkIGRlIG9mZXJ0YXMNCmVuIGxhIGNpdWRhZCBkZSBDYWxpIHN1cGVyYW5kbyBlbiBjYW50aWRhZCBhIGxhcyBjYXNhcyBlbiBsYSB6b25hIE5vcnRlLA0KT2VzdGUgeSBTdXIuIEVuIGxhcyB6b25hcyBDZW50cm8geSBPcmllbnRlLCBoYXkgbcOhcyBjYXNhcyBvZmVydGFkYXMsIGVuDQp1bmEgcHJvcG9yY2nDs24gYXByb3hpbWFkYSBkZSA2IGEgMS4NCg0KLSAgIE1lam9yIHRpcG8gZGUgVml2aWVuZGENCg0KQXVucXVlIGhheSBtw6FzIGFwYXJ0YW1lbnRvcyBxdWUgY2FzYXMsIGxhcyBjYXNhcyBwcmVzZW50YW4gbWF5b3Jlcw0KdmFsb3JlcyBlbiBzdSBwcmVjaW8sIGxvIHF1ZSBsYXMgaGFjZSBtw6FzIGF0cmFjdGl2YXMuIExhcyB6b25hcyBjb24gbcOhcw0KYWx0byBwcm9tZWRpbyBkZSB2ZW50YSBzb24gbGEgT2VzdGUsIGxhIFN1ciwgYSBOb3J0ZSwgbGEgQ2VudHJvIHkgbGENCk9yaWVudGUuIE7Ds3Rlc2UgcXVlIGxhIENlbnRybyB0aWVuZSBwb2NhcyBvZmVydGFzLCBwZXJvIHN1cyBjYXNhcyB0aWVuZW4NCm1lam9yIHByb21lZGlvIHF1ZSBsYXMgZGUgbGEgem9uYSBPcmllbnRlLg0KDQotICAgRXN0cmF0byBjb24gbWF5b3IgY2FudGlkYWQgZGUgaW5tdWVibGVzDQoNCkVsIGVzdHJhdG8gNSBlcyBlbCBlc3RyYXRvIGNvbiBtYXlvciBjYW50aWRhZCBkZSBvZmVydGEgZGUgdmVudGEgZGUNCmlubXVlYmxlcy4gU2kgYmllbiwgZXN0byBubyBlcyBlbiBzaSBpbmZvcm1hY2nDs24gY29udHVuZGVudGUsIHNpIGVzIHVuYQ0KbXVlc3RyYSBkZSBxdWUgbGFzIGNhc2FzIHF1ZSBtw6FzIHNlIGNvbWVyY2lhbGl6YW4gc29uIGxhcyBkZSB2YWxvcmVzDQptZWRpby1hbHRvcywgeSBlc3RvIHB1ZWRlIGRhciB1biBpbmRpY2lvIGRlIGxhIGNsYXNlIGRlIGNvbXByYWRvcmVzIHF1ZQ0Kc2UgZGViZW4gYnVzY2FyLg0KDQojIDUuIERpc2N1c2nDs24NCg0KTG9zIG9iamV0aXZvcyBwbGFudGVhZG9zIGVuIGVzdGEgaW52ZXN0aWdhY2nDs24sIHF1ZSBidXNjYW4gb2ZyZWNlcg0KaW5mb3JtYWNpw7NuIHJlbGV2YW50ZSBhIGxhIElubW9iaWxpYXJpYSBCJkMgcGFyYSBxdWUgdG9tZSBkZWNpc2lvbmVzDQplc3RyYXTDqWdpY2FzIHBhcmEgc3UgZnV0dXJvIHNlIHZlbiBlbXBlw7FhZG9zIHBvciBsYSBwb2JyZSBjYWxpZGFkIGRlbA0KY29uanVudG8gZGUgZGF0b3MgZW50cmVnYWRvLiBObyBzb2xvIGVsIHByb2Nlc28gZGUgZGVwdXJhY2nDs24sIGxpbXBpZXphDQp5IG5vcm1hbGl6YWNpw7NuIG8gZXN0YW5kYXJpemFjacOzbiBkZSBsb3MgZGF0b3Mgc2UgaGFjZSBtdXkgbGFyZ28sIHNpbm8NCnF1ZSB0YW1iacOpbiBzZSBxdWVkYSBjb3J0byBwb3JxdWUgbm8gZXMgc3VmaWNpZW50ZSBsYSBpbmZvcm1hY2nDs24gZGUgbGENCipvZmVydGEqIGRlIGlubXVlYmxlcyBlbiBsYSBjaXVkYWQsIHNpbm8gdGFtYmnDqW4gaW5mb3JtYWNpw7NuIHNvYnJlIGxhcw0KKnZlbnRhcyosIHB1ZXMgZW4gYXJhcyBkZSB0b21hciBkZWNpc2lvbmVzIGVzdHJhdMOpZ2ljYXMgc29icmUgbmljaG9zIGRlDQptZXJjYWRvIG5vIGVzIHN1ZmljaWVudGUgc2FiZXIgcXVlIGhheSBtdWNob3MgaW5tdWVibGVzIGVuIHVuYSB6b25hDQplc3BlY2lmaWNhIHNpZW5kbyBvZmVydGFkb3MsIHNpbm8gcXVlIHNlcsOtYSBtw6FzIGNvbnZlbmllbnRlIHNhYmVyLCBwb3INCmVqZW1wbG8sIGxvcyBkYXRvcyByZWFsZXMgZGUgbG9zIHByZWNpb3MgZGUgdmVudGEgZGUgbGFzIHZpdmllbmRhcywgbyBlbA0KdGllbXBvIHF1ZSB0b21hIHZlbmRlciB1bmEgY2FzYSBvIHVuIGFwYXJ0YW1lbnRvIGVuIGxhcyB6b25hcyBkZSBsYQ0KY2l1ZGFkLg0KDQpEZXNkZSBlbCBwdW50byBkZSB2aXN0YSBlc3RyYXTDqWdpY28sIHkgcGFyYSBlc3RhYmxlY2VyIHNlcnZpY2lvcw0KcGVyc29uYWxpemFkb3MgYSBzdXMgY2xpZW50ZXMsIGhheSBtdWNoYSBkaWZlcmVuY2lhIGVudHJlIGxhIGNhbnRpZGFkIGRlDQpvZmVydGFzIHNlYW4gbXV5IGFsdGEsIGEgcXVlIGxhIGNhbnRpZGFkIGRlIHZlbnRhcyBzZWEgYWx0YS4gTG8gdW5vIG5vDQpsbGV2YSBuZWNlc2FyaWFtZW50ZSBhIGxvIG90cm9zLiBEZSBoZWNobywgbGEgY2FudGlkYWQgZGUgYmllbmVzDQpvZmVydGFkb3MgZW4gdW5hIHpvbmEsIHB1ZWRlcyBzZXIgdW5hIG11ZXN0cmEgZGUgbGEgZGlmaWN1bHRhZCBxdWUgaGF5DQplbiB2ZW5kZXJsb3MsIHkgcG9yIGVzbyBzZSAiYWN1bXVsYW4iIHNpbiB2ZW5kZXJzZSBlbiBlbCBsaXN0YWRvIGRlDQpvZmVydGFzLg0KDQpEZSBpZ3VhbCBtYW5lcmEsIGhheSB2YXJpYWJsZXMgZW4gZWwgY29uanVudG8gZGUgZGF0b3MgcXVlIHB1ZWRlbiBzZXINCnJlbGV2YW50ZXMgcGFyYSBjaWVydG9zIG9iamV0aXZvcyB5IHF1ZSB0aWVuZW4gcmVsYWNpw7NuIGNvbiBsb3MNCmlubXVlYmxlcyBxdWUgc2Ugb2ZlcnRhbiwgcGVybyBxdWUgcHVlZGVuIGVzdGFyIGZhbHRhbmRvIHBhcmEgbG9zIGJpZW5lcw0KcXVlIGVmZWN0aXZhbWVudGUgc2UgdmVuZGVuLiBFc3RhIGRpZmljdWx0YWQgZGUgZW5jb250cmFyIGVzb3MgZGF0b3MgZW4NCmxhIGZ1ZW50ZSBkZSBkb25kZSBzZSBleHRyYWplcm9uIGxvcyBkYXRvcywgaW5kaWNhIHF1ZSB0YWwgdmV6IHNlYSBtdWNobw0KbWVqb3IgYnVzY2FyIGRhdG9zIGVuIG90cmFzIGZ1ZW50ZXMgbcOhcyByZWxldmFudGVzLCBwb3IgZWplbXBsbywgZW4gdmV6DQpkZSBidXNjYXIgbG9zIGRhdG9zIGRlIGxhcyBvZmVydGFzIGVuIGludGVybmV0LCBidXNjYXIgbG9zIGRhdG9zIGRlIGxhcw0KdmVudGFzIGVmZWN0aXZhcyBlbiBsYXMgbm90YXLDrWFzIG8gZW4gbGFzIG9maWNpbmFzIGRlIGNhdGFzdHJvIG8NCmluY2x1c2l2ZSBkZSBsYSBESUFOLCBwdWVzIGVzdG9zICJsdWdhcmVzIiBzb24gbG9zIHF1ZSByZWNpYmVuIGVzZSB0aXBvDQpkZSBpbmZvcm1hY2nDs24sIHkgc2kgZWwgb2JqZXRpdm8gZXMgZGVmaW5pciB1biBwbGFuIGVzdHJhdMOpZ2ljbyBwYXJhDQpvcmllbnRhciBhIGxhIGNvbXBhw7HDrWEsIGVzIG11Y2hvIG1lam9yIGVuZm9jYXJzZSBlbiBsYXMgdmVudGFzIHF1ZSBTSSBzZQ0KbG9ncmFuLCBxdWUgZW4gbGFzIG9mZXJ0YXMgcXVlIG5vIGxvIGhhY2VuLg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyA2LiBDb25jbHVzaW9uZXMNCg0KLSAgIFNlIHB1ZG8gdmVyIHF1ZSBlbCBjb25qdW50byBkZSBkYXRvcyB0aWVuZSBtdWNoYXMgaXJyZWd1bGFyaWRhZGVzLA0KICAgIGRhdG9zIGF0w61waWNvcywgdmFsb3JlcyBudWxvcyBvIHF1ZSBjbGFyYW1lbnRlIHBhcmVjZW4gZXJyw7NuZW9zLg0KICAgIEVzdG8gY2F1c2EgbXVjaGEgZGlmaWN1bHRhZCBlbiBzdSBwcm9jZXNhbWllbnRvLCBwZXJvIHNvYnJlIHRvZG8NCiAgICBtaW5hIGxhIGNvbmZpYW56YSBlbiBlbCBjb25qdW50byBkZSBkYXRvcy4gU2kgYmllbiBubyBoYXkgY29tbw0KICAgIGNvcnJvYm9yYXIgbG9zIGRhdG9zIGRlIGxhcyB2YXJpYWJsZXMgZW4gbGFzIHF1ZSBubyBzYWJlbW9zIGENCiAgICBjaWVuY2lhIGNpZXJ0YSBzaSBoYXkgZGF0b3MgZXJyw7NuZW9zLCBsYSBjYW50aWRhZCBxdWUgc2kgcG9kZW1vcw0KICAgIGRldGVybWluYXIgY29tbyBlcnLDs25lb3MgZXMgdGFuIGFsdGEgcXVlIG5vcyBoYWNlIGRlc2NvbmZpYXIgZGVsDQogICAgY29uanVudG8uIFBvciBlamVtcGxvLCBzZSBwdWVkZSBjb25zdGF0YXIgcXVlIGhheSBlcnJvcmVzIGVuIGxvcw0KICAgIHZhbG9yZXMgZGUgbGFzIHZhcmlhYmxlcyBsYXRpdHVkIHkgbG9uZ2l0dWQsIHBlcm8gbm8gcG9kZW1vcyBzYWJlcg0KICAgIHNpIGhheSBlcnJvcmVzIGVuIGxhIHZhcmlhYmxlIHByZWNpbyBvIMOhcmVhIGNvbnN0cnVpZGEsIHNhbHZvIHVub3MNCiAgICBtdXkgY29udGFkb3MgcmVnaXN0cm9zIHF1ZSBwdWVkZW4gc2VyIGVsaW1pbmFkb3MuDQoNCi0gICBMbyBhbnRlcmlvciBoYWNlIHNvc3BlY2hhciBkZSBsb3MgdmFsb3JlcyBwcmVzZW50ZXMgZW4gb3RyYXMNCiAgICB2YXJpYWJsZXMgYSBsYXMgcXVlIG5vIHNlIGxlcyBwdWVkYSBjb21wcm9iYXIgcXVlIHRpZW5lbiB2YWxvcmVzDQogICAgZXF1aXZvY2Fkb3Mgbm8gcHVlZGFuIHNlciBjb25maWFibGVzLiBEZSB0b2RvcyBtb2RvcywgYWwgZWxpbWluYXINCiAgICBsb3MgcmVnaXN0cm9zIGNvbiBkYXRvcyBjbGFyYW1lbnRlIGVycsOzbmVvcywgc2UgZXN0w6EgZGlzbWludXllbmRvIGxhDQogICAgcHJvYmFiaWxpZGFkIGRlIGVycm9yIGVuIGxvcyBhbsOhbGlzaXMgeSBjb25jbHVzaW9uZXMuDQoNCi0gICBFcyBtdXkgaW1wb3J0YW50ZSB0cmFiYWphciBjb24gbG9zIGRhdG9zIGRlIGxhIG1lam9yIGNhbGlkYWQNCiAgICBwb3NpYmxlLCBpbmNsdXNvIHNpIGhheSBxdWUgc2FjcmlmaWNhciB5IGRpc21pbnVpciBsYSBjYW50aWRhZCBkZQ0KICAgIGRhdG9zIHByZXNlbnRlcyBjb24gbG9zIHF1ZSBzZSBwdWVkZSB0cmFiYWphci4NCg0KLSAgIFBhcmEgbWFudGVuZXIgbGEgY2FsaWRhZCBkZSBsb3MgZGF0b3MsIGVzIG5lY2VzYXJpbyBsbGV2YXIgYSBjYWJvDQogICAgdW5hIHJldmlzacOzbiBkZSBsb3MgbWlzbW9zIHkgdW5hIGVsaW1pbmFjacOzbiBkZSBsb3MgZGF0b3MgY29uDQogICAgdmFsb3JlcyBjbGFyYW1lbnRlIGVxdWl2b2NhZG9zLCBjb21vIMOhcmVhcyBpZ3VhbGVzIGEgMCwgbyB2aXZpZW5kYXMNCiAgICBzaW4gaGFiaXRhY2lvbmVzIG8gYmHDsW9zLg0KDQotICAgQWwgc2VyIGxvcyBkYXRvcyByZWNvZ2lkb3MgZGUgcHVibGljYWNpb25lcyBlbiBpbnRlcm5ldCwgbm8gc2UNCiAgICBwdWVkZW4gY29ycm9ib3JhciBuaSBtZWpvcmFyIHN1c3RhbmNpYWxtZW50ZSwgc2Fsdm8gZW4gY3Vlc3Rpb25lcw0KICAgIGNvbnRhZGFzLCBjb21vIHBvciBlamVtcGxvIGNydXphbmRvIGxhcyBjb29yZGVuYWRhcyBjb24gZWwgYmFycmlvLg0KICAgIFNpbiBlbWJhcmdvLCBlbCBkZXNvcmRlbiBkZSBlc3RhcyBkb3MgdmFyaWFibGVzIG5vIGluZGljYSBxdWUgZXNlDQogICAgYW7DoWxpc2lzIHNlYSBpbXBvcnRhbnRlIGhhY2VybG8uDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDcuIEFuZXhvcyB7LnRhYnNldH0NCg0KVG9kbyBlc3RlIGRvY3VtZW50byB5IGPDs2RpZ28gZXN0YSBkaXNwb25pYmxlIFtBcXXDrV0oaHR0cDovL3JwdWJzLmNvbS9rZXBlbmEvYWN0MS1NeVMtRUpQRikNCg0KIyMgQ29uc2lnbmEgZGUgbGEgQWN0aXZpZGFkIDENCg0KTGEgKiplbXByZXNhIEImQyoqIChCaWVuZXMgeSBDYXNhcykgZXMgdW5hIGFnZW5jaWEgZGUgYmllbmVzIHJhw61jZXMgcXVlDQpvcGVyYSBlbiBsYSBjaXVkYWQgZGUgQ2FsaSwgQ29sb21iaWEuIExhIGVtcHJlc2EgZnVlIGZ1bmRhZGEgcG9yIFNhbmRyYQ0KTWlsZW5hIGhhY2UgMTAgYcOxb3MgeSBhY3R1YWxtZW50ZSBjdWVudGEgY29uIG9jaG8gYWdlbnRlcyBkZSBiaWVuZXMNCnJhw61jZXMuDQoNCkVsIG1lcmNhZG8gZGUgYmllbmVzIHJhw61jZXMgZW4gQ2FsaSBoYSBjcmVjaWRvIHNpZ25pZmljYXRpdmFtZW50ZSBlbiBsb3MNCsO6bHRpbW9zIGHDsW9zLCBpbXB1bHNhZG8gcG9yIGVsIGNyZWNpbWllbnRvIGRlIGxhIHBvYmxhY2nDs24sIGxhIGludmVyc2nDs24NCmV4dHJhbmplcmEgZGlyZWN0YSB5IGVsIGRlc2Fycm9sbG8gZGUgbnVldm9zIHByb3llY3RvcyBpbm1vYmlsaWFyaW9zLiBFbg0KMjAyMiwgbGFzIHZlbnRhcyBkZWwgc2VjdG9yIGVuIENhbGkgbGxlZ2Fyb24gYSBcJDY3MDAgbWlsbG9uZXMgeSBlbiAyMDIzDQphIFwkNjEwMCBtaWwgbWlsbG9uZXMuIFNlIGVzcGVyYSBxdWUgZXN0ZSBzZWN0b3IgY29udGludWUgY3JlY2llbmRvDQpkdXJhbnRlIGxvcyBwcsOzeGltb3MgYcOxb3MsIHBlcm1pdGllbmRvIHVuIGRlc2Fycm9sbG8gZGluw6FtaWNvIGVuIGxhDQplY29ub23DrWEgcmVnaW9uYWwuDQoNCkxhIGVtcHJlc2EgKkImQyogaGEgcmVjb2dpZG8gaW5mb3JtYWNpw7NuIHNvYnJlIHZpdmllbmRhcyBxdWUgaW5jbHV5ZQ0KaW5mb3JtYWNpw7NuIHNvYnJlIGVsIHByZWNpbywgbGEgdWJpY2FjacOzbiwgbGFzIGNhcmFjdGVyw61zdGljYXMgeSBsYQ0KdmVudGEgZGUgdml2aWVuZGFzIGVuIENhbGkuIEVzdGEgYmFzZSBkZSBkYXRvcyBwdWVkZSBzZXIgdXRpbGl6YWRhIHBhcmENCnJlYWxpemFyIHVuIGluZm9ybWUgZXN0YWTDrXN0aWNvIHF1ZSBzZXLDrWEgZGUgZ3JhbiBpbnRlcsOpcyBwYXJhIGxhDQplbXByZXNhLg0KDQpFbCBpbmZvcm1lIGVzdGFkw61zdGljbyBwb2Ryw61hIHByb3BvcmNpb25hciBpbmZvcm1hY2nDs24gc29icmUgbG9zDQpzaWd1aWVudGVzIHRlbWFzOg0KDQotICAgUHJlY2lvIGRlIGxhcyB2aXZpZW5kYXMgZW4gZGlmZXJlbnRlcyB6b25hcyBkZSBDYWxpLg0KLSAgIFRpcG8gZGUgdml2aWVuZGFzIG3DoXMgb2ZlcnRhZGFzIGVuIENhbGkuDQotICAgQ2FyYWN0ZXLDrXN0aWNhcyBtw6FzIHJlbGV2YW50ZXMgZGUgbGEgb2ZlcnRhIGRlIHZpdmllbmRhIGVuIENhbGkuDQoNCkVzdGEgaW5mb3JtYWNpw7NuIHNlcsOtYSDDunRpbCBwYXJhIGxhIGVtcHJlc2EgQiZDIHBhcmEgdG9tYXIgZGVjaXNpb25lcw0Kc29icmUgc3UgbmVnb2NpbywgdGFsZXMgY29tbzoNCg0KLSAgIERlZmluaXIgc3UgbmljaG8gZGUgbWVyY2Fkby4NCi0gICBEZXNhcnJvbGxhciBlc3RyYXRlZ2lhcyBkZSBtYXJrZXRpbmcuDQotICAgRXN0YWJsZWNlciBwcmVjaW9zIGRlIHZlbnRhLg0KLSAgIE9mcmVjZXIgc2VydmljaW9zIHBlcnNvbmFsaXphZG9zIGEgc3VzIGNsaWVudGVzLg0KDQpMYSBlbXByZXNhIHNvbGljaXRhIHVuIGFuw6FsaXNpcyBkZXNjcmlwdGl2byBkZSBsb3MgZGF0b3MsIHBhcmENCmlkZW50aWZpY2FyIGxhcyB0ZW5kZW5jaWFzIHkgcGF0cm9uZXMgZW4gbG9zIGRhdG9zLg0KDQpFbCBpbmZvcm1lIGRlYmUgaW5jbHVpciBsb3Mgc2lndWllbnRlcyBlbGVtZW50b3M6DQoNCjEuICBJbnRyb2R1Y2Npw7NuDQoyLiAgT2JqZXRpdm9zDQozLiAgTcOpdG9kb3MNCjQuICBSZXN1bHRhZG9zDQo1LiAgRGlzY3VzacOzbg0KNi4gIENvbmNsdXNpb25lcw0KNy4gIEFuZXhvcw0KDQpFbCBpbmZvcm1lIGRlYmUgc2VyIHJlZGFjdGFkbyBlbiB1biBsZW5ndWFqZSBjbGFybyB5IGNvbmNpc28sIHkgZGViZQ0KZXN0YXIgZGlyaWdpZG8gYSBsb3MgZGlyZWN0aXZvcyBkZSBsYSBlbXByZXNhIEImQy4NCg0KU29saWNpdHVkIGRlIGVudHJlZ2EgZGVsIGluZm9ybWUgU2UgZGViZSBlbnRyZWdhciBlbmxhY2UgZGUgbGENCnBsYXRhZm9ybWEgUlB1YnMgcXVlIGNvbnRlbmdhIGVsIGRvY3VtZW50byBmaW5hbCwgdXRpbGl6YW5kbyBlbCBmb3JtYXRvDQpNYXJrZG93bi4NCg0KRWwgaW5mb3JtZSBkZWJlIGVzdGFyIG9yZ2FuaXphZG8gZW4gdW4gKsO6bmljbyBkb2N1bWVudG8qIHF1ZSBjb250ZW5nYSBsYQ0KaW50cm9kdWNjacOzbiwgbG9zIG9iamV0aXZvcywgbG9zIG3DqXRvZG9zLCBsb3MgcmVzdWx0YWRvcywgbGEgZGlzY3VzacOzbiB5DQpsYXMgY29uY2x1c2lvbmVzLiBDYWRhICpzZWNjacOzbiogZGVsIGluZm9ybWUgZGViZSBlc3RhciAqbnVtZXJhZGEqIHkNCmRlYmUgdGVuZXIgdW4gKmVuY2FiZXphZG8gZGVzY3JpcHRpdm8qLg0KDQpFbnRyZWdhYmxlICoqRW5sYWNlIGRlbCBpbmZvcm1lIGVuIFJQdWJzKiosICpjb3BpYWRvIGVuIEFjdGl2aWRhZDEqIGRlbA0KY3Vyc28gZW4gQnMNCg0KIyMgQ29uanVudG8gIGRlIERhdG9zDQoNCioqRGVzY3JpcGNpw7NuKioNCg0KRXN0b3MgZGF0b3MgaGFuIHNpZG8gZXh0cmHDrWRvcyBtZWRpYW50ZSB3ZWJzY3JhcGluZy4gRWwgZGF0YXNldCBjb250aWVuZSBjYXJhY3RlcsOtc3RpY2FzIGRlIHZpdmllbmRhcyBkZSBDYWxpLg0KDQoqKsK/Q8OzbW8gc2UgdXNhPzoqKiBTb2xvIGhheSBxdWUgZXNjcmliaXIgInZpdmllbmRhX2ZhbHRhbnRlcyIgc2luIGxhcyBjb21pbGxhcy4NCg0KKipSZWdpc3Ryb3MqKjogQ29uanVudG8gY29uIDgzMjIgcmVnaXN0cm9zIHkgMTMgdmFyaWFibGVzDQoNCioqVmFyaWFibGVzL0NvbHVtbmFzKiogDQoNCi0gaWQ6IA0KSWRlbnRpZmljYWRvciDDum5pY28gZGUgbGEgdml2aWVuZGENCg0KLSB6b25hOg0KWm9uYSBkZSBsYSBjaXVkYWQgKFVuYSBkZSBjaW5jbzogTm9ydGUsIFN1ciwgT3JpZW50ZSwgT2VzdGUgeSBDZW50cm8pDQoNCi0gcGlzbzoNClBpc28gZW4gbGEgcXVlIGVzdMOhIHViaWNhZGEgbGEgdml2aWVuZGENCg0KLSBlc3RyYXRvOg0KRXN0cmF0byBkb25kZSBlc3RhIGxhIHZpdmllbmRhDQoNCi0gcHJlY2lvbToNClByZWNpbyBlbiBtaWxsb25lcyBkZSBwZXNvcw0KDQotIGFyZWFjb25zdDoNCsOBcmVhIGNvbnN0cnVpZGEgZW4gbWV0cm9zIGN1YWRyYWRvcw0KDQotIHBhcnF1ZWFkZXJvczoNCk7Dum1lcm8gZGUgcGFycXVlYWRlcm9zDQoNCi0gYmFuaW9zOg0KTsO6bWVybyBkZSBiYcOxb3MNCg0KLSBoYWJpdGFjaW9uZXM6DQpOw7ptZXJvIGRlIGhhYml0YWNpb25lcw0KDQotIHRpcG86DQpUaXBvIGRlIHZpdmllbmRhDQoNCi0gYmFycmlvOg0KQmFycmlvDQoNCi0gbG9uZ2l0dWQ6DQpDb29yZGVuYWRhIGRlIGxvbmdpdHVkDQoNCi0gbGF0aXR1ZDoNCkNvb3JkZW5hZGEgZGUgbGF0aXR1ZA0KDQoNCg==