-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathhca-standalone.html
649 lines (636 loc) · 188 KB
/
hca-standalone.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
<!DOCTYPE html>
<html>
<head></head>
<body>
<h1>HCA decoder demo</h1>
<i>Standalone version - you may right-click & save this page for offline use.</i><br>
<hr>
<button disabled id="startworkerbtn">start background worker</button><br>
<button disabled id="shutdownbtn">shutdown background worker</button><br>
<hr>
<h3>Choose a HCA file</h3>
Drag & drop a file here,<br>
<form id="localfileform">
Or pick a local file: <input type="file" id="localfile" accept=".hca,application/octet-stream" onchange="buttons.loadfilebtn = this.files.length > 0"><br>
</form>
<b><u>Don't forget to</u></b> <button disabled id="loadfilebtn">load picked file</button><br>
Or download from URL: <input type="text" spellcheck="false" id="urlinput" value="bgm01_anime02_hca.hca"><br>
<button id="downloadbtn">download</button><br>
<hr>
<h3>Set keys for decryption/encryption</h3>
key1=<input type="text" spellcheck="false" id="key1input" value="0x01395C51"><br>
key2=<input type="text" spellcheck="false" id="key2input" value="0x00000000"><br>
<i>Note: output waveform will be nothing but unpleasant meaningless noise if incorrect keys are given!</i><br>
<hr>
<h3>Decode the whole file</h3>
Decoding mode: <input type="number" step="8" min="0" max="32" placeholder="0-99" id="decodingmodeinput" value="16"><br>
Loop count: <input type="number" step="1" min="0" max="99" placeholder="0-99" id="loopcountinput" value="0"><br>
Volume: <input type="number" step="1" min="0" max="100" placeholder="0-100" id="volumeinput" value="100"><br>
Note:<br>
(1) Setting decoding mode to <b>zero means 32-bit float mode</b>, or <b>8/16/24/32-bit integer mode</b> otherwise.<br>
(2) Loop count is <b>ignored if HCA header doesn't have loop section</b><br>
(3) Loop count doesn't count the existing part which is originally supposed to be looped.<br>
<b>In other words, actual loop count will be: the number set here plus one.</b><br>
(4) When <b>decoding the whole file</b>, setting loop count to <b>zero</b> means: <b>disabling loop</b>.</b><br>
<button disabled id="infobtn">get HCA info</button><br>
<style>
table {
border-top: 1px solid #000;
border-left: 1px solid #000;
border-spacing: 0;
}
tbody td {
border-bottom: 1px solid #000;
border-right: 1px solid #000;
min-width: 8ch;
}
thead tr th, tfoot tr th {
background-color: #fff;
color: #000;
border-bottom: 1px solid #000;
border-right: 1px solid #000;
}
</style>
<table id="hcaInfoTable">
<thead>
<tr>
<th colspan="3">HCA info</th>
</tr>
</thead>
<tbody>
<tr>
<td>(Not loaded)</td>
</tr>
</tbody>
</table>
<button disabled id="fixcsumbtn">fix checksum</button><br>
<button disabled id="encryptbtn">encrypt</button><br>
<button disabled id="decryptbtn">decrypt</button><br>
<button disabled id="decodebtn">decode</button><br>
<audio id="audioElement" controls></audio>
<!-- <script src="https://unpkg.com/@ffmpeg/[email protected]/dist/ffmpeg.min.js"></script> -->
<script type="module">
const hcaJsUrl = new URL("data:text/javascript;base64,dmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7CiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH0KICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH0KICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvclsidGhyb3ciXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9CiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH0KICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7CiAgICB9KTsKfTsKdmFyIF9hLCBfYjsKZXhwb3J0IGNsYXNzIEhDQUluZm8gewogICAgY29uc3RydWN0b3IoaGNhLCBjaGFuZ2VNYXNrID0gZmFsc2UsIGVuY3J5cHQgPSBmYWxzZSkgewogICAgICAgIHRoaXMudmVyc2lvbiA9ICIiOwogICAgICAgIHRoaXMuZGF0YU9mZnNldCA9IDA7CiAgICAgICAgdGhpcy5mb3JtYXQgPSB7CiAgICAgICAgICAgIGNoYW5uZWxDb3VudDogMCwKICAgICAgICAgICAgc2FtcGxpbmdSYXRlOiAwLAogICAgICAgICAgICBibG9ja0NvdW50OiAwLAogICAgICAgICAgICBkcm9wcGVkSGVhZGVyOiAwLAogICAgICAgICAgICBkcm9wcGVkRm9vdGVyOiAwCiAgICAgICAgfTsKICAgICAgICB0aGlzLmJsb2NrU2l6ZSA9IDA7CiAgICAgICAgdGhpcy5oYXNIZWFkZXIgPSB7fTsKICAgICAgICB0aGlzLmhlYWRlck9mZnNldCA9IHt9OyAvLyBbc3RhcnQgKGluY2x1c2l2ZSksIGVuZCAoZXhjbHVzaXZlKV0KICAgICAgICB0aGlzLmticHMgPSAwOwogICAgICAgIHRoaXMuY29tcERlYyA9IHsKICAgICAgICAgICAgTWluUmVzb2x1dGlvbjogMCwKICAgICAgICAgICAgTWF4UmVzb2x1dGlvbjogMCwKICAgICAgICAgICAgVHJhY2tDb3VudDogMCwKICAgICAgICAgICAgQ2hhbm5lbENvbmZpZzogMCwKICAgICAgICAgICAgVG90YWxCYW5kQ291bnQ6IDAsCiAgICAgICAgICAgIEJhc2VCYW5kQ291bnQ6IDAsCiAgICAgICAgICAgIFN0ZXJlb0JhbmRDb3VudDogMCwKICAgICAgICAgICAgSGZyQmFuZENvdW50OiAwLAogICAgICAgICAgICBCYW5kc1Blckhmckdyb3VwOiAwLAogICAgICAgICAgICBSZXNlcnZlZDE6IDAsCiAgICAgICAgICAgIFJlc2VydmVkMjogMCwKICAgICAgICB9OwogICAgICAgIHRoaXMuZGVjID0gewogICAgICAgICAgICBEZWNTdGVyZW9UeXBlOiAwLAogICAgICAgIH07CiAgICAgICAgdGhpcy5sb29wID0gewogICAgICAgICAgICBzdGFydDogMCwKICAgICAgICAgICAgZW5kOiAwLAogICAgICAgICAgICAvLyBjb3VudDogMCwgLy8gTnlhZ2Ftb24ncyBpbnRlcnByZXRhdGlvbgogICAgICAgICAgICAvLyByMDE6IDAsCiAgICAgICAgICAgIGRyb3BwZWRIZWFkZXI6IDAsCiAgICAgICAgICAgIGRyb3BwZWRGb290ZXI6IDAsCiAgICAgICAgfTsKICAgICAgICB0aGlzLnZiciA9IHsKICAgICAgICAgICAgTWF4QmxvY2tTaXplOiAwLAogICAgICAgICAgICBOb2lzZUxldmVsOiAwLAogICAgICAgIH07CiAgICAgICAgdGhpcy5Vc2VBdGhDdXJ2ZSA9IGZhbHNlOwogICAgICAgIHRoaXMuY2lwaGVyID0gMDsKICAgICAgICB0aGlzLnJ2YSA9IDAuMDsKICAgICAgICB0aGlzLmNvbW1lbnQgPSAiIjsKICAgICAgICAvLyBjb21wdXRlZCBzYW1wbGUgY291bnQvb2Zmc2V0cwogICAgICAgIHRoaXMuSGZyR3JvdXBDb3VudCA9IDA7CiAgICAgICAgdGhpcy5mdWxsU2FtcGxlQ291bnQgPSAwOwogICAgICAgIHRoaXMuc3RhcnRBdFNhbXBsZSA9IDA7CiAgICAgICAgdGhpcy5mdWxsRW5kQXRTYW1wbGUgPSAwOwogICAgICAgIHRoaXMubG9vcFN0YXJ0QXRTYW1wbGUgPSAwOwogICAgICAgIHRoaXMubG9vcEVuZEF0U2FtcGxlID0gMDsKICAgICAgICB0aGlzLmxvb3BTYW1wbGVDb3VudCA9IDA7CiAgICAgICAgdGhpcy5lbmRBdFNhbXBsZSA9IDA7CiAgICAgICAgdGhpcy5zYW1wbGVDb3VudCA9IDA7CiAgICAgICAgLy8gZnVsbCBmaWxlIHNpemUgLyBkYXRhIHBhcnQgKGV4Y2x1ZGluZyBoZWFkZXIsIGp1c3QgYmxvY2tzL2ZyYW1lcykgc2l6ZQogICAgICAgIHRoaXMuZnVsbFNpemUgPSAwOwogICAgICAgIHRoaXMuZGF0YVNpemUgPSAwOwogICAgICAgIC8vIGlmIGNoYW5nZU1hc2sgPT0gdHJ1ZSwgKHVuKW1hc2sgdGhlIGhlYWRlciBzaWdzIGluLXBsYWNlCiAgICAgICAgdGhpcy5yYXdIZWFkZXIgPSB0aGlzLnBhcnNlSGVhZGVyKGhjYSwgY2hhbmdlTWFzaywgZW5jcnlwdCwge30pOwogICAgfQogICAgc3RhdGljIGdldFNpZ24ocmF3LCBvZmZzZXQgPSAwLCBjaGFuZ2VNYXNrLCBlbmNyeXB0KSB7CiAgICAgICAgbGV0IG1hZ2ljID0gcmF3LmdldFVpbnQzMihvZmZzZXQsIHRydWUpOwogICAgICAgIGxldCBzdHJMZW4gPSA0OwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChyYXcuZ2V0VWludDgob2Zmc2V0ICsgaSkgPT0gMCkgewogICAgICAgICAgICAgICAgc3RyTGVuID0gaTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChzdHJMZW4gPiAwKSB7CiAgICAgICAgICAgIGxldCBtYXNrID0gMHg4MDgwODA4MCA+Pj4gOCAqICg0IC0gc3RyTGVuKTsKICAgICAgICAgICAgbWFnaWMgJj0gMHg3ZjdmN2Y3ZjsKICAgICAgICAgICAgaWYgKGNoYW5nZU1hc2spCiAgICAgICAgICAgICAgICByYXcuc2V0VWludDMyKG9mZnNldCwgZW5jcnlwdCA/IG1hZ2ljIHwgbWFzayA6IG1hZ2ljLCB0cnVlKTsKICAgICAgICB9CiAgICAgICAgbGV0IGhleCA9IFttYWdpYyAmIDB4ZmYsIG1hZ2ljID4+IDggJiAweGZmLCBtYWdpYyA+PiAxNiAmIDB4ZmYsIG1hZ2ljID4+IDI0ICYgMHhmZl07CiAgICAgICAgaGV4ID0gaGV4LnNsaWNlKDAsIHN0ckxlbik7CiAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBoZXgpOwogICAgfQogICAgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBIQ0FJbmZvKHRoaXMucmF3SGVhZGVyKTsKICAgIH0KICAgIHBhcnNlSGVhZGVyKGhjYSwgY2hhbmdlTWFzaywgZW5jcnlwdCwgbW9kTGlzdCkgewogICAgICAgIGxldCBwID0gbmV3IERhdGFWaWV3KGhjYS5idWZmZXIsIGhjYS5ieXRlT2Zmc2V0LCA4KTsKICAgICAgICBsZXQgaGVhZCA9IEhDQUluZm8uZ2V0U2lnbihwLCAwLCBmYWxzZSwgZW5jcnlwdCk7IC8vIGRvIG5vdCBvdmVyd3JpdGUgZm9yIG5vdywgdW50aWwgY2hlY2tzdW0gdmVyaWZpZWQKICAgICAgICBpZiAoaGVhZCAhPT0gIkhDQSIpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJOb3QgYSBIQ0EgZmlsZSIpOwogICAgICAgIH0KICAgICAgICBjb25zdCB2ZXJzaW9uID0gewogICAgICAgICAgICBtYWluOiBwLmdldFVpbnQ4KDQpLAogICAgICAgICAgICBzdWI6IHAuZ2V0VWludDgoNSkKICAgICAgICB9OwogICAgICAgIHRoaXMudmVyc2lvbiA9IHZlcnNpb24ubWFpbiArICcuJyArIHZlcnNpb24uc3ViOwogICAgICAgIHRoaXMuZGF0YU9mZnNldCA9IHAuZ2V0VWludDE2KDYpOwogICAgICAgIC8vIHZlcmlmeSBjaGVja3N1bQogICAgICAgIEhDQUNyYzE2LnZlcmlmeShoY2EsIHRoaXMuZGF0YU9mZnNldCAtIDIpOwogICAgICAgIGxldCBoYXNNb2REb25lID0gZmFsc2U7CiAgICAgICAgLy8gY2hlY2tzdW0gdmVyaWZpZWQsIG5vdyB3ZSBjYW4gb3ZlcndyaXRlIGl0CiAgICAgICAgaWYgKGNoYW5nZU1hc2spCiAgICAgICAgICAgIEhDQUluZm8uZ2V0U2lnbihwLCAwLCBjaGFuZ2VNYXNrLCBlbmNyeXB0KTsKICAgICAgICAvLyBwYXJzZSB0aGUgaGVhZGVyCiAgICAgICAgcCA9IG5ldyBEYXRhVmlldyhoY2EuYnVmZmVyLCBoY2EuYnl0ZU9mZnNldCwgdGhpcy5kYXRhT2Zmc2V0KTsKICAgICAgICBsZXQgZnRlbGwgPSA4OwogICAgICAgIHdoaWxlIChmdGVsbCA8IHRoaXMuZGF0YU9mZnNldCAtIDIpIHsKICAgICAgICAgICAgbGV0IGxhc3RGdGVsbCA9IGZ0ZWxsOwogICAgICAgICAgICAvLyBnZXQgdGhlIHNpZwogICAgICAgICAgICBsZXQgc2lnbiA9IEhDQUluZm8uZ2V0U2lnbihwLCBmdGVsbCwgY2hhbmdlTWFzaywgZW5jcnlwdCk7CiAgICAgICAgICAgIC8vIHJlY29yZCBoYXNIZWFkZXIKICAgICAgICAgICAgdGhpcy5oYXNIZWFkZXJbc2lnbl0gPSB0cnVlOwogICAgICAgICAgICAvLyBwYWRkaW5nIHNob3VsZCBiZSB0aGUgbGFzdCBvbmUKICAgICAgICAgICAgaWYgKHNpZ24gPT0gInBhZCIpIHsKICAgICAgICAgICAgICAgIHRoaXMuaGVhZGVyT2Zmc2V0W3NpZ25dID0gW2Z0ZWxsLCB0aGlzLmRhdGFPZmZzZXQgLSAyXTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIHBhcnNlIGRhdGEgYWNjb3JkaW5nbHkKICAgICAgICAgICAgc3dpdGNoIChzaWduKSB7CiAgICAgICAgICAgICAgICBjYXNlICJmbXQiOgogICAgICAgICAgICAgICAgICAgIHRoaXMuZm9ybWF0LmNoYW5uZWxDb3VudCA9IHAuZ2V0VWludDgoZnRlbGwgKyA0KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm1hdC5zYW1wbGluZ1JhdGUgPSBwLmdldFVpbnQzMihmdGVsbCArIDQpICYgMHgwMGZmZmZmZjsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm1hdC5ibG9ja0NvdW50ID0gcC5nZXRVaW50MzIoZnRlbGwgKyA4KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm1hdC5kcm9wcGVkSGVhZGVyID0gcC5nZXRVaW50MTYoZnRlbGwgKyAxMik7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtYXQuZHJvcHBlZEZvb3RlciA9IHAuZ2V0VWludDE2KGZ0ZWxsICsgMTQpOwogICAgICAgICAgICAgICAgICAgIGZ0ZWxsICs9IDE2OwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiY29tcCI6CiAgICAgICAgICAgICAgICAgICAgdGhpcy5ibG9ja1NpemUgPSBwLmdldFVpbnQxNihmdGVsbCArIDQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMua2JwcyA9IHRoaXMuZm9ybWF0LnNhbXBsaW5nUmF0ZSAqIHRoaXMuYmxvY2tTaXplIC8gMTI4MDAwLjA7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLk1pblJlc29sdXRpb24gPSBwLmdldFVpbnQ4KGZ0ZWxsICsgNik7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLk1heFJlc29sdXRpb24gPSBwLmdldFVpbnQ4KGZ0ZWxsICsgNyk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLlRyYWNrQ291bnQgPSBwLmdldFVpbnQ4KGZ0ZWxsICsgOCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLkNoYW5uZWxDb25maWcgPSBwLmdldFVpbnQ4KGZ0ZWxsICsgOSk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLlRvdGFsQmFuZENvdW50ID0gcC5nZXRVaW50OChmdGVsbCArIDEwKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuQmFzZUJhbmRDb3VudCA9IHAuZ2V0VWludDgoZnRlbGwgKyAxMSk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLlN0ZXJlb0JhbmRDb3VudCA9IHAuZ2V0VWludDgoZnRlbGwgKyAxMik7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLkJhbmRzUGVySGZyR3JvdXAgPSBwLmdldFVpbnQ4KGZ0ZWxsICsgMTMpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcERlYy5SZXNlcnZlZDEgPSBwLmdldFVpbnQ4KGZ0ZWxsICsgMTQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcERlYy5SZXNlcnZlZDIgPSBwLmdldFVpbnQ4KGZ0ZWxsICsgMTUpOwogICAgICAgICAgICAgICAgICAgIGZ0ZWxsICs9IDE2OwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiZGVjIjoKICAgICAgICAgICAgICAgICAgICB0aGlzLmJsb2NrU2l6ZSA9IHAuZ2V0VWludDE2KGZ0ZWxsICsgNCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5rYnBzID0gdGhpcy5mb3JtYXQuc2FtcGxpbmdSYXRlICogdGhpcy5ibG9ja1NpemUgLyAxMjgwMDAuMDsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuTWluUmVzb2x1dGlvbiA9IHAuZ2V0VWludDgoZnRlbGwgKyA2KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuTWF4UmVzb2x1dGlvbiA9IHAuZ2V0VWludDgoZnRlbGwgKyA3KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuVG90YWxCYW5kQ291bnQgPSBwLmdldFVpbnQ4KGZ0ZWxsICsgOCk7CiAgICAgICAgICAgICAgICAgICAgKzE7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLkJhc2VCYW5kQ291bnQgPSBwLmdldFVpbnQ4KGZ0ZWxsICsgOSk7CiAgICAgICAgICAgICAgICAgICAgKzE7CiAgICAgICAgICAgICAgICAgICAgbGV0IGEgPSBwLmdldFVpbnQ4KGZ0ZWxsICsgMTApOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcERlYy5UcmFja0NvdW50ID0gSENBVXRpbEZ1bmMuR2V0SGlnaE5pYmJsZShhKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuQ2hhbm5lbENvbmZpZyA9IEhDQVV0aWxGdW5jLkdldExvd05pYmJsZShhKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmRlYy5EZWNTdGVyZW9UeXBlID0gcC5nZXRVaW50OChmdGVsbCArIDExKTsKICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kZWMuRGVjU3RlcmVvVHlwZSA9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcERlYy5CYXNlQmFuZENvdW50ID0gdGhpcy5jb21wRGVjLlRvdGFsQmFuZENvdW50OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLlN0ZXJlb0JhbmRDb3VudCA9IHRoaXMuY29tcERlYy5Ub3RhbEJhbmRDb3VudCAtIHRoaXMuY29tcERlYy5CYXNlQmFuZENvdW50OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmdGVsbCArPSAxMjsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgInZiciI6CiAgICAgICAgICAgICAgICAgICAgZnRlbGwgKz0gODsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgImF0aCI6CiAgICAgICAgICAgICAgICAgICAgdGhpcy5Vc2VBdGhDdXJ2ZSA9IHAuZ2V0VWludDE2KGZ0ZWxsICsgNCkgPT0gMTsKICAgICAgICAgICAgICAgICAgICBmdGVsbCArPSA2OwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAibG9vcCI6CiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb29wLnN0YXJ0ID0gcC5nZXRVaW50MzIoZnRlbGwgKyA0KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmxvb3AuZW5kID0gcC5nZXRVaW50MzIoZnRlbGwgKyA4KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmxvb3AuZHJvcHBlZEhlYWRlciA9IHAuZ2V0VWludDE2KGZ0ZWxsICsgMTIpOwogICAgICAgICAgICAgICAgICAgIHRoaXMubG9vcC5kcm9wcGVkRm9vdGVyID0gcC5nZXRVaW50MTYoZnRlbGwgKyAxNCk7CiAgICAgICAgICAgICAgICAgICAgZnRlbGwgKz0gMTY7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJjaXBoIjoKICAgICAgICAgICAgICAgICAgICB0aGlzLmNpcGhlciA9IHAuZ2V0VWludDE2KGZ0ZWxsICsgNCk7CiAgICAgICAgICAgICAgICAgICAgZnRlbGwgKz0gNjsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgInJ2YSI6CiAgICAgICAgICAgICAgICAgICAgdGhpcy5ydmEgPSBwLmdldEZsb2F0MzIoZnRlbGwgKyA0KTsKICAgICAgICAgICAgICAgICAgICBmdGVsbCArPSA4OwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAidmJyIjoKICAgICAgICAgICAgICAgICAgICB0aGlzLnZici5NYXhCbG9ja1NpemUgPSBwLmdldFVpbnQxNihmdGVsbCArIDQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMudmJyLk5vaXNlTGV2ZWwgPSBwLmdldEludDE2KGZ0ZWxsICsgNik7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJjb21tIjoKICAgICAgICAgICAgICAgICAgICBsZXQgbGVuID0gcC5nZXRVaW50OChmdGVsbCArIDQpOwogICAgICAgICAgICAgICAgICAgIGxldCBqaXNkZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCdzaGlmdC1qaXMnKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbW1lbnQgPSBqaXNkZWNvZGVyLmRlY29kZShoY2Euc2xpY2UoZnRlbGwgKyA1LCBmdGVsbCArIDUgKyBsZW4pKTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHRocm93IG5ldyBFcnJvcigidW5rbm93biBoZWFkZXIgc2lnIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gcmVjb3JkIGhlYWRlck9mZnNldAogICAgICAgICAgICB0aGlzLmhlYWRlck9mZnNldFtzaWduXSA9IFtsYXN0RnRlbGwsIGZ0ZWxsXTsKICAgICAgICAgICAgLy8gZG8gbW9kaWZpY2F0aW9uIGlmIG5lZWRlZAogICAgICAgICAgICBsZXQgc2VjdGlvbkRhdGFMZW4gPSBmdGVsbCAtIGxhc3RGdGVsbCAtIDQ7CiAgICAgICAgICAgIGxldCBuZXdEYXRhID0gbW9kTGlzdFtzaWduXTsKICAgICAgICAgICAgaWYgKG5ld0RhdGEgIT0gbnVsbCkgewogICAgICAgICAgICAgICAgaWYgKG5ld0RhdGEuYnl0ZUxlbmd0aCA+IHNlY3Rpb25EYXRhTGVuKQogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgICAgICAgICAgaGNhLnNldChuZXdEYXRhLCBsYXN0RnRlbGwgKyA0KTsKICAgICAgICAgICAgICAgIGhhc01vZERvbmUgPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qCiAgICAgICAgLy8gKHBvcnRlZCBmcm9tKSBOeWFnYW1vbidzIG9yaWdpbmFsIGNvZGUsIHNob3VsZCBiZSAoYWxtb3N0KSBlcXVpdmFsZW50IHRvIENhbGN1bGF0ZUhmclZhbHVlcwogICAgICAgIHRoaXMuY29tcFBhcmFtWzJdID0gdGhpcy5jb21wUGFyYW1bMl0gfHwgMTsKICAgICAgICBsZXQgX2EgPSB0aGlzLmNvbXBQYXJhbVs0XSAtIHRoaXMuY29tcFBhcmFtWzVdIC0gdGhpcy5jb21wUGFyYW1bNl07CiAgICAgICAgbGV0IF9iID0gdGhpcy5jb21wUGFyYW1bN107CiAgICAgICAgdGhpcy5jb21wRGVjLlJlc2VydmVkMSA9IF9iID4gMCA/IF9hIC8gX2IgKyAoX2EgJSBfYiA/IDEgOiAwKSA6IDA7CiAgICAgICAgLy8gVHJhbnNsYXRpbmcgdGhlIGFib3ZlIGNvZGUgd2l0aCBtZWFuaW5nZnVsIHZhcmlhYmxlIG5hbWVzOgogICAgICAgIHRoaXMuY29tcERlYy5UcmFja0NvdW50ID0gdGhpcy5jb21wRGVjLlRyYWNrQ291bnQgfHwgMTsKICAgICAgICB0aGlzLmNvbXBEZWMuSGZyQmFuZENvdW50ID0gdGhpcy5jb21wRGVjLlRvdGFsQmFuZENvdW50IC0gdGhpcy5jb21wRGVjLkJhc2VCYW5kQ291bnQgLSB0aGlzLmNvbXBEZWMuU3RlcmVvQmFuZENvdW50OwogICAgICAgIHRoaXMuSGZyR3JvdXBDb3VudCA9IHRoaXMuY29tcERlYy5CYW5kc1Blckhmckdyb3VwOwogICAgICAgIHRoaXMuY29tcERlYy5SZXNlcnZlZDEgPSB0aGlzLkhmckdyb3VwQ291bnQgPiAwID8gdGhpcy5jb21wRGVjLkhmckJhbmRDb3VudCAvIHRoaXMuSGZyR3JvdXBDb3VudCArICh0aGlzLmNvbXBEZWMuSGZyQmFuZENvdW50ICUgdGhpcy5IZnJHcm91cENvdW50ID8gMSA6IDApIDogMDsKICAgICAgICAqLwogICAgICAgIC8vIENhbGN1bGF0ZUhmclZhbHVlcywgcG9ydGVkIGZyb20gVkdBdWRpbwogICAgICAgIGlmICh0aGlzLmNvbXBEZWMuQmFuZHNQZXJIZnJHcm91cCA+IDApIHsKICAgICAgICAgICAgdGhpcy5jb21wRGVjLkhmckJhbmRDb3VudCA9IHRoaXMuY29tcERlYy5Ub3RhbEJhbmRDb3VudCAtIHRoaXMuY29tcERlYy5CYXNlQmFuZENvdW50IC0gdGhpcy5jb21wRGVjLlN0ZXJlb0JhbmRDb3VudDsKICAgICAgICAgICAgdGhpcy5IZnJHcm91cENvdW50ID0gSENBVXRpbEZ1bmMuRGl2aWRlQnlSb3VuZFVwKHRoaXMuY29tcERlYy5IZnJCYW5kQ291bnQsIHRoaXMuY29tcERlYy5CYW5kc1Blckhmckdyb3VwKTsKICAgICAgICB9CiAgICAgICAgLy8gY2FsY3VsYXRlIHNhbXBsZSBjb3VudC9vZmZzZXRzCiAgICAgICAgdGhpcy5mdWxsU2FtcGxlQ291bnQgPSB0aGlzLmZvcm1hdC5ibG9ja0NvdW50ICogSENBRnJhbWUuU2FtcGxlc1BlckZyYW1lOwogICAgICAgIHRoaXMuc3RhcnRBdFNhbXBsZSA9IHRoaXMuZm9ybWF0LmRyb3BwZWRIZWFkZXI7CiAgICAgICAgdGhpcy5mdWxsRW5kQXRTYW1wbGUgPSB0aGlzLmZ1bGxTYW1wbGVDb3VudCAtIHRoaXMuZm9ybWF0LmRyb3BwZWRGb290ZXI7CiAgICAgICAgaWYgKHRoaXMuaGFzSGVhZGVyWyJsb29wIl0pIHsKICAgICAgICAgICAgdGhpcy5sb29wU3RhcnRBdFNhbXBsZSA9IHRoaXMubG9vcC5zdGFydCAqIEhDQUZyYW1lLlNhbXBsZXNQZXJGcmFtZSArIHRoaXMubG9vcC5kcm9wcGVkSGVhZGVyOwogICAgICAgICAgICB0aGlzLmxvb3BFbmRBdFNhbXBsZSA9ICh0aGlzLmxvb3AuZW5kICsgMSkgKiBIQ0FGcmFtZS5TYW1wbGVzUGVyRnJhbWUgLSB0aGlzLmxvb3AuZHJvcHBlZEZvb3RlcjsKICAgICAgICAgICAgdGhpcy5sb29wU2FtcGxlQ291bnQgPSB0aGlzLmxvb3BFbmRBdFNhbXBsZSAtIHRoaXMubG9vcFN0YXJ0QXRTYW1wbGU7CiAgICAgICAgfQogICAgICAgIHRoaXMuZW5kQXRTYW1wbGUgPSB0aGlzLmhhc0hlYWRlclsibG9vcCJdID8gdGhpcy5sb29wRW5kQXRTYW1wbGUgOiB0aGlzLmZ1bGxFbmRBdFNhbXBsZTsKICAgICAgICB0aGlzLnNhbXBsZUNvdW50ID0gdGhpcy5lbmRBdFNhbXBsZSAtIHRoaXMuc3RhcnRBdFNhbXBsZTsKICAgICAgICAvLyBjYWxjdWxhdGUgZmlsZS9kYXRhIHNpemUKICAgICAgICB0aGlzLmRhdGFTaXplID0gdGhpcy5ibG9ja1NpemUgKiB0aGlzLmZvcm1hdC5ibG9ja0NvdW50OwogICAgICAgIHRoaXMuZnVsbFNpemUgPSB0aGlzLmRhdGFPZmZzZXQgKyB0aGlzLmRhdGFTaXplOwogICAgICAgIGlmIChjaGFuZ2VNYXNrIHx8IGhhc01vZERvbmUpIHsKICAgICAgICAgICAgLy8gZml4IGNoZWNrc3VtIGlmIHJlcXVlc3RlZAogICAgICAgICAgICBIQ0FDcmMxNi5maXgoaGNhLCB0aGlzLmRhdGFPZmZzZXQgLSAyKTsKICAgICAgICB9CiAgICAgICAgbGV0IHJhd0hlYWRlciA9IGhjYS5zbGljZSgwLCB0aGlzLmRhdGFPZmZzZXQpOwogICAgICAgIC8vIGNoZWNrIHZhbGlkaXR5IG9mIHBhcnNlZCB2YWx1ZXMKICAgICAgICB0aGlzLmNoZWNrVmFsaWRpdHkoKTsKICAgICAgICByZXR1cm4gcmF3SGVhZGVyOwogICAgfQogICAgY2hlY2tWYWxpZGl0eSgpIHsKICAgICAgICBjb25zdCByZXN1bHRzID0gWwogICAgICAgICAgICB0aGlzLmJsb2NrU2l6ZSA+IDAsCiAgICAgICAgICAgIDAgPCB0aGlzLmZvcm1hdC5ibG9ja0NvdW50LAogICAgICAgICAgICAwIDw9IHRoaXMuc3RhcnRBdFNhbXBsZSwKICAgICAgICAgICAgdGhpcy5zdGFydEF0U2FtcGxlIDwgdGhpcy5mdWxsRW5kQXRTYW1wbGUsCiAgICAgICAgICAgIHRoaXMuZnVsbEVuZEF0U2FtcGxlIDw9IHRoaXMuZnVsbFNhbXBsZUNvdW50LAogICAgICAgIF07CiAgICAgICAgcmVzdWx0cy5maW5kKChyZXN1bHQsIGluZGV4KSA9PiB7CiAgICAgICAgICAgIGlmICghcmVzdWx0KSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGRpZCBub3QgcGFzcyBub3JtYWwgY2hlY2sgb24gcnVsZSAke2luZGV4fWApOwogICAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgICAgaWYgKHRoaXMuaGFzSGVhZGVyWyJsb29wIl0pIHsKICAgICAgICAgICAgY29uc3QgbG9vcENoZWNrcyA9IFsKICAgICAgICAgICAgICAgIHRoaXMuc3RhcnRBdFNhbXBsZSA8PSB0aGlzLmxvb3BTdGFydEF0U2FtcGxlLAogICAgICAgICAgICAgICAgdGhpcy5sb29wU3RhcnRBdFNhbXBsZSA8IHRoaXMubG9vcEVuZEF0U2FtcGxlLAogICAgICAgICAgICAgICAgdGhpcy5sb29wRW5kQXRTYW1wbGUgPD0gdGhpcy5mdWxsRW5kQXRTYW1wbGUsCiAgICAgICAgICAgIF07CiAgICAgICAgICAgIGxvb3BDaGVja3MuZmluZCgocmVzdWx0LCBpbmRleCkgPT4gewogICAgICAgICAgICAgICAgaWYgKCFyZXN1bHQpIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGRpZCBub3QgcGFzcyBsb29wIGNoZWNrIG9uIHJ1bGUgJHtpbmRleH1gKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgfQogICAgZ2V0UmF3SGVhZGVyKCkgewogICAgICAgIHJldHVybiB0aGlzLnJhd0hlYWRlci5zbGljZSgwKTsKICAgIH0KICAgIGlzSGVhZGVyQ2hhbmdlZChoY2EpIHsKICAgICAgICBpZiAoaGNhLmxlbmd0aCA+PSB0aGlzLnJhd0hlYWRlci5sZW5ndGgpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnJhd0hlYWRlci5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgaWYgKGhjYVtpXSAhPSB0aGlzLnJhd0hlYWRlcltpXSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgbW9kaWZ5KGhjYSwgc2lnLCBuZXdEYXRhKSB7CiAgICAgICAgLy8gcmVwYXJzZSBoZWFkZXIgaWYgbmVlZGVkCiAgICAgICAgaWYgKHRoaXMuaXNIZWFkZXJDaGFuZ2VkKGhjYSkpIHsKICAgICAgICAgICAgdGhpcy5wYXJzZUhlYWRlcihoY2EsIGZhbHNlLCBmYWxzZSwge30pOwogICAgICAgIH0KICAgICAgICAvLyBwcmVwYXJlIHRvIG1vZGlmeSBkYXRhIGluLXBsYWNlCiAgICAgICAgbGV0IG1vZExpc3QgPSB7fTsKICAgICAgICBtb2RMaXN0W3NpZ10gPSBuZXdEYXRhOwogICAgICAgIGxldCBlbmNyeXB0ID0gdGhpcy5jaXBoZXIgIT0gMDsKICAgICAgICBpZiAoc2lnID09PSAiY2lwaCIpIHsKICAgICAgICAgICAgZW5jcnlwdCA9IG5ldyBEYXRhVmlldyhuZXdEYXRhLmJ1ZmZlciwgbmV3RGF0YS5ieXRlT2Zmc2V0LCBuZXdEYXRhLmJ5dGVMZW5ndGgpLmdldFVpbnQxNigwKSAhPSAwOwogICAgICAgIH0KICAgICAgICAvLyBkbyBhY3R1YWwgbW9kaWZpY2F0aW9uICYgY2hlY2sgdmFsaWRpdHkKICAgICAgICB0aGlzLnJhd0hlYWRlciA9IHRoaXMucGFyc2VIZWFkZXIoaGNhLCB0cnVlLCBlbmNyeXB0LCBtb2RMaXN0KTsKICAgIH0KICAgIHN0YXRpYyBhZGRIZWFkZXIoaGNhLCBzaWcsIG5ld0RhdGEpIHsKICAgICAgICAvLyBzaWcgbXVzdCBjb25zaXN0IG9mIDEtNCBBU0NJSSBjaGFyYWN0ZXJzCiAgICAgICAgaWYgKHNpZy5sZW5ndGggPCAxIHx8IHNpZy5sZW5ndGggPiA0KQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICBsZXQgbmV3U2lnID0gbmV3IFVpbnQ4QXJyYXkoNCk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA0OyBpKyspIHsKICAgICAgICAgICAgbGV0IGMgPSBzaWcuY2hhckNvZGVBdChpKTsKICAgICAgICAgICAgaWYgKGMgPj0gMHg4MCkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgICAgICBuZXdTaWdbaV0gPSBjOwogICAgICAgIH0KICAgICAgICAvLyBwYXJzZSBoZWFkZXIgJiBjaGVjayB2YWxpZHR5CiAgICAgICAgbGV0IGluZm8gPSBuZXcgSENBSW5mbyhoY2EpOwogICAgICAgIC8vIGNoZWNrIHdoZXRoZXIgc3BlY2lmaWVkIGhlYWRlciBzZWN0aW9uIGFscmVhZHkgZXhpc3RzCiAgICAgICAgaWYgKGluZm8uaGFzSGVhZGVyW3NpZ10pCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgaGVhZGVyIHNlY3Rpb24gJHtzaWd9IGFscmVhZHkgZXhpc3RzYCk7CiAgICAgICAgLy8gcHJlcGFyZSBhIG5ld2x5IGFsbG9jYXRlZCBidWZmZXIKICAgICAgICBsZXQgbmV3SGNhID0gbmV3IFVpbnQ4QXJyYXkoaGNhLmJ5dGVMZW5ndGggKyBuZXdTaWcuYnl0ZUxlbmd0aCArIG5ld0RhdGEuYnl0ZUxlbmd0aCk7CiAgICAgICAgbGV0IGluc2VydE9mZnNldCA9IGluZm8uaGVhZGVyT2Zmc2V0WyJwYWQiXVswXTsKICAgICAgICAvLyBjb3B5IGV4aXN0aW5nIGhlYWRlcnMgKGV4Y2VwdCBwYWRkaW5nKQogICAgICAgIG5ld0hjYS5zZXQoaGNhLnN1YmFycmF5KDAsIGluc2VydE9mZnNldCksIDApOwogICAgICAgIC8vIGNvcHkgaW5zZXJ0ZWQgaGVhZGVyCiAgICAgICAgbmV3SGNhLnNldChuZXdTaWcsIGluc2VydE9mZnNldCk7CiAgICAgICAgbmV3SGNhLnNldChuZXdEYXRhLCBpbnNlcnRPZmZzZXQgKyBuZXdTaWcuYnl0ZUxlbmd0aCk7CiAgICAgICAgLy8gY29weSByZW1haW5pbmcgZGF0YSAocGFkZGluZyBhbmQgYmxvY2tzKQogICAgICAgIG5ld0hjYS5zZXQoaGNhLnN1YmFycmF5KGluc2VydE9mZnNldCwgaGNhLmJ5dGVMZW5ndGgpLCBpbnNlcnRPZmZzZXQgKyBuZXdTaWcuYnl0ZUxlbmd0aCArIG5ld0RhdGEuYnl0ZUxlbmd0aCk7CiAgICAgICAgLy8gdXBkYXRlIGRhdGFPZmZzZXQKICAgICAgICBpbmZvLmRhdGFPZmZzZXQgKz0gbmV3U2lnLmJ5dGVMZW5ndGggKyBuZXdEYXRhLmJ5dGVMZW5ndGg7CiAgICAgICAgbGV0IHAgPSBuZXcgRGF0YVZpZXcobmV3SGNhLmJ1ZmZlciwgbmV3SGNhLmJ5dGVPZmZzZXQsIG5ld0hjYS5ieXRlTGVuZ3RoKTsKICAgICAgICBwLnNldEludDE2KDYsIGluZm8uZGF0YU9mZnNldCk7CiAgICAgICAgLy8gZml4IGNoZWNrc3VtCiAgICAgICAgSENBQ3JjMTYuZml4KG5ld0hjYSwgaW5mby5kYXRhT2Zmc2V0IC0gMik7CiAgICAgICAgLy8gcmVwYXJzZSBoZWFkZXIgJiByZWNoZWNrIHZhbGlkdHkKICAgICAgICBpbmZvID0gbmV3IEhDQUluZm8obmV3SGNhKTsKICAgICAgICByZXR1cm4gbmV3SGNhOwogICAgfQogICAgc3RhdGljIGFkZENpcGhlckhlYWRlcihoY2EsIGNpcGhlclR5cGUpIHsKICAgICAgICBsZXQgbmV3RGF0YSA9IG5ldyBVaW50OEFycmF5KDIpOwogICAgICAgIGlmIChjaXBoZXJUeXBlICE9IG51bGwpCiAgICAgICAgICAgIG5ldyBEYXRhVmlldyhuZXdEYXRhLmJ1ZmZlcikuc2V0VWludDE2KDAsIGNpcGhlclR5cGUpOwogICAgICAgIHJldHVybiB0aGlzLmFkZEhlYWRlcihoY2EsICJjaXBoIiwgbmV3RGF0YSk7CiAgICB9CiAgICBzdGF0aWMgZml4SGVhZGVyQ2hlY2tzdW0oaGNhKSB7CiAgICAgICAgbGV0IHAgPSBuZXcgRGF0YVZpZXcoaGNhLmJ1ZmZlciwgaGNhLmJ5dGVPZmZzZXQsIDgpOwogICAgICAgIGxldCBoZWFkID0gdGhpcy5nZXRTaWduKHAsIDAsIGZhbHNlLCBmYWxzZSk7CiAgICAgICAgaWYgKGhlYWQgIT09ICJIQ0EiKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiTm90IGEgSENBIGZpbGUiKTsKICAgICAgICB9CiAgICAgICAgbGV0IGRhdGFPZmZzZXQgPSBwLmdldFVpbnQxNig2KTsKICAgICAgICBIQ0FDcmMxNi5maXgoaGNhLCBkYXRhT2Zmc2V0IC0gMik7CiAgICAgICAgcmV0dXJuIGhjYTsKICAgIH0KICAgIGNhbGNJbldhdlNpemUobW9kZSA9IDMyKSB7CiAgICAgICAgc3dpdGNoIChtb2RlKSB7CiAgICAgICAgICAgIGNhc2UgMDogLy8gZmxvYXQKICAgICAgICAgICAgY2FzZSA4OgogICAgICAgICAgICBjYXNlIDE2OgogICAgICAgICAgICBjYXNlIDI0OgogICAgICAgICAgICBjYXNlIDMyOiAvLyBpbnRlZ2VyCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIG1vZGUgPSAzMjsKICAgICAgICB9CiAgICAgICAgbGV0IGJpdHNQZXJTYW1wbGUgPSBtb2RlID09IDAgPyAzMiA6IG1vZGU7CiAgICAgICAgbGV0IHNhbXBsZVNpemVJbldhdiA9IHRoaXMuZm9ybWF0LmNoYW5uZWxDb3VudCAqIGJpdHNQZXJTYW1wbGUgLyA4OwogICAgICAgIHJldHVybiB0aGlzLmluV2F2U2l6ZSA9IHsKICAgICAgICAgICAgYml0c1BlclNhbXBsZTogYml0c1BlclNhbXBsZSwKICAgICAgICAgICAgc2FtcGxlOiBzYW1wbGVTaXplSW5XYXYsCiAgICAgICAgICAgIGJsb2NrOiBIQ0FGcmFtZS5TYW1wbGVzUGVyRnJhbWUgKiBzYW1wbGVTaXplSW5XYXYsCiAgICAgICAgICAgIGRyb3BwZWQ6IHsKICAgICAgICAgICAgICAgIGhlYWRlcjogdGhpcy5mb3JtYXQuZHJvcHBlZEhlYWRlciAqIHNhbXBsZVNpemVJbldhdiwKICAgICAgICAgICAgICAgIGZvb3RlcjogdGhpcy5mb3JtYXQuZHJvcHBlZEZvb3RlciAqIHNhbXBsZVNpemVJbldhdiwKICAgICAgICAgICAgfSwKICAgICAgICAgICAgbG9vcDogdGhpcy5oYXNIZWFkZXJbImxvb3AiXSA/IHsKICAgICAgICAgICAgICAgIGxvb3BQYXJ0OiAodGhpcy5sb29wRW5kQXRTYW1wbGUgLSB0aGlzLmxvb3BTdGFydEF0U2FtcGxlKSAqIHNhbXBsZVNpemVJbldhdiwKICAgICAgICAgICAgICAgIGRyb3BwZWQ6IHsKICAgICAgICAgICAgICAgICAgICBoZWFkZXI6IHRoaXMubG9vcC5kcm9wcGVkSGVhZGVyICogc2FtcGxlU2l6ZUluV2F2LAogICAgICAgICAgICAgICAgICAgIGZvb3RlcjogdGhpcy5sb29wLmRyb3BwZWRGb290ZXIgKiBzYW1wbGVTaXplSW5XYXYsCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gOiB1bmRlZmluZWQsCiAgICAgICAgfTsKICAgIH0KfQpjbGFzcyBIQ0FVdGlsRnVuYyB7CiAgICBzdGF0aWMgRGl2aWRlQnlSb3VuZFVwKHZhbHVlLCBkaXZpc29yKSB7CiAgICAgICAgcmV0dXJuIE1hdGguY2VpbCh2YWx1ZSAvIGRpdmlzb3IpOwogICAgfQogICAgc3RhdGljIEdldEhpZ2hOaWJibGUodmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPiAweGZmKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICBpZiAodmFsdWUgPCAtMHg4MCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgcmV0dXJuICh2YWx1ZSA+Pj4gNCkgJiAweEY7CiAgICB9CiAgICBzdGF0aWMgR2V0TG93TmliYmxlKHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID4gMHhmZikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgaWYgKHZhbHVlIDwgLTB4ODApCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIHJldHVybiB2YWx1ZSAmIDB4RjsKICAgIH0KICAgIHN0YXRpYyBHZXRIaWdoTmliYmxlU2lnbmVkKHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID4gMHhmZikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgaWYgKHZhbHVlIDwgLTB4ODApCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIHJldHVybiB0aGlzLlNpZ25lZE5pYmJsZXNbKHZhbHVlID4+PiA0KSAmIDB4Rl07CiAgICB9CiAgICBzdGF0aWMgR2V0TG93TmliYmxlU2lnbmVkKHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID4gMHhmZikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgaWYgKHZhbHVlIDwgLTB4ODApCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIHJldHVybiB0aGlzLlNpZ25lZE5pYmJsZXNbdmFsdWUgJiAweEZdOwogICAgfQogICAgc3RhdGljIENvbWJpbmVOaWJibGVzKGhpZ2gsIGxvdykgewogICAgICAgIHJldHVybiAoKGhpZ2ggPDwgNCkgfCAobG93ICYgMHhGKSkgJiAweEZGOwogICAgfQogICAgc3RhdGljIEdldE5leHRNdWx0aXBsZSh2YWx1ZSwgbXVsdGlwbGUpIHsKICAgICAgICBpZiAobXVsdGlwbGUgPD0gMCkKICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgIGlmICh2YWx1ZSAlIG11bHRpcGxlID09IDApCiAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICByZXR1cm4gdmFsdWUgKyBtdWx0aXBsZSAtIHZhbHVlICUgbXVsdGlwbGU7CiAgICB9CiAgICBzdGF0aWMgU2lnbmVkQml0UmV2ZXJzZTMyKHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID4gMHhmZmZmZmZmZikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgaWYgKHZhbHVlIDwgLTB4ODAwMDAwMDApCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIHZhbHVlID0gKCh2YWx1ZSAmIDB4YWFhYWFhYWEpID4+PiAxKSB8ICgodmFsdWUgJiAweDU1NTU1NTU1KSA8PCAxKTsKICAgICAgICB2YWx1ZSA9ICgodmFsdWUgJiAweGNjY2NjY2NjKSA+Pj4gMikgfCAoKHZhbHVlICYgMHgzMzMzMzMzMykgPDwgMik7CiAgICAgICAgdmFsdWUgPSAoKHZhbHVlICYgMHhmMGYwZjBmMCkgPj4+IDQpIHwgKCh2YWx1ZSAmIDB4MGYwZjBmMGYpIDw8IDQpOwogICAgICAgIHZhbHVlID0gKCh2YWx1ZSAmIDB4ZmYwMGZmMDApID4+PiA4KSB8ICgodmFsdWUgJiAweDAwZmYwMGZmKSA8PCA4KTsKICAgICAgICByZXR1cm4gKCh2YWx1ZSAmIDB4ZmZmZjAwMDApID4+PiAxNikgfCAoKHZhbHVlICYgMHgwMDAwZmZmZikgPDwgMTYpOwogICAgfQogICAgc3RhdGljIFVuc2lnbmVkQml0UmV2ZXJzZTMyKHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuU2lnbmVkQml0UmV2ZXJzZTMyKHZhbHVlKSA+Pj4gMDsKICAgIH0KICAgIHN0YXRpYyBVbnNpZ25lZEJpdFJldmVyc2UzMlRydW5jKHZhbHVlLCBiaXRDb3VudCkgewogICAgICAgIHJldHVybiB0aGlzLlVuc2lnbmVkQml0UmV2ZXJzZTMyKHZhbHVlKSA+Pj4gKDMyIC0gYml0Q291bnQpOwogICAgfQogICAgc3RhdGljIFNpZ25lZEJpdFJldmVyc2UzMlRydW5jKHZhbHVlLCBiaXRDb3VudCkgewogICAgICAgIHJldHVybiB0aGlzLlVuc2lnbmVkQml0UmV2ZXJzZTMyVHJ1bmModmFsdWUgPj4+IDAsIGJpdENvdW50KTsKICAgIH0KICAgIHN0YXRpYyBCaXRSZXZlcnNlOCh2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA+IDB4ZmYpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIGlmICh2YWx1ZSA8IC0weDgwKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICB2YWx1ZSA+Pj49IDA7CiAgICAgICAgdmFsdWUgPSAoKHZhbHVlICYgMHhhYSkgPj4+IDEpIHwgKCh2YWx1ZSAmIDB4NTUpIDw8IDEpOwogICAgICAgIHZhbHVlID0gKCh2YWx1ZSAmIDB4Y2MpID4+PiAyKSB8ICgodmFsdWUgJiAweDMzKSA8PCAyKTsKICAgICAgICByZXR1cm4gKCgodmFsdWUgJiAweGYwKSA+Pj4gNCkgfCAoKHZhbHVlICYgMHgwZikgPDwgNCkpID4+PiAwOwogICAgfQogICAgc3RhdGljIENsYW1wKHZhbHVlLCBtaW4sIG1heCkgewogICAgICAgIGlmICh2YWx1ZSA8IG1pbikKICAgICAgICAgICAgcmV0dXJuIG1pbjsKICAgICAgICBpZiAodmFsdWUgPiBtYXgpCiAgICAgICAgICAgIHJldHVybiBtYXg7CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQogICAgc3RhdGljIERlYnVnQXNzZXJ0KGNvbmRpdGlvbikgewogICAgICAgIGlmICghY29uZGl0aW9uKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkRlYnVnQXNzZXJ0IGZhaWxlZCIpOwogICAgfQp9CkhDQVV0aWxGdW5jLlNpZ25lZE5pYmJsZXMgPSBbMCwgMSwgMiwgMywgNCwgNSwgNiwgNywgLTgsIC03LCAtNiwgLTUsIC00LCAtMywgLTIsIC0xXTsKZXhwb3J0IGNsYXNzIEhDQSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgIH0KICAgIHN0YXRpYyBkZWNyeXB0KGhjYSwga2V5MSwga2V5MikgewogICAgICAgIHJldHVybiB0aGlzLmRlY3J5cHRPckVuY3J5cHQoaGNhLCBmYWxzZSwga2V5MSwga2V5Mik7CiAgICB9CiAgICBzdGF0aWMgZW5jcnlwdChoY2EsIGtleTEsIGtleTIpIHsKICAgICAgICByZXR1cm4gdGhpcy5kZWNyeXB0T3JFbmNyeXB0KGhjYSwgdHJ1ZSwga2V5MSwga2V5Mik7CiAgICB9CiAgICBzdGF0aWMgZGVjcnlwdE9yRW5jcnlwdChoY2EsIGVuY3J5cHQsIGtleTEsIGtleTIpIHsKICAgICAgICAvLyBpbi1wbGFjZSBkZWNyeXB0aW9uL2VuY3J5cHRpb24KICAgICAgICAvLyBwYXJzZSBoZWFkZXIKICAgICAgICBsZXQgaW5mbyA9IG5ldyBIQ0FJbmZvKGhjYSk7IC8vIHRocm93cyAiTm90IGEgSENBIGZpbGUiIGlmIG1pc21hdGNoCiAgICAgICAgaWYgKCFlbmNyeXB0ICYmICFpbmZvLmhhc0hlYWRlclsiY2lwaCJdKSB7CiAgICAgICAgICAgIHJldHVybiBoY2E7IC8vIG5vdCBlbmNyeXB0ZWQKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoZW5jcnlwdCAmJiAhaW5mby5oYXNIZWFkZXJbImNpcGgiXSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIklucHV0IGhjYSBsYWNrcyBcImNpcGhcIiBoZWFkZXIgc2VjdGlvbi4gUGxlYXNlIGNhbGwgSENBSW5mby5hZGRDaXBoZXJIZWFkZXIoaGNhKSBmaXJzdC4iKTsKICAgICAgICB9CiAgICAgICAgbGV0IGNpcGhlcjsKICAgICAgICBzd2l0Y2ggKGluZm8uY2lwaGVyKSB7CiAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIC8vIG5vdCBlbmNyeXB0ZWQKICAgICAgICAgICAgICAgIGlmIChlbmNyeXB0KQogICAgICAgICAgICAgICAgICAgIGNpcGhlciA9IG5ldyBIQ0FDaXBoZXIoa2V5MSwga2V5MikuaW52ZXJ0VGFibGUoKTsKICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICByZXR1cm4gaGNhOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICAgIC8vIGVuY3J5cHRlZCB3aXRoICJubyBrZXkiCiAgICAgICAgICAgICAgICBpZiAoZW5jcnlwdCkKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImFscmVhZHkgZW5jcnlwdGVkIHdpdGggXCJubyBrZXlcIiwgcGxlYXNlIGRlY3J5cHQgZmlyc3QiKTsKICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICBjaXBoZXIgPSBuZXcgSENBQ2lwaGVyKCJub25lIik7IC8vIGlnbm9yZSBnaXZlbiBrZXlzCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDM4OgogICAgICAgICAgICAgICAgLy8gZW5jcnlwdGVkIHdpdGgga2V5cyAtIHdpbGwgeWllbGQgaW5jb3JyZWN0IHdhdmVmb3JtIGlmIGluY29ycmVjdCBrZXlzIGFyZSBnaXZlbiEKICAgICAgICAgICAgICAgIGlmIChlbmNyeXB0KQogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiYWxyZWFkeSBlbmNyeXB0ZWQgd2l0aCBzcGVjaWZpYyBrZXlzLCBwbGVhc2UgZGVjcnlwdCB3aXRoIGNvcnJlY3Qga2V5cyBmaXJzdCIpOwogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIGNpcGhlciA9IG5ldyBIQ0FDaXBoZXIoa2V5MSwga2V5Mik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigidW5rbm93biBjaXBoLnR5cGUiKTsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmZvLmZvcm1hdC5ibG9ja0NvdW50OyArK2kpIHsKICAgICAgICAgICAgbGV0IGZ0ZWxsID0gaW5mby5kYXRhT2Zmc2V0ICsgaW5mby5ibG9ja1NpemUgKiBpOwogICAgICAgICAgICBsZXQgYmxvY2sgPSBoY2Euc3ViYXJyYXkoZnRlbGwsIGZ0ZWxsICsgaW5mby5ibG9ja1NpemUpOwogICAgICAgICAgICAvLyB2ZXJpZnkgYmxvY2sgY2hlY2tzdW0KICAgICAgICAgICAgSENBQ3JjMTYudmVyaWZ5KGJsb2NrLCBpbmZvLmJsb2NrU2l6ZSAtIDIpOwogICAgICAgICAgICAvLyBkZWNyeXB0L2VuY3J5cHQgYmxvY2sKICAgICAgICAgICAgY2lwaGVyLm1hc2soYmxvY2ssIDAsIGluZm8uYmxvY2tTaXplIC0gMik7CiAgICAgICAgICAgIC8vIGZpeCBjaGVja3N1bQogICAgICAgICAgICBIQ0FDcmMxNi5maXgoYmxvY2ssIGluZm8uYmxvY2tTaXplIC0gMik7CiAgICAgICAgfQogICAgICAgIC8vIHJlLSh1biltYXNrIGhlYWRlcnMsIGFuZCBzZXQgY2lwaCBoZWFkZXIgdG8gbmV3IHZhbHVlCiAgICAgICAgbGV0IG5ld0NpcGhlckRhdGEgPSBuZXcgVWludDhBcnJheSgyKTsKICAgICAgICBsZXQgbmV3Q2lwaGVyVHlwZSA9IGVuY3J5cHQgPyBjaXBoZXIuZ2V0VHlwZSgpIDogMDsKICAgICAgICBuZXcgRGF0YVZpZXcobmV3Q2lwaGVyRGF0YS5idWZmZXIpLnNldFVpbnQxNigwLCBuZXdDaXBoZXJUeXBlKTsKICAgICAgICBpbmZvLm1vZGlmeShoY2EsICJjaXBoIiwgbmV3Q2lwaGVyRGF0YSk7CiAgICAgICAgcmV0dXJuIGhjYTsKICAgIH0KICAgIHN0YXRpYyBkZWNvZGUoaGNhLCBtb2RlID0gMzIsIGxvb3AgPSAwLCB2b2x1bWUgPSAxLjApIHsKICAgICAgICBzd2l0Y2ggKG1vZGUpIHsKICAgICAgICAgICAgY2FzZSAwOiAvLyBmbG9hdAogICAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgIGNhc2UgMjQ6CiAgICAgICAgICAgIGNhc2UgMzI6IC8vIGludGVnZXIKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgbW9kZSA9IDMyOwogICAgICAgIH0KICAgICAgICBpZiAodm9sdW1lID4gMSkKICAgICAgICAgICAgdm9sdW1lID0gMTsKICAgICAgICBlbHNlIGlmICh2b2x1bWUgPCAwKQogICAgICAgICAgICB2b2x1bWUgPSAwOwogICAgICAgIGxldCBpbmZvID0gbmV3IEhDQUluZm8oaGNhKTsgLy8gdGhyb3dzICJOb3QgYSBIQ0EgZmlsZSIgaWYgbWlzbWF0Y2gKICAgICAgICBsZXQgZnJhbWUgPSBuZXcgSENBRnJhbWUoaW5mbyk7CiAgICAgICAgaWYgKGluZm8uaGFzSGVhZGVyWyJjaXBoIl0gJiYgaW5mby5jaXBoZXIgIT0gMCkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkhDQSBpcyBlbmNyeXB0ZWQsIHBsZWFzZSBkZWNyeXB0IGl0IGZpcnN0IGJlZm9yZSBkZWNvZGluZyIpOwogICAgICAgIH0KICAgICAgICAvLyBwcmVwYXJlIG91dHB1dCBXQVYgZmlsZQogICAgICAgIGNvbnN0IG91dHB1dFdhdiA9IG5ldyBIQ0FXYXYoaW5mbywgbW9kZSwgbG9vcCk7CiAgICAgICAgY29uc3QgZmlsZUJ1ZiA9IG91dHB1dFdhdi5maWxlQnVmOwogICAgICAgIGNvbnN0IGRhdGFQYXJ0ID0gb3V0cHV0V2F2LmRhdGFQYXJ0OwogICAgICAgIC8vIGNhbGN1bGF0ZSBpbi1XQVYgc2l6ZQogICAgICAgIGxldCBpbldhdlNpemUgPSBpbmZvLmNhbGNJbldhdlNpemUobW9kZSk7CiAgICAgICAgLy8gZGVjb2RlIGJsb2NrcyAoZnJhbWVzKQogICAgICAgIGZvciAobGV0IGkgPSAwLCBvZmZzZXQgPSAwOyBpIDwgaW5mby5mb3JtYXQuYmxvY2tDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGxldCBsYXN0RGVjb2RlZFNhbXBsZXMgPSBpICogSENBRnJhbWUuU2FtcGxlc1BlckZyYW1lOwogICAgICAgICAgICBsZXQgY3VycmVudERlY29kZWRTYW1wbGVzID0gbGFzdERlY29kZWRTYW1wbGVzICsgSENBRnJhbWUuU2FtcGxlc1BlckZyYW1lOwogICAgICAgICAgICBpZiAoY3VycmVudERlY29kZWRTYW1wbGVzIDw9IGluZm8uc3RhcnRBdFNhbXBsZSB8fCBsYXN0RGVjb2RlZFNhbXBsZXMgPj0gaW5mby5lbmRBdFNhbXBsZSkgewogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGV0IHN0YXJ0T2Zmc2V0ID0gaW5mby5kYXRhT2Zmc2V0ICsgaW5mby5ibG9ja1NpemUgKiBpOwogICAgICAgICAgICBsZXQgYmxvY2sgPSBoY2Euc3ViYXJyYXkoc3RhcnRPZmZzZXQsIHN0YXJ0T2Zmc2V0ICsgaW5mby5ibG9ja1NpemUpOwogICAgICAgICAgICB0aGlzLmRlY29kZUJsb2NrKGZyYW1lLCBibG9jayk7CiAgICAgICAgICAgIGxldCB3YXZlYnVmZjsKICAgICAgICAgICAgaWYgKGxhc3REZWNvZGVkU2FtcGxlcyA8IGluZm8uc3RhcnRBdFNhbXBsZSB8fCBjdXJyZW50RGVjb2RlZFNhbXBsZXMgPiBpbmZvLmVuZEF0U2FtcGxlKSB7CiAgICAgICAgICAgICAgICAvLyBjcm9zc2luZyBzdGFydEF0U2FtcGxlL2VuZEF0U2FtcGxlLCBza2lwL2Ryb3Agc3BlY2lmaWVkIGJ5dGVzCiAgICAgICAgICAgICAgICB3YXZlYnVmZiA9IHRoaXMud3JpdGVUb1BDTShmcmFtZSwgbW9kZSwgdm9sdW1lKTsKICAgICAgICAgICAgICAgIGlmIChsYXN0RGVjb2RlZFNhbXBsZXMgPCBpbmZvLnN0YXJ0QXRTYW1wbGUpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgc2tpcHBlZFNpemUgPSAoaW5mby5zdGFydEF0U2FtcGxlIC0gbGFzdERlY29kZWRTYW1wbGVzKSAqIGluV2F2U2l6ZS5zYW1wbGU7CiAgICAgICAgICAgICAgICAgICAgd2F2ZWJ1ZmYgPSB3YXZlYnVmZi5zdWJhcnJheShza2lwcGVkU2l6ZSwgaW5XYXZTaXplLmJsb2NrKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgaWYgKGN1cnJlbnREZWNvZGVkU2FtcGxlcyA+IGluZm8uZW5kQXRTYW1wbGUpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgd3JpdGVTaXplID0gKGluZm8uZW5kQXRTYW1wbGUgLSBsYXN0RGVjb2RlZFNhbXBsZXMpICogaW5XYXZTaXplLnNhbXBsZTsKICAgICAgICAgICAgICAgICAgICB3YXZlYnVmZiA9IHdhdmVidWZmLnN1YmFycmF5KDAsIHdyaXRlU2l6ZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoInNob3VsZCBuZXZlciBnbyBoZXJlIik7CiAgICAgICAgICAgICAgICBkYXRhUGFydC5zZXQod2F2ZWJ1ZmYsIG9mZnNldCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB3YXZlYnVmZiA9IHRoaXMud3JpdGVUb1BDTShmcmFtZSwgbW9kZSwgdm9sdW1lLCBkYXRhUGFydCwgb2Zmc2V0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvZmZzZXQgKz0gd2F2ZWJ1ZmYuYnl0ZUxlbmd0aDsKICAgICAgICB9CiAgICAgICAgLy8gZGVjb2RpbmcgZG9uZSwgdGhlbiBqdXN0IGNvcHkgbG9vcGluZyBwYXJ0CiAgICAgICAgaWYgKGluZm8uaGFzSGVhZGVyWyJsb29wIl0gJiYgbG9vcCkgewogICAgICAgICAgICAvLyAidGFpbCIgYmV5b25kIGxvb3AgZW5kIGlzIGRyb3BwZWQKICAgICAgICAgICAgLy8gY29weSBsb29waW5nIGF1ZGlvIGNsaXBzCiAgICAgICAgICAgIGlmIChpbldhdlNpemUubG9vcCA9PSBudWxsKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgICAgIGxldCBwcmVMb29wU2l6ZUluV2F2ID0gaW5XYXZTaXplLnNhbXBsZSAqIChpbmZvLmxvb3BTdGFydEF0U2FtcGxlIC0gaW5mby5zdGFydEF0U2FtcGxlKTsKICAgICAgICAgICAgbGV0IHNyYyA9IGRhdGFQYXJ0LnN1YmFycmF5KHByZUxvb3BTaXplSW5XYXYsIHByZUxvb3BTaXplSW5XYXYgKyBpbldhdlNpemUubG9vcC5sb29wUGFydCk7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBzdGFydCA9IHByZUxvb3BTaXplSW5XYXYgKyBpbldhdlNpemUubG9vcC5sb29wUGFydDsgaSA8IGxvb3A7IGkrKykgewogICAgICAgICAgICAgICAgbGV0IGRzdCA9IGRhdGFQYXJ0LnN1YmFycmF5KHN0YXJ0LCBzdGFydCArIGluV2F2U2l6ZS5sb29wLmxvb3BQYXJ0KTsKICAgICAgICAgICAgICAgIGRzdC5zZXQoc3JjKTsKICAgICAgICAgICAgICAgIHN0YXJ0ICs9IGluV2F2U2l6ZS5sb29wLmxvb3BQYXJ0OwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBmaWxlQnVmOwogICAgfQogICAgc3RhdGljIGRlY29kZUJsb2NrKGZyYW1lLCBibG9jaykgewogICAgICAgIGxldCBpbmZvID0gZnJhbWUuSGNhOwogICAgICAgIGlmIChibG9jay5ieXRlTGVuZ3RoICE9IGluZm8uYmxvY2tTaXplKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAvLyB2ZXJpZnkgY2hlY2tzdW0KICAgICAgICBIQ0FDcmMxNi52ZXJpZnkoYmxvY2ssIGluZm8uYmxvY2tTaXplIC0gMik7CiAgICAgICAgLy8gZGVjb2RlCiAgICAgICAgSENBRGVjb2Rlci5EZWNvZGVGcmFtZShibG9jaywgZnJhbWUpOwogICAgfQogICAgc3RhdGljIHdyaXRlVG9QQ00oZnJhbWUsIG1vZGUgPSAzMiwgdm9sdW1lID0gMS4wLCB3cml0ZXIsIGZ0ZWxsKSB7CiAgICAgICAgc3dpdGNoIChtb2RlKSB7CiAgICAgICAgICAgIGNhc2UgMDogLy8gZmxvYXQKICAgICAgICAgICAgY2FzZSA4OgogICAgICAgICAgICBjYXNlIDE2OgogICAgICAgICAgICBjYXNlIDI0OgogICAgICAgICAgICBjYXNlIDMyOiAvLyBpbnRlZ2VyCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIG1vZGUgPSAzMjsKICAgICAgICB9CiAgICAgICAgaWYgKHZvbHVtZSA+IDEpCiAgICAgICAgICAgIHZvbHVtZSA9IDE7CiAgICAgICAgZWxzZSBpZiAodm9sdW1lIDwgMCkKICAgICAgICAgICAgdm9sdW1lID0gMDsKICAgICAgICAvLyBjcmVhdGUgbmV3IHdyaXRlciBpZiBub3Qgc3BlY2lmaWVkCiAgICAgICAgbGV0IGluZm8gPSBmcmFtZS5IY2E7CiAgICAgICAgaWYgKHdyaXRlciA9PSBudWxsKSB7CiAgICAgICAgICAgIHdyaXRlciA9IG5ldyBVaW50OEFycmF5KEhDQUZyYW1lLlNhbXBsZXNQZXJGcmFtZSAqIGluZm8uZm9ybWF0LmNoYW5uZWxDb3VudCAqIChtb2RlID09IDAgPyAzMiA6IG1vZGUpIC8gOCk7CiAgICAgICAgICAgIGlmIChmdGVsbCA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICBmdGVsbCA9IDA7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGlmIChmdGVsbCA9PSBudWxsKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgfQogICAgICAgIC8vIHdyaXRlIGRlY29kZWQgZGF0YSBpbnRvIHdyaXRlcgogICAgICAgIGxldCBwID0gbmV3IERhdGFWaWV3KHdyaXRlci5idWZmZXIsIHdyaXRlci5ieXRlT2Zmc2V0LCB3cml0ZXIuYnl0ZUxlbmd0aCk7CiAgICAgICAgbGV0IGZ0ZWxsQmVnaW4gPSBmdGVsbDsKICAgICAgICBmb3IgKGxldCBzZiA9IDA7IHNmIDwgSENBRnJhbWUuU3ViZnJhbWVzUGVyRnJhbWU7IHNmKyspIHsKICAgICAgICAgICAgZm9yIChsZXQgcyA9IDA7IHMgPCBIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWU7IHMrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCBmcmFtZS5DaGFubmVscy5sZW5ndGg7IGMrKykgewogICAgICAgICAgICAgICAgICAgIGxldCBmID0gZnJhbWUuQ2hhbm5lbHNbY10uUGNtRmxvYXRbc2ZdW3NdICogdm9sdW1lOwogICAgICAgICAgICAgICAgICAgIGlmIChmID4gMSkKICAgICAgICAgICAgICAgICAgICAgICAgZiA9IDE7CiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoZiA8IC0xKQogICAgICAgICAgICAgICAgICAgICAgICBmID0gLTE7CiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChtb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgODoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG11c3QgYmUgdW5zaWduZWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAuc2V0VWludDgoZnRlbGwsIGYgKiAweDdGICsgMHg4MCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdGVsbCArPSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmb3IgYWJvdmUgOC1iaXQgaW50ZWdlciwgbGl0dGxlLWVuZGlhbiBzaWduZWQgaW50ZWdlciBpcyB1c2VkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAoc2V0VWludDE2L3NldEludDE2IGFjdHVhbGx5IGRvZXNuJ3Qgc2VlbSB0byBtYWtlIGFueSBkaWZmZXJlbmNlIGhlcmUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLnNldEludDE2KGZ0ZWxsLCBmICogMHg3RkZGLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ0ZWxsICs9IDI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyNDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZXJlJ3Mgbm8gc2V0SW50MjQsIHdyaXRlIDMgYnl0ZXMgd2l0aCBzZXRVaW50OCByZXNwZWN0aXZlbHkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGYgKj0gMHg3RkZGRkY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLnNldFVpbnQ4KGZ0ZWxsLCBmICYgMHhGRik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLnNldFVpbnQ4KGZ0ZWxsICsgMSwgZiA+PiA4ICYgMHhGRik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLnNldFVpbnQ4KGZ0ZWxsICsgMiwgZiA+PiAxNiAmIDB4RkYpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZnRlbGwgKz0gMzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDMyOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcC5zZXRJbnQzMihmdGVsbCwgZiAqIDB4N0ZGRkZGRkYsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZnRlbGwgKz0gNDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmbG9hdAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcC5zZXRGbG9hdDMyKGZ0ZWxsLCBmLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ0ZWxsICs9IDQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigidW5rbm93biBtb2RlIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB3cml0ZXIuc3ViYXJyYXkoZnRlbGxCZWdpbiwgZnRlbGwpOwogICAgfQogICAgc3RhdGljIGZpeENoZWNrc3VtKGhjYSkgewogICAgICAgIEhDQUluZm8uZml4SGVhZGVyQ2hlY2tzdW0oaGNhKTsKICAgICAgICBsZXQgaW5mbyA9IG5ldyBIQ0FJbmZvKGhjYSk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmZvLmZvcm1hdC5ibG9ja0NvdW50OyBpKyspIHsKICAgICAgICAgICAgbGV0IGZ0ZWxsID0gaW5mby5kYXRhT2Zmc2V0ICsgaSAqIGluZm8uYmxvY2tTaXplOwogICAgICAgICAgICBsZXQgYmxvY2sgPSBoY2Euc3ViYXJyYXkoZnRlbGwsIGZ0ZWxsICsgaW5mby5ibG9ja1NpemUpOwogICAgICAgICAgICBIQ0FDcmMxNi5maXgoYmxvY2ssIGluZm8uYmxvY2tTaXplIC0gMik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBoY2E7CiAgICB9Cn0KY2xhc3MgSENBV2F2IHsKICAgIGNvbnN0cnVjdG9yKGluZm8sIG1vZGUgPSAzMiwgbG9vcCA9IDApIHsKICAgICAgICBzd2l0Y2ggKG1vZGUpIHsKICAgICAgICAgICAgY2FzZSAwOiAvLyBmbG9hdAogICAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgIGNhc2UgMjQ6CiAgICAgICAgICAgIGNhc2UgMzI6IC8vIGludGVnZXIKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgbW9kZSA9IDMyOwogICAgICAgIH0KICAgICAgICBpZiAoaXNOYU4obG9vcCkpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigibG9vcCBpcyBub3QgbnVtYmVyIik7CiAgICAgICAgbG9vcCA9IE1hdGguZmxvb3IobG9vcCk7CiAgICAgICAgaWYgKGxvb3AgPCAwKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICBsZXQgaW5XYXZTaXplID0gaW5mby5jYWxjSW5XYXZTaXplKG1vZGUpOwogICAgICAgIGxldCBkYXRhU2l6ZSA9IGluV2F2U2l6ZS5zYW1wbGUgKiBpbmZvLnNhbXBsZUNvdW50OwogICAgICAgIGlmIChsb29wID4gMCkgewogICAgICAgICAgICBpZiAoaW5XYXZTaXplLmxvb3AgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgICAgICBkYXRhU2l6ZSArPSBpbldhdlNpemUubG9vcC5sb29wUGFydCAqIGxvb3A7CiAgICAgICAgfQogICAgICAgIC8vIHByZXBhcmUgbWV0YWRhdGEgY2h1bmtzIGFuZCBkYXRhIGNodW5rIGhlYWRlcgogICAgICAgIHRoaXMuZm10ID0gbmV3IEhDQVdhdkZtdENodW5rKGluZm8sIG1vZGUpOwogICAgICAgIGlmIChpbmZvLmhhc0hlYWRlclsiY29tbSJdKQogICAgICAgICAgICB0aGlzLm5vdGUgPSBuZXcgSENBV2F2Q29tbWVudENodW5rKGluZm8pOwogICAgICAgIGlmIChpbmZvLmhhc0hlYWRlclsibG9vcCJdKQogICAgICAgICAgICB0aGlzLnNtcGwgPSBuZXcgSENBV2F2ZVNtcGxDaHVuayhpbmZvKTsKICAgICAgICB0aGlzLndhdmVSaWZmID0gbmV3IEhDQVdhdldhdmVSaWZmSGVhZGVyKDggKyB0aGlzLmZtdC5zaXplCiAgICAgICAgICAgICsgKHRoaXMubm90ZSA9PSBudWxsID8gMCA6IDggKyB0aGlzLm5vdGUuc2l6ZSkKICAgICAgICAgICAgKyA4ICsgZGF0YVNpemUKICAgICAgICAgICAgKyAodGhpcy5zbXBsID09IG51bGwgPyAwIDogOCArIHRoaXMuc21wbC5zaXplKSk7CiAgICAgICAgLy8gZ2V0IGJ5dGVzIG9mIHByZXBhcmVkIGNodW5rcwogICAgICAgIGxldCB3YXZlUmlmZkhlYWRlciA9IHRoaXMud2F2ZVJpZmYuZ2V0KCk7CiAgICAgICAgbGV0IGZtdENodW5rID0gdGhpcy5mbXQuZ2V0KCk7CiAgICAgICAgbGV0IG5vdGVDaHVuayA9IHRoaXMubm90ZSAhPSBudWxsID8gdGhpcy5ub3RlLmdldCgpIDogbmV3IFVpbnQ4QXJyYXkoMCk7CiAgICAgICAgbGV0IGRhdGFDaHVua0hlYWRlciA9IG5ldyBVaW50OEFycmF5KDgpOwogICAgICAgIGRhdGFDaHVua0hlYWRlci5zZXQobmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKCJkYXRhIikpOwogICAgICAgIG5ldyBEYXRhVmlldyhkYXRhQ2h1bmtIZWFkZXIuYnVmZmVyKS5zZXRVaW50MzIoNCwgZGF0YVNpemUsIHRydWUpOwogICAgICAgIGxldCBzbXBsQ2h1bmsgPSB0aGlzLnNtcGwgIT0gbnVsbCA/IHRoaXMuc21wbC5nZXQoKSA6IG5ldyBVaW50OEFycmF5KDApOwogICAgICAgIC8vIGNyZWF0ZSB3aG9sZS1maWxlIGJ1ZmZlcgogICAgICAgIHRoaXMuZmlsZUJ1ZiA9IG5ldyBVaW50OEFycmF5KDggKyB0aGlzLndhdmVSaWZmLnNpemUpOwogICAgICAgIC8vIGNvcHkgcHJlcGFyZWQgbWV0YWRhdGEgY2h1bmtzIGFuZCBkYXRhIGNodW5rIGhlYWRlciB0byB3aG9sZS1maWxlIGJ1ZmZlcgogICAgICAgIGxldCB3cml0dGVuTGVuZ3RoID0gMDsKICAgICAgICBbd2F2ZVJpZmZIZWFkZXIsIGZtdENodW5rLCBub3RlQ2h1bmssIGRhdGFDaHVua0hlYWRlcl0uZm9yRWFjaCgoY2h1bmspID0+IHsKICAgICAgICAgICAgdGhpcy5maWxlQnVmLnNldChjaHVuaywgd3JpdHRlbkxlbmd0aCk7CiAgICAgICAgICAgIHdyaXR0ZW5MZW5ndGggKz0gY2h1bmsuYnl0ZUxlbmd0aDsKICAgICAgICB9KTsKICAgICAgICAvLyBza2lwIGRhdGFQYXJ0IHNpbmNlIGl0J3MgZW1wdHkKICAgICAgICB0aGlzLmRhdGFQYXJ0ID0gdGhpcy5maWxlQnVmLnN1YmFycmF5KHdyaXR0ZW5MZW5ndGgsIHdyaXR0ZW5MZW5ndGggKyBkYXRhU2l6ZSk7CiAgICAgICAgd3JpdHRlbkxlbmd0aCArPSBkYXRhU2l6ZTsKICAgICAgICAvLyBjb3B5IHRoZSBsYXN0IHByZXBhcmVkIGNodW5rIHRvIHdob2xlLWZpbGUgYnVmZmVyCiAgICAgICAgdGhpcy5maWxlQnVmLnNldChzbXBsQ2h1bmssIHdyaXR0ZW5MZW5ndGgpOwogICAgICAgIHdyaXR0ZW5MZW5ndGggKz0gc21wbENodW5rLmJ5dGVMZW5ndGg7CiAgICAgICAgaWYgKHdyaXR0ZW5MZW5ndGggIT0gdGhpcy5maWxlQnVmLmJ5dGVMZW5ndGgpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgfQp9CmNsYXNzIEhDQVdhdldhdmVSaWZmSGVhZGVyIHsKICAgIGNvbnN0cnVjdG9yKHNpemUpIHsKICAgICAgICBpZiAoaXNOYU4oc2l6ZSkpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigic2l6ZSBtdXN0IGJlIG51bWJlciIpOwogICAgICAgIHNpemUgPSBNYXRoLmZsb29yKHNpemUpOwogICAgICAgIGlmIChzaXplIDw9IDApCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIHRoaXMuc2l6ZSA9IDQgKyBzaXplOyAvLyAiV0FWRSIgKyByZW1haW5pbmcgcGFydAogICAgfQogICAgZ2V0KCkgewogICAgICAgIGxldCBidWYgPSBuZXcgQXJyYXlCdWZmZXIoMTIpOwogICAgICAgIGxldCByZXQgPSBuZXcgVWludDhBcnJheShidWYpOwogICAgICAgIGxldCBwID0gbmV3IERhdGFWaWV3KGJ1Zik7CiAgICAgICAgbGV0IHRlID0gbmV3IFRleHRFbmNvZGVyKCk7CiAgICAgICAgcmV0LnNldCh0ZS5lbmNvZGUoIlJJRkYiKSwgMCk7CiAgICAgICAgcC5zZXRVaW50MzIoNCwgdGhpcy5zaXplLCB0cnVlKTsKICAgICAgICByZXQuc2V0KHRlLmVuY29kZSgiV0FWRSIpLCA4KTsKICAgICAgICByZXR1cm4gcmV0OwogICAgfQp9CmNsYXNzIEhDQVdhdkZtdENodW5rIHsKICAgIGNvbnN0cnVjdG9yKGluZm8sIG1vZGUgPSAzMikgewogICAgICAgIHRoaXMuc2l6ZSA9IDE2OwogICAgICAgIHN3aXRjaCAobW9kZSkgewogICAgICAgICAgICBjYXNlIDA6IC8vIGZsb2F0CiAgICAgICAgICAgIGNhc2UgODoKICAgICAgICAgICAgY2FzZSAxNjoKICAgICAgICAgICAgY2FzZSAyNDoKICAgICAgICAgICAgY2FzZSAzMjogLy8gaW50ZWdlcgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBtb2RlID0gMzI7CiAgICAgICAgfQogICAgICAgIGxldCBpbldhdlNpemUgPSBpbmZvLmNhbGNJbldhdlNpemUobW9kZSk7CiAgICAgICAgdGhpcy5mb3JtYXRUYWcgPSBtb2RlID4gMCA/IDEgOiAzOwogICAgICAgIHRoaXMuY2hhbm5lbENvdW50ID0gaW5mby5mb3JtYXQuY2hhbm5lbENvdW50OwogICAgICAgIHRoaXMuc2FtcGxlc1BlclNlYyA9IGluZm8uZm9ybWF0LnNhbXBsaW5nUmF0ZTsKICAgICAgICB0aGlzLmJ5dGVzUGVyU2VjID0gaW5XYXZTaXplLnNhbXBsZSAqIGluZm8uZm9ybWF0LnNhbXBsaW5nUmF0ZTsKICAgICAgICB0aGlzLmJsb2NrQWxpZ24gPSBpbldhdlNpemUuc2FtcGxlOwogICAgICAgIHRoaXMuYml0c1BlclNhbXBsZSA9IGluV2F2U2l6ZS5iaXRzUGVyU2FtcGxlOwogICAgfQogICAgZ2V0KCkgewogICAgICAgIGxldCBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCArIHRoaXMuc2l6ZSk7CiAgICAgICAgbGV0IHJldCA9IG5ldyBVaW50OEFycmF5KGJ1Zik7CiAgICAgICAgbGV0IHAgPSBuZXcgRGF0YVZpZXcoYnVmKTsKICAgICAgICBsZXQgdGUgPSBuZXcgVGV4dEVuY29kZXIoKTsKICAgICAgICByZXQuc2V0KHRlLmVuY29kZSgiZm10ICIpLCAwKTsKICAgICAgICBwLnNldFVpbnQzMig0LCB0aGlzLnNpemUsIHRydWUpOwogICAgICAgIHAuc2V0VWludDE2KDgsIHRoaXMuZm9ybWF0VGFnLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQxNigxMCwgdGhpcy5jaGFubmVsQ291bnQsIHRydWUpOwogICAgICAgIHAuc2V0VWludDMyKDEyLCB0aGlzLnNhbXBsZXNQZXJTZWMsIHRydWUpOwogICAgICAgIHAuc2V0VWludDMyKDE2LCB0aGlzLmJ5dGVzUGVyU2VjLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQxNigyMCwgdGhpcy5ibG9ja0FsaWduLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQxNigyMiwgdGhpcy5iaXRzUGVyU2FtcGxlLCB0cnVlKTsKICAgICAgICByZXR1cm4gcmV0OwogICAgfQp9CmNsYXNzIEhDQVdhdkNvbW1lbnRDaHVuayB7CiAgICBjb25zdHJ1Y3RvcihpbmZvKSB7CiAgICAgICAgdGhpcy5jb21tZW50QnVmID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKGluZm8uY29tbWVudCk7CiAgICAgICAgbGV0IHNpemUgPSB0aGlzLmNvbW1lbnRCdWYuYnl0ZUxlbmd0aDsKICAgICAgICBzaXplICs9IDQ7CiAgICAgICAgaWYgKHNpemUgJSA0KQogICAgICAgICAgICBzaXplICs9IDQgLSBzaXplICUgNDsKICAgICAgICB0aGlzLnNpemUgPSBzaXplOwogICAgfQogICAgZ2V0KCkgewogICAgICAgIGxldCBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCArIHRoaXMuc2l6ZSk7CiAgICAgICAgbGV0IHJldCA9IG5ldyBVaW50OEFycmF5KGJ1Zik7CiAgICAgICAgbGV0IHAgPSBuZXcgRGF0YVZpZXcoYnVmKTsKICAgICAgICBsZXQgdGUgPSBuZXcgVGV4dEVuY29kZXIoKTsKICAgICAgICByZXQuc2V0KHRlLmVuY29kZSgibm90ZSIpLCAwKTsKICAgICAgICBwLnNldFVpbnQzMig0LCB0aGlzLnNpemUsIHRydWUpOwogICAgICAgIHJldC5zZXQodGhpcy5jb21tZW50QnVmLCA4KTsKICAgICAgICByZXR1cm4gcmV0OwogICAgfQp9CmNsYXNzIEhDQVdhdmVTbXBsQ2h1bmsgewogICAgY29uc3RydWN0b3IoaW5mbykgewogICAgICAgIHRoaXMuc2l6ZSA9IDYwOwogICAgICAgIHRoaXMubWFudWZhY3R1cmVyID0gMDsKICAgICAgICB0aGlzLnByb2R1Y3QgPSAwOwogICAgICAgIHRoaXMuTUlESVVuaXR5Tm90ZSA9IDB4M2M7CiAgICAgICAgdGhpcy5NSURJUGl0Y2hGcmFjdGlvbiA9IDA7CiAgICAgICAgdGhpcy5TTVBURUZvcm1hdCA9IDA7CiAgICAgICAgdGhpcy5zYW1wbGVMb29wcyA9IDE7CiAgICAgICAgdGhpcy5zYW1wbGVyRGF0YSA9IDB4MTg7CiAgICAgICAgdGhpcy5sb29wX0lkZW50aWZpZXIgPSAwOwogICAgICAgIHRoaXMubG9vcF9UeXBlID0gMDsKICAgICAgICB0aGlzLmxvb3BfRnJhY3Rpb24gPSAwOwogICAgICAgIHRoaXMubG9vcF9QbGF5Q291bnQgPSAwOwogICAgICAgIGlmICghaW5mby5oYXNIZWFkZXJbImxvb3AiXSkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJtaXNzaW5nIFwibG9vcFwiIGhlYWRlciIpOwogICAgICAgIHRoaXMuc2FtcGxlUGVyaW9kID0gKDEgLyBpbmZvLmZvcm1hdC5zYW1wbGluZ1JhdGUgKiAxMDAwMDAwMDAwKTsKICAgICAgICB0aGlzLmxvb3BfU3RhcnQgPSBpbmZvLmxvb3BTdGFydEF0U2FtcGxlIC0gaW5mby5zdGFydEF0U2FtcGxlOwogICAgICAgIHRoaXMubG9vcF9FbmQgPSBpbmZvLmxvb3BFbmRBdFNhbXBsZSAtIGluZm8uc3RhcnRBdFNhbXBsZTsKICAgICAgICB0aGlzLlNNUFRFT2Zmc2V0ID0gMTsKICAgIH0KICAgIGdldCgpIHsKICAgICAgICBsZXQgYnVmID0gbmV3IEFycmF5QnVmZmVyKDggKyB0aGlzLnNpemUpOwogICAgICAgIGxldCByZXQgPSBuZXcgVWludDhBcnJheShidWYpOwogICAgICAgIGxldCBwID0gbmV3IERhdGFWaWV3KGJ1Zik7CiAgICAgICAgbGV0IHRlID0gbmV3IFRleHRFbmNvZGVyKCk7CiAgICAgICAgcmV0LnNldCh0ZS5lbmNvZGUoInNtcGwiKSwgMCk7CiAgICAgICAgcC5zZXRVaW50MzIoNCwgdGhpcy5zaXplLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMig4LCB0aGlzLm1hbnVmYWN0dXJlciwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoMTIsIHRoaXMucHJvZHVjdCwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoMTYsIHRoaXMuc2FtcGxlUGVyaW9kLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMigyMCwgdGhpcy5NSURJVW5pdHlOb3RlLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMigyNCwgdGhpcy5NSURJUGl0Y2hGcmFjdGlvbiwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoMjgsIHRoaXMuU01QVEVGb3JtYXQsIHRydWUpOwogICAgICAgIHAuc2V0VWludDMyKDMyLCB0aGlzLlNNUFRFT2Zmc2V0LCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMigzNiwgdGhpcy5zYW1wbGVMb29wcywgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoNDAsIHRoaXMuc2FtcGxlckRhdGEsIHRydWUpOwogICAgICAgIHAuc2V0VWludDMyKDQ0LCB0aGlzLmxvb3BfSWRlbnRpZmllciwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoNDgsIHRoaXMubG9vcF9UeXBlLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMig1MiwgdGhpcy5sb29wX1N0YXJ0LCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMig1NiwgdGhpcy5sb29wX0VuZCwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoNjAsIHRoaXMubG9vcF9GcmFjdGlvbiwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoNjQsIHRoaXMubG9vcF9QbGF5Q291bnQsIHRydWUpOwogICAgICAgIHJldHVybiByZXQ7CiAgICB9Cn0KY2xhc3MgSENBQml0UmVhZGVyIHsKICAgIGNvbnN0cnVjdG9yKGJ1ZmZlcikgewogICAgICAgIHRoaXMuQnVmZmVyID0gYnVmZmVyOwogICAgICAgIHRoaXMuZHYgPSBuZXcgRGF0YVZpZXcoYnVmZmVyLmJ1ZmZlciwgYnVmZmVyLmJ5dGVPZmZzZXQsIGJ1ZmZlci5ieXRlTGVuZ3RoKTsKICAgICAgICB0aGlzLkxlbmd0aEJpdHMgPSBidWZmZXIubGVuZ3RoICogODsKICAgICAgICB0aGlzLlBvc2l0aW9uID0gMDsKICAgIH0KICAgIGdldCBSZW1haW5pbmcoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuTGVuZ3RoQml0cyAtIHRoaXMuUG9zaXRpb247CiAgICB9CiAgICBSZWFkSW50KGJpdENvdW50KSB7CiAgICAgICAgbGV0IHZhbHVlID0gdGhpcy5QZWVrSW50KGJpdENvdW50KTsKICAgICAgICB0aGlzLlBvc2l0aW9uICs9IGJpdENvdW50OwogICAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KICAgIFJlYWRCb29sKCkgewogICAgICAgIHJldHVybiB0aGlzLlJlYWRJbnQoMSkgPT0gMTsKICAgIH0KICAgIFJlYWRPZmZzZXRCaW5hcnkoYml0Q291bnQsIGJpYXMpIHsKICAgICAgICBsZXQgb2Zmc2V0ID0gKDEgPDwgKGJpdENvdW50IC0gMSkpIC0gYmlhczsKICAgICAgICBsZXQgdmFsdWUgPSB0aGlzLlBlZWtJbnQoYml0Q291bnQpIC0gb2Zmc2V0OwogICAgICAgIHRoaXMuUG9zaXRpb24gKz0gYml0Q291bnQ7CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQogICAgQWxpZ25Qb3NpdGlvbihtdWx0aXBsZSkgewogICAgICAgIHRoaXMuUG9zaXRpb24gPSBIQ0FVdGlsRnVuYy5HZXROZXh0TXVsdGlwbGUodGhpcy5Qb3NpdGlvbiwgbXVsdGlwbGUpOwogICAgfQogICAgUGVla0ludChiaXRDb3VudCkgewogICAgICAgIEhDQVV0aWxGdW5jLkRlYnVnQXNzZXJ0KGJpdENvdW50ID49IDAgJiYgYml0Q291bnQgPD0gMzIpOwogICAgICAgIGlmIChiaXRDb3VudCA+IHRoaXMuUmVtYWluaW5nKSB7CiAgICAgICAgICAgIGlmICh0aGlzLlBvc2l0aW9uID49IHRoaXMuTGVuZ3RoQml0cykKICAgICAgICAgICAgICAgIHJldHVybiAwOwogICAgICAgICAgICBsZXQgZXh0cmFCaXRzID0gYml0Q291bnQgLSB0aGlzLlJlbWFpbmluZzsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuUGVla0ludEZhbGxiYWNrKHRoaXMuUmVtYWluaW5nKSA8PCBleHRyYUJpdHM7CiAgICAgICAgfQogICAgICAgIGxldCBieXRlSW5kZXggPSB0aGlzLlBvc2l0aW9uIC8gODsKICAgICAgICBsZXQgYml0SW5kZXggPSB0aGlzLlBvc2l0aW9uICUgODsKICAgICAgICBpZiAoYml0Q291bnQgPD0gOSAmJiB0aGlzLlJlbWFpbmluZyA+PSAxNikgewogICAgICAgICAgICBsZXQgdmFsdWUgPSB0aGlzLmR2LmdldFVpbnQxNihieXRlSW5kZXgpOwogICAgICAgICAgICB2YWx1ZSAmPSAweEZGRkYgPj4gYml0SW5kZXg7CiAgICAgICAgICAgIHZhbHVlID4+PSAxNiAtIGJpdENvdW50IC0gYml0SW5kZXg7CiAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKGJpdENvdW50IDw9IDE3ICYmIHRoaXMuUmVtYWluaW5nID49IDI0KSB7CiAgICAgICAgICAgIGxldCB2YWx1ZSA9IHRoaXMuZHYuZ2V0VWludDE2KGJ5dGVJbmRleCkgPDwgOCB8IHRoaXMuZHYuZ2V0VWludDgoYnl0ZUluZGV4ICsgMik7CiAgICAgICAgICAgIHZhbHVlICY9IDB4RkZGRkZGID4+IGJpdEluZGV4OwogICAgICAgICAgICB2YWx1ZSA+Pj0gMjQgLSBiaXRDb3VudCAtIGJpdEluZGV4OwogICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgfQogICAgICAgIGlmIChiaXRDb3VudCA8PSAyNSAmJiB0aGlzLlJlbWFpbmluZyA+PSAzMikgewogICAgICAgICAgICBsZXQgdmFsdWUgPSB0aGlzLmR2LmdldFVpbnQzMihieXRlSW5kZXgpOwogICAgICAgICAgICB2YWx1ZSAmPSAweEZGRkZGRkZGID4+PiBiaXRJbmRleDsKICAgICAgICAgICAgdmFsdWUgPj49IDMyIC0gYml0Q291bnQgLSBiaXRJbmRleDsKICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpcy5QZWVrSW50RmFsbGJhY2soYml0Q291bnQpOwogICAgfQogICAgUGVla0ludEZhbGxiYWNrKGJpdENvdW50KSB7CiAgICAgICAgbGV0IHZhbHVlID0gMDsKICAgICAgICBsZXQgYnl0ZUluZGV4ID0gdGhpcy5Qb3NpdGlvbiAvIDg7CiAgICAgICAgbGV0IGJpdEluZGV4ID0gdGhpcy5Qb3NpdGlvbiAlIDg7CiAgICAgICAgd2hpbGUgKGJpdENvdW50ID4gMCkgewogICAgICAgICAgICBpZiAoYml0SW5kZXggPj0gOCkgewogICAgICAgICAgICAgICAgYml0SW5kZXggPSAwOwogICAgICAgICAgICAgICAgYnl0ZUluZGV4Kys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGV0IGJpdHNUb1JlYWQgPSBNYXRoLm1pbihiaXRDb3VudCwgOCAtIGJpdEluZGV4KTsKICAgICAgICAgICAgbGV0IG1hc2sgPSAweEZGID4+IGJpdEluZGV4OwogICAgICAgICAgICBsZXQgY3VycmVudEJ5dGUgPSAobWFzayAmIHRoaXMuZHYuZ2V0VWludDgoYnl0ZUluZGV4KSkgPj4gKDggLSBiaXRJbmRleCAtIGJpdHNUb1JlYWQpOwogICAgICAgICAgICB2YWx1ZSA9ICh2YWx1ZSA8PCBiaXRzVG9SZWFkKSB8IGN1cnJlbnRCeXRlOwogICAgICAgICAgICBiaXRJbmRleCArPSBiaXRzVG9SZWFkOwogICAgICAgICAgICBiaXRDb3VudCAtPSBiaXRzVG9SZWFkOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdmFsdWU7CiAgICB9Cn0KdmFyIEhDQU9mZnNldEJpYXM7CihmdW5jdGlvbiAoSENBT2Zmc2V0QmlhcykgewogICAgLy8vIDxzdW1tYXJ5PgogICAgLy8vIFNwZWNpZmllcyB0aGUgYmlhcyBvZiBhbiBvZmZzZXQgYmluYXJ5IHZhbHVlLiBBIHBvc2l0aXZlIGJpYXMgY2FuIHJlcHJlc2VudCBvbmUgbW9yZQogICAgLy8vIHBvc2l0aXZlIHZhbHVlIHRoYW4gbmVnYXRpdmUgdmFsdWUsIGFuZCBhIG5lZ2F0aXZlIGJpYXMgY2FuIHJlcHJlc2VudCBvbmUgbW9yZQogICAgLy8vIG5lZ2F0aXZlIHZhbHVlIHRoYW4gcG9zaXRpdmUgdmFsdWUuCiAgICAvLy8gPC9zdW1tYXJ5PgogICAgLy8vIDxyZW1hcmtzPkV4YW1wbGU6CiAgICAvLy8gQSA0LWJpdCBvZmZzZXQgYmluYXJ5IHZhbHVlIHdpdGggYSBwb3NpdGl2ZSBiaWFzIGNhbiBzdG9yZQogICAgLy8vIHRoZSB2YWx1ZXMgOCB0aHJvdWdoIC03IGluY2x1c2l2ZS4KICAgIC8vLyBBIDQtYml0IG9mZnNldCBiaW5hcnkgdmFsdWUgd2l0aCBhIG5lZ2F0aXZlIGJpYXMgY2FuIHN0b3JlCiAgICAvLy8gdGhlIHZhbHVlcyA3IHRocm91Z2ggLTggaW5jbHVzaXZlLjwvcmVtYXJrcz4KICAgIEhDQU9mZnNldEJpYXNbSENBT2Zmc2V0Qmlhc1siUG9zaXRpdmUiXSA9IDFdID0gIlBvc2l0aXZlIjsKICAgIEhDQU9mZnNldEJpYXNbSENBT2Zmc2V0Qmlhc1siTmVnYXRpdmUiXSA9IDBdID0gIk5lZ2F0aXZlIjsKfSkoSENBT2Zmc2V0QmlhcyB8fCAoSENBT2Zmc2V0QmlhcyA9IHt9KSk7CmNsYXNzIEhDQUJpdFdyaXRlciB7CiAgICBjb25zdHJ1Y3RvcihidWZmZXIpIHsKICAgICAgICB0aGlzLlBvc2l0aW9uID0gMDsKICAgICAgICB0aGlzLkJ1ZmZlciA9IGJ1ZmZlcjsKICAgICAgICB0aGlzLmR2ID0gbmV3IERhdGFWaWV3KGJ1ZmZlci5idWZmZXIsIGJ1ZmZlci5ieXRlT2Zmc2V0LCBidWZmZXIuYnl0ZUxlbmd0aCk7CiAgICAgICAgdGhpcy5MZW5ndGhCaXRzID0gYnVmZmVyLmxlbmd0aCAqIDg7CiAgICB9CiAgICBnZXQgUmVtYWluaW5nKCkgeyByZXR1cm4gdGhpcy5MZW5ndGhCaXRzIC0gdGhpcy5Qb3NpdGlvbjsgfQogICAgQWxpZ25Qb3NpdGlvbihtdWx0aXBsZSkgewogICAgICAgIGxldCBuZXdQb3NpdGlvbiA9IEhDQVV0aWxGdW5jLkdldE5leHRNdWx0aXBsZSh0aGlzLlBvc2l0aW9uLCBtdWx0aXBsZSk7CiAgICAgICAgbGV0IGJpdHMgPSBuZXdQb3NpdGlvbiAtIHRoaXMuUG9zaXRpb247CiAgICAgICAgdGhpcy5Xcml0ZSgwLCBiaXRzKTsKICAgIH0KICAgIFdyaXRlKHZhbHVlLCBiaXRDb3VudCkgewogICAgICAgIEhDQVV0aWxGdW5jLkRlYnVnQXNzZXJ0KGJpdENvdW50ID49IDAgJiYgYml0Q291bnQgPD0gMzIpOwogICAgICAgIGlmIChiaXRDb3VudCA+IHRoaXMuUmVtYWluaW5nKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiTm90IGVub3VnaCBiaXRzIGxlZnQgaW4gb3V0cHV0IGJ1ZmZlciIpOwogICAgICAgIH0KICAgICAgICBsZXQgYnl0ZUluZGV4ID0gdGhpcy5Qb3NpdGlvbiAvIDg7CiAgICAgICAgbGV0IGJpdEluZGV4ID0gdGhpcy5Qb3NpdGlvbiAlIDg7CiAgICAgICAgaWYgKGJpdENvdW50IDw9IDkgJiYgdGhpcy5SZW1haW5pbmcgPj0gMTYpIHsKICAgICAgICAgICAgbGV0IG91dFZhbHVlID0gKCh2YWx1ZSA8PCAoMTYgLSBiaXRDb3VudCkpICYgMHhGRkZGKSA+PiBiaXRJbmRleDsKICAgICAgICAgICAgb3V0VmFsdWUgfD0gdGhpcy5kdi5nZXRVaW50MTYoYnl0ZUluZGV4KTsKICAgICAgICAgICAgdGhpcy5kdi5zZXRVaW50MTYoYnl0ZUluZGV4LCBvdXRWYWx1ZSk7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKGJpdENvdW50IDw9IDE3ICYmIHRoaXMuUmVtYWluaW5nID49IDI0KSB7CiAgICAgICAgICAgIGxldCBvdXRWYWx1ZSA9ICgodmFsdWUgPDwgKDI0IC0gYml0Q291bnQpKSAmIDB4RkZGRkZGKSA+PiBiaXRJbmRleDsKICAgICAgICAgICAgb3V0VmFsdWUgfD0gdGhpcy5kdi5nZXRVaW50MTYoYnl0ZUluZGV4KSA8PCA4IHwgdGhpcy5kdi5nZXRVaW50OChieXRlSW5kZXggKyAyKTsKICAgICAgICAgICAgdGhpcy5kdi5zZXRVaW50MTYoYnl0ZUluZGV4LCBvdXRWYWx1ZSA+Pj4gOCk7CiAgICAgICAgICAgIHRoaXMuZHYuc2V0VWludDgoYnl0ZUluZGV4ICsgMiwgb3V0VmFsdWUgJiAweEZGKTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoYml0Q291bnQgPD0gMjUgJiYgdGhpcy5SZW1haW5pbmcgPj0gMzIpIHsKICAgICAgICAgICAgbGV0IG91dFZhbHVlID0gKCgodmFsdWUgPDwgKDMyIC0gYml0Q291bnQpKSAmIDB4RkZGRkZGRkYpID4+PiBiaXRJbmRleCk7CiAgICAgICAgICAgIG91dFZhbHVlIHw9IHRoaXMuZHYuZ2V0VWludDMyKGJ5dGVJbmRleCk7CiAgICAgICAgICAgIHRoaXMuZHYuc2V0VWludDMyKGJ5dGVJbmRleCwgb3V0VmFsdWUpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgdGhpcy5Xcml0ZUZhbGxiYWNrKHZhbHVlLCBiaXRDb3VudCk7CiAgICAgICAgfQogICAgICAgIHRoaXMuUG9zaXRpb24gKz0gYml0Q291bnQ7CiAgICB9CiAgICBXcml0ZUZhbGxiYWNrKHZhbHVlLCBiaXRDb3VudCkgewogICAgICAgIGxldCBieXRlSW5kZXggPSB0aGlzLlBvc2l0aW9uIC8gODsKICAgICAgICBsZXQgYml0SW5kZXggPSB0aGlzLlBvc2l0aW9uICUgODsKICAgICAgICB3aGlsZSAoYml0Q291bnQgPiAwKSB7CiAgICAgICAgICAgIGlmIChiaXRJbmRleCA+PSA4KSB7CiAgICAgICAgICAgICAgICBiaXRJbmRleCA9IDA7CiAgICAgICAgICAgICAgICBieXRlSW5kZXgrKzsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgdG9TaGlmdCA9IDggLSBiaXRJbmRleCAtIGJpdENvdW50OwogICAgICAgICAgICBsZXQgc2hpZnRlZCA9IHRvU2hpZnQgPCAwID8gdmFsdWUgPj4+IC10b1NoaWZ0IDogdmFsdWUgPDwgdG9TaGlmdDsKICAgICAgICAgICAgbGV0IGJpdHNUb1dyaXRlID0gTWF0aC5taW4oYml0Q291bnQsIDggLSBiaXRJbmRleCk7CiAgICAgICAgICAgIGxldCBtYXNrID0gKCgxIDw8IGJpdHNUb1dyaXRlKSAtIDEpIDw8IDggLSBiaXRJbmRleCAtIGJpdHNUb1dyaXRlOwogICAgICAgICAgICBsZXQgb3V0Qnl0ZSA9IHRoaXMuZHYuZ2V0VWludDgoYnl0ZUluZGV4KSAmIH5tYXNrOwogICAgICAgICAgICBvdXRCeXRlIHw9IHNoaWZ0ZWQgJiBtYXNrOwogICAgICAgICAgICB0aGlzLmR2LnNldFVpbnQ4KGJ5dGVJbmRleCwgb3V0Qnl0ZSk7CiAgICAgICAgICAgIGJpdEluZGV4ICs9IGJpdHNUb1dyaXRlOwogICAgICAgICAgICBiaXRDb3VudCAtPSBiaXRzVG9Xcml0ZTsKICAgICAgICB9CiAgICB9Cn0KY2xhc3MgSENBRnJhbWUgewogICAgY29uc3RydWN0b3IoaGNhKSB7CiAgICAgICAgdGhpcy5BY2NlcHRhYmxlTm9pc2VMZXZlbCA9IDA7CiAgICAgICAgdGhpcy5FdmFsdWF0aW9uQm91bmRhcnkgPSAwOwogICAgICAgIHRoaXMuSGNhID0gaGNhOwogICAgICAgIGxldCBjaGFubmVsVHlwZXMgPSBIQ0FGcmFtZS5HZXRDaGFubmVsVHlwZXMoaGNhKTsKICAgICAgICB0aGlzLkNoYW5uZWxzID0gW107CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoY2EuZm9ybWF0LmNoYW5uZWxDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIHRoaXMuQ2hhbm5lbHMucHVzaChuZXcgSENBQ2hhbm5lbCh7CiAgICAgICAgICAgICAgICBUeXBlOiBjaGFubmVsVHlwZXNbaV0sCiAgICAgICAgICAgICAgICBDb2RlZFNjYWxlRmFjdG9yQ291bnQ6IGNoYW5uZWxUeXBlc1tpXSA9PSBIQ0FDaGFubmVsVHlwZS5TdGVyZW9TZWNvbmRhcnkKICAgICAgICAgICAgICAgICAgICA/IGhjYS5jb21wRGVjLkJhc2VCYW5kQ291bnQKICAgICAgICAgICAgICAgICAgICA6IGhjYS5jb21wRGVjLkJhc2VCYW5kQ291bnQgKyBoY2EuY29tcERlYy5TdGVyZW9CYW5kQ291bnQKICAgICAgICAgICAgfSkpOwogICAgICAgIH0KICAgICAgICB0aGlzLkF0aEN1cnZlID0gaGNhLlVzZUF0aEN1cnZlID8gSENBRnJhbWUuU2NhbGVBdGhDdXJ2ZShoY2EuZm9ybWF0LnNhbXBsaW5nUmF0ZSkgOiBuZXcgVWludDhBcnJheShIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWUpOwogICAgfQogICAgc3RhdGljIEdldENoYW5uZWxUeXBlcyhoY2EpIHsKICAgICAgICBsZXQgY2hhbm5lbHNQZXJUcmFjayA9IGhjYS5mb3JtYXQuY2hhbm5lbENvdW50IC8gaGNhLmNvbXBEZWMuVHJhY2tDb3VudDsKICAgICAgICBpZiAoaGNhLmNvbXBEZWMuU3RlcmVvQmFuZENvdW50ID09IDAgfHwgY2hhbm5lbHNQZXJUcmFjayA9PSAxKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgQXJyYXkoOCkuZmlsbChIQ0FDaGFubmVsVHlwZSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IERpc2NyZXRlID0gSENBQ2hhbm5lbFR5cGUuRGlzY3JldGU7CiAgICAgICAgY29uc3QgU3RlcmVvUHJpbWFyeSA9IEhDQUNoYW5uZWxUeXBlLlN0ZXJlb1ByaW1hcnk7CiAgICAgICAgY29uc3QgU3RlcmVvU2Vjb25kYXJ5ID0gSENBQ2hhbm5lbFR5cGUuU3RlcmVvU2Vjb25kYXJ5OwogICAgICAgIHN3aXRjaCAoY2hhbm5lbHNQZXJUcmFjaykgewogICAgICAgICAgICBjYXNlIDI6IHJldHVybiBbU3RlcmVvUHJpbWFyeSwgU3RlcmVvU2Vjb25kYXJ5XTsKICAgICAgICAgICAgY2FzZSAzOiByZXR1cm4gW1N0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeSwgRGlzY3JldGVdOwogICAgICAgICAgICBjYXNlIDQ6IGlmIChoY2EuY29tcERlYy5DaGFubmVsQ29uZmlnICE9IDApCiAgICAgICAgICAgICAgICByZXR1cm4gW1N0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeSwgRGlzY3JldGUsIERpc2NyZXRlXTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgcmV0dXJuIFtTdGVyZW9QcmltYXJ5LCBTdGVyZW9TZWNvbmRhcnksIFN0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeV07CiAgICAgICAgICAgIGNhc2UgNTogaWYgKGhjYS5jb21wRGVjLkNoYW5uZWxDb25maWcgPiAyKQogICAgICAgICAgICAgICAgcmV0dXJuIFtTdGVyZW9QcmltYXJ5LCBTdGVyZW9TZWNvbmRhcnksIERpc2NyZXRlLCBEaXNjcmV0ZSwgRGlzY3JldGVdOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICByZXR1cm4gW1N0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeSwgRGlzY3JldGUsIFN0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeV07CiAgICAgICAgICAgIGNhc2UgNjogcmV0dXJuIFtTdGVyZW9QcmltYXJ5LCBTdGVyZW9TZWNvbmRhcnksIERpc2NyZXRlLCBEaXNjcmV0ZSwgU3RlcmVvUHJpbWFyeSwgU3RlcmVvU2Vjb25kYXJ5XTsKICAgICAgICAgICAgY2FzZSA3OiByZXR1cm4gW1N0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeSwgRGlzY3JldGUsIERpc2NyZXRlLCBTdGVyZW9QcmltYXJ5LCBTdGVyZW9TZWNvbmRhcnksIERpc2NyZXRlXTsKICAgICAgICAgICAgY2FzZSA4OiByZXR1cm4gW1N0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeSwgRGlzY3JldGUsIERpc2NyZXRlLCBTdGVyZW9QcmltYXJ5LCBTdGVyZW9TZWNvbmRhcnksIFN0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeV07CiAgICAgICAgICAgIGRlZmF1bHQ6IHJldHVybiBuZXcgQXJyYXkoY2hhbm5lbHNQZXJUcmFjaykuZmlsbChIQ0FDaGFubmVsVHlwZSk7CiAgICAgICAgfQogICAgfQogICAgLy8vIDxzdW1tYXJ5PgogICAgLy8vIFNjYWxlcyBhbiBBVEggY3VydmUgdG8gdGhlIHNwZWNpZmllZCBmcmVxdWVuY3kuCiAgICAvLy8gPC9zdW1tYXJ5PgogICAgLy8vIDxwYXJhbSBuYW1lPSJmcmVxdWVuY3kiPlRoZSBmcmVxdWVuY3kgdG8gc2NhbGUgdGhlIGN1cnZlIHRvLjwvcGFyYW0+CiAgICAvLy8gPHJldHVybnM+VGhlIHNjYWxlZCBBVEggY3VydmU8L3JldHVybnM+CiAgICAvLy8gPHJlbWFya3M+VGhlIG9yaWdpbmFsIEFUSCBjdXJ2ZSBpcyBmb3IgYSBmcmVxdWVuY3kgb2YgNDE4NTYgSHouPC9yZW1hcmtzPgogICAgc3RhdGljIFNjYWxlQXRoQ3VydmUoZnJlcXVlbmN5KSB7CiAgICAgICAgdmFyIGF0aCA9IG5ldyBVaW50OEFycmF5KEhDQUZyYW1lLlNhbXBsZXNQZXJTdWJGcmFtZSk7CiAgICAgICAgbGV0IGFjYyA9IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGF0aC5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBhY2MgKz0gZnJlcXVlbmN5OwogICAgICAgICAgICBsZXQgaW5kZXggPSBhY2MgPj4gMTM7CiAgICAgICAgICAgIGlmIChpbmRleCA+PSBIQ0FUYWJsZXMuQXRoQ3VydmUubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBhdGhbaV0gPSBIQ0FUYWJsZXMuQXRoQ3VydmVbaW5kZXhdOwogICAgICAgIH0KICAgICAgICBmb3IgKDsgaSA8IGF0aC5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBhdGhbaV0gPSAweGZmOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYXRoOwogICAgfQp9Cl9hID0gSENBRnJhbWU7CkhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lID0gODsKSENBRnJhbWUuU3ViRnJhbWVTYW1wbGVzQml0cyA9IDc7CkhDQUZyYW1lLlNhbXBsZXNQZXJTdWJGcmFtZSA9IDEgPDwgX2EuU3ViRnJhbWVTYW1wbGVzQml0czsKSENBRnJhbWUuU2FtcGxlc1BlckZyYW1lID0gX2EuU3ViZnJhbWVzUGVyRnJhbWUgKiBfYS5TYW1wbGVzUGVyU3ViRnJhbWU7CmNsYXNzIEhDQUNoYW5uZWwgewogICAgY29uc3RydWN0b3IodmFsdWVzKSB7CiAgICAgICAgdGhpcy5UeXBlID0gMDsKICAgICAgICB0aGlzLkNvZGVkU2NhbGVGYWN0b3JDb3VudCA9IDA7CiAgICAgICAgdGhpcy5QY21GbG9hdCA9IEFycmF5LmZyb20oeyBsZW5ndGg6IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lIH0sICgpID0+IG5ldyBGbG9hdDY0QXJyYXkoSENBRnJhbWUuU2FtcGxlc1BlclN1YkZyYW1lKSk7CiAgICAgICAgdGhpcy5TcGVjdHJhID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogSENBRnJhbWUuU3ViZnJhbWVzUGVyRnJhbWUgfSwgKCkgPT4gbmV3IEZsb2F0NjRBcnJheShIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWUpKTsKICAgICAgICB0aGlzLlNjYWxlZFNwZWN0cmEgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiBIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWUgfSwgKCkgPT4gbmV3IEZsb2F0NjRBcnJheShIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZSkpOwogICAgICAgIHRoaXMuUXVhbnRpemVkU3BlY3RyYSA9IEFycmF5LmZyb20oeyBsZW5ndGg6IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lIH0sICgpID0+IG5ldyBJbnQzMkFycmF5KEhDQUZyYW1lLlNhbXBsZXNQZXJTdWJGcmFtZSkpOwogICAgICAgIHRoaXMuR2FpbiA9IG5ldyBGbG9hdDY0QXJyYXkoSENBRnJhbWUuU2FtcGxlc1BlclN1YkZyYW1lKTsKICAgICAgICB0aGlzLkludGVuc2l0eSA9IG5ldyBJbnQzMkFycmF5KEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lKTsKICAgICAgICB0aGlzLkhmclNjYWxlcyA9IG5ldyBJbnQzMkFycmF5KDgpOwogICAgICAgIHRoaXMuSGZyR3JvdXBBdmVyYWdlU3BlY3RyYSA9IG5ldyBGbG9hdDY0QXJyYXkoOCk7CiAgICAgICAgdGhpcy5NZGN0ID0gbmV3IEhDQU1kY3QoSENBRnJhbWUuU3ViRnJhbWVTYW1wbGVzQml0cywgSENBVGFibGVzLk1kY3RXaW5kb3csIE1hdGguc3FydCgyLjAgLyBIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWUpKTsKICAgICAgICB0aGlzLlNjYWxlRmFjdG9ycyA9IG5ldyBJbnQzMkFycmF5KEhDQUZyYW1lLlNhbXBsZXNQZXJTdWJGcmFtZSk7CiAgICAgICAgdGhpcy5SZXNvbHV0aW9uID0gbmV3IEludDMyQXJyYXkoSENBRnJhbWUuU2FtcGxlc1BlclN1YkZyYW1lKTsKICAgICAgICB0aGlzLkhlYWRlckxlbmd0aEJpdHMgPSAwOwogICAgICAgIHRoaXMuU2NhbGVGYWN0b3JEZWx0YUJpdHMgPSAwOwogICAgICAgIGxldCB0ID0gdGhpczsKICAgICAgICBmb3IgKGxldCBrZXkgaW4gdmFsdWVzKSB7CiAgICAgICAgICAgIHRba2V5XSA9IHZhbHVlc1trZXldOwogICAgICAgIH0KICAgIH0KfQp2YXIgSENBQ2hhbm5lbFR5cGU7CihmdW5jdGlvbiAoSENBQ2hhbm5lbFR5cGUpIHsKICAgIEhDQUNoYW5uZWxUeXBlW0hDQUNoYW5uZWxUeXBlWyJEaXNjcmV0ZSJdID0gMF0gPSAiRGlzY3JldGUiOwogICAgSENBQ2hhbm5lbFR5cGVbSENBQ2hhbm5lbFR5cGVbIlN0ZXJlb1ByaW1hcnkiXSA9IDFdID0gIlN0ZXJlb1ByaW1hcnkiOwogICAgSENBQ2hhbm5lbFR5cGVbSENBQ2hhbm5lbFR5cGVbIlN0ZXJlb1NlY29uZGFyeSJdID0gMl0gPSAiU3RlcmVvU2Vjb25kYXJ5IjsKfSkoSENBQ2hhbm5lbFR5cGUgfHwgKEhDQUNoYW5uZWxUeXBlID0ge30pKTsKY2xhc3MgSENBRGVjb2RlciB7CiAgICBzdGF0aWMgRGVjb2RlRnJhbWUoYXVkaW8sIGZyYW1lKSB7CiAgICAgICAgbGV0IHJlYWRlciA9IG5ldyBIQ0FCaXRSZWFkZXIoYXVkaW8pOwogICAgICAgIEhDQVBhY2tpbmcuVW5wYWNrRnJhbWUoZnJhbWUsIHJlYWRlcik7CiAgICAgICAgdGhpcy5EZXF1YW50aXplRnJhbWUoZnJhbWUpOwogICAgICAgIHRoaXMuUmVzdG9yZU1pc3NpbmdCYW5kcyhmcmFtZSk7CiAgICAgICAgdGhpcy5SdW5JbWRjdChmcmFtZSk7CiAgICB9CiAgICBzdGF0aWMgRGVxdWFudGl6ZUZyYW1lKGZyYW1lKSB7CiAgICAgICAgZm9yIChsZXQgY2hhbm5lbCBvZiBmcmFtZS5DaGFubmVscykgewogICAgICAgICAgICB0aGlzLkNhbGN1bGF0ZUdhaW4oY2hhbm5lbCk7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IHNmID0gMDsgc2YgPCBIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZTsgc2YrKykgewogICAgICAgICAgICBmb3IgKGxldCBjaGFubmVsIG9mIGZyYW1lLkNoYW5uZWxzKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBzID0gMDsgcyA8IGNoYW5uZWwuQ29kZWRTY2FsZUZhY3RvckNvdW50OyBzKyspIHsKICAgICAgICAgICAgICAgICAgICBjaGFubmVsLlNwZWN0cmFbc2ZdW3NdID0gY2hhbm5lbC5RdWFudGl6ZWRTcGVjdHJhW3NmXVtzXSAqIGNoYW5uZWwuR2FpbltzXTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIHN0YXRpYyBSZXN0b3JlTWlzc2luZ0JhbmRzKGZyYW1lKSB7CiAgICAgICAgdGhpcy5SZWNvbnN0cnVjdEhpZ2hGcmVxdWVuY3koZnJhbWUpOwogICAgICAgIHRoaXMuQXBwbHlJbnRlbnNpdHlTdGVyZW8oZnJhbWUpOwogICAgfQogICAgc3RhdGljIENhbGN1bGF0ZUdhaW4oY2hhbm5lbCkgewogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhbm5lbC5Db2RlZFNjYWxlRmFjdG9yQ291bnQ7IGkrKykgewogICAgICAgICAgICBjaGFubmVsLkdhaW5baV0gPSBIQ0FUYWJsZXMuRGVxdWFudGl6ZXJTY2FsaW5nVGFibGVbY2hhbm5lbC5TY2FsZUZhY3RvcnNbaV1dICogSENBVGFibGVzLlF1YW50aXplclN0ZXBTaXplW2NoYW5uZWwuUmVzb2x1dGlvbltpXV07CiAgICAgICAgfQogICAgfQogICAgc3RhdGljIFJlY29uc3RydWN0SGlnaEZyZXF1ZW5jeShmcmFtZSkgewogICAgICAgIGxldCBoY2EgPSBmcmFtZS5IY2E7CiAgICAgICAgaWYgKGhjYS5IZnJHcm91cENvdW50ID09IDApCiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAvLyBUaGUgbGFzdCBzcGVjdHJhbCBjb2VmZmljaWVudCBzaG91bGQgYWx3YXlzIGJlIDA7CiAgICAgICAgbGV0IHRvdGFsQmFuZENvdW50ID0gTWF0aC5taW4oaGNhLmNvbXBEZWMuVG90YWxCYW5kQ291bnQsIDEyNyk7CiAgICAgICAgbGV0IGhmclN0YXJ0QmFuZCA9IGhjYS5jb21wRGVjLkJhc2VCYW5kQ291bnQgKyBoY2EuY29tcERlYy5TdGVyZW9CYW5kQ291bnQ7CiAgICAgICAgbGV0IGhmckJhbmRDb3VudCA9IE1hdGgubWluKGhjYS5jb21wRGVjLkhmckJhbmRDb3VudCwgdG90YWxCYW5kQ291bnQgLSBoY2EuY29tcERlYy5IZnJCYW5kQ291bnQpOwogICAgICAgIGZvciAobGV0IGNoYW5uZWwgb2YgZnJhbWUuQ2hhbm5lbHMpIHsKICAgICAgICAgICAgaWYgKGNoYW5uZWwuVHlwZSA9PSBIQ0FDaGFubmVsVHlwZS5TdGVyZW9TZWNvbmRhcnkpCiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgZm9yIChsZXQgZ3JvdXAgPSAwLCBiYW5kID0gMDsgZ3JvdXAgPCBoY2EuSGZyR3JvdXBDb3VudDsgZ3JvdXArKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoY2EuY29tcERlYy5CYW5kc1Blckhmckdyb3VwICYmIGJhbmQgPCBoZnJCYW5kQ291bnQ7IGJhbmQrKywgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IGhpZ2hCYW5kID0gaGZyU3RhcnRCYW5kICsgYmFuZDsKICAgICAgICAgICAgICAgICAgICBsZXQgbG93QmFuZCA9IGhmclN0YXJ0QmFuZCAtIGJhbmQgLSAxOwogICAgICAgICAgICAgICAgICAgIGxldCBpbmRleCA9IGNoYW5uZWwuSGZyU2NhbGVzW2dyb3VwXSAtIGNoYW5uZWwuU2NhbGVGYWN0b3JzW2xvd0JhbmRdICsgNjQ7CiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgc2YgPSAwOyBzZiA8IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lOyBzZisrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNoYW5uZWwuU3BlY3RyYVtzZl1baGlnaEJhbmRdID0gSENBVGFibGVzLlNjYWxlQ29udmVyc2lvblRhYmxlW2luZGV4XSAqIGNoYW5uZWwuU3BlY3RyYVtzZl1bbG93QmFuZF07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgc3RhdGljIEFwcGx5SW50ZW5zaXR5U3RlcmVvKGZyYW1lKSB7CiAgICAgICAgaWYgKGZyYW1lLkhjYS5jb21wRGVjLlN0ZXJlb0JhbmRDb3VudCA8PSAwKQogICAgICAgICAgICByZXR1cm47CiAgICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCBmcmFtZS5DaGFubmVscy5sZW5ndGg7IGMrKykgewogICAgICAgICAgICBpZiAoZnJhbWUuQ2hhbm5lbHNbY10uVHlwZSAhPSBIQ0FDaGFubmVsVHlwZS5TdGVyZW9QcmltYXJ5KQogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIGZvciAobGV0IHNmID0gMDsgc2YgPCBIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZTsgc2YrKykgewogICAgICAgICAgICAgICAgbGV0IGwgPSBmcmFtZS5DaGFubmVsc1tjXS5TcGVjdHJhW3NmXTsKICAgICAgICAgICAgICAgIGxldCByID0gZnJhbWUuQ2hhbm5lbHNbYyArIDFdLlNwZWN0cmFbc2ZdOwogICAgICAgICAgICAgICAgbGV0IHJhdGlvTCA9IEhDQVRhYmxlcy5JbnRlbnNpdHlSYXRpb1RhYmxlW2ZyYW1lLkNoYW5uZWxzW2MgKyAxXS5JbnRlbnNpdHlbc2ZdXTsKICAgICAgICAgICAgICAgIGxldCByYXRpb1IgPSByYXRpb0wgLSAyLjA7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBiID0gZnJhbWUuSGNhLmNvbXBEZWMuQmFzZUJhbmRDb3VudDsgYiA8IGZyYW1lLkhjYS5jb21wRGVjLlRvdGFsQmFuZENvdW50OyBiKyspIHsKICAgICAgICAgICAgICAgICAgICByW2JdID0gbFtiXSAqIHJhdGlvUjsKICAgICAgICAgICAgICAgICAgICBsW2JdICo9IHJhdGlvTDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIHN0YXRpYyBSdW5JbWRjdChmcmFtZSkgewogICAgICAgIGZvciAobGV0IHNmID0gMDsgc2YgPCBIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZTsgc2YrKykgewogICAgICAgICAgICBmb3IgKGxldCBjaGFubmVsIG9mIGZyYW1lLkNoYW5uZWxzKSB7CiAgICAgICAgICAgICAgICBjaGFubmVsLk1kY3QuUnVuSW1kY3QoY2hhbm5lbC5TcGVjdHJhW3NmXSwgY2hhbm5lbC5QY21GbG9hdFtzZl0pOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9CmNsYXNzIEhDQVBhY2tpbmcgewogICAgc3RhdGljIFVucGFja0ZyYW1lKGZyYW1lLCByZWFkZXIpIHsKICAgICAgICBpZiAoIXRoaXMuVW5wYWNrRnJhbWVIZWFkZXIoZnJhbWUsIHJlYWRlcikpCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB0aGlzLlJlYWRTcGVjdHJhbENvZWZmaWNpZW50cyhmcmFtZSwgcmVhZGVyKTsKICAgICAgICByZXR1cm4gdGhpcy5VbnBhY2tpbmdXYXNTdWNjZXNzZnVsKGZyYW1lLCByZWFkZXIpOwogICAgfQogICAgc3RhdGljIFBhY2tGcmFtZShmcmFtZSwgb3V0QnVmZmVyKSB7CiAgICAgICAgdmFyIHdyaXRlciA9IG5ldyBIQ0FCaXRXcml0ZXIob3V0QnVmZmVyKTsKICAgICAgICB3cml0ZXIuV3JpdGUoMHhmZmZmLCAxNik7CiAgICAgICAgd3JpdGVyLldyaXRlKGZyYW1lLkFjY2VwdGFibGVOb2lzZUxldmVsLCA5KTsKICAgICAgICB3cml0ZXIuV3JpdGUoZnJhbWUuRXZhbHVhdGlvbkJvdW5kYXJ5LCA3KTsKICAgICAgICBmb3IgKGxldCBjaGFubmVsIG9mIGZyYW1lLkNoYW5uZWxzKSB7CiAgICAgICAgICAgIHRoaXMuV3JpdGVTY2FsZUZhY3RvcnMod3JpdGVyLCBjaGFubmVsKTsKICAgICAgICAgICAgaWYgKGNoYW5uZWwuVHlwZSA9PSBIQ0FDaGFubmVsVHlwZS5TdGVyZW9TZWNvbmRhcnkpIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgSENBRnJhbWUuU3ViZnJhbWVzUGVyRnJhbWU7IGkrKykgewogICAgICAgICAgICAgICAgICAgIHdyaXRlci5Xcml0ZShjaGFubmVsLkludGVuc2l0eVtpXSwgNCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoZnJhbWUuSGNhLkhmckdyb3VwQ291bnQgPiAwKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZyYW1lLkhjYS5IZnJHcm91cENvdW50OyBpKyspIHsKICAgICAgICAgICAgICAgICAgICB3cml0ZXIuV3JpdGUoY2hhbm5lbC5IZnJTY2FsZXNbaV0sIDYpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IHNmID0gMDsgc2YgPCBIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZTsgc2YrKykgewogICAgICAgICAgICBmb3IgKGxldCBjaGFubmVsIG9mIGZyYW1lLkNoYW5uZWxzKSB7CiAgICAgICAgICAgICAgICB0aGlzLldyaXRlU3BlY3RyYSh3cml0ZXIsIGNoYW5uZWwsIHNmKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB3cml0ZXIuQWxpZ25Qb3NpdGlvbig4KTsKICAgICAgICBmb3IgKGxldCBpID0gd3JpdGVyLlBvc2l0aW9uIC8gODsgaSA8IGZyYW1lLkhjYS5ibG9ja1NpemUgLSAyOyBpKyspIHsKICAgICAgICAgICAgd3JpdGVyLmR2LnNldFVpbnQ4KGksIDApOwogICAgICAgIH0KICAgICAgICB0aGlzLldyaXRlQ2hlY2tzdW0od3JpdGVyLCBvdXRCdWZmZXIpOwogICAgfQogICAgc3RhdGljIENhbGN1bGF0ZVJlc29sdXRpb24oc2NhbGVGYWN0b3IsIG5vaXNlTGV2ZWwpIHsKICAgICAgICBpZiAoc2NhbGVGYWN0b3IgPT0gMCkgewogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICB9CiAgICAgICAgbGV0IGN1cnZlUG9zaXRpb24gPSBub2lzZUxldmVsIC0gKDUgKiBzY2FsZUZhY3RvciA+PiAxKSArIDI7CiAgICAgICAgY3VydmVQb3NpdGlvbiA9IEhDQVV0aWxGdW5jLkNsYW1wKGN1cnZlUG9zaXRpb24sIDAsIDU4KTsKICAgICAgICByZXR1cm4gSENBVGFibGVzLlNjYWxlVG9SZXNvbHV0aW9uQ3VydmVbY3VydmVQb3NpdGlvbl07CiAgICB9CiAgICBzdGF0aWMgVW5wYWNrRnJhbWVIZWFkZXIoZnJhbWUsIHJlYWRlcikgewogICAgICAgIGxldCBzeW5jV29yZCA9IHJlYWRlci5SZWFkSW50KDE2KTsKICAgICAgICBpZiAoc3luY1dvcmQgIT0gMHhmZmZmKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiSW52YWxpZCBmcmFtZSBoZWFkZXIiKTsKICAgICAgICB9CiAgICAgICAgbGV0IGF0aEN1cnZlID0gZnJhbWUuQXRoQ3VydmU7CiAgICAgICAgZnJhbWUuQWNjZXB0YWJsZU5vaXNlTGV2ZWwgPSByZWFkZXIuUmVhZEludCg5KTsKICAgICAgICBmcmFtZS5FdmFsdWF0aW9uQm91bmRhcnkgPSByZWFkZXIuUmVhZEludCg3KTsKICAgICAgICBmb3IgKGxldCBjaGFubmVsIG9mIGZyYW1lLkNoYW5uZWxzKSB7CiAgICAgICAgICAgIGlmICghdGhpcy5SZWFkU2NhbGVGYWN0b3JzKGNoYW5uZWwsIHJlYWRlcikpCiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnJhbWUuRXZhbHVhdGlvbkJvdW5kYXJ5OyBpKyspIHsKICAgICAgICAgICAgICAgIGNoYW5uZWwuUmVzb2x1dGlvbltpXSA9IHRoaXMuQ2FsY3VsYXRlUmVzb2x1dGlvbihjaGFubmVsLlNjYWxlRmFjdG9yc1tpXSwgYXRoQ3VydmVbaV0gKyBmcmFtZS5BY2NlcHRhYmxlTm9pc2VMZXZlbCAtIDEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciAobGV0IGkgPSBmcmFtZS5FdmFsdWF0aW9uQm91bmRhcnk7IGkgPCBjaGFubmVsLkNvZGVkU2NhbGVGYWN0b3JDb3VudDsgaSsrKSB7CiAgICAgICAgICAgICAgICBjaGFubmVsLlJlc29sdXRpb25baV0gPSB0aGlzLkNhbGN1bGF0ZVJlc29sdXRpb24oY2hhbm5lbC5TY2FsZUZhY3RvcnNbaV0sIGF0aEN1cnZlW2ldICsgZnJhbWUuQWNjZXB0YWJsZU5vaXNlTGV2ZWwpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChjaGFubmVsLlR5cGUgPT0gSENBQ2hhbm5lbFR5cGUuU3RlcmVvU2Vjb25kYXJ5KSB7CiAgICAgICAgICAgICAgICB0aGlzLlJlYWRJbnRlbnNpdHkocmVhZGVyLCBjaGFubmVsLkludGVuc2l0eSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoZnJhbWUuSGNhLkhmckdyb3VwQ291bnQgPiAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLlJlYWRIZnJTY2FsZUZhY3RvcnMocmVhZGVyLCBmcmFtZS5IY2EuSGZyR3JvdXBDb3VudCwgY2hhbm5lbC5IZnJTY2FsZXMpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgc3RhdGljIFJlYWRTY2FsZUZhY3RvcnMoY2hhbm5lbCwgcmVhZGVyKSB7CiAgICAgICAgY2hhbm5lbC5TY2FsZUZhY3RvckRlbHRhQml0cyA9IHJlYWRlci5SZWFkSW50KDMpOwogICAgICAgIGlmIChjaGFubmVsLlNjYWxlRmFjdG9yRGVsdGFCaXRzID09IDApIHsKICAgICAgICAgICAgY2hhbm5lbC5TY2FsZUZhY3RvcnMuZmlsbCgwLCAwLCBjaGFubmVsLlNjYWxlRmFjdG9ycy5sZW5ndGgpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKGNoYW5uZWwuU2NhbGVGYWN0b3JEZWx0YUJpdHMgPj0gNikgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoYW5uZWwuQ29kZWRTY2FsZUZhY3RvckNvdW50OyBpKyspIHsKICAgICAgICAgICAgICAgIGNoYW5uZWwuU2NhbGVGYWN0b3JzW2ldID0gcmVhZGVyLlJlYWRJbnQoNik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzLkRlbHRhRGVjb2RlKHJlYWRlciwgY2hhbm5lbC5TY2FsZUZhY3RvckRlbHRhQml0cywgNiwgY2hhbm5lbC5Db2RlZFNjYWxlRmFjdG9yQ291bnQsIGNoYW5uZWwuU2NhbGVGYWN0b3JzKTsKICAgIH0KICAgIHN0YXRpYyBSZWFkSW50ZW5zaXR5KHJlYWRlciwgaW50ZW5zaXR5KSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZTsgaSsrKSB7CiAgICAgICAgICAgIGludGVuc2l0eVtpXSA9IHJlYWRlci5SZWFkSW50KDQpOwogICAgICAgIH0KICAgIH0KICAgIHN0YXRpYyBSZWFkSGZyU2NhbGVGYWN0b3JzKHJlYWRlciwgZ3JvdXBDb3VudCwgaGZyU2NhbGUpIHsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGdyb3VwQ291bnQ7IGkrKykgewogICAgICAgICAgICBoZnJTY2FsZVtpXSA9IHJlYWRlci5SZWFkSW50KDYpOwogICAgICAgIH0KICAgIH0KICAgIHN0YXRpYyBSZWFkU3BlY3RyYWxDb2VmZmljaWVudHMoZnJhbWUsIHJlYWRlcikgewogICAgICAgIGZvciAobGV0IHNmID0gMDsgc2YgPCBIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZTsgc2YrKykgewogICAgICAgICAgICBmb3IgKGxldCBjaGFubmVsIG9mIGZyYW1lLkNoYW5uZWxzKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBzID0gMDsgcyA8IGNoYW5uZWwuQ29kZWRTY2FsZUZhY3RvckNvdW50OyBzKyspIHsKICAgICAgICAgICAgICAgICAgICBsZXQgcmVzb2x1dGlvbiA9IGNoYW5uZWwuUmVzb2x1dGlvbltzXTsKICAgICAgICAgICAgICAgICAgICBsZXQgYml0cyA9IEhDQVRhYmxlcy5RdWFudGl6ZWRTcGVjdHJ1bU1heEJpdHNbcmVzb2x1dGlvbl07CiAgICAgICAgICAgICAgICAgICAgbGV0IGNvZGUgPSByZWFkZXIuUGVla0ludChiaXRzKTsKICAgICAgICAgICAgICAgICAgICBpZiAocmVzb2x1dGlvbiA8IDgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgYml0cyA9IEhDQVRhYmxlcy5RdWFudGl6ZWRTcGVjdHJ1bUJpdHNbcmVzb2x1dGlvbl1bY29kZV07CiAgICAgICAgICAgICAgICAgICAgICAgIGNoYW5uZWwuUXVhbnRpemVkU3BlY3RyYVtzZl1bc10gPSBIQ0FUYWJsZXMuUXVhbnRpemVkU3BlY3RydW1WYWx1ZVtyZXNvbHV0aW9uXVtjb2RlXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlYWQgdGhlIHNpZ24tbWFnbml0dWRlIHZhbHVlLiBUaGUgbG93IGJpdCBpcyB0aGUgc2lnbgogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcXVhbnRpemVkQ29lZmZpY2llbnQgPSAoY29kZSA+PiAxKSAqICgxIC0gKGNvZGUgJSAyICogMikpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocXVhbnRpemVkQ29lZmZpY2llbnQgPT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0cy0tOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNoYW5uZWwuUXVhbnRpemVkU3BlY3RyYVtzZl1bc10gPSBxdWFudGl6ZWRDb2VmZmljaWVudDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLlBvc2l0aW9uICs9IGJpdHM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjaGFubmVsLlNwZWN0cmFbc2ZdLmZpbGwoMCwgY2hhbm5lbC5Db2RlZFNjYWxlRmFjdG9yQ291bnQsIGNoYW5uZWwuQ29kZWRTY2FsZUZhY3RvckNvdW50ICsgMHg4MCAtIGNoYW5uZWwuQ29kZWRTY2FsZUZhY3RvckNvdW50KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIHN0YXRpYyBEZWx0YURlY29kZShyZWFkZXIsIGRlbHRhQml0cywgZGF0YUJpdHMsIGNvdW50LCBvdXRwdXQpIHsKICAgICAgICBvdXRwdXRbMF0gPSByZWFkZXIuUmVhZEludChkYXRhQml0cyk7CiAgICAgICAgbGV0IG1heERlbHRhID0gMSA8PCAoZGVsdGFCaXRzIC0gMSk7CiAgICAgICAgbGV0IG1heFZhbHVlID0gKDEgPDwgZGF0YUJpdHMpIC0gMTsKICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgICAgICAgbGV0IGRlbHRhID0gcmVhZGVyLlJlYWRPZmZzZXRCaW5hcnkoZGVsdGFCaXRzLCBIQ0FPZmZzZXRCaWFzLlBvc2l0aXZlKTsKICAgICAgICAgICAgaWYgKGRlbHRhIDwgbWF4RGVsdGEpIHsKICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IG91dHB1dFtpIC0gMV0gKyBkZWx0YTsKICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA8IDAgfHwgdmFsdWUgPiBtYXhWYWx1ZSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIG91dHB1dFtpXSA9IHZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgb3V0cHV0W2ldID0gcmVhZGVyLlJlYWRJbnQoZGF0YUJpdHMpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgc3RhdGljIFVucGFja2luZ1dhc1N1Y2Nlc3NmdWwoZnJhbWUsIHJlYWRlcikgewogICAgICAgIC8vIDEyOCBsZWZ0b3ZlciBiaXRzIGFmdGVyIHVucGFja2luZyBzaG91bGQgYmUgaGlnaCBlbm91Z2ggdG8gZ2V0IHJpZCBvZiBmYWxzZSBuZWdhdGl2ZXMsCiAgICAgICAgLy8gYW5kIGxvdyBlbm91Z2ggdGhhdCBmYWxzZSBwb3NpdGl2ZXMgd2lsbCBiZSB1bmNvbW1vbi4KICAgICAgICByZXR1cm4gcmVhZGVyLlJlbWFpbmluZyA+PSAxNiAmJiByZWFkZXIuUmVtYWluaW5nIDw9IDEyOAogICAgICAgICAgICB8fCB0aGlzLkZyYW1lRW1wdHkoZnJhbWUpCiAgICAgICAgICAgIHx8IGZyYW1lLkFjY2VwdGFibGVOb2lzZUxldmVsID09IDAgJiYgcmVhZGVyLlJlbWFpbmluZyA+PSAxNjsKICAgIH0KICAgIHN0YXRpYyBGcmFtZUVtcHR5KGZyYW1lKSB7CiAgICAgICAgaWYgKGZyYW1lLkFjY2VwdGFibGVOb2lzZUxldmVsID4gMCkKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIC8vIElmIGFsbCB0aGUgc2NhbGUgZmFjdG9ycyBhcmUgMCwgdGhlIGZyYW1lIGlzIGVtcHR5CiAgICAgICAgZm9yIChsZXQgY2hhbm5lbCBvZiBmcmFtZS5DaGFubmVscykgewogICAgICAgICAgICBpZiAoY2hhbm5lbC5TY2FsZUZhY3RvckRlbHRhQml0cyA+IDApIHsKICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHN0YXRpYyBXcml0ZUNoZWNrc3VtKHdyaXRlciwgaGNhQnVmZmVyKSB7CiAgICAgICAgd3JpdGVyLlBvc2l0aW9uID0gd3JpdGVyLkxlbmd0aEJpdHMgLSAxNjsKICAgICAgICBsZXQgY3JjMTYgPSBIQ0FDcmMxNi5jYWxjKGhjYUJ1ZmZlciwgaGNhQnVmZmVyLmxlbmd0aCAtIDIpOwogICAgICAgIHdyaXRlci5Xcml0ZShjcmMxNiwgMTYpOwogICAgfQogICAgc3RhdGljIFdyaXRlU3BlY3RyYSh3cml0ZXIsIGNoYW5uZWwsIHN1YkZyYW1lKSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGFubmVsLkNvZGVkU2NhbGVGYWN0b3JDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGxldCByZXNvbHV0aW9uID0gY2hhbm5lbC5SZXNvbHV0aW9uW2ldOwogICAgICAgICAgICBsZXQgcXVhbnRpemVkU3BlY3RyYSA9IGNoYW5uZWwuUXVhbnRpemVkU3BlY3RyYVtzdWJGcmFtZV1baV07CiAgICAgICAgICAgIGlmIChyZXNvbHV0aW9uID09IDApCiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgaWYgKHJlc29sdXRpb24gPCA4KSB7CiAgICAgICAgICAgICAgICBsZXQgYml0cyA9IEhDQVRhYmxlcy5RdWFudGl6ZVNwZWN0cnVtQml0c1tyZXNvbHV0aW9uXVtxdWFudGl6ZWRTcGVjdHJhICsgOF07CiAgICAgICAgICAgICAgICB3cml0ZXIuV3JpdGUoSENBVGFibGVzLlF1YW50aXplU3BlY3RydW1WYWx1ZVtyZXNvbHV0aW9uXVtxdWFudGl6ZWRTcGVjdHJhICsgOF0sIGJpdHMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKHJlc29sdXRpb24gPCAxNikgewogICAgICAgICAgICAgICAgbGV0IGJpdHMgPSBIQ0FUYWJsZXMuUXVhbnRpemVkU3BlY3RydW1NYXhCaXRzW3Jlc29sdXRpb25dIC0gMTsKICAgICAgICAgICAgICAgIHdyaXRlci5Xcml0ZShNYXRoLmFicyhxdWFudGl6ZWRTcGVjdHJhKSwgYml0cyk7CiAgICAgICAgICAgICAgICBpZiAocXVhbnRpemVkU3BlY3RyYSAhPSAwKSB7CiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLldyaXRlKHF1YW50aXplZFNwZWN0cmEgPiAwID8gMCA6IDEsIDEpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgc3RhdGljIFdyaXRlU2NhbGVGYWN0b3JzKHdyaXRlciwgY2hhbm5lbCkgewogICAgICAgIGxldCBkZWx0YUJpdHMgPSBjaGFubmVsLlNjYWxlRmFjdG9yRGVsdGFCaXRzOwogICAgICAgIGxldCBzY2FsZXMgPSBjaGFubmVsLlNjYWxlRmFjdG9yczsKICAgICAgICB3cml0ZXIuV3JpdGUoZGVsdGFCaXRzLCAzKTsKICAgICAgICBpZiAoZGVsdGFCaXRzID09IDApCiAgICAgICAgICAgIHJldHVybjsKICAgICAgICBpZiAoZGVsdGFCaXRzID09IDYpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGFubmVsLkNvZGVkU2NhbGVGYWN0b3JDb3VudDsgaSsrKSB7CiAgICAgICAgICAgICAgICB3cml0ZXIuV3JpdGUoc2NhbGVzW2ldLCA2KTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIHdyaXRlci5Xcml0ZShzY2FsZXNbMF0sIDYpOwogICAgICAgIGxldCBtYXhEZWx0YSA9ICgxIDw8IChkZWx0YUJpdHMgLSAxKSkgLSAxOwogICAgICAgIGxldCBlc2NhcGVWYWx1ZSA9ICgxIDw8IGRlbHRhQml0cykgLSAxOwogICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgY2hhbm5lbC5Db2RlZFNjYWxlRmFjdG9yQ291bnQ7IGkrKykgewogICAgICAgICAgICBsZXQgZGVsdGEgPSBzY2FsZXNbaV0gLSBzY2FsZXNbaSAtIDFdOwogICAgICAgICAgICBpZiAoTWF0aC5hYnMoZGVsdGEpID4gbWF4RGVsdGEpIHsKICAgICAgICAgICAgICAgIHdyaXRlci5Xcml0ZShlc2NhcGVWYWx1ZSwgZGVsdGFCaXRzKTsKICAgICAgICAgICAgICAgIHdyaXRlci5Xcml0ZShzY2FsZXNbaV0sIDYpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgd3JpdGVyLldyaXRlKG1heERlbHRhICsgZGVsdGEsIGRlbHRhQml0cyk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9Cn0KY2xhc3MgSENBTWRjdCB7CiAgICBjb25zdHJ1Y3RvcihtZGN0Qml0cywgd2luZG93LCBzY2FsZSA9IDEpIHsKICAgICAgICBIQ0FNZGN0LlNldFRhYmxlcyhtZGN0Qml0cyk7CiAgICAgICAgdGhpcy5NZGN0Qml0cyA9IG1kY3RCaXRzOwogICAgICAgIHRoaXMuTWRjdFNpemUgPSAxIDw8IG1kY3RCaXRzOwogICAgICAgIHRoaXMuU2NhbGUgPSBzY2FsZTsKICAgICAgICBpZiAod2luZG93Lmxlbmd0aCA8IHRoaXMuTWRjdFNpemUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJXaW5kb3cgbXVzdCBiZSBhcyBsb25nIGFzIHRoZSBNRENUIHNpemUuIik7CiAgICAgICAgfQogICAgICAgIHRoaXMuX21kY3RQcmV2aW91cyA9IG5ldyBGbG9hdDY0QXJyYXkodGhpcy5NZGN0U2l6ZSk7CiAgICAgICAgdGhpcy5faW1kY3RQcmV2aW91cyA9IG5ldyBGbG9hdDY0QXJyYXkodGhpcy5NZGN0U2l6ZSk7CiAgICAgICAgdGhpcy5fc2NyYXRjaE1kY3QgPSBuZXcgRmxvYXQ2NEFycmF5KHRoaXMuTWRjdFNpemUpOwogICAgICAgIHRoaXMuX3NjcmF0Y2hEY3QgPSBuZXcgRmxvYXQ2NEFycmF5KHRoaXMuTWRjdFNpemUpOwogICAgICAgIHRoaXMuX2ltZGN0V2luZG93ID0gd2luZG93OwogICAgfQogICAgc3RhdGljIFNldFRhYmxlcyhtYXhCaXRzKSB7CiAgICAgICAgaWYgKG1heEJpdHMgPiB0aGlzLl90YWJsZUJpdHMpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMuX3RhYmxlQml0cyArIDE7IGkgPD0gbWF4Qml0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBsZXQgb3V0ID0gdGhpcy5HZW5lcmF0ZVRyaWdUYWJsZXMoaSk7CiAgICAgICAgICAgICAgICB0aGlzLlNpblRhYmxlcy5wdXNoKG91dC5zaW4pOwogICAgICAgICAgICAgICAgdGhpcy5Db3NUYWJsZXMucHVzaChvdXQuY29zKTsKICAgICAgICAgICAgICAgIHRoaXMuU2h1ZmZsZVRhYmxlcy5wdXNoKHRoaXMuR2VuZXJhdGVTaHVmZmxlVGFibGUoaSkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuX3RhYmxlQml0cyA9IG1heEJpdHM7CiAgICAgICAgfQogICAgfQogICAgUnVuTWRjdChpbnB1dCwgb3V0cHV0KSB7CiAgICAgICAgaWYgKGlucHV0Lmxlbmd0aCA8IHRoaXMuTWRjdFNpemUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJJbnB1dCBtdXN0IGJlIGFzIGxvbmcgYXMgdGhlIE1EQ1Qgc2l6ZS4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPCB0aGlzLk1kY3RTaXplKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiT3V0cHV0IG11c3QgYmUgYXMgbG9uZyBhcyB0aGUgTURDVCBzaXplLiIpOwogICAgICAgIH0KICAgICAgICBsZXQgc2l6ZSA9IHRoaXMuTWRjdFNpemU7CiAgICAgICAgbGV0IGhhbGYgPSAoc2l6ZSA+PiAxKTsKICAgICAgICBsZXQgZGN0SW4gPSB0aGlzLl9zY3JhdGNoTWRjdDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGhhbGY7IGkrKykgewogICAgICAgICAgICBsZXQgYSA9IHRoaXMuX2ltZGN0V2luZG93W2hhbGYgLSBpIC0gMV0gKiAtaW5wdXRbaGFsZiArIGldOwogICAgICAgICAgICBsZXQgYiA9IHRoaXMuX2ltZGN0V2luZG93W2hhbGYgKyBpXSAqIGlucHV0W2hhbGYgLSBpIC0gMV07CiAgICAgICAgICAgIGxldCBjID0gdGhpcy5faW1kY3RXaW5kb3dbaV0gKiB0aGlzLl9tZGN0UHJldmlvdXNbaV07CiAgICAgICAgICAgIGxldCBkID0gdGhpcy5faW1kY3RXaW5kb3dbc2l6ZSAtIGkgLSAxXSAqIHRoaXMuX21kY3RQcmV2aW91c1tzaXplIC0gaSAtIDFdOwogICAgICAgICAgICBkY3RJbltpXSA9IGEgLSBiOwogICAgICAgICAgICBkY3RJbltoYWxmICsgaV0gPSBjIC0gZDsKICAgICAgICB9CiAgICAgICAgdGhpcy5EY3Q0KGRjdEluLCBvdXRwdXQpOwogICAgICAgIHRoaXMuX21kY3RQcmV2aW91cy5zZXQoaW5wdXQsIGlucHV0Lmxlbmd0aCk7CiAgICB9CiAgICBSdW5JbWRjdChpbnB1dCwgb3V0cHV0KSB7CiAgICAgICAgaWYgKGlucHV0Lmxlbmd0aCA8IHRoaXMuTWRjdFNpemUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJJbnB1dCBtdXN0IGJlIGFzIGxvbmcgYXMgdGhlIE1EQ1Qgc2l6ZS4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPCB0aGlzLk1kY3RTaXplKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiT3V0cHV0IG11c3QgYmUgYXMgbG9uZyBhcyB0aGUgTURDVCBzaXplLiIpOwogICAgICAgIH0KICAgICAgICBsZXQgc2l6ZSA9IHRoaXMuTWRjdFNpemU7CiAgICAgICAgbGV0IGhhbGYgPSAoc2l6ZSA+PiAxKTsKICAgICAgICBsZXQgZGN0T3V0ID0gdGhpcy5fc2NyYXRjaE1kY3Q7CiAgICAgICAgdGhpcy5EY3Q0KGlucHV0LCBkY3RPdXQpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGFsZjsgaSsrKSB7CiAgICAgICAgICAgIG91dHB1dFtpXSA9IHRoaXMuX2ltZGN0V2luZG93W2ldICogZGN0T3V0W2kgKyBoYWxmXSArIHRoaXMuX2ltZGN0UHJldmlvdXNbaV07CiAgICAgICAgICAgIG91dHB1dFtpICsgaGFsZl0gPSB0aGlzLl9pbWRjdFdpbmRvd1tpICsgaGFsZl0gKiAtZGN0T3V0W3NpemUgLSAxIC0gaV0gLSB0aGlzLl9pbWRjdFByZXZpb3VzW2kgKyBoYWxmXTsKICAgICAgICAgICAgdGhpcy5faW1kY3RQcmV2aW91c1tpXSA9IHRoaXMuX2ltZGN0V2luZG93W3NpemUgLSAxIC0gaV0gKiAtZGN0T3V0W2hhbGYgLSBpIC0gMV07CiAgICAgICAgICAgIHRoaXMuX2ltZGN0UHJldmlvdXNbaSArIGhhbGZdID0gdGhpcy5faW1kY3RXaW5kb3dbaGFsZiAtIGkgLSAxXSAqIGRjdE91dFtpXTsKICAgICAgICB9CiAgICB9CiAgICAvLy8gPHN1bW1hcnk+CiAgICAvLy8gRG9lcyBhIFR5cGUtNCBEQ1QuCiAgICAvLy8gPC9zdW1tYXJ5PgogICAgLy8vIDxwYXJhbSBuYW1lPSJpbnB1dCI+VGhlIGlucHV0IGFycmF5IGNvbnRhaW5pbmcgdGhlIHRpbWUgb3IgZnJlcXVlbmN5LWRvbWFpbiBzYW1wbGVzPC9wYXJhbT4KICAgIC8vLyA8cGFyYW0gbmFtZT0ib3V0cHV0Ij5UaGUgb3V0cHV0IGFycmF5IHRoYXQgd2lsbCBjb250YWluIHRoZSB0cmFuc2Zvcm1lZCB0aW1lIG9yIGZyZXF1ZW5jeS1kb21haW4gc2FtcGxlczwvcGFyYW0+CiAgICBEY3Q0KGlucHV0LCBvdXRwdXQpIHsKICAgICAgICBsZXQgc2h1ZmZsZVRhYmxlID0gSENBTWRjdC5TaHVmZmxlVGFibGVzW3RoaXMuTWRjdEJpdHNdOwogICAgICAgIGxldCBzaW5UYWJsZSA9IEhDQU1kY3QuU2luVGFibGVzW3RoaXMuTWRjdEJpdHNdOwogICAgICAgIGxldCBjb3NUYWJsZSA9IEhDQU1kY3QuQ29zVGFibGVzW3RoaXMuTWRjdEJpdHNdOwogICAgICAgIGxldCBkY3RUZW1wID0gdGhpcy5fc2NyYXRjaERjdDsKICAgICAgICBsZXQgc2l6ZSA9IHRoaXMuTWRjdFNpemU7CiAgICAgICAgbGV0IGxhc3RJbmRleCA9IHNpemUgLSAxOwogICAgICAgIGxldCBoYWxmU2l6ZSA9IChzaXplID4+IDEpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGFsZlNpemU7IGkrKykgewogICAgICAgICAgICBsZXQgaTIgPSBpICogMjsKICAgICAgICAgICAgbGV0IGEgPSBpbnB1dFtpMl07CiAgICAgICAgICAgIGxldCBiID0gaW5wdXRbbGFzdEluZGV4IC0gaTJdOwogICAgICAgICAgICBsZXQgc2luID0gc2luVGFibGVbaV07CiAgICAgICAgICAgIGxldCBjb3MgPSBjb3NUYWJsZVtpXTsKICAgICAgICAgICAgZGN0VGVtcFtpMl0gPSBhICogY29zICsgYiAqIHNpbjsKICAgICAgICAgICAgZGN0VGVtcFtpMiArIDFdID0gYSAqIHNpbiAtIGIgKiBjb3M7CiAgICAgICAgfQogICAgICAgIGxldCBzdGFnZUNvdW50ID0gdGhpcy5NZGN0Qml0cyAtIDE7CiAgICAgICAgZm9yIChsZXQgc3RhZ2UgPSAwOyBzdGFnZSA8IHN0YWdlQ291bnQ7IHN0YWdlKyspIHsKICAgICAgICAgICAgbGV0IGJsb2NrQ291bnQgPSAxIDw8IHN0YWdlOwogICAgICAgICAgICBsZXQgYmxvY2tTaXplQml0cyA9IHN0YWdlQ291bnQgLSBzdGFnZTsKICAgICAgICAgICAgbGV0IGJsb2NrSGFsZlNpemVCaXRzID0gYmxvY2tTaXplQml0cyAtIDE7CiAgICAgICAgICAgIGxldCBibG9ja1NpemUgPSAxIDw8IGJsb2NrU2l6ZUJpdHM7CiAgICAgICAgICAgIGxldCBibG9ja0hhbGZTaXplID0gMSA8PCBibG9ja0hhbGZTaXplQml0czsKICAgICAgICAgICAgc2luVGFibGUgPSBIQ0FNZGN0LlNpblRhYmxlc1tibG9ja0hhbGZTaXplQml0c107CiAgICAgICAgICAgIGNvc1RhYmxlID0gSENBTWRjdC5Db3NUYWJsZXNbYmxvY2tIYWxmU2l6ZUJpdHNdOwogICAgICAgICAgICBmb3IgKGxldCBibG9jayA9IDA7IGJsb2NrIDwgYmxvY2tDb3VudDsgYmxvY2srKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBibG9ja0hhbGZTaXplOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICBsZXQgZnJvbnRQb3MgPSAoYmxvY2sgKiBibG9ja1NpemUgKyBpKSAqIDI7CiAgICAgICAgICAgICAgICAgICAgbGV0IGJhY2tQb3MgPSBmcm9udFBvcyArIGJsb2NrU2l6ZTsKICAgICAgICAgICAgICAgICAgICBsZXQgYSA9IGRjdFRlbXBbZnJvbnRQb3NdIC0gZGN0VGVtcFtiYWNrUG9zXTsKICAgICAgICAgICAgICAgICAgICBsZXQgYiA9IGRjdFRlbXBbZnJvbnRQb3MgKyAxXSAtIGRjdFRlbXBbYmFja1BvcyArIDFdOwogICAgICAgICAgICAgICAgICAgIGxldCBzaW4gPSBzaW5UYWJsZVtpXTsKICAgICAgICAgICAgICAgICAgICBsZXQgY29zID0gY29zVGFibGVbaV07CiAgICAgICAgICAgICAgICAgICAgZGN0VGVtcFtmcm9udFBvc10gKz0gZGN0VGVtcFtiYWNrUG9zXTsKICAgICAgICAgICAgICAgICAgICBkY3RUZW1wW2Zyb250UG9zICsgMV0gKz0gZGN0VGVtcFtiYWNrUG9zICsgMV07CiAgICAgICAgICAgICAgICAgICAgZGN0VGVtcFtiYWNrUG9zXSA9IGEgKiBjb3MgKyBiICogc2luOwogICAgICAgICAgICAgICAgICAgIGRjdFRlbXBbYmFja1BvcyArIDFdID0gYSAqIHNpbiAtIGIgKiBjb3M7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLk1kY3RTaXplOyBpKyspIHsKICAgICAgICAgICAgb3V0cHV0W2ldID0gZGN0VGVtcFtzaHVmZmxlVGFibGVbaV1dICogdGhpcy5TY2FsZTsKICAgICAgICB9CiAgICB9CiAgICBzdGF0aWMgR2VuZXJhdGVUcmlnVGFibGVzKHNpemVCaXRzKSB7CiAgICAgICAgbGV0IHNpemUgPSAxIDw8IHNpemVCaXRzOwogICAgICAgIGxldCBvdXQgPSB7CiAgICAgICAgICAgIHNpbjogbmV3IEZsb2F0NjRBcnJheShzaXplKSwKICAgICAgICAgICAgY29zOiBuZXcgRmxvYXQ2NEFycmF5KHNpemUpCiAgICAgICAgfTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykgewogICAgICAgICAgICBsZXQgdmFsdWUgPSBNYXRoLlBJICogKDQgKiBpICsgMSkgLyAoNCAqIHNpemUpOwogICAgICAgICAgICBvdXQuc2luW2ldID0gTWF0aC5zaW4odmFsdWUpOwogICAgICAgICAgICBvdXQuY29zW2ldID0gTWF0aC5jb3ModmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gb3V0OwogICAgfQogICAgc3RhdGljIEdlbmVyYXRlU2h1ZmZsZVRhYmxlKHNpemVCaXRzKSB7CiAgICAgICAgbGV0IHNpemUgPSAxIDw8IHNpemVCaXRzOwogICAgICAgIHZhciB0YWJsZSA9IG5ldyBJbnQzMkFycmF5KHNpemUpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CiAgICAgICAgICAgIHRhYmxlW2ldID0gSENBVXRpbEZ1bmMuU2lnbmVkQml0UmV2ZXJzZTMyVHJ1bmMoaSBeIChpID4+IDEpLCBzaXplQml0cyk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0YWJsZTsKICAgIH0KICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgVW51c2VkTWVtYmVyLkxvY2FsCiAgICAvLy8gPHN1bW1hcnk+CiAgICAvLy8gRG9lcyBhIFR5cGUtNCBEQ1QuIEludGVuZGVkIGZvciByZWZlcmVuY2UuCiAgICAvLy8gPC9zdW1tYXJ5PgogICAgLy8vIDxwYXJhbSBuYW1lPSJpbnB1dCI+VGhlIGlucHV0IGFycmF5IGNvbnRhaW5pbmcgdGhlIHRpbWUgb3IgZnJlcXVlbmN5LWRvbWFpbiBzYW1wbGVzPC9wYXJhbT4KICAgIC8vLyA8cGFyYW0gbmFtZT0ib3V0cHV0Ij5UaGUgb3V0cHV0IGFycmF5IHRoYXQgd2lsbCBjb250YWluIHRoZSB0cmFuc2Zvcm1lZCB0aW1lIG9yIGZyZXF1ZW5jeS1kb21haW4gc2FtcGxlczwvcGFyYW0+CiAgICBEY3Q0U2xvdyhpbnB1dCwgb3V0cHV0KSB7CiAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCB0aGlzLk1kY3RTaXplOyBrKyspIHsKICAgICAgICAgICAgbGV0IHNhbXBsZSA9IDA7CiAgICAgICAgICAgIGZvciAobGV0IG4gPSAwOyBuIDwgdGhpcy5NZGN0U2l6ZTsgbisrKSB7CiAgICAgICAgICAgICAgICBsZXQgYW5nbGUgPSBNYXRoLlBJIC8gdGhpcy5NZGN0U2l6ZSAqIChrICsgMC41KSAqIChuICsgMC41KTsKICAgICAgICAgICAgICAgIHNhbXBsZSArPSBNYXRoLmNvcyhhbmdsZSkgKiBpbnB1dFtuXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvdXRwdXRba10gPSBzYW1wbGUgKiB0aGlzLlNjYWxlOwogICAgICAgIH0KICAgIH0KfQpIQ0FNZGN0Ll90YWJsZUJpdHMgPSAtMTsKSENBTWRjdC5TaW5UYWJsZXMgPSBbXTsKSENBTWRjdC5Db3NUYWJsZXMgPSBbXTsKSENBTWRjdC5TaHVmZmxlVGFibGVzID0gW107CmNsYXNzIEhDQVRhYmxlcyB7CiAgICBzdGF0aWMgaXNMaXR0bGVFbmRpYW4oKSB7CiAgICAgICAgbGV0IHRlc3QgPSBuZXcgRmxvYXQ2NEFycmF5KFsxLjBdKTsKICAgICAgICBsZXQgZHYgPSBuZXcgRGF0YVZpZXcodGVzdC5idWZmZXIpOwogICAgICAgIGlmIChkdi5nZXRVaW50MzIoMCkgIT0gMCkKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgc3RhdGljIGFkYXB0RW5kaWFubmVzczY0MzIoYSkgewogICAgICAgIGlmIChhLmJ5dGVMZW5ndGggJSA4ICE9IDApCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIGlmICghdGhpcy5pc0xpdHRsZUVuZGlhbigpKSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkgKz0gMikgewogICAgICAgICAgICAgICAgbGV0IHRlbXAgPSBhW2ldOwogICAgICAgICAgICAgICAgYVtpXSA9IGFbaSArIDFdOwogICAgICAgICAgICAgICAgYVtpICsgMV0gPSB0ZW1wOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBhOwogICAgfQp9Cl9iID0gSENBVGFibGVzOwpIQ0FUYWJsZXMuUXVhbnRpemVTcGVjdHJ1bUJpdHMgPSBbCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMiwgMHgwMSwgMHgwMiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMywgMHgwMiwgMHgwMiwgMHgwMiwgMHgwMywgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMywgMHgwMywgMHgwMywgMHgwMiwgMHgwMywgMHgwMywgMHgwMywgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNCwgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwNCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwNCwgMHgwNCwgMHgwNCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwMywgMHgwMywgMHgwMywgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwMywgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNAogICAgXSksCl07CkhDQVRhYmxlcy5RdWFudGl6ZVNwZWN0cnVtVmFsdWUgPSBbCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMywgMHgwMCwgMHgwMiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNywgMHgwMiwgMHgwMCwgMHgwMSwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNywgMHgwNSwgMHgwMywgMHgwMCwgMHgwMiwgMHgwNCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwRiwgMHgwNiwgMHgwNCwgMHgwMiwgMHgwMCwgMHgwMSwgMHgwMywgMHgwNSwgMHgwRSwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwRiwgMHgwRCwgMHgwQiwgMHgwNCwgMHgwMiwgMHgwMCwgMHgwMSwgMHgwMywgMHgwQSwgMHgwQywgMHgwRSwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwRiwgMHgwRCwgMHgwQiwgMHgwOSwgMHgwNywgMHgwMiwgMHgwMCwgMHgwMSwgMHgwNiwgMHgwOCwgMHgwQSwgMHgwQywgMHgwRSwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwRiwgMHgwRCwgMHgwQiwgMHgwOSwgMHgwNywgMHgwNSwgMHgwMywgMHgwMCwgMHgwMiwgMHgwNCwgMHgwNiwgMHgwOCwgMHgwQSwgMHgwQywgMHgwRQogICAgXSksCl07CkhDQVRhYmxlcy5RdWFudGl6ZWRTcGVjdHJ1bUJpdHMgPSBbCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMSwgMHgwMSwgMHgwMiwgMHgwMiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMiwgMHgwMiwgMHgwMiwgMHgwMiwgMHgwMiwgMHgwMiwgMHgwMywgMHgwMywgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMiwgMHgwMiwgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwNCwgMHgwNAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwMywgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNAogICAgXSksCiAgICBuZXcgVWludDhBcnJheShbCiAgICAgICAgMHgwMywgMHgwMywgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNAogICAgXSksCl07CkhDQVRhYmxlcy5RdWFudGl6ZWRTcGVjdHJ1bU1heEJpdHMgPSBuZXcgVWludDhBcnJheShbCiAgICAweDAwLCAweDAyLCAweDAzLCAweDAzLCAweDA0LCAweDA0LCAweDA0LCAweDA0LCAweDA1LCAweDA2LCAweDA3LCAweDA4LCAweDA5LCAweDBBLCAweDBCLCAweDBDCl0pOwpIQ0FUYWJsZXMuUXVhbnRpemVkU3BlY3RydW1WYWx1ZSA9IFsKICAgIG5ldyBJbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IEludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMSwgMHhGRiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgSW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAwLCAweDAxLCAweDAxLCAweEZGLCAweEZGLCAweDAyLCAweEZFLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwCiAgICBdKSwKICAgIG5ldyBJbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDEsIDB4RkYsIDB4MDIsIDB4RkUsIDB4MDMsIDB4RkQsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IEludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMSwgMHgwMSwgMHhGRiwgMHhGRiwgMHgwMiwgMHgwMiwgMHhGRSwgMHhGRSwgMHgwMywgMHgwMywgMHhGRCwgMHhGRCwgMHgwNCwgMHhGQwogICAgXSksCiAgICBuZXcgSW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAwLCAweDAxLCAweDAxLCAweEZGLCAweEZGLCAweDAyLCAweDAyLCAweEZFLCAweEZFLCAweDAzLCAweEZELCAweDA0LCAweEZDLCAweDA1LCAweEZCCiAgICBdKSwKICAgIG5ldyBJbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDEsIDB4MDEsIDB4RkYsIDB4RkYsIDB4MDIsIDB4RkUsIDB4MDMsIDB4RkQsIDB4MDQsIDB4RkMsIDB4MDUsIDB4RkIsIDB4MDYsIDB4RkEKICAgIF0pLAogICAgbmV3IEludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMSwgMHhGRiwgMHgwMiwgMHhGRSwgMHgwMywgMHhGRCwgMHgwNCwgMHhGQywgMHgwNSwgMHhGQiwgMHgwNiwgMHhGQSwgMHgwNywgMHhGOQogICAgXSksCl07CkhDQVRhYmxlcy5TY2FsZVRvUmVzb2x1dGlvbkN1cnZlID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgMHgwRiwgMHgwRSwgMHgwRSwgMHgwRSwgMHgwRSwgMHgwRSwgMHgwRSwgMHgwRCwgMHgwRCwgMHgwRCwgMHgwRCwgMHgwRCwgMHgwRCwgMHgwQywgMHgwQywgMHgwQywKICAgIDB4MEMsIDB4MEMsIDB4MEMsIDB4MEIsIDB4MEIsIDB4MEIsIDB4MEIsIDB4MEIsIDB4MEIsIDB4MEEsIDB4MEEsIDB4MEEsIDB4MEEsIDB4MEEsIDB4MEEsIDB4MEEsCiAgICAweDA5LCAweDA5LCAweDA5LCAweDA5LCAweDA5LCAweDA5LCAweDA4LCAweDA4LCAweDA4LCAweDA4LCAweDA4LCAweDA4LCAweDA3LCAweDA2LCAweDA2LCAweDA1LAogICAgMHgwNCwgMHgwNCwgMHgwNCwgMHgwMywgMHgwMywgMHgwMywgMHgwMiwgMHgwMiwgMHgwMiwgMHgwMiwgMHgwMQpdKTsKSENBVGFibGVzLkF0aEN1cnZlID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgMHg3OCwgMHg1RiwgMHg1NiwgMHg1MSwgMHg0RSwgMHg0QywgMHg0QiwgMHg0OSwgMHg0OCwgMHg0OCwgMHg0NywgMHg0NiwgMHg0NiwgMHg0NSwgMHg0NSwgMHg0NSwKICAgIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDMsIDB4NDMsIDB4NDMsIDB4NDMsIDB4NDMsIDB4NDMsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsCiAgICAweDQyLCAweDQyLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQwLCAweDQwLCAweDQwLCAweDQwLAogICAgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwKICAgIDB4M0YsIDB4M0YsIDB4M0YsIDB4M0UsIDB4M0UsIDB4M0UsIDB4M0UsIDB4M0UsIDB4M0UsIDB4M0QsIDB4M0QsIDB4M0QsIDB4M0QsIDB4M0QsIDB4M0QsIDB4M0QsCiAgICAweDNDLCAweDNDLCAweDNDLCAweDNDLCAweDNDLCAweDNDLCAweDNDLCAweDNDLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLAogICAgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwKICAgIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0MsCiAgICAweDNELCAweDNELCAweDNELCAweDNELCAweDNELCAweDNELCAweDNELCAweDNELCAweDNFLCAweDNFLCAweDNFLCAweDNFLCAweDNFLCAweDNFLCAweDNFLCAweDNGLAogICAgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwKICAgIDB4M0YsIDB4M0YsIDB4M0YsIDB4M0YsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsCiAgICAweDQwLCAweDQwLCAweDQwLCAweDQwLCAweDQwLCAweDQwLCAweDQwLCAweDQwLCAweDQwLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLAogICAgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwKICAgIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsCiAgICAweDQyLCAweDQyLCAweDQyLCAweDQyLCAweDQyLCAweDQyLCAweDQyLCAweDQyLCAweDQyLCAweDQyLCAweDQyLCAweDQyLCAweDQyLCAweDQzLCAweDQzLCAweDQzLAogICAgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0NCwgMHg0NCwKICAgIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDQsIDB4NDUsIDB4NDUsIDB4NDUsIDB4NDUsCiAgICAweDQ1LCAweDQ1LCAweDQ1LCAweDQ1LCAweDQ1LCAweDQ1LCAweDQ1LCAweDQ1LCAweDQ2LCAweDQ2LCAweDQ2LCAweDQ2LCAweDQ2LCAweDQ2LCAweDQ2LCAweDQ2LAogICAgMHg0NiwgMHg0NiwgMHg0NywgMHg0NywgMHg0NywgMHg0NywgMHg0NywgMHg0NywgMHg0NywgMHg0NywgMHg0NywgMHg0NywgMHg0OCwgMHg0OCwgMHg0OCwgMHg0OCwKICAgIDB4NDgsIDB4NDgsIDB4NDgsIDB4NDgsIDB4NDksIDB4NDksIDB4NDksIDB4NDksIDB4NDksIDB4NDksIDB4NDksIDB4NDksIDB4NEEsIDB4NEEsIDB4NEEsIDB4NEEsCiAgICAweDRBLCAweDRBLCAweDRBLCAweDRBLCAweDRCLCAweDRCLCAweDRCLCAweDRCLCAweDRCLCAweDRCLCAweDRCLCAweDRDLCAweDRDLCAweDRDLCAweDRDLCAweDRDLAogICAgMHg0QywgMHg0RCwgMHg0RCwgMHg0RCwgMHg0RCwgMHg0RCwgMHg0RCwgMHg0RSwgMHg0RSwgMHg0RSwgMHg0RSwgMHg0RSwgMHg0RSwgMHg0RiwgMHg0RiwgMHg0RiwKICAgIDB4NEYsIDB4NEYsIDB4NEYsIDB4NTAsIDB4NTAsIDB4NTAsIDB4NTAsIDB4NTAsIDB4NTEsIDB4NTEsIDB4NTEsIDB4NTEsIDB4NTEsIDB4NTIsIDB4NTIsIDB4NTIsCiAgICAweDUyLCAweDUyLCAweDUzLCAweDUzLCAweDUzLCAweDUzLCAweDU0LCAweDU0LCAweDU0LCAweDU0LCAweDU0LCAweDU1LCAweDU1LCAweDU1LCAweDU1LCAweDU2LAogICAgMHg1NiwgMHg1NiwgMHg1NiwgMHg1NywgMHg1NywgMHg1NywgMHg1NywgMHg1NywgMHg1OCwgMHg1OCwgMHg1OCwgMHg1OSwgMHg1OSwgMHg1OSwgMHg1OSwgMHg1QSwKICAgIDB4NUEsIDB4NUEsIDB4NUEsIDB4NUIsIDB4NUIsIDB4NUIsIDB4NUIsIDB4NUMsIDB4NUMsIDB4NUMsIDB4NUQsIDB4NUQsIDB4NUQsIDB4NUQsIDB4NUUsIDB4NUUsCiAgICAweDVFLCAweDVGLCAweDVGLCAweDVGLCAweDYwLCAweDYwLCAweDYwLCAweDYxLCAweDYxLCAweDYxLCAweDYxLCAweDYyLCAweDYyLCAweDYyLCAweDYzLCAweDYzLAogICAgMHg2MywgMHg2NCwgMHg2NCwgMHg2NCwgMHg2NSwgMHg2NSwgMHg2NiwgMHg2NiwgMHg2NiwgMHg2NywgMHg2NywgMHg2NywgMHg2OCwgMHg2OCwgMHg2OCwgMHg2OSwKICAgIDB4NjksIDB4NkEsIDB4NkEsIDB4NkEsIDB4NkIsIDB4NkIsIDB4NkIsIDB4NkMsIDB4NkMsIDB4NkQsIDB4NkQsIDB4NkQsIDB4NkUsIDB4NkUsIDB4NkYsIDB4NkYsCiAgICAweDcwLCAweDcwLCAweDcwLCAweDcxLCAweDcxLCAweDcyLCAweDcyLCAweDczLCAweDczLCAweDczLCAweDc0LCAweDc0LCAweDc1LCAweDc1LCAweDc2LCAweDc2LAogICAgMHg3NywgMHg3NywgMHg3OCwgMHg3OCwgMHg3OCwgMHg3OSwgMHg3OSwgMHg3QSwgMHg3QSwgMHg3QiwgMHg3QiwgMHg3QywgMHg3QywgMHg3RCwgMHg3RCwgMHg3RSwKICAgIDB4N0UsIDB4N0YsIDB4N0YsIDB4ODAsIDB4ODAsIDB4ODEsIDB4ODEsIDB4ODIsIDB4ODMsIDB4ODMsIDB4ODQsIDB4ODQsIDB4ODUsIDB4ODUsIDB4ODYsIDB4ODYsCiAgICAweDg3LCAweDg4LCAweDg4LCAweDg5LCAweDg5LCAweDhBLCAweDhBLCAweDhCLCAweDhDLCAweDhDLCAweDhELCAweDhELCAweDhFLCAweDhGLCAweDhGLCAweDkwLAogICAgMHg5MCwgMHg5MSwgMHg5MiwgMHg5MiwgMHg5MywgMHg5NCwgMHg5NCwgMHg5NSwgMHg5NSwgMHg5NiwgMHg5NywgMHg5NywgMHg5OCwgMHg5OSwgMHg5OSwgMHg5QSwKICAgIDB4OUIsIDB4OUIsIDB4OUMsIDB4OUQsIDB4OUQsIDB4OUUsIDB4OUYsIDB4QTAsIDB4QTAsIDB4QTEsIDB4QTIsIDB4QTIsIDB4QTMsIDB4QTQsIDB4QTUsIDB4QTUsCiAgICAweEE2LCAweEE3LCAweEE3LCAweEE4LCAweEE5LCAweEFBLCAweEFBLCAweEFCLCAweEFDLCAweEFELCAweEFFLCAweEFFLCAweEFGLCAweEIwLCAweEIxLCAweEIxLAogICAgMHhCMiwgMHhCMywgMHhCNCwgMHhCNSwgMHhCNiwgMHhCNiwgMHhCNywgMHhCOCwgMHhCOSwgMHhCQSwgMHhCQSwgMHhCQiwgMHhCQywgMHhCRCwgMHhCRSwgMHhCRiwKICAgIDB4QzAsIDB4QzEsIDB4QzEsIDB4QzIsIDB4QzMsIDB4QzQsIDB4QzUsIDB4QzYsIDB4QzcsIDB4QzgsIDB4QzksIDB4QzksIDB4Q0EsIDB4Q0IsIDB4Q0MsIDB4Q0QsCiAgICAweENFLCAweENGLCAweEQwLCAweEQxLCAweEQyLCAweEQzLCAweEQ0LCAweEQ1LCAweEQ2LCAweEQ3LCAweEQ4LCAweEQ5LCAweERBLCAweERCLCAweERDLCAweERELAogICAgMHhERSwgMHhERiwgMHhFMCwgMHhFMSwgMHhFMiwgMHhFMywgMHhFNCwgMHhFNSwgMHhFNiwgMHhFNywgMHhFOCwgMHhFOSwgMHhFQSwgMHhFQiwgMHhFRCwgMHhFRSwKICAgIDB4RUYsIDB4RjAsIDB4RjEsIDB4RjIsIDB4RjMsIDB4RjQsIDB4RjUsIDB4RjcsIDB4RjgsIDB4RjksIDB4RkEsIDB4RkIsIDB4RkMsIDB4RkQKXSk7CkhDQVRhYmxlcy5NZGN0V2luZG93ID0gbmV3IEZsb2F0NjRBcnJheShfYi5hZGFwdEVuZGlhbm5lc3M2NDMyKG5ldyBVaW50MzJBcnJheShbCiAgICAweDAwMDAwMDAwLCAweDNGNDZBMDlFLCAweDAwMDAwMDAwLCAweDNGNjAzMDc3LCAweDAwMDAwMDAwLCAweDNGNkUxOEE3LCAweDAwMDAwMDAwLCAweDNGNzc3MjRELAogICAgMHgyMDAwMDAwMCwgMHgzRjgwOTUwMSwgMHgwMDAwMDAwMCwgMHgzRjg2MTA0MCwgMHg4MDAwMDAwMCwgMHgzRjhDMjUwOSwgMHhFMDAwMDAwMCwgMHgzRjkxNjdFMiwKICAgIDB4NDAwMDAwMDAsIDB4M0Y5NTA3MzIsIDB4QTAwMDAwMDAsIDB4M0Y5OEVGRjcsIDB4MDAwMDAwMDAsIDB4M0Y5RDIyMjIsIDB4QTAwMDAwMDAsIDB4M0ZBMENFRjksCiAgICAweDgwMDAwMDAwLCAweDNGQTMzMUY4LCAweDgwMDAwMDAwLCAweDNGQTVCQTZCLCAweDYwMDAwMDAwLCAweDNGQTg2OEM4LCAweDIwMDAwMDAwLCAweDNGQUIzRDk4LAogICAgMHgwMDAwMDAwMCwgMHgzRkFFMzk3NSwgMHhDMDAwMDAwMCwgMHgzRkIwQUU4MywgMHg2MDAwMDAwMCwgMHgzRkIyNTQ4MiwgMHg4MDAwMDAwMCwgMHgzRkI0MEYxNiwKICAgIDB4NDAwMDAwMDAsIDB4M0ZCNURFQTQsIDB4QzAwMDAwMDAsIDB4M0ZCN0MzOTMsIDB4NjAwMDAwMDAsIDB4M0ZCOUJFNEYsIDB4QTAwMDAwMDAsIDB4M0ZCQkNGNDMsCiAgICAweEEwMDAwMDAwLCAweDNGQkRGNkRELCAweDYwMDAwMDAwLCAweDNGQzAxQUM1LCAweDQwMDAwMDAwLCAweDNGQzE0NURCLCAweDQwMDAwMDAwLCAweDNGQzI3Q0U1LAogICAgMHgyMDAwMDAwMCwgMHgzRkMzQzAxNiwgMHg0MDAwMDAwMCwgMHgzRkM1MEY5RSwgMHhBMDAwMDAwMCwgMHgzRkM2NkJBQSwgMHgyMDAwMDAwMCwgMHgzRkM3RDQ2NCwKICAgIDB4QTAwMDAwMDAsIDB4M0ZDOTQ5RUUsIDB4RTAwMDAwMDAsIDB4M0ZDQUNDNjcsIDB4RTAwMDAwMDAsIDB4M0ZDQzVCRTYsIDB4MjAwMDAwMDAsIDB4M0ZDREY4N0EsCiAgICAweDAwMDAwMDAwLCAweDNGQ0ZBMjI3LCAweDQwMDAwMDAwLCAweDNGRDBBQzc0LCAweEUwMDAwMDAwLCAweDNGRDE4RTU2LCAweDIwMDAwMDAwLCAweDNGRDI3NkFDLAogICAgMHhFMDAwMDAwMCwgMHgzRkQzNjU1RCwgMHhFMDAwMDAwMCwgMHgzRkQ0NUE0RCwgMHg2MDAwMDAwMCwgMHgzRkQ1NTU1NSwgMHg0MDAwMDAwMCwgMHgzRkQ2NTY0NCwKICAgIDB4QzAwMDAwMDAsIDB4M0ZENzVDRTAsIDB4RTAwMDAwMDAsIDB4M0ZEODY4RTYsIDB4QTAwMDAwMDAsIDB4M0ZEOTdBMDcsIDB4QzAwMDAwMDAsIDB4M0ZEQThGRTgsCiAgICAweDAwMDAwMDAwLCAweDNGREJBQTI1LCAweDgwMDAwMDAwLCAweDNGRENDODRCLCAweEUwMDAwMDAwLCAweDNGRERFOURGLCAweEUwMDAwMDAwLCAweDNGREYwRTVBLAogICAgMHgyMDAwMDAwMCwgMHgzRkUwMUE5NSwgMHg0MDAwMDAwMCwgMHgzRkUwQUVEOSwgMHg2MDAwMDAwMCwgMHgzRkUxNDNBNywgMHgwMDAwMDAwMCwgMHgzRkUxRDhBOSwKICAgIDB4QTAwMDAwMDAsIDB4M0ZFMjZEODQsIDB4NDAwMDAwMDAsIDB4M0ZFMzAxREUsIDB4NDAwMDAwMDAsIDB4M0ZFMzk1NTgsIDB4NDAwMDAwMDAsIDB4M0ZFNDI3OTQsCiAgICAweEEwMDAwMDAwLCAweDNGRTRCODM0LCAweEUwMDAwMDAwLCAweDNGRTU0NkRDLCAweDAwMDAwMDAwLCAweDNGRTVEMzMzLCAweEEwMDAwMDAwLCAweDNGRTY1Q0UwLAogICAgMHhDMDAwMDAwMCwgMHgzRkU2RTM5MywgMHhDMDAwMDAwMCwgMHgzRkU3NjZGRiwgMHg0MDAwMDAwMCwgMHgzRkU3RTZERSwgMHgwMDAwMDAwMCwgMHgzRkU4NjJGMCwKICAgIDB4QzAwMDAwMDAsIDB4M0ZFOERBRkMsIDB4ODAwMDAwMDAsIDB4M0ZFOTRFRDQsIDB4ODAwMDAwMDAsIDB4M0ZFOUJFNEYsIDB4RTAwMDAwMDAsIDB4M0ZFQTI5NEQsCiAgICAweEEwMDAwMDAwLCAweDNGRUE4RkI4LCAweDYwMDAwMDAwLCAweDNGRUFGMTgwLCAweEMwMDAwMDAwLCAweDNGRUI0RTlELCAweEUwMDAwMDAwLCAweDNGRUJBNzEwLAogICAgMHhFMDAwMDAwMCwgMHgzRkVCRkFFMCwgMHg0MDAwMDAwMCwgMHgzRkVDNEExQiwgMHgyMDAwMDAwMCwgMHgzRkVDOTREMywgMHgwMDAwMDAwMCwgMHgzRkVDREIyMSwKICAgIDB4QzAwMDAwMDAsIDB4M0ZFRDFEMjEsIDB4MjAwMDAwMDAsIDB4M0ZFRDVBRjYsIDB4MjAwMDAwMDAsIDB4M0ZFRDk0QzIsIDB4NDAwMDAwMDAsIDB4M0ZFRENBQUMsCiAgICAweEUwMDAwMDAwLCAweDNGRURGQ0RDLCAweEUwMDAwMDAwLCAweDNGRUUyQjdELCAweDIwMDAwMDAwLCAweDNGRUU1NkJBLCAweEMwMDAwMDAwLCAweDNGRUU3RUJDLAogICAgMHgyMDAwMDAwMCwgMHgzRkVFQTNCMSwgMHg2MDAwMDAwMCwgMHgzRkVFQzVDMiwgMHhFMDAwMDAwMCwgMHgzRkVFRTUxQSwgMHgwMDAwMDAwMCwgMHgzRkVGMDFFNCwKICAgIDB4ODAwMDAwMDAsIDB4M0ZFRjFDNDYsIDB4ODAwMDAwMDAsIDB4M0ZFRjM0NjksIDB4RTAwMDAwMDAsIDB4M0ZFRjRBNzIsIDB4MjAwMDAwMDAsIDB4M0ZFRjVFODcsCiAgICAweDAwMDAwMDAwLCAweDNGRUY3MEM5LCAweEMwMDAwMDAwLCAweDNGRUY4MTU5LCAweDAwMDAwMDAwLCAweDNGRUY5MDU5LCAweEMwMDAwMDAwLCAweDNGRUY5REU0LAogICAgMHg2MDAwMDAwMCwgMHgzRkVGQUExOSwgMHhDMDAwMDAwMCwgMHgzRkVGQjUxMSwgMHhFMDAwMDAwMCwgMHgzRkVGQkVFNiwgMHhDMDAwMDAwMCwgMHgzRkVGQzdCMCwKICAgIDB4NDAwMDAwMDAsIDB4M0ZFRkNGODUsIDB4ODAwMDAwMDAsIDB4M0ZFRkQ2NzksIDB4RTAwMDAwMDAsIDB4M0ZFRkRDQTAsIDB4ODAwMDAwMDAsIDB4M0ZFRkUyMEQsCiAgICAweDYwMDAwMDAwLCAweDNGRUZFNkQwLCAweDQwMDAwMDAwLCAweDNGRUZFQUY5LCAweEMwMDAwMDAwLCAweDNGRUZFRTk2LCAweEMwMDAwMDAwLCAweDNGRUZGMUI2LAogICAgMHhDMDAwMDAwMCwgMHgzRkVGRjQ2NSwgMHg2MDAwMDAwMCwgMHgzRkVGRjZBRiwgMHhDMDAwMDAwMCwgMHgzRkVGRjg5RSwgMHhBMDAwMDAwMCwgMHgzRkVGRkEzRCwKICAgIDB4QTAwMDAwMDAsIDB4M0ZFRkZCOTUsIDB4MjAwMDAwMDAsIDB4M0ZFRkZDQUYsIDB4MDAwMDAwMDAsIDB4M0ZFRkZEOTIsIDB4QzAwMDAwMDAsIDB4M0ZFRkZFNDUsCiAgICAweDAwMDAwMDAwLCAweDNGRUZGRUQxLCAweDAwMDAwMDAwLCAweDNGRUZGRjNBLCAweDQwMDAwMDAwLCAweDNGRUZGRjg2LCAweDQwMDAwMDAwLCAweDNGRUZGRkJCLAogICAgMHhBMDAwMDAwMCwgMHgzRkVGRkZERCwgMHhFMDAwMDAwMCwgMHgzRkVGRkZGMSwgMHhFMDAwMDAwMCwgMHgzRkVGRkZGQiwgMHg4MDAwMDAwMCwgMHgzRkVGRkZGRgpdKSkuYnVmZmVyKTsKSENBVGFibGVzLkRlZmF1bHRDaGFubmVsTWFwcGluZyA9IG5ldyBVaW50OEFycmF5KFsKICAgIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDQsIDB4MDAsIDB4MDEsIDB4MDMsIDB4MDcsIDB4MDMKXSk7CkhDQVRhYmxlcy5WYWxpZENoYW5uZWxNYXBwaW5ncyA9IFsKICAgIG5ldyBVaW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwCiAgICBdKSwKICAgIG5ldyBVaW50OEFycmF5KFsKICAgICAgICAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwCiAgICBdKSwKICAgIG5ldyBVaW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAxLCAweDAxLCAweDAwLCAweDAxLCAweDAwLCAweDAwLCAweDAwCiAgICBdKSwKICAgIG5ldyBVaW50OEFycmF5KFsKICAgICAgICAweDAxLCAweDAwLCAweDAwLCAweDAxLCAweDAwLCAweDAxLCAweDAwLCAweDAwCiAgICBdKSwKICAgIG5ldyBVaW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAxLCAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAxCiAgICBdKSwKICAgIG5ldyBVaW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAwLCAweDAwLCAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAwCiAgICBdKSwKICAgIG5ldyBVaW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAxCiAgICBdKSwKICAgIG5ldyBVaW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAwLCAweDAwLCAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAwCiAgICBdKSwKXTsKSENBVGFibGVzLkRlcXVhbnRpemVyU2NhbGluZ1RhYmxlID0gbmV3IEZsb2F0NjRBcnJheShfYi5hZGFwdEVuZGlhbm5lc3M2NDMyKG5ldyBVaW50MzJBcnJheShbCiAgICAweENBNUQ5MjAxLCAweDNFODU1MUE0LCAweDJFNTdEMTM5LCAweDNFOEM2N0YxLCAweEE5M0UyRjRBLCAweDNFOTJFQ0FGLCAweEIwQ0RDNUQ1LCAweDNFOTkzNzM3LAogICAgMHgyQjcyNDdFRCwgMHgzRUEwQ0M5MiwgMHg4MjU1MjIxNywgMHgzRUE2NjIzOCwgMHhGMzAxQjQ0RiwgMHgzRUFERDMyMSwgMHg0QzEyMzQxNiwgMHgzRUIzREVBNiwKICAgIDB4MTMzMEIzNDksIDB4M0VCQTc5OUUsIDB4RUI2RkNCNkMsIDB4M0VDMUEzNUIsIDB4NEZERTVEMzMsIDB4M0VDNzgwNjksIDB4NUI2RTQ1MkYsIDB4M0VDRjUwNzYsCiAgICAweDk5RkRERDAzLCAweDNFRDREQ0IyLCAweDkwNEJDMUMzLCAweDNFREJDQzFFLCAweEUxRjU2Mzc4LCAweDNFRTI4NERGLCAweDQyMkFBMENGLCAweDNFRThBQ0U1LAogICAgMHgyOURERjZENiwgMHgzRUYwNzA2QiwgMHgxNUFEMjEzRSwgMHgzRUY1RTc2RiwgMHgwODBEODlFMywgMHgzRUZEMkY4NywgMHgzNzNBQTlDMiwgMHgzRjAzNzFBNywKICAgIDB4MTlFMzIzMTgsIDB4M0YwOUU4NjMsIDB4QUVBOTJERDgsIDB4M0YxMTQyOUEsIDB4Rjk1MTk0N0IsIDB4M0YxNkZGN0QsIDB4QTJBNDkwQ0QsIDB4M0YxRUE0QUYsCiAgICAweEVEMUQwMDUwLCAweDNGMjQ2QTQxLCAweEI4NEYxNUYwLCAweDNGMkIzM0EyLCAweDkxN0REQzkwLCAweDNGMzIxRjQ5LCAweDk5NENDRTBBLCAweDNGMzgyNTg5LAogICAgMHhBOUZCMzMyRiwgMHgzRjQwMTYzRCwgMHgzNkI1MjdEMywgMHgzRjQ1NkY0NywgMHg5NDA2RTdBQywgMHgzRjRDOEY2RCwgMHgwQTMxQjcwRiwgMHgzRjUzMDZGRSwKICAgIDB4Q0JDODUyMDcsIDB4M0Y1OTVBNDQsIDB4MzJEM0QxOUQsIDB4M0Y2MEUzRUMsIDB4RDQ0Q0E5NkMsIDB4M0Y2NjgxNTUsIDB4MzM3QjlCNTYsIDB4M0Y2REZDOTcsCiAgICAweDA0QUM4MDE2LCAweDNGNzNGQTQ1LCAweDU1NzlGREI4LCAweDNGN0E5RTZCLCAweDg0MDQ1Q0NGLCAweDNGODFCQkUwLCAweDczRUIwMTgxLCAweDNGODdBMTE0LAogICAgMHhBRDlDQkUwQywgMHgzRjhGN0JGRCwgMHg3NjlEMkNBMiwgMHgzRjk0RjlCMiwgMHg1QkQ3MUUwMywgMHgzRjlCRjJDMiwgMHhGNTFGREVERSwgMHgzRkEyOUU5RCwKICAgIDB4MTZCNTQ0ODcsIDB4M0ZBOENGMzIsIDB4MTg3NTlCQzUsIDB4M0ZCMDg3NDUsIDB4Qjk3NkRDMDUsIDB4M0ZCNjA1RTEsIDB4RENGQkE0ODMsIDB4M0ZCRDU4MTgsCiAgICAweDZEMDVEODYzLCAweDNGQzM4Q0FFLCAweDdCNURFNTYxLCAweDNGQ0EwQzY2LCAweEM4QTU4RTRGLCAweDNGRDE1QTk4LCAweEU4RUM1RjcxLCAweDNGRDcxRjc1LAogICAgMHgyRDhFNjdFRCwgMHgzRkRFQ0Y0OCwgMHhCNUMxM0NDRSwgMHgzRkU0ODZBMiwgMHg4REU1NTkzOCwgMHgzRkVCNTk3MiwgMHg2RTc1NjIzNywgMHgzRkYyMzg3QSwKICAgIDB4NDYyM0M3QUMsIDB4M0ZGODQ3MUEsIDB4M0U3NzgwNjAsIDB4NDAwMDJDOUEsIDB4RDQ5N0M3RkQsIDB4NDAwNThEMTIsIDB4RENFRjkwNjgsIDB4NDAwQ0I3MjAsCiAgICAweEZDNENEODMxLCAweDQwMTMyMTcwLCAweDlGREU0RTUwLCAweDQwMTk3RDgyLCAweEFGRkVEMzFCLCAweDQwMjBGQjY2LCAweDY2N0YzQkNELCAweDQwMjZBMDlFCl0pKS5idWZmZXIpOwpIQ0FUYWJsZXMuUXVhbnRpemVyU3RlcFNpemUgPSBuZXcgRmxvYXQ2NEFycmF5KF9iLmFkYXB0RW5kaWFubmVzczY0MzIobmV3IFVpbnQzMkFycmF5KFsKICAgIDB4MDAwMDAwMDAsIDB4MDAwMDAwMDAsIDB4NTU1NTU1NTUsIDB4M0ZFNTU1NTUsIDB4OTk5OTk5OUEsIDB4M0ZEOTk5OTksIDB4OTI0OTI0OTIsIDB4M0ZEMjQ5MjQsCiAgICAweDFDNzFDNzFDLCAweDNGQ0M3MUM3LCAweDc0NUQxNzQ2LCAweDNGQzc0NUQxLCAweDEzQjEzQjE0LCAweDNGQzNCMTNCLCAweDExMTExMTExLCAweDNGQzExMTExLAogICAgMHgwODQyMTA4NCwgMHgzRkIwODQyMSwgMHgxMDQxMDQxMCwgMHgzRkEwNDEwNCwgMHg4MTAyMDQwOCwgMHgzRjkwMjA0MCwgMHgxMDEwMTAxMCwgMHgzRjgwMTAxMCwKICAgIDB4MDIwMTAwODAsIDB4M0Y3MDA4MDQsIDB4MDA0MDEwMDQsIDB4M0Y2MDA0MDEsIDB4NDAwODAxMDAsIDB4M0Y1MDAyMDAsIDB4MTAwMTAwMTAsIDB4M0Y0MDAxMDAKXSkpLmJ1ZmZlcik7CkhDQVRhYmxlcy5RdWFudGl6ZXJEZWFkWm9uZSA9IG5ldyBGbG9hdDY0QXJyYXkoX2IuYWRhcHRFbmRpYW5uZXNzNjQzMihuZXcgVWludDMyQXJyYXkoWwogICAgMHhGRkZGRkZGRiwgMHhGRkZGRkZGRiwgMHg1NTU1NTU1MywgMHgzRkQ1NTU1NSwgMHg5OTk5OTk5NywgMHgzRkM5OTk5OSwgMHg5MjQ5MjQ4RSwgMHgzRkMyNDkyNCwKICAgIDB4MUM3MUM3MTcsIDB4M0ZCQzcxQzcsIDB4NzQ1RDE3NDAsIDB4M0ZCNzQ1RDEsIDB4MTNCMTNCMEQsIDB4M0ZCM0IxM0IsIDB4MTExMTExMDksIDB4M0ZCMTExMTEsCiAgICAweDA4NDIxMDc0LCAweDNGQTA4NDIxLCAweDEwNDEwM0YwLCAweDNGOTA0MTA0LCAweDgxMDIwM0M4LCAweDNGODAyMDQwLCAweDEwMTAwRjkwLCAweDNGNzAxMDEwLAogICAgMHgwMjAwRkY4MCwgMHgzRjYwMDgwNCwgMHgwMDQwMEUwNCwgMHgzRjUwMDQwMSwgMHg0MDA3RkQwMCwgMHgzRjQwMDIwMCwgMHgxMDAwRjgxMCwgMHgzRjMwMDEwMApdKSkuYnVmZmVyKTsKSENBVGFibGVzLlF1YW50aXplclNjYWxpbmdUYWJsZSA9IG5ldyBGbG9hdDY0QXJyYXkoX2IuYWRhcHRFbmRpYW5uZXNzNjQzMihuZXcgVWludDMyQXJyYXkoWwogICAgMHg1NDNFMUEyMSwgMHg0MTU4MDQyNywgMHg4ODYyOENFMiwgMHg0MTUyMDYzQiwgMHgyOThEQjY3NywgMHg0MTRCMEUwNywgMHg2MDYxODkzQSwgMHg0MTQ0NEUwOCwKICAgIDB4RkJDNzRDOTYsIDB4NDEzRTdBNTEsIDB4M0M2NTFBM0QsIDB4NDEzNkRGQjIsIDB4QzA2QzMxRDYsIDB4NDEzMTJBQkQsIDB4ODJBM0YwQTAsIDB4NDEyOUM0OTEsCiAgICAweDVGOTI5RkZDLCAweDQxMjM1NkM1LCAweDRBMDc4OThCLCAweDQxMUQwNzJELCAweDhBNTk0NkMyLCAweDQxMTVDOTI2LCAweEQzMTU4NTdELCAweDQxMTA1OUIwLAogICAgMHhEOThBNjZBNiwgMHg0MTA4OEFDNywgMHg2NUUyN0NFNywgMHg0MTAyNkI0NSwgMHgzMEExMDY1NiwgMHg0MEZCQTVCMCwgMHhENTM2MkEzMiwgMHg0MEY0QkZEQSwKICAgIDB4Mzc2QkJBQTYsIDB4NDBFRjI1MkIsIDB4NTY0MjY3RDQsIDB4NDBFNzVGRUIsIDB4Mzg4QzhERjIsIDB4NDBFMThBRjksIDB4QjIzRTI1NjgsIDB4NDBEQTU1MDMsCiAgICAweEMzMTNBOEVELCAweDQwRDNDMzJELCAweDAzREIzMjkzLCAweDQwQ0RBOUU2LCAweDM0Q0NDMzI4LCAweDQwQzY0MzQ2LCAweDZDRjk4OTE2LCAweDQwQzBCNTU4LAogICAgMHgwQjkxRkZDRiwgMHg0MEI5MTQ1QiwgMHhBNkU0MDMxMywgMHg0MEIyRDI4NSwgMHg1RkZGRDA4NCwgMHg0MEFDNDBBQiwgMHg1NjlENEY4OSwgMHg0MEE1MzQyQiwKICAgIDB4MkI4RjcxRkUsIDB4NDA5RkQzQzIsIDB4MzZDRjRFNkEsIDB4NDA5N0UyRjMsIDB4MjJGQ0Q5MjIsIDB4NDA5MUVENTAsIDB4OTk1QUQzQjYsIDB4NDA4QUU4OUYsCiAgICAweEQ5NTBBODlELCAweDQwODQzMUY1LCAweEU3OEIzRkZGLCAweDQwN0U1MDJFLCAweDc1MEJEQUM2LCAweDQwNzZDMDEyLCAweEQwMTI1QjU2LCAweDQwNzExMzAxLAogICAgMHg3MENBMDdDMSwgMHg0MDY5QTBGMSwgMHhCMjY0MTcwNSwgMHg0MDYzM0MwOCwgMHg1NTVEQzQwMSwgMHg0MDVDREYwQiwgMHhERDQ4NTQyRiwgMHg0MDU1QUIwNywKICAgIDB4RTg2RTdGODksIDB4NDA1MDQzMTUsIDB4OUI0NDkyRjIsIDB4NDA0ODY4RDksIDB4NEZCMkE2NDMsIDB4NDA0MjUxQ0UsIDB4RjJGQjVFNEMsIDB4NDAzQjdGNzYsCiAgICAweEYwRDdEM0UzLCAweDQwMzRBMzJBLCAweEVFNjE1QTJELCAweDQwMkVGQTFCLCAweDQ4QTU4MTc4LCAweDQwMjczRjlBLCAweDNDN0Q1MTdELCAweDQwMjE3MkI4LAogICAgMHhFQzRBMkQzNywgMHg0MDFBMzA5QiwgMHgzNEU1OUZGQSwgMHg0MDEzQTdEQiwgMHgxNkM5ODM5QiwgMHg0MDBEODBFMywgMHhCMDNBNTU4NywgMHg0MDA2MjQ3RSwKICAgIDB4Q0FDNkYzODUsIDB4NDAwMDlFM0UsIDB4OTkxNTc3MzksIDB4M0ZGOEYxQUUsIDB4RDBEQUQ5OTEsIDB4M0ZGMkI4N0YsIDB4REQ4NTUyOUUsIDB4M0ZFQzE5OUIsCiAgICAweEEyQ0Y2NjQyLCAweDNGRTUxNkRBLCAweDgxOUU5MERBLCAweDNGREZBN0MxLCAweDAxMzBDMTMzLCAweDNGRDdDMUVELCAweDMxNjhCOUFCLCAweDNGRDFENDg3LAogICAgMHhCRkQzRjM3QSwgMHgzRkNBQzM2QiwgMHgyMUY3MkUyQSwgMHgzRkM0MTYwQSwgMHgxNEY1QTEyOSwgMHgzRkJFMjY0NiwgMHg2NjdGM0JDQywgMHgzRkI2QTA5RQpdKSkuYnVmZmVyKTsKSENBVGFibGVzLlF1YW50aXplckludmVyc2VTdGVwU2l6ZSA9IG5ldyBGbG9hdDY0QXJyYXkoX2IuYWRhcHRFbmRpYW5uZXNzNjQzMihuZXcgVWludDMyQXJyYXkoWwogICAgMHgwMDAwMDAwMCwgMHgzRkUwMDAwMCwgMHgwMDAwMDAwMCwgMHgzRkY4MDAwMCwgMHgwMDAwMDAwMCwgMHg0MDA0MDAwMCwgMHgwMDAwMDAwMCwgMHg0MDBDMDAwMCwKICAgIDB4MDAwMDAwMDAsIDB4NDAxMjAwMDAsIDB4MDAwMDAwMDAsIDB4NDAxNjAwMDAsIDB4MDAwMDAwMDAsIDB4NDAxQTAwMDAsIDB4MDAwMDAwMDAsIDB4NDAxRTAwMDAsCiAgICAweDAwMDAwMDAwLCAweDQwMkYwMDAwLCAweDAwMDAwMDAwLCAweDQwM0Y4MDAwLCAweDAwMDAwMDAwLCAweDQwNEZDMDAwLCAweDAwMDAwMDAwLCAweDQwNUZFMDAwLAogICAgMHgwMDAwMDAwMCwgMHg0MDZGRjAwMCwgMHgwMDAwMDAwMCwgMHg0MDdGRjgwMCwgMHgwMDAwMDAwMCwgMHg0MDhGRkMwMCwgMHgwMDAwMDAwMCwgMHg0MDlGRkUwMApdKSkuYnVmZmVyKTsKSENBVGFibGVzLlJlc29sdXRpb25NYXhWYWx1ZXMgPSBuZXcgSW50MzJBcnJheShbCiAgICAweDAwMDAwMDAwLCAweDAwMDAwMDAxLCAweDAwMDAwMDAyLCAweDAwMDAwMDAzLCAweDAwMDAwMDA0LCAweDAwMDAwMDA1LCAweDAwMDAwMDA2LCAweDAwMDAwMDA3LAogICAgMHgwMDAwMDAwRiwgMHgwMDAwMDAxRiwgMHgwMDAwMDAzRiwgMHgwMDAwMDA3RiwgMHgwMDAwMDBGRiwgMHgwMDAwMDFGRiwgMHgwMDAwMDNGRiwgMHgwMDAwMDdGRgpdKTsKSENBVGFibGVzLkludGVuc2l0eVJhdGlvVGFibGUgPSBuZXcgRmxvYXQ2NEFycmF5KF9iLmFkYXB0RW5kaWFubmVzczY0MzIobmV3IFVpbnQzMkFycmF5KFsKICAgIDB4MDAwMDAwMDAsIDB4NDAwMDAwMDAsIDB4NkRCNkRCNkUsIDB4M0ZGREI2REIsIDB4REI2REI2REIsIDB4M0ZGQjZEQjYsIDB4NDkyNDkyNDksIDB4M0ZGOTI0OTIsCiAgICAweEI2REI2REI3LCAweDNGRjZEQjZELCAweDI0OTI0OTI1LCAweDNGRjQ5MjQ5LCAweDkyNDkyNDkyLCAweDNGRjI0OTI0LCAweDAwMDAwMDAwLCAweDNGRjAwMDAwLAogICAgMHhEQjZEQjZEQiwgMHgzRkVCNkRCNiwgMHhCNkRCNkRCNywgMHgzRkU2REI2RCwgMHg5MjQ5MjQ5MiwgMHgzRkUyNDkyNCwgMHhEQjZEQjZEQiwgMHgzRkRCNkRCNiwKICAgIDB4OTI0OTI0OTIsIDB4M0ZEMjQ5MjQsIDB4OTI0OTI0OTIsIDB4M0ZDMjQ5MjQsIDB4MDAwMDAwMDAsIDB4MDAwMDAwMDAKXSkpLmJ1ZmZlcik7CkhDQVRhYmxlcy5JbnRlbnNpdHlSYXRpb0JvdW5kc1RhYmxlID0gbmV3IEZsb2F0NjRBcnJheShfYi5hZGFwdEVuZGlhbm5lc3M2NDMyKG5ldyBVaW50MzJBcnJheShbCiAgICAweEI2REI2REI3LCAweDNGRkVEQjZELCAweDI0OTI0OTI1LCAweDNGRkM5MjQ5LCAweDkyNDkyNDkyLCAweDNGRkE0OTI0LCAweDAwMDAwMDAwLCAweDNGRjgwMDAwLAogICAgMHg2REI2REI2RSwgMHgzRkY1QjZEQiwgMHhEQjZEQjZEQiwgMHgzRkYzNkRCNiwgMHg0OTI0OTI0OSwgMHgzRkYxMjQ5MiwgMHg2REI2REI2RSwgMHgzRkVEQjZEQiwKICAgIDB4NDkyNDkyNDksIDB4M0ZFOTI0OTIsIDB4MjQ5MjQ5MjUsIDB4M0ZFNDkyNDksIDB4MDAwMDAwMDAsIDB4M0ZFMDAwMDAsIDB4QjZEQjZEQjcsIDB4M0ZENkRCNkQsCiAgICAweERCNkRCNkRCLCAweDNGQ0I2REI2LCAweDkyNDkyNDkyLCAweDNGQjI0OTI0Cl0pKS5idWZmZXIpOwpIQ0FUYWJsZXMuU2NhbGVDb252ZXJzaW9uVGFibGUgPSBuZXcgRmxvYXQ2NEFycmF5KF9iLmFkYXB0RW5kaWFubmVzczY0MzIobmV3IFVpbnQzMkFycmF5KFsKICAgIDB4MDAwMDAwMDAsIDB4MDAwMDAwMDAsIDB4MDAwMDAwMDAsIDB4MDAwMDAwMDAsIDB4MjFGNzJFMUQsIDB4M0U1NDE2MEEsIDB4QkZEM0YzNjgsIDB4M0U1QUMzNkIsCiAgICAweDMxNjhCOTlGLCAweDNFNjFENDg3LCAweDAxMzBDMTIzLCAweDNFNjdDMUVELCAweDgxOUU5MEM0LCAweDNFNkZBN0MxLCAweEEyQ0Y2NjM1LCAweDNFNzUxNkRBLAogICAgMHhERDg1NTI4QiwgMHgzRTdDMTk5QiwgMHhEMERBRDk4NSwgMHgzRTgyQjg3RiwgMHg5OTE1NzcyOCwgMHgzRTg4RjFBRSwgMHhDQUM2RjM3QSwgMHgzRTkwOUUzRSwKICAgIDB4QjAzQTU1NzgsIDB4M0U5NjI0N0UsIDB4MTZDOTgzODgsIDB4M0U5RDgwRTMsIDB4MzRFNTlGRUMsIDB4M0VBM0E3REIsIDB4RUM0QTJEMjYsIDB4M0VBQTMwOUIsCiAgICAweDNDN0Q1MTcyLCAweDNFQjE3MkI4LCAweDQ4QTU4MTY4LCAweDNFQjczRjlBLCAweEVFNjE1QTE4LCAweDNFQkVGQTFCLCAweEYwRDdEM0Q0LCAweDNFQzRBMzJBLAogICAgMHhGMkZCNUUzQSwgMHgzRUNCN0Y3NiwgMHg0RkIyQTYzNywgMHgzRUQyNTFDRSwgMHg5QjQ0OTJFMSwgMHgzRUQ4NjhEOSwgMHhFODZFN0Y3RSwgMHgzRUUwNDMxNSwKICAgIDB4REQ0ODU0MjAsIDB4M0VFNUFCMDcsIDB4NTU1REMzRUUsIDB4M0VFQ0RGMEIsIDB4QjI2NDE2RjcsIDB4M0VGMzNDMDgsIDB4NzBDQTA3QjAsIDB4M0VGOUEwRjEsCiAgICAweEQwMTI1QjRBLCAweDNGMDExMzAxLCAweDc1MEJEQUI2LCAweDNGMDZDMDEyLCAweEU3OEIzRkVCLCAweDNGMEU1MDJFLCAweEQ5NTBBODkwLCAweDNGMTQzMUY1LAogICAgMHg5OTVBRDNBNCwgMHgzRjFBRTg5RiwgMHgyMkZDRDkxNywgMHgzRjIxRUQ1MCwgMHgzNkNGNEU1QSwgMHgzRjI3RTJGMywgMHgyQjhGNzFFNywgMHgzRjJGRDNDMiwKICAgIDB4NTY5RDRGN0IsIDB4M0YzNTM0MkIsIDB4NUZGRkQwNzIsIDB4M0YzQzQwQUIsIDB4QTZFNDAzMDYsIDB4M0Y0MkQyODUsIDB4MEI5MUZGQkYsIDB4M0Y0OTE0NUIsCiAgICAweDZDRjk4OTBCLCAweDNGNTBCNTU4LCAweDM0Q0NDMzFBLCAweDNGNTY0MzQ2LCAweDAzREIzMjdFLCAweDNGNURBOUU2LCAweEMzMTNBOEUwLCAweDNGNjNDMzJELAogICAgMHhCMjNFMjU1NywgMHgzRjZBNTUwMywgMHgzODhDOERFNiwgMHgzRjcxOEFGOSwgMHg1NjQyNjdDNCwgMHgzRjc3NUZFQiwgMHgzNzZCQkE5MiwgMHgzRjdGMjUyQiwKICAgIDB4RDUzNjJBMjQsIDB4M0Y4NEJGREEsIDB4MzBBMTA2NDUsIDB4M0Y4QkE1QjAsIDB4NjVFMjdDREEsIDB4M0Y5MjZCNDUsIDB4RDk4QTY2OTYsIDB4M0Y5ODhBQzcsCiAgICAweEQzMTU4NTcyLCAweDNGQTA1OUIwLCAweDhBNTk0NkI0LCAweDNGQTVDOTI2LCAweDRBMDc4OTc4LCAweDNGQUQwNzJELCAweDVGOTI5RkVGLCAweDNGQjM1NkM1LAogICAgMHg4MkEzRjA4RSwgMHgzRkI5QzQ5MSwgMHhDMDZDMzFDQiwgMHgzRkMxMkFCRCwgMHgzQzY1MUEyRCwgMHgzRkM2REZCMiwgMHhGQkM3NEM4MiwgMHgzRkNFN0E1MSwKICAgIDB4NjA2MTg5MkMsIDB4M0ZENDRFMDgsIDB4Mjk4REI2NjUsIDB4M0ZEQjBFMDcsIDB4ODg2MjhDRDYsIDB4M0ZFMjA2M0IsIDB4NTQzRTFBMTEsIDB4M0ZFODA0MjcsCiAgICAweDAwMDAwMDAwLCAweDNGRjAwMDAwLCAweENBNUQ5MjBGLCAweDNGRjU1MUE0LCAweDJFNTdEMTRDLCAweDNGRkM2N0YxLCAweEE5M0UyRjU3LCAweDQwMDJFQ0FGLAogICAgMHhCMENEQzVFNiwgMHg0MDA5MzczNywgMHgyQjcyNDdGOCwgMHg0MDEwQ0M5MiwgMHg4MjU1MjIyNiwgMHg0MDE2NjIzOCwgMHhGMzAxQjQ2MywgMHg0MDFERDMyMSwKICAgIDB4NEMxMjM0MjQsIDB4NDAyM0RFQTYsIDB4MTMzMEIzNUIsIDB4NDAyQTc5OUUsIDB4RUI2RkNCNzcsIDB4NDAzMUEzNUIsIDB4NEZERTVENDIsIDB4NDAzNzgwNjksCiAgICAweDVCNkU0NTQ0LCAweDQwM0Y1MDc2LCAweDk5RkRERDEwLCAweDQwNDREQ0IyLCAweDkwNEJDMUQ2LCAweDQwNEJDQzFFLCAweEUxRjU2Mzg0LCAweDQwNTI4NERGLAogICAgMHg0MjJBQTBFMCwgMHg0MDU4QUNFNSwgMHgyOURERjZFMSwgMHg0MDYwNzA2QiwgMHgxNUFEMjE0RCwgMHg0MDY1RTc2RiwgMHgwODBEODlGOCwgMHg0MDZEMkY4NywKICAgIDB4MzczQUE5Q0YsIDB4NDA3MzcxQTcsIDB4MTlFMzIzMjksIDB4NDA3OUU4NjMsIDB4QUVBOTJERTQsIDB4NDA4MTQyOUEsIDB4Rjk1MTk0OEEsIDB4NDA4NkZGN0QsCiAgICAweEEyQTQ5MEUxLCAweDQwOEVBNEFGLCAweEVEMUQwMDVELCAweDQwOTQ2QTQxLCAweEI4NEYxNjAzLCAweDQwOUIzM0EyLCAweDkxN0REQzlCLCAweDQwQTIxRjQ5LAogICAgMHg5OTRDQ0UxQSwgMHg0MEE4MjU4OSwgMHhBOUZCMzMzQSwgMHg0MEIwMTYzRCwgMHgzNkI1MjdFMSwgMHg0MEI1NkY0NywgMHg5NDA2RTdCRiwgMHg0MEJDOEY2RCwKICAgIDB4MEEzMUI3MUMsIDB4NDBDMzA2RkUsIDB4Q0JDODUyMTgsIDB4NDBDOTVBNDQsIDB4MzJEM0QxQTgsIDB4NDBEMEUzRUMsIDB4RDQ0Q0E5N0MsIDB4NDBENjgxNTUsCiAgICAweDMzN0I5QjZBLCAweDQwRERGQzk3LCAweDA0QUM4MDI0LCAweDQwRTNGQTQ1LCAweDU1NzlGRENBLCAweDQwRUE5RTZCLCAweDg0MDQ1Q0RCLCAweDQwRjFCQkUwLAogICAgMHg3M0VCMDE5MSwgMHg0MEY3QTExNCwgMHhBRDlDQkUyMSwgMHg0MEZGN0JGRCwgMHg3NjlEMkNCMCwgMHg0MTA0RjlCMiwgMHg1QkQ3MUUxNSwgMHg0MTBCRjJDMiwKICAgIDB4RjUxRkRFRUEsIDB4NDExMjlFOUQsIDB4MTZCNTQ0OTgsIDB4NDExOENGMzIsIDB4MTg3NTlCRDAsIDB4NDEyMDg3NDUsIDB4Qjk3NkRDMTQsIDB4NDEyNjA1RTEsCiAgICAweERDRkJBNDk2LCAweDQxMkQ1ODE4LCAweDZEMDVEODcwLCAweDQxMzM4Q0FFLCAweDdCNURFNTczLCAweDQxM0EwQzY2LCAweEM4QTU4RTVCLCAweDQxNDE1QTk4LAogICAgMHhFOEVDNUY4MSwgMHg0MTQ3MUY3NSwgMHgyRDhFNjgwMiwgMHg0MTRFQ0Y0OCwgMHhCNUMxM0NEQywgMHg0MTU0ODZBMiwgMHg4REU1NTk0QSwgMHg0MTVCNTk3MiwKICAgIDB4NkU3NTYyNDMsIDB4NDE2MjM4N0EsIDB4NDYyM0M3QkMsIDB4NDE2ODQ3MUEsIDB4M0U3NzgwNkIsIDB4NDE3MDJDOUEsIDB4RDQ5N0M4MEIsIDB4NDE3NThEMTIsCiAgICAweERDRUY5MDdDLCAweDQxN0NCNzIwLCAweEZDNENEODNFLCAweDQxODMyMTcwLCAweDlGREU0RTYxLCAweDQxODk3RDgyLCAweDAwMDAwMDAwLCAweDAwMDAwMDAwCl0pKS5idWZmZXIpOwpjbGFzcyBIQ0FDcmMxNiB7CiAgICBzdGF0aWMgY2FsYyhkYXRhLCBzaXplKSB7CiAgICAgICAgaWYgKHNpemUgPiBkYXRhLmJ5dGVMZW5ndGgpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIGlmIChzaXplIDwgMCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgbGV0IHN1bSA9IDA7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspCiAgICAgICAgICAgIHN1bSA9ICgoc3VtIDw8IDgpIF4gdGhpcy5fdlsoc3VtID4+IDgpIF4gZGF0YVtpXV0pICYgMHgwMDAwZmZmZjsKICAgICAgICByZXR1cm4gc3VtICYgMHgwMDAwZmZmZjsKICAgIH0KICAgIHN0YXRpYyB2ZXJpZnkoZGF0YSwgc2l6ZSwgZXhwZWN0ZWQsIGRvTm90VGhyb3cgPSBmYWxzZSkgewogICAgICAgIGlmIChleHBlY3RlZCA9PSBudWxsKSB7CiAgICAgICAgICAgIGV4cGVjdGVkID0gbmV3IERhdGFWaWV3KGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQsIGRhdGEuYnl0ZUxlbmd0aCkuZ2V0VWludDE2KHNpemUpOwogICAgICAgIH0KICAgICAgICBsZXQgYWN0dWFsID0gdGhpcy5jYWxjKGRhdGEsIHNpemUpOwogICAgICAgIGxldCByZXN1bHQgPSBleHBlY3RlZCA9PSBhY3R1YWw7CiAgICAgICAgaWYgKCFyZXN1bHQpIHsKICAgICAgICAgICAgZnVuY3Rpb24gdG9IZXgobnVtKSB7CiAgICAgICAgICAgICAgICBjb25zdCBwYWRkaW5nID0gIjAwMDAiOwogICAgICAgICAgICAgICAgbGV0IGhleCA9IHBhZGRpbmcgKyBudW0udG9TdHJpbmcocGFkZGluZy5sZW5ndGggKiA0KS50b1VwcGVyQ2FzZSgpOwogICAgICAgICAgICAgICAgcmV0dXJuICIweCIgKyBoZXguc3Vic3RyaW5nKGhleC5sZW5ndGggLSBwYWRkaW5nLmxlbmd0aCwgaGV4Lmxlbmd0aCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGV0IG1zZyA9IGBjaGVja3N1bSBtaXNtYXRjaCAoZXhwZWN0ZWQ9JHt0b0hleChleHBlY3RlZCl9IGFjdHVhbD0ke3RvSGV4KGFjdHVhbCl9KWA7CiAgICAgICAgICAgIGlmIChkb05vdFRocm93KQogICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihtc2cpOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIHN0YXRpYyBmaXgoZGF0YSwgc2l6ZSkgewogICAgICAgIGxldCBuZXdDcmMxNiA9IHRoaXMuY2FsYyhkYXRhLCBzaXplKTsKICAgICAgICBuZXcgRGF0YVZpZXcoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgZGF0YS5ieXRlTGVuZ3RoKS5zZXRVaW50MTYoc2l6ZSwgbmV3Q3JjMTYpOwogICAgICAgIHJldHVybiBkYXRhOwogICAgfQp9CkhDQUNyYzE2Ll92ID0gbmV3IFVpbnQxNkFycmF5KFsKICAgIDB4MDAwMCwgMHg4MDA1LCAweDgwMEYsIDB4MDAwQSwgMHg4MDFCLCAweDAwMUUsIDB4MDAxNCwgMHg4MDExLCAweDgwMzMsIDB4MDAzNiwgMHgwMDNDLCAweDgwMzksIDB4MDAyOCwgMHg4MDJELCAweDgwMjcsIDB4MDAyMiwKICAgIDB4ODA2MywgMHgwMDY2LCAweDAwNkMsIDB4ODA2OSwgMHgwMDc4LCAweDgwN0QsIDB4ODA3NywgMHgwMDcyLCAweDAwNTAsIDB4ODA1NSwgMHg4MDVGLCAweDAwNUEsIDB4ODA0QiwgMHgwMDRFLCAweDAwNDQsIDB4ODA0MSwKICAgIDB4ODBDMywgMHgwMEM2LCAweDAwQ0MsIDB4ODBDOSwgMHgwMEQ4LCAweDgwREQsIDB4ODBENywgMHgwMEQyLCAweDAwRjAsIDB4ODBGNSwgMHg4MEZGLCAweDAwRkEsIDB4ODBFQiwgMHgwMEVFLCAweDAwRTQsIDB4ODBFMSwKICAgIDB4MDBBMCwgMHg4MEE1LCAweDgwQUYsIDB4MDBBQSwgMHg4MEJCLCAweDAwQkUsIDB4MDBCNCwgMHg4MEIxLCAweDgwOTMsIDB4MDA5NiwgMHgwMDlDLCAweDgwOTksIDB4MDA4OCwgMHg4MDhELCAweDgwODcsIDB4MDA4MiwKICAgIDB4ODE4MywgMHgwMTg2LCAweDAxOEMsIDB4ODE4OSwgMHgwMTk4LCAweDgxOUQsIDB4ODE5NywgMHgwMTkyLCAweDAxQjAsIDB4ODFCNSwgMHg4MUJGLCAweDAxQkEsIDB4ODFBQiwgMHgwMUFFLCAweDAxQTQsIDB4ODFBMSwKICAgIDB4MDFFMCwgMHg4MUU1LCAweDgxRUYsIDB4MDFFQSwgMHg4MUZCLCAweDAxRkUsIDB4MDFGNCwgMHg4MUYxLCAweDgxRDMsIDB4MDFENiwgMHgwMURDLCAweDgxRDksIDB4MDFDOCwgMHg4MUNELCAweDgxQzcsIDB4MDFDMiwKICAgIDB4MDE0MCwgMHg4MTQ1LCAweDgxNEYsIDB4MDE0QSwgMHg4MTVCLCAweDAxNUUsIDB4MDE1NCwgMHg4MTUxLCAweDgxNzMsIDB4MDE3NiwgMHgwMTdDLCAweDgxNzksIDB4MDE2OCwgMHg4MTZELCAweDgxNjcsIDB4MDE2MiwKICAgIDB4ODEyMywgMHgwMTI2LCAweDAxMkMsIDB4ODEyOSwgMHgwMTM4LCAweDgxM0QsIDB4ODEzNywgMHgwMTMyLCAweDAxMTAsIDB4ODExNSwgMHg4MTFGLCAweDAxMUEsIDB4ODEwQiwgMHgwMTBFLCAweDAxMDQsIDB4ODEwMSwKICAgIDB4ODMwMywgMHgwMzA2LCAweDAzMEMsIDB4ODMwOSwgMHgwMzE4LCAweDgzMUQsIDB4ODMxNywgMHgwMzEyLCAweDAzMzAsIDB4ODMzNSwgMHg4MzNGLCAweDAzM0EsIDB4ODMyQiwgMHgwMzJFLCAweDAzMjQsIDB4ODMyMSwKICAgIDB4MDM2MCwgMHg4MzY1LCAweDgzNkYsIDB4MDM2QSwgMHg4MzdCLCAweDAzN0UsIDB4MDM3NCwgMHg4MzcxLCAweDgzNTMsIDB4MDM1NiwgMHgwMzVDLCAweDgzNTksIDB4MDM0OCwgMHg4MzRELCAweDgzNDcsIDB4MDM0MiwKICAgIDB4MDNDMCwgMHg4M0M1LCAweDgzQ0YsIDB4MDNDQSwgMHg4M0RCLCAweDAzREUsIDB4MDNENCwgMHg4M0QxLCAweDgzRjMsIDB4MDNGNiwgMHgwM0ZDLCAweDgzRjksIDB4MDNFOCwgMHg4M0VELCAweDgzRTcsIDB4MDNFMiwKICAgIDB4ODNBMywgMHgwM0E2LCAweDAzQUMsIDB4ODNBOSwgMHgwM0I4LCAweDgzQkQsIDB4ODNCNywgMHgwM0IyLCAweDAzOTAsIDB4ODM5NSwgMHg4MzlGLCAweDAzOUEsIDB4ODM4QiwgMHgwMzhFLCAweDAzODQsIDB4ODM4MSwKICAgIDB4MDI4MCwgMHg4Mjg1LCAweDgyOEYsIDB4MDI4QSwgMHg4MjlCLCAweDAyOUUsIDB4MDI5NCwgMHg4MjkxLCAweDgyQjMsIDB4MDJCNiwgMHgwMkJDLCAweDgyQjksIDB4MDJBOCwgMHg4MkFELCAweDgyQTcsIDB4MDJBMiwKICAgIDB4ODJFMywgMHgwMkU2LCAweDAyRUMsIDB4ODJFOSwgMHgwMkY4LCAweDgyRkQsIDB4ODJGNywgMHgwMkYyLCAweDAyRDAsIDB4ODJENSwgMHg4MkRGLCAweDAyREEsIDB4ODJDQiwgMHgwMkNFLCAweDAyQzQsIDB4ODJDMSwKICAgIDB4ODI0MywgMHgwMjQ2LCAweDAyNEMsIDB4ODI0OSwgMHgwMjU4LCAweDgyNUQsIDB4ODI1NywgMHgwMjUyLCAweDAyNzAsIDB4ODI3NSwgMHg4MjdGLCAweDAyN0EsIDB4ODI2QiwgMHgwMjZFLCAweDAyNjQsIDB4ODI2MSwKICAgIDB4MDIyMCwgMHg4MjI1LCAweDgyMkYsIDB4MDIyQSwgMHg4MjNCLCAweDAyM0UsIDB4MDIzNCwgMHg4MjMxLCAweDgyMTMsIDB4MDIxNiwgMHgwMjFDLCAweDgyMTksIDB4MDIwOCwgMHg4MjBELCAweDgyMDcsIDB4MDIwMgpdKTsKY2xhc3MgSENBQ2lwaGVyIHsKICAgIGNvbnN0cnVjdG9yKGtleTEsIGtleTIpIHsKICAgICAgICB0aGlzLmNpcGhlclR5cGUgPSAwOwogICAgICAgIHRoaXMuZW5jcnlwdCA9IGZhbHNlOwogICAgICAgIHRoaXMua2V5MWJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTsKICAgICAgICB0aGlzLmtleTJidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7CiAgICAgICAgdGhpcy5fdGFibGUgPSBuZXcgVWludDhBcnJheSgyNTYpOwogICAgICAgIHRoaXMuZHYxID0gbmV3IERhdGFWaWV3KHRoaXMua2V5MWJ1Zik7CiAgICAgICAgdGhpcy5kdjIgPSBuZXcgRGF0YVZpZXcodGhpcy5rZXkyYnVmKTsKICAgICAgICBpZiAoa2V5MSA9PSBudWxsKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIm5vIGtleXMgZ2l2ZW4uIHVzZSBcImRlZmF1bHRrZXlcIiBpZiB5b3Ugd2FudCB0byB1c2UgdGhlIGRlZmF1bHQga2V5Iik7CiAgICAgICAgc3dpdGNoIChrZXkxKSB7CiAgICAgICAgICAgIGNhc2UgIm5vbmUiOgogICAgICAgICAgICBjYXNlICJub2tleSI6CiAgICAgICAgICAgIGNhc2UgIm5vS2V5IjoKICAgICAgICAgICAgY2FzZSAibm8ga2V5IjoKICAgICAgICAgICAgY2FzZSAibm9fS2V5IjoKICAgICAgICAgICAgICAgIHRoaXMuc2V0VG9Ob0tleSgpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImRlZmF1bHRrZXkiOgogICAgICAgICAgICBjYXNlICJkZWZhdWx0S2V5IjoKICAgICAgICAgICAgY2FzZSAiZGVmYXVsdCBrZXkiOgogICAgICAgICAgICBjYXNlICJkZWZhdWx0X2tleSI6CiAgICAgICAgICAgICAgICB0aGlzLnNldFRvRGVmS2V5cygpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBrZXkxID0gSENBQ2lwaGVyLnBhcnNlS2V5KGtleTEpOwogICAgICAgICAgICAgICAgaWYgKGtleTIgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgIGtleTIgPSAwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAga2V5MiA9IEhDQUNpcGhlci5wYXJzZUtleShrZXkyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRoaXMuc2V0S2V5cyhrZXkxLCBrZXkyKTsKICAgICAgICB9CiAgICB9CiAgICBpbml0MSgpIHsKICAgICAgICBmb3IgKGxldCBpID0gMSwgdiA9IDA7IGkgPCAweEZGOyBpKyspIHsKICAgICAgICAgICAgdiA9ICh2ICogMTMgKyAxMSkgJiAweEZGOwogICAgICAgICAgICBpZiAodiA9PSAwIHx8IHYgPT0gMHhGRikKICAgICAgICAgICAgICAgIHYgPSAodiAqIDEzICsgMTEpICYgMHhGRjsKICAgICAgICAgICAgdGhpcy5fdGFibGVbaV0gPSB2OwogICAgICAgIH0KICAgICAgICB0aGlzLl90YWJsZVswXSA9IDA7CiAgICAgICAgdGhpcy5fdGFibGVbMHhGRl0gPSAweEZGOwogICAgfQogICAgaW5pdDU2KCkgewogICAgICAgIGxldCBrZXkxID0gdGhpcy5nZXRLZXkxKCk7CiAgICAgICAgbGV0IGtleTIgPSB0aGlzLmdldEtleTIoKTsKICAgICAgICBpZiAoIWtleTEpCiAgICAgICAgICAgIGtleTItLTsKICAgICAgICBrZXkxLS07CiAgICAgICAgdGhpcy5kdjEuc2V0VWludDMyKDAsIGtleTEsIHRydWUpOwogICAgICAgIHRoaXMuZHYyLnNldFVpbnQzMigwLCBrZXkyLCB0cnVlKTsKICAgICAgICBsZXQgdDEgPSB0aGlzLmdldEJ5dGVzT2ZUd29LZXlzKCk7CiAgICAgICAgbGV0IHQyID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgICAgICB0MVsxXSwgdDFbMV0gXiB0MVs2XSwgdDFbMl0gXiB0MVszXSwKICAgICAgICAgICAgdDFbMl0sIHQxWzJdIF4gdDFbMV0sIHQxWzNdIF4gdDFbNF0sCiAgICAgICAgICAgIHQxWzNdLCB0MVszXSBeIHQxWzJdLCB0MVs0XSBeIHQxWzVdLAogICAgICAgICAgICB0MVs0XSwgdDFbNF0gXiB0MVszXSwgdDFbNV0gXiB0MVs2XSwKICAgICAgICAgICAgdDFbNV0sIHQxWzVdIF4gdDFbNF0sIHQxWzZdIF4gdDFbMV0sCiAgICAgICAgICAgIHQxWzZdCiAgICAgICAgXSk7CiAgICAgICAgbGV0IHQzID0gbmV3IFVpbnQ4QXJyYXkoMHgxMDApOwogICAgICAgIGxldCB0MzEgPSBuZXcgVWludDhBcnJheSgweDEwKTsKICAgICAgICBsZXQgdDMyID0gbmV3IFVpbnQ4QXJyYXkoMHgxMCk7CiAgICAgICAgdGhpcy5jcmVhdGVUYWJsZSh0MzEsIHQxWzBdKTsKICAgICAgICBmb3IgKGxldCBpID0gMCwgdCA9IDA7IGkgPCAweDEwOyBpKyspIHsKICAgICAgICAgICAgdGhpcy5jcmVhdGVUYWJsZSh0MzIsIHQyW2ldKTsKICAgICAgICAgICAgbGV0IHYgPSB0MzFbaV0gPDwgNDsKICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCAweDEwOyBqKyspIHsKICAgICAgICAgICAgICAgIHQzW3QrK10gPSB2IHwgdDMyW2pdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAwLCB2ID0gMCwgdCA9IDE7IGkgPCAweDEwMDsgaSsrKSB7CiAgICAgICAgICAgIHYgPSAodiArIDB4MTEpICYgMHhGRjsKICAgICAgICAgICAgbGV0IGEgPSB0M1t2XTsKICAgICAgICAgICAgaWYgKGEgIT0gMCAmJiBhICE9IDB4RkYpCiAgICAgICAgICAgICAgICB0aGlzLl90YWJsZVt0KytdID0gYTsKICAgICAgICB9CiAgICAgICAgdGhpcy5fdGFibGVbMF0gPSAwOwogICAgICAgIHRoaXMuX3RhYmxlWzB4RkZdID0gMHhGRjsKICAgIH0KICAgIGNyZWF0ZVRhYmxlKHIsIGtleSkgewogICAgICAgIGxldCBtdWwgPSAoKGtleSAmIDEpIDw8IDMpIHwgNTsKICAgICAgICBsZXQgYWRkID0gKGtleSAmIDB4RSkgfCAxOwogICAgICAgIGxldCB0ID0gMDsKICAgICAgICBrZXkgPj49IDQ7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAweDEwOyBpKyspIHsKICAgICAgICAgICAga2V5ID0gKGtleSAqIG11bCArIGFkZCkgJiAweEY7CiAgICAgICAgICAgIHJbdCsrXSA9IGtleTsKICAgICAgICB9CiAgICB9CiAgICBpbnZlcnRUYWJsZSgpIHsKICAgICAgICAvLyBhY3R1YWxseSwgdGhpcyBtZXRob2Qgc3dpdGNoIHRoZSBtb2RlIGJldHdlZW4gZW5jcnlwdC9kZWNyeXB0CiAgICAgICAgdGhpcy5lbmNyeXB0ID0gIXRoaXMuZW5jcnlwdDsKICAgICAgICBsZXQgX29sZF90YWJsZSA9IHRoaXMuX3RhYmxlLnNsaWNlKDApOwogICAgICAgIGxldCBiaXRNYXAgPSBuZXcgVWludDE2QXJyYXkoMTYpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjU2OyBpKyspIHsKICAgICAgICAgICAgLy8gaW52ZXJ0IGtleSBhbmQgdmFsdWUKICAgICAgICAgICAgbGV0IGtleSA9IF9vbGRfdGFibGVbaV07CiAgICAgICAgICAgIGxldCB2YWwgPSBpOwogICAgICAgICAgICAvLyBjaGVjayBmb3IgaW5jb25zaXN0ZW5jeQogICAgICAgICAgICBsZXQgaGlnaGVyNCA9IGtleSA+PiA0ICYgMHgwRjsKICAgICAgICAgICAgbGV0IGxvd2VyNCA9IGtleSAmIDB4MEY7CiAgICAgICAgICAgIGxldCBmbGFnID0gMHgwMSA8PCBsb3dlcjQ7CiAgICAgICAgICAgIGlmIChiaXRNYXBbaGlnaGVyNF0gJiBmbGFnKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJfdGFibGUgaXMgbm90IGJpamVjdGl2ZSIpOwogICAgICAgICAgICAvLyB1cGRhdGUgdGFibGUKICAgICAgICAgICAgdGhpcy5fdGFibGVba2V5XSA9IHZhbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBnZXRUeXBlKCkgewogICAgICAgIHJldHVybiB0aGlzLmNpcGhlclR5cGU7CiAgICB9CiAgICBnZXRFbmNyeXB0KCkgewogICAgICAgIHJldHVybiB0aGlzLmVuY3J5cHQ7CiAgICB9CiAgICBnZXRLZXkxKCkgewogICAgICAgIHJldHVybiB0aGlzLmR2MS5nZXRVaW50MzIoMCwgdHJ1ZSk7CiAgICB9CiAgICBnZXRLZXkyKCkgewogICAgICAgIHJldHVybiB0aGlzLmR2Mi5nZXRVaW50MzIoMCwgdHJ1ZSk7CiAgICB9CiAgICBnZXRCeXRlc09mVHdvS2V5cygpIHsKICAgICAgICBsZXQgYnVmID0gbmV3IFVpbnQ4QXJyYXkoOCk7CiAgICAgICAgYnVmLnNldChuZXcgVWludDhBcnJheSh0aGlzLmtleTFidWYpLCAwKTsKICAgICAgICBidWYuc2V0KG5ldyBVaW50OEFycmF5KHRoaXMua2V5MmJ1ZiksIDQpOwogICAgICAgIHJldHVybiBidWY7CiAgICB9CiAgICBzZXRLZXkxKGtleSkgewogICAgICAgIHRoaXMuZHYxLnNldFVpbnQzMigwLCBrZXksIHRydWUpOwogICAgICAgIHRoaXMuaW5pdDU2KCk7CiAgICAgICAgdGhpcy5jaXBoZXJUeXBlID0gMHgzODsKICAgICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIHNldEtleTIoa2V5KSB7CiAgICAgICAgdGhpcy5kdjIuc2V0VWludDMyKDAsIGtleSwgdHJ1ZSk7CiAgICAgICAgdGhpcy5pbml0NTYoKTsKICAgICAgICB0aGlzLmNpcGhlclR5cGUgPSAweDM4OwogICAgICAgIHJldHVybiB0aGlzOwogICAgfQogICAgc2V0S2V5cyhrZXkxLCBrZXkyKSB7CiAgICAgICAgdGhpcy5kdjEuc2V0VWludDMyKDAsIGtleTEsIHRydWUpOwogICAgICAgIHRoaXMuZHYyLnNldFVpbnQzMigwLCBrZXkyLCB0cnVlKTsKICAgICAgICB0aGlzLmluaXQ1NigpOwogICAgICAgIHRoaXMuY2lwaGVyVHlwZSA9IDB4Mzg7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBzZXRUb0RlZktleXMoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuc2V0S2V5cyhIQ0FDaXBoZXIuZGVmS2V5MSwgSENBQ2lwaGVyLmRlZktleTIpOwogICAgfQogICAgc2V0VG9Ob0tleSgpIHsKICAgICAgICB0aGlzLmluaXQxKCk7CiAgICAgICAgdGhpcy5jaXBoZXJUeXBlID0gMHgwMTsKICAgICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIG1hc2soYmxvY2ssIG9mZnNldCwgc2l6ZSkgewogICAgICAgIC8vIGVuY3J5cHQgb3IgZGVjcnlwdCBibG9jayBkYXRhCiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspCiAgICAgICAgICAgIGJsb2NrW29mZnNldCArIGldID0gdGhpcy5fdGFibGVbYmxvY2tbb2Zmc2V0ICsgaV1dOwogICAgfQogICAgc3RhdGljIGlzSENBSGVhZGVyTWFza2VkKGhjYSkgewogICAgICAgIC8vIGZhc3QgJiBkaXJ0eSB3YXkgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgZW5jcnlwdGVkLCBub3QgcmVjb21tZW5kZWQKICAgICAgICBpZiAoaGNhWzBdICYgMHg4MCB8fCBoY2FbMV0gJiAweDgwIHx8IGhjYVsyXSAmIDB4ODApCiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIGVsc2UKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgc3RhdGljIHBhcnNlS2V5KGtleSkgewogICAgICAgIHN3aXRjaCAodHlwZW9mIGtleSkgewogICAgICAgICAgICBjYXNlICJudW1iZXIiOgogICAgICAgICAgICAgICAgcmV0dXJuIGtleTsKICAgICAgICAgICAgY2FzZSAic3RyaW5nIjoKICAgICAgICAgICAgICAgIC8vIGF2b2lkIGFtYmlndWl0eTogYWx3YXlzIHRyZWF0IGFzIGhleAogICAgICAgICAgICAgICAgaWYgKCFrZXkubWF0Y2goL14weC8pKQogICAgICAgICAgICAgICAgICAgIGtleSA9ICIweCIgKyBrZXk7CiAgICAgICAgICAgICAgICBrZXkgPSBwYXJzZUludChrZXkpOwogICAgICAgICAgICAgICAgaWYgKGlzTmFOKGtleSkpCiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJjYW5ub3QgcGFyc2UgYXMgaW50ZWdlciIpOwogICAgICAgICAgICAgICAgcmV0dXJuIGtleTsKICAgICAgICAgICAgY2FzZSAib2JqZWN0IjoKICAgICAgICAgICAgICAgIC8vIGF2b2lkIGVuZGlhbm5lc3MgYW1iaWd1aXR5OiBvbmx5IGFjY2VwdGluZyBVaW50OEFycmF5LCB0aGVuIHJlYWQgYXMgbGl0dGxlIGVuZGlhbgogICAgICAgICAgICAgICAgaWYgKGtleSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgJiYga2V5LmJ5dGVMZW5ndGggPT0gNCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRGF0YVZpZXcoa2V5LmJ1ZmZlciwga2V5LmJ5dGVPZmZzZXQsIGtleS5ieXRlTGVuZ3RoKS5nZXRVaW50MzIoMCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImNhbiBvbmx5IGFjY2VwdCBudW1iZXIvaGV4IHN0cmluZy9VaW50OEFycmF5WzRdIik7CiAgICAgICAgfQogICAgfQp9CkhDQUNpcGhlci5kZWZLZXkxID0gMHgwMTM5NUM1MTsKSENBQ2lwaGVyLmRlZktleTIgPSAweDAwMDAwMDAwOwovLyBjb252ZXJ0IG5vbi10cmFuc2ZlcmFibGUgdHlwZWQgYXJyYXkgdG8gdHJhbnNmZXJhYmxlIGFycmF5IGJ1ZmZlcgpjbGFzcyBIQ0FUcmFuc1R5cGVkQXJyYXkgewogICAgY29uc3RydWN0b3IodGEsIHRyYW5zZmVyTGlzdCkgewogICAgICAgIGNvbnN0IHR5cGUgPSBIQ0FUcmFuc1R5cGVkQXJyYXkuZ2V0VHlwZSh0YSk7CiAgICAgICAgaWYgKHR5cGUgIT0gbnVsbCkKICAgICAgICAgICAgdGhpcy50eXBlID0gdHlwZS50eXBlOwogICAgICAgIGVsc2UKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJ1bmV4cGVjdGVkIHR5cGUiKTsKICAgICAgICB0aGlzLmJ1ZmZlciA9IHRhLmJ1ZmZlcjsKICAgICAgICB0aGlzLmJ5dGVPZmZzZXQgPSB0YS5ieXRlT2Zmc2V0OwogICAgICAgIHRoaXMubGVuZ3RoID0gdGEubGVuZ3RoOwogICAgICAgIGlmICghdHJhbnNmZXJMaXN0LmZpbmQoKHZhbCkgPT4gdmFsID09PSB0aGlzLmJ1ZmZlcikpCiAgICAgICAgICAgIHRyYW5zZmVyTGlzdC5wdXNoKHRoaXMuYnVmZmVyKTsKICAgIH0KICAgIHN0YXRpYyBjb252ZXJ0KGFyZywgdHJhbnNmZXJMaXN0KSB7CiAgICAgICAgaWYgKHRoaXMuZ2V0VHlwZShhcmcpICE9IG51bGwpCiAgICAgICAgICAgIHJldHVybiBuZXcgSENBVHJhbnNUeXBlZEFycmF5KGFyZywgdHJhbnNmZXJMaXN0KTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiBhcmc7CiAgICB9CiAgICBzdGF0aWMgcmVzdG9yZShhcmcpIHsKICAgICAgICBjb25zdCB0eXBlID0gdGhpcy5nZXRUeXBlKGFyZyk7CiAgICAgICAgaWYgKHR5cGUgIT0gbnVsbCAmJiB0eXBlLmNvbnZlcnRlZCkKICAgICAgICAgICAgcmV0dXJuIGFyZy5hcnJheTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiBhcmc7CiAgICB9CiAgICBzdGF0aWMgZ2V0VHlwZShhcmcpIHsKICAgICAgICBpZiAoYXJnID09IG51bGwgfHwgdHlwZW9mIGFyZyAhPT0gIm9iamVjdCIpCiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICAgICAgZWxzZSBpZiAoYXJnIGluc3RhbmNlb2YgSW50OEFycmF5KQogICAgICAgICAgICByZXR1cm4geyBjb252ZXJ0ZWQ6IGZhbHNlLCB0eXBlOiAiSW50OCIgfTsKICAgICAgICBlbHNlIGlmIChhcmcgaW5zdGFuY2VvZiBJbnQxNkFycmF5KQogICAgICAgICAgICByZXR1cm4geyBjb252ZXJ0ZWQ6IGZhbHNlLCB0eXBlOiAiSW50MTYiIH07CiAgICAgICAgZWxzZSBpZiAoYXJnIGluc3RhbmNlb2YgSW50MzJBcnJheSkKICAgICAgICAgICAgcmV0dXJuIHsgY29udmVydGVkOiBmYWxzZSwgdHlwZTogIkludDMyIiB9OwogICAgICAgIGVsc2UgaWYgKGFyZyBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpCiAgICAgICAgICAgIHJldHVybiB7IGNvbnZlcnRlZDogZmFsc2UsIHR5cGU6ICJVaW50OCIgfTsKICAgICAgICBlbHNlIGlmIChhcmcgaW5zdGFuY2VvZiBVaW50MTZBcnJheSkKICAgICAgICAgICAgcmV0dXJuIHsgY29udmVydGVkOiBmYWxzZSwgdHlwZTogIlVpbnQxNiIgfTsKICAgICAgICBlbHNlIGlmIChhcmcgaW5zdGFuY2VvZiBVaW50MzJBcnJheSkKICAgICAgICAgICAgcmV0dXJuIHsgY29udmVydGVkOiBmYWxzZSwgdHlwZTogIlVpbnQzMiIgfTsKICAgICAgICBlbHNlIGlmIChhcmcgaW5zdGFuY2VvZiBGbG9hdDMyQXJyYXkpCiAgICAgICAgICAgIHJldHVybiB7IGNvbnZlcnRlZDogZmFsc2UsIHR5cGU6ICJGbG9hdDMyIiB9OwogICAgICAgIGVsc2UgaWYgKGFyZyBpbnN0YW5jZW9mIEZsb2F0NjRBcnJheSkKICAgICAgICAgICAgcmV0dXJuIHsgY29udmVydGVkOiBmYWxzZSwgdHlwZTogIkZsb2F0NjQiIH07CiAgICAgICAgZWxzZSBpZiAoYXJnLmJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyICYmIHR5cGVvZiBhcmcudHlwZSA9PT0gInN0cmluZyIpCiAgICAgICAgICAgIHJldHVybiB7IGNvbnZlcnRlZDogdHJ1ZSwgdHlwZTogYXJnLnR5cGUgfTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICBnZXQgYXJyYXkoKSB7CiAgICAgICAgc3dpdGNoICh0aGlzLnR5cGUpIHsKICAgICAgICAgICAgY2FzZSAiSW50OCI6IHJldHVybiBuZXcgSW50OEFycmF5KHRoaXMuYnVmZmVyLCB0aGlzLmJ5dGVPZmZzZXQsIHRoaXMubGVuZ3RoKTsKICAgICAgICAgICAgY2FzZSAiSW50MTYiOiByZXR1cm4gbmV3IEludDE2QXJyYXkodGhpcy5idWZmZXIsIHRoaXMuYnl0ZU9mZnNldCwgdGhpcy5sZW5ndGgpOwogICAgICAgICAgICBjYXNlICJJbnQzMiI6IHJldHVybiBuZXcgSW50MzJBcnJheSh0aGlzLmJ1ZmZlciwgdGhpcy5ieXRlT2Zmc2V0LCB0aGlzLmxlbmd0aCk7CiAgICAgICAgICAgIGNhc2UgIlVpbnQ4IjogcmV0dXJuIG5ldyBVaW50OEFycmF5KHRoaXMuYnVmZmVyLCB0aGlzLmJ5dGVPZmZzZXQsIHRoaXMubGVuZ3RoKTsKICAgICAgICAgICAgY2FzZSAiVWludDE2IjogcmV0dXJuIG5ldyBVaW50MTZBcnJheSh0aGlzLmJ1ZmZlciwgdGhpcy5ieXRlT2Zmc2V0LCB0aGlzLmxlbmd0aCk7CiAgICAgICAgICAgIGNhc2UgIlVpbnQzMiI6IHJldHVybiBuZXcgVWludDMyQXJyYXkodGhpcy5idWZmZXIsIHRoaXMuYnl0ZU9mZnNldCwgdGhpcy5sZW5ndGgpOwogICAgICAgICAgICBjYXNlICJGbG9hdDMyIjogcmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkodGhpcy5idWZmZXIsIHRoaXMuYnl0ZU9mZnNldCwgdGhpcy5sZW5ndGgpOwogICAgICAgICAgICBjYXNlICJGbG9hdDY0IjogcmV0dXJuIG5ldyBGbG9hdDY0QXJyYXkodGhpcy5idWZmZXIsIHRoaXMuYnl0ZU9mZnNldCwgdGhpcy5sZW5ndGgpOwogICAgICAgIH0KICAgICAgICB0aHJvdyBuZXcgRXJyb3IoInVuZXhwZWN0ZWQgdHlwZSIpOwogICAgfQp9CmNsYXNzIEhDQVRhc2sgewogICAgY29uc3RydWN0b3Iob3JpZ2luLCB0YXNrSUQsIGNtZCwgYXJncywgcmVwbHlBcmdzLCBpc0R1bW15KSB7CiAgICAgICAgdGhpcy50cmFuc2Zlckxpc3QgPSBbXTsKICAgICAgICB0aGlzLl9oYXNSZXN1bHQgPSBmYWxzZTsKICAgICAgICB0aGlzLm9yaWdpbiA9IG9yaWdpbjsKICAgICAgICB0aGlzLnRhc2tJRCA9IHRhc2tJRDsKICAgICAgICB0aGlzLmNtZCA9IGNtZDsKICAgICAgICB0aGlzLl9hcmdzID0gYXJncyA9PT0gbnVsbCB8fCBhcmdzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBhcmdzLm1hcCgoYXJnKSA9PiBIQ0FUcmFuc1R5cGVkQXJyYXkuY29udmVydChhcmcsIHRoaXMudHJhbnNmZXJMaXN0KSk7CiAgICAgICAgdGhpcy5fcmVwbHlBcmdzID0gcmVwbHlBcmdzOwogICAgICAgIGlmIChpc0R1bW15ICE9IG51bGwgJiYgaXNEdW1teSkKICAgICAgICAgICAgdGhpcy5pc0R1bW15ID0gdHJ1ZTsKICAgIH0KICAgIGdldCBhcmdzKCkgewogICAgICAgIHZhciBfYzsKICAgICAgICByZXR1cm4gKF9jID0gdGhpcy5fYXJncykgPT09IG51bGwgfHwgX2MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jLm1hcCgoYXJnKSA9PiBIQ0FUcmFuc1R5cGVkQXJyYXkucmVzdG9yZShhcmcpKTsKICAgIH0KICAgIGdldCBoYXNSZXN1bHQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2hhc1Jlc3VsdDsKICAgIH0KICAgIGdldCByZXN1bHQoKSB7CiAgICAgICAgaWYgKCF0aGlzLl9oYXNSZXN1bHQpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigibm8gcmVzdWx0Iik7CiAgICAgICAgcmV0dXJuIEhDQVRyYW5zVHlwZWRBcnJheS5yZXN0b3JlKHRoaXMuX3Jlc3VsdCk7CiAgICB9CiAgICBzZXQgcmVzdWx0KHJlc3VsdCkgewogICAgICAgIGlmICh0aGlzLmhhc0VycikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJhbHJlYWR5IGhhcyBlcnJvciwgY2Fubm90IHNldCByZXN1bHQiKTsKICAgICAgICBpZiAodGhpcy5faGFzUmVzdWx0KQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImNhbm5vdCBzZXQgcmVzdWx0IGFnYWluIik7CiAgICAgICAgdGhpcy5fcmVzdWx0ID0gSENBVHJhbnNUeXBlZEFycmF5LmNvbnZlcnQocmVzdWx0LCB0aGlzLnRyYW5zZmVyTGlzdCk7CiAgICAgICAgdGhpcy5faGFzUmVzdWx0ID0gdHJ1ZTsKICAgICAgICBpZiAoIXRoaXMuX3JlcGx5QXJncykKICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2FyZ3M7CiAgICB9CiAgICBnZXQgaGFzRXJyKCkgewogICAgICAgIHJldHVybiB0aGlzLl9lcnJNc2cgIT0gbnVsbDsKICAgIH0KICAgIGdldCBlcnJNc2coKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2Vyck1zZzsKICAgIH0KICAgIHNldCBlcnJNc2cobXNnKSB7CiAgICAgICAgLy8gY2hhbmdpbmcgZXJyTXNnIGlzIGFsbG93ZWQsIGJ1dCBjbGVhcmluZyBlcnJNc2cgaXMgZGlzYWxsb3dlZAogICAgICAgIGlmICh0eXBlb2YgbXNnICE9PSAic3RyaW5nIikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJlcnJvciBtZXNzYWdlIG11c3QgYmUgYSBzdHJpbmciKTsKICAgICAgICBkZWxldGUgdGhpcy5fYXJnczsKICAgICAgICBpZiAodGhpcy5faGFzUmVzdWx0KSB7CiAgICAgICAgICAgIC8vIGNsZWFyIHJlc3VsdCBvbiBlcnJvcgogICAgICAgICAgICBkZWxldGUgdGhpcy5fcmVzdWx0OwogICAgICAgICAgICB0aGlzLl9oYXNSZXN1bHQgPSBmYWxzZTsKICAgICAgICAgICAgdGhpcy50cmFuc2Zlckxpc3QgPSBbXTsKICAgICAgICAgICAgdGhpcy5hcmdzLmZvckVhY2goKGFyZykgPT4gSENBVHJhbnNUeXBlZEFycmF5LmNvbnZlcnQoYXJnLCB0aGlzLnRyYW5zZmVyTGlzdCkpOwogICAgICAgIH0KICAgICAgICB0aGlzLl9lcnJNc2cgPSBtc2c7CiAgICB9CiAgICBzdGF0aWMgcmVjcmVhdGUodGFzaykgewogICAgICAgIGNvbnN0IHJlY3JlYXRlZCA9IG5ldyBIQ0FUYXNrKHRhc2sub3JpZ2luLCB0YXNrLnRhc2tJRCwgdGFzay5jbWQsIHRhc2suX2FyZ3MsIHRhc2suX3JlcGx5QXJncyk7CiAgICAgICAgaWYgKHRhc2suX2Vyck1zZyAhPSBudWxsKQogICAgICAgICAgICByZWNyZWF0ZWQuZXJyTXNnID0gdGFzay5fZXJyTXNnOwogICAgICAgIGVsc2UgaWYgKHRhc2suX2hhc1Jlc3VsdCkKICAgICAgICAgICAgcmVjcmVhdGVkLnJlc3VsdCA9IHRhc2suX3Jlc3VsdDsKICAgICAgICByZXR1cm4gcmVjcmVhdGVkOwogICAgfQp9CmNsYXNzIEhDQVRhc2tRdWV1ZSB7CiAgICBjb25zdHJ1Y3RvcihvcmlnaW4sIHBvc3RNZXNzYWdlLCB0YXNrSGFuZGxlciwgZGVzdHJveSkgewogICAgICAgIHRoaXMuX2lzQWxpdmUgPSB0cnVlOwogICAgICAgIHRoaXMuaXNJZGxlID0gdHJ1ZTsKICAgICAgICAvLyBjb21wYXJpbmcgdG8gc3RydWN0dXJlZCBjb3B5IChieSBkZWZhdWx0KSwgaWYgZGF0YSBzaXplIGlzIGJpZyAoYmVjYXVzZSBvZiB6ZXJvLWNvcHkpLAogICAgICAgIC8vIHRyYW5zZmVycmluZyBpcyBnZW5lcmFsbHkgbXVjaCBmYXN0ZXIuIGhvd2V2ZXIgaXQgb2J2aW91c2x5IGhhcyBhIGRyYXdiYWNrLAogICAgICAgIC8vIHRoYXQgdHJhbnNmZXJyZWQgYXJndW1lbnRzIGFyZSBubyBsb25nZXIgYWNjZXNzaWJsZSBpbiB0aGUgc2VuZGVyIHRocmVhZAogICAgICAgIHRoaXMudHJhbnNmZXJBcmdzID0gZmFsc2U7CiAgICAgICAgLy8gdGhlIHJlY2VpdmVyL2NhbGxlZSB3aWxsIGFsd2F5cyB1c2UgdHJhbnNmZXJyaW5nIHRvIHNlbmQgYmFjayBhcmd1bWVudHMsCiAgICAgICAgLy8gbm90IHNlbmRpbmcgdGhlIGFyZ3VtZW50cyBiYWNrIGlzIHN1cHBvc2VkIHRvIHNhdmUgYSBsaXR0bGUgdGltZS9vdmVyaGVhZAogICAgICAgIHRoaXMucmVwbHlBcmdzID0gZmFsc2U7CiAgICAgICAgdGhpcy5xdWV1ZSA9IFtdOwogICAgICAgIHRoaXMuX2xhc3RUYXNrSUQgPSAwOwogICAgICAgIHRoaXMuY2FsbGJhY2tzID0ge307CiAgICAgICAgdGhpcy5vcmlnaW4gPSBvcmlnaW47CiAgICAgICAgdGhpcy5wb3N0TWVzc2FnZSA9IHBvc3RNZXNzYWdlOwogICAgICAgIHRoaXMudGFza0hhbmRsZXIgPSB0YXNrSGFuZGxlcjsKICAgICAgICB0aGlzLmRlc3Ryb3kgPSBkZXN0cm95OwogICAgfQogICAgZ2V0TmV4dFRhc2tJRCgpIHsKICAgICAgICBjb25zdCBtYXggPSBIQ0FUYXNrUXVldWUubWF4VGFza0lEIC0gMTsKICAgICAgICBpZiAodGhpcy5fbGFzdFRhc2tJRCA8IDAgfHwgdGhpcy5fbGFzdFRhc2tJRCA+IG1heCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJsYXN0VGFza0lEIG91dCBvZiByYW5nZSIpOwogICAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5fbGFzdFRhc2tJRCArIDE7CiAgICAgICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDw9IHN0YXJ0ICsgbWF4OyBpKyspIHsKICAgICAgICAgICAgY29uc3QgdGFza0lEID0gaSAlIChtYXggKyAxKTsKICAgICAgICAgICAgaWYgKHRoaXMuY2FsbGJhY2tzW3Rhc2tJRF0gPT0gbnVsbCkKICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9sYXN0VGFza0lEID0gdGFza0lEOwogICAgICAgIH0KICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImNhbm5vdCBmaW5kIG5leHQgdGFza0lEIik7CiAgICB9CiAgICBzZW5kVGFzayh0YXNrKSB7CiAgICAgICAgaWYgKHRhc2sub3JpZ2luICE9PSB0aGlzLm9yaWdpbikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJ0aGUgdGFzayB0byBiZSBzZW50IG11c3QgaGF2ZSB0aGUgc2FtZSBvcmlnaW4gYXMgdGhlIHRhc2sgcXVldWUiKTsKICAgICAgICB0aGlzLnBvc3RNZXNzYWdlKHRhc2ssIHRoaXMudHJhbnNmZXJBcmdzID8gdGFzay50cmFuc2Zlckxpc3QgOiBbXSk7CiAgICB9CiAgICBzZW5kUmVwbHkodGFzaykgewogICAgICAgIGlmICh0YXNrLm9yaWdpbiA9PT0gdGhpcy5vcmlnaW4pCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigidGhlIHJlcGx5IHRvIGJlIHNlbnQgbXVzdCBub3QgaGF2ZSB0aGUgc2FtZSBvcmlnaW4gYXMgdGhlIHRhc2sgcXVldWUiKTsKICAgICAgICB0aGlzLnBvc3RNZXNzYWdlKHRhc2ssIHRhc2sudHJhbnNmZXJMaXN0KTsgLy8gYWx3YXlzIHVzZSB0cmFuc2ZlcnJpbmcgdG8gc2VuZCBiYWNrIGFyZ3VtZW50cwogICAgfQogICAgc2VuZE5leHRUYXNrKCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIGxldCB0YXNrID0gdGhpcy5xdWV1ZS5zaGlmdCgpOwogICAgICAgICAgICBpZiAodGFzayA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICB0aGlzLmlzSWRsZSA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB0aGlzLmlzSWRsZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgLy8gYXBwbHkgaG9vayBmaXJzdAogICAgICAgICAgICAgICAgY29uc3QgcmVnaXN0ZXJlZCA9IHRoaXMuY2FsbGJhY2tzW3Rhc2sudGFza0lEXTsKICAgICAgICAgICAgICAgIGNvbnN0IHRhc2tIb29rID0gcmVnaXN0ZXJlZCAhPSBudWxsICYmIHJlZ2lzdGVyZWQuaG9vayAhPSBudWxsICYmIHJlZ2lzdGVyZWQuaG9vay50YXNrICE9IG51bGwKICAgICAgICAgICAgICAgICAgICA/IHJlZ2lzdGVyZWQuaG9vay50YXNrCiAgICAgICAgICAgICAgICAgICAgOiB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICBpZiAodGFza0hvb2sgIT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICB0YXNrID0geWllbGQgdGFza0hvb2sodGFzayk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suZXJyTXNnID0gYFske3RoaXMub3JpZ2lufV0gZXJyb3Igd2hlbiBhcHBseWluZyBob29rIGAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgYGJlZm9yZSBleGVjdXRpbmcgY21kICR7dGFzay5jbWR9IGZyb20gJHt0YXNrLm9yaWdpbn1gOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGUgPT09ICJzdHJpbmciIHx8IGUgaW5zdGFuY2VvZiBFcnJvcikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suZXJyTXNnICs9ICJcbiIgKyBlLnRvU3RyaW5nKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suaXNEdW1teSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gc2VuZCB0YXNrCiAgICAgICAgICAgICAgICBpZiAodGFzay5pc0R1bW15KSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YXNrLmhhc0VyciAmJiAhdGFzay5oYXNSZXN1bHQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2sucmVzdWx0ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBldiA9IG5ldyBNZXNzYWdlRXZlbnQoIm1lc3NhZ2UiLCB7IGRhdGE6IHRhc2sgfSk7IC8vIG5vdCBhY3R1YWxseSBzZW5kaW5nLCB1c2UgYSBmYWtlIHJlcGx5CiAgICAgICAgICAgICAgICAgICAgdGhpcy5tc2dIYW5kbGVyKGV2KTsgLy8gd29uJ3QgYXdhaXQKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIHRoaXMuc2VuZFRhc2sodGFzayk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgIH0KICAgIGdldCBpc0FsaXZlKCkgewogICAgICAgIHJldHVybiB0aGlzLl9pc0FsaXZlOwogICAgfQogICAgLy8gdGhlc2UgZm9sbG93aW5nIHR3byBtZXRob2RzL2Z1bmN0aW9ucyBhcmUgc3VwcG9zZWQgdG8gYmUgY2FsbGJhY2tzCiAgICBtc2dIYW5kbGVyKGV2KSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBIQ0FUYXNrLnJlY3JlYXRlKGV2LmRhdGEpOwogICAgICAgICAgICAgICAgaWYgKHRhc2sub3JpZ2luICE9PSB0aGlzLm9yaWdpbikgewogICAgICAgICAgICAgICAgICAgIC8vIGluY29taW5nIGNtZCB0byBleGVjdXRlCiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5yZXN1bHQgPSB5aWVsZCB0aGlzLnRhc2tIYW5kbGVyKHRhc2spOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBpdCdzIG9ic2VydmVkIHRoYXQgRmlyZWZveCByZWZ1c2VzIHRvIHBvc3RNZXNzYWdlIGFuIEVycm9yIG9iamVjdDoKICAgICAgICAgICAgICAgICAgICAgICAgLy8gIkRhdGFDbG9uZUVycm9yOiBUaGUgb2JqZWN0IGNvdWxkIG5vdCBiZSBjbG9uZWQuIgogICAgICAgICAgICAgICAgICAgICAgICAvLyAob2JzZXJ2ZWQgaW4gRmlyZWZveCA5Nywgbm90IGNsZWFyIGFib3V0IG90aGVyIHZlcnNpb25zKQogICAgICAgICAgICAgICAgICAgICAgICAvLyBDaHJvbWUgZG9lc24ndCBzZWVtIHRvIGhhdmUgdGhpcyBwcm9ibGVtLAogICAgICAgICAgICAgICAgICAgICAgICAvLyBob3dldmVyLCBpbiBvcmRlciB0byBrZWVwIGNvbXBhdGlibGUgd2l0aCBGaXJlZm94LAogICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSBzdGlsbCBoYXZlIHRvIGF2b2lkIHBvc3RpbmcgYW4gRXJyb3Igb2JqZWN0CiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suZXJyTXNnID0gYFske3RoaXMub3JpZ2lufV0gZXJyb3Igd2hlbiBleGVjdXRpbmcgY21kICR7dGFzay5jbWR9IGZyb20gJHt0YXNrLm9yaWdpbn1gOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGUgPT09ICJzdHJpbmciIHx8IGUgaW5zdGFuY2VvZiBFcnJvcikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suZXJyTXNnICs9ICJcbiIgKyBlLnRvU3RyaW5nKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmICh0YXNrLnRhc2tJRCAhPSBIQ0FUYXNrUXVldWUuZGlzY2FyZFJlcGx5VGFza0lEKQogICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZW5kUmVwbHkodGFzayk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFske3RoaXMub3JpZ2lufV0gc2VuZFJlcGx5IGZhaWxlZC5gLCBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suZXJyTXNnID0gKHRhc2suZXJyTXNnID09IG51bGwgPyAiIiA6IHRhc2suZXJyTXNnICsgIlxuXG4iKSArICJwb3N0TWVzc2FnZSBmcm9tIFdvcmtlciBmYWlsZWQiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBlID09PSAic3RyaW5nIiB8fCBlIGluc3RhbmNlb2YgRXJyb3IpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5lcnJNc2cgKz0gIlxuIiArIGUudG9TdHJpbmcoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRyeSBhZ2FpbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZW5kUmVwbHkodGFzayk7IC8vIGlmIGl0IHRocm93cywganVzdCBsZXQgaXQgdGhyb3cKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgLy8gcmVjZWl2aW5nIGNtZCByZXN1bHQKICAgICAgICAgICAgICAgICAgICAvLyBmaW5kICYgdW5yZWdpc3RlciBjYWxsYmFjawogICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlZ2lzdGVyZWQgPSB0aGlzLmNhbGxiYWNrc1t0YXNrLnRhc2tJRF07CiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW3Rhc2sudGFza0lEXTsKICAgICAgICAgICAgICAgICAgICAvLyBhcHBseSBob29rCiAgICAgICAgICAgICAgICAgICAgbGV0IHJlc3VsdCA9IHRhc2suaGFzUmVzdWx0ID8gdGFzay5yZXN1bHQgOiB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaG9vayA9IHJlZ2lzdGVyZWQuaG9vazsKICAgICAgICAgICAgICAgICAgICBpZiAoaG9vayAhPSBudWxsKQogICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRhc2suaGFzRXJyICYmIGhvb2suZXJyb3IgIT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5aWVsZCBob29rLmVycm9yKHRhc2suZXJyTXNnKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHRhc2suaGFzUmVzdWx0ICYmIGhvb2sucmVzdWx0ICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0geWllbGQgaG9vay5yZXN1bHQodGFzay5yZXN1bHQpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRhc2suaGFzRXJyKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suZXJyTXNnID0gIiI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXNrLmVyck1zZyArPSBgWyR7dGhpcy5vcmlnaW59XSBlcnJvciB3aGVuIGFwcGx5aW5nIGhvb2sgYAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgYGFmdGVyIGV4ZWN1dGluZyBjbWQgJHt0YXNrLmNtZH0gZnJvbSAke3Rhc2sub3JpZ2lufWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGUgPT09ICJzdHJpbmciIHx8IGUgaW5zdGFuY2VvZiBFcnJvcikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXNrLmVyck1zZyArPSAiXG4iICsgZS50b1N0cmluZygpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgLy8gc2V0dGxlIHByb21pc2UKICAgICAgICAgICAgICAgICAgICBpZiAodGFzay5oYXNFcnIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmVnaXN0ZXJlZC5yZWplY3QodGFzay5lcnJNc2cpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0YXNrLmhhc1Jlc3VsdCkgewogICAgICAgICAgICAgICAgICAgICAgICByZWdpc3RlcmVkLnJlc29sdmUocmVzdWx0KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHRhc2sgKG9yaWdpbj0ke3Rhc2sub3JpZ2lufSB0YXNrSUQ9JHt0YXNrLnRhc2tJRH0gY21kPSR7dGFzay5jbWR9KSBgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICArIGBoYXMgbmVpdGhlciBlcnJvciBub3IgcmVzdWx0YCk7IC8vIHNob3VsZCBuZXZlciBoYXBwZW4KICAgICAgICAgICAgICAgICAgICAvLyBzdGFydCBuZXh0IHRhc2sKICAgICAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLnNlbmROZXh0VGFzaygpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAvLyBpcnJlY292ZXJhYmxlIGVycm9yCiAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLmVyckhhbmRsZXIoZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgIH0KICAgIGVyckhhbmRsZXIoZGF0YSkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIC8vIGlycmVjb3ZlcmFibGUgZXJyb3IKICAgICAgICAgICAgaWYgKHRoaXMuX2lzQWxpdmUpIHsKICAgICAgICAgICAgICAgIC8vIHByaW50IGVycm9yIG1lc3NhZ2UKICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFske3RoaXMub3JpZ2lufV0gZGVzdHJveWluZyBiYWNrZ3JvdW5kIHdvcmtlciBvbiBpcnJlY292ZXJhYmxlIGVycm9yYCwgZGF0YSk7CiAgICAgICAgICAgICAgICAvLyBkZXN0cm95IGJhY2tncm91bmQgd29ya2VyCiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMuZGVzdHJveSgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBbJHt0aGlzLm9yaWdpbn1dIGVycm9yIHdoZW4gdHJ5aW5nIHRvIGRlc3Ryb3koKWAsIGUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gYWZ0ZXIgZGVzdHJveSwgbWFyayBpc0FsaXZlIGFzIGZhbHNlIChvdGhlcndpc2Ugc2VuZENtZCB3aWxsIGZhaWwpCiAgICAgICAgICAgICAgICB0aGlzLl9pc0FsaXZlID0gZmFsc2U7CiAgICAgICAgICAgICAgICAvLyByZWplY3QgYWxsIHBlbmRpbmcgcHJvbWlzZXMKICAgICAgICAgICAgICAgIGZvciAobGV0IHRhc2tJRCBpbiB0aGlzLmNhbGxiYWNrcykgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlamVjdCA9IHRoaXMuY2FsbGJhY2tzW3Rhc2tJRF0ucmVqZWN0OwogICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1t0YXNrSURdOwogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBbJHt0aGlzLm9yaWdpbn1dIGVycm9yIHJlamVjdGluZyB0YXNrSUQ9JHt0YXNrSUR9YCwgZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICB9CiAgICBnZXRUcmFuc2ZlckNvbmZpZygpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICBpZiAoIXRoaXMuX2lzQWxpdmUpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImRlYWQiKTsKICAgICAgICAgICAgcmV0dXJuIHlpZWxkIHRoaXMuZXhlY0NtZCgibm9wIiwgW10sIHsgcmVzdWx0OiAoKSA9PiAoewogICAgICAgICAgICAgICAgICAgIHRyYW5zZmVyQXJnczogdGhpcy50cmFuc2ZlckFyZ3MsCiAgICAgICAgICAgICAgICAgICAgcmVwbHlBcmdzOiB0aGlzLnJlcGx5QXJncwogICAgICAgICAgICAgICAgfSkgfSk7CiAgICAgICAgfSk7CiAgICB9CiAgICBjb25maWdUcmFuc2Zlcih0cmFuc2ZlckFyZ3MsIHJlcGx5QXJncykgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIGlmICghdGhpcy5faXNBbGl2ZSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiZGVhZCIpOwogICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy5leGVjQ21kKCJub3AiLCBbXSwgeyByZXN1bHQ6ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYW5zZmVyQXJncyA9IHRyYW5zZmVyQXJncyA/IHRydWUgOiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB0aGlzLnJlcGx5QXJncyA9IHJlcGx5QXJncyA/IHRydWUgOiBmYWxzZTsKICAgICAgICAgICAgICAgIH0gfSk7CiAgICAgICAgfSk7CiAgICB9CiAgICBleGVjQ21kKGNtZCwgYXJncywgaG9vaykgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIC8vIGNhbiBiZSBtb2RpZmllZCB0byBzaW1wbHkgd3JhcCBleGVjTXVsdGlDbWQgYnV0IEkganVzdCB3YW50IHRvIGxldCBpdCBhbG9uZSBmb3Igbm8gc3BlY2lhbCByZWFzb24KICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0FsaXZlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJkZWFkIik7CiAgICAgICAgICAgIC8vIGFzc2lnbiBuZXcgdGFza0lECiAgICAgICAgICAgIGNvbnN0IHRhc2tJRCA9IHRoaXMuZ2V0TmV4dFRhc2tJRCgpOwogICAgICAgICAgICBjb25zdCB0YXNrID0gbmV3IEhDQVRhc2sodGhpcy5vcmlnaW4sIHRhc2tJRCwgY21kLCBhcmdzLCB0aGlzLnJlcGx5QXJncyk7CiAgICAgICAgICAgIC8vIHJlZ2lzdGVyIGNhbGxiYWNrCiAgICAgICAgICAgIGlmICh0aGlzLmNhbGxiYWNrc1t0YXNrSURdICE9IG51bGwpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHRhc2tJRD0ke3Rhc2tJRH0gaXMgYWxyZWFkeSBvY2N1cGllZGApOwogICAgICAgICAgICBjb25zdCByZXN1bHRQcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gdGhpcy5jYWxsYmFja3NbdGFza0lEXSA9IHsgcmVzb2x2ZTogcmVzb2x2ZSwgcmVqZWN0OiByZWplY3QsCiAgICAgICAgICAgICAgICBob29rOiBob29rIH0pOwogICAgICAgICAgICAvLyBhcHBlbmQgdG8gY29tbWFuZCBxdWV1ZQogICAgICAgICAgICB0aGlzLnF1ZXVlLnB1c2godGFzayk7CiAgICAgICAgICAgIC8vIHN0YXJ0IGV4ZWN1dGluZyB0YXNrcwogICAgICAgICAgICBpZiAodGhpcy5pc0lkbGUpCiAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLnNlbmROZXh0VGFzaygpOwogICAgICAgICAgICAvLyByZXR1cm4gcmVzdWx0CiAgICAgICAgICAgIHJldHVybiB5aWVsZCByZXN1bHRQcm9taXNlOwogICAgICAgIH0pOwogICAgfQogICAgZXhlY011bHRpQ21kKGNtZExpc3QpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICAvLyB0aGUgcG9pbnQgaXMgdG8gZW5zdXJlICJhdG9taWNpdHkiIGJldHdlZW4gY21kcwogICAgICAgICAgICBpZiAoIXRoaXMuX2lzQWxpdmUpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImRlYWQiKTsKICAgICAgICAgICAgbGV0IHJlc3VsdFByb21pc2VzID0gW107CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY21kTGlzdC5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgLy8gYXNzaWduIG5ldyB0YXNrSUQKICAgICAgICAgICAgICAgIGNvbnN0IHRhc2tJRCA9IHRoaXMuZ2V0TmV4dFRhc2tJRCgpOwogICAgICAgICAgICAgICAgY29uc3QgbGlzdEl0ZW0gPSBjbWRMaXN0W2ldOwogICAgICAgICAgICAgICAgY29uc3QgdGFzayA9IG5ldyBIQ0FUYXNrKHRoaXMub3JpZ2luLCB0YXNrSUQsIGxpc3RJdGVtLmNtZCwgbGlzdEl0ZW0uYXJncywgdGhpcy5yZXBseUFyZ3MpOwogICAgICAgICAgICAgICAgLy8gcmVnaXN0ZXIgY2FsbGJhY2sKICAgICAgICAgICAgICAgIGlmICh0aGlzLmNhbGxiYWNrc1t0YXNrSURdICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB0YXNrSUQ9JHt0YXNrSUR9IGlzIGFscmVhZHkgb2NjdXBpZWRgKTsKICAgICAgICAgICAgICAgIHJlc3VsdFByb21pc2VzLnB1c2gobmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gdGhpcy5jYWxsYmFja3NbdGFza0lEXSA9IHsgcmVzb2x2ZTogcmVzb2x2ZSwgcmVqZWN0OiByZWplY3QsCiAgICAgICAgICAgICAgICAgICAgaG9vazogbGlzdEl0ZW0uaG9vayB9KSk7CiAgICAgICAgICAgICAgICAvLyBhcHBlbmQgdG8gY29tbWFuZCBxdWV1ZQogICAgICAgICAgICAgICAgdGhpcy5xdWV1ZS5wdXNoKHRhc2spOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIHN0YXJ0IGV4ZWN1dGluZyB0YXNrcwogICAgICAgICAgICBpZiAodGhpcy5pc0lkbGUpCiAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLnNlbmROZXh0VGFzaygpOwogICAgICAgICAgICAvLyByZXR1cm4gcmVzdWx0cwogICAgICAgICAgICByZXR1cm4geWllbGQgUHJvbWlzZS5hbGwocmVzdWx0UHJvbWlzZXMpOwogICAgICAgIH0pOwogICAgfQogICAgc2VuZENtZChjbWQsIGFyZ3MpIHsKICAgICAgICAvLyBzZW5kIGNtZCB3aXRob3V0IHJlZ2lzdGVyaW5nIGNhbGxiYWNrCiAgICAgICAgLy8gZ2VuZXJhbGx5IG5vdCByZWNvbW1lbmRlZAogICAgICAgIGlmICghdGhpcy5faXNBbGl2ZSkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJkZWFkIik7CiAgICAgICAgY29uc3QgdGFzayA9IG5ldyBIQ0FUYXNrKHRoaXMub3JpZ2luLCBIQ0FUYXNrUXVldWUuZGlzY2FyZFJlcGx5VGFza0lELCBjbWQsIGFyZ3MsIGZhbHNlKTsKICAgICAgICB0aGlzLnNlbmRUYXNrKHRhc2spOwogICAgfQogICAgc2h1dGRvd24oZm9yY2libHkgPSBmYWxzZSkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIGlmICh0aGlzLl9pc0FsaXZlKSB7CiAgICAgICAgICAgICAgICBpZiAoZm9yY2libHkpIHsKICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLmRlc3Ryb3koKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgWyR7dGhpcy5vcmlnaW59XSBlcnJvciB3aGVuIHRyeWluZyB0byBmb3JjaWJseSBzaHV0ZG93bi5gLCBlKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdGhpcy5faXNBbGl2ZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMuZXhlY0NtZCgibm9wIiwgW10sIHsgcmVzdWx0OiAoKSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLmRlc3Ryb3koKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2lzQWxpdmUgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfSkgfSk7CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgIH0KfQpIQ0FUYXNrUXVldWUubWF4VGFza0lEID0gMjU2OyAvLyB0aGVyZSdzIHJlY3Vyc2lvbiBpbiBzZW5kTmV4dFRhc2sgd2hlbiBtYWtpbmcgZmFrZSByZXBseQpIQ0FUYXNrUXVldWUuZGlzY2FyZFJlcGx5VGFza0lEID0gLTE7CmlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICJ1bmRlZmluZWQiKSB7CiAgICBpZiAodHlwZW9mIG9ubWVzc2FnZSA9PT0gInVuZGVmaW5lZCIpIHsKICAgICAgICAvLyBBdWRpb1dvcmtsZXQKICAgIH0KICAgIGVsc2UgewogICAgICAgIC8vIFdlYiBXb3JrZXIKICAgICAgICBjb25zdCB0YXNrUXVldWUgPSBuZXcgSENBVGFza1F1ZXVlKCJCYWNrZ3JvdW5kLUhDQVdvcmtlciIsIChtc2csIHRyYW5zKSA9PiBwb3N0TWVzc2FnZShtc2csIHRyYW5zKSwgKHRhc2spID0+IHsKICAgICAgICAgICAgc3dpdGNoICh0YXNrLmNtZCkgewogICAgICAgICAgICAgICAgY2FzZSAibm9wIjoKICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICBjYXNlICJmaXhIZWFkZXJDaGVja3N1bSI6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEhDQUluZm8uZml4SGVhZGVyQ2hlY2tzdW0uYXBwbHkoSENBSW5mbywgdGFzay5hcmdzKTsKICAgICAgICAgICAgICAgIGNhc2UgImZpeENoZWNrc3VtIjoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gSENBLmZpeENoZWNrc3VtLmFwcGx5KEhDQSwgdGFzay5hcmdzKTsKICAgICAgICAgICAgICAgIGNhc2UgImRlY3J5cHQiOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBIQ0EuZGVjcnlwdC5hcHBseShIQ0EsIHRhc2suYXJncyk7CiAgICAgICAgICAgICAgICBjYXNlICJlbmNyeXB0IjoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gSENBLmVuY3J5cHQuYXBwbHkoSENBLCB0YXNrLmFyZ3MpOwogICAgICAgICAgICAgICAgY2FzZSAiYWRkQ2lwaGVySGVhZGVyIjoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gSENBSW5mby5hZGRDaXBoZXJIZWFkZXIuYXBwbHkoSENBSW5mbywgdGFzay5hcmdzKTsKICAgICAgICAgICAgICAgIGNhc2UgImRlY29kZSI6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEhDQS5kZWNvZGUuYXBwbHkoSENBLCB0YXNrLmFyZ3MpOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gY21kICR7dGFzay5jbWR9YCk7CiAgICAgICAgICAgIH0KICAgICAgICB9LCAoKSA9PiB7IHRhc2tRdWV1ZS5zZW5kQ21kKCJzZWxmLWRlc3RydWN0IiwgW10pOyB9KTsKICAgICAgICBvbm1lc3NhZ2UgPSAoZXYpID0+IHRhc2tRdWV1ZS5tc2dIYW5kbGVyKGV2KTsKICAgIH0KfQovLyBjcmVhdGUgJiBjb250cm9sIHdvcmtlcgpleHBvcnQgY2xhc3MgSENBV29ya2VyIHsKICAgIGNvbnN0cnVjdG9yKHNlbGZVcmwpIHsKICAgICAgICB0aGlzLmxhc3RUaWNrID0gMDsKICAgICAgICB0aGlzLmhjYVdvcmtlciA9IG5ldyBXb3JrZXIoc2VsZlVybCwgeyB0eXBlOiAibW9kdWxlIiB9KTsgLy8gc2V0dGluZyB0eXBlIHRvICJtb2R1bGUiIGlzIGN1cnJlbnRseSBib2d1cyBpbiBGaXJlZm94CiAgICAgICAgdGhpcy5zZWxmVXJsID0gc2VsZlVybDsKICAgICAgICB0aGlzLnRhc2tRdWV1ZSA9IG5ldyBIQ0FUYXNrUXVldWUoIk1haW4tSENBV29ya2VyIiwgKG1zZywgdHJhbnMpID0+IHRoaXMuaGNhV29ya2VyLnBvc3RNZXNzYWdlKG1zZywgdHJhbnMpLCAodGFzaykgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICBzd2l0Y2ggKHRhc2suY21kKSB7CiAgICAgICAgICAgICAgICBjYXNlICJzZWxmLWRlc3RydWN0IjogLy8gZG9lc24ndCBzZWVtIHRvIGhhdmUgYSBjaGFuY2UgdG8gYmUgY2FsbGVkCiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgaGNhV29ya2VyIHJlcXVlc3RlZCB0byBzZWxmLWRlc3RydWN0YCk7CiAgICAgICAgICAgICAgICAgICAgeWllbGQgdGhpcy50YXNrUXVldWUuc2h1dGRvd24odHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICB9KSwgKCkgPT4gdGhpcy5oY2FXb3JrZXIudGVybWluYXRlKCkpOwogICAgICAgIHRoaXMuaGNhV29ya2VyLm9ubWVzc2FnZSA9IChtc2cpID0+IHRoaXMudGFza1F1ZXVlLm1zZ0hhbmRsZXIobXNnKTsKICAgICAgICB0aGlzLmhjYVdvcmtlci5vbmVycm9yID0gKG1zZykgPT4gdGhpcy50YXNrUXVldWUuZXJySGFuZGxlcihtc2cpOwogICAgICAgIHRoaXMuaGNhV29ya2VyLm9ubWVzc2FnZWVycm9yID0gKG1zZykgPT4gdGhpcy50YXNrUXVldWUuZXJySGFuZGxlcihtc2cpOwogICAgfQogICAgZ2V0IGlzQWxpdmUoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMudGFza1F1ZXVlLmlzQWxpdmU7CiAgICB9CiAgICBzaHV0ZG93bihmb3JjaWJseSA9IGZhbHNlKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgaWYgKHRoaXMudGFza1F1ZXVlLmlzQWxpdmUpCiAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5zaHV0ZG93bihmb3JjaWJseSk7CiAgICAgICAgfSk7CiAgICB9CiAgICB0aWNrKCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHlpZWxkIHRoaXMudGFza1F1ZXVlLmV4ZWNDbWQoIm5vcCIsIFtdKTsKICAgICAgICAgICAgdGhpcy5sYXN0VGljayA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpOwogICAgICAgIH0pOwogICAgfQogICAgdG9jayh0ZXh0ID0gIiIpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5leGVjQ21kKCJub3AiLCBbXSk7CiAgICAgICAgICAgIGNvbnN0IGR1cmF0aW9uID0gbmV3IERhdGUoKS5nZXRUaW1lKCkgLSB0aGlzLmxhc3RUaWNrOwogICAgICAgICAgICBjb25zb2xlLmxvZyhgJHt0ZXh0fSB0b29rICR7ZHVyYXRpb259IG1zYCk7CiAgICAgICAgICAgIHJldHVybiBkdXJhdGlvbjsKICAgICAgICB9KTsKICAgIH0KICAgIHN0YXRpYyBjcmVhdGUoc2VsZlVybCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZlVybCA9PT0gInN0cmluZyIpCiAgICAgICAgICAgICAgICBzZWxmVXJsID0gbmV3IFVSTChzZWxmVXJsLCBkb2N1bWVudC5iYXNlVVJJKTsKICAgICAgICAgICAgZWxzZSBpZiAoIShzZWxmVXJsIGluc3RhbmNlb2YgVVJMKSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigic2VsZlVybCBtdXN0IGJlIGVpdGhlciBzdHJpbmcgb3IgVVJMIik7CiAgICAgICAgICAgIC8vIGZldGNoICYgc2F2ZSBoY2EuanMgYXMgYmxvYiBpbiBhZHZhbmNlLCB0byBhdm9pZCBjcmVhdGluZyB3b3JrZXIgYmVpbmcgYmxvY2tlZCBsYXRlciwgbGlrZToKICAgICAgICAgICAgLy8gKEkgb2JzZXJ2ZWQgdGhpcyBwcm9ibGVtIGluIEZpcmVmb3gpCiAgICAgICAgICAgIC8vIGNyZWF0aW5nIEhDQUF1ZGlvV29ya2xldEhDQVBsYXllciByZXF1aXJlcyBpbmZvcm1hdGlvbiBmcm9tIEhDQSwgd2hpY2ggaXMgc2FtcGxlIHJhdGUgYW5kIGNoYW5uZWwgY291bnQ7CiAgICAgICAgICAgIC8vIGhvd2V2ZXIsIGZldGNoaW5nIEhDQSAob3JpZ2luYWxseSBzdXBwb3NlZCB0byBiZSBwcm9ncmVzc2l2ZS9zdHJlYW1lZCkgYmxvY2tzIGxhdGVyIHJlcXVlc3QgdG8gZmV0Y2ggaGNhLmpzLAogICAgICAgICAgICAvLyBzbyB0aGF0IEhDQUF1ZGlvV29ya2xldEhDQVBsYXllciBjYW4gb25seSBiZSBjcmVhdGVkIGFmdGVyIGZpbmlzaGluZyBkb3dubG9hZGluZyB0aGUgd2hvbGUgSENBLAogICAgICAgICAgICAvLyB3aGljaCBvYnZpb3VzbHkgZGVmZWF0cyB0aGUgcHVycG9zZSBvZiBzdHJlYW1pbmcgSENBCiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0geWllbGQgZmV0Y2goc2VsZlVybC5ocmVmKTsKICAgICAgICAgICAgLy8gRmlyZWZveCBjdXJyZW50bHkgZG9lcyBub3Qgc3VwcG9ydCBFQ01BU2NyaXB0IG1vZHVsZXMgaW4gV29ya2VyLAogICAgICAgICAgICAvLyB0aGVyZWZvcmUgd2UgbXVzdCBzdHJpcCBhbGwgZXhwb3J0IGRlY2xhcmF0aW9ucwogICAgICAgICAgICBjb25zdCBvcmlnVGV4dCA9IHlpZWxkIHJlc3BvbnNlLnRleHQoKTsKICAgICAgICAgICAgY29uc3QgY29udmVydGVkVGV4dCA9ICgiXG4iICsgb3JpZ1RleHQpLnJlcGxhY2UoLygoXG58OylbIFx0XSopKChleHBvcnRbIFx0XStcey4qP1x9WyBcdF0qO3swLDF9KSt8KGV4cG9ydFsgXHRdKykpL2csICIkMSIpLnNsaWNlKDEpOwogICAgICAgICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW2NvbnZlcnRlZFRleHRdLCB7IHR5cGU6ICJ0ZXh0L2phdmFzY3JpcHQiIH0pOwogICAgICAgICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpOwogICAgICAgICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChibG9iKTsKICAgICAgICAgICAgY29uc3QgZGF0YVVSSSA9IHlpZWxkIG5ldyBQcm9taXNlKChyZXMpID0+IHsKICAgICAgICAgICAgICAgIHJlYWRlci5vbmxvYWRlbmQgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmVzKHJlYWRlci5yZXN1bHQpOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHNlbGZVcmwgPSBuZXcgVVJMKGRhdGFVUkksIGRvY3VtZW50LmJhc2VVUkkpOwogICAgICAgICAgICByZXR1cm4gbmV3IEhDQVdvcmtlcihzZWxmVXJsKTsKICAgICAgICB9KTsKICAgIH0KICAgIC8vIGNvbW1hbmRzCiAgICBnZXRUcmFuc2ZlckNvbmZpZygpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy50YXNrUXVldWUuZ2V0VHJhbnNmZXJDb25maWcoKTsKICAgICAgICB9KTsKICAgIH0KICAgIGNvbmZpZ1RyYW5zZmVyKHRyYW5zZmVyQXJncywgcmVwbHlBcmdzKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgcmV0dXJuIHlpZWxkIHRoaXMudGFza1F1ZXVlLmNvbmZpZ1RyYW5zZmVyKHRyYW5zZmVyQXJncywgcmVwbHlBcmdzKTsKICAgICAgICB9KTsKICAgIH0KICAgIGZpeEhlYWRlckNoZWNrc3VtKGhjYSkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5leGVjQ21kKCJmaXhIZWFkZXJDaGVja3N1bSIsIFtoY2FdKTsKICAgICAgICB9KTsKICAgIH0KICAgIGZpeENoZWNrc3VtKGhjYSkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5leGVjQ21kKCJmaXhDaGVja3N1bSIsIFtoY2FdKTsKICAgICAgICB9KTsKICAgIH0KICAgIGRlY3J5cHQoaGNhLCBrZXkxLCBrZXkyKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgcmV0dXJuIHlpZWxkIHRoaXMudGFza1F1ZXVlLmV4ZWNDbWQoImRlY3J5cHQiLCBbaGNhLCBrZXkxLCBrZXkyXSk7CiAgICAgICAgfSk7CiAgICB9CiAgICBlbmNyeXB0KGhjYSwga2V5MSwga2V5MikgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5leGVjQ21kKCJlbmNyeXB0IiwgW2hjYSwga2V5MSwga2V5Ml0pOwogICAgICAgIH0pOwogICAgfQogICAgYWRkSGVhZGVyKGhjYSwgc2lnLCBuZXdEYXRhKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgcmV0dXJuIHlpZWxkIHRoaXMudGFza1F1ZXVlLmV4ZWNDbWQoImFkZEhlYWRlciIsIFtoY2EsIHNpZywgbmV3RGF0YV0pOwogICAgICAgIH0pOwogICAgfQogICAgYWRkQ2lwaGVySGVhZGVyKGhjYSwgY2lwaGVyVHlwZSkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5leGVjQ21kKCJhZGRDaXBoZXJIZWFkZXIiLCBbaGNhLCBjaXBoZXJUeXBlXSk7CiAgICAgICAgfSk7CiAgICB9CiAgICBkZWNvZGUoaGNhLCBtb2RlID0gMzIsIGxvb3AgPSAwLCB2b2x1bWUgPSAxLjApIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy50YXNrUXVldWUuZXhlY0NtZCgiZGVjb2RlIiwgW2hjYSwgbW9kZSwgbG9vcCwgdm9sdW1lXSk7CiAgICAgICAgfSk7CiAgICB9Cn0K", document.baseURI);
var hcaJsModule, hcaJsObjUrl, HCAInfo, HCAWorker;
// mime types
const defMimeType = "application/octet-stream";
const mimeTypeMap = {
wav: "audio/x-wav",
hca: defMimeType,
}
// HCAWorker instance
var worker = null;
// dragged file
var draggedFile = null;
// local file picker
const localfile = document.getElementById("localfile");
const localfileform = document.getElementById("localfileform");
// reset state on refresh
// https://bugzilla.mozilla.org/show_bug.cgi?id=685657
localfileform.reset();
// input HCA URL
const urlinput = document.getElementById("urlinput");
// file name
var fileName = null;
// HCA info table
const hcaInfoTable = {
el: document.getElementById("hcaInfoTable"),
body: {
el: document.getElementById("hcaInfoTable")
.getElementsByTagName('tbody')[0],
defText: document.getElementById("hcaInfoTable")
.getElementsByTagName('tbody')[0]
.getElementsByTagName("td")[0]
.textContent,
data: {},
},
}
Object.defineProperty(hcaInfoTable.body, "data", {
get: function () {return this.value},
set: function (val) {
// clear existing content
for (let i = hcaInfoTable.body.el.getElementsByTagName("tr").length - 1; i >= 0; i--) {
hcaInfoTable.body.el.deleteRow(i);
}
function appendRow(cells, rowspan) {
let newRow = hcaInfoTable.body.el.insertRow(-1);
cells.forEach((val, idx) => {
let newCell = newRow.insertCell(idx);
if (rowspan != null && idx == 0)
newCell.setAttribute("rowspan", rowspan);
if (cells.length < 3 && idx == cells.length - 1)
newCell.setAttribute("colspan", cells.length - idx + 1);
let newText = val != null
? document.createTextNode("" + val)
: (() => {
let italic = document.createElement("i");
italic.innerHTML = "(not defined)";
return italic;
})();
newCell.appendChild(newText);
});
}
function toHex(num) {
const padding = "0000";
let hex = padding + num.toString(padding.length * 4).toUpperCase();
return "0x" + hex.substring(hex.length - padding.length, hex.length)
}
if (val == null || !val instanceof HCAInfo) {
appendRow([hcaInfoTable.body.defText]);
return; // nothing to add
}
// add given content
let info = val;
const hcaInfoTextArray = [
["Version", info.version],
["Header size", info.dataOffset],
["Format", !info.hasHeader["fmt"] ? null : [
["Channels", info.format.channelCount],
["Sampling Rate", info.format.samplingRate],
["Blocks", info.format.blockCount],
["Dropped smpl. (head)", info.format.droppedHeader],
["Dropped smpl. (tail)", info.format.droppedFooter],
]],
["Block size", !info.hasHeader["comp"] && !info.hasHeader["dec"] ? null : info.blockSize],
["Bitrate (kbps)", !info.hasHeader["comp"] && !info.hasHeader["dec"] ? null : info.kbps],
["VBR", info.hasHeader["vbr"] ? "yes" : "no"],
["ATH", !info.hasHeader["ath"] ? null : toHex(info.ath)],
["Loop", !info.hasHeader["loop"] ? null : [
["Start", info.loop.start],
["End", info.loop.end],
["Dropped smpl. (head)", info.loop.droppedHeader],
["Dropped smpl. (tail)", info.loop.droppedFooter],
]],
["Cipher", !info.hasHeader["ciph"] ? null : toHex(info.cipher)],
["RVA (volume)", !info.hasHeader["rva"] ? null : info.rva],
["Comment", !info.hasHeader["comm"] ? null : info.comment],
];
for (let item of hcaInfoTextArray) {
let key = item[0];
let val = item[1];
if (Array.isArray(val)) {
let textList = val[0].slice(0);
textList.unshift(key);
appendRow(textList, val.length);
val.shift();
val.forEach((item) => appendRow(item))
} else {
appendRow([key, val]);
}
}
// update value
this.value = val;
},
});
// keys
const keys = {key1: undefined, key2: undefined};
for (let key in keys) {
Object.defineProperty(keys, key, {
get: function () {return document.getElementById(key + "input").value},
set: function (val) {document.getElementById(key + "input").value = val},
});
}
// mode/loop/volume
const decodingParam = {
mode: {
el: document.getElementById("decodingmodeinput"),
defVal: 16,
},
loop: {
el: document.getElementById("loopcountinput"),
defVal: 0,
},
volumePerCent: {
el: document.getElementById("volumeinput"),
defVal: 100,
},
}
for (let paramName in decodingParam) {
let el = decodingParam[paramName].el;
let defVal = decodingParam[paramName].defVal;
let attr = {};
["min", "max", "step"].forEach((attrName) => attr[attrName] = el.getAttribute(attrName));
let clampVal = function (val) {
if (val == null || val === "")
return defVal;
val = parseInt(val);
if (isNaN(val))
return defVal;
if (val % attr.step != 0)
val = Math.floor(val / attr.step);
else if (val < attr.min)
val = attr.min;
else if (val > attr.max)
val = attr.max;
return val;
}
Object.defineProperty(decodingParam, paramName, {
get: function () {
let clamped = clampVal(el.value);
el.value = "" + clamped;
return clamped;
},
set: function (val) {
el.value = "" + clampVal(val);
}
});
}
// HCA file data
const hcaFileData = {
// original HCA file content
original: {
btnID: "downloadbtn",
data: {},
},
// after fixing checksum
fixed_checksum: {
btnID: "fixcsumbtn",
data: {},
},
// after decryption
decrypted: {
btnID: "decryptbtn",
data: {},
},
// after encryption
encrypted: {
btnID: "encryptbtn",
data: {},
},
// after decoding
decoded: {
btnID: "decodebtn",
data: {},
},
}
for (let suffix in hcaFileData) {
Object.defineProperty(hcaFileData[suffix], "data", {
get: function () {return this.value},
set: function (val) {
this.value = null; // clear existing data
const fileExtRegEx = /\.([^\.]+)$/;
let newFileName = fileName.replace(fileExtRegEx, "_" + suffix + ".$1");
if (suffix === "decoded")
newFileName = newFileName.replace(fileExtRegEx, ".wav");
let id = suffix + "-download-link";
let el = document.getElementById(id);
if (el != null) {
// remove existing download link
URL.revokeObjectURL(el.getAttribute("href"));
el.nextSibling.remove();
el.remove();
}
if (val == null) {
console.log(`hcaFileData ${suffix} cleared`);
return; // nothing to create
}
console.log(`hcaFileData ${suffix} byteLength=${val.byteLength}`);
// create new download link
el = document.createElement("a");
el.setAttribute("id", id);
el.setAttribute("download", newFileName);
let extName = newFileName.match(fileExtRegEx)[0];
let mimeType = mimeTypeMap[extName];
if (mimeType == null) mimeType = defMimeType;
el.setAttribute("href", URL.createObjectURL(new Blob([val], {type: mimeType})));
el.innerHTML = newFileName;
let refNode = document.getElementById(hcaFileData[suffix].btnID).nextSibling;
document.body.insertBefore(document.createElement("br"), refNode);
document.body.insertBefore(el, refNode);
// update value
this.value = val;
},
});
}
function clearAllData() {
localfileform.reset();
for (let suffix in hcaFileData) {
hcaFileData[suffix].data = null;
}
hcaInfoTable.body.data = null;
audioElement.src = null;
console.log(`cleared all data`);
}
// Audio element
const audioElement = {
el: document.getElementById("audioElement"),
src: ""
};
Object.defineProperty(audioElement, "src", {
get: function () {return this.value},
set: function (val) {
if (this.value != null && this.value != "")
URL.revokeObjectURL(this.value);
if (val == null || val === "") {
this.value = audioElement.el.src = "";
return;
}
let newUrl;
if (val instanceof ArrayBuffer || val.buffer instanceof ArrayBuffer) {
newUrl = URL.createObjectURL(new Blob([val], {type: mimeTypeMap.wav}));
} else {
newUrl = val;
}
this.value = audioElement.el.src = newUrl;
}
});
// buttons
const buttons = {
startworkerbtn: async (self) => {
if (worker == null) {
if (hcaJsObjUrl == null) {
const response = await fetch(hcaJsUrl.href);
const blob = new Blob([await response.arrayBuffer()], {type: "text/javascript"});
hcaJsObjUrl = URL.createObjectURL(blob);
}
if (hcaJsModule == null) {
hcaJsModule = await import(hcaJsObjUrl);
}
if (HCAInfo == null) HCAInfo = hcaJsModule.HCAInfo;
if (HCAWorker == null) HCAWorker = hcaJsModule.HCAWorker;
worker = await HCAWorker.create(hcaJsObjUrl);
console.log("started background worker");
}
self.disabled = true; // added because button won't grey out if there's any await above
buttons.shutdownbtn = true;
},
shutdownbtn: async (self) => {
if (worker != null) {
await worker.shutdown();
worker = null;
console.log("background worker is now shut down");
}
self.disabled = true; // added together with above startworkerbtn
buttons.startworkerbtn = true;
},
loadfilebtn: async (self) => {
let file = null;
if (draggedFile != null) {
self.textContent = "loading dragged file...";
file = draggedFile;
draggedFile = null;
} else {
self.textContent = "loading picked file...";
file = localfile.files[0];
}
let newFileName = file.name;
// update fileName
fileName = newFileName;
// clear all existing data
clearAllData();
resetButtonsExcept(self.id);
// update data
let ab = await file.arrayBuffer();
hcaFileData.original.data = new Uint8Array(ab);
self.textContent = "load picked file (successful)";
// let the button bounce
self.disabled = false;
// next step
buttons.infobtn = true;
buttons.fixcsumbtn = true;
},
downloadbtn: async (self) => {
self.textContent = "downloading...";
let requestUrl = urlinput.value;
if (requestUrl === "") {
self.textContent = "download (empty URL)";
self.disabled = false;
return;
}
let response = null;
try {
response = await fetch(requestUrl);
} catch (e) {
console.error(e);
self.textContent = "download (network error)";
self.disabled = false;
return;
}
if (response.status != 200) {
console.error("download failed,", response);
self.textContent = `download (failed, ${response.status} ${response.statusText})`;
self.disabled = false;
return;
}
// get filename from Content-Disposition
let cd = response.headers.get("Content-Disposition");
let newFileName = null;
if (cd != null) {
let splitted = cd.split(";");
let cdFileName = splitted.find((substr) => substr.startsWith("filename="));
if (cdFileName != null) {
newFileName = cdFileName.substring("filename=".length)
.replaceAll(" ", "")
.replaceAll("\"", "");
}
}
// failed to get filename from Content-Disposition, try URL
const fileNameRegEx = /[^\/^\\]+$/;
if (newFileName == null || newFileName === "") {
let urlFilename = [response.url, requestUrl].find((url) => url != null && url.match(fileNameRegEx));
if (urlFilename != null)
newFileName = urlFilename.match(fileNameRegEx)[0];
}
// failed to get filename, use default filename
if (newFileName == null || newFileName === "") {
newFileName = "downloaded.hca";
}
// strip query string
let stripped = newFileName.match(/^[^\?]+/);
if (stripped != null)
newFileName = stripped[0];
// update fileName
fileName = newFileName;
// clear all existing data
clearAllData();
resetButtonsExcept(self.id);
// update data
let ab = await response.arrayBuffer();
hcaFileData.original.data = new Uint8Array(ab);
self.textContent = "download (successful)";
// let the button bounce
self.disabled = false;
// next step
buttons.infobtn = true;
buttons.fixcsumbtn = true;
},
infobtn: async (self) => {
let hca = hcaFileData[
["fixed_checksum", "original"].find((suffix) => {
if (hcaFileData[suffix].data != null) {
console.log(`get HCA info from ${suffix} file data`);
return true;
}
})
].data;
try {
let info = new HCAInfo(hca);
self.textContent = "get HCA info (successful)";
// update table content
hcaInfoTable.body.data = info;
// next step
let isEncrypted = info.hasHeader["ciph"] && info.cipher !=0;
buttons.encryptbtn = !isEncrypted;
buttons.decryptbtn = isEncrypted;
buttons.decodebtn = !isEncrypted;
} catch (e) {
console.error(e);
self.textContent = "get HCA info (failed)";
}
// let the button bounce
self.disabled = false;
},
fixcsumbtn: async (self) => {
try {
worker.tick();
let newHcaPromise = worker.fixChecksum(hcaFileData.original.data);
worker.tock("fix checksum");
let newHca = await newHcaPromise;
// update data
hcaFileData.fixed_checksum.data = newHca;
self.textContent = "fix checksum (successful)";
} catch (e) {
console.error(e);
self.textContent = "fix checksum (failed)";
}
// let the button bounce
self.disabled = false;
},
encryptbtn: async (self) => {
await encryptOrDecrypt(self, true);
// let the button bounce
self.disabled = false;
},
decryptbtn: async (self) => {
await encryptOrDecrypt(self, false);
// let the button bounce
self.disabled = false;
},
decodebtn: async (self) => {
// prepare data
let hca = hcaFileData[
["decrypted", "fixed_checksum", "original"].find((suffix) => {
if (hcaFileData[suffix].data != null) {
console.log(`decoding ${suffix} data...`);
return true;
}
})
].data;
// start decoding
try {
worker.tick();
let decodedPromise = worker.decode(hca,
decodingParam.mode, decodingParam.loop, decodingParam.volumePerCent / 100);
worker.tock("decoding");
let decoded = await decodedPromise;
// update data
hcaFileData.decoded.data = decoded;
self.textContent = "decode (done)";
// next step (play)
audioElement.src = decoded;
} catch (e) {
console.error(e);
self.textContent = "decode (failed)";
}
// let the button bounce
self.disabled = false;
},
};
const _buttons = {};
for (let id in buttons) {
let el = document.getElementById(id);
let onclick = buttons[id];
el.onclick = (ev) => {
let self = ev.srcElement;
self.disabled = true;
onclick(self);
}
const initialText = el.textContent;
Object.defineProperty(buttons, id, {
get: function () {return !el.disabled},
set: function (val) {
if (val === "click") {
el.disabled = true;
onclick(el);
return;
}
el.textContent = initialText;
el.disabled = !val;
},
});
Object.defineProperty(_buttons, id, {
get: function () {return onclick;},
});
}
buttons.startworkerbtn = "click"; // start background worker
function resetButtonsExcept(exceptBtnID) {
for (let btnID in buttons) {
if (btnID !== exceptBtnID) switch (btnID) {
case "startworkerbtn":
buttons[btnID] = worker == null || !worker.isAlive;
break;
case "shutdownbtn":
buttons[btnID] = worker != null && worker.isAlive;
break;
case "loadfilebtn":
buttons[btnID] = false;
break;
case "downloadbtn":
buttons[btnID] = true;
break;
default:
buttons[btnID] = false;
}
}
}
resetButtonsExcept(); // same to above, reset state on refresh
async function encryptOrDecrypt(self, isEncrypting) {
const action = isEncrypting ? "encrypt" : "decrypt";
const opposite = isEncrypting ? "decrypt" : "encrypt";
// disable both buttons
self.disabled = true;
buttons[opposite + "btn"] = false;
self.textContent = action + "ing...";
// disable decodebtn if necessary
if (!isEncrypting)
buttons.decodebtn = false
// prepare data
let hca = hcaFileData[
[opposite + "ed", "fixed_checksum", "original"].find((suffix) => {
if (hcaFileData[suffix].data != null) {
console.log(`${action}ing ${suffix} data...`);
return true;
}
})
].data;
if (isEncrypting && !hcaInfoTable.body.data.hasHeader["ciph"]) {
// check for ciph header section
console.log("input HCA lacks ciph header section, adding it");
hca = await worker.addCipherHeader(hca);
} else {
hca = hca.slice(0); // just copy to new buffer
}
// start to encrypt/decrypt
try {
worker.tick();
// although decryption/encryption is done in-place,
// however since we are not using SharedArrayBuffer,
// the background worker is still actually overwritting a newly allocated buffer
let resultPromise = worker[action](hca, keys.key1, keys.key2);
worker.tock(isEncrypting ? "encryption" : "decryption");
let result = await resultPromise;
self.textContent = action + " (done)";
// update data
hcaFileData[action + "ed"].data = result;
// next steps
buttons[opposite + "btn"] = true;
if (!isEncrypting)
buttons.decodebtn = true;
} catch (e) {
console.error(e);
self.textContent = "Error during " + (isEncrypting ? "encryption" : "decryption");
}
}
</script>
</body>
</html>