1 Case Study

For the case study we will be looking at Philidelphia Neighborhood Shootings. We will be getting this data in the form of a geojson file.

phillyNeighborShooting  <- na.omit(st_read("https://pengdsci.github.io/STA553VIZ/w08/PhillyShootings.geojson"))
phillyNeighbor  <- st_read("https://pengdsci.github.io/STA553VIZ/w08/Neighborhoods_Philadelphia.geojson")
philly  <- st_read("https://pengdsci.github.io/STA553VIZ/w08/PhillyNeighborhood-blocks.geojson") # block level data
SubCrime = phillyNeighborShooting[,c("dc_key","fatal","location","year")]
aggregateCrime = aggregate(SubCrime$fatal, by=list(SubCrime$location,SubCrime$year), FUN=length)
## Longitude and latitude of zip code center
ZipLon = aggregate(as.numeric(phillyNeighborShooting$point_x), by=list(phillyNeighborShooting$location), FUN=mean)
ZipLat = aggregate(as.numeric(phillyNeighborShooting$point_y), by=list(phillyNeighborShooting$location), FUN=mean)
ZipLonLat = merge(ZipLon, ZipLat, by = "Group.1")
names(ZipLonLat) = c("location", "lng", "lat")
##  Zip code crime
ZipCrimeTable = table(phillyNeighborShooting$fatal,  phillyNeighborShooting$location)
ZipCrime = data.frame(location=names(table(phillyNeighborShooting$location)), 
                      fatal = table(phillyNeighborShooting$fatal, phillyNeighborShooting$location)[1,],
                      nonfatal = table(phillyNeighborShooting$fatal, phillyNeighborShooting$location)[2,],
                      total.crime = table(phillyNeighborShooting$location) 
                      )
ZipCrime = ZipCrime[, c("location", "fatal", "nonfatal", "total.crime.Freq")]
colnames(ZipCrime) = c("location", "fatal", "nonfatal", "total.crime")
ZipCrime = merge(ZipLonLat, ZipCrime, by = "location")

2 Creating the plots to be turned into images

2.1 Wound Histogram

plot_ly(
  data = phillyNeighborShooting,
   x = ~ tolower(wound),
   type = "histogram",
   nbinsx = 10, 
   name = "Area Wounded",
   alpha = .5,
   marker = list(line = list(color = "darkgray",  width = 2)) ) %>%
   ## Adding additional histograms and stacking them
    add_histogram(x = ~tolower(wound),
                name = "Area Wounded", nbinsx = 10, alpha = 0.5,
                marker = list(line = list(color = "darkgray",  width = 2))) %>%
    layout(barmode = "overlay",
         title = "Histogram of Wounded Areas",
         xaxis = list(title = "Area Wounded",
                      zeroline = TRUE),
         yaxis = list(title = "Count",
                      zeroline =TRUE),
               ## margin of the plot
      margin = list(
              b = 50,
              l = 100,
              t = 120,
              r = 50
      ))

2.2 Box Plot of Fatalities for each Race

barplotdata = aggregate(phillyNeighborShooting[,21], by = list(phillyNeighborShooting$race), FUN = sum)

plot_ly(
  data = barplotdata,
   x = ~Group.1,
   y = ~fatal,
   type = "bar",
   name = "fatal",
   ## graphic size
   width = 700,
   height = 400) %>%
    layout( yaxis = list(title ="Number of Fatalities"),
            xaxis = list(title = "Race"),
            title = "Fatalaty Shootings by Race"
       )

2.3 Density of Sex

# define three densities
male.which <- phillyNeighborShooting[which(phillyNeighborShooting$sex == "M"),]
male <- density(male.which$fatal)
female.which <- phillyNeighborShooting[which(phillyNeighborShooting$sex == "F"),]
female <- density(female.which$fatal)
# plot density curves
fig <- plot_ly(x = ~male$x, 
               y = ~male$y, 
               type = 'scatter', #A character string specifying the trace type
               mode = 'lines', 
               name = 'males', 
               fill = 'tozeroy')  %>% 
           # adding more density curves
       add_trace(x = ~female$x, 
                 y = ~female$y, 
                 name = 'female', 
                 fill = 'tozeroy')  %>%   
       layout(xaxis = list(title = 'Sex'),
              yaxis = list(title = 'Density'))
fig

3 Final Map

## Images to be plot on the map
fatalitybyrace = "https://dannyoc99.github.io/DOCAL/img/FatalitybyRace.png"
SexFatality = "https://dannyoc99.github.io/DOCAL/img/SexFatality.png"
WoundHistogram = "https://dannyoc99.github.io/DOCAL/img/WoundHistogram.png"
fata = st_as_sf(data.frame(x = -75.3877, y = 39.9168),
                coords = c("x", "y"),
                crs = 4326)
SexFatalityloc = st_as_sf(data.frame(x = -75.3677, y = 39.9168),
                coords = c("x", "y"),
                crs = 4326)
WoundHistogramloc = st_as_sf(data.frame(x = -75.3477, y = 39.9168),
                coords = c("x", "y"),
                crs = 4326)


##################################################
## Crime distribution by zip code - bubble plot
pal0 <- colorNumeric(palette = viridis(256, option = "B"), domain = range(ZipCrime$total.crime))
zipfig <- leaflet() %>%
  setView(lng=-75.1527, lat=39.9707, zoom = 11) %>%
  addProviderTiles(providers$Esri.WorldGrayCanvas) %>% 
  ## plot the neighborhood boundary of Philly
  addPolygons(data = phillyNeighbor,
              color = 'skyblue',
              weight = 1)  %>%
  ##
  addCircleMarkers(data = ZipCrime,
                   radius = ~((total.crime)^(1/3)),
                   stroke = FALSE, 
                   fillOpacity = 0.5,
                   popup = ~paste('Location:', location, 
                      '<br>Total Crime:', total.crime, 
                      '<br>Fatal Crime:', fatal,
                      '<br>Nonfatal Crime:', nonfatal)) 
##################################################
## popup interactive graphs with plotly
fl = tempfile(fileext = ".html")
saveWidget(zipfig, file = fl)
###
leaflet() %>%
  setView(lng=-75.15092, lat=40.00995, zoom = 11) %>%
  #addProviderTiles(providers$CartoDB.DarkMatter) %>% 
  ##
  addProviderTiles(providers$CartoDB.DarkMatter, group="Dark") %>%
  addProviderTiles(providers$CartoDB.DarkMatterNoLabels, group="DarkLabel") %>%  
  addProviderTiles(providers$Esri.NatGeoWorldMap, group="Esri") %>%
  #addTiles(providers$CartoDB.PositronNoLabels) %>%
  ## mini reference map
  addMiniMap() %>%
  ## neighborhood boundary
  addPolygons(data = phillyNeighbor,
              color = 'skyblue',
              weight = 1)  %>%
  ## plot information on the map
  addCircleMarkers(data = phillyNeighborShooting,
                   radius = ~ifelse(fatal == "1", 5, 3),
                   stroke = FALSE, 
                   fillOpacity = 0.5,
                   popup = ~popupTable(phillyNeighborShooting),
                   clusterOptions = markerClusterOptions(maxClusterRadius = 40)) %>%

  # Trend of crimes over the years
  addCircleMarkers(data = fata, 
                   color = "red",
                   weight = 2,
                   label = "fatality by race",
                   stroke = FALSE, 
                   fillOpacity = 0.95,
                   group = "fata") %>%
  addPopupImages(fatalitybyrace, 
                  width = 500,
                  height = 350,
                  tooltip = FALSE,
                  group = "fata") %>%
 # age distribution within the two types of crimes
 addCircleMarkers(data = SexFatalityloc, 
                   color = "black",
                   weight = 2,
                   label = "Density of Fatalities by Sex",
                   stroke = FALSE, 
                   fillOpacity = 0.95,
                   group = "SexFatalityloc") %>%
  addPopupImages(SexFatality, 
                  width = 500,
                  height = 320,
                  tooltip = FALSE,
                  group = "SexFatalityloc") %>%
  addCircleMarkers(data = WoundHistogramloc, 
                   color = "blue",
                   weight = 2,
                   label = "Wound Location Histogram",
                   stroke = FALSE, 
                   fillOpacity = 0.95,
                   group = "WoundHistogramloc") %>%
  addPopupImages(WoundHistogram, 
                  width = 500,
                  height = 400,
                  tooltip = FALSE,
                  group = "WoundHistogramloc") %>% 
  ##
  browsable()

As a case study I decided to graph the shootings by location on a map of the Philidelphia Area. By looking at the map we can see that a crimes are generally in the Center-North Philidelphia Area. Given our data, I was curious to see whether or not the information about these shootings could be expanded on so I made 3 graphs to get more information out of our map besides where these crimes were taking place. Our first graph, fatality by race shows that a large majority of our fatalities are African American shootings. The next graph, density of fatal shootings by sex shows that while females have a lower density, their density curves are wider in both the fatal and non-fatal shootings. Our final graph, a histogram, shows the count of where people are getting shot. The histogram shows that getting shot in multiple locations is the most commmon, but if you were to limit the shooting to only one area, the leg is the most common place to get shot.

4 Chloreopath Data Preparation

democrat2020<-read_csv(file ="https://dannyoc99.github.io/DOCAL/dataset/countypresidential_election_2000-2020.csv")%>%filter(year==2020)%>%filter(party=="DEMOCRAT")%>%subset(select=c(state_po, county_name, county_fips, candidatevotes))%>%rename(dem_candidate_votes=candidatevotes)
rep2020<-read_csv(file ="https://dannyoc99.github.io/DOCAL/dataset/countypresidential_election_2000-2020.csv")%>%filter(year==2020)%>%filter(party=="REPUBLICAN")%>%subset(select=c(county_fips, candidatevotes))%>%rename(rep_candidate_votes=candidatevotes)
election2020<-inner_join(democrat2020, rep2020, by = c("county_fips" = "county_fips")) 
fips_to_geo<-read_csv(file ="https://dannyoc99.github.io/DOCAL/dataset/fips2geocode.csv")
all_data<-inner_join(election2020, fips_to_geo, by = c("county_fips" = "fips"))
all_data$rep_to_dem<-with(all_data,rep_candidate_votes-dem_candidate_votes)

To look at the 2020 election we will limit our election data to 2020, only look at democrat vs republican candidates. We will also bring in Geo information via an inner join

5 Chloreopath Map of the 2020 Election

#library(plotly)
#install.packages('rjson')
#library("RColorBrewer")  # brewer.pal.info for list of color scales

url <- 'https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json'  
counties <- rjson::fromJSON(file=url)  

df=all_data
g <- list(
      scope = 'usa',
      projection = list(type = 'albers usa'),
      showlakes = TRUE,
      lakecolor = toRGB('white')
    )
###
fig <- plot_ly()  %>% 
  add_trace( type = "choropleth",
          geojson = counties,
        locations = df$fips,
                z = df$rep_to_dem,
       colorscale = "RdBu",  
             zmin = 0,
             zmax = 30,
             text = df$name, # hover mesg
           marker = list(line=list(width=0.2))
          )   %>% 
  colorbar(title = "Party (Rep to Dem)",
           colorscale='Viridis')  %>% 
  layout( ### Title 
          title =list(text = "US 2020 Election Choropleth", 
                          font = list(family = "Times New Roman",  # HTML font family  
                                        size = 18,
                                       color = "red")), 
          geo = g)
## The actual HTML page does shoe colorbar correctly, we hide the legend.
hide_legend(fig)

I could not get the graph to display exactly correctly, but the code behind this looks correct, so I thought it may have something to do with the package and thought it worth submitting.

LS0tDQp0aXRsZTogIkRlbW9uc3RyYXRpbmcgQWR2YW5jZWQgTWFwIEtub3dsZWRnZSB0aHJvdWdoIFBoaWxpZGVscGhpYSBDcmltZSBEYXRhIg0KYXV0aG9yOiAiRGFubnkgT0NhbGxhZ2hhbiINCmRhdGU6ICJXZXN0IENoZXN0ZXIgVW5pdmVyc2l0eSAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRoZW1lOiByZWFkYWJsZQ0KLS0tDQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQpkaXYjVE9DIGxpIHsNCiAgICBsaXN0LXN0eWxlOm5vbmU7DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDI0cHg7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMSB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMnB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmgyIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTVweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoNCB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQo8L3N0eWxlPg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiAgIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJzZiIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJzZiIpDQogICBsaWJyYXJ5KHNmKQ0KfQ0KaWYgKCFyZXF1aXJlKCJ0ZXJyYSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJ0ZXJyYSIpDQogICBsaWJyYXJ5KHRlcnJhKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikNCiAgIGxpYnJhcnkocGxvdGx5KQ0KfQ0KaWYgKCFyZXF1aXJlKCJkcGx5ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpDQogICBsaWJyYXJ5KGRwbHlyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwbmciKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoInBuZyIpICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoInBuZyIpDQp9DQppZiAoIXJlcXVpcmUoInNwRGF0YSIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygic3BEYXRhIikgICAgICAgICAgICAgDQogICAgbGlicmFyeSgic3BEYXRhIikNCn0NCmlmICghcmVxdWlyZSgiY29sb3VycGlja2VyIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJjb2xvdXJwaWNrZXIiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiY29sb3VycGlja2VyIikNCn0NCmlmICghcmVxdWlyZSgiZ2lmc2tpIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnaWZza2kiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ2lmc2tpIikNCn0NCmlmICghcmVxdWlyZSgibWFnaWNrIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJtYWdpY2siKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgibWFnaWNrIikNCn0NCiMjIyBnZ3Bsb3QgYW5kIGV4dGVuc2lvbnMNCmlmICghcmVxdWlyZSgiZ2dwbG90MiIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJnZ3Bsb3QyIikNCn0NCmlmICghcmVxdWlyZSgiZ2dhbmltYXRlIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnZ2FuaW1hdGUiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ2dhbmltYXRlIikNCn0NCmlmICghcmVxdWlyZSgidG1hcCIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygidG1hcCIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJ0bWFwIikNCn0NCmlmICghcmVxdWlyZSgic2YiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoInNmIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoInNmIikNCn0NCmlmICghcmVxdWlyZSgidGlncmlzIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWdyaXMiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgidGlncmlzIikNCn0NCmlmICghcmVxdWlyZSgibWFwdmlldyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygibWFwdmlldyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJtYXB2aWV3IikNCn0NCmlmICghcmVxdWlyZSgicGFuZGVyIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJwYW5kZXIiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgicGFuZGVyIikNCn0NCmlmICghcmVxdWlyZSgibGF0dGljZSIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygibGF0dGljZSIpDQpsaWJyYXJ5KCJsYXR0aWNlIikNCn0NCmlmICghcmVxdWlyZSgic3AiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoInNwIikNCmxpYnJhcnkoInNwIikNCn0NCmlmICghcmVxdWlyZSgibGVhZmxldCIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygibGVhZmxldCIpDQpsaWJyYXJ5KCJsZWFmbGV0IikNCn0NCmlmICghcmVxdWlyZSgibGVhZnBvcCIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygibGVhZnBvcCIpDQpsaWJyYXJ5KCJsZWFmcG9wIikNCn0NCmlmICghcmVxdWlyZSgibGVhZmVtIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJsZWFmZW0iKQ0KbGlicmFyeSgibGVhZmVtIikNCn0NCmlmICghcmVxdWlyZSgiaHRtbHdpZGdldHMiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImh0bWx3aWRnZXRzIikNCmxpYnJhcnkoImh0bWx3aWRnZXRzIikNCn0NCmlmICghcmVxdWlyZSgibGVhZmxldC5leHRyYXMiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImxlYWZsZXQuZXh0cmFzIikNCmxpYnJhcnkoImxlYWZsZXQuZXh0cmFzIikNCn0NCmlmICghcmVxdWlyZSgiaHRtbHRvb2xzIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJodG1sdG9vbHMiKQ0KbGlicmFyeSgiaHRtbHRvb2xzIikNCn0NCmlmKCFyZXF1aXJlKCJwbmciKSl7DQogIGluc3RhbGwucGFja2FnZXMoInBuZyIpDQogIGxpYnJhcnkocG5nKQ0KfQ0KaWYoIXJlcXVpcmUoInZpcmlkaXMiKSl7DQogIGluc3RhbGwucGFja2FnZXMoInZpcmlkaXMiKQ0KICBsaWJyYXJ5KHZpcmlkaXMpDQp9DQppZighcmVxdWlyZSgiZ2dtYXAiKSl7DQogIGluc3RhbGwucGFja2FnZXMoImdnbWFwIikNCiAgbGlicmFyeShnZ21hcCkNCn0NCmlmKCFyZXF1aXJlKCJ3ZWJzaG90Iikpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJ3ZWJzaG90IikNCiAgbGlicmFyeSh3ZWJzaG90KQ0KfQ0KaWYoIXJlcXVpcmUoImh0bWx3aWRnZXRzIikpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJodG1sd2lkZ2V0cyIpDQogIGxpYnJhcnkoaHRtbHdpZGdldHMpDQp9DQppZighcmVxdWlyZSgiYW5pbWF0aW9uIikpew0KICBpbnN0YWxsLnBhY2thZ2VzKCJhbmltYXRpb24iKQ0KICBsaWJyYXJ5KGFuaW1hdGlvbikNCn0NCmlmKCFyZXF1aXJlKCJnaWZza2kiKSl7DQogIGluc3RhbGwucGFja2FnZXMoImdpZnNraSIpDQogIGxpYnJhcnkoZ2lmc2tpKQ0KfQ0KaWYoIXJlcXVpcmUoImh0bWxUYWJsZSIpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygiaHRtbFRhYmxlIikNCiAgbGlicmFyeShodG1sVGFibGUpDQp9DQppZighcmVxdWlyZSgibWFncml0dHIiKSl7DQogIGluc3RhbGwucGFja2FnZXMoIm1hZ3JpdHRyIikNCiAgbGlicmFyeShtYWdyaXR0cikNCn0NCiMjIyBsaWJyYXJ5KG1hZ3JpdHRyKQ0KIyMjDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gVFJVRSwgICANCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BKQ0KYGBgDQoNCiMgQ2FzZSBTdHVkeQ0KDQpGb3IgdGhlIGNhc2Ugc3R1ZHkgd2Ugd2lsbCBiZSBsb29raW5nIGF0IFBoaWxpZGVscGhpYSBOZWlnaGJvcmhvb2QgU2hvb3RpbmdzLiBXZSB3aWxsIGJlIGdldHRpbmcgdGhpcyBkYXRhIGluIHRoZSBmb3JtIG9mIGEgZ2VvanNvbiBmaWxlLiANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0UsIHJlc3VsdHM9RkFMU0V9DQpwaGlsbHlOZWlnaGJvclNob290aW5nICA8LSBuYS5vbWl0KHN0X3JlYWQoImh0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL1NUQTU1M1ZJWi93MDgvUGhpbGx5U2hvb3RpbmdzLmdlb2pzb24iKSkNCnBoaWxseU5laWdoYm9yICA8LSBzdF9yZWFkKCJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9TVEE1NTNWSVovdzA4L05laWdoYm9yaG9vZHNfUGhpbGFkZWxwaGlhLmdlb2pzb24iKQ0KcGhpbGx5ICA8LSBzdF9yZWFkKCJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9TVEE1NTNWSVovdzA4L1BoaWxseU5laWdoYm9yaG9vZC1ibG9ja3MuZ2VvanNvbiIpICMgYmxvY2sgbGV2ZWwgZGF0YQ0KU3ViQ3JpbWUgPSBwaGlsbHlOZWlnaGJvclNob290aW5nWyxjKCJkY19rZXkiLCJmYXRhbCIsImxvY2F0aW9uIiwieWVhciIpXQ0KYWdncmVnYXRlQ3JpbWUgPSBhZ2dyZWdhdGUoU3ViQ3JpbWUkZmF0YWwsIGJ5PWxpc3QoU3ViQ3JpbWUkbG9jYXRpb24sU3ViQ3JpbWUkeWVhciksIEZVTj1sZW5ndGgpDQojIyBMb25naXR1ZGUgYW5kIGxhdGl0dWRlIG9mIHppcCBjb2RlIGNlbnRlcg0KWmlwTG9uID0gYWdncmVnYXRlKGFzLm51bWVyaWMocGhpbGx5TmVpZ2hib3JTaG9vdGluZyRwb2ludF94KSwgYnk9bGlzdChwaGlsbHlOZWlnaGJvclNob290aW5nJGxvY2F0aW9uKSwgRlVOPW1lYW4pDQpaaXBMYXQgPSBhZ2dyZWdhdGUoYXMubnVtZXJpYyhwaGlsbHlOZWlnaGJvclNob290aW5nJHBvaW50X3kpLCBieT1saXN0KHBoaWxseU5laWdoYm9yU2hvb3RpbmckbG9jYXRpb24pLCBGVU49bWVhbikNClppcExvbkxhdCA9IG1lcmdlKFppcExvbiwgWmlwTGF0LCBieSA9ICJHcm91cC4xIikNCm5hbWVzKFppcExvbkxhdCkgPSBjKCJsb2NhdGlvbiIsICJsbmciLCAibGF0IikNCiMjICBaaXAgY29kZSBjcmltZQ0KWmlwQ3JpbWVUYWJsZSA9IHRhYmxlKHBoaWxseU5laWdoYm9yU2hvb3RpbmckZmF0YWwsICBwaGlsbHlOZWlnaGJvclNob290aW5nJGxvY2F0aW9uKQ0KWmlwQ3JpbWUgPSBkYXRhLmZyYW1lKGxvY2F0aW9uPW5hbWVzKHRhYmxlKHBoaWxseU5laWdoYm9yU2hvb3RpbmckbG9jYXRpb24pKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmF0YWwgPSB0YWJsZShwaGlsbHlOZWlnaGJvclNob290aW5nJGZhdGFsLCBwaGlsbHlOZWlnaGJvclNob290aW5nJGxvY2F0aW9uKVsxLF0sDQogICAgICAgICAgICAgICAgICAgICAgbm9uZmF0YWwgPSB0YWJsZShwaGlsbHlOZWlnaGJvclNob290aW5nJGZhdGFsLCBwaGlsbHlOZWlnaGJvclNob290aW5nJGxvY2F0aW9uKVsyLF0sDQogICAgICAgICAgICAgICAgICAgICAgdG90YWwuY3JpbWUgPSB0YWJsZShwaGlsbHlOZWlnaGJvclNob290aW5nJGxvY2F0aW9uKSANCiAgICAgICAgICAgICAgICAgICAgICApDQpaaXBDcmltZSA9IFppcENyaW1lWywgYygibG9jYXRpb24iLCAiZmF0YWwiLCAibm9uZmF0YWwiLCAidG90YWwuY3JpbWUuRnJlcSIpXQ0KY29sbmFtZXMoWmlwQ3JpbWUpID0gYygibG9jYXRpb24iLCAiZmF0YWwiLCAibm9uZmF0YWwiLCAidG90YWwuY3JpbWUiKQ0KWmlwQ3JpbWUgPSBtZXJnZShaaXBMb25MYXQsIFppcENyaW1lLCBieSA9ICJsb2NhdGlvbiIpDQpgYGANCg0KIyBDcmVhdGluZyB0aGUgcGxvdHMgdG8gYmUgdHVybmVkIGludG8gaW1hZ2VzDQoNCiMjIFdvdW5kIEhpc3RvZ3JhbQ0KDQpgYGB7cn0NCnBsb3RfbHkoDQogIGRhdGEgPSBwaGlsbHlOZWlnaGJvclNob290aW5nLA0KICAgeCA9IH4gdG9sb3dlcih3b3VuZCksDQogICB0eXBlID0gImhpc3RvZ3JhbSIsDQogICBuYmluc3ggPSAxMCwgDQogICBuYW1lID0gIkFyZWEgV291bmRlZCIsDQogICBhbHBoYSA9IC41LA0KICAgbWFya2VyID0gbGlzdChsaW5lID0gbGlzdChjb2xvciA9ICJkYXJrZ3JheSIsICB3aWR0aCA9IDIpKSApICU+JQ0KICAgIyMgQWRkaW5nIGFkZGl0aW9uYWwgaGlzdG9ncmFtcyBhbmQgc3RhY2tpbmcgdGhlbQ0KICAgIGFkZF9oaXN0b2dyYW0oeCA9IH50b2xvd2VyKHdvdW5kKSwNCiAgICAgICAgICAgICAgICBuYW1lID0gIkFyZWEgV291bmRlZCIsIG5iaW5zeCA9IDEwLCBhbHBoYSA9IDAuNSwNCiAgICAgICAgICAgICAgICBtYXJrZXIgPSBsaXN0KGxpbmUgPSBsaXN0KGNvbG9yID0gImRhcmtncmF5IiwgIHdpZHRoID0gMikpKSAlPiUNCiAgICBsYXlvdXQoYmFybW9kZSA9ICJvdmVybGF5IiwNCiAgICAgICAgIHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBXb3VuZGVkIEFyZWFzIiwNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJBcmVhIFdvdW5kZWQiLA0KICAgICAgICAgICAgICAgICAgICAgIHplcm9saW5lID0gVFJVRSksDQogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiQ291bnQiLA0KICAgICAgICAgICAgICAgICAgICAgIHplcm9saW5lID1UUlVFKSwNCiAgICAgICAgICAgICAgICMjIG1hcmdpbiBvZiB0aGUgcGxvdA0KICAgICAgbWFyZ2luID0gbGlzdCgNCiAgICAgICAgICAgICAgYiA9IDUwLA0KICAgICAgICAgICAgICBsID0gMTAwLA0KICAgICAgICAgICAgICB0ID0gMTIwLA0KICAgICAgICAgICAgICByID0gNTANCiAgICAgICkpDQpgYGANCg0KIyMgQm94IFBsb3Qgb2YgRmF0YWxpdGllcyBmb3IgZWFjaCBSYWNlDQoNCmBgYHtyfQ0KYmFycGxvdGRhdGEgPSBhZ2dyZWdhdGUocGhpbGx5TmVpZ2hib3JTaG9vdGluZ1ssMjFdLCBieSA9IGxpc3QocGhpbGx5TmVpZ2hib3JTaG9vdGluZyRyYWNlKSwgRlVOID0gc3VtKQ0KDQpwbG90X2x5KA0KICBkYXRhID0gYmFycGxvdGRhdGEsDQogICB4ID0gfkdyb3VwLjEsDQogICB5ID0gfmZhdGFsLA0KICAgdHlwZSA9ICJiYXIiLA0KICAgbmFtZSA9ICJmYXRhbCIsDQogICAjIyBncmFwaGljIHNpemUNCiAgIHdpZHRoID0gNzAwLA0KICAgaGVpZ2h0ID0gNDAwKSAlPiUNCiAgICBsYXlvdXQoIHlheGlzID0gbGlzdCh0aXRsZSA9Ik51bWJlciBvZiBGYXRhbGl0aWVzIiksDQogICAgICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiUmFjZSIpLA0KICAgICAgICAgICAgdGl0bGUgPSAiRmF0YWxhdHkgU2hvb3RpbmdzIGJ5IFJhY2UiDQogICAgICAgKQ0KYGBgDQoNCiMjIERlbnNpdHkgb2YgU2V4IA0KDQpgYGB7cn0NCiMgZGVmaW5lIHRocmVlIGRlbnNpdGllcw0KbWFsZS53aGljaCA8LSBwaGlsbHlOZWlnaGJvclNob290aW5nW3doaWNoKHBoaWxseU5laWdoYm9yU2hvb3Rpbmckc2V4ID09ICJNIiksXQ0KbWFsZSA8LSBkZW5zaXR5KG1hbGUud2hpY2gkZmF0YWwpDQpmZW1hbGUud2hpY2ggPC0gcGhpbGx5TmVpZ2hib3JTaG9vdGluZ1t3aGljaChwaGlsbHlOZWlnaGJvclNob290aW5nJHNleCA9PSAiRiIpLF0NCmZlbWFsZSA8LSBkZW5zaXR5KGZlbWFsZS53aGljaCRmYXRhbCkNCiMgcGxvdCBkZW5zaXR5IGN1cnZlcw0KZmlnIDwtIHBsb3RfbHkoeCA9IH5tYWxlJHgsIA0KICAgICAgICAgICAgICAgeSA9IH5tYWxlJHksIA0KICAgICAgICAgICAgICAgdHlwZSA9ICdzY2F0dGVyJywgI0EgY2hhcmFjdGVyIHN0cmluZyBzcGVjaWZ5aW5nIHRoZSB0cmFjZSB0eXBlDQogICAgICAgICAgICAgICBtb2RlID0gJ2xpbmVzJywgDQogICAgICAgICAgICAgICBuYW1lID0gJ21hbGVzJywgDQogICAgICAgICAgICAgICBmaWxsID0gJ3RvemVyb3knKSAgJT4lIA0KICAgICAgICAgICAjIGFkZGluZyBtb3JlIGRlbnNpdHkgY3VydmVzDQogICAgICAgYWRkX3RyYWNlKHggPSB+ZmVtYWxlJHgsIA0KICAgICAgICAgICAgICAgICB5ID0gfmZlbWFsZSR5LCANCiAgICAgICAgICAgICAgICAgbmFtZSA9ICdmZW1hbGUnLCANCiAgICAgICAgICAgICAgICAgZmlsbCA9ICd0b3plcm95JykgICU+JSAgIA0KICAgICAgIGxheW91dCh4YXhpcyA9IGxpc3QodGl0bGUgPSAnU2V4JyksDQogICAgICAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdEZW5zaXR5JykpDQpmaWcNCmBgYA0KDQojIEZpbmFsIE1hcCANCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMCwgd2FybmluZz1GQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQ0KDQojIyBJbWFnZXMgdG8gYmUgcGxvdCBvbiB0aGUgbWFwDQpmYXRhbGl0eWJ5cmFjZSA9ICJodHRwczovL2Rhbm55b2M5OS5naXRodWIuaW8vRE9DQUwvaW1nL0ZhdGFsaXR5YnlSYWNlLnBuZyINClNleEZhdGFsaXR5ID0gImh0dHBzOi8vZGFubnlvYzk5LmdpdGh1Yi5pby9ET0NBTC9pbWcvU2V4RmF0YWxpdHkucG5nIg0KV291bmRIaXN0b2dyYW0gPSAiaHR0cHM6Ly9kYW5ueW9jOTkuZ2l0aHViLmlvL0RPQ0FML2ltZy9Xb3VuZEhpc3RvZ3JhbS5wbmciDQpmYXRhID0gc3RfYXNfc2YoZGF0YS5mcmFtZSh4ID0gLTc1LjM4NzcsIHkgPSAzOS45MTY4KSwNCiAgICAgICAgICAgICAgICBjb29yZHMgPSBjKCJ4IiwgInkiKSwNCiAgICAgICAgICAgICAgICBjcnMgPSA0MzI2KQ0KU2V4RmF0YWxpdHlsb2MgPSBzdF9hc19zZihkYXRhLmZyYW1lKHggPSAtNzUuMzY3NywgeSA9IDM5LjkxNjgpLA0KICAgICAgICAgICAgICAgIGNvb3JkcyA9IGMoIngiLCAieSIpLA0KICAgICAgICAgICAgICAgIGNycyA9IDQzMjYpDQpXb3VuZEhpc3RvZ3JhbWxvYyA9IHN0X2FzX3NmKGRhdGEuZnJhbWUoeCA9IC03NS4zNDc3LCB5ID0gMzkuOTE2OCksDQogICAgICAgICAgICAgICAgY29vcmRzID0gYygieCIsICJ5IiksDQogICAgICAgICAgICAgICAgY3JzID0gNDMyNikNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMgQ3JpbWUgZGlzdHJpYnV0aW9uIGJ5IHppcCBjb2RlIC0gYnViYmxlIHBsb3QNCnBhbDAgPC0gY29sb3JOdW1lcmljKHBhbGV0dGUgPSB2aXJpZGlzKDI1Niwgb3B0aW9uID0gIkIiKSwgZG9tYWluID0gcmFuZ2UoWmlwQ3JpbWUkdG90YWwuY3JpbWUpKQ0KemlwZmlnIDwtIGxlYWZsZXQoKSAlPiUNCiAgc2V0Vmlldyhsbmc9LTc1LjE1MjcsIGxhdD0zOS45NzA3LCB6b29tID0gMTEpICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRFc3JpLldvcmxkR3JheUNhbnZhcykgJT4lIA0KICAjIyBwbG90IHRoZSBuZWlnaGJvcmhvb2QgYm91bmRhcnkgb2YgUGhpbGx5DQogIGFkZFBvbHlnb25zKGRhdGEgPSBwaGlsbHlOZWlnaGJvciwNCiAgICAgICAgICAgICAgY29sb3IgPSAnc2t5Ymx1ZScsDQogICAgICAgICAgICAgIHdlaWdodCA9IDEpICAlPiUNCiAgIyMNCiAgYWRkQ2lyY2xlTWFya2VycyhkYXRhID0gWmlwQ3JpbWUsDQogICAgICAgICAgICAgICAgICAgcmFkaXVzID0gfigodG90YWwuY3JpbWUpXigxLzMpKSwNCiAgICAgICAgICAgICAgICAgICBzdHJva2UgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjUsDQogICAgICAgICAgICAgICAgICAgcG9wdXAgPSB+cGFzdGUoJ0xvY2F0aW9uOicsIGxvY2F0aW9uLCANCiAgICAgICAgICAgICAgICAgICAgICAnPGJyPlRvdGFsIENyaW1lOicsIHRvdGFsLmNyaW1lLCANCiAgICAgICAgICAgICAgICAgICAgICAnPGJyPkZhdGFsIENyaW1lOicsIGZhdGFsLA0KICAgICAgICAgICAgICAgICAgICAgICc8YnI+Tm9uZmF0YWwgQ3JpbWU6Jywgbm9uZmF0YWwpKSANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyBwb3B1cCBpbnRlcmFjdGl2ZSBncmFwaHMgd2l0aCBwbG90bHkNCmZsID0gdGVtcGZpbGUoZmlsZWV4dCA9ICIuaHRtbCIpDQpzYXZlV2lkZ2V0KHppcGZpZywgZmlsZSA9IGZsKQ0KIyMjDQpsZWFmbGV0KCkgJT4lDQogIHNldFZpZXcobG5nPS03NS4xNTA5MiwgbGF0PTQwLjAwOTk1LCB6b29tID0gMTEpICU+JQ0KICAjYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5EYXJrTWF0dGVyKSAlPiUgDQogICMjDQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuRGFya01hdHRlciwgZ3JvdXA9IkRhcmsiKSAlPiUNCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5EYXJrTWF0dGVyTm9MYWJlbHMsIGdyb3VwPSJEYXJrTGFiZWwiKSAlPiUgIA0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRFc3JpLk5hdEdlb1dvcmxkTWFwLCBncm91cD0iRXNyaSIpICU+JQ0KICAjYWRkVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb25Ob0xhYmVscykgJT4lDQogICMjIG1pbmkgcmVmZXJlbmNlIG1hcA0KICBhZGRNaW5pTWFwKCkgJT4lDQogICMjIG5laWdoYm9yaG9vZCBib3VuZGFyeQ0KICBhZGRQb2x5Z29ucyhkYXRhID0gcGhpbGx5TmVpZ2hib3IsDQogICAgICAgICAgICAgIGNvbG9yID0gJ3NreWJsdWUnLA0KICAgICAgICAgICAgICB3ZWlnaHQgPSAxKSAgJT4lDQogICMjIHBsb3QgaW5mb3JtYXRpb24gb24gdGhlIG1hcA0KICBhZGRDaXJjbGVNYXJrZXJzKGRhdGEgPSBwaGlsbHlOZWlnaGJvclNob290aW5nLA0KICAgICAgICAgICAgICAgICAgIHJhZGl1cyA9IH5pZmVsc2UoZmF0YWwgPT0gIjEiLCA1LCAzKSwNCiAgICAgICAgICAgICAgICAgICBzdHJva2UgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjUsDQogICAgICAgICAgICAgICAgICAgcG9wdXAgPSB+cG9wdXBUYWJsZShwaGlsbHlOZWlnaGJvclNob290aW5nKSwNCiAgICAgICAgICAgICAgICAgICBjbHVzdGVyT3B0aW9ucyA9IG1hcmtlckNsdXN0ZXJPcHRpb25zKG1heENsdXN0ZXJSYWRpdXMgPSA0MCkpICU+JQ0KDQogICMgVHJlbmQgb2YgY3JpbWVzIG92ZXIgdGhlIHllYXJzDQogIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IGZhdGEsIA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsDQogICAgICAgICAgICAgICAgICAgd2VpZ2h0ID0gMiwNCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICJmYXRhbGl0eSBieSByYWNlIiwNCiAgICAgICAgICAgICAgICAgICBzdHJva2UgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjk1LA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gImZhdGEiKSAlPiUNCiAgYWRkUG9wdXBJbWFnZXMoZmF0YWxpdHlieXJhY2UsIA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSA1MDAsDQogICAgICAgICAgICAgICAgICBoZWlnaHQgPSAzNTAsDQogICAgICAgICAgICAgICAgICB0b29sdGlwID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICBncm91cCA9ICJmYXRhIikgJT4lDQogIyBhZ2UgZGlzdHJpYnV0aW9uIHdpdGhpbiB0aGUgdHdvIHR5cGVzIG9mIGNyaW1lcw0KIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IFNleEZhdGFsaXR5bG9jLCANCiAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsDQogICAgICAgICAgICAgICAgICAgd2VpZ2h0ID0gMiwNCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICJEZW5zaXR5IG9mIEZhdGFsaXRpZXMgYnkgU2V4IiwNCiAgICAgICAgICAgICAgICAgICBzdHJva2UgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjk1LA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gIlNleEZhdGFsaXR5bG9jIikgJT4lDQogIGFkZFBvcHVwSW1hZ2VzKFNleEZhdGFsaXR5LCANCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gNTAwLA0KICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gMzIwLA0KICAgICAgICAgICAgICAgICAgdG9vbHRpcCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAiU2V4RmF0YWxpdHlsb2MiKSAlPiUNCiAgYWRkQ2lyY2xlTWFya2VycyhkYXRhID0gV291bmRIaXN0b2dyYW1sb2MsIA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsdWUiLA0KICAgICAgICAgICAgICAgICAgIHdlaWdodCA9IDIsDQogICAgICAgICAgICAgICAgICAgbGFiZWwgPSAiV291bmQgTG9jYXRpb24gSGlzdG9ncmFtIiwNCiAgICAgICAgICAgICAgICAgICBzdHJva2UgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjk1LA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gIldvdW5kSGlzdG9ncmFtbG9jIikgJT4lDQogIGFkZFBvcHVwSW1hZ2VzKFdvdW5kSGlzdG9ncmFtLCANCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gNTAwLA0KICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gNDAwLA0KICAgICAgICAgICAgICAgICAgdG9vbHRpcCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAiV291bmRIaXN0b2dyYW1sb2MiKSAlPiUgDQogICMjDQogIGJyb3dzYWJsZSgpDQpgYGANCg0KQXMgYSBjYXNlIHN0dWR5IEkgZGVjaWRlZCB0byBncmFwaCB0aGUgc2hvb3RpbmdzIGJ5IGxvY2F0aW9uIG9uIGEgbWFwIG9mIHRoZSBQaGlsaWRlbHBoaWEgQXJlYS4gQnkgbG9va2luZyBhdCB0aGUgbWFwIHdlIGNhbiBzZWUgdGhhdCBhIGNyaW1lcyBhcmUgZ2VuZXJhbGx5IGluIHRoZSBDZW50ZXItTm9ydGggUGhpbGlkZWxwaGlhIEFyZWEuIEdpdmVuIG91ciBkYXRhLCBJIHdhcyBjdXJpb3VzIHRvIHNlZSB3aGV0aGVyIG9yIG5vdCB0aGUgaW5mb3JtYXRpb24gYWJvdXQgdGhlc2Ugc2hvb3RpbmdzIGNvdWxkIGJlIGV4cGFuZGVkIG9uIHNvIEkgbWFkZSAzIGdyYXBocyB0byBnZXQgbW9yZSBpbmZvcm1hdGlvbiBvdXQgb2Ygb3VyIG1hcCBiZXNpZGVzIHdoZXJlIHRoZXNlIGNyaW1lcyB3ZXJlIHRha2luZyBwbGFjZS4gT3VyIGZpcnN0IGdyYXBoLCBmYXRhbGl0eSBieSByYWNlIHNob3dzIHRoYXQgYSBsYXJnZSBtYWpvcml0eSBvZiBvdXIgZmF0YWxpdGllcyBhcmUgQWZyaWNhbiBBbWVyaWNhbiBzaG9vdGluZ3MuIFRoZSBuZXh0IGdyYXBoLCBkZW5zaXR5IG9mIGZhdGFsIHNob290aW5ncyBieSBzZXggc2hvd3MgdGhhdCB3aGlsZSBmZW1hbGVzIGhhdmUgYSBsb3dlciBkZW5zaXR5LCB0aGVpciBkZW5zaXR5IGN1cnZlcyBhcmUgd2lkZXIgaW4gYm90aCB0aGUgZmF0YWwgYW5kIG5vbi1mYXRhbCBzaG9vdGluZ3MuIE91ciBmaW5hbCBncmFwaCwgYSBoaXN0b2dyYW0sIHNob3dzIHRoZSBjb3VudCBvZiB3aGVyZSBwZW9wbGUgYXJlIGdldHRpbmcgc2hvdC4gVGhlIGhpc3RvZ3JhbSBzaG93cyB0aGF0IGdldHRpbmcgc2hvdCBpbiBtdWx0aXBsZSBsb2NhdGlvbnMgaXMgdGhlIG1vc3QgY29tbW1vbiwgYnV0IGlmIHlvdSB3ZXJlIHRvIGxpbWl0IHRoZSBzaG9vdGluZyB0byBvbmx5IG9uZSBhcmVhLCB0aGUgbGVnIGlzIHRoZSBtb3N0IGNvbW1vbiBwbGFjZSB0byBnZXQgc2hvdC4NCg0KIyBDaGxvcmVvcGF0aCBEYXRhIFByZXBhcmF0aW9uDQoNCmBgYHtyLCBjaGxvcnByZXB9DQpkZW1vY3JhdDIwMjA8LXJlYWRfY3N2KGZpbGUgPSJodHRwczovL2Rhbm55b2M5OS5naXRodWIuaW8vRE9DQUwvZGF0YXNldC9jb3VudHlwcmVzaWRlbnRpYWxfZWxlY3Rpb25fMjAwMC0yMDIwLmNzdiIpJT4lZmlsdGVyKHllYXI9PTIwMjApJT4lZmlsdGVyKHBhcnR5PT0iREVNT0NSQVQiKSU+JXN1YnNldChzZWxlY3Q9YyhzdGF0ZV9wbywgY291bnR5X25hbWUsIGNvdW50eV9maXBzLCBjYW5kaWRhdGV2b3RlcykpJT4lcmVuYW1lKGRlbV9jYW5kaWRhdGVfdm90ZXM9Y2FuZGlkYXRldm90ZXMpDQpyZXAyMDIwPC1yZWFkX2NzdihmaWxlID0iaHR0cHM6Ly9kYW5ueW9jOTkuZ2l0aHViLmlvL0RPQ0FML2RhdGFzZXQvY291bnR5cHJlc2lkZW50aWFsX2VsZWN0aW9uXzIwMDAtMjAyMC5jc3YiKSU+JWZpbHRlcih5ZWFyPT0yMDIwKSU+JWZpbHRlcihwYXJ0eT09IlJFUFVCTElDQU4iKSU+JXN1YnNldChzZWxlY3Q9Yyhjb3VudHlfZmlwcywgY2FuZGlkYXRldm90ZXMpKSU+JXJlbmFtZShyZXBfY2FuZGlkYXRlX3ZvdGVzPWNhbmRpZGF0ZXZvdGVzKQ0KZWxlY3Rpb24yMDIwPC1pbm5lcl9qb2luKGRlbW9jcmF0MjAyMCwgcmVwMjAyMCwgYnkgPSBjKCJjb3VudHlfZmlwcyIgPSAiY291bnR5X2ZpcHMiKSkgDQpmaXBzX3RvX2dlbzwtcmVhZF9jc3YoZmlsZSA9Imh0dHBzOi8vZGFubnlvYzk5LmdpdGh1Yi5pby9ET0NBTC9kYXRhc2V0L2ZpcHMyZ2VvY29kZS5jc3YiKQ0KYWxsX2RhdGE8LWlubmVyX2pvaW4oZWxlY3Rpb24yMDIwLCBmaXBzX3RvX2dlbywgYnkgPSBjKCJjb3VudHlfZmlwcyIgPSAiZmlwcyIpKQ0KYWxsX2RhdGEkcmVwX3RvX2RlbTwtd2l0aChhbGxfZGF0YSxyZXBfY2FuZGlkYXRlX3ZvdGVzLWRlbV9jYW5kaWRhdGVfdm90ZXMpDQpgYGANCg0KVG8gbG9vayBhdCB0aGUgMjAyMCBlbGVjdGlvbiB3ZSB3aWxsIGxpbWl0IG91ciBlbGVjdGlvbiBkYXRhIHRvIDIwMjAsIG9ubHkgbG9vayBhdCBkZW1vY3JhdCB2cyByZXB1YmxpY2FuIGNhbmRpZGF0ZXMuIFdlIHdpbGwgYWxzbyBicmluZyBpbiBHZW8gaW5mb3JtYXRpb24gdmlhIGFuIGlubmVyIGpvaW4NCg0KIyBDaGxvcmVvcGF0aCBNYXAgb2YgdGhlIDIwMjAgRWxlY3Rpb24NCg0KYGBge3IgZWxlY3Rpb259DQojbGlicmFyeShwbG90bHkpDQojaW5zdGFsbC5wYWNrYWdlcygncmpzb24nKQ0KI2xpYnJhcnkoIlJDb2xvckJyZXdlciIpICAjIGJyZXdlci5wYWwuaW5mbyBmb3IgbGlzdCBvZiBjb2xvciBzY2FsZXMNCg0KdXJsIDwtICdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcGxvdGx5L2RhdGFzZXRzL21hc3Rlci9nZW9qc29uLWNvdW50aWVzLWZpcHMuanNvbicgIA0KY291bnRpZXMgPC0gcmpzb246OmZyb21KU09OKGZpbGU9dXJsKSAgDQoNCmRmPWFsbF9kYXRhDQpnIDwtIGxpc3QoDQogICAgICBzY29wZSA9ICd1c2EnLA0KICAgICAgcHJvamVjdGlvbiA9IGxpc3QodHlwZSA9ICdhbGJlcnMgdXNhJyksDQogICAgICBzaG93bGFrZXMgPSBUUlVFLA0KICAgICAgbGFrZWNvbG9yID0gdG9SR0IoJ3doaXRlJykNCiAgICApDQojIyMNCmZpZyA8LSBwbG90X2x5KCkgICU+JSANCiAgYWRkX3RyYWNlKCB0eXBlID0gImNob3JvcGxldGgiLA0KICAgICAgICAgIGdlb2pzb24gPSBjb3VudGllcywNCiAgICAgICAgbG9jYXRpb25zID0gZGYkZmlwcywNCiAgICAgICAgICAgICAgICB6ID0gZGYkcmVwX3RvX2RlbSwNCiAgICAgICBjb2xvcnNjYWxlID0gIlJkQnUiLCAgDQogICAgICAgICAgICAgem1pbiA9IDAsDQogICAgICAgICAgICAgem1heCA9IDMwLA0KICAgICAgICAgICAgIHRleHQgPSBkZiRuYW1lLCAjIGhvdmVyIG1lc2cNCiAgICAgICAgICAgbWFya2VyID0gbGlzdChsaW5lPWxpc3Qod2lkdGg9MC4yKSkNCiAgICAgICAgICApICAgJT4lIA0KICBjb2xvcmJhcih0aXRsZSA9ICJQYXJ0eSAoUmVwIHRvIERlbSkiLA0KICAgICAgICAgICBjb2xvcnNjYWxlPSdWaXJpZGlzJykgICU+JSANCiAgbGF5b3V0KCAjIyMgVGl0bGUgDQogICAgICAgICAgdGl0bGUgPWxpc3QodGV4dCA9ICJVUyAyMDIwIEVsZWN0aW9uIENob3JvcGxldGgiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gIlRpbWVzIE5ldyBSb21hbiIsICAjIEhUTUwgZm9udCBmYW1pbHkgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxOCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIpKSwgDQogICAgICAgICAgZ2VvID0gZykNCiMjIFRoZSBhY3R1YWwgSFRNTCBwYWdlIGRvZXMgc2hvZSBjb2xvcmJhciBjb3JyZWN0bHksIHdlIGhpZGUgdGhlIGxlZ2VuZC4NCmhpZGVfbGVnZW5kKGZpZykNCg0KYGBgDQoNCkkgY291bGQgbm90IGdldCB0aGUgZ3JhcGggdG8gZGlzcGxheSBleGFjdGx5IGNvcnJlY3RseSwgYnV0IHRoZSBjb2RlIGJlaGluZCB0aGlzIGxvb2tzIGNvcnJlY3QsIHNvIEkgdGhvdWdodCBpdCBtYXkgaGF2ZSBzb21ldGhpbmcgdG8gZG8gd2l0aCB0aGUgcGFja2FnZSBhbmQgdGhvdWdodCBpdCB3b3J0aCBzdWJtaXR0aW5nLg==