@clickview/library-editor 1.1.45-rc.3 → 1.1.46-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundles.json +3 -3
- package/dist/css/{library-editor-app-9c24416a39.css → library-editor-app-d4e455dc19.css} +1 -1
- package/dist/scripts/{0-2f5a66d67a.chunk.js → 0-39b4264c40.chunk.js} +1 -1
- package/dist/scripts/{1-6e8dcc5ca2.chunk.js → 1-c2f2ee50e1.chunk.js} +1 -1
- package/dist/scripts/{10-a4ab5eff50.chunk.js → 10-74b6a07baa.chunk.js} +1 -1
- package/dist/scripts/{11-3dec7d2c7e.chunk.js → 11-f9ca151e61.chunk.js} +1 -1
- package/dist/scripts/{12-bb9475eac6.chunk.js → 12-a961dabbb5.chunk.js} +1 -1
- package/dist/scripts/{13-de5b2bb606.chunk.js → 13-31b759d4dc.chunk.js} +1 -1
- package/dist/scripts/{14-c671e8bc46.chunk.js → 14-28ab8d5025.chunk.js} +1 -1
- package/dist/scripts/{15-7de7fc2b35.chunk.js → 15-e326770074.chunk.js} +1 -1
- package/dist/scripts/{16-382f0c41cf.chunk.js → 16-33bc415c72.chunk.js} +1 -1
- package/dist/scripts/{17-1eb8479302.chunk.js → 17-4d85362caa.chunk.js} +1 -1
- package/dist/scripts/{2-7cc9176e8a.chunk.js → 2-6334a56d75.chunk.js} +1 -1
- package/dist/scripts/{20-d3444fe825.chunk.js → 20-be33eea416.chunk.js} +1 -1
- package/dist/scripts/{21-df15d4d827.chunk.js → 21-d07eac93af.chunk.js} +1 -1
- package/dist/scripts/{22-5d9b14f0b0.chunk.js → 22-f61848d852.chunk.js} +1 -1
- package/dist/scripts/{23-7922bfa9d3.chunk.js → 23-883535facb.chunk.js} +1 -1
- package/dist/scripts/{24-a675687323.chunk.js → 24-28d1ee1ddb.chunk.js} +1 -1
- package/dist/scripts/{25-a1259842aa.chunk.js → 25-36f6c0f04c.chunk.js} +1 -1
- package/dist/scripts/{26-bbf1c17cb5.chunk.js → 26-41d73fb1cc.chunk.js} +1 -1
- package/dist/scripts/{27-eff11570d8.chunk.js → 27-9faadbc5ad.chunk.js} +1 -1
- package/dist/scripts/{28-285eb18d9a.chunk.js → 28-1abda5ddcd.chunk.js} +1 -1
- package/dist/scripts/{29-b7d2b7cde1.chunk.js → 29-e1b5688929.chunk.js} +1 -1
- package/dist/scripts/{3-aa8256fe40.chunk.js → 3-c468e5f805.chunk.js} +1 -1
- package/dist/scripts/{30-6fdc3a1e11.chunk.js → 30-4331611384.chunk.js} +1 -1
- package/dist/scripts/{31-4a94075827.chunk.js → 31-f594f549df.chunk.js} +1 -1
- package/dist/scripts/{32-7e2b293f23.chunk.js → 32-b5a8e7c2a3.chunk.js} +1 -1
- package/dist/scripts/{33-8de738bfb9.chunk.js → 33-b88d856ab0.chunk.js} +1 -1
- package/dist/scripts/{34-7d112464d3.chunk.js → 34-7fcaaeddea.chunk.js} +1 -1
- package/dist/scripts/{35-e850443dff.chunk.js → 35-e210da4f12.chunk.js} +1 -1
- package/dist/scripts/{36-a480ba6fea.chunk.js → 36-524bf056e4.chunk.js} +1 -1
- package/dist/scripts/{37-43b5d8c3af.chunk.js → 37-0336031536.chunk.js} +1 -1
- package/dist/scripts/{38-1b53bc0747.chunk.js → 38-1aa8ca825c.chunk.js} +1 -1
- package/dist/scripts/{39-674f9ca697.chunk.js → 39-faf8a59822.chunk.js} +1 -1
- package/dist/scripts/{4-9915802afa.chunk.js → 4-4c62127fb2.chunk.js} +1 -1
- package/dist/scripts/{40-4f0571b8a2.chunk.js → 40-9b473a87c2.chunk.js} +1 -1
- package/dist/scripts/{41-5ed5f9712e.chunk.js → 41-20fe91435b.chunk.js} +1 -1
- package/dist/scripts/{42-c280d7752c.chunk.js → 42-143ac3914b.chunk.js} +1 -1
- package/dist/scripts/{43-c0a7d44737.chunk.js → 43-ce726c3839.chunk.js} +1 -1
- package/dist/scripts/{44-b04dab25e6.chunk.js → 44-fc7c025c5f.chunk.js} +1 -1
- package/dist/scripts/{45-a6b9650b26.chunk.js → 45-1e84cd6639.chunk.js} +1 -1
- package/dist/scripts/{46-319d735448.chunk.js → 46-26b40a870e.chunk.js} +1 -1
- package/dist/scripts/{47-87b93cae7d.chunk.js → 47-f03e03252c.chunk.js} +1 -1
- package/dist/scripts/{48-92ee4ae7a7.chunk.js → 48-c9a61fd1e3.chunk.js} +1 -1
- package/dist/scripts/{49-5c6fe71808.chunk.js → 49-2879e96eed.chunk.js} +1 -1
- package/dist/scripts/{5-5341544820.chunk.js → 5-5d2e1c890e.chunk.js} +1 -1
- package/dist/scripts/{50-38186c72b7.chunk.js → 50-b76b6c7d52.chunk.js} +1 -1
- package/dist/scripts/{51-37749b146e.chunk.js → 51-c252822f95.chunk.js} +1 -1
- package/dist/scripts/{52-67c9e2601b.chunk.js → 52-ecde4fecf3.chunk.js} +1 -1
- package/dist/scripts/{53-16ef9ed0cb.chunk.js → 53-3ab3b83088.chunk.js} +1 -1
- package/dist/scripts/{54-8d377c5aff.chunk.js → 54-0e921db390.chunk.js} +1 -1
- package/dist/scripts/{55-2360f690da.chunk.js → 55-bd9dc838cd.chunk.js} +1 -1
- package/dist/scripts/{56-d6e13d4afb.chunk.js → 56-6528a68474.chunk.js} +1 -1
- package/dist/scripts/{57-d31643829d.chunk.js → 57-3477d4f9b5.chunk.js} +1 -1
- package/dist/scripts/{58-21714dd15f.chunk.js → 58-2c62df5dbd.chunk.js} +1 -1
- package/dist/scripts/{59-b36d9e7be9.chunk.js → 59-13ade58ba1.chunk.js} +1 -1
- package/dist/scripts/{6-19be7f0d3b.chunk.js → 6-1fdfa2191a.chunk.js} +1 -1
- package/dist/scripts/{60-86a780fb81.chunk.js → 60-f36c57ef33.chunk.js} +1 -1
- package/dist/scripts/{61-897e3aacfb.chunk.js → 61-24acf3201f.chunk.js} +1 -1
- package/dist/scripts/{62-35425b2e29.chunk.js → 62-d869eccf9a.chunk.js} +1 -1
- package/dist/scripts/{63-714e5c1ee7.chunk.js → 63-d35e9ced47.chunk.js} +1 -1
- package/dist/scripts/{64-6ee45d0114.chunk.js → 64-dfc3cd19ee.chunk.js} +1 -1
- package/dist/scripts/{65-4041af23f8.chunk.js → 65-b66a158393.chunk.js} +1 -1
- package/dist/scripts/{66-1089ec4f34.chunk.js → 66-89b577d70f.chunk.js} +1 -1
- package/dist/scripts/{67-c03fd65497.chunk.js → 67-83b2b3ad1a.chunk.js} +1 -1
- package/dist/scripts/{68-53e4b905db.chunk.js → 68-452e0327d9.chunk.js} +1 -1
- package/dist/scripts/{69-6e315af542.chunk.js → 69-0491a8faf5.chunk.js} +1 -1
- package/dist/scripts/{7-8626ad1134.chunk.js → 7-13b4886b73.chunk.js} +1 -1
- package/dist/scripts/{70-64d4bc3567.chunk.js → 70-62aff2ab4e.chunk.js} +1 -1
- package/dist/scripts/{71-979bac4e9f.chunk.js → 71-91b4d4dfcb.chunk.js} +1 -1
- package/dist/scripts/{72-be5d02bfe6.chunk.js → 72-4d851db609.chunk.js} +1 -1
- package/dist/scripts/{8-ed9e11c370.chunk.js → 8-55ea9736c8.chunk.js} +1 -1
- package/dist/scripts/{9-82e97cb80a.chunk.js → 9-175ec73a5d.chunk.js} +1 -1
- package/dist/scripts/bundle-804e733ae8.min.js +10 -0
- package/dist/scripts/polyfills-e2b8375767.min.js +1 -0
- package/package.json +3 -3
- package/typings/libs/trackjs.d.ts +3 -0
- package/dist/css/0-library-editor.chunk.css +0 -26
- package/dist/css/10-library-editor.chunk.css +0 -25
- package/dist/css/11-library-editor.chunk.css +0 -135
- package/dist/css/12-library-editor.chunk.css +0 -18
- package/dist/css/13-library-editor.chunk.css +0 -21
- package/dist/css/14-library-editor.chunk.css +0 -76
- package/dist/css/16-library-editor.chunk.css +0 -52
- package/dist/css/17-library-editor.chunk.css +0 -14
- package/dist/css/18-library-editor.chunk.css +0 -18
- package/dist/css/2-library-editor.chunk.css +0 -143
- package/dist/css/21-library-editor.chunk.css +0 -52
- package/dist/css/22-library-editor.chunk.css +0 -12
- package/dist/css/23-library-editor.chunk.css +0 -25
- package/dist/css/25-library-editor.chunk.css +0 -35
- package/dist/css/26-library-editor.chunk.css +0 -20
- package/dist/css/28-library-editor.chunk.css +0 -63
- package/dist/css/29-library-editor.chunk.css +0 -80
- package/dist/css/3-library-editor.chunk.css +0 -15
- package/dist/css/30-library-editor.chunk.css +0 -33
- package/dist/css/31-library-editor.chunk.css +0 -30
- package/dist/css/32-library-editor.chunk.css +0 -45
- package/dist/css/33-library-editor.chunk.css +0 -13
- package/dist/css/34-library-editor.chunk.css +0 -19
- package/dist/css/35-library-editor.chunk.css +0 -18
- package/dist/css/36-library-editor.chunk.css +0 -12
- package/dist/css/37-library-editor.chunk.css +0 -5
- package/dist/css/38-library-editor.chunk.css +0 -5
- package/dist/css/40-library-editor.chunk.css +0 -24
- package/dist/css/41-library-editor.chunk.css +0 -76
- package/dist/css/42-library-editor.chunk.css +0 -44
- package/dist/css/43-library-editor.chunk.css +0 -30
- package/dist/css/44-library-editor.chunk.css +0 -12
- package/dist/css/45-library-editor.chunk.css +0 -25
- package/dist/css/46-library-editor.chunk.css +0 -24
- package/dist/css/47-library-editor.chunk.css +0 -84
- package/dist/css/48-library-editor.chunk.css +0 -4
- package/dist/css/49-library-editor.chunk.css +0 -33
- package/dist/css/50-library-editor.chunk.css +0 -20
- package/dist/css/51-library-editor.chunk.css +0 -37
- package/dist/css/52-library-editor.chunk.css +0 -64
- package/dist/css/55-library-editor.chunk.css +0 -3
- package/dist/css/56-library-editor.chunk.css +0 -3
- package/dist/css/58-library-editor.chunk.css +0 -3
- package/dist/css/59-library-editor.chunk.css +0 -3
- package/dist/css/6-library-editor.chunk.css +0 -42
- package/dist/css/60-library-editor.chunk.css +0 -16
- package/dist/css/62-library-editor.chunk.css +0 -4
- package/dist/css/63-library-editor.chunk.css +0 -168
- package/dist/css/67-library-editor.chunk.css +0 -76
- package/dist/css/68-library-editor.chunk.css +0 -15
- package/dist/css/69-library-editor.chunk.css +0 -15
- package/dist/css/7-library-editor.chunk.css +0 -10
- package/dist/css/70-library-editor.chunk.css +0 -21
- package/dist/css/71-library-editor.chunk.css +0 -38
- package/dist/css/72-library-editor.chunk.css +0 -14
- package/dist/css/73-library-editor.chunk.css +0 -35
- package/dist/css/74-library-editor.chunk.css +0 -27
- package/dist/css/75-library-editor.chunk.css +0 -4
- package/dist/css/76-library-editor.chunk.css +0 -4
- package/dist/css/8-library-editor.chunk.css +0 -7
- package/dist/css/library-editor-app.css +0 -9291
- package/dist/scripts/0-298010e33a.chunk.js +0 -1
- package/dist/scripts/0-aaa3608203.chunk.js +0 -1
- package/dist/scripts/0.chunk.js +0 -64
- package/dist/scripts/1-323257c9af.chunk.js +0 -1
- package/dist/scripts/1-c690200bdb.chunk.js +0 -1
- package/dist/scripts/1.chunk.js +0 -75
- package/dist/scripts/10-466cc9683b.chunk.js +0 -1
- package/dist/scripts/10-abb1be81df.chunk.js +0 -1
- package/dist/scripts/10.chunk.js +0 -62
- package/dist/scripts/11-2356f4df85.chunk.js +0 -11
- package/dist/scripts/11-3ea7c37829.chunk.js +0 -11
- package/dist/scripts/11.chunk.js +0 -317
- package/dist/scripts/12-26db35cb21.chunk.js +0 -1
- package/dist/scripts/12-c76d68628d.chunk.js +0 -1
- package/dist/scripts/12.chunk.js +0 -56
- package/dist/scripts/13-a886aeba95.chunk.js +0 -1
- package/dist/scripts/13-ffdf6d7db4.chunk.js +0 -1
- package/dist/scripts/13.chunk.js +0 -25
- package/dist/scripts/14-377ed1af74.chunk.js +0 -1
- package/dist/scripts/14-d80e0ddb3c.chunk.js +0 -1
- package/dist/scripts/14.chunk.js +0 -272
- package/dist/scripts/15-3c4f92249c.chunk.js +0 -1
- package/dist/scripts/15-ac502fa5ec.chunk.js +0 -1
- package/dist/scripts/15.chunk.js +0 -35
- package/dist/scripts/16-082a975dbb.chunk.js +0 -1
- package/dist/scripts/16-783d3e4092.chunk.js +0 -1
- package/dist/scripts/16.chunk.js +0 -79
- package/dist/scripts/17-b13fb41bd3.chunk.js +0 -1
- package/dist/scripts/17-c66a2978ae.chunk.js +0 -1
- package/dist/scripts/17.chunk.js +0 -40
- package/dist/scripts/18.chunk.js +0 -40
- package/dist/scripts/19.chunk.js +0 -43
- package/dist/scripts/2-717e5953ab.chunk.js +0 -1
- package/dist/scripts/2-8e809f7467.chunk.js +0 -1
- package/dist/scripts/2.chunk.js +0 -33
- package/dist/scripts/20-6dd45d4f46.chunk.js +0 -1
- package/dist/scripts/20-fa33bbf746.chunk.js +0 -1
- package/dist/scripts/20.chunk.js +0 -18
- package/dist/scripts/21-4de1bd55b0.chunk.js +0 -1
- package/dist/scripts/21-dadfbacfbc.chunk.js +0 -1
- package/dist/scripts/21.chunk.js +0 -55
- package/dist/scripts/22-6d8b1c21c5.chunk.js +0 -1
- package/dist/scripts/22-d381139a29.chunk.js +0 -1
- package/dist/scripts/22.chunk.js +0 -47
- package/dist/scripts/23-30dffdfecf.chunk.js +0 -1
- package/dist/scripts/23-9f6cc70b65.chunk.js +0 -1
- package/dist/scripts/23.chunk.js +0 -47
- package/dist/scripts/24-7406b564f6.chunk.js +0 -1
- package/dist/scripts/24-b6ec3366cb.chunk.js +0 -1
- package/dist/scripts/24.chunk.js +0 -33
- package/dist/scripts/25-7faa89d5e3.chunk.js +0 -1
- package/dist/scripts/25-d7396e955d.chunk.js +0 -1
- package/dist/scripts/25.chunk.js +0 -25
- package/dist/scripts/26-2d98320aae.chunk.js +0 -1
- package/dist/scripts/26-c1fc20583b.chunk.js +0 -1
- package/dist/scripts/26.chunk.js +0 -25
- package/dist/scripts/27-31485d4b2a.chunk.js +0 -1
- package/dist/scripts/27-531532942a.chunk.js +0 -1
- package/dist/scripts/27.chunk.js +0 -10
- package/dist/scripts/28-b71b9ac0eb.chunk.js +0 -1
- package/dist/scripts/28-e85da77e0f.chunk.js +0 -1
- package/dist/scripts/28.chunk.js +0 -334
- package/dist/scripts/29-7be825c44d.chunk.js +0 -1
- package/dist/scripts/29-d980d0cbb5.chunk.js +0 -1
- package/dist/scripts/29.chunk.js +0 -202
- package/dist/scripts/3-151fc3d544.chunk.js +0 -1
- package/dist/scripts/3-eeb2d3d492.chunk.js +0 -1
- package/dist/scripts/3.chunk.js +0 -57
- package/dist/scripts/30-0e805630f4.chunk.js +0 -1
- package/dist/scripts/30-ad62e78d54.chunk.js +0 -1
- package/dist/scripts/30.chunk.js +0 -137
- package/dist/scripts/31-49c7676cff.chunk.js +0 -1
- package/dist/scripts/31-b1a679306a.chunk.js +0 -1
- package/dist/scripts/31.chunk.js +0 -113
- package/dist/scripts/32-042cda92ae.chunk.js +0 -1
- package/dist/scripts/32-e448ef7e82.chunk.js +0 -1
- package/dist/scripts/32.chunk.js +0 -115
- package/dist/scripts/33-36ddd95595.chunk.js +0 -1
- package/dist/scripts/33-b5cf4cfa6f.chunk.js +0 -1
- package/dist/scripts/33.chunk.js +0 -93
- package/dist/scripts/34-894005f525.chunk.js +0 -1
- package/dist/scripts/34-b206a218e9.chunk.js +0 -1
- package/dist/scripts/34.chunk.js +0 -63
- package/dist/scripts/35-9cdb858587.chunk.js +0 -1
- package/dist/scripts/35-d0137a950e.chunk.js +0 -1
- package/dist/scripts/35.chunk.js +0 -48
- package/dist/scripts/36-54624daa85.chunk.js +0 -1
- package/dist/scripts/36-846ab1a7ae.chunk.js +0 -1
- package/dist/scripts/36.chunk.js +0 -33
- package/dist/scripts/37-3314327a46.chunk.js +0 -1
- package/dist/scripts/37-6ffb96d64b.chunk.js +0 -1
- package/dist/scripts/37.chunk.js +0 -25
- package/dist/scripts/38-a18528bd5a.chunk.js +0 -1
- package/dist/scripts/38-d5dc6c775d.chunk.js +0 -1
- package/dist/scripts/38.chunk.js +0 -25
- package/dist/scripts/39-a4d5bf70ed.chunk.js +0 -1
- package/dist/scripts/39-d1b6c2defd.chunk.js +0 -1
- package/dist/scripts/39.chunk.js +0 -19
- package/dist/scripts/4-3516e54324.chunk.js +0 -1
- package/dist/scripts/4-adab2b69d4.chunk.js +0 -1
- package/dist/scripts/4.chunk.js +0 -26
- package/dist/scripts/40-264a3768ac.chunk.js +0 -1
- package/dist/scripts/40-bc2c6ae993.chunk.js +0 -1
- package/dist/scripts/40.chunk.js +0 -182
- package/dist/scripts/41-2084077727.chunk.js +0 -1
- package/dist/scripts/41-a4121258fa.chunk.js +0 -1
- package/dist/scripts/41.chunk.js +0 -175
- package/dist/scripts/42-16c4690eeb.chunk.js +0 -1
- package/dist/scripts/42-6b99047385.chunk.js +0 -1
- package/dist/scripts/42.chunk.js +0 -176
- package/dist/scripts/43-16efe31266.chunk.js +0 -1
- package/dist/scripts/43-f0a2833261.chunk.js +0 -1
- package/dist/scripts/43.chunk.js +0 -121
- package/dist/scripts/44-66950d4440.chunk.js +0 -1
- package/dist/scripts/44-dbc3731bcb.chunk.js +0 -1
- package/dist/scripts/44.chunk.js +0 -122
- package/dist/scripts/45-6dd66a0ec6.chunk.js +0 -1
- package/dist/scripts/45-bc07f6ed34.chunk.js +0 -1
- package/dist/scripts/45.chunk.js +0 -85
- package/dist/scripts/46-1188acdeb9.chunk.js +0 -1
- package/dist/scripts/46-b403f6be5b.chunk.js +0 -1
- package/dist/scripts/46.chunk.js +0 -78
- package/dist/scripts/47-2964488de7.chunk.js +0 -1
- package/dist/scripts/47-b482682154.chunk.js +0 -1
- package/dist/scripts/47.chunk.js +0 -70
- package/dist/scripts/48-48a409c875.chunk.js +0 -1
- package/dist/scripts/48-d924ddb603.chunk.js +0 -1
- package/dist/scripts/48.chunk.js +0 -88
- package/dist/scripts/49-3728b15a3c.chunk.js +0 -1
- package/dist/scripts/49-a76be85054.chunk.js +0 -1
- package/dist/scripts/49.chunk.js +0 -62
- package/dist/scripts/5-3fe2876121.chunk.js +0 -1
- package/dist/scripts/5-c3a1e51e77.chunk.js +0 -1
- package/dist/scripts/5.chunk.js +0 -10
- package/dist/scripts/50-06212d1dc8.chunk.js +0 -1
- package/dist/scripts/50-a20245292f.chunk.js +0 -1
- package/dist/scripts/50.chunk.js +0 -64
- package/dist/scripts/51-4e98f3c73f.chunk.js +0 -1
- package/dist/scripts/51-af622cc279.chunk.js +0 -1
- package/dist/scripts/51.chunk.js +0 -55
- package/dist/scripts/52-1ece273b07.chunk.js +0 -1
- package/dist/scripts/52-c988320a6f.chunk.js +0 -1
- package/dist/scripts/52.chunk.js +0 -47
- package/dist/scripts/53-1514119651.chunk.js +0 -1
- package/dist/scripts/53-eae4eb72dc.chunk.js +0 -1
- package/dist/scripts/53.chunk.js +0 -56
- package/dist/scripts/54-56e7cb4493.chunk.js +0 -1
- package/dist/scripts/54-f489df5eda.chunk.js +0 -1
- package/dist/scripts/54.chunk.js +0 -56
- package/dist/scripts/55-b621cecfd3.chunk.js +0 -1
- package/dist/scripts/55-c7303d997f.chunk.js +0 -1
- package/dist/scripts/55.chunk.js +0 -41
- package/dist/scripts/56-53c4bdf797.chunk.js +0 -1
- package/dist/scripts/56-db9dbfd5fa.chunk.js +0 -1
- package/dist/scripts/56.chunk.js +0 -41
- package/dist/scripts/57-be599f08b2.chunk.js +0 -1
- package/dist/scripts/57-fb4f8ce1ab.chunk.js +0 -1
- package/dist/scripts/57.chunk.js +0 -50
- package/dist/scripts/58-8d1653ecd7.chunk.js +0 -1
- package/dist/scripts/58-c0e985cbc4.chunk.js +0 -1
- package/dist/scripts/58.chunk.js +0 -33
- package/dist/scripts/59-9b9c8c0f2d.chunk.js +0 -1
- package/dist/scripts/59-fcf6a940d6.chunk.js +0 -1
- package/dist/scripts/59.chunk.js +0 -33
- package/dist/scripts/6-a39d1f4585.chunk.js +0 -1
- package/dist/scripts/6-deb7609cc9.chunk.js +0 -1
- package/dist/scripts/6.chunk.js +0 -40
- package/dist/scripts/60-6995cd4cf5.chunk.js +0 -1
- package/dist/scripts/60-b4f7090720.chunk.js +0 -1
- package/dist/scripts/60.chunk.js +0 -33
- package/dist/scripts/61-7d1475b277.chunk.js +0 -1
- package/dist/scripts/61-cac68e627b.chunk.js +0 -1
- package/dist/scripts/61.chunk.js +0 -33
- package/dist/scripts/62-2aa55f08d5.chunk.js +0 -1
- package/dist/scripts/62-3a96a88b11.chunk.js +0 -1
- package/dist/scripts/62.chunk.js +0 -25
- package/dist/scripts/63-65744e61fe.chunk.js +0 -1
- package/dist/scripts/63-90bb249d0f.chunk.js +0 -1
- package/dist/scripts/63.chunk.js +0 -25
- package/dist/scripts/64-4f64cd6916.chunk.js +0 -1
- package/dist/scripts/64-b92f429d9a.chunk.js +0 -1
- package/dist/scripts/64.chunk.js +0 -33
- package/dist/scripts/65-179891d951.chunk.js +0 -1
- package/dist/scripts/65-fe362dec65.chunk.js +0 -1
- package/dist/scripts/65.chunk.js +0 -34
- package/dist/scripts/66-0bda221806.chunk.js +0 -1
- package/dist/scripts/66-b1de02727e.chunk.js +0 -1
- package/dist/scripts/66.chunk.js +0 -33
- package/dist/scripts/67-9773a2f9cf.chunk.js +0 -1
- package/dist/scripts/67-fc341ce660.chunk.js +0 -1
- package/dist/scripts/67.chunk.js +0 -25
- package/dist/scripts/68-2ff366d408.chunk.js +0 -1
- package/dist/scripts/68-c6ef8701a2.chunk.js +0 -1
- package/dist/scripts/68.chunk.js +0 -25
- package/dist/scripts/69-4af679bc4c.chunk.js +0 -1
- package/dist/scripts/69-5368c32a2e.chunk.js +0 -1
- package/dist/scripts/69.chunk.js +0 -25
- package/dist/scripts/7-c387d70c9b.chunk.js +0 -1
- package/dist/scripts/7-c86af5cc3a.chunk.js +0 -1
- package/dist/scripts/7.chunk.js +0 -33
- package/dist/scripts/70-3650ef74f8.chunk.js +0 -1
- package/dist/scripts/70-e782f523de.chunk.js +0 -1
- package/dist/scripts/70.chunk.js +0 -25
- package/dist/scripts/71-a45419aed7.chunk.js +0 -1
- package/dist/scripts/71-cf362223a9.chunk.js +0 -1
- package/dist/scripts/71.chunk.js +0 -25
- package/dist/scripts/72-3f71367bdd.chunk.js +0 -1
- package/dist/scripts/72-93adcc17c5.chunk.js +0 -1
- package/dist/scripts/72.chunk.js +0 -25
- package/dist/scripts/73.chunk.js +0 -25
- package/dist/scripts/74.chunk.js +0 -25
- package/dist/scripts/75.chunk.js +0 -25
- package/dist/scripts/76.chunk.js +0 -25
- package/dist/scripts/77.chunk.js +0 -26
- package/dist/scripts/78.chunk.js +0 -26
- package/dist/scripts/79.chunk.js +0 -26
- package/dist/scripts/8-2e66d6cb35.chunk.js +0 -1
- package/dist/scripts/8-82c9c86dfd.chunk.js +0 -1
- package/dist/scripts/8.chunk.js +0 -33
- package/dist/scripts/80.chunk.js +0 -26
- package/dist/scripts/81.chunk.js +0 -26
- package/dist/scripts/82.chunk.js +0 -26
- package/dist/scripts/83.chunk.js +0 -26
- package/dist/scripts/84.chunk.js +0 -26
- package/dist/scripts/85.chunk.js +0 -26
- package/dist/scripts/86.chunk.js +0 -18
- package/dist/scripts/87.chunk.js +0 -18
- package/dist/scripts/88.chunk.js +0 -18
- package/dist/scripts/89.chunk.js +0 -18
- package/dist/scripts/9-61225547b6.chunk.js +0 -1
- package/dist/scripts/9-bd46228181.chunk.js +0 -1
- package/dist/scripts/9.chunk.js +0 -18
- package/dist/scripts/90.chunk.js +0 -18
- package/dist/scripts/91.chunk.js +0 -18
- package/dist/scripts/92.chunk.js +0 -18
- package/dist/scripts/bundle-39b749b21d.min.js +0 -10
- package/dist/scripts/bundle-42046b5b88.min.js +0 -10
- package/dist/scripts/bundle-a8b8854ef1.min.js +0 -10
- package/dist/scripts/bundle-f18858be26.min.js +0 -10
- package/dist/scripts/bundle.js +0 -8153
- package/dist/scripts/polyfills-022d27190f.min.js +0 -1
- package/dist/scripts/polyfills-5139b6bb05.min.js +0 -1
- package/dist/scripts/polyfills-b0f2bc073f.min.js +0 -1
- package/dist/scripts/polyfills.js +0 -2701
package/dist/scripts/27.chunk.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
(window["webpackJsonp_clickview_library_editor"] = window["webpackJsonp_clickview_library_editor"] || []).push([[27],{
|
|
2
|
-
|
|
3
|
-
/***/ "../../../node_modules/cropperjs/dist/cropper.js":
|
|
4
|
-
/***/ (function(module, exports, __webpack_require__) {
|
|
5
|
-
|
|
6
|
-
eval("/*!\n * Cropper.js v1.5.6\n * https://fengyuanchen.github.io/cropperjs\n *\n * Copyright 2015-present Chen Fengyuan\n * Released under the MIT license\n *\n * Date: 2019-10-04T04:33:48.372Z\n */\n\n(function (global, factory) {\n true ? module.exports = factory() :\n undefined;\n}(this, function () { 'use strict';\n\n function _typeof(obj) {\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n _typeof = function (obj) {\n return typeof obj;\n };\n } else {\n _typeof = function (obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n\n return _typeof(obj);\n }\n\n function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n }\n\n function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n }\n\n function _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n }\n\n function _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n }\n\n function ownKeys(object, enumerableOnly) {\n var keys = Object.keys(object);\n\n if (Object.getOwnPropertySymbols) {\n var symbols = Object.getOwnPropertySymbols(object);\n if (enumerableOnly) symbols = symbols.filter(function (sym) {\n return Object.getOwnPropertyDescriptor(object, sym).enumerable;\n });\n keys.push.apply(keys, symbols);\n }\n\n return keys;\n }\n\n function _objectSpread2(target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i] != null ? arguments[i] : {};\n\n if (i % 2) {\n ownKeys(source, true).forEach(function (key) {\n _defineProperty(target, key, source[key]);\n });\n } else if (Object.getOwnPropertyDescriptors) {\n Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));\n } else {\n ownKeys(source).forEach(function (key) {\n Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));\n });\n }\n }\n\n return target;\n }\n\n function _toConsumableArray(arr) {\n return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();\n }\n\n function _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) {\n for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];\n\n return arr2;\n }\n }\n\n function _iterableToArray(iter) {\n if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter);\n }\n\n function _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance\");\n }\n\n var IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined';\n var WINDOW = IS_BROWSER ? window : {};\n var IS_TOUCH_DEVICE = IS_BROWSER ? 'ontouchstart' in WINDOW.document.documentElement : false;\n var HAS_POINTER_EVENT = IS_BROWSER ? 'PointerEvent' in WINDOW : false;\n var NAMESPACE = 'cropper'; // Actions\n\n var ACTION_ALL = 'all';\n var ACTION_CROP = 'crop';\n var ACTION_MOVE = 'move';\n var ACTION_ZOOM = 'zoom';\n var ACTION_EAST = 'e';\n var ACTION_WEST = 'w';\n var ACTION_SOUTH = 's';\n var ACTION_NORTH = 'n';\n var ACTION_NORTH_EAST = 'ne';\n var ACTION_NORTH_WEST = 'nw';\n var ACTION_SOUTH_EAST = 'se';\n var ACTION_SOUTH_WEST = 'sw'; // Classes\n\n var CLASS_CROP = \"\".concat(NAMESPACE, \"-crop\");\n var CLASS_DISABLED = \"\".concat(NAMESPACE, \"-disabled\");\n var CLASS_HIDDEN = \"\".concat(NAMESPACE, \"-hidden\");\n var CLASS_HIDE = \"\".concat(NAMESPACE, \"-hide\");\n var CLASS_INVISIBLE = \"\".concat(NAMESPACE, \"-invisible\");\n var CLASS_MODAL = \"\".concat(NAMESPACE, \"-modal\");\n var CLASS_MOVE = \"\".concat(NAMESPACE, \"-move\"); // Data keys\n\n var DATA_ACTION = \"\".concat(NAMESPACE, \"Action\");\n var DATA_PREVIEW = \"\".concat(NAMESPACE, \"Preview\"); // Drag modes\n\n var DRAG_MODE_CROP = 'crop';\n var DRAG_MODE_MOVE = 'move';\n var DRAG_MODE_NONE = 'none'; // Events\n\n var EVENT_CROP = 'crop';\n var EVENT_CROP_END = 'cropend';\n var EVENT_CROP_MOVE = 'cropmove';\n var EVENT_CROP_START = 'cropstart';\n var EVENT_DBLCLICK = 'dblclick';\n var EVENT_TOUCH_START = IS_TOUCH_DEVICE ? 'touchstart' : 'mousedown';\n var EVENT_TOUCH_MOVE = IS_TOUCH_DEVICE ? 'touchmove' : 'mousemove';\n var EVENT_TOUCH_END = IS_TOUCH_DEVICE ? 'touchend touchcancel' : 'mouseup';\n var EVENT_POINTER_DOWN = HAS_POINTER_EVENT ? 'pointerdown' : EVENT_TOUCH_START;\n var EVENT_POINTER_MOVE = HAS_POINTER_EVENT ? 'pointermove' : EVENT_TOUCH_MOVE;\n var EVENT_POINTER_UP = HAS_POINTER_EVENT ? 'pointerup pointercancel' : EVENT_TOUCH_END;\n var EVENT_READY = 'ready';\n var EVENT_RESIZE = 'resize';\n var EVENT_WHEEL = 'wheel';\n var EVENT_ZOOM = 'zoom'; // Mime types\n\n var MIME_TYPE_JPEG = 'image/jpeg'; // RegExps\n\n var REGEXP_ACTIONS = /^e|w|s|n|se|sw|ne|nw|all|crop|move|zoom$/;\n var REGEXP_DATA_URL = /^data:/;\n var REGEXP_DATA_URL_JPEG = /^data:image\\/jpeg;base64,/;\n var REGEXP_TAG_NAME = /^img|canvas$/i; // Misc\n // Inspired by the default width and height of a canvas element.\n\n var MIN_CONTAINER_WIDTH = 200;\n var MIN_CONTAINER_HEIGHT = 100;\n\n var DEFAULTS = {\n // Define the view mode of the cropper\n viewMode: 0,\n // 0, 1, 2, 3\n // Define the dragging mode of the cropper\n dragMode: DRAG_MODE_CROP,\n // 'crop', 'move' or 'none'\n // Define the initial aspect ratio of the crop box\n initialAspectRatio: NaN,\n // Define the aspect ratio of the crop box\n aspectRatio: NaN,\n // An object with the previous cropping result data\n data: null,\n // A selector for adding extra containers to preview\n preview: '',\n // Re-render the cropper when resize the window\n responsive: true,\n // Restore the cropped area after resize the window\n restore: true,\n // Check if the current image is a cross-origin image\n checkCrossOrigin: true,\n // Check the current image's Exif Orientation information\n checkOrientation: true,\n // Show the black modal\n modal: true,\n // Show the dashed lines for guiding\n guides: true,\n // Show the center indicator for guiding\n center: true,\n // Show the white modal to highlight the crop box\n highlight: true,\n // Show the grid background\n background: true,\n // Enable to crop the image automatically when initialize\n autoCrop: true,\n // Define the percentage of automatic cropping area when initializes\n autoCropArea: 0.8,\n // Enable to move the image\n movable: true,\n // Enable to rotate the image\n rotatable: true,\n // Enable to scale the image\n scalable: true,\n // Enable to zoom the image\n zoomable: true,\n // Enable to zoom the image by dragging touch\n zoomOnTouch: true,\n // Enable to zoom the image by wheeling mouse\n zoomOnWheel: true,\n // Define zoom ratio when zoom the image by wheeling mouse\n wheelZoomRatio: 0.1,\n // Enable to move the crop box\n cropBoxMovable: true,\n // Enable to resize the crop box\n cropBoxResizable: true,\n // Toggle drag mode between \"crop\" and \"move\" when click twice on the cropper\n toggleDragModeOnDblclick: true,\n // Size limitation\n minCanvasWidth: 0,\n minCanvasHeight: 0,\n minCropBoxWidth: 0,\n minCropBoxHeight: 0,\n minContainerWidth: 200,\n minContainerHeight: 100,\n // Shortcuts of events\n ready: null,\n cropstart: null,\n cropmove: null,\n cropend: null,\n crop: null,\n zoom: null\n };\n\n var TEMPLATE = '<div class=\"cropper-container\" touch-action=\"none\">' + '<div class=\"cropper-wrap-box\">' + '<div class=\"cropper-canvas\"></div>' + '</div>' + '<div class=\"cropper-drag-box\"></div>' + '<div class=\"cropper-crop-box\">' + '<span class=\"cropper-view-box\"></span>' + '<span class=\"cropper-dashed dashed-h\"></span>' + '<span class=\"cropper-dashed dashed-v\"></span>' + '<span class=\"cropper-center\"></span>' + '<span class=\"cropper-face\"></span>' + '<span class=\"cropper-line line-e\" data-cropper-action=\"e\"></span>' + '<span class=\"cropper-line line-n\" data-cropper-action=\"n\"></span>' + '<span class=\"cropper-line line-w\" data-cropper-action=\"w\"></span>' + '<span class=\"cropper-line line-s\" data-cropper-action=\"s\"></span>' + '<span class=\"cropper-point point-e\" data-cropper-action=\"e\"></span>' + '<span class=\"cropper-point point-n\" data-cropper-action=\"n\"></span>' + '<span class=\"cropper-point point-w\" data-cropper-action=\"w\"></span>' + '<span class=\"cropper-point point-s\" data-cropper-action=\"s\"></span>' + '<span class=\"cropper-point point-ne\" data-cropper-action=\"ne\"></span>' + '<span class=\"cropper-point point-nw\" data-cropper-action=\"nw\"></span>' + '<span class=\"cropper-point point-sw\" data-cropper-action=\"sw\"></span>' + '<span class=\"cropper-point point-se\" data-cropper-action=\"se\"></span>' + '</div>' + '</div>';\n\n /**\n * Check if the given value is not a number.\n */\n\n var isNaN = Number.isNaN || WINDOW.isNaN;\n /**\n * Check if the given value is a number.\n * @param {*} value - The value to check.\n * @returns {boolean} Returns `true` if the given value is a number, else `false`.\n */\n\n function isNumber(value) {\n return typeof value === 'number' && !isNaN(value);\n }\n /**\n * Check if the given value is a positive number.\n * @param {*} value - The value to check.\n * @returns {boolean} Returns `true` if the given value is a positive number, else `false`.\n */\n\n var isPositiveNumber = function isPositiveNumber(value) {\n return value > 0 && value < Infinity;\n };\n /**\n * Check if the given value is undefined.\n * @param {*} value - The value to check.\n * @returns {boolean} Returns `true` if the given value is undefined, else `false`.\n */\n\n function isUndefined(value) {\n return typeof value === 'undefined';\n }\n /**\n * Check if the given value is an object.\n * @param {*} value - The value to check.\n * @returns {boolean} Returns `true` if the given value is an object, else `false`.\n */\n\n function isObject(value) {\n return _typeof(value) === 'object' && value !== null;\n }\n var hasOwnProperty = Object.prototype.hasOwnProperty;\n /**\n * Check if the given value is a plain object.\n * @param {*} value - The value to check.\n * @returns {boolean} Returns `true` if the given value is a plain object, else `false`.\n */\n\n function isPlainObject(value) {\n if (!isObject(value)) {\n return false;\n }\n\n try {\n var _constructor = value.constructor;\n var prototype = _constructor.prototype;\n return _constructor && prototype && hasOwnProperty.call(prototype, 'isPrototypeOf');\n } catch (error) {\n return false;\n }\n }\n /**\n * Check if the given value is a function.\n * @param {*} value - The value to check.\n * @returns {boolean} Returns `true` if the given value is a function, else `false`.\n */\n\n function isFunction(value) {\n return typeof value === 'function';\n }\n var slice = Array.prototype.slice;\n /**\n * Convert array-like or iterable object to an array.\n * @param {*} value - The value to convert.\n * @returns {Array} Returns a new array.\n */\n\n function toArray(value) {\n return Array.from ? Array.from(value) : slice.call(value);\n }\n /**\n * Iterate the given data.\n * @param {*} data - The data to iterate.\n * @param {Function} callback - The process function for each element.\n * @returns {*} The original data.\n */\n\n function forEach(data, callback) {\n if (data && isFunction(callback)) {\n if (Array.isArray(data) || isNumber(data.length)\n /* array-like */\n ) {\n toArray(data).forEach(function (value, key) {\n callback.call(data, value, key, data);\n });\n } else if (isObject(data)) {\n Object.keys(data).forEach(function (key) {\n callback.call(data, data[key], key, data);\n });\n }\n }\n\n return data;\n }\n /**\n * Extend the given object.\n * @param {*} target - The target object to extend.\n * @param {*} args - The rest objects for merging to the target object.\n * @returns {Object} The extended object.\n */\n\n var assign = Object.assign || function assign(target) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n\n if (isObject(target) && args.length > 0) {\n args.forEach(function (arg) {\n if (isObject(arg)) {\n Object.keys(arg).forEach(function (key) {\n target[key] = arg[key];\n });\n }\n });\n }\n\n return target;\n };\n var REGEXP_DECIMALS = /\\.\\d*(?:0|9){12}\\d*$/;\n /**\n * Normalize decimal number.\n * Check out {@link http://0.30000000000000004.com/}\n * @param {number} value - The value to normalize.\n * @param {number} [times=100000000000] - The times for normalizing.\n * @returns {number} Returns the normalized number.\n */\n\n function normalizeDecimalNumber(value) {\n var times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000;\n return REGEXP_DECIMALS.test(value) ? Math.round(value * times) / times : value;\n }\n var REGEXP_SUFFIX = /^width|height|left|top|marginLeft|marginTop$/;\n /**\n * Apply styles to the given element.\n * @param {Element} element - The target element.\n * @param {Object} styles - The styles for applying.\n */\n\n function setStyle(element, styles) {\n var style = element.style;\n forEach(styles, function (value, property) {\n if (REGEXP_SUFFIX.test(property) && isNumber(value)) {\n value = \"\".concat(value, \"px\");\n }\n\n style[property] = value;\n });\n }\n /**\n * Check if the given element has a special class.\n * @param {Element} element - The element to check.\n * @param {string} value - The class to search.\n * @returns {boolean} Returns `true` if the special class was found.\n */\n\n function hasClass(element, value) {\n return element.classList ? element.classList.contains(value) : element.className.indexOf(value) > -1;\n }\n /**\n * Add classes to the given element.\n * @param {Element} element - The target element.\n * @param {string} value - The classes to be added.\n */\n\n function addClass(element, value) {\n if (!value) {\n return;\n }\n\n if (isNumber(element.length)) {\n forEach(element, function (elem) {\n addClass(elem, value);\n });\n return;\n }\n\n if (element.classList) {\n element.classList.add(value);\n return;\n }\n\n var className = element.className.trim();\n\n if (!className) {\n element.className = value;\n } else if (className.indexOf(value) < 0) {\n element.className = \"\".concat(className, \" \").concat(value);\n }\n }\n /**\n * Remove classes from the given element.\n * @param {Element} element - The target element.\n * @param {string} value - The classes to be removed.\n */\n\n function removeClass(element, value) {\n if (!value) {\n return;\n }\n\n if (isNumber(element.length)) {\n forEach(element, function (elem) {\n removeClass(elem, value);\n });\n return;\n }\n\n if (element.classList) {\n element.classList.remove(value);\n return;\n }\n\n if (element.className.indexOf(value) >= 0) {\n element.className = element.className.replace(value, '');\n }\n }\n /**\n * Add or remove classes from the given element.\n * @param {Element} element - The target element.\n * @param {string} value - The classes to be toggled.\n * @param {boolean} added - Add only.\n */\n\n function toggleClass(element, value, added) {\n if (!value) {\n return;\n }\n\n if (isNumber(element.length)) {\n forEach(element, function (elem) {\n toggleClass(elem, value, added);\n });\n return;\n } // IE10-11 doesn't support the second parameter of `classList.toggle`\n\n\n if (added) {\n addClass(element, value);\n } else {\n removeClass(element, value);\n }\n }\n var REGEXP_CAMEL_CASE = /([a-z\\d])([A-Z])/g;\n /**\n * Transform the given string from camelCase to kebab-case\n * @param {string} value - The value to transform.\n * @returns {string} The transformed value.\n */\n\n function toParamCase(value) {\n return value.replace(REGEXP_CAMEL_CASE, '$1-$2').toLowerCase();\n }\n /**\n * Get data from the given element.\n * @param {Element} element - The target element.\n * @param {string} name - The data key to get.\n * @returns {string} The data value.\n */\n\n function getData(element, name) {\n if (isObject(element[name])) {\n return element[name];\n }\n\n if (element.dataset) {\n return element.dataset[name];\n }\n\n return element.getAttribute(\"data-\".concat(toParamCase(name)));\n }\n /**\n * Set data to the given element.\n * @param {Element} element - The target element.\n * @param {string} name - The data key to set.\n * @param {string} data - The data value.\n */\n\n function setData(element, name, data) {\n if (isObject(data)) {\n element[name] = data;\n } else if (element.dataset) {\n element.dataset[name] = data;\n } else {\n element.setAttribute(\"data-\".concat(toParamCase(name)), data);\n }\n }\n /**\n * Remove data from the given element.\n * @param {Element} element - The target element.\n * @param {string} name - The data key to remove.\n */\n\n function removeData(element, name) {\n if (isObject(element[name])) {\n try {\n delete element[name];\n } catch (error) {\n element[name] = undefined;\n }\n } else if (element.dataset) {\n // #128 Safari not allows to delete dataset property\n try {\n delete element.dataset[name];\n } catch (error) {\n element.dataset[name] = undefined;\n }\n } else {\n element.removeAttribute(\"data-\".concat(toParamCase(name)));\n }\n }\n var REGEXP_SPACES = /\\s\\s*/;\n\n var onceSupported = function () {\n var supported = false;\n\n if (IS_BROWSER) {\n var once = false;\n\n var listener = function listener() {};\n\n var options = Object.defineProperty({}, 'once', {\n get: function get() {\n supported = true;\n return once;\n },\n\n /**\n * This setter can fix a `TypeError` in strict mode\n * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only}\n * @param {boolean} value - The value to set\n */\n set: function set(value) {\n once = value;\n }\n });\n WINDOW.addEventListener('test', listener, options);\n WINDOW.removeEventListener('test', listener, options);\n }\n\n return supported;\n }();\n /**\n * Remove event listener from the target element.\n * @param {Element} element - The event target.\n * @param {string} type - The event type(s).\n * @param {Function} listener - The event listener.\n * @param {Object} options - The event options.\n */\n\n\n function removeListener(element, type, listener) {\n var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n var handler = listener;\n type.trim().split(REGEXP_SPACES).forEach(function (event) {\n if (!onceSupported) {\n var listeners = element.listeners;\n\n if (listeners && listeners[event] && listeners[event][listener]) {\n handler = listeners[event][listener];\n delete listeners[event][listener];\n\n if (Object.keys(listeners[event]).length === 0) {\n delete listeners[event];\n }\n\n if (Object.keys(listeners).length === 0) {\n delete element.listeners;\n }\n }\n }\n\n element.removeEventListener(event, handler, options);\n });\n }\n /**\n * Add event listener to the target element.\n * @param {Element} element - The event target.\n * @param {string} type - The event type(s).\n * @param {Function} listener - The event listener.\n * @param {Object} options - The event options.\n */\n\n function addListener(element, type, listener) {\n var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n var _handler = listener;\n type.trim().split(REGEXP_SPACES).forEach(function (event) {\n if (options.once && !onceSupported) {\n var _element$listeners = element.listeners,\n listeners = _element$listeners === void 0 ? {} : _element$listeners;\n\n _handler = function handler() {\n delete listeners[event][listener];\n element.removeEventListener(event, _handler, options);\n\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n\n listener.apply(element, args);\n };\n\n if (!listeners[event]) {\n listeners[event] = {};\n }\n\n if (listeners[event][listener]) {\n element.removeEventListener(event, listeners[event][listener], options);\n }\n\n listeners[event][listener] = _handler;\n element.listeners = listeners;\n }\n\n element.addEventListener(event, _handler, options);\n });\n }\n /**\n * Dispatch event on the target element.\n * @param {Element} element - The event target.\n * @param {string} type - The event type(s).\n * @param {Object} data - The additional event data.\n * @returns {boolean} Indicate if the event is default prevented or not.\n */\n\n function dispatchEvent(element, type, data) {\n var event; // Event and CustomEvent on IE9-11 are global objects, not constructors\n\n if (isFunction(Event) && isFunction(CustomEvent)) {\n event = new CustomEvent(type, {\n detail: data,\n bubbles: true,\n cancelable: true\n });\n } else {\n event = document.createEvent('CustomEvent');\n event.initCustomEvent(type, true, true, data);\n }\n\n return element.dispatchEvent(event);\n }\n /**\n * Get the offset base on the document.\n * @param {Element} element - The target element.\n * @returns {Object} The offset data.\n */\n\n function getOffset(element) {\n var box = element.getBoundingClientRect();\n return {\n left: box.left + (window.pageXOffset - document.documentElement.clientLeft),\n top: box.top + (window.pageYOffset - document.documentElement.clientTop)\n };\n }\n var location = WINDOW.location;\n var REGEXP_ORIGINS = /^(\\w+:)\\/\\/([^:/?#]*):?(\\d*)/i;\n /**\n * Check if the given URL is a cross origin URL.\n * @param {string} url - The target URL.\n * @returns {boolean} Returns `true` if the given URL is a cross origin URL, else `false`.\n */\n\n function isCrossOriginURL(url) {\n var parts = url.match(REGEXP_ORIGINS);\n return parts !== null && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port);\n }\n /**\n * Add timestamp to the given URL.\n * @param {string} url - The target URL.\n * @returns {string} The result URL.\n */\n\n function addTimestamp(url) {\n var timestamp = \"timestamp=\".concat(new Date().getTime());\n return url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp;\n }\n /**\n * Get transforms base on the given object.\n * @param {Object} obj - The target object.\n * @returns {string} A string contains transform values.\n */\n\n function getTransforms(_ref) {\n var rotate = _ref.rotate,\n scaleX = _ref.scaleX,\n scaleY = _ref.scaleY,\n translateX = _ref.translateX,\n translateY = _ref.translateY;\n var values = [];\n\n if (isNumber(translateX) && translateX !== 0) {\n values.push(\"translateX(\".concat(translateX, \"px)\"));\n }\n\n if (isNumber(translateY) && translateY !== 0) {\n values.push(\"translateY(\".concat(translateY, \"px)\"));\n } // Rotate should come first before scale to match orientation transform\n\n\n if (isNumber(rotate) && rotate !== 0) {\n values.push(\"rotate(\".concat(rotate, \"deg)\"));\n }\n\n if (isNumber(scaleX) && scaleX !== 1) {\n values.push(\"scaleX(\".concat(scaleX, \")\"));\n }\n\n if (isNumber(scaleY) && scaleY !== 1) {\n values.push(\"scaleY(\".concat(scaleY, \")\"));\n }\n\n var transform = values.length ? values.join(' ') : 'none';\n return {\n WebkitTransform: transform,\n msTransform: transform,\n transform: transform\n };\n }\n /**\n * Get the max ratio of a group of pointers.\n * @param {string} pointers - The target pointers.\n * @returns {number} The result ratio.\n */\n\n function getMaxZoomRatio(pointers) {\n var pointers2 = _objectSpread2({}, pointers);\n\n var ratios = [];\n forEach(pointers, function (pointer, pointerId) {\n delete pointers2[pointerId];\n forEach(pointers2, function (pointer2) {\n var x1 = Math.abs(pointer.startX - pointer2.startX);\n var y1 = Math.abs(pointer.startY - pointer2.startY);\n var x2 = Math.abs(pointer.endX - pointer2.endX);\n var y2 = Math.abs(pointer.endY - pointer2.endY);\n var z1 = Math.sqrt(x1 * x1 + y1 * y1);\n var z2 = Math.sqrt(x2 * x2 + y2 * y2);\n var ratio = (z2 - z1) / z1;\n ratios.push(ratio);\n });\n });\n ratios.sort(function (a, b) {\n return Math.abs(a) < Math.abs(b);\n });\n return ratios[0];\n }\n /**\n * Get a pointer from an event object.\n * @param {Object} event - The target event object.\n * @param {boolean} endOnly - Indicates if only returns the end point coordinate or not.\n * @returns {Object} The result pointer contains start and/or end point coordinates.\n */\n\n function getPointer(_ref2, endOnly) {\n var pageX = _ref2.pageX,\n pageY = _ref2.pageY;\n var end = {\n endX: pageX,\n endY: pageY\n };\n return endOnly ? end : _objectSpread2({\n startX: pageX,\n startY: pageY\n }, end);\n }\n /**\n * Get the center point coordinate of a group of pointers.\n * @param {Object} pointers - The target pointers.\n * @returns {Object} The center point coordinate.\n */\n\n function getPointersCenter(pointers) {\n var pageX = 0;\n var pageY = 0;\n var count = 0;\n forEach(pointers, function (_ref3) {\n var startX = _ref3.startX,\n startY = _ref3.startY;\n pageX += startX;\n pageY += startY;\n count += 1;\n });\n pageX /= count;\n pageY /= count;\n return {\n pageX: pageX,\n pageY: pageY\n };\n }\n /**\n * Get the max sizes in a rectangle under the given aspect ratio.\n * @param {Object} data - The original sizes.\n * @param {string} [type='contain'] - The adjust type.\n * @returns {Object} The result sizes.\n */\n\n function getAdjustedSizes(_ref4) // or 'cover'\n {\n var aspectRatio = _ref4.aspectRatio,\n height = _ref4.height,\n width = _ref4.width;\n var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'contain';\n var isValidWidth = isPositiveNumber(width);\n var isValidHeight = isPositiveNumber(height);\n\n if (isValidWidth && isValidHeight) {\n var adjustedWidth = height * aspectRatio;\n\n if (type === 'contain' && adjustedWidth > width || type === 'cover' && adjustedWidth < width) {\n height = width / aspectRatio;\n } else {\n width = height * aspectRatio;\n }\n } else if (isValidWidth) {\n height = width / aspectRatio;\n } else if (isValidHeight) {\n width = height * aspectRatio;\n }\n\n return {\n width: width,\n height: height\n };\n }\n /**\n * Get the new sizes of a rectangle after rotated.\n * @param {Object} data - The original sizes.\n * @returns {Object} The result sizes.\n */\n\n function getRotatedSizes(_ref5) {\n var width = _ref5.width,\n height = _ref5.height,\n degree = _ref5.degree;\n degree = Math.abs(degree) % 180;\n\n if (degree === 90) {\n return {\n width: height,\n height: width\n };\n }\n\n var arc = degree % 90 * Math.PI / 180;\n var sinArc = Math.sin(arc);\n var cosArc = Math.cos(arc);\n var newWidth = width * cosArc + height * sinArc;\n var newHeight = width * sinArc + height * cosArc;\n return degree > 90 ? {\n width: newHeight,\n height: newWidth\n } : {\n width: newWidth,\n height: newHeight\n };\n }\n /**\n * Get a canvas which drew the given image.\n * @param {HTMLImageElement} image - The image for drawing.\n * @param {Object} imageData - The image data.\n * @param {Object} canvasData - The canvas data.\n * @param {Object} options - The options.\n * @returns {HTMLCanvasElement} The result canvas.\n */\n\n function getSourceCanvas(image, _ref6, _ref7, _ref8) {\n var imageAspectRatio = _ref6.aspectRatio,\n imageNaturalWidth = _ref6.naturalWidth,\n imageNaturalHeight = _ref6.naturalHeight,\n _ref6$rotate = _ref6.rotate,\n rotate = _ref6$rotate === void 0 ? 0 : _ref6$rotate,\n _ref6$scaleX = _ref6.scaleX,\n scaleX = _ref6$scaleX === void 0 ? 1 : _ref6$scaleX,\n _ref6$scaleY = _ref6.scaleY,\n scaleY = _ref6$scaleY === void 0 ? 1 : _ref6$scaleY;\n var aspectRatio = _ref7.aspectRatio,\n naturalWidth = _ref7.naturalWidth,\n naturalHeight = _ref7.naturalHeight;\n var _ref8$fillColor = _ref8.fillColor,\n fillColor = _ref8$fillColor === void 0 ? 'transparent' : _ref8$fillColor,\n _ref8$imageSmoothingE = _ref8.imageSmoothingEnabled,\n imageSmoothingEnabled = _ref8$imageSmoothingE === void 0 ? true : _ref8$imageSmoothingE,\n _ref8$imageSmoothingQ = _ref8.imageSmoothingQuality,\n imageSmoothingQuality = _ref8$imageSmoothingQ === void 0 ? 'low' : _ref8$imageSmoothingQ,\n _ref8$maxWidth = _ref8.maxWidth,\n maxWidth = _ref8$maxWidth === void 0 ? Infinity : _ref8$maxWidth,\n _ref8$maxHeight = _ref8.maxHeight,\n maxHeight = _ref8$maxHeight === void 0 ? Infinity : _ref8$maxHeight,\n _ref8$minWidth = _ref8.minWidth,\n minWidth = _ref8$minWidth === void 0 ? 0 : _ref8$minWidth,\n _ref8$minHeight = _ref8.minHeight,\n minHeight = _ref8$minHeight === void 0 ? 0 : _ref8$minHeight;\n var canvas = document.createElement('canvas');\n var context = canvas.getContext('2d');\n var maxSizes = getAdjustedSizes({\n aspectRatio: aspectRatio,\n width: maxWidth,\n height: maxHeight\n });\n var minSizes = getAdjustedSizes({\n aspectRatio: aspectRatio,\n width: minWidth,\n height: minHeight\n }, 'cover');\n var width = Math.min(maxSizes.width, Math.max(minSizes.width, naturalWidth));\n var height = Math.min(maxSizes.height, Math.max(minSizes.height, naturalHeight)); // Note: should always use image's natural sizes for drawing as\n // imageData.naturalWidth === canvasData.naturalHeight when rotate % 180 === 90\n\n var destMaxSizes = getAdjustedSizes({\n aspectRatio: imageAspectRatio,\n width: maxWidth,\n height: maxHeight\n });\n var destMinSizes = getAdjustedSizes({\n aspectRatio: imageAspectRatio,\n width: minWidth,\n height: minHeight\n }, 'cover');\n var destWidth = Math.min(destMaxSizes.width, Math.max(destMinSizes.width, imageNaturalWidth));\n var destHeight = Math.min(destMaxSizes.height, Math.max(destMinSizes.height, imageNaturalHeight));\n var params = [-destWidth / 2, -destHeight / 2, destWidth, destHeight];\n canvas.width = normalizeDecimalNumber(width);\n canvas.height = normalizeDecimalNumber(height);\n context.fillStyle = fillColor;\n context.fillRect(0, 0, width, height);\n context.save();\n context.translate(width / 2, height / 2);\n context.rotate(rotate * Math.PI / 180);\n context.scale(scaleX, scaleY);\n context.imageSmoothingEnabled = imageSmoothingEnabled;\n context.imageSmoothingQuality = imageSmoothingQuality;\n context.drawImage.apply(context, [image].concat(_toConsumableArray(params.map(function (param) {\n return Math.floor(normalizeDecimalNumber(param));\n }))));\n context.restore();\n return canvas;\n }\n var fromCharCode = String.fromCharCode;\n /**\n * Get string from char code in data view.\n * @param {DataView} dataView - The data view for read.\n * @param {number} start - The start index.\n * @param {number} length - The read length.\n * @returns {string} The read result.\n */\n\n function getStringFromCharCode(dataView, start, length) {\n var str = '';\n length += start;\n\n for (var i = start; i < length; i += 1) {\n str += fromCharCode(dataView.getUint8(i));\n }\n\n return str;\n }\n var REGEXP_DATA_URL_HEAD = /^data:.*,/;\n /**\n * Transform Data URL to array buffer.\n * @param {string} dataURL - The Data URL to transform.\n * @returns {ArrayBuffer} The result array buffer.\n */\n\n function dataURLToArrayBuffer(dataURL) {\n var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, '');\n var binary = atob(base64);\n var arrayBuffer = new ArrayBuffer(binary.length);\n var uint8 = new Uint8Array(arrayBuffer);\n forEach(uint8, function (value, i) {\n uint8[i] = binary.charCodeAt(i);\n });\n return arrayBuffer;\n }\n /**\n * Transform array buffer to Data URL.\n * @param {ArrayBuffer} arrayBuffer - The array buffer to transform.\n * @param {string} mimeType - The mime type of the Data URL.\n * @returns {string} The result Data URL.\n */\n\n function arrayBufferToDataURL(arrayBuffer, mimeType) {\n var chunks = []; // Chunk Typed Array for better performance (#435)\n\n var chunkSize = 8192;\n var uint8 = new Uint8Array(arrayBuffer);\n\n while (uint8.length > 0) {\n // XXX: Babel's `toConsumableArray` helper will throw error in IE or Safari 9\n // eslint-disable-next-line prefer-spread\n chunks.push(fromCharCode.apply(null, toArray(uint8.subarray(0, chunkSize))));\n uint8 = uint8.subarray(chunkSize);\n }\n\n return \"data:\".concat(mimeType, \";base64,\").concat(btoa(chunks.join('')));\n }\n /**\n * Get orientation value from given array buffer.\n * @param {ArrayBuffer} arrayBuffer - The array buffer to read.\n * @returns {number} The read orientation value.\n */\n\n function resetAndGetOrientation(arrayBuffer) {\n var dataView = new DataView(arrayBuffer);\n var orientation; // Ignores range error when the image does not have correct Exif information\n\n try {\n var littleEndian;\n var app1Start;\n var ifdStart; // Only handle JPEG image (start by 0xFFD8)\n\n if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {\n var length = dataView.byteLength;\n var offset = 2;\n\n while (offset + 1 < length) {\n if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {\n app1Start = offset;\n break;\n }\n\n offset += 1;\n }\n }\n\n if (app1Start) {\n var exifIDCode = app1Start + 4;\n var tiffOffset = app1Start + 10;\n\n if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {\n var endianness = dataView.getUint16(tiffOffset);\n littleEndian = endianness === 0x4949;\n\n if (littleEndian || endianness === 0x4D4D\n /* bigEndian */\n ) {\n if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {\n var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);\n\n if (firstIFDOffset >= 0x00000008) {\n ifdStart = tiffOffset + firstIFDOffset;\n }\n }\n }\n }\n }\n\n if (ifdStart) {\n var _length = dataView.getUint16(ifdStart, littleEndian);\n\n var _offset;\n\n var i;\n\n for (i = 0; i < _length; i += 1) {\n _offset = ifdStart + i * 12 + 2;\n\n if (dataView.getUint16(_offset, littleEndian) === 0x0112\n /* Orientation */\n ) {\n // 8 is the offset of the current tag's value\n _offset += 8; // Get the original orientation value\n\n orientation = dataView.getUint16(_offset, littleEndian); // Override the orientation with its default value\n\n dataView.setUint16(_offset, 1, littleEndian);\n break;\n }\n }\n }\n } catch (error) {\n orientation = 1;\n }\n\n return orientation;\n }\n /**\n * Parse Exif Orientation value.\n * @param {number} orientation - The orientation to parse.\n * @returns {Object} The parsed result.\n */\n\n function parseOrientation(orientation) {\n var rotate = 0;\n var scaleX = 1;\n var scaleY = 1;\n\n switch (orientation) {\n // Flip horizontal\n case 2:\n scaleX = -1;\n break;\n // Rotate left 180°\n\n case 3:\n rotate = -180;\n break;\n // Flip vertical\n\n case 4:\n scaleY = -1;\n break;\n // Flip vertical and rotate right 90°\n\n case 5:\n rotate = 90;\n scaleY = -1;\n break;\n // Rotate right 90°\n\n case 6:\n rotate = 90;\n break;\n // Flip horizontal and rotate right 90°\n\n case 7:\n rotate = 90;\n scaleX = -1;\n break;\n // Rotate left 90°\n\n case 8:\n rotate = -90;\n break;\n\n default:\n }\n\n return {\n rotate: rotate,\n scaleX: scaleX,\n scaleY: scaleY\n };\n }\n\n var render = {\n render: function render() {\n this.initContainer();\n this.initCanvas();\n this.initCropBox();\n this.renderCanvas();\n\n if (this.cropped) {\n this.renderCropBox();\n }\n },\n initContainer: function initContainer() {\n var element = this.element,\n options = this.options,\n container = this.container,\n cropper = this.cropper;\n addClass(cropper, CLASS_HIDDEN);\n removeClass(element, CLASS_HIDDEN);\n var containerData = {\n width: Math.max(container.offsetWidth, Number(options.minContainerWidth) || 200),\n height: Math.max(container.offsetHeight, Number(options.minContainerHeight) || 100)\n };\n this.containerData = containerData;\n setStyle(cropper, {\n width: containerData.width,\n height: containerData.height\n });\n addClass(element, CLASS_HIDDEN);\n removeClass(cropper, CLASS_HIDDEN);\n },\n // Canvas (image wrapper)\n initCanvas: function initCanvas() {\n var containerData = this.containerData,\n imageData = this.imageData;\n var viewMode = this.options.viewMode;\n var rotated = Math.abs(imageData.rotate) % 180 === 90;\n var naturalWidth = rotated ? imageData.naturalHeight : imageData.naturalWidth;\n var naturalHeight = rotated ? imageData.naturalWidth : imageData.naturalHeight;\n var aspectRatio = naturalWidth / naturalHeight;\n var canvasWidth = containerData.width;\n var canvasHeight = containerData.height;\n\n if (containerData.height * aspectRatio > containerData.width) {\n if (viewMode === 3) {\n canvasWidth = containerData.height * aspectRatio;\n } else {\n canvasHeight = containerData.width / aspectRatio;\n }\n } else if (viewMode === 3) {\n canvasHeight = containerData.width / aspectRatio;\n } else {\n canvasWidth = containerData.height * aspectRatio;\n }\n\n var canvasData = {\n aspectRatio: aspectRatio,\n naturalWidth: naturalWidth,\n naturalHeight: naturalHeight,\n width: canvasWidth,\n height: canvasHeight\n };\n canvasData.left = (containerData.width - canvasWidth) / 2;\n canvasData.top = (containerData.height - canvasHeight) / 2;\n canvasData.oldLeft = canvasData.left;\n canvasData.oldTop = canvasData.top;\n this.canvasData = canvasData;\n this.limited = viewMode === 1 || viewMode === 2;\n this.limitCanvas(true, true);\n this.initialImageData = assign({}, imageData);\n this.initialCanvasData = assign({}, canvasData);\n },\n limitCanvas: function limitCanvas(sizeLimited, positionLimited) {\n var options = this.options,\n containerData = this.containerData,\n canvasData = this.canvasData,\n cropBoxData = this.cropBoxData;\n var viewMode = options.viewMode;\n var aspectRatio = canvasData.aspectRatio;\n var cropped = this.cropped && cropBoxData;\n\n if (sizeLimited) {\n var minCanvasWidth = Number(options.minCanvasWidth) || 0;\n var minCanvasHeight = Number(options.minCanvasHeight) || 0;\n\n if (viewMode > 1) {\n minCanvasWidth = Math.max(minCanvasWidth, containerData.width);\n minCanvasHeight = Math.max(minCanvasHeight, containerData.height);\n\n if (viewMode === 3) {\n if (minCanvasHeight * aspectRatio > minCanvasWidth) {\n minCanvasWidth = minCanvasHeight * aspectRatio;\n } else {\n minCanvasHeight = minCanvasWidth / aspectRatio;\n }\n }\n } else if (viewMode > 0) {\n if (minCanvasWidth) {\n minCanvasWidth = Math.max(minCanvasWidth, cropped ? cropBoxData.width : 0);\n } else if (minCanvasHeight) {\n minCanvasHeight = Math.max(minCanvasHeight, cropped ? cropBoxData.height : 0);\n } else if (cropped) {\n minCanvasWidth = cropBoxData.width;\n minCanvasHeight = cropBoxData.height;\n\n if (minCanvasHeight * aspectRatio > minCanvasWidth) {\n minCanvasWidth = minCanvasHeight * aspectRatio;\n } else {\n minCanvasHeight = minCanvasWidth / aspectRatio;\n }\n }\n }\n\n var _getAdjustedSizes = getAdjustedSizes({\n aspectRatio: aspectRatio,\n width: minCanvasWidth,\n height: minCanvasHeight\n });\n\n minCanvasWidth = _getAdjustedSizes.width;\n minCanvasHeight = _getAdjustedSizes.height;\n canvasData.minWidth = minCanvasWidth;\n canvasData.minHeight = minCanvasHeight;\n canvasData.maxWidth = Infinity;\n canvasData.maxHeight = Infinity;\n }\n\n if (positionLimited) {\n if (viewMode > (cropped ? 0 : 1)) {\n var newCanvasLeft = containerData.width - canvasData.width;\n var newCanvasTop = containerData.height - canvasData.height;\n canvasData.minLeft = Math.min(0, newCanvasLeft);\n canvasData.minTop = Math.min(0, newCanvasTop);\n canvasData.maxLeft = Math.max(0, newCanvasLeft);\n canvasData.maxTop = Math.max(0, newCanvasTop);\n\n if (cropped && this.limited) {\n canvasData.minLeft = Math.min(cropBoxData.left, cropBoxData.left + (cropBoxData.width - canvasData.width));\n canvasData.minTop = Math.min(cropBoxData.top, cropBoxData.top + (cropBoxData.height - canvasData.height));\n canvasData.maxLeft = cropBoxData.left;\n canvasData.maxTop = cropBoxData.top;\n\n if (viewMode === 2) {\n if (canvasData.width >= containerData.width) {\n canvasData.minLeft = Math.min(0, newCanvasLeft);\n canvasData.maxLeft = Math.max(0, newCanvasLeft);\n }\n\n if (canvasData.height >= containerData.height) {\n canvasData.minTop = Math.min(0, newCanvasTop);\n canvasData.maxTop = Math.max(0, newCanvasTop);\n }\n }\n }\n } else {\n canvasData.minLeft = -canvasData.width;\n canvasData.minTop = -canvasData.height;\n canvasData.maxLeft = containerData.width;\n canvasData.maxTop = containerData.height;\n }\n }\n },\n renderCanvas: function renderCanvas(changed, transformed) {\n var canvasData = this.canvasData,\n imageData = this.imageData;\n\n if (transformed) {\n var _getRotatedSizes = getRotatedSizes({\n width: imageData.naturalWidth * Math.abs(imageData.scaleX || 1),\n height: imageData.naturalHeight * Math.abs(imageData.scaleY || 1),\n degree: imageData.rotate || 0\n }),\n naturalWidth = _getRotatedSizes.width,\n naturalHeight = _getRotatedSizes.height;\n\n var width = canvasData.width * (naturalWidth / canvasData.naturalWidth);\n var height = canvasData.height * (naturalHeight / canvasData.naturalHeight);\n canvasData.left -= (width - canvasData.width) / 2;\n canvasData.top -= (height - canvasData.height) / 2;\n canvasData.width = width;\n canvasData.height = height;\n canvasData.aspectRatio = naturalWidth / naturalHeight;\n canvasData.naturalWidth = naturalWidth;\n canvasData.naturalHeight = naturalHeight;\n this.limitCanvas(true, false);\n }\n\n if (canvasData.width > canvasData.maxWidth || canvasData.width < canvasData.minWidth) {\n canvasData.left = canvasData.oldLeft;\n }\n\n if (canvasData.height > canvasData.maxHeight || canvasData.height < canvasData.minHeight) {\n canvasData.top = canvasData.oldTop;\n }\n\n canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth);\n canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight);\n this.limitCanvas(false, true);\n canvasData.left = Math.min(Math.max(canvasData.left, canvasData.minLeft), canvasData.maxLeft);\n canvasData.top = Math.min(Math.max(canvasData.top, canvasData.minTop), canvasData.maxTop);\n canvasData.oldLeft = canvasData.left;\n canvasData.oldTop = canvasData.top;\n setStyle(this.canvas, assign({\n width: canvasData.width,\n height: canvasData.height\n }, getTransforms({\n translateX: canvasData.left,\n translateY: canvasData.top\n })));\n this.renderImage(changed);\n\n if (this.cropped && this.limited) {\n this.limitCropBox(true, true);\n }\n },\n renderImage: function renderImage(changed) {\n var canvasData = this.canvasData,\n imageData = this.imageData;\n var width = imageData.naturalWidth * (canvasData.width / canvasData.naturalWidth);\n var height = imageData.naturalHeight * (canvasData.height / canvasData.naturalHeight);\n assign(imageData, {\n width: width,\n height: height,\n left: (canvasData.width - width) / 2,\n top: (canvasData.height - height) / 2\n });\n setStyle(this.image, assign({\n width: imageData.width,\n height: imageData.height\n }, getTransforms(assign({\n translateX: imageData.left,\n translateY: imageData.top\n }, imageData))));\n\n if (changed) {\n this.output();\n }\n },\n initCropBox: function initCropBox() {\n var options = this.options,\n canvasData = this.canvasData;\n var aspectRatio = options.aspectRatio || options.initialAspectRatio;\n var autoCropArea = Number(options.autoCropArea) || 0.8;\n var cropBoxData = {\n width: canvasData.width,\n height: canvasData.height\n };\n\n if (aspectRatio) {\n if (canvasData.height * aspectRatio > canvasData.width) {\n cropBoxData.height = cropBoxData.width / aspectRatio;\n } else {\n cropBoxData.width = cropBoxData.height * aspectRatio;\n }\n }\n\n this.cropBoxData = cropBoxData;\n this.limitCropBox(true, true); // Initialize auto crop area\n\n cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth);\n cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight); // The width/height of auto crop area must large than \"minWidth/Height\"\n\n cropBoxData.width = Math.max(cropBoxData.minWidth, cropBoxData.width * autoCropArea);\n cropBoxData.height = Math.max(cropBoxData.minHeight, cropBoxData.height * autoCropArea);\n cropBoxData.left = canvasData.left + (canvasData.width - cropBoxData.width) / 2;\n cropBoxData.top = canvasData.top + (canvasData.height - cropBoxData.height) / 2;\n cropBoxData.oldLeft = cropBoxData.left;\n cropBoxData.oldTop = cropBoxData.top;\n this.initialCropBoxData = assign({}, cropBoxData);\n },\n limitCropBox: function limitCropBox(sizeLimited, positionLimited) {\n var options = this.options,\n containerData = this.containerData,\n canvasData = this.canvasData,\n cropBoxData = this.cropBoxData,\n limited = this.limited;\n var aspectRatio = options.aspectRatio;\n\n if (sizeLimited) {\n var minCropBoxWidth = Number(options.minCropBoxWidth) || 0;\n var minCropBoxHeight = Number(options.minCropBoxHeight) || 0;\n var maxCropBoxWidth = limited ? Math.min(containerData.width, canvasData.width, canvasData.width + canvasData.left, containerData.width - canvasData.left) : containerData.width;\n var maxCropBoxHeight = limited ? Math.min(containerData.height, canvasData.height, canvasData.height + canvasData.top, containerData.height - canvasData.top) : containerData.height; // The min/maxCropBoxWidth/Height must be less than container's width/height\n\n minCropBoxWidth = Math.min(minCropBoxWidth, containerData.width);\n minCropBoxHeight = Math.min(minCropBoxHeight, containerData.height);\n\n if (aspectRatio) {\n if (minCropBoxWidth && minCropBoxHeight) {\n if (minCropBoxHeight * aspectRatio > minCropBoxWidth) {\n minCropBoxHeight = minCropBoxWidth / aspectRatio;\n } else {\n minCropBoxWidth = minCropBoxHeight * aspectRatio;\n }\n } else if (minCropBoxWidth) {\n minCropBoxHeight = minCropBoxWidth / aspectRatio;\n } else if (minCropBoxHeight) {\n minCropBoxWidth = minCropBoxHeight * aspectRatio;\n }\n\n if (maxCropBoxHeight * aspectRatio > maxCropBoxWidth) {\n maxCropBoxHeight = maxCropBoxWidth / aspectRatio;\n } else {\n maxCropBoxWidth = maxCropBoxHeight * aspectRatio;\n }\n } // The minWidth/Height must be less than maxWidth/Height\n\n\n cropBoxData.minWidth = Math.min(minCropBoxWidth, maxCropBoxWidth);\n cropBoxData.minHeight = Math.min(minCropBoxHeight, maxCropBoxHeight);\n cropBoxData.maxWidth = maxCropBoxWidth;\n cropBoxData.maxHeight = maxCropBoxHeight;\n }\n\n if (positionLimited) {\n if (limited) {\n cropBoxData.minLeft = Math.max(0, canvasData.left);\n cropBoxData.minTop = Math.max(0, canvasData.top);\n cropBoxData.maxLeft = Math.min(containerData.width, canvasData.left + canvasData.width) - cropBoxData.width;\n cropBoxData.maxTop = Math.min(containerData.height, canvasData.top + canvasData.height) - cropBoxData.height;\n } else {\n cropBoxData.minLeft = 0;\n cropBoxData.minTop = 0;\n cropBoxData.maxLeft = containerData.width - cropBoxData.width;\n cropBoxData.maxTop = containerData.height - cropBoxData.height;\n }\n }\n },\n renderCropBox: function renderCropBox() {\n var options = this.options,\n containerData = this.containerData,\n cropBoxData = this.cropBoxData;\n\n if (cropBoxData.width > cropBoxData.maxWidth || cropBoxData.width < cropBoxData.minWidth) {\n cropBoxData.left = cropBoxData.oldLeft;\n }\n\n if (cropBoxData.height > cropBoxData.maxHeight || cropBoxData.height < cropBoxData.minHeight) {\n cropBoxData.top = cropBoxData.oldTop;\n }\n\n cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth);\n cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight);\n this.limitCropBox(false, true);\n cropBoxData.left = Math.min(Math.max(cropBoxData.left, cropBoxData.minLeft), cropBoxData.maxLeft);\n cropBoxData.top = Math.min(Math.max(cropBoxData.top, cropBoxData.minTop), cropBoxData.maxTop);\n cropBoxData.oldLeft = cropBoxData.left;\n cropBoxData.oldTop = cropBoxData.top;\n\n if (options.movable && options.cropBoxMovable) {\n // Turn to move the canvas when the crop box is equal to the container\n setData(this.face, DATA_ACTION, cropBoxData.width >= containerData.width && cropBoxData.height >= containerData.height ? ACTION_MOVE : ACTION_ALL);\n }\n\n setStyle(this.cropBox, assign({\n width: cropBoxData.width,\n height: cropBoxData.height\n }, getTransforms({\n translateX: cropBoxData.left,\n translateY: cropBoxData.top\n })));\n\n if (this.cropped && this.limited) {\n this.limitCanvas(true, true);\n }\n\n if (!this.disabled) {\n this.output();\n }\n },\n output: function output() {\n this.preview();\n dispatchEvent(this.element, EVENT_CROP, this.getData());\n }\n };\n\n var preview = {\n initPreview: function initPreview() {\n var element = this.element,\n crossOrigin = this.crossOrigin;\n var preview = this.options.preview;\n var url = crossOrigin ? this.crossOriginUrl : this.url;\n var alt = element.alt || 'The image to preview';\n var image = document.createElement('img');\n\n if (crossOrigin) {\n image.crossOrigin = crossOrigin;\n }\n\n image.src = url;\n image.alt = alt;\n this.viewBox.appendChild(image);\n this.viewBoxImage = image;\n\n if (!preview) {\n return;\n }\n\n var previews = preview;\n\n if (typeof preview === 'string') {\n previews = element.ownerDocument.querySelectorAll(preview);\n } else if (preview.querySelector) {\n previews = [preview];\n }\n\n this.previews = previews;\n forEach(previews, function (el) {\n var img = document.createElement('img'); // Save the original size for recover\n\n setData(el, DATA_PREVIEW, {\n width: el.offsetWidth,\n height: el.offsetHeight,\n html: el.innerHTML\n });\n\n if (crossOrigin) {\n img.crossOrigin = crossOrigin;\n }\n\n img.src = url;\n img.alt = alt;\n /**\n * Override img element styles\n * Add `display:block` to avoid margin top issue\n * Add `height:auto` to override `height` attribute on IE8\n * (Occur only when margin-top <= -height)\n */\n\n img.style.cssText = 'display:block;' + 'width:100%;' + 'height:auto;' + 'min-width:0!important;' + 'min-height:0!important;' + 'max-width:none!important;' + 'max-height:none!important;' + 'image-orientation:0deg!important;\"';\n el.innerHTML = '';\n el.appendChild(img);\n });\n },\n resetPreview: function resetPreview() {\n forEach(this.previews, function (element) {\n var data = getData(element, DATA_PREVIEW);\n setStyle(element, {\n width: data.width,\n height: data.height\n });\n element.innerHTML = data.html;\n removeData(element, DATA_PREVIEW);\n });\n },\n preview: function preview() {\n var imageData = this.imageData,\n canvasData = this.canvasData,\n cropBoxData = this.cropBoxData;\n var cropBoxWidth = cropBoxData.width,\n cropBoxHeight = cropBoxData.height;\n var width = imageData.width,\n height = imageData.height;\n var left = cropBoxData.left - canvasData.left - imageData.left;\n var top = cropBoxData.top - canvasData.top - imageData.top;\n\n if (!this.cropped || this.disabled) {\n return;\n }\n\n setStyle(this.viewBoxImage, assign({\n width: width,\n height: height\n }, getTransforms(assign({\n translateX: -left,\n translateY: -top\n }, imageData))));\n forEach(this.previews, function (element) {\n var data = getData(element, DATA_PREVIEW);\n var originalWidth = data.width;\n var originalHeight = data.height;\n var newWidth = originalWidth;\n var newHeight = originalHeight;\n var ratio = 1;\n\n if (cropBoxWidth) {\n ratio = originalWidth / cropBoxWidth;\n newHeight = cropBoxHeight * ratio;\n }\n\n if (cropBoxHeight && newHeight > originalHeight) {\n ratio = originalHeight / cropBoxHeight;\n newWidth = cropBoxWidth * ratio;\n newHeight = originalHeight;\n }\n\n setStyle(element, {\n width: newWidth,\n height: newHeight\n });\n setStyle(element.getElementsByTagName('img')[0], assign({\n width: width * ratio,\n height: height * ratio\n }, getTransforms(assign({\n translateX: -left * ratio,\n translateY: -top * ratio\n }, imageData))));\n });\n }\n };\n\n var events = {\n bind: function bind() {\n var element = this.element,\n options = this.options,\n cropper = this.cropper;\n\n if (isFunction(options.cropstart)) {\n addListener(element, EVENT_CROP_START, options.cropstart);\n }\n\n if (isFunction(options.cropmove)) {\n addListener(element, EVENT_CROP_MOVE, options.cropmove);\n }\n\n if (isFunction(options.cropend)) {\n addListener(element, EVENT_CROP_END, options.cropend);\n }\n\n if (isFunction(options.crop)) {\n addListener(element, EVENT_CROP, options.crop);\n }\n\n if (isFunction(options.zoom)) {\n addListener(element, EVENT_ZOOM, options.zoom);\n }\n\n addListener(cropper, EVENT_POINTER_DOWN, this.onCropStart = this.cropStart.bind(this));\n\n if (options.zoomable && options.zoomOnWheel) {\n addListener(cropper, EVENT_WHEEL, this.onWheel = this.wheel.bind(this), {\n passive: false,\n capture: true\n });\n }\n\n if (options.toggleDragModeOnDblclick) {\n addListener(cropper, EVENT_DBLCLICK, this.onDblclick = this.dblclick.bind(this));\n }\n\n addListener(element.ownerDocument, EVENT_POINTER_MOVE, this.onCropMove = this.cropMove.bind(this));\n addListener(element.ownerDocument, EVENT_POINTER_UP, this.onCropEnd = this.cropEnd.bind(this));\n\n if (options.responsive) {\n addListener(window, EVENT_RESIZE, this.onResize = this.resize.bind(this));\n }\n },\n unbind: function unbind() {\n var element = this.element,\n options = this.options,\n cropper = this.cropper;\n\n if (isFunction(options.cropstart)) {\n removeListener(element, EVENT_CROP_START, options.cropstart);\n }\n\n if (isFunction(options.cropmove)) {\n removeListener(element, EVENT_CROP_MOVE, options.cropmove);\n }\n\n if (isFunction(options.cropend)) {\n removeListener(element, EVENT_CROP_END, options.cropend);\n }\n\n if (isFunction(options.crop)) {\n removeListener(element, EVENT_CROP, options.crop);\n }\n\n if (isFunction(options.zoom)) {\n removeListener(element, EVENT_ZOOM, options.zoom);\n }\n\n removeListener(cropper, EVENT_POINTER_DOWN, this.onCropStart);\n\n if (options.zoomable && options.zoomOnWheel) {\n removeListener(cropper, EVENT_WHEEL, this.onWheel, {\n passive: false,\n capture: true\n });\n }\n\n if (options.toggleDragModeOnDblclick) {\n removeListener(cropper, EVENT_DBLCLICK, this.onDblclick);\n }\n\n removeListener(element.ownerDocument, EVENT_POINTER_MOVE, this.onCropMove);\n removeListener(element.ownerDocument, EVENT_POINTER_UP, this.onCropEnd);\n\n if (options.responsive) {\n removeListener(window, EVENT_RESIZE, this.onResize);\n }\n }\n };\n\n var handlers = {\n resize: function resize() {\n var options = this.options,\n container = this.container,\n containerData = this.containerData;\n var minContainerWidth = Number(options.minContainerWidth) || MIN_CONTAINER_WIDTH;\n var minContainerHeight = Number(options.minContainerHeight) || MIN_CONTAINER_HEIGHT;\n\n if (this.disabled || containerData.width <= minContainerWidth || containerData.height <= minContainerHeight) {\n return;\n }\n\n var ratio = container.offsetWidth / containerData.width; // Resize when width changed or height changed\n\n if (ratio !== 1 || container.offsetHeight !== containerData.height) {\n var canvasData;\n var cropBoxData;\n\n if (options.restore) {\n canvasData = this.getCanvasData();\n cropBoxData = this.getCropBoxData();\n }\n\n this.render();\n\n if (options.restore) {\n this.setCanvasData(forEach(canvasData, function (n, i) {\n canvasData[i] = n * ratio;\n }));\n this.setCropBoxData(forEach(cropBoxData, function (n, i) {\n cropBoxData[i] = n * ratio;\n }));\n }\n }\n },\n dblclick: function dblclick() {\n if (this.disabled || this.options.dragMode === DRAG_MODE_NONE) {\n return;\n }\n\n this.setDragMode(hasClass(this.dragBox, CLASS_CROP) ? DRAG_MODE_MOVE : DRAG_MODE_CROP);\n },\n wheel: function wheel(event) {\n var _this = this;\n\n var ratio = Number(this.options.wheelZoomRatio) || 0.1;\n var delta = 1;\n\n if (this.disabled) {\n return;\n }\n\n event.preventDefault(); // Limit wheel speed to prevent zoom too fast (#21)\n\n if (this.wheeling) {\n return;\n }\n\n this.wheeling = true;\n setTimeout(function () {\n _this.wheeling = false;\n }, 50);\n\n if (event.deltaY) {\n delta = event.deltaY > 0 ? 1 : -1;\n } else if (event.wheelDelta) {\n delta = -event.wheelDelta / 120;\n } else if (event.detail) {\n delta = event.detail > 0 ? 1 : -1;\n }\n\n this.zoom(-delta * ratio, event);\n },\n cropStart: function cropStart(event) {\n var buttons = event.buttons,\n button = event.button;\n\n if (this.disabled // Handle mouse event and pointer event and ignore touch event\n || (event.type === 'mousedown' || event.type === 'pointerdown' && event.pointerType === 'mouse') && ( // No primary button (Usually the left button)\n isNumber(buttons) && buttons !== 1 || isNumber(button) && button !== 0 // Open context menu\n || event.ctrlKey)) {\n return;\n }\n\n var options = this.options,\n pointers = this.pointers;\n var action;\n\n if (event.changedTouches) {\n // Handle touch event\n forEach(event.changedTouches, function (touch) {\n pointers[touch.identifier] = getPointer(touch);\n });\n } else {\n // Handle mouse event and pointer event\n pointers[event.pointerId || 0] = getPointer(event);\n }\n\n if (Object.keys(pointers).length > 1 && options.zoomable && options.zoomOnTouch) {\n action = ACTION_ZOOM;\n } else {\n action = getData(event.target, DATA_ACTION);\n }\n\n if (!REGEXP_ACTIONS.test(action)) {\n return;\n }\n\n if (dispatchEvent(this.element, EVENT_CROP_START, {\n originalEvent: event,\n action: action\n }) === false) {\n return;\n } // This line is required for preventing page zooming in iOS browsers\n\n\n event.preventDefault();\n this.action = action;\n this.cropping = false;\n\n if (action === ACTION_CROP) {\n this.cropping = true;\n addClass(this.dragBox, CLASS_MODAL);\n }\n },\n cropMove: function cropMove(event) {\n var action = this.action;\n\n if (this.disabled || !action) {\n return;\n }\n\n var pointers = this.pointers;\n event.preventDefault();\n\n if (dispatchEvent(this.element, EVENT_CROP_MOVE, {\n originalEvent: event,\n action: action\n }) === false) {\n return;\n }\n\n if (event.changedTouches) {\n forEach(event.changedTouches, function (touch) {\n // The first parameter should not be undefined (#432)\n assign(pointers[touch.identifier] || {}, getPointer(touch, true));\n });\n } else {\n assign(pointers[event.pointerId || 0] || {}, getPointer(event, true));\n }\n\n this.change(event);\n },\n cropEnd: function cropEnd(event) {\n if (this.disabled) {\n return;\n }\n\n var action = this.action,\n pointers = this.pointers;\n\n if (event.changedTouches) {\n forEach(event.changedTouches, function (touch) {\n delete pointers[touch.identifier];\n });\n } else {\n delete pointers[event.pointerId || 0];\n }\n\n if (!action) {\n return;\n }\n\n event.preventDefault();\n\n if (!Object.keys(pointers).length) {\n this.action = '';\n }\n\n if (this.cropping) {\n this.cropping = false;\n toggleClass(this.dragBox, CLASS_MODAL, this.cropped && this.options.modal);\n }\n\n dispatchEvent(this.element, EVENT_CROP_END, {\n originalEvent: event,\n action: action\n });\n }\n };\n\n var change = {\n change: function change(event) {\n var options = this.options,\n canvasData = this.canvasData,\n containerData = this.containerData,\n cropBoxData = this.cropBoxData,\n pointers = this.pointers;\n var action = this.action;\n var aspectRatio = options.aspectRatio;\n var left = cropBoxData.left,\n top = cropBoxData.top,\n width = cropBoxData.width,\n height = cropBoxData.height;\n var right = left + width;\n var bottom = top + height;\n var minLeft = 0;\n var minTop = 0;\n var maxWidth = containerData.width;\n var maxHeight = containerData.height;\n var renderable = true;\n var offset; // Locking aspect ratio in \"free mode\" by holding shift key\n\n if (!aspectRatio && event.shiftKey) {\n aspectRatio = width && height ? width / height : 1;\n }\n\n if (this.limited) {\n minLeft = cropBoxData.minLeft;\n minTop = cropBoxData.minTop;\n maxWidth = minLeft + Math.min(containerData.width, canvasData.width, canvasData.left + canvasData.width);\n maxHeight = minTop + Math.min(containerData.height, canvasData.height, canvasData.top + canvasData.height);\n }\n\n var pointer = pointers[Object.keys(pointers)[0]];\n var range = {\n x: pointer.endX - pointer.startX,\n y: pointer.endY - pointer.startY\n };\n\n var check = function check(side) {\n switch (side) {\n case ACTION_EAST:\n if (right + range.x > maxWidth) {\n range.x = maxWidth - right;\n }\n\n break;\n\n case ACTION_WEST:\n if (left + range.x < minLeft) {\n range.x = minLeft - left;\n }\n\n break;\n\n case ACTION_NORTH:\n if (top + range.y < minTop) {\n range.y = minTop - top;\n }\n\n break;\n\n case ACTION_SOUTH:\n if (bottom + range.y > maxHeight) {\n range.y = maxHeight - bottom;\n }\n\n break;\n\n default:\n }\n };\n\n switch (action) {\n // Move crop box\n case ACTION_ALL:\n left += range.x;\n top += range.y;\n break;\n // Resize crop box\n\n case ACTION_EAST:\n if (range.x >= 0 && (right >= maxWidth || aspectRatio && (top <= minTop || bottom >= maxHeight))) {\n renderable = false;\n break;\n }\n\n check(ACTION_EAST);\n width += range.x;\n\n if (width < 0) {\n action = ACTION_WEST;\n width = -width;\n left -= width;\n }\n\n if (aspectRatio) {\n height = width / aspectRatio;\n top += (cropBoxData.height - height) / 2;\n }\n\n break;\n\n case ACTION_NORTH:\n if (range.y <= 0 && (top <= minTop || aspectRatio && (left <= minLeft || right >= maxWidth))) {\n renderable = false;\n break;\n }\n\n check(ACTION_NORTH);\n height -= range.y;\n top += range.y;\n\n if (height < 0) {\n action = ACTION_SOUTH;\n height = -height;\n top -= height;\n }\n\n if (aspectRatio) {\n width = height * aspectRatio;\n left += (cropBoxData.width - width) / 2;\n }\n\n break;\n\n case ACTION_WEST:\n if (range.x <= 0 && (left <= minLeft || aspectRatio && (top <= minTop || bottom >= maxHeight))) {\n renderable = false;\n break;\n }\n\n check(ACTION_WEST);\n width -= range.x;\n left += range.x;\n\n if (width < 0) {\n action = ACTION_EAST;\n width = -width;\n left -= width;\n }\n\n if (aspectRatio) {\n height = width / aspectRatio;\n top += (cropBoxData.height - height) / 2;\n }\n\n break;\n\n case ACTION_SOUTH:\n if (range.y >= 0 && (bottom >= maxHeight || aspectRatio && (left <= minLeft || right >= maxWidth))) {\n renderable = false;\n break;\n }\n\n check(ACTION_SOUTH);\n height += range.y;\n\n if (height < 0) {\n action = ACTION_NORTH;\n height = -height;\n top -= height;\n }\n\n if (aspectRatio) {\n width = height * aspectRatio;\n left += (cropBoxData.width - width) / 2;\n }\n\n break;\n\n case ACTION_NORTH_EAST:\n if (aspectRatio) {\n if (range.y <= 0 && (top <= minTop || right >= maxWidth)) {\n renderable = false;\n break;\n }\n\n check(ACTION_NORTH);\n height -= range.y;\n top += range.y;\n width = height * aspectRatio;\n } else {\n check(ACTION_NORTH);\n check(ACTION_EAST);\n\n if (range.x >= 0) {\n if (right < maxWidth) {\n width += range.x;\n } else if (range.y <= 0 && top <= minTop) {\n renderable = false;\n }\n } else {\n width += range.x;\n }\n\n if (range.y <= 0) {\n if (top > minTop) {\n height -= range.y;\n top += range.y;\n }\n } else {\n height -= range.y;\n top += range.y;\n }\n }\n\n if (width < 0 && height < 0) {\n action = ACTION_SOUTH_WEST;\n height = -height;\n width = -width;\n top -= height;\n left -= width;\n } else if (width < 0) {\n action = ACTION_NORTH_WEST;\n width = -width;\n left -= width;\n } else if (height < 0) {\n action = ACTION_SOUTH_EAST;\n height = -height;\n top -= height;\n }\n\n break;\n\n case ACTION_NORTH_WEST:\n if (aspectRatio) {\n if (range.y <= 0 && (top <= minTop || left <= minLeft)) {\n renderable = false;\n break;\n }\n\n check(ACTION_NORTH);\n height -= range.y;\n top += range.y;\n width = height * aspectRatio;\n left += cropBoxData.width - width;\n } else {\n check(ACTION_NORTH);\n check(ACTION_WEST);\n\n if (range.x <= 0) {\n if (left > minLeft) {\n width -= range.x;\n left += range.x;\n } else if (range.y <= 0 && top <= minTop) {\n renderable = false;\n }\n } else {\n width -= range.x;\n left += range.x;\n }\n\n if (range.y <= 0) {\n if (top > minTop) {\n height -= range.y;\n top += range.y;\n }\n } else {\n height -= range.y;\n top += range.y;\n }\n }\n\n if (width < 0 && height < 0) {\n action = ACTION_SOUTH_EAST;\n height = -height;\n width = -width;\n top -= height;\n left -= width;\n } else if (width < 0) {\n action = ACTION_NORTH_EAST;\n width = -width;\n left -= width;\n } else if (height < 0) {\n action = ACTION_SOUTH_WEST;\n height = -height;\n top -= height;\n }\n\n break;\n\n case ACTION_SOUTH_WEST:\n if (aspectRatio) {\n if (range.x <= 0 && (left <= minLeft || bottom >= maxHeight)) {\n renderable = false;\n break;\n }\n\n check(ACTION_WEST);\n width -= range.x;\n left += range.x;\n height = width / aspectRatio;\n } else {\n check(ACTION_SOUTH);\n check(ACTION_WEST);\n\n if (range.x <= 0) {\n if (left > minLeft) {\n width -= range.x;\n left += range.x;\n } else if (range.y >= 0 && bottom >= maxHeight) {\n renderable = false;\n }\n } else {\n width -= range.x;\n left += range.x;\n }\n\n if (range.y >= 0) {\n if (bottom < maxHeight) {\n height += range.y;\n }\n } else {\n height += range.y;\n }\n }\n\n if (width < 0 && height < 0) {\n action = ACTION_NORTH_EAST;\n height = -height;\n width = -width;\n top -= height;\n left -= width;\n } else if (width < 0) {\n action = ACTION_SOUTH_EAST;\n width = -width;\n left -= width;\n } else if (height < 0) {\n action = ACTION_NORTH_WEST;\n height = -height;\n top -= height;\n }\n\n break;\n\n case ACTION_SOUTH_EAST:\n if (aspectRatio) {\n if (range.x >= 0 && (right >= maxWidth || bottom >= maxHeight)) {\n renderable = false;\n break;\n }\n\n check(ACTION_EAST);\n width += range.x;\n height = width / aspectRatio;\n } else {\n check(ACTION_SOUTH);\n check(ACTION_EAST);\n\n if (range.x >= 0) {\n if (right < maxWidth) {\n width += range.x;\n } else if (range.y >= 0 && bottom >= maxHeight) {\n renderable = false;\n }\n } else {\n width += range.x;\n }\n\n if (range.y >= 0) {\n if (bottom < maxHeight) {\n height += range.y;\n }\n } else {\n height += range.y;\n }\n }\n\n if (width < 0 && height < 0) {\n action = ACTION_NORTH_WEST;\n height = -height;\n width = -width;\n top -= height;\n left -= width;\n } else if (width < 0) {\n action = ACTION_SOUTH_WEST;\n width = -width;\n left -= width;\n } else if (height < 0) {\n action = ACTION_NORTH_EAST;\n height = -height;\n top -= height;\n }\n\n break;\n // Move canvas\n\n case ACTION_MOVE:\n this.move(range.x, range.y);\n renderable = false;\n break;\n // Zoom canvas\n\n case ACTION_ZOOM:\n this.zoom(getMaxZoomRatio(pointers), event);\n renderable = false;\n break;\n // Create crop box\n\n case ACTION_CROP:\n if (!range.x || !range.y) {\n renderable = false;\n break;\n }\n\n offset = getOffset(this.cropper);\n left = pointer.startX - offset.left;\n top = pointer.startY - offset.top;\n width = cropBoxData.minWidth;\n height = cropBoxData.minHeight;\n\n if (range.x > 0) {\n action = range.y > 0 ? ACTION_SOUTH_EAST : ACTION_NORTH_EAST;\n } else if (range.x < 0) {\n left -= width;\n action = range.y > 0 ? ACTION_SOUTH_WEST : ACTION_NORTH_WEST;\n }\n\n if (range.y < 0) {\n top -= height;\n } // Show the crop box if is hidden\n\n\n if (!this.cropped) {\n removeClass(this.cropBox, CLASS_HIDDEN);\n this.cropped = true;\n\n if (this.limited) {\n this.limitCropBox(true, true);\n }\n }\n\n break;\n\n default:\n }\n\n if (renderable) {\n cropBoxData.width = width;\n cropBoxData.height = height;\n cropBoxData.left = left;\n cropBoxData.top = top;\n this.action = action;\n this.renderCropBox();\n } // Override\n\n\n forEach(pointers, function (p) {\n p.startX = p.endX;\n p.startY = p.endY;\n });\n }\n };\n\n var methods = {\n // Show the crop box manually\n crop: function crop() {\n if (this.ready && !this.cropped && !this.disabled) {\n this.cropped = true;\n this.limitCropBox(true, true);\n\n if (this.options.modal) {\n addClass(this.dragBox, CLASS_MODAL);\n }\n\n removeClass(this.cropBox, CLASS_HIDDEN);\n this.setCropBoxData(this.initialCropBoxData);\n }\n\n return this;\n },\n // Reset the image and crop box to their initial states\n reset: function reset() {\n if (this.ready && !this.disabled) {\n this.imageData = assign({}, this.initialImageData);\n this.canvasData = assign({}, this.initialCanvasData);\n this.cropBoxData = assign({}, this.initialCropBoxData);\n this.renderCanvas();\n\n if (this.cropped) {\n this.renderCropBox();\n }\n }\n\n return this;\n },\n // Clear the crop box\n clear: function clear() {\n if (this.cropped && !this.disabled) {\n assign(this.cropBoxData, {\n left: 0,\n top: 0,\n width: 0,\n height: 0\n });\n this.cropped = false;\n this.renderCropBox();\n this.limitCanvas(true, true); // Render canvas after crop box rendered\n\n this.renderCanvas();\n removeClass(this.dragBox, CLASS_MODAL);\n addClass(this.cropBox, CLASS_HIDDEN);\n }\n\n return this;\n },\n\n /**\n * Replace the image's src and rebuild the cropper\n * @param {string} url - The new URL.\n * @param {boolean} [hasSameSize] - Indicate if the new image has the same size as the old one.\n * @returns {Cropper} this\n */\n replace: function replace(url) {\n var hasSameSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n if (!this.disabled && url) {\n if (this.isImg) {\n this.element.src = url;\n }\n\n if (hasSameSize) {\n this.url = url;\n this.image.src = url;\n\n if (this.ready) {\n this.viewBoxImage.src = url;\n forEach(this.previews, function (element) {\n element.getElementsByTagName('img')[0].src = url;\n });\n }\n } else {\n if (this.isImg) {\n this.replaced = true;\n }\n\n this.options.data = null;\n this.uncreate();\n this.load(url);\n }\n }\n\n return this;\n },\n // Enable (unfreeze) the cropper\n enable: function enable() {\n if (this.ready && this.disabled) {\n this.disabled = false;\n removeClass(this.cropper, CLASS_DISABLED);\n }\n\n return this;\n },\n // Disable (freeze) the cropper\n disable: function disable() {\n if (this.ready && !this.disabled) {\n this.disabled = true;\n addClass(this.cropper, CLASS_DISABLED);\n }\n\n return this;\n },\n\n /**\n * Destroy the cropper and remove the instance from the image\n * @returns {Cropper} this\n */\n destroy: function destroy() {\n var element = this.element;\n\n if (!element[NAMESPACE]) {\n return this;\n }\n\n element[NAMESPACE] = undefined;\n\n if (this.isImg && this.replaced) {\n element.src = this.originalUrl;\n }\n\n this.uncreate();\n return this;\n },\n\n /**\n * Move the canvas with relative offsets\n * @param {number} offsetX - The relative offset distance on the x-axis.\n * @param {number} [offsetY=offsetX] - The relative offset distance on the y-axis.\n * @returns {Cropper} this\n */\n move: function move(offsetX) {\n var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : offsetX;\n var _this$canvasData = this.canvasData,\n left = _this$canvasData.left,\n top = _this$canvasData.top;\n return this.moveTo(isUndefined(offsetX) ? offsetX : left + Number(offsetX), isUndefined(offsetY) ? offsetY : top + Number(offsetY));\n },\n\n /**\n * Move the canvas to an absolute point\n * @param {number} x - The x-axis coordinate.\n * @param {number} [y=x] - The y-axis coordinate.\n * @returns {Cropper} this\n */\n moveTo: function moveTo(x) {\n var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x;\n var canvasData = this.canvasData;\n var changed = false;\n x = Number(x);\n y = Number(y);\n\n if (this.ready && !this.disabled && this.options.movable) {\n if (isNumber(x)) {\n canvasData.left = x;\n changed = true;\n }\n\n if (isNumber(y)) {\n canvasData.top = y;\n changed = true;\n }\n\n if (changed) {\n this.renderCanvas(true);\n }\n }\n\n return this;\n },\n\n /**\n * Zoom the canvas with a relative ratio\n * @param {number} ratio - The target ratio.\n * @param {Event} _originalEvent - The original event if any.\n * @returns {Cropper} this\n */\n zoom: function zoom(ratio, _originalEvent) {\n var canvasData = this.canvasData;\n ratio = Number(ratio);\n\n if (ratio < 0) {\n ratio = 1 / (1 - ratio);\n } else {\n ratio = 1 + ratio;\n }\n\n return this.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, null, _originalEvent);\n },\n\n /**\n * Zoom the canvas to an absolute ratio\n * @param {number} ratio - The target ratio.\n * @param {Object} pivot - The zoom pivot point coordinate.\n * @param {Event} _originalEvent - The original event if any.\n * @returns {Cropper} this\n */\n zoomTo: function zoomTo(ratio, pivot, _originalEvent) {\n var options = this.options,\n canvasData = this.canvasData;\n var width = canvasData.width,\n height = canvasData.height,\n naturalWidth = canvasData.naturalWidth,\n naturalHeight = canvasData.naturalHeight;\n ratio = Number(ratio);\n\n if (ratio >= 0 && this.ready && !this.disabled && options.zoomable) {\n var newWidth = naturalWidth * ratio;\n var newHeight = naturalHeight * ratio;\n\n if (dispatchEvent(this.element, EVENT_ZOOM, {\n ratio: ratio,\n oldRatio: width / naturalWidth,\n originalEvent: _originalEvent\n }) === false) {\n return this;\n }\n\n if (_originalEvent) {\n var pointers = this.pointers;\n var offset = getOffset(this.cropper);\n var center = pointers && Object.keys(pointers).length ? getPointersCenter(pointers) : {\n pageX: _originalEvent.pageX,\n pageY: _originalEvent.pageY\n }; // Zoom from the triggering point of the event\n\n canvasData.left -= (newWidth - width) * ((center.pageX - offset.left - canvasData.left) / width);\n canvasData.top -= (newHeight - height) * ((center.pageY - offset.top - canvasData.top) / height);\n } else if (isPlainObject(pivot) && isNumber(pivot.x) && isNumber(pivot.y)) {\n canvasData.left -= (newWidth - width) * ((pivot.x - canvasData.left) / width);\n canvasData.top -= (newHeight - height) * ((pivot.y - canvasData.top) / height);\n } else {\n // Zoom from the center of the canvas\n canvasData.left -= (newWidth - width) / 2;\n canvasData.top -= (newHeight - height) / 2;\n }\n\n canvasData.width = newWidth;\n canvasData.height = newHeight;\n this.renderCanvas(true);\n }\n\n return this;\n },\n\n /**\n * Rotate the canvas with a relative degree\n * @param {number} degree - The rotate degree.\n * @returns {Cropper} this\n */\n rotate: function rotate(degree) {\n return this.rotateTo((this.imageData.rotate || 0) + Number(degree));\n },\n\n /**\n * Rotate the canvas to an absolute degree\n * @param {number} degree - The rotate degree.\n * @returns {Cropper} this\n */\n rotateTo: function rotateTo(degree) {\n degree = Number(degree);\n\n if (isNumber(degree) && this.ready && !this.disabled && this.options.rotatable) {\n this.imageData.rotate = degree % 360;\n this.renderCanvas(true, true);\n }\n\n return this;\n },\n\n /**\n * Scale the image on the x-axis.\n * @param {number} scaleX - The scale ratio on the x-axis.\n * @returns {Cropper} this\n */\n scaleX: function scaleX(_scaleX) {\n var scaleY = this.imageData.scaleY;\n return this.scale(_scaleX, isNumber(scaleY) ? scaleY : 1);\n },\n\n /**\n * Scale the image on the y-axis.\n * @param {number} scaleY - The scale ratio on the y-axis.\n * @returns {Cropper} this\n */\n scaleY: function scaleY(_scaleY) {\n var scaleX = this.imageData.scaleX;\n return this.scale(isNumber(scaleX) ? scaleX : 1, _scaleY);\n },\n\n /**\n * Scale the image\n * @param {number} scaleX - The scale ratio on the x-axis.\n * @param {number} [scaleY=scaleX] - The scale ratio on the y-axis.\n * @returns {Cropper} this\n */\n scale: function scale(scaleX) {\n var scaleY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scaleX;\n var imageData = this.imageData;\n var transformed = false;\n scaleX = Number(scaleX);\n scaleY = Number(scaleY);\n\n if (this.ready && !this.disabled && this.options.scalable) {\n if (isNumber(scaleX)) {\n imageData.scaleX = scaleX;\n transformed = true;\n }\n\n if (isNumber(scaleY)) {\n imageData.scaleY = scaleY;\n transformed = true;\n }\n\n if (transformed) {\n this.renderCanvas(true, true);\n }\n }\n\n return this;\n },\n\n /**\n * Get the cropped area position and size data (base on the original image)\n * @param {boolean} [rounded=false] - Indicate if round the data values or not.\n * @returns {Object} The result cropped data.\n */\n getData: function getData() {\n var rounded = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n var options = this.options,\n imageData = this.imageData,\n canvasData = this.canvasData,\n cropBoxData = this.cropBoxData;\n var data;\n\n if (this.ready && this.cropped) {\n data = {\n x: cropBoxData.left - canvasData.left,\n y: cropBoxData.top - canvasData.top,\n width: cropBoxData.width,\n height: cropBoxData.height\n };\n var ratio = imageData.width / imageData.naturalWidth;\n forEach(data, function (n, i) {\n data[i] = n / ratio;\n });\n\n if (rounded) {\n // In case rounding off leads to extra 1px in right or bottom border\n // we should round the top-left corner and the dimension (#343).\n var bottom = Math.round(data.y + data.height);\n var right = Math.round(data.x + data.width);\n data.x = Math.round(data.x);\n data.y = Math.round(data.y);\n data.width = right - data.x;\n data.height = bottom - data.y;\n }\n } else {\n data = {\n x: 0,\n y: 0,\n width: 0,\n height: 0\n };\n }\n\n if (options.rotatable) {\n data.rotate = imageData.rotate || 0;\n }\n\n if (options.scalable) {\n data.scaleX = imageData.scaleX || 1;\n data.scaleY = imageData.scaleY || 1;\n }\n\n return data;\n },\n\n /**\n * Set the cropped area position and size with new data\n * @param {Object} data - The new data.\n * @returns {Cropper} this\n */\n setData: function setData(data) {\n var options = this.options,\n imageData = this.imageData,\n canvasData = this.canvasData;\n var cropBoxData = {};\n\n if (this.ready && !this.disabled && isPlainObject(data)) {\n var transformed = false;\n\n if (options.rotatable) {\n if (isNumber(data.rotate) && data.rotate !== imageData.rotate) {\n imageData.rotate = data.rotate;\n transformed = true;\n }\n }\n\n if (options.scalable) {\n if (isNumber(data.scaleX) && data.scaleX !== imageData.scaleX) {\n imageData.scaleX = data.scaleX;\n transformed = true;\n }\n\n if (isNumber(data.scaleY) && data.scaleY !== imageData.scaleY) {\n imageData.scaleY = data.scaleY;\n transformed = true;\n }\n }\n\n if (transformed) {\n this.renderCanvas(true, true);\n }\n\n var ratio = imageData.width / imageData.naturalWidth;\n\n if (isNumber(data.x)) {\n cropBoxData.left = data.x * ratio + canvasData.left;\n }\n\n if (isNumber(data.y)) {\n cropBoxData.top = data.y * ratio + canvasData.top;\n }\n\n if (isNumber(data.width)) {\n cropBoxData.width = data.width * ratio;\n }\n\n if (isNumber(data.height)) {\n cropBoxData.height = data.height * ratio;\n }\n\n this.setCropBoxData(cropBoxData);\n }\n\n return this;\n },\n\n /**\n * Get the container size data.\n * @returns {Object} The result container data.\n */\n getContainerData: function getContainerData() {\n return this.ready ? assign({}, this.containerData) : {};\n },\n\n /**\n * Get the image position and size data.\n * @returns {Object} The result image data.\n */\n getImageData: function getImageData() {\n return this.sized ? assign({}, this.imageData) : {};\n },\n\n /**\n * Get the canvas position and size data.\n * @returns {Object} The result canvas data.\n */\n getCanvasData: function getCanvasData() {\n var canvasData = this.canvasData;\n var data = {};\n\n if (this.ready) {\n forEach(['left', 'top', 'width', 'height', 'naturalWidth', 'naturalHeight'], function (n) {\n data[n] = canvasData[n];\n });\n }\n\n return data;\n },\n\n /**\n * Set the canvas position and size with new data.\n * @param {Object} data - The new canvas data.\n * @returns {Cropper} this\n */\n setCanvasData: function setCanvasData(data) {\n var canvasData = this.canvasData;\n var aspectRatio = canvasData.aspectRatio;\n\n if (this.ready && !this.disabled && isPlainObject(data)) {\n if (isNumber(data.left)) {\n canvasData.left = data.left;\n }\n\n if (isNumber(data.top)) {\n canvasData.top = data.top;\n }\n\n if (isNumber(data.width)) {\n canvasData.width = data.width;\n canvasData.height = data.width / aspectRatio;\n } else if (isNumber(data.height)) {\n canvasData.height = data.height;\n canvasData.width = data.height * aspectRatio;\n }\n\n this.renderCanvas(true);\n }\n\n return this;\n },\n\n /**\n * Get the crop box position and size data.\n * @returns {Object} The result crop box data.\n */\n getCropBoxData: function getCropBoxData() {\n var cropBoxData = this.cropBoxData;\n var data;\n\n if (this.ready && this.cropped) {\n data = {\n left: cropBoxData.left,\n top: cropBoxData.top,\n width: cropBoxData.width,\n height: cropBoxData.height\n };\n }\n\n return data || {};\n },\n\n /**\n * Set the crop box position and size with new data.\n * @param {Object} data - The new crop box data.\n * @returns {Cropper} this\n */\n setCropBoxData: function setCropBoxData(data) {\n var cropBoxData = this.cropBoxData;\n var aspectRatio = this.options.aspectRatio;\n var widthChanged;\n var heightChanged;\n\n if (this.ready && this.cropped && !this.disabled && isPlainObject(data)) {\n if (isNumber(data.left)) {\n cropBoxData.left = data.left;\n }\n\n if (isNumber(data.top)) {\n cropBoxData.top = data.top;\n }\n\n if (isNumber(data.width) && data.width !== cropBoxData.width) {\n widthChanged = true;\n cropBoxData.width = data.width;\n }\n\n if (isNumber(data.height) && data.height !== cropBoxData.height) {\n heightChanged = true;\n cropBoxData.height = data.height;\n }\n\n if (aspectRatio) {\n if (widthChanged) {\n cropBoxData.height = cropBoxData.width / aspectRatio;\n } else if (heightChanged) {\n cropBoxData.width = cropBoxData.height * aspectRatio;\n }\n }\n\n this.renderCropBox();\n }\n\n return this;\n },\n\n /**\n * Get a canvas drawn the cropped image.\n * @param {Object} [options={}] - The config options.\n * @returns {HTMLCanvasElement} - The result canvas.\n */\n getCroppedCanvas: function getCroppedCanvas() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n if (!this.ready || !window.HTMLCanvasElement) {\n return null;\n }\n\n var canvasData = this.canvasData;\n var source = getSourceCanvas(this.image, this.imageData, canvasData, options); // Returns the source canvas if it is not cropped.\n\n if (!this.cropped) {\n return source;\n }\n\n var _this$getData = this.getData(),\n initialX = _this$getData.x,\n initialY = _this$getData.y,\n initialWidth = _this$getData.width,\n initialHeight = _this$getData.height;\n\n var ratio = source.width / Math.floor(canvasData.naturalWidth);\n\n if (ratio !== 1) {\n initialX *= ratio;\n initialY *= ratio;\n initialWidth *= ratio;\n initialHeight *= ratio;\n }\n\n var aspectRatio = initialWidth / initialHeight;\n var maxSizes = getAdjustedSizes({\n aspectRatio: aspectRatio,\n width: options.maxWidth || Infinity,\n height: options.maxHeight || Infinity\n });\n var minSizes = getAdjustedSizes({\n aspectRatio: aspectRatio,\n width: options.minWidth || 0,\n height: options.minHeight || 0\n }, 'cover');\n\n var _getAdjustedSizes = getAdjustedSizes({\n aspectRatio: aspectRatio,\n width: options.width || (ratio !== 1 ? source.width : initialWidth),\n height: options.height || (ratio !== 1 ? source.height : initialHeight)\n }),\n width = _getAdjustedSizes.width,\n height = _getAdjustedSizes.height;\n\n width = Math.min(maxSizes.width, Math.max(minSizes.width, width));\n height = Math.min(maxSizes.height, Math.max(minSizes.height, height));\n var canvas = document.createElement('canvas');\n var context = canvas.getContext('2d');\n canvas.width = normalizeDecimalNumber(width);\n canvas.height = normalizeDecimalNumber(height);\n context.fillStyle = options.fillColor || 'transparent';\n context.fillRect(0, 0, width, height);\n var _options$imageSmoothi = options.imageSmoothingEnabled,\n imageSmoothingEnabled = _options$imageSmoothi === void 0 ? true : _options$imageSmoothi,\n imageSmoothingQuality = options.imageSmoothingQuality;\n context.imageSmoothingEnabled = imageSmoothingEnabled;\n\n if (imageSmoothingQuality) {\n context.imageSmoothingQuality = imageSmoothingQuality;\n } // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage\n\n\n var sourceWidth = source.width;\n var sourceHeight = source.height; // Source canvas parameters\n\n var srcX = initialX;\n var srcY = initialY;\n var srcWidth;\n var srcHeight; // Destination canvas parameters\n\n var dstX;\n var dstY;\n var dstWidth;\n var dstHeight;\n\n if (srcX <= -initialWidth || srcX > sourceWidth) {\n srcX = 0;\n srcWidth = 0;\n dstX = 0;\n dstWidth = 0;\n } else if (srcX <= 0) {\n dstX = -srcX;\n srcX = 0;\n srcWidth = Math.min(sourceWidth, initialWidth + srcX);\n dstWidth = srcWidth;\n } else if (srcX <= sourceWidth) {\n dstX = 0;\n srcWidth = Math.min(initialWidth, sourceWidth - srcX);\n dstWidth = srcWidth;\n }\n\n if (srcWidth <= 0 || srcY <= -initialHeight || srcY > sourceHeight) {\n srcY = 0;\n srcHeight = 0;\n dstY = 0;\n dstHeight = 0;\n } else if (srcY <= 0) {\n dstY = -srcY;\n srcY = 0;\n srcHeight = Math.min(sourceHeight, initialHeight + srcY);\n dstHeight = srcHeight;\n } else if (srcY <= sourceHeight) {\n dstY = 0;\n srcHeight = Math.min(initialHeight, sourceHeight - srcY);\n dstHeight = srcHeight;\n }\n\n var params = [srcX, srcY, srcWidth, srcHeight]; // Avoid \"IndexSizeError\"\n\n if (dstWidth > 0 && dstHeight > 0) {\n var scale = width / initialWidth;\n params.push(dstX * scale, dstY * scale, dstWidth * scale, dstHeight * scale);\n } // All the numerical parameters should be integer for `drawImage`\n // https://github.com/fengyuanchen/cropper/issues/476\n\n\n context.drawImage.apply(context, [source].concat(_toConsumableArray(params.map(function (param) {\n return Math.floor(normalizeDecimalNumber(param));\n }))));\n return canvas;\n },\n\n /**\n * Change the aspect ratio of the crop box.\n * @param {number} aspectRatio - The new aspect ratio.\n * @returns {Cropper} this\n */\n setAspectRatio: function setAspectRatio(aspectRatio) {\n var options = this.options;\n\n if (!this.disabled && !isUndefined(aspectRatio)) {\n // 0 -> NaN\n options.aspectRatio = Math.max(0, aspectRatio) || NaN;\n\n if (this.ready) {\n this.initCropBox();\n\n if (this.cropped) {\n this.renderCropBox();\n }\n }\n }\n\n return this;\n },\n\n /**\n * Change the drag mode.\n * @param {string} mode - The new drag mode.\n * @returns {Cropper} this\n */\n setDragMode: function setDragMode(mode) {\n var options = this.options,\n dragBox = this.dragBox,\n face = this.face;\n\n if (this.ready && !this.disabled) {\n var croppable = mode === DRAG_MODE_CROP;\n var movable = options.movable && mode === DRAG_MODE_MOVE;\n mode = croppable || movable ? mode : DRAG_MODE_NONE;\n options.dragMode = mode;\n setData(dragBox, DATA_ACTION, mode);\n toggleClass(dragBox, CLASS_CROP, croppable);\n toggleClass(dragBox, CLASS_MOVE, movable);\n\n if (!options.cropBoxMovable) {\n // Sync drag mode to crop box when it is not movable\n setData(face, DATA_ACTION, mode);\n toggleClass(face, CLASS_CROP, croppable);\n toggleClass(face, CLASS_MOVE, movable);\n }\n }\n\n return this;\n }\n };\n\n var AnotherCropper = WINDOW.Cropper;\n\n var Cropper =\n /*#__PURE__*/\n function () {\n /**\n * Create a new Cropper.\n * @param {Element} element - The target element for cropping.\n * @param {Object} [options={}] - The configuration options.\n */\n function Cropper(element) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n _classCallCheck(this, Cropper);\n\n if (!element || !REGEXP_TAG_NAME.test(element.tagName)) {\n throw new Error('The first argument is required and must be an <img> or <canvas> element.');\n }\n\n this.element = element;\n this.options = assign({}, DEFAULTS, isPlainObject(options) && options);\n this.cropped = false;\n this.disabled = false;\n this.pointers = {};\n this.ready = false;\n this.reloading = false;\n this.replaced = false;\n this.sized = false;\n this.sizing = false;\n this.init();\n }\n\n _createClass(Cropper, [{\n key: \"init\",\n value: function init() {\n var element = this.element;\n var tagName = element.tagName.toLowerCase();\n var url;\n\n if (element[NAMESPACE]) {\n return;\n }\n\n element[NAMESPACE] = this;\n\n if (tagName === 'img') {\n this.isImg = true; // e.g.: \"img/picture.jpg\"\n\n url = element.getAttribute('src') || '';\n this.originalUrl = url; // Stop when it's a blank image\n\n if (!url) {\n return;\n } // e.g.: \"http://example.com/img/picture.jpg\"\n\n\n url = element.src;\n } else if (tagName === 'canvas' && window.HTMLCanvasElement) {\n url = element.toDataURL();\n }\n\n this.load(url);\n }\n }, {\n key: \"load\",\n value: function load(url) {\n var _this = this;\n\n if (!url) {\n return;\n }\n\n this.url = url;\n this.imageData = {};\n var element = this.element,\n options = this.options;\n\n if (!options.rotatable && !options.scalable) {\n options.checkOrientation = false;\n } // Only IE10+ supports Typed Arrays\n\n\n if (!options.checkOrientation || !window.ArrayBuffer) {\n this.clone();\n return;\n } // Detect the mime type of the image directly if it is a Data URL\n\n\n if (REGEXP_DATA_URL.test(url)) {\n // Read ArrayBuffer from Data URL of JPEG images directly for better performance\n if (REGEXP_DATA_URL_JPEG.test(url)) {\n this.read(dataURLToArrayBuffer(url));\n } else {\n // Only a JPEG image may contains Exif Orientation information,\n // the rest types of Data URLs are not necessary to check orientation at all.\n this.clone();\n }\n\n return;\n } // 1. Detect the mime type of the image by a XMLHttpRequest.\n // 2. Load the image as ArrayBuffer for reading orientation if its a JPEG image.\n\n\n var xhr = new XMLHttpRequest();\n var clone = this.clone.bind(this);\n this.reloading = true;\n this.xhr = xhr; // 1. Cross origin requests are only supported for protocol schemes:\n // http, https, data, chrome, chrome-extension.\n // 2. Access to XMLHttpRequest from a Data URL will be blocked by CORS policy\n // in some browsers as IE11 and Safari.\n\n xhr.onabort = clone;\n xhr.onerror = clone;\n xhr.ontimeout = clone;\n\n xhr.onprogress = function () {\n // Abort the request directly if it not a JPEG image for better performance\n if (xhr.getResponseHeader('content-type') !== MIME_TYPE_JPEG) {\n xhr.abort();\n }\n };\n\n xhr.onload = function () {\n _this.read(xhr.response);\n };\n\n xhr.onloadend = function () {\n _this.reloading = false;\n _this.xhr = null;\n }; // Bust cache when there is a \"crossOrigin\" property to avoid browser cache error\n\n\n if (options.checkCrossOrigin && isCrossOriginURL(url) && element.crossOrigin) {\n url = addTimestamp(url);\n }\n\n xhr.open('GET', url);\n xhr.responseType = 'arraybuffer';\n xhr.withCredentials = element.crossOrigin === 'use-credentials';\n xhr.send();\n }\n }, {\n key: \"read\",\n value: function read(arrayBuffer) {\n var options = this.options,\n imageData = this.imageData; // Reset the orientation value to its default value 1\n // as some iOS browsers will render image with its orientation\n\n var orientation = resetAndGetOrientation(arrayBuffer);\n var rotate = 0;\n var scaleX = 1;\n var scaleY = 1;\n\n if (orientation > 1) {\n // Generate a new URL which has the default orientation value\n this.url = arrayBufferToDataURL(arrayBuffer, MIME_TYPE_JPEG);\n\n var _parseOrientation = parseOrientation(orientation);\n\n rotate = _parseOrientation.rotate;\n scaleX = _parseOrientation.scaleX;\n scaleY = _parseOrientation.scaleY;\n }\n\n if (options.rotatable) {\n imageData.rotate = rotate;\n }\n\n if (options.scalable) {\n imageData.scaleX = scaleX;\n imageData.scaleY = scaleY;\n }\n\n this.clone();\n }\n }, {\n key: \"clone\",\n value: function clone() {\n var element = this.element,\n url = this.url;\n var crossOrigin = element.crossOrigin;\n var crossOriginUrl = url;\n\n if (this.options.checkCrossOrigin && isCrossOriginURL(url)) {\n if (!crossOrigin) {\n crossOrigin = 'anonymous';\n } // Bust cache when there is not a \"crossOrigin\" property (#519)\n\n\n crossOriginUrl = addTimestamp(url);\n }\n\n this.crossOrigin = crossOrigin;\n this.crossOriginUrl = crossOriginUrl;\n var image = document.createElement('img');\n\n if (crossOrigin) {\n image.crossOrigin = crossOrigin;\n }\n\n image.src = crossOriginUrl || url;\n image.alt = element.alt || 'The image to crop';\n this.image = image;\n image.onload = this.start.bind(this);\n image.onerror = this.stop.bind(this);\n addClass(image, CLASS_HIDE);\n element.parentNode.insertBefore(image, element.nextSibling);\n }\n }, {\n key: \"start\",\n value: function start() {\n var _this2 = this;\n\n var image = this.image;\n image.onload = null;\n image.onerror = null;\n this.sizing = true; // Match all browsers that use WebKit as the layout engine in iOS devices,\n // such as Safari for iOS, Chrome for iOS, and in-app browsers.\n\n var isIOSWebKit = WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent);\n\n var done = function done(naturalWidth, naturalHeight) {\n assign(_this2.imageData, {\n naturalWidth: naturalWidth,\n naturalHeight: naturalHeight,\n aspectRatio: naturalWidth / naturalHeight\n });\n _this2.sizing = false;\n _this2.sized = true;\n\n _this2.build();\n }; // Most modern browsers (excepts iOS WebKit)\n\n\n if (image.naturalWidth && !isIOSWebKit) {\n done(image.naturalWidth, image.naturalHeight);\n return;\n }\n\n var sizingImage = document.createElement('img');\n var body = document.body || document.documentElement;\n this.sizingImage = sizingImage;\n\n sizingImage.onload = function () {\n done(sizingImage.width, sizingImage.height);\n\n if (!isIOSWebKit) {\n body.removeChild(sizingImage);\n }\n };\n\n sizingImage.src = image.src; // iOS WebKit will convert the image automatically\n // with its orientation once append it into DOM (#279)\n\n if (!isIOSWebKit) {\n sizingImage.style.cssText = 'left:0;' + 'max-height:none!important;' + 'max-width:none!important;' + 'min-height:0!important;' + 'min-width:0!important;' + 'opacity:0;' + 'position:absolute;' + 'top:0;' + 'z-index:-1;';\n body.appendChild(sizingImage);\n }\n }\n }, {\n key: \"stop\",\n value: function stop() {\n var image = this.image;\n image.onload = null;\n image.onerror = null;\n image.parentNode.removeChild(image);\n this.image = null;\n }\n }, {\n key: \"build\",\n value: function build() {\n if (!this.sized || this.ready) {\n return;\n }\n\n var element = this.element,\n options = this.options,\n image = this.image; // Create cropper elements\n\n var container = element.parentNode;\n var template = document.createElement('div');\n template.innerHTML = TEMPLATE;\n var cropper = template.querySelector(\".\".concat(NAMESPACE, \"-container\"));\n var canvas = cropper.querySelector(\".\".concat(NAMESPACE, \"-canvas\"));\n var dragBox = cropper.querySelector(\".\".concat(NAMESPACE, \"-drag-box\"));\n var cropBox = cropper.querySelector(\".\".concat(NAMESPACE, \"-crop-box\"));\n var face = cropBox.querySelector(\".\".concat(NAMESPACE, \"-face\"));\n this.container = container;\n this.cropper = cropper;\n this.canvas = canvas;\n this.dragBox = dragBox;\n this.cropBox = cropBox;\n this.viewBox = cropper.querySelector(\".\".concat(NAMESPACE, \"-view-box\"));\n this.face = face;\n canvas.appendChild(image); // Hide the original image\n\n addClass(element, CLASS_HIDDEN); // Inserts the cropper after to the current image\n\n container.insertBefore(cropper, element.nextSibling); // Show the image if is hidden\n\n if (!this.isImg) {\n removeClass(image, CLASS_HIDE);\n }\n\n this.initPreview();\n this.bind();\n options.initialAspectRatio = Math.max(0, options.initialAspectRatio) || NaN;\n options.aspectRatio = Math.max(0, options.aspectRatio) || NaN;\n options.viewMode = Math.max(0, Math.min(3, Math.round(options.viewMode))) || 0;\n addClass(cropBox, CLASS_HIDDEN);\n\n if (!options.guides) {\n addClass(cropBox.getElementsByClassName(\"\".concat(NAMESPACE, \"-dashed\")), CLASS_HIDDEN);\n }\n\n if (!options.center) {\n addClass(cropBox.getElementsByClassName(\"\".concat(NAMESPACE, \"-center\")), CLASS_HIDDEN);\n }\n\n if (options.background) {\n addClass(cropper, \"\".concat(NAMESPACE, \"-bg\"));\n }\n\n if (!options.highlight) {\n addClass(face, CLASS_INVISIBLE);\n }\n\n if (options.cropBoxMovable) {\n addClass(face, CLASS_MOVE);\n setData(face, DATA_ACTION, ACTION_ALL);\n }\n\n if (!options.cropBoxResizable) {\n addClass(cropBox.getElementsByClassName(\"\".concat(NAMESPACE, \"-line\")), CLASS_HIDDEN);\n addClass(cropBox.getElementsByClassName(\"\".concat(NAMESPACE, \"-point\")), CLASS_HIDDEN);\n }\n\n this.render();\n this.ready = true;\n this.setDragMode(options.dragMode);\n\n if (options.autoCrop) {\n this.crop();\n }\n\n this.setData(options.data);\n\n if (isFunction(options.ready)) {\n addListener(element, EVENT_READY, options.ready, {\n once: true\n });\n }\n\n dispatchEvent(element, EVENT_READY);\n }\n }, {\n key: \"unbuild\",\n value: function unbuild() {\n if (!this.ready) {\n return;\n }\n\n this.ready = false;\n this.unbind();\n this.resetPreview();\n this.cropper.parentNode.removeChild(this.cropper);\n removeClass(this.element, CLASS_HIDDEN);\n }\n }, {\n key: \"uncreate\",\n value: function uncreate() {\n if (this.ready) {\n this.unbuild();\n this.ready = false;\n this.cropped = false;\n } else if (this.sizing) {\n this.sizingImage.onload = null;\n this.sizing = false;\n this.sized = false;\n } else if (this.reloading) {\n this.xhr.onabort = null;\n this.xhr.abort();\n } else if (this.image) {\n this.stop();\n }\n }\n /**\n * Get the no conflict cropper class.\n * @returns {Cropper} The cropper class.\n */\n\n }], [{\n key: \"noConflict\",\n value: function noConflict() {\n window.Cropper = AnotherCropper;\n return Cropper;\n }\n /**\n * Change the default options.\n * @param {Object} options - The new default options.\n */\n\n }, {\n key: \"setDefaults\",\n value: function setDefaults(options) {\n assign(DEFAULTS, isPlainObject(options) && options);\n }\n }]);\n\n return Cropper;\n }();\n\n assign(Cropper.prototype, render, preview, events, handlers, change, methods);\n\n return Cropper;\n\n}));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2Nyb3BwZXJqcy9kaXN0L2Nyb3BwZXIuanMuanMiLCJzb3VyY2VzIjpbImZpbGU6Ly9DOi9DbGlja1ZpZXcgUHJvamVjdHMvQGNsaWNrdmlldy9ub2RlX21vZHVsZXMvY3JvcHBlcmpzL2Rpc3QvY3JvcHBlci5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIENyb3BwZXIuanMgdjEuNS42XG4gKiBodHRwczovL2Zlbmd5dWFuY2hlbi5naXRodWIuaW8vY3JvcHBlcmpzXG4gKlxuICogQ29weXJpZ2h0IDIwMTUtcHJlc2VudCBDaGVuIEZlbmd5dWFuXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2VcbiAqXG4gKiBEYXRlOiAyMDE5LTEwLTA0VDA0OjMzOjQ4LjM3MlpcbiAqL1xuXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShmYWN0b3J5KSA6XG4gIChnbG9iYWwgPSBnbG9iYWwgfHwgc2VsZiwgZ2xvYmFsLkNyb3BwZXIgPSBmYWN0b3J5KCkpO1xufSh0aGlzLCBmdW5jdGlvbiAoKSB7ICd1c2Ugc3RyaWN0JztcblxuICBmdW5jdGlvbiBfdHlwZW9mKG9iaikge1xuICAgIGlmICh0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIikge1xuICAgICAgX3R5cGVvZiA9IGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBfdHlwZW9mID0gZnVuY3Rpb24gKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIF90eXBlb2Yob2JqKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHtcbiAgICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTtcbiAgICAgIGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTtcbiAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTtcbiAgICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykge1xuICAgIGlmIChwcm90b1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpO1xuICAgIGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgICByZXR1cm4gQ29uc3RydWN0b3I7XG4gIH1cblxuICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydHkob2JqLCBrZXksIHZhbHVlKSB7XG4gICAgaWYgKGtleSBpbiBvYmopIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwge1xuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWVcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBvYmpba2V5XSA9IHZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICBmdW5jdGlvbiBvd25LZXlzKG9iamVjdCwgZW51bWVyYWJsZU9ubHkpIHtcbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iamVjdCk7XG5cbiAgICBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scykge1xuICAgICAgdmFyIHN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iamVjdCk7XG4gICAgICBpZiAoZW51bWVyYWJsZU9ubHkpIHN5bWJvbHMgPSBzeW1ib2xzLmZpbHRlcihmdW5jdGlvbiAoc3ltKSB7XG4gICAgICAgIHJldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgc3ltKS5lbnVtZXJhYmxlO1xuICAgICAgfSk7XG4gICAgICBrZXlzLnB1c2guYXBwbHkoa2V5cywgc3ltYm9scyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGtleXM7XG4gIH1cblxuICBmdW5jdGlvbiBfb2JqZWN0U3ByZWFkMih0YXJnZXQpIHtcbiAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXSAhPSBudWxsID8gYXJndW1lbnRzW2ldIDoge307XG5cbiAgICAgIGlmIChpICUgMikge1xuICAgICAgICBvd25LZXlzKHNvdXJjZSwgdHJ1ZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgX2RlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCBzb3VyY2Vba2V5XSk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycykge1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKHNvdXJjZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3duS2V5cyhzb3VyY2UpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihzb3VyY2UsIGtleSkpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGFyZ2V0O1xuICB9XG5cbiAgZnVuY3Rpb24gX3RvQ29uc3VtYWJsZUFycmF5KGFycikge1xuICAgIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5KGFycikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7XG4gIH1cblxuICBmdW5jdGlvbiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGFycjIgPSBuZXcgQXJyYXkoYXJyLmxlbmd0aCk7IGkgPCBhcnIubGVuZ3RoOyBpKyspIGFycjJbaV0gPSBhcnJbaV07XG5cbiAgICAgIHJldHVybiBhcnIyO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikge1xuICAgIGlmIChTeW1ib2wuaXRlcmF0b3IgaW4gT2JqZWN0KGl0ZXIpIHx8IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpdGVyKSA9PT0gXCJbb2JqZWN0IEFyZ3VtZW50c11cIikgcmV0dXJuIEFycmF5LmZyb20oaXRlcik7XG4gIH1cblxuICBmdW5jdGlvbiBfbm9uSXRlcmFibGVTcHJlYWQoKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXR0ZW1wdCB0byBzcHJlYWQgbm9uLWl0ZXJhYmxlIGluc3RhbmNlXCIpO1xuICB9XG5cbiAgdmFyIElTX0JST1dTRVIgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygd2luZG93LmRvY3VtZW50ICE9PSAndW5kZWZpbmVkJztcbiAgdmFyIFdJTkRPVyA9IElTX0JST1dTRVIgPyB3aW5kb3cgOiB7fTtcbiAgdmFyIElTX1RPVUNIX0RFVklDRSA9IElTX0JST1dTRVIgPyAnb250b3VjaHN0YXJ0JyBpbiBXSU5ET1cuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IDogZmFsc2U7XG4gIHZhciBIQVNfUE9JTlRFUl9FVkVOVCA9IElTX0JST1dTRVIgPyAnUG9pbnRlckV2ZW50JyBpbiBXSU5ET1cgOiBmYWxzZTtcbiAgdmFyIE5BTUVTUEFDRSA9ICdjcm9wcGVyJzsgLy8gQWN0aW9uc1xuXG4gIHZhciBBQ1RJT05fQUxMID0gJ2FsbCc7XG4gIHZhciBBQ1RJT05fQ1JPUCA9ICdjcm9wJztcbiAgdmFyIEFDVElPTl9NT1ZFID0gJ21vdmUnO1xuICB2YXIgQUNUSU9OX1pPT00gPSAnem9vbSc7XG4gIHZhciBBQ1RJT05fRUFTVCA9ICdlJztcbiAgdmFyIEFDVElPTl9XRVNUID0gJ3cnO1xuICB2YXIgQUNUSU9OX1NPVVRIID0gJ3MnO1xuICB2YXIgQUNUSU9OX05PUlRIID0gJ24nO1xuICB2YXIgQUNUSU9OX05PUlRIX0VBU1QgPSAnbmUnO1xuICB2YXIgQUNUSU9OX05PUlRIX1dFU1QgPSAnbncnO1xuICB2YXIgQUNUSU9OX1NPVVRIX0VBU1QgPSAnc2UnO1xuICB2YXIgQUNUSU9OX1NPVVRIX1dFU1QgPSAnc3cnOyAvLyBDbGFzc2VzXG5cbiAgdmFyIENMQVNTX0NST1AgPSBcIlwiLmNvbmNhdChOQU1FU1BBQ0UsIFwiLWNyb3BcIik7XG4gIHZhciBDTEFTU19ESVNBQkxFRCA9IFwiXCIuY29uY2F0KE5BTUVTUEFDRSwgXCItZGlzYWJsZWRcIik7XG4gIHZhciBDTEFTU19ISURERU4gPSBcIlwiLmNvbmNhdChOQU1FU1BBQ0UsIFwiLWhpZGRlblwiKTtcbiAgdmFyIENMQVNTX0hJREUgPSBcIlwiLmNvbmNhdChOQU1FU1BBQ0UsIFwiLWhpZGVcIik7XG4gIHZhciBDTEFTU19JTlZJU0lCTEUgPSBcIlwiLmNvbmNhdChOQU1FU1BBQ0UsIFwiLWludmlzaWJsZVwiKTtcbiAgdmFyIENMQVNTX01PREFMID0gXCJcIi5jb25jYXQoTkFNRVNQQUNFLCBcIi1tb2RhbFwiKTtcbiAgdmFyIENMQVNTX01PVkUgPSBcIlwiLmNvbmNhdChOQU1FU1BBQ0UsIFwiLW1vdmVcIik7IC8vIERhdGEga2V5c1xuXG4gIHZhciBEQVRBX0FDVElPTiA9IFwiXCIuY29uY2F0KE5BTUVTUEFDRSwgXCJBY3Rpb25cIik7XG4gIHZhciBEQVRBX1BSRVZJRVcgPSBcIlwiLmNvbmNhdChOQU1FU1BBQ0UsIFwiUHJldmlld1wiKTsgLy8gRHJhZyBtb2Rlc1xuXG4gIHZhciBEUkFHX01PREVfQ1JPUCA9ICdjcm9wJztcbiAgdmFyIERSQUdfTU9ERV9NT1ZFID0gJ21vdmUnO1xuICB2YXIgRFJBR19NT0RFX05PTkUgPSAnbm9uZSc7IC8vIEV2ZW50c1xuXG4gIHZhciBFVkVOVF9DUk9QID0gJ2Nyb3AnO1xuICB2YXIgRVZFTlRfQ1JPUF9FTkQgPSAnY3JvcGVuZCc7XG4gIHZhciBFVkVOVF9DUk9QX01PVkUgPSAnY3JvcG1vdmUnO1xuICB2YXIgRVZFTlRfQ1JPUF9TVEFSVCA9ICdjcm9wc3RhcnQnO1xuICB2YXIgRVZFTlRfREJMQ0xJQ0sgPSAnZGJsY2xpY2snO1xuICB2YXIgRVZFTlRfVE9VQ0hfU1RBUlQgPSBJU19UT1VDSF9ERVZJQ0UgPyAndG91Y2hzdGFydCcgOiAnbW91c2Vkb3duJztcbiAgdmFyIEVWRU5UX1RPVUNIX01PVkUgPSBJU19UT1VDSF9ERVZJQ0UgPyAndG91Y2htb3ZlJyA6ICdtb3VzZW1vdmUnO1xuICB2YXIgRVZFTlRfVE9VQ0hfRU5EID0gSVNfVE9VQ0hfREVWSUNFID8gJ3RvdWNoZW5kIHRvdWNoY2FuY2VsJyA6ICdtb3VzZXVwJztcbiAgdmFyIEVWRU5UX1BPSU5URVJfRE9XTiA9IEhBU19QT0lOVEVSX0VWRU5UID8gJ3BvaW50ZXJkb3duJyA6IEVWRU5UX1RPVUNIX1NUQVJUO1xuICB2YXIgRVZFTlRfUE9JTlRFUl9NT1ZFID0gSEFTX1BPSU5URVJfRVZFTlQgPyAncG9pbnRlcm1vdmUnIDogRVZFTlRfVE9VQ0hfTU9WRTtcbiAgdmFyIEVWRU5UX1BPSU5URVJfVVAgPSBIQVNfUE9JTlRFUl9FVkVOVCA/ICdwb2ludGVydXAgcG9pbnRlcmNhbmNlbCcgOiBFVkVOVF9UT1VDSF9FTkQ7XG4gIHZhciBFVkVOVF9SRUFEWSA9ICdyZWFkeSc7XG4gIHZhciBFVkVOVF9SRVNJWkUgPSAncmVzaXplJztcbiAgdmFyIEVWRU5UX1dIRUVMID0gJ3doZWVsJztcbiAgdmFyIEVWRU5UX1pPT00gPSAnem9vbSc7IC8vIE1pbWUgdHlwZXNcblxuICB2YXIgTUlNRV9UWVBFX0pQRUcgPSAnaW1hZ2UvanBlZyc7IC8vIFJlZ0V4cHNcblxuICB2YXIgUkVHRVhQX0FDVElPTlMgPSAvXmV8d3xzfG58c2V8c3d8bmV8bnd8YWxsfGNyb3B8bW92ZXx6b29tJC87XG4gIHZhciBSRUdFWFBfREFUQV9VUkwgPSAvXmRhdGE6LztcbiAgdmFyIFJFR0VYUF9EQVRBX1VSTF9KUEVHID0gL15kYXRhOmltYWdlXFwvanBlZztiYXNlNjQsLztcbiAgdmFyIFJFR0VYUF9UQUdfTkFNRSA9IC9eaW1nfGNhbnZhcyQvaTsgLy8gTWlzY1xuICAvLyBJbnNwaXJlZCBieSB0aGUgZGVmYXVsdCB3aWR0aCBhbmQgaGVpZ2h0IG9mIGEgY2FudmFzIGVsZW1lbnQuXG5cbiAgdmFyIE1JTl9DT05UQUlORVJfV0lEVEggPSAyMDA7XG4gIHZhciBNSU5fQ09OVEFJTkVSX0hFSUdIVCA9IDEwMDtcblxuICB2YXIgREVGQVVMVFMgPSB7XG4gICAgLy8gRGVmaW5lIHRoZSB2aWV3IG1vZGUgb2YgdGhlIGNyb3BwZXJcbiAgICB2aWV3TW9kZTogMCxcbiAgICAvLyAwLCAxLCAyLCAzXG4gICAgLy8gRGVmaW5lIHRoZSBkcmFnZ2luZyBtb2RlIG9mIHRoZSBjcm9wcGVyXG4gICAgZHJhZ01vZGU6IERSQUdfTU9ERV9DUk9QLFxuICAgIC8vICdjcm9wJywgJ21vdmUnIG9yICdub25lJ1xuICAgIC8vIERlZmluZSB0aGUgaW5pdGlhbCBhc3BlY3QgcmF0aW8gb2YgdGhlIGNyb3AgYm94XG4gICAgaW5pdGlhbEFzcGVjdFJhdGlvOiBOYU4sXG4gICAgLy8gRGVmaW5lIHRoZSBhc3BlY3QgcmF0aW8gb2YgdGhlIGNyb3AgYm94XG4gICAgYXNwZWN0UmF0aW86IE5hTixcbiAgICAvLyBBbiBvYmplY3Qgd2l0aCB0aGUgcHJldmlvdXMgY3JvcHBpbmcgcmVzdWx0IGRhdGFcbiAgICBkYXRhOiBudWxsLFxuICAgIC8vIEEgc2VsZWN0b3IgZm9yIGFkZGluZyBleHRyYSBjb250YWluZXJzIHRvIHByZXZpZXdcbiAgICBwcmV2aWV3OiAnJyxcbiAgICAvLyBSZS1yZW5kZXIgdGhlIGNyb3BwZXIgd2hlbiByZXNpemUgdGhlIHdpbmRvd1xuICAgIHJlc3BvbnNpdmU6IHRydWUsXG4gICAgLy8gUmVzdG9yZSB0aGUgY3JvcHBlZCBhcmVhIGFmdGVyIHJlc2l6ZSB0aGUgd2luZG93XG4gICAgcmVzdG9yZTogdHJ1ZSxcbiAgICAvLyBDaGVjayBpZiB0aGUgY3VycmVudCBpbWFnZSBpcyBhIGNyb3NzLW9yaWdpbiBpbWFnZVxuICAgIGNoZWNrQ3Jvc3NPcmlnaW46IHRydWUsXG4gICAgLy8gQ2hlY2sgdGhlIGN1cnJlbnQgaW1hZ2UncyBFeGlmIE9yaWVudGF0aW9uIGluZm9ybWF0aW9uXG4gICAgY2hlY2tPcmllbnRhdGlvbjogdHJ1ZSxcbiAgICAvLyBTaG93IHRoZSBibGFjayBtb2RhbFxuICAgIG1vZGFsOiB0cnVlLFxuICAgIC8vIFNob3cgdGhlIGRhc2hlZCBsaW5lcyBmb3IgZ3VpZGluZ1xuICAgIGd1aWRlczogdHJ1ZSxcbiAgICAvLyBTaG93IHRoZSBjZW50ZXIgaW5kaWNhdG9yIGZvciBndWlkaW5nXG4gICAgY2VudGVyOiB0cnVlLFxuICAgIC8vIFNob3cgdGhlIHdoaXRlIG1vZGFsIHRvIGhpZ2hsaWdodCB0aGUgY3JvcCBib3hcbiAgICBoaWdobGlnaHQ6IHRydWUsXG4gICAgLy8gU2hvdyB0aGUgZ3JpZCBiYWNrZ3JvdW5kXG4gICAgYmFja2dyb3VuZDogdHJ1ZSxcbiAgICAvLyBFbmFibGUgdG8gY3JvcCB0aGUgaW1hZ2UgYXV0b21hdGljYWxseSB3aGVuIGluaXRpYWxpemVcbiAgICBhdXRvQ3JvcDogdHJ1ZSxcbiAgICAvLyBEZWZpbmUgdGhlIHBlcmNlbnRhZ2Ugb2YgYXV0b21hdGljIGNyb3BwaW5nIGFyZWEgd2hlbiBpbml0aWFsaXplc1xuICAgIGF1dG9Dcm9wQXJlYTogMC44LFxuICAgIC8vIEVuYWJsZSB0byBtb3ZlIHRoZSBpbWFnZVxuICAgIG1vdmFibGU6IHRydWUsXG4gICAgLy8gRW5hYmxlIHRvIHJvdGF0ZSB0aGUgaW1hZ2VcbiAgICByb3RhdGFibGU6IHRydWUsXG4gICAgLy8gRW5hYmxlIHRvIHNjYWxlIHRoZSBpbWFnZVxuICAgIHNjYWxhYmxlOiB0cnVlLFxuICAgIC8vIEVuYWJsZSB0byB6b29tIHRoZSBpbWFnZVxuICAgIHpvb21hYmxlOiB0cnVlLFxuICAgIC8vIEVuYWJsZSB0byB6b29tIHRoZSBpbWFnZSBieSBkcmFnZ2luZyB0b3VjaFxuICAgIHpvb21PblRvdWNoOiB0cnVlLFxuICAgIC8vIEVuYWJsZSB0byB6b29tIHRoZSBpbWFnZSBieSB3aGVlbGluZyBtb3VzZVxuICAgIHpvb21PbldoZWVsOiB0cnVlLFxuICAgIC8vIERlZmluZSB6b29tIHJhdGlvIHdoZW4gem9vbSB0aGUgaW1hZ2UgYnkgd2hlZWxpbmcgbW91c2VcbiAgICB3aGVlbFpvb21SYXRpbzogMC4xLFxuICAgIC8vIEVuYWJsZSB0byBtb3ZlIHRoZSBjcm9wIGJveFxuICAgIGNyb3BCb3hNb3ZhYmxlOiB0cnVlLFxuICAgIC8vIEVuYWJsZSB0byByZXNpemUgdGhlIGNyb3AgYm94XG4gICAgY3JvcEJveFJlc2l6YWJsZTogdHJ1ZSxcbiAgICAvLyBUb2dnbGUgZHJhZyBtb2RlIGJldHdlZW4gXCJjcm9wXCIgYW5kIFwibW92ZVwiIHdoZW4gY2xpY2sgdHdpY2Ugb24gdGhlIGNyb3BwZXJcbiAgICB0b2dnbGVEcmFnTW9kZU9uRGJsY2xpY2s6IHRydWUsXG4gICAgLy8gU2l6ZSBsaW1pdGF0aW9uXG4gICAgbWluQ2FudmFzV2lkdGg6IDAsXG4gICAgbWluQ2FudmFzSGVpZ2h0OiAwLFxuICAgIG1pbkNyb3BCb3hXaWR0aDogMCxcbiAgICBtaW5Dcm9wQm94SGVpZ2h0OiAwLFxuICAgIG1pbkNvbnRhaW5lcldpZHRoOiAyMDAsXG4gICAgbWluQ29udGFpbmVySGVpZ2h0OiAxMDAsXG4gICAgLy8gU2hvcnRjdXRzIG9mIGV2ZW50c1xuICAgIHJlYWR5OiBudWxsLFxuICAgIGNyb3BzdGFydDogbnVsbCxcbiAgICBjcm9wbW92ZTogbnVsbCxcbiAgICBjcm9wZW5kOiBudWxsLFxuICAgIGNyb3A6IG51bGwsXG4gICAgem9vbTogbnVsbFxuICB9O1xuXG4gIHZhciBURU1QTEFURSA9ICc8ZGl2IGNsYXNzPVwiY3JvcHBlci1jb250YWluZXJcIiB0b3VjaC1hY3Rpb249XCJub25lXCI+JyArICc8ZGl2IGNsYXNzPVwiY3JvcHBlci13cmFwLWJveFwiPicgKyAnPGRpdiBjbGFzcz1cImNyb3BwZXItY2FudmFzXCI+PC9kaXY+JyArICc8L2Rpdj4nICsgJzxkaXYgY2xhc3M9XCJjcm9wcGVyLWRyYWctYm94XCI+PC9kaXY+JyArICc8ZGl2IGNsYXNzPVwiY3JvcHBlci1jcm9wLWJveFwiPicgKyAnPHNwYW4gY2xhc3M9XCJjcm9wcGVyLXZpZXctYm94XCI+PC9zcGFuPicgKyAnPHNwYW4gY2xhc3M9XCJjcm9wcGVyLWRhc2hlZCBkYXNoZWQtaFwiPjwvc3Bhbj4nICsgJzxzcGFuIGNsYXNzPVwiY3JvcHBlci1kYXNoZWQgZGFzaGVkLXZcIj48L3NwYW4+JyArICc8c3BhbiBjbGFzcz1cImNyb3BwZXItY2VudGVyXCI+PC9zcGFuPicgKyAnPHNwYW4gY2xhc3M9XCJjcm9wcGVyLWZhY2VcIj48L3NwYW4+JyArICc8c3BhbiBjbGFzcz1cImNyb3BwZXItbGluZSBsaW5lLWVcIiBkYXRhLWNyb3BwZXItYWN0aW9uPVwiZVwiPjwvc3Bhbj4nICsgJzxzcGFuIGNsYXNzPVwiY3JvcHBlci1saW5lIGxpbmUtblwiIGRhdGEtY3JvcHBlci1hY3Rpb249XCJuXCI+PC9zcGFuPicgKyAnPHNwYW4gY2xhc3M9XCJjcm9wcGVyLWxpbmUgbGluZS13XCIgZGF0YS1jcm9wcGVyLWFjdGlvbj1cIndcIj48L3NwYW4+JyArICc8c3BhbiBjbGFzcz1cImNyb3BwZXItbGluZSBsaW5lLXNcIiBkYXRhLWNyb3BwZXItYWN0aW9uPVwic1wiPjwvc3Bhbj4nICsgJzxzcGFuIGNsYXNzPVwiY3JvcHBlci1wb2ludCBwb2ludC1lXCIgZGF0YS1jcm9wcGVyLWFjdGlvbj1cImVcIj48L3NwYW4+JyArICc8c3BhbiBjbGFzcz1cImNyb3BwZXItcG9pbnQgcG9pbnQtblwiIGRhdGEtY3JvcHBlci1hY3Rpb249XCJuXCI+PC9zcGFuPicgKyAnPHNwYW4gY2xhc3M9XCJjcm9wcGVyLXBvaW50IHBvaW50LXdcIiBkYXRhLWNyb3BwZXItYWN0aW9uPVwid1wiPjwvc3Bhbj4nICsgJzxzcGFuIGNsYXNzPVwiY3JvcHBlci1wb2ludCBwb2ludC1zXCIgZGF0YS1jcm9wcGVyLWFjdGlvbj1cInNcIj48L3NwYW4+JyArICc8c3BhbiBjbGFzcz1cImNyb3BwZXItcG9pbnQgcG9pbnQtbmVcIiBkYXRhLWNyb3BwZXItYWN0aW9uPVwibmVcIj48L3NwYW4+JyArICc8c3BhbiBjbGFzcz1cImNyb3BwZXItcG9pbnQgcG9pbnQtbndcIiBkYXRhLWNyb3BwZXItYWN0aW9uPVwibndcIj48L3NwYW4+JyArICc8c3BhbiBjbGFzcz1cImNyb3BwZXItcG9pbnQgcG9pbnQtc3dcIiBkYXRhLWNyb3BwZXItYWN0aW9uPVwic3dcIj48L3NwYW4+JyArICc8c3BhbiBjbGFzcz1cImNyb3BwZXItcG9pbnQgcG9pbnQtc2VcIiBkYXRhLWNyb3BwZXItYWN0aW9uPVwic2VcIj48L3NwYW4+JyArICc8L2Rpdj4nICsgJzwvZGl2Pic7XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBnaXZlbiB2YWx1ZSBpcyBub3QgYSBudW1iZXIuXG4gICAqL1xuXG4gIHZhciBpc05hTiA9IE51bWJlci5pc05hTiB8fCBXSU5ET1cuaXNOYU47XG4gIC8qKlxuICAgKiBDaGVjayBpZiB0aGUgZ2l2ZW4gdmFsdWUgaXMgYSBudW1iZXIuXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gdmFsdWUgaXMgYSBudW1iZXIsIGVsc2UgYGZhbHNlYC5cbiAgICovXG5cbiAgZnVuY3Rpb24gaXNOdW1iZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiAhaXNOYU4odmFsdWUpO1xuICB9XG4gIC8qKlxuICAgKiBDaGVjayBpZiB0aGUgZ2l2ZW4gdmFsdWUgaXMgYSBwb3NpdGl2ZSBudW1iZXIuXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gdmFsdWUgaXMgYSBwb3NpdGl2ZSBudW1iZXIsIGVsc2UgYGZhbHNlYC5cbiAgICovXG5cbiAgdmFyIGlzUG9zaXRpdmVOdW1iZXIgPSBmdW5jdGlvbiBpc1Bvc2l0aXZlTnVtYmVyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID4gMCAmJiB2YWx1ZSA8IEluZmluaXR5O1xuICB9O1xuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlIGdpdmVuIHZhbHVlIGlzIHVuZGVmaW5lZC5cbiAgICogQHBhcmFtIHsqfSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiB2YWx1ZSBpcyB1bmRlZmluZWQsIGVsc2UgYGZhbHNlYC5cbiAgICovXG5cbiAgZnVuY3Rpb24gaXNVbmRlZmluZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbiAgfVxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlIGdpdmVuIHZhbHVlIGlzIGFuIG9iamVjdC5cbiAgICogQHBhcmFtIHsqfSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiB2YWx1ZSBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICovXG5cbiAgZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgICByZXR1cm4gX3R5cGVvZih2YWx1ZSkgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsO1xuICB9XG4gIHZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG4gIC8qKlxuICAgKiBDaGVjayBpZiB0aGUgZ2l2ZW4gdmFsdWUgaXMgYSBwbGFpbiBvYmplY3QuXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gdmFsdWUgaXMgYSBwbGFpbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICovXG5cbiAgZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2YWx1ZSkge1xuICAgIGlmICghaXNPYmplY3QodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHZhciBfY29uc3RydWN0b3IgPSB2YWx1ZS5jb25zdHJ1Y3RvcjtcbiAgICAgIHZhciBwcm90b3R5cGUgPSBfY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgcmV0dXJuIF9jb25zdHJ1Y3RvciAmJiBwcm90b3R5cGUgJiYgaGFzT3duUHJvcGVydHkuY2FsbChwcm90b3R5cGUsICdpc1Byb3RvdHlwZU9mJyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBnaXZlbiB2YWx1ZSBpcyBhIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0geyp9IHZhbHVlIC0gVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIHZhbHVlIGlzIGEgZnVuY3Rpb24sIGVsc2UgYGZhbHNlYC5cbiAgICovXG5cbiAgZnVuY3Rpb24gaXNGdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbic7XG4gIH1cbiAgdmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuICAvKipcbiAgICogQ29udmVydCBhcnJheS1saWtlIG9yIGl0ZXJhYmxlIG9iamVjdCB0byBhbiBhcnJheS5cbiAgICogQHBhcmFtIHsqfSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBuZXcgYXJyYXkuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIHRvQXJyYXkodmFsdWUpIHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbSA/IEFycmF5LmZyb20odmFsdWUpIDogc2xpY2UuY2FsbCh2YWx1ZSk7XG4gIH1cbiAgLyoqXG4gICAqIEl0ZXJhdGUgdGhlIGdpdmVuIGRhdGEuXG4gICAqIEBwYXJhbSB7Kn0gZGF0YSAtIFRoZSBkYXRhIHRvIGl0ZXJhdGUuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIHByb2Nlc3MgZnVuY3Rpb24gZm9yIGVhY2ggZWxlbWVudC5cbiAgICogQHJldHVybnMgeyp9IFRoZSBvcmlnaW5hbCBkYXRhLlxuICAgKi9cblxuICBmdW5jdGlvbiBmb3JFYWNoKGRhdGEsIGNhbGxiYWNrKSB7XG4gICAgaWYgKGRhdGEgJiYgaXNGdW5jdGlvbihjYWxsYmFjaykpIHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpIHx8IGlzTnVtYmVyKGRhdGEubGVuZ3RoKVxuICAgICAgLyogYXJyYXktbGlrZSAqL1xuICAgICAgKSB7XG4gICAgICAgICAgdG9BcnJheShkYXRhKS5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7XG4gICAgICAgICAgICBjYWxsYmFjay5jYWxsKGRhdGEsIHZhbHVlLCBrZXksIGRhdGEpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGRhdGEpKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGRhdGEpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgIGNhbGxiYWNrLmNhbGwoZGF0YSwgZGF0YVtrZXldLCBrZXksIGRhdGEpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuICAvKipcbiAgICogRXh0ZW5kIHRoZSBnaXZlbiBvYmplY3QuXG4gICAqIEBwYXJhbSB7Kn0gdGFyZ2V0IC0gVGhlIHRhcmdldCBvYmplY3QgdG8gZXh0ZW5kLlxuICAgKiBAcGFyYW0geyp9IGFyZ3MgLSBUaGUgcmVzdCBvYmplY3RzIGZvciBtZXJnaW5nIHRvIHRoZSB0YXJnZXQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZXh0ZW5kZWQgb2JqZWN0LlxuICAgKi9cblxuICB2YXIgYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBhc3NpZ24odGFyZ2V0KSB7XG4gICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5ID0gMTsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgYXJnc1tfa2V5IC0gMV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgfVxuXG4gICAgaWYgKGlzT2JqZWN0KHRhcmdldCkgJiYgYXJncy5sZW5ndGggPiAwKSB7XG4gICAgICBhcmdzLmZvckVhY2goZnVuY3Rpb24gKGFyZykge1xuICAgICAgICBpZiAoaXNPYmplY3QoYXJnKSkge1xuICAgICAgICAgIE9iamVjdC5rZXlzKGFyZykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICB0YXJnZXRba2V5XSA9IGFyZ1trZXldO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGFyZ2V0O1xuICB9O1xuICB2YXIgUkVHRVhQX0RFQ0lNQUxTID0gL1xcLlxcZCooPzowfDkpezEyfVxcZCokLztcbiAgLyoqXG4gICAqIE5vcm1hbGl6ZSBkZWNpbWFsIG51bWJlci5cbiAgICogQ2hlY2sgb3V0IHtAbGluayBodHRwOi8vMC4zMDAwMDAwMDAwMDAwMDAwNC5jb20vfVxuICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gbm9ybWFsaXplLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW3RpbWVzPTEwMDAwMDAwMDAwMF0gLSBUaGUgdGltZXMgZm9yIG5vcm1hbGl6aW5nLlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBub3JtYWxpemVkIG51bWJlci5cbiAgICovXG5cbiAgZnVuY3Rpb24gbm9ybWFsaXplRGVjaW1hbE51bWJlcih2YWx1ZSkge1xuICAgIHZhciB0aW1lcyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogMTAwMDAwMDAwMDAwO1xuICAgIHJldHVybiBSRUdFWFBfREVDSU1BTFMudGVzdCh2YWx1ZSkgPyBNYXRoLnJvdW5kKHZhbHVlICogdGltZXMpIC8gdGltZXMgOiB2YWx1ZTtcbiAgfVxuICB2YXIgUkVHRVhQX1NVRkZJWCA9IC9ed2lkdGh8aGVpZ2h0fGxlZnR8dG9wfG1hcmdpbkxlZnR8bWFyZ2luVG9wJC87XG4gIC8qKlxuICAgKiBBcHBseSBzdHlsZXMgdG8gdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudCAtIFRoZSB0YXJnZXQgZWxlbWVudC5cbiAgICogQHBhcmFtIHtPYmplY3R9IHN0eWxlcyAtIFRoZSBzdHlsZXMgZm9yIGFwcGx5aW5nLlxuICAgKi9cblxuICBmdW5jdGlvbiBzZXRTdHlsZShlbGVtZW50LCBzdHlsZXMpIHtcbiAgICB2YXIgc3R5bGUgPSBlbGVtZW50LnN0eWxlO1xuICAgIGZvckVhY2goc3R5bGVzLCBmdW5jdGlvbiAodmFsdWUsIHByb3BlcnR5KSB7XG4gICAgICBpZiAoUkVHRVhQX1NVRkZJWC50ZXN0KHByb3BlcnR5KSAmJiBpc051bWJlcih2YWx1ZSkpIHtcbiAgICAgICAgdmFsdWUgPSBcIlwiLmNvbmNhdCh2YWx1ZSwgXCJweFwiKTtcbiAgICAgIH1cblxuICAgICAgc3R5bGVbcHJvcGVydHldID0gdmFsdWU7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBnaXZlbiBlbGVtZW50IGhhcyBhIHNwZWNpYWwgY2xhc3MuXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudCAtIFRoZSBlbGVtZW50IHRvIGNoZWNrLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBUaGUgY2xhc3MgdG8gc2VhcmNoLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHNwZWNpYWwgY2xhc3Mgd2FzIGZvdW5kLlxuICAgKi9cblxuICBmdW5jdGlvbiBoYXNDbGFzcyhlbGVtZW50LCB2YWx1ZSkge1xuICAgIHJldHVybiBlbGVtZW50LmNsYXNzTGlzdCA/IGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKHZhbHVlKSA6IGVsZW1lbnQuY2xhc3NOYW1lLmluZGV4T2YodmFsdWUpID4gLTE7XG4gIH1cbiAgLyoqXG4gICAqIEFkZCBjbGFzc2VzIHRvIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnQgLSBUaGUgdGFyZ2V0IGVsZW1lbnQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSBjbGFzc2VzIHRvIGJlIGFkZGVkLlxuICAgKi9cblxuICBmdW5jdGlvbiBhZGRDbGFzcyhlbGVtZW50LCB2YWx1ZSkge1xuICAgIGlmICghdmFsdWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoaXNOdW1iZXIoZWxlbWVudC5sZW5ndGgpKSB7XG4gICAgICBmb3JFYWNoKGVsZW1lbnQsIGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgIGFkZENsYXNzKGVsZW0sIHZhbHVlKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChlbGVtZW50LmNsYXNzTGlzdCkge1xuICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKHZhbHVlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgY2xhc3NOYW1lID0gZWxlbWVudC5jbGFzc05hbWUudHJpbSgpO1xuXG4gICAgaWYgKCFjbGFzc05hbWUpIHtcbiAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gdmFsdWU7XG4gICAgfSBlbHNlIGlmIChjbGFzc05hbWUuaW5kZXhPZih2YWx1ZSkgPCAwKSB7XG4gICAgICBlbGVtZW50LmNsYXNzTmFtZSA9IFwiXCIuY29uY2F0KGNsYXNzTmFtZSwgXCIgXCIpLmNvbmNhdCh2YWx1ZSk7XG4gICAgfVxuICB9XG4gIC8qKlxuICAgKiBSZW1vdmUgY2xhc3NlcyBmcm9tIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnQgLSBUaGUgdGFyZ2V0IGVsZW1lbnQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSBjbGFzc2VzIHRvIGJlIHJlbW92ZWQuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIHJlbW92ZUNsYXNzKGVsZW1lbnQsIHZhbHVlKSB7XG4gICAgaWYgKCF2YWx1ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChpc051bWJlcihlbGVtZW50Lmxlbmd0aCkpIHtcbiAgICAgIGZvckVhY2goZWxlbWVudCwgZnVuY3Rpb24gKGVsZW0pIHtcbiAgICAgICAgcmVtb3ZlQ2xhc3MoZWxlbSwgdmFsdWUpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGVsZW1lbnQuY2xhc3NMaXN0KSB7XG4gICAgICBlbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUodmFsdWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChlbGVtZW50LmNsYXNzTmFtZS5pbmRleE9mKHZhbHVlKSA+PSAwKSB7XG4gICAgICBlbGVtZW50LmNsYXNzTmFtZSA9IGVsZW1lbnQuY2xhc3NOYW1lLnJlcGxhY2UodmFsdWUsICcnKTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIEFkZCBvciByZW1vdmUgY2xhc3NlcyBmcm9tIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnQgLSBUaGUgdGFyZ2V0IGVsZW1lbnQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSBjbGFzc2VzIHRvIGJlIHRvZ2dsZWQuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gYWRkZWQgLSBBZGQgb25seS5cbiAgICovXG5cbiAgZnVuY3Rpb24gdG9nZ2xlQ2xhc3MoZWxlbWVudCwgdmFsdWUsIGFkZGVkKSB7XG4gICAgaWYgKCF2YWx1ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChpc051bWJlcihlbGVtZW50Lmxlbmd0aCkpIHtcbiAgICAgIGZvckVhY2goZWxlbWVudCwgZnVuY3Rpb24gKGVsZW0pIHtcbiAgICAgICAgdG9nZ2xlQ2xhc3MoZWxlbSwgdmFsdWUsIGFkZGVkKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gSUUxMC0xMSBkb2Vzbid0IHN1cHBvcnQgdGhlIHNlY29uZCBwYXJhbWV0ZXIgb2YgYGNsYXNzTGlzdC50b2dnbGVgXG5cblxuICAgIGlmIChhZGRlZCkge1xuICAgICAgYWRkQ2xhc3MoZWxlbWVudCwgdmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZW1vdmVDbGFzcyhlbGVtZW50LCB2YWx1ZSk7XG4gICAgfVxuICB9XG4gIHZhciBSRUdFWFBfQ0FNRUxfQ0FTRSA9IC8oW2EtelxcZF0pKFtBLVpdKS9nO1xuICAvKipcbiAgICogVHJhbnNmb3JtIHRoZSBnaXZlbiBzdHJpbmcgZnJvbSBjYW1lbENhc2UgdG8ga2ViYWItY2FzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBUaGUgdmFsdWUgdG8gdHJhbnNmb3JtLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgdHJhbnNmb3JtZWQgdmFsdWUuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIHRvUGFyYW1DYXNlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJlcGxhY2UoUkVHRVhQX0NBTUVMX0NBU0UsICckMS0kMicpLnRvTG93ZXJDYXNlKCk7XG4gIH1cbiAgLyoqXG4gICAqIEdldCBkYXRhIGZyb20gdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudCAtIFRoZSB0YXJnZXQgZWxlbWVudC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgZGF0YSBrZXkgdG8gZ2V0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZGF0YSB2YWx1ZS5cbiAgICovXG5cbiAgZnVuY3Rpb24gZ2V0RGF0YShlbGVtZW50LCBuYW1lKSB7XG4gICAgaWYgKGlzT2JqZWN0KGVsZW1lbnRbbmFtZV0pKSB7XG4gICAgICByZXR1cm4gZWxlbWVudFtuYW1lXTtcbiAgICB9XG5cbiAgICBpZiAoZWxlbWVudC5kYXRhc2V0KSB7XG4gICAgICByZXR1cm4gZWxlbWVudC5kYXRhc2V0W25hbWVdO1xuICAgIH1cblxuICAgIHJldHVybiBlbGVtZW50LmdldEF0dHJpYnV0ZShcImRhdGEtXCIuY29uY2F0KHRvUGFyYW1DYXNlKG5hbWUpKSk7XG4gIH1cbiAgLyoqXG4gICAqIFNldCBkYXRhIHRvIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnQgLSBUaGUgdGFyZ2V0IGVsZW1lbnQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIGRhdGEga2V5IHRvIHNldC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBUaGUgZGF0YSB2YWx1ZS5cbiAgICovXG5cbiAgZnVuY3Rpb24gc2V0RGF0YShlbGVtZW50LCBuYW1lLCBkYXRhKSB7XG4gICAgaWYgKGlzT2JqZWN0KGRhdGEpKSB7XG4gICAgICBlbGVtZW50W25hbWVdID0gZGF0YTtcbiAgICB9IGVsc2UgaWYgKGVsZW1lbnQuZGF0YXNldCkge1xuICAgICAgZWxlbWVudC5kYXRhc2V0W25hbWVdID0gZGF0YTtcbiAgICB9IGVsc2Uge1xuICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoXCJkYXRhLVwiLmNvbmNhdCh0b1BhcmFtQ2FzZShuYW1lKSksIGRhdGEpO1xuICAgIH1cbiAgfVxuICAvKipcbiAgICogUmVtb3ZlIGRhdGEgZnJvbSB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50IC0gVGhlIHRhcmdldCBlbGVtZW50LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBkYXRhIGtleSB0byByZW1vdmUuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIHJlbW92ZURhdGEoZWxlbWVudCwgbmFtZSkge1xuICAgIGlmIChpc09iamVjdChlbGVtZW50W25hbWVdKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZGVsZXRlIGVsZW1lbnRbbmFtZV07XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBlbGVtZW50W25hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZWxlbWVudC5kYXRhc2V0KSB7XG4gICAgICAvLyAjMTI4IFNhZmFyaSBub3QgYWxsb3dzIHRvIGRlbGV0ZSBkYXRhc2V0IHByb3BlcnR5XG4gICAgICB0cnkge1xuICAgICAgICBkZWxldGUgZWxlbWVudC5kYXRhc2V0W25hbWVdO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgZWxlbWVudC5kYXRhc2V0W25hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZShcImRhdGEtXCIuY29uY2F0KHRvUGFyYW1DYXNlKG5hbWUpKSk7XG4gICAgfVxuICB9XG4gIHZhciBSRUdFWFBfU1BBQ0VTID0gL1xcc1xccyovO1xuXG4gIHZhciBvbmNlU3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdXBwb3J0ZWQgPSBmYWxzZTtcblxuICAgIGlmIChJU19CUk9XU0VSKSB7XG4gICAgICB2YXIgb25jZSA9IGZhbHNlO1xuXG4gICAgICB2YXIgbGlzdGVuZXIgPSBmdW5jdGlvbiBsaXN0ZW5lcigpIHt9O1xuXG4gICAgICB2YXIgb3B0aW9ucyA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgJ29uY2UnLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHN1cHBvcnRlZCA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuIG9uY2U7XG4gICAgICAgIH0sXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoaXMgc2V0dGVyIGNhbiBmaXggYSBgVHlwZUVycm9yYCBpbiBzdHJpY3QgbW9kZVxuICAgICAgICAgKiB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvRXJyb3JzL0dldHRlcl9vbmx5fVxuICAgICAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHZhbHVlIC0gVGhlIHZhbHVlIHRvIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodmFsdWUpIHtcbiAgICAgICAgICBvbmNlID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgV0lORE9XLmFkZEV2ZW50TGlzdGVuZXIoJ3Rlc3QnLCBsaXN0ZW5lciwgb3B0aW9ucyk7XG4gICAgICBXSU5ET1cucmVtb3ZlRXZlbnRMaXN0ZW5lcigndGVzdCcsIGxpc3RlbmVyLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3VwcG9ydGVkO1xuICB9KCk7XG4gIC8qKlxuICAgKiBSZW1vdmUgZXZlbnQgbGlzdGVuZXIgZnJvbSB0aGUgdGFyZ2V0IGVsZW1lbnQuXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudCAtIFRoZSBldmVudCB0YXJnZXQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIC0gVGhlIGV2ZW50IHR5cGUocykuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIC0gVGhlIGV2ZW50IGxpc3RlbmVyLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIFRoZSBldmVudCBvcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGVsZW1lbnQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IHt9O1xuICAgIHZhciBoYW5kbGVyID0gbGlzdGVuZXI7XG4gICAgdHlwZS50cmltKCkuc3BsaXQoUkVHRVhQX1NQQUNFUykuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIGlmICghb25jZVN1cHBvcnRlZCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gZWxlbWVudC5saXN0ZW5lcnM7XG5cbiAgICAgICAgaWYgKGxpc3RlbmVycyAmJiBsaXN0ZW5lcnNbZXZlbnRdICYmIGxpc3RlbmVyc1tldmVudF1bbGlzdGVuZXJdKSB7XG4gICAgICAgICAgaGFuZGxlciA9IGxpc3RlbmVyc1tldmVudF1bbGlzdGVuZXJdO1xuICAgICAgICAgIGRlbGV0ZSBsaXN0ZW5lcnNbZXZlbnRdW2xpc3RlbmVyXTtcblxuICAgICAgICAgIGlmIChPYmplY3Qua2V5cyhsaXN0ZW5lcnNbZXZlbnRdKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGRlbGV0ZSBsaXN0ZW5lcnNbZXZlbnRdO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChPYmplY3Qua2V5cyhsaXN0ZW5lcnMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgZGVsZXRlIGVsZW1lbnQubGlzdGVuZXJzO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZXIsIG9wdGlvbnMpO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBBZGQgZXZlbnQgbGlzdGVuZXIgdG8gdGhlIHRhcmdldCBlbGVtZW50LlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnQgLSBUaGUgZXZlbnQgdGFyZ2V0LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSAtIFRoZSBldmVudCB0eXBlKHMpLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciAtIFRoZSBldmVudCBsaXN0ZW5lci5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBUaGUgZXZlbnQgb3B0aW9ucy5cbiAgICovXG5cbiAgZnVuY3Rpb24gYWRkTGlzdGVuZXIoZWxlbWVudCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDoge307XG4gICAgdmFyIF9oYW5kbGVyID0gbGlzdGVuZXI7XG4gICAgdHlwZS50cmltKCkuc3BsaXQoUkVHRVhQX1NQQUNFUykuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIGlmIChvcHRpb25zLm9uY2UgJiYgIW9uY2VTdXBwb3J0ZWQpIHtcbiAgICAgICAgdmFyIF9lbGVtZW50JGxpc3RlbmVycyA9IGVsZW1lbnQubGlzdGVuZXJzLFxuICAgICAgICAgICAgbGlzdGVuZXJzID0gX2VsZW1lbnQkbGlzdGVuZXJzID09PSB2b2lkIDAgPyB7fSA6IF9lbGVtZW50JGxpc3RlbmVycztcblxuICAgICAgICBfaGFuZGxlciA9IGZ1bmN0aW9uIGhhbmRsZXIoKSB7XG4gICAgICAgICAgZGVsZXRlIGxpc3RlbmVyc1tldmVudF1bbGlzdGVuZXJdO1xuICAgICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudCwgX2hhbmRsZXIsIG9wdGlvbnMpO1xuXG4gICAgICAgICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yKSwgX2tleTIgPSAwOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7XG4gICAgICAgICAgICBhcmdzW19rZXkyXSA9IGFyZ3VtZW50c1tfa2V5Ml07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbGlzdGVuZXIuYXBwbHkoZWxlbWVudCwgYXJncyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKCFsaXN0ZW5lcnNbZXZlbnRdKSB7XG4gICAgICAgICAgbGlzdGVuZXJzW2V2ZW50XSA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxpc3RlbmVyc1tldmVudF1bbGlzdGVuZXJdKSB7XG4gICAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcnNbZXZlbnRdW2xpc3RlbmVyXSwgb3B0aW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICBsaXN0ZW5lcnNbZXZlbnRdW2xpc3RlbmVyXSA9IF9oYW5kbGVyO1xuICAgICAgICBlbGVtZW50Lmxpc3RlbmVycyA9IGxpc3RlbmVycztcbiAgICAgIH1cblxuICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBfaGFuZGxlciwgb3B0aW9ucyk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIERpc3BhdGNoIGV2ZW50IG9uIHRoZSB0YXJnZXQgZWxlbWVudC5cbiAgICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50IC0gVGhlIGV2ZW50IHRhcmdldC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgLSBUaGUgZXZlbnQgdHlwZShzKS5cbiAgICogQHBhcmFtIHtPYmplY3R9IGRhdGEgLSBUaGUgYWRkaXRpb25hbCBldmVudCBkYXRhLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gSW5kaWNhdGUgaWYgdGhlIGV2ZW50IGlzIGRlZmF1bHQgcHJldmVudGVkIG9yIG5vdC5cbiAgICovXG5cbiAgZnVuY3Rpb24gZGlzcGF0Y2hFdmVudChlbGVtZW50LCB0eXBlLCBkYXRhKSB7XG4gICAgdmFyIGV2ZW50OyAvLyBFdmVudCBhbmQgQ3VzdG9tRXZlbnQgb24gSUU5LTExIGFyZSBnbG9iYWwgb2JqZWN0cywgbm90IGNvbnN0cnVjdG9yc1xuXG4gICAgaWYgKGlzRnVuY3Rpb24oRXZlbnQpICYmIGlzRnVuY3Rpb24oQ3VzdG9tRXZlbnQpKSB7XG4gICAgICBldmVudCA9IG5ldyBDdXN0b21FdmVudCh0eXBlLCB7XG4gICAgICAgIGRldGFpbDogZGF0YSxcbiAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgY2FuY2VsYWJsZTogdHJ1ZVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV2ZW50ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0N1c3RvbUV2ZW50Jyk7XG4gICAgICBldmVudC5pbml0Q3VzdG9tRXZlbnQodHlwZSwgdHJ1ZSwgdHJ1ZSwgZGF0YSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnQuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gIH1cbiAgLyoqXG4gICAqIEdldCB0aGUgb2Zmc2V0IGJhc2Ugb24gdGhlIGRvY3VtZW50LlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnQgLSBUaGUgdGFyZ2V0IGVsZW1lbnQuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBvZmZzZXQgZGF0YS5cbiAgICovXG5cbiAgZnVuY3Rpb24gZ2V0T2Zmc2V0KGVsZW1lbnQpIHtcbiAgICB2YXIgYm94ID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICByZXR1cm4ge1xuICAgICAgbGVmdDogYm94LmxlZnQgKyAod2luZG93LnBhZ2VYT2Zmc2V0IC0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudExlZnQpLFxuICAgICAgdG9wOiBib3gudG9wICsgKHdpbmRvdy5wYWdlWU9mZnNldCAtIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRUb3ApXG4gICAgfTtcbiAgfVxuICB2YXIgbG9jYXRpb24gPSBXSU5ET1cubG9jYXRpb247XG4gIHZhciBSRUdFWFBfT1JJR0lOUyA9IC9eKFxcdys6KVxcL1xcLyhbXjovPyNdKik6PyhcXGQqKS9pO1xuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlIGdpdmVuIFVSTCBpcyBhIGNyb3NzIG9yaWdpbiBVUkwuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgLSBUaGUgdGFyZ2V0IFVSTC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiBVUkwgaXMgYSBjcm9zcyBvcmlnaW4gVVJMLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGlzQ3Jvc3NPcmlnaW5VUkwodXJsKSB7XG4gICAgdmFyIHBhcnRzID0gdXJsLm1hdGNoKFJFR0VYUF9PUklHSU5TKTtcbiAgICByZXR1cm4gcGFydHMgIT09IG51bGwgJiYgKHBhcnRzWzFdICE9PSBsb2NhdGlvbi5wcm90b2NvbCB8fCBwYXJ0c1syXSAhPT0gbG9jYXRpb24uaG9zdG5hbWUgfHwgcGFydHNbM10gIT09IGxvY2F0aW9uLnBvcnQpO1xuICB9XG4gIC8qKlxuICAgKiBBZGQgdGltZXN0YW1wIHRvIHRoZSBnaXZlbiBVUkwuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgLSBUaGUgdGFyZ2V0IFVSTC5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHJlc3VsdCBVUkwuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFkZFRpbWVzdGFtcCh1cmwpIHtcbiAgICB2YXIgdGltZXN0YW1wID0gXCJ0aW1lc3RhbXA9XCIuY29uY2F0KG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcbiAgICByZXR1cm4gdXJsICsgKHVybC5pbmRleE9mKCc/JykgPT09IC0xID8gJz8nIDogJyYnKSArIHRpbWVzdGFtcDtcbiAgfVxuICAvKipcbiAgICogR2V0IHRyYW5zZm9ybXMgYmFzZSBvbiB0aGUgZ2l2ZW4gb2JqZWN0LlxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIC0gVGhlIHRhcmdldCBvYmplY3QuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IEEgc3RyaW5nIGNvbnRhaW5zIHRyYW5zZm9ybSB2YWx1ZXMuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGdldFRyYW5zZm9ybXMoX3JlZikge1xuICAgIHZhciByb3RhdGUgPSBfcmVmLnJvdGF0ZSxcbiAgICAgICAgc2NhbGVYID0gX3JlZi5zY2FsZVgsXG4gICAgICAgIHNjYWxlWSA9IF9yZWYuc2NhbGVZLFxuICAgICAgICB0cmFuc2xhdGVYID0gX3JlZi50cmFuc2xhdGVYLFxuICAgICAgICB0cmFuc2xhdGVZID0gX3JlZi50cmFuc2xhdGVZO1xuICAgIHZhciB2YWx1ZXMgPSBbXTtcblxuICAgIGlmIChpc051bWJlcih0cmFuc2xhdGVYKSAmJiB0cmFuc2xhdGVYICE9PSAwKSB7XG4gICAgICB2YWx1ZXMucHVzaChcInRyYW5zbGF0ZVgoXCIuY29uY2F0KHRyYW5zbGF0ZVgsIFwicHgpXCIpKTtcbiAgICB9XG5cbiAgICBpZiAoaXNOdW1iZXIodHJhbnNsYXRlWSkgJiYgdHJhbnNsYXRlWSAhPT0gMCkge1xuICAgICAgdmFsdWVzLnB1c2goXCJ0cmFuc2xhdGVZKFwiLmNvbmNhdCh0cmFuc2xhdGVZLCBcInB4KVwiKSk7XG4gICAgfSAvLyBSb3RhdGUgc2hvdWxkIGNvbWUgZmlyc3QgYmVmb3JlIHNjYWxlIHRvIG1hdGNoIG9yaWVudGF0aW9uIHRyYW5zZm9ybVxuXG5cbiAgICBpZiAoaXNOdW1iZXIocm90YXRlKSAmJiByb3RhdGUgIT09IDApIHtcbiAgICAgIHZhbHVlcy5wdXNoKFwicm90YXRlKFwiLmNvbmNhdChyb3RhdGUsIFwiZGVnKVwiKSk7XG4gICAgfVxuXG4gICAgaWYgKGlzTnVtYmVyKHNjYWxlWCkgJiYgc2NhbGVYICE9PSAxKSB7XG4gICAgICB2YWx1ZXMucHVzaChcInNjYWxlWChcIi5jb25jYXQoc2NhbGVYLCBcIilcIikpO1xuICAgIH1cblxuICAgIGlmIChpc051bWJlcihzY2FsZVkpICYmIHNjYWxlWSAhPT0gMSkge1xuICAgICAgdmFsdWVzLnB1c2goXCJzY2FsZVkoXCIuY29uY2F0KHNjYWxlWSwgXCIpXCIpKTtcbiAgICB9XG5cbiAgICB2YXIgdHJhbnNmb3JtID0gdmFsdWVzLmxlbmd0aCA/IHZhbHVlcy5qb2luKCcgJykgOiAnbm9uZSc7XG4gICAgcmV0dXJuIHtcbiAgICAgIFdlYmtpdFRyYW5zZm9ybTogdHJhbnNmb3JtLFxuICAgICAgbXNUcmFuc2Zvcm06IHRyYW5zZm9ybSxcbiAgICAgIHRyYW5zZm9ybTogdHJhbnNmb3JtXG4gICAgfTtcbiAgfVxuICAvKipcbiAgICogR2V0IHRoZSBtYXggcmF0aW8gb2YgYSBncm91cCBvZiBwb2ludGVycy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHBvaW50ZXJzIC0gVGhlIHRhcmdldCBwb2ludGVycy5cbiAgICogQHJldHVybnMge251bWJlcn0gVGhlIHJlc3VsdCByYXRpby5cbiAgICovXG5cbiAgZnVuY3Rpb24gZ2V0TWF4Wm9vbVJhdGlvKHBvaW50ZXJzKSB7XG4gICAgdmFyIHBvaW50ZXJzMiA9IF9vYmplY3RTcHJlYWQyKHt9LCBwb2ludGVycyk7XG5cbiAgICB2YXIgcmF0aW9zID0gW107XG4gICAgZm9yRWFjaChwb2ludGVycywgZnVuY3Rpb24gKHBvaW50ZXIsIHBvaW50ZXJJZCkge1xuICAgICAgZGVsZXRlIHBvaW50ZXJzMltwb2ludGVySWRdO1xuICAgICAgZm9yRWFjaChwb2ludGVyczIsIGZ1bmN0aW9uIChwb2ludGVyMikge1xuICAgICAgICB2YXIgeDEgPSBNYXRoLmFicyhwb2ludGVyLnN0YXJ0WCAtIHBvaW50ZXIyLnN0YXJ0WCk7XG4gICAgICAgIHZhciB5MSA9IE1hdGguYWJzKHBvaW50ZXIuc3RhcnRZIC0gcG9pbnRlcjIuc3RhcnRZKTtcbiAgICAgICAgdmFyIHgyID0gTWF0aC5hYnMocG9pbnRlci5lbmRYIC0gcG9pbnRlcjIuZW5kWCk7XG4gICAgICAgIHZhciB5MiA9IE1hdGguYWJzKHBvaW50ZXIuZW5kWSAtIHBvaW50ZXIyLmVuZFkpO1xuICAgICAgICB2YXIgejEgPSBNYXRoLnNxcnQoeDEgKiB4MSArIHkxICogeTEpO1xuICAgICAgICB2YXIgejIgPSBNYXRoLnNxcnQoeDIgKiB4MiArIHkyICogeTIpO1xuICAgICAgICB2YXIgcmF0aW8gPSAoejIgLSB6MSkgLyB6MTtcbiAgICAgICAgcmF0aW9zLnB1c2gocmF0aW8pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmF0aW9zLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgIHJldHVybiBNYXRoLmFicyhhKSA8IE1hdGguYWJzKGIpO1xuICAgIH0pO1xuICAgIHJldHVybiByYXRpb3NbMF07XG4gIH1cbiAgLyoqXG4gICAqIEdldCBhIHBvaW50ZXIgZnJvbSBhbiBldmVudCBvYmplY3QuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCAtIFRoZSB0YXJnZXQgZXZlbnQgb2JqZWN0LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGVuZE9ubHkgLSBJbmRpY2F0ZXMgaWYgb25seSByZXR1cm5zIHRoZSBlbmQgcG9pbnQgY29vcmRpbmF0ZSBvciBub3QuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSByZXN1bHQgcG9pbnRlciBjb250YWlucyBzdGFydCBhbmQvb3IgZW5kIHBvaW50IGNvb3JkaW5hdGVzLlxuICAgKi9cblxuICBmdW5jdGlvbiBnZXRQb2ludGVyKF9yZWYyLCBlbmRPbmx5KSB7XG4gICAgdmFyIHBhZ2VYID0gX3JlZjIucGFnZVgsXG4gICAgICAgIHBhZ2VZID0gX3JlZjIucGFnZVk7XG4gICAgdmFyIGVuZCA9IHtcbiAgICAgIGVuZFg6IHBhZ2VYLFxuICAgICAgZW5kWTogcGFnZVlcbiAgICB9O1xuICAgIHJldHVybiBlbmRPbmx5ID8gZW5kIDogX29iamVjdFNwcmVhZDIoe1xuICAgICAgc3RhcnRYOiBwYWdlWCxcbiAgICAgIHN0YXJ0WTogcGFnZVlcbiAgICB9LCBlbmQpO1xuICB9XG4gIC8qKlxuICAgKiBHZXQgdGhlIGNlbnRlciBwb2ludCBjb29yZGluYXRlIG9mIGEgZ3JvdXAgb2YgcG9pbnRlcnMuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwb2ludGVycyAtIFRoZSB0YXJnZXQgcG9pbnRlcnMuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBjZW50ZXIgcG9pbnQgY29vcmRpbmF0ZS5cbiAgICovXG5cbiAgZnVuY3Rpb24gZ2V0UG9pbnRlcnNDZW50ZXIocG9pbnRlcnMpIHtcbiAgICB2YXIgcGFnZVggPSAwO1xuICAgIHZhciBwYWdlWSA9IDA7XG4gICAgdmFyIGNvdW50ID0gMDtcbiAgICBmb3JFYWNoKHBvaW50ZXJzLCBmdW5jdGlvbiAoX3JlZjMpIHtcbiAgICAgIHZhciBzdGFydFggPSBfcmVmMy5zdGFydFgsXG4gICAgICAgICAgc3RhcnRZID0gX3JlZjMuc3RhcnRZO1xuICAgICAgcGFnZVggKz0gc3RhcnRYO1xuICAgICAgcGFnZVkgKz0gc3RhcnRZO1xuICAgICAgY291bnQgKz0gMTtcbiAgICB9KTtcbiAgICBwYWdlWCAvPSBjb3VudDtcbiAgICBwYWdlWSAvPSBjb3VudDtcbiAgICByZXR1cm4ge1xuICAgICAgcGFnZVg6IHBhZ2VYLFxuICAgICAgcGFnZVk6IHBhZ2VZXG4gICAgfTtcbiAgfVxuICAvKipcbiAgICogR2V0IHRoZSBtYXggc2l6ZXMgaW4gYSByZWN0YW5nbGUgdW5kZXIgdGhlIGdpdmVuIGFzcGVjdCByYXRpby5cbiAgICogQHBhcmFtIHtPYmplY3R9IGRhdGEgLSBUaGUgb3JpZ2luYWwgc2l6ZXMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbdHlwZT0nY29udGFpbiddIC0gVGhlIGFkanVzdCB0eXBlLlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgcmVzdWx0IHNpemVzLlxuICAgKi9cblxuICBmdW5jdGlvbiBnZXRBZGp1c3RlZFNpemVzKF9yZWY0KSAvLyBvciAnY292ZXInXG4gIHtcbiAgICB2YXIgYXNwZWN0UmF0aW8gPSBfcmVmNC5hc3BlY3RSYXRpbyxcbiAgICAgICAgaGVpZ2h0ID0gX3JlZjQuaGVpZ2h0LFxuICAgICAgICB3aWR0aCA9IF9yZWY0LndpZHRoO1xuICAgIHZhciB0eXBlID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiAnY29udGFpbic7XG4gICAgdmFyIGlzVmFsaWRXaWR0aCA9IGlzUG9zaXRpdmVOdW1iZXIod2lkdGgpO1xuICAgIHZhciBpc1ZhbGlkSGVpZ2h0ID0gaXNQb3NpdGl2ZU51bWJlcihoZWlnaHQpO1xuXG4gICAgaWYgKGlzVmFsaWRXaWR0aCAmJiBpc1ZhbGlkSGVpZ2h0KSB7XG4gICAgICB2YXIgYWRqdXN0ZWRXaWR0aCA9IGhlaWdodCAqIGFzcGVjdFJhdGlvO1xuXG4gICAgICBpZiAodHlwZSA9PT0gJ2NvbnRhaW4nICYmIGFkanVzdGVkV2lkdGggPiB3aWR0aCB8fCB0eXBlID09PSAnY292ZXInICYmIGFkanVzdGVkV2lkdGggPCB3aWR0aCkge1xuICAgICAgICBoZWlnaHQgPSB3aWR0aCAvIGFzcGVjdFJhdGlvO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2lkdGggPSBoZWlnaHQgKiBhc3BlY3RSYXRpbztcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzVmFsaWRXaWR0aCkge1xuICAgICAgaGVpZ2h0ID0gd2lkdGggLyBhc3BlY3RSYXRpbztcbiAgICB9IGVsc2UgaWYgKGlzVmFsaWRIZWlnaHQpIHtcbiAgICAgIHdpZHRoID0gaGVpZ2h0ICogYXNwZWN0UmF0aW87XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHdpZHRoOiB3aWR0aCxcbiAgICAgIGhlaWdodDogaGVpZ2h0XG4gICAgfTtcbiAgfVxuICAvKipcbiAgICogR2V0IHRoZSBuZXcgc2l6ZXMgb2YgYSByZWN0YW5nbGUgYWZ0ZXIgcm90YXRlZC5cbiAgICogQHBhcmFtIHtPYmplY3R9IGRhdGEgLSBUaGUgb3JpZ2luYWwgc2l6ZXMuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSByZXN1bHQgc2l6ZXMuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGdldFJvdGF0ZWRTaXplcyhfcmVmNSkge1xuICAgIHZhciB3aWR0aCA9IF9yZWY1LndpZHRoLFxuICAgICAgICBoZWlnaHQgPSBfcmVmNS5oZWlnaHQsXG4gICAgICAgIGRlZ3JlZSA9IF9yZWY1LmRlZ3JlZTtcbiAgICBkZWdyZWUgPSBNYXRoLmFicyhkZWdyZWUpICUgMTgwO1xuXG4gICAgaWYgKGRlZ3JlZSA9PT0gOTApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHdpZHRoOiBoZWlnaHQsXG4gICAgICAgIGhlaWdodDogd2lkdGhcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGFyYyA9IGRlZ3JlZSAlIDkwICogTWF0aC5QSSAvIDE4MDtcbiAgICB2YXIgc2luQXJjID0gTWF0aC5zaW4oYXJjKTtcbiAgICB2YXIgY29zQXJjID0gTWF0aC5jb3MoYXJjKTtcbiAgICB2YXIgbmV3V2lkdGggPSB3aWR0aCAqIGNvc0FyYyArIGhlaWdodCAqIHNpbkFyYztcbiAgICB2YXIgbmV3SGVpZ2h0ID0gd2lkdGggKiBzaW5BcmMgKyBoZWlnaHQgKiBjb3NBcmM7XG4gICAgcmV0dXJuIGRlZ3JlZSA+IDkwID8ge1xuICAgICAgd2lkdGg6IG5ld0hlaWdodCxcbiAgICAgIGhlaWdodDogbmV3V2lkdGhcbiAgICB9IDoge1xuICAgICAgd2lkdGg6IG5ld1dpZHRoLFxuICAgICAgaGVpZ2h0OiBuZXdIZWlnaHRcbiAgICB9O1xuICB9XG4gIC8qKlxuICAgKiBHZXQgYSBjYW52YXMgd2hpY2ggZHJldyB0aGUgZ2l2ZW4gaW1hZ2UuXG4gICAqIEBwYXJhbSB7SFRNTEltYWdlRWxlbWVudH0gaW1hZ2UgLSBUaGUgaW1hZ2UgZm9yIGRyYXdpbmcuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBpbWFnZURhdGEgLSBUaGUgaW1hZ2UgZGF0YS5cbiAgICogQHBhcmFtIHtPYmplY3R9IGNhbnZhc0RhdGEgLSBUaGUgY2FudmFzIGRhdGEuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gVGhlIG9wdGlvbnMuXG4gICAqIEByZXR1cm5zIHtIVE1MQ2FudmFzRWxlbWVudH0gVGhlIHJlc3VsdCBjYW52YXMuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGdldFNvdXJjZUNhbnZhcyhpbWFnZSwgX3JlZjYsIF9yZWY3LCBfcmVmOCkge1xuICAgIHZhciBpbWFnZUFzcGVjdFJhdGlvID0gX3JlZjYuYXNwZWN0UmF0aW8sXG4gICAgICAgIGltYWdlTmF0dXJhbFdpZHRoID0gX3JlZjYubmF0dXJhbFdpZHRoLFxuICAgICAgICBpbWFnZU5hdHVyYWxIZWlnaHQgPSBfcmVmNi5uYXR1cmFsSGVpZ2h0LFxuICAgICAgICBfcmVmNiRyb3RhdGUgPSBfcmVmNi5yb3RhdGUsXG4gICAgICAgIHJvdGF0ZSA9IF9yZWY2JHJvdGF0ZSA9PT0gdm9pZCAwID8gMCA6IF9yZWY2JHJvdGF0ZSxcbiAgICAgICAgX3JlZjYkc2NhbGVYID0gX3JlZjYuc2NhbGVYLFxuICAgICAgICBzY2FsZVggPSBfcmVmNiRzY2FsZVggPT09IHZvaWQgMCA/IDEgOiBfcmVmNiRzY2FsZVgsXG4gICAgICAgIF9yZWY2JHNjYWxlWSA9IF9yZWY2LnNjYWxlWSxcbiAgICAgICAgc2NhbGVZID0gX3JlZjYkc2NhbGVZID09PSB2b2lkIDAgPyAxIDogX3JlZjYkc2NhbGVZO1xuICAgIHZhciBhc3BlY3RSYXRpbyA9IF9yZWY3LmFzcGVjdFJhdGlvLFxuICAgICAgICBuYXR1cmFsV2lkdGggPSBfcmVmNy5uYXR1cmFsV2lkdGgsXG4gICAgICAgIG5hdHVyYWxIZWlnaHQgPSBfcmVmNy5uYXR1cmFsSGVpZ2h0O1xuICAgIHZhciBfcmVmOCRmaWxsQ29sb3IgPSBfcmVmOC5maWxsQ29sb3IsXG4gICAgICAgIGZpbGxDb2xvciA9IF9yZWY4JGZpbGxDb2xvciA9PT0gdm9pZCAwID8gJ3RyYW5zcGFyZW50JyA6IF9yZWY4JGZpbGxDb2xvcixcbiAgICAgICAgX3JlZjgkaW1hZ2VTbW9vdGhpbmdFID0gX3JlZjguaW1hZ2VTbW9vdGhpbmdFbmFibGVkLFxuICAgICAgICBpbWFnZVNtb290aGluZ0VuYWJsZWQgPSBfcmVmOCRpbWFnZVNtb290aGluZ0UgPT09IHZvaWQgMCA/IHRydWUgOiBfcmVmOCRpbWFnZVNtb290aGluZ0UsXG4gICAgICAgIF9yZWY4JGltYWdlU21vb3RoaW5nUSA9IF9yZWY4LmltYWdlU21vb3RoaW5nUXVhbGl0eSxcbiAgICAgICAgaW1hZ2VTbW9vdGhpbmdRdWFsaXR5ID0gX3JlZjgkaW1hZ2VTbW9vdGhpbmdRID09PSB2b2lkIDAgPyAnbG93JyA6IF9yZWY4JGltYWdlU21vb3RoaW5nUSxcbiAgICAgICAgX3JlZjgkbWF4V2lkdGggPSBfcmVmOC5tYXhXaWR0aCxcbiAgICAgICAgbWF4V2lkdGggPSBfcmVmOCRtYXhXaWR0aCA9PT0gdm9pZCAwID8gSW5maW5pdHkgOiBfcmVmOCRtYXhXaWR0aCxcbiAgICAgICAgX3JlZjgkbWF4SGVpZ2h0ID0gX3JlZjgubWF4SGVpZ2h0LFxuICAgICAgICBtYXhIZWlnaHQgPSBfcmVmOCRtYXhIZWlnaHQgPT09IHZvaWQgMCA/IEluZmluaXR5IDogX3JlZjgkbWF4SGVpZ2h0LFxuICAgICAgICBfcmVmOCRtaW5XaWR0aCA9IF9yZWY4Lm1pbldpZHRoLFxuICAgICAgICBtaW5XaWR0aCA9IF9yZWY4JG1pbldpZHRoID09PSB2b2lkIDAgPyAwIDogX3JlZjgkbWluV2lkdGgsXG4gICAgICAgIF9yZWY4JG1pbkhlaWdodCA9IF9yZWY4Lm1pbkhlaWdodCxcbiAgICAgICAgbWluSGVpZ2h0ID0gX3JlZjgkbWluSGVpZ2h0ID09PSB2b2lkIDAgPyAwIDogX3JlZjgkbWluSGVpZ2h0O1xuICAgIHZhciBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIHZhciBtYXhTaXplcyA9IGdldEFkanVzdGVkU2l6ZXMoe1xuICAgICAgYXNwZWN0UmF0aW86IGFzcGVjdFJhdGlvLFxuICAgICAgd2lkdGg6IG1heFdpZHRoLFxuICAgICAgaGVpZ2h0OiBtYXhIZWlnaHRcbiAgICB9KTtcbiAgICB2YXIgbWluU2l6ZXMgPSBnZXRBZGp1c3RlZFNpemVzKHtcbiAgICAgIGFzcGVjdFJhdGlvOiBhc3BlY3RSYXRpbyxcbiAgICAgIHdpZHRoOiBtaW5XaWR0aCxcbiAgICAgIGhlaWdodDogbWluSGVpZ2h0XG4gICAgfSwgJ2NvdmVyJyk7XG4gICAgdmFyIHdpZHRoID0gTWF0aC5taW4obWF4U2l6ZXMud2lkdGgsIE1hdGgubWF4KG1pblNpemVzLndpZHRoLCBuYXR1cmFsV2lkdGgpKTtcbiAgICB2YXIgaGVpZ2h0ID0gTWF0aC5taW4obWF4U2l6ZXMuaGVpZ2h0LCBNYXRoLm1heChtaW5TaXplcy5oZWlnaHQsIG5hdHVyYWxIZWlnaHQpKTsgLy8gTm90ZTogc2hvdWxkIGFsd2F5cyB1c2UgaW1hZ2UncyBuYXR1cmFsIHNpemVzIGZvciBkcmF3aW5nIGFzXG4gICAgLy8gaW1hZ2VEYXRhLm5hdHVyYWxXaWR0aCA9PT0gY2FudmFzRGF0YS5uYXR1cmFsSGVpZ2h0IHdoZW4gcm90YXRlICUgMTgwID09PSA5MFxuXG4gICAgdmFyIGRlc3RNYXhTaXplcyA9IGdldEFkanVzdGVkU2l6ZXMoe1xuICAgICAgYXNwZWN0UmF0aW86IGltYWdlQXNwZWN0UmF0aW8sXG4gICAgICB3aWR0aDogbWF4V2lkdGgsXG4gICAgICBoZWlnaHQ6IG1heEhlaWdodFxuICAgIH0pO1xuICAgIHZhciBkZXN0TWluU2l6ZXMgPSBnZXRBZGp1c3RlZFNpemVzKHtcbiAgICAgIGFzcGVjdFJhdGlvOiBpbWFnZUFzcGVjdFJhdGlvLFxuICAgICAgd2lkdGg6IG1pbldpZHRoLFxuICAgICAgaGVpZ2h0OiBtaW5IZWlnaHRcbiAgICB9LCAnY292ZXInKTtcbiAgICB2YXIgZGVzdFdpZHRoID0gTWF0aC5taW4oZGVzdE1heFNpemVzLndpZHRoLCBNYXRoLm1heChkZXN0TWluU2l6ZXMud2lkdGgsIGltYWdlTmF0dXJhbFdpZHRoKSk7XG4gICAgdmFyIGRlc3RIZWlnaHQgPSBNYXRoLm1pbihkZXN0TWF4U2l6ZXMuaGVpZ2h0LCBNYXRoLm1heChkZXN0TWluU2l6ZXMuaGVpZ2h0LCBpbWFnZU5hdHVyYWxIZWlnaHQpKTtcbiAgICB2YXIgcGFyYW1zID0gWy1kZXN0V2lkdGggLyAyLCAtZGVzdEhlaWdodCAvIDIsIGRlc3RXaWR0aCwgZGVzdEhlaWdodF07XG4gICAgY2FudmFzLndpZHRoID0gbm9ybWFsaXplRGVjaW1hbE51bWJlcih3aWR0aCk7XG4gICAgY2FudmFzLmhlaWdodCA9IG5vcm1hbGl6ZURlY2ltYWxOdW1iZXIoaGVpZ2h0KTtcbiAgICBjb250ZXh0LmZpbGxTdHlsZSA9IGZpbGxDb2xvcjtcbiAgICBjb250ZXh0LmZpbGxSZWN0KDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xuICAgIGNvbnRleHQuc2F2ZSgpO1xuICAgIGNvbnRleHQudHJhbnNsYXRlKHdpZHRoIC8gMiwgaGVpZ2h0IC8gMik7XG4gICAgY29udGV4dC5yb3RhdGUocm90YXRlICogTWF0aC5QSSAvIDE4MCk7XG4gICAgY29udGV4dC5zY2FsZShzY2FsZVgsIHNjYWxlWSk7XG4gICAgY29udGV4dC5pbWFnZVNtb290aGluZ0VuYWJsZWQgPSBpbWFnZVNtb290aGluZ0VuYWJsZWQ7XG4gICAgY29udGV4dC5pbWFnZVNtb290aGluZ1F1YWxpdHkgPSBpbWFnZVNtb290aGluZ1F1YWxpdHk7XG4gICAgY29udGV4dC5kcmF3SW1hZ2UuYXBwbHkoY29udGV4dCwgW2ltYWdlXS5jb25jYXQoX3RvQ29uc3VtYWJsZUFycmF5KHBhcmFtcy5tYXAoZnVuY3Rpb24gKHBhcmFtKSB7XG4gICAgICByZXR1cm4gTWF0aC5mbG9vcihub3JtYWxpemVEZWNpbWFsTnVtYmVyKHBhcmFtKSk7XG4gICAgfSkpKSk7XG4gICAgY29udGV4dC5yZXN0b3JlKCk7XG4gICAgcmV0dXJuIGNhbnZhcztcbiAgfVxuICB2YXIgZnJvbUNoYXJDb2RlID0gU3RyaW5nLmZyb21DaGFyQ29kZTtcbiAgLyoqXG4gICAqIEdldCBzdHJpbmcgZnJvbSBjaGFyIGNvZGUgaW4gZGF0YSB2aWV3LlxuICAgKiBAcGFyYW0ge0RhdGFWaWV3fSBkYXRhVmlldyAtIFRoZSBkYXRhIHZpZXcgZm9yIHJlYWQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydCAtIFRoZSBzdGFydCBpbmRleC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGxlbmd0aCAtIFRoZSByZWFkIGxlbmd0aC5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHJlYWQgcmVzdWx0LlxuICAgKi9cblxuICBmdW5jdGlvbiBnZXRTdHJpbmdGcm9tQ2hhckNvZGUoZGF0YVZpZXcsIHN0YXJ0LCBsZW5ndGgpIHtcbiAgICB2YXIgc3RyID0gJyc7XG4gICAgbGVuZ3RoICs9IHN0YXJ0O1xuXG4gICAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgIHN0ciArPSBmcm9tQ2hhckNvZGUoZGF0YVZpZXcuZ2V0VWludDgoaSkpO1xuICAgIH1cblxuICAgIHJldHVybiBzdHI7XG4gIH1cbiAgdmFyIFJFR0VYUF9EQVRBX1VSTF9IRUFEID0gL15kYXRhOi4qLC87XG4gIC8qKlxuICAgKiBUcmFuc2Zvcm0gRGF0YSBVUkwgdG8gYXJyYXkgYnVmZmVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZGF0YVVSTCAtIFRoZSBEYXRhIFVSTCB0byB0cmFuc2Zvcm0uXG4gICAqIEByZXR1cm5zIHtBcnJheUJ1ZmZlcn0gVGhlIHJlc3VsdCBhcnJheSBidWZmZXIuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGRhdGFVUkxUb0FycmF5QnVmZmVyKGRhdGFVUkwpIHtcbiAgICB2YXIgYmFzZTY0ID0gZGF0YVVSTC5yZXBsYWNlKFJFR0VYUF9EQVRBX1VSTF9IRUFELCAnJyk7XG4gICAgdmFyIGJpbmFyeSA9IGF0b2IoYmFzZTY0KTtcbiAgICB2YXIgYXJyYXlCdWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIoYmluYXJ5Lmxlbmd0aCk7XG4gICAgdmFyIHVpbnQ4ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpO1xuICAgIGZvckVhY2godWludDgsIGZ1bmN0aW9uICh2YWx1ZSwgaSkge1xuICAgICAgdWludDhbaV0gPSBiaW5hcnkuY2hhckNvZGVBdChpKTtcbiAgICB9KTtcbiAgICByZXR1cm4gYXJyYXlCdWZmZXI7XG4gIH1cbiAgLyoqXG4gICAqIFRyYW5zZm9ybSBhcnJheSBidWZmZXIgdG8gRGF0YSBVUkwuXG4gICAqIEBwYXJhbSB7QXJyYXlCdWZmZXJ9IGFycmF5QnVmZmVyIC0gVGhlIGFycmF5IGJ1ZmZlciB0byB0cmFuc2Zvcm0uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtaW1lVHlwZSAtIFRoZSBtaW1lIHR5cGUgb2YgdGhlIERhdGEgVVJMLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgcmVzdWx0IERhdGEgVVJMLlxuICAgKi9cblxuICBmdW5jdGlvbiBhcnJheUJ1ZmZlclRvRGF0YVVSTChhcnJheUJ1ZmZlciwgbWltZVR5cGUpIHtcbiAgICB2YXIgY2h1bmtzID0gW107IC8vIENodW5rIFR5cGVkIEFycmF5IGZvciBiZXR0ZXIgcGVyZm9ybWFuY2UgKCM0MzUpXG5cbiAgICB2YXIgY2h1bmtTaXplID0gODE5MjtcbiAgICB2YXIgdWludDggPSBuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcik7XG5cbiAgICB3aGlsZSAodWludDgubGVuZ3RoID4gMCkge1xuICAgICAgLy8gWFhYOiBCYWJlbCdzIGB0b0NvbnN1bWFibGVBcnJheWAgaGVscGVyIHdpbGwgdGhyb3cgZXJyb3IgaW4gSUUgb3IgU2FmYXJpIDlcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItc3ByZWFkXG4gICAgICBjaHVua3MucHVzaChmcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgdG9BcnJheSh1aW50OC5zdWJhcnJheSgwLCBjaHVua1NpemUpKSkpO1xuICAgICAgdWludDggPSB1aW50OC5zdWJhcnJheShjaHVua1NpemUpO1xuICAgIH1cblxuICAgIHJldHVybiBcImRhdGE6XCIuY29uY2F0KG1pbWVUeXBlLCBcIjtiYXNlNjQsXCIpLmNvbmNhdChidG9hKGNodW5rcy5qb2luKCcnKSkpO1xuICB9XG4gIC8qKlxuICAgKiBHZXQgb3JpZW50YXRpb24gdmFsdWUgZnJvbSBnaXZlbiBhcnJheSBidWZmZXIuXG4gICAqIEBwYXJhbSB7QXJyYXlCdWZmZXJ9IGFycmF5QnVmZmVyIC0gVGhlIGFycmF5IGJ1ZmZlciB0byByZWFkLlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBUaGUgcmVhZCBvcmllbnRhdGlvbiB2YWx1ZS5cbiAgICovXG5cbiAgZnVuY3Rpb24gcmVzZXRBbmRHZXRPcmllbnRhdGlvbihhcnJheUJ1ZmZlcikge1xuICAgIHZhciBkYXRhVmlldyA9IG5ldyBEYXRhVmlldyhhcnJheUJ1ZmZlcik7XG4gICAgdmFyIG9yaWVudGF0aW9uOyAvLyBJZ25vcmVzIHJhbmdlIGVycm9yIHdoZW4gdGhlIGltYWdlIGRvZXMgbm90IGhhdmUgY29ycmVjdCBFeGlmIGluZm9ybWF0aW9uXG5cbiAgICB0cnkge1xuICAgICAgdmFyIGxpdHRsZUVuZGlhbjtcbiAgICAgIHZhciBhcHAxU3RhcnQ7XG4gICAgICB2YXIgaWZkU3RhcnQ7IC8vIE9ubHkgaGFuZGxlIEpQRUcgaW1hZ2UgKHN0YXJ0IGJ5IDB4RkZEOClcblxuICAgICAgaWYgKGRhdGFWaWV3LmdldFVpbnQ4KDApID09PSAweEZGICYmIGRhdGFWaWV3LmdldFVpbnQ4KDEpID09PSAweEQ4KSB7XG4gICAgICAgIHZhciBsZW5ndGggPSBkYXRhVmlldy5ieXRlTGVuZ3RoO1xuICAgICAgICB2YXIgb2Zmc2V0ID0gMjtcblxuICAgICAgICB3aGlsZSAob2Zmc2V0ICsgMSA8IGxlbmd0aCkge1xuICAgICAgICAgIGlmIChkYXRhVmlldy5nZXRVaW50OChvZmZzZXQpID09PSAweEZGICYmIGRhdGFWaWV3LmdldFVpbnQ4KG9mZnNldCArIDEpID09PSAweEUxKSB7XG4gICAgICAgICAgICBhcHAxU3RhcnQgPSBvZmZzZXQ7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBvZmZzZXQgKz0gMTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoYXBwMVN0YXJ0KSB7XG4gICAgICAgIHZhciBleGlmSURDb2RlID0gYXBwMVN0YXJ0ICsgNDtcbiAgICAgICAgdmFyIHRpZmZPZmZzZXQgPSBhcHAxU3RhcnQgKyAxMDtcblxuICAgICAgICBpZiAoZ2V0U3RyaW5nRnJvbUNoYXJDb2RlKGRhdGFWaWV3LCBleGlmSURDb2RlLCA0KSA9PT0gJ0V4aWYnKSB7XG4gICAgICAgICAgdmFyIGVuZGlhbm5lc3MgPSBkYXRhVmlldy5nZXRVaW50MTYodGlmZk9mZnNldCk7XG4gICAgICAgICAgbGl0dGxlRW5kaWFuID0gZW5kaWFubmVzcyA9PT0gMHg0OTQ5O1xuXG4gICAgICAgICAgaWYgKGxpdHRsZUVuZGlhbiB8fCBlbmRpYW5uZXNzID09PSAweDRENERcbiAgICAgICAgICAvKiBiaWdFbmRpYW4gKi9cbiAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgaWYgKGRhdGFWaWV3LmdldFVpbnQxNih0aWZmT2Zmc2V0ICsgMiwgbGl0dGxlRW5kaWFuKSA9PT0gMHgwMDJBKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZpcnN0SUZET2Zmc2V0ID0gZGF0YVZpZXcuZ2V0VWludDMyKHRpZmZPZmZzZXQgKyA0LCBsaXR0bGVFbmRpYW4pO1xuXG4gICAgICAgICAgICAgICAgaWYgKGZpcnN0SUZET2Zmc2V0ID49IDB4MDAwMDAwMDgpIHtcbiAgICAgICAgICAgICAgICAgIGlmZFN0YXJ0ID0gdGlmZk9mZnNldCArIGZpcnN0SUZET2Zmc2V0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChpZmRTdGFydCkge1xuICAgICAgICB2YXIgX2xlbmd0aCA9IGRhdGFWaWV3LmdldFVpbnQxNihpZmRTdGFydCwgbGl0dGxlRW5kaWFuKTtcblxuICAgICAgICB2YXIgX29mZnNldDtcblxuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgX2xlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgX29mZnNldCA9IGlmZFN0YXJ0ICsgaSAqIDEyICsgMjtcblxuICAgICAgICAgIGlmIChkYXRhVmlldy5nZXRVaW50MTYoX29mZnNldCwgbGl0dGxlRW5kaWFuKSA9PT0gMHgwMTEyXG4gICAgICAgICAgLyogT3JpZW50YXRpb24gKi9cbiAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgLy8gOCBpcyB0aGUgb2Zmc2V0IG9mIHRoZSBjdXJyZW50IHRhZydzIHZhbHVlXG4gICAgICAgICAgICAgIF9vZmZzZXQgKz0gODsgLy8gR2V0IHRoZSBvcmlnaW5hbCBvcmllbnRhdGlvbiB2YWx1ZVxuXG4gICAgICAgICAgICAgIG9yaWVudGF0aW9uID0gZGF0YVZpZXcuZ2V0VWludDE2KF9vZmZzZXQsIGxpdHRsZUVuZGlhbik7IC8vIE92ZXJyaWRlIHRoZSBvcmllbnRhdGlvbiB3aXRoIGl0cyBkZWZhdWx0IHZhbHVlXG5cbiAgICAgICAgICAgICAgZGF0YVZpZXcuc2V0VWludDE2KF9vZmZzZXQsIDEsIGxpdHRsZUVuZGlhbik7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIG9yaWVudGF0aW9uID0gMTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3JpZW50YXRpb247XG4gIH1cbiAgLyoqXG4gICAqIFBhcnNlIEV4aWYgT3JpZW50YXRpb24gdmFsdWUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvcmllbnRhdGlvbiAtIFRoZSBvcmllbnRhdGlvbiB0byBwYXJzZS5cbiAgICogQHJldHVybnMge09iamVjdH0gVGhlIHBhcnNlZCByZXN1bHQuXG4gICAqL1xuXG4gIGZ1bmN0aW9uIHBhcnNlT3JpZW50YXRpb24ob3JpZW50YXRpb24pIHtcbiAgICB2YXIgcm90YXRlID0gMDtcbiAgICB2YXIgc2NhbGVYID0gMTtcbiAgICB2YXIgc2NhbGVZID0gMTtcblxuICAgIHN3aXRjaCAob3JpZW50YXRpb24pIHtcbiAgICAgIC8vIEZsaXAgaG9yaXpvbnRhbFxuICAgICAgY2FzZSAyOlxuICAgICAgICBzY2FsZVggPSAtMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBSb3RhdGUgbGVmdCAxODDCsFxuXG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJvdGF0ZSA9IC0xODA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gRmxpcCB2ZXJ0aWNhbFxuXG4gICAgICBjYXNlIDQ6XG4gICAgICAgIHNjYWxlWSA9IC0xO1xuICAgICAgICBicmVhaztcbiAgICAgIC8vIEZsaXAgdmVydGljYWwgYW5kIHJvdGF0ZSByaWdodCA5MMKwXG5cbiAgICAgIGNhc2UgNTpcbiAgICAgICAgcm90YXRlID0gOTA7XG4gICAgICAgIHNjYWxlWSA9IC0xO1xuICAgICAgICBicmVhaztcbiAgICAgIC8vIFJvdGF0ZSByaWdodCA5MMKwXG5cbiAgICAgIGNhc2UgNjpcbiAgICAgICAgcm90YXRlID0gOTA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gRmxpcCBob3Jpem9udGFsIGFuZCByb3RhdGUgcmlnaHQgOTDCsFxuXG4gICAgICBjYXNlIDc6XG4gICAgICAgIHJvdGF0ZSA9IDkwO1xuICAgICAgICBzY2FsZVggPSAtMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBSb3RhdGUgbGVmdCA5MMKwXG5cbiAgICAgIGNhc2UgODpcbiAgICAgICAgcm90YXRlID0gLTkwO1xuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcm90YXRlOiByb3RhdGUsXG4gICAgICBzY2FsZVg6IHNjYWxlWCxcbiAgICAgIHNjYWxlWTogc2NhbGVZXG4gICAgfTtcbiAgfVxuXG4gIHZhciByZW5kZXIgPSB7XG4gICAgcmVuZGVyOiBmdW5jdGlvbiByZW5kZXIoKSB7XG4gICAgICB0aGlzLmluaXRDb250YWluZXIoKTtcbiAgICAgIHRoaXMuaW5pdENhbnZhcygpO1xuICAgICAgdGhpcy5pbml0Q3JvcEJveCgpO1xuICAgICAgdGhpcy5yZW5kZXJDYW52YXMoKTtcblxuICAgICAgaWYgKHRoaXMuY3JvcHBlZCkge1xuICAgICAgICB0aGlzLnJlbmRlckNyb3BCb3goKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGluaXRDb250YWluZXI6IGZ1bmN0aW9uIGluaXRDb250YWluZXIoKSB7XG4gICAgICB2YXIgZWxlbWVudCA9IHRoaXMuZWxlbWVudCxcbiAgICAgICAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICAgIGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyLFxuICAgICAgICAgIGNyb3BwZXIgPSB0aGlzLmNyb3BwZXI7XG4gICAgICBhZGRDbGFzcyhjcm9wcGVyLCBDTEFTU19ISURERU4pO1xuICAgICAgcmVtb3ZlQ2xhc3MoZWxlbWVudCwgQ0xBU1NfSElEREVOKTtcbiAgICAgIHZhciBjb250YWluZXJEYXRhID0ge1xuICAgICAgICB3aWR0aDogTWF0aC5tYXgoY29udGFpbmVyLm9mZnNldFdpZHRoLCBOdW1iZXIob3B0aW9ucy5taW5Db250YWluZXJXaWR0aCkgfHwgMjAwKSxcbiAgICAgICAgaGVpZ2h0OiBNYXRoLm1heChjb250YWluZXIub2Zmc2V0SGVpZ2h0LCBOdW1iZXIob3B0aW9ucy5taW5Db250YWluZXJIZWlnaHQpIHx8IDEwMClcbiAgICAgIH07XG4gICAgICB0aGlzLmNvbnRhaW5lckRhdGEgPSBjb250YWluZXJEYXRhO1xuICAgICAgc2V0U3R5bGUoY3JvcHBlciwge1xuICAgICAgICB3aWR0aDogY29udGFpbmVyRGF0YS53aWR0aCxcbiAgICAgICAgaGVpZ2h0OiBjb250YWluZXJEYXRhLmhlaWdodFxuICAgICAgfSk7XG4gICAgICBhZGRDbGFzcyhlbGVtZW50LCBDTEFTU19ISURERU4pO1xuICAgICAgcmVtb3ZlQ2xhc3MoY3JvcHBlciwgQ0xBU1NfSElEREVOKTtcbiAgICB9LFxuICAgIC8vIENhbnZhcyAoaW1hZ2Ugd3JhcHBlcilcbiAgICBpbml0Q2FudmFzOiBmdW5jdGlvbiBpbml0Q2FudmFzKCkge1xuICAgICAgdmFyIGNvbnRhaW5lckRhdGEgPSB0aGlzLmNvbnRhaW5lckRhdGEsXG4gICAgICAgICAgaW1hZ2VEYXRhID0gdGhpcy5pbWFnZURhdGE7XG4gICAgICB2YXIgdmlld01vZGUgPSB0aGlzLm9wdGlvbnMudmlld01vZGU7XG4gICAgICB2YXIgcm90YXRlZCA9IE1hdGguYWJzKGltYWdlRGF0YS5yb3RhdGUpICUgMTgwID09PSA5MDtcbiAgICAgIHZhciBuYXR1cmFsV2lkdGggPSByb3RhdGVkID8gaW1hZ2VEYXRhLm5hdHVyYWxIZWlnaHQgOiBpbWFnZURhdGEubmF0dXJhbFdpZHRoO1xuICAgICAgdmFyIG5hdHVyYWxIZWlnaHQgPSByb3RhdGVkID8gaW1hZ2VEYXRhLm5hdHVyYWxXaWR0aCA6IGltYWdlRGF0YS5uYXR1cmFsSGVpZ2h0O1xuICAgICAgdmFyIGFzcGVjdFJhdGlvID0gbmF0dXJhbFdpZHRoIC8gbmF0dXJhbEhlaWdodDtcbiAgICAgIHZhciBjYW52YXNXaWR0aCA9IGNvbnRhaW5lckRhdGEud2lkdGg7XG4gICAgICB2YXIgY2FudmFzSGVpZ2h0ID0gY29udGFpbmVyRGF0YS5oZWlnaHQ7XG5cbiAgICAgIGlmIChjb250YWluZXJEYXRhLmhlaWdodCAqIGFzcGVjdFJhdGlvID4gY29udGFpbmVyRGF0YS53aWR0aCkge1xuICAgICAgICBpZiAodmlld01vZGUgPT09IDMpIHtcbiAgICAgICAgICBjYW52YXNXaWR0aCA9IGNvbnRhaW5lckRhdGEuaGVpZ2h0ICogYXNwZWN0UmF0aW87XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2FudmFzSGVpZ2h0ID0gY29udGFpbmVyRGF0YS53aWR0aCAvIGFzcGVjdFJhdGlvO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHZpZXdNb2RlID09PSAzKSB7XG4gICAgICAgIGNhbnZhc0hlaWdodCA9IGNvbnRhaW5lckRhdGEud2lkdGggLyBhc3BlY3RSYXRpbztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNhbnZhc1dpZHRoID0gY29udGFpbmVyRGF0YS5oZWlnaHQgKiBhc3BlY3RSYXRpbztcbiAgICAgIH1cblxuICAgICAgdmFyIGNhbnZhc0RhdGEgPSB7XG4gICAgICAgIGFzcGVjdFJhdGlvOiBhc3BlY3RSYXRpbyxcbiAgICAgICAgbmF0dXJhbFdpZHRoOiBuYXR1cmFsV2lkdGgsXG4gICAgICAgIG5hdHVyYWxIZWlnaHQ6IG5hdHVyYWxIZWlnaHQsXG4gICAgICAgIHdpZHRoOiBjYW52YXNXaWR0aCxcbiAgICAgICAgaGVpZ2h0OiBjYW52YXNIZWlnaHRcbiAgICAgIH07XG4gICAgICBjYW52YXNEYXRhLmxlZnQgPSAoY29udGFpbmVyRGF0YS53aWR0aCAtIGNhbnZhc1dpZHRoKSAvIDI7XG4gICAgICBjYW52YXNEYXRhLnRvcCA9IChjb250YWluZXJEYXRhLmhlaWdodCAtIGNhbnZhc0hlaWdodCkgLyAyO1xuICAgICAgY2FudmFzRGF0YS5vbGRMZWZ0ID0gY2FudmFzRGF0YS5sZWZ0O1xuICAgICAgY2FudmFzRGF0YS5vbGRUb3AgPSBjYW52YXNEYXRhLnRvcDtcbiAgICAgIHRoaXMuY2FudmFzRGF0YSA9IGNhbnZhc0RhdGE7XG4gICAgICB0aGlzLmxpbWl0ZWQgPSB2aWV3TW9kZSA9PT0gMSB8fCB2aWV3TW9kZSA9PT0gMjtcbiAgICAgIHRoaXMubGltaXRDYW52YXModHJ1ZSwgdHJ1ZSk7XG4gICAgICB0aGlzLmluaXRpYWxJbWFnZURhdGEgPSBhc3NpZ24oe30sIGltYWdlRGF0YSk7XG4gICAgICB0aGlzLmluaXRpYWxDYW52YXNEYXRhID0gYXNzaWduKHt9LCBjYW52YXNEYXRhKTtcbiAgICB9LFxuICAgIGxpbWl0Q2FudmFzOiBmdW5jdGlvbiBsaW1pdENhbnZhcyhzaXplTGltaXRlZCwgcG9zaXRpb25MaW1pdGVkKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyxcbiAgICAgICAgICBjb250YWluZXJEYXRhID0gdGhpcy5jb250YWluZXJEYXRhLFxuICAgICAgICAgIGNhbnZhc0RhdGEgPSB0aGlzLmNhbnZhc0RhdGEsXG4gICAgICAgICAgY3JvcEJveERhdGEgPSB0aGlzLmNyb3BCb3hEYXRhO1xuICAgICAgdmFyIHZpZXdNb2RlID0gb3B0aW9ucy52aWV3TW9kZTtcbiAgICAgIHZhciBhc3BlY3RSYXRpbyA9IGNhbnZhc0RhdGEuYXNwZWN0UmF0aW87XG4gICAgICB2YXIgY3JvcHBlZCA9IHRoaXMuY3JvcHBlZCAmJiBjcm9wQm94RGF0YTtcblxuICAgICAgaWYgKHNpemVMaW1pdGVkKSB7XG4gICAgICAgIHZhciBtaW5DYW52YXNXaWR0aCA9IE51bWJlcihvcHRpb25zLm1pbkNhbnZhc1dpZHRoKSB8fCAwO1xuICAgICAgICB2YXIgbWluQ2FudmFzSGVpZ2h0ID0gTnVtYmVyKG9wdGlvbnMubWluQ2FudmFzSGVpZ2h0KSB8fCAwO1xuXG4gICAgICAgIGlmICh2aWV3TW9kZSA+IDEpIHtcbiAgICAgICAgICBtaW5DYW52YXNXaWR0aCA9IE1hdGgubWF4KG1pbkNhbnZhc1dpZHRoLCBjb250YWluZXJEYXRhLndpZHRoKTtcbiAgICAgICAgICBtaW5DYW52YXNIZWlnaHQgPSBNYXRoLm1heChtaW5DYW52YXNIZWlnaHQsIGNvbnRhaW5lckRhdGEuaGVpZ2h0KTtcblxuICAgICAgICAgIGlmICh2aWV3TW9kZSA9PT0gMykge1xuICAgICAgICAgICAgaWYgKG1pbkNhbnZhc0hlaWdodCAqIGFzcGVjdFJhdGlvID4gbWluQ2FudmFzV2lkdGgpIHtcbiAgICAgICAgICAgICAgbWluQ2FudmFzV2lkdGggPSBtaW5DYW52YXNIZWlnaHQgKiBhc3BlY3RSYXRpbztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIG1pbkNhbnZhc0hlaWdodCA9IG1pbkNhbnZhc1dpZHRoIC8gYXNwZWN0UmF0aW87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHZpZXdNb2RlID4gMCkge1xuICAgICAgICAgIGlmIChtaW5DYW52YXNXaWR0aCkge1xuICAgICAgICAgICAgbWluQ2FudmFzV2lkdGggPSBNYXRoLm1heChtaW5DYW52YXNXaWR0aCwgY3JvcHBlZCA/IGNyb3BCb3hEYXRhLndpZHRoIDogMCk7XG4gICAgICAgICAgfSBlbHNlIGlmIChtaW5DYW52YXNIZWlnaHQpIHtcbiAgICAgICAgICAgIG1pbkNhbnZhc0hlaWdodCA9IE1hdGgubWF4KG1pbkNhbnZhc0hlaWdodCwgY3JvcHBlZCA/IGNyb3BCb3hEYXRhLmhlaWdodCA6IDApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoY3JvcHBlZCkge1xuICAgICAgICAgICAgbWluQ2FudmFzV2lkdGggPSBjcm9wQm94RGF0YS53aWR0aDtcbiAgICAgICAgICAgIG1pbkNhbnZhc0hlaWdodCA9IGNyb3BCb3hEYXRhLmhlaWdodDtcblxuICAgICAgICAgICAgaWYgKG1pbkNhbnZhc0hlaWdodCAqIGFzcGVjdFJhdGlvID4gbWluQ2FudmFzV2lkdGgpIHtcbiAgICAgICAgICAgICAgbWluQ2FudmFzV2lkdGggPSBtaW5DYW52YXNIZWlnaHQgKiBhc3BlY3RSYXRpbztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIG1pbkNhbnZhc0hlaWdodCA9IG1pbkNhbnZhc1dpZHRoIC8gYXNwZWN0UmF0aW87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIF9nZXRBZGp1c3RlZFNpemVzID0gZ2V0QWRqdXN0ZWRTaXplcyh7XG4gICAgICAgICAgYXNwZWN0UmF0aW86IGFzcGVjdFJhdGlvLFxuICAgICAgICAgIHdpZHRoOiBtaW5DYW52YXNXaWR0aCxcbiAgICAgICAgICBoZWlnaHQ6IG1pbkNhbnZhc0hlaWdodFxuICAgICAgICB9KTtcblxuICAgICAgICBtaW5DYW52YXNXaWR0aCA9IF9nZXRBZGp1c3RlZFNpemVzLndpZHRoO1xuICAgICAgICBtaW5DYW52YXNIZWlnaHQgPSBfZ2V0QWRqdXN0ZWRTaXplcy5oZWlnaHQ7XG4gICAgICAgIGNhbnZhc0RhdGEubWluV2lkdGggPSBtaW5DYW52YXNXaWR0aDtcbiAgICAgICAgY2FudmFzRGF0YS5taW5IZWlnaHQgPSBtaW5DYW52YXNIZWlnaHQ7XG4gICAgICAgIGNhbnZhc0RhdGEubWF4V2lkdGggPSBJbmZpbml0eTtcbiAgICAgICAgY2FudmFzRGF0YS5tYXhIZWlnaHQgPSBJbmZpbml0eTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBvc2l0aW9uTGltaXRlZCkge1xuICAgICAgICBpZiAodmlld01vZGUgPiAoY3JvcHBlZCA/IDAgOiAxKSkge1xuICAgICAgICAgIHZhciBuZXdDYW52YXNMZWZ0ID0gY29udGFpbmVyRGF0YS53aWR0aCAtIGNhbnZhc0RhdGEud2lkdGg7XG4gICAgICAgICAgdmFyIG5ld0NhbnZhc1RvcCA9IGNvbnRhaW5lckRhdGEuaGVpZ2h0IC0gY2FudmFzRGF0YS5oZWlnaHQ7XG4gICAgICAgICAgY2FudmFzRGF0YS5taW5MZWZ0ID0gTWF0aC5taW4oMCwgbmV3Q2FudmFzTGVmdCk7XG4gICAgICAgICAgY2FudmFzRGF0YS5taW5Ub3AgPSBNYXRoLm1pbigwLCBuZXdDYW52YXNUb3ApO1xuICAgICAgICAgIGNhbnZhc0RhdGEubWF4TGVmdCA9IE1hdGgubWF4KDAsIG5ld0NhbnZhc0xlZnQpO1xuICAgICAgICAgIGNhbnZhc0RhdGEubWF4VG9wID0gTWF0aC5tYXgoMCwgbmV3Q2FudmFzVG9wKTtcblxuICAgICAgICAgIGlmIChjcm9wcGVkICYmIHRoaXMubGltaXRlZCkge1xuICAgICAgICAgICAgY2FudmFzRGF0YS5taW5MZWZ0ID0gTWF0aC5taW4oY3JvcEJveERhdGEubGVmdCwgY3JvcEJveERhdGEubGVmdCArIChjcm9wQm94RGF0YS53aWR0aCAtIGNhbnZhc0RhdGEud2lkdGgpKTtcbiAgICAgICAgICAgIGNhbnZhc0RhdGEubWluVG9wID0gTWF0aC5taW4oY3JvcEJveERhdGEudG9wLCBjcm9wQm94RGF0YS50b3AgKyAoY3JvcEJveERhdGEuaGVpZ2h0IC0gY2FudmFzRGF0YS5oZWlnaHQpKTtcbiAgICAgICAgICAgIGNhbnZhc0RhdGEubWF4TGVmdCA9IGNyb3BCb3hEYXRhLmxlZnQ7XG4gICAgICAgICAgICBjYW52YXNEYXRhLm1heFRvcCA9IGNyb3BCb3hEYXRhLnRvcDtcblxuICAgICAgICAgICAgaWYgKHZpZXdNb2RlID09PSAyKSB7XG4gICAgICAgICAgICAgIGlmIChjYW52YXNEYXRhLndpZHRoID49IGNvbnRhaW5lckRhdGEud2lkdGgpIHtcbiAgICAgICAgICAgICAgICBjYW52YXNEYXRhLm1pbkxlZnQgPSBNYXRoLm1pbigwLCBuZXdDYW52YXNMZWZ0KTtcbiAgICAgICAgICAgICAgICBjYW52YXNEYXRhLm1heExlZnQgPSBNYXRoLm1heCgwLCBuZXdDYW52YXNMZWZ0KTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmIChjYW52YXNEYXRhLmhlaWdodCA+PSBjb250YWluZXJEYXRhLmhlaWdodCkge1xuICAgICAgICAgICAgICAgIGNhbnZhc0RhdGEubWluVG9wID0gTWF0aC5taW4oMCwgbmV3Q2FudmFzVG9wKTtcbiAgICAgICAgICAgICAgICBjYW52YXNEYXRhLm1heFRvcCA9IE1hdGgubWF4KDAsIG5ld0NhbnZhc1RvcCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2FudmFzRGF0YS5taW5MZWZ0ID0gLWNhbnZhc0RhdGEud2lkdGg7XG4gICAgICAgICAgY2FudmFzRGF0YS5taW5Ub3AgPSAtY2FudmFzRGF0YS5oZWlnaHQ7XG4gICAgICAgICAgY2FudmFzRGF0YS5tYXhMZWZ0ID0gY29udGFpbmVyRGF0YS53aWR0aDtcbiAgICAgICAgICBjYW52YXNEYXRhLm1heFRvcCA9IGNvbnRhaW5lckRhdGEuaGVpZ2h0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICByZW5kZXJDYW52YXM6IGZ1bmN0aW9uIHJlbmRlckNhbnZhcyhjaGFuZ2VkLCB0cmFuc2Zvcm1lZCkge1xuICAgICAgdmFyIGNhbnZhc0RhdGEgPSB0aGlzLmNhbnZhc0RhdGEsXG4gICAgICAgICAgaW1hZ2VEYXRhID0gdGhpcy5pbWFnZURhdGE7XG5cbiAgICAgIGlmICh0cmFuc2Zvcm1lZCkge1xuICAgICAgICB2YXIgX2dldFJvdGF0ZWRTaXplcyA9IGdldFJvdGF0ZWRTaXplcyh7XG4gICAgICAgICAgd2lkdGg6IGltYWdlRGF0YS5uYXR1cmFsV2lkdGggKiBNYXRoLmFicyhpbWFnZURhdGEuc2NhbGVYIHx8IDEpLFxuICAgICAgICAgIGhlaWdodDogaW1hZ2VEYXRhLm5hdHVyYWxIZWlnaHQgKiBNYXRoLmFicyhpbWFnZURhdGEuc2NhbGVZIHx8IDEpLFxuICAgICAgICAgIGRlZ3JlZTogaW1hZ2VEYXRhLnJvdGF0ZSB8fCAwXG4gICAgICAgIH0pLFxuICAgICAgICAgICAgbmF0dXJhbFdpZHRoID0gX2dldFJvdGF0ZWRTaXplcy53aWR0aCxcbiAgICAgICAgICAgIG5hdHVyYWxIZWlnaHQgPSBfZ2V0Um90YXRlZFNpemVzLmhlaWdodDtcblxuICAgICAgICB2YXIgd2lkdGggPSBjYW52YXNEYXRhLndpZHRoICogKG5hdHVyYWxXaWR0aCAvIGNhbnZhc0RhdGEubmF0dXJhbFdpZHRoKTtcbiAgICAgICAgdmFyIGhlaWdodCA9IGNhbnZhc0RhdGEuaGVpZ2h0ICogKG5hdHVyYWxIZWlnaHQgLyBjYW52YXNEYXRhLm5hdHVyYWxIZWlnaHQpO1xuICAgICAgICBjYW52YXNEYXRhLmxlZnQgLT0gKHdpZHRoIC0gY2FudmFzRGF0YS53aWR0aCkgLyAyO1xuICAgICAgICBjYW52YXNEYXRhLnRvcCAtPSAoaGVpZ2h0IC0gY2FudmFzRGF0YS5oZWlnaHQpIC8gMjtcbiAgICAgICAgY2FudmFzRGF0YS53aWR0aCA9IHdpZHRoO1xuICAgICAgICBjYW52YXNEYXRhLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgY2FudmFzRGF0YS5hc3BlY3RSYXRpbyA9IG5hdHVyYWxXaWR0aCAvIG5hdHVyYWxIZWlnaHQ7XG4gICAgICAgIGNhbnZhc0RhdGEubmF0dXJhbFdpZHRoID0gbmF0dXJhbFdpZHRoO1xuICAgICAgICBjYW52YXNEYXRhLm5hdHVyYWxIZWlnaHQgPSBuYXR1cmFsSGVpZ2h0O1xuICAgICAgICB0aGlzLmxpbWl0Q2FudmFzKHRydWUsIGZhbHNlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNhbnZhc0RhdGEud2lkdGggPiBjYW52YXNEYXRhLm1heFdpZHRoIHx8IGNhbnZhc0RhdGEud2lkdGggPCBjYW52YXNEYXRhLm1pbldpZHRoKSB7XG4gICAgICAgIGNhbnZhc0RhdGEubGVmdCA9IGNhbnZhc0RhdGEub2xkTGVmdDtcbiAgICAgIH1cblxuICAgICAgaWYgKGNhbnZhc0RhdGEuaGVpZ2h0ID4gY2FudmFzRGF0YS5tYXhIZWlnaHQgfHwgY2FudmFzRGF0YS5oZWlnaHQgPCBjYW52YXNEYXRhLm1pbkhlaWdodCkge1xuICAgICAgICBjYW52YXNEYXRhLnRvcCA9IGNhbnZhc0RhdGEub2xkVG9wO1xuICAgICAgfVxuXG4gICAgICBjYW52YXNEYXRhLndpZHRoID0gTWF0aC5taW4oTWF0aC5tYXgoY2FudmFzRGF0YS53aWR0aCwgY2FudmFzRGF0YS5taW5XaWR0aCksIGNhbnZhc0RhdGEubWF4V2lkdGgpO1xuICAgICAgY2FudmFzRGF0YS5oZWlnaHQgPSBNYXRoLm1pbihNYXRoLm1heChjYW52YXNEYXRhLmhlaWdodCwgY2FudmFzRGF0YS5taW5IZWlnaHQpLCBjYW52YXNEYXRhLm1heEhlaWdodCk7XG4gICAgICB0aGlzLmxpbWl0Q2FudmFzKGZhbHNlLCB0cnVlKTtcbiAgICAgIGNhbnZhc0RhdGEubGVmdCA9IE1hdGgubWluKE1hdGgubWF4KGNhbnZhc0RhdGEubGVmdCwgY2FudmFzRGF0YS5taW5MZWZ0KSwgY2FudmFzRGF0YS5tYXhMZWZ0KTtcbiAgICAgIGNhbnZhc0RhdGEudG9wID0gTWF0aC5taW4oTWF0aC5tYXgoY2FudmFzRGF0YS50b3AsIGNhbnZhc0RhdGEubWluVG9wKSwgY2FudmFzRGF0YS5tYXhUb3ApO1xuICAgICAgY2FudmFzRGF0YS5vbGRMZWZ0ID0gY2FudmFzRGF0YS5sZWZ0O1xuICAgICAgY2FudmFzRGF0YS5vbGRUb3AgPSBjYW52YXNEYXRhLnRvcDtcbiAgICAgIHNldFN0eWxlKHRoaXMuY2FudmFzLCBhc3NpZ24oe1xuICAgICAgICB3aWR0aDogY2FudmFzRGF0YS53aWR0aCxcbiAgICAgICAgaGVpZ2h0OiBjYW52YXNEYXRhLmhlaWdodFxuICAgICAgfSwgZ2V0VHJhbnNmb3Jtcyh7XG4gICAgICAgIHRyYW5zbGF0ZVg6IGNhbnZhc0RhdGEubGVmdCxcbiAgICAgICAgdHJhbnNsYXRlWTogY2FudmFzRGF0YS50b3BcbiAgICAgIH0pKSk7XG4gICAgICB0aGlzLnJlbmRlckltYWdlKGNoYW5nZWQpO1xuXG4gICAgICBpZiAodGhpcy5jcm9wcGVkICYmIHRoaXMubGltaXRlZCkge1xuICAgICAgICB0aGlzLmxpbWl0Q3JvcEJveCh0cnVlLCB0cnVlKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHJlbmRlckltYWdlOiBmdW5jdGlvbiByZW5kZXJJbWFnZShjaGFuZ2VkKSB7XG4gICAgICB2YXIgY2FudmFzRGF0YSA9IHRoaXMuY2FudmFzRGF0YSxcbiAgICAgICAgICBpbWFnZURhdGEgPSB0aGlzLmltYWdlRGF0YTtcbiAgICAgIHZhciB3aWR0aCA9IGltYWdlRGF0YS5uYXR1cmFsV2lkdGggKiAoY2FudmFzRGF0YS53aWR0aCAvIGNhbnZhc0RhdGEubmF0dXJhbFdpZHRoKTtcbiAgICAgIHZhciBoZWlnaHQgPSBpbWFnZURhdGEubmF0dXJhbEhlaWdodCAqIChjYW52YXNEYXRhLmhlaWdodCAvIGNhbnZhc0RhdGEubmF0dXJhbEhlaWdodCk7XG4gICAgICBhc3NpZ24oaW1hZ2VEYXRhLCB7XG4gICAgICAgIHdpZHRoOiB3aWR0aCxcbiAgICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgIGxlZnQ6IChjYW52YXNEYXRhLndpZHRoIC0gd2lkdGgpIC8gMixcbiAgICAgICAgdG9wOiAoY2FudmFzRGF0YS5oZWlnaHQgLSBoZWlnaHQpIC8gMlxuICAgICAgfSk7XG4gICAgICBzZXRTdHlsZSh0aGlzLmltYWdlLCBhc3NpZ24oe1xuICAgICAgICB3aWR0aDogaW1hZ2VEYXRhLndpZHRoLFxuICAgICAgICBoZWlnaHQ6IGltYWdlRGF0YS5oZWlnaHRcbiAgICAgIH0sIGdldFRyYW5zZm9ybXMoYXNzaWduKHtcbiAgICAgICAgdHJhbnNsYXRlWDogaW1hZ2VEYXRhLmxlZnQsXG4gICAgICAgIHRyYW5zbGF0ZVk6IGltYWdlRGF0YS50b3BcbiAgICAgIH0sIGltYWdlRGF0YSkpKSk7XG5cbiAgICAgIGlmIChjaGFuZ2VkKSB7XG4gICAgICAgIHRoaXMub3V0cHV0KCk7XG4gICAgICB9XG4gICAgfSxcbiAgICBpbml0Q3JvcEJveDogZnVuY3Rpb24gaW5pdENyb3BCb3goKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyxcbiAgICAgICAgICBjYW52YXNEYXRhID0gdGhpcy5jYW52YXNEYXRhO1xuICAgICAgdmFyIGFzcGVjdFJhdGlvID0gb3B0aW9ucy5hc3BlY3RSYXRpbyB8fCBvcHRpb25zLmluaXRpYWxBc3BlY3RSYXRpbztcbiAgICAgIHZhciBhdXRvQ3JvcEFyZWEgPSBOdW1iZXIob3B0aW9ucy5hdXRvQ3JvcEFyZWEpIHx8IDAuODtcbiAgICAgIHZhciBjcm9wQm94RGF0YSA9IHtcbiAgICAgICAgd2lkdGg6IGNhbnZhc0RhdGEud2lkdGgsXG4gICAgICAgIGhlaWdodDogY2FudmFzRGF0YS5oZWlnaHRcbiAgICAgIH07XG5cbiAgICAgIGlmIChhc3BlY3RSYXRpbykge1xuICAgICAgICBpZiAoY2FudmFzRGF0YS5oZWlnaHQgKiBhc3BlY3RSYXRpbyA+IGNhbnZhc0RhdGEud2lkdGgpIHtcbiAgICAgICAgICBjcm9wQm94RGF0YS5oZWlnaHQgPSBjcm9wQm94RGF0YS53aWR0aCAvIGFzcGVjdFJhdGlvO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNyb3BCb3hEYXRhLndpZHRoID0gY3JvcEJveERhdGEuaGVpZ2h0ICogYXNwZWN0UmF0aW87XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5jcm9wQm94RGF0YSA9IGNyb3BCb3hEYXRhO1xuICAgICAgdGhpcy5saW1pdENyb3BCb3godHJ1ZSwgdHJ1ZSk7IC8vIEluaXRpYWxpemUgYXV0byBjcm9wIGFyZWFcblxuICAgICAgY3JvcEJveERhdGEud2lkdGggPSBNYXRoLm1pbihNYXRoLm1heChjcm9wQm94RGF0YS53aWR0aCwgY3JvcEJveERhdGEubWluV2lkdGgpLCBjcm9wQm94RGF0YS5tYXhXaWR0aCk7XG4gICAgICBjcm9wQm94RGF0YS5oZWlnaHQgPSBNYXRoLm1pbihNYXRoLm1heChjcm9wQm94RGF0YS5oZWlnaHQsIGNyb3BCb3hEYXRhLm1pbkhlaWdodCksIGNyb3BCb3hEYXRhLm1heEhlaWdodCk7IC8vIFRoZSB3aWR0aC9oZWlnaHQgb2YgYXV0byBjcm9wIGFyZWEgbXVzdCBsYXJnZSB0aGFuIFwibWluV2lkdGgvSGVpZ2h0XCJcblxuICAgICAgY3JvcEJveERhdGEud2lkdGggPSBNYXRoLm1heChjcm9wQm94RGF0YS5taW5XaWR0aCwgY3JvcEJveERhdGEud2lkdGggKiBhdXRvQ3JvcEFyZWEpO1xuICAgICAgY3JvcEJveERhdGEuaGVpZ2h0ID0gTWF0aC5tYXgoY3JvcEJveERhdGEubWluSGVpZ2h0LCBjcm9wQm94RGF0YS5oZWlnaHQgKiBhdXRvQ3JvcEFyZWEpO1xuICAgICAgY3JvcEJveERhdGEubGVmdCA9IGNhbnZhc0RhdGEubGVmdCArIChjYW52YXNEYXRhLndpZHRoIC0gY3JvcEJveERhdGEud2lkdGgpIC8gMjtcbiAgICAgIGNyb3BCb3hEYXRhLnRvcCA9IGNhbnZhc0RhdGEudG9wICsgKGNhbnZhc0RhdGEuaGVpZ2h0IC0gY3JvcEJveERhdGEuaGVpZ2h0KSAvIDI7XG4gICAgICBjcm9wQm94RGF0YS5vbGRMZWZ0ID0gY3JvcEJveERhdGEubGVmdDtcbiAgICAgIGNyb3BCb3hEYXRhLm9sZFRvcCA9IGNyb3BCb3hEYXRhLnRvcDtcbiAgICAgIHRoaXMuaW5pdGlhbENyb3BCb3hEYXRhID0gYXNzaWduKHt9LCBjcm9wQm94RGF0YSk7XG4gICAgfSxcbiAgICBsaW1pdENyb3BCb3g6IGZ1bmN0aW9uIGxpbWl0Q3JvcEJveChzaXplTGltaXRlZCwgcG9zaXRpb25MaW1pdGVkKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyxcbiAgICAgICAgICBjb250YWluZXJEYXRhID0gdGhpcy5jb250YWluZXJEYXRhLFxuICAgICAgICAgIGNhbnZhc0RhdGEgPSB0aGlzLmNhbnZhc0RhdGEsXG4gICAgICAgICAgY3JvcEJveERhdGEgPSB0aGlzLmNyb3BCb3hEYXRhLFxuICAgICAgICAgIGxpbWl0ZWQgPSB0aGlzLmxpbWl0ZWQ7XG4gICAgICB2YXIgYXNwZWN0UmF0aW8gPSBvcHRpb25zLmFzcGVjdFJhdGlvO1xuXG4gICAgICBpZiAoc2l6ZUxpbWl0ZWQpIHtcbiAgICAgICAgdmFyIG1pbkNyb3BCb3hXaWR0aCA9IE51bWJlcihvcHRpb25zLm1pbkNyb3BCb3hXaWR0aCkgfHwgMDtcbiAgICAgICAgdmFyIG1pbkNyb3BCb3hIZWlnaHQgPSBOdW1iZXIob3B0aW9ucy5taW5Dcm9wQm94SGVpZ2h0KSB8fCAwO1xuICAgICAgICB2YXIgbWF4Q3JvcEJveFdpZHRoID0gbGltaXRlZCA/IE1hdGgubWluKGNvbnRhaW5lckRhdGEud2lkdGgsIGNhbnZhc0RhdGEud2lkdGgsIGNhbnZhc0RhdGEud2lkdGggKyBjYW52YXNEYXRhLmxlZnQsIGNvbnRhaW5lckRhdGEud2lkdGggLSBjYW52YXNEYXRhLmxlZnQpIDogY29udGFpbmVyRGF0YS53aWR0aDtcbiAgICAgICAgdmFyIG1heENyb3BCb3hIZWlnaHQgPSBsaW1pdGVkID8gTWF0aC5taW4oY29udGFpbmVyRGF0YS5oZWlnaHQsIGNhbnZhc0RhdGEuaGVpZ2h0LCBjYW52YXNEYXRhLmhlaWdodCArIGNhbnZhc0RhdGEudG9wLCBjb250YWluZXJEYXRhLmhlaWdodCAtIGNhbnZhc0RhdGEudG9wKSA6IGNvbnRhaW5lckRhdGEuaGVpZ2h0OyAvLyBUaGUgbWluL21heENyb3BCb3hXaWR0aC9IZWlnaHQgbXVzdCBiZSBsZXNzIHRoYW4gY29udGFpbmVyJ3Mgd2lkdGgvaGVpZ2h0XG5cbiAgICAgICAgbWluQ3JvcEJveFdpZHRoID0gTWF0aC5taW4obWluQ3JvcEJveFdpZHRoLCBjb250YWluZXJEYXRhLndpZHRoKTtcbiAgICAgICAgbWluQ3JvcEJveEhlaWdodCA9IE1hdGgubWluKG1pbkNyb3BCb3hIZWlnaHQsIGNvbnRhaW5lckRhdGEuaGVpZ2h0KTtcblxuICAgICAgICBpZiAoYXNwZWN0UmF0aW8pIHtcbiAgICAgICAgICBpZiAobWluQ3JvcEJveFdpZHRoICYmIG1pbkNyb3BCb3hIZWlnaHQpIHtcbiAgICAgICAgICAgIGlmIChtaW5Dcm9wQm94SGVpZ2h0ICogYXNwZWN0UmF0aW8gPiBtaW5Dcm9wQm94V2lkdGgpIHtcbiAgICAgICAgICAgICAgbWluQ3JvcEJveEhlaWdodCA9IG1pbkNyb3BCb3hXaWR0aCAvIGFzcGVjdFJhdGlvO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbWluQ3JvcEJveFdpZHRoID0gbWluQ3JvcEJveEhlaWdodCAqIGFzcGVjdFJhdGlvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAobWluQ3JvcEJveFdpZHRoKSB7XG4gICAgICAgICAgICBtaW5Dcm9wQm94SGVpZ2h0ID0gbWluQ3JvcEJveFdpZHRoIC8gYXNwZWN0UmF0aW87XG4gICAgICAgICAgfSBlbHNlIGlmIChtaW5Dcm9wQm94SGVpZ2h0KSB7XG4gICAgICAgICAgICBtaW5Dcm9wQm94V2lkdGggPSBtaW5Dcm9wQm94SGVpZ2h0ICogYXNwZWN0UmF0aW87XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG1heENyb3BCb3hIZWlnaHQgKiBhc3BlY3RSYXRpbyA+IG1heENyb3BCb3hXaWR0aCkge1xuICAgICAgICAgICAgbWF4Q3JvcEJveEhlaWdodCA9IG1heENyb3BCb3hXaWR0aCAvIGFzcGVjdFJhdGlvO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtYXhDcm9wQm94V2lkdGggPSBtYXhDcm9wQm94SGVpZ2h0ICogYXNwZWN0UmF0aW87XG4gICAgICAgICAgfVxuICAgICAgICB9IC8vIFRoZSBtaW5XaWR0aC9IZWlnaHQgbXVzdCBiZSBsZXNzIHRoYW4gbWF4V2lkdGgvSGVpZ2h0XG5cblxuICAgICAgICBjcm9wQm94RGF0YS5taW5XaWR0aCA9IE1hdGgubWluKG1pbkNyb3BCb3hXaWR0aCwgbWF4Q3JvcEJveFdpZHRoKTtcbiAgICAgICAgY3JvcEJveERhdGEubWluSGVpZ2h0ID0gTWF0aC5taW4obWluQ3JvcEJveEhlaWdodCwgbWF4Q3JvcEJveEhlaWdodCk7XG4gICAgICAgIGNyb3BCb3hEYXRhLm1heFdpZHRoID0gbWF4Q3JvcEJveFdpZHRoO1xuICAgICAgICBjcm9wQm94RGF0YS5tYXhIZWlnaHQgPSBtYXhDcm9wQm94SGVpZ2h0O1xuICAgICAgfVxuXG4gICAgICBpZiAocG9zaXRpb25MaW1pdGVkKSB7XG4gICAgICAgIGlmIChsaW1pdGVkKSB7XG4gICAgICAgICAgY3JvcEJveERhdGEubWluTGVmdCA9IE1hdGgubWF4KDAsIGNhbnZhc0RhdGEubGVmdCk7XG4gICAgICAgICAgY3JvcEJveERhdGEubWluVG9wID0gTWF0aC5tYXgoMCwgY2FudmFzRGF0YS50b3ApO1xuICAgICAgICAgIGNyb3BCb3hEYXRhLm1heExlZnQgPSBNYXRoLm1pbihjb250YWluZXJEYXRhLndpZHRoLCBjYW52YXNEYXRhLmxlZnQgKyBjYW52YXNEYXRhLndpZHRoKSAtIGNyb3BCb3hEYXRhLndpZHRoO1xuICAgICAgICAgIGNyb3BCb3hEYXRhLm1heFRvcCA9IE1hdGgubWluKGNvbnRhaW5lckRhdGEuaGVpZ2h0LCBjYW52YXNEYXRhLnRvcCArIGNhbnZhc0RhdGEuaGVpZ2h0KSAtIGNyb3BCb3hEYXRhLmhlaWdodDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjcm9wQm94RGF0YS5taW5MZWZ0ID0gMDtcbiAgICAgICAgICBjcm9wQm94RGF0YS5taW5Ub3AgPSAwO1xuICAgICAgICAgIGNyb3BCb3hEYXRhLm1heExlZnQgPSBjb250YWluZXJEYXRhLndpZHRoIC0gY3JvcEJveERhdGEud2lkdGg7XG4gICAgICAgICAgY3JvcEJveERhdGEubWF4VG9wID0gY29udGFpbmVyRGF0YS5oZWlnaHQgLSBjcm9wQm94RGF0YS5oZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIHJlbmRlckNyb3BCb3g6IGZ1bmN0aW9uIHJlbmRlckNyb3BCb3goKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyxcbiAgICAgICAgICBjb250YWluZXJEYXRhID0gdGhpcy5jb250YWluZXJEYXRhLFxuICAgICAgICAgIGNyb3BCb3hEYXRhID0gdGhpcy5jcm9wQm94RGF0YTtcblxuICAgICAgaWYgKGNyb3BCb3hEYXRhLndpZHRoID4gY3JvcEJveERhdGEubWF4V2lkdGggfHwgY3JvcEJveERhdGEud2lkdGggPCBjcm9wQm94RGF0YS5taW5XaWR0aCkge1xuICAgICAgICBjcm9wQm94RGF0YS5sZWZ0ID0gY3JvcEJveERhdGEub2xkTGVmdDtcbiAgICAgIH1cblxuICAgICAgaWYgKGNyb3BCb3hEYXRhLmhlaWdodCA+IGNyb3BCb3hEYXRhLm1heEhlaWdodCB8fCBjcm9wQm94RGF0YS5oZWlnaHQgPCBjcm9wQm94RGF0YS5taW5IZWlnaHQpIHtcbiAgICAgICAgY3JvcEJveERhdGEudG9wID0gY3JvcEJveERhdGEub2xkVG9wO1xuICAgICAgfVxuXG4gICAgICBjcm9wQm94RGF0YS53aWR0aCA9IE1hdGgubWluKE1hdGgubWF4KGNyb3BCb3hEYXRhLndpZHRoLCBjcm9wQm94RGF0YS5taW5XaWR0aCksIGNyb3BCb3hEYXRhLm1heFdpZHRoKTtcbiAgICAgIGNyb3BCb3hEYXRhLmhlaWdodCA9IE1hdGgubWluKE1hdGgubWF4KGNyb3BCb3hEYXRhLmhlaWdodCwgY3JvcEJveERhdGEubWluSGVpZ2h0KSwgY3JvcEJveERhdGEubWF4SGVpZ2h0KTtcbiAgICAgIHRoaXMubGltaXRDcm9wQm94KGZhbHNlLCB0cnVlKTtcbiAgICAgIGNyb3BCb3hEYXRhLmxlZnQgPSBNYXRoLm1pbihNYXRoLm1heChjcm9wQm94RGF0YS5sZWZ0LCBjcm9wQm94RGF0YS5taW5MZWZ0KSwgY3JvcEJveERhdGEubWF4TGVmdCk7XG4gICAgICBjcm9wQm94RGF0YS50b3AgPSBNYXRoLm1pbihNYXRoLm1heChjcm9wQm94RGF0YS50b3AsIGNyb3BCb3hEYXRhLm1pblRvcCksIGNyb3BCb3hEYXRhLm1heFRvcCk7XG4gICAgICBjcm9wQm94RGF0YS5vbGRMZWZ0ID0gY3JvcEJveERhdGEubGVmdDtcbiAgICAgIGNyb3BCb3hEYXRhLm9sZFRvcCA9IGNyb3BCb3hEYXRhLnRvcDtcblxuICAgICAgaWYgKG9wdGlvbnMubW92YWJsZSAmJiBvcHRpb25zLmNyb3BCb3hNb3ZhYmxlKSB7XG4gICAgICAgIC8vIFR1cm4gdG8gbW92ZSB0aGUgY2FudmFzIHdoZW4gdGhlIGNyb3AgYm94IGlzIGVxdWFsIHRvIHRoZSBjb250YWluZXJcbiAgICAgICAgc2V0RGF0YSh0aGlzLmZhY2UsIERBVEFfQUNUSU9OLCBjcm9wQm94RGF0YS53aWR0aCA+PSBjb250YWluZXJEYXRhLndpZHRoICYmIGNyb3BCb3hEYXRhLmhlaWdodCA+PSBjb250YWluZXJEYXRhLmhlaWdodCA/IEFDVElPTl9NT1ZFIDogQUNUSU9OX0FMTCk7XG4gICAgICB9XG5cbiAgICAgIHNldFN0eWxlKHRoaXMuY3JvcEJveCwgYXNzaWduKHtcbiAgICAgICAgd2lkdGg6IGNyb3BCb3hEYXRhLndpZHRoLFxuICAgICAgICBoZWlnaHQ6IGNyb3BCb3hEYXRhLmhlaWdodFxuICAgICAgfSwgZ2V0VHJhbnNmb3Jtcyh7XG4gICAgICAgIHRyYW5zbGF0ZVg6IGNyb3BCb3hEYXRhLmxlZnQsXG4gICAgICAgIHRyYW5zbGF0ZVk6IGNyb3BCb3hEYXRhLnRvcFxuICAgICAgfSkpKTtcblxuICAgICAgaWYgKHRoaXMuY3JvcHBlZCAmJiB0aGlzLmxpbWl0ZWQpIHtcbiAgICAgICAgdGhpcy5saW1pdENhbnZhcyh0cnVlLCB0cnVlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLmRpc2FibGVkKSB7XG4gICAgICAgIHRoaXMub3V0cHV0KCk7XG4gICAgICB9XG4gICAgfSxcbiAgICBvdXRwdXQ6IGZ1bmN0aW9uIG91dHB1dCgpIHtcbiAgICAgIHRoaXMucHJldmlldygpO1xuICAgICAgZGlzcGF0Y2hFdmVudCh0aGlzLmVsZW1lbnQsIEVWRU5UX0NST1AsIHRoaXMuZ2V0RGF0YSgpKTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIHByZXZpZXcgPSB7XG4gICAgaW5pdFByZXZpZXc6IGZ1bmN0aW9uIGluaXRQcmV2aWV3KCkge1xuICAgICAgdmFyIGVsZW1lbnQgPSB0aGlzLmVsZW1lbnQsXG4gICAgICAgICAgY3Jvc3NPcmlnaW4gPSB0aGlzLmNyb3NzT3JpZ2luO1xuICAgICAgdmFyIHByZXZpZXcgPSB0aGlzLm9wdGlvbnMucHJldmlldztcbiAgICAgIHZhciB1cmwgPSBjcm9zc09yaWdpbiA/IHRoaXMuY3Jvc3NPcmlnaW5VcmwgOiB0aGlzLnVybDtcbiAgICAgIHZhciBhbHQgPSBlbGVtZW50LmFsdCB8fCAnVGhlIGltYWdlIHRvIHByZXZpZXcnO1xuICAgICAgdmFyIGltYWdlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyk7XG5cbiAgICAgIGlmIChjcm9zc09yaWdpbikge1xuICAgICAgICBpbWFnZS5jcm9zc09yaWdpbiA9IGNyb3NzT3JpZ2luO1xuICAgICAgfVxuXG4gICAgICBpbWFnZS5zcmMgPSB1cmw7XG4gICAgICBpbWFnZS5hbHQgPSBhbHQ7XG4gICAgICB0aGlzLnZpZXdCb3guYXBwZW5kQ2hpbGQoaW1hZ2UpO1xuICAgICAgdGhpcy52aWV3Qm94SW1hZ2UgPSBpbWFnZTtcblxuICAgICAgaWYgKCFwcmV2aWV3KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIHByZXZpZXdzID0gcHJldmlldztcblxuICAgICAgaWYgKHR5cGVvZiBwcmV2aWV3ID09PSAnc3RyaW5nJykge1xuICAgICAgICBwcmV2aWV3cyA9IGVsZW1lbnQub3duZXJEb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHByZXZpZXcpO1xuICAgICAgfSBlbHNlIGlmIChwcmV2aWV3LnF1ZXJ5U2VsZWN0b3IpIHtcbiAgICAgICAgcHJldmlld3MgPSBbcHJldmlld107XG4gICAgICB9XG5cbiAgICAgIHRoaXMucHJldmlld3MgPSBwcmV2aWV3cztcbiAgICAgIGZvckVhY2gocHJldmlld3MsIGZ1bmN0aW9uIChlbCkge1xuICAgICAgICB2YXIgaW1nID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyk7IC8vIFNhdmUgdGhlIG9yaWdpbmFsIHNpemUgZm9yIHJlY292ZXJcblxuICAgICAgICBzZXREYXRhKGVsLCBEQVRBX1BSRVZJRVcsIHtcbiAgICAgICAgICB3aWR0aDogZWwub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgaGVpZ2h0OiBlbC5vZmZzZXRIZWlnaHQsXG4gICAgICAgICAgaHRtbDogZWwuaW5uZXJIVE1MXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChjcm9zc09yaWdpbikge1xuICAgICAgICAgIGltZy5jcm9zc09yaWdpbiA9IGNyb3NzT3JpZ2luO1xuICAgICAgICB9XG5cbiAgICAgICAgaW1nLnNyYyA9IHVybDtcbiAgICAgICAgaW1nLmFsdCA9IGFsdDtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIE92ZXJyaWRlIGltZyBlbGVtZW50IHN0eWxlc1xuICAgICAgICAgKiBBZGQgYGRpc3BsYXk6YmxvY2tgIHRvIGF2b2lkIG1hcmdpbiB0b3AgaXNzdWVcbiAgICAgICAgICogQWRkIGBoZWlnaHQ6YXV0b2AgdG8gb3ZlcnJpZGUgYGhlaWdodGAgYXR0cmlidXRlIG9uIElFOFxuICAgICAgICAgKiAoT2NjdXIgb25seSB3aGVuIG1hcmdpbi10b3AgPD0gLWhlaWdodClcbiAgICAgICAgICovXG5cbiAgICAgICAgaW1nLnN0eWxlLmNzc1RleHQgPSAnZGlzcGxheTpibG9jazsnICsgJ3dpZHRoOjEwMCU7JyArICdoZWlnaHQ6YXV0bzsnICsgJ21pbi13aWR0aDowIWltcG9ydGFudDsnICsgJ21pbi1oZWlnaHQ6MCFpbXBvcnRhbnQ7JyArICdtYXgtd2lkdGg6bm9uZSFpbXBvcnRhbnQ7JyArICdtYXgtaGVpZ2h0Om5vbmUhaW1wb3J0YW50OycgKyAnaW1hZ2Utb3JpZW50YXRpb246MGRlZyFpbXBvcnRhbnQ7XCInO1xuICAgICAgICBlbC5pbm5lckhUTUwgPSAnJztcbiAgICAgICAgZWwuYXBwZW5kQ2hpbGQoaW1nKTtcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgcmVzZXRQcmV2aWV3OiBmdW5jdGlvbiByZXNldFByZXZpZXcoKSB7XG4gICAgICBmb3JFYWNoKHRoaXMucHJldmlld3MsIGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIHZhciBkYXRhID0gZ2V0RGF0YShlbGVtZW50LCBEQVRBX1BSRVZJRVcpO1xuICAgICAgICBzZXRTdHlsZShlbGVtZW50LCB7XG4gICAgICAgICAgd2lkdGg6IGRhdGEud2lkdGgsXG4gICAgICAgICAgaGVpZ2h0OiBkYXRhLmhlaWdodFxuICAgICAgICB9KTtcbiAgICAgICAgZWxlbWVudC5pbm5lckhUTUwgPSBkYXRhLmh0bWw7XG4gICAgICAgIHJlbW92ZURhdGEoZWxlbWVudCwgREFUQV9QUkVWSUVXKTtcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgcHJldmlldzogZnVuY3Rpb24gcHJldmlldygpIHtcbiAgICAgIHZhciBpbWFnZURhdGEgPSB0aGlzLmltYWdlRGF0YSxcbiAgICAgICAgICBjYW52YXNEYXRhID0gdGhpcy5jYW52YXNEYXRhLFxuICAgICAgICAgIGNyb3BCb3hEYXRhID0gdGhpcy5jcm9wQm94RGF0YTtcbiAgICAgIHZhciBjcm9wQm94V2lkdGggPSBjcm9wQm94RGF0YS53aWR0aCxcbiAgICAgICAgICBjcm9wQm94SGVpZ2h0ID0gY3JvcEJveERhdGEuaGVpZ2h0O1xuICAgICAgdmFyIHdpZHRoID0gaW1hZ2VEYXRhLndpZHRoLFxuICAgICAgICAgIGhlaWdodCA9IGltYWdlRGF0YS5oZWlnaHQ7XG4gICAgICB2YXIgbGVmdCA9IGNyb3BCb3hEYXRhLmxlZnQgLSBjYW52YXNEYXRhLmxlZnQgLSBpbWFnZURhdGEubGVmdDtcbiAgICAgIHZhciB0b3AgPSBjcm9wQm94RGF0YS50b3AgLSBjYW52YXNEYXRhLnRvcCAtIGltYWdlRGF0YS50b3A7XG5cbiAgICAgIGlmICghdGhpcy5jcm9wcGVkIHx8IHRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzZXRTdHlsZSh0aGlzLnZpZXdCb3hJbWFnZSwgYXNzaWduKHtcbiAgICAgICAgd2lkdGg6IHdpZHRoLFxuICAgICAgICBoZWlnaHQ6IGhlaWdodFxuICAgICAgfSwgZ2V0VHJhbnNmb3Jtcyhhc3NpZ24oe1xuICAgICAgICB0cmFuc2xhdGVYOiAtbGVmdCxcbiAgICAgICAgdHJhbnNsYXRlWTogLXRvcFxuICAgICAgfSwgaW1hZ2VEYXRhKSkpKTtcbiAgICAgIGZvckVhY2godGhpcy5wcmV2aWV3cywgZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIGRhdGEgPSBnZXREYXRhKGVsZW1lbnQsIERBVEFfUFJFVklFVyk7XG4gICAgICAgIHZhciBvcmlnaW5hbFdpZHRoID0gZGF0YS53aWR0aDtcbiAgICAgICAgdmFyIG9yaWdpbmFsSGVpZ2h0ID0gZGF0YS5oZWlnaHQ7XG4gICAgICAgIHZhciBuZXdXaWR0aCA9IG9yaWdpbmFsV2lkdGg7XG4gICAgICAgIHZhciBuZXdIZWlnaHQgPSBvcmlnaW5hbEhlaWdodDtcbiAgICAgICAgdmFyIHJhdGlvID0gMTtcblxuICAgICAgICBpZiAoY3JvcEJveFdpZHRoKSB7XG4gICAgICAgICAgcmF0aW8gPSBvcmlnaW5hbFdpZHRoIC8gY3JvcEJveFdpZHRoO1xuICAgICAgICAgIG5ld0hlaWdodCA9IGNyb3BCb3hIZWlnaHQgKiByYXRpbztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjcm9wQm94SGVpZ2h0ICYmIG5ld0hlaWdodCA+IG9yaWdpbmFsSGVpZ2h0KSB7XG4gICAgICAgICAgcmF0aW8gPSBvcmlnaW5hbEhlaWdodCAvIGNyb3BCb3hIZWlnaHQ7XG4gICAgICAgICAgbmV3V2lkdGggPSBjcm9wQm94V2lkdGggKiByYXRpbztcbiAgICAgICAgICBuZXdIZWlnaHQgPSBvcmlnaW5hbEhlaWdodDtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldFN0eWxlKGVsZW1lbnQsIHtcbiAgICAgICAgICB3aWR0aDogbmV3V2lkdGgsXG4gICAgICAgICAgaGVpZ2h0OiBuZXdIZWlnaHRcbiAgICAgICAgfSk7XG4gICAgICAgIHNldFN0eWxlKGVsZW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2ltZycpWzBdLCBhc3NpZ24oe1xuICAgICAgICAgIHdpZHRoOiB3aWR0aCAqIHJhdGlvLFxuICAgICAgICAgIGhlaWdodDogaGVpZ2h0ICogcmF0aW9cbiAgICAgICAgfSwgZ2V0VHJhbnNmb3Jtcyhhc3NpZ24oe1xuICAgICAgICAgIHRyYW5zbGF0ZVg6IC1sZWZ0ICogcmF0aW8sXG4gICAgICAgICAgdHJhbnNsYXRlWTogLXRvcCAqIHJhdGlvXG4gICAgICAgIH0sIGltYWdlRGF0YSkpKSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIGV2ZW50cyA9IHtcbiAgICBiaW5kOiBmdW5jdGlvbiBiaW5kKCkge1xuICAgICAgdmFyIGVsZW1lbnQgPSB0aGlzLmVsZW1lbnQsXG4gICAgICAgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyxcbiAgICAgICAgICBjcm9wcGVyID0gdGhpcy5jcm9wcGVyO1xuXG4gICAgICBpZiAoaXNGdW5jdGlvbihvcHRpb25zLmNyb3BzdGFydCkpIHtcbiAgICAgICAgYWRkTGlzdGVuZXIoZWxlbWVudCwgRVZFTlRfQ1JPUF9TVEFSVCwgb3B0aW9ucy5jcm9wc3RhcnQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNGdW5jdGlvbihvcHRpb25zLmNyb3Btb3ZlKSkge1xuICAgICAgICBhZGRMaXN0ZW5lcihlbGVtZW50LCBFVkVOVF9DUk9QX01PVkUsIG9wdGlvbnMuY3JvcG1vdmUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNGdW5jdGlvbihvcHRpb25zLmNyb3BlbmQpKSB7XG4gICAgICAgIGFkZExpc3RlbmVyKGVsZW1lbnQsIEVWRU5UX0NST1BfRU5ELCBvcHRpb25zLmNyb3BlbmQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNGdW5jdGlvbihvcHRpb25zLmNyb3ApKSB7XG4gICAgICAgIGFkZExpc3RlbmVyKGVsZW1lbnQsIEVWRU5UX0NST1AsIG9wdGlvbnMuY3JvcCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0Z1bmN0aW9uKG9wdGlvbnMuem9vbSkpIHtcbiAgICAgICAgYWRkTGlzdGVuZXIoZWxlbWVudCwgRVZFTlRfWk9PTSwgb3B0aW9ucy56b29tKTtcbiAgICAgIH1cblxuICAgICAgYWRkTGlzdGVuZXIoY3JvcHBlciwgRVZFTlRfUE9JTlRFUl9ET1dOLCB0aGlzLm9uQ3JvcFN0YXJ0ID0gdGhpcy5jcm9wU3RhcnQuYmluZCh0aGlzKSk7XG5cbiAgICAgIGlmIChvcHRpb25zLnpvb21hYmxlICYmIG9wdGlvbnMuem9vbU9uV2hlZWwpIHtcbiAgICAgICAgYWRkTGlzdGVuZXIoY3JvcHBlciwgRVZFTlRfV0hFRUwsIHRoaXMub25XaGVlbCA9IHRoaXMud2hlZWwuYmluZCh0aGlzKSwge1xuICAgICAgICAgIHBhc3NpdmU6IGZhbHNlLFxuICAgICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLnRvZ2dsZURyYWdNb2RlT25EYmxjbGljaykge1xuICAgICAgICBhZGRMaXN0ZW5lcihjcm9wcGVyLCBFVkVOVF9EQkxDTElDSywgdGhpcy5vbkRibGNsaWNrID0gdGhpcy5kYmxjbGljay5iaW5kKHRoaXMpKTtcbiAgICAgIH1cblxuICAgICAgYWRkTGlzdGVuZXIoZWxlbWVudC5vd25lckRvY3VtZW50LCBFVkVOVF9QT0lOVEVSX01PVkUsIHRoaXMub25Dcm9wTW92ZSA9IHRoaXMuY3JvcE1vdmUuYmluZCh0aGlzKSk7XG4gICAgICBhZGRMaXN0ZW5lcihlbGVtZW50Lm93bmVyRG9jdW1lbnQsIEVWRU5UX1BPSU5URVJfVVAsIHRoaXMub25Dcm9wRW5kID0gdGhpcy5jcm9wRW5kLmJpbmQodGhpcykpO1xuXG4gICAgICBpZiAob3B0aW9ucy5yZXNwb25zaXZlKSB7XG4gICAgICAgIGFkZExpc3RlbmVyKHdpbmRvdywgRVZFTlRfUkVTSVpFLCB0aGlzLm9uUmVzaXplID0gdGhpcy5yZXNpemUuYmluZCh0aGlzKSk7XG4gICAgICB9XG4gICAgfSxcbiAgICB1bmJpbmQ6IGZ1bmN0aW9uIHVuYmluZCgpIHtcbiAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5lbGVtZW50LFxuICAgICAgICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG4gICAgICAgICAgY3JvcHBlciA9IHRoaXMuY3JvcHBlcjtcblxuICAgICAgaWYgKGlzRnVuY3Rpb24ob3B0aW9ucy5jcm9wc3RhcnQpKSB7XG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGVsZW1lbnQsIEVWRU5UX0NST1BfU1RBUlQsIG9wdGlvbnMuY3JvcHN0YXJ0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzRnVuY3Rpb24ob3B0aW9ucy5jcm9wbW92ZSkpIHtcbiAgICAgICAgcmVtb3ZlTGlzdGVuZXIoZWxlbWVudCwgRVZFTlRfQ1JPUF9NT1ZFLCBvcHRpb25zLmNyb3Btb3ZlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzRnVuY3Rpb24ob3B0aW9ucy5jcm9wZW5kKSkge1xuICAgICAgICByZW1vdmVMaXN0ZW5lcihlbGVtZW50LCBFVkVOVF9DUk9QX0VORCwgb3B0aW9ucy5jcm9wZW5kKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzRnVuY3Rpb24ob3B0aW9ucy5jcm9wKSkge1xuICAgICAgICByZW1vdmVMaXN0ZW5lcihlbGVtZW50LCBFVkVOVF9DUk9QLCBvcHRpb25zLmNyb3ApO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNGdW5jdGlvbihvcHRpb25zLnpvb20pKSB7XG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGVsZW1lbnQsIEVWRU5UX1pPT00sIG9wdGlvbnMuem9vbSk7XG4gICAgICB9XG5cbiAgICAgIHJlbW92ZUxpc3RlbmVyKGNyb3BwZXIsIEVWRU5UX1BPSU5URVJfRE9XTiwgdGhpcy5vbkNyb3BTdGFydCk7XG5cbiAgICAgIGlmIChvcHRpb25zLnpvb21hYmxlICYmIG9wdGlvbnMuem9vbU9uV2hlZWwpIHtcbiAgICAgICAgcmVtb3ZlTGlzdGVuZXIoY3JvcHBlciwgRVZFTlRfV0hFRUwsIHRoaXMub25XaGVlbCwge1xuICAgICAgICAgIHBhc3NpdmU6IGZhbHNlLFxuICAgICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLnRvZ2dsZURyYWdNb2RlT25EYmxjbGljaykge1xuICAgICAgICByZW1vdmVMaXN0ZW5lcihjcm9wcGVyLCBFVkVOVF9EQkxDTElDSywgdGhpcy5vbkRibGNsaWNrKTtcbiAgICAgIH1cblxuICAgICAgcmVtb3ZlTGlzdGVuZXIoZWxlbWVudC5vd25lckRvY3VtZW50LCBFVkVOVF9QT0lOVEVSX01PVkUsIHRoaXMub25Dcm9wTW92ZSk7XG4gICAgICByZW1vdmVMaXN0ZW5lcihlbGVtZW50Lm93bmVyRG9jdW1lbnQsIEVWRU5UX1BPSU5URVJfVVAsIHRoaXMub25Dcm9wRW5kKTtcblxuICAgICAgaWYgKG9wdGlvbnMucmVzcG9uc2l2ZSkge1xuICAgICAgICByZW1vdmVMaXN0ZW5lcih3aW5kb3csIEVWRU5UX1JFU0laRSwgdGhpcy5vblJlc2l6ZSk7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHZhciBoYW5kbGVycyA9IHtcbiAgICByZXNpemU6IGZ1bmN0aW9uIHJlc2l6ZSgpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICAgIGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyLFxuICAgICAgICAgIGNvbnRhaW5lckRhdGEgPSB0aGlzLmNvbnRhaW5lckRhdGE7XG4gICAgICB2YXIgbWluQ29udGFpbmVyV2lkdGggPSBOdW1iZXIob3B0aW9ucy5taW5Db250YWluZXJXaWR0aCkgfHwgTUlOX0NPTlRBSU5FUl9XSURUSDtcbiAgICAgIHZhciBtaW5Db250YWluZXJIZWlnaHQgPSBOdW1iZXIob3B0aW9ucy5taW5Db250YWluZXJIZWlnaHQpIHx8IE1JTl9DT05UQUlORVJfSEVJR0hUO1xuXG4gICAgICBpZiAodGhpcy5kaXNhYmxlZCB8fCBjb250YWluZXJEYXRhLndpZHRoIDw9IG1pbkNvbnRhaW5lcldpZHRoIHx8IGNvbnRhaW5lckRhdGEuaGVpZ2h0IDw9IG1pbkNvbnRhaW5lckhlaWdodCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciByYXRpbyA9IGNvbnRhaW5lci5vZmZzZXRXaWR0aCAvIGNvbnRhaW5lckRhdGEud2lkdGg7IC8vIFJlc2l6ZSB3aGVuIHdpZHRoIGNoYW5nZWQgb3IgaGVpZ2h0IGNoYW5nZWRcblxuICAgICAgaWYgKHJhdGlvICE9PSAxIHx8IGNvbnRhaW5lci5vZmZzZXRIZWlnaHQgIT09IGNvbnRhaW5lckRhdGEuaGVpZ2h0KSB7XG4gICAgICAgIHZhciBjYW52YXNEYXRhO1xuICAgICAgICB2YXIgY3JvcEJveERhdGE7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMucmVzdG9yZSkge1xuICAgICAgICAgIGNhbnZhc0RhdGEgPSB0aGlzLmdldENhbnZhc0RhdGEoKTtcbiAgICAgICAgICBjcm9wQm94RGF0YSA9IHRoaXMuZ2V0Q3JvcEJveERhdGEoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucmVuZGVyKCk7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMucmVzdG9yZSkge1xuICAgICAgICAgIHRoaXMuc2V0Q2FudmFzRGF0YShmb3JFYWNoKGNhbnZhc0RhdGEsIGZ1bmN0aW9uIChuLCBpKSB7XG4gICAgICAgICAgICBjYW52YXNEYXRhW2ldID0gbiAqIHJhdGlvO1xuICAgICAgICAgIH0pKTtcbiAgICAgICAgICB0aGlzLnNldENyb3BCb3hEYXRhKGZvckVhY2goY3JvcEJveERhdGEsIGZ1bmN0aW9uIChuLCBpKSB7XG4gICAgICAgICAgICBjcm9wQm94RGF0YVtpXSA9IG4gKiByYXRpbztcbiAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIGRibGNsaWNrOiBmdW5jdGlvbiBkYmxjbGljaygpIHtcbiAgICAgIGlmICh0aGlzLmRpc2FibGVkIHx8IHRoaXMub3B0aW9ucy5kcmFnTW9kZSA9PT0gRFJBR19NT0RFX05PTkUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnNldERyYWdNb2RlKGhhc0NsYXNzKHRoaXMuZHJhZ0JveCwgQ0xBU1NfQ1JPUCkgPyBEUkFHX01PREVfTU9WRSA6IERSQUdfTU9ERV9DUk9QKTtcbiAgICB9LFxuICAgIHdoZWVsOiBmdW5jdGlvbiB3aGVlbChldmVudCkge1xuICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgdmFyIHJhdGlvID0gTnVtYmVyKHRoaXMub3B0aW9ucy53aGVlbFpvb21SYXRpbykgfHwgMC4xO1xuICAgICAgdmFyIGRlbHRhID0gMTtcblxuICAgICAgaWYgKHRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOyAvLyBMaW1pdCB3aGVlbCBzcGVlZCB0byBwcmV2ZW50IHpvb20gdG9vIGZhc3QgKCMyMSlcblxuICAgICAgaWYgKHRoaXMud2hlZWxpbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLndoZWVsaW5nID0gdHJ1ZTtcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBfdGhpcy53aGVlbGluZyA9IGZhbHNlO1xuICAgICAgfSwgNTApO1xuXG4gICAgICBpZiAoZXZlbnQuZGVsdGFZKSB7XG4gICAgICAgIGRlbHRhID0gZXZlbnQuZGVsdGFZID4gMCA/IDEgOiAtMTtcbiAgICAgIH0gZWxzZSBpZiAoZXZlbnQud2hlZWxEZWx0YSkge1xuICAgICAgICBkZWx0YSA9IC1ldmVudC53aGVlbERlbHRhIC8gMTIwO1xuICAgICAgfSBlbHNlIGlmIChldmVudC5kZXRhaWwpIHtcbiAgICAgICAgZGVsdGEgPSBldmVudC5kZXRhaWwgPiAwID8gMSA6IC0xO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnpvb20oLWRlbHRhICogcmF0aW8sIGV2ZW50KTtcbiAgICB9LFxuICAgIGNyb3BTdGFydDogZnVuY3Rpb24gY3JvcFN0YXJ0KGV2ZW50KSB7XG4gICAgICB2YXIgYnV0dG9ucyA9IGV2ZW50LmJ1dHRvbnMsXG4gICAgICAgICAgYnV0dG9uID0gZXZlbnQuYnV0dG9uO1xuXG4gICAgICBpZiAodGhpcy5kaXNhYmxlZCAvLyBIYW5kbGUgbW91c2UgZXZlbnQgYW5kIHBvaW50ZXIgZXZlbnQgYW5kIGlnbm9yZSB0b3VjaCBldmVudFxuICAgICAgfHwgKGV2ZW50LnR5cGUgPT09ICdtb3VzZWRvd24nIHx8IGV2ZW50LnR5cGUgPT09ICdwb2ludGVyZG93bicgJiYgZXZlbnQucG9pbnRlclR5cGUgPT09ICdtb3VzZScpICYmICggLy8gTm8gcHJpbWFyeSBidXR0b24gKFVzdWFsbHkgdGhlIGxlZnQgYnV0dG9uKVxuICAgICAgaXNOdW1iZXIoYnV0dG9ucykgJiYgYnV0dG9ucyAhPT0gMSB8fCBpc051bWJlcihidXR0b24pICYmIGJ1dHRvbiAhPT0gMCAvLyBPcGVuIGNvbnRleHQgbWVudVxuICAgICAgfHwgZXZlbnQuY3RybEtleSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyxcbiAgICAgICAgICBwb2ludGVycyA9IHRoaXMucG9pbnRlcnM7XG4gICAgICB2YXIgYWN0aW9uO1xuXG4gICAgICBpZiAoZXZlbnQuY2hhbmdlZFRvdWNoZXMpIHtcbiAgICAgICAgLy8gSGFuZGxlIHRvdWNoIGV2ZW50XG4gICAgICAgIGZvckVhY2goZXZlbnQuY2hhbmdlZFRvdWNoZXMsIGZ1bmN0aW9uICh0b3VjaCkge1xuICAgICAgICAgIHBvaW50ZXJzW3RvdWNoLmlkZW50aWZpZXJdID0gZ2V0UG9pbnRlcih0b3VjaCk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSGFuZGxlIG1vdXNlIGV2ZW50IGFuZCBwb2ludGVyIGV2ZW50XG4gICAgICAgIHBvaW50ZXJzW2V2ZW50LnBvaW50ZXJJZCB8fCAwXSA9IGdldFBvaW50ZXIoZXZlbnQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoT2JqZWN0LmtleXMocG9pbnRlcnMpLmxlbmd0aCA+IDEgJiYgb3B0aW9ucy56b29tYWJsZSAmJiBvcHRpb25zLnpvb21PblRvdWNoKSB7XG4gICAgICAgIGFjdGlvbiA9IEFDVElPTl9aT09NO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWN0aW9uID0gZ2V0RGF0YShldmVudC50YXJnZXQsIERBVEFfQUNUSU9OKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFSRUdFWFBfQUNUSU9OUy50ZXN0KGFjdGlvbikpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZGlzcGF0Y2hFdmVudCh0aGlzLmVsZW1lbnQsIEVWRU5UX0NST1BfU1RBUlQsIHtcbiAgICAgICAgb3JpZ2luYWxFdmVudDogZXZlbnQsXG4gICAgICAgIGFjdGlvbjogYWN0aW9uXG4gICAgICB9KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBUaGlzIGxpbmUgaXMgcmVxdWlyZWQgZm9yIHByZXZlbnRpbmcgcGFnZSB6b29taW5nIGluIGlPUyBicm93c2Vyc1xuXG5cbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB0aGlzLmFjdGlvbiA9IGFjdGlvbjtcbiAgICAgIHRoaXMuY3JvcHBpbmcgPSBmYWxzZTtcblxuICAgICAgaWYgKGFjdGlvbiA9PT0gQUNUSU9OX0NST1ApIHtcbiAgICAgICAgdGhpcy5jcm9wcGluZyA9IHRydWU7XG4gICAgICAgIGFkZENsYXNzKHRoaXMuZHJhZ0JveCwgQ0xBU1NfTU9EQUwpO1xuICAgICAgfVxuICAgIH0sXG4gICAgY3JvcE1vdmU6IGZ1bmN0aW9uIGNyb3BNb3ZlKGV2ZW50KSB7XG4gICAgICB2YXIgYWN0aW9uID0gdGhpcy5hY3Rpb247XG5cbiAgICAgIGlmICh0aGlzLmRpc2FibGVkIHx8ICFhY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgcG9pbnRlcnMgPSB0aGlzLnBvaW50ZXJzO1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgaWYgKGRpc3BhdGNoRXZlbnQodGhpcy5lbGVtZW50LCBFVkVOVF9DUk9QX01PVkUsIHtcbiAgICAgICAgb3JpZ2luYWxFdmVudDogZXZlbnQsXG4gICAgICAgIGFjdGlvbjogYWN0aW9uXG4gICAgICB9KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnQuY2hhbmdlZFRvdWNoZXMpIHtcbiAgICAgICAgZm9yRWFjaChldmVudC5jaGFuZ2VkVG91Y2hlcywgZnVuY3Rpb24gKHRvdWNoKSB7XG4gICAgICAgICAgLy8gVGhlIGZpcnN0IHBhcmFtZXRlciBzaG91bGQgbm90IGJlIHVuZGVmaW5lZCAoIzQzMilcbiAgICAgICAgICBhc3NpZ24ocG9pbnRlcnNbdG91Y2guaWRlbnRpZmllcl0gfHwge30sIGdldFBvaW50ZXIodG91Y2gsIHRydWUpKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhc3NpZ24ocG9pbnRlcnNbZXZlbnQucG9pbnRlcklkIHx8IDBdIHx8IHt9LCBnZXRQb2ludGVyKGV2ZW50LCB0cnVlKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY2hhbmdlKGV2ZW50KTtcbiAgICB9LFxuICAgIGNyb3BFbmQ6IGZ1bmN0aW9uIGNyb3BFbmQoZXZlbnQpIHtcbiAgICAgIGlmICh0aGlzLmRpc2FibGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIGFjdGlvbiA9IHRoaXMuYWN0aW9uLFxuICAgICAgICAgIHBvaW50ZXJzID0gdGhpcy5wb2ludGVycztcblxuICAgICAgaWYgKGV2ZW50LmNoYW5nZWRUb3VjaGVzKSB7XG4gICAgICAgIGZvckVhY2goZXZlbnQuY2hhbmdlZFRvdWNoZXMsIGZ1bmN0aW9uICh0b3VjaCkge1xuICAgICAgICAgIGRlbGV0ZSBwb2ludGVyc1t0b3VjaC5pZGVudGlmaWVyXTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZWxldGUgcG9pbnRlcnNbZXZlbnQucG9pbnRlcklkIHx8IDBdO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWFjdGlvbikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIGlmICghT2JqZWN0LmtleXMocG9pbnRlcnMpLmxlbmd0aCkge1xuICAgICAgICB0aGlzLmFjdGlvbiA9ICcnO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5jcm9wcGluZykge1xuICAgICAgICB0aGlzLmNyb3BwaW5nID0gZmFsc2U7XG4gICAgICAgIHRvZ2dsZUNsYXNzKHRoaXMuZHJhZ0JveCwgQ0xBU1NfTU9EQUwsIHRoaXMuY3JvcHBlZCAmJiB0aGlzLm9wdGlvbnMubW9kYWwpO1xuICAgICAgfVxuXG4gICAgICBkaXNwYXRjaEV2ZW50KHRoaXMuZWxlbWVudCwgRVZFTlRfQ1JPUF9FTkQsIHtcbiAgICAgICAgb3JpZ2luYWxFdmVudDogZXZlbnQsXG4gICAgICAgIGFjdGlvbjogYWN0aW9uXG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgdmFyIGNoYW5nZSA9IHtcbiAgICBjaGFuZ2U6IGZ1bmN0aW9uIGNoYW5nZShldmVudCkge1xuICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG4gICAgICAgICAgY2FudmFzRGF0YSA9IHRoaXMuY2FudmFzRGF0YSxcbiAgICAgICAgICBjb250YWluZXJEYXRhID0gdGhpcy5jb250YWluZXJEYXRhLFxuICAgICAgICAgIGNyb3BCb3hEYXRhID0gdGhpcy5jcm9wQm94RGF0YSxcbiAgICAgICAgICBwb2ludGVycyA9IHRoaXMucG9pbnRlcnM7XG4gICAgICB2YXIgYWN0aW9uID0gdGhpcy5hY3Rpb247XG4gICAgICB2YXIgYXNwZWN0UmF0aW8gPSBvcHRpb25zLmFzcGVjdFJhdGlvO1xuICAgICAgdmFyIGxlZnQgPSBjcm9wQm94RGF0YS5sZWZ0LFxuICAgICAgICAgIHRvcCA9IGNyb3BCb3hEYXRhLnRvcCxcbiAgICAgICAgICB3aWR0aCA9IGNyb3BCb3hEYXRhLndpZHRoLFxuICAgICAgICAgIGhlaWdodCA9IGNyb3BCb3hEYXRhLmhlaWdodDtcbiAgICAgIHZhciByaWdodCA9IGxlZnQgKyB3aWR0aDtcbiAgICAgIHZhciBib3R0b20gPSB0b3AgKyBoZWlnaHQ7XG4gICAgICB2YXIgbWluTGVmdCA9IDA7XG4gICAgICB2YXIgbWluVG9wID0gMDtcbiAgICAgIHZhciBtYXhXaWR0aCA9IGNvbnRhaW5lckRhdGEud2lkdGg7XG4gICAgICB2YXIgbWF4SGVpZ2h0ID0gY29udGFpbmVyRGF0YS5oZWlnaHQ7XG4gICAgICB2YXIgcmVuZGVyYWJsZSA9IHRydWU7XG4gICAgICB2YXIgb2Zmc2V0OyAvLyBMb2NraW5nIGFzcGVjdCByYXRpbyBpbiBcImZyZWUgbW9kZVwiIGJ5IGhvbGRpbmcgc2hpZnQga2V5XG5cbiAgICAgIGlmICghYXNwZWN0UmF0aW8gJiYgZXZlbnQuc2hpZnRLZXkpIHtcbiAgICAgICAgYXNwZWN0UmF0aW8gPSB3aWR0aCAmJiBoZWlnaHQgPyB3aWR0aCAvIGhlaWdodCA6IDE7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmxpbWl0ZWQpIHtcbiAgICAgICAgbWluTGVmdCA9IGNyb3BCb3hEYXRhLm1pbkxlZnQ7XG4gICAgICAgIG1pblRvcCA9IGNyb3BCb3hEYXRhLm1pblRvcDtcbiAgICAgICAgbWF4V2lkdGggPSBtaW5MZWZ0ICsgTWF0aC5taW4oY29udGFpbmVyRGF0YS53aWR0aCwgY2FudmFzRGF0YS53aWR0aCwgY2FudmFzRGF0YS5sZWZ0ICsgY2FudmFzRGF0YS53aWR0aCk7XG4gICAgICAgIG1heEhlaWdodCA9IG1pblRvcCArIE1hdGgubWluKGNvbnRhaW5lckRhdGEuaGVpZ2h0LCBjYW52YXNEYXRhLmhlaWdodCwgY2FudmFzRGF0YS50b3AgKyBjYW52YXNEYXRhLmhlaWdodCk7XG4gICAgICB9XG5cbiAgICAgIHZhciBwb2ludGVyID0gcG9pbnRlcnNbT2JqZWN0LmtleXMocG9pbnRlcnMpWzBdXTtcbiAgICAgIHZhciByYW5nZSA9IHtcbiAgICAgICAgeDogcG9pbnRlci5lbmRYIC0gcG9pbnRlci5zdGFydFgsXG4gICAgICAgIHk6IHBvaW50ZXIuZW5kWSAtIHBvaW50ZXIuc3RhcnRZXG4gICAgICB9O1xuXG4gICAgICB2YXIgY2hlY2sgPSBmdW5jdGlvbiBjaGVjayhzaWRlKSB7XG4gICAgICAgIHN3aXRjaCAoc2lkZSkge1xuICAgICAgICAgIGNhc2UgQUNUSU9OX0VBU1Q6XG4gICAgICAgICAgICBpZiAocmlnaHQgKyByYW5nZS54ID4gbWF4V2lkdGgpIHtcbiAgICAgICAgICAgICAgcmFuZ2UueCA9IG1heFdpZHRoIC0gcmlnaHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSBBQ1RJT05fV0VTVDpcbiAgICAgICAgICAgIGlmIChsZWZ0ICsgcmFuZ2UueCA8IG1pbkxlZnQpIHtcbiAgICAgICAgICAgICAgcmFuZ2UueCA9IG1pbkxlZnQgLSBsZWZ0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGNhc2UgQUNUSU9OX05PUlRIOlxuICAgICAgICAgICAgaWYgKHRvcCArIHJhbmdlLnkgPCBtaW5Ub3ApIHtcbiAgICAgICAgICAgICAgcmFuZ2UueSA9IG1pblRvcCAtIHRvcDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlIEFDVElPTl9TT1VUSDpcbiAgICAgICAgICAgIGlmIChib3R0b20gKyByYW5nZS55ID4gbWF4SGVpZ2h0KSB7XG4gICAgICAgICAgICAgIHJhbmdlLnkgPSBtYXhIZWlnaHQgLSBib3R0b207XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgLy8gTW92ZSBjcm9wIGJveFxuICAgICAgICBjYXNlIEFDVElPTl9BTEw6XG4gICAgICAgICAgbGVmdCArPSByYW5nZS54O1xuICAgICAgICAgIHRvcCArPSByYW5nZS55O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICAvLyBSZXNpemUgY3JvcCBib3hcblxuICAgICAgICBjYXNlIEFDVElPTl9FQVNUOlxuICAgICAgICAgIGlmIChyYW5nZS54ID49IDAgJiYgKHJpZ2h0ID49IG1heFdpZHRoIHx8IGFzcGVjdFJhdGlvICYmICh0b3AgPD0gbWluVG9wIHx8IGJvdHRvbSA+PSBtYXhIZWlnaHQpKSkge1xuICAgICAgICAgICAgcmVuZGVyYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY2hlY2soQUNUSU9OX0VBU1QpO1xuICAgICAgICAgIHdpZHRoICs9IHJhbmdlLng7XG5cbiAgICAgICAgICBpZiAod2lkdGggPCAwKSB7XG4gICAgICAgICAgICBhY3Rpb24gPSBBQ1RJT05fV0VTVDtcbiAgICAgICAgICAgIHdpZHRoID0gLXdpZHRoO1xuICAgICAgICAgICAgbGVmdCAtPSB3aWR0aDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoYXNwZWN0UmF0aW8pIHtcbiAgICAgICAgICAgIGhlaWdodCA9IHdpZHRoIC8gYXNwZWN0UmF0aW87XG4gICAgICAgICAgICB0b3AgKz0gKGNyb3BCb3hEYXRhLmhlaWdodCAtIGhlaWdodCkgLyAyO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgQUNUSU9OX05PUlRIOlxuICAgICAgICAgIGlmIChyYW5nZS55IDw9IDAgJiYgKHRvcCA8PSBtaW5Ub3AgfHwgYXNwZWN0UmF0aW8gJiYgKGxlZnQgPD0gbWluTGVmdCB8fCByaWdodCA+PSBtYXhXaWR0aCkpKSB7XG4gICAgICAgICAgICByZW5kZXJhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjaGVjayhBQ1RJT05fTk9SVEgpO1xuICAgICAgICAgIGhlaWdodCAtPSByYW5nZS55O1xuICAgICAgICAgIHRvcCArPSByYW5nZS55O1xuXG4gICAgICAgICAgaWYgKGhlaWdodCA8IDApIHtcbiAgICAgICAgICAgIGFjdGlvbiA9IEFDVElPTl9TT1VUSDtcbiAgICAgICAgICAgIGhlaWdodCA9IC1oZWlnaHQ7XG4gICAgICAgICAgICB0b3AgLT0gaGVpZ2h0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChhc3BlY3RSYXRpbykge1xuICAgICAgICAgICAgd2lkdGggPSBoZWlnaHQgKiBhc3BlY3RSYXRpbztcbiAgICAgICAgICAgIGxlZnQgKz0gKGNyb3BCb3hEYXRhLndpZHRoIC0gd2lkdGgpIC8gMjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIEFDVElPTl9XRVNUOlxuICAgICAgICAgIGlmIChyYW5nZS54IDw9IDAgJiYgKGxlZnQgPD0gbWluTGVmdCB8fCBhc3BlY3RSYXRpbyAmJiAodG9wIDw9IG1pblRvcCB8fCBib3R0b20gPj0gbWF4SGVpZ2h0KSkpIHtcbiAgICAgICAgICAgIHJlbmRlcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNoZWNrKEFDVElPTl9XRVNUKTtcbiAgICAgICAgICB3aWR0aCAtPSByYW5nZS54O1xuICAgICAgICAgIGxlZnQgKz0gcmFuZ2UueDtcblxuICAgICAgICAgIGlmICh3aWR0aCA8IDApIHtcbiAgICAgICAgICAgIGFjdGlvbiA9IEFDVElPTl9FQVNUO1xuICAgICAgICAgICAgd2lkdGggPSAtd2lkdGg7XG4gICAgICAgICAgICBsZWZ0IC09IHdpZHRoO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChhc3BlY3RSYXRpbykge1xuICAgICAgICAgICAgaGVpZ2h0ID0gd2lkdGggLyBhc3BlY3RSYXRpbztcbiAgICAgICAgICAgIHRvcCArPSAoY3JvcEJveERhdGEuaGVpZ2h0IC0gaGVpZ2h0KSAvIDI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBBQ1RJT05fU09VVEg6XG4gICAgICAgICAgaWYgKHJhbmdlLnkgPj0gMCAmJiAoYm90dG9tID49IG1heEhlaWdodCB8fCBhc3BlY3RSYXRpbyAmJiAobGVmdCA8PSBtaW5MZWZ0IHx8IHJpZ2h0ID49IG1heFdpZHRoKSkpIHtcbiAgICAgICAgICAgIHJlbmRlcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNoZWNrKEFDVElPTl9TT1VUSCk7XG4gICAgICAgICAgaGVpZ2h0ICs9IHJhbmdlLnk7XG5cbiAgICAgICAgICBpZiAoaGVpZ2h0IDwgMCkge1xuICAgICAgICAgICAgYWN0aW9uID0gQUNUSU9OX05PUlRIO1xuICAgICAgICAgICAgaGVpZ2h0ID0gLWhlaWdodDtcbiAgICAgICAgICAgIHRvcCAtPSBoZWlnaHQ7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGFzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICB3aWR0aCA9IGhlaWdodCAqIGFzcGVjdFJhdGlvO1xuICAgICAgICAgICAgbGVmdCArPSAoY3JvcEJveERhdGEud2lkdGggLSB3aWR0aCkgLyAyO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgQUNUSU9OX05PUlRIX0VBU1Q6XG4gICAgICAgICAgaWYgKGFzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICBpZiAocmFuZ2UueSA8PSAwICYmICh0b3AgPD0gbWluVG9wIHx8IHJpZ2h0ID49IG1heFdpZHRoKSkge1xuICAgICAgICAgICAgICByZW5kZXJhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjaGVjayhBQ1RJT05fTk9SVEgpO1xuICAgICAgICAgICAgaGVpZ2h0IC09IHJhbmdlLnk7XG4gICAgICAgICAgICB0b3AgKz0gcmFuZ2UueTtcbiAgICAgICAgICAgIHdpZHRoID0gaGVpZ2h0ICogYXNwZWN0UmF0aW87XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoZWNrKEFDVElPTl9OT1JUSCk7XG4gICAgICAgICAgICBjaGVjayhBQ1RJT05fRUFTVCk7XG5cbiAgICAgICAgICAgIGlmIChyYW5nZS54ID49IDApIHtcbiAgICAgICAgICAgICAgaWYgKHJpZ2h0IDwgbWF4V2lkdGgpIHtcbiAgICAgICAgICAgICAgICB3aWR0aCArPSByYW5nZS54O1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKHJhbmdlLnkgPD0gMCAmJiB0b3AgPD0gbWluVG9wKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB3aWR0aCArPSByYW5nZS54O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocmFuZ2UueSA8PSAwKSB7XG4gICAgICAgICAgICAgIGlmICh0b3AgPiBtaW5Ub3ApIHtcbiAgICAgICAgICAgICAgICBoZWlnaHQgLT0gcmFuZ2UueTtcbiAgICAgICAgICAgICAgICB0b3AgKz0gcmFuZ2UueTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaGVpZ2h0IC09IHJhbmdlLnk7XG4gICAgICAgICAgICAgIHRvcCArPSByYW5nZS55O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh3aWR0aCA8IDAgJiYgaGVpZ2h0IDwgMCkge1xuICAgICAgICAgICAgYWN0aW9uID0gQUNUSU9OX1NPVVRIX1dFU1Q7XG4gICAgICAgICAgICBoZWlnaHQgPSAtaGVpZ2h0O1xuICAgICAgICAgICAgd2lkdGggPSAtd2lkdGg7XG4gICAgICAgICAgICB0b3AgLT0gaGVpZ2h0O1xuICAgICAgICAgICAgbGVmdCAtPSB3aWR0aDtcbiAgICAgICAgICB9IGVsc2UgaWYgKHdpZHRoIDwgMCkge1xuICAgICAgICAgICAgYWN0aW9uID0gQUNUSU9OX05PUlRIX1dFU1Q7XG4gICAgICAgICAgICB3aWR0aCA9IC13aWR0aDtcbiAgICAgICAgICAgIGxlZnQgLT0gd2lkdGg7XG4gICAgICAgICAgfSBlbHNlIGlmIChoZWlnaHQgPCAwKSB7XG4gICAgICAgICAgICBhY3Rpb24gPSBBQ1RJT05fU09VVEhfRUFTVDtcbiAgICAgICAgICAgIGhlaWdodCA9IC1oZWlnaHQ7XG4gICAgICAgICAgICB0b3AgLT0gaGVpZ2h0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgQUNUSU9OX05PUlRIX1dFU1Q6XG4gICAgICAgICAgaWYgKGFzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICBpZiAocmFuZ2UueSA8PSAwICYmICh0b3AgPD0gbWluVG9wIHx8IGxlZnQgPD0gbWluTGVmdCkpIHtcbiAgICAgICAgICAgICAgcmVuZGVyYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2hlY2soQUNUSU9OX05PUlRIKTtcbiAgICAgICAgICAgIGhlaWdodCAtPSByYW5nZS55O1xuICAgICAgICAgICAgdG9wICs9IHJhbmdlLnk7XG4gICAgICAgICAgICB3aWR0aCA9IGhlaWdodCAqIGFzcGVjdFJhdGlvO1xuICAgICAgICAgICAgbGVmdCArPSBjcm9wQm94RGF0YS53aWR0aCAtIHdpZHRoO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjaGVjayhBQ1RJT05fTk9SVEgpO1xuICAgICAgICAgICAgY2hlY2soQUNUSU9OX1dFU1QpO1xuXG4gICAgICAgICAgICBpZiAocmFuZ2UueCA8PSAwKSB7XG4gICAgICAgICAgICAgIGlmIChsZWZ0ID4gbWluTGVmdCkge1xuICAgICAgICAgICAgICAgIHdpZHRoIC09IHJhbmdlLng7XG4gICAgICAgICAgICAgICAgbGVmdCArPSByYW5nZS54O1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKHJhbmdlLnkgPD0gMCAmJiB0b3AgPD0gbWluVG9wKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB3aWR0aCAtPSByYW5nZS54O1xuICAgICAgICAgICAgICBsZWZ0ICs9IHJhbmdlLng7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyYW5nZS55IDw9IDApIHtcbiAgICAgICAgICAgICAgaWYgKHRvcCA+IG1pblRvcCkge1xuICAgICAgICAgICAgICAgIGhlaWdodCAtPSByYW5nZS55O1xuICAgICAgICAgICAgICAgIHRvcCArPSByYW5nZS55O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBoZWlnaHQgLT0gcmFuZ2UueTtcbiAgICAgICAgICAgICAgdG9wICs9IHJhbmdlLnk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHdpZHRoIDwgMCAmJiBoZWlnaHQgPCAwKSB7XG4gICAgICAgICAgICBhY3Rpb24gPSBBQ1RJT05fU09VVEhfRUFTVDtcbiAgICAgICAgICAgIGhlaWdodCA9IC1oZWlnaHQ7XG4gICAgICAgICAgICB3aWR0aCA9IC13aWR0aDtcbiAgICAgICAgICAgIHRvcCAtPSBoZWlnaHQ7XG4gICAgICAgICAgICBsZWZ0IC09IHdpZHRoO1xuICAgICAgICAgIH0gZWxzZSBpZiAod2lkdGggPCAwKSB7XG4gICAgICAgICAgICBhY3Rpb24gPSBBQ1RJT05fTk9SVEhfRUFTVDtcbiAgICAgICAgICAgIHdpZHRoID0gLXdpZHRoO1xuICAgICAgICAgICAgbGVmdCAtPSB3aWR0aDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGhlaWdodCA8IDApIHtcbiAgICAgICAgICAgIGFjdGlvbiA9IEFDVElPTl9TT1VUSF9XRVNUO1xuICAgICAgICAgICAgaGVpZ2h0ID0gLWhlaWdodDtcbiAgICAgICAgICAgIHRvcCAtPSBoZWlnaHQ7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBBQ1RJT05fU09VVEhfV0VTVDpcbiAgICAgICAgICBpZiAoYXNwZWN0UmF0aW8pIHtcbiAgICAgICAgICAgIGlmIChyYW5nZS54IDw9IDAgJiYgKGxlZnQgPD0gbWluTGVmdCB8fCBib3R0b20gPj0gbWF4SGVpZ2h0KSkge1xuICAgICAgICAgICAgICByZW5kZXJhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjaGVjayhBQ1RJT05fV0VTVCk7XG4gICAgICAgICAgICB3aWR0aCAtPSByYW5nZS54O1xuICAgICAgICAgICAgbGVmdCArPSByYW5nZS54O1xuICAgICAgICAgICAgaGVpZ2h0ID0gd2lkdGggLyBhc3BlY3RSYXRpbztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hlY2soQUNUSU9OX1NPVVRIKTtcbiAgICAgICAgICAgIGNoZWNrKEFDVElPTl9XRVNUKTtcblxuICAgICAgICAgICAgaWYgKHJhbmdlLnggPD0gMCkge1xuICAgICAgICAgICAgICBpZiAobGVmdCA+IG1pbkxlZnQpIHtcbiAgICAgICAgICAgICAgICB3aWR0aCAtPSByYW5nZS54O1xuICAgICAgICAgICAgICAgIGxlZnQgKz0gcmFuZ2UueDtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChyYW5nZS55ID49IDAgJiYgYm90dG9tID49IG1heEhlaWdodCkge1xuICAgICAgICAgICAgICAgIHJlbmRlcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgd2lkdGggLT0gcmFuZ2UueDtcbiAgICAgICAgICAgICAgbGVmdCArPSByYW5nZS54O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocmFuZ2UueSA+PSAwKSB7XG4gICAgICAgICAgICAgIGlmIChib3R0b20gPCBtYXhIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBoZWlnaHQgKz0gcmFuZ2UueTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaGVpZ2h0ICs9IHJhbmdlLnk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHdpZHRoIDwgMCAmJiBoZWlnaHQgPCAwKSB7XG4gICAgICAgICAgICBhY3Rpb24gPSBBQ1RJT05fTk9SVEhfRUFTVDtcbiAgICAgICAgICAgIGhlaWdodCA9IC1oZWlnaHQ7XG4gICAgICAgICAgICB3aWR0aCA9IC13aWR0aDtcbiAgICAgICAgICAgIHRvcCAtPSBoZWlnaHQ7XG4gICAgICAgICAgICBsZWZ0IC09IHdpZHRoO1xuICAgICAgICAgIH0gZWxzZSBpZiAod2lkdGggPCAwKSB7XG4gICAgICAgICAgICBhY3Rpb24gPSBBQ1RJT05fU09VVEhfRUFTVDtcbiAgICAgICAgICAgIHdpZHRoID0gLXdpZHRoO1xuICAgICAgICAgICAgbGVmdCAtPSB3aWR0aDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGhlaWdodCA8IDApIHtcbiAgICAgICAgICAgIGFjdGlvbiA9IEFDVElPTl9OT1JUSF9XRVNUO1xuICAgICAgICAgICAgaGVpZ2h0ID0gLWhlaWdodDtcbiAgICAgICAgICAgIHRvcCAtPSBoZWlnaHQ7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBBQ1RJT05fU09VVEhfRUFTVDpcbiAgICAgICAgICBpZiAoYXNwZWN0UmF0aW8pIHtcbiAgICAgICAgICAgIGlmIChyYW5nZS54ID49IDAgJiYgKHJpZ2h0ID49IG1heFdpZHRoIHx8IGJvdHRvbSA+PSBtYXhIZWlnaHQpKSB7XG4gICAgICAgICAgICAgIHJlbmRlcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNoZWNrKEFDVElPTl9FQVNUKTtcbiAgICAgICAgICAgIHdpZHRoICs9IHJhbmdlLng7XG4gICAgICAgICAgICBoZWlnaHQgPSB3aWR0aCAvIGFzcGVjdFJhdGlvO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjaGVjayhBQ1RJT05fU09VVEgpO1xuICAgICAgICAgICAgY2hlY2soQUNUSU9OX0VBU1QpO1xuXG4gICAgICAgICAgICBpZiAocmFuZ2UueCA+PSAwKSB7XG4gICAgICAgICAgICAgIGlmIChyaWdodCA8IG1heFdpZHRoKSB7XG4gICAgICAgICAgICAgICAgd2lkdGggKz0gcmFuZ2UueDtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChyYW5nZS55ID49IDAgJiYgYm90dG9tID49IG1heEhlaWdodCkge1xuICAgICAgICAgICAgICAgIHJlbmRlcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgd2lkdGggKz0gcmFuZ2UueDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHJhbmdlLnkgPj0gMCkge1xuICAgICAgICAgICAgICBpZiAoYm90dG9tIDwgbWF4SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaGVpZ2h0ICs9IHJhbmdlLnk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGhlaWdodCArPSByYW5nZS55O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh3aWR0aCA8IDAgJiYgaGVpZ2h0IDwgMCkge1xuICAgICAgICAgICAgYWN0aW9uID0gQUNUSU9OX05PUlRIX1dFU1Q7XG4gICAgICAgICAgICBoZWlnaHQgPSAtaGVpZ2h0O1xuICAgICAgICAgICAgd2lkdGggPSAtd2lkdGg7XG4gICAgICAgICAgICB0b3AgLT0gaGVpZ2h0O1xuICAgICAgICAgICAgbGVmdCAtPSB3aWR0aDtcbiAgICAgICAgICB9IGVsc2UgaWYgKHdpZHRoIDwgMCkge1xuICAgICAgICAgICAgYWN0aW9uID0gQUNUSU9OX1NPVVRIX1dFU1Q7XG4gICAgICAgICAgICB3aWR0aCA9IC13aWR0aDtcbiAgICAgICAgICAgIGxlZnQgLT0gd2lkdGg7XG4gICAgICAgICAgfSBlbHNlIGlmIChoZWlnaHQgPCAwKSB7XG4gICAgICAgICAgICBhY3Rpb24gPSBBQ1RJT05fTk9SVEhfRUFTVDtcbiAgICAgICAgICAgIGhlaWdodCA9IC1oZWlnaHQ7XG4gICAgICAgICAgICB0b3AgLT0gaGVpZ2h0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICAvLyBNb3ZlIGNhbnZhc1xuXG4gICAgICAgIGNhc2UgQUNUSU9OX01PVkU6XG4gICAgICAgICAgdGhpcy5tb3ZlKHJhbmdlLngsIHJhbmdlLnkpO1xuICAgICAgICAgIHJlbmRlcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgLy8gWm9vbSBjYW52YXNcblxuICAgICAgICBjYXNlIEFDVElPTl9aT09NOlxuICAgICAgICAgIHRoaXMuem9vbShnZXRNYXhab29tUmF0aW8ocG9pbnRlcnMpLCBldmVudCk7XG4gICAgICAgICAgcmVuZGVyYWJsZSA9IGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICAvLyBDcmVhdGUgY3JvcCBib3hcblxuICAgICAgICBjYXNlIEFDVElPTl9DUk9QOlxuICAgICAgICAgIGlmICghcmFuZ2UueCB8fCAhcmFuZ2UueSkge1xuICAgICAgICAgICAgcmVuZGVyYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgb2Zmc2V0ID0gZ2V0T2Zmc2V0KHRoaXMuY3JvcHBlcik7XG4gICAgICAgICAgbGVmdCA9IHBvaW50ZXIuc3RhcnRYIC0gb2Zmc2V0LmxlZnQ7XG4gICAgICAgICAgdG9wID0gcG9pbnRlci5zdGFydFkgLSBvZmZzZXQudG9wO1xuICAgICAgICAgIHdpZHRoID0gY3JvcEJveERhdGEubWluV2lkdGg7XG4gICAgICAgICAgaGVpZ2h0ID0gY3JvcEJveERhdGEubWluSGVpZ2h0O1xuXG4gICAgICAgICAgaWYgKHJhbmdlLnggPiAwKSB7XG4gICAgICAgICAgICBhY3Rpb24gPSByYW5nZS55ID4gMCA/IEFDVElPTl9TT1VUSF9FQVNUIDogQUNUSU9OX05PUlRIX0VBU1Q7XG4gICAgICAgICAgfSBlbHNlIGlmIChyYW5nZS54IDwgMCkge1xuICAgICAgICAgICAgbGVmdCAtPSB3aWR0aDtcbiAgICAgICAgICAgIGFjdGlvbiA9IHJhbmdlLnkgPiAwID8gQUNUSU9OX1NPVVRIX1dFU1QgOiBBQ1RJT05fTk9SVEhfV0VTVDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocmFuZ2UueSA8IDApIHtcbiAgICAgICAgICAgIHRvcCAtPSBoZWlnaHQ7XG4gICAgICAgICAgfSAvLyBTaG93IHRoZSBjcm9wIGJveCBpZiBpcyBoaWRkZW5cblxuXG4gICAgICAgICAgaWYgKCF0aGlzLmNyb3BwZWQpIHtcbiAgICAgICAgICAgIHJlbW92ZUNsYXNzKHRoaXMuY3JvcEJveCwgQ0xBU1NfSElEREVOKTtcbiAgICAgICAgICAgIHRoaXMuY3JvcHBlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmxpbWl0ZWQpIHtcbiAgICAgICAgICAgICAgdGhpcy5saW1pdENyb3BCb3godHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgIH1cblxuICAgICAgaWYgKHJlbmRlcmFibGUpIHtcbiAgICAgICAgY3JvcEJveERhdGEud2lkdGggPSB3aWR0aDtcbiAgICAgICAgY3JvcEJveERhdGEuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICBjcm9wQm94RGF0YS5sZWZ0ID0gbGVmdDtcbiAgICAgICAgY3JvcEJveERhdGEudG9wID0gdG9wO1xuICAgICAgICB0aGlzLmFjdGlvbiA9IGFjdGlvbjtcbiAgICAgICAgdGhpcy5yZW5kZXJDcm9wQm94KCk7XG4gICAgICB9IC8vIE92ZXJyaWRlXG5cblxuICAgICAgZm9yRWFjaChwb2ludGVycywgZnVuY3Rpb24gKHApIHtcbiAgICAgICAgcC5zdGFydFggPSBwLmVuZFg7XG4gICAgICAgIHAuc3RhcnRZID0gcC5lbmRZO1xuICAgICAgfSk7XG4gICAgfVxuICB9O1xuXG4gIHZhciBtZXRob2RzID0ge1xuICAgIC8vIFNob3cgdGhlIGNyb3AgYm94IG1hbnVhbGx5XG4gICAgY3JvcDogZnVuY3Rpb24gY3JvcCgpIHtcbiAgICAgIGlmICh0aGlzLnJlYWR5ICYmICF0aGlzLmNyb3BwZWQgJiYgIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgdGhpcy5jcm9wcGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5saW1pdENyb3BCb3godHJ1ZSwgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5tb2RhbCkge1xuICAgICAgICAgIGFkZENsYXNzKHRoaXMuZHJhZ0JveCwgQ0xBU1NfTU9EQUwpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVtb3ZlQ2xhc3ModGhpcy5jcm9wQm94LCBDTEFTU19ISURERU4pO1xuICAgICAgICB0aGlzLnNldENyb3BCb3hEYXRhKHRoaXMuaW5pdGlhbENyb3BCb3hEYXRhKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICAvLyBSZXNldCB0aGUgaW1hZ2UgYW5kIGNyb3AgYm94IHRvIHRoZWlyIGluaXRpYWwgc3RhdGVzXG4gICAgcmVzZXQ6IGZ1bmN0aW9uIHJlc2V0KCkge1xuICAgICAgaWYgKHRoaXMucmVhZHkgJiYgIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgdGhpcy5pbWFnZURhdGEgPSBhc3NpZ24oe30sIHRoaXMuaW5pdGlhbEltYWdlRGF0YSk7XG4gICAgICAgIHRoaXMuY2FudmFzRGF0YSA9IGFzc2lnbih7fSwgdGhpcy5pbml0aWFsQ2FudmFzRGF0YSk7XG4gICAgICAgIHRoaXMuY3JvcEJveERhdGEgPSBhc3NpZ24oe30sIHRoaXMuaW5pdGlhbENyb3BCb3hEYXRhKTtcbiAgICAgICAgdGhpcy5yZW5kZXJDYW52YXMoKTtcblxuICAgICAgICBpZiAodGhpcy5jcm9wcGVkKSB7XG4gICAgICAgICAgdGhpcy5yZW5kZXJDcm9wQm94KCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICAvLyBDbGVhciB0aGUgY3JvcCBib3hcbiAgICBjbGVhcjogZnVuY3Rpb24gY2xlYXIoKSB7XG4gICAgICBpZiAodGhpcy5jcm9wcGVkICYmICF0aGlzLmRpc2FibGVkKSB7XG4gICAgICAgIGFzc2lnbih0aGlzLmNyb3BCb3hEYXRhLCB7XG4gICAgICAgICAgbGVmdDogMCxcbiAgICAgICAgICB0b3A6IDAsXG4gICAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgICAgaGVpZ2h0OiAwXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNyb3BwZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZW5kZXJDcm9wQm94KCk7XG4gICAgICAgIHRoaXMubGltaXRDYW52YXModHJ1ZSwgdHJ1ZSk7IC8vIFJlbmRlciBjYW52YXMgYWZ0ZXIgY3JvcCBib3ggcmVuZGVyZWRcblxuICAgICAgICB0aGlzLnJlbmRlckNhbnZhcygpO1xuICAgICAgICByZW1vdmVDbGFzcyh0aGlzLmRyYWdCb3gsIENMQVNTX01PREFMKTtcbiAgICAgICAgYWRkQ2xhc3ModGhpcy5jcm9wQm94LCBDTEFTU19ISURERU4pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVwbGFjZSB0aGUgaW1hZ2UncyBzcmMgYW5kIHJlYnVpbGQgdGhlIGNyb3BwZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIC0gVGhlIG5ldyBVUkwuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaGFzU2FtZVNpemVdIC0gSW5kaWNhdGUgaWYgdGhlIG5ldyBpbWFnZSBoYXMgdGhlIHNhbWUgc2l6ZSBhcyB0aGUgb2xkIG9uZS5cbiAgICAgKiBAcmV0dXJucyB7Q3JvcHBlcn0gdGhpc1xuICAgICAqL1xuICAgIHJlcGxhY2U6IGZ1bmN0aW9uIHJlcGxhY2UodXJsKSB7XG4gICAgICB2YXIgaGFzU2FtZVNpemUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IGZhbHNlO1xuXG4gICAgICBpZiAoIXRoaXMuZGlzYWJsZWQgJiYgdXJsKSB7XG4gICAgICAgIGlmICh0aGlzLmlzSW1nKSB7XG4gICAgICAgICAgdGhpcy5lbGVtZW50LnNyYyA9IHVybDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChoYXNTYW1lU2l6ZSkge1xuICAgICAgICAgIHRoaXMudXJsID0gdXJsO1xuICAgICAgICAgIHRoaXMuaW1hZ2Uuc3JjID0gdXJsO1xuXG4gICAgICAgICAgaWYgKHRoaXMucmVhZHkpIHtcbiAgICAgICAgICAgIHRoaXMudmlld0JveEltYWdlLnNyYyA9IHVybDtcbiAgICAgICAgICAgIGZvckVhY2godGhpcy5wcmV2aWV3cywgZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgZWxlbWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaW1nJylbMF0uc3JjID0gdXJsO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICh0aGlzLmlzSW1nKSB7XG4gICAgICAgICAgICB0aGlzLnJlcGxhY2VkID0gdHJ1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLm9wdGlvbnMuZGF0YSA9IG51bGw7XG4gICAgICAgICAgdGhpcy51bmNyZWF0ZSgpO1xuICAgICAgICAgIHRoaXMubG9hZCh1cmwpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgLy8gRW5hYmxlICh1bmZyZWV6ZSkgdGhlIGNyb3BwZXJcbiAgICBlbmFibGU6IGZ1bmN0aW9uIGVuYWJsZSgpIHtcbiAgICAgIGlmICh0aGlzLnJlYWR5ICYmIHRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgdGhpcy5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICByZW1vdmVDbGFzcyh0aGlzLmNyb3BwZXIsIENMQVNTX0RJU0FCTEVEKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICAvLyBEaXNhYmxlIChmcmVlemUpIHRoZSBjcm9wcGVyXG4gICAgZGlzYWJsZTogZnVuY3Rpb24gZGlzYWJsZSgpIHtcbiAgICAgIGlmICh0aGlzLnJlYWR5ICYmICF0aGlzLmRpc2FibGVkKSB7XG4gICAgICAgIHRoaXMuZGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICBhZGRDbGFzcyh0aGlzLmNyb3BwZXIsIENMQVNTX0RJU0FCTEVEKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIERlc3Ryb3kgdGhlIGNyb3BwZXIgYW5kIHJlbW92ZSB0aGUgaW5zdGFuY2UgZnJvbSB0aGUgaW1hZ2VcbiAgICAgKiBAcmV0dXJucyB7Q3JvcHBlcn0gdGhpc1xuICAgICAqL1xuICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICB2YXIgZWxlbWVudCA9IHRoaXMuZWxlbWVudDtcblxuICAgICAgaWYgKCFlbGVtZW50W05BTUVTUEFDRV0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGVsZW1lbnRbTkFNRVNQQUNFXSA9IHVuZGVmaW5lZDtcblxuICAgICAgaWYgKHRoaXMuaXNJbWcgJiYgdGhpcy5yZXBsYWNlZCkge1xuICAgICAgICBlbGVtZW50LnNyYyA9IHRoaXMub3JpZ2luYWxVcmw7XG4gICAgICB9XG5cbiAgICAgIHRoaXMudW5jcmVhdGUoKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBNb3ZlIHRoZSBjYW52YXMgd2l0aCByZWxhdGl2ZSBvZmZzZXRzXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFggLSBUaGUgcmVsYXRpdmUgb2Zmc2V0IGRpc3RhbmNlIG9uIHRoZSB4LWF4aXMuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvZmZzZXRZPW9mZnNldFhdIC0gVGhlIHJlbGF0aXZlIG9mZnNldCBkaXN0YW5jZSBvbiB0aGUgeS1heGlzLlxuICAgICAqIEByZXR1cm5zIHtDcm9wcGVyfSB0aGlzXG4gICAgICovXG4gICAgbW92ZTogZnVuY3Rpb24gbW92ZShvZmZzZXRYKSB7XG4gICAgICB2YXIgb2Zmc2V0WSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogb2Zmc2V0WDtcbiAgICAgIHZhciBfdGhpcyRjYW52YXNEYXRhID0gdGhpcy5jYW52YXNEYXRhLFxuICAgICAgICAgIGxlZnQgPSBfdGhpcyRjYW52YXNEYXRhLmxlZnQsXG4gICAgICAgICAgdG9wID0gX3RoaXMkY2FudmFzRGF0YS50b3A7XG4gICAgICByZXR1cm4gdGhpcy5tb3ZlVG8oaXNVbmRlZmluZWQob2Zmc2V0WCkgPyBvZmZzZXRYIDogbGVmdCArIE51bWJlcihvZmZzZXRYKSwgaXNVbmRlZmluZWQob2Zmc2V0WSkgPyBvZmZzZXRZIDogdG9wICsgTnVtYmVyKG9mZnNldFkpKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogTW92ZSB0aGUgY2FudmFzIHRvIGFuIGFic29sdXRlIHBvaW50XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgeC1heGlzIGNvb3JkaW5hdGUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFt5PXhdIC0gVGhlIHktYXhpcyBjb29yZGluYXRlLlxuICAgICAqIEByZXR1cm5zIHtDcm9wcGVyfSB0aGlzXG4gICAgICovXG4gICAgbW92ZVRvOiBmdW5jdGlvbiBtb3ZlVG8oeCkge1xuICAgICAgdmFyIHkgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHg7XG4gICAgICB2YXIgY2FudmFzRGF0YSA9IHRoaXMuY2FudmFzRGF0YTtcbiAgICAgIHZhciBjaGFuZ2VkID0gZmFsc2U7XG4gICAgICB4ID0gTnVtYmVyKHgpO1xuICAgICAgeSA9IE51bWJlcih5KTtcblxuICAgICAgaWYgKHRoaXMucmVhZHkgJiYgIXRoaXMuZGlzYWJsZWQgJiYgdGhpcy5vcHRpb25zLm1vdmFibGUpIHtcbiAgICAgICAgaWYgKGlzTnVtYmVyKHgpKSB7XG4gICAgICAgICAgY2FudmFzRGF0YS5sZWZ0ID0geDtcbiAgICAgICAgICBjaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc051bWJlcih5KSkge1xuICAgICAgICAgIGNhbnZhc0RhdGEudG9wID0geTtcbiAgICAgICAgICBjaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjaGFuZ2VkKSB7XG4gICAgICAgICAgdGhpcy5yZW5kZXJDYW52YXModHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFpvb20gdGhlIGNhbnZhcyB3aXRoIGEgcmVsYXRpdmUgcmF0aW9cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcmF0aW8gLSBUaGUgdGFyZ2V0IHJhdGlvLlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IF9vcmlnaW5hbEV2ZW50IC0gVGhlIG9yaWdpbmFsIGV2ZW50IGlmIGFueS5cbiAgICAgKiBAcmV0dXJucyB7Q3JvcHBlcn0gdGhpc1xuICAgICAqL1xuICAgIHpvb206IGZ1bmN0aW9uIHpvb20ocmF0aW8sIF9vcmlnaW5hbEV2ZW50KSB7XG4gICAgICB2YXIgY2FudmFzRGF0YSA9IHRoaXMuY2FudmFzRGF0YTtcbiAgICAgIHJhdGlvID0gTnVtYmVyKHJhdGlvKTtcblxuICAgICAgaWYgKHJhdGlvIDwgMCkge1xuICAgICAgICByYXRpbyA9IDEgLyAoMSAtIHJhdGlvKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJhdGlvID0gMSArIHJhdGlvO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy56b29tVG8oY2FudmFzRGF0YS53aWR0aCAqIHJhdGlvIC8gY2FudmFzRGF0YS5uYXR1cmFsV2lkdGgsIG51bGwsIF9vcmlnaW5hbEV2ZW50KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogWm9vbSB0aGUgY2FudmFzIHRvIGFuIGFic29sdXRlIHJhdGlvXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHJhdGlvIC0gVGhlIHRhcmdldCByYXRpby5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGl2b3QgLSBUaGUgem9vbSBwaXZvdCBwb2ludCBjb29yZGluYXRlLlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IF9vcmlnaW5hbEV2ZW50IC0gVGhlIG9yaWdpbmFsIGV2ZW50IGlmIGFueS5cbiAgICAgKiBAcmV0dXJucyB7Q3JvcHBlcn0gdGhpc1xuICAgICAqL1xuICAgIHpvb21UbzogZnVuY3Rpb24gem9vbVRvKHJhdGlvLCBwaXZvdCwgX29yaWdpbmFsRXZlbnQpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICAgIGNhbnZhc0RhdGEgPSB0aGlzLmNhbnZhc0RhdGE7XG4gICAgICB2YXIgd2lkdGggPSBjYW52YXNEYXRhLndpZHRoLFxuICAgICAgICAgIGhlaWdodCA9IGNhbnZhc0RhdGEuaGVpZ2h0LFxuICAgICAgICAgIG5hdHVyYWxXaWR0aCA9IGNhbnZhc0RhdGEubmF0dXJhbFdpZHRoLFxuICAgICAgICAgIG5hdHVyYWxIZWlnaHQgPSBjYW52YXNEYXRhLm5hdHVyYWxIZWlnaHQ7XG4gICAgICByYXRpbyA9IE51bWJlcihyYXRpbyk7XG5cbiAgICAgIGlmIChyYXRpbyA+PSAwICYmIHRoaXMucmVhZHkgJiYgIXRoaXMuZGlzYWJsZWQgJiYgb3B0aW9ucy56b29tYWJsZSkge1xuICAgICAgICB2YXIgbmV3V2lkdGggPSBuYXR1cmFsV2lkdGggKiByYXRpbztcbiAgICAgICAgdmFyIG5ld0hlaWdodCA9IG5hdHVyYWxIZWlnaHQgKiByYXRpbztcblxuICAgICAgICBpZiAoZGlzcGF0Y2hFdmVudCh0aGlzLmVsZW1lbnQsIEVWRU5UX1pPT00sIHtcbiAgICAgICAgICByYXRpbzogcmF0aW8sXG4gICAgICAgICAgb2xkUmF0aW86IHdpZHRoIC8gbmF0dXJhbFdpZHRoLFxuICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IF9vcmlnaW5hbEV2ZW50XG4gICAgICAgIH0pID09PSBmYWxzZSkge1xuICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKF9vcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgdmFyIHBvaW50ZXJzID0gdGhpcy5wb2ludGVycztcbiAgICAgICAgICB2YXIgb2Zmc2V0ID0gZ2V0T2Zmc2V0KHRoaXMuY3JvcHBlcik7XG4gICAgICAgICAgdmFyIGNlbnRlciA9IHBvaW50ZXJzICYmIE9iamVjdC5rZXlzKHBvaW50ZXJzKS5sZW5ndGggPyBnZXRQb2ludGVyc0NlbnRlcihwb2ludGVycykgOiB7XG4gICAgICAgICAgICBwYWdlWDogX29yaWdpbmFsRXZlbnQucGFnZVgsXG4gICAgICAgICAgICBwYWdlWTogX29yaWdpbmFsRXZlbnQucGFnZVlcbiAgICAgICAgICB9OyAvLyBab29tIGZyb20gdGhlIHRyaWdnZXJpbmcgcG9pbnQgb2YgdGhlIGV2ZW50XG5cbiAgICAgICAgICBjYW52YXNEYXRhLmxlZnQgLT0gKG5ld1dpZHRoIC0gd2lkdGgpICogKChjZW50ZXIucGFnZVggLSBvZmZzZXQubGVmdCAtIGNhbnZhc0RhdGEubGVmdCkgLyB3aWR0aCk7XG4gICAgICAgICAgY2FudmFzRGF0YS50b3AgLT0gKG5ld0hlaWdodCAtIGhlaWdodCkgKiAoKGNlbnRlci5wYWdlWSAtIG9mZnNldC50b3AgLSBjYW52YXNEYXRhLnRvcCkgLyBoZWlnaHQpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzUGxhaW5PYmplY3QocGl2b3QpICYmIGlzTnVtYmVyKHBpdm90LngpICYmIGlzTnVtYmVyKHBpdm90LnkpKSB7XG4gICAgICAgICAgY2FudmFzRGF0YS5sZWZ0IC09IChuZXdXaWR0aCAtIHdpZHRoKSAqICgocGl2b3QueCAtIGNhbnZhc0RhdGEubGVmdCkgLyB3aWR0aCk7XG4gICAgICAgICAgY2FudmFzRGF0YS50b3AgLT0gKG5ld0hlaWdodCAtIGhlaWdodCkgKiAoKHBpdm90LnkgLSBjYW52YXNEYXRhLnRvcCkgLyBoZWlnaHQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFpvb20gZnJvbSB0aGUgY2VudGVyIG9mIHRoZSBjYW52YXNcbiAgICAgICAgICBjYW52YXNEYXRhLmxlZnQgLT0gKG5ld1dpZHRoIC0gd2lkdGgpIC8gMjtcbiAgICAgICAgICBjYW52YXNEYXRhLnRvcCAtPSAobmV3SGVpZ2h0IC0gaGVpZ2h0KSAvIDI7XG4gICAgICAgIH1cblxuICAgICAgICBjYW52YXNEYXRhLndpZHRoID0gbmV3V2lkdGg7XG4gICAgICAgIGNhbnZhc0RhdGEuaGVpZ2h0ID0gbmV3SGVpZ2h0O1xuICAgICAgICB0aGlzLnJlbmRlckNhbnZhcyh0cnVlKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJvdGF0ZSB0aGUgY2FudmFzIHdpdGggYSByZWxhdGl2ZSBkZWdyZWVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZGVncmVlIC0gVGhlIHJvdGF0ZSBkZWdyZWUuXG4gICAgICogQHJldHVybnMge0Nyb3BwZXJ9IHRoaXNcbiAgICAgKi9cbiAgICByb3RhdGU6IGZ1bmN0aW9uIHJvdGF0ZShkZWdyZWUpIHtcbiAgICAgIHJldHVybiB0aGlzLnJvdGF0ZVRvKCh0aGlzLmltYWdlRGF0YS5yb3RhdGUgfHwgMCkgKyBOdW1iZXIoZGVncmVlKSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJvdGF0ZSB0aGUgY2FudmFzIHRvIGFuIGFic29sdXRlIGRlZ3JlZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkZWdyZWUgLSBUaGUgcm90YXRlIGRlZ3JlZS5cbiAgICAgKiBAcmV0dXJucyB7Q3JvcHBlcn0gdGhpc1xuICAgICAqL1xuICAgIHJvdGF0ZVRvOiBmdW5jdGlvbiByb3RhdGVUbyhkZWdyZWUpIHtcbiAgICAgIGRlZ3JlZSA9IE51bWJlcihkZWdyZWUpO1xuXG4gICAgICBpZiAoaXNOdW1iZXIoZGVncmVlKSAmJiB0aGlzLnJlYWR5ICYmICF0aGlzLmRpc2FibGVkICYmIHRoaXMub3B0aW9ucy5yb3RhdGFibGUpIHtcbiAgICAgICAgdGhpcy5pbWFnZURhdGEucm90YXRlID0gZGVncmVlICUgMzYwO1xuICAgICAgICB0aGlzLnJlbmRlckNhbnZhcyh0cnVlLCB0cnVlKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNjYWxlIHRoZSBpbWFnZSBvbiB0aGUgeC1heGlzLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzY2FsZVggLSBUaGUgc2NhbGUgcmF0aW8gb24gdGhlIHgtYXhpcy5cbiAgICAgKiBAcmV0dXJucyB7Q3JvcHBlcn0gdGhpc1xuICAgICAqL1xuICAgIHNjYWxlWDogZnVuY3Rpb24gc2NhbGVYKF9zY2FsZVgpIHtcbiAgICAgIHZhciBzY2FsZVkgPSB0aGlzLmltYWdlRGF0YS5zY2FsZVk7XG4gICAgICByZXR1cm4gdGhpcy5zY2FsZShfc2NhbGVYLCBpc051bWJlcihzY2FsZVkpID8gc2NhbGVZIDogMSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNjYWxlIHRoZSBpbWFnZSBvbiB0aGUgeS1heGlzLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzY2FsZVkgLSBUaGUgc2NhbGUgcmF0aW8gb24gdGhlIHktYXhpcy5cbiAgICAgKiBAcmV0dXJucyB7Q3JvcHBlcn0gdGhpc1xuICAgICAqL1xuICAgIHNjYWxlWTogZnVuY3Rpb24gc2NhbGVZKF9zY2FsZVkpIHtcbiAgICAgIHZhciBzY2FsZVggPSB0aGlzLmltYWdlRGF0YS5zY2FsZVg7XG4gICAgICByZXR1cm4gdGhpcy5zY2FsZShpc051bWJlcihzY2FsZVgpID8gc2NhbGVYIDogMSwgX3NjYWxlWSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNjYWxlIHRoZSBpbWFnZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzY2FsZVggLSBUaGUgc2NhbGUgcmF0aW8gb24gdGhlIHgtYXhpcy5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3NjYWxlWT1zY2FsZVhdIC0gVGhlIHNjYWxlIHJhdGlvIG9uIHRoZSB5LWF4aXMuXG4gICAgICogQHJldHVybnMge0Nyb3BwZXJ9IHRoaXNcbiAgICAgKi9cbiAgICBzY2FsZTogZnVuY3Rpb24gc2NhbGUoc2NhbGVYKSB7XG4gICAgICB2YXIgc2NhbGVZID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBzY2FsZVg7XG4gICAgICB2YXIgaW1hZ2VEYXRhID0gdGhpcy5pbWFnZURhdGE7XG4gICAgICB2YXIgdHJhbnNmb3JtZWQgPSBmYWxzZTtcbiAgICAgIHNjYWxlWCA9IE51bWJlcihzY2FsZVgpO1xuICAgICAgc2NhbGVZID0gTnVtYmVyKHNjYWxlWSk7XG5cbiAgICAgIGlmICh0aGlzLnJlYWR5ICYmICF0aGlzLmRpc2FibGVkICYmIHRoaXMub3B0aW9ucy5zY2FsYWJsZSkge1xuICAgICAgICBpZiAoaXNOdW1iZXIoc2NhbGVYKSkge1xuICAgICAgICAgIGltYWdlRGF0YS5zY2FsZVggPSBzY2FsZVg7XG4gICAgICAgICAgdHJhbnNmb3JtZWQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzTnVtYmVyKHNjYWxlWSkpIHtcbiAgICAgICAgICBpbWFnZURhdGEuc2NhbGVZID0gc2NhbGVZO1xuICAgICAgICAgIHRyYW5zZm9ybWVkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0cmFuc2Zvcm1lZCkge1xuICAgICAgICAgIHRoaXMucmVuZGVyQ2FudmFzKHRydWUsIHRydWUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGNyb3BwZWQgYXJlYSBwb3NpdGlvbiBhbmQgc2l6ZSBkYXRhIChiYXNlIG9uIHRoZSBvcmlnaW5hbCBpbWFnZSlcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtyb3VuZGVkPWZhbHNlXSAtIEluZGljYXRlIGlmIHJvdW5kIHRoZSBkYXRhIHZhbHVlcyBvciBub3QuXG4gICAgICogQHJldHVybnMge09iamVjdH0gVGhlIHJlc3VsdCBjcm9wcGVkIGRhdGEuXG4gICAgICovXG4gICAgZ2V0RGF0YTogZnVuY3Rpb24gZ2V0RGF0YSgpIHtcbiAgICAgIHZhciByb3VuZGVkID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBmYWxzZTtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICAgIGltYWdlRGF0YSA9IHRoaXMuaW1hZ2VEYXRhLFxuICAgICAgICAgIGNhbnZhc0RhdGEgPSB0aGlzLmNhbnZhc0RhdGEsXG4gICAgICAgICAgY3JvcEJveERhdGEgPSB0aGlzLmNyb3BCb3hEYXRhO1xuICAgICAgdmFyIGRhdGE7XG5cbiAgICAgIGlmICh0aGlzLnJlYWR5ICYmIHRoaXMuY3JvcHBlZCkge1xuICAgICAgICBkYXRhID0ge1xuICAgICAgICAgIHg6IGNyb3BCb3hEYXRhLmxlZnQgLSBjYW52YXNEYXRhLmxlZnQsXG4gICAgICAgICAgeTogY3JvcEJveERhdGEudG9wIC0gY2FudmFzRGF0YS50b3AsXG4gICAgICAgICAgd2lkdGg6IGNyb3BCb3hEYXRhLndpZHRoLFxuICAgICAgICAgIGhlaWdodDogY3JvcEJveERhdGEuaGVpZ2h0XG4gICAgICAgIH07XG4gICAgICAgIHZhciByYXRpbyA9IGltYWdlRGF0YS53aWR0aCAvIGltYWdlRGF0YS5uYXR1cmFsV2lkdGg7XG4gICAgICAgIGZvckVhY2goZGF0YSwgZnVuY3Rpb24gKG4sIGkpIHtcbiAgICAgICAgICBkYXRhW2ldID0gbiAvIHJhdGlvO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocm91bmRlZCkge1xuICAgICAgICAgIC8vIEluIGNhc2Ugcm91bmRpbmcgb2ZmIGxlYWRzIHRvIGV4dHJhIDFweCBpbiByaWdodCBvciBib3R0b20gYm9yZGVyXG4gICAgICAgICAgLy8gd2Ugc2hvdWxkIHJvdW5kIHRoZSB0b3AtbGVmdCBjb3JuZXIgYW5kIHRoZSBkaW1lbnNpb24gKCMzNDMpLlxuICAgICAgICAgIHZhciBib3R0b20gPSBNYXRoLnJvdW5kKGRhdGEueSArIGRhdGEuaGVpZ2h0KTtcbiAgICAgICAgICB2YXIgcmlnaHQgPSBNYXRoLnJvdW5kKGRhdGEueCArIGRhdGEud2lkdGgpO1xuICAgICAgICAgIGRhdGEueCA9IE1hdGgucm91bmQoZGF0YS54KTtcbiAgICAgICAgICBkYXRhLnkgPSBNYXRoLnJvdW5kKGRhdGEueSk7XG4gICAgICAgICAgZGF0YS53aWR0aCA9IHJpZ2h0IC0gZGF0YS54O1xuICAgICAgICAgIGRhdGEuaGVpZ2h0ID0gYm90dG9tIC0gZGF0YS55O1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkYXRhID0ge1xuICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgeTogMCxcbiAgICAgICAgICB3aWR0aDogMCxcbiAgICAgICAgICBoZWlnaHQ6IDBcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMucm90YXRhYmxlKSB7XG4gICAgICAgIGRhdGEucm90YXRlID0gaW1hZ2VEYXRhLnJvdGF0ZSB8fCAwO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5zY2FsYWJsZSkge1xuICAgICAgICBkYXRhLnNjYWxlWCA9IGltYWdlRGF0YS5zY2FsZVggfHwgMTtcbiAgICAgICAgZGF0YS5zY2FsZVkgPSBpbWFnZURhdGEuc2NhbGVZIHx8IDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGNyb3BwZWQgYXJlYSBwb3NpdGlvbiBhbmQgc2l6ZSB3aXRoIG5ldyBkYXRhXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRhdGEgLSBUaGUgbmV3IGRhdGEuXG4gICAgICogQHJldHVybnMge0Nyb3BwZXJ9IHRoaXNcbiAgICAgKi9cbiAgICBzZXREYXRhOiBmdW5jdGlvbiBzZXREYXRhKGRhdGEpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICAgIGltYWdlRGF0YSA9IHRoaXMuaW1hZ2VEYXRhLFxuICAgICAgICAgIGNhbnZhc0RhdGEgPSB0aGlzLmNhbnZhc0RhdGE7XG4gICAgICB2YXIgY3JvcEJveERhdGEgPSB7fTtcblxuICAgICAgaWYgKHRoaXMucmVhZHkgJiYgIXRoaXMuZGlzYWJsZWQgJiYgaXNQbGFpbk9iamVjdChkYXRhKSkge1xuICAgICAgICB2YXIgdHJhbnNmb3JtZWQgPSBmYWxzZTtcblxuICAgICAgICBpZiAob3B0aW9ucy5yb3RhdGFibGUpIHtcbiAgICAgICAgICBpZiAoaXNOdW1iZXIoZGF0YS5yb3RhdGUpICYmIGRhdGEucm90YXRlICE9PSBpbWFnZURhdGEucm90YXRlKSB7XG4gICAgICAgICAgICBpbWFnZURhdGEucm90YXRlID0gZGF0YS5yb3RhdGU7XG4gICAgICAgICAgICB0cmFuc2Zvcm1lZCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuc2NhbGFibGUpIHtcbiAgICAgICAgICBpZiAoaXNOdW1iZXIoZGF0YS5zY2FsZVgpICYmIGRhdGEuc2NhbGVYICE9PSBpbWFnZURhdGEuc2NhbGVYKSB7XG4gICAgICAgICAgICBpbWFnZURhdGEuc2NhbGVYID0gZGF0YS5zY2FsZVg7XG4gICAgICAgICAgICB0cmFuc2Zvcm1lZCA9IHRydWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGlzTnVtYmVyKGRhdGEuc2NhbGVZKSAmJiBkYXRhLnNjYWxlWSAhPT0gaW1hZ2VEYXRhLnNjYWxlWSkge1xuICAgICAgICAgICAgaW1hZ2VEYXRhLnNjYWxlWSA9IGRhdGEuc2NhbGVZO1xuICAgICAgICAgICAgdHJhbnNmb3JtZWQgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0cmFuc2Zvcm1lZCkge1xuICAgICAgICAgIHRoaXMucmVuZGVyQ2FudmFzKHRydWUsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJhdGlvID0gaW1hZ2VEYXRhLndpZHRoIC8gaW1hZ2VEYXRhLm5hdHVyYWxXaWR0aDtcblxuICAgICAgICBpZiAoaXNOdW1iZXIoZGF0YS54KSkge1xuICAgICAgICAgIGNyb3BCb3hEYXRhLmxlZnQgPSBkYXRhLnggKiByYXRpbyArIGNhbnZhc0RhdGEubGVmdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc051bWJlcihkYXRhLnkpKSB7XG4gICAgICAgICAgY3JvcEJveERhdGEudG9wID0gZGF0YS55ICogcmF0aW8gKyBjYW52YXNEYXRhLnRvcDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc051bWJlcihkYXRhLndpZHRoKSkge1xuICAgICAgICAgIGNyb3BCb3hEYXRhLndpZHRoID0gZGF0YS53aWR0aCAqIHJhdGlvO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzTnVtYmVyKGRhdGEuaGVpZ2h0KSkge1xuICAgICAgICAgIGNyb3BCb3hEYXRhLmhlaWdodCA9IGRhdGEuaGVpZ2h0ICogcmF0aW87XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldENyb3BCb3hEYXRhKGNyb3BCb3hEYXRhKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY29udGFpbmVyIHNpemUgZGF0YS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgcmVzdWx0IGNvbnRhaW5lciBkYXRhLlxuICAgICAqL1xuICAgIGdldENvbnRhaW5lckRhdGE6IGZ1bmN0aW9uIGdldENvbnRhaW5lckRhdGEoKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWFkeSA/IGFzc2lnbih7fSwgdGhpcy5jb250YWluZXJEYXRhKSA6IHt9O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGltYWdlIHBvc2l0aW9uIGFuZCBzaXplIGRhdGEuXG4gICAgICogQHJldHVybnMge09iamVjdH0gVGhlIHJlc3VsdCBpbWFnZSBkYXRhLlxuICAgICAqL1xuICAgIGdldEltYWdlRGF0YTogZnVuY3Rpb24gZ2V0SW1hZ2VEYXRhKCkge1xuICAgICAgcmV0dXJuIHRoaXMuc2l6ZWQgPyBhc3NpZ24oe30sIHRoaXMuaW1hZ2VEYXRhKSA6IHt9O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGNhbnZhcyBwb3NpdGlvbiBhbmQgc2l6ZSBkYXRhLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSByZXN1bHQgY2FudmFzIGRhdGEuXG4gICAgICovXG4gICAgZ2V0Q2FudmFzRGF0YTogZnVuY3Rpb24gZ2V0Q2FudmFzRGF0YSgpIHtcbiAgICAgIHZhciBjYW52YXNEYXRhID0gdGhpcy5jYW52YXNEYXRhO1xuICAgICAgdmFyIGRhdGEgPSB7fTtcblxuICAgICAgaWYgKHRoaXMucmVhZHkpIHtcbiAgICAgICAgZm9yRWFjaChbJ2xlZnQnLCAndG9wJywgJ3dpZHRoJywgJ2hlaWdodCcsICduYXR1cmFsV2lkdGgnLCAnbmF0dXJhbEhlaWdodCddLCBmdW5jdGlvbiAobikge1xuICAgICAgICAgIGRhdGFbbl0gPSBjYW52YXNEYXRhW25dO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgY2FudmFzIHBvc2l0aW9uIGFuZCBzaXplIHdpdGggbmV3IGRhdGEuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRhdGEgLSBUaGUgbmV3IGNhbnZhcyBkYXRhLlxuICAgICAqIEByZXR1cm5zIHtDcm9wcGVyfSB0aGlzXG4gICAgICovXG4gICAgc2V0Q2FudmFzRGF0YTogZnVuY3Rpb24gc2V0Q2FudmFzRGF0YShkYXRhKSB7XG4gICAgICB2YXIgY2FudmFzRGF0YSA9IHRoaXMuY2FudmFzRGF0YTtcbiAgICAgIHZhciBhc3BlY3RSYXRpbyA9IGNhbnZhc0RhdGEuYXNwZWN0UmF0aW87XG5cbiAgICAgIGlmICh0aGlzLnJlYWR5ICYmICF0aGlzLmRpc2FibGVkICYmIGlzUGxhaW5PYmplY3QoZGF0YSkpIHtcbiAgICAgICAgaWYgKGlzTnVtYmVyKGRhdGEubGVmdCkpIHtcbiAgICAgICAgICBjYW52YXNEYXRhLmxlZnQgPSBkYXRhLmxlZnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNOdW1iZXIoZGF0YS50b3ApKSB7XG4gICAgICAgICAgY2FudmFzRGF0YS50b3AgPSBkYXRhLnRvcDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc051bWJlcihkYXRhLndpZHRoKSkge1xuICAgICAgICAgIGNhbnZhc0RhdGEud2lkdGggPSBkYXRhLndpZHRoO1xuICAgICAgICAgIGNhbnZhc0RhdGEuaGVpZ2h0ID0gZGF0YS53aWR0aCAvIGFzcGVjdFJhdGlvO1xuICAgICAgICB9IGVsc2UgaWYgKGlzTnVtYmVyKGRhdGEuaGVpZ2h0KSkge1xuICAgICAgICAgIGNhbnZhc0RhdGEuaGVpZ2h0ID0gZGF0YS5oZWlnaHQ7XG4gICAgICAgICAgY2FudmFzRGF0YS53aWR0aCA9IGRhdGEuaGVpZ2h0ICogYXNwZWN0UmF0aW87XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlbmRlckNhbnZhcyh0cnVlKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY3JvcCBib3ggcG9zaXRpb24gYW5kIHNpemUgZGF0YS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgcmVzdWx0IGNyb3AgYm94IGRhdGEuXG4gICAgICovXG4gICAgZ2V0Q3JvcEJveERhdGE6IGZ1bmN0aW9uIGdldENyb3BCb3hEYXRhKCkge1xuICAgICAgdmFyIGNyb3BCb3hEYXRhID0gdGhpcy5jcm9wQm94RGF0YTtcbiAgICAgIHZhciBkYXRhO1xuXG4gICAgICBpZiAodGhpcy5yZWFkeSAmJiB0aGlzLmNyb3BwZWQpIHtcbiAgICAgICAgZGF0YSA9IHtcbiAgICAgICAgICBsZWZ0OiBjcm9wQm94RGF0YS5sZWZ0LFxuICAgICAgICAgIHRvcDogY3JvcEJveERhdGEudG9wLFxuICAgICAgICAgIHdpZHRoOiBjcm9wQm94RGF0YS53aWR0aCxcbiAgICAgICAgICBoZWlnaHQ6IGNyb3BCb3hEYXRhLmhlaWdodFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZGF0YSB8fCB7fTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBjcm9wIGJveCBwb3NpdGlvbiBhbmQgc2l6ZSB3aXRoIG5ldyBkYXRhLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIC0gVGhlIG5ldyBjcm9wIGJveCBkYXRhLlxuICAgICAqIEByZXR1cm5zIHtDcm9wcGVyfSB0aGlzXG4gICAgICovXG4gICAgc2V0Q3JvcEJveERhdGE6IGZ1bmN0aW9uIHNldENyb3BCb3hEYXRhKGRhdGEpIHtcbiAgICAgIHZhciBjcm9wQm94RGF0YSA9IHRoaXMuY3JvcEJveERhdGE7XG4gICAgICB2YXIgYXNwZWN0UmF0aW8gPSB0aGlzLm9wdGlvbnMuYXNwZWN0UmF0aW87XG4gICAgICB2YXIgd2lkdGhDaGFuZ2VkO1xuICAgICAgdmFyIGhlaWdodENoYW5nZWQ7XG5cbiAgICAgIGlmICh0aGlzLnJlYWR5ICYmIHRoaXMuY3JvcHBlZCAmJiAhdGhpcy5kaXNhYmxlZCAmJiBpc1BsYWluT2JqZWN0KGRhdGEpKSB7XG4gICAgICAgIGlmIChpc051bWJlcihkYXRhLmxlZnQpKSB7XG4gICAgICAgICAgY3JvcEJveERhdGEubGVmdCA9IGRhdGEubGVmdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc051bWJlcihkYXRhLnRvcCkpIHtcbiAgICAgICAgICBjcm9wQm94RGF0YS50b3AgPSBkYXRhLnRvcDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc051bWJlcihkYXRhLndpZHRoKSAmJiBkYXRhLndpZHRoICE9PSBjcm9wQm94RGF0YS53aWR0aCkge1xuICAgICAgICAgIHdpZHRoQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgICAgY3JvcEJveERhdGEud2lkdGggPSBkYXRhLndpZHRoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzTnVtYmVyKGRhdGEuaGVpZ2h0KSAmJiBkYXRhLmhlaWdodCAhPT0gY3JvcEJveERhdGEuaGVpZ2h0KSB7XG4gICAgICAgICAgaGVpZ2h0Q2hhbmdlZCA9IHRydWU7XG4gICAgICAgICAgY3JvcEJveERhdGEuaGVpZ2h0ID0gZGF0YS5oZWlnaHQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYXNwZWN0UmF0aW8pIHtcbiAgICAgICAgICBpZiAod2lkdGhDaGFuZ2VkKSB7XG4gICAgICAgICAgICBjcm9wQm94RGF0YS5oZWlnaHQgPSBjcm9wQm94RGF0YS53aWR0aCAvIGFzcGVjdFJhdGlvO1xuICAgICAgICAgIH0gZWxzZSBpZiAoaGVpZ2h0Q2hhbmdlZCkge1xuICAgICAgICAgICAgY3JvcEJveERhdGEud2lkdGggPSBjcm9wQm94RGF0YS5oZWlnaHQgKiBhc3BlY3RSYXRpbztcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlbmRlckNyb3BCb3goKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBhIGNhbnZhcyBkcmF3biB0aGUgY3JvcHBlZCBpbWFnZS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIC0gVGhlIGNvbmZpZyBvcHRpb25zLlxuICAgICAqIEByZXR1cm5zIHtIVE1MQ2FudmFzRWxlbWVudH0gLSBUaGUgcmVzdWx0IGNhbnZhcy5cbiAgICAgKi9cbiAgICBnZXRDcm9wcGVkQ2FudmFzOiBmdW5jdGlvbiBnZXRDcm9wcGVkQ2FudmFzKCkge1xuICAgICAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHt9O1xuXG4gICAgICBpZiAoIXRoaXMucmVhZHkgfHwgIXdpbmRvdy5IVE1MQ2FudmFzRWxlbWVudCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgdmFyIGNhbnZhc0RhdGEgPSB0aGlzLmNhbnZhc0RhdGE7XG4gICAgICB2YXIgc291cmNlID0gZ2V0U291cmNlQ2FudmFzKHRoaXMuaW1hZ2UsIHRoaXMuaW1hZ2VEYXRhLCBjYW52YXNEYXRhLCBvcHRpb25zKTsgLy8gUmV0dXJucyB0aGUgc291cmNlIGNhbnZhcyBpZiBpdCBpcyBub3QgY3JvcHBlZC5cblxuICAgICAgaWYgKCF0aGlzLmNyb3BwZWQpIHtcbiAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICAgIH1cblxuICAgICAgdmFyIF90aGlzJGdldERhdGEgPSB0aGlzLmdldERhdGEoKSxcbiAgICAgICAgICBpbml0aWFsWCA9IF90aGlzJGdldERhdGEueCxcbiAgICAgICAgICBpbml0aWFsWSA9IF90aGlzJGdldERhdGEueSxcbiAgICAgICAgICBpbml0aWFsV2lkdGggPSBfdGhpcyRnZXREYXRhLndpZHRoLFxuICAgICAgICAgIGluaXRpYWxIZWlnaHQgPSBfdGhpcyRnZXREYXRhLmhlaWdodDtcblxuICAgICAgdmFyIHJhdGlvID0gc291cmNlLndpZHRoIC8gTWF0aC5mbG9vcihjYW52YXNEYXRhLm5hdHVyYWxXaWR0aCk7XG5cbiAgICAgIGlmIChyYXRpbyAhPT0gMSkge1xuICAgICAgICBpbml0aWFsWCAqPSByYXRpbztcbiAgICAgICAgaW5pdGlhbFkgKj0gcmF0aW87XG4gICAgICAgIGluaXRpYWxXaWR0aCAqPSByYXRpbztcbiAgICAgICAgaW5pdGlhbEhlaWdodCAqPSByYXRpbztcbiAgICAgIH1cblxuICAgICAgdmFyIGFzcGVjdFJhdGlvID0gaW5pdGlhbFdpZHRoIC8gaW5pdGlhbEhlaWdodDtcbiAgICAgIHZhciBtYXhTaXplcyA9IGdldEFkanVzdGVkU2l6ZXMoe1xuICAgICAgICBhc3BlY3RSYXRpbzogYXNwZWN0UmF0aW8sXG4gICAgICAgIHdpZHRoOiBvcHRpb25zLm1heFdpZHRoIHx8IEluZmluaXR5LFxuICAgICAgICBoZWlnaHQ6IG9wdGlvbnMubWF4SGVpZ2h0IHx8IEluZmluaXR5XG4gICAgICB9KTtcbiAgICAgIHZhciBtaW5TaXplcyA9IGdldEFkanVzdGVkU2l6ZXMoe1xuICAgICAgICBhc3BlY3RSYXRpbzogYXNwZWN0UmF0aW8sXG4gICAgICAgIHdpZHRoOiBvcHRpb25zLm1pbldpZHRoIHx8IDAsXG4gICAgICAgIGhlaWdodDogb3B0aW9ucy5taW5IZWlnaHQgfHwgMFxuICAgICAgfSwgJ2NvdmVyJyk7XG5cbiAgICAgIHZhciBfZ2V0QWRqdXN0ZWRTaXplcyA9IGdldEFkanVzdGVkU2l6ZXMoe1xuICAgICAgICBhc3BlY3RSYXRpbzogYXNwZWN0UmF0aW8sXG4gICAgICAgIHdpZHRoOiBvcHRpb25zLndpZHRoIHx8IChyYXRpbyAhPT0gMSA/IHNvdXJjZS53aWR0aCA6IGluaXRpYWxXaWR0aCksXG4gICAgICAgIGhlaWdodDogb3B0aW9ucy5oZWlnaHQgfHwgKHJhdGlvICE9PSAxID8gc291cmNlLmhlaWdodCA6IGluaXRpYWxIZWlnaHQpXG4gICAgICB9KSxcbiAgICAgICAgICB3aWR0aCA9IF9nZXRBZGp1c3RlZFNpemVzLndpZHRoLFxuICAgICAgICAgIGhlaWdodCA9IF9nZXRBZGp1c3RlZFNpemVzLmhlaWdodDtcblxuICAgICAgd2lkdGggPSBNYXRoLm1pbihtYXhTaXplcy53aWR0aCwgTWF0aC5tYXgobWluU2l6ZXMud2lkdGgsIHdpZHRoKSk7XG4gICAgICBoZWlnaHQgPSBNYXRoLm1pbihtYXhTaXplcy5oZWlnaHQsIE1hdGgubWF4KG1pblNpemVzLmhlaWdodCwgaGVpZ2h0KSk7XG4gICAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgY2FudmFzLndpZHRoID0gbm9ybWFsaXplRGVjaW1hbE51bWJlcih3aWR0aCk7XG4gICAgICBjYW52YXMuaGVpZ2h0ID0gbm9ybWFsaXplRGVjaW1hbE51bWJlcihoZWlnaHQpO1xuICAgICAgY29udGV4dC5maWxsU3R5bGUgPSBvcHRpb25zLmZpbGxDb2xvciB8fCAndHJhbnNwYXJlbnQnO1xuICAgICAgY29udGV4dC5maWxsUmVjdCgwLCAwLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgIHZhciBfb3B0aW9ucyRpbWFnZVNtb290aGkgPSBvcHRpb25zLmltYWdlU21vb3RoaW5nRW5hYmxlZCxcbiAgICAgICAgICBpbWFnZVNtb290aGluZ0VuYWJsZWQgPSBfb3B0aW9ucyRpbWFnZVNtb290aGkgPT09IHZvaWQgMCA/IHRydWUgOiBfb3B0aW9ucyRpbWFnZVNtb290aGksXG4gICAgICAgICAgaW1hZ2VTbW9vdGhpbmdRdWFsaXR5ID0gb3B0aW9ucy5pbWFnZVNtb290aGluZ1F1YWxpdHk7XG4gICAgICBjb250ZXh0LmltYWdlU21vb3RoaW5nRW5hYmxlZCA9IGltYWdlU21vb3RoaW5nRW5hYmxlZDtcblxuICAgICAgaWYgKGltYWdlU21vb3RoaW5nUXVhbGl0eSkge1xuICAgICAgICBjb250ZXh0LmltYWdlU21vb3RoaW5nUXVhbGl0eSA9IGltYWdlU21vb3RoaW5nUXVhbGl0eTtcbiAgICAgIH0gLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC5kcmF3SW1hZ2VcblxuXG4gICAgICB2YXIgc291cmNlV2lkdGggPSBzb3VyY2Uud2lkdGg7XG4gICAgICB2YXIgc291cmNlSGVpZ2h0ID0gc291cmNlLmhlaWdodDsgLy8gU291cmNlIGNhbnZhcyBwYXJhbWV0ZXJzXG5cbiAgICAgIHZhciBzcmNYID0gaW5pdGlhbFg7XG4gICAgICB2YXIgc3JjWSA9IGluaXRpYWxZO1xuICAgICAgdmFyIHNyY1dpZHRoO1xuICAgICAgdmFyIHNyY0hlaWdodDsgLy8gRGVzdGluYXRpb24gY2FudmFzIHBhcmFtZXRlcnNcblxuICAgICAgdmFyIGRzdFg7XG4gICAgICB2YXIgZHN0WTtcbiAgICAgIHZhciBkc3RXaWR0aDtcbiAgICAgIHZhciBkc3RIZWlnaHQ7XG5cbiAgICAgIGlmIChzcmNYIDw9IC1pbml0aWFsV2lkdGggfHwgc3JjWCA+IHNvdXJjZVdpZHRoKSB7XG4gICAgICAgIHNyY1ggPSAwO1xuICAgICAgICBzcmNXaWR0aCA9IDA7XG4gICAgICAgIGRzdFggPSAwO1xuICAgICAgICBkc3RXaWR0aCA9IDA7XG4gICAgICB9IGVsc2UgaWYgKHNyY1ggPD0gMCkge1xuICAgICAgICBkc3RYID0gLXNyY1g7XG4gICAgICAgIHNyY1ggPSAwO1xuICAgICAgICBzcmNXaWR0aCA9IE1hdGgubWluKHNvdXJjZVdpZHRoLCBpbml0aWFsV2lkdGggKyBzcmNYKTtcbiAgICAgICAgZHN0V2lkdGggPSBzcmNXaWR0aDtcbiAgICAgIH0gZWxzZSBpZiAoc3JjWCA8PSBzb3VyY2VXaWR0aCkge1xuICAgICAgICBkc3RYID0gMDtcbiAgICAgICAgc3JjV2lkdGggPSBNYXRoLm1pbihpbml0aWFsV2lkdGgsIHNvdXJjZVdpZHRoIC0gc3JjWCk7XG4gICAgICAgIGRzdFdpZHRoID0gc3JjV2lkdGg7XG4gICAgICB9XG5cbiAgICAgIGlmIChzcmNXaWR0aCA8PSAwIHx8IHNyY1kgPD0gLWluaXRpYWxIZWlnaHQgfHwgc3JjWSA+IHNvdXJjZUhlaWdodCkge1xuICAgICAgICBzcmNZID0gMDtcbiAgICAgICAgc3JjSGVpZ2h0ID0gMDtcbiAgICAgICAgZHN0WSA9IDA7XG4gICAgICAgIGRzdEhlaWdodCA9IDA7XG4gICAgICB9IGVsc2UgaWYgKHNyY1kgPD0gMCkge1xuICAgICAgICBkc3RZID0gLXNyY1k7XG4gICAgICAgIHNyY1kgPSAwO1xuICAgICAgICBzcmNIZWlnaHQgPSBNYXRoLm1pbihzb3VyY2VIZWlnaHQsIGluaXRpYWxIZWlnaHQgKyBzcmNZKTtcbiAgICAgICAgZHN0SGVpZ2h0ID0gc3JjSGVpZ2h0O1xuICAgICAgfSBlbHNlIGlmIChzcmNZIDw9IHNvdXJjZUhlaWdodCkge1xuICAgICAgICBkc3RZID0gMDtcbiAgICAgICAgc3JjSGVpZ2h0ID0gTWF0aC5taW4oaW5pdGlhbEhlaWdodCwgc291cmNlSGVpZ2h0IC0gc3JjWSk7XG4gICAgICAgIGRzdEhlaWdodCA9IHNyY0hlaWdodDtcbiAgICAgIH1cblxuICAgICAgdmFyIHBhcmFtcyA9IFtzcmNYLCBzcmNZLCBzcmNXaWR0aCwgc3JjSGVpZ2h0XTsgLy8gQXZvaWQgXCJJbmRleFNpemVFcnJvclwiXG5cbiAgICAgIGlmIChkc3RXaWR0aCA+IDAgJiYgZHN0SGVpZ2h0ID4gMCkge1xuICAgICAgICB2YXIgc2NhbGUgPSB3aWR0aCAvIGluaXRpYWxXaWR0aDtcbiAgICAgICAgcGFyYW1zLnB1c2goZHN0WCAqIHNjYWxlLCBkc3RZICogc2NhbGUsIGRzdFdpZHRoICogc2NhbGUsIGRzdEhlaWdodCAqIHNjYWxlKTtcbiAgICAgIH0gLy8gQWxsIHRoZSBudW1lcmljYWwgcGFyYW1ldGVycyBzaG91bGQgYmUgaW50ZWdlciBmb3IgYGRyYXdJbWFnZWBcbiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9mZW5neXVhbmNoZW4vY3JvcHBlci9pc3N1ZXMvNDc2XG5cblxuICAgICAgY29udGV4dC5kcmF3SW1hZ2UuYXBwbHkoY29udGV4dCwgW3NvdXJjZV0uY29uY2F0KF90b0NvbnN1bWFibGVBcnJheShwYXJhbXMubWFwKGZ1bmN0aW9uIChwYXJhbSkge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihub3JtYWxpemVEZWNpbWFsTnVtYmVyKHBhcmFtKSk7XG4gICAgICB9KSkpKTtcbiAgICAgIHJldHVybiBjYW52YXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENoYW5nZSB0aGUgYXNwZWN0IHJhdGlvIG9mIHRoZSBjcm9wIGJveC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYXNwZWN0UmF0aW8gLSBUaGUgbmV3IGFzcGVjdCByYXRpby5cbiAgICAgKiBAcmV0dXJucyB7Q3JvcHBlcn0gdGhpc1xuICAgICAqL1xuICAgIHNldEFzcGVjdFJhdGlvOiBmdW5jdGlvbiBzZXRBc3BlY3RSYXRpbyhhc3BlY3RSYXRpbykge1xuICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cbiAgICAgIGlmICghdGhpcy5kaXNhYmxlZCAmJiAhaXNVbmRlZmluZWQoYXNwZWN0UmF0aW8pKSB7XG4gICAgICAgIC8vIDAgLT4gTmFOXG4gICAgICAgIG9wdGlvbnMuYXNwZWN0UmF0aW8gPSBNYXRoLm1heCgwLCBhc3BlY3RSYXRpbykgfHwgTmFOO1xuXG4gICAgICAgIGlmICh0aGlzLnJlYWR5KSB7XG4gICAgICAgICAgdGhpcy5pbml0Q3JvcEJveCgpO1xuXG4gICAgICAgICAgaWYgKHRoaXMuY3JvcHBlZCkge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJDcm9wQm94KCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2UgdGhlIGRyYWcgbW9kZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbW9kZSAtIFRoZSBuZXcgZHJhZyBtb2RlLlxuICAgICAqIEByZXR1cm5zIHtDcm9wcGVyfSB0aGlzXG4gICAgICovXG4gICAgc2V0RHJhZ01vZGU6IGZ1bmN0aW9uIHNldERyYWdNb2RlKG1vZGUpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICAgIGRyYWdCb3ggPSB0aGlzLmRyYWdCb3gsXG4gICAgICAgICAgZmFjZSA9IHRoaXMuZmFjZTtcblxuICAgICAgaWYgKHRoaXMucmVhZHkgJiYgIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgdmFyIGNyb3BwYWJsZSA9IG1vZGUgPT09IERSQUdfTU9ERV9DUk9QO1xuICAgICAgICB2YXIgbW92YWJsZSA9IG9wdGlvbnMubW92YWJsZSAmJiBtb2RlID09PSBEUkFHX01PREVfTU9WRTtcbiAgICAgICAgbW9kZSA9IGNyb3BwYWJsZSB8fCBtb3ZhYmxlID8gbW9kZSA6IERSQUdfTU9ERV9OT05FO1xuICAgICAgICBvcHRpb25zLmRyYWdNb2RlID0gbW9kZTtcbiAgICAgICAgc2V0RGF0YShkcmFnQm94LCBEQVRBX0FDVElPTiwgbW9kZSk7XG4gICAgICAgIHRvZ2dsZUNsYXNzKGRyYWdCb3gsIENMQVNTX0NST1AsIGNyb3BwYWJsZSk7XG4gICAgICAgIHRvZ2dsZUNsYXNzKGRyYWdCb3gsIENMQVNTX01PVkUsIG1vdmFibGUpO1xuXG4gICAgICAgIGlmICghb3B0aW9ucy5jcm9wQm94TW92YWJsZSkge1xuICAgICAgICAgIC8vIFN5bmMgZHJhZyBtb2RlIHRvIGNyb3AgYm94IHdoZW4gaXQgaXMgbm90IG1vdmFibGVcbiAgICAgICAgICBzZXREYXRhKGZhY2UsIERBVEFfQUNUSU9OLCBtb2RlKTtcbiAgICAgICAgICB0b2dnbGVDbGFzcyhmYWNlLCBDTEFTU19DUk9QLCBjcm9wcGFibGUpO1xuICAgICAgICAgIHRvZ2dsZUNsYXNzKGZhY2UsIENMQVNTX01PVkUsIG1vdmFibGUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfTtcblxuICB2YXIgQW5vdGhlckNyb3BwZXIgPSBXSU5ET1cuQ3JvcHBlcjtcblxuICB2YXIgQ3JvcHBlciA9XG4gIC8qI19fUFVSRV9fKi9cbiAgZnVuY3Rpb24gKCkge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIG5ldyBDcm9wcGVyLlxuICAgICAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudCAtIFRoZSB0YXJnZXQgZWxlbWVudCBmb3IgY3JvcHBpbmcuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSAtIFRoZSBjb25maWd1cmF0aW9uIG9wdGlvbnMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gQ3JvcHBlcihlbGVtZW50KSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDcm9wcGVyKTtcblxuICAgICAgaWYgKCFlbGVtZW50IHx8ICFSRUdFWFBfVEFHX05BTUUudGVzdChlbGVtZW50LnRhZ05hbWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGZpcnN0IGFyZ3VtZW50IGlzIHJlcXVpcmVkIGFuZCBtdXN0IGJlIGFuIDxpbWc+IG9yIDxjYW52YXM+IGVsZW1lbnQuJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICB0aGlzLm9wdGlvbnMgPSBhc3NpZ24oe30sIERFRkFVTFRTLCBpc1BsYWluT2JqZWN0KG9wdGlvbnMpICYmIG9wdGlvbnMpO1xuICAgICAgdGhpcy5jcm9wcGVkID0gZmFsc2U7XG4gICAgICB0aGlzLmRpc2FibGVkID0gZmFsc2U7XG4gICAgICB0aGlzLnBvaW50ZXJzID0ge307XG4gICAgICB0aGlzLnJlYWR5ID0gZmFsc2U7XG4gICAgICB0aGlzLnJlbG9hZGluZyA9IGZhbHNlO1xuICAgICAgdGhpcy5yZXBsYWNlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5zaXplZCA9IGZhbHNlO1xuICAgICAgdGhpcy5zaXppbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMuaW5pdCgpO1xuICAgIH1cblxuICAgIF9jcmVhdGVDbGFzcyhDcm9wcGVyLCBbe1xuICAgICAga2V5OiBcImluaXRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0KCkge1xuICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXMuZWxlbWVudDtcbiAgICAgICAgdmFyIHRhZ05hbWUgPSBlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgdmFyIHVybDtcblxuICAgICAgICBpZiAoZWxlbWVudFtOQU1FU1BBQ0VdKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZWxlbWVudFtOQU1FU1BBQ0VdID0gdGhpcztcblxuICAgICAgICBpZiAodGFnTmFtZSA9PT0gJ2ltZycpIHtcbiAgICAgICAgICB0aGlzLmlzSW1nID0gdHJ1ZTsgLy8gZS5nLjogXCJpbWcvcGljdHVyZS5qcGdcIlxuXG4gICAgICAgICAgdXJsID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3NyYycpIHx8ICcnO1xuICAgICAgICAgIHRoaXMub3JpZ2luYWxVcmwgPSB1cmw7IC8vIFN0b3Agd2hlbiBpdCdzIGEgYmxhbmsgaW1hZ2VcblxuICAgICAgICAgIGlmICghdXJsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfSAvLyBlLmcuOiBcImh0dHA6Ly9leGFtcGxlLmNvbS9pbWcvcGljdHVyZS5qcGdcIlxuXG5cbiAgICAgICAgICB1cmwgPSBlbGVtZW50LnNyYztcbiAgICAgICAgfSBlbHNlIGlmICh0YWdOYW1lID09PSAnY2FudmFzJyAmJiB3aW5kb3cuSFRNTENhbnZhc0VsZW1lbnQpIHtcbiAgICAgICAgICB1cmwgPSBlbGVtZW50LnRvRGF0YVVSTCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5sb2FkKHVybCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImxvYWRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBsb2FkKHVybCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIGlmICghdXJsKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cmwgPSB1cmw7XG4gICAgICAgIHRoaXMuaW1hZ2VEYXRhID0ge307XG4gICAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5lbGVtZW50LFxuICAgICAgICAgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcblxuICAgICAgICBpZiAoIW9wdGlvbnMucm90YXRhYmxlICYmICFvcHRpb25zLnNjYWxhYmxlKSB7XG4gICAgICAgICAgb3B0aW9ucy5jaGVja09yaWVudGF0aW9uID0gZmFsc2U7XG4gICAgICAgIH0gLy8gT25seSBJRTEwKyBzdXBwb3J0cyBUeXBlZCBBcnJheXNcblxuXG4gICAgICAgIGlmICghb3B0aW9ucy5jaGVja09yaWVudGF0aW9uIHx8ICF3aW5kb3cuQXJyYXlCdWZmZXIpIHtcbiAgICAgICAgICB0aGlzLmNsb25lKCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IC8vIERldGVjdCB0aGUgbWltZSB0eXBlIG9mIHRoZSBpbWFnZSBkaXJlY3RseSBpZiBpdCBpcyBhIERhdGEgVVJMXG5cblxuICAgICAgICBpZiAoUkVHRVhQX0RBVEFfVVJMLnRlc3QodXJsKSkge1xuICAgICAgICAgIC8vIFJlYWQgQXJyYXlCdWZmZXIgZnJvbSBEYXRhIFVSTCBvZiBKUEVHIGltYWdlcyBkaXJlY3RseSBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlXG4gICAgICAgICAgaWYgKFJFR0VYUF9EQVRBX1VSTF9KUEVHLnRlc3QodXJsKSkge1xuICAgICAgICAgICAgdGhpcy5yZWFkKGRhdGFVUkxUb0FycmF5QnVmZmVyKHVybCkpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPbmx5IGEgSlBFRyBpbWFnZSBtYXkgY29udGFpbnMgRXhpZiBPcmllbnRhdGlvbiBpbmZvcm1hdGlvbixcbiAgICAgICAgICAgIC8vIHRoZSByZXN0IHR5cGVzIG9mIERhdGEgVVJMcyBhcmUgbm90IG5lY2Vzc2FyeSB0byBjaGVjayBvcmllbnRhdGlvbiBhdCBhbGwuXG4gICAgICAgICAgICB0aGlzLmNsb25lKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IC8vIDEuIERldGVjdCB0aGUgbWltZSB0eXBlIG9mIHRoZSBpbWFnZSBieSBhIFhNTEh0dHBSZXF1ZXN0LlxuICAgICAgICAvLyAyLiBMb2FkIHRoZSBpbWFnZSBhcyBBcnJheUJ1ZmZlciBmb3IgcmVhZGluZyBvcmllbnRhdGlvbiBpZiBpdHMgYSBKUEVHIGltYWdlLlxuXG5cbiAgICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICB2YXIgY2xvbmUgPSB0aGlzLmNsb25lLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMucmVsb2FkaW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy54aHIgPSB4aHI7IC8vIDEuIENyb3NzIG9yaWdpbiByZXF1ZXN0cyBhcmUgb25seSBzdXBwb3J0ZWQgZm9yIHByb3RvY29sIHNjaGVtZXM6XG4gICAgICAgIC8vIGh0dHAsIGh0dHBzLCBkYXRhLCBjaHJvbWUsIGNocm9tZS1leHRlbnNpb24uXG4gICAgICAgIC8vIDIuIEFjY2VzcyB0byBYTUxIdHRwUmVxdWVzdCBmcm9tIGEgRGF0YSBVUkwgd2lsbCBiZSBibG9ja2VkIGJ5IENPUlMgcG9saWN5XG4gICAgICAgIC8vIGluIHNvbWUgYnJvd3NlcnMgYXMgSUUxMSBhbmQgU2FmYXJpLlxuXG4gICAgICAgIHhoci5vbmFib3J0ID0gY2xvbmU7XG4gICAgICAgIHhoci5vbmVycm9yID0gY2xvbmU7XG4gICAgICAgIHhoci5vbnRpbWVvdXQgPSBjbG9uZTtcblxuICAgICAgICB4aHIub25wcm9ncmVzcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAvLyBBYm9ydCB0aGUgcmVxdWVzdCBkaXJlY3RseSBpZiBpdCBub3QgYSBKUEVHIGltYWdlIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcbiAgICAgICAgICBpZiAoeGhyLmdldFJlc3BvbnNlSGVhZGVyKCdjb250ZW50LXR5cGUnKSAhPT0gTUlNRV9UWVBFX0pQRUcpIHtcbiAgICAgICAgICAgIHhoci5hYm9ydCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB4aHIub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnJlYWQoeGhyLnJlc3BvbnNlKTtcbiAgICAgICAgfTtcblxuICAgICAgICB4aHIub25sb2FkZW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnJlbG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgIF90aGlzLnhociA9IG51bGw7XG4gICAgICAgIH07IC8vIEJ1c3QgY2FjaGUgd2hlbiB0aGVyZSBpcyBhIFwiY3Jvc3NPcmlnaW5cIiBwcm9wZXJ0eSB0byBhdm9pZCBicm93c2VyIGNhY2hlIGVycm9yXG5cblxuICAgICAgICBpZiAob3B0aW9ucy5jaGVja0Nyb3NzT3JpZ2luICYmIGlzQ3Jvc3NPcmlnaW5VUkwodXJsKSAmJiBlbGVtZW50LmNyb3NzT3JpZ2luKSB7XG4gICAgICAgICAgdXJsID0gYWRkVGltZXN0YW1wKHVybCk7XG4gICAgICAgIH1cblxuICAgICAgICB4aHIub3BlbignR0VUJywgdXJsKTtcbiAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9ICdhcnJheWJ1ZmZlcic7XG4gICAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSBlbGVtZW50LmNyb3NzT3JpZ2luID09PSAndXNlLWNyZWRlbnRpYWxzJztcbiAgICAgICAgeGhyLnNlbmQoKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwicmVhZFwiLFxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlYWQoYXJyYXlCdWZmZXIpIHtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG4gICAgICAgICAgICBpbWFnZURhdGEgPSB0aGlzLmltYWdlRGF0YTsgLy8gUmVzZXQgdGhlIG9yaWVudGF0aW9uIHZhbHVlIHRvIGl0cyBkZWZhdWx0IHZhbHVlIDFcbiAgICAgICAgLy8gYXMgc29tZSBpT1MgYnJvd3NlcnMgd2lsbCByZW5kZXIgaW1hZ2Ugd2l0aCBpdHMgb3JpZW50YXRpb25cblxuICAgICAgICB2YXIgb3JpZW50YXRpb24gPSByZXNldEFuZEdldE9yaWVudGF0aW9uKGFycmF5QnVmZmVyKTtcbiAgICAgICAgdmFyIHJvdGF0ZSA9IDA7XG4gICAgICAgIHZhciBzY2FsZVggPSAxO1xuICAgICAgICB2YXIgc2NhbGVZID0gMTtcblxuICAgICAgICBpZiAob3JpZW50YXRpb24gPiAxKSB7XG4gICAgICAgICAgLy8gR2VuZXJhdGUgYSBuZXcgVVJMIHdoaWNoIGhhcyB0aGUgZGVmYXVsdCBvcmllbnRhdGlvbiB2YWx1ZVxuICAgICAgICAgIHRoaXMudXJsID0gYXJyYXlCdWZmZXJUb0RhdGFVUkwoYXJyYXlCdWZmZXIsIE1JTUVfVFlQRV9KUEVHKTtcblxuICAgICAgICAgIHZhciBfcGFyc2VPcmllbnRhdGlvbiA9IHBhcnNlT3JpZW50YXRpb24ob3JpZW50YXRpb24pO1xuXG4gICAgICAgICAgcm90YXRlID0gX3BhcnNlT3JpZW50YXRpb24ucm90YXRlO1xuICAgICAgICAgIHNjYWxlWCA9IF9wYXJzZU9yaWVudGF0aW9uLnNjYWxlWDtcbiAgICAgICAgICBzY2FsZVkgPSBfcGFyc2VPcmllbnRhdGlvbi5zY2FsZVk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5yb3RhdGFibGUpIHtcbiAgICAgICAgICBpbWFnZURhdGEucm90YXRlID0gcm90YXRlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuc2NhbGFibGUpIHtcbiAgICAgICAgICBpbWFnZURhdGEuc2NhbGVYID0gc2NhbGVYO1xuICAgICAgICAgIGltYWdlRGF0YS5zY2FsZVkgPSBzY2FsZVk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNsb25lKCk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcImNsb25lXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gY2xvbmUoKSB7XG4gICAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5lbGVtZW50LFxuICAgICAgICAgICAgdXJsID0gdGhpcy51cmw7XG4gICAgICAgIHZhciBjcm9zc09yaWdpbiA9IGVsZW1lbnQuY3Jvc3NPcmlnaW47XG4gICAgICAgIHZhciBjcm9zc09yaWdpblVybCA9IHVybDtcblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmNoZWNrQ3Jvc3NPcmlnaW4gJiYgaXNDcm9zc09yaWdpblVSTCh1cmwpKSB7XG4gICAgICAgICAgaWYgKCFjcm9zc09yaWdpbikge1xuICAgICAgICAgICAgY3Jvc3NPcmlnaW4gPSAnYW5vbnltb3VzJztcbiAgICAgICAgICB9IC8vIEJ1c3QgY2FjaGUgd2hlbiB0aGVyZSBpcyBub3QgYSBcImNyb3NzT3JpZ2luXCIgcHJvcGVydHkgKCM1MTkpXG5cblxuICAgICAgICAgIGNyb3NzT3JpZ2luVXJsID0gYWRkVGltZXN0YW1wKHVybCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNyb3NzT3JpZ2luID0gY3Jvc3NPcmlnaW47XG4gICAgICAgIHRoaXMuY3Jvc3NPcmlnaW5VcmwgPSBjcm9zc09yaWdpblVybDtcbiAgICAgICAgdmFyIGltYWdlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyk7XG5cbiAgICAgICAgaWYgKGNyb3NzT3JpZ2luKSB7XG4gICAgICAgICAgaW1hZ2UuY3Jvc3NPcmlnaW4gPSBjcm9zc09yaWdpbjtcbiAgICAgICAgfVxuXG4gICAgICAgIGltYWdlLnNyYyA9IGNyb3NzT3JpZ2luVXJsIHx8IHVybDtcbiAgICAgICAgaW1hZ2UuYWx0ID0gZWxlbWVudC5hbHQgfHwgJ1RoZSBpbWFnZSB0byBjcm9wJztcbiAgICAgICAgdGhpcy5pbWFnZSA9IGltYWdlO1xuICAgICAgICBpbWFnZS5vbmxvYWQgPSB0aGlzLnN0YXJ0LmJpbmQodGhpcyk7XG4gICAgICAgIGltYWdlLm9uZXJyb3IgPSB0aGlzLnN0b3AuYmluZCh0aGlzKTtcbiAgICAgICAgYWRkQ2xhc3MoaW1hZ2UsIENMQVNTX0hJREUpO1xuICAgICAgICBlbGVtZW50LnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGltYWdlLCBlbGVtZW50Lm5leHRTaWJsaW5nKTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwic3RhcnRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBzdGFydCgpIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGltYWdlID0gdGhpcy5pbWFnZTtcbiAgICAgICAgaW1hZ2Uub25sb2FkID0gbnVsbDtcbiAgICAgICAgaW1hZ2Uub25lcnJvciA9IG51bGw7XG4gICAgICAgIHRoaXMuc2l6aW5nID0gdHJ1ZTsgLy8gTWF0Y2ggYWxsIGJyb3dzZXJzIHRoYXQgdXNlIFdlYktpdCBhcyB0aGUgbGF5b3V0IGVuZ2luZSBpbiBpT1MgZGV2aWNlcyxcbiAgICAgICAgLy8gc3VjaCBhcyBTYWZhcmkgZm9yIGlPUywgQ2hyb21lIGZvciBpT1MsIGFuZCBpbi1hcHAgYnJvd3NlcnMuXG5cbiAgICAgICAgdmFyIGlzSU9TV2ViS2l0ID0gV0lORE9XLm5hdmlnYXRvciAmJiAvKD86aVBhZHxpUGhvbmV8aVBvZCkuKj9BcHBsZVdlYktpdC9pLnRlc3QoV0lORE9XLm5hdmlnYXRvci51c2VyQWdlbnQpO1xuXG4gICAgICAgIHZhciBkb25lID0gZnVuY3Rpb24gZG9uZShuYXR1cmFsV2lkdGgsIG5hdHVyYWxIZWlnaHQpIHtcbiAgICAgICAgICBhc3NpZ24oX3RoaXMyLmltYWdlRGF0YSwge1xuICAgICAgICAgICAgbmF0dXJhbFdpZHRoOiBuYXR1cmFsV2lkdGgsXG4gICAgICAgICAgICBuYXR1cmFsSGVpZ2h0OiBuYXR1cmFsSGVpZ2h0LFxuICAgICAgICAgICAgYXNwZWN0UmF0aW86IG5hdHVyYWxXaWR0aCAvIG5hdHVyYWxIZWlnaHRcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBfdGhpczIuc2l6aW5nID0gZmFsc2U7XG4gICAgICAgICAgX3RoaXMyLnNpemVkID0gdHJ1ZTtcblxuICAgICAgICAgIF90aGlzMi5idWlsZCgpO1xuICAgICAgICB9OyAvLyBNb3N0IG1vZGVybiBicm93c2VycyAoZXhjZXB0cyBpT1MgV2ViS2l0KVxuXG5cbiAgICAgICAgaWYgKGltYWdlLm5hdHVyYWxXaWR0aCAmJiAhaXNJT1NXZWJLaXQpIHtcbiAgICAgICAgICBkb25lKGltYWdlLm5hdHVyYWxXaWR0aCwgaW1hZ2UubmF0dXJhbEhlaWdodCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNpemluZ0ltYWdlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyk7XG4gICAgICAgIHZhciBib2R5ID0gZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgICAgIHRoaXMuc2l6aW5nSW1hZ2UgPSBzaXppbmdJbWFnZTtcblxuICAgICAgICBzaXppbmdJbWFnZS5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgZG9uZShzaXppbmdJbWFnZS53aWR0aCwgc2l6aW5nSW1hZ2UuaGVpZ2h0KTtcblxuICAgICAgICAgIGlmICghaXNJT1NXZWJLaXQpIHtcbiAgICAgICAgICAgIGJvZHkucmVtb3ZlQ2hpbGQoc2l6aW5nSW1hZ2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBzaXppbmdJbWFnZS5zcmMgPSBpbWFnZS5zcmM7IC8vIGlPUyBXZWJLaXQgd2lsbCBjb252ZXJ0IHRoZSBpbWFnZSBhdXRvbWF0aWNhbGx5XG4gICAgICAgIC8vIHdpdGggaXRzIG9yaWVudGF0aW9uIG9uY2UgYXBwZW5kIGl0IGludG8gRE9NICgjMjc5KVxuXG4gICAgICAgIGlmICghaXNJT1NXZWJLaXQpIHtcbiAgICAgICAgICBzaXppbmdJbWFnZS5zdHlsZS5jc3NUZXh0ID0gJ2xlZnQ6MDsnICsgJ21heC1oZWlnaHQ6bm9uZSFpbXBvcnRhbnQ7JyArICdtYXgtd2lkdGg6bm9uZSFpbXBvcnRhbnQ7JyArICdtaW4taGVpZ2h0OjAhaW1wb3J0YW50OycgKyAnbWluLXdpZHRoOjAhaW1wb3J0YW50OycgKyAnb3BhY2l0eTowOycgKyAncG9zaXRpb246YWJzb2x1dGU7JyArICd0b3A6MDsnICsgJ3otaW5kZXg6LTE7JztcbiAgICAgICAgICBib2R5LmFwcGVuZENoaWxkKHNpemluZ0ltYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJzdG9wXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gc3RvcCgpIHtcbiAgICAgICAgdmFyIGltYWdlID0gdGhpcy5pbWFnZTtcbiAgICAgICAgaW1hZ2Uub25sb2FkID0gbnVsbDtcbiAgICAgICAgaW1hZ2Uub25lcnJvciA9IG51bGw7XG4gICAgICAgIGltYWdlLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoaW1hZ2UpO1xuICAgICAgICB0aGlzLmltYWdlID0gbnVsbDtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiYnVpbGRcIixcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBidWlsZCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNpemVkIHx8IHRoaXMucmVhZHkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXMuZWxlbWVudCxcbiAgICAgICAgICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG4gICAgICAgICAgICBpbWFnZSA9IHRoaXMuaW1hZ2U7IC8vIENyZWF0ZSBjcm9wcGVyIGVsZW1lbnRzXG5cbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IGVsZW1lbnQucGFyZW50Tm9kZTtcbiAgICAgICAgdmFyIHRlbXBsYXRlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIHRlbXBsYXRlLmlubmVySFRNTCA9IFRFTVBMQVRFO1xuICAgICAgICB2YXIgY3JvcHBlciA9IHRlbXBsYXRlLnF1ZXJ5U2VsZWN0b3IoXCIuXCIuY29uY2F0KE5BTUVTUEFDRSwgXCItY29udGFpbmVyXCIpKTtcbiAgICAgICAgdmFyIGNhbnZhcyA9IGNyb3BwZXIucXVlcnlTZWxlY3RvcihcIi5cIi5jb25jYXQoTkFNRVNQQUNFLCBcIi1jYW52YXNcIikpO1xuICAgICAgICB2YXIgZHJhZ0JveCA9IGNyb3BwZXIucXVlcnlTZWxlY3RvcihcIi5cIi5jb25jYXQoTkFNRVNQQUNFLCBcIi1kcmFnLWJveFwiKSk7XG4gICAgICAgIHZhciBjcm9wQm94ID0gY3JvcHBlci5xdWVyeVNlbGVjdG9yKFwiLlwiLmNvbmNhdChOQU1FU1BBQ0UsIFwiLWNyb3AtYm94XCIpKTtcbiAgICAgICAgdmFyIGZhY2UgPSBjcm9wQm94LnF1ZXJ5U2VsZWN0b3IoXCIuXCIuY29uY2F0KE5BTUVTUEFDRSwgXCItZmFjZVwiKSk7XG4gICAgICAgIHRoaXMuY29udGFpbmVyID0gY29udGFpbmVyO1xuICAgICAgICB0aGlzLmNyb3BwZXIgPSBjcm9wcGVyO1xuICAgICAgICB0aGlzLmNhbnZhcyA9IGNhbnZhcztcbiAgICAgICAgdGhpcy5kcmFnQm94ID0gZHJhZ0JveDtcbiAgICAgICAgdGhpcy5jcm9wQm94ID0gY3JvcEJveDtcbiAgICAgICAgdGhpcy52aWV3Qm94ID0gY3JvcHBlci5xdWVyeVNlbGVjdG9yKFwiLlwiLmNvbmNhdChOQU1FU1BBQ0UsIFwiLXZpZXctYm94XCIpKTtcbiAgICAgICAgdGhpcy5mYWNlID0gZmFjZTtcbiAgICAgICAgY2FudmFzLmFwcGVuZENoaWxkKGltYWdlKTsgLy8gSGlkZSB0aGUgb3JpZ2luYWwgaW1hZ2VcblxuICAgICAgICBhZGRDbGFzcyhlbGVtZW50LCBDTEFTU19ISURERU4pOyAvLyBJbnNlcnRzIHRoZSBjcm9wcGVyIGFmdGVyIHRvIHRoZSBjdXJyZW50IGltYWdlXG5cbiAgICAgICAgY29udGFpbmVyLmluc2VydEJlZm9yZShjcm9wcGVyLCBlbGVtZW50Lm5leHRTaWJsaW5nKTsgLy8gU2hvdyB0aGUgaW1hZ2UgaWYgaXMgaGlkZGVuXG5cbiAgICAgICAgaWYgKCF0aGlzLmlzSW1nKSB7XG4gICAgICAgICAgcmVtb3ZlQ2xhc3MoaW1hZ2UsIENMQVNTX0hJREUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pbml0UHJldmlldygpO1xuICAgICAgICB0aGlzLmJpbmQoKTtcbiAgICAgICAgb3B0aW9ucy5pbml0aWFsQXNwZWN0UmF0aW8gPSBNYXRoLm1heCgwLCBvcHRpb25zLmluaXRpYWxBc3BlY3RSYXRpbykgfHwgTmFOO1xuICAgICAgICBvcHRpb25zLmFzcGVjdFJhdGlvID0gTWF0aC5tYXgoMCwgb3B0aW9ucy5hc3BlY3RSYXRpbykgfHwgTmFOO1xuICAgICAgICBvcHRpb25zLnZpZXdNb2RlID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMywgTWF0aC5yb3VuZChvcHRpb25zLnZpZXdNb2RlKSkpIHx8IDA7XG4gICAgICAgIGFkZENsYXNzKGNyb3BCb3gsIENMQVNTX0hJRERFTik7XG5cbiAgICAgICAgaWYgKCFvcHRpb25zLmd1aWRlcykge1xuICAgICAgICAgIGFkZENsYXNzKGNyb3BCb3guZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcIlwiLmNvbmNhdChOQU1FU1BBQ0UsIFwiLWRhc2hlZFwiKSksIENMQVNTX0hJRERFTik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIW9wdGlvbnMuY2VudGVyKSB7XG4gICAgICAgICAgYWRkQ2xhc3MoY3JvcEJveC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiXCIuY29uY2F0KE5BTUVTUEFDRSwgXCItY2VudGVyXCIpKSwgQ0xBU1NfSElEREVOKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zLmJhY2tncm91bmQpIHtcbiAgICAgICAgICBhZGRDbGFzcyhjcm9wcGVyLCBcIlwiLmNvbmNhdChOQU1FU1BBQ0UsIFwiLWJnXCIpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghb3B0aW9ucy5oaWdobGlnaHQpIHtcbiAgICAgICAgICBhZGRDbGFzcyhmYWNlLCBDTEFTU19JTlZJU0lCTEUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuY3JvcEJveE1vdmFibGUpIHtcbiAgICAgICAgICBhZGRDbGFzcyhmYWNlLCBDTEFTU19NT1ZFKTtcbiAgICAgICAgICBzZXREYXRhKGZhY2UsIERBVEFfQUNUSU9OLCBBQ1RJT05fQUxMKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghb3B0aW9ucy5jcm9wQm94UmVzaXphYmxlKSB7XG4gICAgICAgICAgYWRkQ2xhc3MoY3JvcEJveC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiXCIuY29uY2F0KE5BTUVTUEFDRSwgXCItbGluZVwiKSksIENMQVNTX0hJRERFTik7XG4gICAgICAgICAgYWRkQ2xhc3MoY3JvcEJveC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiXCIuY29uY2F0KE5BTUVTUEFDRSwgXCItcG9pbnRcIikpLCBDTEFTU19ISURERU4pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgICAgdGhpcy5yZWFkeSA9IHRydWU7XG4gICAgICAgIHRoaXMuc2V0RHJhZ01vZGUob3B0aW9ucy5kcmFnTW9kZSk7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuYXV0b0Nyb3ApIHtcbiAgICAgICAgICB0aGlzLmNyb3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0RGF0YShvcHRpb25zLmRhdGEpO1xuXG4gICAgICAgIGlmIChpc0Z1bmN0aW9uKG9wdGlvbnMucmVhZHkpKSB7XG4gICAgICAgICAgYWRkTGlzdGVuZXIoZWxlbWVudCwgRVZFTlRfUkVBRFksIG9wdGlvbnMucmVhZHksIHtcbiAgICAgICAgICAgIG9uY2U6IHRydWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRpc3BhdGNoRXZlbnQoZWxlbWVudCwgRVZFTlRfUkVBRFkpO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJ1bmJ1aWxkXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdW5idWlsZCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJlYWR5KSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZWFkeSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnVuYmluZCgpO1xuICAgICAgICB0aGlzLnJlc2V0UHJldmlldygpO1xuICAgICAgICB0aGlzLmNyb3BwZXIucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLmNyb3BwZXIpO1xuICAgICAgICByZW1vdmVDbGFzcyh0aGlzLmVsZW1lbnQsIENMQVNTX0hJRERFTik7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcInVuY3JlYXRlXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gdW5jcmVhdGUoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlYWR5KSB7XG4gICAgICAgICAgdGhpcy51bmJ1aWxkKCk7XG4gICAgICAgICAgdGhpcy5yZWFkeSA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMuY3JvcHBlZCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2l6aW5nKSB7XG4gICAgICAgICAgdGhpcy5zaXppbmdJbWFnZS5vbmxvYWQgPSBudWxsO1xuICAgICAgICAgIHRoaXMuc2l6aW5nID0gZmFsc2U7XG4gICAgICAgICAgdGhpcy5zaXplZCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMucmVsb2FkaW5nKSB7XG4gICAgICAgICAgdGhpcy54aHIub25hYm9ydCA9IG51bGw7XG4gICAgICAgICAgdGhpcy54aHIuYWJvcnQoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmltYWdlKSB7XG4gICAgICAgICAgdGhpcy5zdG9wKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8qKlxuICAgICAgICogR2V0IHRoZSBubyBjb25mbGljdCBjcm9wcGVyIGNsYXNzLlxuICAgICAgICogQHJldHVybnMge0Nyb3BwZXJ9IFRoZSBjcm9wcGVyIGNsYXNzLlxuICAgICAgICovXG5cbiAgICB9XSwgW3tcbiAgICAgIGtleTogXCJub0NvbmZsaWN0XCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gbm9Db25mbGljdCgpIHtcbiAgICAgICAgd2luZG93LkNyb3BwZXIgPSBBbm90aGVyQ3JvcHBlcjtcbiAgICAgICAgcmV0dXJuIENyb3BwZXI7XG4gICAgICB9XG4gICAgICAvKipcbiAgICAgICAqIENoYW5nZSB0aGUgZGVmYXVsdCBvcHRpb25zLlxuICAgICAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBUaGUgbmV3IGRlZmF1bHQgb3B0aW9ucy5cbiAgICAgICAqL1xuXG4gICAgfSwge1xuICAgICAga2V5OiBcInNldERlZmF1bHRzXCIsXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gc2V0RGVmYXVsdHMob3B0aW9ucykge1xuICAgICAgICBhc3NpZ24oREVGQVVMVFMsIGlzUGxhaW5PYmplY3Qob3B0aW9ucykgJiYgb3B0aW9ucyk7XG4gICAgICB9XG4gICAgfV0pO1xuXG4gICAgcmV0dXJuIENyb3BwZXI7XG4gIH0oKTtcblxuICBhc3NpZ24oQ3JvcHBlci5wcm90b3R5cGUsIHJlbmRlciwgcHJldmlldywgZXZlbnRzLCBoYW5kbGVycywgY2hhbmdlLCBtZXRob2RzKTtcblxuICByZXR1cm4gQ3JvcHBlcjtcblxufSkpO1xuIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///../../../node_modules/cropperjs/dist/cropper.js\n");
|
|
7
|
-
|
|
8
|
-
/***/ })
|
|
9
|
-
|
|
10
|
-
}]);
|