1 Libraries and raw data

library(tidyverse)
library(magrittr)
library(sf)
library(tmap)

library(spdep) # Spatial weights, Moran's I, and LISA
library(spatialreg) # Spatial Regression

library(spgwr) # GWR
load("../04_MexicoCity_HTS/Mexico_HTS.RData")
ls()
[1] "MexicoCity_HTS"

1.1 Remove districts

summary(MexicoCity_HTS$TotalPeople)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
    634     968    1035    1027    1103    1333       1 
MexicoCity_HTS %>% filter(is.na(TotalPeople)) %>% select(Distrito)
Simple feature collection with 1 feature and 1 field
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -99.09278 ymin: 19.41697 xmax: -99.04731 ymax: 19.45018
Geodetic CRS:  WGS 84
  Distrito                       geometry
1      034 MULTIPOLYGON (((-99.08461 1...
MexicoCity_HTS %<>% filter(Distrito != "034")
summary(MexicoCity_HTS$Total_Homes)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  272.0   285.0   293.0   293.7   301.0   352.0 

1.2 Map preparation

MexicoCity_Fringe <- st_read("../04_MexicoCity_HTS/UrbanFringe_MexicoCity.shp")
Reading layer `UrbanFringe_MexicoCity' from data source 
  `C:\Users\Orlan\Dropbox\Teaching\SpatialAnalysis\Tutorials\04_MexicoCity_HTS\UrbanFringe_MexicoCity.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 1 feature and 5 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: -99.36492 ymin: 19.04824 xmax: -98.9403 ymax: 19.59276
Geodetic CRS:  WGS 84
BB_Districts <- st_bbox(MexicoCity_HTS)
BB_Districts[1] <- -99.8
BB_Districts
     xmin      ymin      xmax      ymax 
-99.80000  18.93534 -98.59687  20.06826 

2 GWR

MexicoCity_HTS %<>%
  mutate(CarTrips_PerPopulation = Trips_Automovil/TotalPeople,
         Prop_Male = Total_Male/TotalPeople,
         Prop_HomesWithCars = Homes_With_Cars/Total_Homes,
         Prop_HomesWithBicycles = Homes_With_Bicycles/Total_Homes,
         Prop_Education_Low = TotalEducation_Low/TotalPeople,
         Prop_Education_Medium = TotalEducation_Medium/TotalPeople,
         Prop_Education_High = TotalEducation_High/TotalPeople)
ModelEquation <- "CarTrips_PerPopulation ~ 
                          Prop_Male + 
                          Prop_HomesWithCars + 
                          Prop_HomesWithBicycles +
                          # Prop_Education_Low + 
                          Age"
st_is_longlat(MexicoCity_HTS)
[1] TRUE
Data_SP <- as(MexicoCity_HTS, "Spatial")
Data_Centroids <- st_centroid(MexicoCity_HTS)
Warning: st_centroid assumes attributes are constant over geometries of x
Data_Centroids_SP <- as(Data_Centroids, "Spatial")
Data_Centroids_SP <- as(Data_Centroids, "Spatial")
Bandwidth = gwr.sel(ModelEquation, 
                    data = Data_SP, adapt = T)
Adaptive q: 0.381966 CV score: 15.79799 
Adaptive q: 0.618034 CV score: 16.06607 
Adaptive q: 0.236068 CV score: 15.58982 
Adaptive q: 0.145898 CV score: 15.57813 
Adaptive q: 0.1791799 CV score: 15.52235 
Adaptive q: 0.1889397 CV score: 15.52933 
Adaptive q: 0.1776273 CV score: 15.52027 
Adaptive q: 0.1655078 CV score: 15.54149 
Adaptive q: 0.1729981 CV score: 15.51867 
Adaptive q: 0.1742408 CV score: 15.51841 
Adaptive q: 0.1742815 CV score: 15.5184 
Adaptive q: 0.1755595 CV score: 15.51829 
Adaptive q: 0.1759044 CV score: 15.51828 
Adaptive q: 0.1759451 CV score: 15.51828 
Adaptive q: 0.1758637 CV score: 15.51828 
Adaptive q: 0.1759044 CV score: 15.51828 
Model_GWR = gwr(ModelEquation, 
                data = Data_SP, 
                adapt = Bandwidth, 
                hatmatrix = T, 
                se.fit = T)
Warning: CRS object has comment, which is lost in output; in tests, see
https://cran.r-project.org/web/packages/sp/vignettes/CRS_warnings.html
Model_GWR
Call:
gwr(formula = ModelEquation, data = Data_SP, adapt = Bandwidth, 
    hatmatrix = T, se.fit = T)
Kernel function: gwr.Gauss 
Adaptive quantile: 0.1759044 (about 33 of 193 data points)
Summary of GWR coefficient estimates at data points:
                            Min.   1st Qu.    Median   3rd Qu.      Max.  Global
X.Intercept.           -4.596397 -3.308457 -2.509538 -1.814455 -1.476676 -1.9269
Prop_Male              -0.610742  0.462755  0.909108  1.463229  2.486808 -0.1161
Prop_HomesWithCars      1.456090  1.636658  1.906816  2.131098  2.370322  1.8743
Prop_HomesWithBicycles -0.711226 -0.435152 -0.222469 -0.098109 -0.011571 -0.0213
Age                     0.025141  0.042468  0.055391  0.069582  0.095840  0.0513
Number of data points: 193 
Effective number of parameters (residual: 2traceS - traceS'S): 19.61997 
Effective degrees of freedom (residual: 2traceS - traceS'S): 173.38 
Sigma (residual: 2traceS - traceS'S): 0.2714758 
Effective number of parameters (model: traceS): 14.23004 
Effective degrees of freedom (model: traceS): 178.77 
Sigma (model: traceS): 0.2673519 
Sigma (ML): 0.2573072 
AICc (GWR p. 61, eq 2.33; p. 96, eq. 4.21): 56.97799 
AIC (GWR p. 96, eq. 4.22): 37.95128 
Residual sum of squares: 12.77795 
Quasi-global R2: 0.7102361 
results <- as.data.frame(Model_GWR$SDF)
names(results)
 [1] "sum.w"                         "X.Intercept."                 
 [3] "Prop_Male"                     "Prop_HomesWithCars"           
 [5] "Prop_HomesWithBicycles"        "Age"                          
 [7] "X.Intercept._se"               "Prop_Male_se"                 
 [9] "Prop_HomesWithCars_se"         "Prop_HomesWithBicycles_se"    
[11] "Age_se"                        "gwr.e"                        
[13] "pred"                          "pred.se"                      
[15] "localR2"                       "X.Intercept._se_EDF"          
[17] "Prop_Male_se_EDF"              "Prop_HomesWithCars_se_EDF"    
[19] "Prop_HomesWithBicycles_se_EDF" "Age_se_EDF"                   
[21] "pred.se.1"                    

2.1 Homes with cars

Temp <- results %>% 
  select(Variable = Prop_HomesWithCars, SE = Prop_HomesWithCars_se) %>% 
  mutate(T_value = Variable/SE) %>% 
  mutate(Significance = cut(T_value,
                            breaks = c(-0.01 + min(T_value), 
                                       -1.96, 1.96, 
                                       0.01 + max(T_value)),
                            labels = c("sig","nonsig", "sig")))

Temp_GWR_Coefficient <- Data_SP

Temp_GWR_Coefficient$Variable <- Temp$Variable
Temp_GWR_Coefficient$SE <- Temp$SE
Temp_GWR_Coefficient$T_value <- Temp$T_value
Temp_GWR_Coefficient$Significance <- Temp$Significance

Temp_GWR_Coefficient <- as(Temp_GWR_Coefficient,"sf")

Temp_GWR_Coefficient %<>% select(Variable, SE, T_value, Significance) 

Temp_GWR_Coefficient_SIGNIGICANT <- Temp_GWR_Coefficient %>% 
  filter(Significance == "sig")
Temp_GWR_Coefficient_NON_SIGNIGICANT <- Temp_GWR_Coefficient %>% 
  filter(Significance != "sig")
summary(Temp_GWR_Coefficient_SIGNIGICANT$Variable)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.456   1.637   1.907   1.893   2.131   2.370 
Q <- quantile(Temp_GWR_Coefficient_SIGNIGICANT$Variable, 
         probs = c(0, 0.2, 0.4, 0.6, 0.8, 1))
Q
      0%      20%      40%      60%      80%     100% 
1.456090 1.596206 1.755150 2.015792 2.165692 2.370322 
Breaks <- c(
  as.numeric(Q[1]), as.numeric(Q[2]),
  as.numeric(Q[3]), as.numeric(Q[4]),
  as.numeric(Q[5]), as.numeric(Q[6]))

Labels <- c(
  paste(floor(Breaks[1]*1000)/1000, round(Breaks[2], 3), sep = " - "),
  paste(round(Breaks[2], 3), round(Breaks[3], 3), sep = " - "),
  paste(round(Breaks[3], 3), round(Breaks[4], 3), sep = " - "),
  paste(round(Breaks[4], 3), round(Breaks[5], 3), sep = " - "),
  paste(round(Breaks[5], 3), ceiling(Breaks[6]*1000)/1000, sep = " - "))

MyPalette <- c("#ffffcc", "#a1dab4", "#41b6c4", "#2c7fb8", "#253494")
GWR_Map_Cars <- tm_shape(MexicoCity_Fringe, bbox = BB_Districts) + 
  tm_polygons(lwd = 2.5, border.col = "black") +
  tm_shape(Temp_GWR_Coefficient_SIGNIGICANT) + 
  tm_polygons("Variable",
          palette = MyPalette, lwd = 0, border.col = "black", border.alpha = 0,
          title = "Theft (quantiles)", 
          breaks = Breaks, labels = Labels) +
  # tm_shape(Temp_GWR_Coefficient_NON_SIGNIGICANT) +
  # tm_polygons(col = "white") +
  tm_compass(size = 2, type = "arrow", position = c(0.85,0.87)) +
  tm_scale_bar(position = c(0.2,0.02)) +
  tm_layout(title = "Car ownership", legend.position = c(0.01, 0.58)) +
  tm_add_legend(
    type = c("fill"),
    labels = c("Not significant"), 
    col = c("white"),
    title = "")


GWR_Map_Cars

GWR_Map_Cars <- tm_shape(Temp_GWR_Coefficient_SIGNIGICANT) + 
  tm_polygons("Variable",
          palette = MyPalette, lwd = 0, border.col = "black", border.alpha = 0,
          title = "Quantiles", 
          breaks = Breaks, labels = Labels) +
  tm_borders(alpha = 0.4) +
  tm_shape(MexicoCity_Fringe) + 
  tm_polygons(alpha = 0, border.col = "black", lwd = 1.4, lty = "solid") +
  tm_compass(size = 2, type = "arrow", position = c(0.85,0.87)) + 
  tm_scale_bar(position = c(0.4,0.02)) +
  tm_layout(title = "Cars", legend.position = c(0.01,0.15), scale = 1)


GWR_Map_Cars

LS0tDQp0aXRsZTogIkdXUiINCmF1dGhvcjogIk9ybGFuZG8gU2Fib2dhbC1DYXJkb25hIg0KZGF0ZTogIlN1bW1lciAyMDIzIg0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHRydWUNCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQotLS0NCg0KIyBMaWJyYXJpZXMgYW5kIHJhdyBkYXRhDQoNCmBgYHtyIGxpYnJhcmllcyB1c2VkfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KbGlicmFyeShzZikNCmxpYnJhcnkodG1hcCkNCg0KbGlicmFyeShzcGRlcCkgIyBTcGF0aWFsIHdlaWdodHMsIE1vcmFuJ3MgSSwgYW5kIExJU0ENCmxpYnJhcnkoc3BhdGlhbHJlZykgIyBTcGF0aWFsIFJlZ3Jlc3Npb24NCg0KbGlicmFyeShzcGd3cikgIyBHV1INCmBgYA0KDQpgYGB7cn0NCmxvYWQoIi4uLzA0X01leGljb0NpdHlfSFRTL01leGljb19IVFMuUkRhdGEiKQ0KbHMoKQ0KYGBgDQoNCiMjIFJlbW92ZSBkaXN0cmljdHMNCg0KYGBge3J9DQpzdW1tYXJ5KE1leGljb0NpdHlfSFRTJFRvdGFsUGVvcGxlKQ0KTWV4aWNvQ2l0eV9IVFMgJT4lIGZpbHRlcihpcy5uYShUb3RhbFBlb3BsZSkpICU+JSBzZWxlY3QoRGlzdHJpdG8pDQpgYGANCg0KYGBge3J9DQpNZXhpY29DaXR5X0hUUyAlPD4lIGZpbHRlcihEaXN0cml0byAhPSAiMDM0IikNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoTWV4aWNvQ2l0eV9IVFMkVG90YWxfSG9tZXMpDQpgYGANCg0KIyMgTWFwIHByZXBhcmF0aW9uDQogDQpgYGB7cn0NCk1leGljb0NpdHlfRnJpbmdlIDwtIHN0X3JlYWQoIi4uLzA0X01leGljb0NpdHlfSFRTL1VyYmFuRnJpbmdlX01leGljb0NpdHkuc2hwIikNCmBgYA0KDQpgYGB7cn0NCkJCX0Rpc3RyaWN0cyA8LSBzdF9iYm94KE1leGljb0NpdHlfSFRTKQ0KQkJfRGlzdHJpY3RzWzFdIDwtIC05OS44DQpCQl9EaXN0cmljdHMNCmBgYA0KDQojIEdXUg0KDQpgYGB7cn0NCk1leGljb0NpdHlfSFRTICU8PiUNCiAgbXV0YXRlKENhclRyaXBzX1BlclBvcHVsYXRpb24gPSBUcmlwc19BdXRvbW92aWwvVG90YWxQZW9wbGUsDQogICAgICAgICBQcm9wX01hbGUgPSBUb3RhbF9NYWxlL1RvdGFsUGVvcGxlLA0KICAgICAgICAgUHJvcF9Ib21lc1dpdGhDYXJzID0gSG9tZXNfV2l0aF9DYXJzL1RvdGFsX0hvbWVzLA0KICAgICAgICAgUHJvcF9Ib21lc1dpdGhCaWN5Y2xlcyA9IEhvbWVzX1dpdGhfQmljeWNsZXMvVG90YWxfSG9tZXMsDQogICAgICAgICBQcm9wX0VkdWNhdGlvbl9Mb3cgPSBUb3RhbEVkdWNhdGlvbl9Mb3cvVG90YWxQZW9wbGUsDQogICAgICAgICBQcm9wX0VkdWNhdGlvbl9NZWRpdW0gPSBUb3RhbEVkdWNhdGlvbl9NZWRpdW0vVG90YWxQZW9wbGUsDQogICAgICAgICBQcm9wX0VkdWNhdGlvbl9IaWdoID0gVG90YWxFZHVjYXRpb25fSGlnaC9Ub3RhbFBlb3BsZSkNCmBgYA0KDQpgYGB7cn0NCk1vZGVsRXF1YXRpb24gPC0gIkNhclRyaXBzX1BlclBvcHVsYXRpb24gfiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgUHJvcF9NYWxlICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgIFByb3BfSG9tZXNXaXRoQ2FycyArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBQcm9wX0hvbWVzV2l0aEJpY3ljbGVzICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyBQcm9wX0VkdWNhdGlvbl9Mb3cgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgQWdlIg0KYGBgDQoNCmBgYHtyfQ0Kc3RfaXNfbG9uZ2xhdChNZXhpY29DaXR5X0hUUykNCmBgYA0KDQpgYGB7cn0NCkRhdGFfU1AgPC0gYXMoTWV4aWNvQ2l0eV9IVFMsICJTcGF0aWFsIikNCkRhdGFfQ2VudHJvaWRzIDwtIHN0X2NlbnRyb2lkKE1leGljb0NpdHlfSFRTKQ0KDQpEYXRhX0NlbnRyb2lkc19TUCA8LSBhcyhEYXRhX0NlbnRyb2lkcywgIlNwYXRpYWwiKQ0KYGBgDQoNCmBgYHtyfQ0KRGF0YV9DZW50cm9pZHNfU1AgPC0gYXMoRGF0YV9DZW50cm9pZHMsICJTcGF0aWFsIikNCmBgYA0KDQpgYGB7cn0NCkJhbmR3aWR0aCA9IGd3ci5zZWwoTW9kZWxFcXVhdGlvbiwgDQogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBEYXRhX1NQLCBhZGFwdCA9IFQpDQpgYGANCg0KDQpgYGB7cn0NCk1vZGVsX0dXUiA9IGd3cihNb2RlbEVxdWF0aW9uLCANCiAgICAgICAgICAgICAgICBkYXRhID0gRGF0YV9TUCwgDQogICAgICAgICAgICAgICAgYWRhcHQgPSBCYW5kd2lkdGgsIA0KICAgICAgICAgICAgICAgIGhhdG1hdHJpeCA9IFQsIA0KICAgICAgICAgICAgICAgIHNlLmZpdCA9IFQpDQpgYGANCg0KYGBge3J9DQpNb2RlbF9HV1INCmBgYA0KDQpgYGB7cn0NCnJlc3VsdHMgPC0gYXMuZGF0YS5mcmFtZShNb2RlbF9HV1IkU0RGKQ0KbmFtZXMocmVzdWx0cykNCmBgYA0KIyMgSG9tZXMgd2l0aCBjYXJzDQoNCmBgYHtyfQ0KVGVtcCA8LSByZXN1bHRzICU+JSANCiAgc2VsZWN0KFZhcmlhYmxlID0gUHJvcF9Ib21lc1dpdGhDYXJzLCBTRSA9IFByb3BfSG9tZXNXaXRoQ2Fyc19zZSkgJT4lIA0KICBtdXRhdGUoVF92YWx1ZSA9IFZhcmlhYmxlL1NFKSAlPiUgDQogIG11dGF0ZShTaWduaWZpY2FuY2UgPSBjdXQoVF92YWx1ZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKC0wLjAxICsgbWluKFRfdmFsdWUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0xLjk2LCAxLjk2LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDAuMDEgKyBtYXgoVF92YWx1ZSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoInNpZyIsIm5vbnNpZyIsICJzaWciKSkpDQoNClRlbXBfR1dSX0NvZWZmaWNpZW50IDwtIERhdGFfU1ANCg0KVGVtcF9HV1JfQ29lZmZpY2llbnQkVmFyaWFibGUgPC0gVGVtcCRWYXJpYWJsZQ0KVGVtcF9HV1JfQ29lZmZpY2llbnQkU0UgPC0gVGVtcCRTRQ0KVGVtcF9HV1JfQ29lZmZpY2llbnQkVF92YWx1ZSA8LSBUZW1wJFRfdmFsdWUNClRlbXBfR1dSX0NvZWZmaWNpZW50JFNpZ25pZmljYW5jZSA8LSBUZW1wJFNpZ25pZmljYW5jZQ0KDQpUZW1wX0dXUl9Db2VmZmljaWVudCA8LSBhcyhUZW1wX0dXUl9Db2VmZmljaWVudCwic2YiKQ0KDQpUZW1wX0dXUl9Db2VmZmljaWVudCAlPD4lIHNlbGVjdChWYXJpYWJsZSwgU0UsIFRfdmFsdWUsIFNpZ25pZmljYW5jZSkgDQoNClRlbXBfR1dSX0NvZWZmaWNpZW50X1NJR05JR0lDQU5UIDwtIFRlbXBfR1dSX0NvZWZmaWNpZW50ICU+JSANCiAgZmlsdGVyKFNpZ25pZmljYW5jZSA9PSAic2lnIikNClRlbXBfR1dSX0NvZWZmaWNpZW50X05PTl9TSUdOSUdJQ0FOVCA8LSBUZW1wX0dXUl9Db2VmZmljaWVudCAlPiUgDQogIGZpbHRlcihTaWduaWZpY2FuY2UgIT0gInNpZyIpDQpgYGANCg0KYGBge3J9DQpzdW1tYXJ5KFRlbXBfR1dSX0NvZWZmaWNpZW50X1NJR05JR0lDQU5UJFZhcmlhYmxlKQ0KYGBgDQoNCmBgYHtyfQ0KUSA8LSBxdWFudGlsZShUZW1wX0dXUl9Db2VmZmljaWVudF9TSUdOSUdJQ0FOVCRWYXJpYWJsZSwgDQogICAgICAgICBwcm9icyA9IGMoMCwgMC4yLCAwLjQsIDAuNiwgMC44LCAxKSkNClENCmBgYA0KDQpgYGB7cn0NCkJyZWFrcyA8LSBjKA0KICBhcy5udW1lcmljKFFbMV0pLCBhcy5udW1lcmljKFFbMl0pLA0KICBhcy5udW1lcmljKFFbM10pLCBhcy5udW1lcmljKFFbNF0pLA0KICBhcy5udW1lcmljKFFbNV0pLCBhcy5udW1lcmljKFFbNl0pKQ0KDQpMYWJlbHMgPC0gYygNCiAgcGFzdGUoZmxvb3IoQnJlYWtzWzFdKjEwMDApLzEwMDAsIHJvdW5kKEJyZWFrc1syXSwgMyksIHNlcCA9ICIgLSAiKSwNCiAgcGFzdGUocm91bmQoQnJlYWtzWzJdLCAzKSwgcm91bmQoQnJlYWtzWzNdLCAzKSwgc2VwID0gIiAtICIpLA0KICBwYXN0ZShyb3VuZChCcmVha3NbM10sIDMpLCByb3VuZChCcmVha3NbNF0sIDMpLCBzZXAgPSAiIC0gIiksDQogIHBhc3RlKHJvdW5kKEJyZWFrc1s0XSwgMyksIHJvdW5kKEJyZWFrc1s1XSwgMyksIHNlcCA9ICIgLSAiKSwNCiAgcGFzdGUocm91bmQoQnJlYWtzWzVdLCAzKSwgY2VpbGluZyhCcmVha3NbNl0qMTAwMCkvMTAwMCwgc2VwID0gIiAtICIpKQ0KDQpNeVBhbGV0dGUgPC0gYygiI2ZmZmZjYyIsICIjYTFkYWI0IiwgIiM0MWI2YzQiLCAiIzJjN2ZiOCIsICIjMjUzNDk0IikNCmBgYA0KDQpgYGB7cn0NCkdXUl9NYXBfQ2FycyA8LSB0bV9zaGFwZShNZXhpY29DaXR5X0ZyaW5nZSwgYmJveCA9IEJCX0Rpc3RyaWN0cykgKyANCiAgdG1fcG9seWdvbnMobHdkID0gMi41LCBib3JkZXIuY29sID0gImJsYWNrIikgKw0KICB0bV9zaGFwZShUZW1wX0dXUl9Db2VmZmljaWVudF9TSUdOSUdJQ0FOVCkgKyANCiAgdG1fcG9seWdvbnMoIlZhcmlhYmxlIiwNCiAgICAgICAgICBwYWxldHRlID0gTXlQYWxldHRlLCBsd2QgPSAwLCBib3JkZXIuY29sID0gImJsYWNrIiwgYm9yZGVyLmFscGhhID0gMCwNCiAgICAgICAgICB0aXRsZSA9ICJUaGVmdCAocXVhbnRpbGVzKSIsIA0KICAgICAgICAgIGJyZWFrcyA9IEJyZWFrcywgbGFiZWxzID0gTGFiZWxzKSArDQogICMgdG1fc2hhcGUoVGVtcF9HV1JfQ29lZmZpY2llbnRfTk9OX1NJR05JR0lDQU5UKSArDQogICMgdG1fcG9seWdvbnMoY29sID0gIndoaXRlIikgKw0KICB0bV9jb21wYXNzKHNpemUgPSAyLCB0eXBlID0gImFycm93IiwgcG9zaXRpb24gPSBjKDAuODUsMC44NykpICsNCiAgdG1fc2NhbGVfYmFyKHBvc2l0aW9uID0gYygwLjIsMC4wMikpICsNCiAgdG1fbGF5b3V0KHRpdGxlID0gIkNhciBvd25lcnNoaXAiLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsIDAuNTgpKSArDQogIHRtX2FkZF9sZWdlbmQoDQogICAgdHlwZSA9IGMoImZpbGwiKSwNCiAgICBsYWJlbHMgPSBjKCJOb3Qgc2lnbmlmaWNhbnQiKSwgDQogICAgY29sID0gYygid2hpdGUiKSwNCiAgICB0aXRsZSA9ICIiKQ0KDQoNCkdXUl9NYXBfQ2Fycw0KYGBgDQoNCmBgYHtyfQ0KR1dSX01hcF9DYXJzIDwtIHRtX3NoYXBlKFRlbXBfR1dSX0NvZWZmaWNpZW50X1NJR05JR0lDQU5UKSArIA0KICB0bV9wb2x5Z29ucygiVmFyaWFibGUiLA0KICAgICAgICAgIHBhbGV0dGUgPSBNeVBhbGV0dGUsIGx3ZCA9IDAsIGJvcmRlci5jb2wgPSAiYmxhY2siLCBib3JkZXIuYWxwaGEgPSAwLA0KICAgICAgICAgIHRpdGxlID0gIlF1YW50aWxlcyIsIA0KICAgICAgICAgIGJyZWFrcyA9IEJyZWFrcywgbGFiZWxzID0gTGFiZWxzKSArDQogIHRtX2JvcmRlcnMoYWxwaGEgPSAwLjQpICsNCiAgdG1fc2hhcGUoTWV4aWNvQ2l0eV9GcmluZ2UpICsgDQogIHRtX3BvbHlnb25zKGFscGhhID0gMCwgYm9yZGVyLmNvbCA9ICJibGFjayIsIGx3ZCA9IDEuNCwgbHR5ID0gInNvbGlkIikgKw0KICB0bV9jb21wYXNzKHNpemUgPSAyLCB0eXBlID0gImFycm93IiwgcG9zaXRpb24gPSBjKDAuODUsMC44NykpICsgDQogIHRtX3NjYWxlX2Jhcihwb3NpdGlvbiA9IGMoMC40LDAuMDIpKSArDQogIHRtX2xheW91dCh0aXRsZSA9ICJDYXJzIiwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuMTUpLCBzY2FsZSA9IDEpDQoNCg0KR1dSX01hcF9DYXJzDQpgYGANCg0K