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
sum(is.na(nycfiredcopy4B)) #we have 78 null values
summary(is.na(nycfiredcopy4B)) # all variables except for incident_key contains Null values
nycfiredcopy4B <- na.omit(nycfiredcopy4B)
sum(duplicated(nycfiredcopy4B)) # no duplicates
sum(is.na(nycfiredcopy4B)) #no null values / NA
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)
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)
ggplot(daily_monthly_shooting,aes(reorder(Total,day),Total,fill=month))+
geom_col(, linewidth=5)+
ggtitle('Shootings by Day and month')+
theme_dark()+scale_fill_manual(values=colors)+theme(axis.text.x = element_text(angle = 90))+xlab('day')+theme(legend.position = 'none')
#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
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
#trend
nycfiredcopy4T <- nycfiredcopy4D
nycfiredcopy4T <- nycfiredcopy4T %>%
select(-c(dayofweek,month,day,))
nycfiredcopy4T %>%
# filter(year <=2019) %>%
select(year,statistical_murder_flag) %>%
group_by(year,statistical_murder_flag) %>%
summarise(total=n()) %>%
ggplot(aes(year,total,col=statistical_murder_flag))+
geom_line(linewidth=1.1)+geom_point(size=2.2,col='black')+theme_classic()+ggtitle('Overall annual trend of non-lethal Shootings') +
geom_text(aes(label = total),col='black',size=2.8,vjust=2)+geom_smooth(se=F,lty=2,col='black',linewidth=1)+theme(legend.position = 'none')
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 highest points of July and August from which then
drops 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')
Findings
-
Shootings tend to increase in the spring and summer months and decrease
in the autumn to winter months
-
The months of July and August had the highest counts of shootings
followed by June and May
-
Brooklyn had the most overall shootings followed by the Bronx
-
Brooklyn had the most shootings per month followed by the Bronx
-
Brooklyn had the most shootings per weekday followed by the Bronx
-
Brooklyn had the most shootings per year followed by the Bronx except
for the year 2018
-
Sundays and Saturdays were the days throughout the week that accounted
for the majority of shootings
-
The greatest majority of high volume shootings occurred within the first
20 days of the month
-
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
-
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
Insights:
What the city can do despite the declining trend in year after year
non lethal shootings is reform policies that would provide summer time
recreational activities, shelters for the homeless, drug rehab programs,
therapy as well as provide any potential perpetrator with jobs which
would then greatly mitigate the number of shootings accounted for
throughout the summer months.
LS0tDQp0aXRsZTogIkVEQSBvbiBOWUMgc2hvb3RpbmdzIGJldHdlZW4gMjAwNiBhbmQgMjAxOSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KYXV0aG9yOiBIYXJyaXNvbg0KLS0tDQo8YnI+DQo8YnI+DQpUaGUgb2JqZWN0aXZlIG9mIHRoaXMgYW5hbHlzaXMgd2FzIHRvIGV4cGxvcmUgdGhlIHNob290aW5nIGluY2lkZW5jZXMgdGhhdCB0b29rIHBsYWNlIHRocm91Z2hvdXQgTmV3IFlvcmsgQ2l0eSBmcm9tIDIwMDYgdG8gMjAyMiAoSSBmb2N1c2VkIHByaW1hcmlseSBvbiAyMDA2IHRvIDIwMTkgYXMgSSBmZWx0IHRoYXQgcG9saWN5IGNoYW5nZXMsIGFuIGVsZWN0aW9uIGFuZCBldmVyeXRoaW5nIGdvaW5nIG9uIHdpdGggdGhlIENvdmlkLTE5IHBhbmRlbWljIHdvdWxkIHBsYXkgdG9vIG11Y2ggdGhlIHBhcnQgb2YgYW4gZXh0cmVtZSBpbmZsdWVuY2UpLiBJIGxvb2tlZCB0byBleGFtaW5lIGJvdGggbGV0aGFsIGFuZCBub24gbGV0aGFsIHNob290aW5ncyB3aXRoICB3aGVyZSBhbmQgd2hlbiB0aGV5IG9jY3VycmVkIHRvIHNlZSB3aGF0IHBhdHRlcm5zL3RyZW5kcyBtaWdodCBiZSBvYnRhaW5lZC4NCg0KRm9yIHRoaXMgYW5hbHlzaXM6IDxicj4NCkkgdXNlZCB2aXN1YWxpemF0aW9ucyBzdWNoIGFzIGJhciBjaGFydHMsIGxpbmUgY2hhcnRzLCBoZWF0bWFwcywgYW5kIG1hcHMuDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KERUKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGdndGhlbWVzKQ0KbGlicmFyeShyZWFkeGwpDQoNCmBgYA0KDQoNCg0KYGBge3IsZWNobz1GQUxTRX0NCm55Y2ZpcmVkY29weTRCIDwtICByZWFkX3hsc3goIkM6L1VzZXJzL3RoZXB5L0Rvd25sb2Fkcy9SZWNlbnQgRGF0YSBjc3Ygb3IgeGxzeCBkb3dubG9hZHMgdG8gYW5hbHl6ZS9OWVBEX1Nob290aW5nX0luY2lkZW50X0RhdGEueGxzeCIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0Kc3VtKGR1cGxpY2F0ZWQobnljZmlyZWRjb3B5NEIpKSAjIG5vIGR1cGxpY2F0ZXMNCnN1bShpcy5uYShueWNmaXJlZGNvcHk0QikpICN3ZSBoYXZlIDc4IG51bGwgdmFsdWVzDQoNCnN1bW1hcnkoaXMubmEobnljZmlyZWRjb3B5NEIpKSAjIGFsbCB2YXJpYWJsZXMgZXhjZXB0IGZvciBpbmNpZGVudF9rZXkgY29udGFpbnMgTnVsbCB2YWx1ZXMNCg0KbnljZmlyZWRjb3B5NEIgPC0gbmEub21pdChueWNmaXJlZGNvcHk0QikNCnN1bShkdXBsaWNhdGVkKG55Y2ZpcmVkY29weTRCKSkgIyBubyBkdXBsaWNhdGVzDQpzdW0oaXMubmEobnljZmlyZWRjb3B5NEIpKSAjbm8gbnVsbCB2YWx1ZXMgLyBOQQ0KYGBgDQoNCg0KYGBge3IsaW5jbHVkZT1GQUxTRX0NCm55Y2ZpcmVkY29weTRCIDwtIG55Y2ZpcmVkY29weTRCICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUgDQogIG11dGF0ZV9pZihpcy5jaGFyYWN0ZXIsYXMuZmFjdG9yKSAlPiUgDQogIG11dGF0ZShvY2N1cl9kYXRlID0geW1kKG9jY3VyX2RhdGUpKQ0KDQoNCm55Y2ZpcmVkY29weTRDIDwtIG55Y2ZpcmVkY29weTRCDQoNCg0KbnljZmlyZWRjb3B5NEMkeWVhciA8LSB5ZWFyKG55Y2ZpcmVkY29weTRDJG9jY3VyX2RhdGUpDQpueWNmaXJlZGNvcHk0QyRkYXkgPC0gZGF5KG55Y2ZpcmVkY29weTRDJG9jY3VyX2RhdGUpDQpueWNmaXJlZGNvcHk0QyRtb250aCA8LSBmYWN0b3IobW9udGgobnljZmlyZWRjb3B5NEMkb2NjdXJfZGF0ZSwgbGFiZWwgPSBUUlVFKSkNCiNueWNmaXJlZGNvcHk0QyR5ZWFyIDwtIGZhY3Rvcih5ZWFyKG55Y2ZpcmVkY29weTRDJG9jY3VyX2RhdGUpKQ0KbnljZmlyZWRjb3B5NEMkZGF5b2Z3ZWVrIDwtIGZhY3Rvcih3ZGF5KG55Y2ZpcmVkY29weTRDJG9jY3VyX2RhdGUsIGxhYmVsID0gVFJVRSkpDQoNCm55Y2ZpcmVkY29weTREPC0gbnljZmlyZWRjb3B5NEMgJT4lIA0KICBmaWx0ZXIoeWVhcjw9MjAxOSkgJT4lDQogIGZpbHRlcihzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZyA9PSdGQUxTRScpICU+JSANCiAgc2VsZWN0KC1jKG9jY3VyX2RhdGUsIHByZWNpbmN0LGp1cmlzZGljdGlvbl9jb2RlLHBlcnBfYWdlX2dyb3VwLHBlcnBfc2V4LHBlcnBfcmFjZSx2aWNfYWdlX2dyb3VwLHZpY19zZXgsdmljX3JhY2UsaW5jaWRlbnRfa2V5KSkNCmBgYA0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0NCmRhdGF2aWV3IDwtIG55Y2ZpcmVkY29weTRDICU+JSANCiAgcmVsb2NhdGUoaW5jaWRlbnRfa2V5LC5hZnRlciA9ICdvY2N1cl9kYXRlJykgJT4lIA0KICBzZWxlY3QoLWMobGF0aXR1ZGUsbG9uZ2l0dWRlLHllYXIsZGF5LG1vbnRoLGRheW9md2VlaykpDQpkYXRhdGFibGUoZGF0YXZpZXcpDQpgYGANCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCm55Y2ZpcmVkY29weTREIDwtIG55Y2ZpcmVkY29weTREICU+JSANCiAgcmVsb2NhdGUobW9udGgsLmJlZm9yZSA9ICdkYXknKQ0KYGBgDQoNCg0KYGBge3IsaW5jbHVkZT1GQUxTRX0NCm55Y2ZpcmVkY29weTREDQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShueWNmaXJlZGNvcHk0RCkNCmBgYA0KDQpCcm9va2x5biBoYXMgdGhlIG1vc3Qgc2hvb3RpbmdzDQpvbmx5IGZvY3VzZWQgb24gbm9uIG11cmRlci0NCnRoZXJlIGFyZSBmYXIgbW9yZSBzaG9vdGluZ3Mgbm90IGZsYWdnZWQgYXMgbXVyZGVyIHRoYW4gYXJlIGZsYWdnZWQgYXMgbXVyZGVyICg4NDIyIG5vIG11cmRlcikNCmZyb20gd2hhdCB3ZSBjYW4gc2VlIDIwMDggc2F3IHRoZSBtb3N0IHNob290aW5ncywNCkp1bHkgaXMgdGhlIG1vbnRoIHdpdGggdGhlIG1vc3Qgc2hvb3RpbmdzIA0KdGhlIG1vc3Qgc2hvb3RpbmdzIG9jY3VyIG9uIFNhdHVyZGF5cyxTdW5kYXlzLCBNb25kYXlzLCBGcmlkYXlzDQpgYGB7cn0NCmBgYA0KDQoNCg0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCmRhaWx5c2hvb3RpbmcgPC0gbnljZmlyZWRjb3B5NEQgJT4lIA0KICBncm91cF9ieShkYXksIHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcml6ZShUb3RhbCA9IG4oKSkNCmRhdGF0YWJsZShkYWlseXNob290aW5nKQ0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCg0KZ2dwbG90KGRhaWx5c2hvb3RpbmcsYWVzKGRheSxUb3RhbCkpK2dlb21fbGluZSgpKw0KICB0aGVtZV9jbGFzc2ljKCkgK2ZhY2V0X3dyYXAofnN0YXRpc3RpY2FsX211cmRlcl9mbGFnLHNjYWxlcyA9ICdmcmVlJykrdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpDQpgYGANCnRoZXJlIHNlZW1zIHRvIGJlIGEgc21hbGwgdXB0cmVuZCBpbiBzaG9vdGluZ3MgZHVyaW5nIHRoZSBmaXJzdCAyMCBkYXlzIGluIHRoZSBtb250aCBhbmQgdGhlbiBpbiB0aGUgbGFzdCAxMCBpdCBzdGVhZGlseSBkZWNsaW5lcw0KYGBge3J9DQpgYGANCg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KZGFpbHlfbW9udGhseV9zaG9vdGluZzwtIG55Y2ZpcmVkY29weTREICU+JSANCiAgZ3JvdXBfYnkobW9udGgsZGF5LHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcml6ZShUb3RhbCA9IG4oKSkgDQoNCmRhdGF0YWJsZShkYWlseV9tb250aGx5X3Nob290aW5nKQ0KYGBgDQoNCmBgYHtyLGluY2x1ZGU9RkFMU0V9DQpjb2xvcnMgPSBjKCJyZWQiLCAiZ3JlZW4iLCAib3JhbmdlIiwgImJsdWUiLCAieWVsbG93IiwgInB1cnBsZSIsICJibGFjayIsJ3BpbmsnLCdjeWFuJywnZ3JleScsJ2ZvcmVzdGdyZWVuJywgJ21hcm9vbicgKQ0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCmdncGxvdChkYWlseV9tb250aGx5X3Nob290aW5nLGFlcyhyZW9yZGVyKFRvdGFsLGRheSksVG90YWwsZmlsbD1tb250aCkpKw0KICBnZW9tX2NvbCgsIGxpbmV3aWR0aD01KSsNCiAgZ2d0aXRsZSgnU2hvb3RpbmdzIGJ5IERheSBhbmQgbW9udGgnKSsNCiAgdGhlbWVfZGFyaygpK3NjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jb2xvcnMpK3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSt4bGFiKCdkYXknKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnbm9uZScpDQpgYGANCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KI21vbnRoIHRvIHllYXIgdHJlbmQNCnNob290aW5nX21vbnRoX3llYXI8LSBueWNmaXJlZGNvcHk0RCAlPiUgDQogICNmaWx0ZXIoeWVhcjw9MjAxOSkgJT4lIA0KICBncm91cF9ieSh5ZWFyLG1vbnRoLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcml6ZShUb3RhbCA9IG4oKSkNCmRhdGF0YWJsZShzaG9vdGluZ19tb250aF95ZWFyKQ0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCm1vbnRoeWVhcjEgPC0gc2hvb3RpbmdfbW9udGhfeWVhciAlPiUgDQoNCmdncGxvdChhZXMoeWVhcixUb3RhbCxmaWxsPW1vbnRoKSkrdGhlbWVfY2xhc3NpYygpKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpKw0KICBnZ3RpdGxlKCdTaG9vdGluZ3MgcGVyIG1vbnRocyBhbmQgeWVhcicpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y29sb3JzKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnbm9uZScpDQptb250aHllYXIxDQoNCmBgYA0Kbm9uIGxldGhhbCBzaG9vdGluZ3Mgd2FzIGF0IGl0cyBoaWdoZXN0IGluIGJvdGggSnVseSBvZiAyMDA3IGFuZCBBdWd1c3QgMjAwOA0Kbm9uIGxldGhhbCBzaG9vdGluZ3Mgd2FzIGF0IGl0cyBsb3dlc3QgaW4gYm90aCBGZWJydWFyeSBvZiAyMDE4DQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0Kc2hvb3RpbmdzX21vbnRoX3dlZWtkYXk8LSBueWNmaXJlZGNvcHk0RCAlPiUNCiAgIyBmaWx0ZXIoeWVhcjw9MjAxOSkgJT4lIA0KICBncm91cF9ieShtb250aCxkYXlvZndlZWssc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgc3VtbWFyaXplKFRvdGFsID0gbigpKQ0KDQpkYXRhdGFibGUoc2hvb3RpbmdzX21vbnRoX3dlZWtkYXkpDQpgYGANCg0KDQpgYGB7cn0NCg0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCmdncGxvdChzaG9vdGluZ3NfbW9udGhfd2Vla2RheSxhZXMocmVvcmRlcihtb250aCxUb3RhbCksVG90YWwsZmlsbD1kYXlvZndlZWspKSt0aGVtZV9jbGFzc2ljKCkrDQogIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJywgbGluZXdpZHRoPTgpK2dndGl0bGUoJ1Nob290aW5ncyBieSBkYXlzIG9mIHdlZWsgYW5kIG1vbnRoJykrZmFjZXRfd3JhcCh+c3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcsbnJvdz0yLHNjYWxlcyA9ICdmcmVlJykrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jb2xvcnMpK3hsYWIoJ21vbnRoJykNCmBgYA0Kbm9uIGxldGhhbCBzaG9vdGluZ3Mgd2VyZSBhdCB0aGVyZSBwZWFrIG9uIFN1bmRheXMgaW4gdGhlIG1vbnRoIG9mIEp1bHkNCm5vbiBsZXRoYWwgc2hvb3RpbmdzIHdlcmUgYXQgdGhlcmUgbG93ZXN0IG9uIFRodXJzZGF5cyBpbiB0aGUgbW9udGggb2YgRmVicnVhcnkNCg0KDQpgYGB7cn0NCg0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCm55Y2ZpcmVkY29weTREICU+JSANCg0KICBzZWxlY3QoYm9ybyxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICAgDQogIGdyb3VwX2J5KGJvcm8sc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgc3VtbWFyaXplKGNvdW50PW4oKSkgJT4lIA0KZ2dwbG90KGFlcyhyZW9yZGVyKGJvcm8sY291bnQpLGNvdW50KSkrdGhlbWVfY2xhc3NpYygpKw0KICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScsZmlsbD0nb3JhbmdlJykrZ2VvbV90ZXh0KGFlcyhsYWJlbD1jb3VudCkpK2dndGl0bGUoJ1Nob290aW5nIHBlciBib3JvdWdoJykrdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpK3hsYWIoJ2Jvcm91Z2gnKQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQpueWNmaXJlZGNvcHk0RCAlPiUgIA0KICBzZWxlY3QoYm9ybyxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZyxtb250aCkgJT4lIA0KICBncm91cF9ieShib3JvLG1vbnRoLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcml6ZShjb3VudD1uKCkpICU+JSANCmdncGxvdChhZXMocmVvcmRlcihtb250aCxjb3VudCksY291bnQsZmlsbD1ib3JvKSkrdGhlbWVfY2xhc3NpYygpK2dlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykrDQogIA0KICBnZ3RpdGxlKCdNb250aGx5IFNob290aW5nIHBlciBib3JvdWdoICcpK3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKStjb29yZF9mbGlwKCkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpK3hsYWIoJ21vbnRoJykNCmBgYA0KZm9yIG5vbiBsZXRoYWwgc2hvb3RpbmdzLCBpdCBpcyBKdWx5IGFzIHRoZSBtb250aCB3aXRoIHRoZSBtb3N0IHNob290aW5ncyBhbmQgQnJvb2tseW4gYXMgdGhlIGJvcm91Z2ggd2l0aCB0aGUgZ3JlYXRlc3QgbWFqb3JpdHkgaW4gSnVseSwgd2hpbGUgRmVicnVhcnkgaXMgdGhlIG1vbnRoIHdpdGggdGhlIGxlYXN0IHNob290aW5ncyBhbmQgQnJvb2tseW4gYXMgdGhlIGJvcm91Z2ggd2l0aCB0aGUgZ3JlYXRlc3QgbWFqb3JpdHkgaW4gRmVicnVhcnkNClRocm91Z2hvdXQgYWxsIHRoZSBtb250aHMgQnJvb2tseW4gaGFkIGFuIG92ZXJ3aGVsbWluZyBtYWpvcml0eSBvZiBzaG9vdGluZ3Mgd2l0aCB0aGUgZXhjZXB0aW9uIG9mIEphbnVhcnkgd2hlcmUgQnJvb2tseW4gc2F3IG9ubHkgb25lIG1vcmUgc2hvb3RpbmcgdGhhbiBCcm9ueCAgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQpueWNmaXJlZGNvcHk0RCAlPiUgDQogIHNlbGVjdChib3JvLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnLGRheW9md2VlaykgJT4lIA0KICBncm91cF9ieShib3JvLGRheW9md2VlayxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICBzdW1tYXJpemUoY291bnQ9bigpKSAlPiUgDQpnZ3Bsb3QoYWVzKGRheW9md2Vlayxjb3VudCxmaWxsPWJvcm8pKSt0aGVtZV9jbGFzc2ljKCkrZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSsNCiAgZ2d0aXRsZSgnRGFpbHkgU2hvb3RpbmcgYnkgd2Vla2RheSBhbmQgYm9yb3VnaCAnKSt0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkrY29vcmRfZmxpcCgpDQpgYGANCmZvciBub24gbGV0aGFsIHNob290aW5ncyBCcm9va2x5biBzYXcgdGhlIGhpZ2hlc3QgY291bnQgb24gYm90aCBTdW5kYXlzIGFuZCBTYXR1cmRheXMsIE9uIFNhdHVyZGF5cywNCg0KDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQoNCm55Y2ZpcmVkY29weTREICU+JQ0KICBzZWxlY3QobW9udGgsc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcseWVhcixib3JvKSAlPiUgDQogIGdyb3VwX2J5KHllYXIsc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcsYm9ybykgJT4lIA0KICBzdW1tYXJpemUoY291bnQ9bigpKSAlPiUgDQpnZ3Bsb3QoYWVzKHllYXIsY291bnQsZmlsbD1ib3JvKSkrdGhlbWVfY2xhc3NpYygpK2dlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykrDQoNCiAgZ2d0aXRsZSgnU2hvb3RpbmcgcGVyIHllYXIgYW5kIGJvcm91Z2ggJykrdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpK2Nvb3JkX2ZsaXAoKQ0KYGBgDQpmaXJzdCwgb3V0IG9mIHRoZSBmaXZlIGJvcm91Z2hzIGl0IHdhcyBCcm9va2x5biBhbmQgQnJvbnggdGhhdCBzYXcgdGhlIG1vc3Qgbm9uIGxldGhhbCBzaG9vdGluZ3MgZXZlcnkgeWVhcg0KDQoNCg0KPGJyPg0KPGJyPg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCm55Y2ZpcmVkY29weTREICU+JSANCiAgI2ZpbHRlcih5ZWFyIDw9IDIwMTkpICU+JSANCiAgZ3JvdXBfYnkoZGF5b2Z3ZWVrLG1vbnRoLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcml6ZShjb3VudD1uKCkpICU+JSANCiAgZ2dwbG90KGFlcyhkYXlvZndlZWssbW9udGgsZmlsbD1jb3VudCkpKw0KICBnZW9tX3RpbGUoY29sb3I9J3doaXRlJyxsaW5ld2lkdGggPSAuNSxsaW5ldHlwZSA9IDEpK3RoZW1lX2RhcmsoKStnZ3RpdGxlKCdIZWF0IE1hcCBvZiBTaG9vdGluZ3MgYnkgRGF5IGFuZCBNb250aCcpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gY291bnQpLGNvbD0neWVsbG93JyxzaXplPTMuMikrZmFjZXRfd3JhcCh+c3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcsbnJvdz0yLHNjYWxlcyA9ICdmcmVlJykNCmBgYA0KRnJvbSAyMDA2IHRvIDIwMTkgaXQgaXMgY2xlYXIgdGhhdCBkdXJpbmcgSnVuZSwgSnVseSwgQXVndXN0IGFuZCBpbiBzb21lIGNhc2VzIE1heSB3ZSBoYXZlIHRoZSBoaWdoZXN0IGNvdW50cyBvZiBub24gbGV0aGFsIHNob290aW5ncyBvY2N1cnJpbmcgb24gU3VuZGF5IHdpdGggSnVseSAmIEF1Z3VzdCByZWFjaGluZyBvdmVyIDIwMCB3aGlsZSBKdW5lLEp1bHksQXVndXN0IGFuZCBNYXkgd2UgaGFkIFNob290aW5nIGNvdW50cyB1bmRlciAyMDAgYnV0IHN1cnBhc3NpbmcgMTUwIHRha2luZyBwbGFjZSBvbiBTYXR1cmRheXMgd2hlcmVhcyB0aHJvdWdob3V0IGFsbCBvdGhlciBwZXJpb2RzIG9mIHRoZSB3ZWVrIHNob290aW5ncyB0ZW5kIHRvIGFsbCBiZSBiZWxvdyAxNTAgdG9vIGV2ZW4gYmVsb3cgMTAwDQoNCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCg0KIG55Y2ZpcmVkY29weTREICU+JSANCiAjIGZpbHRlcih5ZWFyPD0yMDE5KSAlPiUgDQogICBncm91cF9ieShkYXksbW9udGgsc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgc3VtbWFyaXplKFRvdGFsPW4oKSkgJT4lIA0KICANCiAgZ2dwbG90KGFlcyhkYXksbW9udGgsZmlsbD1Ub3RhbCkpKw0KICBnZW9tX3RpbGUoY29sb3I9J3doaXRlJyxsaW5ld2lkdGggPSAuNSxsaW5ldHlwZSA9IDEpK3RoZW1lX2RhcmsoKStnZ3RpdGxlKCdIZWF0IE1hcCBvZiBub24tbGV0aGFsIFNob290aW5ncyBwZXIgRGF5IGFuZCBNb250aCcpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gVG90YWwpLGNvbD0neWVsbG93JyxzaXplPTIuOCkNCmBgYA0KaXQgaXMgSmFudWFyeSAxIHRoYXQgd2Ugc2VlIHRoZSBoaWdoZXN0IGNvdW50IG9mIG5vbiBsZXRoYWwgc2hvb3RpbmdzIGF0IDUxDQphbGwgdG9nZXRoZXIgdGhlIGdyZWF0ZXN0IG1ham9yaXR5IG9mIHNob290aW5ncyBhcmUgd2l0aGluIHRoZSBmaXJzdCAyMCBkYXlzDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KIG55Y2ZpcmVkY29weTREICU+JSANCiAgI2ZpbHRlcih5ZWFyPD0yMDE5KSAlPiUgDQogICBncm91cF9ieSh5ZWFyLG1vbnRoLHN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSAlPiUgDQogIHN1bW1hcml6ZShUb3RhbD1uKCkpICU+JSANCiAgDQogIGdncGxvdChhZXMobW9udGgseWVhcixmaWxsPVRvdGFsKSkrDQogIGdlb21fdGlsZShjb2xvcj0nd2hpdGUnLGxpbmV3aWR0aCA9IC41LGxpbmV0eXBlID0gMSkrdGhlbWVfZGFyaygpK2dndGl0bGUoJ0hlYXQgTWFwIG9mIG5vbiBsZXRoYWwgU2hvb3RpbmdzIHBlciBNb250aCBhbmQgWWVhcicpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gVG90YWwpLGNvbD0neWVsbG93JyxzaXplPTIuOCkNCmBgYA0KSnVseSBvZiAyMDA3IGFuZCBhdWd1c3QgMjAwOCBoYWQgbW9zdCBub24gbGV0aGFsIHNob290aW5ncw0KdGhlIGxhdGUgc3ByaW5nIHRvIHN1bW1lciBtb250aHMgb2YgMjAwNiwyMDA3IGFuZCAyMDA4IHNhdyB0aGUgZ3JlYXRlc3QgbnVtYmVyIG9mIG5vbiBsZXRoYWwgc2hvb3RpbmdzDQpgYGB7cn0NCiN0cmVuZA0KbnljZmlyZWRjb3B5NFQgPC0gbnljZmlyZWRjb3B5NEQNCg0KbnljZmlyZWRjb3B5NFQgPC0gbnljZmlyZWRjb3B5NFQgJT4lIA0KICBzZWxlY3QoLWMoZGF5b2Z3ZWVrLG1vbnRoLGRheSwpKQ0KYGBgDQoNCjxicj4NCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQpueWNmaXJlZGNvcHk0VCAlPiUgDQogIyBmaWx0ZXIoeWVhciA8PTIwMTkpICU+JSANCiAgc2VsZWN0KHllYXIsc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgZ3JvdXBfYnkoeWVhcixzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICBzdW1tYXJpc2UodG90YWw9bigpKSAgJT4lIA0KZ2dwbG90KGFlcyh5ZWFyLHRvdGFsLGNvbD1zdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykpKw0KICBnZW9tX2xpbmUobGluZXdpZHRoPTEuMSkrZ2VvbV9wb2ludChzaXplPTIuMixjb2w9J2JsYWNrJykrdGhlbWVfY2xhc3NpYygpK2dndGl0bGUoJ092ZXJhbGwgYW5udWFsIHRyZW5kIG9mIG5vbi1sZXRoYWwgU2hvb3RpbmdzJykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gdG90YWwpLGNvbD0nYmxhY2snLHNpemU9Mi44LHZqdXN0PTIpK2dlb21fc21vb3RoKHNlPUYsbHR5PTIsY29sPSdibGFjaycsbGluZXdpZHRoPTEpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykNCmBgYA0KaW4gMjAwOCB0aGUgbnVtYmVyIG9mIG92ZXJhbGwgc2hvb3RpbmdzIHJlYWNoZWQgaXRzIHplbml0aCBvZiA4NzUgbm9uIGxldGhhbCBzaG9vdGluZ3Mgb25seSB0byB0aGVuIHNsb3dseSBkcm9wIHRvIDM5MiBzaG9vdGluZ3MgdGhyb3VnaG91dCBOWUMuIFRoaXMgYW1hemluZyBkb3duIHRyZW5kIGluIHNob290aW5ncyBjbGVhcmx5IGluZGljYXRlcyBzb21lIGZvcm0gb2Ygc3Vic3RhbnRpYWwgY2hhbmdlIHRvIGxpZmUgaW4gTllDIHdoZXRoZXIgaXQgYmUgZWNvbm9taWNhbCBvciBjcmltZSByZWxhdGVkLiANCg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KbnljZmlyZWRjb3B5NFQgJT4lIA0KICBmaWx0ZXIoeWVhciA8PTIwMTkpICU+JSANCiAgc2VsZWN0KHllYXIsYm9ybyxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICBncm91cF9ieSh5ZWFyLGJvcm8sc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgc3VtbWFyaXNlKHRvdGFsPW4oKSkgJT4lIA0KZ2dwbG90KGFlcyh5ZWFyLHRvdGFsLGNvbD1zdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykpKw0KICBnZW9tX2xpbmUoKStnZW9tX3BvaW50KCkrdGhlbWVfZGFyaygpK2dndGl0bGUoJ2FubnVhbCB0cmVuZCBvZiBTaG9vdGluZ3MgYW5kIEJvcm91Z2gnKSsNCiANCiAgZmFjZXRfd3JhcCh+Ym9ybyxucm93PTIsc2NhbGVzID0gJ2ZyZWVfeCcpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykNCmBgYA0KDQpCcm9va2x5biBhbmQgQnJvbnggaGFkIHRoZSBoaWdoZXN0IHBlYWtzIG9mIHNob290aW5ncyBpbiB0aGUgbWlkIDIwMDAncyBhbmQgc2luY2UgdGhlbiB3ZSd2ZSBzZWUgYSB0cmVuZCBzaG93aW5nIHRoZSBncmVhdGVzdCBkZWNsaW5lIGluIG92ZXJhbGwgc2hvb3RpbmdzIHdoZXJlYXMgdGhlIG90aGVyIGJvcm91Z2hzIHJlbWFpbmVkIHJlbGF0aXZlbHkgc3RhYmxlLiAgDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQpueWNmaXJlZGNvcHk0RCAlPiUgDQogIGZpbHRlcih5ZWFyIDw9MjAxOSkgJT4lIA0KICBzZWxlY3QobW9udGgsc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgZ3JvdXBfYnkobW9udGgsc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JSANCiAgc3VtbWFyaXNlKHRvdGFsPW4oKSkgJT4lIA0KZ2dwbG90KGFlcyhtb250aCx0b3RhbCxmaWxsPXN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSkrdGhlbWVfY2xhc3NpYygpKw0KICBnZW9tX2NvbCgpK2dndGl0bGUoJ01vbnRobHkgdHJlbmQgb2YgU2hvb3RpbmdzICcpK2dlb21fc21vb3RoKHNlPUYsbHR5PTIsY29sPSdibGFjaycsbGluZXdpZHRoPTEpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gdG90YWwpLGNvbD0nYmxhY2snLHNpemU9My40KSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnbm9uZScpDQpgYGANCg0KdGhlIHBsb3Qgc2hvd3MgdGhhdCBnb2luZyBpbnRvIHRoZSBmYWxsIG9yIGF1dHVtbiBzZWFzb24gc2hvb3RpbmdzIGFyZSBvbiBhIGRlY2xpbmUgYW5kIGhpdCB0aGVpciBsb3dlc3QgcG9pbnQgaW4gRmVicnVhcnkgYXQgd2hpY2ggcG9pbnQgd2Ugc2VlIGEgc2hhcnAgcmlzaW5nIHRyZW5kIGVzcGVjaWFsbHkgaW4gbm9uIGxldGhhbCBzaG9vdGluZ3MgdW50aWwgd2UgcmVhY2ggdGhlIG1vbnRoIG9mIHRoZSBoaWdoZXN0IHBvaW50cyBvZiBKdWx5IGFuZCBBdWd1c3QgZnJvbSB3aGljaCB0aGVuIGRyb3BzIGluIHNob290aW5ncyB0aGVuIGJlZ2lucyAgIA0KDQp0aGUgYWJvdmUgcGxvdCBpbmRpY2F0ZXMgdGhhdCBKdWx5IGlzIHRoZSBtb250aCB3aXRoIGhpZ2hlc3QgdG90YWwgY291bnQgb2Ygbm9uIGxldGhhbCBzaG9vdGluZ3MNCg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KbnljZmlyZWRjb3B5NEQgJT4lIA0KICBmaWx0ZXIoeWVhciA8PTIwMTkpICU+JSANCiAgc2VsZWN0KGRheW9md2VlayxzdGF0aXN0aWNhbF9tdXJkZXJfZmxhZykgJT4lIA0KICBncm91cF9ieShkYXlvZndlZWssc3RhdGlzdGljYWxfbXVyZGVyX2ZsYWcpICU+JQ0KICBzdW1tYXJpc2UodG90YWw9bigpKSAlPiUgDQpnZ3Bsb3QoYWVzKGRheW9md2Vlayx0b3RhbCxmaWxsPXN0YXRpc3RpY2FsX211cmRlcl9mbGFnKSkrdGhlbWVfY2xhc3NpYygpKw0KICAjZ2VvbV9saW5lKGxpbmV3aWR0aD0uOTUpK2dlb21fcG9pbnQoKQ0KZ2VvbV9jb2woKStnZ3RpdGxlKCdTZXZlbiBEYXkgdHJlbmQgb2YgU2hvb3RpbmdzJykrZ2VvbV9zbW9vdGgoc2U9RixsdHk9Mixjb2w9J2JsYWNrJyxsaW5ld2lkdGg9MSkrDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSB0b3RhbCksY29sPSdibGFjaycsc2l6ZT0zLjIpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykNCmBgYA0KdGhlIGhpZ2hlc3QgYW1vdW50IG9mIG5vbiBsZXRoYWwgc2hvb3RpbmdzIG9jY3VyIG9uIFN1bmRheXMgYW5kIFNhdHVyZGF5cyB3aGlsZSB0aGUgbG93ZXN0IHRvdGFsIHNob290aW5ncyBvY2N1ciBvbiBUaHVyc2RheXMNCg0KDQo8YnI+DQoNCmBgYHtyfQ0KDQpueWNmaXJlZGNvcHk0VCAlPiUgDQogIGZpbHRlcih5ZWFyPD0gMjAxOSkgJT4lIA0KZ2dwbG90KGFlcyhsb25naXR1ZGUsbGF0aXR1ZGUpKSsNCiAgZ2VvbV9wb2ludChzaXplPTEsY29sb3I9J3B1cnBsZScpKw0KICAjc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKG1pbl9sb25nLG1heF9sb25nKSkrDQogIyBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMobWluX2xhdCxtYXhfbGF0KSkrDQogIHRoZW1lX21hcCgpK2dndGl0bGUoJ01hcCBvZiBzaG9vdGluZ3Mgbm90IHJlc3VsdGluZyBpbiBtdXJkZXIgdGhyb3VnaG91dCBOZXcgWW9yaycpDQpgYGANCg0KDQoNCmBgYHtyfQ0KYGBgDQoNCjxoMz5GaW5kaW5nczwvaDM+DQo8YnI+DQo8YnI+DQo8YnI+DQo8b2w+DQo8bGk+DQpTaG9vdGluZ3MgdGVuZCB0byBpbmNyZWFzZSBpbiB0aGUgc3ByaW5nIGFuZCBzdW1tZXIgbW9udGhzIGFuZCBkZWNyZWFzZSBpbiB0aGUgYXV0dW1uIHRvIHdpbnRlciBtb250aHMNCjwvbGk+DQo8YnI+DQo8bGk+DQpUaGUgbW9udGhzIG9mIEp1bHkgYW5kIEF1Z3VzdCBoYWQgdGhlIGhpZ2hlc3QgY291bnRzIG9mIHNob290aW5ncyBmb2xsb3dlZCBieSBKdW5lIGFuZCBNYXkNCjwvbGk+DQo8YnI+DQo8bGk+IA0KQnJvb2tseW4gaGFkIHRoZSBtb3N0IG92ZXJhbGwgc2hvb3RpbmdzIGZvbGxvd2VkIGJ5IHRoZSBCcm9ueA0KPC9saT4NCjxicj4NCjxsaT4NCkJyb29rbHluIGhhZCB0aGUgbW9zdCBzaG9vdGluZ3MgcGVyIG1vbnRoIGZvbGxvd2VkIGJ5IHRoZSBCcm9ueA0KPC9saT4NCjxicj4NCjxsaT4NCkJyb29rbHluIGhhZCB0aGUgbW9zdCBzaG9vdGluZ3MgcGVyIHdlZWtkYXkgZm9sbG93ZWQgYnkgdGhlIEJyb254DQo8L2xpPg0KPGJyPg0KPGxpPg0KQnJvb2tseW4gaGFkIHRoZSBtb3N0IHNob290aW5ncyBwZXIgeWVhciBmb2xsb3dlZCBieSB0aGUgQnJvbnggZXhjZXB0IGZvciB0aGUgeWVhciAyMDE4DQo8L2xpPg0KPGJyPg0KPGxpPg0KU3VuZGF5cyBhbmQgU2F0dXJkYXlzIHdlcmUgdGhlIGRheXMgdGhyb3VnaG91dCB0aGUgd2VlayB0aGF0IGFjY291bnRlZCBmb3IgdGhlIG1ham9yaXR5IG9mIHNob290aW5ncw0KPC9saT4NCjxicj4NCjxsaT4NClRoZSBncmVhdGVzdCBtYWpvcml0eSBvZiBoaWdoIHZvbHVtZSBzaG9vdGluZ3Mgb2NjdXJyZWQgd2l0aGluIHRoZSBmaXJzdCAyMCBkYXlzIG9mIHRoZSBtb250aA0KPC9saT4NCjxicj4NCjxsaT4NClRoZSBtb250aHMgb2YgSnVseSAyMDA3IGFuZCBBdWd1c3QgMjAwOCBib3RoIHNoYXJlZCB0aGUgZ3JlYXRlc3QgbnVtYmVyIG9mIHNob290aW5ncyBhdCAxMTAgd2hpbGUgTWF5IHRocm91Z2ggQXVndXN0IG9mIDIwMDYsMjAwNywyMDA4IGFzIHdlbGwgYXMgTWF5IG9mIDIwMDkgaGFkIHNob290aW5ncyB0aGF0IHdlcmUgYWJvdmUgb3Igc2xpZ2h0bHkgYmVsb3cgMTAwDQo8L2xpPg0KPGJyPg0KPGxpPg0KaXQgYWxzbyBzZWVtcyB0aGF0IGZyb20gMjAwNiB0byAyMDE5IHNob290aW5ncyB0aHJvdWdob3V0IE5ZQyBleHBlcmllbmNlZCBhIHN0cm9uZyBkb3dudHJlbmQgYXMgdGhleSBkcm9wcGVkIGZyb20gODc1IGluIDIwMDggdG8gMzkyIGluIDIwMTkgYW5kIHdoZXJlIHRoaXMgdHJlbmQgd2FzIG1vc3Qgbm90aWNlYWJsZSBpbiBCcm9va2x5biBhbmQgQnJvbnggDQo8L2xpPg0KPC9vbD4NCg0KYGBge3J9DQpgYGANCg0KPGgzPkluc2lnaHRzOjwvaDM+DQo8YnI+DQo8YnI+DQoNCldoYXQgdGhlIGNpdHkgY2FuIGRvIGRlc3BpdGUgdGhlIGRlY2xpbmluZyB0cmVuZCBpbiB5ZWFyIGFmdGVyIHllYXIgbm9uIGxldGhhbCBzaG9vdGluZ3MgaXMgcmVmb3JtIHBvbGljaWVzIHRoYXQgd291bGQgcHJvdmlkZSBzdW1tZXIgdGltZSByZWNyZWF0aW9uYWwgYWN0aXZpdGllcywgc2hlbHRlcnMgZm9yIHRoZSBob21lbGVzcywgZHJ1ZyByZWhhYiBwcm9ncmFtcywgdGhlcmFweSBhcyB3ZWxsIGFzIHByb3ZpZGUgYW55IHBvdGVudGlhbCBwZXJwZXRyYXRvciB3aXRoIGpvYnMgd2hpY2ggd291bGQgdGhlbiBncmVhdGx5IG1pdGlnYXRlIHRoZSBudW1iZXIgb2Ygc2hvb3RpbmdzIGFjY291bnRlZCBmb3IgdGhyb3VnaG91dCB0aGUgc3VtbWVyIG1vbnRocy4gIA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0K