1 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)

2 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")

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