This project was created in order to demonstrate the data visualization and interactive mapping capabilities of R. For this project I will be using the November 2018 Woolsey Fire as a case study to demonstrate how R can help in spatial analysis of fire data as well as in displaying that data to a broader audience. I chose this case study since it can benefit from spatial layering of different data formats and multiple levels of analysis can be done to it.

I will be using data aggregatd from multiple sources, all data sources referenced in this project are free to access for anyone interested in duplicating this project or applying its methods towards a similar project. A majority of the documentation will be written in the code chunks to allow for better step-by-step explanation.

This code chunk shows all the packages and libraries that I used for this project.

##################Packages and Libraries##################
install.packages("magick")
library(magick)
library(devtools)
install_github("mtennekes/tmaptools")
install_github("mtennekes/tmap")
#install.packages("tmap")
library(tmap)
library(sp)
library(raster)
library(RColorBrewer)
library(classInt)
install.packages('rasterVis')
library(rasterVis)
install.packages('tigris')
library(tigris)
install.packages('rgdal', type = "source", configure.args=c('--with-proj-include=/Library/Frameworks/PROJ.framework/Headers', '--with-proj-lib=/Library/Frameworks/PROJ.framework/unix/lib'))
library(rgdal)
#install.packages("tmaptools")
install.packages("sf")
install.packages("leaflet")
library(tmaptools)
library("sf")
library(leaflet)
library(tigris)
install.packages('devtools')
devtools::install_github('thomasp85/gganimate')
library(ggplot2)
library(gganimate)
library(ggplot2)
library(ggmap)
library(maps)
library(ggthemes)
install.packages("plotly")
library(plotly)

Interactive tmap() map: For this map, I used the tmap package to create an interactive map that layers the Digital Elevation Model, median home value, and fire incidence data on one interactive map. The layer toggle also allows the user to select which layers to display in order to customize the map to only show information that the end user wants to see.

##################Add Fire Data from NASA FIRMS##################
#Create download requests here:https://firms.modaps.eosdis.nasa.gov/download/

#import fire points data
dir("/Users/krgr.df/Desktop/GEOG208/Final Assignment/Fire Data/DL_FIRE_V1_33042(SHP8-24)")
Fire.Points <- readOGR("/Users/krgr.df/Desktop/GEOG208/Final Assignment/Fire Data/DL_FIRE_V1_33042(SHP8-24)", "fire_nrt_V1_33042")

##################Merge and Reclassify Raster##################
#raster data downloaded from from glovis: https://glovis.usgs.gov/app

#import and merge two raster files
DEM_4 <- raster("/Users/krgr.df/Desktop/GEOG208/Final Assignment/DEMs/n34_w120_3arc_v2.tif")
DEM_5 <- raster("/Users/krgr.df/Desktop/GEOG208/Final Assignment/DEMs/n34_w119_3arc_v2.tif")
mosaic(DEM_4, DEM_5, fun = mean, tolerance=0.05, filename="/Users/krgr.df/Desktop/GEOG208/Final Assignment/DEMs/Mosaic_test_1.tif", overwrite=TRUE) 
mosaic_test <- raster("/Users/krgr.df/Desktop/GEOG208/Final Assignment/DEMs/Mosaic_test_1.tif", overwrite=TRUE)

#reclassify raster to set values below 500 to NA, this removes them from display
DEM <- calc(mosaic_test, fun=function(x){ x[x < 500] <- NA; return(x)} )

##################Add Demographic Data##################
#pull ventura & LA county boundary map from library(tigris)
Ven_bound <- tracts(state = "CA", county = "Ventura", cb = TRUE)

LA_bound <- tracts(state = "CA", county = "Los Angeles", cb = TRUE)

#import csv file with median home value data (Ventura)
HW4 <- file.path ("/Users/krgr.df/Desktop/GEOG208/Assignment 4/ventura_median_val.csv")
median.val <- read.csv(HW4, stringsAsFactors = FALSE)
median.val$median.value <- as.numeric(median.val$median.value)
median.val$id2 <- as.character(median.val$id2)

#import csv file with median home value data (Los Angeles)
HW4.2 <- file.path ("/Users/krgr.df/Desktop/GEOG208/Assignment 4/LA_median_val.csv")
LA.median.val <- read.csv(HW4.2, stringsAsFactors = FALSE)
LA.median.val$median.val <- as.numeric(LA.median.val$median.val)
LA.median.val$id2 <- as.character(LA.median.val$id2)

#merge census tract boundaries with median home values (Ventura)
Ventura.Stats <- merge(Ven_bound, median.val, by.x = "AFFGEOID", by.y = "id")

#merge census tract boundaries with median home values (Los Angeles)
LA.Stats <- merge(LA_bound, LA.median.val, by.x = "AFFGEOID", by.y = "id")

##################Create Interactive tmap()##################
#set tmap to interactive viewing mode and set theme to 'cobalt'
tmap_mode("view")
tmap_style("cobalt")

#allows toggling between static aka 'plot' and interactive aka 'view' modes
ttm() 

#the following lines of code adds layers into tmap and edits the appearance of the map
tmap_map <- tm_shape(Ventura.Stats)+
  tm_fill(col = "median.value", palette = "PuBu", title = "Ventura County Median Home Value", 
          style = "fixed",
          breaks = c(0, 250000, 500000, 750000, 1000000, Inf),
          textNA = "No Data", 
          colorNA = "gray",
          alpha = .7) +
  tm_borders(col = "white") +
  tm_layout(legend.title.size = 1,
            legend.text.size = 0.6,
            legend.text.color = "gray20",
            legend.bg.color = "white",
            legend.width = -1,
            legend.bg.alpha = 1)+
  tm_view(view.legend.position = c("right", "bottom")) +
  tm_shape(LA.Stats)+
  tm_fill(col = "median.val", palette = "YlGn", title = "LA County Median Home Value", 
          style = "fixed",
          breaks = c(0, 250000, 500000, 750000, 1000000, Inf),
          textNA = "No Data", 
          colorNA = "gray",
          alpha = .7) +
  tm_borders(col = "white") +
  tm_layout(legend.title.size = 1,
            legend.text.size = 0.6,
            legend.text.color = "gray20",
            legend.bg.color = "white",
            legend.width = -1,
            legend.bg.alpha = 1) +
  tm_view(view.legend.position = c("left", "bottom")) +
  tm_shape(Fire.Points) +
  tm_dots("BRIGHT_TI4", 
          alpha = 1,
          border.col = NA,
          title = "Fire Intensity",
          popup.vars = "ACQ_DATE",
          palette = "YlOrRd") +
  tm_view(view.legend.position = c("right", "top")) +
  tm_shape(DEM, unit = "mi") +
  tm_raster("layer", 
            midpoint = NA, 
            title = "DEM",
            legend.show = FALSE) +
  tmap_options(max.raster = c(plot = 2883601, view = 2883601)) +
  tm_scale_bar(size = 1, 
               text.color = NA,
               color.dark = "black", color.light = "white", 
               lwd = 1, 
               position = c("bottom", "left"))

tmap_map

I created a histogram of fire frequency over time in order to pinpoint which days had the highest number of fire incidents

##################Plot Histogram Data##################

#import NASA fire points .csv data
fire_csv <- read.csv("/Users/krgr.df/Desktop/GEOG208/Final Assignment/Fire Data/NASA VIIRs CSV/fire_nrt_V1_32986.csv")

#change acquired date column from numeric to date
fire_csv$acq_date <- as.Date(fire_csv$acq_date)

#plot a histogram of fire frequency over time
hist(fire_csv$acq_date, "days", 
     freq = TRUE,
     breaks = 15,
     xlab = "Date Acquired",
     col = "firebrick3",
     border = "orange"
     )

I also created an animated map that displays the distribution of fire instances over time during the extent of the Woolsey Fire.

##################Animated Map##################
#created using gganimate package from: https://github.com/thomasp85/gganimate

#change format of date column from numeric to date
fire_csv$acq_date <- as.Date(fire_csv$acq_date)
str(fire_csv)

#create animated map using gganimate
animated_map <- ggplot(fire_csv, (aes(longitude, latitude, color = bright_ti4))) +
  borders("county", ".*ventura",colour = "gray85", fill = "gray80", ) +
  theme_map() +
  borders("county", ".*los angeles",colour = "gray85", fill = "gray80", ) +
  theme_map() +
  geom_point(alpha = .5) +
  scale_color_gradient(low="yellow", high="red", name = "Brightness Value") + 
  labs(title = 'Date: {frame_time}', size = 3) +
  transition_time(acq_date) +
  enter_fade() + 
  ease_aes("linear")

animated_map

ANIMATED MAP HERE (open link in new tab): https://photos.google.com/share/AF1QipNZN2aIUorKUYKMkM5VbLYoWQUNbYvYlYubbeNgeh5SEIdfSBAkNcCuuEAu__RiHg/photo/AF1QipM8bCC5syWDq5n3_9v2GmFVQO7jzpSIIFAcZCIM?key=NDFycU16eExNSl81dUpRLXAwVEtWZmtFMkhuX3V3

A heatmap is useful in this case because the name fits perfectly with my case study (get it, “heat” “map” ok im done) and because its useful for seeing which areas had the highest concentration of fire incidents.

##################Heatmap##################
#created by using techniques from:
#http://trucvietle.me/r/tutorial/2017/01/18/spatial-heat-map-plotting-using-r.html

#import fire data in .csv format
fire_csv <- read.csv("/Users/krgr.df/Desktop/GEOG208/Final Assignment/Fire Data/NASA VIIRs CSV/fire_nrt_V1_32986.csv")

#set map extent by taking mean lat long of fire points (genius method created by Truc Viet)
mean.longitude <- mean(fire_csv$longitude)
mean.latitude <- mean(fire_csv$latitude)

#get Google basemap
if(!requireNamespace("devtools")) install.packages("devtools")
devtools::install_github("dkahle/ggmap", ref = "tidyup")
register_google(key = "AIzaSyDpOleZ5sm6jctsh7fHZ8vRKamcCW33nNM")
affected_area <- get_map(location = c(mean.longitude, mean.latitude), zoom = 9, scale = 2)
affected_area <- ggmap(affected_area, extent="device", legend="none")

#create heatmap, in-depth documentation from website linked above
heatmap1 <- affected_area + 
            stat_density2d(data=fire_csv,
                 aes(x=longitude, y=latitude, fill=..level.., alpha=..level..), 
                 geom="polygon") +
            scale_fill_gradientn(colours=(brewer.pal(7, "YlOrRd"))) +
            guides(size=FALSE, alpha = FALSE)
heatmap1

#transform static ggplot() heatmap to interactive map using ggplotly()
heatmaply <- ggplotly(heatmap1)
heatmaply

This final map is a GIF showing satellite imagery of the area before and after the fire, the fire points from the NASA dataset are also added to highlight which areas had a higher fire incident frequency.

#created by using magick package see:
#https://cran.r-project.org/web/packages/magick/vignettes/intro.html
#satellite imagery (Sentinel2) downloaded from Earth Explorer:
#https://earthexplorer.usgs.gov

#created by cycling through screenshotted images from QGIS
before_fire <- image_scale(image_read("/Users/krgr.df/Desktop/Screen Shot 2018-12-04 at 2.20.06 AM.png"), "x450")
before_points <- image_scale(image_read("/Users/krgr.df/Desktop/Screen Shot 2018-12-04 at 2.07.35 AM.png"), "x450")
with_points <- image_scale(image_read("/Users/krgr.df/Desktop/Screen Shot 2018-12-04 at 2.07.52 AM.png"), "x450")
frames <- image_morph(c( before_fire, with_points, before_points, before_points, before_points, before_fire), frames = 25)
image_animate(frames)

ANIMATED MAP HERE (open link in new tab): https://photos.google.com/share/AF1QipNZN2aIUorKUYKMkM5VbLYoWQUNbYvYlYubbeNgeh5SEIdfSBAkNcCuuEAu__RiHg/photo/AF1QipNkvlR-hjBYCTTb4qZYSz-cO5hbNM0GNOsES2rP?key=NDFycU16eExNSl81dUpRLXAwVEtWZmtFMkhuX3V3

Next Steps: For the next steps I plan on implementing other factors into the first interactive map such as wind strength and direction (especially the Santa Ana winds), infrastructure types, and vegetation/land use data.

LS0tCnRpdGxlOiAiR0VPRyAyMDggRmluYWw6IFdvb2xzZXkgRmlyZSIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIHRoZW1lOiBzcGFjZWxhYgotLS0KClRoaXMgcHJvamVjdCB3YXMgY3JlYXRlZCBpbiBvcmRlciB0byBkZW1vbnN0cmF0ZSB0aGUgZGF0YSB2aXN1YWxpemF0aW9uIGFuZCBpbnRlcmFjdGl2ZSBtYXBwaW5nIGNhcGFiaWxpdGllcyBvZiBSLiBGb3IgdGhpcyBwcm9qZWN0IEkgd2lsbCBiZSB1c2luZyB0aGUgTm92ZW1iZXIgMjAxOCBXb29sc2V5IEZpcmUgYXMgYSBjYXNlIHN0dWR5IHRvIGRlbW9uc3RyYXRlIGhvdyBSIGNhbiBoZWxwIGluIHNwYXRpYWwgYW5hbHlzaXMgb2YgZmlyZSBkYXRhIGFzIHdlbGwgYXMgaW4gZGlzcGxheWluZyB0aGF0IGRhdGEgdG8gYSBicm9hZGVyIGF1ZGllbmNlLiBJIGNob3NlIHRoaXMgY2FzZSBzdHVkeSBzaW5jZSBpdCBjYW4gYmVuZWZpdCBmcm9tIHNwYXRpYWwgbGF5ZXJpbmcgb2YgZGlmZmVyZW50IGRhdGEgZm9ybWF0cyBhbmQgbXVsdGlwbGUgbGV2ZWxzIG9mIGFuYWx5c2lzIGNhbiBiZSBkb25lIHRvIGl0LiAKCkkgd2lsbCBiZSB1c2luZyBkYXRhIGFnZ3JlZ2F0ZCBmcm9tIG11bHRpcGxlIHNvdXJjZXMsIGFsbCBkYXRhIHNvdXJjZXMgcmVmZXJlbmNlZCBpbiB0aGlzIHByb2plY3QgYXJlIGZyZWUgdG8gYWNjZXNzIGZvciBhbnlvbmUgaW50ZXJlc3RlZCBpbiBkdXBsaWNhdGluZyB0aGlzIHByb2plY3Qgb3IgYXBwbHlpbmcgaXRzIG1ldGhvZHMgdG93YXJkcyBhIHNpbWlsYXIgcHJvamVjdC4gQSBtYWpvcml0eSBvZiB0aGUgZG9jdW1lbnRhdGlvbiB3aWxsIGJlIHdyaXR0ZW4gaW4gdGhlIGNvZGUgY2h1bmtzIHRvIGFsbG93IGZvciBiZXR0ZXIgc3RlcC1ieS1zdGVwIGV4cGxhbmF0aW9uLgoKVGhpcyBjb2RlIGNodW5rIHNob3dzIGFsbCB0aGUgcGFja2FnZXMgYW5kIGxpYnJhcmllcyB0aGF0IEkgdXNlZCBmb3IgdGhpcyBwcm9qZWN0LiAKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjI1BhY2thZ2VzIGFuZCBMaWJyYXJpZXMjIyMjIyMjIyMjIyMjIyMjIyMKaW5zdGFsbC5wYWNrYWdlcygibWFnaWNrIikKbGlicmFyeShtYWdpY2spCmxpYnJhcnkoZGV2dG9vbHMpCmluc3RhbGxfZ2l0aHViKCJtdGVubmVrZXMvdG1hcHRvb2xzIikKaW5zdGFsbF9naXRodWIoIm10ZW5uZWtlcy90bWFwIikKI2luc3RhbGwucGFja2FnZXMoInRtYXAiKQpsaWJyYXJ5KHRtYXApCmxpYnJhcnkoc3ApCmxpYnJhcnkocmFzdGVyKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShjbGFzc0ludCkKaW5zdGFsbC5wYWNrYWdlcygncmFzdGVyVmlzJykKbGlicmFyeShyYXN0ZXJWaXMpCmluc3RhbGwucGFja2FnZXMoJ3RpZ3JpcycpCmxpYnJhcnkodGlncmlzKQppbnN0YWxsLnBhY2thZ2VzKCdyZ2RhbCcsIHR5cGUgPSAic291cmNlIiwgY29uZmlndXJlLmFyZ3M9YygnLS13aXRoLXByb2otaW5jbHVkZT0vTGlicmFyeS9GcmFtZXdvcmtzL1BST0ouZnJhbWV3b3JrL0hlYWRlcnMnLCAnLS13aXRoLXByb2otbGliPS9MaWJyYXJ5L0ZyYW1ld29ya3MvUFJPSi5mcmFtZXdvcmsvdW5peC9saWInKSkKbGlicmFyeShyZ2RhbCkKI2luc3RhbGwucGFja2FnZXMoInRtYXB0b29scyIpCmluc3RhbGwucGFja2FnZXMoInNmIikKaW5zdGFsbC5wYWNrYWdlcygibGVhZmxldCIpCmxpYnJhcnkodG1hcHRvb2xzKQpsaWJyYXJ5KCJzZiIpCmxpYnJhcnkobGVhZmxldCkKbGlicmFyeSh0aWdyaXMpCmluc3RhbGwucGFja2FnZXMoJ2RldnRvb2xzJykKZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCd0aG9tYXNwODUvZ2dhbmltYXRlJykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnYW5pbWF0ZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnbWFwKQpsaWJyYXJ5KG1hcHMpCmxpYnJhcnkoZ2d0aGVtZXMpCmluc3RhbGwucGFja2FnZXMoInBsb3RseSIpCmxpYnJhcnkocGxvdGx5KQpgYGAKCkludGVyYWN0aXZlIHRtYXAoKSBtYXA6IApGb3IgdGhpcyBtYXAsIEkgdXNlZCB0aGUgdG1hcCBwYWNrYWdlIHRvIGNyZWF0ZSBhbiBpbnRlcmFjdGl2ZSBtYXAgdGhhdCBsYXllcnMgdGhlIERpZ2l0YWwgRWxldmF0aW9uIE1vZGVsLCBtZWRpYW4gaG9tZSB2YWx1ZSwgYW5kIGZpcmUgaW5jaWRlbmNlIGRhdGEgb24gb25lIGludGVyYWN0aXZlIG1hcC4gVGhlIGxheWVyIHRvZ2dsZSBhbHNvIGFsbG93cyB0aGUgdXNlciB0byBzZWxlY3Qgd2hpY2ggbGF5ZXJzIHRvIGRpc3BsYXkgaW4gb3JkZXIgdG8gY3VzdG9taXplIHRoZSBtYXAgdG8gb25seSBzaG93IGluZm9ybWF0aW9uIHRoYXQgdGhlIGVuZCB1c2VyIHdhbnRzIHRvIHNlZS4gCmBgYHtyfQojIyMjIyMjIyMjIyMjIyMjIyNBZGQgRmlyZSBEYXRhIGZyb20gTkFTQSBGSVJNUyMjIyMjIyMjIyMjIyMjIyMjIwojQ3JlYXRlIGRvd25sb2FkIHJlcXVlc3RzIGhlcmU6aHR0cHM6Ly9maXJtcy5tb2RhcHMuZW9zZGlzLm5hc2EuZ292L2Rvd25sb2FkLwoKI2ltcG9ydCBmaXJlIHBvaW50cyBkYXRhCmRpcigiL1VzZXJzL2tyZ3IuZGYvRGVza3RvcC9HRU9HMjA4L0ZpbmFsIEFzc2lnbm1lbnQvRmlyZSBEYXRhL0RMX0ZJUkVfVjFfMzMwNDIoU0hQOC0yNCkiKQpGaXJlLlBvaW50cyA8LSByZWFkT0dSKCIvVXNlcnMva3Jnci5kZi9EZXNrdG9wL0dFT0cyMDgvRmluYWwgQXNzaWdubWVudC9GaXJlIERhdGEvRExfRklSRV9WMV8zMzA0MihTSFA4LTI0KSIsICJmaXJlX25ydF9WMV8zMzA0MiIpCgojIyMjIyMjIyMjIyMjIyMjIyNNZXJnZSBhbmQgUmVjbGFzc2lmeSBSYXN0ZXIjIyMjIyMjIyMjIyMjIyMjIyMKI3Jhc3RlciBkYXRhIGRvd25sb2FkZWQgZnJvbSBmcm9tIGdsb3ZpczogaHR0cHM6Ly9nbG92aXMudXNncy5nb3YvYXBwCgojaW1wb3J0IGFuZCBtZXJnZSB0d28gcmFzdGVyIGZpbGVzCkRFTV80IDwtIHJhc3RlcigiL1VzZXJzL2tyZ3IuZGYvRGVza3RvcC9HRU9HMjA4L0ZpbmFsIEFzc2lnbm1lbnQvREVNcy9uMzRfdzEyMF8zYXJjX3YyLnRpZiIpCkRFTV81IDwtIHJhc3RlcigiL1VzZXJzL2tyZ3IuZGYvRGVza3RvcC9HRU9HMjA4L0ZpbmFsIEFzc2lnbm1lbnQvREVNcy9uMzRfdzExOV8zYXJjX3YyLnRpZiIpCm1vc2FpYyhERU1fNCwgREVNXzUsIGZ1biA9IG1lYW4sIHRvbGVyYW5jZT0wLjA1LCBmaWxlbmFtZT0iL1VzZXJzL2tyZ3IuZGYvRGVza3RvcC9HRU9HMjA4L0ZpbmFsIEFzc2lnbm1lbnQvREVNcy9Nb3NhaWNfdGVzdF8xLnRpZiIsIG92ZXJ3cml0ZT1UUlVFKSAKbW9zYWljX3Rlc3QgPC0gcmFzdGVyKCIvVXNlcnMva3Jnci5kZi9EZXNrdG9wL0dFT0cyMDgvRmluYWwgQXNzaWdubWVudC9ERU1zL01vc2FpY190ZXN0XzEudGlmIiwgb3ZlcndyaXRlPVRSVUUpCgojcmVjbGFzc2lmeSByYXN0ZXIgdG8gc2V0IHZhbHVlcyBiZWxvdyA1MDAgdG8gTkEsIHRoaXMgcmVtb3ZlcyB0aGVtIGZyb20gZGlzcGxheQpERU0gPC0gY2FsYyhtb3NhaWNfdGVzdCwgZnVuPWZ1bmN0aW9uKHgpeyB4W3ggPCA1MDBdIDwtIE5BOyByZXR1cm4oeCl9ICkKCiMjIyMjIyMjIyMjIyMjIyMjI0FkZCBEZW1vZ3JhcGhpYyBEYXRhIyMjIyMjIyMjIyMjIyMjIyMjCiNwdWxsIHZlbnR1cmEgJiBMQSBjb3VudHkgYm91bmRhcnkgbWFwIGZyb20gbGlicmFyeSh0aWdyaXMpClZlbl9ib3VuZCA8LSB0cmFjdHMoc3RhdGUgPSAiQ0EiLCBjb3VudHkgPSAiVmVudHVyYSIsIGNiID0gVFJVRSkKCkxBX2JvdW5kIDwtIHRyYWN0cyhzdGF0ZSA9ICJDQSIsIGNvdW50eSA9ICJMb3MgQW5nZWxlcyIsIGNiID0gVFJVRSkKCiNpbXBvcnQgY3N2IGZpbGUgd2l0aCBtZWRpYW4gaG9tZSB2YWx1ZSBkYXRhIChWZW50dXJhKQpIVzQgPC0gZmlsZS5wYXRoICgiL1VzZXJzL2tyZ3IuZGYvRGVza3RvcC9HRU9HMjA4L0Fzc2lnbm1lbnQgNC92ZW50dXJhX21lZGlhbl92YWwuY3N2IikKbWVkaWFuLnZhbCA8LSByZWFkLmNzdihIVzQsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKbWVkaWFuLnZhbCRtZWRpYW4udmFsdWUgPC0gYXMubnVtZXJpYyhtZWRpYW4udmFsJG1lZGlhbi52YWx1ZSkKbWVkaWFuLnZhbCRpZDIgPC0gYXMuY2hhcmFjdGVyKG1lZGlhbi52YWwkaWQyKQoKI2ltcG9ydCBjc3YgZmlsZSB3aXRoIG1lZGlhbiBob21lIHZhbHVlIGRhdGEgKExvcyBBbmdlbGVzKQpIVzQuMiA8LSBmaWxlLnBhdGggKCIvVXNlcnMva3Jnci5kZi9EZXNrdG9wL0dFT0cyMDgvQXNzaWdubWVudCA0L0xBX21lZGlhbl92YWwuY3N2IikKTEEubWVkaWFuLnZhbCA8LSByZWFkLmNzdihIVzQuMiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQpMQS5tZWRpYW4udmFsJG1lZGlhbi52YWwgPC0gYXMubnVtZXJpYyhMQS5tZWRpYW4udmFsJG1lZGlhbi52YWwpCkxBLm1lZGlhbi52YWwkaWQyIDwtIGFzLmNoYXJhY3RlcihMQS5tZWRpYW4udmFsJGlkMikKCiNtZXJnZSBjZW5zdXMgdHJhY3QgYm91bmRhcmllcyB3aXRoIG1lZGlhbiBob21lIHZhbHVlcyAoVmVudHVyYSkKVmVudHVyYS5TdGF0cyA8LSBtZXJnZShWZW5fYm91bmQsIG1lZGlhbi52YWwsIGJ5LnggPSAiQUZGR0VPSUQiLCBieS55ID0gImlkIikKCiNtZXJnZSBjZW5zdXMgdHJhY3QgYm91bmRhcmllcyB3aXRoIG1lZGlhbiBob21lIHZhbHVlcyAoTG9zIEFuZ2VsZXMpCkxBLlN0YXRzIDwtIG1lcmdlKExBX2JvdW5kLCBMQS5tZWRpYW4udmFsLCBieS54ID0gIkFGRkdFT0lEIiwgYnkueSA9ICJpZCIpCgojIyMjIyMjIyMjIyMjIyMjIyNDcmVhdGUgSW50ZXJhY3RpdmUgdG1hcCgpIyMjIyMjIyMjIyMjIyMjIyMjCiNzZXQgdG1hcCB0byBpbnRlcmFjdGl2ZSB2aWV3aW5nIG1vZGUgYW5kIHNldCB0aGVtZSB0byAnY29iYWx0Jwp0bWFwX21vZGUoInZpZXciKQp0bWFwX3N0eWxlKCJjb2JhbHQiKQoKI2FsbG93cyB0b2dnbGluZyBiZXR3ZWVuIHN0YXRpYyBha2EgJ3Bsb3QnIGFuZCBpbnRlcmFjdGl2ZSBha2EgJ3ZpZXcnIG1vZGVzCnR0bSgpIAoKI3RoZSBmb2xsb3dpbmcgbGluZXMgb2YgY29kZSBhZGRzIGxheWVycyBpbnRvIHRtYXAgYW5kIGVkaXRzIHRoZSBhcHBlYXJhbmNlIG9mIHRoZSBtYXAKdG1hcF9tYXAgPC0gdG1fc2hhcGUoVmVudHVyYS5TdGF0cykrCiAgdG1fZmlsbChjb2wgPSAibWVkaWFuLnZhbHVlIiwgcGFsZXR0ZSA9ICJQdUJ1IiwgdGl0bGUgPSAiVmVudHVyYSBDb3VudHkgTWVkaWFuIEhvbWUgVmFsdWUiLCAKICAgICAgICAgIHN0eWxlID0gImZpeGVkIiwKICAgICAgICAgIGJyZWFrcyA9IGMoMCwgMjUwMDAwLCA1MDAwMDAsIDc1MDAwMCwgMTAwMDAwMCwgSW5mKSwKICAgICAgICAgIHRleHROQSA9ICJObyBEYXRhIiwgCiAgICAgICAgICBjb2xvck5BID0gImdyYXkiLAogICAgICAgICAgYWxwaGEgPSAuNykgKwogIHRtX2JvcmRlcnMoY29sID0gIndoaXRlIikgKwogIHRtX2xheW91dChsZWdlbmQudGl0bGUuc2l6ZSA9IDEsCiAgICAgICAgICAgIGxlZ2VuZC50ZXh0LnNpemUgPSAwLjYsCiAgICAgICAgICAgIGxlZ2VuZC50ZXh0LmNvbG9yID0gImdyYXkyMCIsCiAgICAgICAgICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsCiAgICAgICAgICAgIGxlZ2VuZC53aWR0aCA9IC0xLAogICAgICAgICAgICBsZWdlbmQuYmcuYWxwaGEgPSAxKSsKICB0bV92aWV3KHZpZXcubGVnZW5kLnBvc2l0aW9uID0gYygicmlnaHQiLCAiYm90dG9tIikpICsKICB0bV9zaGFwZShMQS5TdGF0cykrCiAgdG1fZmlsbChjb2wgPSAibWVkaWFuLnZhbCIsIHBhbGV0dGUgPSAiWWxHbiIsIHRpdGxlID0gIkxBIENvdW50eSBNZWRpYW4gSG9tZSBWYWx1ZSIsIAogICAgICAgICAgc3R5bGUgPSAiZml4ZWQiLAogICAgICAgICAgYnJlYWtzID0gYygwLCAyNTAwMDAsIDUwMDAwMCwgNzUwMDAwLCAxMDAwMDAwLCBJbmYpLAogICAgICAgICAgdGV4dE5BID0gIk5vIERhdGEiLCAKICAgICAgICAgIGNvbG9yTkEgPSAiZ3JheSIsCiAgICAgICAgICBhbHBoYSA9IC43KSArCiAgdG1fYm9yZGVycyhjb2wgPSAid2hpdGUiKSArCiAgdG1fbGF5b3V0KGxlZ2VuZC50aXRsZS5zaXplID0gMSwKICAgICAgICAgICAgbGVnZW5kLnRleHQuc2l6ZSA9IDAuNiwKICAgICAgICAgICAgbGVnZW5kLnRleHQuY29sb3IgPSAiZ3JheTIwIiwKICAgICAgICAgICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwKICAgICAgICAgICAgbGVnZW5kLndpZHRoID0gLTEsCiAgICAgICAgICAgIGxlZ2VuZC5iZy5hbHBoYSA9IDEpICsKICB0bV92aWV3KHZpZXcubGVnZW5kLnBvc2l0aW9uID0gYygibGVmdCIsICJib3R0b20iKSkgKwogIHRtX3NoYXBlKEZpcmUuUG9pbnRzKSArCiAgdG1fZG90cygiQlJJR0hUX1RJNCIsIAogICAgICAgICAgYWxwaGEgPSAxLAogICAgICAgICAgYm9yZGVyLmNvbCA9IE5BLAogICAgICAgICAgdGl0bGUgPSAiRmlyZSBJbnRlbnNpdHkiLAogICAgICAgICAgcG9wdXAudmFycyA9ICJBQ1FfREFURSIsCiAgICAgICAgICBwYWxldHRlID0gIllsT3JSZCIpICsKICB0bV92aWV3KHZpZXcubGVnZW5kLnBvc2l0aW9uID0gYygicmlnaHQiLCAidG9wIikpICsKICB0bV9zaGFwZShERU0sIHVuaXQgPSAibWkiKSArCiAgdG1fcmFzdGVyKCJsYXllciIsIAogICAgICAgICAgICBtaWRwb2ludCA9IE5BLCAKICAgICAgICAgICAgdGl0bGUgPSAiREVNIiwKICAgICAgICAgICAgbGVnZW5kLnNob3cgPSBGQUxTRSkgKwogIHRtYXBfb3B0aW9ucyhtYXgucmFzdGVyID0gYyhwbG90ID0gMjg4MzYwMSwgdmlldyA9IDI4ODM2MDEpKSArCiAgdG1fc2NhbGVfYmFyKHNpemUgPSAxLCAKICAgICAgICAgICAgICAgdGV4dC5jb2xvciA9IE5BLAogICAgICAgICAgICAgICBjb2xvci5kYXJrID0gImJsYWNrIiwgY29sb3IubGlnaHQgPSAid2hpdGUiLCAKICAgICAgICAgICAgICAgbHdkID0gMSwgCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gYygiYm90dG9tIiwgImxlZnQiKSkKCnRtYXBfbWFwCmBgYAoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjI0FkZCBGaXJlIERhdGEgZnJvbSBOQVNBIEZJUk1TIyMjIyMjIyMjIyMjIyMjIyMjCiNDcmVhdGUgZG93bmxvYWQgcmVxdWVzdHMgaGVyZTpodHRwczovL2Zpcm1zLm1vZGFwcy5lb3NkaXMubmFzYS5nb3YvZG93bmxvYWQvCgojaW1wb3J0IGZpcmUgcG9pbnRzIGRhdGEKZGlyKCIvVXNlcnMva3Jnci5kZi9EZXNrdG9wL0dFT0cyMDgvRmluYWwgQXNzaWdubWVudC9GaXJlIERhdGEvRExfRklSRV9WMV8zMzA0MihTSFA4LTI0KSIpCkZpcmUuUG9pbnRzIDwtIHJlYWRPR1IoIi9Vc2Vycy9rcmdyLmRmL0Rlc2t0b3AvR0VPRzIwOC9GaW5hbCBBc3NpZ25tZW50L0ZpcmUgRGF0YS9ETF9GSVJFX1YxXzMzMDQyKFNIUDgtMjQpIiwgImZpcmVfbnJ0X1YxXzMzMDQyIikKCiMjIyMjIyMjIyMjIyMjIyMjI01lcmdlIGFuZCBSZWNsYXNzaWZ5IFJhc3RlciMjIyMjIyMjIyMjIyMjIyMjIwojcmFzdGVyIGRhdGEgZG93bmxvYWRlZCBmcm9tIGZyb20gZ2xvdmlzOiBodHRwczovL2dsb3Zpcy51c2dzLmdvdi9hcHAKCiNpbXBvcnQgYW5kIG1lcmdlIHR3byByYXN0ZXIgZmlsZXMKREVNXzQgPC0gcmFzdGVyKCIvVXNlcnMva3Jnci5kZi9EZXNrdG9wL0dFT0cyMDgvRmluYWwgQXNzaWdubWVudC9ERU1zL24zNF93MTIwXzNhcmNfdjIudGlmIikKREVNXzUgPC0gcmFzdGVyKCIvVXNlcnMva3Jnci5kZi9EZXNrdG9wL0dFT0cyMDgvRmluYWwgQXNzaWdubWVudC9ERU1zL24zNF93MTE5XzNhcmNfdjIudGlmIikKbW9zYWljKERFTV80LCBERU1fNSwgZnVuID0gbWVhbiwgdG9sZXJhbmNlPTAuMDUsIGZpbGVuYW1lPSIvVXNlcnMva3Jnci5kZi9EZXNrdG9wL0dFT0cyMDgvRmluYWwgQXNzaWdubWVudC9ERU1zL01vc2FpY190ZXN0XzEudGlmIiwgb3ZlcndyaXRlPVRSVUUpIAptb3NhaWNfdGVzdCA8LSByYXN0ZXIoIi9Vc2Vycy9rcmdyLmRmL0Rlc2t0b3AvR0VPRzIwOC9GaW5hbCBBc3NpZ25tZW50L0RFTXMvTW9zYWljX3Rlc3RfMS50aWYiLCBvdmVyd3JpdGU9VFJVRSkKCiNyZWNsYXNzaWZ5IHJhc3RlciB0byBzZXQgdmFsdWVzIGJlbG93IDUwMCB0byBOQSwgdGhpcyByZW1vdmVzIHRoZW0gZnJvbSBkaXNwbGF5CkRFTSA8LSBjYWxjKG1vc2FpY190ZXN0LCBmdW49ZnVuY3Rpb24oeCl7IHhbeCA8IDUwMF0gPC0gTkE7IHJldHVybih4KX0gKQoKIyMjIyMjIyMjIyMjIyMjIyMjQWRkIERlbW9ncmFwaGljIERhdGEjIyMjIyMjIyMjIyMjIyMjIyMKI3B1bGwgdmVudHVyYSAmIExBIGNvdW50eSBib3VuZGFyeSBtYXAgZnJvbSBsaWJyYXJ5KHRpZ3JpcykKVmVuX2JvdW5kIDwtIHRyYWN0cyhzdGF0ZSA9ICJDQSIsIGNvdW50eSA9ICJWZW50dXJhIiwgY2IgPSBUUlVFKQoKTEFfYm91bmQgPC0gdHJhY3RzKHN0YXRlID0gIkNBIiwgY291bnR5ID0gIkxvcyBBbmdlbGVzIiwgY2IgPSBUUlVFKQoKI2ltcG9ydCBjc3YgZmlsZSB3aXRoIG1lZGlhbiBob21lIHZhbHVlIGRhdGEgKFZlbnR1cmEpCkhXNCA8LSBmaWxlLnBhdGggKCIvVXNlcnMva3Jnci5kZi9EZXNrdG9wL0dFT0cyMDgvQXNzaWdubWVudCA0L3ZlbnR1cmFfbWVkaWFuX3ZhbC5jc3YiKQptZWRpYW4udmFsIDwtIHJlYWQuY3N2KEhXNCwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQptZWRpYW4udmFsJG1lZGlhbi52YWx1ZSA8LSBhcy5udW1lcmljKG1lZGlhbi52YWwkbWVkaWFuLnZhbHVlKQptZWRpYW4udmFsJGlkMiA8LSBhcy5jaGFyYWN0ZXIobWVkaWFuLnZhbCRpZDIpCgojaW1wb3J0IGNzdiBmaWxlIHdpdGggbWVkaWFuIGhvbWUgdmFsdWUgZGF0YSAoTG9zIEFuZ2VsZXMpCkhXNC4yIDwtIGZpbGUucGF0aCAoIi9Vc2Vycy9rcmdyLmRmL0Rlc2t0b3AvR0VPRzIwOC9Bc3NpZ25tZW50IDQvTEFfbWVkaWFuX3ZhbC5jc3YiKQpMQS5tZWRpYW4udmFsIDwtIHJlYWQuY3N2KEhXNC4yLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCkxBLm1lZGlhbi52YWwkbWVkaWFuLnZhbCA8LSBhcy5udW1lcmljKExBLm1lZGlhbi52YWwkbWVkaWFuLnZhbCkKTEEubWVkaWFuLnZhbCRpZDIgPC0gYXMuY2hhcmFjdGVyKExBLm1lZGlhbi52YWwkaWQyKQoKI21lcmdlIGNlbnN1cyB0cmFjdCBib3VuZGFyaWVzIHdpdGggbWVkaWFuIGhvbWUgdmFsdWVzIChWZW50dXJhKQpWZW50dXJhLlN0YXRzIDwtIG1lcmdlKFZlbl9ib3VuZCwgbWVkaWFuLnZhbCwgYnkueCA9ICJBRkZHRU9JRCIsIGJ5LnkgPSAiaWQiKQoKI21lcmdlIGNlbnN1cyB0cmFjdCBib3VuZGFyaWVzIHdpdGggbWVkaWFuIGhvbWUgdmFsdWVzIChMb3MgQW5nZWxlcykKTEEuU3RhdHMgPC0gbWVyZ2UoTEFfYm91bmQsIExBLm1lZGlhbi52YWwsIGJ5LnggPSAiQUZGR0VPSUQiLCBieS55ID0gImlkIikKCiMjIyMjIyMjIyMjIyMjIyMjI0NyZWF0ZSBJbnRlcmFjdGl2ZSB0bWFwKCkjIyMjIyMjIyMjIyMjIyMjIyMKI3NldCB0bWFwIHRvIGludGVyYWN0aXZlIHZpZXdpbmcgbW9kZSBhbmQgc2V0IHRoZW1lIHRvICdjb2JhbHQnCnRtYXBfbW9kZSgidmlldyIpCnRtYXBfc3R5bGUoImNvYmFsdCIpCgojYWxsb3dzIHRvZ2dsaW5nIGJldHdlZW4gc3RhdGljIGFrYSAncGxvdCcgYW5kIGludGVyYWN0aXZlIGFrYSAndmlldycgbW9kZXMKdHRtKCkgCgojdGhlIGZvbGxvd2luZyBsaW5lcyBvZiBjb2RlIGFkZHMgbGF5ZXJzIGludG8gdG1hcCBhbmQgZWRpdHMgdGhlIGFwcGVhcmFuY2Ugb2YgdGhlIG1hcAp0bWFwX21hcCA8LSB0bV9zaGFwZShWZW50dXJhLlN0YXRzKSsKICB0bV9maWxsKGNvbCA9ICJtZWRpYW4udmFsdWUiLCBwYWxldHRlID0gIlB1QnUiLCB0aXRsZSA9ICJWZW50dXJhIENvdW50eSBNZWRpYW4gSG9tZSBWYWx1ZSIsIAogICAgICAgICAgc3R5bGUgPSAiZml4ZWQiLAogICAgICAgICAgYnJlYWtzID0gYygwLCAyNTAwMDAsIDUwMDAwMCwgNzUwMDAwLCAxMDAwMDAwLCBJbmYpLAogICAgICAgICAgdGV4dE5BID0gIk5vIERhdGEiLCAKICAgICAgICAgIGNvbG9yTkEgPSAiZ3JheSIsCiAgICAgICAgICBhbHBoYSA9IC43KSArCiAgdG1fYm9yZGVycyhjb2wgPSAid2hpdGUiKSArCiAgdG1fbGF5b3V0KGxlZ2VuZC50aXRsZS5zaXplID0gMSwKICAgICAgICAgICAgbGVnZW5kLnRleHQuc2l6ZSA9IDAuNiwKICAgICAgICAgICAgbGVnZW5kLnRleHQuY29sb3IgPSAiZ3JheTIwIiwKICAgICAgICAgICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwKICAgICAgICAgICAgbGVnZW5kLndpZHRoID0gLTEsCiAgICAgICAgICAgIGxlZ2VuZC5iZy5hbHBoYSA9IDEpKwogIHRtX3ZpZXcodmlldy5sZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgKwogIHRtX3NoYXBlKExBLlN0YXRzKSsKICB0bV9maWxsKGNvbCA9ICJtZWRpYW4udmFsIiwgcGFsZXR0ZSA9ICJZbEduIiwgdGl0bGUgPSAiTEEgQ291bnR5IE1lZGlhbiBIb21lIFZhbHVlIiwgCiAgICAgICAgICBzdHlsZSA9ICJmaXhlZCIsCiAgICAgICAgICBicmVha3MgPSBjKDAsIDI1MDAwMCwgNTAwMDAwLCA3NTAwMDAsIDEwMDAwMDAsIEluZiksCiAgICAgICAgICB0ZXh0TkEgPSAiTm8gRGF0YSIsIAogICAgICAgICAgY29sb3JOQSA9ICJncmF5IiwKICAgICAgICAgIGFscGhhID0gLjcpICsKICB0bV9ib3JkZXJzKGNvbCA9ICJ3aGl0ZSIpICsKICB0bV9sYXlvdXQobGVnZW5kLnRpdGxlLnNpemUgPSAxLAogICAgICAgICAgICBsZWdlbmQudGV4dC5zaXplID0gMC42LAogICAgICAgICAgICBsZWdlbmQudGV4dC5jb2xvciA9ICJncmF5MjAiLAogICAgICAgICAgICBsZWdlbmQuYmcuY29sb3IgPSAid2hpdGUiLAogICAgICAgICAgICBsZWdlbmQud2lkdGggPSAtMSwKICAgICAgICAgICAgbGVnZW5kLmJnLmFscGhhID0gMSkgKwogIHRtX3ZpZXcodmlldy5sZWdlbmQucG9zaXRpb24gPSBjKCJsZWZ0IiwgImJvdHRvbSIpKSArCiAgdG1fc2hhcGUoRmlyZS5Qb2ludHMpICsKICB0bV9kb3RzKCJCUklHSFRfVEk0IiwgCiAgICAgICAgICBhbHBoYSA9IDEsCiAgICAgICAgICBib3JkZXIuY29sID0gTkEsCiAgICAgICAgICB0aXRsZSA9ICJGaXJlIEludGVuc2l0eSIsCiAgICAgICAgICBwb3B1cC52YXJzID0gIkFDUV9EQVRFIiwKICAgICAgICAgIHBhbGV0dGUgPSAiWWxPclJkIikgKwogIHRtX3ZpZXcodmlldy5sZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJ0b3AiKSkgKwogIHRtX3NoYXBlKERFTSwgdW5pdCA9ICJtaSIpICsKICB0bV9yYXN0ZXIoImxheWVyIiwgCiAgICAgICAgICAgIG1pZHBvaW50ID0gTkEsIAogICAgICAgICAgICB0aXRsZSA9ICJERU0iLAogICAgICAgICAgICBsZWdlbmQuc2hvdyA9IEZBTFNFKSArCiAgdG1hcF9vcHRpb25zKG1heC5yYXN0ZXIgPSBjKHBsb3QgPSAyODgzNjAxLCB2aWV3ID0gMjg4MzYwMSkpICsKICB0bV9zY2FsZV9iYXIoc2l6ZSA9IDEsIAogICAgICAgICAgICAgICB0ZXh0LmNvbG9yID0gTkEsCiAgICAgICAgICAgICAgIGNvbG9yLmRhcmsgPSAiYmxhY2siLCBjb2xvci5saWdodCA9ICJ3aGl0ZSIsIAogICAgICAgICAgICAgICBsd2QgPSAxLCAKICAgICAgICAgICAgICAgcG9zaXRpb24gPSBjKCJib3R0b20iLCAibGVmdCIpKQoKdG1hcF9tYXAKYGBgCgpJIGNyZWF0ZWQgYSBoaXN0b2dyYW0gb2YgZmlyZSBmcmVxdWVuY3kgb3ZlciB0aW1lIGluIG9yZGVyIHRvIHBpbnBvaW50IHdoaWNoIGRheXMgaGFkIHRoZSBoaWdoZXN0IG51bWJlciBvZiBmaXJlIGluY2lkZW50cyAKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjI1Bsb3QgSGlzdG9ncmFtIERhdGEjIyMjIyMjIyMjIyMjIyMjIyMKCiNpbXBvcnQgTkFTQSBmaXJlIHBvaW50cyAuY3N2IGRhdGEKZmlyZV9jc3YgPC0gcmVhZC5jc3YoIi9Vc2Vycy9rcmdyLmRmL0Rlc2t0b3AvR0VPRzIwOC9GaW5hbCBBc3NpZ25tZW50L0ZpcmUgRGF0YS9OQVNBIFZJSVJzIENTVi9maXJlX25ydF9WMV8zMjk4Ni5jc3YiKQoKI2NoYW5nZSBhY3F1aXJlZCBkYXRlIGNvbHVtbiBmcm9tIG51bWVyaWMgdG8gZGF0ZQpmaXJlX2NzdiRhY3FfZGF0ZSA8LSBhcy5EYXRlKGZpcmVfY3N2JGFjcV9kYXRlKQoKI3Bsb3QgYSBoaXN0b2dyYW0gb2YgZmlyZSBmcmVxdWVuY3kgb3ZlciB0aW1lCmhpc3QoZmlyZV9jc3YkYWNxX2RhdGUsICJkYXlzIiwgCiAgICAgZnJlcSA9IFRSVUUsCiAgICAgYnJlYWtzID0gMTUsCiAgICAgeGxhYiA9ICJEYXRlIEFjcXVpcmVkIiwKICAgICBjb2wgPSAiZmlyZWJyaWNrMyIsCiAgICAgYm9yZGVyID0gIm9yYW5nZSIKICAgICApCmBgYAoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjI1Bsb3QgSGlzdG9ncmFtIERhdGEjIyMjIyMjIyMjIyMjIyMjIyMKCiNpbXBvcnQgTkFTQSBmaXJlIHBvaW50cyAuY3N2IGRhdGEKZmlyZV9jc3YgPC0gcmVhZC5jc3YoIi9Vc2Vycy9rcmdyLmRmL0Rlc2t0b3AvR0VPRzIwOC9GaW5hbCBBc3NpZ25tZW50L0ZpcmUgRGF0YS9OQVNBIFZJSVJzIENTVi9maXJlX25ydF9WMV8zMjk4Ni5jc3YiKQoKI2NoYW5nZSBhY3F1aXJlZCBkYXRlIGNvbHVtbiBmcm9tIG51bWVyaWMgdG8gZGF0ZQpmaXJlX2NzdiRhY3FfZGF0ZSA8LSBhcy5EYXRlKGZpcmVfY3N2JGFjcV9kYXRlKQoKI3Bsb3QgYSBoaXN0b2dyYW0gb2YgZmlyZSBmcmVxdWVuY3kgb3ZlciB0aW1lCmhpc3QoZmlyZV9jc3YkYWNxX2RhdGUsICJkYXlzIiwgCiAgICAgZnJlcSA9IFRSVUUsCiAgICAgYnJlYWtzID0gMTUsCiAgICAgeGxhYiA9ICJEYXRlIEFjcXVpcmVkIiwKICAgICBjb2wgPSAiZmlyZWJyaWNrMyIsCiAgICAgYm9yZGVyID0gIm9yYW5nZSIKICAgICApCmBgYAoKSSBhbHNvIGNyZWF0ZWQgYW4gYW5pbWF0ZWQgbWFwIHRoYXQgZGlzcGxheXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmaXJlIGluc3RhbmNlcyBvdmVyIHRpbWUgZHVyaW5nIHRoZSBleHRlbnQgb2YgdGhlIFdvb2xzZXkgRmlyZS4KYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjI0FuaW1hdGVkIE1hcCMjIyMjIyMjIyMjIyMjIyMjIwojY3JlYXRlZCB1c2luZyBnZ2FuaW1hdGUgcGFja2FnZSBmcm9tOiBodHRwczovL2dpdGh1Yi5jb20vdGhvbWFzcDg1L2dnYW5pbWF0ZQoKI2NoYW5nZSBmb3JtYXQgb2YgZGF0ZSBjb2x1bW4gZnJvbSBudW1lcmljIHRvIGRhdGUKZmlyZV9jc3YkYWNxX2RhdGUgPC0gYXMuRGF0ZShmaXJlX2NzdiRhY3FfZGF0ZSkKc3RyKGZpcmVfY3N2KQoKI2NyZWF0ZSBhbmltYXRlZCBtYXAgdXNpbmcgZ2dhbmltYXRlCmFuaW1hdGVkX21hcCA8LSBnZ3Bsb3QoZmlyZV9jc3YsIChhZXMobG9uZ2l0dWRlLCBsYXRpdHVkZSwgY29sb3IgPSBicmlnaHRfdGk0KSkpICsKICBib3JkZXJzKCJjb3VudHkiLCAiLip2ZW50dXJhIixjb2xvdXIgPSAiZ3JheTg1IiwgZmlsbCA9ICJncmF5ODAiLCApICsKICB0aGVtZV9tYXAoKSArCiAgYm9yZGVycygiY291bnR5IiwgIi4qbG9zIGFuZ2VsZXMiLGNvbG91ciA9ICJncmF5ODUiLCBmaWxsID0gImdyYXk4MCIsICkgKwogIHRoZW1lX21hcCgpICsKICBnZW9tX3BvaW50KGFscGhhID0gLjUpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3c9InllbGxvdyIsIGhpZ2g9InJlZCIsIG5hbWUgPSAiQnJpZ2h0bmVzcyBWYWx1ZSIpICsgCiAgbGFicyh0aXRsZSA9ICdEYXRlOiB7ZnJhbWVfdGltZX0nLCBzaXplID0gMykgKwogIHRyYW5zaXRpb25fdGltZShhY3FfZGF0ZSkgKwogIGVudGVyX2ZhZGUoKSArIAogIGVhc2VfYWVzKCJsaW5lYXIiKQoKYW5pbWF0ZWRfbWFwCmBgYApBTklNQVRFRCBNQVAgSEVSRSAob3BlbiBsaW5rIGluIG5ldyB0YWIpOgpodHRwczovL3Bob3Rvcy5nb29nbGUuY29tL3NoYXJlL0FGMVFpcE5aTjJhSVVvcktVWUtNa001VmJMWW9XUVVOYll2WWxZdWJiZU5nZWg1U0VJZGZTQkFrTmNDdXVFQXVfX1JpSGcvcGhvdG8vQUYxUWlwTThiQ0M1c3lXRHE1bjNfOXYyR21GVlFPN2p6cFNJSUZBY1pDSU0/a2V5PU5ERnljVTE2ZUV4TlNsODFkVXBSTFhBd1ZFdFdabXRGTWtodVgzVjMKCkEgaGVhdG1hcCBpcyB1c2VmdWwgaW4gdGhpcyBjYXNlIGJlY2F1c2UgdGhlIG5hbWUgZml0cyBwZXJmZWN0bHkgd2l0aCBteSBjYXNlIHN0dWR5IChnZXQgaXQsICJoZWF0IiAibWFwIiBvayBpbSBkb25lKSBhbmQgYmVjYXVzZSBpdHMgdXNlZnVsIGZvciBzZWVpbmcgd2hpY2ggYXJlYXMgaGFkIHRoZSBoaWdoZXN0IGNvbmNlbnRyYXRpb24gb2YgZmlyZSBpbmNpZGVudHMuCmBgYHtyfQojIyMjIyMjIyMjIyMjIyMjIyNIZWF0bWFwIyMjIyMjIyMjIyMjIyMjIyMjCiNjcmVhdGVkIGJ5IHVzaW5nIHRlY2huaXF1ZXMgZnJvbToKI2h0dHA6Ly90cnVjdmlldGxlLm1lL3IvdHV0b3JpYWwvMjAxNy8wMS8xOC9zcGF0aWFsLWhlYXQtbWFwLXBsb3R0aW5nLXVzaW5nLXIuaHRtbAoKI2ltcG9ydCBmaXJlIGRhdGEgaW4gLmNzdiBmb3JtYXQKZmlyZV9jc3YgPC0gcmVhZC5jc3YoIi9Vc2Vycy9rcmdyLmRmL0Rlc2t0b3AvR0VPRzIwOC9GaW5hbCBBc3NpZ25tZW50L0ZpcmUgRGF0YS9OQVNBIFZJSVJzIENTVi9maXJlX25ydF9WMV8zMjk4Ni5jc3YiKQoKI3NldCBtYXAgZXh0ZW50IGJ5IHRha2luZyBtZWFuIGxhdCBsb25nIG9mIGZpcmUgcG9pbnRzIChnZW5pdXMgbWV0aG9kIGNyZWF0ZWQgYnkgVHJ1YyBWaWV0KQptZWFuLmxvbmdpdHVkZSA8LSBtZWFuKGZpcmVfY3N2JGxvbmdpdHVkZSkKbWVhbi5sYXRpdHVkZSA8LSBtZWFuKGZpcmVfY3N2JGxhdGl0dWRlKQoKI2dldCBHb29nbGUgYmFzZW1hcAppZighcmVxdWlyZU5hbWVzcGFjZSgiZGV2dG9vbHMiKSkgaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKQpkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImRrYWhsZS9nZ21hcCIsIHJlZiA9ICJ0aWR5dXAiKQpyZWdpc3Rlcl9nb29nbGUoa2V5ID0gIkFJemFTeURwT2xlWjVzbTZqY3RzaDdmSFo4dlJLYW1jQ1czM25OTSIpCmFmZmVjdGVkX2FyZWEgPC0gZ2V0X21hcChsb2NhdGlvbiA9IGMobWVhbi5sb25naXR1ZGUsIG1lYW4ubGF0aXR1ZGUpLCB6b29tID0gOSwgc2NhbGUgPSAyKQphZmZlY3RlZF9hcmVhIDwtIGdnbWFwKGFmZmVjdGVkX2FyZWEsIGV4dGVudD0iZGV2aWNlIiwgbGVnZW5kPSJub25lIikKCiNjcmVhdGUgaGVhdG1hcCwgaW4tZGVwdGggZG9jdW1lbnRhdGlvbiBmcm9tIHdlYnNpdGUgbGlua2VkIGFib3ZlCmhlYXRtYXAxIDwtIGFmZmVjdGVkX2FyZWEgKyAKICAgICAgICAgICAgc3RhdF9kZW5zaXR5MmQoZGF0YT1maXJlX2NzdiwKICAgICAgICAgICAgICAgICBhZXMoeD1sb25naXR1ZGUsIHk9bGF0aXR1ZGUsIGZpbGw9Li5sZXZlbC4uLCBhbHBoYT0uLmxldmVsLi4pLCAKICAgICAgICAgICAgICAgICBnZW9tPSJwb2x5Z29uIikgKwogICAgICAgICAgICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPShicmV3ZXIucGFsKDcsICJZbE9yUmQiKSkpICsKICAgICAgICAgICAgZ3VpZGVzKHNpemU9RkFMU0UsIGFscGhhID0gRkFMU0UpCmhlYXRtYXAxCgojdHJhbnNmb3JtIHN0YXRpYyBnZ3Bsb3QoKSBoZWF0bWFwIHRvIGludGVyYWN0aXZlIG1hcCB1c2luZyBnZ3Bsb3RseSgpCmhlYXRtYXBseSA8LSBnZ3Bsb3RseShoZWF0bWFwMSkKaGVhdG1hcGx5CmBgYAoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjI0hlYXRtYXAjIyMjIyMjIyMjIyMjIyMjIyMKI2NyZWF0ZWQgYnkgdXNpbmcgdGVjaG5pcXVlcyBmcm9tOgojaHR0cDovL3RydWN2aWV0bGUubWUvci90dXRvcmlhbC8yMDE3LzAxLzE4L3NwYXRpYWwtaGVhdC1tYXAtcGxvdHRpbmctdXNpbmctci5odG1sCgojaW1wb3J0IGZpcmUgZGF0YSBpbiAuY3N2IGZvcm1hdApmaXJlX2NzdiA8LSByZWFkLmNzdigiL1VzZXJzL2tyZ3IuZGYvRGVza3RvcC9HRU9HMjA4L0ZpbmFsIEFzc2lnbm1lbnQvRmlyZSBEYXRhL05BU0EgVklJUnMgQ1NWL2ZpcmVfbnJ0X1YxXzMyOTg2LmNzdiIpCgojc2V0IG1hcCBleHRlbnQgYnkgdGFraW5nIG1lYW4gbGF0IGxvbmcgb2YgZmlyZSBwb2ludHMgKGdlbml1cyBtZXRob2QgY3JlYXRlZCBieSBUcnVjIFZpZXQpCm1lYW4ubG9uZ2l0dWRlIDwtIG1lYW4oZmlyZV9jc3YkbG9uZ2l0dWRlKQptZWFuLmxhdGl0dWRlIDwtIG1lYW4oZmlyZV9jc3YkbGF0aXR1ZGUpCgojZ2V0IEdvb2dsZSBiYXNlbWFwCmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJkZXZ0b29scyIpKSBpbnN0YWxsLnBhY2thZ2VzKCJkZXZ0b29scyIpCmRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiZGthaGxlL2dnbWFwIiwgcmVmID0gInRpZHl1cCIpCnJlZ2lzdGVyX2dvb2dsZShrZXkgPSAiQUl6YVN5RHBPbGVaNXNtNmpjdHNoN2ZIWjh2UkthbWNDVzMzbk5NIikKYWZmZWN0ZWRfYXJlYSA8LSBnZXRfbWFwKGxvY2F0aW9uID0gYyhtZWFuLmxvbmdpdHVkZSwgbWVhbi5sYXRpdHVkZSksIHpvb20gPSA5LCBzY2FsZSA9IDIpCmFmZmVjdGVkX2FyZWEgPC0gZ2dtYXAoYWZmZWN0ZWRfYXJlYSwgZXh0ZW50PSJkZXZpY2UiLCBsZWdlbmQ9Im5vbmUiKQoKI2NyZWF0ZSBoZWF0bWFwLCBpbi1kZXB0aCBkb2N1bWVudGF0aW9uIGZyb20gd2Vic2l0ZSBsaW5rZWQgYWJvdmUKaGVhdG1hcDEgPC0gYWZmZWN0ZWRfYXJlYSArIAogICAgICAgICAgICBzdGF0X2RlbnNpdHkyZChkYXRhPWZpcmVfY3N2LAogICAgICAgICAgICAgICAgIGFlcyh4PWxvbmdpdHVkZSwgeT1sYXRpdHVkZSwgZmlsbD0uLmxldmVsLi4sIGFscGhhPS4ubGV2ZWwuLiksIAogICAgICAgICAgICAgICAgIGdlb209InBvbHlnb24iKSArCiAgICAgICAgICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnM9KGJyZXdlci5wYWwoNywgIllsT3JSZCIpKSkgKwogICAgICAgICAgICBndWlkZXMoc2l6ZT1GQUxTRSwgYWxwaGEgPSBGQUxTRSkKaGVhdG1hcDEKCiN0cmFuc2Zvcm0gc3RhdGljIGdncGxvdCgpIGhlYXRtYXAgdG8gaW50ZXJhY3RpdmUgbWFwIHVzaW5nIGdncGxvdGx5KCkKaGVhdG1hcGx5IDwtIGdncGxvdGx5KGhlYXRtYXAxKQpoZWF0bWFwbHkKYGBgCgpUaGlzIGZpbmFsIG1hcCBpcyBhIEdJRiBzaG93aW5nIHNhdGVsbGl0ZSBpbWFnZXJ5IG9mIHRoZSBhcmVhIGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIGZpcmUsIHRoZSBmaXJlIHBvaW50cyBmcm9tIHRoZSBOQVNBIGRhdGFzZXQgYXJlIGFsc28gYWRkZWQgdG8gaGlnaGxpZ2h0IHdoaWNoIGFyZWFzIGhhZCBhIGhpZ2hlciBmaXJlIGluY2lkZW50IGZyZXF1ZW5jeS4gCmBgYHtyfQojY3JlYXRlZCBieSB1c2luZyBtYWdpY2sgcGFja2FnZSBzZWU6CiNodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbWFnaWNrL3ZpZ25ldHRlcy9pbnRyby5odG1sCiNzYXRlbGxpdGUgaW1hZ2VyeSAoU2VudGluZWwyKSBkb3dubG9hZGVkIGZyb20gRWFydGggRXhwbG9yZXI6CiNodHRwczovL2VhcnRoZXhwbG9yZXIudXNncy5nb3YKCiNjcmVhdGVkIGJ5IGN5Y2xpbmcgdGhyb3VnaCBzY3JlZW5zaG90dGVkIGltYWdlcyBmcm9tIFFHSVMKYmVmb3JlX2ZpcmUgPC0gaW1hZ2Vfc2NhbGUoaW1hZ2VfcmVhZCgiL1VzZXJzL2tyZ3IuZGYvRGVza3RvcC9TY3JlZW4gU2hvdCAyMDE4LTEyLTA0IGF0IDIuMjAuMDYgQU0ucG5nIiksICJ4NDUwIikKYmVmb3JlX3BvaW50cyA8LSBpbWFnZV9zY2FsZShpbWFnZV9yZWFkKCIvVXNlcnMva3Jnci5kZi9EZXNrdG9wL1NjcmVlbiBTaG90IDIwMTgtMTItMDQgYXQgMi4wNy4zNSBBTS5wbmciKSwgIng0NTAiKQp3aXRoX3BvaW50cyA8LSBpbWFnZV9zY2FsZShpbWFnZV9yZWFkKCIvVXNlcnMva3Jnci5kZi9EZXNrdG9wL1NjcmVlbiBTaG90IDIwMTgtMTItMDQgYXQgMi4wNy41MiBBTS5wbmciKSwgIng0NTAiKQpmcmFtZXMgPC0gaW1hZ2VfbW9ycGgoYyggYmVmb3JlX2ZpcmUsIHdpdGhfcG9pbnRzLCBiZWZvcmVfcG9pbnRzLCBiZWZvcmVfcG9pbnRzLCBiZWZvcmVfcG9pbnRzLCBiZWZvcmVfZmlyZSksIGZyYW1lcyA9IDI1KQppbWFnZV9hbmltYXRlKGZyYW1lcykKYGBgCkFOSU1BVEVEIE1BUCBIRVJFIChvcGVuIGxpbmsgaW4gbmV3IHRhYik6Cmh0dHBzOi8vcGhvdG9zLmdvb2dsZS5jb20vc2hhcmUvQUYxUWlwTlpOMmFJVW9yS1VZS01rTTVWYkxZb1dRVU5iWXZZbFl1YmJlTmdlaDVTRUlkZlNCQWtOY0N1dUVBdV9fUmlIZy9waG90by9BRjFRaXBOa3ZsUi1oakJZQ1RUYjRxWllTei1jTzVoYk5NMEdOT3NFUzJyUD9rZXk9TkRGeWNVMTZlRXhOU2w4MWRVcFJMWEF3VkV0V1ptdEZNa2h1WDNWMwoKTmV4dCBTdGVwczoKRm9yIHRoZSBuZXh0IHN0ZXBzIEkgcGxhbiBvbiBpbXBsZW1lbnRpbmcgb3RoZXIgZmFjdG9ycyBpbnRvIHRoZSBmaXJzdCBpbnRlcmFjdGl2ZSBtYXAgc3VjaCBhcyB3aW5kIHN0cmVuZ3RoIGFuZCBkaXJlY3Rpb24gKGVzcGVjaWFsbHkgdGhlIFNhbnRhIEFuYSB3aW5kcyksIGluZnJhc3RydWN0dXJlIHR5cGVzLCBhbmQgdmVnZXRhdGlvbi9sYW5kIHVzZSBkYXRhLiAKCgo=