Alumno: Rossi, Santiago

Cargo las librerias

library(tidyverse)
library(knitr)
library(kableExtra)
library(ggplot2)
library(GGally)
library(ggthemes)

1.Preparacion de los datos (I)

Cargo el dataset

properati<-read.csv("ar_properties.csv", sep=",", encoding = "UTF-8")

El dataset de Properati cuenta información de avisos inmobiliarios para cuatro países. Entre las principales variables del datset se destacan: fecha de al aviso, longitud y latitud de la propiedad, localidad, barrio, tipo de propiedad, cantidad de habitaciones, metros cuadrados cubiertos y totales y precio.


str(properati)

Filtro variables seleccionadas: país (Argentina), ciudad (CABA), tipo dde operación (venta), tipo de propiedad y moneda de la operación (dólares).

properati<-properati %>% 
  filter(l1=="Argentina" & l2=="Capital Federal" &
                                  currency=="USD" & (property_type=="PH" | property_type=="Departamento" |
                                                     property_type=="Casa") & operation_type=="Venta") %>%
  select(id,l3,rooms,bedrooms,bathrooms,surface_total,surface_covered,price,property_type)
properati %>% 
  head() %>% 
  kable() %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"))

2.Analisis exploratorio (I)

2.a. Obtener la cantidad de valores unicos y de valores faltantes (NAs) para cada una de estas variables

Funciones para el cálculo de faltantes y valores únicos

sumo_na<-function(x){  sum(is.na(x))}
cant_unicos<-function(x){  length(unique(x))}

Cantidad de valores unicos (subíndice “cant_unicos”) y faltantes (subindice “cant_na”)

properati %>% summarise_all(list(cant_na = sumo_na, cant_unicos= cant_unicos)) %>% t()

2.b. Obtener la matriz de correlacion para las variables numericas. Pista: usen ‘complete.obs’ para poder omitir los valores faltantes.

properati %>%
  select(-id,-l3,-property_type) %>% 
  cor(., use="complete.obs", method="pearson")

3. Preparacion de los datos (II)

Elimino variable bedrooms por tener una proporción grande de faltantes y tener una elevada correlación con rooms. Asimismo, me quedo con aquellos registros completos.

properati<-properati %>% select(-bedrooms) %>% filter(complete.cases(.))

4. Analisis exploratorios (II)

4.a.Obtener estadísticas descriptivas para la variable precio (cuartiles, promedio, minimo y maximo) y realizar un histograma de la variable

Estadisticas descriptivas de la variable precio:

summary(properati$price)

Los precios presentan una distribución log-normal

ggplot(properati, aes(x = price)) + geom_histogram(bins = 40, col="#4d4d4d", fill="#d8b365")+theme_tufte(base_size = 15)+ggtitle("Distribución de precios de inmuebles")+xlab("Precio (USD)")+ylab("Frecuencia")

A continuación se presenta el box-plot de los precios por tipo de propiedad. Para facilitar la visualización se consideró un valor máximo de USD 950 mil. De observar el gráfico se desprende que: - las casas tienen una mayor dispersión de precios que los otros tipos de vivienda. - las casas son en promedio más caras que los PH y los departamentos. - Los PHs son en promedio más caros que os departamentos.

ggplot(properati, aes(y = price,fill=property_type)) + geom_boxplot()+theme_tufte(base_size = 15) + labs(title = "Precios de inmuebles por tipo de vivienda", subtitle = "en dólares")+xlab("")+ylab("Precios (USD)")+labs(fill = "Tipo de propiedad")+
theme(plot.title = element_text(size = 14, family = "Tahoma", face = "bold"),
      panel.border = element_rect(colour = "black", fill = NA, size = .5),
      legend.position = "bottom")
  
#geom_boxplot(outlier.shape = NA)
properati %>%
  select(-id,-l3,property_type) %>% 

ggpairs(., 
        title = "Matriz de correlaciones",
        mapping = aes(colour= property_type))

5. Outliers

Eliminar los outliers de la variable precio con algún criterio que elijan: puede ser por valores de corte, eliminar el x% a izquierda y derecha,etc.


lim_sup_precio <- function(data, tipo_vivienda){data %>% filter(property_type==tipo_vivienda) %>% summarise( l_sup =  quantile(price,probs = 0.75) +IQR(price) ) }

lim_inf_precio <- function(data, tipo_vivienda){data %>% filter(property_type==tipo_vivienda) %>% summarise( l_sup =  quantile(price,probs = 0.25) -1.5*IQR(price) ) }

properati <- properati %>% mutate(outlier = ifelse( (property_type=="Casa" & price > lim_sup_precio(.,"Casa")[[1]]) |
                                       (property_type=="Casa" & price < lim_inf_precio(.,"Casa")[[1]]) |
                                       (property_type=="PH" & price > lim_sup_precio(.,"PH")[[1]]) |
                                       (property_type=="PH" & price < lim_inf_precio(.,"PH")[[1]]) | 
                                       (property_type=="Departamento" & price > lim_sup_precio(.,"Departamento")[[1]]) |
                                       (property_type=="Departamento" & price < lim_inf_precio(.,"Departamento")[[1]]),1,0 ))

properati_1<-properati %>% filter(outlier==0)

glue::glue("Proporción de outliers = ", sum(properati$outlier)/nrow(properati))

6.Analisis exploratorios (III)


ggplot(properati_1, aes(x = price)) + geom_histogram(bins = 40, col="#4d4d4d", fill="#d8b365")+theme_tufte(base_size = 15)+ggtitle("Distribución de precios de inmuebles")+xlab("Precio (USD)")+ylab("Frecuencia")
ggplot(properati_1, aes(y = price,fill=property_type)) + geom_boxplot()+theme_tufte(base_size = 15) + labs(title = "Precios de inmuebles por tipo de vivienda", subtitle = "en dólares")+xlab("")+ylab("Precios (USD)")+ylim(0,9.5e+05)+labs(fill = "Tipo de propiedad")+
theme(plot.title = element_text(size = 14, family = "Tahoma", face = "bold"),
      panel.border = element_rect(colour = "black", fill = NA, size = .5),
      legend.position = "bottom")
  
properati_1 %>%
  select(-id,-l3,property_type) %>% 

ggpairs(., 
        title = "Matriz de correlaciones",
        mapping = aes(colour= property_type))

7.Modelo lineal

Realizar un modelo lineal simple para explicar el precio en función de las habitaciones (rooms) y otro modelo que explique el precio en función de la superficie total (surface_total)

Usar la función summary() para obtener informacion de ambos modelos. Explicar los valores de los coeficientes estimados. ¿Cuál modelo usarían para predecir el precio? ¿Por qué?


modelo_rooms<-lm(data = properati_1,formula = price ~ rooms)
summary(modelo_rooms)

modelo_surface<-lm(data = properati_1, price ~ surface_total)
summary(modelo_surface)

Cuál modelo usarían para predecir el precio? ¿Por qué?

por cada habitacion el precio aumenta 47 mil dolares.

por cada m2 el precio aumenta 5 dolares. me parece que se rompió por los outliers

ggplot(properati_1,mapping = aes(x=price, y = rooms))+geom_point()+geom_smooth(method = "lm")+ labs(title = "Cantidad de habitaciones y precios de inmuebles", subtitle = "")+xlab("Precio (USD)")+ylab("Cat. Habitaciones")+theme_bw()+
theme(plot.title = element_text(size = 14, face = "bold"),
      panel.border = element_rect(colour = "black", fill = NA, size = .5))
  
ggplot(properati_1,mapping = aes(x=price, y = surface_total))+geom_point()+geom_smooth(method = "lm")+ labs(title = "Superficie total y precios de inmuebles", subtitle = "")+xlab("Precio (USD)")+ylab("Superficie (m2)")+theme_bw()+
theme(plot.title = element_text(size = 14, face = "bold"),
      panel.border = element_rect(colour = "black", fill = NA, size = .5))
  
LS0tDQp0aXRsZTogIkVuZm9xdWUgZXN0YWTDrXN0aWNvIGRlbCBhcHJlbmRpemFqZSAtIFRyYWJham8gUHLDoWN0aW8gTsK6MSAiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojI0FsdW1ubzogUm9zc2ksIFNhbnRpYWdvIA0KDQpDYXJnbyBsYXMgbGlicmVyaWFzDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoR0dhbGx5KQ0KbGlicmFyeShnZ3RoZW1lcykNCmBgYA0KDQojMS5QcmVwYXJhY2lvbiBkZSBsb3MgZGF0b3MgKEkpIA0KDQpDYXJnbyBlbCBkYXRhc2V0DQoNCmBgYHtyfQ0KcHJvcGVyYXRpPC1yZWFkLmNzdigiYXJfcHJvcGVydGllcy5jc3YiLCBzZXA9IiwiLCBlbmNvZGluZyA9ICJVVEYtOCIpDQoNCmBgYA0KDQoNCkVsIGRhdGFzZXQgZGUgUHJvcGVyYXRpIGN1ZW50YSBpbmZvcm1hY2nDs24gZGUgYXZpc29zIGlubW9iaWxpYXJpb3MgcGFyYSBjdWF0cm8gcGHDrXNlcy4gRW50cmUgbGFzIHByaW5jaXBhbGVzIHZhcmlhYmxlcyBkZWwgZGF0c2V0IHNlIGRlc3RhY2FuOiBmZWNoYSBkZSBhbCBhdmlzbywgbG9uZ2l0dWQgeSBsYXRpdHVkIGRlIGxhIHByb3BpZWRhZCwgbG9jYWxpZGFkLCBiYXJyaW8sIHRpcG8gZGUgcHJvcGllZGFkLCBjYW50aWRhZCBkZSBoYWJpdGFjaW9uZXMsIG1ldHJvcyBjdWFkcmFkb3MgY3ViaWVydG9zIHkgdG90YWxlcyB5IHByZWNpby4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQoNCnN0cihwcm9wZXJhdGkpDQoNCmBgYA0KIA0KRmlsdHJvIHZhcmlhYmxlcyBzZWxlY2Npb25hZGFzOiBwYcOtcyAoQXJnZW50aW5hKSwgY2l1ZGFkIChDQUJBKSwgdGlwbyBkZGUgb3BlcmFjacOzbiAodmVudGEpLCB0aXBvIGRlIHByb3BpZWRhZCB5IG1vbmVkYSBkZSBsYSBvcGVyYWNpw7NuIChkw7NsYXJlcykuDQoNCmBgYHtyfQ0KcHJvcGVyYXRpPC1wcm9wZXJhdGkgJT4lIA0KICBmaWx0ZXIobDE9PSJBcmdlbnRpbmEiICYgbDI9PSJDYXBpdGFsIEZlZGVyYWwiICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW5jeT09IlVTRCIgJiAocHJvcGVydHlfdHlwZT09IlBIIiB8IHByb3BlcnR5X3R5cGU9PSJEZXBhcnRhbWVudG8iIHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydHlfdHlwZT09IkNhc2EiKSAmIG9wZXJhdGlvbl90eXBlPT0iVmVudGEiKSAlPiUNCiAgc2VsZWN0KGlkLGwzLHJvb21zLGJlZHJvb21zLGJhdGhyb29tcyxzdXJmYWNlX3RvdGFsLHN1cmZhY2VfY292ZXJlZCxwcmljZSxwcm9wZXJ0eV90eXBlKQ0KDQpgYGANCmBgYHtyfQ0KcHJvcGVyYXRpICU+JSANCiAgaGVhZCgpICU+JSANCiAga2FibGUoKSAlPiUgDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIikpDQpgYGANCg0KIzIuQW5hbGlzaXMgZXhwbG9yYXRvcmlvIChJKSANCg0KIyMyLmEuIE9idGVuZXIgbGEgY2FudGlkYWQgZGUgdmFsb3JlcyB1bmljb3MgeSBkZSB2YWxvcmVzIGZhbHRhbnRlcyAoTkFzKSBwYXJhIGNhZGEgdW5hIGRlIGVzdGFzIHZhcmlhYmxlcw0KRnVuY2lvbmVzIHBhcmEgZWwgY8OhbGN1bG8gZGUgZmFsdGFudGVzIHkgdmFsb3JlcyDDum5pY29zDQpgYGB7cn0NCnN1bW9fbmE8LWZ1bmN0aW9uKHgpeyAgc3VtKGlzLm5hKHgpKX0NCmNhbnRfdW5pY29zPC1mdW5jdGlvbih4KXsgIGxlbmd0aCh1bmlxdWUoeCkpfQ0KYGBgDQoNCkNhbnRpZGFkIGRlIHZhbG9yZXMgdW5pY29zIChzdWLDrW5kaWNlICJjYW50X3VuaWNvcyIpIHkgZmFsdGFudGVzIChzdWJpbmRpY2UgImNhbnRfbmEiKQ0KYGBge3J9DQpwcm9wZXJhdGkgJT4lIHN1bW1hcmlzZV9hbGwobGlzdChjYW50X25hID0gc3Vtb19uYSwgY2FudF91bmljb3M9IGNhbnRfdW5pY29zKSkgJT4lIHQoKQ0KDQoNCmBgYA0KIyMyLmIuIE9idGVuZXIgbGEgbWF0cml6IGRlIGNvcnJlbGFjaW9uIHBhcmEgbGFzIHZhcmlhYmxlcyBudW1lcmljYXMuIFBpc3RhOiB1c2VuIOKAmGNvbXBsZXRlLm9ic+KAmSBwYXJhIHBvZGVyIG9taXRpciBsb3MgdmFsb3JlcyBmYWx0YW50ZXMuDQpgYGB7cn0NCnByb3BlcmF0aSAlPiUNCiAgc2VsZWN0KC1pZCwtbDMsLXByb3BlcnR5X3R5cGUpICU+JSANCiAgY29yKC4sIHVzZT0iY29tcGxldGUub2JzIiwgbWV0aG9kPSJwZWFyc29uIikNCmBgYCAgICAgIA0KDQoNCiMzLiBQcmVwYXJhY2lvbiBkZSBsb3MgZGF0b3MgKElJKQ0KRWxpbWlubyB2YXJpYWJsZSBgYmVkcm9vbXNgIHBvciB0ZW5lciB1bmEgcHJvcG9yY2nDs24gZ3JhbmRlIGRlIGZhbHRhbnRlcyB5IHRlbmVyIHVuYSBlbGV2YWRhIGNvcnJlbGFjacOzbiBjb24gYHJvb21zYC4gQXNpbWlzbW8sIG1lIHF1ZWRvIGNvbiBhcXVlbGxvcyByZWdpc3Ryb3MgY29tcGxldG9zLg0KDQpgYGB7cn0NCnByb3BlcmF0aTwtcHJvcGVyYXRpICU+JSBzZWxlY3QoLWJlZHJvb21zKSAlPiUgZmlsdGVyKGNvbXBsZXRlLmNhc2VzKC4pKQ0KYGBgICANCg0KIzQuIEFuYWxpc2lzIGV4cGxvcmF0b3Jpb3MgKElJKQ0KDQojIyM0LmEuT2J0ZW5lciBlc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcyBwYXJhIGxhIHZhcmlhYmxlIHByZWNpbyAoY3VhcnRpbGVzLCBwcm9tZWRpbywgbWluaW1vIHkgbWF4aW1vKSB5IHJlYWxpemFyIHVuIGhpc3RvZ3JhbWEgZGUgbGEgdmFyaWFibGUNCg0KDQpFc3RhZGlzdGljYXMgZGVzY3JpcHRpdmFzIGRlIGxhIHZhcmlhYmxlICoqcHJlY2lvKio6DQoNCmBgYHtyfQ0Kc3VtbWFyeShwcm9wZXJhdGkkcHJpY2UpDQpgYGANCkxvcyBwcmVjaW9zIHByZXNlbnRhbiB1bmEgIGRpc3RyaWJ1Y2nDs24gbG9nLW5vcm1hbA0KDQpgYGB7cn0NCmdncGxvdChwcm9wZXJhdGksIGFlcyh4ID0gcHJpY2UpKSArIGdlb21faGlzdG9ncmFtKGJpbnMgPSA0MCwgY29sPSIjNGQ0ZDRkIiwgZmlsbD0iI2Q4YjM2NSIpK3RoZW1lX3R1ZnRlKGJhc2Vfc2l6ZSA9IDE1KStnZ3RpdGxlKCJEaXN0cmlidWNpw7NuIGRlIHByZWNpb3MgZGUgaW5tdWVibGVzIikreGxhYigiUHJlY2lvIChVU0QpIikreWxhYigiRnJlY3VlbmNpYSIpDQpgYGANCg0KQSBjb250aW51YWNpw7NuIHNlIHByZXNlbnRhIGVsIGJveC1wbG90IGRlIGxvcyBwcmVjaW9zIHBvciB0aXBvIGRlIHByb3BpZWRhZC4gUGFyYSBmYWNpbGl0YXIgbGEgdmlzdWFsaXphY2nDs24gc2UgY29uc2lkZXLDsyB1biB2YWxvciBtw6F4aW1vIGRlIFVTRCA5NTAgbWlsLiBEZSBvYnNlcnZhciBlbCBncsOhZmljbyBzZSBkZXNwcmVuZGUgcXVlOg0KLSBsYXMgY2FzYXMgdGllbmVuIHVuYSBtYXlvciBkaXNwZXJzacOzbiBkZSBwcmVjaW9zIHF1ZSBsb3Mgb3Ryb3MgdGlwb3MgZGUgdml2aWVuZGEuDQotIGxhcyBjYXNhcyBzb24gZW4gcHJvbWVkaW8gbcOhcyBjYXJhcyBxdWUgbG9zIFBIIHkgbG9zIGRlcGFydGFtZW50b3MuDQotIExvcyBQSHMgc29uIGVuIHByb21lZGlvIG3DoXMgY2Fyb3MgcXVlIG9zIGRlcGFydGFtZW50b3MuDQoNCg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCmdncGxvdChwcm9wZXJhdGksIGFlcyh5ID0gcHJpY2UsZmlsbD1wcm9wZXJ0eV90eXBlKSkgKyBnZW9tX2JveHBsb3QoKSt0aGVtZV90dWZ0ZShiYXNlX3NpemUgPSAxNSkgKyBsYWJzKHRpdGxlID0gIlByZWNpb3MgZGUgaW5tdWVibGVzIHBvciB0aXBvIGRlIHZpdmllbmRhIiwgc3VidGl0bGUgPSAiZW4gZMOzbGFyZXMiKSt4bGFiKCIiKSt5bGFiKCJQcmVjaW9zIChVU0QpIikrbGFicyhmaWxsID0gIlRpcG8gZGUgcHJvcGllZGFkIikrDQp0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFtaWx5ID0gIlRhaG9tYSIsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSBOQSwgc2l6ZSA9IC41KSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQ0KICANCiNnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKQ0KYGBgDQoNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQpwcm9wZXJhdGkgJT4lDQogIHNlbGVjdCgtaWQsLWwzLHByb3BlcnR5X3R5cGUpICU+JSANCg0KZ2dwYWlycyguLCANCiAgICAgICAgdGl0bGUgPSAiTWF0cml6IGRlIGNvcnJlbGFjaW9uZXMiLA0KICAgICAgICBtYXBwaW5nID0gYWVzKGNvbG91cj0gcHJvcGVydHlfdHlwZSkpDQpgYGANCg0KDQojNS4gT3V0bGllcnMNCg0KRWxpbWluYXIgbG9zIG91dGxpZXJzIGRlIGxhIHZhcmlhYmxlIHByZWNpbyBjb24gYWxnw7puIGNyaXRlcmlvIHF1ZSBlbGlqYW46IHB1ZWRlIHNlciBwb3IgdmFsb3JlcyBkZSBjb3J0ZSwgZWxpbWluYXIgZWwgeCUgYSBpenF1aWVyZGEgeSBkZXJlY2hhLGV0Yy4NCg0KYGBge3J9DQoNCmxpbV9zdXBfcHJlY2lvIDwtIGZ1bmN0aW9uKGRhdGEsIHRpcG9fdml2aWVuZGEpe2RhdGEgJT4lIGZpbHRlcihwcm9wZXJ0eV90eXBlPT10aXBvX3ZpdmllbmRhKSAlPiUgc3VtbWFyaXNlKCBsX3N1cCA9ICBxdWFudGlsZShwcmljZSxwcm9icyA9IDAuNzUpICtJUVIocHJpY2UpICkgfQ0KDQpsaW1faW5mX3ByZWNpbyA8LSBmdW5jdGlvbihkYXRhLCB0aXBvX3ZpdmllbmRhKXtkYXRhICU+JSBmaWx0ZXIocHJvcGVydHlfdHlwZT09dGlwb192aXZpZW5kYSkgJT4lIHN1bW1hcmlzZSggbF9zdXAgPSAgcXVhbnRpbGUocHJpY2UscHJvYnMgPSAwLjI1KSAtMS41KklRUihwcmljZSkgKSB9DQoNCg0KYGBgDQoNCmBgYHtyfQ0KDQpwcm9wZXJhdGkgPC0gcHJvcGVyYXRpICU+JSBtdXRhdGUob3V0bGllciA9IGlmZWxzZSggKHByb3BlcnR5X3R5cGU9PSJDYXNhIiAmIHByaWNlID4gbGltX3N1cF9wcmVjaW8oLiwiQ2FzYSIpW1sxXV0pIHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwcm9wZXJ0eV90eXBlPT0iQ2FzYSIgJiBwcmljZSA8IGxpbV9pbmZfcHJlY2lvKC4sIkNhc2EiKVtbMV1dKSB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocHJvcGVydHlfdHlwZT09IlBIIiAmIHByaWNlID4gbGltX3N1cF9wcmVjaW8oLiwiUEgiKVtbMV1dKSB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocHJvcGVydHlfdHlwZT09IlBIIiAmIHByaWNlIDwgbGltX2luZl9wcmVjaW8oLiwiUEgiKVtbMV1dKSB8IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHByb3BlcnR5X3R5cGU9PSJEZXBhcnRhbWVudG8iICYgcHJpY2UgPiBsaW1fc3VwX3ByZWNpbyguLCJEZXBhcnRhbWVudG8iKVtbMV1dKSB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocHJvcGVydHlfdHlwZT09IkRlcGFydGFtZW50byIgJiBwcmljZSA8IGxpbV9pbmZfcHJlY2lvKC4sIkRlcGFydGFtZW50byIpW1sxXV0pLDEsMCApKQ0KDQpwcm9wZXJhdGlfMTwtcHJvcGVyYXRpICU+JSBmaWx0ZXIob3V0bGllcj09MCkNCg0KZ2x1ZTo6Z2x1ZSgiUHJvcG9yY2nDs24gZGUgb3V0bGllcnMgPSAiLCBzdW0ocHJvcGVyYXRpJG91dGxpZXIpL25yb3cocHJvcGVyYXRpKSkNCg0KYGBgDQoNCiM2LkFuYWxpc2lzIGV4cGxvcmF0b3Jpb3MgKElJSSkNCmBgYHtyfQ0KDQpnZ3Bsb3QocHJvcGVyYXRpXzEsIGFlcyh4ID0gcHJpY2UpKSArIGdlb21faGlzdG9ncmFtKGJpbnMgPSA0MCwgY29sPSIjNGQ0ZDRkIiwgZmlsbD0iI2Q4YjM2NSIpK3RoZW1lX3R1ZnRlKGJhc2Vfc2l6ZSA9IDE1KStnZ3RpdGxlKCJEaXN0cmlidWNpw7NuIGRlIHByZWNpb3MgZGUgaW5tdWVibGVzIikreGxhYigiUHJlY2lvIChVU0QpIikreWxhYigiRnJlY3VlbmNpYSIpDQpgYGANCg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCmdncGxvdChwcm9wZXJhdGlfMSwgYWVzKHkgPSBwcmljZSxmaWxsPXByb3BlcnR5X3R5cGUpKSArIGdlb21fYm94cGxvdCgpK3RoZW1lX3R1ZnRlKGJhc2Vfc2l6ZSA9IDE1KSArIGxhYnModGl0bGUgPSAiUHJlY2lvcyBkZSBpbm11ZWJsZXMgcG9yIHRpcG8gZGUgdml2aWVuZGEiLCBzdWJ0aXRsZSA9ICJlbiBkw7NsYXJlcyIpK3hsYWIoIiIpK3lsYWIoIlByZWNpb3MgKFVTRCkiKSt5bGltKDAsOS41ZSswNSkrbGFicyhmaWxsID0gIlRpcG8gZGUgcHJvcGllZGFkIikrDQp0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFtaWx5ID0gIlRhaG9tYSIsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSBOQSwgc2l6ZSA9IC41KSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQ0KICANCmBgYA0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCnByb3BlcmF0aV8xICU+JQ0KICBzZWxlY3QoLWlkLC1sMyxwcm9wZXJ0eV90eXBlKSAlPiUgDQoNCmdncGFpcnMoLiwgDQogICAgICAgIHRpdGxlID0gIk1hdHJpeiBkZSBjb3JyZWxhY2lvbmVzIiwNCiAgICAgICAgbWFwcGluZyA9IGFlcyhjb2xvdXI9IHByb3BlcnR5X3R5cGUpKQ0KYGBgDQoNCg0KIzcuTW9kZWxvIGxpbmVhbA0KDQpSZWFsaXphciB1biBtb2RlbG8gbGluZWFsIHNpbXBsZSBwYXJhIGV4cGxpY2FyIGVsIHByZWNpbyBlbiBmdW5jacOzbiBkZSBsYXMgaGFiaXRhY2lvbmVzIChyb29tcykgeSBvdHJvIG1vZGVsbyBxdWUgZXhwbGlxdWUgZWwgcHJlY2lvIGVuIGZ1bmNpw7NuIGRlIGxhIHN1cGVyZmljaWUgdG90YWwgKHN1cmZhY2VfdG90YWwpDQoNClVzYXIgbGEgZnVuY2nDs24gc3VtbWFyeSgpIHBhcmEgb2J0ZW5lciBpbmZvcm1hY2lvbiBkZSBhbWJvcyBtb2RlbG9zLiBFeHBsaWNhciBsb3MgdmFsb3JlcyBkZSBsb3MgY29lZmljaWVudGVzIGVzdGltYWRvcy4NCiAgICDCv0N1w6FsIG1vZGVsbyB1c2Fyw61hbiBwYXJhIHByZWRlY2lyIGVsIHByZWNpbz8gwr9Qb3IgcXXDqT8NCg0KDQpgYGB7cn0NCg0KbW9kZWxvX3Jvb21zPC1sbShkYXRhID0gcHJvcGVyYXRpXzEsZm9ybXVsYSA9IHByaWNlIH4gcm9vbXMpDQpzdW1tYXJ5KG1vZGVsb19yb29tcykNCg0KbW9kZWxvX3N1cmZhY2U8LWxtKGRhdGEgPSBwcm9wZXJhdGlfMSwgcHJpY2UgfiBzdXJmYWNlX3RvdGFsKQ0Kc3VtbWFyeShtb2RlbG9fc3VyZmFjZSkNCg0KDQoNCmBgYA0KDQpDdcOhbCBtb2RlbG8gdXNhcsOtYW4gcGFyYSBwcmVkZWNpciBlbCBwcmVjaW8/IMK/UG9yIHF1w6k/DQoNCnBvciBjYWRhIGhhYml0YWNpb24gZWwgcHJlY2lvIGF1bWVudGEgNDcgbWlsIGRvbGFyZXMuDQoNCnBvciBjYWRhIG0yIGVsIHByZWNpbyBhdW1lbnRhIDUgZG9sYXJlcy4gbWUgcGFyZWNlIHF1ZSBzZSByb21wacOzIHBvciBsb3Mgb3V0bGllcnMNCg0KYGBge3J9DQpnZ3Bsb3QocHJvcGVyYXRpXzEsbWFwcGluZyA9IGFlcyh4PXByaWNlLCB5ID0gcm9vbXMpKStnZW9tX3BvaW50KCkrZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikrIGxhYnModGl0bGUgPSAiQ2FudGlkYWQgZGUgaGFiaXRhY2lvbmVzIHkgcHJlY2lvcyBkZSBpbm11ZWJsZXMiLCBzdWJ0aXRsZSA9ICIiKSt4bGFiKCJQcmVjaW8gKFVTRCkiKSt5bGFiKCJDYXQuIEhhYml0YWNpb25lcyIpK3RoZW1lX2J3KCkrDQp0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksDQogICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIiwgZmlsbCA9IE5BLCBzaXplID0gLjUpKQ0KICANCmBgYA0KDQpgYGB7cn0NCmdncGxvdChwcm9wZXJhdGlfMSxtYXBwaW5nID0gYWVzKHg9cHJpY2UsIHkgPSBzdXJmYWNlX3RvdGFsKSkrZ2VvbV9wb2ludCgpK2dlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpKyBsYWJzKHRpdGxlID0gIlN1cGVyZmljaWUgdG90YWwgeSBwcmVjaW9zIGRlIGlubXVlYmxlcyIsIHN1YnRpdGxlID0gIiIpK3hsYWIoIlByZWNpbyAoVVNEKSIpK3lsYWIoIlN1cGVyZmljaWUgKG0yKSIpK3RoZW1lX2J3KCkrDQp0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksDQogICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIiwgZmlsbCA9IE5BLCBzaXplID0gLjUpKQ0KICANCmBgYA0KDQoNCg0KDQoNCg==