Trabajo sobre un dataset de Properati Argentina*

          used (Mb) gc trigger (Mb) max used (Mb)
Ncells  776312 41.5    1234088   66  1234088   66
Vcells 1770271 13.6    8388608   64  8388570   64
          used (Mb) gc trigger (Mb) max used (Mb)
Ncells  776273 41.5    1234088   66  1234088   66
Vcells 1770206 13.6    8388608   64  8388570   64
          used (Mb) gc trigger (Mb) max used (Mb)
Ncells  776340 41.5    1234088   66  1234088   66
Vcells 1770272 13.6    8388608   64  8388570   64
str(prop)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   45904 obs. of  8 variables:
 $ id             : chr  "AfdcsqUSelai1ofCAq2B0Q==" "ESzybdH7YU2uIU1/kHtRGw==" "r22OfzZ3kXooSPoE5HMuZQ==" "atZQXVtyfG7+OiX6gYY3lA==" ...
 $ l3             : Factor w/ 57 levels "Abasto","Agronomía",..: 43 25 3 3 3 3 3 3 3 3 ...
 $ rooms          : num  3 1 1 1 1 1 1 1 1 1 ...
 $ bathrooms      : num  2 1 1 1 1 1 1 1 1 1 ...
 $ surface_total  : num  95 44 40 49 40 40 40 49 40 40 ...
 $ surface_covered: num  69 38 37 44 37 37 37 44 37 37 ...
 $ price          : num  199900 147000 92294 115000 77000 ...
 $ property_type  : Factor w/ 3 levels "Casa","Departamento",..: 1 2 2 2 2 2 2 2 2 2 ...

1 Regresión lineal múltiple

a. Crear un modelo para predecir el precio con todas las covariables.


\(\begin{aligned}price = \beta_{0}+\beta_{1}.l3+\beta_{2}.rooms+\beta_{3}.bathrooms\\+\beta_{4}.surface\_total+\beta_{5}.surface\_covered+\beta_{6}.property\_type\end{aligned}\)

Las variables continuas son rooms cantidad de habitaciones, bathrooms cantidad de baños, surface_total (superficie total) y surface_covered superficie cubierta

Las variables categoricas en cambio son property_type Tipo de propiedad, “Casa”, “Ph” y “Deparatamento” y por otro lado l3 que representa las zonas donde se ubican dichas propiedades. Para generar el modelo lineal debo transformar las variables categoricas a variables dummy.

anova(prop_lm1)
Analysis of Variance Table

Response: price
                   Df     Sum Sq    Mean Sq  F value    Pr(>F)    
l3                 56 1.8443e+14 3.2934e+12   742.95 < 2.2e-16 ***
rooms               1 3.0174e+14 3.0174e+14 68067.54 < 2.2e-16 ***
bathrooms           1 9.7588e+13 9.7588e+13 22014.36 < 2.2e-16 ***
surface_total       1 9.6762e+13 9.6762e+13 21827.91 < 2.2e-16 ***
surface_covered     1 1.2667e+13 1.2667e+13  2857.40 < 2.2e-16 ***
property_type       2 1.2491e+13 6.2453e+12  1408.85 < 2.2e-16 ***
Residuals       45841 2.0321e+14 4.4329e+09                       
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Realizando el test de Anova puedo verificar que ambos tipos de variables son significativas y por lo tanto puedo analizar en particular cada coeficiente en detalle

summary(prop_lm1)

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

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 ***
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 ***
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 ***
---
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
b. Analizar los resultados del modelo.

i. Interpretación de los coeficientes estimados.

Analizando el valor del estadístico F, se puede rechazar la hipotesis nula. Por otro lado el coeficiente R cuadrado ajustado determina que el 77% de la variabilidad del precio está explicada por las variables.

En el caso de l3 la categoría basal es Abasto y para property_type es Casa. En este modelo hay coeficientes estimados que no resultan significativos, cómo Almagro y Montecastro. Por otro lado existen barrios que tienen un coeficiente negativo, es decir que están por debajo del precio medio de referencia. En el caso de property_type el precio de los PH o Departamentos tienen una influencia positiva respecto a la variable control “Casa”

Analizando, coeficiente de la variable surface_covered se espera que un aumento del metro cuadrado aumente 1457usd el precio de la propiedad.

Por otro lado, una manera de buscar departamentos es según la cantidad de habitaciones, es decir, por la variable rooms. Parecería contraintuitivo el coeficiente del modelo que determina que frente al resto de las variables constantes, una habitación adicional disminuye el precio esperado en 3961usd. Sería interesante agregar a este dataset la antiguedad de la propiedad, para entender si hay alguna correlación entre la variable cantidad de habitaciones y antiguedad de la propiedad.

En el caso de los coeficientes de las variables dummy indican cómo se modifica la variable respuesta respecto a la basal fijando las demás covariables. cuando dicha variable corresponde a cada uno de sus niveles. En el caso de la variable categórica property_type se obtiene que al tratarse de departamentos, el precio medio aumentará 92653.32 USD con respecto a su variable de referencia, casa. Para la variable l3 el nivel de referencia es abasto, lo que significa que por ejemplo, una propiedad ubicada en el barrio de Belgrano presentará un precio medio esperado mayor de 69648.12USD con respecto a una en la zona Abasto. En cambio una propiedad ubicada en Villa Lugano tendrá un precio medio esperado 83039.18 USD menor

Tabla 1: Dummies de las zonas.

Tabla 2: Dummies para el tipo de propiedad.

ii. ¿Qué observan respecto de la significatividad de las variables dummy?
Para evaluar las variables dummies hay que realizar test de hipotesis sobre cada coeficiente.

Tabla 3: coeficientes de lsa variables dummies.

Frente a los resultados del test de hipotesis observados en la tabla 3 no podemos rechazar la hipotesis nula y los coeficientes son distintos de cero. Sin embargo podemos hacer un gran diferencia entre aproperty_type y l3. Muchos barrios no tienen un coeficiente muy alto y sin embargo tenemos significativdad para utilizarlos como variables explicativas pueden no tener tanta información.

iii. Medidas de evaluación del modelo.

Antes de analizar la significativdad de cada variable hay que mirar el resultado del test F que envalúa la significatividad conjunta de las variables para explicar a la respuesta. Si la observamos vemos que es un valor alto (2568 on 62) y el pvalor es un valor ceracno a cero, por lo tanto las variables son significativas de forma conjunta a nivel alfa 0,05. .
Luego observamos el coeficiente R ajustado en un valor aprox de 0.77 considerando al modelo cómo adecuado. Dicho coeficiente representa la proporción por la cual la variable predicha es explicada por nuestro modelo.


c. ¿Qué es preferible tener para vender?:

i. un departamento de 120 mts cuadrados cubiertos en Abasto, con 3 dormitorios y 2 baños.
ii. Un PH en balvanera, con 80 mts cuadrados cubiertos, 20 mts cuadrados no cubiertos, 2 dormitorios y 3 baños.

# Predicción para i
predict(prop_lm1, data.frame(l3="Abasto",rooms=3,bathrooms=2,surface_covered=120,property_type="Departamento", surface_total=120))
       1 
324596.4 
# Predicción para ii
predict(prop_lm1, data.frame(l3="Balvanera",rooms=2,bathrooms=3,surface_covered=80,property_type="PH", surface_total=100))
       1 
215267.6 

Dado los valores de mts cuadrados, dormitorios y baños. un departamento del barrio Abasto tendrán un precio medio mayor que uno de Balvanera, por lo tanto es preferible tener la opción i para vender


d. Realizar un modelo sin la covariable l3 e interpretar sus resultados (todas las partes de la salida que consideren relevantes).

summary(prop_lm2)

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

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

Lo primero a analizar es el estadístico F y el p valor, en el cual analizamos que el F es aún mayor que el anterior y el valor p sigue en un valor cercano a cero. Luego vemos en particular cada coeficiente, tanto las variables continuas como las categoricas son significativas. El R ajustado por otro lado disminuyo de 0.77 a 0.68 en el modelo nuevo.

e. ¿Cuál es el modelo que mejor explica la variabilidad del precio?
El primer modelo que posee la variable de la zona posee un mayor r cuadrado ajustado, por lo tanto explica mejor la variabilidad del precio que el segundo modelo.

2 Creación de variables

a. En el ejercicio anterior encontramos que algunos barrios son significativos, aunque no todos. Crear una nueva variable barrios que divida a los barrios según el precio por metro cuadrado promedio de las propiedades en ellos, con los grupos c(‘alto’, ‘medio’, ‘bajo’). Realizar un análisis exploratorio para definir los puntos de corte de la nueva variable y explicar los criterios utilizados en la construcción de la misma.

Se observa en el histograma 1 y el boxplot 1, que la mayoría de los casos se encuentra concentrados alrededor de 2500USD por metro cuadrado. Por lo tanto determino que los valores Por bajo este valor serán el bin “Bajo”, Medio tomaré cómo límite hasta el tercer cuartil 3207 y por encima al valor alto.

b. Calcular el modelo que predice el precio en función de las nuevas covariables e interpretar sus resultados (todas las partes de la salida que consideren relevantes).

glimpse(prop)
Observations: 45,904
Variables: 11
Groups: l3 [57]
$ id              <chr> "AfdcsqUSelai1ofCAq2B0Q==", "ESzybdH7YU2uIU1/kHtRGw=...
$ l3              <fct> Velez Sarsfield, Nuñez, Almagro, Almagro, Almagro, A...
$ rooms           <dbl> 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2...
$ bathrooms       <dbl> 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1...
$ surface_total   <dbl> 95, 44, 40, 49, 40, 40, 40, 49, 40, 40, 40, 32, 40, ...
$ surface_covered <dbl> 69, 38, 37, 44, 37, 37, 37, 44, 37, 37, 37, 30, 34, ...
$ price           <dbl> 199900, 147000, 92294, 115000, 77000, 88900, 88798, ...
$ property_type   <fct> Casa, Departamento, Departamento, Departamento, Depa...
$ price_mts       <dbl> 2104.211, 3340.909, 2307.350, 2346.939, 1925.000, 22...
$ mean_price      <dbl> 1831.980, 3212.144, 2472.049, 2472.049, 2472.049, 24...
$ barrios         <fct> bajo, alto, medio, medio, medio, medio, medio, medio...
summary(prop_lm3)

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

Residuals:
    Min      1Q  Median      3Q     Max 
-427740  -35811   -5227   25355  681886 

Coefficients:
                           Estimate Std. Error t value Pr(>|t|)    
(Intercept)               -42011.99    2603.42  -16.14   <2e-16 ***
barriosbajo               -98160.19     993.03  -98.85   <2e-16 ***
barriosmedio              -62104.73     758.61  -81.87   <2e-16 ***
rooms                      -7631.29     467.91  -16.31   <2e-16 ***
bathrooms                  36638.88     680.15   53.87   <2e-16 ***
surface_total                929.85      24.71   37.63   <2e-16 ***
surface_covered             1530.56      30.12   50.81   <2e-16 ***
property_typeDepartamento  97709.34    2280.28   42.85   <2e-16 ***
property_typePH            49497.03    2405.16   20.58   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

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

tabla 4: variables dummies para la categoría del barrio.

Se generó un nuevo modelo lineal múltiple con dos variables categóricas property_type y barrios que clasifica a los mismos según el precio por metro cuadrado promedio. El nivel de referencia esta dado por una propiedad tipo casa para la variable del tipo de propiedad y un barrio de precio alto para la variable correspondiente al precio medio de la zona. Los coeficientes estimados para las varaibles barrios bajo y barrios medio son negativos. Esto determina que manteniendo todo fijo, tanto barrios medio como barrios bajo disminuyen el valor medio del precio con respecto al de referencia.

El test F indica significancia conjunta de las variables y para todos los coeficientes se observa un p-valor cercano a cero. El R cuadrado ajustado es mayor en este modelo que en los anteriores y es de 75%.

c. ¿Qué modelo explica mejor la variabilidad de los datos, el que utiliza la variable l3 o el que utiliza barrios? En su opinión, ¿Qué modelo es más útil? ¿Por qué?
El valor de r cuadrado ajustado del modelo 1 y del modelo 3 que incluyen la variable barrios son: 0.776 vs. 0.746. La diferencia de explicatividad no parece ser tan significativa en relación a la cantidad de variables que estoy perdiendo con el modelo 1. Sin embargo dependerá del tipo de estudio elegir el modelo en función de la investigación.
En lo que es este trabajo el modelo 3 posee una informacion de resumen del barrio clasificado como “bajo”, “medio” o “alto” y a su vez permite entender la determinación del precio en función de las caracteristicas del edificio.

d. La interpretación de los coeficientes de las variables surface_covered y surface_total puede ser un poco problemática ya que se encuentran correlacionadas. Entonces, podemos construir una nueva variable surface_patio para la diferencia entre ambas superficies:

i. Construir una nueva variable surface_patio. Dado que algunos registros pueden contener la contradicción de que surface_total < surface_covered, explicitar cómo se procede para dichos casos.

ii. Calcular nuevamente el modelo lineal para todas las covariables previas (excepto surface_total), surface_covered y surface_patio e interpretar los coeficientes de estas dos últimas variables.

summary(prop_lm4)

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

Residuals:
    Min      1Q  Median      3Q     Max 
-427740  -35811   -5227   25355  681886 

Coefficients:
                           Estimate Std. Error t value Pr(>|t|)    
(Intercept)               -42011.99    2603.42  -16.14   <2e-16 ***
barriosbajo               -98160.19     993.03  -98.85   <2e-16 ***
barriosmedio              -62104.73     758.61  -81.87   <2e-16 ***
rooms                      -7631.29     467.91  -16.31   <2e-16 ***
bathrooms                  36638.88     680.15   53.87   <2e-16 ***
surface_patio                929.85      24.71   37.63   <2e-16 ***
surface_covered             2460.42      15.91  154.61   <2e-16 ***
property_typeDepartamento  97709.34    2280.28   42.85   <2e-16 ***
property_typePH            49497.03    2405.16   20.58   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

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

En el nuevo modelo lineal, el nivel de referencia se conforma con una propiedad del tipo casa para la variable property_type y un barrio de precio promedio alto para barrios. El coeficiente dw surface_patio determina que manteniendo todas las demás variables fijas, al aumentar el valor medio el precio aumentará 929 USD. En cambio el aumento del precio de surface_covered es de 2460 USD. Con respecto al modelo anterior, el coeficiente estimado de la superficie cubierta aumentó y el r cuadrado ajustado se mantiene en el mismo valor.

3 Evaluación del modelo

a. Analizar los residuos del modelo elaborado en 2.d.

Observano la distribución de los residuos observamos que se agrupan alrededor del valor cero. El valor de la media es de 4.406828e-08- .

mean(prop$resid)
[1] 4.406828e-08

En la figura 2 de residuos vs prediccion y en la figura 4 conlos residuos estandarizados vemos que la forma supone heterocedasticidad, en tanto para cada valor de X la varianza de los residuos cambian. En la figura 3 (QQPlot) se observa a los residuos desviandose en los extremos y en la figura 5 vemos que los residuos estandarizados en funcion del leverage muestra a los puntos concentrados en un nivle bajo, es decir, poco influyente.

Podemos determinar que no se cumplen los supuestos del modelo linean. Sin embargo se puede hacer una transformación o aplicar un modelo robusto.

b. Calcular el modelo

\(\begin{aligned}\log(price) = \beta_{0}+\beta_{1}.\log(rooms)+\beta_{2}.\log(bathrooms)+\beta_{3}.\log(surface\_covered)\\+\beta_{4}.property\_type+\beta_{5}.barrio+\beta_{6}.surface\_patio\end{aligned}\)

Comparar la performance del modelo de 2.d con éste, tanto en términos de la variabilidad explicada cómo de su relación con los supuestos del modelo lineal. Re-interpretar los parámetros del modelo.

Para aplicar logratimo, reemplazo todos los valores distintos de cero de las variables continuas.

summary(prop_lm5)

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

Residuals:
     Min       1Q   Median       3Q      Max 
-1.34665 -0.14810 -0.01394  0.13791  1.30682 

Coefficients:
                            Estimate Std. Error  t value Pr(>|t|)    
(Intercept)                8.869e+00  2.283e-02  388.445  < 2e-16 ***
barriosbajo               -4.401e-01  3.811e-03 -115.478  < 2e-16 ***
barriosmedio              -2.366e-01  2.832e-03  -83.528  < 2e-16 ***
log(rooms)                 3.514e-03  4.464e-03    0.787    0.431    
log(bathrooms)             1.658e-01  4.396e-03   37.715  < 2e-16 ***
surface_patio              3.008e-03  9.436e-05   31.875  < 2e-16 ***
log(surface_covered)       7.729e-01  5.540e-03  139.512  < 2e-16 ***
property_typeDepartamento  2.275e-01  8.432e-03   26.981  < 2e-16 ***
property_typePH            5.479e-02  8.996e-03    6.090 1.14e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2242 on 32645 degrees of freedom
Multiple R-squared:  0.8177,    Adjusted R-squared:  0.8176 
F-statistic: 1.83e+04 on 8 and 32645 DF,  p-value: < 2.2e-16

El R cuadrado ajustado del modelo es el mayor respecto a los anteriores, ubicandose en un valor del 81,76%, mayor al obtenido anteriormente de aproximadamente 75% de la variabilidad de price

Para este modelo la variable de referencia es casa para la variable tipo de propiedad y una zona de precio alto para la variable barrios. Si observo los T-Test individuales se observa que la variable log(rooms) no es una variable respuesta a log(price) a nivel alfa 0.05. El resto de las variables siguen cayendo dentro de la zona de sinigficatividad

# Promedio de residuos
mean(prop1$resid)
[1] 1.761914e-13

En la figura 7: distribución de residuos, se observa que con la transformacion logaritmica los residuos se distribuyen de una manera más uniforme a lo largo del eje X. En la figura8: QQ-Plot con los datos transformados, podemos observar una mayor correspondencia con el modelo normal.

Con la transformación logaritmica observamos que se cumple con los supuestos del modelo lineal. Por otro lado el R cuadrado ajustado aumenta de 74,6% a 81,7% del modelo anterior respecto al modelo con transformación logaritmica. Por lo tanto sería el modelo a considerar cómo válido. Otro punto a considerar es que todos los coeficientes se mantienen cómo significativos individualmente y de manera global por el estadistico F.

El valor del intercept no tiene sentido real dado que todas las variables deberían tomar valor cero.

En el modelo anterior tmb teniamos como nivel de referencia una propiedad del tipo “Casa” para la variable property_type y un barrio de precio promedio alto para barrios. Sin embargo el aumento del precio frente a un aumento de surface_covered se esperaba que el precio aumentara 2460 USD. Dado el texto de Wooldrige, la transformación logaritmica de este modelo nos plantea el analisis en término de elasticidades, esto significa que el coeficiente ya no es un monto absoluto, sino relativo a la variable dependiente. En la transformación surface_covered tiene cómo coeficiente 0,75, esto quiere decir que manteniendo constantes el resto de las variables, un aumento de 1% en los m2 de superficie cubierta aumentará un 0,75% el precio esperado de la vivienda.

En el caso del coeficiente de log(rooms) su valor es de -0.03%, lo cual significa que frente a un aumento de 100% de la cantidad de cuartos el precio disminuye en 3%. En cambio cómo el coeficiente de log(bathrooms) es 0,165 un aumento de 100% en la cantidad de baños, determina un aumento de 16% en el precio esperado. Es decir, para el caso de las variables contínuas (a las cuales se les aplicó la transformación logarítmica, los coeficientes pueden interpretarse cómo el porcentaje de aumento en el precio medio esperado al aumentar 1% la variable explicativa y manteniendo el resto fijas

En el caso de surface_patio (la cual no fue transformada), su coeficiente multiplicado puede interpretarse como el poecentaje de aumento en el precio medio al aumentar en una unidad de la variable y mantener fija las demás. Es decir, aumentaría un 3% el valor esperado del precio al aumentar una unidad de la superficie cubierta de patio.

4 Dataframes anidados

a. Anidar por la variable property_type.

b. Construir para cada tipo de propiedad el modelo de 2.d e interpretar los resultados en cada caso. Qué diferencias encuentran entre los distintos modelos?

Casa, departamento y PH presentan el mismo nivel de referencia, una propiedad en una zona de precio por metro cuadrado promedio alto. En los tres casos barrios bajo y barrios medio tiene un coeficiente estimado negativo respecto al nivel de referencia.

El coeficiente de superficie cubierta representa un aumento en el precio medio. Si fijo las demás variables en el caso de departamentos veo que duplica y casi triplica a Ph´s y casas.

La variabilidad de la respuesta explicada por cada modelo es aproximadamente 59% para casa, 77% para departamento y 69% para PH; ninguno supera al modelo anterior con la transformación logarítmica. Los desvios aumentan dado que ahora tenemos un modelo más complejo.

LS0tDQp0aXRsZTogPGNlbnRlcj5FbmZvcXVlIEVzdGFkw61zdGljbyBkZWwgQXByZW5kaXphamU8L2NlbnRlcj4NCnN1YnRpdGxlOiA8Y2VudGVyPlRyYWJham8gUHLDoWN0aWNvIE7CujI8L2NlbnRlcj4NCmF1dGhvcjogRmVkZXJpY28gTW9yZW5vDQoNCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZSANCiAgICB0b2NfZGVwdGg6IDQNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICB0aGVtZTogc3BhY2VsYWINCi0tLQ0KPHN0eWxlPg0KYm9keSB7DQp0ZXh0LWFsaWduOiBqdXN0aWZ5fQ0KDQoubGlzdC1ncm91cC1pdGVtLmFjdGl2ZSwgLmxpc3QtZ3JvdXAtaXRlbS5hY3RpdmU6Zm9jdXMsIC5saXN0LWdyb3VwLWl0ZW0uYWN0aXZlOmhvdmVyIHsNCiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjREQ4RDE7DQp9DQo8L3N0eWxlPg0KDQoNCipmZWRlcmljb21vcmVubzYxM0BnbWFpbC5jb20qPGJyPg0KKlRyYWJham8gc29icmUgdW4gZGF0YXNldCBkZSBQcm9wZXJhdGkgQXJnZW50aW5hKjxicj4NCmBgYHtyIHBhcXVldGVzLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kcm0obGlzdD1scygpKQ0KZ2MoKQ0KbGlicmFyeShyc2Nvbm5lY3QpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobW9kZWxyKQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkoZ2dzY2kpDQpycGFsID1wYWxfcmlja2FuZG1vcnR5KHBhbGV0dGUgPSBjKCJzY2h3aWZ0eSIpLCBhbHBoYSA9IDEpDQpgYGANCg0KYGBge3IgY2FyZ2EgZGVsIGRhdGFzZXR9DQojIENhcmdhIGRlIGRhdG9zDQpwcm9wID0gcmVhZF9yZHMoImFyX3Byb3BlcnRpZXMucmRzIikNCmBgYA0KYGBge3IgaW5zcGVjY2nDs24gZGVsIGRhdGFzZXR9DQoNCmdsaW1wc2UocHJvcCkNCiNDYXRlZ29yaWNhcyBhIGZhY3Rvcg0KcHJvcCRsMyA9IGFzLmZhY3Rvcihwcm9wJGwzKQ0KcHJvcCRwcm9wZXJ0eV90eXBlID0gYXMuZmFjdG9yKHByb3AkcHJvcGVydHlfdHlwZSkNCiMgQW5hbGl6byB2YXJpYWJsZXMNCnN0cihwcm9wKQ0KYGBgDQoNCg0KIyBSZWdyZXNpw7NuIGxpbmVhbCBtw7psdGlwbGUNCioqYS4gQ3JlYXIgdW4gbW9kZWxvIHBhcmEgcHJlZGVjaXIgZWwgcHJlY2lvIGNvbiB0b2RhcyBsYXMgY292YXJpYWJsZXMuKio8YnI+DQoNCjxicj4NCiRcYmVnaW57YWxpZ25lZH1wcmljZSA9IFxiZXRhX3swfStcYmV0YV97MX0ubDMrXGJldGFfezJ9LnJvb21zK1xiZXRhX3szfS5iYXRocm9vbXNcXCtcYmV0YV97NH0uc3VyZmFjZVxfdG90YWwrXGJldGFfezV9LnN1cmZhY2VcX2NvdmVyZWQrXGJldGFfezZ9LnByb3BlcnR5XF90eXBlXGVuZHthbGlnbmVkfSQ8YnI+DQo8YnI+DQoNCg0KKkxhcyB2YXJpYWJsZXMgY29udGludWFzIHNvbiAgPGNvZGU+cm9vbXM8L2NvZGU+IGNhbnRpZGFkIGRlIGhhYml0YWNpb25lcywgPGNvZGU+YmF0aHJvb21zPC9jb2RlPiBjYW50aWRhZCBkZSBiYcOxb3MsIDxjb2RlPnN1cmZhY2VfdG90YWw8L2NvZGU+IChzdXBlcmZpY2llIHRvdGFsKSB5IDxjb2RlPnN1cmZhY2VfY292ZXJlZDwvY29kZT4gc3VwZXJmaWNpZSBjdWJpZXJ0YSo8YnI+DQoNCipMYXMgdmFyaWFibGVzIGNhdGVnb3JpY2FzIGVuIGNhbWJpbyBzb24gPGNvZGU+cHJvcGVydHlfdHlwZTwvY29kZT4gVGlwbyBkZSBwcm9waWVkYWQsICJDYXNhIiwgIlBoIiB5ICJEZXBhcmF0YW1lbnRvIiB5IHBvciBvdHJvIGxhZG8gIDxjb2RlPmwzPC9jb2RlPiBxdWUgcmVwcmVzZW50YSBsYXMgem9uYXMgZG9uZGUgc2UgdWJpY2FuIGRpY2hhcyBwcm9waWVkYWRlcy4gUGFyYSBnZW5lcmFyIGVsIG1vZGVsbyBsaW5lYWwgZGVibyB0cmFuc2Zvcm1hciBsYXMgdmFyaWFibGVzIGNhdGVnb3JpY2FzIGEgdmFyaWFibGVzIGR1bW15LiogPGJyPg0KDQoNCmBgYHtyfQ0KIyBNb2RlbG8gbGluZWFsIG3Dumx0aXBsZQ0KcHJvcF9sbTEgPSBsbShwcmljZSB+IGwzK3Jvb21zK2JhdGhyb29tcytzdXJmYWNlX3RvdGFsK3N1cmZhY2VfY292ZXJlZCtwcm9wZXJ0eV90eXBlLCBkYXRhID0gcHJvcCkNCmFub3ZhKHByb3BfbG0xKQ0KYGBgDQoNCipSZWFsaXphbmRvIGVsIHRlc3QgZGUgQW5vdmEgcHVlZG8gdmVyaWZpY2FyIHF1ZSBhbWJvcyB0aXBvcyBkZSB2YXJpYWJsZXMgc29uIHNpZ25pZmljYXRpdmFzIHkgcG9yIGxvIHRhbnRvIHB1ZWRvIGFuYWxpemFyIGVuIHBhcnRpY3VsYXIgY2FkYSBjb2VmaWNpZW50ZSBlbiBkZXRhbGxlKiA8YnI+DQoNCmBgYHtyIEVqLjEuYX0NCnN1bW1hcnkocHJvcF9sbTEpDQpgYGANCioqYi4gQW5hbGl6YXIgbG9zIHJlc3VsdGFkb3MgZGVsIG1vZGVsby4qKjxicj4NCjxkaXYgc3R5bGU9Im1hcmdpbi1sZWZ0OiAyZW07Ij4NCioqaS4gSW50ZXJwcmV0YWNpw7NuIGRlIGxvcyBjb2VmaWNpZW50ZXMgZXN0aW1hZG9zLioqPGJyPg0KDQoqQW5hbGl6YW5kbyBlbCB2YWxvciBkZWwgZXN0YWTDrXN0aWNvIEYsIHNlIHB1ZWRlIHJlY2hhemFyIGxhIGhpcG90ZXNpcyBudWxhLiBQb3Igb3RybyBsYWRvIGVsIGNvZWZpY2llbnRlIFIgY3VhZHJhZG8gYWp1c3RhZG8gZGV0ZXJtaW5hIHF1ZSBlbCA3NyUgZGUgbGEgdmFyaWFiaWxpZGFkIGRlbCBwcmVjaW8gZXN0w6EgZXhwbGljYWRhIHBvciBsYXMgdmFyaWFibGVzLiogPGJyPg0KDQoqRW4gZWwgY2FzbyBkZSA8Y29kZT5sMzwvY29kZT4gbGEgY2F0ZWdvcsOtYSBiYXNhbCBlcyBBYmFzdG8geSBwYXJhIDxjb2RlPnByb3BlcnR5X3R5cGU8L2NvZGU+IGVzIENhc2EuIEVuIGVzdGUgbW9kZWxvIGhheSBjb2VmaWNpZW50ZXMgZXN0aW1hZG9zIHF1ZSBubyByZXN1bHRhbiBzaWduaWZpY2F0aXZvcywgY8OzbW8gQWxtYWdybyB5IE1vbnRlY2FzdHJvLiBQb3Igb3RybyBsYWRvIGV4aXN0ZW4gYmFycmlvcyBxdWUgdGllbmVuIHVuIGNvZWZpY2llbnRlIG5lZ2F0aXZvLCBlcyBkZWNpciBxdWUgZXN0w6FuIHBvciBkZWJham8gZGVsIHByZWNpbyBtZWRpbyBkZSByZWZlcmVuY2lhLiBFbiBlbCBjYXNvIGRlIDxjb2RlPnByb3BlcnR5X3R5cGU8L2NvZGU+IGVsIHByZWNpbyBkZSBsb3MgUEggbyBEZXBhcnRhbWVudG9zIHRpZW5lbiB1bmEgaW5mbHVlbmNpYSBwb3NpdGl2YSAgcmVzcGVjdG8gYSBsYSB2YXJpYWJsZSBjb250cm9sICJDYXNhIiAqIDxicj4NCg0KKkFuYWxpemFuZG8sIGNvZWZpY2llbnRlIGRlIGxhIHZhcmlhYmxlIDxjb2RlPnN1cmZhY2VfY292ZXJlZDwvY29kZT4gc2UgZXNwZXJhIHF1ZSB1biBhdW1lbnRvIGRlbCBtZXRybyBjdWFkcmFkbyBhdW1lbnRlIDE0NTd1c2QgZWwgcHJlY2lvIGRlIGxhIHByb3BpZWRhZC4qPGJyPg0KDQoqUG9yIG90cm8gbGFkbywgdW5hIG1hbmVyYSAgZGUgYnVzY2FyIGRlcGFydGFtZW50b3MgZXMgc2Vnw7puIGxhIGNhbnRpZGFkIGRlIGhhYml0YWNpb25lcywgZXMgZGVjaXIsIHBvciBsYSB2YXJpYWJsZSA8Y29kZT5yb29tczwvY29kZT4uIFBhcmVjZXLDrWEgY29udHJhaW50dWl0aXZvIGVsIGNvZWZpY2llbnRlIGRlbCBtb2RlbG8gcXVlIGRldGVybWluYSBxdWUgZnJlbnRlIGFsIHJlc3RvIGRlIGxhcyB2YXJpYWJsZXMgY29uc3RhbnRlcywgdW5hIGhhYml0YWNpw7NuIGFkaWNpb25hbCBkaXNtaW51eWUgZWwgcHJlY2lvIGVzcGVyYWRvIGVuIDM5NjF1c2QuIFNlcsOtYSBpbnRlcmVzYW50ZSBhZ3JlZ2FyIGEgZXN0ZSBkYXRhc2V0IGxhIGFudGlndWVkYWQgZGUgbGEgcHJvcGllZGFkLCBwYXJhIGVudGVuZGVyIHNpIGhheSBhbGd1bmEgY29ycmVsYWNpw7NuIGVudHJlIGxhIHZhcmlhYmxlIGNhbnRpZGFkIGRlIGhhYml0YWNpb25lcyB5IGFudGlndWVkYWQgZGUgbGEgcHJvcGllZGFkLio8YnI+DQoNCipFbiBlbCBjYXNvIGRlIGxvcyBjb2VmaWNpZW50ZXMgZGUgbGFzIHZhcmlhYmxlcyBkdW1teSBpbmRpY2FuIGPDs21vIHNlIG1vZGlmaWNhIGxhIHZhcmlhYmxlIHJlc3B1ZXN0YSByZXNwZWN0byBhIGxhIGJhc2FsIGZpamFuZG8gbGFzIGRlbcOhcyBjb3ZhcmlhYmxlcy4gY3VhbmRvIGRpY2hhIHZhcmlhYmxlIGNvcnJlc3BvbmRlIGEgY2FkYSB1bm8gZGUgc3VzIG5pdmVsZXMuIEVuIGVsIGNhc28gZGUgbGEgdmFyaWFibGUgY2F0ZWfDs3JpY2EgPGNvZGU+cHJvcGVydHlfdHlwZTwvY29kZT4gc2Ugb2J0aWVuZSBxdWUgYWwgdHJhdGFyc2UgZGUgZGVwYXJ0YW1lbnRvcywgZWwgcHJlY2lvIG1lZGlvIGF1bWVudGFyw6EgOTI2NTMuMzIgVVNEIGNvbiByZXNwZWN0byBhIHN1IHZhcmlhYmxlIGRlIHJlZmVyZW5jaWEsIGNhc2EuIFBhcmEgbGEgdmFyaWFibGUgPGNvZGU+bDM8L2NvZGU+IGVsIG5pdmVsIGRlIHJlZmVyZW5jaWEgZXMgYWJhc3RvLCBsbyBxdWUgc2lnbmlmaWNhIHF1ZSBwb3IgZWplbXBsbywgdW5hIHByb3BpZWRhZCB1YmljYWRhIGVuIGVsIGJhcnJpbyBkZSBCZWxncmFubyBwcmVzZW50YXLDoSB1biBwcmVjaW8gbWVkaW8gZXNwZXJhZG8gbWF5b3IgZGUgNjk2NDguMTJVU0QgY29uIHJlc3BlY3RvIGEgdW5hIGVuIGxhIHpvbmEgQWJhc3RvLiBFbiBjYW1iaW8gdW5hIHByb3BpZWRhZCB1YmljYWRhIGVuIFZpbGxhIEx1Z2FubyB0ZW5kcsOhIHVuIHByZWNpbyBtZWRpbyBlc3BlcmFkbyA4MzAzOS4xOCBVU0QgbWVub3IqPGJyPg0KDQoNCmBgYHtyIEVqLjEuYSBkdW1taWVzIHpvbmF9DQojIFZhcmlhYmxlcyBkdW1taWVzIGRlIGxhIHpvbmENCmRhdGEuZnJhbWUoY29udHJhc3RzKHByb3AkbDMpKQ0KYGBgDQo8Zm9udCBzaXplPSIyIj48Zm9udCBjb2xvcj0iIzNhNDc2NyI+KipUYWJsYSAxOioqPC9mb250PiBEdW1taWVzIGRlIGxhcyB6b25hcy48L2ZvbnQ+PGJyPg0KDQpgYGB7ciBFai4xLmEgZHVtbWllcyB0aXBvfQ0KIyBWYXJpYWJsZXMgZHVtbWllcyBkZWwgdGlwbyBkZSBwcm9waWVkYWQNCmRhdGEuZnJhbWUoY29udHJhc3RzKHByb3AkcHJvcGVydHlfdHlwZSkpDQpgYGANCjxmb250IHNpemU9IjIiPjxmb250IGNvbG9yPSIjM2E0NzY3Ij4qKlRhYmxhIDI6Kio8L2ZvbnQ+IER1bW1pZXMgcGFyYSBlbCB0aXBvIGRlIHByb3BpZWRhZC48L2ZvbnQ+PGJyPg0KPGJyPg0KDQoqKmlpLiDCv1F1w6kgb2JzZXJ2YW4gcmVzcGVjdG8gZGUgbGEgc2lnbmlmaWNhdGl2aWRhZCBkZSBsYXMgdmFyaWFibGVzIGR1bW15PyoqPGJyPg0KKlBhcmEgZXZhbHVhciBsYXMgdmFyaWFibGVzIGR1bW1pZXMgaGF5IHF1ZSByZWFsaXphciB0ZXN0IGRlIGhpcG90ZXNpcyBzb2JyZSBjYWRhIGNvZWZpY2llbnRlLiAqPGJyPg0KDQpgYGB7cn0NCiMgVmFyaWFibGVzIHkgc3UgcC12YWxvciBkZWwgdGVzdCBpbmRpdmlkdWFsDQpwcm9wX2xtMSAlPiUNCiAgdGlkeSguKSAlPiUgDQogIGZpbHRlciguLCBwLnZhbHVlID4gMC4wNSkgJT4lIA0KICBzZWxlY3QodGVybSwgcC52YWx1ZSkgJT4lIA0KICByZW5hbWUoQ29lZmljaWVudGVzID0gdGVybSkgJT4lDQogIGFycmFuZ2UoLiwgZGVzYyhwLnZhbHVlKSkNCmBgYA0KPGZvbnQgc2l6ZT0iMiI+PGZvbnQgY29sb3I9IiMzYTQ3NjciPioqVGFibGEgMzoqKjwvZm9udD4gY29lZmljaWVudGVzIGRlIGxzYSB2YXJpYWJsZXMgZHVtbWllcy48L2ZvbnQ+PGJyPg0KPGJyPg0KDQoqRnJlbnRlIGEgbG9zIHJlc3VsdGFkb3MgZGVsIHRlc3QgZGUgaGlwb3Rlc2lzIG9ic2VydmFkb3MgZW4gbGEgIHRhYmxhIDMgbm8gcG9kZW1vcyByZWNoYXphciBsYSBoaXBvdGVzaXMgbnVsYSB5IGxvcyBjb2VmaWNpZW50ZXMgc29uIGRpc3RpbnRvcyBkZSBjZXJvLiBTaW4gZW1iYXJnbyBwb2RlbW9zIGhhY2VyIHVuIGdyYW4gZGlmZXJlbmNpYSBlbnRyZSBhPGNvZGU+cHJvcGVydHlfdHlwZTwvY29kZT4geSA8Y29kZT5sMzwvY29kZT4uIE11Y2hvcyBiYXJyaW9zIG5vIHRpZW5lbiB1biBjb2VmaWNpZW50ZSBtdXkgYWx0byB5IHNpbiBlbWJhcmdvIHRlbmVtb3Mgc2lnbmlmaWNhdGl2ZGFkIHBhcmEgdXRpbGl6YXJsb3MgY29tbyB2YXJpYWJsZXMgZXhwbGljYXRpdmFzIHB1ZWRlbiBubyB0ZW5lciB0YW50YSBpbmZvcm1hY2nDs24uKjxicj4NCg0KDQoqKmlpaS4gTWVkaWRhcyBkZSBldmFsdWFjacOzbiBkZWwgbW9kZWxvLioqPGJyPg0KDQoqQW50ZXMgZGUgYW5hbGl6YXIgbGEgc2lnbmlmaWNhdGl2ZGFkIGRlIGNhZGEgdmFyaWFibGUgaGF5IHF1ZSBtaXJhciBlbCByZXN1bHRhZG8gZGVsIHRlc3QgRiBxdWUgZW52YWzDumEgbGEgc2lnbmlmaWNhdGl2aWRhZCBjb25qdW50YSBkZSBsYXMgdmFyaWFibGVzIHBhcmEgZXhwbGljYXIgYSBsYSByZXNwdWVzdGEuIFNpIGxhIG9ic2VydmFtb3MgdmVtb3MgcXVlIGVzIHVuIHZhbG9yIGFsdG8gKDI1Njggb24gNjIpIHkgZWwgcHZhbG9yIGVzIHVuIHZhbG9yIGNlcmFjbm8gYSBjZXJvLCBwb3IgbG8gdGFudG8gbGFzIHZhcmlhYmxlcyBzb24gc2lnbmlmaWNhdGl2YXMgZGUgZm9ybWEgY29uanVudGEgYSBuaXZlbCBhbGZhIDAsMDUuIC4qPGJyPiANCipMdWVnbyBvYnNlcnZhbW9zIGVsIGNvZWZpY2llbnRlIFIgYWp1c3RhZG8gZW4gdW4gdmFsb3IgYXByb3ggZGUgMC43NyBjb25zaWRlcmFuZG8gYWwgbW9kZWxvIGPDs21vIGFkZWN1YWRvLiBEaWNobyBjb2VmaWNpZW50ZSByZXByZXNlbnRhIGxhIHByb3BvcmNpw7NuIHBvciBsYSBjdWFsIGxhIHZhcmlhYmxlIHByZWRpY2hhIGVzIGV4cGxpY2FkYSBwb3IgbnVlc3RybyBtb2RlbG8uKg0KPC9kaXY+DQo8YnI+DQoqKmMuIMK/UXXDqSBlcyBwcmVmZXJpYmxlIHRlbmVyIHBhcmEgdmVuZGVyPzoqKjxicj4NCjxkaXYgc3R5bGU9Im1hcmdpbi1sZWZ0OiAyZW07Ij4NCioqaS4gdW4gZGVwYXJ0YW1lbnRvIGRlIDEyMCBtdHMgY3VhZHJhZG9zIGN1YmllcnRvcyBlbiBBYmFzdG8sIGNvbiAzIGRvcm1pdG9yaW9zIHkgMiBiYcOxb3MuKio8YnI+DQoqKmlpLiBVbiBQSCBlbiBiYWx2YW5lcmEsIGNvbiA4MCBtdHMgY3VhZHJhZG9zIGN1YmllcnRvcywgMjAgbXRzIGN1YWRyYWRvcyBubyBjdWJpZXJ0b3MsIDIgZG9ybWl0b3Jpb3MgeSAzIGJhw7Fvcy4qKjxicj4NCmBgYHtyIEVqLjEuY30NCiMgUHJlZGljY2nDs24gcGFyYSBpDQpwcmVkaWN0KHByb3BfbG0xLCBkYXRhLmZyYW1lKGwzPSJBYmFzdG8iLHJvb21zPTMsYmF0aHJvb21zPTIsc3VyZmFjZV9jb3ZlcmVkPTEyMCxwcm9wZXJ0eV90eXBlPSJEZXBhcnRhbWVudG8iLCBzdXJmYWNlX3RvdGFsPTEyMCkpDQoNCmBgYA0KDQoNCmBgYHtyIEVqLjEuYzJ9DQojIFByZWRpY2Npw7NuIHBhcmEgaWkNCnByZWRpY3QocHJvcF9sbTEsIGRhdGEuZnJhbWUobDM9IkJhbHZhbmVyYSIscm9vbXM9MixiYXRocm9vbXM9MyxzdXJmYWNlX2NvdmVyZWQ9ODAscHJvcGVydHlfdHlwZT0iUEgiLCBzdXJmYWNlX3RvdGFsPTEwMCkpDQpgYGANCipEYWRvIGxvcyB2YWxvcmVzIGRlIG10cyBjdWFkcmFkb3MsIGRvcm1pdG9yaW9zIHkgYmHDsW9zLiB1biBkZXBhcnRhbWVudG8gZGVsIGJhcnJpbyBBYmFzdG8gdGVuZHLDoW4gdW4gcHJlY2lvIG1lZGlvIG1heW9yIHF1ZSB1bm8gZGUgQmFsdmFuZXJhLCBwb3IgbG8gdGFudG8gZXMgcHJlZmVyaWJsZSB0ZW5lciBsYSBvcGNpw7NuIGkgcGFyYSB2ZW5kZXIgKg0KPC9kaXY+DQo8YnI+DQoqKmQuIFJlYWxpemFyIHVuIG1vZGVsbyBzaW4gbGEgY292YXJpYWJsZSA8Y29kZT5sMzwvY29kZT4gZSBpbnRlcnByZXRhciBzdXMgcmVzdWx0YWRvcyAodG9kYXMgbGFzIHBhcnRlcyBkZSBsYSBzYWxpZGEgcXVlIGNvbnNpZGVyZW4gcmVsZXZhbnRlcykuKio8YnI+DQpgYGB7ciBFai4xLmR9DQojIE1vZGVsbyBsaW5lYWwgbcO6bHRpcGxlDQpwcm9wX2xtMiA9IGxtKHByaWNlIH4gcm9vbXMrYmF0aHJvb21zK3N1cmZhY2VfdG90YWwrc3VyZmFjZV9jb3ZlcmVkK3Byb3BlcnR5X3R5cGUsIGRhdGEgPSBwcm9wKQ0Kc3VtbWFyeShwcm9wX2xtMikNCmBgYA0KKkxvIHByaW1lcm8gYSBhbmFsaXphciBlcyBlbCBlc3RhZMOtc3RpY28gRiB5IGVsIHAgdmFsb3IsIGVuIGVsIGN1YWwgYW5hbGl6YW1vcyBxdWUgZWwgRiBlcyBhw7puIG1heW9yIHF1ZSBlbCBhbnRlcmlvciAgeSBlbCB2YWxvciBwIHNpZ3VlIGVuIHVuIHZhbG9yIGNlcmNhbm8gYSBjZXJvLiBMdWVnbyB2ZW1vcyBlbiBwYXJ0aWN1bGFyIGNhZGEgY29lZmljaWVudGUsIHRhbnRvIGxhcyB2YXJpYWJsZXMgY29udGludWFzIGNvbW8gbGFzIGNhdGVnb3JpY2FzIHNvbiBzaWduaWZpY2F0aXZhcy4gRWwgUiBhanVzdGFkbyBwb3Igb3RybyBsYWRvIGRpc21pbnV5byAgZGUgMC43NyBhIDAuNjggZW4gZWwgbW9kZWxvIG51ZXZvLiAqPGJyPg0KPGJyPg0KKiplLiDCv0N1w6FsIGVzIGVsIG1vZGVsbyBxdWUgbWVqb3IgZXhwbGljYSBsYSB2YXJpYWJpbGlkYWQgZGVsIHByZWNpbz8qKjxicj4NCipFbCBwcmltZXIgbW9kZWxvIHF1ZSBwb3NlZSBsYSB2YXJpYWJsZSBkZSBsYSB6b25hIHBvc2VlIHVuIG1heW9yIHIgY3VhZHJhZG8gYWp1c3RhZG8sIHBvciBsbyB0YW50byBleHBsaWNhIG1lam9yIGxhIHZhcmlhYmlsaWRhZCBkZWwgcHJlY2lvIHF1ZSBlbCBzZWd1bmRvIG1vZGVsby4qPGJyPg0KDQojIENyZWFjacOzbiBkZSB2YXJpYWJsZXMNCioqYS4gRW4gZWwgZWplcmNpY2lvIGFudGVyaW9yIGVuY29udHJhbW9zIHF1ZSBhbGd1bm9zIGJhcnJpb3Mgc29uIHNpZ25pZmljYXRpdm9zLCBhdW5xdWUgbm8gdG9kb3MuIENyZWFyIHVuYSBudWV2YSB2YXJpYWJsZSA8Y29kZT5iYXJyaW9zPC9jb2RlPiBxdWUgZGl2aWRhIGEgbG9zIGJhcnJpb3Mgc2Vnw7puIGVsIHByZWNpbyBwb3IgbWV0cm8gY3VhZHJhZG8gcHJvbWVkaW8gZGUgbGFzIHByb3BpZWRhZGVzIGVuIGVsbG9zLCBjb24gbG9zIGdydXBvcyBjKOKAmGFsdG/igJksIOKAmG1lZGlv4oCZLCDigJhiYWpv4oCZKS4gUmVhbGl6YXIgdW4gYW7DoWxpc2lzIGV4cGxvcmF0b3JpbyBwYXJhIGRlZmluaXIgbG9zIHB1bnRvcyBkZSBjb3J0ZSBkZSBsYSBudWV2YSB2YXJpYWJsZSB5IGV4cGxpY2FyIGxvcyBjcml0ZXJpb3MgdXRpbGl6YWRvcyBlbiBsYSBjb25zdHJ1Y2Npw7NuIGRlIGxhIG1pc21hLioqPGJyPg0KYGBge3IgRWouMi5hIGNyZWFjaW9uIGRlIHZhcmlhYmxlc30NCiMgQ3JlYWNpw7NuIGRlIHZhcmlhYmxlcw0KcHJvcCA9IHByb3AgJT4lIA0KICBtdXRhdGUocHJpY2VfbXRzID0gcHJpY2Uvc3VyZmFjZV90b3RhbCkgJT4lIA0KICBncm91cF9ieShsMykgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBtdXRhdGUobWVhbl9wcmljZSA9IG1lYW4ocHJpY2VfbXRzKSkgICAgICAgIA0KYGBgDQoNCmBgYHtyIEVqLjIuYSBleHBsb3JhdG9yaW99DQojIEhpc3RvZ3JhbWExDQpoaXN0MSA9IGdncGxvdChwcm9wLCBhZXMoeD1wcmljZV9tdHMpKSArIGdlb21faGlzdG9ncmFtKGZpbGw9IiMzYTQ3NjciLCBjb2xvcj0iYmxhY2siKSArDQogICAgICBsYWJzKHRpdGxlPSJIaXN0b2dyYW1hIDE6IHZhcmlhYmxlIHByZWNpbyBwb3IgbWV0cm8gY3VhZHJhZG8iLCB4PSJwcmVjaW8vbTIgKFVTRCkiLCB5ID0gIkZyZWN1ZW5jaWEiKQ0KIyBCb3hwbG90MQ0KYm94MSA9Z2dwbG90KHByb3AsIGFlcyh5PXByaWNlX210cykpICsgZ2VvbV9ib3hwbG90KGZpbGw9IiNGOEQzQUMiKSArIGNvb3JkX2ZsaXAoKSArDQogICAgICBsYWJzKHRpdGxlPSJCb3hwbG90IDE6IFZhcmlhYmxlIHByZWNpbyBwb3IgbWV0cm8gY3VhZHJhZG8iLCB5PSJwcmVjaW8vbTIgKFVTRCkiKQ0KIyBNZWRpZGFzIGRlIHJlc3VtZW4gZGUgcHJlY2lvIHBvciBtMg0Kc3VtbWFyeShwcm9wJHByaWNlX210cykNCg0KbGlicmFyeShncmlkRXh0cmEpDQpncmlkLmFycmFuZ2UoaGlzdDEsYm94MSwgbnJvdyA9IDIsIG5jb2w9MSkNCmBgYA0KKlNlIG9ic2VydmEgZW4gZWwgaGlzdG9ncmFtYSAxICB5IGVsIGJveHBsb3QgMSwgcXVlIGxhIG1heW9yw61hIGRlIGxvcyBjYXNvcyBzZSBlbmN1ZW50cmEgY29uY2VudHJhZG9zIGFscmVkZWRvciBkZSAyNTAwVVNEIHBvciBtZXRybyBjdWFkcmFkby4gUG9yIGxvIHRhbnRvIGRldGVybWlubyBxdWUgbG9zIHZhbG9yZXMgUG9yIGJham8gZXN0ZSB2YWxvciBzZXLDoW4gZWwgYmluICJCYWpvIiwgTWVkaW8gdG9tYXLDqSBjw7NtbyBsw61taXRlIGhhc3RhIGVsIHRlcmNlciBjdWFydGlsIDMyMDcgeSBwb3IgZW5jaW1hIGFsIHZhbG9yIGFsdG8uICo8YnI+DQoNCg0KYGBge3IgRWouMi5hIGNsYXNpZmljYWNpw7NufQ0KIyBDbGFzaWZpY2FkbyBwb3IgdmFsb3IgbWVkaW8NCnByb3AgPSBwcm9wICU+JSANCiAgbXV0YXRlKGJhcnJpb3MgPSBjYXNlX3doZW4obWVhbl9wcmljZSA8PSAyMjAwIH4gImJham8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIChtZWFuX3ByaWNlID4gMjIwMCAmICBtZWFuX3ByaWNlIDw9IDMyMDcpIH4gIm1lZGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbl9wcmljZSA+IDMyMDcgfiAiYWx0byIpDQogICkNCmBgYA0KDQoqKmIuIENhbGN1bGFyIGVsIG1vZGVsbyBxdWUgcHJlZGljZSBlbCBwcmVjaW8gZW4gZnVuY2nDs24gZGUgbGFzIG51ZXZhcyBjb3ZhcmlhYmxlcyBlIGludGVycHJldGFyIHN1cyByZXN1bHRhZG9zICh0b2RhcyBsYXMgcGFydGVzIGRlIGxhIHNhbGlkYSBxdWUgY29uc2lkZXJlbiByZWxldmFudGVzKS4qKjxicj4NCmBgYHtyIEVqLjIuYiBkYXRhc2V0fQ0KcHJvcCRiYXJyaW9zID0gYXMuZmFjdG9yKHByb3AkYmFycmlvcykNCmdsaW1wc2UocHJvcCkNCmBgYA0KYGBge3IgRWouMi5iIG1vZGVsb30NCiMgTW9kZWxvIGxpbmVhbA0KcHJvcF9sbTMgPSBsbShwcmljZSB+IGJhcnJpb3Mrcm9vbXMrYmF0aHJvb21zK3N1cmZhY2VfdG90YWwrc3VyZmFjZV9jb3ZlcmVkK3Byb3BlcnR5X3R5cGUsIGRhdGEgPSBwcm9wKQ0Kc3VtbWFyeShwcm9wX2xtMykNCmBgYA0KDQpgYGB7ciBFai4yLmIgdmFyaWFibGVzIGR1bW1pZXN9DQojIFZhcmlhYmxlcyBkdW1taWVzIGRlIGJhcnJpb3MNCmRhdGEuZnJhbWUoY29udHJhc3RzKHByb3AkYmFycmlvcykpDQpgYGANCjxmb250IHNpemU9IjIiPjxmb250IGNvbG9yPSIjM2E0NzY3Ij4qKnRhYmxhIDQ6Kio8L2ZvbnQ+IHZhcmlhYmxlcyBkdW1taWVzIHBhcmEgbGEgY2F0ZWdvcsOtYSBkZWwgYmFycmlvLjwvZm9udD48YnI+DQo8YnI+DQoqU2UgZ2VuZXLDsyB1biBudWV2byBtb2RlbG8gbGluZWFsIG3Dumx0aXBsZSBjb24gZG9zIHZhcmlhYmxlcyBjYXRlZ8OzcmljYXMgPGNvZGU+cHJvcGVydHlfdHlwZTwvY29kZT4geSA8Y29kZT5iYXJyaW9zPC9jb2RlPiBxdWUgY2xhc2lmaWNhIGEgbG9zIG1pc21vcyBzZWfDum4gZWwgcHJlY2lvIHBvciBtZXRybyBjdWFkcmFkbyBwcm9tZWRpby4gRWwgbml2ZWwgZGUgcmVmZXJlbmNpYSBlc3RhIGRhZG8gcG9yIHVuYSBwcm9waWVkYWQgdGlwbyBjYXNhIHBhcmEgbGEgdmFyaWFibGUgZGVsIHRpcG8gZGUgcHJvcGllZGFkIHkgdW4gYmFycmlvIGRlIHByZWNpbyBhbHRvIHBhcmEgbGEgdmFyaWFibGUgY29ycmVzcG9uZGllbnRlIGFsIHByZWNpbyBtZWRpbyBkZSBsYSB6b25hLiBMb3MgY29lZmljaWVudGVzIGVzdGltYWRvcyBwYXJhIGxhcyB2YXJhaWJsZXMgPGNvZGU+YmFycmlvcyBiYWpvPC9jb2RlPiB5IDxjb2RlPmJhcnJpb3MgbWVkaW88L2NvZGU+IHNvbiBuZWdhdGl2b3MuIEVzdG8gZGV0ZXJtaW5hIHF1ZSBtYW50ZW5pZW5kbyAgdG9kbyBmaWpvLCB0YW50byBiYXJyaW9zIG1lZGlvIGNvbW8gYmFycmlvcyBiYWpvIGRpc21pbnV5ZW4gZWwgdmFsb3IgbWVkaW8gZGVsIHByZWNpbyBjb24gcmVzcGVjdG8gYWwgZGUgcmVmZXJlbmNpYS4qPGJyPg0KDQoqRWwgdGVzdCBGIGluZGljYSBzaWduaWZpY2FuY2lhIGNvbmp1bnRhIGRlIGxhcyB2YXJpYWJsZXMgeSBwYXJhIHRvZG9zIGxvcyBjb2VmaWNpZW50ZXMgc2Ugb2JzZXJ2YSB1biBwLXZhbG9yIGNlcmNhbm8gYSBjZXJvLiBFbCBSIGN1YWRyYWRvIGFqdXN0YWRvIGVzIG1heW9yIGVuIGVzdGUgbW9kZWxvIHF1ZSBlbiBsb3MgYW50ZXJpb3JlcyB5IGVzIGRlIDc1JS4qPGJyPg0KDQoqKmMuIMK/UXXDqSBtb2RlbG8gZXhwbGljYSBtZWpvciBsYSB2YXJpYWJpbGlkYWQgZGUgbG9zIGRhdG9zLCBlbCBxdWUgdXRpbGl6YSBsYSB2YXJpYWJsZSA8Y29kZT5sMzwvY29kZT4gbyBlbCBxdWUgdXRpbGl6YSA8Y29kZT5iYXJyaW9zPC9jb2RlPj8gRW4gc3Ugb3BpbmnDs24sIMK/UXXDqSBtb2RlbG8gZXMgbcOhcyDDunRpbD8gwr9Qb3IgcXXDqT8qKjxicj4NCipFbCB2YWxvciBkZSByIGN1YWRyYWRvIGFqdXN0YWRvIGRlbCBtb2RlbG8gMSB5IGRlbCBtb2RlbG8gMyBxdWUgaW5jbHV5ZW4gbGEgdmFyaWFibGUgPGNvZGU+YmFycmlvczwvY29kZT4gc29uOiAwLjc3NiB2cy4gMC43NDYuIExhIGRpZmVyZW5jaWEgZGUgZXhwbGljYXRpdmlkYWQgbm8gcGFyZWNlIHNlciB0YW4gc2lnbmlmaWNhdGl2YSBlbiByZWxhY2nDs24gYSBsYSBjYW50aWRhZCBkZSB2YXJpYWJsZXMgcXVlIGVzdG95IHBlcmRpZW5kbyBjb24gZWwgbW9kZWxvIDEuIFNpbiBlbWJhcmdvIGRlcGVuZGVyw6EgZGVsIHRpcG8gZGUgZXN0dWRpbyBlbGVnaXIgZWwgbW9kZWxvIGVuIGZ1bmNpw7NuIGRlIGxhIGludmVzdGlnYWNpw7NuLio8YnI+DQoqRW4gbG8gcXVlIGVzIGVzdGUgdHJhYmFqbyBlbCBtb2RlbG8gMyBwb3NlZSB1bmEgaW5mb3JtYWNpb24gZGUgcmVzdW1lbiBkZWwgYmFycmlvIGNsYXNpZmljYWRvIGNvbW8gImJham8iLCAibWVkaW8iIG8gImFsdG8iIHkgYSBzdSB2ZXogcGVybWl0ZSBlbnRlbmRlciBsYSBkZXRlcm1pbmFjacOzbiBkZWwgcHJlY2lvIGVuIGZ1bmNpw7NuIGRlIGxhcyBjYXJhY3RlcmlzdGljYXMgZGVsIGVkaWZpY2lvLio8L2ZvbnQ+DQoNCioqZC4gTGEgaW50ZXJwcmV0YWNpw7NuIGRlIGxvcyBjb2VmaWNpZW50ZXMgZGUgbGFzIHZhcmlhYmxlcyA8Y29kZT5zdXJmYWNlX2NvdmVyZWQ8L2NvZGU+IHkgPGNvZGU+c3VyZmFjZV90b3RhbDwvY29kZT4gcHVlZGUgc2VyIHVuIHBvY28gcHJvYmxlbcOhdGljYSB5YSBxdWUgc2UgZW5jdWVudHJhbiBjb3JyZWxhY2lvbmFkYXMuIEVudG9uY2VzLCBwb2RlbW9zIGNvbnN0cnVpciB1bmEgbnVldmEgdmFyaWFibGUgPGNvZGU+c3VyZmFjZV9wYXRpbzwvY29kZT4gcGFyYSBsYSBkaWZlcmVuY2lhIGVudHJlIGFtYmFzIHN1cGVyZmljaWVzOioqPGJyPg0KPGRpdiBzdHlsZT0ibWFyZ2luLWxlZnQ6IDJlbTsiPg0KKippLiBDb25zdHJ1aXIgdW5hIG51ZXZhIHZhcmlhYmxlIDxjb2RlPnN1cmZhY2VfcGF0aW88L2NvZGU+LiBEYWRvIHF1ZSBhbGd1bm9zIHJlZ2lzdHJvcyBwdWVkZW4gY29udGVuZXIgbGEgY29udHJhZGljY2nDs24gZGUgcXVlIDxjb2RlPnN1cmZhY2VfdG90YWw8L2NvZGU+IDwgPGNvZGU+c3VyZmFjZV9jb3ZlcmVkPC9jb2RlPiwgZXhwbGljaXRhciBjw7NtbyBzZSBwcm9jZWRlIHBhcmEgZGljaG9zIGNhc29zLioqPGJyPg0KDQpgYGB7ciBFai4yLmQuaX0NCiMgIHN1cmZhY2VfcGF0aW8NCnByb3AgPSBwcm9wICU+JSANCiAgICAgICAgbXV0YXRlKHN1cmZhY2VfcGF0aW8gPSBjYXNlX3doZW4oKHN1cmZhY2VfdG90YWwgPCBzdXJmYWNlX2NvdmVyZWQpIH4gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN1cmZhY2VfdG90YWwgPj0gc3VyZmFjZV9jb3ZlcmVkKSB+IChzdXJmYWNlX3RvdGFsIC0gc3VyZmFjZV9jb3ZlcmVkKSkNCiAgICAgICAgKQ0KYGBgDQoNCioqaWkuIENhbGN1bGFyIG51ZXZhbWVudGUgZWwgbW9kZWxvIGxpbmVhbCBwYXJhIHRvZGFzIGxhcyBjb3ZhcmlhYmxlcyBwcmV2aWFzIChleGNlcHRvIDxjb2RlPnN1cmZhY2VfdG90YWw8L2NvZGU+KSwgPGNvZGU+c3VyZmFjZV9jb3ZlcmVkPC9jb2RlPiB5IDxjb2RlPnN1cmZhY2VfcGF0aW88L2NvZGU+IGUgaW50ZXJwcmV0YXIgbG9zIGNvZWZpY2llbnRlcyBkZSBlc3RhcyBkb3Mgw7psdGltYXMgdmFyaWFibGVzLioqPGJyPg0KYGBge3IgRWouMi5kLmlpfQ0KIyBNb2RlbG8gbGluZWFsDQpwcm9wX2xtNCA9IGxtKHByaWNlIH4gYmFycmlvcytyb29tcytiYXRocm9vbXMrc3VyZmFjZV9wYXRpbytzdXJmYWNlX2NvdmVyZWQrcHJvcGVydHlfdHlwZSwgZGF0YSA9IHByb3ApDQpzdW1tYXJ5KHByb3BfbG00KQ0KYGBgDQoqRW4gZWwgbnVldm8gbW9kZWxvIGxpbmVhbCwgZWwgbml2ZWwgZGUgcmVmZXJlbmNpYSBzZSBjb25mb3JtYSBjb24gdW5hIHByb3BpZWRhZCBkZWwgdGlwbyBjYXNhIHBhcmEgbGEgdmFyaWFibGUgPGNvZGU+cHJvcGVydHlfdHlwZTwvY29kZT4geSB1biBiYXJyaW8gZGUgcHJlY2lvIHByb21lZGlvIGFsdG8gcGFyYSA8Y29kZT5iYXJyaW9zPC9jb2RlPi4gRWwgY29lZmljaWVudGUgZHcgPGNvZGU+c3VyZmFjZV9wYXRpbzwvY29kZT4gZGV0ZXJtaW5hIHF1ZSBtYW50ZW5pZW5kbyB0b2RhcyBsYXMgZGVtw6FzIHZhcmlhYmxlcyBmaWphcywgYWwgYXVtZW50YXIgZWwgdmFsb3IgbWVkaW8gZWwgcHJlY2lvIGF1bWVudGFyw6EgIDkyOSBVU0QuIEVuIGNhbWJpbyBlbCBhdW1lbnRvIGRlbCBwcmVjaW8gZGUgPGNvZGU+c3VyZmFjZV9jb3ZlcmVkPC9jb2RlPiBlcyBkZSAyNDYwIFVTRC4gQ29uIHJlc3BlY3RvIGFsIG1vZGVsbyBhbnRlcmlvciwgZWwgY29lZmljaWVudGUgZXN0aW1hZG8gZGUgbGEgc3VwZXJmaWNpZSBjdWJpZXJ0YSBhdW1lbnTDsyB5IGVsIHIgY3VhZHJhZG8gYWp1c3RhZG8gc2UgbWFudGllbmUgZW4gZWwgbWlzbW8gdmFsb3IuKg0KPC9kaXY+DQojIEV2YWx1YWNpw7NuIGRlbCBtb2RlbG8NCioqYS4gQW5hbGl6YXIgbG9zIHJlc2lkdW9zIGRlbCBtb2RlbG8gZWxhYm9yYWRvIGVuIDIuZC4qKjxicj4NCg0KDQpgYGB7ciBFai4zLmF9DQpwcm9wID0gcHJvcCAlPiUgYWRkX3Jlc2lkdWFscyhwcm9wX2xtNCkgJT4lIGFkZF9wcmVkaWN0aW9ucyhwcm9wX2xtNCkNCmBgYA0KYGBge3IgRWouMy5hIGZyZWN1ZW5jaWEgcmVzaWR1b3N9DQpnZ3Bsb3QocHJvcCwgYWVzKHJlc2lkKSkgKyBnZW9tX2ZyZXFwb2x5KGJpbndpZHRoID0gMTAwMDAsIGNvbG9yPSIjRTY0MzU4IikrIA0KICBsYWJzKHRpdGxlPSJGaWd1cmEgMTogRnJlY3VlbmNpYSBkZSByZXNpZHVvcyIsIHk9IkZyZWN1ZW5jaWEiLCB4PSJSZXNpZHVvcyIpDQpgYGANCg0KKk9ic2VydmFubyBsYSBkaXN0cmlidWNpw7NuIGRlIGxvcyByZXNpZHVvcyBvYnNlcnZhbW9zIHF1ZSBzZSBhZ3J1cGFuIGFscmVkZWRvciBkZWwgdmFsb3IgY2Vyby4gRWwgdmFsb3IgZGUgbGEgbWVkaWEgZXMgZGUgNC40MDY4MjhlLTA4LSAuKjxicj4NCg0KYGBge3IgRWouMy5hIHByb21lZGlvIHJlc2lkdW9zfQ0KbWVhbihwcm9wJHJlc2lkKQ0KYGBgDQpgYGB7ciBFai4zLmEgbXVjaG9zIGdyw6FmaWNvcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnByb3BfYXVnNCAgPSBhdWdtZW50KHByb3BfbG00LCBwcm9wKQ0KIyBSZXNpZHVvcyB2cy4gcHJlZGljY2lvbmVzDQpmaWcyID0gZ2dwbG90KHByb3BfYXVnNCwgYWVzKC5maXR0ZWQsIC5yZXNpZCkpICsNCiAgZ2VvbV9wb2ludChjb2xvcj0iIzAxQjRDNiIsIGFscGhhPTAuNSkrDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG91ciA9ICIjM2E0NzY3IikgKw0KICBnZW9tX3Ntb290aChzZSA9IEZBTFNFLCBjb2xvdXIgPSAiI0U2NDM1OCIpICsNCiAgbGFicyh0aXRsZT0iRmlndXJhIDI6IERpc3RyaWJ1Y2nDs24gZGUgcmVzaWR1b3MiLCB5PSJSZXNpZHVvcyIsIHg9IlByZWRpY2Npb25lcyIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTcpKQ0KIyBRUVBsb3QNCmZpZzMgPSBnZ3Bsb3QocHJvcF9hdWc0LCBhZXMoc2FtcGxlPSAuc3RkLnJlc2lkKSkrDQogIHN0YXRfcXEoY29sb3I9IiMwMUI0QzYiKSsNCiAgZ2VvbV9hYmxpbmUoY29sb3VyID0gIiNFNjQzNTgiKSArDQogIGxhYnModGl0bGU9IkZpZ3VyYSAzOiBRUVBsb3QiLCB5PSJSZWFsIiwgeD0iVGXDs3JpY28iKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT03KSkNCg0KIyBTY2FsZS1sb2NhdGlvbiBwbG90DQpmaWc0ID0gZ2dwbG90KHByb3BfYXVnNCwgYWVzKC5maXR0ZWQsIHNxcnQoYWJzKC5zdGQucmVzaWQpKSkpKw0KICBnZW9tX3BvaW50KGNvbG9yPSIjMDFCNEM2IiwgYWxwaGE9MC41KSsNCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSwgY29sb3VyID0gIiNFNjQzNTgiKSArDQogIGxhYnModGl0bGU9IkZpZ3VyYSA0OiBEaXN0cmlidWNpw7NuIGRlIGxhIHJhw616IGRlIGxvcyByZXNpZHVvcyBzdGFuZGFyaXphZG9zIiwgeT0iUmHDrXogZGUgUmVzaWR1b3MgU3QuIiwgeD0iUHJlZGljY2lvbmVzIikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9NykpDQojIHNjYWxlIHZzIGxldmVyYWdlDQpmaWc1ID0gZ2dwbG90KHByb3BfYXVnNCwgYWVzKC5oYXQsIC5zdGQucmVzaWQpKSArDQogIGdlb21fdmxpbmUoc2l6ZSA9IDEsIGNvbG91ciA9ICIjM2E0NzY3IiwgeGludGVyY2VwdCA9IDApICsNCiAgZ2VvbV9obGluZShzaXplID0gMSwgY29sb3VyID0gIiMzYTQ3NjciLCB5aW50ZXJjZXB0ID0gMCkgKw0KICBnZW9tX3BvaW50KGNvbG9yPSIjMDFCNEM2IiwgYWxwaGE9MC41KSArIA0KICBnZW9tX3Ntb290aChzZSA9IEZBTFNFLCBjb2xvdXIgPSAiI0U2NDM1OCIpICsNCiAgbGFicyh0aXRsZT0iRmlndXJhIDU6IFJlc2lkdW9zIHN0YW5kYXJpemFkb3MgdnMuIExldmVyYWdlIiwgeT0iUmVzaWR1b3MgU3RhbmRhcml6YWRvcyIsIHg9IkxldmVyYWdlIikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9NykpDQpncmlkLmFycmFuZ2UoZmlnMiwgZmlnMywgZmlnNCwgZmlnNSwgbnJvdyA9IDIsIG5jb2w9MikNCmBgYA0KDQoqRW4gbGEgZmlndXJhIDIgZGUgcmVzaWR1b3MgdnMgcHJlZGljY2lvbiB5IGVuIGxhIGZpZ3VyYSA0IGNvbmxvcyByZXNpZHVvcyBlc3RhbmRhcml6YWRvcyB2ZW1vcyBxdWUgbGEgZm9ybWEgc3Vwb25lIGhldGVyb2NlZGFzdGljaWRhZCwgZW4gdGFudG8gcGFyYSBjYWRhIHZhbG9yIGRlIFggbGEgdmFyaWFuemEgZGUgbG9zIHJlc2lkdW9zIGNhbWJpYW4uIEVuIGxhIGZpZ3VyYSAzIChRUVBsb3QpIHNlIG9ic2VydmEgYSBsb3MgcmVzaWR1b3MgZGVzdmlhbmRvc2UgZW4gbG9zIGV4dHJlbW9zIHkgZW4gbGEgZmlndXJhIDUgdmVtb3MgcXVlIGxvcyByZXNpZHVvcyBlc3RhbmRhcml6YWRvcyBlbiBmdW5jaW9uIGRlbCBsZXZlcmFnZSBtdWVzdHJhIGEgbG9zIHB1bnRvcyBjb25jZW50cmFkb3MgZW4gdW4gbml2bGUgYmFqbywgZXMgZGVjaXIsIHBvY28gaW5mbHV5ZW50ZS4qPGJyPg0KDQoNCipQb2RlbW9zIGRldGVybWluYXIgcXVlIG5vIHNlIGN1bXBsZW4gbG9zIHN1cHVlc3RvcyBkZWwgbW9kZWxvIGxpbmVhbi4gU2luIGVtYmFyZ28gc2UgcHVlZGUgaGFjZXIgdW5hIHRyYW5zZm9ybWFjacOzbiBvIGFwbGljYXIgdW4gbW9kZWxvIHJvYnVzdG8uKiA8YnI+DQoNCg0KKipiLiBDYWxjdWxhciBlbCBtb2RlbG8qKjxicj4NCjxicj4NCiRcYmVnaW57YWxpZ25lZH1cbG9nKHByaWNlKSA9IFxiZXRhX3swfStcYmV0YV97MX0uXGxvZyhyb29tcykrXGJldGFfezJ9Llxsb2coYmF0aHJvb21zKStcYmV0YV97M30uXGxvZyhzdXJmYWNlXF9jb3ZlcmVkKVxcK1xiZXRhX3s0fS5wcm9wZXJ0eVxfdHlwZStcYmV0YV97NX0uYmFycmlvK1xiZXRhX3s2fS5zdXJmYWNlXF9wYXRpb1xlbmR7YWxpZ25lZH0kPGJyPg0KPGJyPg0KKipDb21wYXJhciBsYSBwZXJmb3JtYW5jZSBkZWwgbW9kZWxvIGRlIDIuZCBjb24gw6lzdGUsIHRhbnRvIGVuIHTDqXJtaW5vcyBkZSBsYSB2YXJpYWJpbGlkYWQgZXhwbGljYWRhIGPDs21vIGRlIHN1IHJlbGFjacOzbiBjb24gbG9zIHN1cHVlc3RvcyBkZWwgbW9kZWxvIGxpbmVhbC4gUmUtaW50ZXJwcmV0YXIgbG9zIHBhcsOhbWV0cm9zIGRlbCBtb2RlbG8uKio8YnI+DQoNCipQYXJhIGFwbGljYXIgbG9ncmF0aW1vLCByZWVtcGxhem8gdG9kb3MgbG9zIHZhbG9yZXMgZGlzdGludG9zIGRlIGNlcm8gZGUgbGFzIHZhcmlhYmxlcyBjb250aW51YXMuKjxicj4NCg0KYGBge3IgRWouMy5iIHByZXBhcmFjacOzbn0NCnByb3AxID0gcHJvcCAlPiUgbmFfaWYoMCkNCnByb3AxID0gbmEub21pdChwcm9wMSkNCmBgYA0KYGBge3IgRWouMy5iIG1vZGVsb30NCiMgTW9kZWxvIGxpbmVhbA0KcHJvcF9sbTUgPSBsbShsb2cocHJpY2UpIH4gYmFycmlvcytsb2cocm9vbXMpK2xvZyhiYXRocm9vbXMpK3N1cmZhY2VfcGF0aW8rbG9nKHN1cmZhY2VfY292ZXJlZCkrcHJvcGVydHlfdHlwZSwgZGF0YSA9IHByb3AxKQ0Kc3VtbWFyeShwcm9wX2xtNSkNCmBgYA0KKkVsIFIgY3VhZHJhZG8gYWp1c3RhZG8gZGVsIG1vZGVsbyBlcyBlbCBtYXlvciByZXNwZWN0byBhIGxvcyBhbnRlcmlvcmVzLCB1YmljYW5kb3NlIGVuIHVuIHZhbG9yIGRlbCA4MSw3NiUsIG1heW9yIGFsIG9idGVuaWRvIGFudGVyaW9ybWVudGUgZGUgYXByb3hpbWFkYW1lbnRlIDc1JSBkZSBsYSB2YXJpYWJpbGlkYWQgZGUgPGNvZGU+cHJpY2U8L2NvZGU+Kjxicj4NCg0KKlBhcmEgZXN0ZSBtb2RlbG8gbGEgdmFyaWFibGUgZGUgcmVmZXJlbmNpYSBlcyBjYXNhIHBhcmEgbGEgdmFyaWFibGUgdGlwbyBkZSBwcm9waWVkYWQgeSB1bmEgem9uYSBkZSBwcmVjaW8gYWx0byBwYXJhIGxhIHZhcmlhYmxlIGJhcnJpb3MuIFNpIG9ic2Vydm8gbG9zIFQtVGVzdCBpbmRpdmlkdWFsZXMgc2Ugb2JzZXJ2YSBxdWUgbGEgdmFyaWFibGUgbG9nKHJvb21zKSBubyBlcyB1bmEgdmFyaWFibGUgcmVzcHVlc3RhIGEgbG9nKHByaWNlKSBhIG5pdmVsIGFsZmEgMC4wNS4gRWwgcmVzdG8gZGUgbGFzIHZhcmlhYmxlcyBzaWd1ZW4gY2F5ZW5kbyBkZW50cm8gZGUgbGEgem9uYSBkZSBzaW5pZ2ZpY2F0aXZpZGFkKjxicj4NCg0KDQpgYGB7ciBFai4zLmIgZnJlY3VlbmNpYSBkZSByZXNpZHVvc30NCiMgUmVzaWR1b3MgeSBwcmVkaWNjaW9uZXMgYWwgZGF0YXNldA0KcHJvcDEgPSBwcm9wMSAlPiUgYWRkX3Jlc2lkdWFscyhwcm9wX2xtNSkgJT4lIGFkZF9wcmVkaWN0aW9ucyhwcm9wX2xtNSkNCmBgYA0KYGBge3IgRWouMy5iIGZyZWN1ZW5jaWEgcmVzaWR1b3N9DQojIEZyZWN1ZW5jaWEgcmVzaWR1b3MNCmdncGxvdChwcm9wMSwgYWVzKHJlc2lkKSkgKyBnZW9tX2ZyZXFwb2x5KGJpbndpZHRoID0gMC4xLCBjb2xvcj0gIiM5N2NlNGMiKSsgDQogIGxhYnModGl0bGU9IkZpZ3VyYSA2OiBGcmVjdWVuY2lhIGRlIHJlc2lkdW9zIChkYXRvcyB0cmFuc2Zvcm1hZG9zKSIsIHk9IkZyZWN1ZW5jaWEiLCB4PSJSZXNpZHVvcyIpDQpgYGANCmBgYHtyIEVqLjMuYiBwcm9tZWRpbyByZXNpZHVvc30NCiMgUHJvbWVkaW8gZGUgcmVzaWR1b3MNCm1lYW4ocHJvcDEkcmVzaWQpDQpgYGANCmBgYHtyIEVqLjMuYiBtdWNob3MgZ3LDoWZpY29zLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KcHJvcF9hdWc1ICA9IGF1Z21lbnQocHJvcF9sbTUsIHByb3AxKQ0KIyBSZXNpZHVvcyB2cy4gcHJlZGljY2lvbmVzDQpmaWc3ID0gZ2dwbG90KHByb3BfYXVnNSwgYWVzKC5maXR0ZWQsIC5yZXNpZCkpICsNCiAgZ2VvbV9wb2ludChjb2xvcj0iIzAxQjRDNiIsIGFscGhhPTAuNSkrDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG91ciA9ICIjM2E0NzY3IikgKw0KICBnZW9tX3Ntb290aChzZSA9IEZBTFNFLCBjb2xvdXIgPSAiI0U2NDM1OCIpICsNCiAgbGFicyh0aXRsZT0iRmlndXJhIDc6IERpc3RyaWJ1Y2nDs24gZGUgcmVzaWR1b3MgKGRhdG9zIHRyYW5zZm9ybWFkb3MpIiwgeT0iUmVzaWR1b3MiLCB4PSJQcmVkaWNjaW9uZXMiKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT03KSkNCiMgUVFQbG90DQpmaWc4ID0gZ2dwbG90KHByb3BfYXVnNSwgYWVzKHNhbXBsZT0gLnN0ZC5yZXNpZCkpKw0KICBzdGF0X3FxKGNvbG9yPSIjMDFCNEM2IikrDQogIGdlb21fYWJsaW5lKGNvbG91ciA9ICIjRTY0MzU4IikgKw0KICBsYWJzKHRpdGxlPSJGaWd1cmEgODogUVFQbG90IChkYXRvcyB0cmFuc2Zvcm1hZG9zKSIsIHk9IlJlYWwiLCB4PSJUZcOzcmljbyIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTcpKQ0KIyBTY2FsZS1sb2NhdGlvbiBwbG90DQpmaWc5ID0gZ2dwbG90KHByb3BfYXVnNSwgYWVzKC5maXR0ZWQsIHNxcnQoYWJzKC5zdGQucmVzaWQpKSkpKw0KICBnZW9tX3BvaW50KGNvbG9yPSIjMDFCNEM2IiwgYWxwaGE9MC41KSsNCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSwgY29sb3VyID0gIiNFNjQzNTgiKSArDQogIGxhYnModGl0bGU9IkZpZ3VyYSA5OiBEaXN0cmlidWNpw7NuIGRlIGxhIHJhw616IGRlIGxvcyByZXNpZHVvcyBzdGFuZGFyaXphZG9zIChkYXRvcyB0cmFuc2Zvcm1hZG9zKSIsIHk9IlJhw616IGRlIFJlc2lkdW9zIFN0LiIsIHg9IlByZWRpY2Npb25lcyIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTcpKQ0KIyBzY2FsZSB2cyBsZXZlcmFnZQ0KZmlnMTAgPSBnZ3Bsb3QocHJvcF9hdWc1LCBhZXMoLmhhdCwgLnN0ZC5yZXNpZCkpICsNCiAgZ2VvbV92bGluZShzaXplID0gMSwgY29sb3VyID0gIiMzYTQ3NjciLCB4aW50ZXJjZXB0ID0gMCkgKw0KICBnZW9tX2hsaW5lKHNpemUgPSAxLCBjb2xvdXIgPSAiIzNhNDc2NyIsIHlpbnRlcmNlcHQgPSAwKSArDQogIGdlb21fcG9pbnQoY29sb3I9IiMwMUI0QzYiLCBhbHBoYT0wLjUpICsgDQogIGdlb21fc21vb3RoKHNlID0gRkFMU0UsIGNvbG91ciA9ICIjRTY0MzU4IikgKw0KICBsYWJzKHRpdGxlPSJGaWd1cmEgMTA6IFJlc2lkdW9zIHN0YW5kYXJpemFkb3MgdnMuIExldmVyYWdlIChkYXRvcyB0cmFuc2Zvcm1hZG9zKSIsIHk9IlJlc2lkdW9zIFN0YW5kYXJpemFkb3MiLCB4PSJMZXZlcmFnZSIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTcpKQ0KDQpncmlkLmFycmFuZ2UoZmlnNywgZmlnOCwgZmlnOSwgZmlnMTAsIG5yb3cgPSAyLCBuY29sPTIpDQpgYGANCg0KKkVuIGxhIGZpZ3VyYSA3OiBkaXN0cmlidWNpw7NuIGRlIHJlc2lkdW9zLCBzZSBvYnNlcnZhIHF1ZSBjb24gbGEgdHJhbnNmb3JtYWNpb24gbG9nYXJpdG1pY2EgbG9zIHJlc2lkdW9zIHNlIGRpc3RyaWJ1eWVuIGRlIHVuYSBtYW5lcmEgbcOhcyB1bmlmb3JtZSBhIGxvIGxhcmdvIGRlbCBlamUgWC4gRW4gbGEgZmlndXJhODogUVEtUGxvdCBjb24gbG9zIGRhdG9zIHRyYW5zZm9ybWFkb3MsIHBvZGVtb3Mgb2JzZXJ2YXIgdW5hIG1heW9yIGNvcnJlc3BvbmRlbmNpYSBjb24gZWwgbW9kZWxvIG5vcm1hbC4qPGJyPg0KDQoqQ29uIGxhIHRyYW5zZm9ybWFjacOzbiBsb2dhcml0bWljYSBvYnNlcnZhbW9zIHF1ZSBzZSBjdW1wbGUgY29uIGxvcyBzdXB1ZXN0b3MgZGVsIG1vZGVsbyBsaW5lYWwuIFBvciBvdHJvIGxhZG8gZWwgUiBjdWFkcmFkbyBhanVzdGFkbyBhdW1lbnRhIGRlIDc0LDYlIGEgODEsNyUgZGVsIG1vZGVsbyBhbnRlcmlvciByZXNwZWN0byBhbCBtb2RlbG8gY29uIHRyYW5zZm9ybWFjacOzbiBsb2dhcml0bWljYS4gUG9yIGxvIHRhbnRvIHNlcsOtYSBlbCBtb2RlbG8gYSBjb25zaWRlcmFyIGPDs21vIHbDoWxpZG8uIE90cm8gcHVudG8gYSBjb25zaWRlcmFyIGVzIHF1ZSB0b2RvcyBsb3MgY29lZmljaWVudGVzIHNlIG1hbnRpZW5lbiBjw7NtbyBzaWduaWZpY2F0aXZvcyBpbmRpdmlkdWFsbWVudGUgeSBkZSBtYW5lcmEgZ2xvYmFsIHBvciBlbCBlc3RhZGlzdGljbyBGLio8YnI+DQoNCipFbCB2YWxvciBkZWwgaW50ZXJjZXB0IG5vIHRpZW5lIHNlbnRpZG8gcmVhbCBkYWRvIHF1ZSB0b2RhcyBsYXMgdmFyaWFibGVzIGRlYmVyw61hbiB0b21hciB2YWxvciBjZXJvLio8YnI+DQoNCg0KKkVuIGVsIG1vZGVsbyBhbnRlcmlvciB0bWIgdGVuaWFtb3MgY29tbyBuaXZlbCBkZSByZWZlcmVuY2lhIHVuYSBwcm9waWVkYWQgZGVsIHRpcG8gIkNhc2EiIHBhcmEgbGEgdmFyaWFibGUgPGNvZGU+cHJvcGVydHlfdHlwZTwvY29kZT4geSB1biBiYXJyaW8gZGUgcHJlY2lvIHByb21lZGlvIGFsdG8gcGFyYSA8Y29kZT5iYXJyaW9zPC9jb2RlPi4gU2luIGVtYmFyZ28gZWwgYXVtZW50byBkZWwgcHJlY2lvIGZyZW50ZSBhIHVuIGF1bWVudG8gZGUgPGNvZGU+c3VyZmFjZV9jb3ZlcmVkPC9jb2RlPiBzZSBlc3BlcmFiYSBxdWUgZWwgcHJlY2lvIGF1bWVudGFyYSAyNDYwIFVTRC4gRGFkbyBlbCB0ZXh0byBkZSBXb29sZHJpZ2UsIGxhIHRyYW5zZm9ybWFjacOzbiBsb2dhcml0bWljYSBkZSBlc3RlIG1vZGVsbyBub3MgcGxhbnRlYSBlbCBhbmFsaXNpcyBlbiB0w6lybWlubyBkZSBlbGFzdGljaWRhZGVzLCBlc3RvIHNpZ25pZmljYSBxdWUgZWwgY29lZmljaWVudGUgeWEgbm8gZXMgdW4gbW9udG8gYWJzb2x1dG8sIHNpbm8gcmVsYXRpdm8gYSBsYSB2YXJpYWJsZSBkZXBlbmRpZW50ZS4gRW4gbGEgdHJhbnNmb3JtYWNpw7NuICA8Y29kZT5zdXJmYWNlX2NvdmVyZWQ8L2NvZGU+IHRpZW5lIGPDs21vIGNvZWZpY2llbnRlIDAsNzUsIGVzdG8gcXVpZXJlIGRlY2lyIHF1ZSBtYW50ZW5pZW5kbyBjb25zdGFudGVzIGVsIHJlc3RvIGRlIGxhcyB2YXJpYWJsZXMsIHVuIGF1bWVudG8gZGUgMSUgZW4gbG9zIG0yIGRlIHN1cGVyZmljaWUgY3ViaWVydGEgYXVtZW50YXLDoSB1biAwLDc1JSBlbCBwcmVjaW8gZXNwZXJhZG8gZGUgbGEgdml2aWVuZGEuICo8YnI+DQoNCipFbiBlbCBjYXNvIGRlbCBjb2VmaWNpZW50ZSBkZSBsb2cocm9vbXMpIHN1IHZhbG9yIGVzIGRlIC0wLjAzJSwgbG8gY3VhbCBzaWduaWZpY2EgcXVlIGZyZW50ZSBhIHVuIGF1bWVudG8gZGUgMTAwJSBkZSBsYSBjYW50aWRhZCBkZSBjdWFydG9zIGVsIHByZWNpbyBkaXNtaW51eWUgZW4gMyUuIEVuIGNhbWJpbyBjw7NtbyBlbCBjb2VmaWNpZW50ZSBkZSBsb2coYmF0aHJvb21zKSBlcyAwLDE2NSB1biBhdW1lbnRvIGRlIDEwMCUgZW4gbGEgY2FudGlkYWQgZGUgYmHDsW9zLCBkZXRlcm1pbmEgdW4gYXVtZW50byBkZSAxNiUgZW4gZWwgcHJlY2lvIGVzcGVyYWRvLiBFcyBkZWNpciwgcGFyYSBlbCBjYXNvIGRlIGxhcyB2YXJpYWJsZXMgY29udMOtbnVhcyAoYSBsYXMgY3VhbGVzIHNlIGxlcyBhcGxpY8OzIGxhIHRyYW5zZm9ybWFjacOzbiBsb2dhcsOtdG1pY2EsIGxvcyBjb2VmaWNpZW50ZXMgcHVlZGVuIGludGVycHJldGFyc2UgY8OzbW8gZWwgcG9yY2VudGFqZSBkZSBhdW1lbnRvIGVuIGVsIHByZWNpbyBtZWRpbyBlc3BlcmFkbyBhbCBhdW1lbnRhciAxJSBsYSB2YXJpYWJsZSBleHBsaWNhdGl2YSB5IG1hbnRlbmllbmRvIGVsIHJlc3RvIGZpamFzICo8YnI+DQoNCipFbiBlbCBjYXNvIGRlIDxjb2RlPnN1cmZhY2VfcGF0aW88L2NvZGU+IChsYSBjdWFsIG5vIGZ1ZSB0cmFuc2Zvcm1hZGEpLCBzdSBjb2VmaWNpZW50ZSBtdWx0aXBsaWNhZG8gIHB1ZWRlIGludGVycHJldGFyc2UgY29tbyBlbCBwb2VjZW50YWplIGRlIGF1bWVudG8gZW4gZWwgcHJlY2lvIG1lZGlvIGFsIGF1bWVudGFyIGVuIHVuYSB1bmlkYWQgZGUgbGEgdmFyaWFibGUgeSBtYW50ZW5lciBmaWphIGxhcyBkZW3DoXMuIEVzIGRlY2lyLCBhdW1lbnRhcsOtYSB1biAzJSBlbCB2YWxvciBlc3BlcmFkbyBkZWwgcHJlY2lvIGFsIGF1bWVudGFyIHVuYSB1bmlkYWQgZGUgbGEgc3VwZXJmaWNpZSBjdWJpZXJ0YSBkZSBwYXRpby4qPGJyPg0KDQoNCg0KIyBEYXRhZnJhbWVzIGFuaWRhZG9zDQoqKmEuIEFuaWRhciBwb3IgbGEgdmFyaWFibGUgPGNvZGU+cHJvcGVydHlfdHlwZTwvY29kZT4uKio8YnI+DQpgYGB7ciBFai40LmEgbmVzdH0NCnByb3AyID0gcHJvcCAlPiUgDQogIGdyb3VwX2J5KHByb3BlcnR5X3R5cGUpICU+JSANCiAgbmVzdCgpDQoNCnByb3AyDQpgYGANCg0KKipiLiBDb25zdHJ1aXIgcGFyYSBjYWRhIHRpcG8gZGUgcHJvcGllZGFkIGVsIG1vZGVsbyBkZSAyLmQgZSBpbnRlcnByZXRhciBsb3MgcmVzdWx0YWRvcyBlbiBjYWRhIGNhc28uIFF1w6kgZGlmZXJlbmNpYXMgZW5jdWVudHJhbiBlbnRyZSBsb3MgZGlzdGludG9zIG1vZGVsb3M/Kio8YnI+DQpgYGB7ciBFai40LmIgZnVuY2nDs259DQojIEZ1bmNpw7NuIHBhcmEgY3JlYXIgbG9zIG1vZGVsb3MNCm1vZGVsb3MgPSBmdW5jdGlvbihkZikgew0KICBsbShwcmljZSB+IGJhcnJpb3Mrcm9vbXMrYmF0aHJvb21zK3N1cmZhY2VfcGF0aW8rc3VyZmFjZV9jb3ZlcmVkLCBkYXRhID0gZGYpDQp9DQpgYGANCmBgYHtyIEVqLjQuYn0NCg0KcHJvcDIgPSBwcm9wMiAlPiUgDQogIG11dGF0ZShtb2RlbCA9IG1hcChkYXRhLCBtb2RlbG9zKSkNCnByb3AyJG1vZGVsDQpwcm9wMiAlPiUgDQogIG11dGF0ZShnbG5jID0gbWFwKG1vZGVsLCBnbGFuY2UpKSAlPiUgDQogIHVubmVzdChnbG5jKQ0KYGBgDQoNCg0KDQoqQ2FzYSwgZGVwYXJ0YW1lbnRvIHkgUEggcHJlc2VudGFuIGVsIG1pc21vIG5pdmVsIGRlIHJlZmVyZW5jaWEsIHVuYSBwcm9waWVkYWQgZW4gdW5hIHpvbmEgZGUgcHJlY2lvIHBvciBtZXRybyBjdWFkcmFkbyBwcm9tZWRpbyBhbHRvLiBFbiBsb3MgdHJlcyBjYXNvcyBiYXJyaW9zIGJham8geSBiYXJyaW9zIG1lZGlvIHRpZW5lIHVuIGNvZWZpY2llbnRlIGVzdGltYWRvIG5lZ2F0aXZvIHJlc3BlY3RvIGFsIG5pdmVsIGRlIHJlZmVyZW5jaWEuKjxicj4NCg0KKkVsIGNvZWZpY2llbnRlIGRlIHN1cGVyZmljaWUgY3ViaWVydGEgcmVwcmVzZW50YSB1biBhdW1lbnRvIGVuIGVsIHByZWNpbyBtZWRpby4gU2kgZmlqbyBsYXMgZGVtw6FzIHZhcmlhYmxlcyBlbiBlbCBjYXNvIGRlIGRlcGFydGFtZW50b3MgdmVvIHF1ZSBkdXBsaWNhIHkgY2FzaSB0cmlwbGljYSBhIFBowrRzIHkgY2FzYXMuKjxicj4NCg0KKkxhIHZhcmlhYmlsaWRhZCBkZSBsYSByZXNwdWVzdGEgZXhwbGljYWRhIHBvciBjYWRhIG1vZGVsbyBlcyBhcHJveGltYWRhbWVudGUgNTklIHBhcmEgY2FzYSwgNzclIHBhcmEgZGVwYXJ0YW1lbnRvIHkgNjklIHBhcmEgUEg7IG5pbmd1bm8gc3VwZXJhIGFsIG1vZGVsbyBhbnRlcmlvciBjb24gbGEgdHJhbnNmb3JtYWNpw7NuIGxvZ2Fyw610bWljYS4gTG9zIGRlc3Zpb3MgYXVtZW50YW4gZGFkbyBxdWUgYWhvcmEgdGVuZW1vcyB1biBtb2RlbG8gbcOhcyBjb21wbGVqby4qPGJyPg0KDQoNCg0KDQoNCg0KDQo=