Este problema es una de las competencias juego de la plataforma Kaggle, en la cual busca predecir el precio de venta de una propiedad en dólares (SalePrice) teniendo un gran número de características (79) como su área, número de habitaciones, área del garaje, altura del sótano, etc.

Se evalúa el nivel de ajuste del modelo en base a la raíz del error cuadrático medio (RMSE).

Enlace competencia: https://www.kaggle.com/c/house-prices-advanced-regression-techniques/overview

la competencia brinda una base de entrenamiento y una base de prueba, en esta última se debe predecir el precio de venta de un conjunto de propiedades desconociendo su valor original.

Con la ayuda de R se crea una función para calcular el RMSE de las predicciones obtenidas.

A continuación se presentarán los dos mejores modelos de ambos estudiantes, ambos seleccionados por el puntaje alcanzado en la competencia.

1 Jaime Andrés Molina Correa - Mejor modelo (0.15649 de puntaje)

Se realizaron modelos de regresión lineal, bagging y Random Forest para predecir el predecir el precio de venta de una propiedad. El mejor modelo obtenido fue un baggin con 12 variables consideradas. El procedimiento para llegar al modelo se enseña a continuación.

paquetes utilizados:

A continuación se enseñan el número de datos faltantes (NA) en las variables del conjunto de entrenamiento. Las que no se muestran no tienen datos faltantes.

##       PoolQC  MiscFeature        Alley        Fence  FireplaceQu  LotFrontage 
##         1453         1406         1369         1179          690          259 
##   GarageType  GarageYrBlt GarageFinish   GarageQual   GarageCond BsmtExposure 
##           81           81           81           81           81           38 
## BsmtFinType2     BsmtQual     BsmtCond BsmtFinType1   MasVnrType   MasVnrArea 
##           38           37           37           37            8            8 
##   Electrical 
##            1

Se eliminan las variables con mayor número de datos faltantes, variable con más de 50 faltantes en el conjunto de entrenamiento se desprecia.

Posteriormente se eliminan las observaciones con datos faltantes ya que ahora se podrían perder pocas observaciones.

1.1 Modelo Random Forest para selección de variables.

Para entrenar un modelo con el método Random Forest se hace uso de la función randomForest del paquete randomForest.

Se procede a la creación del modelo con el número de árboles que utiliza por defecto la función (500). El número de variables que selecciona aleatoriamente en cada muestra bootstrap es calculado según el número de variables consideradas, para este número de variables se usan 22 en cada muestra.

## 
## Call:
##  randomForest(formula = SalePrice ~ ., data = train[, -1], importance = TRUE) 
##                Type of random forest: regression
##                      Number of trees: 500
## No. of variables tried at each split: 22
## 
##           Mean of squared residuals: 781781463
##                     % Var explained: 87.55

A continación se muestran cuales son las variables que aportan más al modelo según dos metricas diferentes.

1.2 Modelo Bagging.

En un principio se pensó en utilizar las 3 variables que son más informativas según el MSE, pero al no tener muy buenos resultados en el puntaje de la competencia, se decide utilizar las primeras 12. A continuación se crea el modelo.

## 
## Call:
##  randomForest(formula = SalePrice ~ GrLivArea + Neighborhood +      OverallQual + TotalBsmtSF + X1stFlrSF + X2ndFlrSF + GarageCars +      GarageArea + LotArea + BsmtFinSF1 + ExterQual + FullBath,      data = train, importance = TRUE, ntree = 500, mtry = 12) 
##                Type of random forest: regression
##                      Number of trees: 500
## No. of variables tried at each split: 12
## 
##           Mean of squared residuals: 847029853
##                     % Var explained: 86.51

1.3 Conjunto de prueba kaggle

Se seleccionan solo las variables usadas en el modelo final

número de datos faltantes en el conjunto de prueba.

##  TotalBsmtSF   GarageCars   GarageArea   BsmtFinSF1           Id    GrLivArea 
##            1            1            1            1            0            0 
## Neighborhood  OverallQual    X1stFlrSF    X2ndFlrSF      LotArea    ExterQual 
##            0            0            0            0            0            0 
##     FullBath 
##            0

Se puede observar que cuatro de las variables usadas en el modelo tienen un valor faltante, por lo que se deben reemplazar. Como son variables continuas se decide reemplazar el valor faltante con la mediana de la respectiva variable en el conjunto de entrenamiento

1.4 Predicción y creación de base de datos

Finalmente, con la ayuda de la función predict() se obtienen los valores ajustados para subir a la competencia.

Por último, se crea la base de datos.

2 Valentina Garcia Velasquez - Mejor modelo (0.13398 de puntaje)

Se lee nuevamente el conjunto de datos y entrenamiento

Se seleccionan únicamente las columnas numéricas y se reeemplazan los NA con el valor -99.

Se crea una matriz con las covariables y otra para la variable respuesta, re realiza el mismo procedimiento para el conjunto de prueba.

3 Evidencias

3.1 Ranking alcanzado

3.2 Mejor puntaje Valentina Garcia

3.3 Mejor puntaje Jaime Molina

LS0tCnRpdGxlOiAiSG91c2UgUHJpY2VzOiBBZHZhbmNlZCBSZWdyZXNzaW9uIFRlY2huaXF1ZXMiCmF1dGhvcjogIlZhbGVudGluYSBHYXJjw61hIFZlbGFzcXVleiAtIEphaW1lIEFuZHJlcyBNb2xpbmEgQ29ycmVhIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBjb3NtbwogICAgaGlnaGxpZ2h0OiBrYXRlCiAgICBjc3M6IGZvcm1hdC5jc3MKICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IFRSVUUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkKYGBgCgoKRXN0ZSBwcm9ibGVtYSBlcyB1bmEgZGUgbGFzIGNvbXBldGVuY2lhcyBqdWVnbyBkZSBsYSBwbGF0YWZvcm1hIEthZ2dsZSwgZW4gbGEgY3VhbCBidXNjYSBwcmVkZWNpciBlbCBwcmVjaW8gZGUgdmVudGEgZGUgdW5hIHByb3BpZWRhZCBlbiBkw7NsYXJlcyAoU2FsZVByaWNlKSB0ZW5pZW5kbyB1biBncmFuIG7Dum1lcm8gZGUgY2FyYWN0ZXLDrXN0aWNhcyAoNzkpIGNvbW8gc3Ugw6FyZWEsIG7Dum1lcm8gZGUgaGFiaXRhY2lvbmVzLCDDoXJlYSBkZWwgZ2FyYWplLCBhbHR1cmEgZGVsIHPDs3Rhbm8sIGV0Yy4KClNlIGV2YWzDumEgZWwgbml2ZWwgZGUgYWp1c3RlIGRlbCBtb2RlbG8gZW4gYmFzZSBhIGxhIHJhw616IGRlbCBlcnJvciBjdWFkcsOhdGljbyBtZWRpbyAoUk1TRSkuCgpFbmxhY2UgY29tcGV0ZW5jaWE6IGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vYy9ob3VzZS1wcmljZXMtYWR2YW5jZWQtcmVncmVzc2lvbi10ZWNobmlxdWVzL292ZXJ2aWV3CgpsYSBjb21wZXRlbmNpYSBicmluZGEgdW5hIGJhc2UgZGUgZW50cmVuYW1pZW50byB5IHVuYSBiYXNlIGRlIHBydWViYSwgZW4gZXN0YSDDumx0aW1hIHNlIGRlYmUgcHJlZGVjaXIgZWwgcHJlY2lvIGRlIHZlbnRhIGRlIHVuIGNvbmp1bnRvIGRlIHByb3BpZWRhZGVzIGRlc2Nvbm9jaWVuZG8gc3UgdmFsb3Igb3JpZ2luYWwuCgpgYGB7cn0KIyBCYXNlIGRlIGVudHJlbmFtaWVudG8KdHJhaW4gPC0gcmVhZC5jc3YoZmlsZSA9ICJ0cmFpbi5jc3YiLCBoZWFkZXIgPSBULCBzdHJpbmdzQXNGYWN0b3JzID0gVCkKCiMgQmFzZSBkZSBwcnVlYmEKdGVzdCA8LSByZWFkLmNzdihmaWxlID0gInRlc3QuY3N2IiwgaGVhZGVyID0gVCwgc3RyaW5nc0FzRmFjdG9ycyA9IFQpCmBgYAoKQ29uIGxhIGF5dWRhIGRlIFIgc2UgY3JlYSB1bmEgZnVuY2nDs24gcGFyYSBjYWxjdWxhciBlbCBSTVNFIGRlIGxhcyBwcmVkaWNjaW9uZXMgb2J0ZW5pZGFzLiAKCmBgYHtyfQpSTVNFIDwtIGZ1bmN0aW9uKHksIHloYXQpIHNxcnQobWVhbigoeS15aGF0KSoqMikpCmBgYAoKQSBjb250aW51YWNpw7NuIHNlIHByZXNlbnRhcsOhbiBsb3MgZG9zIG1lam9yZXMgbW9kZWxvcyBkZSBhbWJvcyBlc3R1ZGlhbnRlcywgYW1ib3Mgc2VsZWNjaW9uYWRvcyBwb3IgZWwgcHVudGFqZSBhbGNhbnphZG8gZW4gbGEgY29tcGV0ZW5jaWEuCgojIEphaW1lIEFuZHLDqXMgTW9saW5hIENvcnJlYSAtIE1lam9yIG1vZGVsbyAoMC4xNTY0OSBkZSBwdW50YWplKQoKU2UgcmVhbGl6YXJvbiBtb2RlbG9zIGRlIHJlZ3Jlc2nDs24gbGluZWFsLCBiYWdnaW5nIHkgUmFuZG9tIEZvcmVzdCBwYXJhIHByZWRlY2lyIGVsIHByZWRlY2lyIGVsIHByZWNpbyBkZSB2ZW50YSBkZSB1bmEgcHJvcGllZGFkLiBFbCBtZWpvciBtb2RlbG8gb2J0ZW5pZG8gZnVlIHVuIGJhZ2dpbiBjb24gMTIgdmFyaWFibGVzIGNvbnNpZGVyYWRhcy4gRWwgcHJvY2VkaW1pZW50byBwYXJhIGxsZWdhciBhbCBtb2RlbG8gc2UgZW5zZcOxYSBhIGNvbnRpbnVhY2nDs24uCgoqKnBhcXVldGVzIHV0aWxpemFkb3M6KioKCmBgYHtyfQpsaWJyYXJ5KHJhbmRvbUZvcmVzdCkgIyBQYXJhIGNyZWFyIG1vZGVsb3MgZGUgYm9zcXVlcyBhbGVhdG9yaW9zIHkgYmFnZ2luZwpsaWJyYXJ5KGRwbHlyKSAgICAgICAgIyBQYXJhIG1vZGlmaWNhciBsb3MgY29uanVudG9zIGRlIGRhdG9zLgpgYGAKCmBgYHtyfQpzZW1pbGxhIDwtIDE5OTggIyBTZSBjcmVhIHVuYSBzZW1pbGxhIHBhcmEgcmVwcm9kdWN0aXZpZGFkLgpgYGAKCkEgY29udGludWFjacOzbiBzZSBlbnNlw7FhbiBlbCBuw7ptZXJvIGRlIGRhdG9zIGZhbHRhbnRlcyAoYE5BYCkgZW4gbGFzIHZhcmlhYmxlcyBkZWwgY29uanVudG8gZGUgZW50cmVuYW1pZW50by4gTGFzIHF1ZSBubyBzZSBtdWVzdHJhbiBubyB0aWVuZW4gZGF0b3MgZmFsdGFudGVzLgoKYGBge3J9CnNvcnQoc2FwcGx5KHRyYWluLCBmdW5jdGlvbih5KSBzdW0obGVuZ3RoKHdoaWNoKGlzLm5hKHkpKSkpKSwgZGVjcmVhc2luZyA9IFQpWzE6MTldCmBgYAoKU2UgZWxpbWluYW4gbGFzIHZhcmlhYmxlcyBjb24gbWF5b3IgbsO6bWVybyBkZSBkYXRvcyBmYWx0YW50ZXMsIHZhcmlhYmxlIGNvbiBtw6FzIGRlIDUwIGZhbHRhbnRlcyBlbiBlbCBjb25qdW50byBkZSBlbnRyZW5hbWllbnRvIHNlIGRlc3ByZWNpYS4KCmBgYHtyfQp0cmFpbiA8LSB0cmFpbiAlPiUgc2VsZWN0KC1jKFBvb2xRQywgTWlzY0ZlYXR1cmUsIEFsbGV5LCBGZW5jZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGaXJlcGxhY2VRdSwgTG90RnJvbnRhZ2UsIEdhcmFnZVR5cGUsIEdhcmFnZVlyQmx0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdhcmFnZUZpbmlzaCwgR2FyYWdlUXVhbCxHYXJhZ2VDb25kKSkKYGBgCgpQb3N0ZXJpb3JtZW50ZSBzZSBlbGltaW5hbiBsYXMgb2JzZXJ2YWNpb25lcyBjb24gZGF0b3MgZmFsdGFudGVzIHlhIHF1ZSBhaG9yYSBzZSBwb2Ryw61hbiBwZXJkZXIgcG9jYXMgb2JzZXJ2YWNpb25lcy4KCmBgYHtyfQp0cmFpbiA8LSBuYS5vbWl0KHRyYWluKQpgYGAKCgojIyBNb2RlbG8gUmFuZG9tIEZvcmVzdCBwYXJhIHNlbGVjY2nDs24gZGUgdmFyaWFibGVzLgoKUGFyYSBlbnRyZW5hciB1biBtb2RlbG8gY29uIGVsIG3DqXRvZG8gKlJhbmRvbSBGb3Jlc3QqIHNlIGhhY2UgdXNvIGRlIGxhIGZ1bmNpw7NuIGByYW5kb21Gb3Jlc3RgIGRlbCBwYXF1ZXRlIGByYW5kb21Gb3Jlc3RgLgoKU2UgcHJvY2VkZSBhIGxhIGNyZWFjacOzbiBkZWwgbW9kZWxvIGNvbiBlbCBuw7ptZXJvIGRlIMOhcmJvbGVzIHF1ZSB1dGlsaXphIHBvciBkZWZlY3RvIGxhIGZ1bmNpw7NuICg1MDApLiBFbCBuw7ptZXJvIGRlIHZhcmlhYmxlcyBxdWUgc2VsZWNjaW9uYSBhbGVhdG9yaWFtZW50ZSBlbiBjYWRhIG11ZXN0cmEgYm9vdHN0cmFwIGVzIGNhbGN1bGFkbyBzZWfDum4gZWwgbsO6bWVybyBkZSB2YXJpYWJsZXMgY29uc2lkZXJhZGFzLCBwYXJhIGVzdGUgbsO6bWVybyBkZSB2YXJpYWJsZXMgc2UgdXNhbiAyMiBlbiBjYWRhIG11ZXN0cmEuCgpgYGB7cn0Kc2V0LnNlZWQoc2VtaWxsYSkKbW9kUkYgPC0gcmFuZG9tRm9yZXN0KFNhbGVQcmljZSB+IC4sIGRhdGEgPSB0cmFpblssLTFdLCBpbXBvcnRhbmNlID0gVFJVRSkKbW9kUkYKYGBgCgpBIGNvbnRpbmFjacOzbiBzZSBtdWVzdHJhbiBjdWFsZXMgc29uIGxhcyB2YXJpYWJsZXMgcXVlIGFwb3J0YW4gbcOhcyBhbCBtb2RlbG8gc2Vnw7puIGRvcyBtZXRyaWNhcyBkaWZlcmVudGVzLgoKYGBge3J9CnZhckltcFBsb3QobW9kUkYsIGNvbCA9IDQsIHBjaCA9IDE2LCBtYWluID0gIk1vZGVsbyBSYW5kb20gRm9yZXN0IiwgY2V4ID0gMC42NSkKYGBgCgojIyBNb2RlbG8gQmFnZ2luZy4KCkVuIHVuIHByaW5jaXBpbyBzZSBwZW5zw7MgZW4gdXRpbGl6YXIgbGFzIDMgdmFyaWFibGVzIHF1ZSBzb24gbcOhcyBpbmZvcm1hdGl2YXMgc2Vnw7puIGVsIE1TRSwgcGVybyBhbCBubyB0ZW5lciBtdXkgYnVlbm9zIHJlc3VsdGFkb3MgZW4gZWwgcHVudGFqZSBkZSBsYSBjb21wZXRlbmNpYSwgc2UgZGVjaWRlIHV0aWxpemFyIGxhcyBwcmltZXJhcyAxMi4gQSBjb250aW51YWNpw7NuIHNlIGNyZWEgZWwgbW9kZWxvLgoKCmBgYHtyfQpzZXQuc2VlZChzZW1pbGxhKQptb2RiYWcgPC0gcmFuZG9tRm9yZXN0KFNhbGVQcmljZSB+IEdyTGl2QXJlYSArIE5laWdoYm9yaG9vZCArIE92ZXJhbGxRdWFsICsKICAgICAgICAgICAgICAgICAgICAgICAgVG90YWxCc210U0YgKyBYMXN0RmxyU0YgKyBYMm5kRmxyU0YgKyBHYXJhZ2VDYXJzICsKICAgICAgICAgICAgICAgICAgICAgICAgR2FyYWdlQXJlYSArIExvdEFyZWEgKyBCc210RmluU0YxICsgRXh0ZXJRdWFsICsgRnVsbEJhdGgsCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gdHJhaW4sCiAgICAgICAgICAgICAgICAgICAgICBpbXBvcnRhbmNlID0gVFJVRSwgbnRyZWUgPSA1MDAsIG10cnkgPSAxMikKCm1vZGJhZwpgYGAKCgojIyBDb25qdW50byBkZSBwcnVlYmEga2FnZ2xlCgpTZSBzZWxlY2Npb25hbiBzb2xvIGxhcyB2YXJpYWJsZXMgdXNhZGFzIGVuIGVsIG1vZGVsbyBmaW5hbAoKYGBge3J9CnRlc3QgPC0gdGVzdCAlPiUgc2VsZWN0KElkLCBHckxpdkFyZWEsIE5laWdoYm9yaG9vZCwgT3ZlcmFsbFF1YWwsIFRvdGFsQnNtdFNGLAogICAgICAgICAgICAgICAgICAgICAgICBYMXN0RmxyU0YsIFgybmRGbHJTRiwgR2FyYWdlQ2FycywgR2FyYWdlQXJlYSwgTG90QXJlYSwKICAgICAgICAgICAgICAgICAgICAgICAgQnNtdEZpblNGMSwgRXh0ZXJRdWFsLCBGdWxsQmF0aCkKYGBgCgpuw7ptZXJvIGRlIGRhdG9zIGZhbHRhbnRlcyBlbiBlbCBjb25qdW50byBkZSBwcnVlYmEuCgpgYGB7cn0Kc29ydChzYXBwbHkodGVzdCwgZnVuY3Rpb24oeSkgc3VtKGxlbmd0aCh3aGljaChpcy5uYSh5KSkpKSksIGRlY3JlYXNpbmcgPSBUKQpgYGAKClNlIHB1ZWRlIG9ic2VydmFyIHF1ZSBjdWF0cm8gZGUgbGFzIHZhcmlhYmxlcyB1c2FkYXMgZW4gZWwgbW9kZWxvIHRpZW5lbiB1biB2YWxvciBmYWx0YW50ZSwgcG9yIGxvIHF1ZSBzZSBkZWJlbiByZWVtcGxhemFyLiBDb21vIHNvbiB2YXJpYWJsZXMgY29udGludWFzIHNlIGRlY2lkZSByZWVtcGxhemFyIGVsIHZhbG9yIGZhbHRhbnRlIGNvbiBsYSBtZWRpYW5hIGRlIGxhIHJlc3BlY3RpdmEgdmFyaWFibGUgZW4gZWwgY29uanVudG8gZGUgZW50cmVuYW1pZW50bwoKYGBge3J9CnRlc3QkVG90YWxCc210U0ZbaXMubmEodGVzdCRUb3RhbEJzbXRTRildIDwtIG1lZGlhbih0cmFpbiRUb3RhbEJzbXRTRiwgbmEucm0gPSBUKQp0ZXN0JEdhcmFnZUNhcnNbaXMubmEodGVzdCRHYXJhZ2VDYXJzKV0gPC0gbWVkaWFuKHRyYWluJEdhcmFnZUNhcnMsIG5hLnJtID0gVCkKdGVzdCRHYXJhZ2VBcmVhW2lzLm5hKHRlc3QkR2FyYWdlQXJlYSldIDwtIG1lZGlhbih0cmFpbiRHYXJhZ2VBcmVhLCBuYS5ybSA9IFQpCnRlc3QkQnNtdEZpblNGMVtpcy5uYSh0ZXN0JEJzbXRGaW5TRjEpXSA8LSBtZWRpYW4odHJhaW4kQnNtdEZpblNGMSwgbmEucm0gPSBUKQpgYGAKCiMjIFByZWRpY2Npw7NuIHkgY3JlYWNpw7NuIGRlIGJhc2UgZGUgZGF0b3MKCkZpbmFsbWVudGUsIGNvbiBsYSBheXVkYSBkZSBsYSBmdW5jacOzbiBgcHJlZGljdCgpYCBzZSBvYnRpZW5lbiBsb3MgdmFsb3JlcyBhanVzdGFkb3MgcGFyYSBzdWJpciBhIGxhIGNvbXBldGVuY2lhLgoKYGBge3J9CnRlc3QuU2FsZXMgPC0gcHJlZGljdChtb2RiYWcsIG5ld2RhdGEgPSB0ZXN0LCB0eXBlID0gInJlc3BvbnNlIikKYGBgCgpQb3Igw7psdGltbywgc2UgY3JlYSBsYSBiYXNlIGRlIGRhdG9zLgoKYGBge3IsIGV2YWw9RkFMU0V9CndyaXRlLmNzdihkYXRhLmZyYW1lKElkID0gdGVzdCRJZCwgU2FsZVByaWNlID0gdGVzdC5TYWxlcyksIGZpbGUgPSAiYmFnZ2luMTIuY3N2IiwKICAgICAgICAgIHJvdy5uYW1lcyA9IEYpCmBgYAoKCiMgVmFsZW50aW5hIEdhcmNpYSBWZWxhc3F1ZXogLSBNZWpvciBtb2RlbG8gKDAuMTMzOTggZGUgcHVudGFqZSkKCgpgYGB7cn0KbGlicmFyeSh4Z2Jvb3N0KQpsaWJyYXJ5KGNhcmV0KQpgYGAKClNlIGxlZSBudWV2YW1lbnRlIGVsIGNvbmp1bnRvIGRlIGRhdG9zIHkgZW50cmVuYW1pZW50bwoKCmBgYHtyfQojIExlZXIgZGF0b3MgZGUgZW50cmVuYW1pZW50bwpkZiA8LSByZWFkLmNzdigndHJhaW4uY3N2Jywgc3RyaW5nc0FzRmFjdG9ycyA9IFQpCnRlc3QgPC0gcmVhZC5jc3YoJ3Rlc3QuY3N2Jywgc3RyaW5nc0FzRmFjdG9ycyA9IFQpCmBgYAoKU2Ugc2VsZWNjaW9uYW4gw7puaWNhbWVudGUgbGFzIGNvbHVtbmFzIG51bcOpcmljYXMgeSBzZSByZWVlbXBsYXphbiBsb3MgTkEgY29uIGVsIHZhbG9yIC05OS4KCmBgYHtyfQpudW1lcmljX2NvbHVtbnMgPC0gZGYgJT4lIGRwbHlyOjpzZWxlY3Qod2hlcmUoaXMubnVtZXJpYykpCm51bWVyaWNfY29sdW1uc1tpcy5uYShudW1lcmljX2NvbHVtbnMpXSA8LSAtOTkKYGBgCgoKU2UgY3JlYSB1bmEgbWF0cml6IGNvbiBsYXMgY292YXJpYWJsZXMgeSBvdHJhIHBhcmEgbGEgdmFyaWFibGUgcmVzcHVlc3RhLCByZSByZWFsaXphIGVsIG1pc21vIHByb2NlZGltaWVudG8gcGFyYSBlbCBjb25qdW50byBkZSBwcnVlYmEuCgpgYGB7cn0KdHJhaW5feCA8LSBkYXRhLm1hdHJpeChudW1lcmljX2NvbHVtbnNbLCAtYygxLDM4KV0pCnRyYWluX3kgPC0gbnVtZXJpY19jb2x1bW5zWywgMzhdCmBgYAoKCmBgYHtyfQpudW1lcmljX2NvbHVtbnMyIDwtIHRlc3QgJT4lIGRwbHlyOjpzZWxlY3Qod2hlcmUoaXMubnVtZXJpYykpCm51bWVyaWNfY29sdW1uczJbaXMubmEobnVtZXJpY19jb2x1bW5zMildIDwtIC05OQpgYGAKCmBgYHtyfQp0ZXN0X3ggPSBkYXRhLm1hdHJpeChudW1lcmljX2NvbHVtbnMyWywgLTFdKQpgYGAKCiMjIE1vZGVsbyB4Z2Jvb3N0IGNvbiBncmlkIHNlYXJjaCAoTWVqb3IgbW9kZWxvKQoKU2UgYWp1c3RhIHVuIG1vZGVsbyBYR0Jvb3N0LCBzZSByZWFsaXphIHVuYSByZWppbGxhIGNvbiB2YWxvcmVzIHBhcmEgbG9zIGRpZmVyZW50ZXMgcGFyw6FtZXRyb3MgeSBzZSBvYnRpZW5lIGVsIG3DoXMgw7NwdGltbyBjb24gZWwgbcOpdG9kbyBjcm9zcyB2YWxpZGF0aW9uLgoKYGBge3J9CiMgU2UgZGViZW4gcHJlcGFyYXIgbG9zIGRhdG9zIGRlIG90cmEgZm9ybWEKWCA8LSB4Z2IuRE1hdHJpeChhcy5tYXRyaXgodHJhaW5feCkpCnkgPC0gdHJhaW5feQoKeGdiX3RyY29udHJvbCA9IHRyYWluQ29udHJvbCgKICBtZXRob2QgPSAiY3YiLCAjIENyb3NzIHZhbGlkYXRpb24KICBudW1iZXIgPSAxMCwgIAogIGFsbG93UGFyYWxsZWwgPSBUUlVFLAogIHZlcmJvc2VJdGVyID0gRkFMU0UsCiAgcmV0dXJuRGF0YSA9IEZBTFNFCikKCnhnYkdyaWQgPC0gZXhwYW5kLmdyaWQobnJvdW5kcz1jKDEwMCwyMDAsMzAwLDQwMCksCiAgICAgICAgICAgICAgICAgICAgICAgbWF4X2RlcHRoID0gYygzOjcpLAogICAgICAgICAgICAgICAgICAgICAgIGV0YSA9IHNlcSgwLjA1LCAxLDEwKSwKICAgICAgICAgICAgICAgICAgICAgICBnYW1tYSA9IHNlcSgwLjAxLDEsMTApLAogICAgICAgICAgICAgICAgICAgICAgIGNvbHNhbXBsZV9ieXRyZWUgPSBjKDAuNzUpLAogICAgICAgICAgICAgICAgICAgICAgIHN1YnNhbXBsZSA9IGMoMC41MCksCiAgICAgICAgICAgICAgICAgICAgICAgbWluX2NoaWxkX3dlaWdodCA9IGMoMCkpCmBgYAoKRW50cmVuYW1pZW50byBkZWwgbW9kZWxvCgpgYGB7ciwgd2FybmluZz1GfQptb2QyIDwtIHRyYWluKAogIFgsIHksCiAgdHJDb250cm9sID0geGdiX3RyY29udHJvbCwKICB0dW5lR3JpZCA9IHhnYkdyaWQsCiAgbWV0aG9kID0gInhnYlRyZWUiLAogIG9iamVjdGl2ZSA9ICdyZWc6c3F1YXJlZGVycm9yJwopCgpgYGAKClNlIGd1YXJkYW4gbGFzIHByZWRpY2Npb25lcwpgYGB7cn0KeGdiX3Rlc3QgPC0geGdiLkRNYXRyaXgoYXMubWF0cml4KHRlc3RfeCkpCnByZWRfeSA8LSBwcmVkaWN0KG1vZDIsIHhnYl90ZXN0KQp3cml0ZS5jc3YoZGF0YS5mcmFtZShJZCA9IG51bWVyaWNfY29sdW1uczIkSWQsIFNhbGVQcmljZSA9IHByZWRfeSksJ3NhbXBsZTMuY3N2Jyxyb3cubmFtZXMgPSBGKQpgYGAKCgoKIyMgTW9kZWxvIFhHQm9vc3QgY29uIGdyaWRzZWFyY2ggeSB2YXJpYWJsZXMgc2VsZWNjaW9uYWRhcyBhbnRlcmlvcm1lbnRlIGNvbiBSRgoKU2FsZVByaWNlIH4gLAogICAgICAgICAgICAgICAgICAgICAgICAKYGBge3J9CnRyYWluX3gyIDwtIG51bWVyaWNfY29sdW1uc1ssIC1jKDEsMzgpXQp0cmFpbl94MiA8LSBkYXRhLm1hdHJpeCh0cmFpbl94MlssYygnR3JMaXZBcmVhJywnT3ZlcmFsbFF1YWwnLAogICAgICAgICAgICAgICAgICAgICAgICAnVG90YWxCc210U0YnLCdYMXN0RmxyU0YnLCdYMm5kRmxyU0YnLCdHYXJhZ2VDYXJzJywKICAgICAgICAgICAgICAgICAgICAgICAgJ0dhcmFnZUFyZWEnLCAnTG90QXJlYScsICdCc210RmluU0YxJywnRnVsbEJhdGgnKV0pCnRyYWluX3kyIDwtIG51bWVyaWNfY29sdW1uc1ssIDM4XQp0ZXN0X3gyIDwtIG51bWVyaWNfY29sdW1uczJbLCAtMV0KdGVzdF94MiA8LSBkYXRhLm1hdHJpeCh0ZXN0X3gyWyxjKCdHckxpdkFyZWEnLCdPdmVyYWxsUXVhbCcsCiAgICAgICAgICAgICAgICAgICAgICAgICdUb3RhbEJzbXRTRicsJ1gxc3RGbHJTRicsJ1gybmRGbHJTRicsJ0dhcmFnZUNhcnMnLAogICAgICAgICAgICAgICAgICAgICAgICAnR2FyYWdlQXJlYScsICdMb3RBcmVhJywgJ0JzbXRGaW5TRjEnLCdGdWxsQmF0aCcpXSkKCgojIFNlIGRlYmVuIHByZXBhcmFyIGxvcyBkYXRvcyBkZSBvdHJhIGZvcm1hClgyIDwtIHhnYi5ETWF0cml4KGFzLm1hdHJpeCh0cmFpbl94MikpCnkyIDwtIHRyYWluX3kyCgp4Z2JfdHJjb250cm9sID0gdHJhaW5Db250cm9sKAogIG1ldGhvZCA9ICJjdiIsICMgQ3Jvc3MgdmFsaWRhdGlvbgogIG51bWJlciA9IDEwLCAgCiAgYWxsb3dQYXJhbGxlbCA9IFRSVUUsCiAgdmVyYm9zZUl0ZXIgPSBGQUxTRSwKICByZXR1cm5EYXRhID0gRkFMU0UKKQoKeGdiR3JpZCA8LSBleHBhbmQuZ3JpZChucm91bmRzPWMoMTAwLDIwMCwzMDAsNDAwKSwKICAgICAgICAgICAgICAgICAgICAgICBtYXhfZGVwdGggPSBjKDM6NyksCiAgICAgICAgICAgICAgICAgICAgICAgZXRhID0gc2VxKDAuMDUsIDEsMTApLAogICAgICAgICAgICAgICAgICAgICAgIGdhbW1hID0gc2VxKDAuMDEsMSwxMCksCiAgICAgICAgICAgICAgICAgICAgICAgY29sc2FtcGxlX2J5dHJlZSA9IGMoMC43NSksCiAgICAgICAgICAgICAgICAgICAgICAgc3Vic2FtcGxlID0gYygwLjUwKSwKICAgICAgICAgICAgICAgICAgICAgICBtaW5fY2hpbGRfd2VpZ2h0ID0gYygwKSkKYGBgCgoKYGBge3IsIHdhcm5pbmc9Rn0KbW9kMyA8LSB0cmFpbigKICBYMiwgeTIsCiAgdHJDb250cm9sID0geGdiX3RyY29udHJvbCwKICB0dW5lR3JpZCA9IHhnYkdyaWQsCiAgbWV0aG9kID0gInhnYlRyZWUiLAogIG9iamVjdGl2ZSA9ICdyZWc6c3F1YXJlZGVycm9yJwopCmBgYAoKYGBge3J9CnhnYl90ZXN0MiA8LSB4Z2IuRE1hdHJpeChhcy5tYXRyaXgodGVzdF94MikpCnByZWRfeTIgPC0gcHJlZGljdChtb2QzLCB4Z2JfdGVzdDIpCndyaXRlLmNzdihkYXRhLmZyYW1lKElkID0gbnVtZXJpY19jb2x1bW5zMiRJZCwgU2FsZVByaWNlID0gcHJlZF95MiksJ2ZpbmFsX3NhbXBsZS5jc3YnLHJvdy5uYW1lcyA9IEYpCmBgYAoKIyBFdmlkZW5jaWFzCgoKIyMgUmFua2luZyBhbGNhbnphZG8KCjxpbWcgc3JjPSJSYW5raW5nLkpQRyIgd2lkdGg9IjYwMCIvPgoKIyMgTWVqb3IgcHVudGFqZSBWYWxlbnRpbmEgR2FyY2lhCgo8aW1nIHNyYz0icHVudGFqZV92YWxlbi5KUEciIHdpZHRoPSI2MDAiLz4KCiMjIE1lam9yIHB1bnRhamUgSmFpbWUgTW9saW5hCgo8aW1nIHNyYz0icHVudGFqZV9qYWltZS5KUEciIHdpZHRoPSI2MDAiLz4KCg==