forked from y2361547758/hca.js
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhca-standalone.html
1097 lines (1071 loc) · 285 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
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!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>
<a href="https://github.com/y2361547758/hca.js">GitHub repo</a>
<hr>
<button disabled id="startworkerbtn">start background worker</button><br>
<button disabled id="shutdownbtn">shutdown background worker</button><br>
<hr>
<h3>Choose a HCA or AWB 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"><br>
<input type="checkbox" id="hcaonly" checked>
<label for="hcaonly">pick HCA file only (uncheck if unable to pick)</label><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="bgm22_battle01_hca.hca"><br>
<button id="downloadbtn">download</button><br>
<div id="awbsubsongswitcher"></div>
<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>(optional) </i>subkey=<input type="text" spellcheck="false" id="subkeyinput" value="0x0"><br>
<i>Note: output waveform will be (almostly all) silence if incorrect keys are given!</i><br>
<hr>
<h3>Streaming (<a href="https://developer.mozilla.org/en-US/docs/Web/API/AudioWorklet">AudioWorklet API</a>)</h3>
<input type="checkbox" checked id="awautoplayondrop">
<label for="awautoplyondrop">Automatically play drag & dropped HCA file</label><br>
<b><u>Some browsers like Safari (Apple WebKit) may lock AudioContext initially, which blocks auto-play.<br>
To unlock AudioContext (so that auto-play will no longer be blocked),<br>
please click anywhere on this page after drag & drop.</u></b><br>
Load a HCA file for playing, which has been fully loaded/downloaded above:<br>
<button id="awloadwholehcabtn">Load</button><br>
Load directly from the URL above, without fully downloading the whole file:<br>
<button id="awloadfromurlbtn">Load</button><br>
Progress control:<br>
<input type="checkbox" id="awplayinbackground">
<label for="awplayinbackground">Play in background (may glitch)</label><br>
<button id="awresumebtn">Play/Resume</button><br>
<button id="awpausebtn">Pause</button><br>
<button id="awstopbtn">Stop</button><br>
<a href="#volumeslider">Volume control</a> (in "decoding parameters" section)<br>
<hr>
<h3>Decode the whole file</h3>
Note:<br>
(1) <b>Please click "get HCA info" button first.</b><br>
(2) Setting decoding mode to <b>zero means 32-bit float mode</b>, or <b>8/16/24/32-bit integer mode</b>
otherwise.<br>
(3) Loop count is <b>ignored if HCA header doesn't have loop section</b><br>
(4) 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>
(5) When <b>decoding the whole file</b>, setting loop count to <b>zero</b> means: <b>disabling loop</b>.</b><br>
<fieldset>
<legend>HCA info</legend>
<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>
</fieldset>
<fieldset>
<legend>Checksum</legend>
<button disabled id="fixcsumbtn">fix checksum</button><br>
</fieldset>
<fieldset>
<legend>Cipher</legend>
<button disabled id="encryptbtn">encrypt</button><br>
<button disabled id="decryptbtn">decrypt</button><br>
</fieldset>
<fieldset>
<legend>Decoding parameters</legend>
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="range" step="1" min="0" max="100" placeholder="0-100" id="volumeslider" value="100">
<input type="number" step="1" min="0" max="100" placeholder="0-100" id="volumeinput" value="100"><br>
<i>This volume control affects <a href="#awresumebtn">AudioWorklet</a> and <a
href="#webaudioplaybtn">WebAudio</a> playing as well.</i><br>
</fieldset>
<fieldset>
<legend>Decode to HTML5 Audio</legend>
<button disabled id="decodetoh5btn">decode</button><br>
<audio id="audioElement" controls></audio><br>
</fieldset>
<fieldset>
<legend>Decode to WebAudio AudioBufferSourceNode</legend>
<b>Playing will seamlessly loop if HCA supports looping.</b><br>
<button disabled id="decodetowabtn">decode</button><br>
<input type="checkbox" id="webaudioplayinbackground">
<label for="webaudioplayinbackground">Play in background (may glitch)</label><br>
<button disabled id="webaudioplaybtn">Play</button><br>
<button disabled id="webaudiopausebtn">Pause</button><br>
<button disabled id="webaudiostopbtn">Stop</button><br>
</fieldset>
<!-- <script src="https://unpkg.com/@ffmpeg/[email protected]/dist/ffmpeg.min.js"></script> -->
<script>
var AWBSubsongSelect = null;
</script>
<script type="module">
const hcaJsUrl = new URL("data:text/javascript;base64,dmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7CiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH0KICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH0KICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvclsidGhyb3ciXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9CiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH0KICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7CiAgICB9KTsKfTsKdmFyIF9hLCBfYjsKZXhwb3J0IGNsYXNzIEhDQUluZm8gewogICAgc3RhdGljIGdldFNpZ24ocmF3LCBvZmZzZXQgPSAwLCBjaGFuZ2VNYXNrLCBlbmNyeXB0KSB7CiAgICAgICAgbGV0IG1hZ2ljID0gcmF3LmdldFVpbnQzMihvZmZzZXQsIHRydWUpOwogICAgICAgIGxldCBzdHJMZW4gPSA0OwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChyYXcuZ2V0VWludDgob2Zmc2V0ICsgaSkgPT0gMCkgewogICAgICAgICAgICAgICAgc3RyTGVuID0gaTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChzdHJMZW4gPiAwKSB7CiAgICAgICAgICAgIGxldCBtYXNrID0gMHg4MDgwODA4MCA+Pj4gOCAqICg0IC0gc3RyTGVuKTsKICAgICAgICAgICAgbWFnaWMgJj0gMHg3ZjdmN2Y3ZjsKICAgICAgICAgICAgaWYgKGNoYW5nZU1hc2spCiAgICAgICAgICAgICAgICByYXcuc2V0VWludDMyKG9mZnNldCwgZW5jcnlwdCA/IG1hZ2ljIHwgbWFzayA6IG1hZ2ljLCB0cnVlKTsKICAgICAgICB9CiAgICAgICAgbGV0IGhleCA9IFttYWdpYyAmIDB4ZmYsIG1hZ2ljID4+IDggJiAweGZmLCBtYWdpYyA+PiAxNiAmIDB4ZmYsIG1hZ2ljID4+IDI0ICYgMHhmZl07CiAgICAgICAgaGV4ID0gaGV4LnNsaWNlKDAsIHN0ckxlbik7CiAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBoZXgpOwogICAgfQogICAgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBIQ0FJbmZvKHRoaXMucmF3SGVhZGVyKTsKICAgIH0KICAgIHBhcnNlSGVhZGVyKGhjYSwgY2hhbmdlTWFzaywgZW5jcnlwdCwgbW9kTGlzdCkgewogICAgICAgIGxldCBwID0gbmV3IERhdGFWaWV3KGhjYS5idWZmZXIsIGhjYS5ieXRlT2Zmc2V0LCA4KTsKICAgICAgICBsZXQgaGVhZCA9IEhDQUluZm8uZ2V0U2lnbihwLCAwLCBmYWxzZSwgZW5jcnlwdCk7IC8vIGRvIG5vdCBvdmVyd3JpdGUgZm9yIG5vdywgdW50aWwgY2hlY2tzdW0gdmVyaWZpZWQKICAgICAgICBpZiAoaGVhZCAhPT0gIkhDQSIpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJOb3QgYSBIQ0EgZmlsZSIpOwogICAgICAgIH0KICAgICAgICBjb25zdCB2ZXJzaW9uID0gewogICAgICAgICAgICBtYWluOiBwLmdldFVpbnQ4KDQpLAogICAgICAgICAgICBzdWI6IHAuZ2V0VWludDgoNSkKICAgICAgICB9OwogICAgICAgIHRoaXMudmVyc2lvbiA9IHZlcnNpb24ubWFpbiArICcuJyArIHZlcnNpb24uc3ViOwogICAgICAgIHRoaXMudmVyc2lvbk1ham9yID0gdmVyc2lvbi5tYWluOwogICAgICAgIHRoaXMudmVyc2lvbk1pbm9yID0gdmVyc2lvbi5zdWI7CiAgICAgICAgdGhpcy5kYXRhT2Zmc2V0ID0gcC5nZXRVaW50MTYoNik7CiAgICAgICAgLy8gdmVyaWZ5IGNoZWNrc3VtCiAgICAgICAgSENBQ3JjMTYudmVyaWZ5KGhjYSwgdGhpcy5kYXRhT2Zmc2V0IC0gMik7CiAgICAgICAgbGV0IGhhc01vZERvbmUgPSBmYWxzZTsKICAgICAgICAvLyBjaGVja3N1bSB2ZXJpZmllZCwgbm93IHdlIGNhbiBvdmVyd3JpdGUgaXQKICAgICAgICBpZiAoY2hhbmdlTWFzaykKICAgICAgICAgICAgSENBSW5mby5nZXRTaWduKHAsIDAsIGNoYW5nZU1hc2ssIGVuY3J5cHQpOwogICAgICAgIC8vIHBhcnNlIHRoZSBoZWFkZXIKICAgICAgICBwID0gbmV3IERhdGFWaWV3KGhjYS5idWZmZXIsIGhjYS5ieXRlT2Zmc2V0LCB0aGlzLmRhdGFPZmZzZXQpOwogICAgICAgIGxldCBmdGVsbCA9IDg7CiAgICAgICAgd2hpbGUgKGZ0ZWxsIDwgdGhpcy5kYXRhT2Zmc2V0IC0gMikgewogICAgICAgICAgICBsZXQgbGFzdEZ0ZWxsID0gZnRlbGw7CiAgICAgICAgICAgIC8vIGdldCB0aGUgc2lnCiAgICAgICAgICAgIGxldCBzaWduID0gSENBSW5mby5nZXRTaWduKHAsIGZ0ZWxsLCBjaGFuZ2VNYXNrLCBlbmNyeXB0KTsKICAgICAgICAgICAgLy8gcmVjb3JkIGhhc0hlYWRlcgogICAgICAgICAgICB0aGlzLmhhc0hlYWRlcltzaWduXSA9IHRydWU7CiAgICAgICAgICAgIC8vIHBhZGRpbmcgc2hvdWxkIGJlIHRoZSBsYXN0IG9uZQogICAgICAgICAgICBpZiAoc2lnbiA9PSAicGFkIikgewogICAgICAgICAgICAgICAgdGhpcy5oZWFkZXJPZmZzZXRbc2lnbl0gPSBbZnRlbGwsIHRoaXMuZGF0YU9mZnNldCAtIDJdOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gcGFyc2UgZGF0YSBhY2NvcmRpbmdseQogICAgICAgICAgICBzd2l0Y2ggKHNpZ24pIHsKICAgICAgICAgICAgICAgIGNhc2UgImZtdCI6CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtYXQuY2hhbm5lbENvdW50ID0gcC5nZXRVaW50OChmdGVsbCArIDQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZm9ybWF0LnNhbXBsaW5nUmF0ZSA9IHAuZ2V0VWludDMyKGZ0ZWxsICsgNCkgJiAweDAwZmZmZmZmOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZm9ybWF0LmJsb2NrQ291bnQgPSBwLmdldFVpbnQzMihmdGVsbCArIDgpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZm9ybWF0LmRyb3BwZWRIZWFkZXIgPSBwLmdldFVpbnQxNihmdGVsbCArIDEyKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm1hdC5kcm9wcGVkRm9vdGVyID0gcC5nZXRVaW50MTYoZnRlbGwgKyAxNCk7CiAgICAgICAgICAgICAgICAgICAgZnRlbGwgKz0gMTY7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJjb21wIjoKICAgICAgICAgICAgICAgICAgICB0aGlzLmJsb2NrU2l6ZSA9IHAuZ2V0VWludDE2KGZ0ZWxsICsgNCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5rYnBzID0gdGhpcy5mb3JtYXQuc2FtcGxpbmdSYXRlICogdGhpcy5ibG9ja1NpemUgLyAxMjgwMDAuMDsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuTWluUmVzb2x1dGlvbiA9IHAuZ2V0VWludDgoZnRlbGwgKyA2KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuTWF4UmVzb2x1dGlvbiA9IHAuZ2V0VWludDgoZnRlbGwgKyA3KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuVHJhY2tDb3VudCA9IHAuZ2V0VWludDgoZnRlbGwgKyA4KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuQ2hhbm5lbENvbmZpZyA9IHAuZ2V0VWludDgoZnRlbGwgKyA5KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuVG90YWxCYW5kQ291bnQgPSBwLmdldFVpbnQ4KGZ0ZWxsICsgMTApOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcERlYy5CYXNlQmFuZENvdW50ID0gcC5nZXRVaW50OChmdGVsbCArIDExKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuU3RlcmVvQmFuZENvdW50ID0gcC5nZXRVaW50OChmdGVsbCArIDEyKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuQmFuZHNQZXJIZnJHcm91cCA9IHAuZ2V0VWludDgoZnRlbGwgKyAxMyk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLlJlc2VydmVkMSA9IHAuZ2V0VWludDgoZnRlbGwgKyAxNCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLlJlc2VydmVkMiA9IHAuZ2V0VWludDgoZnRlbGwgKyAxNSk7CiAgICAgICAgICAgICAgICAgICAgZnRlbGwgKz0gMTY7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJkZWMiOgogICAgICAgICAgICAgICAgICAgIHRoaXMuYmxvY2tTaXplID0gcC5nZXRVaW50MTYoZnRlbGwgKyA0KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmticHMgPSB0aGlzLmZvcm1hdC5zYW1wbGluZ1JhdGUgKiB0aGlzLmJsb2NrU2l6ZSAvIDEyODAwMC4wOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcERlYy5NaW5SZXNvbHV0aW9uID0gcC5nZXRVaW50OChmdGVsbCArIDYpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcERlYy5NYXhSZXNvbHV0aW9uID0gcC5nZXRVaW50OChmdGVsbCArIDcpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcERlYy5Ub3RhbEJhbmRDb3VudCA9IHAuZ2V0VWludDgoZnRlbGwgKyA4KTsKICAgICAgICAgICAgICAgICAgICArMTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuQmFzZUJhbmRDb3VudCA9IHAuZ2V0VWludDgoZnRlbGwgKyA5KTsKICAgICAgICAgICAgICAgICAgICArMTsKICAgICAgICAgICAgICAgICAgICBsZXQgYSA9IHAuZ2V0VWludDgoZnRlbGwgKyAxMCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLlRyYWNrQ291bnQgPSBIQ0FVdGlsRnVuYy5HZXRIaWdoTmliYmxlKGEpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcERlYy5DaGFubmVsQ29uZmlnID0gSENBVXRpbEZ1bmMuR2V0TG93TmliYmxlKGEpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZGVjLkRlY1N0ZXJlb1R5cGUgPSBwLmdldFVpbnQ4KGZ0ZWxsICsgMTEpOwogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlYy5EZWNTdGVyZW9UeXBlID09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wRGVjLkJhc2VCYW5kQ291bnQgPSB0aGlzLmNvbXBEZWMuVG90YWxCYW5kQ291bnQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBEZWMuU3RlcmVvQmFuZENvdW50ID0gdGhpcy5jb21wRGVjLlRvdGFsQmFuZENvdW50IC0gdGhpcy5jb21wRGVjLkJhc2VCYW5kQ291bnQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZ0ZWxsICs9IDEyOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAidmJyIjoKICAgICAgICAgICAgICAgICAgICBmdGVsbCArPSA4OwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiYXRoIjoKICAgICAgICAgICAgICAgICAgICB0aGlzLlVzZUF0aEN1cnZlID0gcC5nZXRVaW50MTYoZnRlbGwgKyA0KSA9PSAxOwogICAgICAgICAgICAgICAgICAgIGZ0ZWxsICs9IDY7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJsb29wIjoKICAgICAgICAgICAgICAgICAgICB0aGlzLmxvb3Auc3RhcnQgPSBwLmdldFVpbnQzMihmdGVsbCArIDQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMubG9vcC5lbmQgPSBwLmdldFVpbnQzMihmdGVsbCArIDgpOwogICAgICAgICAgICAgICAgICAgIHRoaXMubG9vcC5kcm9wcGVkSGVhZGVyID0gcC5nZXRVaW50MTYoZnRlbGwgKyAxMik7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb29wLmRyb3BwZWRGb290ZXIgPSBwLmdldFVpbnQxNihmdGVsbCArIDE0KTsKICAgICAgICAgICAgICAgICAgICBmdGVsbCArPSAxNjsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgImNpcGgiOgogICAgICAgICAgICAgICAgICAgIHRoaXMuY2lwaGVyID0gcC5nZXRVaW50MTYoZnRlbGwgKyA0KTsKICAgICAgICAgICAgICAgICAgICBmdGVsbCArPSA2OwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAicnZhIjoKICAgICAgICAgICAgICAgICAgICB0aGlzLnJ2YSA9IHAuZ2V0RmxvYXQzMihmdGVsbCArIDQpOwogICAgICAgICAgICAgICAgICAgIGZ0ZWxsICs9IDg7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJ2YnIiOgogICAgICAgICAgICAgICAgICAgIHRoaXMudmJyLk1heEJsb2NrU2l6ZSA9IHAuZ2V0VWludDE2KGZ0ZWxsICsgNCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy52YnIuTm9pc2VMZXZlbCA9IHAuZ2V0SW50MTYoZnRlbGwgKyA2KTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgImNvbW0iOgogICAgICAgICAgICAgICAgICAgIGxldCBsZW4gPSBwLmdldFVpbnQ4KGZ0ZWxsICsgNCk7CiAgICAgICAgICAgICAgICAgICAgbGV0IGppc2RlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoJ3NoaWZ0LWppcycpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWVudCA9IGppc2RlY29kZXIuZGVjb2RlKGhjYS5zbGljZShmdGVsbCArIDUsIGZ0ZWxsICsgNSArIGxlbikpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDogdGhyb3cgbmV3IEVycm9yKCJ1bmtub3duIGhlYWRlciBzaWciKTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyByZWNvcmQgaGVhZGVyT2Zmc2V0CiAgICAgICAgICAgIHRoaXMuaGVhZGVyT2Zmc2V0W3NpZ25dID0gW2xhc3RGdGVsbCwgZnRlbGxdOwogICAgICAgICAgICAvLyBkbyBtb2RpZmljYXRpb24gaWYgbmVlZGVkCiAgICAgICAgICAgIGxldCBzZWN0aW9uRGF0YUxlbiA9IGZ0ZWxsIC0gbGFzdEZ0ZWxsIC0gNDsKICAgICAgICAgICAgbGV0IG5ld0RhdGEgPSBtb2RMaXN0W3NpZ25dOwogICAgICAgICAgICBpZiAobmV3RGF0YSAhPSBudWxsKSB7CiAgICAgICAgICAgICAgICBpZiAobmV3RGF0YS5ieXRlTGVuZ3RoID4gc2VjdGlvbkRhdGFMZW4pCiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgICAgICAgICBoY2Euc2V0KG5ld0RhdGEsIGxhc3RGdGVsbCArIDQpOwogICAgICAgICAgICAgICAgaGFzTW9kRG9uZSA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoKICAgICAgICAvLyAocG9ydGVkIGZyb20pIE55YWdhbW9uJ3Mgb3JpZ2luYWwgY29kZSwgc2hvdWxkIGJlIChhbG1vc3QpIGVxdWl2YWxlbnQgdG8gQ2FsY3VsYXRlSGZyVmFsdWVzCiAgICAgICAgdGhpcy5jb21wUGFyYW1bMl0gPSB0aGlzLmNvbXBQYXJhbVsyXSB8fCAxOwogICAgICAgIGxldCBfYSA9IHRoaXMuY29tcFBhcmFtWzRdIC0gdGhpcy5jb21wUGFyYW1bNV0gLSB0aGlzLmNvbXBQYXJhbVs2XTsKICAgICAgICBsZXQgX2IgPSB0aGlzLmNvbXBQYXJhbVs3XTsKICAgICAgICB0aGlzLmNvbXBEZWMuUmVzZXJ2ZWQxID0gX2IgPiAwID8gX2EgLyBfYiArIChfYSAlIF9iID8gMSA6IDApIDogMDsKICAgICAgICAvLyBUcmFuc2xhdGluZyB0aGUgYWJvdmUgY29kZSB3aXRoIG1lYW5pbmdmdWwgdmFyaWFibGUgbmFtZXM6CiAgICAgICAgdGhpcy5jb21wRGVjLlRyYWNrQ291bnQgPSB0aGlzLmNvbXBEZWMuVHJhY2tDb3VudCB8fCAxOwogICAgICAgIHRoaXMuY29tcERlYy5IZnJCYW5kQ291bnQgPSB0aGlzLmNvbXBEZWMuVG90YWxCYW5kQ291bnQgLSB0aGlzLmNvbXBEZWMuQmFzZUJhbmRDb3VudCAtIHRoaXMuY29tcERlYy5TdGVyZW9CYW5kQ291bnQ7CiAgICAgICAgdGhpcy5IZnJHcm91cENvdW50ID0gdGhpcy5jb21wRGVjLkJhbmRzUGVySGZyR3JvdXA7CiAgICAgICAgdGhpcy5jb21wRGVjLlJlc2VydmVkMSA9IHRoaXMuSGZyR3JvdXBDb3VudCA+IDAgPyB0aGlzLmNvbXBEZWMuSGZyQmFuZENvdW50IC8gdGhpcy5IZnJHcm91cENvdW50ICsgKHRoaXMuY29tcERlYy5IZnJCYW5kQ291bnQgJSB0aGlzLkhmckdyb3VwQ291bnQgPyAxIDogMCkgOiAwOwogICAgICAgICovCiAgICAgICAgLy8gQ2FsY3VsYXRlSGZyVmFsdWVzLCBwb3J0ZWQgZnJvbSBWR0F1ZGlvCiAgICAgICAgaWYgKHRoaXMuY29tcERlYy5CYW5kc1Blckhmckdyb3VwID4gMCkgewogICAgICAgICAgICB0aGlzLmNvbXBEZWMuSGZyQmFuZENvdW50ID0gdGhpcy5jb21wRGVjLlRvdGFsQmFuZENvdW50IC0gdGhpcy5jb21wRGVjLkJhc2VCYW5kQ291bnQgLSB0aGlzLmNvbXBEZWMuU3RlcmVvQmFuZENvdW50OwogICAgICAgICAgICB0aGlzLkhmckdyb3VwQ291bnQgPSBIQ0FVdGlsRnVuYy5EaXZpZGVCeVJvdW5kVXAodGhpcy5jb21wRGVjLkhmckJhbmRDb3VudCwgdGhpcy5jb21wRGVjLkJhbmRzUGVySGZyR3JvdXApOwogICAgICAgIH0KICAgICAgICAvLyBjYWxjdWxhdGUgc2FtcGxlIGNvdW50L29mZnNldHMKICAgICAgICB0aGlzLmZ1bGxTYW1wbGVDb3VudCA9IHRoaXMuZm9ybWF0LmJsb2NrQ291bnQgKiBIQ0FGcmFtZS5TYW1wbGVzUGVyRnJhbWU7CiAgICAgICAgdGhpcy5zdGFydEF0U2FtcGxlID0gdGhpcy5mb3JtYXQuZHJvcHBlZEhlYWRlcjsKICAgICAgICB0aGlzLmZ1bGxFbmRBdFNhbXBsZSA9IHRoaXMuZnVsbFNhbXBsZUNvdW50IC0gdGhpcy5mb3JtYXQuZHJvcHBlZEZvb3RlcjsKICAgICAgICBpZiAodGhpcy5oYXNIZWFkZXJbImxvb3AiXSkgewogICAgICAgICAgICB0aGlzLmxvb3BTdGFydEF0U2FtcGxlID0gdGhpcy5sb29wLnN0YXJ0ICogSENBRnJhbWUuU2FtcGxlc1BlckZyYW1lICsgdGhpcy5sb29wLmRyb3BwZWRIZWFkZXI7CiAgICAgICAgICAgIHRoaXMubG9vcEVuZEF0U2FtcGxlID0gKHRoaXMubG9vcC5lbmQgKyAxKSAqIEhDQUZyYW1lLlNhbXBsZXNQZXJGcmFtZSAtIHRoaXMubG9vcC5kcm9wcGVkRm9vdGVyOwogICAgICAgICAgICB0aGlzLmxvb3BTYW1wbGVDb3VudCA9IHRoaXMubG9vcEVuZEF0U2FtcGxlIC0gdGhpcy5sb29wU3RhcnRBdFNhbXBsZTsKICAgICAgICAgICAgdGhpcy5sb29wU3RhcnRUaW1lID0gKHRoaXMubG9vcFN0YXJ0QXRTYW1wbGUgLSB0aGlzLnN0YXJ0QXRTYW1wbGUpIC8gdGhpcy5mb3JtYXQuc2FtcGxpbmdSYXRlOwogICAgICAgICAgICB0aGlzLmxvb3BEdXJhdGlvbiA9IHRoaXMubG9vcFNhbXBsZUNvdW50IC8gdGhpcy5mb3JtYXQuc2FtcGxpbmdSYXRlOwogICAgICAgICAgICB0aGlzLmxvb3BFbmRUaW1lID0gdGhpcy5sb29wU3RhcnRUaW1lICsgdGhpcy5sb29wRHVyYXRpb247CiAgICAgICAgfQogICAgICAgIHRoaXMuZW5kQXRTYW1wbGUgPSB0aGlzLmhhc0hlYWRlclsibG9vcCJdID8gdGhpcy5sb29wRW5kQXRTYW1wbGUgOiB0aGlzLmZ1bGxFbmRBdFNhbXBsZTsKICAgICAgICB0aGlzLnNhbXBsZUNvdW50ID0gdGhpcy5lbmRBdFNhbXBsZSAtIHRoaXMuc3RhcnRBdFNhbXBsZTsKICAgICAgICB0aGlzLmR1cmF0aW9uID0gdGhpcy5zYW1wbGVDb3VudCAvIHRoaXMuZm9ybWF0LnNhbXBsaW5nUmF0ZTsKICAgICAgICAvLyBjYWxjdWxhdGUgZmlsZS9kYXRhIHNpemUKICAgICAgICB0aGlzLmRhdGFTaXplID0gdGhpcy5ibG9ja1NpemUgKiB0aGlzLmZvcm1hdC5ibG9ja0NvdW50OwogICAgICAgIHRoaXMuZnVsbFNpemUgPSB0aGlzLmRhdGFPZmZzZXQgKyB0aGlzLmRhdGFTaXplOwogICAgICAgIGlmIChjaGFuZ2VNYXNrIHx8IGhhc01vZERvbmUpIHsKICAgICAgICAgICAgLy8gZml4IGNoZWNrc3VtIGlmIHJlcXVlc3RlZAogICAgICAgICAgICBIQ0FDcmMxNi5maXgoaGNhLCB0aGlzLmRhdGFPZmZzZXQgLSAyKTsKICAgICAgICB9CiAgICAgICAgbGV0IHJhd0hlYWRlciA9IGhjYS5zbGljZSgwLCB0aGlzLmRhdGFPZmZzZXQpOwogICAgICAgIC8vIGNoZWNrIHZhbGlkaXR5IG9mIHBhcnNlZCB2YWx1ZXMKICAgICAgICB0aGlzLmNoZWNrVmFsaWRpdHkoKTsKICAgICAgICByZXR1cm4gcmF3SGVhZGVyOwogICAgfQogICAgY2hlY2tWYWxpZGl0eSgpIHsKICAgICAgICBjb25zdCByZXN1bHRzID0gWwogICAgICAgICAgICB0aGlzLmJsb2NrU2l6ZSA+IDAsCiAgICAgICAgICAgIDAgPCB0aGlzLmZvcm1hdC5ibG9ja0NvdW50LAogICAgICAgICAgICAwIDw9IHRoaXMuc3RhcnRBdFNhbXBsZSwKICAgICAgICAgICAgdGhpcy5zdGFydEF0U2FtcGxlIDwgdGhpcy5mdWxsRW5kQXRTYW1wbGUsCiAgICAgICAgICAgIHRoaXMuZnVsbEVuZEF0U2FtcGxlIDw9IHRoaXMuZnVsbFNhbXBsZUNvdW50LAogICAgICAgICAgICB0aGlzLmR1cmF0aW9uID4gMCwKICAgICAgICBdOwogICAgICAgIHJlc3VsdHMuZmluZCgocmVzdWx0LCBpbmRleCkgPT4gewogICAgICAgICAgICBpZiAoIXJlc3VsdCkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBkaWQgbm90IHBhc3Mgbm9ybWFsIGNoZWNrIG9uIHJ1bGUgJHtpbmRleH1gKTsKICAgICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIGlmICh0aGlzLmhhc0hlYWRlclsibG9vcCJdKSB7CiAgICAgICAgICAgIGNvbnN0IGxvb3BDaGVja3MgPSBbCiAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0QXRTYW1wbGUgPD0gdGhpcy5sb29wU3RhcnRBdFNhbXBsZSwKICAgICAgICAgICAgICAgIHRoaXMubG9vcFN0YXJ0QXRTYW1wbGUgPCB0aGlzLmxvb3BFbmRBdFNhbXBsZSwKICAgICAgICAgICAgICAgIHRoaXMubG9vcEVuZEF0U2FtcGxlIDw9IHRoaXMuZnVsbEVuZEF0U2FtcGxlLAogICAgICAgICAgICAgICAgMCA8PSB0aGlzLmxvb3BTdGFydFRpbWUsCiAgICAgICAgICAgICAgICB0aGlzLmxvb3BTdGFydFRpbWUgPCB0aGlzLmxvb3BFbmRUaW1lLAogICAgICAgICAgICAgICAgdGhpcy5sb29wRW5kVGltZSA8PSB0aGlzLmR1cmF0aW9uICsgMS4wIC8gdGhpcy5mb3JtYXQuc2FtcGxpbmdSYXRlLAogICAgICAgICAgICBdOwogICAgICAgICAgICBsb29wQ2hlY2tzLmZpbmQoKHJlc3VsdCwgaW5kZXgpID0+IHsKICAgICAgICAgICAgICAgIGlmICghcmVzdWx0KSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBkaWQgbm90IHBhc3MgbG9vcCBjaGVjayBvbiBydWxlICR7aW5kZXh9YCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgIH0KICAgIGdldFJhd0hlYWRlcigpIHsKICAgICAgICByZXR1cm4gdGhpcy5yYXdIZWFkZXIuc2xpY2UoMCk7CiAgICB9CiAgICBpc0hlYWRlckNoYW5nZWQoaGNhKSB7CiAgICAgICAgaWYgKGhjYS5sZW5ndGggPj0gdGhpcy5yYXdIZWFkZXIubGVuZ3RoKSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5yYXdIZWFkZXIubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIGlmIChoY2FbaV0gIT0gdGhpcy5yYXdIZWFkZXJbaV0pIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIG1vZGlmeShoY2EsIHNpZywgbmV3RGF0YSkgewogICAgICAgIC8vIHJlcGFyc2UgaGVhZGVyIGlmIG5lZWRlZAogICAgICAgIGlmICh0aGlzLmlzSGVhZGVyQ2hhbmdlZChoY2EpKSB7CiAgICAgICAgICAgIHRoaXMucGFyc2VIZWFkZXIoaGNhLCBmYWxzZSwgZmFsc2UsIHt9KTsKICAgICAgICB9CiAgICAgICAgLy8gcHJlcGFyZSB0byBtb2RpZnkgZGF0YSBpbi1wbGFjZQogICAgICAgIGxldCBtb2RMaXN0ID0ge307CiAgICAgICAgbW9kTGlzdFtzaWddID0gbmV3RGF0YTsKICAgICAgICBsZXQgZW5jcnlwdCA9IHRoaXMuY2lwaGVyICE9IDA7CiAgICAgICAgaWYgKHNpZyA9PT0gImNpcGgiKSB7CiAgICAgICAgICAgIGVuY3J5cHQgPSBuZXcgRGF0YVZpZXcobmV3RGF0YS5idWZmZXIsIG5ld0RhdGEuYnl0ZU9mZnNldCwgbmV3RGF0YS5ieXRlTGVuZ3RoKS5nZXRVaW50MTYoMCkgIT0gMDsKICAgICAgICB9CiAgICAgICAgLy8gZG8gYWN0dWFsIG1vZGlmaWNhdGlvbiAmIGNoZWNrIHZhbGlkaXR5CiAgICAgICAgdGhpcy5yYXdIZWFkZXIgPSB0aGlzLnBhcnNlSGVhZGVyKGhjYSwgdHJ1ZSwgZW5jcnlwdCwgbW9kTGlzdCk7CiAgICB9CiAgICBzdGF0aWMgYWRkSGVhZGVyKGhjYSwgc2lnLCBuZXdEYXRhKSB7CiAgICAgICAgLy8gc2lnIG11c3QgY29uc2lzdCBvZiAxLTQgQVNDSUkgY2hhcmFjdGVycwogICAgICAgIGlmIChzaWcubGVuZ3RoIDwgMSB8fCBzaWcubGVuZ3RoID4gNCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgbGV0IG5ld1NpZyA9IG5ldyBVaW50OEFycmF5KDQpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgaSsrKSB7CiAgICAgICAgICAgIGxldCBjID0gc2lnLmNoYXJDb2RlQXQoaSk7CiAgICAgICAgICAgIGlmIChjID49IDB4ODApCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAgICAgbmV3U2lnW2ldID0gYzsKICAgICAgICB9CiAgICAgICAgLy8gcGFyc2UgaGVhZGVyICYgY2hlY2sgdmFsaWR0eQogICAgICAgIGxldCBpbmZvID0gbmV3IEhDQUluZm8oaGNhKTsKICAgICAgICAvLyBjaGVjayB3aGV0aGVyIHNwZWNpZmllZCBoZWFkZXIgc2VjdGlvbiBhbHJlYWR5IGV4aXN0cwogICAgICAgIGlmIChpbmZvLmhhc0hlYWRlcltzaWddKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGhlYWRlciBzZWN0aW9uICR7c2lnfSBhbHJlYWR5IGV4aXN0c2ApOwogICAgICAgIC8vIHByZXBhcmUgYSBuZXdseSBhbGxvY2F0ZWQgYnVmZmVyCiAgICAgICAgbGV0IG5ld0hjYSA9IG5ldyBVaW50OEFycmF5KGhjYS5ieXRlTGVuZ3RoICsgbmV3U2lnLmJ5dGVMZW5ndGggKyBuZXdEYXRhLmJ5dGVMZW5ndGgpOwogICAgICAgIGxldCBpbnNlcnRPZmZzZXQgPSBpbmZvLmhlYWRlck9mZnNldFsicGFkIl1bMF07CiAgICAgICAgLy8gY29weSBleGlzdGluZyBoZWFkZXJzIChleGNlcHQgcGFkZGluZykKICAgICAgICBuZXdIY2Euc2V0KGhjYS5zdWJhcnJheSgwLCBpbnNlcnRPZmZzZXQpLCAwKTsKICAgICAgICAvLyBjb3B5IGluc2VydGVkIGhlYWRlcgogICAgICAgIG5ld0hjYS5zZXQobmV3U2lnLCBpbnNlcnRPZmZzZXQpOwogICAgICAgIG5ld0hjYS5zZXQobmV3RGF0YSwgaW5zZXJ0T2Zmc2V0ICsgbmV3U2lnLmJ5dGVMZW5ndGgpOwogICAgICAgIC8vIGNvcHkgcmVtYWluaW5nIGRhdGEgKHBhZGRpbmcgYW5kIGJsb2NrcykKICAgICAgICBuZXdIY2Euc2V0KGhjYS5zdWJhcnJheShpbnNlcnRPZmZzZXQsIGhjYS5ieXRlTGVuZ3RoKSwgaW5zZXJ0T2Zmc2V0ICsgbmV3U2lnLmJ5dGVMZW5ndGggKyBuZXdEYXRhLmJ5dGVMZW5ndGgpOwogICAgICAgIC8vIHVwZGF0ZSBkYXRhT2Zmc2V0CiAgICAgICAgaW5mby5kYXRhT2Zmc2V0ICs9IG5ld1NpZy5ieXRlTGVuZ3RoICsgbmV3RGF0YS5ieXRlTGVuZ3RoOwogICAgICAgIGxldCBwID0gbmV3IERhdGFWaWV3KG5ld0hjYS5idWZmZXIsIG5ld0hjYS5ieXRlT2Zmc2V0LCBuZXdIY2EuYnl0ZUxlbmd0aCk7CiAgICAgICAgcC5zZXRJbnQxNig2LCBpbmZvLmRhdGFPZmZzZXQpOwogICAgICAgIC8vIGZpeCBjaGVja3N1bQogICAgICAgIEhDQUNyYzE2LmZpeChuZXdIY2EsIGluZm8uZGF0YU9mZnNldCAtIDIpOwogICAgICAgIC8vIHJlcGFyc2UgaGVhZGVyICYgcmVjaGVjayB2YWxpZHR5CiAgICAgICAgaW5mbyA9IG5ldyBIQ0FJbmZvKG5ld0hjYSk7CiAgICAgICAgcmV0dXJuIG5ld0hjYTsKICAgIH0KICAgIHN0YXRpYyBhZGRDaXBoZXJIZWFkZXIoaGNhLCBjaXBoZXJUeXBlKSB7CiAgICAgICAgbGV0IG5ld0RhdGEgPSBuZXcgVWludDhBcnJheSgyKTsKICAgICAgICBpZiAoY2lwaGVyVHlwZSAhPSBudWxsKQogICAgICAgICAgICBuZXcgRGF0YVZpZXcobmV3RGF0YS5idWZmZXIpLnNldFVpbnQxNigwLCBjaXBoZXJUeXBlKTsKICAgICAgICByZXR1cm4gdGhpcy5hZGRIZWFkZXIoaGNhLCAiY2lwaCIsIG5ld0RhdGEpOwogICAgfQogICAgc3RhdGljIGZpeEhlYWRlckNoZWNrc3VtKGhjYSkgewogICAgICAgIGxldCBwID0gbmV3IERhdGFWaWV3KGhjYS5idWZmZXIsIGhjYS5ieXRlT2Zmc2V0LCA4KTsKICAgICAgICBsZXQgaGVhZCA9IHRoaXMuZ2V0U2lnbihwLCAwLCBmYWxzZSwgZmFsc2UpOwogICAgICAgIGlmIChoZWFkICE9PSAiSENBIikgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIk5vdCBhIEhDQSBmaWxlIik7CiAgICAgICAgfQogICAgICAgIGxldCBkYXRhT2Zmc2V0ID0gcC5nZXRVaW50MTYoNik7CiAgICAgICAgSENBQ3JjMTYuZml4KGhjYSwgZGF0YU9mZnNldCAtIDIpOwogICAgICAgIHJldHVybiBoY2E7CiAgICB9CiAgICBjYWxjSW5XYXZTaXplKG1vZGUgPSAzMikgewogICAgICAgIHN3aXRjaCAobW9kZSkgewogICAgICAgICAgICBjYXNlIDA6IC8vIGZsb2F0CiAgICAgICAgICAgIGNhc2UgODoKICAgICAgICAgICAgY2FzZSAxNjoKICAgICAgICAgICAgY2FzZSAyNDoKICAgICAgICAgICAgY2FzZSAzMjogLy8gaW50ZWdlcgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBtb2RlID0gMzI7CiAgICAgICAgfQogICAgICAgIGxldCBiaXRzUGVyU2FtcGxlID0gbW9kZSA9PSAwID8gMzIgOiBtb2RlOwogICAgICAgIGxldCBzYW1wbGVTaXplSW5XYXYgPSB0aGlzLmZvcm1hdC5jaGFubmVsQ291bnQgKiBiaXRzUGVyU2FtcGxlIC8gODsKICAgICAgICByZXR1cm4gdGhpcy5pbldhdlNpemUgPSB7CiAgICAgICAgICAgIGJpdHNQZXJTYW1wbGU6IGJpdHNQZXJTYW1wbGUsCiAgICAgICAgICAgIHNhbXBsZTogc2FtcGxlU2l6ZUluV2F2LAogICAgICAgICAgICBibG9jazogSENBRnJhbWUuU2FtcGxlc1BlckZyYW1lICogc2FtcGxlU2l6ZUluV2F2LAogICAgICAgICAgICBkcm9wcGVkOiB7CiAgICAgICAgICAgICAgICBoZWFkZXI6IHRoaXMuZm9ybWF0LmRyb3BwZWRIZWFkZXIgKiBzYW1wbGVTaXplSW5XYXYsCiAgICAgICAgICAgICAgICBmb290ZXI6IHRoaXMuZm9ybWF0LmRyb3BwZWRGb290ZXIgKiBzYW1wbGVTaXplSW5XYXYsCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGxvb3A6IHRoaXMuaGFzSGVhZGVyWyJsb29wIl0gPyB7CiAgICAgICAgICAgICAgICBsb29wUGFydDogKHRoaXMubG9vcEVuZEF0U2FtcGxlIC0gdGhpcy5sb29wU3RhcnRBdFNhbXBsZSkgKiBzYW1wbGVTaXplSW5XYXYsCiAgICAgICAgICAgICAgICBkcm9wcGVkOiB7CiAgICAgICAgICAgICAgICAgICAgaGVhZGVyOiB0aGlzLmxvb3AuZHJvcHBlZEhlYWRlciAqIHNhbXBsZVNpemVJbldhdiwKICAgICAgICAgICAgICAgICAgICBmb290ZXI6IHRoaXMubG9vcC5kcm9wcGVkRm9vdGVyICogc2FtcGxlU2l6ZUluV2F2LAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IDogdW5kZWZpbmVkLAogICAgICAgIH07CiAgICB9CiAgICBjb25zdHJ1Y3RvcihoY2EsIGNoYW5nZU1hc2sgPSBmYWxzZSwgZW5jcnlwdCA9IGZhbHNlKSB7CiAgICAgICAgdGhpcy52ZXJzaW9uID0gIiI7CiAgICAgICAgdGhpcy52ZXJzaW9uTWFqb3IgPSAyOwogICAgICAgIHRoaXMudmVyc2lvbk1pbm9yID0gMDsKICAgICAgICB0aGlzLmRhdGFPZmZzZXQgPSAwOwogICAgICAgIHRoaXMuZm9ybWF0ID0gewogICAgICAgICAgICBjaGFubmVsQ291bnQ6IDAsCiAgICAgICAgICAgIHNhbXBsaW5nUmF0ZTogMCwKICAgICAgICAgICAgYmxvY2tDb3VudDogMCwKICAgICAgICAgICAgZHJvcHBlZEhlYWRlcjogMCwKICAgICAgICAgICAgZHJvcHBlZEZvb3RlcjogMAogICAgICAgIH07CiAgICAgICAgdGhpcy5ibG9ja1NpemUgPSAwOwogICAgICAgIHRoaXMuaGFzSGVhZGVyID0ge307CiAgICAgICAgdGhpcy5oZWFkZXJPZmZzZXQgPSB7fTsgLy8gW3N0YXJ0IChpbmNsdXNpdmUpLCBlbmQgKGV4Y2x1c2l2ZSldCiAgICAgICAgdGhpcy5rYnBzID0gMDsKICAgICAgICB0aGlzLmNvbXBEZWMgPSB7CiAgICAgICAgICAgIE1pblJlc29sdXRpb246IDAsCiAgICAgICAgICAgIE1heFJlc29sdXRpb246IDAsCiAgICAgICAgICAgIFRyYWNrQ291bnQ6IDAsCiAgICAgICAgICAgIENoYW5uZWxDb25maWc6IDAsCiAgICAgICAgICAgIFRvdGFsQmFuZENvdW50OiAwLAogICAgICAgICAgICBCYXNlQmFuZENvdW50OiAwLAogICAgICAgICAgICBTdGVyZW9CYW5kQ291bnQ6IDAsCiAgICAgICAgICAgIEhmckJhbmRDb3VudDogMCwKICAgICAgICAgICAgQmFuZHNQZXJIZnJHcm91cDogMCwKICAgICAgICAgICAgUmVzZXJ2ZWQxOiAwLAogICAgICAgICAgICBSZXNlcnZlZDI6IDAsCiAgICAgICAgfTsKICAgICAgICB0aGlzLmRlYyA9IHsKICAgICAgICAgICAgRGVjU3RlcmVvVHlwZTogMCwKICAgICAgICB9OwogICAgICAgIHRoaXMubG9vcCA9IHsKICAgICAgICAgICAgc3RhcnQ6IDAsCiAgICAgICAgICAgIGVuZDogMCwKICAgICAgICAgICAgLy8gY291bnQ6IDAsIC8vIE55YWdhbW9uJ3MgaW50ZXJwcmV0YXRpb24KICAgICAgICAgICAgLy8gcjAxOiAwLAogICAgICAgICAgICBkcm9wcGVkSGVhZGVyOiAwLAogICAgICAgICAgICBkcm9wcGVkRm9vdGVyOiAwLAogICAgICAgIH07CiAgICAgICAgdGhpcy52YnIgPSB7CiAgICAgICAgICAgIE1heEJsb2NrU2l6ZTogMCwKICAgICAgICAgICAgTm9pc2VMZXZlbDogMCwKICAgICAgICB9OwogICAgICAgIHRoaXMuVXNlQXRoQ3VydmUgPSBmYWxzZTsKICAgICAgICB0aGlzLmNpcGhlciA9IDA7CiAgICAgICAgdGhpcy5ydmEgPSAwLjA7CiAgICAgICAgdGhpcy5jb21tZW50ID0gIiI7CiAgICAgICAgLy8gY29tcHV0ZWQgc2FtcGxlIGNvdW50L29mZnNldHMKICAgICAgICB0aGlzLkhmckdyb3VwQ291bnQgPSAwOwogICAgICAgIHRoaXMuZnVsbFNhbXBsZUNvdW50ID0gMDsKICAgICAgICB0aGlzLnN0YXJ0QXRTYW1wbGUgPSAwOwogICAgICAgIHRoaXMuZnVsbEVuZEF0U2FtcGxlID0gMDsKICAgICAgICB0aGlzLmxvb3BTdGFydEF0U2FtcGxlID0gMDsKICAgICAgICB0aGlzLmxvb3BFbmRBdFNhbXBsZSA9IDA7CiAgICAgICAgdGhpcy5sb29wU2FtcGxlQ291bnQgPSAwOwogICAgICAgIHRoaXMubG9vcFN0YXJ0VGltZSA9IDA7IC8vIGluIHNlY29uZHMKICAgICAgICB0aGlzLmxvb3BFbmRUaW1lID0gMDsgLy8gaW4gc2Vjb25kcwogICAgICAgIHRoaXMubG9vcER1cmF0aW9uID0gMDsgLy8gaW4gc2Vjb25kcwogICAgICAgIHRoaXMuZW5kQXRTYW1wbGUgPSAwOwogICAgICAgIHRoaXMuc2FtcGxlQ291bnQgPSAwOwogICAgICAgIHRoaXMuZHVyYXRpb24gPSAwOyAvLyBpbiBzZWNvbmRzCiAgICAgICAgLy8gZnVsbCBmaWxlIHNpemUgLyBkYXRhIHBhcnQgKGV4Y2x1ZGluZyBoZWFkZXIsIGp1c3QgYmxvY2tzL2ZyYW1lcykgc2l6ZQogICAgICAgIHRoaXMuZnVsbFNpemUgPSAwOwogICAgICAgIHRoaXMuZGF0YVNpemUgPSAwOwogICAgICAgIC8vIGlmIGNoYW5nZU1hc2sgPT0gdHJ1ZSwgKHVuKW1hc2sgdGhlIGhlYWRlciBzaWdzIGluLXBsYWNlCiAgICAgICAgdGhpcy5yYXdIZWFkZXIgPSB0aGlzLnBhcnNlSGVhZGVyKGhjYSwgY2hhbmdlTWFzaywgZW5jcnlwdCwge30pOwogICAgfQp9CmNsYXNzIEhDQVV0aWxGdW5jIHsKICAgIHN0YXRpYyBEaXZpZGVCeVJvdW5kVXAodmFsdWUsIGRpdmlzb3IpIHsKICAgICAgICByZXR1cm4gTWF0aC5jZWlsKHZhbHVlIC8gZGl2aXNvcik7CiAgICB9CiAgICBzdGF0aWMgR2V0SGlnaE5pYmJsZSh2YWx1ZSkgewogICAgICAgIGlmICh2YWx1ZSA+IDB4ZmYpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIGlmICh2YWx1ZSA8IC0weDgwKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICByZXR1cm4gKHZhbHVlID4+PiA0KSAmIDB4RjsKICAgIH0KICAgIHN0YXRpYyBHZXRMb3dOaWJibGUodmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPiAweGZmKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICBpZiAodmFsdWUgPCAtMHg4MCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgcmV0dXJuIHZhbHVlICYgMHhGOwogICAgfQogICAgc3RhdGljIEdldEhpZ2hOaWJibGVTaWduZWQodmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPiAweGZmKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICBpZiAodmFsdWUgPCAtMHg4MCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgcmV0dXJuIHRoaXMuU2lnbmVkTmliYmxlc1sodmFsdWUgPj4+IDQpICYgMHhGXTsKICAgIH0KICAgIHN0YXRpYyBHZXRMb3dOaWJibGVTaWduZWQodmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPiAweGZmKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICBpZiAodmFsdWUgPCAtMHg4MCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgcmV0dXJuIHRoaXMuU2lnbmVkTmliYmxlc1t2YWx1ZSAmIDB4Rl07CiAgICB9CiAgICBzdGF0aWMgQ29tYmluZU5pYmJsZXMoaGlnaCwgbG93KSB7CiAgICAgICAgcmV0dXJuICgoaGlnaCA8PCA0KSB8IChsb3cgJiAweEYpKSAmIDB4RkY7CiAgICB9CiAgICBzdGF0aWMgR2V0TmV4dE11bHRpcGxlKHZhbHVlLCBtdWx0aXBsZSkgewogICAgICAgIGlmIChtdWx0aXBsZSA8PSAwKQogICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgaWYgKHZhbHVlICUgbXVsdGlwbGUgPT0gMCkKICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgIHJldHVybiB2YWx1ZSArIG11bHRpcGxlIC0gdmFsdWUgJSBtdWx0aXBsZTsKICAgIH0KICAgIHN0YXRpYyBTaWduZWRCaXRSZXZlcnNlMzIodmFsdWUpIHsKICAgICAgICBpZiAodmFsdWUgPiAweGZmZmZmZmZmKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICBpZiAodmFsdWUgPCAtMHg4MDAwMDAwMCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgdmFsdWUgPSAoKHZhbHVlICYgMHhhYWFhYWFhYSkgPj4+IDEpIHwgKCh2YWx1ZSAmIDB4NTU1NTU1NTUpIDw8IDEpOwogICAgICAgIHZhbHVlID0gKCh2YWx1ZSAmIDB4Y2NjY2NjY2MpID4+PiAyKSB8ICgodmFsdWUgJiAweDMzMzMzMzMzKSA8PCAyKTsKICAgICAgICB2YWx1ZSA9ICgodmFsdWUgJiAweGYwZjBmMGYwKSA+Pj4gNCkgfCAoKHZhbHVlICYgMHgwZjBmMGYwZikgPDwgNCk7CiAgICAgICAgdmFsdWUgPSAoKHZhbHVlICYgMHhmZjAwZmYwMCkgPj4+IDgpIHwgKCh2YWx1ZSAmIDB4MDBmZjAwZmYpIDw8IDgpOwogICAgICAgIHJldHVybiAoKHZhbHVlICYgMHhmZmZmMDAwMCkgPj4+IDE2KSB8ICgodmFsdWUgJiAweDAwMDBmZmZmKSA8PCAxNik7CiAgICB9CiAgICBzdGF0aWMgVW5zaWduZWRCaXRSZXZlcnNlMzIodmFsdWUpIHsKICAgICAgICByZXR1cm4gdGhpcy5TaWduZWRCaXRSZXZlcnNlMzIodmFsdWUpID4+PiAwOwogICAgfQogICAgc3RhdGljIFVuc2lnbmVkQml0UmV2ZXJzZTMyVHJ1bmModmFsdWUsIGJpdENvdW50KSB7CiAgICAgICAgcmV0dXJuIHRoaXMuVW5zaWduZWRCaXRSZXZlcnNlMzIodmFsdWUpID4+PiAoMzIgLSBiaXRDb3VudCk7CiAgICB9CiAgICBzdGF0aWMgU2lnbmVkQml0UmV2ZXJzZTMyVHJ1bmModmFsdWUsIGJpdENvdW50KSB7CiAgICAgICAgcmV0dXJuIHRoaXMuVW5zaWduZWRCaXRSZXZlcnNlMzJUcnVuYyh2YWx1ZSA+Pj4gMCwgYml0Q291bnQpOwogICAgfQogICAgc3RhdGljIEJpdFJldmVyc2U4KHZhbHVlKSB7CiAgICAgICAgaWYgKHZhbHVlID4gMHhmZikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgaWYgKHZhbHVlIDwgLTB4ODApCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIHZhbHVlID4+Pj0gMDsKICAgICAgICB2YWx1ZSA9ICgodmFsdWUgJiAweGFhKSA+Pj4gMSkgfCAoKHZhbHVlICYgMHg1NSkgPDwgMSk7CiAgICAgICAgdmFsdWUgPSAoKHZhbHVlICYgMHhjYykgPj4+IDIpIHwgKCh2YWx1ZSAmIDB4MzMpIDw8IDIpOwogICAgICAgIHJldHVybiAoKCh2YWx1ZSAmIDB4ZjApID4+PiA0KSB8ICgodmFsdWUgJiAweDBmKSA8PCA0KSkgPj4+IDA7CiAgICB9CiAgICBzdGF0aWMgQ2xhbXAodmFsdWUsIG1pbiwgbWF4KSB7CiAgICAgICAgaWYgKHZhbHVlIDwgbWluKQogICAgICAgICAgICByZXR1cm4gbWluOwogICAgICAgIGlmICh2YWx1ZSA+IG1heCkKICAgICAgICAgICAgcmV0dXJuIG1heDsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICB9CiAgICBzdGF0aWMgRGVidWdBc3NlcnQoY29uZGl0aW9uKSB7CiAgICAgICAgaWYgKCFjb25kaXRpb24pCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiRGVidWdBc3NlcnQgZmFpbGVkIik7CiAgICB9Cn0KSENBVXRpbEZ1bmMuU2lnbmVkTmliYmxlcyA9IFswLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCAtOCwgLTcsIC02LCAtNSwgLTQsIC0zLCAtMiwgLTFdOwpleHBvcnQgY2xhc3MgSENBIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgfQogICAgc3RhdGljIGRlY3J5cHQoaGNhLCBrZXkxLCBrZXkyLCBzdWJrZXkpIHsKICAgICAgICByZXR1cm4gdGhpcy5kZWNyeXB0T3JFbmNyeXB0KGhjYSwgZmFsc2UsIGtleTEsIGtleTIsIHN1YmtleSk7CiAgICB9CiAgICBzdGF0aWMgZW5jcnlwdChoY2EsIGtleTEsIGtleTIsIHN1YmtleSkgewogICAgICAgIHJldHVybiB0aGlzLmRlY3J5cHRPckVuY3J5cHQoaGNhLCB0cnVlLCBrZXkxLCBrZXkyLCBzdWJrZXkpOwogICAgfQogICAgc3RhdGljIGRlY3J5cHRPckVuY3J5cHQoaGNhLCBlbmNyeXB0LCBrZXkxLCBrZXkyLCBzdWJrZXkpIHsKICAgICAgICAvLyBpbi1wbGFjZSBkZWNyeXB0aW9uL2VuY3J5cHRpb24KICAgICAgICAvLyBoYW5kbGUgc3Via2V5CiAgICAgICAgbGV0IG1peGVkID0gSENBQ2lwaGVyLm1peFdpdGhTdWJrZXkoa2V5MSwga2V5Miwgc3Via2V5KTsKICAgICAgICBrZXkxID0gbWl4ZWQua2V5MTsKICAgICAgICBrZXkyID0gbWl4ZWQua2V5MjsKICAgICAgICAvLyBwYXJzZSBoZWFkZXIKICAgICAgICBsZXQgaW5mbyA9IG5ldyBIQ0FJbmZvKGhjYSk7IC8vIHRocm93cyAiTm90IGEgSENBIGZpbGUiIGlmIG1pc21hdGNoCiAgICAgICAgaWYgKCFlbmNyeXB0ICYmICFpbmZvLmhhc0hlYWRlclsiY2lwaCJdKSB7CiAgICAgICAgICAgIHJldHVybiBoY2E7IC8vIG5vdCBlbmNyeXB0ZWQKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoZW5jcnlwdCAmJiAhaW5mby5oYXNIZWFkZXJbImNpcGgiXSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIklucHV0IGhjYSBsYWNrcyBcImNpcGhcIiBoZWFkZXIgc2VjdGlvbi4gUGxlYXNlIGNhbGwgSENBSW5mby5hZGRDaXBoZXJIZWFkZXIoaGNhKSBmaXJzdC4iKTsKICAgICAgICB9CiAgICAgICAgbGV0IGNpcGhlcjsKICAgICAgICBzd2l0Y2ggKGluZm8uY2lwaGVyKSB7CiAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIC8vIG5vdCBlbmNyeXB0ZWQKICAgICAgICAgICAgICAgIGlmIChlbmNyeXB0KQogICAgICAgICAgICAgICAgICAgIGNpcGhlciA9IG5ldyBIQ0FDaXBoZXIoa2V5MSwga2V5MikuaW52ZXJ0VGFibGUoKTsKICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICByZXR1cm4gaGNhOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICAgIC8vIGVuY3J5cHRlZCB3aXRoICJubyBrZXkiCiAgICAgICAgICAgICAgICBpZiAoZW5jcnlwdCkKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImFscmVhZHkgZW5jcnlwdGVkIHdpdGggXCJubyBrZXlcIiwgcGxlYXNlIGRlY3J5cHQgZmlyc3QiKTsKICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICBjaXBoZXIgPSBuZXcgSENBQ2lwaGVyKCJub25lIik7IC8vIGlnbm9yZSBnaXZlbiBrZXlzCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDM4OgogICAgICAgICAgICAgICAgLy8gZW5jcnlwdGVkIHdpdGgga2V5cyAtIHdpbGwgeWllbGQgaW5jb3JyZWN0IHdhdmVmb3JtIGlmIGluY29ycmVjdCBrZXlzIGFyZSBnaXZlbiEKICAgICAgICAgICAgICAgIGlmIChlbmNyeXB0KQogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiYWxyZWFkeSBlbmNyeXB0ZWQgd2l0aCBzcGVjaWZpYyBrZXlzLCBwbGVhc2UgZGVjcnlwdCB3aXRoIGNvcnJlY3Qga2V5cyBmaXJzdCIpOwogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIGNpcGhlciA9IG5ldyBIQ0FDaXBoZXIoa2V5MSwga2V5Mik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigidW5rbm93biBjaXBoLnR5cGUiKTsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmZvLmZvcm1hdC5ibG9ja0NvdW50OyArK2kpIHsKICAgICAgICAgICAgbGV0IGZ0ZWxsID0gaW5mby5kYXRhT2Zmc2V0ICsgaW5mby5ibG9ja1NpemUgKiBpOwogICAgICAgICAgICBsZXQgYmxvY2sgPSBoY2Euc3ViYXJyYXkoZnRlbGwsIGZ0ZWxsICsgaW5mby5ibG9ja1NpemUpOwogICAgICAgICAgICAvLyB2ZXJpZnkgYmxvY2sgY2hlY2tzdW0KICAgICAgICAgICAgSENBQ3JjMTYudmVyaWZ5KGJsb2NrLCBpbmZvLmJsb2NrU2l6ZSAtIDIpOwogICAgICAgICAgICAvLyBkZWNyeXB0L2VuY3J5cHQgYmxvY2sKICAgICAgICAgICAgY2lwaGVyLm1hc2soYmxvY2ssIDAsIGluZm8uYmxvY2tTaXplIC0gMik7CiAgICAgICAgICAgIC8vIGZpeCBjaGVja3N1bQogICAgICAgICAgICBIQ0FDcmMxNi5maXgoYmxvY2ssIGluZm8uYmxvY2tTaXplIC0gMik7CiAgICAgICAgfQogICAgICAgIC8vIHJlLSh1biltYXNrIGhlYWRlcnMsIGFuZCBzZXQgY2lwaCBoZWFkZXIgdG8gbmV3IHZhbHVlCiAgICAgICAgbGV0IG5ld0NpcGhlckRhdGEgPSBuZXcgVWludDhBcnJheSgyKTsKICAgICAgICBsZXQgbmV3Q2lwaGVyVHlwZSA9IGVuY3J5cHQgPyBjaXBoZXIuZ2V0VHlwZSgpIDogMDsKICAgICAgICBuZXcgRGF0YVZpZXcobmV3Q2lwaGVyRGF0YS5idWZmZXIpLnNldFVpbnQxNigwLCBuZXdDaXBoZXJUeXBlKTsKICAgICAgICBpbmZvLm1vZGlmeShoY2EsICJjaXBoIiwgbmV3Q2lwaGVyRGF0YSk7CiAgICAgICAgcmV0dXJuIGhjYTsKICAgIH0KICAgIHN0YXRpYyBmaW5kS2V5KGhjYSwgZ2l2ZW5LZXlMaXN0LCBzdWJrZXksIHRocmVzaG9sZCA9IDAuNSwgZGVwdGggPSAxMDI0KSB7CiAgICAgICAgbGV0IGtleUxpc3QsIHVubWl4ZWRLZXlMaXN0OwogICAgICAgIGlmIChnaXZlbktleUxpc3QgPT0gbnVsbCkgewogICAgICAgICAgICBrZXlMaXN0ID0gSENBS25vd25LZXlzOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAga2V5TGlzdCA9IGdpdmVuS2V5TGlzdC5tYXAoKGtleXMpID0+IFtIQ0FDaXBoZXIucGFyc2VLZXkoa2V5c1swXSksIEhDQUNpcGhlci5wYXJzZUtleShrZXlzWzFdKV0pOwogICAgICAgICAgICBIQ0FLbm93bktleXMuZm9yRWFjaCgoa2V5cykgPT4ga2V5TGlzdCA9PT0gbnVsbCB8fCBrZXlMaXN0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBrZXlMaXN0LnB1c2goa2V5cykpOwogICAgICAgIH0KICAgICAgICB1bm1peGVkS2V5TGlzdCA9IGtleUxpc3Quc2xpY2UoKTsKICAgICAgICBpZiAoc3Via2V5ICE9IG51bGwpIHsKICAgICAgICAgICAgLy8gaGFuZGxlIHN1YmtleQogICAgICAgICAgICBrZXlMaXN0ID0ga2V5TGlzdC5tYXAoKGtleXMpID0+IHsKICAgICAgICAgICAgICAgIGxldCBtaXhlZCA9IEhDQUNpcGhlci5taXhXaXRoU3Via2V5KGtleXNbMF0sIGtleXNbMV0sIHN1YmtleSk7CiAgICAgICAgICAgICAgICByZXR1cm4gW21peGVkLmtleTEsIG1peGVkLmtleTJdOwogICAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgLy8gcGFyc2UgaGVhZGVyCiAgICAgICAgY29uc3QgaW5mbyA9IG5ldyBIQ0FJbmZvKGhjYSk7IC8vIHRocm93cyAiTm90IGEgSENBIGZpbGUiIGlmIG1pc21hdGNoCiAgICAgICAgaWYgKGluZm8uY2lwaGVyID09IDApCiAgICAgICAgICAgIHJldHVybjsgLy8gbm90IGVuY3J5cHRlZAogICAgICAgIGNvbnN0IGZyYW1lID0gbmV3IEhDQUZyYW1lKGluZm8pOwogICAgICAgIGNvbnN0IHNjb3JlcyA9IGtleUxpc3QubWFwKCgpID0+IDApOwogICAgICAgIGxldCBjaXBoZXI7CiAgICAgICAgY29uc3QgdGVzdEtleSA9IChibG9jaywga2V5cykgPT4gewogICAgICAgICAgICBpZiAoY2lwaGVyID09IG51bGwpCiAgICAgICAgICAgICAgICBjaXBoZXIgPSBuZXcgSENBQ2lwaGVyKGtleXNbMF0sIGtleXNbMV0pOwogICAgICAgICAgICAvLyBkZWNyeXB0IGJsb2NrCiAgICAgICAgICAgIGJsb2NrID0gYmxvY2suc2xpY2UoKTsKICAgICAgICAgICAgY2lwaGVyLm1hc2soYmxvY2ssIDAsIGluZm8uYmxvY2tTaXplIC0gMik7CiAgICAgICAgICAgIC8vIHRlc3QgaWYgdGhlIGtleSBpcyBjb3JyZWN0CiAgICAgICAgICAgIGxldCByZWFkZXIgPSBuZXcgSENBQml0UmVhZGVyKGJsb2NrKTsKICAgICAgICAgICAgbGV0IHJlc3VsdCA9IGZhbHNlOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgcmVzdWx0ID0gSENBUGFja2luZy5VbnBhY2tGcmFtZShmcmFtZSwgcmVhZGVyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjYXRjaCAoZSkgeyB9CiAgICAgICAgICAgIGlmICghcmVzdWx0KSB7CiAgICAgICAgICAgICAgICBjaXBoZXIgPSB1bmRlZmluZWQ7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9OwogICAgICAgIGxldCB0ZXN0ZWRCbG9ja0NvdW50ID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMCwgbGFzdEZvdW5kID0gLTE7IGkgPCBpbmZvLmZvcm1hdC5ibG9ja0NvdW50ICYmIGkgPCBkZXB0aDsgaSsrKSB7CiAgICAgICAgICAgIGxldCBmdGVsbCA9IGluZm8uZGF0YU9mZnNldCArIGluZm8uYmxvY2tTaXplICogaTsKICAgICAgICAgICAgbGV0IGJsb2NrID0gaGNhLnN1YmFycmF5KGZ0ZWxsLCBmdGVsbCArIGluZm8uYmxvY2tTaXplKTsKICAgICAgICAgICAgbGV0IGZvdW5kID0gLTE7CiAgICAgICAgICAgIGlmIChsYXN0Rm91bmQgIT0gLTEpIHsKICAgICAgICAgICAgICAgIC8vIHRlc3QgbGFzdCBmb3VuZCBrZXkKICAgICAgICAgICAgICAgIGlmICh0ZXN0S2V5KGJsb2NrLCBrZXlMaXN0W2xhc3RGb3VuZF0pKQogICAgICAgICAgICAgICAgICAgIGZvdW5kID0gbGFzdEZvdW5kOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChmb3VuZCA9PSAtMSkgewogICAgICAgICAgICAgICAgLy8gbGFzdCBmb3VuZCBrZXkgZG9lcyBub3QgbWF0Y2gsIHRlc3Qgb3RoZXJzCiAgICAgICAgICAgICAgICBmb3VuZCA9IGtleUxpc3QuZmluZEluZGV4KChrZXlzLCBpbmRleCkgPT4gaW5kZXggPT0gbGFzdEZvdW5kID8gZmFsc2UgOiB0ZXN0S2V5KGJsb2NrLCBrZXlzKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGZvdW5kICE9IC0xKSB7CiAgICAgICAgICAgICAgICBsYXN0Rm91bmQgPSBmb3VuZDsKICAgICAgICAgICAgICAgIHNjb3Jlc1tmb3VuZF0rKzsKICAgICAgICAgICAgfQogICAgICAgICAgICB0ZXN0ZWRCbG9ja0NvdW50Kys7CiAgICAgICAgfQogICAgICAgIGxldCBiZXN0U2NvcmUgPSAwLCBiZXN0SW5kZXggPSAtMTsKICAgICAgICBzY29yZXMuZm9yRWFjaCgocywgaSkgPT4gcyA+IGJlc3RTY29yZSAmJiAoYmVzdFNjb3JlID0gcywgYmVzdEluZGV4ID0gaSkpOwogICAgICAgIGlmIChiZXN0SW5kZXggPT0gLTEgfHwgYmVzdFNjb3JlIC8gdGVzdGVkQmxvY2tDb3VudCA8IHRocmVzaG9sZCkKICAgICAgICAgICAgcmV0dXJuOyAvLyBjYW5ub3QgZm91bmQgdmFsaWQga2V5CiAgICAgICAgZWxzZQogICAgICAgICAgICByZXR1cm4gdW5taXhlZEtleUxpc3RbYmVzdEluZGV4XTsKICAgIH0KICAgIHN0YXRpYyBkZWNvZGUoaGNhLCBtb2RlID0gMzIsIGxvb3AgPSAwLCB2b2x1bWUgPSAxLjApIHsKICAgICAgICBzd2l0Y2ggKG1vZGUpIHsKICAgICAgICAgICAgY2FzZSAwOiAvLyBmbG9hdAogICAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgIGNhc2UgMjQ6CiAgICAgICAgICAgIGNhc2UgMzI6IC8vIGludGVnZXIKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgbW9kZSA9IDMyOwogICAgICAgIH0KICAgICAgICBpZiAodm9sdW1lID4gMSkKICAgICAgICAgICAgdm9sdW1lID0gMTsKICAgICAgICBlbHNlIGlmICh2b2x1bWUgPCAwKQogICAgICAgICAgICB2b2x1bWUgPSAwOwogICAgICAgIGxldCBpbmZvID0gbmV3IEhDQUluZm8oaGNhKTsgLy8gdGhyb3dzICJOb3QgYSBIQ0EgZmlsZSIgaWYgbWlzbWF0Y2gKICAgICAgICBsZXQgZnJhbWUgPSBuZXcgSENBRnJhbWUoaW5mbyk7CiAgICAgICAgaWYgKGluZm8uaGFzSGVhZGVyWyJjaXBoIl0gJiYgaW5mby5jaXBoZXIgIT0gMCkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkhDQSBpcyBlbmNyeXB0ZWQsIHBsZWFzZSBkZWNyeXB0IGl0IGZpcnN0IGJlZm9yZSBkZWNvZGluZyIpOwogICAgICAgIH0KICAgICAgICAvLyBwcmVwYXJlIG91dHB1dCBXQVYgZmlsZQogICAgICAgIGNvbnN0IG91dHB1dFdhdiA9IG5ldyBIQ0FXYXYoaW5mbywgbW9kZSwgbG9vcCk7CiAgICAgICAgY29uc3QgZmlsZUJ1ZiA9IG91dHB1dFdhdi5maWxlQnVmOwogICAgICAgIGNvbnN0IGRhdGFQYXJ0ID0gb3V0cHV0V2F2LmRhdGFQYXJ0OwogICAgICAgIC8vIGNhbGN1bGF0ZSBpbi1XQVYgc2l6ZQogICAgICAgIGxldCBpbldhdlNpemUgPSBpbmZvLmNhbGNJbldhdlNpemUobW9kZSk7CiAgICAgICAgLy8gZGVjb2RlIGJsb2NrcyAoZnJhbWVzKQogICAgICAgIGxldCBmYWlsZWRCbG9ja3MgPSBbXSwgbGFzdEVycm9yID0gdW5kZWZpbmVkOwogICAgICAgIGZvciAobGV0IGkgPSAwLCBvZmZzZXQgPSAwOyBpIDwgaW5mby5mb3JtYXQuYmxvY2tDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGxldCBsYXN0RGVjb2RlZFNhbXBsZXMgPSBpICogSENBRnJhbWUuU2FtcGxlc1BlckZyYW1lOwogICAgICAgICAgICBsZXQgY3VycmVudERlY29kZWRTYW1wbGVzID0gbGFzdERlY29kZWRTYW1wbGVzICsgSENBRnJhbWUuU2FtcGxlc1BlckZyYW1lOwogICAgICAgICAgICBpZiAoY3VycmVudERlY29kZWRTYW1wbGVzIDw9IGluZm8uc3RhcnRBdFNhbXBsZSB8fCBsYXN0RGVjb2RlZFNhbXBsZXMgPj0gaW5mby5lbmRBdFNhbXBsZSkgewogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGV0IHN0YXJ0T2Zmc2V0ID0gaW5mby5kYXRhT2Zmc2V0ICsgaW5mby5ibG9ja1NpemUgKiBpOwogICAgICAgICAgICBsZXQgYmxvY2sgPSBoY2Euc3ViYXJyYXkoc3RhcnRPZmZzZXQsIHN0YXJ0T2Zmc2V0ICsgaW5mby5ibG9ja1NpemUpOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgdGhpcy5kZWNvZGVCbG9jayhmcmFtZSwgYmxvY2spOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICBmYWlsZWRCbG9ja3MucHVzaChpKTsKICAgICAgICAgICAgICAgIGxhc3RFcnJvciA9IGU7CiAgICAgICAgICAgICAgICBmcmFtZSA9IG5ldyBIQ0FGcmFtZShpbmZvKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgd2F2ZWJ1ZmY7CiAgICAgICAgICAgIGlmIChsYXN0RGVjb2RlZFNhbXBsZXMgPCBpbmZvLnN0YXJ0QXRTYW1wbGUgfHwgY3VycmVudERlY29kZWRTYW1wbGVzID4gaW5mby5lbmRBdFNhbXBsZSkgewogICAgICAgICAgICAgICAgLy8gY3Jvc3Npbmcgc3RhcnRBdFNhbXBsZS9lbmRBdFNhbXBsZSwgc2tpcC9kcm9wIHNwZWNpZmllZCBieXRlcwogICAgICAgICAgICAgICAgd2F2ZWJ1ZmYgPSB0aGlzLndyaXRlVG9QQ00oZnJhbWUsIG1vZGUsIHZvbHVtZSk7CiAgICAgICAgICAgICAgICBpZiAobGFzdERlY29kZWRTYW1wbGVzIDwgaW5mby5zdGFydEF0U2FtcGxlKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IHNraXBwZWRTaXplID0gKGluZm8uc3RhcnRBdFNhbXBsZSAtIGxhc3REZWNvZGVkU2FtcGxlcykgKiBpbldhdlNpemUuc2FtcGxlOwogICAgICAgICAgICAgICAgICAgIHdhdmVidWZmID0gd2F2ZWJ1ZmYuc3ViYXJyYXkoc2tpcHBlZFNpemUsIGluV2F2U2l6ZS5ibG9jayk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIGlmIChjdXJyZW50RGVjb2RlZFNhbXBsZXMgPiBpbmZvLmVuZEF0U2FtcGxlKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IHdyaXRlU2l6ZSA9IChpbmZvLmVuZEF0U2FtcGxlIC0gbGFzdERlY29kZWRTYW1wbGVzKSAqIGluV2F2U2l6ZS5zYW1wbGU7CiAgICAgICAgICAgICAgICAgICAgd2F2ZWJ1ZmYgPSB3YXZlYnVmZi5zdWJhcnJheSgwLCB3cml0ZVNpemUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKCJzaG91bGQgbmV2ZXIgZ28gaGVyZSIpOwogICAgICAgICAgICAgICAgZGF0YVBhcnQuc2V0KHdhdmVidWZmLCBvZmZzZXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgd2F2ZWJ1ZmYgPSB0aGlzLndyaXRlVG9QQ00oZnJhbWUsIG1vZGUsIHZvbHVtZSwgZGF0YVBhcnQsIG9mZnNldCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb2Zmc2V0ICs9IHdhdmVidWZmLmJ5dGVMZW5ndGg7CiAgICAgICAgfQogICAgICAgIGlmIChmYWlsZWRCbG9ja3MubGVuZ3RoID4gMCkgewogICAgICAgICAgICBjb25zb2xlLmVycm9yKGBlcnJvciBkZWNvZGluZyBmb2xsb3dpbmcgYmxvY2tzLCBmaWxsZWQgemVyb2AsIGZhaWxlZEJsb2NrcywgbGFzdEVycm9yKTsKICAgICAgICB9CiAgICAgICAgLy8gZGVjb2RpbmcgZG9uZSwgdGhlbiBqdXN0IGNvcHkgbG9vcGluZyBwYXJ0CiAgICAgICAgaWYgKGluZm8uaGFzSGVhZGVyWyJsb29wIl0gJiYgbG9vcCkgewogICAgICAgICAgICAvLyAidGFpbCIgYmV5b25kIGxvb3AgZW5kIGlzIGRyb3BwZWQKICAgICAgICAgICAgLy8gY29weSBsb29waW5nIGF1ZGlvIGNsaXBzCiAgICAgICAgICAgIGlmIChpbldhdlNpemUubG9vcCA9PSBudWxsKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgICAgIGxldCBwcmVMb29wU2l6ZUluV2F2ID0gaW5XYXZTaXplLnNhbXBsZSAqIChpbmZvLmxvb3BTdGFydEF0U2FtcGxlIC0gaW5mby5zdGFydEF0U2FtcGxlKTsKICAgICAgICAgICAgbGV0IHNyYyA9IGRhdGFQYXJ0LnN1YmFycmF5KHByZUxvb3BTaXplSW5XYXYsIHByZUxvb3BTaXplSW5XYXYgKyBpbldhdlNpemUubG9vcC5sb29wUGFydCk7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBzdGFydCA9IHByZUxvb3BTaXplSW5XYXYgKyBpbldhdlNpemUubG9vcC5sb29wUGFydDsgaSA8IGxvb3A7IGkrKykgewogICAgICAgICAgICAgICAgbGV0IGRzdCA9IGRhdGFQYXJ0LnN1YmFycmF5KHN0YXJ0LCBzdGFydCArIGluV2F2U2l6ZS5sb29wLmxvb3BQYXJ0KTsKICAgICAgICAgICAgICAgIGRzdC5zZXQoc3JjKTsKICAgICAgICAgICAgICAgIHN0YXJ0ICs9IGluV2F2U2l6ZS5sb29wLmxvb3BQYXJ0OwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBmaWxlQnVmOwogICAgfQogICAgc3RhdGljIGRlY29kZUJsb2NrKGZyYW1lLCBibG9jaykgewogICAgICAgIGxldCBpbmZvID0gZnJhbWUuSGNhOwogICAgICAgIGlmIChibG9jay5ieXRlTGVuZ3RoICE9IGluZm8uYmxvY2tTaXplKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAvLyB2ZXJpZnkgY2hlY2tzdW0KICAgICAgICBIQ0FDcmMxNi52ZXJpZnkoYmxvY2ssIGluZm8uYmxvY2tTaXplIC0gMik7CiAgICAgICAgLy8gZGVjb2RlCiAgICAgICAgSENBRGVjb2Rlci5EZWNvZGVGcmFtZShibG9jaywgZnJhbWUpOwogICAgfQogICAgc3RhdGljIHdyaXRlVG9QQ00oZnJhbWUsIG1vZGUgPSAzMiwgdm9sdW1lID0gMS4wLCB3cml0ZXIsIGZ0ZWxsKSB7CiAgICAgICAgc3dpdGNoIChtb2RlKSB7CiAgICAgICAgICAgIGNhc2UgMDogLy8gZmxvYXQKICAgICAgICAgICAgY2FzZSA4OgogICAgICAgICAgICBjYXNlIDE2OgogICAgICAgICAgICBjYXNlIDI0OgogICAgICAgICAgICBjYXNlIDMyOiAvLyBpbnRlZ2VyCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIG1vZGUgPSAzMjsKICAgICAgICB9CiAgICAgICAgaWYgKHZvbHVtZSA+IDEpCiAgICAgICAgICAgIHZvbHVtZSA9IDE7CiAgICAgICAgZWxzZSBpZiAodm9sdW1lIDwgMCkKICAgICAgICAgICAgdm9sdW1lID0gMDsKICAgICAgICAvLyBjcmVhdGUgbmV3IHdyaXRlciBpZiBub3Qgc3BlY2lmaWVkCiAgICAgICAgbGV0IGluZm8gPSBmcmFtZS5IY2E7CiAgICAgICAgaWYgKHdyaXRlciA9PSBudWxsKSB7CiAgICAgICAgICAgIHdyaXRlciA9IG5ldyBVaW50OEFycmF5KEhDQUZyYW1lLlNhbXBsZXNQZXJGcmFtZSAqIGluZm8uZm9ybWF0LmNoYW5uZWxDb3VudCAqIChtb2RlID09IDAgPyAzMiA6IG1vZGUpIC8gOCk7CiAgICAgICAgICAgIGlmIChmdGVsbCA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICBmdGVsbCA9IDA7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGlmIChmdGVsbCA9PSBudWxsKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgfQogICAgICAgIC8vIHdyaXRlIGRlY29kZWQgZGF0YSBpbnRvIHdyaXRlcgogICAgICAgIGxldCBwID0gbmV3IERhdGFWaWV3KHdyaXRlci5idWZmZXIsIHdyaXRlci5ieXRlT2Zmc2V0LCB3cml0ZXIuYnl0ZUxlbmd0aCk7CiAgICAgICAgbGV0IGZ0ZWxsQmVnaW4gPSBmdGVsbDsKICAgICAgICBmb3IgKGxldCBzZiA9IDA7IHNmIDwgSENBRnJhbWUuU3ViZnJhbWVzUGVyRnJhbWU7IHNmKyspIHsKICAgICAgICAgICAgZm9yIChsZXQgcyA9IDA7IHMgPCBIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWU7IHMrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCBmcmFtZS5DaGFubmVscy5sZW5ndGg7IGMrKykgewogICAgICAgICAgICAgICAgICAgIGxldCBmID0gZnJhbWUuQ2hhbm5lbHNbY10uUGNtRmxvYXRbc2ZdW3NdICogdm9sdW1lOwogICAgICAgICAgICAgICAgICAgIGlmIChmID4gMSkKICAgICAgICAgICAgICAgICAgICAgICAgZiA9IDE7CiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoZiA8IC0xKQogICAgICAgICAgICAgICAgICAgICAgICBmID0gLTE7CiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChtb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgODoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG11c3QgYmUgdW5zaWduZWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAuc2V0VWludDgoZnRlbGwsIGYgKiAweDdGICsgMHg4MCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdGVsbCArPSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmb3IgYWJvdmUgOC1iaXQgaW50ZWdlciwgbGl0dGxlLWVuZGlhbiBzaWduZWQgaW50ZWdlciBpcyB1c2VkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAoc2V0VWludDE2L3NldEludDE2IGFjdHVhbGx5IGRvZXNuJ3Qgc2VlbSB0byBtYWtlIGFueSBkaWZmZXJlbmNlIGhlcmUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLnNldEludDE2KGZ0ZWxsLCBmICogMHg3RkZGLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ0ZWxsICs9IDI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyNDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZXJlJ3Mgbm8gc2V0SW50MjQsIHdyaXRlIDMgYnl0ZXMgd2l0aCBzZXRVaW50OCByZXNwZWN0aXZlbHkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGYgKj0gMHg3RkZGRkY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLnNldFVpbnQ4KGZ0ZWxsLCBmICYgMHhGRik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLnNldFVpbnQ4KGZ0ZWxsICsgMSwgZiA+PiA4ICYgMHhGRik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLnNldFVpbnQ4KGZ0ZWxsICsgMiwgZiA+PiAxNiAmIDB4RkYpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZnRlbGwgKz0gMzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDMyOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcC5zZXRJbnQzMihmdGVsbCwgZiAqIDB4N0ZGRkZGRkYsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZnRlbGwgKz0gNDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmbG9hdAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcC5zZXRGbG9hdDMyKGZ0ZWxsLCBmLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ0ZWxsICs9IDQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigidW5rbm93biBtb2RlIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB3cml0ZXIuc3ViYXJyYXkoZnRlbGxCZWdpbiwgZnRlbGwpOwogICAgfQogICAgc3RhdGljIGZpeENoZWNrc3VtKGhjYSkgewogICAgICAgIEhDQUluZm8uZml4SGVhZGVyQ2hlY2tzdW0oaGNhKTsKICAgICAgICBsZXQgaW5mbyA9IG5ldyBIQ0FJbmZvKGhjYSk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmZvLmZvcm1hdC5ibG9ja0NvdW50OyBpKyspIHsKICAgICAgICAgICAgbGV0IGZ0ZWxsID0gaW5mby5kYXRhT2Zmc2V0ICsgaSAqIGluZm8uYmxvY2tTaXplOwogICAgICAgICAgICBsZXQgYmxvY2sgPSBoY2Euc3ViYXJyYXkoZnRlbGwsIGZ0ZWxsICsgaW5mby5ibG9ja1NpemUpOwogICAgICAgICAgICBIQ0FDcmMxNi5maXgoYmxvY2ssIGluZm8uYmxvY2tTaXplIC0gMik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBoY2E7CiAgICB9Cn0KY2xhc3MgSENBV2F2IHsKICAgIGNvbnN0cnVjdG9yKGluZm8sIG1vZGUgPSAzMiwgbG9vcCA9IDApIHsKICAgICAgICBzd2l0Y2ggKG1vZGUpIHsKICAgICAgICAgICAgY2FzZSAwOiAvLyBmbG9hdAogICAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgIGNhc2UgMjQ6CiAgICAgICAgICAgIGNhc2UgMzI6IC8vIGludGVnZXIKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgbW9kZSA9IDMyOwogICAgICAgIH0KICAgICAgICBpZiAoaXNOYU4obG9vcCkpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigibG9vcCBpcyBub3QgbnVtYmVyIik7CiAgICAgICAgbG9vcCA9IE1hdGguZmxvb3IobG9vcCk7CiAgICAgICAgaWYgKGxvb3AgPCAwKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICBsZXQgaW5XYXZTaXplID0gaW5mby5jYWxjSW5XYXZTaXplKG1vZGUpOwogICAgICAgIGxldCBkYXRhU2l6ZSA9IGluV2F2U2l6ZS5zYW1wbGUgKiBpbmZvLnNhbXBsZUNvdW50OwogICAgICAgIGlmIChsb29wID4gMCkgewogICAgICAgICAgICBpZiAoaW5XYXZTaXplLmxvb3AgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgICAgICBkYXRhU2l6ZSArPSBpbldhdlNpemUubG9vcC5sb29wUGFydCAqIGxvb3A7CiAgICAgICAgfQogICAgICAgIC8vIHByZXBhcmUgbWV0YWRhdGEgY2h1bmtzIGFuZCBkYXRhIGNodW5rIGhlYWRlcgogICAgICAgIHRoaXMuZm10ID0gbmV3IEhDQVdhdkZtdENodW5rKGluZm8sIG1vZGUpOwogICAgICAgIGlmIChpbmZvLmhhc0hlYWRlclsiY29tbSJdKQogICAgICAgICAgICB0aGlzLm5vdGUgPSBuZXcgSENBV2F2Q29tbWVudENodW5rKGluZm8pOwogICAgICAgIGlmIChpbmZvLmhhc0hlYWRlclsibG9vcCJdKQogICAgICAgICAgICB0aGlzLnNtcGwgPSBuZXcgSENBV2F2ZVNtcGxDaHVuayhpbmZvKTsKICAgICAgICB0aGlzLndhdmVSaWZmID0gbmV3IEhDQVdhdldhdmVSaWZmSGVhZGVyKDggKyB0aGlzLmZtdC5zaXplCiAgICAgICAgICAgICsgKHRoaXMubm90ZSA9PSBudWxsID8gMCA6IDggKyB0aGlzLm5vdGUuc2l6ZSkKICAgICAgICAgICAgKyA4ICsgZGF0YVNpemUKICAgICAgICAgICAgKyAodGhpcy5zbXBsID09IG51bGwgPyAwIDogOCArIHRoaXMuc21wbC5zaXplKSk7CiAgICAgICAgLy8gZ2V0IGJ5dGVzIG9mIHByZXBhcmVkIGNodW5rcwogICAgICAgIGxldCB3YXZlUmlmZkhlYWRlciA9IHRoaXMud2F2ZVJpZmYuZ2V0KCk7CiAgICAgICAgbGV0IGZtdENodW5rID0gdGhpcy5mbXQuZ2V0KCk7CiAgICAgICAgbGV0IG5vdGVDaHVuayA9IHRoaXMubm90ZSAhPSBudWxsID8gdGhpcy5ub3RlLmdldCgpIDogbmV3IFVpbnQ4QXJyYXkoMCk7CiAgICAgICAgbGV0IGRhdGFDaHVua0hlYWRlciA9IG5ldyBVaW50OEFycmF5KDgpOwogICAgICAgIGRhdGFDaHVua0hlYWRlci5zZXQobmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKCJkYXRhIikpOwogICAgICAgIG5ldyBEYXRhVmlldyhkYXRhQ2h1bmtIZWFkZXIuYnVmZmVyKS5zZXRVaW50MzIoNCwgZGF0YVNpemUsIHRydWUpOwogICAgICAgIGxldCBzbXBsQ2h1bmsgPSB0aGlzLnNtcGwgIT0gbnVsbCA/IHRoaXMuc21wbC5nZXQoKSA6IG5ldyBVaW50OEFycmF5KDApOwogICAgICAgIC8vIGNyZWF0ZSB3aG9sZS1maWxlIGJ1ZmZlcgogICAgICAgIHRoaXMuZmlsZUJ1ZiA9IG5ldyBVaW50OEFycmF5KDggKyB0aGlzLndhdmVSaWZmLnNpemUpOwogICAgICAgIC8vIGNvcHkgcHJlcGFyZWQgbWV0YWRhdGEgY2h1bmtzIGFuZCBkYXRhIGNodW5rIGhlYWRlciB0byB3aG9sZS1maWxlIGJ1ZmZlcgogICAgICAgIGxldCB3cml0dGVuTGVuZ3RoID0gMDsKICAgICAgICBbd2F2ZVJpZmZIZWFkZXIsIGZtdENodW5rLCBub3RlQ2h1bmssIGRhdGFDaHVua0hlYWRlcl0uZm9yRWFjaCgoY2h1bmspID0+IHsKICAgICAgICAgICAgdGhpcy5maWxlQnVmLnNldChjaHVuaywgd3JpdHRlbkxlbmd0aCk7CiAgICAgICAgICAgIHdyaXR0ZW5MZW5ndGggKz0gY2h1bmsuYnl0ZUxlbmd0aDsKICAgICAgICB9KTsKICAgICAgICAvLyBza2lwIGRhdGFQYXJ0IHNpbmNlIGl0J3MgZW1wdHkKICAgICAgICB0aGlzLmRhdGFQYXJ0ID0gdGhpcy5maWxlQnVmLnN1YmFycmF5KHdyaXR0ZW5MZW5ndGgsIHdyaXR0ZW5MZW5ndGggKyBkYXRhU2l6ZSk7CiAgICAgICAgd3JpdHRlbkxlbmd0aCArPSBkYXRhU2l6ZTsKICAgICAgICAvLyBjb3B5IHRoZSBsYXN0IHByZXBhcmVkIGNodW5rIHRvIHdob2xlLWZpbGUgYnVmZmVyCiAgICAgICAgdGhpcy5maWxlQnVmLnNldChzbXBsQ2h1bmssIHdyaXR0ZW5MZW5ndGgpOwogICAgICAgIHdyaXR0ZW5MZW5ndGggKz0gc21wbENodW5rLmJ5dGVMZW5ndGg7CiAgICAgICAgaWYgKHdyaXR0ZW5MZW5ndGggIT0gdGhpcy5maWxlQnVmLmJ5dGVMZW5ndGgpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgfQp9CmNsYXNzIEhDQVdhdldhdmVSaWZmSGVhZGVyIHsKICAgIGNvbnN0cnVjdG9yKHNpemUpIHsKICAgICAgICBpZiAoaXNOYU4oc2l6ZSkpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigic2l6ZSBtdXN0IGJlIG51bWJlciIpOwogICAgICAgIHNpemUgPSBNYXRoLmZsb29yKHNpemUpOwogICAgICAgIGlmIChzaXplIDw9IDApCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIHRoaXMuc2l6ZSA9IDQgKyBzaXplOyAvLyAiV0FWRSIgKyByZW1haW5pbmcgcGFydAogICAgfQogICAgZ2V0KCkgewogICAgICAgIGxldCBidWYgPSBuZXcgQXJyYXlCdWZmZXIoMTIpOwogICAgICAgIGxldCByZXQgPSBuZXcgVWludDhBcnJheShidWYpOwogICAgICAgIGxldCBwID0gbmV3IERhdGFWaWV3KGJ1Zik7CiAgICAgICAgbGV0IHRlID0gbmV3IFRleHRFbmNvZGVyKCk7CiAgICAgICAgcmV0LnNldCh0ZS5lbmNvZGUoIlJJRkYiKSwgMCk7CiAgICAgICAgcC5zZXRVaW50MzIoNCwgdGhpcy5zaXplLCB0cnVlKTsKICAgICAgICByZXQuc2V0KHRlLmVuY29kZSgiV0FWRSIpLCA4KTsKICAgICAgICByZXR1cm4gcmV0OwogICAgfQp9CmNsYXNzIEhDQVdhdkZtdENodW5rIHsKICAgIGNvbnN0cnVjdG9yKGluZm8sIG1vZGUgPSAzMikgewogICAgICAgIHRoaXMuc2l6ZSA9IDE2OwogICAgICAgIHN3aXRjaCAobW9kZSkgewogICAgICAgICAgICBjYXNlIDA6IC8vIGZsb2F0CiAgICAgICAgICAgIGNhc2UgODoKICAgICAgICAgICAgY2FzZSAxNjoKICAgICAgICAgICAgY2FzZSAyNDoKICAgICAgICAgICAgY2FzZSAzMjogLy8gaW50ZWdlcgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBtb2RlID0gMzI7CiAgICAgICAgfQogICAgICAgIGxldCBpbldhdlNpemUgPSBpbmZvLmNhbGNJbldhdlNpemUobW9kZSk7CiAgICAgICAgdGhpcy5mb3JtYXRUYWcgPSBtb2RlID4gMCA/IDEgOiAzOwogICAgICAgIHRoaXMuY2hhbm5lbENvdW50ID0gaW5mby5mb3JtYXQuY2hhbm5lbENvdW50OwogICAgICAgIHRoaXMuc2FtcGxlc1BlclNlYyA9IGluZm8uZm9ybWF0LnNhbXBsaW5nUmF0ZTsKICAgICAgICB0aGlzLmJ5dGVzUGVyU2VjID0gaW5XYXZTaXplLnNhbXBsZSAqIGluZm8uZm9ybWF0LnNhbXBsaW5nUmF0ZTsKICAgICAgICB0aGlzLmJsb2NrQWxpZ24gPSBpbldhdlNpemUuc2FtcGxlOwogICAgICAgIHRoaXMuYml0c1BlclNhbXBsZSA9IGluV2F2U2l6ZS5iaXRzUGVyU2FtcGxlOwogICAgfQogICAgZ2V0KCkgewogICAgICAgIGxldCBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCArIHRoaXMuc2l6ZSk7CiAgICAgICAgbGV0IHJldCA9IG5ldyBVaW50OEFycmF5KGJ1Zik7CiAgICAgICAgbGV0IHAgPSBuZXcgRGF0YVZpZXcoYnVmKTsKICAgICAgICBsZXQgdGUgPSBuZXcgVGV4dEVuY29kZXIoKTsKICAgICAgICByZXQuc2V0KHRlLmVuY29kZSgiZm10ICIpLCAwKTsKICAgICAgICBwLnNldFVpbnQzMig0LCB0aGlzLnNpemUsIHRydWUpOwogICAgICAgIHAuc2V0VWludDE2KDgsIHRoaXMuZm9ybWF0VGFnLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQxNigxMCwgdGhpcy5jaGFubmVsQ291bnQsIHRydWUpOwogICAgICAgIHAuc2V0VWludDMyKDEyLCB0aGlzLnNhbXBsZXNQZXJTZWMsIHRydWUpOwogICAgICAgIHAuc2V0VWludDMyKDE2LCB0aGlzLmJ5dGVzUGVyU2VjLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQxNigyMCwgdGhpcy5ibG9ja0FsaWduLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQxNigyMiwgdGhpcy5iaXRzUGVyU2FtcGxlLCB0cnVlKTsKICAgICAgICByZXR1cm4gcmV0OwogICAgfQp9CmNsYXNzIEhDQVdhdkNvbW1lbnRDaHVuayB7CiAgICBjb25zdHJ1Y3RvcihpbmZvKSB7CiAgICAgICAgdGhpcy5jb21tZW50QnVmID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKGluZm8uY29tbWVudCk7CiAgICAgICAgbGV0IHNpemUgPSB0aGlzLmNvbW1lbnRCdWYuYnl0ZUxlbmd0aDsKICAgICAgICBzaXplICs9IDQ7CiAgICAgICAgaWYgKHNpemUgJSA0KQogICAgICAgICAgICBzaXplICs9IDQgLSBzaXplICUgNDsKICAgICAgICB0aGlzLnNpemUgPSBzaXplOwogICAgfQogICAgZ2V0KCkgewogICAgICAgIGxldCBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCArIHRoaXMuc2l6ZSk7CiAgICAgICAgbGV0IHJldCA9IG5ldyBVaW50OEFycmF5KGJ1Zik7CiAgICAgICAgbGV0IHAgPSBuZXcgRGF0YVZpZXcoYnVmKTsKICAgICAgICBsZXQgdGUgPSBuZXcgVGV4dEVuY29kZXIoKTsKICAgICAgICByZXQuc2V0KHRlLmVuY29kZSgibm90ZSIpLCAwKTsKICAgICAgICBwLnNldFVpbnQzMig0LCB0aGlzLnNpemUsIHRydWUpOwogICAgICAgIHJldC5zZXQodGhpcy5jb21tZW50QnVmLCA4KTsKICAgICAgICByZXR1cm4gcmV0OwogICAgfQp9CmNsYXNzIEhDQVdhdmVTbXBsQ2h1bmsgewogICAgY29uc3RydWN0b3IoaW5mbykgewogICAgICAgIHRoaXMuc2l6ZSA9IDYwOwogICAgICAgIHRoaXMubWFudWZhY3R1cmVyID0gMDsKICAgICAgICB0aGlzLnByb2R1Y3QgPSAwOwogICAgICAgIHRoaXMuTUlESVVuaXR5Tm90ZSA9IDB4M2M7CiAgICAgICAgdGhpcy5NSURJUGl0Y2hGcmFjdGlvbiA9IDA7CiAgICAgICAgdGhpcy5TTVBURUZvcm1hdCA9IDA7CiAgICAgICAgdGhpcy5zYW1wbGVMb29wcyA9IDE7CiAgICAgICAgdGhpcy5zYW1wbGVyRGF0YSA9IDB4MTg7CiAgICAgICAgdGhpcy5sb29wX0lkZW50aWZpZXIgPSAwOwogICAgICAgIHRoaXMubG9vcF9UeXBlID0gMDsKICAgICAgICB0aGlzLmxvb3BfRnJhY3Rpb24gPSAwOwogICAgICAgIHRoaXMubG9vcF9QbGF5Q291bnQgPSAwOwogICAgICAgIGlmICghaW5mby5oYXNIZWFkZXJbImxvb3AiXSkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJtaXNzaW5nIFwibG9vcFwiIGhlYWRlciIpOwogICAgICAgIHRoaXMuc2FtcGxlUGVyaW9kID0gKDEgLyBpbmZvLmZvcm1hdC5zYW1wbGluZ1JhdGUgKiAxMDAwMDAwMDAwKTsKICAgICAgICB0aGlzLmxvb3BfU3RhcnQgPSBpbmZvLmxvb3BTdGFydEF0U2FtcGxlIC0gaW5mby5zdGFydEF0U2FtcGxlOwogICAgICAgIHRoaXMubG9vcF9FbmQgPSBpbmZvLmxvb3BFbmRBdFNhbXBsZSAtIGluZm8uc3RhcnRBdFNhbXBsZTsKICAgICAgICB0aGlzLlNNUFRFT2Zmc2V0ID0gMTsKICAgIH0KICAgIGdldCgpIHsKICAgICAgICBsZXQgYnVmID0gbmV3IEFycmF5QnVmZmVyKDggKyB0aGlzLnNpemUpOwogICAgICAgIGxldCByZXQgPSBuZXcgVWludDhBcnJheShidWYpOwogICAgICAgIGxldCBwID0gbmV3IERhdGFWaWV3KGJ1Zik7CiAgICAgICAgbGV0IHRlID0gbmV3IFRleHRFbmNvZGVyKCk7CiAgICAgICAgcmV0LnNldCh0ZS5lbmNvZGUoInNtcGwiKSwgMCk7CiAgICAgICAgcC5zZXRVaW50MzIoNCwgdGhpcy5zaXplLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMig4LCB0aGlzLm1hbnVmYWN0dXJlciwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoMTIsIHRoaXMucHJvZHVjdCwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoMTYsIHRoaXMuc2FtcGxlUGVyaW9kLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMigyMCwgdGhpcy5NSURJVW5pdHlOb3RlLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMigyNCwgdGhpcy5NSURJUGl0Y2hGcmFjdGlvbiwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoMjgsIHRoaXMuU01QVEVGb3JtYXQsIHRydWUpOwogICAgICAgIHAuc2V0VWludDMyKDMyLCB0aGlzLlNNUFRFT2Zmc2V0LCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMigzNiwgdGhpcy5zYW1wbGVMb29wcywgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoNDAsIHRoaXMuc2FtcGxlckRhdGEsIHRydWUpOwogICAgICAgIHAuc2V0VWludDMyKDQ0LCB0aGlzLmxvb3BfSWRlbnRpZmllciwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoNDgsIHRoaXMubG9vcF9UeXBlLCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMig1MiwgdGhpcy5sb29wX1N0YXJ0LCB0cnVlKTsKICAgICAgICBwLnNldFVpbnQzMig1NiwgdGhpcy5sb29wX0VuZCwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoNjAsIHRoaXMubG9vcF9GcmFjdGlvbiwgdHJ1ZSk7CiAgICAgICAgcC5zZXRVaW50MzIoNjQsIHRoaXMubG9vcF9QbGF5Q291bnQsIHRydWUpOwogICAgICAgIHJldHVybiByZXQ7CiAgICB9Cn0KY2xhc3MgSENBQml0UmVhZGVyIHsKICAgIGdldCBSZW1haW5pbmcoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuTGVuZ3RoQml0cyAtIHRoaXMuUG9zaXRpb247CiAgICB9CiAgICBjb25zdHJ1Y3RvcihidWZmZXIpIHsKICAgICAgICB0aGlzLkJ1ZmZlciA9IGJ1ZmZlcjsKICAgICAgICB0aGlzLmR2ID0gbmV3IERhdGFWaWV3KGJ1ZmZlci5idWZmZXIsIGJ1ZmZlci5ieXRlT2Zmc2V0LCBidWZmZXIuYnl0ZUxlbmd0aCk7CiAgICAgICAgdGhpcy5MZW5ndGhCaXRzID0gYnVmZmVyLmxlbmd0aCAqIDg7CiAgICAgICAgdGhpcy5Qb3NpdGlvbiA9IDA7CiAgICB9CiAgICBSZWFkSW50KGJpdENvdW50KSB7CiAgICAgICAgbGV0IHZhbHVlID0gdGhpcy5QZWVrSW50KGJpdENvdW50KTsKICAgICAgICB0aGlzLlBvc2l0aW9uICs9IGJpdENvdW50OwogICAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KICAgIFJlYWRCb29sKCkgewogICAgICAgIHJldHVybiB0aGlzLlJlYWRJbnQoMSkgPT0gMTsKICAgIH0KICAgIFJlYWRPZmZzZXRCaW5hcnkoYml0Q291bnQsIGJpYXMpIHsKICAgICAgICBsZXQgb2Zmc2V0ID0gKDEgPDwgKGJpdENvdW50IC0gMSkpIC0gYmlhczsKICAgICAgICBsZXQgdmFsdWUgPSB0aGlzLlBlZWtJbnQoYml0Q291bnQpIC0gb2Zmc2V0OwogICAgICAgIHRoaXMuUG9zaXRpb24gKz0gYml0Q291bnQ7CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQogICAgQWxpZ25Qb3NpdGlvbihtdWx0aXBsZSkgewogICAgICAgIHRoaXMuUG9zaXRpb24gPSBIQ0FVdGlsRnVuYy5HZXROZXh0TXVsdGlwbGUodGhpcy5Qb3NpdGlvbiwgbXVsdGlwbGUpOwogICAgfQogICAgUGVla0ludChiaXRDb3VudCkgewogICAgICAgIEhDQVV0aWxGdW5jLkRlYnVnQXNzZXJ0KGJpdENvdW50ID49IDAgJiYgYml0Q291bnQgPD0gMzIpOwogICAgICAgIGlmIChiaXRDb3VudCA+IHRoaXMuUmVtYWluaW5nKSB7CiAgICAgICAgICAgIGlmICh0aGlzLlBvc2l0aW9uID49IHRoaXMuTGVuZ3RoQml0cykKICAgICAgICAgICAgICAgIHJldHVybiAwOwogICAgICAgICAgICBsZXQgZXh0cmFCaXRzID0gYml0Q291bnQgLSB0aGlzLlJlbWFpbmluZzsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuUGVla0ludEZhbGxiYWNrKHRoaXMuUmVtYWluaW5nKSA8PCBleHRyYUJpdHM7CiAgICAgICAgfQogICAgICAgIGxldCBieXRlSW5kZXggPSB0aGlzLlBvc2l0aW9uIC8gODsKICAgICAgICBsZXQgYml0SW5kZXggPSB0aGlzLlBvc2l0aW9uICUgODsKICAgICAgICBpZiAoYml0Q291bnQgPD0gOSAmJiB0aGlzLlJlbWFpbmluZyA+PSAxNikgewogICAgICAgICAgICBsZXQgdmFsdWUgPSB0aGlzLmR2LmdldFVpbnQxNihieXRlSW5kZXgpOwogICAgICAgICAgICB2YWx1ZSAmPSAweEZGRkYgPj4gYml0SW5kZXg7CiAgICAgICAgICAgIHZhbHVlID4+PSAxNiAtIGJpdENvdW50IC0gYml0SW5kZXg7CiAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKGJpdENvdW50IDw9IDE3ICYmIHRoaXMuUmVtYWluaW5nID49IDI0KSB7CiAgICAgICAgICAgIGxldCB2YWx1ZSA9IHRoaXMuZHYuZ2V0VWludDE2KGJ5dGVJbmRleCkgPDwgOCB8IHRoaXMuZHYuZ2V0VWludDgoYnl0ZUluZGV4ICsgMik7CiAgICAgICAgICAgIHZhbHVlICY9IDB4RkZGRkZGID4+IGJpdEluZGV4OwogICAgICAgICAgICB2YWx1ZSA+Pj0gMjQgLSBiaXRDb3VudCAtIGJpdEluZGV4OwogICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgfQogICAgICAgIGlmIChiaXRDb3VudCA8PSAyNSAmJiB0aGlzLlJlbWFpbmluZyA+PSAzMikgewogICAgICAgICAgICBsZXQgdmFsdWUgPSB0aGlzLmR2LmdldFVpbnQzMihieXRlSW5kZXgpOwogICAgICAgICAgICB2YWx1ZSAmPSAweEZGRkZGRkZGID4+PiBiaXRJbmRleDsKICAgICAgICAgICAgdmFsdWUgPj49IDMyIC0gYml0Q291bnQgLSBiaXRJbmRleDsKICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpcy5QZWVrSW50RmFsbGJhY2soYml0Q291bnQpOwogICAgfQogICAgUGVla0ludEZhbGxiYWNrKGJpdENvdW50KSB7CiAgICAgICAgbGV0IHZhbHVlID0gMDsKICAgICAgICBsZXQgYnl0ZUluZGV4ID0gdGhpcy5Qb3NpdGlvbiAvIDg7CiAgICAgICAgbGV0IGJpdEluZGV4ID0gdGhpcy5Qb3NpdGlvbiAlIDg7CiAgICAgICAgd2hpbGUgKGJpdENvdW50ID4gMCkgewogICAgICAgICAgICBpZiAoYml0SW5kZXggPj0gOCkgewogICAgICAgICAgICAgICAgYml0SW5kZXggPSAwOwogICAgICAgICAgICAgICAgYnl0ZUluZGV4Kys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGV0IGJpdHNUb1JlYWQgPSBNYXRoLm1pbihiaXRDb3VudCwgOCAtIGJpdEluZGV4KTsKICAgICAgICAgICAgbGV0IG1hc2sgPSAweEZGID4+IGJpdEluZGV4OwogICAgICAgICAgICBsZXQgY3VycmVudEJ5dGUgPSAobWFzayAmIHRoaXMuZHYuZ2V0VWludDgoYnl0ZUluZGV4KSkgPj4gKDggLSBiaXRJbmRleCAtIGJpdHNUb1JlYWQpOwogICAgICAgICAgICB2YWx1ZSA9ICh2YWx1ZSA8PCBiaXRzVG9SZWFkKSB8IGN1cnJlbnRCeXRlOwogICAgICAgICAgICBiaXRJbmRleCArPSBiaXRzVG9SZWFkOwogICAgICAgICAgICBiaXRDb3VudCAtPSBiaXRzVG9SZWFkOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdmFsdWU7CiAgICB9Cn0KdmFyIEhDQU9mZnNldEJpYXM7CihmdW5jdGlvbiAoSENBT2Zmc2V0QmlhcykgewogICAgLy8vIDxzdW1tYXJ5PgogICAgLy8vIFNwZWNpZmllcyB0aGUgYmlhcyBvZiBhbiBvZmZzZXQgYmluYXJ5IHZhbHVlLiBBIHBvc2l0aXZlIGJpYXMgY2FuIHJlcHJlc2VudCBvbmUgbW9yZQogICAgLy8vIHBvc2l0aXZlIHZhbHVlIHRoYW4gbmVnYXRpdmUgdmFsdWUsIGFuZCBhIG5lZ2F0aXZlIGJpYXMgY2FuIHJlcHJlc2VudCBvbmUgbW9yZQogICAgLy8vIG5lZ2F0aXZlIHZhbHVlIHRoYW4gcG9zaXRpdmUgdmFsdWUuCiAgICAvLy8gPC9zdW1tYXJ5PgogICAgLy8vIDxyZW1hcmtzPkV4YW1wbGU6CiAgICAvLy8gQSA0LWJpdCBvZmZzZXQgYmluYXJ5IHZhbHVlIHdpdGggYSBwb3NpdGl2ZSBiaWFzIGNhbiBzdG9yZQogICAgLy8vIHRoZSB2YWx1ZXMgOCB0aHJvdWdoIC03IGluY2x1c2l2ZS4KICAgIC8vLyBBIDQtYml0IG9mZnNldCBiaW5hcnkgdmFsdWUgd2l0aCBhIG5lZ2F0aXZlIGJpYXMgY2FuIHN0b3JlCiAgICAvLy8gdGhlIHZhbHVlcyA3IHRocm91Z2ggLTggaW5jbHVzaXZlLjwvcmVtYXJrcz4KICAgIEhDQU9mZnNldEJpYXNbSENBT2Zmc2V0Qmlhc1siUG9zaXRpdmUiXSA9IDFdID0gIlBvc2l0aXZlIjsKICAgIEhDQU9mZnNldEJpYXNbSENBT2Zmc2V0Qmlhc1siTmVnYXRpdmUiXSA9IDBdID0gIk5lZ2F0aXZlIjsKfSkoSENBT2Zmc2V0QmlhcyB8fCAoSENBT2Zmc2V0QmlhcyA9IHt9KSk7CmNsYXNzIEhDQUJpdFdyaXRlciB7CiAgICBnZXQgUmVtYWluaW5nKCkgeyByZXR1cm4gdGhpcy5MZW5ndGhCaXRzIC0gdGhpcy5Qb3NpdGlvbjsgfQogICAgY29uc3RydWN0b3IoYnVmZmVyKSB7CiAgICAgICAgdGhpcy5Qb3NpdGlvbiA9IDA7CiAgICAgICAgdGhpcy5CdWZmZXIgPSBidWZmZXI7CiAgICAgICAgdGhpcy5kdiA9IG5ldyBEYXRhVmlldyhidWZmZXIuYnVmZmVyLCBidWZmZXIuYnl0ZU9mZnNldCwgYnVmZmVyLmJ5dGVMZW5ndGgpOwogICAgICAgIHRoaXMuTGVuZ3RoQml0cyA9IGJ1ZmZlci5sZW5ndGggKiA4OwogICAgfQogICAgQWxpZ25Qb3NpdGlvbihtdWx0aXBsZSkgewogICAgICAgIGxldCBuZXdQb3NpdGlvbiA9IEhDQVV0aWxGdW5jLkdldE5leHRNdWx0aXBsZSh0aGlzLlBvc2l0aW9uLCBtdWx0aXBsZSk7CiAgICAgICAgbGV0IGJpdHMgPSBuZXdQb3NpdGlvbiAtIHRoaXMuUG9zaXRpb247CiAgICAgICAgdGhpcy5Xcml0ZSgwLCBiaXRzKTsKICAgIH0KICAgIFdyaXRlKHZhbHVlLCBiaXRDb3VudCkgewogICAgICAgIEhDQVV0aWxGdW5jLkRlYnVnQXNzZXJ0KGJpdENvdW50ID49IDAgJiYgYml0Q291bnQgPD0gMzIpOwogICAgICAgIGlmIChiaXRDb3VudCA+IHRoaXMuUmVtYWluaW5nKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiTm90IGVub3VnaCBiaXRzIGxlZnQgaW4gb3V0cHV0IGJ1ZmZlciIpOwogICAgICAgIH0KICAgICAgICBsZXQgYnl0ZUluZGV4ID0gdGhpcy5Qb3NpdGlvbiAvIDg7CiAgICAgICAgbGV0IGJpdEluZGV4ID0gdGhpcy5Qb3NpdGlvbiAlIDg7CiAgICAgICAgaWYgKGJpdENvdW50IDw9IDkgJiYgdGhpcy5SZW1haW5pbmcgPj0gMTYpIHsKICAgICAgICAgICAgbGV0IG91dFZhbHVlID0gKCh2YWx1ZSA8PCAoMTYgLSBiaXRDb3VudCkpICYgMHhGRkZGKSA+PiBiaXRJbmRleDsKICAgICAgICAgICAgb3V0VmFsdWUgfD0gdGhpcy5kdi5nZXRVaW50MTYoYnl0ZUluZGV4KTsKICAgICAgICAgICAgdGhpcy5kdi5zZXRVaW50MTYoYnl0ZUluZGV4LCBvdXRWYWx1ZSk7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKGJpdENvdW50IDw9IDE3ICYmIHRoaXMuUmVtYWluaW5nID49IDI0KSB7CiAgICAgICAgICAgIGxldCBvdXRWYWx1ZSA9ICgodmFsdWUgPDwgKDI0IC0gYml0Q291bnQpKSAmIDB4RkZGRkZGKSA+PiBiaXRJbmRleDsKICAgICAgICAgICAgb3V0VmFsdWUgfD0gdGhpcy5kdi5nZXRVaW50MTYoYnl0ZUluZGV4KSA8PCA4IHwgdGhpcy5kdi5nZXRVaW50OChieXRlSW5kZXggKyAyKTsKICAgICAgICAgICAgdGhpcy5kdi5zZXRVaW50MTYoYnl0ZUluZGV4LCBvdXRWYWx1ZSA+Pj4gOCk7CiAgICAgICAgICAgIHRoaXMuZHYuc2V0VWludDgoYnl0ZUluZGV4ICsgMiwgb3V0VmFsdWUgJiAweEZGKTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoYml0Q291bnQgPD0gMjUgJiYgdGhpcy5SZW1haW5pbmcgPj0gMzIpIHsKICAgICAgICAgICAgbGV0IG91dFZhbHVlID0gKCgodmFsdWUgPDwgKDMyIC0gYml0Q291bnQpKSAmIDB4RkZGRkZGRkYpID4+PiBiaXRJbmRleCk7CiAgICAgICAgICAgIG91dFZhbHVlIHw9IHRoaXMuZHYuZ2V0VWludDMyKGJ5dGVJbmRleCk7CiAgICAgICAgICAgIHRoaXMuZHYuc2V0VWludDMyKGJ5dGVJbmRleCwgb3V0VmFsdWUpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgdGhpcy5Xcml0ZUZhbGxiYWNrKHZhbHVlLCBiaXRDb3VudCk7CiAgICAgICAgfQogICAgICAgIHRoaXMuUG9zaXRpb24gKz0gYml0Q291bnQ7CiAgICB9CiAgICBXcml0ZUZhbGxiYWNrKHZhbHVlLCBiaXRDb3VudCkgewogICAgICAgIGxldCBieXRlSW5kZXggPSB0aGlzLlBvc2l0aW9uIC8gODsKICAgICAgICBsZXQgYml0SW5kZXggPSB0aGlzLlBvc2l0aW9uICUgODsKICAgICAgICB3aGlsZSAoYml0Q291bnQgPiAwKSB7CiAgICAgICAgICAgIGlmIChiaXRJbmRleCA+PSA4KSB7CiAgICAgICAgICAgICAgICBiaXRJbmRleCA9IDA7CiAgICAgICAgICAgICAgICBieXRlSW5kZXgrKzsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgdG9TaGlmdCA9IDggLSBiaXRJbmRleCAtIGJpdENvdW50OwogICAgICAgICAgICBsZXQgc2hpZnRlZCA9IHRvU2hpZnQgPCAwID8gdmFsdWUgPj4+IC10b1NoaWZ0IDogdmFsdWUgPDwgdG9TaGlmdDsKICAgICAgICAgICAgbGV0IGJpdHNUb1dyaXRlID0gTWF0aC5taW4oYml0Q291bnQsIDggLSBiaXRJbmRleCk7CiAgICAgICAgICAgIGxldCBtYXNrID0gKCgxIDw8IGJpdHNUb1dyaXRlKSAtIDEpIDw8IDggLSBiaXRJbmRleCAtIGJpdHNUb1dyaXRlOwogICAgICAgICAgICBsZXQgb3V0Qnl0ZSA9IHRoaXMuZHYuZ2V0VWludDgoYnl0ZUluZGV4KSAmIH5tYXNrOwogICAgICAgICAgICBvdXRCeXRlIHw9IHNoaWZ0ZWQgJiBtYXNrOwogICAgICAgICAgICB0aGlzLmR2LnNldFVpbnQ4KGJ5dGVJbmRleCwgb3V0Qnl0ZSk7CiAgICAgICAgICAgIGJpdEluZGV4ICs9IGJpdHNUb1dyaXRlOwogICAgICAgICAgICBiaXRDb3VudCAtPSBiaXRzVG9Xcml0ZTsKICAgICAgICB9CiAgICB9Cn0KY2xhc3MgSENBRnJhbWUgewogICAgY29uc3RydWN0b3IoaGNhKSB7CiAgICAgICAgdGhpcy5BY2NlcHRhYmxlTm9pc2VMZXZlbCA9IDA7CiAgICAgICAgdGhpcy5FdmFsdWF0aW9uQm91bmRhcnkgPSAwOwogICAgICAgIHRoaXMuSGNhID0gaGNhOwogICAgICAgIGxldCBjaGFubmVsVHlwZXMgPSBIQ0FGcmFtZS5HZXRDaGFubmVsVHlwZXMoaGNhKTsKICAgICAgICB0aGlzLkNoYW5uZWxzID0gW107CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoY2EuZm9ybWF0LmNoYW5uZWxDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIHRoaXMuQ2hhbm5lbHMucHVzaChuZXcgSENBQ2hhbm5lbCh7CiAgICAgICAgICAgICAgICBUeXBlOiBjaGFubmVsVHlwZXNbaV0sCiAgICAgICAgICAgICAgICBDb2RlZFNjYWxlRmFjdG9yQ291bnQ6IGNoYW5uZWxUeXBlc1tpXSA9PSBIQ0FDaGFubmVsVHlwZS5TdGVyZW9TZWNvbmRhcnkKICAgICAgICAgICAgICAgICAgICA/IGhjYS5jb21wRGVjLkJhc2VCYW5kQ291bnQKICAgICAgICAgICAgICAgICAgICA6IGhjYS5jb21wRGVjLkJhc2VCYW5kQ291bnQgKyBoY2EuY29tcERlYy5TdGVyZW9CYW5kQ291bnQKICAgICAgICAgICAgfSkpOwogICAgICAgIH0KICAgICAgICB0aGlzLkF0aEN1cnZlID0gaGNhLlVzZUF0aEN1cnZlID8gSENBRnJhbWUuU2NhbGVBdGhDdXJ2ZShoY2EuZm9ybWF0LnNhbXBsaW5nUmF0ZSkgOiBuZXcgVWludDhBcnJheShIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWUpOwogICAgfQogICAgc3RhdGljIEdldENoYW5uZWxUeXBlcyhoY2EpIHsKICAgICAgICBsZXQgY2hhbm5lbHNQZXJUcmFjayA9IGhjYS5mb3JtYXQuY2hhbm5lbENvdW50IC8gaGNhLmNvbXBEZWMuVHJhY2tDb3VudDsKICAgICAgICBpZiAoaGNhLmNvbXBEZWMuU3RlcmVvQmFuZENvdW50ID09IDAgfHwgY2hhbm5lbHNQZXJUcmFjayA9PSAxKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgQXJyYXkoOCkuZmlsbChIQ0FDaGFubmVsVHlwZSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IERpc2NyZXRlID0gSENBQ2hhbm5lbFR5cGUuRGlzY3JldGU7CiAgICAgICAgY29uc3QgU3RlcmVvUHJpbWFyeSA9IEhDQUNoYW5uZWxUeXBlLlN0ZXJlb1ByaW1hcnk7CiAgICAgICAgY29uc3QgU3RlcmVvU2Vjb25kYXJ5ID0gSENBQ2hhbm5lbFR5cGUuU3RlcmVvU2Vjb25kYXJ5OwogICAgICAgIHN3aXRjaCAoY2hhbm5lbHNQZXJUcmFjaykgewogICAgICAgICAgICBjYXNlIDI6IHJldHVybiBbU3RlcmVvUHJpbWFyeSwgU3RlcmVvU2Vjb25kYXJ5XTsKICAgICAgICAgICAgY2FzZSAzOiByZXR1cm4gW1N0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeSwgRGlzY3JldGVdOwogICAgICAgICAgICBjYXNlIDQ6IGlmIChoY2EuY29tcERlYy5DaGFubmVsQ29uZmlnICE9IDApCiAgICAgICAgICAgICAgICByZXR1cm4gW1N0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeSwgRGlzY3JldGUsIERpc2NyZXRlXTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgcmV0dXJuIFtTdGVyZW9QcmltYXJ5LCBTdGVyZW9TZWNvbmRhcnksIFN0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeV07CiAgICAgICAgICAgIGNhc2UgNTogaWYgKGhjYS5jb21wRGVjLkNoYW5uZWxDb25maWcgPiAyKQogICAgICAgICAgICAgICAgcmV0dXJuIFtTdGVyZW9QcmltYXJ5LCBTdGVyZW9TZWNvbmRhcnksIERpc2NyZXRlLCBEaXNjcmV0ZSwgRGlzY3JldGVdOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICByZXR1cm4gW1N0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeSwgRGlzY3JldGUsIFN0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeV07CiAgICAgICAgICAgIGNhc2UgNjogcmV0dXJuIFtTdGVyZW9QcmltYXJ5LCBTdGVyZW9TZWNvbmRhcnksIERpc2NyZXRlLCBEaXNjcmV0ZSwgU3RlcmVvUHJpbWFyeSwgU3RlcmVvU2Vjb25kYXJ5XTsKICAgICAgICAgICAgY2FzZSA3OiByZXR1cm4gW1N0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeSwgRGlzY3JldGUsIERpc2NyZXRlLCBTdGVyZW9QcmltYXJ5LCBTdGVyZW9TZWNvbmRhcnksIERpc2NyZXRlXTsKICAgICAgICAgICAgY2FzZSA4OiByZXR1cm4gW1N0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeSwgRGlzY3JldGUsIERpc2NyZXRlLCBTdGVyZW9QcmltYXJ5LCBTdGVyZW9TZWNvbmRhcnksIFN0ZXJlb1ByaW1hcnksIFN0ZXJlb1NlY29uZGFyeV07CiAgICAgICAgICAgIGRlZmF1bHQ6IHJldHVybiBuZXcgQXJyYXkoY2hhbm5lbHNQZXJUcmFjaykuZmlsbChIQ0FDaGFubmVsVHlwZSk7CiAgICAgICAgfQogICAgfQogICAgLy8vIDxzdW1tYXJ5PgogICAgLy8vIFNjYWxlcyBhbiBBVEggY3VydmUgdG8gdGhlIHNwZWNpZmllZCBmcmVxdWVuY3kuCiAgICAvLy8gPC9zdW1tYXJ5PgogICAgLy8vIDxwYXJhbSBuYW1lPSJmcmVxdWVuY3kiPlRoZSBmcmVxdWVuY3kgdG8gc2NhbGUgdGhlIGN1cnZlIHRvLjwvcGFyYW0+CiAgICAvLy8gPHJldHVybnM+VGhlIHNjYWxlZCBBVEggY3VydmU8L3JldHVybnM+CiAgICAvLy8gPHJlbWFya3M+VGhlIG9yaWdpbmFsIEFUSCBjdXJ2ZSBpcyBmb3IgYSBmcmVxdWVuY3kgb2YgNDE4NTYgSHouPC9yZW1hcmtzPgogICAgc3RhdGljIFNjYWxlQXRoQ3VydmUoZnJlcXVlbmN5KSB7CiAgICAgICAgdmFyIGF0aCA9IG5ldyBVaW50OEFycmF5KEhDQUZyYW1lLlNhbXBsZXNQZXJTdWJGcmFtZSk7CiAgICAgICAgbGV0IGFjYyA9IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGF0aC5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBhY2MgKz0gZnJlcXVlbmN5OwogICAgICAgICAgICBsZXQgaW5kZXggPSBhY2MgPj4gMTM7CiAgICAgICAgICAgIGlmIChpbmRleCA+PSBIQ0FUYWJsZXMuQXRoQ3VydmUubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBhdGhbaV0gPSBIQ0FUYWJsZXMuQXRoQ3VydmVbaW5kZXhdOwogICAgICAgIH0KICAgICAgICBmb3IgKDsgaSA8IGF0aC5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBhdGhbaV0gPSAweGZmOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYXRoOwogICAgfQp9Cl9hID0gSENBRnJhbWU7CkhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lID0gODsKSENBRnJhbWUuU3ViRnJhbWVTYW1wbGVzQml0cyA9IDc7CkhDQUZyYW1lLlNhbXBsZXNQZXJTdWJGcmFtZSA9IDEgPDwgX2EuU3ViRnJhbWVTYW1wbGVzQml0czsKSENBRnJhbWUuU2FtcGxlc1BlckZyYW1lID0gX2EuU3ViZnJhbWVzUGVyRnJhbWUgKiBfYS5TYW1wbGVzUGVyU3ViRnJhbWU7CmNsYXNzIEhDQUNoYW5uZWwgewogICAgY29uc3RydWN0b3IodmFsdWVzKSB7CiAgICAgICAgdGhpcy5UeXBlID0gMDsKICAgICAgICB0aGlzLkNvZGVkU2NhbGVGYWN0b3JDb3VudCA9IDA7CiAgICAgICAgdGhpcy5QY21GbG9hdCA9IEFycmF5LmZyb20oeyBsZW5ndGg6IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lIH0sICgpID0+IG5ldyBGbG9hdDY0QXJyYXkoSENBRnJhbWUuU2FtcGxlc1BlclN1YkZyYW1lKSk7CiAgICAgICAgdGhpcy5TcGVjdHJhID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogSENBRnJhbWUuU3ViZnJhbWVzUGVyRnJhbWUgfSwgKCkgPT4gbmV3IEZsb2F0NjRBcnJheShIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWUpKTsKICAgICAgICB0aGlzLlNjYWxlZFNwZWN0cmEgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiBIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWUgfSwgKCkgPT4gbmV3IEZsb2F0NjRBcnJheShIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZSkpOwogICAgICAgIHRoaXMuUXVhbnRpemVkU3BlY3RyYSA9IEFycmF5LmZyb20oeyBsZW5ndGg6IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lIH0sICgpID0+IG5ldyBJbnQzMkFycmF5KEhDQUZyYW1lLlNhbXBsZXNQZXJTdWJGcmFtZSkpOwogICAgICAgIHRoaXMuR2FpbiA9IG5ldyBGbG9hdDY0QXJyYXkoSENBRnJhbWUuU2FtcGxlc1BlclN1YkZyYW1lKTsKICAgICAgICB0aGlzLkludGVuc2l0eSA9IG5ldyBJbnQzMkFycmF5KEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lKTsKICAgICAgICB0aGlzLkhmclNjYWxlcyA9IG5ldyBJbnQzMkFycmF5KDgpOwogICAgICAgIHRoaXMuSGZyR3JvdXBBdmVyYWdlU3BlY3RyYSA9IG5ldyBGbG9hdDY0QXJyYXkoOCk7CiAgICAgICAgdGhpcy5NZGN0ID0gbmV3IEhDQU1kY3QoSENBRnJhbWUuU3ViRnJhbWVTYW1wbGVzQml0cywgSENBVGFibGVzLk1kY3RXaW5kb3csIE1hdGguc3FydCgyLjAgLyBIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWUpKTsKICAgICAgICB0aGlzLlNjYWxlRmFjdG9ycyA9IG5ldyBJbnQzMkFycmF5KEhDQUZyYW1lLlNhbXBsZXNQZXJTdWJGcmFtZSk7CiAgICAgICAgdGhpcy5SZXNvbHV0aW9uID0gbmV3IEludDMyQXJyYXkoSENBRnJhbWUuU2FtcGxlc1BlclN1YkZyYW1lKTsKICAgICAgICB0aGlzLkhlYWRlckxlbmd0aEJpdHMgPSAwOwogICAgICAgIHRoaXMuU2NhbGVGYWN0b3JEZWx0YUJpdHMgPSAwOwogICAgICAgIGxldCB0ID0gdGhpczsKICAgICAgICBmb3IgKGxldCBrZXkgaW4gdmFsdWVzKSB7CiAgICAgICAgICAgIHRba2V5XSA9IHZhbHVlc1trZXldOwogICAgICAgIH0KICAgIH0KfQp2YXIgSENBQ2hhbm5lbFR5cGU7CihmdW5jdGlvbiAoSENBQ2hhbm5lbFR5cGUpIHsKICAgIEhDQUNoYW5uZWxUeXBlW0hDQUNoYW5uZWxUeXBlWyJEaXNjcmV0ZSJdID0gMF0gPSAiRGlzY3JldGUiOwogICAgSENBQ2hhbm5lbFR5cGVbSENBQ2hhbm5lbFR5cGVbIlN0ZXJlb1ByaW1hcnkiXSA9IDFdID0gIlN0ZXJlb1ByaW1hcnkiOwogICAgSENBQ2hhbm5lbFR5cGVbSENBQ2hhbm5lbFR5cGVbIlN0ZXJlb1NlY29uZGFyeSJdID0gMl0gPSAiU3RlcmVvU2Vjb25kYXJ5IjsKfSkoSENBQ2hhbm5lbFR5cGUgfHwgKEhDQUNoYW5uZWxUeXBlID0ge30pKTsKY2xhc3MgSENBRGVjb2RlciB7CiAgICBzdGF0aWMgRGVjb2RlRnJhbWUoYXVkaW8sIGZyYW1lKSB7CiAgICAgICAgbGV0IHJlYWRlciA9IG5ldyBIQ0FCaXRSZWFkZXIoYXVkaW8pOwogICAgICAgIGlmICghSENBUGFja2luZy5VbnBhY2tGcmFtZShmcmFtZSwgcmVhZGVyKSkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnBhY2tGcmFtZSBmYWlsZWRgKTsKICAgICAgICB0aGlzLkRlcXVhbnRpemVGcmFtZShmcmFtZSk7CiAgICAgICAgdGhpcy5SZXN0b3JlTWlzc2luZ0JhbmRzKGZyYW1lKTsKICAgICAgICB0aGlzLlJ1bkltZGN0KGZyYW1lKTsKICAgIH0KICAgIHN0YXRpYyBEZXF1YW50aXplRnJhbWUoZnJhbWUpIHsKICAgICAgICBmb3IgKGxldCBjaGFubmVsIG9mIGZyYW1lLkNoYW5uZWxzKSB7CiAgICAgICAgICAgIHRoaXMuQ2FsY3VsYXRlR2FpbihjaGFubmVsKTsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgc2YgPSAwOyBzZiA8IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lOyBzZisrKSB7CiAgICAgICAgICAgIGZvciAobGV0IGNoYW5uZWwgb2YgZnJhbWUuQ2hhbm5lbHMpIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IHMgPSAwOyBzIDwgY2hhbm5lbC5Db2RlZFNjYWxlRmFjdG9yQ291bnQ7IHMrKykgewogICAgICAgICAgICAgICAgICAgIGNoYW5uZWwuU3BlY3RyYVtzZl1bc10gPSBjaGFubmVsLlF1YW50aXplZFNwZWN0cmFbc2ZdW3NdICogY2hhbm5lbC5HYWluW3NdOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgc3RhdGljIFJlc3RvcmVNaXNzaW5nQmFuZHMoZnJhbWUpIHsKICAgICAgICB0aGlzLlJlY29uc3RydWN0SGlnaEZyZXF1ZW5jeShmcmFtZSk7CiAgICAgICAgdGhpcy5BcHBseUludGVuc2l0eVN0ZXJlbyhmcmFtZSk7CiAgICB9CiAgICBzdGF0aWMgQ2FsY3VsYXRlR2FpbihjaGFubmVsKSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGFubmVsLkNvZGVkU2NhbGVGYWN0b3JDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGNoYW5uZWwuR2FpbltpXSA9IEhDQVRhYmxlcy5EZXF1YW50aXplclNjYWxpbmdUYWJsZVtjaGFubmVsLlNjYWxlRmFjdG9yc1tpXV0gKiBIQ0FUYWJsZXMuUXVhbnRpemVyU3RlcFNpemVbY2hhbm5lbC5SZXNvbHV0aW9uW2ldXTsKICAgICAgICB9CiAgICB9CiAgICBzdGF0aWMgUmVjb25zdHJ1Y3RIaWdoRnJlcXVlbmN5KGZyYW1lKSB7CiAgICAgICAgbGV0IGhjYSA9IGZyYW1lLkhjYTsKICAgICAgICBpZiAoaGNhLkhmckdyb3VwQ291bnQgPT0gMCkKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIC8vIFRoZSBsYXN0IHNwZWN0cmFsIGNvZWZmaWNpZW50IHNob3VsZCBhbHdheXMgYmUgMDsKICAgICAgICBsZXQgdG90YWxCYW5kQ291bnQgPSBNYXRoLm1pbihoY2EuY29tcERlYy5Ub3RhbEJhbmRDb3VudCwgMTI3KTsKICAgICAgICBsZXQgaGZyU3RhcnRCYW5kID0gaGNhLmNvbXBEZWMuQmFzZUJhbmRDb3VudCArIGhjYS5jb21wRGVjLlN0ZXJlb0JhbmRDb3VudDsKICAgICAgICBsZXQgaGZyQmFuZENvdW50ID0gTWF0aC5taW4oaGNhLmNvbXBEZWMuSGZyQmFuZENvdW50LCB0b3RhbEJhbmRDb3VudCAtIGhjYS5jb21wRGVjLkhmckJhbmRDb3VudCk7CiAgICAgICAgZm9yIChsZXQgY2hhbm5lbCBvZiBmcmFtZS5DaGFubmVscykgewogICAgICAgICAgICBpZiAoY2hhbm5lbC5UeXBlID09IEhDQUNoYW5uZWxUeXBlLlN0ZXJlb1NlY29uZGFyeSkKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICBmb3IgKGxldCBncm91cCA9IDAsIGJhbmQgPSAwOyBncm91cCA8IGhjYS5IZnJHcm91cENvdW50OyBncm91cCsrKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGhjYS5jb21wRGVjLkJhbmRzUGVySGZyR3JvdXAgJiYgYmFuZCA8IGhmckJhbmRDb3VudDsgYmFuZCsrLCBpKyspIHsKICAgICAgICAgICAgICAgICAgICBsZXQgaGlnaEJhbmQgPSBoZnJTdGFydEJhbmQgKyBiYW5kOwogICAgICAgICAgICAgICAgICAgIGxldCBsb3dCYW5kID0gaGZyU3RhcnRCYW5kIC0gYmFuZCAtIDE7CiAgICAgICAgICAgICAgICAgICAgbGV0IGluZGV4ID0gY2hhbm5lbC5IZnJTY2FsZXNbZ3JvdXBdIC0gY2hhbm5lbC5TY2FsZUZhY3RvcnNbbG93QmFuZF0gKyA2NDsKICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBzZiA9IDA7IHNmIDwgSENBRnJhbWUuU3ViZnJhbWVzUGVyRnJhbWU7IHNmKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2hhbm5lbC5TcGVjdHJhW3NmXVtoaWdoQmFuZF0gPSBIQ0FUYWJsZXMuU2NhbGVDb252ZXJzaW9uVGFibGVbaW5kZXhdICogY2hhbm5lbC5TcGVjdHJhW3NmXVtsb3dCYW5kXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICBzdGF0aWMgQXBwbHlJbnRlbnNpdHlTdGVyZW8oZnJhbWUpIHsKICAgICAgICBpZiAoZnJhbWUuSGNhLmNvbXBEZWMuU3RlcmVvQmFuZENvdW50IDw9IDApCiAgICAgICAgICAgIHJldHVybjsKICAgICAgICBmb3IgKGxldCBjID0gMDsgYyA8IGZyYW1lLkNoYW5uZWxzLmxlbmd0aDsgYysrKSB7CiAgICAgICAgICAgIGlmIChmcmFtZS5DaGFubmVsc1tjXS5UeXBlICE9IEhDQUNoYW5uZWxUeXBlLlN0ZXJlb1ByaW1hcnkpCiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgZm9yIChsZXQgc2YgPSAwOyBzZiA8IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lOyBzZisrKSB7CiAgICAgICAgICAgICAgICBsZXQgbCA9IGZyYW1lLkNoYW5uZWxzW2NdLlNwZWN0cmFbc2ZdOwogICAgICAgICAgICAgICAgbGV0IHIgPSBmcmFtZS5DaGFubmVsc1tjICsgMV0uU3BlY3RyYVtzZl07CiAgICAgICAgICAgICAgICBsZXQgcmF0aW9MID0gSENBVGFibGVzLkludGVuc2l0eVJhdGlvVGFibGVbZnJhbWUuQ2hhbm5lbHNbYyArIDFdLkludGVuc2l0eVtzZl1dOwogICAgICAgICAgICAgICAgbGV0IHJhdGlvUiA9IHJhdGlvTCAtIDIuMDsKICAgICAgICAgICAgICAgIGZvciAobGV0IGIgPSBmcmFtZS5IY2EuY29tcERlYy5CYXNlQmFuZENvdW50OyBiIDwgZnJhbWUuSGNhLmNvbXBEZWMuVG90YWxCYW5kQ291bnQ7IGIrKykgewogICAgICAgICAgICAgICAgICAgIHJbYl0gPSBsW2JdICogcmF0aW9SOwogICAgICAgICAgICAgICAgICAgIGxbYl0gKj0gcmF0aW9MOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgc3RhdGljIFJ1bkltZGN0KGZyYW1lKSB7CiAgICAgICAgZm9yIChsZXQgc2YgPSAwOyBzZiA8IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lOyBzZisrKSB7CiAgICAgICAgICAgIGZvciAobGV0IGNoYW5uZWwgb2YgZnJhbWUuQ2hhbm5lbHMpIHsKICAgICAgICAgICAgICAgIGNoYW5uZWwuTWRjdC5SdW5JbWRjdChjaGFubmVsLlNwZWN0cmFbc2ZdLCBjaGFubmVsLlBjbUZsb2F0W3NmXSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9Cn0KY2xhc3MgSENBUGFja2luZyB7CiAgICBzdGF0aWMgVW5wYWNrRnJhbWUoZnJhbWUsIHJlYWRlcikgewogICAgICAgIGlmICghdGhpcy5VbnBhY2tGcmFtZUhlYWRlcihmcmFtZSwgcmVhZGVyKSkKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIHRoaXMuUmVhZFNwZWN0cmFsQ29lZmZpY2llbnRzKGZyYW1lLCByZWFkZXIpOwogICAgICAgIHJldHVybiB0aGlzLlVucGFja2luZ1dhc1N1Y2Nlc3NmdWwoZnJhbWUsIHJlYWRlcik7CiAgICB9CiAgICBzdGF0aWMgUGFja0ZyYW1lKGZyYW1lLCBvdXRCdWZmZXIpIHsKICAgICAgICB2YXIgd3JpdGVyID0gbmV3IEhDQUJpdFdyaXRlcihvdXRCdWZmZXIpOwogICAgICAgIHdyaXRlci5Xcml0ZSgweGZmZmYsIDE2KTsKICAgICAgICB3cml0ZXIuV3JpdGUoZnJhbWUuQWNjZXB0YWJsZU5vaXNlTGV2ZWwsIDkpOwogICAgICAgIHdyaXRlci5Xcml0ZShmcmFtZS5FdmFsdWF0aW9uQm91bmRhcnksIDcpOwogICAgICAgIGZvciAobGV0IGNoYW5uZWwgb2YgZnJhbWUuQ2hhbm5lbHMpIHsKICAgICAgICAgICAgdGhpcy5Xcml0ZVNjYWxlRmFjdG9ycyh3cml0ZXIsIGNoYW5uZWwpOwogICAgICAgICAgICBpZiAoY2hhbm5lbC5UeXBlID09IEhDQUNoYW5uZWxUeXBlLlN0ZXJlb1NlY29uZGFyeSkgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZTsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLldyaXRlKGNoYW5uZWwuSW50ZW5zaXR5W2ldLCA0KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmIChmcmFtZS5IY2EuSGZyR3JvdXBDb3VudCA+IDApIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnJhbWUuSGNhLkhmckdyb3VwQ291bnQ7IGkrKykgewogICAgICAgICAgICAgICAgICAgIHdyaXRlci5Xcml0ZShjaGFubmVsLkhmclNjYWxlc1tpXSwgNik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgc2YgPSAwOyBzZiA8IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lOyBzZisrKSB7CiAgICAgICAgICAgIGZvciAobGV0IGNoYW5uZWwgb2YgZnJhbWUuQ2hhbm5lbHMpIHsKICAgICAgICAgICAgICAgIHRoaXMuV3JpdGVTcGVjdHJhKHdyaXRlciwgY2hhbm5lbCwgc2YpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHdyaXRlci5BbGlnblBvc2l0aW9uKDgpOwogICAgICAgIGZvciAobGV0IGkgPSB3cml0ZXIuUG9zaXRpb24gLyA4OyBpIDwgZnJhbWUuSGNhLmJsb2NrU2l6ZSAtIDI7IGkrKykgewogICAgICAgICAgICB3cml0ZXIuZHYuc2V0VWludDgoaSwgMCk7CiAgICAgICAgfQogICAgICAgIHRoaXMuV3JpdGVDaGVja3N1bSh3cml0ZXIsIG91dEJ1ZmZlcik7CiAgICB9CiAgICBzdGF0aWMgQ2FsY3VsYXRlUmVzb2x1dGlvbihzY2FsZUZhY3Rvciwgbm9pc2VMZXZlbCwgdmVyc2lvbk1ham9yKSB7CiAgICAgICAgaWYgKHNjYWxlRmFjdG9yID09IDApIHsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQogICAgICAgIGxldCBjdXJ2ZVBvc2l0aW9uID0gbm9pc2VMZXZlbCAtICg1ICogc2NhbGVGYWN0b3IgPj4gMSkgKyAyOwogICAgICAgIC8vaHR0cHM6Ly9naXRodWIuY29tL3ZnbXN0cmVhbS92Z21zdHJlYW0vYmxvYi80ZWVjZGFkYTlhMDNhNzNhZjBjN2MxN2Y1Y2Q2ZTA4NTE4ZmQ3ZTNmL3NyYy9jb2RpbmcvaGNhX2RlY29kZXJfY2xoY2EuYyNMMTQ1MAogICAgICAgIC8vRklYTUUgaGNhMi4wIGRlY29kaW5nIGJyZWFrcyBpZiBjb25kaXRpb25hbCAodGVybmFyeSkgb3BlcmF0b3IgaXMgcmVtb3ZlZAogICAgICAgIC8vY3VydmVQb3NpdGlvbiA9IEhDQVV0aWxGdW5jLkNsYW1wKGN1cnZlUG9zaXRpb24sIDAsIDY3KTsKICAgICAgICBjdXJ2ZVBvc2l0aW9uID0gSENBVXRpbEZ1bmMuQ2xhbXAoY3VydmVQb3NpdGlvbiwgMCwgdmVyc2lvbk1ham9yIDw9IDIgPyA1OCA6IDY3KTsKICAgICAgICByZXR1cm4gSENBVGFibGVzLlNjYWxlVG9SZXNvbHV0aW9uQ3VydmVbY3VydmVQb3NpdGlvbl07CiAgICB9CiAgICBzdGF0aWMgVW5wYWNrRnJhbWVIZWFkZXIoZnJhbWUsIHJlYWRlcikgewogICAgICAgIGxldCBoY2EgPSBmcmFtZS5IY2E7CiAgICAgICAgbGV0IHN5bmNXb3JkID0gcmVhZGVyLlJlYWRJbnQoMTYpOwogICAgICAgIGlmIChzeW5jV29yZCAhPSAweGZmZmYpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJJbnZhbGlkIGZyYW1lIGhlYWRlciIpOwogICAgICAgIH0KICAgICAgICBsZXQgYXRoQ3VydmUgPSBmcmFtZS5BdGhDdXJ2ZTsKICAgICAgICBmcmFtZS5BY2NlcHRhYmxlTm9pc2VMZXZlbCA9IHJlYWRlci5SZWFkSW50KDkpOwogICAgICAgIGZyYW1lLkV2YWx1YXRpb25Cb3VuZGFyeSA9IHJlYWRlci5SZWFkSW50KDcpOwogICAgICAgIGZvciAobGV0IGNoYW5uZWwgb2YgZnJhbWUuQ2hhbm5lbHMpIHsKICAgICAgICAgICAgaWYgKCF0aGlzLlJlYWRTY2FsZUZhY3RvcnMoY2hhbm5lbCwgcmVhZGVyLCBoY2EuSGZyR3JvdXBDb3VudCwgaGNhLnZlcnNpb25NYWpvcikpCiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIC8vIGFkZGVkIGNsYW1wCiAgICAgICAgICAgIC8vaHR0cHM6Ly9naXRodWIuY29tL3ZnbXN0cmVhbS92Z21zdHJlYW0vYmxvYi80ZWVjZGFkYTlhMDNhNzNhZjBjN2MxN2Y1Y2Q2ZTA4NTE4ZmQ3ZTNmL3NyYy9jb2RpbmcvaGNhX2RlY29kZXJfY2xoY2EuYyNMMTQ2MgogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZyYW1lLkV2YWx1YXRpb25Cb3VuZGFyeTsgaSsrKSB7CiAgICAgICAgICAgICAgICBsZXQgbmV3UmVzb2x1dGlvbiA9IHRoaXMuQ2FsY3VsYXRlUmVzb2x1dGlvbihjaGFubmVsLlNjYWxlRmFjdG9yc1tpXSwgYXRoQ3VydmVbaV0gKyBmcmFtZS5BY2NlcHRhYmxlTm9pc2VMZXZlbCAtIDEsIGhjYS52ZXJzaW9uTWFqb3IpOwogICAgICAgICAgICAgICAgaWYgKGhjYS52ZXJzaW9uTWFqb3IgPiAyKQogICAgICAgICAgICAgICAgICAgIG5ld1Jlc29sdXRpb24gPSBIQ0FVdGlsRnVuYy5DbGFtcChuZXdSZXNvbHV0aW9uLCBoY2EuY29tcERlYy5NaW5SZXNvbHV0aW9uLCBoY2EuY29tcERlYy5NYXhSZXNvbHV0aW9uKTsKICAgICAgICAgICAgICAgIGNoYW5uZWwuUmVzb2x1dGlvbltpXSA9IG5ld1Jlc29sdXRpb247CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yIChsZXQgaSA9IGZyYW1lLkV2YWx1YXRpb25Cb3VuZGFyeTsgaSA8IGNoYW5uZWwuQ29kZWRTY2FsZUZhY3RvckNvdW50OyBpKyspIHsKICAgICAgICAgICAgICAgIGxldCBuZXdSZXNvbHV0aW9uID0gdGhpcy5DYWxjdWxhdGVSZXNvbHV0aW9uKGNoYW5uZWwuU2NhbGVGYWN0b3JzW2ldLCBhdGhDdXJ2ZVtpXSArIGZyYW1lLkFjY2VwdGFibGVOb2lzZUxldmVsLCBoY2EudmVyc2lvbk1ham9yKTsKICAgICAgICAgICAgICAgIGlmIChoY2EudmVyc2lvbk1ham9yID4gMikKICAgICAgICAgICAgICAgICAgICBuZXdSZXNvbHV0aW9uID0gSENBVXRpbEZ1bmMuQ2xhbXAobmV3UmVzb2x1dGlvbiwgaGNhLmNvbXBEZWMuTWluUmVzb2x1dGlvbiwgaGNhLmNvbXBEZWMuTWF4UmVzb2x1dGlvbik7CiAgICAgICAgICAgICAgICBjaGFubmVsLlJlc29sdXRpb25baV0gPSBuZXdSZXNvbHV0aW9uOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChjaGFubmVsLlR5cGUgPT0gSENBQ2hhbm5lbFR5cGUuU3RlcmVvU2Vjb25kYXJ5KSB7CiAgICAgICAgICAgICAgICB0aGlzLlJlYWRJbnRlbnNpdHkocmVhZGVyLCBjaGFubmVsLkludGVuc2l0eSwgaGNhLnZlcnNpb25NYWpvcik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoZnJhbWUuSGNhLkhmckdyb3VwQ291bnQgPiAwKSB7CiAgICAgICAgICAgICAgICBpZiAoaGNhLnZlcnNpb25NYWpvciA8PSAyKQogICAgICAgICAgICAgICAgICAgIHRoaXMuUmVhZEhmclNjYWxlRmFjdG9ycyhyZWFkZXIsIGZyYW1lLkhjYS5IZnJHcm91cENvdW50LCBjaGFubmVsLkhmclNjYWxlcyk7CiAgICAgICAgICAgICAgICAvLyB2My4wIHVzZXMgdmFsdWVzIGRlcml2ZWQgaW4gUmVhZFNjYWxlRmFjdG9ycwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgc3RhdGljIFJlYWRTY2FsZUZhY3RvcnMoY2hhbm5lbCwgcmVhZGVyLCBoZnJHcm91cENvdW50LCB2ZXJzaW9uTWFqb3IpIHsKICAgICAgICBjaGFubmVsLlNjYWxlRmFjdG9yRGVsdGFCaXRzID0gcmVhZGVyLlJlYWRJbnQoMyk7CiAgICAgICAgaWYgKGNoYW5uZWwuU2NhbGVGYWN0b3JEZWx0YUJpdHMgPT0gMCkgewogICAgICAgICAgICBjaGFubmVsLlNjYWxlRmFjdG9ycy5maWxsKDAsIDAsIGNoYW5uZWwuU2NhbGVGYWN0b3JzLmxlbmd0aCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICAvLyBhZGRlZCBpbiB2My4wCiAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3ZnbXN0cmVhbS92Z21zdHJlYW0vYmxvYi80ZWVjZGFkYTlhMDNhNzNhZjBjN2MxN2Y1Y2Q2ZTA4NTE4ZmQ3ZTNmL3NyYy9jb2RpbmcvaGNhX2RlY29kZXJfY2xoY2EuYyNMMTI4NwogICAgICAgIGxldCBleHRyYUNvZGVkU2NhbGVGYWN0b3JDb3VudDsKICAgICAgICBsZXQgY29kZWRTY2FsZUZhY3RvckNvdW50OwogICAgICAgIGlmIChjaGFubmVsLlR5cGUgPT0gSENBQ2hhbm5lbFR5cGUuU3RlcmVvU2Vjb25kYXJ5IHx8IGhmckdyb3VwQ291bnQgPD0gMCB8fCB2ZXJzaW9uTWFqb3IgPD0gMikgewogICAgICAgICAgICBleHRyYUNvZGVkU2NhbGVGYWN0b3JDb3VudCA9IDA7CiAgICAgICAgICAgIGNvZGVkU2NhbGVGYWN0b3JDb3VudCA9IGNoYW5uZWwuQ29kZWRTY2FsZUZhY3RvckNvdW50OwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgZXh0cmFDb2RlZFNjYWxlRmFjdG9yQ291bnQgPSBoZnJHcm91cENvdW50OwogICAgICAgICAgICBjb2RlZFNjYWxlRmFjdG9yQ291bnQgPSBjaGFubmVsLkNvZGVkU2NhbGVGYWN0b3JDb3VudCArIGV4dHJhQ29kZWRTY2FsZUZhY3RvckNvdW50OwogICAgICAgICAgICAvLyBqdXN0IGluIGNhc2UKICAgICAgICAgICAgaWYgKGNvZGVkU2NhbGVGYWN0b3JDb3VudCA+IEhDQUZyYW1lLlNhbXBsZXNQZXJTdWJGcmFtZSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgY29kZWRTY2FsZUZhY3RvckNvdW50ID4gSENBRnJhbWUuU2FtcGxlc1BlclN1YkZyYW1lYCk7CiAgICAgICAgfQogICAgICAgIGlmIChjaGFubmVsLlNjYWxlRmFjdG9yRGVsdGFCaXRzID49IDYpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb2RlZFNjYWxlRmFjdG9yQ291bnQ7IGkrKykgewogICAgICAgICAgICAgICAgY2hhbm5lbC5TY2FsZUZhY3RvcnNbaV0gPSByZWFkZXIuUmVhZEludCg2KTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgbGV0IHJlc3VsdCA9IHRoaXMuRGVsdGFEZWNvZGUocmVhZGVyLCBjaGFubmVsLlNjYWxlRmFjdG9yRGVsdGFCaXRzLCA2LCBjb2RlZFNjYWxlRmFjdG9yQ291bnQsIGNoYW5uZWwuU2NhbGVGYWN0b3JzKTsKICAgICAgICBpZiAoIXJlc3VsdCkKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAvLyBzZXQgZGVyaXZlZCBIRlIgc2NhbGVzIGZvciB2My4wCiAgICAgICAgLy9GSVhNRSBVTlRFU1RFRAogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXh0cmFDb2RlZFNjYWxlRmFjdG9yQ291bnQ7IGkrKykgewogICAgICAgICAgICBjaGFubmVsLkhmclNjYWxlc1tjb2RlZFNjYWxlRmFjdG9yQ291bnQgLSAxIC0gaV0gPSBjaGFubmVsLlNjYWxlRmFjdG9yc1tjb2RlZFNjYWxlRmFjdG9yQ291bnQgLSBpXTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIHN0YXRpYyBSZWFkSW50ZW5zaXR5KHJlYWRlciwgaW50ZW5zaXR5LCB2ZXJzaW9uTWFqb3IpIHsKICAgICAgICBpZiAodmVyc2lvbk1ham9yIDw9IDIpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZTsgaSsrKSB7CiAgICAgICAgICAgICAgICBpbnRlbnNpdHlbaV0gPSByZWFkZXIuUmVhZEludCg0KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgLy9odHRwczovL2dpdGh1Yi5jb20vdmdtc3RyZWFtL3ZnbXN0cmVhbS9ibG9iLzRlZWNkYWRhOWEwM2E3M2FmMGM3YzE3ZjVjZDZlMDg1MThmZDdlM2Yvc3JjL2NvZGluZy9oY2FfZGVjb2Rlcl9jbGhjYS5jI0wxMzc0CiAgICAgICAgICAgIGxldCB2YWx1ZSA9IHJlYWRlci5SZWFkSW50KDQpOwogICAgICAgICAgICBsZXQgZGVsdGFfYml0czsKICAgICAgICAgICAgaWYgKHZhbHVlIDwgMTUpIHsKICAgICAgICAgICAgICAgIGRlbHRhX2JpdHMgPSByZWFkZXIuUmVhZEludCgyKTsgLyogKzEgKi8KICAgICAgICAgICAgICAgIGludGVuc2l0eVswXSA9IHZhbHVlOwogICAgICAgICAgICAgICAgaWYgKGRlbHRhX2JpdHMgPT0gMykgeyAvKiAzKzEgPSA0YiAqLwogICAgICAgICAgICAgICAgICAgIC8qIGZpeGVkIGludGVuc2l0aWVzICovCiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBIQ0FGcmFtZS5TdWJmcmFtZXNQZXJGcmFtZTsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGludGVuc2l0eVtpXSA9IHJlYWRlci5SZWFkSW50KDQpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIC8qIGRlbHRhIGludGVuc2l0aWVzICovCiAgICAgICAgICAgICAgICAgICAgbGV0IGJtYXggPSAoMiA8PCBkZWx0YV9iaXRzKSAtIDE7CiAgICAgICAgICAgICAgICAgICAgbGV0IGJpdHMgPSBkZWx0YV9iaXRzICsgMTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRlbHRhID0gcmVhZGVyLlJlYWRJbnQoYml0cyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZWx0YSA9PSBibWF4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHJlYWRlci5SZWFkSW50KDQpOyAvKiBlbmNvZGVkICovCiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlIC0gKGJtYXggPj4gMSkgKyBkZWx0YTsgLyogZGlmZmVyZW50aWFsICovCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgPiAxNSkgLy90b2RvIGNoZWNrCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB2YWx1ZSA+IDE1YCk7IC8qIG5vdCBkb25lIGluIGxpYiAqLwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGludGVuc2l0eVtpXSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgSENBRnJhbWUuU3ViZnJhbWVzUGVyRnJhbWU7IGkrKykgewogICAgICAgICAgICAgICAgICAgIGludGVuc2l0eVtpXSA9IDc7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICBzdGF0aWMgUmVhZEhmclNjYWxlRmFjdG9ycyhyZWFkZXIsIGdyb3VwQ291bnQsIGhmclNjYWxlKSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBncm91cENvdW50OyBpKyspIHsKICAgICAgICAgICAgaGZyU2NhbGVbaV0gPSByZWFkZXIuUmVhZEludCg2KTsKICAgICAgICB9CiAgICB9CiAgICBzdGF0aWMgUmVhZFNwZWN0cmFsQ29lZmZpY2llbnRzKGZyYW1lLCByZWFkZXIpIHsKICAgICAgICBmb3IgKGxldCBzZiA9IDA7IHNmIDwgSENBRnJhbWUuU3ViZnJhbWVzUGVyRnJhbWU7IHNmKyspIHsKICAgICAgICAgICAgZm9yIChsZXQgY2hhbm5lbCBvZiBmcmFtZS5DaGFubmVscykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgcyA9IDA7IHMgPCBjaGFubmVsLkNvZGVkU2NhbGVGYWN0b3JDb3VudDsgcysrKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IHJlc29sdXRpb24gPSBjaGFubmVsLlJlc29sdXRpb25bc107CiAgICAgICAgICAgICAgICAgICAgbGV0IGJpdHMgPSBIQ0FUYWJsZXMuUXVhbnRpemVkU3BlY3RydW1NYXhCaXRzW3Jlc29sdXRpb25dOwogICAgICAgICAgICAgICAgICAgIGxldCBjb2RlID0gcmVhZGVyLlBlZWtJbnQoYml0cyk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc29sdXRpb24gPCA4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJpdHMgPSBIQ0FUYWJsZXMuUXVhbnRpemVkU3BlY3RydW1CaXRzW3Jlc29sdXRpb25dW2NvZGVdOwogICAgICAgICAgICAgICAgICAgICAgICBjaGFubmVsLlF1YW50aXplZFNwZWN0cmFbc2ZdW3NdID0gSENBVGFibGVzLlF1YW50aXplZFNwZWN0cnVtVmFsdWVbcmVzb2x1dGlvbl1bY29kZV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWFkIHRoZSBzaWduLW1hZ25pdHVkZSB2YWx1ZS4gVGhlIGxvdyBiaXQgaXMgdGhlIHNpZ24KICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHF1YW50aXplZENvZWZmaWNpZW50ID0gKGNvZGUgPj4gMSkgKiAoMSAtIChjb2RlICUgMiAqIDIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHF1YW50aXplZENvZWZmaWNpZW50ID09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpdHMtLTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjaGFubmVsLlF1YW50aXplZFNwZWN0cmFbc2ZdW3NdID0gcXVhbnRpemVkQ29lZmZpY2llbnQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlYWRlci5Qb3NpdGlvbiArPSBiaXRzOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2hhbm5lbC5TcGVjdHJhW3NmXS5maWxsKDAsIGNoYW5uZWwuQ29kZWRTY2FsZUZhY3RvckNvdW50LCBjaGFubmVsLkNvZGVkU2NhbGVGYWN0b3JDb3VudCArIDB4ODAgLSBjaGFubmVsLkNvZGVkU2NhbGVGYWN0b3JDb3VudCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICBzdGF0aWMgRGVsdGFEZWNvZGUocmVhZGVyLCBkZWx0YUJpdHMsIGRhdGFCaXRzLCBjb3VudCwgb3V0cHV0KSB7CiAgICAgICAgb3V0cHV0WzBdID0gcmVhZGVyLlJlYWRJbnQoZGF0YUJpdHMpOwogICAgICAgIGxldCBtYXhEZWx0YSA9IDEgPDwgKGRlbHRhQml0cyAtIDEpOwogICAgICAgIGxldCBtYXhWYWx1ZSA9ICgxIDw8IGRhdGFCaXRzKSAtIDE7CiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGxldCBkZWx0YSA9IHJlYWRlci5SZWFkT2Zmc2V0QmluYXJ5KGRlbHRhQml0cywgSENBT2Zmc2V0Qmlhcy5Qb3NpdGl2ZSk7CiAgICAgICAgICAgIGlmIChkZWx0YSA8IG1heERlbHRhKSB7CiAgICAgICAgICAgICAgICBsZXQgdmFsdWUgPSBvdXRwdXRbaSAtIDFdICsgZGVsdGE7CiAgICAgICAgICAgICAgICBpZiAodmFsdWUgPCAwIHx8IHZhbHVlID4gbWF4VmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vdmdtc3RyZWFtL3ZnbXN0cmVhbS9ibG9iLzRlZWNkYWRhOWEwM2E3M2FmMGM3YzE3ZjVjZDZlMDg1MThmZDdlM2Yvc3JjL2NvZGluZy9oY2FfZGVjb2Rlcl9jbGhjYS5jI0wxMzI3CiAgICAgICAgICAgICAgICAvL3ZhbHVlICY9IDB4M0Y7IC8vIHYzLjAgbGliCiAgICAgICAgICAgICAgICBvdXRwdXRbaV0gPSB2YWx1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIG91dHB1dFtpXSA9IHJlYWRlci5SZWFkSW50KGRhdGFCaXRzKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHN0YXRpYyBVbnBhY2tpbmdXYXNTdWNjZXNzZnVsKGZyYW1lLCByZWFkZXIpIHsKICAgICAgICAvLyAxMjggbGVmdG92ZXIgYml0cyBhZnRlciB1bnBhY2tpbmcgc2hvdWxkIGJlIGhpZ2ggZW5vdWdoIHRvIGdldCByaWQgb2YgZmFsc2UgbmVnYXRpdmVzLAogICAgICAgIC8vIGFuZCBsb3cgZW5vdWdoIHRoYXQgZmFsc2UgcG9zaXRpdmVzIHdpbGwgYmUgdW5jb21tb24uCiAgICAgICAgcmV0dXJuIHJlYWRlci5SZW1haW5pbmcgPj0gMTYgJiYgcmVhZGVyLlJlbWFpbmluZyA8PSAxMjgKICAgICAgICAgICAgfHwgdGhpcy5GcmFtZUVtcHR5KGZyYW1lKQogICAgICAgICAgICB8fCBmcmFtZS5BY2NlcHRhYmxlTm9pc2VMZXZlbCA9PSAwICYmIHJlYWRlci5SZW1haW5pbmcgPj0gMTY7CiAgICB9CiAgICBzdGF0aWMgRnJhbWVFbXB0eShmcmFtZSkgewogICAgICAgIGlmIChmcmFtZS5BY2NlcHRhYmxlTm9pc2VMZXZlbCA+IDApCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAvLyBJZiBhbGwgdGhlIHNjYWxlIGZhY3RvcnMgYXJlIDAsIHRoZSBmcmFtZSBpcyBlbXB0eQogICAgICAgIGZvciAobGV0IGNoYW5uZWwgb2YgZnJhbWUuQ2hhbm5lbHMpIHsKICAgICAgICAgICAgaWYgKGNoYW5uZWwuU2NhbGVGYWN0b3JEZWx0YUJpdHMgPiAwKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBzdGF0aWMgV3JpdGVDaGVja3N1bSh3cml0ZXIsIGhjYUJ1ZmZlcikgewogICAgICAgIHdyaXRlci5Qb3NpdGlvbiA9IHdyaXRlci5MZW5ndGhCaXRzIC0gMTY7CiAgICAgICAgbGV0IGNyYzE2ID0gSENBQ3JjMTYuY2FsYyhoY2FCdWZmZXIsIGhjYUJ1ZmZlci5sZW5ndGggLSAyKTsKICAgICAgICB3cml0ZXIuV3JpdGUoY3JjMTYsIDE2KTsKICAgIH0KICAgIHN0YXRpYyBXcml0ZVNwZWN0cmEod3JpdGVyLCBjaGFubmVsLCBzdWJGcmFtZSkgewogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhbm5lbC5Db2RlZFNjYWxlRmFjdG9yQ291bnQ7IGkrKykgewogICAgICAgICAgICBsZXQgcmVzb2x1dGlvbiA9IGNoYW5uZWwuUmVzb2x1dGlvbltpXTsKICAgICAgICAgICAgbGV0IHF1YW50aXplZFNwZWN0cmEgPSBjaGFubmVsLlF1YW50aXplZFNwZWN0cmFbc3ViRnJhbWVdW2ldOwogICAgICAgICAgICBpZiAocmVzb2x1dGlvbiA9PSAwKQogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIGlmIChyZXNvbHV0aW9uIDwgOCkgewogICAgICAgICAgICAgICAgbGV0IGJpdHMgPSBIQ0FUYWJsZXMuUXVhbnRpemVTcGVjdHJ1bUJpdHNbcmVzb2x1dGlvbl1bcXVhbnRpemVkU3BlY3RyYSArIDhdOwogICAgICAgICAgICAgICAgd3JpdGVyLldyaXRlKEhDQVRhYmxlcy5RdWFudGl6ZVNwZWN0cnVtVmFsdWVbcmVzb2x1dGlvbl1bcXVhbnRpemVkU3BlY3RyYSArIDhdLCBiaXRzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmIChyZXNvbHV0aW9uIDwgMTYpIHsKICAgICAgICAgICAgICAgIGxldCBiaXRzID0gSENBVGFibGVzLlF1YW50aXplZFNwZWN0cnVtTWF4Qml0c1tyZXNvbHV0aW9uXSAtIDE7CiAgICAgICAgICAgICAgICB3cml0ZXIuV3JpdGUoTWF0aC5hYnMocXVhbnRpemVkU3BlY3RyYSksIGJpdHMpOwogICAgICAgICAgICAgICAgaWYgKHF1YW50aXplZFNwZWN0cmEgIT0gMCkgewogICAgICAgICAgICAgICAgICAgIHdyaXRlci5Xcml0ZShxdWFudGl6ZWRTcGVjdHJhID4gMCA/IDAgOiAxLCAxKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIHN0YXRpYyBXcml0ZVNjYWxlRmFjdG9ycyh3cml0ZXIsIGNoYW5uZWwpIHsKICAgICAgICBsZXQgZGVsdGFCaXRzID0gY2hhbm5lbC5TY2FsZUZhY3RvckRlbHRhQml0czsKICAgICAgICBsZXQgc2NhbGVzID0gY2hhbm5lbC5TY2FsZUZhY3RvcnM7CiAgICAgICAgd3JpdGVyLldyaXRlKGRlbHRhQml0cywgMyk7CiAgICAgICAgaWYgKGRlbHRhQml0cyA9PSAwKQogICAgICAgICAgICByZXR1cm47CiAgICAgICAgaWYgKGRlbHRhQml0cyA9PSA2KSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhbm5lbC5Db2RlZFNjYWxlRmFjdG9yQ291bnQ7IGkrKykgewogICAgICAgICAgICAgICAgd3JpdGVyLldyaXRlKHNjYWxlc1tpXSwgNik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICB3cml0ZXIuV3JpdGUoc2NhbGVzWzBdLCA2KTsKICAgICAgICBsZXQgbWF4RGVsdGEgPSAoMSA8PCAoZGVsdGFCaXRzIC0gMSkpIC0gMTsKICAgICAgICBsZXQgZXNjYXBlVmFsdWUgPSAoMSA8PCBkZWx0YUJpdHMpIC0gMTsKICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGNoYW5uZWwuQ29kZWRTY2FsZUZhY3RvckNvdW50OyBpKyspIHsKICAgICAgICAgICAgbGV0IGRlbHRhID0gc2NhbGVzW2ldIC0gc2NhbGVzW2kgLSAxXTsKICAgICAgICAgICAgaWYgKE1hdGguYWJzKGRlbHRhKSA+IG1heERlbHRhKSB7CiAgICAgICAgICAgICAgICB3cml0ZXIuV3JpdGUoZXNjYXBlVmFsdWUsIGRlbHRhQml0cyk7CiAgICAgICAgICAgICAgICB3cml0ZXIuV3JpdGUoc2NhbGVzW2ldLCA2KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHdyaXRlci5Xcml0ZShtYXhEZWx0YSArIGRlbHRhLCBkZWx0YUJpdHMpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9CmNsYXNzIEhDQU1kY3QgewogICAgY29uc3RydWN0b3IobWRjdEJpdHMsIHdpbmRvdywgc2NhbGUgPSAxKSB7CiAgICAgICAgSENBTWRjdC5TZXRUYWJsZXMobWRjdEJpdHMpOwogICAgICAgIHRoaXMuTWRjdEJpdHMgPSBtZGN0Qml0czsKICAgICAgICB0aGlzLk1kY3RTaXplID0gMSA8PCBtZGN0Qml0czsKICAgICAgICB0aGlzLlNjYWxlID0gc2NhbGU7CiAgICAgICAgaWYgKHdpbmRvdy5sZW5ndGggPCB0aGlzLk1kY3RTaXplKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiV2luZG93IG11c3QgYmUgYXMgbG9uZyBhcyB0aGUgTURDVCBzaXplLiIpOwogICAgICAgIH0KICAgICAgICB0aGlzLl9tZGN0UHJldmlvdXMgPSBuZXcgRmxvYXQ2NEFycmF5KHRoaXMuTWRjdFNpemUpOwogICAgICAgIHRoaXMuX2ltZGN0UHJldmlvdXMgPSBuZXcgRmxvYXQ2NEFycmF5KHRoaXMuTWRjdFNpemUpOwogICAgICAgIHRoaXMuX3NjcmF0Y2hNZGN0ID0gbmV3IEZsb2F0NjRBcnJheSh0aGlzLk1kY3RTaXplKTsKICAgICAgICB0aGlzLl9zY3JhdGNoRGN0ID0gbmV3IEZsb2F0NjRBcnJheSh0aGlzLk1kY3RTaXplKTsKICAgICAgICB0aGlzLl9pbWRjdFdpbmRvdyA9IHdpbmRvdzsKICAgIH0KICAgIHN0YXRpYyBTZXRUYWJsZXMobWF4Qml0cykgewogICAgICAgIGlmIChtYXhCaXRzID4gdGhpcy5fdGFibGVCaXRzKSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSB0aGlzLl90YWJsZUJpdHMgKyAxOyBpIDw9IG1heEJpdHM7IGkrKykgewogICAgICAgICAgICAgICAgbGV0IG91dCA9IHRoaXMuR2VuZXJhdGVUcmlnVGFibGVzKGkpOwogICAgICAgICAgICAgICAgdGhpcy5TaW5UYWJsZXMucHVzaChvdXQuc2luKTsKICAgICAgICAgICAgICAgIHRoaXMuQ29zVGFibGVzLnB1c2gob3V0LmNvcyk7CiAgICAgICAgICAgICAgICB0aGlzLlNodWZmbGVUYWJsZXMucHVzaCh0aGlzLkdlbmVyYXRlU2h1ZmZsZVRhYmxlKGkpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLl90YWJsZUJpdHMgPSBtYXhCaXRzOwogICAgICAgIH0KICAgIH0KICAgIFJ1bk1kY3QoaW5wdXQsIG91dHB1dCkgewogICAgICAgIGlmIChpbnB1dC5sZW5ndGggPCB0aGlzLk1kY3RTaXplKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiSW5wdXQgbXVzdCBiZSBhcyBsb25nIGFzIHRoZSBNRENUIHNpemUuIik7CiAgICAgICAgfQogICAgICAgIGlmIChvdXRwdXQubGVuZ3RoIDwgdGhpcy5NZGN0U2l6ZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIk91dHB1dCBtdXN0IGJlIGFzIGxvbmcgYXMgdGhlIE1EQ1Qgc2l6ZS4iKTsKICAgICAgICB9CiAgICAgICAgbGV0IHNpemUgPSB0aGlzLk1kY3RTaXplOwogICAgICAgIGxldCBoYWxmID0gKHNpemUgPj4gMSk7CiAgICAgICAgbGV0IGRjdEluID0gdGhpcy5fc2NyYXRjaE1kY3Q7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoYWxmOyBpKyspIHsKICAgICAgICAgICAgbGV0IGEgPSB0aGlzLl9pbWRjdFdpbmRvd1toYWxmIC0gaSAtIDFdICogLWlucHV0W2hhbGYgKyBpXTsKICAgICAgICAgICAgbGV0IGIgPSB0aGlzLl9pbWRjdFdpbmRvd1toYWxmICsgaV0gKiBpbnB1dFtoYWxmIC0gaSAtIDFdOwogICAgICAgICAgICBsZXQgYyA9IHRoaXMuX2ltZGN0V2luZG93W2ldICogdGhpcy5fbWRjdFByZXZpb3VzW2ldOwogICAgICAgICAgICBsZXQgZCA9IHRoaXMuX2ltZGN0V2luZG93W3NpemUgLSBpIC0gMV0gKiB0aGlzLl9tZGN0UHJldmlvdXNbc2l6ZSAtIGkgLSAxXTsKICAgICAgICAgICAgZGN0SW5baV0gPSBhIC0gYjsKICAgICAgICAgICAgZGN0SW5baGFsZiArIGldID0gYyAtIGQ7CiAgICAgICAgfQogICAgICAgIHRoaXMuRGN0NChkY3RJbiwgb3V0cHV0KTsKICAgICAgICB0aGlzLl9tZGN0UHJldmlvdXMuc2V0KGlucHV0LCBpbnB1dC5sZW5ndGgpOwogICAgfQogICAgUnVuSW1kY3QoaW5wdXQsIG91dHB1dCkgewogICAgICAgIGlmIChpbnB1dC5sZW5ndGggPCB0aGlzLk1kY3RTaXplKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiSW5wdXQgbXVzdCBiZSBhcyBsb25nIGFzIHRoZSBNRENUIHNpemUuIik7CiAgICAgICAgfQogICAgICAgIGlmIChvdXRwdXQubGVuZ3RoIDwgdGhpcy5NZGN0U2l6ZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIk91dHB1dCBtdXN0IGJlIGFzIGxvbmcgYXMgdGhlIE1EQ1Qgc2l6ZS4iKTsKICAgICAgICB9CiAgICAgICAgbGV0IHNpemUgPSB0aGlzLk1kY3RTaXplOwogICAgICAgIGxldCBoYWxmID0gKHNpemUgPj4gMSk7CiAgICAgICAgbGV0IGRjdE91dCA9IHRoaXMuX3NjcmF0Y2hNZGN0OwogICAgICAgIHRoaXMuRGN0NChpbnB1dCwgZGN0T3V0KTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGhhbGY7IGkrKykgewogICAgICAgICAgICBvdXRwdXRbaV0gPSB0aGlzLl9pbWRjdFdpbmRvd1tpXSAqIGRjdE91dFtpICsgaGFsZl0gKyB0aGlzLl9pbWRjdFByZXZpb3VzW2ldOwogICAgICAgICAgICBvdXRwdXRbaSArIGhhbGZdID0gdGhpcy5faW1kY3RXaW5kb3dbaSArIGhhbGZdICogLWRjdE91dFtzaXplIC0gMSAtIGldIC0gdGhpcy5faW1kY3RQcmV2aW91c1tpICsgaGFsZl07CiAgICAgICAgICAgIHRoaXMuX2ltZGN0UHJldmlvdXNbaV0gPSB0aGlzLl9pbWRjdFdpbmRvd1tzaXplIC0gMSAtIGldICogLWRjdE91dFtoYWxmIC0gaSAtIDFdOwogICAgICAgICAgICB0aGlzLl9pbWRjdFByZXZpb3VzW2kgKyBoYWxmXSA9IHRoaXMuX2ltZGN0V2luZG93W2hhbGYgLSBpIC0gMV0gKiBkY3RPdXRbaV07CiAgICAgICAgfQogICAgfQogICAgLy8vIDxzdW1tYXJ5PgogICAgLy8vIERvZXMgYSBUeXBlLTQgRENULgogICAgLy8vIDwvc3VtbWFyeT4KICAgIC8vLyA8cGFyYW0gbmFtZT0iaW5wdXQiPlRoZSBpbnB1dCBhcnJheSBjb250YWluaW5nIHRoZSB0aW1lIG9yIGZyZXF1ZW5jeS1kb21haW4gc2FtcGxlczwvcGFyYW0+CiAgICAvLy8gPHBhcmFtIG5hbWU9Im91dHB1dCI+VGhlIG91dHB1dCBhcnJheSB0aGF0IHdpbGwgY29udGFpbiB0aGUgdHJhbnNmb3JtZWQgdGltZSBvciBmcmVxdWVuY3ktZG9tYWluIHNhbXBsZXM8L3BhcmFtPgogICAgRGN0NChpbnB1dCwgb3V0cHV0KSB7CiAgICAgICAgbGV0IHNodWZmbGVUYWJsZSA9IEhDQU1kY3QuU2h1ZmZsZVRhYmxlc1t0aGlzLk1kY3RCaXRzXTsKICAgICAgICBsZXQgc2luVGFibGUgPSBIQ0FNZGN0LlNpblRhYmxlc1t0aGlzLk1kY3RCaXRzXTsKICAgICAgICBsZXQgY29zVGFibGUgPSBIQ0FNZGN0LkNvc1RhYmxlc1t0aGlzLk1kY3RCaXRzXTsKICAgICAgICBsZXQgZGN0VGVtcCA9IHRoaXMuX3NjcmF0Y2hEY3Q7CiAgICAgICAgbGV0IHNpemUgPSB0aGlzLk1kY3RTaXplOwogICAgICAgIGxldCBsYXN0SW5kZXggPSBzaXplIC0gMTsKICAgICAgICBsZXQgaGFsZlNpemUgPSAoc2l6ZSA+PiAxKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGhhbGZTaXplOyBpKyspIHsKICAgICAgICAgICAgbGV0IGkyID0gaSAqIDI7CiAgICAgICAgICAgIGxldCBhID0gaW5wdXRbaTJdOwogICAgICAgICAgICBsZXQgYiA9IGlucHV0W2xhc3RJbmRleCAtIGkyXTsKICAgICAgICAgICAgbGV0IHNpbiA9IHNpblRhYmxlW2ldOwogICAgICAgICAgICBsZXQgY29zID0gY29zVGFibGVbaV07CiAgICAgICAgICAgIGRjdFRlbXBbaTJdID0gYSAqIGNvcyArIGIgKiBzaW47CiAgICAgICAgICAgIGRjdFRlbXBbaTIgKyAxXSA9IGEgKiBzaW4gLSBiICogY29zOwogICAgICAgIH0KICAgICAgICBsZXQgc3RhZ2VDb3VudCA9IHRoaXMuTWRjdEJpdHMgLSAxOwogICAgICAgIGZvciAobGV0IHN0YWdlID0gMDsgc3RhZ2UgPCBzdGFnZUNvdW50OyBzdGFnZSsrKSB7CiAgICAgICAgICAgIGxldCBibG9ja0NvdW50ID0gMSA8PCBzdGFnZTsKICAgICAgICAgICAgbGV0IGJsb2NrU2l6ZUJpdHMgPSBzdGFnZUNvdW50IC0gc3RhZ2U7CiAgICAgICAgICAgIGxldCBibG9ja0hhbGZTaXplQml0cyA9IGJsb2NrU2l6ZUJpdHMgLSAxOwogICAgICAgICAgICBsZXQgYmxvY2tTaXplID0gMSA8PCBibG9ja1NpemVCaXRzOwogICAgICAgICAgICBsZXQgYmxvY2tIYWxmU2l6ZSA9IDEgPDwgYmxvY2tIYWxmU2l6ZUJpdHM7CiAgICAgICAgICAgIHNpblRhYmxlID0gSENBTWRjdC5TaW5UYWJsZXNbYmxvY2tIYWxmU2l6ZUJpdHNdOwogICAgICAgICAgICBjb3NUYWJsZSA9IEhDQU1kY3QuQ29zVGFibGVzW2Jsb2NrSGFsZlNpemVCaXRzXTsKICAgICAgICAgICAgZm9yIChsZXQgYmxvY2sgPSAwOyBibG9jayA8IGJsb2NrQ291bnQ7IGJsb2NrKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYmxvY2tIYWxmU2l6ZTsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IGZyb250UG9zID0gKGJsb2NrICogYmxvY2tTaXplICsgaSkgKiAyOwogICAgICAgICAgICAgICAgICAgIGxldCBiYWNrUG9zID0gZnJvbnRQb3MgKyBibG9ja1NpemU7CiAgICAgICAgICAgICAgICAgICAgbGV0IGEgPSBkY3RUZW1wW2Zyb250UG9zXSAtIGRjdFRlbXBbYmFja1Bvc107CiAgICAgICAgICAgICAgICAgICAgbGV0IGIgPSBkY3RUZW1wW2Zyb250UG9zICsgMV0gLSBkY3RUZW1wW2JhY2tQb3MgKyAxXTsKICAgICAgICAgICAgICAgICAgICBsZXQgc2luID0gc2luVGFibGVbaV07CiAgICAgICAgICAgICAgICAgICAgbGV0IGNvcyA9IGNvc1RhYmxlW2ldOwogICAgICAgICAgICAgICAgICAgIGRjdFRlbXBbZnJvbnRQb3NdICs9IGRjdFRlbXBbYmFja1Bvc107CiAgICAgICAgICAgICAgICAgICAgZGN0VGVtcFtmcm9udFBvcyArIDFdICs9IGRjdFRlbXBbYmFja1BvcyArIDFdOwogICAgICAgICAgICAgICAgICAgIGRjdFRlbXBbYmFja1Bvc10gPSBhICogY29zICsgYiAqIHNpbjsKICAgICAgICAgICAgICAgICAgICBkY3RUZW1wW2JhY2tQb3MgKyAxXSA9IGEgKiBzaW4gLSBiICogY29zOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5NZGN0U2l6ZTsgaSsrKSB7CiAgICAgICAgICAgIG91dHB1dFtpXSA9IGRjdFRlbXBbc2h1ZmZsZVRhYmxlW2ldXSAqIHRoaXMuU2NhbGU7CiAgICAgICAgfQogICAgfQogICAgc3RhdGljIEdlbmVyYXRlVHJpZ1RhYmxlcyhzaXplQml0cykgewogICAgICAgIGxldCBzaXplID0gMSA8PCBzaXplQml0czsKICAgICAgICBsZXQgb3V0ID0gewogICAgICAgICAgICBzaW46IG5ldyBGbG9hdDY0QXJyYXkoc2l6ZSksCiAgICAgICAgICAgIGNvczogbmV3IEZsb2F0NjRBcnJheShzaXplKQogICAgICAgIH07CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKICAgICAgICAgICAgbGV0IHZhbHVlID0gTWF0aC5QSSAqICg0ICogaSArIDEpIC8gKDQgKiBzaXplKTsKICAgICAgICAgICAgb3V0LnNpbltpXSA9IE1hdGguc2luKHZhbHVlKTsKICAgICAgICAgICAgb3V0LmNvc1tpXSA9IE1hdGguY29zKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG91dDsKICAgIH0KICAgIHN0YXRpYyBHZW5lcmF0ZVNodWZmbGVUYWJsZShzaXplQml0cykgewogICAgICAgIGxldCBzaXplID0gMSA8PCBzaXplQml0czsKICAgICAgICB2YXIgdGFibGUgPSBuZXcgSW50MzJBcnJheShzaXplKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykgewogICAgICAgICAgICB0YWJsZVtpXSA9IEhDQVV0aWxGdW5jLlNpZ25lZEJpdFJldmVyc2UzMlRydW5jKGkgXiAoaSA+PiAxKSwgc2l6ZUJpdHMpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGFibGU7CiAgICB9CiAgICAvLyBSZVNoYXJwZXIgZGlzYWJsZSBvbmNlIFVudXNlZE1lbWJlci5Mb2NhbAogICAgLy8vIDxzdW1tYXJ5PgogICAgLy8vIERvZXMgYSBUeXBlLTQgRENULiBJbnRlbmRlZCBmb3IgcmVmZXJlbmNlLgogICAgLy8vIDwvc3VtbWFyeT4KICAgIC8vLyA8cGFyYW0gbmFtZT0iaW5wdXQiPlRoZSBpbnB1dCBhcnJheSBjb250YWluaW5nIHRoZSB0aW1lIG9yIGZyZXF1ZW5jeS1kb21haW4gc2FtcGxlczwvcGFyYW0+CiAgICAvLy8gPHBhcmFtIG5hbWU9Im91dHB1dCI+VGhlIG91dHB1dCBhcnJheSB0aGF0IHdpbGwgY29udGFpbiB0aGUgdHJhbnNmb3JtZWQgdGltZSBvciBmcmVxdWVuY3ktZG9tYWluIHNhbXBsZXM8L3BhcmFtPgogICAgRGN0NFNsb3coaW5wdXQsIG91dHB1dCkgewogICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgdGhpcy5NZGN0U2l6ZTsgaysrKSB7CiAgICAgICAgICAgIGxldCBzYW1wbGUgPSAwOwogICAgICAgICAgICBmb3IgKGxldCBuID0gMDsgbiA8IHRoaXMuTWRjdFNpemU7IG4rKykgewogICAgICAgICAgICAgICAgbGV0IGFuZ2xlID0gTWF0aC5QSSAvIHRoaXMuTWRjdFNpemUgKiAoayArIDAuNSkgKiAobiArIDAuNSk7CiAgICAgICAgICAgICAgICBzYW1wbGUgKz0gTWF0aC5jb3MoYW5nbGUpICogaW5wdXRbbl07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb3V0cHV0W2tdID0gc2FtcGxlICogdGhpcy5TY2FsZTsKICAgICAgICB9CiAgICB9Cn0KSENBTWRjdC5fdGFibGVCaXRzID0gLTE7CkhDQU1kY3QuU2luVGFibGVzID0gW107CkhDQU1kY3QuQ29zVGFibGVzID0gW107CkhDQU1kY3QuU2h1ZmZsZVRhYmxlcyA9IFtdOwpjbGFzcyBIQ0FUYWJsZXMgewogICAgc3RhdGljIGlzTGl0dGxlRW5kaWFuKCkgewogICAgICAgIGxldCB0ZXN0ID0gbmV3IEZsb2F0NjRBcnJheShbMS4wXSk7CiAgICAgICAgbGV0IGR2ID0gbmV3IERhdGFWaWV3KHRlc3QuYnVmZmVyKTsKICAgICAgICBpZiAoZHYuZ2V0VWludDMyKDApICE9IDApCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHN0YXRpYyBhZGFwdEVuZGlhbm5lc3M2NDMyKGEpIHsKICAgICAgICBpZiAoYS5ieXRlTGVuZ3RoICUgOCAhPSAwKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICBpZiAoIXRoaXMuaXNMaXR0bGVFbmRpYW4oKSkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGEubGVuZ3RoOyBpICs9IDIpIHsKICAgICAgICAgICAgICAgIGxldCB0ZW1wID0gYVtpXTsKICAgICAgICAgICAgICAgIGFbaV0gPSBhW2kgKyAxXTsKICAgICAgICAgICAgICAgIGFbaSArIDFdID0gdGVtcDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gYTsKICAgIH0KfQpfYiA9IEhDQVRhYmxlczsKSENBVGFibGVzLlF1YW50aXplU3BlY3RydW1CaXRzID0gWwogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDIsIDB4MDEsIDB4MDIsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDMsIDB4MDIsIDB4MDIsIDB4MDIsIDB4MDMsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDIsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDQsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDQsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDMsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQKICAgIF0pLApdOwpIQ0FUYWJsZXMuUXVhbnRpemVTcGVjdHJ1bVZhbHVlID0gWwogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDMsIDB4MDAsIDB4MDIsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDcsIDB4MDIsIDB4MDAsIDB4MDEsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDcsIDB4MDUsIDB4MDMsIDB4MDAsIDB4MDIsIDB4MDQsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MEYsIDB4MDYsIDB4MDQsIDB4MDIsIDB4MDAsIDB4MDEsIDB4MDMsIDB4MDUsIDB4MEUsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MEYsIDB4MEQsIDB4MEIsIDB4MDQsIDB4MDIsIDB4MDAsIDB4MDEsIDB4MDMsIDB4MEEsIDB4MEMsIDB4MEUsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MEYsIDB4MEQsIDB4MEIsIDB4MDksIDB4MDcsIDB4MDIsIDB4MDAsIDB4MDEsIDB4MDYsIDB4MDgsIDB4MEEsIDB4MEMsIDB4MEUsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MEYsIDB4MEQsIDB4MEIsIDB4MDksIDB4MDcsIDB4MDUsIDB4MDMsIDB4MDAsIDB4MDIsIDB4MDQsIDB4MDYsIDB4MDgsIDB4MEEsIDB4MEMsIDB4MEUKICAgIF0pLApdOwpIQ0FUYWJsZXMuUXVhbnRpemVkU3BlY3RydW1CaXRzID0gWwogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDEsIDB4MDEsIDB4MDIsIDB4MDIsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDIsIDB4MDIsIDB4MDIsIDB4MDIsIDB4MDIsIDB4MDIsIDB4MDMsIDB4MDMsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDIsIDB4MDIsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDQsIDB4MDQKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDMsIDB4MDMsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDQKICAgIF0pLApdOwpIQ0FUYWJsZXMuUXVhbnRpemVkU3BlY3RydW1NYXhCaXRzID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgMHgwMCwgMHgwMiwgMHgwMywgMHgwMywgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNCwgMHgwNSwgMHgwNiwgMHgwNywgMHgwOCwgMHgwOSwgMHgwQSwgMHgwQiwgMHgwQwpdKTsKSENBVGFibGVzLlF1YW50aXplZFNwZWN0cnVtVmFsdWUgPSBbCiAgICBuZXcgSW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwCiAgICBdKSwKICAgIG5ldyBJbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDEsIDB4RkYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IEludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMSwgMHgwMSwgMHhGRiwgMHhGRiwgMHgwMiwgMHhGRSwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMAogICAgXSksCiAgICBuZXcgSW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAwLCAweDAxLCAweEZGLCAweDAyLCAweEZFLCAweDAzLCAweEZELCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwCiAgICBdKSwKICAgIG5ldyBJbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDEsIDB4MDEsIDB4RkYsIDB4RkYsIDB4MDIsIDB4MDIsIDB4RkUsIDB4RkUsIDB4MDMsIDB4MDMsIDB4RkQsIDB4RkQsIDB4MDQsIDB4RkMKICAgIF0pLAogICAgbmV3IEludDhBcnJheShbCiAgICAgICAgMHgwMCwgMHgwMCwgMHgwMSwgMHgwMSwgMHhGRiwgMHhGRiwgMHgwMiwgMHgwMiwgMHhGRSwgMHhGRSwgMHgwMywgMHhGRCwgMHgwNCwgMHhGQywgMHgwNSwgMHhGQgogICAgXSksCiAgICBuZXcgSW50OEFycmF5KFsKICAgICAgICAweDAwLCAweDAwLCAweDAxLCAweDAxLCAweEZGLCAweEZGLCAweDAyLCAweEZFLCAweDAzLCAweEZELCAweDA0LCAweEZDLCAweDA1LCAweEZCLCAweDA2LCAweEZBCiAgICBdKSwKICAgIG5ldyBJbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDEsIDB4RkYsIDB4MDIsIDB4RkUsIDB4MDMsIDB4RkQsIDB4MDQsIDB4RkMsIDB4MDUsIDB4RkIsIDB4MDYsIDB4RkEsIDB4MDcsIDB4RjkKICAgIF0pLApdOwpIQ0FUYWJsZXMuU2NhbGVUb1Jlc29sdXRpb25DdXJ2ZSA9IG5ldyBVaW50OEFycmF5KFsKICAgIDB4MEYsIDB4MEUsIDB4MEUsIDB4MEUsIDB4MEUsIDB4MEUsIDB4MEUsIDB4MEQsIDB4MEQsIDB4MEQsIDB4MEQsIDB4MEQsIDB4MEQsIDB4MEMsIDB4MEMsIDB4MEMsCiAgICAweDBDLCAweDBDLCAweDBDLCAweDBCLCAweDBCLCAweDBCLCAweDBCLCAweDBCLCAweDBCLCAweDBBLCAweDBBLCAweDBBLCAweDBBLCAweDBBLCAweDBBLCAweDBBLAogICAgMHgwOSwgMHgwOSwgMHgwOSwgMHgwOSwgMHgwOSwgMHgwOSwgMHgwOCwgMHgwOCwgMHgwOCwgMHgwOCwgMHgwOCwgMHgwOCwgMHgwNywgMHgwNiwgMHgwNiwgMHgwNSwKICAgIDB4MDQsIDB4MDQsIDB4MDQsIDB4MDMsIDB4MDMsIDB4MDMsIDB4MDIsIDB4MDIsIDB4MDIsIDB4MDIsIDB4MDEsIDB4MDEsIDB4MDEsIDB4MDEsIDB4MDEsIDB4MDEsCiAgICAweDAxLCAweDAxLCAweDAxLCAweDAwCl0pOwpIQ0FUYWJsZXMuQXRoQ3VydmUgPSBuZXcgVWludDhBcnJheShbCiAgICAweDc4LCAweDVGLCAweDU2LCAweDUxLCAweDRFLCAweDRDLCAweDRCLCAweDQ5LCAweDQ4LCAweDQ4LCAweDQ3LCAweDQ2LCAweDQ2LCAweDQ1LCAweDQ1LCAweDQ1LAogICAgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NCwgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MywgMHg0MiwgMHg0MiwgMHg0MiwgMHg0MiwgMHg0MiwgMHg0MiwKICAgIDB4NDIsIDB4NDIsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsCiAgICAweDQwLCAweDQwLCAweDQwLCAweDQwLCAweDQwLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLAogICAgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRSwgMHgzRSwgMHgzRSwgMHgzRSwgMHgzRSwgMHgzRSwgMHgzRCwgMHgzRCwgMHgzRCwgMHgzRCwgMHgzRCwgMHgzRCwgMHgzRCwKICAgIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0MsIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0IsIDB4M0IsCiAgICAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLCAweDNCLAogICAgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQiwgMHgzQywgMHgzQywgMHgzQywgMHgzQywgMHgzQywgMHgzQywgMHgzQywgMHgzQywKICAgIDB4M0QsIDB4M0QsIDB4M0QsIDB4M0QsIDB4M0QsIDB4M0QsIDB4M0QsIDB4M0QsIDB4M0UsIDB4M0UsIDB4M0UsIDB4M0UsIDB4M0UsIDB4M0UsIDB4M0UsIDB4M0YsCiAgICAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLCAweDNGLAogICAgMHgzRiwgMHgzRiwgMHgzRiwgMHgzRiwgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwgMHg0MCwKICAgIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDAsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsIDB4NDEsCiAgICAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLCAweDQxLAogICAgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MSwgMHg0MiwgMHg0MiwgMHg0MiwgMHg0MiwgMHg0MiwgMHg0MiwgMHg0MiwgMHg0MiwgMHg0MiwKICAgIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDIsIDB4NDMsIDB4NDMsIDB4NDMsCiAgICAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQzLCAweDQ0LCAweDQ0LAogICAgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NCwgMHg0NSwgMHg0NSwgMHg0NSwgMHg0NSwKICAgIDB4NDUsIDB4NDUsIDB4NDUsIDB4NDUsIDB4NDUsIDB4NDUsIDB4NDUsIDB4NDUsIDB4NDYsIDB4NDYsIDB4NDYsIDB4NDYsIDB4NDYsIDB4NDYsIDB4NDYsIDB4NDYsCiAgICAweDQ2LCAweDQ2LCAweDQ3LCAweDQ3LCAweDQ3LCAweDQ3LCAweDQ3LCAweDQ3LCAweDQ3LCAweDQ3LCAweDQ3LCAweDQ3LCAweDQ4LCAweDQ4LCAweDQ4LCAweDQ4LAogICAgMHg0OCwgMHg0OCwgMHg0OCwgMHg0OCwgMHg0OSwgMHg0OSwgMHg0OSwgMHg0OSwgMHg0OSwgMHg0OSwgMHg0OSwgMHg0OSwgMHg0QSwgMHg0QSwgMHg0QSwgMHg0QSwKICAgIDB4NEEsIDB4NEEsIDB4NEEsIDB4NEEsIDB4NEIsIDB4NEIsIDB4NEIsIDB4NEIsIDB4NEIsIDB4NEIsIDB4NEIsIDB4NEMsIDB4NEMsIDB4NEMsIDB4NEMsIDB4NEMsCiAgICAweDRDLCAweDRELCAweDRELCAweDRELCAweDRELCAweDRELCAweDRELCAweDRFLCAweDRFLCAweDRFLCAweDRFLCAweDRFLCAweDRFLCAweDRGLCAweDRGLCAweDRGLAogICAgMHg0RiwgMHg0RiwgMHg0RiwgMHg1MCwgMHg1MCwgMHg1MCwgMHg1MCwgMHg1MCwgMHg1MSwgMHg1MSwgMHg1MSwgMHg1MSwgMHg1MSwgMHg1MiwgMHg1MiwgMHg1MiwKICAgIDB4NTIsIDB4NTIsIDB4NTMsIDB4NTMsIDB4NTMsIDB4NTMsIDB4NTQsIDB4NTQsIDB4NTQsIDB4NTQsIDB4NTQsIDB4NTUsIDB4NTUsIDB4NTUsIDB4NTUsIDB4NTYsCiAgICAweDU2LCAweDU2LCAweDU2LCAweDU3LCAweDU3LCAweDU3LCAweDU3LCAweDU3LCAweDU4LCAweDU4LCAweDU4LCAweDU5LCAweDU5LCAweDU5LCAweDU5LCAweDVBLAogICAgMHg1QSwgMHg1QSwgMHg1QSwgMHg1QiwgMHg1QiwgMHg1QiwgMHg1QiwgMHg1QywgMHg1QywgMHg1QywgMHg1RCwgMHg1RCwgMHg1RCwgMHg1RCwgMHg1RSwgMHg1RSwKICAgIDB4NUUsIDB4NUYsIDB4NUYsIDB4NUYsIDB4NjAsIDB4NjAsIDB4NjAsIDB4NjEsIDB4NjEsIDB4NjEsIDB4NjEsIDB4NjIsIDB4NjIsIDB4NjIsIDB4NjMsIDB4NjMsCiAgICAweDYzLCAweDY0LCAweDY0LCAweDY0LCAweDY1LCAweDY1LCAweDY2LCAweDY2LCAweDY2LCAweDY3LCAweDY3LCAweDY3LCAweDY4LCAweDY4LCAweDY4LCAweDY5LAogICAgMHg2OSwgMHg2QSwgMHg2QSwgMHg2QSwgMHg2QiwgMHg2QiwgMHg2QiwgMHg2QywgMHg2QywgMHg2RCwgMHg2RCwgMHg2RCwgMHg2RSwgMHg2RSwgMHg2RiwgMHg2RiwKICAgIDB4NzAsIDB4NzAsIDB4NzAsIDB4NzEsIDB4NzEsIDB4NzIsIDB4NzIsIDB4NzMsIDB4NzMsIDB4NzMsIDB4NzQsIDB4NzQsIDB4NzUsIDB4NzUsIDB4NzYsIDB4NzYsCiAgICAweDc3LCAweDc3LCAweDc4LCAweDc4LCAweDc4LCAweDc5LCAweDc5LCAweDdBLCAweDdBLCAweDdCLCAweDdCLCAweDdDLCAweDdDLCAweDdELCAweDdELCAweDdFLAogICAgMHg3RSwgMHg3RiwgMHg3RiwgMHg4MCwgMHg4MCwgMHg4MSwgMHg4MSwgMHg4MiwgMHg4MywgMHg4MywgMHg4NCwgMHg4NCwgMHg4NSwgMHg4NSwgMHg4NiwgMHg4NiwKICAgIDB4ODcsIDB4ODgsIDB4ODgsIDB4ODksIDB4ODksIDB4OEEsIDB4OEEsIDB4OEIsIDB4OEMsIDB4OEMsIDB4OEQsIDB4OEQsIDB4OEUsIDB4OEYsIDB4OEYsIDB4OTAsCiAgICAweDkwLCAweDkxLCAweDkyLCAweDkyLCAweDkzLCAweDk0LCAweDk0LCAweDk1LCAweDk1LCAweDk2LCAweDk3LCAweDk3LCAweDk4LCAweDk5LCAweDk5LCAweDlBLAogICAgMHg5QiwgMHg5QiwgMHg5QywgMHg5RCwgMHg5RCwgMHg5RSwgMHg5RiwgMHhBMCwgMHhBMCwgMHhBMSwgMHhBMiwgMHhBMiwgMHhBMywgMHhBNCwgMHhBNSwgMHhBNSwKICAgIDB4QTYsIDB4QTcsIDB4QTcsIDB4QTgsIDB4QTksIDB4QUEsIDB4QUEsIDB4QUIsIDB4QUMsIDB4QUQsIDB4QUUsIDB4QUUsIDB4QUYsIDB4QjAsIDB4QjEsIDB4QjEsCiAgICAweEIyLCAweEIzLCAweEI0LCAweEI1LCAweEI2LCAweEI2LCAweEI3LCAweEI4LCAweEI5LCAweEJBLCAweEJBLCAweEJCLCAweEJDLCAweEJELCAweEJFLCAweEJGLAogICAgMHhDMCwgMHhDMSwgMHhDMSwgMHhDMiwgMHhDMywgMHhDNCwgMHhDNSwgMHhDNiwgMHhDNywgMHhDOCwgMHhDOSwgMHhDOSwgMHhDQSwgMHhDQiwgMHhDQywgMHhDRCwKICAgIDB4Q0UsIDB4Q0YsIDB4RDAsIDB4RDEsIDB4RDIsIDB4RDMsIDB4RDQsIDB4RDUsIDB4RDYsIDB4RDcsIDB4RDgsIDB4RDksIDB4REEsIDB4REIsIDB4REMsIDB4REQsCiAgICAweERFLCAweERGLCAweEUwLCAweEUxLCAweEUyLCAweEUzLCAweEU0LCAweEU1LCAweEU2LCAweEU3LCAweEU4LCAweEU5LCAweEVBLCAweEVCLCAweEVELCAweEVFLAogICAgMHhFRiwgMHhGMCwgMHhGMSwgMHhGMiwgMHhGMywgMHhGNCwgMHhGNSwgMHhGNywgMHhGOCwgMHhGOSwgMHhGQSwgMHhGQiwgMHhGQywgMHhGRApdKTsKSENBVGFibGVzLk1kY3RXaW5kb3cgPSBuZXcgRmxvYXQ2NEFycmF5KF9iLmFkYXB0RW5kaWFubmVzczY0MzIobmV3IFVpbnQzMkFycmF5KFsKICAgIDB4MDAwMDAwMDAsIDB4M0Y0NkEwOUUsIDB4MDAwMDAwMDAsIDB4M0Y2MDMwNzcsIDB4MDAwMDAwMDAsIDB4M0Y2RTE4QTcsIDB4MDAwMDAwMDAsIDB4M0Y3NzcyNEQsCiAgICAweDIwMDAwMDAwLCAweDNGODA5NTAxLCAweDAwMDAwMDAwLCAweDNGODYxMDQwLCAweDgwMDAwMDAwLCAweDNGOEMyNTA5LCAweEUwMDAwMDAwLCAweDNGOTE2N0UyLAogICAgMHg0MDAwMDAwMCwgMHgzRjk1MDczMiwgMHhBMDAwMDAwMCwgMHgzRjk4RUZGNywgMHgwMDAwMDAwMCwgMHgzRjlEMjIyMiwgMHhBMDAwMDAwMCwgMHgzRkEwQ0VGOSwKICAgIDB4ODAwMDAwMDAsIDB4M0ZBMzMxRjgsIDB4ODAwMDAwMDAsIDB4M0ZBNUJBNkIsIDB4NjAwMDAwMDAsIDB4M0ZBODY4QzgsIDB4MjAwMDAwMDAsIDB4M0ZBQjNEOTgsCiAgICAweDAwMDAwMDAwLCAweDNGQUUzOTc1LCAweEMwMDAwMDAwLCAweDNGQjBBRTgzLCAweDYwMDAwMDAwLCAweDNGQjI1NDgyLCAweDgwMDAwMDAwLCAweDNGQjQwRjE2LAogICAgMHg0MDAwMDAwMCwgMHgzRkI1REVBNCwgMHhDMDAwMDAwMCwgMHgzRkI3QzM5MywgMHg2MDAwMDAwMCwgMHgzRkI5QkU0RiwgMHhBMDAwMDAwMCwgMHgzRkJCQ0Y0MywKICAgIDB4QTAwMDAwMDAsIDB4M0ZCREY2REQsIDB4NjAwMDAwMDAsIDB4M0ZDMDFBQzUsIDB4NDAwMDAwMDAsIDB4M0ZDMTQ1REIsIDB4NDAwMDAwMDAsIDB4M0ZDMjdDRTUsCiAgICAweDIwMDAwMDAwLCAweDNGQzNDMDE2LCAweDQwMDAwMDAwLCAweDNGQzUwRjlFLCAweEEwMDAwMDAwLCAweDNGQzY2QkFBLCAweDIwMDAwMDAwLCAweDNGQzdENDY0LAogICAgMHhBMDAwMDAwMCwgMHgzRkM5NDlFRSwgMHhFMDAwMDAwMCwgMHgzRkNBQ0M2NywgMHhFMDAwMDAwMCwgMHgzRkNDNUJFNiwgMHgyMDAwMDAwMCwgMHgzRkNERjg3QSwKICAgIDB4MDAwMDAwMDAsIDB4M0ZDRkEyMjcsIDB4NDAwMDAwMDAsIDB4M0ZEMEFDNzQsIDB4RTAwMDAwMDAsIDB4M0ZEMThFNTYsIDB4MjAwMDAwMDAsIDB4M0ZEMjc2QUMsCiAgICAweEUwMDAwMDAwLCAweDNGRDM2NTVELCAweEUwMDAwMDAwLCAweDNGRDQ1QTRELCAweDYwMDAwMDAwLCAweDNGRDU1NTU1LCAweDQwMDAwMDAwLCAweDNGRDY1NjQ0LAogICAgMHhDMDAwMDAwMCwgMHgzRkQ3NUNFMCwgMHhFMDAwMDAwMCwgMHgzRkQ4NjhFNiwgMHhBMDAwMDAwMCwgMHgzRkQ5N0EwNywgMHhDMDAwMDAwMCwgMHgzRkRBOEZFOCwKICAgIDB4MDAwMDAwMDAsIDB4M0ZEQkFBMjUsIDB4ODAwMDAwMDAsIDB4M0ZEQ0M4NEIsIDB4RTAwMDAwMDAsIDB4M0ZEREU5REYsIDB4RTAwMDAwMDAsIDB4M0ZERjBFNUEsCiAgICAweDIwMDAwMDAwLCAweDNGRTAxQTk1LCAweDQwMDAwMDAwLCAweDNGRTBBRUQ5LCAweDYwMDAwMDAwLCAweDNGRTE0M0E3LCAweDAwMDAwMDAwLCAweDNGRTFEOEE5LAogICAgMHhBMDAwMDAwMCwgMHgzRkUyNkQ4NCwgMHg0MDAwMDAwMCwgMHgzRkUzMDFERSwgMHg0MDAwMDAwMCwgMHgzRkUzOTU1OCwgMHg0MDAwMDAwMCwgMHgzRkU0Mjc5NCwKICAgIDB4QTAwMDAwMDAsIDB4M0ZFNEI4MzQsIDB4RTAwMDAwMDAsIDB4M0ZFNTQ2REMsIDB4MDAwMDAwMDAsIDB4M0ZFNUQzMzMsIDB4QTAwMDAwMDAsIDB4M0ZFNjVDRTAsCiAgICAweEMwMDAwMDAwLCAweDNGRTZFMzkzLCAweEMwMDAwMDAwLCAweDNGRTc2NkZGLCAweDQwMDAwMDAwLCAweDNGRTdFNkRFLCAweDAwMDAwMDAwLCAweDNGRTg2MkYwLAogICAgMHhDMDAwMDAwMCwgMHgzRkU4REFGQywgMHg4MDAwMDAwMCwgMHgzRkU5NEVENCwgMHg4MDAwMDAwMCwgMHgzRkU5QkU0RiwgMHhFMDAwMDAwMCwgMHgzRkVBMjk0RCwKICAgIDB4QTAwMDAwMDAsIDB4M0ZFQThGQjgsIDB4NjAwMDAwMDAsIDB4M0ZFQUYxODAsIDB4QzAwMDAwMDAsIDB4M0ZFQjRFOUQsIDB4RTAwMDAwMDAsIDB4M0ZFQkE3MTAsCiAgICAweEUwMDAwMDAwLCAweDNGRUJGQUUwLCAweDQwMDAwMDAwLCAweDNGRUM0QTFCLCAweDIwMDAwMDAwLCAweDNGRUM5NEQzLCAweDAwMDAwMDAwLCAweDNGRUNEQjIxLAogICAgMHhDMDAwMDAwMCwgMHgzRkVEMUQyMSwgMHgyMDAwMDAwMCwgMHgzRkVENUFGNiwgMHgyMDAwMDAwMCwgMHgzRkVEOTRDMiwgMHg0MDAwMDAwMCwgMHgzRkVEQ0FBQywKICAgIDB4RTAwMDAwMDAsIDB4M0ZFREZDREMsIDB4RTAwMDAwMDAsIDB4M0ZFRTJCN0QsIDB4MjAwMDAwMDAsIDB4M0ZFRTU2QkEsIDB4QzAwMDAwMDAsIDB4M0ZFRTdFQkMsCiAgICAweDIwMDAwMDAwLCAweDNGRUVBM0IxLCAweDYwMDAwMDAwLCAweDNGRUVDNUMyLCAweEUwMDAwMDAwLCAweDNGRUVFNTFBLCAweDAwMDAwMDAwLCAweDNGRUYwMUU0LAogICAgMHg4MDAwMDAwMCwgMHgzRkVGMUM0NiwgMHg4MDAwMDAwMCwgMHgzRkVGMzQ2OSwgMHhFMDAwMDAwMCwgMHgzRkVGNEE3MiwgMHgyMDAwMDAwMCwgMHgzRkVGNUU4NywKICAgIDB4MDAwMDAwMDAsIDB4M0ZFRjcwQzksIDB4QzAwMDAwMDAsIDB4M0ZFRjgxNTksIDB4MDAwMDAwMDAsIDB4M0ZFRjkwNTksIDB4QzAwMDAwMDAsIDB4M0ZFRjlERTQsCiAgICAweDYwMDAwMDAwLCAweDNGRUZBQTE5LCAweEMwMDAwMDAwLCAweDNGRUZCNTExLCAweEUwMDAwMDAwLCAweDNGRUZCRUU2LCAweEMwMDAwMDAwLCAweDNGRUZDN0IwLAogICAgMHg0MDAwMDAwMCwgMHgzRkVGQ0Y4NSwgMHg4MDAwMDAwMCwgMHgzRkVGRDY3OSwgMHhFMDAwMDAwMCwgMHgzRkVGRENBMCwgMHg4MDAwMDAwMCwgMHgzRkVGRTIwRCwKICAgIDB4NjAwMDAwMDAsIDB4M0ZFRkU2RDAsIDB4NDAwMDAwMDAsIDB4M0ZFRkVBRjksIDB4QzAwMDAwMDAsIDB4M0ZFRkVFOTYsIDB4QzAwMDAwMDAsIDB4M0ZFRkYxQjYsCiAgICAweEMwMDAwMDAwLCAweDNGRUZGNDY1LCAweDYwMDAwMDAwLCAweDNGRUZGNkFGLCAweEMwMDAwMDAwLCAweDNGRUZGODlFLCAweEEwMDAwMDAwLCAweDNGRUZGQTNELAogICAgMHhBMDAwMDAwMCwgMHgzRkVGRkI5NSwgMHgyMDAwMDAwMCwgMHgzRkVGRkNBRiwgMHgwMDAwMDAwMCwgMHgzRkVGRkQ5MiwgMHhDMDAwMDAwMCwgMHgzRkVGRkU0NSwKICAgIDB4MDAwMDAwMDAsIDB4M0ZFRkZFRDEsIDB4MDAwMDAwMDAsIDB4M0ZFRkZGM0EsIDB4NDAwMDAwMDAsIDB4M0ZFRkZGODYsIDB4NDAwMDAwMDAsIDB4M0ZFRkZGQkIsCiAgICAweEEwMDAwMDAwLCAweDNGRUZGRkRELCAweEUwMDAwMDAwLCAweDNGRUZGRkYxLCAweEUwMDAwMDAwLCAweDNGRUZGRkZCLCAweDgwMDAwMDAwLCAweDNGRUZGRkZGCl0pKS5idWZmZXIpOwpIQ0FUYWJsZXMuRGVmYXVsdENoYW5uZWxNYXBwaW5nID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgMHgwMCwgMHgwMSwgMHgwMCwgMHgwNCwgMHgwMCwgMHgwMSwgMHgwMywgMHgwNywgMHgwMwpdKTsKSENBVGFibGVzLlZhbGlkQ2hhbm5lbE1hcHBpbmdzID0gWwogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDEsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDEsIDB4MDEsIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDEsIDB4MDAsIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDEsIDB4MDEsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEKICAgIF0pLAogICAgbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAKICAgIF0pLApdOwpIQ0FUYWJsZXMuRGVxdWFudGl6ZXJTY2FsaW5nVGFibGUgPSBuZXcgRmxvYXQ2NEFycmF5KF9iLmFkYXB0RW5kaWFubmVzczY0MzIobmV3IFVpbnQzMkFycmF5KFsKICAgIDB4Q0E1RDkyMDEsIDB4M0U4NTUxQTQsIDB4MkU1N0QxMzksIDB4M0U4QzY3RjEsIDB4QTkzRTJGNEEsIDB4M0U5MkVDQUYsIDB4QjBDREM1RDUsIDB4M0U5OTM3MzcsCiAgICAweDJCNzI0N0VELCAweDNFQTBDQzkyLCAweDgyNTUyMjE3LCAweDNFQTY2MjM4LCAweEYzMDFCNDRGLCAweDNFQUREMzIxLCAweDRDMTIzNDE2LCAweDNFQjNERUE2LAogICAgMHgxMzMwQjM0OSwgMHgzRUJBNzk5RSwgMHhFQjZGQ0I2QywgMHgzRUMxQTM1QiwgMHg0RkRFNUQzMywgMHgzRUM3ODA2OSwgMHg1QjZFNDUyRiwgMHgzRUNGNTA3NiwKICAgIDB4OTlGREREMDMsIDB4M0VENERDQjIsIDB4OTA0QkMxQzMsIDB4M0VEQkNDMUUsIDB4RTFGNTYzNzgsIDB4M0VFMjg0REYsIDB4NDIyQUEwQ0YsIDB4M0VFOEFDRTUsCiAgICAweDI5RERGNkQ2LCAweDNFRjA3MDZCLCAweDE1QUQyMTNFLCAweDNFRjVFNzZGLCAweDA4MEQ4OUUzLCAweDNFRkQyRjg3LCAweDM3M0FBOUMyLCAweDNGMDM3MUE3LAogICAgMHgxOUUzMjMxOCwgMHgzRjA5RTg2MywgMHhBRUE5MkREOCwgMHgzRjExNDI5QSwgMHhGOTUxOTQ3QiwgMHgzRjE2RkY3RCwgMHhBMkE0OTBDRCwgMHgzRjFFQTRBRiwKICAgIDB4RUQxRDAwNTAsIDB4M0YyNDZBNDEsIDB4Qjg0RjE1RjAsIDB4M0YyQjMzQTIsIDB4OTE3RERDOTAsIDB4M0YzMjFGNDksIDB4OTk0Q0NFMEEsIDB4M0YzODI1ODksCiAgICAweEE5RkIzMzJGLCAweDNGNDAxNjNELCAweDM2QjUyN0QzLCAweDNGNDU2RjQ3LCAweDk0MDZFN0FDLCAweDNGNEM4RjZELCAweDBBMzFCNzBGLCAweDNGNTMwNkZFLAogICAgMHhDQkM4NTIwNywgMHgzRjU5NUE0NCwgMHgzMkQzRDE5RCwgMHgzRjYwRTNFQywgMHhENDRDQTk2QywgMHgzRjY2ODE1NSwgMHgzMzdCOUI1NiwgMHgzRjZERkM5NywKICAgIDB4MDRBQzgwMTYsIDB4M0Y3M0ZBNDUsIDB4NTU3OUZEQjgsIDB4M0Y3QTlFNkIsIDB4ODQwNDVDQ0YsIDB4M0Y4MUJCRTAsIDB4NzNFQjAxODEsIDB4M0Y4N0ExMTQsCiAgICAweEFEOUNCRTBDLCAweDNGOEY3QkZELCAweDc2OUQyQ0EyLCAweDNGOTRGOUIyLCAweDVCRDcxRTAzLCAweDNGOUJGMkMyLCAweEY1MUZERURFLCAweDNGQTI5RTlELAogICAgMHgxNkI1NDQ4NywgMHgzRkE4Q0YzMiwgMHgxODc1OUJDNSwgMHgzRkIwODc0NSwgMHhCOTc2REMwNSwgMHgzRkI2MDVFMSwgMHhEQ0ZCQTQ4MywgMHgzRkJENTgxOCwKICAgIDB4NkQwNUQ4NjMsIDB4M0ZDMzhDQUUsIDB4N0I1REU1NjEsIDB4M0ZDQTBDNjYsIDB4QzhBNThFNEYsIDB4M0ZEMTVBOTgsIDB4RThFQzVGNzEsIDB4M0ZENzFGNzUsCiAgICAweDJEOEU2N0VELCAweDNGREVDRjQ4LCAweEI1QzEzQ0NFLCAweDNGRTQ4NkEyLCAweDhERTU1OTM4LCAweDNGRUI1OTcyLCAweDZFNzU2MjM3LCAweDNGRjIzODdBLAogICAgMHg0NjIzQzdBQywgMHgzRkY4NDcxQSwgMHgzRTc3ODA2MCwgMHg0MDAwMkM5QSwgMHhENDk3QzdGRCwgMHg0MDA1OEQxMiwgMHhEQ0VGOTA2OCwgMHg0MDBDQjcyMCwKICAgIDB4RkM0Q0Q4MzEsIDB4NDAxMzIxNzAsIDB4OUZERTRFNTAsIDB4NDAxOTdEODIsIDB4QUZGRUQzMUIsIDB4NDAyMEZCNjYsIDB4NjY3RjNCQ0QsIDB4NDAyNkEwOUUKXSkpLmJ1ZmZlcik7CkhDQVRhYmxlcy5RdWFudGl6ZXJTdGVwU2l6ZSA9IG5ldyBGbG9hdDY0QXJyYXkoX2IuYWRhcHRFbmRpYW5uZXNzNjQzMihuZXcgVWludDMyQXJyYXkoWwogICAgMHgwMDAwMDAwMCwgMHgwMDAwMDAwMCwgMHg1NTU1NTU1NSwgMHgzRkU1NTU1NSwgMHg5OTk5OTk5QSwgMHgzRkQ5OTk5OSwgMHg5MjQ5MjQ5MiwgMHgzRkQyNDkyNCwKICAgIDB4MUM3MUM3MUMsIDB4M0ZDQzcxQzcsIDB4NzQ1RDE3NDYsIDB4M0ZDNzQ1RDEsIDB4MTNCMTNCMTQsIDB4M0ZDM0IxM0IsIDB4MTExMTExMTEsIDB4M0ZDMTExMTEsCiAgICAweDA4NDIxMDg0LCAweDNGQjA4NDIxLCAweDEwNDEwNDEwLCAweDNGQTA0MTA0LCAweDgxMDIwNDA4LCAweDNGOTAyMDQwLCAweDEwMTAxMDEwLCAweDNGODAxMDEwLAogICAgMHgwMjAxMDA4MCwgMHgzRjcwMDgwNCwgMHgwMDQwMTAwNCwgMHgzRjYwMDQwMSwgMHg0MDA4MDEwMCwgMHgzRjUwMDIwMCwgMHgxMDAxMDAxMCwgMHgzRjQwMDEwMApdKSkuYnVmZmVyKTsKSENBVGFibGVzLlF1YW50aXplckRlYWRab25lID0gbmV3IEZsb2F0NjRBcnJheShfYi5hZGFwdEVuZGlhbm5lc3M2NDMyKG5ldyBVaW50MzJBcnJheShbCiAgICAweEZGRkZGRkZGLCAweEZGRkZGRkZGLCAweDU1NTU1NTUzLCAweDNGRDU1NTU1LCAweDk5OTk5OTk3LCAweDNGQzk5OTk5LCAweDkyNDkyNDhFLCAweDNGQzI0OTI0LAogICAgMHgxQzcxQzcxNywgMHgzRkJDNzFDNywgMHg3NDVEMTc0MCwgMHgzRkI3NDVEMSwgMHgxM0IxM0IwRCwgMHgzRkIzQjEzQiwgMHgxMTExMTEwOSwgMHgzRkIxMTExMSwKICAgIDB4MDg0MjEwNzQsIDB4M0ZBMDg0MjEsIDB4MTA0MTAzRjAsIDB4M0Y5MDQxMDQsIDB4ODEwMjAzQzgsIDB4M0Y4MDIwNDAsIDB4MTAxMDBGOTAsIDB4M0Y3MDEwMTAsCiAgICAweDAyMDBGRjgwLCAweDNGNjAwODA0LCAweDAwNDAwRTA0LCAweDNGNTAwNDAxLCAweDQwMDdGRDAwLCAweDNGNDAwMjAwLCAweDEwMDBGODEwLCAweDNGMzAwMTAwCl0pKS5idWZmZXIpOwpIQ0FUYWJsZXMuUXVhbnRpemVyU2NhbGluZ1RhYmxlID0gbmV3IEZsb2F0NjRBcnJheShfYi5hZGFwdEVuZGlhbm5lc3M2NDMyKG5ldyBVaW50MzJBcnJheShbCiAgICAweDU0M0UxQTIxLCAweDQxNTgwNDI3LCAweDg4NjI4Q0UyLCAweDQxNTIwNjNCLCAweDI5OERCNjc3LCAweDQxNEIwRTA3LCAweDYwNjE4OTNBLCAweDQxNDQ0RTA4LAogICAgMHhGQkM3NEM5NiwgMHg0MTNFN0E1MSwgMHgzQzY1MUEzRCwgMHg0MTM2REZCMiwgMHhDMDZDMzFENiwgMHg0MTMxMkFCRCwgMHg4MkEzRjBBMCwgMHg0MTI5QzQ5MSwKICAgIDB4NUY5MjlGRkMsIDB4NDEyMzU2QzUsIDB4NEEwNzg5OEIsIDB4NDExRDA3MkQsIDB4OEE1OTQ2QzIsIDB4NDExNUM5MjYsIDB4RDMxNTg1N0QsIDB4NDExMDU5QjAsCiAgICAweEQ5OEE2NkE2LCAweDQxMDg4QUM3LCAweDY1RTI3Q0U3LCAweDQxMDI2QjQ1LCAweDMwQTEwNjU2LCAweDQwRkJBNUIwLCAweEQ1MzYyQTMyLCAweDQwRjRCRkRBLAogICAgMHgzNzZCQkFBNiwgMHg0MEVGMjUyQiwgMHg1NjQyNjdENCwgMHg0MEU3NUZFQiwgMHgzODhDOERGMiwgMHg0MEUxOEFGOSwgMHhCMjNFMjU2OCwgMHg0MERBNTUwMywKICAgIDB4QzMxM0E4RUQsIDB4NDBEM0MzMkQsIDB4MDNEQjMyOTMsIDB4NDBDREE5RTYsIDB4MzRDQ0MzMjgsIDB4NDBDNjQzNDYsIDB4NkNGOTg5MTYsIDB4NDBDMEI1NTgsCiAgICAweDBCOTFGRkNGLCAweDQwQjkxNDVCLCAweEE2RTQwMzEzLCAweDQwQjJEMjg1LCAweDVGRkZEMDg0LCAweDQwQUM0MEFCLCAweDU2OUQ0Rjg5LCAweDQwQTUzNDJCLAogICAgMHgyQjhGNzFGRSwgMHg0MDlGRDNDMiwgMHgzNkNGNEU2QSwgMHg0MDk3RTJGMywgMHgyMkZDRDkyMiwgMHg0MDkxRUQ1MCwgMHg5OTVBRDNCNiwgMHg0MDhBRTg5RiwKICAgIDB4RDk1MEE4OUQsIDB4NDA4NDMxRjUsIDB4RTc4QjNGRkYsIDB4NDA3RTUwMkUsIDB4NzUwQkRBQzYsIDB4NDA3NkMwMTIsIDB4RDAxMjVCNTYsIDB4NDA3MTEzMDEsCiAgICAweDcwQ0EwN0MxLCAweDQwNjlBMEYxLCAweEIyNjQxNzA1LCAweDQwNjMzQzA4LCAweDU1NURDNDAxLCAweDQwNUNERjBCLCAweERENDg1NDJGLCAweDQwNTVBQjA3LAogICAgMHhFODZFN0Y4OSwgMHg0MDUwNDMxNSwgMHg5QjQ0OTJGMiwgMHg0MDQ4NjhEOSwgMHg0RkIyQTY0MywgMHg0MDQyNTFDRSwgMHhGMkZCNUU0QywgMHg0MDNCN0Y3NiwKICAgIDB4RjBEN0QzRTMsIDB4NDAzNEEzMkEsIDB4RUU2MTVBMkQsIDB4NDAyRUZBMUIsIDB4NDhBNTgxNzgsIDB4NDAyNzNGOUEsIDB4M0M3RDUxN0QsIDB4NDAyMTcyQjgsCiAgICAweEVDNEEyRDM3LCAweDQwMUEzMDlCLCAweDM0RTU5RkZBLCAweDQwMTNBN0RCLCAweDE2Qzk4MzlCLCAweDQwMEQ4MEUzLCAweEIwM0E1NTg3LCAweDQwMDYyNDdFLAogICAgMHhDQUM2RjM4NSwgMHg0MDAwOUUzRSwgMHg5OTE1NzczOSwgMHgzRkY4RjFBRSwgMHhEMERBRDk5MSwgMHgzRkYyQjg3RiwgMHhERDg1NTI5RSwgMHgzRkVDMTk5QiwKICAgIDB4QTJDRjY2NDIsIDB4M0ZFNTE2REEsIDB4ODE5RTkwREEsIDB4M0ZERkE3QzEsIDB4MDEzMEMxMzMsIDB4M0ZEN0MxRUQsIDB4MzE2OEI5QUIsIDB4M0ZEMUQ0ODcsCiAgICAweEJGRDNGMzdBLCAweDNGQ0FDMzZCLCAweDIxRjcyRTJBLCAweDNGQzQxNjBBLCAweDE0RjVBMTI5LCAweDNGQkUyNjQ2LCAweDY2N0YzQkNDLCAweDNGQjZBMDlFCl0pKS5idWZmZXIpOwpIQ0FUYWJsZXMuUXVhbnRpemVySW52ZXJzZVN0ZXBTaXplID0gbmV3IEZsb2F0NjRBcnJheShfYi5hZGFwdEVuZGlhbm5lc3M2NDMyKG5ldyBVaW50MzJBcnJheShbCiAgICAweDAwMDAwMDAwLCAweDNGRTAwMDAwLCAweDAwMDAwMDAwLCAweDNGRjgwMDAwLCAweDAwMDAwMDAwLCAweDQwMDQwMDAwLCAweDAwMDAwMDAwLCAweDQwMEMwMDAwLAogICAgMHgwMDAwMDAwMCwgMHg0MDEyMDAwMCwgMHgwMDAwMDAwMCwgMHg0MDE2MDAwMCwgMHgwMDAwMDAwMCwgMHg0MDFBMDAwMCwgMHgwMDAwMDAwMCwgMHg0MDFFMDAwMCwKICAgIDB4MDAwMDAwMDAsIDB4NDAyRjAwMDAsIDB4MDAwMDAwMDAsIDB4NDAzRjgwMDAsIDB4MDAwMDAwMDAsIDB4NDA0RkMwMDAsIDB4MDAwMDAwMDAsIDB4NDA1RkUwMDAsCiAgICAweDAwMDAwMDAwLCAweDQwNkZGMDAwLCAweDAwMDAwMDAwLCAweDQwN0ZGODAwLCAweDAwMDAwMDAwLCAweDQwOEZGQzAwLCAweDAwMDAwMDAwLCAweDQwOUZGRTAwCl0pKS5idWZmZXIpOwpIQ0FUYWJsZXMuUmVzb2x1dGlvbk1heFZhbHVlcyA9IG5ldyBJbnQzMkFycmF5KFsKICAgIDB4MDAwMDAwMDAsIDB4MDAwMDAwMDEsIDB4MDAwMDAwMDIsIDB4MDAwMDAwMDMsIDB4MDAwMDAwMDQsIDB4MDAwMDAwMDUsIDB4MDAwMDAwMDYsIDB4MDAwMDAwMDcsCiAgICAweDAwMDAwMDBGLCAweDAwMDAwMDFGLCAweDAwMDAwMDNGLCAweDAwMDAwMDdGLCAweDAwMDAwMEZGLCAweDAwMDAwMUZGLCAweDAwMDAwM0ZGLCAweDAwMDAwN0ZGCl0pOwpIQ0FUYWJsZXMuSW50ZW5zaXR5UmF0aW9UYWJsZSA9IG5ldyBGbG9hdDY0QXJyYXkoX2IuYWRhcHRFbmRpYW5uZXNzNjQzMihuZXcgVWludDMyQXJyYXkoWwogICAgMHgwMDAwMDAwMCwgMHg0MDAwMDAwMCwgMHg2REI2REI2RSwgMHgzRkZEQjZEQiwgMHhEQjZEQjZEQiwgMHgzRkZCNkRCNiwgMHg0OTI0OTI0OSwgMHgzRkY5MjQ5MiwKICAgIDB4QjZEQjZEQjcsIDB4M0ZGNkRCNkQsIDB4MjQ5MjQ5MjUsIDB4M0ZGNDkyNDksIDB4OTI0OTI0OTIsIDB4M0ZGMjQ5MjQsIDB4MDAwMDAwMDAsIDB4M0ZGMDAwMDAsCiAgICAweERCNkRCNkRCLCAweDNGRUI2REI2LCAweEI2REI2REI3LCAweDNGRTZEQjZELCAweDkyNDkyNDkyLCAweDNGRTI0OTI0LCAweERCNkRCNkRCLCAweDNGREI2REI2LAogICAgMHg5MjQ5MjQ5MiwgMHgzRkQyNDkyNCwgMHg5MjQ5MjQ5MiwgMHgzRkMyNDkyNCwgMHgwMDAwMDAwMCwgMHgwMDAwMDAwMApdKSkuYnVmZmVyKTsKSENBVGFibGVzLkludGVuc2l0eVJhdGlvQm91bmRzVGFibGUgPSBuZXcgRmxvYXQ2NEFycmF5KF9iLmFkYXB0RW5kaWFubmVzczY0MzIobmV3IFVpbnQzMkFycmF5KFsKICAgIDB4QjZEQjZEQjcsIDB4M0ZGRURCNkQsIDB4MjQ5MjQ5MjUsIDB4M0ZGQzkyNDksIDB4OTI0OTI0OTIsIDB4M0ZGQTQ5MjQsIDB4MDAwMDAwMDAsIDB4M0ZGODAwMDAsCiAgICAweDZEQjZEQjZFLCAweDNGRjVCNkRCLCAweERCNkRCNkRCLCAweDNGRjM2REI2LCAweDQ5MjQ5MjQ5LCAweDNGRjEyNDkyLCAweDZEQjZEQjZFLCAweDNGRURCNkRCLAogICAgMHg0OTI0OTI0OSwgMHgzRkU5MjQ5MiwgMHgyNDkyNDkyNSwgMHgzRkU0OTI0OSwgMHgwMDAwMDAwMCwgMHgzRkUwMDAwMCwgMHhCNkRCNkRCNywgMHgzRkQ2REI2RCwKICAgIDB4REI2REI2REIsIDB4M0ZDQjZEQjYsIDB4OTI0OTI0OTIsIDB4M0ZCMjQ5MjQKXSkpLmJ1ZmZlcik7CkhDQVRhYmxlcy5TY2FsZUNvbnZlcnNpb25UYWJsZSA9IG5ldyBGbG9hdDY0QXJyYXkoX2IuYWRhcHRFbmRpYW5uZXNzNjQzMihuZXcgVWludDMyQXJyYXkoWwogICAgMHgwMDAwMDAwMCwgMHgwMDAwMDAwMCwgMHgwMDAwMDAwMCwgMHgwMDAwMDAwMCwgMHgyMUY3MkUxRCwgMHgzRTU0MTYwQSwgMHhCRkQzRjM2OCwgMHgzRTVBQzM2QiwKICAgIDB4MzE2OEI5OUYsIDB4M0U2MUQ0ODcsIDB4MDEzMEMxMjMsIDB4M0U2N0MxRUQsIDB4ODE5RTkwQzQsIDB4M0U2RkE3QzEsIDB4QTJDRjY2MzUsIDB4M0U3NTE2REEsCiAgICAweEREODU1MjhCLCAweDNFN0MxOTlCLCAweEQwREFEOTg1LCAweDNFODJCODdGLCAweDk5MTU3NzI4LCAweDNFODhGMUFFLCAweENBQzZGMzdBLCAweDNFOTA5RTNFLAogICAgMHhCMDNBNTU3OCwgMHgzRTk2MjQ3RSwgMHgxNkM5ODM4OCwgMHgzRTlEODBFMywgMHgzNEU1OUZFQywgMHgzRUEzQTdEQiwgMHhFQzRBMkQyNiwgMHgzRUFBMzA5QiwKICAgIDB4M0M3RDUxNzIsIDB4M0VCMTcyQjgsIDB4NDhBNTgxNjgsIDB4M0VCNzNGOUEsIDB4RUU2MTVBMTgsIDB4M0VCRUZBMUIsIDB4RjBEN0QzRDQsIDB4M0VDNEEzMkEsCiAgICAweEYyRkI1RTNBLCAweDNFQ0I3Rjc2LCAweDRGQjJBNjM3LCAweDNFRDI1MUNFLCAweDlCNDQ5MkUxLCAweDNFRDg2OEQ5LCAweEU4NkU3RjdFLCAweDNFRTA0MzE1LAogICAgMHhERDQ4NTQyMCwgMHgzRUU1QUIwNywgMHg1NTVEQzNFRSwgMHgzRUVDREYwQiwgMHhCMjY0MTZGNywgMHgzRUYzM0MwOCwgMHg3MENBMDdCMCwgMHgzRUY5QTBGMSwKICAgIDB4RDAxMjVCNEEsIDB4M0YwMTEzMDEsIDB4NzUwQkRBQjYsIDB4M0YwNkMwMTIsIDB4RTc4QjNGRUIsIDB4M0YwRTUwMkUsIDB4RDk1MEE4OTAsIDB4M0YxNDMxRjUsCiAgICAweDk5NUFEM0E0LCAweDNGMUFFODlGLCAweDIyRkNEOTE3LCAweDNGMjFFRDUwLCAweDM2Q0Y0RTVBLCAweDNGMjdFMkYzLCAweDJCOEY3MUU3LCAweDNGMkZEM0MyLAogICAgMHg1NjlENEY3QiwgMHgzRjM1MzQyQiwgMHg1RkZGRDA3MiwgMHgzRjNDNDBBQiwgMHhBNkU0MDMwNiwgMHgzRjQyRDI4NSwgMHgwQjkxRkZCRiwgMHgzRjQ5MTQ1QiwKICAgIDB4NkNGOTg5MEIsIDB4M0Y1MEI1NTgsIDB4MzRDQ0MzMUEsIDB4M0Y1NjQzNDYsIDB4MDNEQjMyN0UsIDB4M0Y1REE5RTYsIDB4QzMxM0E4RTAsIDB4M0Y2M0MzMkQsCiAgICAweEIyM0UyNTU3LCAweDNGNkE1NTAzLCAweDM4OEM4REU2LCAweDNGNzE4QUY5LCAweDU2NDI2N0M0LCAweDNGNzc1RkVCLCAweDM3NkJCQTkyLCAweDNGN0YyNTJCLAogICAgMHhENTM2MkEyNCwgMHgzRjg0QkZEQSwgMHgzMEExMDY0NSwgMHgzRjhCQTVCMCwgMHg2NUUyN0NEQSwgMHgzRjkyNkI0NSwgMHhEOThBNjY5NiwgMHgzRjk4OEFDNywKICAgIDB4RDMxNTg1NzIsIDB4M0ZBMDU5QjAsIDB4OEE1OTQ2QjQsIDB4M0ZBNUM5MjYsIDB4NEEwNzg5NzgsIDB4M0ZBRDA3MkQsIDB4NUY5MjlGRUYsIDB4M0ZCMzU2QzUsCiAgICAweDgyQTNGMDhFLCAweDNGQjlDNDkxLCAweEMwNkMzMUNCLCAweDNGQzEyQUJELCAweDNDNjUxQTJELCAweDNGQzZERkIyLCAweEZCQzc0QzgyLCAweDNGQ0U3QTUxLAogICAgMHg2MDYxODkyQywgMHgzRkQ0NEUwOCwgMHgyOThEQjY2NSwgMHgzRkRCMEUwNywgMHg4ODYyOENENiwgMHgzRkUyMDYzQiwgMHg1NDNFMUExMSwgMHgzRkU4MDQyNywKICAgIDB4MDAwMDAwMDAsIDB4M0ZGMDAwMDAsIDB4Q0E1RDkyMEYsIDB4M0ZGNTUxQTQsIDB4MkU1N0QxNEMsIDB4M0ZGQzY3RjEsIDB4QTkzRTJGNTcsIDB4NDAwMkVDQUYsCiAgICAweEIwQ0RDNUU2LCAweDQwMDkzNzM3LCAweDJCNzI0N0Y4LCAweDQwMTBDQzkyLCAweDgyNTUyMjI2LCAweDQwMTY2MjM4LCAweEYzMDFCNDYzLCAweDQwMUREMzIxLAogICAgMHg0QzEyMzQyNCwgMHg0MDIzREVBNiwgMHgxMzMwQjM1QiwgMHg0MDJBNzk5RSwgMHhFQjZGQ0I3NywgMHg0MDMxQTM1QiwgMHg0RkRFNUQ0MiwgMHg0MDM3ODA2OSwKICAgIDB4NUI2RTQ1NDQsIDB4NDAzRjUwNzYsIDB4OTlGREREMTAsIDB4NDA0NERDQjIsIDB4OTA0QkMxRDYsIDB4NDA0QkNDMUUsIDB4RTFGNTYzODQsIDB4NDA1Mjg0REYsCiAgICAweDQyMkFBMEUwLCAweDQwNThBQ0U1LCAweDI5RERGNkUxLCAweDQwNjA3MDZCLCAweDE1QUQyMTRELCAweDQwNjVFNzZGLCAweDA4MEQ4OUY4LCAweDQwNkQyRjg3LAogICAgMHgzNzNBQTlDRiwgMHg0MDczNzFBNywgMHgxOUUzMjMyOSwgMHg0MDc5RTg2MywgMHhBRUE5MkRFNCwgMHg0MDgxNDI5QSwgMHhGOTUxOTQ4QSwgMHg0MDg2RkY3RCwKICAgIDB4QTJBNDkwRTEsIDB4NDA4RUE0QUYsIDB4RUQxRDAwNUQsIDB4NDA5NDZBNDEsIDB4Qjg0RjE2MDMsIDB4NDA5QjMzQTIsIDB4OTE3RERDOUIsIDB4NDBBMjFGNDksCiAgICAweDk5NENDRTFBLCAweDQwQTgyNTg5LCAweEE5RkIzMzNBLCAweDQwQjAxNjNELCAweDM2QjUyN0UxLCAweDQwQjU2RjQ3LCAweDk0MDZFN0JGLCAweDQwQkM4RjZELAogICAgMHgwQTMxQjcxQywgMHg0MEMzMDZGRSwgMHhDQkM4NTIxOCwgMHg0MEM5NUE0NCwgMHgzMkQzRDFBOCwgMHg0MEQwRTNFQywgMHhENDRDQTk3QywgMHg0MEQ2ODE1NSwKICAgIDB4MzM3QjlCNkEsIDB4NDBEREZDOTcsIDB4MDRBQzgwMjQsIDB4NDBFM0ZBNDUsIDB4NTU3OUZEQ0EsIDB4NDBFQTlFNkIsIDB4ODQwNDVDREIsIDB4NDBGMUJCRTAsCiAgICAweDczRUIwMTkxLCAweDQwRjdBMTE0LCAweEFEOUNCRTIxLCAweDQwRkY3QkZELCAweDc2OUQyQ0IwLCAweDQxMDRGOUIyLCAweDVCRDcxRTE1LCAweDQxMEJGMkMyLAogICAgMHhGNTFGREVFQSwgMHg0MTEyOUU5RCwgMHgxNkI1NDQ5OCwgMHg0MTE4Q0YzMiwgMHgxODc1OUJEMCwgMHg0MTIwODc0NSwgMHhCOTc2REMxNCwgMHg0MTI2MDVFMSwKICAgIDB4RENGQkE0OTYsIDB4NDEyRDU4MTgsIDB4NkQwNUQ4NzAsIDB4NDEzMzhDQUUsIDB4N0I1REU1NzMsIDB4NDEzQTBDNjYsIDB4QzhBNThFNUIsIDB4NDE0MTVBOTgsCiAgICAweEU4RUM1RjgxLCAweDQxNDcxRjc1LCAweDJEOEU2ODAyLCAweDQxNEVDRjQ4LCAweEI1QzEzQ0RDLCAweDQxNTQ4NkEyLCAweDhERTU1OTRBLCAweDQxNUI1OTcyLAogICAgMHg2RTc1NjI0MywgMHg0MTYyMzg3QSwgMHg0NjIzQzdCQywgMHg0MTY4NDcxQSwgMHgzRTc3ODA2QiwgMHg0MTcwMkM5QSwgMHhENDk3QzgwQiwgMHg0MTc1OEQxMiwKICAgIDB4RENFRjkwN0MsIDB4NDE3Q0I3MjAsIDB4RkM0Q0Q4M0UsIDB4NDE4MzIxNzAsIDB4OUZERTRFNjEsIDB4NDE4OTdEODIsIDB4MDAwMDAwMDAsIDB4MDAwMDAwMDAKXSkpLmJ1ZmZlcik7CmNsYXNzIEhDQUNyYzE2IHsKICAgIHN0YXRpYyBjYWxjKGRhdGEsIHNpemUpIHsKICAgICAgICBpZiAoc2l6ZSA+IGRhdGEuYnl0ZUxlbmd0aCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgaWYgKHNpemUgPCAwKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICBsZXQgc3VtID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykKICAgICAgICAgICAgc3VtID0gKChzdW0gPDwgOCkgXiB0aGlzLl92WyhzdW0gPj4gOCkgXiBkYXRhW2ldXSkgJiAweDAwMDBmZmZmOwogICAgICAgIHJldHVybiBzdW0gJiAweDAwMDBmZmZmOwogICAgfQogICAgc3RhdGljIHZlcmlmeShkYXRhLCBzaXplLCBleHBlY3RlZCwgZG9Ob3RUaHJvdyA9IGZhbHNlKSB7CiAgICAgICAgaWYgKGV4cGVjdGVkID09IG51bGwpIHsKICAgICAgICAgICAgZXhwZWN0ZWQgPSBuZXcgRGF0YVZpZXcoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgZGF0YS5ieXRlTGVuZ3RoKS5nZXRVaW50MTYoc2l6ZSk7CiAgICAgICAgfQogICAgICAgIGxldCBhY3R1YWwgPSB0aGlzLmNhbGMoZGF0YSwgc2l6ZSk7CiAgICAgICAgbGV0IHJlc3VsdCA9IGV4cGVjdGVkID09IGFjdHVhbDsKICAgICAgICBpZiAoIXJlc3VsdCkgewogICAgICAgICAgICBmdW5jdGlvbiB0b0hleChudW0pIHsKICAgICAgICAgICAgICAgIGNvbnN0IHBhZGRpbmcgPSAiMDAwMCI7CiAgICAgICAgICAgICAgICBsZXQgaGV4ID0gcGFkZGluZyArIG51bS50b1N0cmluZyhwYWRkaW5nLmxlbmd0aCAqIDQpLnRvVXBwZXJDYXNlKCk7CiAgICAgICAgICAgICAgICByZXR1cm4gIjB4IiArIGhleC5zdWJzdHJpbmcoaGV4Lmxlbmd0aCAtIHBhZGRpbmcubGVuZ3RoLCBoZXgubGVuZ3RoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgbXNnID0gYGNoZWNrc3VtIG1pc21hdGNoIChleHBlY3RlZD0ke3RvSGV4KGV4cGVjdGVkKX0gYWN0dWFsPSR7dG9IZXgoYWN0dWFsKX0pYDsKICAgICAgICAgICAgaWYgKGRvTm90VGhyb3cpCiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG1zZyk7CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQogICAgc3RhdGljIGZpeChkYXRhLCBzaXplKSB7CiAgICAgICAgbGV0IG5ld0NyYzE2ID0gdGhpcy5jYWxjKGRhdGEsIHNpemUpOwogICAgICAgIG5ldyBEYXRhVmlldyhkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBkYXRhLmJ5dGVMZW5ndGgpLnNldFVpbnQxNihzaXplLCBuZXdDcmMxNik7CiAgICAgICAgcmV0dXJuIGRhdGE7CiAgICB9Cn0KSENBQ3JjMTYuX3YgPSBuZXcgVWludDE2QXJyYXkoWwogICAgMHgwMDAwLCAweDgwMDUsIDB4ODAwRiwgMHgwMDBBLCAweDgwMUIsIDB4MDAxRSwgMHgwMDE0LCAweDgwMTEsIDB4ODAzMywgMHgwMDM2LCAweDAwM0MsIDB4ODAzOSwgMHgwMDI4LCAweDgwMkQsIDB4ODAyNywgMHgwMDIyLAogICAgMHg4MDYzLCAweDAwNjYsIDB4MDA2QywgMHg4MDY5LCAweDAwNzgsIDB4ODA3RCwgMHg4MDc3LCAweDAwNzIsIDB4MDA1MCwgMHg4MDU1LCAweDgwNUYsIDB4MDA1QSwgMHg4MDRCLCAweDAwNEUsIDB4MDA0NCwgMHg4MDQxLAogICAgMHg4MEMzLCAweDAwQzYsIDB4MDBDQywgMHg4MEM5LCAweDAwRDgsIDB4ODBERCwgMHg4MEQ3LCAweDAwRDIsIDB4MDBGMCwgMHg4MEY1LCAweDgwRkYsIDB4MDBGQSwgMHg4MEVCLCAweDAwRUUsIDB4MDBFNCwgMHg4MEUxLAogICAgMHgwMEEwLCAweDgwQTUsIDB4ODBBRiwgMHgwMEFBLCAweDgwQkIsIDB4MDBCRSwgMHgwMEI0LCAweDgwQjEsIDB4ODA5MywgMHgwMDk2LCAweDAwOUMsIDB4ODA5OSwgMHgwMDg4LCAweDgwOEQsIDB4ODA4NywgMHgwMDgyLAogICAgMHg4MTgzLCAweDAxODYsIDB4MDE4QywgMHg4MTg5LCAweDAxOTgsIDB4ODE5RCwgMHg4MTk3LCAweDAxOTIsIDB4MDFCMCwgMHg4MUI1LCAweDgxQkYsIDB4MDFCQSwgMHg4MUFCLCAweDAxQUUsIDB4MDFBNCwgMHg4MUExLAogICAgMHgwMUUwLCAweDgxRTUsIDB4ODFFRiwgMHgwMUVBLCAweDgxRkIsIDB4MDFGRSwgMHgwMUY0LCAweDgxRjEsIDB4ODFEMywgMHgwMUQ2LCAweDAxREMsIDB4ODFEOSwgMHgwMUM4LCAweDgxQ0QsIDB4ODFDNywgMHgwMUMyLAogICAgMHgwMTQwLCAweDgxNDUsIDB4ODE0RiwgMHgwMTRBLCAweDgxNUIsIDB4MDE1RSwgMHgwMTU0LCAweDgxNTEsIDB4ODE3MywgMHgwMTc2LCAweDAxN0MsIDB4ODE3OSwgMHgwMTY4LCAweDgxNkQsIDB4ODE2NywgMHgwMTYyLAogICAgMHg4MTIzLCAweDAxMjYsIDB4MDEyQywgMHg4MTI5LCAweDAxMzgsIDB4ODEzRCwgMHg4MTM3LCAweDAxMzIsIDB4MDExMCwgMHg4MTE1LCAweDgxMUYsIDB4MDExQSwgMHg4MTBCLCAweDAxMEUsIDB4MDEwNCwgMHg4MTAxLAogICAgMHg4MzAzLCAweDAzMDYsIDB4MDMwQywgMHg4MzA5LCAweDAzMTgsIDB4ODMxRCwgMHg4MzE3LCAweDAzMTIsIDB4MDMzMCwgMHg4MzM1LCAweDgzM0YsIDB4MDMzQSwgMHg4MzJCLCAweDAzMkUsIDB4MDMyNCwgMHg4MzIxLAogICAgMHgwMzYwLCAweDgzNjUsIDB4ODM2RiwgMHgwMzZBLCAweDgzN0IsIDB4MDM3RSwgMHgwMzc0LCAweDgzNzEsIDB4ODM1MywgMHgwMzU2LCAweDAzNUMsIDB4ODM1OSwgMHgwMzQ4LCAweDgzNEQsIDB4ODM0NywgMHgwMzQyLAogICAgMHgwM0MwLCAweDgzQzUsIDB4ODNDRiwgMHgwM0NBLCAweDgzREIsIDB4MDNERSwgMHgwM0Q0LCAweDgzRDEsIDB4ODNGMywgMHgwM0Y2LCAweDAzRkMsIDB4ODNGOSwgMHgwM0U4LCAweDgzRUQsIDB4ODNFNywgMHgwM0UyLAogICAgMHg4M0EzLCAweDAzQTYsIDB4MDNBQywgMHg4M0E5LCAweDAzQjgsIDB4ODNCRCwgMHg4M0I3LCAweDAzQjIsIDB4MDM5MCwgMHg4Mzk1LCAweDgzOUYsIDB4MDM5QSwgMHg4MzhCLCAweDAzOEUsIDB4MDM4NCwgMHg4MzgxLAogICAgMHgwMjgwLCAweDgyODUsIDB4ODI4RiwgMHgwMjhBLCAweDgyOUIsIDB4MDI5RSwgMHgwMjk0LCAweDgyOTEsIDB4ODJCMywgMHgwMkI2LCAweDAyQkMsIDB4ODJCOSwgMHgwMkE4LCAweDgyQUQsIDB4ODJBNywgMHgwMkEyLAogICAgMHg4MkUzLCAweDAyRTYsIDB4MDJFQywgMHg4MkU5LCAweDAyRjgsIDB4ODJGRCwgMHg4MkY3LCAweDAyRjIsIDB4MDJEMCwgMHg4MkQ1LCAweDgyREYsIDB4MDJEQSwgMHg4MkNCLCAweDAyQ0UsIDB4MDJDNCwgMHg4MkMxLAogICAgMHg4MjQzLCAweDAyNDYsIDB4MDI0QywgMHg4MjQ5LCAweDAyNTgsIDB4ODI1RCwgMHg4MjU3LCAweDAyNTIsIDB4MDI3MCwgMHg4Mjc1LCAweDgyN0YsIDB4MDI3QSwgMHg4MjZCLCAweDAyNkUsIDB4MDI2NCwgMHg4MjYxLAogICAgMHgwMjIwLCAweDgyMjUsIDB4ODIyRiwgMHgwMjJBLCAweDgyM0IsIDB4MDIzRSwgMHgwMjM0LCAweDgyMzEsIDB4ODIxMywgMHgwMjE2LCAweDAyMUMsIDB4ODIxOSwgMHgwMjA4LCAweDgyMEQsIDB4ODIwNywgMHgwMjAyCl0pOwpjb25zdCBIQ0FLbm93bktleXMgPSBbCiAgICAvLyBbbG93ZXIgMzIgYml0cywgaGlnaGVyIDMyIGJpdHNdCiAgICAvLyBlZy4gNjYxNTUxOEU4RUNFRDQ0NyA9PiBbMHg4RUNFRDQ0NywgMHg2NjE1NTE4RV0KICAgIC8vIHNvdXJjZTogaHR0cHM6Ly9naXRodWIuY29tL1RoZWFsZXhiYXJuZXkvVkdBdWRpby9ibG9iL21hc3Rlci9kb2NzL2F1ZGlvLWZvcm1hdHMvaGNhL2VuY3J5cHRpb24ta2V5cy5tZAogICAgWzB4MDAwMDA0QzgsIDB4MDAwMDAwMDBdLAogICAgWzB4MDAwMDA5NzgsIDB4MDAwMDAwMDBdLAogICAgWzB4MDAwMDIyQ0UsIDB4MDAwMDAwMDBdLAogICAgWzB4MDAwMDMwMzksIDB4MDAwMDAwMDBdLAogICAgWzB4MDAxRDE0OUEsIDB4MDAwMDAwMDBdLAogICAgWzB4MDA5MTM0RkMsIDB4MDAwMDAwMDBdLAogICAgWzB4MDEyQzlBNTMsIDB4MDAwMDAwMDBdLAogICAgWzB4MDEyRUJDQ0EsIDB4MDAwMDAwMDBdLAogICAgWzB4MDEyRkNGREYsIDB4MDAwMDAwMDBdLAogICAgWzB4MDEzOTVDNTEsIDB4MDAwMDAwMDBdLAogICAgWzB4MEU2MkJFRjAsIDB4MDAwMDAwMDBdLAogICAgWzB4MEU4ODQ3M0MsIDB4MDAwMDAwMDBdLAogICAgWzB4NDk5MTM1NTYsIDB4MDAwMDAwMDBdLAogICAgWzB4NzdFREExM0EsIDB4MDAwMDAwMDBdLAogICAgWzB4NzdFREYyMUMsIDB4MDAwMDAwMDBdLAogICAgWzB4NzIzNUNCMjksIDB4MDAwMDAwMEJdLAogICAgWzB4MjIyQUFBODQsIDB4MDAwMDA0OTddLAogICAgWzB4QTZBRDYxMjUsIDB4MDAwMDFCODVdLAogICAgWzB4RjI3RTNCMjIsIDB4MDAwMDM2NTddLAogICAgWzB4OTc5NzhBOTYsIDB4MDAwMDk2OEFdLAogICAgWzB4OTUzNTZDNzIsIDB4MDAwMjM1NEVdLAogICAgWzB4QkM3MzFBODUsIDB4MDAwMkI4NzVdLAogICAgWzB4MERDNTdGNDgsIDB4MDAxMURDRERdLAogICAgWzB4MTAyNEFERTksIDB4MDAxODlERkJdLAogICAgWzB4NjM0QjVGMDcsIDB4MDAyMDU1QzhdLAogICAgWzB4QTExQ0NGQjAsIDB4MDA2ODg4ODRdLAogICAgWzB4OEQwQzEwRkQsIDB4MDBBMDZBMEJdLAogICAgWzB4Q0M1NTQ2MzksIDB4MDBEQkUxQUJdLAogICAgWzB4NTk5MEZCNUUsIDB4MDIwNTFBRjJdLAogICAgWzB4RjU4MTZBMkEsIDB4MjlBRkU5MTFdLAogICAgWzB4ODM2NTM2OTksIDB4NDM4QkYxRjhdLAogICAgWzB4QjhFNkM2RDIsIDB4NDNFNEVBNjJdLAogICAgWzB4QzMwOTEzNjYsIDB4N0NFQzgxRjddLAogICAgWzB4OTJFQkY0NjQsIDB4N0U4OTYzMThdLAogICAgWzB4MzBEQkUxQUIsIDB4Q0M1NTQ2MzldLAogICAgWzB4RTA3NDg5NzgsIDB4Q0YyMjJGMUZdLAogICAgWzB4MzQzRDAwMDAsIDB4REI1QjYxQjhdLAogICAgWzB4QUI0MTRCQTEsIDB4RkRBRTUzMUFdLAogICAgWzB4RkZGRkZGRkYsIDB4RkZGRkZGRkZdLAogICAgLy8gc291cmNlOiBodHRwczovL2dpdGh1Yi5jb20vdmdtc3RyZWFtL3ZnbXN0cmVhbS9ibG9iLzM2ZjRkZmVhYjQxYWRmOGY4ZmYwODQ3N2RjMDYyZjhjNzZiMDAzZDgvc3JjL21ldGEvaGNhX2tleXMuaCNMMTA1OQogICAgWzB4OEVDRUQ0NDcsIDB4NjYxNTUxOEVdLCAvLyBIZWF2ZW4gQnVybnMgUmVkIChBbmRyb2lkKQpdOwpjbGFzcyBIQ0FDaXBoZXIgewogICAgaW5pdDEoKSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDEsIHYgPSAwOyBpIDwgMHhGRjsgaSsrKSB7CiAgICAgICAgICAgIHYgPSAodiAqIDEzICsgMTEpICYgMHhGRjsKICAgICAgICAgICAgaWYgKHYgPT0gMCB8fCB2ID09IDB4RkYpCiAgICAgICAgICAgICAgICB2ID0gKHYgKiAxMyArIDExKSAmIDB4RkY7CiAgICAgICAgICAgIHRoaXMuX3RhYmxlW2ldID0gdjsKICAgICAgICB9CiAgICAgICAgdGhpcy5fdGFibGVbMF0gPSAwOwogICAgICAgIHRoaXMuX3RhYmxlWzB4RkZdID0gMHhGRjsKICAgIH0KICAgIGluaXQ1NigpIHsKICAgICAgICBsZXQga2V5MSA9IHRoaXMuZHYxLmdldFVpbnQzMigwLCB0cnVlKTsKICAgICAgICBsZXQga2V5MiA9IHRoaXMuZHYyLmdldFVpbnQzMigwLCB0cnVlKTsKICAgICAgICBpZiAoIWtleTEpCiAgICAgICAgICAgIGtleTItLTsKICAgICAgICBrZXkxLS07CiAgICAgICAgdGhpcy5kdjEuc2V0VWludDMyKDAsIGtleTEsIHRydWUpOwogICAgICAgIHRoaXMuZHYyLnNldFVpbnQzMigwLCBrZXkyLCB0cnVlKTsKICAgICAgICBsZXQgdDEgPSB0aGlzLmdldEJ5dGVzT2ZUd29LZXlzKCk7CiAgICAgICAgbGV0IHQyID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgICAgICB0MVsxXSwgdDFbMV0gXiB0MVs2XSwgdDFbMl0gXiB0MVszXSwKICAgICAgICAgICAgdDFbMl0sIHQxWzJdIF4gdDFbMV0sIHQxWzNdIF4gdDFbNF0sCiAgICAgICAgICAgIHQxWzNdLCB0MVszXSBeIHQxWzJdLCB0MVs0XSBeIHQxWzVdLAogICAgICAgICAgICB0MVs0XSwgdDFbNF0gXiB0MVszXSwgdDFbNV0gXiB0MVs2XSwKICAgICAgICAgICAgdDFbNV0sIHQxWzVdIF4gdDFbNF0sIHQxWzZdIF4gdDFbMV0sCiAgICAgICAgICAgIHQxWzZdCiAgICAgICAgXSk7CiAgICAgICAgbGV0IHQzID0gbmV3IFVpbnQ4QXJyYXkoMHgxMDApOwogICAgICAgIGxldCB0MzEgPSBuZXcgVWludDhBcnJheSgweDEwKTsKICAgICAgICBsZXQgdDMyID0gbmV3IFVpbnQ4QXJyYXkoMHgxMCk7CiAgICAgICAgdGhpcy5jcmVhdGVUYWJsZSh0MzEsIHQxWzBdKTsKICAgICAgICBmb3IgKGxldCBpID0gMCwgdCA9IDA7IGkgPCAweDEwOyBpKyspIHsKICAgICAgICAgICAgdGhpcy5jcmVhdGVUYWJsZSh0MzIsIHQyW2ldKTsKICAgICAgICAgICAgbGV0IHYgPSB0MzFbaV0gPDwgNDsKICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCAweDEwOyBqKyspIHsKICAgICAgICAgICAgICAgIHQzW3QrK10gPSB2IHwgdDMyW2pdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAwLCB2ID0gMCwgdCA9IDE7IGkgPCAweDEwMDsgaSsrKSB7CiAgICAgICAgICAgIHYgPSAodiArIDB4MTEpICYgMHhGRjsKICAgICAgICAgICAgbGV0IGEgPSB0M1t2XTsKICAgICAgICAgICAgaWYgKGEgIT0gMCAmJiBhICE9IDB4RkYpCiAgICAgICAgICAgICAgICB0aGlzLl90YWJsZVt0KytdID0gYTsKICAgICAgICB9CiAgICAgICAgdGhpcy5fdGFibGVbMF0gPSAwOwogICAgICAgIHRoaXMuX3RhYmxlWzB4RkZdID0gMHhGRjsKICAgIH0KICAgIGNyZWF0ZVRhYmxlKHIsIGtleSkgewogICAgICAgIGxldCBtdWwgPSAoKGtleSAmIDEpIDw8IDMpIHwgNTsKICAgICAgICBsZXQgYWRkID0gKGtleSAmIDB4RSkgfCAxOwogICAgICAgIGxldCB0ID0gMDsKICAgICAgICBrZXkgPj49IDQ7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAweDEwOyBpKyspIHsKICAgICAgICAgICAga2V5ID0gKGtleSAqIG11bCArIGFkZCkgJiAweEY7CiAgICAgICAgICAgIHJbdCsrXSA9IGtleTsKICAgICAgICB9CiAgICB9CiAgICBpbnZlcnRUYWJsZSgpIHsKICAgICAgICAvLyBhY3R1YWxseSwgdGhpcyBtZXRob2Qgc3dpdGNoIHRoZSBtb2RlIGJldHdlZW4gZW5jcnlwdC9kZWNyeXB0CiAgICAgICAgdGhpcy5lbmNyeXB0ID0gIXRoaXMuZW5jcnlwdDsKICAgICAgICBsZXQgX29sZF90YWJsZSA9IHRoaXMuX3RhYmxlLnNsaWNlKDApOwogICAgICAgIGxldCBiaXRNYXAgPSBuZXcgVWludDE2QXJyYXkoMTYpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjU2OyBpKyspIHsKICAgICAgICAgICAgLy8gaW52ZXJ0IGtleSBhbmQgdmFsdWUKICAgICAgICAgICAgbGV0IGtleSA9IF9vbGRfdGFibGVbaV07CiAgICAgICAgICAgIGxldCB2YWwgPSBpOwogICAgICAgICAgICAvLyBjaGVjayBmb3IgaW5jb25zaXN0ZW5jeQogICAgICAgICAgICBsZXQgaGlnaGVyNCA9IGtleSA+PiA0ICYgMHgwRjsKICAgICAgICAgICAgbGV0IGxvd2VyNCA9IGtleSAmIDB4MEY7CiAgICAgICAgICAgIGxldCBmbGFnID0gMHgwMSA8PCBsb3dlcjQ7CiAgICAgICAgICAgIGlmIChiaXRNYXBbaGlnaGVyNF0gJiBmbGFnKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJfdGFibGUgaXMgbm90IGJpamVjdGl2ZSIpOwogICAgICAgICAgICAvLyB1cGRhdGUgdGFibGUKICAgICAgICAgICAgdGhpcy5fdGFibGVba2V5XSA9IHZhbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBnZXRUeXBlKCkgewogICAgICAgIHJldHVybiB0aGlzLmNpcGhlclR5cGU7CiAgICB9CiAgICBnZXRFbmNyeXB0KCkgewogICAgICAgIHJldHVybiB0aGlzLmVuY3J5cHQ7CiAgICB9CiAgICBnZXRCeXRlc09mVHdvS2V5cygpIHsKICAgICAgICBsZXQgYnVmID0gbmV3IFVpbnQ4QXJyYXkoOCk7CiAgICAgICAgYnVmLnNldChuZXcgVWludDhBcnJheSh0aGlzLmtleTFidWYpLCAwKTsKICAgICAgICBidWYuc2V0KG5ldyBVaW50OEFycmF5KHRoaXMua2V5MmJ1ZiksIDQpOwogICAgICAgIHJldHVybiBidWY7CiAgICB9CiAgICBzdGF0aWMgYmlnVWludE11bHRpcGx5TEUoZHYsIGZhY3RvcikgewogICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIoZHYuYnl0ZUxlbmd0aCArIDQpKTsKICAgICAgICBmYWN0b3IgPSBNYXRoLnRydW5jKGZhY3Rvcik7CiAgICAgICAgQXJyYXkuZnJvbSh7IGxlbmd0aDogZHYuYnl0ZUxlbmd0aCB9LCAoXywgaSkgPT4gZmFjdG9yICogZHYuZ2V0VWludDgoaSkpCiAgICAgICAgICAgIC5mb3JFYWNoKCh2LCBpKSA9PiB7CiAgICAgICAgICAgIHYgKz0gcmVzdWx0LmdldFVpbnQzMihpLCB0cnVlKTsKICAgICAgICAgICAgcmVzdWx0LnNldFVpbnQzMihpLCB2LCB0cnVlKTsKICAgICAgICAgICAgdiAtPSByZXN1bHQuZ2V0VWludDMyKGksIHRydWUpOwogICAgICAgICAgICBpZiAodiA+IDApIHsKICAgICAgICAgICAgICAgIHYgLz0gMHgxMDAwMDAwMDA7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gaSArIDQ7IGogPCByZXN1bHQuYnl0ZUxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgdiArPSByZXN1bHQuZ2V0VWludDgoaik7CiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnNldFVpbnQ4KGosIHYpOwogICAgICAgICAgICAgICAgICAgIHYgLT0gcmVzdWx0LmdldFVpbnQ4KGopOwogICAgICAgICAgICAgICAgICAgIGlmICh2ID4gMCkKICAgICAgICAgICAgICAgICAgICAgICAgdiAvPSAweDEwMDsKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIHN0YXRpYyBtaXhXaXRoU3Via2V5KGtleTEsIGtleTIsIHN1YmtleSkgewogICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS92Z21zdHJlYW0vdmdtc3RyZWFtL2Jsb2IvODRjZmVhZjk5Mzk4MmI0MjQ1Y2U3NTkzZGNiYjY4MTZjNWFlZThiYy9zcmMvY29kaW5nL2hjYV9kZWNvZGVyLmMjTDMxMwogICAgICAgIC8qCiAgICAgICAgICAgIGlmIChzdWJrZXkpIHsKICAgICAgICAgICAgICAgIGtleWNvZGUgPSBrZXljb2RlICogKCAoKHVpbnQ2NF90KXN1YmtleSA8PCAxNnUpIHwgKCh1aW50MTZfdCl+c3Via2V5ICsgMnUpICk7CiAgICAgICAgICAgIH0KICAgICAgICAqLwogICAgICAgIGlmIChzdWJrZXkgPT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIHsga2V5MToga2V5MSwga2V5Mjoga2V5MiB9OwogICAgICAgIGtleTEgPSBIQ0FDaXBoZXIucGFyc2VLZXkoa2V5MSk7CiAgICAgICAga2V5MiA9IEhDQUNpcGhlci5wYXJzZUtleShrZXkyKTsKICAgICAgICBzdWJrZXkgPSBIQ0FDaXBoZXIucGFyc2VLZXkoc3Via2V5KTsKICAgICAgICBjb25zdCBrZXlkdiA9IG5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIoOCkpOwogICAgICAgIGtleWR2LnNldFVpbnQzMigwLCBrZXkxLCB0cnVlKTsKICAgICAgICBrZXlkdi5zZXRVaW50MzIoNCwga2V5MiwgdHJ1ZSk7CiAgICAgICAgY29uc3Qgc3Via2V5ZHYgPSBuZXcgRGF0YVZpZXcobmV3IEFycmF5QnVmZmVyKDQpKTsKICAgICAgICBzdWJrZXlkdi5zZXRVaW50MTYoMiwgc3Via2V5LCB0cnVlKTsKICAgICAgICBpZiAoc3Via2V5ZHYuZ2V0VWludDE2KDIpID09IDApCiAgICAgICAgICAgIHJldHVybiB7IGtleTE6IGtleTEsIGtleTI6IGtleTIgfTsgLy91bmNoYW5nZWQKICAgICAgICBzdWJrZXlkdi5zZXRVaW50MTYoMCwgfnN1YmtleWR2LmdldFVpbnQxNigyLCB0cnVlKSArIDIsIHRydWUpOwogICAgICAgIHN1YmtleSA9IHN1YmtleWR2LmdldFVpbnQzMigwLCB0cnVlKTsKICAgICAgICBjb25zdCBtaXhlZGtleWR2ID0gdGhpcy5iaWdVaW50TXVsdGlwbHlMRShrZXlkdiwgc3Via2V5KTsKICAgICAgICBrZXkxID0gbWl4ZWRrZXlkdi5nZXRVaW50MzIoMCwgdHJ1ZSk7CiAgICAgICAga2V5MiA9IG1peGVka2V5ZHYuZ2V0VWludDMyKDQsIHRydWUpOwogICAgICAgIHJldHVybiB7IGtleTE6IGtleTEsIGtleTI6IGtleTIgfTsKICAgIH0KICAgIHNldEtleXMoa2V5MSwga2V5MikgewogICAgICAgIHRoaXMuZHYxLnNldFVpbnQzMigwLCBrZXkxLCB0cnVlKTsKICAgICAgICB0aGlzLmR2Mi5zZXRVaW50MzIoMCwga2V5MiwgdHJ1ZSk7CiAgICAgICAgdGhpcy5pbml0NTYoKTsKICAgICAgICB0aGlzLmNpcGhlclR5cGUgPSAweDM4OwogICAgICAgIHJldHVybiB0aGlzOwogICAgfQogICAgc2V0VG9EZWZLZXlzKCkgewogICAgICAgIHJldHVybiB0aGlzLnNldEtleXMoSENBQ2lwaGVyLmRlZktleTEsIEhDQUNpcGhlci5kZWZLZXkyKTsKICAgIH0KICAgIHNldFRvTm9LZXkoKSB7CiAgICAgICAgdGhpcy5pbml0MSgpOwogICAgICAgIHRoaXMuY2lwaGVyVHlwZSA9IDB4MDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBtYXNrKGJsb2NrLCBvZmZzZXQsIHNpemUpIHsKICAgICAgICAvLyBlbmNyeXB0IG9yIGRlY3J5cHQgYmxvY2sgZGF0YQogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKQogICAgICAgICAgICBibG9ja1tvZmZzZXQgKyBpXSA9IHRoaXMuX3RhYmxlW2Jsb2NrW29mZnNldCArIGldXTsKICAgIH0KICAgIHN0YXRpYyBpc0hDQUhlYWRlck1hc2tlZChoY2EpIHsKICAgICAgICAvLyBmYXN0ICYgZGlydHkgd2F5IHRvIGRldGVybWluZSB3aGV0aGVyIGVuY3J5cHRlZCwgbm90IHJlY29tbWVuZGVkCiAgICAgICAgaWYgKGhjYVswXSAmIDB4ODAgfHwgaGNhWzFdICYgMHg4MCB8fCBoY2FbMl0gJiAweDgwKQogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHN0YXRpYyBwYXJzZUtleShrZXkpIHsKICAgICAgICBzd2l0Y2ggKHR5cGVvZiBrZXkpIHsKICAgICAgICAgICAgY2FzZSAibnVtYmVyIjoKICAgICAgICAgICAgICAgIHJldHVybiBrZXk7CiAgICAgICAgICAgIGNhc2UgInN0cmluZyI6CiAgICAgICAgICAgICAgICAvLyBhdm9pZCBhbWJpZ3VpdHk6IGFsd2F5cyB0cmVhdCBhcyBoZXgKICAgICAgICAgICAgICAgIGlmICgha2V5Lm1hdGNoKC9eMHgvKSkKICAgICAgICAgICAgICAgICAgICBrZXkgPSAiMHgiICsga2V5OwogICAgICAgICAgICAgICAga2V5ID0gcGFyc2VJbnQoa2V5KTsKICAgICAgICAgICAgICAgIGlmIChpc05hTihrZXkpKQogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiY2Fubm90IHBhcnNlIGFzIGludGVnZXIiKTsKICAgICAgICAgICAgICAgIHJldHVybiBrZXk7CiAgICAgICAgICAgIGNhc2UgIm9iamVjdCI6CiAgICAgICAgICAgICAgICAvLyBhdm9pZCBlbmRpYW5uZXNzIGFtYmlndWl0eTogb25seSBhY2NlcHRpbmcgVWludDhBcnJheSwgdGhlbiByZWFkIGFzIGxpdHRsZSBlbmRpYW4KICAgICAgICAgICAgICAgIGlmIChrZXkgaW5zdGFuY2VvZiBVaW50OEFycmF5ICYmIGtleS5ieXRlTGVuZ3RoID09IDQpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERhdGFWaWV3KGtleS5idWZmZXIsIGtleS5ieXRlT2Zmc2V0LCBrZXkuYnl0ZUxlbmd0aCkuZ2V0VWludDMyKDAsIHRydWUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJjYW4gb25seSBhY2NlcHQgbnVtYmVyL2hleCBzdHJpbmcvVWludDhBcnJheVs0XSIpOwogICAgICAgIH0KICAgIH0KICAgIGNvbnN0cnVjdG9yKGtleTEsIGtleTIpIHsKICAgICAgICB0aGlzLmNpcGhlclR5cGUgPSAwOwogICAgICAgIHRoaXMuZW5jcnlwdCA9IGZhbHNlOwogICAgICAgIHRoaXMua2V5MWJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTsKICAgICAgICB0aGlzLmtleTJidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7CiAgICAgICAgdGhpcy5fdGFibGUgPSBuZXcgVWludDhBcnJheSgyNTYpOwogICAgICAgIHRoaXMuZHYxID0gbmV3IERhdGFWaWV3KHRoaXMua2V5MWJ1Zik7CiAgICAgICAgdGhpcy5kdjIgPSBuZXcgRGF0YVZpZXcodGhpcy5rZXkyYnVmKTsKICAgICAgICBpZiAoa2V5MSA9PSBudWxsKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIm5vIGtleXMgZ2l2ZW4uIHVzZSBcImRlZmF1bHRrZXlcIiBpZiB5b3Ugd2FudCB0byB1c2UgdGhlIGRlZmF1bHQga2V5Iik7CiAgICAgICAgc3dpdGNoIChrZXkxKSB7CiAgICAgICAgICAgIGNhc2UgIm5vbmUiOgogICAgICAgICAgICBjYXNlICJub2tleSI6CiAgICAgICAgICAgIGNhc2UgIm5vS2V5IjoKICAgICAgICAgICAgY2FzZSAibm8ga2V5IjoKICAgICAgICAgICAgY2FzZSAibm9fS2V5IjoKICAgICAgICAgICAgICAgIHRoaXMuc2V0VG9Ob0tleSgpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImRlZmF1bHRrZXkiOgogICAgICAgICAgICBjYXNlICJkZWZhdWx0S2V5IjoKICAgICAgICAgICAgY2FzZSAiZGVmYXVsdCBrZXkiOgogICAgICAgICAgICBjYXNlICJkZWZhdWx0X2tleSI6CiAgICAgICAgICAgICAgICB0aGlzLnNldFRvRGVmS2V5cygpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBrZXkxID0gSENBQ2lwaGVyLnBhcnNlS2V5KGtleTEpOwogICAgICAgICAgICAgICAgaWYgKGtleTIgPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgIGtleTIgPSAwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAga2V5MiA9IEhDQUNpcGhlci5wYXJzZUtleShrZXkyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRoaXMuc2V0S2V5cyhrZXkxLCBrZXkyKTsKICAgICAgICB9CiAgICB9Cn0KSENBQ2lwaGVyLmRlZktleTEgPSAweDAxMzk1QzUxOwpIQ0FDaXBoZXIuZGVmS2V5MiA9IDB4MDAwMDAwMDA7Ci8vIGh0dHBzOi8vZ2l0aHViLmNvbS92Z21zdHJlYW0vdmdtc3RyZWFtL2Jsb2IvNGVlY2RhZGE5YTAzYTczYWYwYzdjMTdmNWNkNmUwODUxOGZkN2UzZi9zcmMvbWV0YS9hd2IuYyNMMTMKZXhwb3J0IGNsYXNzIEFXQkFyY2hpdmUgewogICAgc3RhdGljIGlzQVdCKGZpbGUpIHsKICAgICAgICBjb25zdCBkdiA9IG5ldyBEYXRhVmlldyhmaWxlLmJ1ZmZlciwgZmlsZS5ieXRlT2Zmc2V0LCBmaWxlLmJ5dGVMZW5ndGgpOwogICAgICAgIGNvbnN0IG1hZ2ljID0gMHg0MTQ2NTMzMjsgLy8gIkFGUzIiIGluIFVpbnQzMkJFCiAgICAgICAgcmV0dXJuIGR2LmdldFVpbnQzMigwLCBmYWxzZSkgPT0gbWFnaWM7CiAgICB9CiAgICBjb25zdHJ1Y3Rvcihhd2IpIHsKICAgICAgICBpZiAoIUFXQkFyY2hpdmUuaXNBV0IoYXdiKSkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3QgQVdCIGFyY2hpdmVgKTsKICAgICAgICBjb25zdCBkdiA9IG5ldyBEYXRhVmlldyhhd2IuYnVmZmVyLCBhd2IuYnl0ZU9mZnNldCwgYXdiLmJ5dGVMZW5ndGgpOwogICAgICAgIHRoaXMudmVyc2lvbiA9IGR2LmdldFVpbnQ4KDB4MDQpOwogICAgICAgIHRoaXMub2Zmc2V0U2l6ZSA9IGR2LmdldFVpbnQ4KDB4MDUpOwogICAgICAgIHRoaXMud2F2ZUlkQWxpZ25tZW50ID0gZHYuZ2V0VWludDE2KDB4MDYsIHRydWUpOwogICAgICAgIHRoaXMudG90YWxTdWJzb25ncyA9IGR2LmdldEludDMyKDB4MDgsIHRydWUpOwogICAgICAgIHRoaXMub2Zmc2V0QWxpZ25tZW50ID0gZHYuZ2V0VWludDE2KDB4MGMsIHRydWUpOwogICAgICAgIHRoaXMuc3Via2V5ID0gZHYuZ2V0VWludDE2KDB4MGUsIHRydWUpOwogICAgICAgIGxldCBmdGVsbCA9IDB4MTA7CiAgICAgICAgdGhpcy5oY2FGaWxlcyA9IEFycmF5LmZyb20oeyBsZW5ndGg6IHRoaXMudG90YWxTdWJzb25ncyB9LCAoKSA9PiB7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IGZ0ZWxsOwogICAgICAgICAgICBmdGVsbCArPSB0aGlzLndhdmVJZEFsaWdubWVudDsKICAgICAgICAgICAgcmV0dXJuIHsgd2F2ZUlEOiBkdi5nZXRVaW50MTYob2Zmc2V0LCB0cnVlKSB9OwogICAgICAgIH0pLm1hcCgobykgPT4gewogICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBmdGVsbDsKICAgICAgICAgICAgZnRlbGwgKz0gdGhpcy5vZmZzZXRTaXplICogMjsKICAgICAgICAgICAgc3dpdGNoICh0aGlzLm9mZnNldFNpemUpIHsKICAgICAgICAgICAgICAgIGNhc2UgMHgwNDoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICB3YXZlSUQ6IG8ud2F2ZUlELAogICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IGR2LmdldFVpbnQzMihvZmZzZXQsIHRydWUpLAogICAgICAgICAgICAgICAgICAgICAgICBuZXh0OiBkdi5nZXRVaW50MzIob2Zmc2V0ICsgdGhpcy5vZmZzZXRTaXplLCB0cnVlKSwKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgY2FzZSAweDAyOgogICAgICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgICAgIHdhdmVJRDogby53YXZlSUQsCiAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldDogZHYuZ2V0VWludDE2KG9mZnNldCwgdHJ1ZSksCiAgICAgICAgICAgICAgICAgICAgICAgIG5leHQ6IGR2LmdldFVpbnQxNihvZmZzZXQgKyB0aGlzLm9mZnNldFNpemUsIHRydWUpLAogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQVdCOiB1bmtub3duIG9mZnNldCBzaXplYCk7CiAgICAgICAgICAgIH0KICAgICAgICB9KS5tYXAoKG8pID0+IHsKICAgICAgICAgICAgLy8gb2Zmc2V0IGFyZSBhYnNvbHV0ZSBidXQgc29tZXRpbWVzIG1pc2FsaWduZWQgKHNwZWNpYWxseSBmaXJzdCB0aGF0IGp1c3QgcG9pbnRzIHRvIG9mZnNldCB0YWJsZSBlbmQpCiAgICAgICAgICAgIG8ub2Zmc2V0ICs9IChvLm9mZnNldCAlIHRoaXMub2Zmc2V0QWxpZ25tZW50KSA/CiAgICAgICAgICAgICAgICB0aGlzLm9mZnNldEFsaWdubWVudCAtIChvLm9mZnNldCAlIHRoaXMub2Zmc2V0QWxpZ25tZW50KSA6IDA7CiAgICAgICAgICAgIG8ubmV4dCArPSAoby5uZXh0ICUgdGhpcy5vZmZzZXRBbGlnbm1lbnQpICYmIG8ubmV4dCA8IGF3Yi5ieXRlTGVuZ3RoID8KICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0QWxpZ25tZW50IC0gKG8ubmV4dCAlIHRoaXMub2Zmc2V0QWxpZ25tZW50KSA6IDA7CiAgICAgICAgICAgIHJldHVybiB7IHdhdmVJRDogby53YXZlSUQsIGZpbGU6IGF3Yi5zdWJhcnJheShvLm9mZnNldCwgby5uZXh0KSB9OwogICAgICAgIH0pOwogICAgfQp9CmNvbnN0IHN1c3BlbmRBdWRpb0N0eElmVW5sb2NrZWQgPSAoYXVkaW9DdHgpID0+IF9fYXdhaXRlcih2b2lkIDAsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgLy8gc3VzcGVuZCBhdWRpbyBjb250ZXh0IGZvciBub3cKICAgIC8vIGluIGFwcGxlIHdlYmtpdCBpdCdzIGFscmVhZHkgc3VzcGVuZGVkICYgY2FsbGluZyBzdXNwZW5kIHlldCBhZ2FpbiB3aWxsIGJsb2NrCiAgICBzd2l0Y2ggKGF1ZGlvQ3R4LnN0YXRlKSB7CiAgICAgICAgY2FzZSAicnVubmluZyI6CiAgICAgICAgICAgIHlpZWxkIGF1ZGlvQ3R4LnN1c3BlbmQoKTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgY2FzZSAic3VzcGVuZGVkIjoKICAgICAgICAgICAgY29uc29sZS53YXJuKGBhdWRpbyBjb250ZXh0IGZvciBzYW1wbGVSYXRlPSR7YXVkaW9DdHguc2FtcGxlUmF0ZX0gaXMgc3VzcGVuZGVkL2xvY2tlZCxgCiAgICAgICAgICAgICAgICArIGAgd2hpY2ggY2FuIG9ubHkgYmUgcmVzdW1lZC91bmxvY2tlZCBieSBVSSBldmVudC5gKTsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgYXVkaW8gY29udGV4dCBpcyBuZWl0aGVyIHJ1bm5pbmcgbm9yIHN1c3BlbmRlZGApOwogICAgfQp9KTsKLy8gV2ViQXVkaW8tYmFzZWQgbG9vcCBwbGF5ZXIKZXhwb3J0IGNsYXNzIEhDQVdlYkF1ZGlvTG9vcFBsYXllciB7CiAgICBnZXQgdW5sb2NrZWQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3VubG9ja2VkOwogICAgfQogICAgZ2V0IHZvbHVtZSgpIHsKICAgICAgICByZXR1cm4gdGhpcy5nYWluTm9kZS5nYWluLnZhbHVlOwogICAgfQogICAgc2V0IHZvbHVtZSh2YWwpIHsKICAgICAgICBpZiAoaXNOYU4odmFsKSkKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIGlmICh2YWwgPiAxLjApCiAgICAgICAgICAgIHZhbCA9IDEuMDsKICAgICAgICBpZiAodmFsIDwgMCkKICAgICAgICAgICAgdmFsID0gMDsKICAgICAgICB0aGlzLmdhaW5Ob2RlLmdhaW4udmFsdWUgPSB2YWw7CiAgICB9CiAgICBjb25zdHJ1Y3RvcihpbmZvLCBidWZTcmMsIGF1ZGlvQ3R4LCB1bmxvY2tlZCwgZ2Fpbk5vZGUsIHZvbHVtZSkgewogICAgICAgIHRoaXMuYnVmU3JjU3RhcnRlZCA9IGZhbHNlOwogICAgICAgIHRoaXMuY2xvc2VkID0gZmFsc2U7CiAgICAgICAgdGhpcy5wbGF5SW5CYWNrZ3JvdW5kID0gZmFsc2U7IC8vIEZJWE1FCiAgICAgICAgdGhpcy5yZXF1ZXN0ZWRUb1BsYXkgPSBmYWxzZTsKICAgICAgICB0aGlzLnZpc2liaWxpdHlDaGFuZ2VMaXN0ZW5lciA9ICgpID0+IHsKICAgICAgICAgICAgc3dpdGNoIChkb2N1bWVudC52aXNpYmlsaXR5U3RhdGUpIHsKICAgICAgICAgICAgICAgIGNhc2UgJ3Zpc2libGUnOgogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlcXVlc3RlZFRvUGxheSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wbGF5KCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAnaGlkZGVuJzoKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnBsYXlJbkJhY2tncm91bmQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGF1c2UoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHRoaXMuaW5mbyA9IGluZm87CiAgICAgICAgdGhpcy5idWZTcmMgPSBidWZTcmM7CiAgICAgICAgdGhpcy5hdWRpb0N0eCA9IGF1ZGlvQ3R4OwogICAgICAgIHRoaXMuX3VubG9ja2VkID0gdW5sb2NrZWQ7CiAgICAgICAgdGhpcy5nYWluTm9kZSA9IGdhaW5Ob2RlOwogICAgICAgIHRoaXMudm9sdW1lID0gdm9sdW1lOwogICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Zpc2liaWxpdHljaGFuZ2UnLCB0aGlzLnZpc2liaWxpdHlDaGFuZ2VMaXN0ZW5lcik7CiAgICB9CiAgICBzdGF0aWMgY3JlYXRlKGRlY3J5cHRlZCwgd29ya2VyLCB2b2x1bWUgPSAxMDApIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICBjb25zdCBpbmZvID0gbmV3IEhDQUluZm8oZGVjcnlwdGVkKTsKICAgICAgICAgICAgaWYgKGluZm8uY2lwaGVyICE9IDApCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIm9ubHkgZGVjcnlwdGVkIGhjYSBpcyBhY2NlcHRlZCIpOwogICAgICAgICAgICBjb25zdCBhdWRpb0N0eCA9IG5ldyBBdWRpb0NvbnRleHQoewogICAgICAgICAgICAgICAgc2FtcGxlUmF0ZTogaW5mby5mb3JtYXQuc2FtcGxpbmdSYXRlLAogICAgICAgICAgICB9KTsKICAgICAgICAgICAgY29uc3Qgd2F2ID0geWllbGQgd29ya2VyLmRlY29kZShkZWNyeXB0ZWQsIDE2KTsgLy8gZmlyc3QKICAgICAgICAgICAgY29uc3QgdW5sb2NrZWQgPSB5aWVsZCBzdXNwZW5kQXVkaW9DdHhJZlVubG9ja2VkKGF1ZGlvQ3R4KTsKICAgICAgICAgICAgY29uc3QgYnVmZmVyID0geWllbGQgYXVkaW9DdHguZGVjb2RlQXVkaW9EYXRhKHdhdi5idWZmZXIpOwogICAgICAgICAgICBjb25zdCBidWZTcmMgPSBhdWRpb0N0eC5jcmVhdGVCdWZmZXJTb3VyY2UoKTsKICAgICAgICAgICAgYnVmU3JjLmJ1ZmZlciA9IGJ1ZmZlcjsKICAgICAgICAgICAgaWYgKGluZm8ubG9vcCAhPSBudWxsICYmIGluZm8ubG9vcC5lbmQgPiBpbmZvLmxvb3Auc3RhcnQpIHsKICAgICAgICAgICAgICAgIGJ1ZlNyYy5sb29wU3RhcnQgPSBpbmZvLmxvb3BTdGFydFRpbWU7CiAgICAgICAgICAgICAgICBidWZTcmMubG9vcEVuZCA9IGluZm8ubG9vcEVuZFRpbWU7CiAgICAgICAgICAgICAgICBidWZTcmMubG9vcCA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgZ2Fpbk5vZGUgPSBhdWRpb0N0eC5jcmVhdGVHYWluKCk7CiAgICAgICAgICAgIGJ1ZlNyYy5jb25uZWN0KGdhaW5Ob2RlKTsKICAgICAgICAgICAgZ2Fpbk5vZGUuY29ubmVjdChhdWRpb0N0eC5kZXN0aW5hdGlvbik7CiAgICAgICAgICAgIHJldHVybiBuZXcgSENBV2ViQXVkaW9Mb29wUGxheWVyKGluZm8sIGJ1ZlNyYywgYXVkaW9DdHgsIHVubG9ja2VkLCBnYWluTm9kZSwgdm9sdW1lKTsKICAgICAgICB9KTsKICAgIH0KICAgIC8vIG5vdCBzdXBwb3NlZCB0byBiZSB1c2VkIGRpcmVjdGx5CiAgICBfcGxheSgpIHsKICAgICAgICBpZiAodGhpcy5hdWRpb0N0eC5zdGF0ZSAhPT0gInJ1bm5pbmciKQogICAgICAgICAgICB0aGlzLmF1ZGlvQ3R4LnJlc3VtZSgpOwogICAgICAgIGlmICghdGhpcy5idWZTcmNTdGFydGVkKSB7CiAgICAgICAgICAgIHRoaXMuYnVmU3JjLnN0YXJ0KCk7CiAgICAgICAgICAgIHRoaXMuYnVmU3JjU3RhcnRlZCA9IHRydWU7CiAgICAgICAgfQogICAgICAgIC8vIG1hcmsgYXMgdW5sb2NrZWQKICAgICAgICBpZiAoIXRoaXMuX3VubG9ja2VkKSB7CiAgICAgICAgICAgIHRoaXMuX3VubG9ja2VkID0gdHJ1ZTsKICAgICAgICAgICAgY29uc29sZS53YXJuKGBhdWRpbyBjb250ZXh0IGZvciBzYW1wbGVSYXRlPSR7dGhpcy5hdWRpb0N0eC5zYW1wbGVSYXRlfSBpcyBub3cgcmVzdW1lZC91bmxvY2tlZGApOwogICAgICAgIH0KICAgIH0KICAgIF9wYXVzZSgpIHsKICAgICAgICBpZiAodGhpcy5hdWRpb0N0eC5zdGF0ZSAhPT0gInJ1bm5pbmciKQogICAgICAgICAgICByZXR1cm47CiAgICAgICAgdGhpcy5hdWRpb0N0eC5zdXNwZW5kKCk7CiAgICB9CiAgICBwbGF5KCkgewogICAgICAgIHRoaXMucmVxdWVzdGVkVG9QbGF5ID0gdHJ1ZTsKICAgICAgICB0aGlzLl9wbGF5KCk7CiAgICB9CiAgICBwYXVzZSgpIHsKICAgICAgICB0aGlzLnJlcXVlc3RlZFRvUGxheSA9IGZhbHNlOwogICAgICAgIHRoaXMuX3BhdXNlKCk7CiAgICB9CiAgICBzdG9wKCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIGlmICghdGhpcy5fdW5sb2NrZWQpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImF1ZGlvIGNvbnRleHQgaXMgbm90IHVubG9ja2VkLCBjYW5ub3Qgc3RvcCBhbmQgZGVzdHJveSIpOwogICAgICAgICAgICBpZiAodGhpcy5jbG9zZWQpCiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd2aXNpYmlsaXR5Y2hhbmdlJywgdGhpcy52aXNpYmlsaXR5Q2hhbmdlTGlzdGVuZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMucmVxdWVzdGVkVG9QbGF5ID0gZmFsc2U7CiAgICAgICAgICAgIHRoaXMuYnVmU3JjLmRpc2Nvbm5lY3QoKTsKICAgICAgICAgICAgeWllbGQgdGhpcy5hdWRpb0N0eC5jbG9zZSgpOwogICAgICAgICAgICB0aGlzLmNsb3NlZCA9IHRydWU7CiAgICAgICAgfSk7CiAgICB9Cn0KLy8gY29udmVydCBub24tdHJhbnNmZXJhYmxlIHR5cGVkIGFycmF5IHRvIHRyYW5zZmVyYWJsZSBhcnJheSBidWZmZXIKY2xhc3MgSENBVHJhbnNUeXBlZEFycmF5IHsKICAgIHN0YXRpYyBjb252ZXJ0KGFyZywgdHJhbnNmZXJMaXN0KSB7CiAgICAgICAgaWYgKHRoaXMuZ2V0VHlwZShhcmcpICE9IG51bGwpCiAgICAgICAgICAgIHJldHVybiBuZXcgSENBVHJhbnNUeXBlZEFycmF5KGFyZywgdHJhbnNmZXJMaXN0KTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiBhcmc7CiAgICB9CiAgICBzdGF0aWMgcmVzdG9yZShhcmcpIHsKICAgICAgICBjb25zdCB0eXBlID0gdGhpcy5nZXRUeXBlKGFyZyk7CiAgICAgICAgaWYgKHR5cGUgIT0gbnVsbCAmJiB0eXBlLmNvbnZlcnRlZCkKICAgICAgICAgICAgcmV0dXJuIGFyZy5hcnJheTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiBhcmc7CiAgICB9CiAgICBzdGF0aWMgZ2V0VHlwZShhcmcpIHsKICAgICAgICBpZiAoYXJnID09IG51bGwgfHwgdHlwZW9mIGFyZyAhPT0gIm9iamVjdCIpCiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICAgICAgZWxzZSBpZiAoYXJnIGluc3RhbmNlb2YgSW50OEFycmF5KQogICAgICAgICAgICByZXR1cm4geyBjb252ZXJ0ZWQ6IGZhbHNlLCB0eXBlOiAiSW50OCIgfTsKICAgICAgICBlbHNlIGlmIChhcmcgaW5zdGFuY2VvZiBJbnQxNkFycmF5KQogICAgICAgICAgICByZXR1cm4geyBjb252ZXJ0ZWQ6IGZhbHNlLCB0eXBlOiAiSW50MTYiIH07CiAgICAgICAgZWxzZSBpZiAoYXJnIGluc3RhbmNlb2YgSW50MzJBcnJheSkKICAgICAgICAgICAgcmV0dXJuIHsgY29udmVydGVkOiBmYWxzZSwgdHlwZTogIkludDMyIiB9OwogICAgICAgIGVsc2UgaWYgKGFyZyBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpCiAgICAgICAgICAgIHJldHVybiB7IGNvbnZlcnRlZDogZmFsc2UsIHR5cGU6ICJVaW50OCIgfTsKICAgICAgICBlbHNlIGlmIChhcmcgaW5zdGFuY2VvZiBVaW50MTZBcnJheSkKICAgICAgICAgICAgcmV0dXJuIHsgY29udmVydGVkOiBmYWxzZSwgdHlwZTogIlVpbnQxNiIgfTsKICAgICAgICBlbHNlIGlmIChhcmcgaW5zdGFuY2VvZiBVaW50MzJBcnJheSkKICAgICAgICAgICAgcmV0dXJuIHsgY29udmVydGVkOiBmYWxzZSwgdHlwZTogIlVpbnQzMiIgfTsKICAgICAgICBlbHNlIGlmIChhcmcgaW5zdGFuY2VvZiBGbG9hdDMyQXJyYXkpCiAgICAgICAgICAgIHJldHVybiB7IGNvbnZlcnRlZDogZmFsc2UsIHR5cGU6ICJGbG9hdDMyIiB9OwogICAgICAgIGVsc2UgaWYgKGFyZyBpbnN0YW5jZW9mIEZsb2F0NjRBcnJheSkKICAgICAgICAgICAgcmV0dXJuIHsgY29udmVydGVkOiBmYWxzZSwgdHlwZTogIkZsb2F0NjQiIH07CiAgICAgICAgZWxzZSBpZiAoYXJnLmJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyICYmIHR5cGVvZiBhcmcudHlwZSA9PT0gInN0cmluZyIpCiAgICAgICAgICAgIHJldHVybiB7IGNvbnZlcnRlZDogdHJ1ZSwgdHlwZTogYXJnLnR5cGUgfTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICBjb25zdHJ1Y3Rvcih0YSwgdHJhbnNmZXJMaXN0KSB7CiAgICAgICAgY29uc3QgdHlwZSA9IEhDQVRyYW5zVHlwZWRBcnJheS5nZXRUeXBlKHRhKTsKICAgICAgICBpZiAodHlwZSAhPSBudWxsKQogICAgICAgICAgICB0aGlzLnR5cGUgPSB0eXBlLnR5cGU7CiAgICAgICAgZWxzZQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoInVuZXhwZWN0ZWQgdHlwZSIpOwogICAgICAgIHRoaXMuYnVmZmVyID0gdGEuYnVmZmVyOwogICAgICAgIHRoaXMuYnl0ZU9mZnNldCA9IHRhLmJ5dGVPZmZzZXQ7CiAgICAgICAgdGhpcy5sZW5ndGggPSB0YS5sZW5ndGg7CiAgICAgICAgaWYgKCF0cmFuc2Zlckxpc3QuZmluZCgodmFsKSA9PiB2YWwgPT09IHRoaXMuYnVmZmVyKSkKICAgICAgICAgICAgdHJhbnNmZXJMaXN0LnB1c2godGhpcy5idWZmZXIpOwogICAgfQogICAgZ2V0IGFycmF5KCkgewogICAgICAgIHN3aXRjaCAodGhpcy50eXBlKSB7CiAgICAgICAgICAgIGNhc2UgIkludDgiOiByZXR1cm4gbmV3IEludDhBcnJheSh0aGlzLmJ1ZmZlciwgdGhpcy5ieXRlT2Zmc2V0LCB0aGlzLmxlbmd0aCk7CiAgICAgICAgICAgIGNhc2UgIkludDE2IjogcmV0dXJuIG5ldyBJbnQxNkFycmF5KHRoaXMuYnVmZmVyLCB0aGlzLmJ5dGVPZmZzZXQsIHRoaXMubGVuZ3RoKTsKICAgICAgICAgICAgY2FzZSAiSW50MzIiOiByZXR1cm4gbmV3IEludDMyQXJyYXkodGhpcy5idWZmZXIsIHRoaXMuYnl0ZU9mZnNldCwgdGhpcy5sZW5ndGgpOwogICAgICAgICAgICBjYXNlICJVaW50OCI6IHJldHVybiBuZXcgVWludDhBcnJheSh0aGlzLmJ1ZmZlciwgdGhpcy5ieXRlT2Zmc2V0LCB0aGlzLmxlbmd0aCk7CiAgICAgICAgICAgIGNhc2UgIlVpbnQxNiI6IHJldHVybiBuZXcgVWludDE2QXJyYXkodGhpcy5idWZmZXIsIHRoaXMuYnl0ZU9mZnNldCwgdGhpcy5sZW5ndGgpOwogICAgICAgICAgICBjYXNlICJVaW50MzIiOiByZXR1cm4gbmV3IFVpbnQzMkFycmF5KHRoaXMuYnVmZmVyLCB0aGlzLmJ5dGVPZmZzZXQsIHRoaXMubGVuZ3RoKTsKICAgICAgICAgICAgY2FzZSAiRmxvYXQzMiI6IHJldHVybiBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYnVmZmVyLCB0aGlzLmJ5dGVPZmZzZXQsIHRoaXMubGVuZ3RoKTsKICAgICAgICAgICAgY2FzZSAiRmxvYXQ2NCI6IHJldHVybiBuZXcgRmxvYXQ2NEFycmF5KHRoaXMuYnVmZmVyLCB0aGlzLmJ5dGVPZmZzZXQsIHRoaXMubGVuZ3RoKTsKICAgICAgICB9CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJ1bmV4cGVjdGVkIHR5cGUiKTsKICAgIH0KfQpjbGFzcyBIQ0FUYXNrIHsKICAgIGdldCBhcmdzKCkgewogICAgICAgIHZhciBfYzsKICAgICAgICByZXR1cm4gKF9jID0gdGhpcy5fYXJncykgPT09IG51bGwgfHwgX2MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jLm1hcCgoYXJnKSA9PiBIQ0FUcmFuc1R5cGVkQXJyYXkucmVzdG9yZShhcmcpKTsKICAgIH0KICAgIGdldCBoYXNSZXN1bHQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2hhc1Jlc3VsdDsKICAgIH0KICAgIGdldCByZXN1bHQoKSB7CiAgICAgICAgaWYgKCF0aGlzLl9oYXNSZXN1bHQpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigibm8gcmVzdWx0Iik7CiAgICAgICAgcmV0dXJuIEhDQVRyYW5zVHlwZWRBcnJheS5yZXN0b3JlKHRoaXMuX3Jlc3VsdCk7CiAgICB9CiAgICBzZXQgcmVzdWx0KHJlc3VsdCkgewogICAgICAgIGlmICh0aGlzLmhhc0VycikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJhbHJlYWR5IGhhcyBlcnJvciwgY2Fubm90IHNldCByZXN1bHQiKTsKICAgICAgICBpZiAodGhpcy5faGFzUmVzdWx0KQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImNhbm5vdCBzZXQgcmVzdWx0IGFnYWluIik7CiAgICAgICAgdGhpcy5fcmVzdWx0ID0gSENBVHJhbnNUeXBlZEFycmF5LmNvbnZlcnQocmVzdWx0LCB0aGlzLnRyYW5zZmVyTGlzdCk7CiAgICAgICAgdGhpcy5faGFzUmVzdWx0ID0gdHJ1ZTsKICAgICAgICBpZiAoIXRoaXMuX3JlcGx5QXJncykKICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2FyZ3M7CiAgICB9CiAgICBnZXQgaGFzRXJyKCkgewogICAgICAgIHJldHVybiB0aGlzLl9lcnJNc2cgIT0gbnVsbDsKICAgIH0KICAgIGdldCBlcnJNc2coKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2Vyck1zZzsKICAgIH0KICAgIHNldCBlcnJNc2cobXNnKSB7CiAgICAgICAgLy8gY2hhbmdpbmcgZXJyTXNnIGlzIGFsbG93ZWQsIGJ1dCBjbGVhcmluZyBlcnJNc2cgaXMgZGlzYWxsb3dlZAogICAgICAgIGlmICh0eXBlb2YgbXNnICE9PSAic3RyaW5nIikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJlcnJvciBtZXNzYWdlIG11c3QgYmUgYSBzdHJpbmciKTsKICAgICAgICBkZWxldGUgdGhpcy5fYXJnczsKICAgICAgICBpZiAodGhpcy5faGFzUmVzdWx0KSB7CiAgICAgICAgICAgIC8vIGNsZWFyIHJlc3VsdCBvbiBlcnJvcgogICAgICAgICAgICBkZWxldGUgdGhpcy5fcmVzdWx0OwogICAgICAgICAgICB0aGlzLl9oYXNSZXN1bHQgPSBmYWxzZTsKICAgICAgICAgICAgdGhpcy50cmFuc2Zlckxpc3QgPSBbXTsKICAgICAgICAgICAgdGhpcy5hcmdzLmZvckVhY2goKGFyZykgPT4gSENBVHJhbnNUeXBlZEFycmF5LmNvbnZlcnQoYXJnLCB0aGlzLnRyYW5zZmVyTGlzdCkpOwogICAgICAgIH0KICAgICAgICB0aGlzLl9lcnJNc2cgPSBtc2c7CiAgICB9CiAgICBjb25zdHJ1Y3RvcihvcmlnaW4sIHRhc2tJRCwgY21kLCBhcmdzLCByZXBseUFyZ3MsIGlzRHVtbXkpIHsKICAgICAgICB0aGlzLnRyYW5zZmVyTGlzdCA9IFtdOwogICAgICAgIHRoaXMuX2hhc1Jlc3VsdCA9IGZhbHNlOwogICAgICAgIHRoaXMub3JpZ2luID0gb3JpZ2luOwogICAgICAgIHRoaXMudGFza0lEID0gdGFza0lEOwogICAgICAgIHRoaXMuY21kID0gY21kOwogICAgICAgIHRoaXMuX2FyZ3MgPSBhcmdzID09PSBudWxsIHx8IGFyZ3MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGFyZ3MubWFwKChhcmcpID0+IEhDQVRyYW5zVHlwZWRBcnJheS5jb252ZXJ0KGFyZywgdGhpcy50cmFuc2Zlckxpc3QpKTsKICAgICAgICB0aGlzLl9yZXBseUFyZ3MgPSByZXBseUFyZ3M7CiAgICAgICAgaWYgKGlzRHVtbXkgIT0gbnVsbCAmJiBpc0R1bW15KQogICAgICAgICAgICB0aGlzLmlzRHVtbXkgPSB0cnVlOwogICAgfQogICAgc3RhdGljIHJlY3JlYXRlKHRhc2spIHsKICAgICAgICBjb25zdCByZWNyZWF0ZWQgPSBuZXcgSENBVGFzayh0YXNrLm9yaWdpbiwgdGFzay50YXNrSUQsIHRhc2suY21kLCB0YXNrLl9hcmdzLCB0YXNrLl9yZXBseUFyZ3MpOwogICAgICAgIGlmICh0YXNrLl9lcnJNc2cgIT0gbnVsbCkKICAgICAgICAgICAgcmVjcmVhdGVkLmVyck1zZyA9IHRhc2suX2Vyck1zZzsKICAgICAgICBlbHNlIGlmICh0YXNrLl9oYXNSZXN1bHQpCiAgICAgICAgICAgIHJlY3JlYXRlZC5yZXN1bHQgPSB0YXNrLl9yZXN1bHQ7CiAgICAgICAgcmV0dXJuIHJlY3JlYXRlZDsKICAgIH0KfQpjbGFzcyBIQ0FUYXNrUXVldWUgewogICAgZ2V0TmV4dFRhc2tJRCgpIHsKICAgICAgICBjb25zdCBtYXggPSBIQ0FUYXNrUXVldWUubWF4VGFza0lEIC0gMTsKICAgICAgICBpZiAodGhpcy5fbGFzdFRhc2tJRCA8IDAgfHwgdGhpcy5fbGFzdFRhc2tJRCA+IG1heCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJsYXN0VGFza0lEIG91dCBvZiByYW5nZSIpOwogICAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5fbGFzdFRhc2tJRCArIDE7CiAgICAgICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDw9IHN0YXJ0ICsgbWF4OyBpKyspIHsKICAgICAgICAgICAgY29uc3QgdGFza0lEID0gaSAlIChtYXggKyAxKTsKICAgICAgICAgICAgaWYgKHRoaXMuY2FsbGJhY2tzW3Rhc2tJRF0gPT0gbnVsbCkKICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9sYXN0VGFza0lEID0gdGFza0lEOwogICAgICAgIH0KICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImNhbm5vdCBmaW5kIG5leHQgdGFza0lEIik7CiAgICB9CiAgICBzZW5kVGFzayh0YXNrKSB7CiAgICAgICAgaWYgKHRhc2sub3JpZ2luICE9PSB0aGlzLm9yaWdpbikKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJ0aGUgdGFzayB0byBiZSBzZW50IG11c3QgaGF2ZSB0aGUgc2FtZSBvcmlnaW4gYXMgdGhlIHRhc2sgcXVldWUiKTsKICAgICAgICB0aGlzLnBvc3RNZXNzYWdlKHRhc2ssIHRoaXMudHJhbnNmZXJBcmdzID8gdGFzay50cmFuc2Zlckxpc3QgOiBbXSk7CiAgICB9CiAgICBzZW5kUmVwbHkodGFzaykgewogICAgICAgIGlmICh0YXNrLm9yaWdpbiA9PT0gdGhpcy5vcmlnaW4pCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigidGhlIHJlcGx5IHRvIGJlIHNlbnQgbXVzdCBub3QgaGF2ZSB0aGUgc2FtZSBvcmlnaW4gYXMgdGhlIHRhc2sgcXVldWUiKTsKICAgICAgICB0aGlzLnBvc3RNZXNzYWdlKHRhc2ssIHRhc2sudHJhbnNmZXJMaXN0KTsgLy8gYWx3YXlzIHVzZSB0cmFuc2ZlcnJpbmcgdG8gc2VuZCBiYWNrIGFyZ3VtZW50cwogICAgfQogICAgc2VuZE5leHRUYXNrKCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIGxldCB0YXNrID0gdGhpcy5xdWV1ZS5zaGlmdCgpOwogICAgICAgICAgICBpZiAodGFzayA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICB0aGlzLmlzSWRsZSA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB0aGlzLmlzSWRsZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgLy8gYXBwbHkgaG9vayBmaXJzdAogICAgICAgICAgICAgICAgY29uc3QgcmVnaXN0ZXJlZCA9IHRoaXMuY2FsbGJhY2tzW3Rhc2sudGFza0lEXTsKICAgICAgICAgICAgICAgIGNvbnN0IHRhc2tIb29rID0gcmVnaXN0ZXJlZCAhPSBudWxsICYmIHJlZ2lzdGVyZWQuaG9vayAhPSBudWxsICYmIHJlZ2lzdGVyZWQuaG9vay50YXNrICE9IG51bGwKICAgICAgICAgICAgICAgICAgICA/IHJlZ2lzdGVyZWQuaG9vay50YXNrCiAgICAgICAgICAgICAgICAgICAgOiB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICBpZiAodGFza0hvb2sgIT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICB0YXNrID0geWllbGQgdGFza0hvb2sodGFzayk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suZXJyTXNnID0gYFske3RoaXMub3JpZ2lufV0gZXJyb3Igd2hlbiBhcHBseWluZyBob29rIGAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgYGJlZm9yZSBleGVjdXRpbmcgY21kICR7dGFzay5jbWR9IGZyb20gJHt0YXNrLm9yaWdpbn1gOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGUgPT09ICJzdHJpbmciIHx8IGUgaW5zdGFuY2VvZiBFcnJvcikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suZXJyTXNnICs9ICJcbiIgKyBlLnRvU3RyaW5nKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suaXNEdW1teSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gc2VuZCB0YXNrCiAgICAgICAgICAgICAgICBpZiAodGFzay5pc0R1bW15KSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YXNrLmhhc0VyciAmJiAhdGFzay5oYXNSZXN1bHQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2sucmVzdWx0ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBldiA9IG5ldyBNZXNzYWdlRXZlbnQoIm1lc3NhZ2UiLCB7IGRhdGE6IHRhc2sgfSk7IC8vIG5vdCBhY3R1YWxseSBzZW5kaW5nLCB1c2UgYSBmYWtlIHJlcGx5CiAgICAgICAgICAgICAgICAgICAgdGhpcy5tc2dIYW5kbGVyKGV2KTsgLy8gd29uJ3QgYXdhaXQKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIHRoaXMuc2VuZFRhc2sodGFzayk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgIH0KICAgIGNvbnN0cnVjdG9yKG9yaWdpbiwgcG9zdE1lc3NhZ2UsIHRhc2tIYW5kbGVyLCBkZXN0cm95KSB7CiAgICAgICAgdGhpcy5faXNBbGl2ZSA9IHRydWU7CiAgICAgICAgdGhpcy5pc0lkbGUgPSB0cnVlOwogICAgICAgIC8vIGNvbXBhcmluZyB0byBzdHJ1Y3R1cmVkIGNvcHkgKGJ5IGRlZmF1bHQpLCBpZiBkYXRhIHNpemUgaXMgYmlnIChiZWNhdXNlIG9mIHplcm8tY29weSksCiAgICAgICAgLy8gdHJhbnNmZXJyaW5nIGlzIGdlbmVyYWxseSBtdWNoIGZhc3Rlci4gaG93ZXZlciBpdCBvYnZpb3VzbHkgaGFzIGEgZHJhd2JhY2ssCiAgICAgICAgLy8gdGhhdCB0cmFuc2ZlcnJlZCBhcmd1bWVudHMgYXJlIG5vIGxvbmdlciBhY2Nlc3NpYmxlIGluIHRoZSBzZW5kZXIgdGhyZWFkCiAgICAgICAgdGhpcy50cmFuc2ZlckFyZ3MgPSBmYWxzZTsKICAgICAgICAvLyB0aGUgcmVjZWl2ZXIvY2FsbGVlIHdpbGwgYWx3YXlzIHVzZSB0cmFuc2ZlcnJpbmcgdG8gc2VuZCBiYWNrIGFyZ3VtZW50cywKICAgICAgICAvLyBub3Qgc2VuZGluZyB0aGUgYXJndW1lbnRzIGJhY2sgaXMgc3VwcG9zZWQgdG8gc2F2ZSBhIGxpdHRsZSB0aW1lL292ZXJoZWFkCiAgICAgICAgdGhpcy5yZXBseUFyZ3MgPSBmYWxzZTsKICAgICAgICB0aGlzLnF1ZXVlID0gW107CiAgICAgICAgdGhpcy5fbGFzdFRhc2tJRCA9IDA7CiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB7fTsKICAgICAgICB0aGlzLm9yaWdpbiA9IG9yaWdpbjsKICAgICAgICB0aGlzLnBvc3RNZXNzYWdlID0gcG9zdE1lc3NhZ2U7CiAgICAgICAgdGhpcy50YXNrSGFuZGxlciA9IHRhc2tIYW5kbGVyOwogICAgICAgIHRoaXMuZGVzdHJveSA9IGRlc3Ryb3k7CiAgICB9CiAgICBnZXQgaXNBbGl2ZSgpIHsKICAgICAgICByZXR1cm4gdGhpcy5faXNBbGl2ZTsKICAgIH0KICAgIC8vIHRoZXNlIGZvbGxvd2luZyB0d28gbWV0aG9kcy9mdW5jdGlvbnMgYXJlIHN1cHBvc2VkIHRvIGJlIGNhbGxiYWNrcwogICAgbXNnSGFuZGxlcihldikgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBjb25zdCB0YXNrID0gSENBVGFzay5yZWNyZWF0ZShldi5kYXRhKTsKICAgICAgICAgICAgICAgIGlmICh0YXNrLm9yaWdpbiAhPT0gdGhpcy5vcmlnaW4pIHsKICAgICAgICAgICAgICAgICAgICAvLyBpbmNvbWluZyBjbWQgdG8gZXhlY3V0ZQogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2sucmVzdWx0ID0geWllbGQgdGhpcy50YXNrSGFuZGxlcih0YXNrKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXQncyBvYnNlcnZlZCB0aGF0IEZpcmVmb3ggcmVmdXNlcyB0byBwb3N0TWVzc2FnZSBhbiBFcnJvciBvYmplY3Q6CiAgICAgICAgICAgICAgICAgICAgICAgIC8vICJEYXRhQ2xvbmVFcnJvcjogVGhlIG9iamVjdCBjb3VsZCBub3QgYmUgY2xvbmVkLiIKICAgICAgICAgICAgICAgICAgICAgICAgLy8gKG9ic2VydmVkIGluIEZpcmVmb3ggOTcsIG5vdCBjbGVhciBhYm91dCBvdGhlciB2ZXJzaW9ucykKICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lIGRvZXNuJ3Qgc2VlbSB0byBoYXZlIHRoaXMgcHJvYmxlbSwKICAgICAgICAgICAgICAgICAgICAgICAgLy8gaG93ZXZlciwgaW4gb3JkZXIgdG8ga2VlcCBjb21wYXRpYmxlIHdpdGggRmlyZWZveCwKICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2Ugc3RpbGwgaGF2ZSB0byBhdm9pZCBwb3N0aW5nIGFuIEVycm9yIG9iamVjdAogICAgICAgICAgICAgICAgICAgICAgICB0YXNrLmVyck1zZyA9IGBbJHt0aGlzLm9yaWdpbn1dIGVycm9yIHdoZW4gZXhlY3V0aW5nIGNtZCAke3Rhc2suY21kfSBmcm9tICR7dGFzay5vcmlnaW59YDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBlID09PSAic3RyaW5nIiB8fCBlIGluc3RhbmNlb2YgRXJyb3IpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXNrLmVyck1zZyArPSAiXG4iICsgZS50b1N0cmluZygpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAodGFzay50YXNrSUQgIT0gSENBVGFza1F1ZXVlLmRpc2NhcmRSZXBseVRhc2tJRCkKICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VuZFJlcGx5KHRhc2spOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBbJHt0aGlzLm9yaWdpbn1dIHNlbmRSZXBseSBmYWlsZWQuYCwgZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXNrLmVyck1zZyA9ICh0YXNrLmVyck1zZyA9PSBudWxsID8gIiIgOiB0YXNrLmVyck1zZyArICJcblxuIikgKyAicG9zdE1lc3NhZ2UgZnJvbSBXb3JrZXIgZmFpbGVkIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZSA9PT0gInN0cmluZyIgfHwgZSBpbnN0YW5jZW9mIEVycm9yKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suZXJyTXNnICs9ICJcbiIgKyBlLnRvU3RyaW5nKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0cnkgYWdhaW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VuZFJlcGx5KHRhc2spOyAvLyBpZiBpdCB0aHJvd3MsIGp1c3QgbGV0IGl0IHRocm93CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIC8vIHJlY2VpdmluZyBjbWQgcmVzdWx0CiAgICAgICAgICAgICAgICAgICAgLy8gZmluZCAmIHVucmVnaXN0ZXIgY2FsbGJhY2sKICAgICAgICAgICAgICAgICAgICBjb25zdCByZWdpc3RlcmVkID0gdGhpcy5jYWxsYmFja3NbdGFzay50YXNrSURdOwogICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1t0YXNrLnRhc2tJRF07CiAgICAgICAgICAgICAgICAgICAgLy8gYXBwbHkgaG9vawogICAgICAgICAgICAgICAgICAgIGxldCByZXN1bHQgPSB0YXNrLmhhc1Jlc3VsdCA/IHRhc2sucmVzdWx0IDogdW5kZWZpbmVkOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGhvb2sgPSByZWdpc3RlcmVkLmhvb2s7CiAgICAgICAgICAgICAgICAgICAgaWYgKGhvb2sgIT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0YXNrLmhhc0VyciAmJiBob29rLmVycm9yICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWllbGQgaG9vay5lcnJvcih0YXNrLmVyck1zZyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0YXNrLmhhc1Jlc3VsdCAmJiBob29rLnJlc3VsdCAhPSBudWxsKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHlpZWxkIGhvb2sucmVzdWx0KHRhc2sucmVzdWx0KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0YXNrLmhhc0VycikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXNrLmVyck1zZyA9ICIiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5lcnJNc2cgKz0gYFske3RoaXMub3JpZ2lufV0gZXJyb3Igd2hlbiBhcHBseWluZyBob29rIGAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIGBhZnRlciBleGVjdXRpbmcgY21kICR7dGFzay5jbWR9IGZyb20gJHt0YXNrLm9yaWdpbn1gOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBlID09PSAic3RyaW5nIiB8fCBlIGluc3RhbmNlb2YgRXJyb3IpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5lcnJNc2cgKz0gIlxuIiArIGUudG9TdHJpbmcoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIC8vIHNldHRsZSBwcm9taXNlCiAgICAgICAgICAgICAgICAgICAgaWYgKHRhc2suaGFzRXJyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lzdGVyZWQucmVqZWN0KHRhc2suZXJyTXNnKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodGFzay5oYXNSZXN1bHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmVnaXN0ZXJlZC5yZXNvbHZlKHJlc3VsdCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB0YXNrIChvcmlnaW49JHt0YXNrLm9yaWdpbn0gdGFza0lEPSR7dGFzay50YXNrSUR9IGNtZD0ke3Rhc2suY21kfSkgYAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKyBgaGFzIG5laXRoZXIgZXJyb3Igbm9yIHJlc3VsdGApOyAvLyBzaG91bGQgbmV2ZXIgaGFwcGVuCiAgICAgICAgICAgICAgICAgICAgLy8gc3RhcnQgbmV4dCB0YXNrCiAgICAgICAgICAgICAgICAgICAgeWllbGQgdGhpcy5zZW5kTmV4dFRhc2soKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgLy8gaXJyZWNvdmVyYWJsZSBlcnJvcgogICAgICAgICAgICAgICAgeWllbGQgdGhpcy5lcnJIYW5kbGVyKGUpOwogICAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICB9CiAgICBlcnJIYW5kbGVyKGRhdGEpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICAvLyBpcnJlY292ZXJhYmxlIGVycm9yCiAgICAgICAgICAgIGlmICh0aGlzLl9pc0FsaXZlKSB7CiAgICAgICAgICAgICAgICAvLyBwcmludCBlcnJvciBtZXNzYWdlCiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBbJHt0aGlzLm9yaWdpbn1dIGRlc3Ryb3lpbmcgYmFja2dyb3VuZCB3b3JrZXIgb24gaXJyZWNvdmVyYWJsZSBlcnJvcmAsIGRhdGEpOwogICAgICAgICAgICAgICAgLy8gZGVzdHJveSBiYWNrZ3JvdW5kIHdvcmtlcgogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLmRlc3Ryb3koKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgWyR7dGhpcy5vcmlnaW59XSBlcnJvciB3aGVuIHRyeWluZyB0byBkZXN0cm95KClgLCBlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8vIGFmdGVyIGRlc3Ryb3ksIG1hcmsgaXNBbGl2ZSBhcyBmYWxzZSAob3RoZXJ3aXNlIHNlbmRDbWQgd2lsbCBmYWlsKQogICAgICAgICAgICAgICAgdGhpcy5faXNBbGl2ZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgLy8gcmVqZWN0IGFsbCBwZW5kaW5nIHByb21pc2VzCiAgICAgICAgICAgICAgICBmb3IgKGxldCB0YXNrSUQgaW4gdGhpcy5jYWxsYmFja3MpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCByZWplY3QgPSB0aGlzLmNhbGxiYWNrc1t0YXNrSURdLnJlamVjdDsKICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbdGFza0lEXTsKICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgWyR7dGhpcy5vcmlnaW59XSBlcnJvciByZWplY3RpbmcgdGFza0lEPSR7dGFza0lEfWAsIGUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0pOwogICAgfQogICAgZ2V0VHJhbnNmZXJDb25maWcoKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0FsaXZlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJkZWFkIik7CiAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLmV4ZWNDbWQoIm5vcCIsIFtdLCB7CiAgICAgICAgICAgICAgICByZXN1bHQ6ICgpID0+ICh7CiAgICAgICAgICAgICAgICAgICAgdHJhbnNmZXJBcmdzOiB0aGlzLnRyYW5zZmVyQXJncywKICAgICAgICAgICAgICAgICAgICByZXBseUFyZ3M6IHRoaXMucmVwbHlBcmdzCiAgICAgICAgICAgICAgICB9KQogICAgICAgICAgICB9KTsKICAgICAgICB9KTsKICAgIH0KICAgIGNvbmZpZ1RyYW5zZmVyKHRyYW5zZmVyQXJncywgcmVwbHlBcmdzKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0FsaXZlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJkZWFkIik7CiAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLmV4ZWNDbWQoIm5vcCIsIFtdLCB7CiAgICAgICAgICAgICAgICByZXN1bHQ6ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYW5zZmVyQXJncyA9IHRyYW5zZmVyQXJncyA/IHRydWUgOiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB0aGlzLnJlcGx5QXJncyA9IHJlcGx5QXJncyA/IHRydWUgOiBmYWxzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICB9CiAgICBleGVjQ21kKGNtZCwgYXJncywgaG9vaykgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIC8vIGNhbiBiZSBtb2RpZmllZCB0byBzaW1wbHkgd3JhcCBleGVjTXVsdGlDbWQgYnV0IEkganVzdCB3YW50IHRvIGxldCBpdCBhbG9uZSBmb3Igbm8gc3BlY2lhbCByZWFzb24KICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0FsaXZlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJkZWFkIik7CiAgICAgICAgICAgIC8vIGFzc2lnbiBuZXcgdGFza0lECiAgICAgICAgICAgIGNvbnN0IHRhc2tJRCA9IHRoaXMuZ2V0TmV4dFRhc2tJRCgpOwogICAgICAgICAgICBjb25zdCB0YXNrID0gbmV3IEhDQVRhc2sodGhpcy5vcmlnaW4sIHRhc2tJRCwgY21kLCBhcmdzLCB0aGlzLnJlcGx5QXJncyk7CiAgICAgICAgICAgIC8vIHJlZ2lzdGVyIGNhbGxiYWNrCiAgICAgICAgICAgIGlmICh0aGlzLmNhbGxiYWNrc1t0YXNrSURdICE9IG51bGwpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHRhc2tJRD0ke3Rhc2tJRH0gaXMgYWxyZWFkeSBvY2N1cGllZGApOwogICAgICAgICAgICBjb25zdCByZXN1bHRQcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gdGhpcy5jYWxsYmFja3NbdGFza0lEXSA9IHsKICAgICAgICAgICAgICAgIHJlc29sdmU6IHJlc29sdmUsIHJlamVjdDogcmVqZWN0LAogICAgICAgICAgICAgICAgaG9vazogaG9vawogICAgICAgICAgICB9KTsKICAgICAgICAgICAgLy8gYXBwZW5kIHRvIGNvbW1hbmQgcXVldWUKICAgICAgICAgICAgdGhpcy5xdWV1ZS5wdXNoKHRhc2spOwogICAgICAgICAgICAvLyBzdGFydCBleGVjdXRpbmcgdGFza3MKICAgICAgICAgICAgaWYgKHRoaXMuaXNJZGxlKQogICAgICAgICAgICAgICAgeWllbGQgdGhpcy5zZW5kTmV4dFRhc2soKTsKICAgICAgICAgICAgLy8gcmV0dXJuIHJlc3VsdAogICAgICAgICAgICByZXR1cm4geWllbGQgcmVzdWx0UHJvbWlzZTsKICAgICAgICB9KTsKICAgIH0KICAgIGV4ZWNNdWx0aUNtZChjbWRMaXN0KSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgLy8gdGhlIHBvaW50IGlzIHRvIGVuc3VyZSAiYXRvbWljaXR5IiBiZXR3ZWVuIGNtZHMKICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0FsaXZlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJkZWFkIik7CiAgICAgICAgICAgIGxldCByZXN1bHRQcm9taXNlcyA9IFtdOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNtZExpc3QubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIC8vIGFzc2lnbiBuZXcgdGFza0lECiAgICAgICAgICAgICAgICBjb25zdCB0YXNrSUQgPSB0aGlzLmdldE5leHRUYXNrSUQoKTsKICAgICAgICAgICAgICAgIGNvbnN0IGxpc3RJdGVtID0gY21kTGlzdFtpXTsKICAgICAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgSENBVGFzayh0aGlzLm9yaWdpbiwgdGFza0lELCBsaXN0SXRlbS5jbWQsIGxpc3RJdGVtLmFyZ3MsIHRoaXMucmVwbHlBcmdzKTsKICAgICAgICAgICAgICAgIC8vIHJlZ2lzdGVyIGNhbGxiYWNrCiAgICAgICAgICAgICAgICBpZiAodGhpcy5jYWxsYmFja3NbdGFza0lEXSAhPSBudWxsKQogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdGFza0lEPSR7dGFza0lEfSBpcyBhbHJlYWR5IG9jY3VwaWVkYCk7CiAgICAgICAgICAgICAgICByZXN1bHRQcm9taXNlcy5wdXNoKG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHRoaXMuY2FsbGJhY2tzW3Rhc2tJRF0gPSB7CiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZTogcmVzb2x2ZSwgcmVqZWN0OiByZWplY3QsCiAgICAgICAgICAgICAgICAgICAgaG9vazogbGlzdEl0ZW0uaG9vawogICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgLy8gYXBwZW5kIHRvIGNvbW1hbmQgcXVldWUKICAgICAgICAgICAgICAgIHRoaXMucXVldWUucHVzaCh0YXNrKTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBzdGFydCBleGVjdXRpbmcgdGFza3MKICAgICAgICAgICAgaWYgKHRoaXMuaXNJZGxlKQogICAgICAgICAgICAgICAgeWllbGQgdGhpcy5zZW5kTmV4dFRhc2soKTsKICAgICAgICAgICAgLy8gcmV0dXJuIHJlc3VsdHMKICAgICAgICAgICAgcmV0dXJuIHlpZWxkIFByb21pc2UuYWxsKHJlc3VsdFByb21pc2VzKTsKICAgICAgICB9KTsKICAgIH0KICAgIHNlbmRDbWQoY21kLCBhcmdzKSB7CiAgICAgICAgLy8gc2VuZCBjbWQgd2l0aG91dCByZWdpc3RlcmluZyBjYWxsYmFjawogICAgICAgIC8vIGdlbmVyYWxseSBub3QgcmVjb21tZW5kZWQKICAgICAgICBpZiAoIXRoaXMuX2lzQWxpdmUpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiZGVhZCIpOwogICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgSENBVGFzayh0aGlzLm9yaWdpbiwgSENBVGFza1F1ZXVlLmRpc2NhcmRSZXBseVRhc2tJRCwgY21kLCBhcmdzLCBmYWxzZSk7CiAgICAgICAgdGhpcy5zZW5kVGFzayh0YXNrKTsKICAgIH0KICAgIHNodXRkb3duKGZvcmNpYmx5ID0gZmFsc2UpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICBpZiAodGhpcy5faXNBbGl2ZSkgewogICAgICAgICAgICAgICAgaWYgKGZvcmNpYmx5KSB7CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgeWllbGQgdGhpcy5kZXN0cm95KCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFske3RoaXMub3JpZ2lufV0gZXJyb3Igd2hlbiB0cnlpbmcgdG8gZm9yY2libHkgc2h1dGRvd24uYCwgZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHRoaXMuX2lzQWxpdmUgPSBmYWxzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLmV4ZWNDbWQoIm5vcCIsIFtdLCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdDogKCkgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgeWllbGQgdGhpcy5kZXN0cm95KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9pc0FsaXZlID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgIH0KfQpIQ0FUYXNrUXVldWUubWF4VGFza0lEID0gMjU2OyAvLyB0aGVyZSdzIHJlY3Vyc2lvbiBpbiBzZW5kTmV4dFRhc2sgd2hlbiBtYWtpbmcgZmFrZSByZXBseQpIQ0FUYXNrUXVldWUuZGlzY2FyZFJlcGx5VGFza0lEID0gLTE7CmlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICJ1bmRlZmluZWQiKSB7CiAgICBpZiAodHlwZW9mIG9ubWVzc2FnZSA9PT0gInVuZGVmaW5lZCIpIHsKICAgICAgICAvLyBBdWRpb1dvcmtsZXQKICAgICAgICBjbGFzcyBIQ0FGcmFtZVBsYXllckNvbnRleHQgewogICAgICAgICAgICBnZXQgaXNTdGFsbGluZygpIHsKICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9pc1N0YWxsaW5nOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHNldCBpc1N0YWxsaW5nKHZhbCkgewogICAgICAgICAgICAgICAgdGhpcy5faXNTdGFsbGluZyA9IHZhbDsKICAgICAgICAgICAgICAgIGlmICh2YWwpCiAgICAgICAgICAgICAgICAgICAgdGhpcy5vbmNlU3RhbGxlZCA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3RydWN0b3IocHJvY09wdHMpIHsKICAgICAgICAgICAgICAgIHRoaXMuaXNQbGF5aW5nID0gZmFsc2U7CiAgICAgICAgICAgICAgICB0aGlzLmRlZmF1bHRQdWxsQmxvY2tDb3VudCA9IDEyODsKICAgICAgICAgICAgICAgIHRoaXMuZmFpbGVkQmxvY2tzID0gW107CiAgICAgICAgICAgICAgICB0aGlzLnByaW50RXJyb3JDb3VudERvd25Gcm9tID0gMjU2OwogICAgICAgICAgICAgICAgdGhpcy5wcmludEVycm9yQ291bnREb3duID0gdGhpcy5wcmludEVycm9yQ291bnREb3duRnJvbTsKICAgICAgICAgICAgICAgIHRoaXMudG90YWxQdWxsZWRCbG9ja0NvdW50ID0gMDsKICAgICAgICAgICAgICAgIHRoaXMuaXNQdWxsaW5nID0gZmFsc2U7CiAgICAgICAgICAgICAgICB0aGlzLl9pc1N0YWxsaW5nID0gZmFsc2U7CiAgICAgICAgICAgICAgICB0aGlzLm9uY2VTdGFsbGVkID0gZmFsc2U7CiAgICAgICAgICAgICAgICB0aGlzLnNhbXBsZU9mZnNldCA9IDA7CiAgICAgICAgICAgICAgICB0aGlzLmxhc3REZWNvZGVkQmxvY2tJbmRleCA9IC0xOwogICAgICAgICAgICAgICAgdGhpcy5mcmFtZSA9IG5ldyBIQ0FGcmFtZShuZXcgSENBSW5mbyhwcm9jT3B0cy5yYXdIZWFkZXIpKTsKICAgICAgICAgICAgICAgIGNvbnN0IGluZm8gPSB0aGlzLmZyYW1lLkhjYTsKICAgICAgICAgICAgICAgIGNvbnN0IGhhc0xvb3AgPSBpbmZvLmhhc0hlYWRlclsibG9vcCJdID8gdHJ1ZSA6IGZhbHNlOwogICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwcm9jT3B0cy5wdWxsQmxvY2tDb3VudCA9PT0gIm51bWJlciIpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoaXNOYU4ocHJvY09wdHMucHVsbEJsb2NrQ291bnQpKQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAgICAgICAgICAgICBsZXQgcHVsbEJsb2NrQ291bnQgPSBNYXRoLmZsb29yKHByb2NPcHRzLnB1bGxCbG9ja0NvdW50KTsKICAgICAgICAgICAgICAgICAgICBpZiAocHVsbEJsb2NrQ291bnQgPCAyKQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLnB1bGxCbG9ja0NvdW50ID0gcHVsbEJsb2NrQ291bnQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWxsQmxvY2tDb3VudCA9IHRoaXMuZGVmYXVsdFB1bGxCbG9ja0NvdW50OwogICAgICAgICAgICAgICAgY29uc3QgYnVmZmVyZWRCbG9ja0NvdW50ID0gaGFzTG9vcCA/IChpbmZvLmxvb3AuZW5kICsgMSkgOiB0aGlzLnB1bGxCbG9ja0NvdW50ICogMjsKICAgICAgICAgICAgICAgIHRoaXMuZW5jb2RlZCA9IG5ldyBVaW50OEFycmF5KGluZm8uYmxvY2tTaXplICogYnVmZmVyZWRCbG9ja0NvdW50KTsKICAgICAgICAgICAgICAgIHRoaXMuZGVjb2RlZCA9IEFycmF5LmZyb20oeyBsZW5ndGg6IGluZm8uZm9ybWF0LmNoYW5uZWxDb3VudCB9LCAoKSA9PiBuZXcgRmxvYXQzMkFycmF5KEhDQUZyYW1lLlNhbXBsZXNQZXJGcmFtZSAqIDIpKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjbGFzcyBIQ0FGcmFtZVBsYXllciBleHRlbmRzIEF1ZGlvV29ya2xldFByb2Nlc3NvciB7CiAgICAgICAgICAgIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKICAgICAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgICAgICB0aGlzLnVuc2V0dGxlZCA9IFtdOwogICAgICAgICAgICAgICAgdGhpcy53YWl0Q291bnREb3duRnJvbSA9IDMyOwogICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMgPT0gbnVsbCB8fCBvcHRpb25zLnByb2Nlc3Nvck9wdGlvbnMgPT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAgICAgICAgIHRoaXMuY3R4ID0gbmV3IEhDQUZyYW1lUGxheWVyQ29udGV4dChvcHRpb25zLnByb2Nlc3Nvck9wdGlvbnMpOwogICAgICAgICAgICAgICAgdGhpcy50YXNrUXVldWUgPSBuZXcgSENBVGFza1F1ZXVlKCJCYWNrZ3JvdW5kLUhDQUZyYW1lUGxheWVyIiwgKG1zZywgdHJhbnMpID0+IHRoaXMucG9ydC5wb3N0TWVzc2FnZShtc2csIHRyYW5zKSwgKHRhc2spID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhc2suY21kKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIm5vcCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImluaXRpYWxpemUiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHggPSBuZXcgSENBRnJhbWVQbGF5ZXJDb250ZXh0KHRhc2suYXJnc1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAicmVzZXQiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgeWllbGQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5jdHg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51bnNldHRsZWQucHVzaCh7IHJlc29sdmU6IHJlc29sdmUsIGNvdW50ZXI6IHRoaXMud2FpdENvdW50RG93bkZyb20gfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJwYXVzZSI6CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgInJlc3VtZSI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jdHggPT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vdCBpbml0aWFsaXplZGApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguaXNQbGF5aW5nID0gdGFzay5jbWQgPT09ICJyZXN1bWUiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmN0eC5pc1BsYXlpbmcpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWllbGQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51bnNldHRsZWQucHVzaCh7IHJlc29sdmU6IHJlc29sdmUsIGNvdW50ZXI6IHRoaXMud2FpdENvdW50RG93bkZyb20gfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5rbm93biBjbWQgJHt0YXNrLmNtZH1gKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KSwgKCkgPT4geyB0aGlzLnRhc2tRdWV1ZS5zZW5kQ21kKCJzZWxmLWRlc3RydWN0IiwgW10pOyB9KTsKICAgICAgICAgICAgICAgIHRoaXMudGFza1F1ZXVlLmNvbmZpZ1RyYW5zZmVyKHRydWUsIGZhbHNlKTsKICAgICAgICAgICAgICAgIHRoaXMucG9ydC5vbm1lc3NhZ2UgPSAoZXYpID0+IHRoaXMudGFza1F1ZXVlLm1zZ0hhbmRsZXIoZXYpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGhhbmRsZU5ld0Jsb2NrcyhjdHgsIG5ld0Jsb2NrcykgewogICAgICAgICAgICAgICAgY29uc3QgaW5mbyA9IGN0eC5mcmFtZS5IY2E7CiAgICAgICAgICAgICAgICBjb25zdCBoYXNMb29wID0gaW5mby5oYXNIZWFkZXJbImxvb3AiXSA/IHRydWUgOiBmYWxzZTsKICAgICAgICAgICAgICAgIGNvbnN0IHB1bGxCbG9ja0NvdW50ID0gY3R4LnB1bGxCbG9ja0NvdW50OwogICAgICAgICAgICAgICAgY29uc3QgZW5jb2RlZCA9IGN0eC5lbmNvZGVkOwogICAgICAgICAgICAgICAgaWYgKG5ld0Jsb2Nrcy5sZW5ndGggJSBpbmZvLmJsb2NrU2l6ZSAhPSAwKSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBuZXdCbG9ja3MubGVuZ3RoPSR7bmV3QmxvY2tzLmxlbmd0aH0gc2hvdWxkIGJlIG11bHRpcGxlIG9mIGJsb2NrU2l6ZWApOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY29uc3QgbmV3QmxvY2tDb3VudCA9IG5ld0Jsb2Nrcy5sZW5ndGggLyBpbmZvLmJsb2NrU2l6ZTsKICAgICAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkID0gaW5mby5ibG9ja1NpemUgKiBwdWxsQmxvY2tDb3VudDsKICAgICAgICAgICAgICAgIGlmIChoYXNMb29wKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IGVuY29kZWRPZmZzZXQgPSBpbmZvLmJsb2NrU2l6ZSAqIGN0eC50b3RhbFB1bGxlZEJsb2NrQ291bnQ7CiAgICAgICAgICAgICAgICAgICAgaWYgKGVuY29kZWRPZmZzZXQgKyBuZXdCbG9ja3MubGVuZ3RoID4gZW5jb2RlZC5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBoYXMgbG9vcCBoZWFkZXIsIGJ1ZmZlciB3aWxsIG92ZXJmbG93YCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVuY29kZWQuc2V0KG5ld0Jsb2NrcywgZW5jb2RlZE9mZnNldCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBpZiAobmV3QmxvY2tzLmxlbmd0aCAhPSBleHBlY3RlZCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vIGxvb3AgaGVhZGVyLCBuZXdCbG9ja3MubGVuZ3RoICgke25ld0Jsb2Nrcy5sZW5ndGh9KSAhPSBleHBlY3RlZCAoJHtleHBlY3RlZH0pYCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoY3R4LnRvdGFsUHVsbGVkQmxvY2tDb3VudCAlIChwdWxsQmxvY2tDb3VudCAqIDIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuY29kZWQuc2V0KG5ld0Jsb2Nrcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBwdWxsQmxvY2tDb3VudDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuY29kZWQuc2V0KG5ld0Jsb2NrcywgZXhwZWN0ZWQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjdHgudG90YWxQdWxsZWRCbG9ja0NvdW50ICs9IG5ld0Jsb2NrQ291bnQ7CiAgICAgICAgICAgICAgICBjdHguaXNQdWxsaW5nID0gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcHVsbE5ld0Jsb2NrcyhjdHgpIHsKICAgICAgICAgICAgICAgIC8vIGlmIGN0eCBwYXNzZWQgaW4gaGFkIGJlZW4gYWN0dWFsbHkgZGVsZXRlZCwgaXQgd29uJ3QgYWZmZWN0IHRoZSBjdXJyZW50IHVzaW5nIGN0eAogICAgICAgICAgICAgICAgaWYgKGN0eC5pc1B1bGxpbmcpCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBhbHJlYWR5IHB1bGxpbmcuIHdpbGwgYmUgY2FsbGVkIGFnYWluIGlmIHN0aWxsIG5vdCBlbm91Z2gKICAgICAgICAgICAgICAgIGN0eC5pc1B1bGxpbmcgPSB0cnVlOwogICAgICAgICAgICAgICAgLy8gcmVxdWVzdCB0byBwdWxsICYgY29udGludWUgZGVjb2RpbmcKICAgICAgICAgICAgICAgIHRoaXMudGFza1F1ZXVlLmV4ZWNDbWQoInB1bGwiLCBbXSwgewogICAgICAgICAgICAgICAgICAgIHJlc3VsdDogKG5ld0Jsb2NrcykgPT4gdGhpcy5oYW5kbGVOZXdCbG9ja3MoY3R4LCBuZXdCbG9ja3MpLAogICAgICAgICAgICAgICAgICAgIGVycm9yOiAoKSA9PiB7IGN0eC5pc1B1bGxpbmcgPSBmYWxzZTsgfSwKICAgICAgICAgICAgICAgIH0pCiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBwdWxsTmV3QmxvY2tzIGZhaWxlZC5gLCBlKTsKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHdyaXRlVG9EZWNvZGVkQnVmZmVyKGZyYW1lLCBkZWNvZGVkKSB7CiAgICAgICAgICAgICAgICBjb25zdCBoYWxmU2l6ZSA9IEhDQUZyYW1lLlNhbXBsZXNQZXJGcmFtZTsKICAgICAgICAgICAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgZnJhbWUuQ2hhbm5lbHMubGVuZ3RoOyBjKyspIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBmaXJzdEhhbGYgPSBkZWNvZGVkW2NdLnN1YmFycmF5KDAsIGhhbGZTaXplKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBsYXN0SGFsZiA9IGRlY29kZWRbY10uc3ViYXJyYXkoaGFsZlNpemUsIGhhbGZTaXplICogMik7CiAgICAgICAgICAgICAgICAgICAgZmlyc3RIYWxmLnNldChsYXN0SGFsZik7CiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgc2YgPSAwLCBvZmZzZXQgPSAwOyBzZiA8IEhDQUZyYW1lLlN1YmZyYW1lc1BlckZyYW1lOyBzZisrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RIYWxmLnNldChmcmFtZS5DaGFubmVsc1tjXS5QY21GbG9hdFtzZl0sIG9mZnNldCk7CiAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldCArPSBIQ0FGcmFtZS5TYW1wbGVzUGVyU3ViRnJhbWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGFzdEhhbGYubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RIYWxmW2ldID4gMSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RIYWxmW2ldID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobGFzdEhhbGZbaV0gPCAtMSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RIYWxmW2ldID0gLTE7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIG1hcFRvVW5Mb29wZWQoaW5mbywgc2FtcGxlT2Zmc2V0KSB7CiAgICAgICAgICAgICAgICBjb25zdCBoYXNMb29wID0gaW5mby5oYXNIZWFkZXJbImxvb3AiXSA/IHRydWUgOiBmYWxzZTsKICAgICAgICAgICAgICAgIGlmIChzYW1wbGVPZmZzZXQgPD0gaW5mby5lbmRBdFNhbXBsZSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBzYW1wbGVPZmZzZXQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBpZiAoaGFzTG9vcCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0ID0gKHNhbXBsZU9mZnNldCAtIGluZm8ubG9vcFN0YXJ0QXRTYW1wbGUpICUgaW5mby5sb29wU2FtcGxlQ291bnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbmZvLmxvb3BTdGFydEF0U2FtcGxlICsgb2Zmc2V0OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluZm8uZW5kQXRTYW1wbGU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgICAgICBpZiAodGhpcy5jdHggPT0gbnVsbCB8fCAhdGhpcy5jdHguaXNQbGF5aW5nKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gd29ya2Fyb3VuZCB0aGUgInJlc2lkdWUiIGJ1cnN0IG5vaXNlIGlzc3VlIGluIENocm9tZQogICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuc2V0dGxlZCA9IHRoaXMudW5zZXR0bGVkLnNoaWZ0KCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHVuc2V0dGxlZCAhPSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgtLXVuc2V0dGxlZC5jb3VudGVyID4gMCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudW5zZXR0bGVkLnVuc2hpZnQodW5zZXR0bGVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bnNldHRsZWQucmVzb2x2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBlcnJvciB3aGVuIHNldHRsaW5nIHByb21pc2Ugb2YgInJlc2V0IiBvciAic2V0UGxheWluZyIgY21kYCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOyAvLyB3YWl0IGZvciBuZXcgc291cmNlIG9yIHJlc3VtZQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHRoaXMuY3R4LmZhaWxlZEJsb2Nrcy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY3R4LmZhaWxlZEJsb2Nrcy5sZW5ndGggPj0gNjQgfHwgLS10aGlzLmN0eC5wcmludEVycm9yQ291bnREb3duIDw9IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgZXJyb3IgZGVjb2RpbmcgZm9sbG93aW5nIGJsb2Nrc2AsIHRoaXMuY3R4LmZhaWxlZEJsb2NrcywgdGhpcy5jdHgubGFzdEVycm9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguZmFpbGVkQmxvY2tzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4Lmxhc3RFcnJvciA9IHVuZGVmaW5lZDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHgucHJpbnRFcnJvckNvdW50RG93biA9IHRoaXMuY3R4LnByaW50RXJyb3JDb3VudERvd25Gcm9tOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dHNbMF07CiAgICAgICAgICAgICAgICBjb25zdCByZW5kZXJRdWFudHVtU2l6ZSA9IG91dHB1dFswXS5sZW5ndGg7CiAgICAgICAgICAgICAgICBjb25zdCBzYW1wbGVzUGVyQmxvY2sgPSBIQ0FGcmFtZS5TYW1wbGVzUGVyRnJhbWU7CiAgICAgICAgICAgICAgICAvLyBubyBtb3JlIHRoYW4gb25lIGJsb2NrIHdpbGwgYmUgZGVjb2RlZCBlYWNoIHRpbWUgdGhpcyBmdW5jdGlvbiBiZWluZyBjYWxsZWQsCiAgICAgICAgICAgICAgICAvLyB0aGVyZWZvcmUgb25lIGJsb2NrIG11c3QgY292ZXIgdGhlIHdob2xlIHJlbmRlclF1YW50dW1TaXplCiAgICAgICAgICAgICAgICBpZiAoc2FtcGxlc1BlckJsb2NrIDwgcmVuZGVyUXVhbnR1bVNpemUpCiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJyZW5kZXIgcXVhbnR1bSByZXF1aXJlcyBtb3JlIHNhbXBsZSB0aGFuIGEgZnVsbCBibG9jayIpOwogICAgICAgICAgICAgICAgY29uc3QgaW5mbyA9IHRoaXMuY3R4LmZyYW1lLkhjYTsKICAgICAgICAgICAgICAgIGNvbnN0IGhhc0xvb3AgPSBpbmZvLmhhc0hlYWRlclsibG9vcCJdID8gdHJ1ZSA6IGZhbHNlOwogICAgICAgICAgICAgICAgY29uc3QgZW5jb2RlZCA9IHRoaXMuY3R4LmVuY29kZWQ7CiAgICAgICAgICAgICAgICBjb25zdCBkZWNvZGVkID0gdGhpcy5jdHguZGVjb2RlZDsKICAgICAgICAgICAgICAgIC8vIHNraXAgZHJvcHBlZEhlYWRlcgogICAgICAgICAgICAgICAgaWYgKHRoaXMuY3R4LnNhbXBsZU9mZnNldCA8IGluZm8uZm9ybWF0LmRyb3BwZWRIZWFkZXIpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5zYW1wbGVPZmZzZXQgPSBpbmZvLmZvcm1hdC5kcm9wcGVkSGVhZGVyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHRoaXMuY3R4LnNhbXBsZU9mZnNldCA+PSBpbmZvLmVuZEF0U2FtcGxlKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGhhc0xvb3ApIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmV3aW5kIGJhY2sgaWYgYmV5b25kIGxvb3AgZW5kCiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnNhbXBsZU9mZnNldCA9IHRoaXMubWFwVG9Vbkxvb3BlZChpbmZvLCB0aGlzLmN0eC5zYW1wbGVPZmZzZXQpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm90aGluZyBtb3JlIHRvIHBsYXkKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50YXNrUXVldWUuc2VuZENtZCgiZW5kIiwgW10pOyAvLyBub3Qgd2FpdGluZyBmb3IgcmVzdWx0CiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmN0eDsgLy8gYXZvaWQgc2VuZGluZyAiZW5kIiBjbWQgZm9yIG1vcmUgdGhhbiBvbmUgdGltZQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAvLyBkZWNvZGUgYmxvY2sgJiBwdWxsIG5ldyBibG9jayAoaWYgbmVlZGVkKQogICAgICAgICAgICAgICAgY29uc3QgbWFwcGVkU3RhcnRPZmZzZXQgPSB0aGlzLm1hcFRvVW5Mb29wZWQoaW5mbywgdGhpcy5jdHguc2FtcGxlT2Zmc2V0KTsKICAgICAgICAgICAgICAgIGNvbnN0IG1hcHBlZEVuZE9mZnNldCA9IHRoaXMubWFwVG9Vbkxvb3BlZChpbmZvLCB0aGlzLmN0eC5zYW1wbGVPZmZzZXQgKyByZW5kZXJRdWFudHVtU2l6ZSk7CiAgICAgICAgICAgICAgICBjb25zdCBpbkJsb2NrU3RhcnRPZmZzZXQgPSBtYXBwZWRTdGFydE9mZnNldCAlIHNhbXBsZXNQZXJCbG9jazsKICAgICAgICAgICAgICAgIGNvbnN0IGluQmxvY2tFbmRPZmZzZXQgPSBtYXBwZWRFbmRPZmZzZXQgJSBzYW1wbGVzUGVyQmxvY2s7CiAgICAgICAgICAgICAgICBjb25zdCBzdGFydEJsb2NrSW5kZXggPSAobWFwcGVkU3RhcnRPZmZzZXQgLSBpbkJsb2NrU3RhcnRPZmZzZXQpIC8gc2FtcGxlc1BlckJsb2NrOwogICAgICAgICAgICAgICAgY29uc3QgZW5kQmxvY2tJbmRleCA9IChtYXBwZWRFbmRPZmZzZXQgLSBpbkJsb2NrRW5kT2Zmc2V0KSAvIHNhbXBsZXNQZXJCbG9jazsKICAgICAgICAgICAgICAgIGlmIChlbmRCbG9ja0luZGV4ICE9IHRoaXMuY3R4Lmxhc3REZWNvZGVkQmxvY2tJbmRleCkgewogICAgICAgICAgICAgICAgICAgIGlmIChlbmRCbG9ja0luZGV4IDwgdGhpcy5jdHgudG90YWxQdWxsZWRCbG9ja0NvdW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJsb2NrIGlzIGF2YWlsYWJsZSBmb3IgZGVjb2RpbmcKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguaXNTdGFsbGluZyA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnQgPSBpbmZvLmJsb2NrU2l6ZSAqIChoYXNMb29wCiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGVuZEJsb2NrSW5kZXgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogZW5kQmxvY2tJbmRleCAlICh0aGlzLmN0eC5wdWxsQmxvY2tDb3VudCAqIDIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVuZCA9IHN0YXJ0ICsgaW5mby5ibG9ja1NpemU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbmQgPiBlbmNvZGVkLmxlbmd0aCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiYmxvY2sgZW5kIG9mZnNldCBleGNlZWRzIGJ1ZmZlciBzaXplIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBIQ0EuZGVjb2RlQmxvY2sodGhpcy5jdHguZnJhbWUsIGVuY29kZWQuc3ViYXJyYXkoc3RhcnQsIGVuZCkpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5mYWlsZWRCbG9ja3MucHVzaChlbmRCbG9ja0luZGV4KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4Lmxhc3RFcnJvciA9IGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5mcmFtZS5DaGFubmVscy5mb3JFYWNoKChjKSA9PiB7IGMuUGNtRmxvYXQuZm9yRWFjaCgoc2YpID0+IHNmLmZpbGwoMCkpOyB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndyaXRlVG9EZWNvZGVkQnVmZmVyKHRoaXMuY3R4LmZyYW1lLCB0aGlzLmN0eC5kZWNvZGVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHgubGFzdERlY29kZWRCbG9ja0luZGV4ID0gZW5kQmxvY2tJbmRleDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY3R4LnRvdGFsUHVsbGVkQmxvY2tDb3VudCA8IChoYXNMb29wID8gaW5mby5sb29wLmVuZCA6IGluZm8uZm9ybWF0LmJsb2NrQ291bnQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwdWxsIGJsb2NrcyBpbiBhZHZhbmNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYXZhaWxhYmxlQmxvY2tDb3VudCA9IGhhc0xvb3AgJiYgdGhpcy5jdHgudG90YWxQdWxsZWRCbG9ja0NvdW50ID49IGluZm8ubG9vcC5lbmQgKyAxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyAiYWxsX3B1bGxlZCIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHRoaXMuY3R4LnRvdGFsUHVsbGVkQmxvY2tDb3VudCAtICh0aGlzLmN0eC5sYXN0RGVjb2RlZEJsb2NrSW5kZXggKyAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYXZhaWxhYmxlQmxvY2tDb3VudCA9PT0gJ251bWJlcicgJiYgYXZhaWxhYmxlQmxvY2tDb3VudCA8IHRoaXMuY3R4LnB1bGxCbG9ja0NvdW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWxsTmV3QmxvY2tzKHRoaXMuY3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gYmxvY2sgaXMgdW5hdmFpbGFibGUKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmN0eC5pc1N0YWxsaW5nICYmIHRoaXMuY3R4Lm9uY2VTdGFsbGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwcmludCBlcnJvciBhYm91dCBzdGFsbGluZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbSENBRnJhbWVQbGF5ZXJdIHdhaXRpbmcgdW50aWwgYmxvY2sgJHtlbmRCbG9ja0luZGV4fSBiZWNvbWUgYXZhaWxhYmxlLi4uYCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguaXNTdGFsbGluZyA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHVsbE5ld0Jsb2Nrcyh0aGlzLmN0eCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8vIGNvcHkgZGVjb2RlZCBkYXRhCiAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCAhPSBpbmZvLmZvcm1hdC5jaGFubmVsQ291bnQpCiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJjaGFubmVsIGNvdW50IG1pc21hdGNoIik7CiAgICAgICAgICAgICAgICBjb25zdCBpbkJ1ZmZlclN0YXJ0T2Zmc2V0ID0gKGVuZEJsb2NrSW5kZXggIT0gc3RhcnRCbG9ja0luZGV4ID8gMCA6IHNhbXBsZXNQZXJCbG9jaykgKyBpbkJsb2NrU3RhcnRPZmZzZXQ7CiAgICAgICAgICAgICAgICBjb25zdCBpbkJ1ZmZlckVuZE9mZnNldCA9IHNhbXBsZXNQZXJCbG9jayArIGluQmxvY2tFbmRPZmZzZXQ7CiAgICAgICAgICAgICAgICBjb25zdCBpbkJ1ZmZlclNyY1NpemUgPSBpbkJ1ZmZlckVuZE9mZnNldCAtIGluQnVmZmVyU3RhcnRPZmZzZXQ7CiAgICAgICAgICAgICAgICBpZiAoaW5CdWZmZXJTcmNTaXplIDw9IDApCiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJzaXplIGluIGRlY29kZWQgYnVmZmVyIHNob3VsZCBiZSBwb3NpdGl2ZSIpOwogICAgICAgICAgICAgICAgY29uc3QgY29weVNpemUgPSBNYXRoLm1pbihpbkJ1ZmZlclNyY1NpemUsIHJlbmRlclF1YW50dW1TaXplKTsKICAgICAgICAgICAgICAgIGZvciAobGV0IGNoYW5uZWwgPSAwOyBjaGFubmVsIDwgb3V0cHV0Lmxlbmd0aDsgY2hhbm5lbCsrKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IHNyYyA9IGRlY29kZWRbY2hhbm5lbF0uc3ViYXJyYXkoaW5CdWZmZXJTdGFydE9mZnNldCwgaW5CdWZmZXJTdGFydE9mZnNldCArIGNvcHlTaXplKTsKICAgICAgICAgICAgICAgICAgICBvdXRwdXRbY2hhbm5lbF0uc2V0KHNyYyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB0aGlzLmN0eC5zYW1wbGVPZmZzZXQgKz0gY29weVNpemU7CiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZWdpc3RlclByb2Nlc3NvcigiaGNhLWZyYW1lLXBsYXllciIsIEhDQUZyYW1lUGxheWVyKTsKICAgIH0KICAgIGVsc2UgewogICAgICAgIC8vIFdlYiBXb3JrZXIKICAgICAgICBjb25zdCB0YXNrUXVldWUgPSBuZXcgSENBVGFza1F1ZXVlKCJCYWNrZ3JvdW5kLUhDQVdvcmtlciIsIChtc2csIHRyYW5zKSA9PiBwb3N0TWVzc2FnZShtc2csIHRyYW5zKSwgKHRhc2spID0+IHsKICAgICAgICAgICAgc3dpdGNoICh0YXNrLmNtZCkgewogICAgICAgICAgICAgICAgY2FzZSAibm9wIjoKICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICBjYXNlICJmaXhIZWFkZXJDaGVja3N1bSI6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEhDQUluZm8uZml4SGVhZGVyQ2hlY2tzdW0uYXBwbHkoSENBSW5mbywgdGFzay5hcmdzKTsKICAgICAgICAgICAgICAgIGNhc2UgImZpeENoZWNrc3VtIjoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gSENBLmZpeENoZWNrc3VtLmFwcGx5KEhDQSwgdGFzay5hcmdzKTsKICAgICAgICAgICAgICAgIGNhc2UgImZpbmRLZXkiOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBIQ0EuZmluZEtleS5hcHBseShIQ0EsIHRhc2suYXJncyk7CiAgICAgICAgICAgICAgICBjYXNlICJkZWNyeXB0IjoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gSENBLmRlY3J5cHQuYXBwbHkoSENBLCB0YXNrLmFyZ3MpOwogICAgICAgICAgICAgICAgY2FzZSAiZW5jcnlwdCI6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEhDQS5lbmNyeXB0LmFwcGx5KEhDQSwgdGFzay5hcmdzKTsKICAgICAgICAgICAgICAgIGNhc2UgImFkZENpcGhlckhlYWRlciI6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEhDQUluZm8uYWRkQ2lwaGVySGVhZGVyLmFwcGx5KEhDQUluZm8sIHRhc2suYXJncyk7CiAgICAgICAgICAgICAgICBjYXNlICJkZWNvZGUiOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBIQ0EuZGVjb2RlLmFwcGx5KEhDQSwgdGFzay5hcmdzKTsKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIGNtZCAke3Rhc2suY21kfWApOwogICAgICAgICAgICB9CiAgICAgICAgfSwgKCkgPT4geyB0YXNrUXVldWUuc2VuZENtZCgic2VsZi1kZXN0cnVjdCIsIFtdKTsgfSk7CiAgICAgICAgb25tZXNzYWdlID0gKGV2KSA9PiB0YXNrUXVldWUubXNnSGFuZGxlcihldik7CiAgICB9Cn0KLy8gY3JlYXRlICYgY29udHJvbCBhdWRpbyB3b3JrbGV0CmNsYXNzIEhDQUF1ZGlvV29ya2xldEhDQVBsYXllciB7CiAgICBnZXQgaXNBbGl2ZSgpIHsKICAgICAgICByZXR1cm4gdGhpcy50YXNrUXVldWUuaXNBbGl2ZTsKICAgIH0KICAgIGdldCBpbml0aWFsaXplZCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5faW5pdGlhbGl6ZWQ7CiAgICB9CiAgICBnZXQgdW5sb2NrZWQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3VubG9ja2VkOwogICAgfQogICAgZ2V0IGJsb2NrQ2hlY2tzdW1WZXJpZmljYXRpb24oKSB7CiAgICAgICAgcmV0dXJuIHRoaXMudmVyaWZ5Q3N1bTsKICAgIH0KICAgIHNldCBibG9ja0NoZWNrc3VtVmVyaWZpY2F0aW9uKHZhbCkgewogICAgICAgIGlmICh0eXBlb2YgdmFsICE9PSAiYm9vbGVhbiIpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgIHRoaXMudmVyaWZ5Q3N1bSA9IHZhbDsKICAgIH0KICAgIGdldCBmZWVkU2l6ZSgpIHsKICAgICAgICByZXR1cm4gdGhpcy5pbmZvLmJsb2NrU2l6ZSAqIHRoaXMuZmVlZEJsb2NrQ291bnQ7CiAgICB9CiAgICBnZXQgcmVtYWluaW5nQmxvY2tDb3VudCgpIHsKICAgICAgICBsZXQgdG90YWwgPSB0aGlzLmhhc0xvb3AgPyB0aGlzLmluZm8ubG9vcC5lbmQgKyAxIDogdGhpcy5pbmZvLmZvcm1hdC5ibG9ja0NvdW50OwogICAgICAgIGxldCByZW1haW5pbmcgPSB0b3RhbCAtIHRoaXMudG90YWxGZWRCbG9ja0NvdW50OwogICAgICAgIGlmIChyZW1haW5pbmcgPD0gMCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgcmV0dXJuIHJlbWFpbmluZzsKICAgIH0KICAgIGdldCBkb3dubG9hZEJ1ZmZlclNpemUoKSB7CiAgICAgICAgY29uc3QgYnl0ZXNQZXJTZWMgPSB0aGlzLmluZm8ua2JwcyAqIDEwMDAgLyA4OwogICAgICAgIHJldHVybiBieXRlc1BlclNlYyAqIDQ7CiAgICB9CiAgICBnZXQgdm9sdW1lKCkgewogICAgICAgIHJldHVybiB0aGlzLmdhaW5Ob2RlLmdhaW4udmFsdWU7CiAgICB9CiAgICBzZXQgdm9sdW1lKHZhbCkgewogICAgICAgIGlmIChpc05hTih2YWwpKQogICAgICAgICAgICByZXR1cm47CiAgICAgICAgaWYgKHZhbCA+IDEuMCkKICAgICAgICAgICAgdmFsID0gMS4wOwogICAgICAgIGlmICh2YWwgPCAwKQogICAgICAgICAgICB2YWwgPSAwOwogICAgICAgIHRoaXMuZ2Fpbk5vZGUuZ2Fpbi52YWx1ZSA9IHZhbDsKICAgIH0KICAgIHRhc2tIYW5kbGVyKHRhc2spIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICBzd2l0Y2ggKHRhc2suY21kKSB7CiAgICAgICAgICAgICAgICBjYXNlICJub3AiOgogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIGNhc2UgInNlbGYtZGVzdHJ1Y3QiOiAvLyBkb2Vzbid0IHNlZW0gdG8gaGF2ZSBhIGNoYW5jZSB0byBiZSBjYWxsZWQKICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBIQ0FGcmFtZVBsYXllciByZXF1ZXN0ZWQgdG8gc2VsZi1kZXN0cnVjdGApOwogICAgICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMudGFza1F1ZXVlLnNodXRkb3duKHRydWUpOwogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIGNhc2UgImVuZCI6CiAgICAgICAgICAgICAgICAgICAgeWllbGQgdGhpcy5zdG9wKCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBhY3R1YWxseSBub3Qgc2VuZGluZyBiYWNrIHJlcGx5CiAgICAgICAgICAgICAgICBjYXNlICJwdWxsIjoKICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zb3VyY2UgPT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3RoaW5nIHRvIGZlZWRgKTsgLy8gc2hvdWxkIG5ldmVyIGhhcHBlbgogICAgICAgICAgICAgICAgICAgIGxldCBibG9ja0NvdW50ID0gTWF0aC5taW4odGhpcy5mZWVkQmxvY2tDb3VudCwgdGhpcy5yZW1haW5pbmdCbG9ja0NvdW50KTsKICAgICAgICAgICAgICAgICAgICBsZXQgc2l6ZSA9IHRoaXMuaW5mby5ibG9ja1NpemUgKiBibG9ja0NvdW50OwogICAgICAgICAgICAgICAgICAgIGxldCBuZXdCbG9ja3M7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc291cmNlIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyB3aG9sZSBIQ0EgbW9kZQogICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnQgPSB0aGlzLmluZm8uZGF0YU9mZnNldCArIHRoaXMuaW5mby5ibG9ja1NpemUgKiB0aGlzLnRvdGFsRmVkQmxvY2tDb3VudDsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVuZCA9IHN0YXJ0ICsgc2l6ZTsKICAgICAgICAgICAgICAgICAgICAgICAgbmV3QmxvY2tzID0gdGhpcy5zb3VyY2Uuc3ViYXJyYXkoc3RhcnQsIGVuZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vfSBlbHNlIGlmICh0aGlzLnNvdXJjZSBpbnN0YW5jZW9mIFJlYWRhYmxlU3RyZWFtRGVmYXVsdFJlYWRlcikgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBjb21tZW50ZWQgb3V0IGJlY2F1c2UgRmlyZWZveCB0aHJvd3MgIlJlZmVyZW5jZUVycm9yOiBSZWFkYWJsZVN0cmVhbURlZmF1bHRSZWFkZXIgaXMgbm90IGRlZmluZWQiCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBVUkwgbW9kZQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zcmNCdWYgPT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigic3JjQnVmIGlzIHVuZGVmaW5lZCIpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgbWF4RG93bmxhb2RTaXplID0gdGhpcy5pbmZvLmJsb2NrU2l6ZSAqIHRoaXMucmVtYWluaW5nQmxvY2tDb3VudDsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRvd25sb2FkU2l6ZSA9IE1hdGgubWF4KHRoaXMuZG93bmxvYWRCdWZmZXJTaXplLCBzaXplKTsKICAgICAgICAgICAgICAgICAgICAgICAgZG93bmxvYWRTaXplID0gTWF0aC5taW4oZG93bmxvYWRTaXplLCBtYXhEb3dubGFvZFNpemUpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcmVtYWluaW5nID0gZG93bmxvYWRTaXplIC0gdGhpcy5zcmNCdWYubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVtYWluaW5nID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRklYTUUgY29ubmVjdGlvbiBsb3NzIGlzIG5vdCBoYW5kbGVkL3JlY292ZXJlZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zcmNCdWYgPSB5aWVsZCBIQ0FBdWRpb1dvcmtsZXRIQ0FQbGF5ZXIucmVhZEFuZEFwcGVuZCh0aGlzLnNvdXJjZSwgdGhpcy5zcmNCdWYsIHJlbWFpbmluZyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3JjQnVmLmxlbmd0aCA8IHNpemUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoInNyY0J1ZiBzdGlsbCBzbWFsbGVyIHRoYW4gZXhwZWN0ZWQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgbmV3QmxvY2tzID0gdGhpcy5zcmNCdWYuc3ViYXJyYXkoMCwgc2l6ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3JjQnVmID0gdGhpcy5zcmNCdWYuc2xpY2Uoc2l6ZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBzdGFydCA9IDA7IGkgPCBibG9ja0NvdW50OyBpKyssIHN0YXJ0ICs9IHRoaXMuaW5mby5ibG9ja1NpemUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGJsb2NrID0gbmV3QmxvY2tzLnN1YmFycmF5KHN0YXJ0LCBzdGFydCArIHRoaXMuaW5mby5ibG9ja1NpemUpOwogICAgICAgICAgICAgICAgICAgICAgICAvLyB2ZXJpZnkgY2hlY2tzdW0gKGlmIGVuYWJsZWQpCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdpbGwgdGhyb3cgJiBzdG9wIHBsYXlpbmcgb24gbWlzbWF0Y2ghCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnZlcmlmeUNzdW0pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBIQ0FDcmMxNi52ZXJpZnkoYmxvY2ssIHRoaXMuaW5mby5ibG9ja1NpemUgLSAyKTsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGVjcnlwdCAoaWYgZW5jcnlwdGVkKQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jaXBoZXIgIT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2lwaGVyLm1hc2soYmxvY2ssIDAsIHRoaXMuaW5mby5ibG9ja1NpemUgLSAyKTsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gZml4IGNoZWNrc3VtCiAgICAgICAgICAgICAgICAgICAgICAgIEhDQUNyYzE2LmZpeChibG9jaywgdGhpcy5pbmZvLmJsb2NrU2l6ZSAtIDIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5oYXNMb29wKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGp1c3QgY29weSwgbm8gbmVlZCB0byBlbmxhcmdlCiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0Jsb2NrcyA9IG5ld0Jsb2Nrcy5zbGljZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gZW5sYXJnZSAmIGNvcHkKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRhdGEgPSBuZXdCbG9ja3M7CiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0Jsb2NrcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuZmVlZFNpemUpOwogICAgICAgICAgICAgICAgICAgICAgICBuZXdCbG9ja3Muc2V0KGRhdGEpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0aGlzLnRvdGFsRmVkQmxvY2tDb3VudCArPSBibG9ja0NvdW50OwogICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXdCbG9ja3M7CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5rbm93biBjbWQgIiR7dGFzay5jbWR9ImApOwogICAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICB9CiAgICBzdGF0aWMgY3JlYXRlKHNlbGZVcmwsIHNvdXJjZSwga2V5MSwga2V5Miwgc3Via2V5KSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgaWYgKCEoc2VsZlVybCBpbnN0YW5jZW9mIFVSTCkpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAgICAgaWYgKCEoc291cmNlIGluc3RhbmNlb2YgVWludDhBcnJheSB8fCBzb3VyY2UgaW5zdGFuY2VvZiBVUkwpKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgICAgIGxldCBhY3R1YWxTb3VyY2U7CiAgICAgICAgICAgIGxldCBpbmZvOwogICAgICAgICAgICBsZXQgc3JjQnVmID0gdW5kZWZpbmVkOwogICAgICAgICAgICBpZiAoc291cmNlIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogICAgICAgICAgICAgICAgYWN0dWFsU291cmNlID0gc291cmNlLnNsaWNlKDApOwogICAgICAgICAgICAgICAgaW5mbyA9IG5ldyBIQ0FJbmZvKGFjdHVhbFNvdXJjZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoc291cmNlIGluc3RhbmNlb2YgVVJMKSB7CiAgICAgICAgICAgICAgICBjb25zdCBmZXRjaGVkID0geWllbGQgdGhpcy5nZXRIQ0FJbmZvRnJvbVVSTChzb3VyY2UpOwogICAgICAgICAgICAgICAgYWN0dWFsU291cmNlID0gZmV0Y2hlZC5yZWFkZXI7CiAgICAgICAgICAgICAgICBpbmZvID0gZmV0Y2hlZC5pbmZvOwogICAgICAgICAgICAgICAgc3JjQnVmID0gZmV0Y2hlZC5idWZmZXI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoKTsKICAgICAgICAgICAgbGV0IGZlZWRCeXRlTWF4ID0gTWF0aC5mbG9vcih0aGlzLmZlZWRCeXRlTWF4KTsKICAgICAgICAgICAgaWYgKGZlZWRCeXRlTWF4IDwgaW5mby5ibG9ja1NpemUpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAgICAgZmVlZEJ5dGVNYXggLT0gZmVlZEJ5dGVNYXggJSBpbmZvLmJsb2NrU2l6ZTsKICAgICAgICAgICAgY29uc3QgZmVlZEJsb2NrQ291bnQgPSBmZWVkQnl0ZU1heCAvIGluZm8uYmxvY2tTaXplOwogICAgICAgICAgICAvLyBpbml0aWFsaXplIGNpcGhlcgogICAgICAgICAgICBjb25zdCBjaXBoZXIgPSB0aGlzLmdldENpcGhlcihpbmZvLCBrZXkxLCBrZXkyLCBzdWJrZXkpOwogICAgICAgICAgICAvLyBjcmVhdGUgYXVkaW8gY29udGV4dAogICAgICAgICAgICBjb25zdCBhdWRpb0N0eCA9IG5ldyBBdWRpb0NvbnRleHQoewogICAgICAgICAgICAgICAgLy9sYXRlbmN5SGludDogInBsYXliYWNrIiwgLy8gRklYTUUgInBsYXliYWNrIiBzZWVtcyB0byBnbGl0Y2ggaWYgc3dpdGNoZWQgdG8gYmFja2dyb3VuZCBpbiBBbmRyb2lkCiAgICAgICAgICAgICAgICBzYW1wbGVSYXRlOiBpbmZvLmZvcm1hdC5zYW1wbGluZ1JhdGUsCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICAvLyBjcmVhdGUgYXVkaW8gd29ya2xldCBub2RlIChub3QgeWV0IGNvbm5lY3RlZCkKICAgICAgICAgICAgeWllbGQgYXVkaW9DdHguYXVkaW9Xb3JrbGV0LmFkZE1vZHVsZShzZWxmVXJsKTsKICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHsKICAgICAgICAgICAgICAgIG51bWJlck9mSW5wdXRzOiAwLAogICAgICAgICAgICAgICAgbnVtYmVyT2ZPdXRwdXRzOiAxLAogICAgICAgICAgICAgICAgb3V0cHV0Q2hhbm5lbENvdW50OiBbaW5mby5mb3JtYXQuY2hhbm5lbENvdW50XSwKICAgICAgICAgICAgICAgIHByb2Nlc3Nvck9wdGlvbnM6IHsKICAgICAgICAgICAgICAgICAgICByYXdIZWFkZXI6IGluZm8uZ2V0UmF3SGVhZGVyKCksCiAgICAgICAgICAgICAgICAgICAgcHVsbEJsb2NrQ291bnQ6IGZlZWRCbG9ja0NvdW50LAogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgfTsKICAgICAgICAgICAgY29uc3QgaGNhUGxheWVyTm9kZSA9IG5ldyBBdWRpb1dvcmtsZXROb2RlKGF1ZGlvQ3R4LCAiaGNhLWZyYW1lLXBsYXllciIsIG9wdGlvbnMpOwogICAgICAgICAgICAvLyBjcmVhdGUgZ2FpbiBub2RlCiAgICAgICAgICAgIGNvbnN0IGdhaW5Ob2RlID0gYXVkaW9DdHguY3JlYXRlR2FpbigpOwogICAgICAgICAgICBjb25zdCB1bmxvY2tlZCA9IHlpZWxkIHN1c3BlbmRBdWRpb0N0eElmVW5sb2NrZWQoYXVkaW9DdHgpOwogICAgICAgICAgICAvLyBjcmVhdGUgY29udHJvbGxlciBvYmplY3QKICAgICAgICAgICAgcmV0dXJuIG5ldyBIQ0FBdWRpb1dvcmtsZXRIQ0FQbGF5ZXIoc2VsZlVybCwgYXVkaW9DdHgsIHVubG9ja2VkLCBoY2FQbGF5ZXJOb2RlLCBnYWluTm9kZSwgZmVlZEJsb2NrQ291bnQsIGluZm8sIGFjdHVhbFNvdXJjZSwgc3JjQnVmLCBjaXBoZXIpOwogICAgICAgIH0pOwogICAgfQogICAgX3Rlcm1pbmF0ZSgpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICAvLyBJIGRpZG4ndCBmaW5kIHRlcm1pbmF0ZSgpIGZvciBBdWRpb1dvcmtsZXQgc28gSSBtYWRlIG9uZQogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgdGhpcy5oY2FQbGF5ZXJOb2RlLnBvcnQuY2xvc2UoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgZXJyb3IgdHJ5aW5nIHRvIGNsb3NlIG1lc3NhZ2UgcG9ydGAsIGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICB0aGlzLmhjYVBsYXllck5vZGUuZGlzY29ubmVjdCgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBlcnJvciB0cnlpbmcgdG8gZGlzY29ubmVjdCBoY2FQbGF5ZXJOb2RlYCwgZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHRoaXMuZ2Fpbk5vZGUuZGlzY29ubmVjdCgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBlcnJvciB0cnlpbmcgdG8gZGlzY29ubmVjdCBnYWluTm9kZWAsIGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLmF1ZGlvQ3R4LmNsb3NlKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYGVycm9yIHRyeWluZyB0byBjbG9zZSBhdWRpbyBjb250ZXh0YCwgZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgIH0KICAgIGNvbnN0cnVjdG9yKHNlbGZVcmwsIGF1ZGlvQ3R4LCB1bmxvY2tlZCwgaGNhUGxheWVyTm9kZSwgZ2Fpbk5vZGUsIGZlZWRCbG9ja0NvdW50LCBpbmZvLCBzb3VyY2UsIHNyY0J1ZiwgY2lwaGVyKSB7CiAgICAgICAgdGhpcy5faW5pdGlhbGl6ZWQgPSB0cnVlOyAvLyBpbml0aWFsbHkgdGhlcmUgbXVzdCBiZSBzb21ldGhpbmcgdG8gcGxheQogICAgICAgIHRoaXMuaXNQbGF5aW5nID0gZmFsc2U7CiAgICAgICAgdGhpcy5wbGF5SW5CYWNrZ3JvdW5kID0gZmFsc2U7IC8vIEZJWE1FCiAgICAgICAgdGhpcy5yZXF1ZXN0ZWRUb1BsYXkgPSBmYWxzZTsKICAgICAgICB0aGlzLnZlcmlmeUNzdW0gPSBmYWxzZTsKICAgICAgICB0aGlzLnRvdGFsRmVkQmxvY2tDb3VudCA9IDA7CiAgICAgICAgdGhpcy52aXNpYmlsaXR5Q2hhbmdlTGlzdGVuZXIgPSAoKSA9PiB7CiAgICAgICAgICAgIHN3aXRjaCAoZG9jdW1lbnQudmlzaWJpbGl0eVN0YXRlKSB7CiAgICAgICAgICAgICAgICBjYXNlICd2aXNpYmxlJzoKICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5yZXF1ZXN0ZWRUb1BsYXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGxheSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgJ2hpZGRlbic6CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5wbGF5SW5CYWNrZ3JvdW5kKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3BhdXNlKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICB0aGlzLnN0b3BDbWRJdGVtID0gewogICAgICAgICAgICAvLyBleGVjICJyZXNldCIgY21kIGZpcnN0LCBpbiBvcmRlciB0byBhdm9pZCAicmVzaWR1ZSIgYnVyc3Qgbm9pc2UgdG8gYmUgcGxheWVkIGluIHRoZSBmdXR1cmUgKG9ic2VydmVkIGluIENocm9tZSkKICAgICAgICAgICAgY21kOiAicmVzZXQiLCBhcmdzOiBbXSwgaG9vazogewogICAgICAgICAgICAgICAgdGFzazogKHRhc2spID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaXNBbGl2ZSkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJkZWFkIik7CiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzUGxheWluZykKICAgICAgICAgICAgICAgICAgICAgICAgeWllbGQgdGhpcy5fcmVzdW1lKCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRhc2s7CiAgICAgICAgICAgICAgICB9KSwKICAgICAgICAgICAgICAgIHJlc3VsdDogKCkgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMuX3N1c3BlbmQoKTsgLy8gY2FuIG5vdyBzdXNwZW5kCiAgICAgICAgICAgICAgICAgICAgdGhpcy5faW5pdGlhbGl6ZWQgPSBmYWxzZTsgLy8gbm93IHdlIGhhdmUgbm90aGluZyB0byBwbGF5IHVudGlsIG5leHQgc2V0U291cmNlCiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc291cmNlICE9IG51bGwgJiYgISh0aGlzLnNvdXJjZSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMuc291cmNlLmNhbmNlbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5zb3VyY2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSksCiAgICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHRoaXMuc2VsZlVybCA9IHNlbGZVcmw7CiAgICAgICAgdGhpcy5hdWRpb0N0eCA9IGF1ZGlvQ3R4OwogICAgICAgIHRoaXMuX3VubG9ja2VkID0gdW5sb2NrZWQ7CiAgICAgICAgdGhpcy50YXNrUXVldWUgPSBuZXcgSENBVGFza1F1ZXVlKCJNYWluLUhDQUF1ZGlvV29ya2xldEhDQVBsYXllciIsIChtc2csIHRyYW5zKSA9PiBoY2FQbGF5ZXJOb2RlLnBvcnQucG9zdE1lc3NhZ2UobXNnLCB0cmFucyksICh0YXNrKSA9PiB0aGlzLnRhc2tIYW5kbGVyKHRhc2spLCAoKSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7IHJldHVybiB5aWVsZCB0aGlzLl90ZXJtaW5hdGUoKTsgfSkpOwogICAgICAgIGhjYVBsYXllck5vZGUucG9ydC5vbm1lc3NhZ2UgPSAoZXYpID0+IHRoaXMudGFza1F1ZXVlLm1zZ0hhbmRsZXIoZXYpOwogICAgICAgIGhjYVBsYXllck5vZGUucG9ydC5vbm1lc3NhZ2VlcnJvciA9IChldikgPT4gdGhpcy50YXNrUXVldWUuZXJySGFuZGxlcihldik7CiAgICAgICAgaGNhUGxheWVyTm9kZS5vbnByb2Nlc3NvcmVycm9yID0gKGV2KSA9PiB0aGlzLnRhc2tRdWV1ZS5lcnJIYW5kbGVyKGV2KTsKICAgICAgICB0aGlzLmhjYVBsYXllck5vZGUgPSBoY2FQbGF5ZXJOb2RlOwogICAgICAgIHRoaXMuZ2Fpbk5vZGUgPSBnYWluTm9kZTsKICAgICAgICB0aGlzLmZlZWRCbG9ja0NvdW50ID0gZmVlZEJsb2NrQ291bnQ7CiAgICAgICAgdGhpcy5pbmZvID0gaW5mbzsKICAgICAgICB0aGlzLnNvdXJjZSA9IHNvdXJjZTsKICAgICAgICB0aGlzLmNpcGhlciA9IGNpcGhlcjsKICAgICAgICB0aGlzLnNyY0J1ZiA9IHNyY0J1ZjsKICAgICAgICB0aGlzLnNhbXBsZVJhdGUgPSBpbmZvLmZvcm1hdC5zYW1wbGluZ1JhdGU7CiAgICAgICAgdGhpcy5jaGFubmVsQ291bnQgPSBpbmZvLmZvcm1hdC5jaGFubmVsQ291bnQ7CiAgICAgICAgdGhpcy5oYXNMb29wID0gaW5mby5oYXNIZWFkZXJbImxvb3AiXSA/IHRydWUgOiBmYWxzZTsKICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd2aXNpYmlsaXR5Y2hhbmdlJywgdGhpcy52aXNpYmlsaXR5Q2hhbmdlTGlzdGVuZXIpOwogICAgfQogICAgc3RhdGljIGdldENpcGhlcihpbmZvLCBrZXkxLCBrZXkyLCBzdWJrZXkpIHsKICAgICAgICAvLyBoYW5kbGUgc3Via2V5CiAgICAgICAgbGV0IG1peGVkID0gSENBQ2lwaGVyLm1peFdpdGhTdWJrZXkoa2V5MSwga2V5Miwgc3Via2V5KTsKICAgICAgICBrZXkxID0gbWl4ZWQua2V5MTsKICAgICAgICBrZXkyID0gbWl4ZWQua2V5MjsKICAgICAgICBzd2l0Y2ggKGluZm8uY2lwaGVyKSB7CiAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIC8vIG5vdCBlbmNyeXB0ZWQKICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICAgIC8vIGVuY3J5cHRlZCB3aXRoICJubyBrZXkiCiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEhDQUNpcGhlcigibm9uZSIpOyAvLyBpZ25vcmUgZ2l2ZW4ga2V5cwogICAgICAgICAgICBjYXNlIDB4Mzg6CiAgICAgICAgICAgICAgICAvLyBlbmNyeXB0ZWQgd2l0aCBrZXlzIC0gd2lsbCB5aWVsZCBpbmNvcnJlY3Qgd2F2ZWZvcm0gaWYgaW5jb3JyZWN0IGtleXMgYXJlIGdpdmVuIQogICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBIQ0FDaXBoZXIoa2V5MSwga2V5Mik7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoInVua25vd24gY2lwaC50eXBlIik7CiAgICAgICAgfQogICAgfQogICAgc3RhdGljIHJlYWRBbmRBcHBlbmQocmVhZGVyLCBkYXRhLCBtaW5Db3VudCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIGlmIChtaW5Db3VudCA8IDApCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAgICAgY29uc3QgZGVzaXJlZCA9IGRhdGEubGVuZ3RoICsgbWluQ291bnQ7CiAgICAgICAgICAgIGxldCBuZXdEYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGVzaXJlZCk7CiAgICAgICAgICAgIG5ld0RhdGEuc2V0KGRhdGEpOwogICAgICAgICAgICBmb3IgKGxldCBvZmZzZXQgPSBkYXRhLmxlbmd0aDsgb2Zmc2V0IDwgZGVzaXJlZDspIHsKICAgICAgICAgICAgICAgIGNvbnN0IHJlcyA9IHlpZWxkIHJlYWRlci5yZWFkKCk7CiAgICAgICAgICAgICAgICBpZiAocmVzLmRvbmUpCiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmV4cGVjdGVkIHN0cmVhbSBlbmQuIGAKICAgICAgICAgICAgICAgICAgICAgICAgKyBgaXQgaXMgcG9zc2libGUgdGhhdCB0aGUgZG93bmxvYWQgaGFzIGJlZW4gY2FuY2VsZWQgKGJ5IGxhdGVyIHNldFNvdXJjZSksIG9yIHRoZSBmaWxlIGRhdGEgaXMgaW5jb21wbGV0ZWApOwogICAgICAgICAgICAgICAgY29uc3QgYnl0ZXMgPSByZXMudmFsdWU7CiAgICAgICAgICAgICAgICBpZiAoYnl0ZXMubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlcXVpcmVkID0gb2Zmc2V0ICsgYnl0ZXMubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIGlmIChyZXF1aXJlZCA+IG5ld0RhdGEubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nID0gbmV3RGF0YTsKICAgICAgICAgICAgICAgICAgICAgICAgbmV3RGF0YSA9IG5ldyBVaW50OEFycmF5KHJlcXVpcmVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgbmV3RGF0YS5zZXQoZXhpc3RpbmcpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBuZXdEYXRhLnNldChieXRlcywgb2Zmc2V0KTsKICAgICAgICAgICAgICAgICAgICBvZmZzZXQgKz0gYnl0ZXMubGVuZ3RoOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBuZXdEYXRhOwogICAgICAgIH0pOwogICAgfQogICAgc3RhdGljIGdldEhDQUluZm9Gcm9tVVJMKHVybCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIC8vIEZJWE1FIHNlbmQgSFRUUCBSYW5nZSByZXF1ZXN0IHRvIGF2b2lkIGJsb2NraW5nIGxhdGVyIHJlcXVlc3RzIChlc3BlY2lhbGx5IGluIEZpcmVmb3gpCiAgICAgICAgICAgIGNvbnN0IHJlc3AgPSB5aWVsZCBmZXRjaCh1cmwuaHJlZik7CiAgICAgICAgICAgIGlmIChyZXNwLnN0YXR1cyAhPSAyMDApCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHN0YXR1cyAke3Jlc3Auc3RhdHVzfWApOwogICAgICAgICAgICBpZiAocmVzcC5ib2R5ID09IG51bGwpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoInJlc3BvbnNlIGhhcyBubyBib2R5Iik7CiAgICAgICAgICAgIGNvbnN0IHJlYWRlciA9IHJlc3AuYm9keS5nZXRSZWFkZXIoKTsKICAgICAgICAgICAgbGV0IGJ1ZmZlciA9IHlpZWxkIHRoaXMucmVhZEFuZEFwcGVuZChyZWFkZXIsIG5ldyBVaW50OEFycmF5KDApLCA4KTsKICAgICAgICAgICAgY29uc3QgZGF0YU9mZnNldCA9IG5ldyBEYXRhVmlldyhidWZmZXIuYnVmZmVyLCBidWZmZXIuYnl0ZU9mZnNldCwgYnVmZmVyLmJ5dGVMZW5ndGgpLmdldFVpbnQxNig2KTsKICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nID0gZGF0YU9mZnNldCAtIGJ1ZmZlci5sZW5ndGg7CiAgICAgICAgICAgIGlmIChyZW1haW5pbmcgPiAwKSB7CiAgICAgICAgICAgICAgICBidWZmZXIgPSB5aWVsZCB0aGlzLnJlYWRBbmRBcHBlbmQocmVhZGVyLCBidWZmZXIsIHJlbWFpbmluZyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHJlYWRlcjogcmVhZGVyLAogICAgICAgICAgICAgICAgaW5mbzogbmV3IEhDQUluZm8oYnVmZmVyKSwKICAgICAgICAgICAgICAgIGJ1ZmZlcjogYnVmZmVyLnNsaWNlKGRhdGFPZmZzZXQpLAogICAgICAgICAgICB9OwogICAgICAgIH0pOwogICAgfQogICAgc2V0U291cmNlKHNvdXJjZSwga2V5MSwga2V5Miwgc3Via2V5KSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgbGV0IG5ld0luZm87CiAgICAgICAgICAgIGxldCBuZXdTb3VyY2U7CiAgICAgICAgICAgIGxldCBuZXdCdWZmZXIgPSB1bmRlZmluZWQ7CiAgICAgICAgICAgIGNvbnN0IGluaXRpYWxpemVDbWRJdGVtID0gewogICAgICAgICAgICAgICAgY21kOiAiaW5pdGlhbGl6ZSIsIGFyZ3M6IFtudWxsXSwgaG9vazogewogICAgICAgICAgICAgICAgICAgIHRhc2s6ICh0YXNrKSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5pc0FsaXZlKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJkZWFkIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9sZFNvdXJjZSA9IHRoaXMuc291cmNlOwogICAgICAgICAgICAgICAgICAgICAgICAvL2lmIChvbGRTb3VyY2UgaW5zdGFuY2VvZiBSZWFkYWJsZVN0cmVhbURlZmF1bHRSZWFkZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9sZFNvdXJjZSAhPSBudWxsICYmICEob2xkU291cmNlIGluc3RhbmNlb2YgVWludDhBcnJheSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWllbGQgb2xkU291cmNlLmNhbmNlbCgpOyAvLyBzdG9wIGRvd25sb2FkaW5nIGZyb20gcHJldmlvdXMgVVJMCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRklYTUUgRmlyZWZveCBkb2Vzbid0IHNlZW0gdG8gYWJvcnQgcHJldmlvdXMgZG93bmxvYWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgZXJyb3Igd2hlbiBjYW5jZWxsaW5nIHByZXZpb3VzIGRvd25sb2FkLmAsIGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzb3VyY2UgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdTb3VyY2UgPSBzb3VyY2Uuc2xpY2UoMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdJbmZvID0gbmV3IEhDQUluZm8obmV3U291cmNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzb3VyY2UgaW5zdGFuY2VvZiBVUkwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHlpZWxkIEhDQUF1ZGlvV29ya2xldEhDQVBsYXllci5nZXRIQ0FJbmZvRnJvbVVSTChzb3VyY2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3U291cmNlID0gcmVzdWx0LnJlYWRlcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0luZm8gPSByZXN1bHQuaW5mbzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0J1ZmZlciA9IHJlc3VsdC5idWZmZXI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJpbnZhbGlkIHNvdXJjZSIpOwogICAgICAgICAgICAgICAgICAgICAgICAvLyBzYW1wbGUgcmF0ZSBhbmQgY2hhbm5lbCBjb3VudCBpcyBpbW11dGFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZXJlZm9yZSwgdGhlIG9ubHkgd2F5IHRvIGNoYW5nZSB0aGVtIGlzIHRvIHJlY3JlYXRlIGEgbmV3IGluc3RhbmNlLgogICAgICAgICAgICAgICAgICAgICAgICAvLyBob3dldmVyLCB0aGVyZSBpcyBhIG1lbWxlYWsgYnVnIGluIENocm9taXVtLCB0aGF0OgogICAgICAgICAgICAgICAgICAgICAgICAvLyAobm8tbG9uZ2VyLXVzZWQpIGF1ZGlvIHdvcmtsZXQgbm9kZShzKSB3b24ndCBiZSByZWN5Y2xlZDoKICAgICAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9MTI5ODk1NQogICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV3SW5mby5mb3JtYXQuc2FtcGxpbmdSYXRlICE9IHRoaXMuc2FtcGxlUmF0ZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigic2FtcGxlIHJhdGUgbWlzbWF0Y2giKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0luZm8uZm9ybWF0LmNoYW5uZWxDb3VudCAhPSB0aGlzLmNoYW5uZWxDb3VudCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiY2hhbm5lbCBjb3VudCBtaXNtYXRjaCIpOwogICAgICAgICAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLl9yZXN1bWUoKTsgLy8gcmVzdW1lIGl0LCBzbyB0aGF0IGNtZCBjYW4gdGhlbiBiZSBleGVjdXRlZAogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdQcm9jT3B0cyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd0hlYWRlcjogbmV3SW5mby5nZXRSYXdIZWFkZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1bGxCbG9ja0NvdW50OiB0aGlzLmZlZWRCbG9ja0NvdW50LAogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEhDQVRhc2sodGFzay5vcmlnaW4sIHRhc2sudGFza0lELCB0YXNrLmNtZCwgW25ld1Byb2NPcHRzXSwgZmFsc2UpOwogICAgICAgICAgICAgICAgICAgIH0pLCByZXN1bHQ6ICgpID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgeWllbGQgdGhpcy5fc3VzcGVuZCgpOyAvLyBpbml0aWFsaXplZCwgYnV0IGl0J3MgcGF1c2VkLCB1bnRpbCBiZWluZyByZXF1ZXN0ZWQgdG8gc3RhcnQvcGxheSAocmVzdW1lKQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRvdGFsRmVkQmxvY2tDb3VudCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2lwaGVyID0gSENBQXVkaW9Xb3JrbGV0SENBUGxheWVyLmdldENpcGhlcihuZXdJbmZvLCBrZXkxLCBrZXkyLCBzdWJrZXkpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmluZm8gPSBuZXdJbmZvOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNvdXJjZSA9IG5ld1NvdXJjZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zcmNCdWYgPSBuZXdCdWZmZXI7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGFzTG9vcCA9IG5ld0luZm8uaGFzSGVhZGVyWyJsb29wIl0gPyB0cnVlIDogZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2luaXRpYWxpemVkID0gdHJ1ZTsgLy8gYWdhaW4gd2Ugbm93IGhhdmUgc29tZXRoaW5nIHRvIHBsYXkKICAgICAgICAgICAgICAgICAgICB9KQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9OwogICAgICAgICAgICB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5leGVjTXVsdGlDbWQoW3RoaXMuc3RvcENtZEl0ZW0sIGluaXRpYWxpemVDbWRJdGVtXSk7IC8vIGVuc3VyZSBhdG9taWNpdHkKICAgICAgICB9KTsKICAgIH0KICAgIC8vIG5vdCBzdXBwb3NlZCB0byBiZSB1c2VkIGRpcmVjdGx5CiAgICBfcmVzdW1lKCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIGlmICghdGhpcy5pc0FsaXZlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJkZWFkIik7CiAgICAgICAgICAgIGlmICh0aGlzLmlzUGxheWluZykKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgeWllbGQgdGhpcy5hdWRpb0N0eC5yZXN1bWUoKTsKICAgICAgICAgICAgdGhpcy5oY2FQbGF5ZXJOb2RlLmNvbm5lY3QodGhpcy5nYWluTm9kZSk7CiAgICAgICAgICAgIHRoaXMuZ2Fpbk5vZGUuY29ubmVjdCh0aGlzLmF1ZGlvQ3R4LmRlc3RpbmF0aW9uKTsKICAgICAgICAgICAgdGhpcy5pc1BsYXlpbmcgPSB0cnVlOwogICAgICAgICAgICAvLyBtYXJrIGFzIHVubG9ja2VkCiAgICAgICAgICAgIGlmICghdGhpcy5fdW5sb2NrZWQpIHsKICAgICAgICAgICAgICAgIHRoaXMuX3VubG9ja2VkID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgYXVkaW8gY29udGV4dCBmb3Igc2FtcGxlUmF0ZT0ke3RoaXMuYXVkaW9DdHguc2FtcGxlUmF0ZX0gaXMgbm93IHJlc3VtZWQvdW5sb2NrZWRgKTsKICAgICAgICAgICAgfQogICAgICAgIH0pOwogICAgfQogICAgX3N1c3BlbmQoKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgaWYgKCF0aGlzLmlzQWxpdmUpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImRlYWQiKTsKICAgICAgICAgICAgaWYgKCF0aGlzLmlzUGxheWluZykKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgdGhpcy5oY2FQbGF5ZXJOb2RlLmRpc2Nvbm5lY3QoKTsKICAgICAgICAgICAgdGhpcy5nYWluTm9kZS5kaXNjb25uZWN0KCk7CiAgICAgICAgICAgIHlpZWxkIHRoaXMuYXVkaW9DdHguc3VzcGVuZCgpOwogICAgICAgICAgICB0aGlzLmlzUGxheWluZyA9IGZhbHNlOwogICAgICAgIH0pOwogICAgfQogICAgX3BhdXNlKCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHlpZWxkIHRoaXMuc2V0UGxheWluZyhmYWxzZSk7CiAgICAgICAgfSk7CiAgICB9CiAgICBfcGxheSgpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICAvLyBpbiBhcHBsZSB3ZWJraXQsIGF1ZGlvIGNvbnRleHQgaXMgc3VzcGVuZGVkL2xvY2tlZCBpbml0aWFsbHksCiAgICAgICAgICAgIC8vIChvdGhlciBicm93c2VycyBsaWtlIEZpcmVmb3ggbWF5IGhhdmUgc2ltaWxhciBidXQgbGVzcyBzdHJpY3QgcmVzdHJpY3Rpb25zKQogICAgICAgICAgICAvLyB0byByZXN1bWUvdW5sb2NrIGl0LCBmaXJzdCByZXN1bWUoKSBjYWxsIG11c3QgYmUgdHJpZ2dlcmVkIGJ5IGZyb20gVUkgZXZlbnQsCiAgICAgICAgICAgIC8vIHdoaWNoIG11c3Qgbm90IGJlIGFmdGVyIGF3YWl0CiAgICAgICAgICAgIHlpZWxkIHRoaXMuc2V0UGxheWluZyh0cnVlKTsKICAgICAgICB9KTsKICAgIH0KICAgIC8vIHdyYXBlZCB0byBlbnN1cmUgYXRvbWljaXR5CiAgICBzZXRQbGF5aW5nKHRvUGxheSkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIC8vIHNpbWxpbGFyIHRvIHN0b3BDbWRJdGVtIGFib3ZlLCBzZW5kICJwYXVzZSIgY21kIHRvIGF2b2lkICJyZXNpZHVlIiBidXJzdCBub2lzZQogICAgICAgICAgICB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5leGVjQ21kKHRvUGxheSA/ICJyZXN1bWUiIDogInBhdXNlIiwgW10sIHsKICAgICAgICAgICAgICAgIHRhc2s6ICh0YXNrKSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzQWxpdmUpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiZGVhZCIpOwogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzUGxheWluZykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodG9QbGF5KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5pc0R1bW15ID0gdHJ1ZTsgLy8gYWxyZWFkeSByZXN1bWVkLCBub3Qgc2VuZGluZyBjbWQKICAgICAgICAgICAgICAgICAgICAgICAgLy8gZWxzZSBzaG91bGQgc3RpbGwga2VlcCBwbGF5aW5nIHVudGlsICJwYXVzZSIgY21kIHJldHVybnMKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0b1BsYXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5faW5pdGlhbGl6ZWQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3QgaW5pdGlhbGl6ZWQgYnV0IHN0aWxsIGF0dGVtcHQgdG8gcmVzdW1lYCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLl9yZXN1bWUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXNrLmlzRHVtbXkgPSB0cnVlOyAvLyBhbHJlYWR5IHBhdXNlZCwgbm90IHNlbmRpbmcgY21kCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiB0YXNrOwogICAgICAgICAgICAgICAgfSksCiAgICAgICAgICAgICAgICByZXN1bHQ6ICgpID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgICAgICAgICBpZiAodG9QbGF5KQogICAgICAgICAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLl9yZXN1bWUoKTsKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMuX3N1c3BlbmQoKTsKICAgICAgICAgICAgICAgIH0pCiAgICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgfQogICAgcGF1c2UoKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgdGhpcy5yZXF1ZXN0ZWRUb1BsYXkgPSBmYWxzZTsKICAgICAgICAgICAgeWllbGQgdGhpcy5fcGF1c2UoKTsKICAgICAgICB9KTsKICAgIH0KICAgIHBsYXkoKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgdGhpcy5yZXF1ZXN0ZWRUb1BsYXkgPSB0cnVlOwogICAgICAgICAgICB5aWVsZCB0aGlzLl9wbGF5KCk7CiAgICAgICAgfSk7CiAgICB9CiAgICBzdG9wKCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIC8vIGNhbiB1bmxvY2sgdGhlIGxvY2tlZCBhdWRpbyBjb250ZXh0IGFzIHdlbGwgYmVjYXVzZSBpdCdzIHJlc3VtZWQgZmlyc3RseSBiZWZvcmUgZmluYWxseSBzdXNwZW5kZWQKICAgICAgICAgICAgdGhpcy5yZXF1ZXN0ZWRUb1BsYXkgPSBmYWxzZTsKICAgICAgICAgICAgY29uc3QgaXRlbSA9IHRoaXMuc3RvcENtZEl0ZW07CiAgICAgICAgICAgIHlpZWxkIHRoaXMudGFza1F1ZXVlLmV4ZWNDbWQoaXRlbS5jbWQsIGl0ZW0uYXJncywgaXRlbS5ob29rKTsKICAgICAgICB9KTsKICAgIH0KICAgIHNodXRkb3duKGZvcmNpYmx5ID0gZmFsc2UpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICBpZiAoIXRoaXMuaXNBbGl2ZSkgewogICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgYWxyZWFkeSBzaHV0ZG93bmApOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd2aXNpYmlsaXR5Y2hhbmdlJywgdGhpcy52aXNpYmlsaXR5Q2hhbmdlTGlzdGVuZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHlpZWxkIHRoaXMudGFza1F1ZXVlLnNodXRkb3duKGZvcmNpYmx5KTsKICAgICAgICB9KTsKICAgIH0KfQpIQ0FBdWRpb1dvcmtsZXRIQ0FQbGF5ZXIuZmVlZEJ5dGVNYXggPSAzMjc2ODsKLy8gY3JlYXRlICYgY29udHJvbCB3b3JrZXIKZXhwb3J0IGNsYXNzIEhDQVdvcmtlciB7CiAgICBnZXQgaXNBbGl2ZSgpIHsKICAgICAgICByZXR1cm4gdGhpcy50YXNrUXVldWUuaXNBbGl2ZTsKICAgIH0KICAgIHNodXRkb3duKGZvcmNpYmx5ID0gZmFsc2UpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICBpZiAodGhpcy50YXNrUXVldWUuaXNBbGl2ZSkKICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMudGFza1F1ZXVlLnNodXRkb3duKGZvcmNpYmx5KTsKICAgICAgICAgICAgaWYgKHRoaXMuYXdIY2FQbGF5ZXIgIT0gbnVsbCAmJiB0aGlzLmF3SGNhUGxheWVyLmlzQWxpdmUpCiAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLmF3SGNhUGxheWVyLnNodXRkb3duKGZvcmNpYmx5KTsKICAgICAgICB9KTsKICAgIH0KICAgIHRpY2soKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgeWllbGQgdGhpcy50YXNrUXVldWUuZXhlY0NtZCgibm9wIiwgW10pOwogICAgICAgICAgICB0aGlzLmxhc3RUaWNrID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7CiAgICAgICAgfSk7CiAgICB9CiAgICB0b2NrKHRleHQgPSAiIikgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHlpZWxkIHRoaXMudGFza1F1ZXVlLmV4ZWNDbWQoIm5vcCIsIFtdKTsKICAgICAgICAgICAgY29uc3QgZHVyYXRpb24gPSBuZXcgRGF0ZSgpLmdldFRpbWUoKSAtIHRoaXMubGFzdFRpY2s7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKGAke3RleHR9IHRvb2sgJHtkdXJhdGlvbn0gbXNgKTsKICAgICAgICAgICAgcmV0dXJuIGR1cmF0aW9uOwogICAgICAgIH0pOwogICAgfQogICAgc3RhdGljIGNyZWF0ZShzZWxmVXJsKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgaWYgKHR5cGVvZiBzZWxmVXJsID09PSAic3RyaW5nIikKICAgICAgICAgICAgICAgIHNlbGZVcmwgPSBuZXcgVVJMKHNlbGZVcmwsIGRvY3VtZW50LmJhc2VVUkkpOwogICAgICAgICAgICBlbHNlIGlmICghKHNlbGZVcmwgaW5zdGFuY2VvZiBVUkwpKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJzZWxmVXJsIG11c3QgYmUgZWl0aGVyIHN0cmluZyBvciBVUkwiKTsKICAgICAgICAgICAgLy8gZmV0Y2ggJiBzYXZlIGhjYS5qcyBhcyBibG9iIGluIGFkdmFuY2UsIHRvIGF2b2lkIGNyZWF0aW5nIHdvcmtlciBiZWluZyBibG9ja2VkIGxhdGVyLCBsaWtlOgogICAgICAgICAgICAvLyAoSSBvYnNlcnZlZCB0aGlzIHByb2JsZW0gaW4gRmlyZWZveCkKICAgICAgICAgICAgLy8gY3JlYXRpbmcgSENBQXVkaW9Xb3JrbGV0SENBUGxheWVyIHJlcXVpcmVzIGluZm9ybWF0aW9uIGZyb20gSENBLCB3aGljaCBpcyBzYW1wbGUgcmF0ZSBhbmQgY2hhbm5lbCBjb3VudDsKICAgICAgICAgICAgLy8gaG93ZXZlciwgZmV0Y2hpbmcgSENBIChvcmlnaW5hbGx5IHN1cHBvc2VkIHRvIGJlIHByb2dyZXNzaXZlL3N0cmVhbWVkKSBibG9ja3MgbGF0ZXIgcmVxdWVzdCB0byBmZXRjaCBoY2EuanMsCiAgICAgICAgICAgIC8vIHNvIHRoYXQgSENBQXVkaW9Xb3JrbGV0SENBUGxheWVyIGNhbiBvbmx5IGJlIGNyZWF0ZWQgYWZ0ZXIgZmluaXNoaW5nIGRvd25sb2FkaW5nIHRoZSB3aG9sZSBIQ0EsCiAgICAgICAgICAgIC8vIHdoaWNoIG9idmlvdXNseSBkZWZlYXRzIHRoZSBwdXJwb3NlIG9mIHN0cmVhbWluZyBIQ0EKICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSB5aWVsZCBmZXRjaChzZWxmVXJsLmhyZWYpOwogICAgICAgICAgICAvLyBGaXJlZm94IGN1cnJlbnRseSBkb2VzIG5vdCBzdXBwb3J0IEVDTUFTY3JpcHQgbW9kdWxlcyBpbiBXb3JrZXIsCiAgICAgICAgICAgIC8vIHRoZXJlZm9yZSB3ZSBtdXN0IHN0cmlwIGFsbCBleHBvcnQgZGVjbGFyYXRpb25zCiAgICAgICAgICAgIGNvbnN0IG9yaWdUZXh0ID0geWllbGQgcmVzcG9uc2UudGV4dCgpOwogICAgICAgICAgICBjb25zdCBjb252ZXJ0ZWRUZXh0ID0gKCJcbiIgKyBvcmlnVGV4dCkucmVwbGFjZSgvKChcbnw7KVsgXHRdKikoKGV4cG9ydFsgXHRdK1x7Lio/XH1bIFx0XSo7ezAsMX0pK3woZXhwb3J0WyBcdF0rKSkvZywgIiQxIikuc2xpY2UoMSk7CiAgICAgICAgICAgIGNvbnN0IGJsb2IgPSBuZXcgQmxvYihbY29udmVydGVkVGV4dF0sIHsgdHlwZTogInRleHQvamF2YXNjcmlwdCIgfSk7CiAgICAgICAgICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7CiAgICAgICAgICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGJsb2IpOwogICAgICAgICAgICBjb25zdCBkYXRhVVJJID0geWllbGQgbmV3IFByb21pc2UoKHJlcykgPT4gewogICAgICAgICAgICAgICAgcmVhZGVyLm9ubG9hZGVuZCA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXMocmVhZGVyLnJlc3VsdCk7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc2VsZlVybCA9IG5ldyBVUkwoZGF0YVVSSSwgZG9jdW1lbnQuYmFzZVVSSSk7CiAgICAgICAgICAgIHJldHVybiBuZXcgSENBV29ya2VyKHNlbGZVcmwsIGJsb2IpOwogICAgICAgIH0pOwogICAgfQogICAgY29uc3RydWN0b3Ioc2VsZlVybCwgc2VsZkJsb2IpIHsKICAgICAgICB0aGlzLmxhc3RUaWNrID0gMDsKICAgICAgICB0cnkgewogICAgICAgICAgICB0aGlzLmhjYVdvcmtlciA9IG5ldyBXb3JrZXIoc2VsZlVybCwgeyB0eXBlOiAibW9kdWxlIiB9KTsgLy8gc2V0dGluZyB0eXBlIHRvICJtb2R1bGUiIGlzIGN1cnJlbnRseSBib2d1cyBpbiBGaXJlZm94CiAgICAgICAgfQogICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgIC8vIHdvcmthcm91bmQgZm9yIGxlZ2FjeSBpT1MgU2FmYXJpCiAgICAgICAgICAgIGlmIChzZWxmQmxvYiA9PSBudWxsIHx8ICEoc2VsZkJsb2IgaW5zdGFuY2VvZiBCbG9iKSkKICAgICAgICAgICAgICAgIHRocm93IGU7CiAgICAgICAgICAgIGNvbnN0IG9ialVybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoc2VsZkJsb2IpOwogICAgICAgICAgICB0aGlzLmhjYVdvcmtlciA9IG5ldyBXb3JrZXIob2JqVXJsLCB7IHR5cGU6ICJtb2R1bGUiIH0pOwogICAgICAgICAgICBVUkwucmV2b2tlT2JqZWN0VVJMKG9ialVybCk7CiAgICAgICAgfQogICAgICAgIHRoaXMuc2VsZlVybCA9IHNlbGZVcmw7CiAgICAgICAgdGhpcy50YXNrUXVldWUgPSBuZXcgSENBVGFza1F1ZXVlKCJNYWluLUhDQVdvcmtlciIsIChtc2csIHRyYW5zKSA9PiB0aGlzLmhjYVdvcmtlci5wb3N0TWVzc2FnZShtc2csIHRyYW5zKSwgKHRhc2spID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgc3dpdGNoICh0YXNrLmNtZCkgewogICAgICAgICAgICAgICAgY2FzZSAic2VsZi1kZXN0cnVjdCI6IC8vIGRvZXNuJ3Qgc2VlbSB0byBoYXZlIGEgY2hhbmNlIHRvIGJlIGNhbGxlZAogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYGhjYVdvcmtlciByZXF1ZXN0ZWQgdG8gc2VsZi1kZXN0cnVjdGApOwogICAgICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMudGFza1F1ZXVlLnNodXRkb3duKHRydWUpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfSksICgpID0+IHRoaXMuaGNhV29ya2VyLnRlcm1pbmF0ZSgpKTsKICAgICAgICB0aGlzLmhjYVdvcmtlci5vbm1lc3NhZ2UgPSAobXNnKSA9PiB0aGlzLnRhc2tRdWV1ZS5tc2dIYW5kbGVyKG1zZyk7CiAgICAgICAgdGhpcy5oY2FXb3JrZXIub25lcnJvciA9IChtc2cpID0+IHRoaXMudGFza1F1ZXVlLmVyckhhbmRsZXIobXNnKTsKICAgICAgICB0aGlzLmhjYVdvcmtlci5vbm1lc3NhZ2VlcnJvciA9IChtc2cpID0+IHRoaXMudGFza1F1ZXVlLmVyckhhbmRsZXIobXNnKTsKICAgIH0KICAgIC8vIGNvbW1hbmRzCiAgICBnZXRUcmFuc2ZlckNvbmZpZygpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy50YXNrUXVldWUuZ2V0VHJhbnNmZXJDb25maWcoKTsKICAgICAgICB9KTsKICAgIH0KICAgIGNvbmZpZ1RyYW5zZmVyKHRyYW5zZmVyQXJncywgcmVwbHlBcmdzKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgcmV0dXJuIHlpZWxkIHRoaXMudGFza1F1ZXVlLmNvbmZpZ1RyYW5zZmVyKHRyYW5zZmVyQXJncywgcmVwbHlBcmdzKTsKICAgICAgICB9KTsKICAgIH0KICAgIGZpeEhlYWRlckNoZWNrc3VtKGhjYSkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5leGVjQ21kKCJmaXhIZWFkZXJDaGVja3N1bSIsIFtoY2FdKTsKICAgICAgICB9KTsKICAgIH0KICAgIGZpeENoZWNrc3VtKGhjYSkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5leGVjQ21kKCJmaXhDaGVja3N1bSIsIFtoY2FdKTsKICAgICAgICB9KTsKICAgIH0KICAgIGZpbmRLZXkoaGNhLCBnaXZlbktleUxpc3QsIHN1YmtleSwgdGhyZXNob2xkID0gMC41LCBkZXB0aCA9IDEwMjQpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy50YXNrUXVldWUuZXhlY0NtZCgiZmluZEtleSIsIFtoY2EsIGdpdmVuS2V5TGlzdCwgc3Via2V5LCB0aHJlc2hvbGQsIGRlcHRoXSk7CiAgICAgICAgfSk7CiAgICB9CiAgICBkZWNyeXB0KGhjYSwga2V5MSwga2V5Miwgc3Via2V5KSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgcmV0dXJuIHlpZWxkIHRoaXMudGFza1F1ZXVlLmV4ZWNDbWQoImRlY3J5cHQiLCBbaGNhLCBrZXkxLCBrZXkyLCBzdWJrZXldKTsKICAgICAgICB9KTsKICAgIH0KICAgIGVuY3J5cHQoaGNhLCBrZXkxLCBrZXkyLCBzdWJrZXkpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy50YXNrUXVldWUuZXhlY0NtZCgiZW5jcnlwdCIsIFtoY2EsIGtleTEsIGtleTIsIHN1YmtleV0pOwogICAgICAgIH0pOwogICAgfQogICAgYWRkSGVhZGVyKGhjYSwgc2lnLCBuZXdEYXRhKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgcmV0dXJuIHlpZWxkIHRoaXMudGFza1F1ZXVlLmV4ZWNDbWQoImFkZEhlYWRlciIsIFtoY2EsIHNpZywgbmV3RGF0YV0pOwogICAgICAgIH0pOwogICAgfQogICAgYWRkQ2lwaGVySGVhZGVyKGhjYSwgY2lwaGVyVHlwZSkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLnRhc2tRdWV1ZS5leGVjQ21kKCJhZGRDaXBoZXJIZWFkZXIiLCBbaGNhLCBjaXBoZXJUeXBlXSk7CiAgICAgICAgfSk7CiAgICB9CiAgICBkZWNvZGUoaGNhLCBtb2RlID0gMzIsIGxvb3AgPSAwLCB2b2x1bWUgPSAxLjApIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy50YXNrUXVldWUuZXhlY0NtZCgiZGVjb2RlIiwgW2hjYSwgbW9kZSwgbG9vcCwgdm9sdW1lXSk7CiAgICAgICAgfSk7CiAgICB9CiAgICBsb2FkSENBRm9yUGxheWluZyhoY2EsIGtleTEsIGtleTIsIHN1YmtleSkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIGlmICh0eXBlb2YgaGNhID09PSAic3RyaW5nIikgewogICAgICAgICAgICAgICAgaWYgKGhjYSA9PT0gIiIpCiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJlbXB0eSBVUkwiKTsKICAgICAgICAgICAgICAgIGhjYSA9IG5ldyBVUkwoaGNhLCBkb2N1bWVudC5iYXNlVVJJKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmICghKGhjYSBpbnN0YW5jZW9mIFVSTCkgJiYgIShoY2EgaW5zdGFuY2VvZiBVaW50OEFycmF5KSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiaGNhIG11c3QgYmUgZWl0aGVyIFVSTCBvciBVaW50OEFycmF5Iik7CiAgICAgICAgICAgIGlmICh0aGlzLmF3SGNhUGxheWVyID09IG51bGwpIHsKICAgICAgICAgICAgICAgIHRoaXMuYXdIY2FQbGF5ZXIgPSB5aWVsZCBIQ0FBdWRpb1dvcmtsZXRIQ0FQbGF5ZXIuY3JlYXRlKHRoaXMuc2VsZlVybCwgaGNhLCBrZXkxLCBrZXkyLCBzdWJrZXkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLmF3SGNhUGxheWVyLnNldFNvdXJjZShoY2EsIGtleTEsIGtleTIsIHN1YmtleSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYGF3SGNhUGxheWVyLnNldFNvdXJjZSBmYWlsZWQsIGF0dGVtcHQgcmVjcmVhdGUgcGxheWVyIGluc3RhbmNlYCwgZSk7CiAgICAgICAgICAgICAgICAgICAgLy8gRklYTUUgbWVtbGVhawogICAgICAgICAgICAgICAgICAgIHRoaXMuYXdIY2FQbGF5ZXIgPSB5aWVsZCBIQ0FBdWRpb1dvcmtsZXRIQ0FQbGF5ZXIuY3JlYXRlKHRoaXMuc2VsZlVybCwgaGNhLCBrZXkxLCBrZXkyLCBzdWJrZXkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICB9CiAgICBwYXVzZVBsYXlpbmcoKSB7CiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsKICAgICAgICAgICAgaWYgKHRoaXMuYXdIY2FQbGF5ZXIgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgICAgICAgICB5aWVsZCB0aGlzLmF3SGNhUGxheWVyLnBhdXNlKCk7CiAgICAgICAgfSk7CiAgICB9CiAgICByZXN1bWVQbGF5aW5nKCkgewogICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7CiAgICAgICAgICAgIGlmICh0aGlzLmF3SGNhUGxheWVyID09IG51bGwpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTsKICAgICAgICAgICAgeWllbGQgdGhpcy5hd0hjYVBsYXllci5wbGF5KCk7CiAgICAgICAgfSk7CiAgICB9CiAgICBzdG9wUGxheWluZygpIHsKICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgewogICAgICAgICAgICBpZiAodGhpcy5hd0hjYVBsYXllciA9PSBudWxsKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgICAgIHlpZWxkIHRoaXMuYXdIY2FQbGF5ZXIuc3RvcCgpOwogICAgICAgIH0pOwogICAgfQp9Cg==", document.baseURI);
var hcaJsModule, hcaJsObjUrl, AWBArchive, HCAInfo, HCAWorker, HCAWebAudioLoopPlayer;
// mime types
const defMimeType = "application/octet-stream";
const mimeTypeMap = {
wav: "audio/x-wav",
hca: defMimeType,
}
// HCAWorker instance
var worker = null;
// HCAWebAudioLoopPlayer instance
var webAudioLoopPlayer = null;
// dragged file
var draggedFile = null;
// parsed AWB
var parsedAWB = null;
// local file picker
const localfile = document.getElementById("localfile");
const localfileform = document.getElementById("localfileform");
// onchange does not work on iOS Safari
localfile.addEventListener("change", function (ev) { buttons.loadfilebtn = this.files.length > 0; });
// reset state on refresh
// https://bugzilla.mozilla.org/show_bug.cgi?id=685657
localfileform.reset();
// workaround for iOS Safari file picker
document.getElementById("hcaonly").addEventListener("change", function (ev) {
localfile.accept = ev.target.checked ? ".hca,application/octet-stream" : "";
});
// AWB subsong switcher
const awbsubsongswitcher = document.getElementById("awbsubsongswitcher");
AWBSubsongSelect = function (selected, doNotPlay) {
let index = selected.id.replace(/^awb_subsong_index_/, "");
fileName = `${AWBFileName}_${index}.hca`;
hcaFileData.original.data = parsedAWB.hcaFiles[index].file;
if (!doNotPlay && document.getElementById("awautoplayondrop").checked) {
// doNotPlay=true, will play in "drop" event
buttons.awloadwholehcabtn = "click";
buttons.awresumebtn = "click";
}
}
function setAWBSubSongSwitcher(enable) {
if (!enable) {
awbsubsongswitcher.innerHTML = "";
keys.subkey = "0x0";
return;
}
const subkey = `0x${parsedAWB.subkey.toString(16).toUpperCase()}`;
console.log(`AWB archive version=[${parsedAWB.version}]`
+ `, subsong count=[${parsedAWB.hcaFiles.length}], subkey=[${subkey}]`);
const listEntries = parsedAWB.hcaFiles.map((entry, index) => {
// filter out non-HCA entries
if (entry.file.byteLength == 0) return;
try {
new HCAInfo(entry.file);
} catch (e) {
return;
}
// convert to HTML
return `<div><input type=\"radio\" name=\"awb_subsong_id\" id=\"awb_subsong_index_${index}\"`
+ ` onclick=\"AWBSubsongSelect(this);\">`
+ `<label for=\"awb_subsong_index_${index}\">waveID=${entry.waveID}</label>`
+ `</div>`;
}).filter((str) => str != null).join("\n");
keys.subkey = subkey;
awbsubsongswitcher.innerHTML = `<fieldset><legend>AWB archive subsongs</legend>\n`
+ `${listEntries}\n`
+ `</fieldset>`;
}
// input HCA URL
const urlinput = document.getElementById("urlinput");
// file name
var AWBFileName = null;
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],
["Duration (calc)", `${info.duration.toFixed(3)}s`],
]],
["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],
["StartTime (calc)", `${info.loopStartTime.toFixed(3)}s`],
["EndTime (calc)", `${info.loopEndTime.toFixed(3)}s`],
["Duration (calc)", `${info.loopDuration.toFixed(3)}s`],
]],
["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, subkey: 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 },
});
}
async function testAndFindValidKeyAsync() {
worker.tick();
let resultPromise = worker.findKey(hcaFileData.original.data, [[keys.key1, keys.key2]], keys.subkey);
worker.tock(`findKey`);
let result = await resultPromise;
if (result != null) {
result = result.map((k) => `0x${k.toString(16).toUpperCase()}`);
console.log(`found valid key`, result);
keys.key1 = result[0];
keys.key2 = result[1];
} else {
console.warn(`not encrypted, or no valid key found!`);
}
}
// 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,
},
}
function setVolume(val) {
val = Number(val) / 100;
if (worker != null && worker.awHcaPlayer != null) {
worker.awHcaPlayer.volume = val;
}
if (webAudioLoopPlayer != null) {
webAudioLoopPlayer.volume = val;
}
}
document.getElementById("volumeslider").addEventListener("input", (ev) => {
const val = ev.target.value;
document.getElementById("volumeinput").value = val;
setVolume(val);
});
document.getElementById("volumeinput").addEventListener("input", (ev) => {
const val = ev.target.value;
const slider = document.getElementById("volumeslider");
if (slider.value != val) {
slider.value = val;
}
setVolume(val);
});
// play in background checkbox
const awplayinbackground = document.getElementById("awplayinbackground");
awplayinbackground.addEventListener("change", (ev) => {
if (worker == null || worker.awHcaPlayer == null) return;
worker.awHcaPlayer.playInBackground = ev.target.checked;
}, false);
const webaudioplayinbackground = document.getElementById("webaudioplayinbackground");
webaudioplayinbackground.addEventListener("change", (ev) => {
if (webAudioLoopPlayer == null) return;
webAudioLoopPlayer.playInBackground = ev.target.checked;
}, false);
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: "decodetoh5btn",
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;
refNode.parentElement.insertBefore(document.createElement("br"), refNode);
refNode.parentElement.insertBefore(el, refNode);
// update value
this.value = val;
},
});
}
function clearAllData() {
localfileform.reset();
for (let suffix in hcaFileData) {
hcaFileData[suffix].data = null;
}
setAWBSubSongSwitcher(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 (AWBArchive == null) AWBArchive = hcaJsModule.AWBArchive;
if (HCAInfo == null) HCAInfo = hcaJsModule.HCAInfo;
if (HCAWorker == null) HCAWorker = hcaJsModule.HCAWorker;
if (HCAWebAudioLoopPlayer == null) HCAWebAudioLoopPlayer = hcaJsModule.HCAWebAudioLoopPlayer;
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;
if (file.arrayBuffer == null) {
let objUrl = URL.createObjectURL(file);
let resp = await fetch(objUrl);
URL.revokeObjectURL(objUrl);
ab = await resp.arrayBuffer();
} else {
ab = await file.arrayBuffer();
}
// parse AWB
AWBFileName = null;
parsedAWB = null;
if (AWBArchive.isAWB(new Uint8Array(ab))) {
try {
parsedAWB = new AWBArchive(new Uint8Array(ab));
} catch (e) {
console.error(`error parsing AWB archive`, e);
}
}
if (parsedAWB != null && parsedAWB.hcaFiles.length > 0) {
AWBFileName = fileName;
setAWBSubSongSwitcher(true);
AWBSubsongSelect({ id: "awb_subsong_index_0" }, true); // doNotPlay=true, will play in "drop" event
} else {
setAWBSubSongSwitcher(null);
hcaFileData.original.data = new Uint8Array(ab);
}
// find valid key
await testAndFindValidKeyAsync();
self.textContent = "load picked file (successful)";
// no need to let the button bounce
// next step
buttons.awloadwholehcabtn = true;
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();
// parse AWB
AWBFileName = null;
parsedAWB = null;
if (AWBArchive.isAWB(new Uint8Array(ab))) {
try {
parsedAWB = new AWBArchive(new Uint8Array(ab));
} catch (e) {
console.error(`error parsing AWB archive`, e);
}
}
if (parsedAWB != null && parsedAWB.hcaFiles.length > 0) {
AWBFileName = fileName;
setAWBSubSongSwitcher(true);
AWBSubsongSelect({ id: "awb_subsong_index_0" }, true); // doNotPlay=true, will play in "drop" event
} else {
setAWBSubSongSwitcher(null);
hcaFileData.original.data = new Uint8Array(ab);
}
self.textContent = "download (successful)";
// find valid key
await testAndFindValidKeyAsync();
// let the button bounce
self.disabled = false;
// next step
buttons.awloadwholehcabtn = true;
buttons.infobtn = true;
buttons.fixcsumbtn = true;
},
awloadwholehcabtn: async (self) => {
try {
await worker.loadHCAForPlaying(hcaFileData.original.data, keys.key1, keys.key2, keys.subkey);
worker.awHcaPlayer.playInBackground = awplayinbackground.checked;
self.textContent = "Load (successful)";
} catch (e) {
self.textContent = "Load (failed)";
console.error(e);
}
// let the button bounce
self.disabled = false;
// next step
buttons.awpausebtn = false;
buttons.awresumebtn = true;
buttons.awstopbtn = true;
// TODO pause/rewind/fast-forward etc
},
awloadfromurlbtn: async (self) => {
try {
await worker.loadHCAForPlaying(urlinput.value, keys.key1, keys.key2, keys.subkey);
worker.awHcaPlayer.playInBackground = awplayinbackground.checked;
self.textContent = "Load (successful)";
} catch (e) {
self.textContent = "Load (failed)";
console.error(e);
}
// let the button bounce
self.disabled = false;
// next step
buttons.awpausebtn = false;
buttons.awresumebtn = true;
buttons.awstopbtn = true;
// TODO rewind/fast-forward etc
},
awpausebtn: async (self) => {
try {
await worker.pausePlaying();
self.textContent = "Paused";
} catch (e) {
self.textContent = "Pause (Error)";
console.log(e);
// let the button bounce
self.disabled = false;
}
// next step
buttons.awresumebtn = true;
},
awresumebtn: async (self) => {
try {
await worker.resumePlaying();
self.textContent = "Playing/Resumed";
} catch (e) {
self.textContent = "Play/Resume (Error)";
console.log(e);
// let the button bounce
self.disabled = false;
}
// next step
buttons.awpausebtn = true;
},
awstopbtn: async (self) => {
try {
await worker.stopPlaying();
self.textContent = "Stopped";
} catch (e) {
self.textContent = "Stop (Error)";
console.log(e);
// let the button bounce
self.disabled = false;
}
// next step
buttons.awpausebtn = false;
buttons.awresumebtn = false;
},
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.decodetoh5btn = !isEncrypted;
buttons.decodetowabtn = !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;
},
decodetoh5btn: 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;
},
decodetowabtn: 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 = HCAWebAudioLoopPlayer.create(hca, worker, decodingParam.volumePerCent / 100);
worker.tock("decoding");
let newPlayer = await decodedPromise;
// update player instance
if (webAudioLoopPlayer != null) await webAudioLoopPlayer.stop();
webAudioLoopPlayer = newPlayer;
webAudioLoopPlayer.playInBackground = webaudioplayinbackground.checked;
self.textContent = "decode (done)";
// next step (play)
buttons.webaudioplaybtn = true;
} catch (e) {
console.error(e);
self.textContent = "decode (failed)";
}
// let the button bounce
self.disabled = false;
},
webaudioplaybtn: async (self) => {
try {
webAudioLoopPlayer.play();
self.textContent = "Playing/Resumed";
} catch (e) {
self.textContent = "Play/Resume (Error)";
console.log(e);
// let the button bounce
self.disabled = false;
}
// next step
buttons.webaudiopausebtn = true;
buttons.webaudiostopbtn = true;
},
webaudiopausebtn: async (self) => {
try {
webAudioLoopPlayer.pause();
self.textContent = "Paused";
} catch (e) {
self.textContent = "Pause (Error)";
console.log(e);
// let the button bounce
self.disabled = false;
}
// next step
buttons.webaudioplaybtn = true;
},
webaudiostopbtn: async (self) => {
try {
await webAudioLoopPlayer.stop();
self.textContent = "Stopped";
} catch (e) {
self.textContent = "Stop (Error)";
console.log(e);
// let the button bounce
self.disabled = false;
}
// next step
buttons.webaudiopausebtn = false;
buttons.webaudioplaybtn = 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;
case "awloadwholehcabtn":
buttons[btnID] = false;
break;
case "awloadfromurlbtn":
buttons[btnID] = true;
break;
case "awresumebtn":
case "awpausebtn":
case "awstopbtn":
// do not reset except on refresh
if (exceptBtnID == null) buttons[btnID] = false;
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 decodetoh5btn and decodetowabtn if necessary
if (!isEncrypting) {
buttons.decodetoh5btn = false;
buttons.decodetowabtn = 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;