1) Preparación de datos

Cargamos librerías y datos

library(tidyverse)
library(mice)
library(dplyr)
library(tidyr)
library(ggplot2)
library(lubridate)
library(GGally)
library(corrplot)
base <- read_csv('C:/Users/Artur/Desktop/Arturo/EEA2019-master/tp1/ar_properties/ar_properties.csv')

Revisamos brevemente el dataset, su contenido y tipo de variables.

glimpse(base)
Observations: 388,891
Variables: 24
$ id              <chr> "S0we3z3V2JpHUJreqQ2t/w==", "kMxcmAS8NvrynGBVbMOEaQ==", "Ce3ojF+ZTOkB8d+LI9dpxg==",...
$ ad_type         <chr> "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Prop...
$ start_date      <date> 2019-04-14, 2019-04-14, 2019-04-14, 2019-04-14, 2019-04-14, 2019-04-14, 2019-04-14...
$ end_date        <date> 2019-06-14, 2019-04-16, 9999-12-31, 9999-12-31, 2019-07-09, 2019-08-08, 2019-07-10...
$ created_on      <date> 2019-04-14, 2019-04-14, 2019-04-14, 2019-04-14, 2019-04-14, 2019-04-14, 2019-04-14...
$ lat             <dbl> -34.94331, -34.63181, NA, -34.65471, -34.65495, -32.93547, -34.65183, -34.91213, -3...
$ lon             <dbl> -54.92966, -58.42060, NA, -58.79089, -58.78712, -60.68398, -58.65912, -54.84749, -5...
$ l1              <chr> "Uruguay", "Argentina", "Argentina", "Argentina", "Argentina", "Argentina", "Argent...
$ l2              <chr> "Maldonado", "Capital Federal", "Bs.As. G.B.A. Zona Norte", "Bs.As. G.B.A. Zona Oes...
$ l3              <chr> "Punta del Este", "Boedo", NA, "Moreno", "Moreno", "Rosario", "Ituzaingó", "José Ig...
$ l4              <chr> NA, NA, NA, "Moreno", "Moreno", NA, "Ituzaingó", NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ l5              <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,...
$ l6              <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,...
$ rooms           <dbl> 2, NA, 2, 2, 2, 4, NA, 6, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, 1, 1, ...
$ bedrooms        <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,...
$ bathrooms       <dbl> 1, NA, 1, 2, 3, 1, 3, 3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA, 1, 1, 1, 1,...
$ surface_total   <dbl> 45, NA, 200, 460, 660, NA, 70, NA, 1300, 405, 352, 373, 360, 1325, 250, 80142, 101,...
$ surface_covered <dbl> 40, NA, NA, 100, 148, 89, 122, NA, NA, NA, NA, NA, NA, 2, NA, NA, NA, NA, 54, 180, ...
$ price           <dbl> 13000, 0, NA, NA, NA, NA, NA, NA, 0, NA, 0, NA, NA, NA, NA, NA, 0, 0, 0, NA, 0, 0, ...
$ currency        <chr> "UYU", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ price_period    <chr> "Mensual", "Mensual", NA, "Mensual", "Mensual", "Mensual", "Mensual", "Mensual", "M...
$ title           <chr> "Departamento - Roosevelt", "PH - Boedo", "Ituzaingo  1100 - $ 1 - Casa Alquiler", ...
$ property_type   <chr> "Departamento", "PH", "Casa", "Casa", "Casa", "Casa", "Casa", "Casa", "Lote", "Lote...
$ operation_type  <chr> "Alquiler", "Venta", "Alquiler", "Venta", "Venta", "Venta", "Venta", "Alquiler", "V...

Procedemos a filtrar para dejar únicamente las propiedades en “Venta” de Argentina, Capital Federal, valuadas en USD, de tipo “Casa”, “PH” y “Departamento”. Las variables con las contaremos serán, “ID”, Barrio (“l3”), ambientes, cuartos, baños, superficie total, superficie cubierta, precio y tipo de propiedad.

base=base %>%
  filter(l1=="Argentina",l2=="Capital Federal",currency=="USD",property_type=="PH"|property_type=="Casa"|property_type=="Departamento",operation_type=="Venta")%>%
  select(id, l3, rooms, bedrooms, bathrooms, surface_total, surface_covered, price, property_type)

2) Análisis exploratorio I

Observamos cuantos valores únicos y faltantes tiene cada columna

for (i in 1:8){
  a=sum(is.na(base[1:61905,i]))
  b=count(unique(base[,i]))
  c=names(base[,i])
  d= round(a/61905,2)
  print(paste("La columna '",c,"' tiene ",a," faltantes(",d," porcentaje del total) y tiene ", b," valores unicos"))
}
[1] "La columna ' id ' tiene  0  faltantes( 0  porcentaje del total) y tiene  61905  valores unicos"
[1] "La columna ' l3 ' tiene  355  faltantes( 0.01  porcentaje del total) y tiene  58  valores unicos"
[1] "La columna ' rooms ' tiene  5314  faltantes( 0.09  porcentaje del total) y tiene  24  valores unicos"
[1] "La columna ' bedrooms ' tiene  25298  faltantes( 0.41  porcentaje del total) y tiene  25  valores unicos"
[1] "La columna ' bathrooms ' tiene  3196  faltantes( 0.05  porcentaje del total) y tiene  15  valores unicos"
[1] "La columna ' surface_total ' tiene  3671  faltantes( 0.06  porcentaje del total) y tiene  671  valores unicos"
[1] "La columna ' surface_covered ' tiene  2975  faltantes( 0.05  porcentaje del total) y tiene  573  valores unicos"
[1] "La columna ' price ' tiene  0  faltantes( 0  porcentaje del total) y tiene  4095  valores unicos"

En la columna de ID, vemos que no hay datos faltantes y además podemos intuir que no hay IDs repetidos ya que los valores únicos coinciden con la cantidad de filas del dataframe. en cuanto a los barrios (“l3”), hay pocos faltantes en términos relativos y la cantidad de valores únicos de 58, si bien es mayor a los 48 barrios oficiales, existen 115 barrios no oficiales, por lo que puede ser un valor posible. La variable que más faltante presenta es “cuartos” (bedroom) con 25 mil registros aprox., lo que implica una proporción considerable de nuestro data set (de 41%). Esto podría transformarse en un problema si pensaramos en eliminar los registros con algún faltante. Pero falta analizar aún la importancia de esta variable. Las 4 variables restantes no presenta ninguna un faltante mayor al 9%.

Ahora, separamos las variables numéricas para analizar la matriz de correlación omitiendo los valores faltantes.

base_numerica=base %>% 
  select(rooms, bedrooms, bathrooms, surface_total, surface_covered, price)
basecor=cor(base_numerica,use= "complete.obs", method="pearson")
corrplot(basecor,addCoef.col ="black",diag=F,type = "upper")

3) Preparación de datos

Dado que la variable “Bedrooms” y “Rooms” estan altamente correlacionadas (0.92) de forma positiva ello nos indica que una de ellas casi no aporta nueva información adicional a la otra. Considerando, como ya vimos, que “bedrooms” tenía una alta proporción de faltante y este alto nivel de correlación, la eliminaremos.

base=base%>%
  select(-bedrooms)

La siguiente matriz nos muestra que para las 8 variables tenemos datos completos en 51210 casos (con cero faltante). En rojo vemos los faltantes en una columna y sus combinaciones (a la izquierda se ven la cantidad de casos que ocurre la situación de la fila y a la derecha cuantos faltantes por fila de 8 variables). Como se observa a continuación, el caso más común es el de registros en los cuales falta únicamente la variable “rooms”, con 3300 casos.

md.pattern(base)
      id price property_type  l3 surface_covered bathrooms surface_total rooms      
51210  1     1             1   1               1         1             1     1     0
3303   1     1             1   1               1         1             1     0     1
1694   1     1             1   1               1         1             0     1     1
182    1     1             1   1               1         1             0     0     2
1373   1     1             1   1               1         0             1     1     1
728    1     1             1   1               1         0             1     0     2
71     1     1             1   1               1         0             0     1     2
26     1     1             1   1               1         0             0     0     3
1198   1     1             1   1               0         1             1     1     1
199    1     1             1   1               0         1             1     0     2
556    1     1             1   1               0         1             0     1     2
54     1     1             1   1               0         1             0     0     3
83     1     1             1   1               0         0             1     1     2
45     1     1             1   1               0         0             1     0     3
59     1     1             1   1               0         0             0     1     3
769    1     1             1   1               0         0             0     0     4
58     1     1             1   0               1         1             1     1     1
3      1     1             1   0               1         1             1     0     2
247    1     1             1   0               1         1             0     1     2
31     1     1             1   0               1         0             1     1     2
4      1     1             1   0               1         0             0     1     3
2      1     1             1   0               0         1             1     1     2
3      1     1             1   0               0         1             0     1     3
1      1     1             1   0               0         0             1     1     3
1      1     1             1   0               0         0             0     1     4
5      1     1             1   0               0         0             0     0     5
       0     0             0 355            2975      3196          3671  5314 15511

pto 3.b) Con este análisis notamos que si eliminamos los registros con faltante reduciríamos la base en un 17% del dataset pre-seleccionado lo que parece no demasiado arriesgado (nos quedamos con el 82,7%, o sea 51 mil filas de casi 62 mil). Vale aclarar que de haber considerado que este percentaje era demasiado para eliminar, dado que trabajaremos con superficies, precios y ambientes, podríamos haber dejado casos con ciertos faltantes. Por ejemplo, hay casos con solo faltantes en “bathroom”, con lo cual si no eliminàsemos estos casos podríamos sumar 1300 nuevos registros.

basecomp <- na.omit(base)

4) Análisis exploratorio II

Revisamos la variable precio para todas los tipos de propiedades juntas

summary(basecomp$price)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   6000  119000  170000  251577  270000 6000000 

Realizamos un histograma del logaritmo de los precios en USD

ggplot(data = basecomp) +
  geom_histogram(mapping = aes(x = price), fill = "pink") +
  scale_x_log10() +
  labs(x = "Precio en USD (escala log.)", y = "Frecuencia absoluta", 
                title = "Histograma de precio de viviendas",
                subtitle = "escala logarítmica") +
  theme_bw()

PH=basecomp%>%
  filter(property_type=="PH")
casa=basecomp%>%
  filter(property_type=="Casa")
depto=basecomp%>%
  filter(property_type=="Departamento")

print("Analisis de precios de PH:")
[1] "Analisis de precios de PH:"
print(summary(PH$price))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  32000  137000  190000  218747  270000 1500000 
print("Analisis de precios de Casa:")
[1] "Analisis de precios de Casa:"
print(summary(casa$price))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  20000  235000  335000  434189  490000 5000000 
print("Analisis de precios de Departamento:")
[1] "Analisis de precios de Departamento:"
print(summary(depto$price))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   6000  115000  164000  246856  260000 6000000 

Se observa que la media de precios de las casas es considerablemente mas alta (en torno a $430 mil USD) que la de PH y departamente (entre 218 mil USD y 247 mil USD, respectivamente)

Se realizan a continuación los boxplot por tipo de propiedad. Dado que el crecimiento de los precios dificulta ver la la “caja” de los boxplot, realizamos una transformación en logaritmos de la variable precio.

ggplot(basecomp,aes(y=log(price,10),color=property_type))+
  geom_boxplot(alpha=0.75)+
  labs(title = "Logaritmo de precios de propiedades en función de su superficie",x="Superficie Total",y="Logaritmo del precio en USD")+
  theme(legend.position = 'None')+
  facet_wrap(~property_type)

Realizamos un correlogramas para ver la relación y diagrama de dispersión entre las variables numéricas.

var_numericas <- basecomp %>%
  select(rooms,bathrooms,surface_total,surface_covered,price)

GGally::ggpairs(data = var_numericas,
                lower = list(continuous = GGally::wrap("points", alpha = 0.4,    size=0.2),
                             combo = GGally::wrap("dot", alpha = 0.5,            size=0.25) )) +
  ggplot2::labs(title = "Correlograma de variables", x = "", y = "") +
  ggplot2::theme_bw() +
  ggplot2::theme(
    legend.position = "bottom",
    )

Del correlograma se puede ver la relación positiva entre baños y ambientes (ambas discretas, por eso la forma separada de sus puntos). En cuanto superficies (cubierta y total) se observan algunos outlier que aplana considerablemente la distribución de los puntos en cuanto a ambientes (impidiendo ver la relación entre ambas) o concentrando los puntos en cuanto a precios.

5) Outliers

En primer lugar, del análisis precedente resaltan algunas propiedades con mas de 10 baños y pocos ambientes. Descubrimos que los siguientes 9 departamentos tienen mal cargado sus baños por su relación inviable con habitaciones y metros totales. Pese a ello, su relación entre metros cuadrados y precio no parece ameritar su eliminación por ser números razonables (teniendo en cuenta que la variable en la que nos centramos es “precio”, por la consigna del TP).

basecomp%>%
  filter(bathrooms>10)

Dado que muchas propiedades con errores de carga pueden ocultarse al estar dentro el “rango” de precios normales, crearemos una nueva variable “Precio por Metro cuadrado” para detectar mejor posibles errores y outliers.

basecomp=basecomp%>%
  mutate(precio_m2=price/surface_total)

ggplot(data=basecomp,aes(y=precio_m2,color=property_type))+
  geom_boxplot(alpha=0.75)+
  labs(title = "Precio por metro cuadrados de distintas propiedades",y="Precio en USD por metro cuadrado")+
  theme(legend.position = 'None')+
  facet_wrap(~property_type)

Los problemas que notamos al filtrar las propiedades con valor por metro cuadrado por encima de 16 mil dólares son varios: uno de ellos esta dado por superficies totales menores a la superficie cubierta. Otro parecerían ser precios extremos donde los valores podrían tener un dígito de más. Por ello:

1- Primero limpiamos aquellas propiedades con superficie cubierta mayor a la total en 10 metros o más (163 registros). Con esto, además de eliminar propiedades con errores groseros, estaremos eliminando algunos precios por metro cuadrado “posible” (en áreas como puerto madero) pero que en realidad son fruto de cargas erroneas.

2- Limpiamos aquellas propiedades con precios por metro cuadrado superior a los 16.000 mil dólares (se eligió este valor ya que hasta este monto se observaban registros “razonables” en zonas exclusivas de CABA). En este paso se eliminan 11 Registros

3- Por el lado opuesto, de bajos precios por metros cuadrado, se nota que en el rango de menos de 350 dólares el metro cuadrado (78 registros) la tasa de probables errores es sumamente alta, ya sea en superficies exageradas(con dígitos de más) o en precios bajos (con dígitos de menos).

4- Adicionalmente, filtramos las propiedades con 14 metros cuadrados totales o menos, ya que se sospecha que puede tratarse de cocheras, ya que sus precios no superan los 28 mil dólares. Se trata de 9 registros.

5- Por último se eliminan 4 registros (entre los cuales parece haber 3 repetidos en Villa Devoto) con una superficie total de 2000 metros cuadrados (la cual es bastante rara para un departamento o casa ya que sería un tercio de manzana). El resultado final es una base de datos con 50.939 registros.

Basecomp_filtrada=basecomp%>%
  filter((surface_total+10>surface_covered))
         
Basecomp_filtrada=Basecomp_filtrada%>%
  filter(precio_m2<16000)

Basecomp_filtrada=Basecomp_filtrada%>%
  filter(precio_m2>350)

Basecomp_filtrada=Basecomp_filtrada%>%
  filter(surface_total>=15)

Basecomp_filtrada=Basecomp_filtrada%>%
  filter(surface_total<2000)

6) Analisis Exploratorio III

Cuando volvemos a analizar el rango, vemos que las medidas centrales como medias y medianas casi no variaron y apenas se registra algún cambio en los máximos y mínimos

Casa2=Basecomp_filtrada %>%
  filter(property_type=="Casa")
Departamento2=Basecomp_filtrada %>%
  filter(property_type=="Departamento")
PH2=Basecomp_filtrada %>%
  filter(property_type=="PH")


print("PH sin outliers")
[1] "PH sin outliers"
print(summary(PH2$price))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  32000  137000  190000  218639  270000 1500000 
print("Casas sin outliers")
[1] "Casas sin outliers"
print(summary(Casa2$price))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  62000  235000  334450  431491  490000 4000000 
print("Dptos sin outliers")
[1] "Dptos sin outliers"
print(summary(Departamento2$price))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  12500  115000  164000  246510  260000 6000000 

Sin embargo, al realizar nuevamente el boxplot del precio por metro cuadrado de superficie a posteriori de la limpieza de outliers, se observa mejor el comportamientos de las variables en los tres tipos de viviendas, y en escalas dentro de rangos “esperables”. Asimismo, se observa que el precio promedio por metro cuadrado es considerablemente mayor entre los departamentos (2931 USD/M2) que entre casas (1740 USD/M2) y PH (1954 USD/M2)

ggplot(data=Basecomp_filtrada,aes(y=precio_m2,color=property_type))+
  geom_boxplot(alpha=0.75)+
  labs(title = "Precio por metro cuadrados de distintas propiedades",x="Superficie Total",y="Precio en USD por metro cuadrado")+
  theme(legend.position = 'None')+
  facet_wrap(~property_type)

print("PH sin outliers")
[1] "PH sin outliers"
print(summary(PH2$precio_m2))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  388.6  1440.3  1903.4  1954.1  2403.0  4903.8 
print("Casas sin outliers")
[1] "Casas sin outliers"
print(summary(Casa2$precio_m2))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  350.8  1213.1  1634.2  1739.9  2079.3  9600.0 
print("Dptos sin outliers")
[1] "Dptos sin outliers"
print(summary(Departamento2$precio_m2))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  352.6  2297.3  2750.0  2930.9  3333.3 15806.5 

Veamos ahora el comportamiento del precio final en miles de dólares (no por metro cuadrado)

ggplot(Basecomp_filtrada, aes(y = price/1000, fill = property_type )) +
  geom_boxplot()+
  scale_y_continuous(limits = c(0, 5000))+
  labs(x="Tipo de vivienda", y="Precio (en miles de dolares)")+
  facet_wrap(~ property_type, labeller = "label_both")

var_numericas_filtrada <- Basecomp_filtrada %>%
  select(rooms,bathrooms,surface_total,surface_covered,price)

ggpairs(data = var_numericas_filtrada,lower = list(continuous = GGally::wrap("points", alpha = 0.4,    size=0.2),
                combo = GGally::wrap("dot", alpha = 0.5,            size=0.25) )) +
  labs(title = "Correlograma de variables", x = "", y = "") +
  theme_bw() +
  theme(legend.position = "bottom")

A diferencia del correlograma anterior, ahora se puede percibir mejor la relación positiva entre superfies (total y cubierta) y el precio, ambiente o baños. Con estos datos limpios y sospechando algún tipo de relación lineal entre estas variables procedemos a realizar modelos lineales.

7) Modelos lineales

#Lineal por ambientes Realizamos un modelo lineal en función de los ambientes

lmfitrooms <- lm(price~rooms,data = basecomp)

summary(lmfitrooms)

Call:
lm(formula = price ~ rooms, data = basecomp)

Residuals:
     Min       1Q   Median       3Q      Max 
-2711264   -97662   -32662    37125  5413191 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -41911.5     2520.1  -16.63   <2e-16 ***
rooms       104786.7      805.7  130.06   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 253900 on 51208 degrees of freedom
Multiple R-squared:  0.2483,    Adjusted R-squared:  0.2483 
F-statistic: 1.691e+04 on 1 and 51208 DF,  p-value: < 2.2e-16

El coeficiente de ordenada al origen es de -41.911 USD mientras que la pendiente hallada es de casi 105 mil USD. Ambas mediciones tienen p-value altamente significativos. Es decir, que valor estimado por el modelo para una vivienda de 1 ambiente sería un precio de aproximadamente 63 mil USD. El r2, o variabilidad explicada por el modelo, es de casi 25%.

ggplot(Basecomp_filtrada, aes(rooms, price/1000)) +
  geom_smooth(method = "lm") +
  geom_point(size=0.05)+
  labs(x="cantidad de ambientes", y="Precio (en miles de USD)",title = 'Modelo general de regresión lineal', subtitle = 'Precio de viviendas en función de sus ambientes') +
  ggpubr::stat_regline_equation(mapping=aes(label=paste(..eq.label..,..adj.rr.label.., sep="~~~~")))+
  theme_minimal()+
  theme(legend.position = "bottom")

ggplot(Basecomp_filtrada, aes(rooms, price/1000, colour = property_type))+
  geom_smooth(method = "lm",se=TRUE) +
  geom_point(size=0.05)+
  ggpubr::stat_regline_equation(mapping=aes(label=paste(..eq.label..,..adj.rr.label.., sep="~~~~")))+
  labs(x="cantidad de ambientes", y="Precio (en miles de USD)",title = 'Modelo de regresión lineal por tipo de vivienda', subtitle = 'Precio de viviendas en función de sus ambientes') +
  theme_minimal()+
  theme(legend.position = "bottom")+
  facet_wrap(~ property_type, labeller = "label_both")

##Modelo lineal por superficie

Realizamos un modelo lineal en función de la superficie total

lmfitsup <- lm(price~surface_total,data = Basecomp_filtrada)

summary(lmfitsup)

Call:
lm(formula = price ~ surface_total, data = Basecomp_filtrada)

Residuals:
     Min       1Q   Median       3Q      Max 
-2757166   -45643   -15293    19597  4483246 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)   23945.55    1418.26   16.88   <2e-16 ***
surface_total  2488.01      11.73  212.09   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 210200 on 50937 degrees of freedom
Multiple R-squared:  0.469, Adjusted R-squared:  0.469 
F-statistic: 4.498e+04 on 1 and 50937 DF,  p-value: < 2.2e-16

El coeficiente de ordenada al origen es de 23.945 USD mientras que la pendiente hallada es de 1418 USD. Es decir, que valor estimado por el modelo crece a razón de 1400 por metro cuadrado. Ambas mediciones tienen p-value altamente significativos. El r2, o variabilidad explicada por el modelo, es de casi 47%.

ggplot(Basecomp_filtrada, aes(surface_total, price/1000)) +
  geom_smooth(method = "lm") +
  geom_point(size=0.05)+
  labs(x="cantidad de ambientes", y="Precio (en miles de USD)",title = 'Modelo general de regresión lineal', subtitle = 'Precio de viviendas en función de su superficie') +
  ggpubr::stat_regline_equation(mapping=aes(label=paste(..eq.label..,..adj.rr.label.., sep="~~~~")))+
  theme_minimal()+
  theme(legend.position = "bottom")

ggplot(Basecomp_filtrada, aes(surface_total, price/1000, colour = property_type)) +
  geom_smooth(method = "lm") +
  geom_point(size=0.08)+
  labs(x="Sup. Total en M2", y="Precio (en miles de USD)",title = 'Modelo de regresión lineal por tipo de propiedad', subtitle = 'Precio de viviendas en función de su superficie') +
  theme_minimal()+
  ggpubr::stat_regline_equation(mapping=aes(label=paste(..eq.label..,..adj.rr.label.., sep="~~~~")))+
  theme(legend.position = "bottom")+
  facet_wrap(~ property_type, labeller = "label_both")

Conclusiones

De acuerdo los valores de R cuadrado, podemos inferir que entre los dos modelos, aquel con la variable metros cuadrados de superficie total tiene una mayor capacidad de explicar la variaciones en la variable precio en comparación con el modelo que utiliza los ambientes. En esto puede que juegue un rol la mayor rigidez de la variable discreta “ambientes” en relación a la mayor flexibilidad que posee la variable metros cuadrados (continua). Por otra parte, cabe destacar que al realizar las regresiones lineales según tipo de propiedad, los parámetros de las rectas varian considerablemente. Asimismo, en los casos de departamentos y ph se obtuvieron mayores R2 que en los modelos generales, tanto medido en función de los ambientes como de los metros cuadrados de superficie total.

LS0tDQp0aXRsZTogIkVFQTIwMTkgVFAxIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICB0b2M6IHllcw0KZGF0ZTogJycNCnN1YnRpdGxlOiBBcnR1cm8gUy4gTGV3aW5nZXINCi0tLQ0KDQojIyAxKSBQcmVwYXJhY2nDs24gZGUgZGF0b3MNCg0KQ2FyZ2Ftb3MgbGlicmVyw61hcyB5IGRhdG9zDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KG1pY2UpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShHR2FsbHkpDQpsaWJyYXJ5KGNvcnJwbG90KQ0KYmFzZSA8LSByZWFkX2NzdignQzovVXNlcnMvQXJ0dXIvRGVza3RvcC9BcnR1cm8vRUVBMjAxOS1tYXN0ZXIvdHAxL2FyX3Byb3BlcnRpZXMvYXJfcHJvcGVydGllcy5jc3YnKQ0KYGBgDQoNClJldmlzYW1vcyBicmV2ZW1lbnRlIGVsIGRhdGFzZXQsIHN1IGNvbnRlbmlkbyB5IHRpcG8gZGUgdmFyaWFibGVzLg0KDQpgYGB7cn0NCmdsaW1wc2UoYmFzZSkNCmBgYA0KDQoNClByb2NlZGVtb3MgYSBmaWx0cmFyIHBhcmEgZGVqYXIgw7puaWNhbWVudGUgbGFzIHByb3BpZWRhZGVzIGVuICJWZW50YSIgZGUgQXJnZW50aW5hLCBDYXBpdGFsIEZlZGVyYWwsIHZhbHVhZGFzIGVuIFVTRCwgZGUgdGlwbyAiQ2FzYSIsICJQSCIgeSAiRGVwYXJ0YW1lbnRvIi4gTGFzIHZhcmlhYmxlcyBjb24gbGFzIGNvbnRhcmVtb3Mgc2Vyw6FuLCAiSUQiLCBCYXJyaW8gKCJsMyIpLCBhbWJpZW50ZXMsIGN1YXJ0b3MsIGJhw7Fvcywgc3VwZXJmaWNpZSB0b3RhbCwgc3VwZXJmaWNpZSBjdWJpZXJ0YSwgcHJlY2lvIHkgdGlwbyBkZSBwcm9waWVkYWQuIA0KYGBge3J9DQpiYXNlPWJhc2UgJT4lDQogIGZpbHRlcihsMT09IkFyZ2VudGluYSIsbDI9PSJDYXBpdGFsIEZlZGVyYWwiLGN1cnJlbmN5PT0iVVNEIixwcm9wZXJ0eV90eXBlPT0iUEgifHByb3BlcnR5X3R5cGU9PSJDYXNhInxwcm9wZXJ0eV90eXBlPT0iRGVwYXJ0YW1lbnRvIixvcGVyYXRpb25fdHlwZT09IlZlbnRhIiklPiUNCiAgc2VsZWN0KGlkLCBsMywgcm9vbXMsIGJlZHJvb21zLCBiYXRocm9vbXMsIHN1cmZhY2VfdG90YWwsIHN1cmZhY2VfY292ZXJlZCwgcHJpY2UsIHByb3BlcnR5X3R5cGUpDQpgYGANCg0KIyMgMikgQW7DoWxpc2lzIGV4cGxvcmF0b3JpbyBJDQoNCk9ic2VydmFtb3MgY3VhbnRvcyB2YWxvcmVzIMO6bmljb3MgeSBmYWx0YW50ZXMgdGllbmUgY2FkYSBjb2x1bW5hDQpgYGB7cn0NCmZvciAoaSBpbiAxOjgpew0KICBhPXN1bShpcy5uYShiYXNlWzE6NjE5MDUsaV0pKQ0KICBiPWNvdW50KHVuaXF1ZShiYXNlWyxpXSkpDQogIGM9bmFtZXMoYmFzZVssaV0pDQogIGQ9IHJvdW5kKGEvNjE5MDUsMikNCiAgcHJpbnQocGFzdGUoIkxhIGNvbHVtbmEgJyIsYywiJyB0aWVuZSAiLGEsIiBmYWx0YW50ZXMoIixkLCIgcG9yY2VudGFqZSBkZWwgdG90YWwpIHkgdGllbmUgIiwgYiwiIHZhbG9yZXMgdW5pY29zIikpDQp9DQpgYGANCkVuIGxhIGNvbHVtbmEgZGUgSUQsIHZlbW9zIHF1ZSBubyBoYXkgZGF0b3MgZmFsdGFudGVzIHkgYWRlbcOhcyBwb2RlbW9zIGludHVpciBxdWUgbm8gaGF5IElEcyByZXBldGlkb3MgeWEgcXVlIGxvcyB2YWxvcmVzIMO6bmljb3MgY29pbmNpZGVuIGNvbiBsYSBjYW50aWRhZCBkZSBmaWxhcyBkZWwgZGF0YWZyYW1lLg0KZW4gY3VhbnRvIGEgbG9zIGJhcnJpb3MgKCJsMyIpLCBoYXkgcG9jb3MgZmFsdGFudGVzIGVuIHTDqXJtaW5vcyByZWxhdGl2b3MgeSBsYSBjYW50aWRhZCBkZSB2YWxvcmVzIMO6bmljb3MgZGUgNTgsIHNpIGJpZW4gZXMgbWF5b3IgYSBsb3MgNDggYmFycmlvcyBvZmljaWFsZXMsIGV4aXN0ZW4gMTE1IGJhcnJpb3Mgbm8gb2ZpY2lhbGVzLCBwb3IgbG8gcXVlIHB1ZWRlIHNlciB1biB2YWxvciBwb3NpYmxlLg0KTGEgdmFyaWFibGUgcXVlIG3DoXMgZmFsdGFudGUgcHJlc2VudGEgZXMgImN1YXJ0b3MiIChiZWRyb29tKSBjb24gMjUgbWlsIHJlZ2lzdHJvcyBhcHJveC4sIGxvIHF1ZSBpbXBsaWNhIHVuYSBwcm9wb3JjacOzbiBjb25zaWRlcmFibGUgZGUgbnVlc3RybyBkYXRhIHNldCAoZGUgNDElKS4gRXN0byBwb2Ryw61hIHRyYW5zZm9ybWFyc2UgZW4gdW4gcHJvYmxlbWEgc2kgcGVuc2FyYW1vcyBlbiBlbGltaW5hciBsb3MgcmVnaXN0cm9zIGNvbiBhbGfDum4gZmFsdGFudGUuIFBlcm8gZmFsdGEgYW5hbGl6YXIgYcO6biBsYSBpbXBvcnRhbmNpYSBkZSBlc3RhIHZhcmlhYmxlLg0KTGFzIDQgdmFyaWFibGVzIHJlc3RhbnRlcyBubyBwcmVzZW50YSBuaW5ndW5hIHVuIGZhbHRhbnRlIG1heW9yIGFsIDklLg0KDQpBaG9yYSwgc2VwYXJhbW9zIGxhcyB2YXJpYWJsZXMgbnVtw6lyaWNhcyBwYXJhIGFuYWxpemFyIGxhIG1hdHJpeiBkZSBjb3JyZWxhY2nDs24gb21pdGllbmRvIGxvcyB2YWxvcmVzIGZhbHRhbnRlcy4gDQpgYGB7cn0NCmJhc2VfbnVtZXJpY2E9YmFzZSAlPiUgDQogIHNlbGVjdChyb29tcywgYmVkcm9vbXMsIGJhdGhyb29tcywgc3VyZmFjZV90b3RhbCwgc3VyZmFjZV9jb3ZlcmVkLCBwcmljZSkNCmJhc2Vjb3I9Y29yKGJhc2VfbnVtZXJpY2EsdXNlPSAiY29tcGxldGUub2JzIiwgbWV0aG9kPSJwZWFyc29uIikNCmNvcnJwbG90KGJhc2Vjb3IsYWRkQ29lZi5jb2wgPSJibGFjayIsZGlhZz1GLHR5cGUgPSAidXBwZXIiKQ0KDQpgYGANCiMjIDMpIFByZXBhcmFjacOzbiBkZSBkYXRvcw0KDQpEYWRvIHF1ZSBsYSB2YXJpYWJsZSAiQmVkcm9vbXMiIHkgIlJvb21zIiBlc3RhbiBhbHRhbWVudGUgY29ycmVsYWNpb25hZGFzICgwLjkyKSBkZSBmb3JtYSBwb3NpdGl2YSBlbGxvIG5vcyBpbmRpY2EgcXVlIHVuYSBkZSBlbGxhcyBjYXNpIG5vIGFwb3J0YSBudWV2YSBpbmZvcm1hY2nDs24gYWRpY2lvbmFsIGEgbGEgb3RyYS4gQ29uc2lkZXJhbmRvLCBjb21vIHlhIHZpbW9zLCBxdWUgImJlZHJvb21zIiB0ZW7DrWEgdW5hIGFsdGEgcHJvcG9yY2nDs24gZGUgZmFsdGFudGUgeSBlc3RlIGFsdG8gbml2ZWwgZGUgY29ycmVsYWNpw7NuLCBsYSBlbGltaW5hcmVtb3MuDQpgYGB7cn0NCmJhc2U9YmFzZSU+JQ0KICBzZWxlY3QoLWJlZHJvb21zKQ0KYGBgDQoNCkxhIHNpZ3VpZW50ZSBtYXRyaXogbm9zIG11ZXN0cmEgcXVlIHBhcmEgbGFzIDggdmFyaWFibGVzIHRlbmVtb3MgZGF0b3MgY29tcGxldG9zIGVuIDUxMjEwIGNhc29zIChjb24gY2VybyBmYWx0YW50ZSkuIEVuIHJvam8gdmVtb3MgbG9zIGZhbHRhbnRlcyBlbiB1bmEgY29sdW1uYSB5IHN1cyBjb21iaW5hY2lvbmVzIChhIGxhIGl6cXVpZXJkYSBzZSB2ZW4gbGEgY2FudGlkYWQgZGUgY2Fzb3MgcXVlIG9jdXJyZSBsYSBzaXR1YWNpw7NuIGRlIGxhIGZpbGEgeSBhIGxhIGRlcmVjaGEgY3VhbnRvcyBmYWx0YW50ZXMgcG9yIGZpbGEgZGUgOCB2YXJpYWJsZXMpLg0KQ29tbyBzZSBvYnNlcnZhIGEgY29udGludWFjacOzbiwgZWwgY2FzbyBtw6FzIGNvbcO6biBlcyBlbCBkZSByZWdpc3Ryb3MgZW4gbG9zIGN1YWxlcyBmYWx0YSDDum5pY2FtZW50ZSBsYSB2YXJpYWJsZSAicm9vbXMiLCBjb24gMzMwMCBjYXNvcy4NCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9Mjd9DQptZC5wYXR0ZXJuKGJhc2UpDQpgYGANCnB0byAzLmIpDQpDb24gZXN0ZSBhbsOhbGlzaXMgbm90YW1vcyBxdWUgc2kgZWxpbWluYW1vcyBsb3MgcmVnaXN0cm9zIGNvbiBmYWx0YW50ZSByZWR1Y2lyw61hbW9zIGxhIGJhc2UgZW4gdW4gMTclIGRlbCBkYXRhc2V0IHByZS1zZWxlY2Npb25hZG8gbG8gcXVlIHBhcmVjZSBubyBkZW1hc2lhZG8gYXJyaWVzZ2FkbyAobm9zIHF1ZWRhbW9zIGNvbiBlbCA4Miw3JSwgbyBzZWEgNTEgbWlsIGZpbGFzIGRlIGNhc2kgNjIgbWlsKS4gVmFsZSBhY2xhcmFyIHF1ZSBkZSBoYWJlciBjb25zaWRlcmFkbyBxdWUgZXN0ZSBwZXJjZW50YWplIGVyYSBkZW1hc2lhZG8gcGFyYSBlbGltaW5hciwgZGFkbyBxdWUgdHJhYmFqYXJlbW9zIGNvbiBzdXBlcmZpY2llcywgcHJlY2lvcyB5IGFtYmllbnRlcywgcG9kcsOtYW1vcyBoYWJlciBkZWphZG8gY2Fzb3MgY29uIGNpZXJ0b3MgZmFsdGFudGVzLiBQb3IgZWplbXBsbywgaGF5IGNhc29zIGNvbiBzb2xvIGZhbHRhbnRlcyBlbiAiYmF0aHJvb20iLCBjb24gbG8gY3VhbCBzaSBubyBlbGltaW7DoHNlbW9zIGVzdG9zIGNhc29zIHBvZHLDrWFtb3Mgc3VtYXIgMTMwMCBudWV2b3MgcmVnaXN0cm9zLg0KDQoNCmBgYHtyfQ0KYmFzZWNvbXAgPC0gbmEub21pdChiYXNlKQ0KYGBgDQoNCiMjIDQpIEFuw6FsaXNpcyBleHBsb3JhdG9yaW8gSUkNCg0KUmV2aXNhbW9zIGxhIHZhcmlhYmxlIHByZWNpbyBwYXJhIHRvZGFzIGxvcyB0aXBvcyBkZSBwcm9waWVkYWRlcyBqdW50YXMgDQpgYGB7cn0NCnN1bW1hcnkoYmFzZWNvbXAkcHJpY2UpDQoNCmBgYA0KUmVhbGl6YW1vcyB1biBoaXN0b2dyYW1hIGRlbCBsb2dhcml0bW8gZGUgbG9zIHByZWNpb3MgZW4gVVNEDQpgYGB7cn0NCmdncGxvdChkYXRhID0gYmFzZWNvbXApICsNCiAgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyh4ID0gcHJpY2UpLCBmaWxsID0gInBpbmsiKSArDQogIHNjYWxlX3hfbG9nMTAoKSArDQogIGxhYnMoeCA9ICJQcmVjaW8gZW4gVVNEIChlc2NhbGEgbG9nLikiLCB5ID0gIkZyZWN1ZW5jaWEgYWJzb2x1dGEiLCANCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJIaXN0b2dyYW1hIGRlIHByZWNpbyBkZSB2aXZpZW5kYXMiLA0KICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gImVzY2FsYSBsb2dhcsOtdG1pY2EiKSArDQogIHRoZW1lX2J3KCkNCmBgYA0KDQoNCmBgYHtyfQ0KUEg9YmFzZWNvbXAlPiUNCiAgZmlsdGVyKHByb3BlcnR5X3R5cGU9PSJQSCIpDQpjYXNhPWJhc2Vjb21wJT4lDQogIGZpbHRlcihwcm9wZXJ0eV90eXBlPT0iQ2FzYSIpDQpkZXB0bz1iYXNlY29tcCU+JQ0KICBmaWx0ZXIocHJvcGVydHlfdHlwZT09IkRlcGFydGFtZW50byIpDQoNCnByaW50KCJBbmFsaXNpcyBkZSBwcmVjaW9zIGRlIFBIOiIpDQpwcmludChzdW1tYXJ5KFBIJHByaWNlKSkNCnByaW50KCJBbmFsaXNpcyBkZSBwcmVjaW9zIGRlIENhc2E6IikNCnByaW50KHN1bW1hcnkoY2FzYSRwcmljZSkpDQpwcmludCgiQW5hbGlzaXMgZGUgcHJlY2lvcyBkZSBEZXBhcnRhbWVudG86IikNCnByaW50KHN1bW1hcnkoZGVwdG8kcHJpY2UpKQ0KYGBgDQoNClNlIG9ic2VydmEgcXVlIGxhIG1lZGlhIGRlIHByZWNpb3MgZGUgbGFzIGNhc2FzIGVzIGNvbnNpZGVyYWJsZW1lbnRlIG1hcyBhbHRhIChlbiB0b3JubyBhICQ0MzAgbWlsIFVTRCkgcXVlIGxhIGRlIFBIIHkgZGVwYXJ0YW1lbnRlIChlbnRyZSAyMTggbWlsIFVTRCB5IDI0NyBtaWwgVVNELCByZXNwZWN0aXZhbWVudGUpDQoNCg0KU2UgcmVhbGl6YW4gYSBjb250aW51YWNpw7NuIGxvcyBib3hwbG90IHBvciB0aXBvIGRlIHByb3BpZWRhZC4gRGFkbyBxdWUgZWwgY3JlY2ltaWVudG8gZGUgbG9zIHByZWNpb3MgZGlmaWN1bHRhIHZlciBsYSBsYSAiY2FqYSIgZGUgbG9zIGJveHBsb3QsIHJlYWxpemFtb3MgdW5hIHRyYW5zZm9ybWFjacOzbiBlbiBsb2dhcml0bW9zIGRlIGxhIHZhcmlhYmxlIHByZWNpby4NCmBgYHtyfQ0KZ2dwbG90KGJhc2Vjb21wLGFlcyh5PWxvZyhwcmljZSwxMCksY29sb3I9cHJvcGVydHlfdHlwZSkpKw0KICBnZW9tX2JveHBsb3QoYWxwaGE9MC43NSkrDQogIGxhYnModGl0bGUgPSAiTG9nYXJpdG1vIGRlIHByZWNpb3MgZGUgcHJvcGllZGFkZXMgZW4gZnVuY2nDs24gZGUgc3Ugc3VwZXJmaWNpZSIseD0iU3VwZXJmaWNpZSBUb3RhbCIseT0iTG9nYXJpdG1vIGRlbCBwcmVjaW8gZW4gVVNEIikrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdOb25lJykrDQogIGZhY2V0X3dyYXAofnByb3BlcnR5X3R5cGUpDQoNCmBgYA0KDQoNClJlYWxpemFtb3MgdW4gY29ycmVsb2dyYW1hcyBwYXJhIHZlciBsYSByZWxhY2nDs24geSBkaWFncmFtYSBkZSBkaXNwZXJzacOzbiBlbnRyZSBsYXMgdmFyaWFibGVzIG51bcOpcmljYXMuDQoNCmBgYHtyfQ0KdmFyX251bWVyaWNhcyA8LSBiYXNlY29tcCAlPiUNCiAgc2VsZWN0KHJvb21zLGJhdGhyb29tcyxzdXJmYWNlX3RvdGFsLHN1cmZhY2VfY292ZXJlZCxwcmljZSkNCg0KR0dhbGx5OjpnZ3BhaXJzKGRhdGEgPSB2YXJfbnVtZXJpY2FzLA0KICAgICAgICAgICAgICAgIGxvd2VyID0gbGlzdChjb250aW51b3VzID0gR0dhbGx5Ojp3cmFwKCJwb2ludHMiLCBhbHBoYSA9IDAuNCwgICAgc2l6ZT0wLjIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21ibyA9IEdHYWxseTo6d3JhcCgiZG90IiwgYWxwaGEgPSAwLjUsICAgICAgICAgICAgc2l6ZT0wLjI1KSApKSArDQogIGdncGxvdDI6OmxhYnModGl0bGUgPSAiQ29ycmVsb2dyYW1hIGRlIHZhcmlhYmxlcyIsIHggPSAiIiwgeSA9ICIiKSArDQogIGdncGxvdDI6OnRoZW1lX2J3KCkgKw0KICBnZ3Bsb3QyOjp0aGVtZSgNCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICApDQoNCmBgYA0KDQpEZWwgY29ycmVsb2dyYW1hIHNlIHB1ZWRlIHZlciBsYSByZWxhY2nDs24gcG9zaXRpdmEgZW50cmUgYmHDsW9zIHkgYW1iaWVudGVzIChhbWJhcyBkaXNjcmV0YXMsIHBvciBlc28gbGEgZm9ybWEgc2VwYXJhZGEgZGUgc3VzIHB1bnRvcykuIEVuIGN1YW50byBzdXBlcmZpY2llcyAoY3ViaWVydGEgeSB0b3RhbCkgc2Ugb2JzZXJ2YW4gYWxndW5vcyBvdXRsaWVyIHF1ZSBhcGxhbmEgY29uc2lkZXJhYmxlbWVudGUgbGEgZGlzdHJpYnVjacOzbiBkZSBsb3MgcHVudG9zIGVuIGN1YW50byBhIGFtYmllbnRlcyAoaW1waWRpZW5kbyB2ZXIgbGEgcmVsYWNpw7NuIGVudHJlIGFtYmFzKSBvIGNvbmNlbnRyYW5kbyBsb3MgcHVudG9zIGVuIGN1YW50byBhIHByZWNpb3MuDQoNCiMjIDUpIE91dGxpZXJzDQpFbiBwcmltZXIgbHVnYXIsIGRlbCBhbsOhbGlzaXMgcHJlY2VkZW50ZSByZXNhbHRhbiBhbGd1bmFzIHByb3BpZWRhZGVzIGNvbiBtYXMgZGUgMTAgYmHDsW9zIHkgcG9jb3MgYW1iaWVudGVzLg0KRGVzY3Vicmltb3MgcXVlIGxvcyBzaWd1aWVudGVzIDkgZGVwYXJ0YW1lbnRvcyB0aWVuZW4gbWFsIGNhcmdhZG8gc3VzIGJhw7FvcyBwb3Igc3UgcmVsYWNpw7NuIGludmlhYmxlIGNvbiBoYWJpdGFjaW9uZXMgeSBtZXRyb3MgdG90YWxlcy4gUGVzZSBhIGVsbG8sIHN1IHJlbGFjacOzbiBlbnRyZSBtZXRyb3MgY3VhZHJhZG9zIHkgcHJlY2lvIG5vIHBhcmVjZSBhbWVyaXRhciBzdSBlbGltaW5hY2nDs24gcG9yIHNlciBuw7ptZXJvcyByYXpvbmFibGVzICh0ZW5pZW5kbyBlbiBjdWVudGEgcXVlIGxhIHZhcmlhYmxlIGVuIGxhIHF1ZSBub3MgY2VudHJhbW9zIGVzIOKAnHByZWNpb+KAnSwgcG9yIGxhIGNvbnNpZ25hIGRlbCBUUCkuDQpgYGB7cn0NCmJhc2Vjb21wJT4lDQogIGZpbHRlcihiYXRocm9vbXM+MTApDQpgYGANCg0KRGFkbyBxdWUgbXVjaGFzIHByb3BpZWRhZGVzIGNvbiBlcnJvcmVzIGRlIGNhcmdhIHB1ZWRlbiBvY3VsdGFyc2UgYWwgZXN0YXIgZGVudHJvIGVsIOKAnHJhbmdv4oCdIGRlIHByZWNpb3Mgbm9ybWFsZXMsIGNyZWFyZW1vcyB1bmEgbnVldmEgdmFyaWFibGUg4oCcUHJlY2lvIHBvciBNZXRybyBjdWFkcmFkb+KAnSBwYXJhIGRldGVjdGFyIG1lam9yIHBvc2libGVzIGVycm9yZXMgeSBvdXRsaWVycy4NCmBgYHtyfQ0KYmFzZWNvbXA9YmFzZWNvbXAlPiUNCiAgbXV0YXRlKHByZWNpb19tMj1wcmljZS9zdXJmYWNlX3RvdGFsKQ0KDQpnZ3Bsb3QoZGF0YT1iYXNlY29tcCxhZXMoeT1wcmVjaW9fbTIsY29sb3I9cHJvcGVydHlfdHlwZSkpKw0KICBnZW9tX2JveHBsb3QoYWxwaGE9MC43NSkrDQogIGxhYnModGl0bGUgPSAiUHJlY2lvIHBvciBtZXRybyBjdWFkcmFkb3MgZGUgZGlzdGludGFzIHByb3BpZWRhZGVzIix5PSJQcmVjaW8gZW4gVVNEIHBvciBtZXRybyBjdWFkcmFkbyIpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnTm9uZScpKw0KICBmYWNldF93cmFwKH5wcm9wZXJ0eV90eXBlKQ0KYGBgDQoNCkxvcyBwcm9ibGVtYXMgcXVlIG5vdGFtb3MgYWwgZmlsdHJhciBsYXMgcHJvcGllZGFkZXMgY29uIHZhbG9yIHBvciBtZXRybyBjdWFkcmFkbyBwb3IgZW5jaW1hIGRlIDE2IG1pbCBkw7NsYXJlcyBzb24gdmFyaW9zOiB1bm8gZGUgZWxsb3MgZXN0YSBkYWRvIHBvciBzdXBlcmZpY2llcyB0b3RhbGVzIG1lbm9yZXMgYSBsYSBzdXBlcmZpY2llIGN1YmllcnRhLiBPdHJvIHBhcmVjZXLDrWFuIHNlciBwcmVjaW9zIGV4dHJlbW9zIGRvbmRlIGxvcyB2YWxvcmVzIHBvZHLDrWFuIHRlbmVyIHVuIGTDrWdpdG8gZGUgbcOhcy4gUG9yIGVsbG86IA0KDQoxLSBQcmltZXJvIGxpbXBpYW1vcyBhcXVlbGxhcyBwcm9waWVkYWRlcyBjb24gc3VwZXJmaWNpZSBjdWJpZXJ0YSBtYXlvciBhIGxhIHRvdGFsIGVuIDEwIG1ldHJvcyBvIG3DoXMgKDE2MyByZWdpc3Ryb3MpLiBDb24gZXN0bywgYWRlbcOhcyBkZSBlbGltaW5hciBwcm9waWVkYWRlcyBjb24gZXJyb3JlcyBncm9zZXJvcywgZXN0YXJlbW9zIGVsaW1pbmFuZG8gYWxndW5vcyBwcmVjaW9zIHBvciBtZXRybyBjdWFkcmFkbyDigJxwb3NpYmxl4oCdIChlbiDDoXJlYXMgY29tbyBwdWVydG8gbWFkZXJvKSBwZXJvIHF1ZSBlbiByZWFsaWRhZCBzb24gZnJ1dG8gZGUgY2FyZ2FzIGVycm9uZWFzLiANCg0KMi0gTGltcGlhbW9zIGFxdWVsbGFzIHByb3BpZWRhZGVzIGNvbiBwcmVjaW9zIHBvciBtZXRybyBjdWFkcmFkbyBzdXBlcmlvciBhIGxvcyAxNi4wMDAgbWlsIGTDs2xhcmVzIChzZSBlbGlnacOzIGVzdGUgdmFsb3IgeWEgcXVlIGhhc3RhIGVzdGUgbW9udG8gc2Ugb2JzZXJ2YWJhbiByZWdpc3Ryb3Mg4oCccmF6b25hYmxlc+KAnSBlbiB6b25hcyBleGNsdXNpdmFzIGRlIENBQkEpLiBFbiBlc3RlIHBhc28gc2UgZWxpbWluYW4gMTEgUmVnaXN0cm9zIA0KDQozLSBQb3IgZWwgbGFkbyBvcHVlc3RvLCBkZSBiYWpvcyBwcmVjaW9zIHBvciBtZXRyb3MgY3VhZHJhZG8sIHNlIG5vdGEgcXVlIGVuIGVsIHJhbmdvIGRlIG1lbm9zIGRlIDM1MCBkw7NsYXJlcyBlbCBtZXRybyBjdWFkcmFkbyAoNzggcmVnaXN0cm9zKSBsYSB0YXNhIGRlIHByb2JhYmxlcyBlcnJvcmVzIGVzIHN1bWFtZW50ZSBhbHRhLCB5YSBzZWEgZW4gc3VwZXJmaWNpZXMgZXhhZ2VyYWRhcyhjb24gZMOtZ2l0b3MgZGUgbcOhcykgbyBlbiBwcmVjaW9zIGJham9zIChjb24gZMOtZ2l0b3MgZGUgbWVub3MpLiANCg0KNC0gQWRpY2lvbmFsbWVudGUsIGZpbHRyYW1vcyBsYXMgcHJvcGllZGFkZXMgY29uIDE0IG1ldHJvcyBjdWFkcmFkb3MgdG90YWxlcyBvIG1lbm9zLCB5YSBxdWUgc2Ugc29zcGVjaGEgcXVlIHB1ZWRlIHRyYXRhcnNlIGRlIGNvY2hlcmFzLCB5YSBxdWUgc3VzIHByZWNpb3Mgbm8gc3VwZXJhbiBsb3MgMjggbWlsIGTDs2xhcmVzLiBTZSB0cmF0YSBkZSA5IHJlZ2lzdHJvcy4gDQoNCjUtIFBvciDDumx0aW1vIHNlIGVsaW1pbmFuIDQgcmVnaXN0cm9zIChlbnRyZSBsb3MgY3VhbGVzIHBhcmVjZSBoYWJlciAzIHJlcGV0aWRvcyBlbiBWaWxsYSBEZXZvdG8pIGNvbiB1bmEgc3VwZXJmaWNpZSB0b3RhbCBkZSAyMDAwIG1ldHJvcyBjdWFkcmFkb3MgKGxhIGN1YWwgZXMgYmFzdGFudGUgcmFyYSBwYXJhIHVuIGRlcGFydGFtZW50byBvIGNhc2EgeWEgcXVlIHNlcsOtYSB1biB0ZXJjaW8gZGUgbWFuemFuYSkuIEVsIHJlc3VsdGFkbyBmaW5hbCBlcyB1bmEgYmFzZSBkZSBkYXRvcyBjb24gNTAuOTM5IHJlZ2lzdHJvcy4NCg0KYGBge3J9DQpCYXNlY29tcF9maWx0cmFkYT1iYXNlY29tcCU+JQ0KICBmaWx0ZXIoKHN1cmZhY2VfdG90YWwrMTA+c3VyZmFjZV9jb3ZlcmVkKSkNCiAgICAgICAgIA0KQmFzZWNvbXBfZmlsdHJhZGE9QmFzZWNvbXBfZmlsdHJhZGElPiUNCiAgZmlsdGVyKHByZWNpb19tMjwxNjAwMCkNCg0KQmFzZWNvbXBfZmlsdHJhZGE9QmFzZWNvbXBfZmlsdHJhZGElPiUNCiAgZmlsdGVyKHByZWNpb19tMj4zNTApDQoNCkJhc2Vjb21wX2ZpbHRyYWRhPUJhc2Vjb21wX2ZpbHRyYWRhJT4lDQogIGZpbHRlcihzdXJmYWNlX3RvdGFsPj0xNSkNCg0KQmFzZWNvbXBfZmlsdHJhZGE9QmFzZWNvbXBfZmlsdHJhZGElPiUNCiAgZmlsdGVyKHN1cmZhY2VfdG90YWw8MjAwMCkNCmBgYA0KDQoNCiMjIDYpIEFuYWxpc2lzIEV4cGxvcmF0b3JpbyBJSUkNCg0KQ3VhbmRvIHZvbHZlbW9zIGEgYW5hbGl6YXIgZWwgcmFuZ28sIHZlbW9zIHF1ZSBsYXMgbWVkaWRhcyBjZW50cmFsZXMgY29tbyBtZWRpYXMgeSBtZWRpYW5hcyBjYXNpIG5vIHZhcmlhcm9uIHkgYXBlbmFzIHNlIHJlZ2lzdHJhIGFsZ8O6biBjYW1iaW8gZW4gbG9zIG3DoXhpbW9zIHkgbcOtbmltb3MgDQpgYGB7cn0NCkNhc2EyPUJhc2Vjb21wX2ZpbHRyYWRhICU+JQ0KICBmaWx0ZXIocHJvcGVydHlfdHlwZT09IkNhc2EiKQ0KRGVwYXJ0YW1lbnRvMj1CYXNlY29tcF9maWx0cmFkYSAlPiUNCiAgZmlsdGVyKHByb3BlcnR5X3R5cGU9PSJEZXBhcnRhbWVudG8iKQ0KUEgyPUJhc2Vjb21wX2ZpbHRyYWRhICU+JQ0KICBmaWx0ZXIocHJvcGVydHlfdHlwZT09IlBIIikNCg0KDQpwcmludCgiUEggc2luIG91dGxpZXJzIikNCnByaW50KHN1bW1hcnkoUEgyJHByaWNlKSkNCg0KcHJpbnQoIkNhc2FzIHNpbiBvdXRsaWVycyIpDQpwcmludChzdW1tYXJ5KENhc2EyJHByaWNlKSkNCg0KcHJpbnQoIkRwdG9zIHNpbiBvdXRsaWVycyIpDQpwcmludChzdW1tYXJ5KERlcGFydGFtZW50bzIkcHJpY2UpKQ0KDQpgYGANCg0KU2luIGVtYmFyZ28sIGFsIHJlYWxpemFyIG51ZXZhbWVudGUgZWwgYm94cGxvdCBkZWwgcHJlY2lvIHBvciBtZXRybyBjdWFkcmFkbyBkZSBzdXBlcmZpY2llIGEgcG9zdGVyaW9yaSBkZSBsYSBsaW1waWV6YSBkZSBvdXRsaWVycywgc2Ugb2JzZXJ2YSBtZWpvciBlbCBjb21wb3J0YW1pZW50b3MgZGUgbGFzIHZhcmlhYmxlcyBlbiBsb3MgdHJlcyB0aXBvcyBkZSB2aXZpZW5kYXMsIHkgZW4gZXNjYWxhcyBkZW50cm8gZGUgcmFuZ29zIOKAnGVzcGVyYWJsZXPigJ0uIEFzaW1pc21vLCBzZSBvYnNlcnZhIHF1ZSBlbCBwcmVjaW8gcHJvbWVkaW8gcG9yIG1ldHJvIGN1YWRyYWRvIGVzIGNvbnNpZGVyYWJsZW1lbnRlIG1heW9yIGVudHJlIGxvcyBkZXBhcnRhbWVudG9zICgyOTMxIFVTRC9NMikgcXVlIGVudHJlIGNhc2FzICgxNzQwIFVTRC9NMikgeSBQSCAoMTk1NCBVU0QvTTIpDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGE9QmFzZWNvbXBfZmlsdHJhZGEsYWVzKHk9cHJlY2lvX20yLGNvbG9yPXByb3BlcnR5X3R5cGUpKSsNCiAgZ2VvbV9ib3hwbG90KGFscGhhPTAuNzUpKw0KICBsYWJzKHRpdGxlID0gIlByZWNpbyBwb3IgbWV0cm8gY3VhZHJhZG9zIGRlIGRpc3RpbnRhcyBwcm9waWVkYWRlcyIseD0iU3VwZXJmaWNpZSBUb3RhbCIseT0iUHJlY2lvIGVuIFVTRCBwb3IgbWV0cm8gY3VhZHJhZG8iKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ05vbmUnKSsNCiAgZmFjZXRfd3JhcCh+cHJvcGVydHlfdHlwZSkNCg0KYGBgDQoNCmBgYHtyfQ0KcHJpbnQoIlBIIHNpbiBvdXRsaWVycyIpDQpwcmludChzdW1tYXJ5KFBIMiRwcmVjaW9fbTIpKQ0KDQpwcmludCgiQ2FzYXMgc2luIG91dGxpZXJzIikNCnByaW50KHN1bW1hcnkoQ2FzYTIkcHJlY2lvX20yKSkNCg0KcHJpbnQoIkRwdG9zIHNpbiBvdXRsaWVycyIpDQpwcmludChzdW1tYXJ5KERlcGFydGFtZW50bzIkcHJlY2lvX20yKSkNCg0KYGBgDQoNClZlYW1vcyBhaG9yYSBlbCBjb21wb3J0YW1pZW50byBkZWwgcHJlY2lvIGZpbmFsIGVuIG1pbGVzIGRlIGTDs2xhcmVzIChubyBwb3IgbWV0cm8gY3VhZHJhZG8pDQpgYGB7cn0NCmdncGxvdChCYXNlY29tcF9maWx0cmFkYSwgYWVzKHkgPSBwcmljZS8xMDAwLCBmaWxsID0gcHJvcGVydHlfdHlwZSApKSArDQogIGdlb21fYm94cGxvdCgpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA1MDAwKSkrDQogIGxhYnMoeD0iVGlwbyBkZSB2aXZpZW5kYSIsIHk9IlByZWNpbyAoZW4gbWlsZXMgZGUgZG9sYXJlcykiKSsNCiAgZmFjZXRfd3JhcCh+IHByb3BlcnR5X3R5cGUsIGxhYmVsbGVyID0gImxhYmVsX2JvdGgiKQ0KYGBgDQpgYGB7cn0NCnZhcl9udW1lcmljYXNfZmlsdHJhZGEgPC0gQmFzZWNvbXBfZmlsdHJhZGEgJT4lDQogIHNlbGVjdChyb29tcyxiYXRocm9vbXMsc3VyZmFjZV90b3RhbCxzdXJmYWNlX2NvdmVyZWQscHJpY2UpDQoNCmdncGFpcnMoZGF0YSA9IHZhcl9udW1lcmljYXNfZmlsdHJhZGEsbG93ZXIgPSBsaXN0KGNvbnRpbnVvdXMgPSBHR2FsbHk6OndyYXAoInBvaW50cyIsIGFscGhhID0gMC40LCAgICBzaXplPTAuMiksDQogICAgICAgICAgICAgICAgY29tYm8gPSBHR2FsbHk6OndyYXAoImRvdCIsIGFscGhhID0gMC41LCAgICAgICAgICAgIHNpemU9MC4yNSkgKSkgKw0KICBsYWJzKHRpdGxlID0gIkNvcnJlbG9ncmFtYSBkZSB2YXJpYWJsZXMiLCB4ID0gIiIsIHkgPSAiIikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQpgYGANCg0KQSBkaWZlcmVuY2lhIGRlbCBjb3JyZWxvZ3JhbWEgYW50ZXJpb3IsIGFob3JhIHNlIHB1ZWRlIHBlcmNpYmlyIG1lam9yIGxhIHJlbGFjacOzbiBwb3NpdGl2YSBlbnRyZSBzdXBlcmZpZXMgICh0b3RhbCB5IGN1YmllcnRhKSB5IGVsIHByZWNpbywgYW1iaWVudGUgbyBiYcOxb3MuIENvbiBlc3RvcyBkYXRvcyBsaW1waW9zIHkgc29zcGVjaGFuZG8gYWxnw7puIHRpcG8gZGUgcmVsYWNpw7NuIGxpbmVhbCBlbnRyZSBlc3RhcyB2YXJpYWJsZXMgcHJvY2VkZW1vcyBhIHJlYWxpemFyIG1vZGVsb3MgbGluZWFsZXMuDQoNCiMjIDcpIE1vZGVsb3MgbGluZWFsZXMNCg0KI0xpbmVhbCBwb3IgYW1iaWVudGVzDQpSZWFsaXphbW9zIHVuIG1vZGVsbyBsaW5lYWwgZW4gZnVuY2nDs24gZGUgbG9zIGFtYmllbnRlcw0KYGBge3J9DQpsbWZpdHJvb21zIDwtIGxtKHByaWNlfnJvb21zLGRhdGEgPSBiYXNlY29tcCkNCg0Kc3VtbWFyeShsbWZpdHJvb21zKQ0KYGBgDQpFbCBjb2VmaWNpZW50ZSBkZSBvcmRlbmFkYSBhbCBvcmlnZW4gZXMgZGUgLTQxLjkxMSBVU0QgbWllbnRyYXMgcXVlIGxhIHBlbmRpZW50ZSBoYWxsYWRhIGVzIGRlIGNhc2kgMTA1IG1pbCBVU0QuIEFtYmFzIG1lZGljaW9uZXMgdGllbmVuIHAtdmFsdWUgYWx0YW1lbnRlIHNpZ25pZmljYXRpdm9zLiBFcyBkZWNpciwgcXVlIHZhbG9yIGVzdGltYWRvIHBvciBlbCBtb2RlbG8gcGFyYSB1bmEgdml2aWVuZGEgZGUgMSBhbWJpZW50ZSBzZXLDrWEgdW4gcHJlY2lvIGRlIGFwcm94aW1hZGFtZW50ZSA2MyBtaWwgVVNELiBFbCByMiwgbyB2YXJpYWJpbGlkYWQgZXhwbGljYWRhIHBvciBlbCBtb2RlbG8sIGVzIGRlIGNhc2kgMjUlLg0KDQpgYGB7cn0NCmdncGxvdChCYXNlY29tcF9maWx0cmFkYSwgYWVzKHJvb21zLCBwcmljZS8xMDAwKSkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArDQogIGdlb21fcG9pbnQoc2l6ZT0wLjA1KSsNCiAgbGFicyh4PSJjYW50aWRhZCBkZSBhbWJpZW50ZXMiLCB5PSJQcmVjaW8gKGVuIG1pbGVzIGRlIFVTRCkiLHRpdGxlID0gJ01vZGVsbyBnZW5lcmFsIGRlIHJlZ3Jlc2nDs24gbGluZWFsJywgc3VidGl0bGUgPSAnUHJlY2lvIGRlIHZpdmllbmRhcyBlbiBmdW5jacOzbiBkZSBzdXMgYW1iaWVudGVzJykgKw0KICBnZ3B1YnI6OnN0YXRfcmVnbGluZV9lcXVhdGlvbihtYXBwaW5nPWFlcyhsYWJlbD1wYXN0ZSguLmVxLmxhYmVsLi4sLi5hZGoucnIubGFiZWwuLiwgc2VwPSJ+fn5+IikpKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCg0KYGBgDQoNCg0KYGBge3J9DQpnZ3Bsb3QoQmFzZWNvbXBfZmlsdHJhZGEsIGFlcyhyb29tcywgcHJpY2UvMTAwMCwgY29sb3VyID0gcHJvcGVydHlfdHlwZSkpKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLHNlPVRSVUUpICsNCiAgZ2VvbV9wb2ludChzaXplPTAuMDUpKw0KICBnZ3B1YnI6OnN0YXRfcmVnbGluZV9lcXVhdGlvbihtYXBwaW5nPWFlcyhsYWJlbD1wYXN0ZSguLmVxLmxhYmVsLi4sLi5hZGoucnIubGFiZWwuLiwgc2VwPSJ+fn5+IikpKSsNCiAgbGFicyh4PSJjYW50aWRhZCBkZSBhbWJpZW50ZXMiLCB5PSJQcmVjaW8gKGVuIG1pbGVzIGRlIFVTRCkiLHRpdGxlID0gJ01vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbCBwb3IgdGlwbyBkZSB2aXZpZW5kYScsIHN1YnRpdGxlID0gJ1ByZWNpbyBkZSB2aXZpZW5kYXMgZW4gZnVuY2nDs24gZGUgc3VzIGFtYmllbnRlcycpICsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikrDQogIGZhY2V0X3dyYXAofiBwcm9wZXJ0eV90eXBlLCBsYWJlbGxlciA9ICJsYWJlbF9ib3RoIikNCmBgYA0KDQoNCg0KIyNNb2RlbG8gbGluZWFsIHBvciBzdXBlcmZpY2llDQoNClJlYWxpemFtb3MgdW4gbW9kZWxvIGxpbmVhbCBlbiBmdW5jacOzbiBkZSBsYSBzdXBlcmZpY2llIHRvdGFsDQpgYGB7cn0NCmxtZml0c3VwIDwtIGxtKHByaWNlfnN1cmZhY2VfdG90YWwsZGF0YSA9IEJhc2Vjb21wX2ZpbHRyYWRhKQ0KDQpzdW1tYXJ5KGxtZml0c3VwKQ0KYGBgDQpFbCBjb2VmaWNpZW50ZSBkZSBvcmRlbmFkYSBhbCBvcmlnZW4gZXMgZGUgMjMuOTQ1IFVTRCBtaWVudHJhcyBxdWUgbGEgcGVuZGllbnRlIGhhbGxhZGEgZXMgZGUgMTQxOCBVU0QuIEVzIGRlY2lyLCBxdWUgdmFsb3IgZXN0aW1hZG8gcG9yIGVsIG1vZGVsbyBjcmVjZSBhIHJhesOzbiBkZSAxNDAwIHBvciBtZXRybyBjdWFkcmFkby4gQW1iYXMgbWVkaWNpb25lcyB0aWVuZW4gcC12YWx1ZSBhbHRhbWVudGUgc2lnbmlmaWNhdGl2b3MuIEVsIHIyLCBvIHZhcmlhYmlsaWRhZCBleHBsaWNhZGEgcG9yIGVsIG1vZGVsbywgZXMgZGUgY2FzaSA0NyUuDQoNCmBgYHtyfQ0KZ2dwbG90KEJhc2Vjb21wX2ZpbHRyYWRhLCBhZXMoc3VyZmFjZV90b3RhbCwgcHJpY2UvMTAwMCkpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKw0KICBnZW9tX3BvaW50KHNpemU9MC4wNSkrDQogIGxhYnMoeD0iY2FudGlkYWQgZGUgYW1iaWVudGVzIiwgeT0iUHJlY2lvIChlbiBtaWxlcyBkZSBVU0QpIix0aXRsZSA9ICdNb2RlbG8gZ2VuZXJhbCBkZSByZWdyZXNpw7NuIGxpbmVhbCcsIHN1YnRpdGxlID0gJ1ByZWNpbyBkZSB2aXZpZW5kYXMgZW4gZnVuY2nDs24gZGUgc3Ugc3VwZXJmaWNpZScpICsNCiAgZ2dwdWJyOjpzdGF0X3JlZ2xpbmVfZXF1YXRpb24obWFwcGluZz1hZXMobGFiZWw9cGFzdGUoLi5lcS5sYWJlbC4uLC4uYWRqLnJyLmxhYmVsLi4sIHNlcD0ifn5+fiIpKSkrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KZ2dwbG90KEJhc2Vjb21wX2ZpbHRyYWRhLCBhZXMoc3VyZmFjZV90b3RhbCwgcHJpY2UvMTAwMCwgY29sb3VyID0gcHJvcGVydHlfdHlwZSkpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKw0KICBnZW9tX3BvaW50KHNpemU9MC4wOCkrDQogIGxhYnMoeD0iU3VwLiBUb3RhbCBlbiBNMiIsIHk9IlByZWNpbyAoZW4gbWlsZXMgZGUgVVNEKSIsdGl0bGUgPSAnTW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsIHBvciB0aXBvIGRlIHByb3BpZWRhZCcsIHN1YnRpdGxlID0gJ1ByZWNpbyBkZSB2aXZpZW5kYXMgZW4gZnVuY2nDs24gZGUgc3Ugc3VwZXJmaWNpZScpICsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICBnZ3B1YnI6OnN0YXRfcmVnbGluZV9lcXVhdGlvbihtYXBwaW5nPWFlcyhsYWJlbD1wYXN0ZSguLmVxLmxhYmVsLi4sLi5hZGoucnIubGFiZWwuLiwgc2VwPSJ+fn5+IikpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpKw0KICBmYWNldF93cmFwKH4gcHJvcGVydHlfdHlwZSwgbGFiZWxsZXIgPSAibGFiZWxfYm90aCIpDQpgYGANCg0KIyMgQ29uY2x1c2lvbmVzDQoNCkRlIGFjdWVyZG8gbG9zIHZhbG9yZXMgZGUgUiBjdWFkcmFkbywgcG9kZW1vcyBpbmZlcmlyIHF1ZSBlbnRyZSBsb3MgZG9zIG1vZGVsb3MsIGFxdWVsIGNvbiBsYSB2YXJpYWJsZSBtZXRyb3MgY3VhZHJhZG9zIGRlIHN1cGVyZmljaWUgdG90YWwgdGllbmUgdW5hIG1heW9yIGNhcGFjaWRhZCBkZSBleHBsaWNhciBsYSB2YXJpYWNpb25lcyBlbiBsYSB2YXJpYWJsZSBwcmVjaW8gZW4gY29tcGFyYWNpw7NuIGNvbiBlbCBtb2RlbG8gcXVlIHV0aWxpemEgbG9zIGFtYmllbnRlcy4gRW4gZXN0byBwdWVkZSBxdWUganVlZ3VlIHVuIHJvbCBsYSBtYXlvciByaWdpZGV6IGRlIGxhIHZhcmlhYmxlIGRpc2NyZXRhICJhbWJpZW50ZXMiIGVuIHJlbGFjacOzbiBhIGxhIG1heW9yIGZsZXhpYmlsaWRhZCBxdWUgcG9zZWUgbGEgdmFyaWFibGUgbWV0cm9zIGN1YWRyYWRvcyAoY29udGludWEpLiANClBvciBvdHJhIHBhcnRlLCBjYWJlIGRlc3RhY2FyIHF1ZSBhbCByZWFsaXphciBsYXMgcmVncmVzaW9uZXMgbGluZWFsZXMgc2Vnw7puIHRpcG8gZGUgcHJvcGllZGFkLCBsb3MgcGFyw6FtZXRyb3MgZGUgbGFzIHJlY3RhcyB2YXJpYW4gY29uc2lkZXJhYmxlbWVudGUuIEFzaW1pc21vLCBlbiBsb3MgY2Fzb3MgZGUgZGVwYXJ0YW1lbnRvcyB5IHBoIHNlIG9idHV2aWVyb24gbWF5b3JlcyBSMiBxdWUgZW4gbG9zIG1vZGVsb3MgZ2VuZXJhbGVzLCB0YW50byBtZWRpZG8gZW4gZnVuY2nDs24gZGUgbG9zIGFtYmllbnRlcyBjb21vIGRlIGxvcyBtZXRyb3MgY3VhZHJhZG9zIGRlIHN1cGVyZmljaWUgdG90YWwuDQoNCg0K