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.
Incident Type - what is the nature of the incident, and to what area it belongs.
Complexity - how complex is the problem at hand.
Urgency - how urgent is it to resolve the problem.
Performance - relate to the performance of the assignee and the assignment group.
Flow - workload, pending tickets, tickets in process, group transitions etc..
Temporal - like day of the week, hour of the day.
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

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:
- Incident Type
- topic (text analytics)
- subcategory
- case type
- Complexity
- difficulty (text analytics)
- words in description (text analytics)
- Urgency
- Performance
- grpN - assignment group binned number of tickets resolved.
- grpT - assignment group binned median resolution time.
- userN - assignee binned number of tickets resolved.
- userT - assignee binned median resolution time.
- Flow
- assignment_group_change indicator
- assigned_to_change indicator
- Temporal
- opened_at day of the week.
- Workforce
- assignment group
- group type
- originator group
- department
Model Training - Decision Tree
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=