Introducción

En el presente trabajo se realizará una análisis del mercado inmobiliario a través de distintos modelos de regresión múltiple. Se comparan los resultados y se evaluan los supuestos sobre los que se apoyan.

Cargamos librerías y datos

1) Regresión lineal múltiple

Elaboramos un modelo con todas las covariables

modelo0=lm(price~rooms+bathrooms+surface_total+surface_covered+property_type+l3,data=df)
summary(modelo0)

Call:
lm(formula = price ~ rooms + bathrooms + surface_total + surface_covered + 
    property_type + l3, data = df)

Residuals:
    Min      1Q  Median      3Q     Max 
-400904  -33817   -3307   24660  560915 

Coefficients:
                            Estimate Std. Error t value Pr(>|t|)    
(Intercept)               -109406.61    4788.67 -22.847  < 2e-16 ***
rooms                       -3961.27     444.58  -8.910  < 2e-16 ***
bathrooms                   34040.98     644.28  52.836  < 2e-16 ***
surface_total                 919.08      23.52  39.069  < 2e-16 ***
surface_covered              1457.18      28.73  50.715  < 2e-16 ***
property_typeDepartamento   92653.32    2191.23  42.284  < 2e-16 ***
property_typePH             46779.37    2274.94  20.563  < 2e-16 ***
l3Agronomía                   623.53    8846.14   0.070 0.943807    
l3Almagro                   -4520.04    4295.24  -1.052 0.292650    
l3Balvanera                -24788.27    4551.65  -5.446 5.18e-08 ***
l3Barracas                 -10128.24    5351.06  -1.893 0.058397 .  
l3Barrio Norte              49921.81    4417.82  11.300  < 2e-16 ***
l3Belgrano                  69648.12    4283.55  16.259  < 2e-16 ***
l3Boca                     -47540.60    7076.20  -6.718 1.86e-11 ***
l3Boedo                    -19034.38    5219.54  -3.647 0.000266 ***
l3Caballito                  6220.15    4301.29   1.446 0.148153    
l3Catalinas                -76321.95   33563.74  -2.274 0.022974 *  
l3Centro / Microcentro     -29046.49    6781.80  -4.283 1.85e-05 ***
l3Chacarita                 11903.39    5299.02   2.246 0.024687 *  
l3Coghlan                   40820.55    5462.90   7.472 8.02e-14 ***
l3Colegiales                34073.02    4816.54   7.074 1.52e-12 ***
l3Congreso                 -32314.97    5494.75  -5.881 4.10e-09 ***
l3Constitución             -47292.98    6321.63  -7.481 7.50e-14 ***
l3Flores                   -22510.27    4536.15  -4.962 6.99e-07 ***
l3Floresta                 -28315.65    5069.38  -5.586 2.34e-08 ***
l3Las Cañitas               90455.90    5883.38  15.375  < 2e-16 ***
l3Liniers                  -20080.34    5366.27  -3.742 0.000183 ***
l3Mataderos                -33863.43    5424.79  -6.242 4.35e-10 ***
l3Monserrat                -32431.49    5228.46  -6.203 5.59e-10 ***
l3Monte Castro              -8770.72    5949.63  -1.474 0.140445    
l3Nuñez                     56958.42    4559.69  12.492  < 2e-16 ***
l3Once                     -30757.83    5456.51  -5.637 1.74e-08 ***
l3Palermo                   66169.58    4221.50  15.674  < 2e-16 ***
l3Parque Avellaneda        -34398.95    7598.09  -4.527 5.99e-06 ***
l3Parque Centenario        -12288.30    5016.45  -2.450 0.014305 *  
l3Parque Chacabuco         -22537.83    5314.36  -4.241 2.23e-05 ***
l3Parque Chas                5195.26    7542.97   0.689 0.490981    
l3Parque Patricios         -36808.02    5973.29  -6.162 7.24e-10 ***
l3Paternal                 -13314.50    5189.69  -2.566 0.010304 *  
l3Pompeya                  -79977.17    8035.74  -9.953  < 2e-16 ***
l3Puerto Madero            259015.83    5095.12  50.836  < 2e-16 ***
l3Recoleta                  64088.22    4360.34  14.698  < 2e-16 ***
l3Retiro                    26067.40    5281.27   4.936 8.01e-07 ***
l3Saavedra                  19492.00    4914.18   3.966 7.31e-05 ***
l3San Cristobal            -23739.75    4955.13  -4.791 1.67e-06 ***
l3San Nicolás              -26247.55    5168.96  -5.078 3.83e-07 ***
l3San Telmo                 -5653.85    4877.12  -1.159 0.246356    
l3Tribunales               -34608.17    8924.63  -3.878 0.000106 ***
l3Velez Sarsfield          -25943.69    8303.75  -3.124 0.001783 ** 
l3Versalles                -22232.13    6758.40  -3.290 0.001004 ** 
l3Villa Crespo               1595.26    4317.54   0.369 0.711770    
l3Villa del Parque          -3290.17    4866.59  -0.676 0.498997    
l3Villa Devoto              13301.39    4807.08   2.767 0.005659 ** 
l3Villa General Mitre      -19170.08    6802.25  -2.818 0.004831 ** 
l3Villa Lugano             -83039.18    6533.35 -12.710  < 2e-16 ***
l3Villa Luro                -7579.11    5404.78  -1.402 0.160833    
l3Villa Ortuzar             18667.61    6829.18   2.734 0.006269 ** 
l3Villa Pueyrredón          10516.80    5349.56   1.966 0.049314 *  
l3Villa Real                -8823.37    8745.56  -1.009 0.313030    
l3Villa Riachuelo          -32775.66   17171.10  -1.909 0.056298 .  
l3Villa Santa Rita          -5767.71    6383.86  -0.903 0.366274    
l3Villa Soldati           -136489.91   18944.29  -7.205 5.90e-13 ***
l3Villa Urquiza             30648.43    4418.91   6.936 4.09e-12 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 66580 on 45841 degrees of freedom
Multiple R-squared:  0.7764,    Adjusted R-squared:  0.7761 
F-statistic:  2568 on 62 and 45841 DF,  p-value: < 2.2e-16

Análisis de variables constinuas y discretas:

El intercepto en nuestro ejemplo carece de sentido, ya que no tiene sentido ni interpretabilidad para nuestro problema un PH o departamente con cero metros cuadrados totales, cero baños, ambientes, etc. El Coeficiente “superficie cubierta” es significativos en su p-valor y de 1457, es decir, que la respuesta media de nuestro modelo en el precio en dólares de una vivienda cuando se incrementa en un metro cuadrado cubierto (y todas las demás variables de nuestro modelo se mantienen constantes), es de 1457 USD. Sin embargo, como en nuestro modelo tambien tenemos la variable “metros cuadrados totales”, por cada incremento en un metro cuadrado cubierto, inevitablemente se incrementará en la misma medida los metros totales. El coeficiente “superficie total” (tambien muy significativos) nos muestra una respuesta media de nuestro modelo en el precio en dólares de la vivienda de 919 USD (al mantener constante todo lo demás). Como el M2 cubierto y el total suben necesariamente juntos al incrementar un metro cuadrado podrìa pensarse como que el metro cuadrado cubierto en realidad incrementa el precio en 1457+919 =2.376 USD, mientras que el metro cuadrado descubierto (que suma al total pero no en el cubierto) incrementa el precio en el modelo en promedio 919USD. Respecto al coeficiente de “baño”, nos indica que el precio promedio de una vivienda en el modelo sube sube algo mas de 34 mil dólares por cada baño que se adiciona a esta. Cabe destacar que su p-valor es significativo. La interpretación para un único baño también la considero con alguna particularidad, ya que supuestamente cualquier vivienda contaria con un baño. Sin embargo, al incrementarse los baños generalmente suele incrementarse la “calidad” de la vivienda, ya que estos cambios pueden obedecer simplmente otro baño o bien ser un toilette para visitas o cuartos en suite. Por este motivo tiene sentido que el valor sea positivo en este caso. En el caso de los “rooms” o ambientes el coeficiente es de -3961 USD. Si bien el p valor nos dice que valor es significativo, el coeficiente (por su tamaño) no parece estar jugando un rol clave en el precio total por los precios medio de las viviendas y las cantidades medias de ambientes. A primera vista puede sonar raro que al incrementar un ambiente no suba el precio, pero si consideramos que los metros cuadrados totales y cubiertos (y todas las demas variables) estan fijas, lo que vemos es que el incremento de un ambiente en cuanto creciento de la vivienda ya esta reflejado en estas otras variables. Con lo cual, intuimos que una casa grande con muchos ambientes en el modelo estará valuada en promedio a un precio menor que la misma vivienda (junto con sus características) con menos ambientes. Así, por ejemplo, el barrio más caro de Buenos Aires, Puerto Madero, adiciona en nuestro modelo al precio de la vivienda más de 250 mil USD, manteniendo constantes el resto de las variables.

Análisis de variables categóricas:

Las variables categóricas (“tipo de propiedad” y “Barrio” o l3) se abren como nuevas variable dummys (que pueden valer 1 o 0) para cada posibilidad de nivel categórico. Vale aclarar que en todos los casos categóricos un nivel siempre cumplirá el rol basal, esto es, que no veremos un coeficiente para esta categoría y que todos los otros coeficientes estarán expresando su movimiento relativo a la categoría basal. En el caso del tipo de propiedad, el caso basal es Casa, con lo cual vemos los coeficientes de PH y departamento.El coeficiente de ambos es significativo e igual a 46.779 USD y 92.653 USD, respectivamente. Es decir, que si una propiedad se corresponde con PH, el coeficiente Dpto valdrá cero y PH 1. Con lo cual, sus valores nos indican que, ante todo el resto invariante, si una vivienda es Dpto, el valor del precio predicho se incrementará respecto a los valores de una casa en mayor medida que en los casos de PH. De forma análoga pero con muchos más niveles, el factor del barrio puede afectar ajustando el valor de una propiedad positivamente o negativamente respecto a la catagoría basal “Abasto”. Es decir, que los barrios menos exclusivos (generalmente en el sur de la ciudad) como Lugano, la Boca, etc. tienen coeficientes de considerable tamaño, negativos (o sea que tienen un menor valor al relativo a Abasto) y son significativos en términos de su p-valor. Las variables Dummy que no son significativas se corresponden con aquellos barrios en los cuales su coeficiente es chico o se acerca a al nivel basal, esto es, que es dificil saber con precisión si su presencia conlleva un aumento o una descenso del valor de la propiedad respecto al barrio de Abasto.

Creamos un modelo en el que excluye la variable explicativa Barrio

modelo1=lm(price~rooms+bathrooms+surface_total+surface_covered+property_type,data=df)
summary(modelo1)

Call:
lm(formula = price ~ rooms + bathrooms + surface_total + surface_covered + 
    property_type, data = df)

Residuals:
    Min      1Q  Median      3Q     Max 
-518799  -36177   -9643   25740  724251 

Coefficients:
                            Estimate Std. Error t value Pr(>|t|)    
(Intercept)               -131096.86    2750.50  -47.66   <2e-16 ***
rooms                      -13348.53     519.02  -25.72   <2e-16 ***
bathrooms                   42664.68     756.37   56.41   <2e-16 ***
surface_total                 877.03      27.59   31.79   <2e-16 ***
surface_covered              1783.80      33.53   53.21   <2e-16 ***
property_typeDepartamento  135177.47    2513.93   53.77   <2e-16 ***
property_typePH             68598.52    2677.46   25.62   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 79210 on 45897 degrees of freedom
Multiple R-squared:  0.6832,    Adjusted R-squared:  0.6831 
F-statistic: 1.649e+04 on 6 and 45897 DF,  p-value: < 2.2e-16

En el modelo sin barrios todos los coeficientes son significativos. Respecto a los coeficientes, todos mantienen sus signos, aunque en el caso de los ambientes o “rooms” el descenso por unidad aumento de casi 4 mil USD a algo más de 13 mil USD. De forma parecida, pero en positivo, los incrementos asociados a los baños pasaron de 34mil USD a 42,6 mil USD. A su vez el valor del metro cuadrado cubierto, mientras en el modelo anterior crecía a una razon de USD 1457, ahora lo hace en USD 1783. El metro cuadrado total pasó de 919 USD a 877USD. Todo ello implica que el metro cuadrado cubierto completo paso de 2.376 a 2.660. Podría intuirse que al no tener la variable explicativa del barrio, los incrementos y descensos resultante de ella pasan a intentar ser reflajadas con mayores (y menores) coeficientes según corresponda.

Medidas de evaluación del modelo:

Cuando en el primer TP hicimos modelos de regresión simple, la mejor variable (como superficie total) nos arrojó un R2 menor al 0,5. Es decir, que casi en un 50% la proporción de variabilidad de los precios de las viviendas nos quedaba explicada por el modelo de regresión (relativo a la variabilidad explicada simplemente por un promedio). Como al incorporar nuevas variables el R2 nunca puede reducirse (aunque las variables incluso tengan poco que ver con el problema), es que debe usarse el R2 ajustado por el numero de covariables explicativas incluidas en el modelo. En nuestro primer modelo de regresión multiple el valor de R2 ajustado es de 0,776 lo que nos da una idea de que la proporción de variabilidad explicada se incremento en buena medida respecto al TP1. La segunda regresión múltiple sin el barrio, reduce el R2 ajustado a 0,683. Como esta medida esta ajustada por la variable que falta, podemos afirmar que el modelo con los barrios tiene una mayor proporción de variabilidad explicada en el precios de las viviendas respecto a evaluarlo solo la una media.

1.2) Evaluación del modelo en ciertos puntos

#Simplificar este código
vector1=c('Dpto_Abasto','Abasto',4,2,120,120,0,'Departamento')
vector2=c('PH_Balvanera','Balvanera',3,2,80,100,0,'PH')
df_test=rbind(df[1,],vector1,vector2)
df_test$rooms=as.numeric(df_test$rooms)
df_test$bathrooms=as.numeric(df_test$bathrooms)
df_test$surface_total=as.numeric(df_test$surface_total)
df_test$surface_covered=as.numeric(df_test$surface_covered)
df_test$price=as.numeric(df_test$price)
df_test=df_test[2:3,]
prediccion=predict(modelo0,df_test)
print(df_test)
prediccion
       1        2 
320635.2 188027.3 

Creo dos vectores emulando las características de la casa de abasto (1) y la casa de Balvanera (2) y predigo su valor de acuerdo al modelo creado anteriormente. Independientemente de si en el mercado una opción se vende (más rapido) o no y teniendo únicamente en cuenta el valor de la propiedad, de acuerdo con el modelo, el precio del dpto en el Abasto rondaría los 320 mil dólares mientras que PH en Balvanera estaría cerca de los 188 mil dólares. Con lo cual convendría el primero para vender.

2) Creación de variables

Para poder clasificar los barrio en “alto” “medio” y “bajo”, calculo el precio por metro cuadrado total promedio por barrio.

df=df %>% 
  mutate(precio_M_cuadrado=price/surface_total)
precioXbarrio=df %>% 
  # select(l3,precio_M_cuadrado) %>%
  group_by(l3) %>%
  summarise(precio_M_cuadrado_promedio=mean(precio_M_cuadrado))
print(summary(precioXbarrio))  
      l3            precio_M_cuadrado_promedio
 Length:57          Min.   :1093              
 Class :character   1st Qu.:2062              
 Mode  :character   Median :2204              
                    Mean   :2358              
                    3rd Qu.:2579              
                    Max.   :5472              

Ahora, simplemente ordenamos de menor a mayor los precios por metro cuadrados promedio de cada barrio.

ggplot(precioXbarrio,mapping=aes(x=fct_reorder(l3,precio_M_cuadrado_promedio,.desc = F),y=precio_M_cuadrado_promedio))+
geom_point()+
theme_bw()+
theme(axis.text.x = element_text(angle = 90),plot.title = element_text(hjust = 0.5),plot.subtitle = element_text(hjust = 0.5))+
geom_hline(yintercept = 2062,col="blue")+
geom_hline(yintercept = 2579,col="red")+
labs(title = "Precio promedio por M2 de viviendas por barrio",subtitle = "1er cuartil (azul) = 2.062USD // 3er cuartil (rojo) = 2.579USD")+
xlab("Barrio")+
ylab("Precio prom. por metro cuadrado")

Como se puede observar el 50% de los barrios se encuentran en un rango menor de precio promedio por metro cuadrado al 25% de los barrios con precios mas altos y mas bajos. Por este motivo se propone interpretar como “alto” al 25% de los barrios con los mayores precios por metro cuadrado promedio y como “bajo” al 25% de los de menor precio. Es decir, que como utilizaremos esta etiqueta para captar variabilidad del precio de las viviendas en un futuro modelo, entiendo que tomar proporciones de barrios iguales reduciría mucho el efecto de la etiqueta “media” en su capacidad de predecir un precio de una vivienda. No está de más aclarar que esta división no puede mantener dichas proporciones a la hora de analizar a nivel de viviendas ya que cada barrio tiene cantidades de casas en venta distintas.

Incorporamos una columna con “alto” “medio” y “bajo” en función de si superan el Cuartil 3 o estan por debajo del cuartil 1.

df2=df %>%
  group_by(l3=as.factor(l3)) %>% 
  mutate(mediadelbarrio=mean(price/surface_total)) %>%
  ungroup() %>% 
  mutate(Q1=2062,Q3=2579) %>%
  transmute(l3,barrios=as_factor(case_when(
    mediadelbarrio<Q1~"Bajo",
    mediadelbarrio>Q3~"Alto",
    TRUE~"Medio")))
df3=cbind(df,df2)

2.2) Modelo con variables construidas

Procedemos entonces a realizar el modelo de regresión lineal multiple con nuestra nueva variable “barrios”.

modelo2=lm(price~rooms+bathrooms+surface_total+surface_covered+property_type+barrios,data=df3)
summary(modelo2)

Call:
lm(formula = price ~ rooms + bathrooms + surface_total + surface_covered + 
    property_type + barrios, data = df3)

Residuals:
    Min      1Q  Median      3Q     Max 
-434681  -37269   -5344   25482  698983 

Coefficients:
                            Estimate Std. Error t value Pr(>|t|)    
(Intercept)               -154183.93    2757.84  -55.91   <2e-16 ***
rooms                       -8747.45     477.91  -18.30   <2e-16 ***
bathrooms                   36466.47     696.08   52.39   <2e-16 ***
surface_total                 877.73      25.31   34.67   <2e-16 ***
surface_covered              1641.81      30.76   53.37   <2e-16 ***
property_typeDepartamento  103741.18    2333.65   44.45   <2e-16 ***
property_typePH             54097.47    2459.08   22.00   <2e-16 ***
barriosAlto                 87378.78    1539.32   56.77   <2e-16 ***
barriosMedio                25199.05    1546.42   16.30   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 72540 on 45895 degrees of freedom
Multiple R-squared:  0.7343,    Adjusted R-squared:  0.7342 
F-statistic: 1.585e+04 on 8 and 45895 DF,  p-value: < 2.2e-16

Lo que se observa de nuestro tercer modelo (2) es que resulta considerablemente más parecido al modelo con los barrios (modelo0) que al modelo eliminando dicha variable (modelo1). Es decir, el coeficiente de “baño” es 36 mil USD cuando en el modelo0 era de 34 mil, el coeficiente de superficie total era de aproximadamente 900 USD y ahora es de 877 USD, mientras que superficie cubierta era de 1457USD y ahora es de 1641USD (mas alto pero menos a los casi 1800USD del modelo1 sin barrios). En el mismo sentido, el factor “departamento” que sumaba 93 mil USD por sobre el caso basal de Casa en el modelo0 y 135 mil USD en el modelo1 (sin barrios) ahora suma 87 mil (similar al mejor modelo0) e igual con el factor “PH” 47 mil USD en el modelo0 y 69 mil en el modelo1 y ahora 54 mil USD. Los barrios de “alto valor por metro cuadrado promedio” incorporan en nuestro modelo2 de predicción de precio de vivienda, si mantenemos todas las otras variables constante, casi 87 mil USD al valor que tendría una vivienda en un barrio caratulado de “bajo”. Los barrios “medios” adicionarían 25 mil USD en el modelo respecto a los bajos.

2.3) R ajustado de los modelos

En el modelo0 (con l3), el R ajustado es de 0,776 mientras que en el modelo con barrio dicho valor es de 0,734. El primer modelo tiene una diferencia ligeramente superior en la proporción de la variabilidad explicada por el modelo lineal sobre la total. La ventaja que observo del modelo con barrio es que con una importante reducción y simplificación del modelo (gracias a la reducción de más de 50 variables dummys) su R ajustado casi no sufrió una caída considerable. Considero que el primer modelo tiene una diferenciación barrio a barrio que permite, adicionalmente a todo el análisis que realizamos, hacer otro tipo de evaluación como el de registrar si hay movimientos relativos entre los barrios. Esto es, si un barrio está encareciendose o abaratándose en relación a otros.

2.4) Análisis de las superficies de viviendas

Incorporo una variable de “superficie descubierta” como la resta de los metros totales menos los metros cubiertos.

df3=df3[c(1,3,4,5,6,7,8,9,10,11)]
df3=df3 %>% 
  mutate(surface_patio=surface_total-surface_covered)

Si algun registro contuviera valores de superficie cubierta mayor que la total, eso nos estaría indicando un error en la carga de la información. Ese error podría provenir de una carga erronea en la superficie total o en la cubierta o en ambas. Si no tuvieramos forma de averiguarlo y si fueran pocos casos, sería recomendable eliminar los registros por ser poco confiables.

df3 %>% 
  filter(surface_patio<0)
NA

Como vemos, no existe ningún registro con superficie descubierta menor que cero. Todos los registros tienen coherencia.

MODELO LINEAL con la nueva variable “surface_patio”:

modelo3=lm(price~rooms+bathrooms+surface_covered+property_type+barrios+surface_patio,data=df3)
summary(modelo3)

Call:
lm(formula = price ~ rooms + bathrooms + surface_covered + property_type + 
    barrios + surface_patio, data = df3)

Residuals:
    Min      1Q  Median      3Q     Max 
-434681  -37269   -5344   25482  698983 

Coefficients:
                            Estimate Std. Error t value Pr(>|t|)    
(Intercept)               -154183.93    2757.84  -55.91   <2e-16 ***
rooms                       -8747.45     477.91  -18.30   <2e-16 ***
bathrooms                   36466.47     696.08   52.39   <2e-16 ***
surface_covered              2519.54      16.22  155.31   <2e-16 ***
property_typeDepartamento  103741.18    2333.65   44.45   <2e-16 ***
property_typePH             54097.47    2459.08   22.00   <2e-16 ***
barriosAlto                 87378.78    1539.32   56.77   <2e-16 ***
barriosMedio                25199.05    1546.42   16.30   <2e-16 ***
surface_patio                 877.73      25.31   34.67   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 72540 on 45895 degrees of freedom
Multiple R-squared:  0.7343,    Adjusted R-squared:  0.7342 
F-statistic: 1.585e+04 on 8 and 45895 DF,  p-value: < 2.2e-16

En este ejercicio, en el que se quitó la superficie total y se agregó surface_patio, podemos volver a reafirmar las conclusiones obtenidas en el primer modelo0. Esto es, que necesariamente así como el metro cuadrado cubierto era la suma del cubierto y total (ya que no pueden separarse), el “total” tenía que representar al metro cuadrado descubierto. Esto se confirma ya que el modelo 3 y 2 son exactamente iguales.

3) Evaluación de modelo y residuos

Calculamos los residuos

# res <- broom::augment(modelo3,df3)
# ggplot(res,aes(.fitted,.resid))+
#   geom_point()+
#   theme_bw()+
#   theme(plot.title = element_text(hjust = 0.5),plot.subtitle = element_text(hjust = 0.5))+
#   geom_hline(yintercept = 0)+
#   geom_smooth(se=FALSE)+
#   labs(title = "Errores de modelo3 de regresión multiple",subtitle = "Tendencia en linea azul")+
# xlab("predicción")+
# ylab("residuos")
plot(modelo3)

Para chequear que los supuestos del modelo de regresión lineal multiple se cumplen, se realizaron los precedentes gráficos. En el primer gráfico (redisual vs Fitted) lo que se observa es que los residuos contra los valores predichos estan centrados en torno al cero, cosa que en gran medida se verifica si se observa la linea roja, salvo para valores predichos pequeños.Ello refleja que no se observa una correlación importante entre los errores, es decir que no se nota una tendencia o comportamiento claro.
En cuando a la homogeneidad de la varianza de los errores se destaca que no se observa una nube de puntos uniforme, sino que se incrementa en valores predichos medios y vuelve a reducirse en valores grandes. Ello reflejaría un problema de heterocedasticidad de los residuos violando uno de los supuestos necesarios para poder confiar en nuestro modelo de regresión multiple.
El segundo gráfico (normal Q-Q) detalla en qué medida la distribución de los errores se ajustan a una distribución normal (graficada como una recta de pendiente positiva). El problema que vemos es que los errores en sus extremos no se ajustan a una distribución normal, lo que genera otro problema para los supuestos del modelo3.

3.2) Evaluación de modelo con una transformación logaritmica

La transformación logarítmica es una forma de transformar relaciones exponenciales en relaciones lineales sin alterar el comportamiento intrinseco de las variables. Por eso aplicamos estas transformaciones a las variables numéricas.

summary(modelo4)

Call:
lm(formula = log(price) ~ log(rooms) + log(bathrooms) + log(surface_covered) + 
    property_type + barrios + surface_patio, data = df3)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.29710 -0.15116 -0.00538  0.13944  1.38298 

Coefficients:
                            Estimate Std. Error t value Pr(>|t|)    
(Intercept)                8.163e+00  1.943e-02 420.161   <2e-16 ***
log(rooms)                -4.737e-02  3.914e-03 -12.103   <2e-16 ***
log(bathrooms)             1.819e-01  3.951e-03  46.034   <2e-16 ***
log(surface_covered)       8.201e-01  4.596e-03 178.429   <2e-16 ***
property_typeDepartamento  2.379e-01  7.490e-03  31.759   <2e-16 ***
property_typePH            7.122e-02  7.927e-03   8.985   <2e-16 ***
barriosAlto                4.451e-01  5.013e-03  88.779   <2e-16 ***
barriosMedio               1.685e-01  5.036e-03  33.460   <2e-16 ***
surface_patio              3.892e-03  8.262e-05  47.104   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2362 on 45895 degrees of freedom
Multiple R-squared:  0.8079,    Adjusted R-squared:  0.8078 
F-statistic: 2.412e+04 on 8 and 45895 DF,  p-value: < 2.2e-16

Lo primero a destacar del nuevo modelo, es que el R2 ajustado se eleva de 0.73 del modelo3 a 0.808 en el modelo4 lo que nos indica que es el modelo que mayor asociación lineal presenta entre las X y las Y. Para interpretar nuestro nuevo modelo debemos ser concientes que aplicamos la transformación tanto a nuestra variable dependiente precio como a las independientes, por lo que nuestro modelo será log-log (Wooldridge, J.M (2006) pg. 46). En este sentido, el coeficiente de log(room) es de -0,0473 por lo que podemos decir que una variación de un 1% (positivo) en la cantidad de ambientes afectará (negativamente) en -0,0473% por ciento en el precio predicho por el modelo, ante todas las otras variables constantes. Por su partes variaciones de 1% en baños, superficie cubierta y descubierta generaran en nuestro modelo4 variaciones en el precio de 0,1819%, 0,8201% y 0,004%, respectivamente. Para el caso de las variables categóricas, como no se aplicó transformación en la variable independiente, el modelo es Log-nivel lo que nos requiere multiplicar por 100 los coeficientes para ver los cambios porcentuales del precio. Así, si la vivienda es un departamento se incrementará casi un 24% en el precio predicho por sobre las “Casas” o bien un 7% si fuese PH. Barrios rotulados como “alto” adicionan un 44% al precio predicho sobre el nivel de “Bajo” y 16% si es “medio”.

Si repetimos el análisis en materia de residuos con el nuevo modelo obtenemos los siguientes resultados.

Podemos observar que el modelo con las transformaciones logarítmicas ha mejorado considerablemente el problema de heterocedasticidad presente en el modelo3. Esto se observa en el primer gráfico en una mejoría en las homogeneidad relativa de los errores para los valores predichos (fitted values) pequeños y grandes. A su vez también se ve en el QQ plot que los datos se ajustan mucho mejor a la linea de normalidad.

4) Análisis y modelos por tipo de propiedad

En primer lugar agrupamos los datos por tipo de propiedad

Ahora creamos una función para iterar el modelo4 en los distintos tipos de propiedad

  lm(log(price)~log(rooms)+log(bathrooms)+log(surface_covered)+barrios+surface_patio,data=df)
Error in eval(predvars, data, env) : object 'barrios' not found

Corremos la función para cada una de los tipos de propiedades

modelos_por_tipo_propiedad <- modelos_por_tipo_propiedad %>% 
  mutate(model=map(modelos_por_tipo_propiedad$data,funcion_modelo4))

observamos los resultados:

library("broom")
modelos_por_tipo_propiedad %>% 
  mutate(glnc=map(modelos_por_tipo_propiedad$model,glance)) %>% 
  unnest(glnc,.drop=TRUE)
NA

Respecto a los tres modelos, en primer lugar se puede descartar que todos los coeficientes de las variables sean nulos ya que el p-valor resulta significativo. Como los tres modelos son iguales, es decir, que no es necesario ajustar por el número de variables, miramos el valor de R2. En el caso de los “departamentos” se registra la mejor proporción de variabilidad explicada por el modelo, alcanzando un 0.82. Este caso es el único que supera al modelo4. Para Casa y PH el R2 es de 0.65 y 0.72.

Al revisar los coeficientes (todos ellos significativos) de cada modelo se observa mucha similitud en todos los parametros con la salvedad que para el tipo “departamento” se observan algunas particularidades. Asi, por ejemplo, mientras que ante cambios de un 1% en log(room), se prevee un cambio en el precio predicho tanto para Casa como PH de 0,08%, para “departamento” es de -0,07%. Los cambios en el precio predicho por cambios en la superficie cubierta de Casa y PH es de 0,56% y 0,58% mientras que para departamento es de 0,86%. Lo mismo ocurre con la superficie descubierta.

Referencias

-Wooldridge, J.M (2006). Introducción a la econometría: un enfoque moderno. Editorial Paraninfo.

LS0tDQp0aXRsZTogJ0Fuw6FsaXNpcyBkZWwgbWVyY2FkbyBpbm1vYmlsaWFyaW8gZW4gQ0FCQSBjb24gbW9kZWxvcyBkZSByZWdyZXNpb25lcyBtw7psdGlwbGVzJw0KYXV0aG9yOiAiQXJ0dXJvIFMuIExld2luZ2VyIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBoaWdobGlnaHQ6IGthdGUNCiAgICB0aGVtZTogam91cm5hbA0KZWRpdG9yX29wdGlvbnM6DQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQojIA0KIyBJbnRyb2R1Y2Npw7NuDQpFbiBlbCBwcmVzZW50ZSB0cmFiYWpvIHNlIHJlYWxpemFyw6EgdW5hIGFuw6FsaXNpcyBkZWwgbWVyY2FkbyBpbm1vYmlsaWFyaW8gYSB0cmF2w6lzIGRlIGRpc3RpbnRvcyBtb2RlbG9zIGRlIHJlZ3Jlc2nDs24gbcO6bHRpcGxlLiBTZSBjb21wYXJhbiBsb3MgcmVzdWx0YWRvcyB5IHNlIGV2YWx1YW4gbG9zIHN1cHVlc3RvcyBzb2JyZSBsb3MgcXVlIHNlIGFwb3lhbi4NCg0KIyMgQ2FyZ2Ftb3MgbGlicmVyw61hcyB5IGRhdG9zDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmRmIDwtIHJlYWRSRFMoJy4uL0VFQTIwMTkvYXJfcHJvcGVydGllcy5yZHMnKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KG1pY2UpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShHR2FsbHkpDQpsaWJyYXJ5KGNvcnJwbG90KQ0KbGlicmFyeSgiYnJvb20iKQ0KYGBgDQoNCg0KIyAxKSBSZWdyZXNpw7NuIGxpbmVhbCBtw7psdGlwbGUNCg0KRWxhYm9yYW1vcyB1biBtb2RlbG8gY29uIHRvZGFzIGxhcyBjb3ZhcmlhYmxlcw0KYGBge3J9DQptb2RlbG8wPWxtKHByaWNlfnJvb21zK2JhdGhyb29tcytzdXJmYWNlX3RvdGFsK3N1cmZhY2VfY292ZXJlZCtwcm9wZXJ0eV90eXBlK2wzLGRhdGE9ZGYpDQpzdW1tYXJ5KG1vZGVsbzApDQpgYGANCg0KQW7DoWxpc2lzIGRlIHZhcmlhYmxlcyBjb25zdGludWFzIHkgZGlzY3JldGFzOg0KDQpFbCBpbnRlcmNlcHRvIGVuIG51ZXN0cm8gZWplbXBsbyBjYXJlY2UgZGUgc2VudGlkbywgeWEgcXVlIG5vIHRpZW5lIHNlbnRpZG8gbmkgaW50ZXJwcmV0YWJpbGlkYWQgcGFyYSBudWVzdHJvIHByb2JsZW1hIHVuIFBIIG8gZGVwYXJ0YW1lbnRlIGNvbiBjZXJvIG1ldHJvcyBjdWFkcmFkb3MgdG90YWxlcywgY2VybyBiYcOxb3MsIGFtYmllbnRlcywgZXRjLg0KRWwgQ29lZmljaWVudGUgInN1cGVyZmljaWUgY3ViaWVydGEiIGVzIHNpZ25pZmljYXRpdm9zIGVuIHN1IHAtdmFsb3IgeSBkZSAxNDU3LCBlcyBkZWNpciwgcXVlIGxhIHJlc3B1ZXN0YSBtZWRpYSBkZSBudWVzdHJvIG1vZGVsbyBlbiBlbCBwcmVjaW8gZW4gZMOzbGFyZXMgZGUgdW5hIHZpdmllbmRhIGN1YW5kbyBzZSBpbmNyZW1lbnRhIGVuIHVuIG1ldHJvIGN1YWRyYWRvIGN1YmllcnRvICh5IHRvZGFzIGxhcyBkZW3DoXMgdmFyaWFibGVzIGRlIG51ZXN0cm8gbW9kZWxvIHNlIG1hbnRpZW5lbiBjb25zdGFudGVzKSwgZXMgZGUgMTQ1NyBVU0QuIFNpbiBlbWJhcmdvLCBjb21vIGVuIG51ZXN0cm8gbW9kZWxvIHRhbWJpZW4gdGVuZW1vcyBsYSB2YXJpYWJsZSAibWV0cm9zIGN1YWRyYWRvcyB0b3RhbGVzIiwgcG9yIGNhZGEgaW5jcmVtZW50byBlbiB1biBtZXRybyBjdWFkcmFkbyBjdWJpZXJ0bywgaW5ldml0YWJsZW1lbnRlIHNlIGluY3JlbWVudGFyw6EgZW4gbGEgbWlzbWEgbWVkaWRhIGxvcyBtZXRyb3MgdG90YWxlcy4gRWwgY29lZmljaWVudGUgInN1cGVyZmljaWUgdG90YWwiICAodGFtYmllbiBtdXkgc2lnbmlmaWNhdGl2b3MpIG5vcyBtdWVzdHJhIHVuYSByZXNwdWVzdGEgbWVkaWEgZGUgbnVlc3RybyBtb2RlbG8gZW4gZWwgcHJlY2lvIGVuIGTDs2xhcmVzIGRlIGxhIHZpdmllbmRhIGRlIDkxOSBVU0QgKGFsIG1hbnRlbmVyIGNvbnN0YW50ZSB0b2RvIGxvIGRlbcOhcykuIENvbW8gZWwgTTIgY3ViaWVydG8geSBlbCB0b3RhbCBzdWJlbiBuZWNlc2FyaWFtZW50ZSBqdW50b3MgYWwgaW5jcmVtZW50YXIgdW4gbWV0cm8gY3VhZHJhZG8gcG9kcsOsYSBwZW5zYXJzZSBjb21vIHF1ZSBlbCBtZXRybyBjdWFkcmFkbyBjdWJpZXJ0byBlbiByZWFsaWRhZCBpbmNyZW1lbnRhIGVsIHByZWNpbyBlbiAxNDU3KzkxOSA9Mi4zNzYgVVNELCBtaWVudHJhcyBxdWUgZWwgbWV0cm8gY3VhZHJhZG8gZGVzY3ViaWVydG8gKHF1ZSBzdW1hIGFsIHRvdGFsIHBlcm8gbm8gZW4gZWwgY3ViaWVydG8pIGluY3JlbWVudGEgZWwgcHJlY2lvIGVuIGVsIG1vZGVsbyBlbiBwcm9tZWRpbyA5MTlVU0QuDQpSZXNwZWN0byBhbCBjb2VmaWNpZW50ZSBkZSAiYmHDsW8iLCBub3MgaW5kaWNhIHF1ZSBlbCBwcmVjaW8gcHJvbWVkaW8gZGUgdW5hIHZpdmllbmRhIGVuIGVsIG1vZGVsbyBzdWJlIHN1YmUgYWxnbyBtYXMgZGUgMzQgbWlsIGTDs2xhcmVzIHBvciBjYWRhIGJhw7FvIHF1ZSBzZSBhZGljaW9uYSBhIGVzdGEuIENhYmUgZGVzdGFjYXIgcXVlIHN1IHAtdmFsb3IgZXMgc2lnbmlmaWNhdGl2by4gTGEgaW50ZXJwcmV0YWNpw7NuIHBhcmEgdW4gw7puaWNvIGJhw7FvIHRhbWJpw6luIGxhIGNvbnNpZGVybyBjb24gYWxndW5hIHBhcnRpY3VsYXJpZGFkLCB5YSBxdWUgc3VwdWVzdGFtZW50ZSBjdWFscXVpZXIgdml2aWVuZGEgY29udGFyaWEgY29uIHVuIGJhw7FvLiBTaW4gZW1iYXJnbywgYWwgaW5jcmVtZW50YXJzZSBsb3MgYmHDsW9zIGdlbmVyYWxtZW50ZSBzdWVsZSBpbmNyZW1lbnRhcnNlIGxhICJjYWxpZGFkIiBkZSBsYSB2aXZpZW5kYSwgeWEgcXVlIGVzdG9zIGNhbWJpb3MgcHVlZGVuIG9iZWRlY2VyIHNpbXBsbWVudGUgb3RybyBiYcOxbyBvIGJpZW4gc2VyIHVuIHRvaWxldHRlIHBhcmEgdmlzaXRhcyBvIGN1YXJ0b3MgZW4gc3VpdGUuIFBvciBlc3RlIG1vdGl2byB0aWVuZSBzZW50aWRvIHF1ZSBlbCB2YWxvciBzZWEgcG9zaXRpdm8gZW4gZXN0ZSBjYXNvLg0KRW4gZWwgY2FzbyBkZSBsb3MgInJvb21zIiBvIGFtYmllbnRlcyBlbCBjb2VmaWNpZW50ZSBlcyBkZSAtMzk2MSBVU0QuIFNpIGJpZW4gZWwgcCB2YWxvciBub3MgZGljZSBxdWUgdmFsb3IgZXMgc2lnbmlmaWNhdGl2bywgZWwgY29lZmljaWVudGUgKHBvciBzdSB0YW1hw7FvKSBubyBwYXJlY2UgZXN0YXIganVnYW5kbyB1biByb2wgY2xhdmUgZW4gZWwgcHJlY2lvIHRvdGFsIHBvciBsb3MgcHJlY2lvcyBtZWRpbyBkZSBsYXMgdml2aWVuZGFzIHkgbGFzIGNhbnRpZGFkZXMgbWVkaWFzIGRlIGFtYmllbnRlcy4gQSBwcmltZXJhIHZpc3RhIHB1ZWRlIHNvbmFyIHJhcm8gcXVlIGFsIGluY3JlbWVudGFyIHVuIGFtYmllbnRlIG5vIHN1YmEgZWwgcHJlY2lvLCBwZXJvIHNpIGNvbnNpZGVyYW1vcyBxdWUgbG9zIG1ldHJvcyBjdWFkcmFkb3MgdG90YWxlcyB5IGN1YmllcnRvcyAoeSB0b2RhcyBsYXMgZGVtYXMgdmFyaWFibGVzKSBlc3RhbiBmaWphcywgbG8gcXVlIHZlbW9zIGVzIHF1ZSBlbCBpbmNyZW1lbnRvIGRlIHVuIGFtYmllbnRlIGVuIGN1YW50byBjcmVjaWVudG8gZGUgbGEgdml2aWVuZGEgeWEgZXN0YSByZWZsZWphZG8gZW4gZXN0YXMgb3RyYXMgdmFyaWFibGVzLiBDb24gbG8gY3VhbCwgaW50dWltb3MgcXVlIHVuYSBjYXNhIGdyYW5kZSBjb24gbXVjaG9zIGFtYmllbnRlcyBlbiBlbCBtb2RlbG8gZXN0YXLDoSB2YWx1YWRhIGVuIHByb21lZGlvIGEgdW4gcHJlY2lvIG1lbm9yIHF1ZSBsYSBtaXNtYSB2aXZpZW5kYSAoanVudG8gY29uIHN1cyBjYXJhY3RlcsOtc3RpY2FzKSBjb24gbWVub3MgYW1iaWVudGVzLiBBc8OtLCBwb3IgZWplbXBsbywgZWwgYmFycmlvIG3DoXMgY2FybyBkZSBCdWVub3MgQWlyZXMsIFB1ZXJ0byBNYWRlcm8sIGFkaWNpb25hIGVuIG51ZXN0cm8gbW9kZWxvIGFsIHByZWNpbyBkZSBsYSB2aXZpZW5kYSBtw6FzIGRlIDI1MCBtaWwgVVNELCBtYW50ZW5pZW5kbyBjb25zdGFudGVzIGVsIHJlc3RvIGRlIGxhcyB2YXJpYWJsZXMuDQoNCkFuw6FsaXNpcyBkZSB2YXJpYWJsZXMgY2F0ZWfDs3JpY2FzOg0KDQpMYXMgdmFyaWFibGVzIGNhdGVnw7NyaWNhcyAoInRpcG8gZGUgcHJvcGllZGFkIiB5ICJCYXJyaW8iIG8gbDMpIHNlIGFicmVuIGNvbW8gbnVldmFzIHZhcmlhYmxlIGR1bW15cyAocXVlIHB1ZWRlbiB2YWxlciAxIG8gMCkgcGFyYSBjYWRhIHBvc2liaWxpZGFkIGRlIG5pdmVsIGNhdGVnw7NyaWNvLiBWYWxlIGFjbGFyYXIgcXVlIGVuIHRvZG9zIGxvcyBjYXNvcyBjYXRlZ8Ozcmljb3MgdW4gbml2ZWwgc2llbXByZSBjdW1wbGlyw6EgZWwgcm9sIGJhc2FsLCBlc3RvIGVzLCBxdWUgbm8gdmVyZW1vcyB1biBjb2VmaWNpZW50ZSBwYXJhIGVzdGEgY2F0ZWdvcsOtYSB5IHF1ZSB0b2RvcyBsb3Mgb3Ryb3MgY29lZmljaWVudGVzIGVzdGFyw6FuIGV4cHJlc2FuZG8gc3UgbW92aW1pZW50byByZWxhdGl2byBhIGxhIGNhdGVnb3LDrWEgYmFzYWwuIEVuIGVsIGNhc28gZGVsIHRpcG8gZGUgcHJvcGllZGFkLCBlbCBjYXNvIGJhc2FsIGVzIENhc2EsIGNvbiBsbyBjdWFsIHZlbW9zIGxvcyBjb2VmaWNpZW50ZXMgZGUgUEggeSBkZXBhcnRhbWVudG8uRWwgY29lZmljaWVudGUgZGUgYW1ib3MgZXMgc2lnbmlmaWNhdGl2byBlIGlndWFsIGEgNDYuNzc5IFVTRCB5IDkyLjY1MyBVU0QsIHJlc3BlY3RpdmFtZW50ZS4gRXMgZGVjaXIsIHF1ZSBzaSB1bmEgcHJvcGllZGFkIHNlIGNvcnJlc3BvbmRlIGNvbiBQSCwgZWwgY29lZmljaWVudGUgRHB0byB2YWxkcsOhIGNlcm8geSBQSCAxLiBDb24gbG8gY3VhbCwgc3VzIHZhbG9yZXMgbm9zIGluZGljYW4gcXVlLCBhbnRlIHRvZG8gZWwgcmVzdG8gaW52YXJpYW50ZSwgc2kgdW5hIHZpdmllbmRhIGVzIERwdG8sIGVsIHZhbG9yIGRlbCBwcmVjaW8gcHJlZGljaG8gc2UgaW5jcmVtZW50YXLDoSByZXNwZWN0byBhIGxvcyB2YWxvcmVzIGRlIHVuYSBjYXNhIGVuIG1heW9yIG1lZGlkYSBxdWUgZW4gbG9zIGNhc29zIGRlIFBILiANCkRlIGZvcm1hIGFuw6Fsb2dhIHBlcm8gY29uIG11Y2hvcyBtw6FzIG5pdmVsZXMsIGVsIGZhY3RvciBkZWwgYmFycmlvIHB1ZWRlIGFmZWN0YXIgYWp1c3RhbmRvIGVsIHZhbG9yIGRlIHVuYSBwcm9waWVkYWQgcG9zaXRpdmFtZW50ZSBvIG5lZ2F0aXZhbWVudGUgcmVzcGVjdG8gYSBsYSBjYXRhZ29yw61hIGJhc2FsICJBYmFzdG8iLiBFcyBkZWNpciwgcXVlIGxvcyBiYXJyaW9zIG1lbm9zIGV4Y2x1c2l2b3MgKGdlbmVyYWxtZW50ZSBlbiBlbCBzdXIgZGUgbGEgY2l1ZGFkKSBjb21vIEx1Z2FubywgbGEgQm9jYSwgZXRjLiB0aWVuZW4gY29lZmljaWVudGVzIGRlIGNvbnNpZGVyYWJsZSB0YW1hw7FvLCBuZWdhdGl2b3MgKG8gc2VhIHF1ZSB0aWVuZW4gdW4gbWVub3IgdmFsb3IgYWwgcmVsYXRpdm8gYSBBYmFzdG8pIHkgc29uIHNpZ25pZmljYXRpdm9zIGVuIHTDqXJtaW5vcyBkZSBzdSBwLXZhbG9yLiBMYXMgdmFyaWFibGVzIER1bW15IHF1ZSBubyBzb24gc2lnbmlmaWNhdGl2YXMgc2UgY29ycmVzcG9uZGVuIGNvbiBhcXVlbGxvcyBiYXJyaW9zIGVuIGxvcyBjdWFsZXMgc3UgY29lZmljaWVudGUgZXMgY2hpY28gbyBzZSBhY2VyY2EgYSBhbCBuaXZlbCBiYXNhbCwgZXN0byBlcywgcXVlIGVzIGRpZmljaWwgc2FiZXIgY29uIHByZWNpc2nDs24gc2kgc3UgcHJlc2VuY2lhIGNvbmxsZXZhIHVuIGF1bWVudG8gbyB1bmEgZGVzY2Vuc28gZGVsIHZhbG9yIGRlIGxhIHByb3BpZWRhZCByZXNwZWN0byBhbCBiYXJyaW8gZGUgQWJhc3RvLg0KDQoNCkNyZWFtb3MgdW4gbW9kZWxvIGVuIGVsIHF1ZSBleGNsdXllIGxhIHZhcmlhYmxlIGV4cGxpY2F0aXZhIEJhcnJpbw0KYGBge3J9DQptb2RlbG8xPWxtKHByaWNlfnJvb21zK2JhdGhyb29tcytzdXJmYWNlX3RvdGFsK3N1cmZhY2VfY292ZXJlZCtwcm9wZXJ0eV90eXBlLGRhdGE9ZGYpDQpzdW1tYXJ5KG1vZGVsbzEpDQpgYGANCkVuIGVsIG1vZGVsbyBzaW4gYmFycmlvcyB0b2RvcyBsb3MgY29lZmljaWVudGVzIHNvbiBzaWduaWZpY2F0aXZvcy4gUmVzcGVjdG8gYSBsb3MgY29lZmljaWVudGVzLCB0b2RvcyBtYW50aWVuZW4gc3VzIHNpZ25vcywgYXVucXVlIGVuIGVsIGNhc28gZGUgbG9zIGFtYmllbnRlcyBvICJyb29tcyIgZWwgZGVzY2Vuc28gcG9yIHVuaWRhZCBhdW1lbnRvIGRlIGNhc2kgNCBtaWwgVVNEIGEgYWxnbyBtw6FzIGRlIDEzIG1pbCBVU0QuIERlIGZvcm1hIHBhcmVjaWRhLCBwZXJvIGVuIHBvc2l0aXZvLCBsb3MgaW5jcmVtZW50b3MgYXNvY2lhZG9zIGEgbG9zIGJhw7FvcyBwYXNhcm9uIGRlIDM0bWlsIFVTRCBhIDQyLDYgbWlsIFVTRC4NCkEgc3UgdmV6IGVsIHZhbG9yIGRlbCBtZXRybyBjdWFkcmFkbyBjdWJpZXJ0bywgbWllbnRyYXMgZW4gZWwgbW9kZWxvIGFudGVyaW9yIGNyZWPDrWEgYSB1bmEgcmF6b24gZGUgVVNEIDE0NTcsIGFob3JhIGxvIGhhY2UgZW4gVVNEIDE3ODMuIEVsIG1ldHJvIGN1YWRyYWRvIHRvdGFsIHBhc8OzIGRlIDkxOSBVU0QgYSA4NzdVU0QuIFRvZG8gZWxsbyBpbXBsaWNhIHF1ZSBlbCBtZXRybyBjdWFkcmFkbyBjdWJpZXJ0byBjb21wbGV0byBwYXNvIGRlIDIuMzc2IGEgMi42NjAuIFBvZHLDrWEgaW50dWlyc2UgcXVlIGFsIG5vIHRlbmVyIGxhIHZhcmlhYmxlIGV4cGxpY2F0aXZhIGRlbCBiYXJyaW8sIGxvcyBpbmNyZW1lbnRvcyB5IGRlc2NlbnNvcyByZXN1bHRhbnRlIGRlIGVsbGEgcGFzYW4gYSBpbnRlbnRhciBzZXIgcmVmbGFqYWRhcyBjb24gbWF5b3JlcyAoeSBtZW5vcmVzKSBjb2VmaWNpZW50ZXMgc2Vnw7puIGNvcnJlc3BvbmRhLg0KDQoNCg0KTWVkaWRhcyBkZSBldmFsdWFjacOzbiBkZWwgbW9kZWxvOg0KDQpDdWFuZG8gZW4gZWwgcHJpbWVyIFRQIGhpY2ltb3MgbW9kZWxvcyBkZSByZWdyZXNpw7NuIHNpbXBsZSwgbGEgbWVqb3IgdmFyaWFibGUgKGNvbW8gc3VwZXJmaWNpZSB0b3RhbCkgbm9zIGFycm9qw7MgdW4gUjIgbWVub3IgYWwgMCw1LiBFcyBkZWNpciwgcXVlIGNhc2kgZW4gdW4gNTAlIGxhIHByb3BvcmNpw7NuIGRlIHZhcmlhYmlsaWRhZCBkZSBsb3MgcHJlY2lvcyBkZSBsYXMgdml2aWVuZGFzICBub3MgcXVlZGFiYSBleHBsaWNhZGEgcG9yIGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIChyZWxhdGl2byBhIGxhIHZhcmlhYmlsaWRhZCBleHBsaWNhZGEgc2ltcGxlbWVudGUgcG9yIHVuIHByb21lZGlvKS4gQ29tbyBhbCBpbmNvcnBvcmFyIG51ZXZhcyB2YXJpYWJsZXMgZWwgUjIgbnVuY2EgcHVlZGUgcmVkdWNpcnNlIChhdW5xdWUgbGFzIHZhcmlhYmxlcyBpbmNsdXNvIHRlbmdhbiBwb2NvIHF1ZSB2ZXIgY29uIGVsIHByb2JsZW1hKSwgZXMgcXVlIGRlYmUgdXNhcnNlIGVsIFIyIGFqdXN0YWRvIHBvciBlbCBudW1lcm8gZGUgY292YXJpYWJsZXMgZXhwbGljYXRpdmFzIGluY2x1aWRhcyBlbiBlbCBtb2RlbG8uIEVuIG51ZXN0cm8gcHJpbWVyIG1vZGVsbyBkZSByZWdyZXNpw7NuIG11bHRpcGxlIGVsIHZhbG9yIGRlIFIyIGFqdXN0YWRvIGVzIGRlIDAsNzc2IGxvIHF1ZSBub3MgZGEgdW5hIGlkZWEgZGUgcXVlIGxhIHByb3BvcmNpw7NuIGRlIHZhcmlhYmlsaWRhZCBleHBsaWNhZGEgc2UgaW5jcmVtZW50byBlbiBidWVuYSBtZWRpZGEgcmVzcGVjdG8gYWwgVFAxLiBMYSBzZWd1bmRhIHJlZ3Jlc2nDs24gbcO6bHRpcGxlIHNpbiBlbCBiYXJyaW8sIHJlZHVjZSBlbCBSMiBhanVzdGFkbyBhIDAsNjgzLiBDb21vIGVzdGEgbWVkaWRhIGVzdGEgYWp1c3RhZGEgcG9yIGxhIHZhcmlhYmxlIHF1ZSBmYWx0YSwgcG9kZW1vcyBhZmlybWFyIHF1ZSBlbCBtb2RlbG8gY29uIGxvcyBiYXJyaW9zIHRpZW5lIHVuYSBtYXlvciBwcm9wb3JjacOzbiBkZSB2YXJpYWJpbGlkYWQgZXhwbGljYWRhIGVuIGVsIHByZWNpb3MgZGUgbGFzIHZpdmllbmRhcyByZXNwZWN0byBhIGV2YWx1YXJsbyBzb2xvIGxhIHVuYSBtZWRpYS4gDQoNCg0KIyMgMS4yKSBFdmFsdWFjacOzbiBkZWwgbW9kZWxvIGVuIGNpZXJ0b3MgcHVudG9zDQoNCmBgYHtyfQ0KI1NpbXBsaWZpY2FyIGVzdGUgY8OzZGlnbw0KdmVjdG9yMT1jKCdEcHRvX0FiYXN0bycsJ0FiYXN0bycsNCwyLDEyMCwxMjAsMCwnRGVwYXJ0YW1lbnRvJykNCnZlY3RvcjI9YygnUEhfQmFsdmFuZXJhJywnQmFsdmFuZXJhJywzLDIsODAsMTAwLDAsJ1BIJykNCmRmX3Rlc3Q9cmJpbmQoZGZbMSxdLHZlY3RvcjEsdmVjdG9yMikNCmRmX3Rlc3Qkcm9vbXM9YXMubnVtZXJpYyhkZl90ZXN0JHJvb21zKQ0KZGZfdGVzdCRiYXRocm9vbXM9YXMubnVtZXJpYyhkZl90ZXN0JGJhdGhyb29tcykNCmRmX3Rlc3Qkc3VyZmFjZV90b3RhbD1hcy5udW1lcmljKGRmX3Rlc3Qkc3VyZmFjZV90b3RhbCkNCmRmX3Rlc3Qkc3VyZmFjZV9jb3ZlcmVkPWFzLm51bWVyaWMoZGZfdGVzdCRzdXJmYWNlX2NvdmVyZWQpDQpkZl90ZXN0JHByaWNlPWFzLm51bWVyaWMoZGZfdGVzdCRwcmljZSkNCmRmX3Rlc3Q9ZGZfdGVzdFsyOjMsXQ0KcHJlZGljY2lvbj1wcmVkaWN0KG1vZGVsbzAsZGZfdGVzdCkNCnByaW50KGRmX3Rlc3QpDQpwcmVkaWNjaW9uDQpgYGANCkNyZW8gZG9zIHZlY3RvcmVzIGVtdWxhbmRvIGxhcyBjYXJhY3RlcsOtc3RpY2FzIGRlIGxhIGNhc2EgZGUgYWJhc3RvICgxKSB5IGxhIGNhc2EgZGUgQmFsdmFuZXJhICgyKSB5IHByZWRpZ28gc3UgdmFsb3IgZGUgYWN1ZXJkbyBhbCBtb2RlbG8gY3JlYWRvIGFudGVyaW9ybWVudGUuIEluZGVwZW5kaWVudGVtZW50ZSBkZSBzaSBlbiBlbCBtZXJjYWRvIHVuYSBvcGNpw7NuIHNlIHZlbmRlIChtw6FzIHJhcGlkbykgbyBubyB5IHRlbmllbmRvIMO6bmljYW1lbnRlIGVuIGN1ZW50YSBlbCB2YWxvciBkZSBsYSBwcm9waWVkYWQsIGRlIGFjdWVyZG8gY29uIGVsIG1vZGVsbywgZWwgcHJlY2lvIGRlbCBkcHRvIGVuIGVsIEFiYXN0byByb25kYXLDrWEgbG9zIDMyMCBtaWwgZMOzbGFyZXMgbWllbnRyYXMgcXVlIFBIIGVuIEJhbHZhbmVyYSBlc3RhcsOtYSBjZXJjYSBkZSBsb3MgMTg4IG1pbCBkw7NsYXJlcy4gQ29uIGxvIGN1YWwgY29udmVuZHLDrWEgZWwgcHJpbWVybyBwYXJhIHZlbmRlci4NCg0KIyAyKSBDcmVhY2nDs24gZGUgdmFyaWFibGVzDQoNClBhcmEgcG9kZXIgY2xhc2lmaWNhciBsb3MgYmFycmlvIGVuICJhbHRvIiAibWVkaW8iIHkgImJham8iLCBjYWxjdWxvIGVsIHByZWNpbyBwb3IgbWV0cm8gY3VhZHJhZG8gdG90YWwgcHJvbWVkaW8gcG9yIGJhcnJpby4NCmBgYHtyfQ0KZGY9ZGYgJT4lIA0KICBtdXRhdGUocHJlY2lvX01fY3VhZHJhZG89cHJpY2Uvc3VyZmFjZV90b3RhbCkNCnByZWNpb1hiYXJyaW89ZGYgJT4lIA0KICAjIHNlbGVjdChsMyxwcmVjaW9fTV9jdWFkcmFkbykgJT4lDQogIGdyb3VwX2J5KGwzKSAlPiUNCiAgc3VtbWFyaXNlKHByZWNpb19NX2N1YWRyYWRvX3Byb21lZGlvPW1lYW4ocHJlY2lvX01fY3VhZHJhZG8pKQ0KcHJpbnQoc3VtbWFyeShwcmVjaW9YYmFycmlvKSkgIA0KDQpgYGANCkFob3JhLCBzaW1wbGVtZW50ZSBvcmRlbmFtb3MgZGUgbWVub3IgYSBtYXlvciBsb3MgcHJlY2lvcyBwb3IgbWV0cm8gY3VhZHJhZG9zIHByb21lZGlvIGRlIGNhZGEgYmFycmlvLg0KYGBge3J9DQpnZ3Bsb3QocHJlY2lvWGJhcnJpbyxtYXBwaW5nPWFlcyh4PWZjdF9yZW9yZGVyKGwzLHByZWNpb19NX2N1YWRyYWRvX3Byb21lZGlvLC5kZXNjID0gRikseT1wcmVjaW9fTV9jdWFkcmFkb19wcm9tZWRpbykpKw0KZ2VvbV9wb2ludCgpKw0KdGhlbWVfYncoKSsNCnRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApLHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSsNCmdlb21faGxpbmUoeWludGVyY2VwdCA9IDIwNjIsY29sPSJibHVlIikrDQpnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAyNTc5LGNvbD0icmVkIikrDQpsYWJzKHRpdGxlID0gIlByZWNpbyBwcm9tZWRpbyBwb3IgTTIgZGUgdml2aWVuZGFzIHBvciBiYXJyaW8iLHN1YnRpdGxlID0gIjFlciBjdWFydGlsIChhenVsKSA9IDIuMDYyVVNEIC8vIDNlciBjdWFydGlsIChyb2pvKSA9IDIuNTc5VVNEIikrDQp4bGFiKCJCYXJyaW8iKSsNCnlsYWIoIlByZWNpbyBwcm9tLiBwb3IgbWV0cm8gY3VhZHJhZG8iKQ0KYGBgDQpDb21vIHNlIHB1ZWRlIG9ic2VydmFyIGVsIDUwJSBkZSBsb3MgYmFycmlvcyBzZSBlbmN1ZW50cmFuIGVuIHVuIHJhbmdvIG1lbm9yIGRlIHByZWNpbyBwcm9tZWRpbyBwb3IgbWV0cm8gY3VhZHJhZG8gYWwgMjUlIGRlIGxvcyBiYXJyaW9zIGNvbiBwcmVjaW9zIG1hcyBhbHRvcyB5IG1hcyBiYWpvcy4gUG9yIGVzdGUgbW90aXZvIHNlIHByb3BvbmUgaW50ZXJwcmV0YXIgY29tbyAiYWx0byIgYWwgMjUlIGRlIGxvcyBiYXJyaW9zIGNvbiBsb3MgbWF5b3JlcyBwcmVjaW9zIHBvciBtZXRybyBjdWFkcmFkbyBwcm9tZWRpbyB5IGNvbW8gImJham8iIGFsIDI1JSBkZSBsb3MgZGUgbWVub3IgcHJlY2lvLiBFcyBkZWNpciwgcXVlIGNvbW8gdXRpbGl6YXJlbW9zIGVzdGEgZXRpcXVldGEgcGFyYSBjYXB0YXIgdmFyaWFiaWxpZGFkIGRlbCBwcmVjaW8gZGUgbGFzIHZpdmllbmRhcyBlbiB1biBmdXR1cm8gbW9kZWxvLCBlbnRpZW5kbyBxdWUgdG9tYXIgcHJvcG9yY2lvbmVzIGRlIGJhcnJpb3MgaWd1YWxlcyByZWR1Y2lyw61hIG11Y2hvIGVsIGVmZWN0byBkZSBsYSBldGlxdWV0YSAibWVkaWEiIGVuIHN1IGNhcGFjaWRhZCBkZSBwcmVkZWNpciB1biBwcmVjaW8gZGUgdW5hIHZpdmllbmRhLg0KTm8gZXN0w6EgZGUgbcOhcyBhY2xhcmFyIHF1ZSBlc3RhIGRpdmlzacOzbiBubyBwdWVkZSBtYW50ZW5lciBkaWNoYXMgcHJvcG9yY2lvbmVzIGEgbGEgaG9yYSBkZSBhbmFsaXphciBhIG5pdmVsIGRlIHZpdmllbmRhcyB5YSBxdWUgY2FkYSBiYXJyaW8gdGllbmUgY2FudGlkYWRlcyBkZSBjYXNhcyBlbiB2ZW50YSBkaXN0aW50YXMuICAgDQoNCkluY29ycG9yYW1vcyB1bmEgY29sdW1uYSBjb24gImFsdG8iICJtZWRpbyIgeSAiYmFqbyIgZW4gZnVuY2nDs24gZGUgc2kgc3VwZXJhbiBlbCBDdWFydGlsIDMgbyBlc3RhbiBwb3IgZGViYWpvIGRlbCBjdWFydGlsIDEuDQpgYGB7cn0NCmRmMj1kZiAlPiUNCiAgZ3JvdXBfYnkobDM9YXMuZmFjdG9yKGwzKSkgJT4lIA0KICBtdXRhdGUobWVkaWFkZWxiYXJyaW89bWVhbihwcmljZS9zdXJmYWNlX3RvdGFsKSkgJT4lDQogIHVuZ3JvdXAoKSAlPiUgDQogIG11dGF0ZShRMT0yMDYyLFEzPTI1NzkpICU+JQ0KICB0cmFuc211dGUobDMsYmFycmlvcz1hc19mYWN0b3IoY2FzZV93aGVuKA0KICAgIG1lZGlhZGVsYmFycmlvPFExfiJCYWpvIiwNCiAgICBtZWRpYWRlbGJhcnJpbz5RM34iQWx0byIsDQogICAgVFJVRX4iTWVkaW8iKSkpDQpkZjM9Y2JpbmQoZGYsZGYyKQ0KYGBgDQoNCiMjIDIuMikgTW9kZWxvIGNvbiB2YXJpYWJsZXMgY29uc3RydWlkYXMNClByb2NlZGVtb3MgZW50b25jZXMgYSByZWFsaXphciBlbCBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwgbXVsdGlwbGUgY29uIG51ZXN0cmEgbnVldmEgdmFyaWFibGUgImJhcnJpb3MiLiANCmBgYHtyfQ0KbW9kZWxvMj1sbShwcmljZX5yb29tcytiYXRocm9vbXMrc3VyZmFjZV90b3RhbCtzdXJmYWNlX2NvdmVyZWQrcHJvcGVydHlfdHlwZStiYXJyaW9zLGRhdGE9ZGYzKQ0Kc3VtbWFyeShtb2RlbG8yKQ0KDQpgYGANCg0KTG8gcXVlIHNlIG9ic2VydmEgZGUgbnVlc3RybyB0ZXJjZXIgbW9kZWxvICgyKSAgZXMgcXVlIHJlc3VsdGEgY29uc2lkZXJhYmxlbWVudGUgbcOhcyBwYXJlY2lkbyBhbCBtb2RlbG8gY29uIGxvcyBiYXJyaW9zIChtb2RlbG8wKSBxdWUgYWwgbW9kZWxvIGVsaW1pbmFuZG8gZGljaGEgdmFyaWFibGUgKG1vZGVsbzEpLiBFcyBkZWNpciwgZWwgY29lZmljaWVudGUgZGUgImJhw7FvIiBlcyAzNiBtaWwgVVNEIGN1YW5kbyBlbiBlbCBtb2RlbG8wIGVyYSBkZSAzNCBtaWwsIGVsIGNvZWZpY2llbnRlIGRlIHN1cGVyZmljaWUgdG90YWwgZXJhIGRlIGFwcm94aW1hZGFtZW50ZSA5MDAgVVNEIHkgYWhvcmEgZXMgZGUgODc3IFVTRCwgbWllbnRyYXMgcXVlIHN1cGVyZmljaWUgY3ViaWVydGEgZXJhIGRlIDE0NTdVU0QgeSBhaG9yYSBlcyBkZSAxNjQxVVNEIChtYXMgYWx0byBwZXJvIG1lbm9zIGEgbG9zIGNhc2kgMTgwMFVTRCBkZWwgbW9kZWxvMSBzaW4gYmFycmlvcykuIEVuIGVsIG1pc21vIHNlbnRpZG8sIGVsIGZhY3RvciAiZGVwYXJ0YW1lbnRvIiBxdWUgc3VtYWJhIDkzIG1pbCBVU0QgcG9yIHNvYnJlIGVsIGNhc28gYmFzYWwgZGUgQ2FzYSBlbiBlbCBtb2RlbG8wIHkgMTM1IG1pbCBVU0QgZW4gZWwgbW9kZWxvMSAoc2luIGJhcnJpb3MpIGFob3JhIHN1bWEgODcgbWlsIChzaW1pbGFyIGFsIG1lam9yIG1vZGVsbzApIGUgaWd1YWwgY29uIGVsIGZhY3RvciAiUEgiIDQ3IG1pbCBVU0QgZW4gZWwgbW9kZWxvMCB5IDY5IG1pbCBlbiBlbCBtb2RlbG8xIHkgYWhvcmEgNTQgbWlsIFVTRC4gDQpMb3MgYmFycmlvcyBkZSAiYWx0byB2YWxvciBwb3IgbWV0cm8gY3VhZHJhZG8gcHJvbWVkaW8iIGluY29ycG9yYW4gZW4gbnVlc3RybyBtb2RlbG8yIGRlIHByZWRpY2Npw7NuIGRlIHByZWNpbyBkZSB2aXZpZW5kYSwgc2kgbWFudGVuZW1vcyB0b2RhcyBsYXMgb3RyYXMgdmFyaWFibGVzIGNvbnN0YW50ZSwgY2FzaSA4NyBtaWwgVVNEIGFsIHZhbG9yIHF1ZSB0ZW5kcsOtYSB1bmEgdml2aWVuZGEgZW4gdW4gYmFycmlvIGNhcmF0dWxhZG8gZGUgImJham8iLiBMb3MgYmFycmlvcyAibWVkaW9zIiBhZGljaW9uYXLDrWFuIDI1IG1pbCBVU0QgZW4gZWwgbW9kZWxvIHJlc3BlY3RvIGEgbG9zIGJham9zLg0KDQojIyAyLjMpIFIgYWp1c3RhZG8gZGUgbG9zIG1vZGVsb3MNCg0KRW4gZWwgbW9kZWxvMCAoY29uIGwzKSwgZWwgUiBhanVzdGFkbyBlcyBkZSAwLDc3NiBtaWVudHJhcyBxdWUgZW4gZWwgbW9kZWxvIGNvbiBiYXJyaW8gZGljaG8gdmFsb3IgZXMgZGUgMCw3MzQuIEVsIHByaW1lciBtb2RlbG8gdGllbmUgdW5hIGRpZmVyZW5jaWEgbGlnZXJhbWVudGUgc3VwZXJpb3IgZW4gbGEgcHJvcG9yY2nDs24gZGUgbGEgdmFyaWFiaWxpZGFkIGV4cGxpY2FkYSBwb3IgZWwgbW9kZWxvIGxpbmVhbCBzb2JyZSBsYSB0b3RhbC4NCkxhIHZlbnRhamEgcXVlIG9ic2Vydm8gZGVsIG1vZGVsbyBjb24gYmFycmlvIGVzIHF1ZSBjb24gdW5hIGltcG9ydGFudGUgcmVkdWNjacOzbiB5IHNpbXBsaWZpY2FjacOzbiBkZWwgbW9kZWxvIChncmFjaWFzIGEgbGEgcmVkdWNjacOzbiBkZSBtw6FzIGRlIDUwIHZhcmlhYmxlcyBkdW1teXMpIHN1IFIgYWp1c3RhZG8gY2FzaSBubyBzdWZyacOzIHVuYSBjYcOtZGEgY29uc2lkZXJhYmxlLiBDb25zaWRlcm8gcXVlIGVsIHByaW1lciBtb2RlbG8gdGllbmUgdW5hIGRpZmVyZW5jaWFjacOzbiBiYXJyaW8gYSBiYXJyaW8gcXVlIHBlcm1pdGUsIGFkaWNpb25hbG1lbnRlIGEgdG9kbyBlbCBhbsOhbGlzaXMgcXVlIHJlYWxpemFtb3MsIGhhY2VyIG90cm8gdGlwbyBkZSBldmFsdWFjacOzbiBjb21vIGVsIGRlIHJlZ2lzdHJhciBzaSBoYXkgbW92aW1pZW50b3MgcmVsYXRpdm9zIGVudHJlIGxvcyBiYXJyaW9zLiBFc3RvIGVzLCBzaSB1biBiYXJyaW8gZXN0w6EgZW5jYXJlY2llbmRvc2UgbyBhYmFyYXTDoW5kb3NlIGVuIHJlbGFjacOzbiBhIG90cm9zLg0KDQojIyAyLjQpIEFuw6FsaXNpcyBkZSBsYXMgc3VwZXJmaWNpZXMgZGUgdml2aWVuZGFzDQpJbmNvcnBvcm8gdW5hIHZhcmlhYmxlIGRlICJzdXBlcmZpY2llIGRlc2N1YmllcnRhIiBjb21vIGxhIHJlc3RhIGRlIGxvcyBtZXRyb3MgdG90YWxlcyBtZW5vcyBsb3MgbWV0cm9zIGN1YmllcnRvcy4NCmBgYHtyfQ0KZGYzPWRmM1tjKDEsMyw0LDUsNiw3LDgsOSwxMCwxMSldDQpkZjM9ZGYzICU+JSANCiAgbXV0YXRlKHN1cmZhY2VfcGF0aW89c3VyZmFjZV90b3RhbC1zdXJmYWNlX2NvdmVyZWQpDQpgYGANCg0KU2kgYWxndW4gcmVnaXN0cm8gY29udHV2aWVyYSB2YWxvcmVzIGRlIHN1cGVyZmljaWUgY3ViaWVydGEgbWF5b3IgcXVlIGxhIHRvdGFsLCBlc28gbm9zIGVzdGFyw61hIGluZGljYW5kbyB1biBlcnJvciBlbiBsYSBjYXJnYSBkZSBsYSBpbmZvcm1hY2nDs24uIEVzZSBlcnJvciBwb2Ryw61hIHByb3ZlbmlyIGRlIHVuYSBjYXJnYSBlcnJvbmVhIGVuIGxhIHN1cGVyZmljaWUgdG90YWwgbyBlbiBsYSBjdWJpZXJ0YSBvIGVuIGFtYmFzLiBTaSBubyB0dXZpZXJhbW9zIGZvcm1hIGRlIGF2ZXJpZ3VhcmxvIHkgc2kgZnVlcmFuIHBvY29zIGNhc29zLCBzZXLDrWEgcmVjb21lbmRhYmxlIGVsaW1pbmFyIGxvcyByZWdpc3Ryb3MgcG9yIHNlciBwb2NvIGNvbmZpYWJsZXMuDQpgYGB7cn0NCmRmMyAlPiUgDQogIGZpbHRlcihzdXJmYWNlX3BhdGlvPDApDQpgYGANCkNvbW8gdmVtb3MsIG5vIGV4aXN0ZSBuaW5nw7puIHJlZ2lzdHJvIGNvbiBzdXBlcmZpY2llIGRlc2N1YmllcnRhIG1lbm9yIHF1ZSBjZXJvLiBUb2RvcyBsb3MgcmVnaXN0cm9zIHRpZW5lbiBjb2hlcmVuY2lhLg0KDQoNCk1PREVMTyBMSU5FQUwgY29uIGxhIG51ZXZhIHZhcmlhYmxlICJzdXJmYWNlX3BhdGlvIjoNCg0KYGBge3J9DQptb2RlbG8zPWxtKHByaWNlfnJvb21zK2JhdGhyb29tcytzdXJmYWNlX2NvdmVyZWQrcHJvcGVydHlfdHlwZStiYXJyaW9zK3N1cmZhY2VfcGF0aW8sZGF0YT1kZjMpDQpzdW1tYXJ5KG1vZGVsbzMpDQoNCmBgYA0KRW4gZXN0ZSBlamVyY2ljaW8sIGVuIGVsIHF1ZSBzZSBxdWl0w7MgbGEgc3VwZXJmaWNpZSB0b3RhbCB5IHNlIGFncmVnw7Mgc3VyZmFjZV9wYXRpbywgcG9kZW1vcyB2b2x2ZXIgYSByZWFmaXJtYXIgbGFzIGNvbmNsdXNpb25lcyBvYnRlbmlkYXMgZW4gZWwgcHJpbWVyIG1vZGVsbzAuIEVzdG8gZXMsIHF1ZSBuZWNlc2FyaWFtZW50ZSBhc8OtIGNvbW8gZWwgbWV0cm8gY3VhZHJhZG8gY3ViaWVydG8gZXJhIGxhIHN1bWEgZGVsIGN1YmllcnRvIHkgdG90YWwgKHlhIHF1ZSBubyBwdWVkZW4gc2VwYXJhcnNlKSwgZWwgInRvdGFsIiB0ZW7DrWEgcXVlIHJlcHJlc2VudGFyIGFsIG1ldHJvIGN1YWRyYWRvIGRlc2N1YmllcnRvLiBFc3RvIHNlIGNvbmZpcm1hIHlhIHF1ZSBlbCBtb2RlbG8gMyB5IDIgc29uIGV4YWN0YW1lbnRlIGlndWFsZXMuDQoNCiMgMykgRXZhbHVhY2nDs24gZGUgbW9kZWxvIHkgcmVzaWR1b3MNCg0KQ2FsY3VsYW1vcyBsb3MgcmVzaWR1b3MNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpwbG90KG1vZGVsbzMpDQpgYGANCg0KDQpQYXJhIGNoZXF1ZWFyIHF1ZSBsb3Mgc3VwdWVzdG9zIGRlbCBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwgbXVsdGlwbGUgc2UgY3VtcGxlbiwgc2UgcmVhbGl6YXJvbiBsb3MgcHJlY2VkZW50ZXMgZ3LDoWZpY29zLiBFbiBlbCBwcmltZXIgZ3LDoWZpY28gKHJlZGlzdWFsIHZzIEZpdHRlZCkgbG8gcXVlIHNlIG9ic2VydmEgZXMgcXVlIGxvcyByZXNpZHVvcyBjb250cmEgbG9zIHZhbG9yZXMgcHJlZGljaG9zIGVzdGFuIGNlbnRyYWRvcyBlbiB0b3JubyBhbCBjZXJvLCBjb3NhIHF1ZSBlbiBncmFuIG1lZGlkYSBzZSB2ZXJpZmljYSBzaSBzZSBvYnNlcnZhIGxhIGxpbmVhIHJvamEsIHNhbHZvIHBhcmEgdmFsb3JlcyBwcmVkaWNob3MgcGVxdWXDsW9zLkVsbG8gcmVmbGVqYSBxdWUgbm8gc2Ugb2JzZXJ2YSB1bmEgY29ycmVsYWNpw7NuIGltcG9ydGFudGUgZW50cmUgbG9zIGVycm9yZXMsIGVzIGRlY2lyIHF1ZSBubyBzZSBub3RhIHVuYSB0ZW5kZW5jaWEgbyBjb21wb3J0YW1pZW50byBjbGFyby4gIA0KRW4gY3VhbmRvIGEgbGEgaG9tb2dlbmVpZGFkIGRlIGxhIHZhcmlhbnphIGRlIGxvcyBlcnJvcmVzIHNlIGRlc3RhY2EgcXVlIG5vIHNlIG9ic2VydmEgdW5hIG51YmUgZGUgcHVudG9zIHVuaWZvcm1lLCBzaW5vIHF1ZSBzZSBpbmNyZW1lbnRhIGVuIHZhbG9yZXMgcHJlZGljaG9zIG1lZGlvcyB5IHZ1ZWx2ZSBhIHJlZHVjaXJzZSBlbiB2YWxvcmVzIGdyYW5kZXMuIEVsbG8gcmVmbGVqYXLDrWEgdW4gcHJvYmxlbWEgZGUgaGV0ZXJvY2VkYXN0aWNpZGFkIGRlIGxvcyByZXNpZHVvcyB2aW9sYW5kbyB1bm8gZGUgbG9zIHN1cHVlc3RvcyBuZWNlc2FyaW9zIHBhcmEgcG9kZXIgY29uZmlhciBlbiBudWVzdHJvIG1vZGVsbyBkZSByZWdyZXNpw7NuIG11bHRpcGxlLiAgDQogRWwgc2VndW5kbyBncsOhZmljbyAobm9ybWFsIFEtUSkgZGV0YWxsYSBlbiBxdcOpIG1lZGlkYSBsYSBkaXN0cmlidWNpw7NuIGRlIGxvcyBlcnJvcmVzIHNlIGFqdXN0YW4gYSB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwgKGdyYWZpY2FkYSBjb21vIHVuYSByZWN0YSBkZSBwZW5kaWVudGUgcG9zaXRpdmEpLiBFbCBwcm9ibGVtYSBxdWUgdmVtb3MgZXMgcXVlIGxvcyBlcnJvcmVzIGVuIHN1cyBleHRyZW1vcyBubyBzZSBhanVzdGFuIGEgdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsLCBsbyBxdWUgZ2VuZXJhIG90cm8gcHJvYmxlbWEgcGFyYSBsb3Mgc3VwdWVzdG9zIGRlbCBtb2RlbG8zLg0KDQoNCiMjIDMuMikgRXZhbHVhY2nDs24gZGUgbW9kZWxvIGNvbiB1bmEgdHJhbnNmb3JtYWNpw7NuIGxvZ2FyaXRtaWNhDQoNCkxhIHRyYW5zZm9ybWFjacOzbiBsb2dhcsOtdG1pY2EgZXMgdW5hIGZvcm1hIGRlIHRyYW5zZm9ybWFyIHJlbGFjaW9uZXMgZXhwb25lbmNpYWxlcyBlbiByZWxhY2lvbmVzIGxpbmVhbGVzIHNpbiBhbHRlcmFyIGVsIGNvbXBvcnRhbWllbnRvIGludHJpbnNlY28gZGUgbGFzIHZhcmlhYmxlcy4gUG9yIGVzbyBhcGxpY2Ftb3MgZXN0YXMgdHJhbnNmb3JtYWNpb25lcyBhIGxhcyB2YXJpYWJsZXMgbnVtw6lyaWNhcy4NCmBgYHtyfQ0KbW9kZWxvND1sbShsb2cocHJpY2UpfmxvZyhyb29tcykrbG9nKGJhdGhyb29tcykrbG9nKHN1cmZhY2VfY292ZXJlZCkrcHJvcGVydHlfdHlwZStiYXJyaW9zK3N1cmZhY2VfcGF0aW8sZGF0YT1kZjMpDQpzdW1tYXJ5KG1vZGVsbzQpDQpgYGANCkxvIHByaW1lcm8gYSBkZXN0YWNhciBkZWwgbnVldm8gbW9kZWxvLCBlcyBxdWUgZWwgUjIgYWp1c3RhZG8gc2UgZWxldmEgZGUgMC43MyBkZWwgbW9kZWxvMyBhIDAuODA4IGVuIGVsIG1vZGVsbzQgbG8gcXVlIG5vcyBpbmRpY2EgcXVlIGVzIGVsIG1vZGVsbyBxdWUgbWF5b3IgYXNvY2lhY2nDs24gbGluZWFsIHByZXNlbnRhIGVudHJlIGxhcyBYIHkgbGFzIFkuIA0KUGFyYSBpbnRlcnByZXRhciBudWVzdHJvIG51ZXZvIG1vZGVsbyBkZWJlbW9zIHNlciBjb25jaWVudGVzIHF1ZSBhcGxpY2Ftb3MgbGEgdHJhbnNmb3JtYWNpw7NuIHRhbnRvIGEgbnVlc3RyYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSBwcmVjaW8gY29tbyBhIGxhcyBpbmRlcGVuZGllbnRlcywgcG9yIGxvIHF1ZSBudWVzdHJvIG1vZGVsbyBzZXLDoSBsb2ctbG9nIChXb29sZHJpZGdlLCBKLk0gKDIwMDYpIHBnLiA0NikuIEVuIGVzdGUgc2VudGlkbywgZWwgY29lZmljaWVudGUgZGUgbG9nKHJvb20pIGVzIGRlIC0wLDA0NzMgcG9yIGxvIHF1ZSBwb2RlbW9zIGRlY2lyIHF1ZSB1bmEgdmFyaWFjacOzbiBkZSB1biAxJSAocG9zaXRpdm8pIGVuIGxhIGNhbnRpZGFkIGRlIGFtYmllbnRlcyBhZmVjdGFyw6EgKG5lZ2F0aXZhbWVudGUpIGVuIC0wLDA0NzMlIHBvciBjaWVudG8gZW4gZWwgcHJlY2lvIHByZWRpY2hvIHBvciBlbCBtb2RlbG8sIGFudGUgdG9kYXMgbGFzIG90cmFzIHZhcmlhYmxlcyBjb25zdGFudGVzLiBQb3Igc3UgcGFydGVzIHZhcmlhY2lvbmVzIGRlIDElIGVuIGJhw7Fvcywgc3VwZXJmaWNpZSBjdWJpZXJ0YSB5IGRlc2N1YmllcnRhIGdlbmVyYXJhbiBlbiBudWVzdHJvIG1vZGVsbzQgdmFyaWFjaW9uZXMgZW4gZWwgcHJlY2lvIGRlIDAsMTgxOSUsIDAsODIwMSUgeSAwLDAwNCUsIHJlc3BlY3RpdmFtZW50ZS4gUGFyYSBlbCBjYXNvIGRlIGxhcyB2YXJpYWJsZXMgY2F0ZWfDs3JpY2FzLCBjb21vIG5vIHNlIGFwbGljw7MgdHJhbnNmb3JtYWNpw7NuIGVuIGxhIHZhcmlhYmxlIGluZGVwZW5kaWVudGUsIGVsIG1vZGVsbyBlcyBMb2ctbml2ZWwgbG8gcXVlIG5vcyByZXF1aWVyZSBtdWx0aXBsaWNhciBwb3IgMTAwIGxvcyBjb2VmaWNpZW50ZXMgcGFyYSB2ZXIgbG9zIGNhbWJpb3MgcG9yY2VudHVhbGVzIGRlbCBwcmVjaW8uIEFzw60sIHNpIGxhIHZpdmllbmRhIGVzIHVuIGRlcGFydGFtZW50byBzZSBpbmNyZW1lbnRhcsOhIGNhc2kgdW4gMjQlIGVuIGVsIHByZWNpbyBwcmVkaWNobyBwb3Igc29icmUgbGFzICJDYXNhcyIgbyBiaWVuIHVuIDclIHNpIGZ1ZXNlIFBILiBCYXJyaW9zIHJvdHVsYWRvcyBjb21vICJhbHRvIiBhZGljaW9uYW4gdW4gNDQlIGFsIHByZWNpbyBwcmVkaWNobyBzb2JyZSBlbCBuaXZlbCBkZSAiQmFqbyIgeSAxNiUgc2kgZXMgIm1lZGlvIi4NCg0KDQpTaSByZXBldGltb3MgZWwgYW7DoWxpc2lzIGVuIG1hdGVyaWEgZGUgcmVzaWR1b3MgY29uIGVsIG51ZXZvIG1vZGVsbyBvYnRlbmVtb3MgbG9zIHNpZ3VpZW50ZXMgcmVzdWx0YWRvcy4NCmBgYHtyfQ0KcGxvdChtb2RlbG80KQ0KYGBgDQoNClBvZGVtb3Mgb2JzZXJ2YXIgcXVlIGVsIG1vZGVsbyBjb24gbGFzIHRyYW5zZm9ybWFjaW9uZXMgbG9nYXLDrXRtaWNhcyBoYSBtZWpvcmFkbyBjb25zaWRlcmFibGVtZW50ZSBlbCBwcm9ibGVtYSBkZSBoZXRlcm9jZWRhc3RpY2lkYWQgcHJlc2VudGUgZW4gZWwgbW9kZWxvMy4gRXN0byBzZSBvYnNlcnZhIGVuIGVsIHByaW1lciBncsOhZmljbyBlbiB1bmEgbWVqb3LDrWEgZW4gbGFzIGhvbW9nZW5laWRhZCAgcmVsYXRpdmEgZGUgbG9zIGVycm9yZXMgcGFyYSBsb3MgdmFsb3JlcyBwcmVkaWNob3MgKGZpdHRlZCB2YWx1ZXMpIHBlcXVlw7FvcyB5IGdyYW5kZXMuIEEgc3UgdmV6IHRhbWJpw6luIHNlIHZlIGVuIGVsIFFRIHBsb3QgcXVlIGxvcyBkYXRvcyBzZSBhanVzdGFuIG11Y2hvIG1lam9yIGEgbGEgbGluZWEgZGUgbm9ybWFsaWRhZC4NCg0KDQoNCiMgNCkgQW7DoWxpc2lzIHkgbW9kZWxvcyBwb3IgdGlwbyBkZSBwcm9waWVkYWQgDQoNCkVuIHByaW1lciBsdWdhciBhZ3J1cGFtb3MgbG9zIGRhdG9zIHBvciB0aXBvIGRlIHByb3BpZWRhZA0KYGBge3J9DQptb2RlbG9zX3Bvcl90aXBvX3Byb3BpZWRhZCA8LSBkZjMgJT4lIA0KICBncm91cF9ieShwcm9wZXJ0eV90eXBlKSAlPiUgDQogIG5lc3QoKQ0KYGBgDQoNCkFob3JhIGNyZWFtb3MgdW5hIGZ1bmNpw7NuIHBhcmEgaXRlcmFyIGVsIG1vZGVsbzQgZW4gbG9zIGRpc3RpbnRvcyB0aXBvcyBkZSBwcm9waWVkYWQNCmBgYHtyfQ0KZnVuY2lvbl9tb2RlbG80IDwtIGZ1bmN0aW9uKGRmKXsNCiAgbG0obG9nKHByaWNlKX5sb2cocm9vbXMpK2xvZyhiYXRocm9vbXMpK2xvZyhzdXJmYWNlX2NvdmVyZWQpK2JhcnJpb3Mrc3VyZmFjZV9wYXRpbyxkYXRhPWRmKQ0KfQ0KYGBgDQoNCkNvcnJlbW9zIGxhIGZ1bmNpw7NuIHBhcmEgY2FkYSB1bmEgZGUgbG9zIHRpcG9zIGRlIHByb3BpZWRhZGVzDQpgYGB7cn0NCm1vZGVsb3NfcG9yX3RpcG9fcHJvcGllZGFkIDwtIG1vZGVsb3NfcG9yX3RpcG9fcHJvcGllZGFkICU+JSANCiAgbXV0YXRlKG1vZGVsPW1hcChtb2RlbG9zX3Bvcl90aXBvX3Byb3BpZWRhZCRkYXRhLGZ1bmNpb25fbW9kZWxvNCkpDQpgYGANCg0Kb2JzZXJ2YW1vcyBsb3MgcmVzdWx0YWRvczoNCmBgYHtyfQ0KbW9kZWxvc19wb3JfdGlwb19wcm9waWVkYWQgJT4lIA0KICBtdXRhdGUoZ2xuYz1tYXAobW9kZWxvc19wb3JfdGlwb19wcm9waWVkYWQkbW9kZWwsZ2xhbmNlKSkgJT4lIA0KICB1bm5lc3QoZ2xuYywuZHJvcD1UUlVFKQ0KYGBgDQpSZXNwZWN0byBhIGxvcyB0cmVzIG1vZGVsb3MsIGVuIHByaW1lciBsdWdhciBzZSBwdWVkZSBkZXNjYXJ0YXIgcXVlIHRvZG9zIGxvcyBjb2VmaWNpZW50ZXMgZGUgbGFzIHZhcmlhYmxlcyBzZWFuIG51bG9zIHlhIHF1ZSBlbCBwLXZhbG9yIHJlc3VsdGEgc2lnbmlmaWNhdGl2by4gQ29tbyBsb3MgdHJlcyBtb2RlbG9zIHNvbiBpZ3VhbGVzLCBlcyBkZWNpciwgcXVlIG5vIGVzIG5lY2VzYXJpbyBhanVzdGFyIHBvciBlbCBuw7ptZXJvIGRlIHZhcmlhYmxlcywgbWlyYW1vcyBlbCB2YWxvciBkZSBSMi4gRW4gZWwgY2FzbyBkZSBsb3MgImRlcGFydGFtZW50b3MiIHNlIHJlZ2lzdHJhIGxhIG1lam9yIHByb3BvcmNpw7NuIGRlIHZhcmlhYmlsaWRhZCBleHBsaWNhZGEgcG9yIGVsIG1vZGVsbywgYWxjYW56YW5kbyB1biAwLjgyLiBFc3RlIGNhc28gZXMgZWwgw7puaWNvIHF1ZSBzdXBlcmEgYWwgbW9kZWxvNC4gUGFyYSBDYXNhIHkgUEggZWwgUjIgZXMgZGUgMC42NSB5IDAuNzIuIA0KDQoNCg0KYGBge3J9DQptb2RlbG9zX3Bvcl90aXBvX3Byb3BpZWRhZCAlPiUgDQogIG11dGF0ZShjb2VmaWNpZW50ZXM9bWFwKG1vZGVsLHRpZHkpKSAlPiUgDQogIHVubmVzdChjb2VmaWNpZW50ZXMpICU+JSANCiAgYXJyYW5nZSh0ZXJtKQ0KYGBgDQpBbCByZXZpc2FyIGxvcyBjb2VmaWNpZW50ZXMgKHRvZG9zIGVsbG9zIHNpZ25pZmljYXRpdm9zKSBkZSBjYWRhIG1vZGVsbyBzZSBvYnNlcnZhIG11Y2hhIHNpbWlsaXR1ZCBlbiB0b2RvcyBsb3MgcGFyYW1ldHJvcyBjb24gbGEgc2FsdmVkYWQgcXVlIHBhcmEgZWwgdGlwbyAiZGVwYXJ0YW1lbnRvIiBzZSBvYnNlcnZhbiBhbGd1bmFzIHBhcnRpY3VsYXJpZGFkZXMuIEFzaSwgcG9yIGVqZW1wbG8sIG1pZW50cmFzIHF1ZSBhbnRlIGNhbWJpb3MgZGUgdW4gMSUgZW4gbG9nKHJvb20pLCBzZSBwcmV2ZWUgdW4gY2FtYmlvIGVuIGVsIHByZWNpbyBwcmVkaWNobyB0YW50byBwYXJhIENhc2EgY29tbyBQSCBkZSAwLDA4JSwgcGFyYSAiZGVwYXJ0YW1lbnRvIiBlcyBkZSAtMCwwNyUuIExvcyBjYW1iaW9zIGVuIGVsIHByZWNpbyBwcmVkaWNobyBwb3IgY2FtYmlvcyBlbiBsYSBzdXBlcmZpY2llIGN1YmllcnRhIGRlIENhc2EgeSBQSCBlcyBkZSAwLDU2JSB5IDAsNTglIG1pZW50cmFzIHF1ZSBwYXJhIGRlcGFydGFtZW50byBlcyBkZSAwLDg2JS4gTG8gbWlzbW8gb2N1cnJlIGNvbiBsYSBzdXBlcmZpY2llIGRlc2N1YmllcnRhLg0KDQoNCg0KDQojIFJlZmVyZW5jaWFzDQoNCi1Xb29sZHJpZGdlLCBKLk0gKDIwMDYpLiBJbnRyb2R1Y2Npw7NuIGEgbGEgZWNvbm9tZXRyw61hOiB1biBlbmZvcXVlIG1vZGVybm8uIEVkaXRvcmlhbCBQYXJhbmluZm8uDQo=