# Load libraries
library(sf)
library(dplyr)
library(readr)
# Set working directory
setwd("C:/Users/eujoe/Documents/welbeing/Final_submission_2")
getwd()
[1] "C:/Users/eujoe/Documents/welbeing/Final_submission_2"
# List all files
list.files()
[1] "betweenes_clean.csv"
[2] "clossness_clean.csv"
[3] "exercise.nb.html"
[4] "exercise.Rmd"
[5] "frequency_clean.csv"
[6] "Grid.cpg"
[7] "Grid.dbf"
[8] "Grid.prj"
[9] "Grid.qmd"
[10] "Grid.shp"
[11] "Grid.shx"
[12] "pedestrian_network_clean.csv"
[13] "public_Transportation_access_clean.csv"
# Read the spatial grid
grid <- st_read("Grid.shp")
Reading layer `Grid' from data source
`C:\Users\eujoe\Documents\welbeing\Final_submission_2\Grid.shp'
using driver `ESRI Shapefile'
Simple feature collection with 1331 features and 4 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 395103.5 ymin: 5744177 xmax: 415704.7 ymax: 5768641
Projected CRS: ETRS89 / UTM zone 32N
betweenes <- read.csv(
"betweenes_clean.csv",
stringsAsFactors = FALSE,
encoding = "UTF-8"
)
closeness <- read.csv(
"clossness_clean.csv",
stringsAsFactors = FALSE,
fileEncoding = "UTF-8"
)
pedestrian <- read.csv(
"pedestrian_network_clean.csv",
stringsAsFactors = FALSE,
fileEncoding = "UTF-8"
)
public_tr <- read.csv(
"public_Transportation_access_clean.csv",
stringsAsFactors = FALSE,
fileEncoding = "UTF-8"
)
frequency <- read.csv(
"frequency_clean.csv",
stringsAsFactors = FALSE,
fileEncoding = "UTF-8"
)
names(grid)
[1] "OBJECTID" "GRID_ID" "Shape_Leng" "Shape_Area" "geometry"
names(betweenes)
[1] "GRID_ID" "bet_value"
names(closeness)
[1] "GRID_ID" "clos_value"
names(pedestrian)
[1] "GRID_ID" "pd_value"
names(public_tr)
[1] "GRID_ID" "pta_value"
names(frequency)
[1] "GRID_ID" "frq_value"
# Check IDs are the same type
grid$GRID_ID <- as.character(grid$GRID_ID)
betweenes$GRID_ID <- as.character(betweenes$GRID_ID)
closeness$GRID_ID <- as.character(closeness$GRID_ID)
pedestrian$GRID_ID <- as.character(pedestrian$GRID_ID)
public_tr$GRID_ID <- as.character(public_tr$GRID_ID)
frequency$GRID_ID <- as.character(frequency$GRID_ID)
# Join CSVs together
attributes <- betweenes %>%
left_join(closeness, by = "GRID_ID") %>%
left_join(pedestrian, by = "GRID_ID") %>%
left_join(public_tr, by = "GRID_ID") %>%
left_join(frequency, by = "GRID_ID")
# Join to spatial grid
grid_joined <- grid %>%
left_join(attributes, by = "GRID_ID")
# Drop geometry
grid_joined_df <- st_drop_geometry(grid_joined)
# Write to CSV
write.csv(
grid_joined_df,
"Grid_wellbeing.csv",
row.names = FALSE
)
grid_joined_df <- st_drop_geometry(grid_joined)
summary(grid_joined$bet_value)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0 0 59 1099991 528882 45269913
summary(grid_joined$clos_value)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.00000 0.00000 0.06108 4.76393 10.25823 17.84093
summary(grid_joined$frq_value)
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
5.0 715.0 963.2 904.9 1113.9 1934.0 895
sum(!is.finite(grid_joined$bet_value))
[1] 0
sum(!is.finite(grid_joined$clos_value))
[1] 0
sum(!is.finite(grid_joined$frq_value))
[1] 895
grid_joined <- grid_joined %>%
mutate(
bet_value = ifelse(is.finite(bet_value), bet_value, 0),
clos_value = ifelse(is.finite(clos_value), clos_value, 0),
frq_value = ifelse(is.finite(frq_value), frq_value, 0)
)
library(spdep)
# Create neighbors
nb <- poly2nb(grid_joined, queen = TRUE)
lw <- nb2listw(nb, style = "W", zero.policy = TRUE)
# Create lag variables INSIDE grid_joined
grid_joined <- grid_joined %>%
mutate(
bet_lag = lag.listw(lw, bet_value, zero.policy = TRUE),
clos_lag = lag.listw(lw, clos_value, zero.policy = TRUE) ,
frq_lag = lag.listw(lw, frq_value, zero.policy = TRUE)
)
# Drop geometry (lags included)
df <- st_drop_geometry(grid_joined)
z_std <- function(x) {
(x - mean(x, na.rm = TRUE)) / sd(x, na.rm = TRUE)
}
df_std <- df %>%
mutate(
bet_z = z_std(bet_lag),
clos_z = z_std(clos_lag),
pd_z = z_std(pd_value),
pta_z = z_std(pta_value),
frq_z = z_std(frq_lag),
)
names(df)
[1] "OBJECTID" "GRID_ID" "Shape_Leng" "Shape_Area" "bet_value"
[6] "clos_value" "pd_value" "pta_value" "frq_value" "bet_lag"
[11] "clos_lag" "frq_lag"
summary(df$bet_lag)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.000e+00 2.210e+01 1.077e+05 1.102e+06 1.625e+06 1.244e+07
summary(df$clos_lag)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.00000 0.02277 3.72398 4.78497 8.52862 16.13242
summary(df$frq_lag)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.0 0.0 154.9 297.9 531.9 1308.7
df_std <- df_std %>%
mutate(
accessibility_index =
(bet_z + clos_z + pd_z + pta_z+frq_z) / 5
)
write.csv(
df_std,
"Grid_accessibility_index_mixed.csv",
row.names = FALSE
)
df_std <- df_std %>%
mutate(
accessibility_index_01 =
(accessibility_index - min(accessibility_index, na.rm = TRUE)) /
(max(accessibility_index, na.rm = TRUE) - min(accessibility_index, na.rm = TRUE))
)
grid_access <- grid_joined %>%
left_join(
df_std %>% select(GRID_ID, accessibility_index_01),
by = "GRID_ID"
)
st_write(
grid_access,
"Grid_accessibility_index_mixed.gpkg",
layer = "accessibility",
delete_layer = TRUE
)
Deleting layer `accessibility' using driver `GPKG'
Writing layer `accessibility' to data source
`Grid_accessibility_index_mixed.gpkg' using driver `GPKG'
Writing 1331 features with 13 fields and geometry type Multi Polygon.
library(ggplot2)
ggplot(grid_access) +
geom_sf(aes(fill = accessibility_index_01), color = NA) +
scale_fill_viridis_c(
name = "Accessibility\nIndex",
option = "viridis"
) +
labs(
title = "Composite Accessibility Index",
caption = "Higher values indicate better accessibility"
) +
theme_minimal() +
theme(
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank()
)

library(tmap)
library(spdep)
library(dplyr)
tmap_mode("plot")
grid_access <- grid_joined %>%
left_join(
df_std %>%
select(GRID_ID,
bet_z, clos_z, pd_z, pta_z,
accessibility_index,
accessibility_index_01),
by = "GRID_ID"
)
# Z-score function
z_std <- function(x) {
if (sd(x, na.rm = TRUE) == 0) {
rep(0, length(x))
} else {
(x - mean(x, na.rm = TRUE)) / sd(x, na.rm = TRUE)
}
}
grid_access <- grid_access %>%
mutate(
bet_z = z_std(bet_value),
bet_z_lag = z_std(bet_lag),
clos_z = z_std(clos_value),
clos_z_lag = z_std(clos_lag),
frq_z = z_std(frq_value),
frq_z_lag = z_std(frq_lag),
)
names(grid_access)
[1] "OBJECTID" "GRID_ID"
[3] "Shape_Leng" "Shape_Area"
[5] "bet_value" "clos_value"
[7] "pd_value" "pta_value"
[9] "frq_value" "bet_lag"
[11] "clos_lag" "frq_lag"
[13] "bet_z" "clos_z"
[15] "pd_z" "pta_z"
[17] "accessibility_index" "accessibility_index_01"
[19] "geometry" "bet_z_lag"
[21] "clos_z_lag" "frq_z"
[23] "frq_z_lag"
bet_z_map <- tm_shape(grid_access) +
tm_polygons("bet_z", palette = "viridis", title = "Betweenness (z)") +
tm_layout(frame = FALSE)
bet_z_lag_map <- tm_shape(grid_access) +
tm_polygons("bet_z_lag", palette = "viridis", title = "Betweenness (lag + z)") +
tm_layout(frame = FALSE)
clos_z_map <- tm_shape(grid_access) +
tm_polygons("clos_z", palette = "viridis", title = "Closeness (z)") +
tm_layout(frame = FALSE)
clos_z_lag_map <- tm_shape(grid_access) +
tm_polygons("clos_z_lag", palette = "viridis", title = "Closeness (lag + z)") +
tm_layout(frame = FALSE)
frq_z_map <- tm_shape(grid_access) +
tm_polygons("frq_z", palette = "viridis", title = "Frequency (z)") +
tm_layout(frame = FALSE)
frq_z_lag_map <- tm_shape(grid_access) +
tm_polygons("frq_z_lag", palette = "viridis", title = "Frequency (lag + z)") +
tm_layout(frame = FALSE)
tmap_arrange(
bet_z_map, bet_z_lag_map,
clos_z_map, clos_z_lag_map,
frq_z_map, frq_z_lag_map,
ncol = 2
)

tm_shape(grid_access) +
tm_polygons(
"pd_z",
style = "quantile",
n = 5,
palette = "viridis",
title = "Pedestrian Network (z)"
) +
tm_layout(frame = FALSE)

tm_shape(grid_access) +
tm_polygons(
"pta_z",
style = "quantile",
n = 5,
palette = "viridis",
title = "Public Transport Access (z)"
) +
tm_layout(frame = FALSE)

grid_access$accessibility_index_01[
is.na(grid_access$accessibility_index_01)
] <- 0
nb <- poly2nb(grid_access, queen = TRUE)
lw <- nb2listw(nb, style = "W", zero.policy = TRUE)
z <- scale(grid_access$accessibility_index_01)[, 1]
z[!is.finite(z)] <- 0
z_lag <- lag.listw(lw, z, zero.policy = TRUE)
z_lag[!is.finite(z_lag)] <- 0
lisa <- localmoran(
grid_access$accessibility_index_01,
lw,
zero.policy = TRUE,
na.action = na.exclude
)
grid_access$lisa_I <- lisa[, 1]
grid_access$lisa_p <- lisa[, ncol(lisa)]
# Local Moran's I
lisa <- localmoran(
grid_access$accessibility_index_01,
lw,
zero.policy = TRUE,
na.action = na.exclude
)
# Attach results safely
grid_access$lisa_I <- lisa[, 1]
grid_access$lisa_p <- lisa[, ncol(lisa)]
z <- scale(grid_access$accessibility_index_01)[,1]
z[!is.finite(z)] <- 0
z_lag <- lag.listw(lw, z, zero.policy = TRUE)
z_lag[!is.finite(z_lag)] <- 0
grid_access$lisa_cluster <- "Not significant"
grid_access$lisa_cluster[
z > 0 & z_lag > 0 & grid_access$lisa_p <= 0.05
] <- "High–High"
grid_access$lisa_cluster[
z < 0 & z_lag < 0 & grid_access$lisa_p <= 0.05
] <- "Low–Low"
grid_access$lisa_cluster[
z > 0 & z_lag < 0 & grid_access$lisa_p <= 0.05
] <- "High–Low"
grid_access$lisa_cluster[
z < 0 & z_lag > 0 & grid_access$lisa_p <= 0.05
] <- "Low–High"
library(tmap)
tm_shape(grid_access) +
tm_polygons(
"lisa_cluster",
palette = c(
"High–High" = "red",
"Low–Low" = "blue",
"High–Low" = "pink",
"Low–High" = "lightblue",
"Not significant" = "grey80"
),
title = "LISA Clusters (p ≤ 0.05)"
) +
tm_layout(
frame = FALSE,
legend.outside = TRUE
)

tm_shape(grid_access) +
tm_polygons(
"accessibility_index_01",
style = "fixed",
breaks = c(0, 0.2, 0.4, 0.6, 0.8, 1),
palette = "viridis",
title = "Accessibility Index"
)

LS0tDQp0aXRsZTogIkNvbXBvc2l0ZSBhY2Nlc3NpYmlsaXR5IGluZGV4IC0gTXVuc3RlciINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQpgYGB7cn0NCiMgTG9hZCBsaWJyYXJpZXMNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZWFkcikNCmBgYA0KDQpgYGB7cn0NCiMgU2V0IHdvcmtpbmcgZGlyZWN0b3J5DQpzZXR3ZCgiQzovVXNlcnMvZXVqb2UvRG9jdW1lbnRzL3dlbGJlaW5nL0ZpbmFsX3N1Ym1pc3Npb25fMiIpDQpnZXR3ZCgpDQoNCiMgTGlzdCBhbGwgZmlsZXMNCmxpc3QuZmlsZXMoKQ0KYGBgDQoNCmBgYHtyfQ0KIyBSZWFkIHRoZSBzcGF0aWFsIGdyaWQNCmdyaWQgPC0gc3RfcmVhZCgiR3JpZC5zaHAiKQ0KDQpgYGANCmBgYHtyfQ0KYmV0d2VlbmVzIDwtIHJlYWQuY3N2KA0KICAiYmV0d2VlbmVzX2NsZWFuLmNzdiIsDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwNCiAgZW5jb2RpbmcgPSAiVVRGLTgiDQopDQpgYGANCg0KYGBge3J9DQpjbG9zZW5lc3MgPC0gcmVhZC5jc3YoDQogICJjbG9zc25lc3NfY2xlYW4uY3N2IiwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLA0KICBmaWxlRW5jb2RpbmcgPSAiVVRGLTgiDQopDQpgYGANCg0KYGBge3J9DQpwZWRlc3RyaWFuIDwtIHJlYWQuY3N2KA0KICAicGVkZXN0cmlhbl9uZXR3b3JrX2NsZWFuLmNzdiIsDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwNCiAgZmlsZUVuY29kaW5nID0gIlVURi04Ig0KKQ0KDQpgYGANCg0KYGBge3J9DQpwdWJsaWNfdHIgPC0gcmVhZC5jc3YoDQogICJwdWJsaWNfVHJhbnNwb3J0YXRpb25fYWNjZXNzX2NsZWFuLmNzdiIsDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwNCiAgZmlsZUVuY29kaW5nID0gIlVURi04Ig0KKQ0KDQpgYGANCg0KYGBge3J9DQpmcmVxdWVuY3kgPC0gcmVhZC5jc3YoDQogICJmcmVxdWVuY3lfY2xlYW4uY3N2IiwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLA0KICBmaWxlRW5jb2RpbmcgPSAiVVRGLTgiDQopDQpgYGANCg0KDQpgYGB7cn0NCm5hbWVzKGdyaWQpDQpuYW1lcyhiZXR3ZWVuZXMpDQpuYW1lcyhjbG9zZW5lc3MpDQpuYW1lcyhwZWRlc3RyaWFuKQ0KbmFtZXMocHVibGljX3RyKQ0KbmFtZXMoZnJlcXVlbmN5KQ0KYGBgDQpgYGB7cn0NCiMgQ2hlY2sgSURzIGFyZSB0aGUgc2FtZSB0eXBlDQpncmlkJEdSSURfSUQgICAgICAgIDwtIGFzLmNoYXJhY3RlcihncmlkJEdSSURfSUQpDQpiZXR3ZWVuZXMkR1JJRF9JRCA8LSBhcy5jaGFyYWN0ZXIoYmV0d2VlbmVzJEdSSURfSUQpDQpjbG9zZW5lc3MkR1JJRF9JRCAgIDwtIGFzLmNoYXJhY3RlcihjbG9zZW5lc3MkR1JJRF9JRCkNCnBlZGVzdHJpYW4kR1JJRF9JRCAgPC0gYXMuY2hhcmFjdGVyKHBlZGVzdHJpYW4kR1JJRF9JRCkNCnB1YmxpY190ciRHUklEX0lEICAgPC0gYXMuY2hhcmFjdGVyKHB1YmxpY190ciRHUklEX0lEKQ0KZnJlcXVlbmN5JEdSSURfSUQgICA8LSBhcy5jaGFyYWN0ZXIoZnJlcXVlbmN5JEdSSURfSUQpDQpgYGANCg0KYGBge3J9DQojIEpvaW4gQ1NWcyB0b2dldGhlcg0KYXR0cmlidXRlcyA8LSBiZXR3ZWVuZXMgJT4lDQogIGxlZnRfam9pbihjbG9zZW5lc3MsICBieSA9ICJHUklEX0lEIikgJT4lDQogIGxlZnRfam9pbihwZWRlc3RyaWFuLCBieSA9ICJHUklEX0lEIikgJT4lDQogIGxlZnRfam9pbihwdWJsaWNfdHIsICBieSA9ICJHUklEX0lEIikgJT4lDQogIGxlZnRfam9pbihmcmVxdWVuY3ksICBieSA9ICJHUklEX0lEIikNCg0KIyBKb2luIHRvIHNwYXRpYWwgZ3JpZA0KZ3JpZF9qb2luZWQgPC0gZ3JpZCAlPiUNCiAgbGVmdF9qb2luKGF0dHJpYnV0ZXMsIGJ5ID0gIkdSSURfSUQiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBEcm9wIGdlb21ldHJ5DQpncmlkX2pvaW5lZF9kZiA8LSBzdF9kcm9wX2dlb21ldHJ5KGdyaWRfam9pbmVkKQ0KDQojIFdyaXRlIHRvIENTVg0Kd3JpdGUuY3N2KA0KICBncmlkX2pvaW5lZF9kZiwNCiAgIkdyaWRfd2VsbGJlaW5nLmNzdiIsDQogIHJvdy5uYW1lcyA9IEZBTFNFDQopDQpgYGANCg0KYGBge3J9DQpncmlkX2pvaW5lZF9kZiA8LSBzdF9kcm9wX2dlb21ldHJ5KGdyaWRfam9pbmVkKQ0Kc3VtbWFyeShncmlkX2pvaW5lZCRiZXRfdmFsdWUpDQpzdW1tYXJ5KGdyaWRfam9pbmVkJGNsb3NfdmFsdWUpDQpzdW1tYXJ5KGdyaWRfam9pbmVkJGZycV92YWx1ZSkNCg0Kc3VtKCFpcy5maW5pdGUoZ3JpZF9qb2luZWQkYmV0X3ZhbHVlKSkNCnN1bSghaXMuZmluaXRlKGdyaWRfam9pbmVkJGNsb3NfdmFsdWUpKQ0Kc3VtKCFpcy5maW5pdGUoZ3JpZF9qb2luZWQkZnJxX3ZhbHVlKSkNCmBgYA0KYGBge3J9DQpncmlkX2pvaW5lZCA8LSBncmlkX2pvaW5lZCAlPiUNCiAgbXV0YXRlKA0KICAgIGJldF92YWx1ZSAgPSBpZmVsc2UoaXMuZmluaXRlKGJldF92YWx1ZSksICBiZXRfdmFsdWUsICAwKSwNCiAgICBjbG9zX3ZhbHVlID0gaWZlbHNlKGlzLmZpbml0ZShjbG9zX3ZhbHVlKSwgY2xvc192YWx1ZSwgMCksDQogICAgZnJxX3ZhbHVlID0gaWZlbHNlKGlzLmZpbml0ZShmcnFfdmFsdWUpLCBmcnFfdmFsdWUsIDApDQogICkNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoc3BkZXApDQoNCiMgQ3JlYXRlIG5laWdoYm9ycw0KbmIgPC0gcG9seTJuYihncmlkX2pvaW5lZCwgcXVlZW4gPSBUUlVFKQ0KbHcgPC0gbmIybGlzdHcobmIsIHN0eWxlID0gIlciLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQoNCiMgQ3JlYXRlIGxhZyB2YXJpYWJsZXMgSU5TSURFIGdyaWRfam9pbmVkDQpncmlkX2pvaW5lZCA8LSBncmlkX2pvaW5lZCAlPiUNCiAgbXV0YXRlKA0KICAgIGJldF9sYWcgID0gbGFnLmxpc3R3KGx3LCBiZXRfdmFsdWUsICB6ZXJvLnBvbGljeSA9IFRSVUUpLA0KICAgIGNsb3NfbGFnID0gbGFnLmxpc3R3KGx3LCBjbG9zX3ZhbHVlLCB6ZXJvLnBvbGljeSA9IFRSVUUpICwNCiAgICBmcnFfbGFnID0gbGFnLmxpc3R3KGx3LCBmcnFfdmFsdWUsIHplcm8ucG9saWN5ID0gVFJVRSkNCiAgICANCiAgICANCiAgKQ0KDQojIERyb3AgZ2VvbWV0cnkgKGxhZ3MgaW5jbHVkZWQpDQpkZiA8LSBzdF9kcm9wX2dlb21ldHJ5KGdyaWRfam9pbmVkKQ0KDQpgYGANCg0KYGBge3J9DQp6X3N0ZCA8LSBmdW5jdGlvbih4KSB7DQogICh4IC0gbWVhbih4LCBuYS5ybSA9IFRSVUUpKSAvIHNkKHgsIG5hLnJtID0gVFJVRSkNCn0NCg0KZGZfc3RkIDwtIGRmICU+JQ0KICBtdXRhdGUoDQogICAgYmV0X3ogID0gel9zdGQoYmV0X2xhZyksDQogICAgY2xvc196ID0gel9zdGQoY2xvc19sYWcpLA0KICAgIHBkX3ogICA9IHpfc3RkKHBkX3ZhbHVlKSwNCiAgICBwdGFfeiAgPSB6X3N0ZChwdGFfdmFsdWUpLA0KICAgIGZycV96ICA9IHpfc3RkKGZycV9sYWcpLA0KICApDQpgYGANCg0KYGBge3J9DQpuYW1lcyhkZikNCnN1bW1hcnkoZGYkYmV0X2xhZykNCnN1bW1hcnkoZGYkY2xvc19sYWcpDQpzdW1tYXJ5KGRmJGZycV9sYWcpDQpgYGANCmBgYHtyfQ0KZGZfc3RkIDwtIGRmX3N0ZCAlPiUNCiAgbXV0YXRlKA0KICAgIGFjY2Vzc2liaWxpdHlfaW5kZXggPQ0KICAgICAgKGJldF96ICsgY2xvc196ICsgcGRfeiArIHB0YV96K2ZycV96KSAvIDUNCiAgKQ0KYGBgDQoNCmBgYHtyfQ0Kd3JpdGUuY3N2KA0KICBkZl9zdGQsDQogICJHcmlkX2FjY2Vzc2liaWxpdHlfaW5kZXhfbWl4ZWQuY3N2IiwNCiAgcm93Lm5hbWVzID0gRkFMU0UNCikNCmBgYA0KDQpgYGB7cn0NCmRmX3N0ZCA8LSBkZl9zdGQgJT4lDQogIG11dGF0ZSgNCiAgICBhY2Nlc3NpYmlsaXR5X2luZGV4XzAxID0NCiAgICAgIChhY2Nlc3NpYmlsaXR5X2luZGV4IC0gbWluKGFjY2Vzc2liaWxpdHlfaW5kZXgsIG5hLnJtID0gVFJVRSkpIC8NCiAgICAgIChtYXgoYWNjZXNzaWJpbGl0eV9pbmRleCwgbmEucm0gPSBUUlVFKSAtIG1pbihhY2Nlc3NpYmlsaXR5X2luZGV4LCBuYS5ybSA9IFRSVUUpKQ0KICApDQpgYGANCg0KYGBge3J9DQpncmlkX2FjY2VzcyA8LSBncmlkX2pvaW5lZCAlPiUNCiAgbGVmdF9qb2luKA0KICAgIGRmX3N0ZCAlPiUgc2VsZWN0KEdSSURfSUQsIGFjY2Vzc2liaWxpdHlfaW5kZXhfMDEpLA0KICAgIGJ5ID0gIkdSSURfSUQiDQogICkNCg0Kc3Rfd3JpdGUoDQogIGdyaWRfYWNjZXNzLA0KICAiR3JpZF9hY2Nlc3NpYmlsaXR5X2luZGV4X21peGVkLmdwa2ciLA0KICBsYXllciA9ICJhY2Nlc3NpYmlsaXR5IiwNCiAgZGVsZXRlX2xheWVyID0gVFJVRQ0KKQ0KYGBgDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmdncGxvdChncmlkX2FjY2VzcykgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gYWNjZXNzaWJpbGl0eV9pbmRleF8wMSksIGNvbG9yID0gTkEpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2MoDQogICAgbmFtZSA9ICJBY2Nlc3NpYmlsaXR5XG5JbmRleCIsDQogICAgb3B0aW9uID0gInZpcmlkaXMiDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkNvbXBvc2l0ZSBBY2Nlc3NpYmlsaXR5IEluZGV4IiwNCiAgICBjYXB0aW9uID0gIkhpZ2hlciB2YWx1ZXMgaW5kaWNhdGUgYmV0dGVyIGFjY2Vzc2liaWxpdHkiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpDQogICkNCmBgYA0KYGBge3J9DQpsaWJyYXJ5KHRtYXApDQpsaWJyYXJ5KHNwZGVwKQ0KbGlicmFyeShkcGx5cikNCg0KdG1hcF9tb2RlKCJwbG90IikNCmBgYA0KDQpgYGB7cn0NCmdyaWRfYWNjZXNzIDwtIGdyaWRfam9pbmVkICU+JQ0KICBsZWZ0X2pvaW4oDQogICAgZGZfc3RkICU+JQ0KICAgICAgc2VsZWN0KEdSSURfSUQsDQogICAgICAgICAgICAgYmV0X3osIGNsb3NfeiwgcGRfeiwgcHRhX3osDQogICAgICAgICAgICAgYWNjZXNzaWJpbGl0eV9pbmRleCwNCiAgICAgICAgICAgICBhY2Nlc3NpYmlsaXR5X2luZGV4XzAxKSwNCiAgICBieSA9ICJHUklEX0lEIg0KICApDQpgYGANCg0KDQoNCmBgYHtyfQ0KIyBaLXNjb3JlIGZ1bmN0aW9uDQp6X3N0ZCA8LSBmdW5jdGlvbih4KSB7DQogIGlmIChzZCh4LCBuYS5ybSA9IFRSVUUpID09IDApIHsNCiAgICByZXAoMCwgbGVuZ3RoKHgpKQ0KICB9IGVsc2Ugew0KICAgICh4IC0gbWVhbih4LCBuYS5ybSA9IFRSVUUpKSAvIHNkKHgsIG5hLnJtID0gVFJVRSkNCiAgfQ0KfQ0KDQpncmlkX2FjY2VzcyA8LSBncmlkX2FjY2VzcyAlPiUNCiAgbXV0YXRlKA0KICAgIGJldF96ICAgICAgPSB6X3N0ZChiZXRfdmFsdWUpLA0KICAgIGJldF96X2xhZyAgPSB6X3N0ZChiZXRfbGFnKSwNCiAgICBjbG9zX3ogICAgID0gel9zdGQoY2xvc192YWx1ZSksDQogICAgY2xvc196X2xhZyA9IHpfc3RkKGNsb3NfbGFnKSwNCiAgICBmcnFfeiAgPSB6X3N0ZChmcnFfdmFsdWUpLA0KICAgIGZycV96X2xhZyA9IHpfc3RkKGZycV9sYWcpLA0KICAgIA0KICApDQpuYW1lcyhncmlkX2FjY2VzcykNCmBgYA0KDQpgYGB7cn0NCmJldF96X21hcCA8LSB0bV9zaGFwZShncmlkX2FjY2VzcykgKw0KICB0bV9wb2x5Z29ucygiYmV0X3oiLCBwYWxldHRlID0gInZpcmlkaXMiLCB0aXRsZSA9ICJCZXR3ZWVubmVzcyAoeikiKSArDQogIHRtX2xheW91dChmcmFtZSA9IEZBTFNFKQ0KDQpiZXRfel9sYWdfbWFwIDwtIHRtX3NoYXBlKGdyaWRfYWNjZXNzKSArDQogIHRtX3BvbHlnb25zKCJiZXRfel9sYWciLCBwYWxldHRlID0gInZpcmlkaXMiLCB0aXRsZSA9ICJCZXR3ZWVubmVzcyAobGFnICsgeikiKSArDQogIHRtX2xheW91dChmcmFtZSA9IEZBTFNFKQ0KDQpjbG9zX3pfbWFwIDwtIHRtX3NoYXBlKGdyaWRfYWNjZXNzKSArDQogIHRtX3BvbHlnb25zKCJjbG9zX3oiLCBwYWxldHRlID0gInZpcmlkaXMiLCB0aXRsZSA9ICJDbG9zZW5lc3MgKHopIikgKw0KICB0bV9sYXlvdXQoZnJhbWUgPSBGQUxTRSkNCg0KY2xvc196X2xhZ19tYXAgPC0gdG1fc2hhcGUoZ3JpZF9hY2Nlc3MpICsNCiAgdG1fcG9seWdvbnMoImNsb3Nfel9sYWciLCBwYWxldHRlID0gInZpcmlkaXMiLCB0aXRsZSA9ICJDbG9zZW5lc3MgKGxhZyArIHopIikgKw0KICB0bV9sYXlvdXQoZnJhbWUgPSBGQUxTRSkNCg0KZnJxX3pfbWFwIDwtIHRtX3NoYXBlKGdyaWRfYWNjZXNzKSArDQogIHRtX3BvbHlnb25zKCJmcnFfeiIsIHBhbGV0dGUgPSAidmlyaWRpcyIsIHRpdGxlID0gIkZyZXF1ZW5jeSAoeikiKSArDQogIHRtX2xheW91dChmcmFtZSA9IEZBTFNFKQ0KDQpmcnFfel9sYWdfbWFwIDwtIHRtX3NoYXBlKGdyaWRfYWNjZXNzKSArDQogIHRtX3BvbHlnb25zKCJmcnFfel9sYWciLCBwYWxldHRlID0gInZpcmlkaXMiLCB0aXRsZSA9ICJGcmVxdWVuY3kgKGxhZyArIHopIikgKw0KICB0bV9sYXlvdXQoZnJhbWUgPSBGQUxTRSkNCg0KdG1hcF9hcnJhbmdlKA0KICBiZXRfel9tYXAsIGJldF96X2xhZ19tYXAsDQogIGNsb3Nfel9tYXAsIGNsb3Nfel9sYWdfbWFwLA0KICAgZnJxX3pfbWFwLCBmcnFfel9sYWdfbWFwLA0KICANCiAgbmNvbCA9IDINCikNCmBgYA0KDQpgYGB7cn0NCnRtX3NoYXBlKGdyaWRfYWNjZXNzKSArDQogIHRtX3BvbHlnb25zKA0KICAgICJwZF96IiwNCiAgICBzdHlsZSA9ICJxdWFudGlsZSIsDQogICAgbiA9IDUsDQogICAgcGFsZXR0ZSA9ICJ2aXJpZGlzIiwNCiAgICB0aXRsZSA9ICJQZWRlc3RyaWFuIE5ldHdvcmsgKHopIg0KICApICsNCiAgdG1fbGF5b3V0KGZyYW1lID0gRkFMU0UpDQpgYGANCmBgYHtyfQ0KdG1fc2hhcGUoZ3JpZF9hY2Nlc3MpICsNCiAgdG1fcG9seWdvbnMoDQogICAgInB0YV96IiwNCiAgICBzdHlsZSA9ICJxdWFudGlsZSIsDQogICAgbiA9IDUsDQogICAgcGFsZXR0ZSA9ICJ2aXJpZGlzIiwNCiAgICB0aXRsZSA9ICJQdWJsaWMgVHJhbnNwb3J0IEFjY2VzcyAoeikiDQogICkgKw0KICB0bV9sYXlvdXQoZnJhbWUgPSBGQUxTRSkNCmBgYA0KDQpgYGB7cn0NCmdyaWRfYWNjZXNzJGFjY2Vzc2liaWxpdHlfaW5kZXhfMDFbDQogIGlzLm5hKGdyaWRfYWNjZXNzJGFjY2Vzc2liaWxpdHlfaW5kZXhfMDEpDQpdIDwtIDANCmBgYA0KDQpgYGB7cn0NCm5iIDwtIHBvbHkybmIoZ3JpZF9hY2Nlc3MsIHF1ZWVuID0gVFJVRSkNCmx3IDwtIG5iMmxpc3R3KG5iLCBzdHlsZSA9ICJXIiwgemVyby5wb2xpY3kgPSBUUlVFKQ0KDQp6IDwtIHNjYWxlKGdyaWRfYWNjZXNzJGFjY2Vzc2liaWxpdHlfaW5kZXhfMDEpWywgMV0NCnpbIWlzLmZpbml0ZSh6KV0gPC0gMA0KDQp6X2xhZyA8LSBsYWcubGlzdHcobHcsIHosIHplcm8ucG9saWN5ID0gVFJVRSkNCnpfbGFnWyFpcy5maW5pdGUoel9sYWcpXSA8LSAwDQpgYGANCg0KYGBge3J9DQpsaXNhIDwtIGxvY2FsbW9yYW4oDQogIGdyaWRfYWNjZXNzJGFjY2Vzc2liaWxpdHlfaW5kZXhfMDEsDQogIGx3LA0KICB6ZXJvLnBvbGljeSA9IFRSVUUsDQogIG5hLmFjdGlvbiA9IG5hLmV4Y2x1ZGUNCikNCmdyaWRfYWNjZXNzJGxpc2FfSSA8LSBsaXNhWywgMV0NCmdyaWRfYWNjZXNzJGxpc2FfcCA8LSBsaXNhWywgbmNvbChsaXNhKV0NCmBgYA0KDQpgYGB7cn0NCiMgTG9jYWwgTW9yYW4ncyBJDQpsaXNhIDwtIGxvY2FsbW9yYW4oDQogIGdyaWRfYWNjZXNzJGFjY2Vzc2liaWxpdHlfaW5kZXhfMDEsDQogIGx3LA0KICB6ZXJvLnBvbGljeSA9IFRSVUUsDQogIG5hLmFjdGlvbiA9IG5hLmV4Y2x1ZGUNCikNCg0KIyBBdHRhY2ggcmVzdWx0cyBzYWZlbHkNCmdyaWRfYWNjZXNzJGxpc2FfSSA8LSBsaXNhWywgMV0NCmdyaWRfYWNjZXNzJGxpc2FfcCA8LSBsaXNhWywgbmNvbChsaXNhKV0NCmBgYA0KDQpgYGB7cn0NCnogPC0gc2NhbGUoZ3JpZF9hY2Nlc3MkYWNjZXNzaWJpbGl0eV9pbmRleF8wMSlbLDFdDQp6WyFpcy5maW5pdGUoeildIDwtIDANCg0Kel9sYWcgPC0gbGFnLmxpc3R3KGx3LCB6LCB6ZXJvLnBvbGljeSA9IFRSVUUpDQp6X2xhZ1shaXMuZmluaXRlKHpfbGFnKV0gPC0gMA0KDQpncmlkX2FjY2VzcyRsaXNhX2NsdXN0ZXIgPC0gIk5vdCBzaWduaWZpY2FudCINCg0KZ3JpZF9hY2Nlc3MkbGlzYV9jbHVzdGVyWw0KICB6ID4gMCAmIHpfbGFnID4gMCAmIGdyaWRfYWNjZXNzJGxpc2FfcCA8PSAwLjA1DQpdIDwtICJIaWdo4oCTSGlnaCINCg0KZ3JpZF9hY2Nlc3MkbGlzYV9jbHVzdGVyWw0KICB6IDwgMCAmIHpfbGFnIDwgMCAmIGdyaWRfYWNjZXNzJGxpc2FfcCA8PSAwLjA1DQpdIDwtICJMb3figJNMb3ciDQoNCmdyaWRfYWNjZXNzJGxpc2FfY2x1c3RlclsNCiAgeiA+IDAgJiB6X2xhZyA8IDAgJiBncmlkX2FjY2VzcyRsaXNhX3AgPD0gMC4wNQ0KXSA8LSAiSGlnaOKAk0xvdyINCg0KZ3JpZF9hY2Nlc3MkbGlzYV9jbHVzdGVyWw0KICB6IDwgMCAmIHpfbGFnID4gMCAmIGdyaWRfYWNjZXNzJGxpc2FfcCA8PSAwLjA1DQpdIDwtICJMb3figJNIaWdoIg0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeSh0bWFwKQ0KDQp0bV9zaGFwZShncmlkX2FjY2VzcykgKw0KICB0bV9wb2x5Z29ucygNCiAgICAibGlzYV9jbHVzdGVyIiwNCiAgICBwYWxldHRlID0gYygNCiAgICAgICJIaWdo4oCTSGlnaCIgPSAicmVkIiwNCiAgICAgICJMb3figJNMb3ciID0gImJsdWUiLA0KICAgICAgIkhpZ2jigJNMb3ciID0gInBpbmsiLA0KICAgICAgIkxvd+KAk0hpZ2giID0gImxpZ2h0Ymx1ZSIsDQogICAgICAiTm90IHNpZ25pZmljYW50IiA9ICJncmV5ODAiDQogICAgKSwNCiAgICB0aXRsZSA9ICJMSVNBIENsdXN0ZXJzIChwIOKJpCAwLjA1KSINCiAgKSArDQogIHRtX2xheW91dCgNCiAgICBmcmFtZSA9IEZBTFNFLA0KICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRQ0KICAgICApDQpgYGANCg0KYGBge3J9DQp0bV9zaGFwZShncmlkX2FjY2VzcykgKw0KICB0bV9wb2x5Z29ucygNCiAgICAiYWNjZXNzaWJpbGl0eV9pbmRleF8wMSIsDQogIHN0eWxlID0gImZpeGVkIiwNCiAgYnJlYWtzID0gYygwLCAwLjIsIDAuNCwgMC42LCAwLjgsIDEpLA0KICBwYWxldHRlID0gInZpcmlkaXMiLA0KICB0aXRsZSA9ICJBY2Nlc3NpYmlsaXR5IEluZGV4Ig0KKQ0KYGBgDQoNCg==