#install.packages("ggmap")
suppressPackageStartupMessages({
    library(ggmap)
    library(dplyr)
    library(scales)
    library(magrittr)
})

Load map of WWPS

WWPS_map <- get_map(location=c(lon=-94.2348,lat=36.0661),zoom=19,maptype = "satellite",source="google")
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=36.0661,-94.2348&zoom=19&size=640x640&scale=2&maptype=satellite&language=en-EN&sensor=false
ggmap(WWPS_map)

Read in data table with sample positions

sample_locations <- read.csv("C:/Users/faysmith/Desktop/Export_Output.csv")

Plot locations on map

sam_map_gwc <- ggmap(WWPS_map) + geom_point(data = sample_locations, aes(lon,lat,color=gwc), size=2,alpha=0.7)+labs(x="longitude", y="latitude", title = "WWPS Soil Gravimetric Water Content 0-10cm", color="GWC (g H20/g soil)")
sam_map_gwc

sam_map_ph <- ggmap(WWPS_map) + geom_point(data = sample_locations, aes(lon,lat,color=ph1), size=2,alpha=0.7)+labs(x="longitude", y="latitude", title = "WWPS Soil pH 0-10cm", color="pH")
sam_map_ph

sam_map_ec <- ggmap(WWPS_map) + geom_point(data = sample_locations, aes(lon,lat,color=ec1), size=2,alpha=0.7)+labs(x="longitude", y="latitude", title = "WWPS Soil EC 0-10cm", color="EC (uS/cm)")
sam_map_ec

sam_map_clay <- ggmap(WWPS_map) + geom_point(data = sample_locations, aes(lon,lat,color=per_clay), size=2,alpha=0.7)+labs(x="longitude", y="latitude", title = "WWPS Soil % Clay 0-10cm", color="% Clay")
sam_map_clay

sam_map_sand <- ggmap(WWPS_map) + geom_point(data = sample_locations, aes(lon,lat,color=per_sand), size=2,alpha=0.7)+labs(x="longitude", y="latitude", title = "WWPS Soil % Sand 0-10cm", color="% Sand")
sam_map_sand

sam_map_silt <- ggmap(WWPS_map) + geom_point(data = sample_locations, aes(lon,lat,color=per_silt), size=2,alpha=0.7)+labs(x="longitude", y="latitude", title = "WWPS Soil % Silt 0-10cm", color="% Silt")
sam_map_silt

summary(sample_locations$ph1)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  4.670   5.683   5.965   5.966   6.207   6.960 
        summary(sample_locations$ec1)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    9.6    85.4   105.5   116.2   136.2   375.5 
        summary(sample_locations$gwc)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
0.07188 0.20471 0.26766 0.26942 0.34005 0.49295 
        summary(sample_locations$per_clay)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.523   6.923   9.866  10.348  13.168  32.303 
        summary(sample_locations$per_sand)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  12.12   16.53   19.81   20.57   24.34   33.62 
        summary(sample_locations$per_silt)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  41.57   64.73   70.08   69.08   74.57   84.75 

Now I can look at colinearity among all the samples I collected:

just_var <- sample_locations[c(5,6,10,20,27:28)]
pairs(just_var[1:6])

panel.cor <- function(x, y, digits = 2, prefix = "", cex.cor, ...)
{
    usr <- par("usr"); on.exit(par(usr))
    par(usr = c(0, 1, 0, 1))
    r <- abs(cor(x, y))
    txt <- format(c(r, 0.123456789), digits = digits)[1]
    txt <- paste0(prefix, txt)
    if(missing(cex.cor)) cex.cor <- 0.8/strwidth(txt)
    text(0.5, 0.5, txt, cex = cex.cor * r)
}
pairs(just_var[1:6],upper.panel=panel.cor ,lower.panel=panel.smooth)

Then, we use the data from the original file to create a SPDF class object so that data is clearly distinguished from the coordinates.

coordinates(sample_locations) <- ~ lon + lat
Error in `coordinates<-`(`*tmp*`, value = ~lon + lat) : 
  setting coordinates cannot be done on Spatial objects, where they have already been set

In order to perform kriging, we must first create a variogram model for each variable and then fitting a model to each variable’s variogram

lzn.vgm.ph <- variogram((ph1)~lon+lat, sample_locations)
lzn.fit.ph <- fit.variogram(lzn.vgm.ph, model=vgm(c("Exp","Sph", "Gau", "Mat")))
No convergence after 200 iterations: try different initial values?No convergence after 200 iterations: try different initial values?No convergence after 200 iterations: try different initial values?No convergence after 200 iterations: try different initial values?
plot(lzn.vgm.ph, lzn.fit.ph)

lzn.vgm.ec <- variogram((ec1)~lon+lat, sample_locations)
lzn.fit.ec <- fit.variogram(lzn.vgm.ec, model=vgm(c("Exp","Sph", "Gau", "Mat")))
singular model in variogram fit
[1] "a possible solution MIGHT be to scale semivariances and/or distances"
singular model in variogram fit
[1] "a possible solution MIGHT be to scale semivariances and/or distances"
singular model in variogram fit
[1] "a possible solution MIGHT be to scale semivariances and/or distances"
singular model in variogram fit
[1] "a possible solution MIGHT be to scale semivariances and/or distances"
plot(lzn.vgm.ec, lzn.fit.ec)

lzn.vgm.gwc <- variogram((gwc)~lon+lat, sample_locations, width=0.0002)
lzn.fit.gwc <- fit.variogram(lzn.vgm.gwc, model=vgm(c("Exp","Sph", "Gau", "Mat")))
singular model in variogram fit
plot(lzn.vgm.gwc, lzn.fit.gwc)

lzn.vgm.clay <- variogram((per_clay)~lon+lat, sample_locations, width=0.0001)
lzn.fit.clay <- fit.variogram(lzn.vgm.clay, model=vgm(c("Exp","Sph", "Gau", "Mat")))
singular model in variogram fit
plot(lzn.vgm.clay, lzn.fit.clay)

lzn.vgm.sand <- variogram((per_sand)~lon+lat, sample_locations)
lzn.fit.sand <- fit.variogram(lzn.vgm.sand, model=vgm(c("Exp","Sph", "Gau", "Mat")))
plot(lzn.vgm.sand, lzn.fit.sand)

lzn.vgm.silt <- variogram((per_silt)~lon+lat, sample_locations)
lzn.fit.silt <- fit.variogram(lzn.vgm.silt, model=vgm(c("Exp","Sph", "Gau", "Mat")))
No convergence after 200 iterations: try different initial values?
plot(lzn.vgm.silt, lzn.fit.silt, diff=TRUE)

lzn.fit.ph
  model     psill        range
1   Nug 0.0000000 0.000000e+00
2   Sph 0.1656692 8.652802e-05
lzn.fit.ec
  model     psill        range
1   Nug  714.1345 0.000000e+00
2   Sph 1602.3557 6.465045e-05
lzn.fit.gwc
  model       psill       range
1   Nug 0.002608152 0.000000000
2   Exp 0.003623269 0.001107374
lzn.fit.clay
  model     psill       range
1   Nug  4.129199 0.000000000
2   Sph 18.971155 0.000240231
lzn.fit.sand
  model     psill       range
1   Nug  7.888791 0.000000000
2   Gau 18.976200 0.000181561
lzn.fit.silt
  model    psill        range
1   Nug 10.73700 0.0000000000
2   Sph 55.78812 0.0003088612

Now that we fit the variogram models to the data, we will now use this information in kreging

bbox(sample_locations)
          min       max
lon -94.23546 -94.23402
lat  36.06563  36.06665
#Create a grid to estimate values over
x_range <- as.numeric(c(-94.23546, -94.23402))
y_range <- as.numeric(c(36.06563, 36.06665))
# create an empty grid of values ranging from the xmin-xmax, ymin-ymax
sample.grid <- expand.grid(x = seq(from = x_range[1],
                   to = x_range[2], 
                   length.out=30),
                   y = seq(from = y_range[1],                                           to = y_range[2], 
                       length.out=30))  # expand points to grid
class(sample.grid)
[1] "data.frame"
sample.grid$number=seq(from=1, to=900, length.out=900)
plot1 <- sample_locations %>% as.data.frame %>%
  ggplot(aes(lat, lon)) + geom_point(size=.25) + coord_equal() + 
ggtitle("Points with measurements")
# this is clearly gridded over the region of interest
plot2 <- sample.grid %>% as.data.frame %>%
  ggplot(aes(y, x)) + geom_point(size=.25) + coord_equal() + 
  ggtitle("Points at which to estimate")
library(gridExtra)
grid.arrange(plot1, plot2, ncol=2)

coordinates(sample.grid) <- ~ x + y
lzn.kriged.ph <- krige(ph1~1, sample_locations, sample.grid, model=lzn.fit.ph)
[using ordinary kriging]
lzn.kriged.ec <- krige(ec1~1, sample_locations, sample.grid, model=lzn.fit.ec)
[using ordinary kriging]
lzn.kriged.gwc <- krige(gwc~1, sample_locations, sample.grid, model=lzn.fit.gwc)
[using ordinary kriging]
lzn.kriged.clay <- krige(per_clay~1, sample_locations, sample.grid, model=lzn.fit.clay)
[using ordinary kriging]
lzn.kriged.sand <- krige(per_sand~1, sample_locations, sample.grid, model=lzn.fit.sand)
[using ordinary kriging]
lzn.kriged.silt <- krige(per_silt~1, sample_locations, sample.grid, model=lzn.fit.silt)
[using ordinary kriging]
a<- lzn.kriged.ph %>% as.data.frame %>%
  ggplot(aes(x=x, y=y)) + geom_tile(aes(fill=var1.pred)) + coord_equal() +
  scale_fill_gradient(low = "yellow", high="red") +
  scale_x_continuous(labels=comma) + scale_y_continuous(labels=comma) +
  theme_bw() + labs(x="longitude", y="latitude", title = "WWPS Pred pH 0-10cm", fill="Pred pH")
b<- lzn.kriged.ec %>% as.data.frame %>%
  ggplot(aes(x=x, y=y)) + geom_tile(aes(fill=var1.pred)) + coord_equal() +
  scale_fill_gradient(low = "yellow", high="red") +
  scale_x_continuous(labels=comma) + scale_y_continuous(labels=comma) +
  theme_bw() + labs(x="longitude", y="latitude", title = "WWPS Pred EC 0-10cm", fill="Pred EC (uS/cm")
c<- lzn.kriged.gwc %>% as.data.frame %>%
  ggplot(aes(x=x, y=y)) + geom_tile(aes(fill=var1.pred)) + coord_equal() +
  scale_fill_gradient(low = "yellow", high="red") +
  scale_x_continuous(labels=comma) + scale_y_continuous(labels=comma) +
  theme_bw() + labs(x="longitude", y="latitude", title = "WWPS Pred GWC 0-10cm", fill="Pred GWC (% g/g)")
d<- lzn.kriged.clay %>% as.data.frame %>%
  ggplot(aes(x=x, y=y)) + geom_tile(aes(fill=var1.pred)) + coord_equal() +
  scale_fill_gradient(low = "yellow", high="red") +
  scale_x_continuous(labels=comma) + scale_y_continuous(labels=comma) +
  theme_bw() + labs(x="longitude", y="latitude", title = "WWPS Pred % Clay 0-10cm", fill="Pred Clay (%)")
e<- lzn.kriged.sand %>% as.data.frame %>%
  ggplot(aes(x=x, y=y)) + geom_tile(aes(fill=var1.pred)) + coord_equal() +
  scale_fill_gradient(low = "yellow", high="red") +
  scale_x_continuous(labels=comma) + scale_y_continuous(labels=comma) +
  theme_bw() + labs(x="longitude", y="latitude", title = "WWPS Pred % Sand 0-10cm", fill="Pred Sand (%)")
f<- lzn.kriged.silt %>% as.data.frame %>%
  ggplot(aes(x=x, y=y)) + geom_tile(aes(fill=var1.pred)) + coord_equal() +
  scale_fill_gradient(low = "yellow", high="red") +
  scale_x_continuous(labels=comma) + scale_y_continuous(labels=comma) +
  theme_bw() + labs(x="longitude", y="latitude", title = "WWPS Pred % Silt 0-10cm", fill="Pred Silt (%)")
a

b

c

d

e

f

LS0tDQp0aXRsZTogIk1hcHBpbmcgc3BhdGlhbCBkYXRhIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KLS0tDQp0aXRsZTogIk1hcHBpbmcgc3BhdGlhbCBkYXRhIg0KYXV0aG9yOiAiUy4gRmF5ZSBTbWl0aCINCmRhdGU6ICJKdWx5IDE4LCAyMDE4Ig0Kb3V0cHV0OiBodG1sX2RvY3VtZW50DQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KYGBge3J9DQojaW5zdGFsbC5wYWNrYWdlcygiZ2dtYXAiKQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsNCiAgICBsaWJyYXJ5KGdnbWFwKQ0KICAgIGxpYnJhcnkoZHBseXIpDQogICAgbGlicmFyeShzY2FsZXMpDQogICAgbGlicmFyeShtYWdyaXR0cikNCn0pDQpgYGANCg0KTG9hZCBtYXAgb2YgV1dQUw0KDQpgYGB7cn0NCldXUFNfbWFwIDwtIGdldF9tYXAobG9jYXRpb249Yyhsb249LTk0LjIzNDgsbGF0PTM2LjA2NjEpLHpvb209MTksbWFwdHlwZSA9ICJzYXRlbGxpdGUiLHNvdXJjZT0iZ29vZ2xlIikNCmdnbWFwKFdXUFNfbWFwKQ0KYGBgDQoNClJlYWQgaW4gZGF0YSB0YWJsZSB3aXRoIHNhbXBsZSBwb3NpdGlvbnMNCg0KYGBge3J9DQpzYW1wbGVfbG9jYXRpb25zIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9mYXlzbWl0aC9EZXNrdG9wL0V4cG9ydF9PdXRwdXQuY3N2IikNCmBgYA0KDQpQbG90IGxvY2F0aW9ucyBvbiBtYXANCg0KYGBge3J9DQpzYW1fbWFwX2d3YyA8LSBnZ21hcChXV1BTX21hcCkgKyBnZW9tX3BvaW50KGRhdGEgPSBzYW1wbGVfbG9jYXRpb25zLCBhZXMobG9uLGxhdCxjb2xvcj1nd2MpLCBzaXplPTIsYWxwaGE9MC43KStsYWJzKHg9ImxvbmdpdHVkZSIsIHk9ImxhdGl0dWRlIiwgdGl0bGUgPSAiV1dQUyBTb2lsIEdyYXZpbWV0cmljIFdhdGVyIENvbnRlbnQgMC0xMGNtIiwgY29sb3I9IkdXQyAoZyBIMjAvZyBzb2lsKSIpDQpzYW1fbWFwX2d3Yw0KDQpzYW1fbWFwX3BoIDwtIGdnbWFwKFdXUFNfbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IHNhbXBsZV9sb2NhdGlvbnMsIGFlcyhsb24sbGF0LGNvbG9yPXBoMSksIHNpemU9MixhbHBoYT0wLjcpK2xhYnMoeD0ibG9uZ2l0dWRlIiwgeT0ibGF0aXR1ZGUiLCB0aXRsZSA9ICJXV1BTIFNvaWwgcEggMC0xMGNtIiwgY29sb3I9InBIIikNCnNhbV9tYXBfcGgNCg0Kc2FtX21hcF9lYyA8LSBnZ21hcChXV1BTX21hcCkgKyBnZW9tX3BvaW50KGRhdGEgPSBzYW1wbGVfbG9jYXRpb25zLCBhZXMobG9uLGxhdCxjb2xvcj1lYzEpLCBzaXplPTIsYWxwaGE9MC43KStsYWJzKHg9ImxvbmdpdHVkZSIsIHk9ImxhdGl0dWRlIiwgdGl0bGUgPSAiV1dQUyBTb2lsIEVDIDAtMTBjbSIsIGNvbG9yPSJFQyAodVMvY20pIikNCnNhbV9tYXBfZWMNCg0Kc2FtX21hcF9jbGF5IDwtIGdnbWFwKFdXUFNfbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IHNhbXBsZV9sb2NhdGlvbnMsIGFlcyhsb24sbGF0LGNvbG9yPXBlcl9jbGF5KSwgc2l6ZT0yLGFscGhhPTAuNykrbGFicyh4PSJsb25naXR1ZGUiLCB5PSJsYXRpdHVkZSIsIHRpdGxlID0gIldXUFMgU29pbCAlIENsYXkgMC0xMGNtIiwgY29sb3I9IiUgQ2xheSIpDQpzYW1fbWFwX2NsYXkNCg0Kc2FtX21hcF9zYW5kIDwtIGdnbWFwKFdXUFNfbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IHNhbXBsZV9sb2NhdGlvbnMsIGFlcyhsb24sbGF0LGNvbG9yPXBlcl9zYW5kKSwgc2l6ZT0yLGFscGhhPTAuNykrbGFicyh4PSJsb25naXR1ZGUiLCB5PSJsYXRpdHVkZSIsIHRpdGxlID0gIldXUFMgU29pbCAlIFNhbmQgMC0xMGNtIiwgY29sb3I9IiUgU2FuZCIpDQpzYW1fbWFwX3NhbmQNCg0Kc2FtX21hcF9zaWx0IDwtIGdnbWFwKFdXUFNfbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IHNhbXBsZV9sb2NhdGlvbnMsIGFlcyhsb24sbGF0LGNvbG9yPXBlcl9zaWx0KSwgc2l6ZT0yLGFscGhhPTAuNykrbGFicyh4PSJsb25naXR1ZGUiLCB5PSJsYXRpdHVkZSIsIHRpdGxlID0gIldXUFMgU29pbCAlIFNpbHQgMC0xMGNtIiwgY29sb3I9IiUgU2lsdCIpDQpzYW1fbWFwX3NpbHQNCg0KDQpgYGANCg0KYGBge3J9DQpzdW1tYXJ5KHNhbXBsZV9sb2NhdGlvbnMkcGgxKQ0KICAgICAgICBzdW1tYXJ5KHNhbXBsZV9sb2NhdGlvbnMkZWMxKQ0KICAgICAgICBzdW1tYXJ5KHNhbXBsZV9sb2NhdGlvbnMkZ3djKQ0KICAgICAgICBzdW1tYXJ5KHNhbXBsZV9sb2NhdGlvbnMkcGVyX2NsYXkpDQogICAgICAgIHN1bW1hcnkoc2FtcGxlX2xvY2F0aW9ucyRwZXJfc2FuZCkNCiAgICAgICAgc3VtbWFyeShzYW1wbGVfbG9jYXRpb25zJHBlcl9zaWx0KQ0KYGBgDQoNCk5vdyBJIGNhbiBsb29rIGF0IGNvbGluZWFyaXR5IGFtb25nIGFsbCB0aGUgc2FtcGxlcyBJIGNvbGxlY3RlZDoNCg0KYGBge3J9DQpqdXN0X3ZhciA8LSBzYW1wbGVfbG9jYXRpb25zW2MoNSw2LDEwLDIwLDI3OjI4KV0NCg0KcGFpcnMoanVzdF92YXJbMTo2XSkNCg0KcGFuZWwuY29yIDwtIGZ1bmN0aW9uKHgsIHksIGRpZ2l0cyA9IDIsIHByZWZpeCA9ICIiLCBjZXguY29yLCAuLi4pDQp7DQogICAgdXNyIDwtIHBhcigidXNyIik7IG9uLmV4aXQocGFyKHVzcikpDQogICAgcGFyKHVzciA9IGMoMCwgMSwgMCwgMSkpDQogICAgciA8LSBhYnMoY29yKHgsIHkpKQ0KICAgIHR4dCA8LSBmb3JtYXQoYyhyLCAwLjEyMzQ1Njc4OSksIGRpZ2l0cyA9IGRpZ2l0cylbMV0NCiAgICB0eHQgPC0gcGFzdGUwKHByZWZpeCwgdHh0KQ0KICAgIGlmKG1pc3NpbmcoY2V4LmNvcikpIGNleC5jb3IgPC0gMC44L3N0cndpZHRoKHR4dCkNCiAgICB0ZXh0KDAuNSwgMC41LCB0eHQsIGNleCA9IGNleC5jb3IgKiByKQ0KfQ0KDQpwYWlycyhqdXN0X3ZhclsxOjZdLHVwcGVyLnBhbmVsPXBhbmVsLmNvciAsbG93ZXIucGFuZWw9cGFuZWwuc21vb3RoKQ0KYGBgDQoNClRoZW4sIHdlIHVzZSB0aGUgZGF0YSBmcm9tIHRoZSBvcmlnaW5hbCBmaWxlIHRvIGNyZWF0ZSBhIFNQREYgY2xhc3Mgb2JqZWN0IHNvIHRoYXQgZGF0YSBpcyBjbGVhcmx5IGRpc3Rpbmd1aXNoZWQgZnJvbSB0aGUgY29vcmRpbmF0ZXMuIA0KDQpgYGB7cn0NCg0KY29vcmRpbmF0ZXMoc2FtcGxlX2xvY2F0aW9ucykgPC0gfiBsb24gKyBsYXQNCg0KYGBgDQoNCkluIG9yZGVyIHRvIHBlcmZvcm0ga3JpZ2luZywgd2UgbXVzdCBmaXJzdCBjcmVhdGUgYSB2YXJpb2dyYW0gbW9kZWwgZm9yIGVhY2ggdmFyaWFibGUgYW5kIHRoZW4gZml0dGluZyBhIG1vZGVsIHRvIGVhY2ggdmFyaWFibGUncyB2YXJpb2dyYW0NCg0KYGBge3J9DQoNCmx6bi52Z20ucGggPC0gdmFyaW9ncmFtKChwaDEpfmxvbitsYXQsIHNhbXBsZV9sb2NhdGlvbnMpDQpsem4uZml0LnBoIDwtIGZpdC52YXJpb2dyYW0obHpuLnZnbS5waCwgbW9kZWw9dmdtKGMoIkV4cCIsIlNwaCIsICJHYXUiLCAiTWF0IikpKQ0KcGxvdChsem4udmdtLnBoLCBsem4uZml0LnBoKQ0KDQpsem4udmdtLmVjIDwtIHZhcmlvZ3JhbSgoZWMxKX5sb24rbGF0LCBzYW1wbGVfbG9jYXRpb25zKQ0KbHpuLmZpdC5lYyA8LSBmaXQudmFyaW9ncmFtKGx6bi52Z20uZWMsIG1vZGVsPXZnbShjKCJFeHAiLCJTcGgiLCAiR2F1IiwgIk1hdCIpKSkNCnBsb3QobHpuLnZnbS5lYywgbHpuLmZpdC5lYykNCg0KbHpuLnZnbS5nd2MgPC0gdmFyaW9ncmFtKChnd2MpfmxvbitsYXQsIHNhbXBsZV9sb2NhdGlvbnMsIHdpZHRoPTAuMDAwMikNCmx6bi5maXQuZ3djIDwtIGZpdC52YXJpb2dyYW0obHpuLnZnbS5nd2MsIG1vZGVsPXZnbShjKCJFeHAiLCJTcGgiLCAiR2F1IiwgIk1hdCIpKSkNCnBsb3QobHpuLnZnbS5nd2MsIGx6bi5maXQuZ3djKQ0KDQpsem4udmdtLmNsYXkgPC0gdmFyaW9ncmFtKChwZXJfY2xheSl+bG9uK2xhdCwgc2FtcGxlX2xvY2F0aW9ucywgd2lkdGg9MC4wMDAxKQ0KbHpuLmZpdC5jbGF5IDwtIGZpdC52YXJpb2dyYW0obHpuLnZnbS5jbGF5LCBtb2RlbD12Z20oYygiRXhwIiwiU3BoIiwgIkdhdSIsICJNYXQiKSkpDQpwbG90KGx6bi52Z20uY2xheSwgbHpuLmZpdC5jbGF5KQ0KDQpsem4udmdtLnNhbmQgPC0gdmFyaW9ncmFtKChwZXJfc2FuZCl+bG9uK2xhdCwgc2FtcGxlX2xvY2F0aW9ucykNCmx6bi5maXQuc2FuZCA8LSBmaXQudmFyaW9ncmFtKGx6bi52Z20uc2FuZCwgbW9kZWw9dmdtKGMoIkV4cCIsIlNwaCIsICJHYXUiLCAiTWF0IikpKQ0KcGxvdChsem4udmdtLnNhbmQsIGx6bi5maXQuc2FuZCkNCg0KbHpuLnZnbS5zaWx0IDwtIHZhcmlvZ3JhbSgocGVyX3NpbHQpfmxvbitsYXQsIHNhbXBsZV9sb2NhdGlvbnMpDQpsem4uZml0LnNpbHQgPC0gZml0LnZhcmlvZ3JhbShsem4udmdtLnNpbHQsIG1vZGVsPXZnbShjKCJFeHAiLCJTcGgiLCAiR2F1IiwgIk1hdCIpKSkNCnBsb3QobHpuLnZnbS5zaWx0LCBsem4uZml0LnNpbHQsIGRpZmY9VFJVRSkNCg0KbHpuLmZpdC5waA0KbHpuLmZpdC5lYw0KbHpuLmZpdC5nd2MNCmx6bi5maXQuY2xheQ0KbHpuLmZpdC5zYW5kDQpsem4uZml0LnNpbHQNCg0KDQoNCmBgYA0KDQpOb3cgdGhhdCB3ZSBmaXQgdGhlIHZhcmlvZ3JhbSBtb2RlbHMgdG8gdGhlIGRhdGEsIHdlIHdpbGwgbm93IHVzZSB0aGlzIGluZm9ybWF0aW9uIGluIGtyZWdpbmcNCg0KYGBge3J9DQpiYm94KHNhbXBsZV9sb2NhdGlvbnMpDQoNCiNDcmVhdGUgYSBncmlkIHRvIGVzdGltYXRlIHZhbHVlcyBvdmVyDQoNCnhfcmFuZ2UgPC0gYXMubnVtZXJpYyhjKC05NC4yMzU0NiwgLTk0LjIzNDAyKSkNCnlfcmFuZ2UgPC0gYXMubnVtZXJpYyhjKDM2LjA2NTYzLCAzNi4wNjY2NSkpDQoNCiMgY3JlYXRlIGFuIGVtcHR5IGdyaWQgb2YgdmFsdWVzIHJhbmdpbmcgZnJvbSB0aGUgeG1pbi14bWF4LCB5bWluLXltYXgNCnNhbXBsZS5ncmlkIDwtIGV4cGFuZC5ncmlkKHggPSBzZXEoZnJvbSA9IHhfcmFuZ2VbMV0sDQogICAgICAgICAgICAgICAgICAgdG8gPSB4X3JhbmdlWzJdLCANCiAgICAgICAgICAgICAgICAgICBsZW5ndGgub3V0PTMwKSwNCiAgICAgICAgICAgICAgICAgICB5ID0gc2VxKGZyb20gPSB5X3JhbmdlWzFdLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0byA9IHlfcmFuZ2VbMl0sIA0KICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGgub3V0PTMwKSkgICMgZXhwYW5kIHBvaW50cyB0byBncmlkDQoNCmNsYXNzKHNhbXBsZS5ncmlkKQ0Kc2FtcGxlLmdyaWQkbnVtYmVyPXNlcShmcm9tPTEsIHRvPTkwMCwgbGVuZ3RoLm91dD05MDApDQoNCnBsb3QxIDwtIHNhbXBsZV9sb2NhdGlvbnMgJT4lIGFzLmRhdGEuZnJhbWUgJT4lDQogIGdncGxvdChhZXMobGF0LCBsb24pKSArIGdlb21fcG9pbnQoc2l6ZT0uMjUpICsgY29vcmRfZXF1YWwoKSArIA0KZ2d0aXRsZSgiUG9pbnRzIHdpdGggbWVhc3VyZW1lbnRzIikNCg0KDQojIHRoaXMgaXMgY2xlYXJseSBncmlkZGVkIG92ZXIgdGhlIHJlZ2lvbiBvZiBpbnRlcmVzdA0KcGxvdDIgPC0gc2FtcGxlLmdyaWQgJT4lIGFzLmRhdGEuZnJhbWUgJT4lDQogIGdncGxvdChhZXMoeSwgeCkpICsgZ2VvbV9wb2ludChzaXplPS4yNSkgKyBjb29yZF9lcXVhbCgpICsgDQogIGdndGl0bGUoIlBvaW50cyBhdCB3aGljaCB0byBlc3RpbWF0ZSIpDQoNCmxpYnJhcnkoZ3JpZEV4dHJhKQ0KZ3JpZC5hcnJhbmdlKHBsb3QxLCBwbG90MiwgbmNvbD0yKQ0KDQpgYGANCg0KYGBge3J9DQoNCmNvb3JkaW5hdGVzKHNhbXBsZS5ncmlkKSA8LSB+IHggKyB5DQoNCg0KYGBgDQoNCmBgYHtyfQ0KbHpuLmtyaWdlZC5waCA8LSBrcmlnZShwaDF+MSwgc2FtcGxlX2xvY2F0aW9ucywgc2FtcGxlLmdyaWQsIG1vZGVsPWx6bi5maXQucGgpDQpsem4ua3JpZ2VkLmVjIDwtIGtyaWdlKGVjMX4xLCBzYW1wbGVfbG9jYXRpb25zLCBzYW1wbGUuZ3JpZCwgbW9kZWw9bHpuLmZpdC5lYykNCmx6bi5rcmlnZWQuZ3djIDwtIGtyaWdlKGd3Y34xLCBzYW1wbGVfbG9jYXRpb25zLCBzYW1wbGUuZ3JpZCwgbW9kZWw9bHpuLmZpdC5nd2MpDQpsem4ua3JpZ2VkLmNsYXkgPC0ga3JpZ2UocGVyX2NsYXl+MSwgc2FtcGxlX2xvY2F0aW9ucywgc2FtcGxlLmdyaWQsIG1vZGVsPWx6bi5maXQuY2xheSkNCmx6bi5rcmlnZWQuc2FuZCA8LSBrcmlnZShwZXJfc2FuZH4xLCBzYW1wbGVfbG9jYXRpb25zLCBzYW1wbGUuZ3JpZCwgbW9kZWw9bHpuLmZpdC5zYW5kKQ0KbHpuLmtyaWdlZC5zaWx0IDwtIGtyaWdlKHBlcl9zaWx0fjEsIHNhbXBsZV9sb2NhdGlvbnMsIHNhbXBsZS5ncmlkLCBtb2RlbD1sem4uZml0LnNpbHQpDQoNCmE8LSBsem4ua3JpZ2VkLnBoICU+JSBhcy5kYXRhLmZyYW1lICU+JQ0KICBnZ3Bsb3QoYWVzKHg9eCwgeT15KSkgKyBnZW9tX3RpbGUoYWVzKGZpbGw9dmFyMS5wcmVkKSkgKyBjb29yZF9lcXVhbCgpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAieWVsbG93IiwgaGlnaD0icmVkIikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzPWNvbW1hKSArIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9Y29tbWEpICsNCiAgdGhlbWVfYncoKSArIGxhYnMoeD0ibG9uZ2l0dWRlIiwgeT0ibGF0aXR1ZGUiLCB0aXRsZSA9ICJXV1BTIFByZWQgcEggMC0xMGNtIiwgZmlsbD0iUHJlZCBwSCIpDQoNCmI8LSBsem4ua3JpZ2VkLmVjICU+JSBhcy5kYXRhLmZyYW1lICU+JQ0KICBnZ3Bsb3QoYWVzKHg9eCwgeT15KSkgKyBnZW9tX3RpbGUoYWVzKGZpbGw9dmFyMS5wcmVkKSkgKyBjb29yZF9lcXVhbCgpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAieWVsbG93IiwgaGlnaD0icmVkIikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzPWNvbW1hKSArIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9Y29tbWEpICsNCiAgdGhlbWVfYncoKSArIGxhYnMoeD0ibG9uZ2l0dWRlIiwgeT0ibGF0aXR1ZGUiLCB0aXRsZSA9ICJXV1BTIFByZWQgRUMgMC0xMGNtIiwgZmlsbD0iUHJlZCBFQyAodVMvY20iKQ0KDQpjPC0gbHpuLmtyaWdlZC5nd2MgJT4lIGFzLmRhdGEuZnJhbWUgJT4lDQogIGdncGxvdChhZXMoeD14LCB5PXkpKSArIGdlb21fdGlsZShhZXMoZmlsbD12YXIxLnByZWQpKSArIGNvb3JkX2VxdWFsKCkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJ5ZWxsb3ciLCBoaWdoPSJyZWQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9Y29tbWEpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1jb21tYSkgKw0KICB0aGVtZV9idygpICsgbGFicyh4PSJsb25naXR1ZGUiLCB5PSJsYXRpdHVkZSIsIHRpdGxlID0gIldXUFMgUHJlZCBHV0MgMC0xMGNtIiwgZmlsbD0iUHJlZCBHV0MgKCUgZy9nKSIpDQoNCmQ8LSBsem4ua3JpZ2VkLmNsYXkgJT4lIGFzLmRhdGEuZnJhbWUgJT4lDQogIGdncGxvdChhZXMoeD14LCB5PXkpKSArIGdlb21fdGlsZShhZXMoZmlsbD12YXIxLnByZWQpKSArIGNvb3JkX2VxdWFsKCkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJ5ZWxsb3ciLCBoaWdoPSJyZWQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9Y29tbWEpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1jb21tYSkgKw0KICB0aGVtZV9idygpICsgbGFicyh4PSJsb25naXR1ZGUiLCB5PSJsYXRpdHVkZSIsIHRpdGxlID0gIldXUFMgUHJlZCAlIENsYXkgMC0xMGNtIiwgZmlsbD0iUHJlZCBDbGF5ICglKSIpDQoNCmU8LSBsem4ua3JpZ2VkLnNhbmQgJT4lIGFzLmRhdGEuZnJhbWUgJT4lDQogIGdncGxvdChhZXMoeD14LCB5PXkpKSArIGdlb21fdGlsZShhZXMoZmlsbD12YXIxLnByZWQpKSArIGNvb3JkX2VxdWFsKCkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJ5ZWxsb3ciLCBoaWdoPSJyZWQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9Y29tbWEpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1jb21tYSkgKw0KICB0aGVtZV9idygpICsgbGFicyh4PSJsb25naXR1ZGUiLCB5PSJsYXRpdHVkZSIsIHRpdGxlID0gIldXUFMgUHJlZCAlIFNhbmQgMC0xMGNtIiwgZmlsbD0iUHJlZCBTYW5kICglKSIpDQoNCmY8LSBsem4ua3JpZ2VkLnNpbHQgJT4lIGFzLmRhdGEuZnJhbWUgJT4lDQogIGdncGxvdChhZXMoeD14LCB5PXkpKSArIGdlb21fdGlsZShhZXMoZmlsbD12YXIxLnByZWQpKSArIGNvb3JkX2VxdWFsKCkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJ5ZWxsb3ciLCBoaWdoPSJyZWQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9Y29tbWEpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1jb21tYSkgKw0KICB0aGVtZV9idygpICsgbGFicyh4PSJsb25naXR1ZGUiLCB5PSJsYXRpdHVkZSIsIHRpdGxlID0gIldXUFMgUHJlZCAlIFNpbHQgMC0xMGNtIiwgZmlsbD0iUHJlZCBTaWx0ICglKSIpDQoNCmENCmINCmMNCmQNCmUNCmYNCmBgYA0KDQo=