1. Introduction
Climate change impacts such as sea level rise and increasingly severe
and frequent weather events like heavy rains exacerbate present flood
threats. Identifying flood vulnerable areas and predicting where
flooding may occur is integral to planning for a climate-changed future.
The following report is a part of an effort to develop and test a
predictive flood model:
We have been tasked with creating a model that predicts areas
vulnerable to flooding. In order to do so, we chose an area where we
already had recorded flood data: Calgary, Alberta (CAN). In addition, we
needed to choose a comparable city to Calgary, one that could test our
model. We chose Washington DC. Both Calgary and DC have large rivers
running through the cities and are large population centers.
After choosing our cities, we came up with potential factors that
might lead to flooding. Those factors are:
For each factor, we came up with a hypothesis:
Elevation: If an area is at a low elevation, it will most likely
flood.
Impervious Surfaces: If an area has or is made up of many
impervious surfaces, it will most likely flood.
Parks: If an area has or is made up of many green spaces, it will
most likely not flood.
Low Permeable Soils: If an area has or is made up of many low
permeable soils, it will most likely flood.
Waterbodies: If an area has or is made up of existing
waterbodies, it will most likely flood.
To test these hypotheses and build a predictive model, we conducted
feature engineering, spatial lags, and a generalized linear model (GLM).
The following sections highlight our key features, our regression model
summary, and our final flood predictions for Calgary and DC.
Ultimately, the DC predictive model did not perform how we would have
hoped; however, we found promising results in our Calgary model. This
draws us to conclude that Washington DC may not have been a good fit as
a comparison city. For example, while Calgary is far more inland and has
a drier climate, DC is relatively close to the Chesapeake Bay and tends
to be more humid. Other US cities that might have been more comparable
to Calgary could have been Denver, CO, or Salt Lake City, UT.
2. Maps of Variables
To begin our modeling process in R, we uploaded our Calgary fishnet
and our predictive factors or “variables”: elevation, impervious
surfaces, low permeable soils, parks, and waterbodies. A fishnet is a
grid made up of squares–like a net–called “cells” overlaid on some
geographic area. Fishnets have many uses, but our main purpose was to
use the fishnet for spatial analysis and modeling.
The fishnet allows us to measure the presence or “how much” of a
variable is found within a certain area or cell. By running zonal
statistics for each variable in ArcGIS, we determined what was the best
measure for each variable:
Elevation: We decided to measure the lowest point of each cell,
or the minimum value of elevation. We operated under the assumption that
the lowest point of every cell is where most water within the cell will
gather.
Impervious Surfaces: If the mean count of “impervious surface”
pixels within a cell was equal to or exceeded 25% of a cell, then the
cell possessed impervious surfaces.
Low Permeable Soils: If the mean count of “low permeable soil”
pixels within a cell was equal to or exceeded 25% of a cell, then the
cell possessed low permeable soils.
Parks: If the mean count of “park” pixels within a cell was equal
to or exceeded 25%, then the cell possessed a park.
Waterbodies: If the mean count of “waterbodies” pixels within a
cell was equal to or exceeded 25%, then the cell possessed a
waterbody.
Four of these maps are visualized in the next section.
2.1. Impervious Surfaces

2.2. Parks

2.3. Low Permeable Soils

2.4. Existing Waterbodies

3. Model Validation
3.1. Exploratory Analysis: Summary Table

The summary table shows us some interesting aspects of our model. For
example, our hypothesis concerning low elevation was that cells with low
elevation are more likely to flood. However, the summary table shows
that out of the total cells with low elevation, many did not flood. The
same is said for low permeable soils and impervious surfaces. We
predicted that areas with low permeability or impermeability were more
likely to flood, but the summary table shows the opposite was true.
Furthermore, our prediction concerning parks followed that cells with
parks were less likely to flood, but the summary table shows that cells
with parks were actually more likely to flood.
Our summary table, however, may be telling us a positive story: what
do we know about Calgary’s stormwater infrastructure? If Calgary has
effective stormwater infrastructure, then this may explain why areas of
low elevation and parks are flooded while areas with impervious surfaces
and soils are not. For example, it is standard green stormwater
infrastructure practice to use parks as multi-use spaces: during heavy
rains, parks can serve as stormwater holding basins and/or help absorb
excess water. In this sense, parks are engineered or
designed to be flooded.
Additionally, if Calgary’s stormwater infrastructure is effective,
then water should be redirected away from urban areas. Stormwater
infrastructure is often paired with city’s water systems, and many
cities–including Calgary–utilize gravity systems, which take advantage
of gravity as a force to direct water flow “downwards” or towards areas
of low elevation (often waterbodies or water treatment plants).
Although our summary table shows that our variables are not
necessarily following our assumptions, they still may be indicative of a
relationship, and even a positive story!
3.2. Logistic Regression Model Summary
Next, we run a regression summary to determine our variables
statistical significance. Based on our p-values and coefficient
estimates, our regression summary shows that our variables are
statistically significant, meaning there is some relationship between
flooding and the presence of our variables.
floodModel <- glm(Flooded ~ .,
family="binomial"(link="logit"), data = floodTrain %>%
as.data.frame() %>%
dplyr::select(-geometry, -cell))
summary(floodModel)
##
## Call:
## glm(formula = Flooded ~ ., family = binomial(link = "logit"),
## data = floodTrain %>% as.data.frame() %>% dplyr::select(-geometry,
## -cell))
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 1.873002 0.214924 8.715 < 0.0000000000000002 ***
## Low_permeability -1.348975 0.142291 -9.480 < 0.0000000000000002 ***
## Parks_Majority 1.977298 0.165694 11.933 < 0.0000000000000002 ***
## Impervious_majority -0.520810 0.139380 -3.737 0.000187 ***
## elevation_min -0.028850 0.002025 -14.246 < 0.0000000000000002 ***
## Water_majority 2.037572 0.312215 6.526 0.0000000000675 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 2253.5 on 2498 degrees of freedom
## Residual deviance: 1559.3 on 2493 degrees of freedom
## AIC: 1571.3
##
## Number of Fisher Scoring iterations: 6
3.3. Confusion Metrics & ROC Curve

Confusion Matrix and Statistics
Reference
Prediction 0 1 0 766 56 1 137 111
Accuracy : 0.8196
95% CI : (0.7953, 0.8422)
No Information Rate : 0.8439
P-Value [Acc > NIR] : 0.986
Kappa : 0.4283
Mcnemar’s Test P-Value : 0.000000008485
Sensitivity : 0.6647
Specificity : 0.8483
Pos Pred Value : 0.4476
Neg Pred Value : 0.9319
Prevalence : 0.1561
Detection Rate : 0.1037
Detection Prevalence : 0.2318
Balanced Accuracy : 0.7565
'Positive' Class : 1
According to the Confusion Matrix, our model runs at about an 82%
accuracy rate and is best at predicting which cells are not flooded, but
is less accurate at predicting which cells will flood.
For example, the Confusion Matrix shows that our model predicted 903
cells would not flood. Out of those 903 cells, 766 cells were predicted
to not flood and in reality, did not flood based off of our recorded
Calgary flood data; however, 137 of the cells predicted to not flood,
actually did flood. On the other hand, out of 167 cells, our model
correctly predicted 111 cells would flood, but incorrectly predicted 56
cells would flood. In actuality, those 56 cells did not flood.
This information is summed up in the sensitivity and specificity
measure of our model. The Confusion Matrix shows that our model’s
sensitivity, that is, its accuracy in predicting cells that
will flood is about 67%; our model’s specificity, that
is, its accuracy in predicting cells that will not
flood is about 85%.

Initially, we ran our confusion matrix with a 50% probability level.
However, after analyzing our ROC curve and confusion metrics, we decided
to lower our probability threshold.
Our ROC curve visualizes a general diagnostic of our model’s
performance. Based on our probability curve and confusion metrics, we
decided that a threshold of 25% is the best probability level for our
model to predict cells as flooded or not flooded. In other words, a 25%
probability threshold is where our model most accurately predicts
flooded and not flooded cells.
3.4. Cross Validation
Our cross validation plot shows similar accuracies across 100 tests,
making it a promising model to introduce ‘out-of-sample’ data like
DC.

LS0tCnRpdGxlOiAnQ1BMTiA2NzU6IEhvbWV3b3JrIDMnCmF1dGhvcjogIk1pbWkgVHJhbiAmIEphdmllciBGZXJuYW5kZXoiCmRhdGU6ICJBcHJpbCAzLCAyMDI0IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSxtZXNzYWdlID0gRkFMU0UsY2FjaGU9VFJVRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpvcHRpb25zKHNjaXBlbj05OTkpCmxpYnJhcnkoa25pdHIpCmBgYAoKIyAxLiBJbnRyb2R1Y3Rpb24KCkNsaW1hdGUgY2hhbmdlIGltcGFjdHMgc3VjaCBhcyBzZWEgbGV2ZWwgcmlzZSBhbmQgaW5jcmVhc2luZ2x5IHNldmVyZSBhbmQgZnJlcXVlbnQgd2VhdGhlciBldmVudHMgbGlrZSBoZWF2eSByYWlucyBleGFjZXJiYXRlIHByZXNlbnQgZmxvb2QgdGhyZWF0cy4gSWRlbnRpZnlpbmcgZmxvb2QgdnVsbmVyYWJsZSBhcmVhcyBhbmQgcHJlZGljdGluZyB3aGVyZSBmbG9vZGluZyBtYXkgb2NjdXIgaXMgaW50ZWdyYWwgdG8gcGxhbm5pbmcgZm9yIGEgY2xpbWF0ZS1jaGFuZ2VkIGZ1dHVyZS4gVGhlIGZvbGxvd2luZyByZXBvcnQgaXMgYSBwYXJ0IG9mIGFuIGVmZm9ydCB0byBkZXZlbG9wIGFuZCB0ZXN0IGEgcHJlZGljdGl2ZSBmbG9vZCBtb2RlbDogCgpXZSBoYXZlIGJlZW4gdGFza2VkIHdpdGggY3JlYXRpbmcgYSBtb2RlbCB0aGF0IHByZWRpY3RzIGFyZWFzIHZ1bG5lcmFibGUgdG8gZmxvb2RpbmcuIEluIG9yZGVyIHRvIGRvIHNvLCB3ZSBjaG9zZSBhbiBhcmVhIHdoZXJlIHdlIGFscmVhZHkgaGFkIHJlY29yZGVkIGZsb29kIGRhdGE6IENhbGdhcnksIEFsYmVydGEgKENBTikuIEluIGFkZGl0aW9uLCB3ZSBuZWVkZWQgdG8gY2hvb3NlIGEgY29tcGFyYWJsZSBjaXR5IHRvIENhbGdhcnksIG9uZSB0aGF0IGNvdWxkIHRlc3Qgb3VyIG1vZGVsLiBXZSBjaG9zZSBXYXNoaW5ndG9uIERDLiBCb3RoIENhbGdhcnkgYW5kIERDIGhhdmUgbGFyZ2Ugcml2ZXJzIHJ1bm5pbmcgdGhyb3VnaCB0aGUgY2l0aWVzIGFuZCBhcmUgbGFyZ2UgcG9wdWxhdGlvbiBjZW50ZXJzLiAKCkFmdGVyIGNob29zaW5nIG91ciBjaXRpZXMsIHdlIGNhbWUgdXAgd2l0aCBwb3RlbnRpYWwgZmFjdG9ycyB0aGF0IG1pZ2h0IGxlYWQgdG8gZmxvb2RpbmcuIFRob3NlIGZhY3RvcnMgYXJlOiAKCi0gRWxldmF0aW9uCgotIEltcGVydmlvdXMgU3VyZmFjZXMKCi0gUGFya3MKCi0gTG93IFBlcm1lYWJsZSBTb2lscyAoZS5nLiBjbGF5KQoKLSBXYXRlcmJvZGllcwoKRm9yIGVhY2ggZmFjdG9yLCB3ZSBjYW1lIHVwIHdpdGggYSBoeXBvdGhlc2lzOiAKCi0gRWxldmF0aW9uOiBJZiBhbiBhcmVhIGlzIGF0IGEgbG93IGVsZXZhdGlvbiwgaXQgd2lsbCBtb3N0IGxpa2VseSBmbG9vZC4KCi0gSW1wZXJ2aW91cyBTdXJmYWNlczogSWYgYW4gYXJlYSBoYXMgb3IgaXMgbWFkZSB1cCBvZiBtYW55IGltcGVydmlvdXMgc3VyZmFjZXMsIGl0IHdpbGwgbW9zdCBsaWtlbHkgZmxvb2QuCgotIFBhcmtzOiBJZiBhbiBhcmVhIGhhcyBvciBpcyBtYWRlIHVwIG9mIG1hbnkgZ3JlZW4gc3BhY2VzLCBpdCB3aWxsIG1vc3QgbGlrZWx5IG5vdCBmbG9vZC4gCgotIExvdyBQZXJtZWFibGUgU29pbHM6IElmIGFuIGFyZWEgaGFzIG9yIGlzIG1hZGUgdXAgb2YgbWFueSBsb3cgcGVybWVhYmxlIHNvaWxzLCBpdCB3aWxsIG1vc3QgbGlrZWx5IGZsb29kLgoKLSBXYXRlcmJvZGllczogSWYgYW4gYXJlYSBoYXMgb3IgaXMgbWFkZSB1cCBvZiBleGlzdGluZyB3YXRlcmJvZGllcywgaXQgd2lsbCBtb3N0IGxpa2VseSBmbG9vZC4gCgpUbyB0ZXN0IHRoZXNlIGh5cG90aGVzZXMgYW5kIGJ1aWxkIGEgcHJlZGljdGl2ZSBtb2RlbCwgd2UgY29uZHVjdGVkIGZlYXR1cmUgZW5naW5lZXJpbmcsIHNwYXRpYWwgbGFncywgYW5kIGEgZ2VuZXJhbGl6ZWQgbGluZWFyIG1vZGVsIChHTE0pLiBUaGUgZm9sbG93aW5nIHNlY3Rpb25zIGhpZ2hsaWdodCBvdXIga2V5IGZlYXR1cmVzLCBvdXIgcmVncmVzc2lvbiBtb2RlbCBzdW1tYXJ5LCBhbmQgb3VyIGZpbmFsIGZsb29kIHByZWRpY3Rpb25zIGZvciBDYWxnYXJ5IGFuZCBEQy4gCgpVbHRpbWF0ZWx5LCB0aGUgREMgcHJlZGljdGl2ZSBtb2RlbCBkaWQgbm90IHBlcmZvcm0gaG93IHdlIHdvdWxkIGhhdmUgaG9wZWQ7IGhvd2V2ZXIsIHdlIGZvdW5kIHByb21pc2luZyByZXN1bHRzIGluIG91ciBDYWxnYXJ5IG1vZGVsLiBUaGlzIGRyYXdzIHVzIHRvIGNvbmNsdWRlIHRoYXQgV2FzaGluZ3RvbiBEQyBtYXkgbm90IGhhdmUgYmVlbiBhIGdvb2QgZml0IGFzIGEgY29tcGFyaXNvbiBjaXR5LiBGb3IgZXhhbXBsZSwgd2hpbGUgQ2FsZ2FyeSBpcyBmYXIgbW9yZSBpbmxhbmQgYW5kIGhhcyBhIGRyaWVyIGNsaW1hdGUsIERDIGlzIHJlbGF0aXZlbHkgY2xvc2UgdG8gdGhlIENoZXNhcGVha2UgQmF5IGFuZCB0ZW5kcyB0byBiZSBtb3JlIGh1bWlkLiBPdGhlciBVUyBjaXRpZXMgdGhhdCBtaWdodCBoYXZlIGJlZW4gbW9yZSBjb21wYXJhYmxlIHRvIENhbGdhcnkgY291bGQgaGF2ZSBiZWVuIERlbnZlciwgQ08sIG9yIFNhbHQgTGFrZSBDaXR5LCBVVC4gCgpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQojIFNldCBVcAojIGluc3RhbGwKb3B0aW9ucyhyZXBvcyA9ICJodHRwczovL2Nsb3VkLnItcHJvamVjdC5vcmcvIikKaW5zdGFsbC5wYWNrYWdlcygnY2FyZXQnKQppbnN0YWxsLnBhY2thZ2VzKCdwc2NsJykKaW5zdGFsbC5wYWNrYWdlcygncGxvdFJPQycpCmluc3RhbGwucGFja2FnZXMoJ3BST0MnKQppbnN0YWxsLnBhY2thZ2VzKCdzZicpCmluc3RhbGwucGFja2FnZXMoJ3RpZHl2ZXJzZScpCmluc3RhbGwucGFja2FnZXMoJ2tuaXRyJykKaW5zdGFsbC5wYWNrYWdlcygna2FibGVFeHRyYScpCmluc3RhbGwucGFja2FnZXMoJ3RpZ3JpcycpCmluc3RhbGwucGFja2FnZXMoJ3ZpcmlkaXMnKQppbnN0YWxsLnBhY2thZ2VzKCdnc3RhdCcpCmluc3RhbGwucGFja2FnZXMoJ3NwJykKaW5zdGFsbC5wYWNrYWdlcygncmFzdGVyJykKaW5zdGFsbC5wYWNrYWdlcygnc3BhdGlhbHJlZycpCmluc3RhbGwucGFja2FnZXMoJ3RpZHlyJykKaW5zdGFsbC5wYWNrYWdlcygnZHBseXInKQppbnN0YWxsLnBhY2thZ2VzKCdnZ3Bsb3QyJykKCiMgbGlicmFyaWVzCmxpYnJhcnkoY2FyZXQpCmxpYnJhcnkocHNjbCkKbGlicmFyeShwbG90Uk9DKQpsaWJyYXJ5KHBST0MpCmxpYnJhcnkoc2YpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkodGlncmlzKQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkoZ3N0YXQpCmxpYnJhcnkoc3ApCmxpYnJhcnkocmFzdGVyKQpsaWJyYXJ5KHNwZGVwKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCgoKIyBTZXQgdXAKCm1hcFRoZW1lIDwtIHRoZW1lKHBsb3QudGl0bGUgPWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgICAgICAgICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTgpLAogICAgICAgICAgICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYpLAogICAgICAgICAgICAgICAgICBheGlzLmxpbmU9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICBwYW5lbC5ib3JkZXI9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICBwYW5lbC5ncmlkLm1ham9yPWVsZW1lbnRfbGluZShjb2xvdXIgPSAndHJhbnNwYXJlbnQnKSwKICAgICAgICAgICAgICAgICAgcGFuZWwuZ3JpZC5taW5vcj1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAidmVydGljYWwiLCAKICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwKICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMSwgMSwgMSwgMSwgJ2NtJyksCiAgICAgICAgICAgICAgICAgIGxlZ2VuZC5rZXkuaGVpZ2h0ID0gdW5pdCgxLCAiY20iKSwgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMC4yLCAiY20iKSkKCnBsb3RUaGVtZSA8LSB0aGVtZSgKICBwbG90LnRpdGxlID1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTgpLAogIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gNiksCiAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgIyBTZXQgdGhlIGVudGlyZSBjaGFydCByZWdpb24gdG8gYmxhbmsKICBwYW5lbC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwKICBwbG90LmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLAogICNwYW5lbC5ib3JkZXI9ZWxlbWVudF9yZWN0KGNvbG91cj0iI0YwRjBGMCIpLAogICMgRm9ybWF0IHRoZSBncmlkCiAgcGFuZWwuZ3JpZC5tYWpvcj1lbGVtZW50X2xpbmUoY29sb3VyPSIjRDBEMEQwIixzaXplPS43NSksCiAgYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCkpCgpgYGAKCiMgMi4gTWFwcyBvZiBWYXJpYWJsZXMKCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9CiMgc2V0IHVwIGZvciBtYXBzCmNhbF9maXNoIDwtIHN0X3JlYWQoIn4vRGVza3RvcC9tb2RlbC9maXNobmV0X2NsaXAyIiwgcHJvbW90ZV90b19tdWx0aSA9IEZBTFNFKQoKIyBJbXBvcnQgQ2FsZ2FyeSBkYXRhIGZlYXR1cmVzCkNBX1NvaWwgPC0gc3RfcmVhZCgifi9EZXNrdG9wL21vZGVsL3RhYmxlcy9DQV9Tb2lsLnhsc3giKQpDQV9QYXJrcyA8LSBzdF9yZWFkKCJ+L0Rlc2t0b3AvbW9kZWwvdGFibGVzL0NBX1BhcmtzLnhsc3giKQpDQV9JbXBlcnZpb3VzIDwtIHN0X3JlYWQoIn4vRGVza3RvcC9tb2RlbC90YWJsZXMvQ0FfSW1wZXJ2aW91cy54bHN4IikKQ0FfRWxldmF0aW9uIDwtIHN0X3JlYWQoIn4vRGVza3RvcC9tb2RlbC90YWJsZXMvQ0FfRWxldmF0aW9uLnhsc3giKQpDQV9XYXRlcmJvZGllcyA8LSBzdF9yZWFkKCJ+L0Rlc2t0b3AvbW9kZWwvdGFibGVzL0NBX1dhdGVyYm9kaWVzLnhsc3giKQoKIyBSZW5hbWluZyBhbmQgY2xlYW5pbmcgZGF0YQpjYWxfZmlzaCA8LSBjYWxfZmlzaCAlPiUKICByZW5hbWUoY2VsbCA9IE9CSkVDVElEXzEpCgpDQV9Tb2lsIDwtIENBX1NvaWwgJT4lCiAgcmVuYW1lKAogICAgY2VsbCA9IE9CSkVDVElEXzEsCiAgICBzb2lsX3N1bSA9IFNVTSwKICAgICkgJT4lCiAgZHBseXI6OnNlbGVjdCgtT0JKRUNUSUQsIC1DT1VOVCwgLUFSRUEgKQoKCkNBX1BhcmtzIDwtIENBX1BhcmtzICU+JQogIHJlbmFtZSgKICAgIGNlbGwgPSBPQkpFQ1RJRF8xLAogICAgcGFya19zdW0gPSBTVU0sCiAgICBwYXJrX21lYW4gPSBNRUFOLAogICAgcGFya19jb3VudCA9IENPVU5UICAKICAgICkgJT4lCiAgIyBSZW1vdmUgc3BlY2lmaWMgY29sdW1ucwogIGRwbHlyOjpzZWxlY3QoLU9CSkVDVElELCAtQVJFQSwgLU1JTiwgLU1BWCwgLVJBTkdFLCAtU1RELCAtVkFSSUVUWSwgLU1BSk9SSVRZLCAtTUFKT1JJVFlfQ09VTlQsIC1NQUpPUklUWV9QRVJDRU5ULCAtTUlOT1JJVFksLU1JTk9SSVRZX0NPVU5ULCAtTUlOT1JJVFlfUEVSQ0VOVCwgLU1FRElBTiwgLVBDVDkwICkKICAKCkNBX0ltcGVydmlvdXMgPC0gQ0FfSW1wZXJ2aW91cyAlPiUKICByZW5hbWUoCiAgICBjZWxsID0gT0JKRUNUSURfMSwKICAgIGltcGVydmlvdXNfbWVhbiA9IE1FQU4sCiAgICBJbXBlcnZpb3VzX21ham9yaXR5ID0gSW1wZXJ2aW91cwogICAgKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1PQkpFQ1RJRCwgLUNPVU5ULCAtQVJFQSwgLU1BWCwgLU1JTiwgLVJBTkdFLCAtU1VNICkKCgpDQV9XYXRlcmJvZGllcyA8LSBDQV9XYXRlcmJvZGllcyAlPiUKICByZW5hbWUoCiAgICBjZWxsID0gT0JKRUNUSURfMSwKICAgIFdhdGVyYm9kaWVzX21lYW4gPSBNRUFOLAogICkgJT4lCiAgZHBseXI6OnNlbGVjdCgtT0JKRUNUSUQsIC1BUkVBLCAtQ09VTlQsIC0gU1VNLCAtTUlOLCAtTUFYLCAtUkFOR0UsIC1TVEQsIC1WQVJJRVRZLCAtTUFKT1JJVFksIC1NQUpPUklUWV9DT1VOVCwgLU1BSk9SSVRZX1BFUkNFTlQsIC1NSU5PUklUWSwtTUlOT1JJVFlfQ09VTlQsIC1NSU5PUklUWV9QRVJDRU5ULCAtTUVESUFOLCAtUENUOTAgKQoKQ0FfRWxldmF0aW9uIDwtIENBX0VsZXZhdGlvbiAlPiUKICByZW5hbWUoCiAgICBjZWxsID0gT0JKRUNUSURfMSwKICAgIGVsZXZhdGlvbl9tYXggPSBNQVgsCiAgICBlbGV2YXRpb25fbWluID0gTUlOLAogICAgZWxldmF0aW9uX21lYW4gPSBNRUFOLAogICAgKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1PQkpFQ1RJRCwgLUNPVU5ULCAtQVJFQSwgLVJBTkdFLCAtU1RELCAtU1VNICkKCiMgam9pbmluZyBDU1ZzIHRvIENhbGdhcnkgZmlzaG5ldCBieSAiY2VsbCIgbnVtYmVyCmpvaW5lZF9maXNoY2FsIDwtIGNhbF9maXNoICU+JQogIGxlZnRfam9pbihDQV9Tb2lsLCBieSA9ICJjZWxsIikgJT4lCiAgbGVmdF9qb2luKENBX1BhcmtzLCBieSA9ICJjZWxsIikgJT4lCiAgbGVmdF9qb2luKENBX0ltcGVydmlvdXMsIGJ5ID0gImNlbGwiKSAlPiUKICBsZWZ0X2pvaW4oQ0FfRWxldmF0aW9uLCBieSA9ICJjZWxsIikgJT4lCiAgbGVmdF9qb2luKENBX1dhdGVyYm9kaWVzLCBieSA9ICJjZWxsIikgCmBgYAoKVG8gYmVnaW4gb3VyIG1vZGVsaW5nIHByb2Nlc3MgaW4gUiwgd2UgdXBsb2FkZWQgb3VyIENhbGdhcnkgZmlzaG5ldCBhbmQgb3VyIHByZWRpY3RpdmUgZmFjdG9ycyBvciAidmFyaWFibGVzIjogZWxldmF0aW9uLCBpbXBlcnZpb3VzIHN1cmZhY2VzLCBsb3cgcGVybWVhYmxlIHNvaWxzLCBwYXJrcywgYW5kIHdhdGVyYm9kaWVzLiBBIGZpc2huZXQgaXMgYSBncmlkIG1hZGUgdXAgb2Ygc3F1YXJlcy0tbGlrZSBhIG5ldC0tY2FsbGVkICJjZWxscyIgb3ZlcmxhaWQgb24gc29tZSBnZW9ncmFwaGljIGFyZWEuIEZpc2huZXRzIGhhdmUgbWFueSB1c2VzLCBidXQgb3VyIG1haW4gcHVycG9zZSB3YXMgdG8gdXNlIHRoZSBmaXNobmV0IGZvciBzcGF0aWFsIGFuYWx5c2lzIGFuZCBtb2RlbGluZy4KClRoZSBmaXNobmV0IGFsbG93cyB1cyB0byBtZWFzdXJlIHRoZSBwcmVzZW5jZSBvciAiaG93IG11Y2giIG9mIGEgdmFyaWFibGUgaXMgZm91bmQgd2l0aGluIGEgY2VydGFpbiBhcmVhIG9yIGNlbGwuIEJ5IHJ1bm5pbmcgem9uYWwgc3RhdGlzdGljcyBmb3IgZWFjaCB2YXJpYWJsZSBpbiBBcmNHSVMsIHdlIGRldGVybWluZWQgd2hhdCB3YXMgdGhlIGJlc3QgbWVhc3VyZSBmb3IgZWFjaCB2YXJpYWJsZToKCi0gRWxldmF0aW9uOiBXZSBkZWNpZGVkIHRvIG1lYXN1cmUgdGhlIGxvd2VzdCBwb2ludCBvZiBlYWNoIGNlbGwsIG9yIHRoZSBtaW5pbXVtIHZhbHVlIG9mIGVsZXZhdGlvbi4gV2Ugb3BlcmF0ZWQgdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgbG93ZXN0IHBvaW50IG9mIGV2ZXJ5IGNlbGwgaXMgd2hlcmUgbW9zdCB3YXRlciB3aXRoaW4gdGhlIGNlbGwgd2lsbCBnYXRoZXIuIAoKLSBJbXBlcnZpb3VzIFN1cmZhY2VzOiBJZiB0aGUgbWVhbiBjb3VudCBvZiAiaW1wZXJ2aW91cyBzdXJmYWNlIiBwaXhlbHMgd2l0aGluIGEgY2VsbCB3YXMgZXF1YWwgdG8gb3IgZXhjZWVkZWQgMjUlIG9mIGEgY2VsbCwgdGhlbiB0aGUgY2VsbCBwb3NzZXNzZWQgaW1wZXJ2aW91cyBzdXJmYWNlcy4gCgotIExvdyBQZXJtZWFibGUgU29pbHM6IElmIHRoZSBtZWFuIGNvdW50IG9mICJsb3cgcGVybWVhYmxlIHNvaWwiIHBpeGVscyB3aXRoaW4gYSBjZWxsIHdhcyBlcXVhbCB0byBvciBleGNlZWRlZCAyNSUgb2YgYSBjZWxsLCB0aGVuIHRoZSBjZWxsIHBvc3Nlc3NlZCBsb3cgcGVybWVhYmxlIHNvaWxzLiAgCgotIFBhcmtzOiBJZiB0aGUgbWVhbiBjb3VudCBvZiAicGFyayIgcGl4ZWxzIHdpdGhpbiBhIGNlbGwgd2FzIGVxdWFsIHRvIG9yIGV4Y2VlZGVkIDI1JSwgdGhlbiB0aGUgY2VsbCBwb3NzZXNzZWQgYSBwYXJrLiAKCi0gV2F0ZXJib2RpZXM6IElmIHRoZSBtZWFuIGNvdW50IG9mICJ3YXRlcmJvZGllcyIgcGl4ZWxzIHdpdGhpbiBhIGNlbGwgd2FzIGVxdWFsIHRvIG9yIGV4Y2VlZGVkIDI1JSwgdGhlbiB0aGUgY2VsbCBwb3NzZXNzZWQgYSB3YXRlcmJvZHkuCgpGb3VyIG9mIHRoZXNlIG1hcHMgYXJlIHZpc3VhbGl6ZWQgaW4gdGhlIG5leHQgc2VjdGlvbi4KCiMjIDIuMS4gSW1wZXJ2aW91cyBTdXJmYWNlcwpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcycsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQogIGdncGxvdCgpICsKICBnZW9tX3NmKGRhdGEgPSBqb2luZWRfZmlzaGNhbCwgYWVzKGZpbGwgPSBJbXBlcnZpb3VzX21ham9yaXR5KSkgKyAKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJsaWdodGdyZXkiLCBoaWdoID0gInJlZCIpICsgIyBjb2xvcgogIGxhYnMoZmlsbCA9ICJJbXBlcnZpb3VzIFN1cmZhY2UgUHJlc2VudCIsIHRpdGxlID0gIkltcGVydmlvdXMgU3VyZmFjZSIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyAyLjIuIFBhcmtzCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9CmdncGxvdCgpICsKICBnZW9tX3NmKGRhdGEgPSBqb2luZWRfZmlzaGNhbCwgYWVzKGZpbGwgPSBQYXJrc19NYWpvcml0eSkpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJsaWdodGdyZXkiLCBoaWdoID0gImRhcmtncmVlbiIpICsKICBsYWJzKGZpbGwgPSAiUGFya3MgUHJlc2VudCIsIHRpdGxlID0gIlBhcmtzIikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCiMjIDIuMy4gTG93IFBlcm1lYWJsZSBTb2lscwpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcycsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQpnZ3Bsb3QoKSArCiAgZ2VvbV9zZihkYXRhID0gam9pbmVkX2Zpc2hjYWwsIGFlcyhmaWxsID0gTG93X3Blcm1lYWJpbGl0eSkpICsgIAogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImxpZ2h0Z3JleSIsIGhpZ2ggPSAib3JhbmdlIikgKyAKICBsYWJzKGZpbGwgPSAiTG93IFBlcm1lYWJpbGl0eSBTb2lscyBQcmVzZW50IiwgdGl0bGUgPSAiTG93IFBlcm1lYWJpbGl0eSBTb2lscyIpICsgCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKIyMgMi40LiBFeGlzdGluZyBXYXRlcmJvZGllcwpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcycsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQpnZ3Bsb3QoKSArCiAgZ2VvbV9zZihkYXRhID0gam9pbmVkX2Zpc2hjYWwsIGFlcyhmaWxsID0gV2F0ZXJfbWFqb3JpdHkpKSArIAogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImxpZ2h0Z3JleSIsIGhpZ2ggPSAiZGFya2JsdWUiKSArIAogIGxhYnMoZmlsbCA9ICJXYXRlcmJvZHkgUHJlc2VudCIsIHRpdGxlID0gIldhdGVyYm9kaWVzIikgKyAKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIDMuIE1vZGVsIFZhbGlkYXRpb24KCiMjIDMuMS4gRXhwbG9yYXRvcnkgQW5hbHlzaXM6IFN1bW1hcnkgVGFibGUKYGBgIHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSAnaGlkZScsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQojc2V0IHVwCiMgaW1wb3J0aW5nIGludW5kYXRpb24gcmFzdGVyCiMgU3BlY2lmeSB0aGUgVVJMIG9mIHRoZSBUSUZGIGZpbGUKdGlmZl91cmwgPC0gImh0dHBzOi8vZ2l0aHViLmNvbS9mZHpqYXZpZXIvQ1BMTjY3NS9yYXcvbWFpbi9EYXRhL3Jhc3RlcnMvSW51bmRhdGlvbl9yZS50aWYiCgojIFJlYWQgdGhlIFRJRkYgZmlsZSBpbnRvIFIgYXMgYSByYXN0ZXIgb2JqZWN0CmludW5kYXRpb24gPC0gcmFzdGVyKHRpZmZfdXJsKQppbnVuZGF0aW9uCmBgYCAKCmBgYCB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQojIHVwbG9hZCBpbnVuZGF0aW9uIHpvbmFsIHN0YXRpc3RpY3MKaW51X3pvbmFsIDwtIHN0X3JlYWQoIn4vRGVza3RvcC9tb2RlbC90YWJsZXMvWm9uYWxTdF9JbnVuZGF0aW9uX3YyLnhsc3giKSAlPiUKICByZW5hbWUoCiAgICBjZWxsID0gT0JKRUNUSURfMQogICkgJT4lCiAgZHBseXI6OnNlbGVjdCgtT0JKRUNUSUQsIC1BUkVBLCAtQ09VTlQsIC0gU1VNKQoKIyBhdHRhY2ggdG8gZmlzaG5ldApjYWxfaW51X2Zpc2ggPC0gam9pbmVkX2Zpc2hjYWwgJT4lCiAgbGVmdF9qb2luKGludV96b25hbCwgYnkgPSAiY2VsbCIpIAoKaW51bmRhdGlvblBsb3RWYXJpYWJsZXMgPC0gCiAgY2FsX2ludV9maXNoICU+JQogIGFzLmRhdGEuZnJhbWUoKSAlPiUKICBkcGx5cjo6c2VsZWN0KEZsb29kZWQsTG93X3Blcm1lYWJpbGl0eSwgUGFya3NfTWFqb3JpdHksIEltcGVydmlvdXNfbWFqb3JpdHksIGVsZXZhdGlvbl9taW4sIFdhdGVyX21ham9yaXR5KSAlPiUKICBnYXRoZXIodmFyaWFibGUsIHZhbHVlLCAtRmxvb2RlZCkKCiMgUGxvdHRpbmcgVmFyaWFibGVzCnRlc3Rfc3VtbWFyeSA8LSBpbnVuZGF0aW9uUGxvdFZhcmlhYmxlcyAlPiUKICBncm91cF9ieShGbG9vZGVkLCB2YXJpYWJsZSkgJT4lCiAgc3VtbWFyaXplKG1lYW4gPSBtZWFuKHZhbHVlKSkKCmdncGxvdCh0ZXN0X3N1bW1hcnksIGFlcyh4ID0gYXMuZmFjdG9yKEZsb29kZWQpLCB5ID0gbWVhbiwgZmlsbCA9IGFzLmZhY3RvcihGbG9vZGVkKSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgZmFjZXRfd3JhcCh+IHZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImRhcmtibHVlIiwgImRhcmtncmVlbiIpLAogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk5vdCBGbG9vZGVkIiwgIkZsb29kZWQiKSwKICAgICAgICAgICAgICAgICAgICBuYW1lID0gIiIpICsKICBsYWJzKHggPSAiRmxvb2RlZCIsIHkgPSAiVmFsdWUiKQpgYGAKClRoZSBzdW1tYXJ5IHRhYmxlIHNob3dzIHVzIHNvbWUgaW50ZXJlc3RpbmcgYXNwZWN0cyBvZiBvdXIgbW9kZWwuIEZvciBleGFtcGxlLCBvdXIgaHlwb3RoZXNpcyBjb25jZXJuaW5nIGxvdyBlbGV2YXRpb24gd2FzIHRoYXQgY2VsbHMgd2l0aCBsb3cgZWxldmF0aW9uIGFyZSBtb3JlIGxpa2VseSB0byBmbG9vZC4gSG93ZXZlciwgdGhlIHN1bW1hcnkgdGFibGUgc2hvd3MgdGhhdCBvdXQgb2YgdGhlIHRvdGFsIGNlbGxzIHdpdGggbG93IGVsZXZhdGlvbiwgbWFueSBkaWQgbm90IGZsb29kLiBUaGUgc2FtZSBpcyBzYWlkIGZvciBsb3cgcGVybWVhYmxlIHNvaWxzIGFuZCBpbXBlcnZpb3VzIHN1cmZhY2VzLiBXZSBwcmVkaWN0ZWQgdGhhdCBhcmVhcyB3aXRoIGxvdyBwZXJtZWFiaWxpdHkgb3IgaW1wZXJtZWFiaWxpdHkgd2VyZSBtb3JlIGxpa2VseSB0byBmbG9vZCwgYnV0IHRoZSBzdW1tYXJ5IHRhYmxlIHNob3dzIHRoZSBvcHBvc2l0ZSB3YXMgdHJ1ZS4gCgpGdXJ0aGVybW9yZSwgb3VyIHByZWRpY3Rpb24gY29uY2VybmluZyBwYXJrcyBmb2xsb3dlZCB0aGF0IGNlbGxzIHdpdGggcGFya3Mgd2VyZSBsZXNzIGxpa2VseSB0byBmbG9vZCwgYnV0IHRoZSBzdW1tYXJ5IHRhYmxlIHNob3dzIHRoYXQgY2VsbHMgd2l0aCBwYXJrcyB3ZXJlIGFjdHVhbGx5IG1vcmUgbGlrZWx5IHRvIGZsb29kLiAKCk91ciBzdW1tYXJ5IHRhYmxlLCBob3dldmVyLCBtYXkgYmUgdGVsbGluZyB1cyBhIHBvc2l0aXZlIHN0b3J5OiB3aGF0IGRvIHdlIGtub3cgYWJvdXQgQ2FsZ2FyeSdzIHN0b3Jtd2F0ZXIgaW5mcmFzdHJ1Y3R1cmU/IElmIENhbGdhcnkgaGFzIGVmZmVjdGl2ZSBzdG9ybXdhdGVyIGluZnJhc3RydWN0dXJlLCB0aGVuIHRoaXMgbWF5IGV4cGxhaW4gd2h5IGFyZWFzIG9mIGxvdyBlbGV2YXRpb24gYW5kIHBhcmtzIGFyZSBmbG9vZGVkIHdoaWxlIGFyZWFzIHdpdGggaW1wZXJ2aW91cyBzdXJmYWNlcyBhbmQgc29pbHMgYXJlIG5vdC4gRm9yIGV4YW1wbGUsIGl0IGlzIHN0YW5kYXJkIGdyZWVuIHN0b3Jtd2F0ZXIgaW5mcmFzdHJ1Y3R1cmUgcHJhY3RpY2UgdG8gdXNlIHBhcmtzIGFzIG11bHRpLXVzZSBzcGFjZXM6IGR1cmluZyBoZWF2eSByYWlucywgcGFya3MgY2FuIHNlcnZlIGFzIHN0b3Jtd2F0ZXIgaG9sZGluZyBiYXNpbnMgYW5kL29yIGhlbHAgYWJzb3JiIGV4Y2VzcyB3YXRlci4gSW4gdGhpcyBzZW5zZSwgcGFya3MgYXJlICplbmdpbmVlcmVkKiBvciAqZGVzaWduZWQqIHRvIGJlIGZsb29kZWQuICAKCkFkZGl0aW9uYWxseSwgaWYgQ2FsZ2FyeSdzIHN0b3Jtd2F0ZXIgaW5mcmFzdHJ1Y3R1cmUgaXMgZWZmZWN0aXZlLCB0aGVuIHdhdGVyIHNob3VsZCBiZSByZWRpcmVjdGVkIGF3YXkgZnJvbSB1cmJhbiBhcmVhcy4gU3Rvcm13YXRlciBpbmZyYXN0cnVjdHVyZSBpcyBvZnRlbiBwYWlyZWQgd2l0aCBjaXR5J3Mgd2F0ZXIgc3lzdGVtcywgYW5kIG1hbnkgY2l0aWVzLS1pbmNsdWRpbmcgQ2FsZ2FyeS0tdXRpbGl6ZSBncmF2aXR5IHN5c3RlbXMsIHdoaWNoIHRha2UgYWR2YW50YWdlIG9mIGdyYXZpdHkgYXMgYSBmb3JjZSB0byBkaXJlY3Qgd2F0ZXIgZmxvdyAiZG93bndhcmRzIiBvciB0b3dhcmRzIGFyZWFzIG9mIGxvdyBlbGV2YXRpb24gKG9mdGVuIHdhdGVyYm9kaWVzIG9yIHdhdGVyIHRyZWF0bWVudCBwbGFudHMpLgoKQWx0aG91Z2ggb3VyIHN1bW1hcnkgdGFibGUgc2hvd3MgdGhhdCBvdXIgdmFyaWFibGVzIGFyZSBub3QgbmVjZXNzYXJpbHkgZm9sbG93aW5nIG91ciBhc3N1bXB0aW9ucywgdGhleSBzdGlsbCBtYXkgYmUgaW5kaWNhdGl2ZSBvZiBhIHJlbGF0aW9uc2hpcCwgYW5kIGV2ZW4gYSBwb3NpdGl2ZSBzdG9yeSEgCgpgYGAge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9ICdoaWRlJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9IApjYV9pbnVuZGF0aW9uIDwtIGNhbF9pbnVfZmlzaCAlPiUKICBkcGx5cjo6c2VsZWN0KGNlbGwsIEZsb29kZWQsIExvd19wZXJtZWFiaWxpdHksIFBhcmtzX01ham9yaXR5LCBJbXBlcnZpb3VzX21ham9yaXR5LCBlbGV2YXRpb25fbWluLCBXYXRlcl9tYWpvcml0eSkKCiMgcGFydGl0aW9uIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHMKc2V0LnNlZWQoMzQ1NikKdHJhaW5JbmRleCA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKGNhX2ludW5kYXRpb24kRmxvb2RlZCwgcCA9IC43MCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVzID0gMSkKCmZsb29kVHJhaW4gPC0gY2FfaW51bmRhdGlvblsgdHJhaW5JbmRleCxdCmZsb29kVGVzdCAgPC0gY2FfaW51bmRhdGlvblstdHJhaW5JbmRleCxdCmBgYAoKIyMgMy4yLiBMb2dpc3RpYyBSZWdyZXNzaW9uIE1vZGVsIFN1bW1hcnkKCk5leHQsIHdlIHJ1biBhIHJlZ3Jlc3Npb24gc3VtbWFyeSB0byBkZXRlcm1pbmUgb3VyIHZhcmlhYmxlcyBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuIEJhc2VkIG9uIG91ciBwLXZhbHVlcyBhbmQgY29lZmZpY2llbnQgZXN0aW1hdGVzLCBvdXIgcmVncmVzc2lvbiBzdW1tYXJ5IHNob3dzIHRoYXQgb3VyIHZhcmlhYmxlcyBhcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCwgbWVhbmluZyB0aGVyZSBpcyBzb21lIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGZsb29kaW5nIGFuZCB0aGUgcHJlc2VuY2Ugb2Ygb3VyIHZhcmlhYmxlcy4gCgpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CmZsb29kTW9kZWwgPC0gZ2xtKEZsb29kZWQgfiAuLCAKICAgICAgICAgICAgICAgICAgICAgZmFtaWx5PSJiaW5vbWlhbCIobGluaz0ibG9naXQiKSwgZGF0YSA9IGZsb29kVHJhaW4gJT4lCiAgICAgICAgICAgICAgICAgICAgICAgYXMuZGF0YS5mcmFtZSgpICU+JQogICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoLWdlb21ldHJ5LCAtY2VsbCkpCnN1bW1hcnkoZmxvb2RNb2RlbCkKYGBgCgojIyAzLjMuIENvbmZ1c2lvbiBNZXRyaWNzICYgUk9DIEN1cnZlCgpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQojIHRlc3Rwcm9icyBzZXR1cApjbGFzc1Byb2JzIDwtIHByZWRpY3QoZmxvb2RNb2RlbCwgZmxvb2RUZXN0LCB0eXBlPSJyZXNwb25zZSIpCgpoaXN0KGNsYXNzUHJvYnMpCiAgCnRlc3RQcm9icyA8LSBkYXRhLmZyYW1lKG9icyA9IGFzLm51bWVyaWMoZmxvb2RUZXN0JEZsb29kZWQpLAogICAgICAgICAgICAgICAgICAgICAgICBwcmVkID0gY2xhc3NQcm9icykKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcycsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQojIENvbmZ1c2lvbiBtYXRyaXgKdGVzdFByb2JzJHByZWRDbGFzcyAgPSBpZmVsc2UodGVzdFByb2JzJHByZWQgPiAuMjUgLDEsMCkKCmNhcmV0Ojpjb25mdXNpb25NYXRyaXgocmVmZXJlbmNlID0gYXMuZmFjdG9yKHRlc3RQcm9icyRvYnMpLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gYXMuZmFjdG9yKHRlc3RQcm9icyRwcmVkQ2xhc3MpLCAKICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZSA9ICIxIikKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIENvbmZ1c2lvbiBNYXRyaXgsIG91ciBtb2RlbCBydW5zIGF0IGFib3V0IGFuIDgyJSBhY2N1cmFjeSByYXRlIGFuZCBpcyBiZXN0IGF0IHByZWRpY3Rpbmcgd2hpY2ggY2VsbHMgYXJlIG5vdCBmbG9vZGVkLCBidXQgaXMgbGVzcyBhY2N1cmF0ZSBhdCBwcmVkaWN0aW5nIHdoaWNoIGNlbGxzIHdpbGwgZmxvb2QuIAoKRm9yIGV4YW1wbGUsIHRoZSBDb25mdXNpb24gTWF0cml4IHNob3dzIHRoYXQgb3VyIG1vZGVsIHByZWRpY3RlZCA5MDMgY2VsbHMgd291bGQgbm90IGZsb29kLiBPdXQgb2YgdGhvc2UgOTAzIGNlbGxzLCA3NjYgY2VsbHMgd2VyZSBwcmVkaWN0ZWQgdG8gbm90IGZsb29kIGFuZCBpbiByZWFsaXR5LCBkaWQgbm90IGZsb29kIGJhc2VkIG9mZiBvZiBvdXIgcmVjb3JkZWQgQ2FsZ2FyeSBmbG9vZCBkYXRhOyBob3dldmVyLCAxMzcgb2YgdGhlIGNlbGxzIHByZWRpY3RlZCB0byBub3QgZmxvb2QsIGFjdHVhbGx5IGRpZCBmbG9vZC4gT24gdGhlIG90aGVyIGhhbmQsIG91dCBvZiAxNjcgY2VsbHMsIG91ciBtb2RlbCBjb3JyZWN0bHkgcHJlZGljdGVkIDExMSBjZWxscyB3b3VsZCBmbG9vZCwgYnV0IGluY29ycmVjdGx5IHByZWRpY3RlZCA1NiBjZWxscyB3b3VsZCBmbG9vZC4gSW4gYWN0dWFsaXR5LCB0aG9zZSA1NiBjZWxscyBkaWQgbm90IGZsb29kLiAKClRoaXMgaW5mb3JtYXRpb24gaXMgc3VtbWVkIHVwIGluIHRoZSBzZW5zaXRpdml0eSBhbmQgc3BlY2lmaWNpdHkgbWVhc3VyZSBvZiBvdXIgbW9kZWwuIFRoZSBDb25mdXNpb24gTWF0cml4IHNob3dzIHRoYXQgb3VyIG1vZGVsJ3Mgc2Vuc2l0aXZpdHksIHRoYXQgaXMsIGl0cyBhY2N1cmFjeSBpbiBwcmVkaWN0aW5nIGNlbGxzIHRoYXQgKip3aWxsKiogZmxvb2QgaXMgYWJvdXQgNjclOyBvdXIgbW9kZWwncyBzcGVjaWZpY2l0eSwgdGhhdCBpcywgaXRzIGFjY3VyYWN5IGluIHByZWRpY3RpbmcgY2VsbHMgdGhhdCAqKndpbGwgbm90KiogZmxvb2QgaXMgYWJvdXQgODUlLiAKCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9CiMgUk9DIEN1cnZlcyBmb3IgdGhlIHRlc3RpbmcgZGF0YXNldApnZ3Bsb3QodGVzdFByb2JzLCBhZXMoZCA9IG9icywgbSA9IHByZWQpKSArIAogIGdlb21fcm9jKG4uY3V0cyA9IDUwLCBsYWJlbHMgPSBGQUxTRSkgKyAKICBzdHlsZV9yb2ModGhlbWUgPSB0aGVtZV9ncmV5KSArCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBpbnRlcmNlcHQgPSAwLCBzaXplID0gMS41LCBjb2xvciA9ICdncmV5JykKCmF1Yyh0ZXN0UHJvYnMkb2JzLCB0ZXN0UHJvYnMkcHJlZCkKYGBgCgpJbml0aWFsbHksIHdlIHJhbiBvdXIgY29uZnVzaW9uIG1hdHJpeCB3aXRoIGEgNTAlIHByb2JhYmlsaXR5IGxldmVsLiBIb3dldmVyLCBhZnRlciBhbmFseXppbmcgb3VyIFJPQyBjdXJ2ZSBhbmQgY29uZnVzaW9uIG1ldHJpY3MsIHdlIGRlY2lkZWQgdG8gbG93ZXIgb3VyIHByb2JhYmlsaXR5IHRocmVzaG9sZC4gCgpPdXIgUk9DIGN1cnZlIHZpc3VhbGl6ZXMgYSBnZW5lcmFsIGRpYWdub3N0aWMgb2Ygb3VyIG1vZGVsJ3MgcGVyZm9ybWFuY2UuIEJhc2VkIG9uIG91ciBwcm9iYWJpbGl0eSBjdXJ2ZSBhbmQgY29uZnVzaW9uIG1ldHJpY3MsIHdlIGRlY2lkZWQgdGhhdCBhIHRocmVzaG9sZCBvZiAyNSUgaXMgdGhlIGJlc3QgcHJvYmFiaWxpdHkgbGV2ZWwgZm9yIG91ciBtb2RlbCB0byBwcmVkaWN0IGNlbGxzIGFzIGZsb29kZWQgb3Igbm90IGZsb29kZWQuIEluIG90aGVyIHdvcmRzLCBhIDI1JSBwcm9iYWJpbGl0eSB0aHJlc2hvbGQgaXMgd2hlcmUgb3VyIG1vZGVsIG1vc3QgYWNjdXJhdGVseSBwcmVkaWN0cyBmbG9vZGVkIGFuZCBub3QgZmxvb2RlZCBjZWxscy4gCgojIyAzLjQuIENyb3NzIFZhbGlkYXRpb24KCk91ciBjcm9zcyB2YWxpZGF0aW9uIHBsb3Qgc2hvd3Mgc2ltaWxhciBhY2N1cmFjaWVzIGFjcm9zcyAxMDAgdGVzdHMsIG1ha2luZyBpdCBhIHByb21pc2luZyBtb2RlbCB0byBpbnRyb2R1Y2UgJ291dC1vZi1zYW1wbGUnIGRhdGEgbGlrZSBEQy4KCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9CiNDcm9zcyBWYWxpZGF0aW9uCmN0cmwgPC0gdHJhaW5Db250cm9sKG1ldGhvZCA9ICJjdiIsIAogICAgICAgICAgICAgICAgICAgICBudW1iZXIgPSAxMDAsIAogICAgICAgICAgICAgICAgICAgICBwID0gMC43LCAKICAgICAgICAgICAgICAgICAgICAgc2F2ZVByZWRpY3Rpb25zID0gVFJVRSkKCmN2Rml0IDwtIHRyYWluKGFzLmZhY3RvcihGbG9vZGVkKSB+IC4sICBkYXRhID0gY2FfaW51bmRhdGlvbiAlPiUgCiAgICAgICAgICAgICAgICAgYXMuZGF0YS5mcmFtZSgpICU+JQogICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoLWdlb21ldHJ5LCAtY2VsbCksIAogICAgICAgICAgICAgICBtZXRob2Q9ImdsbSIsIGZhbWlseT0iYmlub21pYWwiLAogICAgICAgICAgICAgICB0ckNvbnRyb2wgPSBjdHJsKQoKY3ZGaXQKCmdncGxvdChhcy5kYXRhLmZyYW1lKGN2Rml0JHJlc2FtcGxlKSwgYWVzKEFjY3VyYWN5KSkgKyAKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxKSkgKwogIGxhYnMoeD0iQWNjdXJhY3kiLAogICAgICAgeT0iQ291bnQiKSsKICBwbG90VGhlbWUKYGBgCgojIDQuIFByZWRpY3Rpb24gTWFwcwojIyA0LjEuIENvbmZ1c2lvbiBNZXRyaWNzIGZvciBUcmFpbmluZyBTZXQKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0KI3NldCB1cAphbGxQcmVkaWN0aW9ucyA8LSAKICBwcmVkaWN0KGN2Rml0LCBjYV9pbnVuZGF0aW9uLCB0eXBlPSJwcm9iIilbLDJdCgpjYV9pbnVuZGF0aW9uIDwtIGNhbF9pbnVfZmlzaCAlPiUKICBkcGx5cjo6c2VsZWN0KGNlbGwsIEZsb29kZWQsIExvd19wZXJtZWFiaWxpdHksIFBhcmtzX01ham9yaXR5LCBJbXBlcnZpb3VzX21ham9yaXR5LCBlbGV2YXRpb25fbWluLCBXYXRlcl9tYWpvcml0eSkKYGBgCgpgYGB7ciBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmNvbmZ1c2lvbl9tZXQgPC0gY2FfaW51bmRhdGlvbiAlPiUKICBtdXRhdGUoY29uZlJlc3VsdD1jYXNlX3doZW4oYWxsUHJlZGljdGlvbnMgPCAyNSAmIEZsb29kZWQ9PTAgfiAiVHJ1ZV9OZWdhdGl2ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbFByZWRpY3Rpb25zID49IDI1ICYgRmxvb2RlZD09MSB+ICJUcnVlX1Bvc2l0aXZlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsUHJlZGljdGlvbnMgPCAyNSAmIEZsb29kZWQ9PTEgfiAiRmFsc2VfTmVnYXRpdmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxQcmVkaWN0aW9ucyA+PSAyNSAmIEZsb29kZWQ9PTAgfiAiRmFsc2VfUG9zaXRpdmUiKSkgCmBgYAoKYGBge3IgZXJyb3I9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpjb25mdXNpb25fbWV0MSA8LSBjb25mdXNpb25fbWV0ICU+JQogIG11dGF0ZShjb25mUmVzdWx0ID0gYXMuZmFjdG9yKGNvbmZSZXN1bHQpKQoKY29uZnVzaW9uX21ldDEgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBjb25mUmVzdWx0KSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygicmVkIiwib3JhbmdlIiwibGlnaHRibHVlIiwibGlnaHRncmVlbiIpLCBuYW1lPSJPdXRjb21lcyIpICsKICBsYWJzKHRpdGxlPSJDb25mdXNpb24gTWV0cmljcyIpICsKICBtYXBUaGVtZQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KZ2dzYXZlKCJjb25mdXNpb25fbWV0MS5wbmciLCBwbG90ID0gbGFzdF9wbG90KCksIHdpZHRoID0gNiwgaGVpZ2h0ID0gNCwgZHBpID0gMzAwKQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygifi9EZXNrdG9wL21vZGVsL2NvbmZ1c2lvbl9tZXQxL2NvbmZ1c2lvbl9tZXQxLnBuZyIpCmBgYAoKIyMgNC4yLiBDYWxnYXJ5IFByZWRpY3Rpb25zCgpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcycsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQojTWFwIFByZWRpY3Rpb25zCmFsbFByZWRpY3Rpb25zIDwtIAogIHByZWRpY3QoY3ZGaXQsIGNhX2ludW5kYXRpb24sIHR5cGU9InByb2IiKVssMl0KCmNhX2ludW5kYXRpb24gPC0gCiAgY2JpbmQoY2FfaW51bmRhdGlvbixhbGxQcmVkaWN0aW9ucykgJT4lCiAgbXV0YXRlKGFsbFByZWRpY3Rpb25zID0gcm91bmQoYWxsUHJlZGljdGlvbnMgKiAxMDApKQoKZ2dwbG90KCkgKyAKICBnZW9tX3NmKGRhdGE9Y2FfaW51bmRhdGlvbiwgYWVzKGZpbGw9ZmFjdG9yKG50aWxlKGFsbFByZWRpY3Rpb25zLDUpKSksIAogICAgICAgICAgY29sb3VyPU5BKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2VkZjhmYiIsIiNiM2NkZTMiLCIjOGM5NmM2IiwiIzg4NTZhNyIsIiM4MTBmN2MiKSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YXMuY2hhcmFjdGVyKHF1YW50aWxlKGNhX2ludW5kYXRpb24kYWxsUHJlZGljdGlvbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKDAuMSwuMiwuNCwuNiwuOCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybT1UKSksCiAgICAgICAgICAgICAgICAgICAgbmFtZT0iUHJlZGljdGVkXG5Qcm9iYWJpbGl0aWVzKCUpXG4oUXVpbnRpbGVcbkJyZWFrcykiKSArCiAgbWFwVGhlbWUgKwogIGxhYnModGl0bGU9IlByZWRpY3RlZCBGbG9vZGVkIEFyZWFzIGluIENhbGdhcnkiKQoKZ2dwbG90KCkgKyAKICBnZW9tX3NmKGRhdGE9Y2FfaW51bmRhdGlvbiwgYWVzKGZpbGw9ZmFjdG9yKG50aWxlKGFsbFByZWRpY3Rpb25zLDUpKSksIGNvbG91cj1OQSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNlZGY4ZmIiLCIjYjNjZGUzIiwiIzhjOTZjNiIsIiM4ODU2YTciLCIjODEwZjdjIiksCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWFzLmNoYXJhY3RlcihxdWFudGlsZShjYV9pbnVuZGF0aW9uJGFsbFByZWRpY3Rpb25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygwLjEsLjIsLjQsLjYsLjgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm09VCkpLAogICAgICAgICAgICAgICAgICAgIG5hbWU9IlByZWRpY3RlZFxuUHJvYmFiaWxpdGllcyglKVxuKFF1aW50aWxlXG5CcmVha3MpIikgKwogIGdlb21fc2YoZGF0YT1jYV9pbnVuZGF0aW9uICAlPiUgCiAgICAgICAgICAgIGZpbHRlcihGbG9vZGVkID09IDEpLCAKICAgICAgICAgIGZpbGw9ImJsdWUiLGNvbG91cj1OQSkgKwogIAogIG1hcFRoZW1lICsKICBsYWJzKHRpdGxlPSJPYnNlcnZlZCBhbmQgUHJlZGljdGVkIEZsb29kZWQgQXJlYXMgaW4gQ2FsZ2FyeSIsCiAgICAgICBzdWJ0aXRsZT0iT2JzZXJ2ZWQgZmxvb2RlZCBsYW5kIGluIGJsdWUiKQpgYGAKCiMjIDQuMy4gREMgUHJlZGljdGlvbnMKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0KI01hcCBQcmVkaWN0aW9ucyBmb3IgREMKI3VwbG9hZCBEQyB2YXJpYWJsZXMgYW5kIGNsZWFuaW5nCmRjX2Zpc2gxIDwtIHN0X3JlYWQoIn4vRGVza3RvcC9tb2RlbC9kY19nZW9tNyIsIHByb21vdGVfdG9fbXVsdGkgPSBGQUxTRSkgCmRjZmlzaF9nZW9tIDwtIGRhdGEuZnJhbWUoZGNfZmlzaDEpCiMgY2xlYW5pbmcKZGNmaXNoX2dlb20gPC0gZGNmaXNoX2dlb20gJT4lCiAgcmVuYW1lKGNlbGwgPSBPQkpFQ1RJRCkKCmRjZmlzaF9nZW9tIDwtIGRjZmlzaF9nZW9tWywgLWMoMSwgMiwgNSwgNiwgNywgOCwgOSwgMTEsIDEyLCAxMywgMTUsIDE2LCAxOCwgMTksIDIwLCAyMSldICMgY2xlYW5pbmcKCmRjZmlzaF9nZW9tIDwtIGRjZmlzaF9nZW9tICU+JQogIHJlbmFtZShJbXBlcnZpb3VzX21ham9yaXR5ID0gRENfSU1QX01BSikgJT4lCiAgcmVuYW1lKFBhcmtzX01ham9yaXR5ID0gRENfUEFSS19NQSkgJT4lCiAgcmVuYW1lKExvd19wZXJtZWFiaWxpdHkgPSBTT0lMX01BSk9SKSAlPiUKICByZW5hbWUoZWxldmF0aW9uX21pbiA9IE1JTikgJT4lCiAgcmVuYW1lKFdhdGVyX21ham9yaXR5ID0gRENfV0FURVJfTSkgCgojIHJlb3JkZXIKZGNmaXNoX2dlb20gPC0gZGNmaXNoX2dlb21bLCBjKCJjZWxsIiwgImdlb21ldHJ5IiwgIkxvd19wZXJtZWFiaWxpdHkiLCAiUGFya3NfTWFqb3JpdHkiLCAiSW1wZXJ2aW91c19tYWpvcml0eSIsImVsZXZhdGlvbl9taW4iLCJXYXRlcl9tYWpvcml0eSIpXQpkY19pbnVuZGF0aW9uIDwtIGRjZmlzaF9nZW9tCgojIFJ1bm5pbmcgREMgbW9kZWwKZGNfYWxsUHJlZGljdGlvbnMgPC0gCiAgcHJlZGljdChjdkZpdCwgZGNfaW51bmRhdGlvbiwgdHlwZT0icHJvYiIpWywyXQoKZGNfaW51bmRhdGlvbiA8LSAKICBjYmluZChkY19pbnVuZGF0aW9uLGRjX2FsbFByZWRpY3Rpb25zKSAlPiUKICBtdXRhdGUoZGNfYWxsUHJlZGljdGlvbnMgPSByb3VuZChkY19hbGxQcmVkaWN0aW9ucyAqIDEwMCkpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0KZ2dwbG90KCkgKyAKICBnZW9tX3NmKGRhdGE9ZGNfaW51bmRhdGlvbiRnZW9tZXRyeSwgYWVzKGZpbGw9ZmFjdG9yKG50aWxlKGRjX2FsbFByZWRpY3Rpb25zLDUpKSksIGNvbG91cj1OQSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNlZGY4ZmIiLCIjYjNjZGUzIiwiIzhjOTZjNiIsIiM4ODU2YTciLCIjODEwZjdjIiksCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWFzLmNoYXJhY3RlcihxdWFudGlsZShkY19pbnVuZGF0aW9uJGRjX2FsbFByZWRpY3Rpb25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygwLjEsLjIsLjQsLjYsLjgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm09VCkpLAogICAgICAgICAgICAgICAgICAgIG5hbWU9IlByZWRpY3RlZFxuUHJvYmFiaWxpdGllcyglKVxuKFF1aW50aWxlXG5CcmVha3MpIikgKwogIG1hcFRoZW1lICsKICBsYWJzKHRpdGxlPSJQcmVkaWN0ZWQgRmxvb2RlZCBBcmVhcyBpbiBEQyIpCgpgYGAKCgo=