Introduction and
Background
Here we have a dataset sourced from New York City’s Traffic
Information Management System (TIMS). TIMS recorded the number of
cyclists entering and leaving three of New York City’s five boroughs -
Queens, Manhattan and Brooklyn - via a collection of bridges known as
the East River Bridges (Brooklyn Bridge, Manhattan Bridge, Williamsburg
Bridge, and Queensboro Bridge). These recordings took place in 2017.
April, July and October are the three months that are present in our
available copy of the data.
For today’s analysis we are going to look at a randomly selected
subset of the larger dataset (subset was chosen using R’s runif
function), that pertains to cyclists who entered and left our three
boroughs of interest - Queens, Manhattan and Brooklyn - via the
Manhattan Bridge throughout the entire month of July
2017. This data has 31 observations, one detailing each day, and no
missing values. A breakdown of each of the original dataset’s variables,
their practical meaning and data types are below.
|
Name
|
Meaning
|
Data_Type
|
|
Date
|
Date for that observation; YYYY-MM-DD form
|
Date
|
|
Day
|
Day of the week for that observation
|
character
|
|
HighTemp
|
That day’s highest recorded temperature
|
double
|
|
LowTemp
|
That day’s lowest recorded temperature
|
double
|
|
Precipitation
|
Measure of rain that day (inches)
|
double
|
|
Manhattan
|
Number of cyclists entering/leaving Queens, Manhattan or Brooklyn via
the MANHATTAN Bridge
|
double
|
|
Total
|
Total number of cyclists entering/leaving Queens, Manhattan or Brooklyn
via ANY of the East River Bridges
|
double
|
Objective of
Analysis
With the available data, my goal for this analysis is to examine the
association between weather conditions and day of the week with the
amount of cyclist traffic that the Manhattan Bridge experiences. In
order to do this, I created two new variables - MeanTemp and TempDiff -
which were calculated by averaging that particular day’s low and high
temperatures and finding the difference between those temperatures
respectively.
Using these temperature-related metrics, along with measures of
precipitation and records of the day of the week, I will use Poisson and
quasi-Poisson regression techniques to see which if any of these factors
play a particular role in the overall amount or the relative
rate of cyclist traffic that the Manhattan Bridge experiences.
Poisson Regression
Modeling
To explore any potential associations, I created Poisson models of
two different regression types, one being for counts and one being for
rates.
Poisson counts regression examines the total number of occurrences of
a particular event (in this case cyclists on the Manhattan Bridge) and
uses a logarithmic function to determine which, if any of the
explanatory variables have a significant effect on said response
variable’s mean. The formula for said regression is below:

\(\beta\)0 = the log
of our response variable’s mean; not very useful for practical
interpretation
\(\beta\)1, \(\beta\)2, \(\beta\)3, … \(\beta\)p = the change in our
response variable’s log mean, in association with a one unit increase in
said predictor variable
Additionally, Poisson rates regression aims to find the expected rate
of a particular event’s occurrence relative to that event’s proportion
within a larger “population.” In the instance of this dataset and
analysis, our variable Total, which represents the
total number of cyclists on all the East River Bridges,
will be what the number of cyclists on the Manhattan Bridge are
considered to be a proportion of. The calculation for this type of
Poisson regression is similar to counts regression, but the logarithm of
the population variable is also considered to be a factor. This can be
expressed in both of the following ways.
- In Poisson rates regression, the parameters \(\beta\)0, …. \(\beta\)p should be interpreted
in the same manner as they are in Poisson counts model.
Poisson Regression
(Counts)
Below is a summary of the Poisson counts regression model I created,
with measures of temperature range and averages, precipitation amount
and day of the week all functioning as predictors of how many cyclists
crossed the Manhattan Bridge in or out of our three boroughs of
interest.
# Counts Model:
# Response = Manhattan
# Predictors = Day, MeanTemp, TempDiff, Precipitation
# Day is stored as a Factor
Counts_Model = glm(Manhattan ~ Day + MeanTemp + TempDiff + Precipitation, family = poisson(link = "log"), data = Data)
Counts_Model_Sum = summary(Counts_Model)
Counts_Model_Coef = Counts_Model_Sum$coefficients
invisible(Counts_Model_Coef)
kable(Counts_Model_Coef, caption = "<b><center> Poisson Counts Regression: Weather and Schedule Relationship with Count of Manhattan Bridge Cyclists </center></b>")
Table:
Poisson Counts Regression: Weather and Schedule Relationship with Count
of Manhattan Bridge Cyclists
| (Intercept) |
8.5013371 |
0.0421490 |
201.697286 |
0.0000000 |
| DayMonday |
0.3199236 |
0.0089935 |
35.572866 |
0.0000000 |
| DayTuesday |
0.3357894 |
0.0093242 |
36.012843 |
0.0000000 |
| DayWednesday |
0.4023102 |
0.0090796 |
44.309388 |
0.0000000 |
| DayThursday |
0.2807381 |
0.0096557 |
29.074878 |
0.0000000 |
| DayFriday |
0.1331873 |
0.0107366 |
12.405032 |
0.0000000 |
| DaySaturday |
-0.0859127 |
0.0097279 |
-8.831613 |
0.0000000 |
| MeanTemp |
-0.0029260 |
0.0006129 |
-4.774076 |
0.0000018 |
| TempDiff |
0.0143243 |
0.0008575 |
16.703807 |
0.0000000 |
| Precipitation |
-0.4307477 |
0.0104214 |
-41.332836 |
0.0000000 |
# All predictor variables are significant
In the model, we can see that every predictor variable is
statistically significant as per p values well below the standard of
0.05, so no stepwise regression or model simplification is
necessary.
As for the practical implications of our model summary, we can say
that although every predictor variable is statistically significant, the
magnitude of their impacts are relatively small. Precipitation’s
estimated negative effect on the log mean of Manhattan Bridge cyclists
has an absolute value ~ |.4307|, which is the the highest of all our
predictors.
It appears that the day’s average temperature and difference in daily
highs and lows played very little practical significance in the log mean
of that day’s cyclists. When we look at the difference in log means from
a day-of-the-week perspective, we do see a slightly more impactful
effect. With Sunday being coded in as the baseline, it looks like
Wednesday has the greatest amount of cyclist traffic and Saturday has
the least. This higher count of cyclists during the workweek could be
due to the Manhattan Bridge functioning for many as a commuting
method.
All in all, our Poisson counts model yields some interesting and
statistically significant revelations, most notably that cyclists care
far more about precipitation than they do temperature fluctuation, and
that cyclist traffic appears to tick upwards throughout the workweek
before dying down for the weekend. However, the relatively small
magnitude of each variable’s estimated effect is a downside regarding
the model’s utility.
Poisson Regression
(Rates)
After Poisson counts regression, I then performed Poisson rates
regression with the total number of cyclists entering and exiting our
three boroughs of interest across all the East River Bridges as
the “population” for which the Manhattan Bridge cyclists are acting as a
sample of.
This process consisted of me creating two different Poisson rates
models. The first one I created listed both temperature variables as
statistically insignificant. Given their status as statistically
insignificant in this model, and their minute practical significance in
the previous counts model, I chose to remove them and create a second
Poisson rates model which did not factor in the day’s average or range
of temperature.
### Rates Model 1
Rates_Model = glm(Manhattan ~ Day + MeanTemp + TempDiff + Precipitation, offset = log(Total), family = poisson(link = "log"), data = Data)
Rates_Model_Sum = summary(Rates_Model)
Rates_Model_Coef = Rates_Model_Sum$coefficients
invisible(Rates_Model_Coef)
kable(Rates_Model_Coef, caption = "<b><center> Poisson Rates Regression (1): Weather and Schedule Relationship with Count of Manhattan Bridge Cyclists </center></b>")
Table:
Poisson Rates Regression (1): Weather and Schedule Relationship with
Count of Manhattan Bridge Cyclists
| (Intercept) |
-1.1844325 |
0.0418215 |
-28.3211719 |
0.0000000 |
| DayMonday |
0.0418134 |
0.0088829 |
4.7071774 |
0.0000025 |
| DayTuesday |
0.0549949 |
0.0094416 |
5.8247706 |
0.0000000 |
| DayWednesday |
0.0316272 |
0.0090743 |
3.4853702 |
0.0004915 |
| DayThursday |
0.0048565 |
0.0096974 |
0.5008067 |
0.6165072 |
| DayFriday |
-0.0167479 |
0.0108925 |
-1.5375635 |
0.1241554 |
| DaySaturday |
-0.0667274 |
0.0097414 |
-6.8498669 |
0.0000000 |
| MeanTemp |
-0.0010004 |
0.0006053 |
-1.6527512 |
0.0983815 |
| TempDiff |
0.0008449 |
0.0008628 |
0.9792330 |
0.3274649 |
| Precipitation |
-0.0306511 |
0.0095235 |
-3.2184824 |
0.0012887 |
### Rates Model 2
Rates_Model2 = glm(Manhattan ~ Day + Precipitation, offset = log(Total), family = poisson(link = "log"), data = Data)
Rates_Model2_Sum = summary(Rates_Model2)
Rates_Model2_Coef = Rates_Model2_Sum$coefficients
invisible(Rates_Model_Coef)
kable(Rates_Model2_Coef, caption = "<b><center> Poisson Rates Regression (2): Precipitation and Schedule Relationship with Count of Manhattan Bridge Cyclists </center></b>")
Table:
Poisson Rates Regression (2): Precipitation and Schedule Relationship
with Count of Manhattan Bridge Cyclists
| (Intercept) |
-1.2497005 |
0.0065309 |
-191.3530685 |
0.0000000 |
| DayMonday |
0.0417392 |
0.0088231 |
4.7306551 |
0.0000022 |
| DayTuesday |
0.0522471 |
0.0090521 |
5.7718313 |
0.0000000 |
| DayWednesday |
0.0285783 |
0.0088706 |
3.2216687 |
0.0012745 |
| DayThursday |
0.0006398 |
0.0091826 |
0.0696739 |
0.9444532 |
| DayFriday |
-0.0205402 |
0.0106430 |
-1.9299220 |
0.0536165 |
| DaySaturday |
-0.0684652 |
0.0096858 |
-7.0685797 |
0.0000000 |
| Precipitation |
-0.0288171 |
0.0093266 |
-3.0897749 |
0.0020031 |
Looking at the findings of our second Poisson rates regression model,
we see a trend similar to that of our Poisson counts regression model,
that being a common occurrence of statistical significance but not a
great deal of practical significance on display when the magnitude of
the regression coefficient is taken into consideration.
Once again treating Sunday as our baseline, it looks like the rate of
Manhattan Bridge cyclists in proportion to the entirety of East River
Bridge cyclists is at its highest early in the week, with that rate
declining going into the weekend. That being said, the statistical
significance of this breakdown also greatly decreases when we look at
the data for Thursday and to a much lesser but still noticeable extent
Friday, perhaps suggesting that the Manhattan Bridge cyclist rate’s
decline at the tail end of the workweek could be chalked up to random
chance and not a particular characteristic of the Bridge that affects
the experience of its cyclists only on those particular days.
Day of the Week
Averages
Since both our counts and rates models suggested that the day of the
week has the greatest association with the log mean of the Manhattan
Bridge’s cyclists, I decided to calculate the average counts and rates
per day to compare them to each other and the mean across all days
considered. The table with this information is below.
Count_Averages = c(
round(mean(Data$Manhattan)),
round(mean(Data$Manhattan[Data$Day == "Sunday"])),
round(mean(Data$Manhattan[Data$Day == "Monday"])),
round(mean(Data$Manhattan[Data$Day == "Tuesday"])),
round(mean(Data$Manhattan[Data$Day == "Wednesday"])),
round(mean(Data$Manhattan[Data$Day == "Thursday"])),
round(mean(Data$Manhattan[Data$Day == "Friday"])),
round(mean(Data$Manhattan[Data$Day == "Saturday"]))
)
AllDays_Rates_Avg = sum(Data$Manhattan)/sum(Data$Total)
Sun_Rates_Avg = sum(Data$Manhattan[Data$Day == "Sunday"])/sum(Data$Total[Data$Day == "Sunday"])
Mon_Rates_Avg = sum(Data$Manhattan[Data$Day == "Monday"])/sum(Data$Total[Data$Day == "Monday"])
Tues_Rates_Avg = sum(Data$Manhattan[Data$Day == "Tuesday"])/sum(Data$Total[Data$Day == "Tuesday"])
Wed_Rates_Avg = sum(Data$Manhattan[Data$Day == "Wednesday"])/sum(Data$Total[Data$Day == "Wednesday"])
Thur_Rates_Avg = sum(Data$Manhattan[Data$Day == "Thursday"])/sum(Data$Total[Data$Day == "Thursday"])
Fri_Rates_Avg = sum(Data$Manhattan[Data$Day == "Friday"])/sum(Data$Total[Data$Day == "Friday"])
Sat_Rates_Avg = sum(Data$Manhattan[Data$Day == "Saturday"])/sum(Data$Total[Data$Day == "Saturday"])
Day_Rates_Averages = c(AllDays_Rates_Avg, Sun_Rates_Avg, Mon_Rates_Avg, Tues_Rates_Avg, Wed_Rates_Avg, Thur_Rates_Avg, Fri_Rates_Avg, Sat_Rates_Avg)
Rate_Averages = round(Day_Rates_Averages, digits = 4)
Days = c("All Days", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
Counts_Difference = c(
0, # Difference between the average count of all days and itself
round(mean(Data$Manhattan[Data$Day == "Sunday"])) - round(mean(Data$Manhattan)),
round(mean(Data$Manhattan[Data$Day == "Monday"])) - round(mean(Data$Manhattan)),
round(mean(Data$Manhattan[Data$Day == "Tuesday"])) - round(mean(Data$Manhattan)),
round(mean(Data$Manhattan[Data$Day == "Wednesday"])) - round(mean(Data$Manhattan)),
round(mean(Data$Manhattan[Data$Day == "Thursday"])) - round(mean(Data$Manhattan)),
round(mean(Data$Manhattan[Data$Day == "Friday"])) - round(mean(Data$Manhattan)),
round(mean(Data$Manhattan[Data$Day == "Saturday"])) - round(mean(Data$Manhattan))
)
Rates_DifferenceB = c(
0,
Sun_Rates_Avg - AllDays_Rates_Avg,
Mon_Rates_Avg - AllDays_Rates_Avg,
Tues_Rates_Avg - AllDays_Rates_Avg,
Wed_Rates_Avg - AllDays_Rates_Avg,
Thur_Rates_Avg - AllDays_Rates_Avg,
Fri_Rates_Avg - AllDays_Rates_Avg,
Sat_Rates_Avg - AllDays_Rates_Avg
)
Rates_Difference = round(Rates_DifferenceB, digits = 4)
Table = cbind(Days, Count_Averages, Counts_Difference, Rate_Averages, Rates_Difference)
kable(Table, caption = "<b><center><span style='color:#000000;'>Distribution of Manhattan Bridge Cyclist Count and Rates July 2017</center></b>") %>%
kable_styling(
bootstrap_options = c("striped", "bordered"),
full_width = FALSE,
position = "center"
)
Distribution of Manhattan Bridge Cyclist
Count and Rates July 2017
|
Days
|
Count_Averages
|
Counts_Difference
|
Rate_Averages
|
Rates_Difference
|
|
All Days
|
5425
|
0
|
0.2885
|
0
|
|
Sunday
|
4690
|
-735
|
0.2865
|
-0.002
|
|
Monday
|
6001
|
576
|
0.2975
|
0.009
|
|
Tuesday
|
6363
|
938
|
0.302
|
0.0135
|
|
Wednesday
|
6938
|
1513
|
0.2949
|
0.0064
|
|
Thursday
|
5999
|
574
|
0.2868
|
-0.0017
|
|
Friday
|
4338
|
-1087
|
0.2775
|
-0.0109
|
|
Saturday
|
4031
|
-1394
|
0.2665
|
-0.022
|
The table provides greater detail into the implications of our
Poisson count and rate models. That being weekday totals of Manhattan
Bridge cyclists (specifically Monday - Thursday) far outweigh the count
of cyclists on the bridge from Friday to Sunday. With the average number
of cylclists from Monday - Thursday being about 6,325, and the average
number Friday - Sunday being about 4,353.
As for the rate of Manhattan Bridge cyclists relative to cyclists on
all East River Bridges, we see that the Manhattan Bridge’s cyclist rate
is slightly above average Monday - Wednesday, but then below average
Thursday through Sunday.
Poisson Modeling
Takeaways
To conclude, any implementations done in response to our Poisson
models’ findings should be done with some degree of caution due to the
low practical significance found in both our count and rate models. That
being said, there are still valuable takeaways that we can draw from our
analysis.
First, the Manhattan Bridge is clearly busier, both in the sense of
raw volume and as a proportion of the overall East River Bridge network,
early and throughout the standard workweek than it is during the
weekend. Second, the daily average temperature as well as the difference
between that day’s high and low played very little if any role in the
count or rate of cyclists on any given day, but the measure of
precipitation does appear to have a relatively noticeable and negative
association with the number of that day’s cyclists on the Manhattan
Bridge.
Quasi-Poisson
Regression Modeling
In addition to analyzing our data at hand via Poisson regression, I
decided to also create a quasi-Poisson model of the data. Quasi-Poisson
modeling is an alternative to Poisson modeling, and it is particularly
valuable when the mean and variance of the model’s response variable
(number of cyclists on the Manhattan bridge in this case) are not
approximately equal to one another (known as dispersion).
For my quasi-Poisson model, I included that day’s average
temperature, day of the week and precipitation amount as the relevant
factors. Day of the week obviously played the biggest role in our
previous Poisson models, with precipitation consistently being cited as
statistically significant despite relatively low practical significance.
For this model, I chose to discretize precipitation, with days of no
recorded rain being marked as “0” and days with any amount of
rain being marked as “1.”
Data$NewPrecip = Data$Precipitation
Data$NewPrecip[Data$Precipitation == 0] = 0
Data$NewPrecip[Data$Precipitation > 0] = 1
Data = data.frame(Data$Date, Data$Day, Data$Day_Num, Data$HighTemp, Data$LowTemp, Data$MeanTemp, Data$TempDiff, Data$Precipitation, Data$NewPrecip, Data$Manhattan, Data$Total)
colnames(Data) = c("Date", "Day", "Day_Num", "HighTemp", "LowTemp", "MeanTemp","TempDiff", "Precipitation", "NewPrecip","Manhattan", "Total")
# 1.) Below is the quasi-Poisson regression model
# As instructed, only includes Day, MeanTemp and NewPrecip
Quasi_Counts_Model = glm(Manhattan ~ Day + MeanTemp + NewPrecip, family = quasipoisson, data = Data)
Quasi_Counts_Model_Sum = summary(Quasi_Counts_Model)
Quasi_Counts_Model_Coef = Quasi_Counts_Model_Sum$coefficients
invisible(Quasi_Counts_Model_Coef)
kable(Quasi_Counts_Model_Coef, caption = "<b><center> Quasi-Poisson Counts Regression: Weather and Schedule Relationship with Count of Manhattan Bridge Cyclists </center></b>")
Table:
Quasi-Poisson Counts Regression: Weather and Schedule Relationship with
Count of Manhattan Bridge Cyclists
| (Intercept) |
8.0428119 |
0.5287239 |
15.2117416 |
0.0000000 |
| DayMonday |
0.3201598 |
0.1180432 |
2.7122270 |
0.0127244 |
| DayTuesday |
0.2356884 |
0.1223379 |
1.9265366 |
0.0670535 |
| DayWednesday |
0.3064451 |
0.1211249 |
2.5299920 |
0.0190731 |
| DayThursday |
0.2542985 |
0.1240203 |
2.0504581 |
0.0524206 |
| DayFriday |
0.0302193 |
0.1365853 |
0.2212482 |
0.8269398 |
| DaySaturday |
-0.0805066 |
0.1301538 |
-0.6185500 |
0.5425648 |
| MeanTemp |
0.0062851 |
0.0068223 |
0.9212583 |
0.3669084 |
| NewPrecip |
-0.4057049 |
0.0921307 |
-4.4035809 |
0.0002251 |
A summary of the quasi-Poisson counts model can be seen above. We can
see that there is great similarity between the findings of this model
and our original Poisson counts model. However before we can determine
which one is superior for interpretative use, we must calculate this
quasi-Poisson’s dispersion parameter, “phi hat” (\(\hat{\phi}\)).
Dispersion and Counts
Model Selection
\(\hat{\phi}\) is used in
quasi-Poisson regression to determine if our data’s response variable is
overly or underly dispersed. Generally, a phi hat value of around 1 is
representative of an approximately equal mean and variance of the
response. If a quasi-Poisson model’s dispersion value is significantly
different than 1, then that model should be used for associative
analysis rather than a traditional Poisson counterpart, as the
quasi-Poisson calculation includes greater estimation of standard
errors. However, if \(\hat{\phi}\) ~ 1,
then the traditional Poisson model should be used, as it is less
computationally intensive and avoids otherwise unnecessary extra steps.
The formula for \(\hat{\phi}\)’s
calculation can be seen below.

n = nrow(Data)
p = 3
Pearson_Residuals = residuals(Quasi_Counts_Model, type = "pearson")
Sq_Pearson_Residuals = Pearson_Residuals^2
Dispersion_Parameter = (sum(Sq_Pearson_Residuals))/(n-p)
#### Double checked phi's value using Prof's coding method; got same result
ydif=Data$Manhattan-exp(Quasi_Counts_Model$linear.predictors) # diff between y and yhat
prsd = ydif/sqrt(exp(Quasi_Counts_Model$linear.predictors)) # Pearson residuals
phi_check = sum(prsd^2)/(n-p)
####
invisible(Dispersion_Parameter)
invisible(phi_check)
Our model yielded a value of \(\hat{\phi}\) ~ 142, which is
well beyond the margin of error for a properly
dispersed Poisson response variable. For this reason, we can deem that
the quasi-Poisson counts model is more valuable for associative analysis
than the Poisson counts model. Because of this, we will use the
quasi-Poisson for our ultimate interpretations.
Visual Aids
Referring to our quasi-Poisson model summary above, we see that the
day’s average temperature does not appear to have significant
statistical or practical association with the Manhattan bridge’s number
of cyclists. However, there does appear to be such a difference between
the number of cyclists on a totally clear day as opposed to a day with
at least some level of precipitation (recorded via variable
NewPrecip). And, as consistently seen in our original Poisson regression
models, there is certainly a large difference between the typical number
of cyclists depending on the day of the week.
Knowing this, I created two visuals below to enhance our grasp of the
relationship that both the day of the week and the presence of
precipitation have with each other as well as the standard number of
cyclists that were on the Manhattan Bridge throughout July 2017.
Unfortunately, there were no instances of Tuesdays or Wednesdays with
precipitation in this study, resulting in a blank in both our table and
bar chart below.
#### Table
Days = c("All Days", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
No_Precipitation = c(
round(mean(Data$Manhattan[Data$NewPrecip == 0])),
round(mean(Data$Manhattan[Data$NewPrecip == 0 & Data$Day == "Sunday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 0 & Data$Day == "Monday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 0 & Data$Day == "Tuesday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 0 & Data$Day == "Wednesday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 0 & Data$Day == "Thursday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 0 & Data$Day == "Friday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 0 & Data$Day == "Saturday"]))
)
Some_Precipitation = c(
round(mean(Data$Manhattan[Data$NewPrecip == 1])),
round(mean(Data$Manhattan[Data$NewPrecip == 1 & Data$Day == "Sunday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 1 & Data$Day == "Monday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 1 & Data$Day == "Tuesday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 1 & Data$Day == "Wednesday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 1 & Data$Day == "Thursday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 1 & Data$Day == "Friday"])),
round(mean(Data$Manhattan[Data$NewPrecip == 1 & Data$Day == "Saturday"]))
)
Vis_Table = data.frame(Days, No_Precipitation, Some_Precipitation)
kable(Vis_Table, caption = "<b><center><span style='color:#000000;'>Average Cyclist Counts on the Manhattan Bridge July 2017</center></b>") %>%
kable_styling(
bootstrap_options = c("striped", "bordered"),
full_width = FALSE,
position = "center")
Average Cyclist Counts on the Manhattan
Bridge July 2017
|
Days
|
No_Precipitation
|
Some_Precipitation
|
|
All Days
|
6008
|
3746
|
|
Sunday
|
4924
|
3756
|
|
Monday
|
7408
|
3892
|
|
Tuesday
|
6363
|
NaN
|
|
Wednesday
|
6938
|
NaN
|
|
Thursday
|
6006
|
5980
|
|
Friday
|
5802
|
2874
|
|
Saturday
|
4484
|
3352
|
#### Barchart
Vis_long =
Vis_Table %>%
pivot_longer(
cols = c(No_Precipitation, Some_Precipitation),
names_to = "Precipitation",
values_to = "Manhattan"
)
Vis_long$Days = factor(
Vis_long$Days,
levels = c("All Days", "Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday")
)
ggplot(Vis_long,
aes(x = Days, y = Manhattan, fill = Precipitation)) +
geom_bar(stat = "identity",
position = position_dodge(width = 0.9),
na.rm = TRUE) +
labs(
title = "Average Cyclist Counts on the Manhattan Bridge July 2017",
x = "Day of the Week",
y = "Number of Cyclists",
fill = "Precipitation"
) +
scale_fill_manual(
values = c("No_Precipitation" = "darkred",
"Some_Precipitation" = "lightblue")
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank()
)

The depictions above provide added clarity to the summary statistics
from our quasi-Poisson model. Sunday was the baseline for our regression
model’s calculations, and all remaining days other than Saturday had
positive coefficients. We can see in both our chart and table, that the
count of cyclists is certainly higher throughout the week than it is on
the weekends. As for the role of precipitation; our discretized variable
NewPrecip had a regression coefficent of ~ 0.4 (the highest absolute
value of any factor in the model) and a significant p value ~ .0002.
That finding can be intuitively confirmed by taking a glance at our
visuals. Other than Thursday, all other days for which there are data
points for both precipitation and no precipitation show a
noticeable decrease in cyclists when there is a presence of
precipitation.
Conclusion
Through our analysis via the means of both Poisson and quasi-Poisson
modeling techniques, our findings were relatively consistent. Those
being the following;
- The Manhattan Bridge is far busier during the week than it is on the
weekend.
- At least in the month of July, the temperature does not play any
sort of significant role in the raw number of the bridge’s cyclists nor
its share of the totality of East River Bridge cyclists.
- Although temperature is not significantly associated with cyclist
traffic, precipitation is. Any amount of precipitation has a negative
and statistically significant relationship with Manhattan Bridge’s
cyclist traffic.
Regarding the existence of both our Poisson and quasi-Poisson models
to estimate the association between all these factors, the quasi-Poisson
is more ideal due to this dataset’s extremely high dispersion
parameter (\(\hat{\phi}\) ~ 142).
If we were to continue or expand on this analysis in the future, it
would be valuable to expand the scope of our data outside of the month
of July and into months that border on seasonal changes such as March,
April or October. Intuitively, one might guess that the day’s
temperatures play a much larger role in a time of the year like
that.
LS0tCnRpdGxlOiAiUG9pc3NvbiBhbmQgUXVhc2ktUG9pc3NvbiBBbmFseXNpcyBvZiBSZWxhdGlvbnNoaXAgYmV0d2VlbiBXZWF0aGVyIGFuZCBEYXkgb2YgV2VlayB3aXRoIEN5Y2xpc3QgVHJhZmZpYyBvbiBNYW5oYXR0YW4gQnJpZGdlIgphdXRob3I6ICJDaHJpcyBCYWhtIgpkYXRlOiAiMjAyNS0xMS0xMCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIHRvY19kZXB0aDogNAogICAgZmlnX3dpZHRoOiA2CiAgICBmaWdfaGVpZ2h0OiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0Ci0tLQoKYGBge2NzcywgZWNobyA9IEZBTFNFfQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOwogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOwogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsKICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsKfQoKaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8KICBmb250LXNpemU6IDI0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IAojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4KCmlmICghcmVxdWlyZSgia25pdHIiKSkgeyAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBjb25kaXRpb25hbCBzdGF0ZW1lbnQgdG8gZGV0ZWN0CiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikgICAgICAgICAgICAgICAgICAjIHdoZXRoZXIgYSBwYWNrYWdlIHdhcyBpbnN0YWxsZWQgaW4KICAgbGlicmFyeShrbml0cikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91ciBtYWNoaW5lLiBJZiBub3QsIGluc3RhbGwgaXQgYW5kCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxvYWQgaXQgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgoKaWYgKCFyZXF1aXJlKHRpZHl2ZXJzZSkpIHtsaWJyYXJ5KHRpZHl2c2Vyc2UpfSAKCmlmICghcmVxdWlyZShHR2FsbHkpKSB7bGlicmFyeShHR2FsbHkpfSAKCmlmICghcmVxdWlyZShrYWJsZUV4dHJhKSkge2xpYnJhcnkoa2FibGVFeHRyYSl9IAoKaWYgKCFyZXF1aXJlKGdncGxvdDIpKSB7bGlicmFyeShnZ3Bsb3QyKX0gCgppZiAoIXJlcXVpcmUoY2FyKSkge2xpYnJhcnkoY2FyKX0gCgppZiAoIXJlcXVpcmUoZHBseXIpKSB7bGlicmFyeShkcGx5cil9IAoKaWYgKCFyZXF1aXJlKHBhbmRlcikpIHtsaWJyYXJ5KHBhbmRlcil9IAoKaWYgKCFyZXF1aXJlKGNhcikpIHtsaWJyYXJ5KGNhcil9IAoKaWYgKCFyZXF1aXJlKCJzY2FsZXMiKSkgewppbnN0YWxsLnBhY2thZ2VzKCJzY2FsZXMiKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKbGlicmFyeSgic2NhbGVzIikgCn0KCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKCWVjaG8gPSBUUlVFLAoJbWVzc2FnZSA9IEZBTFNFLAoJd2FybmluZyA9IEZBTFNFLAoJY29tbWVudCA9IE5BLAoJcmVzdWx0cyA9IFRSVUUKKQoKYGBgCgojIEludHJvZHVjdGlvbiBhbmQgQmFja2dyb3VuZCAKSGVyZSB3ZSBoYXZlIGEgZGF0YXNldCBzb3VyY2VkIGZyb20gTmV3IFlvcmsgQ2l0eSdzIFRyYWZmaWMgSW5mb3JtYXRpb24gTWFuYWdlbWVudCBTeXN0ZW0gKFRJTVMpLiBUSU1TIHJlY29yZGVkIHRoZSBudW1iZXIgb2YgY3ljbGlzdHMgZW50ZXJpbmcgYW5kIGxlYXZpbmcgdGhyZWUgb2YgTmV3IFlvcmsgQ2l0eSdzIGZpdmUgYm9yb3VnaHMgLSBRdWVlbnMsIE1hbmhhdHRhbiBhbmQgQnJvb2tseW4gLSB2aWEgYSBjb2xsZWN0aW9uIG9mIGJyaWRnZXMga25vd24gYXMgdGhlIEVhc3QgUml2ZXIgQnJpZGdlcyAoQnJvb2tseW4gQnJpZGdlLCBNYW5oYXR0YW4gQnJpZGdlLCBXaWxsaWFtc2J1cmcgQnJpZGdlLCBhbmQgUXVlZW5zYm9ybyBCcmlkZ2UpLiBUaGVzZSByZWNvcmRpbmdzIHRvb2sgcGxhY2UgaW4gMjAxNy4gQXByaWwsIEp1bHkgYW5kIE9jdG9iZXIgYXJlIHRoZSB0aHJlZSBtb250aHMgdGhhdCBhcmUgcHJlc2VudCBpbiBvdXIgYXZhaWxhYmxlIGNvcHkgb2YgdGhlIGRhdGEuCgpGb3IgdG9kYXkncyBhbmFseXNpcyB3ZSBhcmUgZ29pbmcgdG8gbG9vayBhdCBhIHJhbmRvbWx5IHNlbGVjdGVkIHN1YnNldCBvZiB0aGUgbGFyZ2VyIGRhdGFzZXQgKHN1YnNldCB3YXMgY2hvc2VuIHVzaW5nIFIncyBydW5pZiBmdW5jdGlvbiksIHRoYXQgcGVydGFpbnMgdG8gY3ljbGlzdHMgd2hvIGVudGVyZWQgYW5kIGxlZnQgb3VyIHRocmVlIGJvcm91Z2hzIG9mIGludGVyZXN0IC0gUXVlZW5zLCBNYW5oYXR0YW4gYW5kIEJyb29rbHluIC0gdmlhIHRoZSAqKk1hbmhhdHRhbioqIEJyaWRnZSB0aHJvdWdob3V0IHRoZSBlbnRpcmUgbW9udGggb2YgSnVseSAyMDE3LiBUaGlzIGRhdGEgaGFzIDMxIG9ic2VydmF0aW9ucywgb25lIGRldGFpbGluZyBlYWNoIGRheSwgYW5kIG5vIG1pc3NpbmcgdmFsdWVzLiBBIGJyZWFrZG93biBvZiBlYWNoIG9mIHRoZSBvcmlnaW5hbCBkYXRhc2V0J3MgdmFyaWFibGVzLCB0aGVpciBwcmFjdGljYWwgbWVhbmluZyBhbmQgZGF0YSB0eXBlcyBhcmUgYmVsb3cuCgpgYGB7ciBWYXJpYWJsZSBUYWJsZSwgZWNobz1GQUxTRX0KbGlicmFyeShrbml0cikKClZhcl9UYWJsZSA9IGRhdGEuZnJhbWUoCiAgTmFtZSA9IGMoIkRhdGUiLAogICAgICAgICAgICJEYXkiLCAKICAgICAgICAgICAiSGlnaFRlbXAiLCAKICAgICAgICAgICAiTG93VGVtcCIsCiAgICAgICAgICAgIlByZWNpcGl0YXRpb24iLCAKICAgICAgICAgICAiTWFuaGF0dGFuIiwgCiAgICAgICAgICAgIlRvdGFsIiksCiAgCiAgTWVhbmluZyA9IGMoIkRhdGUgZm9yIHRoYXQgb2JzZXJ2YXRpb247IFlZWVktTU0tREQgZm9ybSIsIAogICAgICAgICAgICAgICJEYXkgb2YgdGhlIHdlZWsgZm9yIHRoYXQgb2JzZXJ2YXRpb24iLAogICAgICAgICAgICAgICJUaGF0IGRheSdzIGhpZ2hlc3QgcmVjb3JkZWQgdGVtcGVyYXR1cmUiLCAKICAgICAgICAgICAgICAiVGhhdCBkYXkncyBsb3dlc3QgcmVjb3JkZWQgdGVtcGVyYXR1cmUiLCAKICAgICAgICAgICAgICAiTWVhc3VyZSBvZiByYWluIHRoYXQgZGF5IChpbmNoZXMpIiwgIAogICAgICAgICAgICAgICJOdW1iZXIgb2YgY3ljbGlzdHMgZW50ZXJpbmcvbGVhdmluZyBRdWVlbnMsIE1hbmhhdHRhbiBvciBCcm9va2x5biB2aWEgdGhlIE1BTkhBVFRBTiBCcmlkZ2UiLAogICAgICAgICAgICAgICJUb3RhbCBudW1iZXIgb2YgY3ljbGlzdHMgZW50ZXJpbmcvbGVhdmluZyBRdWVlbnMsIE1hbmhhdHRhbiBvciBCcm9va2x5biB2aWEgQU5ZIG9mIHRoZSBFYXN0IFJpdmVyIEJyaWRnZXMiKSwgCiAgICAgICAgICAgICAgCiAgCiAgRGF0YV9UeXBlID0gYygiRGF0ZSIsICJjaGFyYWN0ZXIiLCAiZG91YmxlIiwgImRvdWJsZSIsICJkb3VibGUiLCAiZG91YmxlIiwgImRvdWJsZSIpKQoKa2FibGUoVmFyX1RhYmxlKSAlPiUKICBrYWJsZV9zdHlsaW5nKAogICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiksCiAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICBwb3NpdGlvbiA9ICJjZW50ZXIiKQoKYGBgCiMjIE9iamVjdGl2ZSBvZiBBbmFseXNpcwpXaXRoIHRoZSBhdmFpbGFibGUgZGF0YSwgbXkgZ29hbCBmb3IgdGhpcyBhbmFseXNpcyBpcyB0byBleGFtaW5lIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHdlYXRoZXIgY29uZGl0aW9ucyBhbmQgZGF5IG9mIHRoZSB3ZWVrIHdpdGggdGhlIGFtb3VudCBvZiBjeWNsaXN0IHRyYWZmaWMgdGhhdCB0aGUgTWFuaGF0dGFuIEJyaWRnZSBleHBlcmllbmNlcy4gSW4gb3JkZXIgdG8gZG8gdGhpcywgSSBjcmVhdGVkIHR3byBuZXcgdmFyaWFibGVzIC0gTWVhblRlbXAgYW5kIFRlbXBEaWZmIC0gd2hpY2ggd2VyZSBjYWxjdWxhdGVkIGJ5IGF2ZXJhZ2luZyB0aGF0IHBhcnRpY3VsYXIgZGF5J3MgbG93IGFuZCBoaWdoIHRlbXBlcmF0dXJlcyBhbmQgZmluZGluZyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRob3NlIHRlbXBlcmF0dXJlcyByZXNwZWN0aXZlbHkuIAoKVXNpbmcgdGhlc2UgdGVtcGVyYXR1cmUtcmVsYXRlZCBtZXRyaWNzLCBhbG9uZyB3aXRoIG1lYXN1cmVzIG9mIHByZWNpcGl0YXRpb24gYW5kIHJlY29yZHMgb2YgdGhlIGRheSBvZiB0aGUgd2VlaywgSSB3aWxsIHVzZSBQb2lzc29uIGFuZCBxdWFzaS1Qb2lzc29uIHJlZ3Jlc3Npb24gdGVjaG5pcXVlcyB0byBzZWUgd2hpY2ggaWYgYW55IG9mIHRoZXNlIGZhY3RvcnMgcGxheSBhIHBhcnRpY3VsYXIgcm9sZSBpbiB0aGUgb3ZlcmFsbCBhbW91bnQgKm9yKiB0aGUgcmVsYXRpdmUgcmF0ZSBvZiBjeWNsaXN0IHRyYWZmaWMgdGhhdCB0aGUgTWFuaGF0dGFuIEJyaWRnZSBleHBlcmllbmNlcy4KCmBgYHtyIERhdGEgTG9hZGluZyBhbmQgQ2xlYW5pbmcsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkgKG9wZW54bHN4KQpvcHRpb25zKHNjaXBlbiA9IDk5OSkKCiMgcm91bmQocnVuaWYoMSwgbWluID0gMSwgbWF4ID0gMTApKQogICMgVXNlZCBsaW5lIGFib3ZlIHRvIHJhbmRvbWx5IHNlbGVjdCB3aGljaCBzdWJzZXQgb2YgdGhlIGRhdGEgdG8gZG8gbXkgYW5hbHlzaXMgb24uIFRoZSBmaWZ0aCB0YWIgb24gdGhlIG9yaWdpbmFsIGRhdGEgRXhjZWwgc3ByZWFkc2hlZXQgd2FzIGZvciBvYnNlcnZhdGlvbnMgb24gdGhlIE1hbmhhdHRhbiBCcmlkZ2UgZnJvbSA3LzEgdG8gNy8zMQoKRGF0YSA9IHJlYWQueGxzeCgiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0NocmlzQjIzMjMvU1RBMzIxL3JlZnMvaGVhZHMvbWFpbi9OWUNfQ3ljbGlzdHNfRGF0YS54bHN4Iiwgc2hlZXQgPSAiTWFuaGF0dGFuIDIiKQoKZ2xpbXBzZShEYXRhKQoKIyBDb252ZXJ0aW5nIHZhcmlhYmxlIERhdGUgdG8gYSBkYXRlIG9iamVjdC4KIyBPcmlnaW4gPSAxODk5LTEyLTMwIHNpbmNlIEV4Y2VsIHN0b3JlcyBkYXRhIHZhbHVlcyBhcyB0aGUgbnVtYmVyIG9mIGRheXMgc2luY2UgdGhlbi4KRGF0YSREYXRlID0gYXMuRGF0ZShEYXRhJERhdGUsIG9yaWdpbiA9ICIxODk5LTEyLTMwIikKCiMgT3JpZ2luYWxseSBjb252ZXJ0aW5nIHZhcmlhYmxlIERheSB0byBhIGRhdGUgb2JqZWN0LCB0aGVuIHVzaW5nIHRoZSB3ZWVrZGF5cyBmdW5jdGlvbiBvbiBpdC4KRGF0YSREYXkgPSBhcy5EYXRlKERhdGEkRGF5LCBvcmlnaW4gPSAiMTg5OS0xMi0zMCIpCiAgRGF0YSREYXkgPSB3ZWVrZGF5cyhhcy5EYXRlKERhdGEkRGF5KSkKCiAgIyBDcmVhdGlvbiBvZiBEYXlfTnVtIHZhcmlhYmxlCkRhdGEkRGF5X051bVtEYXRhJERheSA9PSAiU3VuZGF5Il0gPSAxCkRhdGEkRGF5X051bVtEYXRhJERheSA9PSAiTW9uZGF5Il0gPSAyCkRhdGEkRGF5X051bVtEYXRhJERheSA9PSAiVHVlc2RheSJdID0gMwpEYXRhJERheV9OdW1bRGF0YSREYXkgPT0gIldlZG5lc2RheSJdID0gNApEYXRhJERheV9OdW1bRGF0YSREYXkgPT0gIlRodXJzZGF5Il0gPSA1CkRhdGEkRGF5X051bVtEYXRhJERheSA9PSAiRnJpZGF5Il0gPSA2CkRhdGEkRGF5X051bVtEYXRhJERheSA9PSAiU2F0dXJkYXkiXSA9IDcKCiAgRGF0YSRNZWFuVGVtcCA9IChEYXRhJEhpZ2hUZW1wICsgRGF0YSRMb3dUZW1wKS8yCiAgRGF0YSRUZW1wRGlmZiA9IERhdGEkSGlnaFRlbXAgLSBEYXRhJExvd1RlbXAKICBEYXRhJERheSA9IGZhY3RvcihEYXRhJERheSwKICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiU3VuZGF5IiwgIk1vbmRheSIsICJUdWVzZGF5IiwgIldlZG5lc2RheSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUaHVyc2RheSIsICJGcmlkYXkiLCAiU2F0dXJkYXkiKSkKICAgICAgICAgICAgIyBTaW5jZSBTdW5kYXkgaXMgdGhlIGZpcnN0IGxldmVsIG9mIHRoZSBmYWN0b3IgbGlzdGVkIGhlcmUsIGl0IHdpbGwgYmUgcmVjb2duaXplZCBhcyB0aGUgYmFzZWxpbmUgYnkgUgoKIyBSZW9yZGVyIGNvbHVtbnMgZm9yIGlkZWFsIHZpc3VhbCBwZXJjZXB0aW9uCkRhdGEgPSBkYXRhLmZyYW1lKERhdGEkRGF0ZSwgRGF0YSREYXksIERhdGEkRGF5X051bSwgRGF0YSRIaWdoVGVtcCwgRGF0YSRMb3dUZW1wLCBEYXRhJE1lYW5UZW1wLCBEYXRhJFRlbXBEaWZmLCBEYXRhJFByZWNpcGl0YXRpb24sIERhdGEkTWFuaGF0dGFuLCBEYXRhJFRvdGFsKQpjb2xuYW1lcyhEYXRhKSA9IGMoIkRhdGUiLCAiRGF5IiwgIkRheV9OdW0iLCAiSGlnaFRlbXAiLCAiTG93VGVtcCIsICJNZWFuVGVtcCIsIlRlbXBEaWZmIiwgIlByZWNpcGl0YXRpb24iLCAiTWFuaGF0dGFuIiwgIlRvdGFsIikKCmdsaW1wc2UoRGF0YSkKYGBgCgojIFBvaXNzb24gUmVncmVzc2lvbiBNb2RlbGluZwpUbyBleHBsb3JlIGFueSBwb3RlbnRpYWwgYXNzb2NpYXRpb25zLCBJIGNyZWF0ZWQgUG9pc3NvbiBtb2RlbHMgb2YgdHdvIGRpZmZlcmVudCByZWdyZXNzaW9uIHR5cGVzLCBvbmUgYmVpbmcgZm9yIGNvdW50cyBhbmQgb25lIGJlaW5nIGZvciByYXRlcy4KClBvaXNzb24gY291bnRzIHJlZ3Jlc3Npb24gZXhhbWluZXMgdGhlIHRvdGFsIG51bWJlciBvZiBvY2N1cnJlbmNlcyBvZiBhIHBhcnRpY3VsYXIgZXZlbnQgKGluIHRoaXMgY2FzZSBjeWNsaXN0cyBvbiB0aGUgTWFuaGF0dGFuIEJyaWRnZSkgYW5kIHVzZXMgYSBsb2dhcml0aG1pYyBmdW5jdGlvbiB0byBkZXRlcm1pbmUgd2hpY2gsIGlmIGFueSBvZiB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGhhdmUgYSBzaWduaWZpY2FudCBlZmZlY3Qgb24gc2FpZCByZXNwb25zZSB2YXJpYWJsZSdzIG1lYW4uIFRoZSBmb3JtdWxhIGZvciBzYWlkIHJlZ3Jlc3Npb24gaXMgYmVsb3c6CgpgYGB7ciwgZWNobz1GQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiUG9pc3Nvbl9Nb2RlbF9Gb3JtLnBuZyIpCmBgYAoKLSAkXGJldGEkfjB+ID0gdGhlIGxvZyBvZiBvdXIgcmVzcG9uc2UgdmFyaWFibGUncyBtZWFuOyBub3QgdmVyeSB1c2VmdWwgZm9yIHByYWN0aWNhbCBpbnRlcnByZXRhdGlvbiAKCi0gJFxiZXRhJH4xfiwgJFxiZXRhJH4yfiwgJFxiZXRhJH4zfiwgLi4uICRcYmV0YSR+cH4gPSB0aGUgY2hhbmdlIGluIG91ciByZXNwb25zZSB2YXJpYWJsZSdzIGxvZyBtZWFuLCBpbiBhc3NvY2lhdGlvbiB3aXRoIGEgb25lIHVuaXQgaW5jcmVhc2UgaW4gc2FpZCBwcmVkaWN0b3IgdmFyaWFibGUKCiA8YnI+IAoKQWRkaXRpb25hbGx5LCBQb2lzc29uIHJhdGVzIHJlZ3Jlc3Npb24gYWltcyB0byBmaW5kIHRoZSBleHBlY3RlZCByYXRlIG9mIGEgcGFydGljdWxhciBldmVudCdzIG9jY3VycmVuY2UgcmVsYXRpdmUgdG8gdGhhdCBldmVudCdzIHByb3BvcnRpb24gd2l0aGluIGEgbGFyZ2VyICJwb3B1bGF0aW9uLiIgSW4gdGhlIGluc3RhbmNlIG9mIHRoaXMgZGF0YXNldCBhbmQgYW5hbHlzaXMsIG91ciB2YXJpYWJsZSBUb3RhbCwgd2hpY2ggcmVwcmVzZW50cyB0aGUgKip0b3RhbCoqIG51bWJlciBvZiBjeWNsaXN0cyBvbiBhbGwgdGhlIEVhc3QgUml2ZXIgQnJpZGdlcywgd2lsbCBiZSB3aGF0IHRoZSBudW1iZXIgb2YgY3ljbGlzdHMgb24gdGhlIE1hbmhhdHRhbiBCcmlkZ2UgYXJlIGNvbnNpZGVyZWQgdG8gYmUgYSBwcm9wb3J0aW9uIG9mLiBUaGUgY2FsY3VsYXRpb24gZm9yIHRoaXMgdHlwZSBvZiBQb2lzc29uIHJlZ3Jlc3Npb24gaXMgc2ltaWxhciB0byBjb3VudHMgcmVncmVzc2lvbiwgYnV0IHRoZSBsb2dhcml0aG0gb2YgdGhlIHBvcHVsYXRpb24gdmFyaWFibGUgaXMgYWxzbyBjb25zaWRlcmVkIHRvIGJlIGEgZmFjdG9yLiBUaGlzIGNhbiBiZSBleHByZXNzZWQgaW4gYm90aCBvZiB0aGUgZm9sbG93aW5nIHdheXMuCjxicj4KYGBge3IsIGVjaG89RkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoIlBvaXNzb25fRm9ybV9SYXRlczEucG5nIikKYGBgCiA8YnI+IApgYGB7ciwgZWNobz1GQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiUG9pc3Nvbl9Nb2RlbF9Gb3JtX1JhdGVzLnBuZyIpCmBgYAogPGJyPiAKIAogLSBJbiBQb2lzc29uIHJhdGVzIHJlZ3Jlc3Npb24sIHRoZSBwYXJhbWV0ZXJzICRcYmV0YSR+MH4sIC4uLi4gJFxiZXRhJH5wfiBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgaW4gdGhlIHNhbWUgbWFubmVyIGFzIHRoZXkgYXJlIGluIFBvaXNzb24gY291bnRzIG1vZGVsLgoKIyMgUG9pc3NvbiBSZWdyZXNzaW9uIChDb3VudHMpCkJlbG93IGlzIGEgc3VtbWFyeSBvZiB0aGUgUG9pc3NvbiBjb3VudHMgcmVncmVzc2lvbiBtb2RlbCBJIGNyZWF0ZWQsIHdpdGggbWVhc3VyZXMgb2YgdGVtcGVyYXR1cmUgcmFuZ2UgYW5kIGF2ZXJhZ2VzLCBwcmVjaXBpdGF0aW9uIGFtb3VudCBhbmQgZGF5IG9mIHRoZSB3ZWVrIGFsbCBmdW5jdGlvbmluZyBhcyBwcmVkaWN0b3JzIG9mIGhvdyBtYW55IGN5Y2xpc3RzIGNyb3NzZWQgdGhlIE1hbmhhdHRhbiBCcmlkZ2UgaW4gb3Igb3V0IG9mIG91ciB0aHJlZSBib3JvdWdocyBvZiBpbnRlcmVzdC4KYGBge3J9CiMgQ291bnRzIE1vZGVsOgogICMgUmVzcG9uc2UgPSBNYW5oYXR0YW4KICAjIFByZWRpY3RvcnMgPSBEYXksIE1lYW5UZW1wLCBUZW1wRGlmZiwgUHJlY2lwaXRhdGlvbgogICAgIyBEYXkgaXMgc3RvcmVkIGFzIGEgRmFjdG9yCgpDb3VudHNfTW9kZWwgPSBnbG0oTWFuaGF0dGFuIH4gRGF5ICsgTWVhblRlbXAgKyBUZW1wRGlmZiArIFByZWNpcGl0YXRpb24sIGZhbWlseSA9IHBvaXNzb24obGluayA9ICJsb2ciKSwgZGF0YSA9IERhdGEpCgpDb3VudHNfTW9kZWxfU3VtID0gc3VtbWFyeShDb3VudHNfTW9kZWwpCkNvdW50c19Nb2RlbF9Db2VmID0gQ291bnRzX01vZGVsX1N1bSRjb2VmZmljaWVudHMKCmludmlzaWJsZShDb3VudHNfTW9kZWxfQ29lZikKa2FibGUoQ291bnRzX01vZGVsX0NvZWYsIGNhcHRpb24gPSAiPGI+PGNlbnRlcj4gUG9pc3NvbiBDb3VudHMgUmVncmVzc2lvbjogV2VhdGhlciBhbmQgU2NoZWR1bGUgUmVsYXRpb25zaGlwIHdpdGggQ291bnQgb2YgTWFuaGF0dGFuIEJyaWRnZSBDeWNsaXN0cyA8L2NlbnRlcj48L2I+IikKCiMgQWxsIHByZWRpY3RvciB2YXJpYWJsZXMgYXJlIHNpZ25pZmljYW50CmBgYApJbiB0aGUgbW9kZWwsIHdlIGNhbiBzZWUgdGhhdCAqZXZlcnkqIHByZWRpY3RvciB2YXJpYWJsZSBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGFzIHBlciBwIHZhbHVlcyB3ZWxsIGJlbG93IHRoZSBzdGFuZGFyZCBvZiAwLjA1LCBzbyBubyBzdGVwd2lzZSByZWdyZXNzaW9uIG9yIG1vZGVsIHNpbXBsaWZpY2F0aW9uIGlzIG5lY2Vzc2FyeS4gCgpBcyBmb3IgdGhlIHByYWN0aWNhbCBpbXBsaWNhdGlvbnMgb2Ygb3VyIG1vZGVsIHN1bW1hcnksIHdlIGNhbiBzYXkgdGhhdCBhbHRob3VnaCBldmVyeSBwcmVkaWN0b3IgdmFyaWFibGUgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCwgdGhlIG1hZ25pdHVkZSBvZiB0aGVpciBpbXBhY3RzIGFyZSByZWxhdGl2ZWx5IHNtYWxsLiBQcmVjaXBpdGF0aW9uJ3MgZXN0aW1hdGVkIG5lZ2F0aXZlIGVmZmVjdCBvbiB0aGUgbG9nIG1lYW4gb2YgTWFuaGF0dGFuIEJyaWRnZSBjeWNsaXN0cyBoYXMgYW4gYWJzb2x1dGUgdmFsdWUgfiB8LjQzMDd8LCB3aGljaCBpcyB0aGUgdGhlIGhpZ2hlc3Qgb2YgYWxsIG91ciBwcmVkaWN0b3JzLgoKSXQgYXBwZWFycyB0aGF0IHRoZSBkYXkncyBhdmVyYWdlIHRlbXBlcmF0dXJlIGFuZCBkaWZmZXJlbmNlIGluIGRhaWx5IGhpZ2hzIGFuZCBsb3dzIHBsYXllZCB2ZXJ5IGxpdHRsZSBwcmFjdGljYWwgc2lnbmlmaWNhbmNlIGluIHRoZSBsb2cgbWVhbiBvZiB0aGF0IGRheSdzIGN5Y2xpc3RzLiBXaGVuIHdlIGxvb2sgYXQgdGhlIGRpZmZlcmVuY2UgaW4gbG9nIG1lYW5zIGZyb20gYSBkYXktb2YtdGhlLXdlZWsgcGVyc3BlY3RpdmUsIHdlIGRvIHNlZSBhIHNsaWdodGx5IG1vcmUgaW1wYWN0ZnVsIGVmZmVjdC4gV2l0aCBTdW5kYXkgYmVpbmcgY29kZWQgaW4gYXMgdGhlIGJhc2VsaW5lLCBpdCBsb29rcyBsaWtlIFdlZG5lc2RheSBoYXMgdGhlIGdyZWF0ZXN0IGFtb3VudCBvZiBjeWNsaXN0IHRyYWZmaWMgYW5kIFNhdHVyZGF5IGhhcyB0aGUgbGVhc3QuIFRoaXMgaGlnaGVyIGNvdW50IG9mIGN5Y2xpc3RzIGR1cmluZyB0aGUgd29ya3dlZWsgY291bGQgYmUgZHVlIHRvIHRoZSBNYW5oYXR0YW4gQnJpZGdlIGZ1bmN0aW9uaW5nIGZvciBtYW55IGFzIGEgY29tbXV0aW5nIG1ldGhvZC4KCkFsbCBpbiBhbGwsIG91ciBQb2lzc29uIGNvdW50cyBtb2RlbCB5aWVsZHMgc29tZSBpbnRlcmVzdGluZyBhbmQgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCByZXZlbGF0aW9ucywgbW9zdCBub3RhYmx5IHRoYXQgY3ljbGlzdHMgY2FyZSBmYXIgbW9yZSBhYm91dCBwcmVjaXBpdGF0aW9uIHRoYW4gdGhleSBkbyB0ZW1wZXJhdHVyZSBmbHVjdHVhdGlvbiwgYW5kIHRoYXQgY3ljbGlzdCB0cmFmZmljIGFwcGVhcnMgdG8gdGljayB1cHdhcmRzIHRocm91Z2hvdXQgdGhlIHdvcmt3ZWVrIGJlZm9yZSBkeWluZyBkb3duIGZvciB0aGUgd2Vla2VuZC4gSG93ZXZlciwgdGhlIHJlbGF0aXZlbHkgc21hbGwgbWFnbml0dWRlIG9mIGVhY2ggdmFyaWFibGUncyBlc3RpbWF0ZWQgZWZmZWN0IGlzIGEgZG93bnNpZGUgcmVnYXJkaW5nIHRoZSBtb2RlbCdzIHV0aWxpdHkuIAoKIyMgUG9pc3NvbiBSZWdyZXNzaW9uIChSYXRlcykKQWZ0ZXIgUG9pc3NvbiBjb3VudHMgcmVncmVzc2lvbiwgSSB0aGVuIHBlcmZvcm1lZCBQb2lzc29uIHJhdGVzIHJlZ3Jlc3Npb24gd2l0aCB0aGUgdG90YWwgbnVtYmVyIG9mIGN5Y2xpc3RzIGVudGVyaW5nIGFuZCBleGl0aW5nIG91ciB0aHJlZSBib3JvdWdocyBvZiBpbnRlcmVzdCBhY3Jvc3MgKmFsbCogdGhlIEVhc3QgUml2ZXIgQnJpZGdlcyBhcyB0aGUgInBvcHVsYXRpb24iIGZvciB3aGljaCB0aGUgTWFuaGF0dGFuIEJyaWRnZSBjeWNsaXN0cyBhcmUgYWN0aW5nIGFzIGEgc2FtcGxlIG9mLiAKClRoaXMgcHJvY2VzcyBjb25zaXN0ZWQgb2YgbWUgY3JlYXRpbmcgdHdvIGRpZmZlcmVudCBQb2lzc29uIHJhdGVzIG1vZGVscy4gVGhlIGZpcnN0IG9uZSBJIGNyZWF0ZWQgbGlzdGVkIGJvdGggdGVtcGVyYXR1cmUgdmFyaWFibGVzIGFzIHN0YXRpc3RpY2FsbHkgaW5zaWduaWZpY2FudC4gR2l2ZW4gdGhlaXIgc3RhdHVzIGFzIHN0YXRpc3RpY2FsbHkgaW5zaWduaWZpY2FudCBpbiB0aGlzIG1vZGVsLCBhbmQgdGhlaXIgbWludXRlIHByYWN0aWNhbCBzaWduaWZpY2FuY2UgaW4gdGhlIHByZXZpb3VzIGNvdW50cyBtb2RlbCwgSSBjaG9zZSB0byByZW1vdmUgdGhlbSBhbmQgY3JlYXRlIGEgc2Vjb25kIFBvaXNzb24gcmF0ZXMgbW9kZWwgd2hpY2ggZGlkIG5vdCBmYWN0b3IgaW4gdGhlIGRheSdzIGF2ZXJhZ2Ugb3IgcmFuZ2Ugb2YgdGVtcGVyYXR1cmUuCmBgYHtyfQojIyMgUmF0ZXMgTW9kZWwgMQpSYXRlc19Nb2RlbCA9IGdsbShNYW5oYXR0YW4gfiBEYXkgKyBNZWFuVGVtcCArIFRlbXBEaWZmICsgUHJlY2lwaXRhdGlvbiwgb2Zmc2V0ID0gbG9nKFRvdGFsKSwgZmFtaWx5ID0gcG9pc3NvbihsaW5rID0gImxvZyIpLCBkYXRhID0gRGF0YSkKClJhdGVzX01vZGVsX1N1bSA9IHN1bW1hcnkoUmF0ZXNfTW9kZWwpClJhdGVzX01vZGVsX0NvZWYgPSBSYXRlc19Nb2RlbF9TdW0kY29lZmZpY2llbnRzCgppbnZpc2libGUoUmF0ZXNfTW9kZWxfQ29lZikKa2FibGUoUmF0ZXNfTW9kZWxfQ29lZiwgY2FwdGlvbiA9ICI8Yj48Y2VudGVyPiBQb2lzc29uIFJhdGVzIFJlZ3Jlc3Npb24gKDEpOiBXZWF0aGVyIGFuZCBTY2hlZHVsZSBSZWxhdGlvbnNoaXAgd2l0aCBDb3VudCBvZiBNYW5oYXR0YW4gQnJpZGdlIEN5Y2xpc3RzIDwvY2VudGVyPjwvYj4iKQoKCiMjIyBSYXRlcyBNb2RlbCAyClJhdGVzX01vZGVsMiA9IGdsbShNYW5oYXR0YW4gfiBEYXkgKyBQcmVjaXBpdGF0aW9uLCBvZmZzZXQgPSBsb2coVG90YWwpLCBmYW1pbHkgPSBwb2lzc29uKGxpbmsgPSAibG9nIiksIGRhdGEgPSBEYXRhKQoKUmF0ZXNfTW9kZWwyX1N1bSA9IHN1bW1hcnkoUmF0ZXNfTW9kZWwyKQpSYXRlc19Nb2RlbDJfQ29lZiA9IFJhdGVzX01vZGVsMl9TdW0kY29lZmZpY2llbnRzCgppbnZpc2libGUoUmF0ZXNfTW9kZWxfQ29lZikKa2FibGUoUmF0ZXNfTW9kZWwyX0NvZWYsIGNhcHRpb24gPSAiPGI+PGNlbnRlcj4gUG9pc3NvbiBSYXRlcyBSZWdyZXNzaW9uICgyKTogUHJlY2lwaXRhdGlvbiBhbmQgU2NoZWR1bGUgUmVsYXRpb25zaGlwIHdpdGggQ291bnQgb2YgTWFuaGF0dGFuIEJyaWRnZSBDeWNsaXN0cyA8L2NlbnRlcj48L2I+IikKCmBgYApMb29raW5nIGF0IHRoZSBmaW5kaW5ncyBvZiBvdXIgc2Vjb25kIFBvaXNzb24gcmF0ZXMgcmVncmVzc2lvbiBtb2RlbCwgd2Ugc2VlIGEgdHJlbmQgc2ltaWxhciB0byB0aGF0IG9mIG91ciBQb2lzc29uIGNvdW50cyByZWdyZXNzaW9uIG1vZGVsLCB0aGF0IGJlaW5nIGEgY29tbW9uIG9jY3VycmVuY2Ugb2Ygc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIGJ1dCBub3QgYSBncmVhdCBkZWFsIG9mIHByYWN0aWNhbCBzaWduaWZpY2FuY2Ugb24gZGlzcGxheSB3aGVuIHRoZSBtYWduaXR1ZGUgb2YgdGhlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnQgaXMgdGFrZW4gaW50byBjb25zaWRlcmF0aW9uLgoKT25jZSBhZ2FpbiB0cmVhdGluZyBTdW5kYXkgYXMgb3VyIGJhc2VsaW5lLCBpdCBsb29rcyBsaWtlIHRoZSByYXRlIG9mIE1hbmhhdHRhbiBCcmlkZ2UgY3ljbGlzdHMgaW4gcHJvcG9ydGlvbiB0byB0aGUgZW50aXJldHkgb2YgRWFzdCBSaXZlciBCcmlkZ2UgY3ljbGlzdHMgaXMgYXQgaXRzIGhpZ2hlc3QgZWFybHkgaW4gdGhlIHdlZWssIHdpdGggdGhhdCByYXRlIGRlY2xpbmluZyBnb2luZyBpbnRvIHRoZSB3ZWVrZW5kLiBUaGF0IGJlaW5nIHNhaWQsIHRoZSBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2Ugb2YgdGhpcyBicmVha2Rvd24gYWxzbyBncmVhdGx5IGRlY3JlYXNlcyB3aGVuIHdlIGxvb2sgYXQgdGhlIGRhdGEgZm9yIFRodXJzZGF5IGFuZCB0byBhIG11Y2ggbGVzc2VyIGJ1dCBzdGlsbCBub3RpY2VhYmxlIGV4dGVudCBGcmlkYXksIHBlcmhhcHMgc3VnZ2VzdGluZyB0aGF0IHRoZSBNYW5oYXR0YW4gQnJpZGdlIGN5Y2xpc3QgcmF0ZSdzIGRlY2xpbmUgYXQgdGhlIHRhaWwgZW5kIG9mIHRoZSB3b3Jrd2VlayBjb3VsZCBiZSBjaGFsa2VkIHVwIHRvIHJhbmRvbSBjaGFuY2UgYW5kIG5vdCBhIHBhcnRpY3VsYXIgY2hhcmFjdGVyaXN0aWMgb2YgdGhlIEJyaWRnZSB0aGF0IGFmZmVjdHMgdGhlIGV4cGVyaWVuY2Ugb2YgaXRzIGN5Y2xpc3RzIG9ubHkgb24gdGhvc2UgcGFydGljdWxhciBkYXlzLgoKIyMgRGF5IG9mIHRoZSBXZWVrIEF2ZXJhZ2VzClNpbmNlIGJvdGggb3VyIGNvdW50cyBhbmQgcmF0ZXMgbW9kZWxzIHN1Z2dlc3RlZCB0aGF0IHRoZSBkYXkgb2YgdGhlIHdlZWsgaGFzIHRoZSBncmVhdGVzdCBhc3NvY2lhdGlvbiB3aXRoIHRoZSBsb2cgbWVhbiBvZiB0aGUgTWFuaGF0dGFuIEJyaWRnZSdzIGN5Y2xpc3RzLCBJIGRlY2lkZWQgdG8gY2FsY3VsYXRlIHRoZSBhdmVyYWdlIGNvdW50cyBhbmQgcmF0ZXMgcGVyIGRheSB0byBjb21wYXJlIHRoZW0gdG8gZWFjaCBvdGhlciBhbmQgdGhlIG1lYW4gYWNyb3NzIGFsbCBkYXlzIGNvbnNpZGVyZWQuIFRoZSB0YWJsZSB3aXRoIHRoaXMgaW5mb3JtYXRpb24gaXMgYmVsb3cuCmBgYHtyfQpDb3VudF9BdmVyYWdlcyA9IGMoCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbikpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlN1bmRheSJdKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiTW9uZGF5Il0pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJUdWVzZGF5Il0pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJXZWRuZXNkYXkiXSkpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlRodXJzZGF5Il0pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJGcmlkYXkiXSkpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlNhdHVyZGF5Il0pKQopCgpBbGxEYXlzX1JhdGVzX0F2ZyA9IHN1bShEYXRhJE1hbmhhdHRhbikvc3VtKERhdGEkVG90YWwpCgpTdW5fUmF0ZXNfQXZnID0gc3VtKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJTdW5kYXkiXSkvc3VtKERhdGEkVG90YWxbRGF0YSREYXkgPT0gIlN1bmRheSJdKQoKTW9uX1JhdGVzX0F2ZyA9IHN1bShEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiTW9uZGF5Il0pL3N1bShEYXRhJFRvdGFsW0RhdGEkRGF5ID09ICJNb25kYXkiXSkKClR1ZXNfUmF0ZXNfQXZnID0gc3VtKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJUdWVzZGF5Il0pL3N1bShEYXRhJFRvdGFsW0RhdGEkRGF5ID09ICJUdWVzZGF5Il0pCgpXZWRfUmF0ZXNfQXZnID0gc3VtKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJXZWRuZXNkYXkiXSkvc3VtKERhdGEkVG90YWxbRGF0YSREYXkgPT0gIldlZG5lc2RheSJdKQoKVGh1cl9SYXRlc19BdmcgPSBzdW0oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlRodXJzZGF5Il0pL3N1bShEYXRhJFRvdGFsW0RhdGEkRGF5ID09ICJUaHVyc2RheSJdKQoKRnJpX1JhdGVzX0F2ZyA9IHN1bShEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiRnJpZGF5Il0pL3N1bShEYXRhJFRvdGFsW0RhdGEkRGF5ID09ICJGcmlkYXkiXSkKClNhdF9SYXRlc19BdmcgPSBzdW0oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlNhdHVyZGF5Il0pL3N1bShEYXRhJFRvdGFsW0RhdGEkRGF5ID09ICJTYXR1cmRheSJdKQoKRGF5X1JhdGVzX0F2ZXJhZ2VzID0gYyhBbGxEYXlzX1JhdGVzX0F2ZywgU3VuX1JhdGVzX0F2ZywgTW9uX1JhdGVzX0F2ZywgVHVlc19SYXRlc19BdmcsIFdlZF9SYXRlc19BdmcsIFRodXJfUmF0ZXNfQXZnLCBGcmlfUmF0ZXNfQXZnLCBTYXRfUmF0ZXNfQXZnKQoKUmF0ZV9BdmVyYWdlcyA9IHJvdW5kKERheV9SYXRlc19BdmVyYWdlcywgZGlnaXRzID0gNCkKCkRheXMgPSBjKCJBbGwgRGF5cyIsICJTdW5kYXkiLCAiTW9uZGF5IiwgIlR1ZXNkYXkiLCAiV2VkbmVzZGF5IiwgIlRodXJzZGF5IiwgIkZyaWRheSIsICJTYXR1cmRheSIpCgpDb3VudHNfRGlmZmVyZW5jZSA9IGMoCiAgMCwgIyBEaWZmZXJlbmNlIGJldHdlZW4gdGhlIGF2ZXJhZ2UgY291bnQgb2YgYWxsIGRheXMgYW5kIGl0c2VsZgogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlN1bmRheSJdKSkgLSByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiTW9uZGF5Il0pKSAtIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW4pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJUdWVzZGF5Il0pKSAtIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW4pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJXZWRuZXNkYXkiXSkpIC0gcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbikpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlRodXJzZGF5Il0pKSAtIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW4pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJGcmlkYXkiXSkpIC0gcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbikpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlNhdHVyZGF5Il0pKSAtIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW4pKQopCgpSYXRlc19EaWZmZXJlbmNlQiA9IGMoCiAgMCwKICBTdW5fUmF0ZXNfQXZnIC0gQWxsRGF5c19SYXRlc19BdmcsCiAgTW9uX1JhdGVzX0F2ZyAtIEFsbERheXNfUmF0ZXNfQXZnLAogIFR1ZXNfUmF0ZXNfQXZnIC0gQWxsRGF5c19SYXRlc19BdmcsCiAgV2VkX1JhdGVzX0F2ZyAtIEFsbERheXNfUmF0ZXNfQXZnLAogIFRodXJfUmF0ZXNfQXZnIC0gQWxsRGF5c19SYXRlc19BdmcsCiAgRnJpX1JhdGVzX0F2ZyAtIEFsbERheXNfUmF0ZXNfQXZnLAogIFNhdF9SYXRlc19BdmcgLSBBbGxEYXlzX1JhdGVzX0F2ZwopCgpSYXRlc19EaWZmZXJlbmNlID0gcm91bmQoUmF0ZXNfRGlmZmVyZW5jZUIsIGRpZ2l0cyA9IDQpCgpUYWJsZSA9IGNiaW5kKERheXMsIENvdW50X0F2ZXJhZ2VzLCBDb3VudHNfRGlmZmVyZW5jZSwgUmF0ZV9BdmVyYWdlcywgUmF0ZXNfRGlmZmVyZW5jZSkKCmthYmxlKFRhYmxlLCBjYXB0aW9uID0gIjxiPjxjZW50ZXI+PHNwYW4gc3R5bGU9J2NvbG9yOiMwMDAwMDA7Jz5EaXN0cmlidXRpb24gb2YgTWFuaGF0dGFuIEJyaWRnZSBDeWNsaXN0IENvdW50IGFuZCBSYXRlcyBKdWx5IDIwMTc8L2NlbnRlcj48L2I+IikgJT4lCiAga2FibGVfc3R5bGluZygKICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIpLAogICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgcG9zaXRpb24gPSAiY2VudGVyIgogICkKCmBgYAoKVGhlIHRhYmxlIHByb3ZpZGVzIGdyZWF0ZXIgZGV0YWlsIGludG8gdGhlIGltcGxpY2F0aW9ucyBvZiBvdXIgUG9pc3NvbiBjb3VudCBhbmQgcmF0ZSBtb2RlbHMuIFRoYXQgYmVpbmcgd2Vla2RheSB0b3RhbHMgb2YgTWFuaGF0dGFuIEJyaWRnZSBjeWNsaXN0cyAoc3BlY2lmaWNhbGx5IE1vbmRheSAtIFRodXJzZGF5KSBmYXIgb3V0d2VpZ2ggdGhlIGNvdW50IG9mIGN5Y2xpc3RzIG9uIHRoZSBicmlkZ2UgZnJvbSBGcmlkYXkgdG8gU3VuZGF5LiBXaXRoIHRoZSBhdmVyYWdlIG51bWJlciBvZiBjeWxjbGlzdHMgZnJvbSBNb25kYXkgLSBUaHVyc2RheSBiZWluZyBhYm91dCA2LDMyNSwgYW5kIHRoZSBhdmVyYWdlIG51bWJlciBGcmlkYXkgLSBTdW5kYXkgYmVpbmcgYWJvdXQgNCwzNTMuCgpBcyBmb3IgdGhlIHJhdGUgb2YgTWFuaGF0dGFuIEJyaWRnZSBjeWNsaXN0cyByZWxhdGl2ZSB0byBjeWNsaXN0cyBvbiBhbGwgRWFzdCBSaXZlciBCcmlkZ2VzLCB3ZSBzZWUgdGhhdCB0aGUgTWFuaGF0dGFuIEJyaWRnZSdzIGN5Y2xpc3QgcmF0ZSBpcyBzbGlnaHRseSBhYm92ZSBhdmVyYWdlIE1vbmRheSAtIFdlZG5lc2RheSwgYnV0IHRoZW4gYmVsb3cgYXZlcmFnZSBUaHVyc2RheSB0aHJvdWdoIFN1bmRheS4KCgojIyBQb2lzc29uIE1vZGVsaW5nIFRha2Vhd2F5cwpUbyBjb25jbHVkZSwgYW55IGltcGxlbWVudGF0aW9ucyBkb25lIGluIHJlc3BvbnNlIHRvIG91ciBQb2lzc29uIG1vZGVscycgZmluZGluZ3Mgc2hvdWxkIGJlIGRvbmUgd2l0aCBzb21lIGRlZ3JlZSBvZiBjYXV0aW9uIGR1ZSB0byB0aGUgbG93IHByYWN0aWNhbCBzaWduaWZpY2FuY2UgZm91bmQgaW4gYm90aCBvdXIgY291bnQgYW5kIHJhdGUgbW9kZWxzLiBUaGF0IGJlaW5nIHNhaWQsIHRoZXJlIGFyZSBzdGlsbCB2YWx1YWJsZSB0YWtlYXdheXMgdGhhdCB3ZSBjYW4gZHJhdyBmcm9tIG91ciBhbmFseXNpcy4gCgpGaXJzdCwgdGhlIE1hbmhhdHRhbiBCcmlkZ2UgaXMgY2xlYXJseSBidXNpZXIsIGJvdGggaW4gdGhlIHNlbnNlIG9mIHJhdyB2b2x1bWUgYW5kIGFzIGEgcHJvcG9ydGlvbiBvZiB0aGUgb3ZlcmFsbCBFYXN0IFJpdmVyIEJyaWRnZSBuZXR3b3JrLCBlYXJseSBhbmQgdGhyb3VnaG91dCB0aGUgc3RhbmRhcmQgd29ya3dlZWsgdGhhbiBpdCBpcyBkdXJpbmcgdGhlIHdlZWtlbmQuIFNlY29uZCwgdGhlIGRhaWx5IGF2ZXJhZ2UgdGVtcGVyYXR1cmUgYXMgd2VsbCBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoYXQgZGF5J3MgaGlnaCBhbmQgbG93IHBsYXllZCB2ZXJ5IGxpdHRsZSBpZiBhbnkgcm9sZSBpbiB0aGUgY291bnQgb3IgcmF0ZSBvZiBjeWNsaXN0cyBvbiBhbnkgZ2l2ZW4gZGF5LCBidXQgdGhlIG1lYXN1cmUgb2YgcHJlY2lwaXRhdGlvbiBkb2VzIGFwcGVhciB0byBoYXZlIGEgcmVsYXRpdmVseSBub3RpY2VhYmxlIGFuZCBuZWdhdGl2ZSBhc3NvY2lhdGlvbiB3aXRoIHRoZSBudW1iZXIgb2YgdGhhdCBkYXkncyBjeWNsaXN0cyBvbiB0aGUgTWFuaGF0dGFuIEJyaWRnZS4KCiMgUXVhc2ktUG9pc3NvbiBSZWdyZXNzaW9uIE1vZGVsaW5nCkluIGFkZGl0aW9uIHRvIGFuYWx5emluZyBvdXIgZGF0YSBhdCBoYW5kIHZpYSBQb2lzc29uIHJlZ3Jlc3Npb24sIEkgZGVjaWRlZCB0byBhbHNvIGNyZWF0ZSBhIHF1YXNpLVBvaXNzb24gbW9kZWwgb2YgdGhlIGRhdGEuIFF1YXNpLVBvaXNzb24gbW9kZWxpbmcgaXMgYW4gYWx0ZXJuYXRpdmUgdG8gUG9pc3NvbiBtb2RlbGluZywgYW5kIGl0IGlzIHBhcnRpY3VsYXJseSB2YWx1YWJsZSB3aGVuIHRoZSBtZWFuIGFuZCB2YXJpYW5jZSBvZiB0aGUgbW9kZWwncyByZXNwb25zZSB2YXJpYWJsZSAobnVtYmVyIG9mIGN5Y2xpc3RzIG9uIHRoZSBNYW5oYXR0YW4gYnJpZGdlIGluIHRoaXMgY2FzZSkgYXJlIG5vdCBhcHByb3hpbWF0ZWx5IGVxdWFsIHRvIG9uZSBhbm90aGVyIChrbm93biBhcyBkaXNwZXJzaW9uKS4KCkZvciBteSBxdWFzaS1Qb2lzc29uIG1vZGVsLCBJIGluY2x1ZGVkIHRoYXQgZGF5J3MgYXZlcmFnZSB0ZW1wZXJhdHVyZSwgZGF5IG9mIHRoZSB3ZWVrIGFuZCBwcmVjaXBpdGF0aW9uIGFtb3VudCBhcyB0aGUgcmVsZXZhbnQgZmFjdG9ycy4gRGF5IG9mIHRoZSB3ZWVrIG9idmlvdXNseSBwbGF5ZWQgdGhlIGJpZ2dlc3Qgcm9sZSBpbiBvdXIgcHJldmlvdXMgUG9pc3NvbiBtb2RlbHMsIHdpdGggcHJlY2lwaXRhdGlvbiBjb25zaXN0ZW50bHkgYmVpbmcgY2l0ZWQgYXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkZXNwaXRlIHJlbGF0aXZlbHkgbG93IHByYWN0aWNhbCBzaWduaWZpY2FuY2UuIEZvciB0aGlzIG1vZGVsLCBJIGNob3NlIHRvIGRpc2NyZXRpemUgcHJlY2lwaXRhdGlvbiwgd2l0aCBkYXlzIG9mIG5vIHJlY29yZGVkIHJhaW4gYmVpbmcgbWFya2VkIGFzICIwIiBhbmQgZGF5cyB3aXRoICphbnkqIGFtb3VudCBvZiByYWluIGJlaW5nIG1hcmtlZCBhcyAiMS4iIApgYGB7ciwgUXVhc2ktUG9pc3NvbiBNb2RlbH0KRGF0YSROZXdQcmVjaXAgPSBEYXRhJFByZWNpcGl0YXRpb24KRGF0YSROZXdQcmVjaXBbRGF0YSRQcmVjaXBpdGF0aW9uID09IDBdID0gMApEYXRhJE5ld1ByZWNpcFtEYXRhJFByZWNpcGl0YXRpb24gPiAwXSA9IDEKCkRhdGEgPSBkYXRhLmZyYW1lKERhdGEkRGF0ZSwgRGF0YSREYXksIERhdGEkRGF5X051bSwgRGF0YSRIaWdoVGVtcCwgRGF0YSRMb3dUZW1wLCBEYXRhJE1lYW5UZW1wLCBEYXRhJFRlbXBEaWZmLCBEYXRhJFByZWNpcGl0YXRpb24sIERhdGEkTmV3UHJlY2lwLCBEYXRhJE1hbmhhdHRhbiwgRGF0YSRUb3RhbCkKY29sbmFtZXMoRGF0YSkgPSBjKCJEYXRlIiwgIkRheSIsICJEYXlfTnVtIiwgIkhpZ2hUZW1wIiwgIkxvd1RlbXAiLCAiTWVhblRlbXAiLCJUZW1wRGlmZiIsICJQcmVjaXBpdGF0aW9uIiwgIk5ld1ByZWNpcCIsIk1hbmhhdHRhbiIsICJUb3RhbCIpCgoKIyAxLikgQmVsb3cgaXMgdGhlIHF1YXNpLVBvaXNzb24gcmVncmVzc2lvbiBtb2RlbAogICMgQXMgaW5zdHJ1Y3RlZCwgb25seSBpbmNsdWRlcyBEYXksIE1lYW5UZW1wIGFuZCBOZXdQcmVjaXAKClF1YXNpX0NvdW50c19Nb2RlbCA9IGdsbShNYW5oYXR0YW4gfiBEYXkgKyBNZWFuVGVtcCArIE5ld1ByZWNpcCwgZmFtaWx5ID0gcXVhc2lwb2lzc29uLCBkYXRhID0gRGF0YSkKICAKUXVhc2lfQ291bnRzX01vZGVsX1N1bSA9IHN1bW1hcnkoUXVhc2lfQ291bnRzX01vZGVsKQpRdWFzaV9Db3VudHNfTW9kZWxfQ29lZiA9IFF1YXNpX0NvdW50c19Nb2RlbF9TdW0kY29lZmZpY2llbnRzCgppbnZpc2libGUoUXVhc2lfQ291bnRzX01vZGVsX0NvZWYpCmthYmxlKFF1YXNpX0NvdW50c19Nb2RlbF9Db2VmLCBjYXB0aW9uID0gIjxiPjxjZW50ZXI+IFF1YXNpLVBvaXNzb24gQ291bnRzIFJlZ3Jlc3Npb246IFdlYXRoZXIgYW5kIFNjaGVkdWxlIFJlbGF0aW9uc2hpcCB3aXRoIENvdW50IG9mIE1hbmhhdHRhbiBCcmlkZ2UgQ3ljbGlzdHMgPC9jZW50ZXI+PC9iPiIpCiAgCmBgYAoKQSBzdW1tYXJ5IG9mIHRoZSBxdWFzaS1Qb2lzc29uIGNvdW50cyBtb2RlbCBjYW4gYmUgc2VlbiBhYm92ZS4gV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGlzIGdyZWF0IHNpbWlsYXJpdHkgYmV0d2VlbiB0aGUgZmluZGluZ3Mgb2YgdGhpcyBtb2RlbCBhbmQgb3VyIG9yaWdpbmFsIFBvaXNzb24gY291bnRzIG1vZGVsLiBIb3dldmVyIGJlZm9yZSB3ZSBjYW4gZGV0ZXJtaW5lIHdoaWNoIG9uZSBpcyBzdXBlcmlvciBmb3IgaW50ZXJwcmV0YXRpdmUgdXNlLCB3ZSBtdXN0IGNhbGN1bGF0ZSB0aGlzIHF1YXNpLVBvaXNzb24ncyBkaXNwZXJzaW9uIHBhcmFtZXRlciwgInBoaSBoYXQiICgkXGhhdHtccGhpfSQpLgoKIyMgRGlzcGVyc2lvbiBhbmQgQ291bnRzIE1vZGVsIFNlbGVjdGlvbgoKJFxoYXR7XHBoaX0kIGlzIHVzZWQgaW4gcXVhc2ktUG9pc3NvbiByZWdyZXNzaW9uIHRvIGRldGVybWluZSBpZiBvdXIgZGF0YSdzIHJlc3BvbnNlIHZhcmlhYmxlIGlzIG92ZXJseSBvciB1bmRlcmx5IGRpc3BlcnNlZC4gR2VuZXJhbGx5LCBhIHBoaSBoYXQgdmFsdWUgb2YgYXJvdW5kIDEgaXMgcmVwcmVzZW50YXRpdmUgb2YgYW4gYXBwcm94aW1hdGVseSBlcXVhbCBtZWFuIGFuZCB2YXJpYW5jZSBvZiB0aGUgcmVzcG9uc2UuIElmIGEgcXVhc2ktUG9pc3NvbiBtb2RlbCdzIGRpc3BlcnNpb24gdmFsdWUgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgdGhhbiAxLCB0aGVuIHRoYXQgbW9kZWwgc2hvdWxkIGJlIHVzZWQgZm9yIGFzc29jaWF0aXZlIGFuYWx5c2lzIHJhdGhlciB0aGFuIGEgdHJhZGl0aW9uYWwgUG9pc3NvbiBjb3VudGVycGFydCwgYXMgdGhlIHF1YXNpLVBvaXNzb24gY2FsY3VsYXRpb24gaW5jbHVkZXMgZ3JlYXRlciBlc3RpbWF0aW9uIG9mIHN0YW5kYXJkIGVycm9ycy4gSG93ZXZlciwgaWYgJFxoYXR7XHBoaX0kIH4gMSwgdGhlbiB0aGUgdHJhZGl0aW9uYWwgUG9pc3NvbiBtb2RlbCBzaG91bGQgYmUgdXNlZCwgYXMgaXQgaXMgbGVzcyBjb21wdXRhdGlvbmFsbHkgaW50ZW5zaXZlIGFuZCBhdm9pZHMgb3RoZXJ3aXNlIHVubmVjZXNzYXJ5IGV4dHJhIHN0ZXBzLiBUaGUgZm9ybXVsYSBmb3IgJFxoYXR7XHBoaX0kJ3MgY2FsY3VsYXRpb24gY2FuIGJlIHNlZW4gYmVsb3cuCgpgYGB7ciwgIGZpZy5hbGlnbj0iY2VudGVyIiwgZWNobz1GQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiRGlzcGVyc2lvbl9QYXJhbWV0ZXIucG5nIikKYGBgCgpgYGB7ciBEaXNwZXJzaW9uIFBhcmFtZXRlcn0KbiA9IG5yb3coRGF0YSkKcCA9IDMKUGVhcnNvbl9SZXNpZHVhbHMgPSByZXNpZHVhbHMoUXVhc2lfQ291bnRzX01vZGVsLCB0eXBlID0gInBlYXJzb24iKQpTcV9QZWFyc29uX1Jlc2lkdWFscyA9IFBlYXJzb25fUmVzaWR1YWxzXjIKRGlzcGVyc2lvbl9QYXJhbWV0ZXIgPSAoc3VtKFNxX1BlYXJzb25fUmVzaWR1YWxzKSkvKG4tcCkKCiMjIyMgRG91YmxlIGNoZWNrZWQgcGhpJ3MgdmFsdWUgdXNpbmcgUHJvZidzIGNvZGluZyBtZXRob2Q7IGdvdCBzYW1lIHJlc3VsdAogIHlkaWY9RGF0YSRNYW5oYXR0YW4tZXhwKFF1YXNpX0NvdW50c19Nb2RlbCRsaW5lYXIucHJlZGljdG9ycykgICMgZGlmZiBiZXR3ZWVuIHkgYW5kIHloYXQKICBwcnNkID0geWRpZi9zcXJ0KGV4cChRdWFzaV9Db3VudHNfTW9kZWwkbGluZWFyLnByZWRpY3RvcnMpKSAgICMgUGVhcnNvbiByZXNpZHVhbHMKICBwaGlfY2hlY2sgPSBzdW0ocHJzZF4yKS8obi1wKQojIyMjIAogIAppbnZpc2libGUoRGlzcGVyc2lvbl9QYXJhbWV0ZXIpCmludmlzaWJsZShwaGlfY2hlY2spCmBgYAoKT3VyIG1vZGVsIHlpZWxkZWQgYSB2YWx1ZSBvZiAkXGhhdHtccGhpfSQgfiAxNDIsIHdoaWNoIGlzICoqd2VsbCoqIGJleW9uZCB0aGUgbWFyZ2luIG9mIGVycm9yIGZvciBhIHByb3Blcmx5IGRpc3BlcnNlZCBQb2lzc29uIHJlc3BvbnNlIHZhcmlhYmxlLiBGb3IgdGhpcyByZWFzb24sIHdlIGNhbiBkZWVtIHRoYXQgdGhlIHF1YXNpLVBvaXNzb24gY291bnRzIG1vZGVsIGlzIG1vcmUgdmFsdWFibGUgZm9yIGFzc29jaWF0aXZlIGFuYWx5c2lzIHRoYW4gdGhlIFBvaXNzb24gY291bnRzIG1vZGVsLiBCZWNhdXNlIG9mIHRoaXMsIHdlIHdpbGwgdXNlIHRoZSBxdWFzaS1Qb2lzc29uIGZvciBvdXIgdWx0aW1hdGUgaW50ZXJwcmV0YXRpb25zLgoKIyMgVmlzdWFsIEFpZHMKUmVmZXJyaW5nIHRvIG91ciBxdWFzaS1Qb2lzc29uIG1vZGVsIHN1bW1hcnkgYWJvdmUsIHdlIHNlZSB0aGF0IHRoZSBkYXkncyBhdmVyYWdlIHRlbXBlcmF0dXJlIGRvZXMgbm90IGFwcGVhciB0byBoYXZlIHNpZ25pZmljYW50IHN0YXRpc3RpY2FsIG9yIHByYWN0aWNhbCBhc3NvY2lhdGlvbiB3aXRoIHRoZSBNYW5oYXR0YW4gYnJpZGdlJ3MgbnVtYmVyIG9mIGN5Y2xpc3RzLiBIb3dldmVyLCB0aGVyZSBkb2VzIGFwcGVhciB0byBiZSBzdWNoIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBudW1iZXIgb2YgY3ljbGlzdHMgb24gYSB0b3RhbGx5IGNsZWFyIGRheSBhcyBvcHBvc2VkIHRvIGEgZGF5IHdpdGggYXQgbGVhc3QgKnNvbWUqIGxldmVsIG9mIHByZWNpcGl0YXRpb24gKHJlY29yZGVkIHZpYSB2YXJpYWJsZSBOZXdQcmVjaXApLiBBbmQsIGFzIGNvbnNpc3RlbnRseSBzZWVuIGluIG91ciBvcmlnaW5hbCBQb2lzc29uIHJlZ3Jlc3Npb24gbW9kZWxzLCB0aGVyZSBpcyBjZXJ0YWlubHkgYSBsYXJnZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR5cGljYWwgbnVtYmVyIG9mIGN5Y2xpc3RzIGRlcGVuZGluZyBvbiB0aGUgZGF5IG9mIHRoZSB3ZWVrLgoKS25vd2luZyB0aGlzLCBJIGNyZWF0ZWQgdHdvIHZpc3VhbHMgYmVsb3cgdG8gZW5oYW5jZSBvdXIgZ3Jhc3Agb2YgdGhlIHJlbGF0aW9uc2hpcCB0aGF0IGJvdGggdGhlIGRheSBvZiB0aGUgd2VlayBhbmQgdGhlIHByZXNlbmNlIG9mIHByZWNpcGl0YXRpb24gaGF2ZSB3aXRoIGVhY2ggb3RoZXIgYXMgd2VsbCBhcyB0aGUgc3RhbmRhcmQgbnVtYmVyIG9mIGN5Y2xpc3RzIHRoYXQgd2VyZSBvbiB0aGUgTWFuaGF0dGFuIEJyaWRnZSB0aHJvdWdob3V0IEp1bHkgMjAxNy4gVW5mb3J0dW5hdGVseSwgdGhlcmUgd2VyZSBubyBpbnN0YW5jZXMgb2YgVHVlc2RheXMgb3IgV2VkbmVzZGF5cyB3aXRoIHByZWNpcGl0YXRpb24gaW4gdGhpcyBzdHVkeSwgcmVzdWx0aW5nIGluIGEgYmxhbmsgaW4gYm90aCBvdXIgdGFibGUgYW5kIGJhciBjaGFydCBiZWxvdy4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02fQojIyMjIFRhYmxlCkRheXMgPSBjKCJBbGwgRGF5cyIsICJTdW5kYXkiLCAiTW9uZGF5IiwgIlR1ZXNkYXkiLCAiV2VkbmVzZGF5IiwgIlRodXJzZGF5IiwgIkZyaWRheSIsICJTYXR1cmRheSIpCgpOb19QcmVjaXBpdGF0aW9uID0gYygKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkTmV3UHJlY2lwID09IDBdKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJE5ld1ByZWNpcCA9PSAwICYgRGF0YSREYXkgPT0gIlN1bmRheSJdKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJE5ld1ByZWNpcCA9PSAwICYgRGF0YSREYXkgPT0gIk1vbmRheSJdKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJE5ld1ByZWNpcCA9PSAwICYgRGF0YSREYXkgPT0gIlR1ZXNkYXkiXSkpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSROZXdQcmVjaXAgPT0gMCAmIERhdGEkRGF5ID09ICJXZWRuZXNkYXkiXSkpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSROZXdQcmVjaXAgPT0gMCAmIERhdGEkRGF5ID09ICJUaHVyc2RheSJdKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJE5ld1ByZWNpcCA9PSAwICYgRGF0YSREYXkgPT0gIkZyaWRheSJdKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJE5ld1ByZWNpcCA9PSAwICYgRGF0YSREYXkgPT0gIlNhdHVyZGF5Il0pKQopCgpTb21lX1ByZWNpcGl0YXRpb24gPSBjKAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSROZXdQcmVjaXAgPT0gMV0pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkTmV3UHJlY2lwID09IDEgJiBEYXRhJERheSA9PSAiU3VuZGF5Il0pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkTmV3UHJlY2lwID09IDEgJiBEYXRhJERheSA9PSAiTW9uZGF5Il0pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkTmV3UHJlY2lwID09IDEgJiBEYXRhJERheSA9PSAiVHVlc2RheSJdKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJE5ld1ByZWNpcCA9PSAxICYgRGF0YSREYXkgPT0gIldlZG5lc2RheSJdKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJE5ld1ByZWNpcCA9PSAxICYgRGF0YSREYXkgPT0gIlRodXJzZGF5Il0pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkTmV3UHJlY2lwID09IDEgJiBEYXRhJERheSA9PSAiRnJpZGF5Il0pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkTmV3UHJlY2lwID09IDEgJiBEYXRhJERheSA9PSAiU2F0dXJkYXkiXSkpCikKClZpc19UYWJsZSA9IGRhdGEuZnJhbWUoRGF5cywgTm9fUHJlY2lwaXRhdGlvbiwgU29tZV9QcmVjaXBpdGF0aW9uKQoKa2FibGUoVmlzX1RhYmxlLCBjYXB0aW9uID0gIjxiPjxjZW50ZXI+PHNwYW4gc3R5bGU9J2NvbG9yOiMwMDAwMDA7Jz5BdmVyYWdlIEN5Y2xpc3QgQ291bnRzIG9uIHRoZSBNYW5oYXR0YW4gQnJpZGdlIEp1bHkgMjAxNzwvY2VudGVyPjwvYj4iKSAlPiUKICBrYWJsZV9zdHlsaW5nKAogICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiksCiAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICBwb3NpdGlvbiA9ICJjZW50ZXIiKQoKIyMjIyBCYXJjaGFydApWaXNfbG9uZyA9CiAgVmlzX1RhYmxlICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSBjKE5vX1ByZWNpcGl0YXRpb24sIFNvbWVfUHJlY2lwaXRhdGlvbiksCiAgICBuYW1lc190byA9ICJQcmVjaXBpdGF0aW9uIiwKICAgIHZhbHVlc190byA9ICJNYW5oYXR0YW4iCiAgKQoKVmlzX2xvbmckRGF5cyA9IGZhY3RvcigKICBWaXNfbG9uZyREYXlzLAogIGxldmVscyA9IGMoIkFsbCBEYXlzIiwgIlN1bmRheSIsICJNb25kYXkiLCAiVHVlc2RheSIsICJXZWRuZXNkYXkiLAogICAgICAgICAgICAgIlRodXJzZGF5IiwgIkZyaWRheSIsICJTYXR1cmRheSIpCikKZ2dwbG90KFZpc19sb25nLAogICAgICAgYWVzKHggPSBEYXlzLCB5ID0gTWFuaGF0dGFuLCBmaWxsID0gUHJlY2lwaXRhdGlvbikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSwKICAgICAgICAgICBuYS5ybSA9IFRSVUUpICsKICBsYWJzKAogICAgdGl0bGUgPSAiQXZlcmFnZSBDeWNsaXN0IENvdW50cyBvbiB0aGUgTWFuaGF0dGFuIEJyaWRnZSBKdWx5IDIwMTciLAogICAgeCA9ICJEYXkgb2YgdGhlIFdlZWsiLAogICAgeSA9ICJOdW1iZXIgb2YgQ3ljbGlzdHMiLAogICAgZmlsbCA9ICJQcmVjaXBpdGF0aW9uIgogICkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKAogICAgdmFsdWVzID0gYygiTm9fUHJlY2lwaXRhdGlvbiIgPSAiZGFya3JlZCIsCiAgICAgICAgICAgICAgICJTb21lX1ByZWNpcGl0YXRpb24iICAgID0gImxpZ2h0Ymx1ZSIpCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAoKVGhlIGRlcGljdGlvbnMgYWJvdmUgcHJvdmlkZSBhZGRlZCBjbGFyaXR5IHRvIHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MgZnJvbSBvdXIgcXVhc2ktUG9pc3NvbiBtb2RlbC4gU3VuZGF5IHdhcyB0aGUgYmFzZWxpbmUgZm9yIG91ciByZWdyZXNzaW9uIG1vZGVsJ3MgY2FsY3VsYXRpb25zLCBhbmQgYWxsIHJlbWFpbmluZyBkYXlzIG90aGVyIHRoYW4gU2F0dXJkYXkgaGFkIHBvc2l0aXZlIGNvZWZmaWNpZW50cy4gV2UgY2FuIHNlZSBpbiBib3RoIG91ciBjaGFydCBhbmQgdGFibGUsIHRoYXQgdGhlIGNvdW50IG9mIGN5Y2xpc3RzIGlzIGNlcnRhaW5seSBoaWdoZXIgdGhyb3VnaG91dCB0aGUgd2VlayB0aGFuIGl0IGlzIG9uIHRoZSB3ZWVrZW5kcy4gQXMgZm9yIHRoZSByb2xlIG9mIHByZWNpcGl0YXRpb247IG91ciBkaXNjcmV0aXplZCB2YXJpYWJsZSBOZXdQcmVjaXAgaGFkIGEgcmVncmVzc2lvbiBjb2VmZmljZW50IG9mIH4gMC40ICh0aGUgaGlnaGVzdCBhYnNvbHV0ZSB2YWx1ZSBvZiBhbnkgZmFjdG9yIGluIHRoZSBtb2RlbCkgYW5kIGEgc2lnbmlmaWNhbnQgcCB2YWx1ZSB+IC4wMDAyLiBUaGF0IGZpbmRpbmcgY2FuIGJlIGludHVpdGl2ZWx5IGNvbmZpcm1lZCBieSB0YWtpbmcgYSBnbGFuY2UgYXQgb3VyIHZpc3VhbHMuIE90aGVyIHRoYW4gVGh1cnNkYXksIGFsbCBvdGhlciBkYXlzIGZvciB3aGljaCB0aGVyZSBhcmUgZGF0YSBwb2ludHMgZm9yIGJvdGggcHJlY2lwaXRhdGlvbiBhbmQgbm8gcHJlY2lwaXRhdGlvbiBzaG93IGEgKm5vdGljZWFibGUqIGRlY3JlYXNlIGluIGN5Y2xpc3RzIHdoZW4gdGhlcmUgaXMgYSBwcmVzZW5jZSBvZiBwcmVjaXBpdGF0aW9uLgoKIyBDb25jbHVzaW9uClRocm91Z2ggb3VyIGFuYWx5c2lzIHZpYSB0aGUgbWVhbnMgb2YgYm90aCBQb2lzc29uIGFuZCBxdWFzaS1Qb2lzc29uIG1vZGVsaW5nIHRlY2huaXF1ZXMsIG91ciBmaW5kaW5ncyB3ZXJlIHJlbGF0aXZlbHkgY29uc2lzdGVudC4gVGhvc2UgYmVpbmcgdGhlIGZvbGxvd2luZzsKCi0gVGhlIE1hbmhhdHRhbiBCcmlkZ2UgaXMgZmFyIGJ1c2llciBkdXJpbmcgdGhlIHdlZWsgdGhhbiBpdCBpcyBvbiB0aGUgd2Vla2VuZC4KLSBBdCBsZWFzdCBpbiB0aGUgbW9udGggb2YgSnVseSwgdGhlIHRlbXBlcmF0dXJlIGRvZXMgbm90IHBsYXkgYW55IHNvcnQgb2Ygc2lnbmlmaWNhbnQgcm9sZSBpbiB0aGUgcmF3IG51bWJlciBvZiB0aGUgYnJpZGdlJ3MgY3ljbGlzdHMgbm9yIGl0cyBzaGFyZSBvZiB0aGUgdG90YWxpdHkgb2YgRWFzdCBSaXZlciBCcmlkZ2UgY3ljbGlzdHMuCi0gQWx0aG91Z2ggdGVtcGVyYXR1cmUgaXMgbm90IHNpZ25pZmljYW50bHkgYXNzb2NpYXRlZCB3aXRoIGN5Y2xpc3QgdHJhZmZpYywgcHJlY2lwaXRhdGlvbiBpcy4gQW55IGFtb3VudCBvZiBwcmVjaXBpdGF0aW9uIGhhcyBhIG5lZ2F0aXZlIGFuZCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IHJlbGF0aW9uc2hpcCB3aXRoIE1hbmhhdHRhbiBCcmlkZ2UncyBjeWNsaXN0IHRyYWZmaWMuCgpSZWdhcmRpbmcgdGhlIGV4aXN0ZW5jZSBvZiBib3RoIG91ciBQb2lzc29uIGFuZCBxdWFzaS1Qb2lzc29uIG1vZGVscyB0byBlc3RpbWF0ZSB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiBhbGwgdGhlc2UgZmFjdG9ycywgdGhlIHF1YXNpLVBvaXNzb24gaXMgbW9yZSBpZGVhbCBkdWUgdG8gdGhpcyBkYXRhc2V0J3MgKmV4dHJlbWVseSogaGlnaCBkaXNwZXJzaW9uIHBhcmFtZXRlciAoJFxoYXR7XHBoaX0kIH4gMTQyKS4gCgpJZiB3ZSB3ZXJlIHRvIGNvbnRpbnVlIG9yIGV4cGFuZCBvbiB0aGlzIGFuYWx5c2lzIGluIHRoZSBmdXR1cmUsIGl0IHdvdWxkIGJlIHZhbHVhYmxlIHRvIGV4cGFuZCB0aGUgc2NvcGUgb2Ygb3VyIGRhdGEgb3V0c2lkZSBvZiB0aGUgbW9udGggb2YgSnVseSBhbmQgaW50byBtb250aHMgdGhhdCBib3JkZXIgb24gc2Vhc29uYWwgY2hhbmdlcyBzdWNoIGFzIE1hcmNoLCBBcHJpbCBvciBPY3RvYmVyLiBJbnR1aXRpdmVseSwgb25lIG1pZ2h0IGd1ZXNzIHRoYXQgdGhlIGRheSdzIHRlbXBlcmF0dXJlcyBwbGF5IGEgbXVjaCBsYXJnZXIgcm9sZSBpbiBhIHRpbWUgb2YgdGhlIHllYXIgbGlrZSB0aGF0LgoKIyBSZWZlcmVuY2VzOgoKT3JpZ2luYWwgRGF0YXNldCBTb3VyY2U6CgotIGh0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL1NUQTMyMS93dzA5L3cwOS1Bc3NpZ25EYXRhU2V0Lnhsc3gKCkRhdGFzZXQgRG93bmxvYWQgTGlua3MgdmlhIEdpdGh1YjoKCi0gaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0NocmlzQjIzMjMvU1RBMzIxL3JlZnMvaGVhZHMvbWFpbi9OWUNfQ3ljbGlzdHNfRGF0YS54bHN4