This file demonstrates that the kinds of locations that are imputed are different from the true locations, in terms of things like population, distance from roads, ruggedness, etc.

rm(list=ls()); gc()
# !diagnostics off
library(MeasuringLandscape)
library(tidyverse)
dir_figures <- glue::glue(getwd(), "/../paper/figures/")
gc()
knitr::opts_knit$set(progress = TRUE, verbose = TRUE)
knitr::opts_chunk$set(fig.width=12, fig.height=8,  warning=FALSE, message=FALSE, cache=TRUE)
options(width = 160)
#Load Events
events_sf <- readRDS(system.file("extdata", "events_sf.Rdata", package = "MeasuringLandscape")) 
events_sf_text_coord_unique <- plyr::ddply(events_sf[,c('location_text','name_clean','name_cleaner','document_district_clean','map_coordinate_clean_latitude','map_coordinate_clean_longitude')],
                                     "location_text", transform,
      map_coordinate_has =sum(!is.na(map_coordinate_clean_latitude))
      )
#Reload from scratch each time in case we subset sometehing weirdly
georef_all_dt <- readRDS(system.file("extdata", "georef_all_dt_recomendations.Rds", package = "MeasuringLandscape")) 
table(events_sf$name_cleaner %in% georef_all_dt$name_cleaner) #All events are in here

 TRUE 
10469 
table(events_sf$name_cleaner %in% georef_all_dt$name_cleaner[!is.na(georef_all_dt$georef_b)]) #7,742 events with at least one gazeteer suggestion

FALSE  TRUE 
 2527  7942 
#Exclude all distance = 0 obs, those are self matches
georef_all_dt <- subset(georef_all_dt, 
                        !is.na(name_cleaner) & # must have a name
                        (is.na(distance_km) | distance_km!=0)  ) #Can be either missing or not zero. Only thing we drop is zero because that's a self match

Create a subset just for those events that have both original coords and a potential match

#Subset to make sure both sides have lat/long
georef_all_dt_covariates <- subset(georef_all_dt, !is.na(X1) & !is.na(X2)) ; dim(georef_all_dt_covariates)
[1] 331127     24
#Create an events dataset for merging on covariates
georef_all_dt_covariates_events <- georef_all_dt_covariates[!duplicated(event_hash)]
georef_all_dt_covariates_events_sf <- georef_all_dt_covariates_events  %>% data.frame() %>% sf::st_as_sf(coords = c("X1","Y1"),  crs = 4326, agr = "constant", remove=F, na.fail =T)
georef_all_dt_covariates_events_sf$imputed <- 0
#Create a gaz dataset for mering on covarates
georef_all_dt_covariates_gaz_sf <- georef_all_dt_covariates[,distance_km_min:=min(distance_km, na.rm=T),
                                                            by=list(event_hash, source_dataset)]
georef_all_dt_covariates_gaz_sf <- georef_all_dt_covariates_gaz_sf[distance_km==distance_km_min]
georef_all_dt_covariates_gaz_sf <- georef_all_dt_covariates_gaz_sf[,head(.SD, 1), by=list(event_hash, source_dataset)] %>% 
                                  data.frame() %>% sf::st_as_sf(coords = c("X2","Y2"),  crs = 4326, agr = "constant", remove=F, na.fail =T)
georef_all_dt_covariates_gaz_sf$imputed <- 1

Load all of the spatial files for the covariates

#covariate_list <- readRDS( '/home/rexdouglass/Dropbox (rex)/Kenya Article Drafts/MeasuringLandscapeCivilWar/inst/extdata/covariate_list.Rds' )
covariate_list <-  MeasuringLandscape:::prep_covariates()
sapply(covariate_list, FUN=function(q) class(q)[1])
          raster_rain        pop_raster_roi     forest_raster_roi ruggedness_raster_roi     roads_distance_to 
        "RasterLayer"         "RasterLayer"         "RasterLayer"         "RasterLayer"         "RasterLayer" 

Extract the values of covariates found at each location and imputed location

#georef_all_dt_covariates_events_sf$district <- new_over(georef_all_dt_covariates_events_sf , covariate_list[[1]]  , 'name' )
#georef_all_dt_covariates_events_sf$cadastral <- new_over(georef_all_dt_covariates_events_sf , covariate_list[[2]]  , 'name' )
#georef_all_dt_covariates_events_sf$language <- new_over(georef_all_dt_covariates_events_sf , covariate_list[[3]]  , 'LANGUAGE' )
#georef_all_dt_covariates_events_sf$tribe <- new_over(georef_all_dt_covariates_events_sf , covariate_list[[4]]  , 'Tribe' )
georef_all_dt_covariates_events_sf$rain <- MeasuringLandscape:::new_over(georef_all_dt_covariates_events_sf ,
                                                    covariate_list[['raster_rain']]  , 'Tribe' )
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
georef_all_dt_covariates_events_sf$population <- MeasuringLandscape:::new_over(georef_all_dt_covariates_events_sf ,
                                                          covariate_list[['pop_raster_roi']]  , '' )
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
georef_all_dt_covariates_events_sf$treecover <- MeasuringLandscape:::new_over(georef_all_dt_covariates_events_sf ,
                                                         covariate_list[['forest_raster_roi']]  , '' )
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
georef_all_dt_covariates_events_sf$ruggedness <- MeasuringLandscape:::new_over(georef_all_dt_covariates_events_sf ,
                                                          covariate_list[['ruggedness_raster_roi']]  , '' )
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
georef_all_dt_covariates_events_sf$roads_distance <- MeasuringLandscape:::new_over(georef_all_dt_covariates_events_sf ,
                                                              covariate_list[['roads_distance_to']]  , '' )
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
#georef_all_dt_covariates_events_sf$landuse <- new_over(georef_all_dt_covariates_events_sf , covariate_list[[9]]  , 'LANDUSE' )
#georef_all_dt_covariates_gaz_sf$district <- new_over(georef_all_dt_covariates_gaz_sf , covariate_list[[1]]  , 'name' )
#georef_all_dt_covariates_gaz_sf$cadastral <- new_over(georef_all_dt_covariates_gaz_sf , covariate_list[[2]]  , 'name' )
#georef_all_dt_covariates_gaz_sf$language <- new_over(georef_all_dt_covariates_gaz_sf , covariate_list[[3]]  , 'LANGUAGE' )
#georef_all_dt_covariates_gaz_sf$tribe <- new_over(georef_all_dt_covariates_gaz_sf , covariate_list[[4]]  , 'Tribe' )
#georef_all_dt_covariates_gaz_sf$rain <- new_over(georef_all_dt_covariates_gaz_sf , covariate_list[[5]]  , '' )
#georef_all_dt_covariates_gaz_sf$population <- new_over(georef_all_dt_covariates_gaz_sf , covariate_list[[6]]  , '' )
#georef_all_dt_covariates_gaz_sf$treecover <- new_over(georef_all_dt_covariates_gaz_sf , covariate_list[[7]]  , '' )
#georef_all_dt_covariates_gaz_sf$ruggedness <- new_over(georef_all_dt_covariates_gaz_sf , covariate_list[[8]]  , '' )
#georef_all_dt_covariates_gaz_sf$roads_distance <- new_over(georef_all_dt_covariates_gaz_sf , covariate_list[[9]]  , '' )
#georef_all_dt_covariates_gaz_sf$landuse <- new_over(georef_all_dt_covariates_gaz_sf , covariate_list[[9]]  , 'LANDUSE' )

Plot the differences of points at real locations versus their imputed counterparts

sentence_case <- function(x) stringr::str_to_sentence(tolower(gsub("_"," ",x)))
#Make that bias in the coef plot
data.table::setkey(georef_all_dt, "rule_ensemble") #sort by ensemble score, pick the best option for each source
georef_all_dt_source <- georef_all_dt[,.SD[1], by=list(event_hash,
                                                       source_dataset) ]
temp <- as.data.frame(georef_all_dt_covariates_events_sf)[,c('source_dataset',
                                                          'population',
                                                          'treecover',
                                                          'ruggedness',
                                                          'roads_distance',
                                                          'rain')
                                                         ] %>% 
                                                           group_by(source_dataset) %>% 
                                                          summarise_all(funs(mean, .args =list(na.rm=T)) )
#I don't think we want to scale this, I think we want to do percentages
#temp[,2:6] <- lapply(temp[,2:6], scale)
#temp[,2:6] <- temp[,2:6] - temp[rep(2,nrow(temp)),2:6] #This demeans each
test <- as.numeric(unlist(as.vector(data.frame(temp[2,]))))
NAs introduced by coercion
temp <- as.data.frame(temp)
temp[,2] <- temp[,2] / rep(test[2],10) #This demeans each
temp[,3] <- temp[,3] / rep(test[3],10)  #This demeans each
temp[,4] <- temp[,4] / rep(test[4],10)  #This demeans each
temp[,5] <- temp[,5] / rep(test[5],10)  #This demeans each
temp[,6] <- temp[,6] / rep(test[6],10)  #This demeans each
temp <- temp %>% tidyr::gather(variable, value, -source_dataset)
p9 <-  temp %>% 
       mutate(source_dataset=sentence_case(source_dataset),
              variable=sentence_case(variable)
      ) %>%
       ggplot(aes(x = value,
                 y = as.factor(sub("_","",source_dataset)),
                 shape=as.factor(sub("_","",source_dataset)))) + 
                 geom_point() + 
                 facet_grid(.~variable, scales="free") + 
                 geom_vline(xintercept=1) + ylab(sentence_case("Source Dataset")) +
                 xlab(sentence_case("Ratio of Mean Value at Imputed Location Relative to True Location")) +
                 scale_shape_manual(values=1:15) + theme_bw() + theme(legend.position="none") 
p9

ggsave(
  filename = glue::glue(dir_figures, "p_bias_in_covariates_by_source.pdf"),
  plot = p9, width = 16, height = 3
)
LS0tCnRpdGxlOiAiMTAgQmlhcyBvbiBjb3ZhcmlhdGVzIgphdXRob3I6ICJSZXggVy4gRG91Z2xhc3MgYW5kIEtyaXN0ZW4gSGFya25lc3MiCmRhdGU6ICJNYXJjaCA5LCAyMDE4IgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KPHN0eWxlPgogICAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgICAgIG1heC13aWR0aDogMTAwJTsKICAgIH0KPC9zdHlsZT4KCiAKVGhpcyBmaWxlIGRlbW9uc3RyYXRlcyB0aGF0IHRoZSBraW5kcyBvZiBsb2NhdGlvbnMgdGhhdCBhcmUgaW1wdXRlZCBhcmUgZGlmZmVyZW50IGZyb20gdGhlIHRydWUgbG9jYXRpb25zLCBpbiB0ZXJtcyBvZiB0aGluZ3MgbGlrZSBwb3B1bGF0aW9uLCBkaXN0YW5jZSBmcm9tIHJvYWRzLCBydWdnZWRuZXNzLCBldGMuCgpgYGB7ciAsIHJlc3VsdHM9J2hpZGUnLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpybShsaXN0PWxzKCkpOyBnYygpCiMgIWRpYWdub3N0aWNzIG9mZgpsaWJyYXJ5KE1lYXN1cmluZ0xhbmRzY2FwZSkKbGlicmFyeSh0aWR5dmVyc2UpCgpkaXJfZmlndXJlcyA8LSBnbHVlOjpnbHVlKGdldHdkKCksICIvLi4vcGFwZXIvZmlndXJlcy8iKQoKZ2MoKQoKa25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3MgPSBUUlVFLCB2ZXJib3NlID0gVFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD04LCAgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9VFJVRSkKb3B0aW9ucyh3aWR0aCA9IDE2MCkKCmBgYAoKCmBgYHtyfQoKI0xvYWQgRXZlbnRzCmV2ZW50c19zZiA8LSByZWFkUkRTKHN5c3RlbS5maWxlKCJleHRkYXRhIiwgImV2ZW50c19zZi5SZGF0YSIsIHBhY2thZ2UgPSAiTWVhc3VyaW5nTGFuZHNjYXBlIikpIAoKZXZlbnRzX3NmX3RleHRfY29vcmRfdW5pcXVlIDwtIHBseXI6OmRkcGx5KGV2ZW50c19zZlssYygnbG9jYXRpb25fdGV4dCcsJ25hbWVfY2xlYW4nLCduYW1lX2NsZWFuZXInLCdkb2N1bWVudF9kaXN0cmljdF9jbGVhbicsJ21hcF9jb29yZGluYXRlX2NsZWFuX2xhdGl0dWRlJywnbWFwX2Nvb3JkaW5hdGVfY2xlYW5fbG9uZ2l0dWRlJyldLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImxvY2F0aW9uX3RleHQiLCB0cmFuc2Zvcm0sCiAgICAgIG1hcF9jb29yZGluYXRlX2hhcyA9c3VtKCFpcy5uYShtYXBfY29vcmRpbmF0ZV9jbGVhbl9sYXRpdHVkZSkpCiAgICAgICkKCmBgYAoKCmBgYHtyfQojUmVsb2FkIGZyb20gc2NyYXRjaCBlYWNoIHRpbWUgaW4gY2FzZSB3ZSBzdWJzZXQgc29tZXRlaGluZyB3ZWlyZGx5Cmdlb3JlZl9hbGxfZHQgPC0gcmVhZFJEUyhzeXN0ZW0uZmlsZSgiZXh0ZGF0YSIsICJnZW9yZWZfYWxsX2R0X3JlY29tZW5kYXRpb25zLlJkcyIsIHBhY2thZ2UgPSAiTWVhc3VyaW5nTGFuZHNjYXBlIikpIAoKdGFibGUoZXZlbnRzX3NmJG5hbWVfY2xlYW5lciAlaW4lIGdlb3JlZl9hbGxfZHQkbmFtZV9jbGVhbmVyKSAjQWxsIGV2ZW50cyBhcmUgaW4gaGVyZQp0YWJsZShldmVudHNfc2YkbmFtZV9jbGVhbmVyICVpbiUgZ2VvcmVmX2FsbF9kdCRuYW1lX2NsZWFuZXJbIWlzLm5hKGdlb3JlZl9hbGxfZHQkZ2VvcmVmX2IpXSkgIzcsNzQyIGV2ZW50cyB3aXRoIGF0IGxlYXN0IG9uZSBnYXpldGVlciBzdWdnZXN0aW9uCgojRXhjbHVkZSBhbGwgZGlzdGFuY2UgPSAwIG9icywgdGhvc2UgYXJlIHNlbGYgbWF0Y2hlcwpnZW9yZWZfYWxsX2R0IDwtIHN1YnNldChnZW9yZWZfYWxsX2R0LCAKICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKG5hbWVfY2xlYW5lcikgJiAjIG11c3QgaGF2ZSBhIG5hbWUKICAgICAgICAgICAgICAgICAgICAgICAgKGlzLm5hKGRpc3RhbmNlX2ttKSB8IGRpc3RhbmNlX2ttIT0wKSAgKSAjQ2FuIGJlIGVpdGhlciBtaXNzaW5nIG9yIG5vdCB6ZXJvLiBPbmx5IHRoaW5nIHdlIGRyb3AgaXMgemVybyBiZWNhdXNlIHRoYXQncyBhIHNlbGYgbWF0Y2gKYGBgCgoKQ3JlYXRlIGEgc3Vic2V0IGp1c3QgZm9yIHRob3NlIGV2ZW50cyB0aGF0IGhhdmUgYm90aCBvcmlnaW5hbCBjb29yZHMgYW5kIGEgcG90ZW50aWFsIG1hdGNoCgpgYGB7cn0KCiNTdWJzZXQgdG8gbWFrZSBzdXJlIGJvdGggc2lkZXMgaGF2ZSBsYXQvbG9uZwpnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXMgPC0gc3Vic2V0KGdlb3JlZl9hbGxfZHQsICFpcy5uYShYMSkgJiAhaXMubmEoWDIpKSA7IGRpbShnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXMpCgojQ3JlYXRlIGFuIGV2ZW50cyBkYXRhc2V0IGZvciBtZXJnaW5nIG9uIGNvdmFyaWF0ZXMKZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50cyA8LSBnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNbIWR1cGxpY2F0ZWQoZXZlbnRfaGFzaCldCmdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19ldmVudHNfc2YgPC0gZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50cyAgJT4lIGRhdGEuZnJhbWUoKSAlPiUgc2Y6OnN0X2FzX3NmKGNvb3JkcyA9IGMoIlgxIiwiWTEiKSwgIGNycyA9IDQzMjYsIGFnciA9ICJjb25zdGFudCIsIHJlbW92ZT1GLCBuYS5mYWlsID1UKQpnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZXZlbnRzX3NmJGltcHV0ZWQgPC0gMAoKI0NyZWF0ZSBhIGdheiBkYXRhc2V0IGZvciBtZXJpbmcgb24gY292YXJhdGVzCmdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YgPC0gZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzWyxkaXN0YW5jZV9rbV9taW46PW1pbihkaXN0YW5jZV9rbSwgbmEucm09VCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5PWxpc3QoZXZlbnRfaGFzaCwgc291cmNlX2RhdGFzZXQpXQpnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZ2F6X3NmIDwtIGdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2ZbZGlzdGFuY2Vfa209PWRpc3RhbmNlX2ttX21pbl0KCmdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YgPC0gZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2dhel9zZlssaGVhZCguU0QsIDEpLCBieT1saXN0KGV2ZW50X2hhc2gsIHNvdXJjZV9kYXRhc2V0KV0gJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZSgpICU+JSBzZjo6c3RfYXNfc2YoY29vcmRzID0gYygiWDIiLCJZMiIpLCAgY3JzID0gNDMyNiwgYWdyID0gImNvbnN0YW50IiwgcmVtb3ZlPUYsIG5hLmZhaWwgPVQpCmdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YkaW1wdXRlZCA8LSAxCgpgYGAKCgoKCiMgTG9hZCBhbGwgb2YgdGhlIHNwYXRpYWwgZmlsZXMgZm9yIHRoZSBjb3ZhcmlhdGVzCgpgYGB7cn0KCgojY292YXJpYXRlX2xpc3QgPC0gcmVhZFJEUyggJy9ob21lL3JleGRvdWdsYXNzL0Ryb3Bib3ggKHJleCkvS2VueWEgQXJ0aWNsZSBEcmFmdHMvTWVhc3VyaW5nTGFuZHNjYXBlQ2l2aWxXYXIvaW5zdC9leHRkYXRhL2NvdmFyaWF0ZV9saXN0LlJkcycgKQpjb3ZhcmlhdGVfbGlzdCA8LSAgTWVhc3VyaW5nTGFuZHNjYXBlOjo6cHJlcF9jb3ZhcmlhdGVzKCkKCnNhcHBseShjb3ZhcmlhdGVfbGlzdCwgRlVOPWZ1bmN0aW9uKHEpIGNsYXNzKHEpWzFdKQoKCmBgYAojIEV4dHJhY3QgdGhlIHZhbHVlcyBvZiBjb3ZhcmlhdGVzIGZvdW5kIGF0IGVhY2ggbG9jYXRpb24gYW5kIGltcHV0ZWQgbG9jYXRpb24KCmBgYHtyfQoKCgojZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiRkaXN0cmljdCA8LSBuZXdfb3ZlcihnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZXZlbnRzX3NmICwgY292YXJpYXRlX2xpc3RbWzFdXSAgLCAnbmFtZScgKQojZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiRjYWRhc3RyYWwgPC0gbmV3X292ZXIoZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiAsIGNvdmFyaWF0ZV9saXN0W1syXV0gICwgJ25hbWUnICkKI2dlb3JlZl9hbGxfZHRfY292YXJpYXRlc19ldmVudHNfc2YkbGFuZ3VhZ2UgPC0gbmV3X292ZXIoZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiAsIGNvdmFyaWF0ZV9saXN0W1szXV0gICwgJ0xBTkdVQUdFJyApCiNnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZXZlbnRzX3NmJHRyaWJlIDwtIG5ld19vdmVyKGdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19ldmVudHNfc2YgLCBjb3ZhcmlhdGVfbGlzdFtbNF1dICAsICdUcmliZScgKQpnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZXZlbnRzX3NmJHJhaW4gPC0gTWVhc3VyaW5nTGFuZHNjYXBlOjo6bmV3X292ZXIoZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3ZhcmlhdGVfbGlzdFtbJ3Jhc3Rlcl9yYWluJ11dICAsICdUcmliZScgKQpnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZXZlbnRzX3NmJHBvcHVsYXRpb24gPC0gTWVhc3VyaW5nTGFuZHNjYXBlOjo6bmV3X292ZXIoZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3ZhcmlhdGVfbGlzdFtbJ3BvcF9yYXN0ZXJfcm9pJ11dICAsICcnICkKZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiR0cmVlY292ZXIgPC0gTWVhc3VyaW5nTGFuZHNjYXBlOjo6bmV3X292ZXIoZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZV9saXN0W1snZm9yZXN0X3Jhc3Rlcl9yb2knXV0gICwgJycgKQpnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZXZlbnRzX3NmJHJ1Z2dlZG5lc3MgPC0gTWVhc3VyaW5nTGFuZHNjYXBlOjo6bmV3X292ZXIoZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3ZhcmlhdGVfbGlzdFtbJ3J1Z2dlZG5lc3NfcmFzdGVyX3JvaSddXSAgLCAnJyApCmdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19ldmVudHNfc2Ykcm9hZHNfZGlzdGFuY2UgPC0gTWVhc3VyaW5nTGFuZHNjYXBlOjo6bmV3X292ZXIoZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292YXJpYXRlX2xpc3RbWydyb2Fkc19kaXN0YW5jZV90byddXSAgLCAnJyApCgojZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2V2ZW50c19zZiRsYW5kdXNlIDwtIG5ld19vdmVyKGdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19ldmVudHNfc2YgLCBjb3ZhcmlhdGVfbGlzdFtbOV1dICAsICdMQU5EVVNFJyApCiNnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZ2F6X3NmJGRpc3RyaWN0IDwtIG5ld19vdmVyKGdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YgLCBjb3ZhcmlhdGVfbGlzdFtbMV1dICAsICduYW1lJyApCiNnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZ2F6X3NmJGNhZGFzdHJhbCA8LSBuZXdfb3ZlcihnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZ2F6X3NmICwgY292YXJpYXRlX2xpc3RbWzJdXSAgLCAnbmFtZScgKQojZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2dhel9zZiRsYW5ndWFnZSA8LSBuZXdfb3ZlcihnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZ2F6X3NmICwgY292YXJpYXRlX2xpc3RbWzNdXSAgLCAnTEFOR1VBR0UnICkKI2dlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YkdHJpYmUgPC0gbmV3X292ZXIoZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2dhel9zZiAsIGNvdmFyaWF0ZV9saXN0W1s0XV0gICwgJ1RyaWJlJyApCiNnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZ2F6X3NmJHJhaW4gPC0gbmV3X292ZXIoZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2dhel9zZiAsIGNvdmFyaWF0ZV9saXN0W1s1XV0gICwgJycgKQojZ2VvcmVmX2FsbF9kdF9jb3ZhcmlhdGVzX2dhel9zZiRwb3B1bGF0aW9uIDwtIG5ld19vdmVyKGdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YgLCBjb3ZhcmlhdGVfbGlzdFtbNl1dICAsICcnICkKI2dlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YkdHJlZWNvdmVyIDwtIG5ld19vdmVyKGdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YgLCBjb3ZhcmlhdGVfbGlzdFtbN11dICAsICcnICkKI2dlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YkcnVnZ2VkbmVzcyA8LSBuZXdfb3ZlcihnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZ2F6X3NmICwgY292YXJpYXRlX2xpc3RbWzhdXSAgLCAnJyApCiNnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZ2F6X3NmJHJvYWRzX2Rpc3RhbmNlIDwtIG5ld19vdmVyKGdlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YgLCBjb3ZhcmlhdGVfbGlzdFtbOV1dICAsICcnICkKI2dlb3JlZl9hbGxfZHRfY292YXJpYXRlc19nYXpfc2YkbGFuZHVzZSA8LSBuZXdfb3ZlcihnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZ2F6X3NmICwgY292YXJpYXRlX2xpc3RbWzldXSAgLCAnTEFORFVTRScgKQoKYGBgCgojIFBsb3QgdGhlIGRpZmZlcmVuY2VzIG9mIHBvaW50cyBhdCByZWFsIGxvY2F0aW9ucyB2ZXJzdXMgdGhlaXIgaW1wdXRlZCBjb3VudGVycGFydHMKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9OH0KCnNlbnRlbmNlX2Nhc2UgPC0gZnVuY3Rpb24oeCkgc3RyaW5ncjo6c3RyX3RvX3NlbnRlbmNlKHRvbG93ZXIoZ3N1YigiXyIsIiAiLHgpKSkKCgojTWFrZSB0aGF0IGJpYXMgaW4gdGhlIGNvZWYgcGxvdApkYXRhLnRhYmxlOjpzZXRrZXkoZ2VvcmVmX2FsbF9kdCwgInJ1bGVfZW5zZW1ibGUiKSAjc29ydCBieSBlbnNlbWJsZSBzY29yZSwgcGljayB0aGUgYmVzdCBvcHRpb24gZm9yIGVhY2ggc291cmNlCmdlb3JlZl9hbGxfZHRfc291cmNlIDwtIGdlb3JlZl9hbGxfZHRbLC5TRFsxXSwgYnk9bGlzdChldmVudF9oYXNoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlX2RhdGFzZXQpIF0KCnRlbXAgPC0gYXMuZGF0YS5mcmFtZShnZW9yZWZfYWxsX2R0X2NvdmFyaWF0ZXNfZXZlbnRzX3NmKVssYygnc291cmNlX2RhdGFzZXQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3BvcHVsYXRpb24nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3RyZWVjb3ZlcicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAncnVnZ2VkbmVzcycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAncm9hZHNfZGlzdGFuY2UnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3JhaW4nKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShzb3VyY2VfZGF0YXNldCkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlX2FsbChmdW5zKG1lYW4sIC5hcmdzID1saXN0KG5hLnJtPVQpKSApCgojSSBkb24ndCB0aGluayB3ZSB3YW50IHRvIHNjYWxlIHRoaXMsIEkgdGhpbmsgd2Ugd2FudCB0byBkbyBwZXJjZW50YWdlcwojdGVtcFssMjo2XSA8LSBsYXBwbHkodGVtcFssMjo2XSwgc2NhbGUpCgojdGVtcFssMjo2XSA8LSB0ZW1wWywyOjZdIC0gdGVtcFtyZXAoMixucm93KHRlbXApKSwyOjZdICNUaGlzIGRlbWVhbnMgZWFjaAp0ZXN0IDwtIGFzLm51bWVyaWModW5saXN0KGFzLnZlY3RvcihkYXRhLmZyYW1lKHRlbXBbMixdKSkpKQp0ZW1wIDwtIGFzLmRhdGEuZnJhbWUodGVtcCkKdGVtcFssMl0gPC0gdGVtcFssMl0gLyByZXAodGVzdFsyXSwxMCkgI1RoaXMgZGVtZWFucyBlYWNoCnRlbXBbLDNdIDwtIHRlbXBbLDNdIC8gcmVwKHRlc3RbM10sMTApICAjVGhpcyBkZW1lYW5zIGVhY2gKdGVtcFssNF0gPC0gdGVtcFssNF0gLyByZXAodGVzdFs0XSwxMCkgICNUaGlzIGRlbWVhbnMgZWFjaAp0ZW1wWyw1XSA8LSB0ZW1wWyw1XSAvIHJlcCh0ZXN0WzVdLDEwKSAgI1RoaXMgZGVtZWFucyBlYWNoCnRlbXBbLDZdIDwtIHRlbXBbLDZdIC8gcmVwKHRlc3RbNl0sMTApICAjVGhpcyBkZW1lYW5zIGVhY2gKCnRlbXAgPC0gdGVtcCAlPiUgdGlkeXI6OmdhdGhlcih2YXJpYWJsZSwgdmFsdWUsIC1zb3VyY2VfZGF0YXNldCkKCnA5IDwtICB0ZW1wICU+JSAKICAgICAgIG11dGF0ZShzb3VyY2VfZGF0YXNldD1zZW50ZW5jZV9jYXNlKHNvdXJjZV9kYXRhc2V0KSwKICAgICAgICAgICAgICB2YXJpYWJsZT1zZW50ZW5jZV9jYXNlKHZhcmlhYmxlKQogICAgICApICU+JQogICAgICAgZ2dwbG90KGFlcyh4ID0gdmFsdWUsCiAgICAgICAgICAgICAgICAgeSA9IGFzLmZhY3RvcihzdWIoIl8iLCIiLHNvdXJjZV9kYXRhc2V0KSksCiAgICAgICAgICAgICAgICAgc2hhcGU9YXMuZmFjdG9yKHN1YigiXyIsIiIsc291cmNlX2RhdGFzZXQpKSkpICsgCiAgICAgICAgICAgICAgICAgZ2VvbV9wb2ludCgpICsgCiAgICAgICAgICAgICAgICAgZmFjZXRfZ3JpZCgufnZhcmlhYmxlLCBzY2FsZXM9ImZyZWUiKSArIAogICAgICAgICAgICAgICAgIGdlb21fdmxpbmUoeGludGVyY2VwdD0xKSArIHlsYWIoc2VudGVuY2VfY2FzZSgiU291cmNlIERhdGFzZXQiKSkgKwogICAgICAgICAgICAgICAgIHhsYWIoc2VudGVuY2VfY2FzZSgiUmF0aW8gb2YgTWVhbiBWYWx1ZSBhdCBJbXB1dGVkIExvY2F0aW9uIFJlbGF0aXZlIHRvIFRydWUgTG9jYXRpb24iKSkgKwogICAgICAgICAgICAgICAgIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9MToxNSkgKyB0aGVtZV9idygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgCnA5Cmdnc2F2ZSgKICBmaWxlbmFtZSA9IGdsdWU6OmdsdWUoZGlyX2ZpZ3VyZXMsICJwX2JpYXNfaW5fY292YXJpYXRlc19ieV9zb3VyY2UucGRmIiksCiAgcGxvdCA9IHA5LCB3aWR0aCA9IDE2LCBoZWlnaHQgPSAzCikKCmBgYAoK