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
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 = "Poisson Counts Regression: Weather and Schedule Relationship with Count of Manhattan Bridge Cyclists")
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 = "Poisson Rates Regression (1): Weather and Schedule Relationship with Count of Manhattan Bridge Cyclists")
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 = "Poisson Rates Regression (2): Precipitation and Schedule Relationship with Count of Manhattan Bridge Cyclists")
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-By-Day
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 = "Distribution of Manhattan Bridge Cyclist Count and Rates July 2017") %>%
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.
Conclusion and
Takeaways
To conclude, any implementations done in response to this model’s
findings should be done with caution due to the low practical
significance found in both our count and rate Poisson 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.
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.
LS0tCnRpdGxlOiAiQXNzb2NpYXRpb24gYmV0d2VlbiBXZWF0aGVyIGFuZCBEYXkgb2YgV2VlayB3aXRoIEN5Y2xpc3QgVHJhZmZpYyBvbiBNYW5oYXR0YW4gQnJpZGdlIgphdXRob3I6ICJDaHJpcyBCYWhtIgpkYXRlOiAiMjAyNS0xMC0zMCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIHRvY19kZXB0aDogNAogICAgZmlnX3dpZHRoOiA2CiAgICBmaWdfaGVpZ2h0OiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0Ci0tLQoKYGBge2NzcywgZWNobyA9IEZBTFNFfQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOwogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOwogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsKICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsKfQoKaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8KICBmb250LXNpemU6IDI0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IAojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4KCmlmICghcmVxdWlyZSgia25pdHIiKSkgeyAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBjb25kaXRpb25hbCBzdGF0ZW1lbnQgdG8gZGV0ZWN0CiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikgICAgICAgICAgICAgICAgICAjIHdoZXRoZXIgYSBwYWNrYWdlIHdhcyBpbnN0YWxsZWQgaW4KICAgbGlicmFyeShrbml0cikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91ciBtYWNoaW5lLiBJZiBub3QsIGluc3RhbGwgaXQgYW5kCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxvYWQgaXQgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgoKaWYgKCFyZXF1aXJlKHRpZHl2ZXJzZSkpIHtsaWJyYXJ5KHRpZHl2c2Vyc2UpfSAKCmlmICghcmVxdWlyZShHR2FsbHkpKSB7bGlicmFyeShHR2FsbHkpfSAKCmlmICghcmVxdWlyZShrYWJsZUV4dHJhKSkge2xpYnJhcnkoa2FibGVFeHRyYSl9IAoKaWYgKCFyZXF1aXJlKGdncGxvdDIpKSB7bGlicmFyeShnZ3Bsb3QyKX0gCgppZiAoIXJlcXVpcmUoY2FyKSkge2xpYnJhcnkoY2FyKX0gCgppZiAoIXJlcXVpcmUoZHBseXIpKSB7bGlicmFyeShkcGx5cil9IAoKaWYgKCFyZXF1aXJlKHBhbmRlcikpIHtsaWJyYXJ5KHBhbmRlcil9IAoKaWYgKCFyZXF1aXJlKGNhcikpIHtsaWJyYXJ5KGNhcil9IAoKaWYgKCFyZXF1aXJlKCJzY2FsZXMiKSkgewppbnN0YWxsLnBhY2thZ2VzKCJzY2FsZXMiKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKbGlicmFyeSgic2NhbGVzIikgCn0KCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKCWVjaG8gPSBUUlVFLAoJbWVzc2FnZSA9IEZBTFNFLAoJd2FybmluZyA9IEZBTFNFLAoJY29tbWVudCA9IE5BLAoJcmVzdWx0cyA9IFRSVUUKKQogICAKYGBgCgojIEludHJvZHVjdGlvbiBhbmQgQmFja2dyb3VuZApIZXJlIHdlIGhhdmUgYSBkYXRhc2V0IHNvdXJjZWQgZnJvbSBOZXcgWW9yayBDaXR5J3MgVHJhZmZpYyBJbmZvcm1hdGlvbiBNYW5hZ2VtZW50IFN5c3RlbSAoVElNUykuIFRJTVMgcmVjb3JkZWQgdGhlIG51bWJlciBvZiBjeWNsaXN0cyBlbnRlcmluZyBhbmQgbGVhdmluZyB0aHJlZSBvZiBOZXcgWW9yayBDaXR5J3MgZml2ZSBib3JvdWdocyAtIFF1ZWVucywgTWFuaGF0dGFuIGFuZCBCcm9va2x5biAtIHZpYSBhIGNvbGxlY3Rpb24gb2YgYnJpZGdlcyBrbm93biBhcyB0aGUgRWFzdCBSaXZlciBCcmlkZ2VzIChCcm9va2x5biBCcmlkZ2UsIE1hbmhhdHRhbiBCcmlkZ2UsIFdpbGxpYW1zYnVyZyBCcmlkZ2UsIGFuZCBRdWVlbnNib3JvIEJyaWRnZSkuIFRoZXNlIHJlY29yZGluZ3MgdG9vayBwbGFjZSBpbiAyMDE3LiBBcHJpbCwgSnVseSBhbmQgT2N0b2JlciBhcmUgdGhlIHRocmVlIG1vbnRocyB0aGF0IGFyZSBwcmVzZW50IGluIG91ciBhdmFpbGFibGUgY29weSBvZiB0aGUgZGF0YS4KCkZvciB0b2RheSdzIGFuYWx5c2lzIHdlIGFyZSBnb2luZyB0byBsb29rIGF0IGEgcmFuZG9tbHkgc2VsZWN0ZWQgc3Vic2V0IG9mIHRoZSBsYXJnZXIgZGF0YXNldCAoc3Vic2V0IHdhcyBjaG9zZW4gdXNpbmcgUidzIHJ1bmlmIGZ1bmN0aW9uKSwgdGhhdCBwZXJ0YWlucyB0byBjeWNsaXN0cyB3aG8gZW50ZXJlZCBhbmQgbGVmdCBvdXIgdGhyZWUgYm9yb3VnaHMgb2YgaW50ZXJlc3QgLSBRdWVlbnMsIE1hbmhhdHRhbiBhbmQgQnJvb2tseW4gLSB2aWEgdGhlICoqTWFuaGF0dGFuKiogQnJpZGdlIHRocm91Z2hvdXQgdGhlIGVudGlyZSBtb250aCBvZiBKdWx5IDIwMTcuIFRoaXMgZGF0YSBoYXMgMzEgb2JzZXJ2YXRpb25zLCBvbmUgZGV0YWlsaW5nIGVhY2ggZGF5LCBhbmQgbm8gbWlzc2luZyB2YWx1ZXMuIEEgYnJlYWtkb3duIG9mIGVhY2ggb2YgdGhlIG9yaWdpbmFsIGRhdGFzZXQncyB2YXJpYWJsZXMsIHRoZWlyIHByYWN0aWNhbCBtZWFuaW5nIGFuZCBkYXRhIHR5cGVzIGFyZSBiZWxvdy4KCmBgYHtyIFZhcmlhYmxlIFRhYmxlLCBlY2hvPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQoKVmFyX1RhYmxlID0gZGF0YS5mcmFtZSgKICBOYW1lID0gYygiRGF0ZSIsCiAgICAgICAgICAgIkRheSIsIAogICAgICAgICAgICJIaWdoVGVtcCIsIAogICAgICAgICAgICJMb3dUZW1wIiwKICAgICAgICAgICAiUHJlY2lwaXRhdGlvbiIsIAogICAgICAgICAgICJNYW5oYXR0YW4iLCAKICAgICAgICAgICAiVG90YWwiKSwKICAKICBNZWFuaW5nID0gYygiRGF0ZSBmb3IgdGhhdCBvYnNlcnZhdGlvbjsgWVlZWS1NTS1ERCBmb3JtIiwgCiAgICAgICAgICAgICAgIkRheSBvZiB0aGUgd2VlayBmb3IgdGhhdCBvYnNlcnZhdGlvbiIsCiAgICAgICAgICAgICAgIlRoYXQgZGF5J3MgaGlnaGVzdCByZWNvcmRlZCB0ZW1wZXJhdHVyZSIsIAogICAgICAgICAgICAgICJUaGF0IGRheSdzIGxvd2VzdCByZWNvcmRlZCB0ZW1wZXJhdHVyZSIsIAogICAgICAgICAgICAgICJNZWFzdXJlIG9mIHJhaW4gdGhhdCBkYXkgKGluY2hlcykiLCAgCiAgICAgICAgICAgICAgIk51bWJlciBvZiBjeWNsaXN0cyBlbnRlcmluZy9sZWF2aW5nIFF1ZWVucywgTWFuaGF0dGFuIG9yIEJyb29rbHluIHZpYSB0aGUgTUFOSEFUVEFOIEJyaWRnZSIsCiAgICAgICAgICAgICAgIlRvdGFsIG51bWJlciBvZiBjeWNsaXN0cyBlbnRlcmluZy9sZWF2aW5nIFF1ZWVucywgTWFuaGF0dGFuIG9yIEJyb29rbHluIHZpYSBBTlkgb2YgdGhlIEVhc3QgUml2ZXIgQnJpZGdlcyIpLCAKICAgICAgICAgICAgICAKICAKICBEYXRhX1R5cGUgPSBjKCJEYXRlIiwgImNoYXJhY3RlciIsICJkb3VibGUiLCAiZG91YmxlIiwgImRvdWJsZSIsICJkb3VibGUiLCAiZG91YmxlIikpCgprYWJsZShWYXJfVGFibGUpICU+JQogIGthYmxlX3N0eWxpbmcoCiAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiYm9yZGVyZWQiKSwKICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwKICAgIHBvc2l0aW9uID0gImNlbnRlciIpCgpgYGAKIyMgT2JqZWN0aXZlIG9mIEFuYWx5c2lzCldpdGggdGhlIGF2YWlsYWJsZSBkYXRhLCBteSBnb2FsIGZvciB0aGlzIGFuYWx5c2lzIGlzIHRvIGV4YW1pbmUgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gd2VhdGhlciBjb25kaXRpb25zIGFuZCBkYXkgb2YgdGhlIHdlZWsgd2l0aCB0aGUgYW1vdW50IG9mIGN5Y2xpc3QgdHJhZmZpYyB0aGF0IHRoZSBNYW5oYXR0YW4gQnJpZGdlIGV4cGVyaWVuY2VzLiBJbiBvcmRlciB0byBkbyB0aGlzLCBJIGNyZWF0ZWQgdHdvIG5ldyB2YXJpYWJsZXMgLSBNZWFuVGVtcCBhbmQgVGVtcERpZmYgLSB3aGljaCB3ZXJlIGNhbGN1bGF0ZWQgYnkgYXZlcmFnaW5nIHRoYXQgcGFydGljdWxhciBkYXkncyBsb3cgYW5kIGhpZ2ggdGVtcGVyYXR1cmVzIGFuZCBmaW5kaW5nIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhvc2UgdGVtcGVyYXR1cmVzIHJlc3BlY3RpdmVseS4gCgpVc2luZyB0aGVzZSB0ZW1wZXJhdHVyZS1yZWxhdGVkIG1ldHJpY3MsIGFsb25nIHdpdGggbWVhc3VyZXMgb2YgcHJlY2lwaXRhdGlvbiBhbmQgcmVjb3JkcyBvZiB0aGUgZGF5IG9mIHRoZSB3ZWVrLCBJIHdpbGwgdXNlIFBvaXNzb24gcmVncmVzc2lvbiB0ZWNobmlxdWVzIHRvIHNlZSB3aGljaCBpZiBhbnkgb2YgdGhlc2UgZmFjdG9ycyBwbGF5IGEgcGFydGljdWxhciByb2xlIGluIHRoZSBvdmVyYWxsIGFtb3VudCAqb3IqIHRoZSByZWxhdGl2ZSByYXRlIG9mIGN5Y2xpc3QgdHJhZmZpYyB0aGF0IHRoZSBNYW5oYXR0YW4gQnJpZGdlIGV4cGVyaWVuY2VzLgoKYGBge3IgRGF0YSBMb2FkaW5nIGFuZCBDbGVhbmluZywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeSAob3Blbnhsc3gpCm9wdGlvbnMoc2NpcGVuID0gOTk5KQoKIyByb3VuZChydW5pZigxLCBtaW4gPSAxLCBtYXggPSAxMCkpCiAgIyBVc2VkIGxpbmUgYWJvdmUgdG8gcmFuZG9tbHkgc2VsZWN0IHdoaWNoIHN1YnNldCBvZiB0aGUgZGF0YSB0byBkbyBteSBhbmFseXNpcyBvbi4gVGhlIGZpZnRoIHRhYiBvbiB0aGUgb3JpZ2luYWwgZGF0YSBFeGNlbCBzcHJlYWRzaGVldCB3YXMgZm9yIG9ic2VydmF0aW9ucyBvbiB0aGUgTWFuaGF0dGFuIEJyaWRnZSBmcm9tIDcvMSB0byA3LzMxCgpEYXRhID0gcmVhZC54bHN4KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vQ2hyaXNCMjMyMy9TVEEzMjEvcmVmcy9oZWFkcy9tYWluL05ZQ19DeWNsaXN0c19EYXRhLnhsc3giLCBzaGVldCA9ICJNYW5oYXR0YW4gMiIpCgpnbGltcHNlKERhdGEpCgojIENvbnZlcnRpbmcgdmFyaWFibGUgRGF0ZSB0byBhIGRhdGUgb2JqZWN0LgojIE9yaWdpbiA9IDE4OTktMTItMzAgc2luY2UgRXhjZWwgc3RvcmVzIGRhdGEgdmFsdWVzIGFzIHRoZSBudW1iZXIgb2YgZGF5cyBzaW5jZSB0aGVuLgpEYXRhJERhdGUgPSBhcy5EYXRlKERhdGEkRGF0ZSwgb3JpZ2luID0gIjE4OTktMTItMzAiKQoKIyBPcmlnaW5hbGx5IGNvbnZlcnRpbmcgdmFyaWFibGUgRGF5IHRvIGEgZGF0ZSBvYmplY3QsIHRoZW4gdXNpbmcgdGhlIHdlZWtkYXlzIGZ1bmN0aW9uIG9uIGl0LgpEYXRhJERheSA9IGFzLkRhdGUoRGF0YSREYXksIG9yaWdpbiA9ICIxODk5LTEyLTMwIikKICBEYXRhJERheSA9IHdlZWtkYXlzKGFzLkRhdGUoRGF0YSREYXkpKQoKICAjIENyZWF0aW9uIG9mIERheV9OdW0gdmFyaWFibGUKRGF0YSREYXlfTnVtW0RhdGEkRGF5ID09ICJTdW5kYXkiXSA9IDEKRGF0YSREYXlfTnVtW0RhdGEkRGF5ID09ICJNb25kYXkiXSA9IDIKRGF0YSREYXlfTnVtW0RhdGEkRGF5ID09ICJUdWVzZGF5Il0gPSAzCkRhdGEkRGF5X051bVtEYXRhJERheSA9PSAiV2VkbmVzZGF5Il0gPSA0CkRhdGEkRGF5X051bVtEYXRhJERheSA9PSAiVGh1cnNkYXkiXSA9IDUKRGF0YSREYXlfTnVtW0RhdGEkRGF5ID09ICJGcmlkYXkiXSA9IDYKRGF0YSREYXlfTnVtW0RhdGEkRGF5ID09ICJTYXR1cmRheSJdID0gNwoKICBEYXRhJE1lYW5UZW1wID0gKERhdGEkSGlnaFRlbXAgKyBEYXRhJExvd1RlbXApLzIKICBEYXRhJFRlbXBEaWZmID0gRGF0YSRIaWdoVGVtcCAtIERhdGEkTG93VGVtcAogIERhdGEkRGF5ID0gZmFjdG9yKERhdGEkRGF5LAogICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJTdW5kYXkiLCAiTW9uZGF5IiwgIlR1ZXNkYXkiLCAiV2VkbmVzZGF5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRodXJzZGF5IiwgIkZyaWRheSIsICJTYXR1cmRheSIpKQogICAgICAgICAgICAjIFNpbmNlIFN1bmRheSBpcyB0aGUgZmlyc3QgbGV2ZWwgb2YgdGhlIGZhY3RvciBsaXN0ZWQgaGVyZSwgaXQgd2lsbCBiZSByZWNvZ25pemVkIGFzIHRoZSBiYXNlbGluZSBieSBSCgoKIyBSZW9yZGVyIGNvbHVtbnMgZm9yIGlkZWFsIHZpc3VhbCBwZXJjZXB0aW9uCkRhdGEgPSBkYXRhLmZyYW1lKERhdGEkRGF0ZSwgRGF0YSREYXksIERhdGEkRGF5X051bSwgRGF0YSRIaWdoVGVtcCwgRGF0YSRMb3dUZW1wLCBEYXRhJE1lYW5UZW1wLCBEYXRhJFRlbXBEaWZmLCBEYXRhJFByZWNpcGl0YXRpb24sIERhdGEkTWFuaGF0dGFuLCBEYXRhJFRvdGFsKQpjb2xuYW1lcyhEYXRhKSA9IGMoIkRhdGUiLCAiRGF5IiwgIkRheV9OdW0iLCAiSGlnaFRlbXAiLCAiTG93VGVtcCIsICJNZWFuVGVtcCIsIlRlbXBEaWZmIiwgIlByZWNpcGl0YXRpb24iLCAiTWFuaGF0dGFuIiwgIlRvdGFsIikKCmdsaW1wc2UoRGF0YSkKYGBgCgojIFBvaXNzb24gUmVncmVzc2lvbiBNb2RlbGluZwpUbyBleHBsb3JlIGFueSBwb3RlbnRpYWwgYXNzb2NpYXRpb25zLCBJIGNyZWF0ZWQgUG9pc3NvbiBtb2RlbHMgb2YgdHdvIGRpZmZlcmVudCByZWdyZXNzaW9uIHR5cGVzLCBvbmUgYmVpbmcgZm9yIGNvdW50cyBhbmQgb25lIGJlaW5nIGZvciByYXRlcy4KClBvaXNzb24gY291bnRzIHJlZ3Jlc3Npb24gZXhhbWluZXMgdGhlIHRvdGFsIG51bWJlciBvZiBvY2N1cnJlbmNlcyBvZiBhIHBhcnRpY3VsYXIgZXZlbnQgKGluIHRoaXMgY2FzZSBjeWNsaXN0cyBvbiB0aGUgTWFuaGF0dGFuIEJyaWRnZSkgYW5kIHVzZXMgYSBsb2dhcml0aG1pYyBmdW5jdGlvbiB0byBkZXRlcm1pbmUgd2hpY2gsIGlmIGFueSBvZiB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGhhdmUgYSBzaWduaWZpY2FudCBlZmZlY3Qgb24gc2FpZCByZXNwb25zZSB2YXJpYWJsZSdzIG1lYW4uIFRoZSBmb3JtdWxhIGZvciBzYWlkIHJlZ3Jlc3Npb24gaXMgYmVsb3c6CgpgYGB7ciwgZWNobz1GQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiUG9pc3Nvbl9Nb2RlbF9Gb3JtLnBuZyIpCmBgYAoKLSAkXGJldGEkfjB+ID0gdGhlIGxvZyBvZiBvdXIgcmVzcG9uc2UgdmFyaWFibGUncyBtZWFuOyBub3QgdmVyeSB1c2VmdWwgZm9yIHByYWN0aWNhbCBpbnRlcnByZXRhdGlvbiAKCi0gJFxiZXRhJH4xfiwgJFxiZXRhJH4yfiwgJFxiZXRhJH4zfiwgLi4uICRcYmV0YSR+cH4gPSB0aGUgY2hhbmdlIGluIG91ciByZXNwb25zZSB2YXJpYWJsZSdzIGxvZyBtZWFuLCBpbiBhc3NvY2lhdGlvbiB3aXRoIGEgb25lIHVuaXQgaW5jcmVhc2UgaW4gc2FpZCBwcmVkaWN0b3IgdmFyaWFibGUKCiA8YnI+IAoKQWRkaXRpb25hbGx5LCBQb2lzc29uIHJhdGVzIHJlZ3Jlc3Npb24gYWltcyB0byBmaW5kIHRoZSBleHBlY3RlZCByYXRlIG9mIGEgcGFydGljdWxhciBldmVudCdzIG9jY3VycmVuY2UgcmVsYXRpdmUgdG8gdGhhdCBldmVudCdzIHByb3BvcnRpb24gd2l0aGluIGEgbGFyZ2VyICJwb3B1bGF0aW9uLiIgSW4gdGhlIGluc3RhbmNlIG9mIHRoaXMgZGF0YXNldCBhbmQgYW5hbHlzaXMsIG91ciB2YXJpYWJsZSBUb3RhbCwgd2hpY2ggcmVwcmVzZW50cyB0aGUgKip0b3RhbCoqIG51bWJlciBvZiBjeWNsaXN0cyBvbiBhbGwgdGhlIEVhc3QgUml2ZXIgQnJpZGdlcywgd2lsbCBiZSB3aGF0IHRoZSBudW1iZXIgb2YgY3ljbGlzdHMgb24gdGhlIE1hbmhhdHRhbiBCcmlkZ2UgYXJlIGNvbnNpZGVyZWQgdG8gYmUgYSBwcm9wb3J0aW9uIG9mLiBUaGUgY2FsY3VsYXRpb24gZm9yIHRoaXMgdHlwZSBvZiBQb2lzc29uIHJlZ3Jlc3Npb24gaXMgc2ltaWxhciB0byBjb3VudHMgcmVncmVzc2lvbiwgYnV0IHRoZSBsb2dhcml0aG0gb2YgdGhlIHBvcHVsYXRpb24gdmFyaWFibGUgaXMgYWxzbyBjb25zaWRlcmVkIHRvIGJlIGEgZmFjdG9yLiBUaGlzIGNhbiBiZSBleHByZXNzZWQgaW4gYm90aCBvZiB0aGUgZm9sbG93aW5nIHdheXMuCjxicj4KYGBge3IsIGVjaG89RkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoIlBvaXNzb25fRm9ybV9SYXRlczEucG5nIikKYGBgCiA8YnI+IApgYGB7ciwgZWNobz1GQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiUG9pc3Nvbl9Nb2RlbF9Gb3JtX1JhdGVzLnBuZyIpCmBgYAogPGJyPiAKIAogLSBJbiBQb2lzc29uIHJhdGVzIHJlZ3Jlc3Npb24sIHRoZSBwYXJhbWV0ZXJzICRcYmV0YSR+MH4sIC4uLi4gJFxiZXRhJH5wfiBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgaW4gdGhlIHNhbWUgbWFubmVyIGFzIHRoZXkgYXJlIGluIFBvaXNzb24gY291bnRzIG1vZGVsLgoKIyMgUG9pc3NvbiBSZWdyZXNzaW9uIChDb3VudHMpCkJlbG93IGlzIGEgc3VtbWFyeSBvZiB0aGUgUG9pc3NvbiBjb3VudHMgcmVncmVzc2lvbiBtb2RlbCBJIGNyZWF0ZWQsIHdpdGggbWVhc3VyZXMgb2YgdGVtcGVyYXR1cmUgcmFuZ2UgYW5kIGF2ZXJhZ2VzLCBwcmVjaXBpdGF0aW9uIGFtb3VudCBhbmQgZGF5IG9mIHRoZSB3ZWVrIGFsbCBmdW5jdGlvbmluZyBhcyBwcmVkaWN0b3JzIG9mIGhvdyBtYW55IGN5Y2xpc3RzIGNyb3NzZWQgdGhlIE1hbmhhdHRhbiBCcmlkZ2UgaW4gb3Igb3V0IG9mIG91ciB0aHJlZSBib3JvdWdocyBvZiBpbnRlcmVzdC4KYGBge3J9CiMgQ291bnRzIE1vZGVsOgogICMgUmVzcG9uc2UgPSBNYW5oYXR0YW4KICAjIFByZWRpY3RvcnMgPSBEYXksIE1lYW5UZW1wLCBUZW1wRGlmZiwgUHJlY2lwaXRhdGlvbgogICAgIyBEYXkgaXMgc3RvcmVkIGFzIGEgRmFjdG9yCgpDb3VudHNfTW9kZWwgPSBnbG0oTWFuaGF0dGFuIH4gRGF5ICsgTWVhblRlbXAgKyBUZW1wRGlmZiArIFByZWNpcGl0YXRpb24sIGZhbWlseSA9IHBvaXNzb24obGluayA9ICJsb2ciKSwgZGF0YSA9IERhdGEpCgpDb3VudHNfTW9kZWxfU3VtID0gc3VtbWFyeShDb3VudHNfTW9kZWwpCkNvdW50c19Nb2RlbF9Db2VmID0gQ291bnRzX01vZGVsX1N1bSRjb2VmZmljaWVudHMKCmludmlzaWJsZShDb3VudHNfTW9kZWxfQ29lZikKa2FibGUoQ291bnRzX01vZGVsX0NvZWYsIGNhcHRpb24gPSAiUG9pc3NvbiBDb3VudHMgUmVncmVzc2lvbjogV2VhdGhlciBhbmQgU2NoZWR1bGUgUmVsYXRpb25zaGlwIHdpdGggQ291bnQgb2YgTWFuaGF0dGFuIEJyaWRnZSBDeWNsaXN0cyIpCgojIEFsbCBwcmVkaWN0b3IgdmFyaWFibGVzIGFyZSBzaWduaWZpY2FudApgYGAKSW4gdGhlIG1vZGVsLCB3ZSBjYW4gc2VlIHRoYXQgKmV2ZXJ5KiBwcmVkaWN0b3IgdmFyaWFibGUgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBhcyBwZXIgcCB2YWx1ZXMgd2VsbCBiZWxvdyB0aGUgc3RhbmRhcmQgb2YgMC4wNSwgc28gbm8gc3RlcHdpc2UgcmVncmVzc2lvbiBvciBtb2RlbCBzaW1wbGlmaWNhdGlvbiBpcyBuZWNlc3NhcnkuIAoKQXMgZm9yIHRoZSBwcmFjdGljYWwgaW1wbGljYXRpb25zIG9mIG91ciBtb2RlbCBzdW1tYXJ5LCB3ZSBjYW4gc2F5IHRoYXQgYWx0aG91Z2ggZXZlcnkgcHJlZGljdG9yIHZhcmlhYmxlIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQsIHRoZSBtYWduaXR1ZGUgb2YgdGhlaXIgaW1wYWN0cyBhcmUgcmVsYXRpdmVseSBzbWFsbC4gUHJlY2lwaXRhdGlvbidzIGVzdGltYXRlZCBuZWdhdGl2ZSBlZmZlY3Qgb24gdGhlIGxvZyBtZWFuIG9mIE1hbmhhdHRhbiBCcmlkZ2UgY3ljbGlzdHMgaGFzIGFuIGFic29sdXRlIHZhbHVlIH4gfC40MzA3fCwgd2hpY2ggaXMgdGhlIHRoZSBoaWdoZXN0IG9mIGFsbCBvdXIgcHJlZGljdG9ycy4KCkl0IGFwcGVhcnMgdGhhdCB0aGUgZGF5J3MgYXZlcmFnZSB0ZW1wZXJhdHVyZSBhbmQgZGlmZmVyZW5jZSBpbiBkYWlseSBoaWdocyBhbmQgbG93cyBwbGF5ZWQgdmVyeSBsaXR0bGUgcHJhY3RpY2FsIHNpZ25pZmljYW5jZSBpbiB0aGUgbG9nIG1lYW4gb2YgdGhhdCBkYXkncyBjeWNsaXN0cy4gV2hlbiB3ZSBsb29rIGF0IHRoZSBkaWZmZXJlbmNlIGluIGxvZyBtZWFucyBmcm9tIGEgZGF5LW9mLXRoZS13ZWVrIHBlcnNwZWN0aXZlLCB3ZSBkbyBzZWUgYSBzbGlnaHRseSBtb3JlIGltcGFjdGZ1bCBlZmZlY3QuIFdpdGggU3VuZGF5IGJlaW5nIGNvZGVkIGluIGFzIHRoZSBiYXNlbGluZSwgaXQgbG9va3MgbGlrZSBXZWRuZXNkYXkgaGFzIHRoZSBncmVhdGVzdCBhbW91bnQgb2YgY3ljbGlzdCB0cmFmZmljIGFuZCBTYXR1cmRheSBoYXMgdGhlIGxlYXN0LiBUaGlzIGhpZ2hlciBjb3VudCBvZiBjeWNsaXN0cyBkdXJpbmcgdGhlIHdvcmt3ZWVrIGNvdWxkIGJlIGR1ZSB0byB0aGUgTWFuaGF0dGFuIEJyaWRnZSBmdW5jdGlvbmluZyBmb3IgbWFueSBhcyBhIGNvbW11dGluZyBtZXRob2QuCgpBbGwgaW4gYWxsLCBvdXIgUG9pc3NvbiBjb3VudHMgbW9kZWwgeWllbGRzIHNvbWUgaW50ZXJlc3RpbmcgYW5kIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgcmV2ZWxhdGlvbnMsIG1vc3Qgbm90YWJseSB0aGF0IGN5Y2xpc3RzIGNhcmUgZmFyIG1vcmUgYWJvdXQgcHJlY2lwaXRhdGlvbiB0aGFuIHRoZXkgZG8gdGVtcGVyYXR1cmUgZmx1Y3R1YXRpb24sIGFuZCB0aGF0IGN5Y2xpc3QgdHJhZmZpYyBhcHBlYXJzIHRvIHRpY2sgdXB3YXJkcyB0aHJvdWdob3V0IHRoZSB3b3Jrd2VlayBiZWZvcmUgZHlpbmcgZG93biBmb3IgdGhlIHdlZWtlbmQuIEhvd2V2ZXIsIHRoZSByZWxhdGl2ZWx5IHNtYWxsIG1hZ25pdHVkZSBvZiBlYWNoIHZhcmlhYmxlJ3MgZXN0aW1hdGVkIGVmZmVjdCBpcyBhIGRvd25zaWRlIHJlZ2FyZGluZyB0aGUgbW9kZWwncyB1dGlsaXR5LiAKCiMjIFBvaXNzb24gUmVncmVzc2lvbiAoUmF0ZXMpCkFmdGVyIFBvaXNzb24gY291bnRzIHJlZ3Jlc3Npb24sIEkgdGhlbiBwZXJmb3JtZWQgUG9pc3NvbiByYXRlcyByZWdyZXNzaW9uIHdpdGggdGhlIHRvdGFsIG51bWJlciBvZiBjeWNsaXN0cyBlbnRlcmluZyBhbmQgZXhpdGluZyBvdXIgdGhyZWUgYm9yb3VnaHMgb2YgaW50ZXJlc3QgYWNyb3NzICphbGwqIHRoZSBFYXN0IFJpdmVyIEJyaWRnZXMgYXMgdGhlICJwb3B1bGF0aW9uIiBmb3Igd2hpY2ggdGhlIE1hbmhhdHRhbiBCcmlkZ2UgY3ljbGlzdHMgYXJlIGFjdGluZyBhcyBhIHNhbXBsZSBvZi4gCgpUaGlzIHByb2Nlc3MgY29uc2lzdGVkIG9mIG1lIGNyZWF0aW5nIHR3byBkaWZmZXJlbnQgUG9pc3NvbiByYXRlcyBtb2RlbHMuIFRoZSBmaXJzdCBvbmUgSSBjcmVhdGVkIGxpc3RlZCBib3RoIHRlbXBlcmF0dXJlIHZhcmlhYmxlcyBhcyBzdGF0aXN0aWNhbGx5IGluc2lnbmlmaWNhbnQuIEdpdmVuIHRoZWlyIHN0YXR1cyBhcyBzdGF0aXN0aWNhbGx5IGluc2lnbmlmaWNhbnQgaW4gdGhpcyBtb2RlbCwgYW5kIHRoZWlyIG1pbnV0ZSBwcmFjdGljYWwgc2lnbmlmaWNhbmNlIGluIHRoZSBwcmV2aW91cyBjb3VudHMgbW9kZWwsIEkgY2hvc2UgdG8gcmVtb3ZlIHRoZW0gYW5kIGNyZWF0ZSBhIHNlY29uZCBQb2lzc29uIHJhdGVzIG1vZGVsIHdoaWNoIGRpZCBub3QgZmFjdG9yIGluIHRoZSBkYXkncyBhdmVyYWdlIG9yIHJhbmdlIG9mIHRlbXBlcmF0dXJlLgpgYGB7cn0KIyMjIFJhdGVzIE1vZGVsIDEKUmF0ZXNfTW9kZWwgPSBnbG0oTWFuaGF0dGFuIH4gRGF5ICsgTWVhblRlbXAgKyBUZW1wRGlmZiArIFByZWNpcGl0YXRpb24sIG9mZnNldCA9IGxvZyhUb3RhbCksIGZhbWlseSA9IHBvaXNzb24obGluayA9ICJsb2ciKSwgZGF0YSA9IERhdGEpCgpSYXRlc19Nb2RlbF9TdW0gPSBzdW1tYXJ5KFJhdGVzX01vZGVsKQpSYXRlc19Nb2RlbF9Db2VmID0gUmF0ZXNfTW9kZWxfU3VtJGNvZWZmaWNpZW50cwoKaW52aXNpYmxlKFJhdGVzX01vZGVsX0NvZWYpCmthYmxlKFJhdGVzX01vZGVsX0NvZWYsIGNhcHRpb24gPSAiUG9pc3NvbiBSYXRlcyBSZWdyZXNzaW9uICgxKTogV2VhdGhlciBhbmQgU2NoZWR1bGUgUmVsYXRpb25zaGlwIHdpdGggQ291bnQgb2YgTWFuaGF0dGFuIEJyaWRnZSBDeWNsaXN0cyIpCgoKIyMjIFJhdGVzIE1vZGVsIDIKUmF0ZXNfTW9kZWwyID0gZ2xtKE1hbmhhdHRhbiB+IERheSArIFByZWNpcGl0YXRpb24sIG9mZnNldCA9IGxvZyhUb3RhbCksIGZhbWlseSA9IHBvaXNzb24obGluayA9ICJsb2ciKSwgZGF0YSA9IERhdGEpCgpSYXRlc19Nb2RlbDJfU3VtID0gc3VtbWFyeShSYXRlc19Nb2RlbDIpClJhdGVzX01vZGVsMl9Db2VmID0gUmF0ZXNfTW9kZWwyX1N1bSRjb2VmZmljaWVudHMKCmludmlzaWJsZShSYXRlc19Nb2RlbF9Db2VmKQprYWJsZShSYXRlc19Nb2RlbDJfQ29lZiwgY2FwdGlvbiA9ICJQb2lzc29uIFJhdGVzIFJlZ3Jlc3Npb24gKDIpOiBQcmVjaXBpdGF0aW9uIGFuZCBTY2hlZHVsZSBSZWxhdGlvbnNoaXAgd2l0aCBDb3VudCBvZiBNYW5oYXR0YW4gQnJpZGdlIEN5Y2xpc3RzIikKCmBgYApMb29raW5nIGF0IHRoZSBmaW5kaW5ncyBvZiBvdXIgc2Vjb25kIFBvaXNzb24gcmF0ZXMgcmVncmVzc2lvbiBtb2RlbCwgd2Ugc2VlIGEgdHJlbmQgc2ltaWxhciB0byB0aGF0IG9mIG91ciBQb2lzc29uIGNvdW50cyByZWdyZXNzaW9uIG1vZGVsLCB0aGF0IGJlaW5nIGEgY29tbW9uIG9jY3VycmVuY2Ugb2Ygc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIGJ1dCBub3QgYSBncmVhdCBkZWFsIG9mIHByYWN0aWNhbCBzaWduaWZpY2FuY2Ugb24gZGlzcGxheSB3aGVuIHRoZSBtYWduaXR1ZGUgb2YgdGhlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnQgaXMgdGFrZW4gaW50byBjb25zaWRlcmF0aW9uLgoKT25jZSBhZ2FpbiB0cmVhdGluZyBTdW5kYXkgYXMgb3VyIGJhc2VsaW5lLCBpdCBsb29rcyBsaWtlIHRoZSByYXRlIG9mIE1hbmhhdHRhbiBCcmlkZ2UgY3ljbGlzdHMgaW4gcHJvcG9ydGlvbiB0byB0aGUgZW50aXJldHkgb2YgRWFzdCBSaXZlciBCcmlkZ2UgY3ljbGlzdHMgaXMgYXQgaXRzIGhpZ2hlc3QgZWFybHkgaW4gdGhlIHdlZWssIHdpdGggdGhhdCByYXRlIGRlY2xpbmluZyBnb2luZyBpbnRvIHRoZSB3ZWVrZW5kLiBUaGF0IGJlaW5nIHNhaWQsIHRoZSBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2Ugb2YgdGhpcyBicmVha2Rvd24gYWxzbyBncmVhdGx5IGRlY3JlYXNlcyB3aGVuIHdlIGxvb2sgYXQgdGhlIGRhdGEgZm9yIFRodXJzZGF5IGFuZCB0byBhIG11Y2ggbGVzc2VyIGJ1dCBzdGlsbCBub3RpY2VhYmxlIGV4dGVudCBGcmlkYXksIHBlcmhhcHMgc3VnZ2VzdGluZyB0aGF0IHRoZSBNYW5oYXR0YW4gQnJpZGdlIGN5Y2xpc3QgcmF0ZSdzIGRlY2xpbmUgYXQgdGhlIHRhaWwgZW5kIG9mIHRoZSB3b3Jrd2VlayBjb3VsZCBiZSBjaGFsa2VkIHVwIHRvIHJhbmRvbSBjaGFuY2UgYW5kIG5vdCBhIHBhcnRpY3VsYXIgY2hhcmFjdGVyaXN0aWMgb2YgdGhlIEJyaWRnZSB0aGF0IGFmZmVjdHMgdGhlIGV4cGVyaWVuY2Ugb2YgaXRzIGN5Y2xpc3RzIG9ubHkgb24gdGhvc2UgcGFydGljdWxhciBkYXlzLgoKCiMjIERheS1CeS1EYXkgQXZlcmFnZXMKU2luY2UgYm90aCBvdXIgY291bnRzIGFuZCByYXRlcyBtb2RlbHMgc3VnZ2VzdGVkIHRoYXQgdGhlIGRheSBvZiB0aGUgd2VlayBoYXMgdGhlIGdyZWF0ZXN0IGFzc29jaWF0aW9uIHdpdGggdGhlIGxvZyBtZWFuIG9mIHRoZSBNYW5oYXR0YW4gQnJpZGdlJ3MgY3ljbGlzdHMsIEkgZGVjaWRlZCB0byBjYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgY291bnRzIGFuZCByYXRlcyBwZXIgZGF5IHRvIGNvbXBhcmUgdGhlbSB0byBlYWNoIG90aGVyIGFuZCB0aGUgbWVhbiBhY3Jvc3MgYWxsIGRheXMgY29uc2lkZXJlZC4gVGhlIHRhYmxlIHdpdGggdGhpcyBpbmZvcm1hdGlvbiBpcyBiZWxvdy4KYGBge3J9CkNvdW50X0F2ZXJhZ2VzID0gYygKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiU3VuZGF5Il0pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJNb25kYXkiXSkpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlR1ZXNkYXkiXSkpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIldlZG5lc2RheSJdKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiVGh1cnNkYXkiXSkpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIkZyaWRheSJdKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiU2F0dXJkYXkiXSkpCikKCkFsbERheXNfUmF0ZXNfQXZnID0gc3VtKERhdGEkTWFuaGF0dGFuKS9zdW0oRGF0YSRUb3RhbCkKClN1bl9SYXRlc19BdmcgPSBzdW0oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlN1bmRheSJdKS9zdW0oRGF0YSRUb3RhbFtEYXRhJERheSA9PSAiU3VuZGF5Il0pCgpNb25fUmF0ZXNfQXZnID0gc3VtKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJNb25kYXkiXSkvc3VtKERhdGEkVG90YWxbRGF0YSREYXkgPT0gIk1vbmRheSJdKQoKVHVlc19SYXRlc19BdmcgPSBzdW0oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlR1ZXNkYXkiXSkvc3VtKERhdGEkVG90YWxbRGF0YSREYXkgPT0gIlR1ZXNkYXkiXSkKCldlZF9SYXRlc19BdmcgPSBzdW0oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIldlZG5lc2RheSJdKS9zdW0oRGF0YSRUb3RhbFtEYXRhJERheSA9PSAiV2VkbmVzZGF5Il0pCgpUaHVyX1JhdGVzX0F2ZyA9IHN1bShEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiVGh1cnNkYXkiXSkvc3VtKERhdGEkVG90YWxbRGF0YSREYXkgPT0gIlRodXJzZGF5Il0pCgpGcmlfUmF0ZXNfQXZnID0gc3VtKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJGcmlkYXkiXSkvc3VtKERhdGEkVG90YWxbRGF0YSREYXkgPT0gIkZyaWRheSJdKQoKU2F0X1JhdGVzX0F2ZyA9IHN1bShEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiU2F0dXJkYXkiXSkvc3VtKERhdGEkVG90YWxbRGF0YSREYXkgPT0gIlNhdHVyZGF5Il0pCgpEYXlfUmF0ZXNfQXZlcmFnZXMgPSBjKEFsbERheXNfUmF0ZXNfQXZnLCBTdW5fUmF0ZXNfQXZnLCBNb25fUmF0ZXNfQXZnLCBUdWVzX1JhdGVzX0F2ZywgV2VkX1JhdGVzX0F2ZywgVGh1cl9SYXRlc19BdmcsIEZyaV9SYXRlc19BdmcsIFNhdF9SYXRlc19BdmcpCgpSYXRlX0F2ZXJhZ2VzID0gcm91bmQoRGF5X1JhdGVzX0F2ZXJhZ2VzLCBkaWdpdHMgPSA0KQoKRGF5cyA9IGMoIkFsbCBEYXlzIiwgIlN1bmRheSIsICJNb25kYXkiLCAiVHVlc2RheSIsICJXZWRuZXNkYXkiLCAiVGh1cnNkYXkiLCAiRnJpZGF5IiwgIlNhdHVyZGF5IikKCkNvdW50c19EaWZmZXJlbmNlID0gYygKICAwLCAjIERpZmZlcmVuY2UgYmV0d2VlbiB0aGUgYXZlcmFnZSBjb3VudCBvZiBhbGwgZGF5cyBhbmQgaXRzZWxmCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiU3VuZGF5Il0pKSAtIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW4pKSwKICByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuW0RhdGEkRGF5ID09ICJNb25kYXkiXSkpIC0gcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbikpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIlR1ZXNkYXkiXSkpIC0gcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbikpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIldlZG5lc2RheSJdKSkgLSByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiVGh1cnNkYXkiXSkpIC0gcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbikpLAogIHJvdW5kKG1lYW4oRGF0YSRNYW5oYXR0YW5bRGF0YSREYXkgPT0gIkZyaWRheSJdKSkgLSByb3VuZChtZWFuKERhdGEkTWFuaGF0dGFuKSksCiAgcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbltEYXRhJERheSA9PSAiU2F0dXJkYXkiXSkpIC0gcm91bmQobWVhbihEYXRhJE1hbmhhdHRhbikpCikKClJhdGVzX0RpZmZlcmVuY2VCID0gYygKICAwLAogIFN1bl9SYXRlc19BdmcgLSBBbGxEYXlzX1JhdGVzX0F2ZywKICBNb25fUmF0ZXNfQXZnIC0gQWxsRGF5c19SYXRlc19BdmcsCiAgVHVlc19SYXRlc19BdmcgLSBBbGxEYXlzX1JhdGVzX0F2ZywKICBXZWRfUmF0ZXNfQXZnIC0gQWxsRGF5c19SYXRlc19BdmcsCiAgVGh1cl9SYXRlc19BdmcgLSBBbGxEYXlzX1JhdGVzX0F2ZywKICBGcmlfUmF0ZXNfQXZnIC0gQWxsRGF5c19SYXRlc19BdmcsCiAgU2F0X1JhdGVzX0F2ZyAtIEFsbERheXNfUmF0ZXNfQXZnCikKClJhdGVzX0RpZmZlcmVuY2UgPSByb3VuZChSYXRlc19EaWZmZXJlbmNlQiwgZGlnaXRzID0gNCkKClRhYmxlID0gY2JpbmQoRGF5cywgQ291bnRfQXZlcmFnZXMsIENvdW50c19EaWZmZXJlbmNlLCBSYXRlX0F2ZXJhZ2VzLCBSYXRlc19EaWZmZXJlbmNlKQoKa2FibGUoVGFibGUsIGNhcHRpb24gPSAiRGlzdHJpYnV0aW9uIG9mIE1hbmhhdHRhbiBCcmlkZ2UgQ3ljbGlzdCBDb3VudCBhbmQgUmF0ZXMgSnVseSAyMDE3IikgJT4lCiAga2FibGVfc3R5bGluZygKICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIpLAogICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgcG9zaXRpb24gPSAiY2VudGVyIgogICkKYGBgCgpUaGUgdGFibGUgcHJvdmlkZXMgZ3JlYXRlciBkZXRhaWwgaW50byB0aGUgaW1wbGljYXRpb25zIG9mIG91ciBQb2lzc29uIGNvdW50IGFuZCByYXRlIG1vZGVscy4gVGhhdCBiZWluZyB3ZWVrZGF5IHRvdGFscyBvZiBNYW5oYXR0YW4gQnJpZGdlIGN5Y2xpc3RzIChzcGVjaWZpY2FsbHkgTW9uZGF5IC0gVGh1cnNkYXkpIGZhciBvdXR3ZWlnaCB0aGUgY291bnQgb2YgY3ljbGlzdHMgb24gdGhlIGJyaWRnZSBmcm9tIEZyaWRheSB0byBTdW5kYXkuIFdpdGggdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGN5bGNsaXN0cyBmcm9tIE1vbmRheSAtIFRodXJzZGF5IGJlaW5nIGFib3V0IDYsMzI1LCBhbmQgdGhlIGF2ZXJhZ2UgbnVtYmVyIEZyaWRheSAtIFN1bmRheSBiZWluZyBhYm91dCA0LDM1My4KCkFzIGZvciB0aGUgcmF0ZSBvZiBNYW5oYXR0YW4gQnJpZGdlIGN5Y2xpc3RzIHJlbGF0aXZlIHRvIGN5Y2xpc3RzIG9uIGFsbCBFYXN0IFJpdmVyIEJyaWRnZXMsIHdlIHNlZSB0aGF0IHRoZSBNYW5oYXR0YW4gQnJpZGdlJ3MgY3ljbGlzdCByYXRlIGlzIHNsaWdodGx5IGFib3ZlIGF2ZXJhZ2UgTW9uZGF5IC0gV2VkbmVzZGF5LCBidXQgdGhlbiBiZWxvdyBhdmVyYWdlIFRodXJzZGF5IHRocm91Z2ggU3VuZGF5LgoKCiMgQ29uY2x1c2lvbiBhbmQgVGFrZWF3YXlzClRvIGNvbmNsdWRlLCBhbnkgaW1wbGVtZW50YXRpb25zIGRvbmUgaW4gcmVzcG9uc2UgdG8gdGhpcyBtb2RlbCdzIGZpbmRpbmdzIHNob3VsZCBiZSBkb25lIHdpdGggY2F1dGlvbiBkdWUgdG8gdGhlIGxvdyBwcmFjdGljYWwgc2lnbmlmaWNhbmNlIGZvdW5kIGluIGJvdGggb3VyIGNvdW50IGFuZCByYXRlIFBvaXNzb24gbW9kZWxzLiBUaGF0IGJlaW5nIHNhaWQsIHRoZXJlIGFyZSBzdGlsbCB2YWx1YWJsZSB0YWtlYXdheXMgdGhhdCB3ZSBjYW4gZHJhdyBmcm9tIG91ciBhbmFseXNpcy4gCgpGaXJzdCwgdGhlIE1hbmhhdHRhbiBCcmlkZ2UgaXMgY2xlYXJseSBidXNpZXIsIGJvdGggaW4gdGhlIHNlbnNlIG9mIHJhdyB2b2x1bWUgYW5kIGFzIGEgcHJvcG9ydGlvbiBvZiB0aGUgb3ZlcmFsbCBFYXN0IFJpdmVyIEJyaWRnZSBuZXR3b3JrLCBlYXJseSBhbmQgdGhyb3VnaG91dCB0aGUgc3RhbmRhcmQgd29ya3dlZWsgdGhhbiBpdCBpcyBkdXJpbmcgdGhlIHdlZWtlbmQuIFNlY29uZCwgdGhlIGRhaWx5IGF2ZXJhZ2UgdGVtcGVyYXR1cmUgYXMgd2VsbCBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoYXQgZGF5J3MgaGlnaCBhbmQgbG93IHBsYXllZCB2ZXJ5IGxpdHRsZSBpZiBhbnkgcm9sZSBpbiB0aGUgY291bnQgb3IgcmF0ZSBvZiBjeWNsaXN0cyBvbiBhbnkgZ2l2ZW4gZGF5LCBidXQgdGhlIG1lYXN1cmUgb2YgcHJlY2lwaXRhdGlvbiBkb2VzIGFwcGVhciB0byBoYXZlIGEgcmVsYXRpdmVseSBub3RpY2VhYmxlIGFuZCBuZWdhdGl2ZSBhc3NvY2lhdGlvbiB3aXRoIHRoZSBudW1iZXIgb2YgdGhhdCBkYXkncyBjeWNsaXN0cyBvbiB0aGUgTWFuaGF0dGFuIEJyaWRnZS4KCklmIHdlIHdlcmUgdG8gY29udGludWUgb3IgZXhwYW5kIG9uIHRoaXMgYW5hbHlzaXMgaW4gdGhlIGZ1dHVyZSwgaXQgd291bGQgYmUgdmFsdWFibGUgdG8gZXhwYW5kIHRoZSBzY29wZSBvZiBvdXIgZGF0YSBvdXRzaWRlIG9mIHRoZSBtb250aCBvZiBKdWx5IGFuZCBpbnRvIG1vbnRocyB0aGF0IGJvcmRlciBvbiBzZWFzb25hbCBjaGFuZ2VzIHN1Y2ggYXMgTWFyY2gsIEFwcmlsIG9yIE9jdG9iZXIuIEludHVpdGl2ZWx5LCBvbmUgbWlnaHQgZ3Vlc3MgdGhhdCB0aGUgZGF5J3MgdGVtcGVyYXR1cmVzIHBsYXkgYSBtdWNoIGxhcmdlciByb2xlIGluIGEgdGltZSBvZiB0aGUgeWVhciBsaWtlIHRoYXQuCgojIFJlZmVyZW5jZXM6CgpPcmlnaW5hbCBEYXRhc2V0IFNvdXJjZToKCi0gaHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vU1RBMzIxL3d3MDkvdzA5LUFzc2lnbkRhdGFTZXQueGxzeAoKRGF0YXNldCBEb3dubG9hZCBMaW5rcyB2aWEgR2l0aHViOgoKLSBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vQ2hyaXNCMjMyMy9TVEEzMjEvcmVmcy9oZWFkcy9tYWluL05ZQ19DeWNsaXN0c19EYXRhLnhsc3g=