To create a quality of contact metric, I’m first creating a multi-class classification model that aims to predict the outcome of each batted ball using a XGBoost model. XGBoost is a decision tree based ensemble supervised machine learning algorithm that uses a gradient boosting framework. Gradient boosting is a case of boosting where errors are minimized by gradient descent and applies the principle of boosting weak learners. The rationale for using XGBoost lies in its easy to understand nature and the structure and size of the data. Decision trees for classifications are easy to interpret on a fundamental level. A basic decision tree, for example just a tree stump, visualized it is easy to see the rationale for the classification. Since this dataset is relatively large (over 100,000 observations per season) and is tabular data, gradient boosting machines (GBMs), specifically XGBoost seems like a fine choice for this problem. Also, GBMs are non-parametric models that are suitable for this non-linear data.

For my modeling, I’m going to use play outcome as the response variable. The play outcome (out, single, double, triple, homerun) is a good starting place for measuring quality of contact. If we are just looking at grading quality of contact based on the result of the batted ball then we know that a homerun is better than a triple which is better than a double and so on. This metric provides a broadly accepted way to rank the quality of a batted ball. Generally speaking, hitting a ball harder (more exit speed) is better than hitting a ball softer. However, it’s important to include the launch angle when using exit speed. A batter would much rather hit a ball 105 mph at 25 degrees than a ball 125 mph at -10 degrees. There are exceptions, but in the aggregate we know that homeruns have the best combination of exit speed and launch angle. There is more to assessing quality of contact than just exit speed and launch angle, such as spray angle, but it’s also incredibly important to account for other contextual variables.

I start the modeling by doing a simple 10-fold cross-validation to determine the appropriate number of iterations to use in a baseline XGBoost model. There are two main choices I made before starting the XGBoost modeling. The first is that I’m going to use multi:softprob as the objective of the model with mlogloss evaluation metric. multi:softprob returns the probability of each observation being a member of each class. There are five classes of the response variable (out, single, double, triple, and homerun). I made this choice because you can gain more information about each batted ball knowing the probability of it belonging to each class rather than the model returning which class has the maximum probability. Second, I used mlogloss as the evaluation metric in the XGBoost modeling. The evaluation metric is used for validation data in both the cross-validation and XGBoost modeling, in addition to being used for early stopping and model evaluation. mlogloss is the loss function used in multinomial logistic regression and is defined as the negative log-likelihood of a logistic model that returns probabilities for its training data. The models also have no hyperparameters specified, meaning that all of those parameters are their default values. Normally, I’d hyperparameter tune an XGBoost model using a latin hypercube, however I don’t want to subject my laptop to running 150 different models, and in my experience tuning seems to increase accuracy by at most 1%.

Even though I’m going to run a model for each season on the entire season’s worth of data, I’m still going to do a typical 70/30 train/test split first to ensure the model is not over- or under-fitting.

In addition, to the XGBoost model, I’m going use the class probabilties (probability of out, single, double, triple, and homerun) as inputs to a generalized linear mixed-effects model (GLMM). The multinomial modeling workflow comes from Baseball Prospectus and their creation of DRC+ (https://www.baseballprospectus.com/news/article/48293/entirely-beyond-wowy-a-breakdown-of-drc/#fnref4). Below I’m going to create four binomial subsets, therefore turning this multinomial problem into multiple binomial models. The four susbets are: out + single, out + double, out + triple, and out + homerun. Each subset has outs because that is our “pivot,” the common category every other event will be regressed against. Outs were selected because, as Judge says, this methodology works best when the pivot is also the largest category. The most common outcome for a batted ball is an out (remember the typical league average batting average of balls in play (BABIP) is ~.300). Then each binomial subset is fit on a GLMM. My singular motivation of using this modeling (besides saying I’m using a GLMM) is to include batter and pitcher identity. It’s clear that batter and pitchers have some effect on the outcome of a batted ball. For example, even without explicitly including sprint speed, in my experience this type of model is able to pick up on what batters are able to turn singles into double or doubles into triples. It’s theoretically possible to include batter and pitchers in my XGBoost modeling as dummy variables, but I don’t think my poor laptop would’ve been able to handle a 105,000 by 3,200 dataset five times for gradient boosting.

I will be using the logit of each class probability and the batter and pitcher as features in the GLMM model. Logit, also known as the log-odds, is the logarithm of the odds \(\frac{p}{1 - p}\), where p is the probability (in our case, the probability of an out, single, double, triple, or homerun). For example, take the out probability, before being used in the model, it would now look like this: \(\log\left(\frac{out.probability}{1 - (out.probability)}\right)\).

The final equation for the each GLMM model is: outcome ~ (1|pitcher) + (1|batter) + logit(out probability) + logit(single probability) + logit(double probability) + logit(triple probability) + logit(homerun probability). In addition to including batter and pitcher identity, which I believe will make the model a lot more robust, this model also acts as a sort of stacking algorithm.

Stacking is a popular ensemble method in machine learning. Generally, stacking involves training several models with different algorithms that are relatively simple (base-learners). Then the predictions from each model are fed into one final model (meta-learner) to make the final prediction. So the inputs for the meta-learner are the prediction outputs of the base-learners. The benefit of stacking is that can combine the capabilities of a multitude of good models that end up making a stronger model than any of the base-learners. I wouldn’t consider my methodology as exactly stacking because I’m not combining models, rather using the outputs from one model, in addition to other features, as the input to a final model. However, I do think that I will still enjoy some of the benefits of stacking. It’s important to note, as it was pointed out to me, that sometimes XGBoost can smooth over the linear model signal for the random effects (pitcher and batter identity). Therefore, it’s a possibility that the mixed-effects model doesn’t entirely capture the random effect of each batter and pitcher accurrately.

Lastly, to create the QC+ metric I will take the new class probabilities from the GLMM model and multiply each probabiity with its associated linear weight. For example, say a batted ball has a probability of being an out of .45, a single .25, a double .15, a triple .10, and a homerun .05. Say this ball was from the 2015 season, on FanGraphs we can see that the linear weight of a single was 0.881, double 1.256, triple 1.594, and homerun 2.065. Then the expected weight for this batted ball would be: \(.45 * 0 + .25 * .881 + .15 * 1.256 + .10 * 1.594 + .05 * 2.065 = 0.6713\). I’m going to do that for every batted ball in the season and then standardize them so that the average QC+ is 100, with a standard deviation of 30. The average of 100 puts QC+ on a similar scale as wRC+, DRC+, and other metrics. I picked a standard deviation of 30, because the standard deviation of wRC+ over the last couple of years was very close to 30.

Below I’m just going to show the process of the 2015 season model, but the 2016-2019 models are the exact same.

# setting seed for reproducibility
set.seed(123) 

Creating a dataset for each season.

batted_ball_model_2015 <- batted_ball_model %>% filter(game_year == 2015)
batted_ball_model_2016 <- batted_ball_model %>% filter(game_year == 2016)
batted_ball_model_2017 <- batted_ball_model %>% filter(game_year == 2017)
batted_ball_model_2018 <- batted_ball_model %>% filter(game_year == 2018)
batted_ball_model_2019 <- batted_ball_model %>% filter(game_year == 2019)

Here is the XGBoost modeling for each season, split into train/test sets to determine overall generalization ability. For the sake of being (somewhat) breif, I’m only going to show the 2015 model throughout the entire notebook, as the 2016-2019 models are the same.

####### 2015
# create indecies for splitting (need to use a specific column from df for it to run)
train_index_2015 <- createDataPartition(y = batted_ball_model_2015$outcome_ec, p = .70, list = FALSE) %>% as.vector()

# split into train and test
train_2015 <- batted_ball_model_2015[train_index_2015,]
test_2015 <- batted_ball_model_2015[-train_index_2015,]

# need a vector of response variable (outcome)
vec_label_train_2015 <- train_2015$outcome_ec

train_data_2015 <- as.matrix(train_2015 %>% dplyr::select(c("launch_angle", "launch_speed", "spray_angle", "stand_r", "p_throws_r", "temperature", "is_dome",
                                                            pitch_type_CH:venue_batter.stand_YankeeStadium_r)))

vec_label_test_2015 <- test_2015$outcome_ec
test_data_2015 <- as.matrix(test_2015 %>% dplyr::select(c("launch_angle", "launch_speed", "spray_angle", "stand_r", "p_throws_r", "temperature", "is_dome",
                                                            pitch_type_CH:venue_batter.stand_YankeeStadium_r)))

# convert the train and test into xgb.DMatrix
x_train_2015 = xgboost::xgb.DMatrix(data = train_data_2015, label = vec_label_train_2015)
x_test_2015 = xgboost::xgb.DMatrix(data = test_data_2015, label = vec_label_test_2015)

baseline_cv_2015 <- xgboost::xgb.cv(params = list(objective = "multi:softprob", eval_metric = c("mlogloss"), num_class = 5), data = x_train_2015, nrounds = 2500, early_stopping_rounds = 10, nfold=10, stratified = T)

base_mod_2015 <- xgboost::xgboost(params = list(objective = "multi:softprob", eval_metric = c("mlogloss"), num_class = 5), data = x_train_2015, nrounds = baseline_cv_2015$best_ntreelimit)

Here I’m computing the test set accuracy for each season’s model. The accuracies range from 80.8% to 81.6%, which is very good. Keep in mind that a naive classifier would have an accuracy around 20% (randomly guessing the class for each observation).

xgb.pred_2015 = predict(base_mod_2015, x_test_2015, reshape=T)
xgb.pred_2015 = as.data.frame(xgb.pred_2015)
colnames(xgb.pred_2015) = c("Out", "Single", "Double", "Triple", "Home_Run")

preds_base_2015 <- test_2015
preds_base_2015$out.prob <- xgb.pred_2015[,1]
preds_base_2015$single.prob <- xgb.pred_2015[,2]
preds_base_2015$double.prob <- xgb.pred_2015[,3]
preds_base_2015$triple.prob <- xgb.pred_2015[,4]
preds_base_2015$hr.prob <- xgb.pred_2015[,5]

max_prob_2015 <- colnames(xgb.pred_2015)[apply(xgb.pred_2015,1,which.max)]

preds_base_2015$max.prob <- max_prob_2015

preds_base_2015$pred.right <- ifelse(preds_base_2015$max.prob == "Out" & preds_base_2015$outcome_ec == 0, "yes", 
                                ifelse(preds_base_2015$max.prob == "Single" & preds_base_2015$outcome_ec == 1, "yes",
                                       ifelse(preds_base_2015$max.prob == "Double" & preds_base_2015$outcome_ec == 2, "yes",
                                              ifelse(preds_base_2015$max.prob == "Triple" & preds_base_2015$outcome_ec == 3, "yes",
                                                     ifelse(preds_base_2015$max.prob == "Home_Run" & preds_base_2015$outcome_ec == 4, "yes", "no")))))
preds_base_2015$pred.right <- as.factor(preds_base_2015$pred.right)

sum(preds_base_2015$pred.right == "yes") / nrow(preds_base_2015) #0.8083159

Now, I’m going to train each model on the entire season’s data.

### 2015
vec_label_2015 <- batted_ball_model_2015$outcome_ec
all_dataset_2015 <- as.matrix(batted_ball_model_2015 %>% dplyr::select(c("launch_angle", "launch_speed", "spray_angle", "stand_r", "p_throws_r", "temperature", "is_dome",
                                                            pitch_type_CH:venue_batter.stand_YankeeStadium_r)))
full_dataset_x_2015 = xgb.DMatrix(data = all_dataset_2015, label = vec_label_2015)

full_cv_2015 <- xgboost::xgb.cv(params = list(objective = "multi:softprob", eval_metric = c("mlogloss"), num_class = 5), data = full_dataset_x_2015, nrounds = 2500, early_stopping_rounds = 10, nfold=10, stratified = T)
full_mod_2015 <- xgboost::xgboost(params = list(objective = "multi:softprob", eval_metric = c("mlogloss"), num_class = 5), data = full_dataset_x_2015, nrounds = full_cv_2015$best_ntreelimit)

Here are the feature importance plots for each model. The results are what to be expected: launch anle, exit speed, and spray angle are the three most important variables that go into classifying the outcome of a batted ball. What surprised me was how influential the infield shift feature was. Feature engineering is incredibly benefical to modeling.

final_2015 
final_2016

final_2017

final_2018

final_2019

Now, I’m going to compute the accuracy of the models that were trained on the entire dataset. They turned out great; ranging from 85.25% to 86.25%.

###### 2015
xgb.full_pred_2015 = predict(full_mod_2015, full_dataset_x_2015, reshape=T)
xgb.full_pred_2015 = as.data.frame(xgb.full_pred_2015)
colnames(xgb.full_pred_2015) = c("Out", "Single", "Double", "Triple", "Home_Run")

preds_full_2015 <- batted_ball_model_2015
preds_full_2015$out.prob <- xgb.full_pred_2015[,1]
preds_full_2015$single.prob <- xgb.full_pred_2015[,2]
preds_full_2015$double.prob <- xgb.full_pred_2015[,3]
preds_full_2015$triple.prob <- xgb.full_pred_2015[,4]
preds_full_2015$hr.prob <- xgb.full_pred_2015[,5]

max_prob_full_2015 <- colnames(xgb.full_pred_2015)[apply(xgb.full_pred_2015,1,which.max)]

preds_full_2015$max.prob <- max_prob_full_2015

preds_full_2015$pred.right <- ifelse(preds_full_2015$max.prob == "Out" & preds_full_2015$outcome_ec == 0, "yes", 
                                ifelse(preds_full_2015$max.prob == "Single" & preds_full_2015$outcome_ec == 1, "yes",
                                       ifelse(preds_full_2015$max.prob == "Double" & preds_full_2015$outcome_ec == 2, "yes",
                                              ifelse(preds_full_2015$max.prob == "Triple" & preds_full_2015$outcome_ec == 3, "yes",
                                                     ifelse(preds_full_2015$max.prob == "Home_Run" & preds_full_2015$outcome_ec == 4, "yes", "no")))))
preds_full_2015$pred.right <- as.factor(preds_full_2015$pred.right)

sum(preds_full_2015$pred.right == "yes") / nrow(preds_full_2015) #0.8544968

This is where it gets fun. Like I mentioned in the opening, I’m going to follow a similar workflow to what Baseball Prospectus used for DRC+. The generalized linear mixed-effects models improved the accruacy of each model, oh so slightly, with increases between 0.002 and 0.004 percent. While the accuracy hardly increased, I think the model is much better off with including the batter and pitcher identity. It’s important to note that there are ‘no free lunches.’ The generalized linear mixed-effects model for the 2015 season increased triple classifcation accuracy from 20.77% (XGBoost model) to 61.54% and increased double accuracy from 59.37% to 69%. But out classification accuracy declined from 93.14% to 91%. In a perfect world, all accuraries would increase in the new model, but that’s not how things work unfortunately. Ultimately, I do think the trade-off is worth it.

df.single <- preds_full_2015 %>%
  filter(outcome_ec == 0 | outcome_ec == 1) %>%
  mutate(outcome = ifelse(outcome_ec == 0, 0, 1))
df.double <- preds_full_2015 %>%
  filter(outcome_ec == 0 | outcome_ec == 2) %>%
  mutate(outcome = ifelse(outcome_ec == 0, 0, 1))
df.triple <- preds_full_2015 %>%
  filter(outcome_ec == 0 | outcome_ec == 3) %>%
  mutate(outcome = ifelse(outcome_ec == 0, 0, 1))
df.home_run <- preds_full_2015 %>%
  filter(outcome_ec == 0 | outcome_ec == 4) %>%
  mutate(outcome = ifelse(outcome_ec == 0, 0, 1))

glmer.single.mod.2015 <- glmer(
  outcome ~
    (1|pitcher_name) +
    (1|player_name) +
    logit(out.prob) + logit(single.prob) + logit(double.prob) + logit(triple.prob) + logit(hr.prob),
  data=df.single,
  family=binomial(link = "probit"),
  nAGQ=0)
glmer.double.mod.2015 <- glmer(
  outcome ~
    (1|pitcher_name) +
    (1|player_name) +     
     logit(out.prob) + logit(single.prob) + logit(double.prob) + logit(triple.prob) + logit(hr.prob),
  data=df.double,
  family=binomial(link = "probit"),
  nAGQ=0)
glmer.triple.mod.2015 <- glmer(
  outcome ~
    (1|pitcher_name) +
    (1|player_name) +
     logit(out.prob) + logit(single.prob) + logit(double.prob) + logit(triple.prob) + logit(hr.prob),
  data=df.triple,
  family=binomial(link = "probit"),
  nAGQ=0)
glmer.home_run.mod.2015 <- glmer(
  outcome ~
    (1|pitcher_name) +
    (1|player_name) + 
    logit(out.prob) + logit(single.prob) + logit(double.prob) + logit(triple.prob) + logit(hr.prob),
  data=df.home_run,
  family=binomial(link = "probit"),
  nAGQ=0)

df.preds_2015 <- preds_full_2015
df.preds_2015$single_all_lp_bat <- predict(glmer.single.mod.2015, newdata=df.preds_2015,
                                    allow.new.levels = TRUE, type='link', re.form=~(1|player_name))
df.preds_2015$double_all_lp_bat <- predict(glmer.double.mod.2015, newdata=df.preds_2015,
                                    allow.new.levels = TRUE, type='link', re.form=~(1|player_name))
df.preds_2015$triple_all_lp_bat <- predict(glmer.triple.mod.2015, newdata=df.preds_2015,
                                    allow.new.levels = TRUE, type='link', re.form=~(1|player_name))
df.preds_2015$home_run_all_lp_bat <- predict(glmer.home_run.mod.2015, newdata=df.preds_2015,
                                    allow.new.levels = TRUE, type='link', re.form=~(1|player_name))

model.coef.2015 <- df.preds_2015 %>%
  dplyr::mutate(
    K_all = 1 + exp(single_all_lp_bat) + exp(double_all_lp_bat) + exp(triple_all_lp_bat) + exp(home_run_all_lp_bat),
    outs_new.prob = 1 / K_all,
    single_new.prob = exp(single_all_lp_bat) / K_all,
    double_new.prob = exp(double_all_lp_bat) / K_all,
    triple_new.prob = exp(triple_all_lp_bat) / K_all,
    home_run_new.prob = exp(home_run_all_lp_bat) / K_all)

model.coef.2015 %<>%
  mutate(max.prob_ec = ifelse(outs_new.prob > single_new.prob & outs_new.prob > double_new.prob & outs_new.prob > triple_new.prob & outs_new.prob > home_run_new.prob, 0,
                           ifelse(single_new.prob > outs_new.prob & single_new.prob > double_new.prob & single_new.prob > triple_new.prob & 
                                    single_new.prob > home_run_new.prob, 1,
                                  ifelse(double_new.prob > outs_new.prob & double_new.prob > single_new.prob & double_new.prob > triple_new.prob 
                                         & double_new.prob > home_run_new.prob, 2,
                                         ifelse(triple_new.prob > outs_new.prob & triple_new.prob > single_new.prob & triple_new.prob > double_new.prob &
                                                  triple_new.prob > home_run_new.prob,  3, 4)))))

model.coef.2015 %<>%
  mutate(pred.right_new = ifelse(max.prob_ec == outcome_ec, "yes", "no"))

sum(model.coef.2015$pred.right_new == "yes") / nrow((model.coef.2015)) #  xgb is 0.8544968 this is 0.8581859

Now, after all of that, I’m actually going to make the metric.

woba_weights_2015 <- c(0, .881, 1.256, 1.594, 2.065) # from FanGraphs

model.coef.2015 %<>%
  mutate(expected_woba = (outs_new.prob * woba_weights_2015[1]) + (single_new.prob * woba_weights_2015[2]) + (double_new.prob * woba_weights_2015[3]) + 
           (triple_new.prob * woba_weights_2015[4]) + (home_run_new.prob * woba_weights_2015[5]))

model.coef.2015$percentile <- 100 * (scales::rescale(model.coef.2015$expected_woba, to=c(0,1)))
model.coef.2015$qcp <- psych::rescale(model.coef.2015$percentile, mean = 100, sd = 30, df=F)
LS0tCnRpdGxlOiAiQ3JlYXRpbmcgUUMrIFBhcnQgMyAtIE1vZGVsaW5nIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUbyBjcmVhdGUgYSBxdWFsaXR5IG9mIGNvbnRhY3QgbWV0cmljLCBJJ20gZmlyc3QgY3JlYXRpbmcgYSBtdWx0aS1jbGFzcyBjbGFzc2lmaWNhdGlvbiBtb2RlbCB0aGF0IGFpbXMgdG8gcHJlZGljdCB0aGUgb3V0Y29tZSBvZiBlYWNoIGJhdHRlZCBiYWxsIHVzaW5nIGEgWEdCb29zdCBtb2RlbC4gWEdCb29zdCBpcyBhIGRlY2lzaW9uIHRyZWUgYmFzZWQgZW5zZW1ibGUgc3VwZXJ2aXNlZCBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSB0aGF0IHVzZXMgYSBncmFkaWVudCBib29zdGluZyBmcmFtZXdvcmsuIEdyYWRpZW50IGJvb3N0aW5nIGlzIGEgY2FzZSBvZiBib29zdGluZyB3aGVyZSBlcnJvcnMgYXJlIG1pbmltaXplZCBieSBncmFkaWVudCBkZXNjZW50IGFuZCBhcHBsaWVzIHRoZSBwcmluY2lwbGUgb2YgYm9vc3Rpbmcgd2VhayBsZWFybmVycy4gVGhlIHJhdGlvbmFsZSBmb3IgdXNpbmcgWEdCb29zdCBsaWVzIGluIGl0cyBlYXN5IHRvIHVuZGVyc3RhbmQgbmF0dXJlIGFuZCB0aGUgc3RydWN0dXJlIGFuZCBzaXplIG9mIHRoZSBkYXRhLiBEZWNpc2lvbiB0cmVlcyBmb3IgY2xhc3NpZmljYXRpb25zIGFyZSBlYXN5IHRvIGludGVycHJldCBvbiBhIGZ1bmRhbWVudGFsIGxldmVsLiBBIGJhc2ljIGRlY2lzaW9uIHRyZWUsIGZvciBleGFtcGxlIGp1c3QgYSB0cmVlIHN0dW1wLCB2aXN1YWxpemVkIGl0IGlzIGVhc3kgdG8gc2VlIHRoZSByYXRpb25hbGUgZm9yIHRoZSBjbGFzc2lmaWNhdGlvbi4gU2luY2UgdGhpcyBkYXRhc2V0IGlzIHJlbGF0aXZlbHkgbGFyZ2UgKG92ZXIgMTAwLDAwMCBvYnNlcnZhdGlvbnMgcGVyIHNlYXNvbikgYW5kIGlzIHRhYnVsYXIgZGF0YSwgZ3JhZGllbnQgYm9vc3RpbmcgbWFjaGluZXMgKEdCTXMpLCBzcGVjaWZpY2FsbHkgWEdCb29zdCBzZWVtcyBsaWtlIGEgZmluZSBjaG9pY2UgZm9yIHRoaXMgcHJvYmxlbS4gQWxzbywgR0JNcyBhcmUgbm9uLXBhcmFtZXRyaWMgbW9kZWxzIHRoYXQgYXJlIHN1aXRhYmxlIGZvciB0aGlzIG5vbi1saW5lYXIgZGF0YS4gCgpGb3IgbXkgbW9kZWxpbmcsIEknbSBnb2luZyB0byB1c2UgcGxheSBvdXRjb21lIGFzIHRoZSByZXNwb25zZSB2YXJpYWJsZS4gVGhlIHBsYXkgb3V0Y29tZSAob3V0LCBzaW5nbGUsIGRvdWJsZSwgdHJpcGxlLCBob21lcnVuKSBpcyBhIGdvb2Qgc3RhcnRpbmcgcGxhY2UgZm9yIG1lYXN1cmluZyBxdWFsaXR5IG9mIGNvbnRhY3QuIElmIHdlIGFyZSBqdXN0IGxvb2tpbmcgYXQgZ3JhZGluZyBxdWFsaXR5IG9mIGNvbnRhY3QgYmFzZWQgb24gdGhlIHJlc3VsdCBvZiB0aGUgYmF0dGVkIGJhbGwgdGhlbiB3ZSBrbm93IHRoYXQgYSBob21lcnVuIGlzIGJldHRlciB0aGFuIGEgdHJpcGxlIHdoaWNoIGlzIGJldHRlciB0aGFuIGEgZG91YmxlIGFuZCBzbyBvbi4gVGhpcyBtZXRyaWMgcHJvdmlkZXMgYSBicm9hZGx5IGFjY2VwdGVkIHdheSB0byByYW5rIHRoZSBxdWFsaXR5IG9mIGEgYmF0dGVkIGJhbGwuIEdlbmVyYWxseSBzcGVha2luZywgaGl0dGluZyBhIGJhbGwgaGFyZGVyIChtb3JlIGV4aXQgc3BlZWQpIGlzIGJldHRlciB0aGFuIGhpdHRpbmcgYSBiYWxsIHNvZnRlci4gSG93ZXZlciwgaXTigJlzIGltcG9ydGFudCB0byBpbmNsdWRlIHRoZSBsYXVuY2ggYW5nbGUgd2hlbiB1c2luZyBleGl0IHNwZWVkLiBBIGJhdHRlciB3b3VsZCBtdWNoIHJhdGhlciBoaXQgYSBiYWxsIDEwNSBtcGggYXQgMjUgZGVncmVlcyB0aGFuIGEgYmFsbCAxMjUgbXBoIGF0IC0xMCBkZWdyZWVzLiBUaGVyZSBhcmUgZXhjZXB0aW9ucywgYnV0IGluIHRoZSBhZ2dyZWdhdGUgd2Uga25vdyB0aGF0IGhvbWVydW5zIGhhdmUgdGhlIGJlc3QgY29tYmluYXRpb24gb2YgZXhpdCBzcGVlZCBhbmQgbGF1bmNoIGFuZ2xlLiBUaGVyZSBpcyBtb3JlIHRvIGFzc2Vzc2luZyBxdWFsaXR5IG9mIGNvbnRhY3QgdGhhbiBqdXN0IGV4aXQgc3BlZWQgYW5kIGxhdW5jaCBhbmdsZSwgc3VjaCBhcyBzcHJheSBhbmdsZSwgYnV0IGl0J3MgYWxzbyBpbmNyZWRpYmx5IGltcG9ydGFudCB0byBhY2NvdW50IGZvciBvdGhlciBjb250ZXh0dWFsIHZhcmlhYmxlcy4KCkkgc3RhcnQgdGhlIG1vZGVsaW5nIGJ5IGRvaW5nIGEgc2ltcGxlIDEwLWZvbGQgY3Jvc3MtdmFsaWRhdGlvbiB0byBkZXRlcm1pbmUgdGhlIGFwcHJvcHJpYXRlIG51bWJlciBvZiBpdGVyYXRpb25zIHRvIHVzZSBpbiBhIGJhc2VsaW5lIFhHQm9vc3QgbW9kZWwuIFRoZXJlIGFyZSB0d28gbWFpbiBjaG9pY2VzIEkgbWFkZSBiZWZvcmUgc3RhcnRpbmcgdGhlIFhHQm9vc3QgbW9kZWxpbmcuIFRoZSBmaXJzdCBpcyB0aGF0IEknbSBnb2luZyB0byB1c2UgbXVsdGk6c29mdHByb2IgYXMgdGhlIG9iamVjdGl2ZSBvZiB0aGUgbW9kZWwgd2l0aCBtbG9nbG9zcyBldmFsdWF0aW9uIG1ldHJpYy4gbXVsdGk6c29mdHByb2IgcmV0dXJucyB0aGUgcHJvYmFiaWxpdHkgb2YgZWFjaCBvYnNlcnZhdGlvbiBiZWluZyBhIG1lbWJlciBvZiBlYWNoIGNsYXNzLiBUaGVyZSBhcmUgZml2ZSBjbGFzc2VzIG9mIHRoZSByZXNwb25zZSB2YXJpYWJsZSAob3V0LCBzaW5nbGUsIGRvdWJsZSwgdHJpcGxlLCBhbmQgaG9tZXJ1bikuIEkgbWFkZSB0aGlzIGNob2ljZSBiZWNhdXNlIHlvdSBjYW4gZ2FpbiBtb3JlIGluZm9ybWF0aW9uIGFib3V0IGVhY2ggYmF0dGVkIGJhbGwga25vd2luZyB0aGUgcHJvYmFiaWxpdHkgb2YgaXQgYmVsb25naW5nIHRvIGVhY2ggY2xhc3MgcmF0aGVyIHRoYW4gdGhlIG1vZGVsIHJldHVybmluZyB3aGljaCBjbGFzcyBoYXMgdGhlIG1heGltdW0gcHJvYmFiaWxpdHkuIFNlY29uZCwgSSB1c2VkIG1sb2dsb3NzIGFzIHRoZSBldmFsdWF0aW9uIG1ldHJpYyBpbiB0aGUgWEdCb29zdCBtb2RlbGluZy4gVGhlIGV2YWx1YXRpb24gbWV0cmljIGlzIHVzZWQgZm9yIHZhbGlkYXRpb24gZGF0YSBpbiBib3RoIHRoZSBjcm9zcy12YWxpZGF0aW9uIGFuZCBYR0Jvb3N0IG1vZGVsaW5nLCBpbiBhZGRpdGlvbiB0byBiZWluZyB1c2VkIGZvciBlYXJseSBzdG9wcGluZyBhbmQgbW9kZWwgZXZhbHVhdGlvbi4gbWxvZ2xvc3MgaXMgdGhlIGxvc3MgZnVuY3Rpb24gdXNlZCBpbiBtdWx0aW5vbWlhbCBsb2dpc3RpYyByZWdyZXNzaW9uIGFuZCBpcyBkZWZpbmVkIGFzIHRoZSBuZWdhdGl2ZSBsb2ctbGlrZWxpaG9vZCBvZiBhIGxvZ2lzdGljIG1vZGVsIHRoYXQgcmV0dXJucyBwcm9iYWJpbGl0aWVzIGZvciBpdHMgdHJhaW5pbmcgZGF0YS4gVGhlIG1vZGVscyBhbHNvIGhhdmUgbm8gaHlwZXJwYXJhbWV0ZXJzIHNwZWNpZmllZCwgbWVhbmluZyB0aGF0IGFsbCBvZiB0aG9zZSBwYXJhbWV0ZXJzIGFyZSB0aGVpciBkZWZhdWx0IHZhbHVlcy4gTm9ybWFsbHksIEknZCBoeXBlcnBhcmFtZXRlciB0dW5lIGFuIFhHQm9vc3QgbW9kZWwgdXNpbmcgYSBsYXRpbiBoeXBlcmN1YmUsIGhvd2V2ZXIgSSBkb24ndCB3YW50IHRvIHN1YmplY3QgbXkgbGFwdG9wIHRvIHJ1bm5pbmcgMTUwIGRpZmZlcmVudCBtb2RlbHMsIGFuZCBpbiBteSBleHBlcmllbmNlIHR1bmluZyBzZWVtcyB0byBpbmNyZWFzZSBhY2N1cmFjeSBieSBhdCBtb3N0IDElLiAKCkV2ZW4gdGhvdWdoIEknbSBnb2luZyB0byBydW4gYSBtb2RlbCBmb3IgZWFjaCBzZWFzb24gb24gdGhlIGVudGlyZSBzZWFzb24ncyB3b3J0aCBvZiBkYXRhLCBJJ20gc3RpbGwgZ29pbmcgdG8gZG8gYSB0eXBpY2FsIDcwLzMwIHRyYWluL3Rlc3Qgc3BsaXQgZmlyc3QgdG8gZW5zdXJlIHRoZSBtb2RlbCBpcyBub3Qgb3Zlci0gb3IgdW5kZXItZml0dGluZy4gCgpJbiBhZGRpdGlvbiwgdG8gdGhlIFhHQm9vc3QgbW9kZWwsIEknbSBnb2luZyB1c2UgdGhlIGNsYXNzIHByb2JhYmlsdGllcyAocHJvYmFiaWxpdHkgb2Ygb3V0LCBzaW5nbGUsIGRvdWJsZSwgdHJpcGxlLCBhbmQgaG9tZXJ1bikgYXMgaW5wdXRzIHRvIGEgZ2VuZXJhbGl6ZWQgbGluZWFyIG1peGVkLWVmZmVjdHMgbW9kZWwgKEdMTU0pLiBUaGUgbXVsdGlub21pYWwgbW9kZWxpbmcgd29ya2Zsb3cgY29tZXMgZnJvbSAqQmFzZWJhbGwgUHJvc3BlY3R1cyogYW5kIHRoZWlyIGNyZWF0aW9uIG9mIERSQysgKGh0dHBzOi8vd3d3LmJhc2ViYWxscHJvc3BlY3R1cy5jb20vbmV3cy9hcnRpY2xlLzQ4MjkzL2VudGlyZWx5LWJleW9uZC13b3d5LWEtYnJlYWtkb3duLW9mLWRyYy8jZm5yZWY0KS4gQmVsb3cgSSdtIGdvaW5nIHRvIGNyZWF0ZSBmb3VyIGJpbm9taWFsIHN1YnNldHMsIHRoZXJlZm9yZSB0dXJuaW5nIHRoaXMgbXVsdGlub21pYWwgcHJvYmxlbSBpbnRvIG11bHRpcGxlIGJpbm9taWFsIG1vZGVscy4gVGhlIGZvdXIgc3VzYmV0cyBhcmU6IG91dCArIHNpbmdsZSwgb3V0ICsgZG91YmxlLCBvdXQgKyB0cmlwbGUsIGFuZCBvdXQgKyBob21lcnVuLiBFYWNoIHN1YnNldCBoYXMgb3V0cyBiZWNhdXNlIHRoYXQgaXMgb3VyICJwaXZvdCwiIHRoZSBjb21tb24gY2F0ZWdvcnkgZXZlcnkgb3RoZXIgZXZlbnQgd2lsbCBiZSByZWdyZXNzZWQgYWdhaW5zdC4gT3V0cyB3ZXJlIHNlbGVjdGVkIGJlY2F1c2UsIGFzIEp1ZGdlIHNheXMsIHRoaXMgbWV0aG9kb2xvZ3kgd29ya3MgYmVzdCB3aGVuIHRoZSBwaXZvdCBpcyBhbHNvIHRoZSBsYXJnZXN0IGNhdGVnb3J5LiBUaGUgbW9zdCBjb21tb24gb3V0Y29tZSBmb3IgYSBiYXR0ZWQgYmFsbCBpcyBhbiBvdXQgKHJlbWVtYmVyIHRoZSB0eXBpY2FsIGxlYWd1ZSBhdmVyYWdlIGJhdHRpbmcgYXZlcmFnZSBvZiBiYWxscyBpbiBwbGF5IChCQUJJUCkgaXMgfi4zMDApLiBUaGVuIGVhY2ggYmlub21pYWwgc3Vic2V0IGlzIGZpdCBvbiBhIEdMTU0uIE15IHNpbmd1bGFyIG1vdGl2YXRpb24gb2YgdXNpbmcgdGhpcyBtb2RlbGluZyAoYmVzaWRlcyBzYXlpbmcgSSdtIHVzaW5nIGEgR0xNTSkgaXMgdG8gaW5jbHVkZSBiYXR0ZXIgYW5kIHBpdGNoZXIgaWRlbnRpdHkuIEl0J3MgY2xlYXIgdGhhdCBiYXR0ZXIgYW5kIHBpdGNoZXJzIGhhdmUgc29tZSBlZmZlY3Qgb24gdGhlIG91dGNvbWUgb2YgYSBiYXR0ZWQgYmFsbC4gRm9yIGV4YW1wbGUsIGV2ZW4gd2l0aG91dCBleHBsaWNpdGx5IGluY2x1ZGluZyBzcHJpbnQgc3BlZWQsIGluIG15IGV4cGVyaWVuY2UgdGhpcyB0eXBlIG9mIG1vZGVsIGlzIGFibGUgdG8gcGljayB1cCBvbiB3aGF0IGJhdHRlcnMgYXJlIGFibGUgdG8gdHVybiBzaW5nbGVzIGludG8gZG91YmxlIG9yIGRvdWJsZXMgaW50byB0cmlwbGVzLiBJdCdzIHRoZW9yZXRpY2FsbHkgcG9zc2libGUgdG8gaW5jbHVkZSBiYXR0ZXIgYW5kIHBpdGNoZXJzIGluIG15IFhHQm9vc3QgbW9kZWxpbmcgYXMgZHVtbXkgdmFyaWFibGVzLCBidXQgSSBkb24ndCB0aGluayBteSBwb29yIGxhcHRvcCB3b3VsZCd2ZSBiZWVuIGFibGUgdG8gaGFuZGxlIGEgMTA1LDAwMCBieSAzLDIwMCBkYXRhc2V0IGZpdmUgdGltZXMgZm9yIGdyYWRpZW50IGJvb3N0aW5nLiAKCkkgd2lsbCBiZSB1c2luZyB0aGUgbG9naXQgb2YgZWFjaCBjbGFzcyBwcm9iYWJpbGl0eSBhbmQgdGhlIGJhdHRlciBhbmQgcGl0Y2hlciBhcyBmZWF0dXJlcyBpbiB0aGUgR0xNTSBtb2RlbC4gTG9naXQsIGFsc28ga25vd24gYXMgdGhlIGxvZy1vZGRzLCBpcyB0aGUgbG9nYXJpdGhtIG9mIHRoZSBvZGRzICRcZnJhY3twfXsxIC0gcH0kLCB3aGVyZSBwIGlzIHRoZSBwcm9iYWJpbGl0eSAoaW4gb3VyIGNhc2UsIHRoZSBwcm9iYWJpbGl0eSBvZiBhbiBvdXQsIHNpbmdsZSwgZG91YmxlLCB0cmlwbGUsIG9yIGhvbWVydW4pLiBGb3IgZXhhbXBsZSwgdGFrZSB0aGUgb3V0IHByb2JhYmlsaXR5LCBiZWZvcmUgYmVpbmcgdXNlZCBpbiB0aGUgbW9kZWwsIGl0IHdvdWxkIG5vdyBsb29rIGxpa2UgdGhpczogJFxsb2dcbGVmdChcZnJhY3tvdXQucHJvYmFiaWxpdHl9ezEgLSAob3V0LnByb2JhYmlsaXR5KX1ccmlnaHQpJC4gCgpUaGUgZmluYWwgZXF1YXRpb24gZm9yIHRoZSBlYWNoIEdMTU0gbW9kZWwgaXM6IG91dGNvbWUgfiAoMXxwaXRjaGVyKSArICgxfGJhdHRlcikgKyBsb2dpdChvdXQgcHJvYmFiaWxpdHkpICsgbG9naXQoc2luZ2xlIHByb2JhYmlsaXR5KSArIGxvZ2l0KGRvdWJsZSBwcm9iYWJpbGl0eSkgKyBsb2dpdCh0cmlwbGUgcHJvYmFiaWxpdHkpICsgbG9naXQoaG9tZXJ1biBwcm9iYWJpbGl0eSkuIEluIGFkZGl0aW9uIHRvIGluY2x1ZGluZyBiYXR0ZXIgYW5kIHBpdGNoZXIgaWRlbnRpdHksIHdoaWNoIEkgYmVsaWV2ZSB3aWxsIG1ha2UgdGhlIG1vZGVsIGEgbG90IG1vcmUgcm9idXN0LCB0aGlzIG1vZGVsIGFsc28gYWN0cyBhcyBhIHNvcnQgb2Ygc3RhY2tpbmcgYWxnb3JpdGhtLgoKU3RhY2tpbmcgaXMgYSBwb3B1bGFyIGVuc2VtYmxlIG1ldGhvZCBpbiBtYWNoaW5lIGxlYXJuaW5nLiBHZW5lcmFsbHksIHN0YWNraW5nIGludm9sdmVzIHRyYWluaW5nIHNldmVyYWwgbW9kZWxzIHdpdGggZGlmZmVyZW50IGFsZ29yaXRobXMgdGhhdCBhcmUgcmVsYXRpdmVseSBzaW1wbGUgKGJhc2UtbGVhcm5lcnMpLiBUaGVuIHRoZSBwcmVkaWN0aW9ucyBmcm9tIGVhY2ggbW9kZWwgYXJlIGZlZCBpbnRvIG9uZSBmaW5hbCBtb2RlbCAobWV0YS1sZWFybmVyKSB0byBtYWtlIHRoZSBmaW5hbCBwcmVkaWN0aW9uLiBTbyB0aGUgaW5wdXRzIGZvciB0aGUgbWV0YS1sZWFybmVyIGFyZSB0aGUgcHJlZGljdGlvbiBvdXRwdXRzIG9mIHRoZSBiYXNlLWxlYXJuZXJzLiBUaGUgYmVuZWZpdCBvZiBzdGFja2luZyBpcyB0aGF0IGNhbiBjb21iaW5lIHRoZSBjYXBhYmlsaXRpZXMgb2YgYSBtdWx0aXR1ZGUgb2YgZ29vZCBtb2RlbHMgdGhhdCBlbmQgdXAgbWFraW5nIGEgc3Ryb25nZXIgbW9kZWwgdGhhbiBhbnkgb2YgdGhlIGJhc2UtbGVhcm5lcnMuIEkgd291bGRuJ3QgY29uc2lkZXIgbXkgbWV0aG9kb2xvZ3kgYXMgZXhhY3RseSBzdGFja2luZyBiZWNhdXNlIEknbSBub3QgY29tYmluaW5nIG1vZGVscywgcmF0aGVyIHVzaW5nIHRoZSBvdXRwdXRzIGZyb20gb25lIG1vZGVsLCBpbiBhZGRpdGlvbiB0byBvdGhlciBmZWF0dXJlcywgYXMgdGhlIGlucHV0IHRvIGEgZmluYWwgbW9kZWwuIEhvd2V2ZXIsIEkgZG8gdGhpbmsgdGhhdCBJIHdpbGwgc3RpbGwgZW5qb3kgc29tZSBvZiB0aGUgYmVuZWZpdHMgb2Ygc3RhY2tpbmcuIEl0J3MgaW1wb3J0YW50IHRvIG5vdGUsIGFzIGl0IHdhcyBwb2ludGVkIG91dCB0byBtZSwgdGhhdCBzb21ldGltZXMgWEdCb29zdCBjYW4gc21vb3RoIG92ZXIgdGhlIGxpbmVhciBtb2RlbCBzaWduYWwgZm9yIHRoZSByYW5kb20gZWZmZWN0cyAocGl0Y2hlciBhbmQgYmF0dGVyIGlkZW50aXR5KS4gVGhlcmVmb3JlLCBpdCdzIGEgcG9zc2liaWxpdHkgdGhhdCB0aGUgbWl4ZWQtZWZmZWN0cyBtb2RlbCBkb2Vzbid0IGVudGlyZWx5IGNhcHR1cmUgdGhlIHJhbmRvbSBlZmZlY3Qgb2YgZWFjaCBiYXR0ZXIgYW5kIHBpdGNoZXIgYWNjdXJyYXRlbHkuIAoKTGFzdGx5LCB0byBjcmVhdGUgdGhlIFFDKyBtZXRyaWMgSSB3aWxsIHRha2UgdGhlIG5ldyBjbGFzcyBwcm9iYWJpbGl0aWVzIGZyb20gdGhlIEdMTU0gbW9kZWwgYW5kIG11bHRpcGx5IGVhY2ggcHJvYmFiaWl0eSB3aXRoIGl0cyBhc3NvY2lhdGVkIGxpbmVhciB3ZWlnaHQuIEZvciBleGFtcGxlLCBzYXkgYSBiYXR0ZWQgYmFsbCBoYXMgYSBwcm9iYWJpbGl0eSBvZiBiZWluZyBhbiBvdXQgb2YgLjQ1LCBhIHNpbmdsZSAuMjUsIGEgZG91YmxlIC4xNSwgYSB0cmlwbGUgLjEwLCBhbmQgYSBob21lcnVuIC4wNS4gU2F5IHRoaXMgYmFsbCB3YXMgZnJvbSB0aGUgMjAxNSBzZWFzb24sIG9uIEZhbkdyYXBocyB3ZSBjYW4gc2VlIHRoYXQgdGhlIGxpbmVhciB3ZWlnaHQgb2YgYSBzaW5nbGUgd2FzIDAuODgxLCBkb3VibGUgMS4yNTYsIHRyaXBsZSAxLjU5NCwgYW5kIGhvbWVydW4gMi4wNjUuIFRoZW4gdGhlIGV4cGVjdGVkIHdlaWdodCBmb3IgdGhpcyBiYXR0ZWQgYmFsbCB3b3VsZCBiZTogJC40NSAqIDAgKyAuMjUgKiAuODgxICsgLjE1ICogMS4yNTYgKyAuMTAgKiAxLjU5NCArIC4wNSAqIDIuMDY1ID0gMC42NzEzJC4gSSdtIGdvaW5nIHRvIGRvIHRoYXQgZm9yIGV2ZXJ5IGJhdHRlZCBiYWxsIGluIHRoZSBzZWFzb24gYW5kIHRoZW4gc3RhbmRhcmRpemUgdGhlbSBzbyB0aGF0IHRoZSBhdmVyYWdlIFFDKyBpcyAxMDAsIHdpdGggYSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMzAuIFRoZSBhdmVyYWdlIG9mIDEwMCBwdXRzIFFDKyBvbiBhIHNpbWlsYXIgc2NhbGUgYXMgd1JDKywgRFJDKywgYW5kIG90aGVyIG1ldHJpY3MuIEkgcGlja2VkIGEgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIDMwLCBiZWNhdXNlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2Ygd1JDKyBvdmVyIHRoZSBsYXN0IGNvdXBsZSBvZiB5ZWFycyB3YXMgdmVyeSBjbG9zZSB0byAzMC4gCgoKQmVsb3cgSSdtIGp1c3QgZ29pbmcgdG8gc2hvdyB0aGUgcHJvY2VzcyBvZiB0aGUgMjAxNSBzZWFzb24gbW9kZWwsIGJ1dCB0aGUgMjAxNi0yMDE5IG1vZGVscyBhcmUgdGhlIGV4YWN0IHNhbWUuIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGJhc2ViYWxscikKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoYXJtKQpsaWJyYXJ5KGJsbWUpCmxpYnJhcnkobG1lNCkKbGlicmFyeSh4Z2Jvb3N0KQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoZmFzdER1bW1pZXMpCmxpYnJhcnkoY2FyZXQpCmBgYAoKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmJhdHRlZF9iYWxsX21vZGVsIDwtIHJlYWRfY3N2KCJiYXR0ZWRfYmFsbF9wcm9jZXNzZWQuY3N2IikgJT4lIGRwbHlyOjpzZWxlY3QoLWMoIlgxIikpCmBgYAoKCmBgYHtyfQojIHNldHRpbmcgc2VlZCBmb3IgcmVwcm9kdWNpYmlsaXR5CnNldC5zZWVkKDEyMykgCmBgYAoKQ3JlYXRpbmcgYSBkYXRhc2V0IGZvciBlYWNoIHNlYXNvbi4KYGBge3J9CmJhdHRlZF9iYWxsX21vZGVsXzIwMTUgPC0gYmF0dGVkX2JhbGxfbW9kZWwgJT4lIGZpbHRlcihnYW1lX3llYXIgPT0gMjAxNSkKYmF0dGVkX2JhbGxfbW9kZWxfMjAxNiA8LSBiYXR0ZWRfYmFsbF9tb2RlbCAlPiUgZmlsdGVyKGdhbWVfeWVhciA9PSAyMDE2KQpiYXR0ZWRfYmFsbF9tb2RlbF8yMDE3IDwtIGJhdHRlZF9iYWxsX21vZGVsICU+JSBmaWx0ZXIoZ2FtZV95ZWFyID09IDIwMTcpCmJhdHRlZF9iYWxsX21vZGVsXzIwMTggPC0gYmF0dGVkX2JhbGxfbW9kZWwgJT4lIGZpbHRlcihnYW1lX3llYXIgPT0gMjAxOCkKYmF0dGVkX2JhbGxfbW9kZWxfMjAxOSA8LSBiYXR0ZWRfYmFsbF9tb2RlbCAlPiUgZmlsdGVyKGdhbWVfeWVhciA9PSAyMDE5KQpgYGAKCkhlcmUgaXMgdGhlIFhHQm9vc3QgbW9kZWxpbmcgZm9yIGVhY2ggc2Vhc29uLCBzcGxpdCBpbnRvIHRyYWluL3Rlc3Qgc2V0cyB0byBkZXRlcm1pbmUgb3ZlcmFsbCBnZW5lcmFsaXphdGlvbiBhYmlsaXR5LiBGb3IgdGhlIHNha2Ugb2YgYmVpbmcgKHNvbWV3aGF0KSBicmVpZiwgSSdtIG9ubHkgZ29pbmcgdG8gc2hvdyB0aGUgMjAxNSBtb2RlbCB0aHJvdWdob3V0IHRoZSBlbnRpcmUgbm90ZWJvb2ssIGFzIHRoZSAyMDE2LTIwMTkgbW9kZWxzIGFyZSB0aGUgc2FtZS4KYGBge3J9CiMjIyMjIyMgMjAxNQojIGNyZWF0ZSBpbmRlY2llcyBmb3Igc3BsaXR0aW5nIChuZWVkIHRvIHVzZSBhIHNwZWNpZmljIGNvbHVtbiBmcm9tIGRmIGZvciBpdCB0byBydW4pCnRyYWluX2luZGV4XzIwMTUgPC0gY3JlYXRlRGF0YVBhcnRpdGlvbih5ID0gYmF0dGVkX2JhbGxfbW9kZWxfMjAxNSRvdXRjb21lX2VjLCBwID0gLjcwLCBsaXN0ID0gRkFMU0UpICU+JSBhcy52ZWN0b3IoKQoKIyBzcGxpdCBpbnRvIHRyYWluIGFuZCB0ZXN0CnRyYWluXzIwMTUgPC0gYmF0dGVkX2JhbGxfbW9kZWxfMjAxNVt0cmFpbl9pbmRleF8yMDE1LF0KdGVzdF8yMDE1IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMTVbLXRyYWluX2luZGV4XzIwMTUsXQoKIyBuZWVkIGEgdmVjdG9yIG9mIHJlc3BvbnNlIHZhcmlhYmxlIChvdXRjb21lKQp2ZWNfbGFiZWxfdHJhaW5fMjAxNSA8LSB0cmFpbl8yMDE1JG91dGNvbWVfZWMKCnRyYWluX2RhdGFfMjAxNSA8LSBhcy5tYXRyaXgodHJhaW5fMjAxNSAlPiUgZHBseXI6OnNlbGVjdChjKCJsYXVuY2hfYW5nbGUiLCAibGF1bmNoX3NwZWVkIiwgInNwcmF5X2FuZ2xlIiwgInN0YW5kX3IiLCAicF90aHJvd3NfciIsICJ0ZW1wZXJhdHVyZSIsICJpc19kb21lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGl0Y2hfdHlwZV9DSDp2ZW51ZV9iYXR0ZXIuc3RhbmRfWWFua2VlU3RhZGl1bV9yKSkpCgp2ZWNfbGFiZWxfdGVzdF8yMDE1IDwtIHRlc3RfMjAxNSRvdXRjb21lX2VjCnRlc3RfZGF0YV8yMDE1IDwtIGFzLm1hdHJpeCh0ZXN0XzIwMTUgJT4lIGRwbHlyOjpzZWxlY3QoYygibGF1bmNoX2FuZ2xlIiwgImxhdW5jaF9zcGVlZCIsICJzcHJheV9hbmdsZSIsICJzdGFuZF9yIiwgInBfdGhyb3dzX3IiLCAidGVtcGVyYXR1cmUiLCAiaXNfZG9tZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpdGNoX3R5cGVfQ0g6dmVudWVfYmF0dGVyLnN0YW5kX1lhbmtlZVN0YWRpdW1fcikpKQoKIyBjb252ZXJ0IHRoZSB0cmFpbiBhbmQgdGVzdCBpbnRvIHhnYi5ETWF0cml4CnhfdHJhaW5fMjAxNSA9IHhnYm9vc3Q6OnhnYi5ETWF0cml4KGRhdGEgPSB0cmFpbl9kYXRhXzIwMTUsIGxhYmVsID0gdmVjX2xhYmVsX3RyYWluXzIwMTUpCnhfdGVzdF8yMDE1ID0geGdib29zdDo6eGdiLkRNYXRyaXgoZGF0YSA9IHRlc3RfZGF0YV8yMDE1LCBsYWJlbCA9IHZlY19sYWJlbF90ZXN0XzIwMTUpCgpiYXNlbGluZV9jdl8yMDE1IDwtIHhnYm9vc3Q6OnhnYi5jdihwYXJhbXMgPSBsaXN0KG9iamVjdGl2ZSA9ICJtdWx0aTpzb2Z0cHJvYiIsIGV2YWxfbWV0cmljID0gYygibWxvZ2xvc3MiKSwgbnVtX2NsYXNzID0gNSksIGRhdGEgPSB4X3RyYWluXzIwMTUsIG5yb3VuZHMgPSAyNTAwLCBlYXJseV9zdG9wcGluZ19yb3VuZHMgPSAxMCwgbmZvbGQ9MTAsIHN0cmF0aWZpZWQgPSBUKQoKYmFzZV9tb2RfMjAxNSA8LSB4Z2Jvb3N0Ojp4Z2Jvb3N0KHBhcmFtcyA9IGxpc3Qob2JqZWN0aXZlID0gIm11bHRpOnNvZnRwcm9iIiwgZXZhbF9tZXRyaWMgPSBjKCJtbG9nbG9zcyIpLCBudW1fY2xhc3MgPSA1KSwgZGF0YSA9IHhfdHJhaW5fMjAxNSwgbnJvdW5kcyA9IGJhc2VsaW5lX2N2XzIwMTUkYmVzdF9udHJlZWxpbWl0KQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CiMjIyMjIyMgMjAxNgoKIyBjcmVhdGUgaW5kZWNpZXMgZm9yIHNwbGl0dGluZyAobmVlZCB0byB1c2UgYSBzcGVjaWZpYyBjb2x1bW4gZnJvbSBkZiBmb3IgaXQgdG8gcnVuKQp0cmFpbl9pbmRleF8yMDE2IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24oeSA9IGJhdHRlZF9iYWxsX21vZGVsXzIwMTYkb3V0Y29tZV9lYywgcCA9IC43MCwgbGlzdCA9IEZBTFNFKSAlPiUgYXMudmVjdG9yKCkKCiMgc3BsaXQgaW50byB0cmFpbiBhbmQgdGVzdAp0cmFpbl8yMDE2IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMTZbdHJhaW5faW5kZXhfMjAxNixdCnRlc3RfMjAxNiA8LSBiYXR0ZWRfYmFsbF9tb2RlbF8yMDE2Wy10cmFpbl9pbmRleF8yMDE2LF0KCiMgbmVlZCBhIHZlY3RvciBvZiByZXNwb25zZSB2YXJpYWJsZSAob3V0Y29tZSkKdmVjX2xhYmVsX3RyYWluXzIwMTYgPC0gdHJhaW5fMjAxNiRvdXRjb21lX2VjCgp0cmFpbl9kYXRhXzIwMTYgPC0gYXMubWF0cml4KHRyYWluXzIwMTYgJT4lIGRwbHlyOjpzZWxlY3QoYygibGF1bmNoX2FuZ2xlIiwgImxhdW5jaF9zcGVlZCIsICJzcHJheV9hbmdsZSIsICJzdGFuZF9yIiwgInBfdGhyb3dzX3IiLCAidGVtcGVyYXR1cmUiLCAiaXNfZG9tZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpdGNoX3R5cGVfQ0g6dmVudWVfYmF0dGVyLnN0YW5kX1lhbmtlZVN0YWRpdW1fcikpKQoKdmVjX2xhYmVsX3Rlc3RfMjAxNiA8LSB0ZXN0XzIwMTYkb3V0Y29tZV9lYwp0ZXN0X2RhdGFfMjAxNiA8LSBhcy5tYXRyaXgodGVzdF8yMDE2ICU+JSBkcGx5cjo6c2VsZWN0KGMoImxhdW5jaF9hbmdsZSIsICJsYXVuY2hfc3BlZWQiLCAic3ByYXlfYW5nbGUiLCAic3RhbmRfciIsICJwX3Rocm93c19yIiwgInRlbXBlcmF0dXJlIiwgImlzX2RvbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaXRjaF90eXBlX0NIOnZlbnVlX2JhdHRlci5zdGFuZF9ZYW5rZWVTdGFkaXVtX3IpKSkKCiMgY29udmVydCB0aGUgdHJhaW4gYW5kIHRlc3QgaW50byB4Z2IuRE1hdHJpeAp4X3RyYWluXzIwMTYgPSB4Z2Jvb3N0Ojp4Z2IuRE1hdHJpeChkYXRhID0gdHJhaW5fZGF0YV8yMDE2LCBsYWJlbCA9IHZlY19sYWJlbF90cmFpbl8yMDE2KQp4X3Rlc3RfMjAxNiA9IHhnYm9vc3Q6OnhnYi5ETWF0cml4KGRhdGEgPSB0ZXN0X2RhdGFfMjAxNiwgbGFiZWwgPSB2ZWNfbGFiZWxfdGVzdF8yMDE2KQoKYmFzZWxpbmVfY3ZfMjAxNiA8LSB4Z2Jvb3N0Ojp4Z2IuY3YocGFyYW1zID0gbGlzdChvYmplY3RpdmUgPSAibXVsdGk6c29mdHByb2IiLCBldmFsX21ldHJpYyA9IGMoIm1sb2dsb3NzIiksIG51bV9jbGFzcyA9IDUpLCBkYXRhID0geF90cmFpbl8yMDE2LCBucm91bmRzID0gMjUwMCwgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gMTAsIG5mb2xkPTEwLCBzdHJhdGlmaWVkID0gVCkKCmJhc2VfbW9kXzIwMTYgPC0geGdib29zdDo6eGdib29zdChwYXJhbXMgPSBsaXN0KG9iamVjdGl2ZSA9ICJtdWx0aTpzb2Z0cHJvYiIsIGV2YWxfbWV0cmljID0gYygibWxvZ2xvc3MiKSwgbnVtX2NsYXNzID0gNSksIGRhdGEgPSB4X3RyYWluXzIwMTYsIG5yb3VuZHMgPSBiYXNlbGluZV9jdl8yMDE2JGJlc3RfbnRyZWVsaW1pdCkKCiMjIyMjIyMgMjAxNwoKIyBjcmVhdGUgaW5kZWNpZXMgZm9yIHNwbGl0dGluZyAobmVlZCB0byB1c2UgYSBzcGVjaWZpYyBjb2x1bW4gZnJvbSBkZiBmb3IgaXQgdG8gcnVuKQp0cmFpbl9pbmRleF8yMDE3IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24oeSA9IGJhdHRlZF9iYWxsX21vZGVsXzIwMTckb3V0Y29tZV9lYywgcCA9IC43MCwgbGlzdCA9IEZBTFNFKSAlPiUgYXMudmVjdG9yKCkKCiMgc3BsaXQgaW50byB0cmFpbiBhbmQgdGVzdAp0cmFpbl8yMDE3IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMTdbdHJhaW5faW5kZXhfMjAxNyxdCnRlc3RfMjAxNyA8LSBiYXR0ZWRfYmFsbF9tb2RlbF8yMDE3Wy10cmFpbl9pbmRleF8yMDE3LF0KCiMgbmVlZCBhIHZlY3RvciBvZiByZXNwb25zZSB2YXJpYWJsZSAob3V0Y29tZSkKdmVjX2xhYmVsX3RyYWluXzIwMTcgPC0gdHJhaW5fMjAxNyRvdXRjb21lX2VjCgp0cmFpbl9kYXRhXzIwMTcgPC0gYXMubWF0cml4KHRyYWluXzIwMTcgJT4lIGRwbHlyOjpzZWxlY3QoYygibGF1bmNoX2FuZ2xlIiwgImxhdW5jaF9zcGVlZCIsICJzcHJheV9hbmdsZSIsICJzdGFuZF9yIiwgInBfdGhyb3dzX3IiLCAidGVtcGVyYXR1cmUiLCAiaXNfZG9tZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpdGNoX3R5cGVfQ0g6dmVudWVfYmF0dGVyLnN0YW5kX1lhbmtlZVN0YWRpdW1fcikpKQoKdmVjX2xhYmVsX3Rlc3RfMjAxNyA8LSB0ZXN0XzIwMTckb3V0Y29tZV9lYwp0ZXN0X2RhdGFfMjAxNyA8LSBhcy5tYXRyaXgodGVzdF8yMDE3ICU+JSBkcGx5cjo6c2VsZWN0KGMoImxhdW5jaF9hbmdsZSIsICJsYXVuY2hfc3BlZWQiLCAic3ByYXlfYW5nbGUiLCAic3RhbmRfciIsICJwX3Rocm93c19yIiwgInRlbXBlcmF0dXJlIiwgImlzX2RvbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaXRjaF90eXBlX0NIOnZlbnVlX2JhdHRlci5zdGFuZF9ZYW5rZWVTdGFkaXVtX3IpKSkKCiMgY29udmVydCB0aGUgdHJhaW4gYW5kIHRlc3QgaW50byB4Z2IuRE1hdHJpeAp4X3RyYWluXzIwMTcgPSB4Z2Jvb3N0Ojp4Z2IuRE1hdHJpeChkYXRhID0gdHJhaW5fZGF0YV8yMDE3LCBsYWJlbCA9IHZlY19sYWJlbF90cmFpbl8yMDE3KQp4X3Rlc3RfMjAxNyA9IHhnYm9vc3Q6OnhnYi5ETWF0cml4KGRhdGEgPSB0ZXN0X2RhdGFfMjAxNywgbGFiZWwgPSB2ZWNfbGFiZWxfdGVzdF8yMDE3KQoKYmFzZWxpbmVfY3ZfMjAxNyA8LSB4Z2Jvb3N0Ojp4Z2IuY3YocGFyYW1zID0gbGlzdChvYmplY3RpdmUgPSAibXVsdGk6c29mdHByb2IiLCBldmFsX21ldHJpYyA9IGMoIm1sb2dsb3NzIiksIG51bV9jbGFzcyA9IDUpLCBkYXRhID0geF90cmFpbl8yMDE3LCBucm91bmRzID0gMjUwMCwgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gMTAsIG5mb2xkPTEwLCBzdHJhdGlmaWVkID0gVCkKCmJhc2VfbW9kXzIwMTcgPC0geGdib29zdDo6eGdib29zdChwYXJhbXMgPSBsaXN0KG9iamVjdGl2ZSA9ICJtdWx0aTpzb2Z0cHJvYiIsIGV2YWxfbWV0cmljID0gYygibWxvZ2xvc3MiKSwgbnVtX2NsYXNzID0gNSksIGRhdGEgPSB4X3RyYWluXzIwMTcsIG5yb3VuZHMgPSBiYXNlbGluZV9jdl8yMDE3JGJlc3RfbnRyZWVsaW1pdCkKCiMjIyMjIyMgMjAxOAoKIyBjcmVhdGUgaW5kZWNpZXMgZm9yIHNwbGl0dGluZyAobmVlZCB0byB1c2UgYSBzcGVjaWZpYyBjb2x1bW4gZnJvbSBkZiBmb3IgaXQgdG8gcnVuKQp0cmFpbl9pbmRleF8yMDE4IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24oeSA9IGJhdHRlZF9iYWxsX21vZGVsXzIwMTgkb3V0Y29tZV9lYywgcCA9IC43MCwgbGlzdCA9IEZBTFNFKSAlPiUgYXMudmVjdG9yKCkKCiMgc3BsaXQgaW50byB0cmFpbiBhbmQgdGVzdAp0cmFpbl8yMDE4IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMThbdHJhaW5faW5kZXhfMjAxOCxdCnRlc3RfMjAxOCA8LSBiYXR0ZWRfYmFsbF9tb2RlbF8yMDE4Wy10cmFpbl9pbmRleF8yMDE4LF0KCiMgbmVlZCBhIHZlY3RvciBvZiByZXNwb25zZSB2YXJpYWJsZSAob3V0Y29tZSkKdmVjX2xhYmVsX3RyYWluXzIwMTggPC0gdHJhaW5fMjAxOCRvdXRjb21lX2VjCgp0cmFpbl9kYXRhXzIwMTggPC0gYXMubWF0cml4KHRyYWluXzIwMTggJT4lIGRwbHlyOjpzZWxlY3QoYygibGF1bmNoX2FuZ2xlIiwgImxhdW5jaF9zcGVlZCIsICJzcHJheV9hbmdsZSIsICJzdGFuZF9yIiwgInBfdGhyb3dzX3IiLCAidGVtcGVyYXR1cmUiLCAiaXNfZG9tZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpdGNoX3R5cGVfQ0g6dmVudWVfYmF0dGVyLnN0YW5kX1lhbmtlZVN0YWRpdW1fcikpKQoKdmVjX2xhYmVsX3Rlc3RfMjAxOCA8LSB0ZXN0XzIwMTgkb3V0Y29tZV9lYwp0ZXN0X2RhdGFfMjAxOCA8LSBhcy5tYXRyaXgodGVzdF8yMDE4ICU+JSBkcGx5cjo6c2VsZWN0KGMoImxhdW5jaF9hbmdsZSIsICJsYXVuY2hfc3BlZWQiLCAic3ByYXlfYW5nbGUiLCAic3RhbmRfciIsICJwX3Rocm93c19yIiwgInRlbXBlcmF0dXJlIiwgImlzX2RvbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaXRjaF90eXBlX0NIOnZlbnVlX2JhdHRlci5zdGFuZF9ZYW5rZWVTdGFkaXVtX3IpKSkKCiMgY29udmVydCB0aGUgdHJhaW4gYW5kIHRlc3QgaW50byB4Z2IuRE1hdHJpeAp4X3RyYWluXzIwMTggPSB4Z2Jvb3N0Ojp4Z2IuRE1hdHJpeChkYXRhID0gdHJhaW5fZGF0YV8yMDE4LCBsYWJlbCA9IHZlY19sYWJlbF90cmFpbl8yMDE4KQp4X3Rlc3RfMjAxOCA9IHhnYm9vc3Q6OnhnYi5ETWF0cml4KGRhdGEgPSB0ZXN0X2RhdGFfMjAxOCwgbGFiZWwgPSB2ZWNfbGFiZWxfdGVzdF8yMDE4KQoKYmFzZWxpbmVfY3ZfMjAxOCA8LSB4Z2Jvb3N0Ojp4Z2IuY3YocGFyYW1zID0gbGlzdChvYmplY3RpdmUgPSAibXVsdGk6c29mdHByb2IiLCBldmFsX21ldHJpYyA9IGMoIm1sb2dsb3NzIiksIG51bV9jbGFzcyA9IDUpLCBkYXRhID0geF90cmFpbl8yMDE4LCBucm91bmRzID0gMjUwMCwgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gMTAsIG5mb2xkPTEwLCBzdHJhdGlmaWVkID0gVCkKCmJhc2VfbW9kXzIwMTggPC0geGdib29zdDo6eGdib29zdChwYXJhbXMgPSBsaXN0KG9iamVjdGl2ZSA9ICJtdWx0aTpzb2Z0cHJvYiIsIGV2YWxfbWV0cmljID0gYygibWxvZ2xvc3MiKSwgbnVtX2NsYXNzID0gNSksIGRhdGEgPSB4X3RyYWluXzIwMTgsIG5yb3VuZHMgPSBiYXNlbGluZV9jdl8yMDE4JGJlc3RfbnRyZWVsaW1pdCkKCiMjIyMjIyMgMjAxOQoKIyBjcmVhdGUgaW5kZWNpZXMgZm9yIHNwbGl0dGluZyAobmVlZCB0byB1c2UgYSBzcGVjaWZpYyBjb2x1bW4gZnJvbSBkZiBmb3IgaXQgdG8gcnVuKQp0cmFpbl9pbmRleF8yMDE5IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24oeSA9IGJhdHRlZF9iYWxsX21vZGVsXzIwMTkkb3V0Y29tZV9lYywgcCA9IC43MCwgbGlzdCA9IEZBTFNFKSAlPiUgYXMudmVjdG9yKCkKCiMgc3BsaXQgaW50byB0cmFpbiBhbmQgdGVzdAp0cmFpbl8yMDE5IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMTlbdHJhaW5faW5kZXhfMjAxOSxdCnRlc3RfMjAxOSA8LSBiYXR0ZWRfYmFsbF9tb2RlbF8yMDE5Wy10cmFpbl9pbmRleF8yMDE5LF0KCiMgbmVlZCBhIHZlY3RvciBvZiByZXNwb25zZSB2YXJpYWJsZSAob3V0Y29tZSkKdmVjX2xhYmVsX3RyYWluXzIwMTkgPC0gdHJhaW5fMjAxOSRvdXRjb21lX2VjCgp0cmFpbl9kYXRhXzIwMTkgPC0gYXMubWF0cml4KHRyYWluXzIwMTkgJT4lIGRwbHlyOjpzZWxlY3QoYygibGF1bmNoX2FuZ2xlIiwgImxhdW5jaF9zcGVlZCIsICJzcHJheV9hbmdsZSIsICJzdGFuZF9yIiwgInBfdGhyb3dzX3IiLCAidGVtcGVyYXR1cmUiLCAiaXNfZG9tZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpdGNoX3R5cGVfQ0g6dmVudWVfYmF0dGVyLnN0YW5kX1lhbmtlZVN0YWRpdW1fcikpKQoKdmVjX2xhYmVsX3Rlc3RfMjAxOSA8LSB0ZXN0XzIwMTkkb3V0Y29tZV9lYwp0ZXN0X2RhdGFfMjAxOSA8LSBhcy5tYXRyaXgodGVzdF8yMDE5ICU+JSBkcGx5cjo6c2VsZWN0KGMoImxhdW5jaF9hbmdsZSIsICJsYXVuY2hfc3BlZWQiLCAic3ByYXlfYW5nbGUiLCAic3RhbmRfciIsICJwX3Rocm93c19yIiwgInRlbXBlcmF0dXJlIiwgImlzX2RvbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaXRjaF90eXBlX0NIOnZlbnVlX2JhdHRlci5zdGFuZF9ZYW5rZWVTdGFkaXVtX3IpKSkKCiMgY29udmVydCB0aGUgdHJhaW4gYW5kIHRlc3QgaW50byB4Z2IuRE1hdHJpeAp4X3RyYWluXzIwMTkgPSB4Z2Jvb3N0Ojp4Z2IuRE1hdHJpeChkYXRhID0gdHJhaW5fZGF0YV8yMDE5LCBsYWJlbCA9IHZlY19sYWJlbF90cmFpbl8yMDE5KQp4X3Rlc3RfMjAxOSA9IHhnYm9vc3Q6OnhnYi5ETWF0cml4KGRhdGEgPSB0ZXN0X2RhdGFfMjAxOSwgbGFiZWwgPSB2ZWNfbGFiZWxfdGVzdF8yMDE5KQoKYmFzZWxpbmVfY3ZfMjAxOSA8LSB4Z2Jvb3N0Ojp4Z2IuY3YocGFyYW1zID0gbGlzdChvYmplY3RpdmUgPSAibXVsdGk6c29mdHByb2IiLCBldmFsX21ldHJpYyA9IGMoIm1sb2dsb3NzIiksIG51bV9jbGFzcyA9IDUpLCBkYXRhID0geF90cmFpbl8yMDE5LCBucm91bmRzID0gMjUwMCwgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gMTAsIG5mb2xkPTEwLCBzdHJhdGlmaWVkID0gVCkKCmJhc2VfbW9kXzIwMTkgPC0geGdib29zdDo6eGdib29zdChwYXJhbXMgPSBsaXN0KG9iamVjdGl2ZSA9ICJtdWx0aTpzb2Z0cHJvYiIsIGV2YWxfbWV0cmljID0gYygibWxvZ2xvc3MiKSwgbnVtX2NsYXNzID0gNSksIGRhdGEgPSB4X3RyYWluXzIwMTksIG5yb3VuZHMgPSBiYXNlbGluZV9jdl8yMDE5JGJlc3RfbnRyZWVsaW1pdCkKYGBgCgpIZXJlIEknbSBjb21wdXRpbmcgdGhlIHRlc3Qgc2V0IGFjY3VyYWN5IGZvciBlYWNoIHNlYXNvbidzIG1vZGVsLiBUaGUgYWNjdXJhY2llcyByYW5nZSBmcm9tIDgwLjglIHRvIDgxLjYlLCB3aGljaCBpcyB2ZXJ5IGdvb2QuIEtlZXAgaW4gbWluZCB0aGF0IGEgbmFpdmUgY2xhc3NpZmllciB3b3VsZCBoYXZlIGFuIGFjY3VyYWN5IGFyb3VuZCAyMCUgKHJhbmRvbWx5IGd1ZXNzaW5nIHRoZSBjbGFzcyBmb3IgZWFjaCBvYnNlcnZhdGlvbikuIApgYGB7cn0KeGdiLnByZWRfMjAxNSA9IHByZWRpY3QoYmFzZV9tb2RfMjAxNSwgeF90ZXN0XzIwMTUsIHJlc2hhcGU9VCkKeGdiLnByZWRfMjAxNSA9IGFzLmRhdGEuZnJhbWUoeGdiLnByZWRfMjAxNSkKY29sbmFtZXMoeGdiLnByZWRfMjAxNSkgPSBjKCJPdXQiLCAiU2luZ2xlIiwgIkRvdWJsZSIsICJUcmlwbGUiLCAiSG9tZV9SdW4iKQoKcHJlZHNfYmFzZV8yMDE1IDwtIHRlc3RfMjAxNQpwcmVkc19iYXNlXzIwMTUkb3V0LnByb2IgPC0geGdiLnByZWRfMjAxNVssMV0KcHJlZHNfYmFzZV8yMDE1JHNpbmdsZS5wcm9iIDwtIHhnYi5wcmVkXzIwMTVbLDJdCnByZWRzX2Jhc2VfMjAxNSRkb3VibGUucHJvYiA8LSB4Z2IucHJlZF8yMDE1WywzXQpwcmVkc19iYXNlXzIwMTUkdHJpcGxlLnByb2IgPC0geGdiLnByZWRfMjAxNVssNF0KcHJlZHNfYmFzZV8yMDE1JGhyLnByb2IgPC0geGdiLnByZWRfMjAxNVssNV0KCm1heF9wcm9iXzIwMTUgPC0gY29sbmFtZXMoeGdiLnByZWRfMjAxNSlbYXBwbHkoeGdiLnByZWRfMjAxNSwxLHdoaWNoLm1heCldCgpwcmVkc19iYXNlXzIwMTUkbWF4LnByb2IgPC0gbWF4X3Byb2JfMjAxNQoKcHJlZHNfYmFzZV8yMDE1JHByZWQucmlnaHQgPC0gaWZlbHNlKHByZWRzX2Jhc2VfMjAxNSRtYXgucHJvYiA9PSAiT3V0IiAmIHByZWRzX2Jhc2VfMjAxNSRvdXRjb21lX2VjID09IDAsICJ5ZXMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfYmFzZV8yMDE1JG1heC5wcm9iID09ICJTaW5nbGUiICYgcHJlZHNfYmFzZV8yMDE1JG91dGNvbWVfZWMgPT0gMSwgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19iYXNlXzIwMTUkbWF4LnByb2IgPT0gIkRvdWJsZSIgJiBwcmVkc19iYXNlXzIwMTUkb3V0Y29tZV9lYyA9PSAyLCAieWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19iYXNlXzIwMTUkbWF4LnByb2IgPT0gIlRyaXBsZSIgJiBwcmVkc19iYXNlXzIwMTUkb3V0Y29tZV9lYyA9PSAzLCAieWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfYmFzZV8yMDE1JG1heC5wcm9iID09ICJIb21lX1J1biIgJiBwcmVkc19iYXNlXzIwMTUkb3V0Y29tZV9lYyA9PSA0LCAieWVzIiwgIm5vIikpKSkpCnByZWRzX2Jhc2VfMjAxNSRwcmVkLnJpZ2h0IDwtIGFzLmZhY3RvcihwcmVkc19iYXNlXzIwMTUkcHJlZC5yaWdodCkKCnN1bShwcmVkc19iYXNlXzIwMTUkcHJlZC5yaWdodCA9PSAieWVzIikgLyBucm93KHByZWRzX2Jhc2VfMjAxNSkgIzAuODA4MzE1OQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CiMjIyMjIyAyMDE2CnhnYi5wcmVkXzIwMTYgPSBwcmVkaWN0KGJhc2VfbW9kXzIwMTYsIHhfdGVzdF8yMDE2LCByZXNoYXBlPVQpCnhnYi5wcmVkXzIwMTYgPSBhcy5kYXRhLmZyYW1lKHhnYi5wcmVkXzIwMTYpCmNvbG5hbWVzKHhnYi5wcmVkXzIwMTYpID0gYygiT3V0IiwgIlNpbmdsZSIsICJEb3VibGUiLCAiVHJpcGxlIiwgIkhvbWVfUnVuIikKCnByZWRzX2Jhc2VfMjAxNiA8LSB0ZXN0XzIwMTYKcHJlZHNfYmFzZV8yMDE2JG91dC5wcm9iIDwtIHhnYi5wcmVkXzIwMTZbLDFdCnByZWRzX2Jhc2VfMjAxNiRzaW5nbGUucHJvYiA8LSB4Z2IucHJlZF8yMDE2WywyXQpwcmVkc19iYXNlXzIwMTYkZG91YmxlLnByb2IgPC0geGdiLnByZWRfMjAxNlssM10KcHJlZHNfYmFzZV8yMDE2JHRyaXBsZS5wcm9iIDwtIHhnYi5wcmVkXzIwMTZbLDRdCnByZWRzX2Jhc2VfMjAxNiRoci5wcm9iIDwtIHhnYi5wcmVkXzIwMTZbLDVdCgptYXhfcHJvYl8yMDE2IDwtIGNvbG5hbWVzKHhnYi5wcmVkXzIwMTYpW2FwcGx5KHhnYi5wcmVkXzIwMTYsMSx3aGljaC5tYXgpXQoKcHJlZHNfYmFzZV8yMDE2JG1heC5wcm9iIDwtIG1heF9wcm9iXzIwMTYKCnByZWRzX2Jhc2VfMjAxNiRwcmVkLnJpZ2h0IDwtIGlmZWxzZShwcmVkc19iYXNlXzIwMTYkbWF4LnByb2IgPT0gIk91dCIgJiBwcmVkc19iYXNlXzIwMTYkb3V0Y29tZV9lYyA9PSAwLCAieWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Jhc2VfMjAxNiRtYXgucHJvYiA9PSAiU2luZ2xlIiAmIHByZWRzX2Jhc2VfMjAxNiRvdXRjb21lX2VjID09IDEsICJ5ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfYmFzZV8yMDE2JG1heC5wcm9iID09ICJEb3VibGUiICYgcHJlZHNfYmFzZV8yMDE2JG91dGNvbWVfZWMgPT0gMiwgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfYmFzZV8yMDE2JG1heC5wcm9iID09ICJUcmlwbGUiICYgcHJlZHNfYmFzZV8yMDE2JG91dGNvbWVfZWMgPT0gMywgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Jhc2VfMjAxNiRtYXgucHJvYiA9PSAiSG9tZV9SdW4iICYgcHJlZHNfYmFzZV8yMDE2JG91dGNvbWVfZWMgPT0gNCwgInllcyIsICJubyIpKSkpKQpwcmVkc19iYXNlXzIwMTYkcHJlZC5yaWdodCA8LSBhcy5mYWN0b3IocHJlZHNfYmFzZV8yMDE2JHByZWQucmlnaHQpCgpzdW0ocHJlZHNfYmFzZV8yMDE2JHByZWQucmlnaHQgPT0gInllcyIpIC8gbnJvdyhwcmVkc19iYXNlXzIwMTYpICMwLjgxMDIwMDIKCgojIyMjIyMgMjAxNwp4Z2IucHJlZF8yMDE3ID0gcHJlZGljdChiYXNlX21vZF8yMDE3LCB4X3Rlc3RfMjAxNywgcmVzaGFwZT1UKQp4Z2IucHJlZF8yMDE3ID0gYXMuZGF0YS5mcmFtZSh4Z2IucHJlZF8yMDE3KQpjb2xuYW1lcyh4Z2IucHJlZF8yMDE3KSA9IGMoIk91dCIsICJTaW5nbGUiLCAiRG91YmxlIiwgIlRyaXBsZSIsICJIb21lX1J1biIpCgpwcmVkc19iYXNlXzIwMTcgPC0gdGVzdF8yMDE3CnByZWRzX2Jhc2VfMjAxNyRvdXQucHJvYiA8LSB4Z2IucHJlZF8yMDE3WywxXQpwcmVkc19iYXNlXzIwMTckc2luZ2xlLnByb2IgPC0geGdiLnByZWRfMjAxN1ssMl0KcHJlZHNfYmFzZV8yMDE3JGRvdWJsZS5wcm9iIDwtIHhnYi5wcmVkXzIwMTdbLDNdCnByZWRzX2Jhc2VfMjAxNyR0cmlwbGUucHJvYiA8LSB4Z2IucHJlZF8yMDE3Wyw0XQpwcmVkc19iYXNlXzIwMTckaHIucHJvYiA8LSB4Z2IucHJlZF8yMDE3Wyw1XQoKbWF4X3Byb2JfMjAxNyA8LSBjb2xuYW1lcyh4Z2IucHJlZF8yMDE3KVthcHBseSh4Z2IucHJlZF8yMDE3LDEsd2hpY2gubWF4KV0KCnByZWRzX2Jhc2VfMjAxNyRtYXgucHJvYiA8LSBtYXhfcHJvYl8yMDE3CgpwcmVkc19iYXNlXzIwMTckcHJlZC5yaWdodCA8LSBpZmVsc2UocHJlZHNfYmFzZV8yMDE3JG1heC5wcm9iID09ICJPdXQiICYgcHJlZHNfYmFzZV8yMDE3JG91dGNvbWVfZWMgPT0gMCwgInllcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19iYXNlXzIwMTckbWF4LnByb2IgPT0gIlNpbmdsZSIgJiBwcmVkc19iYXNlXzIwMTckb3V0Y29tZV9lYyA9PSAxLCAieWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Jhc2VfMjAxNyRtYXgucHJvYiA9PSAiRG91YmxlIiAmIHByZWRzX2Jhc2VfMjAxNyRvdXRjb21lX2VjID09IDIsICJ5ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Jhc2VfMjAxNyRtYXgucHJvYiA9PSAiVHJpcGxlIiAmIHByZWRzX2Jhc2VfMjAxNyRvdXRjb21lX2VjID09IDMsICJ5ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19iYXNlXzIwMTckbWF4LnByb2IgPT0gIkhvbWVfUnVuIiAmIHByZWRzX2Jhc2VfMjAxNyRvdXRjb21lX2VjID09IDQsICJ5ZXMiLCAibm8iKSkpKSkKcHJlZHNfYmFzZV8yMDE3JHByZWQucmlnaHQgPC0gYXMuZmFjdG9yKHByZWRzX2Jhc2VfMjAxNyRwcmVkLnJpZ2h0KQoKc3VtKHByZWRzX2Jhc2VfMjAxNyRwcmVkLnJpZ2h0ID09ICJ5ZXMiKSAvIG5yb3cocHJlZHNfYmFzZV8yMDE3KSAjMC44MTU0MTg5CgoKIyMjIyMjIDIwMTgKeGdiLnByZWRfMjAxOCA9IHByZWRpY3QoYmFzZV9tb2RfMjAxOCwgeF90ZXN0XzIwMTgsIHJlc2hhcGU9VCkKeGdiLnByZWRfMjAxOCA9IGFzLmRhdGEuZnJhbWUoeGdiLnByZWRfMjAxOCkKY29sbmFtZXMoeGdiLnByZWRfMjAxOCkgPSBjKCJPdXQiLCAiU2luZ2xlIiwgIkRvdWJsZSIsICJUcmlwbGUiLCAiSG9tZV9SdW4iKQoKcHJlZHNfYmFzZV8yMDE4IDwtIHRlc3RfMjAxOApwcmVkc19iYXNlXzIwMTgkb3V0LnByb2IgPC0geGdiLnByZWRfMjAxOFssMV0KcHJlZHNfYmFzZV8yMDE4JHNpbmdsZS5wcm9iIDwtIHhnYi5wcmVkXzIwMThbLDJdCnByZWRzX2Jhc2VfMjAxOCRkb3VibGUucHJvYiA8LSB4Z2IucHJlZF8yMDE4WywzXQpwcmVkc19iYXNlXzIwMTgkdHJpcGxlLnByb2IgPC0geGdiLnByZWRfMjAxOFssNF0KcHJlZHNfYmFzZV8yMDE4JGhyLnByb2IgPC0geGdiLnByZWRfMjAxOFssNV0KCm1heF9wcm9iXzIwMTggPC0gY29sbmFtZXMoeGdiLnByZWRfMjAxOClbYXBwbHkoeGdiLnByZWRfMjAxOCwxLHdoaWNoLm1heCldCgpwcmVkc19iYXNlXzIwMTgkbWF4LnByb2IgPC0gbWF4X3Byb2JfMjAxOAoKcHJlZHNfYmFzZV8yMDE4JHByZWQucmlnaHQgPC0gaWZlbHNlKHByZWRzX2Jhc2VfMjAxOCRtYXgucHJvYiA9PSAiT3V0IiAmIHByZWRzX2Jhc2VfMjAxOCRvdXRjb21lX2VjID09IDAsICJ5ZXMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfYmFzZV8yMDE4JG1heC5wcm9iID09ICJTaW5nbGUiICYgcHJlZHNfYmFzZV8yMDE4JG91dGNvbWVfZWMgPT0gMSwgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19iYXNlXzIwMTgkbWF4LnByb2IgPT0gIkRvdWJsZSIgJiBwcmVkc19iYXNlXzIwMTgkb3V0Y29tZV9lYyA9PSAyLCAieWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19iYXNlXzIwMTgkbWF4LnByb2IgPT0gIlRyaXBsZSIgJiBwcmVkc19iYXNlXzIwMTgkb3V0Y29tZV9lYyA9PSAzLCAieWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfYmFzZV8yMDE4JG1heC5wcm9iID09ICJIb21lX1J1biIgJiBwcmVkc19iYXNlXzIwMTgkb3V0Y29tZV9lYyA9PSA0LCAieWVzIiwgIm5vIikpKSkpCnByZWRzX2Jhc2VfMjAxOCRwcmVkLnJpZ2h0IDwtIGFzLmZhY3RvcihwcmVkc19iYXNlXzIwMTgkcHJlZC5yaWdodCkKCnN1bShwcmVkc19iYXNlXzIwMTgkcHJlZC5yaWdodCA9PSAieWVzIikgLyBucm93KHByZWRzX2Jhc2VfMjAxOCkgIzAuODE2MDcyOQoKIyMjIyMjIDIwMTkKeGdiLnByZWRfMjAxOSA9IHByZWRpY3QoYmFzZV9tb2RfMjAxOSwgeF90ZXN0XzIwMTksIHJlc2hhcGU9VCkKeGdiLnByZWRfMjAxOSA9IGFzLmRhdGEuZnJhbWUoeGdiLnByZWRfMjAxOSkKY29sbmFtZXMoeGdiLnByZWRfMjAxOSkgPSBjKCJPdXQiLCAiU2luZ2xlIiwgIkRvdWJsZSIsICJUcmlwbGUiLCAiSG9tZV9SdW4iKQoKcHJlZHNfYmFzZV8yMDE5IDwtIHRlc3RfMjAxOQpwcmVkc19iYXNlXzIwMTkkb3V0LnByb2IgPC0geGdiLnByZWRfMjAxOVssMV0KcHJlZHNfYmFzZV8yMDE5JHNpbmdsZS5wcm9iIDwtIHhnYi5wcmVkXzIwMTlbLDJdCnByZWRzX2Jhc2VfMjAxOSRkb3VibGUucHJvYiA8LSB4Z2IucHJlZF8yMDE5WywzXQpwcmVkc19iYXNlXzIwMTkkdHJpcGxlLnByb2IgPC0geGdiLnByZWRfMjAxOVssNF0KcHJlZHNfYmFzZV8yMDE5JGhyLnByb2IgPC0geGdiLnByZWRfMjAxOVssNV0KCm1heF9wcm9iXzIwMTkgPC0gY29sbmFtZXMoeGdiLnByZWRfMjAxOSlbYXBwbHkoeGdiLnByZWRfMjAxOSwxLHdoaWNoLm1heCldCgpwcmVkc19iYXNlXzIwMTkkbWF4LnByb2IgPC0gbWF4X3Byb2JfMjAxOQoKcHJlZHNfYmFzZV8yMDE5JHByZWQucmlnaHQgPC0gaWZlbHNlKHByZWRzX2Jhc2VfMjAxOSRtYXgucHJvYiA9PSAiT3V0IiAmIHByZWRzX2Jhc2VfMjAxOSRvdXRjb21lX2VjID09IDAsICJ5ZXMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfYmFzZV8yMDE5JG1heC5wcm9iID09ICJTaW5nbGUiICYgcHJlZHNfYmFzZV8yMDE5JG91dGNvbWVfZWMgPT0gMSwgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19iYXNlXzIwMTkkbWF4LnByb2IgPT0gIkRvdWJsZSIgJiBwcmVkc19iYXNlXzIwMTkkb3V0Y29tZV9lYyA9PSAyLCAieWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19iYXNlXzIwMTkkbWF4LnByb2IgPT0gIlRyaXBsZSIgJiBwcmVkc19iYXNlXzIwMTkkb3V0Y29tZV9lYyA9PSAzLCAieWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfYmFzZV8yMDE5JG1heC5wcm9iID09ICJIb21lX1J1biIgJiBwcmVkc19iYXNlXzIwMTkkb3V0Y29tZV9lYyA9PSA0LCAieWVzIiwgIm5vIikpKSkpCnByZWRzX2Jhc2VfMjAxOSRwcmVkLnJpZ2h0IDwtIGFzLmZhY3RvcihwcmVkc19iYXNlXzIwMTkkcHJlZC5yaWdodCkKCnN1bShwcmVkc19iYXNlXzIwMTkkcHJlZC5yaWdodCA9PSAieWVzIikgLyBucm93KHByZWRzX2Jhc2VfMjAxOSkgIzAuODA4NDk4MgpgYGAKCgpOb3csIEknbSBnb2luZyB0byB0cmFpbiBlYWNoIG1vZGVsIG9uIHRoZSBlbnRpcmUgc2Vhc29uJ3MgZGF0YS4KYGBge3J9CiMjIyAyMDE1CnZlY19sYWJlbF8yMDE1IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMTUkb3V0Y29tZV9lYwphbGxfZGF0YXNldF8yMDE1IDwtIGFzLm1hdHJpeChiYXR0ZWRfYmFsbF9tb2RlbF8yMDE1ICU+JSBkcGx5cjo6c2VsZWN0KGMoImxhdW5jaF9hbmdsZSIsICJsYXVuY2hfc3BlZWQiLCAic3ByYXlfYW5nbGUiLCAic3RhbmRfciIsICJwX3Rocm93c19yIiwgInRlbXBlcmF0dXJlIiwgImlzX2RvbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaXRjaF90eXBlX0NIOnZlbnVlX2JhdHRlci5zdGFuZF9ZYW5rZWVTdGFkaXVtX3IpKSkKZnVsbF9kYXRhc2V0X3hfMjAxNSA9IHhnYi5ETWF0cml4KGRhdGEgPSBhbGxfZGF0YXNldF8yMDE1LCBsYWJlbCA9IHZlY19sYWJlbF8yMDE1KQoKZnVsbF9jdl8yMDE1IDwtIHhnYm9vc3Q6OnhnYi5jdihwYXJhbXMgPSBsaXN0KG9iamVjdGl2ZSA9ICJtdWx0aTpzb2Z0cHJvYiIsIGV2YWxfbWV0cmljID0gYygibWxvZ2xvc3MiKSwgbnVtX2NsYXNzID0gNSksIGRhdGEgPSBmdWxsX2RhdGFzZXRfeF8yMDE1LCBucm91bmRzID0gMjUwMCwgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gMTAsIG5mb2xkPTEwLCBzdHJhdGlmaWVkID0gVCkKZnVsbF9tb2RfMjAxNSA8LSB4Z2Jvb3N0Ojp4Z2Jvb3N0KHBhcmFtcyA9IGxpc3Qob2JqZWN0aXZlID0gIm11bHRpOnNvZnRwcm9iIiwgZXZhbF9tZXRyaWMgPSBjKCJtbG9nbG9zcyIpLCBudW1fY2xhc3MgPSA1KSwgZGF0YSA9IGZ1bGxfZGF0YXNldF94XzIwMTUsIG5yb3VuZHMgPSBmdWxsX2N2XzIwMTUkYmVzdF9udHJlZWxpbWl0KQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CiMjIyAyMDE2CnZlY19sYWJlbF8yMDE2IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMTYkb3V0Y29tZV9lYwphbGxfZGF0YXNldF8yMDE2IDwtIGFzLm1hdHJpeChiYXR0ZWRfYmFsbF9tb2RlbF8yMDE2ICU+JSBkcGx5cjo6c2VsZWN0KGMoImxhdW5jaF9hbmdsZSIsICJsYXVuY2hfc3BlZWQiLCAic3ByYXlfYW5nbGUiLCAic3RhbmRfciIsICJwX3Rocm93c19yIiwgInRlbXBlcmF0dXJlIiwgImlzX2RvbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaXRjaF90eXBlX0NIOnZlbnVlX2JhdHRlci5zdGFuZF9ZYW5rZWVTdGFkaXVtX3IpKSkKZnVsbF9kYXRhc2V0X3hfMjAxNiA9IHhnYi5ETWF0cml4KGRhdGEgPSBhbGxfZGF0YXNldF8yMDE2LCBsYWJlbCA9IHZlY19sYWJlbF8yMDE2KQoKZnVsbF9jdl8yMDE2IDwtIHhnYm9vc3Q6OnhnYi5jdihwYXJhbXMgPSBsaXN0KG9iamVjdGl2ZSA9ICJtdWx0aTpzb2Z0cHJvYiIsIGV2YWxfbWV0cmljID0gYygibWxvZ2xvc3MiKSwgbnVtX2NsYXNzID0gNSksIGRhdGEgPSBmdWxsX2RhdGFzZXRfeF8yMDE2LCBucm91bmRzID0gMjUwMCwgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gMTAsIG5mb2xkPTEwLCBzdHJhdGlmaWVkID0gVCkKZnVsbF9tb2RfMjAxNiA8LSB4Z2Jvb3N0Ojp4Z2Jvb3N0KHBhcmFtcyA9IGxpc3Qob2JqZWN0aXZlID0gIm11bHRpOnNvZnRwcm9iIiwgZXZhbF9tZXRyaWMgPSBjKCJtbG9nbG9zcyIpLCBudW1fY2xhc3MgPSA1KSwgZGF0YSA9IGZ1bGxfZGF0YXNldF94XzIwMTYsIG5yb3VuZHMgPSBmdWxsX2N2XzIwMTYkYmVzdF9udHJlZWxpbWl0KQoKIyMjIDIwMTcKdmVjX2xhYmVsXzIwMTcgPC0gYmF0dGVkX2JhbGxfbW9kZWxfMjAxNyRvdXRjb21lX2VjCmFsbF9kYXRhc2V0XzIwMTcgPC0gYXMubWF0cml4KGJhdHRlZF9iYWxsX21vZGVsXzIwMTcgJT4lIGRwbHlyOjpzZWxlY3QoYygibGF1bmNoX2FuZ2xlIiwgImxhdW5jaF9zcGVlZCIsICJzcHJheV9hbmdsZSIsICJzdGFuZF9yIiwgInBfdGhyb3dzX3IiLCAidGVtcGVyYXR1cmUiLCAiaXNfZG9tZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpdGNoX3R5cGVfQ0g6dmVudWVfYmF0dGVyLnN0YW5kX1lhbmtlZVN0YWRpdW1fcikpKQpmdWxsX2RhdGFzZXRfeF8yMDE3ID0geGdiLkRNYXRyaXgoZGF0YSA9IGFsbF9kYXRhc2V0XzIwMTcsIGxhYmVsID0gdmVjX2xhYmVsXzIwMTcpCgpmdWxsX2N2XzIwMTcgPC0geGdib29zdDo6eGdiLmN2KHBhcmFtcyA9IGxpc3Qob2JqZWN0aXZlID0gIm11bHRpOnNvZnRwcm9iIiwgZXZhbF9tZXRyaWMgPSBjKCJtbG9nbG9zcyIpLCBudW1fY2xhc3MgPSA1KSwgZGF0YSA9IGZ1bGxfZGF0YXNldF94XzIwMTcsIG5yb3VuZHMgPSAyNTAwLCBlYXJseV9zdG9wcGluZ19yb3VuZHMgPSAxMCwgbmZvbGQ9MTAsIHN0cmF0aWZpZWQgPSBUKQpmdWxsX21vZF8yMDE3IDwtIHhnYm9vc3Q6OnhnYm9vc3QocGFyYW1zID0gbGlzdChvYmplY3RpdmUgPSAibXVsdGk6c29mdHByb2IiLCBldmFsX21ldHJpYyA9IGMoIm1sb2dsb3NzIiksIG51bV9jbGFzcyA9IDUpLCBkYXRhID0gZnVsbF9kYXRhc2V0X3hfMjAxNywgbnJvdW5kcyA9IGZ1bGxfY3ZfMjAxNyRiZXN0X250cmVlbGltaXQpCgojIyMgMjAxOAp2ZWNfbGFiZWxfMjAxOCA8LSBiYXR0ZWRfYmFsbF9tb2RlbF8yMDE4JG91dGNvbWVfZWMKYWxsX2RhdGFzZXRfMjAxOCA8LSBhcy5tYXRyaXgoYmF0dGVkX2JhbGxfbW9kZWxfMjAxOCAlPiUgZHBseXI6OnNlbGVjdChjKCJsYXVuY2hfYW5nbGUiLCAibGF1bmNoX3NwZWVkIiwgInNwcmF5X2FuZ2xlIiwgInN0YW5kX3IiLCAicF90aHJvd3NfciIsICJ0ZW1wZXJhdHVyZSIsICJpc19kb21lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGl0Y2hfdHlwZV9DSDp2ZW51ZV9iYXR0ZXIuc3RhbmRfWWFua2VlU3RhZGl1bV9yKSkpCmZ1bGxfZGF0YXNldF94XzIwMTggPSB4Z2IuRE1hdHJpeChkYXRhID0gYWxsX2RhdGFzZXRfMjAxOCwgbGFiZWwgPSB2ZWNfbGFiZWxfMjAxOCkKCmZ1bGxfY3ZfMjAxOCA8LSB4Z2Jvb3N0Ojp4Z2IuY3YocGFyYW1zID0gbGlzdChvYmplY3RpdmUgPSAibXVsdGk6c29mdHByb2IiLCBldmFsX21ldHJpYyA9IGMoIm1sb2dsb3NzIiksIG51bV9jbGFzcyA9IDUpLCBkYXRhID0gZnVsbF9kYXRhc2V0X3hfMjAxOCwgbnJvdW5kcyA9IDI1MDAsIGVhcmx5X3N0b3BwaW5nX3JvdW5kcyA9IDEwLCBuZm9sZD0xMCwgc3RyYXRpZmllZCA9IFQpCmZ1bGxfbW9kXzIwMTggPC0geGdib29zdDo6eGdib29zdChwYXJhbXMgPSBsaXN0KG9iamVjdGl2ZSA9ICJtdWx0aTpzb2Z0cHJvYiIsIGV2YWxfbWV0cmljID0gYygibWxvZ2xvc3MiKSwgbnVtX2NsYXNzID0gNSksIGRhdGEgPSBmdWxsX2RhdGFzZXRfeF8yMDE4LCBucm91bmRzID0gZnVsbF9jdl8yMDE4JGJlc3RfbnRyZWVsaW1pdCkKCiMjIyAyMDE5CnZlY19sYWJlbF8yMDE5IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMTkkb3V0Y29tZV9lYwphbGxfZGF0YXNldF8yMDE5IDwtIGFzLm1hdHJpeChiYXR0ZWRfYmFsbF9tb2RlbF8yMDE5ICU+JSBkcGx5cjo6c2VsZWN0KGMoImxhdW5jaF9hbmdsZSIsICJsYXVuY2hfc3BlZWQiLCAic3ByYXlfYW5nbGUiLCAic3RhbmRfciIsICJwX3Rocm93c19yIiwgInRlbXBlcmF0dXJlIiwgImlzX2RvbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaXRjaF90eXBlX0NIOnZlbnVlX2JhdHRlci5zdGFuZF9ZYW5rZWVTdGFkaXVtX3IpKSkKZnVsbF9kYXRhc2V0X3hfMjAxOSA9IHhnYi5ETWF0cml4KGRhdGEgPSBhbGxfZGF0YXNldF8yMDE5LCBsYWJlbCA9IHZlY19sYWJlbF8yMDE5KQoKZnVsbF9jdl8yMDE5IDwtIHhnYm9vc3Q6OnhnYi5jdihwYXJhbXMgPSBsaXN0KG9iamVjdGl2ZSA9ICJtdWx0aTpzb2Z0cHJvYiIsIGV2YWxfbWV0cmljID0gYygibWxvZ2xvc3MiKSwgbnVtX2NsYXNzID0gNSksIGRhdGEgPSBmdWxsX2RhdGFzZXRfeF8yMDE5LCBucm91bmRzID0gMjUwMCwgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gMTAsIG5mb2xkPTEwLCBzdHJhdGlmaWVkID0gVCkKZnVsbF9tb2RfMjAxOSA8LSB4Z2Jvb3N0Ojp4Z2Jvb3N0KHBhcmFtcyA9IGxpc3Qob2JqZWN0aXZlID0gIm11bHRpOnNvZnRwcm9iIiwgZXZhbF9tZXRyaWMgPSBjKCJtbG9nbG9zcyIpLCBudW1fY2xhc3MgPSA1KSwgZGF0YSA9IGZ1bGxfZGF0YXNldF94XzIwMTksIG5yb3VuZHMgPSBmdWxsX2N2XzIwMTkkYmVzdF9udHJlZWxpbWl0KQpgYGAKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmltcG9ydGFuY2VfZnVsbF9tb2RfMjAxOSA8LSB4Z2IuaW1wb3J0YW5jZShmZWF0dXJlX25hbWVzID0gY29sbmFtZXMoZnVsbF9tb2RfMjAxOSksIG1vZGVsID0gZnVsbF9tb2RfMjAxOSkKCmltcG9ydGFuY2VfcGxvdF9mdWxsX21vZF8yMDE5IDwtIHhnYi5nZ3Bsb3QuaW1wb3J0YW5jZShpbXBvcnRhbmNlX21hdHJpeCA9IGltcG9ydGFuY2VfZnVsbF9tb2RfMjAxOSkKCmdycF9pbXBfYmFzZSA8LSBpbXBvcnRhbmNlX2Z1bGxfbW9kXzIwMTkgJT4lCiAgbXV0YXRlKHpvbmUgPSBjYXNlX3doZW4oZ3JlcGwoInpvbmUiLCBGZWF0dXJlKSB+ICJ6b25lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk5vIikpICU+JQogIG11dGF0ZShwaXRjaF90eXBlID0gY2FzZV93aGVuKGdyZXBsKCJwaXRjaF90eXBlIiwgRmVhdHVyZSkgfiAicGl0Y2hfdHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJObyIpKSAlPiUKICBtdXRhdGUoYmF0dGVyX2lmX3NoaWZ0ID0gY2FzZV93aGVuKGdyZXBsKCJiYXR0ZXJfaWZfc2hpZnQiLCBGZWF0dXJlKSB+ICJiYXR0ZXJfaWZfc2hpZnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTm8iKSkgJT4lCiAgbXV0YXRlKGJhdHRlcl9vZl9zaGlmdCA9IGNhc2Vfd2hlbihncmVwbCgiYmF0dGVyX29mX3NoaWZ0IiwgRmVhdHVyZSkgfiAiYmF0dGVyX29mX3NoaWZ0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk5vIikpICU+JQogIG11dGF0ZShnYW1lX3llYXIgPSBjYXNlX3doZW4oZ3JlcGwoImdhbWVfeWVhciIsIEZlYXR1cmUpIH4gImdhbWVfeWVhciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJObyIpKSAlPiUKICBtdXRhdGUoY291bnQgPSBjYXNlX3doZW4oZ3JlcGwoImNvdW50IiwgRmVhdHVyZSkgfiAiY291bnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTm8iKSkgJT4lCiAgbXV0YXRlKHZlbnVlX2JhdHRlci5zdGFuZCA9IGNhc2Vfd2hlbihncmVwbCgidmVudWVfYmF0dGVyLnN0YW5kIiwgRmVhdHVyZSkgfiAidmVudWVfYmF0dGVyLnN0YW5kIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk5vIikpICU+JQogIG11dGF0ZShiYXR0ZXJfcGl0Y2hlcl9tYXRjaHVwID0gY2FzZV93aGVuKGdyZXBsKCJiYXR0ZXJfcGl0Y2hlcl9tYXRjaHVwIiwgRmVhdHVyZSkgfiAiYmF0dGVyX3BpdGNoZXJfbWF0Y2h1cCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJObyIpKQoKem9uZV9pbXAgPC0gZ3JwX2ltcF9iYXNlICU+JQogIGdyb3VwX2J5KHpvbmUpICU+JQogIGZpbHRlcih6b25lID09ICJ6b25lIikgJT4lCiAgc3VtbWFyaXNlKG5ld19nYWluID0gc3VtKEdhaW4pLCAKICAgICAgICAgICAgbmV3X2NvdmVyID0gc3VtKENvdmVyKSwKICAgICAgICAgICAgbmV3X2ZyZXF1ZW5jeSA9IHN1bShGcmVxdWVuY3kpLAogICAgICAgICAgICBuZXdfaW1wb3J0YW5jZSA9IHN1bShJbXBvcnRhbmNlKSkgJT4lCiAgcmVuYW1lKEZlYXR1cmUgPSB6b25lKQoKcGl0Y2hfdHlwZV9pbXAgPC0gZ3JwX2ltcF9iYXNlICU+JQogIGdyb3VwX2J5KHBpdGNoX3R5cGUpICU+JQogIGZpbHRlcihwaXRjaF90eXBlID09ICJwaXRjaF90eXBlIikgJT4lCiAgc3VtbWFyaXNlKG5ld19nYWluID0gc3VtKEdhaW4pLCAKICAgICAgICAgICAgbmV3X2NvdmVyID0gc3VtKENvdmVyKSwKICAgICAgICAgICAgbmV3X2ZyZXF1ZW5jeSA9IHN1bShGcmVxdWVuY3kpLAogICAgICAgICAgICBuZXdfaW1wb3J0YW5jZSA9IHN1bShJbXBvcnRhbmNlKSkgJT4lCiAgcmVuYW1lKEZlYXR1cmUgPSBwaXRjaF90eXBlKQoKYmF0dGVyX2lmX3NoaWZ0X2ltcCA8LSBncnBfaW1wX2Jhc2UgJT4lCiAgZ3JvdXBfYnkoYmF0dGVyX2lmX3NoaWZ0KSAlPiUKICBmaWx0ZXIoYmF0dGVyX2lmX3NoaWZ0ID09ICJiYXR0ZXJfaWZfc2hpZnQiKSAlPiUKICBzdW1tYXJpc2UobmV3X2dhaW4gPSBzdW0oR2FpbiksIAogICAgICAgICAgICBuZXdfY292ZXIgPSBzdW0oQ292ZXIpLAogICAgICAgICAgICBuZXdfZnJlcXVlbmN5ID0gc3VtKEZyZXF1ZW5jeSksCiAgICAgICAgICAgIG5ld19pbXBvcnRhbmNlID0gc3VtKEltcG9ydGFuY2UpKSAlPiUKICByZW5hbWUoRmVhdHVyZSA9IGJhdHRlcl9pZl9zaGlmdCkKCmJhdHRlcl9vZl9zaGlmdF9pbXAgPC0gZ3JwX2ltcF9iYXNlICU+JQogIGdyb3VwX2J5KGJhdHRlcl9vZl9zaGlmdCkgJT4lCiAgZmlsdGVyKGJhdHRlcl9vZl9zaGlmdCA9PSAiYmF0dGVyX29mX3NoaWZ0IikgJT4lCiAgc3VtbWFyaXNlKG5ld19nYWluID0gc3VtKEdhaW4pLCAKICAgICAgICAgICAgbmV3X2NvdmVyID0gc3VtKENvdmVyKSwKICAgICAgICAgICAgbmV3X2ZyZXF1ZW5jeSA9IHN1bShGcmVxdWVuY3kpLAogICAgICAgICAgICBuZXdfaW1wb3J0YW5jZSA9IHN1bShJbXBvcnRhbmNlKSkgJT4lCiAgcmVuYW1lKEZlYXR1cmUgPSBiYXR0ZXJfb2Zfc2hpZnQpCgpnYW1lX3llYXJfaW1wIDwtIGdycF9pbXBfYmFzZSAlPiUKICBncm91cF9ieShnYW1lX3llYXIpICU+JQogIGZpbHRlcihnYW1lX3llYXIgPT0gImdhbWVfeWVhciIpICU+JQogIHN1bW1hcmlzZShuZXdfZ2FpbiA9IHN1bShHYWluKSwgCiAgICAgICAgICAgIG5ld19jb3ZlciA9IHN1bShDb3ZlciksCiAgICAgICAgICAgIG5ld19mcmVxdWVuY3kgPSBzdW0oRnJlcXVlbmN5KSwKICAgICAgICAgICAgbmV3X2ltcG9ydGFuY2UgPSBzdW0oSW1wb3J0YW5jZSkpICU+JQogIHJlbmFtZShGZWF0dXJlID0gZ2FtZV95ZWFyKQoKY291bnRfaW1wIDwtIGdycF9pbXBfYmFzZSAlPiUKICBncm91cF9ieShjb3VudCkgJT4lCiAgZmlsdGVyKGNvdW50ID09ICJjb3VudCIpICU+JQogIHN1bW1hcmlzZShuZXdfZ2FpbiA9IHN1bShHYWluKSwgCiAgICAgICAgICAgIG5ld19jb3ZlciA9IHN1bShDb3ZlciksCiAgICAgICAgICAgIG5ld19mcmVxdWVuY3kgPSBzdW0oRnJlcXVlbmN5KSwKICAgICAgICAgICAgbmV3X2ltcG9ydGFuY2UgPSBzdW0oSW1wb3J0YW5jZSkpICU+JQogIHJlbmFtZShGZWF0dXJlID0gY291bnQpCgp2ZW51ZV9iYXR0ZXIuc3RhbmRfaW1wIDwtIGdycF9pbXBfYmFzZSAlPiUKICBncm91cF9ieSh2ZW51ZV9iYXR0ZXIuc3RhbmQpICU+JQogIGZpbHRlcih2ZW51ZV9iYXR0ZXIuc3RhbmQgPT0gInZlbnVlX2JhdHRlci5zdGFuZCIpICU+JQogIHN1bW1hcmlzZShuZXdfZ2FpbiA9IHN1bShHYWluKSwgCiAgICAgICAgICAgIG5ld19jb3ZlciA9IHN1bShDb3ZlciksCiAgICAgICAgICAgIG5ld19mcmVxdWVuY3kgPSBzdW0oRnJlcXVlbmN5KSwKICAgICAgICAgICAgbmV3X2ltcG9ydGFuY2UgPSBzdW0oSW1wb3J0YW5jZSkpICU+JQogIHJlbmFtZShGZWF0dXJlID0gdmVudWVfYmF0dGVyLnN0YW5kKQoKYmF0dGVyX3BpdGNoZXJfbWF0Y2h1cF9pbXAgPC0gZ3JwX2ltcF9iYXNlICU+JQogIGdyb3VwX2J5KGJhdHRlcl9waXRjaGVyX21hdGNodXApICU+JQogIGZpbHRlcihiYXR0ZXJfcGl0Y2hlcl9tYXRjaHVwID09ICJiYXR0ZXJfcGl0Y2hlcl9tYXRjaHVwIikgJT4lCiAgc3VtbWFyaXNlKG5ld19nYWluID0gc3VtKEdhaW4pLCAKICAgICAgICAgICAgbmV3X2NvdmVyID0gc3VtKENvdmVyKSwKICAgICAgICAgICAgbmV3X2ZyZXF1ZW5jeSA9IHN1bShGcmVxdWVuY3kpLAogICAgICAgICAgICBuZXdfaW1wb3J0YW5jZSA9IHN1bShJbXBvcnRhbmNlKSkgJT4lCiAgcmVuYW1lKEZlYXR1cmUgPSBiYXR0ZXJfcGl0Y2hlcl9tYXRjaHVwKQoKbmV3X2ltcCA8LSByYmluZCh6b25lX2ltcCwgcGl0Y2hfdHlwZV9pbXAsIGJhdHRlcl9pZl9zaGlmdF9pbXAsIGJhdHRlcl9vZl9zaGlmdF9pbXAsIGdhbWVfeWVhcl9pbXAsIGNvdW50X2ltcCwgdmVudWVfYmF0dGVyLnN0YW5kX2ltcCwgCiAgICAgICAgICAgICAgICAgYmF0dGVyX3BpdGNoZXJfbWF0Y2h1cF9pbXApCgpuZXdfaW1wIDwtIHJlbmFtZShuZXdfaW1wLCBHYWluID0gbmV3X2dhaW4sIENvdmVyID0gbmV3X2NvdmVyLCBGcmVxdWVuY3kgPSBuZXdfZnJlcXVlbmN5LCBJbXBvcnRhbmNlID0gbmV3X2ltcG9ydGFuY2UpCgpub25fZHVtbWllcyA8LSBpbXBvcnRhbmNlX2Jhc2VfbW9kXzIwMTkgJT4lCiAgZmlsdGVyKEZlYXR1cmUgPT0gImxhdW5jaF9hbmdsZSIgfCBGZWF0dXJlID09ICJsYXVuY2hfc3BlZWQiIHwgRmVhdHVyZSA9PSAic3ByYXlfYW5nbGUiIHwgRmVhdHVyZSA9PSAic3RhbmRfciIgfCBGZWF0dXJlID09ICJ0ZW1wZXJhdHVyZSIgfCAKICAgICAgICAgICBGZWF0dXJlID09ICJwX3Rocm93c19yIiB8IEZlYXR1cmUgPT0gImlzX2RvbWUiKQoKYWxsX2dycF9pbXBvcnRhbmNlIDwtIHJiaW5kKG5vbl9kdW1taWVzLCBuZXdfaW1wKQoKZ3JwX2ltcG9ydGFuY2VfcGxvdF9mdWxsX21vZF8yMDE5IDwtIHhnYi5nZ3Bsb3QuaW1wb3J0YW5jZShpbXBvcnRhbmNlX21hdHJpeCA9IGFsbF9ncnBfaW1wb3J0YW5jZSkKYGBgCgpIZXJlIGFyZSB0aGUgZmVhdHVyZSBpbXBvcnRhbmNlIHBsb3RzIGZvciBlYWNoIG1vZGVsLiBUaGUgcmVzdWx0cyBhcmUgd2hhdCB0byBiZSBleHBlY3RlZDogbGF1bmNoIGFubGUsIGV4aXQgc3BlZWQsIGFuZCBzcHJheSBhbmdsZSBhcmUgdGhlIHRocmVlIG1vc3QgaW1wb3J0YW50IHZhcmlhYmxlcyB0aGF0IGdvIGludG8gY2xhc3NpZnlpbmcgdGhlIG91dGNvbWUgb2YgYSBiYXR0ZWQgYmFsbC4gV2hhdCBzdXJwcmlzZWQgbWUgd2FzIGhvdyBpbmZsdWVudGlhbCB0aGUgaW5maWVsZCBzaGlmdCBmZWF0dXJlIHdhcy4gRmVhdHVyZSBlbmdpbmVlcmluZyBpcyBpbmNyZWRpYmx5IGJlbmVmaWNhbCB0byBtb2RlbGluZy4gCmBgYHtyfQpmaW5hbF8yMDE1IDwtIGdycF9pbXBvcnRhbmNlX3Bsb3RfZnVsbF9tb2RfMjAxNSArIGdndGl0bGUoIkZlYXR1cmUgSW1wb3J0YW5jZSAtIDIwMTUgTW9kZWwiKQoKZmluYWxfMjAxNiA8LSBncnBfaW1wb3J0YW5jZV9wbG90X2Z1bGxfbW9kXzIwMTYgKyBnZ3RpdGxlKCJGZWF0dXJlIEltcG9ydGFuY2UgLSAyMDE2IE1vZGVsIikKCmZpbmFsXzIwMTcgPC0gZ3JwX2ltcG9ydGFuY2VfcGxvdF9mdWxsX21vZF8yMDE3ICsgZ2d0aXRsZSgiRmVhdHVyZSBJbXBvcnRhbmNlIC0gMjAxNyBNb2RlbCIpCgpmaW5hbF8yMDE4IDwtIGdycF9pbXBvcnRhbmNlX3Bsb3RfZnVsbF9tb2RfMjAxOCArIGdndGl0bGUoIkZlYXR1cmUgSW1wb3J0YW5jZSAtIDIwMTggTW9kZWwiKQoKZmluYWxfMjAxOSA8LSBncnBfaW1wb3J0YW5jZV9wbG90X2Z1bGxfbW9kXzIwMTkgKyBnZ3RpdGxlKCJGZWF0dXJlIEltcG9ydGFuY2UgLSAyMDE5IE1vZGVsIikKCiMoZmluYWxfMjAxNSArIGZpbmFsXzIwMTYgKyBmaW5hbF8yMDE3KSAvIChmaW5hbF8yMDE4ICsgZmluYWxfMjAxOSkKCmZpbmFsXzIwMTUgCmZpbmFsXzIwMTYKZmluYWxfMjAxNwpmaW5hbF8yMDE4CmZpbmFsXzIwMTkKYGBgCgpOb3csIEknbSBnb2luZyB0byBjb21wdXRlIHRoZSBhY2N1cmFjeSBvZiB0aGUgbW9kZWxzIHRoYXQgd2VyZSB0cmFpbmVkIG9uIHRoZSBlbnRpcmUgZGF0YXNldC4gVGhleSB0dXJuZWQgb3V0IGdyZWF0OyByYW5naW5nIGZyb20gODUuMjUlIHRvIDg2LjI1JS4gCmBgYHtyfQojIyMjIyMgMjAxNQp4Z2IuZnVsbF9wcmVkXzIwMTUgPSBwcmVkaWN0KGZ1bGxfbW9kXzIwMTUsIGZ1bGxfZGF0YXNldF94XzIwMTUsIHJlc2hhcGU9VCkKeGdiLmZ1bGxfcHJlZF8yMDE1ID0gYXMuZGF0YS5mcmFtZSh4Z2IuZnVsbF9wcmVkXzIwMTUpCmNvbG5hbWVzKHhnYi5mdWxsX3ByZWRfMjAxNSkgPSBjKCJPdXQiLCAiU2luZ2xlIiwgIkRvdWJsZSIsICJUcmlwbGUiLCAiSG9tZV9SdW4iKQoKcHJlZHNfZnVsbF8yMDE1IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMTUKcHJlZHNfZnVsbF8yMDE1JG91dC5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxNVssMV0KcHJlZHNfZnVsbF8yMDE1JHNpbmdsZS5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxNVssMl0KcHJlZHNfZnVsbF8yMDE1JGRvdWJsZS5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxNVssM10KcHJlZHNfZnVsbF8yMDE1JHRyaXBsZS5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxNVssNF0KcHJlZHNfZnVsbF8yMDE1JGhyLnByb2IgPC0geGdiLmZ1bGxfcHJlZF8yMDE1Wyw1XQoKbWF4X3Byb2JfZnVsbF8yMDE1IDwtIGNvbG5hbWVzKHhnYi5mdWxsX3ByZWRfMjAxNSlbYXBwbHkoeGdiLmZ1bGxfcHJlZF8yMDE1LDEsd2hpY2gubWF4KV0KCnByZWRzX2Z1bGxfMjAxNSRtYXgucHJvYiA8LSBtYXhfcHJvYl9mdWxsXzIwMTUKCnByZWRzX2Z1bGxfMjAxNSRwcmVkLnJpZ2h0IDwtIGlmZWxzZShwcmVkc19mdWxsXzIwMTUkbWF4LnByb2IgPT0gIk91dCIgJiBwcmVkc19mdWxsXzIwMTUkb3V0Y29tZV9lYyA9PSAwLCAieWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Z1bGxfMjAxNSRtYXgucHJvYiA9PSAiU2luZ2xlIiAmIHByZWRzX2Z1bGxfMjAxNSRvdXRjb21lX2VjID09IDEsICJ5ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfZnVsbF8yMDE1JG1heC5wcm9iID09ICJEb3VibGUiICYgcHJlZHNfZnVsbF8yMDE1JG91dGNvbWVfZWMgPT0gMiwgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfZnVsbF8yMDE1JG1heC5wcm9iID09ICJUcmlwbGUiICYgcHJlZHNfZnVsbF8yMDE1JG91dGNvbWVfZWMgPT0gMywgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Z1bGxfMjAxNSRtYXgucHJvYiA9PSAiSG9tZV9SdW4iICYgcHJlZHNfZnVsbF8yMDE1JG91dGNvbWVfZWMgPT0gNCwgInllcyIsICJubyIpKSkpKQpwcmVkc19mdWxsXzIwMTUkcHJlZC5yaWdodCA8LSBhcy5mYWN0b3IocHJlZHNfZnVsbF8yMDE1JHByZWQucmlnaHQpCgpzdW0ocHJlZHNfZnVsbF8yMDE1JHByZWQucmlnaHQgPT0gInllcyIpIC8gbnJvdyhwcmVkc19mdWxsXzIwMTUpICMwLjg1NDQ5NjgKYGBgCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQojIyMjIyMgMjAxNgp4Z2IuZnVsbF9wcmVkXzIwMTYgPSBwcmVkaWN0KGZ1bGxfbW9kXzIwMTYsIGZ1bGxfZGF0YXNldF94XzIwMTYsIHJlc2hhcGU9VCkKeGdiLmZ1bGxfcHJlZF8yMDE2ID0gYXMuZGF0YS5mcmFtZSh4Z2IuZnVsbF9wcmVkXzIwMTYpCmNvbG5hbWVzKHhnYi5mdWxsX3ByZWRfMjAxNikgPSBjKCJPdXQiLCAiU2luZ2xlIiwgIkRvdWJsZSIsICJUcmlwbGUiLCAiSG9tZV9SdW4iKQoKcHJlZHNfZnVsbF8yMDE2IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMTYKcHJlZHNfZnVsbF8yMDE2JG91dC5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxNlssMV0KcHJlZHNfZnVsbF8yMDE2JHNpbmdsZS5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxNlssMl0KcHJlZHNfZnVsbF8yMDE2JGRvdWJsZS5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxNlssM10KcHJlZHNfZnVsbF8yMDE2JHRyaXBsZS5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxNlssNF0KcHJlZHNfZnVsbF8yMDE2JGhyLnByb2IgPC0geGdiLmZ1bGxfcHJlZF8yMDE2Wyw1XQoKbWF4X3Byb2JfZnVsbF8yMDE2IDwtIGNvbG5hbWVzKHhnYi5mdWxsX3ByZWRfMjAxNilbYXBwbHkoeGdiLmZ1bGxfcHJlZF8yMDE2LDEsd2hpY2gubWF4KV0KCnByZWRzX2Z1bGxfMjAxNiRtYXgucHJvYiA8LSBtYXhfcHJvYl9mdWxsXzIwMTYKCnByZWRzX2Z1bGxfMjAxNiRwcmVkLnJpZ2h0IDwtIGlmZWxzZShwcmVkc19mdWxsXzIwMTYkbWF4LnByb2IgPT0gIk91dCIgJiBwcmVkc19mdWxsXzIwMTYkb3V0Y29tZV9lYyA9PSAwLCAieWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Z1bGxfMjAxNiRtYXgucHJvYiA9PSAiU2luZ2xlIiAmIHByZWRzX2Z1bGxfMjAxNiRvdXRjb21lX2VjID09IDEsICJ5ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfZnVsbF8yMDE2JG1heC5wcm9iID09ICJEb3VibGUiICYgcHJlZHNfZnVsbF8yMDE2JG91dGNvbWVfZWMgPT0gMiwgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfZnVsbF8yMDE2JG1heC5wcm9iID09ICJUcmlwbGUiICYgcHJlZHNfZnVsbF8yMDE2JG91dGNvbWVfZWMgPT0gMywgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Z1bGxfMjAxNiRtYXgucHJvYiA9PSAiSG9tZV9SdW4iICYgcHJlZHNfZnVsbF8yMDE2JG91dGNvbWVfZWMgPT0gNCwgInllcyIsICJubyIpKSkpKQpwcmVkc19mdWxsXzIwMTYkcHJlZC5yaWdodCA8LSBhcy5mYWN0b3IocHJlZHNfZnVsbF8yMDE2JHByZWQucmlnaHQpCgpzdW0ocHJlZHNfZnVsbF8yMDE2JHByZWQucmlnaHQgPT0gInllcyIpIC8gbnJvdyhwcmVkc19mdWxsXzIwMTYpICMwLjg1MjQ2OQoKIyMjIyMjIDIwMTcKeGdiLmZ1bGxfcHJlZF8yMDE3ID0gcHJlZGljdChmdWxsX21vZF8yMDE3LCBmdWxsX2RhdGFzZXRfeF8yMDE3LCByZXNoYXBlPVQpCnhnYi5mdWxsX3ByZWRfMjAxNyA9IGFzLmRhdGEuZnJhbWUoeGdiLmZ1bGxfcHJlZF8yMDE3KQpjb2xuYW1lcyh4Z2IuZnVsbF9wcmVkXzIwMTcpID0gYygiT3V0IiwgIlNpbmdsZSIsICJEb3VibGUiLCAiVHJpcGxlIiwgIkhvbWVfUnVuIikKCnByZWRzX2Z1bGxfMjAxNyA8LSBiYXR0ZWRfYmFsbF9tb2RlbF8yMDE3CnByZWRzX2Z1bGxfMjAxNyRvdXQucHJvYiA8LSB4Z2IuZnVsbF9wcmVkXzIwMTdbLDFdCnByZWRzX2Z1bGxfMjAxNyRzaW5nbGUucHJvYiA8LSB4Z2IuZnVsbF9wcmVkXzIwMTdbLDJdCnByZWRzX2Z1bGxfMjAxNyRkb3VibGUucHJvYiA8LSB4Z2IuZnVsbF9wcmVkXzIwMTdbLDNdCnByZWRzX2Z1bGxfMjAxNyR0cmlwbGUucHJvYiA8LSB4Z2IuZnVsbF9wcmVkXzIwMTdbLDRdCnByZWRzX2Z1bGxfMjAxNyRoci5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxN1ssNV0KCm1heF9wcm9iX2Z1bGxfMjAxNyA8LSBjb2xuYW1lcyh4Z2IuZnVsbF9wcmVkXzIwMTcpW2FwcGx5KHhnYi5mdWxsX3ByZWRfMjAxNywxLHdoaWNoLm1heCldCgpwcmVkc19mdWxsXzIwMTckbWF4LnByb2IgPC0gbWF4X3Byb2JfZnVsbF8yMDE3CgpwcmVkc19mdWxsXzIwMTckcHJlZC5yaWdodCA8LSBpZmVsc2UocHJlZHNfZnVsbF8yMDE3JG1heC5wcm9iID09ICJPdXQiICYgcHJlZHNfZnVsbF8yMDE3JG91dGNvbWVfZWMgPT0gMCwgInllcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19mdWxsXzIwMTckbWF4LnByb2IgPT0gIlNpbmdsZSIgJiBwcmVkc19mdWxsXzIwMTckb3V0Y29tZV9lYyA9PSAxLCAieWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Z1bGxfMjAxNyRtYXgucHJvYiA9PSAiRG91YmxlIiAmIHByZWRzX2Z1bGxfMjAxNyRvdXRjb21lX2VjID09IDIsICJ5ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Z1bGxfMjAxNyRtYXgucHJvYiA9PSAiVHJpcGxlIiAmIHByZWRzX2Z1bGxfMjAxNyRvdXRjb21lX2VjID09IDMsICJ5ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19mdWxsXzIwMTckbWF4LnByb2IgPT0gIkhvbWVfUnVuIiAmIHByZWRzX2Z1bGxfMjAxNyRvdXRjb21lX2VjID09IDQsICJ5ZXMiLCAibm8iKSkpKSkKcHJlZHNfZnVsbF8yMDE3JHByZWQucmlnaHQgPC0gYXMuZmFjdG9yKHByZWRzX2Z1bGxfMjAxNyRwcmVkLnJpZ2h0KQoKc3VtKHByZWRzX2Z1bGxfMjAxNyRwcmVkLnJpZ2h0ID09ICJ5ZXMiKSAvIG5yb3cocHJlZHNfZnVsbF8yMDE3KSAjMC44NjA2MTI1CgojIyMjIyMgMjAxOAp4Z2IuZnVsbF9wcmVkXzIwMTggPSBwcmVkaWN0KGZ1bGxfbW9kXzIwMTgsIGZ1bGxfZGF0YXNldF94XzIwMTgsIHJlc2hhcGU9VCkKeGdiLmZ1bGxfcHJlZF8yMDE4ID0gYXMuZGF0YS5mcmFtZSh4Z2IuZnVsbF9wcmVkXzIwMTgpCmNvbG5hbWVzKHhnYi5mdWxsX3ByZWRfMjAxOCkgPSBjKCJPdXQiLCAiU2luZ2xlIiwgIkRvdWJsZSIsICJUcmlwbGUiLCAiSG9tZV9SdW4iKQoKcHJlZHNfZnVsbF8yMDE4IDwtIGJhdHRlZF9iYWxsX21vZGVsXzIwMTgKcHJlZHNfZnVsbF8yMDE4JG91dC5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxOFssMV0KcHJlZHNfZnVsbF8yMDE4JHNpbmdsZS5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxOFssMl0KcHJlZHNfZnVsbF8yMDE4JGRvdWJsZS5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxOFssM10KcHJlZHNfZnVsbF8yMDE4JHRyaXBsZS5wcm9iIDwtIHhnYi5mdWxsX3ByZWRfMjAxOFssNF0KcHJlZHNfZnVsbF8yMDE4JGhyLnByb2IgPC0geGdiLmZ1bGxfcHJlZF8yMDE4Wyw1XQoKbWF4X3Byb2JfZnVsbF8yMDE4IDwtIGNvbG5hbWVzKHhnYi5mdWxsX3ByZWRfMjAxOClbYXBwbHkoeGdiLmZ1bGxfcHJlZF8yMDE4LDEsd2hpY2gubWF4KV0KCnByZWRzX2Z1bGxfMjAxOCRtYXgucHJvYiA8LSBtYXhfcHJvYl9mdWxsXzIwMTgKCnByZWRzX2Z1bGxfMjAxOCRwcmVkLnJpZ2h0IDwtIGlmZWxzZShwcmVkc19mdWxsXzIwMTgkbWF4LnByb2IgPT0gIk91dCIgJiBwcmVkc19mdWxsXzIwMTgkb3V0Y29tZV9lYyA9PSAwLCAieWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Z1bGxfMjAxOCRtYXgucHJvYiA9PSAiU2luZ2xlIiAmIHByZWRzX2Z1bGxfMjAxOCRvdXRjb21lX2VjID09IDEsICJ5ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfZnVsbF8yMDE4JG1heC5wcm9iID09ICJEb3VibGUiICYgcHJlZHNfZnVsbF8yMDE4JG91dGNvbWVfZWMgPT0gMiwgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfZnVsbF8yMDE4JG1heC5wcm9iID09ICJUcmlwbGUiICYgcHJlZHNfZnVsbF8yMDE4JG91dGNvbWVfZWMgPT0gMywgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHByZWRzX2Z1bGxfMjAxOCRtYXgucHJvYiA9PSAiSG9tZV9SdW4iICYgcHJlZHNfZnVsbF8yMDE4JG91dGNvbWVfZWMgPT0gNCwgInllcyIsICJubyIpKSkpKQpwcmVkc19mdWxsXzIwMTgkcHJlZC5yaWdodCA8LSBhcy5mYWN0b3IocHJlZHNfZnVsbF8yMDE4JHByZWQucmlnaHQpCgpzdW0ocHJlZHNfZnVsbF8yMDE4JHByZWQucmlnaHQgPT0gInllcyIpIC8gbnJvdyhwcmVkc19mdWxsXzIwMTgpICMwLjg1NjI3MTMKCiMjIyMjIyAyMDE5CnhnYi5mdWxsX3ByZWRfMjAxOSA9IHByZWRpY3QoZnVsbF9tb2RfMjAxOSwgZnVsbF9kYXRhc2V0X3hfMjAxOSwgcmVzaGFwZT1UKQp4Z2IuZnVsbF9wcmVkXzIwMTkgPSBhcy5kYXRhLmZyYW1lKHhnYi5mdWxsX3ByZWRfMjAxOSkKY29sbmFtZXMoeGdiLmZ1bGxfcHJlZF8yMDE5KSA9IGMoIk91dCIsICJTaW5nbGUiLCAiRG91YmxlIiwgIlRyaXBsZSIsICJIb21lX1J1biIpCgpwcmVkc19mdWxsXzIwMTkgPC0gYmF0dGVkX2JhbGxfbW9kZWxfMjAxOQpwcmVkc19mdWxsXzIwMTkkb3V0LnByb2IgPC0geGdiLmZ1bGxfcHJlZF8yMDE5WywxXQpwcmVkc19mdWxsXzIwMTkkc2luZ2xlLnByb2IgPC0geGdiLmZ1bGxfcHJlZF8yMDE5WywyXQpwcmVkc19mdWxsXzIwMTkkZG91YmxlLnByb2IgPC0geGdiLmZ1bGxfcHJlZF8yMDE5WywzXQpwcmVkc19mdWxsXzIwMTkkdHJpcGxlLnByb2IgPC0geGdiLmZ1bGxfcHJlZF8yMDE5Wyw0XQpwcmVkc19mdWxsXzIwMTkkaHIucHJvYiA8LSB4Z2IuZnVsbF9wcmVkXzIwMTlbLDVdCgptYXhfcHJvYl9mdWxsXzIwMTkgPC0gY29sbmFtZXMoeGdiLmZ1bGxfcHJlZF8yMDE5KVthcHBseSh4Z2IuZnVsbF9wcmVkXzIwMTksMSx3aGljaC5tYXgpXQoKcHJlZHNfZnVsbF8yMDE5JG1heC5wcm9iIDwtIG1heF9wcm9iX2Z1bGxfMjAxOQoKcHJlZHNfZnVsbF8yMDE5JHByZWQucmlnaHQgPC0gaWZlbHNlKHByZWRzX2Z1bGxfMjAxOSRtYXgucHJvYiA9PSAiT3V0IiAmIHByZWRzX2Z1bGxfMjAxOSRvdXRjb21lX2VjID09IDAsICJ5ZXMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfZnVsbF8yMDE5JG1heC5wcm9iID09ICJTaW5nbGUiICYgcHJlZHNfZnVsbF8yMDE5JG91dGNvbWVfZWMgPT0gMSwgInllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19mdWxsXzIwMTkkbWF4LnByb2IgPT0gIkRvdWJsZSIgJiBwcmVkc19mdWxsXzIwMTkkb3V0Y29tZV9lYyA9PSAyLCAieWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwcmVkc19mdWxsXzIwMTkkbWF4LnByb2IgPT0gIlRyaXBsZSIgJiBwcmVkc19mdWxsXzIwMTkkb3V0Y29tZV9lYyA9PSAzLCAieWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocHJlZHNfZnVsbF8yMDE5JG1heC5wcm9iID09ICJIb21lX1J1biIgJiBwcmVkc19mdWxsXzIwMTkkb3V0Y29tZV9lYyA9PSA0LCAieWVzIiwgIm5vIikpKSkpCnByZWRzX2Z1bGxfMjAxOSRwcmVkLnJpZ2h0IDwtIGFzLmZhY3RvcihwcmVkc19mdWxsXzIwMTkkcHJlZC5yaWdodCkKCnN1bShwcmVkc19mdWxsXzIwMTkkcHJlZC5yaWdodCA9PSAieWVzIikgLyBucm93KHByZWRzX2Z1bGxfMjAxOSkgIzAuODYyNDU5CmBgYAoKClRoaXMgaXMgd2hlcmUgaXQgZ2V0cyBmdW4uIExpa2UgSSBtZW50aW9uZWQgaW4gdGhlIG9wZW5pbmcsIEknbSBnb2luZyB0byBmb2xsb3cgYSBzaW1pbGFyIHdvcmtmbG93IHRvIHdoYXQgQmFzZWJhbGwgUHJvc3BlY3R1cyB1c2VkIGZvciBEUkMrLiBUaGUgZ2VuZXJhbGl6ZWQgbGluZWFyIG1peGVkLWVmZmVjdHMgbW9kZWxzIGltcHJvdmVkIHRoZSBhY2NydWFjeSBvZiBlYWNoIG1vZGVsLCBvaCBzbyBzbGlnaHRseSwgd2l0aCBpbmNyZWFzZXMgYmV0d2VlbiAwLjAwMiBhbmQgMC4wMDQgcGVyY2VudC4gV2hpbGUgdGhlIGFjY3VyYWN5IGhhcmRseSBpbmNyZWFzZWQsIEkgdGhpbmsgdGhlIG1vZGVsIGlzIG11Y2ggYmV0dGVyIG9mZiB3aXRoIGluY2x1ZGluZyB0aGUgYmF0dGVyIGFuZCBwaXRjaGVyIGlkZW50aXR5LiBJdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgdGhlcmUgYXJlICdubyBmcmVlIGx1bmNoZXMuJyBUaGUgZ2VuZXJhbGl6ZWQgbGluZWFyIG1peGVkLWVmZmVjdHMgbW9kZWwgZm9yIHRoZSAyMDE1IHNlYXNvbiBpbmNyZWFzZWQgdHJpcGxlIGNsYXNzaWZjYXRpb24gYWNjdXJhY3kgZnJvbSAyMC43NyUgKFhHQm9vc3QgbW9kZWwpIHRvIDYxLjU0JSBhbmQgaW5jcmVhc2VkIGRvdWJsZSBhY2N1cmFjeSBmcm9tIDU5LjM3JSB0byA2OSUuIEJ1dCBvdXQgY2xhc3NpZmljYXRpb24gYWNjdXJhY3kgZGVjbGluZWQgZnJvbSA5My4xNCUgdG8gOTElLiBJbiBhIHBlcmZlY3Qgd29ybGQsIGFsbCBhY2N1cmFyaWVzIHdvdWxkIGluY3JlYXNlIGluIHRoZSBuZXcgbW9kZWwsIGJ1dCB0aGF0J3Mgbm90IGhvdyB0aGluZ3Mgd29yayB1bmZvcnR1bmF0ZWx5LiBVbHRpbWF0ZWx5LCBJIGRvIHRoaW5rIHRoZSB0cmFkZS1vZmYgaXMgd29ydGggaXQuCmBgYHtyfQpkZi5zaW5nbGUgPC0gcHJlZHNfZnVsbF8yMDE1ICU+JQogIGZpbHRlcihvdXRjb21lX2VjID09IDAgfCBvdXRjb21lX2VjID09IDEpICU+JQogIG11dGF0ZShvdXRjb21lID0gaWZlbHNlKG91dGNvbWVfZWMgPT0gMCwgMCwgMSkpCmRmLmRvdWJsZSA8LSBwcmVkc19mdWxsXzIwMTUgJT4lCiAgZmlsdGVyKG91dGNvbWVfZWMgPT0gMCB8IG91dGNvbWVfZWMgPT0gMikgJT4lCiAgbXV0YXRlKG91dGNvbWUgPSBpZmVsc2Uob3V0Y29tZV9lYyA9PSAwLCAwLCAxKSkKZGYudHJpcGxlIDwtIHByZWRzX2Z1bGxfMjAxNSAlPiUKICBmaWx0ZXIob3V0Y29tZV9lYyA9PSAwIHwgb3V0Y29tZV9lYyA9PSAzKSAlPiUKICBtdXRhdGUob3V0Y29tZSA9IGlmZWxzZShvdXRjb21lX2VjID09IDAsIDAsIDEpKQpkZi5ob21lX3J1biA8LSBwcmVkc19mdWxsXzIwMTUgJT4lCiAgZmlsdGVyKG91dGNvbWVfZWMgPT0gMCB8IG91dGNvbWVfZWMgPT0gNCkgJT4lCiAgbXV0YXRlKG91dGNvbWUgPSBpZmVsc2Uob3V0Y29tZV9lYyA9PSAwLCAwLCAxKSkKCmdsbWVyLnNpbmdsZS5tb2QuMjAxNSA8LSBnbG1lcigKICBvdXRjb21lIH4KICAgICgxfHBpdGNoZXJfbmFtZSkgKwogICAgKDF8cGxheWVyX25hbWUpICsKICAgIGxvZ2l0KG91dC5wcm9iKSArIGxvZ2l0KHNpbmdsZS5wcm9iKSArIGxvZ2l0KGRvdWJsZS5wcm9iKSArIGxvZ2l0KHRyaXBsZS5wcm9iKSArIGxvZ2l0KGhyLnByb2IpLAogIGRhdGE9ZGYuc2luZ2xlLAogIGZhbWlseT1iaW5vbWlhbChsaW5rID0gInByb2JpdCIpLAogIG5BR1E9MCkKZ2xtZXIuZG91YmxlLm1vZC4yMDE1IDwtIGdsbWVyKAogIG91dGNvbWUgfgogICAgKDF8cGl0Y2hlcl9uYW1lKSArCiAgICAoMXxwbGF5ZXJfbmFtZSkgKyAgICAgCiAgICAgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi5kb3VibGUsCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQpnbG1lci50cmlwbGUubW9kLjIwMTUgPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsKICAgICgxfHBsYXllcl9uYW1lKSArCiAgICAgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi50cmlwbGUsCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQpnbG1lci5ob21lX3J1bi5tb2QuMjAxNSA8LSBnbG1lcigKICBvdXRjb21lIH4KICAgICgxfHBpdGNoZXJfbmFtZSkgKwogICAgKDF8cGxheWVyX25hbWUpICsgCiAgICBsb2dpdChvdXQucHJvYikgKyBsb2dpdChzaW5nbGUucHJvYikgKyBsb2dpdChkb3VibGUucHJvYikgKyBsb2dpdCh0cmlwbGUucHJvYikgKyBsb2dpdChoci5wcm9iKSwKICBkYXRhPWRmLmhvbWVfcnVuLAogIGZhbWlseT1iaW5vbWlhbChsaW5rID0gInByb2JpdCIpLAogIG5BR1E9MCkKCmRmLnByZWRzXzIwMTUgPC0gcHJlZHNfZnVsbF8yMDE1CmRmLnByZWRzXzIwMTUkc2luZ2xlX2FsbF9scF9iYXQgPC0gcHJlZGljdChnbG1lci5zaW5nbGUubW9kLjIwMTUsIG5ld2RhdGE9ZGYucHJlZHNfMjAxNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3cubmV3LmxldmVscyA9IFRSVUUsIHR5cGU9J2xpbmsnLCByZS5mb3JtPX4oMXxwbGF5ZXJfbmFtZSkpCmRmLnByZWRzXzIwMTUkZG91YmxlX2FsbF9scF9iYXQgPC0gcHJlZGljdChnbG1lci5kb3VibGUubW9kLjIwMTUsIG5ld2RhdGE9ZGYucHJlZHNfMjAxNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3cubmV3LmxldmVscyA9IFRSVUUsIHR5cGU9J2xpbmsnLCByZS5mb3JtPX4oMXxwbGF5ZXJfbmFtZSkpCmRmLnByZWRzXzIwMTUkdHJpcGxlX2FsbF9scF9iYXQgPC0gcHJlZGljdChnbG1lci50cmlwbGUubW9kLjIwMTUsIG5ld2RhdGE9ZGYucHJlZHNfMjAxNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3cubmV3LmxldmVscyA9IFRSVUUsIHR5cGU9J2xpbmsnLCByZS5mb3JtPX4oMXxwbGF5ZXJfbmFtZSkpCmRmLnByZWRzXzIwMTUkaG9tZV9ydW5fYWxsX2xwX2JhdCA8LSBwcmVkaWN0KGdsbWVyLmhvbWVfcnVuLm1vZC4yMDE1LCBuZXdkYXRhPWRmLnByZWRzXzIwMTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93Lm5ldy5sZXZlbHMgPSBUUlVFLCB0eXBlPSdsaW5rJywgcmUuZm9ybT1+KDF8cGxheWVyX25hbWUpKQoKbW9kZWwuY29lZi4yMDE1IDwtIGRmLnByZWRzXzIwMTUgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIEtfYWxsID0gMSArIGV4cChzaW5nbGVfYWxsX2xwX2JhdCkgKyBleHAoZG91YmxlX2FsbF9scF9iYXQpICsgZXhwKHRyaXBsZV9hbGxfbHBfYmF0KSArIGV4cChob21lX3J1bl9hbGxfbHBfYmF0KSwKICAgIG91dHNfbmV3LnByb2IgPSAxIC8gS19hbGwsCiAgICBzaW5nbGVfbmV3LnByb2IgPSBleHAoc2luZ2xlX2FsbF9scF9iYXQpIC8gS19hbGwsCiAgICBkb3VibGVfbmV3LnByb2IgPSBleHAoZG91YmxlX2FsbF9scF9iYXQpIC8gS19hbGwsCiAgICB0cmlwbGVfbmV3LnByb2IgPSBleHAodHJpcGxlX2FsbF9scF9iYXQpIC8gS19hbGwsCiAgICBob21lX3J1bl9uZXcucHJvYiA9IGV4cChob21lX3J1bl9hbGxfbHBfYmF0KSAvIEtfYWxsKQoKbW9kZWwuY29lZi4yMDE1ICU8PiUKICBtdXRhdGUobWF4LnByb2JfZWMgPSBpZmVsc2Uob3V0c19uZXcucHJvYiA+IHNpbmdsZV9uZXcucHJvYiAmIG91dHNfbmV3LnByb2IgPiBkb3VibGVfbmV3LnByb2IgJiBvdXRzX25ldy5wcm9iID4gdHJpcGxlX25ldy5wcm9iICYgb3V0c19uZXcucHJvYiA+IGhvbWVfcnVuX25ldy5wcm9iLCAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2Uoc2luZ2xlX25ldy5wcm9iID4gb3V0c19uZXcucHJvYiAmIHNpbmdsZV9uZXcucHJvYiA+IGRvdWJsZV9uZXcucHJvYiAmIHNpbmdsZV9uZXcucHJvYiA+IHRyaXBsZV9uZXcucHJvYiAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW5nbGVfbmV3LnByb2IgPiBob21lX3J1bl9uZXcucHJvYiwgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkb3VibGVfbmV3LnByb2IgPiBvdXRzX25ldy5wcm9iICYgZG91YmxlX25ldy5wcm9iID4gc2luZ2xlX25ldy5wcm9iICYgZG91YmxlX25ldy5wcm9iID4gdHJpcGxlX25ldy5wcm9iIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICYgZG91YmxlX25ldy5wcm9iID4gaG9tZV9ydW5fbmV3LnByb2IsIDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRyaXBsZV9uZXcucHJvYiA+IG91dHNfbmV3LnByb2IgJiB0cmlwbGVfbmV3LnByb2IgPiBzaW5nbGVfbmV3LnByb2IgJiB0cmlwbGVfbmV3LnByb2IgPiBkb3VibGVfbmV3LnByb2IgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyaXBsZV9uZXcucHJvYiA+IGhvbWVfcnVuX25ldy5wcm9iLCAgMywgNCkpKSkpCgptb2RlbC5jb2VmLjIwMTUgJTw+JQogIG11dGF0ZShwcmVkLnJpZ2h0X25ldyA9IGlmZWxzZShtYXgucHJvYl9lYyA9PSBvdXRjb21lX2VjLCAieWVzIiwgIm5vIikpCgpzdW0obW9kZWwuY29lZi4yMDE1JHByZWQucmlnaHRfbmV3ID09ICJ5ZXMiKSAvIG5yb3coKG1vZGVsLmNvZWYuMjAxNSkpICMgIHhnYiBpcyAwLjg1NDQ5NjggdGhpcyBpcyAwLjg1ODE4NTkKYGBgCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQojIyMjIyMjIyMjIyMgMjAxNgpkZi5zaW5nbGUgPC0gcHJlZHNfZnVsbF8yMDE2ICU+JQogIGZpbHRlcihvdXRjb21lX2VjID09IDAgfCBvdXRjb21lX2VjID09IDEpICU+JQogIG11dGF0ZShvdXRjb21lID0gaWZlbHNlKG91dGNvbWVfZWMgPT0gMCwgMCwgMSkpCmRmLmRvdWJsZSA8LSBwcmVkc19mdWxsXzIwMTYgJT4lCiAgZmlsdGVyKG91dGNvbWVfZWMgPT0gMCB8IG91dGNvbWVfZWMgPT0gMikgJT4lCiAgbXV0YXRlKG91dGNvbWUgPSBpZmVsc2Uob3V0Y29tZV9lYyA9PSAwLCAwLCAxKSkKZGYudHJpcGxlIDwtIHByZWRzX2Z1bGxfMjAxNiAlPiUKICBmaWx0ZXIob3V0Y29tZV9lYyA9PSAwIHwgb3V0Y29tZV9lYyA9PSAzKSAlPiUKICBtdXRhdGUob3V0Y29tZSA9IGlmZWxzZShvdXRjb21lX2VjID09IDAsIDAsIDEpKQpkZi5ob21lX3J1biA8LSBwcmVkc19mdWxsXzIwMTYgJT4lCiAgZmlsdGVyKG91dGNvbWVfZWMgPT0gMCB8IG91dGNvbWVfZWMgPT0gNCkgJT4lCiAgbXV0YXRlKG91dGNvbWUgPSBpZmVsc2Uob3V0Y29tZV9lYyA9PSAwLCAwLCAxKSkKCmdsbWVyLnNpbmdsZS5tb2QuMjAxNiA8LSBnbG1lcigKICBvdXRjb21lIH4KICAgICgxfHBpdGNoZXJfbmFtZSkgKyAoMXxwbGF5ZXJfbmFtZSkgKyAgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi5zaW5nbGUsCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQpnbG1lci5kb3VibGUubW9kLjIwMTYgPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsgKDF8cGxheWVyX25hbWUpICsgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi5kb3VibGUsCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQpnbG1lci50cmlwbGUubW9kLjIwMTYgPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsgKDF8cGxheWVyX25hbWUpICsgIGxvZ2l0KG91dC5wcm9iKSArIGxvZ2l0KHNpbmdsZS5wcm9iKSArIGxvZ2l0KGRvdWJsZS5wcm9iKSArIGxvZ2l0KHRyaXBsZS5wcm9iKSArIGxvZ2l0KGhyLnByb2IpLAogIGRhdGE9ZGYudHJpcGxlLAogIGZhbWlseT1iaW5vbWlhbChsaW5rID0gInByb2JpdCIpLAogIG5BR1E9MCkKZ2xtZXIuaG9tZV9ydW4ubW9kLjIwMTYgPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsgKDF8cGxheWVyX25hbWUpICsgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi5ob21lX3J1biwKICBmYW1pbHk9Ymlub21pYWwobGluayA9ICJwcm9iaXQiKSwKICBuQUdRPTApCgpkZi5wcmVkc18yMDE2IDwtIHByZWRzX2Z1bGxfMjAxNgpkZi5wcmVkc18yMDE2JHNpbmdsZV9hbGxfbHBfYmF0IDwtIHByZWRpY3QoZ2xtZXIuc2luZ2xlLm1vZC4yMDE2LCBuZXdkYXRhPWRmLnByZWRzXzIwMTYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93Lm5ldy5sZXZlbHMgPSBUUlVFLCB0eXBlPSdsaW5rJywgcmUuZm9ybT1+KDF8cGxheWVyX25hbWUpKQpkZi5wcmVkc18yMDE2JGRvdWJsZV9hbGxfbHBfYmF0IDwtIHByZWRpY3QoZ2xtZXIuZG91YmxlLm1vZC4yMDE2LCBuZXdkYXRhPWRmLnByZWRzXzIwMTYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93Lm5ldy5sZXZlbHMgPSBUUlVFLCB0eXBlPSdsaW5rJywgcmUuZm9ybT1+KDF8cGxheWVyX25hbWUpKQpkZi5wcmVkc18yMDE2JHRyaXBsZV9hbGxfbHBfYmF0IDwtIHByZWRpY3QoZ2xtZXIudHJpcGxlLm1vZC4yMDE2LCBuZXdkYXRhPWRmLnByZWRzXzIwMTYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93Lm5ldy5sZXZlbHMgPSBUUlVFLCB0eXBlPSdsaW5rJywgcmUuZm9ybT1+KDF8cGxheWVyX25hbWUpKQpkZi5wcmVkc18yMDE2JGhvbWVfcnVuX2FsbF9scF9iYXQgPC0gcHJlZGljdChnbG1lci5ob21lX3J1bi5tb2QuMjAxNiwgbmV3ZGF0YT1kZi5wcmVkc18yMDE2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvdy5uZXcubGV2ZWxzID0gVFJVRSwgdHlwZT0nbGluaycsIHJlLmZvcm09figxfHBsYXllcl9uYW1lKSkKbW9kZWwuY29lZi4yMDE2IDwtIGRmLnByZWRzXzIwMTYgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIEtfYWxsID0gMSArIGV4cChzaW5nbGVfYWxsX2xwX2JhdCkgKyBleHAoZG91YmxlX2FsbF9scF9iYXQpICsgZXhwKHRyaXBsZV9hbGxfbHBfYmF0KSArIGV4cChob21lX3J1bl9hbGxfbHBfYmF0KSwKICAgIG91dHNfbmV3LnByb2IgPSAxIC8gS19hbGwsCiAgICBzaW5nbGVfbmV3LnByb2IgPSBleHAoc2luZ2xlX2FsbF9scF9iYXQpIC8gS19hbGwsCiAgICBkb3VibGVfbmV3LnByb2IgPSBleHAoZG91YmxlX2FsbF9scF9iYXQpIC8gS19hbGwsCiAgICB0cmlwbGVfbmV3LnByb2IgPSBleHAodHJpcGxlX2FsbF9scF9iYXQpIC8gS19hbGwsCiAgICBob21lX3J1bl9uZXcucHJvYiA9IGV4cChob21lX3J1bl9hbGxfbHBfYmF0KSAvIEtfYWxsCiAgKQoKbW9kZWwuY29lZi4yMDE2ICU8PiUKICBtdXRhdGUobWF4LnByb2JfZWMgPSBpZmVsc2Uob3V0c19uZXcucHJvYiA+IHNpbmdsZV9uZXcucHJvYiAmIG91dHNfbmV3LnByb2IgPiBkb3VibGVfbmV3LnByb2IgJiBvdXRzX25ldy5wcm9iID4gdHJpcGxlX25ldy5wcm9iICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0c19uZXcucHJvYiA+IGhvbWVfcnVuX25ldy5wcm9iLCAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2Uoc2luZ2xlX25ldy5wcm9iID4gb3V0c19uZXcucHJvYiAmIHNpbmdsZV9uZXcucHJvYiA+IGRvdWJsZV9uZXcucHJvYiAmIHNpbmdsZV9uZXcucHJvYiA+IHRyaXBsZV9uZXcucHJvYiAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW5nbGVfbmV3LnByb2IgPiBob21lX3J1bl9uZXcucHJvYiwgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkb3VibGVfbmV3LnByb2IgPiBvdXRzX25ldy5wcm9iICYgZG91YmxlX25ldy5wcm9iID4gc2luZ2xlX25ldy5wcm9iICYgZG91YmxlX25ldy5wcm9iID4gdHJpcGxlX25ldy5wcm9iIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICYgZG91YmxlX25ldy5wcm9iID4gaG9tZV9ydW5fbmV3LnByb2IsIDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRyaXBsZV9uZXcucHJvYiA+IG91dHNfbmV3LnByb2IgJiB0cmlwbGVfbmV3LnByb2IgPiBzaW5nbGVfbmV3LnByb2IgJiB0cmlwbGVfbmV3LnByb2IgPiBkb3VibGVfbmV3LnByb2IgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyaXBsZV9uZXcucHJvYiA+IGhvbWVfcnVuX25ldy5wcm9iLCAzLCA0KSkpKSkKCm1vZGVsLmNvZWYuMjAxNiAlPD4lCiAgbXV0YXRlKHByZWQucmlnaHRfbmV3ID0gaWZlbHNlKG1heC5wcm9iX2VjID09IG91dGNvbWVfZWMsICJ5ZXMiLCAibm8iKSkKCnN1bShtb2RlbC5jb2VmLjIwMTYkcHJlZC5yaWdodF9uZXcgPT0gInllcyIpIC8gbnJvdygobW9kZWwuY29lZi4yMDE2KSkgIyAgeGdiIGlzIDAuODUyNDY5IHRoaXMgaXMgMC44NTQ4MjM2CgojIyMjIyMjIyMjIyMgMjAxNwpkZi5zaW5nbGUgPC0gcHJlZHNfZnVsbF8yMDE3ICU+JQogIGZpbHRlcihvdXRjb21lX2VjID09IDAgfCBvdXRjb21lX2VjID09IDEpICU+JQogIG11dGF0ZShvdXRjb21lID0gaWZlbHNlKG91dGNvbWVfZWMgPT0gMCwgMCwgMSkpCmRmLmRvdWJsZSA8LSBwcmVkc19mdWxsXzIwMTcgJT4lCiAgZmlsdGVyKG91dGNvbWVfZWMgPT0gMCB8IG91dGNvbWVfZWMgPT0gMikgJT4lCiAgbXV0YXRlKG91dGNvbWUgPSBpZmVsc2Uob3V0Y29tZV9lYyA9PSAwLCAwLCAxKSkKZGYudHJpcGxlIDwtIHByZWRzX2Z1bGxfMjAxNyAlPiUKICBmaWx0ZXIob3V0Y29tZV9lYyA9PSAwIHwgb3V0Y29tZV9lYyA9PSAzKSAlPiUKICBtdXRhdGUob3V0Y29tZSA9IGlmZWxzZShvdXRjb21lX2VjID09IDAsIDAsIDEpKQpkZi5ob21lX3J1biA8LSBwcmVkc19mdWxsXzIwMTcgJT4lCiAgZmlsdGVyKG91dGNvbWVfZWMgPT0gMCB8IG91dGNvbWVfZWMgPT0gNCkgJT4lCiAgbXV0YXRlKG91dGNvbWUgPSBpZmVsc2Uob3V0Y29tZV9lYyA9PSAwLCAwLCAxKSkKCmdsbWVyLnNpbmdsZS5tb2QuMjAxNyA8LSBnbG1lcigKICBvdXRjb21lIH4KICAgICgxfHBpdGNoZXJfbmFtZSkgKyAoMXxwbGF5ZXJfbmFtZSkgKyAgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi5zaW5nbGUsCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQpnbG1lci5kb3VibGUubW9kLjIwMTcgPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsgKDF8cGxheWVyX25hbWUpICsgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi5kb3VibGUsCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQpnbG1lci50cmlwbGUubW9kLjIwMTcgPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsgKDF8cGxheWVyX25hbWUpICsgIGxvZ2l0KG91dC5wcm9iKSArIGxvZ2l0KHNpbmdsZS5wcm9iKSArIGxvZ2l0KGRvdWJsZS5wcm9iKSArIGxvZ2l0KHRyaXBsZS5wcm9iKSArIGxvZ2l0KGhyLnByb2IpLAogIGRhdGE9ZGYudHJpcGxlLAogIGZhbWlseT1iaW5vbWlhbChsaW5rID0gInByb2JpdCIpLAogIG5BR1E9MCkKZ2xtZXIuaG9tZV9ydW4ubW9kLjIwMTcgPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsgKDF8cGxheWVyX25hbWUpICsgIGxvZ2l0KG91dC5wcm9iKSArIGxvZ2l0KHNpbmdsZS5wcm9iKSArIGxvZ2l0KGRvdWJsZS5wcm9iKSArIGxvZ2l0KHRyaXBsZS5wcm9iKSArIGxvZ2l0KGhyLnByb2IpLAogIGRhdGE9ZGYuaG9tZV9ydW4sCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQoKZGYucHJlZHNfMjAxNyA8LSBwcmVkc19mdWxsXzIwMTcKZGYucHJlZHNfMjAxNyRzaW5nbGVfYWxsX2xwX2JhdCA8LSBwcmVkaWN0KGdsbWVyLnNpbmdsZS5tb2QuMjAxNywgbmV3ZGF0YT1kZi5wcmVkc18yMDE3LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvdy5uZXcubGV2ZWxzID0gVFJVRSwgdHlwZT0nbGluaycsIHJlLmZvcm09figxfHBsYXllcl9uYW1lKSkKZGYucHJlZHNfMjAxNyRkb3VibGVfYWxsX2xwX2JhdCA8LSBwcmVkaWN0KGdsbWVyLmRvdWJsZS5tb2QuMjAxNywgbmV3ZGF0YT1kZi5wcmVkc18yMDE3LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvdy5uZXcubGV2ZWxzID0gVFJVRSwgdHlwZT0nbGluaycsIHJlLmZvcm09figxfHBsYXllcl9uYW1lKSkKZGYucHJlZHNfMjAxNyR0cmlwbGVfYWxsX2xwX2JhdCA8LSBwcmVkaWN0KGdsbWVyLnRyaXBsZS5tb2QuMjAxNywgbmV3ZGF0YT1kZi5wcmVkc18yMDE3LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvdy5uZXcubGV2ZWxzID0gVFJVRSwgdHlwZT0nbGluaycsIHJlLmZvcm09figxfHBsYXllcl9uYW1lKSkKZGYucHJlZHNfMjAxNyRob21lX3J1bl9hbGxfbHBfYmF0IDwtIHByZWRpY3QoZ2xtZXIuaG9tZV9ydW4ubW9kLjIwMTcsIG5ld2RhdGE9ZGYucHJlZHNfMjAxNywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3cubmV3LmxldmVscyA9IFRSVUUsIHR5cGU9J2xpbmsnLCByZS5mb3JtPX4oMXxwbGF5ZXJfbmFtZSkpCm1vZGVsLmNvZWYuMjAxNyA8LSBkZi5wcmVkc18yMDE3ICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICBLX2FsbCA9IDEgKyBleHAoc2luZ2xlX2FsbF9scF9iYXQpICsgZXhwKGRvdWJsZV9hbGxfbHBfYmF0KSArIGV4cCh0cmlwbGVfYWxsX2xwX2JhdCkgKyBleHAoaG9tZV9ydW5fYWxsX2xwX2JhdCksCiAgICBvdXRzX25ldy5wcm9iID0gMSAvIEtfYWxsLAogICAgc2luZ2xlX25ldy5wcm9iID0gZXhwKHNpbmdsZV9hbGxfbHBfYmF0KSAvIEtfYWxsLAogICAgZG91YmxlX25ldy5wcm9iID0gZXhwKGRvdWJsZV9hbGxfbHBfYmF0KSAvIEtfYWxsLAogICAgdHJpcGxlX25ldy5wcm9iID0gZXhwKHRyaXBsZV9hbGxfbHBfYmF0KSAvIEtfYWxsLAogICAgaG9tZV9ydW5fbmV3LnByb2IgPSBleHAoaG9tZV9ydW5fYWxsX2xwX2JhdCkgLyBLX2FsbAogICkKCm1vZGVsLmNvZWYuMjAxNyAlPD4lCiAgbXV0YXRlKG1heC5wcm9iX2VjID0gaWZlbHNlKG91dHNfbmV3LnByb2IgPiBzaW5nbGVfbmV3LnByb2IgJiBvdXRzX25ldy5wcm9iID4gZG91YmxlX25ldy5wcm9iICYgb3V0c19uZXcucHJvYiA+IHRyaXBsZV9uZXcucHJvYiAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHNfbmV3LnByb2IgPiBob21lX3J1bl9uZXcucHJvYiwgMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHNpbmdsZV9uZXcucHJvYiA+IG91dHNfbmV3LnByb2IgJiBzaW5nbGVfbmV3LnByb2IgPiBkb3VibGVfbmV3LnByb2IgJiBzaW5nbGVfbmV3LnByb2IgPiB0cmlwbGVfbmV3LnByb2IgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2luZ2xlX25ldy5wcm9iID4gaG9tZV9ydW5fbmV3LnByb2IsIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZG91YmxlX25ldy5wcm9iID4gb3V0c19uZXcucHJvYiAmIGRvdWJsZV9uZXcucHJvYiA+IHNpbmdsZV9uZXcucHJvYiAmIGRvdWJsZV9uZXcucHJvYiA+IHRyaXBsZV9uZXcucHJvYiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmIGRvdWJsZV9uZXcucHJvYiA+IGhvbWVfcnVuX25ldy5wcm9iLCAyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0cmlwbGVfbmV3LnByb2IgPiBvdXRzX25ldy5wcm9iICYgdHJpcGxlX25ldy5wcm9iID4gc2luZ2xlX25ldy5wcm9iICYgdHJpcGxlX25ldy5wcm9iID4gZG91YmxlX25ldy5wcm9iICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmlwbGVfbmV3LnByb2IgPiBob21lX3J1bl9uZXcucHJvYiwgMywgNCkpKSkpCgptb2RlbC5jb2VmLjIwMTcgJTw+JQogIG11dGF0ZShwcmVkLnJpZ2h0X25ldyA9IGlmZWxzZShtYXgucHJvYl9lYyA9PSBvdXRjb21lX2VjLCAieWVzIiwgIm5vIikpCgpzdW0obW9kZWwuY29lZi4yMDE3JHByZWQucmlnaHRfbmV3ID09ICJ5ZXMiKSAvIG5yb3coKG1vZGVsLmNvZWYuMjAxNykpICMgeGdiIGlzIDAuODYwNjEyNSB0aGlzIGlzIDAuODY0MDM0OQoKIyMjIyMjIyMjIyMjIDIwMTgKZGYuc2luZ2xlIDwtIHByZWRzX2Z1bGxfMjAxOCAlPiUKICBmaWx0ZXIob3V0Y29tZV9lYyA9PSAwIHwgb3V0Y29tZV9lYyA9PSAxKSAlPiUKICBtdXRhdGUob3V0Y29tZSA9IGlmZWxzZShvdXRjb21lX2VjID09IDAsIDAsIDEpKQpkZi5kb3VibGUgPC0gcHJlZHNfZnVsbF8yMDE4ICU+JQogIGZpbHRlcihvdXRjb21lX2VjID09IDAgfCBvdXRjb21lX2VjID09IDIpICU+JQogIG11dGF0ZShvdXRjb21lID0gaWZlbHNlKG91dGNvbWVfZWMgPT0gMCwgMCwgMSkpCmRmLnRyaXBsZSA8LSBwcmVkc19mdWxsXzIwMTggJT4lCiAgZmlsdGVyKG91dGNvbWVfZWMgPT0gMCB8IG91dGNvbWVfZWMgPT0gMykgJT4lCiAgbXV0YXRlKG91dGNvbWUgPSBpZmVsc2Uob3V0Y29tZV9lYyA9PSAwLCAwLCAxKSkKZGYuaG9tZV9ydW4gPC0gcHJlZHNfZnVsbF8yMDE4ICU+JQogIGZpbHRlcihvdXRjb21lX2VjID09IDAgfCBvdXRjb21lX2VjID09IDQpICU+JQogIG11dGF0ZShvdXRjb21lID0gaWZlbHNlKG91dGNvbWVfZWMgPT0gMCwgMCwgMSkpCgpnbG1lci5zaW5nbGUubW9kLjIwMTggPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsgKDF8cGxheWVyX25hbWUpICsgIGxvZ2l0KG91dC5wcm9iKSArIGxvZ2l0KHNpbmdsZS5wcm9iKSArIGxvZ2l0KGRvdWJsZS5wcm9iKSArIGxvZ2l0KHRyaXBsZS5wcm9iKSArIGxvZ2l0KGhyLnByb2IpLAogIGRhdGE9ZGYuc2luZ2xlLAogIGZhbWlseT1iaW5vbWlhbChsaW5rID0gInByb2JpdCIpLAogIG5BR1E9MCkKZ2xtZXIuZG91YmxlLm1vZC4yMDE4IDwtIGdsbWVyKAogIG91dGNvbWUgfgogICAgKDF8cGl0Y2hlcl9uYW1lKSArICgxfHBsYXllcl9uYW1lKSArICBsb2dpdChvdXQucHJvYikgKyBsb2dpdChzaW5nbGUucHJvYikgKyBsb2dpdChkb3VibGUucHJvYikgKyBsb2dpdCh0cmlwbGUucHJvYikgKyBsb2dpdChoci5wcm9iKSwKICBkYXRhPWRmLmRvdWJsZSwKICBmYW1pbHk9Ymlub21pYWwobGluayA9ICJwcm9iaXQiKSwKICBuQUdRPTApCmdsbWVyLnRyaXBsZS5tb2QuMjAxOCA8LSBnbG1lcigKICBvdXRjb21lIH4KICAgICgxfHBpdGNoZXJfbmFtZSkgKyAoMXxwbGF5ZXJfbmFtZSkgKyAgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi50cmlwbGUsCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQpnbG1lci5ob21lX3J1bi5tb2QuMjAxOCA8LSBnbG1lcigKICBvdXRjb21lIH4KICAgICgxfHBpdGNoZXJfbmFtZSkgKyAoMXxwbGF5ZXJfbmFtZSkgKyAgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi5ob21lX3J1biwKICBmYW1pbHk9Ymlub21pYWwobGluayA9ICJwcm9iaXQiKSwKICBuQUdRPTApCgpkZi5wcmVkc18yMDE4IDwtIHByZWRzX2Z1bGxfMjAxOApkZi5wcmVkc18yMDE4JHNpbmdsZV9hbGxfbHBfYmF0IDwtIHByZWRpY3QoZ2xtZXIuc2luZ2xlLm1vZC4yMDE4LCBuZXdkYXRhPWRmLnByZWRzXzIwMTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93Lm5ldy5sZXZlbHMgPSBUUlVFLCB0eXBlPSdsaW5rJywgcmUuZm9ybT1+KDF8cGxheWVyX25hbWUpKQpkZi5wcmVkc18yMDE4JGRvdWJsZV9hbGxfbHBfYmF0IDwtIHByZWRpY3QoZ2xtZXIuZG91YmxlLm1vZC4yMDE4LCBuZXdkYXRhPWRmLnByZWRzXzIwMTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93Lm5ldy5sZXZlbHMgPSBUUlVFLCB0eXBlPSdsaW5rJywgcmUuZm9ybT1+KDF8cGxheWVyX25hbWUpKQpkZi5wcmVkc18yMDE4JHRyaXBsZV9hbGxfbHBfYmF0IDwtIHByZWRpY3QoZ2xtZXIudHJpcGxlLm1vZC4yMDE4LCBuZXdkYXRhPWRmLnByZWRzXzIwMTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93Lm5ldy5sZXZlbHMgPSBUUlVFLCB0eXBlPSdsaW5rJywgcmUuZm9ybT1+KDF8cGxheWVyX25hbWUpKQpkZi5wcmVkc18yMDE4JGhvbWVfcnVuX2FsbF9scF9iYXQgPC0gcHJlZGljdChnbG1lci5ob21lX3J1bi5tb2QuMjAxOCwgbmV3ZGF0YT1kZi5wcmVkc18yMDE4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvdy5uZXcubGV2ZWxzID0gVFJVRSwgdHlwZT0nbGluaycsIHJlLmZvcm09figxfHBsYXllcl9uYW1lKSkKbW9kZWwuY29lZi4yMDE4IDwtIGRmLnByZWRzXzIwMTggJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIEtfYWxsID0gMSArIGV4cChzaW5nbGVfYWxsX2xwX2JhdCkgKyBleHAoZG91YmxlX2FsbF9scF9iYXQpICsgZXhwKHRyaXBsZV9hbGxfbHBfYmF0KSArIGV4cChob21lX3J1bl9hbGxfbHBfYmF0KSwKICAgIG91dHNfbmV3LnByb2IgPSAxIC8gS19hbGwsCiAgICBzaW5nbGVfbmV3LnByb2IgPSBleHAoc2luZ2xlX2FsbF9scF9iYXQpIC8gS19hbGwsCiAgICBkb3VibGVfbmV3LnByb2IgPSBleHAoZG91YmxlX2FsbF9scF9iYXQpIC8gS19hbGwsCiAgICB0cmlwbGVfbmV3LnByb2IgPSBleHAodHJpcGxlX2FsbF9scF9iYXQpIC8gS19hbGwsCiAgICBob21lX3J1bl9uZXcucHJvYiA9IGV4cChob21lX3J1bl9hbGxfbHBfYmF0KSAvIEtfYWxsCiAgKQoKbW9kZWwuY29lZi4yMDE4ICU8PiUKICBtdXRhdGUobWF4LnByb2JfZWMgPSBpZmVsc2Uob3V0c19uZXcucHJvYiA+IHNpbmdsZV9uZXcucHJvYiAmIG91dHNfbmV3LnByb2IgPiBkb3VibGVfbmV3LnByb2IgJiBvdXRzX25ldy5wcm9iID4gdHJpcGxlX25ldy5wcm9iICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0c19uZXcucHJvYiA+IGhvbWVfcnVuX25ldy5wcm9iLCAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2Uoc2luZ2xlX25ldy5wcm9iID4gb3V0c19uZXcucHJvYiAmIHNpbmdsZV9uZXcucHJvYiA+IGRvdWJsZV9uZXcucHJvYiAmIHNpbmdsZV9uZXcucHJvYiA+IHRyaXBsZV9uZXcucHJvYiAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW5nbGVfbmV3LnByb2IgPiBob21lX3J1bl9uZXcucHJvYiwgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShkb3VibGVfbmV3LnByb2IgPiBvdXRzX25ldy5wcm9iICYgZG91YmxlX25ldy5wcm9iID4gc2luZ2xlX25ldy5wcm9iICYgZG91YmxlX25ldy5wcm9iID4gdHJpcGxlX25ldy5wcm9iIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICYgZG91YmxlX25ldy5wcm9iID4gaG9tZV9ydW5fbmV3LnByb2IsIDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRyaXBsZV9uZXcucHJvYiA+IG91dHNfbmV3LnByb2IgJiB0cmlwbGVfbmV3LnByb2IgPiBzaW5nbGVfbmV3LnByb2IgJiB0cmlwbGVfbmV3LnByb2IgPiBkb3VibGVfbmV3LnByb2IgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyaXBsZV9uZXcucHJvYiA+IGhvbWVfcnVuX25ldy5wcm9iLCAzLCA0KSkpKSkKCm1vZGVsLmNvZWYuMjAxOCAlPD4lCiAgbXV0YXRlKHByZWQucmlnaHRfbmV3ID0gaWZlbHNlKG1heC5wcm9iX2VjID09IG91dGNvbWVfZWMsICJ5ZXMiLCAibm8iKSkKCnN1bShtb2RlbC5jb2VmLjIwMTgkcHJlZC5yaWdodF9uZXcgPT0gInllcyIpIC8gbnJvdygobW9kZWwuY29lZi4yMDE4KSkgIyB4Z2IgaXMgMC44NTYyNzEzIHRoaXMgaXMgMC44NTkwODY0CgojIyMjIyMjIyMjIyMgMjAxOQpkZi5zaW5nbGUgPC0gcHJlZHNfZnVsbF8yMDE5ICU+JQogIGZpbHRlcihvdXRjb21lX2VjID09IDAgfCBvdXRjb21lX2VjID09IDEpICU+JQogIG11dGF0ZShvdXRjb21lID0gaWZlbHNlKG91dGNvbWVfZWMgPT0gMCwgMCwgMSkpCmRmLmRvdWJsZSA8LSBwcmVkc19mdWxsXzIwMTkgJT4lCiAgZmlsdGVyKG91dGNvbWVfZWMgPT0gMCB8IG91dGNvbWVfZWMgPT0gMikgJT4lCiAgbXV0YXRlKG91dGNvbWUgPSBpZmVsc2Uob3V0Y29tZV9lYyA9PSAwLCAwLCAxKSkKZGYudHJpcGxlIDwtIHByZWRzX2Z1bGxfMjAxOSAlPiUKICBmaWx0ZXIob3V0Y29tZV9lYyA9PSAwIHwgb3V0Y29tZV9lYyA9PSAzKSAlPiUKICBtdXRhdGUob3V0Y29tZSA9IGlmZWxzZShvdXRjb21lX2VjID09IDAsIDAsIDEpKQpkZi5ob21lX3J1biA8LSBwcmVkc19mdWxsXzIwMTkgJT4lCiAgZmlsdGVyKG91dGNvbWVfZWMgPT0gMCB8IG91dGNvbWVfZWMgPT0gNCkgJT4lCiAgbXV0YXRlKG91dGNvbWUgPSBpZmVsc2Uob3V0Y29tZV9lYyA9PSAwLCAwLCAxKSkKCmdsbWVyLnNpbmdsZS5tb2QuMjAxOSA8LSBnbG1lcigKICBvdXRjb21lIH4KICAgICgxfHBpdGNoZXJfbmFtZSkgKyAoMXxwbGF5ZXJfbmFtZSkgKyAgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi5zaW5nbGUsCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQpnbG1lci5kb3VibGUubW9kLjIwMTkgPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsgKDF8cGxheWVyX25hbWUpICsgbG9naXQob3V0LnByb2IpICsgbG9naXQoc2luZ2xlLnByb2IpICsgbG9naXQoZG91YmxlLnByb2IpICsgbG9naXQodHJpcGxlLnByb2IpICsgbG9naXQoaHIucHJvYiksCiAgZGF0YT1kZi5kb3VibGUsCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQpnbG1lci50cmlwbGUubW9kLjIwMTkgPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsgKDF8cGxheWVyX25hbWUpICsgIGxvZ2l0KG91dC5wcm9iKSArIGxvZ2l0KHNpbmdsZS5wcm9iKSArIGxvZ2l0KGRvdWJsZS5wcm9iKSArIGxvZ2l0KHRyaXBsZS5wcm9iKSArIGxvZ2l0KGhyLnByb2IpLAogIGRhdGE9ZGYudHJpcGxlLAogIGZhbWlseT1iaW5vbWlhbChsaW5rID0gInByb2JpdCIpLAogIG5BR1E9MCkKZ2xtZXIuaG9tZV9ydW4ubW9kLjIwMTkgPC0gZ2xtZXIoCiAgb3V0Y29tZSB+CiAgICAoMXxwaXRjaGVyX25hbWUpICsgKDF8cGxheWVyX25hbWUpICsgIGxvZ2l0KG91dC5wcm9iKSArIGxvZ2l0KHNpbmdsZS5wcm9iKSArIGxvZ2l0KGRvdWJsZS5wcm9iKSArIGxvZ2l0KHRyaXBsZS5wcm9iKSArIGxvZ2l0KGhyLnByb2IpLAogIGRhdGE9ZGYuaG9tZV9ydW4sCiAgZmFtaWx5PWJpbm9taWFsKGxpbmsgPSAicHJvYml0IiksCiAgbkFHUT0wKQoKZGYucHJlZHNfMjAxOSA8LSBwcmVkc19mdWxsXzIwMTkKZGYucHJlZHNfMjAxOSRzaW5nbGVfYWxsX2xwX2JhdCA8LSBwcmVkaWN0KGdsbWVyLnNpbmdsZS5tb2QuMjAxOSwgbmV3ZGF0YT1kZi5wcmVkc18yMDE5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvdy5uZXcubGV2ZWxzID0gVFJVRSwgdHlwZT0nbGluaycsIHJlLmZvcm09figxfHBsYXllcl9uYW1lKSkKZGYucHJlZHNfMjAxOSRkb3VibGVfYWxsX2xwX2JhdCA8LSBwcmVkaWN0KGdsbWVyLmRvdWJsZS5tb2QuMjAxOSwgbmV3ZGF0YT1kZi5wcmVkc18yMDE5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvdy5uZXcubGV2ZWxzID0gVFJVRSwgdHlwZT0nbGluaycsIHJlLmZvcm09figxfHBsYXllcl9uYW1lKSkKZGYucHJlZHNfMjAxOSR0cmlwbGVfYWxsX2xwX2JhdCA8LSBwcmVkaWN0KGdsbWVyLnRyaXBsZS5tb2QuMjAxOSwgbmV3ZGF0YT1kZi5wcmVkc18yMDE5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvdy5uZXcubGV2ZWxzID0gVFJVRSwgdHlwZT0nbGluaycsIHJlLmZvcm09figxfHBsYXllcl9uYW1lKSkKZGYucHJlZHNfMjAxOSRob21lX3J1bl9hbGxfbHBfYmF0IDwtIHByZWRpY3QoZ2xtZXIuaG9tZV9ydW4ubW9kLjIwMTksIG5ld2RhdGE9ZGYucHJlZHNfMjAxOSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3cubmV3LmxldmVscyA9IFRSVUUsIHR5cGU9J2xpbmsnLCByZS5mb3JtPX4oMXxwbGF5ZXJfbmFtZSkpCm1vZGVsLmNvZWYuMjAxOSA8LSBkZi5wcmVkc18yMDE5ICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICBLX2FsbCA9IDEgKyBleHAoc2luZ2xlX2FsbF9scF9iYXQpICsgZXhwKGRvdWJsZV9hbGxfbHBfYmF0KSArIGV4cCh0cmlwbGVfYWxsX2xwX2JhdCkgKyBleHAoaG9tZV9ydW5fYWxsX2xwX2JhdCksCiAgICBvdXRzX25ldy5wcm9iID0gMSAvIEtfYWxsLAogICAgc2luZ2xlX25ldy5wcm9iID0gZXhwKHNpbmdsZV9hbGxfbHBfYmF0KSAvIEtfYWxsLAogICAgZG91YmxlX25ldy5wcm9iID0gZXhwKGRvdWJsZV9hbGxfbHBfYmF0KSAvIEtfYWxsLAogICAgdHJpcGxlX25ldy5wcm9iID0gZXhwKHRyaXBsZV9hbGxfbHBfYmF0KSAvIEtfYWxsLAogICAgaG9tZV9ydW5fbmV3LnByb2IgPSBleHAoaG9tZV9ydW5fYWxsX2xwX2JhdCkgLyBLX2FsbAogICkKCm1vZGVsLmNvZWYuMjAxOSAlPD4lCiAgbXV0YXRlKG1heC5wcm9iX2VjID0gaWZlbHNlKG91dHNfbmV3LnByb2IgPiBzaW5nbGVfbmV3LnByb2IgJiBvdXRzX25ldy5wcm9iID4gZG91YmxlX25ldy5wcm9iICYgb3V0c19uZXcucHJvYiA+IHRyaXBsZV9uZXcucHJvYiAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHNfbmV3LnByb2IgPiBob21lX3J1bl9uZXcucHJvYiwgMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHNpbmdsZV9uZXcucHJvYiA+IG91dHNfbmV3LnByb2IgJiBzaW5nbGVfbmV3LnByb2IgPiBkb3VibGVfbmV3LnByb2IgJiBzaW5nbGVfbmV3LnByb2IgPiB0cmlwbGVfbmV3LnByb2IgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2luZ2xlX25ldy5wcm9iID4gaG9tZV9ydW5fbmV3LnByb2IsIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZG91YmxlX25ldy5wcm9iID4gb3V0c19uZXcucHJvYiAmIGRvdWJsZV9uZXcucHJvYiA+IHNpbmdsZV9uZXcucHJvYiAmIGRvdWJsZV9uZXcucHJvYiA+IHRyaXBsZV9uZXcucHJvYiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmIGRvdWJsZV9uZXcucHJvYiA+IGhvbWVfcnVuX25ldy5wcm9iLCAyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0cmlwbGVfbmV3LnByb2IgPiBvdXRzX25ldy5wcm9iICYgdHJpcGxlX25ldy5wcm9iID4gc2luZ2xlX25ldy5wcm9iICYgdHJpcGxlX25ldy5wcm9iID4gZG91YmxlX25ldy5wcm9iICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmlwbGVfbmV3LnByb2IgPiBob21lX3J1bl9uZXcucHJvYiwgMywgNCkpKSkpCgptb2RlbC5jb2VmLjIwMTkgJTw+JQogIG11dGF0ZShwcmVkLnJpZ2h0X25ldyA9IGlmZWxzZShtYXgucHJvYl9lYyA9PSBvdXRjb21lX2VjLCAieWVzIiwgIm5vIikpCgpzdW0obW9kZWwuY29lZi4yMDE5JHByZWQucmlnaHRfbmV3ID09ICJ5ZXMiKSAvIG5yb3coKG1vZGVsLmNvZWYuMjAxOSkpICMgeGdiIGlzIDAuODYyNDU5IHRoaXMgaXMgMC44NjY4NjU0CmBgYAoKTm93LCBhZnRlciBhbGwgb2YgdGhhdCwgSSdtIGFjdHVhbGx5IGdvaW5nIHRvIG1ha2UgdGhlIG1ldHJpYy4gCmBgYHtyfQp3b2JhX3dlaWdodHNfMjAxNSA8LSBjKDAsIC44ODEsCTEuMjU2LCAxLjU5NCwgMi4wNjUpICMgZnJvbSBGYW5HcmFwaHMKCm1vZGVsLmNvZWYuMjAxNSAlPD4lCiAgbXV0YXRlKGV4cGVjdGVkX3dvYmEgPSAob3V0c19uZXcucHJvYiAqIHdvYmFfd2VpZ2h0c18yMDE1WzFdKSArIChzaW5nbGVfbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxNVsyXSkgKyAoZG91YmxlX25ldy5wcm9iICogd29iYV93ZWlnaHRzXzIwMTVbM10pICsgCiAgICAgICAgICAgKHRyaXBsZV9uZXcucHJvYiAqIHdvYmFfd2VpZ2h0c18yMDE1WzRdKSArIChob21lX3J1bl9uZXcucHJvYiAqIHdvYmFfd2VpZ2h0c18yMDE1WzVdKSkKCm1vZGVsLmNvZWYuMjAxNSRwZXJjZW50aWxlIDwtIDEwMCAqIChzY2FsZXM6OnJlc2NhbGUobW9kZWwuY29lZi4yMDE1JGV4cGVjdGVkX3dvYmEsIHRvPWMoMCwxKSkpCm1vZGVsLmNvZWYuMjAxNSRxY3AgPC0gcHN5Y2g6OnJlc2NhbGUobW9kZWwuY29lZi4yMDE1JHBlcmNlbnRpbGUsIG1lYW4gPSAxMDAsIHNkID0gMzAsIGRmPUYpCmBgYAoKYGBge3IgaW5jbHVkZT1GQUxTRX0KIyBhbGwgZnJvbSBGYW5HcmFwaHMKd29iYV93ZWlnaHRzXzIwMTYgPC0gYygwLCAuODc4LAkxLjI0MiwgMS41NjksCTIuMDE1KQp3b2JhX3dlaWdodHNfMjAxNyA8LSBjKDAsIC44NzcsIDEuMjMyLCAxLjU1MiwgMS45ODApIAp3b2JhX3dlaWdodHNfMjAxOCA8LSBjKDAsIC44ODAsIDEuMjQ3LCAxLjU3OCwgMi4wMzEpCndvYmFfd2VpZ2h0c18yMDE5IDwtIGMoMCwgLjg3MCwgMS4yMTcsIDEuNTI5LCAxLjk0MCkKCiMjIyMgMjAxNgptb2RlbC5jb2VmLjIwMTYgJTw+JQogIG11dGF0ZShleHBlY3RlZF93b2JhID0gKG91dHNfbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxNlsxXSkgKyAoc2luZ2xlX25ldy5wcm9iICogd29iYV93ZWlnaHRzXzIwMTZbMl0pICsgKGRvdWJsZV9uZXcucHJvYiAqIHdvYmFfd2VpZ2h0c18yMDE2WzNdKSArIAogICAgICAgICAgICh0cmlwbGVfbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxNls0XSkgKyAoaG9tZV9ydW5fbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxNls1XSkpCiAgICAgICAgICAgCm1vZGVsLmNvZWYuMjAxNiRwZXJjZW50aWxlIDwtIDEwMCAqIChzY2FsZXM6OnJlc2NhbGUobW9kZWwuY29lZi4yMDE2JGV4cGVjdGVkX3dvYmEsIHRvPWMoMCwxKSkpCm1vZGVsLmNvZWYuMjAxNiRxY3AgPC0gcHN5Y2g6OnJlc2NhbGUobW9kZWwuY29lZi4yMDE2JHBlcmNlbnRpbGUsIG1lYW4gPSAxMDAsIHNkID0gMzAsIGRmPUYpCgojIyMgMjAxNwptb2RlbC5jb2VmLjIwMTcgJTw+JQogIG11dGF0ZShleHBlY3RlZF93b2JhID0gKG91dHNfbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxN1sxXSkgKyAoc2luZ2xlX25ldy5wcm9iICogd29iYV93ZWlnaHRzXzIwMTdbMl0pICsgKGRvdWJsZV9uZXcucHJvYiAqIHdvYmFfd2VpZ2h0c18yMDE3WzNdKSArIAogICAgICAgICAgICh0cmlwbGVfbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxN1s0XSkgKyAoaG9tZV9ydW5fbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxN1s1XSkpCiAgICAgICAgICAgCm1vZGVsLmNvZWYuMjAxNyRwZXJjZW50aWxlIDwtIDEwMCAqIChzY2FsZXM6OnJlc2NhbGUobW9kZWwuY29lZi4yMDE3JGV4cGVjdGVkX3dvYmEsIHRvPWMoMCwxKSkpCm1vZGVsLmNvZWYuMjAxNyRxY3AgPC0gcHN5Y2g6OnJlc2NhbGUobW9kZWwuY29lZi4yMDE3JHBlcmNlbnRpbGUsIG1lYW4gPSAxMDAsIHNkID0gMzAsIGRmPUYpCgojIyMgMjAxOAptb2RlbC5jb2VmLjIwMTggJTw+JQogIG11dGF0ZShleHBlY3RlZF93b2JhID0gKG91dHNfbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxOFsxXSkgKyAoc2luZ2xlX25ldy5wcm9iICogd29iYV93ZWlnaHRzXzIwMThbMl0pICsgKGRvdWJsZV9uZXcucHJvYiAqIHdvYmFfd2VpZ2h0c18yMDE4WzNdKSArIAogICAgICAgICAgICh0cmlwbGVfbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxOFs0XSkgKyAoaG9tZV9ydW5fbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxOFs1XSkpCiAgICAgICAgICAgCgptb2RlbC5jb2VmLjIwMTgkcGVyY2VudGlsZSA8LSAxMDAgKiAoc2NhbGVzOjpyZXNjYWxlKG1vZGVsLmNvZWYuMjAxOCRleHBlY3RlZF93b2JhLCB0bz1jKDAsMSkpKQptb2RlbC5jb2VmLjIwMTgkcWNwIDwtIHBzeWNoOjpyZXNjYWxlKG1vZGVsLmNvZWYuMjAxOCRwZXJjZW50aWxlLCBtZWFuID0gMTAwLCBzZCA9IDMwLCBkZj1GKQoKIyMjIDIwMTkKbW9kZWwuY29lZi4yMDE5ICU8PiUKICBtdXRhdGUoZXhwZWN0ZWRfd29iYSA9IChvdXRzX25ldy5wcm9iICogd29iYV93ZWlnaHRzXzIwMTlbMV0pICsgKHNpbmdsZV9uZXcucHJvYiAqIHdvYmFfd2VpZ2h0c18yMDE5WzJdKSArIChkb3VibGVfbmV3LnByb2IgKiB3b2JhX3dlaWdodHNfMjAxOVszXSkgKyAKICAgICAgICAgICAodHJpcGxlX25ldy5wcm9iICogd29iYV93ZWlnaHRzXzIwMTlbNF0pICsgKGhvbWVfcnVuX25ldy5wcm9iICogd29iYV93ZWlnaHRzXzIwMTlbNV0pKQogICAgICAgICAgIAptb2RlbC5jb2VmLjIwMTkkcGVyY2VudGlsZSA8LSAxMDAgKiAoc2NhbGVzOjpyZXNjYWxlKG1vZGVsLmNvZWYuMjAxOSRleHBlY3RlZF93b2JhLCB0bz1jKDAsMSkpKQptb2RlbC5jb2VmLjIwMTkkcWNwIDwtIHBzeWNoOjpyZXNjYWxlKG1vZGVsLmNvZWYuMjAxOSRwZXJjZW50aWxlLCBtZWFuID0gMTAwLCBzZCA9IDMwLCBkZj1GKQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmJhdHRlZF9iYWxsX3Jlc3VsdHNfMjAxNSA8LSBtb2RlbC5jb2VmLjIwMTUKYmF0dGVkX2JhbGxfcmVzdWx0c18yMDE2IDwtIG1vZGVsLmNvZWYuMjAxNgpiYXR0ZWRfYmFsbF9yZXN1bHRzXzIwMTcgPC0gbW9kZWwuY29lZi4yMDE3CmJhdHRlZF9iYWxsX3Jlc3VsdHNfMjAxOCA8LSBtb2RlbC5jb2VmLjIwMTgKYmF0dGVkX2JhbGxfcmVzdWx0c18yMDE5IDwtIG1vZGVsLmNvZWYuMjAxOQpgYGAK