library(leaflet)
package 㤼㸱leaflet㤼㸲 was built under R version 4.0.4Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages -------------------------------------------------------------------- tidyverse 1.3.0 --
v ggplot2 3.3.3     v purrr   0.3.4
v tibble  3.1.0     v dplyr   1.0.4
v tidyr   1.1.3     v stringr 1.4.0
v readr   1.4.0     v forcats 0.5.1
package 㤼㸱tidyr㤼㸲 was built under R version 4.0.4-- Conflicts ----------------------------------------------------------------------- tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(lubridate)
package 㤼㸱lubridate㤼㸲 was built under R version 4.0.4
Attaching package: 㤼㸱lubridate㤼㸲

The following objects are masked from 㤼㸱package:base㤼㸲:

    date, intersect, setdiff, union
#library(htmltools)
library(broom)
library(plotly)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     

Attaching package: 㤼㸱plotly㤼㸲

The following object is masked from 㤼㸱package:ggplot2㤼㸲:

    last_plot

The following object is masked from 㤼㸱package:stats㤼㸲:

    filter

The following object is masked from 㤼㸱package:graphics㤼㸲:

    layout
library(DT)
leaflet() %>%
  addTiles()
NA

MAPS AND MASS SHOOTINGS

In this analysis we will take a look at mapping the center of the continental United States as well as where mass shootings occur in the United States.

First we will begin with locating the center of the continental United States. According to Wikipedia the center is located at 44 58’02“N, 103 46’18”W. The center is located just north of Belle Fourche, South Dakota.

44.68 -103.86

58/60
[1] 0.9666667
46/60
[1] 0.7666667
leaflet() %>%
  addTiles() %>%
  setView(lat = 44.68, lng = -103.86, zoom = 11) %>%
  addMarkers(lat = 44.68, lng = -103.86)
NA
NA
NA
NA
shootings <- read_csv("https://docs.google.com/spreadsheets/d/1b9o6uDO18sLxBqPwl_Gh9bnhW-ev_dABH83M5Vb5L8o/export?format=csv", na = "-")
Duplicated column names deduplicated: 'location' => 'location_1' [8]
-- Column specification -------------------------------------------------------------------------------------
cols(
  .default = col_character(),
  fatalities = col_double(),
  injured = col_double(),
  total_victims = col_double(),
  age_of_shooter = col_double(),
  latitude = col_double(),
  longitude = col_double(),
  year = col_double()
)
i Use `spec()` for the full column specifications.

Next we will view where shooting incidents have taken place throughout the continental United States. The dot size indicates the size of the incident. The map shows that mass shootings are widely spread in the United States.

shootings %>% 
  leaflet() %>% 
  addTiles() %>%
  setView(lat = 44.68, lng = -103.86, zoom = 4) %>%
  addCircleMarkers(stroke = F, fillOpacity = .6, radius = ~log(total_victims))
Assuming "longitude" and "latitude" are longitude and latitude, respectively

There is a median of 10 total victims per incident as well as a median of 6 total fatalities per incident.

shootings %>% 
  drop_na(total_victims) %>% 
  summarize(median_total_victims = median(total_victims))
shootings %>% 
  drop_na(fatalities) %>% 
  summarize(median_fatalities = median(fatalities))
shootings %>% 
  plot_ly(x = ~fatalities) %>% 
  add_histogram(nbinsx = 40)
NA

The following data table is a list of incidents and includes such information as what happened, where it happened, when it happened, how many total victims, total fatalities, and total number of injured. Our most recent mass shooting occurred in Boulder, Colorado on March 22, 2021.

shootings %>%
  select(case, location, date, fatalities, total_victims, injured) %>%
  datatable()

In the following graphs, you can see who is the perpetrator in these incidents.These grapsh show that mass shootings are mainly committed by white, middle-aged, males.

shootings %>% 
  drop_na(race) %>% 
  mutate(race = as_factor(race)) %>% 
  mutate(race = fct_collapse(race,
                             White = c("White", "white"),
                             Black = c("Black", "black"),
                             Other = c("Other", "unclear"))) %>% 
  count(race)
shootings %>% 
  drop_na(race) %>% 
  mutate(race = as_factor(race)) %>% 
  mutate(race = fct_collapse(race,
                             White = c("White", "white"),
                             Black = c("Black", "black"),
                             Other = c("Other", "unclear"))) %>% 
  mutate(gender = fct_collapse(gender,
                             Female = c("Female", "F"),
                             Male = c("Male", "M"),
                             Other = c("Male & Female"))) %>% 
  plot_ly(x = ~gender, y = ~race) %>%
  add_histogram2dcontour()
NA
shootings %>%
  plot_ly(x = ~age_of_shooter, y = ~gender) %>%
  mutate(gender = fct_collapse(gender,
                             Female = c("Female", "F"),
                             Male = c("Male", "M"),
                             Other = c("Male & Female"))) %>% 
  add_histogram2dcontour()

Next we will show how many injuries versus fatalities there were in these shootings.

fatalities_data <- shootings %>%                                       # start with the shootings data
  filter(fatalities > 3) %>% 
  group_by(year) %>%                                                   # we're going to count by year
  summarize(count = n(), fatalities = sum(fatalities)) %>%             # get the total number of fatalities per year
  mutate(fatalities_per_incident = fatalities/count)                   # divide by the number of shooting incidents

fatalities_data
fatalities_per_incident_model <- lm(fatalities_per_incident ~ year, data = fatalities_data)
fatalities_per_incident_model

Call:
lm(formula = fatalities_per_incident ~ year, data = fatalities_data)

Coefficients:
(Intercept)         year  
  -67.11301      0.03765  
tidy(fatalities_per_incident_model)
glance(fatalities_per_incident_model)
injuries_data <- shootings %>%                                       # start with the shootings data
  filter(injured > 3) %>% 
  group_by(year) %>%                                                   # we're going to count by year
  summarize(count = n(), injured = sum(injured)) %>%             # get the total number of fatalities per year
  mutate(injuries_per_incident = injured/count) 
 

injuries_data
injuries_per_incident_ <- lm(injuries_per_incident ~ year, data = injuries_data)
injuries_per_incident_

Call:
lm(formula = injuries_per_incident ~ year, data = injuries_data)

Coefficients:
(Intercept)         year  
 -1558.1211       0.7875  
tidy(injuries_per_incident_)
glance(injuries_per_incident_)

You can see in the next two graphs that the number of fatalites and the number of injured has risen slightly through the years.

fatalities_data %>% 
  plot_ly(x = ~year, 
          y = ~fatalities,
          hoverinfo = "text",
          text = ~paste("Fatalities",
                        round(fatalities_per_incident, 1), "<br>", "Year: ", year)) %>% 
  add_markers(showlegend = F, ) %>%
  add_lines(y = ~fitted(fatalities_per_incident_model)) %>%
  layout(title = "Number of Fatalities",
   xaxis = list(title = "Year"),
   yaxis = list(title = "Fatalities"))
NA
injuries_data %>% 
  plot_ly(x = ~year, 
          y = ~injured,
          hoverinfo = "text",
          text = ~paste("Number of Injured ",
                        round(injuries_per_incident, 1), "<br>", "Year: ", year)) %>% 
  add_markers(showlegend = F, ) %>%
  add_lines(y = ~fitted(injuries_per_incident_)) %>%
  layout(title = "Number of Injured",
   xaxis = list(title = "Year"),
   yaxis = list(title = "Injured"))
NA

Finally, we will look at the number of mass shooting incidents per year. In the last graph, it shows that the number of mass shootings has increased steadily over time.

num_per_year <- shootings %>% 
  filter(fatalities > 3) %>% 
  count(year)

num_per_year
shootings_per_year_model <- lm(n ~ year, data = num_per_year)
tidy(shootings_per_year_model)
glance(shootings_per_year_model)
NA
NA
shootings_per_year_model

Call:
lm(formula = n ~ year, data = num_per_year)

Coefficients:
(Intercept)         year  
 -191.32228      0.09692  

num_per_year %>% 
  plot_ly(x = ~year, 
          y = ~shootings_per_year_model,
          hoverinfo = "text",
          text = ~paste("Shootings Per Year: ",
                      (shootings_per_year_model), "<br>", "Year: ", year)) %>% 
  add_markers(showlegend = F, ) %>%
  add_lines(y = ~fitted(shootings_per_year_model)) %>%
  layout(title = "Number of Shootings by Year",
   xaxis = list(title = "Year"),
   yaxis = list(title = "Number of Shootings"))
NA
LS0tDQp0aXRsZTogIk1JTk5JRSBCRUxMIC0gRE9UIE1BUFMgMSAtIFNIT09USU5HUyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGxlYWZsZXQpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KI2xpYnJhcnkoaHRtbHRvb2xzKQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShEVCkNCmBgYA0KDQoNCmBgYHtyfQ0KbGVhZmxldCgpICU+JQ0KICBhZGRUaWxlcygpDQoNCmBgYA0KIyMgTUFQUyBBTkQgTUFTUyBTSE9PVElOR1MNCg0KSW4gdGhpcyBhbmFseXNpcyB3ZSB3aWxsIHRha2UgYSBsb29rIGF0IG1hcHBpbmcgdGhlIGNlbnRlciBvZiB0aGUgY29udGluZW50YWwgVW5pdGVkIFN0YXRlcyBhcyB3ZWxsIGFzIHdoZXJlIG1hc3Mgc2hvb3RpbmdzIG9jY3VyIGluIHRoZSBVbml0ZWQgU3RhdGVzLg0KDQpGaXJzdCB3ZSB3aWxsIGJlZ2luIHdpdGggbG9jYXRpbmcgdGhlIGNlbnRlciBvZiB0aGUgY29udGluZW50YWwgVW5pdGVkIFN0YXRlcy4gQWNjb3JkaW5nIHRvIFdpa2lwZWRpYSB0aGUgY2VudGVyIGlzIGxvY2F0ZWQgYXQgNDQgNTgnMDIiTiwgMTAzIDQ2JzE4IlcuIFRoZSBjZW50ZXIgaXMgbG9jYXRlZCBqdXN0IG5vcnRoIG9mIEJlbGxlIEZvdXJjaGUsIFNvdXRoIERha290YS4NCg0KNDQuNjggDQotMTAzLjg2DQoNCmBgYHtyfQ0KNTgvNjANCg0KYGBgDQoNCmBgYHtyfQ0KNDYvNjANCg0KYGBgDQoNCg0KYGBge3J9DQpsZWFmbGV0KCkgJT4lDQogIGFkZFRpbGVzKCkgJT4lDQogIHNldFZpZXcobGF0ID0gNDQuNjgsIGxuZyA9IC0xMDMuODYsIHpvb20gPSAxMSkgJT4lDQogIGFkZE1hcmtlcnMobGF0ID0gNDQuNjgsIGxuZyA9IC0xMDMuODYpDQoNCiAgDQogIA0KDQpgYGANCg0KDQpgYGB7cn0NCnNob290aW5ncyA8LSByZWFkX2NzdigiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMWI5bzZ1RE8xOHNMeEJxUHdsX0doOWJuaFctZXZfZEFCSDgzTTVWYjVMOG8vZXhwb3J0P2Zvcm1hdD1jc3YiLCBuYSA9ICItIikNCmBgYA0KTmV4dCB3ZSB3aWxsIHZpZXcgd2hlcmUgc2hvb3RpbmcgaW5jaWRlbnRzIGhhdmUgdGFrZW4gcGxhY2UgdGhyb3VnaG91dCB0aGUgY29udGluZW50YWwgVW5pdGVkIFN0YXRlcy4gVGhlIGRvdCBzaXplIGluZGljYXRlcyB0aGUgc2l6ZSBvZiB0aGUgaW5jaWRlbnQuIFRoZSBtYXAgc2hvd3MgdGhhdCBtYXNzIHNob290aW5ncyBhcmUgd2lkZWx5IHNwcmVhZCBpbiB0aGUgVW5pdGVkIFN0YXRlcy4NCg0KDQpgYGB7cn0NCnNob290aW5ncyAlPiUgDQogIGxlYWZsZXQoKSAlPiUgDQogIGFkZFRpbGVzKCkgJT4lDQogIHNldFZpZXcobGF0ID0gNDQuNjgsIGxuZyA9IC0xMDMuODYsIHpvb20gPSA0KSAlPiUNCiAgYWRkQ2lyY2xlTWFya2VycyhzdHJva2UgPSBGLCBmaWxsT3BhY2l0eSA9IC42LCByYWRpdXMgPSB+bG9nKHRvdGFsX3ZpY3RpbXMpKQ0KDQpgYGANCg0KVGhlcmUgaXMgYSBtZWRpYW4gb2YgMTAgdG90YWwgdmljdGltcyBwZXIgaW5jaWRlbnQgYXMgd2VsbCBhcyBhIG1lZGlhbiBvZiA2IHRvdGFsIGZhdGFsaXRpZXMgcGVyIGluY2lkZW50Lg0KDQoNCmBgYHtyfQ0Kc2hvb3RpbmdzICU+JSANCiAgZHJvcF9uYSh0b3RhbF92aWN0aW1zKSAlPiUgDQogIHN1bW1hcml6ZShtZWRpYW5fdG90YWxfdmljdGltcyA9IG1lZGlhbih0b3RhbF92aWN0aW1zKSkNCmBgYA0KDQoNCg0KYGBge3J9DQpzaG9vdGluZ3MgJT4lIA0KICBkcm9wX25hKGZhdGFsaXRpZXMpICU+JSANCiAgc3VtbWFyaXplKG1lZGlhbl9mYXRhbGl0aWVzID0gbWVkaWFuKGZhdGFsaXRpZXMpKQ0KYGBgDQoNCg0KYGBge3J9DQpzaG9vdGluZ3MgJT4lIA0KICBwbG90X2x5KHggPSB+ZmF0YWxpdGllcykgJT4lIA0KICBhZGRfaGlzdG9ncmFtKG5iaW5zeCA9IDQwKQ0KDQpgYGANCg0KVGhlIGZvbGxvd2luZyBkYXRhIHRhYmxlIGlzIGEgbGlzdCBvZiBpbmNpZGVudHMgYW5kIGluY2x1ZGVzIHN1Y2ggaW5mb3JtYXRpb24gYXMgd2hhdCBoYXBwZW5lZCwgd2hlcmUgaXQgaGFwcGVuZWQsIHdoZW4gaXQgaGFwcGVuZWQsIGhvdyBtYW55IHRvdGFsIHZpY3RpbXMsIHRvdGFsIGZhdGFsaXRpZXMsIGFuZCB0b3RhbCBudW1iZXIgb2YgaW5qdXJlZC4gT3VyIG1vc3QgcmVjZW50IG1hc3Mgc2hvb3Rpbmcgb2NjdXJyZWQgaW4gQm91bGRlciwgQ29sb3JhZG8gb24gTWFyY2ggMjIsIDIwMjEuDQoNCmBgYHtyfQ0Kc2hvb3RpbmdzICU+JQ0KICBzZWxlY3QoY2FzZSwgbG9jYXRpb24sIGRhdGUsIGZhdGFsaXRpZXMsIHRvdGFsX3ZpY3RpbXMsIGluanVyZWQpICU+JQ0KICBkYXRhdGFibGUoKQ0KYGBgDQoNCkluIHRoZSBmb2xsb3dpbmcgZ3JhcGhzLCB5b3UgY2FuIHNlZSB3aG8gaXMgdGhlIHBlcnBldHJhdG9yIGluIHRoZXNlIGluY2lkZW50cy5UaGVzZSBncmFwc2ggc2hvdyB0aGF0IG1hc3Mgc2hvb3RpbmdzIGFyZSBtYWlubHkgY29tbWl0dGVkIGJ5IHdoaXRlLCBtaWRkbGUtYWdlZCwgbWFsZXMuDQoNCg0KYGBge3J9DQpzaG9vdGluZ3MgJT4lIA0KICBkcm9wX25hKHJhY2UpICU+JSANCiAgbXV0YXRlKHJhY2UgPSBhc19mYWN0b3IocmFjZSkpICU+JSANCiAgbXV0YXRlKHJhY2UgPSBmY3RfY29sbGFwc2UocmFjZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV2hpdGUgPSBjKCJXaGl0ZSIsICJ3aGl0ZSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCbGFjayA9IGMoIkJsYWNrIiwgImJsYWNrIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIE90aGVyID0gYygiT3RoZXIiLCAidW5jbGVhciIpKSkgJT4lIA0KICBjb3VudChyYWNlKQ0KYGBgDQoNCg0KYGBge3J9DQpzaG9vdGluZ3MgJT4lIA0KICBkcm9wX25hKHJhY2UpICU+JSANCiAgbXV0YXRlKHJhY2UgPSBhc19mYWN0b3IocmFjZSkpICU+JSANCiAgbXV0YXRlKHJhY2UgPSBmY3RfY29sbGFwc2UocmFjZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV2hpdGUgPSBjKCJXaGl0ZSIsICJ3aGl0ZSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCbGFjayA9IGMoIkJsYWNrIiwgImJsYWNrIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIE90aGVyID0gYygiT3RoZXIiLCAidW5jbGVhciIpKSkgJT4lIA0KICBtdXRhdGUoZ2VuZGVyID0gZmN0X2NvbGxhcHNlKGdlbmRlciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRmVtYWxlID0gYygiRmVtYWxlIiwgIkYiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWFsZSA9IGMoIk1hbGUiLCAiTSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPdGhlciA9IGMoIk1hbGUgJiBGZW1hbGUiKSkpICU+JSANCiAgcGxvdF9seSh4ID0gfmdlbmRlciwgeSA9IH5yYWNlKSAlPiUNCiAgYWRkX2hpc3RvZ3JhbTJkY29udG91cigpDQoNCmBgYA0KDQoNCmBgYHtyfQ0Kc2hvb3RpbmdzICU+JQ0KICBwbG90X2x5KHggPSB+YWdlX29mX3Nob290ZXIsIHkgPSB+Z2VuZGVyKSAlPiUNCiAgbXV0YXRlKGdlbmRlciA9IGZjdF9jb2xsYXBzZShnZW5kZXIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZlbWFsZSA9IGMoIkZlbWFsZSIsICJGIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1hbGUgPSBjKCJNYWxlIiwgIk0iKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT3RoZXIgPSBjKCJNYWxlICYgRmVtYWxlIikpKSAlPiUgDQogIGFkZF9oaXN0b2dyYW0yZGNvbnRvdXIoKQ0KYGBgDQoNCg0KTmV4dCB3ZSB3aWxsIHNob3cgaG93IG1hbnkgaW5qdXJpZXMgdmVyc3VzIGZhdGFsaXRpZXMgdGhlcmUgd2VyZSBpbiB0aGVzZSBzaG9vdGluZ3MuDQoNCg0KDQpgYGB7cn0NCmZhdGFsaXRpZXNfZGF0YSA8LSBzaG9vdGluZ3MgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzdGFydCB3aXRoIHRoZSBzaG9vdGluZ3MgZGF0YQ0KICBmaWx0ZXIoZmF0YWxpdGllcyA+IDMpICU+JSANCiAgZ3JvdXBfYnkoeWVhcikgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB3ZSdyZSBnb2luZyB0byBjb3VudCBieSB5ZWFyDQogIHN1bW1hcml6ZShjb3VudCA9IG4oKSwgZmF0YWxpdGllcyA9IHN1bShmYXRhbGl0aWVzKSkgJT4lICAgICAgICAgICAgICMgZ2V0IHRoZSB0b3RhbCBudW1iZXIgb2YgZmF0YWxpdGllcyBwZXIgeWVhcg0KICBtdXRhdGUoZmF0YWxpdGllc19wZXJfaW5jaWRlbnQgPSBmYXRhbGl0aWVzL2NvdW50KSAgICAgICAgICAgICAgICAgICAjIGRpdmlkZSBieSB0aGUgbnVtYmVyIG9mIHNob290aW5nIGluY2lkZW50cw0KDQpmYXRhbGl0aWVzX2RhdGENCmBgYA0KDQoNCg0KYGBge3J9DQpmYXRhbGl0aWVzX3Blcl9pbmNpZGVudF9tb2RlbCA8LSBsbShmYXRhbGl0aWVzX3Blcl9pbmNpZGVudCB+IHllYXIsIGRhdGEgPSBmYXRhbGl0aWVzX2RhdGEpDQoNCmBgYA0KDQoNCg0KDQpgYGB7cn0NCmZhdGFsaXRpZXNfcGVyX2luY2lkZW50X21vZGVsDQpgYGANCg0KYGBge3J9DQp0aWR5KGZhdGFsaXRpZXNfcGVyX2luY2lkZW50X21vZGVsKQ0KZ2xhbmNlKGZhdGFsaXRpZXNfcGVyX2luY2lkZW50X21vZGVsKQ0KYGBgDQoNCg0KDQoNCg0KDQpgYGB7cn0NCmluanVyaWVzX2RhdGEgPC0gc2hvb3RpbmdzICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgc3RhcnQgd2l0aCB0aGUgc2hvb3RpbmdzIGRhdGENCiAgZmlsdGVyKGluanVyZWQgPiAzKSAlPiUgDQogIGdyb3VwX2J5KHllYXIpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgd2UncmUgZ29pbmcgdG8gY291bnQgYnkgeWVhcg0KICBzdW1tYXJpemUoY291bnQgPSBuKCksIGluanVyZWQgPSBzdW0oaW5qdXJlZCkpICU+JSAgICAgICAgICAgICAjIGdldCB0aGUgdG90YWwgbnVtYmVyIG9mIGZhdGFsaXRpZXMgcGVyIHllYXINCiAgbXV0YXRlKGluanVyaWVzX3Blcl9pbmNpZGVudCA9IGluanVyZWQvY291bnQpIA0KIA0KDQppbmp1cmllc19kYXRhDQpgYGANCg0KDQpgYGB7cn0NCmluanVyaWVzX3Blcl9pbmNpZGVudF8gPC0gbG0oaW5qdXJpZXNfcGVyX2luY2lkZW50IH4geWVhciwgZGF0YSA9IGluanVyaWVzX2RhdGEpDQoNCmBgYA0KDQoNCg0KDQpgYGB7cn0NCmluanVyaWVzX3Blcl9pbmNpZGVudF8NCmBgYA0KDQoNCmBgYHtyfQ0KdGlkeShpbmp1cmllc19wZXJfaW5jaWRlbnRfKQ0KZ2xhbmNlKGluanVyaWVzX3Blcl9pbmNpZGVudF8pDQpgYGANCg0KDQpZb3UgY2FuIHNlZSBpbiB0aGUgbmV4dCB0d28gZ3JhcGhzIHRoYXQgdGhlIG51bWJlciBvZiBmYXRhbGl0ZXMgYW5kIHRoZSBudW1iZXIgb2YgaW5qdXJlZCBoYXMgcmlzZW4gc2xpZ2h0bHkgdGhyb3VnaCB0aGUgeWVhcnMuDQoNCg0KDQpgYGB7cn0NCmZhdGFsaXRpZXNfZGF0YSAlPiUgDQogIHBsb3RfbHkoeCA9IH55ZWFyLCANCiAgICAgICAgICB5ID0gfmZhdGFsaXRpZXMsDQogICAgICAgICAgaG92ZXJpbmZvID0gInRleHQiLA0KICAgICAgICAgIHRleHQgPSB+cGFzdGUoIkZhdGFsaXRpZXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQoZmF0YWxpdGllc19wZXJfaW5jaWRlbnQsIDEpLCAiPGJyPiIsICJZZWFyOiAiLCB5ZWFyKSkgJT4lIA0KICBhZGRfbWFya2VycyhzaG93bGVnZW5kID0gRiwgKSAlPiUNCiAgYWRkX2xpbmVzKHkgPSB+Zml0dGVkKGZhdGFsaXRpZXNfcGVyX2luY2lkZW50X21vZGVsKSkgJT4lDQogIGxheW91dCh0aXRsZSA9ICJOdW1iZXIgb2YgRmF0YWxpdGllcyIsDQogICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiWWVhciIpLA0KICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkZhdGFsaXRpZXMiKSkNCg0KYGBgDQoNCg0KDQpgYGB7cn0NCmluanVyaWVzX2RhdGEgJT4lIA0KICBwbG90X2x5KHggPSB+eWVhciwgDQogICAgICAgICAgeSA9IH5pbmp1cmVkLA0KICAgICAgICAgIGhvdmVyaW5mbyA9ICJ0ZXh0IiwNCiAgICAgICAgICB0ZXh0ID0gfnBhc3RlKCJOdW1iZXIgb2YgSW5qdXJlZCAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQoaW5qdXJpZXNfcGVyX2luY2lkZW50LCAxKSwgIjxicj4iLCAiWWVhcjogIiwgeWVhcikpICU+JSANCiAgYWRkX21hcmtlcnMoc2hvd2xlZ2VuZCA9IEYsICkgJT4lDQogIGFkZF9saW5lcyh5ID0gfmZpdHRlZChpbmp1cmllc19wZXJfaW5jaWRlbnRfKSkgJT4lDQogIGxheW91dCh0aXRsZSA9ICJOdW1iZXIgb2YgSW5qdXJlZCIsDQogICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiWWVhciIpLA0KICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkluanVyZWQiKSkNCg0KYGBgDQoNCg0KRmluYWxseSwgd2Ugd2lsbCBsb29rIGF0IHRoZSBudW1iZXIgb2YgbWFzcyBzaG9vdGluZyBpbmNpZGVudHMgcGVyIHllYXIuIEluIHRoZSBsYXN0IGdyYXBoLCBpdCBzaG93cyB0aGF0IHRoZSBudW1iZXIgb2YgbWFzcyBzaG9vdGluZ3MgaGFzIGluY3JlYXNlZCBzdGVhZGlseSBvdmVyIHRpbWUuDQoNCg0KDQpgYGB7cn0NCm51bV9wZXJfeWVhciA8LSBzaG9vdGluZ3MgJT4lIA0KICBmaWx0ZXIoZmF0YWxpdGllcyA+IDMpICU+JSANCiAgY291bnQoeWVhcikNCg0KbnVtX3Blcl95ZWFyDQpgYGANCg0KDQpgYGB7cn0NCnNob290aW5nc19wZXJfeWVhcl9tb2RlbCA8LSBsbShuIH4geWVhciwgZGF0YSA9IG51bV9wZXJfeWVhcikNCnRpZHkoc2hvb3RpbmdzX3Blcl95ZWFyX21vZGVsKQ0KZ2xhbmNlKHNob290aW5nc19wZXJfeWVhcl9tb2RlbCkNCg0KDQpgYGANCg0KYGBge3J9DQpzaG9vdGluZ3NfcGVyX3llYXJfbW9kZWwNCg0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KDQpudW1fcGVyX3llYXIgJT4lIA0KICBwbG90X2x5KHggPSB+eWVhciwgDQogICAgICAgICAgeSA9IH5zaG9vdGluZ3NfcGVyX3llYXJfbW9kZWwsDQogICAgICAgICAgaG92ZXJpbmZvID0gInRleHQiLA0KICAgICAgICAgIHRleHQgPSB+cGFzdGUoIlNob290aW5ncyBQZXIgWWVhcjogIiwNCiAgICAgICAgICAgICAgICAgICAgICAoc2hvb3RpbmdzX3Blcl95ZWFyX21vZGVsKSwgIjxicj4iLCAiWWVhcjogIiwgeWVhcikpICU+JSANCiAgYWRkX21hcmtlcnMoc2hvd2xlZ2VuZCA9IEYsICkgJT4lDQogIGFkZF9saW5lcyh5ID0gfmZpdHRlZChzaG9vdGluZ3NfcGVyX3llYXJfbW9kZWwpKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gIk51bWJlciBvZiBTaG9vdGluZ3MgYnkgWWVhciIsDQogICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiWWVhciIpLA0KICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIk51bWJlciBvZiBTaG9vdGluZ3MiKSkNCg0KYGBgDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=