Resumen Ejecutivo

Introducción

En el presente trabajo se pretende construir un modelo predictivo que permita predecir el valor de un apartamento de estrato 4 en la ciudad de cali a partir del área construida de los mismos. Se realizará la verificación de los supuestos y se contrastará el modelo con otros 4 modelos que son producto de transformaciones, para finalmente escoger el mejor de ellos.

Metodología

Para llegar a los resultados se construyó un modelo de regresión lineal y se realizaron transformaciones al mismo para conocer si hay algún modelo con mejores resultados que pueda reemplazarlo.

  • 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

  • Correlación entre el precio y el área construida

El modelo de regresión lineal confirma la correlación teórica existente entre el área construida y el precio de un inmueble.

  • Modelos transformados

Ninguno de las transformaciones realizadas arrojaron un modelo con mejores resultados y ajustes del modelo original.

Sugerencias a modo de Conclusiones

Los resultados encontrados no se pueden generalizar para otros estratos o tipos de vivienda, pues son exclusivos para los apartamentos de estrato 4 de la ciudad de Cali. Se requerirían modelos propios para cada (sub)conjunto de datos para poder hacer predicciones de precio para viviendas con otras características.

Para un estudio más detallado y que pueda hacer mejores predicciones, se sugiere segmentar los datos por zona, tipo de inmueble y por estrato, y construir modelos propios para cada subconjunto de datos. Esto hará que se tengan en cuenta esas características en las predicciones y que las mismas sean mas acordes a la realidad.

Se presenta a continuación todo el proceso de análisis y de construcción del modelo que se llevó a cabo para la Inmobiliaria A&C.


1. 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. La inmobiliaria A&C quiere construir un modelo predictivo que les permita conocer el precio estimado de un inmueble dada el valor del área construida.

A continuación se muestra el proceso que se llevo a cabo para crear, evaluar y escoger un modelo predictivo con buenas características que sirviera para los propósitos de la Inmobiliaria.


2. Objetivos

Construir un modelo que permita predecir los precios de los inmuebles a negociar, basado en el conjunto de datos de los inmuebles con menos de 200 metros cuadrados construidos.


3. Proceso Preparatorio

Realizaré un análisis inicial al conjunto de datos para detectar registros vacíos, valores atípicos y datos que deban eliminarse. Posteriormente se realizará un análisis descriptivo y estadístico de los datos definiendo las variables de interés. Finalmente se construirá y evaluará un modelo que permita predecir el valor de una casa a partir de sus variables independientes.

3.1. Análisis inicial

Se preparan las librerías a utilizar, se cargan los datos y se visualiza la cabecera del conjunto de datos vivienda4 que tiene los inmuebles de menos de 200 metros cuadrados para el estrato 4.

df
summary(df$zona)
##  Zona Centro   Zona Norte   Zona Oeste Zona Oriente     Zona Sur 
##            8          288           60            6         1344

Podemos observar que el conjunto está bien acotado y tiene las siguientes variables: - Zona/zona: Zona en donde se ubica la casa (Norte, Sur, Centro, Oeste, Oriente) - Estrato/estrato: Para este conjunto todos los inmuebles pertenecen al estrato 4 - Precio/preciom: Precio del inmueble - Área Construida/areaconst: Área construida en metros cuadrados - Tipo de Inmueble/tipo: Casa o Apartamento

Antes de ver como se distribuyen los valores de las variables, veamos si hay valores nulos en ellas:

knitr::opts_chunk$set(echo = TRUE, fig.width = 4, fig.height = 4)
missing_data <- colSums(is.na(df)) %>%
                 as.data.frame() 

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

Se puede notar que no hay valores nulos en ningún registro. Ahora veamos la distribución de las variables Zona y Tipo de Inmueble:

summary(df$zona)
##  Zona Centro   Zona Norte   Zona Oeste Zona Oriente     Zona Sur 
##            8          288           60            6         1344
summary(df$tipo)
## Apartamento        Casa 
##        1363         343

Hay una amplia mayoría de inmuebles en la zona Sur. En cuanto al tipo de inmueble, la mayoría son Apartamentos. NOTA: Según las indicaciones del profesor, se realizarán todos los puntos con un subconjunto de datos que corresponda solamente a los apartamentos.

3.2. Limpieza y Preparación de los datos

Por ser un subconjunto de datos ya filtrado, se puede notar que no existen registros vacíos ni columnas con datos faltantes, tal como se detectó en la sección anterior. Esta es una situación bastante atípica en el proceso de desarrollar un modelo. Se realizará el filtrado para que queden solo los apartamentos.

df <- filter(df, !df$tipo == "Casa")
df

4. Desarrollo del ejercicio

4.1. Análisis exploratorio del Precio y el Área

Realice un análisis exploratorio de las variables precio de vivienda (millones de pesos COP) y área de la vivienda (metros cuadrados) - incluir gráficos e indicadores apropiados interpretados.

4.1.1. Precio de la vivienda

A continuación, se muestra la “estadística descriptiva” para la variable que muestra el valor del inmueble en millones de pesos. Contiene \(1.363\) registros de apartamentos.

summarytools::descr(df$preciom)
## Descriptive Statistics  
## df$preciom  
## N: 1363  
## 
##                     preciom
## ----------------- ---------
##              Mean    237.68
##           Std.Dev     13.29
##               Min    207.41
##                Q1    228.79
##            Median    236.14
##                Q3    243.59
##               Max    305.19
##               MAD     10.98
##               IQR     14.79
##                CV      0.06
##          Skewness      1.28
##       SE.Skewness      0.07
##          Kurtosis      3.19
##           N.Valid   1363.00
##         Pct.Valid    100.00
  • Lo primero que nos entrega la estadística descriptiva es el promedio del valor de los inmuebles, que es \(\$237.68\) millones de pesos, en un rango de entre \(\$207\) y \(\$305\) millones de pesos.
  • El primer cuartil nos indica que el \(25\%\) de las viviendas tiene un precio igual o menor de \(\$228.79\) millones.
  • La mediana es de \(\$236.14\) millones, lo que indica que la mitad de los inmuebles tienen un valor inferior, y la otra mitad uno igual o mayor.
  • El tercer cuartil es de \(\$243.5\) millones, lo que indica que el \(75\%\) de las viviendas tienen un valor igual o inferior al indicado.
  • La variable tiene una desviación estándar de \(13.29\) lo que indica cierta variabilidad en los precios.
  • La Desviación absoluta mediana (MAD) es una medida de dispersión robusta frente a los valores atípicos pues representa la mediana de las diferencias absolutas respecto a la mediana. En este caso es \(10.98\).
  • El rango entre cuartiles (Q3 y Q1) es de \(14.79\), es decir, el \(50\%\) de los datos centrales tienen esa diferencia de precio (en millones de pesos)
  • Tiene un Coeficiente de Variación de \(0,06\) lo que nos dice que hay una variabilidad baja en relación a la media.
  • El skewness, sesgo o asimetría es de \(1.28\) lo que sugiere una distribución sesgada hacia la derecha, es decir, que hay mas precios por encima de la media que por debajo. Esto sugiere que hay una concentración de precios más bajos y una dispersión de precios más altos.
  • La Curtosis (Kurtosis) es \(3.19\) lo que indica que la distribución tiene comportamiento de una distribución normal. Este valor sugiere que hay más precios alrededor de la media y colas más pesadas.

Veamos gráficamente la distribución con un diagrama de cajas y bigotes y un histograma para la variable preciom:

knitr::opts_chunk$set(echo = TRUE, fig.width = 4, fig.height = 4)
# Generate boxplot
fillcolor = "lightgreen"
linecolor = "#08C671"
ggplot(df, aes_string(x = df$preciom)) +
  geom_boxplot(fill = fillcolor,
               outlier.size = 1,
               outlier.shape = 24) +
  labs(title = "Diagrama de Cajas y Bigotes para Precio de Inmueble",
       x = "Precio (millones de pesos)", y = "Distribucion") +
   scale_x_continuous(breaks = seq(200, 320, by = 10)) + # Marks every 10 millions
  theme_tufte()

Se puede observar que por encima de 265 millones de pesos (aproximadamente), los precios de los apartamentos se convierten en valores atípicos, y que el \(50\%\) central se encuentra distribuido alrededor de un poco menos de \(230\) y un poco más de \(240\) millones de pesos. No muestra valores atípicos en los valores bajos.

knitr::opts_chunk$set(echo = TRUE, fig.width = 4, fig.height = 4)
ts = 0.8 #text size
fillcolor = "lightgreen"
linecolor = "#08C671"

# Gráfico de histograma
par(cex = ts) # Ajustar tamaño de texto dentro del gráfico
hist(df$preciom, 
      main = "Histograma para apartamentos de menos de 200 m2",
      ylab = "Frecuencia",
      xlab = "Precio (en millones de pesos)",
      col = fillcolor,
      border = linecolor)

La mayor cantidad de precios de casas se encuentran aproximadamente entre \(230\) y \(240\) millones de pesos, seguidos por los rangos aproximados de \(220-230\) y \(240-250\) millones de pesos respectivamente.

Por último, veamos el gráfico de densidad de distribución de los precios.

# Generar el histograma de densidad
ggplot(df, aes(x = preciom)) +
  geom_density(fill = "lightgreen") +
  labs(title = "Densidad de precios", x = "Precio", y = "Densidad") +
  geom_vline(xintercept = mean(df$preciom), color = "darkgreen", linetype = 4)

4.1.2. Área Construida de la vivienda

A continuación, se muestra la “estadística descriptiva” para la variable que muestra el Área Construida de los apartamentos que contiene \(1.363\) registros.

summarytools::descr(df$areaconst)
## Descriptive Statistics  
## df$areaconst  
## N: 1363  
## 
##                     areaconst
## ----------------- -----------
##              Mean       75.48
##           Std.Dev       22.56
##               Min       40.00
##                Q1       60.00
##            Median       70.00
##                Q3       84.00
##               Max      200.00
##               MAD       14.83
##               IQR       24.00
##                CV        0.30
##          Skewness        2.08
##       SE.Skewness        0.07
##          Kurtosis        6.32
##           N.Valid     1363.00
##         Pct.Valid      100.00
  • El promedio del área de los inmuebles, es \(75.48\) metros cuadrados, en un rango de entre \(40\) y \(200\) metros cuadrados.
  • El primer cuartil nos indica que el \(25\%\) de las viviendas tiene un área igual o menor de 60 metros cuadrados.
  • La mediana es de \(70\) metros cuadrados, lo que indica que la mitad de los inmuebles tienen un valor inferior, y la otra mitad uno igual o mayor.
  • El tercer cuartil es de \(84\) metros cuadrados, lo que indica que el \(75\%\) de las viviendas tienen un valor igual o inferior al indicado.
  • La variable tiene una desviación estándar de 22.56 lo que indica una variabilidad moderada en los precios.
  • El MAD o Desviación absoluta mediana es de \(14.83\).
  • El IQR o rango entre cuartiles (Q3 y Q1) es de \(24\), es decir, el \(50\%\) de los datos centrales tienen esa diferencia de área (en metros cuadrados de pesos)
  • Tiene un Coeficiente de Variación de \(0.3\) lo que nos dice que hay una variabilidad moderada del tamaño del área en relación a la media.
  • El skewness, sesgo o asimetría es de \(2.08\). Al ser positivo sugiere que la distribución tiene una cola hacia la derecha, es decir, que hay más áreas por encima de la media que por debajo. Esto indica que hay una concentración de áreas más bajos y una dispersión de áreas más altas.
  • La Curtosis, que mide la curvatura de la distribución de los datos, es de \(6.32\) lo que sugiere una distribución normal que tiene una mayor concentración de valores de áreas construidas alrededor de la media y colas mas pesadas, especialmente hacia los valores más altos. Ahora veamos gráficamente la distribución con un diagrama de cajas y bigotes y un histograma para la variable areaconst:
# Generate boxplot
fillcolor = "lightgreen"
linecolor = "#08C671"
ggplot(df, aes_string(x = df$areaconst)) +
  geom_boxplot(fill = fillcolor,
               outlier.size = 1,
               outlier.shape = 24) +
  labs(title = "Diagrama de Cajas y Bigotes para Area de Inmueble",
       x = "Metros cuadrados construidos", y = "Distribucion") +
   scale_x_continuous(breaks = seq(min(df$areaconst), max(df$areaconst), by = 10)) + # Marks every 10 millions
  theme_tufte()

Se puede observar que al acercarse a los \(120\) metros cuadrados construidos, los áreas de los inmuebles se convierten en valores atípicos, es decir, poco comunes, y que el \(50\%\) central se encuentra distribuido alrededor de \(60\) y \(84\) metros cuadrados (Q3).

ts = 0.8 #text size
fillcolor = "lightgreen"
linecolor = "#08C671"

# Gráfico de histograma
par(cex = ts) # Ajustar tamaño de texto dentro del gráfico
hist(df$areaconst, 
      main = "Histograma para Apartamentos de menos de 200 m2",
      ylab = "Frecuencia",
      xlab = "Metros cuadrados construidos",
      col = fillcolor,
      border = linecolor)

La mayor cantidad de áreas de apartamentos se encuentra entre \(50\) y \(60\) metros cuadrados, seguidos por los rangos aproximados de \(70-80\) y \(60-70\) metros cuadrados. Se ve que hay una cierta cantidad de valores hacia la derecha del histograma desde los \(130\) hasta \(200\) metros construidos.

Ahora veamos el gráfico de densidad de distribución de las áreas construidas.

# Generar el histograma de densidad
ggplot(df, aes(x = areaconst)) +
  geom_density(fill = "lightgreen") +
  labs(title = "Densidad de precios", x = "Área construida", y = "Densidad") +
  geom_vline(xintercept = mean(df$areaconst), color = "darkgreen", linetype = 4)

4.2. Análisis exploratorio bivariado

Realice un análisis exploratorio bivariado de datos, enfocado en la relación entre la variable respuesta (precio) en función de la variable predictora (área construida) - incluir gráficos e indicadores apropiados interpretados.

Veamos la relación entre las variables preciom y areaconst. Se espera que entre más área construida, el precio sea más alto. Un comportamiento diferente a este, si bien puede ser posible en la práctica, es poco probable y altera 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 cuando las variables estan correlacionadas. 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.

numeric_columns <- names(df)[sapply(df, is.numeric)]
exclude_columns <- c() #Se usaran las dos únicas variables numéricas del conjunto
numeric_columns <- setdiff(numeric_columns, exclude_columns)
cov_matrix <- cov(df[, numeric_columns])
atipicos <- mahalanobis(df[, numeric_columns], center = TRUE, cov = cov_matrix)

ggplot(df, aes_string(x = 'preciom', y = 'areaconst', color = "atipicos")) +
  geom_point(size = 2, alpha = 0.5) +
  scale_color_brewer(palette = "Spectral") + 
  scale_color_continuous(low = "lightgreen", high = "darkgreen") +
  labs(title = "Relacion entre precio y Area construida\n segun distancia de Mahalanobis", 
       x = "Precio del metro cuadrado", y = "Area construida en metros cuadrados", 
       color = "Distancia de Mahalanobis") +
  scale_x_continuous(limits = c(min(df$preciom), max(df$preciom) + 10)) + 
  scale_y_continuous(limits = c(min(df$areaconst), max(df$areaconst) + 10)) 
## Scale for colour is already present.
## Adding another scale for colour, which will replace the existing scale.

Podemos ver que a medida que el área aumenta, también aumenta el precio del inmueble, es decir, hay una relación lineal positiva entre preciom y areaconst. Si validamos numéricamente lo que se ve en el gráfico anterior, podemos corroborarlo con la función cor. Veamos:

cor(df$preciom,df$areaconst)
## [1] 0.8463271

Esta función nos entrega un valor de \(0.84\), el cual se acerca a 1. Probemos con el test de correlación de Pearson:

cor.test(df$preciom,df$areaconst)
## 
##  Pearson's product-moment correlation
## 
## data:  df$preciom and df$areaconst
## t = 58.616, df = 1361, p-value < 0.00000000000000022
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8305531 0.8607445
## sample estimates:
##       cor 
## 0.8463271

Este resultado también sugiere una correlación muy fuerte entre el precio y el área construida de los apartamentos. La hipótesis alternativa es que la correlación verdadera entre las variables no es igual a cero. El resultado del valor p es muy bajito, pues está en el orden de 10 a la menos 16, es decir, prácticamente cero, esto nos permite respaldar la hipótesis alternativa, confirmando que la correlación entre las variables es muy fuerte (muy cercana a cero). El intervalo de confianza es del \(95\%\), es decir, el valor verdadero de la correlación se encuentra en el rango \(0.83\) y \(0.86\). Todo lo anterior nos confirma que a medida que aumenta el área construida de los apartamentos, también aumenta el precio de ellos.

knitr::opts_chunk$set(echo = TRUE, fig.width = 5, fig.height = 5)
plot(df$preciom, df$areaconst,
     xlab = expression("Precio en millones de pesos "),
     ylab = "Area construida en metros cuadrados (m"^"2"~")",
     main = "Grafico de Dispersion",
     col = "lightgreen",          
     pch = 20,       
     cex = 0.8)

Por último, realizaré un gráfico combinado con las correlaciones entre las dos variables en donde se puede corroborar lo encontrado anteriormente.

knitr::opts_chunk$set(echo = TRUE, fig.width = 8, fig.height = 8)

# Crear matriz de correlaciones con ggpairs
ggpairs(df[,4:3], 
        mapping = aes(fill = "red"),
        title = "Matriz de Correlaciones entre precio y área construida", 
        upper = list(geom = "point", size = 2, color = "red"), 
        lower = list(cor = TRUE, p.cex = 0.6, sig.level = 0.05), 
        diag = list(histogram = "density", bins = 15))

4.3. Modelo de Regresión Lineal

Estime el modelo de regresión lineal simple entre \(precio = f(area)+ \epsilon\). Interprete los coeficientes del modelo \(\beta_0\), \(\beta_1\) en caso de ser correcto.

Como existe una correlación positiva entre las dos variables, es posible construir un modelo de regresión lineal que describa la relación existente entre dichas variables. La regresión lineal se expresa a través de una ecuación de una recta con un valor de coeficientes para el intercepto en el eje y \(\beta_0\) y la pendiente de la recta \(\beta_1\).

reg_model = lm(preciom ~ areaconst, data = df)
summary(reg_model)
## 
## Call:
## lm(formula = preciom ~ areaconst, data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -26.5139  -5.0886  -0.0031   4.6406  24.3309 
## 
## Coefficients:
##               Estimate Std. Error t value            Pr(>|t|)    
## (Intercept) 200.063455   0.669847  298.67 <0.0000000000000002 ***
## areaconst     0.498416   0.008503   58.62 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 7.081 on 1361 degrees of freedom
## Multiple R-squared:  0.7163, Adjusted R-squared:  0.7161 
## F-statistic:  3436 on 1 and 1361 DF,  p-value: < 0.00000000000000022

La variable independiente es el área construida y la dependiente es el precio. El modelo estima la relación con la siguiente ecuación: \(preciom = \beta_0 + \beta_1 * areaconst + \epsilon\). \(\beta_0\) es el intercepto en el eje \(y\) que tiene un valor de \(200\). Esto indicaría un valor de \(200\) millones de pesos cuando el área construida es cero, lo que realmente no es posible, pero sirve como una referencia matemática para los cálculos de áreas positivas. \(\beta_1\) es la pendiente de la recta cuyo valor es \(0.498\). Esto indica que para cada unidad en que aumenta el área construida, el precio resultado de la predicción aumentaría en \(0.498\) unidades. Por ejemplo, si la pendiente fuera uno, por cada metro cuadrado mas de área construida, el precio aumentaría un millón de pesos.
El valor de \(p\) para \(\beta_0\) y \(\beta_1\) es altamente significativo (valor menor del orden de \(2e-16\)), es decir, que su correlación no se debe al azar. Según el resultado de Multiple R-squared o el indicador de bondad \(R^2\) del modelo explica el \(71.63%\) de la varianza del precio, pero bien podría haber otros factores que influyen en el precio que no son capturados por el modelo. Esto tiene sentido, pues se sabe que inmuebles de igual área construida en sectores diferentes tienen valores diferentes, también tiene influencia el tipo de acabados, el material de construcción, entre otros factores. Para tener esas variables en cuenta

4.4. Intervalo de confianza

Construir un intervalo de confianza (95%) para el coeficiente \(\beta_1\), interpretar y concluir si el coeficiente es igual a cero o no. Compare este resultado con una prueba de hipótesis t

Pare esto, usaremos la función confint.

confidence_interval = confint(reg_model, level = 0.95)
confidence_interval
##                   2.5 %     97.5 %
## (Intercept) 198.7494103 201.377500
## areaconst     0.4817357   0.515097

Según este resultado, se puede decir que con intervalo de confianza del \(95\%\) el intercepto tiene un valor entre \(\$198.74\) millones y \(\$201.37\) millones cuando el valor de la variable independiente es cero. Como ya se explicó, esto no es real en la práctica pues un apartamento con área construida de cero simplemente no existiría. También, con una confianza del \(95\%\) se puede decir que el efecto de la unidad de aumento en el área construida se encuentra entre \(0.48\) y \(0.51\) para el precio.

4.5. Indicador de Bondad

Calcule e interprete el indicador de bondad \(R^2\).

El indicador o coeficiente de bondad \(R^2\) mide la proporción de la varianza total de los datos que es explicada por el modelo. Un valor de \(R^2\) cercano a 1 indica que el modelo explica una gran parte de la varianza de los datos, mientras que un valor cercano a 0 indica que el modelo explica poca varianza. Para calcularlo usaremos

cat("El indicador o coeficiente de bondad del modelo de regresion lineal es de:", summary(reg_model)$r.squared)
## El indicador o coeficiente de bondad del modelo de regresion lineal es de: 0.7162696

Este resultado de \(0.7162\) del indicador \(R^2\) indica que el \(71.62\%\) de la varianza del precio de los apartamentos es explicada por el modelo. Si bien es más cercano a 1 que a 0, no me parece significativamente cercano a 1, lo que me hace pensar que hay otras variables que influyen en el precio ademas del área construida.

4.6. Estimación de precio

¿Cuál sería el precio promedio estimado para un apartamento de 110 metros cuadrados? Considera entonces con este resultado que un apartamento en la misma zona con 110 metros cuadrados en un precio de 200 millones sería una atractiva esta oferta? ¿Qué consideraciones adicionales se deben tener?.

Para hacer esta estimación, basta con reemplazar los valores encontrados en la ecuación:

\(Y = \beta_0 + \beta_1 * X\), donde

\(Y\) es el precio,

\(X\) es el área construida, es decir \(110m^2\)

\(\beta_0 = 200.06\) y

\(\beta_1 = 0.498\)

Entonces tenemos:

\(precio = 200.06 + 0.498*110\)

\(precio = 200.06 + 54.78\)

\(precio = 254.84\)

Lo que indica que el modelo arroja un precio de \(254.84\) millones de pesos para un apartamento de 110 \(M^2\), luego la oferta de \(200\) millones por parte de la inmobiliaria para un apartamento en el mismo sector sería muy atractiva según lo arrojado por el modelo pues estaría muy por debajo del valor de los apartamentos en la zona. Según lo anterior, la inmobiliaria tendría un margen de \(54\) millones de pesos para subir el valor del apartamento, es decir, aún pidiendo \(225\) millones o hasta \(240\) millones de pesos por el apartamento estaría en buenas condiciones para ser una oferta atractiva para el comprador por estar por debajo de lo esperado en la zona.

4.7. Validación de los supuestos

Realice la validación de los supuestos del modelo por medio de gráficos apropiados, interpretarlos y sugerir posibles soluciones si se violan algunos de ellos. Utilice las pruebas de hipótesis para la validación de supuestos y compare los resultados con lo observado en los gráficos asociados.

4.7.1. Supuesto de Normalidad

Supuesto de Normalidad: Los errores siguen una distribución normal \((\epsilon_i ∼ N(0,\sigma^2))\).

Para validar estos supuestos se utilizarán las pruebas Shapiro-Wilk y Anderson-Darling.

La prueba de Shapiro-Wilk se usa para evaluar si los residuos del modelo siguen una distribución normal. Los residuos son la diferencia entre los valores observados de la variable dependiente (en este caso preciom) y los valores predichos por el modelo.

shapiro.test(reg_model$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  reg_model$residuals
## W = 0.99885, p-value = 0.5419

El resultado muestra un estadístico W: 0.99885 que se acerca a \(1\), lo que indica que la distribución se puede tomar como una distribución normal. Si fuera cercano a \(0\) sería lo contrario.

El valor p representa la probabilidad de obtener un estadístico W igual de extremo que el observado, suponiendo que la hipótesis nula, es decir la normalidad, sea cierta. Generalmente, un valor p menor que el nivel de significancia de \(0.05\) indicaría que debe rechazarse la hipótesis nula, es decir, que los datos no siguen una distribución normal. Para este caso, el valor p es mayor que \(0.05\) lo que no permite rechazar la hipótesis nula de normalidad.

nortest::ad.test(reg_model$residuals)
## 
##  Anderson-Darling normality test
## 
## data:  reg_model$residuals
## A = 0.42398, p-value = 0.318

El resultado muestra un estadístico A: 0.42398 que se acerca a \(0\), lo que indica que la distribución se puede tomar como una distribución normal. Si fuera cercano a \(1\) sería lo contrario.

El valor p en este caso es \(0.318\) también es mayor a \(0.05\) lo que tampoco permite rechazar a hipótesis nula.

4.7.2. Supuesto de Homoscedasticidad

_Supuesto de Homoscedasticidad: La varianza alrededor de la linea de regresión, para cualquier valor constante \((V_([\epsilon]) = \sigma^2)\).

Se utilizará la prueba Breusch-Pagan estandarizada o prueba BP se utiliza para evaluar la heterocedasticidad en los residuos de un modelo de regresión lineal. La heterocedasticidad se refiere a la varianza no constante de los residuos, es decir, que la dispersión de los errores no es uniforme en todos los niveles de la variable independiente, en este caso la área construida.

lmtest::bptest(reg_model)
## 
##  studentized Breusch-Pagan test
## 
## data:  reg_model
## BP = 0.83288, df = 1, p-value = 0.3614

La prueba arroja los siguientes resultados: Estadistico BP \(= 0.83288\) el cual es un valor alejado de cero, lo que indica una posible heterocedasticidad.

El valor p, al igual que en las pruebas anteriores, representa la posibilidad de obtener un estadistico BP tan extremo o mas extremo que el observado. Este valor es mayor a \(0.05\) lo que no permite rechazar la hipótesis nula de homocedasticidad.

4.7.3. Supuesto de No Autocorrelación

Supuesto de No Autocorrelación: Los errores que corresponden a diferentes individuos o diferentes tiempo deben ser independientes unos de otros \((Cov[\epsilon_i,\epsilon_j] = 0)\).

\(H_0:E[\epsilon_i,epsilon_j] = 0\)

\(H_a:E[epsilon_i,epsilon_j] ≠ 0\)

Se utilizará la prueba de Durbin-Watson (DW) para detectar la presencia de autocorrelación en los residuos del modelo de regresión lineal.

lmtest::dwtest(reg_model)
## 
##  Durbin-Watson test
## 
## data:  reg_model
## DW = 2.0204, p-value = 0.6435
## alternative hypothesis: true autocorrelation is greater than 0

El Estadístico DW varia entre \(0\) y \(4\). En este caso dio como resultado \(2.0204\) lo cual sugiere, por ser cercano a 2, que los residuos tienden a estar correlacionados negativamente entre si, es decir, que no hay autocorrelación entre ellos. (Los valores menores que \(2\) indican autocorrelación positiva, y valores superiores a 2, autocorrelación negativa, lo cual es menos común)

Se obtiene un valor p de \(0.6435\) que es mayor al nivel de significancia \(0.05\) no hay evidencia suficiente para rechazar la hipótesis nula de No Autocorrelación.

4.7.4. Outliers

Aunque este no es un supuesto formal, se espera que los datos no contengan datos atípicos que generen sesgos en los estimadores de los coeficientes.

Tal como se vio en los gráficos del conjunto de datos, las variables preciom y areaconst si tienen datos atípicos representados por los triángulos en los gráficos correspondientes. Veamos el gráfico de cajas y bigotes para los residuos del modelo.

knitr::opts_chunk$set(echo = TRUE, fig.width = 4, fig.height = 4)
boxplot(reg_model$residuals,  
        main = "Outliers - Residuos del Modelo", 
        ylab = "Residuos",
        col = "lightgreen",
        border = "darkgreen"
)

4.7.5. Gráficos asociados a las pruebas

knitr::opts_chunk$set(echo = TRUE, fig.width = 6, fig.height = 6)
par(mfrow = c(2,2))
plot(reg_model, 
     col = "lightgreen", 
     pch = 20, 
     lwd = 1, 
     cex = 1)
# Línea de identidad
abline(a = 0, 
       b = 1, 
       col = "green", 
       lty = 1)

Los gráficos de dispersión nos muestran correlación entre las dos variables usando los residuos y los residuos estandarizados, soportando los análisis previamente descritos.


5. Transformaciones del modelo

A continuación se realizan los puntos 8 al 10 en donde se realizarán transformaciones para ver si se mejorar el ajuste y los supuestos del modelo, se compararán los resultados de estas transformaciones con el modelo inicial.

Aunque el modelo inicial cumple los supuestos y se demostró que existe una correlación entre las variables estudiadas, luego no sería estrictamente necesario hacer transformaciones para mejorar el ajuste y los supuestos del modelo, se realizarán algunas transformaciones para ser comparadas con el modelo inicial.

Punto 8: De ser necesario realice una transformación apropiada para mejorar el ajuste y supuestos del modelo.

Punto 9: De ser necesario compare el ajuste y supuestos del modelo inicial y el transformado.

Punto 10: Estime varios modelos y compare los resultados obtenidos. En el mejor de los modelos, ¿se cumplen los supuestos sobre los errores?

knitr::opts_chunk$set(echo = TRUE, fig.width = 6, fig.height = 6)
model1 = lm(df$preciom ~ df$areaconst, data = data.frame(df)) # Lin - Lin
summary(model1)
## 
## Call:
## lm(formula = df$preciom ~ df$areaconst, data = data.frame(df))
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -26.5139  -5.0886  -0.0031   4.6406  24.3309 
## 
## Coefficients:
##                Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)  200.063455   0.669847  298.67 <0.0000000000000002 ***
## df$areaconst   0.498416   0.008503   58.62 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 7.081 on 1361 degrees of freedom
## Multiple R-squared:  0.7163, Adjusted R-squared:  0.7161 
## F-statistic:  3436 on 1 and 1361 DF,  p-value: < 0.00000000000000022
shapiro.test(model1$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  model1$residuals
## W = 0.99885, p-value = 0.5419
nortest::ad.test(model1$residuals)
## 
##  Anderson-Darling normality test
## 
## data:  model1$residuals
## A = 0.42398, p-value = 0.318
lmtest::bgtest(model1)
## 
##  Breusch-Godfrey test for serial correlation of order up to 1
## 
## data:  model1
## LM test = 0.15038, df = 1, p-value = 0.6982
lmtest::dwtest(model1)
## 
##  Durbin-Watson test
## 
## data:  model1
## DW = 2.0204, p-value = 0.6435
## alternative hypothesis: true autocorrelation is greater than 0
par(mfrow = c(2,2))
plot(model1, 
     col = "lightgreen", 
     pch = 20, 
     lwd = 1, 
     cex = 1)

5.1. Transformación Box-Cox

La transformación Box-Cox se utiliza para corregir la no linealidad en la relación entre variables (lo que no seria necesario en este caso), estabilizar la varianza, normalizar la distribución de los residuos y mejorar la interpretabilidad de los resultados.

knitr::opts_chunk$set(echo = TRUE, fig.width = 6, fig.height = 6)
bc <- boxcox(df$preciom ~ df$areaconst, lambda = -1:1)

lambda = bc$x[which.max(bc$y)]
cat("El valor Lambda (λ) es: ", lambda)
## El valor Lambda (λ) es:  1

El valor de \(\lambda\) es \(1\), lo que indica que el modelo no necesita transformación.

5.2. Transformaciones del Modelo Original

5.2.1. Modelo 2: [Lin-Log]

knitr::opts_chunk$set(echo = TRUE, fig.width = 6, fig.height = 6)
model2 = lm(preciom ~ log(areaconst), data = df)      # Lin - Log
summary(model2)
## 
## Call:
## lm(formula = preciom ~ log(areaconst), data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -22.9725  -5.4109  -0.1832   4.9141  24.1899 
## 
## Coefficients:
##                Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)     53.8202     3.4091   15.79 <0.0000000000000002 ***
## log(areaconst)  42.8778     0.7936   54.03 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 7.496 on 1361 degrees of freedom
## Multiple R-squared:  0.682,  Adjusted R-squared:  0.6818 
## F-statistic:  2919 on 1 and 1361 DF,  p-value: < 0.00000000000000022
shapiro.test(model2$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  model2$residuals
## W = 0.9971, p-value = 0.01302
nortest::ad.test(model2$residuals)
## 
##  Anderson-Darling normality test
## 
## data:  model2$residuals
## A = 1.1581, p-value = 0.005009
lmtest::bgtest(model2)
## 
##  Breusch-Godfrey test for serial correlation of order up to 1
## 
## data:  model2
## LM test = 0.93995, df = 1, p-value = 0.3323
lmtest::dwtest(model2)
## 
##  Durbin-Watson test
## 
## data:  model2
## DW = 1.9464, p-value = 0.1587
## alternative hypothesis: true autocorrelation is greater than 0
par(mfrow = c(2,2))
plot(model2, 
     col = "lightgreen", 
     pch = 20, 
     lwd = 1, 
     cex = 1)

5.2.2. Modelo 3: [Log-Lin]

knitr::opts_chunk$set(echo = TRUE, fig.width = 6, fig.height = 6)
model3 = lm(log(preciom) ~ areaconst, data = df)      # Log - Lin
summary(model3)
## 
## Call:
## lm(formula = log(preciom) ~ areaconst, data = df)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.104645 -0.020942  0.000593  0.019371  0.099110 
## 
## Coefficients:
##               Estimate Std. Error t value            Pr(>|t|)    
## (Intercept) 5.31797842 0.00283459 1876.11 <0.0000000000000002 ***
## areaconst   0.00200666 0.00003598   55.77 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.02996 on 1361 degrees of freedom
## Multiple R-squared:  0.6956, Adjusted R-squared:  0.6954 
## F-statistic:  3110 on 1 and 1361 DF,  p-value: < 0.00000000000000022
shapiro.test(model3$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  model3$residuals
## W = 0.99907, p-value = 0.7333
nortest::ad.test(model3$residuals)
## 
##  Anderson-Darling normality test
## 
## data:  model3$residuals
## A = 0.33717, p-value = 0.5044
lmtest::bgtest(model3)
## 
##  Breusch-Godfrey test for serial correlation of order up to 1
## 
## data:  model3
## LM test = 0.17106, df = 1, p-value = 0.6792
lmtest::dwtest(model3)
## 
##  Durbin-Watson test
## 
## data:  model3
## DW = 2.0219, p-value = 0.6534
## alternative hypothesis: true autocorrelation is greater than 0
par(mfrow = c(2,2))
plot(model3, 
     col = "lightgreen", 
     pch = 20, 
     lwd = 1, 
     cex = 1)

5.2.3. Modelo 4: [Log-Log]

knitr::opts_chunk$set(echo = TRUE, fig.width = 6, fig.height = 6)
model4 = lm(log(preciom) ~ log(areaconst), data = df)      # Log- Log
summary(model4)
## 
## Call:
## lm(formula = log(preciom) ~ log(areaconst), data = df)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.104277 -0.022240  0.000027  0.020782  0.093359 
## 
## Coefficients:
##                Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)    4.722680   0.014102  334.91 <0.0000000000000002 ***
## log(areaconst) 0.174148   0.003283   53.05 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.03101 on 1361 degrees of freedom
## Multiple R-squared:  0.674,  Adjusted R-squared:  0.6738 
## F-statistic:  2814 on 1 and 1361 DF,  p-value: < 0.00000000000000022
shapiro.test(model4$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  model4$residuals
## W = 0.9985, p-value = 0.2868
nortest::ad.test(model4$residuals)
## 
##  Anderson-Darling normality test
## 
## data:  model4$residuals
## A = 0.58718, p-value = 0.1259
lmtest::bgtest(model4)
## 
##  Breusch-Godfrey test for serial correlation of order up to 1
## 
## data:  model4
## LM test = 0.42812, df = 1, p-value = 0.5129
lmtest::dwtest(model4)
## 
##  Durbin-Watson test
## 
## data:  model4
## DW = 1.9635, p-value = 0.2469
## alternative hypothesis: true autocorrelation is greater than 0
par(mfrow = c(2,2))
plot(model4, 
     col = "lightgreen", 
     pch = 20, 
     lwd = 1, 
     cex = 1)

5.2.4. Modelo 5: [Lin-\(\sqrt{areaconst}\)]

knitr::opts_chunk$set(echo = TRUE, fig.width = 6, fig.height = 6)
model5 = lm(preciom ~ sqrt(areaconst), data = df)      # Lin - Sqrt(x)
summary(model5)
## 
## Call:
## lm(formula = preciom ~ sqrt(areaconst), data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -25.1087  -5.2451  -0.0772   4.7355  23.6388 
## 
## Coefficients:
##                 Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)     156.3863     1.4349  108.99 <0.0000000000000002 ***
## sqrt(areaconst)   9.4454     0.1652   57.19 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 7.206 on 1361 degrees of freedom
## Multiple R-squared:  0.7061, Adjusted R-squared:  0.7059 
## F-statistic:  3271 on 1 and 1361 DF,  p-value: < 0.00000000000000022
shapiro.test(model5$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  model5$residuals
## W = 0.99832, p-value = 0.1983
nortest::ad.test(model5$residuals)
## 
##  Anderson-Darling normality test
## 
## data:  model5$residuals
## A = 0.70556, p-value = 0.06539
lmtest::bgtest(model5)
## 
##  Breusch-Godfrey test for serial correlation of order up to 1
## 
## data:  model5
## LM test = 0.034307, df = 1, p-value = 0.8531
lmtest::dwtest(model5)
## 
##  Durbin-Watson test
## 
## data:  model5
## DW = 1.9891, p-value = 0.4163
## alternative hypothesis: true autocorrelation is greater than 0
par(mfrow = c(2,2))
plot(model5, 
     col = "lightgreen", 
     pch = 20, 
     lwd = 1, 
     cex = 1)

5.3. Comparación de los Modelos

Para analizar los modelos se puede utilizar el valor de \(R^2\) buscando el valor más alto, ya que este indica la proporción de varianza de la variable dependiente que es explicada por el modelo. También se puede mirar el Error Residual estándar (Residual Std. Error) más bajo, pues este valor representa la variabilidad promedio de los errores de predicción del modelo.

stargazer(model1, model2, model3, model4, model5, type = "text", df = FALSE)
## 
## ====================================================================================
##                                           Dependent variable:                       
##                     ----------------------------------------------------------------
##                       preciom      preciom          log(preciom)          preciom   
##                         (1)          (2)          (3)          (4)          (5)     
## ------------------------------------------------------------------------------------
## areaconst             0.498***                                                      
##                       (0.009)                                                       
##                                                                                     
## log(areaconst)                    42.878***                  0.174***               
##                                    (0.794)                   (0.003)                
##                                                                                     
## areaconst                                       0.002***                            
##                                                (0.00004)                            
##                                                                                     
## sqrt(areaconst)                                                           9.445***  
##                                                                           (0.165)   
##                                                                                     
## Constant             200.063***   53.820***     5.318***     4.723***    156.386*** 
##                       (0.670)      (3.409)      (0.003)      (0.014)      (1.435)   
##                                                                                     
## ------------------------------------------------------------------------------------
## Observations           1,363        1,363        1,363        1,363        1,363    
## R2                     0.716        0.682        0.696        0.674        0.706    
## Adjusted R2            0.716        0.682        0.695        0.674        0.706    
## Residual Std. Error    7.081        7.496        0.030        0.031        7.206    
## F Statistic         3,435.808*** 2,919.088*** 3,110.029*** 2,814.311*** 3,270.505***
## ====================================================================================
## Note:                                                    *p<0.1; **p<0.05; ***p<0.01

Para los modelos comparados en la tabla, podemos ver que el modelo 1, es decir, el Lin-Lin tiene \(R^2\) es el más alto (\(0.716\)), lo que nos dice que es el que mejor explica la variabilidad de la variable dependiente preciom. El siguiente \(R^2\) es el del modelo 5 Lin-\(sqrt(areaconst)\) con un valor de \(0.706\)

En cuanto a los errores estándar residuales, los modelos 3 y 4 son los que tiene este valor más bajo, con \(0.030\) y \(0.031\) respectivamente. Esto indica que para ellos hay un mejor ajuste de los datos.

Si bien ningún modelo mejor el \(R^2\), los modelos 3 y 4 si parecen tener una mejora en cuando al ajuste de los datos.

Ahora bien, si hacemos la estimación para el apartamento con 110\(m^2\), podremos saber cuál es el modelo que ofrece un mejor resultado. Recordemos que para el modelo inicial el resultado fue de \(254.84\)

Veamos el resultado para el modelo 5 [Lin-\(\sqrt{areaconst}\)] que tiene un intercepto de \(156.38\) y una pendiente de \(9.445\).

\(precio = 156.38 + 9.45 * \sqrt(110)\)

\(precio = 156.38 + 9.45 * 10.49\)

\(precio = 156.38 + 99.06\)

\(precio = 255.44\) (en millones de pesos)

Para el modelo 3 [Log-Lin] que tiene un intercepto de \(5.318\) y una pendiente de \(0.002\).

\(\log(precio) = 5.318 + 0.002 * 110\)

\(\log(precio) = 5.318 + 0.22\)

\(\log(precio) = 5.538\)

\(precio = e^{5.538}\)

\(precio = 254,36\) (en millones de pesos)

Todos los valores obtenidos son muy parecidos entre si y no marcan una diferencia significativamente positiva con el resultado del modelo inicial.


6. Conclusiones y Recomendaciones Finales

  • Sobre el conjunto de datos: Nos encontramos con un conjunto de datos limpio, que contenía registros sobre casas y apartamentos del estrato 4 en la ciudad de Cali. La mayoría de registros eran sobre los apartamentos en una relación casi 4 a 1. Se eliminaron los registros de las casas para la realización del ejercicio y el análisis estuvo concentrado específicamente en las variables de preciom (Precio de la vivienda en millones de pesos), como variable dependiente, y areaconst (Área construida) como variable independiente.

  • Sobre las variables de estudio: El tamaño promedio de los apartamentos es de \(75.48m^2\) y el valor promedio es \(\$237.68\) millones de pesos colombianos. Esta relación arroja un promedio de valor por \(m^2\) de un poco más de \(\$3\) millones de pesos.

  • Sobre la correlación de las variables: De acuerdo al resultado del análisis de correlación realizado por medio de una regresión lineal con la ecuación \(y = \beta_0 + \beta_1(x)\), donde \(\beta_0\) es el intercepto de los ejes, y \(\beta_1\) es la pendiente de la recta, es decir, el grado de afectación de una unidad de la variable independiente en la variable dependiente. Se estableció, gracias al modelo de regresión lineal y del análisis realizado, que si existe correlación entre las variables estudiadas. En la práctica, se puede decir que cuando aumenta el área construida, también aumenta el precio del inmueble.

  • Sobre el modelo original: El modelo de regresión lineal aplicado a los datos del conjunto fue revisado frente a los supuestos que se deben cumplir, y todos fueron comprobados y verificados.

  • Sobre los modelos transformados: Con el objetivo de buscar si había otros modelos que mejoraran el rendimiento del modelo de regresión lineal se hicieron varias transformaciones. La comparación entre los 5 modelos, el inicial y las 4 transformaciones, arrojó que ninguno de los modelos producto de las transformaciones supera al modelo inicial, si tenemos en cuenta,por un lado, el valor de \(R^2\) para los modelos, pues todos los de las transformaciones son menores al del modelo original, y por otro lado, si miramos el Error Residual Estandar, el del modelo original es el más bajo de todos. Por lo anterior se puede deducir que, dados los datos existentes, el modelo de regresión lineal original es el mejor de todos los modelos estudiados.

  • Sobre la generalización o extrapolación del modelo: El modelo fue aplicado a los datos de los apartamentos en la ciudad de Cali, y tal como se dijo en los puntos anteriores, no fue tenida en cuenta la variable de zona, que es una variable que puede influir en el valor de los apartamentos. Nota: Las variables tipo y estrato sirvieron como filtro del conjunto de datos, estudiando solo los apartamentos del estrato 4.

  • Sobre trabajos futuros: Existe la posibilidad de aplicar un modelo de regresión lineal a un subconjunto de datos, lo que ofrecería mejores predicciones para ese subconjunto de datos, por ejemplo, teniendo en cuenta la zona y el estrato dentro de la misma ciudad.


7. Anexos

Todo este documento y código esta disponible aquí

Consigna de la Actividad 1

Basado en los datos de ofertas de vivienda descargadas del portal Fincaraiz para apartamento de estrato 4 con área construida menor a 200 m2 (vivienda4.RDS) la inmobiliaria A&C requiere el apoyo de un científico de datos en la construcción de un modelo que lo oriente sobre los precios de inmuebles.

Con este propósito el equipo de asesores ha diseñado los siguientes pasos para obtener un modelo y así poder a futuro determinar los precios de los inmuebles a negociar.

  1. Realice un análisis exploratorio de las variables precio de vivienda (millones de pesos COP) y área de la vivienda (metros cuadrados) - incluir gráficos e indicadores apropiados interpretados.

  2. Realice un análisis exploratorio bivariado de datos, enfocado en la relación entre la variable respuesta (precio) en función de la variable predictora (área construida) - incluir gráficos e indicadores apropiados interpretados.

  3. Estime el modelo de regresión lineal simple entre \(precio = f(area) + epsilon\). Interprete los coeficientes del modelo beta0, beta1 en caso de ser correcto.

  4. Construir un intervalo de confianza (95%) para el coeficiente beta1, interpretar y concluir si el coeficiente es igual a cero o no. Compare este resultado con una prueba de hipótesis t.

  5. Calcule e interprete el indicador de bondad \(R^2\).

  6. ¿Cuál sería el precio promedio estimado para un apartamento de 110 metros cuadrados? Considera entonces con este resultado que un apartamento en la misma zona con 110 metros cuadrados en un precio de 200 millones sería una atractiva esta oferta? ¿Qué consideraciones adicionales se deben tener?.

  7. Realice la validación de los supuestos del modelo por medio de gráficos apropiados, interpretarlos y sugerir posibles soluciones si se violan algunos de ellos. Utilice las pruebas de hipótesis para la validación de supuestos y compare los resultados con lo observado en los gráficos asociados.

  8. De ser necesario realice una transformación apropiada para mejorar el ajuste y supuestos del modelo.

  9. De ser necesario compare el ajuste y supuestos del modelo inicial y el transformado.

  10. Estime varios modelos y compare los resultados obtenidos. En el mejor de los modelos, ¿se cumplen los supuestos sobre los errores?

  11. Con los resultados obtenidos construya un informe para los directivos de la inmobiliaria, indicando el modelo apropiado y sus principales características. A este informe se deben añadir los anexos como evidencia de la realización de los pasos anteriores.

Conjunto de Datos

Descripción

Esta data contiene información sobre caracteristicas de viviendas de la ciudad de Cali.

¿Cómo se usa?: Solo hay que escribir “data(vivienda4)” sin las comillas.

Registros: Conjunto con 1706 registros y 5 variables

Variables/Columnas

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

  • estrato: Estrato donde esta la vivienda

  • preciom: Precio en millones de pesos

  • areaconst: Área construida en metros cuadrados

  • tipo: Tipo de vivienda

LS0tDQp0aXRsZTogIkFuw6FsaXNpcyBkZSBWaXZpZW5kYXMgcGFyYSBJbm1vYmlsaWFyaWEgQSZDIg0KYXV0aG9yOiAiRW5yaXF1ZSBKb3PDqSBQZcOxYSINCmRhdGU6ICIyMDI0LTA0LTEyIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIGNvbGxhcHNlZDogZmFsc2UNCiAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgdGhlbWU6IGZsYXRseQ0KICAgIGhpZ2hsaWdodDoga2F0ZQ0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6ICc0Jw0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAnNCcNCm51bWJlci1zZWN0aW9uczogdHJ1ZQ0Kc3VidGl0bGU6ICJBY3RpdmlkYWQgMyAtIE3DqXRvZG9zIHkgU2ltdWxhY2lvbiBFc3RhZMOtc3RpY2EgLSBQVUogQ2FsaSINCi0tLQ0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KDQpSLnZlcnNpb24NCmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJnZ3Bsb3QyIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQp9DQppZighcmVxdWlyZU5hbWVzcGFjZSgiZGV2dG9vbHMiLCBxdWlldGx5ID0gVFJVRSkpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJkZXZ0b29scyIpDQp9DQppZighcmVxdWlyZU5hbWVzcGFjZSgib3V0bGllcnMiLCBxdWlldGx5ID0gVFJVRSkpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJvdXRsaWVycyIpDQp9DQppZighcmVxdWlyZU5hbWVzcGFjZSgiZHBseXIiLCBxdWlldGx5ID0gVFJVRSkpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpDQp9DQppZighcmVxdWlyZU5hbWVzcGFjZSgidGlkeXZlcnNlIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCn0NCmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJsZXNzUiIsIHF1aWV0bHkgPSBUUlVFKSl7DQogIGluc3RhbGwucGFja2FnZXMoImxlc3NSIikNCn0NCmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJWSU0iLCBxdWlldGx5ID0gVFJVRSkpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJWSU0iKQ0KfQ0KaWYoIXJlcXVpcmVOYW1lc3BhY2UoImdndGhlbWVzIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZ2d0aGVtZXMiKQ0KfQ0KaWYoIXJlcXVpcmVOYW1lc3BhY2UoIkdHYWxseSIsIHF1aWV0bHkgPSBUUlVFKSl7DQogIGluc3RhbGwucGFja2FnZXMoIkdHYWxseSIpDQp9DQppZighcmVxdWlyZU5hbWVzcGFjZSgiUkNvbG9yQnJld2VyIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygiUkNvbG9yQnJld2VyIikNCn0NCmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJub3J0ZXN0IiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygibm9ydGVzdCIpDQp9DQppZighcmVxdWlyZU5hbWVzcGFjZSgic3RhcmdhemVyIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygic3RhcmdhemVyIikNCn0NCmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJwYXF1ZXRlTUVUT0RPUyIsIHF1aWV0bHkgPSBUUlVFKSl7DQogIGluc3RhbGwucGFja2FnZXMoInBhcXVldGVNRVRPRE9TIikNCn0NCmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJNQVNTIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygiTUFTUyIpDQp9DQpsaWJyYXJ5KG91dGxpZXJzKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZGV2dG9vbHMpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobGVzc1IpDQpsaWJyYXJ5KFZJTSkNCmxpYnJhcnkoZ2d0aGVtZXMpDQpsaWJyYXJ5KEdHYWxseSkNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KbGlicmFyeShub3J0ZXN0KQ0KbGlicmFyeShzdGFyZ2F6ZXIpDQpsaWJyYXJ5KHBhcXVldGVNRVRPRE9TKQ0KbGlicmFyeShNQVNTKQ0KYGBgDQoNCiMgKipSZXN1bWVuIEVqZWN1dGl2byoqDQoNCioqSW50cm9kdWNjacOzbioqDQoNCkVuIGVsIHByZXNlbnRlIHRyYWJham8gc2UgcHJldGVuZGUgY29uc3RydWlyIHVuIG1vZGVsbyBwcmVkaWN0aXZvIHF1ZSBwZXJtaXRhIHByZWRlY2lyIGVsIHZhbG9yIGRlIHVuIGFwYXJ0YW1lbnRvIGRlIGVzdHJhdG8gNCBlbiBsYSBjaXVkYWQgZGUgY2FsaSBhIHBhcnRpciBkZWwgw6FyZWEgY29uc3RydWlkYSBkZSBsb3MgbWlzbW9zLiAgU2UgcmVhbGl6YXLDoSBsYSB2ZXJpZmljYWNpw7NuIGRlIGxvcyBzdXB1ZXN0b3MgeSBzZSBjb250cmFzdGFyw6EgZWwgbW9kZWxvIGNvbiBvdHJvcyA0IG1vZGVsb3MgcXVlIHNvbiBwcm9kdWN0byBkZSB0cmFuc2Zvcm1hY2lvbmVzLCBwYXJhIGZpbmFsbWVudGUgZXNjb2dlciBlbCBtZWpvciBkZSBlbGxvcy4NCg0KKipNZXRvZG9sb2fDrWEqKg0KDQpQYXJhIGxsZWdhciBhIGxvcyByZXN1bHRhZG9zIHNlIGNvbnN0cnV5w7MgdW4gbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsIHkgc2UgcmVhbGl6YXJvbiB0cmFuc2Zvcm1hY2lvbmVzIGFsIG1pc21vIHBhcmEgY29ub2NlciBzaSBoYXkgYWxnw7puIG1vZGVsbyBjb24gbWVqb3JlcyByZXN1bHRhZG9zIHF1ZSBwdWVkYSByZWVtcGxhemFybG8uDQoNCi0gQ2FyZ2EgeSByZXZpc2nDs24gZ2VuZXJhbCBkZSBsYSBpbmZvcm1hY2nDs24NCi0gT3JkZW5hbWllbnRvIHkgbGltcGllemEgZGVsIGNvbmp1bnRvIGRlIGRhdG9zDQotIFRyYW5zZm9ybWFjacOzbiBkZWwgY29uanVudG8gZGUgZGF0b3MgeSB2aXN1YWxpemFjacOzbg0KLSBQcmVzZW50YWNpw7NuIGRlIGxvcyBSZXN1bHRhZG9zIHkgQ29uY2x1c2lvbmVzDQoNCioqUmVzdW1lbiBkZSBSZXN1bHRhZG9zKioNCg0KKiBDb3JyZWxhY2nDs24gZW50cmUgZWwgcHJlY2lvIHkgZWwgw6FyZWEgY29uc3RydWlkYQ0KDQpFbCBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwgY29uZmlybWEgbGEgY29ycmVsYWNpw7NuIHRlw7NyaWNhIGV4aXN0ZW50ZSBlbnRyZSBlbCDDoXJlYSBjb25zdHJ1aWRhIHkgZWwgcHJlY2lvIGRlIHVuIGlubXVlYmxlLg0KDQoqIE1vZGVsb3MgdHJhbnNmb3JtYWRvcw0KDQpOaW5ndW5vIGRlIGxhcyB0cmFuc2Zvcm1hY2lvbmVzIHJlYWxpemFkYXMgYXJyb2phcm9uIHVuIG1vZGVsbyBjb24gbWVqb3JlcyByZXN1bHRhZG9zIHkgYWp1c3RlcyBkZWwgbW9kZWxvIG9yaWdpbmFsLg0KDQoqKlN1Z2VyZW5jaWFzIGEgbW9kbyBkZSBDb25jbHVzaW9uZXMqKg0KDQpMb3MgcmVzdWx0YWRvcyBlbmNvbnRyYWRvcyBfbm8gc2UgcHVlZGVuIGdlbmVyYWxpemFyXyBwYXJhIG90cm9zIGVzdHJhdG9zIG8gdGlwb3MgZGUgdml2aWVuZGEsIHB1ZXMgc29uIGV4Y2x1c2l2b3MgcGFyYSBsb3MgYXBhcnRhbWVudG9zIGRlIGVzdHJhdG8gNCBkZSBsYSBjaXVkYWQgZGUgQ2FsaS4gU2UgcmVxdWVyaXLDrWFuIG1vZGVsb3MgcHJvcGlvcyBwYXJhIGNhZGEgKHN1Yiljb25qdW50byBkZSBkYXRvcyBwYXJhIHBvZGVyIGhhY2VyIHByZWRpY2Npb25lcyBkZSBwcmVjaW8gcGFyYSB2aXZpZW5kYXMgY29uIG90cmFzIGNhcmFjdGVyw61zdGljYXMuDQoNClBhcmEgdW4gZXN0dWRpbyBtw6FzIGRldGFsbGFkbyB5IHF1ZSBwdWVkYSBoYWNlciBtZWpvcmVzIHByZWRpY2Npb25lcywgc2Ugc3VnaWVyZSBzZWdtZW50YXIgbG9zIGRhdG9zIHBvciB6b25hLCB0aXBvIGRlIGlubXVlYmxlIHkgcG9yIGVzdHJhdG8sIHkgY29uc3RydWlyIG1vZGVsb3MgcHJvcGlvcyBwYXJhIGNhZGEgc3ViY29uanVudG8gZGUgZGF0b3MuIEVzdG8gaGFyw6EgcXVlIHNlIHRlbmdhbiBlbiBjdWVudGEgZXNhcyBjYXJhY3RlcsOtc3RpY2FzIGVuIGxhcyBwcmVkaWNjaW9uZXMgeSBxdWUgbGFzIG1pc21hcyBzZWFuIG1hcyBhY29yZGVzIGEgbGEgcmVhbGlkYWQuDQoNClNlIHByZXNlbnRhIGEgY29udGludWFjacOzbiB0b2RvIGVsIHByb2Nlc28gZGUgYW7DoWxpc2lzIHkgZGUgY29uc3RydWNjacOzbiBkZWwgbW9kZWxvIHF1ZSBzZSBsbGV2w7MgYSBjYWJvIHBhcmEgbGEgSW5tb2JpbGlhcmlhIEEmQy4NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDEuIEludHJvZHVjY2nDs24NCg0KRWwgbWVyY2FkbyBkZSBCaWVuZXMgUmHDrWNlcyBoYSBjcmVjaWRvIHNpZ25pZmljYXRpdmFtZW50ZSBlbiBsb3Mgw7psdGltb3MgYcOxb3MgZW4gbGEgY2l1ZGFkIGRlIENhbGkuIFBhcmEgZWwgYcOxbyAyMDIyIGxhcyB2ZW50YXMgZGUgaW5tdWVibGVzIGFsY2FuemFyb24gbG9zIFwkNi43MDAgbWlsbG9uZXMgZGUgcGVzb3MgeSBwYXJhIGVsIGHDsW8gMjAyMyBsYXMgdmVudGFzIGZ1ZXJvbiBkZSBcJDYuMTAwIG1pbGxvbmVzLiAgTGEgaW5tb2JpbGlhcmlhIEEmQyBxdWllcmUgY29uc3RydWlyIHVuIG1vZGVsbyBwcmVkaWN0aXZvIHF1ZSBsZXMgcGVybWl0YSBjb25vY2VyIGVsIHByZWNpbyBlc3RpbWFkbyBkZSB1biBpbm11ZWJsZSBkYWRhIGVsIHZhbG9yIGRlbCDDoXJlYSBjb25zdHJ1aWRhLg0KDQpBIGNvbnRpbnVhY2nDs24gc2UgbXVlc3RyYSBlbCBwcm9jZXNvIHF1ZSBzZSBsbGV2byBhIGNhYm8gcGFyYSBjcmVhciwgZXZhbHVhciB5IGVzY29nZXIgdW4gbW9kZWxvIHByZWRpY3Rpdm8gY29uIGJ1ZW5hcyBjYXJhY3RlcsOtc3RpY2FzIHF1ZSBzaXJ2aWVyYSBwYXJhIGxvcyBwcm9ww7NzaXRvcyBkZSBsYSBJbm1vYmlsaWFyaWEuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDIuIE9iamV0aXZvcw0KDQpDb25zdHJ1aXIgdW4gbW9kZWxvIHF1ZSBwZXJtaXRhIHByZWRlY2lyIGxvcyBwcmVjaW9zIGRlIGxvcyBpbm11ZWJsZXMgYSBuZWdvY2lhciwgYmFzYWRvIGVuIGVsIGNvbmp1bnRvIGRlIGRhdG9zIGRlIGxvcyBpbm11ZWJsZXMgY29uIG1lbm9zIGRlIDIwMCBtZXRyb3MgY3VhZHJhZG9zIGNvbnN0cnVpZG9zLg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyAzLiBQcm9jZXNvIFByZXBhcmF0b3JpbyB7LnRhYnNldH0gDQoNClJlYWxpemFyw6kgdW4gYW7DoWxpc2lzIGluaWNpYWwgYWwgY29uanVudG8gZGUgZGF0b3MgcGFyYSBkZXRlY3RhciByZWdpc3Ryb3MgdmFjw61vcywgdmFsb3JlcyBhdMOtcGljb3MgeSBkYXRvcyBxdWUgZGViYW4gZWxpbWluYXJzZS4gUG9zdGVyaW9ybWVudGUgc2UgcmVhbGl6YXLDoSB1biBhbsOhbGlzaXMgZGVzY3JpcHRpdm8geSBlc3RhZMOtc3RpY28gZGUgbG9zIGRhdG9zIGRlZmluaWVuZG8gbGFzIHZhcmlhYmxlcyBkZSBpbnRlcsOpcy4gRmluYWxtZW50ZSBzZSBjb25zdHJ1aXLDoSB5IGV2YWx1YXLDoSB1biBtb2RlbG8gcXVlIHBlcm1pdGEgcHJlZGVjaXIgZWwgdmFsb3IgZGUgdW5hIGNhc2EgYSBwYXJ0aXIgZGUgc3VzIHZhcmlhYmxlcyBpbmRlcGVuZGllbnRlcy4NCg0KIyMgMy4xLiBBbsOhbGlzaXMgaW5pY2lhbA0KDQpTZSBwcmVwYXJhbiBsYXMgbGlicmVyw61hcyBhIHV0aWxpemFyLCBzZSBjYXJnYW4gbG9zIGRhdG9zIHkgc2UgdmlzdWFsaXphIGxhIGNhYmVjZXJhIGRlbCBjb25qdW50byBkZSBkYXRvcyB2aXZpZW5kYTQgcXVlIHRpZW5lIGxvcyBpbm11ZWJsZXMgZGUgbWVub3MgZGUgMjAwIG1ldHJvcyBjdWFkcmFkb3MgcGFyYSBlbCBlc3RyYXRvIDQuDQoNCiANCmBgYHtyIGxvYWRfZGF0YSwgaW5jbHVkZT1GQUxTRX0NCiNkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImRnb254YWxleDgwL3BhcXVldGVNRVRPRE9TIikgI1NvbG8gdW5hIHZleiANCmxpYnJhcnkocGFxdWV0ZU1FVE9ET1MpICMgQ2FyZ2EgcGFxdWV0ZSBwYXF1ZXRlTUVUT0RPUw0KZGF0YSgidml2aWVuZGE0IikgIyBsb2FkIGRhdGEgJ1ZpdmllbmRhNCcgIGZyb20gIHBhcXVldGVNRVRPRE9TDQpzZXQuc2VlZCg2ODkpICMgRml4IHRoZSBzZWVkIGZvciByYW5kb20gbnVtYmVycw0KZGYgPC0gdml2aWVuZGE0DQpgYGANCg0KYGBge3Igdmlld19kYXRhfQ0KZGYNCmBgYA0KDQpgYGB7ciBzdW1tYXJ5fQ0Kc3VtbWFyeShkZiR6b25hKQ0KYGBgDQoNCg0KUG9kZW1vcyBvYnNlcnZhciBxdWUgZWwgY29uanVudG8gZXN0w6EgYmllbiBhY290YWRvIHkgdGllbmUgbGFzIHNpZ3VpZW50ZXMgdmFyaWFibGVzOg0KLSBab25hL196b25hXzogWm9uYSBlbiBkb25kZSBzZSB1YmljYSBsYSBjYXNhIChOb3J0ZSwgU3VyLCBDZW50cm8sIE9lc3RlLCBPcmllbnRlKQ0KLSBFc3RyYXRvL19lc3RyYXRvXzogUGFyYSBlc3RlIGNvbmp1bnRvIHRvZG9zIGxvcyBpbm11ZWJsZXMgcGVydGVuZWNlbiBhbCBlc3RyYXRvIDQNCi0gUHJlY2lvL19wcmVjaW9tXzogUHJlY2lvIGRlbCBpbm11ZWJsZQ0KLSDDgXJlYSBDb25zdHJ1aWRhL19hcmVhY29uc3RfOiDDgXJlYSBjb25zdHJ1aWRhIGVuIG1ldHJvcyBjdWFkcmFkb3MNCi0gVGlwbyBkZSBJbm11ZWJsZS9fdGlwb186IENhc2EgbyBBcGFydGFtZW50bw0KDQpBbnRlcyBkZSB2ZXIgY29tbyBzZSBkaXN0cmlidXllbiBsb3MgdmFsb3JlcyBkZSBsYXMgdmFyaWFibGVzLCB2ZWFtb3Mgc2kgaGF5IHZhbG9yZXMgbnVsb3MgZW4gZWxsYXM6DQoNCmBgYHtyIG1pc3NpbmdfZGF0YX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZmlnLndpZHRoID0gNCwgZmlnLmhlaWdodCA9IDQpDQptaXNzaW5nX2RhdGEgPC0gY29sU3Vtcyhpcy5uYShkZikpICU+JQ0KICAgICAgICAgICAgICAgICBhcy5kYXRhLmZyYW1lKCkgDQoNCm1pc3NpbmdfZGF0YQ0KDQpWSU06OmFnZ3IoZGYsIGNleC5heGlzID0gMC41LCBjZXgubGFiPSAwLjgpICANCmBgYA0KDQpTZSBwdWVkZSBub3RhciBxdWUgbm8gaGF5IHZhbG9yZXMgbnVsb3MgZW4gbmluZ8O6biByZWdpc3Ryby4gIEFob3JhIHZlYW1vcyBsYSBkaXN0cmlidWNpw7NuIGRlIGxhcyB2YXJpYWJsZXMgWm9uYSB5IFRpcG8gZGUgSW5tdWVibGU6DQoNCmBgYHtyIHN1bW1hcmllc30NCnN1bW1hcnkoZGYkem9uYSkNCnN1bW1hcnkoZGYkdGlwbykNCg0KYGBgDQpIYXkgdW5hIGFtcGxpYSBtYXlvcsOtYSBkZSBpbm11ZWJsZXMgZW4gbGEgem9uYSBTdXIuIEVuIGN1YW50byBhbCB0aXBvIGRlIGlubXVlYmxlLCBsYSBtYXlvcsOtYSBzb24gQXBhcnRhbWVudG9zLg0KKk5PVEE6KiBTZWfDum4gbGFzIGluZGljYWNpb25lcyBkZWwgcHJvZmVzb3IsIHNlIHJlYWxpemFyw6FuIHRvZG9zIGxvcyBwdW50b3MgY29uIHVuIHN1YmNvbmp1bnRvIGRlIGRhdG9zIHF1ZSBjb3JyZXNwb25kYSBfc29sYW1lbnRlXyBhIGxvcyBhcGFydGFtZW50b3MuDQoNCiMjIDMuMi4gTGltcGllemEgeSBQcmVwYXJhY2nDs24gZGUgbG9zIGRhdG9zDQoNClBvciBzZXIgdW4gc3ViY29uanVudG8gZGUgZGF0b3MgeWEgZmlsdHJhZG8sIHNlIHB1ZWRlIG5vdGFyIHF1ZSBubyBleGlzdGVuIHJlZ2lzdHJvcyB2YWPDrW9zIG5pIGNvbHVtbmFzIGNvbiBkYXRvcyBmYWx0YW50ZXMsIHRhbCBjb21vIHNlIGRldGVjdMOzIGVuIGxhIHNlY2Npw7NuIGFudGVyaW9yLiBFc3RhIGVzIHVuYSBzaXR1YWNpw7NuIGJhc3RhbnRlIGF0w61waWNhIGVuIGVsIHByb2Nlc28gZGUgZGVzYXJyb2xsYXIgdW4gbW9kZWxvLiAgU2UgcmVhbGl6YXLDoSBlbCBmaWx0cmFkbyBwYXJhIHF1ZSBxdWVkZW4gc29sbyBsb3MgYXBhcnRhbWVudG9zLg0KDQpgYGB7ciBhcHRfZmlsdGVyfQ0KZGYgPC0gZmlsdGVyKGRmLCAhZGYkdGlwbyA9PSAiQ2FzYSIpDQpkZg0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDQuIERlc2Fycm9sbG8gZGVsIGVqZXJjaWNpbw0KDQojIyA0LjEuIEFuw6FsaXNpcyBleHBsb3JhdG9yaW8gZGVsIFByZWNpbyB5IGVsIMOBcmVhIHsudGFic2V0fQ0KDQpfUmVhbGljZSB1biBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvIGRlIGxhcyB2YXJpYWJsZXMgcHJlY2lvIGRlIHZpdmllbmRhIChtaWxsb25lcyBkZSBwZXNvcyBDT1ApIHkgw6FyZWEgZGUgbGEgdml2aWVuZGEgKG1ldHJvcyBjdWFkcmFkb3MpIC0gaW5jbHVpciBncsOhZmljb3MgZSBpbmRpY2Fkb3JlcyBhcHJvcGlhZG9zIGludGVycHJldGFkb3MuXw0KDQojIyMgNC4xLjEuIFByZWNpbyBkZSBsYSB2aXZpZW5kYSANCg0KQSBjb250aW51YWNpw7NuLCBzZSBtdWVzdHJhIGxhICJlc3RhZMOtc3RpY2EgZGVzY3JpcHRpdmEiIHBhcmEgbGEgdmFyaWFibGUgcXVlIG11ZXN0cmEgZWwgdmFsb3IgZGVsIGlubXVlYmxlIGVuIG1pbGxvbmVzIGRlIHBlc29zLiBDb250aWVuZSAkMS4zNjMkIHJlZ2lzdHJvcyBkZSBhcGFydGFtZW50b3MuDQoNCmBgYHtyIHN1bW1hcnlfcHJlY2lvbX0NCnN1bW1hcnl0b29sczo6ZGVzY3IoZGYkcHJlY2lvbSkNCmBgYA0KLSBMbyBwcmltZXJvIHF1ZSBub3MgZW50cmVnYSBsYSBlc3RhZMOtc3RpY2EgZGVzY3JpcHRpdmEgZXMgZWwgcHJvbWVkaW8gZGVsIHZhbG9yIGRlIGxvcyBpbm11ZWJsZXMsIHF1ZSBlcyAkXCQyMzcuNjgkIG1pbGxvbmVzIGRlIHBlc29zLCBlbiB1biByYW5nbyBkZSBlbnRyZSAkXCQyMDckIHkgJFwkMzA1JCBtaWxsb25lcyBkZSBwZXNvcy4gDQotIEVsIHByaW1lciBjdWFydGlsIG5vcyBpbmRpY2EgcXVlIGVsICQyNVwlJCBkZSBsYXMgdml2aWVuZGFzIHRpZW5lIHVuIHByZWNpbyBpZ3VhbCBvIG1lbm9yIGRlICRcJDIyOC43OSQgbWlsbG9uZXMuDQotIExhIG1lZGlhbmEgZXMgZGUgJFwkMjM2LjE0JCBtaWxsb25lcywgbG8gcXVlIGluZGljYSBxdWUgbGEgbWl0YWQgZGUgbG9zIGlubXVlYmxlcyB0aWVuZW4gdW4gdmFsb3IgaW5mZXJpb3IsIHkgbGEgb3RyYSBtaXRhZCB1bm8gaWd1YWwgbyBtYXlvci4NCi0gRWwgdGVyY2VyIGN1YXJ0aWwgZXMgZGUgJFwkMjQzLjUkIG1pbGxvbmVzLCBsbyBxdWUgaW5kaWNhIHF1ZSBlbCAkNzVcJSQgZGUgbGFzIHZpdmllbmRhcyB0aWVuZW4gdW4gdmFsb3IgaWd1YWwgbyBpbmZlcmlvciBhbCBpbmRpY2Fkby4NCi0gTGEgdmFyaWFibGUgdGllbmUgdW5hIGRlc3ZpYWNpw7NuIGVzdMOhbmRhciBkZSAkMTMuMjkkIGxvIHF1ZSBpbmRpY2EgY2llcnRhIHZhcmlhYmlsaWRhZCBlbiBsb3MgcHJlY2lvcy4NCi0gTGEgRGVzdmlhY2nDs24gYWJzb2x1dGEgbWVkaWFuYSAoTUFEKSBlcyB1bmEgbWVkaWRhIGRlIGRpc3BlcnNpw7NuIHJvYnVzdGEgZnJlbnRlIGEgbG9zIHZhbG9yZXMgYXTDrXBpY29zIHB1ZXMgcmVwcmVzZW50YSBsYSBtZWRpYW5hIGRlIGxhcyBkaWZlcmVuY2lhcyBhYnNvbHV0YXMgcmVzcGVjdG8gYSBsYSBtZWRpYW5hLiBFbiBlc3RlIGNhc28gZXMgJDEwLjk4JC4NCi0gRWwgcmFuZ28gZW50cmUgY3VhcnRpbGVzIChRMyB5IFExKSBlcyBkZSAkMTQuNzkkLCBlcyBkZWNpciwgZWwgJDUwXCUkIGRlIGxvcyBkYXRvcyBjZW50cmFsZXMgdGllbmVuIGVzYSBkaWZlcmVuY2lhIGRlIHByZWNpbyAoZW4gbWlsbG9uZXMgZGUgcGVzb3MpDQotIFRpZW5lIHVuIENvZWZpY2llbnRlIGRlIFZhcmlhY2nDs24gZGUgJDAsMDYkIGxvIHF1ZSBub3MgZGljZSBxdWUgaGF5IHVuYSB2YXJpYWJpbGlkYWQgYmFqYSBlbiByZWxhY2nDs24gYSBsYSBtZWRpYS4NCi0gRWwgc2tld25lc3MsIHNlc2dvIG8gYXNpbWV0csOtYSBlcyBkZSAkMS4yOCQgbG8gcXVlIHN1Z2llcmUgdW5hIGRpc3RyaWJ1Y2nDs24gc2VzZ2FkYSBoYWNpYSBsYSBkZXJlY2hhLCBlcyBkZWNpciwgcXVlIGhheSBtYXMgcHJlY2lvcyBwb3IgZW5jaW1hIGRlIGxhIG1lZGlhIHF1ZSBwb3IgZGViYWpvLiBFc3RvIHN1Z2llcmUgcXVlIGhheSB1bmEgY29uY2VudHJhY2nDs24gZGUgcHJlY2lvcyBtw6FzIGJham9zIHkgdW5hIGRpc3BlcnNpw7NuIGRlIHByZWNpb3MgbcOhcyBhbHRvcy4NCi0gTGEgQ3VydG9zaXMgKEt1cnRvc2lzKSBlcyAkMy4xOSQgbG8gcXVlIGluZGljYSBxdWUgbGEgZGlzdHJpYnVjacOzbiB0aWVuZSBjb21wb3J0YW1pZW50byBkZSB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwuIEVzdGUgdmFsb3Igc3VnaWVyZSBxdWUgaGF5IG3DoXMgcHJlY2lvcyBhbHJlZGVkb3IgZGUgbGEgbWVkaWEgeSBjb2xhcyBtw6FzIHBlc2FkYXMuDQoNClZlYW1vcyBncsOhZmljYW1lbnRlIGxhIGRpc3RyaWJ1Y2nDs24gY29uIHVuIGRpYWdyYW1hIGRlIGNhamFzIHkgYmlnb3RlcyB5IHVuIGhpc3RvZ3JhbWEgcGFyYSBsYSB2YXJpYWJsZSBwcmVjaW9tOg0KDQoNCg0KYGBge3IgYmxveF9wbG90X3ByZWNpb219DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy53aWR0aCA9IDQsIGZpZy5oZWlnaHQgPSA0KQ0KIyBHZW5lcmF0ZSBib3hwbG90DQpmaWxsY29sb3IgPSAibGlnaHRncmVlbiINCmxpbmVjb2xvciA9ICIjMDhDNjcxIg0KZ2dwbG90KGRmLCBhZXNfc3RyaW5nKHggPSBkZiRwcmVjaW9tKSkgKw0KICBnZW9tX2JveHBsb3QoZmlsbCA9IGZpbGxjb2xvciwNCiAgICAgICAgICAgICAgIG91dGxpZXIuc2l6ZSA9IDEsDQogICAgICAgICAgICAgICBvdXRsaWVyLnNoYXBlID0gMjQpICsNCiAgbGFicyh0aXRsZSA9ICJEaWFncmFtYSBkZSBDYWphcyB5IEJpZ290ZXMgcGFyYSBQcmVjaW8gZGUgSW5tdWVibGUiLA0KICAgICAgIHggPSAiUHJlY2lvIChtaWxsb25lcyBkZSBwZXNvcykiLCB5ID0gIkRpc3RyaWJ1Y2lvbiIpICsNCiAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwLCAzMjAsIGJ5ID0gMTApKSArICMgTWFya3MgZXZlcnkgMTAgbWlsbGlvbnMNCiAgdGhlbWVfdHVmdGUoKQ0KYGBgDQoNClNlIHB1ZWRlIG9ic2VydmFyIHF1ZSBwb3IgZW5jaW1hIGRlIDI2NSBtaWxsb25lcyBkZSBwZXNvcyAoYXByb3hpbWFkYW1lbnRlKSwgbG9zIHByZWNpb3MgZGUgbG9zIGFwYXJ0YW1lbnRvcyBzZSBjb252aWVydGVuIGVuIHZhbG9yZXMgYXTDrXBpY29zLCB5IHF1ZSBlbCAkNTBcJSQgY2VudHJhbCBzZSBlbmN1ZW50cmEgZGlzdHJpYnVpZG8gYWxyZWRlZG9yIGRlIHVuIHBvY28gbWVub3MgZGUgJDIzMCQgeSB1biBwb2NvIG3DoXMgZGUgJDI0MCQgbWlsbG9uZXMgZGUgcGVzb3MuIE5vIG11ZXN0cmEgdmFsb3JlcyBhdMOtcGljb3MgZW4gbG9zIHZhbG9yZXMgYmFqb3MuDQoNCmBgYHtyIGhpc3RvZ3JhbV9wcmVjaW9tfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcud2lkdGggPSA0LCBmaWcuaGVpZ2h0ID0gNCkNCnRzID0gMC44ICN0ZXh0IHNpemUNCmZpbGxjb2xvciA9ICJsaWdodGdyZWVuIg0KbGluZWNvbG9yID0gIiMwOEM2NzEiDQoNCiMgR3LDoWZpY28gZGUgaGlzdG9ncmFtYQ0KcGFyKGNleCA9IHRzKSAjIEFqdXN0YXIgdGFtYcOxbyBkZSB0ZXh0byBkZW50cm8gZGVsIGdyw6FmaWNvDQpoaXN0KGRmJHByZWNpb20sIA0KICAgICAgbWFpbiA9ICJIaXN0b2dyYW1hIHBhcmEgYXBhcnRhbWVudG9zIGRlIG1lbm9zIGRlIDIwMCBtMiIsDQogICAgICB5bGFiID0gIkZyZWN1ZW5jaWEiLA0KICAgICAgeGxhYiA9ICJQcmVjaW8gKGVuIG1pbGxvbmVzIGRlIHBlc29zKSIsDQogICAgICBjb2wgPSBmaWxsY29sb3IsDQogICAgICBib3JkZXIgPSBsaW5lY29sb3IpDQoNCmBgYA0KDQpMYSBtYXlvciBjYW50aWRhZCBkZSBwcmVjaW9zIGRlIGNhc2FzIHNlIGVuY3VlbnRyYW4gYXByb3hpbWFkYW1lbnRlIGVudHJlICQyMzAkIHkgJDI0MCQgbWlsbG9uZXMgZGUgcGVzb3MsIHNlZ3VpZG9zIHBvciBsb3MgcmFuZ29zIGFwcm94aW1hZG9zIGRlICQyMjAtMjMwJCB5ICQyNDAtMjUwJCBtaWxsb25lcyBkZSBwZXNvcyByZXNwZWN0aXZhbWVudGUuDQoNClBvciDDumx0aW1vLCB2ZWFtb3MgZWwgZ3LDoWZpY28gZGUgZGVuc2lkYWQgZGUgZGlzdHJpYnVjacOzbiBkZSBsb3MgcHJlY2lvcy4NCmBgYHtyIHByZWNpb21fZGVuc2l0eX0NCg0KIyBHZW5lcmFyIGVsIGhpc3RvZ3JhbWEgZGUgZGVuc2lkYWQNCmdncGxvdChkZiwgYWVzKHggPSBwcmVjaW9tKSkgKw0KICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJsaWdodGdyZWVuIikgKw0KICBsYWJzKHRpdGxlID0gIkRlbnNpZGFkIGRlIHByZWNpb3MiLCB4ID0gIlByZWNpbyIsIHkgPSAiRGVuc2lkYWQiKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4oZGYkcHJlY2lvbSksIGNvbG9yID0gImRhcmtncmVlbiIsIGxpbmV0eXBlID0gNCkNCg0KYGBgDQoNCg0KIyMjIDQuMS4yLiDDgXJlYSBDb25zdHJ1aWRhIGRlIGxhIHZpdmllbmRhDQoNCkEgY29udGludWFjacOzbiwgc2UgbXVlc3RyYSBsYSAiZXN0YWTDrXN0aWNhIGRlc2NyaXB0aXZhIiBwYXJhIGxhIHZhcmlhYmxlIHF1ZSBtdWVzdHJhIGVsIMOBcmVhIENvbnN0cnVpZGEgZGUgbG9zIGFwYXJ0YW1lbnRvcyBxdWUgY29udGllbmUgJDEuMzYzJCByZWdpc3Ryb3MuDQoNCmBgYHtyIHN1bW1hcnlfYXJlYWNvbnN0fQ0Kc3VtbWFyeXRvb2xzOjpkZXNjcihkZiRhcmVhY29uc3QpDQpgYGANCg0KLSBFbCBwcm9tZWRpbyBkZWwgw6FyZWEgZGUgbG9zIGlubXVlYmxlcywgZXMgJDc1LjQ4JCBtZXRyb3MgY3VhZHJhZG9zLCBlbiB1biByYW5nbyBkZSBlbnRyZSAkNDAkIHkgJDIwMCQgbWV0cm9zIGN1YWRyYWRvcy4gDQotIEVsIHByaW1lciBjdWFydGlsIG5vcyBpbmRpY2EgcXVlIGVsICQyNVwlJCBkZSBsYXMgdml2aWVuZGFzIHRpZW5lIHVuIMOhcmVhIGlndWFsIG8gbWVub3IgZGUgNjAgbWV0cm9zIGN1YWRyYWRvcy4NCi0gTGEgbWVkaWFuYSBlcyBkZSAkNzAkIG1ldHJvcyBjdWFkcmFkb3MsIGxvIHF1ZSBpbmRpY2EgcXVlIGxhIG1pdGFkIGRlIGxvcyBpbm11ZWJsZXMgdGllbmVuIHVuIHZhbG9yIGluZmVyaW9yLCB5IGxhIG90cmEgbWl0YWQgdW5vIGlndWFsIG8gbWF5b3IuDQotIEVsIHRlcmNlciBjdWFydGlsIGVzIGRlICQ4NCQgbWV0cm9zIGN1YWRyYWRvcywgbG8gcXVlIGluZGljYSBxdWUgZWwgJDc1XCUkIGRlIGxhcyB2aXZpZW5kYXMgdGllbmVuIHVuIHZhbG9yIGlndWFsIG8gaW5mZXJpb3IgYWwgaW5kaWNhZG8uDQotIExhIHZhcmlhYmxlIHRpZW5lIHVuYSBkZXN2aWFjacOzbiBlc3TDoW5kYXIgZGUgMjIuNTYgbG8gcXVlIGluZGljYSB1bmEgdmFyaWFiaWxpZGFkIG1vZGVyYWRhIGVuIGxvcyBwcmVjaW9zLg0KLSBFbCBNQUQgbyBEZXN2aWFjacOzbiBhYnNvbHV0YSBtZWRpYW5hIGVzIGRlICQxNC44MyQuDQotIEVsIElRUiBvIHJhbmdvIGVudHJlIGN1YXJ0aWxlcyAoUTMgeSBRMSkgZXMgZGUgJDI0JCwgZXMgZGVjaXIsIGVsICQ1MFwlJCBkZSBsb3MgZGF0b3MgY2VudHJhbGVzIHRpZW5lbiBlc2EgZGlmZXJlbmNpYSBkZSDDoXJlYSAoZW4gbWV0cm9zIGN1YWRyYWRvcyBkZSBwZXNvcykNCi0gVGllbmUgdW4gQ29lZmljaWVudGUgZGUgVmFyaWFjacOzbiBkZSAkMC4zJCBsbyBxdWUgbm9zIGRpY2UgcXVlIGhheSB1bmEgdmFyaWFiaWxpZGFkIG1vZGVyYWRhIGRlbCB0YW1hw7FvIGRlbCDDoXJlYSBlbiByZWxhY2nDs24gYSBsYSBtZWRpYS4NCi0gRWwgc2tld25lc3MsIHNlc2dvIG8gYXNpbWV0csOtYSBlcyBkZSAkMi4wOCQuIEFsIHNlciBwb3NpdGl2byBzdWdpZXJlIHF1ZSBsYSBkaXN0cmlidWNpw7NuIHRpZW5lIHVuYSBjb2xhIGhhY2lhIGxhIGRlcmVjaGEsIGVzIGRlY2lyLCBxdWUgaGF5IG3DoXMgw6FyZWFzIHBvciBlbmNpbWEgZGUgbGEgbWVkaWEgcXVlIHBvciBkZWJham8uIEVzdG8gaW5kaWNhIHF1ZSBoYXkgdW5hIGNvbmNlbnRyYWNpw7NuIGRlIMOhcmVhcyBtw6FzIGJham9zIHkgdW5hIGRpc3BlcnNpw7NuIGRlIMOhcmVhcyBtw6FzIGFsdGFzLg0KLSBMYSBDdXJ0b3NpcywgcXVlIG1pZGUgbGEgY3VydmF0dXJhIGRlIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGRhdG9zLCBlcyBkZSAkNi4zMiQgbG8gcXVlIHN1Z2llcmUgdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsIHF1ZSB0aWVuZSB1bmEgbWF5b3IgY29uY2VudHJhY2nDs24gZGUgdmFsb3JlcyBkZSDDoXJlYXMgY29uc3RydWlkYXMgYWxyZWRlZG9yIGRlIGxhIG1lZGlhIHkgY29sYXMgbWFzIHBlc2FkYXMsIGVzcGVjaWFsbWVudGUgaGFjaWEgbG9zIHZhbG9yZXMgbcOhcyBhbHRvcy4NCkFob3JhIHZlYW1vcyBncsOhZmljYW1lbnRlIGxhIGRpc3RyaWJ1Y2nDs24gY29uIHVuIGRpYWdyYW1hIGRlIGNhamFzIHkgYmlnb3RlcyB5IHVuIGhpc3RvZ3JhbWEgcGFyYSBsYSB2YXJpYWJsZSBhcmVhY29uc3Q6DQoNCg0KYGBge3IgYmxveF9wbG90X2FyZWFjb25zdH0NCiMgR2VuZXJhdGUgYm94cGxvdA0KZmlsbGNvbG9yID0gImxpZ2h0Z3JlZW4iDQpsaW5lY29sb3IgPSAiIzA4QzY3MSINCmdncGxvdChkZiwgYWVzX3N0cmluZyh4ID0gZGYkYXJlYWNvbnN0KSkgKw0KICBnZW9tX2JveHBsb3QoZmlsbCA9IGZpbGxjb2xvciwNCiAgICAgICAgICAgICAgIG91dGxpZXIuc2l6ZSA9IDEsDQogICAgICAgICAgICAgICBvdXRsaWVyLnNoYXBlID0gMjQpICsNCiAgbGFicyh0aXRsZSA9ICJEaWFncmFtYSBkZSBDYWphcyB5IEJpZ290ZXMgcGFyYSBBcmVhIGRlIElubXVlYmxlIiwNCiAgICAgICB4ID0gIk1ldHJvcyBjdWFkcmFkb3MgY29uc3RydWlkb3MiLCB5ID0gIkRpc3RyaWJ1Y2lvbiIpICsNCiAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGRmJGFyZWFjb25zdCksIG1heChkZiRhcmVhY29uc3QpLCBieSA9IDEwKSkgKyAjIE1hcmtzIGV2ZXJ5IDEwIG1pbGxpb25zDQogIHRoZW1lX3R1ZnRlKCkNCmBgYA0KDQpTZSBwdWVkZSBvYnNlcnZhciBxdWUgYWwgYWNlcmNhcnNlIGEgbG9zICQxMjAkIG1ldHJvcyBjdWFkcmFkb3MgY29uc3RydWlkb3MsIGxvcyDDoXJlYXMgZGUgbG9zIGlubXVlYmxlcyBzZSBjb252aWVydGVuIGVuIHZhbG9yZXMgYXTDrXBpY29zLCBlcyBkZWNpciwgcG9jbyBjb211bmVzLCB5IHF1ZSBlbCAkNTBcJSQgY2VudHJhbCBzZSBlbmN1ZW50cmEgZGlzdHJpYnVpZG8gYWxyZWRlZG9yIGRlICQ2MCQgeSAkODQkIG1ldHJvcyBjdWFkcmFkb3MgKFEzKS4NCg0KYGBge3IgaGlzdG9ncmFtX2FyZWFjb25zdH0NCnRzID0gMC44ICN0ZXh0IHNpemUNCmZpbGxjb2xvciA9ICJsaWdodGdyZWVuIg0KbGluZWNvbG9yID0gIiMwOEM2NzEiDQoNCiMgR3LDoWZpY28gZGUgaGlzdG9ncmFtYQ0KcGFyKGNleCA9IHRzKSAjIEFqdXN0YXIgdGFtYcOxbyBkZSB0ZXh0byBkZW50cm8gZGVsIGdyw6FmaWNvDQpoaXN0KGRmJGFyZWFjb25zdCwgDQogICAgICBtYWluID0gIkhpc3RvZ3JhbWEgcGFyYSBBcGFydGFtZW50b3MgZGUgbWVub3MgZGUgMjAwIG0yIiwNCiAgICAgIHlsYWIgPSAiRnJlY3VlbmNpYSIsDQogICAgICB4bGFiID0gIk1ldHJvcyBjdWFkcmFkb3MgY29uc3RydWlkb3MiLA0KICAgICAgY29sID0gZmlsbGNvbG9yLA0KICAgICAgYm9yZGVyID0gbGluZWNvbG9yKQ0KDQpgYGANCg0KTGEgbWF5b3IgY2FudGlkYWQgZGUgw6FyZWFzIGRlIGFwYXJ0YW1lbnRvcyBzZSBlbmN1ZW50cmEgIGVudHJlICQ1MCQgeSAkNjAkIG1ldHJvcyBjdWFkcmFkb3MsIHNlZ3VpZG9zIHBvciBsb3MgcmFuZ29zIGFwcm94aW1hZG9zIGRlICQ3MC04MCQgeSAkNjAtNzAkIG1ldHJvcyBjdWFkcmFkb3MuIFNlIHZlIHF1ZSBoYXkgdW5hIGNpZXJ0YSBjYW50aWRhZCBkZSB2YWxvcmVzIGhhY2lhIGxhIGRlcmVjaGEgZGVsIGhpc3RvZ3JhbWEgZGVzZGUgbG9zICQxMzAkIGhhc3RhICQyMDAkIG1ldHJvcyBjb25zdHJ1aWRvcy4NCg0KQWhvcmEgdmVhbW9zIGVsIGdyw6FmaWNvIGRlIGRlbnNpZGFkIGRlIGRpc3RyaWJ1Y2nDs24gZGUgbGFzIMOhcmVhcyBjb25zdHJ1aWRhcy4NCg0KYGBge3IgYXJlYWNvbnN0X2RlbnNpdHl9DQoNCiMgR2VuZXJhciBlbCBoaXN0b2dyYW1hIGRlIGRlbnNpZGFkDQpnZ3Bsb3QoZGYsIGFlcyh4ID0gYXJlYWNvbnN0KSkgKw0KICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJsaWdodGdyZWVuIikgKw0KICBsYWJzKHRpdGxlID0gIkRlbnNpZGFkIGRlIHByZWNpb3MiLCB4ID0gIsOBcmVhIGNvbnN0cnVpZGEiLCB5ID0gIkRlbnNpZGFkIikgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuKGRmJGFyZWFjb25zdCksIGNvbG9yID0gImRhcmtncmVlbiIsIGxpbmV0eXBlID0gNCkNCg0KYGBgDQoNCiMjIDQuMi4gQW7DoWxpc2lzIGV4cGxvcmF0b3JpbyBiaXZhcmlhZG8NCg0KX1JlYWxpY2UgdW4gYW7DoWxpc2lzIGV4cGxvcmF0b3JpbyBiaXZhcmlhZG8gZGUgZGF0b3MsIGVuZm9jYWRvIGVuIGxhIHJlbGFjacOzbiBlbnRyZSBsYSB2YXJpYWJsZSByZXNwdWVzdGEgKHByZWNpbykgZW4gZnVuY2nDs24gZGUgbGEgdmFyaWFibGUgcHJlZGljdG9yYSAow6FyZWEgY29uc3RydWlkYSkgLSBpbmNsdWlyIGdyw6FmaWNvcyBlIGluZGljYWRvcmVzIGFwcm9waWFkb3MgaW50ZXJwcmV0YWRvcy5fDQoNClZlYW1vcyBsYSByZWxhY2nDs24gZW50cmUgbGFzIHZhcmlhYmxlcyAqKnByZWNpb20qKiB5ICoqYXJlYWNvbnN0KiouIFNlIGVzcGVyYSBxdWUgZW50cmUgbcOhcyDDoXJlYSBjb25zdHJ1aWRhLCBlbCBwcmVjaW8gc2VhIG3DoXMgYWx0by4gVW4gY29tcG9ydGFtaWVudG8gZGlmZXJlbnRlIGEgZXN0ZSwgc2kgYmllbiBwdWVkZSBzZXIgcG9zaWJsZSBlbiBsYSBwcsOhY3RpY2EsIGVzIHBvY28gcHJvYmFibGUgeSBhbHRlcmEgbGEgaG9tb2dlbmVpZGFkIGRlIGxvcyBkYXRvcy4gUGFyYSBlc3RlIGVzdHVkaW8sIHNpIHNvbiBwb2NvcyBlc3RvcyB2YWxvcmVzIGF0w61waWNvcywgc2UgZWxpbWluYXLDoW4uDQoNClNlIHJlcHJlc2VudGFyw6FuIGdyw6FmaWNhbWVudGUgbGFzICoqZGlzdGFuY2lhcyBkZSBNYWhhbGFub2JpcywqKiBxdWUgZXMgdW5hDQoqbWVkaWRhIGRlIGxhIGRpc3RhbmNpYSBlbnRyZSB1biBwdW50byB5IHVuYSBkaXN0cmlidWNpw7NuIG11bHRpdmFyaWFudGUuKg0KRXMgdW5hIG1lZGlkYSDDunRpbCBwYXJhIGRldGVjdGFyIHZhbG9yZXMgYXTDrXBpY29zIGVuIHVuIGNvbmp1bnRvIGRlDQpkYXRvcyBtdWx0aWRpbWVuc2lvbmFsIGN1YW5kbyBsYXMgdmFyaWFibGVzIGVzdGFuIGNvcnJlbGFjaW9uYWRhcy4gTGEgZGlzdGFuY2lhIGVzIHVuYSBtZWRpZGEgZGUgbGEgZGlzdGFuY2lhIGVuIHVuaWRhZGVzIGRlIGRlc3ZpYWNpb25lcyBlc3TDoW5kYXIsIHBvciBsbyB0YW50bywgdW4gdmFsb3IgYWx0byBkZSBsYSBkaXN0YW5jaWEgaW5kaWNhIHF1ZSBlbCBwdW50byBlc3RhIGxlam9zIGRlIGxhIGRpc3RyaWJ1Y2nDs24gbXVsdGl2YXJpYW50ZS4gVMOtcGljYW1lbnRlLCBsb3MgcHVudG9zIGNvbiB1bmEgZGlzdGFuY2lhIG1heW9yIGEgMyBzZSBjb25zaWRlcmFuIGF0w61waWNvcy4gTGEgZGlzdGFuY2lhIE1haGFsYW5vYmlzIG5vIHNlIGFmZWN0YSBwb3IgbGEgZXNjYWxhIGRlIGxhcyB2YXJpYWJsZXMgeSBlcyBzZW5zaWJsZSBhIGxhIGNvcnJlbGFjacOzbiBlbnRyZSBsYXMgdmFyaWFibGVzLg0KDQpgYGB7ciBNYWhhbGFub2Jpc19kaXN0YW5jZV9wcmljZV9hcmVhfQ0KDQpudW1lcmljX2NvbHVtbnMgPC0gbmFtZXMoZGYpW3NhcHBseShkZiwgaXMubnVtZXJpYyldDQpleGNsdWRlX2NvbHVtbnMgPC0gYygpICNTZSB1c2FyYW4gbGFzIGRvcyDDum5pY2FzIHZhcmlhYmxlcyBudW3DqXJpY2FzIGRlbCBjb25qdW50bw0KbnVtZXJpY19jb2x1bW5zIDwtIHNldGRpZmYobnVtZXJpY19jb2x1bW5zLCBleGNsdWRlX2NvbHVtbnMpDQpjb3ZfbWF0cml4IDwtIGNvdihkZlssIG51bWVyaWNfY29sdW1uc10pDQphdGlwaWNvcyA8LSBtYWhhbGFub2JpcyhkZlssIG51bWVyaWNfY29sdW1uc10sIGNlbnRlciA9IFRSVUUsIGNvdiA9IGNvdl9tYXRyaXgpDQoNCmdncGxvdChkZiwgYWVzX3N0cmluZyh4ID0gJ3ByZWNpb20nLCB5ID0gJ2FyZWFjb25zdCcsIGNvbG9yID0gImF0aXBpY29zIikpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMiwgYWxwaGEgPSAwLjUpICsNCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU3BlY3RyYWwiKSArIA0KICBzY2FsZV9jb2xvcl9jb250aW51b3VzKGxvdyA9ICJsaWdodGdyZWVuIiwgaGlnaCA9ICJkYXJrZ3JlZW4iKSArDQogIGxhYnModGl0bGUgPSAiUmVsYWNpb24gZW50cmUgcHJlY2lvIHkgQXJlYSBjb25zdHJ1aWRhXG4gc2VndW4gZGlzdGFuY2lhIGRlIE1haGFsYW5vYmlzIiwgDQogICAgICAgeCA9ICJQcmVjaW8gZGVsIG1ldHJvIGN1YWRyYWRvIiwgeSA9ICJBcmVhIGNvbnN0cnVpZGEgZW4gbWV0cm9zIGN1YWRyYWRvcyIsIA0KICAgICAgIGNvbG9yID0gIkRpc3RhbmNpYSBkZSBNYWhhbGFub2JpcyIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMobWluKGRmJHByZWNpb20pLCBtYXgoZGYkcHJlY2lvbSkgKyAxMCkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKG1pbihkZiRhcmVhY29uc3QpLCBtYXgoZGYkYXJlYWNvbnN0KSArIDEwKSkgDQoNCmBgYA0KDQpQb2RlbW9zIHZlciBxdWUgYSBtZWRpZGEgcXVlIGVsIMOhcmVhIGF1bWVudGEsIHRhbWJpw6luIGF1bWVudGEgZWwgcHJlY2lvIGRlbCBpbm11ZWJsZSwgZXMgZGVjaXIsIGhheSB1bmEgcmVsYWNpw7NuIGxpbmVhbCBwb3NpdGl2YSBlbnRyZSBwcmVjaW9tIHkgYXJlYWNvbnN0LiAgU2kgdmFsaWRhbW9zIG51bcOpcmljYW1lbnRlIGxvIHF1ZSBzZSB2ZSBlbiBlbCBncsOhZmljbyBhbnRlcmlvciwgcG9kZW1vcyBjb3Jyb2JvcmFybG8gY29uIGxhIGZ1bmNpw7NuIF9jb3JfLiAgVmVhbW9zOg0KYGBge3J9DQpjb3IoZGYkcHJlY2lvbSxkZiRhcmVhY29uc3QpDQpgYGANCkVzdGEgZnVuY2nDs24gbm9zIGVudHJlZ2EgdW4gdmFsb3IgZGUgJDAuODQkLCBlbCBjdWFsIHNlIGFjZXJjYSBhIDEuICBQcm9iZW1vcyBjb24gZWwgdGVzdCBkZSBjb3JyZWxhY2nDs24gZGUgUGVhcnNvbjoNCg0KYGBge3J9DQpjb3IudGVzdChkZiRwcmVjaW9tLGRmJGFyZWFjb25zdCkNCmBgYA0KDQpFc3RlIHJlc3VsdGFkbyB0YW1iacOpbiBzdWdpZXJlIHVuYSBjb3JyZWxhY2nDs24gbXV5IGZ1ZXJ0ZSBlbnRyZSBlbCBwcmVjaW8geSBlbCDDoXJlYSBjb25zdHJ1aWRhIGRlIGxvcyBhcGFydGFtZW50b3MuIExhIGhpcMOzdGVzaXMgYWx0ZXJuYXRpdmEgZXMgcXVlIGxhIGNvcnJlbGFjacOzbiB2ZXJkYWRlcmEgZW50cmUgbGFzIHZhcmlhYmxlcyBubyBlcyBpZ3VhbCBhIGNlcm8uIEVsIHJlc3VsdGFkbyBkZWwgdmFsb3IgX3BfIGVzIG11eSBiYWppdG8sIHB1ZXMgZXN0w6EgZW4gZWwgb3JkZW4gZGUgMTAgYSBsYSBtZW5vcyAxNiwgZXMgZGVjaXIsIHByw6FjdGljYW1lbnRlIGNlcm8sIGVzdG8gbm9zIHBlcm1pdGUgcmVzcGFsZGFyIGxhIGhpcMOzdGVzaXMgYWx0ZXJuYXRpdmEsIGNvbmZpcm1hbmRvIHF1ZSBsYSBjb3JyZWxhY2nDs24gZW50cmUgbGFzIHZhcmlhYmxlcyBlcyBtdXkgZnVlcnRlIChtdXkgY2VyY2FuYSBhIGNlcm8pLiBFbCBpbnRlcnZhbG8gZGUgY29uZmlhbnphIGVzIGRlbCAkOTVcJSQsIGVzIGRlY2lyLCBlbCB2YWxvciB2ZXJkYWRlcm8gZGUgbGEgY29ycmVsYWNpw7NuIHNlIGVuY3VlbnRyYSBlbiBlbCByYW5nbyAkMC44MyQgeSAkMC44NiQuIFRvZG8gbG8gYW50ZXJpb3Igbm9zIGNvbmZpcm1hIHF1ZSBhIG1lZGlkYSBxdWUgYXVtZW50YSBlbCDDoXJlYSBjb25zdHJ1aWRhIGRlIGxvcyBhcGFydGFtZW50b3MsIHRhbWJpw6luIGF1bWVudGEgZWwgcHJlY2lvIGRlIGVsbG9zLg0KDQpgYGB7ciBkaXNwZXJzaW9uX3ByZWNpb21fYXJlYWNvbnN0fQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcud2lkdGggPSA1LCBmaWcuaGVpZ2h0ID0gNSkNCnBsb3QoZGYkcHJlY2lvbSwgZGYkYXJlYWNvbnN0LA0KICAgICB4bGFiID0gZXhwcmVzc2lvbigiUHJlY2lvIGVuIG1pbGxvbmVzIGRlIHBlc29zICIpLA0KICAgICB5bGFiID0gIkFyZWEgY29uc3RydWlkYSBlbiBtZXRyb3MgY3VhZHJhZG9zIChtIl4iMiJ+IikiLA0KICAgICBtYWluID0gIkdyYWZpY28gZGUgRGlzcGVyc2lvbiIsDQogICAgIGNvbCA9ICJsaWdodGdyZWVuIiwgICAgICAgICAgDQogICAgIHBjaCA9IDIwLCAgICAgICANCiAgICAgY2V4ID0gMC44KQ0KDQpgYGANCg0KUG9yIMO6bHRpbW8sIHJlYWxpemFyw6kgdW4gZ3LDoWZpY28gY29tYmluYWRvIGNvbiBsYXMgY29ycmVsYWNpb25lcyBlbnRyZSBsYXMgZG9zIHZhcmlhYmxlcyBlbiBkb25kZSBzZSBwdWVkZSBjb3Jyb2JvcmFyIGxvIGVuY29udHJhZG8gYW50ZXJpb3JtZW50ZS4NCg0KYGBge3IgQ29ycmVsYXRpb25fbWF0cml4fQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcud2lkdGggPSA4LCBmaWcuaGVpZ2h0ID0gOCkNCg0KIyBDcmVhciBtYXRyaXogZGUgY29ycmVsYWNpb25lcyBjb24gZ2dwYWlycw0KZ2dwYWlycyhkZlssNDozXSwgDQogICAgICAgIG1hcHBpbmcgPSBhZXMoZmlsbCA9ICJyZWQiKSwNCiAgICAgICAgdGl0bGUgPSAiTWF0cml6IGRlIENvcnJlbGFjaW9uZXMgZW50cmUgcHJlY2lvIHkgw6FyZWEgY29uc3RydWlkYSIsIA0KICAgICAgICB1cHBlciA9IGxpc3QoZ2VvbSA9ICJwb2ludCIsIHNpemUgPSAyLCBjb2xvciA9ICJyZWQiKSwgDQogICAgICAgIGxvd2VyID0gbGlzdChjb3IgPSBUUlVFLCBwLmNleCA9IDAuNiwgc2lnLmxldmVsID0gMC4wNSksIA0KICAgICAgICBkaWFnID0gbGlzdChoaXN0b2dyYW0gPSAiZGVuc2l0eSIsIGJpbnMgPSAxNSkpDQoNCg0KDQpgYGANCg0KIyMgNC4zLiBNb2RlbG8gZGUgUmVncmVzacOzbiBMaW5lYWwNCg0KX0VzdGltZSBlbCBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwgc2ltcGxlIGVudHJlICRwcmVjaW8gPSBmKGFyZWEpKyBcZXBzaWxvbiQuIEludGVycHJldGUgbG9zIGNvZWZpY2llbnRlcyBkZWwgbW9kZWxvICRcYmV0YV8wJCwgJFxiZXRhXzEkIGVuIGNhc28gZGUgc2VyIGNvcnJlY3RvLl8NCg0KQ29tbyBleGlzdGUgdW5hIGNvcnJlbGFjacOzbiBwb3NpdGl2YSBlbnRyZSBsYXMgZG9zIHZhcmlhYmxlcywgZXMgcG9zaWJsZSBjb25zdHJ1aXIgdW4gbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsIHF1ZSBkZXNjcmliYSBsYSByZWxhY2nDs24gZXhpc3RlbnRlIGVudHJlIGRpY2hhcyB2YXJpYWJsZXMuIExhIHJlZ3Jlc2nDs24gbGluZWFsIHNlIGV4cHJlc2EgYSB0cmF2w6lzIGRlIHVuYSBlY3VhY2nDs24gZGUgdW5hIHJlY3RhIGNvbiB1biB2YWxvciBkZSBjb2VmaWNpZW50ZXMgcGFyYSBlbCBpbnRlcmNlcHRvIGVuIGVsIGVqZSB5ICRcYmV0YV8wJCB5IGxhIHBlbmRpZW50ZSBkZSBsYSByZWN0YSAkXGJldGFfMSQuDQoNCmBgYHtyIHJlZ19tb2RlbH0NCnJlZ19tb2RlbCA9IGxtKHByZWNpb20gfiBhcmVhY29uc3QsIGRhdGEgPSBkZikNCnN1bW1hcnkocmVnX21vZGVsKQ0KYGBgDQoNCkxhIHZhcmlhYmxlIGluZGVwZW5kaWVudGUgZXMgZWwgw6FyZWEgY29uc3RydWlkYSB5IGxhIGRlcGVuZGllbnRlIGVzIGVsIHByZWNpby4gRWwgbW9kZWxvIGVzdGltYSBsYSByZWxhY2nDs24gY29uIGxhIHNpZ3VpZW50ZSBlY3VhY2nDs246ICRwcmVjaW9tID0gXGJldGFfMCArIFxiZXRhXzEgKiBhcmVhY29uc3QgKyBcZXBzaWxvbiQuIA0KJFxiZXRhXzAkIGVzIGVsIGludGVyY2VwdG8gZW4gZWwgZWplICR5JCBxdWUgdGllbmUgdW4gdmFsb3IgZGUgJDIwMCQuICBFc3RvIGluZGljYXLDrWEgdW4gdmFsb3IgZGUgJDIwMCQgbWlsbG9uZXMgZGUgcGVzb3MgY3VhbmRvIGVsIMOhcmVhIGNvbnN0cnVpZGEgZXMgY2VybywgbG8gcXVlIHJlYWxtZW50ZSBubyBlcyBwb3NpYmxlLCBwZXJvIHNpcnZlIGNvbW8gdW5hIHJlZmVyZW5jaWEgbWF0ZW3DoXRpY2EgcGFyYSBsb3MgY8OhbGN1bG9zIGRlIMOhcmVhcyBwb3NpdGl2YXMuDQokXGJldGFfMSQgZXMgbGEgcGVuZGllbnRlIGRlIGxhIHJlY3RhIGN1eW8gdmFsb3IgZXMgJDAuNDk4JC4gRXN0byBpbmRpY2EgcXVlIHBhcmEgY2FkYSB1bmlkYWQgZW4gcXVlIGF1bWVudGEgZWwgw6FyZWEgY29uc3RydWlkYSwgZWwgcHJlY2lvIHJlc3VsdGFkbyBkZSBsYSBwcmVkaWNjacOzbiBhdW1lbnRhcsOtYSBlbiAkMC40OTgkIHVuaWRhZGVzLiBQb3IgZWplbXBsbywgc2kgbGEgcGVuZGllbnRlIGZ1ZXJhIHVubywgcG9yIGNhZGEgbWV0cm8gY3VhZHJhZG8gbWFzIGRlIMOhcmVhIGNvbnN0cnVpZGEsIGVsIHByZWNpbyBhdW1lbnRhcsOtYSB1biBtaWxsw7NuIGRlIHBlc29zLiAgDQpFbCB2YWxvciBkZSAkcCQgcGFyYSAkXGJldGFfMCQgeSAkXGJldGFfMSQgZXMgYWx0YW1lbnRlIHNpZ25pZmljYXRpdm8gKHZhbG9yIG1lbm9yIGRlbCBvcmRlbiBkZSAkMmUtMTYkKSwgZXMgZGVjaXIsIHF1ZSBzdSBjb3JyZWxhY2nDs24gbm8gc2UgZGViZSBhbCBhemFyLg0KU2Vnw7puIGVsIHJlc3VsdGFkbyBkZSBfTXVsdGlwbGUgUi1zcXVhcmVkXyBvIGVsIGluZGljYWRvciBkZSBib25kYWQgJFJeMiQgZGVsIG1vZGVsbyBleHBsaWNhIGVsICQ3MS42MyUkIGRlIGxhIHZhcmlhbnphIGRlbCBwcmVjaW8sIHBlcm8gYmllbiBwb2Ryw61hIGhhYmVyIG90cm9zIGZhY3RvcmVzIHF1ZSBpbmZsdXllbiBlbiBlbCBwcmVjaW8gcXVlIG5vIHNvbiBjYXB0dXJhZG9zIHBvciBlbCBtb2RlbG8uIEVzdG8gdGllbmUgc2VudGlkbywgcHVlcyBzZSBzYWJlIHF1ZSBpbm11ZWJsZXMgZGUgaWd1YWwgw6FyZWEgY29uc3RydWlkYSBlbiBzZWN0b3JlcyBkaWZlcmVudGVzIHRpZW5lbiB2YWxvcmVzIGRpZmVyZW50ZXMsIHRhbWJpw6luIHRpZW5lIGluZmx1ZW5jaWEgZWwgdGlwbyBkZSBhY2FiYWRvcywgZWwgbWF0ZXJpYWwgZGUgY29uc3RydWNjacOzbiwgZW50cmUgb3Ryb3MgZmFjdG9yZXMuIFBhcmEgdGVuZXIgZXNhcyB2YXJpYWJsZXMgZW4gY3VlbnRhDQoNCg0KIyMgNC40LiBJbnRlcnZhbG8gZGUgY29uZmlhbnphDQoNCl9Db25zdHJ1aXIgdW4gaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSAoOTUlKSBwYXJhIGVsIGNvZWZpY2llbnRlICRcYmV0YV8xJCwgaW50ZXJwcmV0YXIgeSBjb25jbHVpciBzaSBlbCBjb2VmaWNpZW50ZSBlcyBpZ3VhbCBhIGNlcm8gbyBuby4gQ29tcGFyZSBlc3RlIHJlc3VsdGFkbyBjb24gdW5hIHBydWViYSBkZSBoaXDDs3Rlc2lzIHRfDQoNClBhcmUgZXN0bywgdXNhcmVtb3MgbGEgZnVuY2nDs24gX2NvbmZpbnRfLg0KYGBge3IgY29uZmlkZW5jZV9pbnRlcnZhbH0NCmNvbmZpZGVuY2VfaW50ZXJ2YWwgPSBjb25maW50KHJlZ19tb2RlbCwgbGV2ZWwgPSAwLjk1KQ0KY29uZmlkZW5jZV9pbnRlcnZhbA0KYGBgDQoNClNlZ8O6biBlc3RlIHJlc3VsdGFkbywgc2UgcHVlZGUgZGVjaXIgcXVlIGNvbiBpbnRlcnZhbG8gZGUgY29uZmlhbnphIGRlbCAkOTVcJSQgZWwgaW50ZXJjZXB0byB0aWVuZSB1biB2YWxvciBlbnRyZSAkXCQxOTguNzQkIG1pbGxvbmVzIHkgJFwkMjAxLjM3JCBtaWxsb25lcyBjdWFuZG8gZWwgdmFsb3IgZGUgbGEgdmFyaWFibGUgaW5kZXBlbmRpZW50ZSBlcyBjZXJvLiAgQ29tbyB5YSBzZSBleHBsaWPDsywgZXN0byBubyBlcyByZWFsIGVuIGxhIHByw6FjdGljYSBwdWVzIHVuIGFwYXJ0YW1lbnRvIGNvbiDDoXJlYSBjb25zdHJ1aWRhIGRlIGNlcm8gc2ltcGxlbWVudGUgbm8gZXhpc3RpcsOtYS4NClRhbWJpw6luLCBjb24gdW5hIGNvbmZpYW56YSBkZWwgJDk1XCUkIHNlIHB1ZWRlIGRlY2lyIHF1ZSBlbCBlZmVjdG8gZGUgbGEgdW5pZGFkIGRlIGF1bWVudG8gZW4gZWwgw6FyZWEgY29uc3RydWlkYSBzZSBlbmN1ZW50cmEgZW50cmUgJDAuNDgkIHkgJDAuNTEkIHBhcmEgZWwgcHJlY2lvLg0KDQoNCiMjIDQuNS4gSW5kaWNhZG9yIGRlIEJvbmRhZA0KDQpfQ2FsY3VsZSBlIGludGVycHJldGUgZWwgaW5kaWNhZG9yIGRlIGJvbmRhZCAkUl4yJC5fDQoNCkVsIGluZGljYWRvciBvIGNvZWZpY2llbnRlIGRlIGJvbmRhZCAkUl4yJCBtaWRlIGxhIHByb3BvcmNpw7NuIGRlIGxhIHZhcmlhbnphIHRvdGFsIGRlIGxvcyBkYXRvcyBxdWUgZXMgZXhwbGljYWRhIHBvciBlbCBtb2RlbG8uIFVuIHZhbG9yIGRlICRSXjIkIGNlcmNhbm8gYSAxIGluZGljYSBxdWUgZWwgbW9kZWxvIGV4cGxpY2EgdW5hIGdyYW4gcGFydGUgZGUgbGEgdmFyaWFuemEgZGUgbG9zIGRhdG9zLCBtaWVudHJhcyBxdWUgdW4gdmFsb3IgY2VyY2FubyBhIDAgaW5kaWNhIHF1ZSBlbCBtb2RlbG8gZXhwbGljYSBwb2NhIHZhcmlhbnphLiAgUGFyYSBjYWxjdWxhcmxvIHVzYXJlbW9zDQoNCmBgYHtyIHJfc3F1YXJlZH0NCmNhdCgiRWwgaW5kaWNhZG9yIG8gY29lZmljaWVudGUgZGUgYm9uZGFkIGRlbCBtb2RlbG8gZGUgcmVncmVzaW9uIGxpbmVhbCBlcyBkZToiLCBzdW1tYXJ5KHJlZ19tb2RlbCkkci5zcXVhcmVkKQ0KYGBgDQoNCkVzdGUgcmVzdWx0YWRvIGRlICQwLjcxNjIkIGRlbCBpbmRpY2Fkb3IgJFJeMiQgaW5kaWNhIHF1ZSBlbCAkNzEuNjJcJSQgZGUgbGEgdmFyaWFuemEgZGVsIHByZWNpbyBkZSBsb3MgYXBhcnRhbWVudG9zIGVzIGV4cGxpY2FkYSBwb3IgZWwgbW9kZWxvLiBTaSBiaWVuIGVzIG3DoXMgY2VyY2FubyBhIDEgcXVlIGEgMCwgbm8gbWUgcGFyZWNlIHNpZ25pZmljYXRpdmFtZW50ZSBjZXJjYW5vIGEgMSwgbG8gcXVlIG1lIGhhY2UgcGVuc2FyIHF1ZSBoYXkgb3RyYXMgdmFyaWFibGVzIHF1ZSBpbmZsdXllbiBlbiBlbCBwcmVjaW8gYWRlbWFzIGRlbCDDoXJlYSBjb25zdHJ1aWRhLg0KDQojIyA0LjYuIEVzdGltYWNpw7NuIGRlIHByZWNpbw0KDQpfwr9DdcOhbCBzZXLDrWEgZWwgcHJlY2lvIHByb21lZGlvIGVzdGltYWRvIHBhcmEgdW4gYXBhcnRhbWVudG8gZGUgMTEwIG1ldHJvcyBjdWFkcmFkb3M/IENvbnNpZGVyYSBlbnRvbmNlcyBjb24gZXN0ZSByZXN1bHRhZG8gcXVlIHVuIGFwYXJ0YW1lbnRvIGVuIGxhIG1pc21hIHpvbmEgY29uIDExMCBtZXRyb3MgY3VhZHJhZG9zIGVuIHVuIHByZWNpbyBkZSAyMDAgbWlsbG9uZXMgc2Vyw61hIHVuYSBhdHJhY3RpdmEgZXN0YSBvZmVydGE/IMK/UXXDqSBjb25zaWRlcmFjaW9uZXMgYWRpY2lvbmFsZXMgc2UgZGViZW4gdGVuZXI/Ll8NCg0KUGFyYSBoYWNlciBlc3RhIGVzdGltYWNpw7NuLCBiYXN0YSBjb24gcmVlbXBsYXphciBsb3MgdmFsb3JlcyBlbmNvbnRyYWRvcyBlbiBsYSBlY3VhY2nDs246DQoNCjxjZW50ZXI+DQoNCiRZID0gXGJldGFfMCArIFxiZXRhXzEgKiBYJCwgZG9uZGUgDQoNCiRZJCBlcyBlbCBwcmVjaW8sDQoNCiRYJCBlcyBlbCDDoXJlYSBjb25zdHJ1aWRhLCBlcyBkZWNpciAkMTEwbV4yJA0KDQokXGJldGFfMCA9IDIwMC4wNiQgeSANCg0KJFxiZXRhXzEgPSAwLjQ5OCQgDQoNCkVudG9uY2VzIHRlbmVtb3M6DQoNCiRwcmVjaW8gPSAyMDAuMDYgKyAwLjQ5OCoxMTAkDQoNCiRwcmVjaW8gPSAyMDAuMDYgKyA1NC43OCQNCg0KJHByZWNpbyA9IDI1NC44NCQNCg0KPC9jZW50ZXI+DQoNCkxvIHF1ZSBpbmRpY2EgcXVlIGVsIG1vZGVsbyBhcnJvamEgdW4gcHJlY2lvIGRlICQyNTQuODQkIG1pbGxvbmVzIGRlIHBlc29zIHBhcmEgdW4gYXBhcnRhbWVudG8gZGUgMTEwICRNXjIkLCBsdWVnbyBsYSBvZmVydGEgZGUgJDIwMCQgbWlsbG9uZXMgcG9yIHBhcnRlIGRlIGxhIGlubW9iaWxpYXJpYSBwYXJhIHVuIGFwYXJ0YW1lbnRvIGVuIGVsIG1pc21vIHNlY3RvciBzZXLDrWEgX211eV8gYXRyYWN0aXZhIHNlZ8O6biBsbyBhcnJvamFkbyBwb3IgZWwgbW9kZWxvIHB1ZXMgZXN0YXLDrWEgbXV5IHBvciBkZWJham8gZGVsIHZhbG9yIGRlIGxvcyBhcGFydGFtZW50b3MgZW4gbGEgem9uYS4gU2Vnw7puIGxvIGFudGVyaW9yLCBsYSBpbm1vYmlsaWFyaWEgdGVuZHLDrWEgdW4gbWFyZ2VuIGRlICQ1NCQgbWlsbG9uZXMgZGUgcGVzb3MgcGFyYSBzdWJpciBlbCB2YWxvciBkZWwgYXBhcnRhbWVudG8sIGVzIGRlY2lyLCBhw7puIHBpZGllbmRvICAkMjI1JCBtaWxsb25lcyBvIGhhc3RhICQyNDAkIG1pbGxvbmVzIGRlIHBlc29zIHBvciBlbCBhcGFydGFtZW50byBlc3RhcsOtYSBlbiBidWVuYXMgY29uZGljaW9uZXMgcGFyYSBzZXIgdW5hIG9mZXJ0YSBhdHJhY3RpdmEgcGFyYSBlbCBjb21wcmFkb3IgcG9yIGVzdGFyIHBvciBkZWJham8gZGUgbG8gZXNwZXJhZG8gZW4gbGEgem9uYS4NCg0KDQojIyA0LjcuIFZhbGlkYWNpw7NuIGRlIGxvcyBzdXB1ZXN0b3Mgey50YWJzZXR9DQoNCl9SZWFsaWNlIGxhIHZhbGlkYWNpw7NuIGRlIGxvcyBzdXB1ZXN0b3MgZGVsIG1vZGVsbyBwb3IgbWVkaW8gZGUgZ3LDoWZpY29zIGFwcm9waWFkb3MsIGludGVycHJldGFybG9zIHkgc3VnZXJpciBwb3NpYmxlcyBzb2x1Y2lvbmVzIHNpIHNlIHZpb2xhbiBhbGd1bm9zIGRlIGVsbG9zLiBVdGlsaWNlIGxhcyBwcnVlYmFzIGRlIGhpcMOzdGVzaXMgcGFyYSBsYSB2YWxpZGFjacOzbiBkZSBzdXB1ZXN0b3MgeSBjb21wYXJlIGxvcyByZXN1bHRhZG9zIGNvbiBsbyBvYnNlcnZhZG8gZW4gbG9zIGdyw6FmaWNvcyBhc29jaWFkb3MuXw0KDQojIyMgNC43LjEuIFN1cHVlc3RvIGRlIF9Ob3JtYWxpZGFkXw0KDQpfU3VwdWVzdG8gZGUgTm9ybWFsaWRhZF86IExvcyBlcnJvcmVzIHNpZ3VlbiB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwgJChcZXBzaWxvbl9pIOKIvCBOKDAsXHNpZ21hXjIpKSQuDQoNClBhcmEgdmFsaWRhciBlc3RvcyBzdXB1ZXN0b3Mgc2UgdXRpbGl6YXLDoW4gbGFzIHBydWViYXMgX1NoYXBpcm8tV2lsa18geSBfQW5kZXJzb24tRGFybGluZ18uDQoNCkxhIHBydWViYSBkZSBfU2hhcGlyby1XaWxrXyBzZSB1c2EgcGFyYSBldmFsdWFyIHNpIGxvcyByZXNpZHVvcyBkZWwgbW9kZWxvIHNpZ3VlbiB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwuIExvcyByZXNpZHVvcyBzb24gbGEgZGlmZXJlbmNpYSBlbnRyZSBsb3MgdmFsb3JlcyBvYnNlcnZhZG9zIGRlIGxhIHZhcmlhYmxlIGRlcGVuZGllbnRlIChlbiBlc3RlIGNhc28gcHJlY2lvbSkgeSBsb3MgdmFsb3JlcyBwcmVkaWNob3MgcG9yIGVsIG1vZGVsby4NCg0KYGBge3Igc2hhcGlyb30NCnNoYXBpcm8udGVzdChyZWdfbW9kZWwkcmVzaWR1YWxzKQ0KYGBgDQoNCkVsIHJlc3VsdGFkbyBtdWVzdHJhIHVuIGVzdGFkw61zdGljbyBfVzogMC45OTg4NV8gcXVlIHNlIGFjZXJjYSBhICQxJCwgbG8gcXVlIGluZGljYSBxdWUgbGEgZGlzdHJpYnVjacOzbiBzZSBwdWVkZSB0b21hciBjb21vIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbC4gU2kgZnVlcmEgY2VyY2FubyBhICQwJCBzZXLDrWEgbG8gY29udHJhcmlvLg0KDQpFbCBfdmFsb3IgcF8gcmVwcmVzZW50YSBsYSBwcm9iYWJpbGlkYWQgZGUgb2J0ZW5lciB1biBlc3RhZMOtc3RpY28gX1dfIGlndWFsIGRlIGV4dHJlbW8gcXVlIGVsIG9ic2VydmFkbywgc3Vwb25pZW5kbyBxdWUgbGEgaGlww7N0ZXNpcyBudWxhLCBlcyBkZWNpciBsYSBub3JtYWxpZGFkLCBzZWEgY2llcnRhLiBHZW5lcmFsbWVudGUsIHVuIF92YWxvciBwXyBtZW5vciBxdWUgZWwgbml2ZWwgZGUgc2lnbmlmaWNhbmNpYSBkZSAkMC4wNSQgaW5kaWNhcsOtYSBxdWUgZGViZSByZWNoYXphcnNlIGxhIGhpcMOzdGVzaXMgbnVsYSwgZXMgZGVjaXIsIHF1ZSBsb3MgZGF0b3Mgbm8gc2lndWVuIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbC4gUGFyYSBlc3RlIGNhc28sIGVsIF92YWxvciBwXyBlcyBtYXlvciBxdWUgJDAuMDUkIGxvIHF1ZSBubyBwZXJtaXRlIHJlY2hhemFyIGxhIGhpcMOzdGVzaXMgbnVsYSBkZSBub3JtYWxpZGFkLg0KDQoNCmBgYHtyIG5vcnRlc3R9DQpub3J0ZXN0OjphZC50ZXN0KHJlZ19tb2RlbCRyZXNpZHVhbHMpDQpgYGANCg0KRWwgcmVzdWx0YWRvIG11ZXN0cmEgdW4gZXN0YWTDrXN0aWNvIF9BOiAwLjQyMzk4XyBxdWUgc2UgYWNlcmNhIGEgJDAkLCBsbyBxdWUgaW5kaWNhIHF1ZSBsYSBkaXN0cmlidWNpw7NuIHNlIHB1ZWRlIHRvbWFyIGNvbW8gdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsLiBTaSBmdWVyYSBjZXJjYW5vIGEgJDEkIHNlcsOtYSBsbyBjb250cmFyaW8uDQoNCkVsIF92YWxvciBwXyBlbiBlc3RlIGNhc28gZXMgJDAuMzE4JCB0YW1iacOpbiBlcyBtYXlvciBhICQwLjA1JCBsbyBxdWUgdGFtcG9jbyBwZXJtaXRlIHJlY2hhemFyIGEgaGlww7N0ZXNpcyBudWxhLg0KDQojIyMgNC43LjIuIFN1cHVlc3RvIGRlIF9Ib21vc2NlZGFzdGljaWRhZF8NCg0KX1N1cHVlc3RvIGRlIF9Ib21vc2NlZGFzdGljaWRhZF86IExhIHZhcmlhbnphIGFscmVkZWRvciBkZSBsYSBsaW5lYSBkZSByZWdyZXNpw7NuLCBwYXJhIGN1YWxxdWllciB2YWxvciBjb25zdGFudGUgJChWXyhbXGVwc2lsb25dKSA9IFxzaWdtYV4yKSQuDQoNClNlIHV0aWxpemFyw6EgbGEgcHJ1ZWJhIF9CcmV1c2NoLVBhZ2FuIGVzdGFuZGFyaXphZGFfIG8gX3BydWViYSBCUF8gc2UgdXRpbGl6YSBwYXJhIGV2YWx1YXIgbGEgaGV0ZXJvY2VkYXN0aWNpZGFkIGVuIGxvcyByZXNpZHVvcyBkZSB1biBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwuIExhIGhldGVyb2NlZGFzdGljaWRhZCBzZSByZWZpZXJlIGEgbGEgdmFyaWFuemEgbm8gY29uc3RhbnRlIGRlIGxvcyByZXNpZHVvcywgZXMgZGVjaXIsIHF1ZSBsYSBkaXNwZXJzacOzbiBkZSBsb3MgZXJyb3JlcyBubyBlcyB1bmlmb3JtZSBlbiB0b2RvcyBsb3Mgbml2ZWxlcyBkZSBsYSB2YXJpYWJsZSBpbmRlcGVuZGllbnRlLCBlbiBlc3RlIGNhc28gbGEgw6FyZWEgY29uc3RydWlkYS4NCg0KYGBge3IgaG9tb3NjZWRhc3RpY2lkYWR9DQpsbXRlc3Q6OmJwdGVzdChyZWdfbW9kZWwpDQpgYGANCg0KTGEgcHJ1ZWJhIGFycm9qYSBsb3Mgc2lndWllbnRlcyByZXN1bHRhZG9zOg0KX0VzdGFkaXN0aWNvIEJQXyAkPSAwLjgzMjg4JCBlbCBjdWFsIGVzIHVuIHZhbG9yIGFsZWphZG8gZGUgY2VybywgbG8gcXVlIGluZGljYSB1bmEgcG9zaWJsZSBoZXRlcm9jZWRhc3RpY2lkYWQuDQoNCkVsIF92YWxvciBwXywgYWwgaWd1YWwgcXVlIGVuIGxhcyBwcnVlYmFzIGFudGVyaW9yZXMsIHJlcHJlc2VudGEgbGEgcG9zaWJpbGlkYWQgZGUgb2J0ZW5lciB1biBlc3RhZGlzdGljbyBfQlBfIHRhbiBleHRyZW1vIG8gbWFzIGV4dHJlbW8gcXVlIGVsIG9ic2VydmFkby4gRXN0ZSB2YWxvciBlcyBtYXlvciBhICQwLjA1JCBsbyBxdWUgbm8gcGVybWl0ZSByZWNoYXphciBsYSBoaXDDs3Rlc2lzIG51bGEgZGUgaG9tb2NlZGFzdGljaWRhZC4NCg0KDQojIyMgNC43LjMuIFN1cHVlc3RvIGRlIF9ObyBBdXRvY29ycmVsYWNpw7NuXw0KDQpfU3VwdWVzdG8gZGUgTm8gQXV0b2NvcnJlbGFjacOzbl86IExvcyBlcnJvcmVzIHF1ZSBjb3JyZXNwb25kZW4gYSBkaWZlcmVudGVzIGluZGl2aWR1b3MgbyBkaWZlcmVudGVzIHRpZW1wbyBkZWJlbiBzZXIgaW5kZXBlbmRpZW50ZXMgdW5vcyBkZSBvdHJvcyAkKENvdltcZXBzaWxvbl9pLFxlcHNpbG9uX2pdID0gMCkkLg0KDQo8Y2VudGVyPg0KDQokSF8wOkVbXGVwc2lsb25faSxlcHNpbG9uX2pdID0gMCQNCg0KJEhfYTpFW2Vwc2lsb25faSxlcHNpbG9uX2pdIOKJoCAwJA0KDQo8L2NlbnRlcj4NCg0KU2UgdXRpbGl6YXLDoSBsYSBwcnVlYmEgZGUgX0R1cmJpbi1XYXRzb24gKERXKV8gcGFyYSBkZXRlY3RhciBsYSBwcmVzZW5jaWEgZGUgYXV0b2NvcnJlbGFjacOzbiBlbiBsb3MgcmVzaWR1b3MgZGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbC4NCg0KYGBge3IgZHVyYmluX3dhdHNvbn0NCmxtdGVzdDo6ZHd0ZXN0KHJlZ19tb2RlbCkNCmBgYA0KDQpFbCBfRXN0YWTDrXN0aWNvIERXXyB2YXJpYSBlbnRyZSAkMCQgeSAkNCQuIEVuIGVzdGUgY2FzbyBkaW8gY29tbyByZXN1bHRhZG8gJDIuMDIwNCQgbG8gY3VhbCBzdWdpZXJlLCBwb3Igc2VyIGNlcmNhbm8gYSAyLCBxdWUgbG9zIHJlc2lkdW9zIHRpZW5kZW4gYSBlc3RhciBjb3JyZWxhY2lvbmFkb3MgbmVnYXRpdmFtZW50ZSBlbnRyZSBzaSwgZXMgZGVjaXIsIHF1ZSBubyBoYXkgYXV0b2NvcnJlbGFjacOzbiBlbnRyZSBlbGxvcy4gKExvcyB2YWxvcmVzIG1lbm9yZXMgcXVlICQyJCBpbmRpY2FuIGF1dG9jb3JyZWxhY2nDs24gcG9zaXRpdmEsIHkgdmFsb3JlcyBzdXBlcmlvcmVzIGEgMiwgYXV0b2NvcnJlbGFjacOzbiBuZWdhdGl2YSwgbG8gY3VhbCBlcyBtZW5vcyBjb23Dum4pDQoNClNlIG9idGllbmUgdW4gX3ZhbG9yIHBfIGRlICQwLjY0MzUkIHF1ZSBlcyBtYXlvciBhbCBuaXZlbCBkZSBzaWduaWZpY2FuY2lhICQwLjA1JCBubyBoYXkgZXZpZGVuY2lhIHN1ZmljaWVudGUgcGFyYSByZWNoYXphciBsYSBoaXDDs3Rlc2lzIG51bGEgZGUgX05vIEF1dG9jb3JyZWxhY2nDs25fLg0KDQojIyMgNC43LjQuIF9PdXRsaWVyc18NCg0KQXVucXVlIGVzdGUgbm8gZXMgdW4gc3VwdWVzdG8gZm9ybWFsLCBzZSBlc3BlcmEgcXVlIGxvcyBkYXRvcyBubyBjb250ZW5nYW4gZGF0b3MgYXTDrXBpY29zIHF1ZSBnZW5lcmVuIHNlc2dvcyBlbiBsb3MgZXN0aW1hZG9yZXMgZGUgbG9zIGNvZWZpY2llbnRlcy4gIA0KDQpUYWwgY29tbyBzZSB2aW8gZW4gbG9zIGdyw6FmaWNvcyBkZWwgY29uanVudG8gZGUgZGF0b3MsIGxhcyB2YXJpYWJsZXMgX3ByZWNpb21fIHkgX2FyZWFjb25zdF8gc2kgdGllbmVuIGRhdG9zIGF0w61waWNvcyByZXByZXNlbnRhZG9zIHBvciBsb3MgdHJpw6FuZ3Vsb3MgZW4gbG9zIGdyw6FmaWNvcyBjb3JyZXNwb25kaWVudGVzLiBWZWFtb3MgZWwgZ3LDoWZpY28gZGUgY2FqYXMgeSBiaWdvdGVzIHBhcmEgbG9zIHJlc2lkdW9zIGRlbCBtb2RlbG8uDQoNCmBgYHtyIGJveHBsb3RfcmVzaWR1YWxzfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcud2lkdGggPSA0LCBmaWcuaGVpZ2h0ID0gNCkNCmJveHBsb3QocmVnX21vZGVsJHJlc2lkdWFscywgIA0KICAgICAgICBtYWluID0gIk91dGxpZXJzIC0gUmVzaWR1b3MgZGVsIE1vZGVsbyIsIA0KICAgICAgICB5bGFiID0gIlJlc2lkdW9zIiwNCiAgICAgICAgY29sID0gImxpZ2h0Z3JlZW4iLA0KICAgICAgICBib3JkZXIgPSAiZGFya2dyZWVuIg0KKQ0KYGBgDQoNCiMjIyA0LjcuNS4gR3LDoWZpY29zIGFzb2NpYWRvcyBhIGxhcyBwcnVlYmFzDQoNCmBgYHtyIGdyYXBoaWNzfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gNikNCnBhcihtZnJvdyA9IGMoMiwyKSkNCnBsb3QocmVnX21vZGVsLCANCiAgICAgY29sID0gImxpZ2h0Z3JlZW4iLCANCiAgICAgcGNoID0gMjAsIA0KICAgICBsd2QgPSAxLCANCiAgICAgY2V4ID0gMSkNCiMgTMOtbmVhIGRlIGlkZW50aWRhZA0KYWJsaW5lKGEgPSAwLCANCiAgICAgICBiID0gMSwgDQogICAgICAgY29sID0gImdyZWVuIiwgDQogICAgICAgbHR5ID0gMSkNCmBgYA0KDQpMb3MgZ3LDoWZpY29zIGRlIGRpc3BlcnNpw7NuIG5vcyBtdWVzdHJhbiBjb3JyZWxhY2nDs24gZW50cmUgbGFzIGRvcyB2YXJpYWJsZXMgdXNhbmRvIGxvcyByZXNpZHVvcyB5IGxvcyByZXNpZHVvcyBlc3RhbmRhcml6YWRvcywgc29wb3J0YW5kbyBsb3MgYW7DoWxpc2lzIHByZXZpYW1lbnRlIGRlc2NyaXRvcy4NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgNS4gVHJhbnNmb3JtYWNpb25lcyBkZWwgbW9kZWxvDQoNCkEgY29udGludWFjacOzbiBzZSByZWFsaXphbiBsb3MgcHVudG9zIDggYWwgMTAgZW4gZG9uZGUgc2UgcmVhbGl6YXLDoW4gdHJhbnNmb3JtYWNpb25lcyBwYXJhIHZlciBzaSBzZSBtZWpvcmFyIGVsIGFqdXN0ZSB5IGxvcyBzdXB1ZXN0b3MgZGVsIG1vZGVsbywgc2UgY29tcGFyYXLDoW4gbG9zIHJlc3VsdGFkb3MgZGUgZXN0YXMgdHJhbnNmb3JtYWNpb25lcyBjb24gZWwgbW9kZWxvIGluaWNpYWwuDQoNCkF1bnF1ZSBlbCBtb2RlbG8gaW5pY2lhbCBjdW1wbGUgbG9zIHN1cHVlc3RvcyB5IHNlIGRlbW9zdHLDsyBxdWUgZXhpc3RlIHVuYSBjb3JyZWxhY2nDs24gZW50cmUgbGFzIHZhcmlhYmxlcyBlc3R1ZGlhZGFzLCBsdWVnbyBubyBzZXLDrWEgZXN0cmljdGFtZW50ZSBuZWNlc2FyaW8gaGFjZXIgdHJhbnNmb3JtYWNpb25lcyBwYXJhIG1lam9yYXIgZWwgYWp1c3RlIHkgbG9zIHN1cHVlc3RvcyBkZWwgbW9kZWxvLCBzZSByZWFsaXphcsOhbiBhbGd1bmFzIHRyYW5zZm9ybWFjaW9uZXMgcGFyYSBzZXIgY29tcGFyYWRhcyBjb24gZWwgbW9kZWxvIGluaWNpYWwuDQoNClB1bnRvIDg6IF9EZSBzZXIgbmVjZXNhcmlvIHJlYWxpY2UgdW5hIHRyYW5zZm9ybWFjacOzbiBhcHJvcGlhZGEgcGFyYSBtZWpvcmFyIGVsIGFqdXN0ZSB5IHN1cHVlc3RvcyBkZWwgbW9kZWxvLl8NCg0KUHVudG8gOTogX0RlIHNlciBuZWNlc2FyaW8gY29tcGFyZSBlbCBhanVzdGUgeSBzdXB1ZXN0b3MgZGVsIG1vZGVsbyBpbmljaWFsIHkgZWwgdHJhbnNmb3JtYWRvLl8NCg0KUHVudG8gMTA6IF9Fc3RpbWUgdmFyaW9zIG1vZGVsb3MgeSBjb21wYXJlIGxvcyByZXN1bHRhZG9zIG9idGVuaWRvcy4gRW4gZWwgbWVqb3IgZGUgbG9zIG1vZGVsb3MsIMK/c2UgY3VtcGxlbiBsb3Mgc3VwdWVzdG9zIHNvYnJlIGxvcyBlcnJvcmVzP18NCg0KYGBge3IgbW9kZWx9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSA2KQ0KbW9kZWwxID0gbG0oZGYkcHJlY2lvbSB+IGRmJGFyZWFjb25zdCwgZGF0YSA9IGRhdGEuZnJhbWUoZGYpKSAjIExpbiAtIExpbg0Kc3VtbWFyeShtb2RlbDEpDQpzaGFwaXJvLnRlc3QobW9kZWwxJHJlc2lkdWFscykNCm5vcnRlc3Q6OmFkLnRlc3QobW9kZWwxJHJlc2lkdWFscykNCmxtdGVzdDo6Ymd0ZXN0KG1vZGVsMSkNCmxtdGVzdDo6ZHd0ZXN0KG1vZGVsMSkNCnBhcihtZnJvdyA9IGMoMiwyKSkNCnBsb3QobW9kZWwxLCANCiAgICAgY29sID0gImxpZ2h0Z3JlZW4iLCANCiAgICAgcGNoID0gMjAsIA0KICAgICBsd2QgPSAxLCANCiAgICAgY2V4ID0gMSkNCmBgYA0KDQojIyA1LjEuICBUcmFuc2Zvcm1hY2nDs24gQm94LUNveA0KDQpMYSB0cmFuc2Zvcm1hY2nDs24gQm94LUNveCBzZSB1dGlsaXphIHBhcmEgY29ycmVnaXIgbGEgbm8gbGluZWFsaWRhZCBlbiBsYSByZWxhY2nDs24gZW50cmUgdmFyaWFibGVzIChsbyBxdWUgbm8gc2VyaWEgbmVjZXNhcmlvIGVuIGVzdGUgY2FzbyksIGVzdGFiaWxpemFyIGxhIHZhcmlhbnphLCBub3JtYWxpemFyIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIHJlc2lkdW9zIHkgbWVqb3JhciBsYSBpbnRlcnByZXRhYmlsaWRhZCBkZSBsb3MgcmVzdWx0YWRvcy4NCg0KYGBge3IgYm94X2NveH0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDYpDQpiYyA8LSBib3hjb3goZGYkcHJlY2lvbSB+IGRmJGFyZWFjb25zdCwgbGFtYmRhID0gLTE6MSkNCmBgYA0KDQpgYGB7cn0NCmxhbWJkYSA9IGJjJHhbd2hpY2gubWF4KGJjJHkpXQ0KY2F0KCJFbCB2YWxvciBMYW1iZGEgKM67KSBlczogIiwgbGFtYmRhKQ0KYGBgDQoNCkVsIHZhbG9yIGRlICRcbGFtYmRhJCBlcyAkMSQsIGxvIHF1ZSBpbmRpY2EgcXVlIGVsIG1vZGVsbyBubyBuZWNlc2l0YSB0cmFuc2Zvcm1hY2nDs24uDQoNCg0KIyMgNS4yLiBUcmFuc2Zvcm1hY2lvbmVzIGRlbCBNb2RlbG8gT3JpZ2luYWwgey50YWJzZXR9DQoNCiMjIyA1LjIuMS4gTW9kZWxvIDI6IF9bTGluLUxvZ11fDQoNCmBgYHtyIG1vZGVsMn0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDYpDQptb2RlbDIgPSBsbShwcmVjaW9tIH4gbG9nKGFyZWFjb25zdCksIGRhdGEgPSBkZikgICAgICAjIExpbiAtIExvZw0Kc3VtbWFyeShtb2RlbDIpDQpzaGFwaXJvLnRlc3QobW9kZWwyJHJlc2lkdWFscykNCm5vcnRlc3Q6OmFkLnRlc3QobW9kZWwyJHJlc2lkdWFscykNCmxtdGVzdDo6Ymd0ZXN0KG1vZGVsMikNCmxtdGVzdDo6ZHd0ZXN0KG1vZGVsMikNCnBhcihtZnJvdyA9IGMoMiwyKSkNCnBsb3QobW9kZWwyLCANCiAgICAgY29sID0gImxpZ2h0Z3JlZW4iLCANCiAgICAgcGNoID0gMjAsIA0KICAgICBsd2QgPSAxLCANCiAgICAgY2V4ID0gMSkNCmBgYA0KDQojIyMgNS4yLjIuIE1vZGVsbyAzOiBfW0xvZy1MaW5dXw0KDQpgYGB7ciBtb2RlbDN9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSA2KQ0KbW9kZWwzID0gbG0obG9nKHByZWNpb20pIH4gYXJlYWNvbnN0LCBkYXRhID0gZGYpICAgICAgIyBMb2cgLSBMaW4NCnN1bW1hcnkobW9kZWwzKQ0Kc2hhcGlyby50ZXN0KG1vZGVsMyRyZXNpZHVhbHMpDQpub3J0ZXN0OjphZC50ZXN0KG1vZGVsMyRyZXNpZHVhbHMpDQpsbXRlc3Q6OmJndGVzdChtb2RlbDMpDQpsbXRlc3Q6OmR3dGVzdChtb2RlbDMpDQpwYXIobWZyb3cgPSBjKDIsMikpDQpwbG90KG1vZGVsMywgDQogICAgIGNvbCA9ICJsaWdodGdyZWVuIiwgDQogICAgIHBjaCA9IDIwLCANCiAgICAgbHdkID0gMSwgDQogICAgIGNleCA9IDEpDQpgYGANCg0KDQojIyMgNS4yLjMuIE1vZGVsbyA0OiBfW0xvZy1Mb2ddXw0KDQpgYGB7ciBtb2RlbDR9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSA2KQ0KbW9kZWw0ID0gbG0obG9nKHByZWNpb20pIH4gbG9nKGFyZWFjb25zdCksIGRhdGEgPSBkZikgICAgICAjIExvZy0gTG9nDQpzdW1tYXJ5KG1vZGVsNCkNCnNoYXBpcm8udGVzdChtb2RlbDQkcmVzaWR1YWxzKQ0Kbm9ydGVzdDo6YWQudGVzdChtb2RlbDQkcmVzaWR1YWxzKQ0KbG10ZXN0OjpiZ3Rlc3QobW9kZWw0KQ0KbG10ZXN0Ojpkd3Rlc3QobW9kZWw0KQ0KcGFyKG1mcm93ID0gYygyLDIpKQ0KcGxvdChtb2RlbDQsIA0KICAgICBjb2wgPSAibGlnaHRncmVlbiIsIA0KICAgICBwY2ggPSAyMCwgDQogICAgIGx3ZCA9IDEsIA0KICAgICBjZXggPSAxKQ0KYGBgDQoNCg0KIyMjIDUuMi40LiBNb2RlbG8gNTogX1tMaW4tJFxzcXJ0e2FyZWFjb25zdH0kXV8NCg0KYGBge3IgbW9kZWw1fQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gNikNCm1vZGVsNSA9IGxtKHByZWNpb20gfiBzcXJ0KGFyZWFjb25zdCksIGRhdGEgPSBkZikgICAgICAjIExpbiAtIFNxcnQoeCkNCnN1bW1hcnkobW9kZWw1KQ0Kc2hhcGlyby50ZXN0KG1vZGVsNSRyZXNpZHVhbHMpDQpub3J0ZXN0OjphZC50ZXN0KG1vZGVsNSRyZXNpZHVhbHMpDQpsbXRlc3Q6OmJndGVzdChtb2RlbDUpDQpsbXRlc3Q6OmR3dGVzdChtb2RlbDUpDQpwYXIobWZyb3cgPSBjKDIsMikpDQpwbG90KG1vZGVsNSwgDQogICAgIGNvbCA9ICJsaWdodGdyZWVuIiwgDQogICAgIHBjaCA9IDIwLCANCiAgICAgbHdkID0gMSwgDQogICAgIGNleCA9IDEpDQpgYGANCg0KIyMgNS4zLiBDb21wYXJhY2nDs24gZGUgbG9zIE1vZGVsb3MNCg0KUGFyYSBhbmFsaXphciBsb3MgbW9kZWxvcyBzZSBwdWVkZSB1dGlsaXphciBlbCB2YWxvciBkZSAkUl4yJCBidXNjYW5kbyBlbCB2YWxvciBtw6FzIGFsdG8sIHlhIHF1ZSBlc3RlIGluZGljYSBsYSBwcm9wb3JjacOzbiBkZSB2YXJpYW56YSBkZSBsYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSBxdWUgZXMgZXhwbGljYWRhIHBvciBlbCBtb2RlbG8uIFRhbWJpw6luIHNlIHB1ZWRlIG1pcmFyIGVsIEVycm9yIFJlc2lkdWFsIGVzdMOhbmRhciAoUmVzaWR1YWwgU3RkLiBFcnJvcikgbcOhcyBiYWpvLCBwdWVzIGVzdGUgdmFsb3IgcmVwcmVzZW50YSBsYSB2YXJpYWJpbGlkYWQgcHJvbWVkaW8gZGUgbG9zIGVycm9yZXMgZGUgcHJlZGljY2nDs24gZGVsIG1vZGVsby4NCg0KYGBge3IgbW9kZWxfY29tcGFyaXNvbn0NCnN0YXJnYXplcihtb2RlbDEsIG1vZGVsMiwgbW9kZWwzLCBtb2RlbDQsIG1vZGVsNSwgdHlwZSA9ICJ0ZXh0IiwgZGYgPSBGQUxTRSkNCmBgYA0KDQpQYXJhIGxvcyBtb2RlbG9zIGNvbXBhcmFkb3MgZW4gbGEgdGFibGEsIHBvZGVtb3MgdmVyIHF1ZSBlbCBtb2RlbG8gMSwgZXMgZGVjaXIsIGVsIF9MaW4tTGluXyB0aWVuZSAkUl4yJCBlcyBlbCBtw6FzIGFsdG8gKCQwLjcxNiQpLCBsbyBxdWUgbm9zIGRpY2UgcXVlIGVzIGVsIHF1ZSBtZWpvciBleHBsaWNhIGxhIHZhcmlhYmlsaWRhZCBkZSBsYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSBfcHJlY2lvbV8uIEVsIHNpZ3VpZW50ZSAkUl4yJCBlcyBlbCBkZWwgbW9kZWxvIDUgX0xpbi0kc3FydChhcmVhY29uc3QpJF8gY29uIHVuIHZhbG9yIGRlICQwLjcwNiQNCg0KRW4gY3VhbnRvIGEgbG9zIGVycm9yZXMgZXN0w6FuZGFyIHJlc2lkdWFsZXMsIGxvcyBtb2RlbG9zIDMgeSA0IHNvbiBsb3MgcXVlIHRpZW5lIGVzdGUgdmFsb3IgbcOhcyBiYWpvLCBjb24gJDAuMDMwJCB5ICQwLjAzMSQgcmVzcGVjdGl2YW1lbnRlLiBFc3RvIGluZGljYSBxdWUgcGFyYSBlbGxvcyBoYXkgdW4gbWVqb3IgYWp1c3RlIGRlIGxvcyBkYXRvcy4NCg0KU2kgYmllbiBuaW5nw7puIG1vZGVsbyBtZWpvciBlbCAkUl4yJCwgbG9zIG1vZGVsb3MgMyB5IDQgc2kgcGFyZWNlbiB0ZW5lciB1bmEgbWVqb3JhIGVuIGN1YW5kbyBhbCBhanVzdGUgZGUgbG9zIGRhdG9zLiANCg0KQWhvcmEgYmllbiwgc2kgaGFjZW1vcyBsYSBlc3RpbWFjacOzbiBwYXJhIGVsIGFwYXJ0YW1lbnRvIGNvbiAxMTAkbV4yJCwgcG9kcmVtb3Mgc2FiZXIgY3XDoWwgZXMgZWwgbW9kZWxvIHF1ZSBvZnJlY2UgdW4gbWVqb3IgcmVzdWx0YWRvLiBSZWNvcmRlbW9zIHF1ZSBwYXJhIGVsIG1vZGVsbyBpbmljaWFsIGVsIHJlc3VsdGFkbyBmdWUgZGUgJDI1NC44NCQNCg0KVmVhbW9zIGVsIHJlc3VsdGFkbyBwYXJhIGVsIG1vZGVsbyA1IF9bTGluLSRcc3FydHthcmVhY29uc3R9JF1fIHF1ZSB0aWVuZSB1biBpbnRlcmNlcHRvIGRlICQxNTYuMzgkIHkgdW5hIHBlbmRpZW50ZSBkZSAkOS40NDUkLg0KDQo8Y2VudGVyPg0KDQokcHJlY2lvID0gMTU2LjM4ICsgOS40NSAqIFxzcXJ0KDExMCkkDQoNCiRwcmVjaW8gPSAxNTYuMzggKyA5LjQ1ICogMTAuNDkkDQoNCiRwcmVjaW8gPSAxNTYuMzggKyA5OS4wNiQNCg0KJHByZWNpbyA9IDI1NS40NCQgKGVuIG1pbGxvbmVzIGRlIHBlc29zKSANCg0KPC9jZW50ZXI+DQoNClBhcmEgZWwgbW9kZWxvIDMgX1tMb2ctTGluXV8gcXVlIHRpZW5lIHVuIGludGVyY2VwdG8gZGUgJDUuMzE4JCB5IHVuYSBwZW5kaWVudGUgZGUgJDAuMDAyJC4NCg0KPGNlbnRlcj4NCg0KJFxsb2cocHJlY2lvKSA9IDUuMzE4ICsgMC4wMDIgKiAxMTAkDQoNCiRcbG9nKHByZWNpbykgPSA1LjMxOCArIDAuMjIkDQoNCiRcbG9nKHByZWNpbykgPSA1LjUzOCQNCg0KJHByZWNpbyA9IGVeezUuNTM4fSQNCg0KJHByZWNpbyA9IDI1NCwzNiQgKGVuIG1pbGxvbmVzIGRlIHBlc29zKQ0KDQo8L2NlbnRlcj4NCg0KVG9kb3MgbG9zIHZhbG9yZXMgb2J0ZW5pZG9zIHNvbiBtdXkgcGFyZWNpZG9zIGVudHJlIHNpIHkgbm8gbWFyY2FuIHVuYSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmFtZW50ZSBwb3NpdGl2YSBjb24gZWwgcmVzdWx0YWRvIGRlbCBtb2RlbG8gaW5pY2lhbC4gDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDYuICBDb25jbHVzaW9uZXMgeSBSZWNvbWVuZGFjaW9uZXMgRmluYWxlcw0KDQotIF8qU29icmUgZWwgY29uanVudG8gZGUgZGF0b3M6Kl8gTm9zIGVuY29udHJhbW9zIGNvbiB1biBjb25qdW50byBkZSBkYXRvcyBsaW1waW8sIHF1ZSBjb250ZW7DrWEgcmVnaXN0cm9zIHNvYnJlIGNhc2FzIHkgYXBhcnRhbWVudG9zIGRlbCBlc3RyYXRvIDQgZW4gbGEgY2l1ZGFkIGRlIENhbGkuIExhIG1heW9yw61hIGRlIHJlZ2lzdHJvcyBlcmFuIHNvYnJlIGxvcyBhcGFydGFtZW50b3MgZW4gdW5hIHJlbGFjacOzbiBjYXNpIDQgYSAxLiAgU2UgZWxpbWluYXJvbiBsb3MgcmVnaXN0cm9zIGRlIGxhcyBjYXNhcyBwYXJhIGxhIHJlYWxpemFjacOzbiBkZWwgZWplcmNpY2lvIHkgZWwgYW7DoWxpc2lzIGVzdHV2byBjb25jZW50cmFkbyBlc3BlY8OtZmljYW1lbnRlIGVuIGxhcyB2YXJpYWJsZXMgZGUgX3ByZWNpb21fIChQcmVjaW8gZGUgbGEgdml2aWVuZGEgZW4gbWlsbG9uZXMgZGUgcGVzb3MpLCBjb21vIHZhcmlhYmxlIGRlcGVuZGllbnRlLCB5IF9hcmVhY29uc3RfICjDgXJlYSBjb25zdHJ1aWRhKSBjb21vIHZhcmlhYmxlIGluZGVwZW5kaWVudGUuDQoNCi0gXypTb2JyZSBsYXMgdmFyaWFibGVzIGRlIGVzdHVkaW86Kl8gRWwgdGFtYcOxbyBwcm9tZWRpbyBkZSBsb3MgYXBhcnRhbWVudG9zIGVzIGRlICQ3NS40OG1eMiQgeSBlbCB2YWxvciBwcm9tZWRpbyBlcyAkXCQyMzcuNjgkIG1pbGxvbmVzIGRlIHBlc29zIGNvbG9tYmlhbm9zLiBFc3RhIHJlbGFjacOzbiBhcnJvamEgdW4gcHJvbWVkaW8gZGUgdmFsb3IgcG9yICRtXjIkIGRlIHVuIHBvY28gbcOhcyBkZSAkXCQzJCBtaWxsb25lcyBkZSBwZXNvcy4NCg0KLSBfKlNvYnJlIGxhIGNvcnJlbGFjacOzbiBkZSBsYXMgdmFyaWFibGVzOipfIERlIGFjdWVyZG8gYWwgcmVzdWx0YWRvIGRlbCBhbsOhbGlzaXMgZGUgY29ycmVsYWNpw7NuIHJlYWxpemFkbyBwb3IgbWVkaW8gZGUgdW5hIHJlZ3Jlc2nDs24gbGluZWFsIGNvbiBsYSBlY3VhY2nDs24gJHkgPSBcYmV0YV8wICsgXGJldGFfMSh4KSQsIGRvbmRlICRcYmV0YV8wJCBlcyBlbCBpbnRlcmNlcHRvIGRlIGxvcyBlamVzLCB5ICRcYmV0YV8xJCBlcyBsYSBwZW5kaWVudGUgZGUgbGEgcmVjdGEsIGVzIGRlY2lyLCBlbCBncmFkbyBkZSBhZmVjdGFjacOzbiBkZSB1bmEgdW5pZGFkIGRlIGxhIHZhcmlhYmxlIGluZGVwZW5kaWVudGUgZW4gbGEgdmFyaWFibGUgZGVwZW5kaWVudGUuICBTZSBlc3RhYmxlY2nDsywgZ3JhY2lhcyBhbCBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwgeSBkZWwgYW7DoWxpc2lzIHJlYWxpemFkbywgcXVlICpzaSogZXhpc3RlIGNvcnJlbGFjacOzbiBlbnRyZSBsYXMgdmFyaWFibGVzIGVzdHVkaWFkYXMuIEVuIGxhIHByw6FjdGljYSwgc2UgcHVlZGUgZGVjaXIgcXVlIGN1YW5kbyBhdW1lbnRhIGVsIMOhcmVhIGNvbnN0cnVpZGEsIHRhbWJpw6luIGF1bWVudGEgZWwgcHJlY2lvIGRlbCBpbm11ZWJsZS4NCg0KLSBfKlNvYnJlIGVsIG1vZGVsbyBvcmlnaW5hbDoqXyBFbCBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwgYXBsaWNhZG8gYSBsb3MgZGF0b3MgZGVsIGNvbmp1bnRvIGZ1ZSByZXZpc2FkbyBmcmVudGUgYSBsb3Mgc3VwdWVzdG9zIHF1ZSBzZSBkZWJlbiBjdW1wbGlyLCB5IHRvZG9zIGZ1ZXJvbiBjb21wcm9iYWRvcyB5IHZlcmlmaWNhZG9zLg0KDQotIF8qU29icmUgbG9zIG1vZGVsb3MgdHJhbnNmb3JtYWRvczoqXyBDb24gZWwgb2JqZXRpdm8gZGUgYnVzY2FyIHNpIGhhYsOtYSBvdHJvcyBtb2RlbG9zIHF1ZSBtZWpvcmFyYW4gZWwgcmVuZGltaWVudG8gZGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbCBzZSBoaWNpZXJvbiB2YXJpYXMgdHJhbnNmb3JtYWNpb25lcy4gTGEgY29tcGFyYWNpw7NuIGVudHJlIGxvcyA1IG1vZGVsb3MsIGVsIGluaWNpYWwgeSBsYXMgNCB0cmFuc2Zvcm1hY2lvbmVzLCBhcnJvasOzIHF1ZSBuaW5ndW5vIGRlIGxvcyBtb2RlbG9zIHByb2R1Y3RvIGRlIGxhcyB0cmFuc2Zvcm1hY2lvbmVzIHN1cGVyYSBhbCBtb2RlbG8gaW5pY2lhbCwgc2kgdGVuZW1vcyBlbiBjdWVudGEscG9yIHVuIGxhZG8sIGVsIHZhbG9yIGRlICRSXjIkIHBhcmEgbG9zIG1vZGVsb3MsIHB1ZXMgdG9kb3MgbG9zIGRlIGxhcyB0cmFuc2Zvcm1hY2lvbmVzIHNvbiBtZW5vcmVzIGFsIGRlbCBtb2RlbG8gb3JpZ2luYWwsIHkgcG9yIG90cm8gbGFkbywgc2kgbWlyYW1vcyBlbCBfRXJyb3IgUmVzaWR1YWwgRXN0YW5kYXJfLCBlbCBkZWwgbW9kZWxvIG9yaWdpbmFsIGVzIGVsIG3DoXMgYmFqbyBkZSB0b2Rvcy4gUG9yIGxvIGFudGVyaW9yIHNlIHB1ZWRlIGRlZHVjaXIgcXVlLCBkYWRvcyBsb3MgZGF0b3MgZXhpc3RlbnRlcywgZWwgbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsIG9yaWdpbmFsIGVzIGVsIG1lam9yIGRlIHRvZG9zIGxvcyBtb2RlbG9zIGVzdHVkaWFkb3MuDQoNCi0gXypTb2JyZSBsYSBnZW5lcmFsaXphY2nDs24gbyBleHRyYXBvbGFjacOzbiBkZWwgbW9kZWxvOipfIEVsIG1vZGVsbyBmdWUgYXBsaWNhZG8gYSBsb3MgZGF0b3MgZGUgbG9zIGFwYXJ0YW1lbnRvcyBlbiBsYSBjaXVkYWQgZGUgQ2FsaSwgeSB0YWwgY29tbyBzZSBkaWpvIGVuIGxvcyBwdW50b3MgYW50ZXJpb3Jlcywgbm8gZnVlIHRlbmlkYSBlbiBjdWVudGEgbGEgdmFyaWFibGUgZGUgem9uYSwgcXVlIGVzIHVuYSB2YXJpYWJsZSBxdWUgcHVlZGUgaW5mbHVpciBlbiBlbCB2YWxvciBkZSBsb3MgYXBhcnRhbWVudG9zLiBfTm90YTpfIExhcyB2YXJpYWJsZXMgdGlwbyB5IGVzdHJhdG8gc2lydmllcm9uIGNvbW8gZmlsdHJvIGRlbCBjb25qdW50byBkZSBkYXRvcywgZXN0dWRpYW5kbyBzb2xvIGxvcyBhcGFydGFtZW50b3MgZGVsIGVzdHJhdG8gNC4NCg0KLSBfKlNvYnJlIHRyYWJham9zIGZ1dHVyb3M6Kl8gRXhpc3RlIGxhIHBvc2liaWxpZGFkIGRlIGFwbGljYXIgdW4gbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsIGEgdW4gc3ViY29uanVudG8gZGUgZGF0b3MsIGxvIHF1ZSBvZnJlY2Vyw61hIG1lam9yZXMgcHJlZGljY2lvbmVzIHBhcmEgZXNlIHN1YmNvbmp1bnRvIGRlIGRhdG9zLCBwb3IgZWplbXBsbywgdGVuaWVuZG8gZW4gY3VlbnRhIGxhIHpvbmEgeSBlbCBlc3RyYXRvIGRlbnRybyBkZSBsYSBtaXNtYSBjaXVkYWQuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDcuIEFuZXhvcyB7LnRhYnNldH0NCg0KVG9kbyBlc3RlIGRvY3VtZW50byB5IGPDs2RpZ28gZXN0YSBkaXNwb25pYmxlIFthcXXDrV0oaHR0cDovL3JwdWJzLmNvbS9rZXBlbmEvYWN0aXZpZGFkMy1NeVMpDQoNCiMjIENvbnNpZ25hIGRlIGxhIEFjdGl2aWRhZCAxDQoNCkJhc2FkbyBlbiBsb3MgZGF0b3MgZGUgb2ZlcnRhcyBkZSB2aXZpZW5kYSBkZXNjYXJnYWRhcyBkZWwgcG9ydGFsIEZpbmNhcmFpeiBwYXJhIGFwYXJ0YW1lbnRvIGRlIGVzdHJhdG8gNCBjb24gw6FyZWEgY29uc3RydWlkYSBtZW5vciBhIDIwMCBtMiAodml2aWVuZGE0LlJEUykgbGEgaW5tb2JpbGlhcmlhIEEmQyByZXF1aWVyZSBlbCBhcG95byBkZSB1biBjaWVudMOtZmljbyBkZSBkYXRvcyBlbiBsYSBjb25zdHJ1Y2Npw7NuIGRlIHVuIG1vZGVsbyBxdWUgbG8gb3JpZW50ZSBzb2JyZSBsb3MgcHJlY2lvcyBkZSBpbm11ZWJsZXMuDQoNCkNvbiBlc3RlIHByb3DDs3NpdG8gZWwgZXF1aXBvIGRlIGFzZXNvcmVzIGhhIGRpc2XDsWFkbyBsb3Mgc2lndWllbnRlcyBwYXNvcyBwYXJhIG9idGVuZXIgdW4gbW9kZWxvIHkgYXPDrSBwb2RlciBhIGZ1dHVybyBkZXRlcm1pbmFyIGxvcyBwcmVjaW9zIGRlIGxvcyBpbm11ZWJsZXMgYSBuZWdvY2lhci4NCg0KMS4gUmVhbGljZSB1biBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvIGRlIGxhcyB2YXJpYWJsZXMgcHJlY2lvIGRlIHZpdmllbmRhIChtaWxsb25lcyBkZSBwZXNvcyBDT1ApIHkgw6FyZWEgZGUgbGEgdml2aWVuZGEgKG1ldHJvcyBjdWFkcmFkb3MpIC0gaW5jbHVpciBncsOhZmljb3MgZSBpbmRpY2Fkb3JlcyBhcHJvcGlhZG9zIGludGVycHJldGFkb3MuDQoNCjIuIFJlYWxpY2UgdW4gYW7DoWxpc2lzIGV4cGxvcmF0b3JpbyBiaXZhcmlhZG8gZGUgZGF0b3MsIGVuZm9jYWRvIGVuIGxhIHJlbGFjacOzbiBlbnRyZSBsYSB2YXJpYWJsZSByZXNwdWVzdGEgKHByZWNpbykgZW4gZnVuY2nDs24gZGUgbGEgdmFyaWFibGUgcHJlZGljdG9yYSAow6FyZWEgY29uc3RydWlkYSkgLSBpbmNsdWlyIGdyw6FmaWNvcyBlIGluZGljYWRvcmVzIGFwcm9waWFkb3MgaW50ZXJwcmV0YWRvcy4NCg0KMy4gRXN0aW1lIGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbCBzaW1wbGUgZW50cmUgJHByZWNpbyA9IGYoYXJlYSkgKyBlcHNpbG9uJC4gSW50ZXJwcmV0ZSBsb3MgY29lZmljaWVudGVzIGRlbCBtb2RlbG8gYmV0YTAsIGJldGExIGVuIGNhc28gZGUgc2VyIGNvcnJlY3RvLg0KDQo0LiBDb25zdHJ1aXIgdW4gaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSAoOTUlKSBwYXJhIGVsIGNvZWZpY2llbnRlIGJldGExLCBpbnRlcnByZXRhciB5IGNvbmNsdWlyIHNpIGVsIGNvZWZpY2llbnRlIGVzIGlndWFsIGEgY2VybyBvIG5vLiBDb21wYXJlIGVzdGUgcmVzdWx0YWRvIGNvbiB1bmEgcHJ1ZWJhIGRlIGhpcMOzdGVzaXMgdC4NCg0KNS4gQ2FsY3VsZSBlIGludGVycHJldGUgZWwgaW5kaWNhZG9yIGRlIGJvbmRhZCAkUl4yJC4NCg0KNi4gwr9DdcOhbCBzZXLDrWEgZWwgcHJlY2lvIHByb21lZGlvIGVzdGltYWRvIHBhcmEgdW4gYXBhcnRhbWVudG8gZGUgMTEwIG1ldHJvcyBjdWFkcmFkb3M/IENvbnNpZGVyYSBlbnRvbmNlcyBjb24gZXN0ZSByZXN1bHRhZG8gcXVlIHVuIGFwYXJ0YW1lbnRvIGVuIGxhIG1pc21hIHpvbmEgY29uIDExMCBtZXRyb3MgY3VhZHJhZG9zIGVuIHVuIHByZWNpbyBkZSAyMDAgbWlsbG9uZXMgc2Vyw61hIHVuYSBhdHJhY3RpdmEgZXN0YSBvZmVydGE/IMK/UXXDqSBjb25zaWRlcmFjaW9uZXMgYWRpY2lvbmFsZXMgc2UgZGViZW4gdGVuZXI/Lg0KIA0KNy4gUmVhbGljZSBsYSB2YWxpZGFjacOzbiBkZSBsb3Mgc3VwdWVzdG9zIGRlbCBtb2RlbG8gcG9yIG1lZGlvIGRlIGdyw6FmaWNvcyBhcHJvcGlhZG9zLCBpbnRlcnByZXRhcmxvcyB5IHN1Z2VyaXIgcG9zaWJsZXMgc29sdWNpb25lcyBzaSBzZSB2aW9sYW4gYWxndW5vcyBkZSBlbGxvcy4gVXRpbGljZSBsYXMgcHJ1ZWJhcyBkZSBoaXDDs3Rlc2lzIHBhcmEgbGEgdmFsaWRhY2nDs24gZGUgc3VwdWVzdG9zIHkgY29tcGFyZSBsb3MgcmVzdWx0YWRvcyBjb24gbG8gb2JzZXJ2YWRvIGVuIGxvcyBncsOhZmljb3MgYXNvY2lhZG9zLg0KDQo4LiBEZSBzZXIgbmVjZXNhcmlvIHJlYWxpY2UgdW5hIHRyYW5zZm9ybWFjacOzbiBhcHJvcGlhZGEgcGFyYSBtZWpvcmFyIGVsIGFqdXN0ZSB5IHN1cHVlc3RvcyBkZWwgbW9kZWxvLg0KDQo5LiBEZSBzZXIgbmVjZXNhcmlvIGNvbXBhcmUgZWwgYWp1c3RlIHkgc3VwdWVzdG9zIGRlbCBtb2RlbG8gaW5pY2lhbCB5IGVsIHRyYW5zZm9ybWFkby4NCg0KMTAuIEVzdGltZSB2YXJpb3MgbW9kZWxvcyB5IGNvbXBhcmUgbG9zIHJlc3VsdGFkb3Mgb2J0ZW5pZG9zLiBFbiBlbCBtZWpvciBkZSBsb3MgbW9kZWxvcywgwr9zZSBjdW1wbGVuIGxvcyBzdXB1ZXN0b3Mgc29icmUgbG9zIGVycm9yZXM/DQoNCjExLiBDb24gbG9zIHJlc3VsdGFkb3Mgb2J0ZW5pZG9zIGNvbnN0cnV5YSB1biBpbmZvcm1lIHBhcmEgbG9zIGRpcmVjdGl2b3MgZGUgbGEgaW5tb2JpbGlhcmlhLCBpbmRpY2FuZG8gZWwgbW9kZWxvIGFwcm9waWFkbyB5IHN1cyBwcmluY2lwYWxlcyBjYXJhY3RlcsOtc3RpY2FzLiBBIGVzdGUgaW5mb3JtZSBzZSBkZWJlbiBhw7FhZGlyIGxvcyBhbmV4b3MgY29tbyBldmlkZW5jaWEgZGUgbGEgcmVhbGl6YWNpw7NuIGRlIGxvcyBwYXNvcyBhbnRlcmlvcmVzLg0KDQojIyBDb25qdW50byAgZGUgRGF0b3MNCg0KKipEZXNjcmlwY2nDs24qKg0KDQpFc3RhIGRhdGEgY29udGllbmUgaW5mb3JtYWNpw7NuIHNvYnJlIGNhcmFjdGVyaXN0aWNhcyBkZSB2aXZpZW5kYXMgZGUgbGEgY2l1ZGFkIGRlIENhbGkuDQoNCioqwr9Dw7NtbyBzZSB1c2E/OioqIFNvbG8gaGF5IHF1ZSBlc2NyaWJpciAiZGF0YSh2aXZpZW5kYTQpIiBzaW4gbGFzIGNvbWlsbGFzLg0KDQoqKlJlZ2lzdHJvcyoqOiBDb25qdW50byBjb24gMTcwNiByZWdpc3Ryb3MgeSA1IHZhcmlhYmxlcw0KDQoqKlZhcmlhYmxlcy9Db2x1bW5hcyoqIA0KDQotIHpvbmE6DQpab25hIGRlIGxhIGNpdWRhZCAoVW5hIGRlIGNpbmNvOiBOb3J0ZSwgU3VyLCBPcmllbnRlLCBPZXN0ZSB5IENlbnRybykNCg0KLSBlc3RyYXRvOg0KRXN0cmF0byBkb25kZSBlc3RhIGxhIHZpdmllbmRhDQoNCi0gcHJlY2lvbToNClByZWNpbyBlbiBtaWxsb25lcyBkZSBwZXNvcw0KDQotIGFyZWFjb25zdDoNCsOBcmVhIGNvbnN0cnVpZGEgZW4gbWV0cm9zIGN1YWRyYWRvcw0KDQotIHRpcG86DQpUaXBvIGRlIHZpdmllbmRhDQo=