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:

  • Elevation

  • Impervious Surfaces

  • Parks

  • Low Permeable Soils (e.g. clay)

  • Waterbodies

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.

4. Prediction Maps

4.1. Confusion Metrics for Training Set

4.2. Calgary Predictions

4.3. DC Predictions

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