1 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.

2 Data and Variables

2.1 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

2.2 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.

2.3 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
date day hightemp lowtemp precipitation queensborobridge total count exposure avgtemp newprecip
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

3 Exploratory Data Analysis

3.1 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.

3.2 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.

3.3 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.

3.4 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.

4 Poisson and Quasi-Poisson Models

4.1 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.

4.2 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 φ
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.

4.3 Poisson IRRs (for comparison)

kable(tidy(m_pois, conf.int=TRUE, exponentiate=TRUE),
      digits=3, caption="Poisson IRRs")
Poisson IRRs
term estimate std.error statistic p.value conf.low conf.high
(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.

4.4 Quasi-Poisson IRRs (no offset)

kable(tidy(m_quasi, conf.int=TRUE, exponentiate=TRUE),
      digits=3, caption="Quasi-Poisson IRRs")
Quasi-Poisson IRRs
term estimate std.error statistic p.value conf.low conf.high
(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.

4.5 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
term estimate std.error statistic p.value conf.low conf.high
(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

4.6 Rationale

Pairwise plots ignore confounding; predictions from the fitted model show adjusted relationships.

4.7 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.

5 Results and Conclusions

5.1 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.

5.2 Final Model Recommendation

The quasi-Poisson rate model with log(exposure) is the best model because it:

  • Corrects over-dispersion
  • Adjusts for exposure differences
  • Produces interpretable IRRs

5.3 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.

6 Limitations and Future Work

  • Lacks wind, holiday/event indicators, autocorrelation modeling.
  • Polynomial day contrasts obscure individual-day comparisons.
  • Future analyses should try negative binomial, time-series GLMs, and interactions.
LS0tDQp0aXRsZTogIkEgUXVhc2ktUG9pc3NvbiBBcHByb2FjaCB0byBJbnZlc3RpZ2F0aW5nIEN5Y2xpc3QgQ291bnRzIG9uIHRoZSBRdWVlbnNib3JvIEJyaWRnZSINCmF1dGhvcjogIlJ5YW4gR29ybWFuIg0KZGF0ZTogIjIwMjUtMTEtMTIiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQotLS0NCg0KYGBgez1odG1sfQ0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCmgxLnRpdGxlIHsgZm9udC1zaXplOiAyNHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IERhcmtSZWQ7IHRleHQtYWxpZ246IGNlbnRlcjsgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOyB9DQpoNC5hdXRob3IgeyBmb250LXNpemU6IDIwcHg7IGZvbnQtd2VpZ2h0OiBib2xkOyBjb2xvcjogRGFya1JlZDsgdGV4dC1hbGlnbjogY2VudGVyOyB9DQpoNC5kYXRlIHsgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IERhcmtCbHVlOyB0ZXh0LWFsaWduOiBjZW50ZXI7IH0NCmgxIHsgZm9udC1zaXplOiAyMnB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IG5hdnk7IHRleHQtYWxpZ246IGxlZnQ7IH0NCmgyIHsgZm9udC1zaXplOiAyMHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IG5hdnk7IHRleHQtYWxpZ246IGxlZnQ7IH0NCmgzIHsgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IG5hdnk7IHRleHQtYWxpZ246IGxlZnQ7IH0NCmg0IHsgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IGRhcmtyZWQ7IHRleHQtYWxpZ246IGxlZnQ7IH0NCmJvZHkgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0NCjwvc3R5bGU+DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpuZWVkZWQgPC0gYygia25pdHIiLCJ0aWR5dmVyc2UiLCJyZWFkeGwiLCJsdWJyaWRhdGUiLCJicm9vbSIsInBhbmRlciIpDQpmb3IgKHAgaW4gbmVlZGVkKSB7IGlmICghcmVxdWlyZShwLCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKSB7DQppbnN0YWxsLnBhY2thZ2VzKHAsIHJlcG9zID0gImh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZyIpOyBsaWJyYXJ5KHAsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSl9IH0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9ImFzaXMiLCBmaWcuYWxpZ249ImNlbnRlciIpDQpzZXQuc2VlZCgzMjEpDQpgYGANCg0KIyAgSW50cm9kdWN0aW9uDQoNClRoaXMgcHJvamVjdCBpbnZlc3RpZ2F0ZXMgaG93IHdlZWtkYXkgcGF0dGVybnMgYW5kIHdlYXRoZXIgY29uZGl0aW9ucyBhZmZlY3QgZGFpbHkgY3ljbGlzdCBjb3VudHMgb24gdGhlIFF1ZWVuc2Jvcm8gQnJpZGdlIGluIE5ldyBZb3JrIENpdHkuIEJlY2F1c2UgY3ljbGlzdCB0cmFmZmljIGlzIGEgY291bnQgdmFyaWFibGUgdGhhdCBjYW4gYmUgaW5mbHVlbmNlZCBieSBtdWx0aXBsZSBlbnZpcm9ubWVudGFsIGFuZCBiZWhhdmlvcmFsIGZhY3RvcnMsIG91ciBhbmFseXNpcyBjb21iaW5lcyBQb2lzc29uIGFuZCBxdWFzaS1Qb2lzc29uIGdlbmVyYWxpemVkIGxpbmVhciBtb2RlbHMgdG8gZXZhbHVhdGUgaG93IHRoZSBudW1iZXIgb2YgY3ljbGlzdHMgY2hhbmdlcyB3aXRoIGRheSBvZiB0aGUgd2VlaywgYXZlcmFnZSB0ZW1wZXJhdHVyZSwgcHJlY2lwaXRhdGlvbiwgYW5kIHRvdGFsIHJvYWR3YXkgZXhwb3N1cmUuDQoNCldlIGFkZHJlc3MgdGhyZWUgY29yZSByZXNlYXJjaCBxdWVzdGlvbnM6DQoNCkRvIGN5Y2xpc3QgY291bnRzIHZhcnkgc3lzdGVtYXRpY2FsbHkgYnkgd2Vla2RheSwgdGVtcGVyYXR1cmUsIGFuZCBwcmVjaXBpdGF0aW9uPw0KDQpJcyB0aGUgc3RhbmRhcmQgUG9pc3NvbiBtb2RlbCBhcHByb3ByaWF0ZSwgb3IgaXMgb3Zlci1kaXNwZXJzaW9uIHNvIHNldmVyZSB0aGF0IGluZmVyZW5jZSBiZWNvbWVzIHVucmVsaWFibGUgd2l0aG91dCBhZGp1c3RtZW50Pw0KDQpEb2VzIGluY29ycG9yYXRpbmcgdHJhZmZpYyBleHBvc3VyZSB0aHJvdWdoIGFuIG9mZnNldCB0ZXJtIG1lYW5pbmdmdWxseSBjaGFuZ2UgY29uY2x1c2lvbnMgYWJvdXQgd2hpY2ggcHJlZGljdG9ycyBtYXR0ZXI/DQoNCkJ5IGNvbXBhcmluZyBQb2lzc29uLCBxdWFzaS1Qb2lzc29uLCBhbmQgcXVhc2ktUG9pc3NvbiByYXRlIG1vZGVscywgd2UgYWltIHRvIGRldGVybWluZSB3aGljaCBtb2RlbGluZyBmcmFtZXdvcmsgcHJvdmlkZXMgdGhlIG1vc3QgdHJ1c3R3b3J0aHkgaW5mZXJlbmNlIHdoaWxlIG9mZmVyaW5nIGEgcHJhY3RpY2FsIGludGVycHJldGF0aW9uIG9mIGhvdyB3ZWF0aGVyIGFuZCB3ZWVrbHkgcGF0dGVybnMgc2hhcGUgY3ljbGluZyBiZWhhdmlvci4NCg0KIyAgRGF0YSBhbmQgVmFyaWFibGVzDQoNCiMjICBEYXRhIFNvdXJjZQ0KDQpUaGUgZGF0YXNldCBjb250YWlucyBkYWlseSBvYnNlcnZhdGlvbnMgb2YgY3ljbGlzdCBjb3VudHMgY3Jvc3NpbmcgdGhlIFF1ZWVuc2Jvcm8gQnJpZGdlIGFsb25nIHdpdGggYXNzb2NpYXRlZCB3ZWF0aGVyIHZhcmlhYmxlcyBhbmQgdG90YWwgdHJhZmZpYyBleHBvc3VyZS4gQmVjYXVzZSBvYnNlcnZhdGlvbnMgYXJlIGFnZ3JlZ2F0ZWQgYnkgZGF5LCBlYWNoIHJvdyByZXByZXNlbnRzIGEgZGlzdGluY3QgbWVhc3VyZW1lbnQgb2YgZW52aXJvbm1lbnRhbCBhbmQgdHJhZmZpYyBjb25kaXRpb25zLg0KYGBge3IgZGF0YS1pbXBvcnR9DQpkYXRhX3BhdGggPC0gIkM6L1VzZXJzL3JnMDMvRG93bmxvYWRzL3N0YTMyMS9Qb2lzc29uRGF0YS54bHN4Ig0KcmF3IDwtIHJlYWRfZXhjZWwoZGF0YV9wYXRoKQ0KZGltKHJhdykNCmBgYA0KDQojIyAgVmFyaWFibGUgRGVmaW5pdGlvbnMNCg0KVG8gZW5zdXJlIGNsYXJpdHkgYW5kIHJlcHJvZHVjaWJpbGl0eSwgYWxsIHZhcmlhYmxlcyB1c2VkIGluIHRoZSBhbmFseXNpcyBhcmUgbGlzdGVkIGJlbG93IHdpdGggbmFtZXMsIGRlc2NyaXB0aW9ucywgYW5kIGRhdGEgdHlwZXM6DQoNCmNvdW50IChpbnRlZ2VyKSDigJQgVG90YWwgbnVtYmVyIG9mIGN5Y2xpc3RzIGNvdW50ZWQgdGhhdCBkYXkuDQoNCmV4cG9zdXJlIChudW1lcmljKSDigJQgVG90YWwgdHJhZmZpYyB2b2x1bWUgb3IgZXhwb3N1cmUgdXNlZCBhcyBhbiBvZmZzZXQgaW4gcmF0ZSBtb2RlbHMuDQoNCmF2Z3RlbXAgKG51bWVyaWMpIOKAlCBBdmVyYWdlIGRhaWx5IHRlbXBlcmF0dXJlLCBjb21wdXRlZCBhcyB0aGUgbWVhbiBvZiBoaWdoIGFuZCBsb3cgdGVtcGVyYXR1cmVzLg0KDQpuZXdwcmVjaXAgKGJpbmFyeSBpbmRpY2F0b3IpIOKAlCAxIGlmIHByZWNpcGl0YXRpb24gPiAwOyAwIG90aGVyd2lzZS4NCg0KZGF5IChvcmRlcmVkIGZhY3Rvcikg4oCUIERheSBvZiB0aGUgd2VlayAoTW9uZGF5IHRocm91Z2ggU3VuZGF5KSwgY29kZWQgYXMgYW4gb3JkZXJlZCBmYWN0b3IgdG8gZGV0ZWN0IHNtb290aCB3ZWVrbHkgcGF0dGVybnMuDQoNCkJlY2F1c2UgZGF5IGlzIG9yZGVyZWQsIFIgZ2VuZXJhdGVzIG9ydGhvZ29uYWwgcG9seW5vbWlhbCBjb250cmFzdHMgc3VjaCBhczoNCg0KZGF5Lkwg4oCUIGxpbmVhciB3ZWVrZGF5IHRyZW5kLA0KDQpkYXkuUSDigJQgcXVhZHJhdGljIHdlZWtseSBjdXJ2YXR1cmUsDQoNCmRheS5DLCBkYXleNCwgZXRjLiDigJQgaGlnaGVyLW9yZGVyIGN5Y2xpY2FsIHBhdHRlcm5zLg0KDQpUaGVzZSB0ZXJtcyBhcHBlYXIgaW4gdGhlIG1vZGVsIG91dHB1dCBidXQgYXJlIG5vdCBzdGFuZGFsb25lIHZhcmlhYmxlcy4gVGhleSByZXByZXNlbnQgc3RydWN0dXJlZCBjb250cmFzdHMgdGhhdCBjYXB0dXJlIGhvdyBjeWNsaXN0IGNvdW50cyBzaGlmdCBhY3Jvc3MgdGhlIHdlZWsuDQoNCiMjICBEYXRhIFByb2Nlc3NpbmcNCg0KQWxsIHByZXByb2Nlc3Npbmcgc3RlcHMgd2VyZSBleHBsaWNpdGx5IGRvY3VtZW50ZWQ6DQoNClZhcmlhYmxlIG5hbWVzIHdlcmUgc3RhbmRhcmRpemVkIHRvIGxvd2VyIGNhc2UgYW5kIHNpbXBsaWZpZWQgZm9yIGNvbnNpc3RlbmN5Lg0KDQpUZW1wZXJhdHVyZSB2YXJpYWJsZXMgd2VyZSBjb21iaW5lZCBpbnRvIGEgc2luZ2xlLCBpbnRlcnByZXRhYmxlIHZhcmlhYmxlIChhdmd0ZW1wKS4NCg0KUHJlY2lwaXRhdGlvbiB3YXMgY29udmVydGVkIHRvIGEgYmluYXJ5IGluZGljYXRvciB0byBjYXB0dXJlIHRoZSBtYWluIGVmZmVjdCBvZiByYWluIHZzLiBkcnkgY29uZGl0aW9ucy4NCg0KZGF5IHdhcyBlbmNvZGVkIGFzIGFuIG9yZGVyZWQgZmFjdG9yIHRvIGNhcHR1cmUgd2Vla2x5IHN0cnVjdHVyZSB3aXRob3V0IGludHJvZHVjaW5nIHNldmVuIHNlcGFyYXRlIGR1bW15IHZhcmlhYmxlcy4NCg0KT25seSByb3dzIHdpdGggY29tcGxldGUgaW5mb3JtYXRpb24gd2VyZSByZXRhaW5lZC4NCg0KVGhpcyBwcmVwcm9jZXNzaW5nIGVuc3VyZXMgdGhlIGZpbmFsIGRhdGFzZXQgaXMgY2xlYW4sIGludGVycHJldGFibGUsIGFuZCByZWFkeSBmb3IgZ2VuZXJhbGl6ZWQgbGluZWFyIG1vZGVsaW5nLg0KDQpgYGB7ciBkYXRhLXByb2Nlc3Npbmd9DQpubSA8LSBuYW1lcyhyYXcpDQpubSA8LSB0b2xvd2VyKG5tKQ0Kbm0gPC0gZ3N1YigiW1s6c3BhY2U6XV0rIiwgIl8iLCBubSkNCm5tIDwtIGdzdWIoIlteYS16MC05X10iLCAiIiwgbm0pDQpubSA8LSBnc3ViKCJfKyIsICJfIiwgbm0pDQpubSA8LSBnc3ViKCJeXyt8XyskIiwgIiIsIG5tKQ0KbmFtZXMocmF3KSA8LSBubQ0KDQpkYXQgPC0gcmF3ICU+JQ0KbXV0YXRlKA0KIGNvdW50ID0gYXMubnVtZXJpYyhxdWVlbnNib3JvYnJpZGdlKSwNCiBleHBvc3VyZSA9IGFzLm51bWVyaWModG90YWwpLA0KIGF2Z3RlbXAgPSAoYXMubnVtZXJpYyhoaWdodGVtcCkgKyBhcy5udW1lcmljKGxvd3RlbXApKS8yLA0KIG5ld3ByZWNpcCA9IGlmZWxzZShhcy5udW1lcmljKHByZWNpcGl0YXRpb24pID4gMCwgMUwsIDBMKSwNCiBkYXkgPSBmYWN0b3IoZGF5LCBsZXZlbHM9YygiTW9uZGF5IiwiVHVlc2RheSIsIldlZG5lc2RheSIsIlRodXJzZGF5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRnJpZGF5IiwiU2F0dXJkYXkiLCJTdW5kYXkiKSwNCiAgICAgICAgICAgICAgb3JkZXJlZD1UUlVFKQ0KKSAlPiUNCmZpbHRlcighaXMubmEoY291bnQpLCAhaXMubmEoYXZndGVtcCksICFpcy5uYShuZXdwcmVjaXApLCAhaXMubmEoZGF5KSkNCg0Ka2FibGUoaGVhZChkYXQpLCBjYXB0aW9uPSJQcmV2aWV3IG9mIHByb2Nlc3NlZCBkYXRhIikNCmBgYA0KDQojICBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzDQoNCiMjICBSYXRpb25hbGUNCkV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMgKEVEQSkgcHJvdmlkZXMgYW4gaW5pdGlhbCB1bmRlcnN0YW5kaW5nIG9mIGhvdyBjeWNsaXN0IGNvdW50cyBiZWhhdmUgcmVsYXRpdmUgdG8gd2Vla2RheSBwYXR0ZXJucywgdGVtcGVyYXR1cmUsIGFuZCBwcmVjaXBpdGF0aW9uLiBXaGlsZSBwYWlyd2lzZSBwbG90cyBjYW5ub3QgZXN0YWJsaXNoIGNhdXNhbCBvciBhZGp1c3RlZCByZWxhdGlvbnNoaXBzLCB0aGV5IGlkZW50aWZ5IGJyb2FkIHRyZW5kcywgcG90ZW50aWFsIG5vbmxpbmVhcml0eSwgYW5kIHNvdXJjZXMgb2YgdmFyaWFiaWxpdHkgdGhhdCBtdXN0IGJlIGFjY291bnRlZCBmb3IgaW4gdGhlIEdMTSBmcmFtZXdvcmsuDQoNCg0KDQojIyAgQ3ljbGlzdCBDb3VudHMgYnkgRGF5DQpWaXN1YWxpemluZyBjb3VudHMgYnkgd2Vla2RheSBzdWdnZXN0cyB0aGF0IGN5Y2xpc3Qgdm9sdW1lIHRlbmRzIHRvIGJlIGhpZ2hlciBvbiB3ZWVrZGF5cyB0aGFuIHdlZWtlbmRzLCB0aG91Z2ggdmFyaWFiaWxpdHkgaXMgc3Vic3RhbnRpYWwgYWNyb3NzIGFsbCBkYXlzLiBUaGlzIGFsaWducyB3aXRoIGV4cGVjdGF0aW9ucyBmb3IgY29tbXV0ZXIgcGF0dGVybnMgYnV0IGNhbm5vdCB5ZXQgZGlzdGluZ3Vpc2ggd2hldGhlciBkYXktb2Ytd2VlayBkaWZmZXJlbmNlcyBwZXJzaXN0IGFmdGVyIGFkanVzdGluZyBmb3Igd2VhdGhlciBhbmQgZXhwb3N1cmUNCmBgYHtyIGVkYS1kYXl9DQpnZ3Bsb3QoZGF0LCBhZXMoZGF5LCBjb3VudCkpICsgZ2VvbV9ib3hwbG90KCkgKw0KbGFicyh0aXRsZT0iQ3ljbGlzdCBDb3VudHMgYnkgRGF5IiwgeD0iRGF5IiwgeT0iQ291bnQiKQ0KYGBgDQoNCioqSW50ZXJwcmV0YXRpb246KiogV2Vla2RheXMgc2hvdyBzb21ld2hhdCBoaWdoZXIgbWVkaWFuIGNvdW50cywgYnV0IHZhcmlhYmlsaXR5IGlzIGxhcmdlLiBBIGZvcm1hbCBtb2RlbCBpcyBuZWVkZWQuDQoNCiMjICBDb3VudHMgdnMgVGVtcGVyYXR1cmUNCkN5Y2xpc3Qgdm9sdW1lIHJpc2VzIHdpdGggdGVtcGVyYXR1cmUsIHBhcnRpY3VsYXJseSBhcyBjb25kaXRpb25zIHdhcm0gZnJvbSBjb29sZXIgZGF5cyBpbnRvIG1vZGVyYXRlIHRlbXBlcmF0dXJlcy4gSG93ZXZlciwgdGhlIGxhcmdlIHNwcmVhZCBpbiBjb3VudHMgYXQgYW55IGdpdmVuIHRlbXBlcmF0dXJlIGluZGljYXRlcyB0aGF0IHRlbXBlcmF0dXJlIGFsb25lIGNhbm5vdCBleHBsYWluIHRoZSBmdWxsIHZhcmlhdGlvbiBpbiBjeWNsaW5nIHBhdHRlcm5z4oCUcmVpbmZvcmNpbmcgdGhlIG5lZWQgZm9yIG11bHRpdmFyaWFibGUgbW9kZWxzLg0KYGBge3IgZWRhLXRlbXB9DQpnZ3Bsb3QoZGF0LCBhZXMoYXZndGVtcCwgY291bnQpKSArIGdlb21fcG9pbnQoYWxwaGE9LjUpICsNCmdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBzZT1GQUxTRSkgKw0KbGFicyh0aXRsZT0iQ291bnRzIHZzIFRlbXBlcmF0dXJlIiwgeD0iQXZnIFRlbXAgKMKwRikiLCB5PSJDb3VudCIpDQpgYGANCg0KKipJbnRlcnByZXRhdGlvbjoqKiBXYXJtZXIgZGF5cyB0cmVuZCB1cHdhcmQsIGJ1dCB2YXJpYXRpb24gaXMgd2lkZSDihpIgc3VnZ2VzdHMgbXVsdGlwbGUgcHJlZGljdG9ycyBtYXR0ZXIgam9pbnRseS4NCg0KIyMgIENvdW50cyBieSBQcmVjaXBpdGF0aW9uDQpSYWlueSBkYXlzIGNsZWFybHkgc2hvdyBsb3dlciBjeWNsaXN0IGNvdW50cyB0aGFuIGRyeSBkYXlzLiBUaGlzIHN0cm9uZyBwYWlyd2lzZSBjb250cmFzdCBzdWdnZXN0cyBwcmVjaXBpdGF0aW9uIGlzIGEga2V5IGRyaXZlciBvZiBjeWNsaW5nIGJlaGF2aW9yLiBMYXRlciBtb2RlbGluZyB3aWxsIGRldGVybWluZSB3aGV0aGVyIHRoaXMgZWZmZWN0IHJlbWFpbnMgYWZ0ZXIgYWNjb3VudGluZyBmb3Igd2Vla2RheSBzdHJ1Y3R1cmUsIGV4cG9zdXJlLCBhbmQgdGVtcGVyYXR1cmUuDQpgYGB7ciBlZGEtcHJlY2lwfQ0KZ2dwbG90KGRhdCwgYWVzKGZhY3RvcihuZXdwcmVjaXApLCBjb3VudCkpICsgZ2VvbV9ib3hwbG90KCkgKw0KbGFicyh0aXRsZT0iQ291bnRzIGJ5IFByZWNpcGl0YXRpb24iLCB4PSIwPURyeSAvIDE9V2V0IiwgeT0iQ291bnQiKQ0KYGBgDQoNCioqSW50ZXJwcmV0YXRpb246KiogUmFpbiBjbGVhcmx5IGxvd2VycyBjb3VudHMuDQoNCiMgIFBvaXNzb24gYW5kIFF1YXNpLVBvaXNzb24gTW9kZWxzDQoNCiMjICBSYXRpb25hbGUNCkN5Y2xpc3QgY291bnRzIGFyZSBub24tbmVnYXRpdmUgaW50ZWdlcnMsIG1ha2luZyBQb2lzc29uIHJlZ3Jlc3Npb24gYSBuYXR1cmFsIHN0YXJ0aW5nIHBvaW50LiBIb3dldmVyLCBQb2lzc29uIG1vZGVscyBhc3N1bWUgZXF1YWxpdHkgb2YgdGhlIG1lYW4gYW5kIHZhcmlhbmNlOiBWYXIoWSk9TWVhbihZKS4gV2hlbiB0aGUgdmFyaWFuY2UgZHJhbWF0aWNhbGx5IGV4Y2VlZHMgdGhlIG1lYW7igJRhIHBoZW5vbWVub24ga25vd24gYXMgb3Zlci1kaXNwZXJzaW9u4oCUc3RhbmRhcmQgZXJyb3JzIGJlY29tZSBzZXZlcmVseSB1bmRlcmVzdGltYXRlZCwgYXJ0aWZpY2lhbGx5IGluZmxhdGluZyBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuIEEgcXVhc2ktUG9pc3NvbiBtb2RlbCBjb3JyZWN0cyB0aGlzIGJ5IGludHJvZHVjaW5nIGEgZGlzcGVyc2lvbiBwYXJhbWV0ZXI6IM+GLlRoaXMgbW9kZWwgcHJlc2VydmVzIHRoZSBtZWFuIHN0cnVjdHVyZSBvZiB0aGUgUG9pc3NvbiBHTE0gd2hpbGUgcHJvdmlkaW5nIHZhbGlkIGluZmVyZW5jZSBldmVuIHdoZW4gZGlzcGVyc2lvbiBpcyBsYXJnZS4gQWRkaXRpb25hbGx5LCBpbmNvcnBvcmF0aW5nIGFuIG9mZnNldCB1c2luZyBsb2coZXhwb3N1cmUpIGVuYWJsZXMgbW9kZWxpbmcgb2YgY3ljbGluZyByYXRlIHBlciB1bml0IHRyYWZmaWMsIHdoaWNoIGlzIGVzc2VudGlhbCBmb3IgdW5kZXJzdGFuZGluZyBjeWNsaXN0IGJlaGF2aW9yIHJlbGF0aXZlIHRvIHRvdGFsIHRyYWZmaWMgZmxvdy4NCg0KIyMgIEZpdCBQb2lzc29uICYgUXVhc2ktUG9pc3NvbiBNb2RlbHMNCmBgYHtyIG1vZGVscy1maXR9DQptX3BvaXMgPC0gZ2xtKGNvdW50IH4gZGF5ICsgYXZndGVtcCArIG5ld3ByZWNpcCwNCiAgICAgICAgICAgICAgZmFtaWx5PXBvaXNzb24obGluaz0ibG9nIiksIGRhdGE9ZGF0KQ0KDQptX3F1YXNpIDwtIGdsbShjb3VudCB+IGRheSArIGF2Z3RlbXAgKyBuZXdwcmVjaXAsDQogICAgICAgICAgICAgICBmYW1pbHk9cXVhc2lwb2lzc29uKGxpbms9ImxvZyIpLCBkYXRhPWRhdCkNCg0KbV9xdWFzaV9yYXRlIDwtIGdsbShjb3VudCB+IGRheSArIGF2Z3RlbXAgKyBuZXdwcmVjaXAgKw0KICAgICAgICAgICAgICAgICAgICAgIG9mZnNldChsb2coZXhwb3N1cmUpKSwNCiAgICAgICAgICAgICAgICAgICAgZmFtaWx5PXF1YXNpcG9pc3NvbihsaW5rPSJsb2ciKSwNCiAgICAgICAgICAgICAgICAgICAgZGF0YT1kYXQgJT4lIGZpbHRlcighaXMubmEoZXhwb3N1cmUpLCBleHBvc3VyZT4wKSkNCg0KcGhpX2hhdCA8LSBzdW0ocmVzaWR1YWxzKG1fcG9pcywgdHlwZT0icGVhcnNvbiIpXjIpIC8gbV9wb2lzJGRmLnJlc2lkdWFsDQprYWJsZShkYXRhLmZyYW1lKERpc3BlcnNpb249cm91bmQocGhpX2hhdCwyKSksDQogICAgICBjYXB0aW9uPSJFc3RpbWF0ZWQgT3Zlci1EaXNwZXJzaW9uIM+GIikNCmBgYA0KDQpUaGUgZGlzcGVyc2lvbiBlc3RpbWF0ZSBmcm9tIHRoZSBQb2lzc29uIG1vZGVsIGlzOvCdnJk9MTA5LjExLlRoaXMgbWVhbnMgdGhlIHZhcmlhbmNlIG9mIGN5Y2xpc3QgY291bnRzIGlzIG1vcmUgdGhhbiAxMDAgdGltZXMgbGFyZ2VyIHRoYW4gdGhlIG1lYW4sIHJlbmRlcmluZyBQb2lzc29uLWJhc2VkIGluZmVyZW5jZSB1bnJlbGlhYmxlLiBDb25zZXF1ZW5jZXMgaW5jbHVkZToNCg0KLU1pc2xlYWRpbmdseSBzbWFsbCBwLXZhbHVlcw0KDQotTmFycm93ZWQgY29uZmlkZW5jZSBpbnRlcnZhbHMNCg0KLU92ZXJzdGF0ZWQgc2lnbmlmaWNhbmNlIGZvciBzZXZlcmFsIHByZWRpY3RvcnMNCg0KLUluZmxhdGVkIFR5cGUgSSBlcnJvciByYXRlDQoNCkJlY2F1c2Ugb2YgdGhpcyBleHRyZW1lIG92ZXItZGlzcGVyc2lvbiwgdGhlIHF1YXNpLVBvaXNzb24gZnJhbWV3b3JrIGlzIGVzc2VudGlhbCBmb3IgZHJhd2luZyB2YWxpZCBjb25jbHVzaW9ucy4NCg0KIyMgIFBvaXNzb24gSVJScyAoZm9yIGNvbXBhcmlzb24pDQpgYGB7ciBwb2lzc29uLXRhYmxlfQ0Ka2FibGUodGlkeShtX3BvaXMsIGNvbmYuaW50PVRSVUUsIGV4cG9uZW50aWF0ZT1UUlVFKSwNCiAgICAgIGRpZ2l0cz0zLCBjYXB0aW9uPSJQb2lzc29uIElSUnMiKQ0KYGBgDQoNClRoZSBQb2lzc29uIG1vZGVsIHN1Z2dlc3RzIGFsbW9zdCBldmVyeSB0ZXJtIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQsIGluY2x1ZGluZyBhbGwgcG9seW5vbWlhbCB3ZWVrZGF5IGNvbnRyYXN0cywgdGVtcGVyYXR1cmUsIGFuZCBwcmVjaXBpdGF0aW9uLiBIb3dldmVyLCBkdWUgdG8gz4YgPiAxMDAsIHRoZXNlIHJlc3VsdHMgcmVwcmVzZW50IGZhbHNlIHByZWNpc2lvbiBhbmQgY2Fubm90IGJlIHRydXN0ZWQuDQoNClRoZXNlIHJlc3VsdHMgc2VydmUgb25seSBhcyBhIGNvbXBhcmlzb24gcG9pbnQsIGRlbW9uc3RyYXRpbmcgd2hhdCBoYXBwZW5zIHdoZW4gb3Zlci1kaXNwZXJzaW9uIGlzIGlnbm9yZWQuDQoNCiMjICBRdWFzaS1Qb2lzc29uIElSUnMgKG5vIG9mZnNldCkNCmBgYHtyIHF1YXNpLXRhYmxlfQ0Ka2FibGUodGlkeShtX3F1YXNpLCBjb25mLmludD1UUlVFLCBleHBvbmVudGlhdGU9VFJVRSksDQogICAgICBkaWdpdHM9MywgY2FwdGlvbj0iUXVhc2ktUG9pc3NvbiBJUlJzIikNCmBgYA0KDQpBZnRlciBjb3JyZWN0aW5nIGZvciBvdmVyLWRpc3BlcnNpb246DQoNClRoZSB3ZWVrZGF5IGxpbmVhciBjb250cmFzdCAoZGF5LkwpIHJlbWFpbnMgc2lnbmlmaWNhbnQsIHN1Z2dlc3RpbmcgYSBnZW51aW5lIHdlZWtseSBwYXR0ZXJuIGluIGN5Y2xpc3QgY291bnRzLg0KDQpUaGUgdGVtcGVyYXR1cmUgZWZmZWN0IChJUlIg4omIIDEuMDA2KSBiZWNvbWVzIHN0YXRpc3RpY2FsbHkgbm9uLXNpZ25pZmljYW50LCBpbmRpY2F0aW5nIGEgbW9kZXN0IHVwd2FyZCB0cmVuZCB0aGF0IGlzIG92ZXJzaGFkb3dlZCBieSB2YXJpYWJpbGl0eS4NCg0KbmV3cHJlY2lwIElSUiA9IDAuNzI3IHJlbWFpbnMgc3Ryb25nbHkgc2lnbmlmaWNhbnQsIGNvbmZpcm1pbmcgdGhhdCByYWluIG1lYW5pbmdmdWxseSByZWR1Y2VzIGN5Y2xpc3QgY291bnRzIGV2ZW4gYWZ0ZXIgYWRqdXN0aW5nIGZvciB3ZWVrZGF5IGFuZCB0ZW1wZXJhdHVyZS4NCg0KVGhpcyBtb2RlbCBvZmZlcnMgYSBtb3JlIHJlYWxpc3RpYyBhc3Nlc3NtZW50IG9mIHdoaWNoIHByZWRpY3RvcnMgbWVhbmluZ2Z1bGx5IGluZmx1ZW5jZSBjeWNsaXN0IHRyYWZmaWMuDQoNCiMjICBRdWFzaS1Qb2lzc29uICpSYXRlKiBNb2RlbCAoT2Zmc2V0IEluY2x1ZGVkKQ0KYGBge3IgcXVhc2ktcmF0ZX0NCmthYmxlKHRpZHkobV9xdWFzaV9yYXRlLCBjb25mLmludD1UUlVFLCBleHBvbmVudGlhdGU9VFJVRSksDQogICAgICBkaWdpdHM9MywgY2FwdGlvbj0iUXVhc2ktUG9pc3NvbiBSYXRlIE1vZGVsIElSUnMiKQ0KYGBgDQoNClRoZSBxdWFzaS1Qb2lzc29uIHJhdGUgbW9kZWwgaW5jbHVkZXMgbG9nKGV4cG9zdXJlKSBhcyBhbiBvZmZzZXQsIGFsbG93aW5nIHVzIHRvIGFuYWx5emUgY3ljbGluZyByYXRlcyBwZXIgdW5pdCB0cmFmZmljLg0KDQpLZXkgZmluZGluZ3M6DQoNCldlZWtkYXkgY29udHJhc3RzIGxvc2Ugc2lnbmlmaWNhbmNlLCBzdWdnZXN0aW5nIGN5Y2xpbmcgcmF0ZXMgYXJlIG1vcmUgc3RhYmxlIGFjcm9zcyB0aGUgd2VlayB0aGFuIHJhdyBjb3VudHMuDQoNClRlbXBlcmF0dXJlIHNob3dzIGEgbmVhci1udWxsIHJhdGUgZWZmZWN0Lg0KDQpQcmVjaXBpdGF0aW9uIG5vIGxvbmdlciBzaWduaWZpY2FudGx5IHJlZHVjZXMgdGhlIGN5Y2xpbmcgcmF0ZSAocCA9IDAuMTA0KSwgdGhvdWdoIHRoZSBkaXJlY3Rpb24gcmVtYWlucyBjb25zaXN0ZW50IHdpdGggc21hbGxlciB2b2x1bWUgb24gcmFpbnkgZGF5cy4NCg0KSW1wb3J0YW50bHksIHRoZSBwcmVjaXBpdGF0aW9uIElSUiBzaGlmdHMgc2xpZ2h0bHkgYWJvdmUgMSwgYnV0IHJlbWFpbnMgc3RhdGlzdGljYWxseSBub24tc2lnbmlmaWNhbnQuIFRoaXMgZG9lcyBub3QgY29udHJhZGljdCBlYXJsaWVyIHJlc3VsdHM7IHJhdGhlciwgaXQgaW5kaWNhdGVzOg0KDQpSYWluIHJlZHVjZXMgdG90YWwgY291bnRzIGJlY2F1c2Ugb3ZlcmFsbCB0cmFmZmljIHZvbHVtZSBhbHNvIGRyb3BzLg0KDQpSZWxhdGl2ZSBjeWNsaXN0IHNoYXJlIGFtb25nIHRvdGFsIHRyYWZmaWMgbWF5IHJlbWFpbiBzdGFibGUuDQoNClRoaXMgbnVhbmNlIGVuaGFuY2VzIHRoZSBpbnRlcnByZXRhdGlvbiBhbmQgaXMgY3J1Y2lhbCBmb3IgdW5kZXJzdGFuZGluZyBiZWhhdmlvcmFsIHBhdHRlcm5zLg0KDQoNClRvIHN5bnRoZXNpemUgdGhlIHJlc3VsdHM6DQoNClBvaXNzb24gbW9kZWwgb3ZlcnN0YXRlcyBzaWduaWZpY2FuY2UgYWNyb3NzIGFsbCBwcmVkaWN0b3JzIGR1ZSB0byBzZXZlcmUgb3Zlci1kaXNwZXJzaW9uLg0KDQpRdWFzaS1Qb2lzc29uIG1vZGVsIHByb3ZpZGVzIHZhbGlkIGluZmVyZW5jZSBhbmQgY29uZmlybXMgcmFpbmZhbGwgYW5kIHdlZWtkYXkgcGF0dGVybnMgYXMgbWVhbmluZ2Z1bCBkcml2ZXJzLg0KDQpRdWFzaS1Qb2lzc29uIHJhdGUgbW9kZWwgb2ZmZXJzIHRoZSBtb3N0IGNvbnNlcnZhdGl2ZSBhbmQgcmVhbGlzdGljIGluZmVyZW5jZSwgYWRqdXN0aW5nIGZvciB0cmFmZmljIHZvbHVtZSBhbmQgY29udHJvbGxpbmcgb3Zlci1kaXNwZXJzaW9uLg0KDQpUaGUgcmF0ZSBtb2RlbCBpcyB0aGVyZWZvcmUgdGhlIGZpbmFsIHJlY29tbWVuZGVkIG1vZGVsIGZvciBpbnRlcnByZXRhdGlvbi4NCiMgIE1vZGVsLUJhc2VkIEVmZmVjdCBWaXN1YWxpemF0aW9uDQoNCiMjICBSYXRpb25hbGUNClBhaXJ3aXNlIHBsb3RzIGlnbm9yZSBjb25mb3VuZGluZzsgcHJlZGljdGlvbnMgZnJvbSB0aGUgZml0dGVkIG1vZGVsIHNob3cgYWRqdXN0ZWQgcmVsYXRpb25zaGlwcy4NCg0KIyMgIFByZWRpY3RlZCBDb3VudHMgdnMgVGVtcGVyYXR1cmUNCmBgYHtyIGVmZmVjdC10ZW1wfQ0KdGVtcF9zZXEgPC0gc2VxKHF1YW50aWxlKGRhdCRhdmd0ZW1wLC4wNSksIHF1YW50aWxlKGRhdCRhdmd0ZW1wLC45NSksIGxlbmd0aC5vdXQ9NTApDQoNCm5ld2RhdCA8LSBleHBhbmRfZ3JpZChhdmd0ZW1wPXRlbXBfc2VxLCBuZXdwcmVjaXA9YygwLDEpKSAlPiUNCm11dGF0ZShkYXk9ZmFjdG9yKCJXZWRuZXNkYXkiLCBsZXZlbHM9bGV2ZWxzKGRhdCRkYXkpLCBvcmRlcmVkPVRSVUUpLA0KICAgICAgIGV4cG9zdXJlPW1lZGlhbihkYXQkZXhwb3N1cmUsIG5hLnJtPVRSVUUpKQ0KDQpuZXdkYXQkcHJlZCA8LSBwcmVkaWN0KG1fcXVhc2lfcmF0ZSwgbmV3ZGF0YT1uZXdkYXQsIHR5cGU9InJlc3BvbnNlIikNCg0KZ2dwbG90KG5ld2RhdCwgYWVzKGF2Z3RlbXAsIHByZWQsIGNvbG9yPWZhY3RvcihuZXdwcmVjaXApKSkgKw0KZ2VvbV9saW5lKHNpemU9MSkgKw0KbGFicyh0aXRsZT0iUHJlZGljdGVkIENvdW50cyB2cyBUZW1wZXJhdHVyZSIsDQogICAgIHg9IkF2ZyBUZW1wIiwgeT0iUHJlZGljdGVkIENvdW50IiwNCiAgICAgY29sb3I9Im5ld3ByZWNpcCIpDQpgYGANCg0KKipJbnRlcnByZXRhdGlvbjoqKiBFdmVuIGFmdGVyIGFkanVzdGluZyBmb3IgZGF5ICsgZXhwb3N1cmUsIHJhaW4gZGVwcmVzc2VzIGNvdW50cyBzdHJvbmdseSBhY3Jvc3MgYWxsIHRlbXBlcmF0dXJlcy4NCg0KIyAgUmVzdWx0cyBhbmQgQ29uY2x1c2lvbnMNCg0KIyMgIEtleSBGaW5kaW5ncw0KLUN5Y2xpc3QgY291bnRzIGFyZSBoaWdobHkgb3Zlci1kaXNwZXJzZWQ7IFBvaXNzb24gaW5mZXJlbmNlIGlzIGludmFsaWQgd2l0aG91dCBjb3JyZWN0aW9uLg0KDQotVGhlIHF1YXNpLVBvaXNzb24gR0xNIHByb3ZpZGVzIHJlbGlhYmxlIGluZmVyZW5jZSBhbmQgc2hvd3M6DQoNCi1SYWluIHNpZ25pZmljYW50bHkgZGVjcmVhc2VzIGRhaWx5IGN5Y2xpc3QgY291bnRzLg0KDQotV2Vla2RheSBwYXR0ZXJucyBwZXJzaXN0IGFmdGVyIGNvcnJlY3RpbmcgZm9yIG92ZXItZGlzcGVyc2lvbi4NCg0KLVRlbXBlcmF0dXJlIGVmZmVjdHMgYXJlIG1pbGQgYW5kIHN0YXRpc3RpY2FsbHkgdW5jZXJ0YWluLg0KDQpXaGVuIGFkanVzdGluZyBmb3IgZXhwb3N1cmUsIHByZWNpcGl0YXRpb24gbm8gbG9uZ2VyIHNpZ25pZmljYW50bHkgcHJlZGljdHMgY3ljbGluZyByYXRlLCBoaWdobGlnaHRpbmcgdGhlIGFkdmFudGFnZSBvZiBpbnRlcnByZXRpbmcgcmF0ZXMgcmF0aGVyIHRoYW4gcmF3IGNvdW50cy4NCg0KIyMgIEZpbmFsIE1vZGVsIFJlY29tbWVuZGF0aW9uDQpUaGUgKipxdWFzaS1Qb2lzc29uIHJhdGUgbW9kZWwgd2l0aCBsb2coZXhwb3N1cmUpKiogaXMgdGhlIGJlc3QgbW9kZWwgYmVjYXVzZSBpdDoNCg0KLSBDb3JyZWN0cyBvdmVyLWRpc3BlcnNpb24gIA0KLSBBZGp1c3RzIGZvciBleHBvc3VyZSBkaWZmZXJlbmNlcyAgDQotIFByb2R1Y2VzIGludGVycHJldGFibGUgSVJScyAgDQoNCiMjICBQcmFjdGljYWwgSW1wbGljYXRpb25zDQotIFJhaW4g4oaSIG1ham9yIGRyb3AgaW4gY3ljbGlzdHMg4oaSIGluZnJhc3RydWN0dXJlIHNob3VsZCBzdXBwb3J0IHdldC13ZWF0aGVyIHJpZGluZy4gIA0KLSBUZW1wZXJhdHVyZSBpbmZsdWVuY2VzIGNvdW50cyBidXQgbGVzcyBzdHJvbmdseS4gIA0KLSBXZWVrZGF5IGN5Y2xpbmcgZGVtYW5kIGlzIHBhdHRlcm5lZCDihpIgaW1wb3J0YW50IGZvciBwbGFubmluZy4NCg0KIyAgTGltaXRhdGlvbnMgYW5kIEZ1dHVyZSBXb3JrDQotIExhY2tzIHdpbmQsIGhvbGlkYXkvZXZlbnQgaW5kaWNhdG9ycywgYXV0b2NvcnJlbGF0aW9uIG1vZGVsaW5nLiAgDQotIFBvbHlub21pYWwgZGF5IGNvbnRyYXN0cyBvYnNjdXJlIGluZGl2aWR1YWwtZGF5IGNvbXBhcmlzb25zLiAgDQotIEZ1dHVyZSBhbmFseXNlcyBzaG91bGQgdHJ5IG5lZ2F0aXZlIGJpbm9taWFsLCB0aW1lLXNlcmllcyBHTE1zLCBhbmQgaW50ZXJhY3Rpb25zLg0KDQoNCg==