# 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==