Introduction
This project investigates how weekday patterns and weather conditions
affect daily cyclist counts on the Queensboro Bridge in New York City.
Because cyclist traffic is a count variable that can be influenced by
multiple environmental and behavioral factors, our analysis combines
Poisson and quasi-Poisson generalized linear models to evaluate how the
number of cyclists changes with day of the week, average temperature,
precipitation, and total roadway exposure.
We address three core research questions:
Do cyclist counts vary systematically by weekday, temperature, and
precipitation?
Is the standard Poisson model appropriate, or is over-dispersion so
severe that inference becomes unreliable without adjustment?
Does incorporating traffic exposure through an offset term
meaningfully change conclusions about which predictors matter?
By comparing Poisson, quasi-Poisson, and quasi-Poisson rate models,
we aim to determine which modeling framework provides the most
trustworthy inference while offering a practical interpretation of how
weather and weekly patterns shape cycling behavior.
Data and Variables
Data Source
The dataset contains daily observations of cyclist counts crossing
the Queensboro Bridge along with associated weather variables and total
traffic exposure. Because observations are aggregated by day, each row
represents a distinct measurement of environmental and traffic
conditions.
data_path <- "C:/Users/rg03/Downloads/sta321/PoissonData.xlsx"
raw <- read_excel(data_path)
dim(raw)
[1] 31 7
Variable
Definitions
To ensure clarity and reproducibility, all variables used in the
analysis are listed below with names, descriptions, and data types:
count (integer) — Total number of cyclists counted that day.
exposure (numeric) — Total traffic volume or exposure used as an
offset in rate models.
avgtemp (numeric) — Average daily temperature, computed as the mean
of high and low temperatures.
newprecip (binary indicator) — 1 if precipitation > 0; 0
otherwise.
day (ordered factor) — Day of the week (Monday through Sunday), coded
as an ordered factor to detect smooth weekly patterns.
Because day is ordered, R generates orthogonal polynomial contrasts
such as:
day.L — linear weekday trend,
day.Q — quadratic weekly curvature,
day.C, day^4, etc. — higher-order cyclical patterns.
These terms appear in the model output but are not standalone
variables. They represent structured contrasts that capture how cyclist
counts shift across the week.
Data Processing
All preprocessing steps were explicitly documented:
Variable names were standardized to lower case and simplified for
consistency.
Temperature variables were combined into a single, interpretable
variable (avgtemp).
Precipitation was converted to a binary indicator to capture the main
effect of rain vs. dry conditions.
day was encoded as an ordered factor to capture weekly structure
without introducing seven separate dummy variables.
Only rows with complete information were retained.
This preprocessing ensures the final dataset is clean, interpretable,
and ready for generalized linear modeling.
nm <- names(raw)
nm <- tolower(nm)
nm <- gsub("[[:space:]]+", "_", nm)
nm <- gsub("[^a-z0-9_]", "", nm)
nm <- gsub("_+", "_", nm)
nm <- gsub("^_+|_+$", "", nm)
names(raw) <- nm
dat <- raw %>%
mutate(
count = as.numeric(queensborobridge),
exposure = as.numeric(total),
avgtemp = (as.numeric(hightemp) + as.numeric(lowtemp))/2,
newprecip = ifelse(as.numeric(precipitation) > 0, 1L, 0L),
day = factor(day, levels=c("Monday","Tuesday","Wednesday","Thursday",
"Friday","Saturday","Sunday"),
ordered=TRUE)
) %>%
filter(!is.na(count), !is.na(avgtemp), !is.na(newprecip), !is.na(day))
kable(head(dat), caption="Preview of processed data")
Preview of processed data
| 2025-07-01 |
Saturday |
84.9 |
72.0 |
0.23 |
3216 |
11867 |
3216 |
11867 |
78.45 |
1 |
| 2025-07-02 |
Sunday |
87.1 |
73.0 |
0.00 |
3579 |
13995 |
3579 |
13995 |
80.05 |
0 |
| 2025-07-03 |
Monday |
87.1 |
71.1 |
0.45 |
4230 |
16067 |
4230 |
16067 |
79.10 |
1 |
| 2025-07-04 |
Tuesday |
82.9 |
70.0 |
0.00 |
3861 |
13925 |
3861 |
13925 |
76.45 |
0 |
| 2025-07-05 |
Wednesday |
84.9 |
71.1 |
0.00 |
5862 |
23110 |
5862 |
23110 |
78.00 |
0 |
| 2025-07-06 |
Thursday |
75.0 |
71.1 |
0.00 |
5251 |
21861 |
5251 |
21861 |
73.05 |
0 |
The first six rows confirm that all preprocessing steps were applied
correctly: count and exposure were accurately converted to numeric
variables, avgtemp reflects the average of high and low temperatures,
newprecip correctly indicates rainy vs. dry days, and day is properly
encoded as an ordered factor. These checks ensure the dataset is clean
and ready for GLM modeling. # Exploratory Data Analysis
Rationale
Exploratory Data Analysis (EDA) provides an initial understanding of
how cyclist counts behave relative to weekday patterns, temperature, and
precipitation. While pairwise plots cannot establish causal or adjusted
relationships, they identify broad trends, potential nonlinearity, and
sources of variability that must be accounted for in the GLM
framework.
Cyclist Counts by
Day
Visualizing counts by weekday suggests that cyclist volume tends to
be higher on weekdays than weekends, though variability is substantial
across all days. This aligns with expectations for commuter patterns but
cannot yet distinguish whether day-of-week differences persist after
adjusting for weather and exposure
ggplot(dat, aes(day, count)) + geom_boxplot() +
labs(title="Cyclist Counts by Day", x="Day", y="Count")

Interpretation: Weekdays show somewhat higher median
counts, but variability is large. A formal model is needed.
Counts vs
Temperature
Cyclist volume rises with temperature, particularly as conditions
warm from cooler days into moderate temperatures. However, the large
spread in counts at any given temperature indicates that temperature
alone cannot explain the full variation in cycling patterns—reinforcing
the need for multivariable models.
ggplot(dat, aes(avgtemp, count)) + geom_point(alpha=.5) +
geom_smooth(method="loess", se=FALSE) +
labs(title="Counts vs Temperature", x="Avg Temp (°F)", y="Count")

Interpretation: Warmer days trend upward, but
variation is wide → suggests multiple predictors matter jointly.
Counts by
Precipitation
Rainy days clearly show lower cyclist counts than dry days. This
strong pairwise contrast suggests precipitation is a key driver of
cycling behavior. Later modeling will determine whether this effect
remains after accounting for weekday structure, exposure, and
temperature.
ggplot(dat, aes(factor(newprecip), count)) + geom_boxplot() +
labs(title="Counts by Precipitation", x="0=Dry / 1=Wet", y="Count")

Interpretation: Rain clearly lowers counts.
Poisson and
Quasi-Poisson Models
Rationale
Cyclist counts are non-negative integers, making Poisson regression a
natural starting point. However, Poisson models assume equality of the
mean and variance: Var(Y)=Mean(Y). When the variance dramatically
exceeds the mean—a phenomenon known as over-dispersion—standard errors
become severely underestimated, artificially inflating statistical
significance. A quasi-Poisson model corrects this by introducing a
dispersion parameter: φ.This model preserves the mean structure of the
Poisson GLM while providing valid inference even when dispersion is
large. Additionally, incorporating an offset using log(exposure) enables
modeling of cycling rate per unit traffic, which is essential for
understanding cyclist behavior relative to total traffic flow.
Fit Poisson &
Quasi-Poisson Models
m_pois <- glm(count ~ day + avgtemp + newprecip,
family=poisson(link="log"), data=dat)
m_quasi <- glm(count ~ day + avgtemp + newprecip,
family=quasipoisson(link="log"), data=dat)
m_quasi_rate <- glm(count ~ day + avgtemp + newprecip +
offset(log(exposure)),
family=quasipoisson(link="log"),
data=dat %>% filter(!is.na(exposure), exposure>0))
phi_hat <- sum(residuals(m_pois, type="pearson")^2) / m_pois$df.residual
kable(data.frame(Dispersion=round(phi_hat,2)),
caption="Estimated Over-Dispersion φ")
Estimated Over-Dispersion φ
| 109.11 |
The dispersion estimate from the Poisson model is:𝜙=109.11.This means
the variance of cyclist counts is more than 100 times larger than the
mean, rendering Poisson-based inference unreliable. Consequences
include:
-Misleadingly small p-values
-Narrowed confidence intervals
-Overstated significance for several predictors
-Inflated Type I error rate
Because of this extreme over-dispersion, the quasi-Poisson framework
is essential for drawing valid conclusions.
Poisson IRRs (for
comparison)
kable(tidy(m_pois, conf.int=TRUE, exponentiate=TRUE),
digits=3, caption="Poisson IRRs")
Poisson IRRs
| (Intercept) |
3067.571 |
0.042 |
189.020 |
0.000 |
2822.419 |
3333.737 |
| day.L |
0.762 |
0.007 |
-38.606 |
0.000 |
0.752 |
0.773 |
| day.Q |
0.888 |
0.007 |
-16.881 |
0.000 |
0.876 |
0.900 |
| day.C |
1.039 |
0.008 |
5.091 |
0.000 |
1.024 |
1.055 |
| day^4 |
1.113 |
0.007 |
15.060 |
0.000 |
1.098 |
1.129 |
| day^5 |
0.951 |
0.007 |
-6.953 |
0.000 |
0.937 |
0.964 |
| day^6 |
0.985 |
0.007 |
-2.149 |
0.032 |
0.971 |
0.999 |
| avgtemp |
1.006 |
0.001 |
11.007 |
0.000 |
1.005 |
1.007 |
| newprecip |
0.727 |
0.007 |
-43.950 |
0.000 |
0.717 |
0.737 |
The Poisson model suggests almost every term is statistically
significant, including all polynomial weekday contrasts, temperature,
and precipitation. However, due to φ > 100, these results represent
false precision and cannot be trusted.
These results serve only as a comparison point, demonstrating what
happens when over-dispersion is ignored.
Quasi-Poisson IRRs
(no offset)
kable(tidy(m_quasi, conf.int=TRUE, exponentiate=TRUE),
digits=3, caption="Quasi-Poisson IRRs")
Quasi-Poisson IRRs
| (Intercept) |
3067.571 |
0.444 |
18.095 |
0.000 |
1279.506 |
7287.428 |
| day.L |
0.762 |
0.073 |
-3.696 |
0.001 |
0.660 |
0.880 |
| day.Q |
0.888 |
0.074 |
-1.616 |
0.120 |
0.768 |
1.025 |
| day.C |
1.039 |
0.079 |
0.487 |
0.631 |
0.890 |
1.215 |
| day^4 |
1.113 |
0.074 |
1.442 |
0.163 |
0.963 |
1.289 |
| day^5 |
0.951 |
0.076 |
-0.666 |
0.513 |
0.818 |
1.103 |
| day^6 |
0.985 |
0.075 |
-0.206 |
0.839 |
0.850 |
1.140 |
| avgtemp |
1.006 |
0.006 |
1.054 |
0.303 |
0.995 |
1.017 |
| newprecip |
0.727 |
0.076 |
-4.207 |
0.000 |
0.626 |
0.842 |
After correcting for over-dispersion:
The weekday linear contrast (day.L) remains significant, suggesting a
genuine weekly pattern in cyclist counts.
The temperature effect (IRR ≈ 1.006) becomes statistically
non-significant, indicating a modest upward trend that is overshadowed
by variability.
newprecip IRR = 0.727 remains strongly significant, confirming that
rain meaningfully reduces cyclist counts even after adjusting for
weekday and temperature.
This model offers a more realistic assessment of which predictors
meaningfully influence cyclist traffic.
Quasi-Poisson
Rate Model (Offset Included)
kable(tidy(m_quasi_rate, conf.int=TRUE, exponentiate=TRUE),
digits=3, caption="Quasi-Poisson Rate Model IRRs")
Quasi-Poisson Rate Model IRRs
| (Intercept) |
0.272 |
0.165 |
-7.879 |
0.000 |
0.197 |
0.376 |
| day.L |
1.005 |
0.028 |
0.176 |
0.862 |
0.952 |
1.060 |
| day.Q |
0.949 |
0.028 |
-1.895 |
0.071 |
0.899 |
1.002 |
| day.C |
0.972 |
0.029 |
-0.964 |
0.345 |
0.918 |
1.030 |
| day^4 |
0.991 |
0.028 |
-0.341 |
0.737 |
0.938 |
1.046 |
| day^5 |
1.017 |
0.028 |
0.596 |
0.557 |
0.962 |
1.075 |
| day^6 |
1.013 |
0.028 |
0.471 |
0.642 |
0.959 |
1.070 |
| avgtemp |
0.998 |
0.002 |
-0.755 |
0.458 |
0.994 |
1.003 |
| newprecip |
1.049 |
0.028 |
1.697 |
0.104 |
0.992 |
1.108 |
The quasi-Poisson rate model includes log(exposure) as an offset,
allowing us to analyze cycling rates per unit traffic.
Key findings:
Weekday contrasts lose significance, suggesting cycling rates are
more stable across the week than raw counts.
Temperature shows a near-null rate effect.
Precipitation no longer significantly reduces the cycling rate (p =
0.104), though the direction remains consistent with smaller volume on
rainy days.
Importantly, the precipitation IRR shifts slightly above 1, but
remains statistically non-significant. This does not contradict earlier
results; rather, it indicates:
Rain reduces total counts because overall traffic volume also
drops.
Relative cyclist share among total traffic may remain stable.
This nuance enhances the interpretation and is crucial for
understanding behavioral patterns.
To synthesize the results:
Poisson model overstates significance across all predictors due to
severe over-dispersion.
Quasi-Poisson model provides valid inference and confirms rainfall
and weekday patterns as meaningful drivers.
Quasi-Poisson rate model offers the most conservative and realistic
inference, adjusting for traffic volume and controlling
over-dispersion.
The rate model is therefore the final recommended model for
interpretation. # Model-Based Effect Visualization
Rationale
Pairwise plots ignore confounding; predictions from the fitted model
show adjusted relationships.
Predicted Counts vs
Temperature
temp_seq <- seq(quantile(dat$avgtemp,.05), quantile(dat$avgtemp,.95), length.out=50)
newdat <- expand_grid(avgtemp=temp_seq, newprecip=c(0,1)) %>%
mutate(day=factor("Wednesday", levels=levels(dat$day), ordered=TRUE),
exposure=median(dat$exposure, na.rm=TRUE))
newdat$pred <- predict(m_quasi_rate, newdata=newdat, type="response")
ggplot(newdat, aes(avgtemp, pred, color=factor(newprecip))) +
geom_line(size=1) +
labs(title="Predicted Counts vs Temperature",
x="Avg Temp", y="Predicted Count",
color="newprecip")

Interpretation: Even after adjusting for day +
exposure, rain depresses counts strongly across all temperatures.
Results and
Conclusions
Connection to Research Questions. RQ1: Weekday patterns and
precipitation significantly affect cyclist volume, while temperature
shows only a modest influence. RQ2: The Poisson model is not appropriate
due to extreme over-dispersion (φ ≈ 109), and the quasi-Poisson approach
successfully corrects the underestimated standard errors. RQ3: Including
an exposure offset alters interpretation by modeling cycling rates
instead of raw counts; rainy days reduce total counts but do not
significantly reduce cycling rate after adjusting for traffic
volume.
Key Findings
-Cyclist counts are highly over-dispersed; Poisson inference is
invalid without correction.
-The quasi-Poisson GLM provides reliable inference and shows:
-Rain significantly decreases daily cyclist counts.
-Weekday patterns persist after correcting for over-dispersion.
-Temperature effects are mild and statistically uncertain.
When adjusting for exposure, precipitation no longer significantly
predicts cycling rate, highlighting the advantage of interpreting rates
rather than raw counts.
Final Model
Recommendation
Based on corrected dispersion, interpretability, and adjustment for
exposure, the quasi-Poisson rate model with a log(exposure) offset is
the final chosen model for this analysis. This model provides the most
reliable inference and best reflects cycling behavior per unit of
traffic flow
Modeling cyclist rates rather than raw counts allows us to interpret
cycling activity relative to overall traffic volume, ensuring that
changes in total roadway use do not obscure actual behavioral patterns
among cyclists.
Although precipitation has a strong negative effect on total cyclist
counts, its effect on cycling rates becomes statistically
non-significant once exposure is included. This shift indicates that
rainy days reduce overall traffic volume across all modes, not only
bicycles; therefore, cyclists may represent a similar share of total
traffic even though their absolute numbers decline.
Assumptions
Check
The quasi-Poisson rate model reasonably satisfies the generalized
linear model assumptions. Daily observations are independent, and visual
diagnostics confirm no serious violation of log-linearity under the log
link. Zero inflation is not a concern because cyclist counts are always
well above zero. The quasi-Poisson variance structure appropriately
addresses over-dispersion, producing standard errors that reflect true
uncertainty in the data.
Practical
Implications
- Rain → major drop in cyclists → infrastructure should support
wet-weather riding.
- Temperature influences counts but less strongly.
- Weekday cycling demand is patterned → important for planning.
LS0tDQp0aXRsZTogIkEgUXVhc2ktUG9pc3NvbiBBcHByb2FjaCB0byBJbnZlc3RpZ2F0aW5nIEN5Y2xpc3QgQ291bnRzIG9uIHRoZSBRdWVlbnNib3JvIEJyaWRnZSINCmF1dGhvcjogIlJ5YW4gR29ybWFuIg0KZGF0ZTogIjIwMjUtMTEtMTIiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQotLS0NCg0KYGBgez1odG1sfQ0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCmgxLnRpdGxlIHsgZm9udC1zaXplOiAyNHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IERhcmtSZWQ7IHRleHQtYWxpZ246IGNlbnRlcjsgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOyB9DQpoNC5hdXRob3IgeyBmb250LXNpemU6IDIwcHg7IGZvbnQtd2VpZ2h0OiBib2xkOyBjb2xvcjogRGFya1JlZDsgdGV4dC1hbGlnbjogY2VudGVyOyB9DQpoNC5kYXRlIHsgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IERhcmtCbHVlOyB0ZXh0LWFsaWduOiBjZW50ZXI7IH0NCmgxIHsgZm9udC1zaXplOiAyMnB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IG5hdnk7IHRleHQtYWxpZ246IGxlZnQ7IH0NCmgyIHsgZm9udC1zaXplOiAyMHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IG5hdnk7IHRleHQtYWxpZ246IGxlZnQ7IH0NCmgzIHsgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IG5hdnk7IHRleHQtYWxpZ246IGxlZnQ7IH0NCmg0IHsgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IGRhcmtyZWQ7IHRleHQtYWxpZ246IGxlZnQ7IH0NCmJvZHkgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0NCjwvc3R5bGU+DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpuZWVkZWQgPC0gYygia25pdHIiLCJ0aWR5dmVyc2UiLCJyZWFkeGwiLCJsdWJyaWRhdGUiLCJicm9vbSIsInBhbmRlciIpDQpmb3IgKHAgaW4gbmVlZGVkKSB7IGlmICghcmVxdWlyZShwLCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKSB7DQppbnN0YWxsLnBhY2thZ2VzKHAsIHJlcG9zID0gImh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZyIpOyBsaWJyYXJ5KHAsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSl9IH0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9ImFzaXMiLCBmaWcuYWxpZ249ImNlbnRlciIpDQpzZXQuc2VlZCgzMjEpDQpgYGANCg0KIyAgSW50cm9kdWN0aW9uDQoNClRoaXMgcHJvamVjdCBpbnZlc3RpZ2F0ZXMgaG93IHdlZWtkYXkgcGF0dGVybnMgYW5kIHdlYXRoZXIgY29uZGl0aW9ucyBhZmZlY3QgZGFpbHkgY3ljbGlzdCBjb3VudHMgb24gdGhlIFF1ZWVuc2Jvcm8gQnJpZGdlIGluIE5ldyBZb3JrIENpdHkuIEJlY2F1c2UgY3ljbGlzdCB0cmFmZmljIGlzIGEgY291bnQgdmFyaWFibGUgdGhhdCBjYW4gYmUgaW5mbHVlbmNlZCBieSBtdWx0aXBsZSBlbnZpcm9ubWVudGFsIGFuZCBiZWhhdmlvcmFsIGZhY3RvcnMsIG91ciBhbmFseXNpcyBjb21iaW5lcyBQb2lzc29uIGFuZCBxdWFzaS1Qb2lzc29uIGdlbmVyYWxpemVkIGxpbmVhciBtb2RlbHMgdG8gZXZhbHVhdGUgaG93IHRoZSBudW1iZXIgb2YgY3ljbGlzdHMgY2hhbmdlcyB3aXRoIGRheSBvZiB0aGUgd2VlaywgYXZlcmFnZSB0ZW1wZXJhdHVyZSwgcHJlY2lwaXRhdGlvbiwgYW5kIHRvdGFsIHJvYWR3YXkgZXhwb3N1cmUuDQoNCldlIGFkZHJlc3MgdGhyZWUgY29yZSByZXNlYXJjaCBxdWVzdGlvbnM6DQoNCkRvIGN5Y2xpc3QgY291bnRzIHZhcnkgc3lzdGVtYXRpY2FsbHkgYnkgd2Vla2RheSwgdGVtcGVyYXR1cmUsIGFuZCBwcmVjaXBpdGF0aW9uPw0KDQpJcyB0aGUgc3RhbmRhcmQgUG9pc3NvbiBtb2RlbCBhcHByb3ByaWF0ZSwgb3IgaXMgb3Zlci1kaXNwZXJzaW9uIHNvIHNldmVyZSB0aGF0IGluZmVyZW5jZSBiZWNvbWVzIHVucmVsaWFibGUgd2l0aG91dCBhZGp1c3RtZW50Pw0KDQpEb2VzIGluY29ycG9yYXRpbmcgdHJhZmZpYyBleHBvc3VyZSB0aHJvdWdoIGFuIG9mZnNldCB0ZXJtIG1lYW5pbmdmdWxseSBjaGFuZ2UgY29uY2x1c2lvbnMgYWJvdXQgd2hpY2ggcHJlZGljdG9ycyBtYXR0ZXI/DQoNCkJ5IGNvbXBhcmluZyBQb2lzc29uLCBxdWFzaS1Qb2lzc29uLCBhbmQgcXVhc2ktUG9pc3NvbiByYXRlIG1vZGVscywgd2UgYWltIHRvIGRldGVybWluZSB3aGljaCBtb2RlbGluZyBmcmFtZXdvcmsgcHJvdmlkZXMgdGhlIG1vc3QgdHJ1c3R3b3J0aHkgaW5mZXJlbmNlIHdoaWxlIG9mZmVyaW5nIGEgcHJhY3RpY2FsIGludGVycHJldGF0aW9uIG9mIGhvdyB3ZWF0aGVyIGFuZCB3ZWVrbHkgcGF0dGVybnMgc2hhcGUgY3ljbGluZyBiZWhhdmlvci4NCg0KIyAgRGF0YSBhbmQgVmFyaWFibGVzDQoNCiMjICBEYXRhIFNvdXJjZQ0KDQpUaGUgZGF0YXNldCBjb250YWlucyBkYWlseSBvYnNlcnZhdGlvbnMgb2YgY3ljbGlzdCBjb3VudHMgY3Jvc3NpbmcgdGhlIFF1ZWVuc2Jvcm8gQnJpZGdlIGFsb25nIHdpdGggYXNzb2NpYXRlZCB3ZWF0aGVyIHZhcmlhYmxlcyBhbmQgdG90YWwgdHJhZmZpYyBleHBvc3VyZS4gQmVjYXVzZSBvYnNlcnZhdGlvbnMgYXJlIGFnZ3JlZ2F0ZWQgYnkgZGF5LCBlYWNoIHJvdyByZXByZXNlbnRzIGEgZGlzdGluY3QgbWVhc3VyZW1lbnQgb2YgZW52aXJvbm1lbnRhbCBhbmQgdHJhZmZpYyBjb25kaXRpb25zLg0KYGBge3IgZGF0YS1pbXBvcnR9DQpkYXRhX3BhdGggPC0gIkM6L1VzZXJzL3JnMDMvRG93bmxvYWRzL3N0YTMyMS9Qb2lzc29uRGF0YS54bHN4Ig0KcmF3IDwtIHJlYWRfZXhjZWwoZGF0YV9wYXRoKQ0KZGltKHJhdykNCmBgYA0KDQojIyAgVmFyaWFibGUgRGVmaW5pdGlvbnMNCg0KVG8gZW5zdXJlIGNsYXJpdHkgYW5kIHJlcHJvZHVjaWJpbGl0eSwgYWxsIHZhcmlhYmxlcyB1c2VkIGluIHRoZSBhbmFseXNpcyBhcmUgbGlzdGVkIGJlbG93IHdpdGggbmFtZXMsIGRlc2NyaXB0aW9ucywgYW5kIGRhdGEgdHlwZXM6DQoNCmNvdW50IChpbnRlZ2VyKSDigJQgVG90YWwgbnVtYmVyIG9mIGN5Y2xpc3RzIGNvdW50ZWQgdGhhdCBkYXkuDQoNCmV4cG9zdXJlIChudW1lcmljKSDigJQgVG90YWwgdHJhZmZpYyB2b2x1bWUgb3IgZXhwb3N1cmUgdXNlZCBhcyBhbiBvZmZzZXQgaW4gcmF0ZSBtb2RlbHMuDQoNCmF2Z3RlbXAgKG51bWVyaWMpIOKAlCBBdmVyYWdlIGRhaWx5IHRlbXBlcmF0dXJlLCBjb21wdXRlZCBhcyB0aGUgbWVhbiBvZiBoaWdoIGFuZCBsb3cgdGVtcGVyYXR1cmVzLg0KDQpuZXdwcmVjaXAgKGJpbmFyeSBpbmRpY2F0b3IpIOKAlCAxIGlmIHByZWNpcGl0YXRpb24gPiAwOyAwIG90aGVyd2lzZS4NCg0KZGF5IChvcmRlcmVkIGZhY3Rvcikg4oCUIERheSBvZiB0aGUgd2VlayAoTW9uZGF5IHRocm91Z2ggU3VuZGF5KSwgY29kZWQgYXMgYW4gb3JkZXJlZCBmYWN0b3IgdG8gZGV0ZWN0IHNtb290aCB3ZWVrbHkgcGF0dGVybnMuDQoNCkJlY2F1c2UgZGF5IGlzIG9yZGVyZWQsIFIgZ2VuZXJhdGVzIG9ydGhvZ29uYWwgcG9seW5vbWlhbCBjb250cmFzdHMgc3VjaCBhczoNCg0KZGF5Lkwg4oCUIGxpbmVhciB3ZWVrZGF5IHRyZW5kLA0KDQpkYXkuUSDigJQgcXVhZHJhdGljIHdlZWtseSBjdXJ2YXR1cmUsDQoNCmRheS5DLCBkYXleNCwgZXRjLiDigJQgaGlnaGVyLW9yZGVyIGN5Y2xpY2FsIHBhdHRlcm5zLg0KDQpUaGVzZSB0ZXJtcyBhcHBlYXIgaW4gdGhlIG1vZGVsIG91dHB1dCBidXQgYXJlIG5vdCBzdGFuZGFsb25lIHZhcmlhYmxlcy4gVGhleSByZXByZXNlbnQgc3RydWN0dXJlZCBjb250cmFzdHMgdGhhdCBjYXB0dXJlIGhvdyBjeWNsaXN0IGNvdW50cyBzaGlmdCBhY3Jvc3MgdGhlIHdlZWsuDQoNCiMjICBEYXRhIFByb2Nlc3NpbmcNCg0KQWxsIHByZXByb2Nlc3Npbmcgc3RlcHMgd2VyZSBleHBsaWNpdGx5IGRvY3VtZW50ZWQ6DQoNClZhcmlhYmxlIG5hbWVzIHdlcmUgc3RhbmRhcmRpemVkIHRvIGxvd2VyIGNhc2UgYW5kIHNpbXBsaWZpZWQgZm9yIGNvbnNpc3RlbmN5Lg0KDQpUZW1wZXJhdHVyZSB2YXJpYWJsZXMgd2VyZSBjb21iaW5lZCBpbnRvIGEgc2luZ2xlLCBpbnRlcnByZXRhYmxlIHZhcmlhYmxlIChhdmd0ZW1wKS4NCg0KUHJlY2lwaXRhdGlvbiB3YXMgY29udmVydGVkIHRvIGEgYmluYXJ5IGluZGljYXRvciB0byBjYXB0dXJlIHRoZSBtYWluIGVmZmVjdCBvZiByYWluIHZzLiBkcnkgY29uZGl0aW9ucy4NCg0KZGF5IHdhcyBlbmNvZGVkIGFzIGFuIG9yZGVyZWQgZmFjdG9yIHRvIGNhcHR1cmUgd2Vla2x5IHN0cnVjdHVyZSB3aXRob3V0IGludHJvZHVjaW5nIHNldmVuIHNlcGFyYXRlIGR1bW15IHZhcmlhYmxlcy4NCg0KT25seSByb3dzIHdpdGggY29tcGxldGUgaW5mb3JtYXRpb24gd2VyZSByZXRhaW5lZC4NCg0KVGhpcyBwcmVwcm9jZXNzaW5nIGVuc3VyZXMgdGhlIGZpbmFsIGRhdGFzZXQgaXMgY2xlYW4sIGludGVycHJldGFibGUsIGFuZCByZWFkeSBmb3IgZ2VuZXJhbGl6ZWQgbGluZWFyIG1vZGVsaW5nLg0KDQpgYGB7ciBkYXRhLXByb2Nlc3Npbmd9DQpubSA8LSBuYW1lcyhyYXcpDQpubSA8LSB0b2xvd2VyKG5tKQ0Kbm0gPC0gZ3N1YigiW1s6c3BhY2U6XV0rIiwgIl8iLCBubSkNCm5tIDwtIGdzdWIoIlteYS16MC05X10iLCAiIiwgbm0pDQpubSA8LSBnc3ViKCJfKyIsICJfIiwgbm0pDQpubSA8LSBnc3ViKCJeXyt8XyskIiwgIiIsIG5tKQ0KbmFtZXMocmF3KSA8LSBubQ0KDQpkYXQgPC0gcmF3ICU+JQ0KbXV0YXRlKA0KIGNvdW50ID0gYXMubnVtZXJpYyhxdWVlbnNib3JvYnJpZGdlKSwNCiBleHBvc3VyZSA9IGFzLm51bWVyaWModG90YWwpLA0KIGF2Z3RlbXAgPSAoYXMubnVtZXJpYyhoaWdodGVtcCkgKyBhcy5udW1lcmljKGxvd3RlbXApKS8yLA0KIG5ld3ByZWNpcCA9IGlmZWxzZShhcy5udW1lcmljKHByZWNpcGl0YXRpb24pID4gMCwgMUwsIDBMKSwNCiBkYXkgPSBmYWN0b3IoZGF5LCBsZXZlbHM9YygiTW9uZGF5IiwiVHVlc2RheSIsIldlZG5lc2RheSIsIlRodXJzZGF5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRnJpZGF5IiwiU2F0dXJkYXkiLCJTdW5kYXkiKSwNCiAgICAgICAgICAgICAgb3JkZXJlZD1UUlVFKQ0KKSAlPiUNCmZpbHRlcighaXMubmEoY291bnQpLCAhaXMubmEoYXZndGVtcCksICFpcy5uYShuZXdwcmVjaXApLCAhaXMubmEoZGF5KSkNCg0Ka2FibGUoaGVhZChkYXQpLCBjYXB0aW9uPSJQcmV2aWV3IG9mIHByb2Nlc3NlZCBkYXRhIikNCmBgYA0KVGhlIGZpcnN0IHNpeCByb3dzIGNvbmZpcm0gdGhhdCBhbGwgcHJlcHJvY2Vzc2luZyBzdGVwcyB3ZXJlIGFwcGxpZWQgY29ycmVjdGx5OiBjb3VudCBhbmQgZXhwb3N1cmUgd2VyZSBhY2N1cmF0ZWx5IGNvbnZlcnRlZCB0byBudW1lcmljIHZhcmlhYmxlcywgYXZndGVtcCByZWZsZWN0cyB0aGUgYXZlcmFnZSBvZiBoaWdoIGFuZCBsb3cgdGVtcGVyYXR1cmVzLCBuZXdwcmVjaXAgY29ycmVjdGx5IGluZGljYXRlcyByYWlueSB2cy4gZHJ5IGRheXMsIGFuZCBkYXkgaXMgcHJvcGVybHkgZW5jb2RlZCBhcyBhbiBvcmRlcmVkIGZhY3Rvci4gVGhlc2UgY2hlY2tzIGVuc3VyZSB0aGUgZGF0YXNldCBpcyBjbGVhbiBhbmQgcmVhZHkgZm9yIEdMTSBtb2RlbGluZy4NCiMgIEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMNCg0KIyMgIFJhdGlvbmFsZQ0KRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcyAoRURBKSBwcm92aWRlcyBhbiBpbml0aWFsIHVuZGVyc3RhbmRpbmcgb2YgaG93IGN5Y2xpc3QgY291bnRzIGJlaGF2ZSByZWxhdGl2ZSB0byB3ZWVrZGF5IHBhdHRlcm5zLCB0ZW1wZXJhdHVyZSwgYW5kIHByZWNpcGl0YXRpb24uIFdoaWxlIHBhaXJ3aXNlIHBsb3RzIGNhbm5vdCBlc3RhYmxpc2ggY2F1c2FsIG9yIGFkanVzdGVkIHJlbGF0aW9uc2hpcHMsIHRoZXkgaWRlbnRpZnkgYnJvYWQgdHJlbmRzLCBwb3RlbnRpYWwgbm9ubGluZWFyaXR5LCBhbmQgc291cmNlcyBvZiB2YXJpYWJpbGl0eSB0aGF0IG11c3QgYmUgYWNjb3VudGVkIGZvciBpbiB0aGUgR0xNIGZyYW1ld29yay4NCg0KDQoNCiMjICBDeWNsaXN0IENvdW50cyBieSBEYXkNClZpc3VhbGl6aW5nIGNvdW50cyBieSB3ZWVrZGF5IHN1Z2dlc3RzIHRoYXQgY3ljbGlzdCB2b2x1bWUgdGVuZHMgdG8gYmUgaGlnaGVyIG9uIHdlZWtkYXlzIHRoYW4gd2Vla2VuZHMsIHRob3VnaCB2YXJpYWJpbGl0eSBpcyBzdWJzdGFudGlhbCBhY3Jvc3MgYWxsIGRheXMuIFRoaXMgYWxpZ25zIHdpdGggZXhwZWN0YXRpb25zIGZvciBjb21tdXRlciBwYXR0ZXJucyBidXQgY2Fubm90IHlldCBkaXN0aW5ndWlzaCB3aGV0aGVyIGRheS1vZi13ZWVrIGRpZmZlcmVuY2VzIHBlcnNpc3QgYWZ0ZXIgYWRqdXN0aW5nIGZvciB3ZWF0aGVyIGFuZCBleHBvc3VyZQ0KYGBge3IgZWRhLWRheX0NCmdncGxvdChkYXQsIGFlcyhkYXksIGNvdW50KSkgKyBnZW9tX2JveHBsb3QoKSArDQpsYWJzKHRpdGxlPSJDeWNsaXN0IENvdW50cyBieSBEYXkiLCB4PSJEYXkiLCB5PSJDb3VudCIpDQpgYGANCg0KKipJbnRlcnByZXRhdGlvbjoqKiBXZWVrZGF5cyBzaG93IHNvbWV3aGF0IGhpZ2hlciBtZWRpYW4gY291bnRzLCBidXQgdmFyaWFiaWxpdHkgaXMgbGFyZ2UuIEEgZm9ybWFsIG1vZGVsIGlzIG5lZWRlZC4NCg0KIyMgIENvdW50cyB2cyBUZW1wZXJhdHVyZQ0KQ3ljbGlzdCB2b2x1bWUgcmlzZXMgd2l0aCB0ZW1wZXJhdHVyZSwgcGFydGljdWxhcmx5IGFzIGNvbmRpdGlvbnMgd2FybSBmcm9tIGNvb2xlciBkYXlzIGludG8gbW9kZXJhdGUgdGVtcGVyYXR1cmVzLiBIb3dldmVyLCB0aGUgbGFyZ2Ugc3ByZWFkIGluIGNvdW50cyBhdCBhbnkgZ2l2ZW4gdGVtcGVyYXR1cmUgaW5kaWNhdGVzIHRoYXQgdGVtcGVyYXR1cmUgYWxvbmUgY2Fubm90IGV4cGxhaW4gdGhlIGZ1bGwgdmFyaWF0aW9uIGluIGN5Y2xpbmcgcGF0dGVybnPigJRyZWluZm9yY2luZyB0aGUgbmVlZCBmb3IgbXVsdGl2YXJpYWJsZSBtb2RlbHMuDQpgYGB7ciBlZGEtdGVtcH0NCmdncGxvdChkYXQsIGFlcyhhdmd0ZW1wLCBjb3VudCkpICsgZ2VvbV9wb2ludChhbHBoYT0uNSkgKw0KZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPUZBTFNFKSArDQpsYWJzKHRpdGxlPSJDb3VudHMgdnMgVGVtcGVyYXR1cmUiLCB4PSJBdmcgVGVtcCAowrBGKSIsIHk9IkNvdW50IikNCmBgYA0KDQoqKkludGVycHJldGF0aW9uOioqIFdhcm1lciBkYXlzIHRyZW5kIHVwd2FyZCwgYnV0IHZhcmlhdGlvbiBpcyB3aWRlIOKGkiBzdWdnZXN0cyBtdWx0aXBsZSBwcmVkaWN0b3JzIG1hdHRlciBqb2ludGx5Lg0KDQojIyAgQ291bnRzIGJ5IFByZWNpcGl0YXRpb24NClJhaW55IGRheXMgY2xlYXJseSBzaG93IGxvd2VyIGN5Y2xpc3QgY291bnRzIHRoYW4gZHJ5IGRheXMuIFRoaXMgc3Ryb25nIHBhaXJ3aXNlIGNvbnRyYXN0IHN1Z2dlc3RzIHByZWNpcGl0YXRpb24gaXMgYSBrZXkgZHJpdmVyIG9mIGN5Y2xpbmcgYmVoYXZpb3IuIExhdGVyIG1vZGVsaW5nIHdpbGwgZGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBlZmZlY3QgcmVtYWlucyBhZnRlciBhY2NvdW50aW5nIGZvciB3ZWVrZGF5IHN0cnVjdHVyZSwgZXhwb3N1cmUsIGFuZCB0ZW1wZXJhdHVyZS4NCmBgYHtyIGVkYS1wcmVjaXB9DQpnZ3Bsb3QoZGF0LCBhZXMoZmFjdG9yKG5ld3ByZWNpcCksIGNvdW50KSkgKyBnZW9tX2JveHBsb3QoKSArDQpsYWJzKHRpdGxlPSJDb3VudHMgYnkgUHJlY2lwaXRhdGlvbiIsIHg9IjA9RHJ5IC8gMT1XZXQiLCB5PSJDb3VudCIpDQpgYGANCg0KKipJbnRlcnByZXRhdGlvbjoqKiBSYWluIGNsZWFybHkgbG93ZXJzIGNvdW50cy4NCg0KIyAgUG9pc3NvbiBhbmQgUXVhc2ktUG9pc3NvbiBNb2RlbHMNCg0KIyMgIFJhdGlvbmFsZQ0KQ3ljbGlzdCBjb3VudHMgYXJlIG5vbi1uZWdhdGl2ZSBpbnRlZ2VycywgbWFraW5nIFBvaXNzb24gcmVncmVzc2lvbiBhIG5hdHVyYWwgc3RhcnRpbmcgcG9pbnQuIEhvd2V2ZXIsIFBvaXNzb24gbW9kZWxzIGFzc3VtZSBlcXVhbGl0eSBvZiB0aGUgbWVhbiBhbmQgdmFyaWFuY2U6IFZhcihZKT1NZWFuKFkpLiBXaGVuIHRoZSB2YXJpYW5jZSBkcmFtYXRpY2FsbHkgZXhjZWVkcyB0aGUgbWVhbuKAlGEgcGhlbm9tZW5vbiBrbm93biBhcyBvdmVyLWRpc3BlcnNpb27igJRzdGFuZGFyZCBlcnJvcnMgYmVjb21lIHNldmVyZWx5IHVuZGVyZXN0aW1hdGVkLCBhcnRpZmljaWFsbHkgaW5mbGF0aW5nIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZS4gQSBxdWFzaS1Qb2lzc29uIG1vZGVsIGNvcnJlY3RzIHRoaXMgYnkgaW50cm9kdWNpbmcgYSBkaXNwZXJzaW9uIHBhcmFtZXRlcjogz4YuVGhpcyBtb2RlbCBwcmVzZXJ2ZXMgdGhlIG1lYW4gc3RydWN0dXJlIG9mIHRoZSBQb2lzc29uIEdMTSB3aGlsZSBwcm92aWRpbmcgdmFsaWQgaW5mZXJlbmNlIGV2ZW4gd2hlbiBkaXNwZXJzaW9uIGlzIGxhcmdlLiBBZGRpdGlvbmFsbHksIGluY29ycG9yYXRpbmcgYW4gb2Zmc2V0IHVzaW5nIGxvZyhleHBvc3VyZSkgZW5hYmxlcyBtb2RlbGluZyBvZiBjeWNsaW5nIHJhdGUgcGVyIHVuaXQgdHJhZmZpYywgd2hpY2ggaXMgZXNzZW50aWFsIGZvciB1bmRlcnN0YW5kaW5nIGN5Y2xpc3QgYmVoYXZpb3IgcmVsYXRpdmUgdG8gdG90YWwgdHJhZmZpYyBmbG93Lg0KDQojIyAgRml0IFBvaXNzb24gJiBRdWFzaS1Qb2lzc29uIE1vZGVscw0KYGBge3IgbW9kZWxzLWZpdH0NCm1fcG9pcyA8LSBnbG0oY291bnQgfiBkYXkgKyBhdmd0ZW1wICsgbmV3cHJlY2lwLA0KICAgICAgICAgICAgICBmYW1pbHk9cG9pc3NvbihsaW5rPSJsb2ciKSwgZGF0YT1kYXQpDQoNCm1fcXVhc2kgPC0gZ2xtKGNvdW50IH4gZGF5ICsgYXZndGVtcCArIG5ld3ByZWNpcCwNCiAgICAgICAgICAgICAgIGZhbWlseT1xdWFzaXBvaXNzb24obGluaz0ibG9nIiksIGRhdGE9ZGF0KQ0KDQptX3F1YXNpX3JhdGUgPC0gZ2xtKGNvdW50IH4gZGF5ICsgYXZndGVtcCArIG5ld3ByZWNpcCArDQogICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0KGxvZyhleHBvc3VyZSkpLA0KICAgICAgICAgICAgICAgICAgICBmYW1pbHk9cXVhc2lwb2lzc29uKGxpbms9ImxvZyIpLA0KICAgICAgICAgICAgICAgICAgICBkYXRhPWRhdCAlPiUgZmlsdGVyKCFpcy5uYShleHBvc3VyZSksIGV4cG9zdXJlPjApKQ0KDQpwaGlfaGF0IDwtIHN1bShyZXNpZHVhbHMobV9wb2lzLCB0eXBlPSJwZWFyc29uIileMikgLyBtX3BvaXMkZGYucmVzaWR1YWwNCmthYmxlKGRhdGEuZnJhbWUoRGlzcGVyc2lvbj1yb3VuZChwaGlfaGF0LDIpKSwNCiAgICAgIGNhcHRpb249IkVzdGltYXRlZCBPdmVyLURpc3BlcnNpb24gz4YiKQ0KYGBgDQoNClRoZSBkaXNwZXJzaW9uIGVzdGltYXRlIGZyb20gdGhlIFBvaXNzb24gbW9kZWwgaXM68J2cmT0xMDkuMTEuVGhpcyBtZWFucyB0aGUgdmFyaWFuY2Ugb2YgY3ljbGlzdCBjb3VudHMgaXMgbW9yZSB0aGFuIDEwMCB0aW1lcyBsYXJnZXIgdGhhbiB0aGUgbWVhbiwgcmVuZGVyaW5nIFBvaXNzb24tYmFzZWQgaW5mZXJlbmNlIHVucmVsaWFibGUuIENvbnNlcXVlbmNlcyBpbmNsdWRlOg0KDQotTWlzbGVhZGluZ2x5IHNtYWxsIHAtdmFsdWVzDQoNCi1OYXJyb3dlZCBjb25maWRlbmNlIGludGVydmFscw0KDQotT3ZlcnN0YXRlZCBzaWduaWZpY2FuY2UgZm9yIHNldmVyYWwgcHJlZGljdG9ycw0KDQotSW5mbGF0ZWQgVHlwZSBJIGVycm9yIHJhdGUNCg0KQmVjYXVzZSBvZiB0aGlzIGV4dHJlbWUgb3Zlci1kaXNwZXJzaW9uLCB0aGUgcXVhc2ktUG9pc3NvbiBmcmFtZXdvcmsgaXMgZXNzZW50aWFsIGZvciBkcmF3aW5nIHZhbGlkIGNvbmNsdXNpb25zLg0KDQojIyAgUG9pc3NvbiBJUlJzIChmb3IgY29tcGFyaXNvbikNCmBgYHtyIHBvaXNzb24tdGFibGV9DQprYWJsZSh0aWR5KG1fcG9pcywgY29uZi5pbnQ9VFJVRSwgZXhwb25lbnRpYXRlPVRSVUUpLA0KICAgICAgZGlnaXRzPTMsIGNhcHRpb249IlBvaXNzb24gSVJScyIpDQpgYGANCg0KVGhlIFBvaXNzb24gbW9kZWwgc3VnZ2VzdHMgYWxtb3N0IGV2ZXJ5IHRlcm0gaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCwgaW5jbHVkaW5nIGFsbCBwb2x5bm9taWFsIHdlZWtkYXkgY29udHJhc3RzLCB0ZW1wZXJhdHVyZSwgYW5kIHByZWNpcGl0YXRpb24uIEhvd2V2ZXIsIGR1ZSB0byDPhiA+IDEwMCwgdGhlc2UgcmVzdWx0cyByZXByZXNlbnQgZmFsc2UgcHJlY2lzaW9uIGFuZCBjYW5ub3QgYmUgdHJ1c3RlZC4NCg0KVGhlc2UgcmVzdWx0cyBzZXJ2ZSBvbmx5IGFzIGEgY29tcGFyaXNvbiBwb2ludCwgZGVtb25zdHJhdGluZyB3aGF0IGhhcHBlbnMgd2hlbiBvdmVyLWRpc3BlcnNpb24gaXMgaWdub3JlZC4NCg0KIyMgIFF1YXNpLVBvaXNzb24gSVJScyAobm8gb2Zmc2V0KQ0KYGBge3IgcXVhc2ktdGFibGV9DQprYWJsZSh0aWR5KG1fcXVhc2ksIGNvbmYuaW50PVRSVUUsIGV4cG9uZW50aWF0ZT1UUlVFKSwNCiAgICAgIGRpZ2l0cz0zLCBjYXB0aW9uPSJRdWFzaS1Qb2lzc29uIElSUnMiKQ0KYGBgDQoNCkFmdGVyIGNvcnJlY3RpbmcgZm9yIG92ZXItZGlzcGVyc2lvbjoNCg0KVGhlIHdlZWtkYXkgbGluZWFyIGNvbnRyYXN0IChkYXkuTCkgcmVtYWlucyBzaWduaWZpY2FudCwgc3VnZ2VzdGluZyBhIGdlbnVpbmUgd2Vla2x5IHBhdHRlcm4gaW4gY3ljbGlzdCBjb3VudHMuDQoNClRoZSB0ZW1wZXJhdHVyZSBlZmZlY3QgKElSUiDiiYggMS4wMDYpIGJlY29tZXMgc3RhdGlzdGljYWxseSBub24tc2lnbmlmaWNhbnQsIGluZGljYXRpbmcgYSBtb2Rlc3QgdXB3YXJkIHRyZW5kIHRoYXQgaXMgb3ZlcnNoYWRvd2VkIGJ5IHZhcmlhYmlsaXR5Lg0KDQpuZXdwcmVjaXAgSVJSID0gMC43MjcgcmVtYWlucyBzdHJvbmdseSBzaWduaWZpY2FudCwgY29uZmlybWluZyB0aGF0IHJhaW4gbWVhbmluZ2Z1bGx5IHJlZHVjZXMgY3ljbGlzdCBjb3VudHMgZXZlbiBhZnRlciBhZGp1c3RpbmcgZm9yIHdlZWtkYXkgYW5kIHRlbXBlcmF0dXJlLg0KDQpUaGlzIG1vZGVsIG9mZmVycyBhIG1vcmUgcmVhbGlzdGljIGFzc2Vzc21lbnQgb2Ygd2hpY2ggcHJlZGljdG9ycyBtZWFuaW5nZnVsbHkgaW5mbHVlbmNlIGN5Y2xpc3QgdHJhZmZpYy4NCg0KIyMgIFF1YXNpLVBvaXNzb24gKlJhdGUqIE1vZGVsIChPZmZzZXQgSW5jbHVkZWQpDQpgYGB7ciBxdWFzaS1yYXRlfQ0Ka2FibGUodGlkeShtX3F1YXNpX3JhdGUsIGNvbmYuaW50PVRSVUUsIGV4cG9uZW50aWF0ZT1UUlVFKSwNCiAgICAgIGRpZ2l0cz0zLCBjYXB0aW9uPSJRdWFzaS1Qb2lzc29uIFJhdGUgTW9kZWwgSVJScyIpDQpgYGANCg0KVGhlIHF1YXNpLVBvaXNzb24gcmF0ZSBtb2RlbCBpbmNsdWRlcyBsb2coZXhwb3N1cmUpIGFzIGFuIG9mZnNldCwgYWxsb3dpbmcgdXMgdG8gYW5hbHl6ZSBjeWNsaW5nIHJhdGVzIHBlciB1bml0IHRyYWZmaWMuDQoNCktleSBmaW5kaW5nczoNCg0KV2Vla2RheSBjb250cmFzdHMgbG9zZSBzaWduaWZpY2FuY2UsIHN1Z2dlc3RpbmcgY3ljbGluZyByYXRlcyBhcmUgbW9yZSBzdGFibGUgYWNyb3NzIHRoZSB3ZWVrIHRoYW4gcmF3IGNvdW50cy4NCg0KVGVtcGVyYXR1cmUgc2hvd3MgYSBuZWFyLW51bGwgcmF0ZSBlZmZlY3QuDQoNClByZWNpcGl0YXRpb24gbm8gbG9uZ2VyIHNpZ25pZmljYW50bHkgcmVkdWNlcyB0aGUgY3ljbGluZyByYXRlIChwID0gMC4xMDQpLCB0aG91Z2ggdGhlIGRpcmVjdGlvbiByZW1haW5zIGNvbnNpc3RlbnQgd2l0aCBzbWFsbGVyIHZvbHVtZSBvbiByYWlueSBkYXlzLg0KDQpJbXBvcnRhbnRseSwgdGhlIHByZWNpcGl0YXRpb24gSVJSIHNoaWZ0cyBzbGlnaHRseSBhYm92ZSAxLCBidXQgcmVtYWlucyBzdGF0aXN0aWNhbGx5IG5vbi1zaWduaWZpY2FudC4gVGhpcyBkb2VzIG5vdCBjb250cmFkaWN0IGVhcmxpZXIgcmVzdWx0czsgcmF0aGVyLCBpdCBpbmRpY2F0ZXM6DQoNClJhaW4gcmVkdWNlcyB0b3RhbCBjb3VudHMgYmVjYXVzZSBvdmVyYWxsIHRyYWZmaWMgdm9sdW1lIGFsc28gZHJvcHMuDQoNClJlbGF0aXZlIGN5Y2xpc3Qgc2hhcmUgYW1vbmcgdG90YWwgdHJhZmZpYyBtYXkgcmVtYWluIHN0YWJsZS4NCg0KVGhpcyBudWFuY2UgZW5oYW5jZXMgdGhlIGludGVycHJldGF0aW9uIGFuZCBpcyBjcnVjaWFsIGZvciB1bmRlcnN0YW5kaW5nIGJlaGF2aW9yYWwgcGF0dGVybnMuDQoNCg0KVG8gc3ludGhlc2l6ZSB0aGUgcmVzdWx0czoNCg0KUG9pc3NvbiBtb2RlbCBvdmVyc3RhdGVzIHNpZ25pZmljYW5jZSBhY3Jvc3MgYWxsIHByZWRpY3RvcnMgZHVlIHRvIHNldmVyZSBvdmVyLWRpc3BlcnNpb24uDQoNClF1YXNpLVBvaXNzb24gbW9kZWwgcHJvdmlkZXMgdmFsaWQgaW5mZXJlbmNlIGFuZCBjb25maXJtcyByYWluZmFsbCBhbmQgd2Vla2RheSBwYXR0ZXJucyBhcyBtZWFuaW5nZnVsIGRyaXZlcnMuDQoNClF1YXNpLVBvaXNzb24gcmF0ZSBtb2RlbCBvZmZlcnMgdGhlIG1vc3QgY29uc2VydmF0aXZlIGFuZCByZWFsaXN0aWMgaW5mZXJlbmNlLCBhZGp1c3RpbmcgZm9yIHRyYWZmaWMgdm9sdW1lIGFuZCBjb250cm9sbGluZyBvdmVyLWRpc3BlcnNpb24uDQoNClRoZSByYXRlIG1vZGVsIGlzIHRoZXJlZm9yZSB0aGUgZmluYWwgcmVjb21tZW5kZWQgbW9kZWwgZm9yIGludGVycHJldGF0aW9uLg0KIyAgTW9kZWwtQmFzZWQgRWZmZWN0IFZpc3VhbGl6YXRpb24NCg0KIyMgIFJhdGlvbmFsZQ0KUGFpcndpc2UgcGxvdHMgaWdub3JlIGNvbmZvdW5kaW5nOyBwcmVkaWN0aW9ucyBmcm9tIHRoZSBmaXR0ZWQgbW9kZWwgc2hvdyBhZGp1c3RlZCByZWxhdGlvbnNoaXBzLg0KDQojIyAgUHJlZGljdGVkIENvdW50cyB2cyBUZW1wZXJhdHVyZQ0KYGBge3IgZWZmZWN0LXRlbXB9DQp0ZW1wX3NlcSA8LSBzZXEocXVhbnRpbGUoZGF0JGF2Z3RlbXAsLjA1KSwgcXVhbnRpbGUoZGF0JGF2Z3RlbXAsLjk1KSwgbGVuZ3RoLm91dD01MCkNCg0KbmV3ZGF0IDwtIGV4cGFuZF9ncmlkKGF2Z3RlbXA9dGVtcF9zZXEsIG5ld3ByZWNpcD1jKDAsMSkpICU+JQ0KbXV0YXRlKGRheT1mYWN0b3IoIldlZG5lc2RheSIsIGxldmVscz1sZXZlbHMoZGF0JGRheSksIG9yZGVyZWQ9VFJVRSksDQogICAgICAgZXhwb3N1cmU9bWVkaWFuKGRhdCRleHBvc3VyZSwgbmEucm09VFJVRSkpDQoNCm5ld2RhdCRwcmVkIDwtIHByZWRpY3QobV9xdWFzaV9yYXRlLCBuZXdkYXRhPW5ld2RhdCwgdHlwZT0icmVzcG9uc2UiKQ0KDQpnZ3Bsb3QobmV3ZGF0LCBhZXMoYXZndGVtcCwgcHJlZCwgY29sb3I9ZmFjdG9yKG5ld3ByZWNpcCkpKSArDQpnZW9tX2xpbmUoc2l6ZT0xKSArDQpsYWJzKHRpdGxlPSJQcmVkaWN0ZWQgQ291bnRzIHZzIFRlbXBlcmF0dXJlIiwNCiAgICAgeD0iQXZnIFRlbXAiLCB5PSJQcmVkaWN0ZWQgQ291bnQiLA0KICAgICBjb2xvcj0ibmV3cHJlY2lwIikNCmBgYA0KDQoqKkludGVycHJldGF0aW9uOioqIEV2ZW4gYWZ0ZXIgYWRqdXN0aW5nIGZvciBkYXkgKyBleHBvc3VyZSwgcmFpbiBkZXByZXNzZXMgY291bnRzIHN0cm9uZ2x5IGFjcm9zcyBhbGwgdGVtcGVyYXR1cmVzLg0KDQojICBSZXN1bHRzIGFuZCBDb25jbHVzaW9ucw0KDQpDb25uZWN0aW9uIHRvIFJlc2VhcmNoIFF1ZXN0aW9ucy4NClJRMTogV2Vla2RheSBwYXR0ZXJucyBhbmQgcHJlY2lwaXRhdGlvbiBzaWduaWZpY2FudGx5IGFmZmVjdCBjeWNsaXN0IHZvbHVtZSwgd2hpbGUgdGVtcGVyYXR1cmUgc2hvd3Mgb25seSBhIG1vZGVzdCBpbmZsdWVuY2UuDQpSUTI6IFRoZSBQb2lzc29uIG1vZGVsIGlzIG5vdCBhcHByb3ByaWF0ZSBkdWUgdG8gZXh0cmVtZSBvdmVyLWRpc3BlcnNpb24gKM+GIOKJiCAxMDkpLCBhbmQgdGhlIHF1YXNpLVBvaXNzb24gYXBwcm9hY2ggc3VjY2Vzc2Z1bGx5IGNvcnJlY3RzIHRoZSB1bmRlcmVzdGltYXRlZCBzdGFuZGFyZCBlcnJvcnMuDQpSUTM6IEluY2x1ZGluZyBhbiBleHBvc3VyZSBvZmZzZXQgYWx0ZXJzIGludGVycHJldGF0aW9uIGJ5IG1vZGVsaW5nIGN5Y2xpbmcgcmF0ZXMgaW5zdGVhZCBvZiByYXcgY291bnRzOyByYWlueSBkYXlzIHJlZHVjZSB0b3RhbCBjb3VudHMgYnV0IGRvIG5vdCBzaWduaWZpY2FudGx5IHJlZHVjZSBjeWNsaW5nIHJhdGUgYWZ0ZXIgYWRqdXN0aW5nIGZvciB0cmFmZmljIHZvbHVtZS4NCg0KIyMgIEtleSBGaW5kaW5ncw0KLUN5Y2xpc3QgY291bnRzIGFyZSBoaWdobHkgb3Zlci1kaXNwZXJzZWQ7IFBvaXNzb24gaW5mZXJlbmNlIGlzIGludmFsaWQgd2l0aG91dCBjb3JyZWN0aW9uLg0KDQotVGhlIHF1YXNpLVBvaXNzb24gR0xNIHByb3ZpZGVzIHJlbGlhYmxlIGluZmVyZW5jZSBhbmQgc2hvd3M6DQoNCi1SYWluIHNpZ25pZmljYW50bHkgZGVjcmVhc2VzIGRhaWx5IGN5Y2xpc3QgY291bnRzLg0KDQotV2Vla2RheSBwYXR0ZXJucyBwZXJzaXN0IGFmdGVyIGNvcnJlY3RpbmcgZm9yIG92ZXItZGlzcGVyc2lvbi4NCg0KLVRlbXBlcmF0dXJlIGVmZmVjdHMgYXJlIG1pbGQgYW5kIHN0YXRpc3RpY2FsbHkgdW5jZXJ0YWluLg0KDQpXaGVuIGFkanVzdGluZyBmb3IgZXhwb3N1cmUsIHByZWNpcGl0YXRpb24gbm8gbG9uZ2VyIHNpZ25pZmljYW50bHkgcHJlZGljdHMgY3ljbGluZyByYXRlLCBoaWdobGlnaHRpbmcgdGhlIGFkdmFudGFnZSBvZiBpbnRlcnByZXRpbmcgcmF0ZXMgcmF0aGVyIHRoYW4gcmF3IGNvdW50cy4NCg0KIyMgIEZpbmFsIE1vZGVsIFJlY29tbWVuZGF0aW9uDQoNCkJhc2VkIG9uIGNvcnJlY3RlZCBkaXNwZXJzaW9uLCBpbnRlcnByZXRhYmlsaXR5LCBhbmQgYWRqdXN0bWVudCBmb3IgZXhwb3N1cmUsIHRoZSBxdWFzaS1Qb2lzc29uIHJhdGUgbW9kZWwgd2l0aCBhIGxvZyhleHBvc3VyZSkgb2Zmc2V0IGlzIHRoZSBmaW5hbCBjaG9zZW4gbW9kZWwgZm9yIHRoaXMgYW5hbHlzaXMuIFRoaXMgbW9kZWwgcHJvdmlkZXMgdGhlIG1vc3QgcmVsaWFibGUgaW5mZXJlbmNlIGFuZCBiZXN0IHJlZmxlY3RzIGN5Y2xpbmcgYmVoYXZpb3IgcGVyIHVuaXQgb2YgdHJhZmZpYyBmbG93DQoNCg0KTW9kZWxpbmcgY3ljbGlzdCByYXRlcyByYXRoZXIgdGhhbiByYXcgY291bnRzIGFsbG93cyB1cyB0byBpbnRlcnByZXQgY3ljbGluZyBhY3Rpdml0eSByZWxhdGl2ZSB0byBvdmVyYWxsIHRyYWZmaWMgdm9sdW1lLCBlbnN1cmluZyB0aGF0IGNoYW5nZXMgaW4gdG90YWwgcm9hZHdheSB1c2UgZG8gbm90IG9ic2N1cmUgYWN0dWFsIGJlaGF2aW9yYWwgcGF0dGVybnMgYW1vbmcgY3ljbGlzdHMuDQoNCkFsdGhvdWdoIHByZWNpcGl0YXRpb24gaGFzIGEgc3Ryb25nIG5lZ2F0aXZlIGVmZmVjdCBvbiB0b3RhbCBjeWNsaXN0IGNvdW50cywgaXRzIGVmZmVjdCBvbiBjeWNsaW5nIHJhdGVzIGJlY29tZXMgc3RhdGlzdGljYWxseSBub24tc2lnbmlmaWNhbnQgb25jZSBleHBvc3VyZSBpcyBpbmNsdWRlZC4gVGhpcyBzaGlmdCBpbmRpY2F0ZXMgdGhhdCByYWlueSBkYXlzIHJlZHVjZSBvdmVyYWxsIHRyYWZmaWMgdm9sdW1lIGFjcm9zcyBhbGwgbW9kZXMsIG5vdCBvbmx5IGJpY3ljbGVzOyB0aGVyZWZvcmUsIGN5Y2xpc3RzIG1heSByZXByZXNlbnQgYSBzaW1pbGFyIHNoYXJlIG9mIHRvdGFsIHRyYWZmaWMgZXZlbiB0aG91Z2ggdGhlaXIgYWJzb2x1dGUgbnVtYmVycyBkZWNsaW5lLg0KDQojIyBBc3N1bXB0aW9ucyBDaGVjaw0KDQpUaGUgcXVhc2ktUG9pc3NvbiByYXRlIG1vZGVsIHJlYXNvbmFibHkgc2F0aXNmaWVzIHRoZSBnZW5lcmFsaXplZCBsaW5lYXIgbW9kZWwgYXNzdW1wdGlvbnMuIERhaWx5IG9ic2VydmF0aW9ucyBhcmUgaW5kZXBlbmRlbnQsIGFuZCB2aXN1YWwgZGlhZ25vc3RpY3MgY29uZmlybSBubyBzZXJpb3VzIHZpb2xhdGlvbiBvZiBsb2ctbGluZWFyaXR5IHVuZGVyIHRoZSBsb2cgbGluay4gWmVybyBpbmZsYXRpb24gaXMgbm90IGEgY29uY2VybiBiZWNhdXNlIGN5Y2xpc3QgY291bnRzIGFyZSBhbHdheXMgd2VsbCBhYm92ZSB6ZXJvLiBUaGUgcXVhc2ktUG9pc3NvbiB2YXJpYW5jZSBzdHJ1Y3R1cmUgYXBwcm9wcmlhdGVseSBhZGRyZXNzZXMgb3Zlci1kaXNwZXJzaW9uLCBwcm9kdWNpbmcgc3RhbmRhcmQgZXJyb3JzIHRoYXQgcmVmbGVjdCB0cnVlIHVuY2VydGFpbnR5IGluIHRoZSBkYXRhLg0KDQojIyAgUHJhY3RpY2FsIEltcGxpY2F0aW9ucw0KLSBSYWluIOKGkiBtYWpvciBkcm9wIGluIGN5Y2xpc3RzIOKGkiBpbmZyYXN0cnVjdHVyZSBzaG91bGQgc3VwcG9ydCB3ZXQtd2VhdGhlciByaWRpbmcuICANCi0gVGVtcGVyYXR1cmUgaW5mbHVlbmNlcyBjb3VudHMgYnV0IGxlc3Mgc3Ryb25nbHkuICANCi0gV2Vla2RheSBjeWNsaW5nIGRlbWFuZCBpcyBwYXR0ZXJuZWQg4oaSIGltcG9ydGFudCBmb3IgcGxhbm5pbmcuDQoNCg0KIyAgTGltaXRhdGlvbnMgYW5kIEZ1dHVyZSBXb3JrDQotIExhY2tzIHdpbmQsIGhvbGlkYXkvZXZlbnQgaW5kaWNhdG9ycywgYXV0b2NvcnJlbGF0aW9uIG1vZGVsaW5nLiAgDQotIFBvbHlub21pYWwgZGF5IGNvbnRyYXN0cyBvYnNjdXJlIGluZGl2aWR1YWwtZGF5IGNvbXBhcmlzb25zLiAgDQotIEZ1dHVyZSBhbmFseXNlcyBzaG91bGQgdHJ5IG5lZ2F0aXZlIGJpbm9taWFsLCB0aW1lLXNlcmllcyBHTE1zLCBhbmQgaW50ZXJhY3Rpb25zLg0KDQoNCg==