HotUpdate.js 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. (function() {
  2. var nodeEnv = typeof require !== 'undefined' && typeof process !== 'undefined';
  3. var __module = nodeEnv ? module : {exports:{}};
  4. var __filename = 'preview-scripts/assets/scriptMain/HotUpdate.js';
  5. var __require = nodeEnv ? function (request) {
  6. return cc.require(request);
  7. } : function (request) {
  8. return __quick_compile_project__.require(request, __filename);
  9. };
  10. function __define (exports, require, module) {
  11. if (!nodeEnv) {__quick_compile_project__.registerModule(__filename, module);}"use strict";
  12. cc._RF.push(module, 'cad1eUCkthF8avyAcwRFs+0', 'HotUpdate');
  13. // scriptMain/HotUpdate.ts
  14. "use strict";
  15. var __extends = (this && this.__extends) || (function () {
  16. var extendStatics = function (d, b) {
  17. extendStatics = Object.setPrototypeOf ||
  18. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  19. function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
  20. return extendStatics(d, b);
  21. };
  22. return function (d, b) {
  23. extendStatics(d, b);
  24. function __() { this.constructor = d; }
  25. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  26. };
  27. })();
  28. var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  29. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  30. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  31. else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  32. return c > 3 && r && Object.defineProperty(target, key, r), r;
  33. };
  34. Object.defineProperty(exports, "__esModule", { value: true });
  35. var _a = cc._decorator, ccclass = _a.ccclass, property = _a.property;
  36. var HotUpdate = /** @class */ (function (_super) {
  37. __extends(HotUpdate, _super);
  38. function HotUpdate() {
  39. var _this = _super !== null && _super.apply(this, arguments) || this;
  40. _this.txtProgress = null;
  41. _this.txtProgressTips = null;
  42. _this.gProgress = null;
  43. _this.imgRole = null;
  44. _this.progress = null;
  45. _this.progressBar = null;
  46. _this.manifestUrl = null;
  47. return _this;
  48. }
  49. HotUpdate.prototype.checkCb = function (event) {
  50. var _this = this;
  51. // cc.log('Code: ' + event.getEventCode());
  52. var isNewVersion = false;
  53. switch (event.getEventCode()) {
  54. case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
  55. console.log("No local manifest file found, hot update skipped.");
  56. break;
  57. case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
  58. case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
  59. console.log("Fail to download manifest file, hot update skipped.");
  60. break;
  61. case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
  62. console.log("Already up to date with the latest remote version.");
  63. this.EnterGame();
  64. break;
  65. case jsb.EventAssetsManager.NEW_VERSION_FOUND:
  66. console.log("New version found, please try to update.(" + this._am.getTotalBytes() + ')');
  67. isNewVersion = true;
  68. break;
  69. default:
  70. return;
  71. }
  72. this._am.setEventCallback(null);
  73. this._checkListener = null;
  74. this._updating = false;
  75. if (isNewVersion) {
  76. //有新版本,显示进度
  77. this.setProgress(0);
  78. this.hotUpdate();
  79. //5秒后判断是否开始下载,如果进度为0.直接进游戏,防止卡死
  80. this.scheduleOnce(function () {
  81. if (_this.progressBar.fillRange == 0) {
  82. _this.EnterGame();
  83. }
  84. }, 10);
  85. }
  86. };
  87. HotUpdate.prototype.setProgress = function (val) {
  88. this.gProgress.active = true;
  89. this.progressBar.fillRange = val;
  90. this.imgRole.x = -this.progress.width / 2 + val * this.progress.width;
  91. this.txtProgress.getComponent(cc.Label).string = Math.floor(val * 100) + "%";
  92. this.txtProgressTips.getComponent(cc.Label).string = "资源更新中";
  93. };
  94. HotUpdate.prototype.updateCb = function (event) {
  95. var needRestart = false;
  96. var failed = false;
  97. // console.log("updateCb event:"+JSON.stringify(event));
  98. switch (event.getEventCode()) {
  99. case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
  100. // console.log('No local manifest file found, hot update skipped.');
  101. failed = true;
  102. break;
  103. case jsb.EventAssetsManager.UPDATE_PROGRESSION:
  104. // this.panel.byteProgress.progress = event.getPercent();
  105. // this.panel.fileProgress.progress = event.getPercentByFile();
  106. // this.panel.fileLabel.string = event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
  107. // this.panel.byteLabel.string = event.getDownloadedBytes() + ' / ' + event.getTotalBytes();
  108. // this.pb_hotUpdate.progress = event.getPercent();
  109. // this.lb_progress.string = Math.floor(event.getPercent()*100).toFixed(2) + '%';
  110. this.setProgress(event.getPercent());
  111. // var msg = event.getMessage();
  112. // if (msg) {
  113. // cc.log(event.getPercent()/100 + '% : ' + msg);
  114. // }
  115. break;
  116. case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
  117. case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
  118. // console.log('Fail to download manifest file, hot update skipped.');
  119. failed = true;
  120. break;
  121. case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
  122. // console.log('Already up to date with the latest remote version.');
  123. failed = true;
  124. break;
  125. case jsb.EventAssetsManager.UPDATE_FINISHED:
  126. // console.log('Update finished. ' + event.getMessage());
  127. needRestart = true;
  128. break;
  129. case jsb.EventAssetsManager.UPDATE_FAILED:
  130. // console.log('Update failed. ' + event.getMessage());
  131. break;
  132. case jsb.EventAssetsManager.ERROR_UPDATING:
  133. // console.log('Asset update error: ' + event.getAssetId() + ', ' + event.getMessage());
  134. break;
  135. case jsb.EventAssetsManager.ERROR_DECOMPRESS:
  136. // console.log("ERROR_DECOMPRESS:"+event.getMessage());
  137. break;
  138. default:
  139. break;
  140. }
  141. if (failed) {
  142. this._am.setEventCallback(null);
  143. this._updateListener = null;
  144. this._updating = false;
  145. this.EnterGame();
  146. }
  147. if (needRestart) {
  148. this._am.setEventCallback(null);
  149. this._updateListener = null;
  150. // Prepend the manifest's search path
  151. var searchPaths = jsb.fileUtils.getSearchPaths();
  152. var newPaths = this._am.getLocalManifest().getSearchPaths();
  153. // console.log(JSON.stringify(newPaths));
  154. for (var i = 0; i < newPaths.length; i++) {
  155. if (searchPaths.indexOf(newPaths[i]) == -1) {
  156. Array.prototype.unshift.apply(searchPaths, [newPaths[i]]);
  157. }
  158. }
  159. // This value will be retrieved and appended to the default search path during game startup,
  160. // please refer to samples/js-tests/main.js for detailed usage.
  161. // !!! Re-add the search paths in main.js is very important, otherwise, new scripts won't take effect.
  162. cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
  163. jsb.fileUtils.setSearchPaths(searchPaths);
  164. cc.audioEngine.stopAll();
  165. cc.game.restart();
  166. }
  167. };
  168. HotUpdate.prototype.retry = function () {
  169. if (!this._updating && this._canRetry) {
  170. this._canRetry = false;
  171. // console.log('Retry failed Assets...');
  172. this._am.downloadFailedAssets();
  173. }
  174. };
  175. HotUpdate.prototype.checkUpdate = function () {
  176. if (this._updating) {
  177. // console.log('Checking or updating ...');
  178. return;
  179. }
  180. if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
  181. // Resolve md5 url
  182. var url = this.manifestUrl.nativeUrl;
  183. if (cc.loader.md5Pipe) {
  184. url = cc.loader.md5Pipe.transformURL(url);
  185. }
  186. this._am.loadLocalManifest(url);
  187. }
  188. if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
  189. console.log('Failed to load local manifest ...');
  190. this.EnterGame();
  191. return;
  192. }
  193. this.getLocalVersion();
  194. this._am.setEventCallback(this.checkCb.bind(this));
  195. this._am.checkUpdate();
  196. this._updating = true;
  197. };
  198. HotUpdate.prototype.hotUpdate = function () {
  199. if (this._am && !this._updating) {
  200. this._am.setEventCallback(this.updateCb.bind(this));
  201. if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
  202. // Resolve md5 url
  203. var url = this.manifestUrl.nativeUrl;
  204. if (cc.loader.md5Pipe) {
  205. url = cc.loader.md5Pipe.transformURL(url);
  206. }
  207. this._am.loadLocalManifest(url);
  208. }
  209. this._failCount = 0;
  210. this._am.update();
  211. this._updating = true;
  212. }
  213. };
  214. // use this for initialization
  215. HotUpdate.prototype.onLoad = function () {
  216. // Hot update is only available in Native build
  217. if (!cc.sys.isNative) {
  218. // this.EnterGame();
  219. return;
  220. }
  221. this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'blackjack-remote-asset');
  222. cc.log('Storage path for remote asset : ' + this._storagePath);
  223. // Setup your own version compare handler, versionA and B is versions in string
  224. // if the return value greater than 0, versionA is greater than B,
  225. // if the return value equals 0, versionA equals to B,
  226. // if the return value smaller than 0, versionA is smaller than B.
  227. this.versionCompareHandle = function (versionA, versionB) {
  228. cc.log("JS Custom Version Compare: version A is " + versionA + ', version B is ' + versionB);
  229. var vA = versionA.split('.');
  230. var vB = versionB.split('.');
  231. for (var i = 0; i < vA.length; ++i) {
  232. var a = parseInt(vA[i]);
  233. var b = parseInt(vB[i] || 0);
  234. if (a === b) {
  235. continue;
  236. }
  237. else {
  238. return a - b;
  239. }
  240. }
  241. if (vB.length > vA.length) {
  242. return -1;
  243. }
  244. else {
  245. return 0;
  246. }
  247. };
  248. // Init with empty manifest url for testing custom manifest
  249. this._am = new jsb.AssetsManager('', this._storagePath, this.versionCompareHandle);
  250. // Setup the verification callback, but we don't have md5 check function yet, so only print some message
  251. // Return true if the verification passed, otherwise return false
  252. this._am.setVerifyCallback(function (path, asset) {
  253. // When asset is compressed, we don't need to check its md5, because zip file have been deleted.
  254. var compressed = asset.compressed;
  255. // Retrieve the correct md5 value.
  256. var expectedMD5 = asset.md5;
  257. // asset.path is relative path and path is absolute.
  258. var relativePath = asset.path;
  259. // The size of asset file, but this value could be absent.
  260. var size = asset.size;
  261. if (compressed) {
  262. // console.log("Verification passed : " + relativePath);
  263. return true;
  264. }
  265. else {
  266. // console.log("Verification passed : " + relativePath + ' (' + expectedMD5 + ')');
  267. return true;
  268. }
  269. });
  270. // // console.log('Hot update is ready, please check or directly update.');
  271. if (cc.sys.os === cc.sys.OS_ANDROID) {
  272. // Some Android device may slow down the download process when concurrent tasks is too much.
  273. // The value may not be accurate, please do more test and find what's most suitable for your game.
  274. this._am.setMaxConcurrentTask(2);
  275. // console.log("Max concurrent tasks count have been limited to 2");
  276. }
  277. // cc.loader.loadRes('/project.manifest',(err,obj)=>{
  278. // if (!err) {
  279. // // let customManifestStr = JSON.stringify(obj);
  280. // let _nativeAsset = JSON.parse(obj._nativeAsset);
  281. // var customManifestStr = JSON.stringify({
  282. // 'packageUrl': _nativeAsset.packageUrl,
  283. // 'remoteManifestUrl': _nativeAsset.remoteManifestUrl,
  284. // 'remoteVersionUrl': _nativeAsset.remoteManifestUrl,
  285. // 'version': _nativeAsset.version,
  286. // 'assets': _nativeAsset.assert,
  287. // 'searchPaths': _nativeAsset.searchPaths
  288. // });
  289. // if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
  290. // var manifest = new jsb.Manifest(customManifestStr, this._storagePath);
  291. // this._am.loadLocalManifest(manifest, this._storagePath);
  292. // }
  293. // }
  294. // });
  295. //开始检测更新
  296. // this.checkUpdate();
  297. };
  298. HotUpdate.prototype.EnterGame = function () {
  299. // 游戏初始化
  300. this.getLocalVersion();
  301. this.scheduleOnce(function () {
  302. cc.director.loadScene("loading");
  303. }, 4);
  304. this._canEnterGame = true;
  305. };
  306. //获取本地版本
  307. HotUpdate.prototype.getLocalVersion = function () {
  308. var localVersion = '';
  309. if (this._am && this._am.getLocalManifest() && !this._updating) {
  310. localVersion = this._am.getLocalManifest().getVersion();
  311. console.log("curVersion1:" + localVersion);
  312. Promise.resolve().then(function () { return require("Config"); }).then(function (cfgParam) {
  313. var config = cfgParam.default;
  314. config.appVersion = localVersion;
  315. console.log("curVersion2:" + localVersion);
  316. });
  317. // console.log("curVersion:"+localVersion);
  318. }
  319. //return localVersion;
  320. };
  321. HotUpdate.prototype.onDestroy = function () {
  322. if (this._updateListener) {
  323. this._am.setEventCallback(null);
  324. this._updateListener = null;
  325. }
  326. };
  327. __decorate([
  328. property({ type: cc.Node })
  329. ], HotUpdate.prototype, "txtProgress", void 0);
  330. __decorate([
  331. property({ type: cc.Node })
  332. ], HotUpdate.prototype, "txtProgressTips", void 0);
  333. __decorate([
  334. property({ type: cc.Node })
  335. ], HotUpdate.prototype, "gProgress", void 0);
  336. __decorate([
  337. property({ type: cc.Node })
  338. ], HotUpdate.prototype, "imgRole", void 0);
  339. __decorate([
  340. property({ type: cc.Node })
  341. ], HotUpdate.prototype, "progress", void 0);
  342. __decorate([
  343. property({ type: cc.Sprite })
  344. ], HotUpdate.prototype, "progressBar", void 0);
  345. __decorate([
  346. property({ type: cc.Asset })
  347. ], HotUpdate.prototype, "manifestUrl", void 0);
  348. HotUpdate = __decorate([
  349. ccclass
  350. ], HotUpdate);
  351. return HotUpdate;
  352. }(cc.Component));
  353. exports.default = HotUpdate;
  354. ;
  355. cc._RF.pop();
  356. }
  357. if (nodeEnv) {
  358. __define(__module.exports, __require, __module);
  359. }
  360. else {
  361. __quick_compile_project__.registerModuleFunc(__filename, function () {
  362. __define(__module.exports, __require, __module);
  363. });
  364. }
  365. })();
  366. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImFzc2V0cy9zY3JpcHRNYWluL0hvdFVwZGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFDTSxJQUFBLEtBQXdCLEVBQUUsQ0FBQyxVQUFVLEVBQW5DLE9BQU8sYUFBQSxFQUFFLFFBQVEsY0FBa0IsQ0FBQztBQUU1QztJQUF1Qyw2QkFBWTtJQUFuRDtRQUFBLHFFQTZVQztRQTNVVSxpQkFBVyxHQUFZLElBQUksQ0FBQztRQUc1QixxQkFBZSxHQUFZLElBQUksQ0FBQztRQUdoQyxlQUFTLEdBQVksSUFBSSxDQUFDO1FBRzFCLGFBQU8sR0FBWSxJQUFJLENBQUM7UUFHeEIsY0FBUSxHQUFZLElBQUksQ0FBQztRQUd6QixpQkFBVyxHQUFjLElBQUksQ0FBQztRQUc5QixpQkFBVyxHQUFhLElBQUksQ0FBQzs7SUF5VHhDLENBQUM7SUE3U1UsMkJBQU8sR0FBZCxVQUFlLEtBQVU7UUFBekIsaUJBcUNDO1FBcENHLDJDQUEyQztRQUMzQyxJQUFJLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDekIsUUFBUSxLQUFLLENBQUMsWUFBWSxFQUFFLEVBQUU7WUFDMUIsS0FBSyxHQUFHLENBQUMsa0JBQWtCLENBQUMsdUJBQXVCO2dCQUMvQyxPQUFPLENBQUMsR0FBRyxDQUFDLG1EQUFtRCxDQUFDLENBQUM7Z0JBQ2pFLE1BQU07WUFDVixLQUFLLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyx1QkFBdUIsQ0FBQztZQUNwRCxLQUFLLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0I7Z0JBQzVDLE9BQU8sQ0FBQyxHQUFHLENBQUMscURBQXFELENBQUMsQ0FBQztnQkFDbkUsTUFBTTtZQUNWLEtBQUssR0FBRyxDQUFDLGtCQUFrQixDQUFDLGtCQUFrQjtnQkFDMUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO2dCQUNsRSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2pCLE1B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QVMsR0E2VWxEO2tCQTdVb0IsU0FBUztBQTZVN0IsQ0FBQyIsImZpbGUiOiIiLCJzb3VyY2VSb290IjoiLyIsInNvdXJjZXNDb250ZW50IjpbIlxuY29uc3QgeyBjY2NsYXNzLCBwcm9wZXJ0eSB9ID0gY2MuX2RlY29yYXRvcjtcbkBjY2NsYXNzXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBIb3RVcGRhdGUgZXh0ZW5kcyBjYy5Db21wb25lbnQge1xuICAgIEBwcm9wZXJ0eSh7IHR5cGU6IGNjLk5vZGUgfSlcbiAgICBwdWJsaWMgdHh0UHJvZ3Jlc3M6IGNjLk5vZGUgPSBudWxsO1xuXG4gICAgQHByb3BlcnR5KHsgdHlwZTogY2MuTm9kZSB9KVxuICAgIHB1YmxpYyB0eHRQcm9ncmVzc1RpcHM6IGNjLk5vZGUgPSBudWxsO1xuXG4gICAgQHByb3BlcnR5KHsgdHlwZTogY2MuTm9kZSB9KVxuICAgIHB1YmxpYyBnUHJvZ3Jlc3M6IGNjLk5vZGUgPSBudWxsO1xuXG4gICAgQHByb3BlcnR5KHsgdHlwZTogY2MuTm9kZSB9KVxuICAgIHB1YmxpYyBpbWdSb2xlOiBjYy5Ob2RlID0gbnVsbDtcblxuICAgIEBwcm9wZXJ0eSh7IHR5cGU6IGNjLk5vZGUgfSlcbiAgICBwdWJsaWMgcHJvZ3Jlc3M6IGNjLk5vZGUgPSBudWxsO1xuXG4gICAgQHByb3BlcnR5KHsgdHlwZTogY2MuU3ByaXRlIH0pXG4gICAgcHVibGljIHByb2dyZXNzQmFyOiBjYy5TcHJpdGUgPSBudWxsO1xuXG4gICAgQHByb3BlcnR5KHsgdHlwZTogY2MuQXNzZXQgfSlcbiAgICBwdWJsaWMgbWFuaWZlc3RVcmw6IGNjLkFzc2V0ID0gbnVsbDtcblxuICAgIF9hbTogYW55O1xuICAgIF9jaGVja0xpc3RlbmVyOiBudWxsO1xuICAgIF91cGRhdGluZzogYm9vbGVhbjtcbiAgICBfdXBkYXRlTGlzdGVuZXI6IG51bGw7XG4gICAgX2NhblJldHJ5OiBib29sZWFuO1xuICAgIF9mYWlsQ291bnQ6IG51bWJlcjtcbiAgICBfc3RvcmFnZVBhdGg6IHN0cmluZztcbiAgICB2ZXJzaW9uQ29tcGFyZUhhbmRsZTogKHZlcnNpb25BOiBhbnksIHZlcnNpb25COiBhbnkpID0+IG51bWJlcjtcbiAgICBwcml2YXRlIF9jYW5FbnRlckdhbWU6IGJvb2xlYW47XG5cbiAgICBwdWJsaWMgY2hlY2tDYihldmVudDogYW55KSB7XG4gICAgICAgIC8vIGNjLmxvZygnQ29kZTogJyArIGV2ZW50LmdldEV2ZW50Q29kZSgpKTtcbiAgICAgICAgbGV0IGlzTmV3VmVyc2lvbiA9IGZhbHNlO1xuICAgICAgICBzd2l0Y2ggKGV2ZW50LmdldEV2ZW50Q29kZSgpKSB7XG4gICAgICAgICAgICBjYXNlIGpzYi5FdmVudEFzc2V0c01hbmFnZXIuRVJST1JfTk9fTE9DQUxfTUFOSUZFU1Q6XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJObyBsb2NhbCBtYW5pZmVzdCBmaWxlIGZvdW5kLCBob3QgdXBkYXRlIHNraXBwZWQuXCIpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBqc2IuRXZlbnRBc3NldHNNYW5hZ2VyLkVSUk9SX0RPV05MT0FEX01BTklGRVNUOlxuICAgICAgICAgICAgY2FzZSBqc2IuRXZlbnRBc3NldHNNYW5hZ2VyLkVSUk9SX1BBUlNFX01BTklGRVNUOlxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiRmFpbCB0byBkb3dubG9hZCBtYW5pZmVzdCBmaWxlLCBob3QgdXBkYXRlIHNraXBwZWQuXCIpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBqc2IuRXZlbnRBc3NldHNNYW5hZ2VyLkFMUkVBRFlfVVBfVE9fREFURTpcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkFscmVhZHkgdXAgdG8gZGF0ZSB3aXRoIHRoZSBsYXRlc3QgcmVtb3RlIHZlcnNpb24uXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuRW50ZXJHYW1lKCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIGpzYi5FdmVudEFzc2V0c01hbmFnZXIuTkVXX1ZFUlNJT05fRk9VTkQ6XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJOZXcgdmVyc2lvbiBmb3VuZCwgcGxlYXNlIHRyeSB0byB1cGRhdGUuKFwiICsgdGhpcy5fYW0uZ2V0VG90YWxCeXRlcygpICsgJyknKTtcbiAgICAgICAgICAgICAgICBpc05ld1ZlcnNpb24gPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9hbS5zZXRFdmVudENhbGxiYWNrKG51bGwpO1xuICAgICAgICB0aGlzLl9jaGVja0xpc3RlbmVyID0gbnVsbDtcbiAgICAgICAgdGhpcy5fdXBkYXRpbmcgPSBmYWxzZTtcbiAgICAgICAgaWYgKGlzTmV3VmVyc2lvbikge1xuICAgICAgICAgICAgLy/mnInmlrDniYjmnKzvvIzmmL7npLrov5vluqZcbiAgICAgICAgICAgIHRoaXMuc2V0UHJvZ3Jlc3MoMClcbiAgICAgICAgICAgIHRoaXMuaG90VXBkYXRlKCk7XG4gICAgICAgICAgICAvLzXnp5LlkI7liKTmlq3mmK/lkKblvIDlp4vkuIvovb3vvIzlpoLmnpzov5vluqbkuLowLuebtOaOpei/m+a4uOaIj++8jOmYsuatouWNoeatu1xuICAgICAgICAgICAgdGhpcy5zY2hlZHVsZU9uY2UoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnByb2dyZXNzQmFyLmZpbGxSYW5nZSA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuRW50ZXJHYW1lKClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCAxMClcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFByb2dyZXNzKHZhbDogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuZ1Byb2dyZXNzLmFjdGl2ZSA9IHRydWVcbiAgICAgICAgdGhpcy5wcm9ncmVzc0Jhci5maWxsUmFuZ2UgPSB2YWxcbiAgICAgICAgdGhpcy5pbWdSb2xlLnggPSAtdGhpcy5wcm9ncmVzcy53aWR0aCAvIDIgKyB2YWwgKiB0aGlzLnByb2dyZXNzLndpZHRoXG4gICAgICAgIHRoaXMudHh0UHJvZ3Jlc3MuZ2V0Q29tcG9uZW50KGNjLkxhYmVsKS5zdHJpbmcgPSBNYXRoLmZsb29yKHZhbCAqIDEwMCkgKyBcIiVcIlxuICAgICAgICB0aGlzLnR4dFByb2dyZXNzVGlwcy5nZXRDb21wb25lbnQoY2MuTGFiZWwpLnN0cmluZyA9IFwi6LWE5rqQ5pu05paw5LitXCJcbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlQ2IoZXZlbnQ6IGFueSkge1xuICAgICAgICB2YXIgbmVlZFJlc3RhcnQgPSBmYWxzZTtcbiAgICAgICAgdmFyIGZhaWxlZCA9IGZhbHNlO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyhcInVwZGF0ZUNiIGV2ZW50OlwiK0pTT04uc3RyaW5naWZ5KGV2ZW50KSk7XG4gICAgICAgIHN3aXRjaCAoZXZlbnQuZ2V0RXZlbnRDb2RlKCkpIHtcbiAgICAgICAgICAgIGNhc2UganNiLkV2ZW50QXNzZXRzTWFuYWdlci5FUlJPUl9OT19MT0NBTF9NQU5JRkVTVDpcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnTm8gbG9jYWwgbWFuaWZlc3QgZmlsZSBmb3VuZCwgaG90IHVwZGF0ZSBza2lwcGVkLicpO1xuICAgICAgICAgICAgICAgIGZhaWxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIGpzYi5FdmVudEFzc2V0c01hbmFnZXIuVVBEQVRFX1BST0dSRVNTSU9OOlxuICAgICAgICAgICAgICAgIC8vIHRoaXMucGFuZWwuYnl0ZVByb2dyZXNzLnByb2dyZXNzID0gZXZlbnQuZ2V0UGVyY2VudCgpO1xuICAgICAgICAgICAgICAgIC8vIHRoaXMucGFuZWwuZmlsZVByb2dyZXNzLnByb2dyZXNzID0gZXZlbnQuZ2V0UGVyY2VudEJ5RmlsZSgpO1xuXG4gICAgICAgICAgICAgICAgLy8gdGhpcy5wYW5lbC5maWxlTGFiZWwuc3RyaW5nID0gZXZlbnQuZ2V0RG93bmxvYWRlZEZpbGVzKCkgKyAnIC8gJyArIGV2ZW50LmdldFRvdGFsRmlsZXMoKTtcbiAgICAgICAgICAgICAgICAvLyB0aGlzLnBhbmVsLmJ5dGVMYWJlbC5zdHJpbmcgPSBldmVudC5nZXREb3dubG9hZGVkQnl0ZXMoKSArICcgLyAnICsgZXZlbnQuZ2V0VG90YWxCeXRlcygpO1xuXG4gICAgICAgICAgICAgICAgLy8gdGhpcy5wYl9ob3RVcGRhdGUucHJvZ3Jlc3MgPSAgZXZlbnQuZ2V0UGVyY2VudCgpO1xuICAgICAgICAgICAgICAgIC8vIHRoaXMubGJfcHJvZ3Jlc3Muc3RyaW5nID0gTWF0aC5mbG9vcihldmVudC5nZXRQZXJjZW50KCkqMTAwKS50b0ZpeGVkKDIpICsgJyUnO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0UHJvZ3Jlc3MoZXZlbnQuZ2V0UGVyY2VudCgpKVxuICAgICAgICAgICAgICAgIC8vIHZhciBtc2cgPSBldmVudC5nZXRNZXNzYWdlKCk7XG4gICAgICAgICAgICAgICAgLy8gaWYgKG1zZykge1xuICAgICAgICAgICAgICAgIC8vICAgICBjYy5sb2coZXZlbnQuZ2V0UGVyY2VudCgpLzEwMCArICclIDogJyArIG1zZyk7XG4gICAgICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBqc2IuRXZlbnRBc3NldHNNYW5hZ2VyLkVSUk9SX0RPV05MT0FEX01BTklGRVNUOlxuICAgICAgICAgICAgY2FzZSBqc2IuRXZlbnRBc3NldHNNYW5hZ2VyLkVSUk9SX1BBUlNFX01BTklGRVNUOlxuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdGYWlsIHRvIGRvd25sb2FkIG1hbmlmZXN0IGZpbGUsIGhvdCB1cGRhdGUgc2tpcHBlZC4nKTtcbiAgICAgICAgICAgICAgICBmYWlsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBqc2IuRXZlbnRBc3NldHNNYW5hZ2VyLkFMUkVBRFlfVVBfVE9fREFURTpcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnQWxyZWFkeSB1cCB0byBkYXRlIHdpdGggdGhlIGxhdGVzdCByZW1vdGUgdmVyc2lvbi4nKTtcbiAgICAgICAgICAgICAgICBmYWlsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBqc2IuRXZlbnRBc3NldHNNYW5hZ2VyLlVQREFURV9GSU5JU0hFRDpcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnVXBkYXRlIGZpbmlzaGVkLiAnICsgZXZlbnQuZ2V0TWVzc2FnZSgpKTtcbiAgICAgICAgICAgICAgICBuZWVkUmVzdGFydCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIGpzYi5FdmVudEFzc2V0c01hbmFnZXIuVVBEQVRFX0ZBSUxFRDpcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnVXBkYXRlIGZhaWxlZC4gJyArIGV2ZW50LmdldE1lc3NhZ2UoKSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIGpzYi5FdmVudEFzc2V0c01hbmFnZXIuRVJST1JfVVBEQVRJTkc6XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0Fzc2V0IHVwZGF0ZSBlcnJvcjogJyArIGV2ZW50LmdldEFzc2V0SWQoKSArICcsICcgKyBldmVudC5nZXRNZXNzYWdlKCkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBqc2IuRXZlbnRBc3NldHNNYW5hZ2VyLkVSUk9SX0RFQ09NUFJFU1M6XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJFUlJPUl9ERUNPTVBSRVNTOlwiK2V2ZW50LmdldE1lc3NhZ2UoKSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZhaWxlZCkge1xuICAgICAgICAgICAgdGhpcy5fYW0uc2V0RXZlbnRDYWxsYmFjayhudWxsKTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUxpc3RlbmVyID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLkVudGVyR2FtZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG5lZWRSZXN0YXJ0KSB7XG4gICAgICAgICAgICB0aGlzLl9hbS5zZXRFdmVudENhbGxiYWNrKG51bGwpO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlTGlzdGVuZXIgPSBudWxsO1xuICAgICAgICAgICAgLy8gUHJlcGVuZCB0aGUgbWFuaWZlc3QncyBzZWFyY2ggcGF0aFxuICAgICAgICAgICAgdmFyIHNlYXJjaFBhdGhzID0ganNiLmZpbGVVdGlscy5nZXRTZWFyY2hQYXRocygpO1xuICAgICAgICAgICAgdmFyIG5ld1BhdGhzID0gdGhpcy5fYW0uZ2V0TG9jYWxNYW5pZmVzdCgpLmdldFNlYXJjaFBhdGhzKCk7XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeShuZXdQYXRocykpO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuZXdQYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChzZWFyY2hQYXRocy5pbmRleE9mKG5ld1BhdGhzW2ldKSA9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUudW5zaGlmdC5hcHBseShzZWFyY2hQYXRocywgW25ld1BhdGhzW2ldXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gVGhpcyB2YWx1ZSB3aWxsIGJlIHJldHJpZXZlZCBhbmQgYXBwZW5kZWQgdG8gdGhlIGRlZmF1bHQgc2VhcmNoIHBhdGggZHVyaW5nIGdhbWUgc3RhcnR1cCxcbiAgICAgICAgICAgIC8vIHBsZWFzZSByZWZlciB0byBzYW1wbGVzL2pzLXRlc3RzL21haW4uanMgZm9yIGRldGFpbGVkIHVzYWdlLlxuICAgICAgICAgICAgLy8gISEhIFJlLWFkZCB0aGUgc2VhcmNoIHBhdGhzIGluIG1haW4uanMgaXMgdmVyeSBpbXBvcnRhbnQsIG90aGVyd2lzZSwgbmV3IHNjcmlwdHMgd29uJ3QgdGFrZSBlZmZlY3QuXG4gICAgICAgICAgICBjYy5zeXMubG9jYWxTdG9yYWdlLnNldEl0ZW0oJ0hvdFVwZGF0ZVNlYXJjaFBhdGhzJywgSlNPTi5zdHJpbmdpZnkoc2VhcmNoUGF0aHMpKTtcbiAgICAgICAgICAgIGpzYi5maWxlVXRpbHMuc2V0U2VhcmNoUGF0aHMoc2VhcmNoUGF0aHMpO1xuXG4gICAgICAgICAgICBjYy5hdWRpb0VuZ2luZS5zdG9wQWxsKCk7XG4gICAgICAgICAgICBjYy5nYW1lLnJlc3RhcnQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyByZXRyeSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLl91cGRhdGluZyAmJiB0aGlzLl9jYW5SZXRyeSkge1xuICAgICAgICAgICAgdGhpcy5fY2FuUmV0cnkgPSBmYWxzZTtcblxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ1JldHJ5IGZhaWxlZCBBc3NldHMuLi4nKTtcbiAgICAgICAgICAgIHRoaXMuX2FtLmRvd25sb2FkRmFpbGVkQXNzZXRzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgY2hlY2tVcGRhdGUoKSB7XG4gICAgICAgIGlmICh0aGlzLl91cGRhdGluZykge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0NoZWNraW5nIG9yIHVwZGF0aW5nIC4uLicpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9hbS5nZXRTdGF0ZSgpID09PSBqc2IuQXNzZXRzTWFuYWdlci5TdGF0ZS5VTklOSVRFRCkge1xuICAgICAgICAgICAgLy8gUmVzb2x2ZSBtZDUgdXJsXG4gICAgICAgICAgICB2YXIgdXJsID0gdGhpcy5tYW5pZmVzdFVybC5uYXRpdmVVcmw7XG4gICAgICAgICAgICBpZiAoY2MubG9hZGVyLm1kNVBpcGUpIHtcbiAgICAgICAgICAgICAgICB1cmwgPSBjYy5sb2FkZXIubWQ1UGlwZS50cmFuc2Zvcm1VUkwodXJsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2FtLmxvYWRMb2NhbE1hbmlmZXN0KHVybCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLl9hbS5nZXRMb2NhbE1hbmlmZXN0KCkgfHwgIXRoaXMuX2FtLmdldExvY2FsTWFuaWZlc3QoKS5pc0xvYWRlZCgpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnRmFpbGVkIHRvIGxvYWQgbG9jYWwgbWFuaWZlc3QgLi4uJyk7XG4gICAgICAgICAgICB0aGlzLkVudGVyR2FtZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZ2V0TG9jYWxWZXJzaW9uKClcbiAgICAgICAgdGhpcy5fYW0uc2V0RXZlbnRDYWxsYmFjayh0aGlzLmNoZWNrQ2IuYmluZCh0aGlzKSk7XG5cbiAgICAgICAgdGhpcy5fYW0uY2hlY2tVcGRhdGUoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRpbmcgPSB0cnVlO1xuICAgIH1cblxuICAgIHB1YmxpYyBob3RVcGRhdGUoKSB7XG4gICAgICAgIGlmICh0aGlzLl9hbSAmJiAhdGhpcy5fdXBkYXRpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuX2FtLnNldEV2ZW50Q2FsbGJhY2sodGhpcy51cGRhdGVDYi5iaW5kKHRoaXMpKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX2FtLmdldFN0YXRlKCkgPT09IGpzYi5Bc3NldHNNYW5hZ2VyLlN0YXRlLlVOSU5JVEVEKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSBtZDUgdXJsXG4gICAgICAgICAgICAgICAgdmFyIHVybCA9IHRoaXMubWFuaWZlc3RVcmwubmF0aXZlVXJsO1xuICAgICAgICAgICAgICAgIGlmIChjYy5sb2FkZXIubWQ1UGlwZSkge1xuICAgICAgICAgICAgICAgICAgICB1cmwgPSBjYy5sb2FkZXIubWQ1UGlwZS50cmFuc2Zvcm1VUkwodXJsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fYW0ubG9hZExvY2FsTWFuaWZlc3QodXJsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2ZhaWxDb3VudCA9IDA7XG4gICAgICAgICAgICB0aGlzLl9hbS51cGRhdGUoKTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0aW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHVzZSB0aGlzIGZvciBpbml0aWFsaXphdGlvblxuICAgIG9uTG9hZCgpIHtcbiAgICAgICAgLy8gSG90IHVwZGF0ZSBpcyBvbmx5IGF2YWlsYWJsZSBpbiBOYXRpdmUgYnVpbGRcbiAgICAgICAgaWYgKCFjYy5zeXMuaXNOYXRpdmUpIHtcbiAgICAgICAgICAgIC8vIHRoaXMuRW50ZXJHYW1lKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc3RvcmFnZVBhdGggPSAoKGpzYi5maWxlVXRpbHMgPyBqc2IuZmlsZVV0aWxzLmdldFdyaXRhYmxlUGF0aCgpIDogJy8nKSArICdibGFja2phY2stcmVtb3RlLWFzc2V0Jyk7XG4gICAgICAgIGNjLmxvZygnU3RvcmFnZSBwYXRoIGZvciByZW1vdGUgYXNzZXQgOiAnICsgdGhpcy5fc3RvcmFnZVBhdGgpO1xuXG5cbiAgICAgICAgLy8gU2V0dXAgeW91ciBvd24gdmVyc2lvbiBjb21wYXJlIGhhbmRsZXIsIHZlcnNpb25BIGFuZCBCIGlzIHZlcnNpb25zIGluIHN0cmluZ1xuICAgICAgICAvLyBpZiB0aGUgcmV0dXJuIHZhbHVlIGdyZWF0ZXIgdGhhbiAwLCB2ZXJzaW9uQSBpcyBncmVhdGVyIHRoYW4gQixcbiAgICAgICAgLy8gaWYgdGhlIHJldHVybiB2YWx1ZSBlcXVhbHMgMCwgdmVyc2lvbkEgZXF1YWxzIHRvIEIsXG4gICAgICAgIC8vIGlmIHRoZSByZXR1cm4gdmFsdWUgc21hbGxlciB0aGFuIDAsIHZlcnNpb25BIGlzIHNtYWxsZXIgdGhhbiBCLlxuICAgICAgICB0aGlzLnZlcnNpb25Db21wYXJlSGFuZGxlID0gZnVuY3Rpb24gKHZlcnNpb25BLCB2ZXJzaW9uQikge1xuICAgICAgICAgICAgY2MubG9nKFwiSlMgQ3VzdG9tIFZlcnNpb24gQ29tcGFyZTogdmVyc2lvbiBBIGlzIFwiICsgdmVyc2lvbkEgKyAnLCB2ZXJzaW9uIEIgaXMgJyArIHZlcnNpb25CKTtcbiAgICAgICAgICAgIHZhciB2QSA9IHZlcnNpb25BLnNwbGl0KCcuJyk7XG4gICAgICAgICAgICB2YXIgdkIgPSB2ZXJzaW9uQi5zcGxpdCgnLicpO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2QS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgIHZhciBhID0gcGFyc2VJbnQodkFbaV0pO1xuICAgICAgICAgICAgICAgIHZhciBiID0gcGFyc2VJbnQodkJbaV0gfHwgMCk7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYSAtIGI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHZCLmxlbmd0aCA+IHZBLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEluaXQgd2l0aCBlbXB0eSBtYW5pZmVzdCB1cmwgZm9yIHRlc3RpbmcgY3VzdG9tIG1hbmlmZXN0XG4gICAgICAgIHRoaXMuX2FtID0gbmV3IGpzYi5Bc3NldHNNYW5hZ2VyKCcnLCB0aGlzLl9zdG9yYWdlUGF0aCwgdGhpcy52ZXJzaW9uQ29tcGFyZUhhbmRsZSk7XG5cbiAgICAgICAgLy8gU2V0dXAgdGhlIHZlcmlmaWNhdGlvbiBjYWxsYmFjaywgYnV0IHdlIGRvbid0IGhhdmUgbWQ1IGNoZWNrIGZ1bmN0aW9uIHlldCwgc28gb25seSBwcmludCBzb21lIG1lc3NhZ2VcbiAgICAgICAgLy8gUmV0dXJuIHRydWUgaWYgdGhlIHZlcmlmaWNhdGlvbiBwYXNzZWQsIG90aGVyd2lzZSByZXR1cm4gZmFsc2VcbiAgICAgICAgdGhpcy5fYW0uc2V0VmVyaWZ5Q2FsbGJhY2soZnVuY3Rpb24gKHBhdGgsIGFzc2V0KSB7XG4gICAgICAgICAgICAvLyBXaGVuIGFzc2V0IGlzIGNvbXByZXNzZWQsIHdlIGRvbid0IG5lZWQgdG8gY2hlY2sgaXRzIG1kNSwgYmVjYXVzZSB6aXAgZmlsZSBoYXZlIGJlZW4gZGVsZXRlZC5cbiAgICAgICAgICAgIHZhciBjb21wcmVzc2VkID0gYXNzZXQuY29tcHJlc3NlZDtcbiAgICAgICAgICAgIC8vIFJldHJpZXZlIHRoZSBjb3JyZWN0IG1kNSB2YWx1ZS5cbiAgICAgICAgICAgIHZhciBleHBlY3RlZE1ENSA9IGFzc2V0Lm1kNTtcbiAgICAgICAgICAgIC8vIGFzc2V0LnBhdGggaXMgcmVsYXRpdmUgcGF0aCBhbmQgcGF0aCBpcyBhYnNvbHV0ZS5cbiAgICAgICAgICAgIHZhciByZWxhdGl2ZVBhdGggPSBhc3NldC5wYXRoO1xuICAgICAgICAgICAgLy8gVGhlIHNpemUgb2YgYXNzZXQgZmlsZSwgYnV0IHRoaXMgdmFsdWUgY291bGQgYmUgYWJzZW50LlxuICAgICAgICAgICAgdmFyIHNpemUgPSBhc3NldC5zaXplO1xuICAgICAgICAgICAgaWYgKGNvbXByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlZlcmlmaWNhdGlvbiBwYXNzZWQgOiBcIiArIHJlbGF0aXZlUGF0aCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlZlcmlmaWNhdGlvbiBwYXNzZWQgOiBcIiArIHJlbGF0aXZlUGF0aCArICcgKCcgKyBleHBlY3RlZE1ENSArICcpJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIC8vIGNvbnNvbGUubG9nKCdIb3QgdXBkYXRlIGlzIHJlYWR5LCBwbGVhc2UgY2hlY2sgb3IgZGlyZWN0bHkgdXBkYXRlLicpO1xuXG4gICAgICAgIGlmIChjYy5zeXMub3MgPT09IGNjLnN5cy5PU19BTkRST0lEKSB7XG4gICAgICAgICAgICAvLyBTb21lIEFuZHJvaWQgZGV2aWNlIG1heSBzbG93IGRvd24gdGhlIGRvd25sb2FkIHByb2Nlc3Mgd2hlbiBjb25jdXJyZW50IHRhc2tzIGlzIHRvbyBtdWNoLlxuICAgICAgICAgICAgLy8gVGhlIHZhbHVlIG1heSBub3QgYmUgYWNjdXJhdGUsIHBsZWFzZSBkbyBtb3JlIHRlc3QgYW5kIGZpbmQgd2hhdCdzIG1vc3Qgc3VpdGFibGUgZm9yIHlvdXIgZ2FtZS5cbiAgICAgICAgICAgIHRoaXMuX2FtLnNldE1heENvbmN1cnJlbnRUYXNrKDIpO1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJNYXggY29uY3VycmVudCB0YXNrcyBjb3VudCBoYXZlIGJlZW4gbGltaXRlZCB0byAyXCIpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNjLmxvYWRlci5sb2FkUmVzKCcvcHJvamVjdC5tYW5pZmVzdCcsKGVycixvYmopPT57XG4gICAgICAgIC8vICAgICBpZiAoIWVycikge1xuICAgICAgICAvLyAgICAgICAgIC8vIGxldCBjdXN0b21NYW5pZmVzdFN0ciA9IEpTT04uc3RyaW5naWZ5KG9iaik7XG4gICAgICAgIC8vICAgICAgICAgbGV0IF9uYXRpdmVBc3NldCA9IEpTT04ucGFyc2Uob2JqLl9uYXRpdmVBc3NldCk7XG4gICAgICAgIC8vICAgICAgICAgdmFyIGN1c3RvbU1hbmlmZXN0U3RyID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAvLyAgICAgICAgICAgICAncGFja2FnZVVybCc6IF9uYXRpdmVBc3NldC5wYWNrYWdlVXJsLFxuICAgICAgICAvLyAgICAgICAgICAgICAncmVtb3RlTWFuaWZlc3RVcmwnOiBfbmF0aXZlQXNzZXQucmVtb3RlTWFuaWZlc3RVcmwsXG4gICAgICAgIC8vICAgICAgICAgICAgICdyZW1vdGVWZXJzaW9uVXJsJzogX25hdGl2ZUFzc2V0LnJlbW90ZU1hbmlmZXN0VXJsLFxuICAgICAgICAvLyAgICAgICAgICAgICAndmVyc2lvbic6IF9uYXRpdmVBc3NldC52ZXJzaW9uLFxuICAgICAgICAvLyAgICAgICAgICAgICAnYXNzZXRzJzogX25hdGl2ZUFzc2V0LmFzc2VydCxcbiAgICAgICAgLy8gICAgICAgICAgICAgJ3NlYXJjaFBhdGhzJzogX25hdGl2ZUFzc2V0LnNlYXJjaFBhdGhzXG4gICAgICAgIC8vICAgICAgICAgfSk7XG4gICAgICAgIC8vICAgICAgICAgaWYgKHRoaXMuX2FtLmdldFN0YXRlKCkgPT09IGpzYi5Bc3NldHNNYW5hZ2VyLlN0YXRlLlVOSU5JVEVEKSB7XG4gICAgICAgIC8vICAgICAgICAgICAgIHZhciBtYW5pZmVzdCA9IG5ldyBqc2IuTWFuaWZlc3QoY3VzdG9tTWFuaWZlc3RTdHIsIHRoaXMuX3N0b3JhZ2VQYXRoKTtcbiAgICAgICAgLy8gICAgICAgICAgICAgdGhpcy5fYW0ubG9hZExvY2FsTWFuaWZlc3QobWFuaWZlc3QsIHRoaXMuX3N0b3JhZ2VQYXRoKTtcbiAgICAgICAgLy8gICAgICAgICB9XG4gICAgICAgIC8vICAgICB9XG4gICAgICAgIC8vIH0pO1xuICAgICAgICAvL+W8gOWni+ajgOa1i+abtOaWsFxuICAgICAgICAvLyB0aGlzLmNoZWNrVXBkYXRlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIEVudGVyR2FtZSgpIHtcbiAgICAgICAgLy8g5ri45oiP5Yid5aeL5YyWXG4gICAgICAgIHRoaXMuZ2V0TG9jYWxWZXJzaW9uKCk7XG4gICAgICAgIHRoaXMuc2NoZWR1bGVPbmNlKCgpID0+IHtcbiAgICAgICAgICAgIGNjLmRpcmVjdG9yLmxvYWRTY2VuZShcImxvYWRpbmdcIilcbiAgICAgICAgfSwgNClcbiAgICAgICAgdGhpcy5fY2FuRW50ZXJHYW1lID0gdHJ1ZVxuICAgIH1cblxuICAgIC8v6I635Y+W5pys5Zyw54mI5pysXG4gICAgcHVibGljIGdldExvY2FsVmVyc2lvbigpIHtcbiAgICAgICAgbGV0IGxvY2FsVmVyc2lvbiA9ICcnO1xuICAgICAgICBpZiAodGhpcy5fYW0gJiYgdGhpcy5fYW0uZ2V0TG9jYWxNYW5pZmVzdCgpICYmICF0aGlzLl91cGRhdGluZykge1xuICAgICAgICAgICAgbG9jYWxWZXJzaW9uID0gdGhpcy5fYW0uZ2V0TG9jYWxNYW5pZmVzdCgpLmdldFZlcnNpb24oKTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiY3VyVmVyc2lvbjE6XCIgKyBsb2NhbFZlcnNpb24pO1xuICAgICAgICAgICAgaW1wb3J0KFwiQ29uZmlnXCIgYXMgYW55KS50aGVuKChjZmdQYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBjb25maWcgPSBjZmdQYXJhbS5kZWZhdWx0XG4gICAgICAgICAgICAgICAgY29uZmlnLmFwcFZlcnNpb24gPSBsb2NhbFZlcnNpb25cbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcImN1clZlcnNpb24yOlwiICsgbG9jYWxWZXJzaW9uKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcImN1clZlcnNpb246XCIrbG9jYWxWZXJzaW9uKTtcbiAgICAgICAgfVxuICAgICAgICAvL3JldHVybiBsb2NhbFZlcnNpb247XG4gICAgfVxuXG4gICAgb25EZXN0cm95KCkge1xuICAgICAgICBpZiAodGhpcy5fdXBkYXRlTGlzdGVuZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX2FtLnNldEV2ZW50Q2FsbGJhY2sobnVsbCk7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVMaXN0ZW5lciA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59O1xuIl19