Goals of this investigation

  1. see which charges are largest drivers of pretrial jail admissions
  2. outline demographics (age, race, gender) of those in pretrial detention
  3. show distribution of bond amounts (and show means by race)
  4. show distribution of jail stays (and show means by race)
  5. show relationship between bond amount and pretrial jail stay duration

Basic facts

Call the csv and clean up.

nrow(CT)
[1] 3534889

It has 3.53 million rows.

How many unique people are in the data?

#search unique by identifier
nrow(unique(CT[,"identifier"]))
[1] 34892

There are 34,892 unique people. But maybe some people have gone in and out of jail multiple times? So, how many unique person-admissions are there?

#search unique rows by identifier and latest admission date
nrow(unique(CT[,c("identifier","latest_admission_date")]))
[1] 50247

50,247 unique person-admissions.

Since an admission might be due to multiple charges, there might be more than 50K charges responsible for the ~50K admissions…

nrow(unique(CT[,c("identifier","latest_admission_date", "offense")]))
[1] 54367

Specifically, there are 54,367 total charges for all admissions in this data.

How many unique charges?

nrow(unique(CT[,c("offense")]))
[1] 348

1. Why in Jail?

Consider the previously mentioned ~54K charges.

charges<-unique(CT[,c("identifier","latest_admission_date", "offense")]) %>%
  group_by(offense)%>%
  summarise(count=n())%>%
  mutate(tot=sum(count), perc=count/tot)

Make a graph of top 10 charges.

library(stringr)

charges10<-subset(charges, charges$perc>.019)
charges10<-charges10[order(-charges10$perc),]

#fix up offense
charges10$offense<-tolower(charges10$offense)
charges10$offense<-str_remove(charges10$offense, " df")
charges10$offense<-str_remove(charges10$offense, "  f")
charges10$offense<-str_remove(charges10$offense, " am")
charges10$offense<-str_squish(charges10$offense)

Make a factor for ordering the x axis

charges10$offense<- factor(charges10$offense, levels = charges10$offense[order(charges10$perc)])

Before making graphs, I call libs.

#Load more libraries
library(ggplot2);library(ggrepel); library(extrafont); library(ggthemes);library(reshape);library(grid); library(dplyr)
library(scales);library(RColorBrewer);library(gridExtra)

I graph!

ggplot(data=charges10, aes(x=offense, y=perc)) + 
  geom_bar(stat = 'identity')+
  theme_minimal()+ theme(text=element_text(family="Palatino"))+
  scale_y_continuous(labels = percent, limits=c(0,.175), breaks=seq(0,.175,.025))+
  theme(plot.title = element_text(hjust = 0))+
  labs(x="", y="", caption="These calculations consider all 54,367 unique person-admission-offense observations from 7/1/16-7/28/19.")+
  theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1))+
  ggtitle("Why Are People in Jail? (Top 10 Charges)", subtitle = "Data Available via Connecticut Open Data")

ggsave("graphs/offense_top_10.png", width=7, height=7, dpi=900)

Note: this is not the same as looking at days in jail across offenses! This looking at admissions! Many of these are smaller so those inmates might be in and out pretty quickly.

2. Demographics

Gender/Race

First, let’s summarize by gender/race. Look at unique people over the whole time period.

CTpeople<-unique(CT[,c("identifier", "race", "gender")])

OK, there are 35,023 instead of 34,892. That means some people are being coded as different genders/races. Let’s check it out.

Let’s exclude the people coded with different race and/or genders across the time period.

CTpeople$dup<-duplicated(CTpeople, by="identifier")
CTpeopledup<-subset(CTpeople, dup=="TRUE")
CTpeopledup1<-CTpeopledup[,1]
CTpeopledup1$exclude<-1
CTpeople<-merge(CTpeople, CTpeopledup1, by ="identifier", all=T)
CTp<-subset(CTpeople, is.na(CTpeople$exclude))
CTp<-CTp[,c(1:3)]

Great, so now we use CTp to get into the race/gender demographics of the 34,761 people who are coded consistently (so, excluding the 131 inconsistent ones) and were inmates in CT correctional facilities from 7/1/2016-7/28/19.

I define some colorblind palettes.

# The palette with grey:
cbPalette <- c("#999999", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
Pal <- c("#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")

# The palette with black:
cbbPalette <- c("#000000", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")

I graph!

ggplot(data=CTp, aes(race, fill=gender)) + 
  geom_bar()+
  theme_minimal()+ theme(text=element_text(family="Palatino"))+
  scale_fill_manual(name="Gender", values = c("gold", "dodgerblue"), labels=c("Female", "Male")) +
  scale_y_continuous(limits=c(0,14000), breaks=seq(0,14000,2000))+
  theme(plot.title = element_text(hjust = 0))+
  labs(x="", y="Number of Pretrial Inmates", caption="The total number of unique pretrial inmates in this time period is 34,892; I present data for 34,761 here.\n(I exclude 131 individuals who are coded inconsistently by race or gender over time).\nThe dataset codes Hispanic as a race (this is different than, say, the Census methodology).")+
  ggtitle("Gender and Race of Connecticut Pretrial Inmates (7/1/16-7/28/19)", subtitle = "Data Available via Connecticut Open Data")

ggsave("graphs/gender_race.png", width=7, height=4.5, dpi=900)

In terms of over/underrepresentation, this is the usual story about whites and asians being underrepresented while black and hispanic people are overrepresented.

Make stacked bars, one for Census CT and one for pretrial inmates

CTrace<-CTp %>%
  group_by(race)%>%
  summarize(count=n()) %>%
  mutate(total=sum(count))%>%
  mutate(perc=count/total)

Manually add the census data, based on an approximation (since ethnicity, race done differently by the census) from this reference.

race <- c('Asian','Black','Hispanic', 'Native American', 'White')
c_perc <- c(.05, .12, .16, .005, .665)
census<-data.frame(race, c_perc)

Merge the census and pretrial.

CTrace_c<-merge(CTrace, census, by="race")

Reshape.

library(tidyr)

Attaching package: ‘tidyr’

The following objects are masked from ‘package:reshape’:

    expand, smiths
CTrace_c <- CTrace_c %>%
  gather(source, percent, perc:c_perc)

Make the plot.

ggplot(data=CTrace_c, aes(x=source, y=percent, fill=race)) + 
  geom_bar(stat = 'identity') +
  theme_minimal()+ theme(text=element_text(family="Palatino"))+
  scale_fill_manual(name="Race", values = cbPalette) +  
  theme(plot.title = element_text(hjust = 0))+
  labs(x="", y="", caption="The pretrial inmate population covers 34,761 people in DOC facilities 7/1/16-7/28/19.\n(I exclude 131 individuals who are coded inconsistently by race or gender over time).\nOverall Population data is estimated from the US Census QuickFacts.")+
  scale_y_continuous(labels = percent)+
  scale_x_discrete(labels=c("Overall Population", "Pretrial Inmate Population"))+ 
  ggtitle("Overall Connecticut Population vs. Connecticut Pretrial Inmate Population", subtitle = "Data Available via Connecticut Open Data")

ggsave("graphs/race_compare.png", width=7, height=5, dpi=900)

Age/race

Let’s see age/race for those as of 7-28-19.

CT19<-subset(CT, download_date=="2019-07-28")

I graph!

ggplot(data=CT19, aes(age, fill=race)) + 
  geom_histogram(breaks=seq(15, 80, by = 1)) +
  theme_minimal()+ theme(text=element_text(family="Palatino"))+
  scale_fill_manual(name="Race", values = cbPalette) +  
  theme(plot.title = element_text(hjust = 0))+
  labs(x="Age", y="Number of Pretrial Inmates", caption="This graphs covers only the 3,230 inmates present in DOC facilities on 7/28/19.")+
  scale_y_continuous(limits=c(0,126), breaks=seq(0,126,25))+
  scale_x_continuous(limits=c(15,81), breaks=seq(15,80,5))+ 
  ggtitle("Age and Race of Connecticut Pretrial Inmates (7/28/2019)", subtitle = "Data Available via Connecticut Open Data")

ggsave("graphs/age_race-7-28-19.png", width=8, height=5, dpi=900)

As expected skewed young compared to the overall population.

What’s the median age?

median(CT19$age)
[1] 33

This is (as expected) lower than the overall median for CT of ~41.


3. Bond amounts

Distribution

Let’s plot mean bond amounts with confidence intervals by race. Let’s then focus on the first instance of bail (first observation in the data).

In effect, we sort by download_date. Then we delete duplicates by identifier and latest_admission_date.

CTbond<-CT[order(CT$download_date, CT$identifier),]
CTbond<-CTbond[!duplicated(CTbond[,c("identifier", "latest_admission_date")]),]
nrow(unique(CTbond))
[1] 50247

No duplicates now by person and admission date. These are the 50,247 unique first instances of a person in for a certain admission date.

min(CTbond$bond_amount)
[1] 1
max(CTbond$bond_amount)
[1] 9000009

The bond amounts range from $1 (can that be right? – well, the code book mentions that bonds under $100 are probably place holders.) to $9,000,009.

How many bond amounts are $100 or under?

CTbond %>% 
  filter(bond_amount<100)%>%
  nrow()
[1] 104

Only 104 of 50,247 observations are under $100. Let’s exclude these since they are unlikely to be true bond amounts (according to the codebook).

CTbond <- CTbond %>% 
  filter(bond_amount>=100)
mean(CTbond$bond_amount)
[1] 85881.43
median(CTbond$bond_amount)
[1] 25100

The mean is $85881.43 and the median is $25,100. Seems shockingly high, but worth noting that this is likely higher than the overall bond mean since this data only covers those who are in jail some night. (Selection is important in understanding this mean.)

Can we visualize the distribution? Without a transformation, it’s super hard (impossible, actually) to see anything because there are huge values on the right (in the millions) but it’s mainly values on the left (but we can’t even see what those are).

CTbond<-merge(CTbond, CTp, by=c("identifier", "gender", "race"), all=F)
nrow(CTbond)
[1] 49817

I exclude those who are coded inconsistently by race or gender for the sake of consistency and that yields 49,817 unique first instances of a person in for a certain admission date.

ggplot(data=CTbond, aes(bond_amount, fill=race)) + geom_histogram(binwidth = .3) +
  scale_fill_manual(name="Race", values = cbPalette) +  
  theme_minimal()+ theme(text=element_text(family="Palatino"))+
  theme(plot.title = element_text(hjust = 0))+
  labs(x="Bond Amount ($)", y="Number of Pretrial Inmates", 
       caption="\nThis plot uses a log10 transformation of the bond amount axis.\nEach observation is the first observation of a person-admission. (n=49,817)\n(Again, I exclude individuals who are coded inconsistently by race or gender over time.)\nI consider the bond amount at first day observed in jail for a given date of admission.")+
  scale_x_log10(labels=comma)+
  scale_y_continuous(label=comma)+
  #scale_x_continuous(limits=c(15,80), breaks=seq(15,80,5))+ 
  ggtitle("Bond Amounts for Connecticut Pretrial Inmates (7/1/2016-7/28/2019)", subtitle = "Data Available via Connecticut Open Data")

ggsave("graphs/bond_dist_race.png", width=8, height=5, dpi=900)

It is clearer now to see where the big parts of the distribution are.

Mean by group

CTbondr<- CTbond[,c("race", "bond_amount", "age")] %>% 
    group_by(race) %>%
    summarise_all(funs(mean,sd,se=sd(.)/sqrt(n())))

Plot it.

#ggplot(CTbondr, aes(x=race, y=bond_amount_mean, colour=race)) + 
ggplot(CTbondr, aes(x=race, y=bond_amount_mean)) +
    geom_errorbar(aes(ymin=bond_amount_mean-(1.96*bond_amount_se), 
                      ymax=bond_amount_mean+(1.96*bond_amount_se)), width=.1) +
    geom_point()+
  #scale_color_manual(values = cbPalette) +  
  theme_minimal()+ theme(text=element_text(family="Palatino"))+
  theme(plot.title = element_text(hjust = 0))+
  labs(x="", y="Mean Bond Amount ($)", caption="I consider only the first observation of bond amount for a given admission (n=49,817).\nThe means by race are presented with 95% confidence intervals.")+
  scale_y_continuous(labels = comma, limits=c(0,110500), breaks=seq(0,110000,10000))+
  #scale_y_continuous(limits=c(0,151), breaks=seq(0,150,25))+
  ggtitle("Mean Bond of Connecticut Pretrial Inmates by Racial Group", subtitle = "Data Available via Connecticut Open Data")
ggsave("graphs/bond_race.png", width=6, height=5, dpi=900)

Clearly (in that the 95% CI’s don’t overlap) white people have lower bonds on average than black, asian, or hispanic people.


4. Time in jail pretrial

Want to focus on the unique person-admission (excluding people who are coded inconsistently over time) observations. I want to focus on people-admissions who are in jail and then are out of the sample. Ie, exclude those still in jail on 7-28-19.

Relevant note from codebook:

LATEST ADMISSION DATE: Most recent date in which the inmate has been admitted. In some instances, this may reflect an original date of admission to a correctional facility. Generally, if a date is more than one year old, an inmate should not be considered to have been held for the entire duration of that time.

So, conceptually, I want to consider the full dataset:

Then,

Last, subset to the earliest date in the data (since bond, facility could alter over time).

#CTp is the dataframe of IDs for consistently coded people
CTz<-merge(CT,CTp, by=c("identifier", "race", "gender"), all=F)

Make a new variable for length of time in jail for person-admission

CTz<- CTz %>% 
   group_by(identifier, latest_admission_date) %>%
   mutate(inmate_time = n())

Generate indicator for date being 7-28-19, take max by person-admission

CTz$d18 <- as.numeric(CTz$download_date == "2019-07-28")

CTz<- CTz %>% 
   group_by(identifier, latest_admission_date) %>%
   mutate(max.d18 = max(d18))

Exclude person-admissions for people still in jail for that admission.

CTz1<-subset(CTz, CTz$max.d18<1)

Now just consider the earliest datapoint for each.

CTz1<-CTz1[order(CTz1$download_date, CTz1$identifier),]
CTds<-CTz1[!duplicated(CTz1[,c("identifier", "latest_admission_date")]),]
nrow(unique(CTds))
[1] 46722

So, there are 46,722 unique person-crimes in the data who’ve been released from jail (excluding inconsistently coded people by gender/race) before 7-28-19.

Let’s look into how long people stay in jail in CT.

min(CTds$inmate_time)
[1] 1
max(CTds$inmate_time)
[1] 1038
mean(CTds$inmate_time)
[1] 64.42002
median(CTds$inmate_time)
[1] 28

Time as an inmate for people in CT ranges from 1 (get out within a day) to 1,038 days, with a mean of 64.42 days and a median of 28 days (4 weeks!).

Plot distribution of length of jail stay.

CTds$dur<-as.numeric(CTds$inmate_time)
#below is for the sake of logs
CTds$dur[CTds$dur==0]<-1

ggplot(data=CTds, aes(dur, fill=race)) + geom_histogram(binwidth = .25) +
  scale_fill_manual(name="Race", values = cbPalette) +  
  theme_minimal()+ theme(text=element_text(family="Palatino"))+
  theme(plot.title = element_text(hjust = 0))+
  labs(x="Days Detained", y="Number of Pretrial Inmates", 
       caption="\nThis plot uses a log10 transformation of the length of jail stay.\nEach observation is for some admission which concluded in a release from jail before 7/28/19. (n=46,722)\n(Again, I exclude individuals who are coded inconsistently by race or gender over time.)")+
  scale_y_continuous(labels=comma)+
  scale_x_log10(labels=comma)+ 
  ggtitle("Jail Stay Duration Pretrial in Connecticut", subtitle = "Data Available via Connecticut Open Data")

ggsave("graphs/inmatetime.png", width=8, height=5, dpi=900)

Plot averages in jail stay by race.

CTds1<- CTds[,c("race", "dur", "age")] %>% 
    group_by(race) %>%
    summarise_all(funs(mean,sd,se=sd(.)/sqrt(n())))

Plot it.

#ggplot(CTbondr, aes(x=race, y=bond_amount_mean, colour=race)) + 
ggplot(CTds1, aes(x=race, y=dur_mean)) +
    geom_errorbar(aes(ymin=dur_mean-(1.96*dur_se), 
                      ymax=dur_mean+(1.96*dur_se)), width=.1) +
    geom_point()+
  #scale_color_manual(values = cbPalette) +  
  theme_minimal()+ theme(text=element_text(family="Palatino"))+
  theme(plot.title = element_text(hjust = 0))+
  labs(x="", y="Mean Jail Stay (Days)", caption="Each observation is for some admission which concluded in a release from jail before 7/28/19. (n=46,722)\n(Again, I exclude individuals who are coded inconsistently by race or gender over time.)\nThe means by race are presented with 95% confidence intervals.")+
  scale_y_continuous(labels = comma, limits=c(0,85), breaks=seq(0,85,15))+
  ggtitle("Mean Pretrial Jail Stay by Racial Group", subtitle = "Data Available via Connecticut Open Data")
ggsave("graphs/stay-race.png", width=7, height=5, dpi=900)


5. Time vs. bail

To look at relationship betwen initial bond and time in jail, merge CTds and CTbond by identifier and latest_admission_date.

bd<-merge(CTds[,c("identifier", "dur", "latest_admission_date", "race")], 
          CTbond[,c("identifier", "bond_amount", "latest_admission_date", "race")], 
          by=c("identifier", "latest_admission_date", "race"), all=F)
nrow(bd)
[1] 46619

There are 46,619 observations to consider – there are 46,619 unique person-crimes in the data who’ve been released from jail (excluding inconsistently coded people by gender/race) before 7-28-19 that also include first observation bond amounts at or above $100 (exclude those below since they are unlikely to be true bond amounts).

library(viridis);library(hexbin)
Loading required package: viridisLite

Attaching package: ‘viridis’

The following object is masked from ‘package:scales’:

    viridis_pal
ggplot(data=bd, aes(x=bond_amount, y=dur))+
  stat_binhex()+ scale_fill_viridis(name="n in hex")+
  theme_minimal()+ theme(text=element_text(family="Palatino"))+
  theme(plot.title = element_text(hjust = 0))+
  labs(x="Initial Bond Amount ($)", y="Jail Stay (Days)", caption="\nThe plot displays the frequency of bond amount/jail stay combinations with hexagonal bins. (See legend.) \nObservations include admissions which concluded in a release from jail before 7/28/19. (n=46,619)")+
  scale_y_log10(labels=comma)+
  scale_x_log10(labels=comma)+ 
  ggtitle("Initial Bond and Jail Stay", subtitle = "Data Available via Connecticut Open Data")
ggsave("graphs/bondtime.png", width=8, height=6, dpi=900)

Check correlation:

cor(bd$bond_amount,bd$dur)
[1] 0.3680861

There is a correlation of 0.368 between time in jail and initial bond bond amount.

Regression footnote

CTbond <- mutate(CTbond, chargenew = factor(offense)) %>%
      mutate(fac_factor = factor(facility)) %>%
      mutate(race_factor = factor(race)) %>%
      within(race_factor <- relevel(race_factor, ref = 5)) %>%
      mutate(gender_factor = factor(gender)) %>%
      within(gender_factor <- relevel(gender_factor, ref = 2))

Use logs on dep variable for regressions.

reg3l <- lm(log(CTbond$bond_amount) ~  race_factor + gender_factor + age , data=CTbond)
reg4l <- lm(log(CTbond$bond_amount) ~  race_factor + gender_factor + age + chargenew , data=CTbond)

Make stargazer table with robust standard errors and log of dep var.

stargazer(reg3l, reg4l, type="text", omit=c("chargenew", "fac_factor"), style="qje",
          se = list(robust_se, robust_se1),
          add.lines = list(c("Offense Dummies?", "No", "Yes")),
          title = "What Explains How Bond is Set?",
          covariate.labels = c("Asian", "Black", "Hispanic", "Native American", "Female", "Age"),
          dep.var.labels   = "Log of Dollar Bond Amount", omit.stat=c("f", "ser"),
          notes = "Using robust standard errors."
          )

What Explains How Bond is Set?
========================================================
                        Log of Dollar Bond Amount       
                         (1)                 (2)        
--------------------------------------------------------
Asian                   0.123               0.108       
                       (0.103)             (0.086)      
                                                        
Black                  0.399***            0.151***     
                       (0.018)             (0.015)      
                                                        
Hispanic               0.320***            0.160***     
                       (0.019)             (0.016)      
                                                        
Native American        0.274**              0.128       
                       (0.121)             (0.104)      
                                                        
Female                -0.466***           -0.315***     
                       (0.020)             (0.017)      
                                                        
Age                   -0.015***           -0.005***     
                       (0.001)             (0.001)      
                                                        
Constant              10.507***           13.091***     
                       (0.028)             (0.021)      
                                                        
Offense Dummies?          No                 Yes        
N                       49,817              49,817      
R2                      0.037               0.368       
Adjusted R2             0.037               0.363       
========================================================
Notes:            ***Significant at the 1 percent level.
                   **Significant at the 5 percent level.
                   *Significant at the 10 percent level.
                           Using robust standard errors.
LS0tCnRpdGxlOiAiRXhwbG9yaW5nIENvbm5lY3RpY3V0J3MgUHJldHJpYWwgSW5tYXRlIERhdGEiCmF1dGhvcjogQWxleCBBbGJyaWdodApkYXRlOiAiSnVseS9BdWd1c3QgMjAxOSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBHb2FscyBvZiB0aGlzIGludmVzdGlnYXRpb24KCjEuIHNlZSB3aGljaCBjaGFyZ2VzIGFyZSBsYXJnZXN0IGRyaXZlcnMgb2YgcHJldHJpYWwgamFpbCBhZG1pc3Npb25zCjIuIG91dGxpbmUgZGVtb2dyYXBoaWNzIChhZ2UsIHJhY2UsIGdlbmRlcikgb2YgdGhvc2UgaW4gcHJldHJpYWwgZGV0ZW50aW9uCjMuIHNob3cgZGlzdHJpYnV0aW9uIG9mIGJvbmQgYW1vdW50cyAoYW5kIHNob3cgbWVhbnMgYnkgcmFjZSkKNC4gc2hvdyBkaXN0cmlidXRpb24gb2YgamFpbCBzdGF5cyAoYW5kIHNob3cgbWVhbnMgYnkgcmFjZSkKNS4gc2hvdyByZWxhdGlvbnNoaXAgYmV0d2VlbiBib25kIGFtb3VudCBhbmQgcHJldHJpYWwgamFpbCBzdGF5IGR1cmF0aW9uCgotLS0KCiMgQmFzaWMgZmFjdHMKCkNhbGwgdGhlIGBjc3ZgIGFuZCBjbGVhbiB1cC4gIApgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShkYXRhLnRhYmxlKTsgbGlicmFyeShqYW5pdG9yKTtsaWJyYXJ5KGRwbHlyKQpDVDwtZnJlYWQoJ2N0LmNzdicpCkNUPC1jbGVhbl9uYW1lcyhDVCkKQ1QkZG93bmxvYWRfZGF0ZTwtYXMuRGF0ZShDVCRkb3dubG9hZF9kYXRlLCAnJW0vJWQvJVknKQpDVCRsYXRlc3RfYWRtaXNzaW9uX2RhdGU8LWFzLkRhdGUoQ1QkbGF0ZXN0X2FkbWlzc2lvbl9kYXRlLCAnJW0vJWQvJVknKQpDVCRpZGVudGlmaWVyPC1hcy5jaGFyYWN0ZXIoQ1QkaWRlbnRpZmllcikKCiNmaXggcmFjZSBuYW1lcwpDVCRyYWNlW0NUJHJhY2UgPT0gJ0FNRVIgSU5EJ10gPC0gJ05hdGl2ZSBBbWVyaWNhbicKQ1QkcmFjZVtDVCRyYWNlID09ICdBU0lBTiddIDwtICdBc2lhbicKQ1QkcmFjZVtDVCRyYWNlID09ICdCTEFDSyddIDwtICdCbGFjaycKQ1QkcmFjZVtDVCRyYWNlID09ICdXSElURSddIDwtICdXaGl0ZScKQ1QkcmFjZVtDVCRyYWNlID09ICdISVNQQU5JQyddIDwtICdIaXNwYW5pYycKYGBgCgoKYGBge3J9Cm5yb3coQ1QpCmBgYAoKSXQgaGFzIDMuNTMgbWlsbGlvbiByb3dzLgoKSG93IG1hbnkgdW5pcXVlIHBlb3BsZSBhcmUgaW4gdGhlIGRhdGE/CgpgYGB7cn0KI3NlYXJjaCB1bmlxdWUgYnkgaWRlbnRpZmllcgpucm93KHVuaXF1ZShDVFssImlkZW50aWZpZXIiXSkpCmBgYApUaGVyZSBhcmUgMzQsODkyIHVuaXF1ZSBwZW9wbGUuIEJ1dCBtYXliZSBzb21lIHBlb3BsZSBoYXZlIGdvbmUgaW4gYW5kIG91dCBvZiBqYWlsIG11bHRpcGxlIHRpbWVzPyBTbywgaG93IG1hbnkgdW5pcXVlIHBlcnNvbi1hZG1pc3Npb25zIGFyZSB0aGVyZT8KCmBgYHtyfQojc2VhcmNoIHVuaXF1ZSByb3dzIGJ5IGlkZW50aWZpZXIgYW5kIGxhdGVzdCBhZG1pc3Npb24gZGF0ZQpucm93KHVuaXF1ZShDVFssYygiaWRlbnRpZmllciIsImxhdGVzdF9hZG1pc3Npb25fZGF0ZSIpXSkpCmBgYAoKNTAsMjQ3IHVuaXF1ZSBwZXJzb24tYWRtaXNzaW9ucy4gCgpTaW5jZSBhbiBhZG1pc3Npb24gbWlnaHQgYmUgZHVlIHRvIG11bHRpcGxlIGNoYXJnZXMsIHRoZXJlIG1pZ2h0IGJlIG1vcmUgdGhhbiA1MEsgY2hhcmdlcyByZXNwb25zaWJsZSBmb3IgdGhlIH41MEsgYWRtaXNzaW9ucy4uLiAKCmBgYHtyfQpucm93KHVuaXF1ZShDVFssYygiaWRlbnRpZmllciIsImxhdGVzdF9hZG1pc3Npb25fZGF0ZSIsICJvZmZlbnNlIildKSkKYGBgCgpTcGVjaWZpY2FsbHksIHRoZXJlIGFyZSA1NCwzNjcgdG90YWwgY2hhcmdlcyBmb3IgYWxsIGFkbWlzc2lvbnMgaW4gdGhpcyBkYXRhLgoKSG93IG1hbnkgdW5pcXVlIGNoYXJnZXM/IAoKYGBge3J9Cm5yb3codW5pcXVlKENUWyxjKCJvZmZlbnNlIildKSkKYGBgCgotLS0KCiMgMS4gV2h5IGluIEphaWw/CgpDb25zaWRlciB0aGUgcHJldmlvdXNseSBtZW50aW9uZWQgfjU0SyBjaGFyZ2VzLgoKYGBge3J9CmNoYXJnZXM8LXVuaXF1ZShDVFssYygiaWRlbnRpZmllciIsImxhdGVzdF9hZG1pc3Npb25fZGF0ZSIsICJvZmZlbnNlIildKSAlPiUKICBncm91cF9ieShvZmZlbnNlKSU+JQogIHN1bW1hcmlzZShjb3VudD1uKCkpJT4lCiAgbXV0YXRlKHRvdD1zdW0oY291bnQpLCBwZXJjPWNvdW50L3RvdCkKYGBgCgpNYWtlIGEgZ3JhcGggb2YgdG9wIDEwIGNoYXJnZXMuCgpgYGB7cn0KbGlicmFyeShzdHJpbmdyKQoKY2hhcmdlczEwPC1zdWJzZXQoY2hhcmdlcywgY2hhcmdlcyRwZXJjPi4wMTkpCmNoYXJnZXMxMDwtY2hhcmdlczEwW29yZGVyKC1jaGFyZ2VzMTAkcGVyYyksXQoKI2ZpeCB1cCBvZmZlbnNlCmNoYXJnZXMxMCRvZmZlbnNlPC10b2xvd2VyKGNoYXJnZXMxMCRvZmZlbnNlKQpjaGFyZ2VzMTAkb2ZmZW5zZTwtc3RyX3JlbW92ZShjaGFyZ2VzMTAkb2ZmZW5zZSwgIiBkZiIpCmNoYXJnZXMxMCRvZmZlbnNlPC1zdHJfcmVtb3ZlKGNoYXJnZXMxMCRvZmZlbnNlLCAiICBmIikKY2hhcmdlczEwJG9mZmVuc2U8LXN0cl9yZW1vdmUoY2hhcmdlczEwJG9mZmVuc2UsICIgYW0iKQpjaGFyZ2VzMTAkb2ZmZW5zZTwtc3RyX3NxdWlzaChjaGFyZ2VzMTAkb2ZmZW5zZSkKYGBgCk1ha2UgYSBmYWN0b3IgZm9yIG9yZGVyaW5nIHRoZSB4IGF4aXMKYGBge3J9CmNoYXJnZXMxMCRvZmZlbnNlPC0gZmFjdG9yKGNoYXJnZXMxMCRvZmZlbnNlLCBsZXZlbHMgPSBjaGFyZ2VzMTAkb2ZmZW5zZVtvcmRlcihjaGFyZ2VzMTAkcGVyYyldKQpgYGAKCkJlZm9yZSBtYWtpbmcgZ3JhcGhzLCBJIGNhbGwgbGlicy4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojTG9hZCBtb3JlIGxpYnJhcmllcwpsaWJyYXJ5KGdncGxvdDIpO2xpYnJhcnkoZ2dyZXBlbCk7IGxpYnJhcnkoZXh0cmFmb250KTsgbGlicmFyeShnZ3RoZW1lcyk7bGlicmFyeShyZXNoYXBlKTtsaWJyYXJ5KGdyaWQpOyBsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHNjYWxlcyk7bGlicmFyeShSQ29sb3JCcmV3ZXIpO2xpYnJhcnkoZ3JpZEV4dHJhKQpgYGAKCkkgZ3JhcGghCmBgYHtyLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD01fQpnZ3Bsb3QoZGF0YT1jaGFyZ2VzMTAsIGFlcyh4PW9mZmVuc2UsIHk9cGVyYykpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpKwogIHRoZW1lX21pbmltYWwoKSsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoZmFtaWx5PSJQYWxhdGlubyIpKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCwgbGltaXRzPWMoMCwuMTc1KSwgYnJlYWtzPXNlcSgwLC4xNzUsLjAyNSkpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwKSkrCiAgbGFicyh4PSIiLCB5PSIiLCBjYXB0aW9uPSJUaGVzZSBjYWxjdWxhdGlvbnMgY29uc2lkZXIgYWxsIDU0LDM2NyB1bmlxdWUgcGVyc29uLWFkbWlzc2lvbi1vZmZlbnNlIG9ic2VydmF0aW9ucyBmcm9tIDcvMS8xNi03LzI4LzE5LiIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgdmp1c3QgPSAxKSkrCiAgZ2d0aXRsZSgiV2h5IEFyZSBQZW9wbGUgaW4gSmFpbD8gKFRvcCAxMCBDaGFyZ2VzKSIsIHN1YnRpdGxlID0gIkRhdGEgQXZhaWxhYmxlIHZpYSBDb25uZWN0aWN1dCBPcGVuIERhdGEiKQpnZ3NhdmUoImdyYXBocy9vZmZlbnNlX3RvcF8xMC5wbmciLCB3aWR0aD03LCBoZWlnaHQ9NywgZHBpPTkwMCkKYGBgCk5vdGU6IHRoaXMgaXMgbm90IHRoZSBzYW1lIGFzIGxvb2tpbmcgYXQgZGF5cyBpbiBqYWlsIGFjcm9zcyBvZmZlbnNlcyEgVGhpcyBsb29raW5nIGF0IGFkbWlzc2lvbnMhIE1hbnkgb2YgdGhlc2UgYXJlIHNtYWxsZXIgc28gdGhvc2UgaW5tYXRlcyBtaWdodCBiZSBpbiBhbmQgb3V0IHByZXR0eSBxdWlja2x5LgoKIyAyLiBEZW1vZ3JhcGhpY3MKCiMjIEdlbmRlci9SYWNlCgpGaXJzdCwgbGV0J3Mgc3VtbWFyaXplIGJ5IGdlbmRlci9yYWNlLiBMb29rIGF0IHVuaXF1ZSBwZW9wbGUgb3ZlciB0aGUgd2hvbGUgdGltZSBwZXJpb2QuCgpgYGB7cn0KQ1RwZW9wbGU8LXVuaXF1ZShDVFssYygiaWRlbnRpZmllciIsICJyYWNlIiwgImdlbmRlciIpXSkKYGBgCgpPSywgdGhlcmUgYXJlIDM1LDAyMyBpbnN0ZWFkIG9mIDM0LDg5Mi4gVGhhdCBtZWFucyBzb21lIHBlb3BsZSBhcmUgYmVpbmcgY29kZWQgYXMgZGlmZmVyZW50IGdlbmRlcnMvcmFjZXMuIExldCdzIGNoZWNrIGl0IG91dC4KCkxldCdzIGV4Y2x1ZGUgdGhlIHBlb3BsZSBjb2RlZCB3aXRoIGRpZmZlcmVudCByYWNlIGFuZC9vciBnZW5kZXJzIGFjcm9zcyB0aGUgdGltZSBwZXJpb2QuCmBgYHtyfQpDVHBlb3BsZSRkdXA8LWR1cGxpY2F0ZWQoQ1RwZW9wbGUsIGJ5PSJpZGVudGlmaWVyIikKQ1RwZW9wbGVkdXA8LXN1YnNldChDVHBlb3BsZSwgZHVwPT0iVFJVRSIpCkNUcGVvcGxlZHVwMTwtQ1RwZW9wbGVkdXBbLDFdCkNUcGVvcGxlZHVwMSRleGNsdWRlPC0xCkNUcGVvcGxlPC1tZXJnZShDVHBlb3BsZSwgQ1RwZW9wbGVkdXAxLCBieSA9ImlkZW50aWZpZXIiLCBhbGw9VCkKQ1RwPC1zdWJzZXQoQ1RwZW9wbGUsIGlzLm5hKENUcGVvcGxlJGV4Y2x1ZGUpKQpDVHA8LUNUcFssYygxOjMpXQpgYGAKCkdyZWF0LCBzbyBub3cgd2UgdXNlIGBDVHBgIHRvIGdldCBpbnRvIHRoZSByYWNlL2dlbmRlciBkZW1vZ3JhcGhpY3Mgb2YgdGhlIDM0LDc2MSBwZW9wbGUgd2hvIGFyZSBjb2RlZCBjb25zaXN0ZW50bHkgKHNvLCBleGNsdWRpbmcgdGhlIDEzMSBpbmNvbnNpc3RlbnQgb25lcykgYW5kIHdlcmUgaW5tYXRlcyBpbiBDVCBjb3JyZWN0aW9uYWwgZmFjaWxpdGllcyBmcm9tIDcvMS8yMDE2LTcvMjgvMTkuCgpJIGRlZmluZSBzb21lIGNvbG9yYmxpbmQgcGFsZXR0ZXMuCmBgYHtyfQojIFRoZSBwYWxldHRlIHdpdGggZ3JleToKY2JQYWxldHRlIDwtIGMoIiM5OTk5OTkiLCAiI0U2OUYwMCIsICIjNTZCNEU5IiwgIiMwMDlFNzMiLCAiI0YwRTQ0MiIsICIjMDA3MkIyIiwgIiNENTVFMDAiLCAiI0NDNzlBNyIpClBhbCA8LSBjKCIjNTZCNEU5IiwgIiMwMDlFNzMiLCAiI0YwRTQ0MiIsICIjMDA3MkIyIiwgIiNENTVFMDAiLCAiI0NDNzlBNyIpCgojIFRoZSBwYWxldHRlIHdpdGggYmxhY2s6CmNiYlBhbGV0dGUgPC0gYygiIzAwMDAwMCIsICIjRTY5RjAwIiwgIiM1NkI0RTkiLCAiIzAwOUU3MyIsICIjRjBFNDQyIiwgIiMwMDcyQjIiLCAiI0Q1NUUwMCIsICIjQ0M3OUE3IikKYGBgCkkgZ3JhcGghCmBgYHtyLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD01fQpnZ3Bsb3QoZGF0YT1DVHAsIGFlcyhyYWNlLCBmaWxsPWdlbmRlcikpICsgCiAgZ2VvbV9iYXIoKSsKICB0aGVtZV9taW5pbWFsKCkrIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KGZhbWlseT0iUGFsYXRpbm8iKSkrCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZT0iR2VuZGVyIiwgdmFsdWVzID0gYygiZ29sZCIsICJkb2RnZXJibHVlIiksIGxhYmVscz1jKCJGZW1hbGUiLCAiTWFsZSIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMTQwMDApLCBicmVha3M9c2VxKDAsMTQwMDAsMjAwMCkpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwKSkrCiAgbGFicyh4PSIiLCB5PSJOdW1iZXIgb2YgUHJldHJpYWwgSW5tYXRlcyIsIGNhcHRpb249IlRoZSB0b3RhbCBudW1iZXIgb2YgdW5pcXVlIHByZXRyaWFsIGlubWF0ZXMgaW4gdGhpcyB0aW1lIHBlcmlvZCBpcyAzNCw4OTI7IEkgcHJlc2VudCBkYXRhIGZvciAzNCw3NjEgaGVyZS5cbihJIGV4Y2x1ZGUgMTMxIGluZGl2aWR1YWxzIHdobyBhcmUgY29kZWQgaW5jb25zaXN0ZW50bHkgYnkgcmFjZSBvciBnZW5kZXIgb3ZlciB0aW1lKS5cblRoZSBkYXRhc2V0IGNvZGVzIEhpc3BhbmljIGFzIGEgcmFjZSAodGhpcyBpcyBkaWZmZXJlbnQgdGhhbiwgc2F5LCB0aGUgQ2Vuc3VzIG1ldGhvZG9sb2d5KS4iKSsKICBnZ3RpdGxlKCJHZW5kZXIgYW5kIFJhY2Ugb2YgQ29ubmVjdGljdXQgUHJldHJpYWwgSW5tYXRlcyAoNy8xLzE2LTcvMjgvMTkpIiwgc3VidGl0bGUgPSAiRGF0YSBBdmFpbGFibGUgdmlhIENvbm5lY3RpY3V0IE9wZW4gRGF0YSIpCmdnc2F2ZSgiZ3JhcGhzL2dlbmRlcl9yYWNlLnBuZyIsIHdpZHRoPTcsIGhlaWdodD00LjUsIGRwaT05MDApCmBgYAoKSW4gdGVybXMgb2Ygb3Zlci91bmRlcnJlcHJlc2VudGF0aW9uLCB0aGlzIGlzIHRoZSB1c3VhbCBzdG9yeSBhYm91dCB3aGl0ZXMgYW5kIGFzaWFucyBiZWluZyB1bmRlcnJlcHJlc2VudGVkIHdoaWxlIGJsYWNrIGFuZCBoaXNwYW5pYyBwZW9wbGUgYXJlIG92ZXJyZXByZXNlbnRlZC4KCk1ha2Ugc3RhY2tlZCBiYXJzLCBvbmUgZm9yIENlbnN1cyBDVCBhbmQgb25lIGZvciBwcmV0cmlhbCBpbm1hdGVzCgpgYGB7cn0KQ1RyYWNlPC1DVHAgJT4lCiAgZ3JvdXBfYnkocmFjZSklPiUKICBzdW1tYXJpemUoY291bnQ9bigpKSAlPiUKICBtdXRhdGUodG90YWw9c3VtKGNvdW50KSklPiUKICBtdXRhdGUocGVyYz1jb3VudC90b3RhbCkKYGBgCgpNYW51YWxseSBhZGQgdGhlIGNlbnN1cyBkYXRhLCBiYXNlZCBvbiBhbiBhcHByb3hpbWF0aW9uIChzaW5jZSBldGhuaWNpdHksIHJhY2UgZG9uZSBkaWZmZXJlbnRseSBieSB0aGUgY2Vuc3VzKSBmcm9tIFt0aGlzIHJlZmVyZW5jZS5dKGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvcXVpY2tmYWN0cy9DVCkKCmBgYHtyfQpyYWNlIDwtIGMoJ0FzaWFuJywnQmxhY2snLCdIaXNwYW5pYycsICdOYXRpdmUgQW1lcmljYW4nLCAnV2hpdGUnKQpjX3BlcmMgPC0gYyguMDUsIC4xMiwgLjE2LCAuMDA1LCAuNjY1KQpjZW5zdXM8LWRhdGEuZnJhbWUocmFjZSwgY19wZXJjKQpgYGAKCk1lcmdlIHRoZSBjZW5zdXMgYW5kIHByZXRyaWFsLgoKYGBge3J9CkNUcmFjZV9jPC1tZXJnZShDVHJhY2UsIGNlbnN1cywgYnk9InJhY2UiKQpgYGAKClJlc2hhcGUuCmBgYHtyIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXIpCkNUcmFjZV9jIDwtIENUcmFjZV9jICU+JQogIGdhdGhlcihzb3VyY2UsIHBlcmNlbnQsIHBlcmM6Y19wZXJjKQpgYGAKCk1ha2UgdGhlIHBsb3QuCgpgYGB7ciwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NX0KZ2dwbG90KGRhdGE9Q1RyYWNlX2MsIGFlcyh4PXNvdXJjZSwgeT1wZXJjZW50LCBmaWxsPXJhY2UpKSArIAogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArCiAgdGhlbWVfbWluaW1hbCgpKyB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChmYW1pbHk9IlBhbGF0aW5vIikpKwogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWU9IlJhY2UiLCB2YWx1ZXMgPSBjYlBhbGV0dGUpICsgIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwKSkrCiAgbGFicyh4PSIiLCB5PSIiLCBjYXB0aW9uPSJUaGUgcHJldHJpYWwgaW5tYXRlIHBvcHVsYXRpb24gY292ZXJzIDM0LDc2MSBwZW9wbGUgaW4gRE9DIGZhY2lsaXRpZXMgNy8xLzE2LTcvMjgvMTkuXG4oSSBleGNsdWRlIDEzMSBpbmRpdmlkdWFscyB3aG8gYXJlIGNvZGVkIGluY29uc2lzdGVudGx5IGJ5IHJhY2Ugb3IgZ2VuZGVyIG92ZXIgdGltZSkuXG5PdmVyYWxsIFBvcHVsYXRpb24gZGF0YSBpcyBlc3RpbWF0ZWQgZnJvbSB0aGUgVVMgQ2Vuc3VzIFF1aWNrRmFjdHMuIikrCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIk92ZXJhbGwgUG9wdWxhdGlvbiIsICJQcmV0cmlhbCBJbm1hdGUgUG9wdWxhdGlvbiIpKSsgCiAgZ2d0aXRsZSgiT3ZlcmFsbCBDb25uZWN0aWN1dCBQb3B1bGF0aW9uIHZzLiBDb25uZWN0aWN1dCBQcmV0cmlhbCBJbm1hdGUgUG9wdWxhdGlvbiIsIHN1YnRpdGxlID0gIkRhdGEgQXZhaWxhYmxlIHZpYSBDb25uZWN0aWN1dCBPcGVuIERhdGEiKQpnZ3NhdmUoImdyYXBocy9yYWNlX2NvbXBhcmUucG5nIiwgd2lkdGg9NywgaGVpZ2h0PTUsIGRwaT05MDApCmBgYAoKIyMgQWdlL3JhY2UKCkxldCdzIHNlZSBhZ2UvcmFjZSBmb3IgdGhvc2UgYXMgb2YgNy0yOC0xOS4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpDVDE5PC1zdWJzZXQoQ1QsIGRvd25sb2FkX2RhdGU9PSIyMDE5LTA3LTI4IikKYGBgCgpJIGdyYXBoIQpgYGB7ciwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NX0KZ2dwbG90KGRhdGE9Q1QxOSwgYWVzKGFnZSwgZmlsbD1yYWNlKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShicmVha3M9c2VxKDE1LCA4MCwgYnkgPSAxKSkgKwogIHRoZW1lX21pbmltYWwoKSsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoZmFtaWx5PSJQYWxhdGlubyIpKSsKICBzY2FsZV9maWxsX21hbnVhbChuYW1lPSJSYWNlIiwgdmFsdWVzID0gY2JQYWxldHRlKSArICAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCkpKwogIGxhYnMoeD0iQWdlIiwgeT0iTnVtYmVyIG9mIFByZXRyaWFsIElubWF0ZXMiLCBjYXB0aW9uPSJUaGlzIGdyYXBocyBjb3ZlcnMgb25seSB0aGUgMywyMzAgaW5tYXRlcyBwcmVzZW50IGluIERPQyBmYWNpbGl0aWVzIG9uIDcvMjgvMTkuIikrCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMTI2KSwgYnJlYWtzPXNlcSgwLDEyNiwyNSkpKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygxNSw4MSksIGJyZWFrcz1zZXEoMTUsODAsNSkpKyAKICBnZ3RpdGxlKCJBZ2UgYW5kIFJhY2Ugb2YgQ29ubmVjdGljdXQgUHJldHJpYWwgSW5tYXRlcyAoNy8yOC8yMDE5KSIsIHN1YnRpdGxlID0gIkRhdGEgQXZhaWxhYmxlIHZpYSBDb25uZWN0aWN1dCBPcGVuIERhdGEiKQpnZ3NhdmUoImdyYXBocy9hZ2VfcmFjZS03LTI4LTE5LnBuZyIsIHdpZHRoPTgsIGhlaWdodD01LCBkcGk9OTAwKQpgYGAKCkFzIGV4cGVjdGVkIHNrZXdlZCB5b3VuZyBjb21wYXJlZCB0byB0aGUgb3ZlcmFsbCBwb3B1bGF0aW9uLgoKV2hhdCdzIHRoZSBtZWRpYW4gYWdlPwoKYGBge3J9Cm1lZGlhbihDVDE5JGFnZSkKYGBgCgpUaGlzIGlzIChhcyBleHBlY3RlZCkgbG93ZXIgdGhhbiB0aGUgb3ZlcmFsbCBtZWRpYW4gZm9yIENUIG9mIH40MS4KCi0tLQoKIyAzLiBCb25kIGFtb3VudHMKCiMjIERpc3RyaWJ1dGlvbgoKTGV0J3MgcGxvdCBtZWFuIGJvbmQgYW1vdW50cyB3aXRoIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGJ5IHJhY2UuICBMZXQncyB0aGVuIGZvY3VzIG9uIHRoZSBmaXJzdCBpbnN0YW5jZSBvZiBiYWlsIChmaXJzdCBvYnNlcnZhdGlvbiBpbiB0aGUgZGF0YSkuCgpJbiBlZmZlY3QsIHdlIHNvcnQgYnkgYGRvd25sb2FkX2RhdGVgLiBUaGVuIHdlIGRlbGV0ZSBkdXBsaWNhdGVzIGJ5IGBpZGVudGlmaWVyYCBhbmQgYGxhdGVzdF9hZG1pc3Npb25fZGF0ZWAuCgpgYGB7cn0KQ1Rib25kPC1DVFtvcmRlcihDVCRkb3dubG9hZF9kYXRlLCBDVCRpZGVudGlmaWVyKSxdCkNUYm9uZDwtQ1Rib25kWyFkdXBsaWNhdGVkKENUYm9uZFssYygiaWRlbnRpZmllciIsICJsYXRlc3RfYWRtaXNzaW9uX2RhdGUiKV0pLF0KbnJvdyh1bmlxdWUoQ1Rib25kKSkKYGBgCk5vIGR1cGxpY2F0ZXMgbm93IGJ5IHBlcnNvbiBhbmQgYWRtaXNzaW9uIGRhdGUuIFRoZXNlIGFyZSB0aGUgNTAsMjQ3IHVuaXF1ZSBmaXJzdCBpbnN0YW5jZXMgb2YgYSBwZXJzb24gaW4gZm9yIGEgY2VydGFpbiBhZG1pc3Npb24gZGF0ZS4gCgpgYGB7cn0KbWluKENUYm9uZCRib25kX2Ftb3VudCkKbWF4KENUYm9uZCRib25kX2Ftb3VudCkKYGBgClRoZSBib25kIGFtb3VudHMgcmFuZ2UgZnJvbSBcJDEgKGNhbiB0aGF0IGJlIHJpZ2h0PyAtLSB3ZWxsLCB0aGUgY29kZSBib29rIG1lbnRpb25zIHRoYXQgYm9uZHMgdW5kZXIgJDEwMCBhcmUgcHJvYmFibHkgcGxhY2UgaG9sZGVycy4pIHRvIFwkOSwwMDAsMDA5LiAKCkhvdyBtYW55IGJvbmQgYW1vdW50cyBhcmUgJDEwMCBvciB1bmRlcj8KCmBgYHtyfQpDVGJvbmQgJT4lIAogIGZpbHRlcihib25kX2Ftb3VudDwxMDApJT4lCiAgbnJvdygpCmBgYAoKT25seSAxMDQgb2YgNTAsMjQ3IG9ic2VydmF0aW9ucyBhcmUgdW5kZXIgJDEwMC4gTGV0J3MgZXhjbHVkZSB0aGVzZSBzaW5jZSB0aGV5IGFyZSB1bmxpa2VseSB0byBiZSB0cnVlIGJvbmQgYW1vdW50cyAoYWNjb3JkaW5nIHRvIHRoZSBjb2RlYm9vaykuCgpgYGB7cn0KQ1Rib25kIDwtIENUYm9uZCAlPiUgCiAgZmlsdGVyKGJvbmRfYW1vdW50Pj0xMDApCmBgYAoKYGBge3J9Cm1lYW4oQ1Rib25kJGJvbmRfYW1vdW50KQptZWRpYW4oQ1Rib25kJGJvbmRfYW1vdW50KQpgYGAKClRoZSBtZWFuIGlzIFwkODU4ODEuNDMgYW5kIHRoZSBtZWRpYW4gaXMgXCQyNSwxMDAuIFNlZW1zIHNob2NraW5nbHkgaGlnaCwgYnV0IHdvcnRoIG5vdGluZyB0aGF0IHRoaXMgaXMgbGlrZWx5IGhpZ2hlciB0aGFuIHRoZSBvdmVyYWxsIGJvbmQgbWVhbiBzaW5jZSB0aGlzIGRhdGEgb25seSBjb3ZlcnMgdGhvc2Ugd2hvIGFyZSBpbiBqYWlsIHNvbWUgbmlnaHQuIChTZWxlY3Rpb24gaXMgaW1wb3J0YW50IGluIHVuZGVyc3RhbmRpbmcgdGhpcyBtZWFuLikKCkNhbiB3ZSB2aXN1YWxpemUgdGhlIGRpc3RyaWJ1dGlvbj8gV2l0aG91dCBhIHRyYW5zZm9ybWF0aW9uLCBpdCdzIHN1cGVyIGhhcmQgKGltcG9zc2libGUsIGFjdHVhbGx5KSB0byBzZWUgYW55dGhpbmcgYmVjYXVzZSB0aGVyZSBhcmUgaHVnZSB2YWx1ZXMgb24gdGhlIHJpZ2h0IChpbiB0aGUgbWlsbGlvbnMpIGJ1dCBpdCdzIG1haW5seSB2YWx1ZXMgb24gdGhlIGxlZnQgKGJ1dCB3ZSBjYW4ndCBldmVuIHNlZSB3aGF0IHRob3NlIGFyZSkuCgpgYGB7cn0KQ1Rib25kPC1tZXJnZShDVGJvbmQsIENUcCwgYnk9YygiaWRlbnRpZmllciIsICJnZW5kZXIiLCAicmFjZSIpLCBhbGw9RikKbnJvdyhDVGJvbmQpCmBgYAoKSSBleGNsdWRlIHRob3NlIHdobyBhcmUgY29kZWQgaW5jb25zaXN0ZW50bHkgYnkgcmFjZSBvciBnZW5kZXIgZm9yIHRoZSBzYWtlIG9mIGNvbnNpc3RlbmN5IGFuZCB0aGF0IHlpZWxkcyA0OSw4MTcgdW5pcXVlIGZpcnN0IGluc3RhbmNlcyBvZiBhIHBlcnNvbiBpbiBmb3IgYSBjZXJ0YWluIGFkbWlzc2lvbiBkYXRlLgoKYGBge3IsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTV9CmdncGxvdChkYXRhPUNUYm9uZCwgYWVzKGJvbmRfYW1vdW50LCBmaWxsPXJhY2UpKSArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gLjMpICsKICBzY2FsZV9maWxsX21hbnVhbChuYW1lPSJSYWNlIiwgdmFsdWVzID0gY2JQYWxldHRlKSArICAKICB0aGVtZV9taW5pbWFsKCkrIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KGZhbWlseT0iUGFsYXRpbm8iKSkrCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDApKSsKICBsYWJzKHg9IkJvbmQgQW1vdW50ICgkKSIsIHk9Ik51bWJlciBvZiBQcmV0cmlhbCBJbm1hdGVzIiwgCiAgICAgICBjYXB0aW9uPSJcblRoaXMgcGxvdCB1c2VzIGEgbG9nMTAgdHJhbnNmb3JtYXRpb24gb2YgdGhlIGJvbmQgYW1vdW50IGF4aXMuXG5FYWNoIG9ic2VydmF0aW9uIGlzIHRoZSBmaXJzdCBvYnNlcnZhdGlvbiBvZiBhIHBlcnNvbi1hZG1pc3Npb24uIChuPTQ5LDgxNylcbihBZ2FpbiwgSSBleGNsdWRlIGluZGl2aWR1YWxzIHdobyBhcmUgY29kZWQgaW5jb25zaXN0ZW50bHkgYnkgcmFjZSBvciBnZW5kZXIgb3ZlciB0aW1lLilcbkkgY29uc2lkZXIgdGhlIGJvbmQgYW1vdW50IGF0IGZpcnN0IGRheSBvYnNlcnZlZCBpbiBqYWlsIGZvciBhIGdpdmVuIGRhdGUgb2YgYWRtaXNzaW9uLiIpKwogIHNjYWxlX3hfbG9nMTAobGFiZWxzPWNvbW1hKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWw9Y29tbWEpKwogICNzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMTUsODApLCBicmVha3M9c2VxKDE1LDgwLDUpKSsgCiAgZ2d0aXRsZSgiQm9uZCBBbW91bnRzIGZvciBDb25uZWN0aWN1dCBQcmV0cmlhbCBJbm1hdGVzICg3LzEvMjAxNi03LzI4LzIwMTkpIiwgc3VidGl0bGUgPSAiRGF0YSBBdmFpbGFibGUgdmlhIENvbm5lY3RpY3V0IE9wZW4gRGF0YSIpCmdnc2F2ZSgiZ3JhcGhzL2JvbmRfZGlzdF9yYWNlLnBuZyIsIHdpZHRoPTgsIGhlaWdodD01LCBkcGk9OTAwKQpgYGAKCkl0IGlzIGNsZWFyZXIgbm93IHRvIHNlZSB3aGVyZSB0aGUgYmlnIHBhcnRzIG9mIHRoZSBkaXN0cmlidXRpb24gYXJlLgoKIyMgTWVhbiBieSBncm91cAoKYGBge3Igd2FybmluZz1GQUxTRX0KQ1Rib25kcjwtIENUYm9uZFssYygicmFjZSIsICJib25kX2Ftb3VudCIsICJhZ2UiKV0gJT4lIAogICAgZ3JvdXBfYnkocmFjZSkgJT4lCiAgICBzdW1tYXJpc2VfYWxsKGZ1bnMobWVhbixzZCxzZT1zZCguKS9zcXJ0KG4oKSkpKQpgYGAKUGxvdCBpdC4KYGBge3J9CiNnZ3Bsb3QoQ1Rib25kciwgYWVzKHg9cmFjZSwgeT1ib25kX2Ftb3VudF9tZWFuLCBjb2xvdXI9cmFjZSkpICsgCmdncGxvdChDVGJvbmRyLCBhZXMoeD1yYWNlLCB5PWJvbmRfYW1vdW50X21lYW4pKSArCiAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWJvbmRfYW1vdW50X21lYW4tKDEuOTYqYm9uZF9hbW91bnRfc2UpLCAKICAgICAgICAgICAgICAgICAgICAgIHltYXg9Ym9uZF9hbW91bnRfbWVhbisoMS45Nipib25kX2Ftb3VudF9zZSkpLCB3aWR0aD0uMSkgKwogICAgZ2VvbV9wb2ludCgpKwogICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY2JQYWxldHRlKSArICAKICB0aGVtZV9taW5pbWFsKCkrIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KGZhbWlseT0iUGFsYXRpbm8iKSkrCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDApKSsKICBsYWJzKHg9IiIsIHk9Ik1lYW4gQm9uZCBBbW91bnQgKCQpIiwgY2FwdGlvbj0iSSBjb25zaWRlciBvbmx5IHRoZSBmaXJzdCBvYnNlcnZhdGlvbiBvZiBib25kIGFtb3VudCBmb3IgYSBnaXZlbiBhZG1pc3Npb24gKG49NDksODE3KS5cblRoZSBtZWFucyBieSByYWNlIGFyZSBwcmVzZW50ZWQgd2l0aCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMuIikrCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hLCBsaW1pdHM9YygwLDExMDUwMCksIGJyZWFrcz1zZXEoMCwxMTAwMDAsMTAwMDApKSsKICAjc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMTUxKSwgYnJlYWtzPXNlcSgwLDE1MCwyNSkpKwogIGdndGl0bGUoIk1lYW4gQm9uZCBvZiBDb25uZWN0aWN1dCBQcmV0cmlhbCBJbm1hdGVzIGJ5IFJhY2lhbCBHcm91cCIsIHN1YnRpdGxlID0gIkRhdGEgQXZhaWxhYmxlIHZpYSBDb25uZWN0aWN1dCBPcGVuIERhdGEiKQpnZ3NhdmUoImdyYXBocy9ib25kX3JhY2UucG5nIiwgd2lkdGg9NiwgaGVpZ2h0PTUsIGRwaT05MDApCmBgYAoKQ2xlYXJseSAoaW4gdGhhdCB0aGUgOTUlIENJJ3MgZG9uJ3Qgb3ZlcmxhcCkgd2hpdGUgcGVvcGxlIGhhdmUgbG93ZXIgYm9uZHMgb24gYXZlcmFnZSB0aGFuIGJsYWNrLCBhc2lhbiwgb3IgaGlzcGFuaWMgcGVvcGxlLgoKLS0tCgojIDQuIFRpbWUgaW4gamFpbCBwcmV0cmlhbAoKV2FudCB0byBmb2N1cyBvbiB0aGUgdW5pcXVlIHBlcnNvbi1hZG1pc3Npb24gKGV4Y2x1ZGluZyBwZW9wbGUgd2hvIGFyZSBjb2RlZCBpbmNvbnNpc3RlbnRseSBvdmVyIHRpbWUpIG9ic2VydmF0aW9ucy4gSSB3YW50IHRvIGZvY3VzIG9uIHBlb3BsZS1hZG1pc3Npb25zIHdobyBhcmUgaW4gamFpbCBhbmQgdGhlbiBhcmUgb3V0IG9mIHRoZSBzYW1wbGUuIEllLCBleGNsdWRlIHRob3NlIHN0aWxsIGluIGphaWwgb24gNy0yOC0xOS4gCgpSZWxldmFudCBub3RlIGZyb20gY29kZWJvb2s6Cgo+IExBVEVTVCBBRE1JU1NJT04gREFURTogTW9zdCByZWNlbnQgZGF0ZSBpbiB3aGljaCB0aGUgaW5tYXRlIGhhcyBiZWVuIGFkbWl0dGVkLiBJbiBzb21lIGluc3RhbmNlcywgdGhpcyBtYXkgcmVmbGVjdCBhbiBvcmlnaW5hbCBkYXRlIG9mIGFkbWlzc2lvbiB0byBhIGNvcnJlY3Rpb25hbCBmYWNpbGl0eS4gR2VuZXJhbGx5LCBpZiBhIGRhdGUgaXMgbW9yZSB0aGFuIG9uZSB5ZWFyIG9sZCwgYW4gaW5tYXRlIHNob3VsZCBub3QgYmUgY29uc2lkZXJlZCB0byBoYXZlIGJlZW4gaGVsZCBmb3IgdGhlIGVudGlyZSBkdXJhdGlvbiBvZiB0aGF0IHRpbWUuCgpTbywgY29uY2VwdHVhbGx5LCBJIHdhbnQgdG8gY29uc2lkZXIgdGhlIGZ1bGwgZGF0YXNldDoKCi0gZXhjbHVkZSB0aG9zZSBwZW9wbGUgd2hvIGFyZSBjb2RlZCBpbmNvbnNpc3RlbnRseSAob24gcmFjZSBhbmQvb3IgZ2VuZGVyKQotIG1ha2UgYSB2YXJpYWJsZSBmb3IgbGVuZ3RoIG9mIHRpbWUgaW4gamFpbCAodmlhIGdyb3VwaW5nIGJ5IHBlcnNvbiwgYWRtaXNzaW9uIGFuZCB0aGVuIHRha2luZyB0aGUgc3VtKQoKVGhlbiwgCgotIGdlbmVyYXRlIGFuIGluZGljYXRvciBmb3IgZGF0ZSB2YXJpYWJsZSBiZWluZyA3LzI4LzE5Ci0gdGFrZSBtYXggb2YgdGhhdCA3LzI4LzE5IGluZGljYXRvciAodGh1cyBzaG93aW5nIHdoaWNoIHBlcnNvbi1hZG1pc3Npb25zIGFyZSBpbiBqYWlsIG9uIHRoZSBsYXN0IGRheSkKLSBleGNsdWRlIHRob3NlIG9ic2VydmF0aW9ucywgc28gdGhhdCBub3cgb25seSBsb29raW5nIGF0IHBlb3BsZSB3aG8gZ290IG91dCBhdCBzb21lIHBvaW50IAoKTGFzdCwgc3Vic2V0IHRvIHRoZSBlYXJsaWVzdCBkYXRlIGluIHRoZSBkYXRhIChzaW5jZSBib25kLCBmYWNpbGl0eSBjb3VsZCBhbHRlciBvdmVyIHRpbWUpLgoKYGBge3J9CiNDVHAgaXMgdGhlIGRhdGFmcmFtZSBvZiBJRHMgZm9yIGNvbnNpc3RlbnRseSBjb2RlZCBwZW9wbGUKQ1R6PC1tZXJnZShDVCxDVHAsIGJ5PWMoImlkZW50aWZpZXIiLCAicmFjZSIsICJnZW5kZXIiKSwgYWxsPUYpCmBgYAoKTWFrZSBhIG5ldyB2YXJpYWJsZSBmb3IgbGVuZ3RoIG9mIHRpbWUgaW4gamFpbCBmb3IgcGVyc29uLWFkbWlzc2lvbgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KQ1R6PC0gQ1R6ICU+JSAKICAgZ3JvdXBfYnkoaWRlbnRpZmllciwgbGF0ZXN0X2FkbWlzc2lvbl9kYXRlKSAlPiUKICAgbXV0YXRlKGlubWF0ZV90aW1lID0gbigpKQpgYGAKR2VuZXJhdGUgaW5kaWNhdG9yIGZvciBkYXRlIGJlaW5nIDctMjgtMTksIHRha2UgbWF4IGJ5IHBlcnNvbi1hZG1pc3Npb24KYGBge3J9CkNUeiRkMTggPC0gYXMubnVtZXJpYyhDVHokZG93bmxvYWRfZGF0ZSA9PSAiMjAxOS0wNy0yOCIpCgpDVHo8LSBDVHogJT4lIAogICBncm91cF9ieShpZGVudGlmaWVyLCBsYXRlc3RfYWRtaXNzaW9uX2RhdGUpICU+JQogICBtdXRhdGUobWF4LmQxOCA9IG1heChkMTgpKQpgYGAKRXhjbHVkZSBwZXJzb24tYWRtaXNzaW9ucyBmb3IgcGVvcGxlIHN0aWxsIGluIGphaWwgZm9yIHRoYXQgYWRtaXNzaW9uLgpgYGB7cn0KQ1R6MTwtc3Vic2V0KENUeiwgQ1R6JG1heC5kMTg8MSkKYGBgCk5vdyBqdXN0IGNvbnNpZGVyIHRoZSBlYXJsaWVzdCBkYXRhcG9pbnQgZm9yIGVhY2guCgpgYGB7cn0KQ1R6MTwtQ1R6MVtvcmRlcihDVHoxJGRvd25sb2FkX2RhdGUsIENUejEkaWRlbnRpZmllciksXQpDVGRzPC1DVHoxWyFkdXBsaWNhdGVkKENUejFbLGMoImlkZW50aWZpZXIiLCAibGF0ZXN0X2FkbWlzc2lvbl9kYXRlIildKSxdCm5yb3codW5pcXVlKENUZHMpKQpgYGAKU28sIHRoZXJlIGFyZSA0Niw3MjIgdW5pcXVlIHBlcnNvbi1jcmltZXMgaW4gdGhlIGRhdGEgd2hvJ3ZlIGJlZW4gcmVsZWFzZWQgZnJvbSBqYWlsIChleGNsdWRpbmcgaW5jb25zaXN0ZW50bHkgY29kZWQgcGVvcGxlIGJ5IGdlbmRlci9yYWNlKSBiZWZvcmUgNy0yOC0xOS4KCkxldCdzIGxvb2sgaW50byBob3cgbG9uZyBwZW9wbGUgc3RheSBpbiBqYWlsIGluIENULgpgYGB7cn0KbWluKENUZHMkaW5tYXRlX3RpbWUpCm1heChDVGRzJGlubWF0ZV90aW1lKQptZWFuKENUZHMkaW5tYXRlX3RpbWUpCm1lZGlhbihDVGRzJGlubWF0ZV90aW1lKQpgYGAKVGltZSBhcyBhbiBpbm1hdGUgZm9yIHBlb3BsZSBpbiBDVCByYW5nZXMgZnJvbSAxIChnZXQgb3V0IHdpdGhpbiBhIGRheSkgdG8gMSwwMzggZGF5cywgd2l0aCBhIG1lYW4gb2YgNjQuNDIgZGF5cyBhbmQgYSBtZWRpYW4gb2YgMjggZGF5cyAoNCB3ZWVrcyEpLgoKUGxvdCBkaXN0cmlidXRpb24gb2YgbGVuZ3RoIG9mIGphaWwgc3RheS4KYGBge3IsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTV9IApDVGRzJGR1cjwtYXMubnVtZXJpYyhDVGRzJGlubWF0ZV90aW1lKQojYmVsb3cgaXMgZm9yIHRoZSBzYWtlIG9mIGxvZ3MKQ1RkcyRkdXJbQ1RkcyRkdXI9PTBdPC0xCgpnZ3Bsb3QoZGF0YT1DVGRzLCBhZXMoZHVyLCBmaWxsPXJhY2UpKSArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gLjI1KSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZT0iUmFjZSIsIHZhbHVlcyA9IGNiUGFsZXR0ZSkgKyAgCiAgdGhlbWVfbWluaW1hbCgpKyB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChmYW1pbHk9IlBhbGF0aW5vIikpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwKSkrCiAgbGFicyh4PSJEYXlzIERldGFpbmVkIiwgeT0iTnVtYmVyIG9mIFByZXRyaWFsIElubWF0ZXMiLCAKICAgICAgIGNhcHRpb249IlxuVGhpcyBwbG90IHVzZXMgYSBsb2cxMCB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgbGVuZ3RoIG9mIGphaWwgc3RheS5cbkVhY2ggb2JzZXJ2YXRpb24gaXMgZm9yIHNvbWUgYWRtaXNzaW9uIHdoaWNoIGNvbmNsdWRlZCBpbiBhIHJlbGVhc2UgZnJvbSBqYWlsIGJlZm9yZSA3LzI4LzE5LiAobj00Niw3MjIpXG4oQWdhaW4sIEkgZXhjbHVkZSBpbmRpdmlkdWFscyB3aG8gYXJlIGNvZGVkIGluY29uc2lzdGVudGx5IGJ5IHJhY2Ugb3IgZ2VuZGVyIG92ZXIgdGltZS4pIikrCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1jb21tYSkrCiAgc2NhbGVfeF9sb2cxMChsYWJlbHM9Y29tbWEpKyAKICBnZ3RpdGxlKCJKYWlsIFN0YXkgRHVyYXRpb24gUHJldHJpYWwgaW4gQ29ubmVjdGljdXQiLCBzdWJ0aXRsZSA9ICJEYXRhIEF2YWlsYWJsZSB2aWEgQ29ubmVjdGljdXQgT3BlbiBEYXRhIikKZ2dzYXZlKCJncmFwaHMvaW5tYXRldGltZS5wbmciLCB3aWR0aD04LCBoZWlnaHQ9NSwgZHBpPTkwMCkKYGBgClBsb3QgYXZlcmFnZXMgaW4gamFpbCBzdGF5IGJ5IHJhY2UuCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpDVGRzMTwtIENUZHNbLGMoInJhY2UiLCAiZHVyIiwgImFnZSIpXSAlPiUgCiAgICBncm91cF9ieShyYWNlKSAlPiUKICAgIHN1bW1hcmlzZV9hbGwoZnVucyhtZWFuLHNkLHNlPXNkKC4pL3NxcnQobigpKSkpCmBgYApQbG90IGl0LgpgYGB7cn0KI2dncGxvdChDVGJvbmRyLCBhZXMoeD1yYWNlLCB5PWJvbmRfYW1vdW50X21lYW4sIGNvbG91cj1yYWNlKSkgKyAKZ2dwbG90KENUZHMxLCBhZXMoeD1yYWNlLCB5PWR1cl9tZWFuKSkgKwogICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1kdXJfbWVhbi0oMS45NipkdXJfc2UpLCAKICAgICAgICAgICAgICAgICAgICAgIHltYXg9ZHVyX21lYW4rKDEuOTYqZHVyX3NlKSksIHdpZHRoPS4xKSArCiAgICBnZW9tX3BvaW50KCkrCiAgI3NjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjYlBhbGV0dGUpICsgIAogIHRoZW1lX21pbmltYWwoKSsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoZmFtaWx5PSJQYWxhdGlubyIpKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCkpKwogIGxhYnMoeD0iIiwgeT0iTWVhbiBKYWlsIFN0YXkgKERheXMpIiwgY2FwdGlvbj0iRWFjaCBvYnNlcnZhdGlvbiBpcyBmb3Igc29tZSBhZG1pc3Npb24gd2hpY2ggY29uY2x1ZGVkIGluIGEgcmVsZWFzZSBmcm9tIGphaWwgYmVmb3JlIDcvMjgvMTkuIChuPTQ2LDcyMilcbihBZ2FpbiwgSSBleGNsdWRlIGluZGl2aWR1YWxzIHdobyBhcmUgY29kZWQgaW5jb25zaXN0ZW50bHkgYnkgcmFjZSBvciBnZW5kZXIgb3ZlciB0aW1lLilcblRoZSBtZWFucyBieSByYWNlIGFyZSBwcmVzZW50ZWQgd2l0aCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMuIikrCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hLCBsaW1pdHM9YygwLDg1KSwgYnJlYWtzPXNlcSgwLDg1LDE1KSkrCiAgZ2d0aXRsZSgiTWVhbiBQcmV0cmlhbCBKYWlsIFN0YXkgYnkgUmFjaWFsIEdyb3VwIiwgc3VidGl0bGUgPSAiRGF0YSBBdmFpbGFibGUgdmlhIENvbm5lY3RpY3V0IE9wZW4gRGF0YSIpCmdnc2F2ZSgiZ3JhcGhzL3N0YXktcmFjZS5wbmciLCB3aWR0aD03LCBoZWlnaHQ9NSwgZHBpPTkwMCkKYGBgCgotLS0KCiMgNS4gVGltZSB2cy4gYmFpbAoKVG8gbG9vayBhdCByZWxhdGlvbnNoaXAgYmV0d2VuIGluaXRpYWwgYm9uZCBhbmQgdGltZSBpbiBqYWlsLCBtZXJnZSBgQ1Rkc2AgYW5kIGBDVGJvbmRgIGJ5IGBpZGVudGlmaWVyYCBhbmQgYGxhdGVzdF9hZG1pc3Npb25fZGF0ZWAuCmBgYHtyfQpiZDwtbWVyZ2UoQ1Rkc1ssYygiaWRlbnRpZmllciIsICJkdXIiLCAibGF0ZXN0X2FkbWlzc2lvbl9kYXRlIiwgInJhY2UiKV0sIAogICAgICAgICAgQ1Rib25kWyxjKCJpZGVudGlmaWVyIiwgImJvbmRfYW1vdW50IiwgImxhdGVzdF9hZG1pc3Npb25fZGF0ZSIsICJyYWNlIildLCAKICAgICAgICAgIGJ5PWMoImlkZW50aWZpZXIiLCAibGF0ZXN0X2FkbWlzc2lvbl9kYXRlIiwgInJhY2UiKSwgYWxsPUYpCmBgYAoKYGBge3J9Cm5yb3coYmQpCmBgYAoKVGhlcmUgYXJlIDQ2LDYxOSBvYnNlcnZhdGlvbnMgdG8gY29uc2lkZXIgLS0gdGhlcmUgYXJlIDQ2LDYxOSB1bmlxdWUgcGVyc29uLWNyaW1lcyBpbiB0aGUgZGF0YSB3aG8ndmUgYmVlbiByZWxlYXNlZCBmcm9tIGphaWwgKGV4Y2x1ZGluZyBpbmNvbnNpc3RlbnRseSBjb2RlZCBwZW9wbGUgYnkgZ2VuZGVyL3JhY2UpIGJlZm9yZSA3LTI4LTE5IHRoYXQgYWxzbyBpbmNsdWRlIGZpcnN0IG9ic2VydmF0aW9uIGJvbmQgYW1vdW50cyBhdCBvciBhYm92ZSAkMTAwIChleGNsdWRlIHRob3NlIGJlbG93IHNpbmNlIHRoZXkgYXJlIHVubGlrZWx5IHRvIGJlIHRydWUgYm9uZCBhbW91bnRzKS4KCmBgYHtyIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodmlyaWRpcyk7bGlicmFyeShoZXhiaW4pCmdncGxvdChkYXRhPWJkLCBhZXMoeD1ib25kX2Ftb3VudCwgeT1kdXIpKSsKICBzdGF0X2JpbmhleCgpKyBzY2FsZV9maWxsX3ZpcmlkaXMobmFtZT0ibiBpbiBoZXgiKSsKICB0aGVtZV9taW5pbWFsKCkrIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KGZhbWlseT0iUGFsYXRpbm8iKSkrCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDApKSsKICBsYWJzKHg9IkluaXRpYWwgQm9uZCBBbW91bnQgKCQpIiwgeT0iSmFpbCBTdGF5IChEYXlzKSIsIGNhcHRpb249IlxuVGhlIHBsb3QgZGlzcGxheXMgdGhlIGZyZXF1ZW5jeSBvZiBib25kIGFtb3VudC9qYWlsIHN0YXkgY29tYmluYXRpb25zIHdpdGggaGV4YWdvbmFsIGJpbnMuIChTZWUgbGVnZW5kLikgXG5PYnNlcnZhdGlvbnMgaW5jbHVkZSBhZG1pc3Npb25zIHdoaWNoIGNvbmNsdWRlZCBpbiBhIHJlbGVhc2UgZnJvbSBqYWlsIGJlZm9yZSA3LzI4LzE5LiAobj00Niw2MTkpIikrCiAgc2NhbGVfeV9sb2cxMChsYWJlbHM9Y29tbWEpKwogIHNjYWxlX3hfbG9nMTAobGFiZWxzPWNvbW1hKSsgCiAgZ2d0aXRsZSgiSW5pdGlhbCBCb25kIGFuZCBKYWlsIFN0YXkiLCBzdWJ0aXRsZSA9ICJEYXRhIEF2YWlsYWJsZSB2aWEgQ29ubmVjdGljdXQgT3BlbiBEYXRhIikKZ2dzYXZlKCJncmFwaHMvYm9uZHRpbWUucG5nIiwgd2lkdGg9OCwgaGVpZ2h0PTYsIGRwaT05MDApCmBgYApDaGVjayBjb3JyZWxhdGlvbjoKYGBge3J9CmNvcihiZCRib25kX2Ftb3VudCxiZCRkdXIpCmBgYApUaGVyZSBpcyBhIGNvcnJlbGF0aW9uIG9mIDAuMzY4IGJldHdlZW4gdGltZSBpbiBqYWlsIGFuZCBpbml0aWFsIGJvbmQgYm9uZCBhbW91bnQuCgojIFJlZ3Jlc3Npb24gZm9vdG5vdGUKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpDVGJvbmQgPC0gbXV0YXRlKENUYm9uZCwgY2hhcmdlbmV3ID0gZmFjdG9yKG9mZmVuc2UpKSAlPiUKICAgICAgbXV0YXRlKGZhY19mYWN0b3IgPSBmYWN0b3IoZmFjaWxpdHkpKSAlPiUKICAgICAgbXV0YXRlKHJhY2VfZmFjdG9yID0gZmFjdG9yKHJhY2UpKSAlPiUKICAgICAgd2l0aGluKHJhY2VfZmFjdG9yIDwtIHJlbGV2ZWwocmFjZV9mYWN0b3IsIHJlZiA9IDUpKSAlPiUKICAgICAgbXV0YXRlKGdlbmRlcl9mYWN0b3IgPSBmYWN0b3IoZ2VuZGVyKSkgJT4lCiAgICAgIHdpdGhpbihnZW5kZXJfZmFjdG9yIDwtIHJlbGV2ZWwoZ2VuZGVyX2ZhY3RvciwgcmVmID0gMikpCmBgYAoKVXNlIGxvZ3Mgb24gZGVwIHZhcmlhYmxlIGZvciByZWdyZXNzaW9ucy4KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJlZzNsIDwtIGxtKGxvZyhDVGJvbmQkYm9uZF9hbW91bnQpIH4gIHJhY2VfZmFjdG9yICsgZ2VuZGVyX2ZhY3RvciArIGFnZSAsIGRhdGE9Q1Rib25kKQpyZWc0bCA8LSBsbShsb2coQ1Rib25kJGJvbmRfYW1vdW50KSB+ICByYWNlX2ZhY3RvciArIGdlbmRlcl9mYWN0b3IgKyBhZ2UgKyBjaGFyZ2VuZXcgLCBkYXRhPUNUYm9uZCkKYGBgCgpNYWtlIHN0YXJnYXplciB0YWJsZSB3aXRoIHJvYnVzdCBzdGFuZGFyZCBlcnJvcnMgYW5kIGxvZyBvZiBkZXAgdmFyLgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgQWRqdXN0IHN0YW5kYXJkIGVycm9ycwpsaWJyYXJ5KHNhbmR3aWNoKQpjb3YgICAgICAgICA8LSB2Y292SEMocmVnM2wsIHR5cGUgPSAiSEMxIikKcm9idXN0X3NlICAgIDwtIHNxcnQoZGlhZyhjb3YpKQpjb3YxICAgICAgICAgPC0gdmNvdkhDKHJlZzRsLCB0eXBlID0gIkhDMSIpCnJvYnVzdF9zZTEgICAgPC0gc3FydChkaWFnKGNvdjEpKQoKbGlicmFyeShzdGFyZ2F6ZXIpCnN0YXJnYXplcihyZWczbCwgcmVnNGwsIHR5cGU9InRleHQiLCBvbWl0PWMoImNoYXJnZW5ldyIsICJmYWNfZmFjdG9yIiksIHN0eWxlPSJxamUiLAogICAgICAgICAgc2UgPSBsaXN0KHJvYnVzdF9zZSwgcm9idXN0X3NlMSksCiAgICAgICAgICBhZGQubGluZXMgPSBsaXN0KGMoIk9mZmVuc2UgRHVtbWllcz8iLCAiTm8iLCAiWWVzIikpLAogICAgICAgICAgdGl0bGUgPSAiV2hhdCBFeHBsYWlucyBIb3cgQm9uZCBpcyBTZXQ/IiwKICAgICAgICAgIGNvdmFyaWF0ZS5sYWJlbHMgPSBjKCJBc2lhbiIsICJCbGFjayIsICJIaXNwYW5pYyIsICJOYXRpdmUgQW1lcmljYW4iLCAiRmVtYWxlIiwgIkFnZSIpLAogICAgICAgICAgZGVwLnZhci5sYWJlbHMgICA9ICJMb2cgb2YgRG9sbGFyIEJvbmQgQW1vdW50Iiwgb21pdC5zdGF0PWMoImYiLCAic2VyIiksCiAgICAgICAgICBub3RlcyA9ICJVc2luZyByb2J1c3Qgc3RhbmRhcmQgZXJyb3JzLiIKICAgICAgICAgICkKYGBg