Purpose

Build a model to predict if an incident will be resolved within the SLA time period.

Training set

Training set include closed tickets from 2017 & 2018.

Data exploration

Visualize and explore the data to highlight it’s main characteristics of distribution, variation, and relationships, and pinpoint data quality issues.
Incident represents an IT service task and “ticket resolution time task” is the net time from ticket creation until resolution
(does not include weekend, pending,after business time, etc.).

For modeling purposes, we are going to use the “total_resolution_time”, the gross time from ticket creation until resolution
(including weekend, pending, after business time, etc.).
The reason for not using the net time is that we are not aware to how it is calculated, and more importantly the data which was used for the calculation is not available.

The meet SLA output will be calculated according to 24 hours threshold.
In general this is a sound approach, because our purpose is to identify the underlining factors that determine the variability is the resolution time.

Resolution time distribution

Plot #1 - Shows the complete distribution, what looks unusual is the longtail composed from tickets that took more then 5 days to resolve.

Plot #2 - Shows the distribution of tickets that took less than 5 days.
The distribution appears to be made up of two or more individual distributions (i.e. the distribution has multiple peaks or modes).

Analyzing the multimodal distribuation

Analyzing the longtail

We see that in 2018 there were more longtail incidents on monthly basis, except for Nov-18.

Looking at the distribution based on the top 20 subcategory reveal that Application and software category dominate the longtail.

SLA rate

64% of the incidents were resolved within 24 hours.

Analysis approach

The major factors influencing the variability of the resolution time, can be grouped as follow.

Complexity

Infer about the incident complexity using text analytics. The short description was processed, and two features were engineered in addition to the number of words in description. In the first we try to assess the topic of the incident, or what it is all about. The second tries to assess how difficult it is.

The plot shows the most frequent words across all incident descriptions.

The second plot shows the sentiment analysis that tag positive and negative words.

Difficulty

Based on negative sentiment tagging, we are able to infer about how difficult is the incident at hand.

Case type

Case types with 1K incidents and above, don’t vary much. Bug cases are exception. It means that case_type is not going to be an strong predictor.

Short Description - Number of words

Longer description indicate complex problem, that takes more time to resolve.

The assumption is supported by the data.

We can clearly see a pattern, the median is growing incrementally, as the number of words increases, but there are many outliers.

Subcategory

Subcategory w/confidance interval

For each subcategory, the SLA Rate is calculated and a 95% confidence interval is shown to help understand what the noise is around this value. We can clearly see which subcategories deviate from randomness and the width of the error bars help the reader understand how much each number should be trusted.

Group type

Service desk teams have the highest sla rate around 76%, next are the support teams with sla of 64% and last are the application teams with 55%. On the right side of the plot we can see the median resolution time per group type, the results are according to the expectations.

Originator Group

Originator group is the first group that handled the ticket, and in many cases the one that resolved the ticket.

Region of assignment group

Urgency

Contact type

Temporal

If the ticket was opened on Friday or Saturday it has lower chances to be resolved on time.

Data Spliting

Random split of the training data based on 10/90 percent split, 10% goes for testing.

Feature Enginnering

The features that goes into the model:

Model Training - Decision Tree

Test Performance

Accuracy of 74.84% compare of 64.17% of majority vote model. which is a 16% improvement. the model has hard time to predict correctly incidents that will not meet the SLA. In an attempt to improve the learning process let’s use random forest which is a bagging (Bootstrap Aggregation) Decision Tree Ensemble.

Feature Importance

Decistion Tree Plot

Model Training - Random Forest

Confusion Matrix and Statistics

          Reference
Prediction   No  Yes
       No   790  342
       Yes  409 1805
                                         
               Accuracy : 0.7756         
                 95% CI : (0.761, 0.7896)
    No Information Rate : 0.6417         
    P-Value [Acc > NIR] : < 2e-16        
                                         
                  Kappa : 0.5058         
 Mcnemar's Test P-Value : 0.01602        
                                         
            Sensitivity : 0.8407         
            Specificity : 0.6589         
         Pos Pred Value : 0.8153         
         Neg Pred Value : 0.6979         
             Prevalence : 0.6417         
         Detection Rate : 0.5395         
   Detection Prevalence : 0.6617         
      Balanced Accuracy : 0.7498         
                                         
       'Positive' Class : Yes            
                                         

Using the RandomForest model we were able to increase the accuracy to 77.56% on the test set compare to 74.84% for a single decision tree.

More importantly the RF model is doing a better job in predicting the incidents that will not meet the SLA.

LS0tDQp0aXRsZTogIlNMQSBDbGFzc2lmZXIiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KIyMjUHVycG9zZQ0KQnVpbGQgYSBtb2RlbCB0byBwcmVkaWN0IGlmIGFuIGluY2lkZW50IHdpbGwgYmUgcmVzb2x2ZWQNCndpdGhpbiB0aGUgU0xBIHRpbWUgcGVyaW9kLg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBsb2FkIGxpYnMNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KERCSSkNCmxpYnJhcnkoUlBvc3RncmVTUUwpDQpsaWJyYXJ5KGNhcmV0KQ0KbGlicmFyeShIbWlzYykNCmxpYnJhcnkoZ3JpZEV4dHJhKQ0KIyBzb3VyY2UgaGVscGVyIGZ1bmMNCnNvdXJjZSgiRnVuY3Rpb25zLlIiKQ0KYGBgDQoNCiMjI1RyYWluaW5nIHNldA0KVHJhaW5pbmcgc2V0IGluY2x1ZGUgY2xvc2VkIHRpY2tldHMgZnJvbSAyMDE3ICYgMjAxOC4NCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQojIGxvYWQgZGF0YQ0KaW5jX2ZpbGVfbmFtZSA8LSAnc291cmNlLWRhdGEvMjAxOC0xMS0xOS9pbmNpZGVudCAxOTExMjAxOC5jc3YnDQoNCmluYyA8LSByZWFkX2NzdihpbmNfZmlsZV9uYW1lKSAlPiUgDQogIG11dGF0ZShvcGVuZWRfYXQgPSBkbXlfaG1zKG9wZW5lZF9hdCkpICU+JSANCiAgbXV0YXRlKHllYXIgPSB5ZWFyKG9wZW5lZF9hdCkpICU+JSANCiAgbXV0YXRlKHJlc29sdXRpb25fdGltZSA9IHVfdG90YWxfcmVzb2x1dGlvbl90aW1lIC8gMzYwMCwNCiAgICAgICAgIHNsYSA9IGlmZWxzZShyZXNvbHV0aW9uX3RpbWUgKiAzNjAwIDwgODY0MDAsJ1llcycsJ05vJykpICU+JQ0KICBmaWx0ZXIoc3RhdGU9PSdDbG9zZWQnLCB5ZWFyPjIwMTYsICFpcy5uYSh1X21ldF90aGVfc2xhKSkgJT4lIA0KICBzZWxlY3QoLXllYXIpDQoNCiMgYXBwZW5kIGdyb3VwIHR5cGUgYW5kIHJlZ2lvbg0KaW5jIDwtIGluYyAlPiUgDQogIGxlZnRfam9pbihmeF9ncm91cF90eXBlKCksYnk9ImFzc2lnbm1lbnRfZ3JvdXAiKSAlPiUNCiAgbGVmdF9qb2luKGZ4X2dyb3VwX3JlZ2lvbigpLCBieT0nYXNzaWdubWVudF9ncm91cCcpDQpgYGANCg0KIyMjRGF0YSBleHBsb3JhdGlvbg0KVmlzdWFsaXplIGFuZCBleHBsb3JlIHRoZSBkYXRhIHRvIGhpZ2hsaWdodCBpdCdzIG1haW4gY2hhcmFjdGVyaXN0aWNzIG9mIGRpc3RyaWJ1dGlvbiwgdmFyaWF0aW9uLCBhbmQgcmVsYXRpb25zaGlwcywgYW5kIHBpbnBvaW50IGRhdGEgcXVhbGl0eSBpc3N1ZXMuICANCkluY2lkZW50IHJlcHJlc2VudHMgYW4gSVQgc2VydmljZSB0YXNrIGFuZCAidGlja2V0IHJlc29sdXRpb24gdGltZSB0YXNrIiBpcyB0aGUNCm5ldCB0aW1lIGZyb20gdGlja2V0IGNyZWF0aW9uIHVudGlsIHJlc29sdXRpb24gIA0KKGRvZXMgbm90IGluY2x1ZGUgd2Vla2VuZCwgcGVuZGluZyxhZnRlciBidXNpbmVzcyB0aW1lLCBldGMuKS4NCg0KRm9yIG1vZGVsaW5nIHB1cnBvc2VzLCB3ZSBhcmUgZ29pbmcgdG8gdXNlIHRoZSAidG90YWxfcmVzb2x1dGlvbl90aW1lIiwgdGhlIGdyb3NzIHRpbWUgZnJvbSB0aWNrZXQgY3JlYXRpb24gdW50aWwgcmVzb2x1dGlvbiAgDQooaW5jbHVkaW5nIHdlZWtlbmQsIHBlbmRpbmcsIGFmdGVyIGJ1c2luZXNzIHRpbWUsIGV0Yy4pLiAgDQpUaGUgcmVhc29uIGZvciBub3QgdXNpbmcgdGhlIG5ldCB0aW1lIGlzIHRoYXQgd2UgYXJlIG5vdCBhd2FyZSB0byBob3cgaXQgaXMgY2FsY3VsYXRlZCwNCmFuZCBtb3JlIGltcG9ydGFudGx5IHRoZSBkYXRhIHdoaWNoIHdhcyB1c2VkIGZvciB0aGUgY2FsY3VsYXRpb24gaXMgbm90IGF2YWlsYWJsZS4NCg0KVGhlIG1lZXQgU0xBIG91dHB1dCB3aWxsIGJlIGNhbGN1bGF0ZWQgYWNjb3JkaW5nIHRvIDI0IGhvdXJzIHRocmVzaG9sZC4gIA0KSW4gZ2VuZXJhbCB0aGlzIGlzIGEgc291bmQgYXBwcm9hY2gsIGJlY2F1c2Ugb3VyIHB1cnBvc2UgaXMgdG8gaWRlbnRpZnkgdGhlDQp1bmRlcmxpbmluZyBmYWN0b3JzIHRoYXQgZGV0ZXJtaW5lIHRoZSB2YXJpYWJpbGl0eSBpcyB0aGUgcmVzb2x1dGlvbiB0aW1lLg0KDQojIyMjUmVzb2x1dGlvbiB0aW1lIGRpc3RyaWJ1dGlvbg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnBsb3QxIDwtIGdncGxvdChpbmMsIGFlcyh4PXJlc29sdXRpb25fdGltZSwgZmlsbD1zbGEpKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh5PS4uZGVuc2l0eS4uKSwgYmlud2lkdGg9MSkgKw0KICB4bGltKDAsNTAwKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQsIGxpbWl0cyA9IGMoMCwwLjEpKSArDQogIGxhYnMoeD0ncmVzb2x1dGlvbiB0aW1lIChob3VycyknLA0KICAgICAgIHRpdGxlID0ncGxvdCAjMScsDQogICAgICAgc3VidGl0bGUgPSAncmVzb2x1dGlvbiB0aW1lIGggPD0gNTAwJykgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQ0KDQpwbG90MiA8LSBnZ3Bsb3QoaW5jLCBhZXMoeD1yZXNvbHV0aW9uX3RpbWUsIGZpbGw9c2xhKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeT0uLmRlbnNpdHkuLiksIGJpbndpZHRoPTEpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsMTIwKSwgYnJlYWtzID0gYygwLDMsNSwxMCwxOCwyNCwzMiw1Niw3Miw5NiwxMjApKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQsIGxpbWl0cyA9IGMoMCwwLjEpKSArDQogIGxhYnMoeD0ncmVzb2x1dGlvbiB0aW1lIChob3VycyknLA0KICAgICAgIHRpdGxlID0gJ3Bsb3QgIzInLA0KICAgICAgIHN1YnRpdGxlID0gJ3Jlc29sdXRpb24gdGltZSBoIDwgPTEyMCcpDQoNCmdyaWQuYXJyYW5nZShwbG90MSwgcGxvdDIsIG5jb2w9MikNCg0KbG9uZ3RhaWwgPC0gaW5jICU+JSBmaWx0ZXIocmVzb2x1dGlvbl90aW1lPjEyMCkgJT4lIGNvdW50KCkgJT4lIHB1bGwoKQ0KDQpgYGANCipQbG90ICMxKiAtIFNob3dzIHRoZSBjb21wbGV0ZSBkaXN0cmlidXRpb24sIHdoYXQgbG9va3MgdW51c3VhbCBpcyB0aGUgDQpsb25ndGFpbCBjb21wb3NlZCBmcm9tIHRpY2tldHMgdGhhdCB0b29rIG1vcmUgdGhlbiA1IGRheXMgdG8gcmVzb2x2ZS4NCg0KKlBsb3QgIzIqIC0gU2hvd3MgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aWNrZXRzIHRoYXQgdG9vayBsZXNzIHRoYW4gNSBkYXlzLiAgDQpUaGUgZGlzdHJpYnV0aW9uIGFwcGVhcnMgdG8gYmUgbWFkZSB1cCBvZiB0d28gb3IgbW9yZSBpbmRpdmlkdWFsIGRpc3RyaWJ1dGlvbnMNCihpLmUuIHRoZSBkaXN0cmlidXRpb24gaGFzIG11bHRpcGxlIHBlYWtzIG9yIG1vZGVzKS4NCg0KIyMjI0FuYWx5emluZyB0aGUgbXVsdGltb2RhbCBkaXN0cmlidWF0aW9uDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KaW5jICU+JSANCiAgZ2dwbG90KGFlcyh4PXJlc29sdXRpb25fdGltZSwgZmlsbD1mYWN0b3IoZ3JvdXBfdHlwZSkpKSArDQogIGdlb21faGlzdG9ncmFtKHBvc2l0aW9uPSJzdGFjayIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsMjQpLCBicmVha3MgPSBzZXEoMDoyNCkpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwyNTAwKSkgKw0KICBsYWJzKHg9J3Jlc29sdXRpb24gdGltZSAoaG91cnMpJywNCiAgICAgICB0aXRsZSA9ICdkaXN0cmlidXRpb24gYnkgZ3JvdXAgdHlwZScpDQpgYGANCg0KXHBhZ2VicmVhaw0KDQojIyMjQW5hbHl6aW5nIHRoZSBsb25ndGFpbA0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OH0NCmluYyAlPiUgDQogIGZpbHRlcihyZXNvbHV0aW9uX3RpbWUgPiAxMjApICU+JSANCiAgbXV0YXRlKHllYXIgPSB5ZWFyKG9wZW5lZF9hdCksDQogICAgICAgICBtb250aCA9IG1vbnRoKG9wZW5lZF9hdCwgbGFiZWw9VFJVRSkpICU+JSANCiAgIyBjb3VudCh5ZWFyLCBtb250aCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9ZmFjdG9yKG1vbnRoKSwgZmlsbD1mYWN0b3IoeWVhcikpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UyKHByZXNlcnZlID0gInNpbmdsZSIpKSArDQogIGdlb21fdGV4dChzdGF0PSJjb3VudCIsIGFlcyhsYWJlbCA9IC4uY291bnQuLiksIHNpemUgPSAzLjAsIGNvbG9yPSdibGFjaycsDQogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksIHZqdXN0PS0uOCkgKw0KICBsYWJzKHRpdGxlID0gJ2xvbmd0YWlsIC0geWVhcmx5IGNvbXBhcmlzaW9uJywgeD0nbW9udGgnKSArDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJ5ZWFyIikNCiAgDQpgYGANCldlIHNlZSB0aGF0IGluIDIwMTggdGhlcmUgd2VyZSBtb3JlIGxvbmd0YWlsIGluY2lkZW50cyBvbiBtb250aGx5IGJhc2lzLA0KZXhjZXB0IGZvciBOb3YtMTguDQoNClxwYWdlYnJlYWsNCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OH0NCmluYyAlPiUgDQogIGZpbHRlcihyZXNvbHV0aW9uX3RpbWUgPiAxMjApICU+JSANCiAgbXV0YXRlKHllYXIgPSB5ZWFyKG9wZW5lZF9hdCksDQogICAgICAgICBtb250aCA9IG1vbnRoKG9wZW5lZF9hdCwgbGFiZWw9VFJVRSkpICU+JSANCiAgY291bnQoY2F0ZWdvcnksIHN1YmNhdGVnb3J5KSAlPiUgDQogIHRvcF9uKDIwLG4pICU+JQ0KICBnZ3Bsb3QoYWVzKHg9c3ViY2F0ZWdvcnksIHk9bikpICsNCiAgZ2VvbV9jb2woKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSwNCiAgICAgICAgICAgIHNpemUgPSAyLjUsIGNvbG9yPSdvcmFuZ2UnLCB2anVzdD0uMiwgaGp1c3Q9MSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBmYWNldF93cmFwKH5jYXRlZ29yeSkgKw0KICBsYWJzKHRpdGxlPSdsb25ndGFpbCBieSBzdWJjYXRlZ29yeScpDQpgYGANCkxvb2tpbmcgYXQgdGhlIGRpc3RyaWJ1dGlvbiBiYXNlZCBvbiB0aGUgdG9wIDIwIHN1YmNhdGVnb3J5IHJldmVhbCB0aGF0IEFwcGxpY2F0aW9uDQphbmQgc29mdHdhcmUgY2F0ZWdvcnkgZG9taW5hdGUgdGhlIGxvbmd0YWlsLg0KDQpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KaW5jICU+JSANCiAgZmlsdGVyKHJlc29sdXRpb25fdGltZSA+IDEyMCkgJT4lIA0KICBjb3VudChhc3NpZ25tZW50X2dyb3VwLCBzdWJjYXRlZ29yeSkgJT4lIA0KICB0b3BfbigyMCxuKSAlPiUNCiAgZ2dwbG90KGFlcyh4PXJlb3JkZXIoYXNzaWdubWVudF9ncm91cCwgbiksIHk9biwgZmlsbD1zdWJjYXRlZ29yeSkpICsNCiAgZ2VvbV9jb2woKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIGxhYnMoeD1OVUxMLCB0aXRsZT0nbG9uZ3RhaWwgYnkgZ3JvdXAnKQ0KIyBTQ00oSVNMKSBhbmQgU2VydmljZSBEZXNrIChTUFRTKSBjb250cmlidXRlIG1vcmUgdG8gdGhlIGxvbmd0YWlsIGNvbXBhcmUgdG8gdGhlIA0KIyBvdGhlciB0ZWFtcy4NCmBgYA0KDQojIyMjU0xBIHJhdGUNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTh9DQpoIDwtIGZ4X292ZXJhbGxfc2xhKCkNCg0KZnhfdml6X3ByZXAoaW5jICU+JSBjb3VudChzbGEpLCBuKSAlPiUgDQpnZ3Bsb3QoYWVzKHggPSBzbGEsIHkgPSBuKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgDQogICAgICAgICAgIHdpZHRoID0gMC43NSkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gYmFyX2xhYmVsKSwNCiAgICAgICAgICAgIHNpemUgPSAzLjUsIGNvbG9yPSdvcmFuZ2UnLCB2anVzdD0wLCBoanVzdD0xLjUpICsgICAgICAgICAgICAgICAgIA0KICBjb29yZF9mbGlwKCkgKw0KICBsYWJzKHg9TlVMTCwgeT0naW5jaWRlbnRzJykNCmBgYA0KDQo2NCUgb2YgdGhlIGluY2lkZW50cyB3ZXJlIHJlc29sdmVkIHdpdGhpbiAyNCBob3Vycy4NCg0KXHBhZ2VicmVhaw0KDQojIyNBbmFseXNpcyBhcHByb2FjaA0KVGhlIG1ham9yIGZhY3RvcnMgaW5mbHVlbmNpbmcgdGhlIHZhcmlhYmlsaXR5IG9mIHRoZSByZXNvbHV0aW9uIHRpbWUsDQpjYW4gYmUgZ3JvdXBlZCBhcyBmb2xsb3cuDQogIA0KICogSW5jaWRlbnQgVHlwZSAtIHdoYXQgaXMgdGhlIG5hdHVyZSBvZiB0aGUgaW5jaWRlbnQsIGFuZCB0byB3aGF0IGFyZWEgaXQgYmVsb25ncy4NCiANCiAqIENvbXBsZXhpdHkgLSBob3cgY29tcGxleCBpcyB0aGUgcHJvYmxlbSBhdCBoYW5kLiANCiANCiAqIFVyZ2VuY3kgLSBob3cgdXJnZW50IGlzIGl0IHRvIHJlc29sdmUgdGhlIHByb2JsZW0uIA0KIA0KICogUGVyZm9ybWFuY2UgLSByZWxhdGUgdG8gdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBhc3NpZ25lZSBhbmQgdGhlIGFzc2lnbm1lbnQgZ3JvdXAuIA0KIA0KICogRmxvdyAtIHdvcmtsb2FkLCBwZW5kaW5nIHRpY2tldHMsIHRpY2tldHMgaW4gcHJvY2VzcywgZ3JvdXAgdHJhbnNpdGlvbnMgZXRjLi4NCg0KICogVGVtcG9yYWwgLSBsaWtlIGRheSBvZiB0aGUgd2VlaywgaG91ciBvZiB0aGUgZGF5LiANCg0KXHBhZ2VicmVhayANCg0KIyMjI0NvbXBsZXhpdHkNCg0KSW5mZXIgYWJvdXQgdGhlIGluY2lkZW50IGNvbXBsZXhpdHkgdXNpbmcgdGV4dCBhbmFseXRpY3MuDQpUaGUgc2hvcnQgZGVzY3JpcHRpb24gd2FzIHByb2Nlc3NlZCwgYW5kIHR3byBmZWF0dXJlcyB3ZXJlIGVuZ2luZWVyZWQgaW4gYWRkaXRpb24gdG8gdGhlDQpudW1iZXIgb2Ygd29yZHMgaW4gZGVzY3JpcHRpb24uDQpJbiB0aGUgZmlyc3Qgd2UgdHJ5IHRvIGFzc2VzcyB0aGUgdG9waWMgb2YgdGhlIGluY2lkZW50LCBvciB3aGF0IGl0IGlzIGFsbCBhYm91dC4NClRoZSBzZWNvbmQgdHJpZXMgdG8gYXNzZXNzIGhvdyBkaWZmaWN1bHQgaXQgaXMuDQoNClRoZSBwbG90IHNob3dzIHRoZSBtb3N0IGZyZXF1ZW50IHdvcmRzIGFjcm9zcyBhbGwgaW5jaWRlbnQgZGVzY3JpcHRpb25zLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dGV4dCkNCmluY19kZXNjIDwtIGluYyAlPiUgDQogIGZpbHRlcighaXMubmEoc2hvcnRfZGVzY3JpcHRpb24pKSAlPiUgDQogIHNlbGVjdCh0ZXh0ID0gc2hvcnRfZGVzY3JpcHRpb24pICU+JSANCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCB0ZXh0KQ0KDQppbmNfY2xlYW5lZCA8LSBpbmNfZGVzYyAlPiUNCiAgYW50aV9qb2luKGdldF9zdG9wd29yZHMoKSkNCg0KaW5jX2NsZWFuZWQgJT4lDQogIGNvdW50KHdvcmQsIHNvcnQgPSBUUlVFKSAlPiUNCiAgZmlsdGVyKG4gPiAxMDAwKSAlPiUNCiAgbXV0YXRlKHdvcmQgPSByZW9yZGVyKHdvcmQsIG4pKSAlPiUNCiAgZ2dwbG90KGFlcyh3b3JkLCBuKSkgKw0KICBnZW9tX2NvbCgpICsNCiAgeGxhYihOVUxMKSArDQogIGNvb3JkX2ZsaXAoKQ0KIyBsaWJyYXJ5KHdvcmRjbG91ZCkNCiMgaW5jX2NsZWFuZWQgJT4lDQojICAgY291bnQod29yZCkgJT4lDQojICAgd2l0aCh3b3JkY2xvdWQod29yZCwgbiwgbWF4LndvcmRzID0gMTAwKSkNCmBgYA0KDQpUaGUgc2Vjb25kIHBsb3Qgc2hvd3MgdGhlIHNlbnRpbWVudCBhbmFseXNpcyB0aGF0IHRhZyBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgd29yZHMuDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpiaW5nX3dvcmRfY291bnRzIDwtIGluY19jbGVhbmVkICU+JQ0KICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJiaW5nIikpICU+JQ0KICBjb3VudCh3b3JkLCBzZW50aW1lbnQsIHNvcnQgPSBUUlVFKSAlPiUNCiAgdW5ncm91cCgpDQoNCmJpbmdfd29yZF9jb3VudHMgJT4lDQogIGdyb3VwX2J5KHNlbnRpbWVudCkgJT4lDQogIHRvcF9uKDEwKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBtdXRhdGUod29yZCA9IHJlb3JkZXIod29yZCwgbikpICU+JQ0KICBnZ3Bsb3QoYWVzKHdvcmQsIG4sIGZpbGwgPSBzZW50aW1lbnQpKSArDQogIGdlb21fY29sKHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgZmFjZXRfd3JhcCh+c2VudGltZW50LCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBsYWJzKHkgPSAiQ29udHJpYnV0aW9uIHRvIHNlbnRpbWVudCIsDQogICAgICAgeCA9IE5VTEwpICsNCiAgY29vcmRfZmxpcCgpDQojIGxpYnJhcnkocmVzaGFwZTIpDQojIGJpbmcgPC0gZ2V0X3NlbnRpbWVudHMoImJpbmciKQ0KIyBpbmNfZGVzYyAlPiUNCiMgICBmaWx0ZXIoIXdvcmQgJWluJSBjKCd3aXNlJywnZXhjZWwnLCd3b3JrYWdpbGUnKSkgJT4lIA0KIyAgIGlubmVyX2pvaW4oYmluZykgJT4lDQojICAgY291bnQod29yZCwgc2VudGltZW50LCBzb3J0ID0gVFJVRSkgJT4lDQojICAgYWNhc3Qod29yZCB+IHNlbnRpbWVudCwgdmFsdWUudmFyID0gIm4iLCBmaWxsID0gMCkgJT4lDQojICAgY29tcGFyaXNvbi5jbG91ZChjb2xvcnMgPSBjKCIjRjg3NjZEIiwgIiMwMEJGQzQiKSwNCiMgICAgICAgICAgICAgICAgICAgIG1heC53b3JkcyA9IDEwMCkNCmBgYA0KDQpccGFnZWJyZWFrDQoNCg0KIyMjIyBEaWZmaWN1bHR5DQpCYXNlZCBvbiBuZWdhdGl2ZSBzZW50aW1lbnQgdGFnZ2luZywgd2UgYXJlIGFibGUgdG8gaW5mZXIgYWJvdXQgaG93DQpkaWZmaWN1bHQgaXMgdGhlIGluY2lkZW50IGF0IGhhbmQuDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQ0KaW5jICU+JSANCiAgbXV0YXRlKGRpZmZpY3VsdHkgPSBpZmVsc2Uoc3RyX2RldGVjdChzdHJfdG9fbG93ZXIoc2hvcnRfZGVzY3JpcHRpb24pLA0KICAgICcoZXJyb3J8cHJvYmxlbXxpc3N1ZXx1bmFibGV8ZmFpbGVkfG1pc3Npbmd8bmVlZHN8d3Jvbmd8c2xvd3xsb2NrZWR8ZGlzYWJsZWR8YnVnKScgKSAmIA0KICAgICAgIWlzLm5hKHNob3J0X2Rlc2NyaXB0aW9uKSwxLDApKSAlPiUgDQogIHNlbGVjdChzaG9ydF9kZXNjcmlwdGlvbiwgZGlmZmljdWx0eSwgc2xhKSAlPiUgDQogIG11dGF0ZShzbGEgPSBpZmVsc2Uoc2xhPT0nWWVzJywgMSwgMCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKGRpZmZpY3VsdHkpLCB5ID0gc2xhKSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX2NsX25vcm1hbCkNCmBgYA0KDQpccGFnZWJyZWFrDQoNCiMjIyMgQ2FzZSB0eXBlDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQ0KaW5jICU+JSANCiAgZmlsdGVyKCFpcy5uYSh1X2Nhc2VfdHlwZSkpICU+JSANCiAgc2VsZWN0KHg9dV9jYXNlX3R5cGUsIHk9cmVzb2x1dGlvbl90aW1lLCBzbGEpICU+JQ0KICBjb3VudCh4LHNsYSkgJT4lDQogIGZpbHRlcihuPjEwKSAlPiUgDQogIHNwcmVhZChzbGEsIG4pICU+JQ0KICBtdXRhdGUoTm8gPSBpZmVsc2UoaXMubmEoTm8pLDAsTm8pLA0KICAgICAgICAgWWVzID0gaWZlbHNlKGlzLm5hKFllcyksMCxZZXMpLA0KICAgICAgICAgc2xhX3JhdGUgPSByb3VuZChZZXMvKFllcytObyksMikpICU+JQ0KICBtdXRhdGUoYmFyX3BlcmNlbnRhZ2UgPSBzcHJpbnRmKCIlLjFmJSUiLCAxMDAqc2xhX3JhdGUpKSAlPiUgDQogIG11dGF0ZShiYXJfbGFiZWwgPSBwYXN0ZTAoZm9ybWF0KFllcywgYmlnLm1hcmsgPSAiLCIpLCAiIH4gIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFyX3BlcmNlbnRhZ2UpKSAlPiUgDQogICAgc2VsZWN0KC1iYXJfcGVyY2VudGFnZSkgJT4lDQogIGdncGxvdChhZXMoeD1yZW9yZGVyKHgsIHNsYV9yYXRlKSwgeT1zbGFfcmF0ZSkpICsNCiAgZ2VvbV9jb2woKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBiYXJfbGFiZWwpLCBoanVzdD0xLCBzaXplPTMsIGNvbG9yPSdvcmFuZ2UnLA0KICAgICAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsgDQogIGNvb3JkX2ZsaXAoKSArDQogICMgT3ZlcmFsbCBTTEEgcmF0ZQ0KICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0PWgpLCBjb2xvdXI9IiNCQjAwMDAiLCBsaW5ldHlwZT0iZGFzaGVkIikgKyANCiAgZ2VvbV90ZXh0KGFlcygwLCBoLCBsYWJlbCA9IHNjYWxlczo6cGVyY2VudChoKSwgdmp1c3QgPSAtMC41LCBoanVzdCA9IC0uMiksDQogICAgICAgICAgICBzaXplID0gMy4wLCBjb2xvcj0nY29yYWwzJykgKw0KICBsYWJzKHRpdGxlPSdjYXNlIHR5cGUgc2xhIHJhdGVzJyx4PU5VTEwsIHk9J3NsYSByYXRlJykNCmBgYA0KQ2FzZSB0eXBlcyB3aXRoIDFLIGluY2lkZW50cyBhbmQgYWJvdmUsIGRvbid0IHZhcnkgbXVjaC4NCkJ1ZyBjYXNlcyBhcmUgZXhjZXB0aW9uLiBJdCBtZWFucyB0aGF0IGNhc2VfdHlwZSBpcyBub3QgZ29pbmcgdG8gYmUNCmFuIHN0cm9uZyBwcmVkaWN0b3IuDQoNClxwYWdlYnJlYWsNCg0KIyMjIyNTaG9ydCBEZXNjcmlwdGlvbiAtIE51bWJlciBvZiB3b3Jkcw0KTG9uZ2VyIGRlc2NyaXB0aW9uIGluZGljYXRlIGNvbXBsZXggcHJvYmxlbSwgdGhhdCB0YWtlcyBtb3JlIHRpbWUgdG8gcmVzb2x2ZS4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmluYyAlPiUgDQogIGZpbHRlcighaXMubmEoc2hvcnRfZGVzY3JpcHRpb24pKSAlPiUgDQogIG11dGF0ZShkZXNjX3dvcmRzID0gc3RyX2NvdW50KHNob3J0X2Rlc2NyaXB0aW9uLCAiXFxTKyIpKSAlPiUgDQogIHNlbGVjdCh4PWRlc2Nfd29yZHMsIHNsYSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9eCwgZmlsbD1zbGEpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICBsYWJzKHRpdGxlPSdkaXN0cmlidXRpb24gb2YgbnVtYmVyIG9mIHdvcmRzIGluIHNob3J0IGRlc2NyaXB0aW9uJywNCiAgICAgICB4PSdudW1iZXIgb2Ygd29yZHMnKQ0KYGBgDQoNClRoZSBhc3N1bXB0aW9uIGlzIHN1cHBvcnRlZCBieSB0aGUgZGF0YS4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OH0NCmluYyAlPiUgDQogIGZpbHRlcighaXMubmEoc2hvcnRfZGVzY3JpcHRpb24pKSAlPiUgDQogIG11dGF0ZShkZXNjX3dvcmRzID0gZmFjdG9yKHN0cl9jb3VudChzaG9ydF9kZXNjcmlwdGlvbiwgIlxcUysiKSksDQogICAgICAgICB3b3Jkc19iaW4gPSBmYWN0b3IobnRpbGUoZGVzY193b3JkcywxMCkpKSAlPiUgDQogIHNlbGVjdCh4PWRlc2Nfd29yZHMsIHk9cmVzb2x1dGlvbl90aW1lLCBzbGEpICU+JSANCiAgZmlsdGVyKHNsYT09J1llcycpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9eCwgeT15KSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIHlsaW0oMCwyNCkgKw0KICBsYWJzKHRpdGxlPSdkaXN0cmlidXRpb24gbnVtYmVyIG9mIHdvcmRzIGluIHNob3J0IGRlc2NyaXB0aW9uJywNCiAgICAgICBzdWJ0aXRsZSA9ICdpbmNpZGVudHMgdGhhdCBtZWV0IHRoZSBTTEEnLA0KICAgICAgIHg9J251bWJlciBvZiB3b3JkcyBpbiBzaG9ydCBkZXNjcmlwdGlvbicsIHk9J3Jlc29sdXRpb24gdGltZSAoaG91ciknKQ0KYGBgDQpXZSBjYW4gY2xlYXJseSBzZWUgYSBwYXR0ZXJuLCB0aGUgbWVkaWFuIGlzIGdyb3dpbmcgaW5jcmVtZW50YWxseSwNCmFzIHRoZSBudW1iZXIgb2Ygd29yZHMgaW5jcmVhc2VzLCBidXQgdGhlcmUgYXJlIG1hbnkgb3V0bGllcnMuDQoNClxwYWdlYnJlYWsNCg0KIyMjI1N1YmNhdGVnb3J5DQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9OH0NCnN1YmNhdCA8LSBpbmMgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKHN1YmNhdGVnb3J5KSkgJT4lIA0KICBsZWZ0X2pvaW4oZnhfc3ViY2F0ZWdvcnlfdCgyMCksIGJ5PWMoJ3N1YmNhdGVnb3J5JykpICU+JSANCiAgc2VsZWN0KGNhdGVnb3J5LCBzdWJjYXRlZ29yeT1uZXdfc3ViY2F0ZWdvcnksIHNsYSkgJT4lIA0KICBjb3VudChjYXRlZ29yeSwgc3ViY2F0ZWdvcnksIHNsYSkgJT4lIA0KICBmaWx0ZXIobj4zMCkgJT4lIA0KICBzcHJlYWQoc2xhLCBuKSAlPiUNCiAgbXV0YXRlKE5vID0gaWZlbHNlKGlzLm5hKE5vKSwwLE5vKSwNCiAgICAgICAgIFllcyA9IGlmZWxzZShpcy5uYShZZXMpLDAsWWVzKSwNCiAgICAgICAgIHNsYV9yYXRlID0gcm91bmQoWWVzLyhZZXMrTm8pLDIpKSAlPiUNCiAgbXV0YXRlKGJhcl9wZXJjZW50YWdlID0gc3ByaW50ZigiJS4xZiUlIiwgMTAwKnNsYV9yYXRlKSkgJT4lIA0KICBtdXRhdGUoYmFyX2xhYmVsID0gcGFzdGUwKGZvcm1hdChZZXMsIGJpZy5tYXJrID0gIiwiKSwgIiB+ICIsIA0KICAgICAgICAgYmFyX3BlcmNlbnRhZ2UpKSAlPiUgc2VsZWN0KC1iYXJfcGVyY2VudGFnZSkNCiAgDQpzdWJjYXQgJT4lIA0KICBmaWx0ZXIoc2xhX3JhdGUhPTApICU+JSANCiAgZ2dwbG90KGFlcyh4PXJlb3JkZXIoc3ViY2F0ZWdvcnksIFllcyksIHk9c2xhX3JhdGUpKSArDQogIGdlb21fY29sKCkgKw0KICBmYWNldF9ncmlkKC5+Y2F0ZWdvcnkpKw0KICAjIEJhciBsYWJlbA0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gYmFyX2xhYmVsKSwgaGp1c3Q9MSwgc2l6ZT0zLCBjb2xvcj0nb3JhbmdlJywNCiAgICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArDQogICMgT3ZlcmFsbCBTTEEgcmF0ZQ0KICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0PWgpLCBjb2xvdXI9IiNCQjAwMDAiLCBsaW5ldHlwZT0iZGFzaGVkIikgKyANCiAgZ2VvbV90ZXh0KGFlcygwLCBoLCBsYWJlbCA9IHNjYWxlczo6cGVyY2VudChoKSwgdmp1c3QgPSAtMC41LCBoanVzdCA9IC0uMiksDQogICAgICAgICAgICBzaXplID0gMy4wLCBjb2xvcj0nY29yYWwzJykgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gJ3NsYSBSYXRlJywNCiAgICAgICB0aXRsZSA9J3NsYSByYXRlcyBieSBzdWJjYXRlZ29yeScpIA0KYGBgDQoNClxwYWdlYnJlYWsNCg0KIyMjI1N1YmNhdGVnb3J5IHcvY29uZmlkYW5jZSBpbnRlcnZhbA0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQppbmMgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKHN1YmNhdGVnb3J5KSkgJT4lIA0KICBsZWZ0X2pvaW4oZnhfc3ViY2F0ZWdvcnlfdCgxMDApLCBieT1jKCdzdWJjYXRlZ29yeScpKSAlPiUgDQogIHNlbGVjdChjYXRlZ29yeSwgc3ViY2F0ZWdvcnk9bmV3X3N1YmNhdGVnb3J5LCBzbGEpICU+JSANCiAgbXV0YXRlKHNsYSA9IGlmZWxzZShzbGE9PSdZZXMnLCAxLCAwKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBzdWJjYXRlZ29yeSwgeSA9IHNsYSkpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9jbF9ub3JtYWwpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgZmFjZXRfZ3JpZCgufmNhdGVnb3J5KSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsNCiAgIyBPdmVyYWxsIFNMQSByYXRlDQogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQ9Znhfb3ZlcmFsbF9zbGEoKSksIGNvbG91cj0iI0JCMDAwMCIsIGxpbmV0eXBlPSJkYXNoZWQiKSArIA0KICBnZW9tX3RleHQoYWVzKDAsIGZ4X292ZXJhbGxfc2xhKCksIGxhYmVsID0gc2NhbGVzOjpwZXJjZW50KGZ4X292ZXJhbGxfc2xhKCkpLCB2anVzdCA9IC0wLjUsIGhqdXN0ID0gLS4yKSwNCiAgICAgICAgICAgIHNpemUgPSAzLjAsIGNvbG9yPSdjb3JhbDMnKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAnc2xhIHJhdGUnLA0KICAgICAgIHRpdGxlID0nc3ViY2F0ZWdvcnkgc2xhIHJhdGVzJykgDQpgYGANCg0KRm9yIGVhY2ggc3ViY2F0ZWdvcnksIHRoZSBTTEEgUmF0ZSBpcyBjYWxjdWxhdGVkIGFuZCBhIDk1JSBjb25maWRlbmNlIGludGVydmFsDQppcyBzaG93biB0byBoZWxwIHVuZGVyc3RhbmQgd2hhdCB0aGUgbm9pc2UgaXMgYXJvdW5kIHRoaXMgdmFsdWUuDQpXZSBjYW4gY2xlYXJseSBzZWUgd2hpY2ggc3ViY2F0ZWdvcmllcyBkZXZpYXRlIGZyb20gcmFuZG9tbmVzcyBhbmQgdGhlIHdpZHRoIG9mDQp0aGUgZXJyb3IgYmFycyBoZWxwIHRoZSByZWFkZXIgdW5kZXJzdGFuZCBob3cgbXVjaCBlYWNoIG51bWJlciBzaG91bGQgYmUgdHJ1c3RlZC4NCg0KXHBhZ2VicmVhaw0KDQojIyMjR3JvdXAgdHlwZQ0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OH0NCnAxIDwtIGluYyAlPiUNCiAgbXV0YXRlKHNsYSA9IGlmZWxzZShzbGE9PSdZZXMnLCAxLCAwKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3IoZ3JvdXBfdHlwZSksIHkgPSBzbGEpKSArDQogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fY2xfbm9ybWFsKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsNCiAgIyBPdmVyYWxsIFNMQSByYXRlDQogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQ9Znhfb3ZlcmFsbF9zbGEoKSksIGNvbG91cj0iI0JCMDAwMCIsIGxpbmV0eXBlPSJkYXNoZWQiKSArDQogIGdlb21fdGV4dChhZXMoMCwgZnhfb3ZlcmFsbF9zbGEoKSwgbGFiZWwgPSBzY2FsZXM6OnBlcmNlbnQoZnhfb3ZlcmFsbF9zbGEoKSksDQogICAgICAgICAgICAgICAgdmp1c3QgPSAtMC41LCBoanVzdCA9IC0uMiksIHNpemUgPSAzLjAsIGNvbG9yPSdjb3JhbDMnKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAnU0xBIHJhdGUnLCB0aXRsZSA9J2dyb3VwIHR5cGUgc2xhIHJhdGVzJykNCg0KbWVkcyA8LSBpbmMgJT4lIGdyb3VwX2J5KGdyb3VwX3R5cGUpICU+JSBzdW1tYXJpc2UobWVkPXJvdW5kKG1lZGlhbihyZXNvbHV0aW9uX3RpbWUpLDEpKQ0KDQpwMiA8LSBpbmMgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9ZmFjdG9yKGdyb3VwX3R5cGUpLCB5PXJlc29sdXRpb25fdGltZSApKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDEyMCkpICsNCiAgIGdlb21fdGV4dChkYXRhID0gbWVkcywgYWVzKHk9bWVkLCBsYWJlbCA9IG1lZCksIHNpemUgPSAzLCB2anVzdCA9IC0xLjUpICsNCiAgbGFicyh0aXRsZT0ibWVkaWFuIHJlc29sdXRpb24gdGltZSBieSBncm91cCB0eXBlIiwNCiAgICAgICB4PSJncm91cCB0eXBlIiwgeT0icmVzb2x1dGlvbiB0aW1lIChob3VycykiKQ0KDQpncmlkLmFycmFuZ2UocDEsIHAyLCBuY29sPTIpDQpgYGANClNlcnZpY2UgZGVzayB0ZWFtcyBoYXZlIHRoZSBoaWdoZXN0IHNsYSByYXRlIGFyb3VuZCA3NiUsIG5leHQgYXJlDQp0aGUgc3VwcG9ydCB0ZWFtcyB3aXRoIHNsYSBvZiA2NCUgYW5kIGxhc3QgYXJlIHRoZSBhcHBsaWNhdGlvbiB0ZWFtcyB3aXRoIDU1JS4NCk9uIHRoZSByaWdodCBzaWRlIG9mIHRoZSBwbG90IHdlIGNhbiBzZWUgdGhlIG1lZGlhbiByZXNvbHV0aW9uIHRpbWUgcGVyIGdyb3VwDQp0eXBlLCB0aGUgcmVzdWx0cyBhcmUgYWNjb3JkaW5nIHRvIHRoZSBleHBlY3RhdGlvbnMuDQoNClxwYWdlYnJlYWsNCg0KIyMjIyNPcmlnaW5hdG9yIEdyb3VwDQpPcmlnaW5hdG9yIGdyb3VwIGlzIHRoZSBmaXJzdCBncm91cCB0aGF0IGhhbmRsZWQgdGhlIHRpY2tldCwgYW5kIGluIG1hbnkgY2FzZXMNCnRoZSBvbmUgdGhhdCByZXNvbHZlZCB0aGUgdGlja2V0Lg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OH0NCmluYyAlPiUgDQogICMgcmVuYW1lKG9yaWdpbmF0b3JfZ3JvdXA9dV9vcmlnaW5hdG9yX2dyb3VwKSAlPiUgDQogIGZpbHRlcighaXMubmEodV9vcmlnaW5hdG9yX2dyb3VwKSkgJT4lIA0KICBzZWxlY3QoeD11X29yaWdpbmF0b3JfZ3JvdXAsIHNsYSkgJT4lDQogIGNvdW50KHgsIHNsYSkgJT4lIA0KICBmaWx0ZXIobj4xMCkgJT4lIA0KICBzcHJlYWQoc2xhLCBuKSAlPiUNCiAgbXV0YXRlKE5vID0gaWZlbHNlKGlzLm5hKE5vKSwwLE5vKSwNCiAgICAgICAgIFllcyA9IGlmZWxzZShpcy5uYShZZXMpLDAsWWVzKSwNCiAgICAgICAgIHNsYV9yYXRlID0gcm91bmQoWWVzLyhZZXMrTm8pLDIpKSAlPiUNCiAgbXV0YXRlKGJhcl9wZXJjZW50YWdlID0gc3ByaW50ZigiJS4xZiUlIiwgMTAwKnNsYV9yYXRlKSkgJT4lIA0KICBtdXRhdGUoYmFyX2xhYmVsID0gcGFzdGUwKGZvcm1hdChZZXMsIGJpZy5tYXJrID0gIiwiKSwgIiB+ICIsIA0KICAgICAgICAgYmFyX3BlcmNlbnRhZ2UpKSAlPiUgc2VsZWN0KC1iYXJfcGVyY2VudGFnZSkgJT4lIA0KICBmaWx0ZXIoc2xhX3JhdGUgPiAwKSAlPiUgDQogIGdncGxvdChhZXMoeCwgeT1zbGFfcmF0ZSkpICsNCiAgZ2VvbV9jb2woKSArDQogICMgQmFyIGxhYmVsDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBiYXJfbGFiZWwpLCBoanVzdD0xLCBzaXplPTMsIGNvbG9yPSdvcmFuZ2UnLA0KICAgICAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsNCiAgIyBPdmVyYWxsIFNMQSByYXRlDQogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQ9aCksIGNvbG91cj0iI0JCMDAwMCIsIGxpbmV0eXBlPSJkYXNoZWQiKSArIA0KICBnZW9tX3RleHQoYWVzKDAsIGgsIGxhYmVsID0gc2NhbGVzOjpwZXJjZW50KGgpLCB2anVzdCA9IDAsIGhqdXN0ID0gMCksDQogICAgICAgICAgICBzaXplID0gMy4wLCBjb2xvcj0nY29yYWwzJykgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gJ3NsYSBSYXRlJywNCiAgICAgICB0aXRsZSA9J29yaWdpbmF0b3IgZ3JvdXAgc2xhIHJhdGVzJykgDQpgYGANCg0KXHBhZ2VicmVhaw0KDQojIyMjUmVnaW9uIG9mIGFzc2lnbm1lbnQgZ3JvdXANCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTh9DQppbmMgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKHJlZ2lvbikpICU+JSANCiAgc2VsZWN0KHg9cmVnaW9uLCBzbGEpICU+JQ0KICBjb3VudCh4LCBzbGEpICU+JSANCiAgIyBmaWx0ZXIobj4xMCkgJT4lDQogIHNwcmVhZChzbGEsIG4pICU+JQ0KICBtdXRhdGUoTm8gPSBpZmVsc2UoaXMubmEoTm8pLDAsTm8pLA0KICAgICAgICAgWWVzID0gaWZlbHNlKGlzLm5hKFllcyksMCxZZXMpLA0KICAgICAgICAgc2xhX3JhdGUgPSByb3VuZChZZXMvKFllcytObyksMikpICU+JQ0KICBtdXRhdGUoYmFyX3BlcmNlbnRhZ2UgPSBzcHJpbnRmKCIlLjFmJSUiLCAxMDAqc2xhX3JhdGUpKSAlPiUgDQogIG11dGF0ZShiYXJfbGFiZWwgPSBwYXN0ZTAoZm9ybWF0KFllcywgYmlnLm1hcmsgPSAiLCIpLCAiIH4gIiwgDQogICAgICAgICBiYXJfcGVyY2VudGFnZSkpICU+JSBzZWxlY3QoLWJhcl9wZXJjZW50YWdlKSAlPiUgDQogIGdncGxvdChhZXMoeD1yZW9yZGVyKHgsIHNsYV9yYXRlKSwgeT1zbGFfcmF0ZSkpICsNCiAgZ2VvbV9jb2woKSArDQogICMgQmFyIGxhYmVsDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBiYXJfbGFiZWwpLCBoanVzdD0xLCBzaXplPTMsIGNvbG9yPSdvcmFuZ2UnLA0KICAgICAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsNCiAgIyBPdmVyYWxsIFNMQSByYXRlDQogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQ9aCksIGNvbG91cj0iI0JCMDAwMCIsIGxpbmV0eXBlPSJkYXNoZWQiKSArIA0KICBnZW9tX3RleHQoYWVzKDAsIGgsIGxhYmVsID0gc2NhbGVzOjpwZXJjZW50KGgpLCB2anVzdCA9IDAsIGhqdXN0ID0gMCksDQogICAgICAgICAgICBzaXplID0gMy4wLCBjb2xvcj0nY29yYWwzJykgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gJ3NsYSByYXRlJywNCiAgICAgICB0aXRsZSA9J3JlZ2lvbiBzbGEgcmF0ZScpIA0KYGBgDQoNClxwYWdlYnJlYWsNCg0KIyMjVXJnZW5jeQ0KIyMjIyNDb250YWN0IHR5cGUNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTh9DQppbmMgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKGNvbnRhY3RfdHlwZSkpICU+JSANCiAgc2VsZWN0KHg9Y29udGFjdF90eXBlLCBzbGEpICU+JQ0KICBjb3VudCh4LCBzbGEpICU+JSANCiAgZmlsdGVyKG4+MTApICU+JQ0KICBzcHJlYWQoc2xhLCBuKSAlPiUNCiAgbXV0YXRlKE5vID0gaWZlbHNlKGlzLm5hKE5vKSwwLE5vKSwNCiAgICAgICAgIFllcyA9IGlmZWxzZShpcy5uYShZZXMpLDAsWWVzKSwNCiAgICAgICAgIHNsYV9yYXRlID0gcm91bmQoWWVzLyhZZXMrTm8pLDIpKSAlPiUNCiAgbXV0YXRlKGJhcl9wZXJjZW50YWdlID0gc3ByaW50ZigiJS4xZiUlIiwgMTAwKnNsYV9yYXRlKSkgJT4lIA0KICBtdXRhdGUoYmFyX2xhYmVsID0gcGFzdGUwKGZvcm1hdChZZXMsIGJpZy5tYXJrID0gIiwiKSwgIiB+ICIsIA0KICAgICAgICAgYmFyX3BlcmNlbnRhZ2UpKSAlPiUgc2VsZWN0KC1iYXJfcGVyY2VudGFnZSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHgsIHk9c2xhX3JhdGUpKSArDQogIGdlb21fY29sKCkgKw0KICAjIEJhciBsYWJlbA0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gYmFyX2xhYmVsKSwgaGp1c3Q9MSwgc2l6ZT0zLCBjb2xvcj0nb3JhbmdlJywNCiAgICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArDQogICMgT3ZlcmFsbCBTTEEgcmF0ZQ0KICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0PWgpLCBjb2xvdXI9IiNCQjAwMDAiLCBsaW5ldHlwZT0iZGFzaGVkIikgKyANCiAgZ2VvbV90ZXh0KGFlcygwLCBoLCBsYWJlbCA9IHNjYWxlczo6cGVyY2VudChoKSwgdmp1c3QgPSAwLCBoanVzdCA9IDApLA0KICAgICAgICAgICAgc2l6ZSA9IDMuMCwgY29sb3I9J2NvcmFsMycpICsNCiAgbGFicyh4ID0gTlVMTCwgeSA9ICdzbGEgcmF0ZScsDQogICAgICAgdGl0bGUgPSdjb250YWN0IHR5cGUgc2xhIHJhdGUnKSANCiANCmBgYA0KDQpccGFnZWJyZWFrDQoNCiMjI1RlbXBvcmFsDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQ0KaW5jICU+JSANCiAgbXV0YXRlKHdkYXkgPSB3ZGF5KG9wZW5lZF9hdCwgbGFiZWwgPSBUUlVFKSkgJT4lIA0KICBjb3VudCh3ZGF5LCBzbGEpICU+JSANCiAgc3ByZWFkKHNsYSwgbikgJT4lDQogIG11dGF0ZShObyA9IGlmZWxzZShpcy5uYShObyksMCxObyksDQogICAgICAgICBZZXMgPSBpZmVsc2UoaXMubmEoWWVzKSwwLFllcyksDQogICAgICAgICBzbGFfcmF0ZSA9IHJvdW5kKFllcy8oWWVzK05vKSwyKSkgJT4lDQogIG11dGF0ZShiYXJfcGVyY2VudGFnZSA9IHNwcmludGYoIiUuMWYlJSIsIDEwMCpzbGFfcmF0ZSkpICU+JSANCiAgbXV0YXRlKGJhcl9sYWJlbCA9IHBhc3RlMChmb3JtYXQoWWVzLCBiaWcubWFyayA9ICIsIiksICIgfiAiLCANCiAgICAgICAgIGJhcl9wZXJjZW50YWdlKSkgJT4lIHNlbGVjdCgtYmFyX3BlcmNlbnRhZ2UpICU+JQ0KICBnZ3Bsb3QoYWVzKHdkYXksIHk9c2xhX3JhdGUpKSArDQogIGdlb21fY29sKCkgKw0KICAjIEJhciBsYWJlbA0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gYmFyX2xhYmVsKSwgaGp1c3Q9MSwgc2l6ZT0zLCBjb2xvcj0nb3JhbmdlJywNCiAgICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArDQogICMgT3ZlcmFsbCBTTEEgcmF0ZQ0KICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0PWgpLCBjb2xvdXI9IiNCQjAwMDAiLCBsaW5ldHlwZT0iZGFzaGVkIikgKyANCiAgZ2VvbV90ZXh0KGFlcygwLCBoLCBsYWJlbCA9IHNjYWxlczo6cGVyY2VudChoKSwgdmp1c3QgPSAwLCBoanVzdCA9IDApLA0KICAgICAgICAgICAgc2l6ZSA9IDMuMCwgY29sb3I9J2NvcmFsMycpICsNCiAgbGFicyh4ID0gJ3dlZWtkYXknLCB5ID0gJ3NsYSByYXRlJywNCiAgICAgICB0aXRsZSA9J3dlZWtkYXkgc2xhIHJhdGVzJykNCiAgDQpgYGANCklmIHRoZSB0aWNrZXQgd2FzIG9wZW5lZCBvbiBGcmlkYXkgb3IgU2F0dXJkYXkgaXQgaGFzIGxvd2VyIGNoYW5jZXMgdG8gYmUNCnJlc29sdmVkIG9uIHRpbWUuDQoNClxwYWdlYnJlYWsNCg0KIyMjRGF0YSBTcGxpdGluZw0KUmFuZG9tIHNwbGl0IG9mIHRoZSB0cmFpbmluZyBkYXRhIGJhc2VkIG9uIDEwLzkwIHBlcmNlbnQgc3BsaXQsIDEwJSBnb2VzIGZvciB0ZXN0aW5nLg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmluYyA8LSBpbmMgJT4lIA0KICBsZWZ0X2pvaW4oZnhfcmFuZG9tX3NwbGl0KC45MCksIGJ5PSdudW1iZXInKQ0KYGBgDQoNCiMjI0ZlYXR1cmUgRW5naW5uZXJpbmcNClRoZSBmZWF0dXJlcyB0aGF0IGdvZXMgaW50byB0aGUgbW9kZWw6DQoNCiAqIEluY2lkZW50IFR5cGUNCiAgICAqIHRvcGljICh0ZXh0IGFuYWx5dGljcykNCiAgICAqIHN1YmNhdGVnb3J5DQogICAgKiBjYXNlIHR5cGUNCg0KICogQ29tcGxleGl0eQ0KICAgICogZGlmZmljdWx0eSAodGV4dCBhbmFseXRpY3MpDQogICAgKiB3b3JkcyBpbiBkZXNjcmlwdGlvbiAodGV4dCBhbmFseXRpY3MpDQogIA0KICogVXJnZW5jeQ0KICAgICogY29udGFjdF90eXBlDQogDQogKiBQZXJmb3JtYW5jZQ0KICAgICogZ3JwTiAtIGFzc2lnbm1lbnQgZ3JvdXAgYmlubmVkIG51bWJlciBvZiB0aWNrZXRzIHJlc29sdmVkLg0KICAgICogZ3JwVCAtIGFzc2lnbm1lbnQgZ3JvdXAgYmlubmVkIG1lZGlhbiByZXNvbHV0aW9uIHRpbWUuDQogICAgKiB1c2VyTiAtIGFzc2lnbmVlIGJpbm5lZCBudW1iZXIgb2YgdGlja2V0cyByZXNvbHZlZC4NCiAgICAqIHVzZXJUIC0gYXNzaWduZWUgYmlubmVkIG1lZGlhbiByZXNvbHV0aW9uIHRpbWUuDQogICAgDQogKiBGbG93DQogICAgKiBhc3NpZ25tZW50X2dyb3VwX2NoYW5nZSBpbmRpY2F0b3INCiAgICAqIGFzc2lnbmVkX3RvX2NoYW5nZSBpbmRpY2F0b3INCiAgICANCiAqIFRlbXBvcmFsDQogICAgKiBvcGVuZWRfYXQgZGF5IG9mIHRoZSB3ZWVrLg0KICANCiAqIFdvcmtmb3JjZSAgDQogICAgKiBhc3NpZ25tZW50IGdyb3VwDQogICAgKiBncm91cCB0eXBlDQogICAgKiBvcmlnaW5hdG9yIGdyb3VwDQogICAgKiBkZXBhcnRtZW50DQogDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KYWJ0IDwtIGluYyAlPiUNCiAgbXV0YXRlKGRpZmZpY3VsdHkgPSBpZmVsc2Uoc3RyX2RldGVjdChzdHJfdG9fbG93ZXIoc2hvcnRfZGVzY3JpcHRpb24pLA0KICAgICcoZXJyb3J8cHJvYmxlbXxpc3N1ZXx1bmFibGV8ZmFpbGVkfG1pc3Npbmd8DQogICAgbmVlZHN8d3Jvbmd8c2xvd3xsb2NrZWR8ZGlzYWJsZWQpJyApICYgIWlzLm5hKHNob3J0X2Rlc2NyaXB0aW9uKSwxLDApKSAlPiUNCiAgIyB0b3BpYyAodGV4dCBhbmFseXRpY3MpIA0KICBsZWZ0X2pvaW4oZnhfdG9waWMoKSwgYnk9J251bWJlcicpICU+JSANCiAgIyBXZWVrZGF5DQogIG11dGF0ZSh3ZGF5ID0gZmFjdG9yKHdkYXkob3BlbmVkX2F0LCBsYWJlbCA9IFRSVUUpLCBvcmRlcmVkID0gRkFMU0UgKSkgJT4lDQogICMgV29yZHMgaW4gZGVzY3JpcHRpb24gKGJpbm5pbmcpDQogIG11dGF0ZSh3b3JkcyA9IHN0cl9jb3VudChzaG9ydF9kZXNjcmlwdGlvbiwgIlxcUysiKSwNCiAgICAgICAgIHdvcmRzID0gaWZlbHNlKGlzLm5hKHdvcmRzKSwwLHdvcmRzKSkgJT4lIA0KICAjIENhc2UgdHlwZSAoY2xlYW5zaW5nKQ0KICBtdXRhdGUoY2FzZV90eXBlID0gc3RyX3JlcGxhY2VfYWxsKHN0cl90b19sb3dlcih1X2Nhc2VfdHlwZSksDQogICAgICAgICAgICAgICAgICAnKFtbOnB1bmN0Ol1dfFxccyknLCAnXycpKSAlPiUgDQogICMgT3JpZ2luYXRvciBncm91cCAoY29sbGFwc2UgbWlub3Igb2NjdXJyZW5jZXMpDQogIGxlZnRfam9pbihmeF9vcmlnX2dyb3VwX3QoMjApLCBieT1jKCd1X29yaWdpbmF0b3JfZ3JvdXAnKSkgJT4lIA0KICAjIHN1YmNhdGVnb3J5IChjb2xsYXBzZSBtaW5vciBvY2N1cnJlbmNlcykNCiAgbGVmdF9qb2luKGZ4X3N1YmNhdGVnb3J5X3QoMjApLCBieT1jKCdzdWJjYXRlZ29yeScpKSAlPiUgDQogICMgYXNzaWduZWUgcGVyZm9ybWFuY2UgKEZFKQ0KICBsZWZ0X2pvaW4oZnhfYXNzaWduZWVfcGVyZigpLCBieT1jKCdhc3NpZ25lZF90bycpKSAlPiUNCiAgIyBncm91cCBwZXJmb3JtYW5jZSAoRkUpDQogIGxlZnRfam9pbihmeF9ncnBfcGVyZigpLCBieT1jKCdhc3NpZ25tZW50X2dyb3VwJz0ndV9yZXNvbHZlcl9ncm91cCcpKSAlPiUgDQogICMgU2VsZWN0aW9uDQogIHNlbGVjdChkaWZmaWN1bHR5LCANCiAgICAgICAgIGNhdGVnb3J5LA0KICAgICAgICAgY2FzZV90eXBlLA0KICAgICAgICAgd29yZHMsIA0KICAgICAgICAgY29udGFjdF90eXBlLCANCiAgICAgICAgIGRlcGFydG1lbnQ9dV9kZXBhcnRtZW50LA0KICAgICAgICAgb3JpZ19ncm91cD1uZXdfb3JpZ19ncm91cCwNCiAgICAgICAgIGFzc2lnbm1lbnRfZ3JvdXAsDQogICAgICAgICBzdWJjYXRlZ29yeT1uZXdfc3ViY2F0ZWdvcnksDQogICAgICAgICBncnBOLCBncnBULCB3ZGF5LCANCiAgICAgICAgIGdyb3VwX3R5cGUsDQogICAgICAgICByZWdpb24sDQogICAgICAgICB1c2VyTiwgdXNlclQsDQogICAgICAgICBhc3NpZ25tZW50X2dyb3VwX2NoYW5nZT11X2Fzc2lnbm1lbnRfZ3JvdXBfY2hhbmdlLA0KICAgICAgICAgYXNzaWduZWRfdG9fY2hhbmdlPXVfYXNzaWduZWRfdG9fY2hhbmdlLA0KICAgICAgICAgc2xhLCBkYXRhc2V0LCANCiAgICAgICAgIGVuZHNfd2l0aCgiVCIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUNCiAgIyByZXBsYWNlIG51bGxzDQogIHJlcGxhY2UoLiwgaXMubmEoLiksICJ1bmtub3duIikgJT4lIA0KICAjIEZhY3Rvcml6YXRpb24NCiAgbXV0YXRlKHNsYSA9IGZhY3RvcihzbGEpLA0KICAgICAgICAgY2F0ZWdvcnkgPSBmYWN0b3IoY2F0ZWdvcnkpLA0KICAgICAgICAgc3ViY2F0ZWdvcnkgPSBmYWN0b3Ioc3ViY2F0ZWdvcnkpLA0KICAgICAgICAgY2FzZV90eXBlID0gZmFjdG9yKGNhc2VfdHlwZSksDQogICAgICAgICBvcmlnX2dyb3VwID0gZmFjdG9yKG9yaWdfZ3JvdXApLA0KICAgICAgICAgYXNzaWdubWVudF9ncm91cCA9IGZhY3Rvcihhc3NpZ25tZW50X2dyb3VwKSwNCiAgICAgICAgIGNvbnRhY3RfdHlwZSA9IGZhY3Rvcihjb250YWN0X3R5cGUpLA0KICAgICAgICAgZGVwYXJ0bWVudCA9IGZhY3RvcihkZXBhcnRtZW50KSwNCiAgICAgICAgIGdycE4gPSBmYWN0b3IoZ3JwTiksDQogICAgICAgICBncnBUID0gZmFjdG9yKGdycFQpLA0KICAgICAgICAgdXNlck4gPSBmYWN0b3IodXNlck4pLA0KICAgICAgICAgdXNlclQgPSBmYWN0b3IodXNlclQpLA0KICAgICAgICAgd2RheSA9IGZhY3Rvcih3ZGF5KSwNCiAgICAgICAgIGdyb3VwX3R5cGUgPSBmYWN0b3IoZ3JvdXBfdHlwZSksDQogICAgICAgICByZWdpb24gPSBmYWN0b3IocmVnaW9uKSwNCiAgICAgICAgIGRpZmZpY3VsdHkgPSBmYWN0b3IoZGlmZmljdWx0eSksIA0KICAgICAgICAgYXNzaWdubWVudF9ncm91cF9jaGFuZ2UgPSBmYWN0b3IoYXNzaWdubWVudF9ncm91cF9jaGFuZ2UpLA0KICAgICAgICAgYXNzaWduZWRfdG9fY2hhbmdlID0gZmFjdG9yKGFzc2lnbmVkX3RvX2NoYW5nZSkpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgZm9yIG5pY2VyIHRyZWUgbGFiZWxzDQphYnQgPC0gYWJ0ICU+JSANCiAgcmVuYW1lKGNhc2UuPWNhc2VfdHlwZSwNCiAgICAgICAgIGNhdC49Y2F0ZWdvcnksDQogICAgICAgICBjb250YWN0Lj1jb250YWN0X3R5cGUsDQogICAgICAgICBkZXB0Lj1kZXBhcnRtZW50LA0KICAgICAgICAgb3JpZ0dycC49b3JpZ19ncm91cCwNCiAgICAgICAgICMgcmVzb2x2ZUdycD1yZXNvbHZlcl9ncm91cCwNCiAgICAgICAgIHN1YkNhdC49c3ViY2F0ZWdvcnksDQogICAgICAgICBncnBDaGcuPWFzc2lnbm1lbnRfZ3JvdXBfY2hhbmdlLA0KICAgICAgICAgdXNlckNoZy49YXNzaWduZWRfdG9fY2hhbmdlLA0KICAgICAgICAgZ3JwVHlwZS49Z3JvdXBfdHlwZSwNCiAgICAgICAgIHJlZ2lvbi49cmVnaW9uKQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojRGF0YSBTcGxpdHRpbmcgDQp0cmFpbiA8LSBhYnQgJT4lIGZpbHRlcihkYXRhc2V0PT0ndHJhaW4nKSAlPiUgc2VsZWN0KC1kYXRhc2V0KQ0KdGVzdCA8LSBhYnQgJT4lIGZpbHRlcihkYXRhc2V0PT0ndGVzdCcpICU+JSBzZWxlY3QoLWRhdGFzZXQpDQpgYGANCg0KIyMjI01vZGVsIFRyYWluaW5nIC0gRGVjaXNpb24gVHJlZSANCmBgYHtyIERFQ0lTVElPTiBUUkVFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kc3VwcHJlc3NNZXNzYWdlcyhsaWJyYXJ5KGRvUGFyYWxsZWwpKQ0KY2wgPC0gbWFrZUNsdXN0ZXIoZGV0ZWN0Q29yZXMoKSkNCnJlZ2lzdGVyRG9QYXJhbGxlbChjbCkNCg0KZml0Q29udHJvbCA8LSB0cmFpbkNvbnRyb2wobWV0aG9kID0gInJlcGVhdGVkY3YiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyID0gMTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICByZXBlYXRzID0gMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzUHJvYnMgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtbWFyeUZ1bmN0aW9uID0gdHdvQ2xhc3NTdW1tYXJ5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3dQYXJhbGxlbCA9IFRSVUUpDQpsaWJyYXJ5KHJwYXJ0KQ0Kc2V0LnNlZWQoMTIzKQ0KY2FydCA8LSB0cmFpbihzbGEgfiAuICwNCiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHRyYWluLA0KICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAicnBhcnQiLA0KICAgICAgICAgICAgICAgICAgICAjIHR1bmVHcmlkPWV4cGFuZC5ncmlkKGNwPTAuMDIpLA0KICAgICAgICAgICAgICAgICAgICB0dW5lTGVuZ3RoID0gMTAsDQogICAgICAgICAgICAgICAgICAgIHRyQ29udHJvbCA9IGZpdENvbnRyb2wsDQogICAgICAgICAgICAgICAgICAgIG1ldHJpYyA9ICJST0MiLA0KICAgICAgICAgICAgICAgICAgICBuYS5hY3Rpb24gPSBuYS5wYXNzKQ0Kc3RvcENsdXN0ZXIoY2wpDQoNCiMgcHJpbnQoY2FydCRyZXN1bHRzKQ0KYGBgDQoNCg0KIyMjI1Rlc3QgUGVyZm9ybWFuY2UNCmBgYHtyIGVjaG89RkFMU0V9DQojIHRlc3QgcHJlZGljdGlvbg0KdGVzdC5wcmVkIDwtIHByZWRpY3QoY2FydCwgbmV3ZGF0YSA9IHRlc3QsIHR5cGU9ICdyYXcnLCBuYS5hY3Rpb24gPSBuYS5wYXNzKQ0KIyB0ZXN0IGV2YWx1YXRpb24NCmNvbmZ1c2lvbk1hdHJpeCh0ZXN0LnByZWQsIHRlc3Qkc2xhLCBwb3NpdGl2ZT0nWWVzJykNCmBgYA0KDQpBY2N1cmFjeSBvZiA3NC44NCUgY29tcGFyZSBvZiA2NC4xNyUgb2YgbWFqb3JpdHkgdm90ZSBtb2RlbC4NCndoaWNoIGlzIGEgMTYlIGltcHJvdmVtZW50Lg0KdGhlIG1vZGVsIGhhcyBoYXJkIHRpbWUgdG8gcHJlZGljdCBjb3JyZWN0bHkgaW5jaWRlbnRzIHRoYXQgd2lsbCBub3QgbWVldCB0aGUgU0xBLg0KSW4gYW4gYXR0ZW1wdCB0byBpbXByb3ZlIHRoZSBsZWFybmluZyBwcm9jZXNzIGxldCdzIHVzZSByYW5kb20gZm9yZXN0IHdoaWNoIGlzDQphIGJhZ2dpbmcgKEJvb3RzdHJhcCBBZ2dyZWdhdGlvbikgRGVjaXNpb24gVHJlZSBFbnNlbWJsZS4NCg0KXHBhZ2VicmVhaw0KDQojIyMjRmVhdHVyZSBJbXBvcnRhbmNlDQpgYGB7ciBGRUFUVVJFIElNUE9SVEFOQ0UsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpmeF92YXJfaW1wKGNhcnQsMSkNCmBgYA0KDQpccGFnZWJyZWFrDQoNCiMjIyNEZWNpc3Rpb24gVHJlZSBQbG90DQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnN1cHByZXNzTWVzc2FnZXMobGlicmFyeShycGFydC5wbG90KSkNCiMgcnBhcnQucGxvdChjYXJ0JGZpbmFsTW9kZWwpDQojIHJwYXJ0LnBsb3QoY2FydCRmaW5hbE1vZGVsLCB0eXBlPTMsIHR3ZWFrID0gMS4yKQ0KcnBhcnQucGxvdChjYXJ0JGZpbmFsTW9kZWwsIHllc25vID0gMiwgdHlwZSA9IDAsIGV4dHJhID0gMCwgdHdlYWsgPSAxLjQpDQpgYGANCg0KYGBge3IgVFJBSU4gUFJFRElDVElPTiwgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCiMjIyNUcmFpbiBQZXJmb3JtYW5jZQ0KIyB0cmFpbiBwcmVkaWN0aW9uDQp0cmFpbi5wcmVkIDwtIHByZWRpY3QoY2FydCwgbmV3ZGF0YSA9IHRyYWluLCB0eXBlPSAncmF3JywgbmEuYWN0aW9uID0gbmEucGFzcykNCiMgdHJhaW4gZXZhbHVhdGlvbg0KY29uZnVzaW9uTWF0cml4KHRyYWluLnByZWQsIHRyYWluJHNsYSwgcG9zaXRpdmU9J1llcycpDQpgYGANCg0KXHBhZ2VicmVhaw0KDQojIyMjTW9kZWwgVHJhaW5pbmcgLSBSYW5kb20gRm9yZXN0DQpgYGB7ciBSYW5kb20gRm9yZXN0LCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBsb2FkIHRoZSBtb2RlbA0Kc3VwcHJlc3NNZXNzYWdlcyhsaWJyYXJ5KHJhbmdlcikpDQojIHJmIDwtIHJlYWRSRFMoIi4vcmZfZmluYWxfbW9kZWwucmRzIikNCnN1cHByZXNzTWVzc2FnZXMobGlicmFyeShkb1BhcmFsbGVsKSkNCmNsIDwtIG1ha2VDbHVzdGVyKGRldGVjdENvcmVzKCkpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCmZpdENvbnRyb2wgPC0gdHJhaW5Db250cm9sKG1ldGhvZCA9ICJjdiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBudW1iZXIgPSA1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NQcm9icyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5RnVuY3Rpb24gPSB0d29DbGFzc1N1bW1hcnksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvd1BhcmFsbGVsID0gVFJVRSkNCg0Kc3VwcHJlc3NNZXNzYWdlcyhsaWJyYXJ5KHJhbmdlcikpDQpzZXQuc2VlZCgxMjMpDQpyZiA8LSB0cmFpbihzbGEgfiAuICwNCiAgICAgICAgICAgIGRhdGEgPSB0cmFpbiwNCiAgICAgICAgICAgIG1ldGhvZCA9ICJyYW5nZXIiLA0KICAgICAgICAgICAgbWV0cmljID0gIlJPQyIsDQogICAgICAgICAgICB0dW5lR3JpZD1leHBhbmQuZ3JpZChtdHJ5PTY5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BsaXRydWxlPSJleHRyYXRyZWVzIiwgbWluLm5vZGUuc2l6ZT0xKSwNCiAgICAgICAgICAgICMgdHVuZUxlbmd0aCA9IDUsDQogICAgICAgICAgICBpbXBvcnRhbmNlID0gImltcHVyaXR5IiwNCiAgICAgICAgICAgIHRyQ29udHJvbCA9IGZpdENvbnRyb2wpDQpzdG9wQ2x1c3RlcihjbCkNCiMgcHJpbnQocmYkcmVzdWx0cykNCiMgc2F2ZVJEUyhyZiRmaW5hbE1vZGVsLCAiLi9yZl9maW5hbF9tb2RlbC5yZHMiKQ0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojICMgdHJhaW4gcHJlZGljdGlvbg0KIyB0cmFpbi5wcmVkIDwtIHByZWRpY3QocmYsIHRyYWluKQ0KIyAjIHRyYWluIGV2YWx1YXRpb24NCiMgY29uZnVzaW9uTWF0cml4KHRyYWluLnByZWQsIHRyYWluJHNsYSwgcG9zaXRpdmU9J1llcycpDQojIHRlc3QgcHJlZGljdGlvbg0KdGVzdC5wcmVkIDwtIHByZWRpY3QocmYsIG5ld2RhdGEgPSB0ZXN0KQ0KIyB0ZXN0IGV2YWx1YXRpb24NCmNvbmZ1c2lvbk1hdHJpeCh0ZXN0LnByZWQsIHRlc3Qkc2xhLCBwb3NpdGl2ZT0nWWVzJykNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KZnhfdmFyX2ltcChyZiwgMTApDQpgYGANCg0KVXNpbmcgdGhlIFJhbmRvbUZvcmVzdCBtb2RlbCB3ZSB3ZXJlIGFibGUgdG8gaW5jcmVhc2UgdGhlIGFjY3VyYWN5IHRvIDc3LjU2JSBvbiB0aGUgdGVzdCBzZXQNCmNvbXBhcmUgdG8gNzQuODQlIGZvciBhIHNpbmdsZSBkZWNpc2lvbiB0cmVlLg0KDQpNb3JlIGltcG9ydGFudGx5IHRoZSBSRiBtb2RlbCBpcyBkb2luZyBhIGJldHRlciBqb2IgaW4gcHJlZGljdGluZyB0aGUgaW5jaWRlbnRzIHRoYXQgd2lsbCBub3QgbWVldCB0aGUgU0xBLg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=