Introduction

Individuals across the globe are urged to slow the spread of COVID-19. Governments are implementing everything from mild shelter in place to extreme shoot them dead measures to control this global crisis.

All these efforts are in hopes of flattening the curve. According to this article, high peaks put a lot of pressure on health care systems which they struggle to respond to.

So what does this curve look like for my state of Virginia? I’ve seen a rising curve for the entire United States, but I’ve only seen the current number of cases for a particular day. I don’t know how this number compares to last week.

World O Meter and Bing’s Coronoavirus updates provide nice summaries, but neither of these web sites showed the trend of confirmed cases over time.

All I needed was the data. After countless searches, I stumbled upon the University of Virginia’s COVID-19 Surveillance Dashboard. It is a nice real-time dashboard that also allows one to download data. Upon inspection of the provided datasets, I found what I was looking for.

This personal project is my attempt to understand the COVID-19 curve and how the number of cases affects the shape of the curve.

Let’s get started.

Sample Data From Imported Files
Name Region Last_Update Confirmed Deaths Recovered
Ningxia Mainland China 2020-03-17 02:00:00 75 0 75
Azerbaijan Azerbaijan 2020-06-04 03:00:00 6260 76 3665
Poland Poland 2020-04-18 17:00:00 8742 347 981
Guyana Guyana 2020-04-18 00:00:00 63 6 9
Angola Angola 2020-05-01 03:00:00 27 2 7
Nevada USA 2020-06-01 03:00:00 8628 417 6316
Mauritius Mauritius 2020-05-29 03:00:00 334 10 322
South Korea South Korea 2020-05-30 12:00:00 11441 269 10398
Belgium Belgium 2020-02-18 15:00:00 1 0 1
Jersey Jersey 2020-03-14 18:00:00 2 0 0

     

After loading the datafile, we find the dataset contains 30599 records, 215 areas of interests with information dated from 2020-01-22 12:00:00 and 2020-06-10 10:00:00.

Globally, there are 7253278 confirmed COVID-19 cases, 411279 deaths, and 3349900 who recovered.


   

What does the curve look like for the US as a whole? This is the graphic we see in mainstream media. Currently there are 1985454 confirmed cases in the United States.

           

Seeing the big picture can be overwhelming. Let’s break it down by regions.

           

Fast rising curves identify those hot spots and priority regions. But what about those states that don’t show a steep rising curve? Are they of concern?
The above graphs group states by regions. One state with a high number of cases could skew the graph for the region. To take this into account and to show the rate of change over time, let’s plot the information on a logarithmic scale.

Graphs with steep curves show states hit hardest by the COVID-19 virus.

           

What does the Virginia curve show?


           

Summary of U.S. Areas of Interest

Summary of US Areas of Interest
Name group Confirmed Deaths Recovered
Midwest
Illinois Midwest 129212 6018 70558
Michigan Midwest 64998 5943 42041
Ohio Midwest 39163 2423 5090
Indiana Midwest 38033 2339 2159
Minnesota Midwest 28523 1228 24221
Iowa Midwest 22236 628 13514
Wisconsin Midwest 21308 661 14583
Nebraska Midwest 15918 189 7598
Missouri Midwest 15352 845 3511
Kansas Midwest 10609 237 5578
South Dakota Midwest 5523 68 4483
North Dakota Midwest 2901 72 2450
Northeast
New York Northeast 384561 30458 47715
New Jersey Northeast 164796 12303 3856
Massachusetts Northeast 103889 7408 78108
Pennsylvania Northeast 80870 6014 1369
Connecticut Northeast 44179 4097 63
Rhode Island Northeast 15691 808 1398
Puerto Rico Northeast 5185 142 850
New Hampshire Northeast 5132 294 3501
Maine Northeast 2606 100 1992
Vermont Northeast 1084 55 901
US Virgin Islands Northeast 71 6 63
South
Texas South 78130 1867 51140
Florida South 66000 2766 381
Maryland South 58904 2811 4279
Georgia South 53249 2285 340
Virginia South 51738 1497 6677
Louisiana South 43612 2957 33904
North Carolina South 37228 1068 23653
Tennessee South 27575 435 18017
Alabama South 21422 729 11395
Mississippi South 18123 847 11203
South Carolina South 15228 568 5076
Kentucky South 11708 477 3359
Arkansas South 10080 161 6875
Delaware South 10020 410 5888
District of Columbia South 9474 495 1143
Oklahoma South 7363 354 6080
West Virginia South 2179 84 1482
West
California West 137060 4753 22258
Colorado West 28354 1554 2404
Arizona West 28296 1076 174
Washington West 25048 1175 5156
Utah West 12559 127 4006
Nevada West 10045 446 7381
New Mexico West 9105 404 3699
Oregon West 4988 169 1894
Idaho West 3221 85 2509
Wyoming West 970 17 789
Hawaii West 682 17 621
Alaska West 573 11 389
Montana West 554 18 485
Guam West 180 5 143
Northern Mariana Islands West 30 2 16
Note: There appears to be a discrepancy to how recoveries are recorded by state. Based upon Bing's COVID-19 stats, some of the recoveries are correct whereas others are not.

States With Most Confirmed Cases
Name # Confirmed Cases
New York 384561
New Jersey 164796
California 137060
Illinois 129212
Massachusetts 103889
Pennsylvania 80870
Texas 78130
Florida 66000
Michigan 64998
Maryland 58904
States With The Largest Daily Change of Confirmed Cases
Name Change In Number of Confirmed Cases From Yesterday
California 3244
Texas 1667
Florida 1096
Illinois 797
Georgia 752
North Carolina 710
New York 668
Arizona 618
Tennessee 570
Louisiana 562
States With Most Deaths
Name # Deaths
New York 30458
New Jersey 12303
Massachusetts 7408
Illinois 6018
Pennsylvania 6014
Michigan 5943
California 4753
Connecticut 4097
Louisiana 2957
Maryland 2811
States With Most Recovered Cases
Name # Recoveries
Massachusetts 78108
Illinois 70558
Texas 51140
New York 47715
Michigan 42041
Louisiana 33904
Minnesota 24221
North Carolina 23653
California 22258
Tennessee 18017
Note: Discrepancies found in how recoveries are recorded by state.


           


A former colleague and Old Dominion University professor, Dr. Chuck Cartledge, provided valuable feedback on my inital attempt on analyzing this information. He also referred me to this insightful How To Tell If We’re Beating COVID-19 video.

Three key points were discussed 1) use a logarithmic scale, 2) focus on change, not absolute numbers, and 3) don’t plot against time.

Taking this into account, let’s take a look at Virginia again.

The following graphs plot the total number of confirmed cases on the x-axis (Confirmed column) and the daily change of confirmed cases (delta_confirmed column) on the y-axis.

Virginia COVID-19 Data
Name Last_Update Confirmed Deaths Recovered delta_confirmed delta_deaths delta_recovered
Virginia 2020-03-08 01:00:00 1 0 0 NA NA NA
Virginia 2020-03-08 14:00:00 2 0 0 1 0 0
Virginia 2020-03-10 03:45:00 7 0 0 5 0 0
Virginia 2020-03-10 18:00:00 8 0 0 1 0 0
Virginia 2020-03-11 15:50:00 9 0 0 1 0 0
Virginia 2020-03-13 02:00:00 18 0 0 9 0 0
Virginia 2020-03-13 20:00:00 30 0 0 12 0 0
Virginia 2020-03-15 03:00:00 41 1 0 11 1 0
Virginia 2020-03-16 03:00:00 45 1 0 4 0 0
Virginia 2020-03-17 02:00:00 52 2 0 7 1 0
Virginia 2020-03-18 03:00:00 67 2 0 15 0 0
Virginia 2020-03-19 03:00:00 79 2 0 12 0 0
Virginia 2020-03-20 03:00:00 104 2 0 25 0 0
Virginia 2020-03-21 02:00:00 125 2 0 21 0 0
Virginia 2020-03-22 03:00:00 158 3 0 33 1 0
Virginia 2020-03-23 03:00:00 221 6 0 63 3 0
Virginia 2020-03-24 03:00:00 254 7 0 33 1 0
Virginia 2020-03-25 03:00:00 304 9 0 50 2 0
Virginia 2020-03-26 03:00:00 399 13 0 95 4 0
Virginia 2020-03-27 03:00:00 471 14 0 72 1 0
Virginia 2020-03-28 03:00:00 610 16 0 139 2 0
Virginia 2020-03-29 03:00:00 740 17 0 130 1 0
Virginia 2020-03-30 03:00:00 890 24 0 150 7 0
Virginia 2020-03-31 03:00:00 1020 25 0 130 1 0
Virginia 2020-04-01 03:00:00 1250 27 0 230 2 0
Virginia 2020-04-02 03:00:00 1486 35 0 236 8 0
Virginia 2020-04-03 03:00:00 1706 41 0 220 6 0
Virginia 2020-04-04 03:00:00 2012 47 0 306 6 0
Virginia 2020-04-05 03:00:00 2407 52 0 395 5 0
Virginia 2020-04-06 03:00:00 2640 52 0 233 0 0
Virginia 2020-04-07 03:00:00 2878 66 0 238 14 0
Virginia 2020-04-08 03:00:00 3335 66 2 457 0 2
Virginia 2020-04-09 03:00:00 3645 75 2 310 9 0
Virginia 2020-04-10 03:00:00 4042 109 2 397 34 0
Virginia 2020-04-11 03:00:00 4509 121 2 467 12 0
Virginia 2020-04-12 09:00:00 5077 130 2 568 9 0
Virginia 2020-04-13 03:00:00 5274 141 2 197 11 0
Virginia 2020-04-14 03:00:00 5747 149 2 473 8 0
Virginia 2020-04-15 03:00:00 6182 157 721 435 8 719
Virginia 2020-04-16 03:00:00 6500 195 721 318 38 0
Virginia 2020-04-17 03:00:00 6889 208 721 389 13 0
Virginia 2020-04-18 03:00:00 7491 231 721 602 23 0
Virginia 2020-04-19 03:00:00 8053 258 721 562 27 0
Virginia 2020-04-20 03:00:00 8542 277 721 489 19 0
Virginia 2020-04-21 03:00:00 8990 300 721 448 23 0
Virginia 2020-04-22 03:00:00 9630 324 721 640 24 0
Virginia 2020-04-23 03:00:00 10266 349 721 636 25 0
Virginia 2020-04-24 03:00:00 10998 373 721 732 24 0
Virginia 2020-04-25 03:00:00 11594 411 721 596 38 0
Virginia 2020-04-26 03:00:00 12366 437 721 772 26 0
Virginia 2020-04-27 03:00:00 12970 449 721 604 12 0
Virginia 2020-04-28 03:00:00 13538 460 721 568 11 0
Virginia 2020-04-29 03:00:00 14339 492 721 801 32 0
Virginia 2020-04-30 03:00:00 14962 522 721 623 30 0
Virginia 2020-05-01 03:00:00 15847 552 721 885 30 0
Virginia 2020-05-02 03:00:00 16902 581 721 1055 29 0
Virginia 2020-05-03 03:00:00 17738 617 721 836 36 0
Virginia 2020-05-04 03:00:00 18672 660 721 934 43 0
Virginia 2020-05-05 03:00:00 19493 684 721 821 24 0
Virginia 2020-05-06 03:00:00 20257 713 721 764 29 0
Virginia 2020-05-07 11:00:00 20257 713 2734 0 0 2013
Virginia 2020-05-08 03:00:00 21570 769 2825 1313 56 91
Virginia 2020-05-09 03:00:00 22342 812 2997 772 43 172
Virginia 2020-05-10 03:00:00 23196 827 3124 854 15 127
Virginia 2020-05-11 03:00:00 24081 839 3201 885 12 77
Virginia 2020-05-12 03:00:00 25070 850 3273 989 11 72
Virginia 2020-05-13 03:00:00 25800 892 3400 730 42 127
Virginia 2020-05-14 03:00:00 26746 928 3554 946 36 154
Virginia 2020-05-15 03:00:00 27813 956 3554 1067 28 0
Virginia 2020-05-16 03:00:00 28672 978 3805 859 22 251
Virginia 2020-05-17 03:00:00 29683 1003 3909 1011 25 104
Virginia 2020-05-18 03:00:00 30388 1010 3993 705 7 84
Virginia 2020-05-19 03:00:00 31140 1015 4107 752 5 114
Virginia 2020-05-20 03:00:00 32145 1042 4271 1005 27 164
Virginia 2020-05-21 03:00:00 32908 1075 4523 763 33 252
Virginia 2020-05-22 03:00:00 34137 1100 4778 1229 25 255
Virginia 2020-05-23 03:00:00 34950 1136 4963 813 36 185
Virginia 2020-05-24 03:00:00 35749 1159 5047 799 23 84
Virginia 2020-05-25 03:00:00 36244 1171 5102 495 12 55
Virginia 2020-05-26 03:00:00 37727 1208 5145 1483 37 43
Virginia 2020-05-27 03:00:00 39342 1236 5227 1615 28 82
Virginia 2020-05-28 03:00:00 40249 1281 5227 907 45 0
Virginia 2020-05-29 03:00:00 41401 1338 5472 1152 57 245
Virginia 2020-05-30 03:00:00 42533 1358 5472 1132 20 0
Virginia 2020-05-31 03:00:00 43611 1370 5745 1078 12 273
Virginia 2020-06-01 03:00:00 44607 1375 5868 996 5 123
Virginia 2020-06-02 03:00:00 45398 1392 5868 791 17 0
Virginia 2020-06-03 03:00:00 46239 1407 6011 841 15 143
Virginia 2020-06-04 03:00:00 46905 1428 6165 666 21 154
Virginia 2020-06-05 03:00:00 47856 1445 6284 951 17 119
Virginia 2020-06-06 12:00:00 48532 1454 6392 676 9 108
Virginia 2020-06-07 03:00:00 49397 1461 6382 865 7 -10
Virginia 2020-06-08 03:00:00 49397 1461 6382 0 0 0
Virginia 2020-06-09 03:00:00 51251 1478 6557 1854 17 175
Virginia 2020-06-10 03:00:00 51738 1497 6677 487 19 120
Virginia 2020-06-10 03:00:00 51738 1497 6677 0 0 0

           

What if we plotted the number of fatalities? The fatalities graphs plot the total number of deaths on the x-axis (Deaths column) and the daily change of deaths (delta_deaths column) on the y-axis.

           

In the video, the creator highlighted two countries exhibiting recovery curves: South Korea and China.

           

The video also showed Japan having a slight uptick (5:49 of the video). What does the data reveal? (Note: On 07 April 2020, Japan declares a state of emergency.)

           

How does the United States compare with these countries?

           

Finally, today (April 5, 2020), I heard that things in Italy are starting look favorable. What does the data say?

End Notes.

Minutes before first publishing this report on 03 April 2020, an article entitled Preparing For the Peak appeared in my email. What a coincidence.

I’ve received questions regarding the validity and source of the data used in this report. The source of the data is from the COVID-19 Surveillance Dashboard. They aggregated the data from numerous reliable sources.

Additional plots. Check out plots from one of these other 65 areas of interest. [If the link fails to render, right-click on it and open in a new window].

     

Every attempt was made to convey valid and accurate results based upon the data provided.

Stay well and be safe.

     

Report generated: 2020-07-10 17:30:22
LS0tDQp0aXRsZTogIkNPVklELTE5OiAgSXMgdGhlIGN1cnZlIGZsYXR0ZW5pbmc/Ig0KYXV0aG9yOiAiSm9obiBTaW51ZXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCmBgYHtyIGNsZWFyYWxsLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPUZBTFNFfQ0Kcm0obGlzdCA9IGxzKCkpDQpgYGANCg0KIyBJbnRyb2R1Y3Rpb24NCkluZGl2aWR1YWxzIGFjcm9zcyB0aGUgZ2xvYmUgYXJlIHVyZ2VkIHRvIHNsb3cgdGhlIHNwcmVhZCBvZiBDT1ZJRC0xOS4gIEdvdmVybm1lbnRzIGFyZSBpbXBsZW1lbnRpbmcgZXZlcnl0aGluZyBmcm9tIG1pbGQgKipzaGVsdGVyIGluIHBsYWNlKiogdG8gZXh0cmVtZSBbKnNob290IHRoZW0gZGVhZCpdKGh0dHBzOi8vd3d3LnZvYW5ld3MuY29tL3NjaWVuY2UtaGVhbHRoL2Nvcm9uYXZpcnVzLW91dGJyZWFrL3BoaWxpcHBpbmUtcHJlc2lkZW50LXNheXMtdGhvc2UtdmlvbGF0aW5nLWFudGktdmlydXMtbWVhc3VyZXMpIG1lYXN1cmVzIHRvIGNvbnRyb2wgdGhpcyBnbG9iYWwgY3Jpc2lzLg0KDQpBbGwgdGhlc2UgZWZmb3J0cyBhcmUgaW4gaG9wZXMgb2YgZmxhdHRlbmluZyB0aGUgY3VydmUuICBBY2NvcmRpbmcgdG8gdGhpcyBbYXJ0aWNsZV0oKGh0dHBzOi8vd3d3LmJpb3NwYWNlLmNvbS9hcnRpY2xlL2ZsYXR0ZW5pbmctdGhlLWN1cnZlLWNvdmlkLTE5LykpLCBoaWdoIHBlYWtzIHB1dCBhIGxvdCBvZiBwcmVzc3VyZSBvbiBoZWFsdGggY2FyZSBzeXN0ZW1zIHdoaWNoIHRoZXkgc3RydWdnbGUgdG8gcmVzcG9uZCB0by4NCg0KU28gd2hhdCBkb2VzIHRoaXMgY3VydmUgbG9vayBsaWtlIGZvciBteSBzdGF0ZSBvZiBWaXJnaW5pYT8gIEkndmUgc2VlbiBhIHJpc2luZyBjdXJ2ZSBmb3IgdGhlIGVudGlyZSBVbml0ZWQgU3RhdGVzLCBidXQgSSd2ZSBvbmx5IHNlZW4gdGhlIGN1cnJlbnQgbnVtYmVyIG9mIGNhc2VzIGZvciBhIHBhcnRpY3VsYXIgZGF5LiAgSSBkb24ndCBrbm93IGhvdyB0aGlzIG51bWJlciBjb21wYXJlcyB0byBsYXN0IHdlZWsuDQoNCltXb3JsZCBPIE1ldGVyXShodHRwczovL3d3dy53b3JsZG9tZXRlcnMuaW5mby9jb3JvbmF2aXJ1cy8pIGFuZCBbQmluZydzIENvcm9ub2F2aXJ1cyB1cGRhdGVzXShodHRwczovL3d3dy5iaW5nLmNvbS9zZWFyY2g/cT1Db3JvbmF2aXJ1cyt1cGRhdGVzKSBwcm92aWRlIG5pY2Ugc3VtbWFyaWVzLCBidXQgbmVpdGhlciBvZiB0aGVzZSB3ZWIgc2l0ZXMgc2hvd2VkIHRoZSB0cmVuZCBvZiBjb25maXJtZWQgY2FzZXMgb3ZlciB0aW1lLg0KDQpBbGwgSSBuZWVkZWQgd2FzIHRoZSBkYXRhLiAgQWZ0ZXIgY291bnRsZXNzIHNlYXJjaGVzLCBJIHN0dW1ibGVkIHVwb24gdGhlIFVuaXZlcnNpdHkgb2YgVmlyZ2luaWEncyBbQ09WSUQtMTkgU3VydmVpbGxhbmNlIERhc2hib2FyZF0oaHR0cHM6Ly9uc3NhYy5iaWkudmlyZ2luaWEuZWR1L2NvdmlkLTE5L2Rhc2hib2FyZC8pLiAgSXQgaXMgYSBuaWNlIHJlYWwtdGltZSBkYXNoYm9hcmQgdGhhdCBhbHNvIGFsbG93cyBvbmUgdG8gZG93bmxvYWQgZGF0YS4gIFVwb24gaW5zcGVjdGlvbiBvZiB0aGUgcHJvdmlkZWQgZGF0YXNldHMsIEkgZm91bmQgd2hhdCBJIHdhcyBsb29raW5nIGZvci4gIA0KDQpUaGlzIHBlcnNvbmFsIHByb2plY3QgaXMgbXkgYXR0ZW1wdCB0byB1bmRlcnN0YW5kIHRoZSBDT1ZJRC0xOSBjdXJ2ZSBhbmQgaG93IHRoZSBudW1iZXIgb2YgY2FzZXMgYWZmZWN0cyB0aGUgc2hhcGUgb2YgdGhlIGN1cnZlLg0KDQojIyMgTGV0J3MgZ2V0IHN0YXJ0ZWQuDQoNCmBgYHtyIGdldF9maWxlcywgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGdndGhlbWVzKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoa2FibGVFeHRyYSkNCg0Kb3B0aW9ucyhzY2lwZW49MTAwMDApICMgcmVtb3ZlIHNjaWVudGlmaWMgbm90YXRpb24gZnJvbSBncmFwaHMNCg0KZmlsZW5hbWUgPC0gIm5zc2FjLW5jb3YtZGF0YS1jb3VudHJ5LXN0YXRlIg0Kc3JjX2ZpbGUgPC0gcGFzdGUwKCJodHRwczovL25zc2FjLmJpaS52aXJnaW5pYS5lZHUvY292aWQtMTkvZGFzaGJvYXJkL2RhdGEvIg0KICAgICAgICAgICAgICAgICAgICwgZmlsZW5hbWUNCiAgICAgICAgICAgICAgICAgICAsICIuemlwIikNCg0KIyBNYWtlIGEgdGVtcG9yYXJ5IGZpbGUgKHRmKSBhbmQgYSB0ZW1wb3JhcnkgZm9sZGVyICh0ZGlyKQ0KdGYgPC0gdGVtcGZpbGUodG1wZGlyID0gdGRpciA8LSB0ZW1wZGlyKCkpDQoNCiMjIERvd25sb2FkIHRoZSB6aXAgZmlsZSANCmRvd25sb2FkLmZpbGUoc3JjX2ZpbGUsIHRmKQ0KDQojIyBVbnppcCBpdCBpbiB0aGUgdGVtcCBmb2xkZXINCmNzdl9maWxlcyA8LSB1bnppcCh0ZiwgZXhkaXIgPSB0ZGlyKQ0KDQpmaWxlc190b19pbXBvcnQgPC0gbGlzdC5maWxlcyhwYXN0ZTAodGRpciwiLyIsIGZpbGVuYW1lKSwgcGF0dGVybiA9ICIuY3N2IiwgZnVsbC5uYW1lcyA9IFRSVUUpDQoNCg0KIyBhcHBseSBtYXBfZGYoKSB0byBpdGVyYXRlIHJlYWRfY3N2IG92ZXIgZmlsZXMNCmRhdGEgPC0gZmlsZXNfdG9faW1wb3J0ICU+JSBtYXBfZGZyKHJlYWRfY3N2LCBjb2xfdHlwZXMgPSAiY2NjaWlpIikNCmNvbG5hbWVzKGRhdGEpIDwtIGMoIk5hbWUiLCAiUmVnaW9uIiwgIkxhc3RfVXBkYXRlIiwgIkNvbmZpcm1lZCIsICJEZWF0aHMiLCAiUmVjb3ZlcmVkIikNCmRhdGEkTGFzdF9VcGRhdGUgPC0geW1kX2htcyhkYXRhJExhc3RfVXBkYXRlKQ0KDQpgYGANCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgcmVzdWx0cyA9ICdhc2lzJ30NCnNob3dUYWJsZSA8LSBmdW5jdGlvbih0aGVEYXRhLCB0YWJsZUNhcHRpb24sIHRoZUZvb3Rub3RlPU5VTEwpIHsNCiAgaWYgKG1pc3NpbmcodGFibGVDYXB0aW9uKSkgew0KICAgIHRoZUNhcHRpb24gPC0gIkN1cnJlbnQgTnVtYmVyIG9mIEluZmVjdGlvbnMiDQogIH0gZWxzZSB7DQogICAgdGhlQ2FwdGlvbiA8LSB0YWJsZUNhcHRpb24NCiAgfQ0KICBrYWJsZSh0aGVEYXRhLCBjYXB0aW9uID0gdGhlQ2FwdGlvbikgJT4lDQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYpICU+JQ0KICAgIHNjcm9sbF9ib3goaGVpZ2h0ID0gIjUwMHB4IikgJT4lDQogICAgZm9vdG5vdGUoZ2VuZXJhbCA9IHRoZUZvb3Rub3RlKQ0KICAgIA0KfQ0KDQpgYGANCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCByZXN1bHRzID0gJ2FzaXMnfQ0Kc2V0LnNlZWQoNzU3KQ0KDQpzaG93VGFibGUoc2FtcGxlX24oZGF0YSwgMTApLCAiU2FtcGxlIERhdGEgRnJvbSBJbXBvcnRlZCBGaWxlcyIpDQoNCmBgYA0KDQpgYGB7ciBkYXRhX3ByZXAsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9RkFMU0V9DQojIGNhbGN1bGF0ZSBjYXNlICB0eXBlIGNoYW5nZSBmcm9tIHByZXZpb3VzIGRheQ0KZGF0YSA8LSBkYXRhICU+JSBncm91cF9ieShOYW1lLCBSZWdpb24pICU+JQ0KICBhcnJhbmdlKFJlZ2lvbiwgTmFtZSwgTGFzdF9VcGRhdGUpICU+JQ0KICBtdXRhdGUoZGVsdGFfY29uZmlybWVkID0gQ29uZmlybWVkIC0gbGFnKENvbmZpcm1lZCkpICU+JQ0KICBtdXRhdGUoZGVsdGFfZGVhdGhzID0gRGVhdGhzIC0gbGFnKERlYXRocykpICU+JQ0KICBtdXRhdGUoZGVsdGFfcmVjb3ZlcmVkID0gUmVjb3ZlcmVkIC0gbGFnKFJlY292ZXJlZCkpDQoNCiMgc2hvcnRlbiBuYW1lDQpkYXRhJE5hbWVbZGF0YSROYW1lID09ICJVbml0ZWQgU3RhdGVzIFZpcmdpbiBJc2xhbmRzIl0gPC0gIlVTIFZpcmdpbiBJc2xhbmRzIg0KDQptaW5fZHQgPC0gbWluKGRhdGEkTGFzdF9VcGRhdGUsIG5hLnJtPVRSVUUpDQptYXhfZHQgPC0gbWF4KGRhdGEkTGFzdF9VcGRhdGUsIG5hLnJtPVRSVUUpDQoNCmBgYA0KXCAgDQpcICANClwgIA0KDQpBZnRlciBsb2FkaW5nIHRoZSBkYXRhZmlsZSwgd2UgZmluZCB0aGUgZGF0YXNldCBjb250YWlucyAqKmByIG5yb3coZGF0YSlgKiogcmVjb3JkcywgKipgciBsZW5ndGgodW5pcXVlKGRhdGEkUmVnaW9uKSlgKiogYXJlYXMgb2YgaW50ZXJlc3RzIHdpdGggaW5mb3JtYXRpb24gZGF0ZWQgZnJvbSAqKmByIG1pbl9kdFtbMV1dYCoqIGFuZCAqKmByIG1heF9kdFtbMV1dYCoqLg0KDQpHbG9iYWxseSwgdGhlcmUgYXJlICoqYHIgc3VtKGRhdGEgJT4lICBzbGljZShjKDE6bigpKS0xKSAlPiUgdW5ncm91cCgpICU+JSBzZWxlY3QoZGVsdGFfY29uZmlybWVkKSwgbmEucm09VFJVRSlgKiogY29uZmlybWVkIENPVklELTE5IGNhc2VzLCAqKmByIHN1bShkYXRhICU+JSAgc2xpY2UoYygxOm4oKSktMSkgJT4lIHVuZ3JvdXAoKSAlPiUgc2VsZWN0KGRlbHRhX2RlYXRocyksIG5hLnJtPVRSVUUpYCoqIGRlYXRocywgYW5kICoqYHIgc3VtKGRhdGEgJT4lICBzbGljZShjKDE6bigpKS0xKSAlPiUgdW5ncm91cCgpICU+JSBzZWxlY3QoZGVsdGFfcmVjb3ZlcmVkKSwgbmEucm09VFJVRSlgKiogd2hvIHJlY292ZXJlZC4NCg0KDQpgYGB7ciB1c19kYXRhLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQpkZi51cyA8LSBkYXRhICU+JSANCiAgZmlsdGVyKFJlZ2lvbiA9PSAiVVNBIikgJT4lIA0KICBzZWxlY3QoTmFtZSwgTGFzdF9VcGRhdGUsIENvbmZpcm1lZCwgRGVhdGhzLCBSZWNvdmVyZWQpICU+JQ0KICBnYXRoZXIoY2FzZV90eXBlLCB2YWx1ZSwgQ29uZmlybWVkOlJlY292ZXJlZCkNCg0KYGBgDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTh9DQpwbG90UmVnaW9ucyA8LSBmdW5jdGlvbih0aGVEYXRhLCBwbG90TG9nLCByZXBvcnRUaXRsZSwgZmFjZXRXcmFwKSB7DQogIHAgPC0gZ2dwbG90KHRoZURhdGEsDQogICAgICAgICAgICAgIGFlcyh4PUxhc3RfVXBkYXRlLCB5PXZhbHVlLCBjb2xvciA9IGZhY3RvcihOYW1lKSkpICsgDQogICAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBjYXNlX3R5cGUpKSArDQogICAgbGFicyh0aXRsZSA9IHJlcG9ydFRpdGxlDQogICAgICAgICAsIHggPSAiRGF0ZSBSZXBvcnRlZCINCiAgICAgICAgICwgeSA9ICIjIENhc2VzIg0KICAgICAgICAgLCBjb2xvciA9ICJDYXNlIFR5cGUiDQogICAgICAgICAsIGNhcHRpb24gPSBwYXN0ZTAoIkNyZWF0ZWQgIiwgU3lzLnRpbWUoKSkpICsNCiAgICBzY2FsZV9jb2xvcl9maXZldGhpcnR5ZWlnaHQoKSArIA0KICAgIHRoZW1lX2ZpdmV0aGlydHllaWdodCgpICsNCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCkpDQoNCiAgaWYgKGZhY2V0V3JhcCA9PSAiWSIpIHsNCiAgICBwIDwtIHAgKyBmYWNldF93cmFwKHZhcnMoTmFtZSkpDQogIH0NCiAgDQogIGlmIChncmVwbChwYXR0ZXJuPSJebG9nWzAtOV17MSwyfSQiLCBwbG90TG9nKSkgew0KICAgIHAgPC0gcCArIHNjYWxlX3lfY29udGludW91cyh0cmFucz1wbG90TG9nKQ0KICB9DQoNCiAgcCAgDQp9DQoNCmBgYA0KDQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCk5vcnRoZWFzdCA8LSBjKCJDb25uZWN0aWN1dCIsICJNYWluZSIsICJNYXNzYWNodXNldHRzIiwgIk5ldyBIYW1wc2hpcmUiLCAiUmhvZGUgSXNsYW5kIg0KICAgICAgICAgICAgICAgLCAiVmVybW9udCIsICJOZXcgSmVyc2V5IiwgIk5ldyBZb3JrIiwgIlBlbm5zeWx2YW5pYSIsICJQdWVydG8gUmljbyINCiAgICAgICAgICAgICAgICwgIlVTIFZpcmdpbiBJc2xhbmRzIikNCk1pZHdlc3QgPC0gYygiSWxsaW5vaXMiLCAiSW5kaWFuYSIsICJNaWNoaWdhbiIsICJPaGlvIiwgIldpc2NvbnNpbiINCiAgICAgICAgICAgICAsICJJb3dhIiwgIkthbnNhcyIsICJNaW5uZXNvdGEiLCAiTWlzc291cmkiLCAiTmVicmFza2EiDQogICAgICAgICAgICAgLCAiTm9ydGggRGFrb3RhIiwgIlNvdXRoIERha290YSIpDQpTb3V0aCA8LSBjKCJEZWxhd2FyZSIsICJGbG9yaWRhIiwgIkdlb3JnaWEiLCAiTWFyeWxhbmQiLCAiTm9ydGggQ2Fyb2xpbmEiDQogICAgICAgICAgICwgIlNvdXRoIENhcm9saW5hIiwgIlZpcmdpbmlhIiwgIkRpc3RyaWN0IG9mIENvbHVtYmlhIiwgIldlc3QgVmlyZ2luaWEiLCAiQWxhYmFtYSINCiAgICAgICAgICAgLCAiS2VudHVja3kiLCAiTWlzc2lzc2lwcGkiLCAiVGVubmVzc2VlIiwgIkFya2Fuc2FzIiwgIkxvdWlzaWFuYSINCiAgICAgICAgICAgLCAiT2tsYWhvbWEiLCAiVGV4YXMiKQ0KV2VzdCA8LSBjKCJBcml6b25hIiwgIkNvbG9yYWRvIiwgIklkYWhvIiwgIk1vbnRhbmEiLCAiTmV2YWRhIg0KICAgICAgICAgICwgIk5ldyBNZXhpY28iLCAiVXRhaCIsICJXeW9taW5nIiwgIkFsYXNrYSIsICJDYWxpZm9ybmlhIg0KICAgICAgICAgICwgIkhhd2FpaSIsICJPcmVnb24iLCAiV2FzaGluZ3RvbiIsICJOb3J0aGVybiBNYXJpYW5hIElzbGFuZHMiLCAiR3VhbSIpDQoNCmBgYA0KDQoqKioNCg0KXCAgDQpcICANCg0KIyMjIyBXaGF0IGRvZXMgdGhlIGN1cnZlIGxvb2sgbGlrZSBmb3IgdGhlIFVTIGFzIGEgd2hvbGU/ICBUaGlzIGlzIHRoZSBncmFwaGljIHdlIHNlZSBpbiBtYWluc3RyZWFtIG1lZGlhLiAgQ3VycmVudGx5IHRoZXJlIGFyZSBgciBzdW0oKGRhdGEgJT4lIGZpbHRlcihOYW1lICVpbiUgYyhOb3J0aGVhc3QsIE1pZHdlc3QsIFNvdXRoLCBXZXN0KSkpWzddLCBuYS5ybSA9IFRSVUUpYCBjb25maXJtZWQgY2FzZXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMuDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTh9DQpwbG90UmVnaW9ucyhkZi51cyAlPiUNCiAgICAgICAgICAgICAgZmlsdGVyKE5hbWUgJWluJSBjKE1pZHdlc3QsIFNvdXRoLCBXZXN0LCBOb3J0aGVhc3QpKSAlPiUgDQogICAgICAgICAgICAgIHVuZ3JvdXAoKSAlPiUNCiAgICAgICAgICAgICAgc2VsZWN0KExhc3RfVXBkYXRlLCBjYXNlX3R5cGUsdmFsdWUpICU+JQ0KICAgICAgICAgICAgICBncm91cF9ieShMYXN0X1VwZGF0ZSwgY2FzZV90eXBlKSAlPiUNCiAgICAgICAgICAgICAgc3VtbWFyaXNlKHZhbHVlPXN1bSh2YWx1ZSwgbmEucm0gPSBUUlVFKSkNCiAgICAgICAgICAgICwgIk4iLCAiQ09WSUQtMTkgQ2FzZXMgLSBFbnRpcmUgVVMgUmVnaW9uIiwgIk4iKQ0KDQpgYGANClwgIA0KXCAgDQpcICANClwgDQpcICANClwgDQoNCiMjIyMgU2VlaW5nIHRoZSBiaWcgcGljdHVyZSBjYW4gYmUgb3ZlcndoZWxtaW5nLiAgTGV0J3MgYnJlYWsgaXQgZG93biBieSByZWdpb25zLg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD04fQ0KcGxvdFJlZ2lvbnMoZGYudXMgJT4lIGZpbHRlcihOYW1lICVpbiUgTm9ydGhlYXN0KSwgIk4iLCAiQ09WSUQtMTkgQ2FzZXMgLSBOb3J0aGVzdCBSZWdpb24iLCAiWSIpDQpwbG90UmVnaW9ucyhkZi51cyAlPiUgZmlsdGVyKE5hbWUgJWluJSBNaWR3ZXN0KSwgIk4iLCAiQ09WSUQtMTkgQ2FzZXMgLSBNaWR3ZXN0IFJlZ2lvbiIsICJZIikNCnBsb3RSZWdpb25zKGRmLnVzICU+JSBmaWx0ZXIoTmFtZSAlaW4lIFNvdXRoKSwgIk4iLCAiQ09WSUQtMTkgQ2FzZXMgLSBTb3V0aCBSZWdpb24iLCAiWSIpDQpwbG90UmVnaW9ucyhkZi51cyAlPiUgZmlsdGVyKE5hbWUgJWluJSBXZXN0KSwgIk4iLCAiQ09WSUQtMTkgQ2FzZXMgLSBXZXN0IFJlZ2lvbiIsICJZIikNCg0KYGBgDQpcICANClwgIA0KXCAgDQpcIA0KXCAgDQpcIA0KDQojIyMjIyBGYXN0IHJpc2luZyBjdXJ2ZXMgaWRlbnRpZnkgdGhvc2UgKmhvdCBzcG90cyogYW5kIHByaW9yaXR5IHJlZ2lvbnMuICBCdXQgd2hhdCBhYm91dCB0aG9zZSBzdGF0ZXMgdGhhdCBkb24ndCBzaG93IGEgc3RlZXAgcmlzaW5nIGN1cnZlPyAgQXJlIHRoZXkgb2YgY29uY2Vybj8NCg0KIyMjIyMgVGhlIGFib3ZlIGdyYXBocyBncm91cCBzdGF0ZXMgYnkgcmVnaW9ucy4gIE9uZSBzdGF0ZSB3aXRoIGEgaGlnaCBudW1iZXIgb2YgY2FzZXMgY291bGQgc2tldyB0aGUgZ3JhcGggZm9yIHRoZSByZWdpb24uICBUbyB0YWtlIHRoaXMgaW50byBhY2NvdW50IGFuZCB0byBzaG93IHRoZSByYXRlIG9mIGNoYW5nZSBvdmVyIHRpbWUsIGxldCdzIHBsb3QgdGhlIGluZm9ybWF0aW9uIG9uIGEgbG9nYXJpdGhtaWMgc2NhbGUuDQoNCj4gR3JhcGhzIHdpdGggc3RlZXAgY3VydmVzIHNob3cgc3RhdGVzIGhpdCBoYXJkZXN0IGJ5IHRoZSBDT1ZJRC0xOSB2aXJ1cy4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgd2FybmluZz1GQUxTRX0NCmNyZWF0ZUxhYmVsIDwtIGZ1bmN0aW9uKGNvdW50cnlOYW1lLCBsb2dCYXNlLCBjYXNlVHlwZT1OVUxMKSB7DQogIGlmIChtaXNzaW5nKGNhc2VUeXBlKSkgew0KICAgIGxhYmVsIDwtIHBhc3RlMCgiQ09WSUQtMTkgQ2FzZXMgLSAiLCBjb3VudHJ5TmFtZSkNCiAgfSBlbHNlIHsNCiAgICBsYWJlbCA8LSBwYXN0ZTAoIkNPVklELTE5ICIsIGNhc2VUeXBlLCAiIC0gIiwgY291bnRyeU5hbWUpDQogIH0NCg0KICAjIG9ubHkgYmFzZSBsb2dzIG9mIDIgYW5kIDEwIGFyZSBzdXBwb3J0ZWQ7IG5vdCBzdXJlIGhvdyB0bw0KICAjIHRha2UgdGhlIExvZ1tuXSB3L2luIHRoZSBicXVvdGUoKSBmdW5jdGlvbg0KICBpZiAobWlzc2luZyhsb2dCYXNlKSkgew0KICAgICMgbm8gbG9nIGxhYmVsDQogICAgYnF1b3RlKC4obGFiZWxbMV0pKQ0KICB9IGVsc2UgaWYgKGxvZ0Jhc2UgPT0gImxvZzIiKSB7DQogICAgYnF1b3RlKC4obGFiZWxbMV0pIH4gKExvZ1syXSkpDQogIH0gZWxzZSBpZiAobG9nQmFzZSA9PSAibG9nMTAiKSB7DQogICAgYnF1b3RlKC4obGFiZWxbMV0pIH4gKExvZ1sxMF0pKQ0KICB9IGVsc2UgaWYgKGdyZXBsKHBhdHRlcm49Il5sb2dbMC05XXsxLDJ9JCIsIGxvZ0Jhc2UpKSB7DQogICAgYnF1b3RlKC4obGFiZWxbMV0pIH4gKExvZykpDQogIH0NCn0NCg0KYGBgDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTh9DQpwbG90UmVnaW9ucyhkZi51cyAlPiUgZmlsdGVyKE5hbWUgJWluJSBOb3J0aGVhc3QpLCAibG9nMTAiLCBjcmVhdGVMYWJlbCgiTm9ydGhlc3QgUmVnaW9uIiksICJZIikNCnBsb3RSZWdpb25zKGRmLnVzICU+JSBmaWx0ZXIoTmFtZSAlaW4lIE1pZHdlc3QpLCAibG9nMTAiLCAgY3JlYXRlTGFiZWwoIk1pZHdlc3QgUmVnaW9uIiksICJZIikNCnBsb3RSZWdpb25zKGRmLnVzICU+JSBmaWx0ZXIoTmFtZSAlaW4lIFNvdXRoKSwgImxvZzEwIiwgIGNyZWF0ZUxhYmVsKCJTb3V0aCBSZWdpb24iKSwgIlkiKQ0KcGxvdFJlZ2lvbnMoZGYudXMgJT4lIGZpbHRlcihOYW1lICVpbiUgV2VzdCksICJsb2cxMCIsICBjcmVhdGVMYWJlbCgiV2VzdCBSZWdpb24iKSwgIlkiKQ0KDQpgYGANClwgIA0KXCAgDQpcICANClwgDQpcICANClwgDQoNCiMjIyMjIFdoYXQgZG9lcyB0aGUgVmlyZ2luaWEgY3VydmUgc2hvdz8NCg0KYGBge3IsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTh9DQpkZi50ZW1wIDwtIGRmLnVzICU+JSBmaWx0ZXIoTmFtZSA9PSAiVmlyZ2luaWEiKQ0KDQpwbG90UmVnaW9ucyhkZi50ZW1wLCAiTiIsIGNyZWF0ZUxhYmVsKCJWaXJnaW5pYSIpLCAiTiIpDQpwbG90UmVnaW9ucyhkZi50ZW1wLCAibG9nMTAiLCBjcmVhdGVMYWJlbCgiVmlyZ2luaWEiLCAibG9nMTAiKSwgIk4iKQ0KDQpgYGANCioqKg0KXCAgDQpcICANClwgIA0KXCANClwgIA0KXCANCg0KIyMjIyBTdW1tYXJ5IG9mIFUuUy4gQXJlYXMgb2YgSW50ZXJlc3QNCg0KYGBge3IgdGFiX3VzX3JlZ2lvbnMsIGVjaG8gPSBGQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmdldF91c19yZWdpb24gPC0gZnVuY3Rpb24odGhlRGF0YSwgcmVnaW9uLCBjYXNlVHlwZSwgbGFiZWwpIHsNCiAgdGhlRGF0YSAlPiUgDQogICAgZmlsdGVyKE5hbWUgJWluJSBjKHJlZ2lvbikgJiBjYXNlX3R5cGUgJWluJSBjYXNlVHlwZSkgJT4lDQogICAgZ3JvdXBfYnkoTmFtZSwgY2FzZV90eXBlKSAlPiUNCiAgICBhcnJhbmdlKExhc3RfVXBkYXRlKSAlPiUNCiAgICBzbGljZShjKG4oKSkpICU+JQ0KICAgIG11dGF0ZShncm91cCA9IGxhYmVsKSAlPiUNCiAgICB1bmdyb3VwKCkgJT4lDQogICAgc2VsZWN0KE5hbWUsIGdyb3VwLCBjYXNlX3R5cGUsIHZhbHVlKQ0KfQ0KDQpkZi50ZW1wIDwtIGdldF91c19yZWdpb24oZGYudXMsIE1pZHdlc3QsIGMoJ0NvbmZpcm1lZCcsICdEZWF0aHMnLCAnUmVjb3ZlcmVkJyksICdNaWR3ZXN0JykNCmRmLnRlbXAgPC0gYmluZF9yb3dzKGRmLnRlbXAsIGdldF91c19yZWdpb24oZGYudXMsIFNvdXRoLCBjKCdDb25maXJtZWQnLCAnRGVhdGhzJywgJ1JlY292ZXJlZCcpLCAnU291dGgnKSkNCmRmLnRlbXAgPC0gYmluZF9yb3dzKGRmLnRlbXAsIGdldF91c19yZWdpb24oZGYudXMsIFdlc3QsIGMoJ0NvbmZpcm1lZCcsICdEZWF0aHMnLCAnUmVjb3ZlcmVkJyksICdXZXN0JykpDQpkZi50ZW1wIDwtIGJpbmRfcm93cyhkZi50ZW1wLCBnZXRfdXNfcmVnaW9uKGRmLnVzLCBOb3J0aGVhc3QsIGMoJ0NvbmZpcm1lZCcsICdEZWF0aHMnLCAnUmVjb3ZlcmVkJyksICdOb3J0aGVhc3QnKSkNCmRmLnRlbXAgPC0gZGYudGVtcCAlPiUgDQogIHNwcmVhZChjYXNlX3R5cGUsIHZhbHVlKSAlPiUNCiAgYXJyYW5nZShncm91cCwgLUNvbmZpcm1lZCkNCg0KZ2V0X3JlZ2lvbl9jb3VudCA8LSBmdW5jdGlvbih0aGVkYXRhLCB0aGVncm91cCkgew0KICBucm93KHRoZWRhdGEgJT4lIGZpbHRlcihncm91cCAlaW4lIHRoZWdyb3VwKSkNCn0NCg0KDQprYWJsZShkZi50ZW1wDQogICAgICAsIGNhcHRpb24gPSAiU3VtbWFyeSBvZiBVUyBBcmVhcyBvZiBJbnRlcmVzdCIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRikgJT4lDQogIHBhY2tfcm93cygiTWlkd2VzdCINCiAgICAgICAgICAgICwgMQ0KICAgICAgICAgICAgLCBnZXRfcmVnaW9uX2NvdW50KGRmLnRlbXAsIGMoIk1pZHdlc3QiKSkpICU+JQ0KICBwYWNrX3Jvd3MoIk5vcnRoZWFzdCINCiAgICAgICAgICAgICwgZ2V0X3JlZ2lvbl9jb3VudChkZi50ZW1wLCBjKCJNaWR3ZXN0IikpICsgMQ0KICAgICAgICAgICAgLCBnZXRfcmVnaW9uX2NvdW50KGRmLnRlbXAsIGMoIk1pZHdlc3QiLCAiTm9ydGhlYXN0IikpKSAlPiUNCiAgcGFja19yb3dzKCJTb3V0aCINCiAgICAgICAgICAgICwgZ2V0X3JlZ2lvbl9jb3VudChkZi50ZW1wLCBjKCJNaWR3ZXN0IiwgIk5vcnRoZWFzdCIpKSArIDENCiAgICAgICAgICAgICwgZ2V0X3JlZ2lvbl9jb3VudChkZi50ZW1wLCBjKCJNaWR3ZXN0IiwgIk5vcnRoZWFzdCIsICJTb3V0aCIpKSkgJT4lDQogIHBhY2tfcm93cygiV2VzdCINCiAgICAgICAgICAgICwgZ2V0X3JlZ2lvbl9jb3VudChkZi50ZW1wLCBjKCJNaWR3ZXN0IiwgIk5vcnRoZWFzdCIsICJTb3V0aCIpKSArIDENCiAgICAgICAgICAgICwgZ2V0X3JlZ2lvbl9jb3VudChkZi50ZW1wLCBjKCJNaWR3ZXN0IiwgIk5vcnRoZWFzdCIsICJTb3V0aCIsICJXZXN0IikpKSAlPiUNCiAgc2Nyb2xsX2JveChoZWlnaHQgPSAiNDAwcHgiKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9ICJUaGVyZSBhcHBlYXJzIHRvIGJlIGEgZGlzY3JlcGFuY3kgdG8gaG93IHJlY292ZXJpZXMgYXJlIHJlY29yZGVkIGJ5IHN0YXRlLiAgQmFzZWQgdXBvbiBCaW5nJ3MgQ09WSUQtMTkgc3RhdHMsIHNvbWUgb2YgdGhlIHJlY292ZXJpZXMgYXJlIGNvcnJlY3Qgd2hlcmVhcyBvdGhlcnMgYXJlIG5vdC4iKQ0KDQpgYGANCioqKg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0Kc2hvd1RhYmxlKGRmLnVzICU+JQ0KICAgICAgICAgICAgZmlsdGVyKGNhc2VfdHlwZSA9PSAiQ29uZmlybWVkIiAmIE5hbWUgJWluJSBjKE1pZHdlc3QsIFNvdXRoLCBXZXN0LCBOb3J0aGVhc3QpKSAlPiUNCiAgICAgICAgICAgIGdyb3VwX2J5KFJlZ2lvbiwgTmFtZSkgJT4lDQogICAgICAgICAgICBhcnJhbmdlKFJlZ2lvbiwgTmFtZSwgTGFzdF9VcGRhdGUpICU+JQ0KICAgICAgICAgICAgc2xpY2UoYyhuKCkpKSAlPiUNCiAgICAgICAgICAgIHVuZ3JvdXAoKSAlPiUNCiAgICAgICAgICAgIHNlbGVjdChOYW1lLCB2YWx1ZSkgJT4lDQogICAgICAgICAgICBhcnJhbmdlKC12YWx1ZSkgJT4lDQogICAgICAgICAgICB0b3BfbigxMCkgJT4lDQogICAgICAgICAgICByZW5hbWUoYygnIyBDb25maXJtZWQgQ2FzZXMnID0gJ3ZhbHVlJykpDQogICAgICAgICAgLCAiU3RhdGVzIFdpdGggTW9zdCBDb25maXJtZWQgQ2FzZXMiKQ0KDQpzaG93VGFibGUoZGF0YSAlPiUNCiAgICAgICAgICAgIGZpbHRlcihOYW1lICVpbiUgYyhNaWR3ZXN0LCBTb3V0aCwgV2VzdCwgTm9ydGhlYXN0KSkgJT4lDQogICAgICAgICAgICBncm91cF9ieShSZWdpb24sIE5hbWUpICU+JQ0KICAgICAgICAgICAgYXJyYW5nZShSZWdpb24sIE5hbWUsIExhc3RfVXBkYXRlKSAlPiUNCiAgICAgICAgICAgIHNsaWNlKGMobigpLTEpKSAlPiUNCiAgICAgICAgICAgIHVuZ3JvdXAoKSAlPiUNCiAgICAgICAgICAgIHNlbGVjdChOYW1lLCBkZWx0YV9jb25maXJtZWQpICU+JQ0KICAgICAgICAgICAgYXJyYW5nZSgtZGVsdGFfY29uZmlybWVkKSAlPiUNCiAgICAgICAgICAgIHRvcF9uKDEwKSAlPiUNCiAgICAgICAgICAgIHJlbmFtZShjKCdDaGFuZ2UgSW4gTnVtYmVyIG9mIENvbmZpcm1lZCBDYXNlcyBGcm9tIFllc3RlcmRheScgPSAnZGVsdGFfY29uZmlybWVkJykpDQogICAgICAgICAgLCAiU3RhdGVzIFdpdGggVGhlIExhcmdlc3QgRGFpbHkgQ2hhbmdlIG9mIENvbmZpcm1lZCBDYXNlcyIpDQoNCnNob3dUYWJsZShkZi51cyAlPiUNCiAgICAgICAgICAgIGZpbHRlcihjYXNlX3R5cGUgPT0gIkRlYXRocyIgJiBOYW1lICVpbiUgYyhNaWR3ZXN0LCBTb3V0aCwgV2VzdCwgTm9ydGhlYXN0KSkgJT4lDQogICAgICAgICAgICBncm91cF9ieShSZWdpb24sIE5hbWUpICU+JQ0KICAgICAgICAgICAgYXJyYW5nZShSZWdpb24sIE5hbWUsIExhc3RfVXBkYXRlKSAlPiUNCiAgICAgICAgICAgIHNsaWNlKGMobigpKSkgJT4lDQogICAgICAgICAgICB1bmdyb3VwKCkgJT4lDQogICAgICAgICAgICBzZWxlY3QoTmFtZSwgdmFsdWUpICU+JQ0KICAgICAgICAgICAgYXJyYW5nZSgtdmFsdWUpICU+JQ0KICAgICAgICAgICAgdG9wX24oMTApICU+JQ0KICAgICAgICAgICAgcmVuYW1lKGMoJyMgRGVhdGhzJyA9ICd2YWx1ZScpKQ0KICAgICAgICAgICwgIlN0YXRlcyBXaXRoIE1vc3QgRGVhdGhzIikNCg0Kc2hvd1RhYmxlKGRmLnVzICU+JQ0KICAgICAgICAgICAgZmlsdGVyKGNhc2VfdHlwZSA9PSAiUmVjb3ZlcmVkIiAmIE5hbWUgJWluJSBjKE1pZHdlc3QsIFNvdXRoLCBXZXN0LCBOb3J0aGVhc3QpKSAlPiUNCiAgICAgICAgICAgIGdyb3VwX2J5KFJlZ2lvbiwgTmFtZSkgJT4lDQogICAgICAgICAgICBhcnJhbmdlKFJlZ2lvbiwgTmFtZSwgTGFzdF9VcGRhdGUpICU+JQ0KICAgICAgICAgICAgc2xpY2UoYyhuKCkpKSAlPiUNCiAgICAgICAgICAgIHVuZ3JvdXAoKSAlPiUNCiAgICAgICAgICAgIHNlbGVjdChOYW1lLCB2YWx1ZSkgJT4lDQogICAgICAgICAgICBhcnJhbmdlKC12YWx1ZSkgJT4lDQogICAgICAgICAgICB0b3BfbigxMCkgJT4lDQogICAgICAgICAgICByZW5hbWUoYygnIyBSZWNvdmVyaWVzJyA9ICd2YWx1ZScpKQ0KICAgICAgICAgICwgIlN0YXRlcyBXaXRoIE1vc3QgUmVjb3ZlcmVkIENhc2VzIg0KICAgICAgICAgICwgIkRpc2NyZXBhbmNpZXMgZm91bmQgaW4gaG93IHJlY292ZXJpZXMgYXJlIHJlY29yZGVkIGJ5IHN0YXRlLiIpDQoNCmBgYA0KKioqDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQpzaG93VGFibGUoZGF0YSAlPiUNCiAgICAgICAgICAgIGFycmFuZ2UoUmVnaW9uLCBMYXN0X1VwZGF0ZSkgJT4lDQogICAgICAgICAgICB1bmdyb3VwKCkgJT4lDQogICAgICAgICAgICBncm91cF9ieShSZWdpb24pICU+JQ0KICAgICAgICAgICAgc3VtbWFyaXNlKGRlbHRhX2NvbmZpcm1lZD1zdW0oZGVsdGFfY29uZmlybWVkLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgICAgICAgICAgIHNlbGVjdChOYW1lLCBkZWx0YV9jb25maXJtZWQpICU+JQ0KICAgICAgICAgICAgc2xpY2UoYyhuKCkpKSAlPiUNCiAgICAgICAgICAgIGFycmFuZ2UoLWRlbHRhX2NvbmZpcm1lZCkgJT4lDQogICAgICAgICAgICB0b3Bfbig1MCkgJT4lDQogICAgICAgICAgICByZW5hbWUoYygnIyBDb25maXJtZWQgQ2FzZXMnID0gJ2RlbHRhX2NvbmZpcm1lZCcpKQ0KICAgICAgICAgICwgIlJlZ2lvbnMgV2l0aCBMYXJnZXN0IE51bWJlciBvZiBDb25maXJtZWQgQ2FzZXMiKQ0KDQpgYGANCg0KXCAgDQpcICANClwgIA0KXCANClwgIA0KXCANCg0KKioqDQoNCkEgZm9ybWVyIGNvbGxlYWd1ZSBhbmQgT2xkIERvbWluaW9uIFVuaXZlcnNpdHkgcHJvZmVzc29yLCBEci4gQ2h1Y2sgQ2FydGxlZGdlLCBwcm92aWRlZCB2YWx1YWJsZSBmZWVkYmFjayBvbiBteSBpbml0YWwgYXR0ZW1wdCBvbiBhbmFseXppbmcgdGhpcyBpbmZvcm1hdGlvbi4gIEhlIGFsc28gcmVmZXJyZWQgbWUgdG8gdGhpcyBpbnNpZ2h0ZnVsIFtIb3cgVG8gVGVsbCBJZiBXZSdyZSBCZWF0aW5nIENPVklELTE5IHZpZGVvXShodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PTU0WExYZzRmWXNjKS4gIA0KDQpUaHJlZSBrZXkgcG9pbnRzIHdlcmUgZGlzY3Vzc2VkIDEpIHVzZSBhIGxvZ2FyaXRobWljIHNjYWxlLCAyKSBmb2N1cyBvbiBjaGFuZ2UsIG5vdCBhYnNvbHV0ZSBudW1iZXJzLCBhbmQgMykgZG9uJ3QgcGxvdCBhZ2FpbnN0IHRpbWUuICANCg0KVGFraW5nIHRoaXMgaW50byBhY2NvdW50LCBsZXQncyB0YWtlIGEgbG9vayBhdCBWaXJnaW5pYSBhZ2Fpbi4NCg0KPiBUaGUgZm9sbG93aW5nIGdyYXBocyBwbG90IHRoZSB0b3RhbCBudW1iZXIgb2YgY29uZmlybWVkIGNhc2VzIG9uIHRoZSB4LWF4aXMgKCpDb25maXJtZWQqIGNvbHVtbikgYW5kIHRoZSBkYWlseSBjaGFuZ2Ugb2YgY29uZmlybWVkIGNhc2VzICgqZGVsdGFfY29uZmlybWVkKiBjb2x1bW4pIG9uIHRoZSB5LWF4aXMuDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJ30NCnBsb3REZWx0YSA8LSBmdW5jdGlvbih0aGVEYXRhLCByZXBvcnRUaXRsZSwgcGxvdExvZywgY2FzZVR5cGUpIHsNCiAgDQogIGlmIChjYXNlVHlwZSA9PSAiUmVjb3ZlcmVkIikgew0KICAgIHAgPC0gZ2dwbG90KHRoZURhdGEsDQogICAgICAgICAgICAgICAgYWVzKFJlY292ZXJlZCwgZGVsdGFfcmVjb3ZlcmVkKSkNCiAgfSBlbHNlIGlmIChjYXNlVHlwZSA9PSAiRGVhdGhzIikgew0KICAgIHAgPC0gZ2dwbG90KHRoZURhdGEsDQogICAgICAgICAgICAgICAgYWVzKERlYXRocywgZGVsdGFfZGVhdGhzKSkNCiAgfSBlbHNlIHsNCiAgICBwIDwtIGdncGxvdCh0aGVEYXRhLA0KICAgICAgICAgICAgICAgIGFlcyhDb25maXJtZWQsIGRlbHRhX2NvbmZpcm1lZCkpDQogIH0NCg0KICBwIDwtIHAgKw0KICAgIGdlb21fcG9pbnQoKSArDQogICAgc3RhdF9zbW9vdGgoKSArDQogICAgbGFicyh0aXRsZSA9IHJlcG9ydFRpdGxlDQogICAgICAgICAsIHggPSBwYXN0ZTAoIlRvdGFsIE51bWJlciBPZiAiLCBjYXNlVHlwZSkNCiAgICAgICAgICwgeSA9IHBhc3RlMCgiUHJldmlvdXMgRGF5cyBUb3RhbCBOdW1iZXIgT2YgIiwgY2FzZVR5cGUpDQogICAgICAgICAsIGNhcHRpb24gPSBwYXN0ZTAoIkNyZWF0ZWQgIiwgU3lzLnRpbWUoKSkpICsNCiAgICBzY2FsZV9jb2xvcl9maXZldGhpcnR5ZWlnaHQoKSArIA0KICAgIHRoZW1lX2ZpdmV0aGlydHllaWdodCgpDQoNCiAgaWYgKGdyZXBsKHBhdHRlcm49Il5sb2dbMC05XXsxLDJ9JCIsIHBsb3RMb2cpKSB7DQogICAgcCA8LSBwICsgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zPXBsb3RMb2cpDQogIH0NCiAgDQogIHANCn0NCg0KYGBgDQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmRmLnRlbXAgPC0gZGF0YSAlPiUgDQogIGZpbHRlcihSZWdpb24gPT0gIlVTQSIgJiBOYW1lID09ICJWaXJnaW5pYSIpICU+JSANCiAgZ3JvdXBfYnkoTmFtZSkgJT4lDQogIHNlbGVjdChOYW1lLCBMYXN0X1VwZGF0ZSwgQ29uZmlybWVkLCBEZWF0aHMsIFJlY292ZXJlZA0KICAgICAgICAgLCBkZWx0YV9jb25maXJtZWQsIGRlbHRhX2RlYXRocywgZGVsdGFfcmVjb3ZlcmVkKSAlPiUNCiAgYXJyYW5nZShMYXN0X1VwZGF0ZSkNCg0Kc2hvd1RhYmxlKGRmLnRlbXAsIlZpcmdpbmlhIENPVklELTE5IERhdGEiKQ0KDQpwbG90RGVsdGEoZGYudGVtcA0KICAgICAgICAgICwgY3JlYXRlTGFiZWwoZGYudGVtcCROYW1lDQogICAgICAgICAgICAgICAgICAgICAgICAgICAsICJsb2cxMCINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICwgcGFzdGUwKCIoIiwgc3VtKGRmLnRlbXAkZGVsdGFfY29uZmlybWVkLCBuYS5ybSA9IFRSVUUpLCAiIENvbmZpcm1lZCBDYXNlcykiKSkNCiAgICAgICAgICAsICJZIg0KICAgICAgICAgICwgIkNvbmZpcm1lZCIpDQoNCmBgYA0KXCAgDQpcICANClwgIA0KXCANClwgIA0KXCANCg0KPiBXaGF0IGlmIHdlIHBsb3R0ZWQgdGhlIG51bWJlciBvZiBmYXRhbGl0aWVzPyAgVGhlIGZhdGFsaXRpZXMgZ3JhcGhzIHBsb3QgdGhlIHRvdGFsIG51bWJlciBvZiBkZWF0aHMgb24gdGhlIHgtYXhpcyAoKkRlYXRocyogY29sdW1uKSBhbmQgdGhlIGRhaWx5IGNoYW5nZSBvZiBkZWF0aHMgKCpkZWx0YV9kZWF0aHMqIGNvbHVtbikgb24gdGhlIHktYXhpcy4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCnBsb3REZWx0YShkZi50ZW1wDQogICAgICAgICAgLCBjcmVhdGVMYWJlbChkZi50ZW1wJE5hbWUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBwYXN0ZTAoIigiLCBzdW0oZGYudGVtcCRkZWx0YV9kZWF0aHMsIG5hLnJtID0gVFJVRSksICIgRGVhdGhzKSIpKQ0KICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICwgIkRlYXRocyIpDQoNCmBgYA0KXCAgDQpcICANClwgIA0KXCANClwgIA0KXCANCg0KSW4gdGhlIHZpZGVvLCB0aGUgY3JlYXRvciBoaWdobGlnaHRlZCB0d28gY291bnRyaWVzIGV4aGliaXRpbmcgcmVjb3ZlcnkgY3VydmVzOiAgU291dGggS29yZWEgYW5kIENoaW5hLg0KDQpgYGB7ciBjaGluYV9zb3V0aF9rb3JlYV9wbG90LCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQoNCmRmLnRlbXAgPC0gZGF0YSAlPiUgDQogIGZpbHRlcihSZWdpb24gPT0gIlNvdXRoIEtvcmVhIikgJT4lIA0KICBncm91cF9ieShSZWdpb24pICU+JQ0KICBzZWxlY3QoTmFtZSwgTGFzdF9VcGRhdGUsIENvbmZpcm1lZCwgRGVhdGhzLCBSZWNvdmVyZWQNCiAgICAgICAgICwgZGVsdGFfY29uZmlybWVkLCBkZWx0YV9kZWF0aHMsIGRlbHRhX3JlY292ZXJlZCkgJT4lDQogIGFycmFuZ2UoTGFzdF9VcGRhdGUpDQoNCnBsb3REZWx0YShkZi50ZW1wDQogICAgICAgICAgLCBjcmVhdGVMYWJlbChkZi50ZW1wJE5hbWUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBwYXN0ZTAoIigiLCBzdW0oZGYudGVtcCRkZWx0YV9jb25maXJtZWQsIG5hLnJtID0gVFJVRSksICIgQ29uZmlybWVkIENhc2VzKSIpKQ0KICAgICAgICAgICwgIlkiDQogICAgICAgICAgLCAiQ29uZmlybWVkIikNCnBsb3REZWx0YShkZi50ZW1wDQogICAgICAgICAgLCBjcmVhdGVMYWJlbChkZi50ZW1wJE5hbWUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBwYXN0ZTAoIigiLCBzdW0oZGYudGVtcCRkZWx0YV9kZWF0aHMsIG5hLnJtID0gVFJVRSksICIgRGVhdGhzKSIpKQ0KICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICwgIkRlYXRocyIpDQoNCg0KZGYudGVtcCA8LSBkYXRhICU+JSANCiAgZmlsdGVyKFJlZ2lvbiA9PSAiTWFpbmxhbmQgQ2hpbmEiKSAlPiUgDQogIGdyb3VwX2J5KFJlZ2lvbikgJT4lDQogIHNlbGVjdChOYW1lLCBMYXN0X1VwZGF0ZSwgQ29uZmlybWVkLCBEZWF0aHMsIFJlY292ZXJlZA0KICAgICAgICAgLCBkZWx0YV9jb25maXJtZWQsIGRlbHRhX2RlYXRocywgZGVsdGFfcmVjb3ZlcmVkKSAlPiUNCiAgYXJyYW5nZShMYXN0X1VwZGF0ZSkNCg0KcGxvdERlbHRhKGRmLnRlbXANCiAgICAgICAgICAsIGNyZWF0ZUxhYmVsKCJNYWlubGFuZCBDaGluYSINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBwYXN0ZTAoIigiLCBzdW0oZGYudGVtcCRkZWx0YV9jb25maXJtZWQsIG5hLnJtID0gVFJVRSksICIgQ29uZmlybWVkIENhc2VzKSIpKQ0KICAgICAgICAgICwgIlkiDQogICAgICAgICAgLCAiQ29uZmlybWVkIikNCnBsb3REZWx0YShkZi50ZW1wDQogICAgICAgICAgLCBjcmVhdGVMYWJlbCgiTWFpbmxhbmQgQ2hpbmEiDQogICAgICAgICAgICAgICAgICAgICAgICAgICAsICJsb2cxMCINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICwgcGFzdGUwKCIoIiwgc3VtKGRmLnRlbXAkZGVsdGFfZGVhdGhzLCBuYS5ybSA9IFRSVUUpLCAiIERlYXRocykiKSkNCiAgICAgICAgICAsICJsb2cxMCINCiAgICAgICAgICAsICJEZWF0aHMiKQ0KDQpgYGANClwgIA0KXCAgDQpcICANClwgDQpcICANClwgDQoNClRoZSB2aWRlbyBhbHNvIHNob3dlZCBKYXBhbiBoYXZpbmcgYSBzbGlnaHQgdXB0aWNrICg1OjQ5IG9mIHRoZSB2aWRlbykuICBXaGF0IGRvZXMgdGhlIGRhdGEgcmV2ZWFsPyAgKE5vdGU6ICBPbiAwNyBBcHJpbCAyMDIwLCBKYXBhbiBkZWNsYXJlcyBhIFtzdGF0ZSBvZiBlbWVyZ2VuY3ldKGh0dHBzOi8vYXBuZXdzLmNvbS82ZTUwNmM0ZjEwNTY3MGI4ZmE4ZWI1NTMxYWFkZjJjMSkuKQ0KDQpgYGB7ciBqYXBhbl9wbG90LCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQpkZi50ZW1wIDwtIGRhdGEgJT4lIA0KICBmaWx0ZXIoUmVnaW9uID09ICJKYXBhbiIpICU+JSANCiAgZ3JvdXBfYnkoUmVnaW9uKSAlPiUNCiAgc2VsZWN0KE5hbWUsIExhc3RfVXBkYXRlLCBDb25maXJtZWQsIERlYXRocywgUmVjb3ZlcmVkDQogICAgICAgICAsIGRlbHRhX2NvbmZpcm1lZCwgZGVsdGFfZGVhdGhzLCBkZWx0YV9yZWNvdmVyZWQpICU+JQ0KICBhcnJhbmdlKExhc3RfVXBkYXRlKQ0KDQpwbG90RGVsdGEoZGYudGVtcA0KICAgICAgICAgICwgY3JlYXRlTGFiZWwoZGYudGVtcCROYW1lDQogICAgICAgICAgICAgICAgICAgICAgICAgICAsICJsb2cxMCINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICwgcGFzdGUwKCIoIiwgc3VtKGRmLnRlbXAkZGVsdGFfY29uZmlybWVkLCBuYS5ybSA9IFRSVUUpLCAiIENvbmZpcm1lZCBDYXNlcykiKSkNCiAgICAgICAgICAsICJZIg0KICAgICAgICAgICwgIkNvbmZpcm1lZCIpDQpwbG90RGVsdGEoZGYudGVtcA0KICAgICAgICAgICwgY3JlYXRlTGFiZWwoZGYudGVtcCROYW1lDQogICAgICAgICAgICAgICAgICAgICAgICAgICAsICJsb2cxMCINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICwgcGFzdGUwKCIoIiwgc3VtKGRmLnRlbXAkZGVsdGFfZGVhdGhzLCBuYS5ybSA9IFRSVUUpLCAiIERlYXRocykiKSkNCiAgICAgICAgICAsICJsb2cxMCINCiAgICAgICAgICAsICJEZWF0aHMiKQ0KDQoNCmBgYA0KXCAgDQpcICANClwgIA0KXCANClwgIA0KXCANCg0KSG93IGRvZXMgdGhlIFVuaXRlZCBTdGF0ZXMgY29tcGFyZSB3aXRoIHRoZXNlIGNvdW50cmllcz8NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmRmLnRlbXAgPC0gZGF0YSAlPiUgDQogIGZpbHRlcihSZWdpb24gPT0gIlVTQSIpICU+JSANCiAgZ3JvdXBfYnkoUmVnaW9uKSAlPiUNCiAgc2VsZWN0KE5hbWUsIExhc3RfVXBkYXRlLCBDb25maXJtZWQsIERlYXRocywgUmVjb3ZlcmVkDQogICAgICAgICAsIGRlbHRhX2NvbmZpcm1lZCwgZGVsdGFfZGVhdGhzLCBkZWx0YV9yZWNvdmVyZWQpICU+JQ0KICBhcnJhbmdlKExhc3RfVXBkYXRlKQ0KDQpwbG90RGVsdGEoZGYudGVtcA0KICAgICAgICAgICwgY3JlYXRlTGFiZWwoIlVTQSINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBwYXN0ZTAoIigiLCBzdW0oZGYudGVtcCRkZWx0YV9jb25maXJtZWQsIG5hLnJtID0gVFJVRSksICIgQ29uZmlybWVkIENhc2VzKSIpKQ0KICAgICAgICAgICwgIlkiDQogICAgICAgICAgLCAiQ29uZmlybWVkIikNCnBsb3REZWx0YShkZi50ZW1wDQogICAgICAgICAgLCBjcmVhdGVMYWJlbCgiVVNBIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAibG9nMTAiDQogICAgICAgICAgICAgICAgICAgICAgICAgICAsIHBhc3RlMCgiKCIsIHN1bShkZi50ZW1wJGRlbHRhX2RlYXRocywgbmEucm0gPSBUUlVFKSwgIiBEZWF0aHMpIikpDQogICAgICAgICAgLCAibG9nMTAiDQogICAgICAgICAgLCAiRGVhdGhzIikNCg0KYGBgDQpcICANClwgIA0KXCAgDQpcIA0KXCAgDQpcIA0KDQpGaW5hbGx5LCB0b2RheSAoQXByaWwgNSwgMjAyMCksIEkgaGVhcmQgdGhhdCB0aGluZ3MgaW4gSXRhbHkgYXJlIHN0YXJ0aW5nIGxvb2sgW2Zhdm9yYWJsZV0oaHR0cHM6Ly93d3cuY2JzbmV3cy5jb20vbGl2ZS92aWRlby8yMDIwMDQwNTE2MjA1NC11cGRhdGUtb24taXRhbHlzLWNvcm9uYXZpcnVzLW91dGJyZWFrLykuICBXaGF0IGRvZXMgdGhlIGRhdGEgc2F5Pw0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KZGYudGVtcCA8LSBkYXRhICU+JSANCiAgZmlsdGVyKFJlZ2lvbiA9PSAiSXRhbHkiKSAlPiUgDQogIGdyb3VwX2J5KFJlZ2lvbikgJT4lDQogIHNlbGVjdChOYW1lLCBMYXN0X1VwZGF0ZSwgQ29uZmlybWVkLCBEZWF0aHMsIFJlY292ZXJlZA0KICAgICAgICAgLCBkZWx0YV9jb25maXJtZWQsIGRlbHRhX2RlYXRocywgZGVsdGFfcmVjb3ZlcmVkKSAlPiUNCiAgYXJyYW5nZShMYXN0X1VwZGF0ZSkNCg0KcGxvdERlbHRhKGRmLnRlbXANCiAgICAgICAgICAsIGNyZWF0ZUxhYmVsKGRmLnRlbXAkTmFtZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAibG9nMTAiDQogICAgICAgICAgICAgICAgICAgICAgICAgICAsIHBhc3RlMCgiKCIsIHN1bShkZi50ZW1wJGRlbHRhX2NvbmZpcm1lZCwgbmEucm0gPSBUUlVFKSwgIiBDb25maXJtZWQgQ2FzZXMpIikpDQogICAgICAgICAgLCAiWSINCiAgICAgICAgICAsICJDb25maXJtZWQiKQ0KcGxvdERlbHRhKGRmLnRlbXANCiAgICAgICAgICAsIGNyZWF0ZUxhYmVsKGRmLnRlbXAkTmFtZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAibG9nMTAiDQogICAgICAgICAgICAgICAgICAgICAgICAgICAsIHBhc3RlMCgiKCIsIHN1bShkZi50ZW1wJGRlbHRhX2RlYXRocywgbmEucm0gPSBUUlVFKSwgIiBEZWF0aHMpIikpDQogICAgICAgICAgLCAibG9nMTAiDQogICAgICAgICAgLCAiRGVhdGhzIikNCnBsb3REZWx0YShkZi50ZW1wDQogICAgICAgICAgLCBjcmVhdGVMYWJlbChkZi50ZW1wJE5hbWUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBwYXN0ZTAoIigiLCBzdW0oZGYudGVtcCRkZWx0YV9yZWNvdmVyZWQsIG5hLnJtID0gVFJVRSksICIgUmVjb3ZlcmVkKSIpKQ0KICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICwgIlJlY292ZXJpZXMiKQ0KDQpgYGANCg0KDQpgYGB7ciBwbG90X3VzX3JlZ2lvbnMsIGVjaG8gPSBGQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCg0KIyBzYXZlIFVTIHJlZ2lvbnMgdG8gZmlsZXMNCg0KZm9yICh2YWwgaW4gYyhNaWR3ZXN0LCBTb3V0aCwgV2VzdCwgTm9ydGhlYXN0KSkgew0KICBkZi50ZW1wIDwtIGRhdGEgJT4lIA0KICAgIGZpbHRlcihSZWdpb24gPT0gIlVTQSIgJiBOYW1lID09IHZhbCkgJT4lIA0KICAgIGdyb3VwX2J5KE5hbWUpICU+JQ0KICAgIHNlbGVjdChOYW1lLCBMYXN0X1VwZGF0ZSwgQ29uZmlybWVkLCBEZWF0aHMsIFJlY292ZXJlZA0KICAgICAgICAgICAsIGRlbHRhX2NvbmZpcm1lZCwgZGVsdGFfZGVhdGhzLCBkZWx0YV9yZWNvdmVyZWQpICU+JQ0KICAgIGFycmFuZ2UoTGFzdF9VcGRhdGUpDQogIA0KICBwIDwtIHBsb3REZWx0YShkZi50ZW1wDQogICAgICAgICAgICAsIGNyZWF0ZUxhYmVsKGRmLnRlbXAkTmFtZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAsICJsb2cxMCINCiAgICAgICAgICAgICAgICAgICAgICAgICAgLCBwYXN0ZTAoIigiLCBzdW0oZGYudGVtcCRkZWx0YV9jb25maXJtZWQsIG5hLnJtID0gVFJVRSksICIgQ29uZmlybWVkIENhc2VzKSIpKQ0KICAgICAgICAgICAgLCAiWSINCiAgICAgICAgICAgICwgIkNvbmZpcm1lZCIpDQogIGdnc2F2ZShmaWxlbmFtZT1wYXN0ZTAoIi4vaW1hZ2VzLyIsIGRmLnRlbXAkTmFtZSwgIl9jb25maXJtZWQucG5nIiksIGRldmljZT0icG5nIiwgcGxvdD1wKQ0KICANCiAgcCA8LSBwbG90RGVsdGEoZGYudGVtcA0KICAgICAgICAgICAgLCBjcmVhdGVMYWJlbChkZi50ZW1wJE5hbWUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgLCAibG9nMTAiDQogICAgICAgICAgICAgICAgICAgICAgICAgICwgcGFzdGUwKCIoIiwgc3VtKGRmLnRlbXAkZGVsdGFfZGVhdGhzLCBuYS5ybSA9IFRSVUUpLCAiIERlYXRocykiKSkNCiAgICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICAgLCAiRGVhdGhzIikNCiAgZ2dzYXZlKGZpbGVuYW1lPXBhc3RlMCgiLi9pbWFnZXMvIiwgZGYudGVtcCROYW1lLCAiX2RlYXRocy5wbmciKSwgZGV2aWNlPSJwbmciLCBwbG90PXApDQp9DQoNCmBgYA0KDQpgYGB7ciBwbG90X2hhcHB5X3JlZ2lvbnMsIGVjaG8gPSBGQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCg0KIyBwbG90IHNlbGVjdGVkIHJlZ2lvbnMgKHRvcCAxMCBoYXBwaWVzdCBjb3VudHJpZXMpDQoNCmZvciAodmFsIGluIGMoIkZpbmxhbmQiLCAiRGVubWFyayIsICJTd2l0emVybGFuZCIsICJJY2VsYW5kIiwgIk5vcndheSINCiAgICAgICAgICAgICwgIk5ldGhlcmxhbmRzIiwgIlN3ZWRlbiIsICJOZXcgWmVhbGFuZCIsICJBdXN0cmlhIiwgIkx1eGVtYm91cmciKSkgew0KICBkZi50ZW1wIDwtIGRhdGEgJT4lIA0KICAgIGZpbHRlcihSZWdpb24gPT0gdmFsKSAlPiUgDQogICAgZ3JvdXBfYnkoUmVnaW9uKSAlPiUNCiAgICBzZWxlY3QoTmFtZSwgTGFzdF9VcGRhdGUsIENvbmZpcm1lZCwgRGVhdGhzLCBSZWNvdmVyZWQNCiAgICAgICAgICAgLCBkZWx0YV9jb25maXJtZWQsIGRlbHRhX2RlYXRocywgZGVsdGFfcmVjb3ZlcmVkKSAlPiUNCiAgICBhcnJhbmdlKExhc3RfVXBkYXRlKQ0KICANCiAgcCA8LSBwbG90RGVsdGEoZGYudGVtcA0KICAgICAgICAgICAgLCBjcmVhdGVMYWJlbChkZi50ZW1wJE5hbWUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgLCAibG9nMTAiDQogICAgICAgICAgICAgICAgICAgICAgICAgICwgcGFzdGUwKCIoIiwgc3VtKGRmLnRlbXAkZGVsdGFfY29uZmlybWVkLCBuYS5ybSA9IFRSVUUpLCAiIENvbmZpcm1lZCBDYXNlcykiKSkNCiAgICAgICAgICAgICwgIlkiDQogICAgICAgICAgICAsICJDb25maXJtZWQiKQ0KICBnZ3NhdmUoZmlsZW5hbWU9cGFzdGUwKCIuL2ltYWdlcy8iLCBkZi50ZW1wJE5hbWUsICJfY29uZmlybWVkLnBuZyIpLCBkZXZpY2U9InBuZyIsIHBsb3Q9cCkNCiAgDQogIHAgPC0gcGxvdERlbHRhKGRmLnRlbXANCiAgICAgICAgICAgICwgY3JlYXRlTGFiZWwoZGYudGVtcCROYW1lDQogICAgICAgICAgICAgICAgICAgICAgICAgICwgImxvZzEwIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAsIHBhc3RlMCgiKCIsIHN1bShkZi50ZW1wJGRlbHRhX2RlYXRocywgbmEucm0gPSBUUlVFKSwgIiBEZWF0aHMpIikpDQogICAgICAgICAgICAsICJsb2cxMCINCiAgICAgICAgICAgICwgIkRlYXRocyIpDQogIGdnc2F2ZShmaWxlbmFtZT1wYXN0ZTAoIi4vaW1hZ2VzLyIsIGRmLnRlbXAkTmFtZSwgIl9kZWF0aHMucG5nIiksIGRldmljZT0icG5nIiwgcGxvdD1wKQ0KfQ0KDQpgYGANCg0KIyMjIEVuZCBOb3Rlcy4NCk1pbnV0ZXMgYmVmb3JlIGZpcnN0IHB1Ymxpc2hpbmcgdGhpcyByZXBvcnQgb24gMDMgQXByaWwgMjAyMCwgYW4gYXJ0aWNsZSBlbnRpdGxlZCBbUHJlcGFyaW5nIEZvciB0aGUgUGVha10oaHR0cHM6Ly93d3cuMTNuZXdzbm93LmNvbS9hcnRpY2xlL25ld3MvaGVhbHRoL2Nvcm9uYXZpcnVzL2hlcmVzLXdoZW4tY292aWQtMTktY291bGQtcGVhay1pbi10aGUtZG12LzI5MS00ZTE5YzU5Yi0wMzczLTQyMGMtYTUyMy1hMjA1YTdkNjBhYmUpIGFwcGVhcmVkIGluIG15IGVtYWlsLiAgV2hhdCBhIGNvaW5jaWRlbmNlLg0KDQpJJ3ZlIHJlY2VpdmVkIHF1ZXN0aW9ucyByZWdhcmRpbmcgdGhlIHZhbGlkaXR5IGFuZCBzb3VyY2Ugb2YgdGhlIGRhdGEgdXNlZCBpbiB0aGlzIHJlcG9ydC4gIFRoZSBzb3VyY2Ugb2YgdGhlIGRhdGEgaXMgZnJvbSB0aGUgW0NPVklELTE5IFN1cnZlaWxsYW5jZSBEYXNoYm9hcmRdKGh0dHBzOi8vbnNzYWMuZ2l0aHViLmlvL2NvdmlkLTE5L2Rhc2hib2FyZC8jZmFxKS4gIFRoZXkgYWdncmVnYXRlZCB0aGUgZGF0YSBmcm9tIG51bWVyb3VzIHJlbGlhYmxlIHNvdXJjZXMuDQoNCioqQWRkaXRpb25hbCBwbG90cy4qKiAgQ2hlY2sgb3V0IHBsb3RzIGZyb20gb25lIG9mIHRoZXNlIG90aGVyIFtgciBsZW5ndGgodW5pcXVlKGdzdWIoIihfY29uZmlybWVkfF9kZWF0aHMpIiwgIiIsIGxpc3QuZmlsZXMocGF0aCA9ICIuL2ltYWdlcyIsIHBhdHRlcm49IlxcLnBuZyIpKSkpYCAgYXJlYXMgb2YgaW50ZXJlc3RdKGh0dHBzOi8vd3d3LmRyb3Bib3guY29tL3NoL2s0cWc5bnc1eXdmazRneS9BQUN4QVpfSWRta1AtbzAzT0FjZC1xd2ZhP2RsPTApLiBbSWYgdGhlIGxpbmsgZmFpbHMgdG8gcmVuZGVyLCByaWdodC1jbGljayBvbiBpdCBhbmQgb3BlbiBpbiBhIG5ldyB3aW5kb3ddLg0KDQpcIA0KXCAgDQpcIA0KDQpgYGANCkV2ZXJ5IGF0dGVtcHQgd2FzIG1hZGUgdG8gY29udmV5IHZhbGlkIGFuZCBhY2N1cmF0ZSByZXN1bHRzIGJhc2VkIHVwb24gdGhlIGRhdGEgcHJvdmlkZWQuDQoNClN0YXkgd2VsbCBhbmQgYmUgc2FmZS4NCg0KYGBgDQoNClwgDQpcICANClwgDQoNCiMjIyMjIyBSZXBvcnQgZ2VuZXJhdGVkOiAgYHIgU3lzLnRpbWUoKWANCg0KDQpgYGB7ciBzY3JhdGNocGFkLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGV2YWw9RkFMU0V9DQoNCiMgIGZpbHRlcihOYW1lICVpbiUgYyhNaWR3ZXN0LCBTb3V0aCwgV2VzdCwgTm9ydGhlYXN0KSAmIGNhc2VfdHlwZSA9PSAnQ29uZmlybWVkJykgJT4lDQoNCmRhdGEgPC0gbXV0YXRlX2F0KGRhdGEsIHZhcnMoJ05hbWUnLCAnZ3JvdXAnKSwgYXMuZmFjdG9yKQ0KDQojIFNldCBhIG51bWJlciBvZiAnZW1wdHkgYmFyJyB0byBhZGQgYXQgdGhlIGVuZCBvZiBlYWNoIGdyb3VwDQplbXB0eV9iYXIgPC0gNA0KdG9fYWRkIDwtIGRhdGEuZnJhbWUoIG1hdHJpeChOQSwgZW1wdHlfYmFyKm5sZXZlbHMoZGF0YSRncm91cCksIG5jb2woZGF0YSkpICkNCmNvbG5hbWVzKHRvX2FkZCkgPC0gY29sbmFtZXMoZGF0YSkNCnRvX2FkZCRncm91cCA8LSByZXAobGV2ZWxzKGRhdGEkZ3JvdXApLCBlYWNoPWVtcHR5X2JhcikNCmRhdGEgPC0gcmJpbmQoZGF0YSwgdG9fYWRkKQ0KZGF0YSA8LSBkYXRhICU+JSBhcnJhbmdlKGdyb3VwKQ0KZGF0YSRpZCA8LSBzZXEoMSwgbnJvdyhkYXRhKSkNCiANCiMgR2V0IHRoZSBuYW1lIGFuZCB0aGUgeSBwb3NpdGlvbiBvZiBlYWNoIGxhYmVsDQpsYWJlbF9kYXRhIDwtIGRhdGENCm51bWJlcl9vZl9iYXIgPC0gbnJvdyhsYWJlbF9kYXRhKQ0KYW5nbGUgPC0gOTAgLSAzNjAgKiAobGFiZWxfZGF0YSRpZC0wLjUpIC9udW1iZXJfb2ZfYmFyICAgICAjIEkgc3Vic3RyYWN0IDAuNSBiZWNhdXNlIHRoZSBsZXR0ZXIgbXVzdCBoYXZlIHRoZSBhbmdsZSBvZiB0aGUgY2VudGVyIG9mIHRoZSBiYXJzLiBOb3QgZXh0cmVtZSByaWdodCgxKSBvciBleHRyZW1lIGxlZnQgKDApDQpsYWJlbF9kYXRhJGhqdXN0IDwtIGlmZWxzZSggYW5nbGUgPCAtOTAsIDEsIDApDQpsYWJlbF9kYXRhJGFuZ2xlIDwtIGlmZWxzZShhbmdsZSA8IC05MCwgYW5nbGUrMTgwLCBhbmdsZSkNCiANCiMgTWFrZSB0aGUgcGxvdA0KcCA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHg9YXMuZmFjdG9yKGlkKSwgeT12YWx1ZSwgZmlsbD1ncm91cCkpICsgICAgICAgIyBOb3RlIHRoYXQgaWQgaXMgYSBmYWN0b3IuIElmIHggaXMgbnVtZXJpYywgdGhlcmUgaXMgc29tZSBzcGFjZSBiZXR3ZWVuIHRoZSBmaXJzdCBiYXINCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBhbHBoYT0wLjUpICsNCiAgeWxpbSgtMTAwLDEyMCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwbG90Lm1hcmdpbiA9IHVuaXQocmVwKC0xLDQpLCAiY20iKSANCiAgKSArDQogIGNvb3JkX3BvbGFyKCkgKyANCiAgZ2VvbV90ZXh0KGRhdGE9bGFiZWxfZGF0YSwgYWVzKHg9aWQsIHk9dmFsdWUrMTAsIGxhYmVsPU5hbWUsIGhqdXN0PWhqdXN0KSwgY29sb3I9ImJsYWNrIiwgZm9udGZhY2U9ImJvbGQiLGFscGhhPTAuNiwgc2l6ZT0yLjUsIGFuZ2xlPSBsYWJlbF9kYXRhJGFuZ2xlLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgDQogDQpwDQoNCg0KIyAtLS0tLS0tLS0tLS0tDQoNCiMgQ3JlYXRlIGRhdGFzZXQNCmRhdGEgPC0gZGF0YS5mcmFtZSgNCiAgaW5kaXZpZHVhbD1wYXN0ZSggIk1pc3RlciAiLCBzZXEoMSw2MCksIHNlcD0iIiksDQogIGdyb3VwPWMoIHJlcCgnQScsIDEwKSwgcmVwKCdCJywgMzApLCByZXAoJ0MnLCAxNCksIHJlcCgnRCcsIDYpKSAsDQogIHZhbHVlPXNhbXBsZSggc2VxKDEwLDEwMCksIDYwLCByZXBsYWNlPVQpDQopDQogDQojIFNldCBhIG51bWJlciBvZiAnZW1wdHkgYmFyJyB0byBhZGQgYXQgdGhlIGVuZCBvZiBlYWNoIGdyb3VwDQplbXB0eV9iYXIgPC0gNA0KdG9fYWRkIDwtIGRhdGEuZnJhbWUoIG1hdHJpeChOQSwgZW1wdHlfYmFyKm5sZXZlbHMoZGF0YSRncm91cCksIG5jb2woZGF0YSkpICkNCmNvbG5hbWVzKHRvX2FkZCkgPC0gY29sbmFtZXMoZGF0YSkNCnRvX2FkZCRncm91cCA8LSByZXAobGV2ZWxzKGRhdGEkZ3JvdXApLCBlYWNoPWVtcHR5X2JhcikNCmRhdGEgPC0gcmJpbmQoZGF0YSwgdG9fYWRkKQ0KZGF0YSA8LSBkYXRhICU+JSBhcnJhbmdlKGdyb3VwKQ0KZGF0YSRpZCA8LSBzZXEoMSwgbnJvdyhkYXRhKSkNCiANCiMgR2V0IHRoZSBuYW1lIGFuZCB0aGUgeSBwb3NpdGlvbiBvZiBlYWNoIGxhYmVsDQpsYWJlbF9kYXRhIDwtIGRhdGENCm51bWJlcl9vZl9iYXIgPC0gbnJvdyhsYWJlbF9kYXRhKQ0KYW5nbGUgPC0gOTAgLSAzNjAgKiAobGFiZWxfZGF0YSRpZC0wLjUpIC9udW1iZXJfb2ZfYmFyICAgICAjIEkgc3Vic3RyYWN0IDAuNSBiZWNhdXNlIHRoZSBsZXR0ZXIgbXVzdCBoYXZlIHRoZSBhbmdsZSBvZiB0aGUgY2VudGVyIG9mIHRoZSBiYXJzLiBOb3QgZXh0cmVtZSByaWdodCgxKSBvciBleHRyZW1lIGxlZnQgKDApDQpsYWJlbF9kYXRhJGhqdXN0IDwtIGlmZWxzZSggYW5nbGUgPCAtOTAsIDEsIDApDQpsYWJlbF9kYXRhJGFuZ2xlIDwtIGlmZWxzZShhbmdsZSA8IC05MCwgYW5nbGUrMTgwLCBhbmdsZSkNCiANCiMgTWFrZSB0aGUgcGxvdA0KcCA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHg9YXMuZmFjdG9yKGlkKSwgeT12YWx1ZSwgZmlsbD1ncm91cCkpICsgICAgICAgIyBOb3RlIHRoYXQgaWQgaXMgYSBmYWN0b3IuIElmIHggaXMgbnVtZXJpYywgdGhlcmUgaXMgc29tZSBzcGFjZSBiZXR3ZWVuIHRoZSBmaXJzdCBiYXINCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBhbHBoYT0wLjUpICsNCiAgeWxpbSgtMTAwLDEyMCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwbG90Lm1hcmdpbiA9IHVuaXQocmVwKC0xLDQpLCAiY20iKSANCiAgKSArDQogIGNvb3JkX3BvbGFyKCkgKyANCiAgZ2VvbV90ZXh0KGRhdGE9bGFiZWxfZGF0YSwgYWVzKHg9aWQsIHk9dmFsdWUrMTAsIGxhYmVsPWluZGl2aWR1YWwsIGhqdXN0PWhqdXN0KSwgY29sb3I9ImJsYWNrIiwgZm9udGZhY2U9ImJvbGQiLGFscGhhPTAuNiwgc2l6ZT0yLjUsIGFuZ2xlPSBsYWJlbF9kYXRhJGFuZ2xlLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgDQogDQpwDQopDQoNCg0KbXlEZiA8LSBkYXRhICU+JSBmaWx0ZXIoTmFtZSA9PSAiVmlyZ2luaWEiKSAlPiUgYXJyYW5nZShMYXN0X1VwZGF0ZSkgJT4lIHVuZ3JvdXAoKSAlPiUgc2VsZWN0KENvbmZpcm1lZCkNCm15RGYgPC0gRGF0YUNvbWJpbmU6OnNsaWRlKG15RGYsICJDb25maXJtZWQiLCBOZXdWYXIgPSAieExhZzEiLCBzbGlkZUJ5ID0gLTEpDQoNCm15REYgPC0gZGF0YSAlPiUNCiAgICAgICAgICAgIGZpbHRlcihOYW1lICVpbiUgYyhOb3J0aGVhc3QpKSAlPiUNCiAgICAgICAgICAgIGdyb3VwX2J5KFJlZ2lvbiwgTmFtZSkgJT4lDQogICAgICAgICAgICBhcnJhbmdlKFJlZ2lvbiwgTmFtZSwgTGFzdF9VcGRhdGUpICU+JQ0KICAgICAgICAgICAgdW5ncm91cCgpICU+JQ0KICAgICAgICAgICAgc2VsZWN0KE5hbWUsIExhc3RfVXBkYXRlLCBkZWx0YV9jb25maXJtZWQpICU+JQ0KICAgICAgICAgICAgYXJyYW5nZShOYW1lLCBMYXN0X1VwZGF0ZSkgJT4lDQogICAgICAgICAgICByZW5hbWUoRGF0ZT1MYXN0X1VwZGF0ZSwgQ2hhbmdlPWRlbHRhX2NvbmZpcm1lZCkNCg0KbXlERiRyb3dfbnVtIDwtIHNlcS5pbnQobnJvdyhteURGKSkgIA0KDQpnZXRBSU9fc3RhcnRfaWR4IDwtIGZ1bmN0aW9uKGRmLCBuYW1lKSB7DQogIGRmICU+JSBmaWx0ZXIoTmFtZSA9PSBuYW1lKSAlPiUgc2xpY2UoMSkgJT4lIHB1bGwocm93X251bSkNCn0NCg0KZ2V0QUlPX2VuZF9pZHggPC0gZnVuY3Rpb24oZGYsIG5hbWUpIHsNCiAgZGYgJT4lIGZpbHRlcihOYW1lID09IG5hbWUpICU+JSBzbGljZShuKCkpICU+JSBwdWxsKHJvd19udW0pDQp9DQoNCmthYmxlKG15REYgJT4lIHNlbGVjdChEYXRlLCBDaGFuZ2UpDQogICAgICAsIGNhcHRpb24gPSAiQ29uZmlybWVkIENhc2VzIFRyZW5kIEZvciBOb3J0aGVhc3QgUmVnaW9uIikgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGKSAlPiUNCiAgcGFja19yb3dzKCJDb25uZWN0aWN1dCINCiAgICAgICAgICAgICwgZ2V0QUlPX3N0YXJ0X2lkeChteURGLCAiQ29ubmVjdGljdXQiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiQ29ubmVjdGljdXQiKQ0KICAgICAgICAgICAgKSAlPiUNCiAgcGFja19yb3dzKCJNYWluZSINCiAgICAgICAgICAgICwgZ2V0QUlPX3N0YXJ0X2lkeChteURGLCAiTWFpbmUiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiTWFpbmUiKQ0KICAgICAgICAgICAgKSAlPiUNCiAgcGFja19yb3dzKCJNYXNzYWNodXNldHRzIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJNYXNzYWNodXNldHRzIikNCiAgICAgICAgICAgICwgZ2V0QUlPX2VuZF9pZHgobXlERiwgIk1hc3NhY2h1c2V0dHMiKQ0KICAgICAgICAgICAgKSAlPiUNCiAgcGFja19yb3dzKCJOZXcgSGFtcHNoaXJlIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJOZXcgSGFtcHNoaXJlIikNCiAgICAgICAgICAgICwgZ2V0QUlPX2VuZF9pZHgobXlERiwgIk5ldyBIYW1wc2hpcmUiKQ0KICAgICAgICAgICAgKSAlPiUNCiAgcGFja19yb3dzKCJSaG9kZSBJc2xhbmQiDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIlJob2RlIElzbGFuZCIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJSaG9kZSBJc2xhbmQiKQ0KICAgICAgICAgICAgKSAlPiUNCiAgcGFja19yb3dzKCJWZXJtb250Ig0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJWZXJtb250IikNCiAgICAgICAgICAgICwgZ2V0QUlPX2VuZF9pZHgobXlERiwgIlZlcm1vbnQiKQ0KICAgICAgICAgICAgKSAlPiUNCiAgcGFja19yb3dzKCJOZXcgSmVyc2V5Ig0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJOZXcgSmVyc2V5IikNCiAgICAgICAgICAgICwgZ2V0QUlPX2VuZF9pZHgobXlERiwgIk5ldyBKZXJzZXkiKQ0KICAgICAgICAgICAgKSAlPiUNCiAgcGFja19yb3dzKCJOZXcgWW9yayINCiAgICAgICAgICAgICwgZ2V0QUlPX3N0YXJ0X2lkeChteURGLCAiTmV3IFlvcmsiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiTmV3IFlvcmsiKQ0KICAgICAgICAgICAgKSAlPiUNCiAgcGFja19yb3dzKCJQZW5uc3lsdmFuaWEiDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIlBlbm5zeWx2YW5pYSIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJQZW5uc3lsdmFuaWEiKQ0KICAgICAgICAgICAgKSAlPiUNCiAgcGFja19yb3dzKCJQdWVydG8gUmljbyINCiAgICAgICAgICAgICwgZ2V0QUlPX3N0YXJ0X2lkeChteURGLCAiUHVlcnRvIFJpY28iKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiUHVlcnRvIFJpY28iKQ0KICAgICAgICAgICAgKSAlPiUNCiAgcGFja19yb3dzKCJVUyBWaXJnaW4gSXNsYW5kcyINCiAgICAgICAgICAgICwgZ2V0QUlPX3N0YXJ0X2lkeChteURGLCAiVVMgVmlyZ2luIElzbGFuZHMiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiVVMgVmlyZ2luIElzbGFuZHMiKQ0KICAgICAgICAgICAgKSAlPiUNCiAgc2Nyb2xsX2JveChoZWlnaHQgPSAiNDAwcHgiKQ0KDQoNCm15REYuMSA8LSBteURGICU+JSBmaWx0ZXIoTmFtZSAlaW4lIGMoTWlkd2VzdCkpDQpteURGLjEgPC0gbXlERiAlPiUgZmlsdGVyKE5hbWUgJWluJSBjKFNvdXRoKSkNCm15REYuMSA8LSBteURGICU+JSBmaWx0ZXIoTmFtZSAlaW4lIGMoV2VzdCkpDQpteURGLjEgPC0gbXlERiAlPiUgZmlsdGVyKE5hbWUgJWluJSBjKE5vcnRoZWFzdCkpDQoNCmthYmxlKG15REYgJT4lIHNlbGVjdChMYXN0X1VwZGF0ZSwgZGVsdGFfY29uZmlybWVkKQ0KICAgICAgLCBjYXB0aW9uID0gIlRyZW5kIG9mIENvbmZpcm1lZCBDYXNlcyBGb3IgVVMgQXJlYXMgb2YgSW50ZXJlc3QiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYpICU+JQ0KICBwYWNrX3Jvd3MoIkFsYWJhbWEiDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIkFsYWJhbWEiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiQWxhYmFtYSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkFsYXNrYSINCiAgICAgICAgICAgICwgZ2V0QUlPX3N0YXJ0X2lkeChteURGLCAiQWxhc2thIikNCiAgICAgICAgICAgICwgZ2V0QUlPX2VuZF9pZHgobXlERiwgIkFsYXNrYSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkFyaXpvbmEiDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIkFyaXpvbmEiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiQXJpem9uYSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkFya2Fuc2FzIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJBcmthbnNhcyIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJBcmthbnNhcyIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkNhbGlmb3JuaWEiDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIkNhbGlmb3JuaWEiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiQ2FsaWZvcm5pYSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkNvbG9yYWRvIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJDb2xvcmFkbyIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJDb2xvcmFkbyIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkNvbm5lY3RpY3V0Ig0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJDb25uZWN0aWN1dCIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJDb25uZWN0aWN1dCIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkRlbGF3YXJlIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJEZWxhd2FyZSIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJEZWxhd2FyZSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkRpc3RyaWN0IG9mIENvbHVtYmlhIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJEaXN0cmljdCBvZiBDb2x1bWJpYSIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJEaXN0cmljdCBvZiBDb2x1bWJpYSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkZsb3JpZGEiDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIkZsb3JpZGEiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiRmxvcmlkYSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkdlb3JnaWEiDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIkdlb3JnaWEiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiR2VvcmdpYSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkd1YW0iDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIkd1YW0iKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiR3VhbSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkhhd2FpaSINCiAgICAgICAgICAgICwgZ2V0QUlPX3N0YXJ0X2lkeChteURGLCAiSGF3YWlpIikNCiAgICAgICAgICAgICwgZ2V0QUlPX2VuZF9pZHgobXlERiwgIkhhd2FpaSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIklkYWhvIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJJZGFobyIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJJZGFobyIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIklsbGlub2lzIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJJbGxpbm9pcyIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJJbGxpbm9pcyIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkluZGlhbmEiDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIkluZGlhbmEiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiSW5kaWFuYSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIklvd2EiDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIklvd2EiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiSW93YSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkthbnNhcyINCiAgICAgICAgICAgICwgZ2V0QUlPX3N0YXJ0X2lkeChteURGLCAiS2Fuc2FzIikNCiAgICAgICAgICAgICwgZ2V0QUlPX2VuZF9pZHgobXlERiwgIkthbnNhcyIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIktlbnR1Y2t5Ig0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJLZW50dWNreSIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJLZW50dWNreSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIkxvdWlzaWFuYSINCiAgICAgICAgICAgICwgZ2V0QUlPX3N0YXJ0X2lkeChteURGLCAiTG91aXNpYW5hIikNCiAgICAgICAgICAgICwgZ2V0QUlPX2VuZF9pZHgobXlERiwgIkxvdWlzaWFuYSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIk1haW5lIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJNYWluZSIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJNYWluZSIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIk1hcnlsYW5kIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJNYXJ5bGFuZCIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJNYXJ5bGFuZCIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIk1hc3NhY2h1c2V0dHMiDQogICAgICAgICAgICAsIGdldEFJT19zdGFydF9pZHgobXlERiwgIk1hc3NhY2h1c2V0dHMiKQ0KICAgICAgICAgICAgLCBnZXRBSU9fZW5kX2lkeChteURGLCAiTWFzc2FjaHVzZXR0cyIpDQogICAgICAgICAgICApICU+JQ0KICBwYWNrX3Jvd3MoIk1pY2hpZ2FuIg0KICAgICAgICAgICAgLCBnZXRBSU9fc3RhcnRfaWR4KG15REYsICJNaWNoaWdhbiIpDQogICAgICAgICAgICAsIGdldEFJT19lbmRfaWR4KG15REYsICJNaWNoaWdhbiIpDQogICAgICAgICAgICApICU+JQ0KICBzY3JvbGxfYm94KGhlaWdodCA9ICI0MDBweCIpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gIlRCRCIpDQoNCmBgYA==