The objective of this analysis was to explore the shooting incidences that took place throughout New York City from 2006 to 2022 (I focused primarily on 2006 to 2019 as I felt that policy changes, an election and everything going on with the Covid-19 pandemic would play too much the part of an extreme influence). I looked to examine both lethal and non lethal shootings with where and when they occurred to see what patterns/trends might be obtained.

For this analysis: I used visualizations such as bar charts, line charts, heatmaps, and maps.

library(tidyverse)
library(DT)
library(lubridate)
library(ggthemes)
library(readxl)
sum(duplicated(nycfiredcopy4B)) # no duplicates
[1] 0
sum(is.na(nycfiredcopy4B)) #we have 78 null values
[1] 78
summary(is.na(nycfiredcopy4B)) # all variables except for incident_key contains Null values
 OCCUR_DATE         BORO          PRECINCT       JURISDICTION_CODE
 Mode :logical   Mode :logical   Mode :logical   Mode :logical    
 FALSE:14642     FALSE:14642     FALSE:14642     FALSE:14642      
 TRUE :6         TRUE :6         TRUE :6         TRUE :6          
 STATISTICAL_MURDER_FLAG PERP_AGE_GROUP   PERP_SEX       PERP_RACE      
 Mode :logical           Mode :logical   Mode :logical   Mode :logical  
 FALSE:14642             FALSE:14642     FALSE:14642     FALSE:14642    
 TRUE :6                 TRUE :6         TRUE :6         TRUE :6        
 VIC_AGE_GROUP    VIC_SEX         VIC_RACE        Latitude       Longitude      
 Mode :logical   Mode :logical   Mode :logical   Mode :logical   Mode :logical  
 FALSE:14642     FALSE:14642     FALSE:14642     FALSE:14642     FALSE:14642    
 TRUE :6         TRUE :6         TRUE :6         TRUE :6         TRUE :6        
 INCIDENT_KEY   
 Mode :logical  
 FALSE:14648    
                
nycfiredcopy4B <- na.omit(nycfiredcopy4B)
sum(duplicated(nycfiredcopy4B)) # no duplicates
[1] 0
sum(is.na(nycfiredcopy4B)) #no null values / NA
[1] 0
dataview <- nycfiredcopy4C %>% 
  relocate(incident_key,.after = 'occur_date') %>% 
  select(-c(latitude,longitude,year,day,month,dayofweek))
datatable(dataview)
nycfiredcopy4D <- nycfiredcopy4D %>% 
  relocate(month,.before = 'day')
summary(nycfiredcopy4D)
            boro      statistical_murder_flag    latitude       longitude     
 BRONX        :2531   Mode :logical           Min.   :40.52   Min.   :-74.23  
 BROOKLYN     :3161   FALSE:8422              1st Qu.:40.67   1st Qu.:-73.94  
 MANHATTAN    :1115                           Median :40.70   Median :-73.92  
 QUEENS       :1238                           Mean   :40.74   Mean   :-73.91  
 STATEN ISLAND: 377                           3rd Qu.:40.83   3rd Qu.:-73.88  
                                              Max.   :40.91   Max.   :-73.72  
                                                                              
      year          month           day        dayofweek 
 Min.   :2006   Jul    : 956   Min.   : 1.00   Sun:1584  
 1st Qu.:2008   Aug    : 944   1st Qu.: 8.00   Mon:1151  
 Median :2011   Jun    : 867   Median :16.00   Tue:1009  
 Mean   :2012   May    : 800   Mean   :15.99   Wed: 976  
 3rd Qu.:2015   Sep    : 719   3rd Qu.:24.00   Thu: 950  
 Max.   :2019   Oct    : 696   Max.   :31.00   Fri:1143  
                (Other):3440                   Sat:1609  

Brooklyn has the most shootings only focused on non murder- there are far more shootings not flagged as murder than are flagged as murder (8422 no murder) from what we can see 2008 saw the most shootings, July is the month with the most shootings the most shootings occur on Saturdays,Sundays, Mondays, Fridays

dailyshooting <- nycfiredcopy4D %>% 
  group_by(day, statistical_murder_flag) %>% 
  summarize(Total = n())
datatable(dailyshooting)

ggplot(dailyshooting,aes(day,Total))+geom_line()+
  theme_classic() +facet_wrap(~statistical_murder_flag,scales = 'free')+theme(axis.text.x = element_text(angle = 90))

there seems to be a small uptrend in shootings during the first 20 days in the month and then in the last 10 it steadily declines

daily_monthly_shooting<- nycfiredcopy4D %>% 
  group_by(month,day,statistical_murder_flag) %>% 
  summarize(Total = n()) 

datatable(daily_monthly_shooting)

Color key:

#month to year trend
shooting_month_year<- nycfiredcopy4D %>% 
  #filter(year<=2019) %>% 
  group_by(year,month,statistical_murder_flag) %>% 
  summarize(Total = n())
datatable(shooting_month_year)
monthyear1 <- shooting_month_year %>% 

ggplot(aes(year,Total,fill=month))+theme_classic()+
  geom_col(position = 'dodge')+
  ggtitle('Shootings per months and year')+
  scale_fill_manual(values=colors)+theme(legend.position = 'none')
monthyear1

non lethal shootings was at its highest in both July of 2007 and August 2008 non lethal shootings was at its lowest in both February of 2018

Color key:
shootings_month_weekday<- nycfiredcopy4D %>%
  # filter(year<=2019) %>% 
  group_by(month,dayofweek,statistical_murder_flag) %>% 
  summarize(Total = n())

datatable(shootings_month_weekday)
ggplot(shootings_month_weekday,aes(reorder(month,Total),Total,fill=dayofweek))+theme_classic()+
  geom_col(position = 'dodge', linewidth=8)+ggtitle('Shootings by days of week and month')+facet_wrap(~statistical_murder_flag,nrow=2,scales = 'free')+
  scale_fill_manual(values=colors)+xlab('month')

non lethal shootings were at there peak on Sundays in the month of July non lethal shootings were at there lowest on Thursdays in the month of February

nycfiredcopy4D %>% 

  select(boro,statistical_murder_flag) %>% 
   
  group_by(boro,statistical_murder_flag) %>% 
  summarize(count=n()) %>% 
ggplot(aes(reorder(boro,count),count))+theme_classic()+
  geom_bar(stat='identity',fill='orange')+geom_text(aes(label=count))+ggtitle('Shooting per borough')+theme(axis.text.x = element_text(angle = 90))+xlab('borough')

nycfiredcopy4D %>%  
  select(boro,statistical_murder_flag,month) %>% 
  group_by(boro,month,statistical_murder_flag) %>% 
  summarize(count=n()) %>% 
ggplot(aes(reorder(month,count),count,fill=boro))+theme_classic()+geom_col(position = 'dodge')+
  
  ggtitle('Monthly Shooting per borough ')+theme(axis.text.x = element_text(angle = 90))+coord_flip()+theme(legend.position = 'bottom')+xlab('month')

for non lethal shootings, it is July as the month with the most shootings and Brooklyn as the borough with the greatest majority in July, while February is the month with the least shootings and Brooklyn as the borough with the greatest majority in February Throughout all the months Brooklyn had an overwhelming majority of shootings with the exception of January where Brooklyn saw only one more shooting than Bronx

nycfiredcopy4D %>% 
  select(boro,statistical_murder_flag,dayofweek) %>% 
  group_by(boro,dayofweek,statistical_murder_flag) %>% 
  summarize(count=n()) %>% 
ggplot(aes(dayofweek,count,fill=boro))+theme_classic()+geom_col(position = 'dodge')+
  ggtitle('Daily Shooting by weekday and borough ')+theme(axis.text.x = element_text(angle = 90))+coord_flip()

for non lethal shootings Brooklyn saw the highest count on both Sundays and Saturdays, On Saturdays,


nycfiredcopy4D %>%
  select(month,statistical_murder_flag,year,boro) %>% 
  group_by(year,statistical_murder_flag,boro) %>% 
  summarize(count=n()) %>% 
ggplot(aes(year,count,fill=boro))+theme_classic()+geom_col(position = 'dodge')+

  ggtitle('Shooting per year and borough ')+theme(axis.text.x = element_text(angle = 90))+coord_flip()

first, out of the five boroughs it was Brooklyn and Bronx that saw the most non lethal shootings every year



nycfiredcopy4D %>% 
  #filter(year <= 2019) %>% 
  group_by(dayofweek,month,statistical_murder_flag) %>% 
  summarize(count=n()) %>% 
  ggplot(aes(dayofweek,month,fill=count))+
  geom_tile(color='white',linewidth = .5,linetype = 1)+theme_dark()+ggtitle('Heat Map of Shootings by Day and Month')+
  geom_text(aes(label = count),col='yellow',size=3.2)+facet_wrap(~statistical_murder_flag,nrow=2,scales = 'free')

From 2006 to 2019 it is clear that during June, July, August and in some cases May we have the highest counts of non lethal shootings occurring on Sunday with July & August reaching over 200 while June,July,August and May we had Shooting counts under 200 but surpassing 150 taking place on Saturdays whereas throughout all other periods of the week shootings tend to all be below 150 too even below 100


 nycfiredcopy4D %>% 
 # filter(year<=2019) %>% 
   group_by(day,month,statistical_murder_flag) %>% 
  summarize(Total=n()) %>% 
  
  ggplot(aes(day,month,fill=Total))+
  geom_tile(color='white',linewidth = .5,linetype = 1)+theme_dark()+ggtitle('Heat Map of non-lethal Shootings per Day and Month')+
  geom_text(aes(label = Total),col='yellow',size=2.8)

it is January 1 that we see the highest count of non lethal shootings at 51 all together the greatest majority of shootings are within the first 20 days

 nycfiredcopy4D %>% 
  #filter(year<=2019) %>% 
   group_by(year,month,statistical_murder_flag) %>% 
  summarize(Total=n()) %>% 
  
  ggplot(aes(month,year,fill=Total))+
  geom_tile(color='white',linewidth = .5,linetype = 1)+theme_dark()+ggtitle('Heat Map of non lethal Shootings per Month and Year')+
  geom_text(aes(label = Total),col='yellow',size=2.8)

July of 2007 and august 2008 had most non lethal shootings the late spring to summer months of 2006,2007 and 2008 saw the greatest number of non lethal shootings


in 2008 the number of overall shootings reached its zenith of 875 non lethal shootings only to then slowly drop to 392 shootings throughout NYC. This amazing down trend in shootings clearly indicates some form of substantial change to life in NYC whether it be economical or crime related.

nycfiredcopy4T %>% 
  filter(year <=2019) %>% 
  select(year,boro,statistical_murder_flag) %>% 
  group_by(year,boro,statistical_murder_flag) %>% 
  summarise(total=n()) %>% 
ggplot(aes(year,total,col=statistical_murder_flag))+
  geom_line()+geom_point()+theme_dark()+ggtitle('annual trend of Shootings and Borough')+
 
  facet_wrap(~boro,nrow=2,scales = 'free_x')+theme(legend.position = 'none')

Brooklyn and Bronx had the highest peaks of shootings in the mid 2000’s and since then we’ve see a trend showing the greatest decline in overall shootings whereas the other boroughs remained relatively stable.

nycfiredcopy4D %>% 
  filter(year <=2019) %>% 
  select(month,statistical_murder_flag) %>% 
  group_by(month,statistical_murder_flag) %>% 
  summarise(total=n()) %>% 
ggplot(aes(month,total,fill=statistical_murder_flag))+theme_classic()+
  geom_col()+ggtitle('Monthly trend of Shootings ')+geom_smooth(se=F,lty=2,col='black',linewidth=1)+
  geom_text(aes(label = total),col='black',size=3.4)+theme(legend.position = 'none')

the plot shows that going into the fall or autumn season shootings are on a decline and hit their lowest point in February at which point we see a sharp rising trend especially in non lethal shootings until we reach the month of the zenith points of July and August from which then drop in shootings then begins

the above plot indicates that July is the month with highest total count of non lethal shootings

nycfiredcopy4D %>% 
  filter(year <=2019) %>% 
  select(dayofweek,statistical_murder_flag) %>% 
  group_by(dayofweek,statistical_murder_flag) %>%
  summarise(total=n()) %>% 
ggplot(aes(dayofweek,total,fill=statistical_murder_flag))+theme_classic()+
  #geom_line(linewidth=.95)+geom_point()
geom_col()+ggtitle('Seven Day trend of Shootings')+geom_smooth(se=F,lty=2,col='black',linewidth=1)+
  geom_text(aes(label = total),col='black',size=3.2)+theme(legend.position = 'none')

the highest amount of non lethal shootings occur on Sundays and Saturdays while the lowest total shootings occur on Thursdays



nycfiredcopy4T %>% 
  filter(year<= 2019) %>% 
ggplot(aes(longitude,latitude))+
  geom_point(size=1,color='purple')+
  #scale_x_continuous(limits=c(min_long,max_long))+
 # scale_y_continuous(limits=c(min_lat,max_lat))+
  theme_map()+ggtitle('Map of shootings not resulting in murder throughout New York')

Conclusion

  1. Shootings tend to increase in the spring and summer months and decrease in the autumn to winter months

  2. The months of July and August had the highest counts of shootings followed by June and May

  3. Brooklyn had the most overall shootings followed by the Bronx

  4. Brooklyn had the most shootings per month followed by the Bronx

  5. Brooklyn had the most shootings per weekday followed by the Bronx

  6. Brooklyn had the most shootings per year followed by the Bronx except for the year 2018

  7. Sundays and Saturdays were the days throughout the week that accounted for the majority of shootings

  8. The greatest majority of high volume shootings occurred within the first 20 days of the month

  9. The months of July 2007 and August 2008 both shared the greatest number of shootings at 110 while May through August of 2006,2007,2008 as well as May of 2009 had shootings that were above or slightly below 100

  10. it also seems that from 2006 to 2019 shootings throughout NYC experienced a strong downtrend as they dropped from 875 in 2008 to 392 in 2019 and where this trend was most noticeable in Brooklyn and Bronx
LS0tDQp0aXRsZTogIkVEQSBvbiBOWUMgc2hvb3RpbmdzIGJldHdlZW4gMjAwNiBhbmQgMjAxOSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KYXV0aG9yOiBIYXJyaXNvbg0KLS0tDQoNClRoZSBvYmplY3RpdmUgb2YgdGhpcyBhbmFseXNpcyB3YXMgdG8gZXhwbG9yZSB0aGUgc2hvb3RpbmcgaW5jaWRlbmNlcyB0aGF0IHRvb2sgcGxhY2UgdGhyb3VnaG91dCBOZXcgWW9yayBDaXR5IGZyb20gMjAwNiB0byAyMDIyIChJIGZvY3VzZWQgcHJpbWFyaWx5IG9uIDIwMDYgdG8gMjAxOSBhcyBJIGZlbHQgdGhhdCBwb2xpY3kgY2hhbmdlcywgYW4gZWxlY3Rpb24gYW5kIGV2ZXJ5dGhpbmcgZ29pbmcgb24gd2l0aCB0aGUgQ292aWQtMTkgcGFuZGVtaWMgd291bGQgcGxheSB0b28gbXVjaCB0aGUgcGFydCBvZiBhbiBleHRyZW1lIGluZmx1ZW5jZSkuIEkgbG9va2VkIHRvIGV4YW1pbmUgYm90aCBsZXRoYWwgYW5kIG5vbiBsZXRoYWwgc2hvb3RpbmdzIHdpdGggIHdoZXJlIGFuZCB3aGVuIHRoZXkgb2NjdXJyZWQgdG8gc2VlIHdoYXQgcGF0dGVybnMvdHJlbmRzIG1pZ2h0IGJlIG9idGFpbmVkLg0KDQpGb3IgdGhpcyBhbmFseXNpczogDQpJIHVzZWQgdmlzdWFsaXphdGlvbnMgc3VjaCBhcyBiYXIgY2hhcnRzLCBsaW5lIGNoYXJ0cywgaGVhdG1hcHMsIGFuZCBtYXBzLg0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShEVCkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShnZ3RoZW1lcykNCmxpYnJhcnkocmVhZHhsKQ0KDQpgYGANCg0KDQoNCmBgYHtyLGVjaG89RkFMU0V9DQpueWNmaXJlZGNvcHk0QiA8LSAgcmVhZF94bHN4KCJDOi9Vc2Vycy90aGVweS9Eb3dubG9hZHMvUmVjZW50IERhdGEgY3N2IG9yIHhsc3ggZG93bmxvYWRzIHRvIGFuYWx5emUvTllQRF9TaG9vdGluZ19JbmNpZGVudF9EYXRhLnhsc3giKQ0KDQpgYGANCg0KDQpgYGB7cn0NCnN1bShkdXBsaWNhdGVkKG55Y2ZpcmVkY29weTRCKSkgIyBubyBkdXBsaWNhdGVzDQpzdW0oaXMubmEobnljZmlyZWRjb3B5NEIpKSAjd2UgaGF2ZSA3OCBudWxsIHZhbHVlcw0KDQpzdW1tYXJ5KGlzLm5hKG55Y2ZpcmVkY29weTRCKSkgIyBhbGwgdmFyaWFibGVzIGV4Y2VwdCBmb3IgaW5jaWRlbnRfa2V5IGNvbnRhaW5zIE51bGwgdmFsdWVzDQoNCm55Y2ZpcmVkY29weTRCIDwtIG5hLm9taXQobnljZmlyZWRjb3B5NEIpDQpzdW0oZHVwbGljYXRlZChueWNmaXJlZGNvcHk0QikpICMgbm8gZHVwbGljYXRlcw0Kc3VtKGlzLm5hKG55Y2ZpcmVkY29weTRCKSkgI25vIG51bGwgdmFsdWVzIC8gTkENCmBgYA0KDQoNCmBgYHtyLGluY2x1ZGU9RkFMU0V9DQpueWNmaXJlZGNvcHk0QiA8LSBueWNmaXJlZGNvcHk0QiAlPiUgDQogIGNsZWFuX25hbWVzKCkgJT4lIA0KICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLGFzLmZhY3RvcikgJT4lIA0KICBtdXRhdGUob2NjdXJfZGF0ZSA9IHltZChvY2N1cl9kYXRlKSkNCg0KDQpueWNmaXJlZGNvcHk0QyA8LSBueWNmaXJlZGNvcHk0Qg0KDQoNCm55Y2ZpcmVkY29weTRDJHllYXIgPC0geWVhcihueWNmaXJlZGNvcHk0QyRvY2N1cl9kYXRlKQ0KbnljZmlyZWRjb3B5NEMkZGF5IDwtIGRheShueWNmaXJlZGNvcHk0QyRvY2N1cl9kYXRlKQ0KbnljZmlyZWRjb3B5NEMkbW9udGggPC0gZmFjdG9yKG1vbnRoKG55Y2ZpcmVkY29weTRDJG9jY3VyX2RhdGUsIGxhYmVsID0gVFJVRSkpDQojbnljZmlyZWRjb3B5NEMkeWVhciA8LSBmYWN0b3IoeWVhcihueWNmaXJlZGNvcHk0QyRvY2N1cl9kYXRlKSkNCm55Y2ZpcmVkY29weTRDJGRheW9md2VlayA8LSBmYWN0b3Iod2RheShueWNmaXJlZGNvcHk0QyRvY2N1cl9kYXRlLCBsYWJlbCA9IFRSVUUpKQ0KDQpueWNmaXJlZGNvcHk0RDwtIG55Y2ZpcmVkY29weTRDICU+JSANCiAgZmlsdGVyKHllYXI8PTIwMTkpICU+JQ0KICBmaWx0ZXIoc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcgPT0nRkFMU0UnKSAlPiUgDQogIHNlbGVjdCgtYyhvY2N1cl9kYXRlLCBwcmVjaW5jdCxqdXJpc2RpY3Rpb25fY29kZSxwZXJwX2FnZV9ncm91cCxwZXJwX3NleCxwZXJwX3JhY2UsdmljX2FnZV9ncm91cCx2aWNfc2V4LHZpY19yYWNlLGluY2lkZW50X2tleSkpDQpgYGANCg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0V9DQpkYXRhdmlldyA8LSBueWNmaXJlZGNvcHk0QyAlPiUgDQogIHJlbG9jYXRlKGluY2lkZW50X2tleSwuYWZ0ZXIgPSAnb2NjdXJfZGF0ZScpICU+JSANCiAgc2VsZWN0KC1jKGxhdGl0dWRlLGxvbmdpdHVkZSx5ZWFyLGRheSxtb250aCxkYXlvZndlZWspKQ0KZGF0YXRhYmxlKGRhdGF2aWV3KQ0KYGBgDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpueWNmaXJlZGNvcHk0RCA8LSBueWNmaXJlZGNvcHk0RCAlPiUgDQogIHJlbG9jYXRlKG1vbnRoLC5iZWZvcmUgPSAnZGF5JykNCmBgYA0KDQoNCmBgYHtyLGluY2x1ZGU9RkFMU0V9DQpueWNmaXJlZGNvcHk0RA0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCnN1bW1hcnkobnljZmlyZWRjb3B5NEQpDQpgYGANCg0KQnJvb2tseW4gaGFzIHRoZSBtb3N0IHNob290aW5ncw0Kb25seSBmb2N1c2VkIG9uIG5vbiBtdXJkZXItDQp0aGVyZSBhcmUgZmFyIG1vcmUgc2hvb3RpbmdzIG5vdCBmbGFnZ2VkIGFzIG11cmRlciB0aGFuIGFyZSBmbGFnZ2VkIGFzIG11cmRlciAoODQyMiBubyBtdXJkZXIpDQpmcm9tIHdoYXQgd2UgY2FuIHNlZSAyMDA4IHNhdyB0aGUgbW9zdCBzaG9vdGluZ3MsDQpKdWx5IGlzIHRoZSBtb250aCB3aXRoIHRoZSBtb3N0IHNob290aW5ncyANCnRoZSBtb3N0IHNob290aW5ncyBvY2N1ciBvbiBTYXR1cmRheXMsU3VuZGF5cywgTW9uZGF5cywgRnJpZGF5cw0KYGBge3J9DQpgYGANCg0KDQoNCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQpkYWlseXNob290aW5nIDwtIG55Y2ZpcmVkY29weTREICU+JSANCiAgZ3JvdXBfYnkoZGF5LCBzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICBzdW1tYXJpemUoVG90YWwgPSBuKCkpDQpkYXRhdGFibGUoZGFpbHlzaG9vdGluZykNCmBgYA0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQoNCmdncGxvdChkYWlseXNob290aW5nLGFlcyhkYXksVG90YWwpKStnZW9tX2xpbmUoKSsNCiAgdGhlbWVfY2xhc3NpYygpICtmYWNldF93cmFwKH5zdGF0aXN0aWNhbF9tdXJkZXJfZmxhZyxzY2FsZXMgPSAnZnJlZScpK3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQ0KYGBgDQp0aGVyZSBzZWVtcyB0byBiZSBhIHNtYWxsIHVwdHJlbmQgaW4gc2hvb3RpbmdzIGR1cmluZyB0aGUgZmlyc3QgMjAgZGF5cyBpbiB0aGUgbW9udGggYW5kIHRoZW4gaW4gdGhlIGxhc3QgMTAgaXQgc3RlYWRpbHkgZGVjbGluZXMNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCmRhaWx5X21vbnRobHlfc2hvb3Rpbmc8LSBueWNmaXJlZGNvcHk0RCAlPiUgDQogIGdyb3VwX2J5KG1vbnRoLGRheSxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICBzdW1tYXJpemUoVG90YWwgPSBuKCkpIA0KDQpkYXRhdGFibGUoZGFpbHlfbW9udGhseV9zaG9vdGluZykNCmBgYA0KYGBge3IsaW5jbHVkZT1GQUxTRX0NCmNvbG9ycyA9IGMoInJlZCIsICJncmVlbiIsICJvcmFuZ2UiLCAiYmx1ZSIsICJ5ZWxsb3ciLCAicHVycGxlIiwgImJsYWNrIiwncGluaycsJ2N5YW4nLCdncmV5JywnZm9yZXN0Z3JlZW4nLCAnbWFyb29uJyApDQpgYGANCg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KZ2dwbG90KGRhaWx5X21vbnRobHlfc2hvb3RpbmcsYWVzKHJlb3JkZXIoVG90YWwsZGF5KSxUb3RhbCxmaWxsPW1vbnRoKSkrDQogIGdlb21fY29sKCwgbGluZXdpZHRoPTUpKw0KICBnZ3RpdGxlKCdTaG9vdGluZ3MgYnkgRGF5IGFuZCBtb250aCcpKw0KICB0aGVtZV9kYXJrKCkrc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNvbG9ycykrdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpK3hsYWIoJ2RheScpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykNCmBgYA0KQ29sb3Iga2V5Og0KDQo8dWw+PGxpPg0KInJlZCIgPSBKYW51YXJ5IDwvbGk+PGxpPg0KImdyZWVuIiA9IEZlYnJ1YXJ5PC9saT48bGk+DQoib3JhbmdlIiA9IE1hcmNoPC9saT48bGk+DQoiYmx1ZSIgPSBBcHJpbDwvbGk+PGxpPg0KInllbGxvdyIgPSBNYXkgPC9saT48bGk+DQoicHVycGxlIiA9IEp1bmUgPC9saT48bGk+DQoiYmxhY2siID0gSnVseTwvbGk+PGxpPg0KJ3BpbmsnPSBBdWd1c3Q8L2xpPjxsaT4NCidjeWFuJyA9IFNlcHRlbWJlcjwvbGk+PGxpPg0KJ2dyZXknID0gT2N0b2JlcjwvbGk+PGxpPg0KJ2ZvcmVzdCBncmVlbicgPSBOb3ZlbWJlcjwvbGk+PGxpPiANCidtYXJvb24nID0gRGVjZW1iZXI8L2xpPg0KPC91bD4NCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCiNtb250aCB0byB5ZWFyIHRyZW5kDQpzaG9vdGluZ19tb250aF95ZWFyPC0gbnljZmlyZWRjb3B5NEQgJT4lIA0KICAjZmlsdGVyKHllYXI8PTIwMTkpICU+JSANCiAgZ3JvdXBfYnkoeWVhcixtb250aCxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICBzdW1tYXJpemUoVG90YWwgPSBuKCkpDQpkYXRhdGFibGUoc2hvb3RpbmdfbW9udGhfeWVhcikNCmBgYA0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQptb250aHllYXIxIDwtIHNob290aW5nX21vbnRoX3llYXIgJT4lIA0KDQpnZ3Bsb3QoYWVzKHllYXIsVG90YWwsZmlsbD1tb250aCkpK3RoZW1lX2NsYXNzaWMoKSsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSsNCiAgZ2d0aXRsZSgnU2hvb3RpbmdzIHBlciBtb250aHMgYW5kIHllYXInKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNvbG9ycykrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnKQ0KbW9udGh5ZWFyMQ0KDQpgYGANCm5vbiBsZXRoYWwgc2hvb3RpbmdzIHdhcyBhdCBpdHMgaGlnaGVzdCBpbiBib3RoIEp1bHkgb2YgMjAwNyBhbmQgQXVndXN0IDIwMDgNCm5vbiBsZXRoYWwgc2hvb3RpbmdzIHdhcyBhdCBpdHMgbG93ZXN0IGluIGJvdGggRmVicnVhcnkgb2YgMjAxOA0KDQpDb2xvciBrZXk6DQo8dWw+PGxpPg0KInJlZCIgPSBKYW51YXJ5IDwvbGk+PGxpPg0KImdyZWVuIiA9IEZlYnJ1YXJ5PC9saT48bGk+DQoib3JhbmdlIiA9IE1hcmNoPC9saT48bGk+DQoiYmx1ZSIgPSBBcHJpbDwvbGk+PGxpPg0KInllbGxvdyIgPSBNYXkgPC9saT48bGk+DQoicHVycGxlIiA9IEp1bmUgPC9saT48bGk+DQoiYmxhY2siID0gSnVseTwvbGk+PGxpPg0KJ3BpbmsnPSBBdWd1c3Q8L2xpPjxsaT4NCidjeWFuJyA9IFNlcHRlbWJlcjwvbGk+PGxpPg0KJ2dyZXknID0gT2N0b2JlcjwvbGk+PGxpPg0KJ2ZvcmVzdCBncmVlbicgPSBOb3ZlbWJlcjwvbGk+PGxpPiANCidtYXJvb24nID0gRGVjZW1iZXI8L2xpPg0KPC91bD4NCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCnNob290aW5nc19tb250aF93ZWVrZGF5PC0gbnljZmlyZWRjb3B5NEQgJT4lDQogICMgZmlsdGVyKHllYXI8PTIwMTkpICU+JSANCiAgZ3JvdXBfYnkobW9udGgsZGF5b2Z3ZWVrLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcml6ZShUb3RhbCA9IG4oKSkNCg0KZGF0YXRhYmxlKHNob290aW5nc19tb250aF93ZWVrZGF5KQ0KYGBgDQoNCg0KYGBge3J9DQoNCmBgYA0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQpnZ3Bsb3Qoc2hvb3RpbmdzX21vbnRoX3dlZWtkYXksYWVzKHJlb3JkZXIobW9udGgsVG90YWwpLFRvdGFsLGZpbGw9ZGF5b2Z3ZWVrKSkrdGhlbWVfY2xhc3NpYygpKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScsIGxpbmV3aWR0aD04KStnZ3RpdGxlKCdTaG9vdGluZ3MgYnkgZGF5cyBvZiB3ZWVrIGFuZCBtb250aCcpK2ZhY2V0X3dyYXAofnN0YXRpc3RpY2FsX211cmRlcl9mbGFnLG5yb3c9MixzY2FsZXMgPSAnZnJlZScpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y29sb3JzKSt4bGFiKCdtb250aCcpDQpgYGANCm5vbiBsZXRoYWwgc2hvb3RpbmdzIHdlcmUgYXQgdGhlcmUgcGVhayBvbiBTdW5kYXlzIGluIHRoZSBtb250aCBvZiBKdWx5DQpub24gbGV0aGFsIHNob290aW5ncyB3ZXJlIGF0IHRoZXJlIGxvd2VzdCBvbiBUaHVyc2RheXMgaW4gdGhlIG1vbnRoIG9mIEZlYnJ1YXJ5DQoNCg0KYGBge3J9DQoNCmBgYA0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQpueWNmaXJlZGNvcHk0RCAlPiUgDQoNCiAgc2VsZWN0KGJvcm8sc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgIA0KICBncm91cF9ieShib3JvLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcml6ZShjb3VudD1uKCkpICU+JSANCmdncGxvdChhZXMocmVvcmRlcihib3JvLGNvdW50KSxjb3VudCkpK3RoZW1lX2NsYXNzaWMoKSsNCiAgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknLGZpbGw9J29yYW5nZScpK2dlb21fdGV4dChhZXMobGFiZWw9Y291bnQpKStnZ3RpdGxlKCdTaG9vdGluZyBwZXIgYm9yb3VnaCcpK3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSt4bGFiKCdib3JvdWdoJykNCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KbnljZmlyZWRjb3B5NEQgJT4lICANCiAgc2VsZWN0KGJvcm8sc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcsbW9udGgpICU+JSANCiAgZ3JvdXBfYnkoYm9ybyxtb250aCxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICBzdW1tYXJpemUoY291bnQ9bigpKSAlPiUgDQpnZ3Bsb3QoYWVzKHJlb3JkZXIobW9udGgsY291bnQpLGNvdW50LGZpbGw9Ym9ybykpK3RoZW1lX2NsYXNzaWMoKStnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpKw0KICANCiAgZ2d0aXRsZSgnTW9udGhseSBTaG9vdGluZyBwZXIgYm9yb3VnaCAnKSt0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkrY29vcmRfZmxpcCgpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nKSt4bGFiKCdtb250aCcpDQpgYGANCmZvciBub24gbGV0aGFsIHNob290aW5ncywgaXQgaXMgSnVseSBhcyB0aGUgbW9udGggd2l0aCB0aGUgbW9zdCBzaG9vdGluZ3MgYW5kIEJyb29rbHluIGFzIHRoZSBib3JvdWdoIHdpdGggdGhlIGdyZWF0ZXN0IG1ham9yaXR5IGluIEp1bHksIHdoaWxlIEZlYnJ1YXJ5IGlzIHRoZSBtb250aCB3aXRoIHRoZSBsZWFzdCBzaG9vdGluZ3MgYW5kIEJyb29rbHluIGFzIHRoZSBib3JvdWdoIHdpdGggdGhlIGdyZWF0ZXN0IG1ham9yaXR5IGluIEZlYnJ1YXJ5DQpUaHJvdWdob3V0IGFsbCB0aGUgbW9udGhzIEJyb29rbHluIGhhZCBhbiBvdmVyd2hlbG1pbmcgbWFqb3JpdHkgb2Ygc2hvb3RpbmdzIHdpdGggdGhlIGV4Y2VwdGlvbiBvZiBKYW51YXJ5IHdoZXJlIEJyb29rbHluIHNhdyBvbmx5IG9uZSBtb3JlIHNob290aW5nIHRoYW4gQnJvbnggIA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KbnljZmlyZWRjb3B5NEQgJT4lIA0KICBzZWxlY3QoYm9ybyxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZyxkYXlvZndlZWspICU+JSANCiAgZ3JvdXBfYnkoYm9ybyxkYXlvZndlZWssc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgc3VtbWFyaXplKGNvdW50PW4oKSkgJT4lIA0KZ2dwbG90KGFlcyhkYXlvZndlZWssY291bnQsZmlsbD1ib3JvKSkrdGhlbWVfY2xhc3NpYygpK2dlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykrDQogIGdndGl0bGUoJ0RhaWx5IFNob290aW5nIGJ5IHdlZWtkYXkgYW5kIGJvcm91Z2ggJykrdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpK2Nvb3JkX2ZsaXAoKQ0KYGBgDQpmb3Igbm9uIGxldGhhbCBzaG9vdGluZ3MgQnJvb2tseW4gc2F3IHRoZSBoaWdoZXN0IGNvdW50IG9uIGJvdGggU3VuZGF5cyBhbmQgU2F0dXJkYXlzLCBPbiBTYXR1cmRheXMsDQoNCg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KDQpueWNmaXJlZGNvcHk0RCAlPiUNCiAgc2VsZWN0KG1vbnRoLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnLHllYXIsYm9ybykgJT4lIA0KICBncm91cF9ieSh5ZWFyLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnLGJvcm8pICU+JSANCiAgc3VtbWFyaXplKGNvdW50PW4oKSkgJT4lIA0KZ2dwbG90KGFlcyh5ZWFyLGNvdW50LGZpbGw9Ym9ybykpK3RoZW1lX2NsYXNzaWMoKStnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpKw0KDQogIGdndGl0bGUoJ1Nob290aW5nIHBlciB5ZWFyIGFuZCBib3JvdWdoICcpK3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKStjb29yZF9mbGlwKCkNCmBgYA0KZmlyc3QsIG91dCBvZiB0aGUgZml2ZSBib3JvdWdocyBpdCB3YXMgQnJvb2tseW4gYW5kIEJyb254IHRoYXQgc2F3IHRoZSBtb3N0IG5vbiBsZXRoYWwgc2hvb3RpbmdzIGV2ZXJ5IHllYXINCg0KDQoNCjxicj4NCjxicj4NCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQpueWNmaXJlZGNvcHk0RCAlPiUgDQogICNmaWx0ZXIoeWVhciA8PSAyMDE5KSAlPiUgDQogIGdyb3VwX2J5KGRheW9md2Vlayxtb250aCxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICBzdW1tYXJpemUoY291bnQ9bigpKSAlPiUgDQogIGdncGxvdChhZXMoZGF5b2Z3ZWVrLG1vbnRoLGZpbGw9Y291bnQpKSsNCiAgZ2VvbV90aWxlKGNvbG9yPSd3aGl0ZScsbGluZXdpZHRoID0gLjUsbGluZXR5cGUgPSAxKSt0aGVtZV9kYXJrKCkrZ2d0aXRsZSgnSGVhdCBNYXAgb2YgU2hvb3RpbmdzIGJ5IERheSBhbmQgTW9udGgnKSsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNvdW50KSxjb2w9J3llbGxvdycsc2l6ZT0zLjIpK2ZhY2V0X3dyYXAofnN0YXRpc3RpY2FsX211cmRlcl9mbGFnLG5yb3c9MixzY2FsZXMgPSAnZnJlZScpDQpgYGANCkZyb20gMjAwNiB0byAyMDE5IGl0IGlzIGNsZWFyIHRoYXQgZHVyaW5nIEp1bmUsIEp1bHksIEF1Z3VzdCBhbmQgaW4gc29tZSBjYXNlcyBNYXkgd2UgaGF2ZSB0aGUgaGlnaGVzdCBjb3VudHMgb2Ygbm9uIGxldGhhbCBzaG9vdGluZ3Mgb2NjdXJyaW5nIG9uIFN1bmRheSB3aXRoIEp1bHkgJiBBdWd1c3QgcmVhY2hpbmcgb3ZlciAyMDAgd2hpbGUgSnVuZSxKdWx5LEF1Z3VzdCBhbmQgTWF5IHdlIGhhZCBTaG9vdGluZyBjb3VudHMgdW5kZXIgMjAwIGJ1dCBzdXJwYXNzaW5nIDE1MCB0YWtpbmcgcGxhY2Ugb24gU2F0dXJkYXlzIHdoZXJlYXMgdGhyb3VnaG91dCBhbGwgb3RoZXIgcGVyaW9kcyBvZiB0aGUgd2VlayBzaG9vdGluZ3MgdGVuZCB0byBhbGwgYmUgYmVsb3cgMTUwIHRvbyBldmVuIGJlbG93IDEwMA0KDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQoNCiBueWNmaXJlZGNvcHk0RCAlPiUgDQogIyBmaWx0ZXIoeWVhcjw9MjAxOSkgJT4lIA0KICAgZ3JvdXBfYnkoZGF5LG1vbnRoLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcml6ZShUb3RhbD1uKCkpICU+JSANCiAgDQogIGdncGxvdChhZXMoZGF5LG1vbnRoLGZpbGw9VG90YWwpKSsNCiAgZ2VvbV90aWxlKGNvbG9yPSd3aGl0ZScsbGluZXdpZHRoID0gLjUsbGluZXR5cGUgPSAxKSt0aGVtZV9kYXJrKCkrZ2d0aXRsZSgnSGVhdCBNYXAgb2Ygbm9uLWxldGhhbCBTaG9vdGluZ3MgcGVyIERheSBhbmQgTW9udGgnKSsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFRvdGFsKSxjb2w9J3llbGxvdycsc2l6ZT0yLjgpDQpgYGANCml0IGlzIEphbnVhcnkgMSB0aGF0IHdlIHNlZSB0aGUgaGlnaGVzdCBjb3VudCBvZiBub24gbGV0aGFsIHNob290aW5ncyBhdCA1MQ0KYWxsIHRvZ2V0aGVyIHRoZSBncmVhdGVzdCBtYWpvcml0eSBvZiBzaG9vdGluZ3MgYXJlIHdpdGhpbiB0aGUgZmlyc3QgMjAgZGF5cw0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCiBueWNmaXJlZGNvcHk0RCAlPiUgDQogICNmaWx0ZXIoeWVhcjw9MjAxOSkgJT4lIA0KICAgZ3JvdXBfYnkoeWVhcixtb250aCxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICBzdW1tYXJpemUoVG90YWw9bigpKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKG1vbnRoLHllYXIsZmlsbD1Ub3RhbCkpKw0KICBnZW9tX3RpbGUoY29sb3I9J3doaXRlJyxsaW5ld2lkdGggPSAuNSxsaW5ldHlwZSA9IDEpK3RoZW1lX2RhcmsoKStnZ3RpdGxlKCdIZWF0IE1hcCBvZiBub24gbGV0aGFsIFNob290aW5ncyBwZXIgTW9udGggYW5kIFllYXInKSsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFRvdGFsKSxjb2w9J3llbGxvdycsc2l6ZT0yLjgpDQpgYGANCkp1bHkgb2YgMjAwNyBhbmQgYXVndXN0IDIwMDggaGFkIG1vc3Qgbm9uIGxldGhhbCBzaG9vdGluZ3MNCnRoZSBsYXRlIHNwcmluZyB0byBzdW1tZXIgbW9udGhzIG9mIDIwMDYsMjAwNyBhbmQgMjAwOCBzYXcgdGhlIGdyZWF0ZXN0IG51bWJlciBvZiBub24gbGV0aGFsIHNob290aW5ncw0KYGBge3J9DQojdHJlbmQNCm55Y2ZpcmVkY29weTRUIDwtIG55Y2ZpcmVkY29weTREDQoNCm55Y2ZpcmVkY29weTRUIDwtIG55Y2ZpcmVkY29weTRUICU+JSANCiAgc2VsZWN0KC1jKGRheW9md2Vlayxtb250aCxkYXksKSkNCmBgYA0KDQo8YnI+DQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KbnljZmlyZWRjb3B5NFQgJT4lIA0KICMgZmlsdGVyKHllYXIgPD0yMDE5KSAlPiUgDQogIHNlbGVjdCh5ZWFyLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIGdyb3VwX2J5KHllYXIsc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgc3VtbWFyaXNlKHRvdGFsPW4oKSkgICU+JSANCmdncGxvdChhZXMoeWVhcix0b3RhbCxjb2w9c3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpKSsNCiAgZ2VvbV9saW5lKGxpbmV3aWR0aD0xLjEpK2dlb21fcG9pbnQoc2l6ZT0yLjIsY29sPSdibGFjaycpK3RoZW1lX2NsYXNzaWMoKStnZ3RpdGxlKCdPdmVyYWxsIGFubnVhbCB0cmVuZCBvZiBub24tbGV0aGFsIFNob290aW5ncycpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHRvdGFsKSxjb2w9J2JsYWNrJyxzaXplPTIuOCx2anVzdD0yKStnZW9tX3Ntb290aChzZT1GLGx0eT0yLGNvbD0nYmxhY2snLGxpbmV3aWR0aD0xKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnbm9uZScpDQpgYGANCmluIDIwMDggdGhlIG51bWJlciBvZiBvdmVyYWxsIHNob290aW5ncyByZWFjaGVkIGl0cyB6ZW5pdGggb2YgODc1IG5vbiBsZXRoYWwgc2hvb3RpbmdzIG9ubHkgdG8gdGhlbiBzbG93bHkgZHJvcCB0byAzOTIgc2hvb3RpbmdzIHRocm91Z2hvdXQgTllDLiBUaGlzIGFtYXppbmcgZG93biB0cmVuZCBpbiBzaG9vdGluZ3MgY2xlYXJseSBpbmRpY2F0ZXMgc29tZSBmb3JtIG9mIHN1YnN0YW50aWFsIGNoYW5nZSB0byBsaWZlIGluIE5ZQyB3aGV0aGVyIGl0IGJlIGVjb25vbWljYWwgb3IgY3JpbWUgcmVsYXRlZC4gDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCm55Y2ZpcmVkY29weTRUICU+JSANCiAgZmlsdGVyKHllYXIgPD0yMDE5KSAlPiUgDQogIHNlbGVjdCh5ZWFyLGJvcm8sc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgZ3JvdXBfYnkoeWVhcixib3JvLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcmlzZSh0b3RhbD1uKCkpICU+JSANCmdncGxvdChhZXMoeWVhcix0b3RhbCxjb2w9c3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpKSsNCiAgZ2VvbV9saW5lKCkrZ2VvbV9wb2ludCgpK3RoZW1lX2RhcmsoKStnZ3RpdGxlKCdhbm51YWwgdHJlbmQgb2YgU2hvb3RpbmdzIGFuZCBCb3JvdWdoJykrDQogDQogIGZhY2V0X3dyYXAofmJvcm8sbnJvdz0yLHNjYWxlcyA9ICdmcmVlX3gnKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnbm9uZScpDQpgYGANCg0KQnJvb2tseW4gYW5kIEJyb254IGhhZCB0aGUgaGlnaGVzdCBwZWFrcyBvZiBzaG9vdGluZ3MgaW4gdGhlIG1pZCAyMDAwJ3MgYW5kIHNpbmNlIHRoZW4gd2UndmUgc2VlIGEgdHJlbmQgc2hvd2luZyB0aGUgZ3JlYXRlc3QgZGVjbGluZSBpbiBvdmVyYWxsIHNob290aW5ncyB3aGVyZWFzIHRoZSBvdGhlciBib3JvdWdocyByZW1haW5lZCByZWxhdGl2ZWx5IHN0YWJsZS4gIA0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KbnljZmlyZWRjb3B5NEQgJT4lIA0KICBmaWx0ZXIoeWVhciA8PTIwMTkpICU+JSANCiAgc2VsZWN0KG1vbnRoLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIGdyb3VwX2J5KG1vbnRoLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcmlzZSh0b3RhbD1uKCkpICU+JSANCmdncGxvdChhZXMobW9udGgsdG90YWwsZmlsbD1zdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykpK3RoZW1lX2NsYXNzaWMoKSsNCiAgZ2VvbV9jb2woKStnZ3RpdGxlKCdNb250aGx5IHRyZW5kIG9mIFNob290aW5ncyAnKStnZW9tX3Ntb290aChzZT1GLGx0eT0yLGNvbD0nYmxhY2snLGxpbmV3aWR0aD0xKSsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHRvdGFsKSxjb2w9J2JsYWNrJyxzaXplPTMuNCkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnKQ0KYGBgDQoNCnRoZSBwbG90IHNob3dzIHRoYXQgZ29pbmcgaW50byB0aGUgZmFsbCBvciBhdXR1bW4gc2Vhc29uIHNob290aW5ncyBhcmUgb24gYSBkZWNsaW5lIGFuZCBoaXQgdGhlaXIgbG93ZXN0IHBvaW50IGluIEZlYnJ1YXJ5IGF0IHdoaWNoIHBvaW50IHdlIHNlZSBhIHNoYXJwIHJpc2luZyB0cmVuZCBlc3BlY2lhbGx5IGluIG5vbiBsZXRoYWwgc2hvb3RpbmdzIHVudGlsIHdlIHJlYWNoIHRoZSBtb250aCBvZiB0aGUgemVuaXRoIHBvaW50cyBvZiBKdWx5IGFuZCBBdWd1c3QgZnJvbSB3aGljaCB0aGVuIGRyb3AgaW4gc2hvb3RpbmdzIHRoZW4gYmVnaW5zICAgDQoNCnRoZSBhYm92ZSBwbG90IGluZGljYXRlcyB0aGF0IEp1bHkgaXMgdGhlIG1vbnRoIHdpdGggaGlnaGVzdCB0b3RhbCBjb3VudCBvZiBub24gbGV0aGFsIHNob290aW5ncw0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQpueWNmaXJlZGNvcHk0RCAlPiUgDQogIGZpbHRlcih5ZWFyIDw9MjAxOSkgJT4lIA0KICBzZWxlY3QoZGF5b2Z3ZWVrLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIGdyb3VwX2J5KGRheW9md2VlayxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lDQogIHN1bW1hcmlzZSh0b3RhbD1uKCkpICU+JSANCmdncGxvdChhZXMoZGF5b2Z3ZWVrLHRvdGFsLGZpbGw9c3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpKSt0aGVtZV9jbGFzc2ljKCkrDQogICNnZW9tX2xpbmUobGluZXdpZHRoPS45NSkrZ2VvbV9wb2ludCgpDQpnZW9tX2NvbCgpK2dndGl0bGUoJ1NldmVuIERheSB0cmVuZCBvZiBTaG9vdGluZ3MnKStnZW9tX3Ntb290aChzZT1GLGx0eT0yLGNvbD0nYmxhY2snLGxpbmV3aWR0aD0xKSsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHRvdGFsKSxjb2w9J2JsYWNrJyxzaXplPTMuMikrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnKQ0KYGBgDQp0aGUgaGlnaGVzdCBhbW91bnQgb2Ygbm9uIGxldGhhbCBzaG9vdGluZ3Mgb2NjdXIgb24gU3VuZGF5cyBhbmQgU2F0dXJkYXlzIHdoaWxlIHRoZSBsb3dlc3QgdG90YWwgc2hvb3RpbmdzIG9jY3VyIG9uIFRodXJzZGF5cw0KDQoNCjxicj4NCg0KYGBge3J9DQoNCm55Y2ZpcmVkY29weTRUICU+JSANCiAgZmlsdGVyKHllYXI8PSAyMDE5KSAlPiUgDQpnZ3Bsb3QoYWVzKGxvbmdpdHVkZSxsYXRpdHVkZSkpKw0KICBnZW9tX3BvaW50KHNpemU9MSxjb2xvcj0ncHVycGxlJykrDQogICNzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMobWluX2xvbmcsbWF4X2xvbmcpKSsNCiAjIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9YyhtaW5fbGF0LG1heF9sYXQpKSsNCiAgdGhlbWVfbWFwKCkrZ2d0aXRsZSgnTWFwIG9mIHNob290aW5ncyBub3QgcmVzdWx0aW5nIGluIG11cmRlciB0aHJvdWdob3V0IE5ldyBZb3JrJykNCmBgYA0KDQoNCg0KYGBge3J9DQpgYGANCg0KQ29uY2x1c2lvbg0KDQo8b2w+DQo8bGk+DQpTaG9vdGluZ3MgdGVuZCB0byBpbmNyZWFzZSBpbiB0aGUgc3ByaW5nIGFuZCBzdW1tZXIgbW9udGhzIGFuZCBkZWNyZWFzZSBpbiB0aGUgYXV0dW1uIHRvIHdpbnRlciBtb250aHMNCjwvbGk+DQo8YnI+DQo8bGk+DQpUaGUgbW9udGhzIG9mIEp1bHkgYW5kIEF1Z3VzdCBoYWQgdGhlIGhpZ2hlc3QgY291bnRzIG9mIHNob290aW5ncyBmb2xsb3dlZCBieSBKdW5lIGFuZCBNYXkNCjwvbGk+DQo8YnI+DQo8bGk+IA0KQnJvb2tseW4gaGFkIHRoZSBtb3N0IG92ZXJhbGwgc2hvb3RpbmdzIGZvbGxvd2VkIGJ5IHRoZSBCcm9ueA0KPC9saT4NCjxicj4NCjxsaT4NCkJyb29rbHluIGhhZCB0aGUgbW9zdCBzaG9vdGluZ3MgcGVyIG1vbnRoIGZvbGxvd2VkIGJ5IHRoZSBCcm9ueA0KPC9saT4NCjxicj4NCjxsaT4NCkJyb29rbHluIGhhZCB0aGUgbW9zdCBzaG9vdGluZ3MgcGVyIHdlZWtkYXkgZm9sbG93ZWQgYnkgdGhlIEJyb254DQo8L2xpPg0KPGJyPg0KPGxpPg0KQnJvb2tseW4gaGFkIHRoZSBtb3N0IHNob290aW5ncyBwZXIgeWVhciBmb2xsb3dlZCBieSB0aGUgQnJvbnggZXhjZXB0IGZvciB0aGUgeWVhciAyMDE4DQo8L2xpPg0KPGJyPg0KPGxpPg0KU3VuZGF5cyBhbmQgU2F0dXJkYXlzIHdlcmUgdGhlIGRheXMgdGhyb3VnaG91dCB0aGUgd2VlayB0aGF0IGFjY291bnRlZCBmb3IgdGhlIG1ham9yaXR5IG9mIHNob290aW5ncw0KPC9saT4NCjxicj4NCjxsaT4NClRoZSBncmVhdGVzdCBtYWpvcml0eSBvZiBoaWdoIHZvbHVtZSBzaG9vdGluZ3Mgb2NjdXJyZWQgd2l0aGluIHRoZSBmaXJzdCAyMCBkYXlzIG9mIHRoZSBtb250aA0KPC9saT4NCjxicj4NCjxsaT4NClRoZSBtb250aHMgb2YgSnVseSAyMDA3IGFuZCBBdWd1c3QgMjAwOCBib3RoIHNoYXJlZCB0aGUgZ3JlYXRlc3QgbnVtYmVyIG9mIHNob290aW5ncyBhdCAxMTAgd2hpbGUgTWF5IHRocm91Z2ggQXVndXN0IG9mIDIwMDYsMjAwNywyMDA4IGFzIHdlbGwgYXMgTWF5IG9mIDIwMDkgaGFkIHNob290aW5ncyB0aGF0IHdlcmUgYWJvdmUgb3Igc2xpZ2h0bHkgYmVsb3cgMTAwDQo8L2xpPg0KPGJyPg0KPGxpPg0KaXQgYWxzbyBzZWVtcyB0aGF0IGZyb20gMjAwNiB0byAyMDE5IHNob290aW5ncyB0aHJvdWdob3V0IE5ZQyBleHBlcmllbmNlZCBhIHN0cm9uZyBkb3dudHJlbmQgYXMgdGhleSBkcm9wcGVkIGZyb20gODc1IGluIDIwMDggdG8gMzkyIGluIDIwMTkgYW5kIHdoZXJlIHRoaXMgdHJlbmQgd2FzIG1vc3Qgbm90aWNlYWJsZSBpbiBCcm9va2x5biBhbmQgQnJvbnggDQo8L2xpPg0KPC9vbD4NCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg==