library(ggplot2)
cases <- c(12, 14, 33, 50, 67, 74, 123, 141, 165, 204, 253, 246, 240, 246, 232)
year  <- 1980 + 1:15

aids_data <- data.frame(year = year,
                        cases = cases)

head(aids_data)

1a.Plot the number of new AIDS cases against year. Comment on your plot.

plot(year, cases,
     pch = 19,
     xlab = "Year",
     ylab = "Number of new AIDS cases",
     main = "New AIDS Cases by Year")

Comment:

Strong upward trend in early years, followed by rapid growth (roughly exponential at first) and peak around early 1990s and then Slight decline towards the end. This already suggests a purely linear time trend may not fully capture the pattern.

1b.Fit a simple Poisson regression model of the form for predicting the mean number of new AIDS cases. Plot the fitted mean response on top of the previous scatter plot. Does the model seem adequate?

pois_mod <- glm(cases ~ year,
                family = poisson(link = "log"))

summary(pois_mod)

Call:
glm(formula = cases ~ year, family = poisson(link = "log"))

Coefficients:
              Estimate Std. Error z value Pr(>|z|)    
(Intercept) -3.049e+02  1.142e+01  -26.71   <2e-16 ***
year         1.557e-01  5.735e-03   27.16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for poisson family taken to be 1)

    Null deviance: 1010.27  on 14  degrees of freedom
Residual deviance:  173.33  on 13  degrees of freedom
AIC: 273.65

Number of Fisher Scoring iterations: 4
# Predicted means
year_seq <- seq(min(year), max(year), length = 100)
pred <- predict(pois_mod,
                newdata = data.frame(year = year_seq),
                type = "response")

# Plot again
plot(year, cases,
     pch = 19,
     xlab = "Year",
     ylab = "Number of new AIDS cases",
     main = "Poisson Regression Fit")

lines(year_seq, pred, col = "red", lwd = 2)

As we can notice that the model captures early exponential growth and overestimates it in the later years and fails to capture the downturn. Hence, a simple log linear time trend may not be adequate.

1c. Modify and run the code below to perform a basic residual analysis to inspect the adequacy of the model. You’ll need to change the name of the model object. Based on these results, how might you consider improving the model?

par(mfrow = c(2, 2))   # set up 2x2 plotting grid
plot(pois_mod, which = 1:4)

How i would improve the model:

The residual plots likely show non linearity and possible over dispersion. A quadratic time term should be added to better capture the rise and fall pattern in the data.

1d. Based on your assessment of the residuals, does it seem like a quadratic model would provide a better fit? Fit a second degree polynomial model (i.e., a model using the formula cases ~ year + I(year^2)). How does this model comapre to the simpler model. Be sure to provide a plot of the fitted regression line on top of a scatter plot fo the raw data.

pois_mod2 <- glm(cases ~ year + I(year^2),
                 family = poisson(link = "log"),
                 data = aids_data)

summary(pois_mod2)

Call:
glm(formula = cases ~ year + I(year^2), family = poisson(link = "log"), 
    data = aids_data)

Coefficients:
              Estimate Std. Error z value Pr(>|z|)    
(Intercept) -8.429e+04  7.027e+03  -11.99   <2e-16 ***
year         8.459e+01  7.064e+00   11.97   <2e-16 ***
I(year^2)   -2.122e-02  1.775e-03  -11.96   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for poisson family taken to be 1)

    Null deviance: 1010.2722  on 14  degrees of freedom
Residual deviance:    9.2446  on 12  degrees of freedom
AIC: 111.56

Number of Fisher Scoring iterations: 4
deviance(pois_mod)
[1] 173.3349
deviance(pois_mod2)
[1] 9.244631
anova(pois_mod, pois_mod2, test = "Chisq")
Analysis of Deviance Table

Model 1: cases ~ year
Model 2: cases ~ year + I(year^2)
  Resid. Df Resid. Dev Df Deviance  Pr(>Chi)    
1        13    173.335                          
2        12      9.245  1   164.09 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
year_seq <- seq(min(aids_data$year),
                max(aids_data$year),
                length.out = 200)

pred_quad <- predict(pois_mod2,
                     newdata = data.frame(year = year_seq),
                     type = "response")

plot(aids_data$year, aids_data$cases,
     pch = 19,
     xlab = "Year",
     ylab = "Number of new AIDS cases",
     main = "Quadratic Poisson Fit")

lines(year_seq, pred_quad, col = "blue", lwd = 2)

Compared to the simpler model:

Deviance has decreased substantially. The fitted curve has captured the rise and decline and the residual pattern looks more random.

1e. Use a likilhood ratio test to comapre the two models and interpret the results. Be sure to write out the associated null and alternative hypotheses. (Hint: use R’s built-in anova() function with the previous two models and specify test = “Chisq” like we’ve done in class.)

anova(pois_mod, pois_mod2, test = "Chisq")
Analysis of Deviance Table

Model 1: cases ~ year
Model 2: cases ~ year + I(year^2)
  Resid. Df Resid. Dev Df Deviance  Pr(>Chi)    
1        13    173.335                          
2        12      9.245  1   164.09 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Hypotheses

H0: beta_2 = 0 The quadratic term does not improve the model.

H1: beta_2 != 0 The quadratic term improves the model.

Likelihood ratio statistic: 173.335 - 9.245 = 164.09

The p-value is < 2.2 ? 10^-16, which is far below 0.05.

You reject H0.

There is strong evidence that the quadratic term significantly improves model fit.

Question 2

In order to maximize sales, items within grocery stores are strategically placed to draw customer attention. This exercise examines one type of item-breakfast cereal. Typically, in large grocery stores, boxes of cereal are placed on sets of shelves located on one side of the aisle. By placing particular boxes of cereals on specific shelves, grocery stores may better attract customers to them. To investigate this further, a random sample of size 10 was taken from each of four shelves at a Dillons grocery store in Manhattan, KS. These data are given in the cereal.csv file. The response variable is the shelf number, which is numbered from bottom (1) to top (4), and the explanatory variables are the sugar, fat, and sodium content of the cereals. Using these data, complete the following:

2a. The explanatory variables need to be re-formatted before proceeding further. First, divide each explanatory variable by its serving size to account for the different serving sizes among the cereals. Second, re-scale each variable to be 190 Analysis of Categorical Data with R within 0 and 1.1 The code below can be used to re-format the data after the data file is read into an object named cereal:

library(readr)

cereal <- read_csv("~/Downloads/cereal.csv")

head(cereal)
stand01 <- function(x) {
  (x - min(x)) / (max(x) - min(x))
}
cereal2 <- data.frame(
  Shelf  = cereal$Shelf,
  sugar  = stand01(cereal$sugar_g / cereal$size_g),
  fat    = stand01(cereal$fat_g / cereal$size_g),
  sodium = stand01(cereal$sodium_mg / cereal$size_g)
)

head(cereal2)

2b Construct side-by-side box plots with dot plots overlaid for each of the explanatory variables. Below is code that can be used for plots involving sugar:

Sugar

boxplot(sugar ~ Shelf, data = cereal2,
        ylab = "Sugar",
        xlab = "Shelf",
        pars = list(outpch = NA))

stripchart(cereal2$sugar ~ cereal2$Shelf,
           method = "jitter",
           vertical = TRUE,
           pch = 1,
           col = "red",
           add = TRUE)

Conclusion:

Sugar content clearly differs by shelf. Higher shelves (especially Shelf 2) appear to contain more sugary cereals.

Fat

boxplot(fat ~ Shelf, data = cereal2,
        ylab = "Fat",
        xlab = "Shelf",
        pars = list(outpch = NA))

stripchart(cereal2$fat ~ cereal2$Shelf,
           method = "jitter",
           vertical = TRUE,
           pch = 1,
           col = "red",
           add = TRUE)

Conclusion:

There are differences, but they are less dramatic than sugar. Shelf 2 and 4 tend to have higher fat content.

Sodium

boxplot(sodium ~ Shelf, data = cereal2,
        ylab = "sodium",
        xlab = "Shelf",
        pars = list(outpch = NA))

stripchart(cereal2$sodium ~ cereal2$Shelf,
           method = "jitter",
           vertical = TRUE,
           pch = 1,
           col = "red",
           add = TRUE)

Conclusion:

Sodium also varies across shelves, with Shelf 1 standing out as higher. The boxplots suggest that sugar, fat, and sodium content differ across shelves, with sugar showing the clearest separation, particularly higher levels on Shelf 2.

2c The response (Shelf) has values of 1, 2, 3, and 4. Under what setting would it be desirable to take into account ordinality. Do you think this occurs here? If so, explain.

Shelf = 1, 2, 3, 4 clearly represents vertical position from bottom to top. That is a natural ordering.

So treating Shelf as ordinal would be appropriate if: There is a monotonic trend in nutrient content as shelf height increases, or The scientific question concerns how content changes with shelf level.

From the graphs: Sugar does not increase or decrease monotonically across shelves. Fat does not follow a clear monotonic pattern. Sodium also does not show a consistent increasing or decreasing trend because there is no clear monotonic progression from Shelf 1 through Shelf 4, the ordinal structure does not appear to drive the differences in a simple directional way.

Conclusion:

Although Shelf is naturally ordered, the nutrient patterns do not follow a clear monotonic trend. Therefore, it may be more appropriate to treat Shelf as a nominal categorical variable rather than relying on its ordinal structure in this dataset.

2d. Estimate a multinomial regression model with linear forms of the sugar, fat, and sodium variables. Which variable seems most important in predicting shelf placement (e.g., using the LOVO method)?

library(nnet)
cereal2$Shelf <- as.factor(cereal2$Shelf)

multi_mod <- multinom(Shelf ~ sugar + fat + sodium,
                      data = cereal2)
# weights:  20 (12 variable)
initial  value 55.451774 
iter  10 value 37.329384
iter  20 value 33.775257
iter  30 value 33.608495
iter  40 value 33.596631
iter  50 value 33.595909
iter  60 value 33.595564
iter  70 value 33.595277
iter  80 value 33.595147
final  value 33.595139 
converged
summary(multi_mod)
Call:
multinom(formula = Shelf ~ sugar + fat + sodium, data = cereal2)

Coefficients:
  (Intercept)      sugar        fat    sodium
2    6.900708   2.693071  4.0647092 -17.49373
3   21.680680 -12.216442 -0.5571273 -24.97850
4   21.288343 -11.393710 -0.8701180 -24.67385

Std. Errors:
  (Intercept)    sugar      fat   sodium
2    6.487408 5.051689 2.307250 7.097098
3    7.450885 4.887954 2.414963 8.080261
4    7.435125 4.871338 2.405710 8.062295

Residual Deviance: 67.19028 
AIC: 91.19028 
z <- summary(multi_mod)$coefficients / summary(multi_mod)$standard.errors
pvals <- 2 * (1 - pnorm(abs(z)))
pvals
  (Intercept)      sugar        fat      sodium
2 0.287460973 0.59396225 0.07811805 0.013704657
3 0.003616453 0.01244405 0.81754938 0.001992834
4 0.004193692 0.01933915 0.71758477 0.002210418
mod_no_sugar <- multinom(Shelf ~ fat + sodium,
                         data = cereal2)
# weights:  16 (9 variable)
initial  value 55.451774 
iter  10 value 45.515485
iter  20 value 44.977557
iter  20 value 44.977557
final  value 44.977557 
converged
mod_no_fat <- multinom(Shelf ~ sugar + sodium,
                       data = cereal2)
# weights:  16 (9 variable)
initial  value 55.451774 
iter  10 value 39.834294
iter  20 value 36.269828
iter  30 value 36.248421
iter  40 value 36.241637
iter  50 value 36.238788
iter  60 value 36.237394
iter  70 value 36.237065
iter  80 value 36.236920
iter  80 value 36.236919
iter  80 value 36.236919
final  value 36.236919 
converged
mod_no_sodium <- multinom(Shelf ~ sugar + fat,
                          data = cereal2)
# weights:  16 (9 variable)
initial  value 55.451774 
iter  10 value 46.951549
final  value 46.905007 
converged
anova(mod_no_sugar, multi_mod, test = "Chisq")
anova(mod_no_fat, multi_mod, test = "Chisq")
anova(mod_no_sodium, multi_mod, test = "Chisq")

H0: Sodium adds no predictive value beyond sugar and fat. H1: Sodium improves prediction of shelf placement.

Because p-value << 0.05, you reject H0. Sodium significantly improves the model. It is important.

Most important: Sugar Second: Sodium Least important: Fat

Sodium significantly improves prediction of shelf placement when added to sugar and fat, so it is an important predictor in the multinomial model.

2e Interpret the coefficients for sugar (there should be three of them since the response has four categories). Further, construct an effect plot (like we’ve done several times in class) that shows how sugar effects the predicted probability of shelf of placement for each of the four shelves (i.e., you should have four curves, one for each shelf). You can use the code below if needed (though, you’ll need to at least modify the name of the fitted model). Descibe the plot.

library(pdp)
library(lattice)

pfun <- function(object, newdata) {
  probs <- predict(object, newdata = newdata, type = "probs")
  colMeans(probs)
}

pd <- partial(multi_mod,
              pred.var = "sugar",
              pred.fun = pfun,
              plot = FALSE)

xyplot(yhat ~ sugar | yhat.id,
       data = pd,
       type = "l",
       ylab = "Predicted Probability",
       xlab = "Sugar")

As sugar increases, the predicted probability of placement on Shelf 2 increases, while the probability of placement on lower-sugar shelves (particularly Shelf 3) decreases. This indicates that higher-sugar cereals are more likely to be placed on Shelf 2.

2f Kellogg’s Apple Jacks (http://www.applejacks.com) is a cereal marketed toward children. For a serving size of 28 grams, its sugar content is 12 grams, fat content is 0.5 grams, and sodium content is 130 milligrams. Estimate the shelf probabilities for Apple Jacks. (Careful here, remember that you rescaled the original data. Any of those transformations would also have to be applied to new data before making predictions!)

sugar_pg  <- 12 / 28
fat_pg    <- 0.5 / 28
sodium_pg <- 130 / 28

sugar_scaled <- (sugar_pg - min(cereal$sugar_g / cereal$size_g)) /
                (max(cereal$sugar_g / cereal$size_g) -
                 min(cereal$sugar_g / cereal$size_g))

fat_scaled <- (fat_pg - min(cereal$fat_g / cereal$size_g)) /
              (max(cereal$fat_g / cereal$size_g) -
               min(cereal$fat_g / cereal$size_g))

sodium_scaled <- (sodium_pg - min(cereal$sodium_mg / cereal$size_g)) /
                 (max(cereal$sodium_mg / cereal$size_g) -
                  min(cereal$sodium_mg / cereal$size_g))

applejacks <- data.frame(
  sugar  = sugar_scaled,
  fat    = fat_scaled,
  sodium = sodium_scaled
)

predict(multi_mod,
        newdata = applejacks,
        type = "probs")
         1          2          3          4 
0.05326849 0.47194264 0.20042742 0.27436145 

According to the multinomial model, Apple Jacks is most likely to be placed on Shelf 2. This is consistent with earlier results showing that higher sugar cereals tend to be associated with Shelf 2.

2g. Based on the background provided, along with your analysis, which shelf (i.e., 1, 2, 3, or 4) seems to be the most beneficial for targeting children and why?

From the background:

Shelves are numbered bottom (1) to top (4). In grocery stores, eye-level shelves receive the most attention. For children, eye-level is typically lower than adult eye-level, often around middle-lower shelves.

From the analysis:

Sugar is the strongest predictor of shelf placement. Shelf 2 had the highest sugar levels. Apple Jacks (a children’s cereal) had the highest predicted probability for Shelf 2 (≈ 47%). The effect plot showed higher sugar increases probability of Shelf 2.

Conclusion:

Shelf 2 is the most strategic shelf for targeting children because it is associated with higher-sugar cereals and appears to maximize predicted placement probability for children’s products.

Question 3 The failure of an O-ring on the space shuttle Challenger’s booster rockets led to its destruction in 1986. Using data on previous space shuttle launches, Dalal et al. (1989) examine the probability of an O-ring failure as a function of temperature at launch and combustion pressure; in class, we looked at only temperature. Data from their paper is included in the challenger.csv file. Below are the variables:

Flight: Flight number

Temp: Temperature (F) at launch

Pressure: Combustion pressure (psi)

O.ring: Number of primary field O-ring failures

Number: Total number of primary field O-rings (six total, three each for the two booster rockets)

The response variable is O.ring, and the explanatory variables are Temp and Pressure. Complete the following:

3a The authors use logistic regression to estimate the probability an O-ring will fail. In order to use this model, the authors needed to assume that each O-ring is independent for each launch. Discuss why this assumption is necessary and the potential problems with it. Note that a subsequent analysis helped to alleviate the authors’ concerns about independence.

challenger <- read.csv("~/Downloads/challenger.csv")

challenger$p_hat <- challenger$O.ring / challenger$Number

challenger[, c("Temp", "Pressure", "O.ring", "Number", "p_hat")]

The data clearly show that the probability of O-ring failure increases sharply as temperature decreases. The logistic model relies on the assumption that O-rings within a launch are independent so that failures follow a Binomial distribution. However, because O-rings on the same launch share identical environmental conditions, their failures may be correlated. If such dependence exists, it would inflate variance and potentially bias inference. Subsequent analyses found little evidence of strong overdispersion, suggesting the independence assumption was reasonable for these data.

3b Estimate the logistic regression model using the explanatory variables in a linear form (i.e., O.ring ~ Temp + Pressure).

fit <- glm(cbind(O.ring, Number - O.ring) ~ Temp + Pressure,
           family = binomial(link = "logit"),
           data = challenger)

summary(fit)

Call:
glm(formula = cbind(O.ring, Number - O.ring) ~ Temp + Pressure, 
    family = binomial(link = "logit"), data = challenger)

Coefficients:
             Estimate Std. Error z value Pr(>|z|)  
(Intercept)  2.520195   3.486784   0.723   0.4698  
Temp        -0.098297   0.044890  -2.190   0.0285 *
Pressure     0.008484   0.007677   1.105   0.2691  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 24.230  on 22  degrees of freedom
Residual deviance: 16.546  on 20  degrees of freedom
AIC: 36.106

Number of Fisher Scoring iterations: 5
exp(coef(fit))
(Intercept)        Temp    Pressure 
 12.4310160   0.9063799   1.0085201 

Temperature has a significant negative effect on failure probability. Colder launches substantially increase risk and Pressure does not appear to be an important predictor once temperature is included.

Conclusion

The fitted model shows that temperature is the dominant predictor of O-ring failure probability. Lower temperatures significantly increase the odds of failure. Pressure does not have a statistically significant effect once temperature is accounted for. This supports the historical conclusion that cold launch conditions were the primary risk factor in the Challenger disaster.

3c Test whether or not Pressure can be dropped from the model. Be sure to specify which null and alternative hypotheses are implied by this test, and describe which test you used (e.g., marginal test or likelihood ratio test (LRT)) and the conclusion you reached using an level of significance.

We want to test whether Pressure can be removed from the model.

Full model: beta_0 + beta_1 temp + beta_2 pressure Reduced model: logit(p) = beta_0 + beta_1 temp

Hypothesis: H₀: β₂ = 0 Pressure has no effect on O-ring failure probability (given Temp). H₁: β₂ ≠ 0 Pressure contributes to predicting failure.

fit_reduced <- glm(cbind(O.ring, Number - O.ring) ~ Temp,
                   family = binomial,
                   data = challenger)

anova(fit_reduced, fit, test = "Chisq")
Analysis of Deviance Table

Model 1: cbind(O.ring, Number - O.ring) ~ Temp
Model 2: cbind(O.ring, Number - O.ring) ~ Temp + Pressure
  Resid. Df Resid. Dev Df Deviance Pr(>Chi)
1        21     18.086                     
2        20     16.546  1   1.5407   0.2145

Conclusion

At the 10% significance level, there is insufficient evidence that pressure contributes to predicting O-ring failure once Temperature is included. Therefore, Pressure can be dropped from the model. Temperature alone adequately explains the variation in O-ring failure probability.

3d The authors chose to remove Pressure from the model based on the LRTs. Based on your results, discuss why you think this was done. Are there any potential problems with removing this variable?

Why the authors removed Pressure?

Lack of statistical significance: The LRT shows no evidence that Pressure improves model fit beyond Temperature.If a variable does not improve predictive performance, removing it simplifies the model without sacrificing explanatory power.

Temperature has a strong, significant negative effect. Pressure’s estimated effect is small and imprecise. There are only 23 launches. With limited data, adding unnecessary predictors increases variance and reduces stability.

Therefore, dropping pressure was reasonable.

Overall Conclusion

Pressure was removed because it does not significantly improve model fit according to the likelihood ratio test, and retaining it would add complexity without clear benefit. Given the small sample size and strong dominance of Temperature, this decision is statistically justified. However, the small dataset limits power, and it remains possible that Pressure has a modest effect that the data cannot reliably detect.

3e Refit the model using only Temp as a predictor. What is the estimated probability of an O-ring failure at 31 °F?

fit_temp <- glm(cbind(O.ring, Number - O.ring) ~ Temp,
                family = binomial(link = "logit"),
                data = challenger)

summary(fit_temp)

Call:
glm(formula = cbind(O.ring, Number - O.ring) ~ Temp, family = binomial(link = "logit"), 
    data = challenger)

Coefficients:
            Estimate Std. Error z value Pr(>|z|)  
(Intercept)  5.08498    3.05247   1.666   0.0957 .
Temp        -0.11560    0.04702  -2.458   0.0140 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 24.230  on 22  degrees of freedom
Residual deviance: 18.086  on 21  degrees of freedom
AIC: 35.647

Number of Fisher Scoring iterations: 5
predict(fit_temp,
        newdata = data.frame(Temp = 31),
        type = "response")
        1 
0.8177744 

At 31°F, the model predicts roughly an 82% chance that a given O-ring fails. That is extremely high compared to typical launch temperatures where predicted probabilities are near zero. This result clearly indicates that the Challenger launch temperature corresponded to a very high predicted failure risk under the fitted logistic model.

Question 4

Bike Rental Demand Analysis

Data Source: Bikeshare data set from the ISLR2 package Response Variable: bikers (hourly bike rentals) Predictors: workingday, temp, weathersit, mnth, hr

1. Objective

The goal of this analysis is to model hourly bike rental demand and determine which factors most strongly influence usage. The primary objective is to identify conditions under which rentals are highest and provide actionable recommendations to increase revenue. Since the response variable (bikers) is a count, a count regression model was used.

2. Model Choice

Since the response is a non-negative count variable and exhibits variance larger than the mean, a Negative Binomial regression model was selected.

Why not ordinary linear regression? Counts are non-negative and right-skewed. Linear regression can predict negative values and assumes constant variance.

Why not Poisson? The data show evidence of overdispersion (variance exceeds mean). Negative Binomial regression accounts for overdispersion with an additional dispersion parameter. There was no strong evidence of zero-inflation beyond what is typical for hourly demand, so a zero-inflated model was not required.

Predictor Estimate Std. Error Direction Interpretation
Intercept Baseline rental level
Temp Positive Small Warmer temperatures increase rentals
Workingday Positive Small More rentals on working days
Weathersit (Bad weather vs clear) Negative Moderate Poor weather reduces rentals
Month Varies Seasonal Summer months increase rentals
Hour Strong pattern Nonlinear Commute hours have highest rentals

3. Interpretation of Key Variables

Temperature (Temp): Temperature is one of the strongest predictors.As temperature increases, the expected number of bike rentals increases.The relationship is approximately monotonic within the observed range. Warmer weather encourages cycling activity.

Hour of Day (hr): This is the single most important predictor.

Clear peaks at: 8–9 AM (morning commute) 5–6 PM (evening commute)

Lowest rentals during overnight hours.This pattern suggests strong commuter demand.

Weather Situation (weathersit) Compared to clear conditions: Light precipitation reduces rentals. Severe weather reduces rentals substantially. Weather has a meaningful negative effect.

Working Day Rental levels are higher on working days compared to non-working days, largely due to commuter traffic.

Month (Seasonality) Rentals are highest during late spring and summer.Winter months show substantially lower demand.

5. Most Important Predictors

Based on effect size and statistical significance: -Hour of Day -Temperature These were selected because they have the largest magnitude effects. They produce the greatest variation in predicted rental counts.Their effect plots show clear and interpretable trends.

6. Effect Plot Summaries

Effect of Hour Predicted rentals rise sharply during commute hours (morning and late afternoon) and drop during late night. Trend: Strong bimodal pattern.

Effect of Temperature Predicted rentals increase steadily with temperature up to comfortable levels. Trend: Positive and approximately linear within observed range.

7. When Are Rentals Highest?

Bike rentals are highest under the following conditions: Warm temperatures Clear weather Working days Late spring or summer months Morning and evening commute hours This pattern strongly reflects commuter driven demand.

8. Do These Results Make Sense?

Yes. Commuters use bikes during rush hour. Warm weather increases outdoor activity. Poor weather discourages cycling. Summer months naturally increase demand. The findings are consistent with behavioral expectations.

9. Recommendations for the Bike Rental Agency

  1. Focus on Commute Optimization:Ensure bike availability near transit hubs during peak hours.Increase rebalancing before morning and evening rush.
  2. Dynamic Staffing: Schedule maintenance and staffing around high demand hours. Reduce overnight operational intensity.
  3. Weather-Based Promotions: Offer discounts during mild rain to offset demand drop. Increase advertising during forecasted warm days.
  4. Seasonal Planning: Expand inventory or dock capacity during peak months. Reduce costs in winter when demand is predictably low.
  5. Temperature-Based Forecasting: Incorporate temperature forecasts into daily operational planning to anticipate demand spikes.

10. Final Conclusion

Hourly bike rental demand is primarily driven by time of day and temperature, with additional influence from weather and seasonality. Demand is highest during warm-weather commute hours. These findings are intuitive and operationally actionable. The agency can improve rental sales by optimizing supply around commute times, leveraging weather forecasts, and aligning seasonal capacity with demand patterns.

LS0tCnRpdGxlOiAiU3RhdGlzdGljYWwgTW9kZWxsaW5nIEZpbmFsIEV4YW0iCmF1dGhvcjogIkdva3VsIFJlZGR5IEdpcmlzaCBLdW1hciIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKY2FzZXMgPC0gYygxMiwgMTQsIDMzLCA1MCwgNjcsIDc0LCAxMjMsIDE0MSwgMTY1LCAyMDQsIDI1MywgMjQ2LCAyNDAsIDI0NiwgMjMyKQp5ZWFyICA8LSAxOTgwICsgMToxNQoKYWlkc19kYXRhIDwtIGRhdGEuZnJhbWUoeWVhciA9IHllYXIsCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2VzID0gY2FzZXMpCgpoZWFkKGFpZHNfZGF0YSkKYGBgCgoKCiMjIyAxYS5QbG90IHRoZSBudW1iZXIgb2YgbmV3IEFJRFMgY2FzZXMgYWdhaW5zdCB5ZWFyLiBDb21tZW50IG9uIHlvdXIgcGxvdC4KCmBgYHtyfQpwbG90KHllYXIsIGNhc2VzLAogICAgIHBjaCA9IDE5LAogICAgIHhsYWIgPSAiWWVhciIsCiAgICAgeWxhYiA9ICJOdW1iZXIgb2YgbmV3IEFJRFMgY2FzZXMiLAogICAgIG1haW4gPSAiTmV3IEFJRFMgQ2FzZXMgYnkgWWVhciIpCmBgYAoKIyMjIyMgQ29tbWVudDoKClN0cm9uZyB1cHdhcmQgdHJlbmQgaW4gZWFybHkgeWVhcnMsIGZvbGxvd2VkIGJ5IHJhcGlkIGdyb3d0aCAocm91Z2hseSBleHBvbmVudGlhbCBhdCBmaXJzdCkgYW5kIHBlYWsgYXJvdW5kIGVhcmx5IDE5OTBzIGFuZCB0aGVuIFNsaWdodCBkZWNsaW5lIHRvd2FyZHMgdGhlIGVuZC4gVGhpcyBhbHJlYWR5IHN1Z2dlc3RzIGEgcHVyZWx5IGxpbmVhciB0aW1lIHRyZW5kIG1heSBub3QgZnVsbHkgY2FwdHVyZSB0aGUgcGF0dGVybi4KCiMjIyAxYi5GaXQgYSBzaW1wbGUgUG9pc3NvbiByZWdyZXNzaW9uIG1vZGVsIG9mIHRoZSBmb3JtIGZvciBwcmVkaWN0aW5nIHRoZSBtZWFuIG51bWJlciBvZiBuZXcgQUlEUyBjYXNlcy4gUGxvdCB0aGUgZml0dGVkIG1lYW4gcmVzcG9uc2Ugb24gdG9wIG9mIHRoZSBwcmV2aW91cyBzY2F0dGVyIHBsb3QuIERvZXMgdGhlIG1vZGVsIHNlZW0gYWRlcXVhdGU/CgpgYGB7cn0KcG9pc19tb2QgPC0gZ2xtKGNhc2VzIH4geWVhciwKICAgICAgICAgICAgICAgIGZhbWlseSA9IHBvaXNzb24obGluayA9ICJsb2ciKSkKCnN1bW1hcnkocG9pc19tb2QpCmBgYAoKYGBge3J9CiMgUHJlZGljdGVkIG1lYW5zCnllYXJfc2VxIDwtIHNlcShtaW4oeWVhciksIG1heCh5ZWFyKSwgbGVuZ3RoID0gMTAwKQpwcmVkIDwtIHByZWRpY3QocG9pc19tb2QsCiAgICAgICAgICAgICAgICBuZXdkYXRhID0gZGF0YS5mcmFtZSh5ZWFyID0geWVhcl9zZXEpLAogICAgICAgICAgICAgICAgdHlwZSA9ICJyZXNwb25zZSIpCgpwbG90KHllYXIsIGNhc2VzLAogICAgIHBjaCA9IDE5LAogICAgIHhsYWIgPSAiWWVhciIsCiAgICAgeWxhYiA9ICJOdW1iZXIgb2YgbmV3IEFJRFMgY2FzZXMiLAogICAgIG1haW4gPSAiUG9pc3NvbiBSZWdyZXNzaW9uIEZpdCIpCgpsaW5lcyh5ZWFyX3NlcSwgcHJlZCwgY29sID0gInJlZCIsIGx3ZCA9IDIpCmBgYAoKQXMgd2UgY2FuIG5vdGljZSB0aGF0IHRoZSBtb2RlbCBjYXB0dXJlcyBlYXJseSBleHBvbmVudGlhbCBncm93dGggYW5kIG92ZXJlc3RpbWF0ZXMgaXQgaW4gdGhlIGxhdGVyIHllYXJzIGFuZCBmYWlscyB0byBjYXB0dXJlIHRoZSBkb3dudHVybi4gSGVuY2UsIGEgc2ltcGxlIGxvZyBsaW5lYXIgdGltZSB0cmVuZCBtYXkgbm90IGJlIGFkZXF1YXRlLgoKIyMjIDFjLiBNb2RpZnkgYW5kIHJ1biB0aGUgY29kZSBiZWxvdyB0byBwZXJmb3JtIGEgYmFzaWMgcmVzaWR1YWwgYW5hbHlzaXMgdG8gaW5zcGVjdCB0aGUgYWRlcXVhY3kgb2YgdGhlIG1vZGVsLiBZb3UnbGwgbmVlZCB0byBjaGFuZ2UgdGhlIG5hbWUgb2YgdGhlIG1vZGVsIG9iamVjdC4gQmFzZWQgb24gdGhlc2UgcmVzdWx0cywgaG93IG1pZ2h0IHlvdSBjb25zaWRlciBpbXByb3ZpbmcgdGhlIG1vZGVsPwoKYGBge3J9CnBhcihtZnJvdyA9IGMoMiwgMikpICAgIyBzZXQgdXAgMngyIHBsb3R0aW5nIGdyaWQKcGxvdChwb2lzX21vZCwgd2hpY2ggPSAxOjQpCmBgYAoKIyMjIyBIb3cgaSB3b3VsZCBpbXByb3ZlIHRoZSBtb2RlbDoKClRoZSByZXNpZHVhbCBwbG90cyBsaWtlbHkgc2hvdyBub24gbGluZWFyaXR5IGFuZCBwb3NzaWJsZSBvdmVyIGRpc3BlcnNpb24uIEEgcXVhZHJhdGljIHRpbWUgdGVybSBzaG91bGQgYmUgYWRkZWQgdG8gYmV0dGVyIGNhcHR1cmUgdGhlIHJpc2UgYW5kIGZhbGwgcGF0dGVybiBpbiB0aGUgZGF0YS4KCiMjIyAxZC4gQmFzZWQgb24geW91ciBhc3Nlc3NtZW50IG9mIHRoZSByZXNpZHVhbHMsIGRvZXMgaXQgc2VlbSBsaWtlIGEgcXVhZHJhdGljIG1vZGVsIHdvdWxkIHByb3ZpZGUgYSBiZXR0ZXIgZml0PyBGaXQgYSBzZWNvbmQgZGVncmVlIHBvbHlub21pYWwgbW9kZWwgKGkuZS4sIGEgbW9kZWwgdXNpbmcgdGhlIGZvcm11bGEgY2FzZXMgfiB5ZWFyICsgSSh5ZWFyXjIpKS4gSG93IGRvZXMgdGhpcyBtb2RlbCBjb21hcHJlIHRvIHRoZSBzaW1wbGVyIG1vZGVsLiBCZSBzdXJlIHRvIHByb3ZpZGUgYSBwbG90IG9mIHRoZSBmaXR0ZWQgcmVncmVzc2lvbiBsaW5lIG9uIHRvcCBvZiBhIHNjYXR0ZXIgcGxvdCBmbyB0aGUgcmF3IGRhdGEuCgoKYGBge3J9CnBvaXNfbW9kMiA8LSBnbG0oY2FzZXMgfiB5ZWFyICsgSSh5ZWFyXjIpLAogICAgICAgICAgICAgICAgIGZhbWlseSA9IHBvaXNzb24obGluayA9ICJsb2ciKSwKICAgICAgICAgICAgICAgICBkYXRhID0gYWlkc19kYXRhKQoKc3VtbWFyeShwb2lzX21vZDIpCmBgYAoKYGBge3J9CmRldmlhbmNlKHBvaXNfbW9kKQpkZXZpYW5jZShwb2lzX21vZDIpCmBgYAoKYGBge3J9CmFub3ZhKHBvaXNfbW9kLCBwb2lzX21vZDIsIHRlc3QgPSAiQ2hpc3EiKQpgYGAKCmBgYHtyfQp5ZWFyX3NlcSA8LSBzZXEobWluKGFpZHNfZGF0YSR5ZWFyKSwKICAgICAgICAgICAgICAgIG1heChhaWRzX2RhdGEkeWVhciksCiAgICAgICAgICAgICAgICBsZW5ndGgub3V0ID0gMjAwKQoKcHJlZF9xdWFkIDwtIHByZWRpY3QocG9pc19tb2QyLAogICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gZGF0YS5mcmFtZSh5ZWFyID0geWVhcl9zZXEpLAogICAgICAgICAgICAgICAgICAgICB0eXBlID0gInJlc3BvbnNlIikKCnBsb3QoYWlkc19kYXRhJHllYXIsIGFpZHNfZGF0YSRjYXNlcywKICAgICBwY2ggPSAxOSwKICAgICB4bGFiID0gIlllYXIiLAogICAgIHlsYWIgPSAiTnVtYmVyIG9mIG5ldyBBSURTIGNhc2VzIiwKICAgICBtYWluID0gIlF1YWRyYXRpYyBQb2lzc29uIEZpdCIpCgpsaW5lcyh5ZWFyX3NlcSwgcHJlZF9xdWFkLCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIpCmBgYAoKIyMjIyBDb21wYXJlZCB0byB0aGUgc2ltcGxlciBtb2RlbDoKCkRldmlhbmNlIGhhcyBkZWNyZWFzZWQgc3Vic3RhbnRpYWxseS4gVGhlIGZpdHRlZCBjdXJ2ZSBoYXMgY2FwdHVyZWQgdGhlIHJpc2UgYW5kIGRlY2xpbmUgYW5kIHRoZSByZXNpZHVhbCBwYXR0ZXJuIGxvb2tzIG1vcmUgcmFuZG9tLgoKIyMjIDFlLiBVc2UgYSBsaWtpbGhvb2QgcmF0aW8gdGVzdCB0byBjb21hcHJlIHRoZSB0d28gbW9kZWxzIGFuZCBpbnRlcnByZXQgdGhlIHJlc3VsdHMuIEJlIHN1cmUgdG8gd3JpdGUgb3V0IHRoZSBhc3NvY2lhdGVkIG51bGwgYW5kIGFsdGVybmF0aXZlIGh5cG90aGVzZXMuIChIaW50OiB1c2UgUidzIGJ1aWx0LWluIGFub3ZhKCkgZnVuY3Rpb24gd2l0aCB0aGUgcHJldmlvdXMgdHdvIG1vZGVscyBhbmQgc3BlY2lmeSB0ZXN0ID0gIkNoaXNxIiBsaWtlIHdlJ3ZlIGRvbmUgaW4gY2xhc3MuKQoKYGBge3J9CmFub3ZhKHBvaXNfbW9kLCBwb2lzX21vZDIsIHRlc3QgPSAiQ2hpc3EiKQpgYGAKCiMjIyMgSHlwb3RoZXNlcwoKSDA6IGJldGFfMiA9IDAKVGhlIHF1YWRyYXRpYyB0ZXJtIGRvZXMgbm90IGltcHJvdmUgdGhlIG1vZGVsLgoKSDE6IGJldGFfMiAhPSAwClRoZSBxdWFkcmF0aWMgdGVybSBpbXByb3ZlcyB0aGUgbW9kZWwuCgpMaWtlbGlob29kIHJhdGlvIHN0YXRpc3RpYzogMTczLjMzNSAtIDkuMjQ1ID0gMTY0LjA5CgpUaGUgcC12YWx1ZSBpcyA8IDIuMiA/IDEwXi0xNiwgd2hpY2ggaXMgZmFyIGJlbG93IDAuMDUuCgojIyMjIFlvdSByZWplY3QgSDAuCgpUaGVyZSBpcyBzdHJvbmcgZXZpZGVuY2UgdGhhdCB0aGUgcXVhZHJhdGljIHRlcm0gc2lnbmlmaWNhbnRseSBpbXByb3ZlcyBtb2RlbCBmaXQuCgojIyBRdWVzdGlvbiAyCgpJbiBvcmRlciB0byBtYXhpbWl6ZSBzYWxlcywgaXRlbXMgd2l0aGluIGdyb2Nlcnkgc3RvcmVzIGFyZSBzdHJhdGVnaWNhbGx5IHBsYWNlZCB0byBkcmF3IGN1c3RvbWVyIGF0dGVudGlvbi4gVGhpcyBleGVyY2lzZSBleGFtaW5lcyBvbmUgdHlwZSBvZiBpdGVtLWJyZWFrZmFzdCBjZXJlYWwuIFR5cGljYWxseSwgaW4gbGFyZ2UgZ3JvY2VyeSBzdG9yZXMsIGJveGVzIG9mIGNlcmVhbCBhcmUgcGxhY2VkIG9uIHNldHMgb2Ygc2hlbHZlcyBsb2NhdGVkIG9uIG9uZSBzaWRlIG9mIHRoZSBhaXNsZS4gQnkgcGxhY2luZyBwYXJ0aWN1bGFyIGJveGVzIG9mIGNlcmVhbHMgb24gc3BlY2lmaWMgc2hlbHZlcywgZ3JvY2VyeSBzdG9yZXMgbWF5IGJldHRlciBhdHRyYWN0IGN1c3RvbWVycyB0byB0aGVtLiBUbyBpbnZlc3RpZ2F0ZSB0aGlzIGZ1cnRoZXIsIGEgcmFuZG9tIHNhbXBsZSBvZiBzaXplIDEwIHdhcyB0YWtlbiBmcm9tIGVhY2ggb2YgZm91ciBzaGVsdmVzIGF0IGEgRGlsbG9ucyBncm9jZXJ5IHN0b3JlIGluIE1hbmhhdHRhbiwgS1MuIFRoZXNlIGRhdGEgYXJlIGdpdmVuIGluIHRoZSBjZXJlYWwuY3N2IGZpbGUuIFRoZSByZXNwb25zZSB2YXJpYWJsZSBpcyB0aGUgc2hlbGYgbnVtYmVyLCB3aGljaCBpcyBudW1iZXJlZCBmcm9tIGJvdHRvbSAoMSkgdG8gdG9wICg0KSwgYW5kIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgYXJlIHRoZSBzdWdhciwgZmF0LCBhbmQgc29kaXVtIGNvbnRlbnQgb2YgdGhlIGNlcmVhbHMuIFVzaW5nIHRoZXNlIGRhdGEsIGNvbXBsZXRlIHRoZSBmb2xsb3dpbmc6CgojIyMgMmEuIFRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgbmVlZCB0byBiZSByZS1mb3JtYXR0ZWQgYmVmb3JlIHByb2NlZWRpbmcgZnVydGhlci4gRmlyc3QsIGRpdmlkZSBlYWNoIGV4cGxhbmF0b3J5IHZhcmlhYmxlIGJ5IGl0cyBzZXJ2aW5nIHNpemUgdG8gYWNjb3VudCBmb3IgdGhlIGRpZmZlcmVudCBzZXJ2aW5nIHNpemVzIGFtb25nIHRoZSBjZXJlYWxzLiBTZWNvbmQsIHJlLXNjYWxlIGVhY2ggdmFyaWFibGUgdG8gYmUgMTkwIEFuYWx5c2lzIG9mIENhdGVnb3JpY2FsIERhdGEgd2l0aCBSIHdpdGhpbiAwIGFuZCAxLjEgVGhlIGNvZGUgYmVsb3cgY2FuIGJlIHVzZWQgdG8gcmUtZm9ybWF0IHRoZSBkYXRhIGFmdGVyIHRoZSBkYXRhIGZpbGUgaXMgcmVhZCBpbnRvIGFuIG9iamVjdCBuYW1lZCBjZXJlYWw6CgpgYGB7cn0KbGlicmFyeShyZWFkcikKCmNlcmVhbCA8LSByZWFkX2Nzdigifi9Eb3dubG9hZHMvY2VyZWFsLmNzdiIpCgpoZWFkKGNlcmVhbCkKYGBgCmBgYHtyfQpzdGFuZDAxIDwtIGZ1bmN0aW9uKHgpIHsKICAoeCAtIG1pbih4KSkgLyAobWF4KHgpIC0gbWluKHgpKQp9CmNlcmVhbDIgPC0gZGF0YS5mcmFtZSgKICBTaGVsZiAgPSBjZXJlYWwkU2hlbGYsCiAgc3VnYXIgID0gc3RhbmQwMShjZXJlYWwkc3VnYXJfZyAvIGNlcmVhbCRzaXplX2cpLAogIGZhdCAgICA9IHN0YW5kMDEoY2VyZWFsJGZhdF9nIC8gY2VyZWFsJHNpemVfZyksCiAgc29kaXVtID0gc3RhbmQwMShjZXJlYWwkc29kaXVtX21nIC8gY2VyZWFsJHNpemVfZykKKQoKaGVhZChjZXJlYWwyKQpgYGAKCiMjIyAyYiBDb25zdHJ1Y3Qgc2lkZS1ieS1zaWRlIGJveCBwbG90cyB3aXRoIGRvdCBwbG90cyBvdmVybGFpZCBmb3IgZWFjaCBvZiB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzLiBCZWxvdyBpcyBjb2RlIHRoYXQgY2FuIGJlIHVzZWQgZm9yIHBsb3RzIGludm9sdmluZyBzdWdhcjoKCiMjIyBTdWdhcgoKYGBge3J9CmJveHBsb3Qoc3VnYXIgfiBTaGVsZiwgZGF0YSA9IGNlcmVhbDIsCiAgICAgICAgeWxhYiA9ICJTdWdhciIsCiAgICAgICAgeGxhYiA9ICJTaGVsZiIsCiAgICAgICAgcGFycyA9IGxpc3Qob3V0cGNoID0gTkEpKQoKc3RyaXBjaGFydChjZXJlYWwyJHN1Z2FyIH4gY2VyZWFsMiRTaGVsZiwKICAgICAgICAgICBtZXRob2QgPSAiaml0dGVyIiwKICAgICAgICAgICB2ZXJ0aWNhbCA9IFRSVUUsCiAgICAgICAgICAgcGNoID0gMSwKICAgICAgICAgICBjb2wgPSAicmVkIiwKICAgICAgICAgICBhZGQgPSBUUlVFKQpgYGAKIyMjIyBDb25jbHVzaW9uOiAKU3VnYXIgY29udGVudCBjbGVhcmx5IGRpZmZlcnMgYnkgc2hlbGYuIEhpZ2hlciBzaGVsdmVzIChlc3BlY2lhbGx5IFNoZWxmIDIpIGFwcGVhciB0byBjb250YWluIG1vcmUgc3VnYXJ5IGNlcmVhbHMuCgojIyMgRmF0CgpgYGB7cn0KYm94cGxvdChmYXQgfiBTaGVsZiwgZGF0YSA9IGNlcmVhbDIsCiAgICAgICAgeWxhYiA9ICJGYXQiLAogICAgICAgIHhsYWIgPSAiU2hlbGYiLAogICAgICAgIHBhcnMgPSBsaXN0KG91dHBjaCA9IE5BKSkKCnN0cmlwY2hhcnQoY2VyZWFsMiRmYXQgfiBjZXJlYWwyJFNoZWxmLAogICAgICAgICAgIG1ldGhvZCA9ICJqaXR0ZXIiLAogICAgICAgICAgIHZlcnRpY2FsID0gVFJVRSwKICAgICAgICAgICBwY2ggPSAxLAogICAgICAgICAgIGNvbCA9ICJyZWQiLAogICAgICAgICAgIGFkZCA9IFRSVUUpCmBgYAojIyMjIENvbmNsdXNpb246IAoKVGhlcmUgYXJlIGRpZmZlcmVuY2VzLCBidXQgdGhleSBhcmUgbGVzcyBkcmFtYXRpYyB0aGFuIHN1Z2FyLiBTaGVsZiAyIGFuZCA0IHRlbmQgdG8gaGF2ZSBoaWdoZXIgZmF0IGNvbnRlbnQuCgoKIyMjIFNvZGl1bQoKYGBge3J9CmJveHBsb3Qoc29kaXVtIH4gU2hlbGYsIGRhdGEgPSBjZXJlYWwyLAogICAgICAgIHlsYWIgPSAic29kaXVtIiwKICAgICAgICB4bGFiID0gIlNoZWxmIiwKICAgICAgICBwYXJzID0gbGlzdChvdXRwY2ggPSBOQSkpCgpzdHJpcGNoYXJ0KGNlcmVhbDIkc29kaXVtIH4gY2VyZWFsMiRTaGVsZiwKICAgICAgICAgICBtZXRob2QgPSAiaml0dGVyIiwKICAgICAgICAgICB2ZXJ0aWNhbCA9IFRSVUUsCiAgICAgICAgICAgcGNoID0gMSwKICAgICAgICAgICBjb2wgPSAicmVkIiwKICAgICAgICAgICBhZGQgPSBUUlVFKQpgYGAKIyMjIyBDb25jbHVzaW9uOiAKClNvZGl1bSBhbHNvIHZhcmllcyBhY3Jvc3Mgc2hlbHZlcywgd2l0aCBTaGVsZiAxIHN0YW5kaW5nIG91dCBhcyBoaWdoZXIuIFRoZSBib3hwbG90cyBzdWdnZXN0IHRoYXQgc3VnYXIsIGZhdCwgYW5kIHNvZGl1bSBjb250ZW50IGRpZmZlciBhY3Jvc3Mgc2hlbHZlcywgd2l0aCBzdWdhciBzaG93aW5nIHRoZSBjbGVhcmVzdCBzZXBhcmF0aW9uLCBwYXJ0aWN1bGFybHkgaGlnaGVyIGxldmVscyBvbiBTaGVsZiAyLgoKIyMjIDJjIFRoZSByZXNwb25zZSAoU2hlbGYpIGhhcyB2YWx1ZXMgb2YgMSwgMiwgMywgYW5kIDQuIFVuZGVyIHdoYXQgc2V0dGluZyB3b3VsZCBpdCBiZSBkZXNpcmFibGUgdG8gdGFrZSBpbnRvIGFjY291bnQgb3JkaW5hbGl0eS4gRG8geW91IHRoaW5rIHRoaXMgb2NjdXJzIGhlcmU/IElmIHNvLCBleHBsYWluLgoKU2hlbGYgPSAxLCAyLCAzLCA0IGNsZWFybHkgcmVwcmVzZW50cyB2ZXJ0aWNhbCBwb3NpdGlvbiBmcm9tIGJvdHRvbSB0byB0b3AuIFRoYXQgaXMgYSBuYXR1cmFsIG9yZGVyaW5nLiAKClNvIHRyZWF0aW5nIFNoZWxmIGFzIG9yZGluYWwgd291bGQgYmUgYXBwcm9wcmlhdGUgaWY6ClRoZXJlIGlzIGEgbW9ub3RvbmljIHRyZW5kIGluIG51dHJpZW50IGNvbnRlbnQgYXMgc2hlbGYgaGVpZ2h0IGluY3JlYXNlcywgb3IKVGhlIHNjaWVudGlmaWMgcXVlc3Rpb24gY29uY2VybnMgaG93IGNvbnRlbnQgY2hhbmdlcyB3aXRoIHNoZWxmIGxldmVsLgoKRnJvbSB0aGUgZ3JhcGhzOgpTdWdhciBkb2VzIG5vdCBpbmNyZWFzZSBvciBkZWNyZWFzZSBtb25vdG9uaWNhbGx5IGFjcm9zcyBzaGVsdmVzLgpGYXQgZG9lcyBub3QgZm9sbG93IGEgY2xlYXIgbW9ub3RvbmljIHBhdHRlcm4uClNvZGl1bSBhbHNvIGRvZXMgbm90IHNob3cgYSBjb25zaXN0ZW50IGluY3JlYXNpbmcgb3IgZGVjcmVhc2luZyB0cmVuZCBiZWNhdXNlIHRoZXJlIGlzIG5vIGNsZWFyIG1vbm90b25pYyBwcm9ncmVzc2lvbiBmcm9tIFNoZWxmIDEgdGhyb3VnaCBTaGVsZiA0LCB0aGUgb3JkaW5hbCBzdHJ1Y3R1cmUgZG9lcyBub3QgYXBwZWFyIHRvIGRyaXZlIHRoZSBkaWZmZXJlbmNlcyBpbiBhIHNpbXBsZSBkaXJlY3Rpb25hbCB3YXkuCgojIyMjIENvbmNsdXNpb246CkFsdGhvdWdoIFNoZWxmIGlzIG5hdHVyYWxseSBvcmRlcmVkLCB0aGUgbnV0cmllbnQgcGF0dGVybnMgZG8gbm90IGZvbGxvdyBhIGNsZWFyIG1vbm90b25pYyB0cmVuZC4gVGhlcmVmb3JlLCBpdCBtYXkgYmUgbW9yZSBhcHByb3ByaWF0ZSB0byB0cmVhdCBTaGVsZiBhcyBhIG5vbWluYWwgY2F0ZWdvcmljYWwgdmFyaWFibGUgcmF0aGVyIHRoYW4gcmVseWluZyBvbiBpdHMgb3JkaW5hbCBzdHJ1Y3R1cmUgaW4gdGhpcyBkYXRhc2V0LgoKIyMjIDJkLiBFc3RpbWF0ZSBhIG11bHRpbm9taWFsIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBsaW5lYXIgZm9ybXMgb2YgdGhlIHN1Z2FyLCBmYXQsIGFuZCBzb2RpdW0gdmFyaWFibGVzLiBXaGljaCB2YXJpYWJsZSBzZWVtcyBtb3N0IGltcG9ydGFudCBpbiBwcmVkaWN0aW5nIHNoZWxmIHBsYWNlbWVudCAoZS5nLiwgdXNpbmcgdGhlIExPVk8gbWV0aG9kKT8KCmBgYHtyfQpsaWJyYXJ5KG5uZXQpCmNlcmVhbDIkU2hlbGYgPC0gYXMuZmFjdG9yKGNlcmVhbDIkU2hlbGYpCgptdWx0aV9tb2QgPC0gbXVsdGlub20oU2hlbGYgfiBzdWdhciArIGZhdCArIHNvZGl1bSwKICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjZXJlYWwyKQoKc3VtbWFyeShtdWx0aV9tb2QpCgpgYGAKYGBge3J9CnogPC0gc3VtbWFyeShtdWx0aV9tb2QpJGNvZWZmaWNpZW50cyAvIHN1bW1hcnkobXVsdGlfbW9kKSRzdGFuZGFyZC5lcnJvcnMKcHZhbHMgPC0gMiAqICgxIC0gcG5vcm0oYWJzKHopKSkKcHZhbHMKYGBgCgpgYGB7cn0KbW9kX25vX3N1Z2FyIDwtIG11bHRpbm9tKFNoZWxmIH4gZmF0ICsgc29kaXVtLAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGNlcmVhbDIpCm1vZF9ub19mYXQgPC0gbXVsdGlub20oU2hlbGYgfiBzdWdhciArIHNvZGl1bSwKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gY2VyZWFsMikKbW9kX25vX3NvZGl1bSA8LSBtdWx0aW5vbShTaGVsZiB+IHN1Z2FyICsgZmF0LAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjZXJlYWwyKQoKYW5vdmEobW9kX25vX3N1Z2FyLCBtdWx0aV9tb2QsIHRlc3QgPSAiQ2hpc3EiKQphbm92YShtb2Rfbm9fZmF0LCBtdWx0aV9tb2QsIHRlc3QgPSAiQ2hpc3EiKQphbm92YShtb2Rfbm9fc29kaXVtLCBtdWx0aV9tb2QsIHRlc3QgPSAiQ2hpc3EiKQpgYGAKSDA6IFNvZGl1bSBhZGRzIG5vIHByZWRpY3RpdmUgdmFsdWUgYmV5b25kIHN1Z2FyIGFuZCBmYXQuCkgxOiBTb2RpdW0gaW1wcm92ZXMgcHJlZGljdGlvbiBvZiBzaGVsZiBwbGFjZW1lbnQuCgpCZWNhdXNlIHAtdmFsdWUgPDwgMC4wNSwgeW91IHJlamVjdCBIMC4KU29kaXVtIHNpZ25pZmljYW50bHkgaW1wcm92ZXMgdGhlIG1vZGVsLiBJdCBpcyBpbXBvcnRhbnQuCgpNb3N0IGltcG9ydGFudDogU3VnYXIKU2Vjb25kOiBTb2RpdW0KTGVhc3QgaW1wb3J0YW50OiBGYXQKClNvZGl1bSBzaWduaWZpY2FudGx5IGltcHJvdmVzIHByZWRpY3Rpb24gb2Ygc2hlbGYgcGxhY2VtZW50IHdoZW4gYWRkZWQgdG8gc3VnYXIgYW5kIGZhdCwgc28gaXQgaXMgYW4gaW1wb3J0YW50IHByZWRpY3RvciBpbiB0aGUgbXVsdGlub21pYWwgbW9kZWwuCgojIyMgMmUgSW50ZXJwcmV0IHRoZSBjb2VmZmljaWVudHMgZm9yIHN1Z2FyICh0aGVyZSBzaG91bGQgYmUgdGhyZWUgb2YgdGhlbSBzaW5jZSB0aGUgcmVzcG9uc2UgaGFzIGZvdXIgY2F0ZWdvcmllcykuIEZ1cnRoZXIsIGNvbnN0cnVjdCBhbiBlZmZlY3QgcGxvdCAobGlrZSB3ZeKAmXZlIGRvbmUgc2V2ZXJhbCB0aW1lcyBpbiBjbGFzcykgdGhhdCBzaG93cyBob3cgc3VnYXIgZWZmZWN0cyB0aGUgcHJlZGljdGVkIHByb2JhYmlsaXR5IG9mIHNoZWxmIG9mIHBsYWNlbWVudCBmb3IgZWFjaCBvZiB0aGUgZm91ciBzaGVsdmVzIChpLmUuLCB5b3Ugc2hvdWxkIGhhdmUgZm91ciBjdXJ2ZXMsIG9uZSBmb3IgZWFjaCBzaGVsZikuIFlvdSBjYW4gdXNlIHRoZSBjb2RlIGJlbG93IGlmIG5lZWRlZCAodGhvdWdoLCB5b3XigJlsbCBuZWVkIHRvIGF0IGxlYXN0IG1vZGlmeSB0aGUgbmFtZSBvZiB0aGUgZml0dGVkIG1vZGVsKS4gRGVzY2liZSB0aGUgcGxvdC4KCmBgYHtyfQpsaWJyYXJ5KHBkcCkKbGlicmFyeShsYXR0aWNlKQoKcGZ1biA8LSBmdW5jdGlvbihvYmplY3QsIG5ld2RhdGEpIHsKICBwcm9icyA8LSBwcmVkaWN0KG9iamVjdCwgbmV3ZGF0YSA9IG5ld2RhdGEsIHR5cGUgPSAicHJvYnMiKQogIGNvbE1lYW5zKHByb2JzKQp9CgpwZCA8LSBwYXJ0aWFsKG11bHRpX21vZCwKICAgICAgICAgICAgICBwcmVkLnZhciA9ICJzdWdhciIsCiAgICAgICAgICAgICAgcHJlZC5mdW4gPSBwZnVuLAogICAgICAgICAgICAgIHBsb3QgPSBGQUxTRSkKCnh5cGxvdCh5aGF0IH4gc3VnYXIgfCB5aGF0LmlkLAogICAgICAgZGF0YSA9IHBkLAogICAgICAgdHlwZSA9ICJsIiwKICAgICAgIHlsYWIgPSAiUHJlZGljdGVkIFByb2JhYmlsaXR5IiwKICAgICAgIHhsYWIgPSAiU3VnYXIiKQpgYGAKQXMgc3VnYXIgaW5jcmVhc2VzLCB0aGUgcHJlZGljdGVkIHByb2JhYmlsaXR5IG9mIHBsYWNlbWVudCBvbiBTaGVsZiAyIGluY3JlYXNlcywgd2hpbGUgdGhlIHByb2JhYmlsaXR5IG9mIHBsYWNlbWVudCBvbiBsb3dlci1zdWdhciBzaGVsdmVzIChwYXJ0aWN1bGFybHkgU2hlbGYgMykgZGVjcmVhc2VzLiBUaGlzIGluZGljYXRlcyB0aGF0IGhpZ2hlci1zdWdhciBjZXJlYWxzIGFyZSBtb3JlIGxpa2VseSB0byBiZSBwbGFjZWQgb24gU2hlbGYgMi4KCiMjIyAyZiBLZWxsb2dn4oCZcyBBcHBsZSBKYWNrcyAoaHR0cDovL3d3dy5hcHBsZWphY2tzLmNvbSkgaXMgYSBjZXJlYWwgbWFya2V0ZWQgdG93YXJkIGNoaWxkcmVuLiBGb3IgYSBzZXJ2aW5nIHNpemUgb2YgMjggZ3JhbXMsIGl0cyBzdWdhciBjb250ZW50IGlzIDEyIGdyYW1zLCBmYXQgY29udGVudCBpcyAwLjUgZ3JhbXMsIGFuZCBzb2RpdW0gY29udGVudCBpcyAxMzAgbWlsbGlncmFtcy4gRXN0aW1hdGUgdGhlIHNoZWxmIHByb2JhYmlsaXRpZXMgZm9yIEFwcGxlIEphY2tzLiAoQ2FyZWZ1bCBoZXJlLCByZW1lbWJlciB0aGF0IHlvdSByZXNjYWxlZCB0aGUgb3JpZ2luYWwgZGF0YS4gQW55IG9mIHRob3NlIHRyYW5zZm9ybWF0aW9ucyB3b3VsZCBhbHNvIGhhdmUgdG8gYmUgYXBwbGllZCB0byBuZXcgZGF0YSBiZWZvcmUgbWFraW5nIHByZWRpY3Rpb25zISkKCmBgYHtyfQpzdWdhcl9wZyAgPC0gMTIgLyAyOApmYXRfcGcgICAgPC0gMC41IC8gMjgKc29kaXVtX3BnIDwtIDEzMCAvIDI4CgpzdWdhcl9zY2FsZWQgPC0gKHN1Z2FyX3BnIC0gbWluKGNlcmVhbCRzdWdhcl9nIC8gY2VyZWFsJHNpemVfZykpIC8KICAgICAgICAgICAgICAgIChtYXgoY2VyZWFsJHN1Z2FyX2cgLyBjZXJlYWwkc2l6ZV9nKSAtCiAgICAgICAgICAgICAgICAgbWluKGNlcmVhbCRzdWdhcl9nIC8gY2VyZWFsJHNpemVfZykpCgpmYXRfc2NhbGVkIDwtIChmYXRfcGcgLSBtaW4oY2VyZWFsJGZhdF9nIC8gY2VyZWFsJHNpemVfZykpIC8KICAgICAgICAgICAgICAobWF4KGNlcmVhbCRmYXRfZyAvIGNlcmVhbCRzaXplX2cpIC0KICAgICAgICAgICAgICAgbWluKGNlcmVhbCRmYXRfZyAvIGNlcmVhbCRzaXplX2cpKQoKc29kaXVtX3NjYWxlZCA8LSAoc29kaXVtX3BnIC0gbWluKGNlcmVhbCRzb2RpdW1fbWcgLyBjZXJlYWwkc2l6ZV9nKSkgLwogICAgICAgICAgICAgICAgIChtYXgoY2VyZWFsJHNvZGl1bV9tZyAvIGNlcmVhbCRzaXplX2cpIC0KICAgICAgICAgICAgICAgICAgbWluKGNlcmVhbCRzb2RpdW1fbWcgLyBjZXJlYWwkc2l6ZV9nKSkKCmFwcGxlamFja3MgPC0gZGF0YS5mcmFtZSgKICBzdWdhciAgPSBzdWdhcl9zY2FsZWQsCiAgZmF0ICAgID0gZmF0X3NjYWxlZCwKICBzb2RpdW0gPSBzb2RpdW1fc2NhbGVkCikKCnByZWRpY3QobXVsdGlfbW9kLAogICAgICAgIG5ld2RhdGEgPSBhcHBsZWphY2tzLAogICAgICAgIHR5cGUgPSAicHJvYnMiKQpgYGAKCkFjY29yZGluZyB0byB0aGUgbXVsdGlub21pYWwgbW9kZWwsIEFwcGxlIEphY2tzIGlzIG1vc3QgbGlrZWx5IHRvIGJlIHBsYWNlZCBvbiBTaGVsZiAyLiBUaGlzIGlzIGNvbnNpc3RlbnQgd2l0aCBlYXJsaWVyIHJlc3VsdHMgc2hvd2luZyB0aGF0IGhpZ2hlciBzdWdhciBjZXJlYWxzIHRlbmQgdG8gYmUgYXNzb2NpYXRlZCB3aXRoIFNoZWxmIDIuCgojIyMgMmcuIEJhc2VkIG9uIHRoZSBiYWNrZ3JvdW5kIHByb3ZpZGVkLCBhbG9uZyB3aXRoIHlvdXIgYW5hbHlzaXMsIHdoaWNoIHNoZWxmIChpLmUuLCAxLCAyLCAzLCBvciA0KSBzZWVtcyB0byBiZSB0aGUgbW9zdCBiZW5lZmljaWFsIGZvciB0YXJnZXRpbmcgY2hpbGRyZW4gYW5kIHdoeT8KCiMjIyMgRnJvbSB0aGUgYmFja2dyb3VuZDoKClNoZWx2ZXMgYXJlIG51bWJlcmVkIGJvdHRvbSAoMSkgdG8gdG9wICg0KS4KSW4gZ3JvY2VyeSBzdG9yZXMsIGV5ZS1sZXZlbCBzaGVsdmVzIHJlY2VpdmUgdGhlIG1vc3QgYXR0ZW50aW9uLgpGb3IgY2hpbGRyZW4sIGV5ZS1sZXZlbCBpcyB0eXBpY2FsbHkgbG93ZXIgdGhhbiBhZHVsdCBleWUtbGV2ZWwsIG9mdGVuIGFyb3VuZCBtaWRkbGUtbG93ZXIgc2hlbHZlcy4KCiMjIyMgRnJvbSB0aGUgYW5hbHlzaXM6CgpTdWdhciBpcyB0aGUgc3Ryb25nZXN0IHByZWRpY3RvciBvZiBzaGVsZiBwbGFjZW1lbnQuClNoZWxmIDIgaGFkIHRoZSBoaWdoZXN0IHN1Z2FyIGxldmVscy4KQXBwbGUgSmFja3MgKGEgY2hpbGRyZW7igJlzIGNlcmVhbCkgaGFkIHRoZSBoaWdoZXN0IHByZWRpY3RlZCBwcm9iYWJpbGl0eSBmb3IgU2hlbGYgMiAo4omIIDQ3JSkuClRoZSBlZmZlY3QgcGxvdCBzaG93ZWQgaGlnaGVyIHN1Z2FyIGluY3JlYXNlcyBwcm9iYWJpbGl0eSBvZiBTaGVsZiAyLgoKIyMjIyBDb25jbHVzaW9uOgoKU2hlbGYgMiBpcyB0aGUgbW9zdCBzdHJhdGVnaWMgc2hlbGYgZm9yIHRhcmdldGluZyBjaGlsZHJlbiBiZWNhdXNlIGl0IGlzIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXItc3VnYXIgY2VyZWFscyBhbmQgYXBwZWFycyB0byBtYXhpbWl6ZSBwcmVkaWN0ZWQgcGxhY2VtZW50IHByb2JhYmlsaXR5IGZvciBjaGlsZHJlbuKAmXMgcHJvZHVjdHMuCgojIyMgUXVlc3Rpb24gMyBUaGUgZmFpbHVyZSBvZiBhbiBPLXJpbmcgb24gdGhlIHNwYWNlIHNodXR0bGUgQ2hhbGxlbmdlcuKAmXMgYm9vc3RlciByb2NrZXRzIGxlZCB0byBpdHMgZGVzdHJ1Y3Rpb24gaW4gMTk4Ni4gVXNpbmcgZGF0YSBvbiBwcmV2aW91cyBzcGFjZSBzaHV0dGxlIGxhdW5jaGVzLCBEYWxhbCBldCBhbC4gKDE5ODkpIGV4YW1pbmUgdGhlIHByb2JhYmlsaXR5IG9mIGFuIE8tcmluZyBmYWlsdXJlIGFzIGEgZnVuY3Rpb24gb2YgdGVtcGVyYXR1cmUgYXQgbGF1bmNoIGFuZCBjb21idXN0aW9uIHByZXNzdXJlOyBpbiBjbGFzcywgd2UgbG9va2VkIGF0IG9ubHkgdGVtcGVyYXR1cmUuIERhdGEgZnJvbSB0aGVpciBwYXBlciBpcyBpbmNsdWRlZCBpbiB0aGUgY2hhbGxlbmdlci5jc3YgZmlsZS4gQmVsb3cgYXJlIHRoZSB2YXJpYWJsZXM6CgojIyMgRmxpZ2h0OiBGbGlnaHQgbnVtYmVyCiMjIyBUZW1wOiBUZW1wZXJhdHVyZSAoRikgYXQgbGF1bmNoCiMjIyBQcmVzc3VyZTogQ29tYnVzdGlvbiBwcmVzc3VyZSAocHNpKQojIyMgTy5yaW5nOiBOdW1iZXIgb2YgcHJpbWFyeSBmaWVsZCBPLXJpbmcgZmFpbHVyZXMKIyMjIE51bWJlcjogVG90YWwgbnVtYmVyIG9mIHByaW1hcnkgZmllbGQgTy1yaW5ncyAoc2l4IHRvdGFsLCB0aHJlZSBlYWNoIGZvciB0aGUgdHdvIGJvb3N0ZXIgcm9ja2V0cykKIyMjIFRoZSByZXNwb25zZSB2YXJpYWJsZSBpcyBPLnJpbmcsIGFuZCB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGFyZSBUZW1wIGFuZCBQcmVzc3VyZS4gQ29tcGxldGUgdGhlIGZvbGxvd2luZzoKCiMjIyAzYSBUaGUgYXV0aG9ycyB1c2UgbG9naXN0aWMgcmVncmVzc2lvbiB0byBlc3RpbWF0ZSB0aGUgcHJvYmFiaWxpdHkgYW4gTy1yaW5nIHdpbGwgZmFpbC4gSW4gb3JkZXIgdG8gdXNlIHRoaXMgbW9kZWwsIHRoZSBhdXRob3JzIG5lZWRlZCB0byBhc3N1bWUgdGhhdCBlYWNoIE8tcmluZyBpcyBpbmRlcGVuZGVudCBmb3IgZWFjaCBsYXVuY2guIERpc2N1c3Mgd2h5IHRoaXMgYXNzdW1wdGlvbiBpcyBuZWNlc3NhcnkgYW5kIHRoZSBwb3RlbnRpYWwgcHJvYmxlbXMgd2l0aCBpdC4gTm90ZSB0aGF0IGEgc3Vic2VxdWVudCBhbmFseXNpcyBoZWxwZWQgdG8gYWxsZXZpYXRlIHRoZSBhdXRob3Jz4oCZIGNvbmNlcm5zIGFib3V0IGluZGVwZW5kZW5jZS4KCmBgYHtyfQpjaGFsbGVuZ2VyIDwtIHJlYWQuY3N2KCJ+L0Rvd25sb2Fkcy9jaGFsbGVuZ2VyLmNzdiIpCgpjaGFsbGVuZ2VyJHBfaGF0IDwtIGNoYWxsZW5nZXIkTy5yaW5nIC8gY2hhbGxlbmdlciROdW1iZXIKCmNoYWxsZW5nZXJbLCBjKCJUZW1wIiwgIlByZXNzdXJlIiwgIk8ucmluZyIsICJOdW1iZXIiLCAicF9oYXQiKV0KYGBgCgpUaGUgZGF0YSBjbGVhcmx5IHNob3cgdGhhdCB0aGUgcHJvYmFiaWxpdHkgb2YgTy1yaW5nIGZhaWx1cmUgaW5jcmVhc2VzIHNoYXJwbHkgYXMgdGVtcGVyYXR1cmUgZGVjcmVhc2VzLiBUaGUgbG9naXN0aWMgbW9kZWwgcmVsaWVzIG9uIHRoZSBhc3N1bXB0aW9uIHRoYXQgTy1yaW5ncyB3aXRoaW4gYSBsYXVuY2ggYXJlIGluZGVwZW5kZW50IHNvIHRoYXQgZmFpbHVyZXMgZm9sbG93IGEgQmlub21pYWwgZGlzdHJpYnV0aW9uLiBIb3dldmVyLCBiZWNhdXNlIE8tcmluZ3Mgb24gdGhlIHNhbWUgbGF1bmNoIHNoYXJlIGlkZW50aWNhbCBlbnZpcm9ubWVudGFsIGNvbmRpdGlvbnMsIHRoZWlyIGZhaWx1cmVzIG1heSBiZSBjb3JyZWxhdGVkLiBJZiBzdWNoIGRlcGVuZGVuY2UgZXhpc3RzLCBpdCB3b3VsZCBpbmZsYXRlIHZhcmlhbmNlIGFuZCBwb3RlbnRpYWxseSBiaWFzIGluZmVyZW5jZS4gU3Vic2VxdWVudCBhbmFseXNlcyBmb3VuZCBsaXR0bGUgZXZpZGVuY2Ugb2Ygc3Ryb25nIG92ZXJkaXNwZXJzaW9uLCBzdWdnZXN0aW5nIHRoZSBpbmRlcGVuZGVuY2UgYXNzdW1wdGlvbiB3YXMgcmVhc29uYWJsZSBmb3IgdGhlc2UgZGF0YS4KCiMjIyAzYiBFc3RpbWF0ZSB0aGUgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCB1c2luZyB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGluIGEgbGluZWFyIGZvcm0gKGkuZS4sIE8ucmluZyB+IFRlbXAgKyBQcmVzc3VyZSkuCgpgYGB7cn0KZml0IDwtIGdsbShjYmluZChPLnJpbmcsIE51bWJlciAtIE8ucmluZykgfiBUZW1wICsgUHJlc3N1cmUsCiAgICAgICAgICAgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpLAogICAgICAgICAgIGRhdGEgPSBjaGFsbGVuZ2VyKQoKc3VtbWFyeShmaXQpCmBgYApgYGB7cn0KZXhwKGNvZWYoZml0KSkKYGBgCgpUZW1wZXJhdHVyZSBoYXMgYSBzaWduaWZpY2FudCBuZWdhdGl2ZSBlZmZlY3Qgb24gZmFpbHVyZSBwcm9iYWJpbGl0eS4gQ29sZGVyIGxhdW5jaGVzIHN1YnN0YW50aWFsbHkgaW5jcmVhc2UgcmlzayBhbmQgUHJlc3N1cmUgZG9lcyBub3QgYXBwZWFyIHRvIGJlIGFuIGltcG9ydGFudCBwcmVkaWN0b3Igb25jZSB0ZW1wZXJhdHVyZSBpcyBpbmNsdWRlZC4KCiMjIyMgQ29uY2x1c2lvbiAKClRoZSBmaXR0ZWQgbW9kZWwgc2hvd3MgdGhhdCB0ZW1wZXJhdHVyZSBpcyB0aGUgZG9taW5hbnQgcHJlZGljdG9yIG9mIE8tcmluZyBmYWlsdXJlIHByb2JhYmlsaXR5LiBMb3dlciB0ZW1wZXJhdHVyZXMgc2lnbmlmaWNhbnRseSBpbmNyZWFzZSB0aGUgb2RkcyBvZiBmYWlsdXJlLiBQcmVzc3VyZSBkb2VzIG5vdCBoYXZlIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBlZmZlY3Qgb25jZSB0ZW1wZXJhdHVyZSBpcyBhY2NvdW50ZWQgZm9yLiBUaGlzIHN1cHBvcnRzIHRoZSBoaXN0b3JpY2FsIGNvbmNsdXNpb24gdGhhdCBjb2xkIGxhdW5jaCBjb25kaXRpb25zIHdlcmUgdGhlIHByaW1hcnkgcmlzayBmYWN0b3IgaW4gdGhlIENoYWxsZW5nZXIgZGlzYXN0ZXIuCgojIyMgM2MgVGVzdCB3aGV0aGVyIG9yIG5vdCBQcmVzc3VyZSBjYW4gYmUgZHJvcHBlZCBmcm9tIHRoZSBtb2RlbC4gQmUgc3VyZSB0byBzcGVjaWZ5IHdoaWNoIG51bGwgYW5kIGFsdGVybmF0aXZlIGh5cG90aGVzZXMgYXJlIGltcGxpZWQgYnkgdGhpcyB0ZXN0LCBhbmQgZGVzY3JpYmUgd2hpY2ggdGVzdCB5b3UgdXNlZCAoZS5nLiwgbWFyZ2luYWwgdGVzdCBvciBsaWtlbGlob29kIHJhdGlvIHRlc3QgKExSVCkpIGFuZCB0aGUgY29uY2x1c2lvbiB5b3UgcmVhY2hlZCB1c2luZyBhbiAgbGV2ZWwgb2Ygc2lnbmlmaWNhbmNlLgoKV2Ugd2FudCB0byB0ZXN0IHdoZXRoZXIgUHJlc3N1cmUgY2FuIGJlIHJlbW92ZWQgZnJvbSB0aGUgbW9kZWwuCgpGdWxsIG1vZGVsOiBiZXRhXzAgKyBiZXRhXzEgdGVtcCArIGJldGFfMiBwcmVzc3VyZQpSZWR1Y2VkIG1vZGVsOiBsb2dpdChwKSA9IGJldGFfMCArIGJldGFfMSB0ZW1wCgpIeXBvdGhlc2lzOgpI4oKAOiDOsuKCgiA9IDAKUHJlc3N1cmUgaGFzIG5vIGVmZmVjdCBvbiBPLXJpbmcgZmFpbHVyZSBwcm9iYWJpbGl0eSAoZ2l2ZW4gVGVtcCkuCkjigoE6IM6y4oKCIOKJoCAwClByZXNzdXJlIGNvbnRyaWJ1dGVzIHRvIHByZWRpY3RpbmcgZmFpbHVyZS4KCmBgYHtyfQpmaXRfcmVkdWNlZCA8LSBnbG0oY2JpbmQoTy5yaW5nLCBOdW1iZXIgLSBPLnJpbmcpIH4gVGVtcCwKICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGJpbm9taWFsLAogICAgICAgICAgICAgICAgICAgZGF0YSA9IGNoYWxsZW5nZXIpCgphbm92YShmaXRfcmVkdWNlZCwgZml0LCB0ZXN0ID0gIkNoaXNxIikKYGBgCiMjIyMgQ29uY2x1c2lvbgoKQXQgdGhlIDEwJSBzaWduaWZpY2FuY2UgbGV2ZWwsIHRoZXJlIGlzIGluc3VmZmljaWVudCBldmlkZW5jZSB0aGF0IHByZXNzdXJlIGNvbnRyaWJ1dGVzIHRvIHByZWRpY3RpbmcgTy1yaW5nIGZhaWx1cmUgb25jZSBUZW1wZXJhdHVyZSBpcyBpbmNsdWRlZC4KVGhlcmVmb3JlLCBQcmVzc3VyZSBjYW4gYmUgZHJvcHBlZCBmcm9tIHRoZSBtb2RlbC4gVGVtcGVyYXR1cmUgYWxvbmUgYWRlcXVhdGVseSBleHBsYWlucyB0aGUgdmFyaWF0aW9uIGluIE8tcmluZyBmYWlsdXJlIHByb2JhYmlsaXR5LgoKIyMjIDNkIFRoZSBhdXRob3JzIGNob3NlIHRvIHJlbW92ZSBQcmVzc3VyZSBmcm9tIHRoZSBtb2RlbCBiYXNlZCBvbiB0aGUgTFJUcy4gQmFzZWQgb24geW91ciByZXN1bHRzLCBkaXNjdXNzIHdoeSB5b3UgdGhpbmsgdGhpcyB3YXMgZG9uZS4gQXJlIHRoZXJlIGFueSBwb3RlbnRpYWwgcHJvYmxlbXMgd2l0aCByZW1vdmluZyB0aGlzIHZhcmlhYmxlPwoKIyMjIyBXaHkgdGhlIGF1dGhvcnMgcmVtb3ZlZCBQcmVzc3VyZT8KCkxhY2sgb2Ygc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlOiBUaGUgTFJUIHNob3dzIG5vIGV2aWRlbmNlIHRoYXQgUHJlc3N1cmUgaW1wcm92ZXMgbW9kZWwgZml0IGJleW9uZCBUZW1wZXJhdHVyZS5JZiBhIHZhcmlhYmxlIGRvZXMgbm90IGltcHJvdmUgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZSwgcmVtb3ZpbmcgaXQgc2ltcGxpZmllcyB0aGUgbW9kZWwgd2l0aG91dCBzYWNyaWZpY2luZyBleHBsYW5hdG9yeSBwb3dlci4KClRlbXBlcmF0dXJlIGhhcyBhIHN0cm9uZywgc2lnbmlmaWNhbnQgbmVnYXRpdmUgZWZmZWN0LiBQcmVzc3VyZeKAmXMgZXN0aW1hdGVkIGVmZmVjdCBpcyBzbWFsbCBhbmQgaW1wcmVjaXNlLiBUaGVyZSBhcmUgb25seSAyMyBsYXVuY2hlcy4gV2l0aCBsaW1pdGVkIGRhdGEsIGFkZGluZyB1bm5lY2Vzc2FyeSBwcmVkaWN0b3JzIGluY3JlYXNlcyB2YXJpYW5jZSBhbmQgcmVkdWNlcyBzdGFiaWxpdHkuCgpUaGVyZWZvcmUsIGRyb3BwaW5nIHByZXNzdXJlIHdhcyByZWFzb25hYmxlLgoKIyMjIyBPdmVyYWxsIENvbmNsdXNpb24KClByZXNzdXJlIHdhcyByZW1vdmVkIGJlY2F1c2UgaXQgZG9lcyBub3Qgc2lnbmlmaWNhbnRseSBpbXByb3ZlIG1vZGVsIGZpdCBhY2NvcmRpbmcgdG8gdGhlIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCwgYW5kIHJldGFpbmluZyBpdCB3b3VsZCBhZGQgY29tcGxleGl0eSB3aXRob3V0IGNsZWFyIGJlbmVmaXQuIEdpdmVuIHRoZSBzbWFsbCBzYW1wbGUgc2l6ZSBhbmQgc3Ryb25nIGRvbWluYW5jZSBvZiBUZW1wZXJhdHVyZSwgdGhpcyBkZWNpc2lvbiBpcyBzdGF0aXN0aWNhbGx5IGp1c3RpZmllZC4gSG93ZXZlciwgdGhlIHNtYWxsIGRhdGFzZXQgbGltaXRzIHBvd2VyLCBhbmQgaXQgcmVtYWlucyBwb3NzaWJsZSB0aGF0IFByZXNzdXJlIGhhcyBhIG1vZGVzdCBlZmZlY3QgdGhhdCB0aGUgZGF0YSBjYW5ub3QgcmVsaWFibHkgZGV0ZWN0LgoKIyMjIDNlIFJlZml0IHRoZSBtb2RlbCB1c2luZyBvbmx5IFRlbXAgYXMgYSBwcmVkaWN0b3IuIFdoYXQgaXMgdGhlIGVzdGltYXRlZCBwcm9iYWJpbGl0eSBvZiBhbiBPLXJpbmcgZmFpbHVyZSBhdCAzMSDCsEY/CgpgYGB7cn0KZml0X3RlbXAgPC0gZ2xtKGNiaW5kKE8ucmluZywgTnVtYmVyIC0gTy5yaW5nKSB+IFRlbXAsCiAgICAgICAgICAgICAgICBmYW1pbHkgPSBiaW5vbWlhbChsaW5rID0gImxvZ2l0IiksCiAgICAgICAgICAgICAgICBkYXRhID0gY2hhbGxlbmdlcikKCnN1bW1hcnkoZml0X3RlbXApCmBgYAoKYGBge3J9CnByZWRpY3QoZml0X3RlbXAsCiAgICAgICAgbmV3ZGF0YSA9IGRhdGEuZnJhbWUoVGVtcCA9IDMxKSwKICAgICAgICB0eXBlID0gInJlc3BvbnNlIikKYGBgCgpBdCAzMcKwRiwgdGhlIG1vZGVsIHByZWRpY3RzIHJvdWdobHkgYW4gODIlIGNoYW5jZSB0aGF0IGEgZ2l2ZW4gTy1yaW5nIGZhaWxzLiBUaGF0IGlzIGV4dHJlbWVseSBoaWdoIGNvbXBhcmVkIHRvIHR5cGljYWwgbGF1bmNoIHRlbXBlcmF0dXJlcyB3aGVyZSBwcmVkaWN0ZWQgcHJvYmFiaWxpdGllcyBhcmUgbmVhciB6ZXJvLiBUaGlzIHJlc3VsdCBjbGVhcmx5IGluZGljYXRlcyB0aGF0IHRoZSBDaGFsbGVuZ2VyIGxhdW5jaCB0ZW1wZXJhdHVyZSBjb3JyZXNwb25kZWQgdG8gYSB2ZXJ5IGhpZ2ggcHJlZGljdGVkIGZhaWx1cmUgcmlzayB1bmRlciB0aGUgZml0dGVkIGxvZ2lzdGljIG1vZGVsLgoKIyMjIDNmIEhvdyBkb2VzIHRoZSBwcm9iYWJpbGl0eSBjaGFuZ2Ugd2hlbiB5b3Ugc3dpdGNoIHRvIHVzaW5nIGEgcHJvYml0IGxpbmsgZnVuY3Rpb24/CgpgYGB7cn0KZml0X3Byb2JpdCA8LSBnbG0oY2JpbmQoTy5yaW5nLCBOdW1iZXIgLSBPLnJpbmcpIH4gVGVtcCwKICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJwcm9iaXQiKSwKICAgICAgICAgICAgICAgICAgZGF0YSA9IGNoYWxsZW5nZXIpCgpzdW1tYXJ5KGZpdF9wcm9iaXQpCmBgYApgYGB7cn0KcHJlZGljdChmaXRfcHJvYml0LAogICAgICAgIG5ld2RhdGEgPSBkYXRhLmZyYW1lKFRlbXAgPSAzMSksCiAgICAgICAgdHlwZSA9ICJyZXNwb25zZSIpCmBgYAoKUmVmaXR0aW5nIHRoZSBtb2RlbCB1c2luZyBhIHByb2JpdCBsaW5rIGFuZCBwcmVkaWN0aW5nIGF0IDMxwrBGIGdpdmVzIGFuIGVzdGltYXRlZCBwcm9iYWJpbGl0eSBvZiAwLjY5LiBSZWZpdHRpbmcgdGhlIG1vZGVsIHVzaW5nIGEgcHJvYml0IGxpbmsgYW5kIHByZWRpY3RpbmcgYXQgMzHCsEYgZ2l2ZXMgYW4gZXN0aW1hdGVkIHByb2JhYmlsaXR5IG9mIDAuODE4CgpUaHVzLCBzd2l0Y2hpbmcgZnJvbSBhIGxvZ2l0IHRvIGEgcHJvYml0IGxpbmsgZGVjcmVhc2VzIHRoZSBlc3RpbWF0ZWQgcHJvYmFiaWxpdHkgb2YgTy1yaW5nIGZhaWx1cmUgYXQgMzHCsEYgZnJvbSBhYm91dCA4MiUgdG8gYWJvdXQgNzAlLgpBbHRob3VnaCB0aGUgbnVtZXJpY2FsIHZhbHVlIGNoYW5nZXMsIHRoZSBzdWJzdGFudGl2ZSBjb25jbHVzaW9uIGRvZXMgbm90OiBib3RoIGxpbmsgZnVuY3Rpb25zIHByZWRpY3QgYSB2ZXJ5IGhpZ2ggcHJvYmFiaWxpdHkgb2YgTy1yaW5nIGZhaWx1cmUgYXQgMzHCsEYsIGluZGljYXRpbmcgc3Vic3RhbnRpYWwgcmlzayB1bmRlciBzdWNoIGNvbGQgbGF1bmNoIGNvbmRpdGlvbnMuCgojIyMgUXVlc3Rpb24gNCAKCiMjIyBCaWtlIFJlbnRhbCBEZW1hbmQgQW5hbHlzaXMKCkRhdGEgU291cmNlOiBCaWtlc2hhcmUgZGF0YSBzZXQgZnJvbSB0aGUgSVNMUjIgcGFja2FnZQpSZXNwb25zZSBWYXJpYWJsZTogYmlrZXJzIChob3VybHkgYmlrZSByZW50YWxzKQpQcmVkaWN0b3JzOiB3b3JraW5nZGF5LCB0ZW1wLCB3ZWF0aGVyc2l0LCBtbnRoLCBocgoKIyMjIyAxLiBPYmplY3RpdmUKVGhlIGdvYWwgb2YgdGhpcyBhbmFseXNpcyBpcyB0byBtb2RlbCBob3VybHkgYmlrZSByZW50YWwgZGVtYW5kIGFuZCBkZXRlcm1pbmUgd2hpY2ggZmFjdG9ycyBtb3N0IHN0cm9uZ2x5IGluZmx1ZW5jZSB1c2FnZS4gVGhlIHByaW1hcnkgb2JqZWN0aXZlIGlzIHRvIGlkZW50aWZ5IGNvbmRpdGlvbnMgdW5kZXIgd2hpY2ggcmVudGFscyBhcmUgaGlnaGVzdCBhbmQgcHJvdmlkZSBhY3Rpb25hYmxlIHJlY29tbWVuZGF0aW9ucyB0byBpbmNyZWFzZSByZXZlbnVlLgpTaW5jZSB0aGUgcmVzcG9uc2UgdmFyaWFibGUgKGJpa2VycykgaXMgYSBjb3VudCwgYSBjb3VudCByZWdyZXNzaW9uIG1vZGVsIHdhcyB1c2VkLgoKIyMjIyAyLiBNb2RlbCBDaG9pY2UKU2luY2UgdGhlIHJlc3BvbnNlIGlzIGEgbm9uLW5lZ2F0aXZlIGNvdW50IHZhcmlhYmxlIGFuZCBleGhpYml0cyB2YXJpYW5jZSBsYXJnZXIgdGhhbiB0aGUgbWVhbiwgYSBOZWdhdGl2ZSBCaW5vbWlhbCByZWdyZXNzaW9uIG1vZGVsIHdhcyBzZWxlY3RlZC4KCldoeSBub3Qgb3JkaW5hcnkgbGluZWFyIHJlZ3Jlc3Npb24/CkNvdW50cyBhcmUgbm9uLW5lZ2F0aXZlIGFuZCByaWdodC1za2V3ZWQuIExpbmVhciByZWdyZXNzaW9uIGNhbiBwcmVkaWN0IG5lZ2F0aXZlIHZhbHVlcyBhbmQgYXNzdW1lcyBjb25zdGFudCB2YXJpYW5jZS4KCldoeSBub3QgUG9pc3Nvbj8KVGhlIGRhdGEgc2hvdyBldmlkZW5jZSBvZiBvdmVyZGlzcGVyc2lvbiAodmFyaWFuY2UgZXhjZWVkcyBtZWFuKS4KTmVnYXRpdmUgQmlub21pYWwgcmVncmVzc2lvbiBhY2NvdW50cyBmb3Igb3ZlcmRpc3BlcnNpb24gd2l0aCBhbiBhZGRpdGlvbmFsIGRpc3BlcnNpb24gcGFyYW1ldGVyLgpUaGVyZSB3YXMgbm8gc3Ryb25nIGV2aWRlbmNlIG9mIHplcm8taW5mbGF0aW9uIGJleW9uZCB3aGF0IGlzIHR5cGljYWwgZm9yIGhvdXJseSBkZW1hbmQsIHNvIGEgemVyby1pbmZsYXRlZCBtb2RlbCB3YXMgbm90IHJlcXVpcmVkLgoKfCBQcmVkaWN0b3IgICAgICAgICAgICAgICAgICAgICAgICAgfCBFc3RpbWF0ZSAgICAgICB8IFN0ZC4gRXJyb3IgfCBEaXJlY3Rpb24gfCBJbnRlcnByZXRhdGlvbiAgICAgICAgICAgICAgICAgICAgICAgfAp8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLSB8IC0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8CnwgSW50ZXJjZXB0ICAgICAgICAgICAgICAgICAgICAgICAgIHwg4oCUICAgICAgICAgICAgICB8IOKAlCAgICAgICAgICB8IOKAlCAgICAgICAgIHwgQmFzZWxpbmUgcmVudGFsIGxldmVsICAgICAgICAgICAgICAgIHwKfCBUZW1wICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBQb3NpdGl2ZSAgICAgICB8IFNtYWxsICAgICAgfCDihpEgICAgICAgICB8IFdhcm1lciB0ZW1wZXJhdHVyZXMgaW5jcmVhc2UgcmVudGFscyB8CnwgV29ya2luZ2RheSAgICAgICAgICAgICAgICAgICAgICAgIHwgUG9zaXRpdmUgICAgICAgfCBTbWFsbCAgICAgIHwg4oaRICAgICAgICAgfCBNb3JlIHJlbnRhbHMgb24gd29ya2luZyBkYXlzICAgICAgICAgfAp8IFdlYXRoZXJzaXQgKEJhZCB3ZWF0aGVyIHZzIGNsZWFyKSB8IE5lZ2F0aXZlICAgICAgIHwgTW9kZXJhdGUgICB8IOKGkyAgICAgICAgIHwgUG9vciB3ZWF0aGVyIHJlZHVjZXMgcmVudGFscyAgICAgICAgIHwKfCBNb250aCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBWYXJpZXMgICAgICAgICB8IOKAlCAgICAgICAgICB8IFNlYXNvbmFsICB8IFN1bW1lciBtb250aHMgaW5jcmVhc2UgcmVudGFscyAgICAgICB8CnwgSG91ciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgU3Ryb25nIHBhdHRlcm4gfCDigJQgICAgICAgICAgfCBOb25saW5lYXIgfCBDb21tdXRlIGhvdXJzIGhhdmUgaGlnaGVzdCByZW50YWxzICAgfAoKCiMjIyMgMy4gSW50ZXJwcmV0YXRpb24gb2YgS2V5IFZhcmlhYmxlcwoKVGVtcGVyYXR1cmUgKFRlbXApOiBUZW1wZXJhdHVyZSBpcyBvbmUgb2YgdGhlIHN0cm9uZ2VzdCBwcmVkaWN0b3JzLkFzIHRlbXBlcmF0dXJlIGluY3JlYXNlcywgdGhlIGV4cGVjdGVkIG51bWJlciBvZiBiaWtlIHJlbnRhbHMgaW5jcmVhc2VzLlRoZSByZWxhdGlvbnNoaXAgaXMgYXBwcm94aW1hdGVseSBtb25vdG9uaWMgd2l0aGluIHRoZSBvYnNlcnZlZCByYW5nZS4KV2FybWVyIHdlYXRoZXIgZW5jb3VyYWdlcyBjeWNsaW5nIGFjdGl2aXR5LgoKSG91ciBvZiBEYXkgKGhyKTogVGhpcyBpcyB0aGUgc2luZ2xlIG1vc3QgaW1wb3J0YW50IHByZWRpY3Rvci4KCkNsZWFyIHBlYWtzIGF0Ogo44oCTOSBBTSAobW9ybmluZyBjb21tdXRlKQo14oCTNiBQTSAoZXZlbmluZyBjb21tdXRlKQoKTG93ZXN0IHJlbnRhbHMgZHVyaW5nIG92ZXJuaWdodCBob3Vycy5UaGlzIHBhdHRlcm4gc3VnZ2VzdHMgc3Ryb25nIGNvbW11dGVyIGRlbWFuZC4KCldlYXRoZXIgU2l0dWF0aW9uICh3ZWF0aGVyc2l0KQpDb21wYXJlZCB0byBjbGVhciBjb25kaXRpb25zOiBMaWdodCBwcmVjaXBpdGF0aW9uIHJlZHVjZXMgcmVudGFscy4gU2V2ZXJlIHdlYXRoZXIgcmVkdWNlcyByZW50YWxzIHN1YnN0YW50aWFsbHkuIFdlYXRoZXIgaGFzIGEgbWVhbmluZ2Z1bCBuZWdhdGl2ZSBlZmZlY3QuCgpXb3JraW5nIERheQpSZW50YWwgbGV2ZWxzIGFyZSBoaWdoZXIgb24gd29ya2luZyBkYXlzIGNvbXBhcmVkIHRvIG5vbi13b3JraW5nIGRheXMsIGxhcmdlbHkgZHVlIHRvIGNvbW11dGVyIHRyYWZmaWMuCgpNb250aCAoU2Vhc29uYWxpdHkpClJlbnRhbHMgYXJlIGhpZ2hlc3QgZHVyaW5nIGxhdGUgc3ByaW5nIGFuZCBzdW1tZXIuV2ludGVyIG1vbnRocyBzaG93IHN1YnN0YW50aWFsbHkgbG93ZXIgZGVtYW5kLgoKIyMjIyA1LiBNb3N0IEltcG9ydGFudCBQcmVkaWN0b3JzCkJhc2VkIG9uIGVmZmVjdCBzaXplIGFuZCBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2U6CiAgLUhvdXIgb2YgRGF5CiAgLVRlbXBlcmF0dXJlClRoZXNlIHdlcmUgc2VsZWN0ZWQgYmVjYXVzZSB0aGV5IGhhdmUgdGhlIGxhcmdlc3QgbWFnbml0dWRlIGVmZmVjdHMuIFRoZXkgcHJvZHVjZSB0aGUgZ3JlYXRlc3QgdmFyaWF0aW9uIGluIHByZWRpY3RlZCByZW50YWwgY291bnRzLlRoZWlyIGVmZmVjdCBwbG90cyBzaG93IGNsZWFyIGFuZCBpbnRlcnByZXRhYmxlIHRyZW5kcy4KCiMjIyMgNi4gRWZmZWN0IFBsb3QgU3VtbWFyaWVzCkVmZmVjdCBvZiBIb3VyCiAgUHJlZGljdGVkIHJlbnRhbHMgcmlzZSBzaGFycGx5IGR1cmluZyBjb21tdXRlIGhvdXJzIChtb3JuaW5nIGFuZCBsYXRlIGFmdGVybm9vbikgYW5kIGRyb3AgZHVyaW5nIGxhdGUgbmlnaHQuClRyZW5kOiBTdHJvbmcgYmltb2RhbCBwYXR0ZXJuLgoKRWZmZWN0IG9mIFRlbXBlcmF0dXJlClByZWRpY3RlZCByZW50YWxzIGluY3JlYXNlIHN0ZWFkaWx5IHdpdGggdGVtcGVyYXR1cmUgdXAgdG8gY29tZm9ydGFibGUgbGV2ZWxzLgpUcmVuZDogUG9zaXRpdmUgYW5kIGFwcHJveGltYXRlbHkgbGluZWFyIHdpdGhpbiBvYnNlcnZlZCByYW5nZS4KCiMjIyMgNy4gV2hlbiBBcmUgUmVudGFscyBIaWdoZXN0PwpCaWtlIHJlbnRhbHMgYXJlIGhpZ2hlc3QgdW5kZXIgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgogIFdhcm0gdGVtcGVyYXR1cmVzCiAgQ2xlYXIgd2VhdGhlcgogIFdvcmtpbmcgZGF5cwogIExhdGUgc3ByaW5nIG9yIHN1bW1lciBtb250aHMKICBNb3JuaW5nIGFuZCBldmVuaW5nIGNvbW11dGUgaG91cnMKVGhpcyBwYXR0ZXJuIHN0cm9uZ2x5IHJlZmxlY3RzIGNvbW11dGVyIGRyaXZlbiBkZW1hbmQuCgojIyMjIDguIERvIFRoZXNlIFJlc3VsdHMgTWFrZSBTZW5zZT8KWWVzLiBDb21tdXRlcnMgdXNlIGJpa2VzIGR1cmluZyBydXNoIGhvdXIuIFdhcm0gd2VhdGhlciBpbmNyZWFzZXMgb3V0ZG9vciBhY3Rpdml0eS4gUG9vciB3ZWF0aGVyIGRpc2NvdXJhZ2VzIGN5Y2xpbmcuIFN1bW1lciBtb250aHMgbmF0dXJhbGx5IGluY3JlYXNlIGRlbWFuZC4gVGhlIGZpbmRpbmdzIGFyZSBjb25zaXN0ZW50IHdpdGggYmVoYXZpb3JhbCBleHBlY3RhdGlvbnMuCgojIyMjIDkuIFJlY29tbWVuZGF0aW9ucyBmb3IgdGhlIEJpa2UgUmVudGFsIEFnZW5jeQogIGEuIEZvY3VzIG9uIENvbW11dGUgT3B0aW1pemF0aW9uOkVuc3VyZSBiaWtlIGF2YWlsYWJpbGl0eSBuZWFyIHRyYW5zaXQgaHVicyBkdXJpbmcgcGVhayBob3Vycy5JbmNyZWFzZSByZWJhbGFuY2luZyBiZWZvcmUgbW9ybmluZyBhbmQgZXZlbmluZyBydXNoLgogIGIuIER5bmFtaWMgU3RhZmZpbmc6IFNjaGVkdWxlIG1haW50ZW5hbmNlIGFuZCBzdGFmZmluZyBhcm91bmQgaGlnaCBkZW1hbmQgaG91cnMuIFJlZHVjZSBvdmVybmlnaHQgb3BlcmF0aW9uYWwgaW50ZW5zaXR5LgogIGMuIFdlYXRoZXItQmFzZWQgUHJvbW90aW9uczogIE9mZmVyIGRpc2NvdW50cyBkdXJpbmcgbWlsZCByYWluIHRvIG9mZnNldCBkZW1hbmQgZHJvcC4gSW5jcmVhc2UgYWR2ZXJ0aXNpbmcgZHVyaW5nIGZvcmVjYXN0ZWQgd2FybSBkYXlzLgogIGQuIFNlYXNvbmFsIFBsYW5uaW5nOiAgRXhwYW5kIGludmVudG9yeSBvciBkb2NrIGNhcGFjaXR5IGR1cmluZyBwZWFrIG1vbnRocy4gUmVkdWNlIGNvc3RzIGluIHdpbnRlciB3aGVuIGRlbWFuZCBpcyBwcmVkaWN0YWJseSBsb3cuCiAgZS4gVGVtcGVyYXR1cmUtQmFzZWQgRm9yZWNhc3Rpbmc6IEluY29ycG9yYXRlIHRlbXBlcmF0dXJlIGZvcmVjYXN0cyBpbnRvIGRhaWx5IG9wZXJhdGlvbmFsIHBsYW5uaW5nIHRvIGFudGljaXBhdGUgZGVtYW5kIHNwaWtlcy4KCiMjIyMgMTAuIEZpbmFsIENvbmNsdXNpb24KSG91cmx5IGJpa2UgcmVudGFsIGRlbWFuZCBpcyBwcmltYXJpbHkgZHJpdmVuIGJ5IHRpbWUgb2YgZGF5IGFuZCB0ZW1wZXJhdHVyZSwgd2l0aCBhZGRpdGlvbmFsIGluZmx1ZW5jZSBmcm9tIHdlYXRoZXIgYW5kIHNlYXNvbmFsaXR5LiBEZW1hbmQgaXMgaGlnaGVzdCBkdXJpbmcgd2FybS13ZWF0aGVyIGNvbW11dGUgaG91cnMuIFRoZXNlIGZpbmRpbmdzIGFyZSBpbnR1aXRpdmUgYW5kIG9wZXJhdGlvbmFsbHkgYWN0aW9uYWJsZS4gVGhlIGFnZW5jeSBjYW4gaW1wcm92ZSByZW50YWwgc2FsZXMgYnkgb3B0aW1pemluZyBzdXBwbHkgYXJvdW5kIGNvbW11dGUgdGltZXMsIGxldmVyYWdpbmcgd2VhdGhlciBmb3JlY2FzdHMsIGFuZCBhbGlnbmluZyBzZWFzb25hbCBjYXBhY2l0eSB3aXRoIGRlbWFuZCBwYXR0ZXJucy4K