Importing and Filtering
of Data and Shape Files
#Creating a reference map using the Philly shooting data set
#Import Shape Data
shootingMap <- st_read("https://tkelleman.github.io/tkweb/Week8/shootings.geojson")
Reading layer `shootings' from data source
`https://tkelleman.github.io/tkweb/Week8/shootings.geojson'
using driver `GeoJSON'
replacing null geometries with empty geometries
Simple feature collection with 15577 features and 21 fields (with 30 geometries empty)
Geometry type: POINT
Dimension: XY
Bounding box: xmin: -75.27362 ymin: 39.87799 xmax: -74.95936 ymax: 40.13117
Geodetic CRS: WGS 84
neighborhoodMap <- st_read("https://tkelleman.github.io/tkweb/Week8/philadelphiaNeighborhoods.geojson")
Reading layer `philadelphiaNeighborhoods' from data source
`https://tkelleman.github.io/tkweb/Week8/philadelphiaNeighborhoods.geojson'
using driver `GeoJSON'
Simple feature collection with 158 features and 8 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -75.28027 ymin: 39.867 xmax: -74.95576 ymax: 40.13799
Geodetic CRS: WGS 84
#Read the Philly Crime data
phillyCrime <- na.omit(read.csv("https://tkelleman.github.io/tkweb/Week7/PhillyCrimeSince2015.csv"))
phillyCrime$name = toupper(gsub("-", "_", phillyCrime$neighborhood))
#Extract Year
y <- mdy_hm(phillyCrime$date)
phillyCrime$year <- year(y)
#Locations of Points on Map
dplotloc = st_as_sf(data.frame(x = -75.3677, y = 39.9168),
coords = c("x", "y"),
crs = 4326)
rplotloc = st_as_sf(data.frame(x = -75.3477, y = 39.9168),
coords = c("x", "y"),
crs = 4326)
Data Processing
In the code chunk above, spatial data for shootings and neighborhoods
in Philadelphia were imported using the st_read function from GeoJSON
files hosted on GitHub. The Philadelphia crime dataset since 2015 was
then read from a CSV file, omitting any missing values, and the
neighborhood names were standardized by converting them to uppercase and
replacing hyphens with underscores. Additionally, the date column from
the crime dataset was parsed to extract the year, which was added as a
new column. Finally, two points were defined using specific longitude
and latitude coordinates to represent locations on the map, and these
were converted into simple feature objects to be used as buttons to show
the ridgeline and density plots.
#Create Density Plot
dplot<-ggplot(phillyCrime, aes(x = age, color = race)) +
geom_density() +
labs(title = "Density Plot of Age by Race", x = "Age", y = "Density", fill="Race")
#Save Ridgeline Plot
ggsave(filename="dplot.png", plot=dplot)
#Create Ridgeline Plot
rplot<-ggplot(phillyCrime, aes(x = age, y = race, fill = race)) +
geom_density_ridges() +
labs(title = "Ridgeline Plot of Philadelphia Crime by Race", subtitle = "Age distribution by race", x = "Age", y = "Race") +
theme(legend.position = "none")
#Save Ridgeline Plot
ggsave(filename="rplot.png", plot=rplot)
# Import Pictures of Plots as PNG
dplot="https://tkelleman.github.io/tkweb/Week8/dplot.png"
rplot="https://tkelleman.github.io/tkweb/Week8/rplot.png"
# Define the style for the map title
style <- "position: fixed; top: 10px; left: 50%; transform: translateX(-50%);
background-color: rgba(135, 206, 235, 0.75); color: white;
padding: 5px; font-size: 18px; z-index: 400;"
map_title <- tags$div(style = style, "Map of Philadelpia Crime by Neighborhood")
#Generate Leaflet Map
leaflet() %>%
setView(lng=-75.15092, lat=40.00995, zoom = 11) %>%
addProviderTiles(providers$CartoDB.DarkMatter, group="DarkLabel") %>%
addProviderTiles(providers$CartoDB.DarkMatterNoLabels, group="Dark") %>%
addProviderTiles(providers$Esri.NatGeoWorldMap, group="Esri") %>%
addControl(map_title, position = "topleft", className="map-title")%>%
addMiniMap() %>%
addPolygons(data = neighborhoodMap,
color = 'skyblue',
weight = 1) %>%
addCircleMarkers(data = phillyCrime,
radius = ~ifelse(fatal == "Fatal", 5, 3),
stroke = FALSE,
fillOpacity = 0.5,
clusterOptions = markerClusterOptions(maxClusterRadius = 40))%>%
addLayersControl(baseGroups = c('Dark', 'DarkLabel', 'Esri'),
overlayGroups = c("Crime Data"))%>%
addCircleMarkers(data = dplotloc,
color = "skyblue",
weight = 2,
label = "Density Plot by Race",
stroke = FALSE,
fillOpacity = 0.95,
group = "dplotloc") %>%
addPopupImages(dplot,
width = 500,
height = 350,
tooltip = FALSE,
group = "dplotloc")%>%
addCircleMarkers(data = rplotloc,
color = "blue",
weight = 2,
label = "Ridgeline Plot by Race",
stroke = FALSE,
fillOpacity = 0.95,
group = "rplotloc") %>%
addPopupImages(rplot,
width = 500,
height = 350,
tooltip = FALSE,
group = "rplotloc")
Interactive Map of
Philadelphia Crime
The code chunk above creates two types of plots from the phillyCrime
dataset: a density plot and a ridgeline plot, both based on the age
distribution of different races in the phillyCrime datase and saves the
plots as a PNG image to be hosted on GitHub. An interactive Leaflet map
centered on Philadelphia is created with layers for dark, dark with
labels, and standard ESRI basemap.
This interactive leaflet
map shows crimes and neighborhoods the Philadelphia region. As the user
zooms in the markers show crimes committed in smaller sections based on
the coordinates in the dataset. From this map it could be interpreted
which neighborhoods in the Philadelphia region have higher or lower
crime rates. This could potentially be beneficial for first responder
resource allocation, prevention strategy implementation, property
valuation, and many other uses. Selecting the sky-blue marker pulls up
the density plot of age by race in the dataset. The blue marker pulls up
the ridgeline plot of Philadelphia crime by race in the dataset. Both of
these dataset show similar trends. From these plots, it is ages 20-40
make up the majority of crimes in the set.
LS0tDQp0aXRsZTogIldlZWsgOCAtIE1vcmUgUiBNYXBzIGFuZCBDYXNlIFN0dWR5Ig0KYXV0aG9yOiAiVGltIEtlbGxlbWFuIg0KZGF0ZTogIjIwMjQtMDMtMjEiDQoNCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiBubw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgZmlnX3dpZHRoOiA4DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jX2NvbGxhcHNlZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgDQogIHBkZl9kb2N1bWVudDogDQogICAgdG9jOiBubw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogNQ0KICAgIGZpZ19oZWlnaHQ6IDQNCi0tLQ0KDQpgYGB7PWh0bWx9DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQpkaXYjVE9DIGxpIHsNCiAgICBsaXN0LXN0eWxlOm5vbmU7DQogICAgYmFja2dyb3VuZC1jb2xvcjpsaWdodGdyYXk7DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KICAgIGZvbnQtZmFtaWx5OiBBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmOw0KICAgIGNvbG9yOiAjNzgwYzBjOw0KfQ0KDQovKiBtb3VzZSBvdmVyIGxpbmsgKi8NCmRpdiNUT0MgYTpob3ZlciB7DQogIGNvbG9yOiByZWQ7DQp9DQoNCi8qIHVudmlzaXRlZCBsaW5rICovDQpkaXYjVE9DIGE6bGluayB7DQogIGNvbG9yOiBibHVlOw0KfQ0KDQoNCg0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDI0cHg7DQogIGNvbG9yOiBEYXJrYmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogQXJpYWwsIEhlbHZldGljYSwgc2Fucy1zZXJpZjsNCiAgZm9udC12YXJpYW50LWNhcHM6IG5vcm1hbDsNCn0NCmg0LmF1dGhvciB7IA0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5kYXRlIHsgDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDEgew0KICAgIGZvbnQtc2l6ZTogMjRweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMiB7DQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgDQogICAgZm9udC1zaXplOiAxNXB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KLyogdW52aXNpdGVkIGxpbmsgKi8NCmE6bGluayB7DQogIGNvbG9yOiBncmVlbjsNCn0NCg0KLyogdmlzaXRlZCBsaW5rICovDQphOnZpc2l0ZWQgew0KICBjb2xvcjogZ3JlZW47DQp9DQoNCi8qIG1vdXNlIG92ZXIgbGluayAqLw0KYTpob3ZlciB7DQogIGNvbG9yOiByZWQ7DQp9DQoNCi8qIHNlbGVjdGVkIGxpbmsgKi8NCmE6YWN0aXZlIHsNCiAgY29sb3I6IHllbGxvdzsNCn0NCjwvc3R5bGU+DQpgYGANCi0tLQ0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCm9wdGlvbnMocmVwb3MgPSBsaXN0KENSQU49Imh0dHA6Ly9jcmFuLnJzdHVkaW8uY29tLyIpKQ0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiAgIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJjb3dwbG90IikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImNvd3Bsb3QiKQ0KICAgbGlicmFyeShjb3dwbG90KQ0KfQ0KaWYgKCFyZXF1aXJlKCJsYXRleDJleHAiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygibGF0ZXgyZXhwIikNCiAgIGxpYnJhcnkobGF0ZXgyZXhwKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikNCiAgIGxpYnJhcnkocGxvdGx5KQ0KfQ0KaWYgKCFyZXF1aXJlKCJnYXBtaW5kZXIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiZ2FwbWluZGVyIikNCiAgIGxpYnJhcnkoZ2FwbWluZGVyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwbmciKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoInBuZyIpICAgICAgICAgICAgICMgSW5zdGFsbCBwbmcgcGFja2FnZQ0KICAgIGxpYnJhcnkoInBuZyIpDQp9DQppZiAoIXJlcXVpcmUoIlJDdXJsIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJSQ3VybCIpICAgICAgICAgICAjIEluc3RhbGwgUkN1cmwgcGFja2FnZQ0KICAgIGxpYnJhcnkoIlJDdXJsIikNCn0NCmlmICghcmVxdWlyZSgiY29sb3VycGlja2VyIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJjb2xvdXJwaWNrZXIiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiY29sb3VycGlja2VyIikNCn0NCmlmICghcmVxdWlyZSgiZ2lmc2tpIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnaWZza2kiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ2lmc2tpIikNCn0NCmlmICghcmVxdWlyZSgibWFnaWNrIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJtYWdpY2siKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgibWFnaWNrIikNCn0NCmlmICghcmVxdWlyZSgiZ3JEZXZpY2VzIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnckRldmljZXMiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ3JEZXZpY2VzIikNCn0NCiMjIyBnZ3Bsb3QgYW5kIGV4dGVuc2lvbnMNCmlmICghcmVxdWlyZSgiZ2dwbG90MiIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJnZ3Bsb3QyIikNCn0NCmlmICghcmVxdWlyZSgiZ2dhbmltYXRlIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnZ2FuaW1hdGUiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ2dhbmltYXRlIikNCn0NCmlmICghcmVxdWlyZSgiZ2dyaWRnZXMiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImdncmlkZ2VzIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdncmlkZ2VzIikNCn0NCmlmICghcmVxdWlyZSgiZ3JhcGhpY3MiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImdyYXBoaWNzIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdyYXBoaWNzIikNCn0NCmlmICghcmVxdWlyZSgiZHBseXIiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImRwbHlyIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImRwbHlyIikNCn0NCmlmICghcmVxdWlyZSgibHVicmlkYXRlIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJsdWJyaWRhdGUiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgibHVicmlkYXRlIikNCn0NCmlmICghcmVxdWlyZSgidG1hcCIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygidG1hcCIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJ0bWFwIikNCn0NCmlmICghcmVxdWlyZSgic2YiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoInNmIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoInNmIikNCn0NCg0KaWYgKCFyZXF1aXJlKCJsZWFmbGV0IikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJsZWFmbGV0IikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImxlYWZsZXQiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJsZWFmcG9wIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJsZWFmcG9wIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImxlYWZwb3AiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJodG1sdG9vbHMiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImh0bWx0b29scyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJodG1sdG9vbHMiKQ0KfQ0KDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBUUlVFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkEpDQpgYGANCiMgSW1wb3J0aW5nIGFuZCBGaWx0ZXJpbmcgb2YgRGF0YSBhbmQgU2hhcGUgRmlsZXMNCmBgYHtyIGV2YWw9VFJVRX0NCiNDcmVhdGluZyBhIHJlZmVyZW5jZSBtYXAgdXNpbmcgdGhlIFBoaWxseSBzaG9vdGluZyBkYXRhIHNldA0KI0ltcG9ydCBTaGFwZSBEYXRhDQpzaG9vdGluZ01hcCA8LSBzdF9yZWFkKCJodHRwczovL3RrZWxsZW1hbi5naXRodWIuaW8vdGt3ZWIvV2Vlazgvc2hvb3RpbmdzLmdlb2pzb24iKQ0KbmVpZ2hib3Job29kTWFwICA8LSBzdF9yZWFkKCJodHRwczovL3RrZWxsZW1hbi5naXRodWIuaW8vdGt3ZWIvV2VlazgvcGhpbGFkZWxwaGlhTmVpZ2hib3Job29kcy5nZW9qc29uIikNCg0KI1JlYWQgdGhlIFBoaWxseSBDcmltZSBkYXRhDQpwaGlsbHlDcmltZSA8LSBuYS5vbWl0KHJlYWQuY3N2KCJodHRwczovL3RrZWxsZW1hbi5naXRodWIuaW8vdGt3ZWIvV2VlazcvUGhpbGx5Q3JpbWVTaW5jZTIwMTUuY3N2IikpDQpwaGlsbHlDcmltZSRuYW1lID0gdG91cHBlcihnc3ViKCItIiwgIl8iLCBwaGlsbHlDcmltZSRuZWlnaGJvcmhvb2QpKSANCiNFeHRyYWN0IFllYXINCnkgPC0gbWR5X2htKHBoaWxseUNyaW1lJGRhdGUpDQpwaGlsbHlDcmltZSR5ZWFyIDwtIHllYXIoeSkNCg0KI0xvY2F0aW9ucyBvZiBQb2ludHMgb24gTWFwDQpkcGxvdGxvYyA9IHN0X2FzX3NmKGRhdGEuZnJhbWUoeCA9IC03NS4zNjc3LCB5ID0gMzkuOTE2OCksDQogICAgICAgICAgICAgICAgY29vcmRzID0gYygieCIsICJ5IiksDQogICAgICAgICAgICAgICAgIGNycyA9IDQzMjYpDQpycGxvdGxvYyA9IHN0X2FzX3NmKGRhdGEuZnJhbWUoeCA9IC03NS4zNDc3LCB5ID0gMzkuOTE2OCksDQogICAgICAgICAgICAgICAgY29vcmRzID0gYygieCIsICJ5IiksDQogICAgICAgICAgICAgICAgY3JzID0gNDMyNikNCmBgYA0KIyBEYXRhIFByb2Nlc3NpbmcNCkluIHRoZSBjb2RlIGNodW5rIGFib3ZlLCBzcGF0aWFsIGRhdGEgZm9yIHNob290aW5ncyBhbmQgbmVpZ2hib3Job29kcyBpbiBQaGlsYWRlbHBoaWEgd2VyZSBpbXBvcnRlZCB1c2luZyB0aGUgc3RfcmVhZCBmdW5jdGlvbiBmcm9tIEdlb0pTT04gZmlsZXMgaG9zdGVkIG9uIEdpdEh1Yi4gVGhlIFBoaWxhZGVscGhpYSBjcmltZSBkYXRhc2V0IHNpbmNlIDIwMTUgd2FzIHRoZW4gcmVhZCBmcm9tIGEgQ1NWIGZpbGUsIG9taXR0aW5nIGFueSBtaXNzaW5nIHZhbHVlcywgYW5kIHRoZSBuZWlnaGJvcmhvb2QgbmFtZXMgd2VyZSBzdGFuZGFyZGl6ZWQgYnkgY29udmVydGluZyB0aGVtIHRvIHVwcGVyY2FzZSBhbmQgcmVwbGFjaW5nIGh5cGhlbnMgd2l0aCB1bmRlcnNjb3Jlcy4gQWRkaXRpb25hbGx5LCB0aGUgZGF0ZSBjb2x1bW4gZnJvbSB0aGUgY3JpbWUgZGF0YXNldCB3YXMgcGFyc2VkIHRvIGV4dHJhY3QgdGhlIHllYXIsIHdoaWNoIHdhcyBhZGRlZCBhcyBhIG5ldyBjb2x1bW4uIEZpbmFsbHksIHR3byBwb2ludHMgd2VyZSBkZWZpbmVkIHVzaW5nIHNwZWNpZmljIGxvbmdpdHVkZSBhbmQgbGF0aXR1ZGUgY29vcmRpbmF0ZXMgdG8gcmVwcmVzZW50IGxvY2F0aW9ucyBvbiB0aGUgbWFwLCBhbmQgdGhlc2Ugd2VyZSBjb252ZXJ0ZWQgaW50byBzaW1wbGUgZmVhdHVyZSBvYmplY3RzIHRvIGJlIHVzZWQgYXMgYnV0dG9ucyB0byBzaG93IHRoZSByaWRnZWxpbmUgYW5kIGRlbnNpdHkgcGxvdHMuIDxicj4NCg0KYGBge3IgZXZhbD1UUlVFfQ0KI0NyZWF0ZSBEZW5zaXR5IFBsb3QNCmRwbG90PC1nZ3Bsb3QocGhpbGx5Q3JpbWUsIGFlcyh4ID0gYWdlLCBjb2xvciA9IHJhY2UpKSArDQogIGdlb21fZGVuc2l0eSgpICsNCiAgbGFicyh0aXRsZSA9ICJEZW5zaXR5IFBsb3Qgb2YgQWdlIGJ5IFJhY2UiLCB4ID0gIkFnZSIsIHkgPSAiRGVuc2l0eSIsIGZpbGw9IlJhY2UiKSAgDQojU2F2ZSBSaWRnZWxpbmUgUGxvdA0KZ2dzYXZlKGZpbGVuYW1lPSJkcGxvdC5wbmciLCBwbG90PWRwbG90KQ0KDQojQ3JlYXRlIFJpZGdlbGluZSBQbG90DQpycGxvdDwtZ2dwbG90KHBoaWxseUNyaW1lLCBhZXMoeCA9IGFnZSwgeSA9IHJhY2UsIGZpbGwgPSByYWNlKSkgKw0KICBnZW9tX2RlbnNpdHlfcmlkZ2VzKCkgKw0KICBsYWJzKHRpdGxlID0gIlJpZGdlbGluZSBQbG90IG9mIFBoaWxhZGVscGhpYSBDcmltZSBieSBSYWNlIiwgc3VidGl0bGUgPSAiQWdlIGRpc3RyaWJ1dGlvbiBieSByYWNlIiwgeCA9ICJBZ2UiLCB5ID0gIlJhY2UiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCiNTYXZlIFJpZGdlbGluZSBQbG90DQpnZ3NhdmUoZmlsZW5hbWU9InJwbG90LnBuZyIsIHBsb3Q9cnBsb3QpICANCg0KIyBJbXBvcnQgUGljdHVyZXMgb2YgUGxvdHMgYXMgUE5HDQpkcGxvdD0iaHR0cHM6Ly90a2VsbGVtYW4uZ2l0aHViLmlvL3Rrd2ViL1dlZWs4L2RwbG90LnBuZyINCnJwbG90PSJodHRwczovL3RrZWxsZW1hbi5naXRodWIuaW8vdGt3ZWIvV2VlazgvcnBsb3QucG5nIg0KDQoNCiMgRGVmaW5lIHRoZSBzdHlsZSBmb3IgdGhlIG1hcCB0aXRsZQ0Kc3R5bGUgPC0gInBvc2l0aW9uOiBmaXhlZDsgdG9wOiAxMHB4OyBsZWZ0OiA1MCU7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtNTAlKTsNCiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDEzNSwgMjA2LCAyMzUsIDAuNzUpOyBjb2xvcjogd2hpdGU7DQogICAgICAgICAgcGFkZGluZzogNXB4OyBmb250LXNpemU6IDE4cHg7IHotaW5kZXg6IDQwMDsiDQptYXBfdGl0bGUgPC0gdGFncyRkaXYoc3R5bGUgPSBzdHlsZSwgIk1hcCBvZiBQaGlsYWRlbHBpYSBDcmltZSBieSBOZWlnaGJvcmhvb2QiKQ0KDQojR2VuZXJhdGUgTGVhZmxldCBNYXANCmxlYWZsZXQoKSAlPiUNCiAgc2V0Vmlldyhsbmc9LTc1LjE1MDkyLCBsYXQ9NDAuMDA5OTUsIHpvb20gPSAxMSkgJT4lDQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuRGFya01hdHRlciwgZ3JvdXA9IkRhcmtMYWJlbCIpICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLkRhcmtNYXR0ZXJOb0xhYmVscywgZ3JvdXA9IkRhcmsiKSAlPiUgIA0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRFc3JpLk5hdEdlb1dvcmxkTWFwLCBncm91cD0iRXNyaSIpICU+JQ0KICBhZGRDb250cm9sKG1hcF90aXRsZSwgcG9zaXRpb24gPSAidG9wbGVmdCIsIGNsYXNzTmFtZT0ibWFwLXRpdGxlIiklPiUNCiAgYWRkTWluaU1hcCgpICU+JQ0KICBhZGRQb2x5Z29ucyhkYXRhID0gbmVpZ2hib3Job29kTWFwLA0KICAgICAgICAgICAgICBjb2xvciA9ICdza3libHVlJywNCiAgICAgICAgICAgICAgd2VpZ2h0ID0gMSkgICU+JQ0KICBhZGRDaXJjbGVNYXJrZXJzKGRhdGEgPSBwaGlsbHlDcmltZSwNCiAgICAgICAgICAgICAgICAgICByYWRpdXMgPSB+aWZlbHNlKGZhdGFsID09ICJGYXRhbCIsIDUsIDMpLA0KICAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDAuNSwNCiAgICAgICAgICAgICAgICAgICBjbHVzdGVyT3B0aW9ucyA9IG1hcmtlckNsdXN0ZXJPcHRpb25zKG1heENsdXN0ZXJSYWRpdXMgPSA0MCkpJT4lDQogIGFkZExheWVyc0NvbnRyb2woYmFzZUdyb3VwcyA9IGMoJ0RhcmsnLCAnRGFya0xhYmVsJywgJ0VzcmknKSwNCiAgICAgICAgICAgICAgICAgICBvdmVybGF5R3JvdXBzID0gYygiQ3JpbWUgRGF0YSIpKSU+JQ0KICBhZGRDaXJjbGVNYXJrZXJzKGRhdGEgPSBkcGxvdGxvYywgDQogICAgICAgICAgICAgICAgICBjb2xvciA9ICJza3libHVlIiwNCiAgICAgICAgICAgICAgICAgIHdlaWdodCA9IDIsDQogICAgICAgICAgICAgICAgICBsYWJlbCA9ICJEZW5zaXR5IFBsb3QgYnkgUmFjZSIsDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDAuOTUsDQogICAgICAgICAgICAgICAgICBncm91cCA9ICJkcGxvdGxvYyIpICU+JQ0KICBhZGRQb3B1cEltYWdlcyhkcGxvdCwgDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDUwMCwNCiAgICAgICAgICAgICAgICAgIGhlaWdodCA9IDM1MCwNCiAgICAgICAgICAgICAgICAgIHRvb2x0aXAgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgIGdyb3VwID0gImRwbG90bG9jIiklPiUNCiAgYWRkQ2lyY2xlTWFya2VycyhkYXRhID0gcnBsb3Rsb2MsIA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmx1ZSIsDQogICAgICAgICAgICAgICAgICB3ZWlnaHQgPSAyLA0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSAiUmlkZ2VsaW5lIFBsb3QgYnkgUmFjZSIsDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDAuOTUsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAicnBsb3Rsb2MiKSAlPiUNCiAgYWRkUG9wdXBJbWFnZXMocnBsb3QsIA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSA1MDAsDQogICAgICAgICAgICAgICAgICBoZWlnaHQgPSAzNTAsDQogICAgICAgICAgICAgICAgICB0b29sdGlwID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICBncm91cCA9ICJycGxvdGxvYyIpDQpgYGANCiMgSW50ZXJhY3RpdmUgTWFwIG9mIFBoaWxhZGVscGhpYSBDcmltZQ0KVGhlIGNvZGUgY2h1bmsgYWJvdmUgY3JlYXRlcyB0d28gdHlwZXMgb2YgcGxvdHMgZnJvbSB0aGUgcGhpbGx5Q3JpbWUgZGF0YXNldDogYSBkZW5zaXR5IHBsb3QgYW5kIGEgcmlkZ2VsaW5lIHBsb3QsIGJvdGggYmFzZWQgb24gdGhlIGFnZSBkaXN0cmlidXRpb24gb2YgZGlmZmVyZW50IHJhY2VzIGluIHRoZSBwaGlsbHlDcmltZSBkYXRhc2UgYW5kIHNhdmVzIHRoZSBwbG90cyBhcyBhIFBORyBpbWFnZSB0byBiZSBob3N0ZWQgb24gR2l0SHViLiBBbiBpbnRlcmFjdGl2ZSBMZWFmbGV0IG1hcCBjZW50ZXJlZCBvbiBQaGlsYWRlbHBoaWEgaXMgY3JlYXRlZCB3aXRoIGxheWVycyBmb3IgZGFyaywgZGFyayB3aXRoIGxhYmVscywgYW5kIHN0YW5kYXJkIEVTUkkgYmFzZW1hcC4gPGJyPiA8YnI+DQpUaGlzIGludGVyYWN0aXZlIGxlYWZsZXQgbWFwIHNob3dzIGNyaW1lcyBhbmQgbmVpZ2hib3Job29kcyB0aGUgUGhpbGFkZWxwaGlhIHJlZ2lvbi4gQXMgdGhlIHVzZXIgem9vbXMgaW4gdGhlIG1hcmtlcnMgc2hvdyBjcmltZXMgY29tbWl0dGVkIGluIHNtYWxsZXIgc2VjdGlvbnMgYmFzZWQgb24gdGhlIGNvb3JkaW5hdGVzIGluIHRoZSBkYXRhc2V0LiBGcm9tIHRoaXMgbWFwIGl0IGNvdWxkIGJlIGludGVycHJldGVkIHdoaWNoIG5laWdoYm9yaG9vZHMgaW4gdGhlIFBoaWxhZGVscGhpYSByZWdpb24gaGF2ZSBoaWdoZXIgb3IgbG93ZXIgY3JpbWUgcmF0ZXMuIFRoaXMgY291bGQgcG90ZW50aWFsbHkgYmUgYmVuZWZpY2lhbCBmb3IgZmlyc3QgcmVzcG9uZGVyIHJlc291cmNlIGFsbG9jYXRpb24sIHByZXZlbnRpb24gc3RyYXRlZ3kgaW1wbGVtZW50YXRpb24sIHByb3BlcnR5IHZhbHVhdGlvbiwgYW5kIG1hbnkgb3RoZXIgdXNlcy4gIFNlbGVjdGluZyB0aGUgc2t5LWJsdWUgbWFya2VyIHB1bGxzIHVwIHRoZSBkZW5zaXR5IHBsb3Qgb2YgYWdlIGJ5IHJhY2UgaW4gdGhlIGRhdGFzZXQuIFRoZSBibHVlIG1hcmtlciBwdWxscyB1cCB0aGUgcmlkZ2VsaW5lIHBsb3Qgb2YgUGhpbGFkZWxwaGlhIGNyaW1lIGJ5IHJhY2UgaW4gdGhlIGRhdGFzZXQuIEJvdGggb2YgdGhlc2UgZGF0YXNldCBzaG93IHNpbWlsYXIgdHJlbmRzLiBGcm9tIHRoZXNlIHBsb3RzLCBpdCBpcyBhZ2VzIDIwLTQwIG1ha2UgdXAgdGhlIG1ham9yaXR5IG9mIGNyaW1lcyBpbiB0aGUgc2V0LiAgDQoNCg==