Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

16129 linhas
1.1 MiB

  1. /**
  2. * swagger-client - swagger.js is a javascript client for use with swaggering APIs.
  3. * @version v2.1.10-M1
  4. * @link http://swagger.io
  5. * @license apache 2.0
  6. */
  7. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.SwaggerClient = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  8. 'use strict';
  9. var auth = require('./lib/auth');
  10. var helpers = require('./lib/helpers');
  11. var SwaggerClient = require('./lib/client-compat');
  12. var deprecationWrapper = function (url, options) {
  13. helpers.log('This is deprecated, use "new SwaggerClient" instead.');
  14. return new SwaggerClient(url, options);
  15. };
  16. /* Here for IE8 Support */
  17. if (!Array.prototype.indexOf) {
  18. Array.prototype.indexOf = function(obj, start) {
  19. for (var i = (start || 0), j = this.length; i < j; i++) {
  20. if (this[i] === obj) { return i; }
  21. }
  22. return -1;
  23. };
  24. }
  25. module.exports = SwaggerClient;
  26. SwaggerClient.ApiKeyAuthorization = auth.ApiKeyAuthorization;
  27. SwaggerClient.PasswordAuthorization = auth.PasswordAuthorization;
  28. SwaggerClient.CookieAuthorization = auth.CookieAuthorization;
  29. SwaggerClient.SwaggerApi = deprecationWrapper;
  30. SwaggerClient.SwaggerClient = deprecationWrapper;
  31. },{"./lib/auth":2,"./lib/client-compat":3,"./lib/helpers":5}],2:[function(require,module,exports){
  32. 'use strict';
  33. var btoa = require('btoa'); // jshint ignore:line
  34. var CookieJar = require('cookiejar');
  35. /**
  36. * SwaggerAuthorizations applys the correct authorization to an operation being executed
  37. */
  38. var SwaggerAuthorizations = module.exports.SwaggerAuthorizations = function () {
  39. this.authz = {};
  40. };
  41. SwaggerAuthorizations.prototype.add = function (name, auth) {
  42. this.authz[name] = auth;
  43. return auth;
  44. };
  45. SwaggerAuthorizations.prototype.remove = function (name) {
  46. return delete this.authz[name];
  47. };
  48. SwaggerAuthorizations.prototype.apply = function (obj, authorizations) {
  49. var status = null;
  50. var key, name, value, result;
  51. // if the 'authorizations' key is undefined, or has an empty array, add all keys
  52. if (typeof authorizations === 'undefined' || Object.keys(authorizations).length === 0) {
  53. for (key in this.authz) {
  54. value = this.authz[key];
  55. result = value.apply(obj, authorizations);
  56. if (result === true) {
  57. status = true;
  58. }
  59. }
  60. } else {
  61. // 2.0 support
  62. if (Array.isArray(authorizations)) {
  63. for (var i = 0; i < authorizations.length; i++) {
  64. var auth = authorizations[i];
  65. for (name in auth) {
  66. for (key in this.authz) {
  67. if (key === name) {
  68. value = this.authz[key];
  69. result = value.apply(obj, authorizations);
  70. if (result === true) {
  71. status = true;
  72. }
  73. }
  74. }
  75. }
  76. }
  77. } else {
  78. // 1.2 support
  79. for (name in authorizations) {
  80. for (key in this.authz) {
  81. if (key === name) {
  82. value = this.authz[key];
  83. result = value.apply(obj, authorizations);
  84. if (result === true) {
  85. status = true;
  86. }
  87. }
  88. }
  89. }
  90. }
  91. }
  92. return status;
  93. };
  94. /**
  95. * ApiKeyAuthorization allows a query param or header to be injected
  96. */
  97. var ApiKeyAuthorization = module.exports.ApiKeyAuthorization = function (name, value, type) {
  98. this.name = name;
  99. this.value = value;
  100. this.type = type;
  101. };
  102. ApiKeyAuthorization.prototype.apply = function (obj) {
  103. if (this.type === 'query') {
  104. if (obj.url.indexOf('?') > 0) {
  105. obj.url = obj.url + '&' + this.name + '=' + this.value;
  106. } else {
  107. obj.url = obj.url + '?' + this.name + '=' + this.value;
  108. }
  109. return true;
  110. } else if (this.type === 'header') {
  111. obj.headers[this.name] = this.value;
  112. return true;
  113. }
  114. };
  115. var CookieAuthorization = module.exports.CookieAuthorization = function (cookie) {
  116. this.cookie = cookie;
  117. };
  118. CookieAuthorization.prototype.apply = function (obj) {
  119. obj.cookieJar = obj.cookieJar || new CookieJar();
  120. obj.cookieJar.setCookie(this.cookie);
  121. return true;
  122. };
  123. /**
  124. * Password Authorization is a basic auth implementation
  125. */
  126. var PasswordAuthorization = module.exports.PasswordAuthorization = function (name, username, password) {
  127. this.name = name;
  128. this.username = username;
  129. this.password = password;
  130. };
  131. PasswordAuthorization.prototype.apply = function (obj) {
  132. obj.headers.Authorization = 'Basic ' + btoa(this.username + ':' + this.password);
  133. return true;
  134. };
  135. },{"btoa":16,"cookiejar":17}],3:[function(require,module,exports){
  136. 'use strict';
  137. var helpers = require('./helpers');
  138. var SwaggerClient = require('./client');
  139. var SwaggerHttp = require('./http');
  140. module.exports = SwaggerClient;
  141. /**
  142. * allows override of the default value based on the parameter being
  143. * supplied
  144. **/
  145. var applyParameterMacro = function (operation, parameter) {
  146. if (operation.api.parameterMacro) {
  147. return operation.api.parameterMacro(operation, parameter);
  148. } else {
  149. return parameter.defaultValue;
  150. }
  151. };
  152. /**
  153. * allows overriding the default value of an model property
  154. **/
  155. var applyModelPropertyMacro = function (model, property) {
  156. if (model.api.modelPropertyMacro) {
  157. return model.api.modelPropertyMacro(model, property);
  158. } else {
  159. return property.defaultValue;
  160. }
  161. };
  162. var SwaggerModelProperty = function (name, obj, model) {
  163. this.name = name;
  164. this.dataType = obj.type || obj.dataType || obj.$ref;
  165. this.isCollection = this.dataType && (this.dataType.toLowerCase() === 'array' || this.dataType.toLowerCase() === 'list' || this.dataType.toLowerCase() === 'set');
  166. this.descr = obj.description;
  167. this.required = obj.required;
  168. this.defaultValue = applyModelPropertyMacro(model, obj);
  169. if (obj.items) {
  170. if (obj.items.type) {
  171. this.refDataType = obj.items.type;
  172. }
  173. if (obj.items.$ref) {
  174. this.refDataType = obj.items.$ref;
  175. }
  176. }
  177. this.dataTypeWithRef = this.refDataType ? (this.dataType + '[' + this.refDataType + ']') : this.dataType;
  178. if (obj.allowableValues) {
  179. this.valueType = obj.allowableValues.valueType;
  180. this.values = obj.allowableValues.values;
  181. if (this.values) {
  182. this.valuesString = '\'' + this.values.join('\' or \'') + '\'';
  183. }
  184. }
  185. if (obj['enum']) {
  186. this.valueType = 'string';
  187. this.values = obj['enum'];
  188. if (this.values) {
  189. this.valueString = '\'' + this.values.join('\' or \'') + '\'';
  190. }
  191. }
  192. };
  193. var SwaggerModel = function (modelName, obj, api) {
  194. this.api = api;
  195. this.name = typeof obj.id !== 'undefined' ? obj.id : modelName;
  196. this.properties = [];
  197. this.sampleModels = api.sampleModels;
  198. var propertyName;
  199. for (propertyName in obj.properties) {
  200. if (obj.required) {
  201. var value;
  202. for (value in obj.required) {
  203. if (propertyName === obj.required[value]) {
  204. obj.properties[propertyName].required = true;
  205. }
  206. }
  207. }
  208. var prop = new SwaggerModelProperty(propertyName, obj.properties[propertyName], this);
  209. this.properties.push(prop);
  210. }
  211. };
  212. var SwaggerOperation = function (nickname, path, method, parameters, summary, notes, type, responseMessages, resource,
  213. consumes, produces, authorizations, deprecated, clientAuthorizations) {
  214. var self = this;
  215. var errors = [];
  216. this.clientAuthorizations = clientAuthorizations;
  217. this.nickname = (nickname || errors.push('SwaggerOperations must have a nickname.'));
  218. this.path = (path || errors.push('SwaggerOperation ' + nickname + ' is missing path.'));
  219. this.method = (method || errors.push('SwaggerOperation ' + nickname + ' is missing method.'));
  220. this.parameters = parameters ? parameters : [];
  221. this.summary = summary;
  222. this.notes = notes;
  223. this.type = type;
  224. this.responseMessages = (responseMessages || []);
  225. this.resource = (resource || errors.push('Resource is required'));
  226. this.consumes = consumes;
  227. this.produces = produces;
  228. this.authorizations = typeof authorizations !== 'undefined' ? authorizations : resource.authorizations;
  229. this.deprecated = deprecated;
  230. this.do = helpers.__bind(this.do, this);
  231. this.api = this.resource.api;
  232. if (typeof this.deprecated === 'string') {
  233. switch(this.deprecated.toLowerCase()) {
  234. case 'true': case 'yes': case '1': {
  235. this.deprecated = true;
  236. break;
  237. }
  238. case 'false': case 'no': case '0': case null: {
  239. this.deprecated = false;
  240. break;
  241. }
  242. default: this.deprecated = Boolean(this.deprecated);
  243. }
  244. }
  245. if (errors.length > 0) {
  246. console.error('SwaggerOperation errors', errors, arguments);
  247. this.resource.api.fail(errors);
  248. }
  249. this.path = this.path.replace('{format}', 'json');
  250. this.method = this.method.toLowerCase();
  251. this.isGetMethod = this.method === 'get';
  252. var i, j, v;
  253. this.resourceName = this.resource.name;
  254. if (typeof this.type !== 'undefined' && this.type === 'void') {
  255. this.type = null;
  256. } else {
  257. this.responseClassSignature = this.getSignature(this.type, this.resource.models);
  258. this.responseSampleJSON = this.getSampleJSON(this.type, this.resource.models);
  259. }
  260. for (i = 0; i < this.parameters.length; i++) {
  261. var param = this.parameters[i];
  262. param.name = param.name || param.type || param.dataType; // might take this away
  263. type = param.type || param.dataType; // for 1.1 compatibility
  264. if (type === 'array') {
  265. type = 'array[' + (param.items.$ref ? param.items.$ref : param.items.type) + ']';
  266. }
  267. param.type = type;
  268. if (type && type.toLowerCase() === 'boolean') {
  269. param.allowableValues = {};
  270. param.allowableValues.values = ['true', 'false'];
  271. }
  272. param.signature = this.getSignature(type, this.resource.models);
  273. param.sampleJSON = this.getSampleJSON(type, this.resource.models);
  274. var enumValue = param['enum'];
  275. if (typeof enumValue !== 'undefined') {
  276. param.isList = true;
  277. param.allowableValues = {};
  278. param.allowableValues.descriptiveValues = [];
  279. for (j = 0; j < enumValue.length; j++) {
  280. v = enumValue[j];
  281. if (param.defaultValue) {
  282. param.allowableValues.descriptiveValues.push({
  283. value: String(v),
  284. isDefault: (v === param.defaultValue)
  285. });
  286. } else {
  287. param.allowableValues.descriptiveValues.push({
  288. value: String(v),
  289. isDefault: false
  290. });
  291. }
  292. }
  293. } else if (param.allowableValues) {
  294. if (param.allowableValues.valueType === 'RANGE') {
  295. param.isRange = true;
  296. } else {
  297. param.isList = true;
  298. }
  299. if (param.allowableValues) {
  300. param.allowableValues.descriptiveValues = [];
  301. if (param.allowableValues.values) {
  302. for (j = 0; j < param.allowableValues.values.length; j++) {
  303. v = param.allowableValues.values[j];
  304. if (param.defaultValue !== null) {
  305. param.allowableValues.descriptiveValues.push({
  306. value: String(v),
  307. isDefault: (v === param.defaultValue)
  308. });
  309. } else {
  310. param.allowableValues.descriptiveValues.push({
  311. value: String(v),
  312. isDefault: false
  313. });
  314. }
  315. }
  316. }
  317. }
  318. }
  319. param.defaultValue = applyParameterMacro(this, param);
  320. }
  321. var defaultSuccessCallback = this.resource.api.defaultSuccessCallback || null;
  322. var defaultErrorCallback = this.resource.api.defaultErrorCallback || null;
  323. this.resource[this.nickname] = function (args, opts, callback, error) {
  324. var arg1, arg2, arg3, arg4;
  325. if (typeof args === 'function') { // right shift 3
  326. arg1 = {}; arg2 = {}; arg3 = args; arg4 = opts;
  327. } else if (typeof args === 'object' && typeof opts === 'function') { // right shift 2
  328. arg1 = args; arg2 = {}; arg3 = opts; arg4 = callback;
  329. } else {
  330. arg1 = args; arg2 = opts; arg3 = callback; arg4 = error;
  331. }
  332. return self['do'](arg1 || {}, arg2 || {}, arg3 || defaultSuccessCallback, arg4 || defaultErrorCallback);
  333. };
  334. this.resource[this.nickname].help = function (dontPrint) {
  335. return self.help(dontPrint);
  336. };
  337. this.resource[this.nickname].asCurl = function (args) {
  338. return self.asCurl(args);
  339. };
  340. };
  341. var SwaggerRequest = function (type, url, params, opts, successCallback, errorCallback, operation, execution) {
  342. var _this = this;
  343. var errors = [];
  344. this.useJQuery = (typeof operation.resource.useJQuery !== 'undefined' ? operation.resource.useJQuery : null);
  345. this.type = (type || errors.push('SwaggerRequest type is required (get/post/put/delete/patch/options).'));
  346. this.url = (url || errors.push('SwaggerRequest url is required.'));
  347. this.params = params;
  348. this.opts = opts;
  349. this.successCallback = (successCallback || errors.push('SwaggerRequest successCallback is required.'));
  350. this.errorCallback = (errorCallback || errors.push('SwaggerRequest error callback is required.'));
  351. this.operation = (operation || errors.push('SwaggerRequest operation is required.'));
  352. this.execution = execution;
  353. this.headers = (params.headers || {});
  354. if (errors.length > 0) {
  355. throw errors;
  356. }
  357. this.type = this.type.toUpperCase();
  358. // set request, response content type headers
  359. var headers = this.setHeaders(params, opts, this.operation);
  360. var body = params.body;
  361. // encode the body for form submits
  362. if (headers['Content-Type']) {
  363. var key, value, values = {}, i;
  364. var operationParams = this.operation.parameters;
  365. for (i = 0; i < operationParams.length; i++) {
  366. var param = operationParams[i];
  367. if (param.paramType === 'form') {
  368. values[param.name] = param;
  369. }
  370. }
  371. if (headers['Content-Type'].indexOf('application/x-www-form-urlencoded') === 0) {
  372. var encoded = '';
  373. for (key in values) {
  374. value = this.params[key];
  375. if (typeof value !== 'undefined') {
  376. if (encoded !== '') {
  377. encoded += '&';
  378. }
  379. encoded += encodeURIComponent(key) + '=' + encodeURIComponent(value);
  380. }
  381. }
  382. body = encoded;
  383. } else if (headers['Content-Type'].indexOf('multipart/form-data') === 0) {
  384. // encode the body for form submits
  385. var data = '';
  386. var boundary = '----SwaggerFormBoundary' + Date.now();
  387. for (key in values) {
  388. value = this.params[key];
  389. if (typeof value !== 'undefined') {
  390. data += '--' + boundary + '\n';
  391. data += 'Content-Disposition: form-data; name="' + key + '"';
  392. data += '\n\n';
  393. data += value + '\n';
  394. }
  395. }
  396. data += '--' + boundary + '--\n';
  397. headers['Content-Type'] = 'multipart/form-data; boundary=' + boundary;
  398. body = data;
  399. }
  400. }
  401. var obj;
  402. if (!((this.headers) && (this.headers.mock))) {
  403. obj = {
  404. url: this.url,
  405. method: this.type,
  406. headers: headers,
  407. body: body,
  408. useJQuery: this.useJQuery,
  409. on: {
  410. error: function (response) {
  411. return _this.errorCallback(response, _this.opts.parent);
  412. },
  413. redirect: function (response) {
  414. return _this.successCallback(response, _this.opts.parent);
  415. },
  416. 307: function (response) {
  417. return _this.successCallback(response, _this.opts.parent);
  418. },
  419. response: function (response) {
  420. return _this.successCallback(response, _this.opts.parent);
  421. }
  422. }
  423. };
  424. var status = false;
  425. if (this.operation.resource && this.operation.resource.api && this.operation.resource.api.clientAuthorizations) {
  426. // Get the client authorizations from the resource declaration
  427. status = this.operation.resource.api.clientAuthorizations.apply(obj, this.operation.authorizations);
  428. }
  429. if (!opts.mock) {
  430. if (status !== false) {
  431. new SwaggerHttp().execute(obj);
  432. } else {
  433. obj.canceled = true;
  434. }
  435. } else {
  436. return obj;
  437. }
  438. }
  439. return obj;
  440. };
  441. var SwaggerResource = function (resourceObj, api) {
  442. var self = this;
  443. this.api = api;
  444. this.swaggerRequstHeaders = api.swaggerRequstHeaders;
  445. this.path = (typeof this.api.resourcePath === 'string') ? this.api.resourcePath : resourceObj.path;
  446. this.description = resourceObj.description;
  447. this.authorizations = (resourceObj.authorizations || {});
  448. var parts = this.path.split('/');
  449. this.name = parts[parts.length - 1].replace('.{format}', '');
  450. this.basePath = this.api.basePath;
  451. this.operations = {};
  452. this.operationsArray = [];
  453. this.modelsArray = [];
  454. this.models = api.models || {};
  455. this.rawModels = {};
  456. this.useJQuery = (typeof api.useJQuery !== 'undefined') ? api.useJQuery : null;
  457. if ((resourceObj.apis) && this.api.resourcePath) {
  458. this.addApiDeclaration(resourceObj);
  459. } else {
  460. if (typeof this.path === 'undefined') {
  461. this.api.fail('SwaggerResources must have a path.');
  462. }
  463. if (this.path.substring(0, 4) === 'http') {
  464. this.url = this.path.replace('{format}', 'json');
  465. } else {
  466. this.url = this.api.basePath + this.path.replace('{format}', 'json');
  467. }
  468. this.api.progress('fetching resource ' + this.name + ': ' + this.url);
  469. var obj = {
  470. url: this.url,
  471. method: 'GET',
  472. useJQuery: this.useJQuery,
  473. headers: {
  474. accept: this.swaggerRequstHeaders
  475. },
  476. on: {
  477. response: function (resp) {
  478. var responseObj = resp.obj || JSON.parse(resp.data);
  479. self.api.resourceCount += 1;
  480. return self.addApiDeclaration(responseObj);
  481. },
  482. error: function (response) {
  483. self.api.resourceCount += 1;
  484. return self.api.fail('Unable to read api \'' +
  485. self.name + '\' from path ' + self.url + ' (server returned ' + response.statusText + ')');
  486. }
  487. }
  488. };
  489. api.clientAuthorizations.apply(obj);
  490. new SwaggerHttp().execute(obj);
  491. }
  492. };
  493. SwaggerClient.prototype.buildFrom1_2Spec = function (response) { // jshint ignore:line
  494. if (response.apiVersion !== null) {
  495. this.apiVersion = response.apiVersion;
  496. }
  497. this.apis = {};
  498. this.apisArray = [];
  499. this.authSchemes = response.authorizations;
  500. this.consumes = response.consumes;
  501. this.info = this.convertInfo(response.info);
  502. this.produces = response.produces;
  503. var isApi = false, i, res;
  504. for (i = 0; i < response.apis.length; i++) {
  505. var api = response.apis[i];
  506. if (api.operations) {
  507. var j;
  508. for (j = 0; j < api.operations.length; j++) {
  509. isApi = true;
  510. }
  511. }
  512. }
  513. if (response.basePath) {
  514. this.basePath = response.basePath;
  515. } else if (this.url.indexOf('?') > 0) {
  516. this.basePath = this.url.substring(0, this.url.lastIndexOf('?'));
  517. } else {
  518. this.basePath = this.url;
  519. }
  520. if (isApi) {
  521. var newName = response.resourcePath.replace(/\//g, '');
  522. this.resourcePath = response.resourcePath;
  523. res = new SwaggerResource(response, this);
  524. this.apis[newName] = res;
  525. this.apisArray.push(res);
  526. this.finish();
  527. } else {
  528. var k;
  529. this.expectedResourceCount = response.apis.length;
  530. for (k = 0; k < response.apis.length; k++) {
  531. var resource = response.apis[k];
  532. res = new SwaggerResource(resource, this);
  533. this.apis[res.name] = res;
  534. this.apisArray.push(res);
  535. }
  536. }
  537. this.isValid = true;
  538. return this;
  539. };
  540. SwaggerClient.prototype.finish = function () {
  541. if (typeof this.success === 'function') {
  542. this.isValid = true;
  543. this.ready = true;
  544. this.isBuilt = true;
  545. this.selfReflect();
  546. this.success();
  547. }
  548. };
  549. SwaggerClient.prototype.buildFrom1_1Spec = function (response) { // jshint ignore:line
  550. helpers.log('This API is using a deprecated version of Swagger! Please see http://github.com/wordnik/swagger-core/wiki for more info');
  551. if (response.apiVersion !== null) {
  552. this.apiVersion = response.apiVersion;
  553. }
  554. this.apis = {};
  555. this.apisArray = [];
  556. this.produces = response.produces;
  557. this.info = this.convertInfo(response.info);
  558. var isApi = false, res;
  559. for (var i = 0; i < response.apis.length; i++) {
  560. var api = response.apis[i];
  561. if (api.operations) {
  562. for (var j = 0; j < api.operations.length; j++) {
  563. isApi = true;
  564. break;
  565. }
  566. }
  567. }
  568. if (response.basePath) {
  569. this.basePath = response.basePath;
  570. } else if (this.url.indexOf('?') > 0) {
  571. this.basePath = this.url.substring(0, this.url.lastIndexOf('?'));
  572. } else {
  573. this.basePath = this.url;
  574. }
  575. if (isApi) {
  576. var newName = response.resourcePath.replace(/\//g, '');
  577. this.resourcePath = response.resourcePath;
  578. res = new SwaggerResource(response, this);
  579. this.apis[newName] = res;
  580. this.apisArray.push(res);
  581. this.finish();
  582. } else {
  583. this.expectedResourceCount = response.apis.length;
  584. for (var k = 0; k < response.apis.length; k++) {
  585. res = new SwaggerResource(response.apis[k], this);
  586. this.apis[res.name] = res;
  587. this.apisArray.push(res);
  588. }
  589. }
  590. this.isValid = true;
  591. return this;
  592. };
  593. SwaggerClient.prototype.convertInfo = function (resp) {
  594. if (typeof resp === 'object') {
  595. var info = {};
  596. info.title = resp.title;
  597. info.description = resp.description;
  598. info.termsOfService = resp.termsOfServiceUrl;
  599. info.contact = {};
  600. info.contact.name = resp.contact;
  601. info.license = {};
  602. info.license.name = resp.license;
  603. info.license.url = resp.licenseUrl;
  604. return info;
  605. }
  606. };
  607. SwaggerClient.prototype.selfReflect = function () {
  608. var tag, ref;
  609. if (this.apis === null) {
  610. return false;
  611. }
  612. ref = this.apis;
  613. for (tag in ref) {
  614. var api = ref[tag];
  615. if (api.ready === null) {
  616. return false;
  617. }
  618. this[tag] = api;
  619. this[tag].help = helpers.__bind(api.help, api);
  620. }
  621. this.setConsolidatedModels();
  622. this.ready = true;
  623. };
  624. SwaggerClient.prototype.setConsolidatedModels = function () {
  625. var model, modelName, resource, resourceName, i, apis, models, results;
  626. this.models = {};
  627. apis = this.apis;
  628. for (resourceName in apis) {
  629. resource = apis[resourceName];
  630. for (modelName in resource.models) {
  631. if (typeof this.models[modelName] === 'undefined') {
  632. this.models[modelName] = resource.models[modelName];
  633. this.modelsArray.push(resource.models[modelName]);
  634. }
  635. }
  636. }
  637. models = this.modelsArray;
  638. results = [];
  639. for (i = 0; i < models.length; i++) {
  640. model = models[i];
  641. results.push(model.setReferencedModels(this.models));
  642. }
  643. return results;
  644. };
  645. SwaggerResource.prototype.help = function (dontPrint) {
  646. var output = 'operations for the "' + this.name + '" tag';
  647. var i;
  648. for (i = 0; i < this.operationsArray.length; i++) {
  649. var api = this.operationsArray[i];
  650. output += '\n * ' + api.nickname + ': ' + api.description;
  651. }
  652. if (dontPrint) {
  653. return output;
  654. } else {
  655. helpers.log(output);
  656. return output;
  657. }
  658. };
  659. SwaggerResource.prototype.getAbsoluteBasePath = function (relativeBasePath) {
  660. var url = this.api.basePath;
  661. var pos = url.lastIndexOf(relativeBasePath);
  662. var parts = url.split('/');
  663. var rootUrl = parts[0] + '//' + parts[2];
  664. if (relativeBasePath.indexOf('http') === 0) {
  665. return relativeBasePath;
  666. }
  667. if (relativeBasePath === '/') {
  668. return rootUrl;
  669. }
  670. if (relativeBasePath.substring(0, 1) === '/') {
  671. // use root + relative
  672. return rootUrl + relativeBasePath;
  673. } else {
  674. pos = this.basePath.lastIndexOf('/');
  675. var base = this.basePath.substring(0, pos);
  676. if (base.substring(base.length - 1) === '/') {
  677. return base + relativeBasePath;
  678. } else {
  679. return base + '/' + relativeBasePath;
  680. }
  681. }
  682. };
  683. SwaggerResource.prototype.addApiDeclaration = function (response) {
  684. if (typeof response.produces === 'string') {
  685. this.produces = response.produces;
  686. }
  687. if (typeof response.consumes === 'string') {
  688. this.consumes = response.consumes;
  689. }
  690. if ((typeof response.basePath === 'string') && response.basePath.replace(/\s/g, '').length > 0) {
  691. this.basePath = response.basePath.indexOf('http') !== 0 ? this.getAbsoluteBasePath(response.basePath) : response.basePath;
  692. }
  693. this.resourcePath = response.resourcePath;
  694. this.addModels(response.models);
  695. if (response.apis) {
  696. for (var i = 0 ; i < response.apis.length; i++) {
  697. var endpoint = response.apis[i];
  698. this.addOperations(endpoint.path, endpoint.operations, response.consumes, response.produces);
  699. }
  700. }
  701. this.api[this.name] = this;
  702. this.ready = true;
  703. if (this.api.resourceCount === this.api.expectedResourceCount) {
  704. this.api.finish();
  705. }
  706. return this;
  707. };
  708. SwaggerResource.prototype.addModels = function (models) {
  709. if (typeof models === 'object') {
  710. var modelName;
  711. for (modelName in models) {
  712. if (typeof this.models[modelName] === 'undefined') {
  713. var swaggerModel = new SwaggerModel(modelName, models[modelName], this.api);
  714. this.modelsArray.push(swaggerModel);
  715. this.models[modelName] = swaggerModel;
  716. this.rawModels[modelName] = models[modelName];
  717. }
  718. }
  719. var output = [];
  720. for (var i = 0; i < this.modelsArray.length; i++) {
  721. var model = this.modelsArray[i];
  722. output.push(model.setReferencedModels(this.models));
  723. }
  724. return output;
  725. }
  726. };
  727. SwaggerResource.prototype.addOperations = function (resourcePath, ops, consumes, produces) {
  728. if (ops) {
  729. var output = [];
  730. for (var i = 0; i < ops.length; i++) {
  731. var o = ops[i];
  732. consumes = this.consumes;
  733. produces = this.produces;
  734. if (typeof o.consumes !== 'undefined') {
  735. consumes = o.consumes;
  736. } else {
  737. consumes = this.consumes;
  738. }
  739. if (typeof o.produces !== 'undefined') {
  740. produces = o.produces;
  741. } else {
  742. produces = this.produces;
  743. }
  744. var type = (o.type || o.responseClass);
  745. if (type === 'array') {
  746. var ref = null;
  747. if (o.items) {
  748. ref = o.items.type || o.items.$ref;
  749. }
  750. type = 'array[' + ref + ']';
  751. }
  752. var responseMessages = o.responseMessages;
  753. var method = o.method;
  754. if (o.httpMethod) {
  755. method = o.httpMethod;
  756. }
  757. if (o.supportedContentTypes) {
  758. consumes = o.supportedContentTypes;
  759. }
  760. if (o.errorResponses) {
  761. responseMessages = o.errorResponses;
  762. for (var j = 0; j < responseMessages.length; j++) {
  763. var r = responseMessages[j];
  764. r.message = r.reason;
  765. r.reason = null;
  766. }
  767. }
  768. o.nickname = this.sanitize(o.nickname);
  769. var op = new SwaggerOperation(o.nickname,
  770. resourcePath,
  771. method,
  772. o.parameters,
  773. o.summary,
  774. o.notes,
  775. type,
  776. responseMessages,
  777. this,
  778. consumes,
  779. produces,
  780. o.authorizations,
  781. o.deprecated, this.clientAuthorizations);
  782. this.operations[op.nickname] = op;
  783. output.push(this.operationsArray.push(op));
  784. }
  785. return output;
  786. }
  787. };
  788. SwaggerResource.prototype.sanitize = function (nickname) {
  789. var op = nickname.replace(/[\s!@#$%^&*()_+=\[{\]};:<>|.\/?,\\'""-]/g, '_');
  790. op = op.replace(/((_){2,})/g, '_');
  791. op = op.replace(/^(_)*/g, '');
  792. op = op.replace(/([_])*$/g, '');
  793. return op;
  794. };
  795. SwaggerModel.prototype.setReferencedModels = function (allModels) {
  796. var results = [];
  797. for (var i = 0; i < this.properties.length; i++) {
  798. var property = this.properties[i];
  799. var type = property.type || property.dataType;
  800. if (allModels[type]) {
  801. results.push(property.refModel = allModels[type]);
  802. } else if ((property.refDataType) && (allModels[property.refDataType])) {
  803. results.push(property.refModel = allModels[property.refDataType]);
  804. } else {
  805. results.push(void 0);
  806. }
  807. }
  808. return results;
  809. };
  810. SwaggerModel.prototype.getMockSignature = function (modelsToIgnore) {
  811. var i, prop, propertiesStr = [];
  812. for (i = 0; i < this.properties.length; i++) {
  813. prop = this.properties[i];
  814. propertiesStr.push(prop.toString());
  815. }
  816. var strong = '<span class="strong">';
  817. var strongClose = '</span>';
  818. var classOpen = strong + this.name + ' {' + strongClose;
  819. var classClose = strong + '}' + strongClose;
  820. var returnVal = classOpen + '<div>' + propertiesStr.join(',</div><div>') + '</div>' + classClose;
  821. if (!modelsToIgnore) {
  822. modelsToIgnore = [];
  823. }
  824. modelsToIgnore.push(this.name);
  825. for (i = 0; i < this.properties.length; i++) {
  826. prop = this.properties[i];
  827. if ((prop.refModel) && modelsToIgnore.indexOf(prop.refModel.name) === -1) {
  828. returnVal = returnVal + ('<br>' + prop.refModel.getMockSignature(modelsToIgnore));
  829. }
  830. }
  831. return returnVal;
  832. };
  833. SwaggerModel.prototype.createJSONSample = function (modelsToIgnore) {
  834. if (this.sampleModels[this.name]) {
  835. return this.sampleModels[this.name];
  836. } else {
  837. var result = {};
  838. modelsToIgnore = (modelsToIgnore || []);
  839. modelsToIgnore.push(this.name);
  840. for (var i = 0; i < this.properties.length; i++) {
  841. var prop = this.properties[i];
  842. result[prop.name] = prop.getSampleValue(modelsToIgnore);
  843. }
  844. modelsToIgnore.pop(this.name);
  845. return result;
  846. }
  847. };
  848. SwaggerModelProperty.prototype.getSampleValue = function (modelsToIgnore) {
  849. var result;
  850. if ((this.refModel) && (modelsToIgnore.indexOf(this.refModel.name) === -1)) {
  851. result = this.refModel.createJSONSample(modelsToIgnore);
  852. } else {
  853. if (this.isCollection) {
  854. result = this.toSampleValue(this.refDataType);
  855. } else {
  856. result = this.toSampleValue(this.dataType);
  857. }
  858. }
  859. if (this.isCollection) {
  860. return [result];
  861. } else {
  862. return result;
  863. }
  864. };
  865. SwaggerModelProperty.prototype.toSampleValue = function (value) {
  866. var result;
  867. if ((typeof this.defaultValue !== 'undefined') && this.defaultValue) {
  868. result = this.defaultValue;
  869. } else if (value === 'integer') {
  870. result = 0;
  871. } else if (value === 'boolean') {
  872. result = false;
  873. } else if (value === 'double' || value === 'number') {
  874. result = 0.0;
  875. } else if (value === 'string') {
  876. result = '';
  877. } else {
  878. result = value;
  879. }
  880. return result;
  881. };
  882. SwaggerModelProperty.prototype.toString = function () {
  883. var req = this.required ? 'propReq' : 'propOpt';
  884. var str = '<span class="propName ' + req + '">' + this.name + '</span> (<span class="propType">' + this.dataTypeWithRef + '</span>';
  885. if (!this.required) {
  886. str += ', <span class="propOptKey">optional</span>';
  887. }
  888. str += ')';
  889. if (this.values) {
  890. str += ' = <span class="propVals">[\'' + this.values.join('\' or \'') + '\']</span>';
  891. }
  892. if (this.descr) {
  893. str += ': <span class="propDesc">' + this.descr + '</span>';
  894. }
  895. return str;
  896. };
  897. SwaggerOperation.prototype.isListType = function (type) {
  898. if (type && type.indexOf('[') >= 0) {
  899. return type.substring(type.indexOf('[') + 1, type.indexOf(']'));
  900. } else {
  901. return void 0;
  902. }
  903. };
  904. SwaggerOperation.prototype.getSignature = function (type, models) {
  905. var listType = this.isListType(type);
  906. var isPrimitive = ((typeof listType !== 'undefined') && models[listType]) || (typeof models[type] !== 'undefined') ? false : true;
  907. if (isPrimitive) {
  908. return type;
  909. } else {
  910. if (typeof listType !== 'undefined') {
  911. return models[listType].getMockSignature();
  912. } else {
  913. return models[type].getMockSignature();
  914. }
  915. }
  916. };
  917. SwaggerOperation.prototype.getSampleJSON = function (type, models) {
  918. var listType = this.isListType(type);
  919. var isPrimitive = ((typeof listType !== 'undefined') && models[listType]) || (typeof models[type] !== 'undefined') ? false : true;
  920. var val = isPrimitive ? void 0 : (listType ? models[listType].createJSONSample() : models[type].createJSONSample());
  921. if (val) {
  922. val = listType ? [val] : val;
  923. if (typeof val === 'string') {
  924. return val;
  925. } else if (typeof val === 'object') {
  926. var t = val;
  927. if (val instanceof Array && val.length > 0) {
  928. t = val[0];
  929. }
  930. if (t.nodeName) {
  931. var xmlString = new XMLSerializer().serializeToString(t);
  932. return this.formatXml(xmlString);
  933. } else {
  934. return JSON.stringify(val, null, 2);
  935. }
  936. } else {
  937. return val;
  938. }
  939. }
  940. };
  941. SwaggerOperation.prototype['do'] = function (args, opts, callback, error) {
  942. var key, param, params, possibleParams = [], req, value;
  943. if (typeof error !== 'function') {
  944. error = function (xhr, textStatus, error) {
  945. return helpers.log(xhr, textStatus, error);
  946. };
  947. }
  948. if (typeof callback !== 'function') {
  949. callback = function (response) {
  950. var content= null;
  951. if (response !== null) {
  952. content = response.data;
  953. } else {
  954. content = 'no data';
  955. }
  956. return helpers.log('default callback: ' + content);
  957. };
  958. }
  959. params = {};
  960. params.headers = [];
  961. if (args.headers) {
  962. params.headers = args.headers;
  963. delete args.headers;
  964. }
  965. // allow override from the opts
  966. if (opts && opts.responseContentType) {
  967. params.headers['Content-Type'] = opts.responseContentType;
  968. }
  969. if (opts && opts.requestContentType) {
  970. params.headers.Accept = opts.requestContentType;
  971. }
  972. for (var i = 0; i < this.parameters.length; i++) {
  973. param = this.parameters[i];
  974. if (param.paramType === 'header') {
  975. if (typeof args[param.name] !== 'undefined') {
  976. params.headers[param.name] = args[param.name];
  977. }
  978. } else if (param.paramType === 'form' || param.paramType.toLowerCase() === 'file') {
  979. possibleParams.push(param);
  980. } else if (param.paramType === 'body' && param.name !== 'body' && typeof args[param.name] !== 'undefined') {
  981. if (args.body) {
  982. throw new Error('Saw two body params in an API listing; expecting a max of one.');
  983. }
  984. args.body = args[param.name];
  985. }
  986. }
  987. if (typeof args.body !== 'undefined') {
  988. params.body = args.body;
  989. delete args.body;
  990. }
  991. if (possibleParams) {
  992. for (key in possibleParams) {
  993. value = possibleParams[key];
  994. if (args[value.name]) {
  995. params[value.name] = args[value.name];
  996. }
  997. }
  998. }
  999. req = new SwaggerRequest(this.method, this.urlify(args), params, opts, callback, error, this);
  1000. if (opts.mock) {
  1001. return req;
  1002. } else {
  1003. return true;
  1004. }
  1005. };
  1006. SwaggerOperation.prototype.pathJson = function () {
  1007. return this.path.replace('{format}', 'json');
  1008. };
  1009. SwaggerOperation.prototype.pathXml = function () {
  1010. return this.path.replace('{format}', 'xml');
  1011. };
  1012. SwaggerOperation.prototype.encodePathParam = function (pathParam) {
  1013. var encParts, part, parts, _i, _len;
  1014. pathParam = pathParam.toString();
  1015. if (pathParam.indexOf('/') === -1) {
  1016. return encodeURIComponent(pathParam);
  1017. } else {
  1018. parts = pathParam.split('/');
  1019. encParts = [];
  1020. for (_i = 0, _len = parts.length; _i < _len; _i++) {
  1021. part = parts[_i];
  1022. encParts.push(encodeURIComponent(part));
  1023. }
  1024. return encParts.join('/');
  1025. }
  1026. };
  1027. SwaggerOperation.prototype.urlify = function (args) {
  1028. var i, j, param, url;
  1029. // ensure no double slashing...
  1030. if (this.resource.basePath.length > 1 && this.resource.basePath.slice(-1) === '/' && this.pathJson().charAt(0) === '/') {
  1031. url = this.resource.basePath + this.pathJson().substring(1);
  1032. } else {
  1033. url = this.resource.basePath + this.pathJson();
  1034. }
  1035. var params = this.parameters;
  1036. for (i = 0; i < params.length; i++) {
  1037. param = params[i];
  1038. if (param.paramType === 'path') {
  1039. if (typeof args[param.name] !== 'undefined') {
  1040. // apply path params and remove from args
  1041. var reg = new RegExp('\\{\\s*?' + param.name + '[^\\{\\}\\/]*(?:\\{.*?\\}[^\\{\\}\\/]*)*\\}(?=(\\/?|$))', 'gi');
  1042. url = url.replace(reg, this.encodePathParam(args[param.name]));
  1043. delete args[param.name];
  1044. } else {
  1045. throw '' + param.name + ' is a required path param.';
  1046. }
  1047. }
  1048. }
  1049. var queryParams = '';
  1050. for (i = 0; i < params.length; i++) {
  1051. param = params[i];
  1052. if (param.paramType === 'query') {
  1053. var addition = '';
  1054. if (Array.isArray(param)) {
  1055. var output = '';
  1056. for (j = 0; j < param.length; j++) {
  1057. if (j > 0) {
  1058. output += ',';
  1059. }
  1060. output += encodeURIComponent(param[j]);
  1061. }
  1062. addition += encodeURIComponent(param.name) + '=' + output;
  1063. } else {
  1064. if (args[param.name]) {
  1065. addition += encodeURIComponent(param.name) + '=' + encodeURIComponent(args[param.name]);
  1066. } else {
  1067. if (param.required) {
  1068. throw '' + param.name + ' is a required query param.';
  1069. }
  1070. }
  1071. }
  1072. if (addition !== '' && queryParams.length > 0) {
  1073. queryParams += '&';
  1074. }
  1075. queryParams += addition;
  1076. }
  1077. }
  1078. if ((queryParams) && queryParams.length > 0) {
  1079. url += '?' + queryParams;
  1080. }
  1081. return url;
  1082. };
  1083. SwaggerOperation.prototype.supportHeaderParams = function () {
  1084. return this.resource.api.supportHeaderParams;
  1085. };
  1086. SwaggerOperation.prototype.supportedSubmitMethods = function () {
  1087. return this.resource.api.supportedSubmitMethods;
  1088. };
  1089. SwaggerOperation.prototype.getQueryParams = function (args) {
  1090. return this.getMatchingParams(['query'], args);
  1091. };
  1092. SwaggerOperation.prototype.getHeaderParams = function (args) {
  1093. return this.getMatchingParams(['header'], args);
  1094. };
  1095. SwaggerOperation.prototype.getMatchingParams = function (paramTypes, args) {
  1096. var matchingParams = {};
  1097. var params = this.parameters;
  1098. for (var i = 0; i < params.length; i++) {
  1099. var param = params[i];
  1100. if (args && args[param.name]) {
  1101. matchingParams[param.name] = args[param.name];
  1102. }
  1103. }
  1104. var headers = this.resource.api.headers;
  1105. var name;
  1106. for (name in headers) {
  1107. var value = headers[name];
  1108. matchingParams[name] = value;
  1109. }
  1110. return matchingParams;
  1111. };
  1112. SwaggerOperation.prototype.help = function (dontPrint) {
  1113. var msg = this.nickname + ': ' + this.summary;
  1114. var params = this.parameters;
  1115. for (var i = 0; i < params.length; i++) {
  1116. var param = params[i];
  1117. msg += '\n* ' + param.name + (param.required ? ' (required)' : '') + ' - ' + param.description;
  1118. }
  1119. if (dontPrint) {
  1120. return msg;
  1121. } else {
  1122. helpers.log(msg);
  1123. return msg;
  1124. }
  1125. };
  1126. SwaggerOperation.prototype.asCurl = function (args) {
  1127. var headers = SwaggerRequest.prototype.setHeaders(args, {}, this);
  1128. var results = [];
  1129. var i;
  1130. for (i = 0; i < this.parameters.length; i++) {
  1131. var param = this.parameters[i];
  1132. if (param.paramType && param.paramType === 'header' && args[param.name]) {
  1133. headers[param.name] = args[param.name];
  1134. }
  1135. }
  1136. var key;
  1137. for (key in headers) {
  1138. results.push('--header "' + key + ': ' + headers[key] + '"');
  1139. }
  1140. return 'curl ' + (results.join(' ')) + ' ' + this.urlify(args);
  1141. };
  1142. SwaggerOperation.prototype.formatXml = function (xml) {
  1143. var contexp, formatted, indent, lastType, lines, ln, pad, reg, transitions, wsexp, _fn, _i, _len;
  1144. reg = /(>)(<)(\/*)/g;
  1145. wsexp = /[ ]*(.*)[ ]+\n/g;
  1146. contexp = /(<.+>)(.+\n)/g;
  1147. xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2');
  1148. pad = 0;
  1149. formatted = '';
  1150. lines = xml.split('\n');
  1151. indent = 0;
  1152. lastType = 'other';
  1153. transitions = {
  1154. 'single->single': 0,
  1155. 'single->closing': -1,
  1156. 'single->opening': 0,
  1157. 'single->other': 0,
  1158. 'closing->single': 0,
  1159. 'closing->closing': -1,
  1160. 'closing->opening': 0,
  1161. 'closing->other': 0,
  1162. 'opening->single': 1,
  1163. 'opening->closing': 0,
  1164. 'opening->opening': 1,
  1165. 'opening->other': 1,
  1166. 'other->single': 0,
  1167. 'other->closing': -1,
  1168. 'other->opening': 0,
  1169. 'other->other': 0
  1170. };
  1171. _fn = function (ln) {
  1172. var fromTo, j, key, padding, type, types, value;
  1173. types = {
  1174. single: Boolean(ln.match(/<.+\/>/)),
  1175. closing: Boolean(ln.match(/<\/.+>/)),
  1176. opening: Boolean(ln.match(/<[^!?].*>/))
  1177. };
  1178. type = ((function () {
  1179. var _results;
  1180. _results = [];
  1181. for (key in types) {
  1182. value = types[key];
  1183. if (value) {
  1184. _results.push(key);
  1185. }
  1186. }
  1187. return _results;
  1188. })())[0];
  1189. type = type === void 0 ? 'other' : type;
  1190. fromTo = lastType + '->' + type;
  1191. lastType = type;
  1192. padding = '';
  1193. indent += transitions[fromTo];
  1194. padding = ((function () {
  1195. var _j, _ref5;
  1196. var _results = [];
  1197. for (j = _j = 0, _ref5 = indent; 0 <= _ref5 ? _j < _ref5 : _j > _ref5; j = 0 <= _ref5 ? ++_j : --_j) {
  1198. _results.push(' ');
  1199. }
  1200. return _results;
  1201. })()).join('');
  1202. if (fromTo === 'opening->closing') {
  1203. formatted = formatted.substr(0, formatted.length - 1) + ln + '\n';
  1204. } else {
  1205. formatted += padding + ln + '\n';
  1206. }
  1207. };
  1208. for (_i = 0, _len = lines.length; _i < _len; _i++) {
  1209. ln = lines[_i];
  1210. _fn(ln);
  1211. }
  1212. return formatted;
  1213. };
  1214. SwaggerRequest.prototype.setHeaders = function (params, opts, operation) {
  1215. var accepts = opts.responseContentType || 'application/json'; // default type
  1216. var consumes = opts.requestContentType || 'application/json'; // default type
  1217. var allDefinedParams = operation.parameters;
  1218. var definedFormParams = [];
  1219. var definedFileParams = [];
  1220. var body = params.body;
  1221. var headers = {};
  1222. var i;
  1223. // get params from the operation and set them in definedFileParams, definedFormParams, headers
  1224. for (i = 0; i < allDefinedParams.length; i++) {
  1225. var param = allDefinedParams[i];
  1226. if (param.paramType === 'form') {
  1227. definedFormParams.push(param);
  1228. } else if (param.paramType === 'file') {
  1229. definedFileParams.push(param);
  1230. } else if (param.paramType === 'header' && this.params.headers) {
  1231. var key = param.name;
  1232. var headerValue = this.params.headers[param.name];
  1233. if (typeof this.params.headers[param.name] !== 'undefined') {
  1234. headers[key] = headerValue;
  1235. }
  1236. }
  1237. }
  1238. // if there's a body, need to set the accepts header via requestContentType
  1239. if (body && (this.type === 'POST' || this.type === 'PUT' || this.type === 'PATCH' || this.type === 'DELETE')) {
  1240. if (this.opts.requestContentType) {
  1241. consumes = this.opts.requestContentType;
  1242. }
  1243. } else {
  1244. // if any form params, content type must be set
  1245. if (definedFormParams.length > 0) {
  1246. if (definedFileParams.length > 0) {
  1247. consumes = 'multipart/form-data';
  1248. } else {
  1249. consumes = 'application/x-www-form-urlencoded';
  1250. }
  1251. } else if (this.type === 'DELETE') {
  1252. body = '{}';
  1253. } else if (this.type !== 'DELETE') {
  1254. consumes = null;
  1255. }
  1256. }
  1257. if (consumes && this.operation.consumes) {
  1258. if (this.operation.consumes.indexOf(consumes) === -1) {
  1259. helpers.log('server doesn\'t consume ' + consumes + ', try ' + JSON.stringify(this.operation.consumes));
  1260. }
  1261. }
  1262. if (this.opts && this.opts.responseContentType) {
  1263. accepts = this.opts.responseContentType;
  1264. } else {
  1265. accepts = 'application/json';
  1266. }
  1267. if (accepts && operation.produces) {
  1268. if (operation.produces.indexOf(accepts) === -1) {
  1269. helpers.log('server can\'t produce ' + accepts);
  1270. }
  1271. }
  1272. if ((consumes && body !== '') || (consumes === 'application/x-www-form-urlencoded')) {
  1273. headers['Content-Type'] = consumes;
  1274. }
  1275. if (accepts) {
  1276. headers.Accept = accepts;
  1277. }
  1278. return headers;
  1279. };
  1280. },{"./client":4,"./helpers":5,"./http":6}],4:[function(require,module,exports){
  1281. 'use strict';
  1282. var auth = require('./auth');
  1283. var helpers = require('./helpers');
  1284. var Model = require('./types/model');
  1285. var Operation = require('./types/operation');
  1286. var OperationGroup = require('./types/operationGroup');
  1287. var Resolver = require('./resolver');
  1288. var SwaggerHttp = require('./http');
  1289. var SwaggerClient = module.exports = function (url, options) {
  1290. this.authorizationScheme = null;
  1291. this.authorizations = null;
  1292. this.basePath = null;
  1293. this.debug = false;
  1294. this.info = null;
  1295. this.isBuilt = false;
  1296. this.isValid = false;
  1297. this.modelsArray = [];
  1298. this.resourceCount = 0;
  1299. this.url = null;
  1300. this.useJQuery = false;
  1301. if (typeof url !== 'undefined') {
  1302. return this.initialize(url, options);
  1303. }
  1304. };
  1305. SwaggerClient.prototype.initialize = function (url, options) {
  1306. this.models = {};
  1307. this.sampleModels = {};
  1308. options = (options||{});
  1309. if (typeof url === 'string') {
  1310. this.url = url;
  1311. } else if (typeof url === 'object') {
  1312. options = url;
  1313. this.url = options.url;
  1314. }
  1315. this.swaggerRequstHeaders = options.swaggerRequstHeaders || 'application/json;charset=utf-8,*/*';
  1316. this.defaultSuccessCallback = options.defaultSuccessCallback || null;
  1317. this.defaultErrorCallback = options.defaultErrorCallback || null;
  1318. if (typeof options.success === 'function') {
  1319. this.success = options.success;
  1320. }
  1321. if (options.useJQuery) {
  1322. this.useJQuery = options.useJQuery;
  1323. }
  1324. if (options.authorizations) {
  1325. this.clientAuthorizations = options.authorizations;
  1326. } else {
  1327. this.clientAuthorizations = new auth.SwaggerAuthorizations();
  1328. }
  1329. this.supportedSubmitMethods = options.supportedSubmitMethods || [];
  1330. this.failure = options.failure || function () {};
  1331. this.progress = options.progress || function () {};
  1332. this.spec = options.spec;
  1333. this.options = options;
  1334. if (typeof options.success === 'function') {
  1335. this.ready = true;
  1336. this.build();
  1337. }
  1338. };
  1339. SwaggerClient.prototype.build = function (mock) {
  1340. if (this.isBuilt) {
  1341. return this;
  1342. }
  1343. var self = this;
  1344. this.progress('fetching resource list: ' + this.url);
  1345. var obj = {
  1346. useJQuery: this.useJQuery,
  1347. url: this.url,
  1348. method: 'get',
  1349. headers: {
  1350. accept: this.swaggerRequstHeaders
  1351. },
  1352. on: {
  1353. error: function (response) {
  1354. if (self.url.substring(0, 4) !== 'http') {
  1355. return self.fail('Please specify the protocol for ' + self.url);
  1356. } else if (response.status === 0) {
  1357. return self.fail('Can\'t read from server. It may not have the appropriate access-control-origin settings.');
  1358. } else if (response.status === 404) {
  1359. return self.fail('Can\'t read swagger JSON from ' + self.url);
  1360. } else {
  1361. return self.fail(response.status + ' : ' + response.statusText + ' ' + self.url);
  1362. }
  1363. },
  1364. response: function (resp) {
  1365. var responseObj = resp.obj || JSON.parse(resp.data);
  1366. self.swaggerVersion = responseObj.swaggerVersion;
  1367. if (responseObj.swagger && parseInt(responseObj.swagger) === 2) {
  1368. self.swaggerVersion = responseObj.swagger;
  1369. new Resolver().resolve(responseObj, self.buildFromSpec, self);
  1370. self.isValid = true;
  1371. } else {
  1372. if (self.swaggerVersion === '1.2') {
  1373. return self.buildFrom1_2Spec(responseObj); // jshint ignore:line
  1374. } else {
  1375. return self.buildFrom1_1Spec(responseObj); // jshint ignore:line
  1376. }
  1377. }
  1378. }
  1379. }
  1380. };
  1381. if (this.spec) {
  1382. setTimeout(function () {
  1383. new Resolver().resolve(self.spec, self.buildFromSpec, self);
  1384. }, 10);
  1385. } else {
  1386. this.clientAuthorizations.apply(obj);
  1387. if (mock) {
  1388. return obj;
  1389. }
  1390. new SwaggerHttp().execute(obj);
  1391. }
  1392. return this;
  1393. };
  1394. SwaggerClient.prototype.buildFromSpec = function (response) {
  1395. if (this.isBuilt) {
  1396. return this;
  1397. }
  1398. this.apis = {};
  1399. this.apisArray = [];
  1400. this.basePath = response.basePath || '';
  1401. this.consumes = response.consumes;
  1402. this.host = response.host || '';
  1403. this.info = response.info || {};
  1404. this.produces = response.produces;
  1405. this.schemes = response.schemes || [];
  1406. this.securityDefinitions = response.securityDefinitions;
  1407. this.title = response.title || '';
  1408. // legacy support
  1409. this.authSchemes = response.securityDefinitions;
  1410. var definedTags = {};
  1411. var k;
  1412. if (Array.isArray(response.tags)) {
  1413. definedTags = {};
  1414. for (k = 0; k < response.tags.length; k++) {
  1415. var t = response.tags[k];
  1416. definedTags[t.name] = t;
  1417. }
  1418. }
  1419. var location;
  1420. if (typeof this.url === 'string') {
  1421. location = this.parseUri(this.url);
  1422. }
  1423. if (typeof this.schemes === 'undefined' || this.schemes.length === 0) {
  1424. this.scheme = location.scheme || 'http';
  1425. } else {
  1426. this.scheme = this.schemes[0];
  1427. }
  1428. if (typeof this.host === 'undefined' || this.host === '') {
  1429. this.host = location.host;
  1430. if (location.port) {
  1431. this.host = this.host + ':' + location.port;
  1432. }
  1433. }
  1434. this.definitions = response.definitions;
  1435. var key;
  1436. for (key in this.definitions) {
  1437. var model = new Model(key, this.definitions[key], this.models);
  1438. if (model) {
  1439. this.models[key] = model;
  1440. }
  1441. }
  1442. // get paths, create functions for each operationId
  1443. var path;
  1444. for (path in response.paths) {
  1445. if (typeof response.paths[path] === 'object') {
  1446. var httpMethod;
  1447. for (httpMethod in response.paths[path]) {
  1448. if (['delete', 'get', 'head', 'options', 'patch', 'post', 'put'].indexOf(httpMethod) === -1) {
  1449. continue;
  1450. }
  1451. var operation = response.paths[path][httpMethod];
  1452. var tags = operation.tags;
  1453. if (typeof tags === 'undefined') {
  1454. operation.tags = [ 'default' ];
  1455. tags = operation.tags;
  1456. }
  1457. var operationId = this.idFromOp(path, httpMethod, operation);
  1458. var operationObject = new Operation (
  1459. this,
  1460. operation.scheme,
  1461. operationId,
  1462. httpMethod,
  1463. path,
  1464. operation,
  1465. this.definitions,
  1466. this.models,
  1467. this.clientAuthorizations
  1468. );
  1469. // bind this operation's execute command to the api
  1470. if (tags.length > 0) {
  1471. var i;
  1472. for (i = 0; i < tags.length; i++) {
  1473. var tag = this.tagFromLabel(tags[i]);
  1474. var operationGroup = this[tag];
  1475. if (typeof this.apis[tag] === 'undefined') {
  1476. this.apis[tag] = {};
  1477. }
  1478. if (typeof operationGroup === 'undefined') {
  1479. this[tag] = [];
  1480. operationGroup = this[tag];
  1481. operationGroup.operations = {};
  1482. operationGroup.label = tag;
  1483. operationGroup.apis = [];
  1484. var tagObject = definedTags[tag];
  1485. if (typeof tagObject === 'object') {
  1486. operationGroup.description = tagObject.description;
  1487. operationGroup.externalDocs = tagObject.externalDocs;
  1488. }
  1489. this[tag].help = this.help.bind(operationGroup);
  1490. this.apisArray.push(new OperationGroup(tag, operationGroup.description, operationGroup.externalDocs, operationObject));
  1491. }
  1492. if (typeof this.apis[tag].help !== 'function') {
  1493. this.apis[tag].help = this.help.bind(operationGroup);
  1494. }
  1495. // bind to the apis object
  1496. this.apis[tag][operationId] = operationObject.execute.bind(operationObject);
  1497. this.apis[tag][operationId].help = operationObject.help.bind(operationObject);
  1498. this.apis[tag][operationId].asCurl = operationObject.asCurl.bind(operationObject);
  1499. operationGroup[operationId] = operationObject.execute.bind(operationObject);
  1500. operationGroup[operationId].help = operationObject.help.bind(operationObject);
  1501. operationGroup[operationId].asCurl = operationObject.asCurl.bind(operationObject);
  1502. operationGroup.apis.push(operationObject);
  1503. operationGroup.operations[operationId] = operationObject;
  1504. // legacy UI feature
  1505. var j;
  1506. var api;
  1507. for (j = 0; j < this.apisArray.length; j++) {
  1508. if (this.apisArray[j].tag === tag) {
  1509. api = this.apisArray[j];
  1510. }
  1511. }
  1512. if (api) {
  1513. api.operationsArray.push(operationObject);
  1514. }
  1515. }
  1516. } else {
  1517. helpers.log('no group to bind to');
  1518. }
  1519. }
  1520. }
  1521. }
  1522. this.isBuilt = true;
  1523. if (this.success) {
  1524. this.isValid = true;
  1525. this.isBuilt = true;
  1526. this.success();
  1527. }
  1528. return this;
  1529. };
  1530. SwaggerClient.prototype.parseUri = function (uri) {
  1531. var urlParseRE = /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/;
  1532. var parts = urlParseRE.exec(uri);
  1533. return {
  1534. scheme: parts[4].replace(':',''),
  1535. host: parts[11],
  1536. port: parts[12],
  1537. path: parts[15]
  1538. };
  1539. };
  1540. SwaggerClient.prototype.help = function (dontPrint) {
  1541. var i;
  1542. var output = 'operations for the "' + this.label + '" tag';
  1543. for (i = 0; i < this.apis.length; i++) {
  1544. var api = this.apis[i];
  1545. output += '\n * ' + api.nickname + ': ' + api.operation.summary;
  1546. }
  1547. if (dontPrint) {
  1548. return output;
  1549. } else {
  1550. helpers.log(output);
  1551. return output;
  1552. }
  1553. };
  1554. SwaggerClient.prototype.tagFromLabel = function (label) {
  1555. return label;
  1556. };
  1557. SwaggerClient.prototype.idFromOp = function (path, httpMethod, op) {
  1558. var opId = op.operationId || (path.substring(1) + '_' + httpMethod);
  1559. return opId.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()\+\s]/g,'_');
  1560. };
  1561. SwaggerClient.prototype.fail = function (message) {
  1562. this.failure(message);
  1563. throw message;
  1564. };
  1565. },{"./auth":2,"./helpers":5,"./http":6,"./resolver":7,"./types/model":9,"./types/operation":10,"./types/operationGroup":11}],5:[function(require,module,exports){
  1566. 'use strict';
  1567. module.exports.__bind = function (fn, me) {
  1568. return function(){
  1569. return fn.apply(me, arguments);
  1570. };
  1571. };
  1572. var log = module.exports.log = function() {
  1573. log.history = log.history || [];
  1574. log.history.push(arguments);
  1575. if (console) {
  1576. console.log(Array.prototype.slice.call(arguments)[0]);
  1577. }
  1578. };
  1579. module.exports.fail = function (message) {
  1580. log(message);
  1581. };
  1582. module.exports.optionHtml = function (label, value) {
  1583. return '<tr><td class="optionName">' + label + ':</td><td>' + value + '</td></tr>';
  1584. };
  1585. module.exports.typeFromJsonSchema = function (type, format) {
  1586. var str;
  1587. if (type === 'integer' && format === 'int32') {
  1588. str = 'integer';
  1589. } else if (type === 'integer' && format === 'int64') {
  1590. str = 'long';
  1591. } else if (type === 'integer' && typeof format === 'undefined') {
  1592. str = 'long';
  1593. } else if (type === 'string' && format === 'date-time') {
  1594. str = 'date-time';
  1595. } else if (type === 'string' && format === 'date') {
  1596. str = 'date';
  1597. } else if (type === 'number' && format === 'float') {
  1598. str = 'float';
  1599. } else if (type === 'number' && format === 'double') {
  1600. str = 'double';
  1601. } else if (type === 'number' && typeof format === 'undefined') {
  1602. str = 'double';
  1603. } else if (type === 'boolean') {
  1604. str = 'boolean';
  1605. } else if (type === 'string') {
  1606. str = 'string';
  1607. }
  1608. return str;
  1609. };
  1610. var simpleRef = module.exports.simpleRef = function (name) {
  1611. if (typeof name === 'undefined') {
  1612. return null;
  1613. }
  1614. if (name.indexOf('#/definitions/') === 0) {
  1615. return name.substring('#/definitions/'.length);
  1616. } else {
  1617. return name;
  1618. }
  1619. };
  1620. var getStringSignature = module.exports.getStringSignature = function (obj, baseComponent) {
  1621. var str = '';
  1622. if (typeof obj.$ref !== 'undefined') {
  1623. str += simpleRef(obj.$ref);
  1624. } else if (typeof obj.type === 'undefined') {
  1625. str += 'object';
  1626. } else if (obj.type === 'array') {
  1627. if (baseComponent) {
  1628. str += getStringSignature((obj.items || obj.$ref || {}));
  1629. } else {
  1630. str += 'Array[';
  1631. str += getStringSignature((obj.items || obj.$ref || {}));
  1632. str += ']';
  1633. }
  1634. } else if (obj.type === 'integer' && obj.format === 'int32') {
  1635. str += 'integer';
  1636. } else if (obj.type === 'integer' && obj.format === 'int64') {
  1637. str += 'long';
  1638. } else if (obj.type === 'integer' && typeof obj.format === 'undefined') {
  1639. str += 'long';
  1640. } else if (obj.type === 'string' && obj.format === 'date-time') {
  1641. str += 'date-time';
  1642. } else if (obj.type === 'string' && obj.format === 'date') {
  1643. str += 'date';
  1644. } else if (obj.type === 'string' && typeof obj.format === 'undefined') {
  1645. str += 'string';
  1646. } else if (obj.type === 'number' && obj.format === 'float') {
  1647. str += 'float';
  1648. } else if (obj.type === 'number' && obj.format === 'double') {
  1649. str += 'double';
  1650. } else if (obj.type === 'number' && typeof obj.format === 'undefined') {
  1651. str += 'double';
  1652. } else if (obj.type === 'boolean') {
  1653. str += 'boolean';
  1654. } else if (obj.$ref) {
  1655. str += simpleRef(obj.$ref);
  1656. } else {
  1657. str += obj.type;
  1658. }
  1659. return str;
  1660. };
  1661. },{}],6:[function(require,module,exports){
  1662. 'use strict';
  1663. var helpers = require('./helpers');
  1664. var jQuery = require('jquery');
  1665. var request = require('superagent');
  1666. /*
  1667. * JQueryHttpClient is a light-weight, node or browser HTTP client
  1668. */
  1669. var JQueryHttpClient = function () {};
  1670. /*
  1671. * SuperagentHttpClient is a light-weight, node or browser HTTP client
  1672. */
  1673. var SuperagentHttpClient = function () {};
  1674. /**
  1675. * SwaggerHttp is a wrapper for executing requests
  1676. */
  1677. var SwaggerHttp = module.exports = function () {};
  1678. SwaggerHttp.prototype.execute = function (obj, opts) {
  1679. if (obj && (typeof obj.useJQuery === 'boolean')) {
  1680. this.useJQuery = obj.useJQuery;
  1681. } else {
  1682. this.useJQuery = this.isIE8();
  1683. }
  1684. if (obj && typeof obj.body === 'object') {
  1685. // special processing for file uploads via jquery
  1686. if (obj.body.type && obj.body.type === 'formData'){
  1687. obj.contentType = false;
  1688. obj.processData = false;
  1689. delete obj.headers['Content-Type'];
  1690. } else {
  1691. obj.body = JSON.stringify(obj.body);
  1692. }
  1693. }
  1694. if (this.useJQuery) {
  1695. return new JQueryHttpClient(opts).execute(obj);
  1696. } else {
  1697. return new SuperagentHttpClient(opts).execute(obj);
  1698. }
  1699. };
  1700. SwaggerHttp.prototype.isIE8 = function () {
  1701. var detectedIE = false;
  1702. if (typeof navigator !== 'undefined' && navigator.userAgent) {
  1703. var nav = navigator.userAgent.toLowerCase();
  1704. if (nav.indexOf('msie') !== -1) {
  1705. var version = parseInt(nav.split('msie')[1]);
  1706. if (version <= 8) {
  1707. detectedIE = true;
  1708. }
  1709. }
  1710. }
  1711. return detectedIE;
  1712. };
  1713. JQueryHttpClient.prototype.execute = function (obj) {
  1714. var cb = obj.on;
  1715. var request = obj;
  1716. obj.type = obj.method;
  1717. obj.cache = false;
  1718. delete obj.useJQuery;
  1719. /*
  1720. obj.beforeSend = function (xhr) {
  1721. var key, results;
  1722. if (obj.headers) {
  1723. results = [];
  1724. for (key in obj.headers) {
  1725. if (key.toLowerCase() === 'content-type') {
  1726. results.push(obj.contentType = obj.headers[key]);
  1727. } else if (key.toLowerCase() === 'accept') {
  1728. results.push(obj.accepts = obj.headers[key]);
  1729. } else {
  1730. results.push(xhr.setRequestHeader(key, obj.headers[key]));
  1731. }
  1732. }
  1733. return results;
  1734. }
  1735. };*/
  1736. obj.data = obj.body;
  1737. delete obj.body;
  1738. obj.complete = function (response) {
  1739. var headers = {};
  1740. var headerArray = response.getAllResponseHeaders().split('\n');
  1741. for (var i = 0; i < headerArray.length; i++) {
  1742. var toSplit = headerArray[i].trim();
  1743. if (toSplit.length === 0) {
  1744. continue;
  1745. }
  1746. var separator = toSplit.indexOf(':');
  1747. if (separator === -1) {
  1748. // Name but no value in the header
  1749. headers[toSplit] = null;
  1750. continue;
  1751. }
  1752. var name = toSplit.substring(0, separator).trim();
  1753. var value = toSplit.substring(separator + 1).trim();
  1754. headers[name] = value;
  1755. }
  1756. var out = {
  1757. url: request.url,
  1758. method: request.method,
  1759. status: response.status,
  1760. statusText: response.statusText,
  1761. data: response.responseText,
  1762. headers: headers
  1763. };
  1764. var contentType = (headers['content-type'] || headers['Content-Type'] || null);
  1765. if (contentType) {
  1766. if (contentType.indexOf('application/json') === 0 || contentType.indexOf('+json') > 0) {
  1767. try {
  1768. out.obj = response.responseJSON || JSON.parse(out.data) || {};
  1769. } catch (ex) {
  1770. // do not set out.obj
  1771. helpers.log('unable to parse JSON content');
  1772. }
  1773. }
  1774. }
  1775. if (response.status >= 200 && response.status < 300) {
  1776. cb.response(out);
  1777. } else if (response.status === 0 || (response.status >= 400 && response.status < 599)) {
  1778. cb.error(out);
  1779. } else {
  1780. return cb.response(out);
  1781. }
  1782. };
  1783. jQuery.support.cors = true;
  1784. return jQuery.ajax(obj);
  1785. };
  1786. SuperagentHttpClient.prototype.execute = function (obj) {
  1787. var method = obj.method.toLowerCase();
  1788. if (method === 'delete') {
  1789. method = 'del';
  1790. }
  1791. var headers = obj.headers || {};
  1792. var r = request[method](obj.url);
  1793. var name;
  1794. for (name in headers) {
  1795. r.set(name, headers[name]);
  1796. }
  1797. if (obj.body) {
  1798. r.send(obj.body);
  1799. }
  1800. r.end(function (err, res) {
  1801. var response = {
  1802. url: obj.url,
  1803. method: obj.method,
  1804. headers: headers
  1805. };
  1806. var cb;
  1807. if (!err && res.error) {
  1808. err = res.error;
  1809. }
  1810. if (err && obj.on && obj.on.error) {
  1811. response.obj = err;
  1812. response.status = res ? res.status : 500;
  1813. response.statusText = res ? res.text : err.message;
  1814. cb = obj.on.error;
  1815. } else if (res && obj.on && obj.on.response) {
  1816. response.obj = (typeof res.body !== 'undefined') ? res.body : res.text;
  1817. response.status = res.status;
  1818. response.statusText = res.text;
  1819. cb = obj.on.response;
  1820. }
  1821. response.data = response.statusText;
  1822. if (cb) {
  1823. cb(response);
  1824. }
  1825. });
  1826. };
  1827. },{"./helpers":5,"jquery":18,"superagent":19}],7:[function(require,module,exports){
  1828. 'use strict';
  1829. var SwaggerHttp = require('./http');
  1830. /**
  1831. * Resolves a spec's remote references
  1832. */
  1833. var Resolver = module.exports = function () {};
  1834. Resolver.prototype.resolve = function (spec, callback, scope) {
  1835. this.scope = (scope || this);
  1836. var host, name, path, property, propertyName;
  1837. var processedCalls = 0, resolvedRefs = {}, unresolvedRefs = {};
  1838. var resolutionTable = {}; // store objects for dereferencing
  1839. // models
  1840. for (name in spec.definitions) {
  1841. var model = spec.definitions[name];
  1842. for (propertyName in model.properties) {
  1843. property = model.properties[propertyName];
  1844. this.resolveTo(property, resolutionTable);
  1845. }
  1846. }
  1847. // operations
  1848. for (name in spec.paths) {
  1849. var method, operation, responseCode;
  1850. path = spec.paths[name];
  1851. for (method in path) {
  1852. operation = path[method];
  1853. var i, parameters = operation.parameters;
  1854. for (i in parameters) {
  1855. var parameter = parameters[i];
  1856. if (parameter.in === 'body' && parameter.schema) {
  1857. this.resolveTo(parameter.schema, resolutionTable);
  1858. }
  1859. if (parameter.$ref) {
  1860. this.resolveInline(spec, parameter, resolutionTable, unresolvedRefs);
  1861. }
  1862. }
  1863. for (responseCode in operation.responses) {
  1864. var response = operation.responses[responseCode];
  1865. if (response.schema) {
  1866. this.resolveTo(response.schema, resolutionTable);
  1867. }
  1868. }
  1869. }
  1870. }
  1871. // get hosts
  1872. var opts = {}, expectedCalls = 0;
  1873. for (name in resolutionTable) {
  1874. var parts = name.split('#');
  1875. if (parts.length === 2) {
  1876. host = parts[0]; path = parts[1];
  1877. if (!Array.isArray(opts[host])) {
  1878. opts[host] = [];
  1879. expectedCalls += 1;
  1880. }
  1881. opts[host].push(path);
  1882. }
  1883. }
  1884. for (name in opts) {
  1885. var self = this, opt = opts[name];
  1886. host = name;
  1887. var obj = {
  1888. useJQuery: false, // TODO
  1889. url: host,
  1890. method: 'get',
  1891. headers: {
  1892. accept: this.scope.swaggerRequestHeaders || 'application/json'
  1893. },
  1894. on: {
  1895. error: function () {
  1896. processedCalls += 1;
  1897. var i;
  1898. for (i = 0; i < opt.length; i++) {
  1899. // fail all of these
  1900. var resolved = host + '#' + opt[i];
  1901. unresolvedRefs[resolved] = null;
  1902. }
  1903. if (processedCalls === expectedCalls) {
  1904. self.finish(spec, resolutionTable, resolvedRefs, unresolvedRefs, callback);
  1905. }
  1906. }, // jshint ignore:line
  1907. response: function (response) {
  1908. var i, j, swagger = response.obj;
  1909. processedCalls += 1;
  1910. for (i = 0; i < opt.length; i++) {
  1911. var location = swagger, path = opt[i], parts = path.split('/');
  1912. for (j = 0; j < parts.length; j++) {
  1913. var segment = parts[j];
  1914. if (typeof location === 'undefined') {
  1915. break;
  1916. }
  1917. if (segment.length > 0) {
  1918. location = location[segment];
  1919. }
  1920. }
  1921. var resolved = host + '#' + path, resolvedName = parts[j-1];
  1922. if (typeof location !== 'undefined') {
  1923. resolvedRefs[resolved] = {
  1924. name: resolvedName,
  1925. obj: location
  1926. };
  1927. } else {
  1928. unresolvedRefs[resolved] = null;
  1929. }
  1930. }
  1931. if (processedCalls === expectedCalls) {
  1932. self.finish(spec, resolutionTable, resolvedRefs, unresolvedRefs, callback);
  1933. }
  1934. }
  1935. } // jshint ignore:line
  1936. };
  1937. if (scope && scope.clientAuthorizations) {
  1938. scope.clientAuthorizations.apply(obj);
  1939. }
  1940. new SwaggerHttp().execute(obj);
  1941. }
  1942. if (Object.keys(opts).length === 0) {
  1943. callback.call(this.scope, spec, unresolvedRefs);
  1944. }
  1945. };
  1946. Resolver.prototype.finish = function (spec, resolutionTable, resolvedRefs, unresolvedRefs, callback) {
  1947. // walk resolution table and replace with resolved refs
  1948. var ref;
  1949. for (ref in resolutionTable) {
  1950. var i, locations = resolutionTable[ref];
  1951. for (i = 0; i < locations.length; i++) {
  1952. var resolvedTo = resolvedRefs[locations[i].obj.$ref];
  1953. if (resolvedTo) {
  1954. if (!spec.definitions) {
  1955. spec.definitions = {};
  1956. }
  1957. if (locations[i].resolveAs === '$ref') {
  1958. spec.definitions[resolvedTo.name] = resolvedTo.obj;
  1959. locations[i].obj.$ref = '#/definitions/' + resolvedTo.name;
  1960. } else if (locations[i].resolveAs === 'inline') {
  1961. var targetObj = locations[i].obj;
  1962. var key;
  1963. delete targetObj.$ref;
  1964. for (key in resolvedTo.obj) {
  1965. targetObj[key] = resolvedTo.obj[key];
  1966. }
  1967. }
  1968. }
  1969. }
  1970. }
  1971. callback.call(this.scope, spec, unresolvedRefs);
  1972. };
  1973. /**
  1974. * immediately in-lines local refs, queues remote refs
  1975. * for inline resolution
  1976. */
  1977. Resolver.prototype.resolveInline = function (spec, property, objs, unresolvedRefs) {
  1978. var ref = property.$ref;
  1979. if (ref) {
  1980. if (ref.indexOf('http') === 0) {
  1981. if (Array.isArray(objs[ref])) {
  1982. objs[ref].push({obj: property, resolveAs: 'inline'});
  1983. } else {
  1984. objs[ref] = [{obj: property, resolveAs: 'inline'}];
  1985. }
  1986. } else if (ref.indexOf('#') === 0) {
  1987. // local resolve
  1988. var shortenedRef = ref.substring(1);
  1989. var i, parts = shortenedRef.split('/'), location = spec;
  1990. for (i = 0; i < parts.length; i++) {
  1991. var part = parts[i];
  1992. if (part.length > 0) {
  1993. location = location[part];
  1994. }
  1995. }
  1996. if (location) {
  1997. delete property.$ref;
  1998. var key;
  1999. for (key in location) {
  2000. property[key] = location[key];
  2001. }
  2002. } else {
  2003. unresolvedRefs[ref] = null;
  2004. }
  2005. }
  2006. } else if (property.type === 'array') {
  2007. this.resolveTo(property.items, objs);
  2008. }
  2009. };
  2010. Resolver.prototype.resolveTo = function (property, objs) {
  2011. var ref = property.$ref;
  2012. if (ref) {
  2013. if (ref.indexOf('http') === 0) {
  2014. if (Array.isArray(objs[ref])) {
  2015. objs[ref].push({obj: property, resolveAs: '$ref'});
  2016. } else {
  2017. objs[ref] = [{obj: property, resolveAs: '$ref'}];
  2018. }
  2019. }
  2020. } else if (property.type === 'array') {
  2021. var items = property.items;
  2022. this.resolveTo(items, objs);
  2023. }
  2024. };
  2025. },{"./http":6}],8:[function(require,module,exports){
  2026. 'use strict';
  2027. var helpers = require('../helpers');
  2028. var ArrayModel = module.exports = function (definition, models) {
  2029. this.models = models;
  2030. this.name = 'arrayModel';
  2031. this.definition = definition || {};
  2032. this.properties = [];
  2033. var innerType = definition.items;
  2034. if (innerType) {
  2035. if (innerType.type) {
  2036. this.type = helpers.typeFromJsonSchema(innerType.type, innerType.format);
  2037. } else {
  2038. this.ref = innerType.$ref;
  2039. }
  2040. }
  2041. return this;
  2042. };
  2043. ArrayModel.prototype.createJSONSample = function (modelsToIgnore) {
  2044. var result;
  2045. modelsToIgnore = (modelsToIgnore||{});
  2046. if (this.type) {
  2047. result = this.type;
  2048. } else if (this.ref) {
  2049. var name = helpers.simpleRef(this.ref);
  2050. if (typeof modelsToIgnore[name] === 'undefined') {
  2051. modelsToIgnore[name] = this;
  2052. result = this.models[name].createJSONSample(modelsToIgnore);
  2053. } else {
  2054. return name;
  2055. }
  2056. }
  2057. return [ result ];
  2058. };
  2059. ArrayModel.prototype.getSampleValue = function (modelsToIgnore) {
  2060. var result;
  2061. modelsToIgnore = (modelsToIgnore || {});
  2062. if (this.type) {
  2063. result = this.type;
  2064. } else if (this.ref) {
  2065. var name = helpers.simpleRef(this.ref);
  2066. result = this.models[name].getSampleValue(modelsToIgnore);
  2067. }
  2068. return [ result ];
  2069. };
  2070. ArrayModel.prototype.getMockSignature = function (modelsToIgnore) {
  2071. var propertiesStr = [];
  2072. var i, prop;
  2073. for (i = 0; i < this.properties.length; i++) {
  2074. prop = this.properties[i];
  2075. propertiesStr.push(prop.toString());
  2076. }
  2077. var strong = '<span class="strong">';
  2078. var strongClose = '</span>';
  2079. var classOpen = strong + 'array' + ' {' + strongClose;
  2080. var classClose = strong + '}' + strongClose;
  2081. var returnVal = classOpen + '<div>' + propertiesStr.join(',</div><div>') + '</div>' + classClose;
  2082. if (!modelsToIgnore) {
  2083. modelsToIgnore = {};
  2084. }
  2085. modelsToIgnore[this.name] = this;
  2086. for (i = 0; i < this.properties.length; i++) {
  2087. prop = this.properties[i];
  2088. var ref = prop.$ref;
  2089. var model = this.models[ref];
  2090. if (model && typeof modelsToIgnore[ref] === 'undefined') {
  2091. returnVal = returnVal + ('<br>' + model.getMockSignature(modelsToIgnore));
  2092. }
  2093. }
  2094. return returnVal;
  2095. };
  2096. },{"../helpers":5}],9:[function(require,module,exports){
  2097. 'use strict';
  2098. var ArrayModel = require('./arrayModel');
  2099. var helpers = require('../helpers');
  2100. var Property = module.exports = function (name, obj, required, models) {
  2101. this.models = models;
  2102. this.schema = obj;
  2103. this.required = required;
  2104. if (obj.$ref) {
  2105. this.$ref = helpers.simpleRef(obj.$ref);
  2106. } else if (obj.type === 'array' && obj.items) {
  2107. if (obj.items.$ref) {
  2108. this.$ref = helpers.simpleRef(obj.items.$ref);
  2109. } else {
  2110. obj = obj.items;
  2111. }
  2112. }
  2113. this.name = name;
  2114. this.description = obj.description;
  2115. this.obj = obj;
  2116. this.optional = true;
  2117. this.optional = !required;
  2118. this.default = obj.default || null;
  2119. this.example = obj.example !== undefined ? obj.example : null;
  2120. this.collectionFormat = obj.collectionFormat || null;
  2121. this.maximum = obj.maximum || null;
  2122. this.exclusiveMaximum = obj.exclusiveMaximum || null;
  2123. this.minimum = obj.minimum || null;
  2124. this.exclusiveMinimum = obj.exclusiveMinimum || null;
  2125. this.maxLength = obj.maxLength || null;
  2126. this.minLength = obj.minLength || null;
  2127. this.pattern = obj.pattern || null;
  2128. this.maxItems = obj.maxItems || null;
  2129. this.minItems = obj.minItems || null;
  2130. this.uniqueItems = obj.uniqueItems || null;
  2131. this['enum'] = obj['enum'] || null;
  2132. this.multipleOf = obj.multipleOf || null;
  2133. };
  2134. var Model = module.exports = function (name, definition, models) {
  2135. this.models = models || {};
  2136. this.name = name;
  2137. this.definition = definition || {};
  2138. this.properties = [];
  2139. if (definition.type === 'array') {
  2140. return new ArrayModel(definition, models);
  2141. }
  2142. var requiredFields = definition.required || [];
  2143. var key;
  2144. var props = definition.properties;
  2145. if (props) {
  2146. for (key in props) {
  2147. var required = false;
  2148. var property = props[key];
  2149. if (requiredFields.indexOf(key) >= 0) {
  2150. required = true;
  2151. }
  2152. this.properties.push(new Property(key, property, required, this.models));
  2153. }
  2154. }
  2155. return this;
  2156. };
  2157. Model.prototype.createJSONSample = function (modelsToIgnore) {
  2158. var i, result = {}, representations = {};
  2159. modelsToIgnore = (modelsToIgnore||{});
  2160. modelsToIgnore[this.name] = this;
  2161. for (i = 0; i < this.properties.length; i++) {
  2162. var prop = this.properties[i];
  2163. var sample = prop.getSampleValue(modelsToIgnore, representations);
  2164. result[prop.name] = sample;
  2165. }
  2166. delete modelsToIgnore[this.name];
  2167. return result;
  2168. };
  2169. Model.prototype.getSampleValue = function (modelsToIgnore) {
  2170. var i, obj = {}, representations = {};
  2171. for (i = 0; i < this.properties.length; i++ ) {
  2172. var property = this.properties[i];
  2173. obj[property.name] = property.sampleValue(false, modelsToIgnore, representations);
  2174. }
  2175. return obj;
  2176. };
  2177. Model.prototype.getMockSignature = function (modelsToIgnore) {
  2178. var i, prop, propertiesStr = [];
  2179. for (i = 0; i < this.properties.length; i++) {
  2180. prop = this.properties[i];
  2181. propertiesStr.push(prop.toString());
  2182. }
  2183. var strong = '<span class="strong">';
  2184. var strongClose = '</span>';
  2185. var classOpen = strong + this.name + ' {' + strongClose;
  2186. var classClose = strong + '}' + strongClose;
  2187. var returnVal = classOpen + '<div>' + propertiesStr.join(',</div><div>') + '</div>' + classClose;
  2188. if (!modelsToIgnore) {
  2189. modelsToIgnore = {};
  2190. }
  2191. modelsToIgnore[this.name] = this;
  2192. for (i = 0; i < this.properties.length; i++) {
  2193. prop = this.properties[i];
  2194. var ref = prop.$ref;
  2195. var model = this.models[ref];
  2196. if (model && typeof modelsToIgnore[model.name] === 'undefined') {
  2197. returnVal = returnVal + ('<br>' + model.getMockSignature(modelsToIgnore));
  2198. }
  2199. }
  2200. return returnVal;
  2201. };
  2202. Property.prototype.getSampleValue = function (modelsToIgnore, representations) {
  2203. return this.sampleValue(false, modelsToIgnore, representations);
  2204. };
  2205. Property.prototype.isArray = function () {
  2206. var schema = this.schema;
  2207. if (schema.type === 'array') {
  2208. return true;
  2209. } else {
  2210. return false;
  2211. }
  2212. };
  2213. Property.prototype.sampleValue = function (isArray, ignoredModels, representations) {
  2214. isArray = (isArray || this.isArray());
  2215. ignoredModels = (ignoredModels || {});
  2216. // representations = (representations || {});
  2217. var self = this;
  2218. var getRefValue = function (ref) {
  2219. var refModelName = helpers.simpleRef(ref);
  2220. var refModel = self.models[refModelName];
  2221. var output;
  2222. if (typeof representations[type] !== 'undefined') {
  2223. output = representations[type];
  2224. }
  2225. if (refModel && typeof ignoredModels[type] === 'undefined') {
  2226. ignoredModels[type] = this;
  2227. output = refModel.getSampleValue(ignoredModels, representations);
  2228. representations[type] = output;
  2229. } else {
  2230. output = (representations[type] || refModelName);
  2231. }
  2232. return output;
  2233. };
  2234. var type = helpers.getStringSignature(this.obj, true);
  2235. var output;
  2236. if (this.$ref) {
  2237. output = getRefValue(this.$ref);
  2238. } else if (this.example) {
  2239. output = this.example;
  2240. } else if (this.default) {
  2241. output = this.default;
  2242. } else if (type === 'date-time') {
  2243. output = new Date().toISOString();
  2244. } else if (type === 'date') {
  2245. output = new Date().toISOString().split('T')[0];
  2246. } else if (type === 'string') {
  2247. output = 'string';
  2248. } else if (type === 'integer') {
  2249. output = 0;
  2250. } else if (type === 'long') {
  2251. output = 0;
  2252. } else if (type === 'float') {
  2253. output = 0.0;
  2254. } else if (type === 'double') {
  2255. output = 0.0;
  2256. } else if (type === 'boolean') {
  2257. output = true;
  2258. } else if (this.schema.$ref) {
  2259. output = getRefValue(this.schema.$ref);
  2260. } else if (this.schema.properties) {
  2261. output = new Model('InlineModel-' + new Date(), this.schema, this.models).getSampleValue();
  2262. } else {
  2263. output = {};
  2264. }
  2265. ignoredModels[type] = output;
  2266. if (isArray) {
  2267. return [output];
  2268. } else {
  2269. return output;
  2270. }
  2271. };
  2272. Property.prototype.toString = function () {
  2273. var str = helpers.getStringSignature(this.obj);
  2274. var strong ='<span class="strong">';
  2275. var strongClose = '</span>';
  2276. var propertiesStr = [];
  2277. var prop;
  2278. if (str === 'object') {
  2279. for (var name in this.schema.properties) {
  2280. if (this.schema.properties.hasOwnProperty(name)) {
  2281. prop = new Property(name, this.schema.properties[name], (this.schema.required || []).indexOf(name) > -1, this.models);
  2282. propertiesStr.push(prop.toString());
  2283. }
  2284. }
  2285. str = strong + this.name + ' {' + strongClose + '<div>' + propertiesStr.join(',</div><div>') + '</div>' + strong + '}' + strongClose;
  2286. } else if (str !== '') {
  2287. str = '<span class="propName ' + this.required + '">' + this.name + '</span> (<span class="propType">' + str + '</span>';
  2288. if (!this.required) {
  2289. str += ', <span class="propOptKey">optional</span>';
  2290. }
  2291. str += ')';
  2292. } else {
  2293. str = this.name + ' (' + JSON.stringify(this.obj) + ')';
  2294. }
  2295. if (typeof this.description !== 'undefined') {
  2296. str += ': ' + this.description;
  2297. }
  2298. if (this['enum']) {
  2299. str += ' = <span class="propVals">[\'' + this['enum'].join('\' or \'') + '\']</span>';
  2300. }
  2301. if (this.descr) {
  2302. str += ': <span class="propDesc">' + this.descr + '</span>';
  2303. }
  2304. var options = '';
  2305. var isArray = this.schema.type === 'array';
  2306. var type;
  2307. if (isArray) {
  2308. if (this.schema.items) {
  2309. type = this.schema.items.type;
  2310. } else {
  2311. type = '';
  2312. }
  2313. } else {
  2314. type = this.schema.type;
  2315. }
  2316. if (this.default) {
  2317. options += helpers.optionHtml('Default', this.default);
  2318. }
  2319. switch (type) {
  2320. case 'string':
  2321. if (this.minLength) {
  2322. options += helpers.optionHtml('Min. Length', this.minLength);
  2323. }
  2324. if (this.maxLength) {
  2325. options += helpers.optionHtml('Max. Length', this.maxLength);
  2326. }
  2327. if (this.pattern) {
  2328. options += helpers.optionHtml('Reg. Exp.', this.pattern);
  2329. }
  2330. break;
  2331. case 'integer':
  2332. case 'number':
  2333. if (this.minimum) {
  2334. options += helpers.optionHtml('Min. Value', this.minimum);
  2335. }
  2336. if (this.exclusiveMinimum) {
  2337. options += helpers.optionHtml('Exclusive Min.', 'true');
  2338. }
  2339. if (this.maximum) {
  2340. options += helpers.optionHtml('Max. Value', this.maximum);
  2341. }
  2342. if (this.exclusiveMaximum) {
  2343. options += helpers.optionHtml('Exclusive Max.', 'true');
  2344. }
  2345. if (this.multipleOf) {
  2346. options += helpers.optionHtml('Multiple Of', this.multipleOf);
  2347. }
  2348. break;
  2349. }
  2350. if (isArray) {
  2351. if (this.minItems) {
  2352. options += helpers.optionHtml('Min. Items', this.minItems);
  2353. }
  2354. if (this.maxItems) {
  2355. options += helpers.optionHtml('Max. Items', this.maxItems);
  2356. }
  2357. if (this.uniqueItems) {
  2358. options += helpers.optionHtml('Unique Items', 'true');
  2359. }
  2360. if (this.collectionFormat) {
  2361. options += helpers.optionHtml('Coll. Format', this.collectionFormat);
  2362. }
  2363. }
  2364. if (this['enum']) {
  2365. var enumString;
  2366. if (type === 'number' || type === 'integer') {
  2367. enumString = this['enum'].join(', ');
  2368. } else {
  2369. enumString = '"' + this['enum'].join('", "') + '"';
  2370. }
  2371. options += helpers.optionHtml('Enum', enumString);
  2372. }
  2373. if (options.length > 0) {
  2374. str = '<span class="propWrap">' + str + '<table class="optionsWrapper"><tr><th colspan="2">' + this.name + '</th></tr>' + options + '</table></span>';
  2375. }
  2376. return str;
  2377. };
  2378. },{"../helpers":5,"./arrayModel":8}],10:[function(require,module,exports){
  2379. 'use strict';
  2380. var ArrayModel = require('./arrayModel');
  2381. var helpers = require('../helpers');
  2382. var Model = require('./model');
  2383. var SwaggerHttp = require('../http');
  2384. var Operation = module.exports = function (parent, scheme, operationId, httpMethod, path, args, definitions, models, clientAuthorizations) {
  2385. var errors = [];
  2386. parent = parent || {};
  2387. args = args || {};
  2388. this.authorizations = args.security;
  2389. this.basePath = parent.basePath || '/';
  2390. this.clientAuthorizations = clientAuthorizations;
  2391. this.consumes = args.consumes;
  2392. this.deprecated = args.deprecated;
  2393. this.description = args.description;
  2394. this.host = parent.host || 'localhost';
  2395. this.method = (httpMethod || errors.push('Operation ' + operationId + ' is missing method.'));
  2396. this.models = models || {};
  2397. this.nickname = (operationId || errors.push('Operations must have a nickname.'));
  2398. this.operation = args;
  2399. this.operations = {};
  2400. this.parameters = args !== null ? (args.parameters || []) : {};
  2401. this.parent = parent;
  2402. this.path = (path || errors.push('Operation ' + this.nickname + ' is missing path.'));
  2403. this.produces = args.produces;
  2404. this.responses = (args.responses || {});
  2405. this.scheme = scheme || parent.scheme || 'http';
  2406. this.schemes = parent.schemes;
  2407. this.security = args.security;
  2408. this.summary = args.summary || '';
  2409. this.type = null;
  2410. this.useJQuery = parent.useJQuery;
  2411. if (typeof this.deprecated === 'string') {
  2412. switch(this.deprecated.toLowerCase()) {
  2413. case 'true': case 'yes': case '1': {
  2414. this.deprecated = true;
  2415. break;
  2416. }
  2417. case 'false': case 'no': case '0': case null: {
  2418. this.deprecated = false;
  2419. break;
  2420. }
  2421. default: this.deprecated = Boolean(this.deprecated);
  2422. }
  2423. }
  2424. var i, model;
  2425. if (definitions) {
  2426. // add to global models
  2427. var key;
  2428. for (key in this.definitions) {
  2429. model = new Model(key, definitions[key], this.models);
  2430. if (model) {
  2431. this.models[key] = model;
  2432. }
  2433. }
  2434. }
  2435. for (i = 0; i < this.parameters.length; i++) {
  2436. var param = this.parameters[i];
  2437. if (param.type === 'array') {
  2438. param.isList = true;
  2439. param.allowMultiple = true;
  2440. }
  2441. var innerType = this.getType(param);
  2442. if (innerType && innerType.toString().toLowerCase() === 'boolean') {
  2443. param.allowableValues = {};
  2444. param.isList = true;
  2445. param['enum'] = ['true', 'false'];
  2446. }
  2447. if (typeof param['enum'] !== 'undefined') {
  2448. var id;
  2449. param.allowableValues = {};
  2450. param.allowableValues.values = [];
  2451. param.allowableValues.descriptiveValues = [];
  2452. for (id = 0; id < param['enum'].length; id++) {
  2453. var value = param['enum'][id];
  2454. var isDefault = (value === param.default) ? true : false;
  2455. param.allowableValues.values.push(value);
  2456. param.allowableValues.descriptiveValues.push({value : value, isDefault: isDefault});
  2457. }
  2458. }
  2459. if (param.type === 'array') {
  2460. innerType = [innerType];
  2461. if (typeof param.allowableValues === 'undefined') {
  2462. // can't show as a list if no values to select from
  2463. delete param.isList;
  2464. delete param.allowMultiple;
  2465. }
  2466. }
  2467. param.signature = this.getModelSignature(innerType, this.models).toString();
  2468. param.sampleJSON = this.getModelSampleJSON(innerType, this.models);
  2469. param.responseClassSignature = param.signature;
  2470. }
  2471. var defaultResponseCode, response, responses = this.responses;
  2472. if (responses['200']) {
  2473. response = responses['200'];
  2474. defaultResponseCode = '200';
  2475. } else if (responses['201']) {
  2476. response = responses['201'];
  2477. defaultResponseCode = '201';
  2478. } else if (responses['202']) {
  2479. response = responses['202'];
  2480. defaultResponseCode = '202';
  2481. } else if (responses['203']) {
  2482. response = responses['203'];
  2483. defaultResponseCode = '203';
  2484. } else if (responses['204']) {
  2485. response = responses['204'];
  2486. defaultResponseCode = '204';
  2487. } else if (responses['205']) {
  2488. response = responses['205'];
  2489. defaultResponseCode = '205';
  2490. } else if (responses['206']) {
  2491. response = responses['206'];
  2492. defaultResponseCode = '206';
  2493. } else if (responses['default']) {
  2494. response = responses['default'];
  2495. defaultResponseCode = 'default';
  2496. }
  2497. if (response && response.schema) {
  2498. var resolvedModel = this.resolveModel(response.schema, definitions);
  2499. delete responses[defaultResponseCode];
  2500. if (resolvedModel) {
  2501. this.successResponse = {};
  2502. this.successResponse[defaultResponseCode] = resolvedModel;
  2503. } else {
  2504. this.successResponse = {};
  2505. this.successResponse[defaultResponseCode] = response.schema.type;
  2506. }
  2507. this.type = response;
  2508. }
  2509. if (errors.length > 0) {
  2510. if (this.resource && this.resource.api && this.resource.api.fail) {
  2511. this.resource.api.fail(errors);
  2512. }
  2513. }
  2514. return this;
  2515. };
  2516. Operation.prototype.getType = function (param) {
  2517. var type = param.type;
  2518. var format = param.format;
  2519. var isArray = false;
  2520. var str;
  2521. if (type === 'integer' && format === 'int32') {
  2522. str = 'integer';
  2523. } else if (type === 'integer' && format === 'int64') {
  2524. str = 'long';
  2525. } else if (type === 'integer') {
  2526. str = 'integer';
  2527. } else if (type === 'string') {
  2528. if (format === 'date-time') {
  2529. str = 'date-time';
  2530. } else if (format === 'date') {
  2531. str = 'date';
  2532. } else {
  2533. str = 'string';
  2534. }
  2535. } else if (type === 'number' && format === 'float') {
  2536. str = 'float';
  2537. } else if (type === 'number' && format === 'double') {
  2538. str = 'double';
  2539. } else if (type === 'number') {
  2540. str = 'double';
  2541. } else if (type === 'boolean') {
  2542. str = 'boolean';
  2543. } else if (type === 'array') {
  2544. isArray = true;
  2545. if (param.items) {
  2546. str = this.getType(param.items);
  2547. }
  2548. }
  2549. if (param.$ref) {
  2550. str = param.$ref;
  2551. }
  2552. var schema = param.schema;
  2553. if (schema) {
  2554. var ref = schema.$ref;
  2555. if (ref) {
  2556. ref = helpers.simpleRef(ref);
  2557. if (isArray) {
  2558. return [ ref ];
  2559. } else {
  2560. return ref;
  2561. }
  2562. } else {
  2563. return this.getType(schema);
  2564. }
  2565. }
  2566. if (isArray) {
  2567. return [ str ];
  2568. } else {
  2569. return str;
  2570. }
  2571. };
  2572. Operation.prototype.resolveModel = function (schema, definitions) {
  2573. if (typeof schema.$ref !== 'undefined') {
  2574. var ref = schema.$ref;
  2575. if (ref.indexOf('#/definitions/') === 0) {
  2576. ref = ref.substring('#/definitions/'.length);
  2577. }
  2578. if (definitions[ref]) {
  2579. return new Model(ref, definitions[ref], this.models);
  2580. }
  2581. }
  2582. if (schema.type === 'array') {
  2583. return new ArrayModel(schema, this.models);
  2584. } else {
  2585. return null;
  2586. }
  2587. };
  2588. Operation.prototype.help = function (dontPrint) {
  2589. var out = this.nickname + ': ' + this.summary + '\n';
  2590. for (var i = 0; i < this.parameters.length; i++) {
  2591. var param = this.parameters[i];
  2592. var typeInfo = param.signature;
  2593. out += '\n * ' + param.name + ' (' + typeInfo + '): ' + param.description;
  2594. }
  2595. if (typeof dontPrint === 'undefined') {
  2596. helpers.log(out);
  2597. }
  2598. return out;
  2599. };
  2600. Operation.prototype.getModelSignature = function (type, definitions) {
  2601. var isPrimitive, listType;
  2602. if (type instanceof Array) {
  2603. listType = true;
  2604. type = type[0];
  2605. } else if (typeof type === 'undefined') {
  2606. type = 'undefined';
  2607. }
  2608. if (type === 'string') {
  2609. isPrimitive = true;
  2610. } else {
  2611. isPrimitive = (listType && definitions[listType]) || (definitions[type]) ? false : true;
  2612. }
  2613. if (isPrimitive) {
  2614. if (listType) {
  2615. return 'Array[' + type + ']';
  2616. } else {
  2617. return type.toString();
  2618. }
  2619. } else {
  2620. if (listType) {
  2621. return 'Array[' + definitions[type].getMockSignature() + ']';
  2622. } else {
  2623. return definitions[type].getMockSignature();
  2624. }
  2625. }
  2626. };
  2627. Operation.prototype.supportHeaderParams = function () {
  2628. return true;
  2629. };
  2630. Operation.prototype.supportedSubmitMethods = function () {
  2631. return this.parent.supportedSubmitMethods;
  2632. };
  2633. Operation.prototype.getHeaderParams = function (args) {
  2634. var headers = this.setContentTypes(args, {});
  2635. for (var i = 0; i < this.parameters.length; i++) {
  2636. var param = this.parameters[i];
  2637. if (typeof args[param.name] !== 'undefined') {
  2638. if (param.in === 'header') {
  2639. var value = args[param.name];
  2640. if (Array.isArray(value)) {
  2641. value = value.toString();
  2642. }
  2643. headers[param.name] = value;
  2644. }
  2645. }
  2646. }
  2647. return headers;
  2648. };
  2649. Operation.prototype.urlify = function (args) {
  2650. var formParams = {};
  2651. var requestUrl = this.path;
  2652. var querystring = ''; // grab params from the args, build the querystring along the way
  2653. for (var i = 0; i < this.parameters.length; i++) {
  2654. var param = this.parameters[i];
  2655. if (typeof args[param.name] !== 'undefined') {
  2656. if (param.in === 'path') {
  2657. var reg = new RegExp('\{' + param.name + '\}', 'gi');
  2658. var value = args[param.name];
  2659. if (Array.isArray(value)) {
  2660. value = this.encodePathCollection(param.collectionFormat, param.name, value);
  2661. } else {
  2662. value = this.encodePathParam(value);
  2663. }
  2664. requestUrl = requestUrl.replace(reg, value);
  2665. } else if (param.in === 'query' && typeof args[param.name] !== 'undefined') {
  2666. if (querystring === '') {
  2667. querystring += '?';
  2668. } else {
  2669. querystring += '&';
  2670. }
  2671. if (typeof param.collectionFormat !== 'undefined') {
  2672. var qp = args[param.name];
  2673. if (Array.isArray(qp)) {
  2674. querystring += this.encodeQueryCollection(param.collectionFormat, param.name, qp);
  2675. } else {
  2676. querystring += this.encodeQueryParam(param.name) + '=' + this.encodeQueryParam(args[param.name]);
  2677. }
  2678. } else {
  2679. querystring += this.encodeQueryParam(param.name) + '=' + this.encodeQueryParam(args[param.name]);
  2680. }
  2681. } else if (param.in === 'formData') {
  2682. formParams[param.name] = args[param.name];
  2683. }
  2684. }
  2685. }
  2686. var url = this.scheme + '://' + this.host;
  2687. if (this.basePath !== '/') {
  2688. url += this.basePath;
  2689. }
  2690. return url + requestUrl + querystring;
  2691. };
  2692. Operation.prototype.getMissingParams = function (args) {
  2693. var missingParams = []; // check required params, track the ones that are missing
  2694. var i;
  2695. for (i = 0; i < this.parameters.length; i++) {
  2696. var param = this.parameters[i];
  2697. if (param.required === true) {
  2698. if (typeof args[param.name] === 'undefined') {
  2699. missingParams = param.name;
  2700. }
  2701. }
  2702. }
  2703. return missingParams;
  2704. };
  2705. Operation.prototype.getBody = function (headers, args, opts) {
  2706. var formParams = {}, body, key, value;
  2707. for (var i = 0; i < this.parameters.length; i++) {
  2708. var param = this.parameters[i];
  2709. if (typeof args[param.name] !== 'undefined') {
  2710. if (param.in === 'body') {
  2711. body = args[param.name];
  2712. } else if (param.in === 'formData') {
  2713. formParams[param.name] = args[param.name];
  2714. }
  2715. }
  2716. }
  2717. // handle form params
  2718. if (headers['Content-Type'] === 'application/x-www-form-urlencoded') {
  2719. var encoded = '';
  2720. for (key in formParams) {
  2721. value = formParams[key];
  2722. if (typeof value !== 'undefined') {
  2723. if (encoded !== '') {
  2724. encoded += '&';
  2725. }
  2726. encoded += encodeURIComponent(key) + '=' + encodeURIComponent(value);
  2727. }
  2728. }
  2729. body = encoded;
  2730. } else if (headers['Content-Type'] && headers['Content-Type'].indexOf('multipart/form-data') >= 0) {
  2731. if (opts.useJQuery) {
  2732. var bodyParam = new FormData();
  2733. bodyParam.type = 'formData';
  2734. for (key in formParams) {
  2735. value = args[key];
  2736. if (typeof value !== 'undefined') {
  2737. // required for jquery file upload
  2738. if (value.type === 'file' && value.value) {
  2739. delete headers['Content-Type'];
  2740. bodyParam.append(key, value.value);
  2741. } else {
  2742. bodyParam.append(key, value);
  2743. }
  2744. }
  2745. }
  2746. body = bodyParam;
  2747. }
  2748. }
  2749. return body;
  2750. };
  2751. /**
  2752. * gets sample response for a single operation
  2753. **/
  2754. Operation.prototype.getModelSampleJSON = function (type, models) {
  2755. var isPrimitive, listType, sampleJson;
  2756. listType = (type instanceof Array);
  2757. isPrimitive = models[type] ? false : true;
  2758. sampleJson = isPrimitive ? void 0 : models[type].createJSONSample();
  2759. if (sampleJson) {
  2760. sampleJson = listType ? [sampleJson] : sampleJson;
  2761. if (typeof sampleJson === 'string') {
  2762. return sampleJson;
  2763. } else if (typeof sampleJson === 'object') {
  2764. var t = sampleJson;
  2765. if (sampleJson instanceof Array && sampleJson.length > 0) {
  2766. t = sampleJson[0];
  2767. }
  2768. if (t.nodeName) {
  2769. var xmlString = new XMLSerializer().serializeToString(t);
  2770. return this.formatXml(xmlString);
  2771. } else {
  2772. return JSON.stringify(sampleJson, null, 2);
  2773. }
  2774. } else {
  2775. return sampleJson;
  2776. }
  2777. }
  2778. };
  2779. /**
  2780. * legacy binding
  2781. **/
  2782. Operation.prototype.do = function (args, opts, callback, error, parent) {
  2783. return this.execute(args, opts, callback, error, parent);
  2784. };
  2785. /**
  2786. * executes an operation
  2787. **/
  2788. Operation.prototype.execute = function (arg1, arg2, arg3, arg4, parent) {
  2789. var args = arg1 || {};
  2790. var opts = {}, success, error;
  2791. if (typeof arg2 === 'object') {
  2792. opts = arg2;
  2793. success = arg3;
  2794. error = arg4;
  2795. }
  2796. if (typeof arg2 === 'function') {
  2797. success = arg2;
  2798. error = arg3;
  2799. }
  2800. success = (success || helpers.log);
  2801. error = (error || helpers.log);
  2802. if (opts.useJQuery) {
  2803. this.useJQuery = opts.useJQuery;
  2804. }
  2805. var missingParams = this.getMissingParams(args);
  2806. if (missingParams.length > 0) {
  2807. var message = 'missing required params: ' + missingParams;
  2808. helpers.fail(message);
  2809. return;
  2810. }
  2811. var allHeaders = this.getHeaderParams(args);
  2812. var contentTypeHeaders = this.setContentTypes(args, opts);
  2813. var headers = {}, attrname;
  2814. for (attrname in allHeaders) { headers[attrname] = allHeaders[attrname]; }
  2815. for (attrname in contentTypeHeaders) { headers[attrname] = contentTypeHeaders[attrname]; }
  2816. var body = this.getBody(headers, args, opts);
  2817. var url = this.urlify(args);
  2818. var obj = {
  2819. url: url,
  2820. method: this.method.toUpperCase(),
  2821. body: body,
  2822. useJQuery: this.useJQuery,
  2823. headers: headers,
  2824. on: {
  2825. response: function (response) {
  2826. return success(response, parent);
  2827. },
  2828. error: function (response) {
  2829. return error(response, parent);
  2830. }
  2831. }
  2832. };
  2833. this.clientAuthorizations.apply(obj, this.operation.security);
  2834. if (opts.mock === true) {
  2835. return obj;
  2836. } else {
  2837. new SwaggerHttp().execute(obj, opts);
  2838. }
  2839. };
  2840. Operation.prototype.setContentTypes = function (args, opts) {
  2841. // default type
  2842. var accepts = 'application/json';
  2843. var allDefinedParams = this.parameters;
  2844. var body;
  2845. var consumes = args.parameterContentType || 'application/json';
  2846. var definedFileParams = [];
  2847. var definedFormParams = [];
  2848. var headers = {};
  2849. var i;
  2850. // get params from the operation and set them in definedFileParams, definedFormParams, headers
  2851. for (i = 0; i < allDefinedParams.length; i++) {
  2852. var param = allDefinedParams[i];
  2853. if (param.in === 'formData') {
  2854. if (param.type === 'file') {
  2855. definedFileParams.push(param);
  2856. } else {
  2857. definedFormParams.push(param);
  2858. }
  2859. } else if (param.in === 'header' && opts) {
  2860. var key = param.name;
  2861. var headerValue = opts[param.name];
  2862. if (typeof opts[param.name] !== 'undefined') {
  2863. headers[key] = headerValue;
  2864. }
  2865. } else if (param.in === 'body' && typeof args[param.name] !== 'undefined') {
  2866. body = args[param.name];
  2867. }
  2868. }
  2869. // if there's a body, need to set the consumes header via requestContentType
  2870. if (body && (this.method === 'post' || this.method === 'put' || this.method === 'patch' || this.method === 'delete')) {
  2871. if (opts.requestContentType) {
  2872. consumes = opts.requestContentType;
  2873. }
  2874. } else {
  2875. // if any form params, content type must be set
  2876. if (definedFormParams.length > 0) {
  2877. if (opts.requestContentType) { // override if set
  2878. consumes = opts.requestContentType;
  2879. } else if (definedFileParams.length > 0) { // if a file, must be multipart/form-data
  2880. consumes = 'multipart/form-data';
  2881. } else { // default to x-www-from-urlencoded
  2882. consumes = 'application/x-www-form-urlencoded';
  2883. }
  2884. } else if (this.type === 'DELETE') {
  2885. body = '{}';
  2886. } else if (this.type !== 'DELETE') {
  2887. consumes = null;
  2888. }
  2889. }
  2890. if (consumes && this.consumes) {
  2891. if (this.consumes.indexOf(consumes) === -1) {
  2892. helpers.log('server doesn\'t consume ' + consumes + ', try ' + JSON.stringify(this.consumes));
  2893. }
  2894. }
  2895. if (opts.responseContentType) {
  2896. accepts = opts.responseContentType;
  2897. } else {
  2898. accepts = 'application/json';
  2899. }
  2900. if (accepts && this.produces) {
  2901. if (this.produces.indexOf(accepts) === -1) {
  2902. helpers.log('server can\'t produce ' + accepts);
  2903. }
  2904. }
  2905. if ((consumes && body !== '') || (consumes === 'application/x-www-form-urlencoded')) {
  2906. headers['Content-Type'] = consumes;
  2907. }
  2908. if (accepts) {
  2909. headers.Accept = accepts;
  2910. }
  2911. return headers;
  2912. };
  2913. Operation.prototype.asCurl = function (args) {
  2914. var obj = this.execute(args, {mock: true});
  2915. this.clientAuthorizations.apply(obj);
  2916. var results = [];
  2917. results.push('-X ' + this.method.toUpperCase());
  2918. if (obj.headers) {
  2919. var key;
  2920. for (key in obj.headers) {
  2921. results.push('--header "' + key + ': ' + obj.headers[key] + '"');
  2922. }
  2923. }
  2924. if (obj.body) {
  2925. var body;
  2926. if (typeof obj.body === 'object') {
  2927. body = JSON.stringify(obj.body);
  2928. } else {
  2929. body = obj.body;
  2930. }
  2931. results.push('-d "' + body.replace(/"/g, '\\"') + '"');
  2932. }
  2933. return 'curl ' + (results.join(' ')) + ' "' + obj.url + '"';
  2934. };
  2935. Operation.prototype.encodePathCollection = function (type, name, value) {
  2936. var encoded = '';
  2937. var i;
  2938. var separator = '';
  2939. if (type === 'ssv') {
  2940. separator = '%20';
  2941. } else if (type === 'tsv') {
  2942. separator = '\\t';
  2943. } else if (type === 'pipes') {
  2944. separator = '|';
  2945. } else {
  2946. separator = ',';
  2947. }
  2948. for (i = 0; i < value.length; i++) {
  2949. if (i === 0) {
  2950. encoded = this.encodeQueryParam(value[i]);
  2951. } else {
  2952. encoded += separator + this.encodeQueryParam(value[i]);
  2953. }
  2954. }
  2955. return encoded;
  2956. };
  2957. Operation.prototype.encodeQueryCollection = function (type, name, value) {
  2958. var encoded = '';
  2959. var i;
  2960. if (type === 'default' || type === 'multi') {
  2961. for (i = 0; i < value.length; i++) {
  2962. if (i > 0) {encoded += '&';}
  2963. encoded += this.encodeQueryParam(name) + '=' + this.encodeQueryParam(value[i]);
  2964. }
  2965. } else {
  2966. var separator = '';
  2967. if (type === 'csv') {
  2968. separator = ',';
  2969. } else if (type === 'ssv') {
  2970. separator = '%20';
  2971. } else if (type === 'tsv') {
  2972. separator = '\\t';
  2973. } else if (type === 'pipes') {
  2974. separator = '|';
  2975. } else if (type === 'brackets') {
  2976. for (i = 0; i < value.length; i++) {
  2977. if (i !== 0) {
  2978. encoded += '&';
  2979. }
  2980. encoded += this.encodeQueryParam(name) + '[]=' + this.encodeQueryParam(value[i]);
  2981. }
  2982. }
  2983. if (separator !== '') {
  2984. for (i = 0; i < value.length; i++) {
  2985. if (i === 0) {
  2986. encoded = this.encodeQueryParam(name) + '=' + this.encodeQueryParam(value[i]);
  2987. } else {
  2988. encoded += separator + this.encodeQueryParam(value[i]);
  2989. }
  2990. }
  2991. }
  2992. }
  2993. return encoded;
  2994. };
  2995. Operation.prototype.encodeQueryParam = function (arg) {
  2996. return encodeURIComponent(arg);
  2997. };
  2998. /**
  2999. * TODO revisit, might not want to leave '/'
  3000. **/
  3001. Operation.prototype.encodePathParam = function (pathParam) {
  3002. var encParts, parts, i, len;
  3003. pathParam = pathParam.toString();
  3004. if (pathParam.indexOf('/') === -1) {
  3005. return encodeURIComponent(pathParam);
  3006. } else {
  3007. parts = pathParam.split('/');
  3008. encParts = [];
  3009. for (i = 0, len = parts.length; i < len; i++) {
  3010. encParts.push(encodeURIComponent(parts[i]));
  3011. }
  3012. return encParts.join('/');
  3013. }
  3014. };
  3015. },{"../helpers":5,"../http":6,"./arrayModel":8,"./model":9}],11:[function(require,module,exports){
  3016. 'use strict';
  3017. var OperationGroup = module.exports = function (tag, description, externalDocs, operation) {
  3018. this.tag = tag;
  3019. this.path = tag;
  3020. this.description = description;
  3021. this.externalDocs = externalDocs;
  3022. this.name = tag;
  3023. this.operation = operation;
  3024. this.operationsArray = [];
  3025. };
  3026. OperationGroup.prototype.sort = function () {
  3027. };
  3028. },{}],12:[function(require,module,exports){
  3029. /*!
  3030. * The buffer module from node.js, for the browser.
  3031. *
  3032. * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
  3033. * @license MIT
  3034. */
  3035. var base64 = require('base64-js')
  3036. var ieee754 = require('ieee754')
  3037. var isArray = require('is-array')
  3038. exports.Buffer = Buffer
  3039. exports.SlowBuffer = SlowBuffer
  3040. exports.INSPECT_MAX_BYTES = 50
  3041. Buffer.poolSize = 8192 // not used by this implementation
  3042. var kMaxLength = 0x3fffffff
  3043. var rootParent = {}
  3044. /**
  3045. * If `Buffer.TYPED_ARRAY_SUPPORT`:
  3046. * === true Use Uint8Array implementation (fastest)
  3047. * === false Use Object implementation (most compatible, even IE6)
  3048. *
  3049. * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
  3050. * Opera 11.6+, iOS 4.2+.
  3051. *
  3052. * Note:
  3053. *
  3054. * - Implementation must support adding new properties to `Uint8Array` instances.
  3055. * Firefox 4-29 lacked support, fixed in Firefox 30+.
  3056. * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
  3057. *
  3058. * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
  3059. *
  3060. * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
  3061. * incorrect length in some situations.
  3062. *
  3063. * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will
  3064. * get the Object implementation, which is slower but will work correctly.
  3065. */
  3066. Buffer.TYPED_ARRAY_SUPPORT = (function () {
  3067. try {
  3068. var buf = new ArrayBuffer(0)
  3069. var arr = new Uint8Array(buf)
  3070. arr.foo = function () { return 42 }
  3071. return arr.foo() === 42 && // typed array instances can be augmented
  3072. typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
  3073. new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
  3074. } catch (e) {
  3075. return false
  3076. }
  3077. })()
  3078. /**
  3079. * Class: Buffer
  3080. * =============
  3081. *
  3082. * The Buffer constructor returns instances of `Uint8Array` that are augmented
  3083. * with function properties for all the node `Buffer` API functions. We use
  3084. * `Uint8Array` so that square bracket notation works as expected -- it returns
  3085. * a single octet.
  3086. *
  3087. * By augmenting the instances, we can avoid modifying the `Uint8Array`
  3088. * prototype.
  3089. */
  3090. function Buffer (subject, encoding, noZero) {
  3091. if (!(this instanceof Buffer))
  3092. return new Buffer(subject, encoding, noZero)
  3093. var type = typeof subject
  3094. // Find the length
  3095. var length
  3096. if (type === 'number') {
  3097. length = +subject
  3098. } else if (type === 'string') {
  3099. length = Buffer.byteLength(subject, encoding)
  3100. } else if (type === 'object' && subject !== null) { // assume object is array-like
  3101. if (subject.type === 'Buffer' && isArray(subject.data))
  3102. subject = subject.data
  3103. length = +subject.length
  3104. } else {
  3105. throw new TypeError('must start with number, buffer, array or string')
  3106. }
  3107. if (length > kMaxLength)
  3108. throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
  3109. 'size: 0x' + kMaxLength.toString(16) + ' bytes')
  3110. if (length < 0)
  3111. length = 0
  3112. else
  3113. length >>>= 0 // Coerce to uint32.
  3114. var self = this
  3115. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3116. // Preferred: Return an augmented `Uint8Array` instance for best performance
  3117. /*eslint-disable consistent-this */
  3118. self = Buffer._augment(new Uint8Array(length))
  3119. /*eslint-enable consistent-this */
  3120. } else {
  3121. // Fallback: Return THIS instance of Buffer (created by `new`)
  3122. self.length = length
  3123. self._isBuffer = true
  3124. }
  3125. var i
  3126. if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') {
  3127. // Speed optimization -- use set if we're copying from a typed array
  3128. self._set(subject)
  3129. } else if (isArrayish(subject)) {
  3130. // Treat array-ish objects as a byte array
  3131. if (Buffer.isBuffer(subject)) {
  3132. for (i = 0; i < length; i++)
  3133. self[i] = subject.readUInt8(i)
  3134. } else {
  3135. for (i = 0; i < length; i++)
  3136. self[i] = ((subject[i] % 256) + 256) % 256
  3137. }
  3138. } else if (type === 'string') {
  3139. self.write(subject, 0, encoding)
  3140. } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) {
  3141. for (i = 0; i < length; i++) {
  3142. self[i] = 0
  3143. }
  3144. }
  3145. if (length > 0 && length <= Buffer.poolSize)
  3146. self.parent = rootParent
  3147. return self
  3148. }
  3149. function SlowBuffer (subject, encoding, noZero) {
  3150. if (!(this instanceof SlowBuffer))
  3151. return new SlowBuffer(subject, encoding, noZero)
  3152. var buf = new Buffer(subject, encoding, noZero)
  3153. delete buf.parent
  3154. return buf
  3155. }
  3156. Buffer.isBuffer = function (b) {
  3157. return !!(b != null && b._isBuffer)
  3158. }
  3159. Buffer.compare = function (a, b) {
  3160. if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b))
  3161. throw new TypeError('Arguments must be Buffers')
  3162. if (a === b) return 0
  3163. var x = a.length
  3164. var y = b.length
  3165. for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {}
  3166. if (i !== len) {
  3167. x = a[i]
  3168. y = b[i]
  3169. }
  3170. if (x < y) return -1
  3171. if (y < x) return 1
  3172. return 0
  3173. }
  3174. Buffer.isEncoding = function (encoding) {
  3175. switch (String(encoding).toLowerCase()) {
  3176. case 'hex':
  3177. case 'utf8':
  3178. case 'utf-8':
  3179. case 'ascii':
  3180. case 'binary':
  3181. case 'base64':
  3182. case 'raw':
  3183. case 'ucs2':
  3184. case 'ucs-2':
  3185. case 'utf16le':
  3186. case 'utf-16le':
  3187. return true
  3188. default:
  3189. return false
  3190. }
  3191. }
  3192. Buffer.concat = function (list, totalLength) {
  3193. if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])')
  3194. if (list.length === 0) {
  3195. return new Buffer(0)
  3196. } else if (list.length === 1) {
  3197. return list[0]
  3198. }
  3199. var i
  3200. if (totalLength === undefined) {
  3201. totalLength = 0
  3202. for (i = 0; i < list.length; i++) {
  3203. totalLength += list[i].length
  3204. }
  3205. }
  3206. var buf = new Buffer(totalLength)
  3207. var pos = 0
  3208. for (i = 0; i < list.length; i++) {
  3209. var item = list[i]
  3210. item.copy(buf, pos)
  3211. pos += item.length
  3212. }
  3213. return buf
  3214. }
  3215. Buffer.byteLength = function (str, encoding) {
  3216. var ret
  3217. str = str + ''
  3218. switch (encoding || 'utf8') {
  3219. case 'ascii':
  3220. case 'binary':
  3221. case 'raw':
  3222. ret = str.length
  3223. break
  3224. case 'ucs2':
  3225. case 'ucs-2':
  3226. case 'utf16le':
  3227. case 'utf-16le':
  3228. ret = str.length * 2
  3229. break
  3230. case 'hex':
  3231. ret = str.length >>> 1
  3232. break
  3233. case 'utf8':
  3234. case 'utf-8':
  3235. ret = utf8ToBytes(str).length
  3236. break
  3237. case 'base64':
  3238. ret = base64ToBytes(str).length
  3239. break
  3240. default:
  3241. ret = str.length
  3242. }
  3243. return ret
  3244. }
  3245. // pre-set for values that may exist in the future
  3246. Buffer.prototype.length = undefined
  3247. Buffer.prototype.parent = undefined
  3248. // toString(encoding, start=0, end=buffer.length)
  3249. Buffer.prototype.toString = function (encoding, start, end) {
  3250. var loweredCase = false
  3251. start = start >>> 0
  3252. end = end === undefined || end === Infinity ? this.length : end >>> 0
  3253. if (!encoding) encoding = 'utf8'
  3254. if (start < 0) start = 0
  3255. if (end > this.length) end = this.length
  3256. if (end <= start) return ''
  3257. while (true) {
  3258. switch (encoding) {
  3259. case 'hex':
  3260. return hexSlice(this, start, end)
  3261. case 'utf8':
  3262. case 'utf-8':
  3263. return utf8Slice(this, start, end)
  3264. case 'ascii':
  3265. return asciiSlice(this, start, end)
  3266. case 'binary':
  3267. return binarySlice(this, start, end)
  3268. case 'base64':
  3269. return base64Slice(this, start, end)
  3270. case 'ucs2':
  3271. case 'ucs-2':
  3272. case 'utf16le':
  3273. case 'utf-16le':
  3274. return utf16leSlice(this, start, end)
  3275. default:
  3276. if (loweredCase)
  3277. throw new TypeError('Unknown encoding: ' + encoding)
  3278. encoding = (encoding + '').toLowerCase()
  3279. loweredCase = true
  3280. }
  3281. }
  3282. }
  3283. Buffer.prototype.equals = function (b) {
  3284. if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
  3285. if (this === b) return true
  3286. return Buffer.compare(this, b) === 0
  3287. }
  3288. Buffer.prototype.inspect = function () {
  3289. var str = ''
  3290. var max = exports.INSPECT_MAX_BYTES
  3291. if (this.length > 0) {
  3292. str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
  3293. if (this.length > max)
  3294. str += ' ... '
  3295. }
  3296. return '<Buffer ' + str + '>'
  3297. }
  3298. Buffer.prototype.compare = function (b) {
  3299. if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
  3300. if (this === b) return 0
  3301. return Buffer.compare(this, b)
  3302. }
  3303. // `get` will be removed in Node 0.13+
  3304. Buffer.prototype.get = function (offset) {
  3305. console.log('.get() is deprecated. Access using array indexes instead.')
  3306. return this.readUInt8(offset)
  3307. }
  3308. // `set` will be removed in Node 0.13+
  3309. Buffer.prototype.set = function (v, offset) {
  3310. console.log('.set() is deprecated. Access using array indexes instead.')
  3311. return this.writeUInt8(v, offset)
  3312. }
  3313. function hexWrite (buf, string, offset, length) {
  3314. offset = Number(offset) || 0
  3315. var remaining = buf.length - offset
  3316. if (!length) {
  3317. length = remaining
  3318. } else {
  3319. length = Number(length)
  3320. if (length > remaining) {
  3321. length = remaining
  3322. }
  3323. }
  3324. // must be an even number of digits
  3325. var strLen = string.length
  3326. if (strLen % 2 !== 0) throw new Error('Invalid hex string')
  3327. if (length > strLen / 2) {
  3328. length = strLen / 2
  3329. }
  3330. for (var i = 0; i < length; i++) {
  3331. var byte = parseInt(string.substr(i * 2, 2), 16)
  3332. if (isNaN(byte)) throw new Error('Invalid hex string')
  3333. buf[offset + i] = byte
  3334. }
  3335. return i
  3336. }
  3337. function utf8Write (buf, string, offset, length) {
  3338. var charsWritten = blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
  3339. return charsWritten
  3340. }
  3341. function asciiWrite (buf, string, offset, length) {
  3342. var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length)
  3343. return charsWritten
  3344. }
  3345. function binaryWrite (buf, string, offset, length) {
  3346. return asciiWrite(buf, string, offset, length)
  3347. }
  3348. function base64Write (buf, string, offset, length) {
  3349. var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length)
  3350. return charsWritten
  3351. }
  3352. function utf16leWrite (buf, string, offset, length) {
  3353. var charsWritten = blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
  3354. return charsWritten
  3355. }
  3356. Buffer.prototype.write = function (string, offset, length, encoding) {
  3357. // Support both (string, offset, length, encoding)
  3358. // and the legacy (string, encoding, offset, length)
  3359. if (isFinite(offset)) {
  3360. if (!isFinite(length)) {
  3361. encoding = length
  3362. length = undefined
  3363. }
  3364. } else { // legacy
  3365. var swap = encoding
  3366. encoding = offset
  3367. offset = length
  3368. length = swap
  3369. }
  3370. offset = Number(offset) || 0
  3371. if (length < 0 || offset < 0 || offset > this.length)
  3372. throw new RangeError('attempt to write outside buffer bounds')
  3373. var remaining = this.length - offset
  3374. if (!length) {
  3375. length = remaining
  3376. } else {
  3377. length = Number(length)
  3378. if (length > remaining) {
  3379. length = remaining
  3380. }
  3381. }
  3382. encoding = String(encoding || 'utf8').toLowerCase()
  3383. var ret
  3384. switch (encoding) {
  3385. case 'hex':
  3386. ret = hexWrite(this, string, offset, length)
  3387. break
  3388. case 'utf8':
  3389. case 'utf-8':
  3390. ret = utf8Write(this, string, offset, length)
  3391. break
  3392. case 'ascii':
  3393. ret = asciiWrite(this, string, offset, length)
  3394. break
  3395. case 'binary':
  3396. ret = binaryWrite(this, string, offset, length)
  3397. break
  3398. case 'base64':
  3399. ret = base64Write(this, string, offset, length)
  3400. break
  3401. case 'ucs2':
  3402. case 'ucs-2':
  3403. case 'utf16le':
  3404. case 'utf-16le':
  3405. ret = utf16leWrite(this, string, offset, length)
  3406. break
  3407. default:
  3408. throw new TypeError('Unknown encoding: ' + encoding)
  3409. }
  3410. return ret
  3411. }
  3412. Buffer.prototype.toJSON = function () {
  3413. return {
  3414. type: 'Buffer',
  3415. data: Array.prototype.slice.call(this._arr || this, 0)
  3416. }
  3417. }
  3418. function base64Slice (buf, start, end) {
  3419. if (start === 0 && end === buf.length) {
  3420. return base64.fromByteArray(buf)
  3421. } else {
  3422. return base64.fromByteArray(buf.slice(start, end))
  3423. }
  3424. }
  3425. function utf8Slice (buf, start, end) {
  3426. var res = ''
  3427. var tmp = ''
  3428. end = Math.min(buf.length, end)
  3429. for (var i = start; i < end; i++) {
  3430. if (buf[i] <= 0x7F) {
  3431. res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
  3432. tmp = ''
  3433. } else {
  3434. tmp += '%' + buf[i].toString(16)
  3435. }
  3436. }
  3437. return res + decodeUtf8Char(tmp)
  3438. }
  3439. function asciiSlice (buf, start, end) {
  3440. var ret = ''
  3441. end = Math.min(buf.length, end)
  3442. for (var i = start; i < end; i++) {
  3443. ret += String.fromCharCode(buf[i] & 0x7F)
  3444. }
  3445. return ret
  3446. }
  3447. function binarySlice (buf, start, end) {
  3448. var ret = ''
  3449. end = Math.min(buf.length, end)
  3450. for (var i = start; i < end; i++) {
  3451. ret += String.fromCharCode(buf[i])
  3452. }
  3453. return ret
  3454. }
  3455. function hexSlice (buf, start, end) {
  3456. var len = buf.length
  3457. if (!start || start < 0) start = 0
  3458. if (!end || end < 0 || end > len) end = len
  3459. var out = ''
  3460. for (var i = start; i < end; i++) {
  3461. out += toHex(buf[i])
  3462. }
  3463. return out
  3464. }
  3465. function utf16leSlice (buf, start, end) {
  3466. var bytes = buf.slice(start, end)
  3467. var res = ''
  3468. for (var i = 0; i < bytes.length; i += 2) {
  3469. res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
  3470. }
  3471. return res
  3472. }
  3473. Buffer.prototype.slice = function (start, end) {
  3474. var len = this.length
  3475. start = ~~start
  3476. end = end === undefined ? len : ~~end
  3477. if (start < 0) {
  3478. start += len
  3479. if (start < 0)
  3480. start = 0
  3481. } else if (start > len) {
  3482. start = len
  3483. }
  3484. if (end < 0) {
  3485. end += len
  3486. if (end < 0)
  3487. end = 0
  3488. } else if (end > len) {
  3489. end = len
  3490. }
  3491. if (end < start)
  3492. end = start
  3493. var newBuf
  3494. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3495. newBuf = Buffer._augment(this.subarray(start, end))
  3496. } else {
  3497. var sliceLen = end - start
  3498. newBuf = new Buffer(sliceLen, undefined, true)
  3499. for (var i = 0; i < sliceLen; i++) {
  3500. newBuf[i] = this[i + start]
  3501. }
  3502. }
  3503. if (newBuf.length)
  3504. newBuf.parent = this.parent || this
  3505. return newBuf
  3506. }
  3507. /*
  3508. * Need to make sure that buffer isn't trying to write out of bounds.
  3509. */
  3510. function checkOffset (offset, ext, length) {
  3511. if ((offset % 1) !== 0 || offset < 0)
  3512. throw new RangeError('offset is not uint')
  3513. if (offset + ext > length)
  3514. throw new RangeError('Trying to access beyond buffer length')
  3515. }
  3516. Buffer.prototype.readUIntLE = function (offset, byteLength, noAssert) {
  3517. offset = offset >>> 0
  3518. byteLength = byteLength >>> 0
  3519. if (!noAssert)
  3520. checkOffset(offset, byteLength, this.length)
  3521. var val = this[offset]
  3522. var mul = 1
  3523. var i = 0
  3524. while (++i < byteLength && (mul *= 0x100))
  3525. val += this[offset + i] * mul
  3526. return val
  3527. }
  3528. Buffer.prototype.readUIntBE = function (offset, byteLength, noAssert) {
  3529. offset = offset >>> 0
  3530. byteLength = byteLength >>> 0
  3531. if (!noAssert)
  3532. checkOffset(offset, byteLength, this.length)
  3533. var val = this[offset + --byteLength]
  3534. var mul = 1
  3535. while (byteLength > 0 && (mul *= 0x100))
  3536. val += this[offset + --byteLength] * mul
  3537. return val
  3538. }
  3539. Buffer.prototype.readUInt8 = function (offset, noAssert) {
  3540. if (!noAssert)
  3541. checkOffset(offset, 1, this.length)
  3542. return this[offset]
  3543. }
  3544. Buffer.prototype.readUInt16LE = function (offset, noAssert) {
  3545. if (!noAssert)
  3546. checkOffset(offset, 2, this.length)
  3547. return this[offset] | (this[offset + 1] << 8)
  3548. }
  3549. Buffer.prototype.readUInt16BE = function (offset, noAssert) {
  3550. if (!noAssert)
  3551. checkOffset(offset, 2, this.length)
  3552. return (this[offset] << 8) | this[offset + 1]
  3553. }
  3554. Buffer.prototype.readUInt32LE = function (offset, noAssert) {
  3555. if (!noAssert)
  3556. checkOffset(offset, 4, this.length)
  3557. return ((this[offset]) |
  3558. (this[offset + 1] << 8) |
  3559. (this[offset + 2] << 16)) +
  3560. (this[offset + 3] * 0x1000000)
  3561. }
  3562. Buffer.prototype.readUInt32BE = function (offset, noAssert) {
  3563. if (!noAssert)
  3564. checkOffset(offset, 4, this.length)
  3565. return (this[offset] * 0x1000000) +
  3566. ((this[offset + 1] << 16) |
  3567. (this[offset + 2] << 8) |
  3568. this[offset + 3])
  3569. }
  3570. Buffer.prototype.readIntLE = function (offset, byteLength, noAssert) {
  3571. offset = offset >>> 0
  3572. byteLength = byteLength >>> 0
  3573. if (!noAssert)
  3574. checkOffset(offset, byteLength, this.length)
  3575. var val = this[offset]
  3576. var mul = 1
  3577. var i = 0
  3578. while (++i < byteLength && (mul *= 0x100))
  3579. val += this[offset + i] * mul
  3580. mul *= 0x80
  3581. if (val >= mul)
  3582. val -= Math.pow(2, 8 * byteLength)
  3583. return val
  3584. }
  3585. Buffer.prototype.readIntBE = function (offset, byteLength, noAssert) {
  3586. offset = offset >>> 0
  3587. byteLength = byteLength >>> 0
  3588. if (!noAssert)
  3589. checkOffset(offset, byteLength, this.length)
  3590. var i = byteLength
  3591. var mul = 1
  3592. var val = this[offset + --i]
  3593. while (i > 0 && (mul *= 0x100))
  3594. val += this[offset + --i] * mul
  3595. mul *= 0x80
  3596. if (val >= mul)
  3597. val -= Math.pow(2, 8 * byteLength)
  3598. return val
  3599. }
  3600. Buffer.prototype.readInt8 = function (offset, noAssert) {
  3601. if (!noAssert)
  3602. checkOffset(offset, 1, this.length)
  3603. if (!(this[offset] & 0x80))
  3604. return (this[offset])
  3605. return ((0xff - this[offset] + 1) * -1)
  3606. }
  3607. Buffer.prototype.readInt16LE = function (offset, noAssert) {
  3608. if (!noAssert)
  3609. checkOffset(offset, 2, this.length)
  3610. var val = this[offset] | (this[offset + 1] << 8)
  3611. return (val & 0x8000) ? val | 0xFFFF0000 : val
  3612. }
  3613. Buffer.prototype.readInt16BE = function (offset, noAssert) {
  3614. if (!noAssert)
  3615. checkOffset(offset, 2, this.length)
  3616. var val = this[offset + 1] | (this[offset] << 8)
  3617. return (val & 0x8000) ? val | 0xFFFF0000 : val
  3618. }
  3619. Buffer.prototype.readInt32LE = function (offset, noAssert) {
  3620. if (!noAssert)
  3621. checkOffset(offset, 4, this.length)
  3622. return (this[offset]) |
  3623. (this[offset + 1] << 8) |
  3624. (this[offset + 2] << 16) |
  3625. (this[offset + 3] << 24)
  3626. }
  3627. Buffer.prototype.readInt32BE = function (offset, noAssert) {
  3628. if (!noAssert)
  3629. checkOffset(offset, 4, this.length)
  3630. return (this[offset] << 24) |
  3631. (this[offset + 1] << 16) |
  3632. (this[offset + 2] << 8) |
  3633. (this[offset + 3])
  3634. }
  3635. Buffer.prototype.readFloatLE = function (offset, noAssert) {
  3636. if (!noAssert)
  3637. checkOffset(offset, 4, this.length)
  3638. return ieee754.read(this, offset, true, 23, 4)
  3639. }
  3640. Buffer.prototype.readFloatBE = function (offset, noAssert) {
  3641. if (!noAssert)
  3642. checkOffset(offset, 4, this.length)
  3643. return ieee754.read(this, offset, false, 23, 4)
  3644. }
  3645. Buffer.prototype.readDoubleLE = function (offset, noAssert) {
  3646. if (!noAssert)
  3647. checkOffset(offset, 8, this.length)
  3648. return ieee754.read(this, offset, true, 52, 8)
  3649. }
  3650. Buffer.prototype.readDoubleBE = function (offset, noAssert) {
  3651. if (!noAssert)
  3652. checkOffset(offset, 8, this.length)
  3653. return ieee754.read(this, offset, false, 52, 8)
  3654. }
  3655. function checkInt (buf, value, offset, ext, max, min) {
  3656. if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
  3657. if (value > max || value < min) throw new RangeError('value is out of bounds')
  3658. if (offset + ext > buf.length) throw new RangeError('index out of range')
  3659. }
  3660. Buffer.prototype.writeUIntLE = function (value, offset, byteLength, noAssert) {
  3661. value = +value
  3662. offset = offset >>> 0
  3663. byteLength = byteLength >>> 0
  3664. if (!noAssert)
  3665. checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  3666. var mul = 1
  3667. var i = 0
  3668. this[offset] = value & 0xFF
  3669. while (++i < byteLength && (mul *= 0x100))
  3670. this[offset + i] = (value / mul) >>> 0 & 0xFF
  3671. return offset + byteLength
  3672. }
  3673. Buffer.prototype.writeUIntBE = function (value, offset, byteLength, noAssert) {
  3674. value = +value
  3675. offset = offset >>> 0
  3676. byteLength = byteLength >>> 0
  3677. if (!noAssert)
  3678. checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  3679. var i = byteLength - 1
  3680. var mul = 1
  3681. this[offset + i] = value & 0xFF
  3682. while (--i >= 0 && (mul *= 0x100))
  3683. this[offset + i] = (value / mul) >>> 0 & 0xFF
  3684. return offset + byteLength
  3685. }
  3686. Buffer.prototype.writeUInt8 = function (value, offset, noAssert) {
  3687. value = +value
  3688. offset = offset >>> 0
  3689. if (!noAssert)
  3690. checkInt(this, value, offset, 1, 0xff, 0)
  3691. if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
  3692. this[offset] = value
  3693. return offset + 1
  3694. }
  3695. function objectWriteUInt16 (buf, value, offset, littleEndian) {
  3696. if (value < 0) value = 0xffff + value + 1
  3697. for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
  3698. buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
  3699. (littleEndian ? i : 1 - i) * 8
  3700. }
  3701. }
  3702. Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) {
  3703. value = +value
  3704. offset = offset >>> 0
  3705. if (!noAssert)
  3706. checkInt(this, value, offset, 2, 0xffff, 0)
  3707. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3708. this[offset] = value
  3709. this[offset + 1] = (value >>> 8)
  3710. } else objectWriteUInt16(this, value, offset, true)
  3711. return offset + 2
  3712. }
  3713. Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) {
  3714. value = +value
  3715. offset = offset >>> 0
  3716. if (!noAssert)
  3717. checkInt(this, value, offset, 2, 0xffff, 0)
  3718. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3719. this[offset] = (value >>> 8)
  3720. this[offset + 1] = value
  3721. } else objectWriteUInt16(this, value, offset, false)
  3722. return offset + 2
  3723. }
  3724. function objectWriteUInt32 (buf, value, offset, littleEndian) {
  3725. if (value < 0) value = 0xffffffff + value + 1
  3726. for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
  3727. buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
  3728. }
  3729. }
  3730. Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) {
  3731. value = +value
  3732. offset = offset >>> 0
  3733. if (!noAssert)
  3734. checkInt(this, value, offset, 4, 0xffffffff, 0)
  3735. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3736. this[offset + 3] = (value >>> 24)
  3737. this[offset + 2] = (value >>> 16)
  3738. this[offset + 1] = (value >>> 8)
  3739. this[offset] = value
  3740. } else objectWriteUInt32(this, value, offset, true)
  3741. return offset + 4
  3742. }
  3743. Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) {
  3744. value = +value
  3745. offset = offset >>> 0
  3746. if (!noAssert)
  3747. checkInt(this, value, offset, 4, 0xffffffff, 0)
  3748. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3749. this[offset] = (value >>> 24)
  3750. this[offset + 1] = (value >>> 16)
  3751. this[offset + 2] = (value >>> 8)
  3752. this[offset + 3] = value
  3753. } else objectWriteUInt32(this, value, offset, false)
  3754. return offset + 4
  3755. }
  3756. Buffer.prototype.writeIntLE = function (value, offset, byteLength, noAssert) {
  3757. value = +value
  3758. offset = offset >>> 0
  3759. if (!noAssert) {
  3760. checkInt(this,
  3761. value,
  3762. offset,
  3763. byteLength,
  3764. Math.pow(2, 8 * byteLength - 1) - 1,
  3765. -Math.pow(2, 8 * byteLength - 1))
  3766. }
  3767. var i = 0
  3768. var mul = 1
  3769. var sub = value < 0 ? 1 : 0
  3770. this[offset] = value & 0xFF
  3771. while (++i < byteLength && (mul *= 0x100))
  3772. this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
  3773. return offset + byteLength
  3774. }
  3775. Buffer.prototype.writeIntBE = function (value, offset, byteLength, noAssert) {
  3776. value = +value
  3777. offset = offset >>> 0
  3778. if (!noAssert) {
  3779. checkInt(this,
  3780. value,
  3781. offset,
  3782. byteLength,
  3783. Math.pow(2, 8 * byteLength - 1) - 1,
  3784. -Math.pow(2, 8 * byteLength - 1))
  3785. }
  3786. var i = byteLength - 1
  3787. var mul = 1
  3788. var sub = value < 0 ? 1 : 0
  3789. this[offset + i] = value & 0xFF
  3790. while (--i >= 0 && (mul *= 0x100))
  3791. this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
  3792. return offset + byteLength
  3793. }
  3794. Buffer.prototype.writeInt8 = function (value, offset, noAssert) {
  3795. value = +value
  3796. offset = offset >>> 0
  3797. if (!noAssert)
  3798. checkInt(this, value, offset, 1, 0x7f, -0x80)
  3799. if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
  3800. if (value < 0) value = 0xff + value + 1
  3801. this[offset] = value
  3802. return offset + 1
  3803. }
  3804. Buffer.prototype.writeInt16LE = function (value, offset, noAssert) {
  3805. value = +value
  3806. offset = offset >>> 0
  3807. if (!noAssert)
  3808. checkInt(this, value, offset, 2, 0x7fff, -0x8000)
  3809. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3810. this[offset] = value
  3811. this[offset + 1] = (value >>> 8)
  3812. } else objectWriteUInt16(this, value, offset, true)
  3813. return offset + 2
  3814. }
  3815. Buffer.prototype.writeInt16BE = function (value, offset, noAssert) {
  3816. value = +value
  3817. offset = offset >>> 0
  3818. if (!noAssert)
  3819. checkInt(this, value, offset, 2, 0x7fff, -0x8000)
  3820. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3821. this[offset] = (value >>> 8)
  3822. this[offset + 1] = value
  3823. } else objectWriteUInt16(this, value, offset, false)
  3824. return offset + 2
  3825. }
  3826. Buffer.prototype.writeInt32LE = function (value, offset, noAssert) {
  3827. value = +value
  3828. offset = offset >>> 0
  3829. if (!noAssert)
  3830. checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
  3831. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3832. this[offset] = value
  3833. this[offset + 1] = (value >>> 8)
  3834. this[offset + 2] = (value >>> 16)
  3835. this[offset + 3] = (value >>> 24)
  3836. } else objectWriteUInt32(this, value, offset, true)
  3837. return offset + 4
  3838. }
  3839. Buffer.prototype.writeInt32BE = function (value, offset, noAssert) {
  3840. value = +value
  3841. offset = offset >>> 0
  3842. if (!noAssert)
  3843. checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
  3844. if (value < 0) value = 0xffffffff + value + 1
  3845. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3846. this[offset] = (value >>> 24)
  3847. this[offset + 1] = (value >>> 16)
  3848. this[offset + 2] = (value >>> 8)
  3849. this[offset + 3] = value
  3850. } else objectWriteUInt32(this, value, offset, false)
  3851. return offset + 4
  3852. }
  3853. function checkIEEE754 (buf, value, offset, ext, max, min) {
  3854. if (value > max || value < min) throw new RangeError('value is out of bounds')
  3855. if (offset + ext > buf.length) throw new RangeError('index out of range')
  3856. if (offset < 0) throw new RangeError('index out of range')
  3857. }
  3858. function writeFloat (buf, value, offset, littleEndian, noAssert) {
  3859. if (!noAssert)
  3860. checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
  3861. ieee754.write(buf, value, offset, littleEndian, 23, 4)
  3862. return offset + 4
  3863. }
  3864. Buffer.prototype.writeFloatLE = function (value, offset, noAssert) {
  3865. return writeFloat(this, value, offset, true, noAssert)
  3866. }
  3867. Buffer.prototype.writeFloatBE = function (value, offset, noAssert) {
  3868. return writeFloat(this, value, offset, false, noAssert)
  3869. }
  3870. function writeDouble (buf, value, offset, littleEndian, noAssert) {
  3871. if (!noAssert)
  3872. checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
  3873. ieee754.write(buf, value, offset, littleEndian, 52, 8)
  3874. return offset + 8
  3875. }
  3876. Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) {
  3877. return writeDouble(this, value, offset, true, noAssert)
  3878. }
  3879. Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) {
  3880. return writeDouble(this, value, offset, false, noAssert)
  3881. }
  3882. // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  3883. Buffer.prototype.copy = function (target, target_start, start, end) {
  3884. var self = this // source
  3885. if (!start) start = 0
  3886. if (!end && end !== 0) end = this.length
  3887. if (target_start >= target.length) target_start = target.length
  3888. if (!target_start) target_start = 0
  3889. if (end > 0 && end < start) end = start
  3890. // Copy 0 bytes; we're done
  3891. if (end === start) return 0
  3892. if (target.length === 0 || self.length === 0) return 0
  3893. // Fatal error conditions
  3894. if (target_start < 0)
  3895. throw new RangeError('targetStart out of bounds')
  3896. if (start < 0 || start >= self.length) throw new RangeError('sourceStart out of bounds')
  3897. if (end < 0) throw new RangeError('sourceEnd out of bounds')
  3898. // Are we oob?
  3899. if (end > this.length)
  3900. end = this.length
  3901. if (target.length - target_start < end - start)
  3902. end = target.length - target_start + start
  3903. var len = end - start
  3904. if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
  3905. for (var i = 0; i < len; i++) {
  3906. target[i + target_start] = this[i + start]
  3907. }
  3908. } else {
  3909. target._set(this.subarray(start, start + len), target_start)
  3910. }
  3911. return len
  3912. }
  3913. // fill(value, start=0, end=buffer.length)
  3914. Buffer.prototype.fill = function (value, start, end) {
  3915. if (!value) value = 0
  3916. if (!start) start = 0
  3917. if (!end) end = this.length
  3918. if (end < start) throw new RangeError('end < start')
  3919. // Fill 0 bytes; we're done
  3920. if (end === start) return
  3921. if (this.length === 0) return
  3922. if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
  3923. if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
  3924. var i
  3925. if (typeof value === 'number') {
  3926. for (i = start; i < end; i++) {
  3927. this[i] = value
  3928. }
  3929. } else {
  3930. var bytes = utf8ToBytes(value.toString())
  3931. var len = bytes.length
  3932. for (i = start; i < end; i++) {
  3933. this[i] = bytes[i % len]
  3934. }
  3935. }
  3936. return this
  3937. }
  3938. /**
  3939. * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
  3940. * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
  3941. */
  3942. Buffer.prototype.toArrayBuffer = function () {
  3943. if (typeof Uint8Array !== 'undefined') {
  3944. if (Buffer.TYPED_ARRAY_SUPPORT) {
  3945. return (new Buffer(this)).buffer
  3946. } else {
  3947. var buf = new Uint8Array(this.length)
  3948. for (var i = 0, len = buf.length; i < len; i += 1) {
  3949. buf[i] = this[i]
  3950. }
  3951. return buf.buffer
  3952. }
  3953. } else {
  3954. throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
  3955. }
  3956. }
  3957. // HELPER FUNCTIONS
  3958. // ================
  3959. var BP = Buffer.prototype
  3960. /**
  3961. * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
  3962. */
  3963. Buffer._augment = function (arr) {
  3964. arr.constructor = Buffer
  3965. arr._isBuffer = true
  3966. // save reference to original Uint8Array get/set methods before overwriting
  3967. arr._get = arr.get
  3968. arr._set = arr.set
  3969. // deprecated, will be removed in node 0.13+
  3970. arr.get = BP.get
  3971. arr.set = BP.set
  3972. arr.write = BP.write
  3973. arr.toString = BP.toString
  3974. arr.toLocaleString = BP.toString
  3975. arr.toJSON = BP.toJSON
  3976. arr.equals = BP.equals
  3977. arr.compare = BP.compare
  3978. arr.copy = BP.copy
  3979. arr.slice = BP.slice
  3980. arr.readUIntLE = BP.readUIntLE
  3981. arr.readUIntBE = BP.readUIntBE
  3982. arr.readUInt8 = BP.readUInt8
  3983. arr.readUInt16LE = BP.readUInt16LE
  3984. arr.readUInt16BE = BP.readUInt16BE
  3985. arr.readUInt32LE = BP.readUInt32LE
  3986. arr.readUInt32BE = BP.readUInt32BE
  3987. arr.readIntLE = BP.readIntLE
  3988. arr.readIntBE = BP.readIntBE
  3989. arr.readInt8 = BP.readInt8
  3990. arr.readInt16LE = BP.readInt16LE
  3991. arr.readInt16BE = BP.readInt16BE
  3992. arr.readInt32LE = BP.readInt32LE
  3993. arr.readInt32BE = BP.readInt32BE
  3994. arr.readFloatLE = BP.readFloatLE
  3995. arr.readFloatBE = BP.readFloatBE
  3996. arr.readDoubleLE = BP.readDoubleLE
  3997. arr.readDoubleBE = BP.readDoubleBE
  3998. arr.writeUInt8 = BP.writeUInt8
  3999. arr.writeUIntLE = BP.writeUIntLE
  4000. arr.writeUIntBE = BP.writeUIntBE
  4001. arr.writeUInt16LE = BP.writeUInt16LE
  4002. arr.writeUInt16BE = BP.writeUInt16BE
  4003. arr.writeUInt32LE = BP.writeUInt32LE
  4004. arr.writeUInt32BE = BP.writeUInt32BE
  4005. arr.writeIntLE = BP.writeIntLE
  4006. arr.writeIntBE = BP.writeIntBE
  4007. arr.writeInt8 = BP.writeInt8
  4008. arr.writeInt16LE = BP.writeInt16LE
  4009. arr.writeInt16BE = BP.writeInt16BE
  4010. arr.writeInt32LE = BP.writeInt32LE
  4011. arr.writeInt32BE = BP.writeInt32BE
  4012. arr.writeFloatLE = BP.writeFloatLE
  4013. arr.writeFloatBE = BP.writeFloatBE
  4014. arr.writeDoubleLE = BP.writeDoubleLE
  4015. arr.writeDoubleBE = BP.writeDoubleBE
  4016. arr.fill = BP.fill
  4017. arr.inspect = BP.inspect
  4018. arr.toArrayBuffer = BP.toArrayBuffer
  4019. return arr
  4020. }
  4021. var INVALID_BASE64_RE = /[^+\/0-9A-z\-]/g
  4022. function base64clean (str) {
  4023. // Node strips out invalid characters like \n and \t from the string, base64-js does not
  4024. str = stringtrim(str).replace(INVALID_BASE64_RE, '')
  4025. // Node converts strings with length < 2 to ''
  4026. if (str.length < 2) return ''
  4027. // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
  4028. while (str.length % 4 !== 0) {
  4029. str = str + '='
  4030. }
  4031. return str
  4032. }
  4033. function stringtrim (str) {
  4034. if (str.trim) return str.trim()
  4035. return str.replace(/^\s+|\s+$/g, '')
  4036. }
  4037. function isArrayish (subject) {
  4038. return isArray(subject) || Buffer.isBuffer(subject) ||
  4039. subject && typeof subject === 'object' &&
  4040. typeof subject.length === 'number'
  4041. }
  4042. function toHex (n) {
  4043. if (n < 16) return '0' + n.toString(16)
  4044. return n.toString(16)
  4045. }
  4046. function utf8ToBytes (string, units) {
  4047. units = units || Infinity
  4048. var codePoint
  4049. var length = string.length
  4050. var leadSurrogate = null
  4051. var bytes = []
  4052. var i = 0
  4053. for (; i < length; i++) {
  4054. codePoint = string.charCodeAt(i)
  4055. // is surrogate component
  4056. if (codePoint > 0xD7FF && codePoint < 0xE000) {
  4057. // last char was a lead
  4058. if (leadSurrogate) {
  4059. // 2 leads in a row
  4060. if (codePoint < 0xDC00) {
  4061. if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
  4062. leadSurrogate = codePoint
  4063. continue
  4064. } else {
  4065. // valid surrogate pair
  4066. codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
  4067. leadSurrogate = null
  4068. }
  4069. } else {
  4070. // no lead yet
  4071. if (codePoint > 0xDBFF) {
  4072. // unexpected trail
  4073. if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
  4074. continue
  4075. } else if (i + 1 === length) {
  4076. // unpaired lead
  4077. if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
  4078. continue
  4079. } else {
  4080. // valid lead
  4081. leadSurrogate = codePoint
  4082. continue
  4083. }
  4084. }
  4085. } else if (leadSurrogate) {
  4086. // valid bmp char, but last char was a lead
  4087. if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
  4088. leadSurrogate = null
  4089. }
  4090. // encode utf8
  4091. if (codePoint < 0x80) {
  4092. if ((units -= 1) < 0) break
  4093. bytes.push(codePoint)
  4094. } else if (codePoint < 0x800) {
  4095. if ((units -= 2) < 0) break
  4096. bytes.push(
  4097. codePoint >> 0x6 | 0xC0,
  4098. codePoint & 0x3F | 0x80
  4099. )
  4100. } else if (codePoint < 0x10000) {
  4101. if ((units -= 3) < 0) break
  4102. bytes.push(
  4103. codePoint >> 0xC | 0xE0,
  4104. codePoint >> 0x6 & 0x3F | 0x80,
  4105. codePoint & 0x3F | 0x80
  4106. )
  4107. } else if (codePoint < 0x200000) {
  4108. if ((units -= 4) < 0) break
  4109. bytes.push(
  4110. codePoint >> 0x12 | 0xF0,
  4111. codePoint >> 0xC & 0x3F | 0x80,
  4112. codePoint >> 0x6 & 0x3F | 0x80,
  4113. codePoint & 0x3F | 0x80
  4114. )
  4115. } else {
  4116. throw new Error('Invalid code point')
  4117. }
  4118. }
  4119. return bytes
  4120. }
  4121. function asciiToBytes (str) {
  4122. var byteArray = []
  4123. for (var i = 0; i < str.length; i++) {
  4124. // Node's code seems to be doing this and not & 0x7F..
  4125. byteArray.push(str.charCodeAt(i) & 0xFF)
  4126. }
  4127. return byteArray
  4128. }
  4129. function utf16leToBytes (str, units) {
  4130. var c, hi, lo
  4131. var byteArray = []
  4132. for (var i = 0; i < str.length; i++) {
  4133. if ((units -= 2) < 0) break
  4134. c = str.charCodeAt(i)
  4135. hi = c >> 8
  4136. lo = c % 256
  4137. byteArray.push(lo)
  4138. byteArray.push(hi)
  4139. }
  4140. return byteArray
  4141. }
  4142. function base64ToBytes (str) {
  4143. return base64.toByteArray(base64clean(str))
  4144. }
  4145. function blitBuffer (src, dst, offset, length) {
  4146. for (var i = 0; i < length; i++) {
  4147. if ((i + offset >= dst.length) || (i >= src.length))
  4148. break
  4149. dst[i + offset] = src[i]
  4150. }
  4151. return i
  4152. }
  4153. function decodeUtf8Char (str) {
  4154. try {
  4155. return decodeURIComponent(str)
  4156. } catch (err) {
  4157. return String.fromCharCode(0xFFFD) // UTF 8 invalid char
  4158. }
  4159. }
  4160. },{"base64-js":13,"ieee754":14,"is-array":15}],13:[function(require,module,exports){
  4161. var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  4162. ;(function (exports) {
  4163. 'use strict';
  4164. var Arr = (typeof Uint8Array !== 'undefined')
  4165. ? Uint8Array
  4166. : Array
  4167. var PLUS = '+'.charCodeAt(0)
  4168. var SLASH = '/'.charCodeAt(0)
  4169. var NUMBER = '0'.charCodeAt(0)
  4170. var LOWER = 'a'.charCodeAt(0)
  4171. var UPPER = 'A'.charCodeAt(0)
  4172. var PLUS_URL_SAFE = '-'.charCodeAt(0)
  4173. var SLASH_URL_SAFE = '_'.charCodeAt(0)
  4174. function decode (elt) {
  4175. var code = elt.charCodeAt(0)
  4176. if (code === PLUS ||
  4177. code === PLUS_URL_SAFE)
  4178. return 62 // '+'
  4179. if (code === SLASH ||
  4180. code === SLASH_URL_SAFE)
  4181. return 63 // '/'
  4182. if (code < NUMBER)
  4183. return -1 //no match
  4184. if (code < NUMBER + 10)
  4185. return code - NUMBER + 26 + 26
  4186. if (code < UPPER + 26)
  4187. return code - UPPER
  4188. if (code < LOWER + 26)
  4189. return code - LOWER + 26
  4190. }
  4191. function b64ToByteArray (b64) {
  4192. var i, j, l, tmp, placeHolders, arr
  4193. if (b64.length % 4 > 0) {
  4194. throw new Error('Invalid string. Length must be a multiple of 4')
  4195. }
  4196. // the number of equal signs (place holders)
  4197. // if there are two placeholders, than the two characters before it
  4198. // represent one byte
  4199. // if there is only one, then the three characters before it represent 2 bytes
  4200. // this is just a cheap hack to not do indexOf twice
  4201. var len = b64.length
  4202. placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
  4203. // base64 is 4/3 + up to two characters of the original data
  4204. arr = new Arr(b64.length * 3 / 4 - placeHolders)
  4205. // if there are placeholders, only get up to the last complete 4 chars
  4206. l = placeHolders > 0 ? b64.length - 4 : b64.length
  4207. var L = 0
  4208. function push (v) {
  4209. arr[L++] = v
  4210. }
  4211. for (i = 0, j = 0; i < l; i += 4, j += 3) {
  4212. tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
  4213. push((tmp & 0xFF0000) >> 16)
  4214. push((tmp & 0xFF00) >> 8)
  4215. push(tmp & 0xFF)
  4216. }
  4217. if (placeHolders === 2) {
  4218. tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
  4219. push(tmp & 0xFF)
  4220. } else if (placeHolders === 1) {
  4221. tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
  4222. push((tmp >> 8) & 0xFF)
  4223. push(tmp & 0xFF)
  4224. }
  4225. return arr
  4226. }
  4227. function uint8ToBase64 (uint8) {
  4228. var i,
  4229. extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
  4230. output = "",
  4231. temp, length
  4232. function encode (num) {
  4233. return lookup.charAt(num)
  4234. }
  4235. function tripletToBase64 (num) {
  4236. return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
  4237. }
  4238. // go through the array every three bytes, we'll deal with trailing stuff later
  4239. for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
  4240. temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
  4241. output += tripletToBase64(temp)
  4242. }
  4243. // pad the end with zeros, but make sure to not forget the extra bytes
  4244. switch (extraBytes) {
  4245. case 1:
  4246. temp = uint8[uint8.length - 1]
  4247. output += encode(temp >> 2)
  4248. output += encode((temp << 4) & 0x3F)
  4249. output += '=='
  4250. break
  4251. case 2:
  4252. temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
  4253. output += encode(temp >> 10)
  4254. output += encode((temp >> 4) & 0x3F)
  4255. output += encode((temp << 2) & 0x3F)
  4256. output += '='
  4257. break
  4258. }
  4259. return output
  4260. }
  4261. exports.toByteArray = b64ToByteArray
  4262. exports.fromByteArray = uint8ToBase64
  4263. }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
  4264. },{}],14:[function(require,module,exports){
  4265. exports.read = function(buffer, offset, isLE, mLen, nBytes) {
  4266. var e, m,
  4267. eLen = nBytes * 8 - mLen - 1,
  4268. eMax = (1 << eLen) - 1,
  4269. eBias = eMax >> 1,
  4270. nBits = -7,
  4271. i = isLE ? (nBytes - 1) : 0,
  4272. d = isLE ? -1 : 1,
  4273. s = buffer[offset + i];
  4274. i += d;
  4275. e = s & ((1 << (-nBits)) - 1);
  4276. s >>= (-nBits);
  4277. nBits += eLen;
  4278. for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
  4279. m = e & ((1 << (-nBits)) - 1);
  4280. e >>= (-nBits);
  4281. nBits += mLen;
  4282. for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
  4283. if (e === 0) {
  4284. e = 1 - eBias;
  4285. } else if (e === eMax) {
  4286. return m ? NaN : ((s ? -1 : 1) * Infinity);
  4287. } else {
  4288. m = m + Math.pow(2, mLen);
  4289. e = e - eBias;
  4290. }
  4291. return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
  4292. };
  4293. exports.write = function(buffer, value, offset, isLE, mLen, nBytes) {
  4294. var e, m, c,
  4295. eLen = nBytes * 8 - mLen - 1,
  4296. eMax = (1 << eLen) - 1,
  4297. eBias = eMax >> 1,
  4298. rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
  4299. i = isLE ? 0 : (nBytes - 1),
  4300. d = isLE ? 1 : -1,
  4301. s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
  4302. value = Math.abs(value);
  4303. if (isNaN(value) || value === Infinity) {
  4304. m = isNaN(value) ? 1 : 0;
  4305. e = eMax;
  4306. } else {
  4307. e = Math.floor(Math.log(value) / Math.LN2);
  4308. if (value * (c = Math.pow(2, -e)) < 1) {
  4309. e--;
  4310. c *= 2;
  4311. }
  4312. if (e + eBias >= 1) {
  4313. value += rt / c;
  4314. } else {
  4315. value += rt * Math.pow(2, 1 - eBias);
  4316. }
  4317. if (value * c >= 2) {
  4318. e++;
  4319. c /= 2;
  4320. }
  4321. if (e + eBias >= eMax) {
  4322. m = 0;
  4323. e = eMax;
  4324. } else if (e + eBias >= 1) {
  4325. m = (value * c - 1) * Math.pow(2, mLen);
  4326. e = e + eBias;
  4327. } else {
  4328. m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
  4329. e = 0;
  4330. }
  4331. }
  4332. for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
  4333. e = (e << mLen) | m;
  4334. eLen += mLen;
  4335. for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
  4336. buffer[offset + i - d] |= s * 128;
  4337. };
  4338. },{}],15:[function(require,module,exports){
  4339. /**
  4340. * isArray
  4341. */
  4342. var isArray = Array.isArray;
  4343. /**
  4344. * toString
  4345. */
  4346. var str = Object.prototype.toString;
  4347. /**
  4348. * Whether or not the given `val`
  4349. * is an array.
  4350. *
  4351. * example:
  4352. *
  4353. * isArray([]);
  4354. * // > true
  4355. * isArray(arguments);
  4356. * // > false
  4357. * isArray('');
  4358. * // > false
  4359. *
  4360. * @param {mixed} val
  4361. * @return {bool}
  4362. */
  4363. module.exports = isArray || function (val) {
  4364. return !! val && '[object Array]' == str.call(val);
  4365. };
  4366. },{}],16:[function(require,module,exports){
  4367. (function (Buffer){
  4368. (function () {
  4369. "use strict";
  4370. function btoa(str) {
  4371. var buffer
  4372. ;
  4373. if (str instanceof Buffer) {
  4374. buffer = str;
  4375. } else {
  4376. buffer = new Buffer(str.toString(), 'binary');
  4377. }
  4378. return buffer.toString('base64');
  4379. }
  4380. module.exports = btoa;
  4381. }());
  4382. }).call(this,require("buffer").Buffer)
  4383. },{"buffer":12}],17:[function(require,module,exports){
  4384. /* jshint node: true */
  4385. (function () {
  4386. "use strict";
  4387. function CookieAccessInfo(domain, path, secure, script) {
  4388. if (this instanceof CookieAccessInfo) {
  4389. this.domain = domain || undefined;
  4390. this.path = path || "/";
  4391. this.secure = !!secure;
  4392. this.script = !!script;
  4393. return this;
  4394. }
  4395. return new CookieAccessInfo(domain, path, secure, script);
  4396. }
  4397. exports.CookieAccessInfo = CookieAccessInfo;
  4398. function Cookie(cookiestr, request_domain, request_path) {
  4399. if (cookiestr instanceof Cookie) {
  4400. return cookiestr;
  4401. }
  4402. if (this instanceof Cookie) {
  4403. this.name = null;
  4404. this.value = null;
  4405. this.expiration_date = Infinity;
  4406. this.path = String(request_path || "/");
  4407. this.explicit_path = false;
  4408. this.domain = request_domain || null;
  4409. this.explicit_domain = false;
  4410. this.secure = false; //how to define default?
  4411. this.noscript = false; //httponly
  4412. if (cookiestr) {
  4413. this.parse(cookiestr, request_domain, request_path);
  4414. }
  4415. return this;
  4416. }
  4417. return new Cookie(cookiestr);
  4418. }
  4419. exports.Cookie = Cookie;
  4420. Cookie.prototype.toString = function toString() {
  4421. var str = [this.name + "=" + this.value];
  4422. if (this.expiration_date !== Infinity) {
  4423. str.push("expires=" + (new Date(this.expiration_date)).toGMTString());
  4424. }
  4425. if (this.domain) {
  4426. str.push("domain=" + this.domain);
  4427. }
  4428. if (this.path) {
  4429. str.push("path=" + this.path);
  4430. }
  4431. if (this.secure) {
  4432. str.push("secure");
  4433. }
  4434. if (this.noscript) {
  4435. str.push("httponly");
  4436. }
  4437. return str.join("; ");
  4438. };
  4439. Cookie.prototype.toValueString = function toValueString() {
  4440. return this.name + "=" + this.value;
  4441. };
  4442. var cookie_str_splitter = /[:](?=\s*[a-zA-Z0-9_\-]+\s*[=])/g;
  4443. Cookie.prototype.parse = function parse(str, request_domain, request_path) {
  4444. if (this instanceof Cookie) {
  4445. var parts = str.split(";").filter(function (value) {
  4446. return !!value;
  4447. }),
  4448. pair = parts[0].match(/([^=]+)=([\s\S]*)/),
  4449. key = pair[1],
  4450. value = pair[2],
  4451. i;
  4452. this.name = key;
  4453. this.value = value;
  4454. for (i = 1; i < parts.length; i += 1) {
  4455. pair = parts[i].match(/([^=]+)(?:=([\s\S]*))?/);
  4456. key = pair[1].trim().toLowerCase();
  4457. value = pair[2];
  4458. switch (key) {
  4459. case "httponly":
  4460. this.noscript = true;
  4461. break;
  4462. case "expires":
  4463. this.expiration_date = value ?
  4464. Number(Date.parse(value)) :
  4465. Infinity;
  4466. break;
  4467. case "path":
  4468. this.path = value ?
  4469. value.trim() :
  4470. "";
  4471. this.explicit_path = true;
  4472. break;
  4473. case "domain":
  4474. this.domain = value ?
  4475. value.trim() :
  4476. "";
  4477. this.explicit_domain = !!this.domain;
  4478. break;
  4479. case "secure":
  4480. this.secure = true;
  4481. break;
  4482. }
  4483. }
  4484. if (!this.explicit_path) {
  4485. this.path = request_path || "/";
  4486. }
  4487. if (!this.explicit_domain) {
  4488. this.domain = request_domain;
  4489. }
  4490. return this;
  4491. }
  4492. return new Cookie().parse(str, request_domain, request_path);
  4493. };
  4494. Cookie.prototype.matches = function matches(access_info) {
  4495. if (this.noscript && access_info.script ||
  4496. this.secure && !access_info.secure ||
  4497. !this.collidesWith(access_info)) {
  4498. return false;
  4499. }
  4500. return true;
  4501. };
  4502. Cookie.prototype.collidesWith = function collidesWith(access_info) {
  4503. if ((this.path && !access_info.path) || (this.domain && !access_info.domain)) {
  4504. return false;
  4505. }
  4506. if (this.path && access_info.path.indexOf(this.path) !== 0) {
  4507. return false;
  4508. }
  4509. if (!this.explicit_path) {
  4510. if (this.path !== access_info.path) {
  4511. return false;
  4512. }
  4513. }
  4514. var access_domain = access_info.domain && access_info.domain.replace(/^[\.]/,'');
  4515. var cookie_domain = this.domain && this.domain.replace(/^[\.]/,'');
  4516. if (cookie_domain === access_domain) {
  4517. return true;
  4518. }
  4519. if (cookie_domain) {
  4520. if (!this.explicit_domain) {
  4521. return false; // we already checked if the domains were exactly the same
  4522. }
  4523. var wildcard = access_domain.indexOf(cookie_domain);
  4524. if (wildcard === -1 || wildcard !== access_domain.length - cookie_domain.length) {
  4525. return false;
  4526. }
  4527. return true;
  4528. }
  4529. return true;
  4530. };
  4531. function CookieJar() {
  4532. var cookies, cookies_list, collidable_cookie;
  4533. if (this instanceof CookieJar) {
  4534. cookies = Object.create(null); //name: [Cookie]
  4535. this.setCookie = function setCookie(cookie, request_domain, request_path) {
  4536. var remove, i;
  4537. cookie = new Cookie(cookie, request_domain, request_path);
  4538. //Delete the cookie if the set is past the current time
  4539. remove = cookie.expiration_date <= Date.now();
  4540. if (cookies[cookie.name] !== undefined) {
  4541. cookies_list = cookies[cookie.name];
  4542. for (i = 0; i < cookies_list.length; i += 1) {
  4543. collidable_cookie = cookies_list[i];
  4544. if (collidable_cookie.collidesWith(cookie)) {
  4545. if (remove) {
  4546. cookies_list.splice(i, 1);
  4547. if (cookies_list.length === 0) {
  4548. delete cookies[cookie.name];
  4549. }
  4550. return false;
  4551. }
  4552. cookies_list[i] = cookie;
  4553. return cookie;
  4554. }
  4555. }
  4556. if (remove) {
  4557. return false;
  4558. }
  4559. cookies_list.push(cookie);
  4560. return cookie;
  4561. }
  4562. if (remove) {
  4563. return false;
  4564. }
  4565. cookies[cookie.name] = [cookie];
  4566. return cookies[cookie.name];
  4567. };
  4568. //returns a cookie
  4569. this.getCookie = function getCookie(cookie_name, access_info) {
  4570. var cookie, i;
  4571. cookies_list = cookies[cookie_name];
  4572. if (!cookies_list) {
  4573. return;
  4574. }
  4575. for (i = 0; i < cookies_list.length; i += 1) {
  4576. cookie = cookies_list[i];
  4577. if (cookie.expiration_date <= Date.now()) {
  4578. if (cookies_list.length === 0) {
  4579. delete cookies[cookie.name];
  4580. }
  4581. continue;
  4582. }
  4583. if (cookie.matches(access_info)) {
  4584. return cookie;
  4585. }
  4586. }
  4587. };
  4588. //returns a list of cookies
  4589. this.getCookies = function getCookies(access_info) {
  4590. var matches = [], cookie_name, cookie;
  4591. for (cookie_name in cookies) {
  4592. cookie = this.getCookie(cookie_name, access_info);
  4593. if (cookie) {
  4594. matches.push(cookie);
  4595. }
  4596. }
  4597. matches.toString = function toString() {
  4598. return matches.join(":");
  4599. };
  4600. matches.toValueString = function toValueString() {
  4601. return matches.map(function (c) {
  4602. return c.toValueString();
  4603. }).join(';');
  4604. };
  4605. return matches;
  4606. };
  4607. return this;
  4608. }
  4609. return new CookieJar();
  4610. }
  4611. exports.CookieJar = CookieJar;
  4612. //returns list of cookies that were set correctly. Cookies that are expired and removed are not returned.
  4613. CookieJar.prototype.setCookies = function setCookies(cookies, request_domain, request_path) {
  4614. cookies = Array.isArray(cookies) ?
  4615. cookies :
  4616. cookies.split(cookie_str_splitter);
  4617. var successful = [],
  4618. i,
  4619. cookie;
  4620. cookies = cookies.map(Cookie);
  4621. for (i = 0; i < cookies.length; i += 1) {
  4622. cookie = cookies[i];
  4623. if (this.setCookie(cookie, request_domain, request_path)) {
  4624. successful.push(cookie);
  4625. }
  4626. }
  4627. return successful;
  4628. };
  4629. }());
  4630. },{}],18:[function(require,module,exports){
  4631. /*!
  4632. * jQuery JavaScript Library v2.1.3
  4633. * http://jquery.com/
  4634. *
  4635. * Includes Sizzle.js
  4636. * http://sizzlejs.com/
  4637. *
  4638. * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
  4639. * Released under the MIT license
  4640. * http://jquery.org/license
  4641. *
  4642. * Date: 2014-12-18T15:11Z
  4643. */
  4644. (function( global, factory ) {
  4645. if ( typeof module === "object" && typeof module.exports === "object" ) {
  4646. // For CommonJS and CommonJS-like environments where a proper `window`
  4647. // is present, execute the factory and get jQuery.
  4648. // For environments that do not have a `window` with a `document`
  4649. // (such as Node.js), expose a factory as module.exports.
  4650. // This accentuates the need for the creation of a real `window`.
  4651. // e.g. var jQuery = require("jquery")(window);
  4652. // See ticket #14549 for more info.
  4653. module.exports = global.document ?
  4654. factory( global, true ) :
  4655. function( w ) {
  4656. if ( !w.document ) {
  4657. throw new Error( "jQuery requires a window with a document" );
  4658. }
  4659. return factory( w );
  4660. };
  4661. } else {
  4662. factory( global );
  4663. }
  4664. // Pass this if window is not defined yet
  4665. }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
  4666. // Support: Firefox 18+
  4667. // Can't be in strict mode, several libs including ASP.NET trace
  4668. // the stack via arguments.caller.callee and Firefox dies if
  4669. // you try to trace through "use strict" call chains. (#13335)
  4670. //
  4671. var arr = [];
  4672. var slice = arr.slice;
  4673. var concat = arr.concat;
  4674. var push = arr.push;
  4675. var indexOf = arr.indexOf;
  4676. var class2type = {};
  4677. var toString = class2type.toString;
  4678. var hasOwn = class2type.hasOwnProperty;
  4679. var support = {};
  4680. var
  4681. // Use the correct document accordingly with window argument (sandbox)
  4682. document = window.document,
  4683. version = "2.1.3",
  4684. // Define a local copy of jQuery
  4685. jQuery = function( selector, context ) {
  4686. // The jQuery object is actually just the init constructor 'enhanced'
  4687. // Need init if jQuery is called (just allow error to be thrown if not included)
  4688. return new jQuery.fn.init( selector, context );
  4689. },
  4690. // Support: Android<4.1
  4691. // Make sure we trim BOM and NBSP
  4692. rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
  4693. // Matches dashed string for camelizing
  4694. rmsPrefix = /^-ms-/,
  4695. rdashAlpha = /-([\da-z])/gi,
  4696. // Used by jQuery.camelCase as callback to replace()
  4697. fcamelCase = function( all, letter ) {
  4698. return letter.toUpperCase();
  4699. };
  4700. jQuery.fn = jQuery.prototype = {
  4701. // The current version of jQuery being used
  4702. jquery: version,
  4703. constructor: jQuery,
  4704. // Start with an empty selector
  4705. selector: "",
  4706. // The default length of a jQuery object is 0
  4707. length: 0,
  4708. toArray: function() {
  4709. return slice.call( this );
  4710. },
  4711. // Get the Nth element in the matched element set OR
  4712. // Get the whole matched element set as a clean array
  4713. get: function( num ) {
  4714. return num != null ?
  4715. // Return just the one element from the set
  4716. ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
  4717. // Return all the elements in a clean array
  4718. slice.call( this );
  4719. },
  4720. // Take an array of elements and push it onto the stack
  4721. // (returning the new matched element set)
  4722. pushStack: function( elems ) {
  4723. // Build a new jQuery matched element set
  4724. var ret = jQuery.merge( this.constructor(), elems );
  4725. // Add the old object onto the stack (as a reference)
  4726. ret.prevObject = this;
  4727. ret.context = this.context;
  4728. // Return the newly-formed element set
  4729. return ret;
  4730. },
  4731. // Execute a callback for every element in the matched set.
  4732. // (You can seed the arguments with an array of args, but this is
  4733. // only used internally.)
  4734. each: function( callback, args ) {
  4735. return jQuery.each( this, callback, args );
  4736. },
  4737. map: function( callback ) {
  4738. return this.pushStack( jQuery.map(this, function( elem, i ) {
  4739. return callback.call( elem, i, elem );
  4740. }));
  4741. },
  4742. slice: function() {
  4743. return this.pushStack( slice.apply( this, arguments ) );
  4744. },
  4745. first: function() {
  4746. return this.eq( 0 );
  4747. },
  4748. last: function() {
  4749. return this.eq( -1 );
  4750. },
  4751. eq: function( i ) {
  4752. var len = this.length,
  4753. j = +i + ( i < 0 ? len : 0 );
  4754. return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
  4755. },
  4756. end: function() {
  4757. return this.prevObject || this.constructor(null);
  4758. },
  4759. // For internal use only.
  4760. // Behaves like an Array's method, not like a jQuery method.
  4761. push: push,
  4762. sort: arr.sort,
  4763. splice: arr.splice
  4764. };
  4765. jQuery.extend = jQuery.fn.extend = function() {
  4766. var options, name, src, copy, copyIsArray, clone,
  4767. target = arguments[0] || {},
  4768. i = 1,
  4769. length = arguments.length,
  4770. deep = false;
  4771. // Handle a deep copy situation
  4772. if ( typeof target === "boolean" ) {
  4773. deep = target;
  4774. // Skip the boolean and the target
  4775. target = arguments[ i ] || {};
  4776. i++;
  4777. }
  4778. // Handle case when target is a string or something (possible in deep copy)
  4779. if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
  4780. target = {};
  4781. }
  4782. // Extend jQuery itself if only one argument is passed
  4783. if ( i === length ) {
  4784. target = this;
  4785. i--;
  4786. }
  4787. for ( ; i < length; i++ ) {
  4788. // Only deal with non-null/undefined values
  4789. if ( (options = arguments[ i ]) != null ) {
  4790. // Extend the base object
  4791. for ( name in options ) {
  4792. src = target[ name ];
  4793. copy = options[ name ];
  4794. // Prevent never-ending loop
  4795. if ( target === copy ) {
  4796. continue;
  4797. }
  4798. // Recurse if we're merging plain objects or arrays
  4799. if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
  4800. if ( copyIsArray ) {
  4801. copyIsArray = false;
  4802. clone = src && jQuery.isArray(src) ? src : [];
  4803. } else {
  4804. clone = src && jQuery.isPlainObject(src) ? src : {};
  4805. }
  4806. // Never move original objects, clone them
  4807. target[ name ] = jQuery.extend( deep, clone, copy );
  4808. // Don't bring in undefined values
  4809. } else if ( copy !== undefined ) {
  4810. target[ name ] = copy;
  4811. }
  4812. }
  4813. }
  4814. }
  4815. // Return the modified object
  4816. return target;
  4817. };
  4818. jQuery.extend({
  4819. // Unique for each copy of jQuery on the page
  4820. expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
  4821. // Assume jQuery is ready without the ready module
  4822. isReady: true,
  4823. error: function( msg ) {
  4824. throw new Error( msg );
  4825. },
  4826. noop: function() {},
  4827. isFunction: function( obj ) {
  4828. return jQuery.type(obj) === "function";
  4829. },
  4830. isArray: Array.isArray,
  4831. isWindow: function( obj ) {
  4832. return obj != null && obj === obj.window;
  4833. },
  4834. isNumeric: function( obj ) {
  4835. // parseFloat NaNs numeric-cast false positives (null|true|false|"")
  4836. // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
  4837. // subtraction forces infinities to NaN
  4838. // adding 1 corrects loss of precision from parseFloat (#15100)
  4839. return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
  4840. },
  4841. isPlainObject: function( obj ) {
  4842. // Not plain objects:
  4843. // - Any object or value whose internal [[Class]] property is not "[object Object]"
  4844. // - DOM nodes
  4845. // - window
  4846. if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
  4847. return false;
  4848. }
  4849. if ( obj.constructor &&
  4850. !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
  4851. return false;
  4852. }
  4853. // If the function hasn't returned already, we're confident that
  4854. // |obj| is a plain object, created by {} or constructed with new Object
  4855. return true;
  4856. },
  4857. isEmptyObject: function( obj ) {
  4858. var name;
  4859. for ( name in obj ) {
  4860. return false;
  4861. }
  4862. return true;
  4863. },
  4864. type: function( obj ) {
  4865. if ( obj == null ) {
  4866. return obj + "";
  4867. }
  4868. // Support: Android<4.0, iOS<6 (functionish RegExp)
  4869. return typeof obj === "object" || typeof obj === "function" ?
  4870. class2type[ toString.call(obj) ] || "object" :
  4871. typeof obj;
  4872. },
  4873. // Evaluates a script in a global context
  4874. globalEval: function( code ) {
  4875. var script,
  4876. indirect = eval;
  4877. code = jQuery.trim( code );
  4878. if ( code ) {
  4879. // If the code includes a valid, prologue position
  4880. // strict mode pragma, execute code by injecting a
  4881. // script tag into the document.
  4882. if ( code.indexOf("use strict") === 1 ) {
  4883. script = document.createElement("script");
  4884. script.text = code;
  4885. document.head.appendChild( script ).parentNode.removeChild( script );
  4886. } else {
  4887. // Otherwise, avoid the DOM node creation, insertion
  4888. // and removal by using an indirect global eval
  4889. indirect( code );
  4890. }
  4891. }
  4892. },
  4893. // Convert dashed to camelCase; used by the css and data modules
  4894. // Support: IE9-11+
  4895. // Microsoft forgot to hump their vendor prefix (#9572)
  4896. camelCase: function( string ) {
  4897. return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
  4898. },
  4899. nodeName: function( elem, name ) {
  4900. return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
  4901. },
  4902. // args is for internal usage only
  4903. each: function( obj, callback, args ) {
  4904. var value,
  4905. i = 0,
  4906. length = obj.length,
  4907. isArray = isArraylike( obj );
  4908. if ( args ) {
  4909. if ( isArray ) {
  4910. for ( ; i < length; i++ ) {
  4911. value = callback.apply( obj[ i ], args );
  4912. if ( value === false ) {
  4913. break;
  4914. }
  4915. }
  4916. } else {
  4917. for ( i in obj ) {
  4918. value = callback.apply( obj[ i ], args );
  4919. if ( value === false ) {
  4920. break;
  4921. }
  4922. }
  4923. }
  4924. // A special, fast, case for the most common use of each
  4925. } else {
  4926. if ( isArray ) {
  4927. for ( ; i < length; i++ ) {
  4928. value = callback.call( obj[ i ], i, obj[ i ] );
  4929. if ( value === false ) {
  4930. break;
  4931. }
  4932. }
  4933. } else {
  4934. for ( i in obj ) {
  4935. value = callback.call( obj[ i ], i, obj[ i ] );
  4936. if ( value === false ) {
  4937. break;
  4938. }
  4939. }
  4940. }
  4941. }
  4942. return obj;
  4943. },
  4944. // Support: Android<4.1
  4945. trim: function( text ) {
  4946. return text == null ?
  4947. "" :
  4948. ( text + "" ).replace( rtrim, "" );
  4949. },
  4950. // results is for internal usage only
  4951. makeArray: function( arr, results ) {
  4952. var ret = results || [];
  4953. if ( arr != null ) {
  4954. if ( isArraylike( Object(arr) ) ) {
  4955. jQuery.merge( ret,
  4956. typeof arr === "string" ?
  4957. [ arr ] : arr
  4958. );
  4959. } else {
  4960. push.call( ret, arr );
  4961. }
  4962. }
  4963. return ret;
  4964. },
  4965. inArray: function( elem, arr, i ) {
  4966. return arr == null ? -1 : indexOf.call( arr, elem, i );
  4967. },
  4968. merge: function( first, second ) {
  4969. var len = +second.length,
  4970. j = 0,
  4971. i = first.length;
  4972. for ( ; j < len; j++ ) {
  4973. first[ i++ ] = second[ j ];
  4974. }
  4975. first.length = i;
  4976. return first;
  4977. },
  4978. grep: function( elems, callback, invert ) {
  4979. var callbackInverse,
  4980. matches = [],
  4981. i = 0,
  4982. length = elems.length,
  4983. callbackExpect = !invert;
  4984. // Go through the array, only saving the items
  4985. // that pass the validator function
  4986. for ( ; i < length; i++ ) {
  4987. callbackInverse = !callback( elems[ i ], i );
  4988. if ( callbackInverse !== callbackExpect ) {
  4989. matches.push( elems[ i ] );
  4990. }
  4991. }
  4992. return matches;
  4993. },
  4994. // arg is for internal usage only
  4995. map: function( elems, callback, arg ) {
  4996. var value,
  4997. i = 0,
  4998. length = elems.length,
  4999. isArray = isArraylike( elems ),
  5000. ret = [];
  5001. // Go through the array, translating each of the items to their new values
  5002. if ( isArray ) {
  5003. for ( ; i < length; i++ ) {
  5004. value = callback( elems[ i ], i, arg );
  5005. if ( value != null ) {
  5006. ret.push( value );
  5007. }
  5008. }
  5009. // Go through every key on the object,
  5010. } else {
  5011. for ( i in elems ) {
  5012. value = callback( elems[ i ], i, arg );
  5013. if ( value != null ) {
  5014. ret.push( value );
  5015. }
  5016. }
  5017. }
  5018. // Flatten any nested arrays
  5019. return concat.apply( [], ret );
  5020. },
  5021. // A global GUID counter for objects
  5022. guid: 1,
  5023. // Bind a function to a context, optionally partially applying any
  5024. // arguments.
  5025. proxy: function( fn, context ) {
  5026. var tmp, args, proxy;
  5027. if ( typeof context === "string" ) {
  5028. tmp = fn[ context ];
  5029. context = fn;
  5030. fn = tmp;
  5031. }
  5032. // Quick check to determine if target is callable, in the spec
  5033. // this throws a TypeError, but we will just return undefined.
  5034. if ( !jQuery.isFunction( fn ) ) {
  5035. return undefined;
  5036. }
  5037. // Simulated bind
  5038. args = slice.call( arguments, 2 );
  5039. proxy = function() {
  5040. return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
  5041. };
  5042. // Set the guid of unique handler to the same of original handler, so it can be removed
  5043. proxy.guid = fn.guid = fn.guid || jQuery.guid++;
  5044. return proxy;
  5045. },
  5046. now: Date.now,
  5047. // jQuery.support is not used in Core but other projects attach their
  5048. // properties to it so it needs to exist.
  5049. support: support
  5050. });
  5051. // Populate the class2type map
  5052. jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
  5053. class2type[ "[object " + name + "]" ] = name.toLowerCase();
  5054. });
  5055. function isArraylike( obj ) {
  5056. var length = obj.length,
  5057. type = jQuery.type( obj );
  5058. if ( type === "function" || jQuery.isWindow( obj ) ) {
  5059. return false;
  5060. }
  5061. if ( obj.nodeType === 1 && length ) {
  5062. return true;
  5063. }
  5064. return type === "array" || length === 0 ||
  5065. typeof length === "number" && length > 0 && ( length - 1 ) in obj;
  5066. }
  5067. var Sizzle =
  5068. /*!
  5069. * Sizzle CSS Selector Engine v2.2.0-pre
  5070. * http://sizzlejs.com/
  5071. *
  5072. * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
  5073. * Released under the MIT license
  5074. * http://jquery.org/license
  5075. *
  5076. * Date: 2014-12-16
  5077. */
  5078. (function( window ) {
  5079. var i,
  5080. support,
  5081. Expr,
  5082. getText,
  5083. isXML,
  5084. tokenize,
  5085. compile,
  5086. select,
  5087. outermostContext,
  5088. sortInput,
  5089. hasDuplicate,
  5090. // Local document vars
  5091. setDocument,
  5092. document,
  5093. docElem,
  5094. documentIsHTML,
  5095. rbuggyQSA,
  5096. rbuggyMatches,
  5097. matches,
  5098. contains,
  5099. // Instance-specific data
  5100. expando = "sizzle" + 1 * new Date(),
  5101. preferredDoc = window.document,
  5102. dirruns = 0,
  5103. done = 0,
  5104. classCache = createCache(),
  5105. tokenCache = createCache(),
  5106. compilerCache = createCache(),
  5107. sortOrder = function( a, b ) {
  5108. if ( a === b ) {
  5109. hasDuplicate = true;
  5110. }
  5111. return 0;
  5112. },
  5113. // General-purpose constants
  5114. MAX_NEGATIVE = 1 << 31,
  5115. // Instance methods
  5116. hasOwn = ({}).hasOwnProperty,
  5117. arr = [],
  5118. pop = arr.pop,
  5119. push_native = arr.push,
  5120. push = arr.push,
  5121. slice = arr.slice,
  5122. // Use a stripped-down indexOf as it's faster than native
  5123. // http://jsperf.com/thor-indexof-vs-for/5
  5124. indexOf = function( list, elem ) {
  5125. var i = 0,
  5126. len = list.length;
  5127. for ( ; i < len; i++ ) {
  5128. if ( list[i] === elem ) {
  5129. return i;
  5130. }
  5131. }
  5132. return -1;
  5133. },
  5134. booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
  5135. // Regular expressions
  5136. // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
  5137. whitespace = "[\\x20\\t\\r\\n\\f]",
  5138. // http://www.w3.org/TR/css3-syntax/#characters
  5139. characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
  5140. // Loosely modeled on CSS identifier characters
  5141. // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
  5142. // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
  5143. identifier = characterEncoding.replace( "w", "w#" ),
  5144. // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
  5145. attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
  5146. // Operator (capture 2)
  5147. "*([*^$|!~]?=)" + whitespace +
  5148. // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
  5149. "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
  5150. "*\\]",
  5151. pseudos = ":(" + characterEncoding + ")(?:\\((" +
  5152. // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
  5153. // 1. quoted (capture 3; capture 4 or capture 5)
  5154. "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
  5155. // 2. simple (capture 6)
  5156. "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
  5157. // 3. anything else (capture 2)
  5158. ".*" +
  5159. ")\\)|)",
  5160. // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
  5161. rwhitespace = new RegExp( whitespace + "+", "g" ),
  5162. rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
  5163. rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
  5164. rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
  5165. rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
  5166. rpseudo = new RegExp( pseudos ),
  5167. ridentifier = new RegExp( "^" + identifier + "$" ),
  5168. matchExpr = {
  5169. "ID": new RegExp( "^#(" + characterEncoding + ")" ),
  5170. "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
  5171. "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
  5172. "ATTR": new RegExp( "^" + attributes ),
  5173. "PSEUDO": new RegExp( "^" + pseudos ),
  5174. "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
  5175. "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
  5176. "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
  5177. "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
  5178. // For use in libraries implementing .is()
  5179. // We use this for POS matching in `select`
  5180. "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
  5181. whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
  5182. },
  5183. rinputs = /^(?:input|select|textarea|button)$/i,
  5184. rheader = /^h\d$/i,
  5185. rnative = /^[^{]+\{\s*\[native \w/,
  5186. // Easily-parseable/retrievable ID or TAG or CLASS selectors
  5187. rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
  5188. rsibling = /[+~]/,
  5189. rescape = /'|\\/g,
  5190. // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
  5191. runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
  5192. funescape = function( _, escaped, escapedWhitespace ) {
  5193. var high = "0x" + escaped - 0x10000;
  5194. // NaN means non-codepoint
  5195. // Support: Firefox<24
  5196. // Workaround erroneous numeric interpretation of +"0x"
  5197. return high !== high || escapedWhitespace ?
  5198. escaped :
  5199. high < 0 ?
  5200. // BMP codepoint
  5201. String.fromCharCode( high + 0x10000 ) :
  5202. // Supplemental Plane codepoint (surrogate pair)
  5203. String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
  5204. },
  5205. // Used for iframes
  5206. // See setDocument()
  5207. // Removing the function wrapper causes a "Permission Denied"
  5208. // error in IE
  5209. unloadHandler = function() {
  5210. setDocument();
  5211. };
  5212. // Optimize for push.apply( _, NodeList )
  5213. try {
  5214. push.apply(
  5215. (arr = slice.call( preferredDoc.childNodes )),
  5216. preferredDoc.childNodes
  5217. );
  5218. // Support: Android<4.0
  5219. // Detect silently failing push.apply
  5220. arr[ preferredDoc.childNodes.length ].nodeType;
  5221. } catch ( e ) {
  5222. push = { apply: arr.length ?
  5223. // Leverage slice if possible
  5224. function( target, els ) {
  5225. push_native.apply( target, slice.call(els) );
  5226. } :
  5227. // Support: IE<9
  5228. // Otherwise append directly
  5229. function( target, els ) {
  5230. var j = target.length,
  5231. i = 0;
  5232. // Can't trust NodeList.length
  5233. while ( (target[j++] = els[i++]) ) {}
  5234. target.length = j - 1;
  5235. }
  5236. };
  5237. }
  5238. function Sizzle( selector, context, results, seed ) {
  5239. var match, elem, m, nodeType,
  5240. // QSA vars
  5241. i, groups, old, nid, newContext, newSelector;
  5242. if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
  5243. setDocument( context );
  5244. }
  5245. context = context || document;
  5246. results = results || [];
  5247. nodeType = context.nodeType;
  5248. if ( typeof selector !== "string" || !selector ||
  5249. nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
  5250. return results;
  5251. }
  5252. if ( !seed && documentIsHTML ) {
  5253. // Try to shortcut find operations when possible (e.g., not under DocumentFragment)
  5254. if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
  5255. // Speed-up: Sizzle("#ID")
  5256. if ( (m = match[1]) ) {
  5257. if ( nodeType === 9 ) {
  5258. elem = context.getElementById( m );
  5259. // Check parentNode to catch when Blackberry 4.6 returns
  5260. // nodes that are no longer in the document (jQuery #6963)
  5261. if ( elem && elem.parentNode ) {
  5262. // Handle the case where IE, Opera, and Webkit return items
  5263. // by name instead of ID
  5264. if ( elem.id === m ) {
  5265. results.push( elem );
  5266. return results;
  5267. }
  5268. } else {
  5269. return results;
  5270. }
  5271. } else {
  5272. // Context is not a document
  5273. if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
  5274. contains( context, elem ) && elem.id === m ) {
  5275. results.push( elem );
  5276. return results;
  5277. }
  5278. }
  5279. // Speed-up: Sizzle("TAG")
  5280. } else if ( match[2] ) {
  5281. push.apply( results, context.getElementsByTagName( selector ) );
  5282. return results;
  5283. // Speed-up: Sizzle(".CLASS")
  5284. } else if ( (m = match[3]) && support.getElementsByClassName ) {
  5285. push.apply( results, context.getElementsByClassName( m ) );
  5286. return results;
  5287. }
  5288. }
  5289. // QSA path
  5290. if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
  5291. nid = old = expando;
  5292. newContext = context;
  5293. newSelector = nodeType !== 1 && selector;
  5294. // qSA works strangely on Element-rooted queries
  5295. // We can work around this by specifying an extra ID on the root
  5296. // and working up from there (Thanks to Andrew Dupont for the technique)
  5297. // IE 8 doesn't work on object elements
  5298. if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
  5299. groups = tokenize( selector );
  5300. if ( (old = context.getAttribute("id")) ) {
  5301. nid = old.replace( rescape, "\\$&" );
  5302. } else {
  5303. context.setAttribute( "id", nid );
  5304. }
  5305. nid = "[id='" + nid + "'] ";
  5306. i = groups.length;
  5307. while ( i-- ) {
  5308. groups[i] = nid + toSelector( groups[i] );
  5309. }
  5310. newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
  5311. newSelector = groups.join(",");
  5312. }
  5313. if ( newSelector ) {
  5314. try {
  5315. push.apply( results,
  5316. newContext.querySelectorAll( newSelector )
  5317. );
  5318. return results;
  5319. } catch(qsaError) {
  5320. } finally {
  5321. if ( !old ) {
  5322. context.removeAttribute("id");
  5323. }
  5324. }
  5325. }
  5326. }
  5327. }
  5328. // All others
  5329. return select( selector.replace( rtrim, "$1" ), context, results, seed );
  5330. }
  5331. /**
  5332. * Create key-value caches of limited size
  5333. * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
  5334. * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
  5335. * deleting the oldest entry
  5336. */
  5337. function createCache() {
  5338. var keys = [];
  5339. function cache( key, value ) {
  5340. // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
  5341. if ( keys.push( key + " " ) > Expr.cacheLength ) {
  5342. // Only keep the most recent entries
  5343. delete cache[ keys.shift() ];
  5344. }
  5345. return (cache[ key + " " ] = value);
  5346. }
  5347. return cache;
  5348. }
  5349. /**
  5350. * Mark a function for special use by Sizzle
  5351. * @param {Function} fn The function to mark
  5352. */
  5353. function markFunction( fn ) {
  5354. fn[ expando ] = true;
  5355. return fn;
  5356. }
  5357. /**
  5358. * Support testing using an element
  5359. * @param {Function} fn Passed the created div and expects a boolean result
  5360. */
  5361. function assert( fn ) {
  5362. var div = document.createElement("div");
  5363. try {
  5364. return !!fn( div );
  5365. } catch (e) {
  5366. return false;
  5367. } finally {
  5368. // Remove from its parent by default
  5369. if ( div.parentNode ) {
  5370. div.parentNode.removeChild( div );
  5371. }
  5372. // release memory in IE
  5373. div = null;
  5374. }
  5375. }
  5376. /**
  5377. * Adds the same handler for all of the specified attrs
  5378. * @param {String} attrs Pipe-separated list of attributes
  5379. * @param {Function} handler The method that will be applied
  5380. */
  5381. function addHandle( attrs, handler ) {
  5382. var arr = attrs.split("|"),
  5383. i = attrs.length;
  5384. while ( i-- ) {
  5385. Expr.attrHandle[ arr[i] ] = handler;
  5386. }
  5387. }
  5388. /**
  5389. * Checks document order of two siblings
  5390. * @param {Element} a
  5391. * @param {Element} b
  5392. * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
  5393. */
  5394. function siblingCheck( a, b ) {
  5395. var cur = b && a,
  5396. diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
  5397. ( ~b.sourceIndex || MAX_NEGATIVE ) -
  5398. ( ~a.sourceIndex || MAX_NEGATIVE );
  5399. // Use IE sourceIndex if available on both nodes
  5400. if ( diff ) {
  5401. return diff;
  5402. }
  5403. // Check if b follows a
  5404. if ( cur ) {
  5405. while ( (cur = cur.nextSibling) ) {
  5406. if ( cur === b ) {
  5407. return -1;
  5408. }
  5409. }
  5410. }
  5411. return a ? 1 : -1;
  5412. }
  5413. /**
  5414. * Returns a function to use in pseudos for input types
  5415. * @param {String} type
  5416. */
  5417. function createInputPseudo( type ) {
  5418. return function( elem ) {
  5419. var name = elem.nodeName.toLowerCase();
  5420. return name === "input" && elem.type === type;
  5421. };
  5422. }
  5423. /**
  5424. * Returns a function to use in pseudos for buttons
  5425. * @param {String} type
  5426. */
  5427. function createButtonPseudo( type ) {
  5428. return function( elem ) {
  5429. var name = elem.nodeName.toLowerCase();
  5430. return (name === "input" || name === "button") && elem.type === type;
  5431. };
  5432. }
  5433. /**
  5434. * Returns a function to use in pseudos for positionals
  5435. * @param {Function} fn
  5436. */
  5437. function createPositionalPseudo( fn ) {
  5438. return markFunction(function( argument ) {
  5439. argument = +argument;
  5440. return markFunction(function( seed, matches ) {
  5441. var j,
  5442. matchIndexes = fn( [], seed.length, argument ),
  5443. i = matchIndexes.length;
  5444. // Match elements found at the specified indexes
  5445. while ( i-- ) {
  5446. if ( seed[ (j = matchIndexes[i]) ] ) {
  5447. seed[j] = !(matches[j] = seed[j]);
  5448. }
  5449. }
  5450. });
  5451. });
  5452. }
  5453. /**
  5454. * Checks a node for validity as a Sizzle context
  5455. * @param {Element|Object=} context
  5456. * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
  5457. */
  5458. function testContext( context ) {
  5459. return context && typeof context.getElementsByTagName !== "undefined" && context;
  5460. }
  5461. // Expose support vars for convenience
  5462. support = Sizzle.support = {};
  5463. /**
  5464. * Detects XML nodes
  5465. * @param {Element|Object} elem An element or a document
  5466. * @returns {Boolean} True iff elem is a non-HTML XML node
  5467. */
  5468. isXML = Sizzle.isXML = function( elem ) {
  5469. // documentElement is verified for cases where it doesn't yet exist
  5470. // (such as loading iframes in IE - #4833)
  5471. var documentElement = elem && (elem.ownerDocument || elem).documentElement;
  5472. return documentElement ? documentElement.nodeName !== "HTML" : false;
  5473. };
  5474. /**
  5475. * Sets document-related variables once based on the current document
  5476. * @param {Element|Object} [doc] An element or document object to use to set the document
  5477. * @returns {Object} Returns the current document
  5478. */
  5479. setDocument = Sizzle.setDocument = function( node ) {
  5480. var hasCompare, parent,
  5481. doc = node ? node.ownerDocument || node : preferredDoc;
  5482. // If no document and documentElement is available, return
  5483. if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
  5484. return document;
  5485. }
  5486. // Set our document
  5487. document = doc;
  5488. docElem = doc.documentElement;
  5489. parent = doc.defaultView;
  5490. // Support: IE>8
  5491. // If iframe document is assigned to "document" variable and if iframe has been reloaded,
  5492. // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
  5493. // IE6-8 do not support the defaultView property so parent will be undefined
  5494. if ( parent && parent !== parent.top ) {
  5495. // IE11 does not have attachEvent, so all must suffer
  5496. if ( parent.addEventListener ) {
  5497. parent.addEventListener( "unload", unloadHandler, false );
  5498. } else if ( parent.attachEvent ) {
  5499. parent.attachEvent( "onunload", unloadHandler );
  5500. }
  5501. }
  5502. /* Support tests
  5503. ---------------------------------------------------------------------- */
  5504. documentIsHTML = !isXML( doc );
  5505. /* Attributes
  5506. ---------------------------------------------------------------------- */
  5507. // Support: IE<8
  5508. // Verify that getAttribute really returns attributes and not properties
  5509. // (excepting IE8 booleans)
  5510. support.attributes = assert(function( div ) {
  5511. div.className = "i";
  5512. return !div.getAttribute("className");
  5513. });
  5514. /* getElement(s)By*
  5515. ---------------------------------------------------------------------- */
  5516. // Check if getElementsByTagName("*") returns only elements
  5517. support.getElementsByTagName = assert(function( div ) {
  5518. div.appendChild( doc.createComment("") );
  5519. return !div.getElementsByTagName("*").length;
  5520. });
  5521. // Support: IE<9
  5522. support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
  5523. // Support: IE<10
  5524. // Check if getElementById returns elements by name
  5525. // The broken getElementById methods don't pick up programatically-set names,
  5526. // so use a roundabout getElementsByName test
  5527. support.getById = assert(function( div ) {
  5528. docElem.appendChild( div ).id = expando;
  5529. return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
  5530. });
  5531. // ID find and filter
  5532. if ( support.getById ) {
  5533. Expr.find["ID"] = function( id, context ) {
  5534. if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
  5535. var m = context.getElementById( id );
  5536. // Check parentNode to catch when Blackberry 4.6 returns
  5537. // nodes that are no longer in the document #6963
  5538. return m && m.parentNode ? [ m ] : [];
  5539. }
  5540. };
  5541. Expr.filter["ID"] = function( id ) {
  5542. var attrId = id.replace( runescape, funescape );
  5543. return function( elem ) {
  5544. return elem.getAttribute("id") === attrId;
  5545. };
  5546. };
  5547. } else {
  5548. // Support: IE6/7
  5549. // getElementById is not reliable as a find shortcut
  5550. delete Expr.find["ID"];
  5551. Expr.filter["ID"] = function( id ) {
  5552. var attrId = id.replace( runescape, funescape );
  5553. return function( elem ) {
  5554. var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
  5555. return node && node.value === attrId;
  5556. };
  5557. };
  5558. }
  5559. // Tag
  5560. Expr.find["TAG"] = support.getElementsByTagName ?
  5561. function( tag, context ) {
  5562. if ( typeof context.getElementsByTagName !== "undefined" ) {
  5563. return context.getElementsByTagName( tag );
  5564. // DocumentFragment nodes don't have gEBTN
  5565. } else if ( support.qsa ) {
  5566. return context.querySelectorAll( tag );
  5567. }
  5568. } :
  5569. function( tag, context ) {
  5570. var elem,
  5571. tmp = [],
  5572. i = 0,
  5573. // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
  5574. results = context.getElementsByTagName( tag );
  5575. // Filter out possible comments
  5576. if ( tag === "*" ) {
  5577. while ( (elem = results[i++]) ) {
  5578. if ( elem.nodeType === 1 ) {
  5579. tmp.push( elem );
  5580. }
  5581. }
  5582. return tmp;
  5583. }
  5584. return results;
  5585. };
  5586. // Class
  5587. Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
  5588. if ( documentIsHTML ) {
  5589. return context.getElementsByClassName( className );
  5590. }
  5591. };
  5592. /* QSA/matchesSelector
  5593. ---------------------------------------------------------------------- */
  5594. // QSA and matchesSelector support
  5595. // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
  5596. rbuggyMatches = [];
  5597. // qSa(:focus) reports false when true (Chrome 21)
  5598. // We allow this because of a bug in IE8/9 that throws an error
  5599. // whenever `document.activeElement` is accessed on an iframe
  5600. // So, we allow :focus to pass through QSA all the time to avoid the IE error
  5601. // See http://bugs.jquery.com/ticket/13378
  5602. rbuggyQSA = [];
  5603. if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
  5604. // Build QSA regex
  5605. // Regex strategy adopted from Diego Perini
  5606. assert(function( div ) {
  5607. // Select is set to empty string on purpose
  5608. // This is to test IE's treatment of not explicitly
  5609. // setting a boolean content attribute,
  5610. // since its presence should be enough
  5611. // http://bugs.jquery.com/ticket/12359
  5612. docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
  5613. "<select id='" + expando + "-\f]' msallowcapture=''>" +
  5614. "<option selected=''></option></select>";
  5615. // Support: IE8, Opera 11-12.16
  5616. // Nothing should be selected when empty strings follow ^= or $= or *=
  5617. // The test attribute must be unknown in Opera but "safe" for WinRT
  5618. // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
  5619. if ( div.querySelectorAll("[msallowcapture^='']").length ) {
  5620. rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
  5621. }
  5622. // Support: IE8
  5623. // Boolean attributes and "value" are not treated correctly
  5624. if ( !div.querySelectorAll("[selected]").length ) {
  5625. rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
  5626. }
  5627. // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
  5628. if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
  5629. rbuggyQSA.push("~=");
  5630. }
  5631. // Webkit/Opera - :checked should return selected option elements
  5632. // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  5633. // IE8 throws error here and will not see later tests
  5634. if ( !div.querySelectorAll(":checked").length ) {
  5635. rbuggyQSA.push(":checked");
  5636. }
  5637. // Support: Safari 8+, iOS 8+
  5638. // https://bugs.webkit.org/show_bug.cgi?id=136851
  5639. // In-page `selector#id sibing-combinator selector` fails
  5640. if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
  5641. rbuggyQSA.push(".#.+[+~]");
  5642. }
  5643. });
  5644. assert(function( div ) {
  5645. // Support: Windows 8 Native Apps
  5646. // The type and name attributes are restricted during .innerHTML assignment
  5647. var input = doc.createElement("input");
  5648. input.setAttribute( "type", "hidden" );
  5649. div.appendChild( input ).setAttribute( "name", "D" );
  5650. // Support: IE8
  5651. // Enforce case-sensitivity of name attribute
  5652. if ( div.querySelectorAll("[name=d]").length ) {
  5653. rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
  5654. }
  5655. // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
  5656. // IE8 throws error here and will not see later tests
  5657. if ( !div.querySelectorAll(":enabled").length ) {
  5658. rbuggyQSA.push( ":enabled", ":disabled" );
  5659. }
  5660. // Opera 10-11 does not throw on post-comma invalid pseudos
  5661. div.querySelectorAll("*,:x");
  5662. rbuggyQSA.push(",.*:");
  5663. });
  5664. }
  5665. if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
  5666. docElem.webkitMatchesSelector ||
  5667. docElem.mozMatchesSelector ||
  5668. docElem.oMatchesSelector ||
  5669. docElem.msMatchesSelector) )) ) {
  5670. assert(function( div ) {
  5671. // Check to see if it's possible to do matchesSelector
  5672. // on a disconnected node (IE 9)
  5673. support.disconnectedMatch = matches.call( div, "div" );
  5674. // This should fail with an exception
  5675. // Gecko does not error, returns false instead
  5676. matches.call( div, "[s!='']:x" );
  5677. rbuggyMatches.push( "!=", pseudos );
  5678. });
  5679. }
  5680. rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
  5681. rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
  5682. /* Contains
  5683. ---------------------------------------------------------------------- */
  5684. hasCompare = rnative.test( docElem.compareDocumentPosition );
  5685. // Element contains another
  5686. // Purposefully does not implement inclusive descendent
  5687. // As in, an element does not contain itself
  5688. contains = hasCompare || rnative.test( docElem.contains ) ?
  5689. function( a, b ) {
  5690. var adown = a.nodeType === 9 ? a.documentElement : a,
  5691. bup = b && b.parentNode;
  5692. return a === bup || !!( bup && bup.nodeType === 1 && (
  5693. adown.contains ?
  5694. adown.contains( bup ) :
  5695. a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
  5696. ));
  5697. } :
  5698. function( a, b ) {
  5699. if ( b ) {
  5700. while ( (b = b.parentNode) ) {
  5701. if ( b === a ) {
  5702. return true;
  5703. }
  5704. }
  5705. }
  5706. return false;
  5707. };
  5708. /* Sorting
  5709. ---------------------------------------------------------------------- */
  5710. // Document order sorting
  5711. sortOrder = hasCompare ?
  5712. function( a, b ) {
  5713. // Flag for duplicate removal
  5714. if ( a === b ) {
  5715. hasDuplicate = true;
  5716. return 0;
  5717. }
  5718. // Sort on method existence if only one input has compareDocumentPosition
  5719. var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
  5720. if ( compare ) {
  5721. return compare;
  5722. }
  5723. // Calculate position if both inputs belong to the same document
  5724. compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
  5725. a.compareDocumentPosition( b ) :
  5726. // Otherwise we know they are disconnected
  5727. 1;
  5728. // Disconnected nodes
  5729. if ( compare & 1 ||
  5730. (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
  5731. // Choose the first element that is related to our preferred document
  5732. if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
  5733. return -1;
  5734. }
  5735. if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
  5736. return 1;
  5737. }
  5738. // Maintain original order
  5739. return sortInput ?
  5740. ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  5741. 0;
  5742. }
  5743. return compare & 4 ? -1 : 1;
  5744. } :
  5745. function( a, b ) {
  5746. // Exit early if the nodes are identical
  5747. if ( a === b ) {
  5748. hasDuplicate = true;
  5749. return 0;
  5750. }
  5751. var cur,
  5752. i = 0,
  5753. aup = a.parentNode,
  5754. bup = b.parentNode,
  5755. ap = [ a ],
  5756. bp = [ b ];
  5757. // Parentless nodes are either documents or disconnected
  5758. if ( !aup || !bup ) {
  5759. return a === doc ? -1 :
  5760. b === doc ? 1 :
  5761. aup ? -1 :
  5762. bup ? 1 :
  5763. sortInput ?
  5764. ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  5765. 0;
  5766. // If the nodes are siblings, we can do a quick check
  5767. } else if ( aup === bup ) {
  5768. return siblingCheck( a, b );
  5769. }
  5770. // Otherwise we need full lists of their ancestors for comparison
  5771. cur = a;
  5772. while ( (cur = cur.parentNode) ) {
  5773. ap.unshift( cur );
  5774. }
  5775. cur = b;
  5776. while ( (cur = cur.parentNode) ) {
  5777. bp.unshift( cur );
  5778. }
  5779. // Walk down the tree looking for a discrepancy
  5780. while ( ap[i] === bp[i] ) {
  5781. i++;
  5782. }
  5783. return i ?
  5784. // Do a sibling check if the nodes have a common ancestor
  5785. siblingCheck( ap[i], bp[i] ) :
  5786. // Otherwise nodes in our document sort first
  5787. ap[i] === preferredDoc ? -1 :
  5788. bp[i] === preferredDoc ? 1 :
  5789. 0;
  5790. };
  5791. return doc;
  5792. };
  5793. Sizzle.matches = function( expr, elements ) {
  5794. return Sizzle( expr, null, null, elements );
  5795. };
  5796. Sizzle.matchesSelector = function( elem, expr ) {
  5797. // Set document vars if needed
  5798. if ( ( elem.ownerDocument || elem ) !== document ) {
  5799. setDocument( elem );
  5800. }
  5801. // Make sure that attribute selectors are quoted
  5802. expr = expr.replace( rattributeQuotes, "='$1']" );
  5803. if ( support.matchesSelector && documentIsHTML &&
  5804. ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
  5805. ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
  5806. try {
  5807. var ret = matches.call( elem, expr );
  5808. // IE 9's matchesSelector returns false on disconnected nodes
  5809. if ( ret || support.disconnectedMatch ||
  5810. // As well, disconnected nodes are said to be in a document
  5811. // fragment in IE 9
  5812. elem.document && elem.document.nodeType !== 11 ) {
  5813. return ret;
  5814. }
  5815. } catch (e) {}
  5816. }
  5817. return Sizzle( expr, document, null, [ elem ] ).length > 0;
  5818. };
  5819. Sizzle.contains = function( context, elem ) {
  5820. // Set document vars if needed
  5821. if ( ( context.ownerDocument || context ) !== document ) {
  5822. setDocument( context );
  5823. }
  5824. return contains( context, elem );
  5825. };
  5826. Sizzle.attr = function( elem, name ) {
  5827. // Set document vars if needed
  5828. if ( ( elem.ownerDocument || elem ) !== document ) {
  5829. setDocument( elem );
  5830. }
  5831. var fn = Expr.attrHandle[ name.toLowerCase() ],
  5832. // Don't get fooled by Object.prototype properties (jQuery #13807)
  5833. val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
  5834. fn( elem, name, !documentIsHTML ) :
  5835. undefined;
  5836. return val !== undefined ?
  5837. val :
  5838. support.attributes || !documentIsHTML ?
  5839. elem.getAttribute( name ) :
  5840. (val = elem.getAttributeNode(name)) && val.specified ?
  5841. val.value :
  5842. null;
  5843. };
  5844. Sizzle.error = function( msg ) {
  5845. throw new Error( "Syntax error, unrecognized expression: " + msg );
  5846. };
  5847. /**
  5848. * Document sorting and removing duplicates
  5849. * @param {ArrayLike} results
  5850. */
  5851. Sizzle.uniqueSort = function( results ) {
  5852. var elem,
  5853. duplicates = [],
  5854. j = 0,
  5855. i = 0;
  5856. // Unless we *know* we can detect duplicates, assume their presence
  5857. hasDuplicate = !support.detectDuplicates;
  5858. sortInput = !support.sortStable && results.slice( 0 );
  5859. results.sort( sortOrder );
  5860. if ( hasDuplicate ) {
  5861. while ( (elem = results[i++]) ) {
  5862. if ( elem === results[ i ] ) {
  5863. j = duplicates.push( i );
  5864. }
  5865. }
  5866. while ( j-- ) {
  5867. results.splice( duplicates[ j ], 1 );
  5868. }
  5869. }
  5870. // Clear input after sorting to release objects
  5871. // See https://github.com/jquery/sizzle/pull/225
  5872. sortInput = null;
  5873. return results;
  5874. };
  5875. /**
  5876. * Utility function for retrieving the text value of an array of DOM nodes
  5877. * @param {Array|Element} elem
  5878. */
  5879. getText = Sizzle.getText = function( elem ) {
  5880. var node,
  5881. ret = "",
  5882. i = 0,
  5883. nodeType = elem.nodeType;
  5884. if ( !nodeType ) {
  5885. // If no nodeType, this is expected to be an array
  5886. while ( (node = elem[i++]) ) {
  5887. // Do not traverse comment nodes
  5888. ret += getText( node );
  5889. }
  5890. } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
  5891. // Use textContent for elements
  5892. // innerText usage removed for consistency of new lines (jQuery #11153)
  5893. if ( typeof elem.textContent === "string" ) {
  5894. return elem.textContent;
  5895. } else {
  5896. // Traverse its children
  5897. for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  5898. ret += getText( elem );
  5899. }
  5900. }
  5901. } else if ( nodeType === 3 || nodeType === 4 ) {
  5902. return elem.nodeValue;
  5903. }
  5904. // Do not include comment or processing instruction nodes
  5905. return ret;
  5906. };
  5907. Expr = Sizzle.selectors = {
  5908. // Can be adjusted by the user
  5909. cacheLength: 50,
  5910. createPseudo: markFunction,
  5911. match: matchExpr,
  5912. attrHandle: {},
  5913. find: {},
  5914. relative: {
  5915. ">": { dir: "parentNode", first: true },
  5916. " ": { dir: "parentNode" },
  5917. "+": { dir: "previousSibling", first: true },
  5918. "~": { dir: "previousSibling" }
  5919. },
  5920. preFilter: {
  5921. "ATTR": function( match ) {
  5922. match[1] = match[1].replace( runescape, funescape );
  5923. // Move the given value to match[3] whether quoted or unquoted
  5924. match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
  5925. if ( match[2] === "~=" ) {
  5926. match[3] = " " + match[3] + " ";
  5927. }
  5928. return match.slice( 0, 4 );
  5929. },
  5930. "CHILD": function( match ) {
  5931. /* matches from matchExpr["CHILD"]
  5932. 1 type (only|nth|...)
  5933. 2 what (child|of-type)
  5934. 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
  5935. 4 xn-component of xn+y argument ([+-]?\d*n|)
  5936. 5 sign of xn-component
  5937. 6 x of xn-component
  5938. 7 sign of y-component
  5939. 8 y of y-component
  5940. */
  5941. match[1] = match[1].toLowerCase();
  5942. if ( match[1].slice( 0, 3 ) === "nth" ) {
  5943. // nth-* requires argument
  5944. if ( !match[3] ) {
  5945. Sizzle.error( match[0] );
  5946. }
  5947. // numeric x and y parameters for Expr.filter.CHILD
  5948. // remember that false/true cast respectively to 0/1
  5949. match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
  5950. match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
  5951. // other types prohibit arguments
  5952. } else if ( match[3] ) {
  5953. Sizzle.error( match[0] );
  5954. }
  5955. return match;
  5956. },
  5957. "PSEUDO": function( match ) {
  5958. var excess,
  5959. unquoted = !match[6] && match[2];
  5960. if ( matchExpr["CHILD"].test( match[0] ) ) {
  5961. return null;
  5962. }
  5963. // Accept quoted arguments as-is
  5964. if ( match[3] ) {
  5965. match[2] = match[4] || match[5] || "";
  5966. // Strip excess characters from unquoted arguments
  5967. } else if ( unquoted && rpseudo.test( unquoted ) &&
  5968. // Get excess from tokenize (recursively)
  5969. (excess = tokenize( unquoted, true )) &&
  5970. // advance to the next closing parenthesis
  5971. (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
  5972. // excess is a negative index
  5973. match[0] = match[0].slice( 0, excess );
  5974. match[2] = unquoted.slice( 0, excess );
  5975. }
  5976. // Return only captures needed by the pseudo filter method (type and argument)
  5977. return match.slice( 0, 3 );
  5978. }
  5979. },
  5980. filter: {
  5981. "TAG": function( nodeNameSelector ) {
  5982. var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
  5983. return nodeNameSelector === "*" ?
  5984. function() { return true; } :
  5985. function( elem ) {
  5986. return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
  5987. };
  5988. },
  5989. "CLASS": function( className ) {
  5990. var pattern = classCache[ className + " " ];
  5991. return pattern ||
  5992. (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
  5993. classCache( className, function( elem ) {
  5994. return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
  5995. });
  5996. },
  5997. "ATTR": function( name, operator, check ) {
  5998. return function( elem ) {
  5999. var result = Sizzle.attr( elem, name );
  6000. if ( result == null ) {
  6001. return operator === "!=";
  6002. }
  6003. if ( !operator ) {
  6004. return true;
  6005. }
  6006. result += "";
  6007. return operator === "=" ? result === check :
  6008. operator === "!=" ? result !== check :
  6009. operator === "^=" ? check && result.indexOf( check ) === 0 :
  6010. operator === "*=" ? check && result.indexOf( check ) > -1 :
  6011. operator === "$=" ? check && result.slice( -check.length ) === check :
  6012. operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
  6013. operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
  6014. false;
  6015. };
  6016. },
  6017. "CHILD": function( type, what, argument, first, last ) {
  6018. var simple = type.slice( 0, 3 ) !== "nth",
  6019. forward = type.slice( -4 ) !== "last",
  6020. ofType = what === "of-type";
  6021. return first === 1 && last === 0 ?
  6022. // Shortcut for :nth-*(n)
  6023. function( elem ) {
  6024. return !!elem.parentNode;
  6025. } :
  6026. function( elem, context, xml ) {
  6027. var cache, outerCache, node, diff, nodeIndex, start,
  6028. dir = simple !== forward ? "nextSibling" : "previousSibling",
  6029. parent = elem.parentNode,
  6030. name = ofType && elem.nodeName.toLowerCase(),
  6031. useCache = !xml && !ofType;
  6032. if ( parent ) {
  6033. // :(first|last|only)-(child|of-type)
  6034. if ( simple ) {
  6035. while ( dir ) {
  6036. node = elem;
  6037. while ( (node = node[ dir ]) ) {
  6038. if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
  6039. return false;
  6040. }
  6041. }
  6042. // Reverse direction for :only-* (if we haven't yet done so)
  6043. start = dir = type === "only" && !start && "nextSibling";
  6044. }
  6045. return true;
  6046. }
  6047. start = [ forward ? parent.firstChild : parent.lastChild ];
  6048. // non-xml :nth-child(...) stores cache data on `parent`
  6049. if ( forward && useCache ) {
  6050. // Seek `elem` from a previously-cached index
  6051. outerCache = parent[ expando ] || (parent[ expando ] = {});
  6052. cache = outerCache[ type ] || [];
  6053. nodeIndex = cache[0] === dirruns && cache[1];
  6054. diff = cache[0] === dirruns && cache[2];
  6055. node = nodeIndex && parent.childNodes[ nodeIndex ];
  6056. while ( (node = ++nodeIndex && node && node[ dir ] ||
  6057. // Fallback to seeking `elem` from the start
  6058. (diff = nodeIndex = 0) || start.pop()) ) {
  6059. // When found, cache indexes on `parent` and break
  6060. if ( node.nodeType === 1 && ++diff && node === elem ) {
  6061. outerCache[ type ] = [ dirruns, nodeIndex, diff ];
  6062. break;
  6063. }
  6064. }
  6065. // Use previously-cached element index if available
  6066. } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
  6067. diff = cache[1];
  6068. // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
  6069. } else {
  6070. // Use the same loop as above to seek `elem` from the start
  6071. while ( (node = ++nodeIndex && node && node[ dir ] ||
  6072. (diff = nodeIndex = 0) || start.pop()) ) {
  6073. if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
  6074. // Cache the index of each encountered element
  6075. if ( useCache ) {
  6076. (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
  6077. }
  6078. if ( node === elem ) {
  6079. break;
  6080. }
  6081. }
  6082. }
  6083. }
  6084. // Incorporate the offset, then check against cycle size
  6085. diff -= last;
  6086. return diff === first || ( diff % first === 0 && diff / first >= 0 );
  6087. }
  6088. };
  6089. },
  6090. "PSEUDO": function( pseudo, argument ) {
  6091. // pseudo-class names are case-insensitive
  6092. // http://www.w3.org/TR/selectors/#pseudo-classes
  6093. // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
  6094. // Remember that setFilters inherits from pseudos
  6095. var args,
  6096. fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
  6097. Sizzle.error( "unsupported pseudo: " + pseudo );
  6098. // The user may use createPseudo to indicate that
  6099. // arguments are needed to create the filter function
  6100. // just as Sizzle does
  6101. if ( fn[ expando ] ) {
  6102. return fn( argument );
  6103. }
  6104. // But maintain support for old signatures
  6105. if ( fn.length > 1 ) {
  6106. args = [ pseudo, pseudo, "", argument ];
  6107. return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
  6108. markFunction(function( seed, matches ) {
  6109. var idx,
  6110. matched = fn( seed, argument ),
  6111. i = matched.length;
  6112. while ( i-- ) {
  6113. idx = indexOf( seed, matched[i] );
  6114. seed[ idx ] = !( matches[ idx ] = matched[i] );
  6115. }
  6116. }) :
  6117. function( elem ) {
  6118. return fn( elem, 0, args );
  6119. };
  6120. }
  6121. return fn;
  6122. }
  6123. },
  6124. pseudos: {
  6125. // Potentially complex pseudos
  6126. "not": markFunction(function( selector ) {
  6127. // Trim the selector passed to compile
  6128. // to avoid treating leading and trailing
  6129. // spaces as combinators
  6130. var input = [],
  6131. results = [],
  6132. matcher = compile( selector.replace( rtrim, "$1" ) );
  6133. return matcher[ expando ] ?
  6134. markFunction(function( seed, matches, context, xml ) {
  6135. var elem,
  6136. unmatched = matcher( seed, null, xml, [] ),
  6137. i = seed.length;
  6138. // Match elements unmatched by `matcher`
  6139. while ( i-- ) {
  6140. if ( (elem = unmatched[i]) ) {
  6141. seed[i] = !(matches[i] = elem);
  6142. }
  6143. }
  6144. }) :
  6145. function( elem, context, xml ) {
  6146. input[0] = elem;
  6147. matcher( input, null, xml, results );
  6148. // Don't keep the element (issue #299)
  6149. input[0] = null;
  6150. return !results.pop();
  6151. };
  6152. }),
  6153. "has": markFunction(function( selector ) {
  6154. return function( elem ) {
  6155. return Sizzle( selector, elem ).length > 0;
  6156. };
  6157. }),
  6158. "contains": markFunction(function( text ) {
  6159. text = text.replace( runescape, funescape );
  6160. return function( elem ) {
  6161. return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
  6162. };
  6163. }),
  6164. // "Whether an element is represented by a :lang() selector
  6165. // is based solely on the element's language value
  6166. // being equal to the identifier C,
  6167. // or beginning with the identifier C immediately followed by "-".
  6168. // The matching of C against the element's language value is performed case-insensitively.
  6169. // The identifier C does not have to be a valid language name."
  6170. // http://www.w3.org/TR/selectors/#lang-pseudo
  6171. "lang": markFunction( function( lang ) {
  6172. // lang value must be a valid identifier
  6173. if ( !ridentifier.test(lang || "") ) {
  6174. Sizzle.error( "unsupported lang: " + lang );
  6175. }
  6176. lang = lang.replace( runescape, funescape ).toLowerCase();
  6177. return function( elem ) {
  6178. var elemLang;
  6179. do {
  6180. if ( (elemLang = documentIsHTML ?
  6181. elem.lang :
  6182. elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
  6183. elemLang = elemLang.toLowerCase();
  6184. return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
  6185. }
  6186. } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
  6187. return false;
  6188. };
  6189. }),
  6190. // Miscellaneous
  6191. "target": function( elem ) {
  6192. var hash = window.location && window.location.hash;
  6193. return hash && hash.slice( 1 ) === elem.id;
  6194. },
  6195. "root": function( elem ) {
  6196. return elem === docElem;
  6197. },
  6198. "focus": function( elem ) {
  6199. return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
  6200. },
  6201. // Boolean properties
  6202. "enabled": function( elem ) {
  6203. return elem.disabled === false;
  6204. },
  6205. "disabled": function( elem ) {
  6206. return elem.disabled === true;
  6207. },
  6208. "checked": function( elem ) {
  6209. // In CSS3, :checked should return both checked and selected elements
  6210. // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  6211. var nodeName = elem.nodeName.toLowerCase();
  6212. return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
  6213. },
  6214. "selected": function( elem ) {
  6215. // Accessing this property makes selected-by-default
  6216. // options in Safari work properly
  6217. if ( elem.parentNode ) {
  6218. elem.parentNode.selectedIndex;
  6219. }
  6220. return elem.selected === true;
  6221. },
  6222. // Contents
  6223. "empty": function( elem ) {
  6224. // http://www.w3.org/TR/selectors/#empty-pseudo
  6225. // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
  6226. // but not by others (comment: 8; processing instruction: 7; etc.)
  6227. // nodeType < 6 works because attributes (2) do not appear as children
  6228. for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  6229. if ( elem.nodeType < 6 ) {
  6230. return false;
  6231. }
  6232. }
  6233. return true;
  6234. },
  6235. "parent": function( elem ) {
  6236. return !Expr.pseudos["empty"]( elem );
  6237. },
  6238. // Element/input types
  6239. "header": function( elem ) {
  6240. return rheader.test( elem.nodeName );
  6241. },
  6242. "input": function( elem ) {
  6243. return rinputs.test( elem.nodeName );
  6244. },
  6245. "button": function( elem ) {
  6246. var name = elem.nodeName.toLowerCase();
  6247. return name === "input" && elem.type === "button" || name === "button";
  6248. },
  6249. "text": function( elem ) {
  6250. var attr;
  6251. return elem.nodeName.toLowerCase() === "input" &&
  6252. elem.type === "text" &&
  6253. // Support: IE<8
  6254. // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
  6255. ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
  6256. },
  6257. // Position-in-collection
  6258. "first": createPositionalPseudo(function() {
  6259. return [ 0 ];
  6260. }),
  6261. "last": createPositionalPseudo(function( matchIndexes, length ) {
  6262. return [ length - 1 ];
  6263. }),
  6264. "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
  6265. return [ argument < 0 ? argument + length : argument ];
  6266. }),
  6267. "even": createPositionalPseudo(function( matchIndexes, length ) {
  6268. var i = 0;
  6269. for ( ; i < length; i += 2 ) {
  6270. matchIndexes.push( i );
  6271. }
  6272. return matchIndexes;
  6273. }),
  6274. "odd": createPositionalPseudo(function( matchIndexes, length ) {
  6275. var i = 1;
  6276. for ( ; i < length; i += 2 ) {
  6277. matchIndexes.push( i );
  6278. }
  6279. return matchIndexes;
  6280. }),
  6281. "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  6282. var i = argument < 0 ? argument + length : argument;
  6283. for ( ; --i >= 0; ) {
  6284. matchIndexes.push( i );
  6285. }
  6286. return matchIndexes;
  6287. }),
  6288. "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  6289. var i = argument < 0 ? argument + length : argument;
  6290. for ( ; ++i < length; ) {
  6291. matchIndexes.push( i );
  6292. }
  6293. return matchIndexes;
  6294. })
  6295. }
  6296. };
  6297. Expr.pseudos["nth"] = Expr.pseudos["eq"];
  6298. // Add button/input type pseudos
  6299. for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
  6300. Expr.pseudos[ i ] = createInputPseudo( i );
  6301. }
  6302. for ( i in { submit: true, reset: true } ) {
  6303. Expr.pseudos[ i ] = createButtonPseudo( i );
  6304. }
  6305. // Easy API for creating new setFilters
  6306. function setFilters() {}
  6307. setFilters.prototype = Expr.filters = Expr.pseudos;
  6308. Expr.setFilters = new setFilters();
  6309. tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
  6310. var matched, match, tokens, type,
  6311. soFar, groups, preFilters,
  6312. cached = tokenCache[ selector + " " ];
  6313. if ( cached ) {
  6314. return parseOnly ? 0 : cached.slice( 0 );
  6315. }
  6316. soFar = selector;
  6317. groups = [];
  6318. preFilters = Expr.preFilter;
  6319. while ( soFar ) {
  6320. // Comma and first run
  6321. if ( !matched || (match = rcomma.exec( soFar )) ) {
  6322. if ( match ) {
  6323. // Don't consume trailing commas as valid
  6324. soFar = soFar.slice( match[0].length ) || soFar;
  6325. }
  6326. groups.push( (tokens = []) );
  6327. }
  6328. matched = false;
  6329. // Combinators
  6330. if ( (match = rcombinators.exec( soFar )) ) {
  6331. matched = match.shift();
  6332. tokens.push({
  6333. value: matched,
  6334. // Cast descendant combinators to space
  6335. type: match[0].replace( rtrim, " " )
  6336. });
  6337. soFar = soFar.slice( matched.length );
  6338. }
  6339. // Filters
  6340. for ( type in Expr.filter ) {
  6341. if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
  6342. (match = preFilters[ type ]( match ))) ) {
  6343. matched = match.shift();
  6344. tokens.push({
  6345. value: matched,
  6346. type: type,
  6347. matches: match
  6348. });
  6349. soFar = soFar.slice( matched.length );
  6350. }
  6351. }
  6352. if ( !matched ) {
  6353. break;
  6354. }
  6355. }
  6356. // Return the length of the invalid excess
  6357. // if we're just parsing
  6358. // Otherwise, throw an error or return tokens
  6359. return parseOnly ?
  6360. soFar.length :
  6361. soFar ?
  6362. Sizzle.error( selector ) :
  6363. // Cache the tokens
  6364. tokenCache( selector, groups ).slice( 0 );
  6365. };
  6366. function toSelector( tokens ) {
  6367. var i = 0,
  6368. len = tokens.length,
  6369. selector = "";
  6370. for ( ; i < len; i++ ) {
  6371. selector += tokens[i].value;
  6372. }
  6373. return selector;
  6374. }
  6375. function addCombinator( matcher, combinator, base ) {
  6376. var dir = combinator.dir,
  6377. checkNonElements = base && dir === "parentNode",
  6378. doneName = done++;
  6379. return combinator.first ?
  6380. // Check against closest ancestor/preceding element
  6381. function( elem, context, xml ) {
  6382. while ( (elem = elem[ dir ]) ) {
  6383. if ( elem.nodeType === 1 || checkNonElements ) {
  6384. return matcher( elem, context, xml );
  6385. }
  6386. }
  6387. } :
  6388. // Check against all ancestor/preceding elements
  6389. function( elem, context, xml ) {
  6390. var oldCache, outerCache,
  6391. newCache = [ dirruns, doneName ];
  6392. // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
  6393. if ( xml ) {
  6394. while ( (elem = elem[ dir ]) ) {
  6395. if ( elem.nodeType === 1 || checkNonElements ) {
  6396. if ( matcher( elem, context, xml ) ) {
  6397. return true;
  6398. }
  6399. }
  6400. }
  6401. } else {
  6402. while ( (elem = elem[ dir ]) ) {
  6403. if ( elem.nodeType === 1 || checkNonElements ) {
  6404. outerCache = elem[ expando ] || (elem[ expando ] = {});
  6405. if ( (oldCache = outerCache[ dir ]) &&
  6406. oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
  6407. // Assign to newCache so results back-propagate to previous elements
  6408. return (newCache[ 2 ] = oldCache[ 2 ]);
  6409. } else {
  6410. // Reuse newcache so results back-propagate to previous elements
  6411. outerCache[ dir ] = newCache;
  6412. // A match means we're done; a fail means we have to keep checking
  6413. if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
  6414. return true;
  6415. }
  6416. }
  6417. }
  6418. }
  6419. }
  6420. };
  6421. }
  6422. function elementMatcher( matchers ) {
  6423. return matchers.length > 1 ?
  6424. function( elem, context, xml ) {
  6425. var i = matchers.length;
  6426. while ( i-- ) {
  6427. if ( !matchers[i]( elem, context, xml ) ) {
  6428. return false;
  6429. }
  6430. }
  6431. return true;
  6432. } :
  6433. matchers[0];
  6434. }
  6435. function multipleContexts( selector, contexts, results ) {
  6436. var i = 0,
  6437. len = contexts.length;
  6438. for ( ; i < len; i++ ) {
  6439. Sizzle( selector, contexts[i], results );
  6440. }
  6441. return results;
  6442. }
  6443. function condense( unmatched, map, filter, context, xml ) {
  6444. var elem,
  6445. newUnmatched = [],
  6446. i = 0,
  6447. len = unmatched.length,
  6448. mapped = map != null;
  6449. for ( ; i < len; i++ ) {
  6450. if ( (elem = unmatched[i]) ) {
  6451. if ( !filter || filter( elem, context, xml ) ) {
  6452. newUnmatched.push( elem );
  6453. if ( mapped ) {
  6454. map.push( i );
  6455. }
  6456. }
  6457. }
  6458. }
  6459. return newUnmatched;
  6460. }
  6461. function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
  6462. if ( postFilter && !postFilter[ expando ] ) {
  6463. postFilter = setMatcher( postFilter );
  6464. }
  6465. if ( postFinder && !postFinder[ expando ] ) {
  6466. postFinder = setMatcher( postFinder, postSelector );
  6467. }
  6468. return markFunction(function( seed, results, context, xml ) {
  6469. var temp, i, elem,
  6470. preMap = [],
  6471. postMap = [],
  6472. preexisting = results.length,
  6473. // Get initial elements from seed or context
  6474. elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
  6475. // Prefilter to get matcher input, preserving a map for seed-results synchronization
  6476. matcherIn = preFilter && ( seed || !selector ) ?
  6477. condense( elems, preMap, preFilter, context, xml ) :
  6478. elems,
  6479. matcherOut = matcher ?
  6480. // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
  6481. postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
  6482. // ...intermediate processing is necessary
  6483. [] :
  6484. // ...otherwise use results directly
  6485. results :
  6486. matcherIn;
  6487. // Find primary matches
  6488. if ( matcher ) {
  6489. matcher( matcherIn, matcherOut, context, xml );
  6490. }
  6491. // Apply postFilter
  6492. if ( postFilter ) {
  6493. temp = condense( matcherOut, postMap );
  6494. postFilter( temp, [], context, xml );
  6495. // Un-match failing elements by moving them back to matcherIn
  6496. i = temp.length;
  6497. while ( i-- ) {
  6498. if ( (elem = temp[i]) ) {
  6499. matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
  6500. }
  6501. }
  6502. }
  6503. if ( seed ) {
  6504. if ( postFinder || preFilter ) {
  6505. if ( postFinder ) {
  6506. // Get the final matcherOut by condensing this intermediate into postFinder contexts
  6507. temp = [];
  6508. i = matcherOut.length;
  6509. while ( i-- ) {
  6510. if ( (elem = matcherOut[i]) ) {
  6511. // Restore matcherIn since elem is not yet a final match
  6512. temp.push( (matcherIn[i] = elem) );
  6513. }
  6514. }
  6515. postFinder( null, (matcherOut = []), temp, xml );
  6516. }
  6517. // Move matched elements from seed to results to keep them synchronized
  6518. i = matcherOut.length;
  6519. while ( i-- ) {
  6520. if ( (elem = matcherOut[i]) &&
  6521. (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
  6522. seed[temp] = !(results[temp] = elem);
  6523. }
  6524. }
  6525. }
  6526. // Add elements to results, through postFinder if defined
  6527. } else {
  6528. matcherOut = condense(
  6529. matcherOut === results ?
  6530. matcherOut.splice( preexisting, matcherOut.length ) :
  6531. matcherOut
  6532. );
  6533. if ( postFinder ) {
  6534. postFinder( null, results, matcherOut, xml );
  6535. } else {
  6536. push.apply( results, matcherOut );
  6537. }
  6538. }
  6539. });
  6540. }
  6541. function matcherFromTokens( tokens ) {
  6542. var checkContext, matcher, j,
  6543. len = tokens.length,
  6544. leadingRelative = Expr.relative[ tokens[0].type ],
  6545. implicitRelative = leadingRelative || Expr.relative[" "],
  6546. i = leadingRelative ? 1 : 0,
  6547. // The foundational matcher ensures that elements are reachable from top-level context(s)
  6548. matchContext = addCombinator( function( elem ) {
  6549. return elem === checkContext;
  6550. }, implicitRelative, true ),
  6551. matchAnyContext = addCombinator( function( elem ) {
  6552. return indexOf( checkContext, elem ) > -1;
  6553. }, implicitRelative, true ),
  6554. matchers = [ function( elem, context, xml ) {
  6555. var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
  6556. (checkContext = context).nodeType ?
  6557. matchContext( elem, context, xml ) :
  6558. matchAnyContext( elem, context, xml ) );
  6559. // Avoid hanging onto element (issue #299)
  6560. checkContext = null;
  6561. return ret;
  6562. } ];
  6563. for ( ; i < len; i++ ) {
  6564. if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
  6565. matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
  6566. } else {
  6567. matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
  6568. // Return special upon seeing a positional matcher
  6569. if ( matcher[ expando ] ) {
  6570. // Find the next relative operator (if any) for proper handling
  6571. j = ++i;
  6572. for ( ; j < len; j++ ) {
  6573. if ( Expr.relative[ tokens[j].type ] ) {
  6574. break;
  6575. }
  6576. }
  6577. return setMatcher(
  6578. i > 1 && elementMatcher( matchers ),
  6579. i > 1 && toSelector(
  6580. // If the preceding token was a descendant combinator, insert an implicit any-element `*`
  6581. tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
  6582. ).replace( rtrim, "$1" ),
  6583. matcher,
  6584. i < j && matcherFromTokens( tokens.slice( i, j ) ),
  6585. j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
  6586. j < len && toSelector( tokens )
  6587. );
  6588. }
  6589. matchers.push( matcher );
  6590. }
  6591. }
  6592. return elementMatcher( matchers );
  6593. }
  6594. function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
  6595. var bySet = setMatchers.length > 0,
  6596. byElement = elementMatchers.length > 0,
  6597. superMatcher = function( seed, context, xml, results, outermost ) {
  6598. var elem, j, matcher,
  6599. matchedCount = 0,
  6600. i = "0",
  6601. unmatched = seed && [],
  6602. setMatched = [],
  6603. contextBackup = outermostContext,
  6604. // We must always have either seed elements or outermost context
  6605. elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
  6606. // Use integer dirruns iff this is the outermost matcher
  6607. dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
  6608. len = elems.length;
  6609. if ( outermost ) {
  6610. outermostContext = context !== document && context;
  6611. }
  6612. // Add elements passing elementMatchers directly to results
  6613. // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
  6614. // Support: IE<9, Safari
  6615. // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
  6616. for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
  6617. if ( byElement && elem ) {
  6618. j = 0;
  6619. while ( (matcher = elementMatchers[j++]) ) {
  6620. if ( matcher( elem, context, xml ) ) {
  6621. results.push( elem );
  6622. break;
  6623. }
  6624. }
  6625. if ( outermost ) {
  6626. dirruns = dirrunsUnique;
  6627. }
  6628. }
  6629. // Track unmatched elements for set filters
  6630. if ( bySet ) {
  6631. // They will have gone through all possible matchers
  6632. if ( (elem = !matcher && elem) ) {
  6633. matchedCount--;
  6634. }
  6635. // Lengthen the array for every element, matched or not
  6636. if ( seed ) {
  6637. unmatched.push( elem );
  6638. }
  6639. }
  6640. }
  6641. // Apply set filters to unmatched elements
  6642. matchedCount += i;
  6643. if ( bySet && i !== matchedCount ) {
  6644. j = 0;
  6645. while ( (matcher = setMatchers[j++]) ) {
  6646. matcher( unmatched, setMatched, context, xml );
  6647. }
  6648. if ( seed ) {
  6649. // Reintegrate element matches to eliminate the need for sorting
  6650. if ( matchedCount > 0 ) {
  6651. while ( i-- ) {
  6652. if ( !(unmatched[i] || setMatched[i]) ) {
  6653. setMatched[i] = pop.call( results );
  6654. }
  6655. }
  6656. }
  6657. // Discard index placeholder values to get only actual matches
  6658. setMatched = condense( setMatched );
  6659. }
  6660. // Add matches to results
  6661. push.apply( results, setMatched );
  6662. // Seedless set matches succeeding multiple successful matchers stipulate sorting
  6663. if ( outermost && !seed && setMatched.length > 0 &&
  6664. ( matchedCount + setMatchers.length ) > 1 ) {
  6665. Sizzle.uniqueSort( results );
  6666. }
  6667. }
  6668. // Override manipulation of globals by nested matchers
  6669. if ( outermost ) {
  6670. dirruns = dirrunsUnique;
  6671. outermostContext = contextBackup;
  6672. }
  6673. return unmatched;
  6674. };
  6675. return bySet ?
  6676. markFunction( superMatcher ) :
  6677. superMatcher;
  6678. }
  6679. compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
  6680. var i,
  6681. setMatchers = [],
  6682. elementMatchers = [],
  6683. cached = compilerCache[ selector + " " ];
  6684. if ( !cached ) {
  6685. // Generate a function of recursive functions that can be used to check each element
  6686. if ( !match ) {
  6687. match = tokenize( selector );
  6688. }
  6689. i = match.length;
  6690. while ( i-- ) {
  6691. cached = matcherFromTokens( match[i] );
  6692. if ( cached[ expando ] ) {
  6693. setMatchers.push( cached );
  6694. } else {
  6695. elementMatchers.push( cached );
  6696. }
  6697. }
  6698. // Cache the compiled function
  6699. cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
  6700. // Save selector and tokenization
  6701. cached.selector = selector;
  6702. }
  6703. return cached;
  6704. };
  6705. /**
  6706. * A low-level selection function that works with Sizzle's compiled
  6707. * selector functions
  6708. * @param {String|Function} selector A selector or a pre-compiled
  6709. * selector function built with Sizzle.compile
  6710. * @param {Element} context
  6711. * @param {Array} [results]
  6712. * @param {Array} [seed] A set of elements to match against
  6713. */
  6714. select = Sizzle.select = function( selector, context, results, seed ) {
  6715. var i, tokens, token, type, find,
  6716. compiled = typeof selector === "function" && selector,
  6717. match = !seed && tokenize( (selector = compiled.selector || selector) );
  6718. results = results || [];
  6719. // Try to minimize operations if there is no seed and only one group
  6720. if ( match.length === 1 ) {
  6721. // Take a shortcut and set the context if the root selector is an ID
  6722. tokens = match[0] = match[0].slice( 0 );
  6723. if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
  6724. support.getById && context.nodeType === 9 && documentIsHTML &&
  6725. Expr.relative[ tokens[1].type ] ) {
  6726. context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
  6727. if ( !context ) {
  6728. return results;
  6729. // Precompiled matchers will still verify ancestry, so step up a level
  6730. } else if ( compiled ) {
  6731. context = context.parentNode;
  6732. }
  6733. selector = selector.slice( tokens.shift().value.length );
  6734. }
  6735. // Fetch a seed set for right-to-left matching
  6736. i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
  6737. while ( i-- ) {
  6738. token = tokens[i];
  6739. // Abort if we hit a combinator
  6740. if ( Expr.relative[ (type = token.type) ] ) {
  6741. break;
  6742. }
  6743. if ( (find = Expr.find[ type ]) ) {
  6744. // Search, expanding context for leading sibling combinators
  6745. if ( (seed = find(
  6746. token.matches[0].replace( runescape, funescape ),
  6747. rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
  6748. )) ) {
  6749. // If seed is empty or no tokens remain, we can return early
  6750. tokens.splice( i, 1 );
  6751. selector = seed.length && toSelector( tokens );
  6752. if ( !selector ) {
  6753. push.apply( results, seed );
  6754. return results;
  6755. }
  6756. break;
  6757. }
  6758. }
  6759. }
  6760. }
  6761. // Compile and execute a filtering function if one is not provided
  6762. // Provide `match` to avoid retokenization if we modified the selector above
  6763. ( compiled || compile( selector, match ) )(
  6764. seed,
  6765. context,
  6766. !documentIsHTML,
  6767. results,
  6768. rsibling.test( selector ) && testContext( context.parentNode ) || context
  6769. );
  6770. return results;
  6771. };
  6772. // One-time assignments
  6773. // Sort stability
  6774. support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
  6775. // Support: Chrome 14-35+
  6776. // Always assume duplicates if they aren't passed to the comparison function
  6777. support.detectDuplicates = !!hasDuplicate;
  6778. // Initialize against the default document
  6779. setDocument();
  6780. // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
  6781. // Detached nodes confoundingly follow *each other*
  6782. support.sortDetached = assert(function( div1 ) {
  6783. // Should return 1, but returns 4 (following)
  6784. return div1.compareDocumentPosition( document.createElement("div") ) & 1;
  6785. });
  6786. // Support: IE<8
  6787. // Prevent attribute/property "interpolation"
  6788. // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
  6789. if ( !assert(function( div ) {
  6790. div.innerHTML = "<a href='#'></a>";
  6791. return div.firstChild.getAttribute("href") === "#" ;
  6792. }) ) {
  6793. addHandle( "type|href|height|width", function( elem, name, isXML ) {
  6794. if ( !isXML ) {
  6795. return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
  6796. }
  6797. });
  6798. }
  6799. // Support: IE<9
  6800. // Use defaultValue in place of getAttribute("value")
  6801. if ( !support.attributes || !assert(function( div ) {
  6802. div.innerHTML = "<input/>";
  6803. div.firstChild.setAttribute( "value", "" );
  6804. return div.firstChild.getAttribute( "value" ) === "";
  6805. }) ) {
  6806. addHandle( "value", function( elem, name, isXML ) {
  6807. if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
  6808. return elem.defaultValue;
  6809. }
  6810. });
  6811. }
  6812. // Support: IE<9
  6813. // Use getAttributeNode to fetch booleans when getAttribute lies
  6814. if ( !assert(function( div ) {
  6815. return div.getAttribute("disabled") == null;
  6816. }) ) {
  6817. addHandle( booleans, function( elem, name, isXML ) {
  6818. var val;
  6819. if ( !isXML ) {
  6820. return elem[ name ] === true ? name.toLowerCase() :
  6821. (val = elem.getAttributeNode( name )) && val.specified ?
  6822. val.value :
  6823. null;
  6824. }
  6825. });
  6826. }
  6827. return Sizzle;
  6828. })( window );
  6829. jQuery.find = Sizzle;
  6830. jQuery.expr = Sizzle.selectors;
  6831. jQuery.expr[":"] = jQuery.expr.pseudos;
  6832. jQuery.unique = Sizzle.uniqueSort;
  6833. jQuery.text = Sizzle.getText;
  6834. jQuery.isXMLDoc = Sizzle.isXML;
  6835. jQuery.contains = Sizzle.contains;
  6836. var rneedsContext = jQuery.expr.match.needsContext;
  6837. var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
  6838. var risSimple = /^.[^:#\[\.,]*$/;
  6839. // Implement the identical functionality for filter and not
  6840. function winnow( elements, qualifier, not ) {
  6841. if ( jQuery.isFunction( qualifier ) ) {
  6842. return jQuery.grep( elements, function( elem, i ) {
  6843. /* jshint -W018 */
  6844. return !!qualifier.call( elem, i, elem ) !== not;
  6845. });
  6846. }
  6847. if ( qualifier.nodeType ) {
  6848. return jQuery.grep( elements, function( elem ) {
  6849. return ( elem === qualifier ) !== not;
  6850. });
  6851. }
  6852. if ( typeof qualifier === "string" ) {
  6853. if ( risSimple.test( qualifier ) ) {
  6854. return jQuery.filter( qualifier, elements, not );
  6855. }
  6856. qualifier = jQuery.filter( qualifier, elements );
  6857. }
  6858. return jQuery.grep( elements, function( elem ) {
  6859. return ( indexOf.call( qualifier, elem ) >= 0 ) !== not;
  6860. });
  6861. }
  6862. jQuery.filter = function( expr, elems, not ) {
  6863. var elem = elems[ 0 ];
  6864. if ( not ) {
  6865. expr = ":not(" + expr + ")";
  6866. }
  6867. return elems.length === 1 && elem.nodeType === 1 ?
  6868. jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
  6869. jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
  6870. return elem.nodeType === 1;
  6871. }));
  6872. };
  6873. jQuery.fn.extend({
  6874. find: function( selector ) {
  6875. var i,
  6876. len = this.length,
  6877. ret = [],
  6878. self = this;
  6879. if ( typeof selector !== "string" ) {
  6880. return this.pushStack( jQuery( selector ).filter(function() {
  6881. for ( i = 0; i < len; i++ ) {
  6882. if ( jQuery.contains( self[ i ], this ) ) {
  6883. return true;
  6884. }
  6885. }
  6886. }) );
  6887. }
  6888. for ( i = 0; i < len; i++ ) {
  6889. jQuery.find( selector, self[ i ], ret );
  6890. }
  6891. // Needed because $( selector, context ) becomes $( context ).find( selector )
  6892. ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
  6893. ret.selector = this.selector ? this.selector + " " + selector : selector;
  6894. return ret;
  6895. },
  6896. filter: function( selector ) {
  6897. return this.pushStack( winnow(this, selector || [], false) );
  6898. },
  6899. not: function( selector ) {
  6900. return this.pushStack( winnow(this, selector || [], true) );
  6901. },
  6902. is: function( selector ) {
  6903. return !!winnow(
  6904. this,
  6905. // If this is a positional/relative selector, check membership in the returned set
  6906. // so $("p:first").is("p:last") won't return true for a doc with two "p".
  6907. typeof selector === "string" && rneedsContext.test( selector ) ?
  6908. jQuery( selector ) :
  6909. selector || [],
  6910. false
  6911. ).length;
  6912. }
  6913. });
  6914. // Initialize a jQuery object
  6915. // A central reference to the root jQuery(document)
  6916. var rootjQuery,
  6917. // A simple way to check for HTML strings
  6918. // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
  6919. // Strict HTML recognition (#11290: must start with <)
  6920. rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
  6921. init = jQuery.fn.init = function( selector, context ) {
  6922. var match, elem;
  6923. // HANDLE: $(""), $(null), $(undefined), $(false)
  6924. if ( !selector ) {
  6925. return this;
  6926. }
  6927. // Handle HTML strings
  6928. if ( typeof selector === "string" ) {
  6929. if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) {
  6930. // Assume that strings that start and end with <> are HTML and skip the regex check
  6931. match = [ null, selector, null ];
  6932. } else {
  6933. match = rquickExpr.exec( selector );
  6934. }
  6935. // Match html or make sure no context is specified for #id
  6936. if ( match && (match[1] || !context) ) {
  6937. // HANDLE: $(html) -> $(array)
  6938. if ( match[1] ) {
  6939. context = context instanceof jQuery ? context[0] : context;
  6940. // Option to run scripts is true for back-compat
  6941. // Intentionally let the error be thrown if parseHTML is not present
  6942. jQuery.merge( this, jQuery.parseHTML(
  6943. match[1],
  6944. context && context.nodeType ? context.ownerDocument || context : document,
  6945. true
  6946. ) );
  6947. // HANDLE: $(html, props)
  6948. if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
  6949. for ( match in context ) {
  6950. // Properties of context are called as methods if possible
  6951. if ( jQuery.isFunction( this[ match ] ) ) {
  6952. this[ match ]( context[ match ] );
  6953. // ...and otherwise set as attributes
  6954. } else {
  6955. this.attr( match, context[ match ] );
  6956. }
  6957. }
  6958. }
  6959. return this;
  6960. // HANDLE: $(#id)
  6961. } else {
  6962. elem = document.getElementById( match[2] );
  6963. // Support: Blackberry 4.6
  6964. // gEBID returns nodes no longer in the document (#6963)
  6965. if ( elem && elem.parentNode ) {
  6966. // Inject the element directly into the jQuery object
  6967. this.length = 1;
  6968. this[0] = elem;
  6969. }
  6970. this.context = document;
  6971. this.selector = selector;
  6972. return this;
  6973. }
  6974. // HANDLE: $(expr, $(...))
  6975. } else if ( !context || context.jquery ) {
  6976. return ( context || rootjQuery ).find( selector );
  6977. // HANDLE: $(expr, context)
  6978. // (which is just equivalent to: $(context).find(expr)
  6979. } else {
  6980. return this.constructor( context ).find( selector );
  6981. }
  6982. // HANDLE: $(DOMElement)
  6983. } else if ( selector.nodeType ) {
  6984. this.context = this[0] = selector;
  6985. this.length = 1;
  6986. return this;
  6987. // HANDLE: $(function)
  6988. // Shortcut for document ready
  6989. } else if ( jQuery.isFunction( selector ) ) {
  6990. return typeof rootjQuery.ready !== "undefined" ?
  6991. rootjQuery.ready( selector ) :
  6992. // Execute immediately if ready is not present
  6993. selector( jQuery );
  6994. }
  6995. if ( selector.selector !== undefined ) {
  6996. this.selector = selector.selector;
  6997. this.context = selector.context;
  6998. }
  6999. return jQuery.makeArray( selector, this );
  7000. };
  7001. // Give the init function the jQuery prototype for later instantiation
  7002. init.prototype = jQuery.fn;
  7003. // Initialize central reference
  7004. rootjQuery = jQuery( document );
  7005. var rparentsprev = /^(?:parents|prev(?:Until|All))/,
  7006. // Methods guaranteed to produce a unique set when starting from a unique set
  7007. guaranteedUnique = {
  7008. children: true,
  7009. contents: true,
  7010. next: true,
  7011. prev: true
  7012. };
  7013. jQuery.extend({
  7014. dir: function( elem, dir, until ) {
  7015. var matched = [],
  7016. truncate = until !== undefined;
  7017. while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
  7018. if ( elem.nodeType === 1 ) {
  7019. if ( truncate && jQuery( elem ).is( until ) ) {
  7020. break;
  7021. }
  7022. matched.push( elem );
  7023. }
  7024. }
  7025. return matched;
  7026. },
  7027. sibling: function( n, elem ) {
  7028. var matched = [];
  7029. for ( ; n; n = n.nextSibling ) {
  7030. if ( n.nodeType === 1 && n !== elem ) {
  7031. matched.push( n );
  7032. }
  7033. }
  7034. return matched;
  7035. }
  7036. });
  7037. jQuery.fn.extend({
  7038. has: function( target ) {
  7039. var targets = jQuery( target, this ),
  7040. l = targets.length;
  7041. return this.filter(function() {
  7042. var i = 0;
  7043. for ( ; i < l; i++ ) {
  7044. if ( jQuery.contains( this, targets[i] ) ) {
  7045. return true;
  7046. }
  7047. }
  7048. });
  7049. },
  7050. closest: function( selectors, context ) {
  7051. var cur,
  7052. i = 0,
  7053. l = this.length,
  7054. matched = [],
  7055. pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
  7056. jQuery( selectors, context || this.context ) :
  7057. 0;
  7058. for ( ; i < l; i++ ) {
  7059. for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
  7060. // Always skip document fragments
  7061. if ( cur.nodeType < 11 && (pos ?
  7062. pos.index(cur) > -1 :
  7063. // Don't pass non-elements to Sizzle
  7064. cur.nodeType === 1 &&
  7065. jQuery.find.matchesSelector(cur, selectors)) ) {
  7066. matched.push( cur );
  7067. break;
  7068. }
  7069. }
  7070. }
  7071. return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
  7072. },
  7073. // Determine the position of an element within the set
  7074. index: function( elem ) {
  7075. // No argument, return index in parent
  7076. if ( !elem ) {
  7077. return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
  7078. }
  7079. // Index in selector
  7080. if ( typeof elem === "string" ) {
  7081. return indexOf.call( jQuery( elem ), this[ 0 ] );
  7082. }
  7083. // Locate the position of the desired element
  7084. return indexOf.call( this,
  7085. // If it receives a jQuery object, the first element is used
  7086. elem.jquery ? elem[ 0 ] : elem
  7087. );
  7088. },
  7089. add: function( selector, context ) {
  7090. return this.pushStack(
  7091. jQuery.unique(
  7092. jQuery.merge( this.get(), jQuery( selector, context ) )
  7093. )
  7094. );
  7095. },
  7096. addBack: function( selector ) {
  7097. return this.add( selector == null ?
  7098. this.prevObject : this.prevObject.filter(selector)
  7099. );
  7100. }
  7101. });
  7102. function sibling( cur, dir ) {
  7103. while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
  7104. return cur;
  7105. }
  7106. jQuery.each({
  7107. parent: function( elem ) {
  7108. var parent = elem.parentNode;
  7109. return parent && parent.nodeType !== 11 ? parent : null;
  7110. },
  7111. parents: function( elem ) {
  7112. return jQuery.dir( elem, "parentNode" );
  7113. },
  7114. parentsUntil: function( elem, i, until ) {
  7115. return jQuery.dir( elem, "parentNode", until );
  7116. },
  7117. next: function( elem ) {
  7118. return sibling( elem, "nextSibling" );
  7119. },
  7120. prev: function( elem ) {
  7121. return sibling( elem, "previousSibling" );
  7122. },
  7123. nextAll: function( elem ) {
  7124. return jQuery.dir( elem, "nextSibling" );
  7125. },
  7126. prevAll: function( elem ) {
  7127. return jQuery.dir( elem, "previousSibling" );
  7128. },
  7129. nextUntil: function( elem, i, until ) {
  7130. return jQuery.dir( elem, "nextSibling", until );
  7131. },
  7132. prevUntil: function( elem, i, until ) {
  7133. return jQuery.dir( elem, "previousSibling", until );
  7134. },
  7135. siblings: function( elem ) {
  7136. return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
  7137. },
  7138. children: function( elem ) {
  7139. return jQuery.sibling( elem.firstChild );
  7140. },
  7141. contents: function( elem ) {
  7142. return elem.contentDocument || jQuery.merge( [], elem.childNodes );
  7143. }
  7144. }, function( name, fn ) {
  7145. jQuery.fn[ name ] = function( until, selector ) {
  7146. var matched = jQuery.map( this, fn, until );
  7147. if ( name.slice( -5 ) !== "Until" ) {
  7148. selector = until;
  7149. }
  7150. if ( selector && typeof selector === "string" ) {
  7151. matched = jQuery.filter( selector, matched );
  7152. }
  7153. if ( this.length > 1 ) {
  7154. // Remove duplicates
  7155. if ( !guaranteedUnique[ name ] ) {
  7156. jQuery.unique( matched );
  7157. }
  7158. // Reverse order for parents* and prev-derivatives
  7159. if ( rparentsprev.test( name ) ) {
  7160. matched.reverse();
  7161. }
  7162. }
  7163. return this.pushStack( matched );
  7164. };
  7165. });
  7166. var rnotwhite = (/\S+/g);
  7167. // String to Object options format cache
  7168. var optionsCache = {};
  7169. // Convert String-formatted options into Object-formatted ones and store in cache
  7170. function createOptions( options ) {
  7171. var object = optionsCache[ options ] = {};
  7172. jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
  7173. object[ flag ] = true;
  7174. });
  7175. return object;
  7176. }
  7177. /*
  7178. * Create a callback list using the following parameters:
  7179. *
  7180. * options: an optional list of space-separated options that will change how
  7181. * the callback list behaves or a more traditional option object
  7182. *
  7183. * By default a callback list will act like an event callback list and can be
  7184. * "fired" multiple times.
  7185. *
  7186. * Possible options:
  7187. *
  7188. * once: will ensure the callback list can only be fired once (like a Deferred)
  7189. *
  7190. * memory: will keep track of previous values and will call any callback added
  7191. * after the list has been fired right away with the latest "memorized"
  7192. * values (like a Deferred)
  7193. *
  7194. * unique: will ensure a callback can only be added once (no duplicate in the list)
  7195. *
  7196. * stopOnFalse: interrupt callings when a callback returns false
  7197. *
  7198. */
  7199. jQuery.Callbacks = function( options ) {
  7200. // Convert options from String-formatted to Object-formatted if needed
  7201. // (we check in cache first)
  7202. options = typeof options === "string" ?
  7203. ( optionsCache[ options ] || createOptions( options ) ) :
  7204. jQuery.extend( {}, options );
  7205. var // Last fire value (for non-forgettable lists)
  7206. memory,
  7207. // Flag to know if list was already fired
  7208. fired,
  7209. // Flag to know if list is currently firing
  7210. firing,
  7211. // First callback to fire (used internally by add and fireWith)
  7212. firingStart,
  7213. // End of the loop when firing
  7214. firingLength,
  7215. // Index of currently firing callback (modified by remove if needed)
  7216. firingIndex,
  7217. // Actual callback list
  7218. list = [],
  7219. // Stack of fire calls for repeatable lists
  7220. stack = !options.once && [],
  7221. // Fire callbacks
  7222. fire = function( data ) {
  7223. memory = options.memory && data;
  7224. fired = true;
  7225. firingIndex = firingStart || 0;
  7226. firingStart = 0;
  7227. firingLength = list.length;
  7228. firing = true;
  7229. for ( ; list && firingIndex < firingLength; firingIndex++ ) {
  7230. if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
  7231. memory = false; // To prevent further calls using add
  7232. break;
  7233. }
  7234. }
  7235. firing = false;
  7236. if ( list ) {
  7237. if ( stack ) {
  7238. if ( stack.length ) {
  7239. fire( stack.shift() );
  7240. }
  7241. } else if ( memory ) {
  7242. list = [];
  7243. } else {
  7244. self.disable();
  7245. }
  7246. }
  7247. },
  7248. // Actual Callbacks object
  7249. self = {
  7250. // Add a callback or a collection of callbacks to the list
  7251. add: function() {
  7252. if ( list ) {
  7253. // First, we save the current length
  7254. var start = list.length;
  7255. (function add( args ) {
  7256. jQuery.each( args, function( _, arg ) {
  7257. var type = jQuery.type( arg );
  7258. if ( type === "function" ) {
  7259. if ( !options.unique || !self.has( arg ) ) {
  7260. list.push( arg );
  7261. }
  7262. } else if ( arg && arg.length && type !== "string" ) {
  7263. // Inspect recursively
  7264. add( arg );
  7265. }
  7266. });
  7267. })( arguments );
  7268. // Do we need to add the callbacks to the
  7269. // current firing batch?
  7270. if ( firing ) {
  7271. firingLength = list.length;
  7272. // With memory, if we're not firing then
  7273. // we should call right away
  7274. } else if ( memory ) {
  7275. firingStart = start;
  7276. fire( memory );
  7277. }
  7278. }
  7279. return this;
  7280. },
  7281. // Remove a callback from the list
  7282. remove: function() {
  7283. if ( list ) {
  7284. jQuery.each( arguments, function( _, arg ) {
  7285. var index;
  7286. while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
  7287. list.splice( index, 1 );
  7288. // Handle firing indexes
  7289. if ( firing ) {
  7290. if ( index <= firingLength ) {
  7291. firingLength--;
  7292. }
  7293. if ( index <= firingIndex ) {
  7294. firingIndex--;
  7295. }
  7296. }
  7297. }
  7298. });
  7299. }
  7300. return this;
  7301. },
  7302. // Check if a given callback is in the list.
  7303. // If no argument is given, return whether or not list has callbacks attached.
  7304. has: function( fn ) {
  7305. return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
  7306. },
  7307. // Remove all callbacks from the list
  7308. empty: function() {
  7309. list = [];
  7310. firingLength = 0;
  7311. return this;
  7312. },
  7313. // Have the list do nothing anymore
  7314. disable: function() {
  7315. list = stack = memory = undefined;
  7316. return this;
  7317. },
  7318. // Is it disabled?
  7319. disabled: function() {
  7320. return !list;
  7321. },
  7322. // Lock the list in its current state
  7323. lock: function() {
  7324. stack = undefined;
  7325. if ( !memory ) {
  7326. self.disable();
  7327. }
  7328. return this;
  7329. },
  7330. // Is it locked?
  7331. locked: function() {
  7332. return !stack;
  7333. },
  7334. // Call all callbacks with the given context and arguments
  7335. fireWith: function( context, args ) {
  7336. if ( list && ( !fired || stack ) ) {
  7337. args = args || [];
  7338. args = [ context, args.slice ? args.slice() : args ];
  7339. if ( firing ) {
  7340. stack.push( args );
  7341. } else {
  7342. fire( args );
  7343. }
  7344. }
  7345. return this;
  7346. },
  7347. // Call all the callbacks with the given arguments
  7348. fire: function() {
  7349. self.fireWith( this, arguments );
  7350. return this;
  7351. },
  7352. // To know if the callbacks have already been called at least once
  7353. fired: function() {
  7354. return !!fired;
  7355. }
  7356. };
  7357. return self;
  7358. };
  7359. jQuery.extend({
  7360. Deferred: function( func ) {
  7361. var tuples = [
  7362. // action, add listener, listener list, final state
  7363. [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
  7364. [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
  7365. [ "notify", "progress", jQuery.Callbacks("memory") ]
  7366. ],
  7367. state = "pending",
  7368. promise = {
  7369. state: function() {
  7370. return state;
  7371. },
  7372. always: function() {
  7373. deferred.done( arguments ).fail( arguments );
  7374. return this;
  7375. },
  7376. then: function( /* fnDone, fnFail, fnProgress */ ) {
  7377. var fns = arguments;
  7378. return jQuery.Deferred(function( newDefer ) {
  7379. jQuery.each( tuples, function( i, tuple ) {
  7380. var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
  7381. // deferred[ done | fail | progress ] for forwarding actions to newDefer
  7382. deferred[ tuple[1] ](function() {
  7383. var returned = fn && fn.apply( this, arguments );
  7384. if ( returned && jQuery.isFunction( returned.promise ) ) {
  7385. returned.promise()
  7386. .done( newDefer.resolve )
  7387. .fail( newDefer.reject )
  7388. .progress( newDefer.notify );
  7389. } else {
  7390. newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
  7391. }
  7392. });
  7393. });
  7394. fns = null;
  7395. }).promise();
  7396. },
  7397. // Get a promise for this deferred
  7398. // If obj is provided, the promise aspect is added to the object
  7399. promise: function( obj ) {
  7400. return obj != null ? jQuery.extend( obj, promise ) : promise;
  7401. }
  7402. },
  7403. deferred = {};
  7404. // Keep pipe for back-compat
  7405. promise.pipe = promise.then;
  7406. // Add list-specific methods
  7407. jQuery.each( tuples, function( i, tuple ) {
  7408. var list = tuple[ 2 ],
  7409. stateString = tuple[ 3 ];
  7410. // promise[ done | fail | progress ] = list.add
  7411. promise[ tuple[1] ] = list.add;
  7412. // Handle state
  7413. if ( stateString ) {
  7414. list.add(function() {
  7415. // state = [ resolved | rejected ]
  7416. state = stateString;
  7417. // [ reject_list | resolve_list ].disable; progress_list.lock
  7418. }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
  7419. }
  7420. // deferred[ resolve | reject | notify ]
  7421. deferred[ tuple[0] ] = function() {
  7422. deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
  7423. return this;
  7424. };
  7425. deferred[ tuple[0] + "With" ] = list.fireWith;
  7426. });
  7427. // Make the deferred a promise
  7428. promise.promise( deferred );
  7429. // Call given func if any
  7430. if ( func ) {
  7431. func.call( deferred, deferred );
  7432. }
  7433. // All done!
  7434. return deferred;
  7435. },
  7436. // Deferred helper
  7437. when: function( subordinate /* , ..., subordinateN */ ) {
  7438. var i = 0,
  7439. resolveValues = slice.call( arguments ),
  7440. length = resolveValues.length,
  7441. // the count of uncompleted subordinates
  7442. remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
  7443. // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
  7444. deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
  7445. // Update function for both resolve and progress values
  7446. updateFunc = function( i, contexts, values ) {
  7447. return function( value ) {
  7448. contexts[ i ] = this;
  7449. values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
  7450. if ( values === progressValues ) {
  7451. deferred.notifyWith( contexts, values );
  7452. } else if ( !( --remaining ) ) {
  7453. deferred.resolveWith( contexts, values );
  7454. }
  7455. };
  7456. },
  7457. progressValues, progressContexts, resolveContexts;
  7458. // Add listeners to Deferred subordinates; treat others as resolved
  7459. if ( length > 1 ) {
  7460. progressValues = new Array( length );
  7461. progressContexts = new Array( length );
  7462. resolveContexts = new Array( length );
  7463. for ( ; i < length; i++ ) {
  7464. if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
  7465. resolveValues[ i ].promise()
  7466. .done( updateFunc( i, resolveContexts, resolveValues ) )
  7467. .fail( deferred.reject )
  7468. .progress( updateFunc( i, progressContexts, progressValues ) );
  7469. } else {
  7470. --remaining;
  7471. }
  7472. }
  7473. }
  7474. // If we're not waiting on anything, resolve the master
  7475. if ( !remaining ) {
  7476. deferred.resolveWith( resolveContexts, resolveValues );
  7477. }
  7478. return deferred.promise();
  7479. }
  7480. });
  7481. // The deferred used on DOM ready
  7482. var readyList;
  7483. jQuery.fn.ready = function( fn ) {
  7484. // Add the callback
  7485. jQuery.ready.promise().done( fn );
  7486. return this;
  7487. };
  7488. jQuery.extend({
  7489. // Is the DOM ready to be used? Set to true once it occurs.
  7490. isReady: false,
  7491. // A counter to track how many items to wait for before
  7492. // the ready event fires. See #6781
  7493. readyWait: 1,
  7494. // Hold (or release) the ready event
  7495. holdReady: function( hold ) {
  7496. if ( hold ) {
  7497. jQuery.readyWait++;
  7498. } else {
  7499. jQuery.ready( true );
  7500. }
  7501. },
  7502. // Handle when the DOM is ready
  7503. ready: function( wait ) {
  7504. // Abort if there are pending holds or we're already ready
  7505. if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
  7506. return;
  7507. }
  7508. // Remember that the DOM is ready
  7509. jQuery.isReady = true;
  7510. // If a normal DOM Ready event fired, decrement, and wait if need be
  7511. if ( wait !== true && --jQuery.readyWait > 0 ) {
  7512. return;
  7513. }
  7514. // If there are functions bound, to execute
  7515. readyList.resolveWith( document, [ jQuery ] );
  7516. // Trigger any bound ready events
  7517. if ( jQuery.fn.triggerHandler ) {
  7518. jQuery( document ).triggerHandler( "ready" );
  7519. jQuery( document ).off( "ready" );
  7520. }
  7521. }
  7522. });
  7523. /**
  7524. * The ready event handler and self cleanup method
  7525. */
  7526. function completed() {
  7527. document.removeEventListener( "DOMContentLoaded", completed, false );
  7528. window.removeEventListener( "load", completed, false );
  7529. jQuery.ready();
  7530. }
  7531. jQuery.ready.promise = function( obj ) {
  7532. if ( !readyList ) {
  7533. readyList = jQuery.Deferred();
  7534. // Catch cases where $(document).ready() is called after the browser event has already occurred.
  7535. // We once tried to use readyState "interactive" here, but it caused issues like the one
  7536. // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
  7537. if ( document.readyState === "complete" ) {
  7538. // Handle it asynchronously to allow scripts the opportunity to delay ready
  7539. setTimeout( jQuery.ready );
  7540. } else {
  7541. // Use the handy event callback
  7542. document.addEventListener( "DOMContentLoaded", completed, false );
  7543. // A fallback to window.onload, that will always work
  7544. window.addEventListener( "load", completed, false );
  7545. }
  7546. }
  7547. return readyList.promise( obj );
  7548. };
  7549. // Kick off the DOM ready check even if the user does not
  7550. jQuery.ready.promise();
  7551. // Multifunctional method to get and set values of a collection
  7552. // The value/s can optionally be executed if it's a function
  7553. var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
  7554. var i = 0,
  7555. len = elems.length,
  7556. bulk = key == null;
  7557. // Sets many values
  7558. if ( jQuery.type( key ) === "object" ) {
  7559. chainable = true;
  7560. for ( i in key ) {
  7561. jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
  7562. }
  7563. // Sets one value
  7564. } else if ( value !== undefined ) {
  7565. chainable = true;
  7566. if ( !jQuery.isFunction( value ) ) {
  7567. raw = true;
  7568. }
  7569. if ( bulk ) {
  7570. // Bulk operations run against the entire set
  7571. if ( raw ) {
  7572. fn.call( elems, value );
  7573. fn = null;
  7574. // ...except when executing function values
  7575. } else {
  7576. bulk = fn;
  7577. fn = function( elem, key, value ) {
  7578. return bulk.call( jQuery( elem ), value );
  7579. };
  7580. }
  7581. }
  7582. if ( fn ) {
  7583. for ( ; i < len; i++ ) {
  7584. fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
  7585. }
  7586. }
  7587. }
  7588. return chainable ?
  7589. elems :
  7590. // Gets
  7591. bulk ?
  7592. fn.call( elems ) :
  7593. len ? fn( elems[0], key ) : emptyGet;
  7594. };
  7595. /**
  7596. * Determines whether an object can have data
  7597. */
  7598. jQuery.acceptData = function( owner ) {
  7599. // Accepts only:
  7600. // - Node
  7601. // - Node.ELEMENT_NODE
  7602. // - Node.DOCUMENT_NODE
  7603. // - Object
  7604. // - Any
  7605. /* jshint -W018 */
  7606. return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
  7607. };
  7608. function Data() {
  7609. // Support: Android<4,
  7610. // Old WebKit does not have Object.preventExtensions/freeze method,
  7611. // return new empty object instead with no [[set]] accessor
  7612. Object.defineProperty( this.cache = {}, 0, {
  7613. get: function() {
  7614. return {};
  7615. }
  7616. });
  7617. this.expando = jQuery.expando + Data.uid++;
  7618. }
  7619. Data.uid = 1;
  7620. Data.accepts = jQuery.acceptData;
  7621. Data.prototype = {
  7622. key: function( owner ) {
  7623. // We can accept data for non-element nodes in modern browsers,
  7624. // but we should not, see #8335.
  7625. // Always return the key for a frozen object.
  7626. if ( !Data.accepts( owner ) ) {
  7627. return 0;
  7628. }
  7629. var descriptor = {},
  7630. // Check if the owner object already has a cache key
  7631. unlock = owner[ this.expando ];
  7632. // If not, create one
  7633. if ( !unlock ) {
  7634. unlock = Data.uid++;
  7635. // Secure it in a non-enumerable, non-writable property
  7636. try {
  7637. descriptor[ this.expando ] = { value: unlock };
  7638. Object.defineProperties( owner, descriptor );
  7639. // Support: Android<4
  7640. // Fallback to a less secure definition
  7641. } catch ( e ) {
  7642. descriptor[ this.expando ] = unlock;
  7643. jQuery.extend( owner, descriptor );
  7644. }
  7645. }
  7646. // Ensure the cache object
  7647. if ( !this.cache[ unlock ] ) {
  7648. this.cache[ unlock ] = {};
  7649. }
  7650. return unlock;
  7651. },
  7652. set: function( owner, data, value ) {
  7653. var prop,
  7654. // There may be an unlock assigned to this node,
  7655. // if there is no entry for this "owner", create one inline
  7656. // and set the unlock as though an owner entry had always existed
  7657. unlock = this.key( owner ),
  7658. cache = this.cache[ unlock ];
  7659. // Handle: [ owner, key, value ] args
  7660. if ( typeof data === "string" ) {
  7661. cache[ data ] = value;
  7662. // Handle: [ owner, { properties } ] args
  7663. } else {
  7664. // Fresh assignments by object are shallow copied
  7665. if ( jQuery.isEmptyObject( cache ) ) {
  7666. jQuery.extend( this.cache[ unlock ], data );
  7667. // Otherwise, copy the properties one-by-one to the cache object
  7668. } else {
  7669. for ( prop in data ) {
  7670. cache[ prop ] = data[ prop ];
  7671. }
  7672. }
  7673. }
  7674. return cache;
  7675. },
  7676. get: function( owner, key ) {
  7677. // Either a valid cache is found, or will be created.
  7678. // New caches will be created and the unlock returned,
  7679. // allowing direct access to the newly created
  7680. // empty data object. A valid owner object must be provided.
  7681. var cache = this.cache[ this.key( owner ) ];
  7682. return key === undefined ?
  7683. cache : cache[ key ];
  7684. },
  7685. access: function( owner, key, value ) {
  7686. var stored;
  7687. // In cases where either:
  7688. //
  7689. // 1. No key was specified
  7690. // 2. A string key was specified, but no value provided
  7691. //
  7692. // Take the "read" path and allow the get method to determine
  7693. // which value to return, respectively either:
  7694. //
  7695. // 1. The entire cache object
  7696. // 2. The data stored at the key
  7697. //
  7698. if ( key === undefined ||
  7699. ((key && typeof key === "string") && value === undefined) ) {
  7700. stored = this.get( owner, key );
  7701. return stored !== undefined ?
  7702. stored : this.get( owner, jQuery.camelCase(key) );
  7703. }
  7704. // [*]When the key is not a string, or both a key and value
  7705. // are specified, set or extend (existing objects) with either:
  7706. //
  7707. // 1. An object of properties
  7708. // 2. A key and value
  7709. //
  7710. this.set( owner, key, value );
  7711. // Since the "set" path can have two possible entry points
  7712. // return the expected data based on which path was taken[*]
  7713. return value !== undefined ? value : key;
  7714. },
  7715. remove: function( owner, key ) {
  7716. var i, name, camel,
  7717. unlock = this.key( owner ),
  7718. cache = this.cache[ unlock ];
  7719. if ( key === undefined ) {
  7720. this.cache[ unlock ] = {};
  7721. } else {
  7722. // Support array or space separated string of keys
  7723. if ( jQuery.isArray( key ) ) {
  7724. // If "name" is an array of keys...
  7725. // When data is initially created, via ("key", "val") signature,
  7726. // keys will be converted to camelCase.
  7727. // Since there is no way to tell _how_ a key was added, remove
  7728. // both plain key and camelCase key. #12786
  7729. // This will only penalize the array argument path.
  7730. name = key.concat( key.map( jQuery.camelCase ) );
  7731. } else {
  7732. camel = jQuery.camelCase( key );
  7733. // Try the string as a key before any manipulation
  7734. if ( key in cache ) {
  7735. name = [ key, camel ];
  7736. } else {
  7737. // If a key with the spaces exists, use it.
  7738. // Otherwise, create an array by matching non-whitespace
  7739. name = camel;
  7740. name = name in cache ?
  7741. [ name ] : ( name.match( rnotwhite ) || [] );
  7742. }
  7743. }
  7744. i = name.length;
  7745. while ( i-- ) {
  7746. delete cache[ name[ i ] ];
  7747. }
  7748. }
  7749. },
  7750. hasData: function( owner ) {
  7751. return !jQuery.isEmptyObject(
  7752. this.cache[ owner[ this.expando ] ] || {}
  7753. );
  7754. },
  7755. discard: function( owner ) {
  7756. if ( owner[ this.expando ] ) {
  7757. delete this.cache[ owner[ this.expando ] ];
  7758. }
  7759. }
  7760. };
  7761. var data_priv = new Data();
  7762. var data_user = new Data();
  7763. // Implementation Summary
  7764. //
  7765. // 1. Enforce API surface and semantic compatibility with 1.9.x branch
  7766. // 2. Improve the module's maintainability by reducing the storage
  7767. // paths to a single mechanism.
  7768. // 3. Use the same single mechanism to support "private" and "user" data.
  7769. // 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
  7770. // 5. Avoid exposing implementation details on user objects (eg. expando properties)
  7771. // 6. Provide a clear path for implementation upgrade to WeakMap in 2014
  7772. var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
  7773. rmultiDash = /([A-Z])/g;
  7774. function dataAttr( elem, key, data ) {
  7775. var name;
  7776. // If nothing was found internally, try to fetch any
  7777. // data from the HTML5 data-* attribute
  7778. if ( data === undefined && elem.nodeType === 1 ) {
  7779. name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
  7780. data = elem.getAttribute( name );
  7781. if ( typeof data === "string" ) {
  7782. try {
  7783. data = data === "true" ? true :
  7784. data === "false" ? false :
  7785. data === "null" ? null :
  7786. // Only convert to a number if it doesn't change the string
  7787. +data + "" === data ? +data :
  7788. rbrace.test( data ) ? jQuery.parseJSON( data ) :
  7789. data;
  7790. } catch( e ) {}
  7791. // Make sure we set the data so it isn't changed later
  7792. data_user.set( elem, key, data );
  7793. } else {
  7794. data = undefined;
  7795. }
  7796. }
  7797. return data;
  7798. }
  7799. jQuery.extend({
  7800. hasData: function( elem ) {
  7801. return data_user.hasData( elem ) || data_priv.hasData( elem );
  7802. },
  7803. data: function( elem, name, data ) {
  7804. return data_user.access( elem, name, data );
  7805. },
  7806. removeData: function( elem, name ) {
  7807. data_user.remove( elem, name );
  7808. },
  7809. // TODO: Now that all calls to _data and _removeData have been replaced
  7810. // with direct calls to data_priv methods, these can be deprecated.
  7811. _data: function( elem, name, data ) {
  7812. return data_priv.access( elem, name, data );
  7813. },
  7814. _removeData: function( elem, name ) {
  7815. data_priv.remove( elem, name );
  7816. }
  7817. });
  7818. jQuery.fn.extend({
  7819. data: function( key, value ) {
  7820. var i, name, data,
  7821. elem = this[ 0 ],
  7822. attrs = elem && elem.attributes;
  7823. // Gets all values
  7824. if ( key === undefined ) {
  7825. if ( this.length ) {
  7826. data = data_user.get( elem );
  7827. if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
  7828. i = attrs.length;
  7829. while ( i-- ) {
  7830. // Support: IE11+
  7831. // The attrs elements can be null (#14894)
  7832. if ( attrs[ i ] ) {
  7833. name = attrs[ i ].name;
  7834. if ( name.indexOf( "data-" ) === 0 ) {
  7835. name = jQuery.camelCase( name.slice(5) );
  7836. dataAttr( elem, name, data[ name ] );
  7837. }
  7838. }
  7839. }
  7840. data_priv.set( elem, "hasDataAttrs", true );
  7841. }
  7842. }
  7843. return data;
  7844. }
  7845. // Sets multiple values
  7846. if ( typeof key === "object" ) {
  7847. return this.each(function() {
  7848. data_user.set( this, key );
  7849. });
  7850. }
  7851. return access( this, function( value ) {
  7852. var data,
  7853. camelKey = jQuery.camelCase( key );
  7854. // The calling jQuery object (element matches) is not empty
  7855. // (and therefore has an element appears at this[ 0 ]) and the
  7856. // `value` parameter was not undefined. An empty jQuery object
  7857. // will result in `undefined` for elem = this[ 0 ] which will
  7858. // throw an exception if an attempt to read a data cache is made.
  7859. if ( elem && value === undefined ) {
  7860. // Attempt to get data from the cache
  7861. // with the key as-is
  7862. data = data_user.get( elem, key );
  7863. if ( data !== undefined ) {
  7864. return data;
  7865. }
  7866. // Attempt to get data from the cache
  7867. // with the key camelized
  7868. data = data_user.get( elem, camelKey );
  7869. if ( data !== undefined ) {
  7870. return data;
  7871. }
  7872. // Attempt to "discover" the data in
  7873. // HTML5 custom data-* attrs
  7874. data = dataAttr( elem, camelKey, undefined );
  7875. if ( data !== undefined ) {
  7876. return data;
  7877. }
  7878. // We tried really hard, but the data doesn't exist.
  7879. return;
  7880. }
  7881. // Set the data...
  7882. this.each(function() {
  7883. // First, attempt to store a copy or reference of any
  7884. // data that might've been store with a camelCased key.
  7885. var data = data_user.get( this, camelKey );
  7886. // For HTML5 data-* attribute interop, we have to
  7887. // store property names with dashes in a camelCase form.
  7888. // This might not apply to all properties...*
  7889. data_user.set( this, camelKey, value );
  7890. // *... In the case of properties that might _actually_
  7891. // have dashes, we need to also store a copy of that
  7892. // unchanged property.
  7893. if ( key.indexOf("-") !== -1 && data !== undefined ) {
  7894. data_user.set( this, key, value );
  7895. }
  7896. });
  7897. }, null, value, arguments.length > 1, null, true );
  7898. },
  7899. removeData: function( key ) {
  7900. return this.each(function() {
  7901. data_user.remove( this, key );
  7902. });
  7903. }
  7904. });
  7905. jQuery.extend({
  7906. queue: function( elem, type, data ) {
  7907. var queue;
  7908. if ( elem ) {
  7909. type = ( type || "fx" ) + "queue";
  7910. queue = data_priv.get( elem, type );
  7911. // Speed up dequeue by getting out quickly if this is just a lookup
  7912. if ( data ) {
  7913. if ( !queue || jQuery.isArray( data ) ) {
  7914. queue = data_priv.access( elem, type, jQuery.makeArray(data) );
  7915. } else {
  7916. queue.push( data );
  7917. }
  7918. }
  7919. return queue || [];
  7920. }
  7921. },
  7922. dequeue: function( elem, type ) {
  7923. type = type || "fx";
  7924. var queue = jQuery.queue( elem, type ),
  7925. startLength = queue.length,
  7926. fn = queue.shift(),
  7927. hooks = jQuery._queueHooks( elem, type ),
  7928. next = function() {
  7929. jQuery.dequeue( elem, type );
  7930. };
  7931. // If the fx queue is dequeued, always remove the progress sentinel
  7932. if ( fn === "inprogress" ) {
  7933. fn = queue.shift();
  7934. startLength--;
  7935. }
  7936. if ( fn ) {
  7937. // Add a progress sentinel to prevent the fx queue from being
  7938. // automatically dequeued
  7939. if ( type === "fx" ) {
  7940. queue.unshift( "inprogress" );
  7941. }
  7942. // Clear up the last queue stop function
  7943. delete hooks.stop;
  7944. fn.call( elem, next, hooks );
  7945. }
  7946. if ( !startLength && hooks ) {
  7947. hooks.empty.fire();
  7948. }
  7949. },
  7950. // Not public - generate a queueHooks object, or return the current one
  7951. _queueHooks: function( elem, type ) {
  7952. var key = type + "queueHooks";
  7953. return data_priv.get( elem, key ) || data_priv.access( elem, key, {
  7954. empty: jQuery.Callbacks("once memory").add(function() {
  7955. data_priv.remove( elem, [ type + "queue", key ] );
  7956. })
  7957. });
  7958. }
  7959. });
  7960. jQuery.fn.extend({
  7961. queue: function( type, data ) {
  7962. var setter = 2;
  7963. if ( typeof type !== "string" ) {
  7964. data = type;
  7965. type = "fx";
  7966. setter--;
  7967. }
  7968. if ( arguments.length < setter ) {
  7969. return jQuery.queue( this[0], type );
  7970. }
  7971. return data === undefined ?
  7972. this :
  7973. this.each(function() {
  7974. var queue = jQuery.queue( this, type, data );
  7975. // Ensure a hooks for this queue
  7976. jQuery._queueHooks( this, type );
  7977. if ( type === "fx" && queue[0] !== "inprogress" ) {
  7978. jQuery.dequeue( this, type );
  7979. }
  7980. });
  7981. },
  7982. dequeue: function( type ) {
  7983. return this.each(function() {
  7984. jQuery.dequeue( this, type );
  7985. });
  7986. },
  7987. clearQueue: function( type ) {
  7988. return this.queue( type || "fx", [] );
  7989. },
  7990. // Get a promise resolved when queues of a certain type
  7991. // are emptied (fx is the type by default)
  7992. promise: function( type, obj ) {
  7993. var tmp,
  7994. count = 1,
  7995. defer = jQuery.Deferred(),
  7996. elements = this,
  7997. i = this.length,
  7998. resolve = function() {
  7999. if ( !( --count ) ) {
  8000. defer.resolveWith( elements, [ elements ] );
  8001. }
  8002. };
  8003. if ( typeof type !== "string" ) {
  8004. obj = type;
  8005. type = undefined;
  8006. }
  8007. type = type || "fx";
  8008. while ( i-- ) {
  8009. tmp = data_priv.get( elements[ i ], type + "queueHooks" );
  8010. if ( tmp && tmp.empty ) {
  8011. count++;
  8012. tmp.empty.add( resolve );
  8013. }
  8014. }
  8015. resolve();
  8016. return defer.promise( obj );
  8017. }
  8018. });
  8019. var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
  8020. var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
  8021. var isHidden = function( elem, el ) {
  8022. // isHidden might be called from jQuery#filter function;
  8023. // in that case, element will be second argument
  8024. elem = el || elem;
  8025. return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
  8026. };
  8027. var rcheckableType = (/^(?:checkbox|radio)$/i);
  8028. (function() {
  8029. var fragment = document.createDocumentFragment(),
  8030. div = fragment.appendChild( document.createElement( "div" ) ),
  8031. input = document.createElement( "input" );
  8032. // Support: Safari<=5.1
  8033. // Check state lost if the name is set (#11217)
  8034. // Support: Windows Web Apps (WWA)
  8035. // `name` and `type` must use .setAttribute for WWA (#14901)
  8036. input.setAttribute( "type", "radio" );
  8037. input.setAttribute( "checked", "checked" );
  8038. input.setAttribute( "name", "t" );
  8039. div.appendChild( input );
  8040. // Support: Safari<=5.1, Android<4.2
  8041. // Older WebKit doesn't clone checked state correctly in fragments
  8042. support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
  8043. // Support: IE<=11+
  8044. // Make sure textarea (and checkbox) defaultValue is properly cloned
  8045. div.innerHTML = "<textarea>x</textarea>";
  8046. support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
  8047. })();
  8048. var strundefined = typeof undefined;
  8049. support.focusinBubbles = "onfocusin" in window;
  8050. var
  8051. rkeyEvent = /^key/,
  8052. rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
  8053. rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
  8054. rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
  8055. function returnTrue() {
  8056. return true;
  8057. }
  8058. function returnFalse() {
  8059. return false;
  8060. }
  8061. function safeActiveElement() {
  8062. try {
  8063. return document.activeElement;
  8064. } catch ( err ) { }
  8065. }
  8066. /*
  8067. * Helper functions for managing events -- not part of the public interface.
  8068. * Props to Dean Edwards' addEvent library for many of the ideas.
  8069. */
  8070. jQuery.event = {
  8071. global: {},
  8072. add: function( elem, types, handler, data, selector ) {
  8073. var handleObjIn, eventHandle, tmp,
  8074. events, t, handleObj,
  8075. special, handlers, type, namespaces, origType,
  8076. elemData = data_priv.get( elem );
  8077. // Don't attach events to noData or text/comment nodes (but allow plain objects)
  8078. if ( !elemData ) {
  8079. return;
  8080. }
  8081. // Caller can pass in an object of custom data in lieu of the handler
  8082. if ( handler.handler ) {
  8083. handleObjIn = handler;
  8084. handler = handleObjIn.handler;
  8085. selector = handleObjIn.selector;
  8086. }
  8087. // Make sure that the handler has a unique ID, used to find/remove it later
  8088. if ( !handler.guid ) {
  8089. handler.guid = jQuery.guid++;
  8090. }
  8091. // Init the element's event structure and main handler, if this is the first
  8092. if ( !(events = elemData.events) ) {
  8093. events = elemData.events = {};
  8094. }
  8095. if ( !(eventHandle = elemData.handle) ) {
  8096. eventHandle = elemData.handle = function( e ) {
  8097. // Discard the second event of a jQuery.event.trigger() and
  8098. // when an event is called after a page has unloaded
  8099. return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
  8100. jQuery.event.dispatch.apply( elem, arguments ) : undefined;
  8101. };
  8102. }
  8103. // Handle multiple events separated by a space
  8104. types = ( types || "" ).match( rnotwhite ) || [ "" ];
  8105. t = types.length;
  8106. while ( t-- ) {
  8107. tmp = rtypenamespace.exec( types[t] ) || [];
  8108. type = origType = tmp[1];
  8109. namespaces = ( tmp[2] || "" ).split( "." ).sort();
  8110. // There *must* be a type, no attaching namespace-only handlers
  8111. if ( !type ) {
  8112. continue;
  8113. }
  8114. // If event changes its type, use the special event handlers for the changed type
  8115. special = jQuery.event.special[ type ] || {};
  8116. // If selector defined, determine special event api type, otherwise given type
  8117. type = ( selector ? special.delegateType : special.bindType ) || type;
  8118. // Update special based on newly reset type
  8119. special = jQuery.event.special[ type ] || {};
  8120. // handleObj is passed to all event handlers
  8121. handleObj = jQuery.extend({
  8122. type: type,
  8123. origType: origType,
  8124. data: data,
  8125. handler: handler,
  8126. guid: handler.guid,
  8127. selector: selector,
  8128. needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
  8129. namespace: namespaces.join(".")
  8130. }, handleObjIn );
  8131. // Init the event handler queue if we're the first
  8132. if ( !(handlers = events[ type ]) ) {
  8133. handlers = events[ type ] = [];
  8134. handlers.delegateCount = 0;
  8135. // Only use addEventListener if the special events handler returns false
  8136. if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
  8137. if ( elem.addEventListener ) {
  8138. elem.addEventListener( type, eventHandle, false );
  8139. }
  8140. }
  8141. }
  8142. if ( special.add ) {
  8143. special.add.call( elem, handleObj );
  8144. if ( !handleObj.handler.guid ) {
  8145. handleObj.handler.guid = handler.guid;
  8146. }
  8147. }
  8148. // Add to the element's handler list, delegates in front
  8149. if ( selector ) {
  8150. handlers.splice( handlers.delegateCount++, 0, handleObj );
  8151. } else {
  8152. handlers.push( handleObj );
  8153. }
  8154. // Keep track of which events have ever been used, for event optimization
  8155. jQuery.event.global[ type ] = true;
  8156. }
  8157. },
  8158. // Detach an event or set of events from an element
  8159. remove: function( elem, types, handler, selector, mappedTypes ) {
  8160. var j, origCount, tmp,
  8161. events, t, handleObj,
  8162. special, handlers, type, namespaces, origType,
  8163. elemData = data_priv.hasData( elem ) && data_priv.get( elem );
  8164. if ( !elemData || !(events = elemData.events) ) {
  8165. return;
  8166. }
  8167. // Once for each type.namespace in types; type may be omitted
  8168. types = ( types || "" ).match( rnotwhite ) || [ "" ];
  8169. t = types.length;
  8170. while ( t-- ) {
  8171. tmp = rtypenamespace.exec( types[t] ) || [];
  8172. type = origType = tmp[1];
  8173. namespaces = ( tmp[2] || "" ).split( "." ).sort();
  8174. // Unbind all events (on this namespace, if provided) for the element
  8175. if ( !type ) {
  8176. for ( type in events ) {
  8177. jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
  8178. }
  8179. continue;
  8180. }
  8181. special = jQuery.event.special[ type ] || {};
  8182. type = ( selector ? special.delegateType : special.bindType ) || type;
  8183. handlers = events[ type ] || [];
  8184. tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
  8185. // Remove matching events
  8186. origCount = j = handlers.length;
  8187. while ( j-- ) {
  8188. handleObj = handlers[ j ];
  8189. if ( ( mappedTypes || origType === handleObj.origType ) &&
  8190. ( !handler || handler.guid === handleObj.guid ) &&
  8191. ( !tmp || tmp.test( handleObj.namespace ) ) &&
  8192. ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
  8193. handlers.splice( j, 1 );
  8194. if ( handleObj.selector ) {
  8195. handlers.delegateCount--;
  8196. }
  8197. if ( special.remove ) {
  8198. special.remove.call( elem, handleObj );
  8199. }
  8200. }
  8201. }
  8202. // Remove generic event handler if we removed something and no more handlers exist
  8203. // (avoids potential for endless recursion during removal of special event handlers)
  8204. if ( origCount && !handlers.length ) {
  8205. if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
  8206. jQuery.removeEvent( elem, type, elemData.handle );
  8207. }
  8208. delete events[ type ];
  8209. }
  8210. }
  8211. // Remove the expando if it's no longer used
  8212. if ( jQuery.isEmptyObject( events ) ) {
  8213. delete elemData.handle;
  8214. data_priv.remove( elem, "events" );
  8215. }
  8216. },
  8217. trigger: function( event, data, elem, onlyHandlers ) {
  8218. var i, cur, tmp, bubbleType, ontype, handle, special,
  8219. eventPath = [ elem || document ],
  8220. type = hasOwn.call( event, "type" ) ? event.type : event,
  8221. namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
  8222. cur = tmp = elem = elem || document;
  8223. // Don't do events on text and comment nodes
  8224. if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
  8225. return;
  8226. }
  8227. // focus/blur morphs to focusin/out; ensure we're not firing them right now
  8228. if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
  8229. return;
  8230. }
  8231. if ( type.indexOf(".") >= 0 ) {
  8232. // Namespaced trigger; create a regexp to match event type in handle()
  8233. namespaces = type.split(".");
  8234. type = namespaces.shift();
  8235. namespaces.sort();
  8236. }
  8237. ontype = type.indexOf(":") < 0 && "on" + type;
  8238. // Caller can pass in a jQuery.Event object, Object, or just an event type string
  8239. event = event[ jQuery.expando ] ?
  8240. event :
  8241. new jQuery.Event( type, typeof event === "object" && event );
  8242. // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
  8243. event.isTrigger = onlyHandlers ? 2 : 3;
  8244. event.namespace = namespaces.join(".");
  8245. event.namespace_re = event.namespace ?
  8246. new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
  8247. null;
  8248. // Clean up the event in case it is being reused
  8249. event.result = undefined;
  8250. if ( !event.target ) {
  8251. event.target = elem;
  8252. }
  8253. // Clone any incoming data and prepend the event, creating the handler arg list
  8254. data = data == null ?
  8255. [ event ] :
  8256. jQuery.makeArray( data, [ event ] );
  8257. // Allow special events to draw outside the lines
  8258. special = jQuery.event.special[ type ] || {};
  8259. if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
  8260. return;
  8261. }
  8262. // Determine event propagation path in advance, per W3C events spec (#9951)
  8263. // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
  8264. if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
  8265. bubbleType = special.delegateType || type;
  8266. if ( !rfocusMorph.test( bubbleType + type ) ) {
  8267. cur = cur.parentNode;
  8268. }
  8269. for ( ; cur; cur = cur.parentNode ) {
  8270. eventPath.push( cur );
  8271. tmp = cur;
  8272. }
  8273. // Only add window if we got to document (e.g., not plain obj or detached DOM)
  8274. if ( tmp === (elem.ownerDocument || document) ) {
  8275. eventPath.push( tmp.defaultView || tmp.parentWindow || window );
  8276. }
  8277. }
  8278. // Fire handlers on the event path
  8279. i = 0;
  8280. while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
  8281. event.type = i > 1 ?
  8282. bubbleType :
  8283. special.bindType || type;
  8284. // jQuery handler
  8285. handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
  8286. if ( handle ) {
  8287. handle.apply( cur, data );
  8288. }
  8289. // Native handler
  8290. handle = ontype && cur[ ontype ];
  8291. if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
  8292. event.result = handle.apply( cur, data );
  8293. if ( event.result === false ) {
  8294. event.preventDefault();
  8295. }
  8296. }
  8297. }
  8298. event.type = type;
  8299. // If nobody prevented the default action, do it now
  8300. if ( !onlyHandlers && !event.isDefaultPrevented() ) {
  8301. if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
  8302. jQuery.acceptData( elem ) ) {
  8303. // Call a native DOM method on the target with the same name name as the event.
  8304. // Don't do default actions on window, that's where global variables be (#6170)
  8305. if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
  8306. // Don't re-trigger an onFOO event when we call its FOO() method
  8307. tmp = elem[ ontype ];
  8308. if ( tmp ) {
  8309. elem[ ontype ] = null;
  8310. }
  8311. // Prevent re-triggering of the same event, since we already bubbled it above
  8312. jQuery.event.triggered = type;
  8313. elem[ type ]();
  8314. jQuery.event.triggered = undefined;
  8315. if ( tmp ) {
  8316. elem[ ontype ] = tmp;
  8317. }
  8318. }
  8319. }
  8320. }
  8321. return event.result;
  8322. },
  8323. dispatch: function( event ) {
  8324. // Make a writable jQuery.Event from the native event object
  8325. event = jQuery.event.fix( event );
  8326. var i, j, ret, matched, handleObj,
  8327. handlerQueue = [],
  8328. args = slice.call( arguments ),
  8329. handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
  8330. special = jQuery.event.special[ event.type ] || {};
  8331. // Use the fix-ed jQuery.Event rather than the (read-only) native event
  8332. args[0] = event;
  8333. event.delegateTarget = this;
  8334. // Call the preDispatch hook for the mapped type, and let it bail if desired
  8335. if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
  8336. return;
  8337. }
  8338. // Determine handlers
  8339. handlerQueue = jQuery.event.handlers.call( this, event, handlers );
  8340. // Run delegates first; they may want to stop propagation beneath us
  8341. i = 0;
  8342. while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
  8343. event.currentTarget = matched.elem;
  8344. j = 0;
  8345. while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
  8346. // Triggered event must either 1) have no namespace, or 2) have namespace(s)
  8347. // a subset or equal to those in the bound event (both can have no namespace).
  8348. if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
  8349. event.handleObj = handleObj;
  8350. event.data = handleObj.data;
  8351. ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
  8352. .apply( matched.elem, args );
  8353. if ( ret !== undefined ) {
  8354. if ( (event.result = ret) === false ) {
  8355. event.preventDefault();
  8356. event.stopPropagation();
  8357. }
  8358. }
  8359. }
  8360. }
  8361. }
  8362. // Call the postDispatch hook for the mapped type
  8363. if ( special.postDispatch ) {
  8364. special.postDispatch.call( this, event );
  8365. }
  8366. return event.result;
  8367. },
  8368. handlers: function( event, handlers ) {
  8369. var i, matches, sel, handleObj,
  8370. handlerQueue = [],
  8371. delegateCount = handlers.delegateCount,
  8372. cur = event.target;
  8373. // Find delegate handlers
  8374. // Black-hole SVG <use> instance trees (#13180)
  8375. // Avoid non-left-click bubbling in Firefox (#3861)
  8376. if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
  8377. for ( ; cur !== this; cur = cur.parentNode || this ) {
  8378. // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
  8379. if ( cur.disabled !== true || event.type !== "click" ) {
  8380. matches = [];
  8381. for ( i = 0; i < delegateCount; i++ ) {
  8382. handleObj = handlers[ i ];
  8383. // Don't conflict with Object.prototype properties (#13203)
  8384. sel = handleObj.selector + " ";
  8385. if ( matches[ sel ] === undefined ) {
  8386. matches[ sel ] = handleObj.needsContext ?
  8387. jQuery( sel, this ).index( cur ) >= 0 :
  8388. jQuery.find( sel, this, null, [ cur ] ).length;
  8389. }
  8390. if ( matches[ sel ] ) {
  8391. matches.push( handleObj );
  8392. }
  8393. }
  8394. if ( matches.length ) {
  8395. handlerQueue.push({ elem: cur, handlers: matches });
  8396. }
  8397. }
  8398. }
  8399. }
  8400. // Add the remaining (directly-bound) handlers
  8401. if ( delegateCount < handlers.length ) {
  8402. handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
  8403. }
  8404. return handlerQueue;
  8405. },
  8406. // Includes some event props shared by KeyEvent and MouseEvent
  8407. props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
  8408. fixHooks: {},
  8409. keyHooks: {
  8410. props: "char charCode key keyCode".split(" "),
  8411. filter: function( event, original ) {
  8412. // Add which for key events
  8413. if ( event.which == null ) {
  8414. event.which = original.charCode != null ? original.charCode : original.keyCode;
  8415. }
  8416. return event;
  8417. }
  8418. },
  8419. mouseHooks: {
  8420. props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
  8421. filter: function( event, original ) {
  8422. var eventDoc, doc, body,
  8423. button = original.button;
  8424. // Calculate pageX/Y if missing and clientX/Y available
  8425. if ( event.pageX == null && original.clientX != null ) {
  8426. eventDoc = event.target.ownerDocument || document;
  8427. doc = eventDoc.documentElement;
  8428. body = eventDoc.body;
  8429. event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
  8430. event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
  8431. }
  8432. // Add which for click: 1 === left; 2 === middle; 3 === right
  8433. // Note: button is not normalized, so don't use it
  8434. if ( !event.which && button !== undefined ) {
  8435. event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
  8436. }
  8437. return event;
  8438. }
  8439. },
  8440. fix: function( event ) {
  8441. if ( event[ jQuery.expando ] ) {
  8442. return event;
  8443. }
  8444. // Create a writable copy of the event object and normalize some properties
  8445. var i, prop, copy,
  8446. type = event.type,
  8447. originalEvent = event,
  8448. fixHook = this.fixHooks[ type ];
  8449. if ( !fixHook ) {
  8450. this.fixHooks[ type ] = fixHook =
  8451. rmouseEvent.test( type ) ? this.mouseHooks :
  8452. rkeyEvent.test( type ) ? this.keyHooks :
  8453. {};
  8454. }
  8455. copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
  8456. event = new jQuery.Event( originalEvent );
  8457. i = copy.length;
  8458. while ( i-- ) {
  8459. prop = copy[ i ];
  8460. event[ prop ] = originalEvent[ prop ];
  8461. }
  8462. // Support: Cordova 2.5 (WebKit) (#13255)
  8463. // All events should have a target; Cordova deviceready doesn't
  8464. if ( !event.target ) {
  8465. event.target = document;
  8466. }
  8467. // Support: Safari 6.0+, Chrome<28
  8468. // Target should not be a text node (#504, #13143)
  8469. if ( event.target.nodeType === 3 ) {
  8470. event.target = event.target.parentNode;
  8471. }
  8472. return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
  8473. },
  8474. special: {
  8475. load: {
  8476. // Prevent triggered image.load events from bubbling to window.load
  8477. noBubble: true
  8478. },
  8479. focus: {
  8480. // Fire native event if possible so blur/focus sequence is correct
  8481. trigger: function() {
  8482. if ( this !== safeActiveElement() && this.focus ) {
  8483. this.focus();
  8484. return false;
  8485. }
  8486. },
  8487. delegateType: "focusin"
  8488. },
  8489. blur: {
  8490. trigger: function() {
  8491. if ( this === safeActiveElement() && this.blur ) {
  8492. this.blur();
  8493. return false;
  8494. }
  8495. },
  8496. delegateType: "focusout"
  8497. },
  8498. click: {
  8499. // For checkbox, fire native event so checked state will be right
  8500. trigger: function() {
  8501. if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
  8502. this.click();
  8503. return false;
  8504. }
  8505. },
  8506. // For cross-browser consistency, don't fire native .click() on links
  8507. _default: function( event ) {
  8508. return jQuery.nodeName( event.target, "a" );
  8509. }
  8510. },
  8511. beforeunload: {
  8512. postDispatch: function( event ) {
  8513. // Support: Firefox 20+
  8514. // Firefox doesn't alert if the returnValue field is not set.
  8515. if ( event.result !== undefined && event.originalEvent ) {
  8516. event.originalEvent.returnValue = event.result;
  8517. }
  8518. }
  8519. }
  8520. },
  8521. simulate: function( type, elem, event, bubble ) {
  8522. // Piggyback on a donor event to simulate a different one.
  8523. // Fake originalEvent to avoid donor's stopPropagation, but if the
  8524. // simulated event prevents default then we do the same on the donor.
  8525. var e = jQuery.extend(
  8526. new jQuery.Event(),
  8527. event,
  8528. {
  8529. type: type,
  8530. isSimulated: true,
  8531. originalEvent: {}
  8532. }
  8533. );
  8534. if ( bubble ) {
  8535. jQuery.event.trigger( e, null, elem );
  8536. } else {
  8537. jQuery.event.dispatch.call( elem, e );
  8538. }
  8539. if ( e.isDefaultPrevented() ) {
  8540. event.preventDefault();
  8541. }
  8542. }
  8543. };
  8544. jQuery.removeEvent = function( elem, type, handle ) {
  8545. if ( elem.removeEventListener ) {
  8546. elem.removeEventListener( type, handle, false );
  8547. }
  8548. };
  8549. jQuery.Event = function( src, props ) {
  8550. // Allow instantiation without the 'new' keyword
  8551. if ( !(this instanceof jQuery.Event) ) {
  8552. return new jQuery.Event( src, props );
  8553. }
  8554. // Event object
  8555. if ( src && src.type ) {
  8556. this.originalEvent = src;
  8557. this.type = src.type;
  8558. // Events bubbling up the document may have been marked as prevented
  8559. // by a handler lower down the tree; reflect the correct value.
  8560. this.isDefaultPrevented = src.defaultPrevented ||
  8561. src.defaultPrevented === undefined &&
  8562. // Support: Android<4.0
  8563. src.returnValue === false ?
  8564. returnTrue :
  8565. returnFalse;
  8566. // Event type
  8567. } else {
  8568. this.type = src;
  8569. }
  8570. // Put explicitly provided properties onto the event object
  8571. if ( props ) {
  8572. jQuery.extend( this, props );
  8573. }
  8574. // Create a timestamp if incoming event doesn't have one
  8575. this.timeStamp = src && src.timeStamp || jQuery.now();
  8576. // Mark it as fixed
  8577. this[ jQuery.expando ] = true;
  8578. };
  8579. // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
  8580. // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  8581. jQuery.Event.prototype = {
  8582. isDefaultPrevented: returnFalse,
  8583. isPropagationStopped: returnFalse,
  8584. isImmediatePropagationStopped: returnFalse,
  8585. preventDefault: function() {
  8586. var e = this.originalEvent;
  8587. this.isDefaultPrevented = returnTrue;
  8588. if ( e && e.preventDefault ) {
  8589. e.preventDefault();
  8590. }
  8591. },
  8592. stopPropagation: function() {
  8593. var e = this.originalEvent;
  8594. this.isPropagationStopped = returnTrue;
  8595. if ( e && e.stopPropagation ) {
  8596. e.stopPropagation();
  8597. }
  8598. },
  8599. stopImmediatePropagation: function() {
  8600. var e = this.originalEvent;
  8601. this.isImmediatePropagationStopped = returnTrue;
  8602. if ( e && e.stopImmediatePropagation ) {
  8603. e.stopImmediatePropagation();
  8604. }
  8605. this.stopPropagation();
  8606. }
  8607. };
  8608. // Create mouseenter/leave events using mouseover/out and event-time checks
  8609. // Support: Chrome 15+
  8610. jQuery.each({
  8611. mouseenter: "mouseover",
  8612. mouseleave: "mouseout",
  8613. pointerenter: "pointerover",
  8614. pointerleave: "pointerout"
  8615. }, function( orig, fix ) {
  8616. jQuery.event.special[ orig ] = {
  8617. delegateType: fix,
  8618. bindType: fix,
  8619. handle: function( event ) {
  8620. var ret,
  8621. target = this,
  8622. related = event.relatedTarget,
  8623. handleObj = event.handleObj;
  8624. // For mousenter/leave call the handler if related is outside the target.
  8625. // NB: No relatedTarget if the mouse left/entered the browser window
  8626. if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
  8627. event.type = handleObj.origType;
  8628. ret = handleObj.handler.apply( this, arguments );
  8629. event.type = fix;
  8630. }
  8631. return ret;
  8632. }
  8633. };
  8634. });
  8635. // Support: Firefox, Chrome, Safari
  8636. // Create "bubbling" focus and blur events
  8637. if ( !support.focusinBubbles ) {
  8638. jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
  8639. // Attach a single capturing handler on the document while someone wants focusin/focusout
  8640. var handler = function( event ) {
  8641. jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
  8642. };
  8643. jQuery.event.special[ fix ] = {
  8644. setup: function() {
  8645. var doc = this.ownerDocument || this,
  8646. attaches = data_priv.access( doc, fix );
  8647. if ( !attaches ) {
  8648. doc.addEventListener( orig, handler, true );
  8649. }
  8650. data_priv.access( doc, fix, ( attaches || 0 ) + 1 );
  8651. },
  8652. teardown: function() {
  8653. var doc = this.ownerDocument || this,
  8654. attaches = data_priv.access( doc, fix ) - 1;
  8655. if ( !attaches ) {
  8656. doc.removeEventListener( orig, handler, true );
  8657. data_priv.remove( doc, fix );
  8658. } else {
  8659. data_priv.access( doc, fix, attaches );
  8660. }
  8661. }
  8662. };
  8663. });
  8664. }
  8665. jQuery.fn.extend({
  8666. on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
  8667. var origFn, type;
  8668. // Types can be a map of types/handlers
  8669. if ( typeof types === "object" ) {
  8670. // ( types-Object, selector, data )
  8671. if ( typeof selector !== "string" ) {
  8672. // ( types-Object, data )
  8673. data = data || selector;
  8674. selector = undefined;
  8675. }
  8676. for ( type in types ) {
  8677. this.on( type, selector, data, types[ type ], one );
  8678. }
  8679. return this;
  8680. }
  8681. if ( data == null && fn == null ) {
  8682. // ( types, fn )
  8683. fn = selector;
  8684. data = selector = undefined;
  8685. } else if ( fn == null ) {
  8686. if ( typeof selector === "string" ) {
  8687. // ( types, selector, fn )
  8688. fn = data;
  8689. data = undefined;
  8690. } else {
  8691. // ( types, data, fn )
  8692. fn = data;
  8693. data = selector;
  8694. selector = undefined;
  8695. }
  8696. }
  8697. if ( fn === false ) {
  8698. fn = returnFalse;
  8699. } else if ( !fn ) {
  8700. return this;
  8701. }
  8702. if ( one === 1 ) {
  8703. origFn = fn;
  8704. fn = function( event ) {
  8705. // Can use an empty set, since event contains the info
  8706. jQuery().off( event );
  8707. return origFn.apply( this, arguments );
  8708. };
  8709. // Use same guid so caller can remove using origFn
  8710. fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
  8711. }
  8712. return this.each( function() {
  8713. jQuery.event.add( this, types, fn, data, selector );
  8714. });
  8715. },
  8716. one: function( types, selector, data, fn ) {
  8717. return this.on( types, selector, data, fn, 1 );
  8718. },
  8719. off: function( types, selector, fn ) {
  8720. var handleObj, type;
  8721. if ( types && types.preventDefault && types.handleObj ) {
  8722. // ( event ) dispatched jQuery.Event
  8723. handleObj = types.handleObj;
  8724. jQuery( types.delegateTarget ).off(
  8725. handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
  8726. handleObj.selector,
  8727. handleObj.handler
  8728. );
  8729. return this;
  8730. }
  8731. if ( typeof types === "object" ) {
  8732. // ( types-object [, selector] )
  8733. for ( type in types ) {
  8734. this.off( type, selector, types[ type ] );
  8735. }
  8736. return this;
  8737. }
  8738. if ( selector === false || typeof selector === "function" ) {
  8739. // ( types [, fn] )
  8740. fn = selector;
  8741. selector = undefined;
  8742. }
  8743. if ( fn === false ) {
  8744. fn = returnFalse;
  8745. }
  8746. return this.each(function() {
  8747. jQuery.event.remove( this, types, fn, selector );
  8748. });
  8749. },
  8750. trigger: function( type, data ) {
  8751. return this.each(function() {
  8752. jQuery.event.trigger( type, data, this );
  8753. });
  8754. },
  8755. triggerHandler: function( type, data ) {
  8756. var elem = this[0];
  8757. if ( elem ) {
  8758. return jQuery.event.trigger( type, data, elem, true );
  8759. }
  8760. }
  8761. });
  8762. var
  8763. rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
  8764. rtagName = /<([\w:]+)/,
  8765. rhtml = /<|&#?\w+;/,
  8766. rnoInnerhtml = /<(?:script|style|link)/i,
  8767. // checked="checked" or checked
  8768. rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
  8769. rscriptType = /^$|\/(?:java|ecma)script/i,
  8770. rscriptTypeMasked = /^true\/(.*)/,
  8771. rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
  8772. // We have to close these tags to support XHTML (#13200)
  8773. wrapMap = {
  8774. // Support: IE9
  8775. option: [ 1, "<select multiple='multiple'>", "</select>" ],
  8776. thead: [ 1, "<table>", "</table>" ],
  8777. col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
  8778. tr: [ 2, "<table><tbody>", "</tbody></table>" ],
  8779. td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
  8780. _default: [ 0, "", "" ]
  8781. };
  8782. // Support: IE9
  8783. wrapMap.optgroup = wrapMap.option;
  8784. wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
  8785. wrapMap.th = wrapMap.td;
  8786. // Support: 1.x compatibility
  8787. // Manipulating tables requires a tbody
  8788. function manipulationTarget( elem, content ) {
  8789. return jQuery.nodeName( elem, "table" ) &&
  8790. jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
  8791. elem.getElementsByTagName("tbody")[0] ||
  8792. elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
  8793. elem;
  8794. }
  8795. // Replace/restore the type attribute of script elements for safe DOM manipulation
  8796. function disableScript( elem ) {
  8797. elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
  8798. return elem;
  8799. }
  8800. function restoreScript( elem ) {
  8801. var match = rscriptTypeMasked.exec( elem.type );
  8802. if ( match ) {
  8803. elem.type = match[ 1 ];
  8804. } else {
  8805. elem.removeAttribute("type");
  8806. }
  8807. return elem;
  8808. }
  8809. // Mark scripts as having already been evaluated
  8810. function setGlobalEval( elems, refElements ) {
  8811. var i = 0,
  8812. l = elems.length;
  8813. for ( ; i < l; i++ ) {
  8814. data_priv.set(
  8815. elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )
  8816. );
  8817. }
  8818. }
  8819. function cloneCopyEvent( src, dest ) {
  8820. var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
  8821. if ( dest.nodeType !== 1 ) {
  8822. return;
  8823. }
  8824. // 1. Copy private data: events, handlers, etc.
  8825. if ( data_priv.hasData( src ) ) {
  8826. pdataOld = data_priv.access( src );
  8827. pdataCur = data_priv.set( dest, pdataOld );
  8828. events = pdataOld.events;
  8829. if ( events ) {
  8830. delete pdataCur.handle;
  8831. pdataCur.events = {};
  8832. for ( type in events ) {
  8833. for ( i = 0, l = events[ type ].length; i < l; i++ ) {
  8834. jQuery.event.add( dest, type, events[ type ][ i ] );
  8835. }
  8836. }
  8837. }
  8838. }
  8839. // 2. Copy user data
  8840. if ( data_user.hasData( src ) ) {
  8841. udataOld = data_user.access( src );
  8842. udataCur = jQuery.extend( {}, udataOld );
  8843. data_user.set( dest, udataCur );
  8844. }
  8845. }
  8846. function getAll( context, tag ) {
  8847. var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :
  8848. context.querySelectorAll ? context.querySelectorAll( tag || "*" ) :
  8849. [];
  8850. return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
  8851. jQuery.merge( [ context ], ret ) :
  8852. ret;
  8853. }
  8854. // Fix IE bugs, see support tests
  8855. function fixInput( src, dest ) {
  8856. var nodeName = dest.nodeName.toLowerCase();
  8857. // Fails to persist the checked state of a cloned checkbox or radio button.
  8858. if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
  8859. dest.checked = src.checked;
  8860. // Fails to return the selected option to the default selected state when cloning options
  8861. } else if ( nodeName === "input" || nodeName === "textarea" ) {
  8862. dest.defaultValue = src.defaultValue;
  8863. }
  8864. }
  8865. jQuery.extend({
  8866. clone: function( elem, dataAndEvents, deepDataAndEvents ) {
  8867. var i, l, srcElements, destElements,
  8868. clone = elem.cloneNode( true ),
  8869. inPage = jQuery.contains( elem.ownerDocument, elem );
  8870. // Fix IE cloning issues
  8871. if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
  8872. !jQuery.isXMLDoc( elem ) ) {
  8873. // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
  8874. destElements = getAll( clone );
  8875. srcElements = getAll( elem );
  8876. for ( i = 0, l = srcElements.length; i < l; i++ ) {
  8877. fixInput( srcElements[ i ], destElements[ i ] );
  8878. }
  8879. }
  8880. // Copy the events from the original to the clone
  8881. if ( dataAndEvents ) {
  8882. if ( deepDataAndEvents ) {
  8883. srcElements = srcElements || getAll( elem );
  8884. destElements = destElements || getAll( clone );
  8885. for ( i = 0, l = srcElements.length; i < l; i++ ) {
  8886. cloneCopyEvent( srcElements[ i ], destElements[ i ] );
  8887. }
  8888. } else {
  8889. cloneCopyEvent( elem, clone );
  8890. }
  8891. }
  8892. // Preserve script evaluation history
  8893. destElements = getAll( clone, "script" );
  8894. if ( destElements.length > 0 ) {
  8895. setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
  8896. }
  8897. // Return the cloned set
  8898. return clone;
  8899. },
  8900. buildFragment: function( elems, context, scripts, selection ) {
  8901. var elem, tmp, tag, wrap, contains, j,
  8902. fragment = context.createDocumentFragment(),
  8903. nodes = [],
  8904. i = 0,
  8905. l = elems.length;
  8906. for ( ; i < l; i++ ) {
  8907. elem = elems[ i ];
  8908. if ( elem || elem === 0 ) {
  8909. // Add nodes directly
  8910. if ( jQuery.type( elem ) === "object" ) {
  8911. // Support: QtWebKit, PhantomJS
  8912. // push.apply(_, arraylike) throws on ancient WebKit
  8913. jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
  8914. // Convert non-html into a text node
  8915. } else if ( !rhtml.test( elem ) ) {
  8916. nodes.push( context.createTextNode( elem ) );
  8917. // Convert html into DOM nodes
  8918. } else {
  8919. tmp = tmp || fragment.appendChild( context.createElement("div") );
  8920. // Deserialize a standard representation
  8921. tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
  8922. wrap = wrapMap[ tag ] || wrapMap._default;
  8923. tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];
  8924. // Descend through wrappers to the right content
  8925. j = wrap[ 0 ];
  8926. while ( j-- ) {
  8927. tmp = tmp.lastChild;
  8928. }
  8929. // Support: QtWebKit, PhantomJS
  8930. // push.apply(_, arraylike) throws on ancient WebKit
  8931. jQuery.merge( nodes, tmp.childNodes );
  8932. // Remember the top-level container
  8933. tmp = fragment.firstChild;
  8934. // Ensure the created nodes are orphaned (#12392)
  8935. tmp.textContent = "";
  8936. }
  8937. }
  8938. }
  8939. // Remove wrapper from fragment
  8940. fragment.textContent = "";
  8941. i = 0;
  8942. while ( (elem = nodes[ i++ ]) ) {
  8943. // #4087 - If origin and destination elements are the same, and this is
  8944. // that element, do not do anything
  8945. if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
  8946. continue;
  8947. }
  8948. contains = jQuery.contains( elem.ownerDocument, elem );
  8949. // Append to fragment
  8950. tmp = getAll( fragment.appendChild( elem ), "script" );
  8951. // Preserve script evaluation history
  8952. if ( contains ) {
  8953. setGlobalEval( tmp );
  8954. }
  8955. // Capture executables
  8956. if ( scripts ) {
  8957. j = 0;
  8958. while ( (elem = tmp[ j++ ]) ) {
  8959. if ( rscriptType.test( elem.type || "" ) ) {
  8960. scripts.push( elem );
  8961. }
  8962. }
  8963. }
  8964. }
  8965. return fragment;
  8966. },
  8967. cleanData: function( elems ) {
  8968. var data, elem, type, key,
  8969. special = jQuery.event.special,
  8970. i = 0;
  8971. for ( ; (elem = elems[ i ]) !== undefined; i++ ) {
  8972. if ( jQuery.acceptData( elem ) ) {
  8973. key = elem[ data_priv.expando ];
  8974. if ( key && (data = data_priv.cache[ key ]) ) {
  8975. if ( data.events ) {
  8976. for ( type in data.events ) {
  8977. if ( special[ type ] ) {
  8978. jQuery.event.remove( elem, type );
  8979. // This is a shortcut to avoid jQuery.event.remove's overhead
  8980. } else {
  8981. jQuery.removeEvent( elem, type, data.handle );
  8982. }
  8983. }
  8984. }
  8985. if ( data_priv.cache[ key ] ) {
  8986. // Discard any remaining `private` data
  8987. delete data_priv.cache[ key ];
  8988. }
  8989. }
  8990. }
  8991. // Discard any remaining `user` data
  8992. delete data_user.cache[ elem[ data_user.expando ] ];
  8993. }
  8994. }
  8995. });
  8996. jQuery.fn.extend({
  8997. text: function( value ) {
  8998. return access( this, function( value ) {
  8999. return value === undefined ?
  9000. jQuery.text( this ) :
  9001. this.empty().each(function() {
  9002. if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  9003. this.textContent = value;
  9004. }
  9005. });
  9006. }, null, value, arguments.length );
  9007. },
  9008. append: function() {
  9009. return this.domManip( arguments, function( elem ) {
  9010. if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  9011. var target = manipulationTarget( this, elem );
  9012. target.appendChild( elem );
  9013. }
  9014. });
  9015. },
  9016. prepend: function() {
  9017. return this.domManip( arguments, function( elem ) {
  9018. if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  9019. var target = manipulationTarget( this, elem );
  9020. target.insertBefore( elem, target.firstChild );
  9021. }
  9022. });
  9023. },
  9024. before: function() {
  9025. return this.domManip( arguments, function( elem ) {
  9026. if ( this.parentNode ) {
  9027. this.parentNode.insertBefore( elem, this );
  9028. }
  9029. });
  9030. },
  9031. after: function() {
  9032. return this.domManip( arguments, function( elem ) {
  9033. if ( this.parentNode ) {
  9034. this.parentNode.insertBefore( elem, this.nextSibling );
  9035. }
  9036. });
  9037. },
  9038. remove: function( selector, keepData /* Internal Use Only */ ) {
  9039. var elem,
  9040. elems = selector ? jQuery.filter( selector, this ) : this,
  9041. i = 0;
  9042. for ( ; (elem = elems[i]) != null; i++ ) {
  9043. if ( !keepData && elem.nodeType === 1 ) {
  9044. jQuery.cleanData( getAll( elem ) );
  9045. }
  9046. if ( elem.parentNode ) {
  9047. if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
  9048. setGlobalEval( getAll( elem, "script" ) );
  9049. }
  9050. elem.parentNode.removeChild( elem );
  9051. }
  9052. }
  9053. return this;
  9054. },
  9055. empty: function() {
  9056. var elem,
  9057. i = 0;
  9058. for ( ; (elem = this[i]) != null; i++ ) {
  9059. if ( elem.nodeType === 1 ) {
  9060. // Prevent memory leaks
  9061. jQuery.cleanData( getAll( elem, false ) );
  9062. // Remove any remaining nodes
  9063. elem.textContent = "";
  9064. }
  9065. }
  9066. return this;
  9067. },
  9068. clone: function( dataAndEvents, deepDataAndEvents ) {
  9069. dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
  9070. deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
  9071. return this.map(function() {
  9072. return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
  9073. });
  9074. },
  9075. html: function( value ) {
  9076. return access( this, function( value ) {
  9077. var elem = this[ 0 ] || {},
  9078. i = 0,
  9079. l = this.length;
  9080. if ( value === undefined && elem.nodeType === 1 ) {
  9081. return elem.innerHTML;
  9082. }
  9083. // See if we can take a shortcut and just use innerHTML
  9084. if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
  9085. !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
  9086. value = value.replace( rxhtmlTag, "<$1></$2>" );
  9087. try {
  9088. for ( ; i < l; i++ ) {
  9089. elem = this[ i ] || {};
  9090. // Remove element nodes and prevent memory leaks
  9091. if ( elem.nodeType === 1 ) {
  9092. jQuery.cleanData( getAll( elem, false ) );
  9093. elem.innerHTML = value;
  9094. }
  9095. }
  9096. elem = 0;
  9097. // If using innerHTML throws an exception, use the fallback method
  9098. } catch( e ) {}
  9099. }
  9100. if ( elem ) {
  9101. this.empty().append( value );
  9102. }
  9103. }, null, value, arguments.length );
  9104. },
  9105. replaceWith: function() {
  9106. var arg = arguments[ 0 ];
  9107. // Make the changes, replacing each context element with the new content
  9108. this.domManip( arguments, function( elem ) {
  9109. arg = this.parentNode;
  9110. jQuery.cleanData( getAll( this ) );
  9111. if ( arg ) {
  9112. arg.replaceChild( elem, this );
  9113. }
  9114. });
  9115. // Force removal if there was no new content (e.g., from empty arguments)
  9116. return arg && (arg.length || arg.nodeType) ? this : this.remove();
  9117. },
  9118. detach: function( selector ) {
  9119. return this.remove( selector, true );
  9120. },
  9121. domManip: function( args, callback ) {
  9122. // Flatten any nested arrays
  9123. args = concat.apply( [], args );
  9124. var fragment, first, scripts, hasScripts, node, doc,
  9125. i = 0,
  9126. l = this.length,
  9127. set = this,
  9128. iNoClone = l - 1,
  9129. value = args[ 0 ],
  9130. isFunction = jQuery.isFunction( value );
  9131. // We can't cloneNode fragments that contain checked, in WebKit
  9132. if ( isFunction ||
  9133. ( l > 1 && typeof value === "string" &&
  9134. !support.checkClone && rchecked.test( value ) ) ) {
  9135. return this.each(function( index ) {
  9136. var self = set.eq( index );
  9137. if ( isFunction ) {
  9138. args[ 0 ] = value.call( this, index, self.html() );
  9139. }
  9140. self.domManip( args, callback );
  9141. });
  9142. }
  9143. if ( l ) {
  9144. fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
  9145. first = fragment.firstChild;
  9146. if ( fragment.childNodes.length === 1 ) {
  9147. fragment = first;
  9148. }
  9149. if ( first ) {
  9150. scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
  9151. hasScripts = scripts.length;
  9152. // Use the original fragment for the last item instead of the first because it can end up
  9153. // being emptied incorrectly in certain situations (#8070).
  9154. for ( ; i < l; i++ ) {
  9155. node = fragment;
  9156. if ( i !== iNoClone ) {
  9157. node = jQuery.clone( node, true, true );
  9158. // Keep references to cloned scripts for later restoration
  9159. if ( hasScripts ) {
  9160. // Support: QtWebKit
  9161. // jQuery.merge because push.apply(_, arraylike) throws
  9162. jQuery.merge( scripts, getAll( node, "script" ) );
  9163. }
  9164. }
  9165. callback.call( this[ i ], node, i );
  9166. }
  9167. if ( hasScripts ) {
  9168. doc = scripts[ scripts.length - 1 ].ownerDocument;
  9169. // Reenable scripts
  9170. jQuery.map( scripts, restoreScript );
  9171. // Evaluate executable scripts on first document insertion
  9172. for ( i = 0; i < hasScripts; i++ ) {
  9173. node = scripts[ i ];
  9174. if ( rscriptType.test( node.type || "" ) &&
  9175. !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
  9176. if ( node.src ) {
  9177. // Optional AJAX dependency, but won't run scripts if not present
  9178. if ( jQuery._evalUrl ) {
  9179. jQuery._evalUrl( node.src );
  9180. }
  9181. } else {
  9182. jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
  9183. }
  9184. }
  9185. }
  9186. }
  9187. }
  9188. }
  9189. return this;
  9190. }
  9191. });
  9192. jQuery.each({
  9193. appendTo: "append",
  9194. prependTo: "prepend",
  9195. insertBefore: "before",
  9196. insertAfter: "after",
  9197. replaceAll: "replaceWith"
  9198. }, function( name, original ) {
  9199. jQuery.fn[ name ] = function( selector ) {
  9200. var elems,
  9201. ret = [],
  9202. insert = jQuery( selector ),
  9203. last = insert.length - 1,
  9204. i = 0;
  9205. for ( ; i <= last; i++ ) {
  9206. elems = i === last ? this : this.clone( true );
  9207. jQuery( insert[ i ] )[ original ]( elems );
  9208. // Support: QtWebKit
  9209. // .get() because push.apply(_, arraylike) throws
  9210. push.apply( ret, elems.get() );
  9211. }
  9212. return this.pushStack( ret );
  9213. };
  9214. });
  9215. var iframe,
  9216. elemdisplay = {};
  9217. /**
  9218. * Retrieve the actual display of a element
  9219. * @param {String} name nodeName of the element
  9220. * @param {Object} doc Document object
  9221. */
  9222. // Called only from within defaultDisplay
  9223. function actualDisplay( name, doc ) {
  9224. var style,
  9225. elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
  9226. // getDefaultComputedStyle might be reliably used only on attached element
  9227. display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
  9228. // Use of this method is a temporary fix (more like optimization) until something better comes along,
  9229. // since it was removed from specification and supported only in FF
  9230. style.display : jQuery.css( elem[ 0 ], "display" );
  9231. // We don't have any data stored on the element,
  9232. // so use "detach" method as fast way to get rid of the element
  9233. elem.detach();
  9234. return display;
  9235. }
  9236. /**
  9237. * Try to determine the default display value of an element
  9238. * @param {String} nodeName
  9239. */
  9240. function defaultDisplay( nodeName ) {
  9241. var doc = document,
  9242. display = elemdisplay[ nodeName ];
  9243. if ( !display ) {
  9244. display = actualDisplay( nodeName, doc );
  9245. // If the simple way fails, read from inside an iframe
  9246. if ( display === "none" || !display ) {
  9247. // Use the already-created iframe if possible
  9248. iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
  9249. // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
  9250. doc = iframe[ 0 ].contentDocument;
  9251. // Support: IE
  9252. doc.write();
  9253. doc.close();
  9254. display = actualDisplay( nodeName, doc );
  9255. iframe.detach();
  9256. }
  9257. // Store the correct default display
  9258. elemdisplay[ nodeName ] = display;
  9259. }
  9260. return display;
  9261. }
  9262. var rmargin = (/^margin/);
  9263. var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
  9264. var getStyles = function( elem ) {
  9265. // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
  9266. // IE throws on elements created in popups
  9267. // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
  9268. if ( elem.ownerDocument.defaultView.opener ) {
  9269. return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
  9270. }
  9271. return window.getComputedStyle( elem, null );
  9272. };
  9273. function curCSS( elem, name, computed ) {
  9274. var width, minWidth, maxWidth, ret,
  9275. style = elem.style;
  9276. computed = computed || getStyles( elem );
  9277. // Support: IE9
  9278. // getPropertyValue is only needed for .css('filter') (#12537)
  9279. if ( computed ) {
  9280. ret = computed.getPropertyValue( name ) || computed[ name ];
  9281. }
  9282. if ( computed ) {
  9283. if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
  9284. ret = jQuery.style( elem, name );
  9285. }
  9286. // Support: iOS < 6
  9287. // A tribute to the "awesome hack by Dean Edwards"
  9288. // iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
  9289. // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
  9290. if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
  9291. // Remember the original values
  9292. width = style.width;
  9293. minWidth = style.minWidth;
  9294. maxWidth = style.maxWidth;
  9295. // Put in the new values to get a computed value out
  9296. style.minWidth = style.maxWidth = style.width = ret;
  9297. ret = computed.width;
  9298. // Revert the changed values
  9299. style.width = width;
  9300. style.minWidth = minWidth;
  9301. style.maxWidth = maxWidth;
  9302. }
  9303. }
  9304. return ret !== undefined ?
  9305. // Support: IE
  9306. // IE returns zIndex value as an integer.
  9307. ret + "" :
  9308. ret;
  9309. }
  9310. function addGetHookIf( conditionFn, hookFn ) {
  9311. // Define the hook, we'll check on the first run if it's really needed.
  9312. return {
  9313. get: function() {
  9314. if ( conditionFn() ) {
  9315. // Hook not needed (or it's not possible to use it due
  9316. // to missing dependency), remove it.
  9317. delete this.get;
  9318. return;
  9319. }
  9320. // Hook needed; redefine it so that the support test is not executed again.
  9321. return (this.get = hookFn).apply( this, arguments );
  9322. }
  9323. };
  9324. }
  9325. (function() {
  9326. var pixelPositionVal, boxSizingReliableVal,
  9327. docElem = document.documentElement,
  9328. container = document.createElement( "div" ),
  9329. div = document.createElement( "div" );
  9330. if ( !div.style ) {
  9331. return;
  9332. }
  9333. // Support: IE9-11+
  9334. // Style of cloned element affects source element cloned (#8908)
  9335. div.style.backgroundClip = "content-box";
  9336. div.cloneNode( true ).style.backgroundClip = "";
  9337. support.clearCloneStyle = div.style.backgroundClip === "content-box";
  9338. container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" +
  9339. "position:absolute";
  9340. container.appendChild( div );
  9341. // Executing both pixelPosition & boxSizingReliable tests require only one layout
  9342. // so they're executed at the same time to save the second computation.
  9343. function computePixelPositionAndBoxSizingReliable() {
  9344. div.style.cssText =
  9345. // Support: Firefox<29, Android 2.3
  9346. // Vendor-prefix box-sizing
  9347. "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
  9348. "box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
  9349. "border:1px;padding:1px;width:4px;position:absolute";
  9350. div.innerHTML = "";
  9351. docElem.appendChild( container );
  9352. var divStyle = window.getComputedStyle( div, null );
  9353. pixelPositionVal = divStyle.top !== "1%";
  9354. boxSizingReliableVal = divStyle.width === "4px";
  9355. docElem.removeChild( container );
  9356. }
  9357. // Support: node.js jsdom
  9358. // Don't assume that getComputedStyle is a property of the global object
  9359. if ( window.getComputedStyle ) {
  9360. jQuery.extend( support, {
  9361. pixelPosition: function() {
  9362. // This test is executed only once but we still do memoizing
  9363. // since we can use the boxSizingReliable pre-computing.
  9364. // No need to check if the test was already performed, though.
  9365. computePixelPositionAndBoxSizingReliable();
  9366. return pixelPositionVal;
  9367. },
  9368. boxSizingReliable: function() {
  9369. if ( boxSizingReliableVal == null ) {
  9370. computePixelPositionAndBoxSizingReliable();
  9371. }
  9372. return boxSizingReliableVal;
  9373. },
  9374. reliableMarginRight: function() {
  9375. // Support: Android 2.3
  9376. // Check if div with explicit width and no margin-right incorrectly
  9377. // gets computed margin-right based on width of container. (#3333)
  9378. // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
  9379. // This support function is only executed once so no memoizing is needed.
  9380. var ret,
  9381. marginDiv = div.appendChild( document.createElement( "div" ) );
  9382. // Reset CSS: box-sizing; display; margin; border; padding
  9383. marginDiv.style.cssText = div.style.cssText =
  9384. // Support: Firefox<29, Android 2.3
  9385. // Vendor-prefix box-sizing
  9386. "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
  9387. "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
  9388. marginDiv.style.marginRight = marginDiv.style.width = "0";
  9389. div.style.width = "1px";
  9390. docElem.appendChild( container );
  9391. ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );
  9392. docElem.removeChild( container );
  9393. div.removeChild( marginDiv );
  9394. return ret;
  9395. }
  9396. });
  9397. }
  9398. })();
  9399. // A method for quickly swapping in/out CSS properties to get correct calculations.
  9400. jQuery.swap = function( elem, options, callback, args ) {
  9401. var ret, name,
  9402. old = {};
  9403. // Remember the old values, and insert the new ones
  9404. for ( name in options ) {
  9405. old[ name ] = elem.style[ name ];
  9406. elem.style[ name ] = options[ name ];
  9407. }
  9408. ret = callback.apply( elem, args || [] );
  9409. // Revert the old values
  9410. for ( name in options ) {
  9411. elem.style[ name ] = old[ name ];
  9412. }
  9413. return ret;
  9414. };
  9415. var
  9416. // Swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
  9417. // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
  9418. rdisplayswap = /^(none|table(?!-c[ea]).+)/,
  9419. rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
  9420. rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
  9421. cssShow = { position: "absolute", visibility: "hidden", display: "block" },
  9422. cssNormalTransform = {
  9423. letterSpacing: "0",
  9424. fontWeight: "400"
  9425. },
  9426. cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
  9427. // Return a css property mapped to a potentially vendor prefixed property
  9428. function vendorPropName( style, name ) {
  9429. // Shortcut for names that are not vendor prefixed
  9430. if ( name in style ) {
  9431. return name;
  9432. }
  9433. // Check for vendor prefixed names
  9434. var capName = name[0].toUpperCase() + name.slice(1),
  9435. origName = name,
  9436. i = cssPrefixes.length;
  9437. while ( i-- ) {
  9438. name = cssPrefixes[ i ] + capName;
  9439. if ( name in style ) {
  9440. return name;
  9441. }
  9442. }
  9443. return origName;
  9444. }
  9445. function setPositiveNumber( elem, value, subtract ) {
  9446. var matches = rnumsplit.exec( value );
  9447. return matches ?
  9448. // Guard against undefined "subtract", e.g., when used as in cssHooks
  9449. Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
  9450. value;
  9451. }
  9452. function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
  9453. var i = extra === ( isBorderBox ? "border" : "content" ) ?
  9454. // If we already have the right measurement, avoid augmentation
  9455. 4 :
  9456. // Otherwise initialize for horizontal or vertical properties
  9457. name === "width" ? 1 : 0,
  9458. val = 0;
  9459. for ( ; i < 4; i += 2 ) {
  9460. // Both box models exclude margin, so add it if we want it
  9461. if ( extra === "margin" ) {
  9462. val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
  9463. }
  9464. if ( isBorderBox ) {
  9465. // border-box includes padding, so remove it if we want content
  9466. if ( extra === "content" ) {
  9467. val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  9468. }
  9469. // At this point, extra isn't border nor margin, so remove border
  9470. if ( extra !== "margin" ) {
  9471. val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  9472. }
  9473. } else {
  9474. // At this point, extra isn't content, so add padding
  9475. val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  9476. // At this point, extra isn't content nor padding, so add border
  9477. if ( extra !== "padding" ) {
  9478. val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  9479. }
  9480. }
  9481. }
  9482. return val;
  9483. }
  9484. function getWidthOrHeight( elem, name, extra ) {
  9485. // Start with offset property, which is equivalent to the border-box value
  9486. var valueIsBorderBox = true,
  9487. val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
  9488. styles = getStyles( elem ),
  9489. isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
  9490. // Some non-html elements return undefined for offsetWidth, so check for null/undefined
  9491. // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
  9492. // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
  9493. if ( val <= 0 || val == null ) {
  9494. // Fall back to computed then uncomputed css if necessary
  9495. val = curCSS( elem, name, styles );
  9496. if ( val < 0 || val == null ) {
  9497. val = elem.style[ name ];
  9498. }
  9499. // Computed unit is not pixels. Stop here and return.
  9500. if ( rnumnonpx.test(val) ) {
  9501. return val;
  9502. }
  9503. // Check for style in case a browser which returns unreliable values
  9504. // for getComputedStyle silently falls back to the reliable elem.style
  9505. valueIsBorderBox = isBorderBox &&
  9506. ( support.boxSizingReliable() || val === elem.style[ name ] );
  9507. // Normalize "", auto, and prepare for extra
  9508. val = parseFloat( val ) || 0;
  9509. }
  9510. // Use the active box-sizing model to add/subtract irrelevant styles
  9511. return ( val +
  9512. augmentWidthOrHeight(
  9513. elem,
  9514. name,
  9515. extra || ( isBorderBox ? "border" : "content" ),
  9516. valueIsBorderBox,
  9517. styles
  9518. )
  9519. ) + "px";
  9520. }
  9521. function showHide( elements, show ) {
  9522. var display, elem, hidden,
  9523. values = [],
  9524. index = 0,
  9525. length = elements.length;
  9526. for ( ; index < length; index++ ) {
  9527. elem = elements[ index ];
  9528. if ( !elem.style ) {
  9529. continue;
  9530. }
  9531. values[ index ] = data_priv.get( elem, "olddisplay" );
  9532. display = elem.style.display;
  9533. if ( show ) {
  9534. // Reset the inline display of this element to learn if it is
  9535. // being hidden by cascaded rules or not
  9536. if ( !values[ index ] && display === "none" ) {
  9537. elem.style.display = "";
  9538. }
  9539. // Set elements which have been overridden with display: none
  9540. // in a stylesheet to whatever the default browser style is
  9541. // for such an element
  9542. if ( elem.style.display === "" && isHidden( elem ) ) {
  9543. values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) );
  9544. }
  9545. } else {
  9546. hidden = isHidden( elem );
  9547. if ( display !== "none" || !hidden ) {
  9548. data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
  9549. }
  9550. }
  9551. }
  9552. // Set the display of most of the elements in a second loop
  9553. // to avoid the constant reflow
  9554. for ( index = 0; index < length; index++ ) {
  9555. elem = elements[ index ];
  9556. if ( !elem.style ) {
  9557. continue;
  9558. }
  9559. if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
  9560. elem.style.display = show ? values[ index ] || "" : "none";
  9561. }
  9562. }
  9563. return elements;
  9564. }
  9565. jQuery.extend({
  9566. // Add in style property hooks for overriding the default
  9567. // behavior of getting and setting a style property
  9568. cssHooks: {
  9569. opacity: {
  9570. get: function( elem, computed ) {
  9571. if ( computed ) {
  9572. // We should always get a number back from opacity
  9573. var ret = curCSS( elem, "opacity" );
  9574. return ret === "" ? "1" : ret;
  9575. }
  9576. }
  9577. }
  9578. },
  9579. // Don't automatically add "px" to these possibly-unitless properties
  9580. cssNumber: {
  9581. "columnCount": true,
  9582. "fillOpacity": true,
  9583. "flexGrow": true,
  9584. "flexShrink": true,
  9585. "fontWeight": true,
  9586. "lineHeight": true,
  9587. "opacity": true,
  9588. "order": true,
  9589. "orphans": true,
  9590. "widows": true,
  9591. "zIndex": true,
  9592. "zoom": true
  9593. },
  9594. // Add in properties whose names you wish to fix before
  9595. // setting or getting the value
  9596. cssProps: {
  9597. "float": "cssFloat"
  9598. },
  9599. // Get and set the style property on a DOM Node
  9600. style: function( elem, name, value, extra ) {
  9601. // Don't set styles on text and comment nodes
  9602. if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
  9603. return;
  9604. }
  9605. // Make sure that we're working with the right name
  9606. var ret, type, hooks,
  9607. origName = jQuery.camelCase( name ),
  9608. style = elem.style;
  9609. name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
  9610. // Gets hook for the prefixed version, then unprefixed version
  9611. hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  9612. // Check if we're setting a value
  9613. if ( value !== undefined ) {
  9614. type = typeof value;
  9615. // Convert "+=" or "-=" to relative numbers (#7345)
  9616. if ( type === "string" && (ret = rrelNum.exec( value )) ) {
  9617. value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
  9618. // Fixes bug #9237
  9619. type = "number";
  9620. }
  9621. // Make sure that null and NaN values aren't set (#7116)
  9622. if ( value == null || value !== value ) {
  9623. return;
  9624. }
  9625. // If a number, add 'px' to the (except for certain CSS properties)
  9626. if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
  9627. value += "px";
  9628. }
  9629. // Support: IE9-11+
  9630. // background-* props affect original clone's values
  9631. if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
  9632. style[ name ] = "inherit";
  9633. }
  9634. // If a hook was provided, use that value, otherwise just set the specified value
  9635. if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
  9636. style[ name ] = value;
  9637. }
  9638. } else {
  9639. // If a hook was provided get the non-computed value from there
  9640. if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
  9641. return ret;
  9642. }
  9643. // Otherwise just get the value from the style object
  9644. return style[ name ];
  9645. }
  9646. },
  9647. css: function( elem, name, extra, styles ) {
  9648. var val, num, hooks,
  9649. origName = jQuery.camelCase( name );
  9650. // Make sure that we're working with the right name
  9651. name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
  9652. // Try prefixed name followed by the unprefixed name
  9653. hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  9654. // If a hook was provided get the computed value from there
  9655. if ( hooks && "get" in hooks ) {
  9656. val = hooks.get( elem, true, extra );
  9657. }
  9658. // Otherwise, if a way to get the computed value exists, use that
  9659. if ( val === undefined ) {
  9660. val = curCSS( elem, name, styles );
  9661. }
  9662. // Convert "normal" to computed value
  9663. if ( val === "normal" && name in cssNormalTransform ) {
  9664. val = cssNormalTransform[ name ];
  9665. }
  9666. // Make numeric if forced or a qualifier was provided and val looks numeric
  9667. if ( extra === "" || extra ) {
  9668. num = parseFloat( val );
  9669. return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
  9670. }
  9671. return val;
  9672. }
  9673. });
  9674. jQuery.each([ "height", "width" ], function( i, name ) {
  9675. jQuery.cssHooks[ name ] = {
  9676. get: function( elem, computed, extra ) {
  9677. if ( computed ) {
  9678. // Certain elements can have dimension info if we invisibly show them
  9679. // but it must have a current display style that would benefit
  9680. return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
  9681. jQuery.swap( elem, cssShow, function() {
  9682. return getWidthOrHeight( elem, name, extra );
  9683. }) :
  9684. getWidthOrHeight( elem, name, extra );
  9685. }
  9686. },
  9687. set: function( elem, value, extra ) {
  9688. var styles = extra && getStyles( elem );
  9689. return setPositiveNumber( elem, value, extra ?
  9690. augmentWidthOrHeight(
  9691. elem,
  9692. name,
  9693. extra,
  9694. jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
  9695. styles
  9696. ) : 0
  9697. );
  9698. }
  9699. };
  9700. });
  9701. // Support: Android 2.3
  9702. jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
  9703. function( elem, computed ) {
  9704. if ( computed ) {
  9705. return jQuery.swap( elem, { "display": "inline-block" },
  9706. curCSS, [ elem, "marginRight" ] );
  9707. }
  9708. }
  9709. );
  9710. // These hooks are used by animate to expand properties
  9711. jQuery.each({
  9712. margin: "",
  9713. padding: "",
  9714. border: "Width"
  9715. }, function( prefix, suffix ) {
  9716. jQuery.cssHooks[ prefix + suffix ] = {
  9717. expand: function( value ) {
  9718. var i = 0,
  9719. expanded = {},
  9720. // Assumes a single number if not a string
  9721. parts = typeof value === "string" ? value.split(" ") : [ value ];
  9722. for ( ; i < 4; i++ ) {
  9723. expanded[ prefix + cssExpand[ i ] + suffix ] =
  9724. parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
  9725. }
  9726. return expanded;
  9727. }
  9728. };
  9729. if ( !rmargin.test( prefix ) ) {
  9730. jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
  9731. }
  9732. });
  9733. jQuery.fn.extend({
  9734. css: function( name, value ) {
  9735. return access( this, function( elem, name, value ) {
  9736. var styles, len,
  9737. map = {},
  9738. i = 0;
  9739. if ( jQuery.isArray( name ) ) {
  9740. styles = getStyles( elem );
  9741. len = name.length;
  9742. for ( ; i < len; i++ ) {
  9743. map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
  9744. }
  9745. return map;
  9746. }
  9747. return value !== undefined ?
  9748. jQuery.style( elem, name, value ) :
  9749. jQuery.css( elem, name );
  9750. }, name, value, arguments.length > 1 );
  9751. },
  9752. show: function() {
  9753. return showHide( this, true );
  9754. },
  9755. hide: function() {
  9756. return showHide( this );
  9757. },
  9758. toggle: function( state ) {
  9759. if ( typeof state === "boolean" ) {
  9760. return state ? this.show() : this.hide();
  9761. }
  9762. return this.each(function() {
  9763. if ( isHidden( this ) ) {
  9764. jQuery( this ).show();
  9765. } else {
  9766. jQuery( this ).hide();
  9767. }
  9768. });
  9769. }
  9770. });
  9771. function Tween( elem, options, prop, end, easing ) {
  9772. return new Tween.prototype.init( elem, options, prop, end, easing );
  9773. }
  9774. jQuery.Tween = Tween;
  9775. Tween.prototype = {
  9776. constructor: Tween,
  9777. init: function( elem, options, prop, end, easing, unit ) {
  9778. this.elem = elem;
  9779. this.prop = prop;
  9780. this.easing = easing || "swing";
  9781. this.options = options;
  9782. this.start = this.now = this.cur();
  9783. this.end = end;
  9784. this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
  9785. },
  9786. cur: function() {
  9787. var hooks = Tween.propHooks[ this.prop ];
  9788. return hooks && hooks.get ?
  9789. hooks.get( this ) :
  9790. Tween.propHooks._default.get( this );
  9791. },
  9792. run: function( percent ) {
  9793. var eased,
  9794. hooks = Tween.propHooks[ this.prop ];
  9795. if ( this.options.duration ) {
  9796. this.pos = eased = jQuery.easing[ this.easing ](
  9797. percent, this.options.duration * percent, 0, 1, this.options.duration
  9798. );
  9799. } else {
  9800. this.pos = eased = percent;
  9801. }
  9802. this.now = ( this.end - this.start ) * eased + this.start;
  9803. if ( this.options.step ) {
  9804. this.options.step.call( this.elem, this.now, this );
  9805. }
  9806. if ( hooks && hooks.set ) {
  9807. hooks.set( this );
  9808. } else {
  9809. Tween.propHooks._default.set( this );
  9810. }
  9811. return this;
  9812. }
  9813. };
  9814. Tween.prototype.init.prototype = Tween.prototype;
  9815. Tween.propHooks = {
  9816. _default: {
  9817. get: function( tween ) {
  9818. var result;
  9819. if ( tween.elem[ tween.prop ] != null &&
  9820. (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
  9821. return tween.elem[ tween.prop ];
  9822. }
  9823. // Passing an empty string as a 3rd parameter to .css will automatically
  9824. // attempt a parseFloat and fallback to a string if the parse fails.
  9825. // Simple values such as "10px" are parsed to Float;
  9826. // complex values such as "rotate(1rad)" are returned as-is.
  9827. result = jQuery.css( tween.elem, tween.prop, "" );
  9828. // Empty strings, null, undefined and "auto" are converted to 0.
  9829. return !result || result === "auto" ? 0 : result;
  9830. },
  9831. set: function( tween ) {
  9832. // Use step hook for back compat.
  9833. // Use cssHook if its there.
  9834. // Use .style if available and use plain properties where available.
  9835. if ( jQuery.fx.step[ tween.prop ] ) {
  9836. jQuery.fx.step[ tween.prop ]( tween );
  9837. } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
  9838. jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
  9839. } else {
  9840. tween.elem[ tween.prop ] = tween.now;
  9841. }
  9842. }
  9843. }
  9844. };
  9845. // Support: IE9
  9846. // Panic based approach to setting things on disconnected nodes
  9847. Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
  9848. set: function( tween ) {
  9849. if ( tween.elem.nodeType && tween.elem.parentNode ) {
  9850. tween.elem[ tween.prop ] = tween.now;
  9851. }
  9852. }
  9853. };
  9854. jQuery.easing = {
  9855. linear: function( p ) {
  9856. return p;
  9857. },
  9858. swing: function( p ) {
  9859. return 0.5 - Math.cos( p * Math.PI ) / 2;
  9860. }
  9861. };
  9862. jQuery.fx = Tween.prototype.init;
  9863. // Back Compat <1.8 extension point
  9864. jQuery.fx.step = {};
  9865. var
  9866. fxNow, timerId,
  9867. rfxtypes = /^(?:toggle|show|hide)$/,
  9868. rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
  9869. rrun = /queueHooks$/,
  9870. animationPrefilters = [ defaultPrefilter ],
  9871. tweeners = {
  9872. "*": [ function( prop, value ) {
  9873. var tween = this.createTween( prop, value ),
  9874. target = tween.cur(),
  9875. parts = rfxnum.exec( value ),
  9876. unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
  9877. // Starting value computation is required for potential unit mismatches
  9878. start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
  9879. rfxnum.exec( jQuery.css( tween.elem, prop ) ),
  9880. scale = 1,
  9881. maxIterations = 20;
  9882. if ( start && start[ 3 ] !== unit ) {
  9883. // Trust units reported by jQuery.css
  9884. unit = unit || start[ 3 ];
  9885. // Make sure we update the tween properties later on
  9886. parts = parts || [];
  9887. // Iteratively approximate from a nonzero starting point
  9888. start = +target || 1;
  9889. do {
  9890. // If previous iteration zeroed out, double until we get *something*.
  9891. // Use string for doubling so we don't accidentally see scale as unchanged below
  9892. scale = scale || ".5";
  9893. // Adjust and apply
  9894. start = start / scale;
  9895. jQuery.style( tween.elem, prop, start + unit );
  9896. // Update scale, tolerating zero or NaN from tween.cur(),
  9897. // break the loop if scale is unchanged or perfect, or if we've just had enough
  9898. } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
  9899. }
  9900. // Update tween properties
  9901. if ( parts ) {
  9902. start = tween.start = +start || +target || 0;
  9903. tween.unit = unit;
  9904. // If a +=/-= token was provided, we're doing a relative animation
  9905. tween.end = parts[ 1 ] ?
  9906. start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
  9907. +parts[ 2 ];
  9908. }
  9909. return tween;
  9910. } ]
  9911. };
  9912. // Animations created synchronously will run synchronously
  9913. function createFxNow() {
  9914. setTimeout(function() {
  9915. fxNow = undefined;
  9916. });
  9917. return ( fxNow = jQuery.now() );
  9918. }
  9919. // Generate parameters to create a standard animation
  9920. function genFx( type, includeWidth ) {
  9921. var which,
  9922. i = 0,
  9923. attrs = { height: type };
  9924. // If we include width, step value is 1 to do all cssExpand values,
  9925. // otherwise step value is 2 to skip over Left and Right
  9926. includeWidth = includeWidth ? 1 : 0;
  9927. for ( ; i < 4 ; i += 2 - includeWidth ) {
  9928. which = cssExpand[ i ];
  9929. attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
  9930. }
  9931. if ( includeWidth ) {
  9932. attrs.opacity = attrs.width = type;
  9933. }
  9934. return attrs;
  9935. }
  9936. function createTween( value, prop, animation ) {
  9937. var tween,
  9938. collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
  9939. index = 0,
  9940. length = collection.length;
  9941. for ( ; index < length; index++ ) {
  9942. if ( (tween = collection[ index ].call( animation, prop, value )) ) {
  9943. // We're done with this property
  9944. return tween;
  9945. }
  9946. }
  9947. }
  9948. function defaultPrefilter( elem, props, opts ) {
  9949. /* jshint validthis: true */
  9950. var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
  9951. anim = this,
  9952. orig = {},
  9953. style = elem.style,
  9954. hidden = elem.nodeType && isHidden( elem ),
  9955. dataShow = data_priv.get( elem, "fxshow" );
  9956. // Handle queue: false promises
  9957. if ( !opts.queue ) {
  9958. hooks = jQuery._queueHooks( elem, "fx" );
  9959. if ( hooks.unqueued == null ) {
  9960. hooks.unqueued = 0;
  9961. oldfire = hooks.empty.fire;
  9962. hooks.empty.fire = function() {
  9963. if ( !hooks.unqueued ) {
  9964. oldfire();
  9965. }
  9966. };
  9967. }
  9968. hooks.unqueued++;
  9969. anim.always(function() {
  9970. // Ensure the complete handler is called before this completes
  9971. anim.always(function() {
  9972. hooks.unqueued--;
  9973. if ( !jQuery.queue( elem, "fx" ).length ) {
  9974. hooks.empty.fire();
  9975. }
  9976. });
  9977. });
  9978. }
  9979. // Height/width overflow pass
  9980. if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
  9981. // Make sure that nothing sneaks out
  9982. // Record all 3 overflow attributes because IE9-10 do not
  9983. // change the overflow attribute when overflowX and
  9984. // overflowY are set to the same value
  9985. opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
  9986. // Set display property to inline-block for height/width
  9987. // animations on inline elements that are having width/height animated
  9988. display = jQuery.css( elem, "display" );
  9989. // Test default display if display is currently "none"
  9990. checkDisplay = display === "none" ?
  9991. data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
  9992. if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
  9993. style.display = "inline-block";
  9994. }
  9995. }
  9996. if ( opts.overflow ) {
  9997. style.overflow = "hidden";
  9998. anim.always(function() {
  9999. style.overflow = opts.overflow[ 0 ];
  10000. style.overflowX = opts.overflow[ 1 ];
  10001. style.overflowY = opts.overflow[ 2 ];
  10002. });
  10003. }
  10004. // show/hide pass
  10005. for ( prop in props ) {
  10006. value = props[ prop ];
  10007. if ( rfxtypes.exec( value ) ) {
  10008. delete props[ prop ];
  10009. toggle = toggle || value === "toggle";
  10010. if ( value === ( hidden ? "hide" : "show" ) ) {
  10011. // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
  10012. if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
  10013. hidden = true;
  10014. } else {
  10015. continue;
  10016. }
  10017. }
  10018. orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
  10019. // Any non-fx value stops us from restoring the original display value
  10020. } else {
  10021. display = undefined;
  10022. }
  10023. }
  10024. if ( !jQuery.isEmptyObject( orig ) ) {
  10025. if ( dataShow ) {
  10026. if ( "hidden" in dataShow ) {
  10027. hidden = dataShow.hidden;
  10028. }
  10029. } else {
  10030. dataShow = data_priv.access( elem, "fxshow", {} );
  10031. }
  10032. // Store state if its toggle - enables .stop().toggle() to "reverse"
  10033. if ( toggle ) {
  10034. dataShow.hidden = !hidden;
  10035. }
  10036. if ( hidden ) {
  10037. jQuery( elem ).show();
  10038. } else {
  10039. anim.done(function() {
  10040. jQuery( elem ).hide();
  10041. });
  10042. }
  10043. anim.done(function() {
  10044. var prop;
  10045. data_priv.remove( elem, "fxshow" );
  10046. for ( prop in orig ) {
  10047. jQuery.style( elem, prop, orig[ prop ] );
  10048. }
  10049. });
  10050. for ( prop in orig ) {
  10051. tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
  10052. if ( !( prop in dataShow ) ) {
  10053. dataShow[ prop ] = tween.start;
  10054. if ( hidden ) {
  10055. tween.end = tween.start;
  10056. tween.start = prop === "width" || prop === "height" ? 1 : 0;
  10057. }
  10058. }
  10059. }
  10060. // If this is a noop like .hide().hide(), restore an overwritten display value
  10061. } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
  10062. style.display = display;
  10063. }
  10064. }
  10065. function propFilter( props, specialEasing ) {
  10066. var index, name, easing, value, hooks;
  10067. // camelCase, specialEasing and expand cssHook pass
  10068. for ( index in props ) {
  10069. name = jQuery.camelCase( index );
  10070. easing = specialEasing[ name ];
  10071. value = props[ index ];
  10072. if ( jQuery.isArray( value ) ) {
  10073. easing = value[ 1 ];
  10074. value = props[ index ] = value[ 0 ];
  10075. }
  10076. if ( index !== name ) {
  10077. props[ name ] = value;
  10078. delete props[ index ];
  10079. }
  10080. hooks = jQuery.cssHooks[ name ];
  10081. if ( hooks && "expand" in hooks ) {
  10082. value = hooks.expand( value );
  10083. delete props[ name ];
  10084. // Not quite $.extend, this won't overwrite existing keys.
  10085. // Reusing 'index' because we have the correct "name"
  10086. for ( index in value ) {
  10087. if ( !( index in props ) ) {
  10088. props[ index ] = value[ index ];
  10089. specialEasing[ index ] = easing;
  10090. }
  10091. }
  10092. } else {
  10093. specialEasing[ name ] = easing;
  10094. }
  10095. }
  10096. }
  10097. function Animation( elem, properties, options ) {
  10098. var result,
  10099. stopped,
  10100. index = 0,
  10101. length = animationPrefilters.length,
  10102. deferred = jQuery.Deferred().always( function() {
  10103. // Don't match elem in the :animated selector
  10104. delete tick.elem;
  10105. }),
  10106. tick = function() {
  10107. if ( stopped ) {
  10108. return false;
  10109. }
  10110. var currentTime = fxNow || createFxNow(),
  10111. remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
  10112. // Support: Android 2.3
  10113. // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
  10114. temp = remaining / animation.duration || 0,
  10115. percent = 1 - temp,
  10116. index = 0,
  10117. length = animation.tweens.length;
  10118. for ( ; index < length ; index++ ) {
  10119. animation.tweens[ index ].run( percent );
  10120. }
  10121. deferred.notifyWith( elem, [ animation, percent, remaining ]);
  10122. if ( percent < 1 && length ) {
  10123. return remaining;
  10124. } else {
  10125. deferred.resolveWith( elem, [ animation ] );
  10126. return false;
  10127. }
  10128. },
  10129. animation = deferred.promise({
  10130. elem: elem,
  10131. props: jQuery.extend( {}, properties ),
  10132. opts: jQuery.extend( true, { specialEasing: {} }, options ),
  10133. originalProperties: properties,
  10134. originalOptions: options,
  10135. startTime: fxNow || createFxNow(),
  10136. duration: options.duration,
  10137. tweens: [],
  10138. createTween: function( prop, end ) {
  10139. var tween = jQuery.Tween( elem, animation.opts, prop, end,
  10140. animation.opts.specialEasing[ prop ] || animation.opts.easing );
  10141. animation.tweens.push( tween );
  10142. return tween;
  10143. },
  10144. stop: function( gotoEnd ) {
  10145. var index = 0,
  10146. // If we are going to the end, we want to run all the tweens
  10147. // otherwise we skip this part
  10148. length = gotoEnd ? animation.tweens.length : 0;
  10149. if ( stopped ) {
  10150. return this;
  10151. }
  10152. stopped = true;
  10153. for ( ; index < length ; index++ ) {
  10154. animation.tweens[ index ].run( 1 );
  10155. }
  10156. // Resolve when we played the last frame; otherwise, reject
  10157. if ( gotoEnd ) {
  10158. deferred.resolveWith( elem, [ animation, gotoEnd ] );
  10159. } else {
  10160. deferred.rejectWith( elem, [ animation, gotoEnd ] );
  10161. }
  10162. return this;
  10163. }
  10164. }),
  10165. props = animation.props;
  10166. propFilter( props, animation.opts.specialEasing );
  10167. for ( ; index < length ; index++ ) {
  10168. result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
  10169. if ( result ) {
  10170. return result;
  10171. }
  10172. }
  10173. jQuery.map( props, createTween, animation );
  10174. if ( jQuery.isFunction( animation.opts.start ) ) {
  10175. animation.opts.start.call( elem, animation );
  10176. }
  10177. jQuery.fx.timer(
  10178. jQuery.extend( tick, {
  10179. elem: elem,
  10180. anim: animation,
  10181. queue: animation.opts.queue
  10182. })
  10183. );
  10184. // attach callbacks from options
  10185. return animation.progress( animation.opts.progress )
  10186. .done( animation.opts.done, animation.opts.complete )
  10187. .fail( animation.opts.fail )
  10188. .always( animation.opts.always );
  10189. }
  10190. jQuery.Animation = jQuery.extend( Animation, {
  10191. tweener: function( props, callback ) {
  10192. if ( jQuery.isFunction( props ) ) {
  10193. callback = props;
  10194. props = [ "*" ];
  10195. } else {
  10196. props = props.split(" ");
  10197. }
  10198. var prop,
  10199. index = 0,
  10200. length = props.length;
  10201. for ( ; index < length ; index++ ) {
  10202. prop = props[ index ];
  10203. tweeners[ prop ] = tweeners[ prop ] || [];
  10204. tweeners[ prop ].unshift( callback );
  10205. }
  10206. },
  10207. prefilter: function( callback, prepend ) {
  10208. if ( prepend ) {
  10209. animationPrefilters.unshift( callback );
  10210. } else {
  10211. animationPrefilters.push( callback );
  10212. }
  10213. }
  10214. });
  10215. jQuery.speed = function( speed, easing, fn ) {
  10216. var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
  10217. complete: fn || !fn && easing ||
  10218. jQuery.isFunction( speed ) && speed,
  10219. duration: speed,
  10220. easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
  10221. };
  10222. opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
  10223. opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
  10224. // Normalize opt.queue - true/undefined/null -> "fx"
  10225. if ( opt.queue == null || opt.queue === true ) {
  10226. opt.queue = "fx";
  10227. }
  10228. // Queueing
  10229. opt.old = opt.complete;
  10230. opt.complete = function() {
  10231. if ( jQuery.isFunction( opt.old ) ) {
  10232. opt.old.call( this );
  10233. }
  10234. if ( opt.queue ) {
  10235. jQuery.dequeue( this, opt.queue );
  10236. }
  10237. };
  10238. return opt;
  10239. };
  10240. jQuery.fn.extend({
  10241. fadeTo: function( speed, to, easing, callback ) {
  10242. // Show any hidden elements after setting opacity to 0
  10243. return this.filter( isHidden ).css( "opacity", 0 ).show()
  10244. // Animate to the value specified
  10245. .end().animate({ opacity: to }, speed, easing, callback );
  10246. },
  10247. animate: function( prop, speed, easing, callback ) {
  10248. var empty = jQuery.isEmptyObject( prop ),
  10249. optall = jQuery.speed( speed, easing, callback ),
  10250. doAnimation = function() {
  10251. // Operate on a copy of prop so per-property easing won't be lost
  10252. var anim = Animation( this, jQuery.extend( {}, prop ), optall );
  10253. // Empty animations, or finishing resolves immediately
  10254. if ( empty || data_priv.get( this, "finish" ) ) {
  10255. anim.stop( true );
  10256. }
  10257. };
  10258. doAnimation.finish = doAnimation;
  10259. return empty || optall.queue === false ?
  10260. this.each( doAnimation ) :
  10261. this.queue( optall.queue, doAnimation );
  10262. },
  10263. stop: function( type, clearQueue, gotoEnd ) {
  10264. var stopQueue = function( hooks ) {
  10265. var stop = hooks.stop;
  10266. delete hooks.stop;
  10267. stop( gotoEnd );
  10268. };
  10269. if ( typeof type !== "string" ) {
  10270. gotoEnd = clearQueue;
  10271. clearQueue = type;
  10272. type = undefined;
  10273. }
  10274. if ( clearQueue && type !== false ) {
  10275. this.queue( type || "fx", [] );
  10276. }
  10277. return this.each(function() {
  10278. var dequeue = true,
  10279. index = type != null && type + "queueHooks",
  10280. timers = jQuery.timers,
  10281. data = data_priv.get( this );
  10282. if ( index ) {
  10283. if ( data[ index ] && data[ index ].stop ) {
  10284. stopQueue( data[ index ] );
  10285. }
  10286. } else {
  10287. for ( index in data ) {
  10288. if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
  10289. stopQueue( data[ index ] );
  10290. }
  10291. }
  10292. }
  10293. for ( index = timers.length; index--; ) {
  10294. if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
  10295. timers[ index ].anim.stop( gotoEnd );
  10296. dequeue = false;
  10297. timers.splice( index, 1 );
  10298. }
  10299. }
  10300. // Start the next in the queue if the last step wasn't forced.
  10301. // Timers currently will call their complete callbacks, which
  10302. // will dequeue but only if they were gotoEnd.
  10303. if ( dequeue || !gotoEnd ) {
  10304. jQuery.dequeue( this, type );
  10305. }
  10306. });
  10307. },
  10308. finish: function( type ) {
  10309. if ( type !== false ) {
  10310. type = type || "fx";
  10311. }
  10312. return this.each(function() {
  10313. var index,
  10314. data = data_priv.get( this ),
  10315. queue = data[ type + "queue" ],
  10316. hooks = data[ type + "queueHooks" ],
  10317. timers = jQuery.timers,
  10318. length = queue ? queue.length : 0;
  10319. // Enable finishing flag on private data
  10320. data.finish = true;
  10321. // Empty the queue first
  10322. jQuery.queue( this, type, [] );
  10323. if ( hooks && hooks.stop ) {
  10324. hooks.stop.call( this, true );
  10325. }
  10326. // Look for any active animations, and finish them
  10327. for ( index = timers.length; index--; ) {
  10328. if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
  10329. timers[ index ].anim.stop( true );
  10330. timers.splice( index, 1 );
  10331. }
  10332. }
  10333. // Look for any animations in the old queue and finish them
  10334. for ( index = 0; index < length; index++ ) {
  10335. if ( queue[ index ] && queue[ index ].finish ) {
  10336. queue[ index ].finish.call( this );
  10337. }
  10338. }
  10339. // Turn off finishing flag
  10340. delete data.finish;
  10341. });
  10342. }
  10343. });
  10344. jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
  10345. var cssFn = jQuery.fn[ name ];
  10346. jQuery.fn[ name ] = function( speed, easing, callback ) {
  10347. return speed == null || typeof speed === "boolean" ?
  10348. cssFn.apply( this, arguments ) :
  10349. this.animate( genFx( name, true ), speed, easing, callback );
  10350. };
  10351. });
  10352. // Generate shortcuts for custom animations
  10353. jQuery.each({
  10354. slideDown: genFx("show"),
  10355. slideUp: genFx("hide"),
  10356. slideToggle: genFx("toggle"),
  10357. fadeIn: { opacity: "show" },
  10358. fadeOut: { opacity: "hide" },
  10359. fadeToggle: { opacity: "toggle" }
  10360. }, function( name, props ) {
  10361. jQuery.fn[ name ] = function( speed, easing, callback ) {
  10362. return this.animate( props, speed, easing, callback );
  10363. };
  10364. });
  10365. jQuery.timers = [];
  10366. jQuery.fx.tick = function() {
  10367. var timer,
  10368. i = 0,
  10369. timers = jQuery.timers;
  10370. fxNow = jQuery.now();
  10371. for ( ; i < timers.length; i++ ) {
  10372. timer = timers[ i ];
  10373. // Checks the timer has not already been removed
  10374. if ( !timer() && timers[ i ] === timer ) {
  10375. timers.splice( i--, 1 );
  10376. }
  10377. }
  10378. if ( !timers.length ) {
  10379. jQuery.fx.stop();
  10380. }
  10381. fxNow = undefined;
  10382. };
  10383. jQuery.fx.timer = function( timer ) {
  10384. jQuery.timers.push( timer );
  10385. if ( timer() ) {
  10386. jQuery.fx.start();
  10387. } else {
  10388. jQuery.timers.pop();
  10389. }
  10390. };
  10391. jQuery.fx.interval = 13;
  10392. jQuery.fx.start = function() {
  10393. if ( !timerId ) {
  10394. timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
  10395. }
  10396. };
  10397. jQuery.fx.stop = function() {
  10398. clearInterval( timerId );
  10399. timerId = null;
  10400. };
  10401. jQuery.fx.speeds = {
  10402. slow: 600,
  10403. fast: 200,
  10404. // Default speed
  10405. _default: 400
  10406. };
  10407. // Based off of the plugin by Clint Helfers, with permission.
  10408. // http://blindsignals.com/index.php/2009/07/jquery-delay/
  10409. jQuery.fn.delay = function( time, type ) {
  10410. time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
  10411. type = type || "fx";
  10412. return this.queue( type, function( next, hooks ) {
  10413. var timeout = setTimeout( next, time );
  10414. hooks.stop = function() {
  10415. clearTimeout( timeout );
  10416. };
  10417. });
  10418. };
  10419. (function() {
  10420. var input = document.createElement( "input" ),
  10421. select = document.createElement( "select" ),
  10422. opt = select.appendChild( document.createElement( "option" ) );
  10423. input.type = "checkbox";
  10424. // Support: iOS<=5.1, Android<=4.2+
  10425. // Default value for a checkbox should be "on"
  10426. support.checkOn = input.value !== "";
  10427. // Support: IE<=11+
  10428. // Must access selectedIndex to make default options select
  10429. support.optSelected = opt.selected;
  10430. // Support: Android<=2.3
  10431. // Options inside disabled selects are incorrectly marked as disabled
  10432. select.disabled = true;
  10433. support.optDisabled = !opt.disabled;
  10434. // Support: IE<=11+
  10435. // An input loses its value after becoming a radio
  10436. input = document.createElement( "input" );
  10437. input.value = "t";
  10438. input.type = "radio";
  10439. support.radioValue = input.value === "t";
  10440. })();
  10441. var nodeHook, boolHook,
  10442. attrHandle = jQuery.expr.attrHandle;
  10443. jQuery.fn.extend({
  10444. attr: function( name, value ) {
  10445. return access( this, jQuery.attr, name, value, arguments.length > 1 );
  10446. },
  10447. removeAttr: function( name ) {
  10448. return this.each(function() {
  10449. jQuery.removeAttr( this, name );
  10450. });
  10451. }
  10452. });
  10453. jQuery.extend({
  10454. attr: function( elem, name, value ) {
  10455. var hooks, ret,
  10456. nType = elem.nodeType;
  10457. // don't get/set attributes on text, comment and attribute nodes
  10458. if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
  10459. return;
  10460. }
  10461. // Fallback to prop when attributes are not supported
  10462. if ( typeof elem.getAttribute === strundefined ) {
  10463. return jQuery.prop( elem, name, value );
  10464. }
  10465. // All attributes are lowercase
  10466. // Grab necessary hook if one is defined
  10467. if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
  10468. name = name.toLowerCase();
  10469. hooks = jQuery.attrHooks[ name ] ||
  10470. ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
  10471. }
  10472. if ( value !== undefined ) {
  10473. if ( value === null ) {
  10474. jQuery.removeAttr( elem, name );
  10475. } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
  10476. return ret;
  10477. } else {
  10478. elem.setAttribute( name, value + "" );
  10479. return value;
  10480. }
  10481. } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
  10482. return ret;
  10483. } else {
  10484. ret = jQuery.find.attr( elem, name );
  10485. // Non-existent attributes return null, we normalize to undefined
  10486. return ret == null ?
  10487. undefined :
  10488. ret;
  10489. }
  10490. },
  10491. removeAttr: function( elem, value ) {
  10492. var name, propName,
  10493. i = 0,
  10494. attrNames = value && value.match( rnotwhite );
  10495. if ( attrNames && elem.nodeType === 1 ) {
  10496. while ( (name = attrNames[i++]) ) {
  10497. propName = jQuery.propFix[ name ] || name;
  10498. // Boolean attributes get special treatment (#10870)
  10499. if ( jQuery.expr.match.bool.test( name ) ) {
  10500. // Set corresponding property to false
  10501. elem[ propName ] = false;
  10502. }
  10503. elem.removeAttribute( name );
  10504. }
  10505. }
  10506. },
  10507. attrHooks: {
  10508. type: {
  10509. set: function( elem, value ) {
  10510. if ( !support.radioValue && value === "radio" &&
  10511. jQuery.nodeName( elem, "input" ) ) {
  10512. var val = elem.value;
  10513. elem.setAttribute( "type", value );
  10514. if ( val ) {
  10515. elem.value = val;
  10516. }
  10517. return value;
  10518. }
  10519. }
  10520. }
  10521. }
  10522. });
  10523. // Hooks for boolean attributes
  10524. boolHook = {
  10525. set: function( elem, value, name ) {
  10526. if ( value === false ) {
  10527. // Remove boolean attributes when set to false
  10528. jQuery.removeAttr( elem, name );
  10529. } else {
  10530. elem.setAttribute( name, name );
  10531. }
  10532. return name;
  10533. }
  10534. };
  10535. jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
  10536. var getter = attrHandle[ name ] || jQuery.find.attr;
  10537. attrHandle[ name ] = function( elem, name, isXML ) {
  10538. var ret, handle;
  10539. if ( !isXML ) {
  10540. // Avoid an infinite loop by temporarily removing this function from the getter
  10541. handle = attrHandle[ name ];
  10542. attrHandle[ name ] = ret;
  10543. ret = getter( elem, name, isXML ) != null ?
  10544. name.toLowerCase() :
  10545. null;
  10546. attrHandle[ name ] = handle;
  10547. }
  10548. return ret;
  10549. };
  10550. });
  10551. var rfocusable = /^(?:input|select|textarea|button)$/i;
  10552. jQuery.fn.extend({
  10553. prop: function( name, value ) {
  10554. return access( this, jQuery.prop, name, value, arguments.length > 1 );
  10555. },
  10556. removeProp: function( name ) {
  10557. return this.each(function() {
  10558. delete this[ jQuery.propFix[ name ] || name ];
  10559. });
  10560. }
  10561. });
  10562. jQuery.extend({
  10563. propFix: {
  10564. "for": "htmlFor",
  10565. "class": "className"
  10566. },
  10567. prop: function( elem, name, value ) {
  10568. var ret, hooks, notxml,
  10569. nType = elem.nodeType;
  10570. // Don't get/set properties on text, comment and attribute nodes
  10571. if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
  10572. return;
  10573. }
  10574. notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
  10575. if ( notxml ) {
  10576. // Fix name and attach hooks
  10577. name = jQuery.propFix[ name ] || name;
  10578. hooks = jQuery.propHooks[ name ];
  10579. }
  10580. if ( value !== undefined ) {
  10581. return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
  10582. ret :
  10583. ( elem[ name ] = value );
  10584. } else {
  10585. return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
  10586. ret :
  10587. elem[ name ];
  10588. }
  10589. },
  10590. propHooks: {
  10591. tabIndex: {
  10592. get: function( elem ) {
  10593. return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
  10594. elem.tabIndex :
  10595. -1;
  10596. }
  10597. }
  10598. }
  10599. });
  10600. if ( !support.optSelected ) {
  10601. jQuery.propHooks.selected = {
  10602. get: function( elem ) {
  10603. var parent = elem.parentNode;
  10604. if ( parent && parent.parentNode ) {
  10605. parent.parentNode.selectedIndex;
  10606. }
  10607. return null;
  10608. }
  10609. };
  10610. }
  10611. jQuery.each([
  10612. "tabIndex",
  10613. "readOnly",
  10614. "maxLength",
  10615. "cellSpacing",
  10616. "cellPadding",
  10617. "rowSpan",
  10618. "colSpan",
  10619. "useMap",
  10620. "frameBorder",
  10621. "contentEditable"
  10622. ], function() {
  10623. jQuery.propFix[ this.toLowerCase() ] = this;
  10624. });
  10625. var rclass = /[\t\r\n\f]/g;
  10626. jQuery.fn.extend({
  10627. addClass: function( value ) {
  10628. var classes, elem, cur, clazz, j, finalValue,
  10629. proceed = typeof value === "string" && value,
  10630. i = 0,
  10631. len = this.length;
  10632. if ( jQuery.isFunction( value ) ) {
  10633. return this.each(function( j ) {
  10634. jQuery( this ).addClass( value.call( this, j, this.className ) );
  10635. });
  10636. }
  10637. if ( proceed ) {
  10638. // The disjunction here is for better compressibility (see removeClass)
  10639. classes = ( value || "" ).match( rnotwhite ) || [];
  10640. for ( ; i < len; i++ ) {
  10641. elem = this[ i ];
  10642. cur = elem.nodeType === 1 && ( elem.className ?
  10643. ( " " + elem.className + " " ).replace( rclass, " " ) :
  10644. " "
  10645. );
  10646. if ( cur ) {
  10647. j = 0;
  10648. while ( (clazz = classes[j++]) ) {
  10649. if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
  10650. cur += clazz + " ";
  10651. }
  10652. }
  10653. // only assign if different to avoid unneeded rendering.
  10654. finalValue = jQuery.trim( cur );
  10655. if ( elem.className !== finalValue ) {
  10656. elem.className = finalValue;
  10657. }
  10658. }
  10659. }
  10660. }
  10661. return this;
  10662. },
  10663. removeClass: function( value ) {
  10664. var classes, elem, cur, clazz, j, finalValue,
  10665. proceed = arguments.length === 0 || typeof value === "string" && value,
  10666. i = 0,
  10667. len = this.length;
  10668. if ( jQuery.isFunction( value ) ) {
  10669. return this.each(function( j ) {
  10670. jQuery( this ).removeClass( value.call( this, j, this.className ) );
  10671. });
  10672. }
  10673. if ( proceed ) {
  10674. classes = ( value || "" ).match( rnotwhite ) || [];
  10675. for ( ; i < len; i++ ) {
  10676. elem = this[ i ];
  10677. // This expression is here for better compressibility (see addClass)
  10678. cur = elem.nodeType === 1 && ( elem.className ?
  10679. ( " " + elem.className + " " ).replace( rclass, " " ) :
  10680. ""
  10681. );
  10682. if ( cur ) {
  10683. j = 0;
  10684. while ( (clazz = classes[j++]) ) {
  10685. // Remove *all* instances
  10686. while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
  10687. cur = cur.replace( " " + clazz + " ", " " );
  10688. }
  10689. }
  10690. // Only assign if different to avoid unneeded rendering.
  10691. finalValue = value ? jQuery.trim( cur ) : "";
  10692. if ( elem.className !== finalValue ) {
  10693. elem.className = finalValue;
  10694. }
  10695. }
  10696. }
  10697. }
  10698. return this;
  10699. },
  10700. toggleClass: function( value, stateVal ) {
  10701. var type = typeof value;
  10702. if ( typeof stateVal === "boolean" && type === "string" ) {
  10703. return stateVal ? this.addClass( value ) : this.removeClass( value );
  10704. }
  10705. if ( jQuery.isFunction( value ) ) {
  10706. return this.each(function( i ) {
  10707. jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
  10708. });
  10709. }
  10710. return this.each(function() {
  10711. if ( type === "string" ) {
  10712. // Toggle individual class names
  10713. var className,
  10714. i = 0,
  10715. self = jQuery( this ),
  10716. classNames = value.match( rnotwhite ) || [];
  10717. while ( (className = classNames[ i++ ]) ) {
  10718. // Check each className given, space separated list
  10719. if ( self.hasClass( className ) ) {
  10720. self.removeClass( className );
  10721. } else {
  10722. self.addClass( className );
  10723. }
  10724. }
  10725. // Toggle whole class name
  10726. } else if ( type === strundefined || type === "boolean" ) {
  10727. if ( this.className ) {
  10728. // store className if set
  10729. data_priv.set( this, "__className__", this.className );
  10730. }
  10731. // If the element has a class name or if we're passed `false`,
  10732. // then remove the whole classname (if there was one, the above saved it).
  10733. // Otherwise bring back whatever was previously saved (if anything),
  10734. // falling back to the empty string if nothing was stored.
  10735. this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
  10736. }
  10737. });
  10738. },
  10739. hasClass: function( selector ) {
  10740. var className = " " + selector + " ",
  10741. i = 0,
  10742. l = this.length;
  10743. for ( ; i < l; i++ ) {
  10744. if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
  10745. return true;
  10746. }
  10747. }
  10748. return false;
  10749. }
  10750. });
  10751. var rreturn = /\r/g;
  10752. jQuery.fn.extend({
  10753. val: function( value ) {
  10754. var hooks, ret, isFunction,
  10755. elem = this[0];
  10756. if ( !arguments.length ) {
  10757. if ( elem ) {
  10758. hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
  10759. if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
  10760. return ret;
  10761. }
  10762. ret = elem.value;
  10763. return typeof ret === "string" ?
  10764. // Handle most common string cases
  10765. ret.replace(rreturn, "") :
  10766. // Handle cases where value is null/undef or number
  10767. ret == null ? "" : ret;
  10768. }
  10769. return;
  10770. }
  10771. isFunction = jQuery.isFunction( value );
  10772. return this.each(function( i ) {
  10773. var val;
  10774. if ( this.nodeType !== 1 ) {
  10775. return;
  10776. }
  10777. if ( isFunction ) {
  10778. val = value.call( this, i, jQuery( this ).val() );
  10779. } else {
  10780. val = value;
  10781. }
  10782. // Treat null/undefined as ""; convert numbers to string
  10783. if ( val == null ) {
  10784. val = "";
  10785. } else if ( typeof val === "number" ) {
  10786. val += "";
  10787. } else if ( jQuery.isArray( val ) ) {
  10788. val = jQuery.map( val, function( value ) {
  10789. return value == null ? "" : value + "";
  10790. });
  10791. }
  10792. hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
  10793. // If set returns undefined, fall back to normal setting
  10794. if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
  10795. this.value = val;
  10796. }
  10797. });
  10798. }
  10799. });
  10800. jQuery.extend({
  10801. valHooks: {
  10802. option: {
  10803. get: function( elem ) {
  10804. var val = jQuery.find.attr( elem, "value" );
  10805. return val != null ?
  10806. val :
  10807. // Support: IE10-11+
  10808. // option.text throws exceptions (#14686, #14858)
  10809. jQuery.trim( jQuery.text( elem ) );
  10810. }
  10811. },
  10812. select: {
  10813. get: function( elem ) {
  10814. var value, option,
  10815. options = elem.options,
  10816. index = elem.selectedIndex,
  10817. one = elem.type === "select-one" || index < 0,
  10818. values = one ? null : [],
  10819. max = one ? index + 1 : options.length,
  10820. i = index < 0 ?
  10821. max :
  10822. one ? index : 0;
  10823. // Loop through all the selected options
  10824. for ( ; i < max; i++ ) {
  10825. option = options[ i ];
  10826. // IE6-9 doesn't update selected after form reset (#2551)
  10827. if ( ( option.selected || i === index ) &&
  10828. // Don't return options that are disabled or in a disabled optgroup
  10829. ( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) &&
  10830. ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
  10831. // Get the specific value for the option
  10832. value = jQuery( option ).val();
  10833. // We don't need an array for one selects
  10834. if ( one ) {
  10835. return value;
  10836. }
  10837. // Multi-Selects return an array
  10838. values.push( value );
  10839. }
  10840. }
  10841. return values;
  10842. },
  10843. set: function( elem, value ) {
  10844. var optionSet, option,
  10845. options = elem.options,
  10846. values = jQuery.makeArray( value ),
  10847. i = options.length;
  10848. while ( i-- ) {
  10849. option = options[ i ];
  10850. if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
  10851. optionSet = true;
  10852. }
  10853. }
  10854. // Force browsers to behave consistently when non-matching value is set
  10855. if ( !optionSet ) {
  10856. elem.selectedIndex = -1;
  10857. }
  10858. return values;
  10859. }
  10860. }
  10861. }
  10862. });
  10863. // Radios and checkboxes getter/setter
  10864. jQuery.each([ "radio", "checkbox" ], function() {
  10865. jQuery.valHooks[ this ] = {
  10866. set: function( elem, value ) {
  10867. if ( jQuery.isArray( value ) ) {
  10868. return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
  10869. }
  10870. }
  10871. };
  10872. if ( !support.checkOn ) {
  10873. jQuery.valHooks[ this ].get = function( elem ) {
  10874. return elem.getAttribute("value") === null ? "on" : elem.value;
  10875. };
  10876. }
  10877. });
  10878. // Return jQuery for attributes-only inclusion
  10879. jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
  10880. "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
  10881. "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
  10882. // Handle event binding
  10883. jQuery.fn[ name ] = function( data, fn ) {
  10884. return arguments.length > 0 ?
  10885. this.on( name, null, data, fn ) :
  10886. this.trigger( name );
  10887. };
  10888. });
  10889. jQuery.fn.extend({
  10890. hover: function( fnOver, fnOut ) {
  10891. return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
  10892. },
  10893. bind: function( types, data, fn ) {
  10894. return this.on( types, null, data, fn );
  10895. },
  10896. unbind: function( types, fn ) {
  10897. return this.off( types, null, fn );
  10898. },
  10899. delegate: function( selector, types, data, fn ) {
  10900. return this.on( types, selector, data, fn );
  10901. },
  10902. undelegate: function( selector, types, fn ) {
  10903. // ( namespace ) or ( selector, types [, fn] )
  10904. return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
  10905. }
  10906. });
  10907. var nonce = jQuery.now();
  10908. var rquery = (/\?/);
  10909. // Support: Android 2.3
  10910. // Workaround failure to string-cast null input
  10911. jQuery.parseJSON = function( data ) {
  10912. return JSON.parse( data + "" );
  10913. };
  10914. // Cross-browser xml parsing
  10915. jQuery.parseXML = function( data ) {
  10916. var xml, tmp;
  10917. if ( !data || typeof data !== "string" ) {
  10918. return null;
  10919. }
  10920. // Support: IE9
  10921. try {
  10922. tmp = new DOMParser();
  10923. xml = tmp.parseFromString( data, "text/xml" );
  10924. } catch ( e ) {
  10925. xml = undefined;
  10926. }
  10927. if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
  10928. jQuery.error( "Invalid XML: " + data );
  10929. }
  10930. return xml;
  10931. };
  10932. var
  10933. rhash = /#.*$/,
  10934. rts = /([?&])_=[^&]*/,
  10935. rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
  10936. // #7653, #8125, #8152: local protocol detection
  10937. rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
  10938. rnoContent = /^(?:GET|HEAD)$/,
  10939. rprotocol = /^\/\//,
  10940. rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
  10941. /* Prefilters
  10942. * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
  10943. * 2) These are called:
  10944. * - BEFORE asking for a transport
  10945. * - AFTER param serialization (s.data is a string if s.processData is true)
  10946. * 3) key is the dataType
  10947. * 4) the catchall symbol "*" can be used
  10948. * 5) execution will start with transport dataType and THEN continue down to "*" if needed
  10949. */
  10950. prefilters = {},
  10951. /* Transports bindings
  10952. * 1) key is the dataType
  10953. * 2) the catchall symbol "*" can be used
  10954. * 3) selection will start with transport dataType and THEN go to "*" if needed
  10955. */
  10956. transports = {},
  10957. // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
  10958. allTypes = "*/".concat( "*" ),
  10959. // Document location
  10960. ajaxLocation = window.location.href,
  10961. // Segment location into parts
  10962. ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
  10963. // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
  10964. function addToPrefiltersOrTransports( structure ) {
  10965. // dataTypeExpression is optional and defaults to "*"
  10966. return function( dataTypeExpression, func ) {
  10967. if ( typeof dataTypeExpression !== "string" ) {
  10968. func = dataTypeExpression;
  10969. dataTypeExpression = "*";
  10970. }
  10971. var dataType,
  10972. i = 0,
  10973. dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
  10974. if ( jQuery.isFunction( func ) ) {
  10975. // For each dataType in the dataTypeExpression
  10976. while ( (dataType = dataTypes[i++]) ) {
  10977. // Prepend if requested
  10978. if ( dataType[0] === "+" ) {
  10979. dataType = dataType.slice( 1 ) || "*";
  10980. (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
  10981. // Otherwise append
  10982. } else {
  10983. (structure[ dataType ] = structure[ dataType ] || []).push( func );
  10984. }
  10985. }
  10986. }
  10987. };
  10988. }
  10989. // Base inspection function for prefilters and transports
  10990. function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
  10991. var inspected = {},
  10992. seekingTransport = ( structure === transports );
  10993. function inspect( dataType ) {
  10994. var selected;
  10995. inspected[ dataType ] = true;
  10996. jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
  10997. var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
  10998. if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
  10999. options.dataTypes.unshift( dataTypeOrTransport );
  11000. inspect( dataTypeOrTransport );
  11001. return false;
  11002. } else if ( seekingTransport ) {
  11003. return !( selected = dataTypeOrTransport );
  11004. }
  11005. });
  11006. return selected;
  11007. }
  11008. return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
  11009. }
  11010. // A special extend for ajax options
  11011. // that takes "flat" options (not to be deep extended)
  11012. // Fixes #9887
  11013. function ajaxExtend( target, src ) {
  11014. var key, deep,
  11015. flatOptions = jQuery.ajaxSettings.flatOptions || {};
  11016. for ( key in src ) {
  11017. if ( src[ key ] !== undefined ) {
  11018. ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
  11019. }
  11020. }
  11021. if ( deep ) {
  11022. jQuery.extend( true, target, deep );
  11023. }
  11024. return target;
  11025. }
  11026. /* Handles responses to an ajax request:
  11027. * - finds the right dataType (mediates between content-type and expected dataType)
  11028. * - returns the corresponding response
  11029. */
  11030. function ajaxHandleResponses( s, jqXHR, responses ) {
  11031. var ct, type, finalDataType, firstDataType,
  11032. contents = s.contents,
  11033. dataTypes = s.dataTypes;
  11034. // Remove auto dataType and get content-type in the process
  11035. while ( dataTypes[ 0 ] === "*" ) {
  11036. dataTypes.shift();
  11037. if ( ct === undefined ) {
  11038. ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
  11039. }
  11040. }
  11041. // Check if we're dealing with a known content-type
  11042. if ( ct ) {
  11043. for ( type in contents ) {
  11044. if ( contents[ type ] && contents[ type ].test( ct ) ) {
  11045. dataTypes.unshift( type );
  11046. break;
  11047. }
  11048. }
  11049. }
  11050. // Check to see if we have a response for the expected dataType
  11051. if ( dataTypes[ 0 ] in responses ) {
  11052. finalDataType = dataTypes[ 0 ];
  11053. } else {
  11054. // Try convertible dataTypes
  11055. for ( type in responses ) {
  11056. if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
  11057. finalDataType = type;
  11058. break;
  11059. }
  11060. if ( !firstDataType ) {
  11061. firstDataType = type;
  11062. }
  11063. }
  11064. // Or just use first one
  11065. finalDataType = finalDataType || firstDataType;
  11066. }
  11067. // If we found a dataType
  11068. // We add the dataType to the list if needed
  11069. // and return the corresponding response
  11070. if ( finalDataType ) {
  11071. if ( finalDataType !== dataTypes[ 0 ] ) {
  11072. dataTypes.unshift( finalDataType );
  11073. }
  11074. return responses[ finalDataType ];
  11075. }
  11076. }
  11077. /* Chain conversions given the request and the original response
  11078. * Also sets the responseXXX fields on the jqXHR instance
  11079. */
  11080. function ajaxConvert( s, response, jqXHR, isSuccess ) {
  11081. var conv2, current, conv, tmp, prev,
  11082. converters = {},
  11083. // Work with a copy of dataTypes in case we need to modify it for conversion
  11084. dataTypes = s.dataTypes.slice();
  11085. // Create converters map with lowercased keys
  11086. if ( dataTypes[ 1 ] ) {
  11087. for ( conv in s.converters ) {
  11088. converters[ conv.toLowerCase() ] = s.converters[ conv ];
  11089. }
  11090. }
  11091. current = dataTypes.shift();
  11092. // Convert to each sequential dataType
  11093. while ( current ) {
  11094. if ( s.responseFields[ current ] ) {
  11095. jqXHR[ s.responseFields[ current ] ] = response;
  11096. }
  11097. // Apply the dataFilter if provided
  11098. if ( !prev && isSuccess && s.dataFilter ) {
  11099. response = s.dataFilter( response, s.dataType );
  11100. }
  11101. prev = current;
  11102. current = dataTypes.shift();
  11103. if ( current ) {
  11104. // There's only work to do if current dataType is non-auto
  11105. if ( current === "*" ) {
  11106. current = prev;
  11107. // Convert response if prev dataType is non-auto and differs from current
  11108. } else if ( prev !== "*" && prev !== current ) {
  11109. // Seek a direct converter
  11110. conv = converters[ prev + " " + current ] || converters[ "* " + current ];
  11111. // If none found, seek a pair
  11112. if ( !conv ) {
  11113. for ( conv2 in converters ) {
  11114. // If conv2 outputs current
  11115. tmp = conv2.split( " " );
  11116. if ( tmp[ 1 ] === current ) {
  11117. // If prev can be converted to accepted input
  11118. conv = converters[ prev + " " + tmp[ 0 ] ] ||
  11119. converters[ "* " + tmp[ 0 ] ];
  11120. if ( conv ) {
  11121. // Condense equivalence converters
  11122. if ( conv === true ) {
  11123. conv = converters[ conv2 ];
  11124. // Otherwise, insert the intermediate dataType
  11125. } else if ( converters[ conv2 ] !== true ) {
  11126. current = tmp[ 0 ];
  11127. dataTypes.unshift( tmp[ 1 ] );
  11128. }
  11129. break;
  11130. }
  11131. }
  11132. }
  11133. }
  11134. // Apply converter (if not an equivalence)
  11135. if ( conv !== true ) {
  11136. // Unless errors are allowed to bubble, catch and return them
  11137. if ( conv && s[ "throws" ] ) {
  11138. response = conv( response );
  11139. } else {
  11140. try {
  11141. response = conv( response );
  11142. } catch ( e ) {
  11143. return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
  11144. }
  11145. }
  11146. }
  11147. }
  11148. }
  11149. }
  11150. return { state: "success", data: response };
  11151. }
  11152. jQuery.extend({
  11153. // Counter for holding the number of active queries
  11154. active: 0,
  11155. // Last-Modified header cache for next request
  11156. lastModified: {},
  11157. etag: {},
  11158. ajaxSettings: {
  11159. url: ajaxLocation,
  11160. type: "GET",
  11161. isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
  11162. global: true,
  11163. processData: true,
  11164. async: true,
  11165. contentType: "application/x-www-form-urlencoded; charset=UTF-8",
  11166. /*
  11167. timeout: 0,
  11168. data: null,
  11169. dataType: null,
  11170. username: null,
  11171. password: null,
  11172. cache: null,
  11173. throws: false,
  11174. traditional: false,
  11175. headers: {},
  11176. */
  11177. accepts: {
  11178. "*": allTypes,
  11179. text: "text/plain",
  11180. html: "text/html",
  11181. xml: "application/xml, text/xml",
  11182. json: "application/json, text/javascript"
  11183. },
  11184. contents: {
  11185. xml: /xml/,
  11186. html: /html/,
  11187. json: /json/
  11188. },
  11189. responseFields: {
  11190. xml: "responseXML",
  11191. text: "responseText",
  11192. json: "responseJSON"
  11193. },
  11194. // Data converters
  11195. // Keys separate source (or catchall "*") and destination types with a single space
  11196. converters: {
  11197. // Convert anything to text
  11198. "* text": String,
  11199. // Text to html (true = no transformation)
  11200. "text html": true,
  11201. // Evaluate text as a json expression
  11202. "text json": jQuery.parseJSON,
  11203. // Parse text as xml
  11204. "text xml": jQuery.parseXML
  11205. },
  11206. // For options that shouldn't be deep extended:
  11207. // you can add your own custom options here if
  11208. // and when you create one that shouldn't be
  11209. // deep extended (see ajaxExtend)
  11210. flatOptions: {
  11211. url: true,
  11212. context: true
  11213. }
  11214. },
  11215. // Creates a full fledged settings object into target
  11216. // with both ajaxSettings and settings fields.
  11217. // If target is omitted, writes into ajaxSettings.
  11218. ajaxSetup: function( target, settings ) {
  11219. return settings ?
  11220. // Building a settings object
  11221. ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
  11222. // Extending ajaxSettings
  11223. ajaxExtend( jQuery.ajaxSettings, target );
  11224. },
  11225. ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
  11226. ajaxTransport: addToPrefiltersOrTransports( transports ),
  11227. // Main method
  11228. ajax: function( url, options ) {
  11229. // If url is an object, simulate pre-1.5 signature
  11230. if ( typeof url === "object" ) {
  11231. options = url;
  11232. url = undefined;
  11233. }
  11234. // Force options to be an object
  11235. options = options || {};
  11236. var transport,
  11237. // URL without anti-cache param
  11238. cacheURL,
  11239. // Response headers
  11240. responseHeadersString,
  11241. responseHeaders,
  11242. // timeout handle
  11243. timeoutTimer,
  11244. // Cross-domain detection vars
  11245. parts,
  11246. // To know if global events are to be dispatched
  11247. fireGlobals,
  11248. // Loop variable
  11249. i,
  11250. // Create the final options object
  11251. s = jQuery.ajaxSetup( {}, options ),
  11252. // Callbacks context
  11253. callbackContext = s.context || s,
  11254. // Context for global events is callbackContext if it is a DOM node or jQuery collection
  11255. globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
  11256. jQuery( callbackContext ) :
  11257. jQuery.event,
  11258. // Deferreds
  11259. deferred = jQuery.Deferred(),
  11260. completeDeferred = jQuery.Callbacks("once memory"),
  11261. // Status-dependent callbacks
  11262. statusCode = s.statusCode || {},
  11263. // Headers (they are sent all at once)
  11264. requestHeaders = {},
  11265. requestHeadersNames = {},
  11266. // The jqXHR state
  11267. state = 0,
  11268. // Default abort message
  11269. strAbort = "canceled",
  11270. // Fake xhr
  11271. jqXHR = {
  11272. readyState: 0,
  11273. // Builds headers hashtable if needed
  11274. getResponseHeader: function( key ) {
  11275. var match;
  11276. if ( state === 2 ) {
  11277. if ( !responseHeaders ) {
  11278. responseHeaders = {};
  11279. while ( (match = rheaders.exec( responseHeadersString )) ) {
  11280. responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
  11281. }
  11282. }
  11283. match = responseHeaders[ key.toLowerCase() ];
  11284. }
  11285. return match == null ? null : match;
  11286. },
  11287. // Raw string
  11288. getAllResponseHeaders: function() {
  11289. return state === 2 ? responseHeadersString : null;
  11290. },
  11291. // Caches the header
  11292. setRequestHeader: function( name, value ) {
  11293. var lname = name.toLowerCase();
  11294. if ( !state ) {
  11295. name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
  11296. requestHeaders[ name ] = value;
  11297. }
  11298. return this;
  11299. },
  11300. // Overrides response content-type header
  11301. overrideMimeType: function( type ) {
  11302. if ( !state ) {
  11303. s.mimeType = type;
  11304. }
  11305. return this;
  11306. },
  11307. // Status-dependent callbacks
  11308. statusCode: function( map ) {
  11309. var code;
  11310. if ( map ) {
  11311. if ( state < 2 ) {
  11312. for ( code in map ) {
  11313. // Lazy-add the new callback in a way that preserves old ones
  11314. statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
  11315. }
  11316. } else {
  11317. // Execute the appropriate callbacks
  11318. jqXHR.always( map[ jqXHR.status ] );
  11319. }
  11320. }
  11321. return this;
  11322. },
  11323. // Cancel the request
  11324. abort: function( statusText ) {
  11325. var finalText = statusText || strAbort;
  11326. if ( transport ) {
  11327. transport.abort( finalText );
  11328. }
  11329. done( 0, finalText );
  11330. return this;
  11331. }
  11332. };
  11333. // Attach deferreds
  11334. deferred.promise( jqXHR ).complete = completeDeferred.add;
  11335. jqXHR.success = jqXHR.done;
  11336. jqXHR.error = jqXHR.fail;
  11337. // Remove hash character (#7531: and string promotion)
  11338. // Add protocol if not provided (prefilters might expect it)
  11339. // Handle falsy url in the settings object (#10093: consistency with old signature)
  11340. // We also use the url parameter if available
  11341. s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
  11342. .replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
  11343. // Alias method option to type as per ticket #12004
  11344. s.type = options.method || options.type || s.method || s.type;
  11345. // Extract dataTypes list
  11346. s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
  11347. // A cross-domain request is in order when we have a protocol:host:port mismatch
  11348. if ( s.crossDomain == null ) {
  11349. parts = rurl.exec( s.url.toLowerCase() );
  11350. s.crossDomain = !!( parts &&
  11351. ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
  11352. ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
  11353. ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
  11354. );
  11355. }
  11356. // Convert data if not already a string
  11357. if ( s.data && s.processData && typeof s.data !== "string" ) {
  11358. s.data = jQuery.param( s.data, s.traditional );
  11359. }
  11360. // Apply prefilters
  11361. inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
  11362. // If request was aborted inside a prefilter, stop there
  11363. if ( state === 2 ) {
  11364. return jqXHR;
  11365. }
  11366. // We can fire global events as of now if asked to
  11367. // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
  11368. fireGlobals = jQuery.event && s.global;
  11369. // Watch for a new set of requests
  11370. if ( fireGlobals && jQuery.active++ === 0 ) {
  11371. jQuery.event.trigger("ajaxStart");
  11372. }
  11373. // Uppercase the type
  11374. s.type = s.type.toUpperCase();
  11375. // Determine if request has content
  11376. s.hasContent = !rnoContent.test( s.type );
  11377. // Save the URL in case we're toying with the If-Modified-Since
  11378. // and/or If-None-Match header later on
  11379. cacheURL = s.url;
  11380. // More options handling for requests with no content
  11381. if ( !s.hasContent ) {
  11382. // If data is available, append data to url
  11383. if ( s.data ) {
  11384. cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
  11385. // #9682: remove data so that it's not used in an eventual retry
  11386. delete s.data;
  11387. }
  11388. // Add anti-cache in url if needed
  11389. if ( s.cache === false ) {
  11390. s.url = rts.test( cacheURL ) ?
  11391. // If there is already a '_' parameter, set its value
  11392. cacheURL.replace( rts, "$1_=" + nonce++ ) :
  11393. // Otherwise add one to the end
  11394. cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
  11395. }
  11396. }
  11397. // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  11398. if ( s.ifModified ) {
  11399. if ( jQuery.lastModified[ cacheURL ] ) {
  11400. jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
  11401. }
  11402. if ( jQuery.etag[ cacheURL ] ) {
  11403. jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
  11404. }
  11405. }
  11406. // Set the correct header, if data is being sent
  11407. if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
  11408. jqXHR.setRequestHeader( "Content-Type", s.contentType );
  11409. }
  11410. // Set the Accepts header for the server, depending on the dataType
  11411. jqXHR.setRequestHeader(
  11412. "Accept",
  11413. s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
  11414. s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
  11415. s.accepts[ "*" ]
  11416. );
  11417. // Check for headers option
  11418. for ( i in s.headers ) {
  11419. jqXHR.setRequestHeader( i, s.headers[ i ] );
  11420. }
  11421. // Allow custom headers/mimetypes and early abort
  11422. if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
  11423. // Abort if not done already and return
  11424. return jqXHR.abort();
  11425. }
  11426. // Aborting is no longer a cancellation
  11427. strAbort = "abort";
  11428. // Install callbacks on deferreds
  11429. for ( i in { success: 1, error: 1, complete: 1 } ) {
  11430. jqXHR[ i ]( s[ i ] );
  11431. }
  11432. // Get transport
  11433. transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
  11434. // If no transport, we auto-abort
  11435. if ( !transport ) {
  11436. done( -1, "No Transport" );
  11437. } else {
  11438. jqXHR.readyState = 1;
  11439. // Send global event
  11440. if ( fireGlobals ) {
  11441. globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
  11442. }
  11443. // Timeout
  11444. if ( s.async && s.timeout > 0 ) {
  11445. timeoutTimer = setTimeout(function() {
  11446. jqXHR.abort("timeout");
  11447. }, s.timeout );
  11448. }
  11449. try {
  11450. state = 1;
  11451. transport.send( requestHeaders, done );
  11452. } catch ( e ) {
  11453. // Propagate exception as error if not done
  11454. if ( state < 2 ) {
  11455. done( -1, e );
  11456. // Simply rethrow otherwise
  11457. } else {
  11458. throw e;
  11459. }
  11460. }
  11461. }
  11462. // Callback for when everything is done
  11463. function done( status, nativeStatusText, responses, headers ) {
  11464. var isSuccess, success, error, response, modified,
  11465. statusText = nativeStatusText;
  11466. // Called once
  11467. if ( state === 2 ) {
  11468. return;
  11469. }
  11470. // State is "done" now
  11471. state = 2;
  11472. // Clear timeout if it exists
  11473. if ( timeoutTimer ) {
  11474. clearTimeout( timeoutTimer );
  11475. }
  11476. // Dereference transport for early garbage collection
  11477. // (no matter how long the jqXHR object will be used)
  11478. transport = undefined;
  11479. // Cache response headers
  11480. responseHeadersString = headers || "";
  11481. // Set readyState
  11482. jqXHR.readyState = status > 0 ? 4 : 0;
  11483. // Determine if successful
  11484. isSuccess = status >= 200 && status < 300 || status === 304;
  11485. // Get response data
  11486. if ( responses ) {
  11487. response = ajaxHandleResponses( s, jqXHR, responses );
  11488. }
  11489. // Convert no matter what (that way responseXXX fields are always set)
  11490. response = ajaxConvert( s, response, jqXHR, isSuccess );
  11491. // If successful, handle type chaining
  11492. if ( isSuccess ) {
  11493. // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  11494. if ( s.ifModified ) {
  11495. modified = jqXHR.getResponseHeader("Last-Modified");
  11496. if ( modified ) {
  11497. jQuery.lastModified[ cacheURL ] = modified;
  11498. }
  11499. modified = jqXHR.getResponseHeader("etag");
  11500. if ( modified ) {
  11501. jQuery.etag[ cacheURL ] = modified;
  11502. }
  11503. }
  11504. // if no content
  11505. if ( status === 204 || s.type === "HEAD" ) {
  11506. statusText = "nocontent";
  11507. // if not modified
  11508. } else if ( status === 304 ) {
  11509. statusText = "notmodified";
  11510. // If we have data, let's convert it
  11511. } else {
  11512. statusText = response.state;
  11513. success = response.data;
  11514. error = response.error;
  11515. isSuccess = !error;
  11516. }
  11517. } else {
  11518. // Extract error from statusText and normalize for non-aborts
  11519. error = statusText;
  11520. if ( status || !statusText ) {
  11521. statusText = "error";
  11522. if ( status < 0 ) {
  11523. status = 0;
  11524. }
  11525. }
  11526. }
  11527. // Set data for the fake xhr object
  11528. jqXHR.status = status;
  11529. jqXHR.statusText = ( nativeStatusText || statusText ) + "";
  11530. // Success/Error
  11531. if ( isSuccess ) {
  11532. deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
  11533. } else {
  11534. deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
  11535. }
  11536. // Status-dependent callbacks
  11537. jqXHR.statusCode( statusCode );
  11538. statusCode = undefined;
  11539. if ( fireGlobals ) {
  11540. globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
  11541. [ jqXHR, s, isSuccess ? success : error ] );
  11542. }
  11543. // Complete
  11544. completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
  11545. if ( fireGlobals ) {
  11546. globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
  11547. // Handle the global AJAX counter
  11548. if ( !( --jQuery.active ) ) {
  11549. jQuery.event.trigger("ajaxStop");
  11550. }
  11551. }
  11552. }
  11553. return jqXHR;
  11554. },
  11555. getJSON: function( url, data, callback ) {
  11556. return jQuery.get( url, data, callback, "json" );
  11557. },
  11558. getScript: function( url, callback ) {
  11559. return jQuery.get( url, undefined, callback, "script" );
  11560. }
  11561. });
  11562. jQuery.each( [ "get", "post" ], function( i, method ) {
  11563. jQuery[ method ] = function( url, data, callback, type ) {
  11564. // Shift arguments if data argument was omitted
  11565. if ( jQuery.isFunction( data ) ) {
  11566. type = type || callback;
  11567. callback = data;
  11568. data = undefined;
  11569. }
  11570. return jQuery.ajax({
  11571. url: url,
  11572. type: method,
  11573. dataType: type,
  11574. data: data,
  11575. success: callback
  11576. });
  11577. };
  11578. });
  11579. jQuery._evalUrl = function( url ) {
  11580. return jQuery.ajax({
  11581. url: url,
  11582. type: "GET",
  11583. dataType: "script",
  11584. async: false,
  11585. global: false,
  11586. "throws": true
  11587. });
  11588. };
  11589. jQuery.fn.extend({
  11590. wrapAll: function( html ) {
  11591. var wrap;
  11592. if ( jQuery.isFunction( html ) ) {
  11593. return this.each(function( i ) {
  11594. jQuery( this ).wrapAll( html.call(this, i) );
  11595. });
  11596. }
  11597. if ( this[ 0 ] ) {
  11598. // The elements to wrap the target around
  11599. wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
  11600. if ( this[ 0 ].parentNode ) {
  11601. wrap.insertBefore( this[ 0 ] );
  11602. }
  11603. wrap.map(function() {
  11604. var elem = this;
  11605. while ( elem.firstElementChild ) {
  11606. elem = elem.firstElementChild;
  11607. }
  11608. return elem;
  11609. }).append( this );
  11610. }
  11611. return this;
  11612. },
  11613. wrapInner: function( html ) {
  11614. if ( jQuery.isFunction( html ) ) {
  11615. return this.each(function( i ) {
  11616. jQuery( this ).wrapInner( html.call(this, i) );
  11617. });
  11618. }
  11619. return this.each(function() {
  11620. var self = jQuery( this ),
  11621. contents = self.contents();
  11622. if ( contents.length ) {
  11623. contents.wrapAll( html );
  11624. } else {
  11625. self.append( html );
  11626. }
  11627. });
  11628. },
  11629. wrap: function( html ) {
  11630. var isFunction = jQuery.isFunction( html );
  11631. return this.each(function( i ) {
  11632. jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
  11633. });
  11634. },
  11635. unwrap: function() {
  11636. return this.parent().each(function() {
  11637. if ( !jQuery.nodeName( this, "body" ) ) {
  11638. jQuery( this ).replaceWith( this.childNodes );
  11639. }
  11640. }).end();
  11641. }
  11642. });
  11643. jQuery.expr.filters.hidden = function( elem ) {
  11644. // Support: Opera <= 12.12
  11645. // Opera reports offsetWidths and offsetHeights less than zero on some elements
  11646. return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
  11647. };
  11648. jQuery.expr.filters.visible = function( elem ) {
  11649. return !jQuery.expr.filters.hidden( elem );
  11650. };
  11651. var r20 = /%20/g,
  11652. rbracket = /\[\]$/,
  11653. rCRLF = /\r?\n/g,
  11654. rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
  11655. rsubmittable = /^(?:input|select|textarea|keygen)/i;
  11656. function buildParams( prefix, obj, traditional, add ) {
  11657. var name;
  11658. if ( jQuery.isArray( obj ) ) {
  11659. // Serialize array item.
  11660. jQuery.each( obj, function( i, v ) {
  11661. if ( traditional || rbracket.test( prefix ) ) {
  11662. // Treat each array item as a scalar.
  11663. add( prefix, v );
  11664. } else {
  11665. // Item is non-scalar (array or object), encode its numeric index.
  11666. buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
  11667. }
  11668. });
  11669. } else if ( !traditional && jQuery.type( obj ) === "object" ) {
  11670. // Serialize object item.
  11671. for ( name in obj ) {
  11672. buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
  11673. }
  11674. } else {
  11675. // Serialize scalar item.
  11676. add( prefix, obj );
  11677. }
  11678. }
  11679. // Serialize an array of form elements or a set of
  11680. // key/values into a query string
  11681. jQuery.param = function( a, traditional ) {
  11682. var prefix,
  11683. s = [],
  11684. add = function( key, value ) {
  11685. // If value is a function, invoke it and return its value
  11686. value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
  11687. s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
  11688. };
  11689. // Set traditional to true for jQuery <= 1.3.2 behavior.
  11690. if ( traditional === undefined ) {
  11691. traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
  11692. }
  11693. // If an array was passed in, assume that it is an array of form elements.
  11694. if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
  11695. // Serialize the form elements
  11696. jQuery.each( a, function() {
  11697. add( this.name, this.value );
  11698. });
  11699. } else {
  11700. // If traditional, encode the "old" way (the way 1.3.2 or older
  11701. // did it), otherwise encode params recursively.
  11702. for ( prefix in a ) {
  11703. buildParams( prefix, a[ prefix ], traditional, add );
  11704. }
  11705. }
  11706. // Return the resulting serialization
  11707. return s.join( "&" ).replace( r20, "+" );
  11708. };
  11709. jQuery.fn.extend({
  11710. serialize: function() {
  11711. return jQuery.param( this.serializeArray() );
  11712. },
  11713. serializeArray: function() {
  11714. return this.map(function() {
  11715. // Can add propHook for "elements" to filter or add form elements
  11716. var elements = jQuery.prop( this, "elements" );
  11717. return elements ? jQuery.makeArray( elements ) : this;
  11718. })
  11719. .filter(function() {
  11720. var type = this.type;
  11721. // Use .is( ":disabled" ) so that fieldset[disabled] works
  11722. return this.name && !jQuery( this ).is( ":disabled" ) &&
  11723. rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
  11724. ( this.checked || !rcheckableType.test( type ) );
  11725. })
  11726. .map(function( i, elem ) {
  11727. var val = jQuery( this ).val();
  11728. return val == null ?
  11729. null :
  11730. jQuery.isArray( val ) ?
  11731. jQuery.map( val, function( val ) {
  11732. return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
  11733. }) :
  11734. { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
  11735. }).get();
  11736. }
  11737. });
  11738. jQuery.ajaxSettings.xhr = function() {
  11739. try {
  11740. return new XMLHttpRequest();
  11741. } catch( e ) {}
  11742. };
  11743. var xhrId = 0,
  11744. xhrCallbacks = {},
  11745. xhrSuccessStatus = {
  11746. // file protocol always yields status code 0, assume 200
  11747. 0: 200,
  11748. // Support: IE9
  11749. // #1450: sometimes IE returns 1223 when it should be 204
  11750. 1223: 204
  11751. },
  11752. xhrSupported = jQuery.ajaxSettings.xhr();
  11753. // Support: IE9
  11754. // Open requests must be manually aborted on unload (#5280)
  11755. // See https://support.microsoft.com/kb/2856746 for more info
  11756. if ( window.attachEvent ) {
  11757. window.attachEvent( "onunload", function() {
  11758. for ( var key in xhrCallbacks ) {
  11759. xhrCallbacks[ key ]();
  11760. }
  11761. });
  11762. }
  11763. support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
  11764. support.ajax = xhrSupported = !!xhrSupported;
  11765. jQuery.ajaxTransport(function( options ) {
  11766. var callback;
  11767. // Cross domain only allowed if supported through XMLHttpRequest
  11768. if ( support.cors || xhrSupported && !options.crossDomain ) {
  11769. return {
  11770. send: function( headers, complete ) {
  11771. var i,
  11772. xhr = options.xhr(),
  11773. id = ++xhrId;
  11774. xhr.open( options.type, options.url, options.async, options.username, options.password );
  11775. // Apply custom fields if provided
  11776. if ( options.xhrFields ) {
  11777. for ( i in options.xhrFields ) {
  11778. xhr[ i ] = options.xhrFields[ i ];
  11779. }
  11780. }
  11781. // Override mime type if needed
  11782. if ( options.mimeType && xhr.overrideMimeType ) {
  11783. xhr.overrideMimeType( options.mimeType );
  11784. }
  11785. // X-Requested-With header
  11786. // For cross-domain requests, seeing as conditions for a preflight are
  11787. // akin to a jigsaw puzzle, we simply never set it to be sure.
  11788. // (it can always be set on a per-request basis or even using ajaxSetup)
  11789. // For same-domain requests, won't change header if already provided.
  11790. if ( !options.crossDomain && !headers["X-Requested-With"] ) {
  11791. headers["X-Requested-With"] = "XMLHttpRequest";
  11792. }
  11793. // Set headers
  11794. for ( i in headers ) {
  11795. xhr.setRequestHeader( i, headers[ i ] );
  11796. }
  11797. // Callback
  11798. callback = function( type ) {
  11799. return function() {
  11800. if ( callback ) {
  11801. delete xhrCallbacks[ id ];
  11802. callback = xhr.onload = xhr.onerror = null;
  11803. if ( type === "abort" ) {
  11804. xhr.abort();
  11805. } else if ( type === "error" ) {
  11806. complete(
  11807. // file: protocol always yields status 0; see #8605, #14207
  11808. xhr.status,
  11809. xhr.statusText
  11810. );
  11811. } else {
  11812. complete(
  11813. xhrSuccessStatus[ xhr.status ] || xhr.status,
  11814. xhr.statusText,
  11815. // Support: IE9
  11816. // Accessing binary-data responseText throws an exception
  11817. // (#11426)
  11818. typeof xhr.responseText === "string" ? {
  11819. text: xhr.responseText
  11820. } : undefined,
  11821. xhr.getAllResponseHeaders()
  11822. );
  11823. }
  11824. }
  11825. };
  11826. };
  11827. // Listen to events
  11828. xhr.onload = callback();
  11829. xhr.onerror = callback("error");
  11830. // Create the abort callback
  11831. callback = xhrCallbacks[ id ] = callback("abort");
  11832. try {
  11833. // Do send the request (this may raise an exception)
  11834. xhr.send( options.hasContent && options.data || null );
  11835. } catch ( e ) {
  11836. // #14683: Only rethrow if this hasn't been notified as an error yet
  11837. if ( callback ) {
  11838. throw e;
  11839. }
  11840. }
  11841. },
  11842. abort: function() {
  11843. if ( callback ) {
  11844. callback();
  11845. }
  11846. }
  11847. };
  11848. }
  11849. });
  11850. // Install script dataType
  11851. jQuery.ajaxSetup({
  11852. accepts: {
  11853. script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
  11854. },
  11855. contents: {
  11856. script: /(?:java|ecma)script/
  11857. },
  11858. converters: {
  11859. "text script": function( text ) {
  11860. jQuery.globalEval( text );
  11861. return text;
  11862. }
  11863. }
  11864. });
  11865. // Handle cache's special case and crossDomain
  11866. jQuery.ajaxPrefilter( "script", function( s ) {
  11867. if ( s.cache === undefined ) {
  11868. s.cache = false;
  11869. }
  11870. if ( s.crossDomain ) {
  11871. s.type = "GET";
  11872. }
  11873. });
  11874. // Bind script tag hack transport
  11875. jQuery.ajaxTransport( "script", function( s ) {
  11876. // This transport only deals with cross domain requests
  11877. if ( s.crossDomain ) {
  11878. var script, callback;
  11879. return {
  11880. send: function( _, complete ) {
  11881. script = jQuery("<script>").prop({
  11882. async: true,
  11883. charset: s.scriptCharset,
  11884. src: s.url
  11885. }).on(
  11886. "load error",
  11887. callback = function( evt ) {
  11888. script.remove();
  11889. callback = null;
  11890. if ( evt ) {
  11891. complete( evt.type === "error" ? 404 : 200, evt.type );
  11892. }
  11893. }
  11894. );
  11895. document.head.appendChild( script[ 0 ] );
  11896. },
  11897. abort: function() {
  11898. if ( callback ) {
  11899. callback();
  11900. }
  11901. }
  11902. };
  11903. }
  11904. });
  11905. var oldCallbacks = [],
  11906. rjsonp = /(=)\?(?=&|$)|\?\?/;
  11907. // Default jsonp settings
  11908. jQuery.ajaxSetup({
  11909. jsonp: "callback",
  11910. jsonpCallback: function() {
  11911. var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
  11912. this[ callback ] = true;
  11913. return callback;
  11914. }
  11915. });
  11916. // Detect, normalize options and install callbacks for jsonp requests
  11917. jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
  11918. var callbackName, overwritten, responseContainer,
  11919. jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
  11920. "url" :
  11921. typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
  11922. );
  11923. // Handle iff the expected data type is "jsonp" or we have a parameter to set
  11924. if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
  11925. // Get callback name, remembering preexisting value associated with it
  11926. callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
  11927. s.jsonpCallback() :
  11928. s.jsonpCallback;
  11929. // Insert callback into url or form data
  11930. if ( jsonProp ) {
  11931. s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
  11932. } else if ( s.jsonp !== false ) {
  11933. s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
  11934. }
  11935. // Use data converter to retrieve json after script execution
  11936. s.converters["script json"] = function() {
  11937. if ( !responseContainer ) {
  11938. jQuery.error( callbackName + " was not called" );
  11939. }
  11940. return responseContainer[ 0 ];
  11941. };
  11942. // force json dataType
  11943. s.dataTypes[ 0 ] = "json";
  11944. // Install callback
  11945. overwritten = window[ callbackName ];
  11946. window[ callbackName ] = function() {
  11947. responseContainer = arguments;
  11948. };
  11949. // Clean-up function (fires after converters)
  11950. jqXHR.always(function() {
  11951. // Restore preexisting value
  11952. window[ callbackName ] = overwritten;
  11953. // Save back as free
  11954. if ( s[ callbackName ] ) {
  11955. // make sure that re-using the options doesn't screw things around
  11956. s.jsonpCallback = originalSettings.jsonpCallback;
  11957. // save the callback name for future use
  11958. oldCallbacks.push( callbackName );
  11959. }
  11960. // Call if it was a function and we have a response
  11961. if ( responseContainer && jQuery.isFunction( overwritten ) ) {
  11962. overwritten( responseContainer[ 0 ] );
  11963. }
  11964. responseContainer = overwritten = undefined;
  11965. });
  11966. // Delegate to script
  11967. return "script";
  11968. }
  11969. });
  11970. // data: string of html
  11971. // context (optional): If specified, the fragment will be created in this context, defaults to document
  11972. // keepScripts (optional): If true, will include scripts passed in the html string
  11973. jQuery.parseHTML = function( data, context, keepScripts ) {
  11974. if ( !data || typeof data !== "string" ) {
  11975. return null;
  11976. }
  11977. if ( typeof context === "boolean" ) {
  11978. keepScripts = context;
  11979. context = false;
  11980. }
  11981. context = context || document;
  11982. var parsed = rsingleTag.exec( data ),
  11983. scripts = !keepScripts && [];
  11984. // Single tag
  11985. if ( parsed ) {
  11986. return [ context.createElement( parsed[1] ) ];
  11987. }
  11988. parsed = jQuery.buildFragment( [ data ], context, scripts );
  11989. if ( scripts && scripts.length ) {
  11990. jQuery( scripts ).remove();
  11991. }
  11992. return jQuery.merge( [], parsed.childNodes );
  11993. };
  11994. // Keep a copy of the old load method
  11995. var _load = jQuery.fn.load;
  11996. /**
  11997. * Load a url into a page
  11998. */
  11999. jQuery.fn.load = function( url, params, callback ) {
  12000. if ( typeof url !== "string" && _load ) {
  12001. return _load.apply( this, arguments );
  12002. }
  12003. var selector, type, response,
  12004. self = this,
  12005. off = url.indexOf(" ");
  12006. if ( off >= 0 ) {
  12007. selector = jQuery.trim( url.slice( off ) );
  12008. url = url.slice( 0, off );
  12009. }
  12010. // If it's a function
  12011. if ( jQuery.isFunction( params ) ) {
  12012. // We assume that it's the callback
  12013. callback = params;
  12014. params = undefined;
  12015. // Otherwise, build a param string
  12016. } else if ( params && typeof params === "object" ) {
  12017. type = "POST";
  12018. }
  12019. // If we have elements to modify, make the request
  12020. if ( self.length > 0 ) {
  12021. jQuery.ajax({
  12022. url: url,
  12023. // if "type" variable is undefined, then "GET" method will be used
  12024. type: type,
  12025. dataType: "html",
  12026. data: params
  12027. }).done(function( responseText ) {
  12028. // Save response for use in complete callback
  12029. response = arguments;
  12030. self.html( selector ?
  12031. // If a selector was specified, locate the right elements in a dummy div
  12032. // Exclude scripts to avoid IE 'Permission Denied' errors
  12033. jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
  12034. // Otherwise use the full result
  12035. responseText );
  12036. }).complete( callback && function( jqXHR, status ) {
  12037. self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
  12038. });
  12039. }
  12040. return this;
  12041. };
  12042. // Attach a bunch of functions for handling common AJAX events
  12043. jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
  12044. jQuery.fn[ type ] = function( fn ) {
  12045. return this.on( type, fn );
  12046. };
  12047. });
  12048. jQuery.expr.filters.animated = function( elem ) {
  12049. return jQuery.grep(jQuery.timers, function( fn ) {
  12050. return elem === fn.elem;
  12051. }).length;
  12052. };
  12053. var docElem = window.document.documentElement;
  12054. /**
  12055. * Gets a window from an element
  12056. */
  12057. function getWindow( elem ) {
  12058. return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
  12059. }
  12060. jQuery.offset = {
  12061. setOffset: function( elem, options, i ) {
  12062. var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
  12063. position = jQuery.css( elem, "position" ),
  12064. curElem = jQuery( elem ),
  12065. props = {};
  12066. // Set position first, in-case top/left are set even on static elem
  12067. if ( position === "static" ) {
  12068. elem.style.position = "relative";
  12069. }
  12070. curOffset = curElem.offset();
  12071. curCSSTop = jQuery.css( elem, "top" );
  12072. curCSSLeft = jQuery.css( elem, "left" );
  12073. calculatePosition = ( position === "absolute" || position === "fixed" ) &&
  12074. ( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
  12075. // Need to be able to calculate position if either
  12076. // top or left is auto and position is either absolute or fixed
  12077. if ( calculatePosition ) {
  12078. curPosition = curElem.position();
  12079. curTop = curPosition.top;
  12080. curLeft = curPosition.left;
  12081. } else {
  12082. curTop = parseFloat( curCSSTop ) || 0;
  12083. curLeft = parseFloat( curCSSLeft ) || 0;
  12084. }
  12085. if ( jQuery.isFunction( options ) ) {
  12086. options = options.call( elem, i, curOffset );
  12087. }
  12088. if ( options.top != null ) {
  12089. props.top = ( options.top - curOffset.top ) + curTop;
  12090. }
  12091. if ( options.left != null ) {
  12092. props.left = ( options.left - curOffset.left ) + curLeft;
  12093. }
  12094. if ( "using" in options ) {
  12095. options.using.call( elem, props );
  12096. } else {
  12097. curElem.css( props );
  12098. }
  12099. }
  12100. };
  12101. jQuery.fn.extend({
  12102. offset: function( options ) {
  12103. if ( arguments.length ) {
  12104. return options === undefined ?
  12105. this :
  12106. this.each(function( i ) {
  12107. jQuery.offset.setOffset( this, options, i );
  12108. });
  12109. }
  12110. var docElem, win,
  12111. elem = this[ 0 ],
  12112. box = { top: 0, left: 0 },
  12113. doc = elem && elem.ownerDocument;
  12114. if ( !doc ) {
  12115. return;
  12116. }
  12117. docElem = doc.documentElement;
  12118. // Make sure it's not a disconnected DOM node
  12119. if ( !jQuery.contains( docElem, elem ) ) {
  12120. return box;
  12121. }
  12122. // Support: BlackBerry 5, iOS 3 (original iPhone)
  12123. // If we don't have gBCR, just use 0,0 rather than error
  12124. if ( typeof elem.getBoundingClientRect !== strundefined ) {
  12125. box = elem.getBoundingClientRect();
  12126. }
  12127. win = getWindow( doc );
  12128. return {
  12129. top: box.top + win.pageYOffset - docElem.clientTop,
  12130. left: box.left + win.pageXOffset - docElem.clientLeft
  12131. };
  12132. },
  12133. position: function() {
  12134. if ( !this[ 0 ] ) {
  12135. return;
  12136. }
  12137. var offsetParent, offset,
  12138. elem = this[ 0 ],
  12139. parentOffset = { top: 0, left: 0 };
  12140. // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
  12141. if ( jQuery.css( elem, "position" ) === "fixed" ) {
  12142. // Assume getBoundingClientRect is there when computed position is fixed
  12143. offset = elem.getBoundingClientRect();
  12144. } else {
  12145. // Get *real* offsetParent
  12146. offsetParent = this.offsetParent();
  12147. // Get correct offsets
  12148. offset = this.offset();
  12149. if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
  12150. parentOffset = offsetParent.offset();
  12151. }
  12152. // Add offsetParent borders
  12153. parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
  12154. parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
  12155. }
  12156. // Subtract parent offsets and element margins
  12157. return {
  12158. top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
  12159. left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
  12160. };
  12161. },
  12162. offsetParent: function() {
  12163. return this.map(function() {
  12164. var offsetParent = this.offsetParent || docElem;
  12165. while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
  12166. offsetParent = offsetParent.offsetParent;
  12167. }
  12168. return offsetParent || docElem;
  12169. });
  12170. }
  12171. });
  12172. // Create scrollLeft and scrollTop methods
  12173. jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
  12174. var top = "pageYOffset" === prop;
  12175. jQuery.fn[ method ] = function( val ) {
  12176. return access( this, function( elem, method, val ) {
  12177. var win = getWindow( elem );
  12178. if ( val === undefined ) {
  12179. return win ? win[ prop ] : elem[ method ];
  12180. }
  12181. if ( win ) {
  12182. win.scrollTo(
  12183. !top ? val : window.pageXOffset,
  12184. top ? val : window.pageYOffset
  12185. );
  12186. } else {
  12187. elem[ method ] = val;
  12188. }
  12189. }, method, val, arguments.length, null );
  12190. };
  12191. });
  12192. // Support: Safari<7+, Chrome<37+
  12193. // Add the top/left cssHooks using jQuery.fn.position
  12194. // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
  12195. // Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
  12196. // getComputedStyle returns percent when specified for top/left/bottom/right;
  12197. // rather than make the css module depend on the offset module, just check for it here
  12198. jQuery.each( [ "top", "left" ], function( i, prop ) {
  12199. jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
  12200. function( elem, computed ) {
  12201. if ( computed ) {
  12202. computed = curCSS( elem, prop );
  12203. // If curCSS returns percentage, fallback to offset
  12204. return rnumnonpx.test( computed ) ?
  12205. jQuery( elem ).position()[ prop ] + "px" :
  12206. computed;
  12207. }
  12208. }
  12209. );
  12210. });
  12211. // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
  12212. jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
  12213. jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
  12214. // Margin is only for outerHeight, outerWidth
  12215. jQuery.fn[ funcName ] = function( margin, value ) {
  12216. var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
  12217. extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
  12218. return access( this, function( elem, type, value ) {
  12219. var doc;
  12220. if ( jQuery.isWindow( elem ) ) {
  12221. // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
  12222. // isn't a whole lot we can do. See pull request at this URL for discussion:
  12223. // https://github.com/jquery/jquery/pull/764
  12224. return elem.document.documentElement[ "client" + name ];
  12225. }
  12226. // Get document width or height
  12227. if ( elem.nodeType === 9 ) {
  12228. doc = elem.documentElement;
  12229. // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
  12230. // whichever is greatest
  12231. return Math.max(
  12232. elem.body[ "scroll" + name ], doc[ "scroll" + name ],
  12233. elem.body[ "offset" + name ], doc[ "offset" + name ],
  12234. doc[ "client" + name ]
  12235. );
  12236. }
  12237. return value === undefined ?
  12238. // Get width or height on the element, requesting but not forcing parseFloat
  12239. jQuery.css( elem, type, extra ) :
  12240. // Set width or height on the element
  12241. jQuery.style( elem, type, value, extra );
  12242. }, type, chainable ? margin : undefined, chainable, null );
  12243. };
  12244. });
  12245. });
  12246. // The number of elements contained in the matched element set
  12247. jQuery.fn.size = function() {
  12248. return this.length;
  12249. };
  12250. jQuery.fn.andSelf = jQuery.fn.addBack;
  12251. // Register as a named AMD module, since jQuery can be concatenated with other
  12252. // files that may use define, but not via a proper concatenation script that
  12253. // understands anonymous AMD modules. A named AMD is safest and most robust
  12254. // way to register. Lowercase jquery is used because AMD module names are
  12255. // derived from file names, and jQuery is normally delivered in a lowercase
  12256. // file name. Do this after creating the global so that if an AMD module wants
  12257. // to call noConflict to hide this version of jQuery, it will work.
  12258. // Note that for maximum portability, libraries that are not jQuery should
  12259. // declare themselves as anonymous modules, and avoid setting a global if an
  12260. // AMD loader is present. jQuery is a special case. For more information, see
  12261. // https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
  12262. if ( typeof define === "function" && define.amd ) {
  12263. define( "jquery", [], function() {
  12264. return jQuery;
  12265. });
  12266. }
  12267. var
  12268. // Map over jQuery in case of overwrite
  12269. _jQuery = window.jQuery,
  12270. // Map over the $ in case of overwrite
  12271. _$ = window.$;
  12272. jQuery.noConflict = function( deep ) {
  12273. if ( window.$ === jQuery ) {
  12274. window.$ = _$;
  12275. }
  12276. if ( deep && window.jQuery === jQuery ) {
  12277. window.jQuery = _jQuery;
  12278. }
  12279. return jQuery;
  12280. };
  12281. // Expose jQuery and $ identifiers, even in AMD
  12282. // (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
  12283. // and CommonJS for browser emulators (#13566)
  12284. if ( typeof noGlobal === strundefined ) {
  12285. window.jQuery = window.$ = jQuery;
  12286. }
  12287. return jQuery;
  12288. }));
  12289. },{}],19:[function(require,module,exports){
  12290. /**
  12291. * Module dependencies.
  12292. */
  12293. var Emitter = require('emitter');
  12294. var reduce = require('reduce');
  12295. /**
  12296. * Root reference for iframes.
  12297. */
  12298. var root = 'undefined' == typeof window
  12299. ? this
  12300. : window;
  12301. /**
  12302. * Noop.
  12303. */
  12304. function noop(){};
  12305. /**
  12306. * Check if `obj` is a host object,
  12307. * we don't want to serialize these :)
  12308. *
  12309. * TODO: future proof, move to compoent land
  12310. *
  12311. * @param {Object} obj
  12312. * @return {Boolean}
  12313. * @api private
  12314. */
  12315. function isHost(obj) {
  12316. var str = {}.toString.call(obj);
  12317. switch (str) {
  12318. case '[object File]':
  12319. case '[object Blob]':
  12320. case '[object FormData]':
  12321. return true;
  12322. default:
  12323. return false;
  12324. }
  12325. }
  12326. /**
  12327. * Determine XHR.
  12328. */
  12329. function getXHR() {
  12330. if (root.XMLHttpRequest
  12331. && ('file:' != root.location.protocol || !root.ActiveXObject)) {
  12332. return new XMLHttpRequest;
  12333. } else {
  12334. try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
  12335. try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}
  12336. try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}
  12337. try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
  12338. }
  12339. return false;
  12340. }
  12341. /**
  12342. * Removes leading and trailing whitespace, added to support IE.
  12343. *
  12344. * @param {String} s
  12345. * @return {String}
  12346. * @api private
  12347. */
  12348. var trim = ''.trim
  12349. ? function(s) { return s.trim(); }
  12350. : function(s) { return s.replace(/(^\s*|\s*$)/g, ''); };
  12351. /**
  12352. * Check if `obj` is an object.
  12353. *
  12354. * @param {Object} obj
  12355. * @return {Boolean}
  12356. * @api private
  12357. */
  12358. function isObject(obj) {
  12359. return obj === Object(obj);
  12360. }
  12361. /**
  12362. * Serialize the given `obj`.
  12363. *
  12364. * @param {Object} obj
  12365. * @return {String}
  12366. * @api private
  12367. */
  12368. function serialize(obj) {
  12369. if (!isObject(obj)) return obj;
  12370. var pairs = [];
  12371. for (var key in obj) {
  12372. if (null != obj[key]) {
  12373. pairs.push(encodeURIComponent(key)
  12374. + '=' + encodeURIComponent(obj[key]));
  12375. }
  12376. }
  12377. return pairs.join('&');
  12378. }
  12379. /**
  12380. * Expose serialization method.
  12381. */
  12382. request.serializeObject = serialize;
  12383. /**
  12384. * Parse the given x-www-form-urlencoded `str`.
  12385. *
  12386. * @param {String} str
  12387. * @return {Object}
  12388. * @api private
  12389. */
  12390. function parseString(str) {
  12391. var obj = {};
  12392. var pairs = str.split('&');
  12393. var parts;
  12394. var pair;
  12395. for (var i = 0, len = pairs.length; i < len; ++i) {
  12396. pair = pairs[i];
  12397. parts = pair.split('=');
  12398. obj[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
  12399. }
  12400. return obj;
  12401. }
  12402. /**
  12403. * Expose parser.
  12404. */
  12405. request.parseString = parseString;
  12406. /**
  12407. * Default MIME type map.
  12408. *
  12409. * superagent.types.xml = 'application/xml';
  12410. *
  12411. */
  12412. request.types = {
  12413. html: 'text/html',
  12414. json: 'application/json',
  12415. xml: 'application/xml',
  12416. urlencoded: 'application/x-www-form-urlencoded',
  12417. 'form': 'application/x-www-form-urlencoded',
  12418. 'form-data': 'application/x-www-form-urlencoded'
  12419. };
  12420. /**
  12421. * Default serialization map.
  12422. *
  12423. * superagent.serialize['application/xml'] = function(obj){
  12424. * return 'generated xml here';
  12425. * };
  12426. *
  12427. */
  12428. request.serialize = {
  12429. 'application/x-www-form-urlencoded': serialize,
  12430. 'application/json': JSON.stringify
  12431. };
  12432. /**
  12433. * Default parsers.
  12434. *
  12435. * superagent.parse['application/xml'] = function(str){
  12436. * return { object parsed from str };
  12437. * };
  12438. *
  12439. */
  12440. request.parse = {
  12441. 'application/x-www-form-urlencoded': parseString,
  12442. 'application/json': JSON.parse
  12443. };
  12444. /**
  12445. * Parse the given header `str` into
  12446. * an object containing the mapped fields.
  12447. *
  12448. * @param {String} str
  12449. * @return {Object}
  12450. * @api private
  12451. */
  12452. function parseHeader(str) {
  12453. var lines = str.split(/\r?\n/);
  12454. var fields = {};
  12455. var index;
  12456. var line;
  12457. var field;
  12458. var val;
  12459. lines.pop(); // trailing CRLF
  12460. for (var i = 0, len = lines.length; i < len; ++i) {
  12461. line = lines[i];
  12462. index = line.indexOf(':');
  12463. field = line.slice(0, index).toLowerCase();
  12464. val = trim(line.slice(index + 1));
  12465. fields[field] = val;
  12466. }
  12467. return fields;
  12468. }
  12469. /**
  12470. * Return the mime type for the given `str`.
  12471. *
  12472. * @param {String} str
  12473. * @return {String}
  12474. * @api private
  12475. */
  12476. function type(str){
  12477. return str.split(/ *; */).shift();
  12478. };
  12479. /**
  12480. * Return header field parameters.
  12481. *
  12482. * @param {String} str
  12483. * @return {Object}
  12484. * @api private
  12485. */
  12486. function params(str){
  12487. return reduce(str.split(/ *; */), function(obj, str){
  12488. var parts = str.split(/ *= */)
  12489. , key = parts.shift()
  12490. , val = parts.shift();
  12491. if (key && val) obj[key] = val;
  12492. return obj;
  12493. }, {});
  12494. };
  12495. /**
  12496. * Initialize a new `Response` with the given `xhr`.
  12497. *
  12498. * - set flags (.ok, .error, etc)
  12499. * - parse header
  12500. *
  12501. * Examples:
  12502. *
  12503. * Aliasing `superagent` as `request` is nice:
  12504. *
  12505. * request = superagent;
  12506. *
  12507. * We can use the promise-like API, or pass callbacks:
  12508. *
  12509. * request.get('/').end(function(res){});
  12510. * request.get('/', function(res){});
  12511. *
  12512. * Sending data can be chained:
  12513. *
  12514. * request
  12515. * .post('/user')
  12516. * .send({ name: 'tj' })
  12517. * .end(function(res){});
  12518. *
  12519. * Or passed to `.send()`:
  12520. *
  12521. * request
  12522. * .post('/user')
  12523. * .send({ name: 'tj' }, function(res){});
  12524. *
  12525. * Or passed to `.post()`:
  12526. *
  12527. * request
  12528. * .post('/user', { name: 'tj' })
  12529. * .end(function(res){});
  12530. *
  12531. * Or further reduced to a single call for simple cases:
  12532. *
  12533. * request
  12534. * .post('/user', { name: 'tj' }, function(res){});
  12535. *
  12536. * @param {XMLHTTPRequest} xhr
  12537. * @param {Object} options
  12538. * @api private
  12539. */
  12540. function Response(req, options) {
  12541. options = options || {};
  12542. this.req = req;
  12543. this.xhr = this.req.xhr;
  12544. this.text = this.req.method !='HEAD'
  12545. ? this.xhr.responseText
  12546. : null;
  12547. this.setStatusProperties(this.xhr.status);
  12548. this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());
  12549. // getAllResponseHeaders sometimes falsely returns "" for CORS requests, but
  12550. // getResponseHeader still works. so we get content-type even if getting
  12551. // other headers fails.
  12552. this.header['content-type'] = this.xhr.getResponseHeader('content-type');
  12553. this.setHeaderProperties(this.header);
  12554. this.body = this.req.method != 'HEAD'
  12555. ? this.parseBody(this.text)
  12556. : null;
  12557. }
  12558. /**
  12559. * Get case-insensitive `field` value.
  12560. *
  12561. * @param {String} field
  12562. * @return {String}
  12563. * @api public
  12564. */
  12565. Response.prototype.get = function(field){
  12566. return this.header[field.toLowerCase()];
  12567. };
  12568. /**
  12569. * Set header related properties:
  12570. *
  12571. * - `.type` the content type without params
  12572. *
  12573. * A response of "Content-Type: text/plain; charset=utf-8"
  12574. * will provide you with a `.type` of "text/plain".
  12575. *
  12576. * @param {Object} header
  12577. * @api private
  12578. */
  12579. Response.prototype.setHeaderProperties = function(header){
  12580. // content-type
  12581. var ct = this.header['content-type'] || '';
  12582. this.type = type(ct);
  12583. // params
  12584. var obj = params(ct);
  12585. for (var key in obj) this[key] = obj[key];
  12586. };
  12587. /**
  12588. * Parse the given body `str`.
  12589. *
  12590. * Used for auto-parsing of bodies. Parsers
  12591. * are defined on the `superagent.parse` object.
  12592. *
  12593. * @param {String} str
  12594. * @return {Mixed}
  12595. * @api private
  12596. */
  12597. Response.prototype.parseBody = function(str){
  12598. var parse = request.parse[this.type];
  12599. return parse && str && str.length
  12600. ? parse(str)
  12601. : null;
  12602. };
  12603. /**
  12604. * Set flags such as `.ok` based on `status`.
  12605. *
  12606. * For example a 2xx response will give you a `.ok` of __true__
  12607. * whereas 5xx will be __false__ and `.error` will be __true__. The
  12608. * `.clientError` and `.serverError` are also available to be more
  12609. * specific, and `.statusType` is the class of error ranging from 1..5
  12610. * sometimes useful for mapping respond colors etc.
  12611. *
  12612. * "sugar" properties are also defined for common cases. Currently providing:
  12613. *
  12614. * - .noContent
  12615. * - .badRequest
  12616. * - .unauthorized
  12617. * - .notAcceptable
  12618. * - .notFound
  12619. *
  12620. * @param {Number} status
  12621. * @api private
  12622. */
  12623. Response.prototype.setStatusProperties = function(status){
  12624. var type = status / 100 | 0;
  12625. // status / class
  12626. this.status = status;
  12627. this.statusType = type;
  12628. // basics
  12629. this.info = 1 == type;
  12630. this.ok = 2 == type;
  12631. this.clientError = 4 == type;
  12632. this.serverError = 5 == type;
  12633. this.error = (4 == type || 5 == type)
  12634. ? this.toError()
  12635. : false;
  12636. // sugar
  12637. this.accepted = 202 == status;
  12638. this.noContent = 204 == status || 1223 == status;
  12639. this.badRequest = 400 == status;
  12640. this.unauthorized = 401 == status;
  12641. this.notAcceptable = 406 == status;
  12642. this.notFound = 404 == status;
  12643. this.forbidden = 403 == status;
  12644. };
  12645. /**
  12646. * Return an `Error` representative of this response.
  12647. *
  12648. * @return {Error}
  12649. * @api public
  12650. */
  12651. Response.prototype.toError = function(){
  12652. var req = this.req;
  12653. var method = req.method;
  12654. var url = req.url;
  12655. var msg = 'cannot ' + method + ' ' + url + ' (' + this.status + ')';
  12656. var err = new Error(msg);
  12657. err.status = this.status;
  12658. err.method = method;
  12659. err.url = url;
  12660. return err;
  12661. };
  12662. /**
  12663. * Expose `Response`.
  12664. */
  12665. request.Response = Response;
  12666. /**
  12667. * Initialize a new `Request` with the given `method` and `url`.
  12668. *
  12669. * @param {String} method
  12670. * @param {String} url
  12671. * @api public
  12672. */
  12673. function Request(method, url) {
  12674. var self = this;
  12675. Emitter.call(this);
  12676. this._query = this._query || [];
  12677. this.method = method;
  12678. this.url = url;
  12679. this.header = {};
  12680. this._header = {};
  12681. this.on('end', function(){
  12682. var err = null;
  12683. var res = null;
  12684. try {
  12685. res = new Response(self);
  12686. } catch(e) {
  12687. err = new Error('Parser is unable to parse the response');
  12688. err.parse = true;
  12689. err.original = e;
  12690. }
  12691. self.callback(err, res);
  12692. });
  12693. }
  12694. /**
  12695. * Mixin `Emitter`.
  12696. */
  12697. Emitter(Request.prototype);
  12698. /**
  12699. * Allow for extension
  12700. */
  12701. Request.prototype.use = function(fn) {
  12702. fn(this);
  12703. return this;
  12704. }
  12705. /**
  12706. * Set timeout to `ms`.
  12707. *
  12708. * @param {Number} ms
  12709. * @return {Request} for chaining
  12710. * @api public
  12711. */
  12712. Request.prototype.timeout = function(ms){
  12713. this._timeout = ms;
  12714. return this;
  12715. };
  12716. /**
  12717. * Clear previous timeout.
  12718. *
  12719. * @return {Request} for chaining
  12720. * @api public
  12721. */
  12722. Request.prototype.clearTimeout = function(){
  12723. this._timeout = 0;
  12724. clearTimeout(this._timer);
  12725. return this;
  12726. };
  12727. /**
  12728. * Abort the request, and clear potential timeout.
  12729. *
  12730. * @return {Request}
  12731. * @api public
  12732. */
  12733. Request.prototype.abort = function(){
  12734. if (this.aborted) return;
  12735. this.aborted = true;
  12736. this.xhr.abort();
  12737. this.clearTimeout();
  12738. this.emit('abort');
  12739. return this;
  12740. };
  12741. /**
  12742. * Set header `field` to `val`, or multiple fields with one object.
  12743. *
  12744. * Examples:
  12745. *
  12746. * req.get('/')
  12747. * .set('Accept', 'application/json')
  12748. * .set('X-API-Key', 'foobar')
  12749. * .end(callback);
  12750. *
  12751. * req.get('/')
  12752. * .set({ Accept: 'application/json', 'X-API-Key': 'foobar' })
  12753. * .end(callback);
  12754. *
  12755. * @param {String|Object} field
  12756. * @param {String} val
  12757. * @return {Request} for chaining
  12758. * @api public
  12759. */
  12760. Request.prototype.set = function(field, val){
  12761. if (isObject(field)) {
  12762. for (var key in field) {
  12763. this.set(key, field[key]);
  12764. }
  12765. return this;
  12766. }
  12767. this._header[field.toLowerCase()] = val;
  12768. this.header[field] = val;
  12769. return this;
  12770. };
  12771. /**
  12772. * Remove header `field`.
  12773. *
  12774. * Example:
  12775. *
  12776. * req.get('/')
  12777. * .unset('User-Agent')
  12778. * .end(callback);
  12779. *
  12780. * @param {String} field
  12781. * @return {Request} for chaining
  12782. * @api public
  12783. */
  12784. Request.prototype.unset = function(field){
  12785. delete this._header[field.toLowerCase()];
  12786. delete this.header[field];
  12787. return this;
  12788. };
  12789. /**
  12790. * Get case-insensitive header `field` value.
  12791. *
  12792. * @param {String} field
  12793. * @return {String}
  12794. * @api private
  12795. */
  12796. Request.prototype.getHeader = function(field){
  12797. return this._header[field.toLowerCase()];
  12798. };
  12799. /**
  12800. * Set Content-Type to `type`, mapping values from `request.types`.
  12801. *
  12802. * Examples:
  12803. *
  12804. * superagent.types.xml = 'application/xml';
  12805. *
  12806. * request.post('/')
  12807. * .type('xml')
  12808. * .send(xmlstring)
  12809. * .end(callback);
  12810. *
  12811. * request.post('/')
  12812. * .type('application/xml')
  12813. * .send(xmlstring)
  12814. * .end(callback);
  12815. *
  12816. * @param {String} type
  12817. * @return {Request} for chaining
  12818. * @api public
  12819. */
  12820. Request.prototype.type = function(type){
  12821. this.set('Content-Type', request.types[type] || type);
  12822. return this;
  12823. };
  12824. /**
  12825. * Set Accept to `type`, mapping values from `request.types`.
  12826. *
  12827. * Examples:
  12828. *
  12829. * superagent.types.json = 'application/json';
  12830. *
  12831. * request.get('/agent')
  12832. * .accept('json')
  12833. * .end(callback);
  12834. *
  12835. * request.get('/agent')
  12836. * .accept('application/json')
  12837. * .end(callback);
  12838. *
  12839. * @param {String} accept
  12840. * @return {Request} for chaining
  12841. * @api public
  12842. */
  12843. Request.prototype.accept = function(type){
  12844. this.set('Accept', request.types[type] || type);
  12845. return this;
  12846. };
  12847. /**
  12848. * Set Authorization field value with `user` and `pass`.
  12849. *
  12850. * @param {String} user
  12851. * @param {String} pass
  12852. * @return {Request} for chaining
  12853. * @api public
  12854. */
  12855. Request.prototype.auth = function(user, pass){
  12856. var str = btoa(user + ':' + pass);
  12857. this.set('Authorization', 'Basic ' + str);
  12858. return this;
  12859. };
  12860. /**
  12861. * Add query-string `val`.
  12862. *
  12863. * Examples:
  12864. *
  12865. * request.get('/shoes')
  12866. * .query('size=10')
  12867. * .query({ color: 'blue' })
  12868. *
  12869. * @param {Object|String} val
  12870. * @return {Request} for chaining
  12871. * @api public
  12872. */
  12873. Request.prototype.query = function(val){
  12874. if ('string' != typeof val) val = serialize(val);
  12875. if (val) this._query.push(val);
  12876. return this;
  12877. };
  12878. /**
  12879. * Write the field `name` and `val` for "multipart/form-data"
  12880. * request bodies.
  12881. *
  12882. * ``` js
  12883. * request.post('/upload')
  12884. * .field('foo', 'bar')
  12885. * .end(callback);
  12886. * ```
  12887. *
  12888. * @param {String} name
  12889. * @param {String|Blob|File} val
  12890. * @return {Request} for chaining
  12891. * @api public
  12892. */
  12893. Request.prototype.field = function(name, val){
  12894. if (!this._formData) this._formData = new FormData();
  12895. this._formData.append(name, val);
  12896. return this;
  12897. };
  12898. /**
  12899. * Queue the given `file` as an attachment to the specified `field`,
  12900. * with optional `filename`.
  12901. *
  12902. * ``` js
  12903. * request.post('/upload')
  12904. * .attach(new Blob(['<a id="a"><b id="b">hey!</b></a>'], { type: "text/html"}))
  12905. * .end(callback);
  12906. * ```
  12907. *
  12908. * @param {String} field
  12909. * @param {Blob|File} file
  12910. * @param {String} filename
  12911. * @return {Request} for chaining
  12912. * @api public
  12913. */
  12914. Request.prototype.attach = function(field, file, filename){
  12915. if (!this._formData) this._formData = new FormData();
  12916. this._formData.append(field, file, filename);
  12917. return this;
  12918. };
  12919. /**
  12920. * Send `data`, defaulting the `.type()` to "json" when
  12921. * an object is given.
  12922. *
  12923. * Examples:
  12924. *
  12925. * // querystring
  12926. * request.get('/search')
  12927. * .end(callback)
  12928. *
  12929. * // multiple data "writes"
  12930. * request.get('/search')
  12931. * .send({ search: 'query' })
  12932. * .send({ range: '1..5' })
  12933. * .send({ order: 'desc' })
  12934. * .end(callback)
  12935. *
  12936. * // manual json
  12937. * request.post('/user')
  12938. * .type('json')
  12939. * .send('{"name":"tj"})
  12940. * .end(callback)
  12941. *
  12942. * // auto json
  12943. * request.post('/user')
  12944. * .send({ name: 'tj' })
  12945. * .end(callback)
  12946. *
  12947. * // manual x-www-form-urlencoded
  12948. * request.post('/user')
  12949. * .type('form')
  12950. * .send('name=tj')
  12951. * .end(callback)
  12952. *
  12953. * // auto x-www-form-urlencoded
  12954. * request.post('/user')
  12955. * .type('form')
  12956. * .send({ name: 'tj' })
  12957. * .end(callback)
  12958. *
  12959. * // defaults to x-www-form-urlencoded
  12960. * request.post('/user')
  12961. * .send('name=tobi')
  12962. * .send('species=ferret')
  12963. * .end(callback)
  12964. *
  12965. * @param {String|Object} data
  12966. * @return {Request} for chaining
  12967. * @api public
  12968. */
  12969. Request.prototype.send = function(data){
  12970. var obj = isObject(data);
  12971. var type = this.getHeader('Content-Type');
  12972. // merge
  12973. if (obj && isObject(this._data)) {
  12974. for (var key in data) {
  12975. this._data[key] = data[key];
  12976. }
  12977. } else if ('string' == typeof data) {
  12978. if (!type) this.type('form');
  12979. type = this.getHeader('Content-Type');
  12980. if ('application/x-www-form-urlencoded' == type) {
  12981. this._data = this._data
  12982. ? this._data + '&' + data
  12983. : data;
  12984. } else {
  12985. this._data = (this._data || '') + data;
  12986. }
  12987. } else {
  12988. this._data = data;
  12989. }
  12990. if (!obj) return this;
  12991. if (!type) this.type('json');
  12992. return this;
  12993. };
  12994. /**
  12995. * Invoke the callback with `err` and `res`
  12996. * and handle arity check.
  12997. *
  12998. * @param {Error} err
  12999. * @param {Response} res
  13000. * @api private
  13001. */
  13002. Request.prototype.callback = function(err, res){
  13003. var fn = this._callback;
  13004. this.clearTimeout();
  13005. if (2 == fn.length) return fn(err, res);
  13006. if (err) return this.emit('error', err);
  13007. fn(res);
  13008. };
  13009. /**
  13010. * Invoke callback with x-domain error.
  13011. *
  13012. * @api private
  13013. */
  13014. Request.prototype.crossDomainError = function(){
  13015. var err = new Error('Origin is not allowed by Access-Control-Allow-Origin');
  13016. err.crossDomain = true;
  13017. this.callback(err);
  13018. };
  13019. /**
  13020. * Invoke callback with timeout error.
  13021. *
  13022. * @api private
  13023. */
  13024. Request.prototype.timeoutError = function(){
  13025. var timeout = this._timeout;
  13026. var err = new Error('timeout of ' + timeout + 'ms exceeded');
  13027. err.timeout = timeout;
  13028. this.callback(err);
  13029. };
  13030. /**
  13031. * Enable transmission of cookies with x-domain requests.
  13032. *
  13033. * Note that for this to work the origin must not be
  13034. * using "Access-Control-Allow-Origin" with a wildcard,
  13035. * and also must set "Access-Control-Allow-Credentials"
  13036. * to "true".
  13037. *
  13038. * @api public
  13039. */
  13040. Request.prototype.withCredentials = function(){
  13041. this._withCredentials = true;
  13042. return this;
  13043. };
  13044. /**
  13045. * Initiate request, invoking callback `fn(res)`
  13046. * with an instanceof `Response`.
  13047. *
  13048. * @param {Function} fn
  13049. * @return {Request} for chaining
  13050. * @api public
  13051. */
  13052. Request.prototype.end = function(fn){
  13053. var self = this;
  13054. var xhr = this.xhr = getXHR();
  13055. var query = this._query.join('&');
  13056. var timeout = this._timeout;
  13057. var data = this._formData || this._data;
  13058. // store callback
  13059. this._callback = fn || noop;
  13060. // state change
  13061. xhr.onreadystatechange = function(){
  13062. if (4 != xhr.readyState) return;
  13063. if (0 == xhr.status) {
  13064. if (self.aborted) return self.timeoutError();
  13065. return self.crossDomainError();
  13066. }
  13067. self.emit('end');
  13068. };
  13069. // progress
  13070. if (xhr.upload) {
  13071. xhr.upload.onprogress = function(e){
  13072. e.percent = e.loaded / e.total * 100;
  13073. self.emit('progress', e);
  13074. };
  13075. }
  13076. // timeout
  13077. if (timeout && !this._timer) {
  13078. this._timer = setTimeout(function(){
  13079. self.abort();
  13080. }, timeout);
  13081. }
  13082. // querystring
  13083. if (query) {
  13084. query = request.serializeObject(query);
  13085. this.url += ~this.url.indexOf('?')
  13086. ? '&' + query
  13087. : '?' + query;
  13088. }
  13089. // initiate request
  13090. xhr.open(this.method, this.url, true);
  13091. // CORS
  13092. if (this._withCredentials) xhr.withCredentials = true;
  13093. // body
  13094. if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !isHost(data)) {
  13095. // serialize stuff
  13096. var serialize = request.serialize[this.getHeader('Content-Type')];
  13097. if (serialize) data = serialize(data);
  13098. }
  13099. // set header fields
  13100. for (var field in this.header) {
  13101. if (null == this.header[field]) continue;
  13102. xhr.setRequestHeader(field, this.header[field]);
  13103. }
  13104. // send stuff
  13105. this.emit('request', this);
  13106. xhr.send(data);
  13107. return this;
  13108. };
  13109. /**
  13110. * Expose `Request`.
  13111. */
  13112. request.Request = Request;
  13113. /**
  13114. * Issue a request:
  13115. *
  13116. * Examples:
  13117. *
  13118. * request('GET', '/users').end(callback)
  13119. * request('/users').end(callback)
  13120. * request('/users', callback)
  13121. *
  13122. * @param {String} method
  13123. * @param {String|Function} url or callback
  13124. * @return {Request}
  13125. * @api public
  13126. */
  13127. function request(method, url) {
  13128. // callback
  13129. if ('function' == typeof url) {
  13130. return new Request('GET', method).end(url);
  13131. }
  13132. // url first
  13133. if (1 == arguments.length) {
  13134. return new Request('GET', method);
  13135. }
  13136. return new Request(method, url);
  13137. }
  13138. /**
  13139. * GET `url` with optional callback `fn(res)`.
  13140. *
  13141. * @param {String} url
  13142. * @param {Mixed|Function} data or fn
  13143. * @param {Function} fn
  13144. * @return {Request}
  13145. * @api public
  13146. */
  13147. request.get = function(url, data, fn){
  13148. var req = request('GET', url);
  13149. if ('function' == typeof data) fn = data, data = null;
  13150. if (data) req.query(data);
  13151. if (fn) req.end(fn);
  13152. return req;
  13153. };
  13154. /**
  13155. * HEAD `url` with optional callback `fn(res)`.
  13156. *
  13157. * @param {String} url
  13158. * @param {Mixed|Function} data or fn
  13159. * @param {Function} fn
  13160. * @return {Request}
  13161. * @api public
  13162. */
  13163. request.head = function(url, data, fn){
  13164. var req = request('HEAD', url);
  13165. if ('function' == typeof data) fn = data, data = null;
  13166. if (data) req.send(data);
  13167. if (fn) req.end(fn);
  13168. return req;
  13169. };
  13170. /**
  13171. * DELETE `url` with optional callback `fn(res)`.
  13172. *
  13173. * @param {String} url
  13174. * @param {Function} fn
  13175. * @return {Request}
  13176. * @api public
  13177. */
  13178. request.del = function(url, fn){
  13179. var req = request('DELETE', url);
  13180. if (fn) req.end(fn);
  13181. return req;
  13182. };
  13183. /**
  13184. * PATCH `url` with optional `data` and callback `fn(res)`.
  13185. *
  13186. * @param {String} url
  13187. * @param {Mixed} data
  13188. * @param {Function} fn
  13189. * @return {Request}
  13190. * @api public
  13191. */
  13192. request.patch = function(url, data, fn){
  13193. var req = request('PATCH', url);
  13194. if ('function' == typeof data) fn = data, data = null;
  13195. if (data) req.send(data);
  13196. if (fn) req.end(fn);
  13197. return req;
  13198. };
  13199. /**
  13200. * POST `url` with optional `data` and callback `fn(res)`.
  13201. *
  13202. * @param {String} url
  13203. * @param {Mixed} data
  13204. * @param {Function} fn
  13205. * @return {Request}
  13206. * @api public
  13207. */
  13208. request.post = function(url, data, fn){
  13209. var req = request('POST', url);
  13210. if ('function' == typeof data) fn = data, data = null;
  13211. if (data) req.send(data);
  13212. if (fn) req.end(fn);
  13213. return req;
  13214. };
  13215. /**
  13216. * PUT `url` with optional `data` and callback `fn(res)`.
  13217. *
  13218. * @param {String} url
  13219. * @param {Mixed|Function} data or fn
  13220. * @param {Function} fn
  13221. * @return {Request}
  13222. * @api public
  13223. */
  13224. request.put = function(url, data, fn){
  13225. var req = request('PUT', url);
  13226. if ('function' == typeof data) fn = data, data = null;
  13227. if (data) req.send(data);
  13228. if (fn) req.end(fn);
  13229. return req;
  13230. };
  13231. /**
  13232. * Expose `request`.
  13233. */
  13234. module.exports = request;
  13235. },{"emitter":20,"reduce":21}],20:[function(require,module,exports){
  13236. /**
  13237. * Expose `Emitter`.
  13238. */
  13239. module.exports = Emitter;
  13240. /**
  13241. * Initialize a new `Emitter`.
  13242. *
  13243. * @api public
  13244. */
  13245. function Emitter(obj) {
  13246. if (obj) return mixin(obj);
  13247. };
  13248. /**
  13249. * Mixin the emitter properties.
  13250. *
  13251. * @param {Object} obj
  13252. * @return {Object}
  13253. * @api private
  13254. */
  13255. function mixin(obj) {
  13256. for (var key in Emitter.prototype) {
  13257. obj[key] = Emitter.prototype[key];
  13258. }
  13259. return obj;
  13260. }
  13261. /**
  13262. * Listen on the given `event` with `fn`.
  13263. *
  13264. * @param {String} event
  13265. * @param {Function} fn
  13266. * @return {Emitter}
  13267. * @api public
  13268. */
  13269. Emitter.prototype.on =
  13270. Emitter.prototype.addEventListener = function(event, fn){
  13271. this._callbacks = this._callbacks || {};
  13272. (this._callbacks[event] = this._callbacks[event] || [])
  13273. .push(fn);
  13274. return this;
  13275. };
  13276. /**
  13277. * Adds an `event` listener that will be invoked a single
  13278. * time then automatically removed.
  13279. *
  13280. * @param {String} event
  13281. * @param {Function} fn
  13282. * @return {Emitter}
  13283. * @api public
  13284. */
  13285. Emitter.prototype.once = function(event, fn){
  13286. var self = this;
  13287. this._callbacks = this._callbacks || {};
  13288. function on() {
  13289. self.off(event, on);
  13290. fn.apply(this, arguments);
  13291. }
  13292. on.fn = fn;
  13293. this.on(event, on);
  13294. return this;
  13295. };
  13296. /**
  13297. * Remove the given callback for `event` or all
  13298. * registered callbacks.
  13299. *
  13300. * @param {String} event
  13301. * @param {Function} fn
  13302. * @return {Emitter}
  13303. * @api public
  13304. */
  13305. Emitter.prototype.off =
  13306. Emitter.prototype.removeListener =
  13307. Emitter.prototype.removeAllListeners =
  13308. Emitter.prototype.removeEventListener = function(event, fn){
  13309. this._callbacks = this._callbacks || {};
  13310. // all
  13311. if (0 == arguments.length) {
  13312. this._callbacks = {};
  13313. return this;
  13314. }
  13315. // specific event
  13316. var callbacks = this._callbacks[event];
  13317. if (!callbacks) return this;
  13318. // remove all handlers
  13319. if (1 == arguments.length) {
  13320. delete this._callbacks[event];
  13321. return this;
  13322. }
  13323. // remove specific handler
  13324. var cb;
  13325. for (var i = 0; i < callbacks.length; i++) {
  13326. cb = callbacks[i];
  13327. if (cb === fn || cb.fn === fn) {
  13328. callbacks.splice(i, 1);
  13329. break;
  13330. }
  13331. }
  13332. return this;
  13333. };
  13334. /**
  13335. * Emit `event` with the given args.
  13336. *
  13337. * @param {String} event
  13338. * @param {Mixed} ...
  13339. * @return {Emitter}
  13340. */
  13341. Emitter.prototype.emit = function(event){
  13342. this._callbacks = this._callbacks || {};
  13343. var args = [].slice.call(arguments, 1)
  13344. , callbacks = this._callbacks[event];
  13345. if (callbacks) {
  13346. callbacks = callbacks.slice(0);
  13347. for (var i = 0, len = callbacks.length; i < len; ++i) {
  13348. callbacks[i].apply(this, args);
  13349. }
  13350. }
  13351. return this;
  13352. };
  13353. /**
  13354. * Return array of callbacks for `event`.
  13355. *
  13356. * @param {String} event
  13357. * @return {Array}
  13358. * @api public
  13359. */
  13360. Emitter.prototype.listeners = function(event){
  13361. this._callbacks = this._callbacks || {};
  13362. return this._callbacks[event] || [];
  13363. };
  13364. /**
  13365. * Check if this emitter has `event` handlers.
  13366. *
  13367. * @param {String} event
  13368. * @return {Boolean}
  13369. * @api public
  13370. */
  13371. Emitter.prototype.hasListeners = function(event){
  13372. return !! this.listeners(event).length;
  13373. };
  13374. },{}],21:[function(require,module,exports){
  13375. /**
  13376. * Reduce `arr` with `fn`.
  13377. *
  13378. * @param {Array} arr
  13379. * @param {Function} fn
  13380. * @param {Mixed} initial
  13381. *
  13382. * TODO: combatible error handling?
  13383. */
  13384. module.exports = function(arr, fn, initial){
  13385. var idx = 0;
  13386. var len = arr.length;
  13387. var curr = arguments.length == 3
  13388. ? initial
  13389. : arr[idx++];
  13390. while (idx < len) {
  13391. curr = fn.call(null, curr, arr[idx], ++idx, arr);
  13392. }
  13393. return curr;
  13394. };
  13395. },{}]},{},[1])(1)
  13396. });
  13397. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJpbmRleC5qcyIsImxpYi9hdXRoLmpzIiwibGliL2NsaWVudC1jb21wYXQuanMiLCJsaWIvY2xpZW50LmpzIiwibGliL2hlbHBlcnMuanMiLCJsaWIvaHR0cC5qcyIsImxpYi9yZXNvbHZlci5qcyIsImxpYi90eXBlcy9hcnJheU1vZGVsLmpzIiwibGliL3R5cGVzL21vZGVsLmpzIiwibGliL3R5cGVzL29wZXJhdGlvbi5qcyIsImxpYi90eXBlcy9vcGVyYXRpb25Hcm91cC5qcyIsIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9idWZmZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnVmZmVyL25vZGVfbW9kdWxlcy9iYXNlNjQtanMvbGliL2I2NC5qcyIsIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9idWZmZXIvbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnVmZmVyL25vZGVfbW9kdWxlcy9pcy1hcnJheS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9idG9hL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Nvb2tpZWphci9jb29raWVqYXIuanMiLCJub2RlX21vZHVsZXMvanF1ZXJ5L2Rpc3QvanF1ZXJ5LmpzIiwibm9kZV9tb2R1bGVzL3N1cGVyYWdlbnQvbGliL2NsaWVudC5qcyIsIm5vZGVfbW9kdWxlcy9zdXBlcmFnZW50L25vZGVfbW9kdWxlcy9jb21wb25lbnQtZW1pdHRlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zdXBlcmFnZW50L25vZGVfbW9kdWxlcy9yZWR1Y2UtY29tcG9uZW50L2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3Y2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0V0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3UEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9GQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaldBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy93QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzl4Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3IvUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6akNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIid1c2Ugc3RyaWN0JztcblxudmFyIGF1dGggPSByZXF1aXJlKCcuL2xpYi9hdXRoJyk7XG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4vbGliL2hlbHBlcnMnKTtcbnZhciBTd2FnZ2VyQ2xpZW50ID0gcmVxdWlyZSgnLi9saWIvY2xpZW50LWNvbXBhdCcpO1xudmFyIGRlcHJlY2F0aW9uV3JhcHBlciA9IGZ1bmN0aW9uICh1cmwsIG9wdGlvbnMpIHtcbiAgaGVscGVycy5sb2coJ1RoaXMgaXMgZGVwcmVjYXRlZCwgdXNlIFwibmV3IFN3YWdnZXJDbGllbnRcIiBpbnN0ZWFkLicpO1xuXG4gIHJldHVybiBuZXcgU3dhZ2dlckNsaWVudCh1cmwsIG9wdGlvbnMpO1xufTtcblxuLyogSGVyZSBmb3IgSUU4IFN1cHBvcnQgKi9cbmlmICghQXJyYXkucHJvdG90eXBlLmluZGV4T2YpIHtcbiAgQXJyYXkucHJvdG90eXBlLmluZGV4T2YgPSBmdW5jdGlvbihvYmosIHN0YXJ0KSB7XG4gICAgZm9yICh2YXIgaSA9IChzdGFydCB8fCAwKSwgaiA9IHRoaXMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XG4gICAgICBpZiAodGhpc1tpXSA9PT0gb2JqKSB7IHJldHVybiBpOyB9XG4gICAgfVxuICAgIHJldHVybiAtMTtcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBTd2FnZ2VyQ2xpZW50O1xuXG5Td2FnZ2VyQ2xpZW50LkFwaUtleUF1dGhvcml6YXRpb24gPSBhdXRoLkFwaUtleUF1dGhvcml6YXRpb247XG5Td2FnZ2VyQ2xpZW50LlBhc3N3b3JkQXV0aG9yaXphdGlvbiA9IGF1dGguUGFzc3dvcmRBdXRob3JpemF0aW9uO1xuU3dhZ2dlckNsaWVudC5Db29raWVBdXRob3JpemF0aW9uID0gYXV0aC5Db29raWVBdXRob3JpemF0aW9uO1xuU3dhZ2dlckNsaWVudC5Td2FnZ2VyQXBpID0gZGVwcmVjYXRpb25XcmFwcGVyO1xuU3dhZ2dlckNsaWVudC5Td2FnZ2VyQ2xpZW50ID0gZGVwcmVjYXRpb25XcmFwcGVyO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYnRvYSA9IHJlcXVpcmUoJ2J0b2EnKTsgLy8ganNoaW50IGlnbm9yZTpsaW5lXG52YXIgQ29va2llSmFyID0gcmVxdWlyZSgnY29va2llamFyJyk7XG5cbi8qKlxuICogU3dhZ2dlckF1dGhvcml6YXRpb25zIGFwcGx5cyB0aGUgY29ycmVjdCBhdXRob3JpemF0aW9uIHRvIGFuIG9wZXJhdGlvbiBiZWluZyBleGVjdXRlZFxuICovXG52YXIgU3dhZ2dlckF1dGhvcml6YXRpb25zID0gbW9kdWxlLmV4cG9ydHMuU3dhZ2dlckF1dGhvcml6YXRpb25zID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmF1dGh6ID0ge307XG59O1xuXG5Td2FnZ2VyQXV0aG9yaXphdGlvbnMucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIChuYW1lLCBhdXRoKSB7XG4gIHRoaXMuYXV0aHpbbmFtZV0gPSBhdXRoO1xuXG4gIHJldHVybiBhdXRoO1xufTtcblxuU3dhZ2dlckF1dGhvcml6YXRpb25zLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbiAobmFtZSkge1xuICByZXR1cm4gZGVsZXRlIHRoaXMuYXV0aHpbbmFtZV07XG59O1xuXG5Td2FnZ2VyQXV0aG9yaXphdGlvbnMucHJvdG90eXBlLmFwcGx5ID0gZnVuY3Rpb24gKG9iaiwgYXV0aG9yaXphdGlvbnMpIHtcbiAgdmFyIHN0YXR1cyA9IG51bGw7XG4gIHZhciBrZXksIG5hbWUsIHZhbHVlLCByZXN1bHQ7XG5cbiAgLy8gaWYgdGhlICdhdXRob3JpemF0aW9ucycga2V5IGlzIHVuZGVmaW5lZCwgb3IgaGFzIGFuIGVtcHR5IGFycmF5LCBhZGQgYWxsIGtleXNcbiAgaWYgKHR5cGVvZiBhdXRob3JpemF0aW9ucyA9PT0gJ3VuZGVmaW5lZCcgfHwgT2JqZWN0LmtleXMoYXV0aG9yaXphdGlvbnMpLmxlbmd0aCA9PT0gMCkge1xuICAgIGZvciAoa2V5IGluIHRoaXMuYXV0aHopIHtcbiAgICAgIHZhbHVlID0gdGhpcy5hdXRoeltrZXldO1xuICAgICAgcmVzdWx0ID0gdmFsdWUuYXBwbHkob2JqLCBhdXRob3JpemF0aW9ucyk7XG5cbiAgICAgIGlmIChyZXN1bHQgPT09IHRydWUpIHtcbiAgICAgICAgc3RhdHVzID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gMi4wIHN1cHBvcnRcbiAgICBpZiAoQXJyYXkuaXNBcnJheShhdXRob3JpemF0aW9ucykpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXV0aG9yaXphdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF1dGggPSBhdXRob3JpemF0aW9uc1tpXTtcblxuICAgICAgICBmb3IgKG5hbWUgaW4gYXV0aCkge1xuICAgICAgICAgIGZvciAoa2V5IGluIHRoaXMuYXV0aHopIHtcbiAgICAgICAgICAgIGlmIChrZXkgPT09IG5hbWUpIHtcbiAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLmF1dGh6W2tleV07XG4gICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlLmFwcGx5KG9iaiwgYXV0aG9yaXphdGlvbnMpO1xuXG4gICAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBzdGF0dXMgPSB0cnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIDEuMiBzdXBwb3J0XG4gICAgICBmb3IgKG5hbWUgaW4gYXV0aG9yaXphdGlvbnMpIHtcbiAgICAgICAgZm9yIChrZXkgaW4gdGhpcy5hdXRoeikge1xuICAgICAgICAgIGlmIChrZXkgPT09IG5hbWUpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdGhpcy5hdXRoeltrZXldO1xuICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUuYXBwbHkob2JqLCBhdXRob3JpemF0aW9ucyk7XG5cbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgc3RhdHVzID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gc3RhdHVzO1xufTtcblxuLyoqXG4gKiBBcGlLZXlBdXRob3JpemF0aW9uIGFsbG93cyBhIHF1ZXJ5IHBhcmFtIG9yIGhlYWRlciB0byBiZSBpbmplY3RlZFxuICovXG52YXIgQXBpS2V5QXV0aG9yaXphdGlvbiA9IG1vZHVsZS5leHBvcnRzLkFwaUtleUF1dGhvcml6YXRpb24gPSBmdW5jdGlvbiAobmFtZSwgdmFsdWUsIHR5cGUpIHtcbiAgdGhpcy5uYW1lID0gbmFtZTtcbiAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB0aGlzLnR5cGUgPSB0eXBlO1xufTtcblxuQXBpS2V5QXV0aG9yaXphdGlvbi5wcm90b3R5cGUuYXBwbHkgPSBmdW5jdGlvbiAob2JqKSB7XG4gIGlmICh0aGlzLnR5cGUgPT09ICdxdWVyeScpIHtcbiAgICBpZiAob2JqLnVybC5pbmRleE9mKCc/JykgPiAwKSB7XG4gICAgICBvYmoudXJsID0gb2JqLnVybCArICcmJyArIHRoaXMubmFtZSArICc9JyArIHRoaXMudmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9iai51cmwgPSBvYmoudXJsICsgJz8nICsgdGhpcy5uYW1lICsgJz0nICsgdGhpcy52YWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIGlmICh0aGlzLnR5cGUgPT09ICdoZWFkZXInKSB7XG4gICAgb2JqLmhlYWRlcnNbdGhpcy5uYW1lXSA9IHRoaXMudmFsdWU7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufTtcblxudmFyIENvb2tpZUF1dGhvcml6YXRpb24gPSBtb2R1bGUuZXhwb3J0cy5Db29raWVBdXRob3JpemF0aW9uID0gZnVuY3Rpb24gKGNvb2tpZSkge1xuICB0aGlzLmNvb2tpZSA9IGNvb2tpZTtcbn07XG5cbkNvb2tpZUF1dGhvcml6YXRpb24ucHJvdG90eXBlLmFwcGx5ID0gZnVuY3Rpb24gKG9iaikge1xuICBvYmouY29va2llSmFyID0gb2JqLmNvb2tpZUphciB8fCBuZXcgQ29va2llSmFyKCk7XG4gIG9iai5jb29raWVKYXIuc2V0Q29va2llKHRoaXMuY29va2llKTtcblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbi8qKlxuICogUGFzc3dvcmQgQXV0aG9yaXphdGlvbiBpcyBhIGJhc2ljIGF1dGggaW1wbGVtZW50YXRpb25cbiAqL1xudmFyIFBhc3N3b3JkQXV0aG9yaXphdGlvbiA9IG1vZHVsZS5leHBvcnRzLlBhc3N3b3JkQXV0aG9yaXphdGlvbiA9IGZ1bmN0aW9uIChuYW1lLCB1c2VybmFtZSwgcGFzc3dvcmQpIHtcbiAgdGhpcy5uYW1lID0gbmFtZTtcbiAgdGhpcy51c2VybmFtZSA9IHVzZXJuYW1lO1xuICB0aGlzLnBhc3N3b3JkID0gcGFzc3dvcmQ7XG59O1xuXG5QYXNzd29yZEF1dGhvcml6YXRpb24ucHJvdG90eXBlLmFwcGx5ID0gZnVuY3Rpb24gKG9iaikge1xuICBvYmouaGVhZGVycy5BdXRob3JpemF0aW9uID0gJ0Jhc2ljICcgKyBidG9hKHRoaXMudXNlcm5hbWUgKyAnOicgKyB0aGlzLnBhc3N3b3JkKTtcblxuICByZXR1cm4gdHJ1ZTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi9oZWxwZXJzJyk7XG52YXIgU3dhZ2dlckNsaWVudCA9IHJlcXVpcmUoJy4vY2xpZW50Jyk7XG52YXIgU3dhZ2dlckh0dHAgPSByZXF1aXJlKCcuL2h0dHAnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBTd2FnZ2VyQ2xpZW50O1xuXG4vKipcbiAqIGFsbG93cyBvdmVycmlkZSBvZiB0aGUgZGVmYXVsdCB2YWx1ZSBiYXNlZCBvbiB0aGUgcGFyYW1ldGVyIGJlaW5nXG4gKiBzdXBwbGllZFxuICoqL1xudmFyIGFwcGx5UGFyYW1ldGVyTWFjcm8gPSBmdW5jdGlvbiAob3BlcmF0aW9uLCBwYXJhbWV0ZXIpIHtcbiAgaWYgKG9wZXJhdGlvbi5hcGkucGFyYW1ldGVyTWFjcm8pIHtcbiAgICByZXR1cm4gb3BlcmF0aW9uLmFwaS5wYXJhbWV0ZXJNYWNybyhvcGVyYXRpb24sIHBhcmFtZXRlcik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHBhcmFtZXRlci5kZWZhdWx0VmFsdWU7XG4gIH1cbn07XG5cbi8qKlxuICogYWxsb3dzIG92ZXJyaWRpbmcgdGhlIGRlZmF1bHQgdmFsdWUgb2YgYW4gbW9kZWwgcHJvcGVydHlcbiAqKi9cbnZhciBhcHBseU1vZGVsUHJvcGVydHlNYWNybyA9IGZ1bmN0aW9uIChtb2RlbCwgcHJvcGVydHkpIHtcbiAgaWYgKG1vZGVsLmFwaS5tb2RlbFByb3BlcnR5TWFjcm8pIHtcbiAgICByZXR1cm4gbW9kZWwuYXBpLm1vZGVsUHJvcGVydHlNYWNybyhtb2RlbCwgcHJvcGVydHkpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBwcm9wZXJ0eS5kZWZhdWx0VmFsdWU7XG4gIH1cbn07XG5cbnZhciBTd2FnZ2VyTW9kZWxQcm9wZXJ0eSA9IGZ1bmN0aW9uIChuYW1lLCBvYmosIG1vZGVsKSB7XG4gIHRoaXMubmFtZSA9IG5hbWU7XG4gIHRoaXMuZGF0YVR5cGUgPSBvYmoudHlwZSB8fCBvYmouZGF0YVR5cGUgfHwgb2JqLiRyZWY7XG4gIHRoaXMuaXNDb2xsZWN0aW9uID0gdGhpcy5kYXRhVHlwZSAmJiAodGhpcy5kYXRhVHlwZS50b0xvd2VyQ2FzZSgpID09PSAnYXJyYXknIHx8IHRoaXMuZGF0YVR5cGUudG9Mb3dlckNhc2UoKSA9PT0gJ2xpc3QnIHx8IHRoaXMuZGF0YVR5cGUudG9Mb3dlckNhc2UoKSA9PT0gJ3NldCcpO1xuICB0aGlzLmRlc2NyID0gb2JqLmRlc2NyaXB0aW9uO1xuICB0aGlzLnJlcXVpcmVkID0gb2JqLnJlcXVpcmVkO1xuICB0aGlzLmRlZmF1bHRWYWx1ZSA9IGFwcGx5TW9kZWxQcm9wZXJ0eU1hY3JvKG1vZGVsLCBvYmopO1xuXG4gIGlmIChvYmouaXRlbXMpIHtcbiAgICBpZiAob2JqLml0ZW1zLnR5cGUpIHtcbiAgICAgIHRoaXMucmVmRGF0YVR5cGUgPSBvYmouaXRlbXMudHlwZTtcbiAgICB9XG5cbiAgICBpZiAob2JqLml0ZW1zLiRyZWYpIHtcbiAgICAgIHRoaXMucmVmRGF0YVR5cGUgPSBvYmouaXRlbXMuJHJlZjtcbiAgICB9XG4gIH1cblxuICB0aGlzLmRhdGFUeXBlV2l0aFJlZiA9IHRoaXMucmVmRGF0YVR5cGUgPyAodGhpcy5kYXRhVHlwZSArICdbJyArIHRoaXMucmVmRGF0YVR5cGUgKyAnXScpIDogdGhpcy5kYXRhVHlwZTtcblxuICBpZiAob2JqLmFsbG93YWJsZVZhbHVlcykge1xuICAgIHRoaXMudmFsdWVUeXBlID0gb2JqLmFsbG93YWJsZVZhbHVlcy52YWx1ZVR5cGU7XG4gICAgdGhpcy52YWx1ZXMgPSBvYmouYWxsb3dhYmxlVmFsdWVzLnZhbHVlcztcblxuICAgIGlmICh0aGlzLnZhbHVlcykge1xuICAgICAgdGhpcy52YWx1ZXNTdHJpbmcgPSAnXFwnJyArIHRoaXMudmFsdWVzLmpvaW4oJ1xcJyBvciBcXCcnKSArICdcXCcnO1xuICAgIH1cbiAgfVxuXG4gIGlmIChvYmpbJ2VudW0nXSkge1xuICAgIHRoaXMudmFsdWVUeXBlID0gJ3N0cmluZyc7XG4gICAgdGhpcy52YWx1ZXMgPSBvYmpbJ2VudW0nXTtcblxuICAgIGlmICh0aGlzLnZhbHVlcykge1xuICAgICAgdGhpcy52YWx1ZVN0cmluZyA9ICdcXCcnICsgdGhpcy52YWx1ZXMuam9pbignXFwnIG9yIFxcJycpICsgJ1xcJyc7XG4gICAgfVxuICB9XG59O1xuXG52YXIgU3dhZ2dlck1vZGVsID0gZnVuY3Rpb24gKG1vZGVsTmFtZSwgb2JqLCBhcGkpIHtcbiAgdGhpcy5hcGkgPSBhcGk7XG4gIHRoaXMubmFtZSA9IHR5cGVvZiBvYmouaWQgIT09ICd1bmRlZmluZWQnID8gb2JqLmlkIDogbW9kZWxOYW1lO1xuICB0aGlzLnByb3BlcnRpZXMgPSBbXTtcbiAgdGhpcy5zYW1wbGVNb2RlbHMgPSBhcGkuc2FtcGxlTW9kZWxzO1xuXG4gIHZhciBwcm9wZXJ0eU5hbWU7XG5cbiAgZm9yIChwcm9wZXJ0eU5hbWUgaW4gb2JqLnByb3BlcnRpZXMpIHtcbiAgICBpZiAob2JqLnJlcXVpcmVkKSB7XG4gICAgICB2YXIgdmFsdWU7XG5cbiAgICAgIGZvciAodmFsdWUgaW4gb2JqLnJlcXVpcmVkKSB7XG4gICAgICAgIGlmIChwcm9wZXJ0eU5hbWUgPT09IG9iai5yZXF1aXJlZFt2YWx1ZV0pIHtcbiAgICAgICAgICBvYmoucHJvcGVydGllc1twcm9wZXJ0eU5hbWVdLnJlcXVpcmVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBwcm9wID0gbmV3IFN3YWdnZXJNb2RlbFByb3BlcnR5KHByb3BlcnR5TmFtZSwgb2JqLnByb3BlcnRpZXNbcHJvcGVydHlOYW1lXSwgdGhpcyk7XG5cbiAgICB0aGlzLnByb3BlcnRpZXMucHVzaChwcm9wKTtcbiAgfVxufTtcblxudmFyIFN3YWdnZXJPcGVyYXRpb24gPSBmdW5jdGlvbiAobmlja25hbWUsIHBhdGgsIG1ldGhvZCwgcGFyYW1ldGVycywgc3VtbWFyeSwgbm90ZXMsIHR5cGUsIHJlc3BvbnNlTWVzc2FnZXMsIHJlc291cmNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3VtZXMsIHByb2R1Y2VzLCBhdXRob3JpemF0aW9ucywgZGVwcmVjYXRlZCwgY2xpZW50QXV0aG9yaXphdGlvbnMpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgZXJyb3JzID0gW107XG5cbiAgdGhpcy5jbGllbnRBdXRob3JpemF0aW9ucyA9IGNsaWVudEF1dGhvcml6YXRpb25zO1xuICB0aGlzLm5pY2tuYW1lID0gKG5pY2tuYW1lIHx8IGVycm9ycy5wdXNoKCdTd2FnZ2VyT3BlcmF0aW9ucyBtdXN0IGhhdmUgYSBuaWNrbmFtZS4nKSk7XG4gIHRoaXMucGF0aCA9IChwYXRoIHx8IGVycm9ycy5wdXNoKCdTd2FnZ2VyT3BlcmF0aW9uICcgKyBuaWNrbmFtZSArICcgaXMgbWlzc2luZyBwYXRoLicpKTtcbiAgdGhpcy5tZXRob2QgPSAobWV0aG9kIHx8IGVycm9ycy5wdXNoKCdTd2FnZ2VyT3BlcmF0aW9uICcgKyBuaWNrbmFtZSArICcgaXMgbWlzc2luZyBtZXRob2QuJykpO1xuICB0aGlzLnBhcmFtZXRlcnMgPSBwYXJhbWV0ZXJzID8gcGFyYW1ldGVycyA6IFtdO1xuICB0aGlzLnN1bW1hcnkgPSBzdW1tYXJ5O1xuICB0aGlzLm5vdGVzID0gbm90ZXM7XG4gIHRoaXMudHlwZSA9IHR5cGU7XG4gIHRoaXMucmVzcG9uc2VNZXNzYWdlcyA9IChyZXNwb25zZU1lc3NhZ2VzIHx8IFtdKTtcbiAgdGhpcy5yZXNvdXJjZSA9IChyZXNvdXJjZSB8fCBlcnJvcnMucHVzaCgnUmVzb3VyY2UgaXMgcmVxdWlyZWQnKSk7XG4gIHRoaXMuY29uc3VtZXMgPSBjb25zdW1lcztcbiAgdGhpcy5wcm9kdWNlcyA9IHByb2R1Y2VzO1xuICB0aGlzLmF1dGhvcml6YXRpb25zID0gdHlwZW9mIGF1dGhvcml6YXRpb25zICE9PSAndW5kZWZpbmVkJyA/IGF1dGhvcml6YXRpb25zIDogcmVzb3VyY2UuYXV0aG9yaXphdGlvbnM7XG4gIHRoaXMuZGVwcmVjYXRlZCA9IGRlcHJlY2F0ZWQ7XG4gIHRoaXMuZG8gPSBoZWxwZXJzLl9fYmluZCh0aGlzLmRvLCB0aGlzKTtcbiAgdGhpcy5hcGkgPSB0aGlzLnJlc291cmNlLmFwaTtcblxuICBpZiAodHlwZW9mIHRoaXMuZGVwcmVjYXRlZCA9PT0gJ3N0cmluZycpIHtcbiAgICBzd2l0Y2godGhpcy5kZXByZWNhdGVkLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgIGNhc2UgJ3RydWUnOiBjYXNlICd5ZXMnOiBjYXNlICcxJzoge1xuICAgICAgICB0aGlzLmRlcHJlY2F0ZWQgPSB0cnVlO1xuXG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnZmFsc2UnOiBjYXNlICdubyc6IGNhc2UgJzAnOiBjYXNlIG51bGw6IHtcbiAgICAgICAgdGhpcy5kZXByZWNhdGVkID0gZmFsc2U7XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OiB0aGlzLmRlcHJlY2F0ZWQgPSBCb29sZWFuKHRoaXMuZGVwcmVjYXRlZCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgY29uc29sZS5lcnJvcignU3dhZ2dlck9wZXJhdGlvbiBlcnJvcnMnLCBlcnJvcnMsIGFyZ3VtZW50cyk7XG5cbiAgICB0aGlzLnJlc291cmNlLmFwaS5mYWlsKGVycm9ycyk7XG4gIH1cblxuICB0aGlzLnBhdGggPSB0aGlzLnBhdGgucmVwbGFjZSgne2Zvcm1hdH0nLCAnanNvbicpO1xuICB0aGlzLm1ldGhvZCA9IHRoaXMubWV0aG9kLnRvTG93ZXJDYXNlKCk7XG4gIHRoaXMuaXNHZXRNZXRob2QgPSB0aGlzLm1ldGhvZCA9PT0gJ2dldCc7XG5cbiAgdmFyIGksIGosIHY7XG5cbiAgdGhpcy5yZXNvdXJjZU5hbWUgPSB0aGlzLnJlc291cmNlLm5hbWU7XG5cbiAgaWYgKHR5cGVvZiB0aGlzLnR5cGUgIT09ICd1bmRlZmluZWQnICYmIHRoaXMudHlwZSA9PT0gJ3ZvaWQnKSB7XG4gICAgdGhpcy50eXBlID0gbnVsbDtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLnJlc3BvbnNlQ2xhc3NTaWduYXR1cmUgPSB0aGlzLmdldFNpZ25hdHVyZSh0aGlzLnR5cGUsIHRoaXMucmVzb3VyY2UubW9kZWxzKTtcbiAgICB0aGlzLnJlc3BvbnNlU2FtcGxlSlNPTiA9IHRoaXMuZ2V0U2FtcGxlSlNPTih0aGlzLnR5cGUsIHRoaXMucmVzb3VyY2UubW9kZWxzKTtcbiAgfVxuXG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnBhcmFtZXRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFyYW0gPSB0aGlzLnBhcmFtZXRlcnNbaV07XG5cbiAgICBwYXJhbS5uYW1lID0gcGFyYW0ubmFtZSB8fCBwYXJhbS50eXBlIHx8IHBhcmFtLmRhdGFUeXBlOyAvLyBtaWdodCB0YWtlIHRoaXMgYXdheVxuICAgIHR5cGUgPSBwYXJhbS50eXBlIHx8IHBhcmFtLmRhdGFUeXBlOyAvLyBmb3IgMS4xIGNvbXBhdGliaWxpdHlcblxuICAgIGlmICh0eXBlID09PSAnYXJyYXknKSB7XG4gICAgICB0eXBlID0gJ2FycmF5WycgKyAocGFyYW0uaXRlbXMuJHJlZiA/IHBhcmFtLml0ZW1zLiRyZWYgOiBwYXJhbS5pdGVtcy50eXBlKSArICddJztcbiAgICB9XG5cbiAgICBwYXJhbS50eXBlID0gdHlwZTtcblxuICAgIGlmICh0eXBlICYmIHR5cGUudG9Mb3dlckNhc2UoKSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICBwYXJhbS5hbGxvd2FibGVWYWx1ZXMgPSB7fTtcbiAgICAgIHBhcmFtLmFsbG93YWJsZVZhbHVlcy52YWx1ZXMgPSBbJ3RydWUnLCAnZmFsc2UnXTtcbiAgICB9XG5cbiAgICBwYXJhbS5zaWduYXR1cmUgPSB0aGlzLmdldFNpZ25hdHVyZSh0eXBlLCB0aGlzLnJlc291cmNlLm1vZGVscyk7XG4gICAgcGFyYW0uc2FtcGxlSlNPTiA9IHRoaXMuZ2V0U2FtcGxlSlNPTih0eXBlLCB0aGlzLnJlc291cmNlLm1vZGVscyk7XG5cbiAgICB2YXIgZW51bVZhbHVlID0gcGFyYW1bJ2VudW0nXTtcblxuICAgIGlmICh0eXBlb2YgZW51bVZhbHVlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcGFyYW0uaXNMaXN0ID0gdHJ1ZTtcbiAgICAgIHBhcmFtLmFsbG93YWJsZVZhbHVlcyA9IHt9O1xuICAgICAgcGFyYW0uYWxsb3dhYmxlVmFsdWVzLmRlc2NyaXB0aXZlVmFsdWVzID0gW107XG5cbiAgICAgIGZvciAoaiA9IDA7IGogPCBlbnVtVmFsdWUubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdiA9IGVudW1WYWx1ZVtqXTtcblxuICAgICAgICBpZiAocGFyYW0uZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgcGFyYW0uYWxsb3dhYmxlVmFsdWVzLmRlc2NyaXB0aXZlVmFsdWVzLnB1c2goe1xuICAgICAgICAgICAgdmFsdWU6IFN0cmluZyh2KSxcbiAgICAgICAgICAgIGlzRGVmYXVsdDogKHYgPT09IHBhcmFtLmRlZmF1bHRWYWx1ZSlcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwYXJhbS5hbGxvd2FibGVWYWx1ZXMuZGVzY3JpcHRpdmVWYWx1ZXMucHVzaCh7XG4gICAgICAgICAgICB2YWx1ZTogU3RyaW5nKHYpLFxuICAgICAgICAgICAgaXNEZWZhdWx0OiBmYWxzZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChwYXJhbS5hbGxvd2FibGVWYWx1ZXMpIHtcbiAgICAgIGlmIChwYXJhbS5hbGxvd2FibGVWYWx1ZXMudmFsdWVUeXBlID09PSAnUkFOR0UnKSB7XG4gICAgICAgIHBhcmFtLmlzUmFuZ2UgPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyYW0uaXNMaXN0ID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtLmFsbG93YWJsZVZhbHVlcykge1xuICAgICAgICBwYXJhbS5hbGxvd2FibGVWYWx1ZXMuZGVzY3JpcHRpdmVWYWx1ZXMgPSBbXTtcblxuICAgICAgICBpZiAocGFyYW0uYWxsb3dhYmxlVmFsdWVzLnZhbHVlcykge1xuICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBwYXJhbS5hbGxvd2FibGVWYWx1ZXMudmFsdWVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2ID0gcGFyYW0uYWxsb3dhYmxlVmFsdWVzLnZhbHVlc1tqXTtcblxuICAgICAgICAgICAgaWYgKHBhcmFtLmRlZmF1bHRWYWx1ZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICBwYXJhbS5hbGxvd2FibGVWYWx1ZXMuZGVzY3JpcHRpdmVWYWx1ZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgdmFsdWU6IFN0cmluZyh2KSxcbiAgICAgICAgICAgICAgICBpc0RlZmF1bHQ6ICh2ID09PSBwYXJhbS5kZWZhdWx0VmFsdWUpXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGFyYW0uYWxsb3dhYmxlVmFsdWVzLmRlc2NyaXB0aXZlVmFsdWVzLnB1c2goe1xuICAgICAgICAgICAgICAgIHZhbHVlOiBTdHJpbmcodiksXG4gICAgICAgICAgICAgICAgaXNEZWZhdWx0OiBmYWxzZVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBwYXJhbS5kZWZhdWx0VmFsdWUgPSBhcHBseVBhcmFtZXRlck1hY3JvKHRoaXMsIHBhcmFtKTtcbiAgfVxuXG4gIHZhciBkZWZhdWx0U3VjY2Vzc0NhbGxiYWNrID0gdGhpcy5yZXNvdXJjZS5hcGkuZGVmYXVsdFN1Y2Nlc3NDYWxsYmFjayB8fCBudWxsO1xuICB2YXIgZGVmYXVsdEVycm9yQ2FsbGJhY2sgPSB0aGlzLnJlc291cmNlLmFwaS5kZWZhdWx0RXJyb3JDYWxsYmFjayB8fCBudWxsO1xuXG4gIHRoaXMucmVzb3VyY2VbdGhpcy5uaWNrbmFtZV0gPSBmdW5jdGlvbiAoYXJncywgb3B0cywgY2FsbGJhY2ssIGVycm9yKSB7XG4gICAgdmFyIGFyZzEsIGFyZzIsIGFyZzMsIGFyZzQ7XG5cbiAgICBpZiAodHlwZW9mIGFyZ3MgPT09ICdmdW5jdGlvbicpIHsgIC8vIHJpZ2h0IHNoaWZ0IDNcbiAgICAgIGFyZzEgPSB7fTsgYXJnMiA9IHt9OyBhcmczID0gYXJnczsgYXJnNCA9IG9wdHM7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgYXJncyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG9wdHMgPT09ICdmdW5jdGlvbicpIHsgLy8gcmlnaHQgc2hpZnQgMlxuICAgICAgYXJnMSA9IGFyZ3M7IGFyZzIgPSB7fTsgYXJnMyA9IG9wdHM7IGFyZzQgPSBjYWxsYmFjaztcbiAgICB9IGVsc2Uge1xuICAgICAgYXJnMSA9IGFyZ3M7IGFyZzIgPSBvcHRzOyBhcmczID0gY2FsbGJhY2s7IGFyZzQgPSBlcnJvcjtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZlsnZG8nXShhcmcxIHx8IHt9LCBhcmcyIHx8IHt9LCBhcmczIHx8IGRlZmF1bHRTdWNjZXNzQ2FsbGJhY2ssIGFyZzQgfHwgZGVmYXVsdEVycm9yQ2FsbGJhY2spO1xuICB9O1xuXG4gIHRoaXMucmVzb3VyY2VbdGhpcy5uaWNrbmFtZV0uaGVscCA9IGZ1bmN0aW9uIChkb250UHJpbnQpIHtcbiAgICByZXR1cm4gc2VsZi5oZWxwKGRvbnRQcmludCk7XG4gIH07XG4gIHRoaXMucmVzb3VyY2VbdGhpcy5uaWNrbmFtZV0uYXNDdXJsID0gZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICByZXR1cm4gc2VsZi5hc0N1cmwoYXJncyk7XG4gIH07XG59O1xuXG52YXIgU3dhZ2dlclJlcXVlc3QgPSBmdW5jdGlvbiAodHlwZSwgdXJsLCBwYXJhbXMsIG9wdHMsIHN1Y2Nlc3NDYWxsYmFjaywgZXJyb3JDYWxsYmFjaywgb3BlcmF0aW9uLCBleGVjdXRpb24pIHtcbiAgdmFyIF90aGlzID0gdGhpcztcbiAgdmFyIGVycm9ycyA9IFtdO1xuXG4gIHRoaXMudXNlSlF1ZXJ5ID0gKHR5cGVvZiBvcGVyYXRpb24ucmVzb3VyY2UudXNlSlF1ZXJ5ICE9PSAndW5kZWZpbmVkJyA/IG9wZXJhdGlvbi5yZXNvdXJjZS51c2VKUXVlcnkgOiBudWxsKTtcbiAgdGhpcy50eXBlID0gKHR5cGUgfHwgZXJyb3JzLnB1c2goJ1N3YWdnZXJSZXF1ZXN0IHR5cGUgaXMgcmVxdWlyZWQgKGdldC9wb3N0L3B1dC9kZWxldGUvcGF0Y2gvb3B0aW9ucykuJykpO1xuICB0aGlzLnVybCA9ICh1cmwgfHwgZXJyb3JzLnB1c2goJ1N3YWdnZXJSZXF1ZXN0IHVybCBpcyByZXF1aXJlZC4nKSk7XG4gIHRoaXMucGFyYW1zID0gcGFyYW1zO1xuICB0aGlzLm9wdHMgPSBvcHRzO1xuICB0aGlzLnN1Y2Nlc3NDYWxsYmFjayA9IChzdWNjZXNzQ2FsbGJhY2sgfHwgZXJyb3JzLnB1c2goJ1N3YWdnZXJSZXF1ZXN0IHN1Y2Nlc3NDYWxsYmFjayBpcyByZXF1aXJlZC4nKSk7XG4gIHRoaXMuZXJyb3JDYWxsYmFjayA9IChlcnJvckNhbGxiYWNrIHx8IGVycm9ycy5wdXNoKCdTd2FnZ2VyUmVxdWVzdCBlcnJvciBjYWxsYmFjayBpcyByZXF1aXJlZC4nKSk7XG4gIHRoaXMub3BlcmF0aW9uID0gKG9wZXJhdGlvbiB8fCBlcnJvcnMucHVzaCgnU3dhZ2dlclJlcXVlc3Qgb3BlcmF0aW9uIGlzIHJlcXVpcmVkLicpKTtcbiAgdGhpcy5leGVjdXRpb24gPSBleGVjdXRpb247XG4gIHRoaXMuaGVhZGVycyA9IChwYXJhbXMuaGVhZGVycyB8fCB7fSk7XG5cbiAgaWYgKGVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgdGhyb3cgZXJyb3JzO1xuICB9XG5cbiAgdGhpcy50eXBlID0gdGhpcy50eXBlLnRvVXBwZXJDYXNlKCk7XG5cbiAgLy8gc2V0IHJlcXVlc3QsIHJlc3BvbnNlIGNvbnRlbnQgdHlwZSBoZWFkZXJzXG4gIHZhciBoZWFkZXJzID0gdGhpcy5zZXRIZWFkZXJzKHBhcmFtcywgb3B0cywgdGhpcy5vcGVyYXRpb24pO1xuICB2YXIgYm9keSA9IHBhcmFtcy5ib2R5O1xuXG4gIC8vIGVuY29kZSB0aGUgYm9keSBmb3IgZm9ybSBzdWJtaXRzXG4gIGlmIChoZWFkZXJzWydDb250ZW50LVR5cGUnXSkge1xuICAgIHZhciBrZXksIHZhbHVlLCB2YWx1ZXMgPSB7fSwgaTtcbiAgICB2YXIgb3BlcmF0aW9uUGFyYW1zID0gdGhpcy5vcGVyYXRpb24ucGFyYW1ldGVycztcblxuICAgIGZvciAoaSA9IDA7IGkgPCBvcGVyYXRpb25QYXJhbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBwYXJhbSA9IG9wZXJhdGlvblBhcmFtc1tpXTtcblxuICAgICAgaWYgKHBhcmFtLnBhcmFtVHlwZSA9PT0gJ2Zvcm0nKSB7XG4gICAgICAgIHZhbHVlc1twYXJhbS5uYW1lXSA9IHBhcmFtO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChoZWFkZXJzWydDb250ZW50LVR5cGUnXS5pbmRleE9mKCdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnKSA9PT0gMCkge1xuICAgICAgdmFyIGVuY29kZWQgPSAnJztcblxuICAgICAgZm9yIChrZXkgaW4gdmFsdWVzKSB7XG4gICAgICAgIHZhbHVlID0gdGhpcy5wYXJhbXNba2V5XTtcblxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIGlmIChlbmNvZGVkICE9PSAnJykge1xuICAgICAgICAgICAgZW5jb2RlZCArPSAnJic7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZW5jb2RlZCArPSBlbmNvZGVVUklDb21wb25lbnQoa2V5KSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgYm9keSA9IGVuY29kZWQ7XG4gICAgfSBlbHNlIGlmIChoZWFkZXJzWydDb250ZW50LVR5cGUnXS5pbmRleE9mKCdtdWx0aXBhcnQvZm9ybS1kYXRhJykgPT09IDApIHtcbiAgICAgIC8vIGVuY29kZSB0aGUgYm9keSBmb3IgZm9ybSBzdWJtaXRzXG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgdmFyIGJvdW5kYXJ5ID0gJy0tLS1Td2FnZ2VyRm9ybUJvdW5kYXJ5JyArIERhdGUubm93KCk7XG5cbiAgICAgIGZvciAoa2V5IGluIHZhbHVlcykge1xuICAgICAgICB2YWx1ZSA9IHRoaXMucGFyYW1zW2tleV07XG5cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBkYXRhICs9ICctLScgKyBib3VuZGFyeSArICdcXG4nO1xuICAgICAgICAgIGRhdGEgKz0gJ0NvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT1cIicgKyBrZXkgKyAnXCInO1xuICAgICAgICAgIGRhdGEgKz0gJ1xcblxcbic7XG4gICAgICAgICAgZGF0YSArPSB2YWx1ZSArICdcXG4nO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGRhdGEgKz0gJy0tJyArIGJvdW5kYXJ5ICsgJy0tXFxuJztcbiAgICAgIGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddID0gJ211bHRpcGFydC9mb3JtLWRhdGE7IGJvdW5kYXJ5PScgKyBib3VuZGFyeTtcbiAgICAgIGJvZHkgPSBkYXRhO1xuICAgIH1cbiAgfVxuXG4gIHZhciBvYmo7XG5cbiAgaWYgKCEoKHRoaXMuaGVhZGVycykgJiYgKHRoaXMuaGVhZGVycy5tb2NrKSkpIHtcbiAgICBvYmogPSB7XG4gICAgICB1cmw6IHRoaXMudXJsLFxuICAgICAgbWV0aG9kOiB0aGlzLnR5cGUsXG4gICAgICBoZWFkZXJzOiBoZWFkZXJzLFxuICAgICAgYm9keTogYm9keSxcbiAgICAgIHVzZUpRdWVyeTogdGhpcy51c2VKUXVlcnksXG4gICAgICBvbjoge1xuICAgICAgICBlcnJvcjogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzLmVycm9yQ2FsbGJhY2socmVzcG9uc2UsIF90aGlzLm9wdHMucGFyZW50KTtcbiAgICAgICAgfSxcbiAgICAgICAgcmVkaXJlY3Q6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgIHJldHVybiBfdGhpcy5zdWNjZXNzQ2FsbGJhY2socmVzcG9uc2UsIF90aGlzLm9wdHMucGFyZW50KTtcbiAgICAgICAgfSxcbiAgICAgICAgMzA3OiBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICByZXR1cm4gX3RoaXMuc3VjY2Vzc0NhbGxiYWNrKHJlc3BvbnNlLCBfdGhpcy5vcHRzLnBhcmVudCk7XG4gICAgICAgIH0sXG4gICAgICAgIHJlc3BvbnNlOiBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICByZXR1cm4gX3RoaXMuc3VjY2Vzc0NhbGxiYWNrKHJlc3BvbnNlLCBfdGhpcy5vcHRzLnBhcmVudCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFyIHN0YXR1cyA9IGZhbHNlO1xuXG4gICAgaWYgKHRoaXMub3BlcmF0aW9uLnJlc291cmNlICYmIHRoaXMub3BlcmF0aW9uLnJlc291cmNlLmFwaSAmJiB0aGlzLm9wZXJhdGlvbi5yZXNvdXJjZS5hcGkuY2xpZW50QXV0aG9yaXphdGlvbnMpIHtcbiAgICAgIC8vIEdldCB0aGUgY2xpZW50IGF1dGhvcml6YXRpb25zIGZyb20gdGhlIHJlc291cmNlIGRlY2xhcmF0aW9uXG4gICAgICBzdGF0dXMgPSB0aGlzLm9wZXJhdGlvbi5yZXNvdXJjZS5hcGkuY2xpZW50QXV0aG9yaXphdGlvbnMuYXBwbHkob2JqLCB0aGlzLm9wZXJhdGlvbi5hdXRob3JpemF0aW9ucyk7XG4gICAgfVxuXG4gICAgaWYgKCFvcHRzLm1vY2spIHtcbiAgICAgIGlmIChzdGF0dXMgIT09IGZhbHNlKSB7XG4gICAgICAgIG5ldyBTd2FnZ2VySHR0cCgpLmV4ZWN1dGUob2JqKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9iai5jYW5jZWxlZCA9IHRydWU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBvYmo7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9iajtcbn07XG5cbnZhciBTd2FnZ2VyUmVzb3VyY2UgPSBmdW5jdGlvbiAocmVzb3VyY2VPYmosIGFwaSkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgdGhpcy5hcGkgPSBhcGk7XG4gIHRoaXMuc3dhZ2dlclJlcXVzdEhlYWRlcnMgPSBhcGkuc3dhZ2dlclJlcXVzdEhlYWRlcnM7XG4gIHRoaXMucGF0aCA9ICh0eXBlb2YgdGhpcy5hcGkucmVzb3VyY2VQYXRoID09PSAnc3RyaW5nJykgPyB0aGlzLmFwaS5yZXNvdXJjZVBhdGggOiByZXNvdXJjZU9iai5wYXRoO1xuICB0aGlzLmRlc2NyaXB0aW9uID0gcmVzb3VyY2VPYmouZGVzY3JpcHRpb247XG4gIHRoaXMuYXV0aG9yaXphdGlvbnMgPSAocmVzb3VyY2VPYmouYXV0aG9yaXphdGlvbnMgfHwge30pO1xuXG4gIHZhciBwYXJ0cyA9IHRoaXMucGF0aC5zcGxpdCgnLycpO1xuXG4gIHRoaXMubmFtZSA9IHBhcnRzW3BhcnRzLmxlbmd0aCAtIDFdLnJlcGxhY2UoJy57Zm9ybWF0fScsICcnKTtcbiAgdGhpcy5iYXNlUGF0aCA9IHRoaXMuYXBpLmJhc2VQYXRoO1xuICB0aGlzLm9wZXJhdGlvbnMgPSB7fTtcbiAgdGhpcy5vcGVyYXRpb25zQXJyYXkgPSBbXTtcbiAgdGhpcy5tb2RlbHNBcnJheSA9IFtdO1xuICB0aGlzLm1vZGVscyA9IGFwaS5tb2RlbHMgfHwge307XG4gIHRoaXMucmF3TW9kZWxzID0ge307XG4gIHRoaXMudXNlSlF1ZXJ5ID0gKHR5cGVvZiBhcGkudXNlSlF1ZXJ5ICE9PSAndW5kZWZpbmVkJykgPyBhcGkudXNlSlF1ZXJ5IDogbnVsbDtcblxuICBpZiAoKHJlc291cmNlT2JqLmFwaXMpICYmIHRoaXMuYXBpLnJlc291cmNlUGF0aCkge1xuICAgIHRoaXMuYWRkQXBpRGVjbGFyYXRpb24ocmVzb3VyY2VPYmopO1xuICB9IGVsc2Uge1xuICAgIGlmICh0eXBlb2YgdGhpcy5wYXRoID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5hcGkuZmFpbCgnU3dhZ2dlclJlc291cmNlcyBtdXN0IGhhdmUgYSBwYXRoLicpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnBhdGguc3Vic3RyaW5nKDAsIDQpID09PSAnaHR0cCcpIHtcbiAgICAgIHRoaXMudXJsID0gdGhpcy5wYXRoLnJlcGxhY2UoJ3tmb3JtYXR9JywgJ2pzb24nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy51cmwgPSB0aGlzLmFwaS5iYXNlUGF0aCArIHRoaXMucGF0aC5yZXBsYWNlKCd7Zm9ybWF0fScsICdqc29uJyk7XG4gICAgfVxuXG4gICAgdGhpcy5hcGkucHJvZ3Jlc3MoJ2ZldGNoaW5nIHJlc291cmNlICcgKyB0aGlzLm5hbWUgKyAnOiAnICsgdGhpcy51cmwpO1xuXG4gICAgdmFyIG9iaiA9IHtcbiAgICAgIHVybDogdGhpcy51cmwsXG4gICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgdXNlSlF1ZXJ5OiB0aGlzLnVzZUpRdWVyeSxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgYWNjZXB0OiB0aGlzLnN3YWdnZXJSZXF1c3RIZWFkZXJzXG4gICAgICB9LFxuICAgICAgb246IHtcbiAgICAgICAgcmVzcG9uc2U6IGZ1bmN0aW9uIChyZXNwKSB7XG4gICAgICAgICAgdmFyIHJlc3BvbnNlT2JqID0gcmVzcC5vYmogfHwgSlNPTi5wYXJzZShyZXNwLmRhdGEpO1xuICAgICAgICAgIHNlbGYuYXBpLnJlc291cmNlQ291bnQgKz0gMTtcbiAgICAgICAgICByZXR1cm4gc2VsZi5hZGRBcGlEZWNsYXJhdGlvbihyZXNwb25zZU9iaik7XG4gICAgICAgIH0sXG4gICAgICAgIGVycm9yOiBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICBzZWxmLmFwaS5yZXNvdXJjZUNvdW50ICs9IDE7XG4gICAgICAgICAgcmV0dXJuIHNlbGYuYXBpLmZhaWwoJ1VuYWJsZSB0byByZWFkIGFwaSBcXCcnICtcbiAgICAgICAgICBzZWxmLm5hbWUgKyAnXFwnIGZyb20gcGF0aCAnICsgc2VsZi51cmwgKyAnIChzZXJ2ZXIgcmV0dXJuZWQgJyArIHJlc3BvbnNlLnN0YXR1c1RleHQgKyAnKScpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIGFwaS5jbGllbnRBdXRob3JpemF0aW9ucy5hcHBseShvYmopO1xuXG4gICAgbmV3IFN3YWdnZXJIdHRwKCkuZXhlY3V0ZShvYmopO1xuICB9XG59O1xuXG5Td2FnZ2VyQ2xpZW50LnByb3RvdHlwZS5idWlsZEZyb20xXzJTcGVjID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7IC8vIGpzaGludCBpZ25vcmU6bGluZVxuICBpZiAocmVzcG9uc2UuYXBpVmVyc2lvbiAhPT0gbnVsbCkge1xuICAgIHRoaXMuYXBpVmVyc2lvbiA9IHJlc3BvbnNlLmFwaVZlcnNpb247XG4gIH1cblxuICB0aGlzLmFwaXMgPSB7fTtcbiAgdGhpcy5hcGlzQXJyYXkgPSBbXTtcbiAgdGhpcy5hdXRoU2NoZW1lcyA9IHJlc3BvbnNlLmF1dGhvcml6YXRpb25zO1xuICB0aGlzLmNvbnN1bWVzID0gcmVzcG9uc2UuY29uc3VtZXM7XG4gIHRoaXMuaW5mbyA9IHRoaXMuY29udmVydEluZm8ocmVzcG9uc2UuaW5mbyk7XG4gIHRoaXMucHJvZHVjZXMgPSByZXNwb25zZS5wcm9kdWNlcztcblxuICB2YXIgaXNBcGkgPSBmYWxzZSwgaSwgcmVzO1xuXG4gIGZvciAoaSA9IDA7IGkgPCByZXNwb25zZS5hcGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGFwaSA9IHJlc3BvbnNlLmFwaXNbaV07XG5cbiAgICBpZiAoYXBpLm9wZXJhdGlvbnMpIHtcbiAgICAgIHZhciBqO1xuXG4gICAgICBmb3IgKGogPSAwOyBqIDwgYXBpLm9wZXJhdGlvbnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaXNBcGkgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmIChyZXNwb25zZS5iYXNlUGF0aCkge1xuICAgIHRoaXMuYmFzZVBhdGggPSByZXNwb25zZS5iYXNlUGF0aDtcbiAgfSBlbHNlIGlmICh0aGlzLnVybC5pbmRleE9mKCc/JykgPiAwKSB7XG4gICAgdGhpcy5iYXNlUGF0aCA9IHRoaXMudXJsLnN1YnN0cmluZygwLCB0aGlzLnVybC5sYXN0SW5kZXhPZignPycpKTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLmJhc2VQYXRoID0gdGhpcy51cmw7XG4gIH1cblxuICBpZiAoaXNBcGkpIHtcbiAgICB2YXIgbmV3TmFtZSA9IHJlc3BvbnNlLnJlc291cmNlUGF0aC5yZXBsYWNlKC9cXC8vZywgJycpO1xuXG4gICAgdGhpcy5yZXNvdXJjZVBhdGggPSByZXNwb25zZS5yZXNvdXJjZVBhdGg7XG5cbiAgICByZXMgPSBuZXcgU3dhZ2dlclJlc291cmNlKHJlc3BvbnNlLCB0aGlzKTtcblxuICAgIHRoaXMuYXBpc1tuZXdOYW1lXSA9IHJlcztcbiAgICB0aGlzLmFwaXNBcnJheS5wdXNoKHJlcyk7XG4gICAgdGhpcy5maW5pc2goKTtcbiAgfSBlbHNlIHtcbiAgICB2YXIgaztcblxuICAgIHRoaXMuZXhwZWN0ZWRSZXNvdXJjZUNvdW50ID0gcmVzcG9uc2UuYXBpcy5sZW5ndGg7XG5cbiAgICBmb3IgKGsgPSAwOyBrIDwgcmVzcG9uc2UuYXBpcy5sZW5ndGg7IGsrKykge1xuICAgICAgdmFyIHJlc291cmNlID0gcmVzcG9uc2UuYXBpc1trXTtcblxuICAgICAgcmVzID0gbmV3IFN3YWdnZXJSZXNvdXJjZShyZXNvdXJjZSwgdGhpcyk7XG5cbiAgICAgIHRoaXMuYXBpc1tyZXMubmFtZV0gPSByZXM7XG4gICAgICB0aGlzLmFwaXNBcnJheS5wdXNoKHJlcyk7XG4gICAgfVxuICB9XG5cbiAgdGhpcy5pc1ZhbGlkID0gdHJ1ZTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLmZpbmlzaCA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKHR5cGVvZiB0aGlzLnN1Y2Nlc3MgPT09ICdmdW5jdGlvbicpIHtcbiAgICB0aGlzLmlzVmFsaWQgPSB0cnVlO1xuICAgIHRoaXMucmVhZHkgPSB0cnVlO1xuICAgIHRoaXMuaXNCdWlsdCA9IHRydWU7XG4gICAgdGhpcy5zZWxmUmVmbGVjdCgpO1xuICAgIHRoaXMuc3VjY2VzcygpO1xuICB9XG59O1xuXG5Td2FnZ2VyQ2xpZW50LnByb3RvdHlwZS5idWlsZEZyb20xXzFTcGVjID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7IC8vIGpzaGludCBpZ25vcmU6bGluZVxuICBoZWxwZXJzLmxvZygnVGhpcyBBUEkgaXMgdXNpbmcgYSBkZXByZWNhdGVkIHZlcnNpb24gb2YgU3dhZ2dlciEgIFBsZWFzZSBzZWUgaHR0cDovL2dpdGh1Yi5jb20vd29yZG5pay9zd2FnZ2VyLWNvcmUvd2lraSBmb3IgbW9yZSBpbmZvJyk7XG5cbiAgaWYgKHJlc3BvbnNlLmFwaVZlcnNpb24gIT09IG51bGwpIHtcbiAgICB0aGlzLmFwaVZlcnNpb24gPSByZXNwb25zZS5hcGlWZXJzaW9uO1xuICB9XG5cbiAgdGhpcy5hcGlzID0ge307XG4gIHRoaXMuYXBpc0FycmF5ID0gW107XG4gIHRoaXMucHJvZHVjZXMgPSByZXNwb25zZS5wcm9kdWNlcztcbiAgdGhpcy5pbmZvID0gdGhpcy5jb252ZXJ0SW5mbyhyZXNwb25zZS5pbmZvKTtcblxuICB2YXIgaXNBcGkgPSBmYWxzZSwgcmVzO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzcG9uc2UuYXBpcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBhcGkgPSByZXNwb25zZS5hcGlzW2ldO1xuXG4gICAgaWYgKGFwaS5vcGVyYXRpb25zKSB7XG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGFwaS5vcGVyYXRpb25zLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIGlzQXBpID0gdHJ1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlc3BvbnNlLmJhc2VQYXRoKSB7XG4gICAgdGhpcy5iYXNlUGF0aCA9IHJlc3BvbnNlLmJhc2VQYXRoO1xuICB9IGVsc2UgaWYgKHRoaXMudXJsLmluZGV4T2YoJz8nKSA+IDApIHtcbiAgICB0aGlzLmJhc2VQYXRoID0gdGhpcy51cmwuc3Vic3RyaW5nKDAsIHRoaXMudXJsLmxhc3RJbmRleE9mKCc/JykpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMuYmFzZVBhdGggPSB0aGlzLnVybDtcbiAgfVxuXG4gIGlmIChpc0FwaSkge1xuICAgIHZhciBuZXdOYW1lID0gcmVzcG9uc2UucmVzb3VyY2VQYXRoLnJlcGxhY2UoL1xcLy9nLCAnJyk7XG5cbiAgICB0aGlzLnJlc291cmNlUGF0aCA9IHJlc3BvbnNlLnJlc291cmNlUGF0aDtcbiAgICByZXMgPSBuZXcgU3dhZ2dlclJlc291cmNlKHJlc3BvbnNlLCB0aGlzKTtcbiAgICB0aGlzLmFwaXNbbmV3TmFtZV0gPSByZXM7XG4gICAgdGhpcy5hcGlzQXJyYXkucHVzaChyZXMpO1xuICAgIHRoaXMuZmluaXNoKCk7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5leHBlY3RlZFJlc291cmNlQ291bnQgPSByZXNwb25zZS5hcGlzLmxlbmd0aDtcblxuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgcmVzcG9uc2UuYXBpcy5sZW5ndGg7IGsrKykge1xuICAgICAgcmVzID0gbmV3IFN3YWdnZXJSZXNvdXJjZShyZXNwb25zZS5hcGlzW2tdLCB0aGlzKTtcbiAgICAgIHRoaXMuYXBpc1tyZXMubmFtZV0gPSByZXM7XG4gICAgICB0aGlzLmFwaXNBcnJheS5wdXNoKHJlcyk7XG4gICAgfVxuICB9XG5cbiAgdGhpcy5pc1ZhbGlkID0gdHJ1ZTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLmNvbnZlcnRJbmZvID0gZnVuY3Rpb24gKHJlc3ApIHtcbiAgaWYgKHR5cGVvZiByZXNwID09PSAnb2JqZWN0Jykge1xuICAgIHZhciBpbmZvID0ge307XG5cbiAgICBpbmZvLnRpdGxlID0gcmVzcC50aXRsZTtcbiAgICBpbmZvLmRlc2NyaXB0aW9uID0gcmVzcC5kZXNjcmlwdGlvbjtcbiAgICBpbmZvLnRlcm1zT2ZTZXJ2aWNlID0gcmVzcC50ZXJtc09mU2VydmljZVVybDtcbiAgICBpbmZvLmNvbnRhY3QgPSB7fTtcbiAgICBpbmZvLmNvbnRhY3QubmFtZSA9IHJlc3AuY29udGFjdDtcbiAgICBpbmZvLmxpY2Vuc2UgPSB7fTtcbiAgICBpbmZvLmxpY2Vuc2UubmFtZSA9IHJlc3AubGljZW5zZTtcbiAgICBpbmZvLmxpY2Vuc2UudXJsID0gcmVzcC5saWNlbnNlVXJsO1xuXG4gICAgcmV0dXJuIGluZm87XG4gIH1cbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLnNlbGZSZWZsZWN0ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgdGFnLCByZWY7XG5cbiAgaWYgKHRoaXMuYXBpcyA9PT0gbnVsbCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJlZiA9IHRoaXMuYXBpcztcblxuICBmb3IgKHRhZyBpbiByZWYpIHtcbiAgICB2YXIgYXBpID0gcmVmW3RhZ107XG5cbiAgICBpZiAoYXBpLnJlYWR5ID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdGhpc1t0YWddID0gYXBpO1xuICAgIHRoaXNbdGFnXS5oZWxwID0gaGVscGVycy5fX2JpbmQoYXBpLmhlbHAsIGFwaSk7XG4gIH1cblxuICB0aGlzLnNldENvbnNvbGlkYXRlZE1vZGVscygpO1xuICB0aGlzLnJlYWR5ID0gdHJ1ZTtcbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLnNldENvbnNvbGlkYXRlZE1vZGVscyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIG1vZGVsLCBtb2RlbE5hbWUsIHJlc291cmNlLCByZXNvdXJjZU5hbWUsIGksIGFwaXMsIG1vZGVscywgcmVzdWx0cztcblxuICB0aGlzLm1vZGVscyA9IHt9O1xuICBhcGlzID0gdGhpcy5hcGlzO1xuXG4gIGZvciAocmVzb3VyY2VOYW1lIGluIGFwaXMpIHtcbiAgICByZXNvdXJjZSA9IGFwaXNbcmVzb3VyY2VOYW1lXTtcblxuICAgIGZvciAobW9kZWxOYW1lIGluIHJlc291cmNlLm1vZGVscykge1xuICAgICAgaWYgKHR5cGVvZiB0aGlzLm1vZGVsc1ttb2RlbE5hbWVdID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aGlzLm1vZGVsc1ttb2RlbE5hbWVdID0gcmVzb3VyY2UubW9kZWxzW21vZGVsTmFtZV07XG4gICAgICAgIHRoaXMubW9kZWxzQXJyYXkucHVzaChyZXNvdXJjZS5tb2RlbHNbbW9kZWxOYW1lXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgbW9kZWxzID0gdGhpcy5tb2RlbHNBcnJheTtcbiAgcmVzdWx0cyA9IFtdO1xuXG4gIGZvciAoaSA9IDA7IGkgPCBtb2RlbHMubGVuZ3RoOyBpKyspIHtcbiAgICBtb2RlbCA9IG1vZGVsc1tpXTtcblxuICAgIHJlc3VsdHMucHVzaChtb2RlbC5zZXRSZWZlcmVuY2VkTW9kZWxzKHRoaXMubW9kZWxzKSk7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0cztcbn07XG5cblN3YWdnZXJSZXNvdXJjZS5wcm90b3R5cGUuaGVscCA9IGZ1bmN0aW9uIChkb250UHJpbnQpIHtcbiAgdmFyIG91dHB1dCA9ICdvcGVyYXRpb25zIGZvciB0aGUgXCInICsgdGhpcy5uYW1lICsgJ1wiIHRhZyc7XG4gIHZhciBpO1xuXG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLm9wZXJhdGlvbnNBcnJheS5sZW5ndGg7IGkrKykge1xuICAgIHZhciBhcGkgPSB0aGlzLm9wZXJhdGlvbnNBcnJheVtpXTtcblxuICAgIG91dHB1dCArPSAnXFxuICAqICcgKyBhcGkubmlja25hbWUgKyAnOiAnICsgYXBpLmRlc2NyaXB0aW9uO1xuICB9XG5cbiAgaWYgKGRvbnRQcmludCkge1xuICAgIHJldHVybiBvdXRwdXQ7XG4gIH0gZWxzZSB7XG4gICAgaGVscGVycy5sb2cob3V0cHV0KTtcblxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH1cbn07XG5cblN3YWdnZXJSZXNvdXJjZS5wcm90b3R5cGUuZ2V0QWJzb2x1dGVCYXNlUGF0aCA9IGZ1bmN0aW9uIChyZWxhdGl2ZUJhc2VQYXRoKSB7XG4gIHZhciB1cmwgPSB0aGlzLmFwaS5iYXNlUGF0aDtcbiAgdmFyIHBvcyA9IHVybC5sYXN0SW5kZXhPZihyZWxhdGl2ZUJhc2VQYXRoKTtcbiAgdmFyIHBhcnRzID0gdXJsLnNwbGl0KCcvJyk7XG4gIHZhciByb290VXJsID0gcGFydHNbMF0gKyAnLy8nICsgcGFydHNbMl07XG5cbiAgaWYgKHJlbGF0aXZlQmFzZVBhdGguaW5kZXhPZignaHR0cCcpID09PSAwKSB7XG4gICAgcmV0dXJuIHJlbGF0aXZlQmFzZVBhdGg7XG4gIH1cblxuICBpZiAocmVsYXRpdmVCYXNlUGF0aCA9PT0gJy8nKSB7XG4gICAgcmV0dXJuIHJvb3RVcmw7XG4gIH1cblxuICBpZiAocmVsYXRpdmVCYXNlUGF0aC5zdWJzdHJpbmcoMCwgMSkgPT09ICcvJykge1xuICAgIC8vIHVzZSByb290ICsgcmVsYXRpdmVcbiAgICByZXR1cm4gcm9vdFVybCArIHJlbGF0aXZlQmFzZVBhdGg7XG4gIH0gZWxzZSB7XG4gICAgcG9zID0gdGhpcy5iYXNlUGF0aC5sYXN0SW5kZXhPZignLycpO1xuXG4gICAgdmFyIGJhc2UgPSB0aGlzLmJhc2VQYXRoLnN1YnN0cmluZygwLCBwb3MpO1xuXG4gICAgaWYgKGJhc2Uuc3Vic3RyaW5nKGJhc2UubGVuZ3RoIC0gMSkgPT09ICcvJykge1xuICAgICAgcmV0dXJuIGJhc2UgKyByZWxhdGl2ZUJhc2VQYXRoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYmFzZSArICcvJyArIHJlbGF0aXZlQmFzZVBhdGg7XG4gICAgfVxuICB9XG59O1xuXG5Td2FnZ2VyUmVzb3VyY2UucHJvdG90eXBlLmFkZEFwaURlY2xhcmF0aW9uID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gIGlmICh0eXBlb2YgcmVzcG9uc2UucHJvZHVjZXMgPT09ICdzdHJpbmcnKSB7XG4gICAgdGhpcy5wcm9kdWNlcyA9IHJlc3BvbnNlLnByb2R1Y2VzO1xuICB9XG5cbiAgaWYgKHR5cGVvZiByZXNwb25zZS5jb25zdW1lcyA9PT0gJ3N0cmluZycpIHtcbiAgICB0aGlzLmNvbnN1bWVzID0gcmVzcG9uc2UuY29uc3VtZXM7XG4gIH1cblxuICBpZiAoKHR5cGVvZiByZXNwb25zZS5iYXNlUGF0aCA9PT0gJ3N0cmluZycpICYmIHJlc3BvbnNlLmJhc2VQYXRoLnJlcGxhY2UoL1xccy9nLCAnJykubGVuZ3RoID4gMCkge1xuICAgIHRoaXMuYmFzZVBhdGggPSByZXNwb25zZS5iYXNlUGF0aC5pbmRleE9mKCdodHRwJykgIT09IDAgPyB0aGlzLmdldEFic29sdXRlQmFzZVBhdGgocmVzcG9uc2UuYmFzZVBhdGgpIDogcmVzcG9uc2UuYmFzZVBhdGg7XG4gIH1cblxuICB0aGlzLnJlc291cmNlUGF0aCA9IHJlc3BvbnNlLnJlc291cmNlUGF0aDtcbiAgdGhpcy5hZGRNb2RlbHMocmVzcG9uc2UubW9kZWxzKTtcblxuICBpZiAocmVzcG9uc2UuYXBpcykge1xuICAgIGZvciAodmFyIGkgPSAwIDsgaSA8IHJlc3BvbnNlLmFwaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBlbmRwb2ludCA9IHJlc3BvbnNlLmFwaXNbaV07XG5cbiAgICAgIHRoaXMuYWRkT3BlcmF0aW9ucyhlbmRwb2ludC5wYXRoLCBlbmRwb2ludC5vcGVyYXRpb25zLCByZXNwb25zZS5jb25zdW1lcywgcmVzcG9uc2UucHJvZHVjZXMpO1xuICAgIH1cbiAgfVxuXG4gIHRoaXMuYXBpW3RoaXMubmFtZV0gPSB0aGlzO1xuICB0aGlzLnJlYWR5ID0gdHJ1ZTtcblxuICBpZiAodGhpcy5hcGkucmVzb3VyY2VDb3VudCA9PT0gdGhpcy5hcGkuZXhwZWN0ZWRSZXNvdXJjZUNvdW50KSB7XG4gICAgdGhpcy5hcGkuZmluaXNoKCk7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cblN3YWdnZXJSZXNvdXJjZS5wcm90b3R5cGUuYWRkTW9kZWxzID0gZnVuY3Rpb24gKG1vZGVscykge1xuICBpZiAodHlwZW9mIG1vZGVscyA9PT0gJ29iamVjdCcpIHtcbiAgICB2YXIgbW9kZWxOYW1lO1xuXG4gICAgZm9yIChtb2RlbE5hbWUgaW4gbW9kZWxzKSB7XG4gICAgICBpZiAodHlwZW9mIHRoaXMubW9kZWxzW21vZGVsTmFtZV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHZhciBzd2FnZ2VyTW9kZWwgPSBuZXcgU3dhZ2dlck1vZGVsKG1vZGVsTmFtZSwgbW9kZWxzW21vZGVsTmFtZV0sIHRoaXMuYXBpKTtcblxuICAgICAgICB0aGlzLm1vZGVsc0FycmF5LnB1c2goc3dhZ2dlck1vZGVsKTtcbiAgICAgICAgdGhpcy5tb2RlbHNbbW9kZWxOYW1lXSA9IHN3YWdnZXJNb2RlbDtcbiAgICAgICAgdGhpcy5yYXdNb2RlbHNbbW9kZWxOYW1lXSA9IG1vZGVsc1ttb2RlbE5hbWVdO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBvdXRwdXQgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5tb2RlbHNBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIG1vZGVsID0gdGhpcy5tb2RlbHNBcnJheVtpXTtcblxuICAgICAgb3V0cHV0LnB1c2gobW9kZWwuc2V0UmVmZXJlbmNlZE1vZGVscyh0aGlzLm1vZGVscykpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH1cbn07XG5cblN3YWdnZXJSZXNvdXJjZS5wcm90b3R5cGUuYWRkT3BlcmF0aW9ucyA9IGZ1bmN0aW9uIChyZXNvdXJjZVBhdGgsIG9wcywgY29uc3VtZXMsIHByb2R1Y2VzKSB7XG4gIGlmIChvcHMpIHtcbiAgICB2YXIgb3V0cHV0ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIG8gPSBvcHNbaV07XG5cbiAgICAgIGNvbnN1bWVzID0gdGhpcy5jb25zdW1lcztcbiAgICAgIHByb2R1Y2VzID0gdGhpcy5wcm9kdWNlcztcblxuICAgICAgaWYgKHR5cGVvZiBvLmNvbnN1bWVzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBjb25zdW1lcyA9IG8uY29uc3VtZXM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdW1lcyA9IHRoaXMuY29uc3VtZXM7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2Ygby5wcm9kdWNlcyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcHJvZHVjZXMgPSBvLnByb2R1Y2VzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHJvZHVjZXMgPSB0aGlzLnByb2R1Y2VzO1xuICAgICAgfVxuXG4gICAgICB2YXIgdHlwZSA9IChvLnR5cGUgfHwgby5yZXNwb25zZUNsYXNzKTtcblxuICAgICAgaWYgKHR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgdmFyIHJlZiA9IG51bGw7XG5cbiAgICAgICAgaWYgKG8uaXRlbXMpIHtcbiAgICAgICAgICByZWYgPSBvLml0ZW1zLnR5cGUgfHwgby5pdGVtcy4kcmVmO1xuICAgICAgICB9XG5cbiAgICAgICAgdHlwZSA9ICdhcnJheVsnICsgcmVmICsgJ10nO1xuICAgICAgfVxuXG4gICAgICB2YXIgcmVzcG9uc2VNZXNzYWdlcyA9IG8ucmVzcG9uc2VNZXNzYWdlcztcbiAgICAgIHZhciBtZXRob2QgPSBvLm1ldGhvZDtcblxuICAgICAgaWYgKG8uaHR0cE1ldGhvZCkge1xuICAgICAgICBtZXRob2QgPSBvLmh0dHBNZXRob2Q7XG4gICAgICB9XG5cbiAgICAgIGlmIChvLnN1cHBvcnRlZENvbnRlbnRUeXBlcykge1xuICAgICAgICBjb25zdW1lcyA9IG8uc3VwcG9ydGVkQ29udGVudFR5cGVzO1xuICAgICAgfVxuXG4gICAgICBpZiAoby5lcnJvclJlc3BvbnNlcykge1xuICAgICAgICByZXNwb25zZU1lc3NhZ2VzID0gby5lcnJvclJlc3BvbnNlcztcblxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJlc3BvbnNlTWVzc2FnZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICB2YXIgciA9IHJlc3BvbnNlTWVzc2FnZXNbal07XG5cbiAgICAgICAgICByLm1lc3NhZ2UgPSByLnJlYXNvbjtcbiAgICAgICAgICByLnJlYXNvbiA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgby5uaWNrbmFtZSA9IHRoaXMuc2FuaXRpemUoby5uaWNrbmFtZSk7XG5cbiAgICAgIHZhciBvcCA9IG5ldyBTd2FnZ2VyT3BlcmF0aW9uKG8ubmlja25hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvdXJjZVBhdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLnBhcmFtZXRlcnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLnN1bW1hcnksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLm5vdGVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlTWVzc2FnZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3VtZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9kdWNlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG8uYXV0aG9yaXphdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLmRlcHJlY2F0ZWQsIHRoaXMuY2xpZW50QXV0aG9yaXphdGlvbnMpO1xuXG4gICAgICB0aGlzLm9wZXJhdGlvbnNbb3Aubmlja25hbWVdID0gb3A7XG4gICAgICBvdXRwdXQucHVzaCh0aGlzLm9wZXJhdGlvbnNBcnJheS5wdXNoKG9wKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dHB1dDtcbiAgfVxufTtcblxuU3dhZ2dlclJlc291cmNlLnByb3RvdHlwZS5zYW5pdGl6ZSA9IGZ1bmN0aW9uIChuaWNrbmFtZSkge1xuICB2YXIgb3AgPSBuaWNrbmFtZS5yZXBsYWNlKC9bXFxzIUAjJCVeJiooKV8rPVxcW3tcXF19Ozo8PnwuXFwvPyxcXFxcJ1wiXCItXS9nLCAnXycpO1xuXG4gIG9wID0gb3AucmVwbGFjZSgvKChfKXsyLH0pL2csICdfJyk7XG4gIG9wID0gb3AucmVwbGFjZSgvXihfKSovZywgJycpO1xuICBvcCA9IG9wLnJlcGxhY2UoLyhbX10pKiQvZywgJycpO1xuXG4gIHJldHVybiBvcDtcbn07XG5cblN3YWdnZXJNb2RlbC5wcm90b3R5cGUuc2V0UmVmZXJlbmNlZE1vZGVscyA9IGZ1bmN0aW9uIChhbGxNb2RlbHMpIHtcbiAgdmFyIHJlc3VsdHMgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucHJvcGVydGllcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwcm9wZXJ0eSA9IHRoaXMucHJvcGVydGllc1tpXTtcbiAgICB2YXIgdHlwZSA9IHByb3BlcnR5LnR5cGUgfHwgcHJvcGVydHkuZGF0YVR5cGU7XG5cbiAgICBpZiAoYWxsTW9kZWxzW3R5cGVdKSB7XG4gICAgICByZXN1bHRzLnB1c2gocHJvcGVydHkucmVmTW9kZWwgPSBhbGxNb2RlbHNbdHlwZV0pO1xuICAgIH0gZWxzZSBpZiAoKHByb3BlcnR5LnJlZkRhdGFUeXBlKSAmJiAoYWxsTW9kZWxzW3Byb3BlcnR5LnJlZkRhdGFUeXBlXSkpIHtcbiAgICAgIHJlc3VsdHMucHVzaChwcm9wZXJ0eS5yZWZNb2RlbCA9IGFsbE1vZGVsc1twcm9wZXJ0eS5yZWZEYXRhVHlwZV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHRzLnB1c2godm9pZCAwKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzdWx0cztcbn07XG5cblN3YWdnZXJNb2RlbC5wcm90b3R5cGUuZ2V0TW9ja1NpZ25hdHVyZSA9IGZ1bmN0aW9uIChtb2RlbHNUb0lnbm9yZSkge1xuICB2YXIgaSwgcHJvcCwgcHJvcGVydGllc1N0ciA9IFtdO1xuXG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnByb3BlcnRpZXMubGVuZ3RoOyBpKyspIHtcbiAgICBwcm9wID0gdGhpcy5wcm9wZXJ0aWVzW2ldO1xuXG4gICAgcHJvcGVydGllc1N0ci5wdXNoKHByb3AudG9TdHJpbmcoKSk7XG4gIH1cblxuICB2YXIgc3Ryb25nID0gJzxzcGFuIGNsYXNzPVwic3Ryb25nXCI+JztcbiAgdmFyIHN0cm9uZ0Nsb3NlID0gJzwvc3Bhbj4nO1xuICB2YXIgY2xhc3NPcGVuID0gc3Ryb25nICsgdGhpcy5uYW1lICsgJyB7JyArIHN0cm9uZ0Nsb3NlO1xuICB2YXIgY2xhc3NDbG9zZSA9IHN0cm9uZyArICd9JyArIHN0cm9uZ0Nsb3NlO1xuICB2YXIgcmV0dXJuVmFsID0gY2xhc3NPcGVuICsgJzxkaXY+JyArIHByb3BlcnRpZXNTdHIuam9pbignLDwvZGl2PjxkaXY+JykgKyAnPC9kaXY+JyArIGNsYXNzQ2xvc2U7XG5cbiAgaWYgKCFtb2RlbHNUb0lnbm9yZSkge1xuICAgIG1vZGVsc1RvSWdub3JlID0gW107XG4gIH1cblxuICBtb2RlbHNUb0lnbm9yZS5wdXNoKHRoaXMubmFtZSk7XG5cbiAgZm9yIChpID0gMDsgaSA8IHRoaXMucHJvcGVydGllcy5sZW5ndGg7IGkrKykge1xuICAgIHByb3AgPSB0aGlzLnByb3BlcnRpZXNbaV07XG5cbiAgICBpZiAoKHByb3AucmVmTW9kZWwpICYmIG1vZGVsc1RvSWdub3JlLmluZGV4T2YocHJvcC5yZWZNb2RlbC5uYW1lKSA9PT0gLTEpIHtcbiAgICAgIHJldHVyblZhbCA9IHJldHVyblZhbCArICgnPGJyPicgKyBwcm9wLnJlZk1vZGVsLmdldE1vY2tTaWduYXR1cmUobW9kZWxzVG9JZ25vcmUpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuVmFsO1xufTtcblxuU3dhZ2dlck1vZGVsLnByb3RvdHlwZS5jcmVhdGVKU09OU2FtcGxlID0gZnVuY3Rpb24gKG1vZGVsc1RvSWdub3JlKSB7XG4gIGlmICh0aGlzLnNhbXBsZU1vZGVsc1t0aGlzLm5hbWVdKSB7XG4gICAgcmV0dXJuIHRoaXMuc2FtcGxlTW9kZWxzW3RoaXMubmFtZV07XG4gIH0gZWxzZSB7XG4gICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgbW9kZWxzVG9JZ25vcmUgPSAobW9kZWxzVG9JZ25vcmUgfHwgW10pO1xuICAgIG1vZGVsc1RvSWdub3JlLnB1c2godGhpcy5uYW1lKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5wcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcHJvcCA9IHRoaXMucHJvcGVydGllc1tpXTtcblxuICAgICAgcmVzdWx0W3Byb3AubmFtZV0gPSBwcm9wLmdldFNhbXBsZVZhbHVlKG1vZGVsc1RvSWdub3JlKTtcbiAgICB9XG5cbiAgICBtb2RlbHNUb0lnbm9yZS5wb3AodGhpcy5uYW1lKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn07XG5cblN3YWdnZXJNb2RlbFByb3BlcnR5LnByb3RvdHlwZS5nZXRTYW1wbGVWYWx1ZSA9IGZ1bmN0aW9uIChtb2RlbHNUb0lnbm9yZSkge1xuICB2YXIgcmVzdWx0O1xuXG4gIGlmICgodGhpcy5yZWZNb2RlbCkgJiYgKG1vZGVsc1RvSWdub3JlLmluZGV4T2YodGhpcy5yZWZNb2RlbC5uYW1lKSA9PT0gLTEpKSB7XG4gICAgcmVzdWx0ID0gdGhpcy5yZWZNb2RlbC5jcmVhdGVKU09OU2FtcGxlKG1vZGVsc1RvSWdub3JlKTtcbiAgfSBlbHNlIHtcbiAgICBpZiAodGhpcy5pc0NvbGxlY3Rpb24pIHtcbiAgICAgIHJlc3VsdCA9IHRoaXMudG9TYW1wbGVWYWx1ZSh0aGlzLnJlZkRhdGFUeXBlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0ID0gdGhpcy50b1NhbXBsZVZhbHVlKHRoaXMuZGF0YVR5cGUpO1xuICAgIH1cbiAgfVxuXG4gIGlmICh0aGlzLmlzQ29sbGVjdGlvbikge1xuICAgIHJldHVybiBbcmVzdWx0XTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59O1xuXG5Td2FnZ2VyTW9kZWxQcm9wZXJ0eS5wcm90b3R5cGUudG9TYW1wbGVWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICB2YXIgcmVzdWx0O1xuXG4gIGlmICgodHlwZW9mIHRoaXMuZGVmYXVsdFZhbHVlICE9PSAndW5kZWZpbmVkJykgJiYgdGhpcy5kZWZhdWx0VmFsdWUpIHtcbiAgICByZXN1bHQgPSB0aGlzLmRlZmF1bHRWYWx1ZTtcbiAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gJ2ludGVnZXInKSB7XG4gICAgcmVzdWx0ID0gMDtcbiAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgcmVzdWx0ID0gZmFsc2U7XG4gIH0gZWxzZSBpZiAodmFsdWUgPT09ICdkb3VibGUnIHx8IHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIHJlc3VsdCA9IDAuMDtcbiAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXN1bHQgPSAnJztcbiAgfSBlbHNlIHtcbiAgICByZXN1bHQgPSB2YWx1ZTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5Td2FnZ2VyTW9kZWxQcm9wZXJ0eS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciByZXEgPSB0aGlzLnJlcXVpcmVkID8gJ3Byb3BSZXEnIDogJ3Byb3BPcHQnO1xuICB2YXIgc3RyID0gJzxzcGFuIGNsYXNzPVwicHJvcE5hbWUgJyArIHJlcSArICdcIj4nICsgdGhpcy5uYW1lICsgJzwvc3Bhbj4gKDxzcGFuIGNsYXNzPVwicHJvcFR5cGVcIj4nICsgdGhpcy5kYXRhVHlwZVdpdGhSZWYgKyAnPC9zcGFuPic7XG5cbiAgaWYgKCF0aGlzLnJlcXVpcmVkKSB7XG4gICAgc3RyICs9ICcsIDxzcGFuIGNsYXNzPVwicHJvcE9wdEtleVwiPm9wdGlvbmFsPC9zcGFuPic7XG4gIH1cblxuICBzdHIgKz0gJyknO1xuXG4gIGlmICh0aGlzLnZhbHVlcykge1xuICAgIHN0ciArPSAnID0gPHNwYW4gY2xhc3M9XCJwcm9wVmFsc1wiPltcXCcnICsgdGhpcy52YWx1ZXMuam9pbignXFwnIG9yIFxcJycpICsgJ1xcJ108L3NwYW4+JztcbiAgfVxuXG4gIGlmICh0aGlzLmRlc2NyKSB7XG4gICAgc3RyICs9ICc6IDxzcGFuIGNsYXNzPVwicHJvcERlc2NcIj4nICsgdGhpcy5kZXNjciArICc8L3NwYW4+JztcbiAgfVxuXG4gIHJldHVybiBzdHI7XG59O1xuXG5Td2FnZ2VyT3BlcmF0aW9uLnByb3RvdHlwZS5pc0xpc3RUeXBlID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgaWYgKHR5cGUgJiYgdHlwZS5pbmRleE9mKCdbJykgPj0gMCkge1xuICAgIHJldHVybiB0eXBlLnN1YnN0cmluZyh0eXBlLmluZGV4T2YoJ1snKSArIDEsIHR5cGUuaW5kZXhPZignXScpKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdm9pZCAwO1xuICB9XG59O1xuXG5Td2FnZ2VyT3BlcmF0aW9uLnByb3RvdHlwZS5nZXRTaWduYXR1cmUgPSBmdW5jdGlvbiAodHlwZSwgbW9kZWxzKSB7XG4gIHZhciBsaXN0VHlwZSA9IHRoaXMuaXNMaXN0VHlwZSh0eXBlKTtcbiAgdmFyIGlzUHJpbWl0aXZlID0gKCh0eXBlb2YgbGlzdFR5cGUgIT09ICd1bmRlZmluZWQnKSAmJiBtb2RlbHNbbGlzdFR5cGVdKSB8fCAodHlwZW9mIG1vZGVsc1t0eXBlXSAhPT0gJ3VuZGVmaW5lZCcpID8gZmFsc2UgOiB0cnVlO1xuXG4gIGlmIChpc1ByaW1pdGl2ZSkge1xuICAgIHJldHVybiB0eXBlO1xuICB9IGVsc2Uge1xuICAgIGlmICh0eXBlb2YgbGlzdFR5cGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gbW9kZWxzW2xpc3RUeXBlXS5nZXRNb2NrU2lnbmF0dXJlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBtb2RlbHNbdHlwZV0uZ2V0TW9ja1NpZ25hdHVyZSgpO1xuICAgIH1cbiAgfVxufTtcblxuU3dhZ2dlck9wZXJhdGlvbi5wcm90b3R5cGUuZ2V0U2FtcGxlSlNPTiA9IGZ1bmN0aW9uICh0eXBlLCBtb2RlbHMpIHtcbiAgdmFyIGxpc3RUeXBlID0gdGhpcy5pc0xpc3RUeXBlKHR5cGUpO1xuICB2YXIgaXNQcmltaXRpdmUgPSAoKHR5cGVvZiBsaXN0VHlwZSAhPT0gJ3VuZGVmaW5lZCcpICYmIG1vZGVsc1tsaXN0VHlwZV0pIHx8ICh0eXBlb2YgbW9kZWxzW3R5cGVdICE9PSAndW5kZWZpbmVkJykgPyBmYWxzZSA6IHRydWU7XG4gIHZhciB2YWwgPSBpc1ByaW1pdGl2ZSA/IHZvaWQgMCA6IChsaXN0VHlwZSA/IG1vZGVsc1tsaXN0VHlwZV0uY3JlYXRlSlNPTlNhbXBsZSgpIDogbW9kZWxzW3R5cGVdLmNyZWF0ZUpTT05TYW1wbGUoKSk7XG5cbiAgaWYgKHZhbCkge1xuICAgIHZhbCA9IGxpc3RUeXBlID8gW3ZhbF0gOiB2YWw7XG5cbiAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB2YWw7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsID09PSAnb2JqZWN0Jykge1xuICAgICAgdmFyIHQgPSB2YWw7XG5cbiAgICAgIGlmICh2YWwgaW5zdGFuY2VvZiBBcnJheSAmJiB2YWwubGVuZ3RoID4gMCkge1xuICAgICAgICB0ID0gdmFsWzBdO1xuICAgICAgfVxuXG4gICAgICBpZiAodC5ub2RlTmFtZSkge1xuICAgICAgICB2YXIgeG1sU3RyaW5nID0gbmV3IFhNTFNlcmlhbGl6ZXIoKS5zZXJpYWxpemVUb1N0cmluZyh0KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXRYbWwoeG1sU3RyaW5nKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWwsIG51bGwsIDIpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdmFsO1xuICAgIH1cbiAgfVxufTtcblxuU3dhZ2dlck9wZXJhdGlvbi5wcm90b3R5cGVbJ2RvJ10gPSBmdW5jdGlvbiAoYXJncywgb3B0cywgY2FsbGJhY2ssIGVycm9yKSB7XG4gIHZhciBrZXksIHBhcmFtLCBwYXJhbXMsIHBvc3NpYmxlUGFyYW1zID0gW10sIHJlcSwgdmFsdWU7XG5cbiAgaWYgKHR5cGVvZiBlcnJvciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIGVycm9yID0gZnVuY3Rpb24gKHhociwgdGV4dFN0YXR1cywgZXJyb3IpIHtcbiAgICAgIHJldHVybiBoZWxwZXJzLmxvZyh4aHIsIHRleHRTdGF0dXMsIGVycm9yKTtcbiAgICB9O1xuICB9XG5cbiAgaWYgKHR5cGVvZiBjYWxsYmFjayAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIGNhbGxiYWNrID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICB2YXIgY29udGVudD0gbnVsbDtcblxuICAgICAgaWYgKHJlc3BvbnNlICE9PSBudWxsKSB7XG4gICAgICAgIGNvbnRlbnQgPSByZXNwb25zZS5kYXRhO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29udGVudCA9ICdubyBkYXRhJztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGhlbHBlcnMubG9nKCdkZWZhdWx0IGNhbGxiYWNrOiAnICsgY29udGVudCk7XG4gICAgfTtcbiAgfVxuXG4gIHBhcmFtcyA9IHt9O1xuICBwYXJhbXMuaGVhZGVycyA9IFtdO1xuXG4gIGlmIChhcmdzLmhlYWRlcnMpIHtcbiAgICBwYXJhbXMuaGVhZGVycyA9IGFyZ3MuaGVhZGVycztcblxuICAgIGRlbGV0ZSBhcmdzLmhlYWRlcnM7XG4gIH1cblxuICAvLyBhbGxvdyBvdmVycmlkZSBmcm9tIHRoZSBvcHRzXG4gIGlmIChvcHRzICYmIG9wdHMucmVzcG9uc2VDb250ZW50VHlwZSkge1xuICAgIHBhcmFtcy5oZWFkZXJzWydDb250ZW50LVR5cGUnXSA9IG9wdHMucmVzcG9uc2VDb250ZW50VHlwZTtcbiAgfVxuXG4gIGlmIChvcHRzICYmIG9wdHMucmVxdWVzdENvbnRlbnRUeXBlKSB7XG4gICAgcGFyYW1zLmhlYWRlcnMuQWNjZXB0ID0gb3B0cy5yZXF1ZXN0Q29udGVudFR5cGU7XG4gIH1cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucGFyYW1ldGVycy5sZW5ndGg7IGkrKykge1xuICAgIHBhcmFtID0gdGhpcy5wYXJhbWV0ZXJzW2ldO1xuXG4gICAgaWYgKHBhcmFtLnBhcmFtVHlwZSA9PT0gJ2hlYWRlcicpIHtcbiAgICAgIGlmICh0eXBlb2YgYXJnc1twYXJhbS5uYW1lXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcGFyYW1zLmhlYWRlcnNbcGFyYW0ubmFtZV0gPSBhcmdzW3BhcmFtLm5hbWVdO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocGFyYW0ucGFyYW1UeXBlID09PSAnZm9ybScgfHwgcGFyYW0ucGFyYW1UeXBlLnRvTG93ZXJDYXNlKCkgPT09ICdmaWxlJykge1xuICAgICAgcG9zc2libGVQYXJhbXMucHVzaChwYXJhbSk7XG4gICAgfSBlbHNlIGlmIChwYXJhbS5wYXJhbVR5cGUgPT09ICdib2R5JyAmJiBwYXJhbS5uYW1lICE9PSAnYm9keScgJiYgdHlwZW9mIGFyZ3NbcGFyYW0ubmFtZV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBpZiAoYXJncy5ib2R5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignU2F3IHR3byBib2R5IHBhcmFtcyBpbiBhbiBBUEkgbGlzdGluZzsgZXhwZWN0aW5nIGEgbWF4IG9mIG9uZS4nKTtcbiAgICAgIH1cblxuICAgICAgYXJncy5ib2R5ID0gYXJnc1twYXJhbS5uYW1lXTtcbiAgICB9XG4gIH1cblxuICBpZiAodHlwZW9mIGFyZ3MuYm9keSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBwYXJhbXMuYm9keSA9IGFyZ3MuYm9keTtcblxuICAgIGRlbGV0ZSBhcmdzLmJvZHk7XG4gIH1cblxuICBpZiAocG9zc2libGVQYXJhbXMpIHtcbiAgICBmb3IgKGtleSBpbiBwb3NzaWJsZVBhcmFtcykge1xuICAgICAgdmFsdWUgPSBwb3NzaWJsZVBhcmFtc1trZXldO1xuXG4gICAgICBpZiAoYXJnc1t2YWx1ZS5uYW1lXSkge1xuICAgICAgICBwYXJhbXNbdmFsdWUubmFtZV0gPSBhcmdzW3ZhbHVlLm5hbWVdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJlcSA9IG5ldyBTd2FnZ2VyUmVxdWVzdCh0aGlzLm1ldGhvZCwgdGhpcy51cmxpZnkoYXJncyksIHBhcmFtcywgb3B0cywgY2FsbGJhY2ssIGVycm9yLCB0aGlzKTtcblxuICBpZiAob3B0cy5tb2NrKSB7XG4gICAgcmV0dXJuIHJlcTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufTtcblxuU3dhZ2dlck9wZXJhdGlvbi5wcm90b3R5cGUucGF0aEpzb24gPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLnBhdGgucmVwbGFjZSgne2Zvcm1hdH0nLCAnanNvbicpO1xufTtcblxuU3dhZ2dlck9wZXJhdGlvbi5wcm90b3R5cGUucGF0aFhtbCA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMucGF0aC5yZXBsYWNlKCd7Zm9ybWF0fScsICd4bWwnKTtcbn07XG5cblN3YWdnZXJPcGVyYXRpb24ucHJvdG90eXBlLmVuY29kZVBhdGhQYXJhbSA9IGZ1bmN0aW9uIChwYXRoUGFyYW0pIHtcbiAgdmFyIGVuY1BhcnRzLCBwYXJ0LCBwYXJ0cywgX2ksIF9sZW47XG5cbiAgcGF0aFBhcmFtID0gcGF0aFBhcmFtLnRvU3RyaW5nKCk7XG5cbiAgaWYgKHBhdGhQYXJhbS5pbmRleE9mKCcvJykgPT09IC0xKSB7XG4gICAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChwYXRoUGFyYW0pO1xuICB9IGVsc2Uge1xuICAgIHBhcnRzID0gcGF0aFBhcmFtLnNwbGl0KCcvJyk7XG4gICAgZW5jUGFydHMgPSBbXTtcblxuICAgIGZvciAoX2kgPSAwLCBfbGVuID0gcGFydHMubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgIHBhcnQgPSBwYXJ0c1tfaV07XG5cbiAgICAgIGVuY1BhcnRzLnB1c2goZW5jb2RlVVJJQ29tcG9uZW50KHBhcnQpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZW5jUGFydHMuam9pbignLycpO1xuICB9XG59O1xuXG5Td2FnZ2VyT3BlcmF0aW9uLnByb3RvdHlwZS51cmxpZnkgPSBmdW5jdGlvbiAoYXJncykge1xuICB2YXIgaSwgaiwgcGFyYW0sIHVybDtcblxuICAvLyBlbnN1cmUgbm8gZG91YmxlIHNsYXNoaW5nLi4uXG4gIGlmICh0aGlzLnJlc291cmNlLmJhc2VQYXRoLmxlbmd0aCA+IDEgJiYgdGhpcy5yZXNvdXJjZS5iYXNlUGF0aC5zbGljZSgtMSkgPT09ICcvJyAmJiB0aGlzLnBhdGhKc29uKCkuY2hhckF0KDApID09PSAnLycpIHtcbiAgICB1cmwgPSB0aGlzLnJlc291cmNlLmJhc2VQYXRoICsgdGhpcy5wYXRoSnNvbigpLnN1YnN0cmluZygxKTtcbiAgfSBlbHNlIHtcbiAgICB1cmwgPSB0aGlzLnJlc291cmNlLmJhc2VQYXRoICsgdGhpcy5wYXRoSnNvbigpO1xuICB9XG5cbiAgdmFyIHBhcmFtcyA9IHRoaXMucGFyYW1ldGVycztcblxuICBmb3IgKGkgPSAwOyBpIDwgcGFyYW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgcGFyYW0gPSBwYXJhbXNbaV07XG5cbiAgICBpZiAocGFyYW0ucGFyYW1UeXBlID09PSAncGF0aCcpIHtcbiAgICAgIGlmICh0eXBlb2YgYXJnc1twYXJhbS5uYW1lXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgLy8gYXBwbHkgcGF0aCBwYXJhbXMgYW5kIHJlbW92ZSBmcm9tIGFyZ3NcbiAgICAgICAgdmFyIHJlZyA9IG5ldyBSZWdFeHAoJ1xcXFx7XFxcXHMqPycgKyBwYXJhbS5uYW1lICsgJ1teXFxcXHtcXFxcfVxcXFwvXSooPzpcXFxcey4qP1xcXFx9W15cXFxce1xcXFx9XFxcXC9dKikqXFxcXH0oPz0oXFxcXC8/fCQpKScsICdnaScpO1xuXG4gICAgICAgIHVybCA9IHVybC5yZXBsYWNlKHJlZywgdGhpcy5lbmNvZGVQYXRoUGFyYW0oYXJnc1twYXJhbS5uYW1lXSkpO1xuXG4gICAgICAgIGRlbGV0ZSBhcmdzW3BhcmFtLm5hbWVdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgJycgKyBwYXJhbS5uYW1lICsgJyBpcyBhIHJlcXVpcmVkIHBhdGggcGFyYW0uJztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB2YXIgcXVlcnlQYXJhbXMgPSAnJztcblxuICBmb3IgKGkgPSAwOyBpIDwgcGFyYW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgcGFyYW0gPSBwYXJhbXNbaV07XG5cbiAgICBpZiAocGFyYW0ucGFyYW1UeXBlID09PSAncXVlcnknKSB7XG4gICAgICB2YXIgYWRkaXRpb24gPSAnJztcblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkocGFyYW0pKSB7XG4gICAgICAgIHZhciBvdXRwdXQgPSAnJztcblxuICAgICAgICBmb3IgKGogPSAwOyBqIDwgcGFyYW0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICBpZiAoaiA+IDApIHtcbiAgICAgICAgICAgIG91dHB1dCArPSAnLCc7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgb3V0cHV0ICs9IGVuY29kZVVSSUNvbXBvbmVudChwYXJhbVtqXSk7XG4gICAgICAgIH1cblxuICAgICAgICBhZGRpdGlvbiArPSBlbmNvZGVVUklDb21wb25lbnQocGFyYW0ubmFtZSkgKyAnPScgKyBvdXRwdXQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoYXJnc1twYXJhbS5uYW1lXSkge1xuICAgICAgICAgIGFkZGl0aW9uICs9IGVuY29kZVVSSUNvbXBvbmVudChwYXJhbS5uYW1lKSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudChhcmdzW3BhcmFtLm5hbWVdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAocGFyYW0ucmVxdWlyZWQpIHtcbiAgICAgICAgICAgIHRocm93ICcnICsgcGFyYW0ubmFtZSArICcgaXMgYSByZXF1aXJlZCBxdWVyeSBwYXJhbS4nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoYWRkaXRpb24gIT09ICcnICYmIHF1ZXJ5UGFyYW1zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcXVlcnlQYXJhbXMgKz0gJyYnO1xuICAgICAgfVxuXG4gICAgICBxdWVyeVBhcmFtcyArPSBhZGRpdGlvbjtcbiAgICB9XG4gIH1cblxuICBpZiAoKHF1ZXJ5UGFyYW1zKSAmJiBxdWVyeVBhcmFtcy5sZW5ndGggPiAwKSB7XG4gICAgdXJsICs9ICc/JyArIHF1ZXJ5UGFyYW1zO1xuICB9XG5cbiAgcmV0dXJuIHVybDtcbn07XG5cblN3YWdnZXJPcGVyYXRpb24ucHJvdG90eXBlLnN1cHBvcnRIZWFkZXJQYXJhbXMgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLnJlc291cmNlLmFwaS5zdXBwb3J0SGVhZGVyUGFyYW1zO1xufTtcblxuU3dhZ2dlck9wZXJhdGlvbi5wcm90b3R5cGUuc3VwcG9ydGVkU3VibWl0TWV0aG9kcyA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMucmVzb3VyY2UuYXBpLnN1cHBvcnRlZFN1Ym1pdE1ldGhvZHM7XG59O1xuXG5Td2FnZ2VyT3BlcmF0aW9uLnByb3RvdHlwZS5nZXRRdWVyeVBhcmFtcyA9IGZ1bmN0aW9uIChhcmdzKSB7XG4gIHJldHVybiB0aGlzLmdldE1hdGNoaW5nUGFyYW1zKFsncXVlcnknXSwgYXJncyk7XG59O1xuXG5Td2FnZ2VyT3BlcmF0aW9uLnByb3RvdHlwZS5nZXRIZWFkZXJQYXJhbXMgPSBmdW5jdGlvbiAoYXJncykge1xuICByZXR1cm4gdGhpcy5nZXRNYXRjaGluZ1BhcmFtcyhbJ2hlYWRlciddLCBhcmdzKTtcbn07XG5cblN3YWdnZXJPcGVyYXRpb24ucHJvdG90eXBlLmdldE1hdGNoaW5nUGFyYW1zID0gZnVuY3Rpb24gKHBhcmFtVHlwZXMsIGFyZ3MpIHtcbiAgdmFyIG1hdGNoaW5nUGFyYW1zID0ge307XG4gIHZhciBwYXJhbXMgPSB0aGlzLnBhcmFtZXRlcnM7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJhbXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFyYW0gPSBwYXJhbXNbaV07XG5cbiAgICBpZiAoYXJncyAmJiBhcmdzW3BhcmFtLm5hbWVdKSB7XG4gICAgICBtYXRjaGluZ1BhcmFtc1twYXJhbS5uYW1lXSA9IGFyZ3NbcGFyYW0ubmFtZV07XG4gICAgfVxuICB9XG5cbiAgdmFyIGhlYWRlcnMgPSB0aGlzLnJlc291cmNlLmFwaS5oZWFkZXJzO1xuICB2YXIgbmFtZTtcblxuICBmb3IgKG5hbWUgaW4gaGVhZGVycykge1xuICAgIHZhciB2YWx1ZSA9IGhlYWRlcnNbbmFtZV07XG5cbiAgICBtYXRjaGluZ1BhcmFtc1tuYW1lXSA9IHZhbHVlO1xuICB9XG5cbiAgcmV0dXJuIG1hdGNoaW5nUGFyYW1zO1xufTtcblxuU3dhZ2dlck9wZXJhdGlvbi5wcm90b3R5cGUuaGVscCA9IGZ1bmN0aW9uIChkb250UHJpbnQpIHtcbiAgdmFyIG1zZyA9IHRoaXMubmlja25hbWUgKyAnOiAnICsgdGhpcy5zdW1tYXJ5O1xuICB2YXIgcGFyYW1zID0gdGhpcy5wYXJhbWV0ZXJzO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcGFyYW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHBhcmFtID0gcGFyYW1zW2ldO1xuXG4gICAgbXNnICs9ICdcXG4qICcgKyBwYXJhbS5uYW1lICsgKHBhcmFtLnJlcXVpcmVkID8gJyAocmVxdWlyZWQpJyA6ICcnKSArICcgLSAnICsgcGFyYW0uZGVzY3JpcHRpb247XG4gIH1cblxuICBpZiAoZG9udFByaW50KSB7XG4gICAgcmV0dXJuIG1zZztcbiAgfSBlbHNlIHtcbiAgICBoZWxwZXJzLmxvZyhtc2cpO1xuXG4gICAgcmV0dXJuIG1zZztcbiAgfVxufTtcblxuU3dhZ2dlck9wZXJhdGlvbi5wcm90b3R5cGUuYXNDdXJsID0gZnVuY3Rpb24gKGFyZ3MpIHtcbiAgdmFyIGhlYWRlcnMgPSBTd2FnZ2VyUmVxdWVzdC5wcm90b3R5cGUuc2V0SGVhZGVycyhhcmdzLCB7fSwgdGhpcyk7XG4gIHZhciByZXN1bHRzID0gW107XG4gIHZhciBpO1xuXG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnBhcmFtZXRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFyYW0gPSB0aGlzLnBhcmFtZXRlcnNbaV07XG5cbiAgICBpZiAocGFyYW0ucGFyYW1UeXBlICYmIHBhcmFtLnBhcmFtVHlwZSA9PT0gJ2hlYWRlcicgJiYgYXJnc1twYXJhbS5uYW1lXSkge1xuICAgICAgaGVhZGVyc1twYXJhbS5uYW1lXSA9IGFyZ3NbcGFyYW0ubmFtZV07XG4gICAgfVxuICB9XG5cbiAgdmFyIGtleTtcblxuICBmb3IgKGtleSBpbiBoZWFkZXJzKSB7XG4gICAgcmVzdWx0cy5wdXNoKCctLWhlYWRlciBcIicgKyBrZXkgKyAnOiAnICsgaGVhZGVyc1trZXldICsgJ1wiJyk7XG4gIH1cblxuICByZXR1cm4gJ2N1cmwgJyArIChyZXN1bHRzLmpvaW4oJyAnKSkgKyAnICcgKyB0aGlzLnVybGlmeShhcmdzKTtcbn07XG5cblN3YWdnZXJPcGVyYXRpb24ucHJvdG90eXBlLmZvcm1hdFhtbCA9IGZ1bmN0aW9uICh4bWwpIHtcbiAgdmFyIGNvbnRleHAsIGZvcm1hdHRlZCwgaW5kZW50LCBsYXN0VHlwZSwgbGluZXMsIGxuLCBwYWQsIHJlZywgdHJhbnNpdGlvbnMsIHdzZXhwLCBfZm4sIF9pLCBfbGVuO1xuXG4gIHJlZyA9IC8oPikoPCkoXFwvKikvZztcbiAgd3NleHAgPSAvWyBdKiguKilbIF0rXFxuL2c7XG4gIGNvbnRleHAgPSAvKDwuKz4pKC4rXFxuKS9nO1xuICB4bWwgPSB4bWwucmVwbGFjZShyZWcsICckMVxcbiQyJDMnKS5yZXBsYWNlKHdzZXhwLCAnJDFcXG4nKS5yZXBsYWNlKGNvbnRleHAsICckMVxcbiQyJyk7XG4gIHBhZCA9IDA7XG4gIGZvcm1hdHRlZCA9ICcnO1xuICBsaW5lcyA9IHhtbC5zcGxpdCgnXFxuJyk7XG4gIGluZGVudCA9IDA7XG4gIGxhc3RUeXBlID0gJ290aGVyJztcbiAgdHJhbnNpdGlvbnMgPSB7XG4gICAgJ3NpbmdsZS0+c2luZ2xlJzogMCxcbiAgICAnc2luZ2xlLT5jbG9zaW5nJzogLTEsXG4gICAgJ3NpbmdsZS0+b3BlbmluZyc6IDAsXG4gICAgJ3NpbmdsZS0+b3RoZXInOiAwLFxuICAgICdjbG9zaW5nLT5zaW5nbGUnOiAwLFxuICAgICdjbG9zaW5nLT5jbG9zaW5nJzogLTEsXG4gICAgJ2Nsb3NpbmctPm9wZW5pbmcnOiAwLFxuICAgICdjbG9zaW5nLT5vdGhlcic6IDAsXG4gICAgJ29wZW5pbmctPnNpbmdsZSc6IDEsXG4gICAgJ29wZW5pbmctPmNsb3NpbmcnOiAwLFxuICAgICdvcGVuaW5nLT5vcGVuaW5nJzogMSxcbiAgICAnb3BlbmluZy0+b3RoZXInOiAxLFxuICAgICdvdGhlci0+c2luZ2xlJzogMCxcbiAgICAnb3RoZXItPmNsb3NpbmcnOiAtMSxcbiAgICAnb3RoZXItPm9wZW5pbmcnOiAwLFxuICAgICdvdGhlci0+b3RoZXInOiAwXG4gIH07XG4gIF9mbiA9IGZ1bmN0aW9uIChsbikge1xuICAgIHZhciBmcm9tVG8sIGosIGtleSwgcGFkZGluZywgdHlwZSwgdHlwZXMsIHZhbHVlO1xuXG4gICAgdHlwZXMgPSB7XG4gICAgICBzaW5nbGU6IEJvb2xlYW4obG4ubWF0Y2goLzwuK1xcLz4vKSksXG4gICAgICBjbG9zaW5nOiBCb29sZWFuKGxuLm1hdGNoKC88XFwvLis+LykpLFxuICAgICAgb3BlbmluZzogQm9vbGVhbihsbi5tYXRjaCgvPFteIT9dLio+LykpXG4gICAgfTtcbiAgICB0eXBlID0gKChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgX3Jlc3VsdHM7XG4gICAgICBfcmVzdWx0cyA9IFtdO1xuICAgICAgZm9yIChrZXkgaW4gdHlwZXMpIHtcbiAgICAgICAgdmFsdWUgPSB0eXBlc1trZXldO1xuICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICBfcmVzdWx0cy5wdXNoKGtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBfcmVzdWx0cztcbiAgICB9KSgpKVswXTtcbiAgICB0eXBlID0gdHlwZSA9PT0gdm9pZCAwID8gJ290aGVyJyA6IHR5cGU7XG4gICAgZnJvbVRvID0gbGFzdFR5cGUgKyAnLT4nICsgdHlwZTtcbiAgICBsYXN0VHlwZSA9IHR5cGU7XG4gICAgcGFkZGluZyA9ICcnO1xuICAgIGluZGVudCArPSB0cmFuc2l0aW9uc1tmcm9tVG9dO1xuICAgIHBhZGRpbmcgPSAoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBfaiwgX3JlZjU7XG4gICAgICB2YXIgX3Jlc3VsdHMgPSBbXTtcblxuICAgICAgZm9yIChqID0gX2ogPSAwLCBfcmVmNSA9IGluZGVudDsgMCA8PSBfcmVmNSA/IF9qIDwgX3JlZjUgOiBfaiA+IF9yZWY1OyBqID0gMCA8PSBfcmVmNSA/ICsrX2ogOiAtLV9qKSB7XG4gICAgICAgIF9yZXN1bHRzLnB1c2goJyAgJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBfcmVzdWx0cztcbiAgICB9KSgpKS5qb2luKCcnKTtcblxuICAgIGlmIChmcm9tVG8gPT09ICdvcGVuaW5nLT5jbG9zaW5nJykge1xuICAgICAgZm9ybWF0dGVkID0gZm9ybWF0dGVkLnN1YnN0cigwLCBmb3JtYXR0ZWQubGVuZ3RoIC0gMSkgKyBsbiArICdcXG4nO1xuICAgIH0gZWxzZSB7XG4gICAgICBmb3JtYXR0ZWQgKz0gcGFkZGluZyArIGxuICsgJ1xcbic7XG4gICAgfVxuICB9O1xuXG4gIGZvciAoX2kgPSAwLCBfbGVuID0gbGluZXMubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICBsbiA9IGxpbmVzW19pXTtcbiAgICBfZm4obG4pO1xuICB9XG5cbiAgcmV0dXJuIGZvcm1hdHRlZDtcbn07XG5cblN3YWdnZXJSZXF1ZXN0LnByb3RvdHlwZS5zZXRIZWFkZXJzID0gZnVuY3Rpb24gKHBhcmFtcywgb3B0cywgb3BlcmF0aW9uKSB7XG4gIHZhciBhY2NlcHRzID0gb3B0cy5yZXNwb25zZUNvbnRlbnRUeXBlIHx8ICdhcHBsaWNhdGlvbi9qc29uJzsgLy8gZGVmYXVsdCB0eXBlXG4gIHZhciBjb25zdW1lcyA9IG9wdHMucmVxdWVzdENvbnRlbnRUeXBlIHx8ICdhcHBsaWNhdGlvbi9qc29uJzsgLy8gZGVmYXVsdCB0eXBlXG4gIHZhciBhbGxEZWZpbmVkUGFyYW1zID0gb3BlcmF0aW9uLnBhcmFtZXRlcnM7XG4gIHZhciBkZWZpbmVkRm9ybVBhcmFtcyA9IFtdO1xuICB2YXIgZGVmaW5lZEZpbGVQYXJhbXMgPSBbXTtcbiAgdmFyIGJvZHkgPSBwYXJhbXMuYm9keTtcbiAgdmFyIGhlYWRlcnMgPSB7fTtcbiAgdmFyIGk7XG5cbiAgLy8gZ2V0IHBhcmFtcyBmcm9tIHRoZSBvcGVyYXRpb24gYW5kIHNldCB0aGVtIGluIGRlZmluZWRGaWxlUGFyYW1zLCBkZWZpbmVkRm9ybVBhcmFtcywgaGVhZGVyc1xuICBmb3IgKGkgPSAwOyBpIDwgYWxsRGVmaW5lZFBhcmFtcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwYXJhbSA9IGFsbERlZmluZWRQYXJhbXNbaV07XG5cbiAgICBpZiAocGFyYW0ucGFyYW1UeXBlID09PSAnZm9ybScpIHtcbiAgICAgIGRlZmluZWRGb3JtUGFyYW1zLnB1c2gocGFyYW0pO1xuICAgIH0gZWxzZSBpZiAocGFyYW0ucGFyYW1UeXBlID09PSAnZmlsZScpIHtcbiAgICAgIGRlZmluZWRGaWxlUGFyYW1zLnB1c2gocGFyYW0pO1xuICAgIH0gZWxzZSBpZiAocGFyYW0ucGFyYW1UeXBlID09PSAnaGVhZGVyJyAmJiB0aGlzLnBhcmFtcy5oZWFkZXJzKSB7XG4gICAgICB2YXIga2V5ID0gcGFyYW0ubmFtZTtcbiAgICAgIHZhciBoZWFkZXJWYWx1ZSA9IHRoaXMucGFyYW1zLmhlYWRlcnNbcGFyYW0ubmFtZV07XG5cbiAgICAgIGlmICh0eXBlb2YgdGhpcy5wYXJhbXMuaGVhZGVyc1twYXJhbS5uYW1lXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgaGVhZGVyc1trZXldID0gaGVhZGVyVmFsdWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gaWYgdGhlcmUncyBhIGJvZHksIG5lZWQgdG8gc2V0IHRoZSBhY2NlcHRzIGhlYWRlciB2aWEgcmVxdWVzdENvbnRlbnRUeXBlXG4gIGlmIChib2R5ICYmICh0aGlzLnR5cGUgPT09ICdQT1NUJyB8fCB0aGlzLnR5cGUgPT09ICdQVVQnIHx8IHRoaXMudHlwZSA9PT0gJ1BBVENIJyB8fCB0aGlzLnR5cGUgPT09ICdERUxFVEUnKSkge1xuICAgIGlmICh0aGlzLm9wdHMucmVxdWVzdENvbnRlbnRUeXBlKSB7XG4gICAgICBjb25zdW1lcyA9IHRoaXMub3B0cy5yZXF1ZXN0Q29udGVudFR5cGU7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIGlmIGFueSBmb3JtIHBhcmFtcywgY29udGVudCB0eXBlIG11c3QgYmUgc2V0XG4gICAgaWYgKGRlZmluZWRGb3JtUGFyYW1zLmxlbmd0aCA+IDApIHtcbiAgICAgIGlmIChkZWZpbmVkRmlsZVBhcmFtcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN1bWVzID0gJ211bHRpcGFydC9mb3JtLWRhdGEnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3VtZXMgPSAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJztcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRoaXMudHlwZSA9PT0gJ0RFTEVURScpIHtcbiAgICAgIGJvZHkgPSAne30nO1xuICAgIH0gZWxzZSBpZiAodGhpcy50eXBlICE9PSAnREVMRVRFJykge1xuICAgICAgY29uc3VtZXMgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGlmIChjb25zdW1lcyAmJiB0aGlzLm9wZXJhdGlvbi5jb25zdW1lcykge1xuICAgIGlmICh0aGlzLm9wZXJhdGlvbi5jb25zdW1lcy5pbmRleE9mKGNvbnN1bWVzKSA9PT0gLTEpIHtcbiAgICAgIGhlbHBlcnMubG9nKCdzZXJ2ZXIgZG9lc25cXCd0IGNvbnN1bWUgJyArIGNvbnN1bWVzICsgJywgdHJ5ICcgKyBKU09OLnN0cmluZ2lmeSh0aGlzLm9wZXJhdGlvbi5jb25zdW1lcykpO1xuICAgIH1cbiAgfVxuXG4gIGlmICh0aGlzLm9wdHMgJiYgdGhpcy5vcHRzLnJlc3BvbnNlQ29udGVudFR5cGUpIHtcbiAgICBhY2NlcHRzID0gdGhpcy5vcHRzLnJlc3BvbnNlQ29udGVudFR5cGU7XG4gIH0gZWxzZSB7XG4gICAgYWNjZXB0cyA9ICdhcHBsaWNhdGlvbi9qc29uJztcbiAgfVxuXG4gIGlmIChhY2NlcHRzICYmIG9wZXJhdGlvbi5wcm9kdWNlcykge1xuICAgIGlmIChvcGVyYXRpb24ucHJvZHVjZXMuaW5kZXhPZihhY2NlcHRzKSA9PT0gLTEpIHtcbiAgICAgIGhlbHBlcnMubG9nKCdzZXJ2ZXIgY2FuXFwndCBwcm9kdWNlICcgKyBhY2NlcHRzKTtcbiAgICB9XG4gIH1cblxuICBpZiAoKGNvbnN1bWVzICYmIGJvZHkgIT09ICcnKSB8fCAoY29uc3VtZXMgPT09ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnKSkge1xuICAgIGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddID0gY29uc3VtZXM7XG4gIH1cblxuICBpZiAoYWNjZXB0cykge1xuICAgIGhlYWRlcnMuQWNjZXB0ID0gYWNjZXB0cztcbiAgfVxuXG4gIHJldHVybiBoZWFkZXJzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGF1dGggPSByZXF1aXJlKCcuL2F1dGgnKTtcbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi9oZWxwZXJzJyk7XG52YXIgTW9kZWwgPSByZXF1aXJlKCcuL3R5cGVzL21vZGVsJyk7XG52YXIgT3BlcmF0aW9uID0gcmVxdWlyZSgnLi90eXBlcy9vcGVyYXRpb24nKTtcbnZhciBPcGVyYXRpb25Hcm91cCA9IHJlcXVpcmUoJy4vdHlwZXMvb3BlcmF0aW9uR3JvdXAnKTtcbnZhciBSZXNvbHZlciA9IHJlcXVpcmUoJy4vcmVzb2x2ZXInKTtcbnZhciBTd2FnZ2VySHR0cCA9IHJlcXVpcmUoJy4vaHR0cCcpO1xuXG52YXIgU3dhZ2dlckNsaWVudCA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHVybCwgb3B0aW9ucykge1xuICB0aGlzLmF1dGhvcml6YXRpb25TY2hlbWUgPSBudWxsO1xuICB0aGlzLmF1dGhvcml6YXRpb25zID0gbnVsbDtcbiAgdGhpcy5iYXNlUGF0aCA9IG51bGw7XG4gIHRoaXMuZGVidWcgPSBmYWxzZTtcbiAgdGhpcy5pbmZvID0gbnVsbDtcbiAgdGhpcy5pc0J1aWx0ID0gZmFsc2U7XG4gIHRoaXMuaXNWYWxpZCA9IGZhbHNlO1xuICB0aGlzLm1vZGVsc0FycmF5ID0gW107XG4gIHRoaXMucmVzb3VyY2VDb3VudCA9IDA7XG4gIHRoaXMudXJsID0gbnVsbDtcbiAgdGhpcy51c2VKUXVlcnkgPSBmYWxzZTtcblxuICBpZiAodHlwZW9mIHVybCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gdGhpcy5pbml0aWFsaXplKHVybCwgb3B0aW9ucyk7XG4gIH1cbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLmluaXRpYWxpemUgPSBmdW5jdGlvbiAodXJsLCBvcHRpb25zKSB7XG4gIHRoaXMubW9kZWxzID0ge307XG4gIHRoaXMuc2FtcGxlTW9kZWxzID0ge307XG5cbiAgb3B0aW9ucyA9IChvcHRpb25zfHx7fSk7XG5cbiAgaWYgKHR5cGVvZiB1cmwgPT09ICdzdHJpbmcnKSB7XG4gICAgdGhpcy51cmwgPSB1cmw7XG4gIH0gZWxzZSBpZiAodHlwZW9mIHVybCA9PT0gJ29iamVjdCcpIHtcbiAgICBvcHRpb25zID0gdXJsO1xuICAgIHRoaXMudXJsID0gb3B0aW9ucy51cmw7XG4gIH1cblxuICB0aGlzLnN3YWdnZXJSZXF1c3RIZWFkZXJzID0gb3B0aW9ucy5zd2FnZ2VyUmVxdXN0SGVhZGVycyB8fCAnYXBwbGljYXRpb24vanNvbjtjaGFyc2V0PXV0Zi04LCovKic7XG4gIHRoaXMuZGVmYXVsdFN1Y2Nlc3NDYWxsYmFjayA9IG9wdGlvbnMuZGVmYXVsdFN1Y2Nlc3NDYWxsYmFjayB8fCBudWxsO1xuICB0aGlzLmRlZmF1bHRFcnJvckNhbGxiYWNrID0gb3B0aW9ucy5kZWZhdWx0RXJyb3JDYWxsYmFjayB8fCBudWxsO1xuXG4gIGlmICh0eXBlb2Ygb3B0aW9ucy5zdWNjZXNzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhpcy5zdWNjZXNzID0gb3B0aW9ucy5zdWNjZXNzO1xuICB9XG5cbiAgaWYgKG9wdGlvbnMudXNlSlF1ZXJ5KSB7XG4gICAgdGhpcy51c2VKUXVlcnkgPSBvcHRpb25zLnVzZUpRdWVyeTtcbiAgfVxuXG4gIGlmIChvcHRpb25zLmF1dGhvcml6YXRpb25zKSB7XG4gICAgdGhpcy5jbGllbnRBdXRob3JpemF0aW9ucyA9IG9wdGlvbnMuYXV0aG9yaXphdGlvbnM7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5jbGllbnRBdXRob3JpemF0aW9ucyA9IG5ldyBhdXRoLlN3YWdnZXJBdXRob3JpemF0aW9ucygpO1xuICB9XG5cbiAgdGhpcy5zdXBwb3J0ZWRTdWJtaXRNZXRob2RzID0gb3B0aW9ucy5zdXBwb3J0ZWRTdWJtaXRNZXRob2RzIHx8IFtdO1xuICB0aGlzLmZhaWx1cmUgPSBvcHRpb25zLmZhaWx1cmUgfHwgZnVuY3Rpb24gKCkge307XG4gIHRoaXMucHJvZ3Jlc3MgPSBvcHRpb25zLnByb2dyZXNzIHx8IGZ1bmN0aW9uICgpIHt9O1xuICB0aGlzLnNwZWMgPSBvcHRpb25zLnNwZWM7XG4gIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cbiAgaWYgKHR5cGVvZiBvcHRpb25zLnN1Y2Nlc3MgPT09ICdmdW5jdGlvbicpIHtcbiAgICB0aGlzLnJlYWR5ID0gdHJ1ZTtcbiAgICB0aGlzLmJ1aWxkKCk7XG4gIH1cbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLmJ1aWxkID0gZnVuY3Rpb24gKG1vY2spIHtcbiAgaWYgKHRoaXMuaXNCdWlsdCkge1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gIHRoaXMucHJvZ3Jlc3MoJ2ZldGNoaW5nIHJlc291cmNlIGxpc3Q6ICcgKyB0aGlzLnVybCk7XG5cbiAgdmFyIG9iaiA9IHtcbiAgICB1c2VKUXVlcnk6IHRoaXMudXNlSlF1ZXJ5LFxuICAgIHVybDogdGhpcy51cmwsXG4gICAgbWV0aG9kOiAnZ2V0JyxcbiAgICBoZWFkZXJzOiB7XG4gICAgICBhY2NlcHQ6IHRoaXMuc3dhZ2dlclJlcXVzdEhlYWRlcnNcbiAgICB9LFxuICAgIG9uOiB7XG4gICAgICBlcnJvcjogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgIGlmIChzZWxmLnVybC5zdWJzdHJpbmcoMCwgNCkgIT09ICdodHRwJykge1xuICAgICAgICAgIHJldHVybiBzZWxmLmZhaWwoJ1BsZWFzZSBzcGVjaWZ5IHRoZSBwcm90b2NvbCBmb3IgJyArIHNlbGYudXJsKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5zdGF0dXMgPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gc2VsZi5mYWlsKCdDYW5cXCd0IHJlYWQgZnJvbSBzZXJ2ZXIuICBJdCBtYXkgbm90IGhhdmUgdGhlIGFwcHJvcHJpYXRlIGFjY2Vzcy1jb250cm9sLW9yaWdpbiBzZXR0aW5ncy4nKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5zdGF0dXMgPT09IDQwNCkge1xuICAgICAgICAgIHJldHVybiBzZWxmLmZhaWwoJ0NhblxcJ3QgcmVhZCBzd2FnZ2VyIEpTT04gZnJvbSAnICsgc2VsZi51cmwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBzZWxmLmZhaWwocmVzcG9uc2Uuc3RhdHVzICsgJyA6ICcgKyByZXNwb25zZS5zdGF0dXNUZXh0ICsgJyAnICsgc2VsZi51cmwpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgcmVzcG9uc2U6IGZ1bmN0aW9uIChyZXNwKSB7XG4gICAgICAgIHZhciByZXNwb25zZU9iaiA9IHJlc3Aub2JqIHx8IEpTT04ucGFyc2UocmVzcC5kYXRhKTtcbiAgICAgICAgc2VsZi5zd2FnZ2VyVmVyc2lvbiA9IHJlc3BvbnNlT2JqLnN3YWdnZXJWZXJzaW9uO1xuXG4gICAgICAgIGlmIChyZXNwb25zZU9iai5zd2FnZ2VyICYmIHBhcnNlSW50KHJlc3BvbnNlT2JqLnN3YWdnZXIpID09PSAyKSB7XG4gICAgICAgICAgc2VsZi5zd2FnZ2VyVmVyc2lvbiA9IHJlc3BvbnNlT2JqLnN3YWdnZXI7XG5cbiAgICAgICAgICBuZXcgUmVzb2x2ZXIoKS5yZXNvbHZlKHJlc3BvbnNlT2JqLCBzZWxmLmJ1aWxkRnJvbVNwZWMsIHNlbGYpO1xuXG4gICAgICAgICAgc2VsZi5pc1ZhbGlkID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoc2VsZi5zd2FnZ2VyVmVyc2lvbiA9PT0gJzEuMicpIHtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLmJ1aWxkRnJvbTFfMlNwZWMocmVzcG9uc2VPYmopOyAvLyBqc2hpbnQgaWdub3JlOmxpbmVcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuYnVpbGRGcm9tMV8xU3BlYyhyZXNwb25zZU9iaik7IC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBpZiAodGhpcy5zcGVjKSB7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICBuZXcgUmVzb2x2ZXIoKS5yZXNvbHZlKHNlbGYuc3BlYywgc2VsZi5idWlsZEZyb21TcGVjLCBzZWxmKTtcbiAgIH0sIDEwKTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLmNsaWVudEF1dGhvcml6YXRpb25zLmFwcGx5KG9iaik7XG5cbiAgICBpZiAobW9jaykge1xuICAgICAgcmV0dXJuIG9iajtcbiAgICB9XG5cbiAgICBuZXcgU3dhZ2dlckh0dHAoKS5leGVjdXRlKG9iaik7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLmJ1aWxkRnJvbVNwZWMgPSBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgaWYgKHRoaXMuaXNCdWlsdCkge1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgdGhpcy5hcGlzID0ge307XG4gIHRoaXMuYXBpc0FycmF5ID0gW107XG4gIHRoaXMuYmFzZVBhdGggPSByZXNwb25zZS5iYXNlUGF0aCB8fCAnJztcbiAgdGhpcy5jb25zdW1lcyA9IHJlc3BvbnNlLmNvbnN1bWVzO1xuICB0aGlzLmhvc3QgPSByZXNwb25zZS5ob3N0IHx8ICcnO1xuICB0aGlzLmluZm8gPSByZXNwb25zZS5pbmZvIHx8IHt9O1xuICB0aGlzLnByb2R1Y2VzID0gcmVzcG9uc2UucHJvZHVjZXM7XG4gIHRoaXMuc2NoZW1lcyA9IHJlc3BvbnNlLnNjaGVtZXMgfHwgW107XG4gIHRoaXMuc2VjdXJpdHlEZWZpbml0aW9ucyA9IHJlc3BvbnNlLnNlY3VyaXR5RGVmaW5pdGlvbnM7XG4gIHRoaXMudGl0bGUgPSByZXNwb25zZS50aXRsZSB8fCAnJztcblxuICAvLyBsZWdhY3kgc3VwcG9ydFxuICB0aGlzLmF1dGhTY2hlbWVzID0gcmVzcG9uc2Uuc2VjdXJpdHlEZWZpbml0aW9ucztcblxuICB2YXIgZGVmaW5lZFRhZ3MgPSB7fTtcbiAgdmFyIGs7XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkocmVzcG9uc2UudGFncykpIHtcbiAgICBkZWZpbmVkVGFncyA9IHt9O1xuXG4gICAgZm9yIChrID0gMDsgayA8IHJlc3BvbnNlLnRhZ3MubGVuZ3RoOyBrKyspIHtcbiAgICAgIHZhciB0ID0gcmVzcG9uc2UudGFnc1trXTtcblxuICAgICAgZGVmaW5lZFRhZ3NbdC5uYW1lXSA9IHQ7XG4gICAgfVxuICB9XG5cbiAgdmFyIGxvY2F0aW9uO1xuXG4gIGlmICh0eXBlb2YgdGhpcy51cmwgPT09ICdzdHJpbmcnKSB7XG4gICAgbG9jYXRpb24gPSB0aGlzLnBhcnNlVXJpKHRoaXMudXJsKTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgdGhpcy5zY2hlbWVzID09PSAndW5kZWZpbmVkJyB8fCB0aGlzLnNjaGVtZXMubGVuZ3RoID09PSAwKSB7XG4gICAgdGhpcy5zY2hlbWUgPSBsb2NhdGlvbi5zY2hlbWUgfHwgJ2h0dHAnO1xuICB9IGVsc2Uge1xuICAgIHRoaXMuc2NoZW1lID0gdGhpcy5zY2hlbWVzWzBdO1xuICB9XG5cbiAgaWYgKHR5cGVvZiB0aGlzLmhvc3QgPT09ICd1bmRlZmluZWQnIHx8IHRoaXMuaG9zdCA9PT0gJycpIHtcbiAgICB0aGlzLmhvc3QgPSBsb2NhdGlvbi5ob3N0O1xuXG4gICAgaWYgKGxvY2F0aW9uLnBvcnQpIHtcbiAgICAgIHRoaXMuaG9zdCA9IHRoaXMuaG9zdCArICc6JyArIGxvY2F0aW9uLnBvcnQ7XG4gICAgfVxuICB9XG5cbiAgdGhpcy5kZWZpbml0aW9ucyA9IHJlc3BvbnNlLmRlZmluaXRpb25zO1xuXG4gIHZhciBrZXk7XG5cbiAgZm9yIChrZXkgaW4gdGhpcy5kZWZpbml0aW9ucykge1xuICAgIHZhciBtb2RlbCA9IG5ldyBNb2RlbChrZXksIHRoaXMuZGVmaW5pdGlvbnNba2V5XSwgdGhpcy5tb2RlbHMpO1xuXG4gICAgaWYgKG1vZGVsKSB7XG4gICAgICB0aGlzLm1vZGVsc1trZXldID0gbW9kZWw7XG4gICAgfVxuICB9XG5cbiAgLy8gZ2V0IHBhdGhzLCBjcmVhdGUgZnVuY3Rpb25zIGZvciBlYWNoIG9wZXJhdGlvbklkXG4gIHZhciBwYXRoO1xuXG4gIGZvciAocGF0aCBpbiByZXNwb25zZS5wYXRocykge1xuICAgIGlmICh0eXBlb2YgcmVzcG9uc2UucGF0aHNbcGF0aF0gPT09ICdvYmplY3QnKSB7XG4gICAgICB2YXIgaHR0cE1ldGhvZDtcblxuICAgICAgZm9yIChodHRwTWV0aG9kIGluIHJlc3BvbnNlLnBhdGhzW3BhdGhdKSB7XG4gICAgICAgIGlmIChbJ2RlbGV0ZScsICdnZXQnLCAnaGVhZCcsICdvcHRpb25zJywgJ3BhdGNoJywgJ3Bvc3QnLCAncHV0J10uaW5kZXhPZihodHRwTWV0aG9kKSA9PT0gLTEpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBvcGVyYXRpb24gPSByZXNwb25zZS5wYXRoc1twYXRoXVtodHRwTWV0aG9kXTtcbiAgICAgICAgdmFyIHRhZ3MgPSBvcGVyYXRpb24udGFncztcblxuICAgICAgICBpZiAodHlwZW9mIHRhZ3MgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgb3BlcmF0aW9uLnRhZ3MgPSBbICdkZWZhdWx0JyBdO1xuICAgICAgICAgIHRhZ3MgPSBvcGVyYXRpb24udGFncztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBvcGVyYXRpb25JZCA9IHRoaXMuaWRGcm9tT3AocGF0aCwgaHR0cE1ldGhvZCwgb3BlcmF0aW9uKTtcbiAgICAgICAgdmFyIG9wZXJhdGlvbk9iamVjdCA9IG5ldyBPcGVyYXRpb24gKFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgb3BlcmF0aW9uLnNjaGVtZSxcbiAgICAgICAgICBvcGVyYXRpb25JZCxcbiAgICAgICAgICBodHRwTWV0aG9kLFxuICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgb3BlcmF0aW9uLFxuICAgICAgICAgIHRoaXMuZGVmaW5pdGlvbnMsXG4gICAgICAgICAgdGhpcy5tb2RlbHMsXG4gICAgICAgICAgdGhpcy5jbGllbnRBdXRob3JpemF0aW9uc1xuICAgICAgICApO1xuXG4gICAgICAgIC8vIGJpbmQgdGhpcyBvcGVyYXRpb24ncyBleGVjdXRlIGNvbW1hbmQgdG8gdGhlIGFwaVxuICAgICAgICBpZiAodGFncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFncy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRhZyA9IHRoaXMudGFnRnJvbUxhYmVsKHRhZ3NbaV0pO1xuICAgICAgICAgICAgdmFyIG9wZXJhdGlvbkdyb3VwID0gdGhpc1t0YWddO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuYXBpc1t0YWddID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICB0aGlzLmFwaXNbdGFnXSA9IHt9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9wZXJhdGlvbkdyb3VwID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICB0aGlzW3RhZ10gPSBbXTtcbiAgICAgICAgICAgICAgb3BlcmF0aW9uR3JvdXAgPSB0aGlzW3RhZ107XG4gICAgICAgICAgICAgIG9wZXJhdGlvbkdyb3VwLm9wZXJhdGlvbnMgPSB7fTtcbiAgICAgICAgICAgICAgb3BlcmF0aW9uR3JvdXAubGFiZWwgPSB0YWc7XG4gICAgICAgICAgICAgIG9wZXJhdGlvbkdyb3VwLmFwaXMgPSBbXTtcblxuICAgICAgICAgICAgICB2YXIgdGFnT2JqZWN0ID0gZGVmaW5lZFRhZ3NbdGFnXTtcblxuICAgICAgICAgICAgICBpZiAodHlwZW9mIHRhZ09iamVjdCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICBvcGVyYXRpb25Hcm91cC5kZXNjcmlwdGlvbiA9IHRhZ09iamVjdC5kZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICBvcGVyYXRpb25Hcm91cC5leHRlcm5hbERvY3MgPSB0YWdPYmplY3QuZXh0ZXJuYWxEb2NzO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdGhpc1t0YWddLmhlbHAgPSB0aGlzLmhlbHAuYmluZChvcGVyYXRpb25Hcm91cCk7XG4gICAgICAgICAgICAgIHRoaXMuYXBpc0FycmF5LnB1c2gobmV3IE9wZXJhdGlvbkdyb3VwKHRhZywgb3BlcmF0aW9uR3JvdXAuZGVzY3JpcHRpb24sIG9wZXJhdGlvbkdyb3VwLmV4dGVybmFsRG9jcywgb3BlcmF0aW9uT2JqZWN0KSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5hcGlzW3RhZ10uaGVscCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICB0aGlzLmFwaXNbdGFnXS5oZWxwID0gdGhpcy5oZWxwLmJpbmQob3BlcmF0aW9uR3JvdXApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBiaW5kIHRvIHRoZSBhcGlzIG9iamVjdFxuICAgICAgICAgICAgdGhpcy5hcGlzW3RhZ11bb3BlcmF0aW9uSWRdID0gb3BlcmF0aW9uT2JqZWN0LmV4ZWN1dGUuYmluZChvcGVyYXRpb25PYmplY3QpO1xuICAgICAgICAgICAgdGhpcy5hcGlzW3RhZ11bb3BlcmF0aW9uSWRdLmhlbHAgPSBvcGVyYXRpb25PYmplY3QuaGVscC5iaW5kKG9wZXJhdGlvbk9iamVjdCk7XG4gICAgICAgICAgICB0aGlzLmFwaXNbdGFnXVtvcGVyYXRpb25JZF0uYXNDdXJsID0gb3BlcmF0aW9uT2JqZWN0LmFzQ3VybC5iaW5kKG9wZXJhdGlvbk9iamVjdCk7XG5cbiAgICAgICAgICAgIG9wZXJhdGlvbkdyb3VwW29wZXJhdGlvbklkXSA9IG9wZXJhdGlvbk9iamVjdC5leGVjdXRlLmJpbmQob3BlcmF0aW9uT2JqZWN0KTtcbiAgICAgICAgICAgIG9wZXJhdGlvbkdyb3VwW29wZXJhdGlvbklkXS5oZWxwID0gb3BlcmF0aW9uT2JqZWN0LmhlbHAuYmluZChvcGVyYXRpb25PYmplY3QpO1xuICAgICAgICAgICAgb3BlcmF0aW9uR3JvdXBbb3BlcmF0aW9uSWRdLmFzQ3VybCA9IG9wZXJhdGlvbk9iamVjdC5hc0N1cmwuYmluZChvcGVyYXRpb25PYmplY3QpO1xuXG4gICAgICAgICAgICBvcGVyYXRpb25Hcm91cC5hcGlzLnB1c2gob3BlcmF0aW9uT2JqZWN0KTtcbiAgICAgICAgICAgIG9wZXJhdGlvbkdyb3VwLm9wZXJhdGlvbnNbb3BlcmF0aW9uSWRdID0gb3BlcmF0aW9uT2JqZWN0O1xuXG4gICAgICAgICAgICAvLyBsZWdhY3kgVUkgZmVhdHVyZVxuICAgICAgICAgICAgdmFyIGo7XG4gICAgICAgICAgICB2YXIgYXBpO1xuXG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgdGhpcy5hcGlzQXJyYXkubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgaWYgKHRoaXMuYXBpc0FycmF5W2pdLnRhZyA9PT0gdGFnKSB7XG4gICAgICAgICAgICAgICAgYXBpID0gdGhpcy5hcGlzQXJyYXlbal07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFwaSkge1xuICAgICAgICAgICAgICBhcGkub3BlcmF0aW9uc0FycmF5LnB1c2gob3BlcmF0aW9uT2JqZWN0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaGVscGVycy5sb2coJ25vIGdyb3VwIHRvIGJpbmQgdG8nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHRoaXMuaXNCdWlsdCA9IHRydWU7XG5cbiAgaWYgKHRoaXMuc3VjY2Vzcykge1xuICAgIHRoaXMuaXNWYWxpZCA9IHRydWU7XG4gICAgdGhpcy5pc0J1aWx0ID0gdHJ1ZTtcbiAgICB0aGlzLnN1Y2Nlc3MoKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuU3dhZ2dlckNsaWVudC5wcm90b3R5cGUucGFyc2VVcmkgPSBmdW5jdGlvbiAodXJpKSB7XG4gIHZhciB1cmxQYXJzZVJFID0gL14oKCgoW146XFwvI1xcP10rOik/KD86KFxcL1xcLykoKD86KChbXjpAXFwvI1xcP10rKSg/OlxcOihbXjpAXFwvI1xcP10rKSk/KUApPygoW146XFwvI1xcP1xcXVxcW10rfFxcW1teXFwvXFxdQCM/XStcXF0pKD86XFw6KFswLTldKykpPykpPyk/KT8oKFxcLz8oPzpbXlxcL1xcPyNdK1xcLyspKikoW15cXD8jXSopKSk/KFxcP1teI10rKT8pKCMuKik/LztcbiAgdmFyIHBhcnRzID0gdXJsUGFyc2VSRS5leGVjKHVyaSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzY2hlbWU6IHBhcnRzWzRdLnJlcGxhY2UoJzonLCcnKSxcbiAgICBob3N0OiBwYXJ0c1sxMV0sXG4gICAgcG9ydDogcGFydHNbMTJdLFxuICAgIHBhdGg6IHBhcnRzWzE1XVxuICB9O1xufTtcblxuU3dhZ2dlckNsaWVudC5wcm90b3R5cGUuaGVscCA9IGZ1bmN0aW9uIChkb250UHJpbnQpIHtcbiAgdmFyIGk7XG4gIHZhciBvdXRwdXQgPSAnb3BlcmF0aW9ucyBmb3IgdGhlIFwiJyArIHRoaXMubGFiZWwgKyAnXCIgdGFnJztcblxuICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5hcGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGFwaSA9IHRoaXMuYXBpc1tpXTtcblxuICAgIG91dHB1dCArPSAnXFxuICAqICcgKyBhcGkubmlja25hbWUgKyAnOiAnICsgYXBpLm9wZXJhdGlvbi5zdW1tYXJ5O1xuICB9XG5cbiAgaWYgKGRvbnRQcmludCkge1xuICAgIHJldHVybiBvdXRwdXQ7XG4gIH0gZWxzZSB7XG4gICAgaGVscGVycy5sb2cob3V0cHV0KTtcblxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH1cbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLnRhZ0Zyb21MYWJlbCA9IGZ1bmN0aW9uIChsYWJlbCkge1xuICByZXR1cm4gbGFiZWw7XG59O1xuXG5Td2FnZ2VyQ2xpZW50LnByb3RvdHlwZS5pZEZyb21PcCA9IGZ1bmN0aW9uIChwYXRoLCBodHRwTWV0aG9kLCBvcCkge1xuICB2YXIgb3BJZCA9IG9wLm9wZXJhdGlvbklkIHx8IChwYXRoLnN1YnN0cmluZygxKSArICdfJyArIGh0dHBNZXRob2QpO1xuXG4gIHJldHVybiBvcElkLnJlcGxhY2UoL1tcXC4sLVxcLyMhJCVcXF4mXFwqOzp7fT1cXC1fYH4oKVxcK1xcc10vZywnXycpO1xufTtcblxuU3dhZ2dlckNsaWVudC5wcm90b3R5cGUuZmFpbCA9IGZ1bmN0aW9uIChtZXNzYWdlKSB7XG4gIHRoaXMuZmFpbHVyZShtZXNzYWdlKTtcblxuICB0aHJvdyBtZXNzYWdlO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMuX19iaW5kID0gZnVuY3Rpb24gKGZuLCBtZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKXtcbiAgICByZXR1cm4gZm4uYXBwbHkobWUsIGFyZ3VtZW50cyk7XG4gIH07XG59O1xuXG52YXIgbG9nID0gbW9kdWxlLmV4cG9ydHMubG9nID0gZnVuY3Rpb24oKSB7XG4gIGxvZy5oaXN0b3J5ID0gbG9nLmhpc3RvcnkgfHwgW107XG4gIGxvZy5oaXN0b3J5LnB1c2goYXJndW1lbnRzKTtcblxuICBpZiAoY29uc29sZSkge1xuICAgIGNvbnNvbGUubG9nKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cylbMF0pO1xuICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cy5mYWlsID0gZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgbG9nKG1lc3NhZ2UpO1xufTtcblxubW9kdWxlLmV4cG9ydHMub3B0aW9uSHRtbCA9IGZ1bmN0aW9uIChsYWJlbCwgdmFsdWUpIHtcbiAgcmV0dXJuICc8dHI+PHRkIGNsYXNzPVwib3B0aW9uTmFtZVwiPicgKyBsYWJlbCArICc6PC90ZD48dGQ+JyArIHZhbHVlICsgJzwvdGQ+PC90cj4nO1xufTtcblxubW9kdWxlLmV4cG9ydHMudHlwZUZyb21Kc29uU2NoZW1hID0gZnVuY3Rpb24gKHR5cGUsIGZvcm1hdCkge1xuICB2YXIgc3RyO1xuXG4gIGlmICh0eXBlID09PSAnaW50ZWdlcicgJiYgZm9ybWF0ID09PSAnaW50MzInKSB7XG4gICAgc3RyID0gJ2ludGVnZXInO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdpbnRlZ2VyJyAmJiBmb3JtYXQgPT09ICdpbnQ2NCcpIHtcbiAgICBzdHIgPSAnbG9uZyc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2ludGVnZXInICYmIHR5cGVvZiBmb3JtYXQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgc3RyID0gJ2xvbmcnO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdzdHJpbmcnICYmIGZvcm1hdCA9PT0gJ2RhdGUtdGltZScpIHtcbiAgICBzdHIgPSAnZGF0ZS10aW1lJztcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJyAmJiBmb3JtYXQgPT09ICdkYXRlJykge1xuICAgIHN0ciA9ICdkYXRlJztcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJyAmJiBmb3JtYXQgPT09ICdmbG9hdCcpIHtcbiAgICBzdHIgPSAnZmxvYXQnO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdudW1iZXInICYmIGZvcm1hdCA9PT0gJ2RvdWJsZScpIHtcbiAgICBzdHIgPSAnZG91YmxlJztcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgZm9ybWF0ID09PSAndW5kZWZpbmVkJykge1xuICAgIHN0ciA9ICdkb3VibGUnO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdib29sZWFuJykge1xuICAgIHN0ciA9ICdib29sZWFuJztcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgIHN0ciA9ICdzdHJpbmcnO1xuICB9XG5cbiAgcmV0dXJuIHN0cjtcbn07XG5cbnZhciBzaW1wbGVSZWYgPSBtb2R1bGUuZXhwb3J0cy5zaW1wbGVSZWYgPSBmdW5jdGlvbiAobmFtZSkge1xuICBpZiAodHlwZW9mIG5hbWUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAobmFtZS5pbmRleE9mKCcjL2RlZmluaXRpb25zLycpID09PSAwKSB7XG4gICAgcmV0dXJuIG5hbWUuc3Vic3RyaW5nKCcjL2RlZmluaXRpb25zLycubGVuZ3RoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbmFtZTtcbiAgfVxufTtcblxudmFyIGdldFN0cmluZ1NpZ25hdHVyZSA9IG1vZHVsZS5leHBvcnRzLmdldFN0cmluZ1NpZ25hdHVyZSA9IGZ1bmN0aW9uIChvYmosIGJhc2VDb21wb25lbnQpIHtcbiAgdmFyIHN0ciA9ICcnO1xuXG4gIGlmICh0eXBlb2Ygb2JqLiRyZWYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgc3RyICs9IHNpbXBsZVJlZihvYmouJHJlZik7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG9iai50eXBlID09PSAndW5kZWZpbmVkJykge1xuICAgIHN0ciArPSAnb2JqZWN0JztcbiAgfSBlbHNlIGlmIChvYmoudHlwZSA9PT0gJ2FycmF5Jykge1xuICAgIGlmIChiYXNlQ29tcG9uZW50KSB7XG4gICAgICBzdHIgKz0gZ2V0U3RyaW5nU2lnbmF0dXJlKChvYmouaXRlbXMgfHwgb2JqLiRyZWYgfHwge30pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyICs9ICdBcnJheVsnO1xuICAgICAgc3RyICs9IGdldFN0cmluZ1NpZ25hdHVyZSgob2JqLml0ZW1zIHx8IG9iai4kcmVmIHx8IHt9KSk7XG4gICAgICBzdHIgKz0gJ10nO1xuICAgIH1cbiAgfSBlbHNlIGlmIChvYmoudHlwZSA9PT0gJ2ludGVnZXInICYmIG9iai5mb3JtYXQgPT09ICdpbnQzMicpIHtcbiAgICBzdHIgKz0gJ2ludGVnZXInO1xuICB9IGVsc2UgaWYgKG9iai50eXBlID09PSAnaW50ZWdlcicgJiYgb2JqLmZvcm1hdCA9PT0gJ2ludDY0Jykge1xuICAgIHN0ciArPSAnbG9uZyc7XG4gIH0gZWxzZSBpZiAob2JqLnR5cGUgPT09ICdpbnRlZ2VyJyAmJiB0eXBlb2Ygb2JqLmZvcm1hdCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBzdHIgKz0gJ2xvbmcnO1xuICB9IGVsc2UgaWYgKG9iai50eXBlID09PSAnc3RyaW5nJyAmJiBvYmouZm9ybWF0ID09PSAnZGF0ZS10aW1lJykge1xuICAgIHN0ciArPSAnZGF0ZS10aW1lJztcbiAgfSBlbHNlIGlmIChvYmoudHlwZSA9PT0gJ3N0cmluZycgJiYgb2JqLmZvcm1hdCA9PT0gJ2RhdGUnKSB7XG4gICAgc3RyICs9ICdkYXRlJztcbiAgfSBlbHNlIGlmIChvYmoudHlwZSA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIG9iai5mb3JtYXQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgc3RyICs9ICdzdHJpbmcnO1xuICB9IGVsc2UgaWYgKG9iai50eXBlID09PSAnbnVtYmVyJyAmJiBvYmouZm9ybWF0ID09PSAnZmxvYXQnKSB7XG4gICAgc3RyICs9ICdmbG9hdCc7XG4gIH0gZWxzZSBpZiAob2JqLnR5cGUgPT09ICdudW1iZXInICYmIG9iai5mb3JtYXQgPT09ICdkb3VibGUnKSB7XG4gICAgc3RyICs9ICdkb3VibGUnO1xuICB9IGVsc2UgaWYgKG9iai50eXBlID09PSAnbnVtYmVyJyAmJiB0eXBlb2Ygb2JqLmZvcm1hdCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBzdHIgKz0gJ2RvdWJsZSc7XG4gIH0gZWxzZSBpZiAob2JqLnR5cGUgPT09ICdib29sZWFuJykge1xuICAgIHN0ciArPSAnYm9vbGVhbic7XG4gIH0gZWxzZSBpZiAob2JqLiRyZWYpIHtcbiAgICBzdHIgKz0gc2ltcGxlUmVmKG9iai4kcmVmKTtcbiAgfSBlbHNlIHtcbiAgICBzdHIgKz0gb2JqLnR5cGU7XG4gIH1cblxuICByZXR1cm4gc3RyO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcbnZhciBqUXVlcnkgPSByZXF1aXJlKCdqcXVlcnknKTtcbnZhciByZXF1ZXN0ID0gcmVxdWlyZSgnc3VwZXJhZ2VudCcpO1xuXG4vKlxuICogSlF1ZXJ5SHR0cENsaWVudCBpcyBhIGxpZ2h0LXdlaWdodCwgbm9kZSBvciBicm93c2VyIEhUVFAgY2xpZW50XG4gKi9cbnZhciBKUXVlcnlIdHRwQ2xpZW50ID0gZnVuY3Rpb24gKCkge307XG5cbi8qXG4gKiBTdXBlcmFnZW50SHR0cENsaWVudCBpcyBhIGxpZ2h0LXdlaWdodCwgbm9kZSBvciBicm93c2VyIEhUVFAgY2xpZW50XG4gKi9cbnZhciBTdXBlcmFnZW50SHR0cENsaWVudCA9IGZ1bmN0aW9uICgpIHt9O1xuXG4vKipcbiAqIFN3YWdnZXJIdHRwIGlzIGEgd3JhcHBlciBmb3IgZXhlY3V0aW5nIHJlcXVlc3RzXG4gKi9cbnZhciBTd2FnZ2VySHR0cCA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge307XG5cblN3YWdnZXJIdHRwLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKG9iaiwgb3B0cykge1xuICBpZiAob2JqICYmICh0eXBlb2Ygb2JqLnVzZUpRdWVyeSA9PT0gJ2Jvb2xlYW4nKSkge1xuICAgIHRoaXMudXNlSlF1ZXJ5ID0gb2JqLnVzZUpRdWVyeTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLnVzZUpRdWVyeSA9IHRoaXMuaXNJRTgoKTtcbiAgfVxuXG4gIGlmIChvYmogJiYgdHlwZW9mIG9iai5ib2R5ID09PSAnb2JqZWN0Jykge1xuICAgIC8vIHNwZWNpYWwgcHJvY2Vzc2luZyBmb3IgZmlsZSB1cGxvYWRzIHZpYSBqcXVlcnlcbiAgICBpZiAob2JqLmJvZHkudHlwZSAmJiBvYmouYm9keS50eXBlID09PSAnZm9ybURhdGEnKXtcbiAgICAgIG9iai5jb250ZW50VHlwZSA9IGZhbHNlO1xuICAgICAgb2JqLnByb2Nlc3NEYXRhID0gZmFsc2U7XG5cbiAgICAgIGRlbGV0ZSBvYmouaGVhZGVyc1snQ29udGVudC1UeXBlJ107XG4gICAgfSBlbHNlIHtcbiAgICAgIG9iai5ib2R5ID0gSlNPTi5zdHJpbmdpZnkob2JqLmJvZHkpO1xuICAgIH1cbiAgfVxuXG4gIGlmICh0aGlzLnVzZUpRdWVyeSkge1xuICAgIHJldHVybiBuZXcgSlF1ZXJ5SHR0cENsaWVudChvcHRzKS5leGVjdXRlKG9iaik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG5ldyBTdXBlcmFnZW50SHR0cENsaWVudChvcHRzKS5leGVjdXRlKG9iaik7XG4gIH1cbn07XG5cblN3YWdnZXJIdHRwLnByb3RvdHlwZS5pc0lFOCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGRldGVjdGVkSUUgPSBmYWxzZTtcblxuICBpZiAodHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcgJiYgbmF2aWdhdG9yLnVzZXJBZ2VudCkge1xuICAgIHZhciBuYXYgPSBuYXZpZ2F0b3IudXNlckFnZW50LnRvTG93ZXJDYXNlKCk7XG5cbiAgICBpZiAobmF2LmluZGV4T2YoJ21zaWUnKSAhPT0gLTEpIHtcbiAgICAgIHZhciB2ZXJzaW9uID0gcGFyc2VJbnQobmF2LnNwbGl0KCdtc2llJylbMV0pO1xuXG4gICAgICBpZiAodmVyc2lvbiA8PSA4KSB7XG4gICAgICAgIGRldGVjdGVkSUUgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkZXRlY3RlZElFO1xufTtcblxuSlF1ZXJ5SHR0cENsaWVudC5wcm90b3R5cGUuZXhlY3V0ZSA9IGZ1bmN0aW9uIChvYmopIHtcbiAgdmFyIGNiID0gb2JqLm9uO1xuICB2YXIgcmVxdWVzdCA9IG9iajtcblxuICBvYmoudHlwZSA9IG9iai5tZXRob2Q7XG4gIG9iai5jYWNoZSA9IGZhbHNlO1xuICBkZWxldGUgb2JqLnVzZUpRdWVyeTtcblxuICAvKlxuICBvYmouYmVmb3JlU2VuZCA9IGZ1bmN0aW9uICh4aHIpIHtcbiAgICB2YXIga2V5LCByZXN1bHRzO1xuICAgIGlmIChvYmouaGVhZGVycykge1xuICAgICAgcmVzdWx0cyA9IFtdO1xuICAgICAgZm9yIChrZXkgaW4gb2JqLmhlYWRlcnMpIHtcbiAgICAgICAgaWYgKGtleS50b0xvd2VyQ2FzZSgpID09PSAnY29udGVudC10eXBlJykge1xuICAgICAgICAgIHJlc3VsdHMucHVzaChvYmouY29udGVudFR5cGUgPSBvYmouaGVhZGVyc1trZXldKTtcbiAgICAgICAgfSBlbHNlIGlmIChrZXkudG9Mb3dlckNhc2UoKSA9PT0gJ2FjY2VwdCcpIHtcbiAgICAgICAgICByZXN1bHRzLnB1c2gob2JqLmFjY2VwdHMgPSBvYmouaGVhZGVyc1trZXldKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHRzLnB1c2goeGhyLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBvYmouaGVhZGVyc1trZXldKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHRzO1xuICAgIH1cbiAgfTsqL1xuXG4gIG9iai5kYXRhID0gb2JqLmJvZHk7XG5cbiAgZGVsZXRlIG9iai5ib2R5O1xuXG4gIG9iai5jb21wbGV0ZSA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgIHZhciBoZWFkZXJzID0ge307XG4gICAgdmFyIGhlYWRlckFycmF5ID0gcmVzcG9uc2UuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkuc3BsaXQoJ1xcbicpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoZWFkZXJBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHRvU3BsaXQgPSBoZWFkZXJBcnJheVtpXS50cmltKCk7XG5cbiAgICAgIGlmICh0b1NwbGl0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIHNlcGFyYXRvciA9IHRvU3BsaXQuaW5kZXhPZignOicpO1xuXG4gICAgICBpZiAoc2VwYXJhdG9yID09PSAtMSkge1xuICAgICAgICAvLyBOYW1lIGJ1dCBubyB2YWx1ZSBpbiB0aGUgaGVhZGVyXG4gICAgICAgIGhlYWRlcnNbdG9TcGxpdF0gPSBudWxsO1xuXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB2YXIgbmFtZSA9IHRvU3BsaXQuc3Vic3RyaW5nKDAsIHNlcGFyYXRvcikudHJpbSgpO1xuICAgICAgdmFyIHZhbHVlID0gdG9TcGxpdC5zdWJzdHJpbmcoc2VwYXJhdG9yICsgMSkudHJpbSgpO1xuXG4gICAgICBoZWFkZXJzW25hbWVdID0gdmFsdWU7XG4gICAgfVxuXG4gICAgdmFyIG91dCA9IHtcbiAgICAgIHVybDogcmVxdWVzdC51cmwsXG4gICAgICBtZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuICAgICAgc3RhdHVzOiByZXNwb25zZS5zdGF0dXMsXG4gICAgICBzdGF0dXNUZXh0OiByZXNwb25zZS5zdGF0dXNUZXh0LFxuICAgICAgZGF0YTogcmVzcG9uc2UucmVzcG9uc2VUZXh0LFxuICAgICAgaGVhZGVyczogaGVhZGVyc1xuICAgIH07XG5cbiAgICB2YXIgY29udGVudFR5cGUgPSAoaGVhZGVyc1snY29udGVudC10eXBlJ10gfHwgaGVhZGVyc1snQ29udGVudC1UeXBlJ10gfHwgbnVsbCk7XG5cbiAgICBpZiAoY29udGVudFR5cGUpIHtcbiAgICAgIGlmIChjb250ZW50VHlwZS5pbmRleE9mKCdhcHBsaWNhdGlvbi9qc29uJykgPT09IDAgfHwgY29udGVudFR5cGUuaW5kZXhPZignK2pzb24nKSA+IDApIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBvdXQub2JqID0gcmVzcG9uc2UucmVzcG9uc2VKU09OIHx8IEpTT04ucGFyc2Uob3V0LmRhdGEpIHx8IHt9O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIC8vIGRvIG5vdCBzZXQgb3V0Lm9ialxuICAgICAgICAgIGhlbHBlcnMubG9nKCd1bmFibGUgdG8gcGFyc2UgSlNPTiBjb250ZW50Jyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID49IDIwMCAmJiByZXNwb25zZS5zdGF0dXMgPCAzMDApIHtcbiAgICAgIGNiLnJlc3BvbnNlKG91dCk7XG4gICAgfSBlbHNlIGlmIChyZXNwb25zZS5zdGF0dXMgPT09IDAgfHwgKHJlc3BvbnNlLnN0YXR1cyA+PSA0MDAgJiYgcmVzcG9uc2Uuc3RhdHVzIDwgNTk5KSkge1xuICAgICAgY2IuZXJyb3Iob3V0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNiLnJlc3BvbnNlKG91dCk7XG4gICAgfVxuICB9O1xuXG4gIGpRdWVyeS5zdXBwb3J0LmNvcnMgPSB0cnVlO1xuXG4gIHJldHVybiBqUXVlcnkuYWpheChvYmopO1xufTtcblxuU3VwZXJhZ2VudEh0dHBDbGllbnQucHJvdG90eXBlLmV4ZWN1dGUgPSBmdW5jdGlvbiAob2JqKSB7XG4gIHZhciBtZXRob2QgPSBvYmoubWV0aG9kLnRvTG93ZXJDYXNlKCk7XG5cbiAgaWYgKG1ldGhvZCA9PT0gJ2RlbGV0ZScpIHtcbiAgICBtZXRob2QgPSAnZGVsJztcbiAgfVxuXG4gIHZhciBoZWFkZXJzID0gb2JqLmhlYWRlcnMgfHwge307XG4gIHZhciByID0gcmVxdWVzdFttZXRob2RdKG9iai51cmwpO1xuICB2YXIgbmFtZTtcblxuICBmb3IgKG5hbWUgaW4gaGVhZGVycykge1xuICAgIHIuc2V0KG5hbWUsIGhlYWRlcnNbbmFtZV0pO1xuICB9XG5cbiAgaWYgKG9iai5ib2R5KSB7XG4gICAgci5zZW5kKG9iai5ib2R5KTtcbiAgfVxuXG4gIHIuZW5kKGZ1bmN0aW9uIChlcnIsIHJlcykge1xuICAgIHZhciByZXNwb25zZSA9IHtcbiAgICAgIHVybDogb2JqLnVybCxcbiAgICAgIG1ldGhvZDogb2JqLm1ldGhvZCxcbiAgICAgIGhlYWRlcnM6IGhlYWRlcnNcbiAgICB9O1xuICAgIHZhciBjYjtcblxuICAgIGlmICghZXJyICYmIHJlcy5lcnJvcikge1xuICAgICAgZXJyID0gcmVzLmVycm9yO1xuICAgIH1cblxuICAgIGlmIChlcnIgJiYgb2JqLm9uICYmIG9iai5vbi5lcnJvcikge1xuICAgICAgcmVzcG9uc2Uub2JqID0gZXJyO1xuICAgICAgcmVzcG9uc2Uuc3RhdHVzID0gcmVzID8gcmVzLnN0YXR1cyA6IDUwMDtcbiAgICAgIHJlc3BvbnNlLnN0YXR1c1RleHQgPSByZXMgPyByZXMudGV4dCA6IGVyci5tZXNzYWdlO1xuICAgICAgY2IgPSBvYmoub24uZXJyb3I7XG4gICAgfSBlbHNlIGlmIChyZXMgJiYgb2JqLm9uICYmIG9iai5vbi5yZXNwb25zZSkge1xuICAgICAgcmVzcG9uc2Uub2JqID0gKHR5cGVvZiByZXMuYm9keSAhPT0gJ3VuZGVmaW5lZCcpID8gcmVzLmJvZHkgOiByZXMudGV4dDtcbiAgICAgIHJlc3BvbnNlLnN0YXR1cyA9IHJlcy5zdGF0dXM7XG4gICAgICByZXNwb25zZS5zdGF0dXNUZXh0ID0gcmVzLnRleHQ7XG4gICAgICBjYiA9IG9iai5vbi5yZXNwb25zZTtcbiAgICB9XG4gICAgcmVzcG9uc2UuZGF0YSA9IHJlc3BvbnNlLnN0YXR1c1RleHQ7XG5cbiAgICBpZiAoY2IpIHtcbiAgICAgIGNiKHJlc3BvbnNlKTtcbiAgICB9XG4gIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFN3YWdnZXJIdHRwID0gcmVxdWlyZSgnLi9odHRwJyk7XG5cbi8qKiBcbiAqIFJlc29sdmVzIGEgc3BlYydzIHJlbW90ZSByZWZlcmVuY2VzXG4gKi9cbnZhciBSZXNvbHZlciA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge307XG5cblJlc29sdmVyLnByb3RvdHlwZS5yZXNvbHZlID0gZnVuY3Rpb24gKHNwZWMsIGNhbGxiYWNrLCBzY29wZSkge1xuICB0aGlzLnNjb3BlID0gKHNjb3BlIHx8IHRoaXMpO1xuXG4gIHZhciBob3N0LCBuYW1lLCBwYXRoLCBwcm9wZXJ0eSwgcHJvcGVydHlOYW1lO1xuICB2YXIgcHJvY2Vzc2VkQ2FsbHMgPSAwLCByZXNvbHZlZFJlZnMgPSB7fSwgdW5yZXNvbHZlZFJlZnMgPSB7fTtcbiAgdmFyIHJlc29sdXRpb25UYWJsZSA9IHt9OyAvLyBzdG9yZSBvYmplY3RzIGZvciBkZXJlZmVyZW5jaW5nXG5cbiAgLy8gbW9kZWxzXG4gIGZvciAobmFtZSBpbiBzcGVjLmRlZmluaXRpb25zKSB7XG4gICAgdmFyIG1vZGVsID0gc3BlYy5kZWZpbml0aW9uc1tuYW1lXTtcblxuICAgIGZvciAocHJvcGVydHlOYW1lIGluIG1vZGVsLnByb3BlcnRpZXMpIHtcbiAgICAgIHByb3BlcnR5ID0gbW9kZWwucHJvcGVydGllc1twcm9wZXJ0eU5hbWVdO1xuXG4gICAgICB0aGlzLnJlc29sdmVUbyhwcm9wZXJ0eSwgcmVzb2x1dGlvblRhYmxlKTtcbiAgICB9XG4gIH1cblxuICAvLyBvcGVyYXRpb25zXG4gIGZvciAobmFtZSBpbiBzcGVjLnBhdGhzKSB7XG4gICAgdmFyIG1ldGhvZCwgb3BlcmF0aW9uLCByZXNwb25zZUNvZGU7XG5cbiAgICBwYXRoID0gc3BlYy5wYXRoc1tuYW1lXTtcblxuICAgIGZvciAobWV0aG9kIGluIHBhdGgpIHtcbiAgICAgIG9wZXJhdGlvbiA9IHBhdGhbbWV0aG9kXTtcblxuICAgICAgdmFyIGksIHBhcmFtZXRlcnMgPSBvcGVyYXRpb24ucGFyYW1ldGVycztcblxuICAgICAgZm9yIChpIGluIHBhcmFtZXRlcnMpIHtcbiAgICAgICAgdmFyIHBhcmFtZXRlciA9IHBhcmFtZXRlcnNbaV07XG5cbiAgICAgICAgaWYgKHBhcmFtZXRlci5pbiA9PT0gJ2JvZHknICYmIHBhcmFtZXRlci5zY2hlbWEpIHtcbiAgICAgICAgICB0aGlzLnJlc29sdmVUbyhwYXJhbWV0ZXIuc2NoZW1hLCByZXNvbHV0aW9uVGFibGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtZXRlci4kcmVmKSB7XG4gICAgICAgICAgdGhpcy5yZXNvbHZlSW5saW5lKHNwZWMsIHBhcmFtZXRlciwgcmVzb2x1dGlvblRhYmxlLCB1bnJlc29sdmVkUmVmcyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZm9yIChyZXNwb25zZUNvZGUgaW4gb3BlcmF0aW9uLnJlc3BvbnNlcykge1xuICAgICAgICB2YXIgcmVzcG9uc2UgPSBvcGVyYXRpb24ucmVzcG9uc2VzW3Jlc3BvbnNlQ29kZV07XG5cbiAgICAgICAgaWYgKHJlc3BvbnNlLnNjaGVtYSkge1xuICAgICAgICAgIHRoaXMucmVzb2x2ZVRvKHJlc3BvbnNlLnNjaGVtYSwgcmVzb2x1dGlvblRhYmxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIGdldCBob3N0c1xuICB2YXIgb3B0cyA9IHt9LCBleHBlY3RlZENhbGxzID0gMDtcblxuICBmb3IgKG5hbWUgaW4gcmVzb2x1dGlvblRhYmxlKSB7XG4gICAgdmFyIHBhcnRzID0gbmFtZS5zcGxpdCgnIycpO1xuXG4gICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMikge1xuICAgICAgaG9zdCA9IHBhcnRzWzBdOyBwYXRoID0gcGFydHNbMV07XG5cbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShvcHRzW2hvc3RdKSkge1xuICAgICAgICBvcHRzW2hvc3RdID0gW107XG4gICAgICAgIGV4cGVjdGVkQ2FsbHMgKz0gMTtcbiAgICAgIH1cblxuICAgICAgb3B0c1tob3N0XS5wdXNoKHBhdGgpO1xuICAgIH1cbiAgfVxuXG4gIGZvciAobmFtZSBpbiBvcHRzKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzLCBvcHQgPSBvcHRzW25hbWVdO1xuXG4gICAgaG9zdCA9IG5hbWU7XG5cbiAgICB2YXIgb2JqID0ge1xuICAgICAgdXNlSlF1ZXJ5OiBmYWxzZSwgIC8vIFRPRE9cbiAgICAgIHVybDogaG9zdCxcbiAgICAgIG1ldGhvZDogJ2dldCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIGFjY2VwdDogdGhpcy5zY29wZS5zd2FnZ2VyUmVxdWVzdEhlYWRlcnMgfHwgJ2FwcGxpY2F0aW9uL2pzb24nXG4gICAgICB9LFxuICAgICAgb246IHtcbiAgICAgICAgZXJyb3I6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBwcm9jZXNzZWRDYWxscyArPSAxO1xuXG4gICAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgb3B0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAvLyBmYWlsIGFsbCBvZiB0aGVzZVxuICAgICAgICAgICAgdmFyIHJlc29sdmVkID0gaG9zdCArICcjJyArIG9wdFtpXTtcblxuICAgICAgICAgICAgdW5yZXNvbHZlZFJlZnNbcmVzb2x2ZWRdID0gbnVsbDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocHJvY2Vzc2VkQ2FsbHMgPT09IGV4cGVjdGVkQ2FsbHMpIHtcbiAgICAgICAgICAgIHNlbGYuZmluaXNoKHNwZWMsIHJlc29sdXRpb25UYWJsZSwgcmVzb2x2ZWRSZWZzLCB1bnJlc29sdmVkUmVmcywgY2FsbGJhY2spO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgIC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgICAgICByZXNwb25zZTogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgdmFyIGksIGosIHN3YWdnZXIgPSByZXNwb25zZS5vYmo7XG5cbiAgICAgICAgICBwcm9jZXNzZWRDYWxscyArPSAxO1xuXG4gICAgICAgICAgZm9yIChpID0gMDsgaSA8IG9wdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGxvY2F0aW9uID0gc3dhZ2dlciwgcGF0aCA9IG9wdFtpXSwgcGFydHMgPSBwYXRoLnNwbGl0KCcvJyk7XG5cbiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBwYXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICB2YXIgc2VnbWVudCA9IHBhcnRzW2pdO1xuXG4gICAgICAgICAgICAgIGlmICh0eXBlb2YgbG9jYXRpb24gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBpZiAoc2VnbWVudC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24gPSBsb2NhdGlvbltzZWdtZW50XTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcmVzb2x2ZWQgPSBob3N0ICsgJyMnICsgcGF0aCwgcmVzb2x2ZWROYW1lID0gcGFydHNbai0xXTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBsb2NhdGlvbiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgcmVzb2x2ZWRSZWZzW3Jlc29sdmVkXSA9IHtcbiAgICAgICAgICAgICAgICBuYW1lOiByZXNvbHZlZE5hbWUsXG4gICAgICAgICAgICAgICAgb2JqOiBsb2NhdGlvblxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdW5yZXNvbHZlZFJlZnNbcmVzb2x2ZWRdID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHByb2Nlc3NlZENhbGxzID09PSBleHBlY3RlZENhbGxzKSB7XG4gICAgICAgICAgICBzZWxmLmZpbmlzaChzcGVjLCByZXNvbHV0aW9uVGFibGUsIHJlc29sdmVkUmVmcywgdW5yZXNvbHZlZFJlZnMsIGNhbGxiYWNrKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gLy8ganNoaW50IGlnbm9yZTpsaW5lXG4gICAgfTtcblxuICAgIGlmIChzY29wZSAmJiBzY29wZS5jbGllbnRBdXRob3JpemF0aW9ucykge1xuICAgICAgc2NvcGUuY2xpZW50QXV0aG9yaXphdGlvbnMuYXBwbHkob2JqKTtcbiAgICB9XG5cbiAgICBuZXcgU3dhZ2dlckh0dHAoKS5leGVjdXRlKG9iaik7XG4gIH1cblxuICBpZiAoT2JqZWN0LmtleXMob3B0cykubGVuZ3RoID09PSAwKSB7XG4gICAgY2FsbGJhY2suY2FsbCh0aGlzLnNjb3BlLCBzcGVjLCB1bnJlc29sdmVkUmVmcyk7XG4gIH1cbn07XG5cblJlc29sdmVyLnByb3RvdHlwZS5maW5pc2ggPSBmdW5jdGlvbiAoc3BlYywgcmVzb2x1dGlvblRhYmxlLCByZXNvbHZlZFJlZnMsIHVucmVzb2x2ZWRSZWZzLCBjYWxsYmFjaykge1xuICAvLyB3YWxrIHJlc29sdXRpb24gdGFibGUgYW5kIHJlcGxhY2Ugd2l0aCByZXNvbHZlZCByZWZzXG4gIHZhciByZWY7XG5cbiAgZm9yIChyZWYgaW4gcmVzb2x1dGlvblRhYmxlKSB7XG4gICAgdmFyIGksIGxvY2F0aW9ucyA9IHJlc29sdXRpb25UYWJsZVtyZWZdO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IGxvY2F0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHJlc29sdmVkVG8gPSByZXNvbHZlZFJlZnNbbG9jYXRpb25zW2ldLm9iai4kcmVmXTtcblxuICAgICAgaWYgKHJlc29sdmVkVG8pIHtcbiAgICAgICAgaWYgKCFzcGVjLmRlZmluaXRpb25zKSB7XG4gICAgICAgICAgc3BlYy5kZWZpbml0aW9ucyA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxvY2F0aW9uc1tpXS5yZXNvbHZlQXMgPT09ICckcmVmJykge1xuICAgICAgICAgIHNwZWMuZGVmaW5pdGlvbnNbcmVzb2x2ZWRUby5uYW1lXSA9IHJlc29sdmVkVG8ub2JqO1xuICAgICAgICAgIGxvY2F0aW9uc1tpXS5vYmouJHJlZiA9ICcjL2RlZmluaXRpb25zLycgKyByZXNvbHZlZFRvLm5hbWU7XG4gICAgICAgIH0gZWxzZSBpZiAobG9jYXRpb25zW2ldLnJlc29sdmVBcyA9PT0gJ2lubGluZScpIHtcbiAgICAgICAgICB2YXIgdGFyZ2V0T2JqID0gbG9jYXRpb25zW2ldLm9iajtcbiAgICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgICAgZGVsZXRlIHRhcmdldE9iai4kcmVmO1xuXG4gICAgICAgICAgZm9yIChrZXkgaW4gcmVzb2x2ZWRUby5vYmopIHtcbiAgICAgICAgICAgIHRhcmdldE9ialtrZXldID0gcmVzb2x2ZWRUby5vYmpba2V5XTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjYWxsYmFjay5jYWxsKHRoaXMuc2NvcGUsIHNwZWMsIHVucmVzb2x2ZWRSZWZzKTtcbn07XG5cbi8qKlxuICogaW1tZWRpYXRlbHkgaW4tbGluZXMgbG9jYWwgcmVmcywgcXVldWVzIHJlbW90ZSByZWZzXG4gKiBmb3IgaW5saW5lIHJlc29sdXRpb25cbiAqL1xuUmVzb2x2ZXIucHJvdG90eXBlLnJlc29sdmVJbmxpbmUgPSBmdW5jdGlvbiAoc3BlYywgcHJvcGVydHksIG9ianMsIHVucmVzb2x2ZWRSZWZzKSB7XG4gIHZhciByZWYgPSBwcm9wZXJ0eS4kcmVmO1xuXG4gIGlmIChyZWYpIHtcbiAgICBpZiAocmVmLmluZGV4T2YoJ2h0dHAnKSA9PT0gMCkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2Jqc1tyZWZdKSkge1xuICAgICAgICBvYmpzW3JlZl0ucHVzaCh7b2JqOiBwcm9wZXJ0eSwgcmVzb2x2ZUFzOiAnaW5saW5lJ30pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb2Jqc1tyZWZdID0gW3tvYmo6IHByb3BlcnR5LCByZXNvbHZlQXM6ICdpbmxpbmUnfV07XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChyZWYuaW5kZXhPZignIycpID09PSAwKSB7XG4gICAgICAvLyBsb2NhbCByZXNvbHZlXG4gICAgICB2YXIgc2hvcnRlbmVkUmVmID0gcmVmLnN1YnN0cmluZygxKTtcbiAgICAgIHZhciBpLCBwYXJ0cyA9IHNob3J0ZW5lZFJlZi5zcGxpdCgnLycpLCBsb2NhdGlvbiA9IHNwZWM7XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcGFydCA9IHBhcnRzW2ldO1xuXG4gICAgICAgIGlmIChwYXJ0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBsb2NhdGlvbiA9IGxvY2F0aW9uW3BhcnRdO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChsb2NhdGlvbikge1xuICAgICAgICBkZWxldGUgcHJvcGVydHkuJHJlZjtcblxuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxvY2F0aW9uKSB7XG4gICAgICAgICAgcHJvcGVydHlba2V5XSA9IGxvY2F0aW9uW2tleV07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHVucmVzb2x2ZWRSZWZzW3JlZl0gPSBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmIChwcm9wZXJ0eS50eXBlID09PSAnYXJyYXknKSB7XG4gICAgdGhpcy5yZXNvbHZlVG8ocHJvcGVydHkuaXRlbXMsIG9ianMpO1xuICB9XG59O1xuXG5SZXNvbHZlci5wcm90b3R5cGUucmVzb2x2ZVRvID0gZnVuY3Rpb24gKHByb3BlcnR5LCBvYmpzKSB7XG4gIHZhciByZWYgPSBwcm9wZXJ0eS4kcmVmO1xuXG4gIGlmIChyZWYpIHtcbiAgICBpZiAocmVmLmluZGV4T2YoJ2h0dHAnKSA9PT0gMCkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2Jqc1tyZWZdKSkge1xuICAgICAgICBvYmpzW3JlZl0ucHVzaCh7b2JqOiBwcm9wZXJ0eSwgcmVzb2x2ZUFzOiAnJHJlZid9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9ianNbcmVmXSA9IFt7b2JqOiBwcm9wZXJ0eSwgcmVzb2x2ZUFzOiAnJHJlZid9XTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSBpZiAocHJvcGVydHkudHlwZSA9PT0gJ2FycmF5Jykge1xuICAgIHZhciBpdGVtcyA9IHByb3BlcnR5Lml0ZW1zO1xuXG4gICAgdGhpcy5yZXNvbHZlVG8oaXRlbXMsIG9ianMpO1xuICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4uL2hlbHBlcnMnKTtcblxudmFyIEFycmF5TW9kZWwgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChkZWZpbml0aW9uLCBtb2RlbHMpIHtcbiAgdGhpcy5tb2RlbHMgPSBtb2RlbHM7XG4gIHRoaXMubmFtZSA9ICdhcnJheU1vZGVsJztcbiAgdGhpcy5kZWZpbml0aW9uID0gZGVmaW5pdGlvbiB8fCB7fTtcbiAgdGhpcy5wcm9wZXJ0aWVzID0gW107XG5cbiAgdmFyIGlubmVyVHlwZSA9IGRlZmluaXRpb24uaXRlbXM7XG5cbiAgaWYgKGlubmVyVHlwZSkge1xuICAgIGlmIChpbm5lclR5cGUudHlwZSkge1xuICAgICAgdGhpcy50eXBlID0gaGVscGVycy50eXBlRnJvbUpzb25TY2hlbWEoaW5uZXJUeXBlLnR5cGUsIGlubmVyVHlwZS5mb3JtYXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZiA9IGlubmVyVHlwZS4kcmVmO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuQXJyYXlNb2RlbC5wcm90b3R5cGUuY3JlYXRlSlNPTlNhbXBsZSA9IGZ1bmN0aW9uIChtb2RlbHNUb0lnbm9yZSkge1xuICB2YXIgcmVzdWx0O1xuXG4gIG1vZGVsc1RvSWdub3JlID0gKG1vZGVsc1RvSWdub3JlfHx7fSk7XG5cbiAgaWYgKHRoaXMudHlwZSkge1xuICAgIHJlc3VsdCA9IHRoaXMudHlwZTtcbiAgfSBlbHNlIGlmICh0aGlzLnJlZikge1xuICAgIHZhciBuYW1lID0gaGVscGVycy5zaW1wbGVSZWYodGhpcy5yZWYpO1xuXG4gICAgaWYgKHR5cGVvZiBtb2RlbHNUb0lnbm9yZVtuYW1lXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIG1vZGVsc1RvSWdub3JlW25hbWVdID0gdGhpcztcblxuICAgICAgcmVzdWx0ID0gdGhpcy5tb2RlbHNbbmFtZV0uY3JlYXRlSlNPTlNhbXBsZShtb2RlbHNUb0lnbm9yZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBbIHJlc3VsdCBdO1xufTtcblxuQXJyYXlNb2RlbC5wcm90b3R5cGUuZ2V0U2FtcGxlVmFsdWUgPSBmdW5jdGlvbiAobW9kZWxzVG9JZ25vcmUpIHtcbiAgdmFyIHJlc3VsdDtcblxuICBtb2RlbHNUb0lnbm9yZSA9IChtb2RlbHNUb0lnbm9yZSB8fCB7fSk7XG5cbiAgaWYgKHRoaXMudHlwZSkge1xuICAgIHJlc3VsdCA9IHRoaXMudHlwZTtcbiAgfSBlbHNlIGlmICh0aGlzLnJlZikge1xuICAgIHZhciBuYW1lID0gaGVscGVycy5zaW1wbGVSZWYodGhpcy5yZWYpO1xuXG4gICAgcmVzdWx0ID0gdGhpcy5tb2RlbHNbbmFtZV0uZ2V0U2FtcGxlVmFsdWUobW9kZWxzVG9JZ25vcmUpO1xuICB9XG5cbiAgcmV0dXJuIFsgcmVzdWx0IF07XG59O1xuXG5BcnJheU1vZGVsLnByb3RvdHlwZS5nZXRNb2NrU2lnbmF0dXJlID0gZnVuY3Rpb24gKG1vZGVsc1RvSWdub3JlKSB7XG4gIHZhciBwcm9wZXJ0aWVzU3RyID0gW107XG4gIHZhciBpLCBwcm9wO1xuXG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnByb3BlcnRpZXMubGVuZ3RoOyBpKyspIHtcbiAgICBwcm9wID0gdGhpcy5wcm9wZXJ0aWVzW2ldO1xuICAgIHByb3BlcnRpZXNTdHIucHVzaChwcm9wLnRvU3RyaW5nKCkpO1xuICB9XG5cbiAgdmFyIHN0cm9uZyA9ICc8c3BhbiBjbGFzcz1cInN0cm9uZ1wiPic7XG4gIHZhciBzdHJvbmdDbG9zZSA9ICc8L3NwYW4+JztcbiAgdmFyIGNsYXNzT3BlbiA9IHN0cm9uZyArICdhcnJheScgKyAnIHsnICsgc3Ryb25nQ2xvc2U7XG4gIHZhciBjbGFzc0Nsb3NlID0gc3Ryb25nICsgJ30nICsgc3Ryb25nQ2xvc2U7XG4gIHZhciByZXR1cm5WYWwgPSBjbGFzc09wZW4gKyAnPGRpdj4nICsgcHJvcGVydGllc1N0ci5qb2luKCcsPC9kaXY+PGRpdj4nKSArICc8L2Rpdj4nICsgY2xhc3NDbG9zZTtcblxuICBpZiAoIW1vZGVsc1RvSWdub3JlKSB7XG4gICAgbW9kZWxzVG9JZ25vcmUgPSB7fTtcbiAgfVxuXG4gIG1vZGVsc1RvSWdub3JlW3RoaXMubmFtZV0gPSB0aGlzO1xuXG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnByb3BlcnRpZXMubGVuZ3RoOyBpKyspIHtcbiAgICBwcm9wID0gdGhpcy5wcm9wZXJ0aWVzW2ldO1xuXG4gICAgdmFyIHJlZiA9IHByb3AuJHJlZjtcbiAgICB2YXIgbW9kZWwgPSB0aGlzLm1vZGVsc1tyZWZdO1xuXG4gICAgaWYgKG1vZGVsICYmIHR5cGVvZiBtb2RlbHNUb0lnbm9yZVtyZWZdID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuVmFsID0gcmV0dXJuVmFsICsgKCc8YnI+JyArIG1vZGVsLmdldE1vY2tTaWduYXR1cmUobW9kZWxzVG9JZ25vcmUpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuVmFsO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEFycmF5TW9kZWwgPSByZXF1aXJlKCcuL2FycmF5TW9kZWwnKTtcbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi4vaGVscGVycycpO1xuXG52YXIgUHJvcGVydHkgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChuYW1lLCBvYmosIHJlcXVpcmVkLCBtb2RlbHMpIHtcbiAgdGhpcy5tb2RlbHMgPSBtb2RlbHM7XG4gIHRoaXMuc2NoZW1hID0gb2JqO1xuICB0aGlzLnJlcXVpcmVkID0gcmVxdWlyZWQ7XG5cbiAgaWYgKG9iai4kcmVmKSB7XG4gICAgdGhpcy4kcmVmID0gaGVscGVycy5zaW1wbGVSZWYob2JqLiRyZWYpO1xuICB9IGVsc2UgaWYgKG9iai50eXBlID09PSAnYXJyYXknICYmIG9iai5pdGVtcykge1xuICAgIGlmIChvYmouaXRlbXMuJHJlZikge1xuICAgICAgdGhpcy4kcmVmID0gaGVscGVycy5zaW1wbGVSZWYob2JqLml0ZW1zLiRyZWYpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvYmogPSBvYmouaXRlbXM7XG4gICAgfVxuICB9XG5cbiAgdGhpcy5uYW1lID0gbmFtZTtcbiAgdGhpcy5kZXNjcmlwdGlvbiA9IG9iai5kZXNjcmlwdGlvbjtcbiAgdGhpcy5vYmogPSBvYmo7XG4gIHRoaXMub3B0aW9uYWwgPSB0cnVlO1xuICB0aGlzLm9wdGlvbmFsID0gIXJlcXVpcmVkO1xuICB0aGlzLmRlZmF1bHQgPSBvYmouZGVmYXVsdCB8fCBudWxsO1xuICB0aGlzLmV4YW1wbGUgPSBvYmouZXhhbXBsZSAhPT0gdW5kZWZpbmVkID8gb2JqLmV4YW1wbGUgOiBudWxsO1xuICB0aGlzLmNvbGxlY3Rpb25Gb3JtYXQgPSBvYmouY29sbGVjdGlvbkZvcm1hdCB8fCBudWxsO1xuICB0aGlzLm1heGltdW0gPSBvYmoubWF4aW11bSB8fCBudWxsO1xuICB0aGlzLmV4Y2x1c2l2ZU1heGltdW0gPSBvYmouZXhjbHVzaXZlTWF4aW11bSB8fCBudWxsO1xuICB0aGlzLm1pbmltdW0gPSBvYmoubWluaW11bSB8fCBudWxsO1xuICB0aGlzLmV4Y2x1c2l2ZU1pbmltdW0gPSBvYmouZXhjbHVzaXZlTWluaW11bSB8fCBudWxsO1xuICB0aGlzLm1heExlbmd0aCA9IG9iai5tYXhMZW5ndGggfHwgbnVsbDtcbiAgdGhpcy5taW5MZW5ndGggPSBvYmoubWluTGVuZ3RoIHx8IG51bGw7XG4gIHRoaXMucGF0dGVybiA9IG9iai5wYXR0ZXJuIHx8IG51bGw7XG4gIHRoaXMubWF4SXRlbXMgPSBvYmoubWF4SXRlbXMgfHwgbnVsbDtcbiAgdGhpcy5taW5JdGVtcyA9IG9iai5taW5JdGVtcyB8fCBudWxsO1xuICB0aGlzLnVuaXF1ZUl0ZW1zID0gb2JqLnVuaXF1ZUl0ZW1zIHx8IG51bGw7XG4gIHRoaXNbJ2VudW0nXSA9IG9ialsnZW51bSddIHx8IG51bGw7XG4gIHRoaXMubXVsdGlwbGVPZiA9IG9iai5tdWx0aXBsZU9mIHx8IG51bGw7XG59O1xuXG52YXIgTW9kZWwgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChuYW1lLCBkZWZpbml0aW9uLCBtb2RlbHMpIHtcbiAgdGhpcy5tb2RlbHMgPSBtb2RlbHMgfHwge307XG4gIHRoaXMubmFtZSA9IG5hbWU7XG4gIHRoaXMuZGVmaW5pdGlvbiA9IGRlZmluaXRpb24gfHwge307XG4gIHRoaXMucHJvcGVydGllcyA9IFtdO1xuXG4gIGlmIChkZWZpbml0aW9uLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICByZXR1cm4gbmV3IEFycmF5TW9kZWwoZGVmaW5pdGlvbiwgbW9kZWxzKTtcbiAgfVxuXG4gIHZhciByZXF1aXJlZEZpZWxkcyA9IGRlZmluaXRpb24ucmVxdWlyZWQgfHwgW107XG4gIHZhciBrZXk7XG4gIHZhciBwcm9wcyA9IGRlZmluaXRpb24ucHJvcGVydGllcztcblxuICBpZiAocHJvcHMpIHtcbiAgICBmb3IgKGtleSBpbiBwcm9wcykge1xuICAgICAgdmFyIHJlcXVpcmVkID0gZmFsc2U7XG4gICAgICB2YXIgcHJvcGVydHkgPSBwcm9wc1trZXldO1xuXG4gICAgICBpZiAocmVxdWlyZWRGaWVsZHMuaW5kZXhPZihrZXkpID49IDApIHtcbiAgICAgICAgcmVxdWlyZWQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnByb3BlcnRpZXMucHVzaChuZXcgUHJvcGVydHkoa2V5LCBwcm9wZXJ0eSwgcmVxdWlyZWQsIHRoaXMubW9kZWxzKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5Nb2RlbC5wcm90b3R5cGUuY3JlYXRlSlNPTlNhbXBsZSA9IGZ1bmN0aW9uIChtb2RlbHNUb0lnbm9yZSkge1xuICB2YXIgaSwgcmVzdWx0ID0ge30sIHJlcHJlc2VudGF0aW9ucyA9IHt9O1xuXG4gIG1vZGVsc1RvSWdub3JlID0gKG1vZGVsc1RvSWdub3JlfHx7fSk7XG4gIG1vZGVsc1RvSWdub3JlW3RoaXMubmFtZV0gPSB0aGlzO1xuXG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnByb3BlcnRpZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcHJvcCA9IHRoaXMucHJvcGVydGllc1tpXTtcblxuICAgIHZhciBzYW1wbGUgPSBwcm9wLmdldFNhbXBsZVZhbHVlKG1vZGVsc1RvSWdub3JlLCByZXByZXNlbnRhdGlvbnMpO1xuXG4gICAgcmVzdWx0W3Byb3AubmFtZV0gPSBzYW1wbGU7XG4gIH1cblxuICBkZWxldGUgbW9kZWxzVG9JZ25vcmVbdGhpcy5uYW1lXTtcblxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuTW9kZWwucHJvdG90eXBlLmdldFNhbXBsZVZhbHVlID0gZnVuY3Rpb24gKG1vZGVsc1RvSWdub3JlKSB7XG4gIHZhciBpLCBvYmogPSB7fSwgcmVwcmVzZW50YXRpb25zID0ge307XG5cbiAgZm9yIChpID0gMDsgaSA8IHRoaXMucHJvcGVydGllcy5sZW5ndGg7IGkrKyApIHtcbiAgICB2YXIgcHJvcGVydHkgPSB0aGlzLnByb3BlcnRpZXNbaV07XG5cbiAgICBvYmpbcHJvcGVydHkubmFtZV0gPSBwcm9wZXJ0eS5zYW1wbGVWYWx1ZShmYWxzZSwgbW9kZWxzVG9JZ25vcmUsIHJlcHJlc2VudGF0aW9ucyk7XG4gIH1cblxuICByZXR1cm4gb2JqO1xufTtcblxuTW9kZWwucHJvdG90eXBlLmdldE1vY2tTaWduYXR1cmUgPSBmdW5jdGlvbiAobW9kZWxzVG9JZ25vcmUpIHtcbiAgdmFyIGksIHByb3AsIHByb3BlcnRpZXNTdHIgPSBbXTtcblxuICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5wcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgcHJvcCA9IHRoaXMucHJvcGVydGllc1tpXTtcbiAgICBwcm9wZXJ0aWVzU3RyLnB1c2gocHJvcC50b1N0cmluZygpKTtcbiAgfVxuXG4gIHZhciBzdHJvbmcgPSAnPHNwYW4gY2xhc3M9XCJzdHJvbmdcIj4nO1xuICB2YXIgc3Ryb25nQ2xvc2UgPSAnPC9zcGFuPic7XG4gIHZhciBjbGFzc09wZW4gPSBzdHJvbmcgKyB0aGlzLm5hbWUgKyAnIHsnICsgc3Ryb25nQ2xvc2U7XG4gIHZhciBjbGFzc0Nsb3NlID0gc3Ryb25nICsgJ30nICsgc3Ryb25nQ2xvc2U7XG4gIHZhciByZXR1cm5WYWwgPSBjbGFzc09wZW4gKyAnPGRpdj4nICsgcHJvcGVydGllc1N0ci5qb2luKCcsPC9kaXY+PGRpdj4nKSArICc8L2Rpdj4nICsgY2xhc3NDbG9zZTtcblxuICBpZiAoIW1vZGVsc1RvSWdub3JlKSB7XG4gICAgbW9kZWxzVG9JZ25vcmUgPSB7fTtcbiAgfVxuXG4gIG1vZGVsc1RvSWdub3JlW3RoaXMubmFtZV0gPSB0aGlzO1xuXG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnByb3BlcnRpZXMubGVuZ3RoOyBpKyspIHtcbiAgICBwcm9wID0gdGhpcy5wcm9wZXJ0aWVzW2ldO1xuXG4gICAgdmFyIHJlZiA9IHByb3AuJHJlZjtcbiAgICB2YXIgbW9kZWwgPSB0aGlzLm1vZGVsc1tyZWZdO1xuXG4gICAgaWYgKG1vZGVsICYmIHR5cGVvZiBtb2RlbHNUb0lnbm9yZVttb2RlbC5uYW1lXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVyblZhbCA9IHJldHVyblZhbCArICgnPGJyPicgKyBtb2RlbC5nZXRNb2NrU2lnbmF0dXJlKG1vZGVsc1RvSWdub3JlKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldHVyblZhbDtcbn07XG5cblByb3BlcnR5LnByb3RvdHlwZS5nZXRTYW1wbGVWYWx1ZSA9IGZ1bmN0aW9uIChtb2RlbHNUb0lnbm9yZSwgcmVwcmVzZW50YXRpb25zKSB7XG4gIHJldHVybiB0aGlzLnNhbXBsZVZhbHVlKGZhbHNlLCBtb2RlbHNUb0lnbm9yZSwgcmVwcmVzZW50YXRpb25zKTtcbn07XG5cblByb3BlcnR5LnByb3RvdHlwZS5pc0FycmF5ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgc2NoZW1hID0gdGhpcy5zY2hlbWE7XG5cbiAgaWYgKHNjaGVtYS50eXBlID09PSAnYXJyYXknKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5Qcm9wZXJ0eS5wcm90b3R5cGUuc2FtcGxlVmFsdWUgPSBmdW5jdGlvbiAoaXNBcnJheSwgaWdub3JlZE1vZGVscywgcmVwcmVzZW50YXRpb25zKSB7XG4gIGlzQXJyYXkgPSAoaXNBcnJheSB8fCB0aGlzLmlzQXJyYXkoKSk7XG4gIGlnbm9yZWRNb2RlbHMgPSAoaWdub3JlZE1vZGVscyB8fCB7fSk7XG4gIC8vIHJlcHJlc2VudGF0aW9ucyA9IChyZXByZXNlbnRhdGlvbnMgfHwge30pO1xuXG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIGdldFJlZlZhbHVlID0gZnVuY3Rpb24gKHJlZikge1xuICAgIHZhciByZWZNb2RlbE5hbWUgPSBoZWxwZXJzLnNpbXBsZVJlZihyZWYpO1xuICAgIHZhciByZWZNb2RlbCA9IHNlbGYubW9kZWxzW3JlZk1vZGVsTmFtZV07XG4gICAgdmFyIG91dHB1dDtcblxuICAgIGlmICh0eXBlb2YgcmVwcmVzZW50YXRpb25zW3R5cGVdICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgb3V0cHV0ID0gcmVwcmVzZW50YXRpb25zW3R5cGVdO1xuICAgIH1cblxuICAgIGlmIChyZWZNb2RlbCAmJiB0eXBlb2YgaWdub3JlZE1vZGVsc1t0eXBlXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGlnbm9yZWRNb2RlbHNbdHlwZV0gPSB0aGlzO1xuICAgICAgb3V0cHV0ID0gcmVmTW9kZWwuZ2V0U2FtcGxlVmFsdWUoaWdub3JlZE1vZGVscywgcmVwcmVzZW50YXRpb25zKTtcbiAgICAgIHJlcHJlc2VudGF0aW9uc1t0eXBlXSA9IG91dHB1dDtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0ID0gKHJlcHJlc2VudGF0aW9uc1t0eXBlXSB8fCByZWZNb2RlbE5hbWUpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH07XG5cbiAgdmFyIHR5cGUgPSBoZWxwZXJzLmdldFN0cmluZ1NpZ25hdHVyZSh0aGlzLm9iaiwgdHJ1ZSk7XG4gIHZhciBvdXRwdXQ7XG5cbiAgaWYgKHRoaXMuJHJlZikge1xuICAgIG91dHB1dCA9IGdldFJlZlZhbHVlKHRoaXMuJHJlZik7XG4gIH0gZWxzZSBpZiAodGhpcy5leGFtcGxlKSB7XG4gICAgb3V0cHV0ID0gdGhpcy5leGFtcGxlO1xuICB9IGVsc2UgaWYgKHRoaXMuZGVmYXVsdCkge1xuICAgIG91dHB1dCA9IHRoaXMuZGVmYXVsdDtcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnZGF0ZS10aW1lJykge1xuICAgIG91dHB1dCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnZGF0ZScpIHtcbiAgICBvdXRwdXQgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkuc3BsaXQoJ1QnKVswXTtcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgIG91dHB1dCA9ICdzdHJpbmcnO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdpbnRlZ2VyJykge1xuICAgIG91dHB1dCA9IDA7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2xvbmcnKSB7XG4gICAgb3V0cHV0ID0gMDtcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnZmxvYXQnKSB7XG4gICAgb3V0cHV0ID0gMC4wO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdkb3VibGUnKSB7XG4gICAgb3V0cHV0ID0gMC4wO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdib29sZWFuJykge1xuICAgIG91dHB1dCA9IHRydWU7XG4gIH0gZWxzZSBpZiAodGhpcy5zY2hlbWEuJHJlZikge1xuICAgIG91dHB1dCA9IGdldFJlZlZhbHVlKHRoaXMuc2NoZW1hLiRyZWYpO1xuICB9IGVsc2UgaWYgKHRoaXMuc2NoZW1hLnByb3BlcnRpZXMpIHtcbiAgICBvdXRwdXQgPSBuZXcgTW9kZWwoJ0lubGluZU1vZGVsLScgKyBuZXcgRGF0ZSgpLCB0aGlzLnNjaGVtYSwgdGhpcy5tb2RlbHMpLmdldFNhbXBsZVZhbHVlKCk7XG4gIH0gZWxzZSB7XG4gICAgb3V0cHV0ID0ge307XG4gIH1cblxuICBpZ25vcmVkTW9kZWxzW3R5cGVdID0gb3V0cHV0O1xuXG4gIGlmIChpc0FycmF5KSB7XG4gICAgcmV0dXJuIFtvdXRwdXRdO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBvdXRwdXQ7XG4gIH1cbn07XG5cblByb3BlcnR5LnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHN0ciA9IGhlbHBlcnMuZ2V0U3RyaW5nU2lnbmF0dXJlKHRoaXMub2JqKTtcbiAgdmFyIHN0cm9uZyA9JzxzcGFuIGNsYXNzPVwic3Ryb25nXCI+JztcbiAgdmFyIHN0cm9uZ0Nsb3NlID0gJzwvc3Bhbj4nO1xuICB2YXIgcHJvcGVydGllc1N0ciA9IFtdO1xuICB2YXIgcHJvcDtcblxuICBpZiAoc3RyID09PSAnb2JqZWN0Jykge1xuICAgIGZvciAodmFyIG5hbWUgaW4gdGhpcy5zY2hlbWEucHJvcGVydGllcykge1xuICAgICAgaWYgKHRoaXMuc2NoZW1hLnByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgcHJvcCA9IG5ldyBQcm9wZXJ0eShuYW1lLCB0aGlzLnNjaGVtYS5wcm9wZXJ0aWVzW25hbWVdLCAodGhpcy5zY2hlbWEucmVxdWlyZWQgfHwgW10pLmluZGV4T2YobmFtZSkgPiAtMSwgdGhpcy5tb2RlbHMpO1xuXG4gICAgICAgIHByb3BlcnRpZXNTdHIucHVzaChwcm9wLnRvU3RyaW5nKCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHN0ciA9IHN0cm9uZyArIHRoaXMubmFtZSArICcgeycgKyBzdHJvbmdDbG9zZSArICc8ZGl2PicgKyBwcm9wZXJ0aWVzU3RyLmpvaW4oJyw8L2Rpdj48ZGl2PicpICsgJzwvZGl2PicgKyBzdHJvbmcgKyAnfScgKyBzdHJvbmdDbG9zZTtcbiAgfSBlbHNlIGlmIChzdHIgIT09ICcnKSB7XG4gICAgc3RyID0gJzxzcGFuIGNsYXNzPVwicHJvcE5hbWUgJyArIHRoaXMucmVxdWlyZWQgKyAnXCI+JyArIHRoaXMubmFtZSArICc8L3NwYW4+ICg8c3BhbiBjbGFzcz1cInByb3BUeXBlXCI+JyArIHN0ciArICc8L3NwYW4+JztcblxuICAgIGlmICghdGhpcy5yZXF1aXJlZCkge1xuICAgICAgc3RyICs9ICcsIDxzcGFuIGNsYXNzPVwicHJvcE9wdEtleVwiPm9wdGlvbmFsPC9zcGFuPic7XG4gICAgfVxuXG4gICAgc3RyICs9ICcpJztcbiAgfSBlbHNlIHtcbiAgICBzdHIgPSB0aGlzLm5hbWUgKyAnICgnICsgSlNPTi5zdHJpbmdpZnkodGhpcy5vYmopICsgJyknO1xuICB9XG5cbiAgaWYgKHR5cGVvZiB0aGlzLmRlc2NyaXB0aW9uICE9PSAndW5kZWZpbmVkJykge1xuICAgIHN0ciArPSAnOiAnICsgdGhpcy5kZXNjcmlwdGlvbjtcbiAgfVxuXG4gIGlmICh0aGlzWydlbnVtJ10pIHtcbiAgICBzdHIgKz0gJyA9IDxzcGFuIGNsYXNzPVwicHJvcFZhbHNcIj5bXFwnJyArIHRoaXNbJ2VudW0nXS5qb2luKCdcXCcgb3IgXFwnJykgKyAnXFwnXTwvc3Bhbj4nO1xuICB9XG5cbiAgaWYgKHRoaXMuZGVzY3IpIHtcbiAgICBzdHIgKz0gJzogPHNwYW4gY2xhc3M9XCJwcm9wRGVzY1wiPicgKyB0aGlzLmRlc2NyICsgJzwvc3Bhbj4nO1xuICB9XG5cbiAgdmFyIG9wdGlvbnMgPSAnJztcbiAgdmFyIGlzQXJyYXkgPSB0aGlzLnNjaGVtYS50eXBlID09PSAnYXJyYXknO1xuICB2YXIgdHlwZTtcblxuICBpZiAoaXNBcnJheSkge1xuICAgIGlmICh0aGlzLnNjaGVtYS5pdGVtcykge1xuICAgICAgdHlwZSA9IHRoaXMuc2NoZW1hLml0ZW1zLnR5cGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHR5cGUgPSAnJztcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdHlwZSA9IHRoaXMuc2NoZW1hLnR5cGU7XG4gIH1cblxuICBpZiAodGhpcy5kZWZhdWx0KSB7XG4gICAgb3B0aW9ucyArPSBoZWxwZXJzLm9wdGlvbkh0bWwoJ0RlZmF1bHQnLCB0aGlzLmRlZmF1bHQpO1xuICB9XG5cbiAgc3dpdGNoICh0eXBlKSB7XG4gIGNhc2UgJ3N0cmluZyc6XG4gICAgaWYgKHRoaXMubWluTGVuZ3RoKSB7XG4gICAgICBvcHRpb25zICs9IGhlbHBlcnMub3B0aW9uSHRtbCgnTWluLiBMZW5ndGgnLCB0aGlzLm1pbkxlbmd0aCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMubWF4TGVuZ3RoKSB7XG4gICAgICBvcHRpb25zICs9IGhlbHBlcnMub3B0aW9uSHRtbCgnTWF4LiBMZW5ndGgnLCB0aGlzLm1heExlbmd0aCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucGF0dGVybikge1xuICAgICAgb3B0aW9ucyArPSBoZWxwZXJzLm9wdGlvbkh0bWwoJ1JlZy4gRXhwLicsIHRoaXMucGF0dGVybik7XG4gICAgfVxuICAgIGJyZWFrO1xuICBjYXNlICdpbnRlZ2VyJzpcbiAgY2FzZSAnbnVtYmVyJzpcbiAgICBpZiAodGhpcy5taW5pbXVtKSB7XG4gICAgICBvcHRpb25zICs9IGhlbHBlcnMub3B0aW9uSHRtbCgnTWluLiBWYWx1ZScsIHRoaXMubWluaW11bSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZXhjbHVzaXZlTWluaW11bSkge1xuICAgICAgb3B0aW9ucyArPSBoZWxwZXJzLm9wdGlvbkh0bWwoJ0V4Y2x1c2l2ZSBNaW4uJywgJ3RydWUnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5tYXhpbXVtKSB7XG4gICAgICBvcHRpb25zICs9IGhlbHBlcnMub3B0aW9uSHRtbCgnTWF4LiBWYWx1ZScsIHRoaXMubWF4aW11bSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZXhjbHVzaXZlTWF4aW11bSkge1xuICAgICAgb3B0aW9ucyArPSBoZWxwZXJzLm9wdGlvbkh0bWwoJ0V4Y2x1c2l2ZSBNYXguJywgJ3RydWUnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5tdWx0aXBsZU9mKSB7XG4gICAgICBvcHRpb25zICs9IGhlbHBlcnMub3B0aW9uSHRtbCgnTXVsdGlwbGUgT2YnLCB0aGlzLm11bHRpcGxlT2YpO1xuICAgIH1cblxuICAgIGJyZWFrO1xuICB9XG5cbiAgaWYgKGlzQXJyYXkpIHtcbiAgICBpZiAodGhpcy5taW5JdGVtcykge1xuICAgICAgb3B0aW9ucyArPSBoZWxwZXJzLm9wdGlvbkh0bWwoJ01pbi4gSXRlbXMnLCB0aGlzLm1pbkl0ZW1zKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5tYXhJdGVtcykge1xuICAgICAgb3B0aW9ucyArPSBoZWxwZXJzLm9wdGlvbkh0bWwoJ01heC4gSXRlbXMnLCB0aGlzLm1heEl0ZW1zKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy51bmlxdWVJdGVtcykge1xuICAgICAgb3B0aW9ucyArPSBoZWxwZXJzLm9wdGlvbkh0bWwoJ1VuaXF1ZSBJdGVtcycsICd0cnVlJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY29sbGVjdGlvbkZvcm1hdCkge1xuICAgICAgb3B0aW9ucyArPSBoZWxwZXJzLm9wdGlvbkh0bWwoJ0NvbGwuIEZvcm1hdCcsIHRoaXMuY29sbGVjdGlvbkZvcm1hdCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHRoaXNbJ2VudW0nXSkge1xuICAgIHZhciBlbnVtU3RyaW5nO1xuXG4gICAgaWYgKHR5cGUgPT09ICdudW1iZXInIHx8IHR5cGUgPT09ICdpbnRlZ2VyJykge1xuICAgICAgZW51bVN0cmluZyA9IHRoaXNbJ2VudW0nXS5qb2luKCcsICcpO1xuICAgIH0gZWxzZSB7XG4gICAgICBlbnVtU3RyaW5nID0gJ1wiJyArIHRoaXNbJ2VudW0nXS5qb2luKCdcIiwgXCInKSArICdcIic7XG4gICAgfVxuXG4gICAgb3B0aW9ucyArPSBoZWxwZXJzLm9wdGlvbkh0bWwoJ0VudW0nLCBlbnVtU3RyaW5nKTtcbiAgfVxuXG4gIGlmIChvcHRpb25zLmxlbmd0aCA+IDApIHtcbiAgICBzdHIgPSAnPHNwYW4gY2xhc3M9XCJwcm9wV3JhcFwiPicgKyBzdHIgKyAnPHRhYmxlIGNsYXNzPVwib3B0aW9uc1dyYXBwZXJcIj48dHI+PHRoIGNvbHNwYW49XCIyXCI+JyArIHRoaXMubmFtZSArICc8L3RoPjwvdHI+JyArIG9wdGlvbnMgKyAnPC90YWJsZT48L3NwYW4+JztcbiAgfVxuXG4gIHJldHVybiBzdHI7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXJyYXlNb2RlbCA9IHJlcXVpcmUoJy4vYXJyYXlNb2RlbCcpO1xudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuLi9oZWxwZXJzJyk7XG52YXIgTW9kZWwgPSByZXF1aXJlKCcuL21vZGVsJyk7XG52YXIgU3dhZ2dlckh0dHAgPSByZXF1aXJlKCcuLi9odHRwJyk7XG5cbnZhciBPcGVyYXRpb24gPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwYXJlbnQsIHNjaGVtZSwgb3BlcmF0aW9uSWQsIGh0dHBNZXRob2QsIHBhdGgsIGFyZ3MsIGRlZmluaXRpb25zLCBtb2RlbHMsIGNsaWVudEF1dGhvcml6YXRpb25zKSB7XG4gIHZhciBlcnJvcnMgPSBbXTtcblxuICBwYXJlbnQgPSBwYXJlbnQgfHwge307XG4gIGFyZ3MgPSBhcmdzIHx8IHt9O1xuXG4gIHRoaXMuYXV0aG9yaXphdGlvbnMgPSBhcmdzLnNlY3VyaXR5O1xuICB0aGlzLmJhc2VQYXRoID0gcGFyZW50LmJhc2VQYXRoIHx8ICcvJztcbiAgdGhpcy5jbGllbnRBdXRob3JpemF0aW9ucyA9IGNsaWVudEF1dGhvcml6YXRpb25zO1xuICB0aGlzLmNvbnN1bWVzID0gYXJncy5jb25zdW1lcztcbiAgdGhpcy5kZXByZWNhdGVkID0gYXJncy5kZXByZWNhdGVkO1xuICB0aGlzLmRlc2NyaXB0aW9uID0gYXJncy5kZXNjcmlwdGlvbjtcbiAgdGhpcy5ob3N0ID0gcGFyZW50Lmhvc3QgfHwgJ2xvY2FsaG9zdCc7XG4gIHRoaXMubWV0aG9kID0gKGh0dHBNZXRob2QgfHwgZXJyb3JzLnB1c2goJ09wZXJhdGlvbiAnICsgb3BlcmF0aW9uSWQgKyAnIGlzIG1pc3NpbmcgbWV0aG9kLicpKTtcbiAgdGhpcy5tb2RlbHMgPSBtb2RlbHMgfHwge307XG4gIHRoaXMubmlja25hbWUgPSAob3BlcmF0aW9uSWQgfHwgZXJyb3JzLnB1c2goJ09wZXJhdGlvbnMgbXVzdCBoYXZlIGEgbmlja25hbWUuJykpO1xuICB0aGlzLm9wZXJhdGlvbiA9IGFyZ3M7XG4gIHRoaXMub3BlcmF0aW9ucyA9IHt9O1xuICB0aGlzLnBhcmFtZXRlcnMgPSBhcmdzICE9PSBudWxsID8gKGFyZ3MucGFyYW1ldGVycyB8fCBbXSkgOiB7fTtcbiAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gIHRoaXMucGF0aCA9IChwYXRoIHx8IGVycm9ycy5wdXNoKCdPcGVyYXRpb24gJyArIHRoaXMubmlja25hbWUgKyAnIGlzIG1pc3NpbmcgcGF0aC4nKSk7XG4gIHRoaXMucHJvZHVjZXMgPSBhcmdzLnByb2R1Y2VzO1xuICB0aGlzLnJlc3BvbnNlcyA9IChhcmdzLnJlc3BvbnNlcyB8fCB7fSk7XG4gIHRoaXMuc2NoZW1lID0gc2NoZW1lIHx8IHBhcmVudC5zY2hlbWUgfHwgJ2h0dHAnO1xuICB0aGlzLnNjaGVtZXMgPSBwYXJlbnQuc2NoZW1lcztcbiAgdGhpcy5zZWN1cml0eSA9IGFyZ3Muc2VjdXJpdHk7XG4gIHRoaXMuc3VtbWFyeSA9IGFyZ3Muc3VtbWFyeSB8fCAnJztcbiAgdGhpcy50eXBlID0gbnVsbDtcbiAgdGhpcy51c2VKUXVlcnkgPSBwYXJlbnQudXNlSlF1ZXJ5O1xuXG4gIGlmICh0eXBlb2YgdGhpcy5kZXByZWNhdGVkID09PSAnc3RyaW5nJykge1xuICAgIHN3aXRjaCh0aGlzLmRlcHJlY2F0ZWQudG9Mb3dlckNhc2UoKSkge1xuICAgICAgY2FzZSAndHJ1ZSc6IGNhc2UgJ3llcyc6IGNhc2UgJzEnOiB7XG4gICAgICAgIHRoaXMuZGVwcmVjYXRlZCA9IHRydWU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBjYXNlICdmYWxzZSc6IGNhc2UgJ25vJzogY2FzZSAnMCc6IGNhc2UgbnVsbDoge1xuICAgICAgICB0aGlzLmRlcHJlY2F0ZWQgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGRlZmF1bHQ6IHRoaXMuZGVwcmVjYXRlZCA9IEJvb2xlYW4odGhpcy5kZXByZWNhdGVkKTtcbiAgICB9XG4gIH1cblxuICB2YXIgaSwgbW9kZWw7XG5cbiAgaWYgKGRlZmluaXRpb25zKSB7XG4gICAgLy8gYWRkIHRvIGdsb2JhbCBtb2RlbHNcbiAgICB2YXIga2V5O1xuXG4gICAgZm9yIChrZXkgaW4gdGhpcy5kZWZpbml0aW9ucykge1xuICAgICAgbW9kZWwgPSBuZXcgTW9kZWwoa2V5LCBkZWZpbml0aW9uc1trZXldLCB0aGlzLm1vZGVscyk7XG5cbiAgICAgIGlmIChtb2RlbCkge1xuICAgICAgICB0aGlzLm1vZGVsc1trZXldID0gbW9kZWw7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnBhcmFtZXRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFyYW0gPSB0aGlzLnBhcmFtZXRlcnNbaV07XG5cbiAgICBpZiAocGFyYW0udHlwZSA9PT0gJ2FycmF5Jykge1xuICAgICAgcGFyYW0uaXNMaXN0ID0gdHJ1ZTtcbiAgICAgIHBhcmFtLmFsbG93TXVsdGlwbGUgPSB0cnVlO1xuICAgIH1cblxuICAgIHZhciBpbm5lclR5cGUgPSB0aGlzLmdldFR5cGUocGFyYW0pO1xuXG4gICAgaWYgKGlubmVyVHlwZSAmJiBpbm5lclR5cGUudG9TdHJpbmcoKS50b0xvd2VyQ2FzZSgpID09PSAnYm9vbGVhbicpIHtcbiAgICAgIHBhcmFtLmFsbG93YWJsZVZhbHVlcyA9IHt9O1xuICAgICAgcGFyYW0uaXNMaXN0ID0gdHJ1ZTtcbiAgICAgIHBhcmFtWydlbnVtJ10gPSBbJ3RydWUnLCAnZmFsc2UnXTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIHBhcmFtWydlbnVtJ10gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB2YXIgaWQ7XG5cbiAgICAgIHBhcmFtLmFsbG93YWJsZVZhbHVlcyA9IHt9O1xuICAgICAgcGFyYW0uYWxsb3dhYmxlVmFsdWVzLnZhbHVlcyA9IFtdO1xuICAgICAgcGFyYW0uYWxsb3dhYmxlVmFsdWVzLmRlc2NyaXB0aXZlVmFsdWVzID0gW107XG5cbiAgICAgIGZvciAoaWQgPSAwOyBpZCA8IHBhcmFtWydlbnVtJ10ubGVuZ3RoOyBpZCsrKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHBhcmFtWydlbnVtJ11baWRdO1xuICAgICAgICB2YXIgaXNEZWZhdWx0ID0gKHZhbHVlID09PSBwYXJhbS5kZWZhdWx0KSA/IHRydWUgOiBmYWxzZTtcblxuICAgICAgICBwYXJhbS5hbGxvd2FibGVWYWx1ZXMudmFsdWVzLnB1c2godmFsdWUpO1xuICAgICAgICBwYXJhbS5hbGxvd2FibGVWYWx1ZXMuZGVzY3JpcHRpdmVWYWx1ZXMucHVzaCh7dmFsdWUgOiB2YWx1ZSwgaXNEZWZhdWx0OiBpc0RlZmF1bHR9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocGFyYW0udHlwZSA9PT0gJ2FycmF5Jykge1xuICAgICAgaW5uZXJUeXBlID0gW2lubmVyVHlwZV07XG5cbiAgICAgIGlmICh0eXBlb2YgcGFyYW0uYWxsb3dhYmxlVmFsdWVzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAvLyBjYW4ndCBzaG93IGFzIGEgbGlzdCBpZiBubyB2YWx1ZXMgdG8gc2VsZWN0IGZyb21cbiAgICAgICAgZGVsZXRlIHBhcmFtLmlzTGlzdDtcbiAgICAgICAgZGVsZXRlIHBhcmFtLmFsbG93TXVsdGlwbGU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcGFyYW0uc2lnbmF0dXJlID0gdGhpcy5nZXRNb2RlbFNpZ25hdHVyZShpbm5lclR5cGUsIHRoaXMubW9kZWxzKS50b1N0cmluZygpO1xuICAgIHBhcmFtLnNhbXBsZUpTT04gPSB0aGlzLmdldE1vZGVsU2FtcGxlSlNPTihpbm5lclR5cGUsIHRoaXMubW9kZWxzKTtcbiAgICBwYXJhbS5yZXNwb25zZUNsYXNzU2lnbmF0dXJlID0gcGFyYW0uc2lnbmF0dXJlO1xuICB9XG5cbiAgdmFyIGRlZmF1bHRSZXNwb25zZUNvZGUsIHJlc3BvbnNlLCByZXNwb25zZXMgPSB0aGlzLnJlc3BvbnNlcztcblxuICBpZiAocmVzcG9uc2VzWycyMDAnXSkge1xuICAgIHJlc3BvbnNlID0gcmVzcG9uc2VzWycyMDAnXTtcbiAgICBkZWZhdWx0UmVzcG9uc2VDb2RlID0gJzIwMCc7XG4gIH0gZWxzZSBpZiAocmVzcG9uc2VzWycyMDEnXSkge1xuICAgIHJlc3BvbnNlID0gcmVzcG9uc2VzWycyMDEnXTtcbiAgICBkZWZhdWx0UmVzcG9uc2VDb2RlID0gJzIwMSc7XG4gIH0gZWxzZSBpZiAocmVzcG9uc2VzWycyMDInXSkge1xuICAgIHJlc3BvbnNlID0gcmVzcG9uc2VzWycyMDInXTtcbiAgICBkZWZhdWx0UmVzcG9uc2VDb2RlID0gJzIwMic7XG4gIH0gZWxzZSBpZiAocmVzcG9uc2VzWycyMDMnXSkge1xuICAgIHJlc3BvbnNlID0gcmVzcG9uc2VzWycyMDMnXTtcbiAgICBkZWZhdWx0UmVzcG9uc2VDb2RlID0gJzIwMyc7XG4gIH0gZWxzZSBpZiAocmVzcG9uc2VzWycyMDQnXSkge1xuICAgIHJlc3BvbnNlID0gcmVzcG9uc2VzWycyMDQnXTtcbiAgICBkZWZhdWx0UmVzcG9uc2VDb2RlID0gJzIwNCc7XG4gIH0gZWxzZSBpZiAocmVzcG9uc2VzWycyMDUnXSkge1xuICAgIHJlc3BvbnNlID0gcmVzcG9uc2VzWycyMDUnXTtcbiAgICBkZWZhdWx0UmVzcG9uc2VDb2RlID0gJzIwNSc7XG4gIH0gZWxzZSBpZiAocmVzcG9uc2VzWycyMDYnXSkge1xuICAgIHJlc3BvbnNlID0gcmVzcG9uc2VzWycyMDYnXTtcbiAgICBkZWZhdWx0UmVzcG9uc2VDb2RlID0gJzIwNic7XG4gIH0gZWxzZSBpZiAocmVzcG9uc2VzWydkZWZhdWx0J10pIHtcbiAgICByZXNwb25zZSA9IHJlc3BvbnNlc1snZGVmYXVsdCddO1xuICAgIGRlZmF1bHRSZXNwb25zZUNvZGUgPSAnZGVmYXVsdCc7XG4gIH1cblxuICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2Uuc2NoZW1hKSB7XG4gICAgdmFyIHJlc29sdmVkTW9kZWwgPSB0aGlzLnJlc29sdmVNb2RlbChyZXNwb25zZS5zY2hlbWEsIGRlZmluaXRpb25zKTtcblxuICAgIGRlbGV0ZSByZXNwb25zZXNbZGVmYXVsdFJlc3BvbnNlQ29kZV07XG5cbiAgICBpZiAocmVzb2x2ZWRNb2RlbCkge1xuICAgICAgdGhpcy5zdWNjZXNzUmVzcG9uc2UgPSB7fTtcbiAgICAgIHRoaXMuc3VjY2Vzc1Jlc3BvbnNlW2RlZmF1bHRSZXNwb25zZUNvZGVdID0gcmVzb2x2ZWRNb2RlbDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdWNjZXNzUmVzcG9uc2UgPSB7fTtcbiAgICAgIHRoaXMuc3VjY2Vzc1Jlc3BvbnNlW2RlZmF1bHRSZXNwb25zZUNvZGVdID0gcmVzcG9uc2Uuc2NoZW1hLnR5cGU7XG4gICAgfVxuXG4gICAgdGhpcy50eXBlID0gcmVzcG9uc2U7XG4gIH1cblxuICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICBpZiAodGhpcy5yZXNvdXJjZSAmJiB0aGlzLnJlc291cmNlLmFwaSAmJiB0aGlzLnJlc291cmNlLmFwaS5mYWlsKSB7XG4gICAgICB0aGlzLnJlc291cmNlLmFwaS5mYWlsKGVycm9ycyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLmdldFR5cGUgPSBmdW5jdGlvbiAocGFyYW0pIHtcbiAgdmFyIHR5cGUgPSBwYXJhbS50eXBlO1xuICB2YXIgZm9ybWF0ID0gcGFyYW0uZm9ybWF0O1xuICB2YXIgaXNBcnJheSA9IGZhbHNlO1xuICB2YXIgc3RyO1xuXG4gIGlmICh0eXBlID09PSAnaW50ZWdlcicgJiYgZm9ybWF0ID09PSAnaW50MzInKSB7XG4gICAgc3RyID0gJ2ludGVnZXInO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdpbnRlZ2VyJyAmJiBmb3JtYXQgPT09ICdpbnQ2NCcpIHtcbiAgICBzdHIgPSAnbG9uZyc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2ludGVnZXInKSB7XG4gICAgc3RyID0gJ2ludGVnZXInO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKGZvcm1hdCA9PT0gJ2RhdGUtdGltZScpIHtcbiAgICAgIHN0ciA9ICdkYXRlLXRpbWUnO1xuICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSAnZGF0ZScpIHtcbiAgICAgIHN0ciA9ICdkYXRlJztcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gJ3N0cmluZyc7XG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdudW1iZXInICYmIGZvcm1hdCA9PT0gJ2Zsb2F0Jykge1xuICAgIHN0ciA9ICdmbG9hdCc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ251bWJlcicgJiYgZm9ybWF0ID09PSAnZG91YmxlJykge1xuICAgIHN0ciA9ICdkb3VibGUnO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgc3RyID0gJ2RvdWJsZSc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgc3RyID0gJ2Jvb2xlYW4nO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdhcnJheScpIHtcbiAgICBpc0FycmF5ID0gdHJ1ZTtcblxuICAgIGlmIChwYXJhbS5pdGVtcykge1xuICAgICAgc3RyID0gdGhpcy5nZXRUeXBlKHBhcmFtLml0ZW1zKTtcbiAgICB9XG4gIH1cblxuICBpZiAocGFyYW0uJHJlZikge1xuICAgIHN0ciA9IHBhcmFtLiRyZWY7XG4gIH1cblxuICB2YXIgc2NoZW1hID0gcGFyYW0uc2NoZW1hO1xuXG4gIGlmIChzY2hlbWEpIHtcbiAgICB2YXIgcmVmID0gc2NoZW1hLiRyZWY7XG5cbiAgICBpZiAocmVmKSB7XG4gICAgICByZWYgPSBoZWxwZXJzLnNpbXBsZVJlZihyZWYpO1xuXG4gICAgICBpZiAoaXNBcnJheSkge1xuICAgICAgICByZXR1cm4gWyByZWYgXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiByZWY7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmdldFR5cGUoc2NoZW1hKTtcbiAgICB9XG4gIH1cbiAgaWYgKGlzQXJyYXkpIHtcbiAgICByZXR1cm4gWyBzdHIgXTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gc3RyO1xuICB9XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLnJlc29sdmVNb2RlbCA9IGZ1bmN0aW9uIChzY2hlbWEsIGRlZmluaXRpb25zKSB7XG4gIGlmICh0eXBlb2Ygc2NoZW1hLiRyZWYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgdmFyIHJlZiA9IHNjaGVtYS4kcmVmO1xuXG4gICAgaWYgKHJlZi5pbmRleE9mKCcjL2RlZmluaXRpb25zLycpID09PSAwKSB7XG4gICAgICByZWYgPSByZWYuc3Vic3RyaW5nKCcjL2RlZmluaXRpb25zLycubGVuZ3RoKTtcbiAgICB9XG5cbiAgICBpZiAoZGVmaW5pdGlvbnNbcmVmXSkge1xuICAgICAgcmV0dXJuIG5ldyBNb2RlbChyZWYsIGRlZmluaXRpb25zW3JlZl0sIHRoaXMubW9kZWxzKTtcbiAgICB9XG4gIH1cblxuICBpZiAoc2NoZW1hLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICByZXR1cm4gbmV3IEFycmF5TW9kZWwoc2NoZW1hLCB0aGlzLm1vZGVscyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUuaGVscCA9IGZ1bmN0aW9uIChkb250UHJpbnQpIHtcbiAgdmFyIG91dCA9IHRoaXMubmlja25hbWUgKyAnOiAnICsgdGhpcy5zdW1tYXJ5ICsgJ1xcbic7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnBhcmFtZXRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFyYW0gPSB0aGlzLnBhcmFtZXRlcnNbaV07XG4gICAgdmFyIHR5cGVJbmZvID0gcGFyYW0uc2lnbmF0dXJlO1xuXG4gICAgb3V0ICs9ICdcXG4gICogJyArIHBhcmFtLm5hbWUgKyAnICgnICsgdHlwZUluZm8gKyAnKTogJyArIHBhcmFtLmRlc2NyaXB0aW9uO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBkb250UHJpbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgaGVscGVycy5sb2cob3V0KTtcbiAgfVxuXG4gIHJldHVybiBvdXQ7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLmdldE1vZGVsU2lnbmF0dXJlID0gZnVuY3Rpb24gKHR5cGUsIGRlZmluaXRpb25zKSB7XG4gIHZhciBpc1ByaW1pdGl2ZSwgbGlzdFR5cGU7XG5cbiAgaWYgKHR5cGUgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIGxpc3RUeXBlID0gdHJ1ZTtcbiAgICB0eXBlID0gdHlwZVswXTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgdHlwZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICB0eXBlID0gJ3VuZGVmaW5lZCc7XG4gIH1cblxuICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICBpc1ByaW1pdGl2ZSA9IHRydWU7XG4gIH0gZWxzZSB7XG4gICAgaXNQcmltaXRpdmUgPSAobGlzdFR5cGUgJiYgZGVmaW5pdGlvbnNbbGlzdFR5cGVdKSB8fCAoZGVmaW5pdGlvbnNbdHlwZV0pID8gZmFsc2UgOiB0cnVlO1xuICB9XG5cbiAgaWYgKGlzUHJpbWl0aXZlKSB7XG4gICAgaWYgKGxpc3RUeXBlKSB7XG4gICAgICByZXR1cm4gJ0FycmF5WycgKyB0eXBlICsgJ10nO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdHlwZS50b1N0cmluZygpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAobGlzdFR5cGUpIHtcbiAgICAgIHJldHVybiAnQXJyYXlbJyArIGRlZmluaXRpb25zW3R5cGVdLmdldE1vY2tTaWduYXR1cmUoKSArICddJztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRlZmluaXRpb25zW3R5cGVdLmdldE1vY2tTaWduYXR1cmUoKTtcbiAgICB9XG4gIH1cbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUuc3VwcG9ydEhlYWRlclBhcmFtcyA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRydWU7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLnN1cHBvcnRlZFN1Ym1pdE1ldGhvZHMgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLnBhcmVudC5zdXBwb3J0ZWRTdWJtaXRNZXRob2RzO1xufTtcblxuT3BlcmF0aW9uLnByb3RvdHlwZS5nZXRIZWFkZXJQYXJhbXMgPSBmdW5jdGlvbiAoYXJncykge1xuICB2YXIgaGVhZGVycyA9IHRoaXMuc2V0Q29udGVudFR5cGVzKGFyZ3MsIHt9KTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucGFyYW1ldGVycy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwYXJhbSA9IHRoaXMucGFyYW1ldGVyc1tpXTtcblxuICAgIGlmICh0eXBlb2YgYXJnc1twYXJhbS5uYW1lXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGlmIChwYXJhbS5pbiA9PT0gJ2hlYWRlcicpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJnc1twYXJhbS5uYW1lXTtcblxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICBoZWFkZXJzW3BhcmFtLm5hbWVdID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGhlYWRlcnM7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLnVybGlmeSA9IGZ1bmN0aW9uIChhcmdzKSB7XG4gIHZhciBmb3JtUGFyYW1zID0ge307XG4gIHZhciByZXF1ZXN0VXJsID0gdGhpcy5wYXRoO1xuICB2YXIgcXVlcnlzdHJpbmcgPSAnJzsgLy8gZ3JhYiBwYXJhbXMgZnJvbSB0aGUgYXJncywgYnVpbGQgdGhlIHF1ZXJ5c3RyaW5nIGFsb25nIHRoZSB3YXlcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucGFyYW1ldGVycy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwYXJhbSA9IHRoaXMucGFyYW1ldGVyc1tpXTtcblxuICAgIGlmICh0eXBlb2YgYXJnc1twYXJhbS5uYW1lXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGlmIChwYXJhbS5pbiA9PT0gJ3BhdGgnKSB7XG4gICAgICAgIHZhciByZWcgPSBuZXcgUmVnRXhwKCdcXHsnICsgcGFyYW0ubmFtZSArICdcXH0nLCAnZ2knKTtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJnc1twYXJhbS5uYW1lXTtcblxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICB2YWx1ZSA9IHRoaXMuZW5jb2RlUGF0aENvbGxlY3Rpb24ocGFyYW0uY29sbGVjdGlvbkZvcm1hdCwgcGFyYW0ubmFtZSwgdmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlID0gdGhpcy5lbmNvZGVQYXRoUGFyYW0odmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVxdWVzdFVybCA9IHJlcXVlc3RVcmwucmVwbGFjZShyZWcsIHZhbHVlKTtcbiAgICAgIH0gZWxzZSBpZiAocGFyYW0uaW4gPT09ICdxdWVyeScgJiYgdHlwZW9mIGFyZ3NbcGFyYW0ubmFtZV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGlmIChxdWVyeXN0cmluZyA9PT0gJycpIHtcbiAgICAgICAgICBxdWVyeXN0cmluZyArPSAnPyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcXVlcnlzdHJpbmcgKz0gJyYnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBwYXJhbS5jb2xsZWN0aW9uRm9ybWF0ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHZhciBxcCA9IGFyZ3NbcGFyYW0ubmFtZV07XG5cbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShxcCkpIHtcbiAgICAgICAgICAgIHF1ZXJ5c3RyaW5nICs9IHRoaXMuZW5jb2RlUXVlcnlDb2xsZWN0aW9uKHBhcmFtLmNvbGxlY3Rpb25Gb3JtYXQsIHBhcmFtLm5hbWUsIHFwKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcXVlcnlzdHJpbmcgKz0gdGhpcy5lbmNvZGVRdWVyeVBhcmFtKHBhcmFtLm5hbWUpICsgJz0nICsgdGhpcy5lbmNvZGVRdWVyeVBhcmFtKGFyZ3NbcGFyYW0ubmFtZV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBxdWVyeXN0cmluZyArPSB0aGlzLmVuY29kZVF1ZXJ5UGFyYW0ocGFyYW0ubmFtZSkgKyAnPScgKyB0aGlzLmVuY29kZVF1ZXJ5UGFyYW0oYXJnc1twYXJhbS5uYW1lXSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAocGFyYW0uaW4gPT09ICdmb3JtRGF0YScpIHtcbiAgICAgICAgZm9ybVBhcmFtc1twYXJhbS5uYW1lXSA9IGFyZ3NbcGFyYW0ubmFtZV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdmFyIHVybCA9IHRoaXMuc2NoZW1lICsgJzovLycgKyB0aGlzLmhvc3Q7XG5cbiAgaWYgKHRoaXMuYmFzZVBhdGggIT09ICcvJykge1xuICAgIHVybCArPSB0aGlzLmJhc2VQYXRoO1xuICB9XG5cbiAgcmV0dXJuIHVybCArIHJlcXVlc3RVcmwgKyBxdWVyeXN0cmluZztcbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUuZ2V0TWlzc2luZ1BhcmFtcyA9IGZ1bmN0aW9uIChhcmdzKSB7XG4gIHZhciBtaXNzaW5nUGFyYW1zID0gW107IC8vIGNoZWNrIHJlcXVpcmVkIHBhcmFtcywgdHJhY2sgdGhlIG9uZXMgdGhhdCBhcmUgbWlzc2luZ1xuICB2YXIgaTtcblxuICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5wYXJhbWV0ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHBhcmFtID0gdGhpcy5wYXJhbWV0ZXJzW2ldO1xuXG4gICAgaWYgKHBhcmFtLnJlcXVpcmVkID09PSB0cnVlKSB7XG4gICAgICBpZiAodHlwZW9mIGFyZ3NbcGFyYW0ubmFtZV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIG1pc3NpbmdQYXJhbXMgPSBwYXJhbS5uYW1lO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtaXNzaW5nUGFyYW1zO1xufTtcblxuT3BlcmF0aW9uLnByb3RvdHlwZS5nZXRCb2R5ID0gZnVuY3Rpb24gKGhlYWRlcnMsIGFyZ3MsIG9wdHMpIHtcbiAgdmFyIGZvcm1QYXJhbXMgPSB7fSwgYm9keSwga2V5LCB2YWx1ZTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucGFyYW1ldGVycy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwYXJhbSA9IHRoaXMucGFyYW1ldGVyc1tpXTtcblxuICAgIGlmICh0eXBlb2YgYXJnc1twYXJhbS5uYW1lXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGlmIChwYXJhbS5pbiA9PT0gJ2JvZHknKSB7XG4gICAgICAgIGJvZHkgPSBhcmdzW3BhcmFtLm5hbWVdO1xuICAgICAgfSBlbHNlIGlmIChwYXJhbS5pbiA9PT0gJ2Zvcm1EYXRhJykge1xuICAgICAgICBmb3JtUGFyYW1zW3BhcmFtLm5hbWVdID0gYXJnc1twYXJhbS5uYW1lXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBoYW5kbGUgZm9ybSBwYXJhbXNcbiAgaWYgKGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddID09PSAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJykge1xuICAgIHZhciBlbmNvZGVkID0gJyc7XG5cbiAgICBmb3IgKGtleSBpbiBmb3JtUGFyYW1zKSB7XG4gICAgICB2YWx1ZSA9IGZvcm1QYXJhbXNba2V5XTtcblxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgaWYgKGVuY29kZWQgIT09ICcnKSB7XG4gICAgICAgICAgZW5jb2RlZCArPSAnJic7XG4gICAgICAgIH1cblxuICAgICAgICBlbmNvZGVkICs9IGVuY29kZVVSSUNvbXBvbmVudChrZXkpICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBib2R5ID0gZW5jb2RlZDtcbiAgfSBlbHNlIGlmIChoZWFkZXJzWydDb250ZW50LVR5cGUnXSAmJiBoZWFkZXJzWydDb250ZW50LVR5cGUnXS5pbmRleE9mKCdtdWx0aXBhcnQvZm9ybS1kYXRhJykgPj0gMCkge1xuICAgIGlmIChvcHRzLnVzZUpRdWVyeSkge1xuICAgICAgdmFyIGJvZHlQYXJhbSA9IG5ldyBGb3JtRGF0YSgpO1xuXG4gICAgICBib2R5UGFyYW0udHlwZSA9ICdmb3JtRGF0YSc7XG5cbiAgICAgIGZvciAoa2V5IGluIGZvcm1QYXJhbXMpIHtcbiAgICAgICAgdmFsdWUgPSBhcmdzW2tleV07XG5cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAvLyByZXF1aXJlZCBmb3IganF1ZXJ5IGZpbGUgdXBsb2FkXG4gICAgICAgICAgaWYgKHZhbHVlLnR5cGUgPT09ICdmaWxlJyAmJiB2YWx1ZS52YWx1ZSkge1xuICAgICAgICAgICAgZGVsZXRlIGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddO1xuXG4gICAgICAgICAgICBib2R5UGFyYW0uYXBwZW5kKGtleSwgdmFsdWUudmFsdWUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBib2R5UGFyYW0uYXBwZW5kKGtleSwgdmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBib2R5ID0gYm9keVBhcmFtO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBib2R5O1xufTtcblxuLyoqXG4gKiBnZXRzIHNhbXBsZSByZXNwb25zZSBmb3IgYSBzaW5nbGUgb3BlcmF0aW9uXG4gKiovXG5PcGVyYXRpb24ucHJvdG90eXBlLmdldE1vZGVsU2FtcGxlSlNPTiA9IGZ1bmN0aW9uICh0eXBlLCBtb2RlbHMpIHtcbiAgdmFyIGlzUHJpbWl0aXZlLCBsaXN0VHlwZSwgc2FtcGxlSnNvbjtcblxuICBsaXN0VHlwZSA9ICh0eXBlIGluc3RhbmNlb2YgQXJyYXkpO1xuICBpc1ByaW1pdGl2ZSA9IG1vZGVsc1t0eXBlXSA/IGZhbHNlIDogdHJ1ZTtcbiAgc2FtcGxlSnNvbiA9IGlzUHJpbWl0aXZlID8gdm9pZCAwIDogbW9kZWxzW3R5cGVdLmNyZWF0ZUpTT05TYW1wbGUoKTtcblxuICBpZiAoc2FtcGxlSnNvbikge1xuICAgIHNhbXBsZUpzb24gPSBsaXN0VHlwZSA/IFtzYW1wbGVKc29uXSA6IHNhbXBsZUpzb247XG5cbiAgICBpZiAodHlwZW9mIHNhbXBsZUpzb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gc2FtcGxlSnNvbjtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBzYW1wbGVKc29uID09PSAnb2JqZWN0Jykge1xuICAgICAgdmFyIHQgPSBzYW1wbGVKc29uO1xuXG4gICAgICBpZiAoc2FtcGxlSnNvbiBpbnN0YW5jZW9mIEFycmF5ICYmIHNhbXBsZUpzb24ubGVuZ3RoID4gMCkge1xuICAgICAgICB0ID0gc2FtcGxlSnNvblswXTtcbiAgICAgIH1cblxuICAgICAgaWYgKHQubm9kZU5hbWUpIHtcbiAgICAgICAgdmFyIHhtbFN0cmluZyA9IG5ldyBYTUxTZXJpYWxpemVyKCkuc2VyaWFsaXplVG9TdHJpbmcodCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0WG1sKHhtbFN0cmluZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoc2FtcGxlSnNvbiwgbnVsbCwgMik7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzYW1wbGVKc29uO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBsZWdhY3kgYmluZGluZ1xuICoqL1xuT3BlcmF0aW9uLnByb3RvdHlwZS5kbyA9IGZ1bmN0aW9uIChhcmdzLCBvcHRzLCBjYWxsYmFjaywgZXJyb3IsIHBhcmVudCkge1xuICByZXR1cm4gdGhpcy5leGVjdXRlKGFyZ3MsIG9wdHMsIGNhbGxiYWNrLCBlcnJvciwgcGFyZW50KTtcbn07XG5cbi8qKlxuICogZXhlY3V0ZXMgYW4gb3BlcmF0aW9uXG4gKiovXG5PcGVyYXRpb24ucHJvdG90eXBlLmV4ZWN1dGUgPSBmdW5jdGlvbiAoYXJnMSwgYXJnMiwgYXJnMywgYXJnNCwgcGFyZW50KSB7XG4gIHZhciBhcmdzID0gYXJnMSB8fCB7fTtcbiAgdmFyIG9wdHMgPSB7fSwgc3VjY2VzcywgZXJyb3I7XG5cbiAgaWYgKHR5cGVvZiBhcmcyID09PSAnb2JqZWN0Jykge1xuICAgIG9wdHMgPSBhcmcyO1xuICAgIHN1Y2Nlc3MgPSBhcmczO1xuICAgIGVycm9yID0gYXJnNDtcbiAgfVxuXG4gIGlmICh0eXBlb2YgYXJnMiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHN1Y2Nlc3MgPSBhcmcyO1xuICAgIGVycm9yID0gYXJnMztcbiAgfVxuXG4gIHN1Y2Nlc3MgPSAoc3VjY2VzcyB8fCBoZWxwZXJzLmxvZyk7XG4gIGVycm9yID0gKGVycm9yIHx8IGhlbHBlcnMubG9nKTtcblxuICBpZiAob3B0cy51c2VKUXVlcnkpIHtcbiAgICB0aGlzLnVzZUpRdWVyeSA9IG9wdHMudXNlSlF1ZXJ5O1xuICB9XG5cbiAgdmFyIG1pc3NpbmdQYXJhbXMgPSB0aGlzLmdldE1pc3NpbmdQYXJhbXMoYXJncyk7XG5cbiAgaWYgKG1pc3NpbmdQYXJhbXMubGVuZ3RoID4gMCkge1xuICAgIHZhciBtZXNzYWdlID0gJ21pc3NpbmcgcmVxdWlyZWQgcGFyYW1zOiAnICsgbWlzc2luZ1BhcmFtcztcblxuICAgIGhlbHBlcnMuZmFpbChtZXNzYWdlKTtcblxuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBhbGxIZWFkZXJzID0gdGhpcy5nZXRIZWFkZXJQYXJhbXMoYXJncyk7XG4gIHZhciBjb250ZW50VHlwZUhlYWRlcnMgPSB0aGlzLnNldENvbnRlbnRUeXBlcyhhcmdzLCBvcHRzKTtcbiAgdmFyIGhlYWRlcnMgPSB7fSwgYXR0cm5hbWU7XG5cbiAgZm9yIChhdHRybmFtZSBpbiBhbGxIZWFkZXJzKSB7IGhlYWRlcnNbYXR0cm5hbWVdID0gYWxsSGVhZGVyc1thdHRybmFtZV07IH1cbiAgZm9yIChhdHRybmFtZSBpbiBjb250ZW50VHlwZUhlYWRlcnMpIHsgaGVhZGVyc1thdHRybmFtZV0gPSBjb250ZW50VHlwZUhlYWRlcnNbYXR0cm5hbWVdOyB9XG5cbiAgdmFyIGJvZHkgPSB0aGlzLmdldEJvZHkoaGVhZGVycywgYXJncywgb3B0cyk7XG4gIHZhciB1cmwgPSB0aGlzLnVybGlmeShhcmdzKTtcblxuICB2YXIgb2JqID0ge1xuICAgIHVybDogdXJsLFxuICAgIG1ldGhvZDogdGhpcy5tZXRob2QudG9VcHBlckNhc2UoKSxcbiAgICBib2R5OiBib2R5LFxuICAgIHVzZUpRdWVyeTogdGhpcy51c2VKUXVlcnksXG4gICAgaGVhZGVyczogaGVhZGVycyxcbiAgICBvbjoge1xuICAgICAgcmVzcG9uc2U6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICByZXR1cm4gc3VjY2VzcyhyZXNwb25zZSwgcGFyZW50KTtcbiAgICAgIH0sXG4gICAgICBlcnJvcjogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgIHJldHVybiBlcnJvcihyZXNwb25zZSwgcGFyZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgdGhpcy5jbGllbnRBdXRob3JpemF0aW9ucy5hcHBseShvYmosIHRoaXMub3BlcmF0aW9uLnNlY3VyaXR5KTtcblxuICBpZiAob3B0cy5tb2NrID09PSB0cnVlKSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfSBlbHNlIHtcbiAgICBuZXcgU3dhZ2dlckh0dHAoKS5leGVjdXRlKG9iaiwgb3B0cyk7XG4gIH1cbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUuc2V0Q29udGVudFR5cGVzID0gZnVuY3Rpb24gKGFyZ3MsIG9wdHMpIHtcbiAgLy8gZGVmYXVsdCB0eXBlXG4gIHZhciBhY2NlcHRzID0gJ2FwcGxpY2F0aW9uL2pzb24nO1xuICB2YXIgYWxsRGVmaW5lZFBhcmFtcyA9IHRoaXMucGFyYW1ldGVycztcbiAgdmFyIGJvZHk7XG4gIHZhciBjb25zdW1lcyA9IGFyZ3MucGFyYW1ldGVyQ29udGVudFR5cGUgfHwgJ2FwcGxpY2F0aW9uL2pzb24nO1xuICB2YXIgZGVmaW5lZEZpbGVQYXJhbXMgPSBbXTtcbiAgdmFyIGRlZmluZWRGb3JtUGFyYW1zID0gW107XG4gIHZhciBoZWFkZXJzID0ge307XG4gIHZhciBpO1xuXG4gIC8vIGdldCBwYXJhbXMgZnJvbSB0aGUgb3BlcmF0aW9uIGFuZCBzZXQgdGhlbSBpbiBkZWZpbmVkRmlsZVBhcmFtcywgZGVmaW5lZEZvcm1QYXJhbXMsIGhlYWRlcnNcbiAgZm9yIChpID0gMDsgaSA8IGFsbERlZmluZWRQYXJhbXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFyYW0gPSBhbGxEZWZpbmVkUGFyYW1zW2ldO1xuXG4gICAgaWYgKHBhcmFtLmluID09PSAnZm9ybURhdGEnKSB7XG4gICAgICBpZiAocGFyYW0udHlwZSA9PT0gJ2ZpbGUnKSB7XG4gICAgICAgIGRlZmluZWRGaWxlUGFyYW1zLnB1c2gocGFyYW0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGVmaW5lZEZvcm1QYXJhbXMucHVzaChwYXJhbSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChwYXJhbS5pbiA9PT0gJ2hlYWRlcicgJiYgb3B0cykge1xuICAgICAgdmFyIGtleSA9IHBhcmFtLm5hbWU7XG4gICAgICB2YXIgaGVhZGVyVmFsdWUgPSBvcHRzW3BhcmFtLm5hbWVdO1xuXG4gICAgICBpZiAodHlwZW9mIG9wdHNbcGFyYW0ubmFtZV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGhlYWRlcnNba2V5XSA9IGhlYWRlclZhbHVlO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocGFyYW0uaW4gPT09ICdib2R5JyAmJiB0eXBlb2YgYXJnc1twYXJhbS5uYW1lXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGJvZHkgPSBhcmdzW3BhcmFtLm5hbWVdO1xuICAgIH1cbiAgfVxuXG4gIC8vIGlmIHRoZXJlJ3MgYSBib2R5LCBuZWVkIHRvIHNldCB0aGUgY29uc3VtZXMgaGVhZGVyIHZpYSByZXF1ZXN0Q29udGVudFR5cGVcbiAgaWYgKGJvZHkgJiYgKHRoaXMubWV0aG9kID09PSAncG9zdCcgfHwgdGhpcy5tZXRob2QgPT09ICdwdXQnIHx8IHRoaXMubWV0aG9kID09PSAncGF0Y2gnIHx8IHRoaXMubWV0aG9kID09PSAnZGVsZXRlJykpIHtcbiAgICBpZiAob3B0cy5yZXF1ZXN0Q29udGVudFR5cGUpIHtcbiAgICAgIGNvbnN1bWVzID0gb3B0cy5yZXF1ZXN0Q29udGVudFR5cGU7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIGlmIGFueSBmb3JtIHBhcmFtcywgY29udGVudCB0eXBlIG11c3QgYmUgc2V0XG4gICAgaWYgKGRlZmluZWRGb3JtUGFyYW1zLmxlbmd0aCA+IDApIHtcbiAgICAgIGlmIChvcHRzLnJlcXVlc3RDb250ZW50VHlwZSkgeyAgICAgICAgICAgICAvLyBvdmVycmlkZSBpZiBzZXRcbiAgICAgICAgY29uc3VtZXMgPSBvcHRzLnJlcXVlc3RDb250ZW50VHlwZTtcbiAgICAgIH0gZWxzZSBpZiAoZGVmaW5lZEZpbGVQYXJhbXMubGVuZ3RoID4gMCkgeyAvLyBpZiBhIGZpbGUsIG11c3QgYmUgbXVsdGlwYXJ0L2Zvcm0tZGF0YVxuICAgICAgICBjb25zdW1lcyA9ICdtdWx0aXBhcnQvZm9ybS1kYXRhJztcbiAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBkZWZhdWx0IHRvIHgtd3d3LWZyb20tdXJsZW5jb2RlZFxuICAgICAgICBjb25zdW1lcyA9ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGhpcy50eXBlID09PSAnREVMRVRFJykge1xuICAgICAgYm9keSA9ICd7fSc7XG4gICAgfSBlbHNlIGlmICh0aGlzLnR5cGUgIT09ICdERUxFVEUnKSB7XG4gICAgICBjb25zdW1lcyA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgaWYgKGNvbnN1bWVzICYmIHRoaXMuY29uc3VtZXMpIHtcbiAgICBpZiAodGhpcy5jb25zdW1lcy5pbmRleE9mKGNvbnN1bWVzKSA9PT0gLTEpIHtcbiAgICAgIGhlbHBlcnMubG9nKCdzZXJ2ZXIgZG9lc25cXCd0IGNvbnN1bWUgJyArIGNvbnN1bWVzICsgJywgdHJ5ICcgKyBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbnN1bWVzKSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKG9wdHMucmVzcG9uc2VDb250ZW50VHlwZSkge1xuICAgIGFjY2VwdHMgPSBvcHRzLnJlc3BvbnNlQ29udGVudFR5cGU7XG4gIH0gZWxzZSB7XG4gICAgYWNjZXB0cyA9ICdhcHBsaWNhdGlvbi9qc29uJztcbiAgfVxuXG4gIGlmIChhY2NlcHRzICYmIHRoaXMucHJvZHVjZXMpIHtcbiAgICBpZiAodGhpcy5wcm9kdWNlcy5pbmRleE9mKGFjY2VwdHMpID09PSAtMSkge1xuICAgICAgaGVscGVycy5sb2coJ3NlcnZlciBjYW5cXCd0IHByb2R1Y2UgJyArIGFjY2VwdHMpO1xuICAgIH1cbiAgfVxuXG4gIGlmICgoY29uc3VtZXMgJiYgYm9keSAhPT0gJycpIHx8IChjb25zdW1lcyA9PT0gJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcpKSB7XG4gICAgaGVhZGVyc1snQ29udGVudC1UeXBlJ10gPSBjb25zdW1lcztcbiAgfVxuXG4gIGlmIChhY2NlcHRzKSB7XG4gICAgaGVhZGVycy5BY2NlcHQgPSBhY2NlcHRzO1xuICB9XG5cbiAgcmV0dXJuIGhlYWRlcnM7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLmFzQ3VybCA9IGZ1bmN0aW9uIChhcmdzKSB7XG4gIHZhciBvYmogPSB0aGlzLmV4ZWN1dGUoYXJncywge21vY2s6IHRydWV9KTtcblxuICB0aGlzLmNsaWVudEF1dGhvcml6YXRpb25zLmFwcGx5KG9iaik7XG5cbiAgdmFyIHJlc3VsdHMgPSBbXTtcblxuICByZXN1bHRzLnB1c2goJy1YICcgKyB0aGlzLm1ldGhvZC50b1VwcGVyQ2FzZSgpKTtcblxuICBpZiAob2JqLmhlYWRlcnMpIHtcbiAgICB2YXIga2V5O1xuXG4gICAgZm9yIChrZXkgaW4gb2JqLmhlYWRlcnMpIHtcbiAgICAgIHJlc3VsdHMucHVzaCgnLS1oZWFkZXIgXCInICsga2V5ICsgJzogJyArIG9iai5oZWFkZXJzW2tleV0gKyAnXCInKTtcbiAgICB9XG4gIH1cblxuICBpZiAob2JqLmJvZHkpIHtcbiAgICB2YXIgYm9keTtcblxuICAgIGlmICh0eXBlb2Ygb2JqLmJvZHkgPT09ICdvYmplY3QnKSB7XG4gICAgICBib2R5ID0gSlNPTi5zdHJpbmdpZnkob2JqLmJvZHkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBib2R5ID0gb2JqLmJvZHk7XG4gICAgfVxuXG4gICAgcmVzdWx0cy5wdXNoKCctZCBcIicgKyBib2R5LnJlcGxhY2UoL1wiL2csICdcXFxcXCInKSArICdcIicpO1xuICB9XG5cbiAgcmV0dXJuICdjdXJsICcgKyAocmVzdWx0cy5qb2luKCcgJykpICsgJyBcIicgKyBvYmoudXJsICsgJ1wiJztcbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUuZW5jb2RlUGF0aENvbGxlY3Rpb24gPSBmdW5jdGlvbiAodHlwZSwgbmFtZSwgdmFsdWUpIHtcbiAgdmFyIGVuY29kZWQgPSAnJztcbiAgdmFyIGk7XG4gIHZhciBzZXBhcmF0b3IgPSAnJztcblxuICBpZiAodHlwZSA9PT0gJ3NzdicpIHtcbiAgICBzZXBhcmF0b3IgPSAnJTIwJztcbiAgfSBlbHNlIGlmICh0eXBlID09PSAndHN2Jykge1xuICAgIHNlcGFyYXRvciA9ICdcXFxcdCc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3BpcGVzJykge1xuICAgIHNlcGFyYXRvciA9ICd8JztcbiAgfSBlbHNlIHtcbiAgICBzZXBhcmF0b3IgPSAnLCc7XG4gIH1cblxuICBmb3IgKGkgPSAwOyBpIDwgdmFsdWUubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgZW5jb2RlZCA9IHRoaXMuZW5jb2RlUXVlcnlQYXJhbSh2YWx1ZVtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVuY29kZWQgKz0gc2VwYXJhdG9yICsgdGhpcy5lbmNvZGVRdWVyeVBhcmFtKHZhbHVlW2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZW5jb2RlZDtcbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUuZW5jb2RlUXVlcnlDb2xsZWN0aW9uID0gZnVuY3Rpb24gKHR5cGUsIG5hbWUsIHZhbHVlKSB7XG4gIHZhciBlbmNvZGVkID0gJyc7XG4gIHZhciBpO1xuXG4gIGlmICh0eXBlID09PSAnZGVmYXVsdCcgfHwgdHlwZSA9PT0gJ211bHRpJykge1xuICAgIGZvciAoaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGkgPiAwKSB7ZW5jb2RlZCArPSAnJic7fVxuXG4gICAgICBlbmNvZGVkICs9IHRoaXMuZW5jb2RlUXVlcnlQYXJhbShuYW1lKSArICc9JyArIHRoaXMuZW5jb2RlUXVlcnlQYXJhbSh2YWx1ZVtpXSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBzZXBhcmF0b3IgPSAnJztcblxuICAgIGlmICh0eXBlID09PSAnY3N2Jykge1xuICAgICAgc2VwYXJhdG9yID0gJywnO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3NzdicpIHtcbiAgICAgIHNlcGFyYXRvciA9ICclMjAnO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3RzdicpIHtcbiAgICAgIHNlcGFyYXRvciA9ICdcXFxcdCc7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAncGlwZXMnKSB7XG4gICAgICBzZXBhcmF0b3IgPSAnfCc7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnYnJhY2tldHMnKSB7IFxuICAgICAgZm9yIChpID0gMDsgaSA8IHZhbHVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChpICE9PSAwKSB7XG4gICAgICAgICAgZW5jb2RlZCArPSAnJic7XG4gICAgICAgIH1cblxuICAgICAgICBlbmNvZGVkICs9IHRoaXMuZW5jb2RlUXVlcnlQYXJhbShuYW1lKSArICdbXT0nICsgdGhpcy5lbmNvZGVRdWVyeVBhcmFtKHZhbHVlW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc2VwYXJhdG9yICE9PSAnJykge1xuICAgICAgZm9yIChpID0gMDsgaSA8IHZhbHVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChpID09PSAwKSB7XG4gICAgICAgICAgZW5jb2RlZCA9IHRoaXMuZW5jb2RlUXVlcnlQYXJhbShuYW1lKSArICc9JyArIHRoaXMuZW5jb2RlUXVlcnlQYXJhbSh2YWx1ZVtpXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZW5jb2RlZCArPSBzZXBhcmF0b3IgKyB0aGlzLmVuY29kZVF1ZXJ5UGFyYW0odmFsdWVbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGVuY29kZWQ7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLmVuY29kZVF1ZXJ5UGFyYW0gPSBmdW5jdGlvbiAoYXJnKSB7XG4gIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQoYXJnKTtcbn07XG5cbi8qKlxuICogVE9ETyByZXZpc2l0LCBtaWdodCBub3Qgd2FudCB0byBsZWF2ZSAnLydcbiAqKi9cbk9wZXJhdGlvbi5wcm90b3R5cGUuZW5jb2RlUGF0aFBhcmFtID0gZnVuY3Rpb24gKHBhdGhQYXJhbSkge1xuICB2YXIgZW5jUGFydHMsIHBhcnRzLCBpLCBsZW47XG5cbiAgcGF0aFBhcmFtID0gcGF0aFBhcmFtLnRvU3RyaW5nKCk7XG5cbiAgaWYgKHBhdGhQYXJhbS5pbmRleE9mKCcvJykgPT09IC0xKSB7XG4gICAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChwYXRoUGFyYW0pO1xuICB9IGVsc2Uge1xuICAgIHBhcnRzID0gcGF0aFBhcmFtLnNwbGl0KCcvJyk7XG4gICAgZW5jUGFydHMgPSBbXTtcblxuICAgIGZvciAoaSA9IDAsIGxlbiA9IHBhcnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBlbmNQYXJ0cy5wdXNoKGVuY29kZVVSSUNvbXBvbmVudChwYXJ0c1tpXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBlbmNQYXJ0cy5qb2luKCcvJyk7XG4gIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBPcGVyYXRpb25Hcm91cCA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHRhZywgZGVzY3JpcHRpb24sIGV4dGVybmFsRG9jcywgb3BlcmF0aW9uKSB7XG4gIHRoaXMudGFnID0gdGFnO1xuICB0aGlzLnBhdGggPSB0YWc7XG4gIHRoaXMuZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbjtcbiAgdGhpcy5leHRlcm5hbERvY3MgPSBleHRlcm5hbERvY3M7XG4gIHRoaXMubmFtZSA9IHRhZztcbiAgdGhpcy5vcGVyYXRpb24gPSBvcGVyYXRpb247XG4gIHRoaXMub3BlcmF0aW9uc0FycmF5ID0gW107XG59O1xuXG5PcGVyYXRpb25Hcm91cC5wcm90b3R5cGUuc29ydCA9IGZ1bmN0aW9uICgpIHtcblxufTtcblxuIiwiLyohXG4gKiBUaGUgYnVmZmVyIG1vZHVsZSBmcm9tIG5vZGUuanMsIGZvciB0aGUgYnJvd3Nlci5cbiAqXG4gKiBAYXV0aG9yICAgRmVyb3NzIEFib3VraGFkaWplaCA8ZmVyb3NzQGZlcm9zcy5vcmc+IDxodHRwOi8vZmVyb3NzLm9yZz5cbiAqIEBsaWNlbnNlICBNSVRcbiAqL1xuXG52YXIgYmFzZTY0ID0gcmVxdWlyZSgnYmFzZTY0LWpzJylcbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpXG52YXIgaXNBcnJheSA9IHJlcXVpcmUoJ2lzLWFycmF5JylcblxuZXhwb3J0cy5CdWZmZXIgPSBCdWZmZXJcbmV4cG9ydHMuU2xvd0J1ZmZlciA9IFNsb3dCdWZmZXJcbmV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVMgPSA1MFxuQnVmZmVyLnBvb2xTaXplID0gODE5MiAvLyBub3QgdXNlZCBieSB0aGlzIGltcGxlbWVudGF0aW9uXG5cbnZhciBrTWF4TGVuZ3RoID0gMHgzZmZmZmZmZlxudmFyIHJvb3RQYXJlbnQgPSB7fVxuXG4vKipcbiAqIElmIGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGA6XG4gKiAgID09PSB0cnVlICAgIFVzZSBVaW50OEFycmF5IGltcGxlbWVudGF0aW9uIChmYXN0ZXN0KVxuICogICA9PT0gZmFsc2UgICBVc2UgT2JqZWN0IGltcGxlbWVudGF0aW9uIChtb3N0IGNvbXBhdGlibGUsIGV2ZW4gSUU2KVxuICpcbiAqIEJyb3dzZXJzIHRoYXQgc3VwcG9ydCB0eXBlZCBhcnJheXMgYXJlIElFIDEwKywgRmlyZWZveCA0KywgQ2hyb21lIDcrLCBTYWZhcmkgNS4xKyxcbiAqIE9wZXJhIDExLjYrLCBpT1MgNC4yKy5cbiAqXG4gKiBOb3RlOlxuICpcbiAqIC0gSW1wbGVtZW50YXRpb24gbXVzdCBzdXBwb3J0IGFkZGluZyBuZXcgcHJvcGVydGllcyB0byBgVWludDhBcnJheWAgaW5zdGFuY2VzLlxuICogICBGaXJlZm94IDQtMjkgbGFja2VkIHN1cHBvcnQsIGZpeGVkIGluIEZpcmVmb3ggMzArLlxuICogICBTZWU6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY5NTQzOC5cbiAqXG4gKiAgLSBDaHJvbWUgOS0xMCBpcyBtaXNzaW5nIHRoZSBgVHlwZWRBcnJheS5wcm90b3R5cGUuc3ViYXJyYXlgIGZ1bmN0aW9uLlxuICpcbiAqICAtIElFMTAgaGFzIGEgYnJva2VuIGBUeXBlZEFycmF5LnByb3RvdHlwZS5zdWJhcnJheWAgZnVuY3Rpb24gd2hpY2ggcmV0dXJucyBhcnJheXMgb2ZcbiAqICAgIGluY29ycmVjdCBsZW5ndGggaW4gc29tZSBzaXR1YXRpb25zLlxuICpcbiAqIFdlIGRldGVjdCB0aGVzZSBidWdneSBicm93c2VycyBhbmQgc2V0IGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGAgdG8gYGZhbHNlYCBzbyB0aGV5IHdpbGxcbiAqIGdldCB0aGUgT2JqZWN0IGltcGxlbWVudGF0aW9uLCB3aGljaCBpcyBzbG93ZXIgYnV0IHdpbGwgd29yayBjb3JyZWN0bHkuXG4gKi9cbkJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUID0gKGZ1bmN0aW9uICgpIHtcbiAgdHJ5IHtcbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDApXG4gICAgdmFyIGFyciA9IG5ldyBVaW50OEFycmF5KGJ1ZilcbiAgICBhcnIuZm9vID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gNDIgfVxuICAgIHJldHVybiBhcnIuZm9vKCkgPT09IDQyICYmIC8vIHR5cGVkIGFycmF5IGluc3RhbmNlcyBjYW4gYmUgYXVnbWVudGVkXG4gICAgICAgIHR5cGVvZiBhcnIuc3ViYXJyYXkgPT09ICdmdW5jdGlvbicgJiYgLy8gY2hyb21lIDktMTAgbGFjayBgc3ViYXJyYXlgXG4gICAgICAgIG5ldyBVaW50OEFycmF5KDEpLnN1YmFycmF5KDEsIDEpLmJ5dGVMZW5ndGggPT09IDAgLy8gaWUxMCBoYXMgYnJva2VuIGBzdWJhcnJheWBcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59KSgpXG5cbi8qKlxuICogQ2xhc3M6IEJ1ZmZlclxuICogPT09PT09PT09PT09PVxuICpcbiAqIFRoZSBCdWZmZXIgY29uc3RydWN0b3IgcmV0dXJucyBpbnN0YW5jZXMgb2YgYFVpbnQ4QXJyYXlgIHRoYXQgYXJlIGF1Z21lbnRlZFxuICogd2l0aCBmdW5jdGlvbiBwcm9wZXJ0aWVzIGZvciBhbGwgdGhlIG5vZGUgYEJ1ZmZlcmAgQVBJIGZ1bmN0aW9ucy4gV2UgdXNlXG4gKiBgVWludDhBcnJheWAgc28gdGhhdCBzcXVhcmUgYnJhY2tldCBub3RhdGlvbiB3b3JrcyBhcyBleHBlY3RlZCAtLSBpdCByZXR1cm5zXG4gKiBhIHNpbmdsZSBvY3RldC5cbiAqXG4gKiBCeSBhdWdtZW50aW5nIHRoZSBpbnN0YW5jZXMsIHdlIGNhbiBhdm9pZCBtb2RpZnlpbmcgdGhlIGBVaW50OEFycmF5YFxuICogcHJvdG90eXBlLlxuICovXG5mdW5jdGlvbiBCdWZmZXIgKHN1YmplY3QsIGVuY29kaW5nLCBub1plcm8pIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEJ1ZmZlcikpXG4gICAgcmV0dXJuIG5ldyBCdWZmZXIoc3ViamVjdCwgZW5jb2RpbmcsIG5vWmVybylcblxuICB2YXIgdHlwZSA9IHR5cGVvZiBzdWJqZWN0XG5cbiAgLy8gRmluZCB0aGUgbGVuZ3RoXG4gIHZhciBsZW5ndGhcbiAgaWYgKHR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgbGVuZ3RoID0gK3N1YmplY3RcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgIGxlbmd0aCA9IEJ1ZmZlci5ieXRlTGVuZ3RoKHN1YmplY3QsIGVuY29kaW5nKVxuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdvYmplY3QnICYmIHN1YmplY3QgIT09IG51bGwpIHsgLy8gYXNzdW1lIG9iamVjdCBpcyBhcnJheS1saWtlXG4gICAgaWYgKHN1YmplY3QudHlwZSA9PT0gJ0J1ZmZlcicgJiYgaXNBcnJheShzdWJqZWN0LmRhdGEpKVxuICAgICAgc3ViamVjdCA9IHN1YmplY3QuZGF0YVxuICAgIGxlbmd0aCA9ICtzdWJqZWN0Lmxlbmd0aFxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ211c3Qgc3RhcnQgd2l0aCBudW1iZXIsIGJ1ZmZlciwgYXJyYXkgb3Igc3RyaW5nJylcbiAgfVxuXG4gIGlmIChsZW5ndGggPiBrTWF4TGVuZ3RoKVxuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIGFsbG9jYXRlIEJ1ZmZlciBsYXJnZXIgdGhhbiBtYXhpbXVtICcgK1xuICAgICAgJ3NpemU6IDB4JyArIGtNYXhMZW5ndGgudG9TdHJpbmcoMTYpICsgJyBieXRlcycpXG5cbiAgaWYgKGxlbmd0aCA8IDApXG4gICAgbGVuZ3RoID0gMFxuICBlbHNlXG4gICAgbGVuZ3RoID4+Pj0gMCAvLyBDb2VyY2UgdG8gdWludDMyLlxuXG4gIHZhciBzZWxmID0gdGhpc1xuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAvLyBQcmVmZXJyZWQ6IFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlIGZvciBiZXN0IHBlcmZvcm1hbmNlXG4gICAgLyplc2xpbnQtZGlzYWJsZSBjb25zaXN0ZW50LXRoaXMgKi9cbiAgICBzZWxmID0gQnVmZmVyLl9hdWdtZW50KG5ldyBVaW50OEFycmF5KGxlbmd0aCkpXG4gICAgLyplc2xpbnQtZW5hYmxlIGNvbnNpc3RlbnQtdGhpcyAqL1xuICB9IGVsc2Uge1xuICAgIC8vIEZhbGxiYWNrOiBSZXR1cm4gVEhJUyBpbnN0YW5jZSBvZiBCdWZmZXIgKGNyZWF0ZWQgYnkgYG5ld2ApXG4gICAgc2VsZi5sZW5ndGggPSBsZW5ndGhcbiAgICBzZWxmLl9pc0J1ZmZlciA9IHRydWVcbiAgfVxuXG4gIHZhciBpXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCAmJiB0eXBlb2Ygc3ViamVjdC5ieXRlTGVuZ3RoID09PSAnbnVtYmVyJykge1xuICAgIC8vIFNwZWVkIG9wdGltaXphdGlvbiAtLSB1c2Ugc2V0IGlmIHdlJ3JlIGNvcHlpbmcgZnJvbSBhIHR5cGVkIGFycmF5XG4gICAgc2VsZi5fc2V0KHN1YmplY3QpXG4gIH0gZWxzZSBpZiAoaXNBcnJheWlzaChzdWJqZWN0KSkge1xuICAgIC8vIFRyZWF0IGFycmF5LWlzaCBvYmplY3RzIGFzIGEgYnl0ZSBhcnJheVxuICAgIGlmIChCdWZmZXIuaXNCdWZmZXIoc3ViamVjdCkpIHtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKylcbiAgICAgICAgc2VsZltpXSA9IHN1YmplY3QucmVhZFVJbnQ4KGkpXG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKylcbiAgICAgICAgc2VsZltpXSA9ICgoc3ViamVjdFtpXSAlIDI1NikgKyAyNTYpICUgMjU2XG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgc2VsZi53cml0ZShzdWJqZWN0LCAwLCBlbmNvZGluZylcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJyAmJiAhQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgJiYgIW5vWmVybykge1xuICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgc2VsZltpXSA9IDBcbiAgICB9XG4gIH1cblxuICBpZiAobGVuZ3RoID4gMCAmJiBsZW5ndGggPD0gQnVmZmVyLnBvb2xTaXplKVxuICAgIHNlbGYucGFyZW50ID0gcm9vdFBhcmVudFxuXG4gIHJldHVybiBzZWxmXG59XG5cbmZ1bmN0aW9uIFNsb3dCdWZmZXIgKHN1YmplY3QsIGVuY29kaW5nLCBub1plcm8pIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNsb3dCdWZmZXIpKVxuICAgIHJldHVybiBuZXcgU2xvd0J1ZmZlcihzdWJqZWN0LCBlbmNvZGluZywgbm9aZXJvKVxuXG4gIHZhciBidWYgPSBuZXcgQnVmZmVyKHN1YmplY3QsIGVuY29kaW5nLCBub1plcm8pXG4gIGRlbGV0ZSBidWYucGFyZW50XG4gIHJldHVybiBidWZcbn1cblxuQnVmZmVyLmlzQnVmZmVyID0gZnVuY3Rpb24gKGIpIHtcbiAgcmV0dXJuICEhKGIgIT0gbnVsbCAmJiBiLl9pc0J1ZmZlcilcbn1cblxuQnVmZmVyLmNvbXBhcmUgPSBmdW5jdGlvbiAoYSwgYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihhKSB8fCAhQnVmZmVyLmlzQnVmZmVyKGIpKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50cyBtdXN0IGJlIEJ1ZmZlcnMnKVxuXG4gIGlmIChhID09PSBiKSByZXR1cm4gMFxuXG4gIHZhciB4ID0gYS5sZW5ndGhcbiAgdmFyIHkgPSBiLmxlbmd0aFxuICBmb3IgKHZhciBpID0gMCwgbGVuID0gTWF0aC5taW4oeCwgeSk7IGkgPCBsZW4gJiYgYVtpXSA9PT0gYltpXTsgaSsrKSB7fVxuICBpZiAoaSAhPT0gbGVuKSB7XG4gICAgeCA9IGFbaV1cbiAgICB5ID0gYltpXVxuICB9XG4gIGlmICh4IDwgeSkgcmV0dXJuIC0xXG4gIGlmICh5IDwgeCkgcmV0dXJuIDFcbiAgcmV0dXJuIDBcbn1cblxuQnVmZmVyLmlzRW5jb2RpbmcgPSBmdW5jdGlvbiAoZW5jb2RpbmcpIHtcbiAgc3dpdGNoIChTdHJpbmcoZW5jb2RpbmcpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgIGNhc2UgJ3Jhdyc6XG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldHVybiB0cnVlXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbkJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiAobGlzdCwgdG90YWxMZW5ndGgpIHtcbiAgaWYgKCFpc0FycmF5KGxpc3QpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVc2FnZTogQnVmZmVyLmNvbmNhdChsaXN0WywgbGVuZ3RoXSknKVxuXG4gIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBuZXcgQnVmZmVyKDApXG4gIH0gZWxzZSBpZiAobGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gbGlzdFswXVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKHRvdGFsTGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICB0b3RhbExlbmd0aCA9IDBcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgdG90YWxMZW5ndGggKz0gbGlzdFtpXS5sZW5ndGhcbiAgICB9XG4gIH1cblxuICB2YXIgYnVmID0gbmV3IEJ1ZmZlcih0b3RhbExlbmd0aClcbiAgdmFyIHBvcyA9IDBcbiAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgaXRlbSA9IGxpc3RbaV1cbiAgICBpdGVtLmNvcHkoYnVmLCBwb3MpXG4gICAgcG9zICs9IGl0ZW0ubGVuZ3RoXG4gIH1cbiAgcmV0dXJuIGJ1ZlxufVxuXG5CdWZmZXIuYnl0ZUxlbmd0aCA9IGZ1bmN0aW9uIChzdHIsIGVuY29kaW5nKSB7XG4gIHZhciByZXRcbiAgc3RyID0gc3RyICsgJydcbiAgc3dpdGNoIChlbmNvZGluZyB8fCAndXRmOCcpIHtcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICBjYXNlICdyYXcnOlxuICAgICAgcmV0ID0gc3RyLmxlbmd0aFxuICAgICAgYnJlYWtcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0ID0gc3RyLmxlbmd0aCAqIDJcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnaGV4JzpcbiAgICAgIHJldCA9IHN0ci5sZW5ndGggPj4+IDFcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndXRmOCc6XG4gICAgY2FzZSAndXRmLTgnOlxuICAgICAgcmV0ID0gdXRmOFRvQnl0ZXMoc3RyKS5sZW5ndGhcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgIHJldCA9IGJhc2U2NFRvQnl0ZXMoc3RyKS5sZW5ndGhcbiAgICAgIGJyZWFrXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldCA9IHN0ci5sZW5ndGhcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbi8vIHByZS1zZXQgZm9yIHZhbHVlcyB0aGF0IG1heSBleGlzdCBpbiB0aGUgZnV0dXJlXG5CdWZmZXIucHJvdG90eXBlLmxlbmd0aCA9IHVuZGVmaW5lZFxuQnVmZmVyLnByb3RvdHlwZS5wYXJlbnQgPSB1bmRlZmluZWRcblxuLy8gdG9TdHJpbmcoZW5jb2RpbmcsIHN0YXJ0PTAsIGVuZD1idWZmZXIubGVuZ3RoKVxuQnVmZmVyLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIChlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuXG4gIHN0YXJ0ID0gc3RhcnQgPj4+IDBcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgfHwgZW5kID09PSBJbmZpbml0eSA/IHRoaXMubGVuZ3RoIDogZW5kID4+PiAwXG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcbiAgaWYgKHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIGlmIChlbmQgPiB0aGlzLmxlbmd0aCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKGVuZCA8PSBzdGFydCkgcmV0dXJuICcnXG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgICByZXR1cm4gYXNjaWlTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gYmluYXJ5U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1dGYxNmxlU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKVxuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICAgICAgZW5jb2RpbmcgPSAoZW5jb2RpbmcgKyAnJykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiAoYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpXG4gIGlmICh0aGlzID09PSBiKSByZXR1cm4gdHJ1ZVxuICByZXR1cm4gQnVmZmVyLmNvbXBhcmUodGhpcywgYikgPT09IDBcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbnNwZWN0ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgc3RyID0gJydcbiAgdmFyIG1heCA9IGV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVNcbiAgaWYgKHRoaXMubGVuZ3RoID4gMCkge1xuICAgIHN0ciA9IHRoaXMudG9TdHJpbmcoJ2hleCcsIDAsIG1heCkubWF0Y2goLy57Mn0vZykuam9pbignICcpXG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbWF4KVxuICAgICAgc3RyICs9ICcgLi4uICdcbiAgfVxuICByZXR1cm4gJzxCdWZmZXIgJyArIHN0ciArICc+J1xufVxuXG5CdWZmZXIucHJvdG90eXBlLmNvbXBhcmUgPSBmdW5jdGlvbiAoYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpXG4gIGlmICh0aGlzID09PSBiKSByZXR1cm4gMFxuICByZXR1cm4gQnVmZmVyLmNvbXBhcmUodGhpcywgYilcbn1cblxuLy8gYGdldGAgd2lsbCBiZSByZW1vdmVkIGluIE5vZGUgMC4xMytcbkJ1ZmZlci5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24gKG9mZnNldCkge1xuICBjb25zb2xlLmxvZygnLmdldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuJylcbiAgcmV0dXJuIHRoaXMucmVhZFVJbnQ4KG9mZnNldClcbn1cblxuLy8gYHNldGAgd2lsbCBiZSByZW1vdmVkIGluIE5vZGUgMC4xMytcbkJ1ZmZlci5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKHYsIG9mZnNldCkge1xuICBjb25zb2xlLmxvZygnLnNldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuJylcbiAgcmV0dXJuIHRoaXMud3JpdGVVSW50OCh2LCBvZmZzZXQpXG59XG5cbmZ1bmN0aW9uIGhleFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgb2Zmc2V0ID0gTnVtYmVyKG9mZnNldCkgfHwgMFxuICB2YXIgcmVtYWluaW5nID0gYnVmLmxlbmd0aCAtIG9mZnNldFxuICBpZiAoIWxlbmd0aCkge1xuICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICB9IGVsc2Uge1xuICAgIGxlbmd0aCA9IE51bWJlcihsZW5ndGgpXG4gICAgaWYgKGxlbmd0aCA+IHJlbWFpbmluZykge1xuICAgICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gICAgfVxuICB9XG5cbiAgLy8gbXVzdCBiZSBhbiBldmVuIG51bWJlciBvZiBkaWdpdHNcbiAgdmFyIHN0ckxlbiA9IHN0cmluZy5sZW5ndGhcbiAgaWYgKHN0ckxlbiAlIDIgIT09IDApIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBoZXggc3RyaW5nJylcblxuICBpZiAobGVuZ3RoID4gc3RyTGVuIC8gMikge1xuICAgIGxlbmd0aCA9IHN0ckxlbiAvIDJcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGJ5dGUgPSBwYXJzZUludChzdHJpbmcuc3Vic3RyKGkgKiAyLCAyKSwgMTYpXG4gICAgaWYgKGlzTmFOKGJ5dGUpKSB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaGV4IHN0cmluZycpXG4gICAgYnVmW29mZnNldCArIGldID0gYnl0ZVxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIHV0ZjhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG4gIHJldHVybiBjaGFyc1dyaXR0ZW5cbn1cblxuZnVuY3Rpb24gYXNjaWlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBibGl0QnVmZmVyKGFzY2lpVG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxuICByZXR1cm4gY2hhcnNXcml0dGVuXG59XG5cbmZ1bmN0aW9uIGJpbmFyeVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGFzY2lpV3JpdGUoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBiYXNlNjRXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBibGl0QnVmZmVyKGJhc2U2NFRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbiAgcmV0dXJuIGNoYXJzV3JpdHRlblxufVxuXG5mdW5jdGlvbiB1dGYxNmxlV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICB2YXIgY2hhcnNXcml0dGVuID0gYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxuICByZXR1cm4gY2hhcnNXcml0dGVuXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiAoc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCwgZW5jb2RpbmcpIHtcbiAgLy8gU3VwcG9ydCBib3RoIChzdHJpbmcsIG9mZnNldCwgbGVuZ3RoLCBlbmNvZGluZylcbiAgLy8gYW5kIHRoZSBsZWdhY3kgKHN0cmluZywgZW5jb2RpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICBpZiAoaXNGaW5pdGUob2Zmc2V0KSkge1xuICAgIGlmICghaXNGaW5pdGUobGVuZ3RoKSkge1xuICAgICAgZW5jb2RpbmcgPSBsZW5ndGhcbiAgICAgIGxlbmd0aCA9IHVuZGVmaW5lZFxuICAgIH1cbiAgfSBlbHNlIHsgIC8vIGxlZ2FjeVxuICAgIHZhciBzd2FwID0gZW5jb2RpbmdcbiAgICBlbmNvZGluZyA9IG9mZnNldFxuICAgIG9mZnNldCA9IGxlbmd0aFxuICAgIGxlbmd0aCA9IHN3YXBcbiAgfVxuXG4gIG9mZnNldCA9IE51bWJlcihvZmZzZXQpIHx8IDBcblxuICBpZiAobGVuZ3RoIDwgMCB8fCBvZmZzZXQgPCAwIHx8IG9mZnNldCA+IHRoaXMubGVuZ3RoKVxuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdhdHRlbXB0IHRvIHdyaXRlIG91dHNpZGUgYnVmZmVyIGJvdW5kcycpXG5cbiAgdmFyIHJlbWFpbmluZyA9IHRoaXMubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gIH0gZWxzZSB7XG4gICAgbGVuZ3RoID0gTnVtYmVyKGxlbmd0aClcbiAgICBpZiAobGVuZ3RoID4gcmVtYWluaW5nKSB7XG4gICAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgICB9XG4gIH1cbiAgZW5jb2RpbmcgPSBTdHJpbmcoZW5jb2RpbmcgfHwgJ3V0ZjgnKS50b0xvd2VyQ2FzZSgpXG5cbiAgdmFyIHJldFxuICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICAgIHJldCA9IGhleFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgIHJldCA9IHV0ZjhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgICByZXQgPSBhc2NpaVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICByZXQgPSBiaW5hcnlXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgcmV0ID0gYmFzZTY0V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldCA9IHV0ZjE2bGVXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuZnVuY3Rpb24gYmFzZTY0U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBpZiAoc3RhcnQgPT09IDAgJiYgZW5kID09PSBidWYubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1ZilcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmLnNsaWNlKHN0YXJ0LCBlbmQpKVxuICB9XG59XG5cbmZ1bmN0aW9uIHV0ZjhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXMgPSAnJ1xuICB2YXIgdG1wID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgaWYgKGJ1ZltpXSA8PSAweDdGKSB7XG4gICAgICByZXMgKz0gZGVjb2RlVXRmOENoYXIodG1wKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKVxuICAgICAgdG1wID0gJydcbiAgICB9IGVsc2Uge1xuICAgICAgdG1wICs9ICclJyArIGJ1ZltpXS50b1N0cmluZygxNilcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzICsgZGVjb2RlVXRmOENoYXIodG1wKVxufVxuXG5mdW5jdGlvbiBhc2NpaVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSAmIDB4N0YpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBiaW5hcnlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBoZXhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG5cbiAgaWYgKCFzdGFydCB8fCBzdGFydCA8IDApIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCB8fCBlbmQgPCAwIHx8IGVuZCA+IGxlbikgZW5kID0gbGVuXG5cbiAgdmFyIG91dCA9ICcnXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgb3V0ICs9IHRvSGV4KGJ1ZltpXSlcbiAgfVxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBieXRlcyA9IGJ1Zi5zbGljZShzdGFydCwgZW5kKVxuICB2YXIgcmVzID0gJydcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkgKz0gMikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGVzW2ldICsgYnl0ZXNbaSArIDFdICogMjU2KVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uIChzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBzdGFydCA9IH5+c3RhcnRcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW4gOiB+fmVuZFxuXG4gIGlmIChzdGFydCA8IDApIHtcbiAgICBzdGFydCArPSBsZW5cbiAgICBpZiAoc3RhcnQgPCAwKVxuICAgICAgc3RhcnQgPSAwXG4gIH0gZWxzZSBpZiAoc3RhcnQgPiBsZW4pIHtcbiAgICBzdGFydCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IDApIHtcbiAgICBlbmQgKz0gbGVuXG4gICAgaWYgKGVuZCA8IDApXG4gICAgICBlbmQgPSAwXG4gIH0gZWxzZSBpZiAoZW5kID4gbGVuKSB7XG4gICAgZW5kID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgc3RhcnQpXG4gICAgZW5kID0gc3RhcnRcblxuICB2YXIgbmV3QnVmXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIG5ld0J1ZiA9IEJ1ZmZlci5fYXVnbWVudCh0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpKVxuICB9IGVsc2Uge1xuICAgIHZhciBzbGljZUxlbiA9IGVuZCAtIHN0YXJ0XG4gICAgbmV3QnVmID0gbmV3IEJ1ZmZlcihzbGljZUxlbiwgdW5kZWZpbmVkLCB0cnVlKVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2xpY2VMZW47IGkrKykge1xuICAgICAgbmV3QnVmW2ldID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9XG5cbiAgaWYgKG5ld0J1Zi5sZW5ndGgpXG4gICAgbmV3QnVmLnBhcmVudCA9IHRoaXMucGFyZW50IHx8IHRoaXNcblxuICByZXR1cm4gbmV3QnVmXG59XG5cbi8qXG4gKiBOZWVkIHRvIG1ha2Ugc3VyZSB0aGF0IGJ1ZmZlciBpc24ndCB0cnlpbmcgdG8gd3JpdGUgb3V0IG9mIGJvdW5kcy5cbiAqL1xuZnVuY3Rpb24gY2hlY2tPZmZzZXQgKG9mZnNldCwgZXh0LCBsZW5ndGgpIHtcbiAgaWYgKChvZmZzZXQgJSAxKSAhPT0gMCB8fCBvZmZzZXQgPCAwKVxuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdvZmZzZXQgaXMgbm90IHVpbnQnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gbGVuZ3RoKVxuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdUcnlpbmcgdG8gYWNjZXNzIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludExFID0gZnVuY3Rpb24gKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSlcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludEJFID0gZnVuY3Rpb24gKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXQgKyAtLWJ5dGVMZW5ndGhdXG4gIHZhciBtdWwgPSAxXG4gIHdoaWxlIChieXRlTGVuZ3RoID4gMCAmJiAobXVsICo9IDB4MTAwKSlcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWJ5dGVMZW5ndGhdICogbXVsXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCA4KSB8IHRoaXNbb2Zmc2V0ICsgMV1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyTEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICgodGhpc1tvZmZzZXRdKSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikpICtcbiAgICAgICh0aGlzW29mZnNldCArIDNdICogMHgxMDAwMDAwKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSAqIDB4MTAwMDAwMCkgK1xuICAgICAgKCh0aGlzW29mZnNldCArIDFdIDw8IDE2KSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCA4KSB8XG4gICAgICB0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XVxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpXG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bClcbiAgICB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoXG4gIHZhciBtdWwgPSAxXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIC0taV1cbiAgd2hpbGUgKGkgPiAwICYmIChtdWwgKj0gMHgxMDApKVxuICAgIHZhbCArPSB0aGlzW29mZnNldCArIC0taV0gKiBtdWxcbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bClcbiAgICB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQ4ID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICBpZiAoISh0aGlzW29mZnNldF0gJiAweDgwKSlcbiAgICByZXR1cm4gKHRoaXNbb2Zmc2V0XSlcbiAgcmV0dXJuICgoMHhmZiAtIHRoaXNbb2Zmc2V0XSArIDEpICogLTEpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2TEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF0gfCAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2QkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIDFdIHwgKHRoaXNbb2Zmc2V0XSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyTEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0pIHxcbiAgICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAgICh0aGlzW29mZnNldCArIDJdIDw8IDE2KSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAzXSA8PCAyNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCAyNCkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgMTYpIHxcbiAgICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICAgICh0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdExFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgdHJ1ZSwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0QkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCBmYWxzZSwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja09mZnNldChvZmZzZXQsIDgsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgdHJ1ZSwgNTIsIDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja09mZnNldChvZmZzZXQsIDgsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgZmFsc2UsIDUyLCA4KVxufVxuXG5mdW5jdGlvbiBjaGVja0ludCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1ZmZlciBtdXN0IGJlIGEgQnVmZmVyIGluc3RhbmNlJylcbiAgaWYgKHZhbHVlID4gbWF4IHx8IHZhbHVlIDwgbWluKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcigndmFsdWUgaXMgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignaW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnRMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCksIDApXG5cbiAgdmFyIG11bCA9IDFcbiAgdmFyIGkgPSAwXG4gIHRoaXNbb2Zmc2V0XSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSlcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSA+Pj4gMCAmIDB4RkZcblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludEJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKSwgMClcblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHRoaXNbb2Zmc2V0ICsgaV0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKC0taSA+PSAwICYmIChtdWwgKj0gMHgxMDApKVxuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAodmFsdWUgLyBtdWwpID4+PiAwICYgMHhGRlxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50OCA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAxLCAweGZmLCAwKVxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB2YWx1ZSA9IE1hdGguZmxvb3IodmFsdWUpXG4gIHRoaXNbb2Zmc2V0XSA9IHZhbHVlXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbmZ1bmN0aW9uIG9iamVjdFdyaXRlVUludDE2IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbikge1xuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZiArIHZhbHVlICsgMVxuICBmb3IgKHZhciBpID0gMCwgaiA9IE1hdGgubWluKGJ1Zi5sZW5ndGggLSBvZmZzZXQsIDIpOyBpIDwgajsgaSsrKSB7XG4gICAgYnVmW29mZnNldCArIGldID0gKHZhbHVlICYgKDB4ZmYgPDwgKDggKiAobGl0dGxlRW5kaWFuID8gaSA6IDEgLSBpKSkpKSA+Pj5cbiAgICAgIChsaXR0bGVFbmRpYW4gPyBpIDogMSAtIGkpICogOFxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9IHZhbHVlXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgfSBlbHNlIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDFdID0gdmFsdWVcbiAgfSBlbHNlIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5mdW5jdGlvbiBvYmplY3RXcml0ZVVJbnQzMiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4pIHtcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIGZvciAodmFyIGkgPSAwLCBqID0gTWF0aC5taW4oYnVmLmxlbmd0aCAtIG9mZnNldCwgNCk7IGkgPCBqOyBpKyspIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSAodmFsdWUgPj4+IChsaXR0bGVFbmRpYW4gPyBpIDogMyAtIGkpICogOCkgJiAweGZmXG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICAgIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDE2KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXRdID0gdmFsdWVcbiAgfSBlbHNlIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDI0KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDE2KVxuICAgIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9IHZhbHVlXG4gIH0gZWxzZSBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludExFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJbnQodGhpcyxcbiAgICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgICBvZmZzZXQsXG4gICAgICAgICAgICAgYnl0ZUxlbmd0aCxcbiAgICAgICAgICAgICBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCAtIDEpIC0gMSxcbiAgICAgICAgICAgICAtTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGggLSAxKSlcbiAgfVxuXG4gIHZhciBpID0gMFxuICB2YXIgbXVsID0gMVxuICB2YXIgc3ViID0gdmFsdWUgPCAwID8gMSA6IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKVxuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAoKHZhbHVlIC8gbXVsKSA+PiAwKSAtIHN1YiAmIDB4RkZcblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50QkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja0ludCh0aGlzLFxuICAgICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgICAgIG9mZnNldCxcbiAgICAgICAgICAgICBieXRlTGVuZ3RoLFxuICAgICAgICAgICAgIE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoIC0gMSkgLSAxLFxuICAgICAgICAgICAgIC1NYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCAtIDEpKVxuICB9XG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoIC0gMVxuICB2YXIgbXVsID0gMVxuICB2YXIgc3ViID0gdmFsdWUgPCAwID8gMSA6IDBcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpXG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQ4ID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDEsIDB4N2YsIC0weDgwKVxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB2YWx1ZSA9IE1hdGguZmxvb3IodmFsdWUpXG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZiArIHZhbHVlICsgMVxuICB0aGlzW29mZnNldF0gPSB2YWx1ZVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweDdmZmYsIC0weDgwMDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9IHZhbHVlXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgfSBlbHNlIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSB2YWx1ZVxuICB9IGVsc2Ugb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSB2YWx1ZVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSA+Pj4gMjQpXG4gIH0gZWxzZSBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDNdID0gdmFsdWVcbiAgfSBlbHNlIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5mdW5jdGlvbiBjaGVja0lFRUU3NTQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAodmFsdWUgPiBtYXggfHwgdmFsdWUgPCBtaW4pIHRocm93IG5ldyBSYW5nZUVycm9yKCd2YWx1ZSBpcyBvdXQgb2YgYm91bmRzJylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGJ1Zi5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdpbmRleCBvdXQgb2YgcmFuZ2UnKVxuICBpZiAob2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbmZ1bmN0aW9uIHdyaXRlRmxvYXQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSUVFRTc1NChidWYsIHZhbHVlLCBvZmZzZXQsIDQsIDMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgsIC0zLjQwMjgyMzQ2NjM4NTI4ODZlKzM4KVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCAyMywgNClcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0TEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdEJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gd3JpdGVEb3VibGUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSUVFRTc1NChidWYsIHZhbHVlLCBvZmZzZXQsIDgsIDEuNzk3NjkzMTM0ODYyMzE1N0UrMzA4LCAtMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgpXG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDUyLCA4KVxuICByZXR1cm4gb2Zmc2V0ICsgOFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlTEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuLy8gY29weSh0YXJnZXRCdWZmZXIsIHRhcmdldFN0YXJ0PTAsIHNvdXJjZVN0YXJ0PTAsIHNvdXJjZUVuZD1idWZmZXIubGVuZ3RoKVxuQnVmZmVyLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24gKHRhcmdldCwgdGFyZ2V0X3N0YXJ0LCBzdGFydCwgZW5kKSB7XG4gIHZhciBzZWxmID0gdGhpcyAvLyBzb3VyY2VcblxuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgJiYgZW5kICE9PSAwKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0X3N0YXJ0ID49IHRhcmdldC5sZW5ndGgpIHRhcmdldF9zdGFydCA9IHRhcmdldC5sZW5ndGhcbiAgaWYgKCF0YXJnZXRfc3RhcnQpIHRhcmdldF9zdGFydCA9IDBcbiAgaWYgKGVuZCA+IDAgJiYgZW5kIDwgc3RhcnQpIGVuZCA9IHN0YXJ0XG5cbiAgLy8gQ29weSAwIGJ5dGVzOyB3ZSdyZSBkb25lXG4gIGlmIChlbmQgPT09IHN0YXJ0KSByZXR1cm4gMFxuICBpZiAodGFyZ2V0Lmxlbmd0aCA9PT0gMCB8fCBzZWxmLmxlbmd0aCA9PT0gMCkgcmV0dXJuIDBcblxuICAvLyBGYXRhbCBlcnJvciBjb25kaXRpb25zXG4gIGlmICh0YXJnZXRfc3RhcnQgPCAwKVxuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCd0YXJnZXRTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgaWYgKHN0YXJ0IDwgMCB8fCBzdGFydCA+PSBzZWxmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3NvdXJjZVN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBpZiAoZW5kIDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3NvdXJjZUVuZCBvdXQgb2YgYm91bmRzJylcblxuICAvLyBBcmUgd2Ugb29iP1xuICBpZiAoZW5kID4gdGhpcy5sZW5ndGgpXG4gICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKHRhcmdldC5sZW5ndGggLSB0YXJnZXRfc3RhcnQgPCBlbmQgLSBzdGFydClcbiAgICBlbmQgPSB0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0X3N0YXJ0ICsgc3RhcnRcblxuICB2YXIgbGVuID0gZW5kIC0gc3RhcnRcblxuICBpZiAobGVuIDwgMTAwMCB8fCAhQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICB0YXJnZXRbaSArIHRhcmdldF9zdGFydF0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGFyZ2V0Ll9zZXQodGhpcy5zdWJhcnJheShzdGFydCwgc3RhcnQgKyBsZW4pLCB0YXJnZXRfc3RhcnQpXG4gIH1cblxuICByZXR1cm4gbGVuXG59XG5cbi8vIGZpbGwodmFsdWUsIHN0YXJ0PTAsIGVuZD1idWZmZXIubGVuZ3RoKVxuQnVmZmVyLnByb3RvdHlwZS5maWxsID0gZnVuY3Rpb24gKHZhbHVlLCBzdGFydCwgZW5kKSB7XG4gIGlmICghdmFsdWUpIHZhbHVlID0gMFxuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQpIGVuZCA9IHRoaXMubGVuZ3RoXG5cbiAgaWYgKGVuZCA8IHN0YXJ0KSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignZW5kIDwgc3RhcnQnKVxuXG4gIC8vIEZpbGwgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuXG4gIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuXG5cbiAgaWYgKHN0YXJ0IDwgMCB8fCBzdGFydCA+PSB0aGlzLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3N0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBpZiAoZW5kIDwgMCB8fCBlbmQgPiB0aGlzLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2VuZCBvdXQgb2YgYm91bmRzJylcblxuICB2YXIgaVxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICAgIHRoaXNbaV0gPSB2YWx1ZVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgYnl0ZXMgPSB1dGY4VG9CeXRlcyh2YWx1ZS50b1N0cmluZygpKVxuICAgIHZhciBsZW4gPSBieXRlcy5sZW5ndGhcbiAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICB0aGlzW2ldID0gYnl0ZXNbaSAlIGxlbl1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpc1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgYEFycmF5QnVmZmVyYCB3aXRoIHRoZSAqY29waWVkKiBtZW1vcnkgb2YgdGhlIGJ1ZmZlciBpbnN0YW5jZS5cbiAqIEFkZGVkIGluIE5vZGUgMC4xMi4gT25seSBhdmFpbGFibGUgaW4gYnJvd3NlcnMgdGhhdCBzdXBwb3J0IEFycmF5QnVmZmVyLlxuICovXG5CdWZmZXIucHJvdG90eXBlLnRvQXJyYXlCdWZmZXIgPSBmdW5jdGlvbiAoKSB7XG4gIGlmICh0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAgIHJldHVybiAobmV3IEJ1ZmZlcih0aGlzKSkuYnVmZmVyXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBidWYgPSBuZXcgVWludDhBcnJheSh0aGlzLmxlbmd0aClcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBidWYubGVuZ3RoOyBpIDwgbGVuOyBpICs9IDEpIHtcbiAgICAgICAgYnVmW2ldID0gdGhpc1tpXVxuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1Zi5idWZmZXJcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQnVmZmVyLnRvQXJyYXlCdWZmZXIgbm90IHN1cHBvcnRlZCBpbiB0aGlzIGJyb3dzZXInKVxuICB9XG59XG5cbi8vIEhFTFBFUiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT1cblxudmFyIEJQID0gQnVmZmVyLnByb3RvdHlwZVxuXG4vKipcbiAqIEF1Z21lbnQgYSBVaW50OEFycmF5ICppbnN0YW5jZSogKG5vdCB0aGUgVWludDhBcnJheSBjbGFzcyEpIHdpdGggQnVmZmVyIG1ldGhvZHNcbiAqL1xuQnVmZmVyLl9hdWdtZW50ID0gZnVuY3Rpb24gKGFycikge1xuICBhcnIuY29uc3RydWN0b3IgPSBCdWZmZXJcbiAgYXJyLl9pc0J1ZmZlciA9IHRydWVcblxuICAvLyBzYXZlIHJlZmVyZW5jZSB0byBvcmlnaW5hbCBVaW50OEFycmF5IGdldC9zZXQgbWV0aG9kcyBiZWZvcmUgb3ZlcndyaXRpbmdcbiAgYXJyLl9nZXQgPSBhcnIuZ2V0XG4gIGFyci5fc2V0ID0gYXJyLnNldFxuXG4gIC8vIGRlcHJlY2F0ZWQsIHdpbGwgYmUgcmVtb3ZlZCBpbiBub2RlIDAuMTMrXG4gIGFyci5nZXQgPSBCUC5nZXRcbiAgYXJyLnNldCA9IEJQLnNldFxuXG4gIGFyci53cml0ZSA9IEJQLndyaXRlXG4gIGFyci50b1N0cmluZyA9IEJQLnRvU3RyaW5nXG4gIGFyci50b0xvY2FsZVN0cmluZyA9IEJQLnRvU3RyaW5nXG4gIGFyci50b0pTT04gPSBCUC50b0pTT05cbiAgYXJyLmVxdWFscyA9IEJQLmVxdWFsc1xuICBhcnIuY29tcGFyZSA9IEJQLmNvbXBhcmVcbiAgYXJyLmNvcHkgPSBCUC5jb3B5XG4gIGFyci5zbGljZSA9IEJQLnNsaWNlXG4gIGFyci5yZWFkVUludExFID0gQlAucmVhZFVJbnRMRVxuICBhcnIucmVhZFVJbnRCRSA9IEJQLnJlYWRVSW50QkVcbiAgYXJyLnJlYWRVSW50OCA9IEJQLnJlYWRVSW50OFxuICBhcnIucmVhZFVJbnQxNkxFID0gQlAucmVhZFVJbnQxNkxFXG4gIGFyci5yZWFkVUludDE2QkUgPSBCUC5yZWFkVUludDE2QkVcbiAgYXJyLnJlYWRVSW50MzJMRSA9IEJQLnJlYWRVSW50MzJMRVxuICBhcnIucmVhZFVJbnQzMkJFID0gQlAucmVhZFVJbnQzMkJFXG4gIGFyci5yZWFkSW50TEUgPSBCUC5yZWFkSW50TEVcbiAgYXJyLnJlYWRJbnRCRSA9IEJQLnJlYWRJbnRCRVxuICBhcnIucmVhZEludDggPSBCUC5yZWFkSW50OFxuICBhcnIucmVhZEludDE2TEUgPSBCUC5yZWFkSW50MTZMRVxuICBhcnIucmVhZEludDE2QkUgPSBCUC5yZWFkSW50MTZCRVxuICBhcnIucmVhZEludDMyTEUgPSBCUC5yZWFkSW50MzJMRVxuICBhcnIucmVhZEludDMyQkUgPSBCUC5yZWFkSW50MzJCRVxuICBhcnIucmVhZEZsb2F0TEUgPSBCUC5yZWFkRmxvYXRMRVxuICBhcnIucmVhZEZsb2F0QkUgPSBCUC5yZWFkRmxvYXRCRVxuICBhcnIucmVhZERvdWJsZUxFID0gQlAucmVhZERvdWJsZUxFXG4gIGFyci5yZWFkRG91YmxlQkUgPSBCUC5yZWFkRG91YmxlQkVcbiAgYXJyLndyaXRlVUludDggPSBCUC53cml0ZVVJbnQ4XG4gIGFyci53cml0ZVVJbnRMRSA9IEJQLndyaXRlVUludExFXG4gIGFyci53cml0ZVVJbnRCRSA9IEJQLndyaXRlVUludEJFXG4gIGFyci53cml0ZVVJbnQxNkxFID0gQlAud3JpdGVVSW50MTZMRVxuICBhcnIud3JpdGVVSW50MTZCRSA9IEJQLndyaXRlVUludDE2QkVcbiAgYXJyLndyaXRlVUludDMyTEUgPSBCUC53cml0ZVVJbnQzMkxFXG4gIGFyci53cml0ZVVJbnQzMkJFID0gQlAud3JpdGVVSW50MzJCRVxuICBhcnIud3JpdGVJbnRMRSA9IEJQLndyaXRlSW50TEVcbiAgYXJyLndyaXRlSW50QkUgPSBCUC53cml0ZUludEJFXG4gIGFyci53cml0ZUludDggPSBCUC53cml0ZUludDhcbiAgYXJyLndyaXRlSW50MTZMRSA9IEJQLndyaXRlSW50MTZMRVxuICBhcnIud3JpdGVJbnQxNkJFID0gQlAud3JpdGVJbnQxNkJFXG4gIGFyci53cml0ZUludDMyTEUgPSBCUC53cml0ZUludDMyTEVcbiAgYXJyLndyaXRlSW50MzJCRSA9IEJQLndyaXRlSW50MzJCRVxuICBhcnIud3JpdGVGbG9hdExFID0gQlAud3JpdGVGbG9hdExFXG4gIGFyci53cml0ZUZsb2F0QkUgPSBCUC53cml0ZUZsb2F0QkVcbiAgYXJyLndyaXRlRG91YmxlTEUgPSBCUC53cml0ZURvdWJsZUxFXG4gIGFyci53cml0ZURvdWJsZUJFID0gQlAud3JpdGVEb3VibGVCRVxuICBhcnIuZmlsbCA9IEJQLmZpbGxcbiAgYXJyLmluc3BlY3QgPSBCUC5pbnNwZWN0XG4gIGFyci50b0FycmF5QnVmZmVyID0gQlAudG9BcnJheUJ1ZmZlclxuXG4gIHJldHVybiBhcnJcbn1cblxudmFyIElOVkFMSURfQkFTRTY0X1JFID0gL1teK1xcLzAtOUEtelxcLV0vZ1xuXG5mdW5jdGlvbiBiYXNlNjRjbGVhbiAoc3RyKSB7XG4gIC8vIE5vZGUgc3RyaXBzIG91dCBpbnZhbGlkIGNoYXJhY3RlcnMgbGlrZSBcXG4gYW5kIFxcdCBmcm9tIHRoZSBzdHJpbmcsIGJhc2U2NC1qcyBkb2VzIG5vdFxuICBzdHIgPSBzdHJpbmd0cmltKHN0cikucmVwbGFjZShJTlZBTElEX0JBU0U2NF9SRSwgJycpXG4gIC8vIE5vZGUgY29udmVydHMgc3RyaW5ncyB3aXRoIGxlbmd0aCA8IDIgdG8gJydcbiAgaWYgKHN0ci5sZW5ndGggPCAyKSByZXR1cm4gJydcbiAgLy8gTm9kZSBhbGxvd3MgZm9yIG5vbi1wYWRkZWQgYmFzZTY0IHN0cmluZ3MgKG1pc3NpbmcgdHJhaWxpbmcgPT09KSwgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHdoaWxlIChzdHIubGVuZ3RoICUgNCAhPT0gMCkge1xuICAgIHN0ciA9IHN0ciArICc9J1xuICB9XG4gIHJldHVybiBzdHJcbn1cblxuZnVuY3Rpb24gc3RyaW5ndHJpbSAoc3RyKSB7XG4gIGlmIChzdHIudHJpbSkgcmV0dXJuIHN0ci50cmltKClcbiAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLCAnJylcbn1cblxuZnVuY3Rpb24gaXNBcnJheWlzaCAoc3ViamVjdCkge1xuICByZXR1cm4gaXNBcnJheShzdWJqZWN0KSB8fCBCdWZmZXIuaXNCdWZmZXIoc3ViamVjdCkgfHxcbiAgICAgIHN1YmplY3QgJiYgdHlwZW9mIHN1YmplY3QgPT09ICdvYmplY3QnICYmXG4gICAgICB0eXBlb2Ygc3ViamVjdC5sZW5ndGggPT09ICdudW1iZXInXG59XG5cbmZ1bmN0aW9uIHRvSGV4IChuKSB7XG4gIGlmIChuIDwgMTYpIHJldHVybiAnMCcgKyBuLnRvU3RyaW5nKDE2KVxuICByZXR1cm4gbi50b1N0cmluZygxNilcbn1cblxuZnVuY3Rpb24gdXRmOFRvQnl0ZXMgKHN0cmluZywgdW5pdHMpIHtcbiAgdW5pdHMgPSB1bml0cyB8fCBJbmZpbml0eVxuICB2YXIgY29kZVBvaW50XG4gIHZhciBsZW5ndGggPSBzdHJpbmcubGVuZ3RoXG4gIHZhciBsZWFkU3Vycm9nYXRlID0gbnVsbFxuICB2YXIgYnl0ZXMgPSBbXVxuICB2YXIgaSA9IDBcblxuICBmb3IgKDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgY29kZVBvaW50ID0gc3RyaW5nLmNoYXJDb2RlQXQoaSlcblxuICAgIC8vIGlzIHN1cnJvZ2F0ZSBjb21wb25lbnRcbiAgICBpZiAoY29kZVBvaW50ID4gMHhEN0ZGICYmIGNvZGVQb2ludCA8IDB4RTAwMCkge1xuICAgICAgLy8gbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmIChsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAgIC8vIDIgbGVhZHMgaW4gYSByb3dcbiAgICAgICAgaWYgKGNvZGVQb2ludCA8IDB4REMwMCkge1xuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIHZhbGlkIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICAgICAgY29kZVBvaW50ID0gbGVhZFN1cnJvZ2F0ZSAtIDB4RDgwMCA8PCAxMCB8IGNvZGVQb2ludCAtIDB4REMwMCB8IDB4MTAwMDBcbiAgICAgICAgICBsZWFkU3Vycm9nYXRlID0gbnVsbFxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBubyBsZWFkIHlldFxuXG4gICAgICAgIGlmIChjb2RlUG9pbnQgPiAweERCRkYpIHtcbiAgICAgICAgICAvLyB1bmV4cGVjdGVkIHRyYWlsXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfSBlbHNlIGlmIChpICsgMSA9PT0gbGVuZ3RoKSB7XG4gICAgICAgICAgLy8gdW5wYWlyZWQgbGVhZFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gdmFsaWQgbGVhZFxuICAgICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAvLyB2YWxpZCBibXAgY2hhciwgYnV0IGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgIGxlYWRTdXJyb2dhdGUgPSBudWxsXG4gICAgfVxuXG4gICAgLy8gZW5jb2RlIHV0ZjhcbiAgICBpZiAoY29kZVBvaW50IDwgMHg4MCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAxKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKGNvZGVQb2ludClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4ODAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDIpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgfCAweEMwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAzKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDIHwgMHhFMCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgyMDAwMDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gNCkgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4MTIgfCAweEYwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvZGUgcG9pbnQnKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBieXRlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVRvQnl0ZXMgKHN0cikge1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAvLyBOb2RlJ3MgY29kZSBzZWVtcyB0byBiZSBkb2luZyB0aGlzIGFuZCBub3QgJiAweDdGLi5cbiAgICBieXRlQXJyYXkucHVzaChzdHIuY2hhckNvZGVBdChpKSAmIDB4RkYpXG4gIH1cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiB1dGYxNmxlVG9CeXRlcyAoc3RyLCB1bml0cykge1xuICB2YXIgYywgaGksIGxvXG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuXG4gICAgYyA9IHN0ci5jaGFyQ29kZUF0KGkpXG4gICAgaGkgPSBjID4+IDhcbiAgICBsbyA9IGMgJSAyNTZcbiAgICBieXRlQXJyYXkucHVzaChsbylcbiAgICBieXRlQXJyYXkucHVzaChoaSlcbiAgfVxuXG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gYmFzZTY0VG9CeXRlcyAoc3RyKSB7XG4gIHJldHVybiBiYXNlNjQudG9CeXRlQXJyYXkoYmFzZTY0Y2xlYW4oc3RyKSlcbn1cblxuZnVuY3Rpb24gYmxpdEJ1ZmZlciAoc3JjLCBkc3QsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoKGkgKyBvZmZzZXQgPj0gZHN0Lmxlbmd0aCkgfHwgKGkgPj0gc3JjLmxlbmd0aCkpXG4gICAgICBicmVha1xuICAgIGRzdFtpICsgb2Zmc2V0XSA9IHNyY1tpXVxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIGRlY29kZVV0ZjhDaGFyIChzdHIpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHN0cilcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoMHhGRkZEKSAvLyBVVEYgOCBpbnZhbGlkIGNoYXJcbiAgfVxufVxuIiwidmFyIGxvb2t1cCA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJztcblxuOyhmdW5jdGlvbiAoZXhwb3J0cykge1xuXHQndXNlIHN0cmljdCc7XG5cbiAgdmFyIEFyciA9ICh0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcpXG4gICAgPyBVaW50OEFycmF5XG4gICAgOiBBcnJheVxuXG5cdHZhciBQTFVTICAgPSAnKycuY2hhckNvZGVBdCgwKVxuXHR2YXIgU0xBU0ggID0gJy8nLmNoYXJDb2RlQXQoMClcblx0dmFyIE5VTUJFUiA9ICcwJy5jaGFyQ29kZUF0KDApXG5cdHZhciBMT1dFUiAgPSAnYScuY2hhckNvZGVBdCgwKVxuXHR2YXIgVVBQRVIgID0gJ0EnLmNoYXJDb2RlQXQoMClcblx0dmFyIFBMVVNfVVJMX1NBRkUgPSAnLScuY2hhckNvZGVBdCgwKVxuXHR2YXIgU0xBU0hfVVJMX1NBRkUgPSAnXycuY2hhckNvZGVBdCgwKVxuXG5cdGZ1bmN0aW9uIGRlY29kZSAoZWx0KSB7XG5cdFx0dmFyIGNvZGUgPSBlbHQuY2hhckNvZGVBdCgwKVxuXHRcdGlmIChjb2RlID09PSBQTFVTIHx8XG5cdFx0ICAgIGNvZGUgPT09IFBMVVNfVVJMX1NBRkUpXG5cdFx0XHRyZXR1cm4gNjIgLy8gJysnXG5cdFx0aWYgKGNvZGUgPT09IFNMQVNIIHx8XG5cdFx0ICAgIGNvZGUgPT09IFNMQVNIX1VSTF9TQUZFKVxuXHRcdFx0cmV0dXJuIDYzIC8vICcvJ1xuXHRcdGlmIChjb2RlIDwgTlVNQkVSKVxuXHRcdFx0cmV0dXJuIC0xIC8vbm8gbWF0Y2hcblx0XHRpZiAoY29kZSA8IE5VTUJFUiArIDEwKVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBOVU1CRVIgKyAyNiArIDI2XG5cdFx0aWYgKGNvZGUgPCBVUFBFUiArIDI2KVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBVUFBFUlxuXHRcdGlmIChjb2RlIDwgTE9XRVIgKyAyNilcblx0XHRcdHJldHVybiBjb2RlIC0gTE9XRVIgKyAyNlxuXHR9XG5cblx0ZnVuY3Rpb24gYjY0VG9CeXRlQXJyYXkgKGI2NCkge1xuXHRcdHZhciBpLCBqLCBsLCB0bXAsIHBsYWNlSG9sZGVycywgYXJyXG5cblx0XHRpZiAoYjY0Lmxlbmd0aCAlIDQgPiAwKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQnKVxuXHRcdH1cblxuXHRcdC8vIHRoZSBudW1iZXIgb2YgZXF1YWwgc2lnbnMgKHBsYWNlIGhvbGRlcnMpXG5cdFx0Ly8gaWYgdGhlcmUgYXJlIHR3byBwbGFjZWhvbGRlcnMsIHRoYW4gdGhlIHR3byBjaGFyYWN0ZXJzIGJlZm9yZSBpdFxuXHRcdC8vIHJlcHJlc2VudCBvbmUgYnl0ZVxuXHRcdC8vIGlmIHRoZXJlIGlzIG9ubHkgb25lLCB0aGVuIHRoZSB0aHJlZSBjaGFyYWN0ZXJzIGJlZm9yZSBpdCByZXByZXNlbnQgMiBieXRlc1xuXHRcdC8vIHRoaXMgaXMganVzdCBhIGNoZWFwIGhhY2sgdG8gbm90IGRvIGluZGV4T2YgdHdpY2Vcblx0XHR2YXIgbGVuID0gYjY0Lmxlbmd0aFxuXHRcdHBsYWNlSG9sZGVycyA9ICc9JyA9PT0gYjY0LmNoYXJBdChsZW4gLSAyKSA/IDIgOiAnPScgPT09IGI2NC5jaGFyQXQobGVuIC0gMSkgPyAxIDogMFxuXG5cdFx0Ly8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXG5cdFx0YXJyID0gbmV3IEFycihiNjQubGVuZ3RoICogMyAvIDQgLSBwbGFjZUhvbGRlcnMpXG5cblx0XHQvLyBpZiB0aGVyZSBhcmUgcGxhY2Vob2xkZXJzLCBvbmx5IGdldCB1cCB0byB0aGUgbGFzdCBjb21wbGV0ZSA0IGNoYXJzXG5cdFx0bCA9IHBsYWNlSG9sZGVycyA+IDAgPyBiNjQubGVuZ3RoIC0gNCA6IGI2NC5sZW5ndGhcblxuXHRcdHZhciBMID0gMFxuXG5cdFx0ZnVuY3Rpb24gcHVzaCAodikge1xuXHRcdFx0YXJyW0wrK10gPSB2XG5cdFx0fVxuXG5cdFx0Zm9yIChpID0gMCwgaiA9IDA7IGkgPCBsOyBpICs9IDQsIGogKz0gMykge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAxOCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA8PCAxMikgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDIpKSA8PCA2KSB8IGRlY29kZShiNjQuY2hhckF0KGkgKyAzKSlcblx0XHRcdHB1c2goKHRtcCAmIDB4RkYwMDAwKSA+PiAxNilcblx0XHRcdHB1c2goKHRtcCAmIDB4RkYwMCkgPj4gOClcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9XG5cblx0XHRpZiAocGxhY2VIb2xkZXJzID09PSAyKSB7XG5cdFx0XHR0bXAgPSAoZGVjb2RlKGI2NC5jaGFyQXQoaSkpIDw8IDIpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPj4gNClcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9IGVsc2UgaWYgKHBsYWNlSG9sZGVycyA9PT0gMSkge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAxMCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA8PCA0KSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMikpID4+IDIpXG5cdFx0XHRwdXNoKCh0bXAgPj4gOCkgJiAweEZGKVxuXHRcdFx0cHVzaCh0bXAgJiAweEZGKVxuXHRcdH1cblxuXHRcdHJldHVybiBhcnJcblx0fVxuXG5cdGZ1bmN0aW9uIHVpbnQ4VG9CYXNlNjQgKHVpbnQ4KSB7XG5cdFx0dmFyIGksXG5cdFx0XHRleHRyYUJ5dGVzID0gdWludDgubGVuZ3RoICUgMywgLy8gaWYgd2UgaGF2ZSAxIGJ5dGUgbGVmdCwgcGFkIDIgYnl0ZXNcblx0XHRcdG91dHB1dCA9IFwiXCIsXG5cdFx0XHR0ZW1wLCBsZW5ndGhcblxuXHRcdGZ1bmN0aW9uIGVuY29kZSAobnVtKSB7XG5cdFx0XHRyZXR1cm4gbG9va3VwLmNoYXJBdChudW0pXG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gdHJpcGxldFRvQmFzZTY0IChudW0pIHtcblx0XHRcdHJldHVybiBlbmNvZGUobnVtID4+IDE4ICYgMHgzRikgKyBlbmNvZGUobnVtID4+IDEyICYgMHgzRikgKyBlbmNvZGUobnVtID4+IDYgJiAweDNGKSArIGVuY29kZShudW0gJiAweDNGKVxuXHRcdH1cblxuXHRcdC8vIGdvIHRocm91Z2ggdGhlIGFycmF5IGV2ZXJ5IHRocmVlIGJ5dGVzLCB3ZSdsbCBkZWFsIHdpdGggdHJhaWxpbmcgc3R1ZmYgbGF0ZXJcblx0XHRmb3IgKGkgPSAwLCBsZW5ndGggPSB1aW50OC5sZW5ndGggLSBleHRyYUJ5dGVzOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHtcblx0XHRcdHRlbXAgPSAodWludDhbaV0gPDwgMTYpICsgKHVpbnQ4W2kgKyAxXSA8PCA4KSArICh1aW50OFtpICsgMl0pXG5cdFx0XHRvdXRwdXQgKz0gdHJpcGxldFRvQmFzZTY0KHRlbXApXG5cdFx0fVxuXG5cdFx0Ly8gcGFkIHRoZSBlbmQgd2l0aCB6ZXJvcywgYnV0IG1ha2Ugc3VyZSB0byBub3QgZm9yZ2V0IHRoZSBleHRyYSBieXRlc1xuXHRcdHN3aXRjaCAoZXh0cmFCeXRlcykge1xuXHRcdFx0Y2FzZSAxOlxuXHRcdFx0XHR0ZW1wID0gdWludDhbdWludDgubGVuZ3RoIC0gMV1cblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSh0ZW1wID4+IDIpXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPDwgNCkgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gJz09J1xuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAyOlxuXHRcdFx0XHR0ZW1wID0gKHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDJdIDw8IDgpICsgKHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDFdKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKHRlbXAgPj4gMTApXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPj4gNCkgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wIDw8IDIpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9ICc9J1xuXHRcdFx0XHRicmVha1xuXHRcdH1cblxuXHRcdHJldHVybiBvdXRwdXRcblx0fVxuXG5cdGV4cG9ydHMudG9CeXRlQXJyYXkgPSBiNjRUb0J5dGVBcnJheVxuXHRleHBvcnRzLmZyb21CeXRlQXJyYXkgPSB1aW50OFRvQmFzZTY0XG59KHR5cGVvZiBleHBvcnRzID09PSAndW5kZWZpbmVkJyA/ICh0aGlzLmJhc2U2NGpzID0ge30pIDogZXhwb3J0cykpXG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbihidWZmZXIsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLFxuICAgICAgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMSxcbiAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXG4gICAgICBlQmlhcyA9IGVNYXggPj4gMSxcbiAgICAgIG5CaXRzID0gLTcsXG4gICAgICBpID0gaXNMRSA/IChuQnl0ZXMgLSAxKSA6IDAsXG4gICAgICBkID0gaXNMRSA/IC0xIDogMSxcbiAgICAgIHMgPSBidWZmZXJbb2Zmc2V0ICsgaV07XG5cbiAgaSArPSBkO1xuXG4gIGUgPSBzICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpO1xuICBzID4+PSAoLW5CaXRzKTtcbiAgbkJpdHMgKz0gZUxlbjtcbiAgZm9yICg7IG5CaXRzID4gMDsgZSA9IGUgKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCk7XG5cbiAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSk7XG4gIGUgPj49ICgtbkJpdHMpO1xuICBuQml0cyArPSBtTGVuO1xuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gbSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KTtcblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXM7XG4gIH0gZWxzZSBpZiAoZSA9PT0gZU1heCkge1xuICAgIHJldHVybiBtID8gTmFOIDogKChzID8gLTEgOiAxKSAqIEluZmluaXR5KTtcbiAgfSBlbHNlIHtcbiAgICBtID0gbSArIE1hdGgucG93KDIsIG1MZW4pO1xuICAgIGUgPSBlIC0gZUJpYXM7XG4gIH1cbiAgcmV0dXJuIChzID8gLTEgOiAxKSAqIG0gKiBNYXRoLnBvdygyLCBlIC0gbUxlbik7XG59O1xuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24oYnVmZmVyLCB2YWx1ZSwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG0sIGMsXG4gICAgICBlTGVuID0gbkJ5dGVzICogOCAtIG1MZW4gLSAxLFxuICAgICAgZU1heCA9ICgxIDw8IGVMZW4pIC0gMSxcbiAgICAgIGVCaWFzID0gZU1heCA+PiAxLFxuICAgICAgcnQgPSAobUxlbiA9PT0gMjMgPyBNYXRoLnBvdygyLCAtMjQpIC0gTWF0aC5wb3coMiwgLTc3KSA6IDApLFxuICAgICAgaSA9IGlzTEUgPyAwIDogKG5CeXRlcyAtIDEpLFxuICAgICAgZCA9IGlzTEUgPyAxIDogLTEsXG4gICAgICBzID0gdmFsdWUgPCAwIHx8ICh2YWx1ZSA9PT0gMCAmJiAxIC8gdmFsdWUgPCAwKSA/IDEgOiAwO1xuXG4gIHZhbHVlID0gTWF0aC5hYnModmFsdWUpO1xuXG4gIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPT09IEluZmluaXR5KSB7XG4gICAgbSA9IGlzTmFOKHZhbHVlKSA/IDEgOiAwO1xuICAgIGUgPSBlTWF4O1xuICB9IGVsc2Uge1xuICAgIGUgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbHVlKSAvIE1hdGguTE4yKTtcbiAgICBpZiAodmFsdWUgKiAoYyA9IE1hdGgucG93KDIsIC1lKSkgPCAxKSB7XG4gICAgICBlLS07XG4gICAgICBjICo9IDI7XG4gICAgfVxuICAgIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgdmFsdWUgKz0gcnQgLyBjO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZSArPSBydCAqIE1hdGgucG93KDIsIDEgLSBlQmlhcyk7XG4gICAgfVxuICAgIGlmICh2YWx1ZSAqIGMgPj0gMikge1xuICAgICAgZSsrO1xuICAgICAgYyAvPSAyO1xuICAgIH1cblxuICAgIGlmIChlICsgZUJpYXMgPj0gZU1heCkge1xuICAgICAgbSA9IDA7XG4gICAgICBlID0gZU1heDtcbiAgICB9IGVsc2UgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICBtID0gKHZhbHVlICogYyAtIDEpICogTWF0aC5wb3coMiwgbUxlbik7XG4gICAgICBlID0gZSArIGVCaWFzO1xuICAgIH0gZWxzZSB7XG4gICAgICBtID0gdmFsdWUgKiBNYXRoLnBvdygyLCBlQmlhcyAtIDEpICogTWF0aC5wb3coMiwgbUxlbik7XG4gICAgICBlID0gMDtcbiAgICB9XG4gIH1cblxuICBmb3IgKDsgbUxlbiA+PSA4OyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBtICYgMHhmZiwgaSArPSBkLCBtIC89IDI1NiwgbUxlbiAtPSA4KTtcblxuICBlID0gKGUgPDwgbUxlbikgfCBtO1xuICBlTGVuICs9IG1MZW47XG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCk7XG5cbiAgYnVmZmVyW29mZnNldCArIGkgLSBkXSB8PSBzICogMTI4O1xufTtcbiIsIlxuLyoqXG4gKiBpc0FycmF5XG4gKi9cblxudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuXG4vKipcbiAqIHRvU3RyaW5nXG4gKi9cblxudmFyIHN0ciA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbi8qKlxuICogV2hldGhlciBvciBub3QgdGhlIGdpdmVuIGB2YWxgXG4gKiBpcyBhbiBhcnJheS5cbiAqXG4gKiBleGFtcGxlOlxuICpcbiAqICAgICAgICBpc0FycmF5KFtdKTtcbiAqICAgICAgICAvLyA+IHRydWVcbiAqICAgICAgICBpc0FycmF5KGFyZ3VtZW50cyk7XG4gKiAgICAgICAgLy8gPiBmYWxzZVxuICogICAgICAgIGlzQXJyYXkoJycpO1xuICogICAgICAgIC8vID4gZmFsc2VcbiAqXG4gKiBAcGFyYW0ge21peGVkfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2x9XG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBpc0FycmF5IHx8IGZ1bmN0aW9uICh2YWwpIHtcbiAgcmV0dXJuICEhIHZhbCAmJiAnW29iamVjdCBBcnJheV0nID09IHN0ci5jYWxsKHZhbCk7XG59O1xuIiwiKGZ1bmN0aW9uICgpIHtcbiAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgZnVuY3Rpb24gYnRvYShzdHIpIHtcbiAgICB2YXIgYnVmZmVyXG4gICAgICA7XG5cbiAgICBpZiAoc3RyIGluc3RhbmNlb2YgQnVmZmVyKSB7XG4gICAgICBidWZmZXIgPSBzdHI7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJ1ZmZlciA9IG5ldyBCdWZmZXIoc3RyLnRvU3RyaW5nKCksICdiaW5hcnknKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYnVmZmVyLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgfVxuXG4gIG1vZHVsZS5leHBvcnRzID0gYnRvYTtcbn0oKSk7XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuKGZ1bmN0aW9uICgpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIGZ1bmN0aW9uIENvb2tpZUFjY2Vzc0luZm8oZG9tYWluLCBwYXRoLCBzZWN1cmUsIHNjcmlwdCkge1xuICAgICAgICBpZiAodGhpcyBpbnN0YW5jZW9mIENvb2tpZUFjY2Vzc0luZm8pIHtcbiAgICAgICAgICAgIHRoaXMuZG9tYWluID0gZG9tYWluIHx8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMucGF0aCA9IHBhdGggfHwgXCIvXCI7XG4gICAgICAgICAgICB0aGlzLnNlY3VyZSA9ICEhc2VjdXJlO1xuICAgICAgICAgICAgdGhpcy5zY3JpcHQgPSAhIXNjcmlwdDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgQ29va2llQWNjZXNzSW5mbyhkb21haW4sIHBhdGgsIHNlY3VyZSwgc2NyaXB0KTtcbiAgICB9XG4gICAgZXhwb3J0cy5Db29raWVBY2Nlc3NJbmZvID0gQ29va2llQWNjZXNzSW5mbztcblxuICAgIGZ1bmN0aW9uIENvb2tpZShjb29raWVzdHIsIHJlcXVlc3RfZG9tYWluLCByZXF1ZXN0X3BhdGgpIHtcbiAgICAgICAgaWYgKGNvb2tpZXN0ciBpbnN0YW5jZW9mIENvb2tpZSkge1xuICAgICAgICAgICAgcmV0dXJuIGNvb2tpZXN0cjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcyBpbnN0YW5jZW9mIENvb2tpZSkge1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5leHBpcmF0aW9uX2RhdGUgPSBJbmZpbml0eTtcbiAgICAgICAgICAgIHRoaXMucGF0aCA9IFN0cmluZyhyZXF1ZXN0X3BhdGggfHwgXCIvXCIpO1xuICAgICAgICAgICAgdGhpcy5leHBsaWNpdF9wYXRoID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmRvbWFpbiA9IHJlcXVlc3RfZG9tYWluIHx8IG51bGw7XG4gICAgICAgICAgICB0aGlzLmV4cGxpY2l0X2RvbWFpbiA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5zZWN1cmUgPSBmYWxzZTsgLy9ob3cgdG8gZGVmaW5lIGRlZmF1bHQ/XG4gICAgICAgICAgICB0aGlzLm5vc2NyaXB0ID0gZmFsc2U7IC8vaHR0cG9ubHlcbiAgICAgICAgICAgIGlmIChjb29raWVzdHIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlKGNvb2tpZXN0ciwgcmVxdWVzdF9kb21haW4sIHJlcXVlc3RfcGF0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IENvb2tpZShjb29raWVzdHIpO1xuICAgIH1cbiAgICBleHBvcnRzLkNvb2tpZSA9IENvb2tpZTtcblxuICAgIENvb2tpZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICAgICAgdmFyIHN0ciA9IFt0aGlzLm5hbWUgKyBcIj1cIiArIHRoaXMudmFsdWVdO1xuICAgICAgICBpZiAodGhpcy5leHBpcmF0aW9uX2RhdGUgIT09IEluZmluaXR5KSB7XG4gICAgICAgICAgICBzdHIucHVzaChcImV4cGlyZXM9XCIgKyAobmV3IERhdGUodGhpcy5leHBpcmF0aW9uX2RhdGUpKS50b0dNVFN0cmluZygpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5kb21haW4pIHtcbiAgICAgICAgICAgIHN0ci5wdXNoKFwiZG9tYWluPVwiICsgdGhpcy5kb21haW4pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnBhdGgpIHtcbiAgICAgICAgICAgIHN0ci5wdXNoKFwicGF0aD1cIiArIHRoaXMucGF0aCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc2VjdXJlKSB7XG4gICAgICAgICAgICBzdHIucHVzaChcInNlY3VyZVwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5ub3NjcmlwdCkge1xuICAgICAgICAgICAgc3RyLnB1c2goXCJodHRwb25seVwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyLmpvaW4oXCI7IFwiKTtcbiAgICB9O1xuXG4gICAgQ29va2llLnByb3RvdHlwZS50b1ZhbHVlU3RyaW5nID0gZnVuY3Rpb24gdG9WYWx1ZVN0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubmFtZSArIFwiPVwiICsgdGhpcy52YWx1ZTtcbiAgICB9O1xuXG4gICAgdmFyIGNvb2tpZV9zdHJfc3BsaXR0ZXIgPSAvWzpdKD89XFxzKlthLXpBLVowLTlfXFwtXStcXHMqWz1dKS9nO1xuICAgIENvb2tpZS5wcm90b3R5cGUucGFyc2UgPSBmdW5jdGlvbiBwYXJzZShzdHIsIHJlcXVlc3RfZG9tYWluLCByZXF1ZXN0X3BhdGgpIHtcbiAgICAgICAgaWYgKHRoaXMgaW5zdGFuY2VvZiBDb29raWUpIHtcbiAgICAgICAgICAgIHZhciBwYXJ0cyA9IHN0ci5zcGxpdChcIjtcIikuZmlsdGVyKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gISF2YWx1ZTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBwYWlyID0gcGFydHNbMF0ubWF0Y2goLyhbXj1dKyk9KFtcXHNcXFNdKikvKSxcbiAgICAgICAgICAgICAgICBrZXkgPSBwYWlyWzFdLFxuICAgICAgICAgICAgICAgIHZhbHVlID0gcGFpclsyXSxcbiAgICAgICAgICAgICAgICBpO1xuICAgICAgICAgICAgdGhpcy5uYW1lID0ga2V5O1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAxOyBpIDwgcGFydHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICBwYWlyID0gcGFydHNbaV0ubWF0Y2goLyhbXj1dKykoPzo9KFtcXHNcXFNdKikpPy8pO1xuICAgICAgICAgICAgICAgIGtleSA9IHBhaXJbMV0udHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBwYWlyWzJdO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICAgICAgY2FzZSBcImh0dHBvbmx5XCI6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubm9zY3JpcHQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIFwiZXhwaXJlc1wiOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmV4cGlyYXRpb25fZGF0ZSA9IHZhbHVlID9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOdW1iZXIoRGF0ZS5wYXJzZSh2YWx1ZSkpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJbmZpbml0eTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBcInBhdGhcIjpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXRoID0gdmFsdWUgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLnRyaW0oKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5leHBsaWNpdF9wYXRoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBcImRvbWFpblwiOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRvbWFpbiA9IHZhbHVlID9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS50cmltKCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXhwbGljaXRfZG9tYWluID0gISF0aGlzLmRvbWFpbjtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBcInNlY3VyZVwiOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlY3VyZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0aGlzLmV4cGxpY2l0X3BhdGgpIHtcbiAgICAgICAgICAgICAgIHRoaXMucGF0aCA9IHJlcXVlc3RfcGF0aCB8fCBcIi9cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5leHBsaWNpdF9kb21haW4pIHtcbiAgICAgICAgICAgICAgIHRoaXMuZG9tYWluID0gcmVxdWVzdF9kb21haW47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgQ29va2llKCkucGFyc2Uoc3RyLCByZXF1ZXN0X2RvbWFpbiwgcmVxdWVzdF9wYXRoKTtcbiAgICB9O1xuXG4gICAgQ29va2llLnByb3RvdHlwZS5tYXRjaGVzID0gZnVuY3Rpb24gbWF0Y2hlcyhhY2Nlc3NfaW5mbykge1xuICAgICAgICBpZiAodGhpcy5ub3NjcmlwdCAmJiBhY2Nlc3NfaW5mby5zY3JpcHQgfHxcbiAgICAgICAgICAgICAgICB0aGlzLnNlY3VyZSAmJiAhYWNjZXNzX2luZm8uc2VjdXJlIHx8XG4gICAgICAgICAgICAgICAgIXRoaXMuY29sbGlkZXNXaXRoKGFjY2Vzc19pbmZvKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG5cbiAgICBDb29raWUucHJvdG90eXBlLmNvbGxpZGVzV2l0aCA9IGZ1bmN0aW9uIGNvbGxpZGVzV2l0aChhY2Nlc3NfaW5mbykge1xuICAgICAgICBpZiAoKHRoaXMucGF0aCAmJiAhYWNjZXNzX2luZm8ucGF0aCkgfHwgKHRoaXMuZG9tYWluICYmICFhY2Nlc3NfaW5mby5kb21haW4pKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucGF0aCAmJiBhY2Nlc3NfaW5mby5wYXRoLmluZGV4T2YodGhpcy5wYXRoKSAhPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5leHBsaWNpdF9wYXRoKSB7XG4gICAgICAgICAgIGlmICh0aGlzLnBhdGggIT09IGFjY2Vzc19pbmZvLnBhdGgpIHtcbiAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBhY2Nlc3NfZG9tYWluID0gYWNjZXNzX2luZm8uZG9tYWluICYmIGFjY2Vzc19pbmZvLmRvbWFpbi5yZXBsYWNlKC9eW1xcLl0vLCcnKTtcbiAgICAgICAgdmFyIGNvb2tpZV9kb21haW4gPSB0aGlzLmRvbWFpbiAmJiB0aGlzLmRvbWFpbi5yZXBsYWNlKC9eW1xcLl0vLCcnKTtcbiAgICAgICAgaWYgKGNvb2tpZV9kb21haW4gPT09IGFjY2Vzc19kb21haW4pIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb29raWVfZG9tYWluKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZXhwbGljaXRfZG9tYWluKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyB3ZSBhbHJlYWR5IGNoZWNrZWQgaWYgdGhlIGRvbWFpbnMgd2VyZSBleGFjdGx5IHRoZSBzYW1lXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgd2lsZGNhcmQgPSBhY2Nlc3NfZG9tYWluLmluZGV4T2YoY29va2llX2RvbWFpbik7XG4gICAgICAgICAgICBpZiAod2lsZGNhcmQgPT09IC0xIHx8IHdpbGRjYXJkICE9PSBhY2Nlc3NfZG9tYWluLmxlbmd0aCAtIGNvb2tpZV9kb21haW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIENvb2tpZUphcigpIHtcbiAgICAgICAgdmFyIGNvb2tpZXMsIGNvb2tpZXNfbGlzdCwgY29sbGlkYWJsZV9jb29raWU7XG4gICAgICAgIGlmICh0aGlzIGluc3RhbmNlb2YgQ29va2llSmFyKSB7XG4gICAgICAgICAgICBjb29raWVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsgLy9uYW1lOiBbQ29va2llXVxuXG4gICAgICAgICAgICB0aGlzLnNldENvb2tpZSA9IGZ1bmN0aW9uIHNldENvb2tpZShjb29raWUsIHJlcXVlc3RfZG9tYWluLCByZXF1ZXN0X3BhdGgpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlLCBpO1xuICAgICAgICAgICAgICAgIGNvb2tpZSA9IG5ldyBDb29raWUoY29va2llLCByZXF1ZXN0X2RvbWFpbiwgcmVxdWVzdF9wYXRoKTtcbiAgICAgICAgICAgICAgICAvL0RlbGV0ZSB0aGUgY29va2llIGlmIHRoZSBzZXQgaXMgcGFzdCB0aGUgY3VycmVudCB0aW1lXG4gICAgICAgICAgICAgICAgcmVtb3ZlID0gY29va2llLmV4cGlyYXRpb25fZGF0ZSA8PSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgIGlmIChjb29raWVzW2Nvb2tpZS5uYW1lXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvb2tpZXNfbGlzdCA9IGNvb2tpZXNbY29va2llLm5hbWVdO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29va2llc19saXN0Lmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xsaWRhYmxlX2Nvb2tpZSA9IGNvb2tpZXNfbGlzdFtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb2xsaWRhYmxlX2Nvb2tpZS5jb2xsaWRlc1dpdGgoY29va2llKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29va2llc19saXN0LnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvb2tpZXNfbGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBjb29raWVzW2Nvb2tpZS5uYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb2tpZXNfbGlzdFtpXSA9IGNvb2tpZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29va2llO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb29raWVzX2xpc3QucHVzaChjb29raWUpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29va2llO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29va2llc1tjb29raWUubmFtZV0gPSBbY29va2llXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29va2llc1tjb29raWUubmFtZV07XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLy9yZXR1cm5zIGEgY29va2llXG4gICAgICAgICAgICB0aGlzLmdldENvb2tpZSA9IGZ1bmN0aW9uIGdldENvb2tpZShjb29raWVfbmFtZSwgYWNjZXNzX2luZm8pIHtcbiAgICAgICAgICAgICAgICB2YXIgY29va2llLCBpO1xuICAgICAgICAgICAgICAgIGNvb2tpZXNfbGlzdCA9IGNvb2tpZXNbY29va2llX25hbWVdO1xuICAgICAgICAgICAgICAgIGlmICghY29va2llc19saXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvb2tpZXNfbGlzdC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICBjb29raWUgPSBjb29raWVzX2xpc3RbaV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb29raWUuZXhwaXJhdGlvbl9kYXRlIDw9IERhdGUubm93KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb29raWVzX2xpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGNvb2tpZXNbY29va2llLm5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvb2tpZS5tYXRjaGVzKGFjY2Vzc19pbmZvKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvb2tpZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvL3JldHVybnMgYSBsaXN0IG9mIGNvb2tpZXNcbiAgICAgICAgICAgIHRoaXMuZ2V0Q29va2llcyA9IGZ1bmN0aW9uIGdldENvb2tpZXMoYWNjZXNzX2luZm8pIHtcbiAgICAgICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IFtdLCBjb29raWVfbmFtZSwgY29va2llO1xuICAgICAgICAgICAgICAgIGZvciAoY29va2llX25hbWUgaW4gY29va2llcykge1xuICAgICAgICAgICAgICAgICAgICBjb29raWUgPSB0aGlzLmdldENvb2tpZShjb29raWVfbmFtZSwgYWNjZXNzX2luZm8pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29va2llKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzLnB1c2goY29va2llKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtYXRjaGVzLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXRjaGVzLmpvaW4oXCI6XCIpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgbWF0Y2hlcy50b1ZhbHVlU3RyaW5nID0gZnVuY3Rpb24gdG9WYWx1ZVN0cmluZygpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXMubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYy50b1ZhbHVlU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmpvaW4oJzsnKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXRjaGVzO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBDb29raWVKYXIoKTtcbiAgICB9XG4gICAgZXhwb3J0cy5Db29raWVKYXIgPSBDb29raWVKYXI7XG5cbiAgICAvL3JldHVybnMgbGlzdCBvZiBjb29raWVzIHRoYXQgd2VyZSBzZXQgY29ycmVjdGx5LiBDb29raWVzIHRoYXQgYXJlIGV4cGlyZWQgYW5kIHJlbW92ZWQgYXJlIG5vdCByZXR1cm5lZC5cbiAgICBDb29raWVKYXIucHJvdG90eXBlLnNldENvb2tpZXMgPSBmdW5jdGlvbiBzZXRDb29raWVzKGNvb2tpZXMsIHJlcXVlc3RfZG9tYWluLCByZXF1ZXN0X3BhdGgpIHtcbiAgICAgICAgY29va2llcyA9IEFycmF5LmlzQXJyYXkoY29va2llcykgP1xuICAgICAgICAgICAgICAgIGNvb2tpZXMgOlxuICAgICAgICAgICAgICAgIGNvb2tpZXMuc3BsaXQoY29va2llX3N0cl9zcGxpdHRlcik7XG4gICAgICAgIHZhciBzdWNjZXNzZnVsID0gW10sXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgY29va2llO1xuICAgICAgICBjb29raWVzID0gY29va2llcy5tYXAoQ29va2llKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvb2tpZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGNvb2tpZSA9IGNvb2tpZXNbaV07XG4gICAgICAgICAgICBpZiAodGhpcy5zZXRDb29raWUoY29va2llLCByZXF1ZXN0X2RvbWFpbiwgcmVxdWVzdF9wYXRoKSkge1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3NmdWwucHVzaChjb29raWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdWNjZXNzZnVsO1xuICAgIH07XG59KCkpO1xuIiwiLyohXG4gKiBqUXVlcnkgSmF2YVNjcmlwdCBMaWJyYXJ5IHYyLjEuM1xuICogaHR0cDovL2pxdWVyeS5jb20vXG4gKlxuICogSW5jbHVkZXMgU2l6emxlLmpzXG4gKiBodHRwOi8vc2l6emxlanMuY29tL1xuICpcbiAqIENvcHlyaWdodCAyMDA1LCAyMDE0IGpRdWVyeSBGb3VuZGF0aW9uLCBJbmMuIGFuZCBvdGhlciBjb250cmlidXRvcnNcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZVxuICogaHR0cDovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIERhdGU6IDIwMTQtMTItMThUMTU6MTFaXG4gKi9cblxuKGZ1bmN0aW9uKCBnbG9iYWwsIGZhY3RvcnkgKSB7XG5cblx0aWYgKCB0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIiApIHtcblx0XHQvLyBGb3IgQ29tbW9uSlMgYW5kIENvbW1vbkpTLWxpa2UgZW52aXJvbm1lbnRzIHdoZXJlIGEgcHJvcGVyIGB3aW5kb3dgXG5cdFx0Ly8gaXMgcHJlc2VudCwgZXhlY3V0ZSB0aGUgZmFjdG9yeSBhbmQgZ2V0IGpRdWVyeS5cblx0XHQvLyBGb3IgZW52aXJvbm1lbnRzIHRoYXQgZG8gbm90IGhhdmUgYSBgd2luZG93YCB3aXRoIGEgYGRvY3VtZW50YFxuXHRcdC8vIChzdWNoIGFzIE5vZGUuanMpLCBleHBvc2UgYSBmYWN0b3J5IGFzIG1vZHVsZS5leHBvcnRzLlxuXHRcdC8vIFRoaXMgYWNjZW50dWF0ZXMgdGhlIG5lZWQgZm9yIHRoZSBjcmVhdGlvbiBvZiBhIHJlYWwgYHdpbmRvd2AuXG5cdFx0Ly8gZS5nLiB2YXIgalF1ZXJ5ID0gcmVxdWlyZShcImpxdWVyeVwiKSh3aW5kb3cpO1xuXHRcdC8vIFNlZSB0aWNrZXQgIzE0NTQ5IGZvciBtb3JlIGluZm8uXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBnbG9iYWwuZG9jdW1lbnQgP1xuXHRcdFx0ZmFjdG9yeSggZ2xvYmFsLCB0cnVlICkgOlxuXHRcdFx0ZnVuY3Rpb24oIHcgKSB7XG5cdFx0XHRcdGlmICggIXcuZG9jdW1lbnQgKSB7XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcImpRdWVyeSByZXF1aXJlcyBhIHdpbmRvdyB3aXRoIGEgZG9jdW1lbnRcIiApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBmYWN0b3J5KCB3ICk7XG5cdFx0XHR9O1xuXHR9IGVsc2Uge1xuXHRcdGZhY3RvcnkoIGdsb2JhbCApO1xuXHR9XG5cbi8vIFBhc3MgdGhpcyBpZiB3aW5kb3cgaXMgbm90IGRlZmluZWQgeWV0XG59KHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0aGlzLCBmdW5jdGlvbiggd2luZG93LCBub0dsb2JhbCApIHtcblxuLy8gU3VwcG9ydDogRmlyZWZveCAxOCtcbi8vIENhbid0IGJlIGluIHN0cmljdCBtb2RlLCBzZXZlcmFsIGxpYnMgaW5jbHVkaW5nIEFTUC5ORVQgdHJhY2Vcbi8vIHRoZSBzdGFjayB2aWEgYXJndW1lbnRzLmNhbGxlci5jYWxsZWUgYW5kIEZpcmVmb3ggZGllcyBpZlxuLy8geW91IHRyeSB0byB0cmFjZSB0aHJvdWdoIFwidXNlIHN0cmljdFwiIGNhbGwgY2hhaW5zLiAoIzEzMzM1KVxuLy9cblxudmFyIGFyciA9IFtdO1xuXG52YXIgc2xpY2UgPSBhcnIuc2xpY2U7XG5cbnZhciBjb25jYXQgPSBhcnIuY29uY2F0O1xuXG52YXIgcHVzaCA9IGFyci5wdXNoO1xuXG52YXIgaW5kZXhPZiA9IGFyci5pbmRleE9mO1xuXG52YXIgY2xhc3MydHlwZSA9IHt9O1xuXG52YXIgdG9TdHJpbmcgPSBjbGFzczJ0eXBlLnRvU3RyaW5nO1xuXG52YXIgaGFzT3duID0gY2xhc3MydHlwZS5oYXNPd25Qcm9wZXJ0eTtcblxudmFyIHN1cHBvcnQgPSB7fTtcblxuXG5cbnZhclxuXHQvLyBVc2UgdGhlIGNvcnJlY3QgZG9jdW1lbnQgYWNjb3JkaW5nbHkgd2l0aCB3aW5kb3cgYXJndW1lbnQgKHNhbmRib3gpXG5cdGRvY3VtZW50ID0gd2luZG93LmRvY3VtZW50LFxuXG5cdHZlcnNpb24gPSBcIjIuMS4zXCIsXG5cblx0Ly8gRGVmaW5lIGEgbG9jYWwgY29weSBvZiBqUXVlcnlcblx0alF1ZXJ5ID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBjb250ZXh0ICkge1xuXHRcdC8vIFRoZSBqUXVlcnkgb2JqZWN0IGlzIGFjdHVhbGx5IGp1c3QgdGhlIGluaXQgY29uc3RydWN0b3IgJ2VuaGFuY2VkJ1xuXHRcdC8vIE5lZWQgaW5pdCBpZiBqUXVlcnkgaXMgY2FsbGVkIChqdXN0IGFsbG93IGVycm9yIHRvIGJlIHRocm93biBpZiBub3QgaW5jbHVkZWQpXG5cdFx0cmV0dXJuIG5ldyBqUXVlcnkuZm4uaW5pdCggc2VsZWN0b3IsIGNvbnRleHQgKTtcblx0fSxcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkPDQuMVxuXHQvLyBNYWtlIHN1cmUgd2UgdHJpbSBCT00gYW5kIE5CU1Bcblx0cnRyaW0gPSAvXltcXHNcXHVGRUZGXFx4QTBdK3xbXFxzXFx1RkVGRlxceEEwXSskL2csXG5cblx0Ly8gTWF0Y2hlcyBkYXNoZWQgc3RyaW5nIGZvciBjYW1lbGl6aW5nXG5cdHJtc1ByZWZpeCA9IC9eLW1zLS8sXG5cdHJkYXNoQWxwaGEgPSAvLShbXFxkYS16XSkvZ2ksXG5cblx0Ly8gVXNlZCBieSBqUXVlcnkuY2FtZWxDYXNlIGFzIGNhbGxiYWNrIHRvIHJlcGxhY2UoKVxuXHRmY2FtZWxDYXNlID0gZnVuY3Rpb24oIGFsbCwgbGV0dGVyICkge1xuXHRcdHJldHVybiBsZXR0ZXIudG9VcHBlckNhc2UoKTtcblx0fTtcblxualF1ZXJ5LmZuID0galF1ZXJ5LnByb3RvdHlwZSA9IHtcblx0Ly8gVGhlIGN1cnJlbnQgdmVyc2lvbiBvZiBqUXVlcnkgYmVpbmcgdXNlZFxuXHRqcXVlcnk6IHZlcnNpb24sXG5cblx0Y29uc3RydWN0b3I6IGpRdWVyeSxcblxuXHQvLyBTdGFydCB3aXRoIGFuIGVtcHR5IHNlbGVjdG9yXG5cdHNlbGVjdG9yOiBcIlwiLFxuXG5cdC8vIFRoZSBkZWZhdWx0IGxlbmd0aCBvZiBhIGpRdWVyeSBvYmplY3QgaXMgMFxuXHRsZW5ndGg6IDAsXG5cblx0dG9BcnJheTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHNsaWNlLmNhbGwoIHRoaXMgKTtcblx0fSxcblxuXHQvLyBHZXQgdGhlIE50aCBlbGVtZW50IGluIHRoZSBtYXRjaGVkIGVsZW1lbnQgc2V0IE9SXG5cdC8vIEdldCB0aGUgd2hvbGUgbWF0Y2hlZCBlbGVtZW50IHNldCBhcyBhIGNsZWFuIGFycmF5XG5cdGdldDogZnVuY3Rpb24oIG51bSApIHtcblx0XHRyZXR1cm4gbnVtICE9IG51bGwgP1xuXG5cdFx0XHQvLyBSZXR1cm4ganVzdCB0aGUgb25lIGVsZW1lbnQgZnJvbSB0aGUgc2V0XG5cdFx0XHQoIG51bSA8IDAgPyB0aGlzWyBudW0gKyB0aGlzLmxlbmd0aCBdIDogdGhpc1sgbnVtIF0gKSA6XG5cblx0XHRcdC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIGluIGEgY2xlYW4gYXJyYXlcblx0XHRcdHNsaWNlLmNhbGwoIHRoaXMgKTtcblx0fSxcblxuXHQvLyBUYWtlIGFuIGFycmF5IG9mIGVsZW1lbnRzIGFuZCBwdXNoIGl0IG9udG8gdGhlIHN0YWNrXG5cdC8vIChyZXR1cm5pbmcgdGhlIG5ldyBtYXRjaGVkIGVsZW1lbnQgc2V0KVxuXHRwdXNoU3RhY2s6IGZ1bmN0aW9uKCBlbGVtcyApIHtcblxuXHRcdC8vIEJ1aWxkIGEgbmV3IGpRdWVyeSBtYXRjaGVkIGVsZW1lbnQgc2V0XG5cdFx0dmFyIHJldCA9IGpRdWVyeS5tZXJnZSggdGhpcy5jb25zdHJ1Y3RvcigpLCBlbGVtcyApO1xuXG5cdFx0Ly8gQWRkIHRoZSBvbGQgb2JqZWN0IG9udG8gdGhlIHN0YWNrIChhcyBhIHJlZmVyZW5jZSlcblx0XHRyZXQucHJldk9iamVjdCA9IHRoaXM7XG5cdFx0cmV0LmNvbnRleHQgPSB0aGlzLmNvbnRleHQ7XG5cblx0XHQvLyBSZXR1cm4gdGhlIG5ld2x5LWZvcm1lZCBlbGVtZW50IHNldFxuXHRcdHJldHVybiByZXQ7XG5cdH0sXG5cblx0Ly8gRXhlY3V0ZSBhIGNhbGxiYWNrIGZvciBldmVyeSBlbGVtZW50IGluIHRoZSBtYXRjaGVkIHNldC5cblx0Ly8gKFlvdSBjYW4gc2VlZCB0aGUgYXJndW1lbnRzIHdpdGggYW4gYXJyYXkgb2YgYXJncywgYnV0IHRoaXMgaXNcblx0Ly8gb25seSB1c2VkIGludGVybmFsbHkuKVxuXHRlYWNoOiBmdW5jdGlvbiggY2FsbGJhY2ssIGFyZ3MgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5lYWNoKCB0aGlzLCBjYWxsYmFjaywgYXJncyApO1xuXHR9LFxuXG5cdG1hcDogZnVuY3Rpb24oIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggalF1ZXJ5Lm1hcCh0aGlzLCBmdW5jdGlvbiggZWxlbSwgaSApIHtcblx0XHRcdHJldHVybiBjYWxsYmFjay5jYWxsKCBlbGVtLCBpLCBlbGVtICk7XG5cdFx0fSkpO1xuXHR9LFxuXG5cdHNsaWNlOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIHNsaWNlLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKSApO1xuXHR9LFxuXG5cdGZpcnN0OiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5lcSggMCApO1xuXHR9LFxuXG5cdGxhc3Q6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmVxKCAtMSApO1xuXHR9LFxuXG5cdGVxOiBmdW5jdGlvbiggaSApIHtcblx0XHR2YXIgbGVuID0gdGhpcy5sZW5ndGgsXG5cdFx0XHRqID0gK2kgKyAoIGkgPCAwID8gbGVuIDogMCApO1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggaiA+PSAwICYmIGogPCBsZW4gPyBbIHRoaXNbal0gXSA6IFtdICk7XG5cdH0sXG5cblx0ZW5kOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5wcmV2T2JqZWN0IHx8IHRoaXMuY29uc3RydWN0b3IobnVsbCk7XG5cdH0sXG5cblx0Ly8gRm9yIGludGVybmFsIHVzZSBvbmx5LlxuXHQvLyBCZWhhdmVzIGxpa2UgYW4gQXJyYXkncyBtZXRob2QsIG5vdCBsaWtlIGEgalF1ZXJ5IG1ldGhvZC5cblx0cHVzaDogcHVzaCxcblx0c29ydDogYXJyLnNvcnQsXG5cdHNwbGljZTogYXJyLnNwbGljZVxufTtcblxualF1ZXJ5LmV4dGVuZCA9IGpRdWVyeS5mbi5leHRlbmQgPSBmdW5jdGlvbigpIHtcblx0dmFyIG9wdGlvbnMsIG5hbWUsIHNyYywgY29weSwgY29weUlzQXJyYXksIGNsb25lLFxuXHRcdHRhcmdldCA9IGFyZ3VtZW50c1swXSB8fCB7fSxcblx0XHRpID0gMSxcblx0XHRsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoLFxuXHRcdGRlZXAgPSBmYWxzZTtcblxuXHQvLyBIYW5kbGUgYSBkZWVwIGNvcHkgc2l0dWF0aW9uXG5cdGlmICggdHlwZW9mIHRhcmdldCA9PT0gXCJib29sZWFuXCIgKSB7XG5cdFx0ZGVlcCA9IHRhcmdldDtcblxuXHRcdC8vIFNraXAgdGhlIGJvb2xlYW4gYW5kIHRoZSB0YXJnZXRcblx0XHR0YXJnZXQgPSBhcmd1bWVudHNbIGkgXSB8fCB7fTtcblx0XHRpKys7XG5cdH1cblxuXHQvLyBIYW5kbGUgY2FzZSB3aGVuIHRhcmdldCBpcyBhIHN0cmluZyBvciBzb21ldGhpbmcgKHBvc3NpYmxlIGluIGRlZXAgY29weSlcblx0aWYgKCB0eXBlb2YgdGFyZ2V0ICE9PSBcIm9iamVjdFwiICYmICFqUXVlcnkuaXNGdW5jdGlvbih0YXJnZXQpICkge1xuXHRcdHRhcmdldCA9IHt9O1xuXHR9XG5cblx0Ly8gRXh0ZW5kIGpRdWVyeSBpdHNlbGYgaWYgb25seSBvbmUgYXJndW1lbnQgaXMgcGFzc2VkXG5cdGlmICggaSA9PT0gbGVuZ3RoICkge1xuXHRcdHRhcmdldCA9IHRoaXM7XG5cdFx0aS0tO1xuXHR9XG5cblx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpKysgKSB7XG5cdFx0Ly8gT25seSBkZWFsIHdpdGggbm9uLW51bGwvdW5kZWZpbmVkIHZhbHVlc1xuXHRcdGlmICggKG9wdGlvbnMgPSBhcmd1bWVudHNbIGkgXSkgIT0gbnVsbCApIHtcblx0XHRcdC8vIEV4dGVuZCB0aGUgYmFzZSBvYmplY3Rcblx0XHRcdGZvciAoIG5hbWUgaW4gb3B0aW9ucyApIHtcblx0XHRcdFx0c3JjID0gdGFyZ2V0WyBuYW1lIF07XG5cdFx0XHRcdGNvcHkgPSBvcHRpb25zWyBuYW1lIF07XG5cblx0XHRcdFx0Ly8gUHJldmVudCBuZXZlci1lbmRpbmcgbG9vcFxuXHRcdFx0XHRpZiAoIHRhcmdldCA9PT0gY29weSApIHtcblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFJlY3Vyc2UgaWYgd2UncmUgbWVyZ2luZyBwbGFpbiBvYmplY3RzIG9yIGFycmF5c1xuXHRcdFx0XHRpZiAoIGRlZXAgJiYgY29weSAmJiAoIGpRdWVyeS5pc1BsYWluT2JqZWN0KGNvcHkpIHx8IChjb3B5SXNBcnJheSA9IGpRdWVyeS5pc0FycmF5KGNvcHkpKSApICkge1xuXHRcdFx0XHRcdGlmICggY29weUlzQXJyYXkgKSB7XG5cdFx0XHRcdFx0XHRjb3B5SXNBcnJheSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0Y2xvbmUgPSBzcmMgJiYgalF1ZXJ5LmlzQXJyYXkoc3JjKSA/IHNyYyA6IFtdO1xuXG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGNsb25lID0gc3JjICYmIGpRdWVyeS5pc1BsYWluT2JqZWN0KHNyYykgPyBzcmMgOiB7fTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBOZXZlciBtb3ZlIG9yaWdpbmFsIG9iamVjdHMsIGNsb25lIHRoZW1cblx0XHRcdFx0XHR0YXJnZXRbIG5hbWUgXSA9IGpRdWVyeS5leHRlbmQoIGRlZXAsIGNsb25lLCBjb3B5ICk7XG5cblx0XHRcdFx0Ly8gRG9uJ3QgYnJpbmcgaW4gdW5kZWZpbmVkIHZhbHVlc1xuXHRcdFx0XHR9IGVsc2UgaWYgKCBjb3B5ICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0dGFyZ2V0WyBuYW1lIF0gPSBjb3B5O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gUmV0dXJuIHRoZSBtb2RpZmllZCBvYmplY3Rcblx0cmV0dXJuIHRhcmdldDtcbn07XG5cbmpRdWVyeS5leHRlbmQoe1xuXHQvLyBVbmlxdWUgZm9yIGVhY2ggY29weSBvZiBqUXVlcnkgb24gdGhlIHBhZ2Vcblx0ZXhwYW5kbzogXCJqUXVlcnlcIiArICggdmVyc2lvbiArIE1hdGgucmFuZG9tKCkgKS5yZXBsYWNlKCAvXFxEL2csIFwiXCIgKSxcblxuXHQvLyBBc3N1bWUgalF1ZXJ5IGlzIHJlYWR5IHdpdGhvdXQgdGhlIHJlYWR5IG1vZHVsZVxuXHRpc1JlYWR5OiB0cnVlLFxuXG5cdGVycm9yOiBmdW5jdGlvbiggbXNnICkge1xuXHRcdHRocm93IG5ldyBFcnJvciggbXNnICk7XG5cdH0sXG5cblx0bm9vcDogZnVuY3Rpb24oKSB7fSxcblxuXHRpc0Z1bmN0aW9uOiBmdW5jdGlvbiggb2JqICkge1xuXHRcdHJldHVybiBqUXVlcnkudHlwZShvYmopID09PSBcImZ1bmN0aW9uXCI7XG5cdH0sXG5cblx0aXNBcnJheTogQXJyYXkuaXNBcnJheSxcblxuXHRpc1dpbmRvdzogZnVuY3Rpb24oIG9iaiApIHtcblx0XHRyZXR1cm4gb2JqICE9IG51bGwgJiYgb2JqID09PSBvYmoud2luZG93O1xuXHR9LFxuXG5cdGlzTnVtZXJpYzogZnVuY3Rpb24oIG9iaiApIHtcblx0XHQvLyBwYXJzZUZsb2F0IE5hTnMgbnVtZXJpYy1jYXN0IGZhbHNlIHBvc2l0aXZlcyAobnVsbHx0cnVlfGZhbHNlfFwiXCIpXG5cdFx0Ly8gLi4uYnV0IG1pc2ludGVycHJldHMgbGVhZGluZy1udW1iZXIgc3RyaW5ncywgcGFydGljdWxhcmx5IGhleCBsaXRlcmFscyAoXCIweC4uLlwiKVxuXHRcdC8vIHN1YnRyYWN0aW9uIGZvcmNlcyBpbmZpbml0aWVzIHRvIE5hTlxuXHRcdC8vIGFkZGluZyAxIGNvcnJlY3RzIGxvc3Mgb2YgcHJlY2lzaW9uIGZyb20gcGFyc2VGbG9hdCAoIzE1MTAwKVxuXHRcdHJldHVybiAhalF1ZXJ5LmlzQXJyYXkoIG9iaiApICYmIChvYmogLSBwYXJzZUZsb2F0KCBvYmogKSArIDEpID49IDA7XG5cdH0sXG5cblx0aXNQbGFpbk9iamVjdDogZnVuY3Rpb24oIG9iaiApIHtcblx0XHQvLyBOb3QgcGxhaW4gb2JqZWN0czpcblx0XHQvLyAtIEFueSBvYmplY3Qgb3IgdmFsdWUgd2hvc2UgaW50ZXJuYWwgW1tDbGFzc11dIHByb3BlcnR5IGlzIG5vdCBcIltvYmplY3QgT2JqZWN0XVwiXG5cdFx0Ly8gLSBET00gbm9kZXNcblx0XHQvLyAtIHdpbmRvd1xuXHRcdGlmICggalF1ZXJ5LnR5cGUoIG9iaiApICE9PSBcIm9iamVjdFwiIHx8IG9iai5ub2RlVHlwZSB8fCBqUXVlcnkuaXNXaW5kb3coIG9iaiApICkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmICggb2JqLmNvbnN0cnVjdG9yICYmXG5cdFx0XHRcdCFoYXNPd24uY2FsbCggb2JqLmNvbnN0cnVjdG9yLnByb3RvdHlwZSwgXCJpc1Byb3RvdHlwZU9mXCIgKSApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHQvLyBJZiB0aGUgZnVuY3Rpb24gaGFzbid0IHJldHVybmVkIGFscmVhZHksIHdlJ3JlIGNvbmZpZGVudCB0aGF0XG5cdFx0Ly8gfG9ianwgaXMgYSBwbGFpbiBvYmplY3QsIGNyZWF0ZWQgYnkge30gb3IgY29uc3RydWN0ZWQgd2l0aCBuZXcgT2JqZWN0XG5cdFx0cmV0dXJuIHRydWU7XG5cdH0sXG5cblx0aXNFbXB0eU9iamVjdDogZnVuY3Rpb24oIG9iaiApIHtcblx0XHR2YXIgbmFtZTtcblx0XHRmb3IgKCBuYW1lIGluIG9iaiApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH0sXG5cblx0dHlwZTogZnVuY3Rpb24oIG9iaiApIHtcblx0XHRpZiAoIG9iaiA9PSBudWxsICkge1xuXHRcdFx0cmV0dXJuIG9iaiArIFwiXCI7XG5cdFx0fVxuXHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQ8NC4wLCBpT1M8NiAoZnVuY3Rpb25pc2ggUmVnRXhwKVxuXHRcdHJldHVybiB0eXBlb2Ygb2JqID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBvYmogPT09IFwiZnVuY3Rpb25cIiA/XG5cdFx0XHRjbGFzczJ0eXBlWyB0b1N0cmluZy5jYWxsKG9iaikgXSB8fCBcIm9iamVjdFwiIDpcblx0XHRcdHR5cGVvZiBvYmo7XG5cdH0sXG5cblx0Ly8gRXZhbHVhdGVzIGEgc2NyaXB0IGluIGEgZ2xvYmFsIGNvbnRleHRcblx0Z2xvYmFsRXZhbDogZnVuY3Rpb24oIGNvZGUgKSB7XG5cdFx0dmFyIHNjcmlwdCxcblx0XHRcdGluZGlyZWN0ID0gZXZhbDtcblxuXHRcdGNvZGUgPSBqUXVlcnkudHJpbSggY29kZSApO1xuXG5cdFx0aWYgKCBjb2RlICkge1xuXHRcdFx0Ly8gSWYgdGhlIGNvZGUgaW5jbHVkZXMgYSB2YWxpZCwgcHJvbG9ndWUgcG9zaXRpb25cblx0XHRcdC8vIHN0cmljdCBtb2RlIHByYWdtYSwgZXhlY3V0ZSBjb2RlIGJ5IGluamVjdGluZyBhXG5cdFx0XHQvLyBzY3JpcHQgdGFnIGludG8gdGhlIGRvY3VtZW50LlxuXHRcdFx0aWYgKCBjb2RlLmluZGV4T2YoXCJ1c2Ugc3RyaWN0XCIpID09PSAxICkge1xuXHRcdFx0XHRzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic2NyaXB0XCIpO1xuXHRcdFx0XHRzY3JpcHQudGV4dCA9IGNvZGU7XG5cdFx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoIHNjcmlwdCApLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIHNjcmlwdCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdC8vIE90aGVyd2lzZSwgYXZvaWQgdGhlIERPTSBub2RlIGNyZWF0aW9uLCBpbnNlcnRpb25cblx0XHRcdC8vIGFuZCByZW1vdmFsIGJ5IHVzaW5nIGFuIGluZGlyZWN0IGdsb2JhbCBldmFsXG5cdFx0XHRcdGluZGlyZWN0KCBjb2RlICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdC8vIENvbnZlcnQgZGFzaGVkIHRvIGNhbWVsQ2FzZTsgdXNlZCBieSB0aGUgY3NzIGFuZCBkYXRhIG1vZHVsZXNcblx0Ly8gU3VwcG9ydDogSUU5LTExK1xuXHQvLyBNaWNyb3NvZnQgZm9yZ290IHRvIGh1bXAgdGhlaXIgdmVuZG9yIHByZWZpeCAoIzk1NzIpXG5cdGNhbWVsQ2FzZTogZnVuY3Rpb24oIHN0cmluZyApIHtcblx0XHRyZXR1cm4gc3RyaW5nLnJlcGxhY2UoIHJtc1ByZWZpeCwgXCJtcy1cIiApLnJlcGxhY2UoIHJkYXNoQWxwaGEsIGZjYW1lbENhc2UgKTtcblx0fSxcblxuXHRub2RlTmFtZTogZnVuY3Rpb24oIGVsZW0sIG5hbWUgKSB7XG5cdFx0cmV0dXJuIGVsZW0ubm9kZU5hbWUgJiYgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBuYW1lLnRvTG93ZXJDYXNlKCk7XG5cdH0sXG5cblx0Ly8gYXJncyBpcyBmb3IgaW50ZXJuYWwgdXNhZ2Ugb25seVxuXHRlYWNoOiBmdW5jdGlvbiggb2JqLCBjYWxsYmFjaywgYXJncyApIHtcblx0XHR2YXIgdmFsdWUsXG5cdFx0XHRpID0gMCxcblx0XHRcdGxlbmd0aCA9IG9iai5sZW5ndGgsXG5cdFx0XHRpc0FycmF5ID0gaXNBcnJheWxpa2UoIG9iaiApO1xuXG5cdFx0aWYgKCBhcmdzICkge1xuXHRcdFx0aWYgKCBpc0FycmF5ICkge1xuXHRcdFx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0XHR2YWx1ZSA9IGNhbGxiYWNrLmFwcGx5KCBvYmpbIGkgXSwgYXJncyApO1xuXG5cdFx0XHRcdFx0aWYgKCB2YWx1ZSA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGZvciAoIGkgaW4gb2JqICkge1xuXHRcdFx0XHRcdHZhbHVlID0gY2FsbGJhY2suYXBwbHkoIG9ialsgaSBdLCBhcmdzICk7XG5cblx0XHRcdFx0XHRpZiAoIHZhbHVlID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0Ly8gQSBzcGVjaWFsLCBmYXN0LCBjYXNlIGZvciB0aGUgbW9zdCBjb21tb24gdXNlIG9mIGVhY2hcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCBpc0FycmF5ICkge1xuXHRcdFx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0XHR2YWx1ZSA9IGNhbGxiYWNrLmNhbGwoIG9ialsgaSBdLCBpLCBvYmpbIGkgXSApO1xuXG5cdFx0XHRcdFx0aWYgKCB2YWx1ZSA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGZvciAoIGkgaW4gb2JqICkge1xuXHRcdFx0XHRcdHZhbHVlID0gY2FsbGJhY2suY2FsbCggb2JqWyBpIF0sIGksIG9ialsgaSBdICk7XG5cblx0XHRcdFx0XHRpZiAoIHZhbHVlID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBvYmo7XG5cdH0sXG5cblx0Ly8gU3VwcG9ydDogQW5kcm9pZDw0LjFcblx0dHJpbTogZnVuY3Rpb24oIHRleHQgKSB7XG5cdFx0cmV0dXJuIHRleHQgPT0gbnVsbCA/XG5cdFx0XHRcIlwiIDpcblx0XHRcdCggdGV4dCArIFwiXCIgKS5yZXBsYWNlKCBydHJpbSwgXCJcIiApO1xuXHR9LFxuXG5cdC8vIHJlc3VsdHMgaXMgZm9yIGludGVybmFsIHVzYWdlIG9ubHlcblx0bWFrZUFycmF5OiBmdW5jdGlvbiggYXJyLCByZXN1bHRzICkge1xuXHRcdHZhciByZXQgPSByZXN1bHRzIHx8IFtdO1xuXG5cdFx0aWYgKCBhcnIgIT0gbnVsbCApIHtcblx0XHRcdGlmICggaXNBcnJheWxpa2UoIE9iamVjdChhcnIpICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5tZXJnZSggcmV0LFxuXHRcdFx0XHRcdHR5cGVvZiBhcnIgPT09IFwic3RyaW5nXCIgP1xuXHRcdFx0XHRcdFsgYXJyIF0gOiBhcnJcblx0XHRcdFx0KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHB1c2guY2FsbCggcmV0LCBhcnIgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gcmV0O1xuXHR9LFxuXG5cdGluQXJyYXk6IGZ1bmN0aW9uKCBlbGVtLCBhcnIsIGkgKSB7XG5cdFx0cmV0dXJuIGFyciA9PSBudWxsID8gLTEgOiBpbmRleE9mLmNhbGwoIGFyciwgZWxlbSwgaSApO1xuXHR9LFxuXG5cdG1lcmdlOiBmdW5jdGlvbiggZmlyc3QsIHNlY29uZCApIHtcblx0XHR2YXIgbGVuID0gK3NlY29uZC5sZW5ndGgsXG5cdFx0XHRqID0gMCxcblx0XHRcdGkgPSBmaXJzdC5sZW5ndGg7XG5cblx0XHRmb3IgKCA7IGogPCBsZW47IGorKyApIHtcblx0XHRcdGZpcnN0WyBpKysgXSA9IHNlY29uZFsgaiBdO1xuXHRcdH1cblxuXHRcdGZpcnN0Lmxlbmd0aCA9IGk7XG5cblx0XHRyZXR1cm4gZmlyc3Q7XG5cdH0sXG5cblx0Z3JlcDogZnVuY3Rpb24oIGVsZW1zLCBjYWxsYmFjaywgaW52ZXJ0ICkge1xuXHRcdHZhciBjYWxsYmFja0ludmVyc2UsXG5cdFx0XHRtYXRjaGVzID0gW10sXG5cdFx0XHRpID0gMCxcblx0XHRcdGxlbmd0aCA9IGVsZW1zLmxlbmd0aCxcblx0XHRcdGNhbGxiYWNrRXhwZWN0ID0gIWludmVydDtcblxuXHRcdC8vIEdvIHRocm91Z2ggdGhlIGFycmF5LCBvbmx5IHNhdmluZyB0aGUgaXRlbXNcblx0XHQvLyB0aGF0IHBhc3MgdGhlIHZhbGlkYXRvciBmdW5jdGlvblxuXHRcdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXHRcdFx0Y2FsbGJhY2tJbnZlcnNlID0gIWNhbGxiYWNrKCBlbGVtc1sgaSBdLCBpICk7XG5cdFx0XHRpZiAoIGNhbGxiYWNrSW52ZXJzZSAhPT0gY2FsbGJhY2tFeHBlY3QgKSB7XG5cdFx0XHRcdG1hdGNoZXMucHVzaCggZWxlbXNbIGkgXSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBtYXRjaGVzO1xuXHR9LFxuXG5cdC8vIGFyZyBpcyBmb3IgaW50ZXJuYWwgdXNhZ2Ugb25seVxuXHRtYXA6IGZ1bmN0aW9uKCBlbGVtcywgY2FsbGJhY2ssIGFyZyApIHtcblx0XHR2YXIgdmFsdWUsXG5cdFx0XHRpID0gMCxcblx0XHRcdGxlbmd0aCA9IGVsZW1zLmxlbmd0aCxcblx0XHRcdGlzQXJyYXkgPSBpc0FycmF5bGlrZSggZWxlbXMgKSxcblx0XHRcdHJldCA9IFtdO1xuXG5cdFx0Ly8gR28gdGhyb3VnaCB0aGUgYXJyYXksIHRyYW5zbGF0aW5nIGVhY2ggb2YgdGhlIGl0ZW1zIHRvIHRoZWlyIG5ldyB2YWx1ZXNcblx0XHRpZiAoIGlzQXJyYXkgKSB7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0dmFsdWUgPSBjYWxsYmFjayggZWxlbXNbIGkgXSwgaSwgYXJnICk7XG5cblx0XHRcdFx0aWYgKCB2YWx1ZSAhPSBudWxsICkge1xuXHRcdFx0XHRcdHJldC5wdXNoKCB2YWx1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvLyBHbyB0aHJvdWdoIGV2ZXJ5IGtleSBvbiB0aGUgb2JqZWN0LFxuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3IgKCBpIGluIGVsZW1zICkge1xuXHRcdFx0XHR2YWx1ZSA9IGNhbGxiYWNrKCBlbGVtc1sgaSBdLCBpLCBhcmcgKTtcblxuXHRcdFx0XHRpZiAoIHZhbHVlICE9IG51bGwgKSB7XG5cdFx0XHRcdFx0cmV0LnB1c2goIHZhbHVlICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBGbGF0dGVuIGFueSBuZXN0ZWQgYXJyYXlzXG5cdFx0cmV0dXJuIGNvbmNhdC5hcHBseSggW10sIHJldCApO1xuXHR9LFxuXG5cdC8vIEEgZ2xvYmFsIEdVSUQgY291bnRlciBmb3Igb2JqZWN0c1xuXHRndWlkOiAxLFxuXG5cdC8vIEJpbmQgYSBmdW5jdGlvbiB0byBhIGNvbnRleHQsIG9wdGlvbmFsbHkgcGFydGlhbGx5IGFwcGx5aW5nIGFueVxuXHQvLyBhcmd1bWVudHMuXG5cdHByb3h5OiBmdW5jdGlvbiggZm4sIGNvbnRleHQgKSB7XG5cdFx0dmFyIHRtcCwgYXJncywgcHJveHk7XG5cblx0XHRpZiAoIHR5cGVvZiBjb250ZXh0ID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0dG1wID0gZm5bIGNvbnRleHQgXTtcblx0XHRcdGNvbnRleHQgPSBmbjtcblx0XHRcdGZuID0gdG1wO1xuXHRcdH1cblxuXHRcdC8vIFF1aWNrIGNoZWNrIHRvIGRldGVybWluZSBpZiB0YXJnZXQgaXMgY2FsbGFibGUsIGluIHRoZSBzcGVjXG5cdFx0Ly8gdGhpcyB0aHJvd3MgYSBUeXBlRXJyb3IsIGJ1dCB3ZSB3aWxsIGp1c3QgcmV0dXJuIHVuZGVmaW5lZC5cblx0XHRpZiAoICFqUXVlcnkuaXNGdW5jdGlvbiggZm4gKSApIHtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fVxuXG5cdFx0Ly8gU2ltdWxhdGVkIGJpbmRcblx0XHRhcmdzID0gc2xpY2UuY2FsbCggYXJndW1lbnRzLCAyICk7XG5cdFx0cHJveHkgPSBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBmbi5hcHBseSggY29udGV4dCB8fCB0aGlzLCBhcmdzLmNvbmNhdCggc2xpY2UuY2FsbCggYXJndW1lbnRzICkgKSApO1xuXHRcdH07XG5cblx0XHQvLyBTZXQgdGhlIGd1aWQgb2YgdW5pcXVlIGhhbmRsZXIgdG8gdGhlIHNhbWUgb2Ygb3JpZ2luYWwgaGFuZGxlciwgc28gaXQgY2FuIGJlIHJlbW92ZWRcblx0XHRwcm94eS5ndWlkID0gZm4uZ3VpZCA9IGZuLmd1aWQgfHwgalF1ZXJ5Lmd1aWQrKztcblxuXHRcdHJldHVybiBwcm94eTtcblx0fSxcblxuXHRub3c6IERhdGUubm93LFxuXG5cdC8vIGpRdWVyeS5zdXBwb3J0IGlzIG5vdCB1c2VkIGluIENvcmUgYnV0IG90aGVyIHByb2plY3RzIGF0dGFjaCB0aGVpclxuXHQvLyBwcm9wZXJ0aWVzIHRvIGl0IHNvIGl0IG5lZWRzIHRvIGV4aXN0LlxuXHRzdXBwb3J0OiBzdXBwb3J0XG59KTtcblxuLy8gUG9wdWxhdGUgdGhlIGNsYXNzMnR5cGUgbWFwXG5qUXVlcnkuZWFjaChcIkJvb2xlYW4gTnVtYmVyIFN0cmluZyBGdW5jdGlvbiBBcnJheSBEYXRlIFJlZ0V4cCBPYmplY3QgRXJyb3JcIi5zcGxpdChcIiBcIiksIGZ1bmN0aW9uKGksIG5hbWUpIHtcblx0Y2xhc3MydHlwZVsgXCJbb2JqZWN0IFwiICsgbmFtZSArIFwiXVwiIF0gPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG59KTtcblxuZnVuY3Rpb24gaXNBcnJheWxpa2UoIG9iaiApIHtcblx0dmFyIGxlbmd0aCA9IG9iai5sZW5ndGgsXG5cdFx0dHlwZSA9IGpRdWVyeS50eXBlKCBvYmogKTtcblxuXHRpZiAoIHR5cGUgPT09IFwiZnVuY3Rpb25cIiB8fCBqUXVlcnkuaXNXaW5kb3coIG9iaiApICkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGlmICggb2JqLm5vZGVUeXBlID09PSAxICYmIGxlbmd0aCApIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHJldHVybiB0eXBlID09PSBcImFycmF5XCIgfHwgbGVuZ3RoID09PSAwIHx8XG5cdFx0dHlwZW9mIGxlbmd0aCA9PT0gXCJudW1iZXJcIiAmJiBsZW5ndGggPiAwICYmICggbGVuZ3RoIC0gMSApIGluIG9iajtcbn1cbnZhciBTaXp6bGUgPVxuLyohXG4gKiBTaXp6bGUgQ1NTIFNlbGVjdG9yIEVuZ2luZSB2Mi4yLjAtcHJlXG4gKiBodHRwOi8vc2l6emxlanMuY29tL1xuICpcbiAqIENvcHlyaWdodCAyMDA4LCAyMDE0IGpRdWVyeSBGb3VuZGF0aW9uLCBJbmMuIGFuZCBvdGhlciBjb250cmlidXRvcnNcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZVxuICogaHR0cDovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIERhdGU6IDIwMTQtMTItMTZcbiAqL1xuKGZ1bmN0aW9uKCB3aW5kb3cgKSB7XG5cbnZhciBpLFxuXHRzdXBwb3J0LFxuXHRFeHByLFxuXHRnZXRUZXh0LFxuXHRpc1hNTCxcblx0dG9rZW5pemUsXG5cdGNvbXBpbGUsXG5cdHNlbGVjdCxcblx0b3V0ZXJtb3N0Q29udGV4dCxcblx0c29ydElucHV0LFxuXHRoYXNEdXBsaWNhdGUsXG5cblx0Ly8gTG9jYWwgZG9jdW1lbnQgdmFyc1xuXHRzZXREb2N1bWVudCxcblx0ZG9jdW1lbnQsXG5cdGRvY0VsZW0sXG5cdGRvY3VtZW50SXNIVE1MLFxuXHRyYnVnZ3lRU0EsXG5cdHJidWdneU1hdGNoZXMsXG5cdG1hdGNoZXMsXG5cdGNvbnRhaW5zLFxuXG5cdC8vIEluc3RhbmNlLXNwZWNpZmljIGRhdGFcblx0ZXhwYW5kbyA9IFwic2l6emxlXCIgKyAxICogbmV3IERhdGUoKSxcblx0cHJlZmVycmVkRG9jID0gd2luZG93LmRvY3VtZW50LFxuXHRkaXJydW5zID0gMCxcblx0ZG9uZSA9IDAsXG5cdGNsYXNzQ2FjaGUgPSBjcmVhdGVDYWNoZSgpLFxuXHR0b2tlbkNhY2hlID0gY3JlYXRlQ2FjaGUoKSxcblx0Y29tcGlsZXJDYWNoZSA9IGNyZWF0ZUNhY2hlKCksXG5cdHNvcnRPcmRlciA9IGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdGlmICggYSA9PT0gYiApIHtcblx0XHRcdGhhc0R1cGxpY2F0ZSA9IHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiAwO1xuXHR9LFxuXG5cdC8vIEdlbmVyYWwtcHVycG9zZSBjb25zdGFudHNcblx0TUFYX05FR0FUSVZFID0gMSA8PCAzMSxcblxuXHQvLyBJbnN0YW5jZSBtZXRob2RzXG5cdGhhc093biA9ICh7fSkuaGFzT3duUHJvcGVydHksXG5cdGFyciA9IFtdLFxuXHRwb3AgPSBhcnIucG9wLFxuXHRwdXNoX25hdGl2ZSA9IGFyci5wdXNoLFxuXHRwdXNoID0gYXJyLnB1c2gsXG5cdHNsaWNlID0gYXJyLnNsaWNlLFxuXHQvLyBVc2UgYSBzdHJpcHBlZC1kb3duIGluZGV4T2YgYXMgaXQncyBmYXN0ZXIgdGhhbiBuYXRpdmVcblx0Ly8gaHR0cDovL2pzcGVyZi5jb20vdGhvci1pbmRleG9mLXZzLWZvci81XG5cdGluZGV4T2YgPSBmdW5jdGlvbiggbGlzdCwgZWxlbSApIHtcblx0XHR2YXIgaSA9IDAsXG5cdFx0XHRsZW4gPSBsaXN0Lmxlbmd0aDtcblx0XHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdGlmICggbGlzdFtpXSA9PT0gZWxlbSApIHtcblx0XHRcdFx0cmV0dXJuIGk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiAtMTtcblx0fSxcblxuXHRib29sZWFucyA9IFwiY2hlY2tlZHxzZWxlY3RlZHxhc3luY3xhdXRvZm9jdXN8YXV0b3BsYXl8Y29udHJvbHN8ZGVmZXJ8ZGlzYWJsZWR8aGlkZGVufGlzbWFwfGxvb3B8bXVsdGlwbGV8b3BlbnxyZWFkb25seXxyZXF1aXJlZHxzY29wZWRcIixcblxuXHQvLyBSZWd1bGFyIGV4cHJlc3Npb25zXG5cblx0Ly8gV2hpdGVzcGFjZSBjaGFyYWN0ZXJzIGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtc2VsZWN0b3JzLyN3aGl0ZXNwYWNlXG5cdHdoaXRlc3BhY2UgPSBcIltcXFxceDIwXFxcXHRcXFxcclxcXFxuXFxcXGZdXCIsXG5cdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtc3ludGF4LyNjaGFyYWN0ZXJzXG5cdGNoYXJhY3RlckVuY29kaW5nID0gXCIoPzpcXFxcXFxcXC58W1xcXFx3LV18W15cXFxceDAwLVxcXFx4YTBdKStcIixcblxuXHQvLyBMb29zZWx5IG1vZGVsZWQgb24gQ1NTIGlkZW50aWZpZXIgY2hhcmFjdGVyc1xuXHQvLyBBbiB1bnF1b3RlZCB2YWx1ZSBzaG91bGQgYmUgYSBDU1MgaWRlbnRpZmllciBodHRwOi8vd3d3LnczLm9yZy9UUi9jc3MzLXNlbGVjdG9ycy8jYXR0cmlidXRlLXNlbGVjdG9yc1xuXHQvLyBQcm9wZXIgc3ludGF4OiBodHRwOi8vd3d3LnczLm9yZy9UUi9DU1MyMS9zeW5kYXRhLmh0bWwjdmFsdWUtZGVmLWlkZW50aWZpZXJcblx0aWRlbnRpZmllciA9IGNoYXJhY3RlckVuY29kaW5nLnJlcGxhY2UoIFwid1wiLCBcIncjXCIgKSxcblxuXHQvLyBBdHRyaWJ1dGUgc2VsZWN0b3JzOiBodHRwOi8vd3d3LnczLm9yZy9UUi9zZWxlY3RvcnMvI2F0dHJpYnV0ZS1zZWxlY3RvcnNcblx0YXR0cmlidXRlcyA9IFwiXFxcXFtcIiArIHdoaXRlc3BhY2UgKyBcIiooXCIgKyBjaGFyYWN0ZXJFbmNvZGluZyArIFwiKSg/OlwiICsgd2hpdGVzcGFjZSArXG5cdFx0Ly8gT3BlcmF0b3IgKGNhcHR1cmUgMilcblx0XHRcIiooWypeJHwhfl0/PSlcIiArIHdoaXRlc3BhY2UgK1xuXHRcdC8vIFwiQXR0cmlidXRlIHZhbHVlcyBtdXN0IGJlIENTUyBpZGVudGlmaWVycyBbY2FwdHVyZSA1XSBvciBzdHJpbmdzIFtjYXB0dXJlIDMgb3IgY2FwdHVyZSA0XVwiXG5cdFx0XCIqKD86JygoPzpcXFxcXFxcXC58W15cXFxcXFxcXCddKSopJ3xcXFwiKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcXFxcIl0pKilcXFwifChcIiArIGlkZW50aWZpZXIgKyBcIikpfClcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFwiKlxcXFxdXCIsXG5cblx0cHNldWRvcyA9IFwiOihcIiArIGNoYXJhY3RlckVuY29kaW5nICsgXCIpKD86XFxcXCgoXCIgK1xuXHRcdC8vIFRvIHJlZHVjZSB0aGUgbnVtYmVyIG9mIHNlbGVjdG9ycyBuZWVkaW5nIHRva2VuaXplIGluIHRoZSBwcmVGaWx0ZXIsIHByZWZlciBhcmd1bWVudHM6XG5cdFx0Ly8gMS4gcXVvdGVkIChjYXB0dXJlIDM7IGNhcHR1cmUgNCBvciBjYXB0dXJlIDUpXG5cdFx0XCIoJygoPzpcXFxcXFxcXC58W15cXFxcXFxcXCddKSopJ3xcXFwiKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcXFxcIl0pKilcXFwiKXxcIiArXG5cdFx0Ly8gMi4gc2ltcGxlIChjYXB0dXJlIDYpXG5cdFx0XCIoKD86XFxcXFxcXFwufFteXFxcXFxcXFwoKVtcXFxcXV18XCIgKyBhdHRyaWJ1dGVzICsgXCIpKil8XCIgK1xuXHRcdC8vIDMuIGFueXRoaW5nIGVsc2UgKGNhcHR1cmUgMilcblx0XHRcIi4qXCIgK1xuXHRcdFwiKVxcXFwpfClcIixcblxuXHQvLyBMZWFkaW5nIGFuZCBub24tZXNjYXBlZCB0cmFpbGluZyB3aGl0ZXNwYWNlLCBjYXB0dXJpbmcgc29tZSBub24td2hpdGVzcGFjZSBjaGFyYWN0ZXJzIHByZWNlZGluZyB0aGUgbGF0dGVyXG5cdHJ3aGl0ZXNwYWNlID0gbmV3IFJlZ0V4cCggd2hpdGVzcGFjZSArIFwiK1wiLCBcImdcIiApLFxuXHRydHJpbSA9IG5ldyBSZWdFeHAoIFwiXlwiICsgd2hpdGVzcGFjZSArIFwiK3woKD86XnxbXlxcXFxcXFxcXSkoPzpcXFxcXFxcXC4pKilcIiArIHdoaXRlc3BhY2UgKyBcIiskXCIsIFwiZ1wiICksXG5cblx0cmNvbW1hID0gbmV3IFJlZ0V4cCggXCJeXCIgKyB3aGl0ZXNwYWNlICsgXCIqLFwiICsgd2hpdGVzcGFjZSArIFwiKlwiICksXG5cdHJjb21iaW5hdG9ycyA9IG5ldyBSZWdFeHAoIFwiXlwiICsgd2hpdGVzcGFjZSArIFwiKihbPit+XXxcIiArIHdoaXRlc3BhY2UgKyBcIilcIiArIHdoaXRlc3BhY2UgKyBcIipcIiApLFxuXG5cdHJhdHRyaWJ1dGVRdW90ZXMgPSBuZXcgUmVnRXhwKCBcIj1cIiArIHdoaXRlc3BhY2UgKyBcIiooW15cXFxcXSdcXFwiXSo/KVwiICsgd2hpdGVzcGFjZSArIFwiKlxcXFxdXCIsIFwiZ1wiICksXG5cblx0cnBzZXVkbyA9IG5ldyBSZWdFeHAoIHBzZXVkb3MgKSxcblx0cmlkZW50aWZpZXIgPSBuZXcgUmVnRXhwKCBcIl5cIiArIGlkZW50aWZpZXIgKyBcIiRcIiApLFxuXG5cdG1hdGNoRXhwciA9IHtcblx0XHRcIklEXCI6IG5ldyBSZWdFeHAoIFwiXiMoXCIgKyBjaGFyYWN0ZXJFbmNvZGluZyArIFwiKVwiICksXG5cdFx0XCJDTEFTU1wiOiBuZXcgUmVnRXhwKCBcIl5cXFxcLihcIiArIGNoYXJhY3RlckVuY29kaW5nICsgXCIpXCIgKSxcblx0XHRcIlRBR1wiOiBuZXcgUmVnRXhwKCBcIl4oXCIgKyBjaGFyYWN0ZXJFbmNvZGluZy5yZXBsYWNlKCBcIndcIiwgXCJ3KlwiICkgKyBcIilcIiApLFxuXHRcdFwiQVRUUlwiOiBuZXcgUmVnRXhwKCBcIl5cIiArIGF0dHJpYnV0ZXMgKSxcblx0XHRcIlBTRVVET1wiOiBuZXcgUmVnRXhwKCBcIl5cIiArIHBzZXVkb3MgKSxcblx0XHRcIkNISUxEXCI6IG5ldyBSZWdFeHAoIFwiXjoob25seXxmaXJzdHxsYXN0fG50aHxudGgtbGFzdCktKGNoaWxkfG9mLXR5cGUpKD86XFxcXChcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFx0XCIqKGV2ZW58b2RkfCgoWystXXwpKFxcXFxkKilufClcIiArIHdoaXRlc3BhY2UgKyBcIiooPzooWystXXwpXCIgKyB3aGl0ZXNwYWNlICtcblx0XHRcdFwiKihcXFxcZCspfCkpXCIgKyB3aGl0ZXNwYWNlICsgXCIqXFxcXCl8KVwiLCBcImlcIiApLFxuXHRcdFwiYm9vbFwiOiBuZXcgUmVnRXhwKCBcIl4oPzpcIiArIGJvb2xlYW5zICsgXCIpJFwiLCBcImlcIiApLFxuXHRcdC8vIEZvciB1c2UgaW4gbGlicmFyaWVzIGltcGxlbWVudGluZyAuaXMoKVxuXHRcdC8vIFdlIHVzZSB0aGlzIGZvciBQT1MgbWF0Y2hpbmcgaW4gYHNlbGVjdGBcblx0XHRcIm5lZWRzQ29udGV4dFwiOiBuZXcgUmVnRXhwKCBcIl5cIiArIHdoaXRlc3BhY2UgKyBcIipbPit+XXw6KGV2ZW58b2RkfGVxfGd0fGx0fG50aHxmaXJzdHxsYXN0KSg/OlxcXFwoXCIgK1xuXHRcdFx0d2hpdGVzcGFjZSArIFwiKigoPzotXFxcXGQpP1xcXFxkKilcIiArIHdoaXRlc3BhY2UgKyBcIipcXFxcKXwpKD89W14tXXwkKVwiLCBcImlcIiApXG5cdH0sXG5cblx0cmlucHV0cyA9IC9eKD86aW5wdXR8c2VsZWN0fHRleHRhcmVhfGJ1dHRvbikkL2ksXG5cdHJoZWFkZXIgPSAvXmhcXGQkL2ksXG5cblx0cm5hdGl2ZSA9IC9eW157XStcXHtcXHMqXFxbbmF0aXZlIFxcdy8sXG5cblx0Ly8gRWFzaWx5LXBhcnNlYWJsZS9yZXRyaWV2YWJsZSBJRCBvciBUQUcgb3IgQ0xBU1Mgc2VsZWN0b3JzXG5cdHJxdWlja0V4cHIgPSAvXig/OiMoW1xcdy1dKyl8KFxcdyspfFxcLihbXFx3LV0rKSkkLyxcblxuXHRyc2libGluZyA9IC9bK35dLyxcblx0cmVzY2FwZSA9IC8nfFxcXFwvZyxcblxuXHQvLyBDU1MgZXNjYXBlcyBodHRwOi8vd3d3LnczLm9yZy9UUi9DU1MyMS9zeW5kYXRhLmh0bWwjZXNjYXBlZC1jaGFyYWN0ZXJzXG5cdHJ1bmVzY2FwZSA9IG5ldyBSZWdFeHAoIFwiXFxcXFxcXFwoW1xcXFxkYS1mXXsxLDZ9XCIgKyB3aGl0ZXNwYWNlICsgXCI/fChcIiArIHdoaXRlc3BhY2UgKyBcIil8LilcIiwgXCJpZ1wiICksXG5cdGZ1bmVzY2FwZSA9IGZ1bmN0aW9uKCBfLCBlc2NhcGVkLCBlc2NhcGVkV2hpdGVzcGFjZSApIHtcblx0XHR2YXIgaGlnaCA9IFwiMHhcIiArIGVzY2FwZWQgLSAweDEwMDAwO1xuXHRcdC8vIE5hTiBtZWFucyBub24tY29kZXBvaW50XG5cdFx0Ly8gU3VwcG9ydDogRmlyZWZveDwyNFxuXHRcdC8vIFdvcmthcm91bmQgZXJyb25lb3VzIG51bWVyaWMgaW50ZXJwcmV0YXRpb24gb2YgK1wiMHhcIlxuXHRcdHJldHVybiBoaWdoICE9PSBoaWdoIHx8IGVzY2FwZWRXaGl0ZXNwYWNlID9cblx0XHRcdGVzY2FwZWQgOlxuXHRcdFx0aGlnaCA8IDAgP1xuXHRcdFx0XHQvLyBCTVAgY29kZXBvaW50XG5cdFx0XHRcdFN0cmluZy5mcm9tQ2hhckNvZGUoIGhpZ2ggKyAweDEwMDAwICkgOlxuXHRcdFx0XHQvLyBTdXBwbGVtZW50YWwgUGxhbmUgY29kZXBvaW50IChzdXJyb2dhdGUgcGFpcilcblx0XHRcdFx0U3RyaW5nLmZyb21DaGFyQ29kZSggaGlnaCA+PiAxMCB8IDB4RDgwMCwgaGlnaCAmIDB4M0ZGIHwgMHhEQzAwICk7XG5cdH0sXG5cblx0Ly8gVXNlZCBmb3IgaWZyYW1lc1xuXHQvLyBTZWUgc2V0RG9jdW1lbnQoKVxuXHQvLyBSZW1vdmluZyB0aGUgZnVuY3Rpb24gd3JhcHBlciBjYXVzZXMgYSBcIlBlcm1pc3Npb24gRGVuaWVkXCJcblx0Ly8gZXJyb3IgaW4gSUVcblx0dW5sb2FkSGFuZGxlciA9IGZ1bmN0aW9uKCkge1xuXHRcdHNldERvY3VtZW50KCk7XG5cdH07XG5cbi8vIE9wdGltaXplIGZvciBwdXNoLmFwcGx5KCBfLCBOb2RlTGlzdCApXG50cnkge1xuXHRwdXNoLmFwcGx5KFxuXHRcdChhcnIgPSBzbGljZS5jYWxsKCBwcmVmZXJyZWREb2MuY2hpbGROb2RlcyApKSxcblx0XHRwcmVmZXJyZWREb2MuY2hpbGROb2Rlc1xuXHQpO1xuXHQvLyBTdXBwb3J0OiBBbmRyb2lkPDQuMFxuXHQvLyBEZXRlY3Qgc2lsZW50bHkgZmFpbGluZyBwdXNoLmFwcGx5XG5cdGFyclsgcHJlZmVycmVkRG9jLmNoaWxkTm9kZXMubGVuZ3RoIF0ubm9kZVR5cGU7XG59IGNhdGNoICggZSApIHtcblx0cHVzaCA9IHsgYXBwbHk6IGFyci5sZW5ndGggP1xuXG5cdFx0Ly8gTGV2ZXJhZ2Ugc2xpY2UgaWYgcG9zc2libGVcblx0XHRmdW5jdGlvbiggdGFyZ2V0LCBlbHMgKSB7XG5cdFx0XHRwdXNoX25hdGl2ZS5hcHBseSggdGFyZ2V0LCBzbGljZS5jYWxsKGVscykgKTtcblx0XHR9IDpcblxuXHRcdC8vIFN1cHBvcnQ6IElFPDlcblx0XHQvLyBPdGhlcndpc2UgYXBwZW5kIGRpcmVjdGx5XG5cdFx0ZnVuY3Rpb24oIHRhcmdldCwgZWxzICkge1xuXHRcdFx0dmFyIGogPSB0YXJnZXQubGVuZ3RoLFxuXHRcdFx0XHRpID0gMDtcblx0XHRcdC8vIENhbid0IHRydXN0IE5vZGVMaXN0Lmxlbmd0aFxuXHRcdFx0d2hpbGUgKCAodGFyZ2V0W2orK10gPSBlbHNbaSsrXSkgKSB7fVxuXHRcdFx0dGFyZ2V0Lmxlbmd0aCA9IGogLSAxO1xuXHRcdH1cblx0fTtcbn1cblxuZnVuY3Rpb24gU2l6emxlKCBzZWxlY3RvciwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApIHtcblx0dmFyIG1hdGNoLCBlbGVtLCBtLCBub2RlVHlwZSxcblx0XHQvLyBRU0EgdmFyc1xuXHRcdGksIGdyb3Vwcywgb2xkLCBuaWQsIG5ld0NvbnRleHQsIG5ld1NlbGVjdG9yO1xuXG5cdGlmICggKCBjb250ZXh0ID8gY29udGV4dC5vd25lckRvY3VtZW50IHx8IGNvbnRleHQgOiBwcmVmZXJyZWREb2MgKSAhPT0gZG9jdW1lbnQgKSB7XG5cdFx0c2V0RG9jdW1lbnQoIGNvbnRleHQgKTtcblx0fVxuXG5cdGNvbnRleHQgPSBjb250ZXh0IHx8IGRvY3VtZW50O1xuXHRyZXN1bHRzID0gcmVzdWx0cyB8fCBbXTtcblx0bm9kZVR5cGUgPSBjb250ZXh0Lm5vZGVUeXBlO1xuXG5cdGlmICggdHlwZW9mIHNlbGVjdG9yICE9PSBcInN0cmluZ1wiIHx8ICFzZWxlY3RvciB8fFxuXHRcdG5vZGVUeXBlICE9PSAxICYmIG5vZGVUeXBlICE9PSA5ICYmIG5vZGVUeXBlICE9PSAxMSApIHtcblxuXHRcdHJldHVybiByZXN1bHRzO1xuXHR9XG5cblx0aWYgKCAhc2VlZCAmJiBkb2N1bWVudElzSFRNTCApIHtcblxuXHRcdC8vIFRyeSB0byBzaG9ydGN1dCBmaW5kIG9wZXJhdGlvbnMgd2hlbiBwb3NzaWJsZSAoZS5nLiwgbm90IHVuZGVyIERvY3VtZW50RnJhZ21lbnQpXG5cdFx0aWYgKCBub2RlVHlwZSAhPT0gMTEgJiYgKG1hdGNoID0gcnF1aWNrRXhwci5leGVjKCBzZWxlY3RvciApKSApIHtcblx0XHRcdC8vIFNwZWVkLXVwOiBTaXp6bGUoXCIjSURcIilcblx0XHRcdGlmICggKG0gPSBtYXRjaFsxXSkgKSB7XG5cdFx0XHRcdGlmICggbm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdFx0ZWxlbSA9IGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIG0gKTtcblx0XHRcdFx0XHQvLyBDaGVjayBwYXJlbnROb2RlIHRvIGNhdGNoIHdoZW4gQmxhY2tiZXJyeSA0LjYgcmV0dXJuc1xuXHRcdFx0XHRcdC8vIG5vZGVzIHRoYXQgYXJlIG5vIGxvbmdlciBpbiB0aGUgZG9jdW1lbnQgKGpRdWVyeSAjNjk2Mylcblx0XHRcdFx0XHRpZiAoIGVsZW0gJiYgZWxlbS5wYXJlbnROb2RlICkge1xuXHRcdFx0XHRcdFx0Ly8gSGFuZGxlIHRoZSBjYXNlIHdoZXJlIElFLCBPcGVyYSwgYW5kIFdlYmtpdCByZXR1cm4gaXRlbXNcblx0XHRcdFx0XHRcdC8vIGJ5IG5hbWUgaW5zdGVhZCBvZiBJRFxuXHRcdFx0XHRcdFx0aWYgKCBlbGVtLmlkID09PSBtICkge1xuXHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQvLyBDb250ZXh0IGlzIG5vdCBhIGRvY3VtZW50XG5cdFx0XHRcdFx0aWYgKCBjb250ZXh0Lm93bmVyRG9jdW1lbnQgJiYgKGVsZW0gPSBjb250ZXh0Lm93bmVyRG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIG0gKSkgJiZcblx0XHRcdFx0XHRcdGNvbnRhaW5zKCBjb250ZXh0LCBlbGVtICkgJiYgZWxlbS5pZCA9PT0gbSApIHtcblx0XHRcdFx0XHRcdHJlc3VsdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdC8vIFNwZWVkLXVwOiBTaXp6bGUoXCJUQUdcIilcblx0XHRcdH0gZWxzZSBpZiAoIG1hdGNoWzJdICkge1xuXHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCBzZWxlY3RvciApICk7XG5cdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXG5cdFx0XHQvLyBTcGVlZC11cDogU2l6emxlKFwiLkNMQVNTXCIpXG5cdFx0XHR9IGVsc2UgaWYgKCAobSA9IG1hdGNoWzNdKSAmJiBzdXBwb3J0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUgKSB7XG5cdFx0XHRcdHB1c2guYXBwbHkoIHJlc3VsdHMsIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSggbSApICk7XG5cdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFFTQSBwYXRoXG5cdFx0aWYgKCBzdXBwb3J0LnFzYSAmJiAoIXJidWdneVFTQSB8fCAhcmJ1Z2d5UVNBLnRlc3QoIHNlbGVjdG9yICkpICkge1xuXHRcdFx0bmlkID0gb2xkID0gZXhwYW5kbztcblx0XHRcdG5ld0NvbnRleHQgPSBjb250ZXh0O1xuXHRcdFx0bmV3U2VsZWN0b3IgPSBub2RlVHlwZSAhPT0gMSAmJiBzZWxlY3RvcjtcblxuXHRcdFx0Ly8gcVNBIHdvcmtzIHN0cmFuZ2VseSBvbiBFbGVtZW50LXJvb3RlZCBxdWVyaWVzXG5cdFx0XHQvLyBXZSBjYW4gd29yayBhcm91bmQgdGhpcyBieSBzcGVjaWZ5aW5nIGFuIGV4dHJhIElEIG9uIHRoZSByb290XG5cdFx0XHQvLyBhbmQgd29ya2luZyB1cCBmcm9tIHRoZXJlIChUaGFua3MgdG8gQW5kcmV3IER1cG9udCBmb3IgdGhlIHRlY2huaXF1ZSlcblx0XHRcdC8vIElFIDggZG9lc24ndCB3b3JrIG9uIG9iamVjdCBlbGVtZW50c1xuXHRcdFx0aWYgKCBub2RlVHlwZSA9PT0gMSAmJiBjb250ZXh0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgIT09IFwib2JqZWN0XCIgKSB7XG5cdFx0XHRcdGdyb3VwcyA9IHRva2VuaXplKCBzZWxlY3RvciApO1xuXG5cdFx0XHRcdGlmICggKG9sZCA9IGNvbnRleHQuZ2V0QXR0cmlidXRlKFwiaWRcIikpICkge1xuXHRcdFx0XHRcdG5pZCA9IG9sZC5yZXBsYWNlKCByZXNjYXBlLCBcIlxcXFwkJlwiICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Y29udGV4dC5zZXRBdHRyaWJ1dGUoIFwiaWRcIiwgbmlkICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0bmlkID0gXCJbaWQ9J1wiICsgbmlkICsgXCInXSBcIjtcblxuXHRcdFx0XHRpID0gZ3JvdXBzLmxlbmd0aDtcblx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0Z3JvdXBzW2ldID0gbmlkICsgdG9TZWxlY3RvciggZ3JvdXBzW2ldICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0bmV3Q29udGV4dCA9IHJzaWJsaW5nLnRlc3QoIHNlbGVjdG9yICkgJiYgdGVzdENvbnRleHQoIGNvbnRleHQucGFyZW50Tm9kZSApIHx8IGNvbnRleHQ7XG5cdFx0XHRcdG5ld1NlbGVjdG9yID0gZ3JvdXBzLmpvaW4oXCIsXCIpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIG5ld1NlbGVjdG9yICkge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdHB1c2guYXBwbHkoIHJlc3VsdHMsXG5cdFx0XHRcdFx0XHRuZXdDb250ZXh0LnF1ZXJ5U2VsZWN0b3JBbGwoIG5ld1NlbGVjdG9yIClcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHR9IGNhdGNoKHFzYUVycm9yKSB7XG5cdFx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdFx0aWYgKCAhb2xkICkge1xuXHRcdFx0XHRcdFx0Y29udGV4dC5yZW1vdmVBdHRyaWJ1dGUoXCJpZFwiKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBBbGwgb3RoZXJzXG5cdHJldHVybiBzZWxlY3QoIHNlbGVjdG9yLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApO1xufVxuXG4vKipcbiAqIENyZWF0ZSBrZXktdmFsdWUgY2FjaGVzIG9mIGxpbWl0ZWQgc2l6ZVxuICogQHJldHVybnMge0Z1bmN0aW9uKHN0cmluZywgT2JqZWN0KX0gUmV0dXJucyB0aGUgT2JqZWN0IGRhdGEgYWZ0ZXIgc3RvcmluZyBpdCBvbiBpdHNlbGYgd2l0aFxuICpcdHByb3BlcnR5IG5hbWUgdGhlIChzcGFjZS1zdWZmaXhlZCkgc3RyaW5nIGFuZCAoaWYgdGhlIGNhY2hlIGlzIGxhcmdlciB0aGFuIEV4cHIuY2FjaGVMZW5ndGgpXG4gKlx0ZGVsZXRpbmcgdGhlIG9sZGVzdCBlbnRyeVxuICovXG5mdW5jdGlvbiBjcmVhdGVDYWNoZSgpIHtcblx0dmFyIGtleXMgPSBbXTtcblxuXHRmdW5jdGlvbiBjYWNoZSgga2V5LCB2YWx1ZSApIHtcblx0XHQvLyBVc2UgKGtleSArIFwiIFwiKSB0byBhdm9pZCBjb2xsaXNpb24gd2l0aCBuYXRpdmUgcHJvdG90eXBlIHByb3BlcnRpZXMgKHNlZSBJc3N1ZSAjMTU3KVxuXHRcdGlmICgga2V5cy5wdXNoKCBrZXkgKyBcIiBcIiApID4gRXhwci5jYWNoZUxlbmd0aCApIHtcblx0XHRcdC8vIE9ubHkga2VlcCB0aGUgbW9zdCByZWNlbnQgZW50cmllc1xuXHRcdFx0ZGVsZXRlIGNhY2hlWyBrZXlzLnNoaWZ0KCkgXTtcblx0XHR9XG5cdFx0cmV0dXJuIChjYWNoZVsga2V5ICsgXCIgXCIgXSA9IHZhbHVlKTtcblx0fVxuXHRyZXR1cm4gY2FjaGU7XG59XG5cbi8qKlxuICogTWFyayBhIGZ1bmN0aW9uIGZvciBzcGVjaWFsIHVzZSBieSBTaXp6bGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBtYXJrXG4gKi9cbmZ1bmN0aW9uIG1hcmtGdW5jdGlvbiggZm4gKSB7XG5cdGZuWyBleHBhbmRvIF0gPSB0cnVlO1xuXHRyZXR1cm4gZm47XG59XG5cbi8qKlxuICogU3VwcG9ydCB0ZXN0aW5nIHVzaW5nIGFuIGVsZW1lbnRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFBhc3NlZCB0aGUgY3JlYXRlZCBkaXYgYW5kIGV4cGVjdHMgYSBib29sZWFuIHJlc3VsdFxuICovXG5mdW5jdGlvbiBhc3NlcnQoIGZuICkge1xuXHR2YXIgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcblxuXHR0cnkge1xuXHRcdHJldHVybiAhIWZuKCBkaXYgKTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fSBmaW5hbGx5IHtcblx0XHQvLyBSZW1vdmUgZnJvbSBpdHMgcGFyZW50IGJ5IGRlZmF1bHRcblx0XHRpZiAoIGRpdi5wYXJlbnROb2RlICkge1xuXHRcdFx0ZGl2LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIGRpdiApO1xuXHRcdH1cblx0XHQvLyByZWxlYXNlIG1lbW9yeSBpbiBJRVxuXHRcdGRpdiA9IG51bGw7XG5cdH1cbn1cblxuLyoqXG4gKiBBZGRzIHRoZSBzYW1lIGhhbmRsZXIgZm9yIGFsbCBvZiB0aGUgc3BlY2lmaWVkIGF0dHJzXG4gKiBAcGFyYW0ge1N0cmluZ30gYXR0cnMgUGlwZS1zZXBhcmF0ZWQgbGlzdCBvZiBhdHRyaWJ1dGVzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyIFRoZSBtZXRob2QgdGhhdCB3aWxsIGJlIGFwcGxpZWRcbiAqL1xuZnVuY3Rpb24gYWRkSGFuZGxlKCBhdHRycywgaGFuZGxlciApIHtcblx0dmFyIGFyciA9IGF0dHJzLnNwbGl0KFwifFwiKSxcblx0XHRpID0gYXR0cnMubGVuZ3RoO1xuXG5cdHdoaWxlICggaS0tICkge1xuXHRcdEV4cHIuYXR0ckhhbmRsZVsgYXJyW2ldIF0gPSBoYW5kbGVyO1xuXHR9XG59XG5cbi8qKlxuICogQ2hlY2tzIGRvY3VtZW50IG9yZGVyIG9mIHR3byBzaWJsaW5nc1xuICogQHBhcmFtIHtFbGVtZW50fSBhXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGJcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IFJldHVybnMgbGVzcyB0aGFuIDAgaWYgYSBwcmVjZWRlcyBiLCBncmVhdGVyIHRoYW4gMCBpZiBhIGZvbGxvd3MgYlxuICovXG5mdW5jdGlvbiBzaWJsaW5nQ2hlY2soIGEsIGIgKSB7XG5cdHZhciBjdXIgPSBiICYmIGEsXG5cdFx0ZGlmZiA9IGN1ciAmJiBhLm5vZGVUeXBlID09PSAxICYmIGIubm9kZVR5cGUgPT09IDEgJiZcblx0XHRcdCggfmIuc291cmNlSW5kZXggfHwgTUFYX05FR0FUSVZFICkgLVxuXHRcdFx0KCB+YS5zb3VyY2VJbmRleCB8fCBNQVhfTkVHQVRJVkUgKTtcblxuXHQvLyBVc2UgSUUgc291cmNlSW5kZXggaWYgYXZhaWxhYmxlIG9uIGJvdGggbm9kZXNcblx0aWYgKCBkaWZmICkge1xuXHRcdHJldHVybiBkaWZmO1xuXHR9XG5cblx0Ly8gQ2hlY2sgaWYgYiBmb2xsb3dzIGFcblx0aWYgKCBjdXIgKSB7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLm5leHRTaWJsaW5nKSApIHtcblx0XHRcdGlmICggY3VyID09PSBiICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGEgPyAxIDogLTE7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRvIHVzZSBpbiBwc2V1ZG9zIGZvciBpbnB1dCB0eXBlc1xuICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW5wdXRQc2V1ZG8oIHR5cGUgKSB7XG5cdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHR2YXIgbmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRyZXR1cm4gbmFtZSA9PT0gXCJpbnB1dFwiICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIGJ1dHRvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUJ1dHRvblBzZXVkbyggdHlwZSApIHtcblx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBuYW1lID0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdHJldHVybiAobmFtZSA9PT0gXCJpbnB1dFwiIHx8IG5hbWUgPT09IFwiYnV0dG9uXCIpICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIHBvc2l0aW9uYWxzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICovXG5mdW5jdGlvbiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKCBmbiApIHtcblx0cmV0dXJuIG1hcmtGdW5jdGlvbihmdW5jdGlvbiggYXJndW1lbnQgKSB7XG5cdFx0YXJndW1lbnQgPSArYXJndW1lbnQ7XG5cdFx0cmV0dXJuIG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgbWF0Y2hlcyApIHtcblx0XHRcdHZhciBqLFxuXHRcdFx0XHRtYXRjaEluZGV4ZXMgPSBmbiggW10sIHNlZWQubGVuZ3RoLCBhcmd1bWVudCApLFxuXHRcdFx0XHRpID0gbWF0Y2hJbmRleGVzLmxlbmd0aDtcblxuXHRcdFx0Ly8gTWF0Y2ggZWxlbWVudHMgZm91bmQgYXQgdGhlIHNwZWNpZmllZCBpbmRleGVzXG5cdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0aWYgKCBzZWVkWyAoaiA9IG1hdGNoSW5kZXhlc1tpXSkgXSApIHtcblx0XHRcdFx0XHRzZWVkW2pdID0gIShtYXRjaGVzW2pdID0gc2VlZFtqXSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGEgbm9kZSBmb3IgdmFsaWRpdHkgYXMgYSBTaXp6bGUgY29udGV4dFxuICogQHBhcmFtIHtFbGVtZW50fE9iamVjdD19IGNvbnRleHRcbiAqIEByZXR1cm5zIHtFbGVtZW50fE9iamVjdHxCb29sZWFufSBUaGUgaW5wdXQgbm9kZSBpZiBhY2NlcHRhYmxlLCBvdGhlcndpc2UgYSBmYWxzeSB2YWx1ZVxuICovXG5mdW5jdGlvbiB0ZXN0Q29udGV4dCggY29udGV4dCApIHtcblx0cmV0dXJuIGNvbnRleHQgJiYgdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgIT09IFwidW5kZWZpbmVkXCIgJiYgY29udGV4dDtcbn1cblxuLy8gRXhwb3NlIHN1cHBvcnQgdmFycyBmb3IgY29udmVuaWVuY2VcbnN1cHBvcnQgPSBTaXp6bGUuc3VwcG9ydCA9IHt9O1xuXG4vKipcbiAqIERldGVjdHMgWE1MIG5vZGVzXG4gKiBAcGFyYW0ge0VsZW1lbnR8T2JqZWN0fSBlbGVtIEFuIGVsZW1lbnQgb3IgYSBkb2N1bWVudFxuICogQHJldHVybnMge0Jvb2xlYW59IFRydWUgaWZmIGVsZW0gaXMgYSBub24tSFRNTCBYTUwgbm9kZVxuICovXG5pc1hNTCA9IFNpenpsZS5pc1hNTCA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHQvLyBkb2N1bWVudEVsZW1lbnQgaXMgdmVyaWZpZWQgZm9yIGNhc2VzIHdoZXJlIGl0IGRvZXNuJ3QgeWV0IGV4aXN0XG5cdC8vIChzdWNoIGFzIGxvYWRpbmcgaWZyYW1lcyBpbiBJRSAtICM0ODMzKVxuXHR2YXIgZG9jdW1lbnRFbGVtZW50ID0gZWxlbSAmJiAoZWxlbS5vd25lckRvY3VtZW50IHx8IGVsZW0pLmRvY3VtZW50RWxlbWVudDtcblx0cmV0dXJuIGRvY3VtZW50RWxlbWVudCA/IGRvY3VtZW50RWxlbWVudC5ub2RlTmFtZSAhPT0gXCJIVE1MXCIgOiBmYWxzZTtcbn07XG5cbi8qKlxuICogU2V0cyBkb2N1bWVudC1yZWxhdGVkIHZhcmlhYmxlcyBvbmNlIGJhc2VkIG9uIHRoZSBjdXJyZW50IGRvY3VtZW50XG4gKiBAcGFyYW0ge0VsZW1lbnR8T2JqZWN0fSBbZG9jXSBBbiBlbGVtZW50IG9yIGRvY3VtZW50IG9iamVjdCB0byB1c2UgdG8gc2V0IHRoZSBkb2N1bWVudFxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY3VycmVudCBkb2N1bWVudFxuICovXG5zZXREb2N1bWVudCA9IFNpenpsZS5zZXREb2N1bWVudCA9IGZ1bmN0aW9uKCBub2RlICkge1xuXHR2YXIgaGFzQ29tcGFyZSwgcGFyZW50LFxuXHRcdGRvYyA9IG5vZGUgPyBub2RlLm93bmVyRG9jdW1lbnQgfHwgbm9kZSA6IHByZWZlcnJlZERvYztcblxuXHQvLyBJZiBubyBkb2N1bWVudCBhbmQgZG9jdW1lbnRFbGVtZW50IGlzIGF2YWlsYWJsZSwgcmV0dXJuXG5cdGlmICggZG9jID09PSBkb2N1bWVudCB8fCBkb2Mubm9kZVR5cGUgIT09IDkgfHwgIWRvYy5kb2N1bWVudEVsZW1lbnQgKSB7XG5cdFx0cmV0dXJuIGRvY3VtZW50O1xuXHR9XG5cblx0Ly8gU2V0IG91ciBkb2N1bWVudFxuXHRkb2N1bWVudCA9IGRvYztcblx0ZG9jRWxlbSA9IGRvYy5kb2N1bWVudEVsZW1lbnQ7XG5cdHBhcmVudCA9IGRvYy5kZWZhdWx0VmlldztcblxuXHQvLyBTdXBwb3J0OiBJRT44XG5cdC8vIElmIGlmcmFtZSBkb2N1bWVudCBpcyBhc3NpZ25lZCB0byBcImRvY3VtZW50XCIgdmFyaWFibGUgYW5kIGlmIGlmcmFtZSBoYXMgYmVlbiByZWxvYWRlZCxcblx0Ly8gSUUgd2lsbCB0aHJvdyBcInBlcm1pc3Npb24gZGVuaWVkXCIgZXJyb3Igd2hlbiBhY2Nlc3NpbmcgXCJkb2N1bWVudFwiIHZhcmlhYmxlLCBzZWUgalF1ZXJ5ICMxMzkzNlxuXHQvLyBJRTYtOCBkbyBub3Qgc3VwcG9ydCB0aGUgZGVmYXVsdFZpZXcgcHJvcGVydHkgc28gcGFyZW50IHdpbGwgYmUgdW5kZWZpbmVkXG5cdGlmICggcGFyZW50ICYmIHBhcmVudCAhPT0gcGFyZW50LnRvcCApIHtcblx0XHQvLyBJRTExIGRvZXMgbm90IGhhdmUgYXR0YWNoRXZlbnQsIHNvIGFsbCBtdXN0IHN1ZmZlclxuXHRcdGlmICggcGFyZW50LmFkZEV2ZW50TGlzdGVuZXIgKSB7XG5cdFx0XHRwYXJlbnQuYWRkRXZlbnRMaXN0ZW5lciggXCJ1bmxvYWRcIiwgdW5sb2FkSGFuZGxlciwgZmFsc2UgKTtcblx0XHR9IGVsc2UgaWYgKCBwYXJlbnQuYXR0YWNoRXZlbnQgKSB7XG5cdFx0XHRwYXJlbnQuYXR0YWNoRXZlbnQoIFwib251bmxvYWRcIiwgdW5sb2FkSGFuZGxlciApO1xuXHRcdH1cblx0fVxuXG5cdC8qIFN1cHBvcnQgdGVzdHNcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXHRkb2N1bWVudElzSFRNTCA9ICFpc1hNTCggZG9jICk7XG5cblx0LyogQXR0cmlidXRlc1xuXHQtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cblx0Ly8gU3VwcG9ydDogSUU8OFxuXHQvLyBWZXJpZnkgdGhhdCBnZXRBdHRyaWJ1dGUgcmVhbGx5IHJldHVybnMgYXR0cmlidXRlcyBhbmQgbm90IHByb3BlcnRpZXNcblx0Ly8gKGV4Y2VwdGluZyBJRTggYm9vbGVhbnMpXG5cdHN1cHBvcnQuYXR0cmlidXRlcyA9IGFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRcdGRpdi5jbGFzc05hbWUgPSBcImlcIjtcblx0XHRyZXR1cm4gIWRpdi5nZXRBdHRyaWJ1dGUoXCJjbGFzc05hbWVcIik7XG5cdH0pO1xuXG5cdC8qIGdldEVsZW1lbnQocylCeSpcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cdC8vIENoZWNrIGlmIGdldEVsZW1lbnRzQnlUYWdOYW1lKFwiKlwiKSByZXR1cm5zIG9ubHkgZWxlbWVudHNcblx0c3VwcG9ydC5nZXRFbGVtZW50c0J5VGFnTmFtZSA9IGFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRcdGRpdi5hcHBlbmRDaGlsZCggZG9jLmNyZWF0ZUNvbW1lbnQoXCJcIikgKTtcblx0XHRyZXR1cm4gIWRpdi5nZXRFbGVtZW50c0J5VGFnTmFtZShcIipcIikubGVuZ3RoO1xuXHR9KTtcblxuXHQvLyBTdXBwb3J0OiBJRTw5XG5cdHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSA9IHJuYXRpdmUudGVzdCggZG9jLmdldEVsZW1lbnRzQnlDbGFzc05hbWUgKTtcblxuXHQvLyBTdXBwb3J0OiBJRTwxMFxuXHQvLyBDaGVjayBpZiBnZXRFbGVtZW50QnlJZCByZXR1cm5zIGVsZW1lbnRzIGJ5IG5hbWVcblx0Ly8gVGhlIGJyb2tlbiBnZXRFbGVtZW50QnlJZCBtZXRob2RzIGRvbid0IHBpY2sgdXAgcHJvZ3JhbWF0aWNhbGx5LXNldCBuYW1lcyxcblx0Ly8gc28gdXNlIGEgcm91bmRhYm91dCBnZXRFbGVtZW50c0J5TmFtZSB0ZXN0XG5cdHN1cHBvcnQuZ2V0QnlJZCA9IGFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRcdGRvY0VsZW0uYXBwZW5kQ2hpbGQoIGRpdiApLmlkID0gZXhwYW5kbztcblx0XHRyZXR1cm4gIWRvYy5nZXRFbGVtZW50c0J5TmFtZSB8fCAhZG9jLmdldEVsZW1lbnRzQnlOYW1lKCBleHBhbmRvICkubGVuZ3RoO1xuXHR9KTtcblxuXHQvLyBJRCBmaW5kIGFuZCBmaWx0ZXJcblx0aWYgKCBzdXBwb3J0LmdldEJ5SWQgKSB7XG5cdFx0RXhwci5maW5kW1wiSURcIl0gPSBmdW5jdGlvbiggaWQsIGNvbnRleHQgKSB7XG5cdFx0XHRpZiAoIHR5cGVvZiBjb250ZXh0LmdldEVsZW1lbnRCeUlkICE9PSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50SXNIVE1MICkge1xuXHRcdFx0XHR2YXIgbSA9IGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIGlkICk7XG5cdFx0XHRcdC8vIENoZWNrIHBhcmVudE5vZGUgdG8gY2F0Y2ggd2hlbiBCbGFja2JlcnJ5IDQuNiByZXR1cm5zXG5cdFx0XHRcdC8vIG5vZGVzIHRoYXQgYXJlIG5vIGxvbmdlciBpbiB0aGUgZG9jdW1lbnQgIzY5NjNcblx0XHRcdFx0cmV0dXJuIG0gJiYgbS5wYXJlbnROb2RlID8gWyBtIF0gOiBbXTtcblx0XHRcdH1cblx0XHR9O1xuXHRcdEV4cHIuZmlsdGVyW1wiSURcIl0gPSBmdW5jdGlvbiggaWQgKSB7XG5cdFx0XHR2YXIgYXR0cklkID0gaWQucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKFwiaWRcIikgPT09IGF0dHJJZDtcblx0XHRcdH07XG5cdFx0fTtcblx0fSBlbHNlIHtcblx0XHQvLyBTdXBwb3J0OiBJRTYvN1xuXHRcdC8vIGdldEVsZW1lbnRCeUlkIGlzIG5vdCByZWxpYWJsZSBhcyBhIGZpbmQgc2hvcnRjdXRcblx0XHRkZWxldGUgRXhwci5maW5kW1wiSURcIl07XG5cblx0XHRFeHByLmZpbHRlcltcIklEXCJdID0gIGZ1bmN0aW9uKCBpZCApIHtcblx0XHRcdHZhciBhdHRySWQgPSBpZC5yZXBsYWNlKCBydW5lc2NhcGUsIGZ1bmVzY2FwZSApO1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgbm9kZSA9IHR5cGVvZiBlbGVtLmdldEF0dHJpYnV0ZU5vZGUgIT09IFwidW5kZWZpbmVkXCIgJiYgZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKFwiaWRcIik7XG5cdFx0XHRcdHJldHVybiBub2RlICYmIG5vZGUudmFsdWUgPT09IGF0dHJJZDtcblx0XHRcdH07XG5cdFx0fTtcblx0fVxuXG5cdC8vIFRhZ1xuXHRFeHByLmZpbmRbXCJUQUdcIl0gPSBzdXBwb3J0LmdldEVsZW1lbnRzQnlUYWdOYW1lID9cblx0XHRmdW5jdGlvbiggdGFnLCBjb250ZXh0ICkge1xuXHRcdFx0aWYgKCB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiApIHtcblx0XHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIHRhZyApO1xuXG5cdFx0XHQvLyBEb2N1bWVudEZyYWdtZW50IG5vZGVzIGRvbid0IGhhdmUgZ0VCVE5cblx0XHRcdH0gZWxzZSBpZiAoIHN1cHBvcnQucXNhICkge1xuXHRcdFx0XHRyZXR1cm4gY29udGV4dC5xdWVyeVNlbGVjdG9yQWxsKCB0YWcgKTtcblx0XHRcdH1cblx0XHR9IDpcblxuXHRcdGZ1bmN0aW9uKCB0YWcsIGNvbnRleHQgKSB7XG5cdFx0XHR2YXIgZWxlbSxcblx0XHRcdFx0dG1wID0gW10sXG5cdFx0XHRcdGkgPSAwLFxuXHRcdFx0XHQvLyBCeSBoYXBweSBjb2luY2lkZW5jZSwgYSAoYnJva2VuKSBnRUJUTiBhcHBlYXJzIG9uIERvY3VtZW50RnJhZ21lbnQgbm9kZXMgdG9vXG5cdFx0XHRcdHJlc3VsdHMgPSBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCB0YWcgKTtcblxuXHRcdFx0Ly8gRmlsdGVyIG91dCBwb3NzaWJsZSBjb21tZW50c1xuXHRcdFx0aWYgKCB0YWcgPT09IFwiKlwiICkge1xuXHRcdFx0XHR3aGlsZSAoIChlbGVtID0gcmVzdWx0c1tpKytdKSApIHtcblx0XHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdFx0XHR0bXAucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiB0bXA7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHR9O1xuXG5cdC8vIENsYXNzXG5cdEV4cHIuZmluZFtcIkNMQVNTXCJdID0gc3VwcG9ydC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICYmIGZ1bmN0aW9uKCBjbGFzc05hbWUsIGNvbnRleHQgKSB7XG5cdFx0aWYgKCBkb2N1bWVudElzSFRNTCApIHtcblx0XHRcdHJldHVybiBjb250ZXh0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoIGNsYXNzTmFtZSApO1xuXHRcdH1cblx0fTtcblxuXHQvKiBRU0EvbWF0Y2hlc1NlbGVjdG9yXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBRU0EgYW5kIG1hdGNoZXNTZWxlY3RvciBzdXBwb3J0XG5cblx0Ly8gbWF0Y2hlc1NlbGVjdG9yKDphY3RpdmUpIHJlcG9ydHMgZmFsc2Ugd2hlbiB0cnVlIChJRTkvT3BlcmEgMTEuNSlcblx0cmJ1Z2d5TWF0Y2hlcyA9IFtdO1xuXG5cdC8vIHFTYSg6Zm9jdXMpIHJlcG9ydHMgZmFsc2Ugd2hlbiB0cnVlIChDaHJvbWUgMjEpXG5cdC8vIFdlIGFsbG93IHRoaXMgYmVjYXVzZSBvZiBhIGJ1ZyBpbiBJRTgvOSB0aGF0IHRocm93cyBhbiBlcnJvclxuXHQvLyB3aGVuZXZlciBgZG9jdW1lbnQuYWN0aXZlRWxlbWVudGAgaXMgYWNjZXNzZWQgb24gYW4gaWZyYW1lXG5cdC8vIFNvLCB3ZSBhbGxvdyA6Zm9jdXMgdG8gcGFzcyB0aHJvdWdoIFFTQSBhbGwgdGhlIHRpbWUgdG8gYXZvaWQgdGhlIElFIGVycm9yXG5cdC8vIFNlZSBodHRwOi8vYnVncy5qcXVlcnkuY29tL3RpY2tldC8xMzM3OFxuXHRyYnVnZ3lRU0EgPSBbXTtcblxuXHRpZiAoIChzdXBwb3J0LnFzYSA9IHJuYXRpdmUudGVzdCggZG9jLnF1ZXJ5U2VsZWN0b3JBbGwgKSkgKSB7XG5cdFx0Ly8gQnVpbGQgUVNBIHJlZ2V4XG5cdFx0Ly8gUmVnZXggc3RyYXRlZ3kgYWRvcHRlZCBmcm9tIERpZWdvIFBlcmluaVxuXHRcdGFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRcdFx0Ly8gU2VsZWN0IGlzIHNldCB0byBlbXB0eSBzdHJpbmcgb24gcHVycG9zZVxuXHRcdFx0Ly8gVGhpcyBpcyB0byB0ZXN0IElFJ3MgdHJlYXRtZW50IG9mIG5vdCBleHBsaWNpdGx5XG5cdFx0XHQvLyBzZXR0aW5nIGEgYm9vbGVhbiBjb250ZW50IGF0dHJpYnV0ZSxcblx0XHRcdC8vIHNpbmNlIGl0cyBwcmVzZW5jZSBzaG91bGQgYmUgZW5vdWdoXG5cdFx0XHQvLyBodHRwOi8vYnVncy5qcXVlcnkuY29tL3RpY2tldC8xMjM1OVxuXHRcdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZGl2ICkuaW5uZXJIVE1MID0gXCI8YSBpZD0nXCIgKyBleHBhbmRvICsgXCInPjwvYT5cIiArXG5cdFx0XHRcdFwiPHNlbGVjdCBpZD0nXCIgKyBleHBhbmRvICsgXCItXFxmXScgbXNhbGxvd2NhcHR1cmU9Jyc+XCIgK1xuXHRcdFx0XHRcIjxvcHRpb24gc2VsZWN0ZWQ9Jyc+PC9vcHRpb24+PC9zZWxlY3Q+XCI7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IElFOCwgT3BlcmEgMTEtMTIuMTZcblx0XHRcdC8vIE5vdGhpbmcgc2hvdWxkIGJlIHNlbGVjdGVkIHdoZW4gZW1wdHkgc3RyaW5ncyBmb2xsb3cgXj0gb3IgJD0gb3IgKj1cblx0XHRcdC8vIFRoZSB0ZXN0IGF0dHJpYnV0ZSBtdXN0IGJlIHVua25vd24gaW4gT3BlcmEgYnV0IFwic2FmZVwiIGZvciBXaW5SVFxuXHRcdFx0Ly8gaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L2llL2hoNDY1Mzg4LmFzcHgjYXR0cmlidXRlX3NlY3Rpb25cblx0XHRcdGlmICggZGl2LnF1ZXJ5U2VsZWN0b3JBbGwoXCJbbXNhbGxvd2NhcHR1cmVePScnXVwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIlsqXiRdPVwiICsgd2hpdGVzcGFjZSArIFwiKig/OicnfFxcXCJcXFwiKVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN1cHBvcnQ6IElFOFxuXHRcdFx0Ly8gQm9vbGVhbiBhdHRyaWJ1dGVzIGFuZCBcInZhbHVlXCIgYXJlIG5vdCB0cmVhdGVkIGNvcnJlY3RseVxuXHRcdFx0aWYgKCAhZGl2LnF1ZXJ5U2VsZWN0b3JBbGwoXCJbc2VsZWN0ZWRdXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goIFwiXFxcXFtcIiArIHdoaXRlc3BhY2UgKyBcIiooPzp2YWx1ZXxcIiArIGJvb2xlYW5zICsgXCIpXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogQ2hyb21lPDI5LCBBbmRyb2lkPDQuMissIFNhZmFyaTw3LjArLCBpT1M8Ny4wKywgUGhhbnRvbUpTPDEuOS43K1xuXHRcdFx0aWYgKCAhZGl2LnF1ZXJ5U2VsZWN0b3JBbGwoIFwiW2lkfj1cIiArIGV4cGFuZG8gKyBcIi1dXCIgKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKFwifj1cIik7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFdlYmtpdC9PcGVyYSAtIDpjaGVja2VkIHNob3VsZCByZXR1cm4gc2VsZWN0ZWQgb3B0aW9uIGVsZW1lbnRzXG5cdFx0XHQvLyBodHRwOi8vd3d3LnczLm9yZy9UUi8yMDExL1JFQy1jc3MzLXNlbGVjdG9ycy0yMDExMDkyOS8jY2hlY2tlZFxuXHRcdFx0Ly8gSUU4IHRocm93cyBlcnJvciBoZXJlIGFuZCB3aWxsIG5vdCBzZWUgbGF0ZXIgdGVzdHNcblx0XHRcdGlmICggIWRpdi5xdWVyeVNlbGVjdG9yQWxsKFwiOmNoZWNrZWRcIikubGVuZ3RoICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaChcIjpjaGVja2VkXCIpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdXBwb3J0OiBTYWZhcmkgOCssIGlPUyA4K1xuXHRcdFx0Ly8gaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTEzNjg1MVxuXHRcdFx0Ly8gSW4tcGFnZSBgc2VsZWN0b3IjaWQgc2liaW5nLWNvbWJpbmF0b3Igc2VsZWN0b3JgIGZhaWxzXG5cdFx0XHRpZiAoICFkaXYucXVlcnlTZWxlY3RvckFsbCggXCJhI1wiICsgZXhwYW5kbyArIFwiKypcIiApLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCIuIy4rWyt+XVwiKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdGFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRcdFx0Ly8gU3VwcG9ydDogV2luZG93cyA4IE5hdGl2ZSBBcHBzXG5cdFx0XHQvLyBUaGUgdHlwZSBhbmQgbmFtZSBhdHRyaWJ1dGVzIGFyZSByZXN0cmljdGVkIGR1cmluZyAuaW5uZXJIVE1MIGFzc2lnbm1lbnRcblx0XHRcdHZhciBpbnB1dCA9IGRvYy5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIik7XG5cdFx0XHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwidHlwZVwiLCBcImhpZGRlblwiICk7XG5cdFx0XHRkaXYuYXBwZW5kQ2hpbGQoIGlucHV0ICkuc2V0QXR0cmlidXRlKCBcIm5hbWVcIiwgXCJEXCIgKTtcblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU4XG5cdFx0XHQvLyBFbmZvcmNlIGNhc2Utc2Vuc2l0aXZpdHkgb2YgbmFtZSBhdHRyaWJ1dGVcblx0XHRcdGlmICggZGl2LnF1ZXJ5U2VsZWN0b3JBbGwoXCJbbmFtZT1kXVwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIm5hbWVcIiArIHdoaXRlc3BhY2UgKyBcIipbKl4kfCF+XT89XCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRkYgMy41IC0gOmVuYWJsZWQvOmRpc2FibGVkIGFuZCBoaWRkZW4gZWxlbWVudHMgKGhpZGRlbiBlbGVtZW50cyBhcmUgc3RpbGwgZW5hYmxlZClcblx0XHRcdC8vIElFOCB0aHJvd3MgZXJyb3IgaGVyZSBhbmQgd2lsbCBub3Qgc2VlIGxhdGVyIHRlc3RzXG5cdFx0XHRpZiAoICFkaXYucXVlcnlTZWxlY3RvckFsbChcIjplbmFibGVkXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goIFwiOmVuYWJsZWRcIiwgXCI6ZGlzYWJsZWRcIiApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBPcGVyYSAxMC0xMSBkb2VzIG5vdCB0aHJvdyBvbiBwb3N0LWNvbW1hIGludmFsaWQgcHNldWRvc1xuXHRcdFx0ZGl2LnF1ZXJ5U2VsZWN0b3JBbGwoXCIqLDp4XCIpO1xuXHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCIsLio6XCIpO1xuXHRcdH0pO1xuXHR9XG5cblx0aWYgKCAoc3VwcG9ydC5tYXRjaGVzU2VsZWN0b3IgPSBybmF0aXZlLnRlc3QoIChtYXRjaGVzID0gZG9jRWxlbS5tYXRjaGVzIHx8XG5cdFx0ZG9jRWxlbS53ZWJraXRNYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm1vek1hdGNoZXNTZWxlY3RvciB8fFxuXHRcdGRvY0VsZW0ub01hdGNoZXNTZWxlY3RvciB8fFxuXHRcdGRvY0VsZW0ubXNNYXRjaGVzU2VsZWN0b3IpICkpICkge1xuXG5cdFx0YXNzZXJ0KGZ1bmN0aW9uKCBkaXYgKSB7XG5cdFx0XHQvLyBDaGVjayB0byBzZWUgaWYgaXQncyBwb3NzaWJsZSB0byBkbyBtYXRjaGVzU2VsZWN0b3Jcblx0XHRcdC8vIG9uIGEgZGlzY29ubmVjdGVkIG5vZGUgKElFIDkpXG5cdFx0XHRzdXBwb3J0LmRpc2Nvbm5lY3RlZE1hdGNoID0gbWF0Y2hlcy5jYWxsKCBkaXYsIFwiZGl2XCIgKTtcblxuXHRcdFx0Ly8gVGhpcyBzaG91bGQgZmFpbCB3aXRoIGFuIGV4Y2VwdGlvblxuXHRcdFx0Ly8gR2Vja28gZG9lcyBub3QgZXJyb3IsIHJldHVybnMgZmFsc2UgaW5zdGVhZFxuXHRcdFx0bWF0Y2hlcy5jYWxsKCBkaXYsIFwiW3MhPScnXTp4XCIgKTtcblx0XHRcdHJidWdneU1hdGNoZXMucHVzaCggXCIhPVwiLCBwc2V1ZG9zICk7XG5cdFx0fSk7XG5cdH1cblxuXHRyYnVnZ3lRU0EgPSByYnVnZ3lRU0EubGVuZ3RoICYmIG5ldyBSZWdFeHAoIHJidWdneVFTQS5qb2luKFwifFwiKSApO1xuXHRyYnVnZ3lNYXRjaGVzID0gcmJ1Z2d5TWF0Y2hlcy5sZW5ndGggJiYgbmV3IFJlZ0V4cCggcmJ1Z2d5TWF0Y2hlcy5qb2luKFwifFwiKSApO1xuXG5cdC8qIENvbnRhaW5zXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblx0aGFzQ29tcGFyZSA9IHJuYXRpdmUudGVzdCggZG9jRWxlbS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiApO1xuXG5cdC8vIEVsZW1lbnQgY29udGFpbnMgYW5vdGhlclxuXHQvLyBQdXJwb3NlZnVsbHkgZG9lcyBub3QgaW1wbGVtZW50IGluY2x1c2l2ZSBkZXNjZW5kZW50XG5cdC8vIEFzIGluLCBhbiBlbGVtZW50IGRvZXMgbm90IGNvbnRhaW4gaXRzZWxmXG5cdGNvbnRhaW5zID0gaGFzQ29tcGFyZSB8fCBybmF0aXZlLnRlc3QoIGRvY0VsZW0uY29udGFpbnMgKSA/XG5cdFx0ZnVuY3Rpb24oIGEsIGIgKSB7XG5cdFx0XHR2YXIgYWRvd24gPSBhLm5vZGVUeXBlID09PSA5ID8gYS5kb2N1bWVudEVsZW1lbnQgOiBhLFxuXHRcdFx0XHRidXAgPSBiICYmIGIucGFyZW50Tm9kZTtcblx0XHRcdHJldHVybiBhID09PSBidXAgfHwgISEoIGJ1cCAmJiBidXAubm9kZVR5cGUgPT09IDEgJiYgKFxuXHRcdFx0XHRhZG93bi5jb250YWlucyA/XG5cdFx0XHRcdFx0YWRvd24uY29udGFpbnMoIGJ1cCApIDpcblx0XHRcdFx0XHRhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uICYmIGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGJ1cCApICYgMTZcblx0XHRcdCkpO1xuXHRcdH0gOlxuXHRcdGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0aWYgKCBiICkge1xuXHRcdFx0XHR3aGlsZSAoIChiID0gYi5wYXJlbnROb2RlKSApIHtcblx0XHRcdFx0XHRpZiAoIGIgPT09IGEgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9O1xuXG5cdC8qIFNvcnRpbmdcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cdC8vIERvY3VtZW50IG9yZGVyIHNvcnRpbmdcblx0c29ydE9yZGVyID0gaGFzQ29tcGFyZSA/XG5cdGZ1bmN0aW9uKCBhLCBiICkge1xuXG5cdFx0Ly8gRmxhZyBmb3IgZHVwbGljYXRlIHJlbW92YWxcblx0XHRpZiAoIGEgPT09IGIgKSB7XG5cdFx0XHRoYXNEdXBsaWNhdGUgPSB0cnVlO1xuXHRcdFx0cmV0dXJuIDA7XG5cdFx0fVxuXG5cdFx0Ly8gU29ydCBvbiBtZXRob2QgZXhpc3RlbmNlIGlmIG9ubHkgb25lIGlucHV0IGhhcyBjb21wYXJlRG9jdW1lbnRQb3NpdGlvblxuXHRcdHZhciBjb21wYXJlID0gIWEuY29tcGFyZURvY3VtZW50UG9zaXRpb24gLSAhYi5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbjtcblx0XHRpZiAoIGNvbXBhcmUgKSB7XG5cdFx0XHRyZXR1cm4gY29tcGFyZTtcblx0XHR9XG5cblx0XHQvLyBDYWxjdWxhdGUgcG9zaXRpb24gaWYgYm90aCBpbnB1dHMgYmVsb25nIHRvIHRoZSBzYW1lIGRvY3VtZW50XG5cdFx0Y29tcGFyZSA9ICggYS5vd25lckRvY3VtZW50IHx8IGEgKSA9PT0gKCBiLm93bmVyRG9jdW1lbnQgfHwgYiApID9cblx0XHRcdGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGIgKSA6XG5cblx0XHRcdC8vIE90aGVyd2lzZSB3ZSBrbm93IHRoZXkgYXJlIGRpc2Nvbm5lY3RlZFxuXHRcdFx0MTtcblxuXHRcdC8vIERpc2Nvbm5lY3RlZCBub2Rlc1xuXHRcdGlmICggY29tcGFyZSAmIDEgfHxcblx0XHRcdCghc3VwcG9ydC5zb3J0RGV0YWNoZWQgJiYgYi5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiggYSApID09PSBjb21wYXJlKSApIHtcblxuXHRcdFx0Ly8gQ2hvb3NlIHRoZSBmaXJzdCBlbGVtZW50IHRoYXQgaXMgcmVsYXRlZCB0byBvdXIgcHJlZmVycmVkIGRvY3VtZW50XG5cdFx0XHRpZiAoIGEgPT09IGRvYyB8fCBhLm93bmVyRG9jdW1lbnQgPT09IHByZWZlcnJlZERvYyAmJiBjb250YWlucyhwcmVmZXJyZWREb2MsIGEpICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIGIgPT09IGRvYyB8fCBiLm93bmVyRG9jdW1lbnQgPT09IHByZWZlcnJlZERvYyAmJiBjb250YWlucyhwcmVmZXJyZWREb2MsIGIpICkge1xuXHRcdFx0XHRyZXR1cm4gMTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTWFpbnRhaW4gb3JpZ2luYWwgb3JkZXJcblx0XHRcdHJldHVybiBzb3J0SW5wdXQgP1xuXHRcdFx0XHQoIGluZGV4T2YoIHNvcnRJbnB1dCwgYSApIC0gaW5kZXhPZiggc29ydElucHV0LCBiICkgKSA6XG5cdFx0XHRcdDA7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGNvbXBhcmUgJiA0ID8gLTEgOiAxO1xuXHR9IDpcblx0ZnVuY3Rpb24oIGEsIGIgKSB7XG5cdFx0Ly8gRXhpdCBlYXJseSBpZiB0aGUgbm9kZXMgYXJlIGlkZW50aWNhbFxuXHRcdGlmICggYSA9PT0gYiApIHtcblx0XHRcdGhhc0R1cGxpY2F0ZSA9IHRydWU7XG5cdFx0XHRyZXR1cm4gMDtcblx0XHR9XG5cblx0XHR2YXIgY3VyLFxuXHRcdFx0aSA9IDAsXG5cdFx0XHRhdXAgPSBhLnBhcmVudE5vZGUsXG5cdFx0XHRidXAgPSBiLnBhcmVudE5vZGUsXG5cdFx0XHRhcCA9IFsgYSBdLFxuXHRcdFx0YnAgPSBbIGIgXTtcblxuXHRcdC8vIFBhcmVudGxlc3Mgbm9kZXMgYXJlIGVpdGhlciBkb2N1bWVudHMgb3IgZGlzY29ubmVjdGVkXG5cdFx0aWYgKCAhYXVwIHx8ICFidXAgKSB7XG5cdFx0XHRyZXR1cm4gYSA9PT0gZG9jID8gLTEgOlxuXHRcdFx0XHRiID09PSBkb2MgPyAxIDpcblx0XHRcdFx0YXVwID8gLTEgOlxuXHRcdFx0XHRidXAgPyAxIDpcblx0XHRcdFx0c29ydElucHV0ID9cblx0XHRcdFx0KCBpbmRleE9mKCBzb3J0SW5wdXQsIGEgKSAtIGluZGV4T2YoIHNvcnRJbnB1dCwgYiApICkgOlxuXHRcdFx0XHQwO1xuXG5cdFx0Ly8gSWYgdGhlIG5vZGVzIGFyZSBzaWJsaW5ncywgd2UgY2FuIGRvIGEgcXVpY2sgY2hlY2tcblx0XHR9IGVsc2UgaWYgKCBhdXAgPT09IGJ1cCApIHtcblx0XHRcdHJldHVybiBzaWJsaW5nQ2hlY2soIGEsIGIgKTtcblx0XHR9XG5cblx0XHQvLyBPdGhlcndpc2Ugd2UgbmVlZCBmdWxsIGxpc3RzIG9mIHRoZWlyIGFuY2VzdG9ycyBmb3IgY29tcGFyaXNvblxuXHRcdGN1ciA9IGE7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLnBhcmVudE5vZGUpICkge1xuXHRcdFx0YXAudW5zaGlmdCggY3VyICk7XG5cdFx0fVxuXHRcdGN1ciA9IGI7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLnBhcmVudE5vZGUpICkge1xuXHRcdFx0YnAudW5zaGlmdCggY3VyICk7XG5cdFx0fVxuXG5cdFx0Ly8gV2FsayBkb3duIHRoZSB0cmVlIGxvb2tpbmcgZm9yIGEgZGlzY3JlcGFuY3lcblx0XHR3aGlsZSAoIGFwW2ldID09PSBicFtpXSApIHtcblx0XHRcdGkrKztcblx0XHR9XG5cblx0XHRyZXR1cm4gaSA/XG5cdFx0XHQvLyBEbyBhIHNpYmxpbmcgY2hlY2sgaWYgdGhlIG5vZGVzIGhhdmUgYSBjb21tb24gYW5jZXN0b3Jcblx0XHRcdHNpYmxpbmdDaGVjayggYXBbaV0sIGJwW2ldICkgOlxuXG5cdFx0XHQvLyBPdGhlcndpc2Ugbm9kZXMgaW4gb3VyIGRvY3VtZW50IHNvcnQgZmlyc3Rcblx0XHRcdGFwW2ldID09PSBwcmVmZXJyZWREb2MgPyAtMSA6XG5cdFx0XHRicFtpXSA9PT0gcHJlZmVycmVkRG9jID8gMSA6XG5cdFx0XHQwO1xuXHR9O1xuXG5cdHJldHVybiBkb2M7XG59O1xuXG5TaXp6bGUubWF0Y2hlcyA9IGZ1bmN0aW9uKCBleHByLCBlbGVtZW50cyApIHtcblx0cmV0dXJuIFNpenpsZSggZXhwciwgbnVsbCwgbnVsbCwgZWxlbWVudHMgKTtcbn07XG5cblNpenpsZS5tYXRjaGVzU2VsZWN0b3IgPSBmdW5jdGlvbiggZWxlbSwgZXhwciApIHtcblx0Ly8gU2V0IGRvY3VtZW50IHZhcnMgaWYgbmVlZGVkXG5cdGlmICggKCBlbGVtLm93bmVyRG9jdW1lbnQgfHwgZWxlbSApICE9PSBkb2N1bWVudCApIHtcblx0XHRzZXREb2N1bWVudCggZWxlbSApO1xuXHR9XG5cblx0Ly8gTWFrZSBzdXJlIHRoYXQgYXR0cmlidXRlIHNlbGVjdG9ycyBhcmUgcXVvdGVkXG5cdGV4cHIgPSBleHByLnJlcGxhY2UoIHJhdHRyaWJ1dGVRdW90ZXMsIFwiPSckMSddXCIgKTtcblxuXHRpZiAoIHN1cHBvcnQubWF0Y2hlc1NlbGVjdG9yICYmIGRvY3VtZW50SXNIVE1MICYmXG5cdFx0KCAhcmJ1Z2d5TWF0Y2hlcyB8fCAhcmJ1Z2d5TWF0Y2hlcy50ZXN0KCBleHByICkgKSAmJlxuXHRcdCggIXJidWdneVFTQSAgICAgfHwgIXJidWdneVFTQS50ZXN0KCBleHByICkgKSApIHtcblxuXHRcdHRyeSB7XG5cdFx0XHR2YXIgcmV0ID0gbWF0Y2hlcy5jYWxsKCBlbGVtLCBleHByICk7XG5cblx0XHRcdC8vIElFIDkncyBtYXRjaGVzU2VsZWN0b3IgcmV0dXJucyBmYWxzZSBvbiBkaXNjb25uZWN0ZWQgbm9kZXNcblx0XHRcdGlmICggcmV0IHx8IHN1cHBvcnQuZGlzY29ubmVjdGVkTWF0Y2ggfHxcblx0XHRcdFx0XHQvLyBBcyB3ZWxsLCBkaXNjb25uZWN0ZWQgbm9kZXMgYXJlIHNhaWQgdG8gYmUgaW4gYSBkb2N1bWVudFxuXHRcdFx0XHRcdC8vIGZyYWdtZW50IGluIElFIDlcblx0XHRcdFx0XHRlbGVtLmRvY3VtZW50ICYmIGVsZW0uZG9jdW1lbnQubm9kZVR5cGUgIT09IDExICkge1xuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKGUpIHt9XG5cdH1cblxuXHRyZXR1cm4gU2l6emxlKCBleHByLCBkb2N1bWVudCwgbnVsbCwgWyBlbGVtIF0gKS5sZW5ndGggPiAwO1xufTtcblxuU2l6emxlLmNvbnRhaW5zID0gZnVuY3Rpb24oIGNvbnRleHQsIGVsZW0gKSB7XG5cdC8vIFNldCBkb2N1bWVudCB2YXJzIGlmIG5lZWRlZFxuXHRpZiAoICggY29udGV4dC5vd25lckRvY3VtZW50IHx8IGNvbnRleHQgKSAhPT0gZG9jdW1lbnQgKSB7XG5cdFx0c2V0RG9jdW1lbnQoIGNvbnRleHQgKTtcblx0fVxuXHRyZXR1cm4gY29udGFpbnMoIGNvbnRleHQsIGVsZW0gKTtcbn07XG5cblNpenpsZS5hdHRyID0gZnVuY3Rpb24oIGVsZW0sIG5hbWUgKSB7XG5cdC8vIFNldCBkb2N1bWVudCB2YXJzIGlmIG5lZWRlZFxuXHRpZiAoICggZWxlbS5vd25lckRvY3VtZW50IHx8IGVsZW0gKSAhPT0gZG9jdW1lbnQgKSB7XG5cdFx0c2V0RG9jdW1lbnQoIGVsZW0gKTtcblx0fVxuXG5cdHZhciBmbiA9IEV4cHIuYXR0ckhhbmRsZVsgbmFtZS50b0xvd2VyQ2FzZSgpIF0sXG5cdFx0Ly8gRG9uJ3QgZ2V0IGZvb2xlZCBieSBPYmplY3QucHJvdG90eXBlIHByb3BlcnRpZXMgKGpRdWVyeSAjMTM4MDcpXG5cdFx0dmFsID0gZm4gJiYgaGFzT3duLmNhbGwoIEV4cHIuYXR0ckhhbmRsZSwgbmFtZS50b0xvd2VyQ2FzZSgpICkgP1xuXHRcdFx0Zm4oIGVsZW0sIG5hbWUsICFkb2N1bWVudElzSFRNTCApIDpcblx0XHRcdHVuZGVmaW5lZDtcblxuXHRyZXR1cm4gdmFsICE9PSB1bmRlZmluZWQgP1xuXHRcdHZhbCA6XG5cdFx0c3VwcG9ydC5hdHRyaWJ1dGVzIHx8ICFkb2N1bWVudElzSFRNTCA/XG5cdFx0XHRlbGVtLmdldEF0dHJpYnV0ZSggbmFtZSApIDpcblx0XHRcdCh2YWwgPSBlbGVtLmdldEF0dHJpYnV0ZU5vZGUobmFtZSkpICYmIHZhbC5zcGVjaWZpZWQgP1xuXHRcdFx0XHR2YWwudmFsdWUgOlxuXHRcdFx0XHRudWxsO1xufTtcblxuU2l6emxlLmVycm9yID0gZnVuY3Rpb24oIG1zZyApIHtcblx0dGhyb3cgbmV3IEVycm9yKCBcIlN5bnRheCBlcnJvciwgdW5yZWNvZ25pemVkIGV4cHJlc3Npb246IFwiICsgbXNnICk7XG59O1xuXG4vKipcbiAqIERvY3VtZW50IHNvcnRpbmcgYW5kIHJlbW92aW5nIGR1cGxpY2F0ZXNcbiAqIEBwYXJhbSB7QXJyYXlMaWtlfSByZXN1bHRzXG4gKi9cblNpenpsZS51bmlxdWVTb3J0ID0gZnVuY3Rpb24oIHJlc3VsdHMgKSB7XG5cdHZhciBlbGVtLFxuXHRcdGR1cGxpY2F0ZXMgPSBbXSxcblx0XHRqID0gMCxcblx0XHRpID0gMDtcblxuXHQvLyBVbmxlc3Mgd2UgKmtub3cqIHdlIGNhbiBkZXRlY3QgZHVwbGljYXRlcywgYXNzdW1lIHRoZWlyIHByZXNlbmNlXG5cdGhhc0R1cGxpY2F0ZSA9ICFzdXBwb3J0LmRldGVjdER1cGxpY2F0ZXM7XG5cdHNvcnRJbnB1dCA9ICFzdXBwb3J0LnNvcnRTdGFibGUgJiYgcmVzdWx0cy5zbGljZSggMCApO1xuXHRyZXN1bHRzLnNvcnQoIHNvcnRPcmRlciApO1xuXG5cdGlmICggaGFzRHVwbGljYXRlICkge1xuXHRcdHdoaWxlICggKGVsZW0gPSByZXN1bHRzW2krK10pICkge1xuXHRcdFx0aWYgKCBlbGVtID09PSByZXN1bHRzWyBpIF0gKSB7XG5cdFx0XHRcdGogPSBkdXBsaWNhdGVzLnB1c2goIGkgKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0d2hpbGUgKCBqLS0gKSB7XG5cdFx0XHRyZXN1bHRzLnNwbGljZSggZHVwbGljYXRlc1sgaiBdLCAxICk7XG5cdFx0fVxuXHR9XG5cblx0Ly8gQ2xlYXIgaW5wdXQgYWZ0ZXIgc29ydGluZyB0byByZWxlYXNlIG9iamVjdHNcblx0Ly8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9qcXVlcnkvc2l6emxlL3B1bGwvMjI1XG5cdHNvcnRJbnB1dCA9IG51bGw7XG5cblx0cmV0dXJuIHJlc3VsdHM7XG59O1xuXG4vKipcbiAqIFV0aWxpdHkgZnVuY3Rpb24gZm9yIHJldHJpZXZpbmcgdGhlIHRleHQgdmFsdWUgb2YgYW4gYXJyYXkgb2YgRE9NIG5vZGVzXG4gKiBAcGFyYW0ge0FycmF5fEVsZW1lbnR9IGVsZW1cbiAqL1xuZ2V0VGV4dCA9IFNpenpsZS5nZXRUZXh0ID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdHZhciBub2RlLFxuXHRcdHJldCA9IFwiXCIsXG5cdFx0aSA9IDAsXG5cdFx0bm9kZVR5cGUgPSBlbGVtLm5vZGVUeXBlO1xuXG5cdGlmICggIW5vZGVUeXBlICkge1xuXHRcdC8vIElmIG5vIG5vZGVUeXBlLCB0aGlzIGlzIGV4cGVjdGVkIHRvIGJlIGFuIGFycmF5XG5cdFx0d2hpbGUgKCAobm9kZSA9IGVsZW1baSsrXSkgKSB7XG5cdFx0XHQvLyBEbyBub3QgdHJhdmVyc2UgY29tbWVudCBub2Rlc1xuXHRcdFx0cmV0ICs9IGdldFRleHQoIG5vZGUgKTtcblx0XHR9XG5cdH0gZWxzZSBpZiAoIG5vZGVUeXBlID09PSAxIHx8IG5vZGVUeXBlID09PSA5IHx8IG5vZGVUeXBlID09PSAxMSApIHtcblx0XHQvLyBVc2UgdGV4dENvbnRlbnQgZm9yIGVsZW1lbnRzXG5cdFx0Ly8gaW5uZXJUZXh0IHVzYWdlIHJlbW92ZWQgZm9yIGNvbnNpc3RlbmN5IG9mIG5ldyBsaW5lcyAoalF1ZXJ5ICMxMTE1Mylcblx0XHRpZiAoIHR5cGVvZiBlbGVtLnRleHRDb250ZW50ID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIGVsZW0udGV4dENvbnRlbnQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIFRyYXZlcnNlIGl0cyBjaGlsZHJlblxuXHRcdFx0Zm9yICggZWxlbSA9IGVsZW0uZmlyc3RDaGlsZDsgZWxlbTsgZWxlbSA9IGVsZW0ubmV4dFNpYmxpbmcgKSB7XG5cdFx0XHRcdHJldCArPSBnZXRUZXh0KCBlbGVtICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9IGVsc2UgaWYgKCBub2RlVHlwZSA9PT0gMyB8fCBub2RlVHlwZSA9PT0gNCApIHtcblx0XHRyZXR1cm4gZWxlbS5ub2RlVmFsdWU7XG5cdH1cblx0Ly8gRG8gbm90IGluY2x1ZGUgY29tbWVudCBvciBwcm9jZXNzaW5nIGluc3RydWN0aW9uIG5vZGVzXG5cblx0cmV0dXJuIHJldDtcbn07XG5cbkV4cHIgPSBTaXp6bGUuc2VsZWN0b3JzID0ge1xuXG5cdC8vIENhbiBiZSBhZGp1c3RlZCBieSB0aGUgdXNlclxuXHRjYWNoZUxlbmd0aDogNTAsXG5cblx0Y3JlYXRlUHNldWRvOiBtYXJrRnVuY3Rpb24sXG5cblx0bWF0Y2g6IG1hdGNoRXhwcixcblxuXHRhdHRySGFuZGxlOiB7fSxcblxuXHRmaW5kOiB7fSxcblxuXHRyZWxhdGl2ZToge1xuXHRcdFwiPlwiOiB7IGRpcjogXCJwYXJlbnROb2RlXCIsIGZpcnN0OiB0cnVlIH0sXG5cdFx0XCIgXCI6IHsgZGlyOiBcInBhcmVudE5vZGVcIiB9LFxuXHRcdFwiK1wiOiB7IGRpcjogXCJwcmV2aW91c1NpYmxpbmdcIiwgZmlyc3Q6IHRydWUgfSxcblx0XHRcIn5cIjogeyBkaXI6IFwicHJldmlvdXNTaWJsaW5nXCIgfVxuXHR9LFxuXG5cdHByZUZpbHRlcjoge1xuXHRcdFwiQVRUUlwiOiBmdW5jdGlvbiggbWF0Y2ggKSB7XG5cdFx0XHRtYXRjaFsxXSA9IG1hdGNoWzFdLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cblx0XHRcdC8vIE1vdmUgdGhlIGdpdmVuIHZhbHVlIHRvIG1hdGNoWzNdIHdoZXRoZXIgcXVvdGVkIG9yIHVucXVvdGVkXG5cdFx0XHRtYXRjaFszXSA9ICggbWF0Y2hbM10gfHwgbWF0Y2hbNF0gfHwgbWF0Y2hbNV0gfHwgXCJcIiApLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cblx0XHRcdGlmICggbWF0Y2hbMl0gPT09IFwifj1cIiApIHtcblx0XHRcdFx0bWF0Y2hbM10gPSBcIiBcIiArIG1hdGNoWzNdICsgXCIgXCI7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBtYXRjaC5zbGljZSggMCwgNCApO1xuXHRcdH0sXG5cblx0XHRcIkNISUxEXCI6IGZ1bmN0aW9uKCBtYXRjaCApIHtcblx0XHRcdC8qIG1hdGNoZXMgZnJvbSBtYXRjaEV4cHJbXCJDSElMRFwiXVxuXHRcdFx0XHQxIHR5cGUgKG9ubHl8bnRofC4uLilcblx0XHRcdFx0MiB3aGF0IChjaGlsZHxvZi10eXBlKVxuXHRcdFx0XHQzIGFyZ3VtZW50IChldmVufG9kZHxcXGQqfFxcZCpuKFsrLV1cXGQrKT98Li4uKVxuXHRcdFx0XHQ0IHhuLWNvbXBvbmVudCBvZiB4bit5IGFyZ3VtZW50IChbKy1dP1xcZCpufClcblx0XHRcdFx0NSBzaWduIG9mIHhuLWNvbXBvbmVudFxuXHRcdFx0XHQ2IHggb2YgeG4tY29tcG9uZW50XG5cdFx0XHRcdDcgc2lnbiBvZiB5LWNvbXBvbmVudFxuXHRcdFx0XHQ4IHkgb2YgeS1jb21wb25lbnRcblx0XHRcdCovXG5cdFx0XHRtYXRjaFsxXSA9IG1hdGNoWzFdLnRvTG93ZXJDYXNlKCk7XG5cblx0XHRcdGlmICggbWF0Y2hbMV0uc2xpY2UoIDAsIDMgKSA9PT0gXCJudGhcIiApIHtcblx0XHRcdFx0Ly8gbnRoLSogcmVxdWlyZXMgYXJndW1lbnRcblx0XHRcdFx0aWYgKCAhbWF0Y2hbM10gKSB7XG5cdFx0XHRcdFx0U2l6emxlLmVycm9yKCBtYXRjaFswXSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gbnVtZXJpYyB4IGFuZCB5IHBhcmFtZXRlcnMgZm9yIEV4cHIuZmlsdGVyLkNISUxEXG5cdFx0XHRcdC8vIHJlbWVtYmVyIHRoYXQgZmFsc2UvdHJ1ZSBjYXN0IHJlc3BlY3RpdmVseSB0byAwLzFcblx0XHRcdFx0bWF0Y2hbNF0gPSArKCBtYXRjaFs0XSA/IG1hdGNoWzVdICsgKG1hdGNoWzZdIHx8IDEpIDogMiAqICggbWF0Y2hbM10gPT09IFwiZXZlblwiIHx8IG1hdGNoWzNdID09PSBcIm9kZFwiICkgKTtcblx0XHRcdFx0bWF0Y2hbNV0gPSArKCAoIG1hdGNoWzddICsgbWF0Y2hbOF0gKSB8fCBtYXRjaFszXSA9PT0gXCJvZGRcIiApO1xuXG5cdFx0XHQvLyBvdGhlciB0eXBlcyBwcm9oaWJpdCBhcmd1bWVudHNcblx0XHRcdH0gZWxzZSBpZiAoIG1hdGNoWzNdICkge1xuXHRcdFx0XHRTaXp6bGUuZXJyb3IoIG1hdGNoWzBdICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBtYXRjaDtcblx0XHR9LFxuXG5cdFx0XCJQU0VVRE9cIjogZnVuY3Rpb24oIG1hdGNoICkge1xuXHRcdFx0dmFyIGV4Y2Vzcyxcblx0XHRcdFx0dW5xdW90ZWQgPSAhbWF0Y2hbNl0gJiYgbWF0Y2hbMl07XG5cblx0XHRcdGlmICggbWF0Y2hFeHByW1wiQ0hJTERcIl0udGVzdCggbWF0Y2hbMF0gKSApIHtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEFjY2VwdCBxdW90ZWQgYXJndW1lbnRzIGFzLWlzXG5cdFx0XHRpZiAoIG1hdGNoWzNdICkge1xuXHRcdFx0XHRtYXRjaFsyXSA9IG1hdGNoWzRdIHx8IG1hdGNoWzVdIHx8IFwiXCI7XG5cblx0XHRcdC8vIFN0cmlwIGV4Y2VzcyBjaGFyYWN0ZXJzIGZyb20gdW5xdW90ZWQgYXJndW1lbnRzXG5cdFx0XHR9IGVsc2UgaWYgKCB1bnF1b3RlZCAmJiBycHNldWRvLnRlc3QoIHVucXVvdGVkICkgJiZcblx0XHRcdFx0Ly8gR2V0IGV4Y2VzcyBmcm9tIHRva2VuaXplIChyZWN1cnNpdmVseSlcblx0XHRcdFx0KGV4Y2VzcyA9IHRva2VuaXplKCB1bnF1b3RlZCwgdHJ1ZSApKSAmJlxuXHRcdFx0XHQvLyBhZHZhbmNlIHRvIHRoZSBuZXh0IGNsb3NpbmcgcGFyZW50aGVzaXNcblx0XHRcdFx0KGV4Y2VzcyA9IHVucXVvdGVkLmluZGV4T2YoIFwiKVwiLCB1bnF1b3RlZC5sZW5ndGggLSBleGNlc3MgKSAtIHVucXVvdGVkLmxlbmd0aCkgKSB7XG5cblx0XHRcdFx0Ly8gZXhjZXNzIGlzIGEgbmVnYXRpdmUgaW5kZXhcblx0XHRcdFx0bWF0Y2hbMF0gPSBtYXRjaFswXS5zbGljZSggMCwgZXhjZXNzICk7XG5cdFx0XHRcdG1hdGNoWzJdID0gdW5xdW90ZWQuc2xpY2UoIDAsIGV4Y2VzcyApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZXR1cm4gb25seSBjYXB0dXJlcyBuZWVkZWQgYnkgdGhlIHBzZXVkbyBmaWx0ZXIgbWV0aG9kICh0eXBlIGFuZCBhcmd1bWVudClcblx0XHRcdHJldHVybiBtYXRjaC5zbGljZSggMCwgMyApO1xuXHRcdH1cblx0fSxcblxuXHRmaWx0ZXI6IHtcblxuXHRcdFwiVEFHXCI6IGZ1bmN0aW9uKCBub2RlTmFtZVNlbGVjdG9yICkge1xuXHRcdFx0dmFyIG5vZGVOYW1lID0gbm9kZU5hbWVTZWxlY3Rvci5yZXBsYWNlKCBydW5lc2NhcGUsIGZ1bmVzY2FwZSApLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRyZXR1cm4gbm9kZU5hbWVTZWxlY3RvciA9PT0gXCIqXCIgP1xuXHRcdFx0XHRmdW5jdGlvbigpIHsgcmV0dXJuIHRydWU7IH0gOlxuXHRcdFx0XHRmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZWxlbS5ub2RlTmFtZSAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IG5vZGVOYW1lO1xuXHRcdFx0XHR9O1xuXHRcdH0sXG5cblx0XHRcIkNMQVNTXCI6IGZ1bmN0aW9uKCBjbGFzc05hbWUgKSB7XG5cdFx0XHR2YXIgcGF0dGVybiA9IGNsYXNzQ2FjaGVbIGNsYXNzTmFtZSArIFwiIFwiIF07XG5cblx0XHRcdHJldHVybiBwYXR0ZXJuIHx8XG5cdFx0XHRcdChwYXR0ZXJuID0gbmV3IFJlZ0V4cCggXCIoXnxcIiArIHdoaXRlc3BhY2UgKyBcIilcIiArIGNsYXNzTmFtZSArIFwiKFwiICsgd2hpdGVzcGFjZSArIFwifCQpXCIgKSkgJiZcblx0XHRcdFx0Y2xhc3NDYWNoZSggY2xhc3NOYW1lLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0XHRyZXR1cm4gcGF0dGVybi50ZXN0KCB0eXBlb2YgZWxlbS5jbGFzc05hbWUgPT09IFwic3RyaW5nXCIgJiYgZWxlbS5jbGFzc05hbWUgfHwgdHlwZW9mIGVsZW0uZ2V0QXR0cmlidXRlICE9PSBcInVuZGVmaW5lZFwiICYmIGVsZW0uZ2V0QXR0cmlidXRlKFwiY2xhc3NcIikgfHwgXCJcIiApO1xuXHRcdFx0XHR9KTtcblx0XHR9LFxuXG5cdFx0XCJBVFRSXCI6IGZ1bmN0aW9uKCBuYW1lLCBvcGVyYXRvciwgY2hlY2sgKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciByZXN1bHQgPSBTaXp6bGUuYXR0ciggZWxlbSwgbmFtZSApO1xuXG5cdFx0XHRcdGlmICggcmVzdWx0ID09IG51bGwgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG9wZXJhdG9yID09PSBcIiE9XCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCAhb3BlcmF0b3IgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXN1bHQgKz0gXCJcIjtcblxuXHRcdFx0XHRyZXR1cm4gb3BlcmF0b3IgPT09IFwiPVwiID8gcmVzdWx0ID09PSBjaGVjayA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiIT1cIiA/IHJlc3VsdCAhPT0gY2hlY2sgOlxuXHRcdFx0XHRcdG9wZXJhdG9yID09PSBcIl49XCIgPyBjaGVjayAmJiByZXN1bHQuaW5kZXhPZiggY2hlY2sgKSA9PT0gMCA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiKj1cIiA/IGNoZWNrICYmIHJlc3VsdC5pbmRleE9mKCBjaGVjayApID4gLTEgOlxuXHRcdFx0XHRcdG9wZXJhdG9yID09PSBcIiQ9XCIgPyBjaGVjayAmJiByZXN1bHQuc2xpY2UoIC1jaGVjay5sZW5ndGggKSA9PT0gY2hlY2sgOlxuXHRcdFx0XHRcdG9wZXJhdG9yID09PSBcIn49XCIgPyAoIFwiIFwiICsgcmVzdWx0LnJlcGxhY2UoIHJ3aGl0ZXNwYWNlLCBcIiBcIiApICsgXCIgXCIgKS5pbmRleE9mKCBjaGVjayApID4gLTEgOlxuXHRcdFx0XHRcdG9wZXJhdG9yID09PSBcInw9XCIgPyByZXN1bHQgPT09IGNoZWNrIHx8IHJlc3VsdC5zbGljZSggMCwgY2hlY2subGVuZ3RoICsgMSApID09PSBjaGVjayArIFwiLVwiIDpcblx0XHRcdFx0XHRmYWxzZTtcblx0XHRcdH07XG5cdFx0fSxcblxuXHRcdFwiQ0hJTERcIjogZnVuY3Rpb24oIHR5cGUsIHdoYXQsIGFyZ3VtZW50LCBmaXJzdCwgbGFzdCApIHtcblx0XHRcdHZhciBzaW1wbGUgPSB0eXBlLnNsaWNlKCAwLCAzICkgIT09IFwibnRoXCIsXG5cdFx0XHRcdGZvcndhcmQgPSB0eXBlLnNsaWNlKCAtNCApICE9PSBcImxhc3RcIixcblx0XHRcdFx0b2ZUeXBlID0gd2hhdCA9PT0gXCJvZi10eXBlXCI7XG5cblx0XHRcdHJldHVybiBmaXJzdCA9PT0gMSAmJiBsYXN0ID09PSAwID9cblxuXHRcdFx0XHQvLyBTaG9ydGN1dCBmb3IgOm50aC0qKG4pXG5cdFx0XHRcdGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRcdHJldHVybiAhIWVsZW0ucGFyZW50Tm9kZTtcblx0XHRcdFx0fSA6XG5cblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdFx0XHR2YXIgY2FjaGUsIG91dGVyQ2FjaGUsIG5vZGUsIGRpZmYsIG5vZGVJbmRleCwgc3RhcnQsXG5cdFx0XHRcdFx0XHRkaXIgPSBzaW1wbGUgIT09IGZvcndhcmQgPyBcIm5leHRTaWJsaW5nXCIgOiBcInByZXZpb3VzU2libGluZ1wiLFxuXHRcdFx0XHRcdFx0cGFyZW50ID0gZWxlbS5wYXJlbnROb2RlLFxuXHRcdFx0XHRcdFx0bmFtZSA9IG9mVHlwZSAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCksXG5cdFx0XHRcdFx0XHR1c2VDYWNoZSA9ICF4bWwgJiYgIW9mVHlwZTtcblxuXHRcdFx0XHRcdGlmICggcGFyZW50ICkge1xuXG5cdFx0XHRcdFx0XHQvLyA6KGZpcnN0fGxhc3R8b25seSktKGNoaWxkfG9mLXR5cGUpXG5cdFx0XHRcdFx0XHRpZiAoIHNpbXBsZSApIHtcblx0XHRcdFx0XHRcdFx0d2hpbGUgKCBkaXIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0bm9kZSA9IGVsZW07XG5cdFx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9IG5vZGVbIGRpciBdKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGlmICggb2ZUeXBlID8gbm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBuYW1lIDogbm9kZS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHQvLyBSZXZlcnNlIGRpcmVjdGlvbiBmb3IgOm9ubHktKiAoaWYgd2UgaGF2ZW4ndCB5ZXQgZG9uZSBzbylcblx0XHRcdFx0XHRcdFx0XHRzdGFydCA9IGRpciA9IHR5cGUgPT09IFwib25seVwiICYmICFzdGFydCAmJiBcIm5leHRTaWJsaW5nXCI7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdHN0YXJ0ID0gWyBmb3J3YXJkID8gcGFyZW50LmZpcnN0Q2hpbGQgOiBwYXJlbnQubGFzdENoaWxkIF07XG5cblx0XHRcdFx0XHRcdC8vIG5vbi14bWwgOm50aC1jaGlsZCguLi4pIHN0b3JlcyBjYWNoZSBkYXRhIG9uIGBwYXJlbnRgXG5cdFx0XHRcdFx0XHRpZiAoIGZvcndhcmQgJiYgdXNlQ2FjaGUgKSB7XG5cdFx0XHRcdFx0XHRcdC8vIFNlZWsgYGVsZW1gIGZyb20gYSBwcmV2aW91c2x5LWNhY2hlZCBpbmRleFxuXHRcdFx0XHRcdFx0XHRvdXRlckNhY2hlID0gcGFyZW50WyBleHBhbmRvIF0gfHwgKHBhcmVudFsgZXhwYW5kbyBdID0ge30pO1xuXHRcdFx0XHRcdFx0XHRjYWNoZSA9IG91dGVyQ2FjaGVbIHR5cGUgXSB8fCBbXTtcblx0XHRcdFx0XHRcdFx0bm9kZUluZGV4ID0gY2FjaGVbMF0gPT09IGRpcnJ1bnMgJiYgY2FjaGVbMV07XG5cdFx0XHRcdFx0XHRcdGRpZmYgPSBjYWNoZVswXSA9PT0gZGlycnVucyAmJiBjYWNoZVsyXTtcblx0XHRcdFx0XHRcdFx0bm9kZSA9IG5vZGVJbmRleCAmJiBwYXJlbnQuY2hpbGROb2Rlc1sgbm9kZUluZGV4IF07XG5cblx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9ICsrbm9kZUluZGV4ICYmIG5vZGUgJiYgbm9kZVsgZGlyIF0gfHxcblxuXHRcdFx0XHRcdFx0XHRcdC8vIEZhbGxiYWNrIHRvIHNlZWtpbmcgYGVsZW1gIGZyb20gdGhlIHN0YXJ0XG5cdFx0XHRcdFx0XHRcdFx0KGRpZmYgPSBub2RlSW5kZXggPSAwKSB8fCBzdGFydC5wb3AoKSkgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBXaGVuIGZvdW5kLCBjYWNoZSBpbmRleGVzIG9uIGBwYXJlbnRgIGFuZCBicmVha1xuXHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZS5ub2RlVHlwZSA9PT0gMSAmJiArK2RpZmYgJiYgbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGVbIHR5cGUgXSA9IFsgZGlycnVucywgbm9kZUluZGV4LCBkaWZmIF07XG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0Ly8gVXNlIHByZXZpb3VzbHktY2FjaGVkIGVsZW1lbnQgaW5kZXggaWYgYXZhaWxhYmxlXG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCB1c2VDYWNoZSAmJiAoY2FjaGUgPSAoZWxlbVsgZXhwYW5kbyBdIHx8IChlbGVtWyBleHBhbmRvIF0gPSB7fSkpWyB0eXBlIF0pICYmIGNhY2hlWzBdID09PSBkaXJydW5zICkge1xuXHRcdFx0XHRcdFx0XHRkaWZmID0gY2FjaGVbMV07XG5cblx0XHRcdFx0XHRcdC8vIHhtbCA6bnRoLWNoaWxkKC4uLikgb3IgOm50aC1sYXN0LWNoaWxkKC4uLikgb3IgOm50aCgtbGFzdCk/LW9mLXR5cGUoLi4uKVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0Ly8gVXNlIHRoZSBzYW1lIGxvb3AgYXMgYWJvdmUgdG8gc2VlayBgZWxlbWAgZnJvbSB0aGUgc3RhcnRcblx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9ICsrbm9kZUluZGV4ICYmIG5vZGUgJiYgbm9kZVsgZGlyIF0gfHxcblx0XHRcdFx0XHRcdFx0XHQoZGlmZiA9IG5vZGVJbmRleCA9IDApIHx8IHN0YXJ0LnBvcCgpKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdGlmICggKCBvZlR5cGUgPyBub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IG5hbWUgOiBub2RlLm5vZGVUeXBlID09PSAxICkgJiYgKytkaWZmICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gQ2FjaGUgdGhlIGluZGV4IG9mIGVhY2ggZW5jb3VudGVyZWQgZWxlbWVudFxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCB1c2VDYWNoZSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0KG5vZGVbIGV4cGFuZG8gXSB8fCAobm9kZVsgZXhwYW5kbyBdID0ge30pKVsgdHlwZSBdID0gWyBkaXJydW5zLCBkaWZmIF07XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdC8vIEluY29ycG9yYXRlIHRoZSBvZmZzZXQsIHRoZW4gY2hlY2sgYWdhaW5zdCBjeWNsZSBzaXplXG5cdFx0XHRcdFx0XHRkaWZmIC09IGxhc3Q7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZGlmZiA9PT0gZmlyc3QgfHwgKCBkaWZmICUgZmlyc3QgPT09IDAgJiYgZGlmZiAvIGZpcnN0ID49IDAgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH07XG5cdFx0fSxcblxuXHRcdFwiUFNFVURPXCI6IGZ1bmN0aW9uKCBwc2V1ZG8sIGFyZ3VtZW50ICkge1xuXHRcdFx0Ly8gcHNldWRvLWNsYXNzIG5hbWVzIGFyZSBjYXNlLWluc2Vuc2l0aXZlXG5cdFx0XHQvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9zZWxlY3RvcnMvI3BzZXVkby1jbGFzc2VzXG5cdFx0XHQvLyBQcmlvcml0aXplIGJ5IGNhc2Ugc2Vuc2l0aXZpdHkgaW4gY2FzZSBjdXN0b20gcHNldWRvcyBhcmUgYWRkZWQgd2l0aCB1cHBlcmNhc2UgbGV0dGVyc1xuXHRcdFx0Ly8gUmVtZW1iZXIgdGhhdCBzZXRGaWx0ZXJzIGluaGVyaXRzIGZyb20gcHNldWRvc1xuXHRcdFx0dmFyIGFyZ3MsXG5cdFx0XHRcdGZuID0gRXhwci5wc2V1ZG9zWyBwc2V1ZG8gXSB8fCBFeHByLnNldEZpbHRlcnNbIHBzZXVkby50b0xvd2VyQ2FzZSgpIF0gfHxcblx0XHRcdFx0XHRTaXp6bGUuZXJyb3IoIFwidW5zdXBwb3J0ZWQgcHNldWRvOiBcIiArIHBzZXVkbyApO1xuXG5cdFx0XHQvLyBUaGUgdXNlciBtYXkgdXNlIGNyZWF0ZVBzZXVkbyB0byBpbmRpY2F0ZSB0aGF0XG5cdFx0XHQvLyBhcmd1bWVudHMgYXJlIG5lZWRlZCB0byBjcmVhdGUgdGhlIGZpbHRlciBmdW5jdGlvblxuXHRcdFx0Ly8ganVzdCBhcyBTaXp6bGUgZG9lc1xuXHRcdFx0aWYgKCBmblsgZXhwYW5kbyBdICkge1xuXHRcdFx0XHRyZXR1cm4gZm4oIGFyZ3VtZW50ICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEJ1dCBtYWludGFpbiBzdXBwb3J0IGZvciBvbGQgc2lnbmF0dXJlc1xuXHRcdFx0aWYgKCBmbi5sZW5ndGggPiAxICkge1xuXHRcdFx0XHRhcmdzID0gWyBwc2V1ZG8sIHBzZXVkbywgXCJcIiwgYXJndW1lbnQgXTtcblx0XHRcdFx0cmV0dXJuIEV4cHIuc2V0RmlsdGVycy5oYXNPd25Qcm9wZXJ0eSggcHNldWRvLnRvTG93ZXJDYXNlKCkgKSA/XG5cdFx0XHRcdFx0bWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWVkLCBtYXRjaGVzICkge1xuXHRcdFx0XHRcdFx0dmFyIGlkeCxcblx0XHRcdFx0XHRcdFx0bWF0Y2hlZCA9IGZuKCBzZWVkLCBhcmd1bWVudCApLFxuXHRcdFx0XHRcdFx0XHRpID0gbWF0Y2hlZC5sZW5ndGg7XG5cdFx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0XHRcdFx0aWR4ID0gaW5kZXhPZiggc2VlZCwgbWF0Y2hlZFtpXSApO1xuXHRcdFx0XHRcdFx0XHRzZWVkWyBpZHggXSA9ICEoIG1hdGNoZXNbIGlkeCBdID0gbWF0Y2hlZFtpXSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pIDpcblx0XHRcdFx0XHRmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0XHRcdHJldHVybiBmbiggZWxlbSwgMCwgYXJncyApO1xuXHRcdFx0XHRcdH07XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBmbjtcblx0XHR9XG5cdH0sXG5cblx0cHNldWRvczoge1xuXHRcdC8vIFBvdGVudGlhbGx5IGNvbXBsZXggcHNldWRvc1xuXHRcdFwibm90XCI6IG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0XHQvLyBUcmltIHRoZSBzZWxlY3RvciBwYXNzZWQgdG8gY29tcGlsZVxuXHRcdFx0Ly8gdG8gYXZvaWQgdHJlYXRpbmcgbGVhZGluZyBhbmQgdHJhaWxpbmdcblx0XHRcdC8vIHNwYWNlcyBhcyBjb21iaW5hdG9yc1xuXHRcdFx0dmFyIGlucHV0ID0gW10sXG5cdFx0XHRcdHJlc3VsdHMgPSBbXSxcblx0XHRcdFx0bWF0Y2hlciA9IGNvbXBpbGUoIHNlbGVjdG9yLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSApO1xuXG5cdFx0XHRyZXR1cm4gbWF0Y2hlclsgZXhwYW5kbyBdID9cblx0XHRcdFx0bWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWVkLCBtYXRjaGVzLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHRcdFx0dmFyIGVsZW0sXG5cdFx0XHRcdFx0XHR1bm1hdGNoZWQgPSBtYXRjaGVyKCBzZWVkLCBudWxsLCB4bWwsIFtdICksXG5cdFx0XHRcdFx0XHRpID0gc2VlZC5sZW5ndGg7XG5cblx0XHRcdFx0XHQvLyBNYXRjaCBlbGVtZW50cyB1bm1hdGNoZWQgYnkgYG1hdGNoZXJgXG5cdFx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0XHRpZiAoIChlbGVtID0gdW5tYXRjaGVkW2ldKSApIHtcblx0XHRcdFx0XHRcdFx0c2VlZFtpXSA9ICEobWF0Y2hlc1tpXSA9IGVsZW0pO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSkgOlxuXHRcdFx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0XHRcdGlucHV0WzBdID0gZWxlbTtcblx0XHRcdFx0XHRtYXRjaGVyKCBpbnB1dCwgbnVsbCwgeG1sLCByZXN1bHRzICk7XG5cdFx0XHRcdFx0Ly8gRG9uJ3Qga2VlcCB0aGUgZWxlbWVudCAoaXNzdWUgIzI5OSlcblx0XHRcdFx0XHRpbnB1dFswXSA9IG51bGw7XG5cdFx0XHRcdFx0cmV0dXJuICFyZXN1bHRzLnBvcCgpO1xuXHRcdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0XCJoYXNcIjogbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0cmV0dXJuIFNpenpsZSggc2VsZWN0b3IsIGVsZW0gKS5sZW5ndGggPiAwO1xuXHRcdFx0fTtcblx0XHR9KSxcblxuXHRcdFwiY29udGFpbnNcIjogbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCB0ZXh0ICkge1xuXHRcdFx0dGV4dCA9IHRleHQucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0cmV0dXJuICggZWxlbS50ZXh0Q29udGVudCB8fCBlbGVtLmlubmVyVGV4dCB8fCBnZXRUZXh0KCBlbGVtICkgKS5pbmRleE9mKCB0ZXh0ICkgPiAtMTtcblx0XHRcdH07XG5cdFx0fSksXG5cblx0XHQvLyBcIldoZXRoZXIgYW4gZWxlbWVudCBpcyByZXByZXNlbnRlZCBieSBhIDpsYW5nKCkgc2VsZWN0b3Jcblx0XHQvLyBpcyBiYXNlZCBzb2xlbHkgb24gdGhlIGVsZW1lbnQncyBsYW5ndWFnZSB2YWx1ZVxuXHRcdC8vIGJlaW5nIGVxdWFsIHRvIHRoZSBpZGVudGlmaWVyIEMsXG5cdFx0Ly8gb3IgYmVnaW5uaW5nIHdpdGggdGhlIGlkZW50aWZpZXIgQyBpbW1lZGlhdGVseSBmb2xsb3dlZCBieSBcIi1cIi5cblx0XHQvLyBUaGUgbWF0Y2hpbmcgb2YgQyBhZ2FpbnN0IHRoZSBlbGVtZW50J3MgbGFuZ3VhZ2UgdmFsdWUgaXMgcGVyZm9ybWVkIGNhc2UtaW5zZW5zaXRpdmVseS5cblx0XHQvLyBUaGUgaWRlbnRpZmllciBDIGRvZXMgbm90IGhhdmUgdG8gYmUgYSB2YWxpZCBsYW5ndWFnZSBuYW1lLlwiXG5cdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvc2VsZWN0b3JzLyNsYW5nLXBzZXVkb1xuXHRcdFwibGFuZ1wiOiBtYXJrRnVuY3Rpb24oIGZ1bmN0aW9uKCBsYW5nICkge1xuXHRcdFx0Ly8gbGFuZyB2YWx1ZSBtdXN0IGJlIGEgdmFsaWQgaWRlbnRpZmllclxuXHRcdFx0aWYgKCAhcmlkZW50aWZpZXIudGVzdChsYW5nIHx8IFwiXCIpICkge1xuXHRcdFx0XHRTaXp6bGUuZXJyb3IoIFwidW5zdXBwb3J0ZWQgbGFuZzogXCIgKyBsYW5nICk7XG5cdFx0XHR9XG5cdFx0XHRsYW5nID0gbGFuZy5yZXBsYWNlKCBydW5lc2NhcGUsIGZ1bmVzY2FwZSApLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciBlbGVtTGFuZztcblx0XHRcdFx0ZG8ge1xuXHRcdFx0XHRcdGlmICggKGVsZW1MYW5nID0gZG9jdW1lbnRJc0hUTUwgP1xuXHRcdFx0XHRcdFx0ZWxlbS5sYW5nIDpcblx0XHRcdFx0XHRcdGVsZW0uZ2V0QXR0cmlidXRlKFwieG1sOmxhbmdcIikgfHwgZWxlbS5nZXRBdHRyaWJ1dGUoXCJsYW5nXCIpKSApIHtcblxuXHRcdFx0XHRcdFx0ZWxlbUxhbmcgPSBlbGVtTGFuZy50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIGVsZW1MYW5nID09PSBsYW5nIHx8IGVsZW1MYW5nLmluZGV4T2YoIGxhbmcgKyBcIi1cIiApID09PSAwO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSB3aGlsZSAoIChlbGVtID0gZWxlbS5wYXJlbnROb2RlKSAmJiBlbGVtLm5vZGVUeXBlID09PSAxICk7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH07XG5cdFx0fSksXG5cblx0XHQvLyBNaXNjZWxsYW5lb3VzXG5cdFx0XCJ0YXJnZXRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHR2YXIgaGFzaCA9IHdpbmRvdy5sb2NhdGlvbiAmJiB3aW5kb3cubG9jYXRpb24uaGFzaDtcblx0XHRcdHJldHVybiBoYXNoICYmIGhhc2guc2xpY2UoIDEgKSA9PT0gZWxlbS5pZDtcblx0XHR9LFxuXG5cdFx0XCJyb290XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0gPT09IGRvY0VsZW07XG5cdFx0fSxcblxuXHRcdFwiZm9jdXNcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gZWxlbSA9PT0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAmJiAoIWRvY3VtZW50Lmhhc0ZvY3VzIHx8IGRvY3VtZW50Lmhhc0ZvY3VzKCkpICYmICEhKGVsZW0udHlwZSB8fCBlbGVtLmhyZWYgfHwgfmVsZW0udGFiSW5kZXgpO1xuXHRcdH0sXG5cblx0XHQvLyBCb29sZWFuIHByb3BlcnRpZXNcblx0XHRcImVuYWJsZWRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5kaXNhYmxlZCA9PT0gZmFsc2U7XG5cdFx0fSxcblxuXHRcdFwiZGlzYWJsZWRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5kaXNhYmxlZCA9PT0gdHJ1ZTtcblx0XHR9LFxuXG5cdFx0XCJjaGVja2VkXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0Ly8gSW4gQ1NTMywgOmNoZWNrZWQgc2hvdWxkIHJldHVybiBib3RoIGNoZWNrZWQgYW5kIHNlbGVjdGVkIGVsZW1lbnRzXG5cdFx0XHQvLyBodHRwOi8vd3d3LnczLm9yZy9UUi8yMDExL1JFQy1jc3MzLXNlbGVjdG9ycy0yMDExMDkyOS8jY2hlY2tlZFxuXHRcdFx0dmFyIG5vZGVOYW1lID0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0cmV0dXJuIChub2RlTmFtZSA9PT0gXCJpbnB1dFwiICYmICEhZWxlbS5jaGVja2VkKSB8fCAobm9kZU5hbWUgPT09IFwib3B0aW9uXCIgJiYgISFlbGVtLnNlbGVjdGVkKTtcblx0XHR9LFxuXG5cdFx0XCJzZWxlY3RlZFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdC8vIEFjY2Vzc2luZyB0aGlzIHByb3BlcnR5IG1ha2VzIHNlbGVjdGVkLWJ5LWRlZmF1bHRcblx0XHRcdC8vIG9wdGlvbnMgaW4gU2FmYXJpIHdvcmsgcHJvcGVybHlcblx0XHRcdGlmICggZWxlbS5wYXJlbnROb2RlICkge1xuXHRcdFx0XHRlbGVtLnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGVsZW0uc2VsZWN0ZWQgPT09IHRydWU7XG5cdFx0fSxcblxuXHRcdC8vIENvbnRlbnRzXG5cdFx0XCJlbXB0eVwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL3NlbGVjdG9ycy8jZW1wdHktcHNldWRvXG5cdFx0XHQvLyA6ZW1wdHkgaXMgbmVnYXRlZCBieSBlbGVtZW50ICgxKSBvciBjb250ZW50IG5vZGVzICh0ZXh0OiAzOyBjZGF0YTogNDsgZW50aXR5IHJlZjogNSksXG5cdFx0XHQvLyAgIGJ1dCBub3QgYnkgb3RoZXJzIChjb21tZW50OiA4OyBwcm9jZXNzaW5nIGluc3RydWN0aW9uOiA3OyBldGMuKVxuXHRcdFx0Ly8gbm9kZVR5cGUgPCA2IHdvcmtzIGJlY2F1c2UgYXR0cmlidXRlcyAoMikgZG8gbm90IGFwcGVhciBhcyBjaGlsZHJlblxuXHRcdFx0Zm9yICggZWxlbSA9IGVsZW0uZmlyc3RDaGlsZDsgZWxlbTsgZWxlbSA9IGVsZW0ubmV4dFNpYmxpbmcgKSB7XG5cdFx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA8IDYgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9LFxuXG5cdFx0XCJwYXJlbnRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gIUV4cHIucHNldWRvc1tcImVtcHR5XCJdKCBlbGVtICk7XG5cdFx0fSxcblxuXHRcdC8vIEVsZW1lbnQvaW5wdXQgdHlwZXNcblx0XHRcImhlYWRlclwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiByaGVhZGVyLnRlc3QoIGVsZW0ubm9kZU5hbWUgKTtcblx0XHR9LFxuXG5cdFx0XCJpbnB1dFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiByaW5wdXRzLnRlc3QoIGVsZW0ubm9kZU5hbWUgKTtcblx0XHR9LFxuXG5cdFx0XCJidXR0b25cIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHR2YXIgbmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiBuYW1lID09PSBcImlucHV0XCIgJiYgZWxlbS50eXBlID09PSBcImJ1dHRvblwiIHx8IG5hbWUgPT09IFwiYnV0dG9uXCI7XG5cdFx0fSxcblxuXHRcdFwidGV4dFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHZhciBhdHRyO1xuXHRcdFx0cmV0dXJuIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gXCJpbnB1dFwiICYmXG5cdFx0XHRcdGVsZW0udHlwZSA9PT0gXCJ0ZXh0XCIgJiZcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBJRTw4XG5cdFx0XHRcdC8vIE5ldyBIVE1MNSBhdHRyaWJ1dGUgdmFsdWVzIChlLmcuLCBcInNlYXJjaFwiKSBhcHBlYXIgd2l0aCBlbGVtLnR5cGUgPT09IFwidGV4dFwiXG5cdFx0XHRcdCggKGF0dHIgPSBlbGVtLmdldEF0dHJpYnV0ZShcInR5cGVcIikpID09IG51bGwgfHwgYXR0ci50b0xvd2VyQ2FzZSgpID09PSBcInRleHRcIiApO1xuXHRcdH0sXG5cblx0XHQvLyBQb3NpdGlvbi1pbi1jb2xsZWN0aW9uXG5cdFx0XCJmaXJzdFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIFsgMCBdO1xuXHRcdH0pLFxuXG5cdFx0XCJsYXN0XCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoICkge1xuXHRcdFx0cmV0dXJuIFsgbGVuZ3RoIC0gMSBdO1xuXHRcdH0pLFxuXG5cdFx0XCJlcVwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCwgYXJndW1lbnQgKSB7XG5cdFx0XHRyZXR1cm4gWyBhcmd1bWVudCA8IDAgPyBhcmd1bWVudCArIGxlbmd0aCA6IGFyZ3VtZW50IF07XG5cdFx0fSksXG5cblx0XHRcImV2ZW5cIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGggKSB7XG5cdFx0XHR2YXIgaSA9IDA7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkgKz0gMiApIHtcblx0XHRcdFx0bWF0Y2hJbmRleGVzLnB1c2goIGkgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtYXRjaEluZGV4ZXM7XG5cdFx0fSksXG5cblx0XHRcIm9kZFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCApIHtcblx0XHRcdHZhciBpID0gMTtcblx0XHRcdGZvciAoIDsgaSA8IGxlbmd0aDsgaSArPSAyICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KSxcblxuXHRcdFwibHRcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGgsIGFyZ3VtZW50ICkge1xuXHRcdFx0dmFyIGkgPSBhcmd1bWVudCA8IDAgPyBhcmd1bWVudCArIGxlbmd0aCA6IGFyZ3VtZW50O1xuXHRcdFx0Zm9yICggOyAtLWkgPj0gMDsgKSB7XG5cdFx0XHRcdG1hdGNoSW5kZXhlcy5wdXNoKCBpICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbWF0Y2hJbmRleGVzO1xuXHRcdH0pLFxuXG5cdFx0XCJndFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCwgYXJndW1lbnQgKSB7XG5cdFx0XHR2YXIgaSA9IGFyZ3VtZW50IDwgMCA/IGFyZ3VtZW50ICsgbGVuZ3RoIDogYXJndW1lbnQ7XG5cdFx0XHRmb3IgKCA7ICsraSA8IGxlbmd0aDsgKSB7XG5cdFx0XHRcdG1hdGNoSW5kZXhlcy5wdXNoKCBpICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbWF0Y2hJbmRleGVzO1xuXHRcdH0pXG5cdH1cbn07XG5cbkV4cHIucHNldWRvc1tcIm50aFwiXSA9IEV4cHIucHNldWRvc1tcImVxXCJdO1xuXG4vLyBBZGQgYnV0dG9uL2lucHV0IHR5cGUgcHNldWRvc1xuZm9yICggaSBpbiB7IHJhZGlvOiB0cnVlLCBjaGVja2JveDogdHJ1ZSwgZmlsZTogdHJ1ZSwgcGFzc3dvcmQ6IHRydWUsIGltYWdlOiB0cnVlIH0gKSB7XG5cdEV4cHIucHNldWRvc1sgaSBdID0gY3JlYXRlSW5wdXRQc2V1ZG8oIGkgKTtcbn1cbmZvciAoIGkgaW4geyBzdWJtaXQ6IHRydWUsIHJlc2V0OiB0cnVlIH0gKSB7XG5cdEV4cHIucHNldWRvc1sgaSBdID0gY3JlYXRlQnV0dG9uUHNldWRvKCBpICk7XG59XG5cbi8vIEVhc3kgQVBJIGZvciBjcmVhdGluZyBuZXcgc2V0RmlsdGVyc1xuZnVuY3Rpb24gc2V0RmlsdGVycygpIHt9XG5zZXRGaWx0ZXJzLnByb3RvdHlwZSA9IEV4cHIuZmlsdGVycyA9IEV4cHIucHNldWRvcztcbkV4cHIuc2V0RmlsdGVycyA9IG5ldyBzZXRGaWx0ZXJzKCk7XG5cbnRva2VuaXplID0gU2l6emxlLnRva2VuaXplID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBwYXJzZU9ubHkgKSB7XG5cdHZhciBtYXRjaGVkLCBtYXRjaCwgdG9rZW5zLCB0eXBlLFxuXHRcdHNvRmFyLCBncm91cHMsIHByZUZpbHRlcnMsXG5cdFx0Y2FjaGVkID0gdG9rZW5DYWNoZVsgc2VsZWN0b3IgKyBcIiBcIiBdO1xuXG5cdGlmICggY2FjaGVkICkge1xuXHRcdHJldHVybiBwYXJzZU9ubHkgPyAwIDogY2FjaGVkLnNsaWNlKCAwICk7XG5cdH1cblxuXHRzb0ZhciA9IHNlbGVjdG9yO1xuXHRncm91cHMgPSBbXTtcblx0cHJlRmlsdGVycyA9IEV4cHIucHJlRmlsdGVyO1xuXG5cdHdoaWxlICggc29GYXIgKSB7XG5cblx0XHQvLyBDb21tYSBhbmQgZmlyc3QgcnVuXG5cdFx0aWYgKCAhbWF0Y2hlZCB8fCAobWF0Y2ggPSByY29tbWEuZXhlYyggc29GYXIgKSkgKSB7XG5cdFx0XHRpZiAoIG1hdGNoICkge1xuXHRcdFx0XHQvLyBEb24ndCBjb25zdW1lIHRyYWlsaW5nIGNvbW1hcyBhcyB2YWxpZFxuXHRcdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaFswXS5sZW5ndGggKSB8fCBzb0Zhcjtcblx0XHRcdH1cblx0XHRcdGdyb3Vwcy5wdXNoKCAodG9rZW5zID0gW10pICk7XG5cdFx0fVxuXG5cdFx0bWF0Y2hlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gQ29tYmluYXRvcnNcblx0XHRpZiAoIChtYXRjaCA9IHJjb21iaW5hdG9ycy5leGVjKCBzb0ZhciApKSApIHtcblx0XHRcdG1hdGNoZWQgPSBtYXRjaC5zaGlmdCgpO1xuXHRcdFx0dG9rZW5zLnB1c2goe1xuXHRcdFx0XHR2YWx1ZTogbWF0Y2hlZCxcblx0XHRcdFx0Ly8gQ2FzdCBkZXNjZW5kYW50IGNvbWJpbmF0b3JzIHRvIHNwYWNlXG5cdFx0XHRcdHR5cGU6IG1hdGNoWzBdLnJlcGxhY2UoIHJ0cmltLCBcIiBcIiApXG5cdFx0XHR9KTtcblx0XHRcdHNvRmFyID0gc29GYXIuc2xpY2UoIG1hdGNoZWQubGVuZ3RoICk7XG5cdFx0fVxuXG5cdFx0Ly8gRmlsdGVyc1xuXHRcdGZvciAoIHR5cGUgaW4gRXhwci5maWx0ZXIgKSB7XG5cdFx0XHRpZiAoIChtYXRjaCA9IG1hdGNoRXhwclsgdHlwZSBdLmV4ZWMoIHNvRmFyICkpICYmICghcHJlRmlsdGVyc1sgdHlwZSBdIHx8XG5cdFx0XHRcdChtYXRjaCA9IHByZUZpbHRlcnNbIHR5cGUgXSggbWF0Y2ggKSkpICkge1xuXHRcdFx0XHRtYXRjaGVkID0gbWF0Y2guc2hpZnQoKTtcblx0XHRcdFx0dG9rZW5zLnB1c2goe1xuXHRcdFx0XHRcdHZhbHVlOiBtYXRjaGVkLFxuXHRcdFx0XHRcdHR5cGU6IHR5cGUsXG5cdFx0XHRcdFx0bWF0Y2hlczogbWF0Y2hcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHNvRmFyID0gc29GYXIuc2xpY2UoIG1hdGNoZWQubGVuZ3RoICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCAhbWF0Y2hlZCApIHtcblx0XHRcdGJyZWFrO1xuXHRcdH1cblx0fVxuXG5cdC8vIFJldHVybiB0aGUgbGVuZ3RoIG9mIHRoZSBpbnZhbGlkIGV4Y2Vzc1xuXHQvLyBpZiB3ZSdyZSBqdXN0IHBhcnNpbmdcblx0Ly8gT3RoZXJ3aXNlLCB0aHJvdyBhbiBlcnJvciBvciByZXR1cm4gdG9rZW5zXG5cdHJldHVybiBwYXJzZU9ubHkgP1xuXHRcdHNvRmFyLmxlbmd0aCA6XG5cdFx0c29GYXIgP1xuXHRcdFx0U2l6emxlLmVycm9yKCBzZWxlY3RvciApIDpcblx0XHRcdC8vIENhY2hlIHRoZSB0b2tlbnNcblx0XHRcdHRva2VuQ2FjaGUoIHNlbGVjdG9yLCBncm91cHMgKS5zbGljZSggMCApO1xufTtcblxuZnVuY3Rpb24gdG9TZWxlY3RvciggdG9rZW5zICkge1xuXHR2YXIgaSA9IDAsXG5cdFx0bGVuID0gdG9rZW5zLmxlbmd0aCxcblx0XHRzZWxlY3RvciA9IFwiXCI7XG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdHNlbGVjdG9yICs9IHRva2Vuc1tpXS52YWx1ZTtcblx0fVxuXHRyZXR1cm4gc2VsZWN0b3I7XG59XG5cbmZ1bmN0aW9uIGFkZENvbWJpbmF0b3IoIG1hdGNoZXIsIGNvbWJpbmF0b3IsIGJhc2UgKSB7XG5cdHZhciBkaXIgPSBjb21iaW5hdG9yLmRpcixcblx0XHRjaGVja05vbkVsZW1lbnRzID0gYmFzZSAmJiBkaXIgPT09IFwicGFyZW50Tm9kZVwiLFxuXHRcdGRvbmVOYW1lID0gZG9uZSsrO1xuXG5cdHJldHVybiBjb21iaW5hdG9yLmZpcnN0ID9cblx0XHQvLyBDaGVjayBhZ2FpbnN0IGNsb3Nlc3QgYW5jZXN0b3IvcHJlY2VkaW5nIGVsZW1lbnRcblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1bIGRpciBdKSApIHtcblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSA6XG5cblx0XHQvLyBDaGVjayBhZ2FpbnN0IGFsbCBhbmNlc3Rvci9wcmVjZWRpbmcgZWxlbWVudHNcblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIG9sZENhY2hlLCBvdXRlckNhY2hlLFxuXHRcdFx0XHRuZXdDYWNoZSA9IFsgZGlycnVucywgZG9uZU5hbWUgXTtcblxuXHRcdFx0Ly8gV2UgY2FuJ3Qgc2V0IGFyYml0cmFyeSBkYXRhIG9uIFhNTCBub2Rlcywgc28gdGhleSBkb24ndCBiZW5lZml0IGZyb20gZGlyIGNhY2hpbmdcblx0XHRcdGlmICggeG1sICkge1xuXHRcdFx0XHR3aGlsZSAoIChlbGVtID0gZWxlbVsgZGlyIF0pICkge1xuXHRcdFx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSB8fCBjaGVja05vbkVsZW1lbnRzICkge1xuXHRcdFx0XHRcdFx0aWYgKCBtYXRjaGVyKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR3aGlsZSAoIChlbGVtID0gZWxlbVsgZGlyIF0pICkge1xuXHRcdFx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSB8fCBjaGVja05vbkVsZW1lbnRzICkge1xuXHRcdFx0XHRcdFx0b3V0ZXJDYWNoZSA9IGVsZW1bIGV4cGFuZG8gXSB8fCAoZWxlbVsgZXhwYW5kbyBdID0ge30pO1xuXHRcdFx0XHRcdFx0aWYgKCAob2xkQ2FjaGUgPSBvdXRlckNhY2hlWyBkaXIgXSkgJiZcblx0XHRcdFx0XHRcdFx0b2xkQ2FjaGVbIDAgXSA9PT0gZGlycnVucyAmJiBvbGRDYWNoZVsgMSBdID09PSBkb25lTmFtZSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBBc3NpZ24gdG8gbmV3Q2FjaGUgc28gcmVzdWx0cyBiYWNrLXByb3BhZ2F0ZSB0byBwcmV2aW91cyBlbGVtZW50c1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gKG5ld0NhY2hlWyAyIF0gPSBvbGRDYWNoZVsgMiBdKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdC8vIFJldXNlIG5ld2NhY2hlIHNvIHJlc3VsdHMgYmFjay1wcm9wYWdhdGUgdG8gcHJldmlvdXMgZWxlbWVudHNcblx0XHRcdFx0XHRcdFx0b3V0ZXJDYWNoZVsgZGlyIF0gPSBuZXdDYWNoZTtcblxuXHRcdFx0XHRcdFx0XHQvLyBBIG1hdGNoIG1lYW5zIHdlJ3JlIGRvbmU7IGEgZmFpbCBtZWFucyB3ZSBoYXZlIHRvIGtlZXAgY2hlY2tpbmdcblx0XHRcdFx0XHRcdFx0aWYgKCAobmV3Q2FjaGVbIDIgXSA9IG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApKSApIHtcblx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG59XG5cbmZ1bmN0aW9uIGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApIHtcblx0cmV0dXJuIG1hdGNoZXJzLmxlbmd0aCA+IDEgP1xuXHRcdGZ1bmN0aW9uKCBlbGVtLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHR2YXIgaSA9IG1hdGNoZXJzLmxlbmd0aDtcblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRpZiAoICFtYXRjaGVyc1tpXSggZWxlbSwgY29udGV4dCwgeG1sICkgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9IDpcblx0XHRtYXRjaGVyc1swXTtcbn1cblxuZnVuY3Rpb24gbXVsdGlwbGVDb250ZXh0cyggc2VsZWN0b3IsIGNvbnRleHRzLCByZXN1bHRzICkge1xuXHR2YXIgaSA9IDAsXG5cdFx0bGVuID0gY29udGV4dHMubGVuZ3RoO1xuXHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRTaXp6bGUoIHNlbGVjdG9yLCBjb250ZXh0c1tpXSwgcmVzdWx0cyApO1xuXHR9XG5cdHJldHVybiByZXN1bHRzO1xufVxuXG5mdW5jdGlvbiBjb25kZW5zZSggdW5tYXRjaGVkLCBtYXAsIGZpbHRlciwgY29udGV4dCwgeG1sICkge1xuXHR2YXIgZWxlbSxcblx0XHRuZXdVbm1hdGNoZWQgPSBbXSxcblx0XHRpID0gMCxcblx0XHRsZW4gPSB1bm1hdGNoZWQubGVuZ3RoLFxuXHRcdG1hcHBlZCA9IG1hcCAhPSBudWxsO1xuXG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdGlmICggKGVsZW0gPSB1bm1hdGNoZWRbaV0pICkge1xuXHRcdFx0aWYgKCAhZmlsdGVyIHx8IGZpbHRlciggZWxlbSwgY29udGV4dCwgeG1sICkgKSB7XG5cdFx0XHRcdG5ld1VubWF0Y2hlZC5wdXNoKCBlbGVtICk7XG5cdFx0XHRcdGlmICggbWFwcGVkICkge1xuXHRcdFx0XHRcdG1hcC5wdXNoKCBpICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gbmV3VW5tYXRjaGVkO1xufVxuXG5mdW5jdGlvbiBzZXRNYXRjaGVyKCBwcmVGaWx0ZXIsIHNlbGVjdG9yLCBtYXRjaGVyLCBwb3N0RmlsdGVyLCBwb3N0RmluZGVyLCBwb3N0U2VsZWN0b3IgKSB7XG5cdGlmICggcG9zdEZpbHRlciAmJiAhcG9zdEZpbHRlclsgZXhwYW5kbyBdICkge1xuXHRcdHBvc3RGaWx0ZXIgPSBzZXRNYXRjaGVyKCBwb3N0RmlsdGVyICk7XG5cdH1cblx0aWYgKCBwb3N0RmluZGVyICYmICFwb3N0RmluZGVyWyBleHBhbmRvIF0gKSB7XG5cdFx0cG9zdEZpbmRlciA9IHNldE1hdGNoZXIoIHBvc3RGaW5kZXIsIHBvc3RTZWxlY3RvciApO1xuXHR9XG5cdHJldHVybiBtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIHNlZWQsIHJlc3VsdHMsIGNvbnRleHQsIHhtbCApIHtcblx0XHR2YXIgdGVtcCwgaSwgZWxlbSxcblx0XHRcdHByZU1hcCA9IFtdLFxuXHRcdFx0cG9zdE1hcCA9IFtdLFxuXHRcdFx0cHJlZXhpc3RpbmcgPSByZXN1bHRzLmxlbmd0aCxcblxuXHRcdFx0Ly8gR2V0IGluaXRpYWwgZWxlbWVudHMgZnJvbSBzZWVkIG9yIGNvbnRleHRcblx0XHRcdGVsZW1zID0gc2VlZCB8fCBtdWx0aXBsZUNvbnRleHRzKCBzZWxlY3RvciB8fCBcIipcIiwgY29udGV4dC5ub2RlVHlwZSA/IFsgY29udGV4dCBdIDogY29udGV4dCwgW10gKSxcblxuXHRcdFx0Ly8gUHJlZmlsdGVyIHRvIGdldCBtYXRjaGVyIGlucHV0LCBwcmVzZXJ2aW5nIGEgbWFwIGZvciBzZWVkLXJlc3VsdHMgc3luY2hyb25pemF0aW9uXG5cdFx0XHRtYXRjaGVySW4gPSBwcmVGaWx0ZXIgJiYgKCBzZWVkIHx8ICFzZWxlY3RvciApID9cblx0XHRcdFx0Y29uZGVuc2UoIGVsZW1zLCBwcmVNYXAsIHByZUZpbHRlciwgY29udGV4dCwgeG1sICkgOlxuXHRcdFx0XHRlbGVtcyxcblxuXHRcdFx0bWF0Y2hlck91dCA9IG1hdGNoZXIgP1xuXHRcdFx0XHQvLyBJZiB3ZSBoYXZlIGEgcG9zdEZpbmRlciwgb3IgZmlsdGVyZWQgc2VlZCwgb3Igbm9uLXNlZWQgcG9zdEZpbHRlciBvciBwcmVleGlzdGluZyByZXN1bHRzLFxuXHRcdFx0XHRwb3N0RmluZGVyIHx8ICggc2VlZCA/IHByZUZpbHRlciA6IHByZWV4aXN0aW5nIHx8IHBvc3RGaWx0ZXIgKSA/XG5cblx0XHRcdFx0XHQvLyAuLi5pbnRlcm1lZGlhdGUgcHJvY2Vzc2luZyBpcyBuZWNlc3Nhcnlcblx0XHRcdFx0XHRbXSA6XG5cblx0XHRcdFx0XHQvLyAuLi5vdGhlcndpc2UgdXNlIHJlc3VsdHMgZGlyZWN0bHlcblx0XHRcdFx0XHRyZXN1bHRzIDpcblx0XHRcdFx0bWF0Y2hlckluO1xuXG5cdFx0Ly8gRmluZCBwcmltYXJ5IG1hdGNoZXNcblx0XHRpZiAoIG1hdGNoZXIgKSB7XG5cdFx0XHRtYXRjaGVyKCBtYXRjaGVySW4sIG1hdGNoZXJPdXQsIGNvbnRleHQsIHhtbCApO1xuXHRcdH1cblxuXHRcdC8vIEFwcGx5IHBvc3RGaWx0ZXJcblx0XHRpZiAoIHBvc3RGaWx0ZXIgKSB7XG5cdFx0XHR0ZW1wID0gY29uZGVuc2UoIG1hdGNoZXJPdXQsIHBvc3RNYXAgKTtcblx0XHRcdHBvc3RGaWx0ZXIoIHRlbXAsIFtdLCBjb250ZXh0LCB4bWwgKTtcblxuXHRcdFx0Ly8gVW4tbWF0Y2ggZmFpbGluZyBlbGVtZW50cyBieSBtb3ZpbmcgdGhlbSBiYWNrIHRvIG1hdGNoZXJJblxuXHRcdFx0aSA9IHRlbXAubGVuZ3RoO1xuXHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdGlmICggKGVsZW0gPSB0ZW1wW2ldKSApIHtcblx0XHRcdFx0XHRtYXRjaGVyT3V0WyBwb3N0TWFwW2ldIF0gPSAhKG1hdGNoZXJJblsgcG9zdE1hcFtpXSBdID0gZWxlbSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoIHNlZWQgKSB7XG5cdFx0XHRpZiAoIHBvc3RGaW5kZXIgfHwgcHJlRmlsdGVyICkge1xuXHRcdFx0XHRpZiAoIHBvc3RGaW5kZXIgKSB7XG5cdFx0XHRcdFx0Ly8gR2V0IHRoZSBmaW5hbCBtYXRjaGVyT3V0IGJ5IGNvbmRlbnNpbmcgdGhpcyBpbnRlcm1lZGlhdGUgaW50byBwb3N0RmluZGVyIGNvbnRleHRzXG5cdFx0XHRcdFx0dGVtcCA9IFtdO1xuXHRcdFx0XHRcdGkgPSBtYXRjaGVyT3V0Lmxlbmd0aDtcblx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0XHRcdGlmICggKGVsZW0gPSBtYXRjaGVyT3V0W2ldKSApIHtcblx0XHRcdFx0XHRcdFx0Ly8gUmVzdG9yZSBtYXRjaGVySW4gc2luY2UgZWxlbSBpcyBub3QgeWV0IGEgZmluYWwgbWF0Y2hcblx0XHRcdFx0XHRcdFx0dGVtcC5wdXNoKCAobWF0Y2hlckluW2ldID0gZWxlbSkgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cG9zdEZpbmRlciggbnVsbCwgKG1hdGNoZXJPdXQgPSBbXSksIHRlbXAsIHhtbCApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gTW92ZSBtYXRjaGVkIGVsZW1lbnRzIGZyb20gc2VlZCB0byByZXN1bHRzIHRvIGtlZXAgdGhlbSBzeW5jaHJvbml6ZWRcblx0XHRcdFx0aSA9IG1hdGNoZXJPdXQubGVuZ3RoO1xuXHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0XHRpZiAoIChlbGVtID0gbWF0Y2hlck91dFtpXSkgJiZcblx0XHRcdFx0XHRcdCh0ZW1wID0gcG9zdEZpbmRlciA/IGluZGV4T2YoIHNlZWQsIGVsZW0gKSA6IHByZU1hcFtpXSkgPiAtMSApIHtcblxuXHRcdFx0XHRcdFx0c2VlZFt0ZW1wXSA9ICEocmVzdWx0c1t0ZW1wXSA9IGVsZW0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0Ly8gQWRkIGVsZW1lbnRzIHRvIHJlc3VsdHMsIHRocm91Z2ggcG9zdEZpbmRlciBpZiBkZWZpbmVkXG5cdFx0fSBlbHNlIHtcblx0XHRcdG1hdGNoZXJPdXQgPSBjb25kZW5zZShcblx0XHRcdFx0bWF0Y2hlck91dCA9PT0gcmVzdWx0cyA/XG5cdFx0XHRcdFx0bWF0Y2hlck91dC5zcGxpY2UoIHByZWV4aXN0aW5nLCBtYXRjaGVyT3V0Lmxlbmd0aCApIDpcblx0XHRcdFx0XHRtYXRjaGVyT3V0XG5cdFx0XHQpO1xuXHRcdFx0aWYgKCBwb3N0RmluZGVyICkge1xuXHRcdFx0XHRwb3N0RmluZGVyKCBudWxsLCByZXN1bHRzLCBtYXRjaGVyT3V0LCB4bWwgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHB1c2guYXBwbHkoIHJlc3VsdHMsIG1hdGNoZXJPdXQgKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBtYXRjaGVyRnJvbVRva2VucyggdG9rZW5zICkge1xuXHR2YXIgY2hlY2tDb250ZXh0LCBtYXRjaGVyLCBqLFxuXHRcdGxlbiA9IHRva2Vucy5sZW5ndGgsXG5cdFx0bGVhZGluZ1JlbGF0aXZlID0gRXhwci5yZWxhdGl2ZVsgdG9rZW5zWzBdLnR5cGUgXSxcblx0XHRpbXBsaWNpdFJlbGF0aXZlID0gbGVhZGluZ1JlbGF0aXZlIHx8IEV4cHIucmVsYXRpdmVbXCIgXCJdLFxuXHRcdGkgPSBsZWFkaW5nUmVsYXRpdmUgPyAxIDogMCxcblxuXHRcdC8vIFRoZSBmb3VuZGF0aW9uYWwgbWF0Y2hlciBlbnN1cmVzIHRoYXQgZWxlbWVudHMgYXJlIHJlYWNoYWJsZSBmcm9tIHRvcC1sZXZlbCBjb250ZXh0KHMpXG5cdFx0bWF0Y2hDb250ZXh0ID0gYWRkQ29tYmluYXRvciggZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gZWxlbSA9PT0gY2hlY2tDb250ZXh0O1xuXHRcdH0sIGltcGxpY2l0UmVsYXRpdmUsIHRydWUgKSxcblx0XHRtYXRjaEFueUNvbnRleHQgPSBhZGRDb21iaW5hdG9yKCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBpbmRleE9mKCBjaGVja0NvbnRleHQsIGVsZW0gKSA+IC0xO1xuXHRcdH0sIGltcGxpY2l0UmVsYXRpdmUsIHRydWUgKSxcblx0XHRtYXRjaGVycyA9IFsgZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdHZhciByZXQgPSAoICFsZWFkaW5nUmVsYXRpdmUgJiYgKCB4bWwgfHwgY29udGV4dCAhPT0gb3V0ZXJtb3N0Q29udGV4dCApICkgfHwgKFxuXHRcdFx0XHQoY2hlY2tDb250ZXh0ID0gY29udGV4dCkubm9kZVR5cGUgP1xuXHRcdFx0XHRcdG1hdGNoQ29udGV4dCggZWxlbSwgY29udGV4dCwgeG1sICkgOlxuXHRcdFx0XHRcdG1hdGNoQW55Q29udGV4dCggZWxlbSwgY29udGV4dCwgeG1sICkgKTtcblx0XHRcdC8vIEF2b2lkIGhhbmdpbmcgb250byBlbGVtZW50IChpc3N1ZSAjMjk5KVxuXHRcdFx0Y2hlY2tDb250ZXh0ID0gbnVsbDtcblx0XHRcdHJldHVybiByZXQ7XG5cdFx0fSBdO1xuXG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdGlmICggKG1hdGNoZXIgPSBFeHByLnJlbGF0aXZlWyB0b2tlbnNbaV0udHlwZSBdKSApIHtcblx0XHRcdG1hdGNoZXJzID0gWyBhZGRDb21iaW5hdG9yKGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApLCBtYXRjaGVyKSBdO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRtYXRjaGVyID0gRXhwci5maWx0ZXJbIHRva2Vuc1tpXS50eXBlIF0uYXBwbHkoIG51bGwsIHRva2Vuc1tpXS5tYXRjaGVzICk7XG5cblx0XHRcdC8vIFJldHVybiBzcGVjaWFsIHVwb24gc2VlaW5nIGEgcG9zaXRpb25hbCBtYXRjaGVyXG5cdFx0XHRpZiAoIG1hdGNoZXJbIGV4cGFuZG8gXSApIHtcblx0XHRcdFx0Ly8gRmluZCB0aGUgbmV4dCByZWxhdGl2ZSBvcGVyYXRvciAoaWYgYW55KSBmb3IgcHJvcGVyIGhhbmRsaW5nXG5cdFx0XHRcdGogPSArK2k7XG5cdFx0XHRcdGZvciAoIDsgaiA8IGxlbjsgaisrICkge1xuXHRcdFx0XHRcdGlmICggRXhwci5yZWxhdGl2ZVsgdG9rZW5zW2pdLnR5cGUgXSApIHtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gc2V0TWF0Y2hlcihcblx0XHRcdFx0XHRpID4gMSAmJiBlbGVtZW50TWF0Y2hlciggbWF0Y2hlcnMgKSxcblx0XHRcdFx0XHRpID4gMSAmJiB0b1NlbGVjdG9yKFxuXHRcdFx0XHRcdFx0Ly8gSWYgdGhlIHByZWNlZGluZyB0b2tlbiB3YXMgYSBkZXNjZW5kYW50IGNvbWJpbmF0b3IsIGluc2VydCBhbiBpbXBsaWNpdCBhbnktZWxlbWVudCBgKmBcblx0XHRcdFx0XHRcdHRva2Vucy5zbGljZSggMCwgaSAtIDEgKS5jb25jYXQoeyB2YWx1ZTogdG9rZW5zWyBpIC0gMiBdLnR5cGUgPT09IFwiIFwiID8gXCIqXCIgOiBcIlwiIH0pXG5cdFx0XHRcdFx0KS5yZXBsYWNlKCBydHJpbSwgXCIkMVwiICksXG5cdFx0XHRcdFx0bWF0Y2hlcixcblx0XHRcdFx0XHRpIDwgaiAmJiBtYXRjaGVyRnJvbVRva2VucyggdG9rZW5zLnNsaWNlKCBpLCBqICkgKSxcblx0XHRcdFx0XHRqIDwgbGVuICYmIG1hdGNoZXJGcm9tVG9rZW5zKCAodG9rZW5zID0gdG9rZW5zLnNsaWNlKCBqICkpICksXG5cdFx0XHRcdFx0aiA8IGxlbiAmJiB0b1NlbGVjdG9yKCB0b2tlbnMgKVxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdFx0bWF0Y2hlcnMucHVzaCggbWF0Y2hlciApO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBlbGVtZW50TWF0Y2hlciggbWF0Y2hlcnMgKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hlckZyb21Hcm91cE1hdGNoZXJzKCBlbGVtZW50TWF0Y2hlcnMsIHNldE1hdGNoZXJzICkge1xuXHR2YXIgYnlTZXQgPSBzZXRNYXRjaGVycy5sZW5ndGggPiAwLFxuXHRcdGJ5RWxlbWVudCA9IGVsZW1lbnRNYXRjaGVycy5sZW5ndGggPiAwLFxuXHRcdHN1cGVyTWF0Y2hlciA9IGZ1bmN0aW9uKCBzZWVkLCBjb250ZXh0LCB4bWwsIHJlc3VsdHMsIG91dGVybW9zdCApIHtcblx0XHRcdHZhciBlbGVtLCBqLCBtYXRjaGVyLFxuXHRcdFx0XHRtYXRjaGVkQ291bnQgPSAwLFxuXHRcdFx0XHRpID0gXCIwXCIsXG5cdFx0XHRcdHVubWF0Y2hlZCA9IHNlZWQgJiYgW10sXG5cdFx0XHRcdHNldE1hdGNoZWQgPSBbXSxcblx0XHRcdFx0Y29udGV4dEJhY2t1cCA9IG91dGVybW9zdENvbnRleHQsXG5cdFx0XHRcdC8vIFdlIG11c3QgYWx3YXlzIGhhdmUgZWl0aGVyIHNlZWQgZWxlbWVudHMgb3Igb3V0ZXJtb3N0IGNvbnRleHRcblx0XHRcdFx0ZWxlbXMgPSBzZWVkIHx8IGJ5RWxlbWVudCAmJiBFeHByLmZpbmRbXCJUQUdcIl0oIFwiKlwiLCBvdXRlcm1vc3QgKSxcblx0XHRcdFx0Ly8gVXNlIGludGVnZXIgZGlycnVucyBpZmYgdGhpcyBpcyB0aGUgb3V0ZXJtb3N0IG1hdGNoZXJcblx0XHRcdFx0ZGlycnVuc1VuaXF1ZSA9IChkaXJydW5zICs9IGNvbnRleHRCYWNrdXAgPT0gbnVsbCA/IDEgOiBNYXRoLnJhbmRvbSgpIHx8IDAuMSksXG5cdFx0XHRcdGxlbiA9IGVsZW1zLmxlbmd0aDtcblxuXHRcdFx0aWYgKCBvdXRlcm1vc3QgKSB7XG5cdFx0XHRcdG91dGVybW9zdENvbnRleHQgPSBjb250ZXh0ICE9PSBkb2N1bWVudCAmJiBjb250ZXh0O1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBZGQgZWxlbWVudHMgcGFzc2luZyBlbGVtZW50TWF0Y2hlcnMgZGlyZWN0bHkgdG8gcmVzdWx0c1xuXHRcdFx0Ly8gS2VlcCBgaWAgYSBzdHJpbmcgaWYgdGhlcmUgYXJlIG5vIGVsZW1lbnRzIHNvIGBtYXRjaGVkQ291bnRgIHdpbGwgYmUgXCIwMFwiIGJlbG93XG5cdFx0XHQvLyBTdXBwb3J0OiBJRTw5LCBTYWZhcmlcblx0XHRcdC8vIFRvbGVyYXRlIE5vZGVMaXN0IHByb3BlcnRpZXMgKElFOiBcImxlbmd0aFwiOyBTYWZhcmk6IDxudW1iZXI+KSBtYXRjaGluZyBlbGVtZW50cyBieSBpZFxuXHRcdFx0Zm9yICggOyBpICE9PSBsZW4gJiYgKGVsZW0gPSBlbGVtc1tpXSkgIT0gbnVsbDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIGJ5RWxlbWVudCAmJiBlbGVtICkge1xuXHRcdFx0XHRcdGogPSAwO1xuXHRcdFx0XHRcdHdoaWxlICggKG1hdGNoZXIgPSBlbGVtZW50TWF0Y2hlcnNbaisrXSkgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApICkge1xuXHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggb3V0ZXJtb3N0ICkge1xuXHRcdFx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gVHJhY2sgdW5tYXRjaGVkIGVsZW1lbnRzIGZvciBzZXQgZmlsdGVyc1xuXHRcdFx0XHRpZiAoIGJ5U2V0ICkge1xuXHRcdFx0XHRcdC8vIFRoZXkgd2lsbCBoYXZlIGdvbmUgdGhyb3VnaCBhbGwgcG9zc2libGUgbWF0Y2hlcnNcblx0XHRcdFx0XHRpZiAoIChlbGVtID0gIW1hdGNoZXIgJiYgZWxlbSkgKSB7XG5cdFx0XHRcdFx0XHRtYXRjaGVkQ291bnQtLTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBMZW5ndGhlbiB0aGUgYXJyYXkgZm9yIGV2ZXJ5IGVsZW1lbnQsIG1hdGNoZWQgb3Igbm90XG5cdFx0XHRcdFx0aWYgKCBzZWVkICkge1xuXHRcdFx0XHRcdFx0dW5tYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gQXBwbHkgc2V0IGZpbHRlcnMgdG8gdW5tYXRjaGVkIGVsZW1lbnRzXG5cdFx0XHRtYXRjaGVkQ291bnQgKz0gaTtcblx0XHRcdGlmICggYnlTZXQgJiYgaSAhPT0gbWF0Y2hlZENvdW50ICkge1xuXHRcdFx0XHRqID0gMDtcblx0XHRcdFx0d2hpbGUgKCAobWF0Y2hlciA9IHNldE1hdGNoZXJzW2orK10pICkge1xuXHRcdFx0XHRcdG1hdGNoZXIoIHVubWF0Y2hlZCwgc2V0TWF0Y2hlZCwgY29udGV4dCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIHNlZWQgKSB7XG5cdFx0XHRcdFx0Ly8gUmVpbnRlZ3JhdGUgZWxlbWVudCBtYXRjaGVzIHRvIGVsaW1pbmF0ZSB0aGUgbmVlZCBmb3Igc29ydGluZ1xuXHRcdFx0XHRcdGlmICggbWF0Y2hlZENvdW50ID4gMCApIHtcblx0XHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0XHRpZiAoICEodW5tYXRjaGVkW2ldIHx8IHNldE1hdGNoZWRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHRcdHNldE1hdGNoZWRbaV0gPSBwb3AuY2FsbCggcmVzdWx0cyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gRGlzY2FyZCBpbmRleCBwbGFjZWhvbGRlciB2YWx1ZXMgdG8gZ2V0IG9ubHkgYWN0dWFsIG1hdGNoZXNcblx0XHRcdFx0XHRzZXRNYXRjaGVkID0gY29uZGVuc2UoIHNldE1hdGNoZWQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFkZCBtYXRjaGVzIHRvIHJlc3VsdHNcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgc2V0TWF0Y2hlZCApO1xuXG5cdFx0XHRcdC8vIFNlZWRsZXNzIHNldCBtYXRjaGVzIHN1Y2NlZWRpbmcgbXVsdGlwbGUgc3VjY2Vzc2Z1bCBtYXRjaGVycyBzdGlwdWxhdGUgc29ydGluZ1xuXHRcdFx0XHRpZiAoIG91dGVybW9zdCAmJiAhc2VlZCAmJiBzZXRNYXRjaGVkLmxlbmd0aCA+IDAgJiZcblx0XHRcdFx0XHQoIG1hdGNoZWRDb3VudCArIHNldE1hdGNoZXJzLmxlbmd0aCApID4gMSApIHtcblxuXHRcdFx0XHRcdFNpenpsZS51bmlxdWVTb3J0KCByZXN1bHRzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gT3ZlcnJpZGUgbWFuaXB1bGF0aW9uIG9mIGdsb2JhbHMgYnkgbmVzdGVkIG1hdGNoZXJzXG5cdFx0XHRpZiAoIG91dGVybW9zdCApIHtcblx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdG91dGVybW9zdENvbnRleHQgPSBjb250ZXh0QmFja3VwO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdW5tYXRjaGVkO1xuXHRcdH07XG5cblx0cmV0dXJuIGJ5U2V0ID9cblx0XHRtYXJrRnVuY3Rpb24oIHN1cGVyTWF0Y2hlciApIDpcblx0XHRzdXBlck1hdGNoZXI7XG59XG5cbmNvbXBpbGUgPSBTaXp6bGUuY29tcGlsZSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgbWF0Y2ggLyogSW50ZXJuYWwgVXNlIE9ubHkgKi8gKSB7XG5cdHZhciBpLFxuXHRcdHNldE1hdGNoZXJzID0gW10sXG5cdFx0ZWxlbWVudE1hdGNoZXJzID0gW10sXG5cdFx0Y2FjaGVkID0gY29tcGlsZXJDYWNoZVsgc2VsZWN0b3IgKyBcIiBcIiBdO1xuXG5cdGlmICggIWNhY2hlZCApIHtcblx0XHQvLyBHZW5lcmF0ZSBhIGZ1bmN0aW9uIG9mIHJlY3Vyc2l2ZSBmdW5jdGlvbnMgdGhhdCBjYW4gYmUgdXNlZCB0byBjaGVjayBlYWNoIGVsZW1lbnRcblx0XHRpZiAoICFtYXRjaCApIHtcblx0XHRcdG1hdGNoID0gdG9rZW5pemUoIHNlbGVjdG9yICk7XG5cdFx0fVxuXHRcdGkgPSBtYXRjaC5sZW5ndGg7XG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRjYWNoZWQgPSBtYXRjaGVyRnJvbVRva2VucyggbWF0Y2hbaV0gKTtcblx0XHRcdGlmICggY2FjaGVkWyBleHBhbmRvIF0gKSB7XG5cdFx0XHRcdHNldE1hdGNoZXJzLnB1c2goIGNhY2hlZCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZWxlbWVudE1hdGNoZXJzLnB1c2goIGNhY2hlZCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIENhY2hlIHRoZSBjb21waWxlZCBmdW5jdGlvblxuXHRcdGNhY2hlZCA9IGNvbXBpbGVyQ2FjaGUoIHNlbGVjdG9yLCBtYXRjaGVyRnJvbUdyb3VwTWF0Y2hlcnMoIGVsZW1lbnRNYXRjaGVycywgc2V0TWF0Y2hlcnMgKSApO1xuXG5cdFx0Ly8gU2F2ZSBzZWxlY3RvciBhbmQgdG9rZW5pemF0aW9uXG5cdFx0Y2FjaGVkLnNlbGVjdG9yID0gc2VsZWN0b3I7XG5cdH1cblx0cmV0dXJuIGNhY2hlZDtcbn07XG5cbi8qKlxuICogQSBsb3ctbGV2ZWwgc2VsZWN0aW9uIGZ1bmN0aW9uIHRoYXQgd29ya3Mgd2l0aCBTaXp6bGUncyBjb21waWxlZFxuICogIHNlbGVjdG9yIGZ1bmN0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IHNlbGVjdG9yIEEgc2VsZWN0b3Igb3IgYSBwcmUtY29tcGlsZWRcbiAqICBzZWxlY3RvciBmdW5jdGlvbiBidWlsdCB3aXRoIFNpenpsZS5jb21waWxlXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGNvbnRleHRcbiAqIEBwYXJhbSB7QXJyYXl9IFtyZXN1bHRzXVxuICogQHBhcmFtIHtBcnJheX0gW3NlZWRdIEEgc2V0IG9mIGVsZW1lbnRzIHRvIG1hdGNoIGFnYWluc3RcbiAqL1xuc2VsZWN0ID0gU2l6emxlLnNlbGVjdCA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApIHtcblx0dmFyIGksIHRva2VucywgdG9rZW4sIHR5cGUsIGZpbmQsXG5cdFx0Y29tcGlsZWQgPSB0eXBlb2Ygc2VsZWN0b3IgPT09IFwiZnVuY3Rpb25cIiAmJiBzZWxlY3Rvcixcblx0XHRtYXRjaCA9ICFzZWVkICYmIHRva2VuaXplKCAoc2VsZWN0b3IgPSBjb21waWxlZC5zZWxlY3RvciB8fCBzZWxlY3RvcikgKTtcblxuXHRyZXN1bHRzID0gcmVzdWx0cyB8fCBbXTtcblxuXHQvLyBUcnkgdG8gbWluaW1pemUgb3BlcmF0aW9ucyBpZiB0aGVyZSBpcyBubyBzZWVkIGFuZCBvbmx5IG9uZSBncm91cFxuXHRpZiAoIG1hdGNoLmxlbmd0aCA9PT0gMSApIHtcblxuXHRcdC8vIFRha2UgYSBzaG9ydGN1dCBhbmQgc2V0IHRoZSBjb250ZXh0IGlmIHRoZSByb290IHNlbGVjdG9yIGlzIGFuIElEXG5cdFx0dG9rZW5zID0gbWF0Y2hbMF0gPSBtYXRjaFswXS5zbGljZSggMCApO1xuXHRcdGlmICggdG9rZW5zLmxlbmd0aCA+IDIgJiYgKHRva2VuID0gdG9rZW5zWzBdKS50eXBlID09PSBcIklEXCIgJiZcblx0XHRcdFx0c3VwcG9ydC5nZXRCeUlkICYmIGNvbnRleHQubm9kZVR5cGUgPT09IDkgJiYgZG9jdW1lbnRJc0hUTUwgJiZcblx0XHRcdFx0RXhwci5yZWxhdGl2ZVsgdG9rZW5zWzFdLnR5cGUgXSApIHtcblxuXHRcdFx0Y29udGV4dCA9ICggRXhwci5maW5kW1wiSURcIl0oIHRva2VuLm1hdGNoZXNbMF0ucmVwbGFjZShydW5lc2NhcGUsIGZ1bmVzY2FwZSksIGNvbnRleHQgKSB8fCBbXSApWzBdO1xuXHRcdFx0aWYgKCAhY29udGV4dCApIHtcblx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cblx0XHRcdC8vIFByZWNvbXBpbGVkIG1hdGNoZXJzIHdpbGwgc3RpbGwgdmVyaWZ5IGFuY2VzdHJ5LCBzbyBzdGVwIHVwIGEgbGV2ZWxcblx0XHRcdH0gZWxzZSBpZiAoIGNvbXBpbGVkICkge1xuXHRcdFx0XHRjb250ZXh0ID0gY29udGV4dC5wYXJlbnROb2RlO1xuXHRcdFx0fVxuXG5cdFx0XHRzZWxlY3RvciA9IHNlbGVjdG9yLnNsaWNlKCB0b2tlbnMuc2hpZnQoKS52YWx1ZS5sZW5ndGggKTtcblx0XHR9XG5cblx0XHQvLyBGZXRjaCBhIHNlZWQgc2V0IGZvciByaWdodC10by1sZWZ0IG1hdGNoaW5nXG5cdFx0aSA9IG1hdGNoRXhwcltcIm5lZWRzQ29udGV4dFwiXS50ZXN0KCBzZWxlY3RvciApID8gMCA6IHRva2Vucy5sZW5ndGg7XG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHR0b2tlbiA9IHRva2Vuc1tpXTtcblxuXHRcdFx0Ly8gQWJvcnQgaWYgd2UgaGl0IGEgY29tYmluYXRvclxuXHRcdFx0aWYgKCBFeHByLnJlbGF0aXZlWyAodHlwZSA9IHRva2VuLnR5cGUpIF0gKSB7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCAoZmluZCA9IEV4cHIuZmluZFsgdHlwZSBdKSApIHtcblx0XHRcdFx0Ly8gU2VhcmNoLCBleHBhbmRpbmcgY29udGV4dCBmb3IgbGVhZGluZyBzaWJsaW5nIGNvbWJpbmF0b3JzXG5cdFx0XHRcdGlmICggKHNlZWQgPSBmaW5kKFxuXHRcdFx0XHRcdHRva2VuLm1hdGNoZXNbMF0ucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKSxcblx0XHRcdFx0XHRyc2libGluZy50ZXN0KCB0b2tlbnNbMF0udHlwZSApICYmIHRlc3RDb250ZXh0KCBjb250ZXh0LnBhcmVudE5vZGUgKSB8fCBjb250ZXh0XG5cdFx0XHRcdCkpICkge1xuXG5cdFx0XHRcdFx0Ly8gSWYgc2VlZCBpcyBlbXB0eSBvciBubyB0b2tlbnMgcmVtYWluLCB3ZSBjYW4gcmV0dXJuIGVhcmx5XG5cdFx0XHRcdFx0dG9rZW5zLnNwbGljZSggaSwgMSApO1xuXHRcdFx0XHRcdHNlbGVjdG9yID0gc2VlZC5sZW5ndGggJiYgdG9TZWxlY3RvciggdG9rZW5zICk7XG5cdFx0XHRcdFx0aWYgKCAhc2VsZWN0b3IgKSB7XG5cdFx0XHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBzZWVkICk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIENvbXBpbGUgYW5kIGV4ZWN1dGUgYSBmaWx0ZXJpbmcgZnVuY3Rpb24gaWYgb25lIGlzIG5vdCBwcm92aWRlZFxuXHQvLyBQcm92aWRlIGBtYXRjaGAgdG8gYXZvaWQgcmV0b2tlbml6YXRpb24gaWYgd2UgbW9kaWZpZWQgdGhlIHNlbGVjdG9yIGFib3ZlXG5cdCggY29tcGlsZWQgfHwgY29tcGlsZSggc2VsZWN0b3IsIG1hdGNoICkgKShcblx0XHRzZWVkLFxuXHRcdGNvbnRleHQsXG5cdFx0IWRvY3VtZW50SXNIVE1MLFxuXHRcdHJlc3VsdHMsXG5cdFx0cnNpYmxpbmcudGVzdCggc2VsZWN0b3IgKSAmJiB0ZXN0Q29udGV4dCggY29udGV4dC5wYXJlbnROb2RlICkgfHwgY29udGV4dFxuXHQpO1xuXHRyZXR1cm4gcmVzdWx0cztcbn07XG5cbi8vIE9uZS10aW1lIGFzc2lnbm1lbnRzXG5cbi8vIFNvcnQgc3RhYmlsaXR5XG5zdXBwb3J0LnNvcnRTdGFibGUgPSBleHBhbmRvLnNwbGl0KFwiXCIpLnNvcnQoIHNvcnRPcmRlciApLmpvaW4oXCJcIikgPT09IGV4cGFuZG87XG5cbi8vIFN1cHBvcnQ6IENocm9tZSAxNC0zNStcbi8vIEFsd2F5cyBhc3N1bWUgZHVwbGljYXRlcyBpZiB0aGV5IGFyZW4ndCBwYXNzZWQgdG8gdGhlIGNvbXBhcmlzb24gZnVuY3Rpb25cbnN1cHBvcnQuZGV0ZWN0RHVwbGljYXRlcyA9ICEhaGFzRHVwbGljYXRlO1xuXG4vLyBJbml0aWFsaXplIGFnYWluc3QgdGhlIGRlZmF1bHQgZG9jdW1lbnRcbnNldERvY3VtZW50KCk7XG5cbi8vIFN1cHBvcnQ6IFdlYmtpdDw1MzcuMzIgLSBTYWZhcmkgNi4wLjMvQ2hyb21lIDI1IChmaXhlZCBpbiBDaHJvbWUgMjcpXG4vLyBEZXRhY2hlZCBub2RlcyBjb25mb3VuZGluZ2x5IGZvbGxvdyAqZWFjaCBvdGhlcipcbnN1cHBvcnQuc29ydERldGFjaGVkID0gYXNzZXJ0KGZ1bmN0aW9uKCBkaXYxICkge1xuXHQvLyBTaG91bGQgcmV0dXJuIDEsIGJ1dCByZXR1cm5zIDQgKGZvbGxvd2luZylcblx0cmV0dXJuIGRpdjEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIikgKSAmIDE7XG59KTtcblxuLy8gU3VwcG9ydDogSUU8OFxuLy8gUHJldmVudCBhdHRyaWJ1dGUvcHJvcGVydHkgXCJpbnRlcnBvbGF0aW9uXCJcbi8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNjQyOSUyOFZTLjg1JTI5LmFzcHhcbmlmICggIWFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRkaXYuaW5uZXJIVE1MID0gXCI8YSBocmVmPScjJz48L2E+XCI7XG5cdHJldHVybiBkaXYuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoXCJocmVmXCIpID09PSBcIiNcIiA7XG59KSApIHtcblx0YWRkSGFuZGxlKCBcInR5cGV8aHJlZnxoZWlnaHR8d2lkdGhcIiwgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdGlmICggIWlzWE1MICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lLCBuYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwidHlwZVwiID8gMSA6IDIgKTtcblx0XHR9XG5cdH0pO1xufVxuXG4vLyBTdXBwb3J0OiBJRTw5XG4vLyBVc2UgZGVmYXVsdFZhbHVlIGluIHBsYWNlIG9mIGdldEF0dHJpYnV0ZShcInZhbHVlXCIpXG5pZiAoICFzdXBwb3J0LmF0dHJpYnV0ZXMgfHwgIWFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRkaXYuaW5uZXJIVE1MID0gXCI8aW5wdXQvPlwiO1xuXHRkaXYuZmlyc3RDaGlsZC5zZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiwgXCJcIiApO1xuXHRyZXR1cm4gZGl2LmZpcnN0Q2hpbGQuZ2V0QXR0cmlidXRlKCBcInZhbHVlXCIgKSA9PT0gXCJcIjtcbn0pICkge1xuXHRhZGRIYW5kbGUoIFwidmFsdWVcIiwgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdGlmICggIWlzWE1MICYmIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gXCJpbnB1dFwiICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGVmYXVsdFZhbHVlO1xuXHRcdH1cblx0fSk7XG59XG5cbi8vIFN1cHBvcnQ6IElFPDlcbi8vIFVzZSBnZXRBdHRyaWJ1dGVOb2RlIHRvIGZldGNoIGJvb2xlYW5zIHdoZW4gZ2V0QXR0cmlidXRlIGxpZXNcbmlmICggIWFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRyZXR1cm4gZGl2LmdldEF0dHJpYnV0ZShcImRpc2FibGVkXCIpID09IG51bGw7XG59KSApIHtcblx0YWRkSGFuZGxlKCBib29sZWFucywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdHZhciB2YWw7XG5cdFx0aWYgKCAhaXNYTUwgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbVsgbmFtZSBdID09PSB0cnVlID8gbmFtZS50b0xvd2VyQ2FzZSgpIDpcblx0XHRcdFx0XHQodmFsID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKCBuYW1lICkpICYmIHZhbC5zcGVjaWZpZWQgP1xuXHRcdFx0XHRcdHZhbC52YWx1ZSA6XG5cdFx0XHRcdG51bGw7XG5cdFx0fVxuXHR9KTtcbn1cblxucmV0dXJuIFNpenpsZTtcblxufSkoIHdpbmRvdyApO1xuXG5cblxualF1ZXJ5LmZpbmQgPSBTaXp6bGU7XG5qUXVlcnkuZXhwciA9IFNpenpsZS5zZWxlY3RvcnM7XG5qUXVlcnkuZXhwcltcIjpcIl0gPSBqUXVlcnkuZXhwci5wc2V1ZG9zO1xualF1ZXJ5LnVuaXF1ZSA9IFNpenpsZS51bmlxdWVTb3J0O1xualF1ZXJ5LnRleHQgPSBTaXp6bGUuZ2V0VGV4dDtcbmpRdWVyeS5pc1hNTERvYyA9IFNpenpsZS5pc1hNTDtcbmpRdWVyeS5jb250YWlucyA9IFNpenpsZS5jb250YWlucztcblxuXG5cbnZhciBybmVlZHNDb250ZXh0ID0galF1ZXJ5LmV4cHIubWF0Y2gubmVlZHNDb250ZXh0O1xuXG52YXIgcnNpbmdsZVRhZyA9ICgvXjwoXFx3KylcXHMqXFwvPz4oPzo8XFwvXFwxPnwpJC8pO1xuXG5cblxudmFyIHJpc1NpbXBsZSA9IC9eLlteOiNcXFtcXC4sXSokLztcblxuLy8gSW1wbGVtZW50IHRoZSBpZGVudGljYWwgZnVuY3Rpb25hbGl0eSBmb3IgZmlsdGVyIGFuZCBub3RcbmZ1bmN0aW9uIHdpbm5vdyggZWxlbWVudHMsIHF1YWxpZmllciwgbm90ICkge1xuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBxdWFsaWZpZXIgKSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSwgaSApIHtcblx0XHRcdC8qIGpzaGludCAtVzAxOCAqL1xuXHRcdFx0cmV0dXJuICEhcXVhbGlmaWVyLmNhbGwoIGVsZW0sIGksIGVsZW0gKSAhPT0gbm90O1xuXHRcdH0pO1xuXG5cdH1cblxuXHRpZiAoIHF1YWxpZmllci5ub2RlVHlwZSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiAoIGVsZW0gPT09IHF1YWxpZmllciApICE9PSBub3Q7XG5cdFx0fSk7XG5cblx0fVxuXG5cdGlmICggdHlwZW9mIHF1YWxpZmllciA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRpZiAoIHJpc1NpbXBsZS50ZXN0KCBxdWFsaWZpZXIgKSApIHtcblx0XHRcdHJldHVybiBqUXVlcnkuZmlsdGVyKCBxdWFsaWZpZXIsIGVsZW1lbnRzLCBub3QgKTtcblx0XHR9XG5cblx0XHRxdWFsaWZpZXIgPSBqUXVlcnkuZmlsdGVyKCBxdWFsaWZpZXIsIGVsZW1lbnRzICk7XG5cdH1cblxuXHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRyZXR1cm4gKCBpbmRleE9mLmNhbGwoIHF1YWxpZmllciwgZWxlbSApID49IDAgKSAhPT0gbm90O1xuXHR9KTtcbn1cblxualF1ZXJ5LmZpbHRlciA9IGZ1bmN0aW9uKCBleHByLCBlbGVtcywgbm90ICkge1xuXHR2YXIgZWxlbSA9IGVsZW1zWyAwIF07XG5cblx0aWYgKCBub3QgKSB7XG5cdFx0ZXhwciA9IFwiOm5vdChcIiArIGV4cHIgKyBcIilcIjtcblx0fVxuXG5cdHJldHVybiBlbGVtcy5sZW5ndGggPT09IDEgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSA/XG5cdFx0alF1ZXJ5LmZpbmQubWF0Y2hlc1NlbGVjdG9yKCBlbGVtLCBleHByICkgPyBbIGVsZW0gXSA6IFtdIDpcblx0XHRqUXVlcnkuZmluZC5tYXRjaGVzKCBleHByLCBqUXVlcnkuZ3JlcCggZWxlbXMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0ubm9kZVR5cGUgPT09IDE7XG5cdFx0fSkpO1xufTtcblxualF1ZXJ5LmZuLmV4dGVuZCh7XG5cdGZpbmQ6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHR2YXIgaSxcblx0XHRcdGxlbiA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0cmV0ID0gW10sXG5cdFx0XHRzZWxmID0gdGhpcztcblxuXHRcdGlmICggdHlwZW9mIHNlbGVjdG9yICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqUXVlcnkoIHNlbGVjdG9yICkuZmlsdGVyKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRmb3IgKCBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHRcdGlmICggalF1ZXJ5LmNvbnRhaW5zKCBzZWxmWyBpIF0sIHRoaXMgKSApIHtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSkgKTtcblx0XHR9XG5cblx0XHRmb3IgKCBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0alF1ZXJ5LmZpbmQoIHNlbGVjdG9yLCBzZWxmWyBpIF0sIHJldCApO1xuXHRcdH1cblxuXHRcdC8vIE5lZWRlZCBiZWNhdXNlICQoIHNlbGVjdG9yLCBjb250ZXh0ICkgYmVjb21lcyAkKCBjb250ZXh0ICkuZmluZCggc2VsZWN0b3IgKVxuXHRcdHJldCA9IHRoaXMucHVzaFN0YWNrKCBsZW4gPiAxID8galF1ZXJ5LnVuaXF1ZSggcmV0ICkgOiByZXQgKTtcblx0XHRyZXQuc2VsZWN0b3IgPSB0aGlzLnNlbGVjdG9yID8gdGhpcy5zZWxlY3RvciArIFwiIFwiICsgc2VsZWN0b3IgOiBzZWxlY3Rvcjtcblx0XHRyZXR1cm4gcmV0O1xuXHR9LFxuXHRmaWx0ZXI6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIHdpbm5vdyh0aGlzLCBzZWxlY3RvciB8fCBbXSwgZmFsc2UpICk7XG5cdH0sXG5cdG5vdDogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggd2lubm93KHRoaXMsIHNlbGVjdG9yIHx8IFtdLCB0cnVlKSApO1xuXHR9LFxuXHRpczogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiAhIXdpbm5vdyhcblx0XHRcdHRoaXMsXG5cblx0XHRcdC8vIElmIHRoaXMgaXMgYSBwb3NpdGlvbmFsL3JlbGF0aXZlIHNlbGVjdG9yLCBjaGVjayBtZW1iZXJzaGlwIGluIHRoZSByZXR1cm5lZCBzZXRcblx0XHRcdC8vIHNvICQoXCJwOmZpcnN0XCIpLmlzKFwicDpsYXN0XCIpIHdvbid0IHJldHVybiB0cnVlIGZvciBhIGRvYyB3aXRoIHR3byBcInBcIi5cblx0XHRcdHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiAmJiBybmVlZHNDb250ZXh0LnRlc3QoIHNlbGVjdG9yICkgP1xuXHRcdFx0XHRqUXVlcnkoIHNlbGVjdG9yICkgOlxuXHRcdFx0XHRzZWxlY3RvciB8fCBbXSxcblx0XHRcdGZhbHNlXG5cdFx0KS5sZW5ndGg7XG5cdH1cbn0pO1xuXG5cbi8vIEluaXRpYWxpemUgYSBqUXVlcnkgb2JqZWN0XG5cblxuLy8gQSBjZW50cmFsIHJlZmVyZW5jZSB0byB0aGUgcm9vdCBqUXVlcnkoZG9jdW1lbnQpXG52YXIgcm9vdGpRdWVyeSxcblxuXHQvLyBBIHNpbXBsZSB3YXkgdG8gY2hlY2sgZm9yIEhUTUwgc3RyaW5nc1xuXHQvLyBQcmlvcml0aXplICNpZCBvdmVyIDx0YWc+IHRvIGF2b2lkIFhTUyB2aWEgbG9jYXRpb24uaGFzaCAoIzk1MjEpXG5cdC8vIFN0cmljdCBIVE1MIHJlY29nbml0aW9uICgjMTEyOTA6IG11c3Qgc3RhcnQgd2l0aCA8KVxuXHRycXVpY2tFeHByID0gL14oPzpcXHMqKDxbXFx3XFxXXSs+KVtePl0qfCMoW1xcdy1dKikpJC8sXG5cblx0aW5pdCA9IGpRdWVyeS5mbi5pbml0ID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBjb250ZXh0ICkge1xuXHRcdHZhciBtYXRjaCwgZWxlbTtcblxuXHRcdC8vIEhBTkRMRTogJChcIlwiKSwgJChudWxsKSwgJCh1bmRlZmluZWQpLCAkKGZhbHNlKVxuXHRcdGlmICggIXNlbGVjdG9yICkge1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0Ly8gSGFuZGxlIEhUTUwgc3RyaW5nc1xuXHRcdGlmICggdHlwZW9mIHNlbGVjdG9yID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0aWYgKCBzZWxlY3RvclswXSA9PT0gXCI8XCIgJiYgc2VsZWN0b3JbIHNlbGVjdG9yLmxlbmd0aCAtIDEgXSA9PT0gXCI+XCIgJiYgc2VsZWN0b3IubGVuZ3RoID49IDMgKSB7XG5cdFx0XHRcdC8vIEFzc3VtZSB0aGF0IHN0cmluZ3MgdGhhdCBzdGFydCBhbmQgZW5kIHdpdGggPD4gYXJlIEhUTUwgYW5kIHNraXAgdGhlIHJlZ2V4IGNoZWNrXG5cdFx0XHRcdG1hdGNoID0gWyBudWxsLCBzZWxlY3RvciwgbnVsbCBdO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRtYXRjaCA9IHJxdWlja0V4cHIuZXhlYyggc2VsZWN0b3IgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTWF0Y2ggaHRtbCBvciBtYWtlIHN1cmUgbm8gY29udGV4dCBpcyBzcGVjaWZpZWQgZm9yICNpZFxuXHRcdFx0aWYgKCBtYXRjaCAmJiAobWF0Y2hbMV0gfHwgIWNvbnRleHQpICkge1xuXG5cdFx0XHRcdC8vIEhBTkRMRTogJChodG1sKSAtPiAkKGFycmF5KVxuXHRcdFx0XHRpZiAoIG1hdGNoWzFdICkge1xuXHRcdFx0XHRcdGNvbnRleHQgPSBjb250ZXh0IGluc3RhbmNlb2YgalF1ZXJ5ID8gY29udGV4dFswXSA6IGNvbnRleHQ7XG5cblx0XHRcdFx0XHQvLyBPcHRpb24gdG8gcnVuIHNjcmlwdHMgaXMgdHJ1ZSBmb3IgYmFjay1jb21wYXRcblx0XHRcdFx0XHQvLyBJbnRlbnRpb25hbGx5IGxldCB0aGUgZXJyb3IgYmUgdGhyb3duIGlmIHBhcnNlSFRNTCBpcyBub3QgcHJlc2VudFxuXHRcdFx0XHRcdGpRdWVyeS5tZXJnZSggdGhpcywgalF1ZXJ5LnBhcnNlSFRNTChcblx0XHRcdFx0XHRcdG1hdGNoWzFdLFxuXHRcdFx0XHRcdFx0Y29udGV4dCAmJiBjb250ZXh0Lm5vZGVUeXBlID8gY29udGV4dC5vd25lckRvY3VtZW50IHx8IGNvbnRleHQgOiBkb2N1bWVudCxcblx0XHRcdFx0XHRcdHRydWVcblx0XHRcdFx0XHQpICk7XG5cblx0XHRcdFx0XHQvLyBIQU5ETEU6ICQoaHRtbCwgcHJvcHMpXG5cdFx0XHRcdFx0aWYgKCByc2luZ2xlVGFnLnRlc3QoIG1hdGNoWzFdICkgJiYgalF1ZXJ5LmlzUGxhaW5PYmplY3QoIGNvbnRleHQgKSApIHtcblx0XHRcdFx0XHRcdGZvciAoIG1hdGNoIGluIGNvbnRleHQgKSB7XG5cdFx0XHRcdFx0XHRcdC8vIFByb3BlcnRpZXMgb2YgY29udGV4dCBhcmUgY2FsbGVkIGFzIG1ldGhvZHMgaWYgcG9zc2libGVcblx0XHRcdFx0XHRcdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdGhpc1sgbWF0Y2ggXSApICkge1xuXHRcdFx0XHRcdFx0XHRcdHRoaXNbIG1hdGNoIF0oIGNvbnRleHRbIG1hdGNoIF0gKTtcblxuXHRcdFx0XHRcdFx0XHQvLyAuLi5hbmQgb3RoZXJ3aXNlIHNldCBhcyBhdHRyaWJ1dGVzXG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5hdHRyKCBtYXRjaCwgY29udGV4dFsgbWF0Y2ggXSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cblx0XHRcdFx0Ly8gSEFORExFOiAkKCNpZClcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRlbGVtID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIG1hdGNoWzJdICk7XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBCbGFja2JlcnJ5IDQuNlxuXHRcdFx0XHRcdC8vIGdFQklEIHJldHVybnMgbm9kZXMgbm8gbG9uZ2VyIGluIHRoZSBkb2N1bWVudCAoIzY5NjMpXG5cdFx0XHRcdFx0aWYgKCBlbGVtICYmIGVsZW0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0XHRcdC8vIEluamVjdCB0aGUgZWxlbWVudCBkaXJlY3RseSBpbnRvIHRoZSBqUXVlcnkgb2JqZWN0XG5cdFx0XHRcdFx0XHR0aGlzLmxlbmd0aCA9IDE7XG5cdFx0XHRcdFx0XHR0aGlzWzBdID0gZWxlbTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR0aGlzLmNvbnRleHQgPSBkb2N1bWVudDtcblx0XHRcdFx0XHR0aGlzLnNlbGVjdG9yID0gc2VsZWN0b3I7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH1cblxuXHRcdFx0Ly8gSEFORExFOiAkKGV4cHIsICQoLi4uKSlcblx0XHRcdH0gZWxzZSBpZiAoICFjb250ZXh0IHx8IGNvbnRleHQuanF1ZXJ5ICkge1xuXHRcdFx0XHRyZXR1cm4gKCBjb250ZXh0IHx8IHJvb3RqUXVlcnkgKS5maW5kKCBzZWxlY3RvciApO1xuXG5cdFx0XHQvLyBIQU5ETEU6ICQoZXhwciwgY29udGV4dClcblx0XHRcdC8vICh3aGljaCBpcyBqdXN0IGVxdWl2YWxlbnQgdG86ICQoY29udGV4dCkuZmluZChleHByKVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuY29uc3RydWN0b3IoIGNvbnRleHQgKS5maW5kKCBzZWxlY3RvciApO1xuXHRcdFx0fVxuXG5cdFx0Ly8gSEFORExFOiAkKERPTUVsZW1lbnQpXG5cdFx0fSBlbHNlIGlmICggc2VsZWN0b3Iubm9kZVR5cGUgKSB7XG5cdFx0XHR0aGlzLmNvbnRleHQgPSB0aGlzWzBdID0gc2VsZWN0b3I7XG5cdFx0XHR0aGlzLmxlbmd0aCA9IDE7XG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdC8vIEhBTkRMRTogJChmdW5jdGlvbilcblx0XHQvLyBTaG9ydGN1dCBmb3IgZG9jdW1lbnQgcmVhZHlcblx0XHR9IGVsc2UgaWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggc2VsZWN0b3IgKSApIHtcblx0XHRcdHJldHVybiB0eXBlb2Ygcm9vdGpRdWVyeS5yZWFkeSAhPT0gXCJ1bmRlZmluZWRcIiA/XG5cdFx0XHRcdHJvb3RqUXVlcnkucmVhZHkoIHNlbGVjdG9yICkgOlxuXHRcdFx0XHQvLyBFeGVjdXRlIGltbWVkaWF0ZWx5IGlmIHJlYWR5IGlzIG5vdCBwcmVzZW50XG5cdFx0XHRcdHNlbGVjdG9yKCBqUXVlcnkgKTtcblx0XHR9XG5cblx0XHRpZiAoIHNlbGVjdG9yLnNlbGVjdG9yICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHR0aGlzLnNlbGVjdG9yID0gc2VsZWN0b3Iuc2VsZWN0b3I7XG5cdFx0XHR0aGlzLmNvbnRleHQgPSBzZWxlY3Rvci5jb250ZXh0O1xuXHRcdH1cblxuXHRcdHJldHVybiBqUXVlcnkubWFrZUFycmF5KCBzZWxlY3RvciwgdGhpcyApO1xuXHR9O1xuXG4vLyBHaXZlIHRoZSBpbml0IGZ1bmN0aW9uIHRoZSBqUXVlcnkgcHJvdG90eXBlIGZvciBsYXRlciBpbnN0YW50aWF0aW9uXG5pbml0LnByb3RvdHlwZSA9IGpRdWVyeS5mbjtcblxuLy8gSW5pdGlhbGl6ZSBjZW50cmFsIHJlZmVyZW5jZVxucm9vdGpRdWVyeSA9IGpRdWVyeSggZG9jdW1lbnQgKTtcblxuXG52YXIgcnBhcmVudHNwcmV2ID0gL14oPzpwYXJlbnRzfHByZXYoPzpVbnRpbHxBbGwpKS8sXG5cdC8vIE1ldGhvZHMgZ3VhcmFudGVlZCB0byBwcm9kdWNlIGEgdW5pcXVlIHNldCB3aGVuIHN0YXJ0aW5nIGZyb20gYSB1bmlxdWUgc2V0XG5cdGd1YXJhbnRlZWRVbmlxdWUgPSB7XG5cdFx0Y2hpbGRyZW46IHRydWUsXG5cdFx0Y29udGVudHM6IHRydWUsXG5cdFx0bmV4dDogdHJ1ZSxcblx0XHRwcmV2OiB0cnVlXG5cdH07XG5cbmpRdWVyeS5leHRlbmQoe1xuXHRkaXI6IGZ1bmN0aW9uKCBlbGVtLCBkaXIsIHVudGlsICkge1xuXHRcdHZhciBtYXRjaGVkID0gW10sXG5cdFx0XHR0cnVuY2F0ZSA9IHVudGlsICE9PSB1bmRlZmluZWQ7XG5cblx0XHR3aGlsZSAoIChlbGVtID0gZWxlbVsgZGlyIF0pICYmIGVsZW0ubm9kZVR5cGUgIT09IDkgKSB7XG5cdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdGlmICggdHJ1bmNhdGUgJiYgalF1ZXJ5KCBlbGVtICkuaXMoIHVudGlsICkgKSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdFx0bWF0Y2hlZC5wdXNoKCBlbGVtICk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBtYXRjaGVkO1xuXHR9LFxuXG5cdHNpYmxpbmc6IGZ1bmN0aW9uKCBuLCBlbGVtICkge1xuXHRcdHZhciBtYXRjaGVkID0gW107XG5cblx0XHRmb3IgKCA7IG47IG4gPSBuLm5leHRTaWJsaW5nICkge1xuXHRcdFx0aWYgKCBuLm5vZGVUeXBlID09PSAxICYmIG4gIT09IGVsZW0gKSB7XG5cdFx0XHRcdG1hdGNoZWQucHVzaCggbiApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBtYXRjaGVkO1xuXHR9XG59KTtcblxualF1ZXJ5LmZuLmV4dGVuZCh7XG5cdGhhczogZnVuY3Rpb24oIHRhcmdldCApIHtcblx0XHR2YXIgdGFyZ2V0cyA9IGpRdWVyeSggdGFyZ2V0LCB0aGlzICksXG5cdFx0XHRsID0gdGFyZ2V0cy5sZW5ndGg7XG5cblx0XHRyZXR1cm4gdGhpcy5maWx0ZXIoZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgaSA9IDA7XG5cdFx0XHRmb3IgKCA7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdGlmICggalF1ZXJ5LmNvbnRhaW5zKCB0aGlzLCB0YXJnZXRzW2ldICkgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fSxcblxuXHRjbG9zZXN0OiBmdW5jdGlvbiggc2VsZWN0b3JzLCBjb250ZXh0ICkge1xuXHRcdHZhciBjdXIsXG5cdFx0XHRpID0gMCxcblx0XHRcdGwgPSB0aGlzLmxlbmd0aCxcblx0XHRcdG1hdGNoZWQgPSBbXSxcblx0XHRcdHBvcyA9IHJuZWVkc0NvbnRleHQudGVzdCggc2VsZWN0b3JzICkgfHwgdHlwZW9mIHNlbGVjdG9ycyAhPT0gXCJzdHJpbmdcIiA/XG5cdFx0XHRcdGpRdWVyeSggc2VsZWN0b3JzLCBjb250ZXh0IHx8IHRoaXMuY29udGV4dCApIDpcblx0XHRcdFx0MDtcblxuXHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdGZvciAoIGN1ciA9IHRoaXNbaV07IGN1ciAmJiBjdXIgIT09IGNvbnRleHQ7IGN1ciA9IGN1ci5wYXJlbnROb2RlICkge1xuXHRcdFx0XHQvLyBBbHdheXMgc2tpcCBkb2N1bWVudCBmcmFnbWVudHNcblx0XHRcdFx0aWYgKCBjdXIubm9kZVR5cGUgPCAxMSAmJiAocG9zID9cblx0XHRcdFx0XHRwb3MuaW5kZXgoY3VyKSA+IC0xIDpcblxuXHRcdFx0XHRcdC8vIERvbid0IHBhc3Mgbm9uLWVsZW1lbnRzIHRvIFNpenpsZVxuXHRcdFx0XHRcdGN1ci5ub2RlVHlwZSA9PT0gMSAmJlxuXHRcdFx0XHRcdFx0alF1ZXJ5LmZpbmQubWF0Y2hlc1NlbGVjdG9yKGN1ciwgc2VsZWN0b3JzKSkgKSB7XG5cblx0XHRcdFx0XHRtYXRjaGVkLnB1c2goIGN1ciApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBtYXRjaGVkLmxlbmd0aCA+IDEgPyBqUXVlcnkudW5pcXVlKCBtYXRjaGVkICkgOiBtYXRjaGVkICk7XG5cdH0sXG5cblx0Ly8gRGV0ZXJtaW5lIHRoZSBwb3NpdGlvbiBvZiBhbiBlbGVtZW50IHdpdGhpbiB0aGUgc2V0XG5cdGluZGV4OiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdC8vIE5vIGFyZ3VtZW50LCByZXR1cm4gaW5kZXggaW4gcGFyZW50XG5cdFx0aWYgKCAhZWxlbSApIHtcblx0XHRcdHJldHVybiAoIHRoaXNbIDAgXSAmJiB0aGlzWyAwIF0ucGFyZW50Tm9kZSApID8gdGhpcy5maXJzdCgpLnByZXZBbGwoKS5sZW5ndGggOiAtMTtcblx0XHR9XG5cblx0XHQvLyBJbmRleCBpbiBzZWxlY3RvclxuXHRcdGlmICggdHlwZW9mIGVsZW0gPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRyZXR1cm4gaW5kZXhPZi5jYWxsKCBqUXVlcnkoIGVsZW0gKSwgdGhpc1sgMCBdICk7XG5cdFx0fVxuXG5cdFx0Ly8gTG9jYXRlIHRoZSBwb3NpdGlvbiBvZiB0aGUgZGVzaXJlZCBlbGVtZW50XG5cdFx0cmV0dXJuIGluZGV4T2YuY2FsbCggdGhpcyxcblxuXHRcdFx0Ly8gSWYgaXQgcmVjZWl2ZXMgYSBqUXVlcnkgb2JqZWN0LCB0aGUgZmlyc3QgZWxlbWVudCBpcyB1c2VkXG5cdFx0XHRlbGVtLmpxdWVyeSA/IGVsZW1bIDAgXSA6IGVsZW1cblx0XHQpO1xuXHR9LFxuXG5cdGFkZDogZnVuY3Rpb24oIHNlbGVjdG9yLCBjb250ZXh0ICkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayhcblx0XHRcdGpRdWVyeS51bmlxdWUoXG5cdFx0XHRcdGpRdWVyeS5tZXJnZSggdGhpcy5nZXQoKSwgalF1ZXJ5KCBzZWxlY3RvciwgY29udGV4dCApIClcblx0XHRcdClcblx0XHQpO1xuXHR9LFxuXG5cdGFkZEJhY2s6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHRyZXR1cm4gdGhpcy5hZGQoIHNlbGVjdG9yID09IG51bGwgP1xuXHRcdFx0dGhpcy5wcmV2T2JqZWN0IDogdGhpcy5wcmV2T2JqZWN0LmZpbHRlcihzZWxlY3Rvcilcblx0XHQpO1xuXHR9XG59KTtcblxuZnVuY3Rpb24gc2libGluZyggY3VyLCBkaXIgKSB7XG5cdHdoaWxlICggKGN1ciA9IGN1cltkaXJdKSAmJiBjdXIubm9kZVR5cGUgIT09IDEgKSB7fVxuXHRyZXR1cm4gY3VyO1xufVxuXG5qUXVlcnkuZWFjaCh7XG5cdHBhcmVudDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0dmFyIHBhcmVudCA9IGVsZW0ucGFyZW50Tm9kZTtcblx0XHRyZXR1cm4gcGFyZW50ICYmIHBhcmVudC5ub2RlVHlwZSAhPT0gMTEgPyBwYXJlbnQgOiBudWxsO1xuXHR9LFxuXHRwYXJlbnRzOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmRpciggZWxlbSwgXCJwYXJlbnROb2RlXCIgKTtcblx0fSxcblx0cGFyZW50c1VudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5kaXIoIGVsZW0sIFwicGFyZW50Tm9kZVwiLCB1bnRpbCApO1xuXHR9LFxuXHRuZXh0OiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRyZXR1cm4gc2libGluZyggZWxlbSwgXCJuZXh0U2libGluZ1wiICk7XG5cdH0sXG5cdHByZXY6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBzaWJsaW5nKCBlbGVtLCBcInByZXZpb3VzU2libGluZ1wiICk7XG5cdH0sXG5cdG5leHRBbGw6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBqUXVlcnkuZGlyKCBlbGVtLCBcIm5leHRTaWJsaW5nXCIgKTtcblx0fSxcblx0cHJldkFsbDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5kaXIoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIgKTtcblx0fSxcblx0bmV4dFVudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5kaXIoIGVsZW0sIFwibmV4dFNpYmxpbmdcIiwgdW50aWwgKTtcblx0fSxcblx0cHJldlVudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5kaXIoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIsIHVudGlsICk7XG5cdH0sXG5cdHNpYmxpbmdzOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LnNpYmxpbmcoICggZWxlbS5wYXJlbnROb2RlIHx8IHt9ICkuZmlyc3RDaGlsZCwgZWxlbSApO1xuXHR9LFxuXHRjaGlsZHJlbjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5zaWJsaW5nKCBlbGVtLmZpcnN0Q2hpbGQgKTtcblx0fSxcblx0Y29udGVudHM6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBlbGVtLmNvbnRlbnREb2N1bWVudCB8fCBqUXVlcnkubWVyZ2UoIFtdLCBlbGVtLmNoaWxkTm9kZXMgKTtcblx0fVxufSwgZnVuY3Rpb24oIG5hbWUsIGZuICkge1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCB1bnRpbCwgc2VsZWN0b3IgKSB7XG5cdFx0dmFyIG1hdGNoZWQgPSBqUXVlcnkubWFwKCB0aGlzLCBmbiwgdW50aWwgKTtcblxuXHRcdGlmICggbmFtZS5zbGljZSggLTUgKSAhPT0gXCJVbnRpbFwiICkge1xuXHRcdFx0c2VsZWN0b3IgPSB1bnRpbDtcblx0XHR9XG5cblx0XHRpZiAoIHNlbGVjdG9yICYmIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdG1hdGNoZWQgPSBqUXVlcnkuZmlsdGVyKCBzZWxlY3RvciwgbWF0Y2hlZCApO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5sZW5ndGggPiAxICkge1xuXHRcdFx0Ly8gUmVtb3ZlIGR1cGxpY2F0ZXNcblx0XHRcdGlmICggIWd1YXJhbnRlZWRVbmlxdWVbIG5hbWUgXSApIHtcblx0XHRcdFx0alF1ZXJ5LnVuaXF1ZSggbWF0Y2hlZCApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZXZlcnNlIG9yZGVyIGZvciBwYXJlbnRzKiBhbmQgcHJldi1kZXJpdmF0aXZlc1xuXHRcdFx0aWYgKCBycGFyZW50c3ByZXYudGVzdCggbmFtZSApICkge1xuXHRcdFx0XHRtYXRjaGVkLnJldmVyc2UoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIG1hdGNoZWQgKTtcblx0fTtcbn0pO1xudmFyIHJub3R3aGl0ZSA9ICgvXFxTKy9nKTtcblxuXG5cbi8vIFN0cmluZyB0byBPYmplY3Qgb3B0aW9ucyBmb3JtYXQgY2FjaGVcbnZhciBvcHRpb25zQ2FjaGUgPSB7fTtcblxuLy8gQ29udmVydCBTdHJpbmctZm9ybWF0dGVkIG9wdGlvbnMgaW50byBPYmplY3QtZm9ybWF0dGVkIG9uZXMgYW5kIHN0b3JlIGluIGNhY2hlXG5mdW5jdGlvbiBjcmVhdGVPcHRpb25zKCBvcHRpb25zICkge1xuXHR2YXIgb2JqZWN0ID0gb3B0aW9uc0NhY2hlWyBvcHRpb25zIF0gPSB7fTtcblx0alF1ZXJ5LmVhY2goIG9wdGlvbnMubWF0Y2goIHJub3R3aGl0ZSApIHx8IFtdLCBmdW5jdGlvbiggXywgZmxhZyApIHtcblx0XHRvYmplY3RbIGZsYWcgXSA9IHRydWU7XG5cdH0pO1xuXHRyZXR1cm4gb2JqZWN0O1xufVxuXG4vKlxuICogQ3JlYXRlIGEgY2FsbGJhY2sgbGlzdCB1c2luZyB0aGUgZm9sbG93aW5nIHBhcmFtZXRlcnM6XG4gKlxuICpcdG9wdGlvbnM6IGFuIG9wdGlvbmFsIGxpc3Qgb2Ygc3BhY2Utc2VwYXJhdGVkIG9wdGlvbnMgdGhhdCB3aWxsIGNoYW5nZSBob3dcbiAqXHRcdFx0dGhlIGNhbGxiYWNrIGxpc3QgYmVoYXZlcyBvciBhIG1vcmUgdHJhZGl0aW9uYWwgb3B0aW9uIG9iamVjdFxuICpcbiAqIEJ5IGRlZmF1bHQgYSBjYWxsYmFjayBsaXN0IHdpbGwgYWN0IGxpa2UgYW4gZXZlbnQgY2FsbGJhY2sgbGlzdCBhbmQgY2FuIGJlXG4gKiBcImZpcmVkXCIgbXVsdGlwbGUgdGltZXMuXG4gKlxuICogUG9zc2libGUgb3B0aW9uczpcbiAqXG4gKlx0b25jZTpcdFx0XHR3aWxsIGVuc3VyZSB0aGUgY2FsbGJhY2sgbGlzdCBjYW4gb25seSBiZSBmaXJlZCBvbmNlIChsaWtlIGEgRGVmZXJyZWQpXG4gKlxuICpcdG1lbW9yeTpcdFx0XHR3aWxsIGtlZXAgdHJhY2sgb2YgcHJldmlvdXMgdmFsdWVzIGFuZCB3aWxsIGNhbGwgYW55IGNhbGxiYWNrIGFkZGVkXG4gKlx0XHRcdFx0XHRhZnRlciB0aGUgbGlzdCBoYXMgYmVlbiBmaXJlZCByaWdodCBhd2F5IHdpdGggdGhlIGxhdGVzdCBcIm1lbW9yaXplZFwiXG4gKlx0XHRcdFx0XHR2YWx1ZXMgKGxpa2UgYSBEZWZlcnJlZClcbiAqXG4gKlx0dW5pcXVlOlx0XHRcdHdpbGwgZW5zdXJlIGEgY2FsbGJhY2sgY2FuIG9ubHkgYmUgYWRkZWQgb25jZSAobm8gZHVwbGljYXRlIGluIHRoZSBsaXN0KVxuICpcbiAqXHRzdG9wT25GYWxzZTpcdGludGVycnVwdCBjYWxsaW5ncyB3aGVuIGEgY2FsbGJhY2sgcmV0dXJucyBmYWxzZVxuICpcbiAqL1xualF1ZXJ5LkNhbGxiYWNrcyA9IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXG5cdC8vIENvbnZlcnQgb3B0aW9ucyBmcm9tIFN0cmluZy1mb3JtYXR0ZWQgdG8gT2JqZWN0LWZvcm1hdHRlZCBpZiBuZWVkZWRcblx0Ly8gKHdlIGNoZWNrIGluIGNhY2hlIGZpcnN0KVxuXHRvcHRpb25zID0gdHlwZW9mIG9wdGlvbnMgPT09IFwic3RyaW5nXCIgP1xuXHRcdCggb3B0aW9uc0NhY2hlWyBvcHRpb25zIF0gfHwgY3JlYXRlT3B0aW9ucyggb3B0aW9ucyApICkgOlxuXHRcdGpRdWVyeS5leHRlbmQoIHt9LCBvcHRpb25zICk7XG5cblx0dmFyIC8vIExhc3QgZmlyZSB2YWx1ZSAoZm9yIG5vbi1mb3JnZXR0YWJsZSBsaXN0cylcblx0XHRtZW1vcnksXG5cdFx0Ly8gRmxhZyB0byBrbm93IGlmIGxpc3Qgd2FzIGFscmVhZHkgZmlyZWRcblx0XHRmaXJlZCxcblx0XHQvLyBGbGFnIHRvIGtub3cgaWYgbGlzdCBpcyBjdXJyZW50bHkgZmlyaW5nXG5cdFx0ZmlyaW5nLFxuXHRcdC8vIEZpcnN0IGNhbGxiYWNrIHRvIGZpcmUgKHVzZWQgaW50ZXJuYWxseSBieSBhZGQgYW5kIGZpcmVXaXRoKVxuXHRcdGZpcmluZ1N0YXJ0LFxuXHRcdC8vIEVuZCBvZiB0aGUgbG9vcCB3aGVuIGZpcmluZ1xuXHRcdGZpcmluZ0xlbmd0aCxcblx0XHQvLyBJbmRleCBvZiBjdXJyZW50bHkgZmlyaW5nIGNhbGxiYWNrIChtb2RpZmllZCBieSByZW1vdmUgaWYgbmVlZGVkKVxuXHRcdGZpcmluZ0luZGV4LFxuXHRcdC8vIEFjdHVhbCBjYWxsYmFjayBsaXN0XG5cdFx0bGlzdCA9IFtdLFxuXHRcdC8vIFN0YWNrIG9mIGZpcmUgY2FsbHMgZm9yIHJlcGVhdGFibGUgbGlzdHNcblx0XHRzdGFjayA9ICFvcHRpb25zLm9uY2UgJiYgW10sXG5cdFx0Ly8gRmlyZSBjYWxsYmFja3Ncblx0XHRmaXJlID0gZnVuY3Rpb24oIGRhdGEgKSB7XG5cdFx0XHRtZW1vcnkgPSBvcHRpb25zLm1lbW9yeSAmJiBkYXRhO1xuXHRcdFx0ZmlyZWQgPSB0cnVlO1xuXHRcdFx0ZmlyaW5nSW5kZXggPSBmaXJpbmdTdGFydCB8fCAwO1xuXHRcdFx0ZmlyaW5nU3RhcnQgPSAwO1xuXHRcdFx0ZmlyaW5nTGVuZ3RoID0gbGlzdC5sZW5ndGg7XG5cdFx0XHRmaXJpbmcgPSB0cnVlO1xuXHRcdFx0Zm9yICggOyBsaXN0ICYmIGZpcmluZ0luZGV4IDwgZmlyaW5nTGVuZ3RoOyBmaXJpbmdJbmRleCsrICkge1xuXHRcdFx0XHRpZiAoIGxpc3RbIGZpcmluZ0luZGV4IF0uYXBwbHkoIGRhdGFbIDAgXSwgZGF0YVsgMSBdICkgPT09IGZhbHNlICYmIG9wdGlvbnMuc3RvcE9uRmFsc2UgKSB7XG5cdFx0XHRcdFx0bWVtb3J5ID0gZmFsc2U7IC8vIFRvIHByZXZlbnQgZnVydGhlciBjYWxscyB1c2luZyBhZGRcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0ZmlyaW5nID0gZmFsc2U7XG5cdFx0XHRpZiAoIGxpc3QgKSB7XG5cdFx0XHRcdGlmICggc3RhY2sgKSB7XG5cdFx0XHRcdFx0aWYgKCBzdGFjay5sZW5ndGggKSB7XG5cdFx0XHRcdFx0XHRmaXJlKCBzdGFjay5zaGlmdCgpICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2UgaWYgKCBtZW1vcnkgKSB7XG5cdFx0XHRcdFx0bGlzdCA9IFtdO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHNlbGYuZGlzYWJsZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSxcblx0XHQvLyBBY3R1YWwgQ2FsbGJhY2tzIG9iamVjdFxuXHRcdHNlbGYgPSB7XG5cdFx0XHQvLyBBZGQgYSBjYWxsYmFjayBvciBhIGNvbGxlY3Rpb24gb2YgY2FsbGJhY2tzIHRvIHRoZSBsaXN0XG5cdFx0XHRhZGQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIGxpc3QgKSB7XG5cdFx0XHRcdFx0Ly8gRmlyc3QsIHdlIHNhdmUgdGhlIGN1cnJlbnQgbGVuZ3RoXG5cdFx0XHRcdFx0dmFyIHN0YXJ0ID0gbGlzdC5sZW5ndGg7XG5cdFx0XHRcdFx0KGZ1bmN0aW9uIGFkZCggYXJncyApIHtcblx0XHRcdFx0XHRcdGpRdWVyeS5lYWNoKCBhcmdzLCBmdW5jdGlvbiggXywgYXJnICkge1xuXHRcdFx0XHRcdFx0XHR2YXIgdHlwZSA9IGpRdWVyeS50eXBlKCBhcmcgKTtcblx0XHRcdFx0XHRcdFx0aWYgKCB0eXBlID09PSBcImZ1bmN0aW9uXCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCAhb3B0aW9ucy51bmlxdWUgfHwgIXNlbGYuaGFzKCBhcmcgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGxpc3QucHVzaCggYXJnICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCBhcmcgJiYgYXJnLmxlbmd0aCAmJiB0eXBlICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIEluc3BlY3QgcmVjdXJzaXZlbHlcblx0XHRcdFx0XHRcdFx0XHRhZGQoIGFyZyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9KSggYXJndW1lbnRzICk7XG5cdFx0XHRcdFx0Ly8gRG8gd2UgbmVlZCB0byBhZGQgdGhlIGNhbGxiYWNrcyB0byB0aGVcblx0XHRcdFx0XHQvLyBjdXJyZW50IGZpcmluZyBiYXRjaD9cblx0XHRcdFx0XHRpZiAoIGZpcmluZyApIHtcblx0XHRcdFx0XHRcdGZpcmluZ0xlbmd0aCA9IGxpc3QubGVuZ3RoO1xuXHRcdFx0XHRcdC8vIFdpdGggbWVtb3J5LCBpZiB3ZSdyZSBub3QgZmlyaW5nIHRoZW5cblx0XHRcdFx0XHQvLyB3ZSBzaG91bGQgY2FsbCByaWdodCBhd2F5XG5cdFx0XHRcdFx0fSBlbHNlIGlmICggbWVtb3J5ICkge1xuXHRcdFx0XHRcdFx0ZmlyaW5nU3RhcnQgPSBzdGFydDtcblx0XHRcdFx0XHRcdGZpcmUoIG1lbW9yeSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cdFx0XHQvLyBSZW1vdmUgYSBjYWxsYmFjayBmcm9tIHRoZSBsaXN0XG5cdFx0XHRyZW1vdmU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIGxpc3QgKSB7XG5cdFx0XHRcdFx0alF1ZXJ5LmVhY2goIGFyZ3VtZW50cywgZnVuY3Rpb24oIF8sIGFyZyApIHtcblx0XHRcdFx0XHRcdHZhciBpbmRleDtcblx0XHRcdFx0XHRcdHdoaWxlICggKCBpbmRleCA9IGpRdWVyeS5pbkFycmF5KCBhcmcsIGxpc3QsIGluZGV4ICkgKSA+IC0xICkge1xuXHRcdFx0XHRcdFx0XHRsaXN0LnNwbGljZSggaW5kZXgsIDEgKTtcblx0XHRcdFx0XHRcdFx0Ly8gSGFuZGxlIGZpcmluZyBpbmRleGVzXG5cdFx0XHRcdFx0XHRcdGlmICggZmlyaW5nICkge1xuXHRcdFx0XHRcdFx0XHRcdGlmICggaW5kZXggPD0gZmlyaW5nTGVuZ3RoICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZmlyaW5nTGVuZ3RoLS07XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGlmICggaW5kZXggPD0gZmlyaW5nSW5kZXggKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRmaXJpbmdJbmRleC0tO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fSxcblx0XHRcdC8vIENoZWNrIGlmIGEgZ2l2ZW4gY2FsbGJhY2sgaXMgaW4gdGhlIGxpc3QuXG5cdFx0XHQvLyBJZiBubyBhcmd1bWVudCBpcyBnaXZlbiwgcmV0dXJuIHdoZXRoZXIgb3Igbm90IGxpc3QgaGFzIGNhbGxiYWNrcyBhdHRhY2hlZC5cblx0XHRcdGhhczogZnVuY3Rpb24oIGZuICkge1xuXHRcdFx0XHRyZXR1cm4gZm4gPyBqUXVlcnkuaW5BcnJheSggZm4sIGxpc3QgKSA+IC0xIDogISEoIGxpc3QgJiYgbGlzdC5sZW5ndGggKTtcblx0XHRcdH0sXG5cdFx0XHQvLyBSZW1vdmUgYWxsIGNhbGxiYWNrcyBmcm9tIHRoZSBsaXN0XG5cdFx0XHRlbXB0eTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGxpc3QgPSBbXTtcblx0XHRcdFx0ZmlyaW5nTGVuZ3RoID0gMDtcblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXHRcdFx0Ly8gSGF2ZSB0aGUgbGlzdCBkbyBub3RoaW5nIGFueW1vcmVcblx0XHRcdGRpc2FibGU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRsaXN0ID0gc3RhY2sgPSBtZW1vcnkgPSB1bmRlZmluZWQ7XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fSxcblx0XHRcdC8vIElzIGl0IGRpc2FibGVkP1xuXHRcdFx0ZGlzYWJsZWQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRyZXR1cm4gIWxpc3Q7XG5cdFx0XHR9LFxuXHRcdFx0Ly8gTG9jayB0aGUgbGlzdCBpbiBpdHMgY3VycmVudCBzdGF0ZVxuXHRcdFx0bG9jazogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHN0YWNrID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRpZiAoICFtZW1vcnkgKSB7XG5cdFx0XHRcdFx0c2VsZi5kaXNhYmxlKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXHRcdFx0Ly8gSXMgaXQgbG9ja2VkP1xuXHRcdFx0bG9ja2VkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuICFzdGFjaztcblx0XHRcdH0sXG5cdFx0XHQvLyBDYWxsIGFsbCBjYWxsYmFja3Mgd2l0aCB0aGUgZ2l2ZW4gY29udGV4dCBhbmQgYXJndW1lbnRzXG5cdFx0XHRmaXJlV2l0aDogZnVuY3Rpb24oIGNvbnRleHQsIGFyZ3MgKSB7XG5cdFx0XHRcdGlmICggbGlzdCAmJiAoICFmaXJlZCB8fCBzdGFjayApICkge1xuXHRcdFx0XHRcdGFyZ3MgPSBhcmdzIHx8IFtdO1xuXHRcdFx0XHRcdGFyZ3MgPSBbIGNvbnRleHQsIGFyZ3Muc2xpY2UgPyBhcmdzLnNsaWNlKCkgOiBhcmdzIF07XG5cdFx0XHRcdFx0aWYgKCBmaXJpbmcgKSB7XG5cdFx0XHRcdFx0XHRzdGFjay5wdXNoKCBhcmdzICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGZpcmUoIGFyZ3MgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXHRcdFx0Ly8gQ2FsbCBhbGwgdGhlIGNhbGxiYWNrcyB3aXRoIHRoZSBnaXZlbiBhcmd1bWVudHNcblx0XHRcdGZpcmU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRzZWxmLmZpcmVXaXRoKCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXHRcdFx0Ly8gVG8ga25vdyBpZiB0aGUgY2FsbGJhY2tzIGhhdmUgYWxyZWFkeSBiZWVuIGNhbGxlZCBhdCBsZWFzdCBvbmNlXG5cdFx0XHRmaXJlZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiAhIWZpcmVkO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0cmV0dXJuIHNlbGY7XG59O1xuXG5cbmpRdWVyeS5leHRlbmQoe1xuXG5cdERlZmVycmVkOiBmdW5jdGlvbiggZnVuYyApIHtcblx0XHR2YXIgdHVwbGVzID0gW1xuXHRcdFx0XHQvLyBhY3Rpb24sIGFkZCBsaXN0ZW5lciwgbGlzdGVuZXIgbGlzdCwgZmluYWwgc3RhdGVcblx0XHRcdFx0WyBcInJlc29sdmVcIiwgXCJkb25lXCIsIGpRdWVyeS5DYWxsYmFja3MoXCJvbmNlIG1lbW9yeVwiKSwgXCJyZXNvbHZlZFwiIF0sXG5cdFx0XHRcdFsgXCJyZWplY3RcIiwgXCJmYWlsXCIsIGpRdWVyeS5DYWxsYmFja3MoXCJvbmNlIG1lbW9yeVwiKSwgXCJyZWplY3RlZFwiIF0sXG5cdFx0XHRcdFsgXCJub3RpZnlcIiwgXCJwcm9ncmVzc1wiLCBqUXVlcnkuQ2FsbGJhY2tzKFwibWVtb3J5XCIpIF1cblx0XHRcdF0sXG5cdFx0XHRzdGF0ZSA9IFwicGVuZGluZ1wiLFxuXHRcdFx0cHJvbWlzZSA9IHtcblx0XHRcdFx0c3RhdGU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHJldHVybiBzdGF0ZTtcblx0XHRcdFx0fSxcblx0XHRcdFx0YWx3YXlzOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRkZWZlcnJlZC5kb25lKCBhcmd1bWVudHMgKS5mYWlsKCBhcmd1bWVudHMgKTtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fSxcblx0XHRcdFx0dGhlbjogZnVuY3Rpb24oIC8qIGZuRG9uZSwgZm5GYWlsLCBmblByb2dyZXNzICovICkge1xuXHRcdFx0XHRcdHZhciBmbnMgPSBhcmd1bWVudHM7XG5cdFx0XHRcdFx0cmV0dXJuIGpRdWVyeS5EZWZlcnJlZChmdW5jdGlvbiggbmV3RGVmZXIgKSB7XG5cdFx0XHRcdFx0XHRqUXVlcnkuZWFjaCggdHVwbGVzLCBmdW5jdGlvbiggaSwgdHVwbGUgKSB7XG5cdFx0XHRcdFx0XHRcdHZhciBmbiA9IGpRdWVyeS5pc0Z1bmN0aW9uKCBmbnNbIGkgXSApICYmIGZuc1sgaSBdO1xuXHRcdFx0XHRcdFx0XHQvLyBkZWZlcnJlZFsgZG9uZSB8IGZhaWwgfCBwcm9ncmVzcyBdIGZvciBmb3J3YXJkaW5nIGFjdGlvbnMgdG8gbmV3RGVmZXJcblx0XHRcdFx0XHRcdFx0ZGVmZXJyZWRbIHR1cGxlWzFdIF0oZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyIHJldHVybmVkID0gZm4gJiYgZm4uYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdFx0XHRcdFx0XHRcdGlmICggcmV0dXJuZWQgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oIHJldHVybmVkLnByb21pc2UgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybmVkLnByb21pc2UoKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQuZG9uZSggbmV3RGVmZXIucmVzb2x2ZSApXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC5mYWlsKCBuZXdEZWZlci5yZWplY3QgKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQucHJvZ3Jlc3MoIG5ld0RlZmVyLm5vdGlmeSApO1xuXHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRuZXdEZWZlclsgdHVwbGVbIDAgXSArIFwiV2l0aFwiIF0oIHRoaXMgPT09IHByb21pc2UgPyBuZXdEZWZlci5wcm9taXNlKCkgOiB0aGlzLCBmbiA/IFsgcmV0dXJuZWQgXSA6IGFyZ3VtZW50cyApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdGZucyA9IG51bGw7XG5cdFx0XHRcdFx0fSkucHJvbWlzZSgpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHQvLyBHZXQgYSBwcm9taXNlIGZvciB0aGlzIGRlZmVycmVkXG5cdFx0XHRcdC8vIElmIG9iaiBpcyBwcm92aWRlZCwgdGhlIHByb21pc2UgYXNwZWN0IGlzIGFkZGVkIHRvIHRoZSBvYmplY3Rcblx0XHRcdFx0cHJvbWlzZTogZnVuY3Rpb24oIG9iaiApIHtcblx0XHRcdFx0XHRyZXR1cm4gb2JqICE9IG51bGwgPyBqUXVlcnkuZXh0ZW5kKCBvYmosIHByb21pc2UgKSA6IHByb21pc2U7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRkZWZlcnJlZCA9IHt9O1xuXG5cdFx0Ly8gS2VlcCBwaXBlIGZvciBiYWNrLWNvbXBhdFxuXHRcdHByb21pc2UucGlwZSA9IHByb21pc2UudGhlbjtcblxuXHRcdC8vIEFkZCBsaXN0LXNwZWNpZmljIG1ldGhvZHNcblx0XHRqUXVlcnkuZWFjaCggdHVwbGVzLCBmdW5jdGlvbiggaSwgdHVwbGUgKSB7XG5cdFx0XHR2YXIgbGlzdCA9IHR1cGxlWyAyIF0sXG5cdFx0XHRcdHN0YXRlU3RyaW5nID0gdHVwbGVbIDMgXTtcblxuXHRcdFx0Ly8gcHJvbWlzZVsgZG9uZSB8IGZhaWwgfCBwcm9ncmVzcyBdID0gbGlzdC5hZGRcblx0XHRcdHByb21pc2VbIHR1cGxlWzFdIF0gPSBsaXN0LmFkZDtcblxuXHRcdFx0Ly8gSGFuZGxlIHN0YXRlXG5cdFx0XHRpZiAoIHN0YXRlU3RyaW5nICkge1xuXHRcdFx0XHRsaXN0LmFkZChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHQvLyBzdGF0ZSA9IFsgcmVzb2x2ZWQgfCByZWplY3RlZCBdXG5cdFx0XHRcdFx0c3RhdGUgPSBzdGF0ZVN0cmluZztcblxuXHRcdFx0XHQvLyBbIHJlamVjdF9saXN0IHwgcmVzb2x2ZV9saXN0IF0uZGlzYWJsZTsgcHJvZ3Jlc3NfbGlzdC5sb2NrXG5cdFx0XHRcdH0sIHR1cGxlc1sgaSBeIDEgXVsgMiBdLmRpc2FibGUsIHR1cGxlc1sgMiBdWyAyIF0ubG9jayApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBkZWZlcnJlZFsgcmVzb2x2ZSB8IHJlamVjdCB8IG5vdGlmeSBdXG5cdFx0XHRkZWZlcnJlZFsgdHVwbGVbMF0gXSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRkZWZlcnJlZFsgdHVwbGVbMF0gKyBcIldpdGhcIiBdKCB0aGlzID09PSBkZWZlcnJlZCA/IHByb21pc2UgOiB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9O1xuXHRcdFx0ZGVmZXJyZWRbIHR1cGxlWzBdICsgXCJXaXRoXCIgXSA9IGxpc3QuZmlyZVdpdGg7XG5cdFx0fSk7XG5cblx0XHQvLyBNYWtlIHRoZSBkZWZlcnJlZCBhIHByb21pc2Vcblx0XHRwcm9taXNlLnByb21pc2UoIGRlZmVycmVkICk7XG5cblx0XHQvLyBDYWxsIGdpdmVuIGZ1bmMgaWYgYW55XG5cdFx0aWYgKCBmdW5jICkge1xuXHRcdFx0ZnVuYy5jYWxsKCBkZWZlcnJlZCwgZGVmZXJyZWQgKTtcblx0XHR9XG5cblx0XHQvLyBBbGwgZG9uZSFcblx0XHRyZXR1cm4gZGVmZXJyZWQ7XG5cdH0sXG5cblx0Ly8gRGVmZXJyZWQgaGVscGVyXG5cdHdoZW46IGZ1bmN0aW9uKCBzdWJvcmRpbmF0ZSAvKiAsIC4uLiwgc3Vib3JkaW5hdGVOICovICkge1xuXHRcdHZhciBpID0gMCxcblx0XHRcdHJlc29sdmVWYWx1ZXMgPSBzbGljZS5jYWxsKCBhcmd1bWVudHMgKSxcblx0XHRcdGxlbmd0aCA9IHJlc29sdmVWYWx1ZXMubGVuZ3RoLFxuXG5cdFx0XHQvLyB0aGUgY291bnQgb2YgdW5jb21wbGV0ZWQgc3Vib3JkaW5hdGVzXG5cdFx0XHRyZW1haW5pbmcgPSBsZW5ndGggIT09IDEgfHwgKCBzdWJvcmRpbmF0ZSAmJiBqUXVlcnkuaXNGdW5jdGlvbiggc3Vib3JkaW5hdGUucHJvbWlzZSApICkgPyBsZW5ndGggOiAwLFxuXG5cdFx0XHQvLyB0aGUgbWFzdGVyIERlZmVycmVkLiBJZiByZXNvbHZlVmFsdWVzIGNvbnNpc3Qgb2Ygb25seSBhIHNpbmdsZSBEZWZlcnJlZCwganVzdCB1c2UgdGhhdC5cblx0XHRcdGRlZmVycmVkID0gcmVtYWluaW5nID09PSAxID8gc3Vib3JkaW5hdGUgOiBqUXVlcnkuRGVmZXJyZWQoKSxcblxuXHRcdFx0Ly8gVXBkYXRlIGZ1bmN0aW9uIGZvciBib3RoIHJlc29sdmUgYW5kIHByb2dyZXNzIHZhbHVlc1xuXHRcdFx0dXBkYXRlRnVuYyA9IGZ1bmN0aW9uKCBpLCBjb250ZXh0cywgdmFsdWVzICkge1xuXHRcdFx0XHRyZXR1cm4gZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0XHRcdGNvbnRleHRzWyBpIF0gPSB0aGlzO1xuXHRcdFx0XHRcdHZhbHVlc1sgaSBdID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBzbGljZS5jYWxsKCBhcmd1bWVudHMgKSA6IHZhbHVlO1xuXHRcdFx0XHRcdGlmICggdmFsdWVzID09PSBwcm9ncmVzc1ZhbHVlcyApIHtcblx0XHRcdFx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGgoIGNvbnRleHRzLCB2YWx1ZXMgKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKCAhKCAtLXJlbWFpbmluZyApICkge1xuXHRcdFx0XHRcdFx0ZGVmZXJyZWQucmVzb2x2ZVdpdGgoIGNvbnRleHRzLCB2YWx1ZXMgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH07XG5cdFx0XHR9LFxuXG5cdFx0XHRwcm9ncmVzc1ZhbHVlcywgcHJvZ3Jlc3NDb250ZXh0cywgcmVzb2x2ZUNvbnRleHRzO1xuXG5cdFx0Ly8gQWRkIGxpc3RlbmVycyB0byBEZWZlcnJlZCBzdWJvcmRpbmF0ZXM7IHRyZWF0IG90aGVycyBhcyByZXNvbHZlZFxuXHRcdGlmICggbGVuZ3RoID4gMSApIHtcblx0XHRcdHByb2dyZXNzVmFsdWVzID0gbmV3IEFycmF5KCBsZW5ndGggKTtcblx0XHRcdHByb2dyZXNzQ29udGV4dHMgPSBuZXcgQXJyYXkoIGxlbmd0aCApO1xuXHRcdFx0cmVzb2x2ZUNvbnRleHRzID0gbmV3IEFycmF5KCBsZW5ndGggKTtcblx0XHRcdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIHJlc29sdmVWYWx1ZXNbIGkgXSAmJiBqUXVlcnkuaXNGdW5jdGlvbiggcmVzb2x2ZVZhbHVlc1sgaSBdLnByb21pc2UgKSApIHtcblx0XHRcdFx0XHRyZXNvbHZlVmFsdWVzWyBpIF0ucHJvbWlzZSgpXG5cdFx0XHRcdFx0XHQuZG9uZSggdXBkYXRlRnVuYyggaSwgcmVzb2x2ZUNvbnRleHRzLCByZXNvbHZlVmFsdWVzICkgKVxuXHRcdFx0XHRcdFx0LmZhaWwoIGRlZmVycmVkLnJlamVjdCApXG5cdFx0XHRcdFx0XHQucHJvZ3Jlc3MoIHVwZGF0ZUZ1bmMoIGksIHByb2dyZXNzQ29udGV4dHMsIHByb2dyZXNzVmFsdWVzICkgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQtLXJlbWFpbmluZztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIElmIHdlJ3JlIG5vdCB3YWl0aW5nIG9uIGFueXRoaW5nLCByZXNvbHZlIHRoZSBtYXN0ZXJcblx0XHRpZiAoICFyZW1haW5pbmcgKSB7XG5cdFx0XHRkZWZlcnJlZC5yZXNvbHZlV2l0aCggcmVzb2x2ZUNvbnRleHRzLCByZXNvbHZlVmFsdWVzICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGRlZmVycmVkLnByb21pc2UoKTtcblx0fVxufSk7XG5cblxuLy8gVGhlIGRlZmVycmVkIHVzZWQgb24gRE9NIHJlYWR5XG52YXIgcmVhZHlMaXN0O1xuXG5qUXVlcnkuZm4ucmVhZHkgPSBmdW5jdGlvbiggZm4gKSB7XG5cdC8vIEFkZCB0aGUgY2FsbGJhY2tcblx0alF1ZXJ5LnJlYWR5LnByb21pc2UoKS5kb25lKCBmbiApO1xuXG5cdHJldHVybiB0aGlzO1xufTtcblxualF1ZXJ5LmV4dGVuZCh7XG5cdC8vIElzIHRoZSBET00gcmVhZHkgdG8gYmUgdXNlZD8gU2V0IHRvIHRydWUgb25jZSBpdCBvY2N1cnMuXG5cdGlzUmVhZHk6IGZhbHNlLFxuXG5cdC8vIEEgY291bnRlciB0byB0cmFjayBob3cgbWFueSBpdGVtcyB0byB3YWl0IGZvciBiZWZvcmVcblx0Ly8gdGhlIHJlYWR5IGV2ZW50IGZpcmVzLiBTZWUgIzY3ODFcblx0cmVhZHlXYWl0OiAxLFxuXG5cdC8vIEhvbGQgKG9yIHJlbGVhc2UpIHRoZSByZWFkeSBldmVudFxuXHRob2xkUmVhZHk6IGZ1bmN0aW9uKCBob2xkICkge1xuXHRcdGlmICggaG9sZCApIHtcblx0XHRcdGpRdWVyeS5yZWFkeVdhaXQrKztcblx0XHR9IGVsc2Uge1xuXHRcdFx0alF1ZXJ5LnJlYWR5KCB0cnVlICk7XG5cdFx0fVxuXHR9LFxuXG5cdC8vIEhhbmRsZSB3aGVuIHRoZSBET00gaXMgcmVhZHlcblx0cmVhZHk6IGZ1bmN0aW9uKCB3YWl0ICkge1xuXG5cdFx0Ly8gQWJvcnQgaWYgdGhlcmUgYXJlIHBlbmRpbmcgaG9sZHMgb3Igd2UncmUgYWxyZWFkeSByZWFkeVxuXHRcdGlmICggd2FpdCA9PT0gdHJ1ZSA/IC0talF1ZXJ5LnJlYWR5V2FpdCA6IGpRdWVyeS5pc1JlYWR5ICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIFJlbWVtYmVyIHRoYXQgdGhlIERPTSBpcyByZWFkeVxuXHRcdGpRdWVyeS5pc1JlYWR5ID0gdHJ1ZTtcblxuXHRcdC8vIElmIGEgbm9ybWFsIERPTSBSZWFkeSBldmVudCBmaXJlZCwgZGVjcmVtZW50LCBhbmQgd2FpdCBpZiBuZWVkIGJlXG5cdFx0aWYgKCB3YWl0ICE9PSB0cnVlICYmIC0talF1ZXJ5LnJlYWR5V2FpdCA+IDAgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gSWYgdGhlcmUgYXJlIGZ1bmN0aW9ucyBib3VuZCwgdG8gZXhlY3V0ZVxuXHRcdHJlYWR5TGlzdC5yZXNvbHZlV2l0aCggZG9jdW1lbnQsIFsgalF1ZXJ5IF0gKTtcblxuXHRcdC8vIFRyaWdnZXIgYW55IGJvdW5kIHJlYWR5IGV2ZW50c1xuXHRcdGlmICggalF1ZXJ5LmZuLnRyaWdnZXJIYW5kbGVyICkge1xuXHRcdFx0alF1ZXJ5KCBkb2N1bWVudCApLnRyaWdnZXJIYW5kbGVyKCBcInJlYWR5XCIgKTtcblx0XHRcdGpRdWVyeSggZG9jdW1lbnQgKS5vZmYoIFwicmVhZHlcIiApO1xuXHRcdH1cblx0fVxufSk7XG5cbi8qKlxuICogVGhlIHJlYWR5IGV2ZW50IGhhbmRsZXIgYW5kIHNlbGYgY2xlYW51cCBtZXRob2RcbiAqL1xuZnVuY3Rpb24gY29tcGxldGVkKCkge1xuXHRkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCBcIkRPTUNvbnRlbnRMb2FkZWRcIiwgY29tcGxldGVkLCBmYWxzZSApO1xuXHR3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lciggXCJsb2FkXCIsIGNvbXBsZXRlZCwgZmFsc2UgKTtcblx0alF1ZXJ5LnJlYWR5KCk7XG59XG5cbmpRdWVyeS5yZWFkeS5wcm9taXNlID0gZnVuY3Rpb24oIG9iaiApIHtcblx0aWYgKCAhcmVhZHlMaXN0ICkge1xuXG5cdFx0cmVhZHlMaXN0ID0galF1ZXJ5LkRlZmVycmVkKCk7XG5cblx0XHQvLyBDYXRjaCBjYXNlcyB3aGVyZSAkKGRvY3VtZW50KS5yZWFkeSgpIGlzIGNhbGxlZCBhZnRlciB0aGUgYnJvd3NlciBldmVudCBoYXMgYWxyZWFkeSBvY2N1cnJlZC5cblx0XHQvLyBXZSBvbmNlIHRyaWVkIHRvIHVzZSByZWFkeVN0YXRlIFwiaW50ZXJhY3RpdmVcIiBoZXJlLCBidXQgaXQgY2F1c2VkIGlzc3VlcyBsaWtlIHRoZSBvbmVcblx0XHQvLyBkaXNjb3ZlcmVkIGJ5IENocmlzUyBoZXJlOiBodHRwOi8vYnVncy5qcXVlcnkuY29tL3RpY2tldC8xMjI4MiNjb21tZW50OjE1XG5cdFx0aWYgKCBkb2N1bWVudC5yZWFkeVN0YXRlID09PSBcImNvbXBsZXRlXCIgKSB7XG5cdFx0XHQvLyBIYW5kbGUgaXQgYXN5bmNocm9ub3VzbHkgdG8gYWxsb3cgc2NyaXB0cyB0aGUgb3Bwb3J0dW5pdHkgdG8gZGVsYXkgcmVhZHlcblx0XHRcdHNldFRpbWVvdXQoIGpRdWVyeS5yZWFkeSApO1xuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gVXNlIHRoZSBoYW5keSBldmVudCBjYWxsYmFja1xuXHRcdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggXCJET01Db250ZW50TG9hZGVkXCIsIGNvbXBsZXRlZCwgZmFsc2UgKTtcblxuXHRcdFx0Ly8gQSBmYWxsYmFjayB0byB3aW5kb3cub25sb2FkLCB0aGF0IHdpbGwgYWx3YXlzIHdvcmtcblx0XHRcdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCBcImxvYWRcIiwgY29tcGxldGVkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gcmVhZHlMaXN0LnByb21pc2UoIG9iaiApO1xufTtcblxuLy8gS2ljayBvZmYgdGhlIERPTSByZWFkeSBjaGVjayBldmVuIGlmIHRoZSB1c2VyIGRvZXMgbm90XG5qUXVlcnkucmVhZHkucHJvbWlzZSgpO1xuXG5cblxuXG4vLyBNdWx0aWZ1bmN0aW9uYWwgbWV0aG9kIHRvIGdldCBhbmQgc2V0IHZhbHVlcyBvZiBhIGNvbGxlY3Rpb25cbi8vIFRoZSB2YWx1ZS9zIGNhbiBvcHRpb25hbGx5IGJlIGV4ZWN1dGVkIGlmIGl0J3MgYSBmdW5jdGlvblxudmFyIGFjY2VzcyA9IGpRdWVyeS5hY2Nlc3MgPSBmdW5jdGlvbiggZWxlbXMsIGZuLCBrZXksIHZhbHVlLCBjaGFpbmFibGUsIGVtcHR5R2V0LCByYXcgKSB7XG5cdHZhciBpID0gMCxcblx0XHRsZW4gPSBlbGVtcy5sZW5ndGgsXG5cdFx0YnVsayA9IGtleSA9PSBudWxsO1xuXG5cdC8vIFNldHMgbWFueSB2YWx1ZXNcblx0aWYgKCBqUXVlcnkudHlwZSgga2V5ICkgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0Y2hhaW5hYmxlID0gdHJ1ZTtcblx0XHRmb3IgKCBpIGluIGtleSApIHtcblx0XHRcdGpRdWVyeS5hY2Nlc3MoIGVsZW1zLCBmbiwgaSwga2V5W2ldLCB0cnVlLCBlbXB0eUdldCwgcmF3ICk7XG5cdFx0fVxuXG5cdC8vIFNldHMgb25lIHZhbHVlXG5cdH0gZWxzZSBpZiAoIHZhbHVlICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0Y2hhaW5hYmxlID0gdHJ1ZTtcblxuXHRcdGlmICggIWpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApICkge1xuXHRcdFx0cmF3ID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIGJ1bGsgKSB7XG5cdFx0XHQvLyBCdWxrIG9wZXJhdGlvbnMgcnVuIGFnYWluc3QgdGhlIGVudGlyZSBzZXRcblx0XHRcdGlmICggcmF3ICkge1xuXHRcdFx0XHRmbi5jYWxsKCBlbGVtcywgdmFsdWUgKTtcblx0XHRcdFx0Zm4gPSBudWxsO1xuXG5cdFx0XHQvLyAuLi5leGNlcHQgd2hlbiBleGVjdXRpbmcgZnVuY3Rpb24gdmFsdWVzXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRidWxrID0gZm47XG5cdFx0XHRcdGZuID0gZnVuY3Rpb24oIGVsZW0sIGtleSwgdmFsdWUgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGJ1bGsuY2FsbCggalF1ZXJ5KCBlbGVtICksIHZhbHVlICk7XG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCBmbiApIHtcblx0XHRcdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHRmbiggZWxlbXNbaV0sIGtleSwgcmF3ID8gdmFsdWUgOiB2YWx1ZS5jYWxsKCBlbGVtc1tpXSwgaSwgZm4oIGVsZW1zW2ldLCBrZXkgKSApICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGNoYWluYWJsZSA/XG5cdFx0ZWxlbXMgOlxuXG5cdFx0Ly8gR2V0c1xuXHRcdGJ1bGsgP1xuXHRcdFx0Zm4uY2FsbCggZWxlbXMgKSA6XG5cdFx0XHRsZW4gPyBmbiggZWxlbXNbMF0sIGtleSApIDogZW1wdHlHZXQ7XG59O1xuXG5cbi8qKlxuICogRGV0ZXJtaW5lcyB3aGV0aGVyIGFuIG9iamVjdCBjYW4gaGF2ZSBkYXRhXG4gKi9cbmpRdWVyeS5hY2NlcHREYXRhID0gZnVuY3Rpb24oIG93bmVyICkge1xuXHQvLyBBY2NlcHRzIG9ubHk6XG5cdC8vICAtIE5vZGVcblx0Ly8gICAgLSBOb2RlLkVMRU1FTlRfTk9ERVxuXHQvLyAgICAtIE5vZGUuRE9DVU1FTlRfTk9ERVxuXHQvLyAgLSBPYmplY3Rcblx0Ly8gICAgLSBBbnlcblx0LyoganNoaW50IC1XMDE4ICovXG5cdHJldHVybiBvd25lci5ub2RlVHlwZSA9PT0gMSB8fCBvd25lci5ub2RlVHlwZSA9PT0gOSB8fCAhKCArb3duZXIubm9kZVR5cGUgKTtcbn07XG5cblxuZnVuY3Rpb24gRGF0YSgpIHtcblx0Ly8gU3VwcG9ydDogQW5kcm9pZDw0LFxuXHQvLyBPbGQgV2ViS2l0IGRvZXMgbm90IGhhdmUgT2JqZWN0LnByZXZlbnRFeHRlbnNpb25zL2ZyZWV6ZSBtZXRob2QsXG5cdC8vIHJldHVybiBuZXcgZW1wdHkgb2JqZWN0IGluc3RlYWQgd2l0aCBubyBbW3NldF1dIGFjY2Vzc29yXG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSggdGhpcy5jYWNoZSA9IHt9LCAwLCB7XG5cdFx0Z2V0OiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB7fTtcblx0XHR9XG5cdH0pO1xuXG5cdHRoaXMuZXhwYW5kbyA9IGpRdWVyeS5leHBhbmRvICsgRGF0YS51aWQrKztcbn1cblxuRGF0YS51aWQgPSAxO1xuRGF0YS5hY2NlcHRzID0galF1ZXJ5LmFjY2VwdERhdGE7XG5cbkRhdGEucHJvdG90eXBlID0ge1xuXHRrZXk6IGZ1bmN0aW9uKCBvd25lciApIHtcblx0XHQvLyBXZSBjYW4gYWNjZXB0IGRhdGEgZm9yIG5vbi1lbGVtZW50IG5vZGVzIGluIG1vZGVybiBicm93c2Vycyxcblx0XHQvLyBidXQgd2Ugc2hvdWxkIG5vdCwgc2VlICM4MzM1LlxuXHRcdC8vIEFsd2F5cyByZXR1cm4gdGhlIGtleSBmb3IgYSBmcm96ZW4gb2JqZWN0LlxuXHRcdGlmICggIURhdGEuYWNjZXB0cyggb3duZXIgKSApIHtcblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblxuXHRcdHZhciBkZXNjcmlwdG9yID0ge30sXG5cdFx0XHQvLyBDaGVjayBpZiB0aGUgb3duZXIgb2JqZWN0IGFscmVhZHkgaGFzIGEgY2FjaGUga2V5XG5cdFx0XHR1bmxvY2sgPSBvd25lclsgdGhpcy5leHBhbmRvIF07XG5cblx0XHQvLyBJZiBub3QsIGNyZWF0ZSBvbmVcblx0XHRpZiAoICF1bmxvY2sgKSB7XG5cdFx0XHR1bmxvY2sgPSBEYXRhLnVpZCsrO1xuXG5cdFx0XHQvLyBTZWN1cmUgaXQgaW4gYSBub24tZW51bWVyYWJsZSwgbm9uLXdyaXRhYmxlIHByb3BlcnR5XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRkZXNjcmlwdG9yWyB0aGlzLmV4cGFuZG8gXSA9IHsgdmFsdWU6IHVubG9jayB9O1xuXHRcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydGllcyggb3duZXIsIGRlc2NyaXB0b3IgKTtcblxuXHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZDw0XG5cdFx0XHQvLyBGYWxsYmFjayB0byBhIGxlc3Mgc2VjdXJlIGRlZmluaXRpb25cblx0XHRcdH0gY2F0Y2ggKCBlICkge1xuXHRcdFx0XHRkZXNjcmlwdG9yWyB0aGlzLmV4cGFuZG8gXSA9IHVubG9jaztcblx0XHRcdFx0alF1ZXJ5LmV4dGVuZCggb3duZXIsIGRlc2NyaXB0b3IgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBFbnN1cmUgdGhlIGNhY2hlIG9iamVjdFxuXHRcdGlmICggIXRoaXMuY2FjaGVbIHVubG9jayBdICkge1xuXHRcdFx0dGhpcy5jYWNoZVsgdW5sb2NrIF0gPSB7fTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdW5sb2NrO1xuXHR9LFxuXHRzZXQ6IGZ1bmN0aW9uKCBvd25lciwgZGF0YSwgdmFsdWUgKSB7XG5cdFx0dmFyIHByb3AsXG5cdFx0XHQvLyBUaGVyZSBtYXkgYmUgYW4gdW5sb2NrIGFzc2lnbmVkIHRvIHRoaXMgbm9kZSxcblx0XHRcdC8vIGlmIHRoZXJlIGlzIG5vIGVudHJ5IGZvciB0aGlzIFwib3duZXJcIiwgY3JlYXRlIG9uZSBpbmxpbmVcblx0XHRcdC8vIGFuZCBzZXQgdGhlIHVubG9jayBhcyB0aG91Z2ggYW4gb3duZXIgZW50cnkgaGFkIGFsd2F5cyBleGlzdGVkXG5cdFx0XHR1bmxvY2sgPSB0aGlzLmtleSggb3duZXIgKSxcblx0XHRcdGNhY2hlID0gdGhpcy5jYWNoZVsgdW5sb2NrIF07XG5cblx0XHQvLyBIYW5kbGU6IFsgb3duZXIsIGtleSwgdmFsdWUgXSBhcmdzXG5cdFx0aWYgKCB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGNhY2hlWyBkYXRhIF0gPSB2YWx1ZTtcblxuXHRcdC8vIEhhbmRsZTogWyBvd25lciwgeyBwcm9wZXJ0aWVzIH0gXSBhcmdzXG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIEZyZXNoIGFzc2lnbm1lbnRzIGJ5IG9iamVjdCBhcmUgc2hhbGxvdyBjb3BpZWRcblx0XHRcdGlmICggalF1ZXJ5LmlzRW1wdHlPYmplY3QoIGNhY2hlICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5leHRlbmQoIHRoaXMuY2FjaGVbIHVubG9jayBdLCBkYXRhICk7XG5cdFx0XHQvLyBPdGhlcndpc2UsIGNvcHkgdGhlIHByb3BlcnRpZXMgb25lLWJ5LW9uZSB0byB0aGUgY2FjaGUgb2JqZWN0XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRmb3IgKCBwcm9wIGluIGRhdGEgKSB7XG5cdFx0XHRcdFx0Y2FjaGVbIHByb3AgXSA9IGRhdGFbIHByb3AgXTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gY2FjaGU7XG5cdH0sXG5cdGdldDogZnVuY3Rpb24oIG93bmVyLCBrZXkgKSB7XG5cdFx0Ly8gRWl0aGVyIGEgdmFsaWQgY2FjaGUgaXMgZm91bmQsIG9yIHdpbGwgYmUgY3JlYXRlZC5cblx0XHQvLyBOZXcgY2FjaGVzIHdpbGwgYmUgY3JlYXRlZCBhbmQgdGhlIHVubG9jayByZXR1cm5lZCxcblx0XHQvLyBhbGxvd2luZyBkaXJlY3QgYWNjZXNzIHRvIHRoZSBuZXdseSBjcmVhdGVkXG5cdFx0Ly8gZW1wdHkgZGF0YSBvYmplY3QuIEEgdmFsaWQgb3duZXIgb2JqZWN0IG11c3QgYmUgcHJvdmlkZWQuXG5cdFx0dmFyIGNhY2hlID0gdGhpcy5jYWNoZVsgdGhpcy5rZXkoIG93bmVyICkgXTtcblxuXHRcdHJldHVybiBrZXkgPT09IHVuZGVmaW5lZCA/XG5cdFx0XHRjYWNoZSA6IGNhY2hlWyBrZXkgXTtcblx0fSxcblx0YWNjZXNzOiBmdW5jdGlvbiggb3duZXIsIGtleSwgdmFsdWUgKSB7XG5cdFx0dmFyIHN0b3JlZDtcblx0XHQvLyBJbiBjYXNlcyB3aGVyZSBlaXRoZXI6XG5cdFx0Ly9cblx0XHQvLyAgIDEuIE5vIGtleSB3YXMgc3BlY2lmaWVkXG5cdFx0Ly8gICAyLiBBIHN0cmluZyBrZXkgd2FzIHNwZWNpZmllZCwgYnV0IG5vIHZhbHVlIHByb3ZpZGVkXG5cdFx0Ly9cblx0XHQvLyBUYWtlIHRoZSBcInJlYWRcIiBwYXRoIGFuZCBhbGxvdyB0aGUgZ2V0IG1ldGhvZCB0byBkZXRlcm1pbmVcblx0XHQvLyB3aGljaCB2YWx1ZSB0byByZXR1cm4sIHJlc3BlY3RpdmVseSBlaXRoZXI6XG5cdFx0Ly9cblx0XHQvLyAgIDEuIFRoZSBlbnRpcmUgY2FjaGUgb2JqZWN0XG5cdFx0Ly8gICAyLiBUaGUgZGF0YSBzdG9yZWQgYXQgdGhlIGtleVxuXHRcdC8vXG5cdFx0aWYgKCBrZXkgPT09IHVuZGVmaW5lZCB8fFxuXHRcdFx0XHQoKGtleSAmJiB0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiKSAmJiB2YWx1ZSA9PT0gdW5kZWZpbmVkKSApIHtcblxuXHRcdFx0c3RvcmVkID0gdGhpcy5nZXQoIG93bmVyLCBrZXkgKTtcblxuXHRcdFx0cmV0dXJuIHN0b3JlZCAhPT0gdW5kZWZpbmVkID9cblx0XHRcdFx0c3RvcmVkIDogdGhpcy5nZXQoIG93bmVyLCBqUXVlcnkuY2FtZWxDYXNlKGtleSkgKTtcblx0XHR9XG5cblx0XHQvLyBbKl1XaGVuIHRoZSBrZXkgaXMgbm90IGEgc3RyaW5nLCBvciBib3RoIGEga2V5IGFuZCB2YWx1ZVxuXHRcdC8vIGFyZSBzcGVjaWZpZWQsIHNldCBvciBleHRlbmQgKGV4aXN0aW5nIG9iamVjdHMpIHdpdGggZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBBbiBvYmplY3Qgb2YgcHJvcGVydGllc1xuXHRcdC8vICAgMi4gQSBrZXkgYW5kIHZhbHVlXG5cdFx0Ly9cblx0XHR0aGlzLnNldCggb3duZXIsIGtleSwgdmFsdWUgKTtcblxuXHRcdC8vIFNpbmNlIHRoZSBcInNldFwiIHBhdGggY2FuIGhhdmUgdHdvIHBvc3NpYmxlIGVudHJ5IHBvaW50c1xuXHRcdC8vIHJldHVybiB0aGUgZXhwZWN0ZWQgZGF0YSBiYXNlZCBvbiB3aGljaCBwYXRoIHdhcyB0YWtlblsqXVxuXHRcdHJldHVybiB2YWx1ZSAhPT0gdW5kZWZpbmVkID8gdmFsdWUgOiBrZXk7XG5cdH0sXG5cdHJlbW92ZTogZnVuY3Rpb24oIG93bmVyLCBrZXkgKSB7XG5cdFx0dmFyIGksIG5hbWUsIGNhbWVsLFxuXHRcdFx0dW5sb2NrID0gdGhpcy5rZXkoIG93bmVyICksXG5cdFx0XHRjYWNoZSA9IHRoaXMuY2FjaGVbIHVubG9jayBdO1xuXG5cdFx0aWYgKCBrZXkgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHRoaXMuY2FjaGVbIHVubG9jayBdID0ge307XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gU3VwcG9ydCBhcnJheSBvciBzcGFjZSBzZXBhcmF0ZWQgc3RyaW5nIG9mIGtleXNcblx0XHRcdGlmICggalF1ZXJ5LmlzQXJyYXkoIGtleSApICkge1xuXHRcdFx0XHQvLyBJZiBcIm5hbWVcIiBpcyBhbiBhcnJheSBvZiBrZXlzLi4uXG5cdFx0XHRcdC8vIFdoZW4gZGF0YSBpcyBpbml0aWFsbHkgY3JlYXRlZCwgdmlhIChcImtleVwiLCBcInZhbFwiKSBzaWduYXR1cmUsXG5cdFx0XHRcdC8vIGtleXMgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gY2FtZWxDYXNlLlxuXHRcdFx0XHQvLyBTaW5jZSB0aGVyZSBpcyBubyB3YXkgdG8gdGVsbCBfaG93XyBhIGtleSB3YXMgYWRkZWQsIHJlbW92ZVxuXHRcdFx0XHQvLyBib3RoIHBsYWluIGtleSBhbmQgY2FtZWxDYXNlIGtleS4gIzEyNzg2XG5cdFx0XHRcdC8vIFRoaXMgd2lsbCBvbmx5IHBlbmFsaXplIHRoZSBhcnJheSBhcmd1bWVudCBwYXRoLlxuXHRcdFx0XHRuYW1lID0ga2V5LmNvbmNhdCgga2V5Lm1hcCggalF1ZXJ5LmNhbWVsQ2FzZSApICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjYW1lbCA9IGpRdWVyeS5jYW1lbENhc2UoIGtleSApO1xuXHRcdFx0XHQvLyBUcnkgdGhlIHN0cmluZyBhcyBhIGtleSBiZWZvcmUgYW55IG1hbmlwdWxhdGlvblxuXHRcdFx0XHRpZiAoIGtleSBpbiBjYWNoZSApIHtcblx0XHRcdFx0XHRuYW1lID0gWyBrZXksIGNhbWVsIF07XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Ly8gSWYgYSBrZXkgd2l0aCB0aGUgc3BhY2VzIGV4aXN0cywgdXNlIGl0LlxuXHRcdFx0XHRcdC8vIE90aGVyd2lzZSwgY3JlYXRlIGFuIGFycmF5IGJ5IG1hdGNoaW5nIG5vbi13aGl0ZXNwYWNlXG5cdFx0XHRcdFx0bmFtZSA9IGNhbWVsO1xuXHRcdFx0XHRcdG5hbWUgPSBuYW1lIGluIGNhY2hlID9cblx0XHRcdFx0XHRcdFsgbmFtZSBdIDogKCBuYW1lLm1hdGNoKCBybm90d2hpdGUgKSB8fCBbXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGkgPSBuYW1lLmxlbmd0aDtcblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRkZWxldGUgY2FjaGVbIG5hbWVbIGkgXSBdO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0aGFzRGF0YTogZnVuY3Rpb24oIG93bmVyICkge1xuXHRcdHJldHVybiAhalF1ZXJ5LmlzRW1wdHlPYmplY3QoXG5cdFx0XHR0aGlzLmNhY2hlWyBvd25lclsgdGhpcy5leHBhbmRvIF0gXSB8fCB7fVxuXHRcdCk7XG5cdH0sXG5cdGRpc2NhcmQ6IGZ1bmN0aW9uKCBvd25lciApIHtcblx0XHRpZiAoIG93bmVyWyB0aGlzLmV4cGFuZG8gXSApIHtcblx0XHRcdGRlbGV0ZSB0aGlzLmNhY2hlWyBvd25lclsgdGhpcy5leHBhbmRvIF0gXTtcblx0XHR9XG5cdH1cbn07XG52YXIgZGF0YV9wcml2ID0gbmV3IERhdGEoKTtcblxudmFyIGRhdGFfdXNlciA9IG5ldyBEYXRhKCk7XG5cblxuXG4vL1x0SW1wbGVtZW50YXRpb24gU3VtbWFyeVxuLy9cbi8vXHQxLiBFbmZvcmNlIEFQSSBzdXJmYWNlIGFuZCBzZW1hbnRpYyBjb21wYXRpYmlsaXR5IHdpdGggMS45LnggYnJhbmNoXG4vL1x0Mi4gSW1wcm92ZSB0aGUgbW9kdWxlJ3MgbWFpbnRhaW5hYmlsaXR5IGJ5IHJlZHVjaW5nIHRoZSBzdG9yYWdlXG4vL1x0XHRwYXRocyB0byBhIHNpbmdsZSBtZWNoYW5pc20uXG4vL1x0My4gVXNlIHRoZSBzYW1lIHNpbmdsZSBtZWNoYW5pc20gdG8gc3VwcG9ydCBcInByaXZhdGVcIiBhbmQgXCJ1c2VyXCIgZGF0YS5cbi8vXHQ0LiBfTmV2ZXJfIGV4cG9zZSBcInByaXZhdGVcIiBkYXRhIHRvIHVzZXIgY29kZSAoVE9ETzogRHJvcCBfZGF0YSwgX3JlbW92ZURhdGEpXG4vL1x0NS4gQXZvaWQgZXhwb3NpbmcgaW1wbGVtZW50YXRpb24gZGV0YWlscyBvbiB1c2VyIG9iamVjdHMgKGVnLiBleHBhbmRvIHByb3BlcnRpZXMpXG4vL1x0Ni4gUHJvdmlkZSBhIGNsZWFyIHBhdGggZm9yIGltcGxlbWVudGF0aW9uIHVwZ3JhZGUgdG8gV2Vha01hcCBpbiAyMDE0XG5cbnZhciByYnJhY2UgPSAvXig/Olxce1tcXHdcXFddKlxcfXxcXFtbXFx3XFxXXSpcXF0pJC8sXG5cdHJtdWx0aURhc2ggPSAvKFtBLVpdKS9nO1xuXG5mdW5jdGlvbiBkYXRhQXR0ciggZWxlbSwga2V5LCBkYXRhICkge1xuXHR2YXIgbmFtZTtcblxuXHQvLyBJZiBub3RoaW5nIHdhcyBmb3VuZCBpbnRlcm5hbGx5LCB0cnkgdG8gZmV0Y2ggYW55XG5cdC8vIGRhdGEgZnJvbSB0aGUgSFRNTDUgZGF0YS0qIGF0dHJpYnV0ZVxuXHRpZiAoIGRhdGEgPT09IHVuZGVmaW5lZCAmJiBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdG5hbWUgPSBcImRhdGEtXCIgKyBrZXkucmVwbGFjZSggcm11bHRpRGFzaCwgXCItJDFcIiApLnRvTG93ZXJDYXNlKCk7XG5cdFx0ZGF0YSA9IGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lICk7XG5cblx0XHRpZiAoIHR5cGVvZiBkYXRhID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0ZGF0YSA9IGRhdGEgPT09IFwidHJ1ZVwiID8gdHJ1ZSA6XG5cdFx0XHRcdFx0ZGF0YSA9PT0gXCJmYWxzZVwiID8gZmFsc2UgOlxuXHRcdFx0XHRcdGRhdGEgPT09IFwibnVsbFwiID8gbnVsbCA6XG5cdFx0XHRcdFx0Ly8gT25seSBjb252ZXJ0IHRvIGEgbnVtYmVyIGlmIGl0IGRvZXNuJ3QgY2hhbmdlIHRoZSBzdHJpbmdcblx0XHRcdFx0XHQrZGF0YSArIFwiXCIgPT09IGRhdGEgPyArZGF0YSA6XG5cdFx0XHRcdFx0cmJyYWNlLnRlc3QoIGRhdGEgKSA/IGpRdWVyeS5wYXJzZUpTT04oIGRhdGEgKSA6XG5cdFx0XHRcdFx0ZGF0YTtcblx0XHRcdH0gY2F0Y2goIGUgKSB7fVxuXG5cdFx0XHQvLyBNYWtlIHN1cmUgd2Ugc2V0IHRoZSBkYXRhIHNvIGl0IGlzbid0IGNoYW5nZWQgbGF0ZXJcblx0XHRcdGRhdGFfdXNlci5zZXQoIGVsZW0sIGtleSwgZGF0YSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRkYXRhID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gZGF0YTtcbn1cblxualF1ZXJ5LmV4dGVuZCh7XG5cdGhhc0RhdGE6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBkYXRhX3VzZXIuaGFzRGF0YSggZWxlbSApIHx8IGRhdGFfcHJpdi5oYXNEYXRhKCBlbGVtICk7XG5cdH0sXG5cblx0ZGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIGRhdGFfdXNlci5hY2Nlc3MoIGVsZW0sIG5hbWUsIGRhdGEgKTtcblx0fSxcblxuXHRyZW1vdmVEYXRhOiBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHtcblx0XHRkYXRhX3VzZXIucmVtb3ZlKCBlbGVtLCBuYW1lICk7XG5cdH0sXG5cblx0Ly8gVE9ETzogTm93IHRoYXQgYWxsIGNhbGxzIHRvIF9kYXRhIGFuZCBfcmVtb3ZlRGF0YSBoYXZlIGJlZW4gcmVwbGFjZWRcblx0Ly8gd2l0aCBkaXJlY3QgY2FsbHMgdG8gZGF0YV9wcml2IG1ldGhvZHMsIHRoZXNlIGNhbiBiZSBkZXByZWNhdGVkLlxuXHRfZGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIGRhdGFfcHJpdi5hY2Nlc3MoIGVsZW0sIG5hbWUsIGRhdGEgKTtcblx0fSxcblxuXHRfcmVtb3ZlRGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUgKSB7XG5cdFx0ZGF0YV9wcml2LnJlbW92ZSggZWxlbSwgbmFtZSApO1xuXHR9XG59KTtcblxualF1ZXJ5LmZuLmV4dGVuZCh7XG5cdGRhdGE6IGZ1bmN0aW9uKCBrZXksIHZhbHVlICkge1xuXHRcdHZhciBpLCBuYW1lLCBkYXRhLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXSxcblx0XHRcdGF0dHJzID0gZWxlbSAmJiBlbGVtLmF0dHJpYnV0ZXM7XG5cblx0XHQvLyBHZXRzIGFsbCB2YWx1ZXNcblx0XHRpZiAoIGtleSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0aWYgKCB0aGlzLmxlbmd0aCApIHtcblx0XHRcdFx0ZGF0YSA9IGRhdGFfdXNlci5nZXQoIGVsZW0gKTtcblxuXHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgJiYgIWRhdGFfcHJpdi5nZXQoIGVsZW0sIFwiaGFzRGF0YUF0dHJzXCIgKSApIHtcblx0XHRcdFx0XHRpID0gYXR0cnMubGVuZ3RoO1xuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXG5cdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRTExK1xuXHRcdFx0XHRcdFx0Ly8gVGhlIGF0dHJzIGVsZW1lbnRzIGNhbiBiZSBudWxsICgjMTQ4OTQpXG5cdFx0XHRcdFx0XHRpZiAoIGF0dHJzWyBpIF0gKSB7XG5cdFx0XHRcdFx0XHRcdG5hbWUgPSBhdHRyc1sgaSBdLm5hbWU7XG5cdFx0XHRcdFx0XHRcdGlmICggbmFtZS5pbmRleE9mKCBcImRhdGEtXCIgKSA9PT0gMCApIHtcblx0XHRcdFx0XHRcdFx0XHRuYW1lID0galF1ZXJ5LmNhbWVsQ2FzZSggbmFtZS5zbGljZSg1KSApO1xuXHRcdFx0XHRcdFx0XHRcdGRhdGFBdHRyKCBlbGVtLCBuYW1lLCBkYXRhWyBuYW1lIF0gKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRkYXRhX3ByaXYuc2V0KCBlbGVtLCBcImhhc0RhdGFBdHRyc1wiLCB0cnVlICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0fVxuXG5cdFx0Ly8gU2V0cyBtdWx0aXBsZSB2YWx1ZXNcblx0XHRpZiAoIHR5cGVvZiBrZXkgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRkYXRhX3VzZXIuc2V0KCB0aGlzLCBrZXkgKTtcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdHZhciBkYXRhLFxuXHRcdFx0XHRjYW1lbEtleSA9IGpRdWVyeS5jYW1lbENhc2UoIGtleSApO1xuXG5cdFx0XHQvLyBUaGUgY2FsbGluZyBqUXVlcnkgb2JqZWN0IChlbGVtZW50IG1hdGNoZXMpIGlzIG5vdCBlbXB0eVxuXHRcdFx0Ly8gKGFuZCB0aGVyZWZvcmUgaGFzIGFuIGVsZW1lbnQgYXBwZWFycyBhdCB0aGlzWyAwIF0pIGFuZCB0aGVcblx0XHRcdC8vIGB2YWx1ZWAgcGFyYW1ldGVyIHdhcyBub3QgdW5kZWZpbmVkLiBBbiBlbXB0eSBqUXVlcnkgb2JqZWN0XG5cdFx0XHQvLyB3aWxsIHJlc3VsdCBpbiBgdW5kZWZpbmVkYCBmb3IgZWxlbSA9IHRoaXNbIDAgXSB3aGljaCB3aWxsXG5cdFx0XHQvLyB0aHJvdyBhbiBleGNlcHRpb24gaWYgYW4gYXR0ZW1wdCB0byByZWFkIGEgZGF0YSBjYWNoZSBpcyBtYWRlLlxuXHRcdFx0aWYgKCBlbGVtICYmIHZhbHVlID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdC8vIEF0dGVtcHQgdG8gZ2V0IGRhdGEgZnJvbSB0aGUgY2FjaGVcblx0XHRcdFx0Ly8gd2l0aCB0aGUga2V5IGFzLWlzXG5cdFx0XHRcdGRhdGEgPSBkYXRhX3VzZXIuZ2V0KCBlbGVtLCBrZXkgKTtcblx0XHRcdFx0aWYgKCBkYXRhICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBBdHRlbXB0IHRvIGdldCBkYXRhIGZyb20gdGhlIGNhY2hlXG5cdFx0XHRcdC8vIHdpdGggdGhlIGtleSBjYW1lbGl6ZWRcblx0XHRcdFx0ZGF0YSA9IGRhdGFfdXNlci5nZXQoIGVsZW0sIGNhbWVsS2V5ICk7XG5cdFx0XHRcdGlmICggZGF0YSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdHJldHVybiBkYXRhO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQXR0ZW1wdCB0byBcImRpc2NvdmVyXCIgdGhlIGRhdGEgaW5cblx0XHRcdFx0Ly8gSFRNTDUgY3VzdG9tIGRhdGEtKiBhdHRyc1xuXHRcdFx0XHRkYXRhID0gZGF0YUF0dHIoIGVsZW0sIGNhbWVsS2V5LCB1bmRlZmluZWQgKTtcblx0XHRcdFx0aWYgKCBkYXRhICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBXZSB0cmllZCByZWFsbHkgaGFyZCwgYnV0IHRoZSBkYXRhIGRvZXNuJ3QgZXhpc3QuXG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IHRoZSBkYXRhLi4uXG5cdFx0XHR0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdC8vIEZpcnN0LCBhdHRlbXB0IHRvIHN0b3JlIGEgY29weSBvciByZWZlcmVuY2Ugb2YgYW55XG5cdFx0XHRcdC8vIGRhdGEgdGhhdCBtaWdodCd2ZSBiZWVuIHN0b3JlIHdpdGggYSBjYW1lbENhc2VkIGtleS5cblx0XHRcdFx0dmFyIGRhdGEgPSBkYXRhX3VzZXIuZ2V0KCB0aGlzLCBjYW1lbEtleSApO1xuXG5cdFx0XHRcdC8vIEZvciBIVE1MNSBkYXRhLSogYXR0cmlidXRlIGludGVyb3AsIHdlIGhhdmUgdG9cblx0XHRcdFx0Ly8gc3RvcmUgcHJvcGVydHkgbmFtZXMgd2l0aCBkYXNoZXMgaW4gYSBjYW1lbENhc2UgZm9ybS5cblx0XHRcdFx0Ly8gVGhpcyBtaWdodCBub3QgYXBwbHkgdG8gYWxsIHByb3BlcnRpZXMuLi4qXG5cdFx0XHRcdGRhdGFfdXNlci5zZXQoIHRoaXMsIGNhbWVsS2V5LCB2YWx1ZSApO1xuXG5cdFx0XHRcdC8vICouLi4gSW4gdGhlIGNhc2Ugb2YgcHJvcGVydGllcyB0aGF0IG1pZ2h0IF9hY3R1YWxseV9cblx0XHRcdFx0Ly8gaGF2ZSBkYXNoZXMsIHdlIG5lZWQgdG8gYWxzbyBzdG9yZSBhIGNvcHkgb2YgdGhhdFxuXHRcdFx0XHQvLyB1bmNoYW5nZWQgcHJvcGVydHkuXG5cdFx0XHRcdGlmICgga2V5LmluZGV4T2YoXCItXCIpICE9PSAtMSAmJiBkYXRhICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0ZGF0YV91c2VyLnNldCggdGhpcywga2V5LCB2YWx1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9LCBudWxsLCB2YWx1ZSwgYXJndW1lbnRzLmxlbmd0aCA+IDEsIG51bGwsIHRydWUgKTtcblx0fSxcblxuXHRyZW1vdmVEYXRhOiBmdW5jdGlvbigga2V5ICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRkYXRhX3VzZXIucmVtb3ZlKCB0aGlzLCBrZXkgKTtcblx0XHR9KTtcblx0fVxufSk7XG5cblxualF1ZXJ5LmV4dGVuZCh7XG5cdHF1ZXVlOiBmdW5jdGlvbiggZWxlbSwgdHlwZSwgZGF0YSApIHtcblx0XHR2YXIgcXVldWU7XG5cblx0XHRpZiAoIGVsZW0gKSB7XG5cdFx0XHR0eXBlID0gKCB0eXBlIHx8IFwiZnhcIiApICsgXCJxdWV1ZVwiO1xuXHRcdFx0cXVldWUgPSBkYXRhX3ByaXYuZ2V0KCBlbGVtLCB0eXBlICk7XG5cblx0XHRcdC8vIFNwZWVkIHVwIGRlcXVldWUgYnkgZ2V0dGluZyBvdXQgcXVpY2tseSBpZiB0aGlzIGlzIGp1c3QgYSBsb29rdXBcblx0XHRcdGlmICggZGF0YSApIHtcblx0XHRcdFx0aWYgKCAhcXVldWUgfHwgalF1ZXJ5LmlzQXJyYXkoIGRhdGEgKSApIHtcblx0XHRcdFx0XHRxdWV1ZSA9IGRhdGFfcHJpdi5hY2Nlc3MoIGVsZW0sIHR5cGUsIGpRdWVyeS5tYWtlQXJyYXkoZGF0YSkgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRxdWV1ZS5wdXNoKCBkYXRhICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBxdWV1ZSB8fCBbXTtcblx0XHR9XG5cdH0sXG5cblx0ZGVxdWV1ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGUgKSB7XG5cdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdFx0dmFyIHF1ZXVlID0galF1ZXJ5LnF1ZXVlKCBlbGVtLCB0eXBlICksXG5cdFx0XHRzdGFydExlbmd0aCA9IHF1ZXVlLmxlbmd0aCxcblx0XHRcdGZuID0gcXVldWUuc2hpZnQoKSxcblx0XHRcdGhvb2tzID0galF1ZXJ5Ll9xdWV1ZUhvb2tzKCBlbGVtLCB0eXBlICksXG5cdFx0XHRuZXh0ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGpRdWVyeS5kZXF1ZXVlKCBlbGVtLCB0eXBlICk7XG5cdFx0XHR9O1xuXG5cdFx0Ly8gSWYgdGhlIGZ4IHF1ZXVlIGlzIGRlcXVldWVkLCBhbHdheXMgcmVtb3ZlIHRoZSBwcm9ncmVzcyBzZW50aW5lbFxuXHRcdGlmICggZm4gPT09IFwiaW5wcm9ncmVzc1wiICkge1xuXHRcdFx0Zm4gPSBxdWV1ZS5zaGlmdCgpO1xuXHRcdFx0c3RhcnRMZW5ndGgtLTtcblx0XHR9XG5cblx0XHRpZiAoIGZuICkge1xuXG5cdFx0XHQvLyBBZGQgYSBwcm9ncmVzcyBzZW50aW5lbCB0byBwcmV2ZW50IHRoZSBmeCBxdWV1ZSBmcm9tIGJlaW5nXG5cdFx0XHQvLyBhdXRvbWF0aWNhbGx5IGRlcXVldWVkXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwiZnhcIiApIHtcblx0XHRcdFx0cXVldWUudW5zaGlmdCggXCJpbnByb2dyZXNzXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ2xlYXIgdXAgdGhlIGxhc3QgcXVldWUgc3RvcCBmdW5jdGlvblxuXHRcdFx0ZGVsZXRlIGhvb2tzLnN0b3A7XG5cdFx0XHRmbi5jYWxsKCBlbGVtLCBuZXh0LCBob29rcyApO1xuXHRcdH1cblxuXHRcdGlmICggIXN0YXJ0TGVuZ3RoICYmIGhvb2tzICkge1xuXHRcdFx0aG9va3MuZW1wdHkuZmlyZSgpO1xuXHRcdH1cblx0fSxcblxuXHQvLyBOb3QgcHVibGljIC0gZ2VuZXJhdGUgYSBxdWV1ZUhvb2tzIG9iamVjdCwgb3IgcmV0dXJuIHRoZSBjdXJyZW50IG9uZVxuXHRfcXVldWVIb29rczogZnVuY3Rpb24oIGVsZW0sIHR5cGUgKSB7XG5cdFx0dmFyIGtleSA9IHR5cGUgKyBcInF1ZXVlSG9va3NcIjtcblx0XHRyZXR1cm4gZGF0YV9wcml2LmdldCggZWxlbSwga2V5ICkgfHwgZGF0YV9wcml2LmFjY2VzcyggZWxlbSwga2V5LCB7XG5cdFx0XHRlbXB0eTogalF1ZXJ5LkNhbGxiYWNrcyhcIm9uY2UgbWVtb3J5XCIpLmFkZChmdW5jdGlvbigpIHtcblx0XHRcdFx0ZGF0YV9wcml2LnJlbW92ZSggZWxlbSwgWyB0eXBlICsgXCJxdWV1ZVwiLCBrZXkgXSApO1xuXHRcdFx0fSlcblx0XHR9KTtcblx0fVxufSk7XG5cbmpRdWVyeS5mbi5leHRlbmQoe1xuXHRxdWV1ZTogZnVuY3Rpb24oIHR5cGUsIGRhdGEgKSB7XG5cdFx0dmFyIHNldHRlciA9IDI7XG5cblx0XHRpZiAoIHR5cGVvZiB0eXBlICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0ZGF0YSA9IHR5cGU7XG5cdFx0XHR0eXBlID0gXCJmeFwiO1xuXHRcdFx0c2V0dGVyLS07XG5cdFx0fVxuXG5cdFx0aWYgKCBhcmd1bWVudHMubGVuZ3RoIDwgc2V0dGVyICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5xdWV1ZSggdGhpc1swXSwgdHlwZSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBkYXRhID09PSB1bmRlZmluZWQgP1xuXHRcdFx0dGhpcyA6XG5cdFx0XHR0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBxdWV1ZSA9IGpRdWVyeS5xdWV1ZSggdGhpcywgdHlwZSwgZGF0YSApO1xuXG5cdFx0XHRcdC8vIEVuc3VyZSBhIGhvb2tzIGZvciB0aGlzIHF1ZXVlXG5cdFx0XHRcdGpRdWVyeS5fcXVldWVIb29rcyggdGhpcywgdHlwZSApO1xuXG5cdFx0XHRcdGlmICggdHlwZSA9PT0gXCJmeFwiICYmIHF1ZXVlWzBdICE9PSBcImlucHJvZ3Jlc3NcIiApIHtcblx0XHRcdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgdHlwZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0fSxcblx0ZGVxdWV1ZTogZnVuY3Rpb24oIHR5cGUgKSB7XG5cdFx0cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeS5kZXF1ZXVlKCB0aGlzLCB0eXBlICk7XG5cdFx0fSk7XG5cdH0sXG5cdGNsZWFyUXVldWU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdHJldHVybiB0aGlzLnF1ZXVlKCB0eXBlIHx8IFwiZnhcIiwgW10gKTtcblx0fSxcblx0Ly8gR2V0IGEgcHJvbWlzZSByZXNvbHZlZCB3aGVuIHF1ZXVlcyBvZiBhIGNlcnRhaW4gdHlwZVxuXHQvLyBhcmUgZW1wdGllZCAoZnggaXMgdGhlIHR5cGUgYnkgZGVmYXVsdClcblx0cHJvbWlzZTogZnVuY3Rpb24oIHR5cGUsIG9iaiApIHtcblx0XHR2YXIgdG1wLFxuXHRcdFx0Y291bnQgPSAxLFxuXHRcdFx0ZGVmZXIgPSBqUXVlcnkuRGVmZXJyZWQoKSxcblx0XHRcdGVsZW1lbnRzID0gdGhpcyxcblx0XHRcdGkgPSB0aGlzLmxlbmd0aCxcblx0XHRcdHJlc29sdmUgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCAhKCAtLWNvdW50ICkgKSB7XG5cdFx0XHRcdFx0ZGVmZXIucmVzb2x2ZVdpdGgoIGVsZW1lbnRzLCBbIGVsZW1lbnRzIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblxuXHRcdGlmICggdHlwZW9mIHR5cGUgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRvYmogPSB0eXBlO1xuXHRcdFx0dHlwZSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHR0bXAgPSBkYXRhX3ByaXYuZ2V0KCBlbGVtZW50c1sgaSBdLCB0eXBlICsgXCJxdWV1ZUhvb2tzXCIgKTtcblx0XHRcdGlmICggdG1wICYmIHRtcC5lbXB0eSApIHtcblx0XHRcdFx0Y291bnQrKztcblx0XHRcdFx0dG1wLmVtcHR5LmFkZCggcmVzb2x2ZSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXNvbHZlKCk7XG5cdFx0cmV0dXJuIGRlZmVyLnByb21pc2UoIG9iaiApO1xuXHR9XG59KTtcbnZhciBwbnVtID0gKC9bKy1dPyg/OlxcZCpcXC58KVxcZCsoPzpbZUVdWystXT9cXGQrfCkvKS5zb3VyY2U7XG5cbnZhciBjc3NFeHBhbmQgPSBbIFwiVG9wXCIsIFwiUmlnaHRcIiwgXCJCb3R0b21cIiwgXCJMZWZ0XCIgXTtcblxudmFyIGlzSGlkZGVuID0gZnVuY3Rpb24oIGVsZW0sIGVsICkge1xuXHRcdC8vIGlzSGlkZGVuIG1pZ2h0IGJlIGNhbGxlZCBmcm9tIGpRdWVyeSNmaWx0ZXIgZnVuY3Rpb247XG5cdFx0Ly8gaW4gdGhhdCBjYXNlLCBlbGVtZW50IHdpbGwgYmUgc2Vjb25kIGFyZ3VtZW50XG5cdFx0ZWxlbSA9IGVsIHx8IGVsZW07XG5cdFx0cmV0dXJuIGpRdWVyeS5jc3MoIGVsZW0sIFwiZGlzcGxheVwiICkgPT09IFwibm9uZVwiIHx8ICFqUXVlcnkuY29udGFpbnMoIGVsZW0ub3duZXJEb2N1bWVudCwgZWxlbSApO1xuXHR9O1xuXG52YXIgcmNoZWNrYWJsZVR5cGUgPSAoL14oPzpjaGVja2JveHxyYWRpbykkL2kpO1xuXG5cblxuKGZ1bmN0aW9uKCkge1xuXHR2YXIgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCksXG5cdFx0ZGl2ID0gZnJhZ21lbnQuYXBwZW5kQ2hpbGQoIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiZGl2XCIgKSApLFxuXHRcdGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJpbnB1dFwiICk7XG5cblx0Ly8gU3VwcG9ydDogU2FmYXJpPD01LjFcblx0Ly8gQ2hlY2sgc3RhdGUgbG9zdCBpZiB0aGUgbmFtZSBpcyBzZXQgKCMxMTIxNylcblx0Ly8gU3VwcG9ydDogV2luZG93cyBXZWIgQXBwcyAoV1dBKVxuXHQvLyBgbmFtZWAgYW5kIGB0eXBlYCBtdXN0IHVzZSAuc2V0QXR0cmlidXRlIGZvciBXV0EgKCMxNDkwMSlcblx0aW5wdXQuc2V0QXR0cmlidXRlKCBcInR5cGVcIiwgXCJyYWRpb1wiICk7XG5cdGlucHV0LnNldEF0dHJpYnV0ZSggXCJjaGVja2VkXCIsIFwiY2hlY2tlZFwiICk7XG5cdGlucHV0LnNldEF0dHJpYnV0ZSggXCJuYW1lXCIsIFwidFwiICk7XG5cblx0ZGl2LmFwcGVuZENoaWxkKCBpbnB1dCApO1xuXG5cdC8vIFN1cHBvcnQ6IFNhZmFyaTw9NS4xLCBBbmRyb2lkPDQuMlxuXHQvLyBPbGRlciBXZWJLaXQgZG9lc24ndCBjbG9uZSBjaGVja2VkIHN0YXRlIGNvcnJlY3RseSBpbiBmcmFnbWVudHNcblx0c3VwcG9ydC5jaGVja0Nsb25lID0gZGl2LmNsb25lTm9kZSggdHJ1ZSApLmNsb25lTm9kZSggdHJ1ZSApLmxhc3RDaGlsZC5jaGVja2VkO1xuXG5cdC8vIFN1cHBvcnQ6IElFPD0xMStcblx0Ly8gTWFrZSBzdXJlIHRleHRhcmVhIChhbmQgY2hlY2tib3gpIGRlZmF1bHRWYWx1ZSBpcyBwcm9wZXJseSBjbG9uZWRcblx0ZGl2LmlubmVySFRNTCA9IFwiPHRleHRhcmVhPng8L3RleHRhcmVhPlwiO1xuXHRzdXBwb3J0Lm5vQ2xvbmVDaGVja2VkID0gISFkaXYuY2xvbmVOb2RlKCB0cnVlICkubGFzdENoaWxkLmRlZmF1bHRWYWx1ZTtcbn0pKCk7XG52YXIgc3RydW5kZWZpbmVkID0gdHlwZW9mIHVuZGVmaW5lZDtcblxuXG5cbnN1cHBvcnQuZm9jdXNpbkJ1YmJsZXMgPSBcIm9uZm9jdXNpblwiIGluIHdpbmRvdztcblxuXG52YXJcblx0cmtleUV2ZW50ID0gL15rZXkvLFxuXHRybW91c2VFdmVudCA9IC9eKD86bW91c2V8cG9pbnRlcnxjb250ZXh0bWVudSl8Y2xpY2svLFxuXHRyZm9jdXNNb3JwaCA9IC9eKD86Zm9jdXNpbmZvY3VzfGZvY3Vzb3V0Ymx1cikkLyxcblx0cnR5cGVuYW1lc3BhY2UgPSAvXihbXi5dKikoPzpcXC4oLispfCkkLztcblxuZnVuY3Rpb24gcmV0dXJuVHJ1ZSgpIHtcblx0cmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIHJldHVybkZhbHNlKCkge1xuXHRyZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHNhZmVBY3RpdmVFbGVtZW50KCkge1xuXHR0cnkge1xuXHRcdHJldHVybiBkb2N1bWVudC5hY3RpdmVFbGVtZW50O1xuXHR9IGNhdGNoICggZXJyICkgeyB9XG59XG5cbi8qXG4gKiBIZWxwZXIgZnVuY3Rpb25zIGZvciBtYW5hZ2luZyBldmVudHMgLS0gbm90IHBhcnQgb2YgdGhlIHB1YmxpYyBpbnRlcmZhY2UuXG4gKiBQcm9wcyB0byBEZWFuIEVkd2FyZHMnIGFkZEV2ZW50IGxpYnJhcnkgZm9yIG1hbnkgb2YgdGhlIGlkZWFzLlxuICovXG5qUXVlcnkuZXZlbnQgPSB7XG5cblx0Z2xvYmFsOiB7fSxcblxuXHRhZGQ6IGZ1bmN0aW9uKCBlbGVtLCB0eXBlcywgaGFuZGxlciwgZGF0YSwgc2VsZWN0b3IgKSB7XG5cblx0XHR2YXIgaGFuZGxlT2JqSW4sIGV2ZW50SGFuZGxlLCB0bXAsXG5cdFx0XHRldmVudHMsIHQsIGhhbmRsZU9iaixcblx0XHRcdHNwZWNpYWwsIGhhbmRsZXJzLCB0eXBlLCBuYW1lc3BhY2VzLCBvcmlnVHlwZSxcblx0XHRcdGVsZW1EYXRhID0gZGF0YV9wcml2LmdldCggZWxlbSApO1xuXG5cdFx0Ly8gRG9uJ3QgYXR0YWNoIGV2ZW50cyB0byBub0RhdGEgb3IgdGV4dC9jb21tZW50IG5vZGVzIChidXQgYWxsb3cgcGxhaW4gb2JqZWN0cylcblx0XHRpZiAoICFlbGVtRGF0YSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBDYWxsZXIgY2FuIHBhc3MgaW4gYW4gb2JqZWN0IG9mIGN1c3RvbSBkYXRhIGluIGxpZXUgb2YgdGhlIGhhbmRsZXJcblx0XHRpZiAoIGhhbmRsZXIuaGFuZGxlciApIHtcblx0XHRcdGhhbmRsZU9iakluID0gaGFuZGxlcjtcblx0XHRcdGhhbmRsZXIgPSBoYW5kbGVPYmpJbi5oYW5kbGVyO1xuXHRcdFx0c2VsZWN0b3IgPSBoYW5kbGVPYmpJbi5zZWxlY3Rvcjtcblx0XHR9XG5cblx0XHQvLyBNYWtlIHN1cmUgdGhhdCB0aGUgaGFuZGxlciBoYXMgYSB1bmlxdWUgSUQsIHVzZWQgdG8gZmluZC9yZW1vdmUgaXQgbGF0ZXJcblx0XHRpZiAoICFoYW5kbGVyLmd1aWQgKSB7XG5cdFx0XHRoYW5kbGVyLmd1aWQgPSBqUXVlcnkuZ3VpZCsrO1xuXHRcdH1cblxuXHRcdC8vIEluaXQgdGhlIGVsZW1lbnQncyBldmVudCBzdHJ1Y3R1cmUgYW5kIG1haW4gaGFuZGxlciwgaWYgdGhpcyBpcyB0aGUgZmlyc3Rcblx0XHRpZiAoICEoZXZlbnRzID0gZWxlbURhdGEuZXZlbnRzKSApIHtcblx0XHRcdGV2ZW50cyA9IGVsZW1EYXRhLmV2ZW50cyA9IHt9O1xuXHRcdH1cblx0XHRpZiAoICEoZXZlbnRIYW5kbGUgPSBlbGVtRGF0YS5oYW5kbGUpICkge1xuXHRcdFx0ZXZlbnRIYW5kbGUgPSBlbGVtRGF0YS5oYW5kbGUgPSBmdW5jdGlvbiggZSApIHtcblx0XHRcdFx0Ly8gRGlzY2FyZCB0aGUgc2Vjb25kIGV2ZW50IG9mIGEgalF1ZXJ5LmV2ZW50LnRyaWdnZXIoKSBhbmRcblx0XHRcdFx0Ly8gd2hlbiBhbiBldmVudCBpcyBjYWxsZWQgYWZ0ZXIgYSBwYWdlIGhhcyB1bmxvYWRlZFxuXHRcdFx0XHRyZXR1cm4gdHlwZW9mIGpRdWVyeSAhPT0gc3RydW5kZWZpbmVkICYmIGpRdWVyeS5ldmVudC50cmlnZ2VyZWQgIT09IGUudHlwZSA/XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LmRpc3BhdGNoLmFwcGx5KCBlbGVtLCBhcmd1bWVudHMgKSA6IHVuZGVmaW5lZDtcblx0XHRcdH07XG5cdFx0fVxuXG5cdFx0Ly8gSGFuZGxlIG11bHRpcGxlIGV2ZW50cyBzZXBhcmF0ZWQgYnkgYSBzcGFjZVxuXHRcdHR5cGVzID0gKCB0eXBlcyB8fCBcIlwiICkubWF0Y2goIHJub3R3aGl0ZSApIHx8IFsgXCJcIiBdO1xuXHRcdHQgPSB0eXBlcy5sZW5ndGg7XG5cdFx0d2hpbGUgKCB0LS0gKSB7XG5cdFx0XHR0bXAgPSBydHlwZW5hbWVzcGFjZS5leGVjKCB0eXBlc1t0XSApIHx8IFtdO1xuXHRcdFx0dHlwZSA9IG9yaWdUeXBlID0gdG1wWzFdO1xuXHRcdFx0bmFtZXNwYWNlcyA9ICggdG1wWzJdIHx8IFwiXCIgKS5zcGxpdCggXCIuXCIgKS5zb3J0KCk7XG5cblx0XHRcdC8vIFRoZXJlICptdXN0KiBiZSBhIHR5cGUsIG5vIGF0dGFjaGluZyBuYW1lc3BhY2Utb25seSBoYW5kbGVyc1xuXHRcdFx0aWYgKCAhdHlwZSApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIGV2ZW50IGNoYW5nZXMgaXRzIHR5cGUsIHVzZSB0aGUgc3BlY2lhbCBldmVudCBoYW5kbGVycyBmb3IgdGhlIGNoYW5nZWQgdHlwZVxuXHRcdFx0c3BlY2lhbCA9IGpRdWVyeS5ldmVudC5zcGVjaWFsWyB0eXBlIF0gfHwge307XG5cblx0XHRcdC8vIElmIHNlbGVjdG9yIGRlZmluZWQsIGRldGVybWluZSBzcGVjaWFsIGV2ZW50IGFwaSB0eXBlLCBvdGhlcndpc2UgZ2l2ZW4gdHlwZVxuXHRcdFx0dHlwZSA9ICggc2VsZWN0b3IgPyBzcGVjaWFsLmRlbGVnYXRlVHlwZSA6IHNwZWNpYWwuYmluZFR5cGUgKSB8fCB0eXBlO1xuXG5cdFx0XHQvLyBVcGRhdGUgc3BlY2lhbCBiYXNlZCBvbiBuZXdseSByZXNldCB0eXBlXG5cdFx0XHRzcGVjaWFsID0galF1ZXJ5LmV2ZW50LnNwZWNpYWxbIHR5cGUgXSB8fCB7fTtcblxuXHRcdFx0Ly8gaGFuZGxlT2JqIGlzIHBhc3NlZCB0byBhbGwgZXZlbnQgaGFuZGxlcnNcblx0XHRcdGhhbmRsZU9iaiA9IGpRdWVyeS5leHRlbmQoe1xuXHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRvcmlnVHlwZTogb3JpZ1R5cGUsXG5cdFx0XHRcdGRhdGE6IGRhdGEsXG5cdFx0XHRcdGhhbmRsZXI6IGhhbmRsZXIsXG5cdFx0XHRcdGd1aWQ6IGhhbmRsZXIuZ3VpZCxcblx0XHRcdFx0c2VsZWN0b3I6IHNlbGVjdG9yLFxuXHRcdFx0XHRuZWVkc0NvbnRleHQ6IHNlbGVjdG9yICYmIGpRdWVyeS5leHByLm1hdGNoLm5lZWRzQ29udGV4dC50ZXN0KCBzZWxlY3RvciApLFxuXHRcdFx0XHRuYW1lc3BhY2U6IG5hbWVzcGFjZXMuam9pbihcIi5cIilcblx0XHRcdH0sIGhhbmRsZU9iakluICk7XG5cblx0XHRcdC8vIEluaXQgdGhlIGV2ZW50IGhhbmRsZXIgcXVldWUgaWYgd2UncmUgdGhlIGZpcnN0XG5cdFx0XHRpZiAoICEoaGFuZGxlcnMgPSBldmVudHNbIHR5cGUgXSkgKSB7XG5cdFx0XHRcdGhhbmRsZXJzID0gZXZlbnRzWyB0eXBlIF0gPSBbXTtcblx0XHRcdFx0aGFuZGxlcnMuZGVsZWdhdGVDb3VudCA9IDA7XG5cblx0XHRcdFx0Ly8gT25seSB1c2UgYWRkRXZlbnRMaXN0ZW5lciBpZiB0aGUgc3BlY2lhbCBldmVudHMgaGFuZGxlciByZXR1cm5zIGZhbHNlXG5cdFx0XHRcdGlmICggIXNwZWNpYWwuc2V0dXAgfHwgc3BlY2lhbC5zZXR1cC5jYWxsKCBlbGVtLCBkYXRhLCBuYW1lc3BhY2VzLCBldmVudEhhbmRsZSApID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRpZiAoIGVsZW0uYWRkRXZlbnRMaXN0ZW5lciApIHtcblx0XHRcdFx0XHRcdGVsZW0uYWRkRXZlbnRMaXN0ZW5lciggdHlwZSwgZXZlbnRIYW5kbGUsIGZhbHNlICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICggc3BlY2lhbC5hZGQgKSB7XG5cdFx0XHRcdHNwZWNpYWwuYWRkLmNhbGwoIGVsZW0sIGhhbmRsZU9iaiApO1xuXG5cdFx0XHRcdGlmICggIWhhbmRsZU9iai5oYW5kbGVyLmd1aWQgKSB7XG5cdFx0XHRcdFx0aGFuZGxlT2JqLmhhbmRsZXIuZ3VpZCA9IGhhbmRsZXIuZ3VpZDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBBZGQgdG8gdGhlIGVsZW1lbnQncyBoYW5kbGVyIGxpc3QsIGRlbGVnYXRlcyBpbiBmcm9udFxuXHRcdFx0aWYgKCBzZWxlY3RvciApIHtcblx0XHRcdFx0aGFuZGxlcnMuc3BsaWNlKCBoYW5kbGVycy5kZWxlZ2F0ZUNvdW50KyssIDAsIGhhbmRsZU9iaiApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aGFuZGxlcnMucHVzaCggaGFuZGxlT2JqICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEtlZXAgdHJhY2sgb2Ygd2hpY2ggZXZlbnRzIGhhdmUgZXZlciBiZWVuIHVzZWQsIGZvciBldmVudCBvcHRpbWl6YXRpb25cblx0XHRcdGpRdWVyeS5ldmVudC5nbG9iYWxbIHR5cGUgXSA9IHRydWU7XG5cdFx0fVxuXG5cdH0sXG5cblx0Ly8gRGV0YWNoIGFuIGV2ZW50IG9yIHNldCBvZiBldmVudHMgZnJvbSBhbiBlbGVtZW50XG5cdHJlbW92ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGVzLCBoYW5kbGVyLCBzZWxlY3RvciwgbWFwcGVkVHlwZXMgKSB7XG5cblx0XHR2YXIgaiwgb3JpZ0NvdW50LCB0bXAsXG5cdFx0XHRldmVudHMsIHQsIGhhbmRsZU9iaixcblx0XHRcdHNwZWNpYWwsIGhhbmRsZXJzLCB0eXBlLCBuYW1lc3BhY2VzLCBvcmlnVHlwZSxcblx0XHRcdGVsZW1EYXRhID0gZGF0YV9wcml2Lmhhc0RhdGEoIGVsZW0gKSAmJiBkYXRhX3ByaXYuZ2V0KCBlbGVtICk7XG5cblx0XHRpZiAoICFlbGVtRGF0YSB8fCAhKGV2ZW50cyA9IGVsZW1EYXRhLmV2ZW50cykgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gT25jZSBmb3IgZWFjaCB0eXBlLm5hbWVzcGFjZSBpbiB0eXBlczsgdHlwZSBtYXkgYmUgb21pdHRlZFxuXHRcdHR5cGVzID0gKCB0eXBlcyB8fCBcIlwiICkubWF0Y2goIHJub3R3aGl0ZSApIHx8IFsgXCJcIiBdO1xuXHRcdHQgPSB0eXBlcy5sZW5ndGg7XG5cdFx0d2hpbGUgKCB0LS0gKSB7XG5cdFx0XHR0bXAgPSBydHlwZW5hbWVzcGFjZS5leGVjKCB0eXBlc1t0XSApIHx8IFtdO1xuXHRcdFx0dHlwZSA9IG9yaWdUeXBlID0gdG1wWzFdO1xuXHRcdFx0bmFtZXNwYWNlcyA9ICggdG1wWzJdIHx8IFwiXCIgKS5zcGxpdCggXCIuXCIgKS5zb3J0KCk7XG5cblx0XHRcdC8vIFVuYmluZCBhbGwgZXZlbnRzIChvbiB0aGlzIG5hbWVzcGFjZSwgaWYgcHJvdmlkZWQpIGZvciB0aGUgZWxlbWVudFxuXHRcdFx0aWYgKCAhdHlwZSApIHtcblx0XHRcdFx0Zm9yICggdHlwZSBpbiBldmVudHMgKSB7XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnJlbW92ZSggZWxlbSwgdHlwZSArIHR5cGVzWyB0IF0sIGhhbmRsZXIsIHNlbGVjdG9yLCB0cnVlICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgdHlwZSBdIHx8IHt9O1xuXHRcdFx0dHlwZSA9ICggc2VsZWN0b3IgPyBzcGVjaWFsLmRlbGVnYXRlVHlwZSA6IHNwZWNpYWwuYmluZFR5cGUgKSB8fCB0eXBlO1xuXHRcdFx0aGFuZGxlcnMgPSBldmVudHNbIHR5cGUgXSB8fCBbXTtcblx0XHRcdHRtcCA9IHRtcFsyXSAmJiBuZXcgUmVnRXhwKCBcIihefFxcXFwuKVwiICsgbmFtZXNwYWNlcy5qb2luKFwiXFxcXC4oPzouKlxcXFwufClcIikgKyBcIihcXFxcLnwkKVwiICk7XG5cblx0XHRcdC8vIFJlbW92ZSBtYXRjaGluZyBldmVudHNcblx0XHRcdG9yaWdDb3VudCA9IGogPSBoYW5kbGVycy5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdFx0aGFuZGxlT2JqID0gaGFuZGxlcnNbIGogXTtcblxuXHRcdFx0XHRpZiAoICggbWFwcGVkVHlwZXMgfHwgb3JpZ1R5cGUgPT09IGhhbmRsZU9iai5vcmlnVHlwZSApICYmXG5cdFx0XHRcdFx0KCAhaGFuZGxlciB8fCBoYW5kbGVyLmd1aWQgPT09IGhhbmRsZU9iai5ndWlkICkgJiZcblx0XHRcdFx0XHQoICF0bXAgfHwgdG1wLnRlc3QoIGhhbmRsZU9iai5uYW1lc3BhY2UgKSApICYmXG5cdFx0XHRcdFx0KCAhc2VsZWN0b3IgfHwgc2VsZWN0b3IgPT09IGhhbmRsZU9iai5zZWxlY3RvciB8fCBzZWxlY3RvciA9PT0gXCIqKlwiICYmIGhhbmRsZU9iai5zZWxlY3RvciApICkge1xuXHRcdFx0XHRcdGhhbmRsZXJzLnNwbGljZSggaiwgMSApO1xuXG5cdFx0XHRcdFx0aWYgKCBoYW5kbGVPYmouc2VsZWN0b3IgKSB7XG5cdFx0XHRcdFx0XHRoYW5kbGVycy5kZWxlZ2F0ZUNvdW50LS07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggc3BlY2lhbC5yZW1vdmUgKSB7XG5cdFx0XHRcdFx0XHRzcGVjaWFsLnJlbW92ZS5jYWxsKCBlbGVtLCBoYW5kbGVPYmogKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gUmVtb3ZlIGdlbmVyaWMgZXZlbnQgaGFuZGxlciBpZiB3ZSByZW1vdmVkIHNvbWV0aGluZyBhbmQgbm8gbW9yZSBoYW5kbGVycyBleGlzdFxuXHRcdFx0Ly8gKGF2b2lkcyBwb3RlbnRpYWwgZm9yIGVuZGxlc3MgcmVjdXJzaW9uIGR1cmluZyByZW1vdmFsIG9mIHNwZWNpYWwgZXZlbnQgaGFuZGxlcnMpXG5cdFx0XHRpZiAoIG9yaWdDb3VudCAmJiAhaGFuZGxlcnMubGVuZ3RoICkge1xuXHRcdFx0XHRpZiAoICFzcGVjaWFsLnRlYXJkb3duIHx8IHNwZWNpYWwudGVhcmRvd24uY2FsbCggZWxlbSwgbmFtZXNwYWNlcywgZWxlbURhdGEuaGFuZGxlICkgPT09IGZhbHNlICkge1xuXHRcdFx0XHRcdGpRdWVyeS5yZW1vdmVFdmVudCggZWxlbSwgdHlwZSwgZWxlbURhdGEuaGFuZGxlICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRkZWxldGUgZXZlbnRzWyB0eXBlIF07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUmVtb3ZlIHRoZSBleHBhbmRvIGlmIGl0J3Mgbm8gbG9uZ2VyIHVzZWRcblx0XHRpZiAoIGpRdWVyeS5pc0VtcHR5T2JqZWN0KCBldmVudHMgKSApIHtcblx0XHRcdGRlbGV0ZSBlbGVtRGF0YS5oYW5kbGU7XG5cdFx0XHRkYXRhX3ByaXYucmVtb3ZlKCBlbGVtLCBcImV2ZW50c1wiICk7XG5cdFx0fVxuXHR9LFxuXG5cdHRyaWdnZXI6IGZ1bmN0aW9uKCBldmVudCwgZGF0YSwgZWxlbSwgb25seUhhbmRsZXJzICkge1xuXG5cdFx0dmFyIGksIGN1ciwgdG1wLCBidWJibGVUeXBlLCBvbnR5cGUsIGhhbmRsZSwgc3BlY2lhbCxcblx0XHRcdGV2ZW50UGF0aCA9IFsgZWxlbSB8fCBkb2N1bWVudCBdLFxuXHRcdFx0dHlwZSA9IGhhc093bi5jYWxsKCBldmVudCwgXCJ0eXBlXCIgKSA/IGV2ZW50LnR5cGUgOiBldmVudCxcblx0XHRcdG5hbWVzcGFjZXMgPSBoYXNPd24uY2FsbCggZXZlbnQsIFwibmFtZXNwYWNlXCIgKSA/IGV2ZW50Lm5hbWVzcGFjZS5zcGxpdChcIi5cIikgOiBbXTtcblxuXHRcdGN1ciA9IHRtcCA9IGVsZW0gPSBlbGVtIHx8IGRvY3VtZW50O1xuXG5cdFx0Ly8gRG9uJ3QgZG8gZXZlbnRzIG9uIHRleHQgYW5kIGNvbW1lbnQgbm9kZXNcblx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDMgfHwgZWxlbS5ub2RlVHlwZSA9PT0gOCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBmb2N1cy9ibHVyIG1vcnBocyB0byBmb2N1c2luL291dDsgZW5zdXJlIHdlJ3JlIG5vdCBmaXJpbmcgdGhlbSByaWdodCBub3dcblx0XHRpZiAoIHJmb2N1c01vcnBoLnRlc3QoIHR5cGUgKyBqUXVlcnkuZXZlbnQudHJpZ2dlcmVkICkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCB0eXBlLmluZGV4T2YoXCIuXCIpID49IDAgKSB7XG5cdFx0XHQvLyBOYW1lc3BhY2VkIHRyaWdnZXI7IGNyZWF0ZSBhIHJlZ2V4cCB0byBtYXRjaCBldmVudCB0eXBlIGluIGhhbmRsZSgpXG5cdFx0XHRuYW1lc3BhY2VzID0gdHlwZS5zcGxpdChcIi5cIik7XG5cdFx0XHR0eXBlID0gbmFtZXNwYWNlcy5zaGlmdCgpO1xuXHRcdFx0bmFtZXNwYWNlcy5zb3J0KCk7XG5cdFx0fVxuXHRcdG9udHlwZSA9IHR5cGUuaW5kZXhPZihcIjpcIikgPCAwICYmIFwib25cIiArIHR5cGU7XG5cblx0XHQvLyBDYWxsZXIgY2FuIHBhc3MgaW4gYSBqUXVlcnkuRXZlbnQgb2JqZWN0LCBPYmplY3QsIG9yIGp1c3QgYW4gZXZlbnQgdHlwZSBzdHJpbmdcblx0XHRldmVudCA9IGV2ZW50WyBqUXVlcnkuZXhwYW5kbyBdID9cblx0XHRcdGV2ZW50IDpcblx0XHRcdG5ldyBqUXVlcnkuRXZlbnQoIHR5cGUsIHR5cGVvZiBldmVudCA9PT0gXCJvYmplY3RcIiAmJiBldmVudCApO1xuXG5cdFx0Ly8gVHJpZ2dlciBiaXRtYXNrOiAmIDEgZm9yIG5hdGl2ZSBoYW5kbGVyczsgJiAyIGZvciBqUXVlcnkgKGFsd2F5cyB0cnVlKVxuXHRcdGV2ZW50LmlzVHJpZ2dlciA9IG9ubHlIYW5kbGVycyA/IDIgOiAzO1xuXHRcdGV2ZW50Lm5hbWVzcGFjZSA9IG5hbWVzcGFjZXMuam9pbihcIi5cIik7XG5cdFx0ZXZlbnQubmFtZXNwYWNlX3JlID0gZXZlbnQubmFtZXNwYWNlID9cblx0XHRcdG5ldyBSZWdFeHAoIFwiKF58XFxcXC4pXCIgKyBuYW1lc3BhY2VzLmpvaW4oXCJcXFxcLig/Oi4qXFxcXC58KVwiKSArIFwiKFxcXFwufCQpXCIgKSA6XG5cdFx0XHRudWxsO1xuXG5cdFx0Ly8gQ2xlYW4gdXAgdGhlIGV2ZW50IGluIGNhc2UgaXQgaXMgYmVpbmcgcmV1c2VkXG5cdFx0ZXZlbnQucmVzdWx0ID0gdW5kZWZpbmVkO1xuXHRcdGlmICggIWV2ZW50LnRhcmdldCApIHtcblx0XHRcdGV2ZW50LnRhcmdldCA9IGVsZW07XG5cdFx0fVxuXG5cdFx0Ly8gQ2xvbmUgYW55IGluY29taW5nIGRhdGEgYW5kIHByZXBlbmQgdGhlIGV2ZW50LCBjcmVhdGluZyB0aGUgaGFuZGxlciBhcmcgbGlzdFxuXHRcdGRhdGEgPSBkYXRhID09IG51bGwgP1xuXHRcdFx0WyBldmVudCBdIDpcblx0XHRcdGpRdWVyeS5tYWtlQXJyYXkoIGRhdGEsIFsgZXZlbnQgXSApO1xuXG5cdFx0Ly8gQWxsb3cgc3BlY2lhbCBldmVudHMgdG8gZHJhdyBvdXRzaWRlIHRoZSBsaW5lc1xuXHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgdHlwZSBdIHx8IHt9O1xuXHRcdGlmICggIW9ubHlIYW5kbGVycyAmJiBzcGVjaWFsLnRyaWdnZXIgJiYgc3BlY2lhbC50cmlnZ2VyLmFwcGx5KCBlbGVtLCBkYXRhICkgPT09IGZhbHNlICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIERldGVybWluZSBldmVudCBwcm9wYWdhdGlvbiBwYXRoIGluIGFkdmFuY2UsIHBlciBXM0MgZXZlbnRzIHNwZWMgKCM5OTUxKVxuXHRcdC8vIEJ1YmJsZSB1cCB0byBkb2N1bWVudCwgdGhlbiB0byB3aW5kb3c7IHdhdGNoIGZvciBhIGdsb2JhbCBvd25lckRvY3VtZW50IHZhciAoIzk3MjQpXG5cdFx0aWYgKCAhb25seUhhbmRsZXJzICYmICFzcGVjaWFsLm5vQnViYmxlICYmICFqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0YnViYmxlVHlwZSA9IHNwZWNpYWwuZGVsZWdhdGVUeXBlIHx8IHR5cGU7XG5cdFx0XHRpZiAoICFyZm9jdXNNb3JwaC50ZXN0KCBidWJibGVUeXBlICsgdHlwZSApICkge1xuXHRcdFx0XHRjdXIgPSBjdXIucGFyZW50Tm9kZTtcblx0XHRcdH1cblx0XHRcdGZvciAoIDsgY3VyOyBjdXIgPSBjdXIucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0ZXZlbnRQYXRoLnB1c2goIGN1ciApO1xuXHRcdFx0XHR0bXAgPSBjdXI7XG5cdFx0XHR9XG5cblx0XHRcdC8vIE9ubHkgYWRkIHdpbmRvdyBpZiB3ZSBnb3QgdG8gZG9jdW1lbnQgKGUuZy4sIG5vdCBwbGFpbiBvYmogb3IgZGV0YWNoZWQgRE9NKVxuXHRcdFx0aWYgKCB0bXAgPT09IChlbGVtLm93bmVyRG9jdW1lbnQgfHwgZG9jdW1lbnQpICkge1xuXHRcdFx0XHRldmVudFBhdGgucHVzaCggdG1wLmRlZmF1bHRWaWV3IHx8IHRtcC5wYXJlbnRXaW5kb3cgfHwgd2luZG93ICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRmlyZSBoYW5kbGVycyBvbiB0aGUgZXZlbnQgcGF0aFxuXHRcdGkgPSAwO1xuXHRcdHdoaWxlICggKGN1ciA9IGV2ZW50UGF0aFtpKytdKSAmJiAhZXZlbnQuaXNQcm9wYWdhdGlvblN0b3BwZWQoKSApIHtcblxuXHRcdFx0ZXZlbnQudHlwZSA9IGkgPiAxID9cblx0XHRcdFx0YnViYmxlVHlwZSA6XG5cdFx0XHRcdHNwZWNpYWwuYmluZFR5cGUgfHwgdHlwZTtcblxuXHRcdFx0Ly8galF1ZXJ5IGhhbmRsZXJcblx0XHRcdGhhbmRsZSA9ICggZGF0YV9wcml2LmdldCggY3VyLCBcImV2ZW50c1wiICkgfHwge30gKVsgZXZlbnQudHlwZSBdICYmIGRhdGFfcHJpdi5nZXQoIGN1ciwgXCJoYW5kbGVcIiApO1xuXHRcdFx0aWYgKCBoYW5kbGUgKSB7XG5cdFx0XHRcdGhhbmRsZS5hcHBseSggY3VyLCBkYXRhICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIE5hdGl2ZSBoYW5kbGVyXG5cdFx0XHRoYW5kbGUgPSBvbnR5cGUgJiYgY3VyWyBvbnR5cGUgXTtcblx0XHRcdGlmICggaGFuZGxlICYmIGhhbmRsZS5hcHBseSAmJiBqUXVlcnkuYWNjZXB0RGF0YSggY3VyICkgKSB7XG5cdFx0XHRcdGV2ZW50LnJlc3VsdCA9IGhhbmRsZS5hcHBseSggY3VyLCBkYXRhICk7XG5cdFx0XHRcdGlmICggZXZlbnQucmVzdWx0ID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGV2ZW50LnR5cGUgPSB0eXBlO1xuXG5cdFx0Ly8gSWYgbm9ib2R5IHByZXZlbnRlZCB0aGUgZGVmYXVsdCBhY3Rpb24sIGRvIGl0IG5vd1xuXHRcdGlmICggIW9ubHlIYW5kbGVycyAmJiAhZXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkgKSB7XG5cblx0XHRcdGlmICggKCFzcGVjaWFsLl9kZWZhdWx0IHx8IHNwZWNpYWwuX2RlZmF1bHQuYXBwbHkoIGV2ZW50UGF0aC5wb3AoKSwgZGF0YSApID09PSBmYWxzZSkgJiZcblx0XHRcdFx0alF1ZXJ5LmFjY2VwdERhdGEoIGVsZW0gKSApIHtcblxuXHRcdFx0XHQvLyBDYWxsIGEgbmF0aXZlIERPTSBtZXRob2Qgb24gdGhlIHRhcmdldCB3aXRoIHRoZSBzYW1lIG5hbWUgbmFtZSBhcyB0aGUgZXZlbnQuXG5cdFx0XHRcdC8vIERvbid0IGRvIGRlZmF1bHQgYWN0aW9ucyBvbiB3aW5kb3csIHRoYXQncyB3aGVyZSBnbG9iYWwgdmFyaWFibGVzIGJlICgjNjE3MClcblx0XHRcdFx0aWYgKCBvbnR5cGUgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oIGVsZW1bIHR5cGUgXSApICYmICFqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0XHRcdC8vIERvbid0IHJlLXRyaWdnZXIgYW4gb25GT08gZXZlbnQgd2hlbiB3ZSBjYWxsIGl0cyBGT08oKSBtZXRob2Rcblx0XHRcdFx0XHR0bXAgPSBlbGVtWyBvbnR5cGUgXTtcblxuXHRcdFx0XHRcdGlmICggdG1wICkge1xuXHRcdFx0XHRcdFx0ZWxlbVsgb250eXBlIF0gPSBudWxsO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIFByZXZlbnQgcmUtdHJpZ2dlcmluZyBvZiB0aGUgc2FtZSBldmVudCwgc2luY2Ugd2UgYWxyZWFkeSBidWJibGVkIGl0IGFib3ZlXG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXJlZCA9IHR5cGU7XG5cdFx0XHRcdFx0ZWxlbVsgdHlwZSBdKCk7XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXJlZCA9IHVuZGVmaW5lZDtcblxuXHRcdFx0XHRcdGlmICggdG1wICkge1xuXHRcdFx0XHRcdFx0ZWxlbVsgb250eXBlIF0gPSB0bXA7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50LnJlc3VsdDtcblx0fSxcblxuXHRkaXNwYXRjaDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0Ly8gTWFrZSBhIHdyaXRhYmxlIGpRdWVyeS5FdmVudCBmcm9tIHRoZSBuYXRpdmUgZXZlbnQgb2JqZWN0XG5cdFx0ZXZlbnQgPSBqUXVlcnkuZXZlbnQuZml4KCBldmVudCApO1xuXG5cdFx0dmFyIGksIGosIHJldCwgbWF0Y2hlZCwgaGFuZGxlT2JqLFxuXHRcdFx0aGFuZGxlclF1ZXVlID0gW10sXG5cdFx0XHRhcmdzID0gc2xpY2UuY2FsbCggYXJndW1lbnRzICksXG5cdFx0XHRoYW5kbGVycyA9ICggZGF0YV9wcml2LmdldCggdGhpcywgXCJldmVudHNcIiApIHx8IHt9IClbIGV2ZW50LnR5cGUgXSB8fCBbXSxcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgZXZlbnQudHlwZSBdIHx8IHt9O1xuXG5cdFx0Ly8gVXNlIHRoZSBmaXgtZWQgalF1ZXJ5LkV2ZW50IHJhdGhlciB0aGFuIHRoZSAocmVhZC1vbmx5KSBuYXRpdmUgZXZlbnRcblx0XHRhcmdzWzBdID0gZXZlbnQ7XG5cdFx0ZXZlbnQuZGVsZWdhdGVUYXJnZXQgPSB0aGlzO1xuXG5cdFx0Ly8gQ2FsbCB0aGUgcHJlRGlzcGF0Y2ggaG9vayBmb3IgdGhlIG1hcHBlZCB0eXBlLCBhbmQgbGV0IGl0IGJhaWwgaWYgZGVzaXJlZFxuXHRcdGlmICggc3BlY2lhbC5wcmVEaXNwYXRjaCAmJiBzcGVjaWFsLnByZURpc3BhdGNoLmNhbGwoIHRoaXMsIGV2ZW50ICkgPT09IGZhbHNlICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIERldGVybWluZSBoYW5kbGVyc1xuXHRcdGhhbmRsZXJRdWV1ZSA9IGpRdWVyeS5ldmVudC5oYW5kbGVycy5jYWxsKCB0aGlzLCBldmVudCwgaGFuZGxlcnMgKTtcblxuXHRcdC8vIFJ1biBkZWxlZ2F0ZXMgZmlyc3Q7IHRoZXkgbWF5IHdhbnQgdG8gc3RvcCBwcm9wYWdhdGlvbiBiZW5lYXRoIHVzXG5cdFx0aSA9IDA7XG5cdFx0d2hpbGUgKCAobWF0Y2hlZCA9IGhhbmRsZXJRdWV1ZVsgaSsrIF0pICYmICFldmVudC5pc1Byb3BhZ2F0aW9uU3RvcHBlZCgpICkge1xuXHRcdFx0ZXZlbnQuY3VycmVudFRhcmdldCA9IG1hdGNoZWQuZWxlbTtcblxuXHRcdFx0aiA9IDA7XG5cdFx0XHR3aGlsZSAoIChoYW5kbGVPYmogPSBtYXRjaGVkLmhhbmRsZXJzWyBqKysgXSkgJiYgIWV2ZW50LmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkKCkgKSB7XG5cblx0XHRcdFx0Ly8gVHJpZ2dlcmVkIGV2ZW50IG11c3QgZWl0aGVyIDEpIGhhdmUgbm8gbmFtZXNwYWNlLCBvciAyKSBoYXZlIG5hbWVzcGFjZShzKVxuXHRcdFx0XHQvLyBhIHN1YnNldCBvciBlcXVhbCB0byB0aG9zZSBpbiB0aGUgYm91bmQgZXZlbnQgKGJvdGggY2FuIGhhdmUgbm8gbmFtZXNwYWNlKS5cblx0XHRcdFx0aWYgKCAhZXZlbnQubmFtZXNwYWNlX3JlIHx8IGV2ZW50Lm5hbWVzcGFjZV9yZS50ZXN0KCBoYW5kbGVPYmoubmFtZXNwYWNlICkgKSB7XG5cblx0XHRcdFx0XHRldmVudC5oYW5kbGVPYmogPSBoYW5kbGVPYmo7XG5cdFx0XHRcdFx0ZXZlbnQuZGF0YSA9IGhhbmRsZU9iai5kYXRhO1xuXG5cdFx0XHRcdFx0cmV0ID0gKCAoalF1ZXJ5LmV2ZW50LnNwZWNpYWxbIGhhbmRsZU9iai5vcmlnVHlwZSBdIHx8IHt9KS5oYW5kbGUgfHwgaGFuZGxlT2JqLmhhbmRsZXIgKVxuXHRcdFx0XHRcdFx0XHQuYXBwbHkoIG1hdGNoZWQuZWxlbSwgYXJncyApO1xuXG5cdFx0XHRcdFx0aWYgKCByZXQgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRcdGlmICggKGV2ZW50LnJlc3VsdCA9IHJldCkgPT09IGZhbHNlICkge1xuXHRcdFx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDYWxsIHRoZSBwb3N0RGlzcGF0Y2ggaG9vayBmb3IgdGhlIG1hcHBlZCB0eXBlXG5cdFx0aWYgKCBzcGVjaWFsLnBvc3REaXNwYXRjaCApIHtcblx0XHRcdHNwZWNpYWwucG9zdERpc3BhdGNoLmNhbGwoIHRoaXMsIGV2ZW50ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50LnJlc3VsdDtcblx0fSxcblxuXHRoYW5kbGVyczogZnVuY3Rpb24oIGV2ZW50LCBoYW5kbGVycyApIHtcblx0XHR2YXIgaSwgbWF0Y2hlcywgc2VsLCBoYW5kbGVPYmosXG5cdFx0XHRoYW5kbGVyUXVldWUgPSBbXSxcblx0XHRcdGRlbGVnYXRlQ291bnQgPSBoYW5kbGVycy5kZWxlZ2F0ZUNvdW50LFxuXHRcdFx0Y3VyID0gZXZlbnQudGFyZ2V0O1xuXG5cdFx0Ly8gRmluZCBkZWxlZ2F0ZSBoYW5kbGVyc1xuXHRcdC8vIEJsYWNrLWhvbGUgU1ZHIDx1c2U+IGluc3RhbmNlIHRyZWVzICgjMTMxODApXG5cdFx0Ly8gQXZvaWQgbm9uLWxlZnQtY2xpY2sgYnViYmxpbmcgaW4gRmlyZWZveCAoIzM4NjEpXG5cdFx0aWYgKCBkZWxlZ2F0ZUNvdW50ICYmIGN1ci5ub2RlVHlwZSAmJiAoIWV2ZW50LmJ1dHRvbiB8fCBldmVudC50eXBlICE9PSBcImNsaWNrXCIpICkge1xuXG5cdFx0XHRmb3IgKCA7IGN1ciAhPT0gdGhpczsgY3VyID0gY3VyLnBhcmVudE5vZGUgfHwgdGhpcyApIHtcblxuXHRcdFx0XHQvLyBEb24ndCBwcm9jZXNzIGNsaWNrcyBvbiBkaXNhYmxlZCBlbGVtZW50cyAoIzY5MTEsICM4MTY1LCAjMTEzODIsICMxMTc2NClcblx0XHRcdFx0aWYgKCBjdXIuZGlzYWJsZWQgIT09IHRydWUgfHwgZXZlbnQudHlwZSAhPT0gXCJjbGlja1wiICkge1xuXHRcdFx0XHRcdG1hdGNoZXMgPSBbXTtcblx0XHRcdFx0XHRmb3IgKCBpID0gMDsgaSA8IGRlbGVnYXRlQ291bnQ7IGkrKyApIHtcblx0XHRcdFx0XHRcdGhhbmRsZU9iaiA9IGhhbmRsZXJzWyBpIF07XG5cblx0XHRcdFx0XHRcdC8vIERvbid0IGNvbmZsaWN0IHdpdGggT2JqZWN0LnByb3RvdHlwZSBwcm9wZXJ0aWVzICgjMTMyMDMpXG5cdFx0XHRcdFx0XHRzZWwgPSBoYW5kbGVPYmouc2VsZWN0b3IgKyBcIiBcIjtcblxuXHRcdFx0XHRcdFx0aWYgKCBtYXRjaGVzWyBzZWwgXSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0XHRtYXRjaGVzWyBzZWwgXSA9IGhhbmRsZU9iai5uZWVkc0NvbnRleHQgP1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeSggc2VsLCB0aGlzICkuaW5kZXgoIGN1ciApID49IDAgOlxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5maW5kKCBzZWwsIHRoaXMsIG51bGwsIFsgY3VyIF0gKS5sZW5ndGg7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZXNbIHNlbCBdICkge1xuXHRcdFx0XHRcdFx0XHRtYXRjaGVzLnB1c2goIGhhbmRsZU9iaiApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoIG1hdGNoZXMubGVuZ3RoICkge1xuXHRcdFx0XHRcdFx0aGFuZGxlclF1ZXVlLnB1c2goeyBlbGVtOiBjdXIsIGhhbmRsZXJzOiBtYXRjaGVzIH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIEFkZCB0aGUgcmVtYWluaW5nIChkaXJlY3RseS1ib3VuZCkgaGFuZGxlcnNcblx0XHRpZiAoIGRlbGVnYXRlQ291bnQgPCBoYW5kbGVycy5sZW5ndGggKSB7XG5cdFx0XHRoYW5kbGVyUXVldWUucHVzaCh7IGVsZW06IHRoaXMsIGhhbmRsZXJzOiBoYW5kbGVycy5zbGljZSggZGVsZWdhdGVDb3VudCApIH0pO1xuXHRcdH1cblxuXHRcdHJldHVybiBoYW5kbGVyUXVldWU7XG5cdH0sXG5cblx0Ly8gSW5jbHVkZXMgc29tZSBldmVudCBwcm9wcyBzaGFyZWQgYnkgS2V5RXZlbnQgYW5kIE1vdXNlRXZlbnRcblx0cHJvcHM6IFwiYWx0S2V5IGJ1YmJsZXMgY2FuY2VsYWJsZSBjdHJsS2V5IGN1cnJlbnRUYXJnZXQgZXZlbnRQaGFzZSBtZXRhS2V5IHJlbGF0ZWRUYXJnZXQgc2hpZnRLZXkgdGFyZ2V0IHRpbWVTdGFtcCB2aWV3IHdoaWNoXCIuc3BsaXQoXCIgXCIpLFxuXG5cdGZpeEhvb2tzOiB7fSxcblxuXHRrZXlIb29rczoge1xuXHRcdHByb3BzOiBcImNoYXIgY2hhckNvZGUga2V5IGtleUNvZGVcIi5zcGxpdChcIiBcIiksXG5cdFx0ZmlsdGVyOiBmdW5jdGlvbiggZXZlbnQsIG9yaWdpbmFsICkge1xuXG5cdFx0XHQvLyBBZGQgd2hpY2ggZm9yIGtleSBldmVudHNcblx0XHRcdGlmICggZXZlbnQud2hpY2ggPT0gbnVsbCApIHtcblx0XHRcdFx0ZXZlbnQud2hpY2ggPSBvcmlnaW5hbC5jaGFyQ29kZSAhPSBudWxsID8gb3JpZ2luYWwuY2hhckNvZGUgOiBvcmlnaW5hbC5rZXlDb2RlO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZXZlbnQ7XG5cdFx0fVxuXHR9LFxuXG5cdG1vdXNlSG9va3M6IHtcblx0XHRwcm9wczogXCJidXR0b24gYnV0dG9ucyBjbGllbnRYIGNsaWVudFkgb2Zmc2V0WCBvZmZzZXRZIHBhZ2VYIHBhZ2VZIHNjcmVlblggc2NyZWVuWSB0b0VsZW1lbnRcIi5zcGxpdChcIiBcIiksXG5cdFx0ZmlsdGVyOiBmdW5jdGlvbiggZXZlbnQsIG9yaWdpbmFsICkge1xuXHRcdFx0dmFyIGV2ZW50RG9jLCBkb2MsIGJvZHksXG5cdFx0XHRcdGJ1dHRvbiA9IG9yaWdpbmFsLmJ1dHRvbjtcblxuXHRcdFx0Ly8gQ2FsY3VsYXRlIHBhZ2VYL1kgaWYgbWlzc2luZyBhbmQgY2xpZW50WC9ZIGF2YWlsYWJsZVxuXHRcdFx0aWYgKCBldmVudC5wYWdlWCA9PSBudWxsICYmIG9yaWdpbmFsLmNsaWVudFggIT0gbnVsbCApIHtcblx0XHRcdFx0ZXZlbnREb2MgPSBldmVudC50YXJnZXQub3duZXJEb2N1bWVudCB8fCBkb2N1bWVudDtcblx0XHRcdFx0ZG9jID0gZXZlbnREb2MuZG9jdW1lbnRFbGVtZW50O1xuXHRcdFx0XHRib2R5ID0gZXZlbnREb2MuYm9keTtcblxuXHRcdFx0XHRldmVudC5wYWdlWCA9IG9yaWdpbmFsLmNsaWVudFggKyAoIGRvYyAmJiBkb2Muc2Nyb2xsTGVmdCB8fCBib2R5ICYmIGJvZHkuc2Nyb2xsTGVmdCB8fCAwICkgLSAoIGRvYyAmJiBkb2MuY2xpZW50TGVmdCB8fCBib2R5ICYmIGJvZHkuY2xpZW50TGVmdCB8fCAwICk7XG5cdFx0XHRcdGV2ZW50LnBhZ2VZID0gb3JpZ2luYWwuY2xpZW50WSArICggZG9jICYmIGRvYy5zY3JvbGxUb3AgIHx8IGJvZHkgJiYgYm9keS5zY3JvbGxUb3AgIHx8IDAgKSAtICggZG9jICYmIGRvYy5jbGllbnRUb3AgIHx8IGJvZHkgJiYgYm9keS5jbGllbnRUb3AgIHx8IDAgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIHdoaWNoIGZvciBjbGljazogMSA9PT0gbGVmdDsgMiA9PT0gbWlkZGxlOyAzID09PSByaWdodFxuXHRcdFx0Ly8gTm90ZTogYnV0dG9uIGlzIG5vdCBub3JtYWxpemVkLCBzbyBkb24ndCB1c2UgaXRcblx0XHRcdGlmICggIWV2ZW50LndoaWNoICYmIGJ1dHRvbiAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRldmVudC53aGljaCA9ICggYnV0dG9uICYgMSA/IDEgOiAoIGJ1dHRvbiAmIDIgPyAzIDogKCBidXR0b24gJiA0ID8gMiA6IDAgKSApICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBldmVudDtcblx0XHR9XG5cdH0sXG5cblx0Zml4OiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0aWYgKCBldmVudFsgalF1ZXJ5LmV4cGFuZG8gXSApIHtcblx0XHRcdHJldHVybiBldmVudDtcblx0XHR9XG5cblx0XHQvLyBDcmVhdGUgYSB3cml0YWJsZSBjb3B5IG9mIHRoZSBldmVudCBvYmplY3QgYW5kIG5vcm1hbGl6ZSBzb21lIHByb3BlcnRpZXNcblx0XHR2YXIgaSwgcHJvcCwgY29weSxcblx0XHRcdHR5cGUgPSBldmVudC50eXBlLFxuXHRcdFx0b3JpZ2luYWxFdmVudCA9IGV2ZW50LFxuXHRcdFx0Zml4SG9vayA9IHRoaXMuZml4SG9va3NbIHR5cGUgXTtcblxuXHRcdGlmICggIWZpeEhvb2sgKSB7XG5cdFx0XHR0aGlzLmZpeEhvb2tzWyB0eXBlIF0gPSBmaXhIb29rID1cblx0XHRcdFx0cm1vdXNlRXZlbnQudGVzdCggdHlwZSApID8gdGhpcy5tb3VzZUhvb2tzIDpcblx0XHRcdFx0cmtleUV2ZW50LnRlc3QoIHR5cGUgKSA/IHRoaXMua2V5SG9va3MgOlxuXHRcdFx0XHR7fTtcblx0XHR9XG5cdFx0Y29weSA9IGZpeEhvb2sucHJvcHMgPyB0aGlzLnByb3BzLmNvbmNhdCggZml4SG9vay5wcm9wcyApIDogdGhpcy5wcm9wcztcblxuXHRcdGV2ZW50ID0gbmV3IGpRdWVyeS5FdmVudCggb3JpZ2luYWxFdmVudCApO1xuXG5cdFx0aSA9IGNvcHkubGVuZ3RoO1xuXHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0cHJvcCA9IGNvcHlbIGkgXTtcblx0XHRcdGV2ZW50WyBwcm9wIF0gPSBvcmlnaW5hbEV2ZW50WyBwcm9wIF07XG5cdFx0fVxuXG5cdFx0Ly8gU3VwcG9ydDogQ29yZG92YSAyLjUgKFdlYktpdCkgKCMxMzI1NSlcblx0XHQvLyBBbGwgZXZlbnRzIHNob3VsZCBoYXZlIGEgdGFyZ2V0OyBDb3Jkb3ZhIGRldmljZXJlYWR5IGRvZXNuJ3Rcblx0XHRpZiAoICFldmVudC50YXJnZXQgKSB7XG5cdFx0XHRldmVudC50YXJnZXQgPSBkb2N1bWVudDtcblx0XHR9XG5cblx0XHQvLyBTdXBwb3J0OiBTYWZhcmkgNi4wKywgQ2hyb21lPDI4XG5cdFx0Ly8gVGFyZ2V0IHNob3VsZCBub3QgYmUgYSB0ZXh0IG5vZGUgKCM1MDQsICMxMzE0Mylcblx0XHRpZiAoIGV2ZW50LnRhcmdldC5ub2RlVHlwZSA9PT0gMyApIHtcblx0XHRcdGV2ZW50LnRhcmdldCA9IGV2ZW50LnRhcmdldC5wYXJlbnROb2RlO1xuXHRcdH1cblxuXHRcdHJldHVybiBmaXhIb29rLmZpbHRlciA/IGZpeEhvb2suZmlsdGVyKCBldmVudCwgb3JpZ2luYWxFdmVudCApIDogZXZlbnQ7XG5cdH0sXG5cblx0c3BlY2lhbDoge1xuXHRcdGxvYWQ6IHtcblx0XHRcdC8vIFByZXZlbnQgdHJpZ2dlcmVkIGltYWdlLmxvYWQgZXZlbnRzIGZyb20gYnViYmxpbmcgdG8gd2luZG93LmxvYWRcblx0XHRcdG5vQnViYmxlOiB0cnVlXG5cdFx0fSxcblx0XHRmb2N1czoge1xuXHRcdFx0Ly8gRmlyZSBuYXRpdmUgZXZlbnQgaWYgcG9zc2libGUgc28gYmx1ci9mb2N1cyBzZXF1ZW5jZSBpcyBjb3JyZWN0XG5cdFx0XHR0cmlnZ2VyOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCB0aGlzICE9PSBzYWZlQWN0aXZlRWxlbWVudCgpICYmIHRoaXMuZm9jdXMgKSB7XG5cdFx0XHRcdFx0dGhpcy5mb2N1cygpO1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGRlbGVnYXRlVHlwZTogXCJmb2N1c2luXCJcblx0XHR9LFxuXHRcdGJsdXI6IHtcblx0XHRcdHRyaWdnZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIHRoaXMgPT09IHNhZmVBY3RpdmVFbGVtZW50KCkgJiYgdGhpcy5ibHVyICkge1xuXHRcdFx0XHRcdHRoaXMuYmx1cigpO1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGRlbGVnYXRlVHlwZTogXCJmb2N1c291dFwiXG5cdFx0fSxcblx0XHRjbGljazoge1xuXHRcdFx0Ly8gRm9yIGNoZWNrYm94LCBmaXJlIG5hdGl2ZSBldmVudCBzbyBjaGVja2VkIHN0YXRlIHdpbGwgYmUgcmlnaHRcblx0XHRcdHRyaWdnZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIHRoaXMudHlwZSA9PT0gXCJjaGVja2JveFwiICYmIHRoaXMuY2xpY2sgJiYgalF1ZXJ5Lm5vZGVOYW1lKCB0aGlzLCBcImlucHV0XCIgKSApIHtcblx0XHRcdFx0XHR0aGlzLmNsaWNrKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBGb3IgY3Jvc3MtYnJvd3NlciBjb25zaXN0ZW5jeSwgZG9uJ3QgZmlyZSBuYXRpdmUgLmNsaWNrKCkgb24gbGlua3Ncblx0XHRcdF9kZWZhdWx0OiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRcdHJldHVybiBqUXVlcnkubm9kZU5hbWUoIGV2ZW50LnRhcmdldCwgXCJhXCIgKTtcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0YmVmb3JldW5sb2FkOiB7XG5cdFx0XHRwb3N0RGlzcGF0Y2g6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBGaXJlZm94IDIwK1xuXHRcdFx0XHQvLyBGaXJlZm94IGRvZXNuJ3QgYWxlcnQgaWYgdGhlIHJldHVyblZhbHVlIGZpZWxkIGlzIG5vdCBzZXQuXG5cdFx0XHRcdGlmICggZXZlbnQucmVzdWx0ICE9PSB1bmRlZmluZWQgJiYgZXZlbnQub3JpZ2luYWxFdmVudCApIHtcblx0XHRcdFx0XHRldmVudC5vcmlnaW5hbEV2ZW50LnJldHVyblZhbHVlID0gZXZlbnQucmVzdWx0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdHNpbXVsYXRlOiBmdW5jdGlvbiggdHlwZSwgZWxlbSwgZXZlbnQsIGJ1YmJsZSApIHtcblx0XHQvLyBQaWdneWJhY2sgb24gYSBkb25vciBldmVudCB0byBzaW11bGF0ZSBhIGRpZmZlcmVudCBvbmUuXG5cdFx0Ly8gRmFrZSBvcmlnaW5hbEV2ZW50IHRvIGF2b2lkIGRvbm9yJ3Mgc3RvcFByb3BhZ2F0aW9uLCBidXQgaWYgdGhlXG5cdFx0Ly8gc2ltdWxhdGVkIGV2ZW50IHByZXZlbnRzIGRlZmF1bHQgdGhlbiB3ZSBkbyB0aGUgc2FtZSBvbiB0aGUgZG9ub3IuXG5cdFx0dmFyIGUgPSBqUXVlcnkuZXh0ZW5kKFxuXHRcdFx0bmV3IGpRdWVyeS5FdmVudCgpLFxuXHRcdFx0ZXZlbnQsXG5cdFx0XHR7XG5cdFx0XHRcdHR5cGU6IHR5cGUsXG5cdFx0XHRcdGlzU2ltdWxhdGVkOiB0cnVlLFxuXHRcdFx0XHRvcmlnaW5hbEV2ZW50OiB7fVxuXHRcdFx0fVxuXHRcdCk7XG5cdFx0aWYgKCBidWJibGUgKSB7XG5cdFx0XHRqUXVlcnkuZXZlbnQudHJpZ2dlciggZSwgbnVsbCwgZWxlbSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRqUXVlcnkuZXZlbnQuZGlzcGF0Y2guY2FsbCggZWxlbSwgZSApO1xuXHRcdH1cblx0XHRpZiAoIGUuaXNEZWZhdWx0UHJldmVudGVkKCkgKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdH1cblx0fVxufTtcblxualF1ZXJ5LnJlbW92ZUV2ZW50ID0gZnVuY3Rpb24oIGVsZW0sIHR5cGUsIGhhbmRsZSApIHtcblx0aWYgKCBlbGVtLnJlbW92ZUV2ZW50TGlzdGVuZXIgKSB7XG5cdFx0ZWxlbS5yZW1vdmVFdmVudExpc3RlbmVyKCB0eXBlLCBoYW5kbGUsIGZhbHNlICk7XG5cdH1cbn07XG5cbmpRdWVyeS5FdmVudCA9IGZ1bmN0aW9uKCBzcmMsIHByb3BzICkge1xuXHQvLyBBbGxvdyBpbnN0YW50aWF0aW9uIHdpdGhvdXQgdGhlICduZXcnIGtleXdvcmRcblx0aWYgKCAhKHRoaXMgaW5zdGFuY2VvZiBqUXVlcnkuRXZlbnQpICkge1xuXHRcdHJldHVybiBuZXcgalF1ZXJ5LkV2ZW50KCBzcmMsIHByb3BzICk7XG5cdH1cblxuXHQvLyBFdmVudCBvYmplY3Rcblx0aWYgKCBzcmMgJiYgc3JjLnR5cGUgKSB7XG5cdFx0dGhpcy5vcmlnaW5hbEV2ZW50ID0gc3JjO1xuXHRcdHRoaXMudHlwZSA9IHNyYy50eXBlO1xuXG5cdFx0Ly8gRXZlbnRzIGJ1YmJsaW5nIHVwIHRoZSBkb2N1bWVudCBtYXkgaGF2ZSBiZWVuIG1hcmtlZCBhcyBwcmV2ZW50ZWRcblx0XHQvLyBieSBhIGhhbmRsZXIgbG93ZXIgZG93biB0aGUgdHJlZTsgcmVmbGVjdCB0aGUgY29ycmVjdCB2YWx1ZS5cblx0XHR0aGlzLmlzRGVmYXVsdFByZXZlbnRlZCA9IHNyYy5kZWZhdWx0UHJldmVudGVkIHx8XG5cdFx0XHRcdHNyYy5kZWZhdWx0UHJldmVudGVkID09PSB1bmRlZmluZWQgJiZcblx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZDw0LjBcblx0XHRcdFx0c3JjLnJldHVyblZhbHVlID09PSBmYWxzZSA/XG5cdFx0XHRyZXR1cm5UcnVlIDpcblx0XHRcdHJldHVybkZhbHNlO1xuXG5cdC8vIEV2ZW50IHR5cGVcblx0fSBlbHNlIHtcblx0XHR0aGlzLnR5cGUgPSBzcmM7XG5cdH1cblxuXHQvLyBQdXQgZXhwbGljaXRseSBwcm92aWRlZCBwcm9wZXJ0aWVzIG9udG8gdGhlIGV2ZW50IG9iamVjdFxuXHRpZiAoIHByb3BzICkge1xuXHRcdGpRdWVyeS5leHRlbmQoIHRoaXMsIHByb3BzICk7XG5cdH1cblxuXHQvLyBDcmVhdGUgYSB0aW1lc3RhbXAgaWYgaW5jb21pbmcgZXZlbnQgZG9lc24ndCBoYXZlIG9uZVxuXHR0aGlzLnRpbWVTdGFtcCA9IHNyYyAmJiBzcmMudGltZVN0YW1wIHx8IGpRdWVyeS5ub3coKTtcblxuXHQvLyBNYXJrIGl0IGFzIGZpeGVkXG5cdHRoaXNbIGpRdWVyeS5leHBhbmRvIF0gPSB0cnVlO1xufTtcblxuLy8galF1ZXJ5LkV2ZW50IGlzIGJhc2VkIG9uIERPTTMgRXZlbnRzIGFzIHNwZWNpZmllZCBieSB0aGUgRUNNQVNjcmlwdCBMYW5ndWFnZSBCaW5kaW5nXG4vLyBodHRwOi8vd3d3LnczLm9yZy9UUi8yMDAzL1dELURPTS1MZXZlbC0zLUV2ZW50cy0yMDAzMDMzMS9lY21hLXNjcmlwdC1iaW5kaW5nLmh0bWxcbmpRdWVyeS5FdmVudC5wcm90b3R5cGUgPSB7XG5cdGlzRGVmYXVsdFByZXZlbnRlZDogcmV0dXJuRmFsc2UsXG5cdGlzUHJvcGFnYXRpb25TdG9wcGVkOiByZXR1cm5GYWxzZSxcblx0aXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQ6IHJldHVybkZhbHNlLFxuXG5cdHByZXZlbnREZWZhdWx0OiBmdW5jdGlvbigpIHtcblx0XHR2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDtcblxuXHRcdHRoaXMuaXNEZWZhdWx0UHJldmVudGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiBlLnByZXZlbnREZWZhdWx0ICkge1xuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdH1cblx0fSxcblx0c3RvcFByb3BhZ2F0aW9uOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDtcblxuXHRcdHRoaXMuaXNQcm9wYWdhdGlvblN0b3BwZWQgPSByZXR1cm5UcnVlO1xuXG5cdFx0aWYgKCBlICYmIGUuc3RvcFByb3BhZ2F0aW9uICkge1xuXHRcdFx0ZS5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHR9XG5cdH0sXG5cdHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGUgPSB0aGlzLm9yaWdpbmFsRXZlbnQ7XG5cblx0XHR0aGlzLmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbiApIHtcblx0XHRcdGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cdFx0fVxuXG5cdFx0dGhpcy5zdG9wUHJvcGFnYXRpb24oKTtcblx0fVxufTtcblxuLy8gQ3JlYXRlIG1vdXNlZW50ZXIvbGVhdmUgZXZlbnRzIHVzaW5nIG1vdXNlb3Zlci9vdXQgYW5kIGV2ZW50LXRpbWUgY2hlY2tzXG4vLyBTdXBwb3J0OiBDaHJvbWUgMTUrXG5qUXVlcnkuZWFjaCh7XG5cdG1vdXNlZW50ZXI6IFwibW91c2VvdmVyXCIsXG5cdG1vdXNlbGVhdmU6IFwibW91c2VvdXRcIixcblx0cG9pbnRlcmVudGVyOiBcInBvaW50ZXJvdmVyXCIsXG5cdHBvaW50ZXJsZWF2ZTogXCJwb2ludGVyb3V0XCJcbn0sIGZ1bmN0aW9uKCBvcmlnLCBmaXggKSB7XG5cdGpRdWVyeS5ldmVudC5zcGVjaWFsWyBvcmlnIF0gPSB7XG5cdFx0ZGVsZWdhdGVUeXBlOiBmaXgsXG5cdFx0YmluZFR5cGU6IGZpeCxcblxuXHRcdGhhbmRsZTogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0dmFyIHJldCxcblx0XHRcdFx0dGFyZ2V0ID0gdGhpcyxcblx0XHRcdFx0cmVsYXRlZCA9IGV2ZW50LnJlbGF0ZWRUYXJnZXQsXG5cdFx0XHRcdGhhbmRsZU9iaiA9IGV2ZW50LmhhbmRsZU9iajtcblxuXHRcdFx0Ly8gRm9yIG1vdXNlbnRlci9sZWF2ZSBjYWxsIHRoZSBoYW5kbGVyIGlmIHJlbGF0ZWQgaXMgb3V0c2lkZSB0aGUgdGFyZ2V0LlxuXHRcdFx0Ly8gTkI6IE5vIHJlbGF0ZWRUYXJnZXQgaWYgdGhlIG1vdXNlIGxlZnQvZW50ZXJlZCB0aGUgYnJvd3NlciB3aW5kb3dcblx0XHRcdGlmICggIXJlbGF0ZWQgfHwgKHJlbGF0ZWQgIT09IHRhcmdldCAmJiAhalF1ZXJ5LmNvbnRhaW5zKCB0YXJnZXQsIHJlbGF0ZWQgKSkgKSB7XG5cdFx0XHRcdGV2ZW50LnR5cGUgPSBoYW5kbGVPYmoub3JpZ1R5cGU7XG5cdFx0XHRcdHJldCA9IGhhbmRsZU9iai5oYW5kbGVyLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHRcdFx0ZXZlbnQudHlwZSA9IGZpeDtcblx0XHRcdH1cblx0XHRcdHJldHVybiByZXQ7XG5cdFx0fVxuXHR9O1xufSk7XG5cbi8vIFN1cHBvcnQ6IEZpcmVmb3gsIENocm9tZSwgU2FmYXJpXG4vLyBDcmVhdGUgXCJidWJibGluZ1wiIGZvY3VzIGFuZCBibHVyIGV2ZW50c1xuaWYgKCAhc3VwcG9ydC5mb2N1c2luQnViYmxlcyApIHtcblx0alF1ZXJ5LmVhY2goeyBmb2N1czogXCJmb2N1c2luXCIsIGJsdXI6IFwiZm9jdXNvdXRcIiB9LCBmdW5jdGlvbiggb3JpZywgZml4ICkge1xuXG5cdFx0Ly8gQXR0YWNoIGEgc2luZ2xlIGNhcHR1cmluZyBoYW5kbGVyIG9uIHRoZSBkb2N1bWVudCB3aGlsZSBzb21lb25lIHdhbnRzIGZvY3VzaW4vZm9jdXNvdXRcblx0XHR2YXIgaGFuZGxlciA9IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdFx0alF1ZXJ5LmV2ZW50LnNpbXVsYXRlKCBmaXgsIGV2ZW50LnRhcmdldCwgalF1ZXJ5LmV2ZW50LmZpeCggZXZlbnQgKSwgdHJ1ZSApO1xuXHRcdFx0fTtcblxuXHRcdGpRdWVyeS5ldmVudC5zcGVjaWFsWyBmaXggXSA9IHtcblx0XHRcdHNldHVwOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIGRvYyA9IHRoaXMub3duZXJEb2N1bWVudCB8fCB0aGlzLFxuXHRcdFx0XHRcdGF0dGFjaGVzID0gZGF0YV9wcml2LmFjY2VzcyggZG9jLCBmaXggKTtcblxuXHRcdFx0XHRpZiAoICFhdHRhY2hlcyApIHtcblx0XHRcdFx0XHRkb2MuYWRkRXZlbnRMaXN0ZW5lciggb3JpZywgaGFuZGxlciwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGRhdGFfcHJpdi5hY2Nlc3MoIGRvYywgZml4LCAoIGF0dGFjaGVzIHx8IDAgKSArIDEgKTtcblx0XHRcdH0sXG5cdFx0XHR0ZWFyZG93bjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBkb2MgPSB0aGlzLm93bmVyRG9jdW1lbnQgfHwgdGhpcyxcblx0XHRcdFx0XHRhdHRhY2hlcyA9IGRhdGFfcHJpdi5hY2Nlc3MoIGRvYywgZml4ICkgLSAxO1xuXG5cdFx0XHRcdGlmICggIWF0dGFjaGVzICkge1xuXHRcdFx0XHRcdGRvYy5yZW1vdmVFdmVudExpc3RlbmVyKCBvcmlnLCBoYW5kbGVyLCB0cnVlICk7XG5cdFx0XHRcdFx0ZGF0YV9wcml2LnJlbW92ZSggZG9jLCBmaXggKTtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGRhdGFfcHJpdi5hY2Nlc3MoIGRvYywgZml4LCBhdHRhY2hlcyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fTtcblx0fSk7XG59XG5cbmpRdWVyeS5mbi5leHRlbmQoe1xuXG5cdG9uOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiwgLypJTlRFUk5BTCovIG9uZSApIHtcblx0XHR2YXIgb3JpZ0ZuLCB0eXBlO1xuXG5cdFx0Ly8gVHlwZXMgY2FuIGJlIGEgbWFwIG9mIHR5cGVzL2hhbmRsZXJzXG5cdFx0aWYgKCB0eXBlb2YgdHlwZXMgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0XHQvLyAoIHR5cGVzLU9iamVjdCwgc2VsZWN0b3IsIGRhdGEgKVxuXHRcdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRcdC8vICggdHlwZXMtT2JqZWN0LCBkYXRhIClcblx0XHRcdFx0ZGF0YSA9IGRhdGEgfHwgc2VsZWN0b3I7XG5cdFx0XHRcdHNlbGVjdG9yID0gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdFx0Zm9yICggdHlwZSBpbiB0eXBlcyApIHtcblx0XHRcdFx0dGhpcy5vbiggdHlwZSwgc2VsZWN0b3IsIGRhdGEsIHR5cGVzWyB0eXBlIF0sIG9uZSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0aWYgKCBkYXRhID09IG51bGwgJiYgZm4gPT0gbnVsbCApIHtcblx0XHRcdC8vICggdHlwZXMsIGZuIClcblx0XHRcdGZuID0gc2VsZWN0b3I7XG5cdFx0XHRkYXRhID0gc2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdFx0fSBlbHNlIGlmICggZm4gPT0gbnVsbCApIHtcblx0XHRcdGlmICggdHlwZW9mIHNlbGVjdG9yID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0XHQvLyAoIHR5cGVzLCBzZWxlY3RvciwgZm4gKVxuXHRcdFx0XHRmbiA9IGRhdGE7XG5cdFx0XHRcdGRhdGEgPSB1bmRlZmluZWQ7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyAoIHR5cGVzLCBkYXRhLCBmbiApXG5cdFx0XHRcdGZuID0gZGF0YTtcblx0XHRcdFx0ZGF0YSA9IHNlbGVjdG9yO1xuXHRcdFx0XHRzZWxlY3RvciA9IHVuZGVmaW5lZDtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCBmbiA9PT0gZmFsc2UgKSB7XG5cdFx0XHRmbiA9IHJldHVybkZhbHNlO1xuXHRcdH0gZWxzZSBpZiAoICFmbiApIHtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblxuXHRcdGlmICggb25lID09PSAxICkge1xuXHRcdFx0b3JpZ0ZuID0gZm47XG5cdFx0XHRmbiA9IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdFx0Ly8gQ2FuIHVzZSBhbiBlbXB0eSBzZXQsIHNpbmNlIGV2ZW50IGNvbnRhaW5zIHRoZSBpbmZvXG5cdFx0XHRcdGpRdWVyeSgpLm9mZiggZXZlbnQgKTtcblx0XHRcdFx0cmV0dXJuIG9yaWdGbi5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHR9O1xuXHRcdFx0Ly8gVXNlIHNhbWUgZ3VpZCBzbyBjYWxsZXIgY2FuIHJlbW92ZSB1c2luZyBvcmlnRm5cblx0XHRcdGZuLmd1aWQgPSBvcmlnRm4uZ3VpZCB8fCAoIG9yaWdGbi5ndWlkID0galF1ZXJ5Lmd1aWQrKyApO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeS5ldmVudC5hZGQoIHRoaXMsIHR5cGVzLCBmbiwgZGF0YSwgc2VsZWN0b3IgKTtcblx0XHR9KTtcblx0fSxcblx0b25lOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiwgMSApO1xuXHR9LFxuXHRvZmY6IGZ1bmN0aW9uKCB0eXBlcywgc2VsZWN0b3IsIGZuICkge1xuXHRcdHZhciBoYW5kbGVPYmosIHR5cGU7XG5cdFx0aWYgKCB0eXBlcyAmJiB0eXBlcy5wcmV2ZW50RGVmYXVsdCAmJiB0eXBlcy5oYW5kbGVPYmogKSB7XG5cdFx0XHQvLyAoIGV2ZW50ICkgIGRpc3BhdGNoZWQgalF1ZXJ5LkV2ZW50XG5cdFx0XHRoYW5kbGVPYmogPSB0eXBlcy5oYW5kbGVPYmo7XG5cdFx0XHRqUXVlcnkoIHR5cGVzLmRlbGVnYXRlVGFyZ2V0ICkub2ZmKFxuXHRcdFx0XHRoYW5kbGVPYmoubmFtZXNwYWNlID8gaGFuZGxlT2JqLm9yaWdUeXBlICsgXCIuXCIgKyBoYW5kbGVPYmoubmFtZXNwYWNlIDogaGFuZGxlT2JqLm9yaWdUeXBlLFxuXHRcdFx0XHRoYW5kbGVPYmouc2VsZWN0b3IsXG5cdFx0XHRcdGhhbmRsZU9iai5oYW5kbGVyXG5cdFx0XHQpO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXHRcdGlmICggdHlwZW9mIHR5cGVzID09PSBcIm9iamVjdFwiICkge1xuXHRcdFx0Ly8gKCB0eXBlcy1vYmplY3QgWywgc2VsZWN0b3JdIClcblx0XHRcdGZvciAoIHR5cGUgaW4gdHlwZXMgKSB7XG5cdFx0XHRcdHRoaXMub2ZmKCB0eXBlLCBzZWxlY3RvciwgdHlwZXNbIHR5cGUgXSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXHRcdGlmICggc2VsZWN0b3IgPT09IGZhbHNlIHx8IHR5cGVvZiBzZWxlY3RvciA9PT0gXCJmdW5jdGlvblwiICkge1xuXHRcdFx0Ly8gKCB0eXBlcyBbLCBmbl0gKVxuXHRcdFx0Zm4gPSBzZWxlY3Rvcjtcblx0XHRcdHNlbGVjdG9yID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHRpZiAoIGZuID09PSBmYWxzZSApIHtcblx0XHRcdGZuID0gcmV0dXJuRmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRqUXVlcnkuZXZlbnQucmVtb3ZlKCB0aGlzLCB0eXBlcywgZm4sIHNlbGVjdG9yICk7XG5cdFx0fSk7XG5cdH0sXG5cblx0dHJpZ2dlcjogZnVuY3Rpb24oIHR5cGUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCB0aGlzICk7XG5cdFx0fSk7XG5cdH0sXG5cdHRyaWdnZXJIYW5kbGVyOiBmdW5jdGlvbiggdHlwZSwgZGF0YSApIHtcblx0XHR2YXIgZWxlbSA9IHRoaXNbMF07XG5cdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCBlbGVtLCB0cnVlICk7XG5cdFx0fVxuXHR9XG59KTtcblxuXG52YXJcblx0cnhodG1sVGFnID0gLzwoPyFhcmVhfGJyfGNvbHxlbWJlZHxocnxpbWd8aW5wdXR8bGlua3xtZXRhfHBhcmFtKSgoW1xcdzpdKylbXj5dKilcXC8+L2dpLFxuXHRydGFnTmFtZSA9IC88KFtcXHc6XSspLyxcblx0cmh0bWwgPSAvPHwmIz9cXHcrOy8sXG5cdHJub0lubmVyaHRtbCA9IC88KD86c2NyaXB0fHN0eWxlfGxpbmspL2ksXG5cdC8vIGNoZWNrZWQ9XCJjaGVja2VkXCIgb3IgY2hlY2tlZFxuXHRyY2hlY2tlZCA9IC9jaGVja2VkXFxzKig/OltePV18PVxccyouY2hlY2tlZC4pL2ksXG5cdHJzY3JpcHRUeXBlID0gL14kfFxcLyg/OmphdmF8ZWNtYSlzY3JpcHQvaSxcblx0cnNjcmlwdFR5cGVNYXNrZWQgPSAvXnRydWVcXC8oLiopLyxcblx0cmNsZWFuU2NyaXB0ID0gL15cXHMqPCEoPzpcXFtDREFUQVxcW3wtLSl8KD86XFxdXFxdfC0tKT5cXHMqJC9nLFxuXG5cdC8vIFdlIGhhdmUgdG8gY2xvc2UgdGhlc2UgdGFncyB0byBzdXBwb3J0IFhIVE1MICgjMTMyMDApXG5cdHdyYXBNYXAgPSB7XG5cblx0XHQvLyBTdXBwb3J0OiBJRTlcblx0XHRvcHRpb246IFsgMSwgXCI8c2VsZWN0IG11bHRpcGxlPSdtdWx0aXBsZSc+XCIsIFwiPC9zZWxlY3Q+XCIgXSxcblxuXHRcdHRoZWFkOiBbIDEsIFwiPHRhYmxlPlwiLCBcIjwvdGFibGU+XCIgXSxcblx0XHRjb2w6IFsgMiwgXCI8dGFibGU+PGNvbGdyb3VwPlwiLCBcIjwvY29sZ3JvdXA+PC90YWJsZT5cIiBdLFxuXHRcdHRyOiBbIDIsIFwiPHRhYmxlPjx0Ym9keT5cIiwgXCI8L3Rib2R5PjwvdGFibGU+XCIgXSxcblx0XHR0ZDogWyAzLCBcIjx0YWJsZT48dGJvZHk+PHRyPlwiLCBcIjwvdHI+PC90Ym9keT48L3RhYmxlPlwiIF0sXG5cblx0XHRfZGVmYXVsdDogWyAwLCBcIlwiLCBcIlwiIF1cblx0fTtcblxuLy8gU3VwcG9ydDogSUU5XG53cmFwTWFwLm9wdGdyb3VwID0gd3JhcE1hcC5vcHRpb247XG5cbndyYXBNYXAudGJvZHkgPSB3cmFwTWFwLnRmb290ID0gd3JhcE1hcC5jb2xncm91cCA9IHdyYXBNYXAuY2FwdGlvbiA9IHdyYXBNYXAudGhlYWQ7XG53cmFwTWFwLnRoID0gd3JhcE1hcC50ZDtcblxuLy8gU3VwcG9ydDogMS54IGNvbXBhdGliaWxpdHlcbi8vIE1hbmlwdWxhdGluZyB0YWJsZXMgcmVxdWlyZXMgYSB0Ym9keVxuZnVuY3Rpb24gbWFuaXB1bGF0aW9uVGFyZ2V0KCBlbGVtLCBjb250ZW50ICkge1xuXHRyZXR1cm4galF1ZXJ5Lm5vZGVOYW1lKCBlbGVtLCBcInRhYmxlXCIgKSAmJlxuXHRcdGpRdWVyeS5ub2RlTmFtZSggY29udGVudC5ub2RlVHlwZSAhPT0gMTEgPyBjb250ZW50IDogY29udGVudC5maXJzdENoaWxkLCBcInRyXCIgKSA/XG5cblx0XHRlbGVtLmdldEVsZW1lbnRzQnlUYWdOYW1lKFwidGJvZHlcIilbMF0gfHxcblx0XHRcdGVsZW0uYXBwZW5kQ2hpbGQoIGVsZW0ub3duZXJEb2N1bWVudC5jcmVhdGVFbGVtZW50KFwidGJvZHlcIikgKSA6XG5cdFx0ZWxlbTtcbn1cblxuLy8gUmVwbGFjZS9yZXN0b3JlIHRoZSB0eXBlIGF0dHJpYnV0ZSBvZiBzY3JpcHQgZWxlbWVudHMgZm9yIHNhZmUgRE9NIG1hbmlwdWxhdGlvblxuZnVuY3Rpb24gZGlzYWJsZVNjcmlwdCggZWxlbSApIHtcblx0ZWxlbS50eXBlID0gKGVsZW0uZ2V0QXR0cmlidXRlKFwidHlwZVwiKSAhPT0gbnVsbCkgKyBcIi9cIiArIGVsZW0udHlwZTtcblx0cmV0dXJuIGVsZW07XG59XG5mdW5jdGlvbiByZXN0b3JlU2NyaXB0KCBlbGVtICkge1xuXHR2YXIgbWF0Y2ggPSByc2NyaXB0VHlwZU1hc2tlZC5leGVjKCBlbGVtLnR5cGUgKTtcblxuXHRpZiAoIG1hdGNoICkge1xuXHRcdGVsZW0udHlwZSA9IG1hdGNoWyAxIF07XG5cdH0gZWxzZSB7XG5cdFx0ZWxlbS5yZW1vdmVBdHRyaWJ1dGUoXCJ0eXBlXCIpO1xuXHR9XG5cblx0cmV0dXJuIGVsZW07XG59XG5cbi8vIE1hcmsgc2NyaXB0cyBhcyBoYXZpbmcgYWxyZWFkeSBiZWVuIGV2YWx1YXRlZFxuZnVuY3Rpb24gc2V0R2xvYmFsRXZhbCggZWxlbXMsIHJlZkVsZW1lbnRzICkge1xuXHR2YXIgaSA9IDAsXG5cdFx0bCA9IGVsZW1zLmxlbmd0aDtcblxuXHRmb3IgKCA7IGkgPCBsOyBpKysgKSB7XG5cdFx0ZGF0YV9wcml2LnNldChcblx0XHRcdGVsZW1zWyBpIF0sIFwiZ2xvYmFsRXZhbFwiLCAhcmVmRWxlbWVudHMgfHwgZGF0YV9wcml2LmdldCggcmVmRWxlbWVudHNbIGkgXSwgXCJnbG9iYWxFdmFsXCIgKVxuXHRcdCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gY2xvbmVDb3B5RXZlbnQoIHNyYywgZGVzdCApIHtcblx0dmFyIGksIGwsIHR5cGUsIHBkYXRhT2xkLCBwZGF0YUN1ciwgdWRhdGFPbGQsIHVkYXRhQ3VyLCBldmVudHM7XG5cblx0aWYgKCBkZXN0Lm5vZGVUeXBlICE9PSAxICkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdC8vIDEuIENvcHkgcHJpdmF0ZSBkYXRhOiBldmVudHMsIGhhbmRsZXJzLCBldGMuXG5cdGlmICggZGF0YV9wcml2Lmhhc0RhdGEoIHNyYyApICkge1xuXHRcdHBkYXRhT2xkID0gZGF0YV9wcml2LmFjY2Vzcyggc3JjICk7XG5cdFx0cGRhdGFDdXIgPSBkYXRhX3ByaXYuc2V0KCBkZXN0LCBwZGF0YU9sZCApO1xuXHRcdGV2ZW50cyA9IHBkYXRhT2xkLmV2ZW50cztcblxuXHRcdGlmICggZXZlbnRzICkge1xuXHRcdFx0ZGVsZXRlIHBkYXRhQ3VyLmhhbmRsZTtcblx0XHRcdHBkYXRhQ3VyLmV2ZW50cyA9IHt9O1xuXG5cdFx0XHRmb3IgKCB0eXBlIGluIGV2ZW50cyApIHtcblx0XHRcdFx0Zm9yICggaSA9IDAsIGwgPSBldmVudHNbIHR5cGUgXS5sZW5ndGg7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LmFkZCggZGVzdCwgdHlwZSwgZXZlbnRzWyB0eXBlIF1bIGkgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gMi4gQ29weSB1c2VyIGRhdGFcblx0aWYgKCBkYXRhX3VzZXIuaGFzRGF0YSggc3JjICkgKSB7XG5cdFx0dWRhdGFPbGQgPSBkYXRhX3VzZXIuYWNjZXNzKCBzcmMgKTtcblx0XHR1ZGF0YUN1ciA9IGpRdWVyeS5leHRlbmQoIHt9LCB1ZGF0YU9sZCApO1xuXG5cdFx0ZGF0YV91c2VyLnNldCggZGVzdCwgdWRhdGFDdXIgKTtcblx0fVxufVxuXG5mdW5jdGlvbiBnZXRBbGwoIGNvbnRleHQsIHRhZyApIHtcblx0dmFyIHJldCA9IGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgPyBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCB0YWcgfHwgXCIqXCIgKSA6XG5cdFx0XHRjb250ZXh0LnF1ZXJ5U2VsZWN0b3JBbGwgPyBjb250ZXh0LnF1ZXJ5U2VsZWN0b3JBbGwoIHRhZyB8fCBcIipcIiApIDpcblx0XHRcdFtdO1xuXG5cdHJldHVybiB0YWcgPT09IHVuZGVmaW5lZCB8fCB0YWcgJiYgalF1ZXJ5Lm5vZGVOYW1lKCBjb250ZXh0LCB0YWcgKSA/XG5cdFx0alF1ZXJ5Lm1lcmdlKCBbIGNvbnRleHQgXSwgcmV0ICkgOlxuXHRcdHJldDtcbn1cblxuLy8gRml4IElFIGJ1Z3MsIHNlZSBzdXBwb3J0IHRlc3RzXG5mdW5jdGlvbiBmaXhJbnB1dCggc3JjLCBkZXN0ICkge1xuXHR2YXIgbm9kZU5hbWUgPSBkZXN0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cblx0Ly8gRmFpbHMgdG8gcGVyc2lzdCB0aGUgY2hlY2tlZCBzdGF0ZSBvZiBhIGNsb25lZCBjaGVja2JveCBvciByYWRpbyBidXR0b24uXG5cdGlmICggbm9kZU5hbWUgPT09IFwiaW5wdXRcIiAmJiByY2hlY2thYmxlVHlwZS50ZXN0KCBzcmMudHlwZSApICkge1xuXHRcdGRlc3QuY2hlY2tlZCA9IHNyYy5jaGVja2VkO1xuXG5cdC8vIEZhaWxzIHRvIHJldHVybiB0aGUgc2VsZWN0ZWQgb3B0aW9uIHRvIHRoZSBkZWZhdWx0IHNlbGVjdGVkIHN0YXRlIHdoZW4gY2xvbmluZyBvcHRpb25zXG5cdH0gZWxzZSBpZiAoIG5vZGVOYW1lID09PSBcImlucHV0XCIgfHwgbm9kZU5hbWUgPT09IFwidGV4dGFyZWFcIiApIHtcblx0XHRkZXN0LmRlZmF1bHRWYWx1ZSA9IHNyYy5kZWZhdWx0VmFsdWU7XG5cdH1cbn1cblxualF1ZXJ5LmV4dGVuZCh7XG5cdGNsb25lOiBmdW5jdGlvbiggZWxlbSwgZGF0YUFuZEV2ZW50cywgZGVlcERhdGFBbmRFdmVudHMgKSB7XG5cdFx0dmFyIGksIGwsIHNyY0VsZW1lbnRzLCBkZXN0RWxlbWVudHMsXG5cdFx0XHRjbG9uZSA9IGVsZW0uY2xvbmVOb2RlKCB0cnVlICksXG5cdFx0XHRpblBhZ2UgPSBqUXVlcnkuY29udGFpbnMoIGVsZW0ub3duZXJEb2N1bWVudCwgZWxlbSApO1xuXG5cdFx0Ly8gRml4IElFIGNsb25pbmcgaXNzdWVzXG5cdFx0aWYgKCAhc3VwcG9ydC5ub0Nsb25lQ2hlY2tlZCAmJiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgfHwgZWxlbS5ub2RlVHlwZSA9PT0gMTEgKSAmJlxuXHRcdFx0XHQhalF1ZXJ5LmlzWE1MRG9jKCBlbGVtICkgKSB7XG5cblx0XHRcdC8vIFdlIGVzY2hldyBTaXp6bGUgaGVyZSBmb3IgcGVyZm9ybWFuY2UgcmVhc29uczogaHR0cDovL2pzcGVyZi5jb20vZ2V0YWxsLXZzLXNpenpsZS8yXG5cdFx0XHRkZXN0RWxlbWVudHMgPSBnZXRBbGwoIGNsb25lICk7XG5cdFx0XHRzcmNFbGVtZW50cyA9IGdldEFsbCggZWxlbSApO1xuXG5cdFx0XHRmb3IgKCBpID0gMCwgbCA9IHNyY0VsZW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0Zml4SW5wdXQoIHNyY0VsZW1lbnRzWyBpIF0sIGRlc3RFbGVtZW50c1sgaSBdICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ29weSB0aGUgZXZlbnRzIGZyb20gdGhlIG9yaWdpbmFsIHRvIHRoZSBjbG9uZVxuXHRcdGlmICggZGF0YUFuZEV2ZW50cyApIHtcblx0XHRcdGlmICggZGVlcERhdGFBbmRFdmVudHMgKSB7XG5cdFx0XHRcdHNyY0VsZW1lbnRzID0gc3JjRWxlbWVudHMgfHwgZ2V0QWxsKCBlbGVtICk7XG5cdFx0XHRcdGRlc3RFbGVtZW50cyA9IGRlc3RFbGVtZW50cyB8fCBnZXRBbGwoIGNsb25lICk7XG5cblx0XHRcdFx0Zm9yICggaSA9IDAsIGwgPSBzcmNFbGVtZW50cy5sZW5ndGg7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdFx0Y2xvbmVDb3B5RXZlbnQoIHNyY0VsZW1lbnRzWyBpIF0sIGRlc3RFbGVtZW50c1sgaSBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNsb25lQ29weUV2ZW50KCBlbGVtLCBjbG9uZSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFByZXNlcnZlIHNjcmlwdCBldmFsdWF0aW9uIGhpc3Rvcnlcblx0XHRkZXN0RWxlbWVudHMgPSBnZXRBbGwoIGNsb25lLCBcInNjcmlwdFwiICk7XG5cdFx0aWYgKCBkZXN0RWxlbWVudHMubGVuZ3RoID4gMCApIHtcblx0XHRcdHNldEdsb2JhbEV2YWwoIGRlc3RFbGVtZW50cywgIWluUGFnZSAmJiBnZXRBbGwoIGVsZW0sIFwic2NyaXB0XCIgKSApO1xuXHRcdH1cblxuXHRcdC8vIFJldHVybiB0aGUgY2xvbmVkIHNldFxuXHRcdHJldHVybiBjbG9uZTtcblx0fSxcblxuXHRidWlsZEZyYWdtZW50OiBmdW5jdGlvbiggZWxlbXMsIGNvbnRleHQsIHNjcmlwdHMsIHNlbGVjdGlvbiApIHtcblx0XHR2YXIgZWxlbSwgdG1wLCB0YWcsIHdyYXAsIGNvbnRhaW5zLCBqLFxuXHRcdFx0ZnJhZ21lbnQgPSBjb250ZXh0LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSxcblx0XHRcdG5vZGVzID0gW10sXG5cdFx0XHRpID0gMCxcblx0XHRcdGwgPSBlbGVtcy5sZW5ndGg7XG5cblx0XHRmb3IgKCA7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRlbGVtID0gZWxlbXNbIGkgXTtcblxuXHRcdFx0aWYgKCBlbGVtIHx8IGVsZW0gPT09IDAgKSB7XG5cblx0XHRcdFx0Ly8gQWRkIG5vZGVzIGRpcmVjdGx5XG5cdFx0XHRcdGlmICggalF1ZXJ5LnR5cGUoIGVsZW0gKSA9PT0gXCJvYmplY3RcIiApIHtcblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBRdFdlYktpdCwgUGhhbnRvbUpTXG5cdFx0XHRcdFx0Ly8gcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRcdFx0XHRcdGpRdWVyeS5tZXJnZSggbm9kZXMsIGVsZW0ubm9kZVR5cGUgPyBbIGVsZW0gXSA6IGVsZW0gKTtcblxuXHRcdFx0XHQvLyBDb252ZXJ0IG5vbi1odG1sIGludG8gYSB0ZXh0IG5vZGVcblx0XHRcdFx0fSBlbHNlIGlmICggIXJodG1sLnRlc3QoIGVsZW0gKSApIHtcblx0XHRcdFx0XHRub2Rlcy5wdXNoKCBjb250ZXh0LmNyZWF0ZVRleHROb2RlKCBlbGVtICkgKTtcblxuXHRcdFx0XHQvLyBDb252ZXJ0IGh0bWwgaW50byBET00gbm9kZXNcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0bXAgPSB0bXAgfHwgZnJhZ21lbnQuYXBwZW5kQ2hpbGQoIGNvbnRleHQuY3JlYXRlRWxlbWVudChcImRpdlwiKSApO1xuXG5cdFx0XHRcdFx0Ly8gRGVzZXJpYWxpemUgYSBzdGFuZGFyZCByZXByZXNlbnRhdGlvblxuXHRcdFx0XHRcdHRhZyA9ICggcnRhZ05hbWUuZXhlYyggZWxlbSApIHx8IFsgXCJcIiwgXCJcIiBdIClbIDEgXS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0XHRcdHdyYXAgPSB3cmFwTWFwWyB0YWcgXSB8fCB3cmFwTWFwLl9kZWZhdWx0O1xuXHRcdFx0XHRcdHRtcC5pbm5lckhUTUwgPSB3cmFwWyAxIF0gKyBlbGVtLnJlcGxhY2UoIHJ4aHRtbFRhZywgXCI8JDE+PC8kMj5cIiApICsgd3JhcFsgMiBdO1xuXG5cdFx0XHRcdFx0Ly8gRGVzY2VuZCB0aHJvdWdoIHdyYXBwZXJzIHRvIHRoZSByaWdodCBjb250ZW50XG5cdFx0XHRcdFx0aiA9IHdyYXBbIDAgXTtcblx0XHRcdFx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdFx0XHRcdHRtcCA9IHRtcC5sYXN0Q2hpbGQ7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gU3VwcG9ydDogUXRXZWJLaXQsIFBoYW50b21KU1xuXHRcdFx0XHRcdC8vIHB1c2guYXBwbHkoXywgYXJyYXlsaWtlKSB0aHJvd3Mgb24gYW5jaWVudCBXZWJLaXRcblx0XHRcdFx0XHRqUXVlcnkubWVyZ2UoIG5vZGVzLCB0bXAuY2hpbGROb2RlcyApO1xuXG5cdFx0XHRcdFx0Ly8gUmVtZW1iZXIgdGhlIHRvcC1sZXZlbCBjb250YWluZXJcblx0XHRcdFx0XHR0bXAgPSBmcmFnbWVudC5maXJzdENoaWxkO1xuXG5cdFx0XHRcdFx0Ly8gRW5zdXJlIHRoZSBjcmVhdGVkIG5vZGVzIGFyZSBvcnBoYW5lZCAoIzEyMzkyKVxuXHRcdFx0XHRcdHRtcC50ZXh0Q29udGVudCA9IFwiXCI7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBSZW1vdmUgd3JhcHBlciBmcm9tIGZyYWdtZW50XG5cdFx0ZnJhZ21lbnQudGV4dENvbnRlbnQgPSBcIlwiO1xuXG5cdFx0aSA9IDA7XG5cdFx0d2hpbGUgKCAoZWxlbSA9IG5vZGVzWyBpKysgXSkgKSB7XG5cblx0XHRcdC8vICM0MDg3IC0gSWYgb3JpZ2luIGFuZCBkZXN0aW5hdGlvbiBlbGVtZW50cyBhcmUgdGhlIHNhbWUsIGFuZCB0aGlzIGlzXG5cdFx0XHQvLyB0aGF0IGVsZW1lbnQsIGRvIG5vdCBkbyBhbnl0aGluZ1xuXHRcdFx0aWYgKCBzZWxlY3Rpb24gJiYgalF1ZXJ5LmluQXJyYXkoIGVsZW0sIHNlbGVjdGlvbiApICE9PSAtMSApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnRhaW5zID0galF1ZXJ5LmNvbnRhaW5zKCBlbGVtLm93bmVyRG9jdW1lbnQsIGVsZW0gKTtcblxuXHRcdFx0Ly8gQXBwZW5kIHRvIGZyYWdtZW50XG5cdFx0XHR0bXAgPSBnZXRBbGwoIGZyYWdtZW50LmFwcGVuZENoaWxkKCBlbGVtICksIFwic2NyaXB0XCIgKTtcblxuXHRcdFx0Ly8gUHJlc2VydmUgc2NyaXB0IGV2YWx1YXRpb24gaGlzdG9yeVxuXHRcdFx0aWYgKCBjb250YWlucyApIHtcblx0XHRcdFx0c2V0R2xvYmFsRXZhbCggdG1wICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIENhcHR1cmUgZXhlY3V0YWJsZXNcblx0XHRcdGlmICggc2NyaXB0cyApIHtcblx0XHRcdFx0aiA9IDA7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSB0bXBbIGorKyBdKSApIHtcblx0XHRcdFx0XHRpZiAoIHJzY3JpcHRUeXBlLnRlc3QoIGVsZW0udHlwZSB8fCBcIlwiICkgKSB7XG5cdFx0XHRcdFx0XHRzY3JpcHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gZnJhZ21lbnQ7XG5cdH0sXG5cblx0Y2xlYW5EYXRhOiBmdW5jdGlvbiggZWxlbXMgKSB7XG5cdFx0dmFyIGRhdGEsIGVsZW0sIHR5cGUsIGtleSxcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbCxcblx0XHRcdGkgPSAwO1xuXG5cdFx0Zm9yICggOyAoZWxlbSA9IGVsZW1zWyBpIF0pICE9PSB1bmRlZmluZWQ7IGkrKyApIHtcblx0XHRcdGlmICggalF1ZXJ5LmFjY2VwdERhdGEoIGVsZW0gKSApIHtcblx0XHRcdFx0a2V5ID0gZWxlbVsgZGF0YV9wcml2LmV4cGFuZG8gXTtcblxuXHRcdFx0XHRpZiAoIGtleSAmJiAoZGF0YSA9IGRhdGFfcHJpdi5jYWNoZVsga2V5IF0pICkge1xuXHRcdFx0XHRcdGlmICggZGF0YS5ldmVudHMgKSB7XG5cdFx0XHRcdFx0XHRmb3IgKCB0eXBlIGluIGRhdGEuZXZlbnRzICkge1xuXHRcdFx0XHRcdFx0XHRpZiAoIHNwZWNpYWxbIHR5cGUgXSApIHtcblx0XHRcdFx0XHRcdFx0XHRqUXVlcnkuZXZlbnQucmVtb3ZlKCBlbGVtLCB0eXBlICk7XG5cblx0XHRcdFx0XHRcdFx0Ly8gVGhpcyBpcyBhIHNob3J0Y3V0IHRvIGF2b2lkIGpRdWVyeS5ldmVudC5yZW1vdmUncyBvdmVyaGVhZFxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5yZW1vdmVFdmVudCggZWxlbSwgdHlwZSwgZGF0YS5oYW5kbGUgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoIGRhdGFfcHJpdi5jYWNoZVsga2V5IF0gKSB7XG5cdFx0XHRcdFx0XHQvLyBEaXNjYXJkIGFueSByZW1haW5pbmcgYHByaXZhdGVgIGRhdGFcblx0XHRcdFx0XHRcdGRlbGV0ZSBkYXRhX3ByaXYuY2FjaGVbIGtleSBdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Ly8gRGlzY2FyZCBhbnkgcmVtYWluaW5nIGB1c2VyYCBkYXRhXG5cdFx0XHRkZWxldGUgZGF0YV91c2VyLmNhY2hlWyBlbGVtWyBkYXRhX3VzZXIuZXhwYW5kbyBdIF07XG5cdFx0fVxuXHR9XG59KTtcblxualF1ZXJ5LmZuLmV4dGVuZCh7XG5cdHRleHQ6IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0XHRyZXR1cm4gdmFsdWUgPT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdGpRdWVyeS50ZXh0KCB0aGlzICkgOlxuXHRcdFx0XHR0aGlzLmVtcHR5KCkuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAoIHRoaXMubm9kZVR5cGUgPT09IDEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gMTEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gOSApIHtcblx0XHRcdFx0XHRcdHRoaXMudGV4dENvbnRlbnQgPSB2YWx1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdH0sIG51bGwsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH0sXG5cblx0YXBwZW5kOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5kb21NYW5pcCggYXJndW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdGlmICggdGhpcy5ub2RlVHlwZSA9PT0gMSB8fCB0aGlzLm5vZGVUeXBlID09PSAxMSB8fCB0aGlzLm5vZGVUeXBlID09PSA5ICkge1xuXHRcdFx0XHR2YXIgdGFyZ2V0ID0gbWFuaXB1bGF0aW9uVGFyZ2V0KCB0aGlzLCBlbGVtICk7XG5cdFx0XHRcdHRhcmdldC5hcHBlbmRDaGlsZCggZWxlbSApO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9LFxuXG5cdHByZXBlbmQ6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmRvbU1hbmlwKCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0aWYgKCB0aGlzLm5vZGVUeXBlID09PSAxIHx8IHRoaXMubm9kZVR5cGUgPT09IDExIHx8IHRoaXMubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdHZhciB0YXJnZXQgPSBtYW5pcHVsYXRpb25UYXJnZXQoIHRoaXMsIGVsZW0gKTtcblx0XHRcdFx0dGFyZ2V0Lmluc2VydEJlZm9yZSggZWxlbSwgdGFyZ2V0LmZpcnN0Q2hpbGQgKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSxcblxuXHRiZWZvcmU6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmRvbU1hbmlwKCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0aWYgKCB0aGlzLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdHRoaXMucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoIGVsZW0sIHRoaXMgKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSxcblxuXHRhZnRlcjogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZG9tTWFuaXAoIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0dGhpcy5wYXJlbnROb2RlLmluc2VydEJlZm9yZSggZWxlbSwgdGhpcy5uZXh0U2libGluZyApO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9LFxuXG5cdHJlbW92ZTogZnVuY3Rpb24oIHNlbGVjdG9yLCBrZWVwRGF0YSAvKiBJbnRlcm5hbCBVc2UgT25seSAqLyApIHtcblx0XHR2YXIgZWxlbSxcblx0XHRcdGVsZW1zID0gc2VsZWN0b3IgPyBqUXVlcnkuZmlsdGVyKCBzZWxlY3RvciwgdGhpcyApIDogdGhpcyxcblx0XHRcdGkgPSAwO1xuXG5cdFx0Zm9yICggOyAoZWxlbSA9IGVsZW1zW2ldKSAhPSBudWxsOyBpKysgKSB7XG5cdFx0XHRpZiAoICFrZWVwRGF0YSAmJiBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0XHRqUXVlcnkuY2xlYW5EYXRhKCBnZXRBbGwoIGVsZW0gKSApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGVsZW0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0aWYgKCBrZWVwRGF0YSAmJiBqUXVlcnkuY29udGFpbnMoIGVsZW0ub3duZXJEb2N1bWVudCwgZWxlbSApICkge1xuXHRcdFx0XHRcdHNldEdsb2JhbEV2YWwoIGdldEFsbCggZWxlbSwgXCJzY3JpcHRcIiApICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxlbS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCBlbGVtICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0ZW1wdHk6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBlbGVtLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRmb3IgKCA7IChlbGVtID0gdGhpc1tpXSkgIT0gbnVsbDsgaSsrICkge1xuXHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXG5cdFx0XHRcdC8vIFByZXZlbnQgbWVtb3J5IGxlYWtzXG5cdFx0XHRcdGpRdWVyeS5jbGVhbkRhdGEoIGdldEFsbCggZWxlbSwgZmFsc2UgKSApO1xuXG5cdFx0XHRcdC8vIFJlbW92ZSBhbnkgcmVtYWluaW5nIG5vZGVzXG5cdFx0XHRcdGVsZW0udGV4dENvbnRlbnQgPSBcIlwiO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdGNsb25lOiBmdW5jdGlvbiggZGF0YUFuZEV2ZW50cywgZGVlcERhdGFBbmRFdmVudHMgKSB7XG5cdFx0ZGF0YUFuZEV2ZW50cyA9IGRhdGFBbmRFdmVudHMgPT0gbnVsbCA/IGZhbHNlIDogZGF0YUFuZEV2ZW50cztcblx0XHRkZWVwRGF0YUFuZEV2ZW50cyA9IGRlZXBEYXRhQW5kRXZlbnRzID09IG51bGwgPyBkYXRhQW5kRXZlbnRzIDogZGVlcERhdGFBbmRFdmVudHM7XG5cblx0XHRyZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4galF1ZXJ5LmNsb25lKCB0aGlzLCBkYXRhQW5kRXZlbnRzLCBkZWVwRGF0YUFuZEV2ZW50cyApO1xuXHRcdH0pO1xuXHR9LFxuXG5cdGh0bWw6IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0XHR2YXIgZWxlbSA9IHRoaXNbIDAgXSB8fCB7fSxcblx0XHRcdFx0aSA9IDAsXG5cdFx0XHRcdGwgPSB0aGlzLmxlbmd0aDtcblxuXHRcdFx0aWYgKCB2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdHJldHVybiBlbGVtLmlubmVySFRNTDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2VlIGlmIHdlIGNhbiB0YWtlIGEgc2hvcnRjdXQgYW5kIGp1c3QgdXNlIGlubmVySFRNTFxuXHRcdFx0aWYgKCB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgIXJub0lubmVyaHRtbC50ZXN0KCB2YWx1ZSApICYmXG5cdFx0XHRcdCF3cmFwTWFwWyAoIHJ0YWdOYW1lLmV4ZWMoIHZhbHVlICkgfHwgWyBcIlwiLCBcIlwiIF0gKVsgMSBdLnRvTG93ZXJDYXNlKCkgXSApIHtcblxuXHRcdFx0XHR2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoIHJ4aHRtbFRhZywgXCI8JDE+PC8kMj5cIiApO1xuXG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRcdFx0ZWxlbSA9IHRoaXNbIGkgXSB8fCB7fTtcblxuXHRcdFx0XHRcdFx0Ly8gUmVtb3ZlIGVsZW1lbnQgbm9kZXMgYW5kIHByZXZlbnQgbWVtb3J5IGxlYWtzXG5cdFx0XHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdFx0XHRcdGpRdWVyeS5jbGVhbkRhdGEoIGdldEFsbCggZWxlbSwgZmFsc2UgKSApO1xuXHRcdFx0XHRcdFx0XHRlbGVtLmlubmVySFRNTCA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGVsZW0gPSAwO1xuXG5cdFx0XHRcdC8vIElmIHVzaW5nIGlubmVySFRNTCB0aHJvd3MgYW4gZXhjZXB0aW9uLCB1c2UgdGhlIGZhbGxiYWNrIG1ldGhvZFxuXHRcdFx0XHR9IGNhdGNoKCBlICkge31cblx0XHRcdH1cblxuXHRcdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0XHR0aGlzLmVtcHR5KCkuYXBwZW5kKCB2YWx1ZSApO1xuXHRcdFx0fVxuXHRcdH0sIG51bGwsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH0sXG5cblx0cmVwbGFjZVdpdGg6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBhcmcgPSBhcmd1bWVudHNbIDAgXTtcblxuXHRcdC8vIE1ha2UgdGhlIGNoYW5nZXMsIHJlcGxhY2luZyBlYWNoIGNvbnRleHQgZWxlbWVudCB3aXRoIHRoZSBuZXcgY29udGVudFxuXHRcdHRoaXMuZG9tTWFuaXAoIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRhcmcgPSB0aGlzLnBhcmVudE5vZGU7XG5cblx0XHRcdGpRdWVyeS5jbGVhbkRhdGEoIGdldEFsbCggdGhpcyApICk7XG5cblx0XHRcdGlmICggYXJnICkge1xuXHRcdFx0XHRhcmcucmVwbGFjZUNoaWxkKCBlbGVtLCB0aGlzICk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQvLyBGb3JjZSByZW1vdmFsIGlmIHRoZXJlIHdhcyBubyBuZXcgY29udGVudCAoZS5nLiwgZnJvbSBlbXB0eSBhcmd1bWVudHMpXG5cdFx0cmV0dXJuIGFyZyAmJiAoYXJnLmxlbmd0aCB8fCBhcmcubm9kZVR5cGUpID8gdGhpcyA6IHRoaXMucmVtb3ZlKCk7XG5cdH0sXG5cblx0ZGV0YWNoOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0cmV0dXJuIHRoaXMucmVtb3ZlKCBzZWxlY3RvciwgdHJ1ZSApO1xuXHR9LFxuXG5cdGRvbU1hbmlwOiBmdW5jdGlvbiggYXJncywgY2FsbGJhY2sgKSB7XG5cblx0XHQvLyBGbGF0dGVuIGFueSBuZXN0ZWQgYXJyYXlzXG5cdFx0YXJncyA9IGNvbmNhdC5hcHBseSggW10sIGFyZ3MgKTtcblxuXHRcdHZhciBmcmFnbWVudCwgZmlyc3QsIHNjcmlwdHMsIGhhc1NjcmlwdHMsIG5vZGUsIGRvYyxcblx0XHRcdGkgPSAwLFxuXHRcdFx0bCA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0c2V0ID0gdGhpcyxcblx0XHRcdGlOb0Nsb25lID0gbCAtIDEsXG5cdFx0XHR2YWx1ZSA9IGFyZ3NbIDAgXSxcblx0XHRcdGlzRnVuY3Rpb24gPSBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKTtcblxuXHRcdC8vIFdlIGNhbid0IGNsb25lTm9kZSBmcmFnbWVudHMgdGhhdCBjb250YWluIGNoZWNrZWQsIGluIFdlYktpdFxuXHRcdGlmICggaXNGdW5jdGlvbiB8fFxuXHRcdFx0XHQoIGwgPiAxICYmIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJlxuXHRcdFx0XHRcdCFzdXBwb3J0LmNoZWNrQ2xvbmUgJiYgcmNoZWNrZWQudGVzdCggdmFsdWUgKSApICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiggaW5kZXggKSB7XG5cdFx0XHRcdHZhciBzZWxmID0gc2V0LmVxKCBpbmRleCApO1xuXHRcdFx0XHRpZiAoIGlzRnVuY3Rpb24gKSB7XG5cdFx0XHRcdFx0YXJnc1sgMCBdID0gdmFsdWUuY2FsbCggdGhpcywgaW5kZXgsIHNlbGYuaHRtbCgpICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0c2VsZi5kb21NYW5pcCggYXJncywgY2FsbGJhY2sgKTtcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdGlmICggbCApIHtcblx0XHRcdGZyYWdtZW50ID0galF1ZXJ5LmJ1aWxkRnJhZ21lbnQoIGFyZ3MsIHRoaXNbIDAgXS5vd25lckRvY3VtZW50LCBmYWxzZSwgdGhpcyApO1xuXHRcdFx0Zmlyc3QgPSBmcmFnbWVudC5maXJzdENoaWxkO1xuXG5cdFx0XHRpZiAoIGZyYWdtZW50LmNoaWxkTm9kZXMubGVuZ3RoID09PSAxICkge1xuXHRcdFx0XHRmcmFnbWVudCA9IGZpcnN0O1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGZpcnN0ICkge1xuXHRcdFx0XHRzY3JpcHRzID0galF1ZXJ5Lm1hcCggZ2V0QWxsKCBmcmFnbWVudCwgXCJzY3JpcHRcIiApLCBkaXNhYmxlU2NyaXB0ICk7XG5cdFx0XHRcdGhhc1NjcmlwdHMgPSBzY3JpcHRzLmxlbmd0aDtcblxuXHRcdFx0XHQvLyBVc2UgdGhlIG9yaWdpbmFsIGZyYWdtZW50IGZvciB0aGUgbGFzdCBpdGVtIGluc3RlYWQgb2YgdGhlIGZpcnN0IGJlY2F1c2UgaXQgY2FuIGVuZCB1cFxuXHRcdFx0XHQvLyBiZWluZyBlbXB0aWVkIGluY29ycmVjdGx5IGluIGNlcnRhaW4gc2l0dWF0aW9ucyAoIzgwNzApLlxuXHRcdFx0XHRmb3IgKCA7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdFx0bm9kZSA9IGZyYWdtZW50O1xuXG5cdFx0XHRcdFx0aWYgKCBpICE9PSBpTm9DbG9uZSApIHtcblx0XHRcdFx0XHRcdG5vZGUgPSBqUXVlcnkuY2xvbmUoIG5vZGUsIHRydWUsIHRydWUgKTtcblxuXHRcdFx0XHRcdFx0Ly8gS2VlcCByZWZlcmVuY2VzIHRvIGNsb25lZCBzY3JpcHRzIGZvciBsYXRlciByZXN0b3JhdGlvblxuXHRcdFx0XHRcdFx0aWYgKCBoYXNTY3JpcHRzICkge1xuXHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBRdFdlYktpdFxuXHRcdFx0XHRcdFx0XHQvLyBqUXVlcnkubWVyZ2UgYmVjYXVzZSBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzXG5cdFx0XHRcdFx0XHRcdGpRdWVyeS5tZXJnZSggc2NyaXB0cywgZ2V0QWxsKCBub2RlLCBcInNjcmlwdFwiICkgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRjYWxsYmFjay5jYWxsKCB0aGlzWyBpIF0sIG5vZGUsIGkgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggaGFzU2NyaXB0cyApIHtcblx0XHRcdFx0XHRkb2MgPSBzY3JpcHRzWyBzY3JpcHRzLmxlbmd0aCAtIDEgXS5vd25lckRvY3VtZW50O1xuXG5cdFx0XHRcdFx0Ly8gUmVlbmFibGUgc2NyaXB0c1xuXHRcdFx0XHRcdGpRdWVyeS5tYXAoIHNjcmlwdHMsIHJlc3RvcmVTY3JpcHQgKTtcblxuXHRcdFx0XHRcdC8vIEV2YWx1YXRlIGV4ZWN1dGFibGUgc2NyaXB0cyBvbiBmaXJzdCBkb2N1bWVudCBpbnNlcnRpb25cblx0XHRcdFx0XHRmb3IgKCBpID0gMDsgaSA8IGhhc1NjcmlwdHM7IGkrKyApIHtcblx0XHRcdFx0XHRcdG5vZGUgPSBzY3JpcHRzWyBpIF07XG5cdFx0XHRcdFx0XHRpZiAoIHJzY3JpcHRUeXBlLnRlc3QoIG5vZGUudHlwZSB8fCBcIlwiICkgJiZcblx0XHRcdFx0XHRcdFx0IWRhdGFfcHJpdi5hY2Nlc3MoIG5vZGUsIFwiZ2xvYmFsRXZhbFwiICkgJiYgalF1ZXJ5LmNvbnRhaW5zKCBkb2MsIG5vZGUgKSApIHtcblxuXHRcdFx0XHRcdFx0XHRpZiAoIG5vZGUuc3JjICkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIE9wdGlvbmFsIEFKQVggZGVwZW5kZW5jeSwgYnV0IHdvbid0IHJ1biBzY3JpcHRzIGlmIG5vdCBwcmVzZW50XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCBqUXVlcnkuX2V2YWxVcmwgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRqUXVlcnkuX2V2YWxVcmwoIG5vZGUuc3JjICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5nbG9iYWxFdmFsKCBub2RlLnRleHRDb250ZW50LnJlcGxhY2UoIHJjbGVhblNjcmlwdCwgXCJcIiApICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fVxufSk7XG5cbmpRdWVyeS5lYWNoKHtcblx0YXBwZW5kVG86IFwiYXBwZW5kXCIsXG5cdHByZXBlbmRUbzogXCJwcmVwZW5kXCIsXG5cdGluc2VydEJlZm9yZTogXCJiZWZvcmVcIixcblx0aW5zZXJ0QWZ0ZXI6IFwiYWZ0ZXJcIixcblx0cmVwbGFjZUFsbDogXCJyZXBsYWNlV2l0aFwiXG59LCBmdW5jdGlvbiggbmFtZSwgb3JpZ2luYWwgKSB7XG5cdGpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHZhciBlbGVtcyxcblx0XHRcdHJldCA9IFtdLFxuXHRcdFx0aW5zZXJ0ID0galF1ZXJ5KCBzZWxlY3RvciApLFxuXHRcdFx0bGFzdCA9IGluc2VydC5sZW5ndGggLSAxLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRmb3IgKCA7IGkgPD0gbGFzdDsgaSsrICkge1xuXHRcdFx0ZWxlbXMgPSBpID09PSBsYXN0ID8gdGhpcyA6IHRoaXMuY2xvbmUoIHRydWUgKTtcblx0XHRcdGpRdWVyeSggaW5zZXJ0WyBpIF0gKVsgb3JpZ2luYWwgXSggZWxlbXMgKTtcblxuXHRcdFx0Ly8gU3VwcG9ydDogUXRXZWJLaXRcblx0XHRcdC8vIC5nZXQoKSBiZWNhdXNlIHB1c2guYXBwbHkoXywgYXJyYXlsaWtlKSB0aHJvd3Ncblx0XHRcdHB1c2guYXBwbHkoIHJldCwgZWxlbXMuZ2V0KCkgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIHJldCApO1xuXHR9O1xufSk7XG5cblxudmFyIGlmcmFtZSxcblx0ZWxlbWRpc3BsYXkgPSB7fTtcblxuLyoqXG4gKiBSZXRyaWV2ZSB0aGUgYWN0dWFsIGRpc3BsYXkgb2YgYSBlbGVtZW50XG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBub2RlTmFtZSBvZiB0aGUgZWxlbWVudFxuICogQHBhcmFtIHtPYmplY3R9IGRvYyBEb2N1bWVudCBvYmplY3RcbiAqL1xuLy8gQ2FsbGVkIG9ubHkgZnJvbSB3aXRoaW4gZGVmYXVsdERpc3BsYXlcbmZ1bmN0aW9uIGFjdHVhbERpc3BsYXkoIG5hbWUsIGRvYyApIHtcblx0dmFyIHN0eWxlLFxuXHRcdGVsZW0gPSBqUXVlcnkoIGRvYy5jcmVhdGVFbGVtZW50KCBuYW1lICkgKS5hcHBlbmRUbyggZG9jLmJvZHkgKSxcblxuXHRcdC8vIGdldERlZmF1bHRDb21wdXRlZFN0eWxlIG1pZ2h0IGJlIHJlbGlhYmx5IHVzZWQgb25seSBvbiBhdHRhY2hlZCBlbGVtZW50XG5cdFx0ZGlzcGxheSA9IHdpbmRvdy5nZXREZWZhdWx0Q29tcHV0ZWRTdHlsZSAmJiAoIHN0eWxlID0gd2luZG93LmdldERlZmF1bHRDb21wdXRlZFN0eWxlKCBlbGVtWyAwIF0gKSApID9cblxuXHRcdFx0Ly8gVXNlIG9mIHRoaXMgbWV0aG9kIGlzIGEgdGVtcG9yYXJ5IGZpeCAobW9yZSBsaWtlIG9wdGltaXphdGlvbikgdW50aWwgc29tZXRoaW5nIGJldHRlciBjb21lcyBhbG9uZyxcblx0XHRcdC8vIHNpbmNlIGl0IHdhcyByZW1vdmVkIGZyb20gc3BlY2lmaWNhdGlvbiBhbmQgc3VwcG9ydGVkIG9ubHkgaW4gRkZcblx0XHRcdHN0eWxlLmRpc3BsYXkgOiBqUXVlcnkuY3NzKCBlbGVtWyAwIF0sIFwiZGlzcGxheVwiICk7XG5cblx0Ly8gV2UgZG9uJ3QgaGF2ZSBhbnkgZGF0YSBzdG9yZWQgb24gdGhlIGVsZW1lbnQsXG5cdC8vIHNvIHVzZSBcImRldGFjaFwiIG1ldGhvZCBhcyBmYXN0IHdheSB0byBnZXQgcmlkIG9mIHRoZSBlbGVtZW50XG5cdGVsZW0uZGV0YWNoKCk7XG5cblx0cmV0dXJuIGRpc3BsYXk7XG59XG5cbi8qKlxuICogVHJ5IHRvIGRldGVybWluZSB0aGUgZGVmYXVsdCBkaXNwbGF5IHZhbHVlIG9mIGFuIGVsZW1lbnRcbiAqIEBwYXJhbSB7U3RyaW5nfSBub2RlTmFtZVxuICovXG5mdW5jdGlvbiBkZWZhdWx0RGlzcGxheSggbm9kZU5hbWUgKSB7XG5cdHZhciBkb2MgPSBkb2N1bWVudCxcblx0XHRkaXNwbGF5ID0gZWxlbWRpc3BsYXlbIG5vZGVOYW1lIF07XG5cblx0aWYgKCAhZGlzcGxheSApIHtcblx0XHRkaXNwbGF5ID0gYWN0dWFsRGlzcGxheSggbm9kZU5hbWUsIGRvYyApO1xuXG5cdFx0Ly8gSWYgdGhlIHNpbXBsZSB3YXkgZmFpbHMsIHJlYWQgZnJvbSBpbnNpZGUgYW4gaWZyYW1lXG5cdFx0aWYgKCBkaXNwbGF5ID09PSBcIm5vbmVcIiB8fCAhZGlzcGxheSApIHtcblxuXHRcdFx0Ly8gVXNlIHRoZSBhbHJlYWR5LWNyZWF0ZWQgaWZyYW1lIGlmIHBvc3NpYmxlXG5cdFx0XHRpZnJhbWUgPSAoaWZyYW1lIHx8IGpRdWVyeSggXCI8aWZyYW1lIGZyYW1lYm9yZGVyPScwJyB3aWR0aD0nMCcgaGVpZ2h0PScwJy8+XCIgKSkuYXBwZW5kVG8oIGRvYy5kb2N1bWVudEVsZW1lbnQgKTtcblxuXHRcdFx0Ly8gQWx3YXlzIHdyaXRlIGEgbmV3IEhUTUwgc2tlbGV0b24gc28gV2Via2l0IGFuZCBGaXJlZm94IGRvbid0IGNob2tlIG9uIHJldXNlXG5cdFx0XHRkb2MgPSBpZnJhbWVbIDAgXS5jb250ZW50RG9jdW1lbnQ7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IElFXG5cdFx0XHRkb2Mud3JpdGUoKTtcblx0XHRcdGRvYy5jbG9zZSgpO1xuXG5cdFx0XHRkaXNwbGF5ID0gYWN0dWFsRGlzcGxheSggbm9kZU5hbWUsIGRvYyApO1xuXHRcdFx0aWZyYW1lLmRldGFjaCgpO1xuXHRcdH1cblxuXHRcdC8vIFN0b3JlIHRoZSBjb3JyZWN0IGRlZmF1bHQgZGlzcGxheVxuXHRcdGVsZW1kaXNwbGF5WyBub2RlTmFtZSBdID0gZGlzcGxheTtcblx0fVxuXG5cdHJldHVybiBkaXNwbGF5O1xufVxudmFyIHJtYXJnaW4gPSAoL15tYXJnaW4vKTtcblxudmFyIHJudW1ub25weCA9IG5ldyBSZWdFeHAoIFwiXihcIiArIHBudW0gKyBcIikoPyFweClbYS16JV0rJFwiLCBcImlcIiApO1xuXG52YXIgZ2V0U3R5bGVzID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0Ly8gU3VwcG9ydDogSUU8PTExKywgRmlyZWZveDw9MzArICgjMTUwOTgsICMxNDE1MClcblx0XHQvLyBJRSB0aHJvd3Mgb24gZWxlbWVudHMgY3JlYXRlZCBpbiBwb3B1cHNcblx0XHQvLyBGRiBtZWFud2hpbGUgdGhyb3dzIG9uIGZyYW1lIGVsZW1lbnRzIHRocm91Z2ggXCJkZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlXCJcblx0XHRpZiAoIGVsZW0ub3duZXJEb2N1bWVudC5kZWZhdWx0Vmlldy5vcGVuZXIgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUoIGVsZW0sIG51bGwgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gd2luZG93LmdldENvbXB1dGVkU3R5bGUoIGVsZW0sIG51bGwgKTtcblx0fTtcblxuXG5cbmZ1bmN0aW9uIGN1ckNTUyggZWxlbSwgbmFtZSwgY29tcHV0ZWQgKSB7XG5cdHZhciB3aWR0aCwgbWluV2lkdGgsIG1heFdpZHRoLCByZXQsXG5cdFx0c3R5bGUgPSBlbGVtLnN0eWxlO1xuXG5cdGNvbXB1dGVkID0gY29tcHV0ZWQgfHwgZ2V0U3R5bGVzKCBlbGVtICk7XG5cblx0Ly8gU3VwcG9ydDogSUU5XG5cdC8vIGdldFByb3BlcnR5VmFsdWUgaXMgb25seSBuZWVkZWQgZm9yIC5jc3MoJ2ZpbHRlcicpICgjMTI1MzcpXG5cdGlmICggY29tcHV0ZWQgKSB7XG5cdFx0cmV0ID0gY29tcHV0ZWQuZ2V0UHJvcGVydHlWYWx1ZSggbmFtZSApIHx8IGNvbXB1dGVkWyBuYW1lIF07XG5cdH1cblxuXHRpZiAoIGNvbXB1dGVkICkge1xuXG5cdFx0aWYgKCByZXQgPT09IFwiXCIgJiYgIWpRdWVyeS5jb250YWlucyggZWxlbS5vd25lckRvY3VtZW50LCBlbGVtICkgKSB7XG5cdFx0XHRyZXQgPSBqUXVlcnkuc3R5bGUoIGVsZW0sIG5hbWUgKTtcblx0XHR9XG5cblx0XHQvLyBTdXBwb3J0OiBpT1MgPCA2XG5cdFx0Ly8gQSB0cmlidXRlIHRvIHRoZSBcImF3ZXNvbWUgaGFjayBieSBEZWFuIEVkd2FyZHNcIlxuXHRcdC8vIGlPUyA8IDYgKGF0IGxlYXN0KSByZXR1cm5zIHBlcmNlbnRhZ2UgZm9yIGEgbGFyZ2VyIHNldCBvZiB2YWx1ZXMsIGJ1dCB3aWR0aCBzZWVtcyB0byBiZSByZWxpYWJseSBwaXhlbHNcblx0XHQvLyB0aGlzIGlzIGFnYWluc3QgdGhlIENTU09NIGRyYWZ0IHNwZWM6IGh0dHA6Ly9kZXYudzMub3JnL2Nzc3dnL2Nzc29tLyNyZXNvbHZlZC12YWx1ZXNcblx0XHRpZiAoIHJudW1ub25weC50ZXN0KCByZXQgKSAmJiBybWFyZ2luLnRlc3QoIG5hbWUgKSApIHtcblxuXHRcdFx0Ly8gUmVtZW1iZXIgdGhlIG9yaWdpbmFsIHZhbHVlc1xuXHRcdFx0d2lkdGggPSBzdHlsZS53aWR0aDtcblx0XHRcdG1pbldpZHRoID0gc3R5bGUubWluV2lkdGg7XG5cdFx0XHRtYXhXaWR0aCA9IHN0eWxlLm1heFdpZHRoO1xuXG5cdFx0XHQvLyBQdXQgaW4gdGhlIG5ldyB2YWx1ZXMgdG8gZ2V0IGEgY29tcHV0ZWQgdmFsdWUgb3V0XG5cdFx0XHRzdHlsZS5taW5XaWR0aCA9IHN0eWxlLm1heFdpZHRoID0gc3R5bGUud2lkdGggPSByZXQ7XG5cdFx0XHRyZXQgPSBjb21wdXRlZC53aWR0aDtcblxuXHRcdFx0Ly8gUmV2ZXJ0IHRoZSBjaGFuZ2VkIHZhbHVlc1xuXHRcdFx0c3R5bGUud2lkdGggPSB3aWR0aDtcblx0XHRcdHN0eWxlLm1pbldpZHRoID0gbWluV2lkdGg7XG5cdFx0XHRzdHlsZS5tYXhXaWR0aCA9IG1heFdpZHRoO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiByZXQgIT09IHVuZGVmaW5lZCA/XG5cdFx0Ly8gU3VwcG9ydDogSUVcblx0XHQvLyBJRSByZXR1cm5zIHpJbmRleCB2YWx1ZSBhcyBhbiBpbnRlZ2VyLlxuXHRcdHJldCArIFwiXCIgOlxuXHRcdHJldDtcbn1cblxuXG5mdW5jdGlvbiBhZGRHZXRIb29rSWYoIGNvbmRpdGlvbkZuLCBob29rRm4gKSB7XG5cdC8vIERlZmluZSB0aGUgaG9vaywgd2UnbGwgY2hlY2sgb24gdGhlIGZpcnN0IHJ1biBpZiBpdCdzIHJlYWxseSBuZWVkZWQuXG5cdHJldHVybiB7XG5cdFx0Z2V0OiBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggY29uZGl0aW9uRm4oKSApIHtcblx0XHRcdFx0Ly8gSG9vayBub3QgbmVlZGVkIChvciBpdCdzIG5vdCBwb3NzaWJsZSB0byB1c2UgaXQgZHVlXG5cdFx0XHRcdC8vIHRvIG1pc3NpbmcgZGVwZW5kZW5jeSksIHJlbW92ZSBpdC5cblx0XHRcdFx0ZGVsZXRlIHRoaXMuZ2V0O1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdC8vIEhvb2sgbmVlZGVkOyByZWRlZmluZSBpdCBzbyB0aGF0IHRoZSBzdXBwb3J0IHRlc3QgaXMgbm90IGV4ZWN1dGVkIGFnYWluLlxuXHRcdFx0cmV0dXJuICh0aGlzLmdldCA9IGhvb2tGbikuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdH1cblx0fTtcbn1cblxuXG4oZnVuY3Rpb24oKSB7XG5cdHZhciBwaXhlbFBvc2l0aW9uVmFsLCBib3hTaXppbmdSZWxpYWJsZVZhbCxcblx0XHRkb2NFbGVtID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LFxuXHRcdGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiZGl2XCIgKSxcblx0XHRkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICk7XG5cblx0aWYgKCAhZGl2LnN0eWxlICkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdC8vIFN1cHBvcnQ6IElFOS0xMStcblx0Ly8gU3R5bGUgb2YgY2xvbmVkIGVsZW1lbnQgYWZmZWN0cyBzb3VyY2UgZWxlbWVudCBjbG9uZWQgKCM4OTA4KVxuXHRkaXYuc3R5bGUuYmFja2dyb3VuZENsaXAgPSBcImNvbnRlbnQtYm94XCI7XG5cdGRpdi5jbG9uZU5vZGUoIHRydWUgKS5zdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9IFwiXCI7XG5cdHN1cHBvcnQuY2xlYXJDbG9uZVN0eWxlID0gZGl2LnN0eWxlLmJhY2tncm91bmRDbGlwID09PSBcImNvbnRlbnQtYm94XCI7XG5cblx0Y29udGFpbmVyLnN0eWxlLmNzc1RleHQgPSBcImJvcmRlcjowO3dpZHRoOjA7aGVpZ2h0OjA7dG9wOjA7bGVmdDotOTk5OXB4O21hcmdpbi10b3A6MXB4O1wiICtcblx0XHRcInBvc2l0aW9uOmFic29sdXRlXCI7XG5cdGNvbnRhaW5lci5hcHBlbmRDaGlsZCggZGl2ICk7XG5cblx0Ly8gRXhlY3V0aW5nIGJvdGggcGl4ZWxQb3NpdGlvbiAmIGJveFNpemluZ1JlbGlhYmxlIHRlc3RzIHJlcXVpcmUgb25seSBvbmUgbGF5b3V0XG5cdC8vIHNvIHRoZXkncmUgZXhlY3V0ZWQgYXQgdGhlIHNhbWUgdGltZSB0byBzYXZlIHRoZSBzZWNvbmQgY29tcHV0YXRpb24uXG5cdGZ1bmN0aW9uIGNvbXB1dGVQaXhlbFBvc2l0aW9uQW5kQm94U2l6aW5nUmVsaWFibGUoKSB7XG5cdFx0ZGl2LnN0eWxlLmNzc1RleHQgPVxuXHRcdFx0Ly8gU3VwcG9ydDogRmlyZWZveDwyOSwgQW5kcm9pZCAyLjNcblx0XHRcdC8vIFZlbmRvci1wcmVmaXggYm94LXNpemluZ1xuXHRcdFx0XCItd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtcIiArXG5cdFx0XHRcImJveC1zaXppbmc6Ym9yZGVyLWJveDtkaXNwbGF5OmJsb2NrO21hcmdpbi10b3A6MSU7dG9wOjElO1wiICtcblx0XHRcdFwiYm9yZGVyOjFweDtwYWRkaW5nOjFweDt3aWR0aDo0cHg7cG9zaXRpb246YWJzb2x1dGVcIjtcblx0XHRkaXYuaW5uZXJIVE1MID0gXCJcIjtcblx0XHRkb2NFbGVtLmFwcGVuZENoaWxkKCBjb250YWluZXIgKTtcblxuXHRcdHZhciBkaXZTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKCBkaXYsIG51bGwgKTtcblx0XHRwaXhlbFBvc2l0aW9uVmFsID0gZGl2U3R5bGUudG9wICE9PSBcIjElXCI7XG5cdFx0Ym94U2l6aW5nUmVsaWFibGVWYWwgPSBkaXZTdHlsZS53aWR0aCA9PT0gXCI0cHhcIjtcblxuXHRcdGRvY0VsZW0ucmVtb3ZlQ2hpbGQoIGNvbnRhaW5lciApO1xuXHR9XG5cblx0Ly8gU3VwcG9ydDogbm9kZS5qcyBqc2RvbVxuXHQvLyBEb24ndCBhc3N1bWUgdGhhdCBnZXRDb21wdXRlZFN0eWxlIGlzIGEgcHJvcGVydHkgb2YgdGhlIGdsb2JhbCBvYmplY3Rcblx0aWYgKCB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSApIHtcblx0XHRqUXVlcnkuZXh0ZW5kKCBzdXBwb3J0LCB7XG5cdFx0XHRwaXhlbFBvc2l0aW9uOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHQvLyBUaGlzIHRlc3QgaXMgZXhlY3V0ZWQgb25seSBvbmNlIGJ1dCB3ZSBzdGlsbCBkbyBtZW1vaXppbmdcblx0XHRcdFx0Ly8gc2luY2Ugd2UgY2FuIHVzZSB0aGUgYm94U2l6aW5nUmVsaWFibGUgcHJlLWNvbXB1dGluZy5cblx0XHRcdFx0Ly8gTm8gbmVlZCB0byBjaGVjayBpZiB0aGUgdGVzdCB3YXMgYWxyZWFkeSBwZXJmb3JtZWQsIHRob3VnaC5cblx0XHRcdFx0Y29tcHV0ZVBpeGVsUG9zaXRpb25BbmRCb3hTaXppbmdSZWxpYWJsZSgpO1xuXHRcdFx0XHRyZXR1cm4gcGl4ZWxQb3NpdGlvblZhbDtcblx0XHRcdH0sXG5cdFx0XHRib3hTaXppbmdSZWxpYWJsZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggYm94U2l6aW5nUmVsaWFibGVWYWwgPT0gbnVsbCApIHtcblx0XHRcdFx0XHRjb21wdXRlUGl4ZWxQb3NpdGlvbkFuZEJveFNpemluZ1JlbGlhYmxlKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIGJveFNpemluZ1JlbGlhYmxlVmFsO1xuXHRcdFx0fSxcblx0XHRcdHJlbGlhYmxlTWFyZ2luUmlnaHQ6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgMi4zXG5cdFx0XHRcdC8vIENoZWNrIGlmIGRpdiB3aXRoIGV4cGxpY2l0IHdpZHRoIGFuZCBubyBtYXJnaW4tcmlnaHQgaW5jb3JyZWN0bHlcblx0XHRcdFx0Ly8gZ2V0cyBjb21wdXRlZCBtYXJnaW4tcmlnaHQgYmFzZWQgb24gd2lkdGggb2YgY29udGFpbmVyLiAoIzMzMzMpXG5cdFx0XHRcdC8vIFdlYktpdCBCdWcgMTMzNDMgLSBnZXRDb21wdXRlZFN0eWxlIHJldHVybnMgd3JvbmcgdmFsdWUgZm9yIG1hcmdpbi1yaWdodFxuXHRcdFx0XHQvLyBUaGlzIHN1cHBvcnQgZnVuY3Rpb24gaXMgb25seSBleGVjdXRlZCBvbmNlIHNvIG5vIG1lbW9pemluZyBpcyBuZWVkZWQuXG5cdFx0XHRcdHZhciByZXQsXG5cdFx0XHRcdFx0bWFyZ2luRGl2ID0gZGl2LmFwcGVuZENoaWxkKCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICkgKTtcblxuXHRcdFx0XHQvLyBSZXNldCBDU1M6IGJveC1zaXppbmc7IGRpc3BsYXk7IG1hcmdpbjsgYm9yZGVyOyBwYWRkaW5nXG5cdFx0XHRcdG1hcmdpbkRpdi5zdHlsZS5jc3NUZXh0ID0gZGl2LnN0eWxlLmNzc1RleHQgPVxuXHRcdFx0XHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3g8MjksIEFuZHJvaWQgMi4zXG5cdFx0XHRcdFx0Ly8gVmVuZG9yLXByZWZpeCBib3gtc2l6aW5nXG5cdFx0XHRcdFx0XCItd2Via2l0LWJveC1zaXppbmc6Y29udGVudC1ib3g7LW1vei1ib3gtc2l6aW5nOmNvbnRlbnQtYm94O1wiICtcblx0XHRcdFx0XHRcImJveC1zaXppbmc6Y29udGVudC1ib3g7ZGlzcGxheTpibG9jazttYXJnaW46MDtib3JkZXI6MDtwYWRkaW5nOjBcIjtcblx0XHRcdFx0bWFyZ2luRGl2LnN0eWxlLm1hcmdpblJpZ2h0ID0gbWFyZ2luRGl2LnN0eWxlLndpZHRoID0gXCIwXCI7XG5cdFx0XHRcdGRpdi5zdHlsZS53aWR0aCA9IFwiMXB4XCI7XG5cdFx0XHRcdGRvY0VsZW0uYXBwZW5kQ2hpbGQoIGNvbnRhaW5lciApO1xuXG5cdFx0XHRcdHJldCA9ICFwYXJzZUZsb2F0KCB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSggbWFyZ2luRGl2LCBudWxsICkubWFyZ2luUmlnaHQgKTtcblxuXHRcdFx0XHRkb2NFbGVtLnJlbW92ZUNoaWxkKCBjb250YWluZXIgKTtcblx0XHRcdFx0ZGl2LnJlbW92ZUNoaWxkKCBtYXJnaW5EaXYgKTtcblxuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59KSgpO1xuXG5cbi8vIEEgbWV0aG9kIGZvciBxdWlja2x5IHN3YXBwaW5nIGluL291dCBDU1MgcHJvcGVydGllcyB0byBnZXQgY29ycmVjdCBjYWxjdWxhdGlvbnMuXG5qUXVlcnkuc3dhcCA9IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBjYWxsYmFjaywgYXJncyApIHtcblx0dmFyIHJldCwgbmFtZSxcblx0XHRvbGQgPSB7fTtcblxuXHQvLyBSZW1lbWJlciB0aGUgb2xkIHZhbHVlcywgYW5kIGluc2VydCB0aGUgbmV3IG9uZXNcblx0Zm9yICggbmFtZSBpbiBvcHRpb25zICkge1xuXHRcdG9sZFsgbmFtZSBdID0gZWxlbS5zdHlsZVsgbmFtZSBdO1xuXHRcdGVsZW0uc3R5bGVbIG5hbWUgXSA9IG9wdGlvbnNbIG5hbWUgXTtcblx0fVxuXG5cdHJldCA9IGNhbGxiYWNrLmFwcGx5KCBlbGVtLCBhcmdzIHx8IFtdICk7XG5cblx0Ly8gUmV2ZXJ0IHRoZSBvbGQgdmFsdWVzXG5cdGZvciAoIG5hbWUgaW4gb3B0aW9ucyApIHtcblx0XHRlbGVtLnN0eWxlWyBuYW1lIF0gPSBvbGRbIG5hbWUgXTtcblx0fVxuXG5cdHJldHVybiByZXQ7XG59O1xuXG5cbnZhclxuXHQvLyBTd2FwcGFibGUgaWYgZGlzcGxheSBpcyBub25lIG9yIHN0YXJ0cyB3aXRoIHRhYmxlIGV4Y2VwdCBcInRhYmxlXCIsIFwidGFibGUtY2VsbFwiLCBvciBcInRhYmxlLWNhcHRpb25cIlxuXHQvLyBTZWUgaGVyZSBmb3IgZGlzcGxheSB2YWx1ZXM6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvQ1NTL2Rpc3BsYXlcblx0cmRpc3BsYXlzd2FwID0gL14obm9uZXx0YWJsZSg/IS1jW2VhXSkuKykvLFxuXHRybnVtc3BsaXQgPSBuZXcgUmVnRXhwKCBcIl4oXCIgKyBwbnVtICsgXCIpKC4qKSRcIiwgXCJpXCIgKSxcblx0cnJlbE51bSA9IG5ldyBSZWdFeHAoIFwiXihbKy1dKT0oXCIgKyBwbnVtICsgXCIpXCIsIFwiaVwiICksXG5cblx0Y3NzU2hvdyA9IHsgcG9zaXRpb246IFwiYWJzb2x1dGVcIiwgdmlzaWJpbGl0eTogXCJoaWRkZW5cIiwgZGlzcGxheTogXCJibG9ja1wiIH0sXG5cdGNzc05vcm1hbFRyYW5zZm9ybSA9IHtcblx0XHRsZXR0ZXJTcGFjaW5nOiBcIjBcIixcblx0XHRmb250V2VpZ2h0OiBcIjQwMFwiXG5cdH0sXG5cblx0Y3NzUHJlZml4ZXMgPSBbIFwiV2Via2l0XCIsIFwiT1wiLCBcIk1velwiLCBcIm1zXCIgXTtcblxuLy8gUmV0dXJuIGEgY3NzIHByb3BlcnR5IG1hcHBlZCB0byBhIHBvdGVudGlhbGx5IHZlbmRvciBwcmVmaXhlZCBwcm9wZXJ0eVxuZnVuY3Rpb24gdmVuZG9yUHJvcE5hbWUoIHN0eWxlLCBuYW1lICkge1xuXG5cdC8vIFNob3J0Y3V0IGZvciBuYW1lcyB0aGF0IGFyZSBub3QgdmVuZG9yIHByZWZpeGVkXG5cdGlmICggbmFtZSBpbiBzdHlsZSApIHtcblx0XHRyZXR1cm4gbmFtZTtcblx0fVxuXG5cdC8vIENoZWNrIGZvciB2ZW5kb3IgcHJlZml4ZWQgbmFtZXNcblx0dmFyIGNhcE5hbWUgPSBuYW1lWzBdLnRvVXBwZXJDYXNlKCkgKyBuYW1lLnNsaWNlKDEpLFxuXHRcdG9yaWdOYW1lID0gbmFtZSxcblx0XHRpID0gY3NzUHJlZml4ZXMubGVuZ3RoO1xuXG5cdHdoaWxlICggaS0tICkge1xuXHRcdG5hbWUgPSBjc3NQcmVmaXhlc1sgaSBdICsgY2FwTmFtZTtcblx0XHRpZiAoIG5hbWUgaW4gc3R5bGUgKSB7XG5cdFx0XHRyZXR1cm4gbmFtZTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gb3JpZ05hbWU7XG59XG5cbmZ1bmN0aW9uIHNldFBvc2l0aXZlTnVtYmVyKCBlbGVtLCB2YWx1ZSwgc3VidHJhY3QgKSB7XG5cdHZhciBtYXRjaGVzID0gcm51bXNwbGl0LmV4ZWMoIHZhbHVlICk7XG5cdHJldHVybiBtYXRjaGVzID9cblx0XHQvLyBHdWFyZCBhZ2FpbnN0IHVuZGVmaW5lZCBcInN1YnRyYWN0XCIsIGUuZy4sIHdoZW4gdXNlZCBhcyBpbiBjc3NIb29rc1xuXHRcdE1hdGgubWF4KCAwLCBtYXRjaGVzWyAxIF0gLSAoIHN1YnRyYWN0IHx8IDAgKSApICsgKCBtYXRjaGVzWyAyIF0gfHwgXCJweFwiICkgOlxuXHRcdHZhbHVlO1xufVxuXG5mdW5jdGlvbiBhdWdtZW50V2lkdGhPckhlaWdodCggZWxlbSwgbmFtZSwgZXh0cmEsIGlzQm9yZGVyQm94LCBzdHlsZXMgKSB7XG5cdHZhciBpID0gZXh0cmEgPT09ICggaXNCb3JkZXJCb3ggPyBcImJvcmRlclwiIDogXCJjb250ZW50XCIgKSA/XG5cdFx0Ly8gSWYgd2UgYWxyZWFkeSBoYXZlIHRoZSByaWdodCBtZWFzdXJlbWVudCwgYXZvaWQgYXVnbWVudGF0aW9uXG5cdFx0NCA6XG5cdFx0Ly8gT3RoZXJ3aXNlIGluaXRpYWxpemUgZm9yIGhvcml6b250YWwgb3IgdmVydGljYWwgcHJvcGVydGllc1xuXHRcdG5hbWUgPT09IFwid2lkdGhcIiA/IDEgOiAwLFxuXG5cdFx0dmFsID0gMDtcblxuXHRmb3IgKCA7IGkgPCA0OyBpICs9IDIgKSB7XG5cdFx0Ly8gQm90aCBib3ggbW9kZWxzIGV4Y2x1ZGUgbWFyZ2luLCBzbyBhZGQgaXQgaWYgd2Ugd2FudCBpdFxuXHRcdGlmICggZXh0cmEgPT09IFwibWFyZ2luXCIgKSB7XG5cdFx0XHR2YWwgKz0galF1ZXJ5LmNzcyggZWxlbSwgZXh0cmEgKyBjc3NFeHBhbmRbIGkgXSwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBpc0JvcmRlckJveCApIHtcblx0XHRcdC8vIGJvcmRlci1ib3ggaW5jbHVkZXMgcGFkZGluZywgc28gcmVtb3ZlIGl0IGlmIHdlIHdhbnQgY29udGVudFxuXHRcdFx0aWYgKCBleHRyYSA9PT0gXCJjb250ZW50XCIgKSB7XG5cdFx0XHRcdHZhbCAtPSBqUXVlcnkuY3NzKCBlbGVtLCBcInBhZGRpbmdcIiArIGNzc0V4cGFuZFsgaSBdLCB0cnVlLCBzdHlsZXMgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQXQgdGhpcyBwb2ludCwgZXh0cmEgaXNuJ3QgYm9yZGVyIG5vciBtYXJnaW4sIHNvIHJlbW92ZSBib3JkZXJcblx0XHRcdGlmICggZXh0cmEgIT09IFwibWFyZ2luXCIgKSB7XG5cdFx0XHRcdHZhbCAtPSBqUXVlcnkuY3NzKCBlbGVtLCBcImJvcmRlclwiICsgY3NzRXhwYW5kWyBpIF0gKyBcIldpZHRoXCIsIHRydWUsIHN0eWxlcyApO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBBdCB0aGlzIHBvaW50LCBleHRyYSBpc24ndCBjb250ZW50LCBzbyBhZGQgcGFkZGluZ1xuXHRcdFx0dmFsICs9IGpRdWVyeS5jc3MoIGVsZW0sIFwicGFkZGluZ1wiICsgY3NzRXhwYW5kWyBpIF0sIHRydWUsIHN0eWxlcyApO1xuXG5cdFx0XHQvLyBBdCB0aGlzIHBvaW50LCBleHRyYSBpc24ndCBjb250ZW50IG5vciBwYWRkaW5nLCBzbyBhZGQgYm9yZGVyXG5cdFx0XHRpZiAoIGV4dHJhICE9PSBcInBhZGRpbmdcIiApIHtcblx0XHRcdFx0dmFsICs9IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm9yZGVyXCIgKyBjc3NFeHBhbmRbIGkgXSArIFwiV2lkdGhcIiwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHZhbDtcbn1cblxuZnVuY3Rpb24gZ2V0V2lkdGhPckhlaWdodCggZWxlbSwgbmFtZSwgZXh0cmEgKSB7XG5cblx0Ly8gU3RhcnQgd2l0aCBvZmZzZXQgcHJvcGVydHksIHdoaWNoIGlzIGVxdWl2YWxlbnQgdG8gdGhlIGJvcmRlci1ib3ggdmFsdWVcblx0dmFyIHZhbHVlSXNCb3JkZXJCb3ggPSB0cnVlLFxuXHRcdHZhbCA9IG5hbWUgPT09IFwid2lkdGhcIiA/IGVsZW0ub2Zmc2V0V2lkdGggOiBlbGVtLm9mZnNldEhlaWdodCxcblx0XHRzdHlsZXMgPSBnZXRTdHlsZXMoIGVsZW0gKSxcblx0XHRpc0JvcmRlckJveCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm94U2l6aW5nXCIsIGZhbHNlLCBzdHlsZXMgKSA9PT0gXCJib3JkZXItYm94XCI7XG5cblx0Ly8gU29tZSBub24taHRtbCBlbGVtZW50cyByZXR1cm4gdW5kZWZpbmVkIGZvciBvZmZzZXRXaWR0aCwgc28gY2hlY2sgZm9yIG51bGwvdW5kZWZpbmVkXG5cdC8vIHN2ZyAtIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY0OTI4NVxuXHQvLyBNYXRoTUwgLSBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD00OTE2Njhcblx0aWYgKCB2YWwgPD0gMCB8fCB2YWwgPT0gbnVsbCApIHtcblx0XHQvLyBGYWxsIGJhY2sgdG8gY29tcHV0ZWQgdGhlbiB1bmNvbXB1dGVkIGNzcyBpZiBuZWNlc3Nhcnlcblx0XHR2YWwgPSBjdXJDU1MoIGVsZW0sIG5hbWUsIHN0eWxlcyApO1xuXHRcdGlmICggdmFsIDwgMCB8fCB2YWwgPT0gbnVsbCApIHtcblx0XHRcdHZhbCA9IGVsZW0uc3R5bGVbIG5hbWUgXTtcblx0XHR9XG5cblx0XHQvLyBDb21wdXRlZCB1bml0IGlzIG5vdCBwaXhlbHMuIFN0b3AgaGVyZSBhbmQgcmV0dXJuLlxuXHRcdGlmICggcm51bW5vbnB4LnRlc3QodmFsKSApIHtcblx0XHRcdHJldHVybiB2YWw7XG5cdFx0fVxuXG5cdFx0Ly8gQ2hlY2sgZm9yIHN0eWxlIGluIGNhc2UgYSBicm93c2VyIHdoaWNoIHJldHVybnMgdW5yZWxpYWJsZSB2YWx1ZXNcblx0XHQvLyBmb3IgZ2V0Q29tcHV0ZWRTdHlsZSBzaWxlbnRseSBmYWxscyBiYWNrIHRvIHRoZSByZWxpYWJsZSBlbGVtLnN0eWxlXG5cdFx0dmFsdWVJc0JvcmRlckJveCA9IGlzQm9yZGVyQm94ICYmXG5cdFx0XHQoIHN1cHBvcnQuYm94U2l6aW5nUmVsaWFibGUoKSB8fCB2YWwgPT09IGVsZW0uc3R5bGVbIG5hbWUgXSApO1xuXG5cdFx0Ly8gTm9ybWFsaXplIFwiXCIsIGF1dG8sIGFuZCBwcmVwYXJlIGZvciBleHRyYVxuXHRcdHZhbCA9IHBhcnNlRmxvYXQoIHZhbCApIHx8IDA7XG5cdH1cblxuXHQvLyBVc2UgdGhlIGFjdGl2ZSBib3gtc2l6aW5nIG1vZGVsIHRvIGFkZC9zdWJ0cmFjdCBpcnJlbGV2YW50IHN0eWxlc1xuXHRyZXR1cm4gKCB2YWwgK1xuXHRcdGF1Z21lbnRXaWR0aE9ySGVpZ2h0KFxuXHRcdFx0ZWxlbSxcblx0XHRcdG5hbWUsXG5cdFx0XHRleHRyYSB8fCAoIGlzQm9yZGVyQm94ID8gXCJib3JkZXJcIiA6IFwiY29udGVudFwiICksXG5cdFx0XHR2YWx1ZUlzQm9yZGVyQm94LFxuXHRcdFx0c3R5bGVzXG5cdFx0KVxuXHQpICsgXCJweFwiO1xufVxuXG5mdW5jdGlvbiBzaG93SGlkZSggZWxlbWVudHMsIHNob3cgKSB7XG5cdHZhciBkaXNwbGF5LCBlbGVtLCBoaWRkZW4sXG5cdFx0dmFsdWVzID0gW10sXG5cdFx0aW5kZXggPSAwLFxuXHRcdGxlbmd0aCA9IGVsZW1lbnRzLmxlbmd0aDtcblxuXHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdGVsZW0gPSBlbGVtZW50c1sgaW5kZXggXTtcblx0XHRpZiAoICFlbGVtLnN0eWxlICkge1xuXHRcdFx0Y29udGludWU7XG5cdFx0fVxuXG5cdFx0dmFsdWVzWyBpbmRleCBdID0gZGF0YV9wcml2LmdldCggZWxlbSwgXCJvbGRkaXNwbGF5XCIgKTtcblx0XHRkaXNwbGF5ID0gZWxlbS5zdHlsZS5kaXNwbGF5O1xuXHRcdGlmICggc2hvdyApIHtcblx0XHRcdC8vIFJlc2V0IHRoZSBpbmxpbmUgZGlzcGxheSBvZiB0aGlzIGVsZW1lbnQgdG8gbGVhcm4gaWYgaXQgaXNcblx0XHRcdC8vIGJlaW5nIGhpZGRlbiBieSBjYXNjYWRlZCBydWxlcyBvciBub3Rcblx0XHRcdGlmICggIXZhbHVlc1sgaW5kZXggXSAmJiBkaXNwbGF5ID09PSBcIm5vbmVcIiApIHtcblx0XHRcdFx0ZWxlbS5zdHlsZS5kaXNwbGF5ID0gXCJcIjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IGVsZW1lbnRzIHdoaWNoIGhhdmUgYmVlbiBvdmVycmlkZGVuIHdpdGggZGlzcGxheTogbm9uZVxuXHRcdFx0Ly8gaW4gYSBzdHlsZXNoZWV0IHRvIHdoYXRldmVyIHRoZSBkZWZhdWx0IGJyb3dzZXIgc3R5bGUgaXNcblx0XHRcdC8vIGZvciBzdWNoIGFuIGVsZW1lbnRcblx0XHRcdGlmICggZWxlbS5zdHlsZS5kaXNwbGF5ID09PSBcIlwiICYmIGlzSGlkZGVuKCBlbGVtICkgKSB7XG5cdFx0XHRcdHZhbHVlc1sgaW5kZXggXSA9IGRhdGFfcHJpdi5hY2Nlc3MoIGVsZW0sIFwib2xkZGlzcGxheVwiLCBkZWZhdWx0RGlzcGxheShlbGVtLm5vZGVOYW1lKSApO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRoaWRkZW4gPSBpc0hpZGRlbiggZWxlbSApO1xuXG5cdFx0XHRpZiAoIGRpc3BsYXkgIT09IFwibm9uZVwiIHx8ICFoaWRkZW4gKSB7XG5cdFx0XHRcdGRhdGFfcHJpdi5zZXQoIGVsZW0sIFwib2xkZGlzcGxheVwiLCBoaWRkZW4gPyBkaXNwbGF5IDogalF1ZXJ5LmNzcyggZWxlbSwgXCJkaXNwbGF5XCIgKSApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIFNldCB0aGUgZGlzcGxheSBvZiBtb3N0IG9mIHRoZSBlbGVtZW50cyBpbiBhIHNlY29uZCBsb29wXG5cdC8vIHRvIGF2b2lkIHRoZSBjb25zdGFudCByZWZsb3dcblx0Zm9yICggaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRlbGVtID0gZWxlbWVudHNbIGluZGV4IF07XG5cdFx0aWYgKCAhZWxlbS5zdHlsZSApIHtcblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblx0XHRpZiAoICFzaG93IHx8IGVsZW0uc3R5bGUuZGlzcGxheSA9PT0gXCJub25lXCIgfHwgZWxlbS5zdHlsZS5kaXNwbGF5ID09PSBcIlwiICkge1xuXHRcdFx0ZWxlbS5zdHlsZS5kaXNwbGF5ID0gc2hvdyA/IHZhbHVlc1sgaW5kZXggXSB8fCBcIlwiIDogXCJub25lXCI7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW1lbnRzO1xufVxuXG5qUXVlcnkuZXh0ZW5kKHtcblxuXHQvLyBBZGQgaW4gc3R5bGUgcHJvcGVydHkgaG9va3MgZm9yIG92ZXJyaWRpbmcgdGhlIGRlZmF1bHRcblx0Ly8gYmVoYXZpb3Igb2YgZ2V0dGluZyBhbmQgc2V0dGluZyBhIHN0eWxlIHByb3BlcnR5XG5cdGNzc0hvb2tzOiB7XG5cdFx0b3BhY2l0eToge1xuXHRcdFx0Z2V0OiBmdW5jdGlvbiggZWxlbSwgY29tcHV0ZWQgKSB7XG5cdFx0XHRcdGlmICggY29tcHV0ZWQgKSB7XG5cblx0XHRcdFx0XHQvLyBXZSBzaG91bGQgYWx3YXlzIGdldCBhIG51bWJlciBiYWNrIGZyb20gb3BhY2l0eVxuXHRcdFx0XHRcdHZhciByZXQgPSBjdXJDU1MoIGVsZW0sIFwib3BhY2l0eVwiICk7XG5cdFx0XHRcdFx0cmV0dXJuIHJldCA9PT0gXCJcIiA/IFwiMVwiIDogcmV0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdC8vIERvbid0IGF1dG9tYXRpY2FsbHkgYWRkIFwicHhcIiB0byB0aGVzZSBwb3NzaWJseS11bml0bGVzcyBwcm9wZXJ0aWVzXG5cdGNzc051bWJlcjoge1xuXHRcdFwiY29sdW1uQ291bnRcIjogdHJ1ZSxcblx0XHRcImZpbGxPcGFjaXR5XCI6IHRydWUsXG5cdFx0XCJmbGV4R3Jvd1wiOiB0cnVlLFxuXHRcdFwiZmxleFNocmlua1wiOiB0cnVlLFxuXHRcdFwiZm9udFdlaWdodFwiOiB0cnVlLFxuXHRcdFwibGluZUhlaWdodFwiOiB0cnVlLFxuXHRcdFwib3BhY2l0eVwiOiB0cnVlLFxuXHRcdFwib3JkZXJcIjogdHJ1ZSxcblx0XHRcIm9ycGhhbnNcIjogdHJ1ZSxcblx0XHRcIndpZG93c1wiOiB0cnVlLFxuXHRcdFwiekluZGV4XCI6IHRydWUsXG5cdFx0XCJ6b29tXCI6IHRydWVcblx0fSxcblxuXHQvLyBBZGQgaW4gcHJvcGVydGllcyB3aG9zZSBuYW1lcyB5b3Ugd2lzaCB0byBmaXggYmVmb3JlXG5cdC8vIHNldHRpbmcgb3IgZ2V0dGluZyB0aGUgdmFsdWVcblx0Y3NzUHJvcHM6IHtcblx0XHRcImZsb2F0XCI6IFwiY3NzRmxvYXRcIlxuXHR9LFxuXG5cdC8vIEdldCBhbmQgc2V0IHRoZSBzdHlsZSBwcm9wZXJ0eSBvbiBhIERPTSBOb2RlXG5cdHN0eWxlOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUsIGV4dHJhICkge1xuXG5cdFx0Ly8gRG9uJ3Qgc2V0IHN0eWxlcyBvbiB0ZXh0IGFuZCBjb21tZW50IG5vZGVzXG5cdFx0aWYgKCAhZWxlbSB8fCBlbGVtLm5vZGVUeXBlID09PSAzIHx8IGVsZW0ubm9kZVR5cGUgPT09IDggfHwgIWVsZW0uc3R5bGUgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gTWFrZSBzdXJlIHRoYXQgd2UncmUgd29ya2luZyB3aXRoIHRoZSByaWdodCBuYW1lXG5cdFx0dmFyIHJldCwgdHlwZSwgaG9va3MsXG5cdFx0XHRvcmlnTmFtZSA9IGpRdWVyeS5jYW1lbENhc2UoIG5hbWUgKSxcblx0XHRcdHN0eWxlID0gZWxlbS5zdHlsZTtcblxuXHRcdG5hbWUgPSBqUXVlcnkuY3NzUHJvcHNbIG9yaWdOYW1lIF0gfHwgKCBqUXVlcnkuY3NzUHJvcHNbIG9yaWdOYW1lIF0gPSB2ZW5kb3JQcm9wTmFtZSggc3R5bGUsIG9yaWdOYW1lICkgKTtcblxuXHRcdC8vIEdldHMgaG9vayBmb3IgdGhlIHByZWZpeGVkIHZlcnNpb24sIHRoZW4gdW5wcmVmaXhlZCB2ZXJzaW9uXG5cdFx0aG9va3MgPSBqUXVlcnkuY3NzSG9va3NbIG5hbWUgXSB8fCBqUXVlcnkuY3NzSG9va3NbIG9yaWdOYW1lIF07XG5cblx0XHQvLyBDaGVjayBpZiB3ZSdyZSBzZXR0aW5nIGEgdmFsdWVcblx0XHRpZiAoIHZhbHVlICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHR0eXBlID0gdHlwZW9mIHZhbHVlO1xuXG5cdFx0XHQvLyBDb252ZXJ0IFwiKz1cIiBvciBcIi09XCIgdG8gcmVsYXRpdmUgbnVtYmVycyAoIzczNDUpXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwic3RyaW5nXCIgJiYgKHJldCA9IHJyZWxOdW0uZXhlYyggdmFsdWUgKSkgKSB7XG5cdFx0XHRcdHZhbHVlID0gKCByZXRbMV0gKyAxICkgKiByZXRbMl0gKyBwYXJzZUZsb2F0KCBqUXVlcnkuY3NzKCBlbGVtLCBuYW1lICkgKTtcblx0XHRcdFx0Ly8gRml4ZXMgYnVnICM5MjM3XG5cdFx0XHRcdHR5cGUgPSBcIm51bWJlclwiO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBNYWtlIHN1cmUgdGhhdCBudWxsIGFuZCBOYU4gdmFsdWVzIGFyZW4ndCBzZXQgKCM3MTE2KVxuXHRcdFx0aWYgKCB2YWx1ZSA9PSBudWxsIHx8IHZhbHVlICE9PSB2YWx1ZSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBJZiBhIG51bWJlciwgYWRkICdweCcgdG8gdGhlIChleGNlcHQgZm9yIGNlcnRhaW4gQ1NTIHByb3BlcnRpZXMpXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwibnVtYmVyXCIgJiYgIWpRdWVyeS5jc3NOdW1iZXJbIG9yaWdOYW1lIF0gKSB7XG5cdFx0XHRcdHZhbHVlICs9IFwicHhcIjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU5LTExK1xuXHRcdFx0Ly8gYmFja2dyb3VuZC0qIHByb3BzIGFmZmVjdCBvcmlnaW5hbCBjbG9uZSdzIHZhbHVlc1xuXHRcdFx0aWYgKCAhc3VwcG9ydC5jbGVhckNsb25lU3R5bGUgJiYgdmFsdWUgPT09IFwiXCIgJiYgbmFtZS5pbmRleE9mKCBcImJhY2tncm91bmRcIiApID09PSAwICkge1xuXHRcdFx0XHRzdHlsZVsgbmFtZSBdID0gXCJpbmhlcml0XCI7XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQsIHVzZSB0aGF0IHZhbHVlLCBvdGhlcndpc2UganVzdCBzZXQgdGhlIHNwZWNpZmllZCB2YWx1ZVxuXHRcdFx0aWYgKCAhaG9va3MgfHwgIShcInNldFwiIGluIGhvb2tzKSB8fCAodmFsdWUgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBleHRyYSApKSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRzdHlsZVsgbmFtZSBdID0gdmFsdWU7XG5cdFx0XHR9XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gSWYgYSBob29rIHdhcyBwcm92aWRlZCBnZXQgdGhlIG5vbi1jb21wdXRlZCB2YWx1ZSBmcm9tIHRoZXJlXG5cdFx0XHRpZiAoIGhvb2tzICYmIFwiZ2V0XCIgaW4gaG9va3MgJiYgKHJldCA9IGhvb2tzLmdldCggZWxlbSwgZmFsc2UsIGV4dHJhICkpICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHR9XG5cblx0XHRcdC8vIE90aGVyd2lzZSBqdXN0IGdldCB0aGUgdmFsdWUgZnJvbSB0aGUgc3R5bGUgb2JqZWN0XG5cdFx0XHRyZXR1cm4gc3R5bGVbIG5hbWUgXTtcblx0XHR9XG5cdH0sXG5cblx0Y3NzOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgZXh0cmEsIHN0eWxlcyApIHtcblx0XHR2YXIgdmFsLCBudW0sIGhvb2tzLFxuXHRcdFx0b3JpZ05hbWUgPSBqUXVlcnkuY2FtZWxDYXNlKCBuYW1lICk7XG5cblx0XHQvLyBNYWtlIHN1cmUgdGhhdCB3ZSdyZSB3b3JraW5nIHdpdGggdGhlIHJpZ2h0IG5hbWVcblx0XHRuYW1lID0galF1ZXJ5LmNzc1Byb3BzWyBvcmlnTmFtZSBdIHx8ICggalF1ZXJ5LmNzc1Byb3BzWyBvcmlnTmFtZSBdID0gdmVuZG9yUHJvcE5hbWUoIGVsZW0uc3R5bGUsIG9yaWdOYW1lICkgKTtcblxuXHRcdC8vIFRyeSBwcmVmaXhlZCBuYW1lIGZvbGxvd2VkIGJ5IHRoZSB1bnByZWZpeGVkIG5hbWVcblx0XHRob29rcyA9IGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdIHx8IGpRdWVyeS5jc3NIb29rc1sgb3JpZ05hbWUgXTtcblxuXHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQgZ2V0IHRoZSBjb21wdXRlZCB2YWx1ZSBmcm9tIHRoZXJlXG5cdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICkge1xuXHRcdFx0dmFsID0gaG9va3MuZ2V0KCBlbGVtLCB0cnVlLCBleHRyYSApO1xuXHRcdH1cblxuXHRcdC8vIE90aGVyd2lzZSwgaWYgYSB3YXkgdG8gZ2V0IHRoZSBjb21wdXRlZCB2YWx1ZSBleGlzdHMsIHVzZSB0aGF0XG5cdFx0aWYgKCB2YWwgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHZhbCA9IGN1ckNTUyggZWxlbSwgbmFtZSwgc3R5bGVzICk7XG5cdFx0fVxuXG5cdFx0Ly8gQ29udmVydCBcIm5vcm1hbFwiIHRvIGNvbXB1dGVkIHZhbHVlXG5cdFx0aWYgKCB2YWwgPT09IFwibm9ybWFsXCIgJiYgbmFtZSBpbiBjc3NOb3JtYWxUcmFuc2Zvcm0gKSB7XG5cdFx0XHR2YWwgPSBjc3NOb3JtYWxUcmFuc2Zvcm1bIG5hbWUgXTtcblx0XHR9XG5cblx0XHQvLyBNYWtlIG51bWVyaWMgaWYgZm9yY2VkIG9yIGEgcXVhbGlmaWVyIHdhcyBwcm92aWRlZCBhbmQgdmFsIGxvb2tzIG51bWVyaWNcblx0XHRpZiAoIGV4dHJhID09PSBcIlwiIHx8IGV4dHJhICkge1xuXHRcdFx0bnVtID0gcGFyc2VGbG9hdCggdmFsICk7XG5cdFx0XHRyZXR1cm4gZXh0cmEgPT09IHRydWUgfHwgalF1ZXJ5LmlzTnVtZXJpYyggbnVtICkgPyBudW0gfHwgMCA6IHZhbDtcblx0XHR9XG5cdFx0cmV0dXJuIHZhbDtcblx0fVxufSk7XG5cbmpRdWVyeS5lYWNoKFsgXCJoZWlnaHRcIiwgXCJ3aWR0aFwiIF0sIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHRqUXVlcnkuY3NzSG9va3NbIG5hbWUgXSA9IHtcblx0XHRnZXQ6IGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCwgZXh0cmEgKSB7XG5cdFx0XHRpZiAoIGNvbXB1dGVkICkge1xuXG5cdFx0XHRcdC8vIENlcnRhaW4gZWxlbWVudHMgY2FuIGhhdmUgZGltZW5zaW9uIGluZm8gaWYgd2UgaW52aXNpYmx5IHNob3cgdGhlbVxuXHRcdFx0XHQvLyBidXQgaXQgbXVzdCBoYXZlIGEgY3VycmVudCBkaXNwbGF5IHN0eWxlIHRoYXQgd291bGQgYmVuZWZpdFxuXHRcdFx0XHRyZXR1cm4gcmRpc3BsYXlzd2FwLnRlc3QoIGpRdWVyeS5jc3MoIGVsZW0sIFwiZGlzcGxheVwiICkgKSAmJiBlbGVtLm9mZnNldFdpZHRoID09PSAwID9cblx0XHRcdFx0XHRqUXVlcnkuc3dhcCggZWxlbSwgY3NzU2hvdywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZ2V0V2lkdGhPckhlaWdodCggZWxlbSwgbmFtZSwgZXh0cmEgKTtcblx0XHRcdFx0XHR9KSA6XG5cdFx0XHRcdFx0Z2V0V2lkdGhPckhlaWdodCggZWxlbSwgbmFtZSwgZXh0cmEgKTtcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUsIGV4dHJhICkge1xuXHRcdFx0dmFyIHN0eWxlcyA9IGV4dHJhICYmIGdldFN0eWxlcyggZWxlbSApO1xuXHRcdFx0cmV0dXJuIHNldFBvc2l0aXZlTnVtYmVyKCBlbGVtLCB2YWx1ZSwgZXh0cmEgP1xuXHRcdFx0XHRhdWdtZW50V2lkdGhPckhlaWdodChcblx0XHRcdFx0XHRlbGVtLFxuXHRcdFx0XHRcdG5hbWUsXG5cdFx0XHRcdFx0ZXh0cmEsXG5cdFx0XHRcdFx0alF1ZXJ5LmNzcyggZWxlbSwgXCJib3hTaXppbmdcIiwgZmFsc2UsIHN0eWxlcyApID09PSBcImJvcmRlci1ib3hcIixcblx0XHRcdFx0XHRzdHlsZXNcblx0XHRcdFx0KSA6IDBcblx0XHRcdCk7XG5cdFx0fVxuXHR9O1xufSk7XG5cbi8vIFN1cHBvcnQ6IEFuZHJvaWQgMi4zXG5qUXVlcnkuY3NzSG9va3MubWFyZ2luUmlnaHQgPSBhZGRHZXRIb29rSWYoIHN1cHBvcnQucmVsaWFibGVNYXJnaW5SaWdodCxcblx0ZnVuY3Rpb24oIGVsZW0sIGNvbXB1dGVkICkge1xuXHRcdGlmICggY29tcHV0ZWQgKSB7XG5cdFx0XHRyZXR1cm4galF1ZXJ5LnN3YXAoIGVsZW0sIHsgXCJkaXNwbGF5XCI6IFwiaW5saW5lLWJsb2NrXCIgfSxcblx0XHRcdFx0Y3VyQ1NTLCBbIGVsZW0sIFwibWFyZ2luUmlnaHRcIiBdICk7XG5cdFx0fVxuXHR9XG4pO1xuXG4vLyBUaGVzZSBob29rcyBhcmUgdXNlZCBieSBhbmltYXRlIHRvIGV4cGFuZCBwcm9wZXJ0aWVzXG5qUXVlcnkuZWFjaCh7XG5cdG1hcmdpbjogXCJcIixcblx0cGFkZGluZzogXCJcIixcblx0Ym9yZGVyOiBcIldpZHRoXCJcbn0sIGZ1bmN0aW9uKCBwcmVmaXgsIHN1ZmZpeCApIHtcblx0alF1ZXJ5LmNzc0hvb2tzWyBwcmVmaXggKyBzdWZmaXggXSA9IHtcblx0XHRleHBhbmQ6IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdHZhciBpID0gMCxcblx0XHRcdFx0ZXhwYW5kZWQgPSB7fSxcblxuXHRcdFx0XHQvLyBBc3N1bWVzIGEgc2luZ2xlIG51bWJlciBpZiBub3QgYSBzdHJpbmdcblx0XHRcdFx0cGFydHMgPSB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgPyB2YWx1ZS5zcGxpdChcIiBcIikgOiBbIHZhbHVlIF07XG5cblx0XHRcdGZvciAoIDsgaSA8IDQ7IGkrKyApIHtcblx0XHRcdFx0ZXhwYW5kZWRbIHByZWZpeCArIGNzc0V4cGFuZFsgaSBdICsgc3VmZml4IF0gPVxuXHRcdFx0XHRcdHBhcnRzWyBpIF0gfHwgcGFydHNbIGkgLSAyIF0gfHwgcGFydHNbIDAgXTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGV4cGFuZGVkO1xuXHRcdH1cblx0fTtcblxuXHRpZiAoICFybWFyZ2luLnRlc3QoIHByZWZpeCApICkge1xuXHRcdGpRdWVyeS5jc3NIb29rc1sgcHJlZml4ICsgc3VmZml4IF0uc2V0ID0gc2V0UG9zaXRpdmVOdW1iZXI7XG5cdH1cbn0pO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKHtcblx0Y3NzOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIHZhbHVlICkge1xuXHRcdFx0dmFyIHN0eWxlcywgbGVuLFxuXHRcdFx0XHRtYXAgPSB7fSxcblx0XHRcdFx0aSA9IDA7XG5cblx0XHRcdGlmICggalF1ZXJ5LmlzQXJyYXkoIG5hbWUgKSApIHtcblx0XHRcdFx0c3R5bGVzID0gZ2V0U3R5bGVzKCBlbGVtICk7XG5cdFx0XHRcdGxlbiA9IG5hbWUubGVuZ3RoO1xuXG5cdFx0XHRcdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHRcdG1hcFsgbmFtZVsgaSBdIF0gPSBqUXVlcnkuY3NzKCBlbGVtLCBuYW1lWyBpIF0sIGZhbHNlLCBzdHlsZXMgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiBtYXA7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiB2YWx1ZSAhPT0gdW5kZWZpbmVkID9cblx0XHRcdFx0alF1ZXJ5LnN0eWxlKCBlbGVtLCBuYW1lLCB2YWx1ZSApIDpcblx0XHRcdFx0alF1ZXJ5LmNzcyggZWxlbSwgbmFtZSApO1xuXHRcdH0sIG5hbWUsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoID4gMSApO1xuXHR9LFxuXHRzaG93OiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gc2hvd0hpZGUoIHRoaXMsIHRydWUgKTtcblx0fSxcblx0aGlkZTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHNob3dIaWRlKCB0aGlzICk7XG5cdH0sXG5cdHRvZ2dsZTogZnVuY3Rpb24oIHN0YXRlICkge1xuXHRcdGlmICggdHlwZW9mIHN0YXRlID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRcdHJldHVybiBzdGF0ZSA/IHRoaXMuc2hvdygpIDogdGhpcy5oaWRlKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdGlmICggaXNIaWRkZW4oIHRoaXMgKSApIHtcblx0XHRcdFx0alF1ZXJ5KCB0aGlzICkuc2hvdygpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0alF1ZXJ5KCB0aGlzICkuaGlkZSgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59KTtcblxuXG5mdW5jdGlvbiBUd2VlbiggZWxlbSwgb3B0aW9ucywgcHJvcCwgZW5kLCBlYXNpbmcgKSB7XG5cdHJldHVybiBuZXcgVHdlZW4ucHJvdG90eXBlLmluaXQoIGVsZW0sIG9wdGlvbnMsIHByb3AsIGVuZCwgZWFzaW5nICk7XG59XG5qUXVlcnkuVHdlZW4gPSBUd2VlbjtcblxuVHdlZW4ucHJvdG90eXBlID0ge1xuXHRjb25zdHJ1Y3RvcjogVHdlZW4sXG5cdGluaXQ6IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBwcm9wLCBlbmQsIGVhc2luZywgdW5pdCApIHtcblx0XHR0aGlzLmVsZW0gPSBlbGVtO1xuXHRcdHRoaXMucHJvcCA9IHByb3A7XG5cdFx0dGhpcy5lYXNpbmcgPSBlYXNpbmcgfHwgXCJzd2luZ1wiO1xuXHRcdHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cdFx0dGhpcy5zdGFydCA9IHRoaXMubm93ID0gdGhpcy5jdXIoKTtcblx0XHR0aGlzLmVuZCA9IGVuZDtcblx0XHR0aGlzLnVuaXQgPSB1bml0IHx8ICggalF1ZXJ5LmNzc051bWJlclsgcHJvcCBdID8gXCJcIiA6IFwicHhcIiApO1xuXHR9LFxuXHRjdXI6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBob29rcyA9IFR3ZWVuLnByb3BIb29rc1sgdGhpcy5wcm9wIF07XG5cblx0XHRyZXR1cm4gaG9va3MgJiYgaG9va3MuZ2V0ID9cblx0XHRcdGhvb2tzLmdldCggdGhpcyApIDpcblx0XHRcdFR3ZWVuLnByb3BIb29rcy5fZGVmYXVsdC5nZXQoIHRoaXMgKTtcblx0fSxcblx0cnVuOiBmdW5jdGlvbiggcGVyY2VudCApIHtcblx0XHR2YXIgZWFzZWQsXG5cdFx0XHRob29rcyA9IFR3ZWVuLnByb3BIb29rc1sgdGhpcy5wcm9wIF07XG5cblx0XHRpZiAoIHRoaXMub3B0aW9ucy5kdXJhdGlvbiApIHtcblx0XHRcdHRoaXMucG9zID0gZWFzZWQgPSBqUXVlcnkuZWFzaW5nWyB0aGlzLmVhc2luZyBdKFxuXHRcdFx0XHRwZXJjZW50LCB0aGlzLm9wdGlvbnMuZHVyYXRpb24gKiBwZXJjZW50LCAwLCAxLCB0aGlzLm9wdGlvbnMuZHVyYXRpb25cblx0XHRcdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMucG9zID0gZWFzZWQgPSBwZXJjZW50O1xuXHRcdH1cblx0XHR0aGlzLm5vdyA9ICggdGhpcy5lbmQgLSB0aGlzLnN0YXJ0ICkgKiBlYXNlZCArIHRoaXMuc3RhcnQ7XG5cblx0XHRpZiAoIHRoaXMub3B0aW9ucy5zdGVwICkge1xuXHRcdFx0dGhpcy5vcHRpb25zLnN0ZXAuY2FsbCggdGhpcy5lbGVtLCB0aGlzLm5vdywgdGhpcyApO1xuXHRcdH1cblxuXHRcdGlmICggaG9va3MgJiYgaG9va3Muc2V0ICkge1xuXHRcdFx0aG9va3Muc2V0KCB0aGlzICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdFR3ZWVuLnByb3BIb29rcy5fZGVmYXVsdC5zZXQoIHRoaXMgKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cbn07XG5cblR3ZWVuLnByb3RvdHlwZS5pbml0LnByb3RvdHlwZSA9IFR3ZWVuLnByb3RvdHlwZTtcblxuVHdlZW4ucHJvcEhvb2tzID0ge1xuXHRfZGVmYXVsdDoge1xuXHRcdGdldDogZnVuY3Rpb24oIHR3ZWVuICkge1xuXHRcdFx0dmFyIHJlc3VsdDtcblxuXHRcdFx0aWYgKCB0d2Vlbi5lbGVtWyB0d2Vlbi5wcm9wIF0gIT0gbnVsbCAmJlxuXHRcdFx0XHQoIXR3ZWVuLmVsZW0uc3R5bGUgfHwgdHdlZW4uZWxlbS5zdHlsZVsgdHdlZW4ucHJvcCBdID09IG51bGwpICkge1xuXHRcdFx0XHRyZXR1cm4gdHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBQYXNzaW5nIGFuIGVtcHR5IHN0cmluZyBhcyBhIDNyZCBwYXJhbWV0ZXIgdG8gLmNzcyB3aWxsIGF1dG9tYXRpY2FsbHlcblx0XHRcdC8vIGF0dGVtcHQgYSBwYXJzZUZsb2F0IGFuZCBmYWxsYmFjayB0byBhIHN0cmluZyBpZiB0aGUgcGFyc2UgZmFpbHMuXG5cdFx0XHQvLyBTaW1wbGUgdmFsdWVzIHN1Y2ggYXMgXCIxMHB4XCIgYXJlIHBhcnNlZCB0byBGbG9hdDtcblx0XHRcdC8vIGNvbXBsZXggdmFsdWVzIHN1Y2ggYXMgXCJyb3RhdGUoMXJhZClcIiBhcmUgcmV0dXJuZWQgYXMtaXMuXG5cdFx0XHRyZXN1bHQgPSBqUXVlcnkuY3NzKCB0d2Vlbi5lbGVtLCB0d2Vlbi5wcm9wLCBcIlwiICk7XG5cdFx0XHQvLyBFbXB0eSBzdHJpbmdzLCBudWxsLCB1bmRlZmluZWQgYW5kIFwiYXV0b1wiIGFyZSBjb252ZXJ0ZWQgdG8gMC5cblx0XHRcdHJldHVybiAhcmVzdWx0IHx8IHJlc3VsdCA9PT0gXCJhdXRvXCIgPyAwIDogcmVzdWx0O1xuXHRcdH0sXG5cdFx0c2V0OiBmdW5jdGlvbiggdHdlZW4gKSB7XG5cdFx0XHQvLyBVc2Ugc3RlcCBob29rIGZvciBiYWNrIGNvbXBhdC5cblx0XHRcdC8vIFVzZSBjc3NIb29rIGlmIGl0cyB0aGVyZS5cblx0XHRcdC8vIFVzZSAuc3R5bGUgaWYgYXZhaWxhYmxlIGFuZCB1c2UgcGxhaW4gcHJvcGVydGllcyB3aGVyZSBhdmFpbGFibGUuXG5cdFx0XHRpZiAoIGpRdWVyeS5meC5zdGVwWyB0d2Vlbi5wcm9wIF0gKSB7XG5cdFx0XHRcdGpRdWVyeS5meC5zdGVwWyB0d2Vlbi5wcm9wIF0oIHR3ZWVuICk7XG5cdFx0XHR9IGVsc2UgaWYgKCB0d2Vlbi5lbGVtLnN0eWxlICYmICggdHdlZW4uZWxlbS5zdHlsZVsgalF1ZXJ5LmNzc1Byb3BzWyB0d2Vlbi5wcm9wIF0gXSAhPSBudWxsIHx8IGpRdWVyeS5jc3NIb29rc1sgdHdlZW4ucHJvcCBdICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5zdHlsZSggdHdlZW4uZWxlbSwgdHdlZW4ucHJvcCwgdHdlZW4ubm93ICsgdHdlZW4udW5pdCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdID0gdHdlZW4ubm93O1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufTtcblxuLy8gU3VwcG9ydDogSUU5XG4vLyBQYW5pYyBiYXNlZCBhcHByb2FjaCB0byBzZXR0aW5nIHRoaW5ncyBvbiBkaXNjb25uZWN0ZWQgbm9kZXNcblR3ZWVuLnByb3BIb29rcy5zY3JvbGxUb3AgPSBUd2Vlbi5wcm9wSG9va3Muc2Nyb2xsTGVmdCA9IHtcblx0c2V0OiBmdW5jdGlvbiggdHdlZW4gKSB7XG5cdFx0aWYgKCB0d2Vlbi5lbGVtLm5vZGVUeXBlICYmIHR3ZWVuLmVsZW0ucGFyZW50Tm9kZSApIHtcblx0XHRcdHR3ZWVuLmVsZW1bIHR3ZWVuLnByb3AgXSA9IHR3ZWVuLm5vdztcblx0XHR9XG5cdH1cbn07XG5cbmpRdWVyeS5lYXNpbmcgPSB7XG5cdGxpbmVhcjogZnVuY3Rpb24oIHAgKSB7XG5cdFx0cmV0dXJuIHA7XG5cdH0sXG5cdHN3aW5nOiBmdW5jdGlvbiggcCApIHtcblx0XHRyZXR1cm4gMC41IC0gTWF0aC5jb3MoIHAgKiBNYXRoLlBJICkgLyAyO1xuXHR9XG59O1xuXG5qUXVlcnkuZnggPSBUd2Vlbi5wcm90b3R5cGUuaW5pdDtcblxuLy8gQmFjayBDb21wYXQgPDEuOCBleHRlbnNpb24gcG9pbnRcbmpRdWVyeS5meC5zdGVwID0ge307XG5cblxuXG5cbnZhclxuXHRmeE5vdywgdGltZXJJZCxcblx0cmZ4dHlwZXMgPSAvXig/OnRvZ2dsZXxzaG93fGhpZGUpJC8sXG5cdHJmeG51bSA9IG5ldyBSZWdFeHAoIFwiXig/OihbKy1dKT18KShcIiArIHBudW0gKyBcIikoW2EteiVdKikkXCIsIFwiaVwiICksXG5cdHJydW4gPSAvcXVldWVIb29rcyQvLFxuXHRhbmltYXRpb25QcmVmaWx0ZXJzID0gWyBkZWZhdWx0UHJlZmlsdGVyIF0sXG5cdHR3ZWVuZXJzID0ge1xuXHRcdFwiKlwiOiBbIGZ1bmN0aW9uKCBwcm9wLCB2YWx1ZSApIHtcblx0XHRcdHZhciB0d2VlbiA9IHRoaXMuY3JlYXRlVHdlZW4oIHByb3AsIHZhbHVlICksXG5cdFx0XHRcdHRhcmdldCA9IHR3ZWVuLmN1cigpLFxuXHRcdFx0XHRwYXJ0cyA9IHJmeG51bS5leGVjKCB2YWx1ZSApLFxuXHRcdFx0XHR1bml0ID0gcGFydHMgJiYgcGFydHNbIDMgXSB8fCAoIGpRdWVyeS5jc3NOdW1iZXJbIHByb3AgXSA/IFwiXCIgOiBcInB4XCIgKSxcblxuXHRcdFx0XHQvLyBTdGFydGluZyB2YWx1ZSBjb21wdXRhdGlvbiBpcyByZXF1aXJlZCBmb3IgcG90ZW50aWFsIHVuaXQgbWlzbWF0Y2hlc1xuXHRcdFx0XHRzdGFydCA9ICggalF1ZXJ5LmNzc051bWJlclsgcHJvcCBdIHx8IHVuaXQgIT09IFwicHhcIiAmJiArdGFyZ2V0ICkgJiZcblx0XHRcdFx0XHRyZnhudW0uZXhlYyggalF1ZXJ5LmNzcyggdHdlZW4uZWxlbSwgcHJvcCApICksXG5cdFx0XHRcdHNjYWxlID0gMSxcblx0XHRcdFx0bWF4SXRlcmF0aW9ucyA9IDIwO1xuXG5cdFx0XHRpZiAoIHN0YXJ0ICYmIHN0YXJ0WyAzIF0gIT09IHVuaXQgKSB7XG5cdFx0XHRcdC8vIFRydXN0IHVuaXRzIHJlcG9ydGVkIGJ5IGpRdWVyeS5jc3Ncblx0XHRcdFx0dW5pdCA9IHVuaXQgfHwgc3RhcnRbIDMgXTtcblxuXHRcdFx0XHQvLyBNYWtlIHN1cmUgd2UgdXBkYXRlIHRoZSB0d2VlbiBwcm9wZXJ0aWVzIGxhdGVyIG9uXG5cdFx0XHRcdHBhcnRzID0gcGFydHMgfHwgW107XG5cblx0XHRcdFx0Ly8gSXRlcmF0aXZlbHkgYXBwcm94aW1hdGUgZnJvbSBhIG5vbnplcm8gc3RhcnRpbmcgcG9pbnRcblx0XHRcdFx0c3RhcnQgPSArdGFyZ2V0IHx8IDE7XG5cblx0XHRcdFx0ZG8ge1xuXHRcdFx0XHRcdC8vIElmIHByZXZpb3VzIGl0ZXJhdGlvbiB6ZXJvZWQgb3V0LCBkb3VibGUgdW50aWwgd2UgZ2V0ICpzb21ldGhpbmcqLlxuXHRcdFx0XHRcdC8vIFVzZSBzdHJpbmcgZm9yIGRvdWJsaW5nIHNvIHdlIGRvbid0IGFjY2lkZW50YWxseSBzZWUgc2NhbGUgYXMgdW5jaGFuZ2VkIGJlbG93XG5cdFx0XHRcdFx0c2NhbGUgPSBzY2FsZSB8fCBcIi41XCI7XG5cblx0XHRcdFx0XHQvLyBBZGp1c3QgYW5kIGFwcGx5XG5cdFx0XHRcdFx0c3RhcnQgPSBzdGFydCAvIHNjYWxlO1xuXHRcdFx0XHRcdGpRdWVyeS5zdHlsZSggdHdlZW4uZWxlbSwgcHJvcCwgc3RhcnQgKyB1bml0ICk7XG5cblx0XHRcdFx0Ly8gVXBkYXRlIHNjYWxlLCB0b2xlcmF0aW5nIHplcm8gb3IgTmFOIGZyb20gdHdlZW4uY3VyKCksXG5cdFx0XHRcdC8vIGJyZWFrIHRoZSBsb29wIGlmIHNjYWxlIGlzIHVuY2hhbmdlZCBvciBwZXJmZWN0LCBvciBpZiB3ZSd2ZSBqdXN0IGhhZCBlbm91Z2hcblx0XHRcdFx0fSB3aGlsZSAoIHNjYWxlICE9PSAoc2NhbGUgPSB0d2Vlbi5jdXIoKSAvIHRhcmdldCkgJiYgc2NhbGUgIT09IDEgJiYgLS1tYXhJdGVyYXRpb25zICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFVwZGF0ZSB0d2VlbiBwcm9wZXJ0aWVzXG5cdFx0XHRpZiAoIHBhcnRzICkge1xuXHRcdFx0XHRzdGFydCA9IHR3ZWVuLnN0YXJ0ID0gK3N0YXJ0IHx8ICt0YXJnZXQgfHwgMDtcblx0XHRcdFx0dHdlZW4udW5pdCA9IHVuaXQ7XG5cdFx0XHRcdC8vIElmIGEgKz0vLT0gdG9rZW4gd2FzIHByb3ZpZGVkLCB3ZSdyZSBkb2luZyBhIHJlbGF0aXZlIGFuaW1hdGlvblxuXHRcdFx0XHR0d2Vlbi5lbmQgPSBwYXJ0c1sgMSBdID9cblx0XHRcdFx0XHRzdGFydCArICggcGFydHNbIDEgXSArIDEgKSAqIHBhcnRzWyAyIF0gOlxuXHRcdFx0XHRcdCtwYXJ0c1sgMiBdO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdHdlZW47XG5cdFx0fSBdXG5cdH07XG5cbi8vIEFuaW1hdGlvbnMgY3JlYXRlZCBzeW5jaHJvbm91c2x5IHdpbGwgcnVuIHN5bmNocm9ub3VzbHlcbmZ1bmN0aW9uIGNyZWF0ZUZ4Tm93KCkge1xuXHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHRcdGZ4Tm93ID0gdW5kZWZpbmVkO1xuXHR9KTtcblx0cmV0dXJuICggZnhOb3cgPSBqUXVlcnkubm93KCkgKTtcbn1cblxuLy8gR2VuZXJhdGUgcGFyYW1ldGVycyB0byBjcmVhdGUgYSBzdGFuZGFyZCBhbmltYXRpb25cbmZ1bmN0aW9uIGdlbkZ4KCB0eXBlLCBpbmNsdWRlV2lkdGggKSB7XG5cdHZhciB3aGljaCxcblx0XHRpID0gMCxcblx0XHRhdHRycyA9IHsgaGVpZ2h0OiB0eXBlIH07XG5cblx0Ly8gSWYgd2UgaW5jbHVkZSB3aWR0aCwgc3RlcCB2YWx1ZSBpcyAxIHRvIGRvIGFsbCBjc3NFeHBhbmQgdmFsdWVzLFxuXHQvLyBvdGhlcndpc2Ugc3RlcCB2YWx1ZSBpcyAyIHRvIHNraXAgb3ZlciBMZWZ0IGFuZCBSaWdodFxuXHRpbmNsdWRlV2lkdGggPSBpbmNsdWRlV2lkdGggPyAxIDogMDtcblx0Zm9yICggOyBpIDwgNCA7IGkgKz0gMiAtIGluY2x1ZGVXaWR0aCApIHtcblx0XHR3aGljaCA9IGNzc0V4cGFuZFsgaSBdO1xuXHRcdGF0dHJzWyBcIm1hcmdpblwiICsgd2hpY2ggXSA9IGF0dHJzWyBcInBhZGRpbmdcIiArIHdoaWNoIF0gPSB0eXBlO1xuXHR9XG5cblx0aWYgKCBpbmNsdWRlV2lkdGggKSB7XG5cdFx0YXR0cnMub3BhY2l0eSA9IGF0dHJzLndpZHRoID0gdHlwZTtcblx0fVxuXG5cdHJldHVybiBhdHRycztcbn1cblxuZnVuY3Rpb24gY3JlYXRlVHdlZW4oIHZhbHVlLCBwcm9wLCBhbmltYXRpb24gKSB7XG5cdHZhciB0d2Vlbixcblx0XHRjb2xsZWN0aW9uID0gKCB0d2VlbmVyc1sgcHJvcCBdIHx8IFtdICkuY29uY2F0KCB0d2VlbmVyc1sgXCIqXCIgXSApLFxuXHRcdGluZGV4ID0gMCxcblx0XHRsZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aDtcblx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRpZiAoICh0d2VlbiA9IGNvbGxlY3Rpb25bIGluZGV4IF0uY2FsbCggYW5pbWF0aW9uLCBwcm9wLCB2YWx1ZSApKSApIHtcblxuXHRcdFx0Ly8gV2UncmUgZG9uZSB3aXRoIHRoaXMgcHJvcGVydHlcblx0XHRcdHJldHVybiB0d2Vlbjtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gZGVmYXVsdFByZWZpbHRlciggZWxlbSwgcHJvcHMsIG9wdHMgKSB7XG5cdC8qIGpzaGludCB2YWxpZHRoaXM6IHRydWUgKi9cblx0dmFyIHByb3AsIHZhbHVlLCB0b2dnbGUsIHR3ZWVuLCBob29rcywgb2xkZmlyZSwgZGlzcGxheSwgY2hlY2tEaXNwbGF5LFxuXHRcdGFuaW0gPSB0aGlzLFxuXHRcdG9yaWcgPSB7fSxcblx0XHRzdHlsZSA9IGVsZW0uc3R5bGUsXG5cdFx0aGlkZGVuID0gZWxlbS5ub2RlVHlwZSAmJiBpc0hpZGRlbiggZWxlbSApLFxuXHRcdGRhdGFTaG93ID0gZGF0YV9wcml2LmdldCggZWxlbSwgXCJmeHNob3dcIiApO1xuXG5cdC8vIEhhbmRsZSBxdWV1ZTogZmFsc2UgcHJvbWlzZXNcblx0aWYgKCAhb3B0cy5xdWV1ZSApIHtcblx0XHRob29rcyA9IGpRdWVyeS5fcXVldWVIb29rcyggZWxlbSwgXCJmeFwiICk7XG5cdFx0aWYgKCBob29rcy51bnF1ZXVlZCA9PSBudWxsICkge1xuXHRcdFx0aG9va3MudW5xdWV1ZWQgPSAwO1xuXHRcdFx0b2xkZmlyZSA9IGhvb2tzLmVtcHR5LmZpcmU7XG5cdFx0XHRob29rcy5lbXB0eS5maXJlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggIWhvb2tzLnVucXVldWVkICkge1xuXHRcdFx0XHRcdG9sZGZpcmUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblx0XHR9XG5cdFx0aG9va3MudW5xdWV1ZWQrKztcblxuXHRcdGFuaW0uYWx3YXlzKGZ1bmN0aW9uKCkge1xuXHRcdFx0Ly8gRW5zdXJlIHRoZSBjb21wbGV0ZSBoYW5kbGVyIGlzIGNhbGxlZCBiZWZvcmUgdGhpcyBjb21wbGV0ZXNcblx0XHRcdGFuaW0uYWx3YXlzKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRob29rcy51bnF1ZXVlZC0tO1xuXHRcdFx0XHRpZiAoICFqUXVlcnkucXVldWUoIGVsZW0sIFwiZnhcIiApLmxlbmd0aCApIHtcblx0XHRcdFx0XHRob29rcy5lbXB0eS5maXJlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9XG5cblx0Ly8gSGVpZ2h0L3dpZHRoIG92ZXJmbG93IHBhc3Ncblx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICYmICggXCJoZWlnaHRcIiBpbiBwcm9wcyB8fCBcIndpZHRoXCIgaW4gcHJvcHMgKSApIHtcblx0XHQvLyBNYWtlIHN1cmUgdGhhdCBub3RoaW5nIHNuZWFrcyBvdXRcblx0XHQvLyBSZWNvcmQgYWxsIDMgb3ZlcmZsb3cgYXR0cmlidXRlcyBiZWNhdXNlIElFOS0xMCBkbyBub3Rcblx0XHQvLyBjaGFuZ2UgdGhlIG92ZXJmbG93IGF0dHJpYnV0ZSB3aGVuIG92ZXJmbG93WCBhbmRcblx0XHQvLyBvdmVyZmxvd1kgYXJlIHNldCB0byB0aGUgc2FtZSB2YWx1ZVxuXHRcdG9wdHMub3ZlcmZsb3cgPSBbIHN0eWxlLm92ZXJmbG93LCBzdHlsZS5vdmVyZmxvd1gsIHN0eWxlLm92ZXJmbG93WSBdO1xuXG5cdFx0Ly8gU2V0IGRpc3BsYXkgcHJvcGVydHkgdG8gaW5saW5lLWJsb2NrIGZvciBoZWlnaHQvd2lkdGhcblx0XHQvLyBhbmltYXRpb25zIG9uIGlubGluZSBlbGVtZW50cyB0aGF0IGFyZSBoYXZpbmcgd2lkdGgvaGVpZ2h0IGFuaW1hdGVkXG5cdFx0ZGlzcGxheSA9IGpRdWVyeS5jc3MoIGVsZW0sIFwiZGlzcGxheVwiICk7XG5cblx0XHQvLyBUZXN0IGRlZmF1bHQgZGlzcGxheSBpZiBkaXNwbGF5IGlzIGN1cnJlbnRseSBcIm5vbmVcIlxuXHRcdGNoZWNrRGlzcGxheSA9IGRpc3BsYXkgPT09IFwibm9uZVwiID9cblx0XHRcdGRhdGFfcHJpdi5nZXQoIGVsZW0sIFwib2xkZGlzcGxheVwiICkgfHwgZGVmYXVsdERpc3BsYXkoIGVsZW0ubm9kZU5hbWUgKSA6IGRpc3BsYXk7XG5cblx0XHRpZiAoIGNoZWNrRGlzcGxheSA9PT0gXCJpbmxpbmVcIiAmJiBqUXVlcnkuY3NzKCBlbGVtLCBcImZsb2F0XCIgKSA9PT0gXCJub25lXCIgKSB7XG5cdFx0XHRzdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcblx0XHR9XG5cdH1cblxuXHRpZiAoIG9wdHMub3ZlcmZsb3cgKSB7XG5cdFx0c3R5bGUub3ZlcmZsb3cgPSBcImhpZGRlblwiO1xuXHRcdGFuaW0uYWx3YXlzKGZ1bmN0aW9uKCkge1xuXHRcdFx0c3R5bGUub3ZlcmZsb3cgPSBvcHRzLm92ZXJmbG93WyAwIF07XG5cdFx0XHRzdHlsZS5vdmVyZmxvd1ggPSBvcHRzLm92ZXJmbG93WyAxIF07XG5cdFx0XHRzdHlsZS5vdmVyZmxvd1kgPSBvcHRzLm92ZXJmbG93WyAyIF07XG5cdFx0fSk7XG5cdH1cblxuXHQvLyBzaG93L2hpZGUgcGFzc1xuXHRmb3IgKCBwcm9wIGluIHByb3BzICkge1xuXHRcdHZhbHVlID0gcHJvcHNbIHByb3AgXTtcblx0XHRpZiAoIHJmeHR5cGVzLmV4ZWMoIHZhbHVlICkgKSB7XG5cdFx0XHRkZWxldGUgcHJvcHNbIHByb3AgXTtcblx0XHRcdHRvZ2dsZSA9IHRvZ2dsZSB8fCB2YWx1ZSA9PT0gXCJ0b2dnbGVcIjtcblx0XHRcdGlmICggdmFsdWUgPT09ICggaGlkZGVuID8gXCJoaWRlXCIgOiBcInNob3dcIiApICkge1xuXG5cdFx0XHRcdC8vIElmIHRoZXJlIGlzIGRhdGFTaG93IGxlZnQgb3ZlciBmcm9tIGEgc3RvcHBlZCBoaWRlIG9yIHNob3cgYW5kIHdlIGFyZSBnb2luZyB0byBwcm9jZWVkIHdpdGggc2hvdywgd2Ugc2hvdWxkIHByZXRlbmQgdG8gYmUgaGlkZGVuXG5cdFx0XHRcdGlmICggdmFsdWUgPT09IFwic2hvd1wiICYmIGRhdGFTaG93ICYmIGRhdGFTaG93WyBwcm9wIF0gIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRoaWRkZW4gPSB0cnVlO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRvcmlnWyBwcm9wIF0gPSBkYXRhU2hvdyAmJiBkYXRhU2hvd1sgcHJvcCBdIHx8IGpRdWVyeS5zdHlsZSggZWxlbSwgcHJvcCApO1xuXG5cdFx0Ly8gQW55IG5vbi1meCB2YWx1ZSBzdG9wcyB1cyBmcm9tIHJlc3RvcmluZyB0aGUgb3JpZ2luYWwgZGlzcGxheSB2YWx1ZVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRkaXNwbGF5ID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXG5cdGlmICggIWpRdWVyeS5pc0VtcHR5T2JqZWN0KCBvcmlnICkgKSB7XG5cdFx0aWYgKCBkYXRhU2hvdyApIHtcblx0XHRcdGlmICggXCJoaWRkZW5cIiBpbiBkYXRhU2hvdyApIHtcblx0XHRcdFx0aGlkZGVuID0gZGF0YVNob3cuaGlkZGVuO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRkYXRhU2hvdyA9IGRhdGFfcHJpdi5hY2Nlc3MoIGVsZW0sIFwiZnhzaG93XCIsIHt9ICk7XG5cdFx0fVxuXG5cdFx0Ly8gU3RvcmUgc3RhdGUgaWYgaXRzIHRvZ2dsZSAtIGVuYWJsZXMgLnN0b3AoKS50b2dnbGUoKSB0byBcInJldmVyc2VcIlxuXHRcdGlmICggdG9nZ2xlICkge1xuXHRcdFx0ZGF0YVNob3cuaGlkZGVuID0gIWhpZGRlbjtcblx0XHR9XG5cdFx0aWYgKCBoaWRkZW4gKSB7XG5cdFx0XHRqUXVlcnkoIGVsZW0gKS5zaG93KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGFuaW0uZG9uZShmdW5jdGlvbigpIHtcblx0XHRcdFx0alF1ZXJ5KCBlbGVtICkuaGlkZSgpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHRcdGFuaW0uZG9uZShmdW5jdGlvbigpIHtcblx0XHRcdHZhciBwcm9wO1xuXG5cdFx0XHRkYXRhX3ByaXYucmVtb3ZlKCBlbGVtLCBcImZ4c2hvd1wiICk7XG5cdFx0XHRmb3IgKCBwcm9wIGluIG9yaWcgKSB7XG5cdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgcHJvcCwgb3JpZ1sgcHJvcCBdICk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0Zm9yICggcHJvcCBpbiBvcmlnICkge1xuXHRcdFx0dHdlZW4gPSBjcmVhdGVUd2VlbiggaGlkZGVuID8gZGF0YVNob3dbIHByb3AgXSA6IDAsIHByb3AsIGFuaW0gKTtcblxuXHRcdFx0aWYgKCAhKCBwcm9wIGluIGRhdGFTaG93ICkgKSB7XG5cdFx0XHRcdGRhdGFTaG93WyBwcm9wIF0gPSB0d2Vlbi5zdGFydDtcblx0XHRcdFx0aWYgKCBoaWRkZW4gKSB7XG5cdFx0XHRcdFx0dHdlZW4uZW5kID0gdHdlZW4uc3RhcnQ7XG5cdFx0XHRcdFx0dHdlZW4uc3RhcnQgPSBwcm9wID09PSBcIndpZHRoXCIgfHwgcHJvcCA9PT0gXCJoZWlnaHRcIiA/IDEgOiAwO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdC8vIElmIHRoaXMgaXMgYSBub29wIGxpa2UgLmhpZGUoKS5oaWRlKCksIHJlc3RvcmUgYW4gb3ZlcndyaXR0ZW4gZGlzcGxheSB2YWx1ZVxuXHR9IGVsc2UgaWYgKCAoZGlzcGxheSA9PT0gXCJub25lXCIgPyBkZWZhdWx0RGlzcGxheSggZWxlbS5ub2RlTmFtZSApIDogZGlzcGxheSkgPT09IFwiaW5saW5lXCIgKSB7XG5cdFx0c3R5bGUuZGlzcGxheSA9IGRpc3BsYXk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcHJvcEZpbHRlciggcHJvcHMsIHNwZWNpYWxFYXNpbmcgKSB7XG5cdHZhciBpbmRleCwgbmFtZSwgZWFzaW5nLCB2YWx1ZSwgaG9va3M7XG5cblx0Ly8gY2FtZWxDYXNlLCBzcGVjaWFsRWFzaW5nIGFuZCBleHBhbmQgY3NzSG9vayBwYXNzXG5cdGZvciAoIGluZGV4IGluIHByb3BzICkge1xuXHRcdG5hbWUgPSBqUXVlcnkuY2FtZWxDYXNlKCBpbmRleCApO1xuXHRcdGVhc2luZyA9IHNwZWNpYWxFYXNpbmdbIG5hbWUgXTtcblx0XHR2YWx1ZSA9IHByb3BzWyBpbmRleCBdO1xuXHRcdGlmICggalF1ZXJ5LmlzQXJyYXkoIHZhbHVlICkgKSB7XG5cdFx0XHRlYXNpbmcgPSB2YWx1ZVsgMSBdO1xuXHRcdFx0dmFsdWUgPSBwcm9wc1sgaW5kZXggXSA9IHZhbHVlWyAwIF07XG5cdFx0fVxuXG5cdFx0aWYgKCBpbmRleCAhPT0gbmFtZSApIHtcblx0XHRcdHByb3BzWyBuYW1lIF0gPSB2YWx1ZTtcblx0XHRcdGRlbGV0ZSBwcm9wc1sgaW5kZXggXTtcblx0XHR9XG5cblx0XHRob29rcyA9IGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdO1xuXHRcdGlmICggaG9va3MgJiYgXCJleHBhbmRcIiBpbiBob29rcyApIHtcblx0XHRcdHZhbHVlID0gaG9va3MuZXhwYW5kKCB2YWx1ZSApO1xuXHRcdFx0ZGVsZXRlIHByb3BzWyBuYW1lIF07XG5cblx0XHRcdC8vIE5vdCBxdWl0ZSAkLmV4dGVuZCwgdGhpcyB3b24ndCBvdmVyd3JpdGUgZXhpc3Rpbmcga2V5cy5cblx0XHRcdC8vIFJldXNpbmcgJ2luZGV4JyBiZWNhdXNlIHdlIGhhdmUgdGhlIGNvcnJlY3QgXCJuYW1lXCJcblx0XHRcdGZvciAoIGluZGV4IGluIHZhbHVlICkge1xuXHRcdFx0XHRpZiAoICEoIGluZGV4IGluIHByb3BzICkgKSB7XG5cdFx0XHRcdFx0cHJvcHNbIGluZGV4IF0gPSB2YWx1ZVsgaW5kZXggXTtcblx0XHRcdFx0XHRzcGVjaWFsRWFzaW5nWyBpbmRleCBdID0gZWFzaW5nO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHNwZWNpYWxFYXNpbmdbIG5hbWUgXSA9IGVhc2luZztcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gQW5pbWF0aW9uKCBlbGVtLCBwcm9wZXJ0aWVzLCBvcHRpb25zICkge1xuXHR2YXIgcmVzdWx0LFxuXHRcdHN0b3BwZWQsXG5cdFx0aW5kZXggPSAwLFxuXHRcdGxlbmd0aCA9IGFuaW1hdGlvblByZWZpbHRlcnMubGVuZ3RoLFxuXHRcdGRlZmVycmVkID0galF1ZXJ5LkRlZmVycmVkKCkuYWx3YXlzKCBmdW5jdGlvbigpIHtcblx0XHRcdC8vIERvbid0IG1hdGNoIGVsZW0gaW4gdGhlIDphbmltYXRlZCBzZWxlY3RvclxuXHRcdFx0ZGVsZXRlIHRpY2suZWxlbTtcblx0XHR9KSxcblx0XHR0aWNrID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIHN0b3BwZWQgKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHRcdHZhciBjdXJyZW50VGltZSA9IGZ4Tm93IHx8IGNyZWF0ZUZ4Tm93KCksXG5cdFx0XHRcdHJlbWFpbmluZyA9IE1hdGgubWF4KCAwLCBhbmltYXRpb24uc3RhcnRUaW1lICsgYW5pbWF0aW9uLmR1cmF0aW9uIC0gY3VycmVudFRpbWUgKSxcblx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCAyLjNcblx0XHRcdFx0Ly8gQXJjaGFpYyBjcmFzaCBidWcgd29uJ3QgYWxsb3cgdXMgdG8gdXNlIGAxIC0gKCAwLjUgfHwgMCApYCAoIzEyNDk3KVxuXHRcdFx0XHR0ZW1wID0gcmVtYWluaW5nIC8gYW5pbWF0aW9uLmR1cmF0aW9uIHx8IDAsXG5cdFx0XHRcdHBlcmNlbnQgPSAxIC0gdGVtcCxcblx0XHRcdFx0aW5kZXggPSAwLFxuXHRcdFx0XHRsZW5ndGggPSBhbmltYXRpb24udHdlZW5zLmxlbmd0aDtcblxuXHRcdFx0Zm9yICggOyBpbmRleCA8IGxlbmd0aCA7IGluZGV4KysgKSB7XG5cdFx0XHRcdGFuaW1hdGlvbi50d2VlbnNbIGluZGV4IF0ucnVuKCBwZXJjZW50ICk7XG5cdFx0XHR9XG5cblx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCBwZXJjZW50LCByZW1haW5pbmcgXSk7XG5cblx0XHRcdGlmICggcGVyY2VudCA8IDEgJiYgbGVuZ3RoICkge1xuXHRcdFx0XHRyZXR1cm4gcmVtYWluaW5nO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZGVmZXJyZWQucmVzb2x2ZVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uIF0gKTtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0YW5pbWF0aW9uID0gZGVmZXJyZWQucHJvbWlzZSh7XG5cdFx0XHRlbGVtOiBlbGVtLFxuXHRcdFx0cHJvcHM6IGpRdWVyeS5leHRlbmQoIHt9LCBwcm9wZXJ0aWVzICksXG5cdFx0XHRvcHRzOiBqUXVlcnkuZXh0ZW5kKCB0cnVlLCB7IHNwZWNpYWxFYXNpbmc6IHt9IH0sIG9wdGlvbnMgKSxcblx0XHRcdG9yaWdpbmFsUHJvcGVydGllczogcHJvcGVydGllcyxcblx0XHRcdG9yaWdpbmFsT3B0aW9uczogb3B0aW9ucyxcblx0XHRcdHN0YXJ0VGltZTogZnhOb3cgfHwgY3JlYXRlRnhOb3coKSxcblx0XHRcdGR1cmF0aW9uOiBvcHRpb25zLmR1cmF0aW9uLFxuXHRcdFx0dHdlZW5zOiBbXSxcblx0XHRcdGNyZWF0ZVR3ZWVuOiBmdW5jdGlvbiggcHJvcCwgZW5kICkge1xuXHRcdFx0XHR2YXIgdHdlZW4gPSBqUXVlcnkuVHdlZW4oIGVsZW0sIGFuaW1hdGlvbi5vcHRzLCBwcm9wLCBlbmQsXG5cdFx0XHRcdFx0XHRhbmltYXRpb24ub3B0cy5zcGVjaWFsRWFzaW5nWyBwcm9wIF0gfHwgYW5pbWF0aW9uLm9wdHMuZWFzaW5nICk7XG5cdFx0XHRcdGFuaW1hdGlvbi50d2VlbnMucHVzaCggdHdlZW4gKTtcblx0XHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdFx0fSxcblx0XHRcdHN0b3A6IGZ1bmN0aW9uKCBnb3RvRW5kICkge1xuXHRcdFx0XHR2YXIgaW5kZXggPSAwLFxuXHRcdFx0XHRcdC8vIElmIHdlIGFyZSBnb2luZyB0byB0aGUgZW5kLCB3ZSB3YW50IHRvIHJ1biBhbGwgdGhlIHR3ZWVuc1xuXHRcdFx0XHRcdC8vIG90aGVyd2lzZSB3ZSBza2lwIHRoaXMgcGFydFxuXHRcdFx0XHRcdGxlbmd0aCA9IGdvdG9FbmQgPyBhbmltYXRpb24udHdlZW5zLmxlbmd0aCA6IDA7XG5cdFx0XHRcdGlmICggc3RvcHBlZCApIHtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fVxuXHRcdFx0XHRzdG9wcGVkID0gdHJ1ZTtcblx0XHRcdFx0Zm9yICggOyBpbmRleCA8IGxlbmd0aCA7IGluZGV4KysgKSB7XG5cdFx0XHRcdFx0YW5pbWF0aW9uLnR3ZWVuc1sgaW5kZXggXS5ydW4oIDEgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFJlc29sdmUgd2hlbiB3ZSBwbGF5ZWQgdGhlIGxhc3QgZnJhbWU7IG90aGVyd2lzZSwgcmVqZWN0XG5cdFx0XHRcdGlmICggZ290b0VuZCApIHtcblx0XHRcdFx0XHRkZWZlcnJlZC5yZXNvbHZlV2l0aCggZWxlbSwgWyBhbmltYXRpb24sIGdvdG9FbmQgXSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGRlZmVycmVkLnJlamVjdFdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCBnb3RvRW5kIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH1cblx0XHR9KSxcblx0XHRwcm9wcyA9IGFuaW1hdGlvbi5wcm9wcztcblxuXHRwcm9wRmlsdGVyKCBwcm9wcywgYW5pbWF0aW9uLm9wdHMuc3BlY2lhbEVhc2luZyApO1xuXG5cdGZvciAoIDsgaW5kZXggPCBsZW5ndGggOyBpbmRleCsrICkge1xuXHRcdHJlc3VsdCA9IGFuaW1hdGlvblByZWZpbHRlcnNbIGluZGV4IF0uY2FsbCggYW5pbWF0aW9uLCBlbGVtLCBwcm9wcywgYW5pbWF0aW9uLm9wdHMgKTtcblx0XHRpZiAoIHJlc3VsdCApIHtcblx0XHRcdHJldHVybiByZXN1bHQ7XG5cdFx0fVxuXHR9XG5cblx0alF1ZXJ5Lm1hcCggcHJvcHMsIGNyZWF0ZVR3ZWVuLCBhbmltYXRpb24gKTtcblxuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBhbmltYXRpb24ub3B0cy5zdGFydCApICkge1xuXHRcdGFuaW1hdGlvbi5vcHRzLnN0YXJ0LmNhbGwoIGVsZW0sIGFuaW1hdGlvbiApO1xuXHR9XG5cblx0alF1ZXJ5LmZ4LnRpbWVyKFxuXHRcdGpRdWVyeS5leHRlbmQoIHRpY2ssIHtcblx0XHRcdGVsZW06IGVsZW0sXG5cdFx0XHRhbmltOiBhbmltYXRpb24sXG5cdFx0XHRxdWV1ZTogYW5pbWF0aW9uLm9wdHMucXVldWVcblx0XHR9KVxuXHQpO1xuXG5cdC8vIGF0dGFjaCBjYWxsYmFja3MgZnJvbSBvcHRpb25zXG5cdHJldHVybiBhbmltYXRpb24ucHJvZ3Jlc3MoIGFuaW1hdGlvbi5vcHRzLnByb2dyZXNzIClcblx0XHQuZG9uZSggYW5pbWF0aW9uLm9wdHMuZG9uZSwgYW5pbWF0aW9uLm9wdHMuY29tcGxldGUgKVxuXHRcdC5mYWlsKCBhbmltYXRpb24ub3B0cy5mYWlsIClcblx0XHQuYWx3YXlzKCBhbmltYXRpb24ub3B0cy5hbHdheXMgKTtcbn1cblxualF1ZXJ5LkFuaW1hdGlvbiA9IGpRdWVyeS5leHRlbmQoIEFuaW1hdGlvbiwge1xuXG5cdHR3ZWVuZXI6IGZ1bmN0aW9uKCBwcm9wcywgY2FsbGJhY2sgKSB7XG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggcHJvcHMgKSApIHtcblx0XHRcdGNhbGxiYWNrID0gcHJvcHM7XG5cdFx0XHRwcm9wcyA9IFsgXCIqXCIgXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cHJvcHMgPSBwcm9wcy5zcGxpdChcIiBcIik7XG5cdFx0fVxuXG5cdFx0dmFyIHByb3AsXG5cdFx0XHRpbmRleCA9IDAsXG5cdFx0XHRsZW5ndGggPSBwcm9wcy5sZW5ndGg7XG5cblx0XHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoIDsgaW5kZXgrKyApIHtcblx0XHRcdHByb3AgPSBwcm9wc1sgaW5kZXggXTtcblx0XHRcdHR3ZWVuZXJzWyBwcm9wIF0gPSB0d2VlbmVyc1sgcHJvcCBdIHx8IFtdO1xuXHRcdFx0dHdlZW5lcnNbIHByb3AgXS51bnNoaWZ0KCBjYWxsYmFjayApO1xuXHRcdH1cblx0fSxcblxuXHRwcmVmaWx0ZXI6IGZ1bmN0aW9uKCBjYWxsYmFjaywgcHJlcGVuZCApIHtcblx0XHRpZiAoIHByZXBlbmQgKSB7XG5cdFx0XHRhbmltYXRpb25QcmVmaWx0ZXJzLnVuc2hpZnQoIGNhbGxiYWNrICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGFuaW1hdGlvblByZWZpbHRlcnMucHVzaCggY2FsbGJhY2sgKTtcblx0XHR9XG5cdH1cbn0pO1xuXG5qUXVlcnkuc3BlZWQgPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgZm4gKSB7XG5cdHZhciBvcHQgPSBzcGVlZCAmJiB0eXBlb2Ygc3BlZWQgPT09IFwib2JqZWN0XCIgPyBqUXVlcnkuZXh0ZW5kKCB7fSwgc3BlZWQgKSA6IHtcblx0XHRjb21wbGV0ZTogZm4gfHwgIWZuICYmIGVhc2luZyB8fFxuXHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIHNwZWVkICkgJiYgc3BlZWQsXG5cdFx0ZHVyYXRpb246IHNwZWVkLFxuXHRcdGVhc2luZzogZm4gJiYgZWFzaW5nIHx8IGVhc2luZyAmJiAhalF1ZXJ5LmlzRnVuY3Rpb24oIGVhc2luZyApICYmIGVhc2luZ1xuXHR9O1xuXG5cdG9wdC5kdXJhdGlvbiA9IGpRdWVyeS5meC5vZmYgPyAwIDogdHlwZW9mIG9wdC5kdXJhdGlvbiA9PT0gXCJudW1iZXJcIiA/IG9wdC5kdXJhdGlvbiA6XG5cdFx0b3B0LmR1cmF0aW9uIGluIGpRdWVyeS5meC5zcGVlZHMgPyBqUXVlcnkuZnguc3BlZWRzWyBvcHQuZHVyYXRpb24gXSA6IGpRdWVyeS5meC5zcGVlZHMuX2RlZmF1bHQ7XG5cblx0Ly8gTm9ybWFsaXplIG9wdC5xdWV1ZSAtIHRydWUvdW5kZWZpbmVkL251bGwgLT4gXCJmeFwiXG5cdGlmICggb3B0LnF1ZXVlID09IG51bGwgfHwgb3B0LnF1ZXVlID09PSB0cnVlICkge1xuXHRcdG9wdC5xdWV1ZSA9IFwiZnhcIjtcblx0fVxuXG5cdC8vIFF1ZXVlaW5nXG5cdG9wdC5vbGQgPSBvcHQuY29tcGxldGU7XG5cblx0b3B0LmNvbXBsZXRlID0gZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggb3B0Lm9sZCApICkge1xuXHRcdFx0b3B0Lm9sZC5jYWxsKCB0aGlzICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBvcHQucXVldWUgKSB7XG5cdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgb3B0LnF1ZXVlICk7XG5cdFx0fVxuXHR9O1xuXG5cdHJldHVybiBvcHQ7XG59O1xuXG5qUXVlcnkuZm4uZXh0ZW5kKHtcblx0ZmFkZVRvOiBmdW5jdGlvbiggc3BlZWQsIHRvLCBlYXNpbmcsIGNhbGxiYWNrICkge1xuXG5cdFx0Ly8gU2hvdyBhbnkgaGlkZGVuIGVsZW1lbnRzIGFmdGVyIHNldHRpbmcgb3BhY2l0eSB0byAwXG5cdFx0cmV0dXJuIHRoaXMuZmlsdGVyKCBpc0hpZGRlbiApLmNzcyggXCJvcGFjaXR5XCIsIDAgKS5zaG93KClcblxuXHRcdFx0Ly8gQW5pbWF0ZSB0byB0aGUgdmFsdWUgc3BlY2lmaWVkXG5cdFx0XHQuZW5kKCkuYW5pbWF0ZSh7IG9wYWNpdHk6IHRvIH0sIHNwZWVkLCBlYXNpbmcsIGNhbGxiYWNrICk7XG5cdH0sXG5cdGFuaW1hdGU6IGZ1bmN0aW9uKCBwcm9wLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApIHtcblx0XHR2YXIgZW1wdHkgPSBqUXVlcnkuaXNFbXB0eU9iamVjdCggcHJvcCApLFxuXHRcdFx0b3B0YWxsID0galF1ZXJ5LnNwZWVkKCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApLFxuXHRcdFx0ZG9BbmltYXRpb24gPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0Ly8gT3BlcmF0ZSBvbiBhIGNvcHkgb2YgcHJvcCBzbyBwZXItcHJvcGVydHkgZWFzaW5nIHdvbid0IGJlIGxvc3Rcblx0XHRcdFx0dmFyIGFuaW0gPSBBbmltYXRpb24oIHRoaXMsIGpRdWVyeS5leHRlbmQoIHt9LCBwcm9wICksIG9wdGFsbCApO1xuXG5cdFx0XHRcdC8vIEVtcHR5IGFuaW1hdGlvbnMsIG9yIGZpbmlzaGluZyByZXNvbHZlcyBpbW1lZGlhdGVseVxuXHRcdFx0XHRpZiAoIGVtcHR5IHx8IGRhdGFfcHJpdi5nZXQoIHRoaXMsIFwiZmluaXNoXCIgKSApIHtcblx0XHRcdFx0XHRhbmltLnN0b3AoIHRydWUgKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblx0XHRcdGRvQW5pbWF0aW9uLmZpbmlzaCA9IGRvQW5pbWF0aW9uO1xuXG5cdFx0cmV0dXJuIGVtcHR5IHx8IG9wdGFsbC5xdWV1ZSA9PT0gZmFsc2UgP1xuXHRcdFx0dGhpcy5lYWNoKCBkb0FuaW1hdGlvbiApIDpcblx0XHRcdHRoaXMucXVldWUoIG9wdGFsbC5xdWV1ZSwgZG9BbmltYXRpb24gKTtcblx0fSxcblx0c3RvcDogZnVuY3Rpb24oIHR5cGUsIGNsZWFyUXVldWUsIGdvdG9FbmQgKSB7XG5cdFx0dmFyIHN0b3BRdWV1ZSA9IGZ1bmN0aW9uKCBob29rcyApIHtcblx0XHRcdHZhciBzdG9wID0gaG9va3Muc3RvcDtcblx0XHRcdGRlbGV0ZSBob29rcy5zdG9wO1xuXHRcdFx0c3RvcCggZ290b0VuZCApO1xuXHRcdH07XG5cblx0XHRpZiAoIHR5cGVvZiB0eXBlICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0Z290b0VuZCA9IGNsZWFyUXVldWU7XG5cdFx0XHRjbGVhclF1ZXVlID0gdHlwZTtcblx0XHRcdHR5cGUgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdGlmICggY2xlYXJRdWV1ZSAmJiB0eXBlICE9PSBmYWxzZSApIHtcblx0XHRcdHRoaXMucXVldWUoIHR5cGUgfHwgXCJmeFwiLCBbXSApO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgZGVxdWV1ZSA9IHRydWUsXG5cdFx0XHRcdGluZGV4ID0gdHlwZSAhPSBudWxsICYmIHR5cGUgKyBcInF1ZXVlSG9va3NcIixcblx0XHRcdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycyxcblx0XHRcdFx0ZGF0YSA9IGRhdGFfcHJpdi5nZXQoIHRoaXMgKTtcblxuXHRcdFx0aWYgKCBpbmRleCApIHtcblx0XHRcdFx0aWYgKCBkYXRhWyBpbmRleCBdICYmIGRhdGFbIGluZGV4IF0uc3RvcCApIHtcblx0XHRcdFx0XHRzdG9wUXVldWUoIGRhdGFbIGluZGV4IF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Zm9yICggaW5kZXggaW4gZGF0YSApIHtcblx0XHRcdFx0XHRpZiAoIGRhdGFbIGluZGV4IF0gJiYgZGF0YVsgaW5kZXggXS5zdG9wICYmIHJydW4udGVzdCggaW5kZXggKSApIHtcblx0XHRcdFx0XHRcdHN0b3BRdWV1ZSggZGF0YVsgaW5kZXggXSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRmb3IgKCBpbmRleCA9IHRpbWVycy5sZW5ndGg7IGluZGV4LS07ICkge1xuXHRcdFx0XHRpZiAoIHRpbWVyc1sgaW5kZXggXS5lbGVtID09PSB0aGlzICYmICh0eXBlID09IG51bGwgfHwgdGltZXJzWyBpbmRleCBdLnF1ZXVlID09PSB0eXBlKSApIHtcblx0XHRcdFx0XHR0aW1lcnNbIGluZGV4IF0uYW5pbS5zdG9wKCBnb3RvRW5kICk7XG5cdFx0XHRcdFx0ZGVxdWV1ZSA9IGZhbHNlO1xuXHRcdFx0XHRcdHRpbWVycy5zcGxpY2UoIGluZGV4LCAxICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gU3RhcnQgdGhlIG5leHQgaW4gdGhlIHF1ZXVlIGlmIHRoZSBsYXN0IHN0ZXAgd2Fzbid0IGZvcmNlZC5cblx0XHRcdC8vIFRpbWVycyBjdXJyZW50bHkgd2lsbCBjYWxsIHRoZWlyIGNvbXBsZXRlIGNhbGxiYWNrcywgd2hpY2hcblx0XHRcdC8vIHdpbGwgZGVxdWV1ZSBidXQgb25seSBpZiB0aGV5IHdlcmUgZ290b0VuZC5cblx0XHRcdGlmICggZGVxdWV1ZSB8fCAhZ290b0VuZCApIHtcblx0XHRcdFx0alF1ZXJ5LmRlcXVldWUoIHRoaXMsIHR5cGUgKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSxcblx0ZmluaXNoOiBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRpZiAoIHR5cGUgIT09IGZhbHNlICkge1xuXHRcdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIGluZGV4LFxuXHRcdFx0XHRkYXRhID0gZGF0YV9wcml2LmdldCggdGhpcyApLFxuXHRcdFx0XHRxdWV1ZSA9IGRhdGFbIHR5cGUgKyBcInF1ZXVlXCIgXSxcblx0XHRcdFx0aG9va3MgPSBkYXRhWyB0eXBlICsgXCJxdWV1ZUhvb2tzXCIgXSxcblx0XHRcdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycyxcblx0XHRcdFx0bGVuZ3RoID0gcXVldWUgPyBxdWV1ZS5sZW5ndGggOiAwO1xuXG5cdFx0XHQvLyBFbmFibGUgZmluaXNoaW5nIGZsYWcgb24gcHJpdmF0ZSBkYXRhXG5cdFx0XHRkYXRhLmZpbmlzaCA9IHRydWU7XG5cblx0XHRcdC8vIEVtcHR5IHRoZSBxdWV1ZSBmaXJzdFxuXHRcdFx0alF1ZXJ5LnF1ZXVlKCB0aGlzLCB0eXBlLCBbXSApO1xuXG5cdFx0XHRpZiAoIGhvb2tzICYmIGhvb2tzLnN0b3AgKSB7XG5cdFx0XHRcdGhvb2tzLnN0b3AuY2FsbCggdGhpcywgdHJ1ZSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBMb29rIGZvciBhbnkgYWN0aXZlIGFuaW1hdGlvbnMsIGFuZCBmaW5pc2ggdGhlbVxuXHRcdFx0Zm9yICggaW5kZXggPSB0aW1lcnMubGVuZ3RoOyBpbmRleC0tOyApIHtcblx0XHRcdFx0aWYgKCB0aW1lcnNbIGluZGV4IF0uZWxlbSA9PT0gdGhpcyAmJiB0aW1lcnNbIGluZGV4IF0ucXVldWUgPT09IHR5cGUgKSB7XG5cdFx0XHRcdFx0dGltZXJzWyBpbmRleCBdLmFuaW0uc3RvcCggdHJ1ZSApO1xuXHRcdFx0XHRcdHRpbWVycy5zcGxpY2UoIGluZGV4LCAxICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gTG9vayBmb3IgYW55IGFuaW1hdGlvbnMgaW4gdGhlIG9sZCBxdWV1ZSBhbmQgZmluaXNoIHRoZW1cblx0XHRcdGZvciAoIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0XHRcdGlmICggcXVldWVbIGluZGV4IF0gJiYgcXVldWVbIGluZGV4IF0uZmluaXNoICkge1xuXHRcdFx0XHRcdHF1ZXVlWyBpbmRleCBdLmZpbmlzaC5jYWxsKCB0aGlzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gVHVybiBvZmYgZmluaXNoaW5nIGZsYWdcblx0XHRcdGRlbGV0ZSBkYXRhLmZpbmlzaDtcblx0XHR9KTtcblx0fVxufSk7XG5cbmpRdWVyeS5lYWNoKFsgXCJ0b2dnbGVcIiwgXCJzaG93XCIsIFwiaGlkZVwiIF0sIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHR2YXIgY3NzRm4gPSBqUXVlcnkuZm5bIG5hbWUgXTtcblx0alF1ZXJ5LmZuWyBuYW1lIF0gPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIHNwZWVkID09IG51bGwgfHwgdHlwZW9mIHNwZWVkID09PSBcImJvb2xlYW5cIiA/XG5cdFx0XHRjc3NGbi5hcHBseSggdGhpcywgYXJndW1lbnRzICkgOlxuXHRcdFx0dGhpcy5hbmltYXRlKCBnZW5GeCggbmFtZSwgdHJ1ZSApLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9O1xufSk7XG5cbi8vIEdlbmVyYXRlIHNob3J0Y3V0cyBmb3IgY3VzdG9tIGFuaW1hdGlvbnNcbmpRdWVyeS5lYWNoKHtcblx0c2xpZGVEb3duOiBnZW5GeChcInNob3dcIiksXG5cdHNsaWRlVXA6IGdlbkZ4KFwiaGlkZVwiKSxcblx0c2xpZGVUb2dnbGU6IGdlbkZ4KFwidG9nZ2xlXCIpLFxuXHRmYWRlSW46IHsgb3BhY2l0eTogXCJzaG93XCIgfSxcblx0ZmFkZU91dDogeyBvcGFjaXR5OiBcImhpZGVcIiB9LFxuXHRmYWRlVG9nZ2xlOiB7IG9wYWNpdHk6IFwidG9nZ2xlXCIgfVxufSwgZnVuY3Rpb24oIG5hbWUsIHByb3BzICkge1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4gdGhpcy5hbmltYXRlKCBwcm9wcywgc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKTtcblx0fTtcbn0pO1xuXG5qUXVlcnkudGltZXJzID0gW107XG5qUXVlcnkuZngudGljayA9IGZ1bmN0aW9uKCkge1xuXHR2YXIgdGltZXIsXG5cdFx0aSA9IDAsXG5cdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycztcblxuXHRmeE5vdyA9IGpRdWVyeS5ub3coKTtcblxuXHRmb3IgKCA7IGkgPCB0aW1lcnMubGVuZ3RoOyBpKysgKSB7XG5cdFx0dGltZXIgPSB0aW1lcnNbIGkgXTtcblx0XHQvLyBDaGVja3MgdGhlIHRpbWVyIGhhcyBub3QgYWxyZWFkeSBiZWVuIHJlbW92ZWRcblx0XHRpZiAoICF0aW1lcigpICYmIHRpbWVyc1sgaSBdID09PSB0aW1lciApIHtcblx0XHRcdHRpbWVycy5zcGxpY2UoIGktLSwgMSApO1xuXHRcdH1cblx0fVxuXG5cdGlmICggIXRpbWVycy5sZW5ndGggKSB7XG5cdFx0alF1ZXJ5LmZ4LnN0b3AoKTtcblx0fVxuXHRmeE5vdyA9IHVuZGVmaW5lZDtcbn07XG5cbmpRdWVyeS5meC50aW1lciA9IGZ1bmN0aW9uKCB0aW1lciApIHtcblx0alF1ZXJ5LnRpbWVycy5wdXNoKCB0aW1lciApO1xuXHRpZiAoIHRpbWVyKCkgKSB7XG5cdFx0alF1ZXJ5LmZ4LnN0YXJ0KCk7XG5cdH0gZWxzZSB7XG5cdFx0alF1ZXJ5LnRpbWVycy5wb3AoKTtcblx0fVxufTtcblxualF1ZXJ5LmZ4LmludGVydmFsID0gMTM7XG5cbmpRdWVyeS5meC5zdGFydCA9IGZ1bmN0aW9uKCkge1xuXHRpZiAoICF0aW1lcklkICkge1xuXHRcdHRpbWVySWQgPSBzZXRJbnRlcnZhbCggalF1ZXJ5LmZ4LnRpY2ssIGpRdWVyeS5meC5pbnRlcnZhbCApO1xuXHR9XG59O1xuXG5qUXVlcnkuZnguc3RvcCA9IGZ1bmN0aW9uKCkge1xuXHRjbGVhckludGVydmFsKCB0aW1lcklkICk7XG5cdHRpbWVySWQgPSBudWxsO1xufTtcblxualF1ZXJ5LmZ4LnNwZWVkcyA9IHtcblx0c2xvdzogNjAwLFxuXHRmYXN0OiAyMDAsXG5cdC8vIERlZmF1bHQgc3BlZWRcblx0X2RlZmF1bHQ6IDQwMFxufTtcblxuXG4vLyBCYXNlZCBvZmYgb2YgdGhlIHBsdWdpbiBieSBDbGludCBIZWxmZXJzLCB3aXRoIHBlcm1pc3Npb24uXG4vLyBodHRwOi8vYmxpbmRzaWduYWxzLmNvbS9pbmRleC5waHAvMjAwOS8wNy9qcXVlcnktZGVsYXkvXG5qUXVlcnkuZm4uZGVsYXkgPSBmdW5jdGlvbiggdGltZSwgdHlwZSApIHtcblx0dGltZSA9IGpRdWVyeS5meCA/IGpRdWVyeS5meC5zcGVlZHNbIHRpbWUgXSB8fCB0aW1lIDogdGltZTtcblx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdHJldHVybiB0aGlzLnF1ZXVlKCB0eXBlLCBmdW5jdGlvbiggbmV4dCwgaG9va3MgKSB7XG5cdFx0dmFyIHRpbWVvdXQgPSBzZXRUaW1lb3V0KCBuZXh0LCB0aW1lICk7XG5cdFx0aG9va3Muc3RvcCA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0Y2xlYXJUaW1lb3V0KCB0aW1lb3V0ICk7XG5cdFx0fTtcblx0fSk7XG59O1xuXG5cbihmdW5jdGlvbigpIHtcblx0dmFyIGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJpbnB1dFwiICksXG5cdFx0c2VsZWN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJzZWxlY3RcIiApLFxuXHRcdG9wdCA9IHNlbGVjdC5hcHBlbmRDaGlsZCggZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJvcHRpb25cIiApICk7XG5cblx0aW5wdXQudHlwZSA9IFwiY2hlY2tib3hcIjtcblxuXHQvLyBTdXBwb3J0OiBpT1M8PTUuMSwgQW5kcm9pZDw9NC4yK1xuXHQvLyBEZWZhdWx0IHZhbHVlIGZvciBhIGNoZWNrYm94IHNob3VsZCBiZSBcIm9uXCJcblx0c3VwcG9ydC5jaGVja09uID0gaW5wdXQudmFsdWUgIT09IFwiXCI7XG5cblx0Ly8gU3VwcG9ydDogSUU8PTExK1xuXHQvLyBNdXN0IGFjY2VzcyBzZWxlY3RlZEluZGV4IHRvIG1ha2UgZGVmYXVsdCBvcHRpb25zIHNlbGVjdFxuXHRzdXBwb3J0Lm9wdFNlbGVjdGVkID0gb3B0LnNlbGVjdGVkO1xuXG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQ8PTIuM1xuXHQvLyBPcHRpb25zIGluc2lkZSBkaXNhYmxlZCBzZWxlY3RzIGFyZSBpbmNvcnJlY3RseSBtYXJrZWQgYXMgZGlzYWJsZWRcblx0c2VsZWN0LmRpc2FibGVkID0gdHJ1ZTtcblx0c3VwcG9ydC5vcHREaXNhYmxlZCA9ICFvcHQuZGlzYWJsZWQ7XG5cblx0Ly8gU3VwcG9ydDogSUU8PTExK1xuXHQvLyBBbiBpbnB1dCBsb3NlcyBpdHMgdmFsdWUgYWZ0ZXIgYmVjb21pbmcgYSByYWRpb1xuXHRpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiaW5wdXRcIiApO1xuXHRpbnB1dC52YWx1ZSA9IFwidFwiO1xuXHRpbnB1dC50eXBlID0gXCJyYWRpb1wiO1xuXHRzdXBwb3J0LnJhZGlvVmFsdWUgPSBpbnB1dC52YWx1ZSA9PT0gXCJ0XCI7XG59KSgpO1xuXG5cbnZhciBub2RlSG9vaywgYm9vbEhvb2ssXG5cdGF0dHJIYW5kbGUgPSBqUXVlcnkuZXhwci5hdHRySGFuZGxlO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKHtcblx0YXR0cjogZnVuY3Rpb24oIG5hbWUsIHZhbHVlICkge1xuXHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGpRdWVyeS5hdHRyLCBuYW1lLCB2YWx1ZSwgYXJndW1lbnRzLmxlbmd0aCA+IDEgKTtcblx0fSxcblxuXHRyZW1vdmVBdHRyOiBmdW5jdGlvbiggbmFtZSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5LnJlbW92ZUF0dHIoIHRoaXMsIG5hbWUgKTtcblx0XHR9KTtcblx0fVxufSk7XG5cbmpRdWVyeS5leHRlbmQoe1xuXHRhdHRyOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUgKSB7XG5cdFx0dmFyIGhvb2tzLCByZXQsXG5cdFx0XHRuVHlwZSA9IGVsZW0ubm9kZVR5cGU7XG5cblx0XHQvLyBkb24ndCBnZXQvc2V0IGF0dHJpYnV0ZXMgb24gdGV4dCwgY29tbWVudCBhbmQgYXR0cmlidXRlIG5vZGVzXG5cdFx0aWYgKCAhZWxlbSB8fCBuVHlwZSA9PT0gMyB8fCBuVHlwZSA9PT0gOCB8fCBuVHlwZSA9PT0gMiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBGYWxsYmFjayB0byBwcm9wIHdoZW4gYXR0cmlidXRlcyBhcmUgbm90IHN1cHBvcnRlZFxuXHRcdGlmICggdHlwZW9mIGVsZW0uZ2V0QXR0cmlidXRlID09PSBzdHJ1bmRlZmluZWQgKSB7XG5cdFx0XHRyZXR1cm4galF1ZXJ5LnByb3AoIGVsZW0sIG5hbWUsIHZhbHVlICk7XG5cdFx0fVxuXG5cdFx0Ly8gQWxsIGF0dHJpYnV0ZXMgYXJlIGxvd2VyY2FzZVxuXHRcdC8vIEdyYWIgbmVjZXNzYXJ5IGhvb2sgaWYgb25lIGlzIGRlZmluZWRcblx0XHRpZiAoIG5UeXBlICE9PSAxIHx8ICFqUXVlcnkuaXNYTUxEb2MoIGVsZW0gKSApIHtcblx0XHRcdG5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRob29rcyA9IGpRdWVyeS5hdHRySG9va3NbIG5hbWUgXSB8fFxuXHRcdFx0XHQoIGpRdWVyeS5leHByLm1hdGNoLmJvb2wudGVzdCggbmFtZSApID8gYm9vbEhvb2sgOiBub2RlSG9vayApO1xuXHRcdH1cblxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblxuXHRcdFx0aWYgKCB2YWx1ZSA9PT0gbnVsbCApIHtcblx0XHRcdFx0alF1ZXJ5LnJlbW92ZUF0dHIoIGVsZW0sIG5hbWUgKTtcblxuXHRcdFx0fSBlbHNlIGlmICggaG9va3MgJiYgXCJzZXRcIiBpbiBob29rcyAmJiAocmV0ID0gaG9va3Muc2V0KCBlbGVtLCB2YWx1ZSwgbmFtZSApKSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggbmFtZSwgdmFsdWUgKyBcIlwiICk7XG5cdFx0XHRcdHJldHVybiB2YWx1ZTtcblx0XHRcdH1cblxuXHRcdH0gZWxzZSBpZiAoIGhvb2tzICYmIFwiZ2V0XCIgaW4gaG9va3MgJiYgKHJldCA9IGhvb2tzLmdldCggZWxlbSwgbmFtZSApKSAhPT0gbnVsbCApIHtcblx0XHRcdHJldHVybiByZXQ7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0ID0galF1ZXJ5LmZpbmQuYXR0ciggZWxlbSwgbmFtZSApO1xuXG5cdFx0XHQvLyBOb24tZXhpc3RlbnQgYXR0cmlidXRlcyByZXR1cm4gbnVsbCwgd2Ugbm9ybWFsaXplIHRvIHVuZGVmaW5lZFxuXHRcdFx0cmV0dXJuIHJldCA9PSBudWxsID9cblx0XHRcdFx0dW5kZWZpbmVkIDpcblx0XHRcdFx0cmV0O1xuXHRcdH1cblx0fSxcblxuXHRyZW1vdmVBdHRyOiBmdW5jdGlvbiggZWxlbSwgdmFsdWUgKSB7XG5cdFx0dmFyIG5hbWUsIHByb3BOYW1lLFxuXHRcdFx0aSA9IDAsXG5cdFx0XHRhdHRyTmFtZXMgPSB2YWx1ZSAmJiB2YWx1ZS5tYXRjaCggcm5vdHdoaXRlICk7XG5cblx0XHRpZiAoIGF0dHJOYW1lcyAmJiBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0d2hpbGUgKCAobmFtZSA9IGF0dHJOYW1lc1tpKytdKSApIHtcblx0XHRcdFx0cHJvcE5hbWUgPSBqUXVlcnkucHJvcEZpeFsgbmFtZSBdIHx8IG5hbWU7XG5cblx0XHRcdFx0Ly8gQm9vbGVhbiBhdHRyaWJ1dGVzIGdldCBzcGVjaWFsIHRyZWF0bWVudCAoIzEwODcwKVxuXHRcdFx0XHRpZiAoIGpRdWVyeS5leHByLm1hdGNoLmJvb2wudGVzdCggbmFtZSApICkge1xuXHRcdFx0XHRcdC8vIFNldCBjb3JyZXNwb25kaW5nIHByb3BlcnR5IHRvIGZhbHNlXG5cdFx0XHRcdFx0ZWxlbVsgcHJvcE5hbWUgXSA9IGZhbHNlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0ZWxlbS5yZW1vdmVBdHRyaWJ1dGUoIG5hbWUgKTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0YXR0ckhvb2tzOiB7XG5cdFx0dHlwZToge1xuXHRcdFx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUgKSB7XG5cdFx0XHRcdGlmICggIXN1cHBvcnQucmFkaW9WYWx1ZSAmJiB2YWx1ZSA9PT0gXCJyYWRpb1wiICYmXG5cdFx0XHRcdFx0alF1ZXJ5Lm5vZGVOYW1lKCBlbGVtLCBcImlucHV0XCIgKSApIHtcblx0XHRcdFx0XHR2YXIgdmFsID0gZWxlbS52YWx1ZTtcblx0XHRcdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggXCJ0eXBlXCIsIHZhbHVlICk7XG5cdFx0XHRcdFx0aWYgKCB2YWwgKSB7XG5cdFx0XHRcdFx0XHRlbGVtLnZhbHVlID0gdmFsO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cbn0pO1xuXG4vLyBIb29rcyBmb3IgYm9vbGVhbiBhdHRyaWJ1dGVzXG5ib29sSG9vayA9IHtcblx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUsIG5hbWUgKSB7XG5cdFx0aWYgKCB2YWx1ZSA9PT0gZmFsc2UgKSB7XG5cdFx0XHQvLyBSZW1vdmUgYm9vbGVhbiBhdHRyaWJ1dGVzIHdoZW4gc2V0IHRvIGZhbHNlXG5cdFx0XHRqUXVlcnkucmVtb3ZlQXR0ciggZWxlbSwgbmFtZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggbmFtZSwgbmFtZSApO1xuXHRcdH1cblx0XHRyZXR1cm4gbmFtZTtcblx0fVxufTtcbmpRdWVyeS5lYWNoKCBqUXVlcnkuZXhwci5tYXRjaC5ib29sLnNvdXJjZS5tYXRjaCggL1xcdysvZyApLCBmdW5jdGlvbiggaSwgbmFtZSApIHtcblx0dmFyIGdldHRlciA9IGF0dHJIYW5kbGVbIG5hbWUgXSB8fCBqUXVlcnkuZmluZC5hdHRyO1xuXG5cdGF0dHJIYW5kbGVbIG5hbWUgXSA9IGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCBpc1hNTCApIHtcblx0XHR2YXIgcmV0LCBoYW5kbGU7XG5cdFx0aWYgKCAhaXNYTUwgKSB7XG5cdFx0XHQvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wIGJ5IHRlbXBvcmFyaWx5IHJlbW92aW5nIHRoaXMgZnVuY3Rpb24gZnJvbSB0aGUgZ2V0dGVyXG5cdFx0XHRoYW5kbGUgPSBhdHRySGFuZGxlWyBuYW1lIF07XG5cdFx0XHRhdHRySGFuZGxlWyBuYW1lIF0gPSByZXQ7XG5cdFx0XHRyZXQgPSBnZXR0ZXIoIGVsZW0sIG5hbWUsIGlzWE1MICkgIT0gbnVsbCA/XG5cdFx0XHRcdG5hbWUudG9Mb3dlckNhc2UoKSA6XG5cdFx0XHRcdG51bGw7XG5cdFx0XHRhdHRySGFuZGxlWyBuYW1lIF0gPSBoYW5kbGU7XG5cdFx0fVxuXHRcdHJldHVybiByZXQ7XG5cdH07XG59KTtcblxuXG5cblxudmFyIHJmb2N1c2FibGUgPSAvXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24pJC9pO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKHtcblx0cHJvcDogZnVuY3Rpb24oIG5hbWUsIHZhbHVlICkge1xuXHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGpRdWVyeS5wcm9wLCBuYW1lLCB2YWx1ZSwgYXJndW1lbnRzLmxlbmd0aCA+IDEgKTtcblx0fSxcblxuXHRyZW1vdmVQcm9wOiBmdW5jdGlvbiggbmFtZSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0ZGVsZXRlIHRoaXNbIGpRdWVyeS5wcm9wRml4WyBuYW1lIF0gfHwgbmFtZSBdO1xuXHRcdH0pO1xuXHR9XG59KTtcblxualF1ZXJ5LmV4dGVuZCh7XG5cdHByb3BGaXg6IHtcblx0XHRcImZvclwiOiBcImh0bWxGb3JcIixcblx0XHRcImNsYXNzXCI6IFwiY2xhc3NOYW1lXCJcblx0fSxcblxuXHRwcm9wOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUgKSB7XG5cdFx0dmFyIHJldCwgaG9va3MsIG5vdHhtbCxcblx0XHRcdG5UeXBlID0gZWxlbS5ub2RlVHlwZTtcblxuXHRcdC8vIERvbid0IGdldC9zZXQgcHJvcGVydGllcyBvbiB0ZXh0LCBjb21tZW50IGFuZCBhdHRyaWJ1dGUgbm9kZXNcblx0XHRpZiAoICFlbGVtIHx8IG5UeXBlID09PSAzIHx8IG5UeXBlID09PSA4IHx8IG5UeXBlID09PSAyICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdG5vdHhtbCA9IG5UeXBlICE9PSAxIHx8ICFqUXVlcnkuaXNYTUxEb2MoIGVsZW0gKTtcblxuXHRcdGlmICggbm90eG1sICkge1xuXHRcdFx0Ly8gRml4IG5hbWUgYW5kIGF0dGFjaCBob29rc1xuXHRcdFx0bmFtZSA9IGpRdWVyeS5wcm9wRml4WyBuYW1lIF0gfHwgbmFtZTtcblx0XHRcdGhvb2tzID0galF1ZXJ5LnByb3BIb29rc1sgbmFtZSBdO1xuXHRcdH1cblxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybiBob29rcyAmJiBcInNldFwiIGluIGhvb2tzICYmIChyZXQgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBuYW1lICkpICE9PSB1bmRlZmluZWQgP1xuXHRcdFx0XHRyZXQgOlxuXHRcdFx0XHQoIGVsZW1bIG5hbWUgXSA9IHZhbHVlICk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGhvb2tzICYmIFwiZ2V0XCIgaW4gaG9va3MgJiYgKHJldCA9IGhvb2tzLmdldCggZWxlbSwgbmFtZSApKSAhPT0gbnVsbCA/XG5cdFx0XHRcdHJldCA6XG5cdFx0XHRcdGVsZW1bIG5hbWUgXTtcblx0XHR9XG5cdH0sXG5cblx0cHJvcEhvb2tzOiB7XG5cdFx0dGFiSW5kZXg6IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBlbGVtLmhhc0F0dHJpYnV0ZSggXCJ0YWJpbmRleFwiICkgfHwgcmZvY3VzYWJsZS50ZXN0KCBlbGVtLm5vZGVOYW1lICkgfHwgZWxlbS5ocmVmID9cblx0XHRcdFx0XHRlbGVtLnRhYkluZGV4IDpcblx0XHRcdFx0XHQtMTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn0pO1xuXG5pZiAoICFzdXBwb3J0Lm9wdFNlbGVjdGVkICkge1xuXHRqUXVlcnkucHJvcEhvb2tzLnNlbGVjdGVkID0ge1xuXHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHR2YXIgcGFyZW50ID0gZWxlbS5wYXJlbnROb2RlO1xuXHRcdFx0aWYgKCBwYXJlbnQgJiYgcGFyZW50LnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdHBhcmVudC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cdH07XG59XG5cbmpRdWVyeS5lYWNoKFtcblx0XCJ0YWJJbmRleFwiLFxuXHRcInJlYWRPbmx5XCIsXG5cdFwibWF4TGVuZ3RoXCIsXG5cdFwiY2VsbFNwYWNpbmdcIixcblx0XCJjZWxsUGFkZGluZ1wiLFxuXHRcInJvd1NwYW5cIixcblx0XCJjb2xTcGFuXCIsXG5cdFwidXNlTWFwXCIsXG5cdFwiZnJhbWVCb3JkZXJcIixcblx0XCJjb250ZW50RWRpdGFibGVcIlxuXSwgZnVuY3Rpb24oKSB7XG5cdGpRdWVyeS5wcm9wRml4WyB0aGlzLnRvTG93ZXJDYXNlKCkgXSA9IHRoaXM7XG59KTtcblxuXG5cblxudmFyIHJjbGFzcyA9IC9bXFx0XFxyXFxuXFxmXS9nO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKHtcblx0YWRkQ2xhc3M6IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHR2YXIgY2xhc3NlcywgZWxlbSwgY3VyLCBjbGF6eiwgaiwgZmluYWxWYWx1ZSxcblx0XHRcdHByb2NlZWQgPSB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgdmFsdWUsXG5cdFx0XHRpID0gMCxcblx0XHRcdGxlbiA9IHRoaXMubGVuZ3RoO1xuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oIGogKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLmFkZENsYXNzKCB2YWx1ZS5jYWxsKCB0aGlzLCBqLCB0aGlzLmNsYXNzTmFtZSApICk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRpZiAoIHByb2NlZWQgKSB7XG5cdFx0XHQvLyBUaGUgZGlzanVuY3Rpb24gaGVyZSBpcyBmb3IgYmV0dGVyIGNvbXByZXNzaWJpbGl0eSAoc2VlIHJlbW92ZUNsYXNzKVxuXHRcdFx0Y2xhc3NlcyA9ICggdmFsdWUgfHwgXCJcIiApLm1hdGNoKCBybm90d2hpdGUgKSB8fCBbXTtcblxuXHRcdFx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdGVsZW0gPSB0aGlzWyBpIF07XG5cdFx0XHRcdGN1ciA9IGVsZW0ubm9kZVR5cGUgPT09IDEgJiYgKCBlbGVtLmNsYXNzTmFtZSA/XG5cdFx0XHRcdFx0KCBcIiBcIiArIGVsZW0uY2xhc3NOYW1lICsgXCIgXCIgKS5yZXBsYWNlKCByY2xhc3MsIFwiIFwiICkgOlxuXHRcdFx0XHRcdFwiIFwiXG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0aWYgKCBjdXIgKSB7XG5cdFx0XHRcdFx0aiA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoY2xhenogPSBjbGFzc2VzW2orK10pICkge1xuXHRcdFx0XHRcdFx0aWYgKCBjdXIuaW5kZXhPZiggXCIgXCIgKyBjbGF6eiArIFwiIFwiICkgPCAwICkge1xuXHRcdFx0XHRcdFx0XHRjdXIgKz0gY2xhenogKyBcIiBcIjtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBvbmx5IGFzc2lnbiBpZiBkaWZmZXJlbnQgdG8gYXZvaWQgdW5uZWVkZWQgcmVuZGVyaW5nLlxuXHRcdFx0XHRcdGZpbmFsVmFsdWUgPSBqUXVlcnkudHJpbSggY3VyICk7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLmNsYXNzTmFtZSAhPT0gZmluYWxWYWx1ZSApIHtcblx0XHRcdFx0XHRcdGVsZW0uY2xhc3NOYW1lID0gZmluYWxWYWx1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRyZW1vdmVDbGFzczogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdHZhciBjbGFzc2VzLCBlbGVtLCBjdXIsIGNsYXp6LCBqLCBmaW5hbFZhbHVlLFxuXHRcdFx0cHJvY2VlZCA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDAgfHwgdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIHZhbHVlLFxuXHRcdFx0aSA9IDAsXG5cdFx0XHRsZW4gPSB0aGlzLmxlbmd0aDtcblxuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICkgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCBqICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5yZW1vdmVDbGFzcyggdmFsdWUuY2FsbCggdGhpcywgaiwgdGhpcy5jbGFzc05hbWUgKSApO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHRcdGlmICggcHJvY2VlZCApIHtcblx0XHRcdGNsYXNzZXMgPSAoIHZhbHVlIHx8IFwiXCIgKS5tYXRjaCggcm5vdHdoaXRlICkgfHwgW107XG5cblx0XHRcdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHRlbGVtID0gdGhpc1sgaSBdO1xuXHRcdFx0XHQvLyBUaGlzIGV4cHJlc3Npb24gaXMgaGVyZSBmb3IgYmV0dGVyIGNvbXByZXNzaWJpbGl0eSAoc2VlIGFkZENsYXNzKVxuXHRcdFx0XHRjdXIgPSBlbGVtLm5vZGVUeXBlID09PSAxICYmICggZWxlbS5jbGFzc05hbWUgP1xuXHRcdFx0XHRcdCggXCIgXCIgKyBlbGVtLmNsYXNzTmFtZSArIFwiIFwiICkucmVwbGFjZSggcmNsYXNzLCBcIiBcIiApIDpcblx0XHRcdFx0XHRcIlwiXG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0aWYgKCBjdXIgKSB7XG5cdFx0XHRcdFx0aiA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoY2xhenogPSBjbGFzc2VzW2orK10pICkge1xuXHRcdFx0XHRcdFx0Ly8gUmVtb3ZlICphbGwqIGluc3RhbmNlc1xuXHRcdFx0XHRcdFx0d2hpbGUgKCBjdXIuaW5kZXhPZiggXCIgXCIgKyBjbGF6eiArIFwiIFwiICkgPj0gMCApIHtcblx0XHRcdFx0XHRcdFx0Y3VyID0gY3VyLnJlcGxhY2UoIFwiIFwiICsgY2xhenogKyBcIiBcIiwgXCIgXCIgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBPbmx5IGFzc2lnbiBpZiBkaWZmZXJlbnQgdG8gYXZvaWQgdW5uZWVkZWQgcmVuZGVyaW5nLlxuXHRcdFx0XHRcdGZpbmFsVmFsdWUgPSB2YWx1ZSA/IGpRdWVyeS50cmltKCBjdXIgKSA6IFwiXCI7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLmNsYXNzTmFtZSAhPT0gZmluYWxWYWx1ZSApIHtcblx0XHRcdFx0XHRcdGVsZW0uY2xhc3NOYW1lID0gZmluYWxWYWx1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHR0b2dnbGVDbGFzczogZnVuY3Rpb24oIHZhbHVlLCBzdGF0ZVZhbCApIHtcblx0XHR2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcblxuXHRcdGlmICggdHlwZW9mIHN0YXRlVmFsID09PSBcImJvb2xlYW5cIiAmJiB0eXBlID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIHN0YXRlVmFsID8gdGhpcy5hZGRDbGFzcyggdmFsdWUgKSA6IHRoaXMucmVtb3ZlQ2xhc3MoIHZhbHVlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oIGkgKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLnRvZ2dsZUNsYXNzKCB2YWx1ZS5jYWxsKHRoaXMsIGksIHRoaXMuY2xhc3NOYW1lLCBzdGF0ZVZhbCksIHN0YXRlVmFsICk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCB0eXBlID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0XHQvLyBUb2dnbGUgaW5kaXZpZHVhbCBjbGFzcyBuYW1lc1xuXHRcdFx0XHR2YXIgY2xhc3NOYW1lLFxuXHRcdFx0XHRcdGkgPSAwLFxuXHRcdFx0XHRcdHNlbGYgPSBqUXVlcnkoIHRoaXMgKSxcblx0XHRcdFx0XHRjbGFzc05hbWVzID0gdmFsdWUubWF0Y2goIHJub3R3aGl0ZSApIHx8IFtdO1xuXG5cdFx0XHRcdHdoaWxlICggKGNsYXNzTmFtZSA9IGNsYXNzTmFtZXNbIGkrKyBdKSApIHtcblx0XHRcdFx0XHQvLyBDaGVjayBlYWNoIGNsYXNzTmFtZSBnaXZlbiwgc3BhY2Ugc2VwYXJhdGVkIGxpc3Rcblx0XHRcdFx0XHRpZiAoIHNlbGYuaGFzQ2xhc3MoIGNsYXNzTmFtZSApICkge1xuXHRcdFx0XHRcdFx0c2VsZi5yZW1vdmVDbGFzcyggY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHNlbGYuYWRkQ2xhc3MoIGNsYXNzTmFtZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBUb2dnbGUgd2hvbGUgY2xhc3MgbmFtZVxuXHRcdFx0fSBlbHNlIGlmICggdHlwZSA9PT0gc3RydW5kZWZpbmVkIHx8IHR5cGUgPT09IFwiYm9vbGVhblwiICkge1xuXHRcdFx0XHRpZiAoIHRoaXMuY2xhc3NOYW1lICkge1xuXHRcdFx0XHRcdC8vIHN0b3JlIGNsYXNzTmFtZSBpZiBzZXRcblx0XHRcdFx0XHRkYXRhX3ByaXYuc2V0KCB0aGlzLCBcIl9fY2xhc3NOYW1lX19cIiwgdGhpcy5jbGFzc05hbWUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIElmIHRoZSBlbGVtZW50IGhhcyBhIGNsYXNzIG5hbWUgb3IgaWYgd2UncmUgcGFzc2VkIGBmYWxzZWAsXG5cdFx0XHRcdC8vIHRoZW4gcmVtb3ZlIHRoZSB3aG9sZSBjbGFzc25hbWUgKGlmIHRoZXJlIHdhcyBvbmUsIHRoZSBhYm92ZSBzYXZlZCBpdCkuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSBicmluZyBiYWNrIHdoYXRldmVyIHdhcyBwcmV2aW91c2x5IHNhdmVkIChpZiBhbnl0aGluZyksXG5cdFx0XHRcdC8vIGZhbGxpbmcgYmFjayB0byB0aGUgZW1wdHkgc3RyaW5nIGlmIG5vdGhpbmcgd2FzIHN0b3JlZC5cblx0XHRcdFx0dGhpcy5jbGFzc05hbWUgPSB0aGlzLmNsYXNzTmFtZSB8fCB2YWx1ZSA9PT0gZmFsc2UgPyBcIlwiIDogZGF0YV9wcml2LmdldCggdGhpcywgXCJfX2NsYXNzTmFtZV9fXCIgKSB8fCBcIlwiO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9LFxuXG5cdGhhc0NsYXNzOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0dmFyIGNsYXNzTmFtZSA9IFwiIFwiICsgc2VsZWN0b3IgKyBcIiBcIixcblx0XHRcdGkgPSAwLFxuXHRcdFx0bCA9IHRoaXMubGVuZ3RoO1xuXHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdGlmICggdGhpc1tpXS5ub2RlVHlwZSA9PT0gMSAmJiAoXCIgXCIgKyB0aGlzW2ldLmNsYXNzTmFtZSArIFwiIFwiKS5yZXBsYWNlKHJjbGFzcywgXCIgXCIpLmluZGV4T2YoIGNsYXNzTmFtZSApID49IDAgKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxufSk7XG5cblxuXG5cbnZhciBycmV0dXJuID0gL1xcci9nO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKHtcblx0dmFsOiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0dmFyIGhvb2tzLCByZXQsIGlzRnVuY3Rpb24sXG5cdFx0XHRlbGVtID0gdGhpc1swXTtcblxuXHRcdGlmICggIWFyZ3VtZW50cy5sZW5ndGggKSB7XG5cdFx0XHRpZiAoIGVsZW0gKSB7XG5cdFx0XHRcdGhvb2tzID0galF1ZXJ5LnZhbEhvb2tzWyBlbGVtLnR5cGUgXSB8fCBqUXVlcnkudmFsSG9va3NbIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSBdO1xuXG5cdFx0XHRcdGlmICggaG9va3MgJiYgXCJnZXRcIiBpbiBob29rcyAmJiAocmV0ID0gaG9va3MuZ2V0KCBlbGVtLCBcInZhbHVlXCIgKSkgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0ID0gZWxlbS52YWx1ZTtcblxuXHRcdFx0XHRyZXR1cm4gdHlwZW9mIHJldCA9PT0gXCJzdHJpbmdcIiA/XG5cdFx0XHRcdFx0Ly8gSGFuZGxlIG1vc3QgY29tbW9uIHN0cmluZyBjYXNlc1xuXHRcdFx0XHRcdHJldC5yZXBsYWNlKHJyZXR1cm4sIFwiXCIpIDpcblx0XHRcdFx0XHQvLyBIYW5kbGUgY2FzZXMgd2hlcmUgdmFsdWUgaXMgbnVsbC91bmRlZiBvciBudW1iZXJcblx0XHRcdFx0XHRyZXQgPT0gbnVsbCA/IFwiXCIgOiByZXQ7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpc0Z1bmN0aW9uID0galF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICk7XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0dmFyIHZhbDtcblxuXHRcdFx0aWYgKCB0aGlzLm5vZGVUeXBlICE9PSAxICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaXNGdW5jdGlvbiApIHtcblx0XHRcdFx0dmFsID0gdmFsdWUuY2FsbCggdGhpcywgaSwgalF1ZXJ5KCB0aGlzICkudmFsKCkgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhbCA9IHZhbHVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBUcmVhdCBudWxsL3VuZGVmaW5lZCBhcyBcIlwiOyBjb252ZXJ0IG51bWJlcnMgdG8gc3RyaW5nXG5cdFx0XHRpZiAoIHZhbCA9PSBudWxsICkge1xuXHRcdFx0XHR2YWwgPSBcIlwiO1xuXG5cdFx0XHR9IGVsc2UgaWYgKCB0eXBlb2YgdmFsID09PSBcIm51bWJlclwiICkge1xuXHRcdFx0XHR2YWwgKz0gXCJcIjtcblxuXHRcdFx0fSBlbHNlIGlmICggalF1ZXJ5LmlzQXJyYXkoIHZhbCApICkge1xuXHRcdFx0XHR2YWwgPSBqUXVlcnkubWFwKCB2YWwsIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdFx0XHRyZXR1cm4gdmFsdWUgPT0gbnVsbCA/IFwiXCIgOiB2YWx1ZSArIFwiXCI7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXG5cdFx0XHRob29rcyA9IGpRdWVyeS52YWxIb29rc1sgdGhpcy50eXBlIF0gfHwgalF1ZXJ5LnZhbEhvb2tzWyB0aGlzLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgXTtcblxuXHRcdFx0Ly8gSWYgc2V0IHJldHVybnMgdW5kZWZpbmVkLCBmYWxsIGJhY2sgdG8gbm9ybWFsIHNldHRpbmdcblx0XHRcdGlmICggIWhvb2tzIHx8ICEoXCJzZXRcIiBpbiBob29rcykgfHwgaG9va3Muc2V0KCB0aGlzLCB2YWwsIFwidmFsdWVcIiApID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHRoaXMudmFsdWUgPSB2YWw7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn0pO1xuXG5qUXVlcnkuZXh0ZW5kKHtcblx0dmFsSG9va3M6IHtcblx0XHRvcHRpb246IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciB2YWwgPSBqUXVlcnkuZmluZC5hdHRyKCBlbGVtLCBcInZhbHVlXCIgKTtcblx0XHRcdFx0cmV0dXJuIHZhbCAhPSBudWxsID9cblx0XHRcdFx0XHR2YWwgOlxuXHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFMTAtMTErXG5cdFx0XHRcdFx0Ly8gb3B0aW9uLnRleHQgdGhyb3dzIGV4Y2VwdGlvbnMgKCMxNDY4NiwgIzE0ODU4KVxuXHRcdFx0XHRcdGpRdWVyeS50cmltKCBqUXVlcnkudGV4dCggZWxlbSApICk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRzZWxlY3Q6IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciB2YWx1ZSwgb3B0aW9uLFxuXHRcdFx0XHRcdG9wdGlvbnMgPSBlbGVtLm9wdGlvbnMsXG5cdFx0XHRcdFx0aW5kZXggPSBlbGVtLnNlbGVjdGVkSW5kZXgsXG5cdFx0XHRcdFx0b25lID0gZWxlbS50eXBlID09PSBcInNlbGVjdC1vbmVcIiB8fCBpbmRleCA8IDAsXG5cdFx0XHRcdFx0dmFsdWVzID0gb25lID8gbnVsbCA6IFtdLFxuXHRcdFx0XHRcdG1heCA9IG9uZSA/IGluZGV4ICsgMSA6IG9wdGlvbnMubGVuZ3RoLFxuXHRcdFx0XHRcdGkgPSBpbmRleCA8IDAgP1xuXHRcdFx0XHRcdFx0bWF4IDpcblx0XHRcdFx0XHRcdG9uZSA/IGluZGV4IDogMDtcblxuXHRcdFx0XHQvLyBMb29wIHRocm91Z2ggYWxsIHRoZSBzZWxlY3RlZCBvcHRpb25zXG5cdFx0XHRcdGZvciAoIDsgaSA8IG1heDsgaSsrICkge1xuXHRcdFx0XHRcdG9wdGlvbiA9IG9wdGlvbnNbIGkgXTtcblxuXHRcdFx0XHRcdC8vIElFNi05IGRvZXNuJ3QgdXBkYXRlIHNlbGVjdGVkIGFmdGVyIGZvcm0gcmVzZXQgKCMyNTUxKVxuXHRcdFx0XHRcdGlmICggKCBvcHRpb24uc2VsZWN0ZWQgfHwgaSA9PT0gaW5kZXggKSAmJlxuXHRcdFx0XHRcdFx0XHQvLyBEb24ndCByZXR1cm4gb3B0aW9ucyB0aGF0IGFyZSBkaXNhYmxlZCBvciBpbiBhIGRpc2FibGVkIG9wdGdyb3VwXG5cdFx0XHRcdFx0XHRcdCggc3VwcG9ydC5vcHREaXNhYmxlZCA/ICFvcHRpb24uZGlzYWJsZWQgOiBvcHRpb24uZ2V0QXR0cmlidXRlKCBcImRpc2FibGVkXCIgKSA9PT0gbnVsbCApICYmXG5cdFx0XHRcdFx0XHRcdCggIW9wdGlvbi5wYXJlbnROb2RlLmRpc2FibGVkIHx8ICFqUXVlcnkubm9kZU5hbWUoIG9wdGlvbi5wYXJlbnROb2RlLCBcIm9wdGdyb3VwXCIgKSApICkge1xuXG5cdFx0XHRcdFx0XHQvLyBHZXQgdGhlIHNwZWNpZmljIHZhbHVlIGZvciB0aGUgb3B0aW9uXG5cdFx0XHRcdFx0XHR2YWx1ZSA9IGpRdWVyeSggb3B0aW9uICkudmFsKCk7XG5cblx0XHRcdFx0XHRcdC8vIFdlIGRvbid0IG5lZWQgYW4gYXJyYXkgZm9yIG9uZSBzZWxlY3RzXG5cdFx0XHRcdFx0XHRpZiAoIG9uZSApIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHQvLyBNdWx0aS1TZWxlY3RzIHJldHVybiBhbiBhcnJheVxuXHRcdFx0XHRcdFx0dmFsdWVzLnB1c2goIHZhbHVlICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIHZhbHVlcztcblx0XHRcdH0sXG5cblx0XHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdFx0XHR2YXIgb3B0aW9uU2V0LCBvcHRpb24sXG5cdFx0XHRcdFx0b3B0aW9ucyA9IGVsZW0ub3B0aW9ucyxcblx0XHRcdFx0XHR2YWx1ZXMgPSBqUXVlcnkubWFrZUFycmF5KCB2YWx1ZSApLFxuXHRcdFx0XHRcdGkgPSBvcHRpb25zLmxlbmd0aDtcblxuXHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0XHRvcHRpb24gPSBvcHRpb25zWyBpIF07XG5cdFx0XHRcdFx0aWYgKCAob3B0aW9uLnNlbGVjdGVkID0galF1ZXJ5LmluQXJyYXkoIG9wdGlvbi52YWx1ZSwgdmFsdWVzICkgPj0gMCkgKSB7XG5cdFx0XHRcdFx0XHRvcHRpb25TZXQgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEZvcmNlIGJyb3dzZXJzIHRvIGJlaGF2ZSBjb25zaXN0ZW50bHkgd2hlbiBub24tbWF0Y2hpbmcgdmFsdWUgaXMgc2V0XG5cdFx0XHRcdGlmICggIW9wdGlvblNldCApIHtcblx0XHRcdFx0XHRlbGVtLnNlbGVjdGVkSW5kZXggPSAtMTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdmFsdWVzO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufSk7XG5cbi8vIFJhZGlvcyBhbmQgY2hlY2tib3hlcyBnZXR0ZXIvc2V0dGVyXG5qUXVlcnkuZWFjaChbIFwicmFkaW9cIiwgXCJjaGVja2JveFwiIF0sIGZ1bmN0aW9uKCkge1xuXHRqUXVlcnkudmFsSG9va3NbIHRoaXMgXSA9IHtcblx0XHRzZXQ6IGZ1bmN0aW9uKCBlbGVtLCB2YWx1ZSApIHtcblx0XHRcdGlmICggalF1ZXJ5LmlzQXJyYXkoIHZhbHVlICkgKSB7XG5cdFx0XHRcdHJldHVybiAoIGVsZW0uY2hlY2tlZCA9IGpRdWVyeS5pbkFycmF5KCBqUXVlcnkoZWxlbSkudmFsKCksIHZhbHVlICkgPj0gMCApO1xuXHRcdFx0fVxuXHRcdH1cblx0fTtcblx0aWYgKCAhc3VwcG9ydC5jaGVja09uICkge1xuXHRcdGpRdWVyeS52YWxIb29rc1sgdGhpcyBdLmdldCA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKFwidmFsdWVcIikgPT09IG51bGwgPyBcIm9uXCIgOiBlbGVtLnZhbHVlO1xuXHRcdH07XG5cdH1cbn0pO1xuXG5cblxuXG4vLyBSZXR1cm4galF1ZXJ5IGZvciBhdHRyaWJ1dGVzLW9ubHkgaW5jbHVzaW9uXG5cblxualF1ZXJ5LmVhY2goIChcImJsdXIgZm9jdXMgZm9jdXNpbiBmb2N1c291dCBsb2FkIHJlc2l6ZSBzY3JvbGwgdW5sb2FkIGNsaWNrIGRibGNsaWNrIFwiICtcblx0XCJtb3VzZWRvd24gbW91c2V1cCBtb3VzZW1vdmUgbW91c2VvdmVyIG1vdXNlb3V0IG1vdXNlZW50ZXIgbW91c2VsZWF2ZSBcIiArXG5cdFwiY2hhbmdlIHNlbGVjdCBzdWJtaXQga2V5ZG93biBrZXlwcmVzcyBrZXl1cCBlcnJvciBjb250ZXh0bWVudVwiKS5zcGxpdChcIiBcIiksIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXG5cdC8vIEhhbmRsZSBldmVudCBiaW5kaW5nXG5cdGpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIGRhdGEsIGZuICkge1xuXHRcdHJldHVybiBhcmd1bWVudHMubGVuZ3RoID4gMCA/XG5cdFx0XHR0aGlzLm9uKCBuYW1lLCBudWxsLCBkYXRhLCBmbiApIDpcblx0XHRcdHRoaXMudHJpZ2dlciggbmFtZSApO1xuXHR9O1xufSk7XG5cbmpRdWVyeS5mbi5leHRlbmQoe1xuXHRob3ZlcjogZnVuY3Rpb24oIGZuT3ZlciwgZm5PdXQgKSB7XG5cdFx0cmV0dXJuIHRoaXMubW91c2VlbnRlciggZm5PdmVyICkubW91c2VsZWF2ZSggZm5PdXQgfHwgZm5PdmVyICk7XG5cdH0sXG5cblx0YmluZDogZnVuY3Rpb24oIHR5cGVzLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIG51bGwsIGRhdGEsIGZuICk7XG5cdH0sXG5cdHVuYmluZDogZnVuY3Rpb24oIHR5cGVzLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vZmYoIHR5cGVzLCBudWxsLCBmbiApO1xuXHR9LFxuXG5cdGRlbGVnYXRlOiBmdW5jdGlvbiggc2VsZWN0b3IsIHR5cGVzLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApO1xuXHR9LFxuXHR1bmRlbGVnYXRlOiBmdW5jdGlvbiggc2VsZWN0b3IsIHR5cGVzLCBmbiApIHtcblx0XHQvLyAoIG5hbWVzcGFjZSApIG9yICggc2VsZWN0b3IsIHR5cGVzIFssIGZuXSApXG5cdFx0cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyB0aGlzLm9mZiggc2VsZWN0b3IsIFwiKipcIiApIDogdGhpcy5vZmYoIHR5cGVzLCBzZWxlY3RvciB8fCBcIioqXCIsIGZuICk7XG5cdH1cbn0pO1xuXG5cbnZhciBub25jZSA9IGpRdWVyeS5ub3coKTtcblxudmFyIHJxdWVyeSA9ICgvXFw/Lyk7XG5cblxuXG4vLyBTdXBwb3J0OiBBbmRyb2lkIDIuM1xuLy8gV29ya2Fyb3VuZCBmYWlsdXJlIHRvIHN0cmluZy1jYXN0IG51bGwgaW5wdXRcbmpRdWVyeS5wYXJzZUpTT04gPSBmdW5jdGlvbiggZGF0YSApIHtcblx0cmV0dXJuIEpTT04ucGFyc2UoIGRhdGEgKyBcIlwiICk7XG59O1xuXG5cbi8vIENyb3NzLWJyb3dzZXIgeG1sIHBhcnNpbmdcbmpRdWVyeS5wYXJzZVhNTCA9IGZ1bmN0aW9uKCBkYXRhICkge1xuXHR2YXIgeG1sLCB0bXA7XG5cdGlmICggIWRhdGEgfHwgdHlwZW9mIGRhdGEgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHQvLyBTdXBwb3J0OiBJRTlcblx0dHJ5IHtcblx0XHR0bXAgPSBuZXcgRE9NUGFyc2VyKCk7XG5cdFx0eG1sID0gdG1wLnBhcnNlRnJvbVN0cmluZyggZGF0YSwgXCJ0ZXh0L3htbFwiICk7XG5cdH0gY2F0Y2ggKCBlICkge1xuXHRcdHhtbCA9IHVuZGVmaW5lZDtcblx0fVxuXG5cdGlmICggIXhtbCB8fCB4bWwuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIFwicGFyc2VyZXJyb3JcIiApLmxlbmd0aCApIHtcblx0XHRqUXVlcnkuZXJyb3IoIFwiSW52YWxpZCBYTUw6IFwiICsgZGF0YSApO1xuXHR9XG5cdHJldHVybiB4bWw7XG59O1xuXG5cbnZhclxuXHRyaGFzaCA9IC8jLiokLyxcblx0cnRzID0gLyhbPyZdKV89W14mXSovLFxuXHRyaGVhZGVycyA9IC9eKC4qPyk6WyBcXHRdKihbXlxcclxcbl0qKSQvbWcsXG5cdC8vICM3NjUzLCAjODEyNSwgIzgxNTI6IGxvY2FsIHByb3RvY29sIGRldGVjdGlvblxuXHRybG9jYWxQcm90b2NvbCA9IC9eKD86YWJvdXR8YXBwfGFwcC1zdG9yYWdlfC4rLWV4dGVuc2lvbnxmaWxlfHJlc3x3aWRnZXQpOiQvLFxuXHRybm9Db250ZW50ID0gL14oPzpHRVR8SEVBRCkkLyxcblx0cnByb3RvY29sID0gL15cXC9cXC8vLFxuXHRydXJsID0gL14oW1xcdy4rLV0rOikoPzpcXC9cXC8oPzpbXlxcLz8jXSpAfCkoW15cXC8/IzpdKikoPzo6KFxcZCspfCl8KS8sXG5cblx0LyogUHJlZmlsdGVyc1xuXHQgKiAxKSBUaGV5IGFyZSB1c2VmdWwgdG8gaW50cm9kdWNlIGN1c3RvbSBkYXRhVHlwZXMgKHNlZSBhamF4L2pzb25wLmpzIGZvciBhbiBleGFtcGxlKVxuXHQgKiAyKSBUaGVzZSBhcmUgY2FsbGVkOlxuXHQgKiAgICAtIEJFRk9SRSBhc2tpbmcgZm9yIGEgdHJhbnNwb3J0XG5cdCAqICAgIC0gQUZURVIgcGFyYW0gc2VyaWFsaXphdGlvbiAocy5kYXRhIGlzIGEgc3RyaW5nIGlmIHMucHJvY2Vzc0RhdGEgaXMgdHJ1ZSlcblx0ICogMykga2V5IGlzIHRoZSBkYXRhVHlwZVxuXHQgKiA0KSB0aGUgY2F0Y2hhbGwgc3ltYm9sIFwiKlwiIGNhbiBiZSB1c2VkXG5cdCAqIDUpIGV4ZWN1dGlvbiB3aWxsIHN0YXJ0IHdpdGggdHJhbnNwb3J0IGRhdGFUeXBlIGFuZCBUSEVOIGNvbnRpbnVlIGRvd24gdG8gXCIqXCIgaWYgbmVlZGVkXG5cdCAqL1xuXHRwcmVmaWx0ZXJzID0ge30sXG5cblx0LyogVHJhbnNwb3J0cyBiaW5kaW5nc1xuXHQgKiAxKSBrZXkgaXMgdGhlIGRhdGFUeXBlXG5cdCAqIDIpIHRoZSBjYXRjaGFsbCBzeW1ib2wgXCIqXCIgY2FuIGJlIHVzZWRcblx0ICogMykgc2VsZWN0aW9uIHdpbGwgc3RhcnQgd2l0aCB0cmFuc3BvcnQgZGF0YVR5cGUgYW5kIFRIRU4gZ28gdG8gXCIqXCIgaWYgbmVlZGVkXG5cdCAqL1xuXHR0cmFuc3BvcnRzID0ge30sXG5cblx0Ly8gQXZvaWQgY29tbWVudC1wcm9sb2cgY2hhciBzZXF1ZW5jZSAoIzEwMDk4KTsgbXVzdCBhcHBlYXNlIGxpbnQgYW5kIGV2YWRlIGNvbXByZXNzaW9uXG5cdGFsbFR5cGVzID0gXCIqL1wiLmNvbmNhdCggXCIqXCIgKSxcblxuXHQvLyBEb2N1bWVudCBsb2NhdGlvblxuXHRhamF4TG9jYXRpb24gPSB3aW5kb3cubG9jYXRpb24uaHJlZixcblxuXHQvLyBTZWdtZW50IGxvY2F0aW9uIGludG8gcGFydHNcblx0YWpheExvY1BhcnRzID0gcnVybC5leGVjKCBhamF4TG9jYXRpb24udG9Mb3dlckNhc2UoKSApIHx8IFtdO1xuXG4vLyBCYXNlIFwiY29uc3RydWN0b3JcIiBmb3IgalF1ZXJ5LmFqYXhQcmVmaWx0ZXIgYW5kIGpRdWVyeS5hamF4VHJhbnNwb3J0XG5mdW5jdGlvbiBhZGRUb1ByZWZpbHRlcnNPclRyYW5zcG9ydHMoIHN0cnVjdHVyZSApIHtcblxuXHQvLyBkYXRhVHlwZUV4cHJlc3Npb24gaXMgb3B0aW9uYWwgYW5kIGRlZmF1bHRzIHRvIFwiKlwiXG5cdHJldHVybiBmdW5jdGlvbiggZGF0YVR5cGVFeHByZXNzaW9uLCBmdW5jICkge1xuXG5cdFx0aWYgKCB0eXBlb2YgZGF0YVR5cGVFeHByZXNzaW9uICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0ZnVuYyA9IGRhdGFUeXBlRXhwcmVzc2lvbjtcblx0XHRcdGRhdGFUeXBlRXhwcmVzc2lvbiA9IFwiKlwiO1xuXHRcdH1cblxuXHRcdHZhciBkYXRhVHlwZSxcblx0XHRcdGkgPSAwLFxuXHRcdFx0ZGF0YVR5cGVzID0gZGF0YVR5cGVFeHByZXNzaW9uLnRvTG93ZXJDYXNlKCkubWF0Y2goIHJub3R3aGl0ZSApIHx8IFtdO1xuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggZnVuYyApICkge1xuXHRcdFx0Ly8gRm9yIGVhY2ggZGF0YVR5cGUgaW4gdGhlIGRhdGFUeXBlRXhwcmVzc2lvblxuXHRcdFx0d2hpbGUgKCAoZGF0YVR5cGUgPSBkYXRhVHlwZXNbaSsrXSkgKSB7XG5cdFx0XHRcdC8vIFByZXBlbmQgaWYgcmVxdWVzdGVkXG5cdFx0XHRcdGlmICggZGF0YVR5cGVbMF0gPT09IFwiK1wiICkge1xuXHRcdFx0XHRcdGRhdGFUeXBlID0gZGF0YVR5cGUuc2xpY2UoIDEgKSB8fCBcIipcIjtcblx0XHRcdFx0XHQoc3RydWN0dXJlWyBkYXRhVHlwZSBdID0gc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdKS51bnNoaWZ0KCBmdW5jICk7XG5cblx0XHRcdFx0Ly8gT3RoZXJ3aXNlIGFwcGVuZFxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdChzdHJ1Y3R1cmVbIGRhdGFUeXBlIF0gPSBzdHJ1Y3R1cmVbIGRhdGFUeXBlIF0gfHwgW10pLnB1c2goIGZ1bmMgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcbn1cblxuLy8gQmFzZSBpbnNwZWN0aW9uIGZ1bmN0aW9uIGZvciBwcmVmaWx0ZXJzIGFuZCB0cmFuc3BvcnRzXG5mdW5jdGlvbiBpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggc3RydWN0dXJlLCBvcHRpb25zLCBvcmlnaW5hbE9wdGlvbnMsIGpxWEhSICkge1xuXG5cdHZhciBpbnNwZWN0ZWQgPSB7fSxcblx0XHRzZWVraW5nVHJhbnNwb3J0ID0gKCBzdHJ1Y3R1cmUgPT09IHRyYW5zcG9ydHMgKTtcblxuXHRmdW5jdGlvbiBpbnNwZWN0KCBkYXRhVHlwZSApIHtcblx0XHR2YXIgc2VsZWN0ZWQ7XG5cdFx0aW5zcGVjdGVkWyBkYXRhVHlwZSBdID0gdHJ1ZTtcblx0XHRqUXVlcnkuZWFjaCggc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdLCBmdW5jdGlvbiggXywgcHJlZmlsdGVyT3JGYWN0b3J5ICkge1xuXHRcdFx0dmFyIGRhdGFUeXBlT3JUcmFuc3BvcnQgPSBwcmVmaWx0ZXJPckZhY3RvcnkoIG9wdGlvbnMsIG9yaWdpbmFsT3B0aW9ucywganFYSFIgKTtcblx0XHRcdGlmICggdHlwZW9mIGRhdGFUeXBlT3JUcmFuc3BvcnQgPT09IFwic3RyaW5nXCIgJiYgIXNlZWtpbmdUcmFuc3BvcnQgJiYgIWluc3BlY3RlZFsgZGF0YVR5cGVPclRyYW5zcG9ydCBdICkge1xuXHRcdFx0XHRvcHRpb25zLmRhdGFUeXBlcy51bnNoaWZ0KCBkYXRhVHlwZU9yVHJhbnNwb3J0ICk7XG5cdFx0XHRcdGluc3BlY3QoIGRhdGFUeXBlT3JUcmFuc3BvcnQgKTtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fSBlbHNlIGlmICggc2Vla2luZ1RyYW5zcG9ydCApIHtcblx0XHRcdFx0cmV0dXJuICEoIHNlbGVjdGVkID0gZGF0YVR5cGVPclRyYW5zcG9ydCApO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdHJldHVybiBzZWxlY3RlZDtcblx0fVxuXG5cdHJldHVybiBpbnNwZWN0KCBvcHRpb25zLmRhdGFUeXBlc1sgMCBdICkgfHwgIWluc3BlY3RlZFsgXCIqXCIgXSAmJiBpbnNwZWN0KCBcIipcIiApO1xufVxuXG4vLyBBIHNwZWNpYWwgZXh0ZW5kIGZvciBhamF4IG9wdGlvbnNcbi8vIHRoYXQgdGFrZXMgXCJmbGF0XCIgb3B0aW9ucyAobm90IHRvIGJlIGRlZXAgZXh0ZW5kZWQpXG4vLyBGaXhlcyAjOTg4N1xuZnVuY3Rpb24gYWpheEV4dGVuZCggdGFyZ2V0LCBzcmMgKSB7XG5cdHZhciBrZXksIGRlZXAsXG5cdFx0ZmxhdE9wdGlvbnMgPSBqUXVlcnkuYWpheFNldHRpbmdzLmZsYXRPcHRpb25zIHx8IHt9O1xuXG5cdGZvciAoIGtleSBpbiBzcmMgKSB7XG5cdFx0aWYgKCBzcmNbIGtleSBdICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHQoIGZsYXRPcHRpb25zWyBrZXkgXSA/IHRhcmdldCA6ICggZGVlcCB8fCAoZGVlcCA9IHt9KSApIClbIGtleSBdID0gc3JjWyBrZXkgXTtcblx0XHR9XG5cdH1cblx0aWYgKCBkZWVwICkge1xuXHRcdGpRdWVyeS5leHRlbmQoIHRydWUsIHRhcmdldCwgZGVlcCApO1xuXHR9XG5cblx0cmV0dXJuIHRhcmdldDtcbn1cblxuLyogSGFuZGxlcyByZXNwb25zZXMgdG8gYW4gYWpheCByZXF1ZXN0OlxuICogLSBmaW5kcyB0aGUgcmlnaHQgZGF0YVR5cGUgKG1lZGlhdGVzIGJldHdlZW4gY29udGVudC10eXBlIGFuZCBleHBlY3RlZCBkYXRhVHlwZSlcbiAqIC0gcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyByZXNwb25zZVxuICovXG5mdW5jdGlvbiBhamF4SGFuZGxlUmVzcG9uc2VzKCBzLCBqcVhIUiwgcmVzcG9uc2VzICkge1xuXG5cdHZhciBjdCwgdHlwZSwgZmluYWxEYXRhVHlwZSwgZmlyc3REYXRhVHlwZSxcblx0XHRjb250ZW50cyA9IHMuY29udGVudHMsXG5cdFx0ZGF0YVR5cGVzID0gcy5kYXRhVHlwZXM7XG5cblx0Ly8gUmVtb3ZlIGF1dG8gZGF0YVR5cGUgYW5kIGdldCBjb250ZW50LXR5cGUgaW4gdGhlIHByb2Nlc3Ncblx0d2hpbGUgKCBkYXRhVHlwZXNbIDAgXSA9PT0gXCIqXCIgKSB7XG5cdFx0ZGF0YVR5cGVzLnNoaWZ0KCk7XG5cdFx0aWYgKCBjdCA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0Y3QgPSBzLm1pbWVUeXBlIHx8IGpxWEhSLmdldFJlc3BvbnNlSGVhZGVyKFwiQ29udGVudC1UeXBlXCIpO1xuXHRcdH1cblx0fVxuXG5cdC8vIENoZWNrIGlmIHdlJ3JlIGRlYWxpbmcgd2l0aCBhIGtub3duIGNvbnRlbnQtdHlwZVxuXHRpZiAoIGN0ICkge1xuXHRcdGZvciAoIHR5cGUgaW4gY29udGVudHMgKSB7XG5cdFx0XHRpZiAoIGNvbnRlbnRzWyB0eXBlIF0gJiYgY29udGVudHNbIHR5cGUgXS50ZXN0KCBjdCApICkge1xuXHRcdFx0XHRkYXRhVHlwZXMudW5zaGlmdCggdHlwZSApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBDaGVjayB0byBzZWUgaWYgd2UgaGF2ZSBhIHJlc3BvbnNlIGZvciB0aGUgZXhwZWN0ZWQgZGF0YVR5cGVcblx0aWYgKCBkYXRhVHlwZXNbIDAgXSBpbiByZXNwb25zZXMgKSB7XG5cdFx0ZmluYWxEYXRhVHlwZSA9IGRhdGFUeXBlc1sgMCBdO1xuXHR9IGVsc2Uge1xuXHRcdC8vIFRyeSBjb252ZXJ0aWJsZSBkYXRhVHlwZXNcblx0XHRmb3IgKCB0eXBlIGluIHJlc3BvbnNlcyApIHtcblx0XHRcdGlmICggIWRhdGFUeXBlc1sgMCBdIHx8IHMuY29udmVydGVyc1sgdHlwZSArIFwiIFwiICsgZGF0YVR5cGVzWzBdIF0gKSB7XG5cdFx0XHRcdGZpbmFsRGF0YVR5cGUgPSB0eXBlO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGlmICggIWZpcnN0RGF0YVR5cGUgKSB7XG5cdFx0XHRcdGZpcnN0RGF0YVR5cGUgPSB0eXBlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHQvLyBPciBqdXN0IHVzZSBmaXJzdCBvbmVcblx0XHRmaW5hbERhdGFUeXBlID0gZmluYWxEYXRhVHlwZSB8fCBmaXJzdERhdGFUeXBlO1xuXHR9XG5cblx0Ly8gSWYgd2UgZm91bmQgYSBkYXRhVHlwZVxuXHQvLyBXZSBhZGQgdGhlIGRhdGFUeXBlIHRvIHRoZSBsaXN0IGlmIG5lZWRlZFxuXHQvLyBhbmQgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIHJlc3BvbnNlXG5cdGlmICggZmluYWxEYXRhVHlwZSApIHtcblx0XHRpZiAoIGZpbmFsRGF0YVR5cGUgIT09IGRhdGFUeXBlc1sgMCBdICkge1xuXHRcdFx0ZGF0YVR5cGVzLnVuc2hpZnQoIGZpbmFsRGF0YVR5cGUgKTtcblx0XHR9XG5cdFx0cmV0dXJuIHJlc3BvbnNlc1sgZmluYWxEYXRhVHlwZSBdO1xuXHR9XG59XG5cbi8qIENoYWluIGNvbnZlcnNpb25zIGdpdmVuIHRoZSByZXF1ZXN0IGFuZCB0aGUgb3JpZ2luYWwgcmVzcG9uc2VcbiAqIEFsc28gc2V0cyB0aGUgcmVzcG9uc2VYWFggZmllbGRzIG9uIHRoZSBqcVhIUiBpbnN0YW5jZVxuICovXG5mdW5jdGlvbiBhamF4Q29udmVydCggcywgcmVzcG9uc2UsIGpxWEhSLCBpc1N1Y2Nlc3MgKSB7XG5cdHZhciBjb252MiwgY3VycmVudCwgY29udiwgdG1wLCBwcmV2LFxuXHRcdGNvbnZlcnRlcnMgPSB7fSxcblx0XHQvLyBXb3JrIHdpdGggYSBjb3B5IG9mIGRhdGFUeXBlcyBpbiBjYXNlIHdlIG5lZWQgdG8gbW9kaWZ5IGl0IGZvciBjb252ZXJzaW9uXG5cdFx0ZGF0YVR5cGVzID0gcy5kYXRhVHlwZXMuc2xpY2UoKTtcblxuXHQvLyBDcmVhdGUgY29udmVydGVycyBtYXAgd2l0aCBsb3dlcmNhc2VkIGtleXNcblx0aWYgKCBkYXRhVHlwZXNbIDEgXSApIHtcblx0XHRmb3IgKCBjb252IGluIHMuY29udmVydGVycyApIHtcblx0XHRcdGNvbnZlcnRlcnNbIGNvbnYudG9Mb3dlckNhc2UoKSBdID0gcy5jb252ZXJ0ZXJzWyBjb252IF07XG5cdFx0fVxuXHR9XG5cblx0Y3VycmVudCA9IGRhdGFUeXBlcy5zaGlmdCgpO1xuXG5cdC8vIENvbnZlcnQgdG8gZWFjaCBzZXF1ZW50aWFsIGRhdGFUeXBlXG5cdHdoaWxlICggY3VycmVudCApIHtcblxuXHRcdGlmICggcy5yZXNwb25zZUZpZWxkc1sgY3VycmVudCBdICkge1xuXHRcdFx0anFYSFJbIHMucmVzcG9uc2VGaWVsZHNbIGN1cnJlbnQgXSBdID0gcmVzcG9uc2U7XG5cdFx0fVxuXG5cdFx0Ly8gQXBwbHkgdGhlIGRhdGFGaWx0ZXIgaWYgcHJvdmlkZWRcblx0XHRpZiAoICFwcmV2ICYmIGlzU3VjY2VzcyAmJiBzLmRhdGFGaWx0ZXIgKSB7XG5cdFx0XHRyZXNwb25zZSA9IHMuZGF0YUZpbHRlciggcmVzcG9uc2UsIHMuZGF0YVR5cGUgKTtcblx0XHR9XG5cblx0XHRwcmV2ID0gY3VycmVudDtcblx0XHRjdXJyZW50ID0gZGF0YVR5cGVzLnNoaWZ0KCk7XG5cblx0XHRpZiAoIGN1cnJlbnQgKSB7XG5cblx0XHQvLyBUaGVyZSdzIG9ubHkgd29yayB0byBkbyBpZiBjdXJyZW50IGRhdGFUeXBlIGlzIG5vbi1hdXRvXG5cdFx0XHRpZiAoIGN1cnJlbnQgPT09IFwiKlwiICkge1xuXG5cdFx0XHRcdGN1cnJlbnQgPSBwcmV2O1xuXG5cdFx0XHQvLyBDb252ZXJ0IHJlc3BvbnNlIGlmIHByZXYgZGF0YVR5cGUgaXMgbm9uLWF1dG8gYW5kIGRpZmZlcnMgZnJvbSBjdXJyZW50XG5cdFx0XHR9IGVsc2UgaWYgKCBwcmV2ICE9PSBcIipcIiAmJiBwcmV2ICE9PSBjdXJyZW50ICkge1xuXG5cdFx0XHRcdC8vIFNlZWsgYSBkaXJlY3QgY29udmVydGVyXG5cdFx0XHRcdGNvbnYgPSBjb252ZXJ0ZXJzWyBwcmV2ICsgXCIgXCIgKyBjdXJyZW50IF0gfHwgY29udmVydGVyc1sgXCIqIFwiICsgY3VycmVudCBdO1xuXG5cdFx0XHRcdC8vIElmIG5vbmUgZm91bmQsIHNlZWsgYSBwYWlyXG5cdFx0XHRcdGlmICggIWNvbnYgKSB7XG5cdFx0XHRcdFx0Zm9yICggY29udjIgaW4gY29udmVydGVycyApIHtcblxuXHRcdFx0XHRcdFx0Ly8gSWYgY29udjIgb3V0cHV0cyBjdXJyZW50XG5cdFx0XHRcdFx0XHR0bXAgPSBjb252Mi5zcGxpdCggXCIgXCIgKTtcblx0XHRcdFx0XHRcdGlmICggdG1wWyAxIF0gPT09IGN1cnJlbnQgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gSWYgcHJldiBjYW4gYmUgY29udmVydGVkIHRvIGFjY2VwdGVkIGlucHV0XG5cdFx0XHRcdFx0XHRcdGNvbnYgPSBjb252ZXJ0ZXJzWyBwcmV2ICsgXCIgXCIgKyB0bXBbIDAgXSBdIHx8XG5cdFx0XHRcdFx0XHRcdFx0Y29udmVydGVyc1sgXCIqIFwiICsgdG1wWyAwIF0gXTtcblx0XHRcdFx0XHRcdFx0aWYgKCBjb252ICkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIENvbmRlbnNlIGVxdWl2YWxlbmNlIGNvbnZlcnRlcnNcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGNvbnYgPT09IHRydWUgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb252ID0gY29udmVydGVyc1sgY29udjIgXTtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIE90aGVyd2lzZSwgaW5zZXJ0IHRoZSBpbnRlcm1lZGlhdGUgZGF0YVR5cGVcblx0XHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCBjb252ZXJ0ZXJzWyBjb252MiBdICE9PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Y3VycmVudCA9IHRtcFsgMCBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0ZGF0YVR5cGVzLnVuc2hpZnQoIHRtcFsgMSBdICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQXBwbHkgY29udmVydGVyIChpZiBub3QgYW4gZXF1aXZhbGVuY2UpXG5cdFx0XHRcdGlmICggY29udiAhPT0gdHJ1ZSApIHtcblxuXHRcdFx0XHRcdC8vIFVubGVzcyBlcnJvcnMgYXJlIGFsbG93ZWQgdG8gYnViYmxlLCBjYXRjaCBhbmQgcmV0dXJuIHRoZW1cblx0XHRcdFx0XHRpZiAoIGNvbnYgJiYgc1sgXCJ0aHJvd3NcIiBdICkge1xuXHRcdFx0XHRcdFx0cmVzcG9uc2UgPSBjb252KCByZXNwb25zZSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRyZXNwb25zZSA9IGNvbnYoIHJlc3BvbnNlICk7XG5cdFx0XHRcdFx0XHR9IGNhdGNoICggZSApIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHsgc3RhdGU6IFwicGFyc2VyZXJyb3JcIiwgZXJyb3I6IGNvbnYgPyBlIDogXCJObyBjb252ZXJzaW9uIGZyb20gXCIgKyBwcmV2ICsgXCIgdG8gXCIgKyBjdXJyZW50IH07XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHsgc3RhdGU6IFwic3VjY2Vzc1wiLCBkYXRhOiByZXNwb25zZSB9O1xufVxuXG5qUXVlcnkuZXh0ZW5kKHtcblxuXHQvLyBDb3VudGVyIGZvciBob2xkaW5nIHRoZSBudW1iZXIgb2YgYWN0aXZlIHF1ZXJpZXNcblx0YWN0aXZlOiAwLFxuXG5cdC8vIExhc3QtTW9kaWZpZWQgaGVhZGVyIGNhY2hlIGZvciBuZXh0IHJlcXVlc3Rcblx0bGFzdE1vZGlmaWVkOiB7fSxcblx0ZXRhZzoge30sXG5cblx0YWpheFNldHRpbmdzOiB7XG5cdFx0dXJsOiBhamF4TG9jYXRpb24sXG5cdFx0dHlwZTogXCJHRVRcIixcblx0XHRpc0xvY2FsOiBybG9jYWxQcm90b2NvbC50ZXN0KCBhamF4TG9jUGFydHNbIDEgXSApLFxuXHRcdGdsb2JhbDogdHJ1ZSxcblx0XHRwcm9jZXNzRGF0YTogdHJ1ZSxcblx0XHRhc3luYzogdHJ1ZSxcblx0XHRjb250ZW50VHlwZTogXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9VVRGLThcIixcblx0XHQvKlxuXHRcdHRpbWVvdXQ6IDAsXG5cdFx0ZGF0YTogbnVsbCxcblx0XHRkYXRhVHlwZTogbnVsbCxcblx0XHR1c2VybmFtZTogbnVsbCxcblx0XHRwYXNzd29yZDogbnVsbCxcblx0XHRjYWNoZTogbnVsbCxcblx0XHR0aHJvd3M6IGZhbHNlLFxuXHRcdHRyYWRpdGlvbmFsOiBmYWxzZSxcblx0XHRoZWFkZXJzOiB7fSxcblx0XHQqL1xuXG5cdFx0YWNjZXB0czoge1xuXHRcdFx0XCIqXCI6IGFsbFR5cGVzLFxuXHRcdFx0dGV4dDogXCJ0ZXh0L3BsYWluXCIsXG5cdFx0XHRodG1sOiBcInRleHQvaHRtbFwiLFxuXHRcdFx0eG1sOiBcImFwcGxpY2F0aW9uL3htbCwgdGV4dC94bWxcIixcblx0XHRcdGpzb246IFwiYXBwbGljYXRpb24vanNvbiwgdGV4dC9qYXZhc2NyaXB0XCJcblx0XHR9LFxuXG5cdFx0Y29udGVudHM6IHtcblx0XHRcdHhtbDogL3htbC8sXG5cdFx0XHRodG1sOiAvaHRtbC8sXG5cdFx0XHRqc29uOiAvanNvbi9cblx0XHR9LFxuXG5cdFx0cmVzcG9uc2VGaWVsZHM6IHtcblx0XHRcdHhtbDogXCJyZXNwb25zZVhNTFwiLFxuXHRcdFx0dGV4dDogXCJyZXNwb25zZVRleHRcIixcblx0XHRcdGpzb246IFwicmVzcG9uc2VKU09OXCJcblx0XHR9LFxuXG5cdFx0Ly8gRGF0YSBjb252ZXJ0ZXJzXG5cdFx0Ly8gS2V5cyBzZXBhcmF0ZSBzb3VyY2UgKG9yIGNhdGNoYWxsIFwiKlwiKSBhbmQgZGVzdGluYXRpb24gdHlwZXMgd2l0aCBhIHNpbmdsZSBzcGFjZVxuXHRcdGNvbnZlcnRlcnM6IHtcblxuXHRcdFx0Ly8gQ29udmVydCBhbnl0aGluZyB0byB0ZXh0XG5cdFx0XHRcIiogdGV4dFwiOiBTdHJpbmcsXG5cblx0XHRcdC8vIFRleHQgdG8gaHRtbCAodHJ1ZSA9IG5vIHRyYW5zZm9ybWF0aW9uKVxuXHRcdFx0XCJ0ZXh0IGh0bWxcIjogdHJ1ZSxcblxuXHRcdFx0Ly8gRXZhbHVhdGUgdGV4dCBhcyBhIGpzb24gZXhwcmVzc2lvblxuXHRcdFx0XCJ0ZXh0IGpzb25cIjogalF1ZXJ5LnBhcnNlSlNPTixcblxuXHRcdFx0Ly8gUGFyc2UgdGV4dCBhcyB4bWxcblx0XHRcdFwidGV4dCB4bWxcIjogalF1ZXJ5LnBhcnNlWE1MXG5cdFx0fSxcblxuXHRcdC8vIEZvciBvcHRpb25zIHRoYXQgc2hvdWxkbid0IGJlIGRlZXAgZXh0ZW5kZWQ6XG5cdFx0Ly8geW91IGNhbiBhZGQgeW91ciBvd24gY3VzdG9tIG9wdGlvbnMgaGVyZSBpZlxuXHRcdC8vIGFuZCB3aGVuIHlvdSBjcmVhdGUgb25lIHRoYXQgc2hvdWxkbid0IGJlXG5cdFx0Ly8gZGVlcCBleHRlbmRlZCAoc2VlIGFqYXhFeHRlbmQpXG5cdFx0ZmxhdE9wdGlvbnM6IHtcblx0XHRcdHVybDogdHJ1ZSxcblx0XHRcdGNvbnRleHQ6IHRydWVcblx0XHR9XG5cdH0sXG5cblx0Ly8gQ3JlYXRlcyBhIGZ1bGwgZmxlZGdlZCBzZXR0aW5ncyBvYmplY3QgaW50byB0YXJnZXRcblx0Ly8gd2l0aCBib3RoIGFqYXhTZXR0aW5ncyBhbmQgc2V0dGluZ3MgZmllbGRzLlxuXHQvLyBJZiB0YXJnZXQgaXMgb21pdHRlZCwgd3JpdGVzIGludG8gYWpheFNldHRpbmdzLlxuXHRhamF4U2V0dXA6IGZ1bmN0aW9uKCB0YXJnZXQsIHNldHRpbmdzICkge1xuXHRcdHJldHVybiBzZXR0aW5ncyA/XG5cblx0XHRcdC8vIEJ1aWxkaW5nIGEgc2V0dGluZ3Mgb2JqZWN0XG5cdFx0XHRhamF4RXh0ZW5kKCBhamF4RXh0ZW5kKCB0YXJnZXQsIGpRdWVyeS5hamF4U2V0dGluZ3MgKSwgc2V0dGluZ3MgKSA6XG5cblx0XHRcdC8vIEV4dGVuZGluZyBhamF4U2V0dGluZ3Ncblx0XHRcdGFqYXhFeHRlbmQoIGpRdWVyeS5hamF4U2V0dGluZ3MsIHRhcmdldCApO1xuXHR9LFxuXG5cdGFqYXhQcmVmaWx0ZXI6IGFkZFRvUHJlZmlsdGVyc09yVHJhbnNwb3J0cyggcHJlZmlsdGVycyApLFxuXHRhamF4VHJhbnNwb3J0OiBhZGRUb1ByZWZpbHRlcnNPclRyYW5zcG9ydHMoIHRyYW5zcG9ydHMgKSxcblxuXHQvLyBNYWluIG1ldGhvZFxuXHRhamF4OiBmdW5jdGlvbiggdXJsLCBvcHRpb25zICkge1xuXG5cdFx0Ly8gSWYgdXJsIGlzIGFuIG9iamVjdCwgc2ltdWxhdGUgcHJlLTEuNSBzaWduYXR1cmVcblx0XHRpZiAoIHR5cGVvZiB1cmwgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0XHRvcHRpb25zID0gdXJsO1xuXHRcdFx0dXJsID0gdW5kZWZpbmVkO1xuXHRcdH1cblxuXHRcdC8vIEZvcmNlIG9wdGlvbnMgdG8gYmUgYW4gb2JqZWN0XG5cdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblx0XHR2YXIgdHJhbnNwb3J0LFxuXHRcdFx0Ly8gVVJMIHdpdGhvdXQgYW50aS1jYWNoZSBwYXJhbVxuXHRcdFx0Y2FjaGVVUkwsXG5cdFx0XHQvLyBSZXNwb25zZSBoZWFkZXJzXG5cdFx0XHRyZXNwb25zZUhlYWRlcnNTdHJpbmcsXG5cdFx0XHRyZXNwb25zZUhlYWRlcnMsXG5cdFx0XHQvLyB0aW1lb3V0IGhhbmRsZVxuXHRcdFx0dGltZW91dFRpbWVyLFxuXHRcdFx0Ly8gQ3Jvc3MtZG9tYWluIGRldGVjdGlvbiB2YXJzXG5cdFx0XHRwYXJ0cyxcblx0XHRcdC8vIFRvIGtub3cgaWYgZ2xvYmFsIGV2ZW50cyBhcmUgdG8gYmUgZGlzcGF0Y2hlZFxuXHRcdFx0ZmlyZUdsb2JhbHMsXG5cdFx0XHQvLyBMb29wIHZhcmlhYmxlXG5cdFx0XHRpLFxuXHRcdFx0Ly8gQ3JlYXRlIHRoZSBmaW5hbCBvcHRpb25zIG9iamVjdFxuXHRcdFx0cyA9IGpRdWVyeS5hamF4U2V0dXAoIHt9LCBvcHRpb25zICksXG5cdFx0XHQvLyBDYWxsYmFja3MgY29udGV4dFxuXHRcdFx0Y2FsbGJhY2tDb250ZXh0ID0gcy5jb250ZXh0IHx8IHMsXG5cdFx0XHQvLyBDb250ZXh0IGZvciBnbG9iYWwgZXZlbnRzIGlzIGNhbGxiYWNrQ29udGV4dCBpZiBpdCBpcyBhIERPTSBub2RlIG9yIGpRdWVyeSBjb2xsZWN0aW9uXG5cdFx0XHRnbG9iYWxFdmVudENvbnRleHQgPSBzLmNvbnRleHQgJiYgKCBjYWxsYmFja0NvbnRleHQubm9kZVR5cGUgfHwgY2FsbGJhY2tDb250ZXh0LmpxdWVyeSApID9cblx0XHRcdFx0alF1ZXJ5KCBjYWxsYmFja0NvbnRleHQgKSA6XG5cdFx0XHRcdGpRdWVyeS5ldmVudCxcblx0XHRcdC8vIERlZmVycmVkc1xuXHRcdFx0ZGVmZXJyZWQgPSBqUXVlcnkuRGVmZXJyZWQoKSxcblx0XHRcdGNvbXBsZXRlRGVmZXJyZWQgPSBqUXVlcnkuQ2FsbGJhY2tzKFwib25jZSBtZW1vcnlcIiksXG5cdFx0XHQvLyBTdGF0dXMtZGVwZW5kZW50IGNhbGxiYWNrc1xuXHRcdFx0c3RhdHVzQ29kZSA9IHMuc3RhdHVzQ29kZSB8fCB7fSxcblx0XHRcdC8vIEhlYWRlcnMgKHRoZXkgYXJlIHNlbnQgYWxsIGF0IG9uY2UpXG5cdFx0XHRyZXF1ZXN0SGVhZGVycyA9IHt9LFxuXHRcdFx0cmVxdWVzdEhlYWRlcnNOYW1lcyA9IHt9LFxuXHRcdFx0Ly8gVGhlIGpxWEhSIHN0YXRlXG5cdFx0XHRzdGF0ZSA9IDAsXG5cdFx0XHQvLyBEZWZhdWx0IGFib3J0IG1lc3NhZ2Vcblx0XHRcdHN0ckFib3J0ID0gXCJjYW5jZWxlZFwiLFxuXHRcdFx0Ly8gRmFrZSB4aHJcblx0XHRcdGpxWEhSID0ge1xuXHRcdFx0XHRyZWFkeVN0YXRlOiAwLFxuXG5cdFx0XHRcdC8vIEJ1aWxkcyBoZWFkZXJzIGhhc2h0YWJsZSBpZiBuZWVkZWRcblx0XHRcdFx0Z2V0UmVzcG9uc2VIZWFkZXI6IGZ1bmN0aW9uKCBrZXkgKSB7XG5cdFx0XHRcdFx0dmFyIG1hdGNoO1xuXHRcdFx0XHRcdGlmICggc3RhdGUgPT09IDIgKSB7XG5cdFx0XHRcdFx0XHRpZiAoICFyZXNwb25zZUhlYWRlcnMgKSB7XG5cdFx0XHRcdFx0XHRcdHJlc3BvbnNlSGVhZGVycyA9IHt9O1xuXHRcdFx0XHRcdFx0XHR3aGlsZSAoIChtYXRjaCA9IHJoZWFkZXJzLmV4ZWMoIHJlc3BvbnNlSGVhZGVyc1N0cmluZyApKSApIHtcblx0XHRcdFx0XHRcdFx0XHRyZXNwb25zZUhlYWRlcnNbIG1hdGNoWzFdLnRvTG93ZXJDYXNlKCkgXSA9IG1hdGNoWyAyIF07XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdG1hdGNoID0gcmVzcG9uc2VIZWFkZXJzWyBrZXkudG9Mb3dlckNhc2UoKSBdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gbWF0Y2ggPT0gbnVsbCA/IG51bGwgOiBtYXRjaDtcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBSYXcgc3RyaW5nXG5cdFx0XHRcdGdldEFsbFJlc3BvbnNlSGVhZGVyczogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHN0YXRlID09PSAyID8gcmVzcG9uc2VIZWFkZXJzU3RyaW5nIDogbnVsbDtcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBDYWNoZXMgdGhlIGhlYWRlclxuXHRcdFx0XHRzZXRSZXF1ZXN0SGVhZGVyOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0XHRcdFx0dmFyIGxuYW1lID0gbmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0XHRcdGlmICggIXN0YXRlICkge1xuXHRcdFx0XHRcdFx0bmFtZSA9IHJlcXVlc3RIZWFkZXJzTmFtZXNbIGxuYW1lIF0gPSByZXF1ZXN0SGVhZGVyc05hbWVzWyBsbmFtZSBdIHx8IG5hbWU7XG5cdFx0XHRcdFx0XHRyZXF1ZXN0SGVhZGVyc1sgbmFtZSBdID0gdmFsdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIE92ZXJyaWRlcyByZXNwb25zZSBjb250ZW50LXR5cGUgaGVhZGVyXG5cdFx0XHRcdG92ZXJyaWRlTWltZVR5cGU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdFx0XHRcdGlmICggIXN0YXRlICkge1xuXHRcdFx0XHRcdFx0cy5taW1lVHlwZSA9IHR5cGU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRcdHN0YXR1c0NvZGU6IGZ1bmN0aW9uKCBtYXAgKSB7XG5cdFx0XHRcdFx0dmFyIGNvZGU7XG5cdFx0XHRcdFx0aWYgKCBtYXAgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIHN0YXRlIDwgMiApIHtcblx0XHRcdFx0XHRcdFx0Zm9yICggY29kZSBpbiBtYXAgKSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gTGF6eS1hZGQgdGhlIG5ldyBjYWxsYmFjayBpbiBhIHdheSB0aGF0IHByZXNlcnZlcyBvbGQgb25lc1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1c0NvZGVbIGNvZGUgXSA9IFsgc3RhdHVzQ29kZVsgY29kZSBdLCBtYXBbIGNvZGUgXSBdO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQvLyBFeGVjdXRlIHRoZSBhcHByb3ByaWF0ZSBjYWxsYmFja3Ncblx0XHRcdFx0XHRcdFx0anFYSFIuYWx3YXlzKCBtYXBbIGpxWEhSLnN0YXR1cyBdICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIENhbmNlbCB0aGUgcmVxdWVzdFxuXHRcdFx0XHRhYm9ydDogZnVuY3Rpb24oIHN0YXR1c1RleHQgKSB7XG5cdFx0XHRcdFx0dmFyIGZpbmFsVGV4dCA9IHN0YXR1c1RleHQgfHwgc3RyQWJvcnQ7XG5cdFx0XHRcdFx0aWYgKCB0cmFuc3BvcnQgKSB7XG5cdFx0XHRcdFx0XHR0cmFuc3BvcnQuYWJvcnQoIGZpbmFsVGV4dCApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRkb25lKCAwLCBmaW5hbFRleHQgKTtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fVxuXHRcdFx0fTtcblxuXHRcdC8vIEF0dGFjaCBkZWZlcnJlZHNcblx0XHRkZWZlcnJlZC5wcm9taXNlKCBqcVhIUiApLmNvbXBsZXRlID0gY29tcGxldGVEZWZlcnJlZC5hZGQ7XG5cdFx0anFYSFIuc3VjY2VzcyA9IGpxWEhSLmRvbmU7XG5cdFx0anFYSFIuZXJyb3IgPSBqcVhIUi5mYWlsO1xuXG5cdFx0Ly8gUmVtb3ZlIGhhc2ggY2hhcmFjdGVyICgjNzUzMTogYW5kIHN0cmluZyBwcm9tb3Rpb24pXG5cdFx0Ly8gQWRkIHByb3RvY29sIGlmIG5vdCBwcm92aWRlZCAocHJlZmlsdGVycyBtaWdodCBleHBlY3QgaXQpXG5cdFx0Ly8gSGFuZGxlIGZhbHN5IHVybCBpbiB0aGUgc2V0dGluZ3Mgb2JqZWN0ICgjMTAwOTM6IGNvbnNpc3RlbmN5IHdpdGggb2xkIHNpZ25hdHVyZSlcblx0XHQvLyBXZSBhbHNvIHVzZSB0aGUgdXJsIHBhcmFtZXRlciBpZiBhdmFpbGFibGVcblx0XHRzLnVybCA9ICggKCB1cmwgfHwgcy51cmwgfHwgYWpheExvY2F0aW9uICkgKyBcIlwiICkucmVwbGFjZSggcmhhc2gsIFwiXCIgKVxuXHRcdFx0LnJlcGxhY2UoIHJwcm90b2NvbCwgYWpheExvY1BhcnRzWyAxIF0gKyBcIi8vXCIgKTtcblxuXHRcdC8vIEFsaWFzIG1ldGhvZCBvcHRpb24gdG8gdHlwZSBhcyBwZXIgdGlja2V0ICMxMjAwNFxuXHRcdHMudHlwZSA9IG9wdGlvbnMubWV0aG9kIHx8IG9wdGlvbnMudHlwZSB8fCBzLm1ldGhvZCB8fCBzLnR5cGU7XG5cblx0XHQvLyBFeHRyYWN0IGRhdGFUeXBlcyBsaXN0XG5cdFx0cy5kYXRhVHlwZXMgPSBqUXVlcnkudHJpbSggcy5kYXRhVHlwZSB8fCBcIipcIiApLnRvTG93ZXJDYXNlKCkubWF0Y2goIHJub3R3aGl0ZSApIHx8IFsgXCJcIiBdO1xuXG5cdFx0Ly8gQSBjcm9zcy1kb21haW4gcmVxdWVzdCBpcyBpbiBvcmRlciB3aGVuIHdlIGhhdmUgYSBwcm90b2NvbDpob3N0OnBvcnQgbWlzbWF0Y2hcblx0XHRpZiAoIHMuY3Jvc3NEb21haW4gPT0gbnVsbCApIHtcblx0XHRcdHBhcnRzID0gcnVybC5leGVjKCBzLnVybC50b0xvd2VyQ2FzZSgpICk7XG5cdFx0XHRzLmNyb3NzRG9tYWluID0gISEoIHBhcnRzICYmXG5cdFx0XHRcdCggcGFydHNbIDEgXSAhPT0gYWpheExvY1BhcnRzWyAxIF0gfHwgcGFydHNbIDIgXSAhPT0gYWpheExvY1BhcnRzWyAyIF0gfHxcblx0XHRcdFx0XHQoIHBhcnRzWyAzIF0gfHwgKCBwYXJ0c1sgMSBdID09PSBcImh0dHA6XCIgPyBcIjgwXCIgOiBcIjQ0M1wiICkgKSAhPT1cblx0XHRcdFx0XHRcdCggYWpheExvY1BhcnRzWyAzIF0gfHwgKCBhamF4TG9jUGFydHNbIDEgXSA9PT0gXCJodHRwOlwiID8gXCI4MFwiIDogXCI0NDNcIiApICkgKVxuXHRcdFx0KTtcblx0XHR9XG5cblx0XHQvLyBDb252ZXJ0IGRhdGEgaWYgbm90IGFscmVhZHkgYSBzdHJpbmdcblx0XHRpZiAoIHMuZGF0YSAmJiBzLnByb2Nlc3NEYXRhICYmIHR5cGVvZiBzLmRhdGEgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRzLmRhdGEgPSBqUXVlcnkucGFyYW0oIHMuZGF0YSwgcy50cmFkaXRpb25hbCApO1xuXHRcdH1cblxuXHRcdC8vIEFwcGx5IHByZWZpbHRlcnNcblx0XHRpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggcHJlZmlsdGVycywgcywgb3B0aW9ucywganFYSFIgKTtcblxuXHRcdC8vIElmIHJlcXVlc3Qgd2FzIGFib3J0ZWQgaW5zaWRlIGEgcHJlZmlsdGVyLCBzdG9wIHRoZXJlXG5cdFx0aWYgKCBzdGF0ZSA9PT0gMiApIHtcblx0XHRcdHJldHVybiBqcVhIUjtcblx0XHR9XG5cblx0XHQvLyBXZSBjYW4gZmlyZSBnbG9iYWwgZXZlbnRzIGFzIG9mIG5vdyBpZiBhc2tlZCB0b1xuXHRcdC8vIERvbid0IGZpcmUgZXZlbnRzIGlmIGpRdWVyeS5ldmVudCBpcyB1bmRlZmluZWQgaW4gYW4gQU1ELXVzYWdlIHNjZW5hcmlvICgjMTUxMTgpXG5cdFx0ZmlyZUdsb2JhbHMgPSBqUXVlcnkuZXZlbnQgJiYgcy5nbG9iYWw7XG5cblx0XHQvLyBXYXRjaCBmb3IgYSBuZXcgc2V0IG9mIHJlcXVlc3RzXG5cdFx0aWYgKCBmaXJlR2xvYmFscyAmJiBqUXVlcnkuYWN0aXZlKysgPT09IDAgKSB7XG5cdFx0XHRqUXVlcnkuZXZlbnQudHJpZ2dlcihcImFqYXhTdGFydFwiKTtcblx0XHR9XG5cblx0XHQvLyBVcHBlcmNhc2UgdGhlIHR5cGVcblx0XHRzLnR5cGUgPSBzLnR5cGUudG9VcHBlckNhc2UoKTtcblxuXHRcdC8vIERldGVybWluZSBpZiByZXF1ZXN0IGhhcyBjb250ZW50XG5cdFx0cy5oYXNDb250ZW50ID0gIXJub0NvbnRlbnQudGVzdCggcy50eXBlICk7XG5cblx0XHQvLyBTYXZlIHRoZSBVUkwgaW4gY2FzZSB3ZSdyZSB0b3lpbmcgd2l0aCB0aGUgSWYtTW9kaWZpZWQtU2luY2Vcblx0XHQvLyBhbmQvb3IgSWYtTm9uZS1NYXRjaCBoZWFkZXIgbGF0ZXIgb25cblx0XHRjYWNoZVVSTCA9IHMudXJsO1xuXG5cdFx0Ly8gTW9yZSBvcHRpb25zIGhhbmRsaW5nIGZvciByZXF1ZXN0cyB3aXRoIG5vIGNvbnRlbnRcblx0XHRpZiAoICFzLmhhc0NvbnRlbnQgKSB7XG5cblx0XHRcdC8vIElmIGRhdGEgaXMgYXZhaWxhYmxlLCBhcHBlbmQgZGF0YSB0byB1cmxcblx0XHRcdGlmICggcy5kYXRhICkge1xuXHRcdFx0XHRjYWNoZVVSTCA9ICggcy51cmwgKz0gKCBycXVlcnkudGVzdCggY2FjaGVVUkwgKSA/IFwiJlwiIDogXCI/XCIgKSArIHMuZGF0YSApO1xuXHRcdFx0XHQvLyAjOTY4MjogcmVtb3ZlIGRhdGEgc28gdGhhdCBpdCdzIG5vdCB1c2VkIGluIGFuIGV2ZW50dWFsIHJldHJ5XG5cdFx0XHRcdGRlbGV0ZSBzLmRhdGE7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEFkZCBhbnRpLWNhY2hlIGluIHVybCBpZiBuZWVkZWRcblx0XHRcdGlmICggcy5jYWNoZSA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdHMudXJsID0gcnRzLnRlc3QoIGNhY2hlVVJMICkgP1xuXG5cdFx0XHRcdFx0Ly8gSWYgdGhlcmUgaXMgYWxyZWFkeSBhICdfJyBwYXJhbWV0ZXIsIHNldCBpdHMgdmFsdWVcblx0XHRcdFx0XHRjYWNoZVVSTC5yZXBsYWNlKCBydHMsIFwiJDFfPVwiICsgbm9uY2UrKyApIDpcblxuXHRcdFx0XHRcdC8vIE90aGVyd2lzZSBhZGQgb25lIHRvIHRoZSBlbmRcblx0XHRcdFx0XHRjYWNoZVVSTCArICggcnF1ZXJ5LnRlc3QoIGNhY2hlVVJMICkgPyBcIiZcIiA6IFwiP1wiICkgKyBcIl89XCIgKyBub25jZSsrO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFNldCB0aGUgSWYtTW9kaWZpZWQtU2luY2UgYW5kL29yIElmLU5vbmUtTWF0Y2ggaGVhZGVyLCBpZiBpbiBpZk1vZGlmaWVkIG1vZGUuXG5cdFx0aWYgKCBzLmlmTW9kaWZpZWQgKSB7XG5cdFx0XHRpZiAoIGpRdWVyeS5sYXN0TW9kaWZpZWRbIGNhY2hlVVJMIF0gKSB7XG5cdFx0XHRcdGpxWEhSLnNldFJlcXVlc3RIZWFkZXIoIFwiSWYtTW9kaWZpZWQtU2luY2VcIiwgalF1ZXJ5Lmxhc3RNb2RpZmllZFsgY2FjaGVVUkwgXSApO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCBqUXVlcnkuZXRhZ1sgY2FjaGVVUkwgXSApIHtcblx0XHRcdFx0anFYSFIuc2V0UmVxdWVzdEhlYWRlciggXCJJZi1Ob25lLU1hdGNoXCIsIGpRdWVyeS5ldGFnWyBjYWNoZVVSTCBdICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gU2V0IHRoZSBjb3JyZWN0IGhlYWRlciwgaWYgZGF0YSBpcyBiZWluZyBzZW50XG5cdFx0aWYgKCBzLmRhdGEgJiYgcy5oYXNDb250ZW50ICYmIHMuY29udGVudFR5cGUgIT09IGZhbHNlIHx8IG9wdGlvbnMuY29udGVudFR5cGUgKSB7XG5cdFx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKCBcIkNvbnRlbnQtVHlwZVwiLCBzLmNvbnRlbnRUeXBlICk7XG5cdFx0fVxuXG5cdFx0Ly8gU2V0IHRoZSBBY2NlcHRzIGhlYWRlciBmb3IgdGhlIHNlcnZlciwgZGVwZW5kaW5nIG9uIHRoZSBkYXRhVHlwZVxuXHRcdGpxWEhSLnNldFJlcXVlc3RIZWFkZXIoXG5cdFx0XHRcIkFjY2VwdFwiLFxuXHRcdFx0cy5kYXRhVHlwZXNbIDAgXSAmJiBzLmFjY2VwdHNbIHMuZGF0YVR5cGVzWzBdIF0gP1xuXHRcdFx0XHRzLmFjY2VwdHNbIHMuZGF0YVR5cGVzWzBdIF0gKyAoIHMuZGF0YVR5cGVzWyAwIF0gIT09IFwiKlwiID8gXCIsIFwiICsgYWxsVHlwZXMgKyBcIjsgcT0wLjAxXCIgOiBcIlwiICkgOlxuXHRcdFx0XHRzLmFjY2VwdHNbIFwiKlwiIF1cblx0XHQpO1xuXG5cdFx0Ly8gQ2hlY2sgZm9yIGhlYWRlcnMgb3B0aW9uXG5cdFx0Zm9yICggaSBpbiBzLmhlYWRlcnMgKSB7XG5cdFx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKCBpLCBzLmhlYWRlcnNbIGkgXSApO1xuXHRcdH1cblxuXHRcdC8vIEFsbG93IGN1c3RvbSBoZWFkZXJzL21pbWV0eXBlcyBhbmQgZWFybHkgYWJvcnRcblx0XHRpZiAoIHMuYmVmb3JlU2VuZCAmJiAoIHMuYmVmb3JlU2VuZC5jYWxsKCBjYWxsYmFja0NvbnRleHQsIGpxWEhSLCBzICkgPT09IGZhbHNlIHx8IHN0YXRlID09PSAyICkgKSB7XG5cdFx0XHQvLyBBYm9ydCBpZiBub3QgZG9uZSBhbHJlYWR5IGFuZCByZXR1cm5cblx0XHRcdHJldHVybiBqcVhIUi5hYm9ydCgpO1xuXHRcdH1cblxuXHRcdC8vIEFib3J0aW5nIGlzIG5vIGxvbmdlciBhIGNhbmNlbGxhdGlvblxuXHRcdHN0ckFib3J0ID0gXCJhYm9ydFwiO1xuXG5cdFx0Ly8gSW5zdGFsbCBjYWxsYmFja3Mgb24gZGVmZXJyZWRzXG5cdFx0Zm9yICggaSBpbiB7IHN1Y2Nlc3M6IDEsIGVycm9yOiAxLCBjb21wbGV0ZTogMSB9ICkge1xuXHRcdFx0anFYSFJbIGkgXSggc1sgaSBdICk7XG5cdFx0fVxuXG5cdFx0Ly8gR2V0IHRyYW5zcG9ydFxuXHRcdHRyYW5zcG9ydCA9IGluc3BlY3RQcmVmaWx0ZXJzT3JUcmFuc3BvcnRzKCB0cmFuc3BvcnRzLCBzLCBvcHRpb25zLCBqcVhIUiApO1xuXG5cdFx0Ly8gSWYgbm8gdHJhbnNwb3J0LCB3ZSBhdXRvLWFib3J0XG5cdFx0aWYgKCAhdHJhbnNwb3J0ICkge1xuXHRcdFx0ZG9uZSggLTEsIFwiTm8gVHJhbnNwb3J0XCIgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0anFYSFIucmVhZHlTdGF0ZSA9IDE7XG5cblx0XHRcdC8vIFNlbmQgZ2xvYmFsIGV2ZW50XG5cdFx0XHRpZiAoIGZpcmVHbG9iYWxzICkge1xuXHRcdFx0XHRnbG9iYWxFdmVudENvbnRleHQudHJpZ2dlciggXCJhamF4U2VuZFwiLCBbIGpxWEhSLCBzIF0gKTtcblx0XHRcdH1cblx0XHRcdC8vIFRpbWVvdXRcblx0XHRcdGlmICggcy5hc3luYyAmJiBzLnRpbWVvdXQgPiAwICkge1xuXHRcdFx0XHR0aW1lb3V0VGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGpxWEhSLmFib3J0KFwidGltZW91dFwiKTtcblx0XHRcdFx0fSwgcy50aW1lb3V0ICk7XG5cdFx0XHR9XG5cblx0XHRcdHRyeSB7XG5cdFx0XHRcdHN0YXRlID0gMTtcblx0XHRcdFx0dHJhbnNwb3J0LnNlbmQoIHJlcXVlc3RIZWFkZXJzLCBkb25lICk7XG5cdFx0XHR9IGNhdGNoICggZSApIHtcblx0XHRcdFx0Ly8gUHJvcGFnYXRlIGV4Y2VwdGlvbiBhcyBlcnJvciBpZiBub3QgZG9uZVxuXHRcdFx0XHRpZiAoIHN0YXRlIDwgMiApIHtcblx0XHRcdFx0XHRkb25lKCAtMSwgZSApO1xuXHRcdFx0XHQvLyBTaW1wbHkgcmV0aHJvdyBvdGhlcndpc2Vcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aHJvdyBlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbGJhY2sgZm9yIHdoZW4gZXZlcnl0aGluZyBpcyBkb25lXG5cdFx0ZnVuY3Rpb24gZG9uZSggc3RhdHVzLCBuYXRpdmVTdGF0dXNUZXh0LCByZXNwb25zZXMsIGhlYWRlcnMgKSB7XG5cdFx0XHR2YXIgaXNTdWNjZXNzLCBzdWNjZXNzLCBlcnJvciwgcmVzcG9uc2UsIG1vZGlmaWVkLFxuXHRcdFx0XHRzdGF0dXNUZXh0ID0gbmF0aXZlU3RhdHVzVGV4dDtcblxuXHRcdFx0Ly8gQ2FsbGVkIG9uY2Vcblx0XHRcdGlmICggc3RhdGUgPT09IDIgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3RhdGUgaXMgXCJkb25lXCIgbm93XG5cdFx0XHRzdGF0ZSA9IDI7XG5cblx0XHRcdC8vIENsZWFyIHRpbWVvdXQgaWYgaXQgZXhpc3RzXG5cdFx0XHRpZiAoIHRpbWVvdXRUaW1lciApIHtcblx0XHRcdFx0Y2xlYXJUaW1lb3V0KCB0aW1lb3V0VGltZXIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRGVyZWZlcmVuY2UgdHJhbnNwb3J0IGZvciBlYXJseSBnYXJiYWdlIGNvbGxlY3Rpb25cblx0XHRcdC8vIChubyBtYXR0ZXIgaG93IGxvbmcgdGhlIGpxWEhSIG9iamVjdCB3aWxsIGJlIHVzZWQpXG5cdFx0XHR0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG5cblx0XHRcdC8vIENhY2hlIHJlc3BvbnNlIGhlYWRlcnNcblx0XHRcdHJlc3BvbnNlSGVhZGVyc1N0cmluZyA9IGhlYWRlcnMgfHwgXCJcIjtcblxuXHRcdFx0Ly8gU2V0IHJlYWR5U3RhdGVcblx0XHRcdGpxWEhSLnJlYWR5U3RhdGUgPSBzdGF0dXMgPiAwID8gNCA6IDA7XG5cblx0XHRcdC8vIERldGVybWluZSBpZiBzdWNjZXNzZnVsXG5cdFx0XHRpc1N1Y2Nlc3MgPSBzdGF0dXMgPj0gMjAwICYmIHN0YXR1cyA8IDMwMCB8fCBzdGF0dXMgPT09IDMwNDtcblxuXHRcdFx0Ly8gR2V0IHJlc3BvbnNlIGRhdGFcblx0XHRcdGlmICggcmVzcG9uc2VzICkge1xuXHRcdFx0XHRyZXNwb25zZSA9IGFqYXhIYW5kbGVSZXNwb25zZXMoIHMsIGpxWEhSLCByZXNwb25zZXMgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ29udmVydCBubyBtYXR0ZXIgd2hhdCAodGhhdCB3YXkgcmVzcG9uc2VYWFggZmllbGRzIGFyZSBhbHdheXMgc2V0KVxuXHRcdFx0cmVzcG9uc2UgPSBhamF4Q29udmVydCggcywgcmVzcG9uc2UsIGpxWEhSLCBpc1N1Y2Nlc3MgKTtcblxuXHRcdFx0Ly8gSWYgc3VjY2Vzc2Z1bCwgaGFuZGxlIHR5cGUgY2hhaW5pbmdcblx0XHRcdGlmICggaXNTdWNjZXNzICkge1xuXG5cdFx0XHRcdC8vIFNldCB0aGUgSWYtTW9kaWZpZWQtU2luY2UgYW5kL29yIElmLU5vbmUtTWF0Y2ggaGVhZGVyLCBpZiBpbiBpZk1vZGlmaWVkIG1vZGUuXG5cdFx0XHRcdGlmICggcy5pZk1vZGlmaWVkICkge1xuXHRcdFx0XHRcdG1vZGlmaWVkID0ganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoXCJMYXN0LU1vZGlmaWVkXCIpO1xuXHRcdFx0XHRcdGlmICggbW9kaWZpZWQgKSB7XG5cdFx0XHRcdFx0XHRqUXVlcnkubGFzdE1vZGlmaWVkWyBjYWNoZVVSTCBdID0gbW9kaWZpZWQ7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdG1vZGlmaWVkID0ganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoXCJldGFnXCIpO1xuXHRcdFx0XHRcdGlmICggbW9kaWZpZWQgKSB7XG5cdFx0XHRcdFx0XHRqUXVlcnkuZXRhZ1sgY2FjaGVVUkwgXSA9IG1vZGlmaWVkO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIGlmIG5vIGNvbnRlbnRcblx0XHRcdFx0aWYgKCBzdGF0dXMgPT09IDIwNCB8fCBzLnR5cGUgPT09IFwiSEVBRFwiICkge1xuXHRcdFx0XHRcdHN0YXR1c1RleHQgPSBcIm5vY29udGVudFwiO1xuXG5cdFx0XHRcdC8vIGlmIG5vdCBtb2RpZmllZFxuXHRcdFx0XHR9IGVsc2UgaWYgKCBzdGF0dXMgPT09IDMwNCApIHtcblx0XHRcdFx0XHRzdGF0dXNUZXh0ID0gXCJub3Rtb2RpZmllZFwiO1xuXG5cdFx0XHRcdC8vIElmIHdlIGhhdmUgZGF0YSwgbGV0J3MgY29udmVydCBpdFxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHN0YXR1c1RleHQgPSByZXNwb25zZS5zdGF0ZTtcblx0XHRcdFx0XHRzdWNjZXNzID0gcmVzcG9uc2UuZGF0YTtcblx0XHRcdFx0XHRlcnJvciA9IHJlc3BvbnNlLmVycm9yO1xuXHRcdFx0XHRcdGlzU3VjY2VzcyA9ICFlcnJvcjtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gRXh0cmFjdCBlcnJvciBmcm9tIHN0YXR1c1RleHQgYW5kIG5vcm1hbGl6ZSBmb3Igbm9uLWFib3J0c1xuXHRcdFx0XHRlcnJvciA9IHN0YXR1c1RleHQ7XG5cdFx0XHRcdGlmICggc3RhdHVzIHx8ICFzdGF0dXNUZXh0ICkge1xuXHRcdFx0XHRcdHN0YXR1c1RleHQgPSBcImVycm9yXCI7XG5cdFx0XHRcdFx0aWYgKCBzdGF0dXMgPCAwICkge1xuXHRcdFx0XHRcdFx0c3RhdHVzID0gMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IGRhdGEgZm9yIHRoZSBmYWtlIHhociBvYmplY3Rcblx0XHRcdGpxWEhSLnN0YXR1cyA9IHN0YXR1cztcblx0XHRcdGpxWEhSLnN0YXR1c1RleHQgPSAoIG5hdGl2ZVN0YXR1c1RleHQgfHwgc3RhdHVzVGV4dCApICsgXCJcIjtcblxuXHRcdFx0Ly8gU3VjY2Vzcy9FcnJvclxuXHRcdFx0aWYgKCBpc1N1Y2Nlc3MgKSB7XG5cdFx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBjYWxsYmFja0NvbnRleHQsIFsgc3VjY2Vzcywgc3RhdHVzVGV4dCwganFYSFIgXSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZGVmZXJyZWQucmVqZWN0V2l0aCggY2FsbGJhY2tDb250ZXh0LCBbIGpxWEhSLCBzdGF0dXNUZXh0LCBlcnJvciBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRqcVhIUi5zdGF0dXNDb2RlKCBzdGF0dXNDb2RlICk7XG5cdFx0XHRzdGF0dXNDb2RlID0gdW5kZWZpbmVkO1xuXG5cdFx0XHRpZiAoIGZpcmVHbG9iYWxzICkge1xuXHRcdFx0XHRnbG9iYWxFdmVudENvbnRleHQudHJpZ2dlciggaXNTdWNjZXNzID8gXCJhamF4U3VjY2Vzc1wiIDogXCJhamF4RXJyb3JcIixcblx0XHRcdFx0XHRbIGpxWEhSLCBzLCBpc1N1Y2Nlc3MgPyBzdWNjZXNzIDogZXJyb3IgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDb21wbGV0ZVxuXHRcdFx0Y29tcGxldGVEZWZlcnJlZC5maXJlV2l0aCggY2FsbGJhY2tDb250ZXh0LCBbIGpxWEhSLCBzdGF0dXNUZXh0IF0gKTtcblxuXHRcdFx0aWYgKCBmaXJlR2xvYmFscyApIHtcblx0XHRcdFx0Z2xvYmFsRXZlbnRDb250ZXh0LnRyaWdnZXIoIFwiYWpheENvbXBsZXRlXCIsIFsganFYSFIsIHMgXSApO1xuXHRcdFx0XHQvLyBIYW5kbGUgdGhlIGdsb2JhbCBBSkFYIGNvdW50ZXJcblx0XHRcdFx0aWYgKCAhKCAtLWpRdWVyeS5hY3RpdmUgKSApIHtcblx0XHRcdFx0XHRqUXVlcnkuZXZlbnQudHJpZ2dlcihcImFqYXhTdG9wXCIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGpxWEhSO1xuXHR9LFxuXG5cdGdldEpTT046IGZ1bmN0aW9uKCB1cmwsIGRhdGEsIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiBqUXVlcnkuZ2V0KCB1cmwsIGRhdGEsIGNhbGxiYWNrLCBcImpzb25cIiApO1xuXHR9LFxuXG5cdGdldFNjcmlwdDogZnVuY3Rpb24oIHVybCwgY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5nZXQoIHVybCwgdW5kZWZpbmVkLCBjYWxsYmFjaywgXCJzY3JpcHRcIiApO1xuXHR9XG59KTtcblxualF1ZXJ5LmVhY2goIFsgXCJnZXRcIiwgXCJwb3N0XCIgXSwgZnVuY3Rpb24oIGksIG1ldGhvZCApIHtcblx0alF1ZXJ5WyBtZXRob2QgXSA9IGZ1bmN0aW9uKCB1cmwsIGRhdGEsIGNhbGxiYWNrLCB0eXBlICkge1xuXHRcdC8vIFNoaWZ0IGFyZ3VtZW50cyBpZiBkYXRhIGFyZ3VtZW50IHdhcyBvbWl0dGVkXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggZGF0YSApICkge1xuXHRcdFx0dHlwZSA9IHR5cGUgfHwgY2FsbGJhY2s7XG5cdFx0XHRjYWxsYmFjayA9IGRhdGE7XG5cdFx0XHRkYXRhID0gdW5kZWZpbmVkO1xuXHRcdH1cblxuXHRcdHJldHVybiBqUXVlcnkuYWpheCh7XG5cdFx0XHR1cmw6IHVybCxcblx0XHRcdHR5cGU6IG1ldGhvZCxcblx0XHRcdGRhdGFUeXBlOiB0eXBlLFxuXHRcdFx0ZGF0YTogZGF0YSxcblx0XHRcdHN1Y2Nlc3M6IGNhbGxiYWNrXG5cdFx0fSk7XG5cdH07XG59KTtcblxuXG5qUXVlcnkuX2V2YWxVcmwgPSBmdW5jdGlvbiggdXJsICkge1xuXHRyZXR1cm4galF1ZXJ5LmFqYXgoe1xuXHRcdHVybDogdXJsLFxuXHRcdHR5cGU6IFwiR0VUXCIsXG5cdFx0ZGF0YVR5cGU6IFwic2NyaXB0XCIsXG5cdFx0YXN5bmM6IGZhbHNlLFxuXHRcdGdsb2JhbDogZmFsc2UsXG5cdFx0XCJ0aHJvd3NcIjogdHJ1ZVxuXHR9KTtcbn07XG5cblxualF1ZXJ5LmZuLmV4dGVuZCh7XG5cdHdyYXBBbGw6IGZ1bmN0aW9uKCBodG1sICkge1xuXHRcdHZhciB3cmFwO1xuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggaHRtbCApICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiggaSApIHtcblx0XHRcdFx0alF1ZXJ5KCB0aGlzICkud3JhcEFsbCggaHRtbC5jYWxsKHRoaXMsIGkpICk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXNbIDAgXSApIHtcblxuXHRcdFx0Ly8gVGhlIGVsZW1lbnRzIHRvIHdyYXAgdGhlIHRhcmdldCBhcm91bmRcblx0XHRcdHdyYXAgPSBqUXVlcnkoIGh0bWwsIHRoaXNbIDAgXS5vd25lckRvY3VtZW50ICkuZXEoIDAgKS5jbG9uZSggdHJ1ZSApO1xuXG5cdFx0XHRpZiAoIHRoaXNbIDAgXS5wYXJlbnROb2RlICkge1xuXHRcdFx0XHR3cmFwLmluc2VydEJlZm9yZSggdGhpc1sgMCBdICk7XG5cdFx0XHR9XG5cblx0XHRcdHdyYXAubWFwKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR2YXIgZWxlbSA9IHRoaXM7XG5cblx0XHRcdFx0d2hpbGUgKCBlbGVtLmZpcnN0RWxlbWVudENoaWxkICkge1xuXHRcdFx0XHRcdGVsZW0gPSBlbGVtLmZpcnN0RWxlbWVudENoaWxkO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIGVsZW07XG5cdFx0XHR9KS5hcHBlbmQoIHRoaXMgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHR3cmFwSW5uZXI6IGZ1bmN0aW9uKCBodG1sICkge1xuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGh0bWwgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oIGkgKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLndyYXBJbm5lciggaHRtbC5jYWxsKHRoaXMsIGkpICk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIHNlbGYgPSBqUXVlcnkoIHRoaXMgKSxcblx0XHRcdFx0Y29udGVudHMgPSBzZWxmLmNvbnRlbnRzKCk7XG5cblx0XHRcdGlmICggY29udGVudHMubGVuZ3RoICkge1xuXHRcdFx0XHRjb250ZW50cy53cmFwQWxsKCBodG1sICk7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHNlbGYuYXBwZW5kKCBodG1sICk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0sXG5cblx0d3JhcDogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0dmFyIGlzRnVuY3Rpb24gPSBqUXVlcnkuaXNGdW5jdGlvbiggaHRtbCApO1xuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiggaSApIHtcblx0XHRcdGpRdWVyeSggdGhpcyApLndyYXBBbGwoIGlzRnVuY3Rpb24gPyBodG1sLmNhbGwodGhpcywgaSkgOiBodG1sICk7XG5cdFx0fSk7XG5cdH0sXG5cblx0dW53cmFwOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5wYXJlbnQoKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCAhalF1ZXJ5Lm5vZGVOYW1lKCB0aGlzLCBcImJvZHlcIiApICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5yZXBsYWNlV2l0aCggdGhpcy5jaGlsZE5vZGVzICk7XG5cdFx0XHR9XG5cdFx0fSkuZW5kKCk7XG5cdH1cbn0pO1xuXG5cbmpRdWVyeS5leHByLmZpbHRlcnMuaGlkZGVuID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdC8vIFN1cHBvcnQ6IE9wZXJhIDw9IDEyLjEyXG5cdC8vIE9wZXJhIHJlcG9ydHMgb2Zmc2V0V2lkdGhzIGFuZCBvZmZzZXRIZWlnaHRzIGxlc3MgdGhhbiB6ZXJvIG9uIHNvbWUgZWxlbWVudHNcblx0cmV0dXJuIGVsZW0ub2Zmc2V0V2lkdGggPD0gMCAmJiBlbGVtLm9mZnNldEhlaWdodCA8PSAwO1xufTtcbmpRdWVyeS5leHByLmZpbHRlcnMudmlzaWJsZSA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRyZXR1cm4gIWpRdWVyeS5leHByLmZpbHRlcnMuaGlkZGVuKCBlbGVtICk7XG59O1xuXG5cblxuXG52YXIgcjIwID0gLyUyMC9nLFxuXHRyYnJhY2tldCA9IC9cXFtcXF0kLyxcblx0ckNSTEYgPSAvXFxyP1xcbi9nLFxuXHRyc3VibWl0dGVyVHlwZXMgPSAvXig/OnN1Ym1pdHxidXR0b258aW1hZ2V8cmVzZXR8ZmlsZSkkL2ksXG5cdHJzdWJtaXR0YWJsZSA9IC9eKD86aW5wdXR8c2VsZWN0fHRleHRhcmVhfGtleWdlbikvaTtcblxuZnVuY3Rpb24gYnVpbGRQYXJhbXMoIHByZWZpeCwgb2JqLCB0cmFkaXRpb25hbCwgYWRkICkge1xuXHR2YXIgbmFtZTtcblxuXHRpZiAoIGpRdWVyeS5pc0FycmF5KCBvYmogKSApIHtcblx0XHQvLyBTZXJpYWxpemUgYXJyYXkgaXRlbS5cblx0XHRqUXVlcnkuZWFjaCggb2JqLCBmdW5jdGlvbiggaSwgdiApIHtcblx0XHRcdGlmICggdHJhZGl0aW9uYWwgfHwgcmJyYWNrZXQudGVzdCggcHJlZml4ICkgKSB7XG5cdFx0XHRcdC8vIFRyZWF0IGVhY2ggYXJyYXkgaXRlbSBhcyBhIHNjYWxhci5cblx0XHRcdFx0YWRkKCBwcmVmaXgsIHYgKTtcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gSXRlbSBpcyBub24tc2NhbGFyIChhcnJheSBvciBvYmplY3QpLCBlbmNvZGUgaXRzIG51bWVyaWMgaW5kZXguXG5cdFx0XHRcdGJ1aWxkUGFyYW1zKCBwcmVmaXggKyBcIltcIiArICggdHlwZW9mIHYgPT09IFwib2JqZWN0XCIgPyBpIDogXCJcIiApICsgXCJdXCIsIHYsIHRyYWRpdGlvbmFsLCBhZGQgKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHR9IGVsc2UgaWYgKCAhdHJhZGl0aW9uYWwgJiYgalF1ZXJ5LnR5cGUoIG9iaiApID09PSBcIm9iamVjdFwiICkge1xuXHRcdC8vIFNlcmlhbGl6ZSBvYmplY3QgaXRlbS5cblx0XHRmb3IgKCBuYW1lIGluIG9iaiApIHtcblx0XHRcdGJ1aWxkUGFyYW1zKCBwcmVmaXggKyBcIltcIiArIG5hbWUgKyBcIl1cIiwgb2JqWyBuYW1lIF0sIHRyYWRpdGlvbmFsLCBhZGQgKTtcblx0XHR9XG5cblx0fSBlbHNlIHtcblx0XHQvLyBTZXJpYWxpemUgc2NhbGFyIGl0ZW0uXG5cdFx0YWRkKCBwcmVmaXgsIG9iaiApO1xuXHR9XG59XG5cbi8vIFNlcmlhbGl6ZSBhbiBhcnJheSBvZiBmb3JtIGVsZW1lbnRzIG9yIGEgc2V0IG9mXG4vLyBrZXkvdmFsdWVzIGludG8gYSBxdWVyeSBzdHJpbmdcbmpRdWVyeS5wYXJhbSA9IGZ1bmN0aW9uKCBhLCB0cmFkaXRpb25hbCApIHtcblx0dmFyIHByZWZpeCxcblx0XHRzID0gW10sXG5cdFx0YWRkID0gZnVuY3Rpb24oIGtleSwgdmFsdWUgKSB7XG5cdFx0XHQvLyBJZiB2YWx1ZSBpcyBhIGZ1bmN0aW9uLCBpbnZva2UgaXQgYW5kIHJldHVybiBpdHMgdmFsdWVcblx0XHRcdHZhbHVlID0galF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICkgPyB2YWx1ZSgpIDogKCB2YWx1ZSA9PSBudWxsID8gXCJcIiA6IHZhbHVlICk7XG5cdFx0XHRzWyBzLmxlbmd0aCBdID0gZW5jb2RlVVJJQ29tcG9uZW50KCBrZXkgKSArIFwiPVwiICsgZW5jb2RlVVJJQ29tcG9uZW50KCB2YWx1ZSApO1xuXHRcdH07XG5cblx0Ly8gU2V0IHRyYWRpdGlvbmFsIHRvIHRydWUgZm9yIGpRdWVyeSA8PSAxLjMuMiBiZWhhdmlvci5cblx0aWYgKCB0cmFkaXRpb25hbCA9PT0gdW5kZWZpbmVkICkge1xuXHRcdHRyYWRpdGlvbmFsID0galF1ZXJ5LmFqYXhTZXR0aW5ncyAmJiBqUXVlcnkuYWpheFNldHRpbmdzLnRyYWRpdGlvbmFsO1xuXHR9XG5cblx0Ly8gSWYgYW4gYXJyYXkgd2FzIHBhc3NlZCBpbiwgYXNzdW1lIHRoYXQgaXQgaXMgYW4gYXJyYXkgb2YgZm9ybSBlbGVtZW50cy5cblx0aWYgKCBqUXVlcnkuaXNBcnJheSggYSApIHx8ICggYS5qcXVlcnkgJiYgIWpRdWVyeS5pc1BsYWluT2JqZWN0KCBhICkgKSApIHtcblx0XHQvLyBTZXJpYWxpemUgdGhlIGZvcm0gZWxlbWVudHNcblx0XHRqUXVlcnkuZWFjaCggYSwgZnVuY3Rpb24oKSB7XG5cdFx0XHRhZGQoIHRoaXMubmFtZSwgdGhpcy52YWx1ZSApO1xuXHRcdH0pO1xuXG5cdH0gZWxzZSB7XG5cdFx0Ly8gSWYgdHJhZGl0aW9uYWwsIGVuY29kZSB0aGUgXCJvbGRcIiB3YXkgKHRoZSB3YXkgMS4zLjIgb3Igb2xkZXJcblx0XHQvLyBkaWQgaXQpLCBvdGhlcndpc2UgZW5jb2RlIHBhcmFtcyByZWN1cnNpdmVseS5cblx0XHRmb3IgKCBwcmVmaXggaW4gYSApIHtcblx0XHRcdGJ1aWxkUGFyYW1zKCBwcmVmaXgsIGFbIHByZWZpeCBdLCB0cmFkaXRpb25hbCwgYWRkICk7XG5cdFx0fVxuXHR9XG5cblx0Ly8gUmV0dXJuIHRoZSByZXN1bHRpbmcgc2VyaWFsaXphdGlvblxuXHRyZXR1cm4gcy5qb2luKCBcIiZcIiApLnJlcGxhY2UoIHIyMCwgXCIrXCIgKTtcbn07XG5cbmpRdWVyeS5mbi5leHRlbmQoe1xuXHRzZXJpYWxpemU6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiBqUXVlcnkucGFyYW0oIHRoaXMuc2VyaWFsaXplQXJyYXkoKSApO1xuXHR9LFxuXHRzZXJpYWxpemVBcnJheTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFwKGZ1bmN0aW9uKCkge1xuXHRcdFx0Ly8gQ2FuIGFkZCBwcm9wSG9vayBmb3IgXCJlbGVtZW50c1wiIHRvIGZpbHRlciBvciBhZGQgZm9ybSBlbGVtZW50c1xuXHRcdFx0dmFyIGVsZW1lbnRzID0galF1ZXJ5LnByb3AoIHRoaXMsIFwiZWxlbWVudHNcIiApO1xuXHRcdFx0cmV0dXJuIGVsZW1lbnRzID8galF1ZXJ5Lm1ha2VBcnJheSggZWxlbWVudHMgKSA6IHRoaXM7XG5cdFx0fSlcblx0XHQuZmlsdGVyKGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIHR5cGUgPSB0aGlzLnR5cGU7XG5cblx0XHRcdC8vIFVzZSAuaXMoIFwiOmRpc2FibGVkXCIgKSBzbyB0aGF0IGZpZWxkc2V0W2Rpc2FibGVkXSB3b3Jrc1xuXHRcdFx0cmV0dXJuIHRoaXMubmFtZSAmJiAhalF1ZXJ5KCB0aGlzICkuaXMoIFwiOmRpc2FibGVkXCIgKSAmJlxuXHRcdFx0XHRyc3VibWl0dGFibGUudGVzdCggdGhpcy5ub2RlTmFtZSApICYmICFyc3VibWl0dGVyVHlwZXMudGVzdCggdHlwZSApICYmXG5cdFx0XHRcdCggdGhpcy5jaGVja2VkIHx8ICFyY2hlY2thYmxlVHlwZS50ZXN0KCB0eXBlICkgKTtcblx0XHR9KVxuXHRcdC5tYXAoZnVuY3Rpb24oIGksIGVsZW0gKSB7XG5cdFx0XHR2YXIgdmFsID0galF1ZXJ5KCB0aGlzICkudmFsKCk7XG5cblx0XHRcdHJldHVybiB2YWwgPT0gbnVsbCA/XG5cdFx0XHRcdG51bGwgOlxuXHRcdFx0XHRqUXVlcnkuaXNBcnJheSggdmFsICkgP1xuXHRcdFx0XHRcdGpRdWVyeS5tYXAoIHZhbCwgZnVuY3Rpb24oIHZhbCApIHtcblx0XHRcdFx0XHRcdHJldHVybiB7IG5hbWU6IGVsZW0ubmFtZSwgdmFsdWU6IHZhbC5yZXBsYWNlKCByQ1JMRiwgXCJcXHJcXG5cIiApIH07XG5cdFx0XHRcdFx0fSkgOlxuXHRcdFx0XHRcdHsgbmFtZTogZWxlbS5uYW1lLCB2YWx1ZTogdmFsLnJlcGxhY2UoIHJDUkxGLCBcIlxcclxcblwiICkgfTtcblx0XHR9KS5nZXQoKTtcblx0fVxufSk7XG5cblxualF1ZXJ5LmFqYXhTZXR0aW5ncy54aHIgPSBmdW5jdGlvbigpIHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG5cdH0gY2F0Y2goIGUgKSB7fVxufTtcblxudmFyIHhocklkID0gMCxcblx0eGhyQ2FsbGJhY2tzID0ge30sXG5cdHhoclN1Y2Nlc3NTdGF0dXMgPSB7XG5cdFx0Ly8gZmlsZSBwcm90b2NvbCBhbHdheXMgeWllbGRzIHN0YXR1cyBjb2RlIDAsIGFzc3VtZSAyMDBcblx0XHQwOiAyMDAsXG5cdFx0Ly8gU3VwcG9ydDogSUU5XG5cdFx0Ly8gIzE0NTA6IHNvbWV0aW1lcyBJRSByZXR1cm5zIDEyMjMgd2hlbiBpdCBzaG91bGQgYmUgMjA0XG5cdFx0MTIyMzogMjA0XG5cdH0sXG5cdHhoclN1cHBvcnRlZCA9IGpRdWVyeS5hamF4U2V0dGluZ3MueGhyKCk7XG5cbi8vIFN1cHBvcnQ6IElFOVxuLy8gT3BlbiByZXF1ZXN0cyBtdXN0IGJlIG1hbnVhbGx5IGFib3J0ZWQgb24gdW5sb2FkICgjNTI4MClcbi8vIFNlZSBodHRwczovL3N1cHBvcnQubWljcm9zb2Z0LmNvbS9rYi8yODU2NzQ2IGZvciBtb3JlIGluZm9cbmlmICggd2luZG93LmF0dGFjaEV2ZW50ICkge1xuXHR3aW5kb3cuYXR0YWNoRXZlbnQoIFwib251bmxvYWRcIiwgZnVuY3Rpb24oKSB7XG5cdFx0Zm9yICggdmFyIGtleSBpbiB4aHJDYWxsYmFja3MgKSB7XG5cdFx0XHR4aHJDYWxsYmFja3NbIGtleSBdKCk7XG5cdFx0fVxuXHR9KTtcbn1cblxuc3VwcG9ydC5jb3JzID0gISF4aHJTdXBwb3J0ZWQgJiYgKCBcIndpdGhDcmVkZW50aWFsc1wiIGluIHhoclN1cHBvcnRlZCApO1xuc3VwcG9ydC5hamF4ID0geGhyU3VwcG9ydGVkID0gISF4aHJTdXBwb3J0ZWQ7XG5cbmpRdWVyeS5hamF4VHJhbnNwb3J0KGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXHR2YXIgY2FsbGJhY2s7XG5cblx0Ly8gQ3Jvc3MgZG9tYWluIG9ubHkgYWxsb3dlZCBpZiBzdXBwb3J0ZWQgdGhyb3VnaCBYTUxIdHRwUmVxdWVzdFxuXHRpZiAoIHN1cHBvcnQuY29ycyB8fCB4aHJTdXBwb3J0ZWQgJiYgIW9wdGlvbnMuY3Jvc3NEb21haW4gKSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlbmQ6IGZ1bmN0aW9uKCBoZWFkZXJzLCBjb21wbGV0ZSApIHtcblx0XHRcdFx0dmFyIGksXG5cdFx0XHRcdFx0eGhyID0gb3B0aW9ucy54aHIoKSxcblx0XHRcdFx0XHRpZCA9ICsreGhySWQ7XG5cblx0XHRcdFx0eGhyLm9wZW4oIG9wdGlvbnMudHlwZSwgb3B0aW9ucy51cmwsIG9wdGlvbnMuYXN5bmMsIG9wdGlvbnMudXNlcm5hbWUsIG9wdGlvbnMucGFzc3dvcmQgKTtcblxuXHRcdFx0XHQvLyBBcHBseSBjdXN0b20gZmllbGRzIGlmIHByb3ZpZGVkXG5cdFx0XHRcdGlmICggb3B0aW9ucy54aHJGaWVsZHMgKSB7XG5cdFx0XHRcdFx0Zm9yICggaSBpbiBvcHRpb25zLnhockZpZWxkcyApIHtcblx0XHRcdFx0XHRcdHhoclsgaSBdID0gb3B0aW9ucy54aHJGaWVsZHNbIGkgXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBPdmVycmlkZSBtaW1lIHR5cGUgaWYgbmVlZGVkXG5cdFx0XHRcdGlmICggb3B0aW9ucy5taW1lVHlwZSAmJiB4aHIub3ZlcnJpZGVNaW1lVHlwZSApIHtcblx0XHRcdFx0XHR4aHIub3ZlcnJpZGVNaW1lVHlwZSggb3B0aW9ucy5taW1lVHlwZSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gWC1SZXF1ZXN0ZWQtV2l0aCBoZWFkZXJcblx0XHRcdFx0Ly8gRm9yIGNyb3NzLWRvbWFpbiByZXF1ZXN0cywgc2VlaW5nIGFzIGNvbmRpdGlvbnMgZm9yIGEgcHJlZmxpZ2h0IGFyZVxuXHRcdFx0XHQvLyBha2luIHRvIGEgamlnc2F3IHB1enpsZSwgd2Ugc2ltcGx5IG5ldmVyIHNldCBpdCB0byBiZSBzdXJlLlxuXHRcdFx0XHQvLyAoaXQgY2FuIGFsd2F5cyBiZSBzZXQgb24gYSBwZXItcmVxdWVzdCBiYXNpcyBvciBldmVuIHVzaW5nIGFqYXhTZXR1cClcblx0XHRcdFx0Ly8gRm9yIHNhbWUtZG9tYWluIHJlcXVlc3RzLCB3b24ndCBjaGFuZ2UgaGVhZGVyIGlmIGFscmVhZHkgcHJvdmlkZWQuXG5cdFx0XHRcdGlmICggIW9wdGlvbnMuY3Jvc3NEb21haW4gJiYgIWhlYWRlcnNbXCJYLVJlcXVlc3RlZC1XaXRoXCJdICkge1xuXHRcdFx0XHRcdGhlYWRlcnNbXCJYLVJlcXVlc3RlZC1XaXRoXCJdID0gXCJYTUxIdHRwUmVxdWVzdFwiO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gU2V0IGhlYWRlcnNcblx0XHRcdFx0Zm9yICggaSBpbiBoZWFkZXJzICkge1xuXHRcdFx0XHRcdHhoci5zZXRSZXF1ZXN0SGVhZGVyKCBpLCBoZWFkZXJzWyBpIF0gKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIENhbGxiYWNrXG5cdFx0XHRcdGNhbGxiYWNrID0gZnVuY3Rpb24oIHR5cGUgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0aWYgKCBjYWxsYmFjayApIHtcblx0XHRcdFx0XHRcdFx0ZGVsZXRlIHhockNhbGxiYWNrc1sgaWQgXTtcblx0XHRcdFx0XHRcdFx0Y2FsbGJhY2sgPSB4aHIub25sb2FkID0geGhyLm9uZXJyb3IgPSBudWxsO1xuXG5cdFx0XHRcdFx0XHRcdGlmICggdHlwZSA9PT0gXCJhYm9ydFwiICkge1xuXHRcdFx0XHRcdFx0XHRcdHhoci5hYm9ydCgpO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCB0eXBlID09PSBcImVycm9yXCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0Y29tcGxldGUoXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBmaWxlOiBwcm90b2NvbCBhbHdheXMgeWllbGRzIHN0YXR1cyAwOyBzZWUgIzg2MDUsICMxNDIwN1xuXHRcdFx0XHRcdFx0XHRcdFx0eGhyLnN0YXR1cyxcblx0XHRcdFx0XHRcdFx0XHRcdHhoci5zdGF0dXNUZXh0XG5cdFx0XHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZShcblx0XHRcdFx0XHRcdFx0XHRcdHhoclN1Y2Nlc3NTdGF0dXNbIHhoci5zdGF0dXMgXSB8fCB4aHIuc3RhdHVzLFxuXHRcdFx0XHRcdFx0XHRcdFx0eGhyLnN0YXR1c1RleHQsXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRTlcblx0XHRcdFx0XHRcdFx0XHRcdC8vIEFjY2Vzc2luZyBiaW5hcnktZGF0YSByZXNwb25zZVRleHQgdGhyb3dzIGFuIGV4Y2VwdGlvblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gKCMxMTQyNilcblx0XHRcdFx0XHRcdFx0XHRcdHR5cGVvZiB4aHIucmVzcG9uc2VUZXh0ID09PSBcInN0cmluZ1wiID8ge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0ZXh0OiB4aHIucmVzcG9uc2VUZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHR9IDogdW5kZWZpbmVkLFxuXHRcdFx0XHRcdFx0XHRcdFx0eGhyLmdldEFsbFJlc3BvbnNlSGVhZGVycygpXG5cdFx0XHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH07XG5cblx0XHRcdFx0Ly8gTGlzdGVuIHRvIGV2ZW50c1xuXHRcdFx0XHR4aHIub25sb2FkID0gY2FsbGJhY2soKTtcblx0XHRcdFx0eGhyLm9uZXJyb3IgPSBjYWxsYmFjayhcImVycm9yXCIpO1xuXG5cdFx0XHRcdC8vIENyZWF0ZSB0aGUgYWJvcnQgY2FsbGJhY2tcblx0XHRcdFx0Y2FsbGJhY2sgPSB4aHJDYWxsYmFja3NbIGlkIF0gPSBjYWxsYmFjayhcImFib3J0XCIpO1xuXG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Ly8gRG8gc2VuZCB0aGUgcmVxdWVzdCAodGhpcyBtYXkgcmFpc2UgYW4gZXhjZXB0aW9uKVxuXHRcdFx0XHRcdHhoci5zZW5kKCBvcHRpb25zLmhhc0NvbnRlbnQgJiYgb3B0aW9ucy5kYXRhIHx8IG51bGwgKTtcblx0XHRcdFx0fSBjYXRjaCAoIGUgKSB7XG5cdFx0XHRcdFx0Ly8gIzE0NjgzOiBPbmx5IHJldGhyb3cgaWYgdGhpcyBoYXNuJ3QgYmVlbiBub3RpZmllZCBhcyBhbiBlcnJvciB5ZXRcblx0XHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdFx0dGhyb3cgZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cblx0XHRcdGFib3J0OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCBjYWxsYmFjayApIHtcblx0XHRcdFx0XHRjYWxsYmFjaygpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxufSk7XG5cblxuXG5cbi8vIEluc3RhbGwgc2NyaXB0IGRhdGFUeXBlXG5qUXVlcnkuYWpheFNldHVwKHtcblx0YWNjZXB0czoge1xuXHRcdHNjcmlwdDogXCJ0ZXh0L2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2VjbWFzY3JpcHQsIGFwcGxpY2F0aW9uL3gtZWNtYXNjcmlwdFwiXG5cdH0sXG5cdGNvbnRlbnRzOiB7XG5cdFx0c2NyaXB0OiAvKD86amF2YXxlY21hKXNjcmlwdC9cblx0fSxcblx0Y29udmVydGVyczoge1xuXHRcdFwidGV4dCBzY3JpcHRcIjogZnVuY3Rpb24oIHRleHQgKSB7XG5cdFx0XHRqUXVlcnkuZ2xvYmFsRXZhbCggdGV4dCApO1xuXHRcdFx0cmV0dXJuIHRleHQ7XG5cdFx0fVxuXHR9XG59KTtcblxuLy8gSGFuZGxlIGNhY2hlJ3Mgc3BlY2lhbCBjYXNlIGFuZCBjcm9zc0RvbWFpblxualF1ZXJ5LmFqYXhQcmVmaWx0ZXIoIFwic2NyaXB0XCIsIGZ1bmN0aW9uKCBzICkge1xuXHRpZiAoIHMuY2FjaGUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRzLmNhY2hlID0gZmFsc2U7XG5cdH1cblx0aWYgKCBzLmNyb3NzRG9tYWluICkge1xuXHRcdHMudHlwZSA9IFwiR0VUXCI7XG5cdH1cbn0pO1xuXG4vLyBCaW5kIHNjcmlwdCB0YWcgaGFjayB0cmFuc3BvcnRcbmpRdWVyeS5hamF4VHJhbnNwb3J0KCBcInNjcmlwdFwiLCBmdW5jdGlvbiggcyApIHtcblx0Ly8gVGhpcyB0cmFuc3BvcnQgb25seSBkZWFscyB3aXRoIGNyb3NzIGRvbWFpbiByZXF1ZXN0c1xuXHRpZiAoIHMuY3Jvc3NEb21haW4gKSB7XG5cdFx0dmFyIHNjcmlwdCwgY2FsbGJhY2s7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlbmQ6IGZ1bmN0aW9uKCBfLCBjb21wbGV0ZSApIHtcblx0XHRcdFx0c2NyaXB0ID0galF1ZXJ5KFwiPHNjcmlwdD5cIikucHJvcCh7XG5cdFx0XHRcdFx0YXN5bmM6IHRydWUsXG5cdFx0XHRcdFx0Y2hhcnNldDogcy5zY3JpcHRDaGFyc2V0LFxuXHRcdFx0XHRcdHNyYzogcy51cmxcblx0XHRcdFx0fSkub24oXG5cdFx0XHRcdFx0XCJsb2FkIGVycm9yXCIsXG5cdFx0XHRcdFx0Y2FsbGJhY2sgPSBmdW5jdGlvbiggZXZ0ICkge1xuXHRcdFx0XHRcdFx0c2NyaXB0LnJlbW92ZSgpO1xuXHRcdFx0XHRcdFx0Y2FsbGJhY2sgPSBudWxsO1xuXHRcdFx0XHRcdFx0aWYgKCBldnQgKSB7XG5cdFx0XHRcdFx0XHRcdGNvbXBsZXRlKCBldnQudHlwZSA9PT0gXCJlcnJvclwiID8gNDA0IDogMjAwLCBldnQudHlwZSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0KTtcblx0XHRcdFx0ZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZCggc2NyaXB0WyAwIF0gKTtcblx0XHRcdH0sXG5cdFx0XHRhYm9ydDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggY2FsbGJhY2sgKSB7XG5cdFx0XHRcdFx0Y2FsbGJhY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG5cdH1cbn0pO1xuXG5cblxuXG52YXIgb2xkQ2FsbGJhY2tzID0gW10sXG5cdHJqc29ucCA9IC8oPSlcXD8oPz0mfCQpfFxcP1xcPy87XG5cbi8vIERlZmF1bHQganNvbnAgc2V0dGluZ3NcbmpRdWVyeS5hamF4U2V0dXAoe1xuXHRqc29ucDogXCJjYWxsYmFja1wiLFxuXHRqc29ucENhbGxiYWNrOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgY2FsbGJhY2sgPSBvbGRDYWxsYmFja3MucG9wKCkgfHwgKCBqUXVlcnkuZXhwYW5kbyArIFwiX1wiICsgKCBub25jZSsrICkgKTtcblx0XHR0aGlzWyBjYWxsYmFjayBdID0gdHJ1ZTtcblx0XHRyZXR1cm4gY2FsbGJhY2s7XG5cdH1cbn0pO1xuXG4vLyBEZXRlY3QsIG5vcm1hbGl6ZSBvcHRpb25zIGFuZCBpbnN0YWxsIGNhbGxiYWNrcyBmb3IganNvbnAgcmVxdWVzdHNcbmpRdWVyeS5hamF4UHJlZmlsdGVyKCBcImpzb24ganNvbnBcIiwgZnVuY3Rpb24oIHMsIG9yaWdpbmFsU2V0dGluZ3MsIGpxWEhSICkge1xuXG5cdHZhciBjYWxsYmFja05hbWUsIG92ZXJ3cml0dGVuLCByZXNwb25zZUNvbnRhaW5lcixcblx0XHRqc29uUHJvcCA9IHMuanNvbnAgIT09IGZhbHNlICYmICggcmpzb25wLnRlc3QoIHMudXJsICkgP1xuXHRcdFx0XCJ1cmxcIiA6XG5cdFx0XHR0eXBlb2Ygcy5kYXRhID09PSBcInN0cmluZ1wiICYmICEoIHMuY29udGVudFR5cGUgfHwgXCJcIiApLmluZGV4T2YoXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcIikgJiYgcmpzb25wLnRlc3QoIHMuZGF0YSApICYmIFwiZGF0YVwiXG5cdFx0KTtcblxuXHQvLyBIYW5kbGUgaWZmIHRoZSBleHBlY3RlZCBkYXRhIHR5cGUgaXMgXCJqc29ucFwiIG9yIHdlIGhhdmUgYSBwYXJhbWV0ZXIgdG8gc2V0XG5cdGlmICgganNvblByb3AgfHwgcy5kYXRhVHlwZXNbIDAgXSA9PT0gXCJqc29ucFwiICkge1xuXG5cdFx0Ly8gR2V0IGNhbGxiYWNrIG5hbWUsIHJlbWVtYmVyaW5nIHByZWV4aXN0aW5nIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCBpdFxuXHRcdGNhbGxiYWNrTmFtZSA9IHMuanNvbnBDYWxsYmFjayA9IGpRdWVyeS5pc0Z1bmN0aW9uKCBzLmpzb25wQ2FsbGJhY2sgKSA/XG5cdFx0XHRzLmpzb25wQ2FsbGJhY2soKSA6XG5cdFx0XHRzLmpzb25wQ2FsbGJhY2s7XG5cblx0XHQvLyBJbnNlcnQgY2FsbGJhY2sgaW50byB1cmwgb3IgZm9ybSBkYXRhXG5cdFx0aWYgKCBqc29uUHJvcCApIHtcblx0XHRcdHNbIGpzb25Qcm9wIF0gPSBzWyBqc29uUHJvcCBdLnJlcGxhY2UoIHJqc29ucCwgXCIkMVwiICsgY2FsbGJhY2tOYW1lICk7XG5cdFx0fSBlbHNlIGlmICggcy5qc29ucCAhPT0gZmFsc2UgKSB7XG5cdFx0XHRzLnVybCArPSAoIHJxdWVyeS50ZXN0KCBzLnVybCApID8gXCImXCIgOiBcIj9cIiApICsgcy5qc29ucCArIFwiPVwiICsgY2FsbGJhY2tOYW1lO1xuXHRcdH1cblxuXHRcdC8vIFVzZSBkYXRhIGNvbnZlcnRlciB0byByZXRyaWV2ZSBqc29uIGFmdGVyIHNjcmlwdCBleGVjdXRpb25cblx0XHRzLmNvbnZlcnRlcnNbXCJzY3JpcHQganNvblwiXSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCAhcmVzcG9uc2VDb250YWluZXIgKSB7XG5cdFx0XHRcdGpRdWVyeS5lcnJvciggY2FsbGJhY2tOYW1lICsgXCIgd2FzIG5vdCBjYWxsZWRcIiApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJlc3BvbnNlQ29udGFpbmVyWyAwIF07XG5cdFx0fTtcblxuXHRcdC8vIGZvcmNlIGpzb24gZGF0YVR5cGVcblx0XHRzLmRhdGFUeXBlc1sgMCBdID0gXCJqc29uXCI7XG5cblx0XHQvLyBJbnN0YWxsIGNhbGxiYWNrXG5cdFx0b3ZlcndyaXR0ZW4gPSB3aW5kb3dbIGNhbGxiYWNrTmFtZSBdO1xuXHRcdHdpbmRvd1sgY2FsbGJhY2tOYW1lIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdHJlc3BvbnNlQ29udGFpbmVyID0gYXJndW1lbnRzO1xuXHRcdH07XG5cblx0XHQvLyBDbGVhbi11cCBmdW5jdGlvbiAoZmlyZXMgYWZ0ZXIgY29udmVydGVycylcblx0XHRqcVhIUi5hbHdheXMoZnVuY3Rpb24oKSB7XG5cdFx0XHQvLyBSZXN0b3JlIHByZWV4aXN0aW5nIHZhbHVlXG5cdFx0XHR3aW5kb3dbIGNhbGxiYWNrTmFtZSBdID0gb3ZlcndyaXR0ZW47XG5cblx0XHRcdC8vIFNhdmUgYmFjayBhcyBmcmVlXG5cdFx0XHRpZiAoIHNbIGNhbGxiYWNrTmFtZSBdICkge1xuXHRcdFx0XHQvLyBtYWtlIHN1cmUgdGhhdCByZS11c2luZyB0aGUgb3B0aW9ucyBkb2Vzbid0IHNjcmV3IHRoaW5ncyBhcm91bmRcblx0XHRcdFx0cy5qc29ucENhbGxiYWNrID0gb3JpZ2luYWxTZXR0aW5ncy5qc29ucENhbGxiYWNrO1xuXG5cdFx0XHRcdC8vIHNhdmUgdGhlIGNhbGxiYWNrIG5hbWUgZm9yIGZ1dHVyZSB1c2Vcblx0XHRcdFx0b2xkQ2FsbGJhY2tzLnB1c2goIGNhbGxiYWNrTmFtZSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDYWxsIGlmIGl0IHdhcyBhIGZ1bmN0aW9uIGFuZCB3ZSBoYXZlIGEgcmVzcG9uc2Vcblx0XHRcdGlmICggcmVzcG9uc2VDb250YWluZXIgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oIG92ZXJ3cml0dGVuICkgKSB7XG5cdFx0XHRcdG92ZXJ3cml0dGVuKCByZXNwb25zZUNvbnRhaW5lclsgMCBdICk7XG5cdFx0XHR9XG5cblx0XHRcdHJlc3BvbnNlQ29udGFpbmVyID0gb3ZlcndyaXR0ZW4gPSB1bmRlZmluZWQ7XG5cdFx0fSk7XG5cblx0XHQvLyBEZWxlZ2F0ZSB0byBzY3JpcHRcblx0XHRyZXR1cm4gXCJzY3JpcHRcIjtcblx0fVxufSk7XG5cblxuXG5cbi8vIGRhdGE6IHN0cmluZyBvZiBodG1sXG4vLyBjb250ZXh0IChvcHRpb25hbCk6IElmIHNwZWNpZmllZCwgdGhlIGZyYWdtZW50IHdpbGwgYmUgY3JlYXRlZCBpbiB0aGlzIGNvbnRleHQsIGRlZmF1bHRzIHRvIGRvY3VtZW50XG4vLyBrZWVwU2NyaXB0cyAob3B0aW9uYWwpOiBJZiB0cnVlLCB3aWxsIGluY2x1ZGUgc2NyaXB0cyBwYXNzZWQgaW4gdGhlIGh0bWwgc3RyaW5nXG5qUXVlcnkucGFyc2VIVE1MID0gZnVuY3Rpb24oIGRhdGEsIGNvbnRleHQsIGtlZXBTY3JpcHRzICkge1xuXHRpZiAoICFkYXRhIHx8IHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cdGlmICggdHlwZW9mIGNvbnRleHQgPT09IFwiYm9vbGVhblwiICkge1xuXHRcdGtlZXBTY3JpcHRzID0gY29udGV4dDtcblx0XHRjb250ZXh0ID0gZmFsc2U7XG5cdH1cblx0Y29udGV4dCA9IGNvbnRleHQgfHwgZG9jdW1lbnQ7XG5cblx0dmFyIHBhcnNlZCA9IHJzaW5nbGVUYWcuZXhlYyggZGF0YSApLFxuXHRcdHNjcmlwdHMgPSAha2VlcFNjcmlwdHMgJiYgW107XG5cblx0Ly8gU2luZ2xlIHRhZ1xuXHRpZiAoIHBhcnNlZCApIHtcblx0XHRyZXR1cm4gWyBjb250ZXh0LmNyZWF0ZUVsZW1lbnQoIHBhcnNlZFsxXSApIF07XG5cdH1cblxuXHRwYXJzZWQgPSBqUXVlcnkuYnVpbGRGcmFnbWVudCggWyBkYXRhIF0sIGNvbnRleHQsIHNjcmlwdHMgKTtcblxuXHRpZiAoIHNjcmlwdHMgJiYgc2NyaXB0cy5sZW5ndGggKSB7XG5cdFx0alF1ZXJ5KCBzY3JpcHRzICkucmVtb3ZlKCk7XG5cdH1cblxuXHRyZXR1cm4galF1ZXJ5Lm1lcmdlKCBbXSwgcGFyc2VkLmNoaWxkTm9kZXMgKTtcbn07XG5cblxuLy8gS2VlcCBhIGNvcHkgb2YgdGhlIG9sZCBsb2FkIG1ldGhvZFxudmFyIF9sb2FkID0galF1ZXJ5LmZuLmxvYWQ7XG5cbi8qKlxuICogTG9hZCBhIHVybCBpbnRvIGEgcGFnZVxuICovXG5qUXVlcnkuZm4ubG9hZCA9IGZ1bmN0aW9uKCB1cmwsIHBhcmFtcywgY2FsbGJhY2sgKSB7XG5cdGlmICggdHlwZW9mIHVybCAhPT0gXCJzdHJpbmdcIiAmJiBfbG9hZCApIHtcblx0XHRyZXR1cm4gX2xvYWQuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHR9XG5cblx0dmFyIHNlbGVjdG9yLCB0eXBlLCByZXNwb25zZSxcblx0XHRzZWxmID0gdGhpcyxcblx0XHRvZmYgPSB1cmwuaW5kZXhPZihcIiBcIik7XG5cblx0aWYgKCBvZmYgPj0gMCApIHtcblx0XHRzZWxlY3RvciA9IGpRdWVyeS50cmltKCB1cmwuc2xpY2UoIG9mZiApICk7XG5cdFx0dXJsID0gdXJsLnNsaWNlKCAwLCBvZmYgKTtcblx0fVxuXG5cdC8vIElmIGl0J3MgYSBmdW5jdGlvblxuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBwYXJhbXMgKSApIHtcblxuXHRcdC8vIFdlIGFzc3VtZSB0aGF0IGl0J3MgdGhlIGNhbGxiYWNrXG5cdFx0Y2FsbGJhY2sgPSBwYXJhbXM7XG5cdFx0cGFyYW1zID0gdW5kZWZpbmVkO1xuXG5cdC8vIE90aGVyd2lzZSwgYnVpbGQgYSBwYXJhbSBzdHJpbmdcblx0fSBlbHNlIGlmICggcGFyYW1zICYmIHR5cGVvZiBwYXJhbXMgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0dHlwZSA9IFwiUE9TVFwiO1xuXHR9XG5cblx0Ly8gSWYgd2UgaGF2ZSBlbGVtZW50cyB0byBtb2RpZnksIG1ha2UgdGhlIHJlcXVlc3Rcblx0aWYgKCBzZWxmLmxlbmd0aCA+IDAgKSB7XG5cdFx0alF1ZXJ5LmFqYXgoe1xuXHRcdFx0dXJsOiB1cmwsXG5cblx0XHRcdC8vIGlmIFwidHlwZVwiIHZhcmlhYmxlIGlzIHVuZGVmaW5lZCwgdGhlbiBcIkdFVFwiIG1ldGhvZCB3aWxsIGJlIHVzZWRcblx0XHRcdHR5cGU6IHR5cGUsXG5cdFx0XHRkYXRhVHlwZTogXCJodG1sXCIsXG5cdFx0XHRkYXRhOiBwYXJhbXNcblx0XHR9KS5kb25lKGZ1bmN0aW9uKCByZXNwb25zZVRleHQgKSB7XG5cblx0XHRcdC8vIFNhdmUgcmVzcG9uc2UgZm9yIHVzZSBpbiBjb21wbGV0ZSBjYWxsYmFja1xuXHRcdFx0cmVzcG9uc2UgPSBhcmd1bWVudHM7XG5cblx0XHRcdHNlbGYuaHRtbCggc2VsZWN0b3IgP1xuXG5cdFx0XHRcdC8vIElmIGEgc2VsZWN0b3Igd2FzIHNwZWNpZmllZCwgbG9jYXRlIHRoZSByaWdodCBlbGVtZW50cyBpbiBhIGR1bW15IGRpdlxuXHRcdFx0XHQvLyBFeGNsdWRlIHNjcmlwdHMgdG8gYXZvaWQgSUUgJ1Blcm1pc3Npb24gRGVuaWVkJyBlcnJvcnNcblx0XHRcdFx0alF1ZXJ5KFwiPGRpdj5cIikuYXBwZW5kKCBqUXVlcnkucGFyc2VIVE1MKCByZXNwb25zZVRleHQgKSApLmZpbmQoIHNlbGVjdG9yICkgOlxuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSB1c2UgdGhlIGZ1bGwgcmVzdWx0XG5cdFx0XHRcdHJlc3BvbnNlVGV4dCApO1xuXG5cdFx0fSkuY29tcGxldGUoIGNhbGxiYWNrICYmIGZ1bmN0aW9uKCBqcVhIUiwgc3RhdHVzICkge1xuXHRcdFx0c2VsZi5lYWNoKCBjYWxsYmFjaywgcmVzcG9uc2UgfHwgWyBqcVhIUi5yZXNwb25zZVRleHQsIHN0YXR1cywganFYSFIgXSApO1xuXHRcdH0pO1xuXHR9XG5cblx0cmV0dXJuIHRoaXM7XG59O1xuXG5cblxuXG4vLyBBdHRhY2ggYSBidW5jaCBvZiBmdW5jdGlvbnMgZm9yIGhhbmRsaW5nIGNvbW1vbiBBSkFYIGV2ZW50c1xualF1ZXJ5LmVhY2goIFsgXCJhamF4U3RhcnRcIiwgXCJhamF4U3RvcFwiLCBcImFqYXhDb21wbGV0ZVwiLCBcImFqYXhFcnJvclwiLCBcImFqYXhTdWNjZXNzXCIsIFwiYWpheFNlbmRcIiBdLCBmdW5jdGlvbiggaSwgdHlwZSApIHtcblx0alF1ZXJ5LmZuWyB0eXBlIF0gPSBmdW5jdGlvbiggZm4gKSB7XG5cdFx0cmV0dXJuIHRoaXMub24oIHR5cGUsIGZuICk7XG5cdH07XG59KTtcblxuXG5cblxualF1ZXJ5LmV4cHIuZmlsdGVycy5hbmltYXRlZCA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRyZXR1cm4galF1ZXJ5LmdyZXAoalF1ZXJ5LnRpbWVycywgZnVuY3Rpb24oIGZuICkge1xuXHRcdHJldHVybiBlbGVtID09PSBmbi5lbGVtO1xuXHR9KS5sZW5ndGg7XG59O1xuXG5cblxuXG52YXIgZG9jRWxlbSA9IHdpbmRvdy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG5cbi8qKlxuICogR2V0cyBhIHdpbmRvdyBmcm9tIGFuIGVsZW1lbnRcbiAqL1xuZnVuY3Rpb24gZ2V0V2luZG93KCBlbGVtICkge1xuXHRyZXR1cm4galF1ZXJ5LmlzV2luZG93KCBlbGVtICkgPyBlbGVtIDogZWxlbS5ub2RlVHlwZSA9PT0gOSAmJiBlbGVtLmRlZmF1bHRWaWV3O1xufVxuXG5qUXVlcnkub2Zmc2V0ID0ge1xuXHRzZXRPZmZzZXQ6IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBpICkge1xuXHRcdHZhciBjdXJQb3NpdGlvbiwgY3VyTGVmdCwgY3VyQ1NTVG9wLCBjdXJUb3AsIGN1ck9mZnNldCwgY3VyQ1NTTGVmdCwgY2FsY3VsYXRlUG9zaXRpb24sXG5cdFx0XHRwb3NpdGlvbiA9IGpRdWVyeS5jc3MoIGVsZW0sIFwicG9zaXRpb25cIiApLFxuXHRcdFx0Y3VyRWxlbSA9IGpRdWVyeSggZWxlbSApLFxuXHRcdFx0cHJvcHMgPSB7fTtcblxuXHRcdC8vIFNldCBwb3NpdGlvbiBmaXJzdCwgaW4tY2FzZSB0b3AvbGVmdCBhcmUgc2V0IGV2ZW4gb24gc3RhdGljIGVsZW1cblx0XHRpZiAoIHBvc2l0aW9uID09PSBcInN0YXRpY1wiICkge1xuXHRcdFx0ZWxlbS5zdHlsZS5wb3NpdGlvbiA9IFwicmVsYXRpdmVcIjtcblx0XHR9XG5cblx0XHRjdXJPZmZzZXQgPSBjdXJFbGVtLm9mZnNldCgpO1xuXHRcdGN1ckNTU1RvcCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwidG9wXCIgKTtcblx0XHRjdXJDU1NMZWZ0ID0galF1ZXJ5LmNzcyggZWxlbSwgXCJsZWZ0XCIgKTtcblx0XHRjYWxjdWxhdGVQb3NpdGlvbiA9ICggcG9zaXRpb24gPT09IFwiYWJzb2x1dGVcIiB8fCBwb3NpdGlvbiA9PT0gXCJmaXhlZFwiICkgJiZcblx0XHRcdCggY3VyQ1NTVG9wICsgY3VyQ1NTTGVmdCApLmluZGV4T2YoXCJhdXRvXCIpID4gLTE7XG5cblx0XHQvLyBOZWVkIHRvIGJlIGFibGUgdG8gY2FsY3VsYXRlIHBvc2l0aW9uIGlmIGVpdGhlclxuXHRcdC8vIHRvcCBvciBsZWZ0IGlzIGF1dG8gYW5kIHBvc2l0aW9uIGlzIGVpdGhlciBhYnNvbHV0ZSBvciBmaXhlZFxuXHRcdGlmICggY2FsY3VsYXRlUG9zaXRpb24gKSB7XG5cdFx0XHRjdXJQb3NpdGlvbiA9IGN1ckVsZW0ucG9zaXRpb24oKTtcblx0XHRcdGN1clRvcCA9IGN1clBvc2l0aW9uLnRvcDtcblx0XHRcdGN1ckxlZnQgPSBjdXJQb3NpdGlvbi5sZWZ0O1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGN1clRvcCA9IHBhcnNlRmxvYXQoIGN1ckNTU1RvcCApIHx8IDA7XG5cdFx0XHRjdXJMZWZ0ID0gcGFyc2VGbG9hdCggY3VyQ1NTTGVmdCApIHx8IDA7XG5cdFx0fVxuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggb3B0aW9ucyApICkge1xuXHRcdFx0b3B0aW9ucyA9IG9wdGlvbnMuY2FsbCggZWxlbSwgaSwgY3VyT2Zmc2V0ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBvcHRpb25zLnRvcCAhPSBudWxsICkge1xuXHRcdFx0cHJvcHMudG9wID0gKCBvcHRpb25zLnRvcCAtIGN1ck9mZnNldC50b3AgKSArIGN1clRvcDtcblx0XHR9XG5cdFx0aWYgKCBvcHRpb25zLmxlZnQgIT0gbnVsbCApIHtcblx0XHRcdHByb3BzLmxlZnQgPSAoIG9wdGlvbnMubGVmdCAtIGN1ck9mZnNldC5sZWZ0ICkgKyBjdXJMZWZ0O1xuXHRcdH1cblxuXHRcdGlmICggXCJ1c2luZ1wiIGluIG9wdGlvbnMgKSB7XG5cdFx0XHRvcHRpb25zLnVzaW5nLmNhbGwoIGVsZW0sIHByb3BzICk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0Y3VyRWxlbS5jc3MoIHByb3BzICk7XG5cdFx0fVxuXHR9XG59O1xuXG5qUXVlcnkuZm4uZXh0ZW5kKHtcblx0b2Zmc2V0OiBmdW5jdGlvbiggb3B0aW9ucyApIHtcblx0XHRpZiAoIGFyZ3VtZW50cy5sZW5ndGggKSB7XG5cdFx0XHRyZXR1cm4gb3B0aW9ucyA9PT0gdW5kZWZpbmVkID9cblx0XHRcdFx0dGhpcyA6XG5cdFx0XHRcdHRoaXMuZWFjaChmdW5jdGlvbiggaSApIHtcblx0XHRcdFx0XHRqUXVlcnkub2Zmc2V0LnNldE9mZnNldCggdGhpcywgb3B0aW9ucywgaSApO1xuXHRcdFx0XHR9KTtcblx0XHR9XG5cblx0XHR2YXIgZG9jRWxlbSwgd2luLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXSxcblx0XHRcdGJveCA9IHsgdG9wOiAwLCBsZWZ0OiAwIH0sXG5cdFx0XHRkb2MgPSBlbGVtICYmIGVsZW0ub3duZXJEb2N1bWVudDtcblxuXHRcdGlmICggIWRvYyApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRkb2NFbGVtID0gZG9jLmRvY3VtZW50RWxlbWVudDtcblxuXHRcdC8vIE1ha2Ugc3VyZSBpdCdzIG5vdCBhIGRpc2Nvbm5lY3RlZCBET00gbm9kZVxuXHRcdGlmICggIWpRdWVyeS5jb250YWlucyggZG9jRWxlbSwgZWxlbSApICkge1xuXHRcdFx0cmV0dXJuIGJveDtcblx0XHR9XG5cblx0XHQvLyBTdXBwb3J0OiBCbGFja0JlcnJ5IDUsIGlPUyAzIChvcmlnaW5hbCBpUGhvbmUpXG5cdFx0Ly8gSWYgd2UgZG9uJ3QgaGF2ZSBnQkNSLCBqdXN0IHVzZSAwLDAgcmF0aGVyIHRoYW4gZXJyb3Jcblx0XHRpZiAoIHR5cGVvZiBlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCAhPT0gc3RydW5kZWZpbmVkICkge1xuXHRcdFx0Ym94ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0XHR9XG5cdFx0d2luID0gZ2V0V2luZG93KCBkb2MgKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0dG9wOiBib3gudG9wICsgd2luLnBhZ2VZT2Zmc2V0IC0gZG9jRWxlbS5jbGllbnRUb3AsXG5cdFx0XHRsZWZ0OiBib3gubGVmdCArIHdpbi5wYWdlWE9mZnNldCAtIGRvY0VsZW0uY2xpZW50TGVmdFxuXHRcdH07XG5cdH0sXG5cblx0cG9zaXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdGlmICggIXRoaXNbIDAgXSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgb2Zmc2V0UGFyZW50LCBvZmZzZXQsXG5cdFx0XHRlbGVtID0gdGhpc1sgMCBdLFxuXHRcdFx0cGFyZW50T2Zmc2V0ID0geyB0b3A6IDAsIGxlZnQ6IDAgfTtcblxuXHRcdC8vIEZpeGVkIGVsZW1lbnRzIGFyZSBvZmZzZXQgZnJvbSB3aW5kb3cgKHBhcmVudE9mZnNldCA9IHt0b3A6MCwgbGVmdDogMH0sIGJlY2F1c2UgaXQgaXMgaXRzIG9ubHkgb2Zmc2V0IHBhcmVudFxuXHRcdGlmICggalF1ZXJ5LmNzcyggZWxlbSwgXCJwb3NpdGlvblwiICkgPT09IFwiZml4ZWRcIiApIHtcblx0XHRcdC8vIEFzc3VtZSBnZXRCb3VuZGluZ0NsaWVudFJlY3QgaXMgdGhlcmUgd2hlbiBjb21wdXRlZCBwb3NpdGlvbiBpcyBmaXhlZFxuXHRcdFx0b2Zmc2V0ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBHZXQgKnJlYWwqIG9mZnNldFBhcmVudFxuXHRcdFx0b2Zmc2V0UGFyZW50ID0gdGhpcy5vZmZzZXRQYXJlbnQoKTtcblxuXHRcdFx0Ly8gR2V0IGNvcnJlY3Qgb2Zmc2V0c1xuXHRcdFx0b2Zmc2V0ID0gdGhpcy5vZmZzZXQoKTtcblx0XHRcdGlmICggIWpRdWVyeS5ub2RlTmFtZSggb2Zmc2V0UGFyZW50WyAwIF0sIFwiaHRtbFwiICkgKSB7XG5cdFx0XHRcdHBhcmVudE9mZnNldCA9IG9mZnNldFBhcmVudC5vZmZzZXQoKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIG9mZnNldFBhcmVudCBib3JkZXJzXG5cdFx0XHRwYXJlbnRPZmZzZXQudG9wICs9IGpRdWVyeS5jc3MoIG9mZnNldFBhcmVudFsgMCBdLCBcImJvcmRlclRvcFdpZHRoXCIsIHRydWUgKTtcblx0XHRcdHBhcmVudE9mZnNldC5sZWZ0ICs9IGpRdWVyeS5jc3MoIG9mZnNldFBhcmVudFsgMCBdLCBcImJvcmRlckxlZnRXaWR0aFwiLCB0cnVlICk7XG5cdFx0fVxuXG5cdFx0Ly8gU3VidHJhY3QgcGFyZW50IG9mZnNldHMgYW5kIGVsZW1lbnQgbWFyZ2luc1xuXHRcdHJldHVybiB7XG5cdFx0XHR0b3A6IG9mZnNldC50b3AgLSBwYXJlbnRPZmZzZXQudG9wIC0galF1ZXJ5LmNzcyggZWxlbSwgXCJtYXJnaW5Ub3BcIiwgdHJ1ZSApLFxuXHRcdFx0bGVmdDogb2Zmc2V0LmxlZnQgLSBwYXJlbnRPZmZzZXQubGVmdCAtIGpRdWVyeS5jc3MoIGVsZW0sIFwibWFyZ2luTGVmdFwiLCB0cnVlIClcblx0XHR9O1xuXHR9LFxuXG5cdG9mZnNldFBhcmVudDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFwKGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIG9mZnNldFBhcmVudCA9IHRoaXMub2Zmc2V0UGFyZW50IHx8IGRvY0VsZW07XG5cblx0XHRcdHdoaWxlICggb2Zmc2V0UGFyZW50ICYmICggIWpRdWVyeS5ub2RlTmFtZSggb2Zmc2V0UGFyZW50LCBcImh0bWxcIiApICYmIGpRdWVyeS5jc3MoIG9mZnNldFBhcmVudCwgXCJwb3NpdGlvblwiICkgPT09IFwic3RhdGljXCIgKSApIHtcblx0XHRcdFx0b2Zmc2V0UGFyZW50ID0gb2Zmc2V0UGFyZW50Lm9mZnNldFBhcmVudDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG9mZnNldFBhcmVudCB8fCBkb2NFbGVtO1xuXHRcdH0pO1xuXHR9XG59KTtcblxuLy8gQ3JlYXRlIHNjcm9sbExlZnQgYW5kIHNjcm9sbFRvcCBtZXRob2RzXG5qUXVlcnkuZWFjaCggeyBzY3JvbGxMZWZ0OiBcInBhZ2VYT2Zmc2V0XCIsIHNjcm9sbFRvcDogXCJwYWdlWU9mZnNldFwiIH0sIGZ1bmN0aW9uKCBtZXRob2QsIHByb3AgKSB7XG5cdHZhciB0b3AgPSBcInBhZ2VZT2Zmc2V0XCIgPT09IHByb3A7XG5cblx0alF1ZXJ5LmZuWyBtZXRob2QgXSA9IGZ1bmN0aW9uKCB2YWwgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIGVsZW0sIG1ldGhvZCwgdmFsICkge1xuXHRcdFx0dmFyIHdpbiA9IGdldFdpbmRvdyggZWxlbSApO1xuXG5cdFx0XHRpZiAoIHZhbCA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRyZXR1cm4gd2luID8gd2luWyBwcm9wIF0gOiBlbGVtWyBtZXRob2QgXTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB3aW4gKSB7XG5cdFx0XHRcdHdpbi5zY3JvbGxUbyhcblx0XHRcdFx0XHQhdG9wID8gdmFsIDogd2luZG93LnBhZ2VYT2Zmc2V0LFxuXHRcdFx0XHRcdHRvcCA/IHZhbCA6IHdpbmRvdy5wYWdlWU9mZnNldFxuXHRcdFx0XHQpO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRlbGVtWyBtZXRob2QgXSA9IHZhbDtcblx0XHRcdH1cblx0XHR9LCBtZXRob2QsIHZhbCwgYXJndW1lbnRzLmxlbmd0aCwgbnVsbCApO1xuXHR9O1xufSk7XG5cbi8vIFN1cHBvcnQ6IFNhZmFyaTw3KywgQ2hyb21lPDM3K1xuLy8gQWRkIHRoZSB0b3AvbGVmdCBjc3NIb29rcyB1c2luZyBqUXVlcnkuZm4ucG9zaXRpb25cbi8vIFdlYmtpdCBidWc6IGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0yOTA4NFxuLy8gQmxpbmsgYnVnOiBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9MjI5MjgwXG4vLyBnZXRDb21wdXRlZFN0eWxlIHJldHVybnMgcGVyY2VudCB3aGVuIHNwZWNpZmllZCBmb3IgdG9wL2xlZnQvYm90dG9tL3JpZ2h0O1xuLy8gcmF0aGVyIHRoYW4gbWFrZSB0aGUgY3NzIG1vZHVsZSBkZXBlbmQgb24gdGhlIG9mZnNldCBtb2R1bGUsIGp1c3QgY2hlY2sgZm9yIGl0IGhlcmVcbmpRdWVyeS5lYWNoKCBbIFwidG9wXCIsIFwibGVmdFwiIF0sIGZ1bmN0aW9uKCBpLCBwcm9wICkge1xuXHRqUXVlcnkuY3NzSG9va3NbIHByb3AgXSA9IGFkZEdldEhvb2tJZiggc3VwcG9ydC5waXhlbFBvc2l0aW9uLFxuXHRcdGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRcdGlmICggY29tcHV0ZWQgKSB7XG5cdFx0XHRcdGNvbXB1dGVkID0gY3VyQ1NTKCBlbGVtLCBwcm9wICk7XG5cdFx0XHRcdC8vIElmIGN1ckNTUyByZXR1cm5zIHBlcmNlbnRhZ2UsIGZhbGxiYWNrIHRvIG9mZnNldFxuXHRcdFx0XHRyZXR1cm4gcm51bW5vbnB4LnRlc3QoIGNvbXB1dGVkICkgP1xuXHRcdFx0XHRcdGpRdWVyeSggZWxlbSApLnBvc2l0aW9uKClbIHByb3AgXSArIFwicHhcIiA6XG5cdFx0XHRcdFx0Y29tcHV0ZWQ7XG5cdFx0XHR9XG5cdFx0fVxuXHQpO1xufSk7XG5cblxuLy8gQ3JlYXRlIGlubmVySGVpZ2h0LCBpbm5lcldpZHRoLCBoZWlnaHQsIHdpZHRoLCBvdXRlckhlaWdodCBhbmQgb3V0ZXJXaWR0aCBtZXRob2RzXG5qUXVlcnkuZWFjaCggeyBIZWlnaHQ6IFwiaGVpZ2h0XCIsIFdpZHRoOiBcIndpZHRoXCIgfSwgZnVuY3Rpb24oIG5hbWUsIHR5cGUgKSB7XG5cdGpRdWVyeS5lYWNoKCB7IHBhZGRpbmc6IFwiaW5uZXJcIiArIG5hbWUsIGNvbnRlbnQ6IHR5cGUsIFwiXCI6IFwib3V0ZXJcIiArIG5hbWUgfSwgZnVuY3Rpb24oIGRlZmF1bHRFeHRyYSwgZnVuY05hbWUgKSB7XG5cdFx0Ly8gTWFyZ2luIGlzIG9ubHkgZm9yIG91dGVySGVpZ2h0LCBvdXRlcldpZHRoXG5cdFx0alF1ZXJ5LmZuWyBmdW5jTmFtZSBdID0gZnVuY3Rpb24oIG1hcmdpbiwgdmFsdWUgKSB7XG5cdFx0XHR2YXIgY2hhaW5hYmxlID0gYXJndW1lbnRzLmxlbmd0aCAmJiAoIGRlZmF1bHRFeHRyYSB8fCB0eXBlb2YgbWFyZ2luICE9PSBcImJvb2xlYW5cIiApLFxuXHRcdFx0XHRleHRyYSA9IGRlZmF1bHRFeHRyYSB8fCAoIG1hcmdpbiA9PT0gdHJ1ZSB8fCB2YWx1ZSA9PT0gdHJ1ZSA/IFwibWFyZ2luXCIgOiBcImJvcmRlclwiICk7XG5cblx0XHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGZ1bmN0aW9uKCBlbGVtLCB0eXBlLCB2YWx1ZSApIHtcblx0XHRcdFx0dmFyIGRvYztcblxuXHRcdFx0XHRpZiAoIGpRdWVyeS5pc1dpbmRvdyggZWxlbSApICkge1xuXHRcdFx0XHRcdC8vIEFzIG9mIDUvOC8yMDEyIHRoaXMgd2lsbCB5aWVsZCBpbmNvcnJlY3QgcmVzdWx0cyBmb3IgTW9iaWxlIFNhZmFyaSwgYnV0IHRoZXJlXG5cdFx0XHRcdFx0Ly8gaXNuJ3QgYSB3aG9sZSBsb3Qgd2UgY2FuIGRvLiBTZWUgcHVsbCByZXF1ZXN0IGF0IHRoaXMgVVJMIGZvciBkaXNjdXNzaW9uOlxuXHRcdFx0XHRcdC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qcXVlcnkvanF1ZXJ5L3B1bGwvNzY0XG5cdFx0XHRcdFx0cmV0dXJuIGVsZW0uZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50WyBcImNsaWVudFwiICsgbmFtZSBdO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gR2V0IGRvY3VtZW50IHdpZHRoIG9yIGhlaWdodFxuXHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdFx0ZG9jID0gZWxlbS5kb2N1bWVudEVsZW1lbnQ7XG5cblx0XHRcdFx0XHQvLyBFaXRoZXIgc2Nyb2xsW1dpZHRoL0hlaWdodF0gb3Igb2Zmc2V0W1dpZHRoL0hlaWdodF0gb3IgY2xpZW50W1dpZHRoL0hlaWdodF0sXG5cdFx0XHRcdFx0Ly8gd2hpY2hldmVyIGlzIGdyZWF0ZXN0XG5cdFx0XHRcdFx0cmV0dXJuIE1hdGgubWF4KFxuXHRcdFx0XHRcdFx0ZWxlbS5ib2R5WyBcInNjcm9sbFwiICsgbmFtZSBdLCBkb2NbIFwic2Nyb2xsXCIgKyBuYW1lIF0sXG5cdFx0XHRcdFx0XHRlbGVtLmJvZHlbIFwib2Zmc2V0XCIgKyBuYW1lIF0sIGRvY1sgXCJvZmZzZXRcIiArIG5hbWUgXSxcblx0XHRcdFx0XHRcdGRvY1sgXCJjbGllbnRcIiArIG5hbWUgXVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdmFsdWUgPT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdFx0Ly8gR2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudCwgcmVxdWVzdGluZyBidXQgbm90IGZvcmNpbmcgcGFyc2VGbG9hdFxuXHRcdFx0XHRcdGpRdWVyeS5jc3MoIGVsZW0sIHR5cGUsIGV4dHJhICkgOlxuXG5cdFx0XHRcdFx0Ly8gU2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudFxuXHRcdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgdHlwZSwgdmFsdWUsIGV4dHJhICk7XG5cdFx0XHR9LCB0eXBlLCBjaGFpbmFibGUgPyBtYXJnaW4gOiB1bmRlZmluZWQsIGNoYWluYWJsZSwgbnVsbCApO1xuXHRcdH07XG5cdH0pO1xufSk7XG5cblxuLy8gVGhlIG51bWJlciBvZiBlbGVtZW50cyBjb250YWluZWQgaW4gdGhlIG1hdGNoZWQgZWxlbWVudCBzZXRcbmpRdWVyeS5mbi5zaXplID0gZnVuY3Rpb24oKSB7XG5cdHJldHVybiB0aGlzLmxlbmd0aDtcbn07XG5cbmpRdWVyeS5mbi5hbmRTZWxmID0galF1ZXJ5LmZuLmFkZEJhY2s7XG5cblxuXG5cbi8vIFJlZ2lzdGVyIGFzIGEgbmFtZWQgQU1EIG1vZHVsZSwgc2luY2UgalF1ZXJ5IGNhbiBiZSBjb25jYXRlbmF0ZWQgd2l0aCBvdGhlclxuLy8gZmlsZXMgdGhhdCBtYXkgdXNlIGRlZmluZSwgYnV0IG5vdCB2aWEgYSBwcm9wZXIgY29uY2F0ZW5hdGlvbiBzY3JpcHQgdGhhdFxuLy8gdW5kZXJzdGFuZHMgYW5vbnltb3VzIEFNRCBtb2R1bGVzLiBBIG5hbWVkIEFNRCBpcyBzYWZlc3QgYW5kIG1vc3Qgcm9idXN0XG4vLyB3YXkgdG8gcmVnaXN0ZXIuIExvd2VyY2FzZSBqcXVlcnkgaXMgdXNlZCBiZWNhdXNlIEFNRCBtb2R1bGUgbmFtZXMgYXJlXG4vLyBkZXJpdmVkIGZyb20gZmlsZSBuYW1lcywgYW5kIGpRdWVyeSBpcyBub3JtYWxseSBkZWxpdmVyZWQgaW4gYSBsb3dlcmNhc2Vcbi8vIGZpbGUgbmFtZS4gRG8gdGhpcyBhZnRlciBjcmVhdGluZyB0aGUgZ2xvYmFsIHNvIHRoYXQgaWYgYW4gQU1EIG1vZHVsZSB3YW50c1xuLy8gdG8gY2FsbCBub0NvbmZsaWN0IHRvIGhpZGUgdGhpcyB2ZXJzaW9uIG9mIGpRdWVyeSwgaXQgd2lsbCB3b3JrLlxuXG4vLyBOb3RlIHRoYXQgZm9yIG1heGltdW0gcG9ydGFiaWxpdHksIGxpYnJhcmllcyB0aGF0IGFyZSBub3QgalF1ZXJ5IHNob3VsZFxuLy8gZGVjbGFyZSB0aGVtc2VsdmVzIGFzIGFub255bW91cyBtb2R1bGVzLCBhbmQgYXZvaWQgc2V0dGluZyBhIGdsb2JhbCBpZiBhblxuLy8gQU1EIGxvYWRlciBpcyBwcmVzZW50LiBqUXVlcnkgaXMgYSBzcGVjaWFsIGNhc2UuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWVcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qcmJ1cmtlL3JlcXVpcmVqcy93aWtpL1VwZGF0aW5nLWV4aXN0aW5nLWxpYnJhcmllcyN3aWtpLWFub25cblxuaWYgKCB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCApIHtcblx0ZGVmaW5lKCBcImpxdWVyeVwiLCBbXSwgZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGpRdWVyeTtcblx0fSk7XG59XG5cblxuXG5cbnZhclxuXHQvLyBNYXAgb3ZlciBqUXVlcnkgaW4gY2FzZSBvZiBvdmVyd3JpdGVcblx0X2pRdWVyeSA9IHdpbmRvdy5qUXVlcnksXG5cblx0Ly8gTWFwIG92ZXIgdGhlICQgaW4gY2FzZSBvZiBvdmVyd3JpdGVcblx0XyQgPSB3aW5kb3cuJDtcblxualF1ZXJ5Lm5vQ29uZmxpY3QgPSBmdW5jdGlvbiggZGVlcCApIHtcblx0aWYgKCB3aW5kb3cuJCA9PT0galF1ZXJ5ICkge1xuXHRcdHdpbmRvdy4kID0gXyQ7XG5cdH1cblxuXHRpZiAoIGRlZXAgJiYgd2luZG93LmpRdWVyeSA9PT0galF1ZXJ5ICkge1xuXHRcdHdpbmRvdy5qUXVlcnkgPSBfalF1ZXJ5O1xuXHR9XG5cblx0cmV0dXJuIGpRdWVyeTtcbn07XG5cbi8vIEV4cG9zZSBqUXVlcnkgYW5kICQgaWRlbnRpZmllcnMsIGV2ZW4gaW4gQU1EXG4vLyAoIzcxMDIjY29tbWVudDoxMCwgaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9qcXVlcnkvcHVsbC81NTcpXG4vLyBhbmQgQ29tbW9uSlMgZm9yIGJyb3dzZXIgZW11bGF0b3JzICgjMTM1NjYpXG5pZiAoIHR5cGVvZiBub0dsb2JhbCA9PT0gc3RydW5kZWZpbmVkICkge1xuXHR3aW5kb3cualF1ZXJ5ID0gd2luZG93LiQgPSBqUXVlcnk7XG59XG5cblxuXG5cbnJldHVybiBqUXVlcnk7XG5cbn0pKTtcbiIsIi8qKlxuICogTW9kdWxlIGRlcGVuZGVuY2llcy5cbiAqL1xuXG52YXIgRW1pdHRlciA9IHJlcXVpcmUoJ2VtaXR0ZXInKTtcbnZhciByZWR1Y2UgPSByZXF1aXJlKCdyZWR1Y2UnKTtcblxuLyoqXG4gKiBSb290IHJlZmVyZW5jZSBmb3IgaWZyYW1lcy5cbiAqL1xuXG52YXIgcm9vdCA9ICd1bmRlZmluZWQnID09IHR5cGVvZiB3aW5kb3dcbiAgPyB0aGlzXG4gIDogd2luZG93O1xuXG4vKipcbiAqIE5vb3AuXG4gKi9cblxuZnVuY3Rpb24gbm9vcCgpe307XG5cbi8qKlxuICogQ2hlY2sgaWYgYG9iamAgaXMgYSBob3N0IG9iamVjdCxcbiAqIHdlIGRvbid0IHdhbnQgdG8gc2VyaWFsaXplIHRoZXNlIDopXG4gKlxuICogVE9ETzogZnV0dXJlIHByb29mLCBtb3ZlIHRvIGNvbXBvZW50IGxhbmRcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gaXNIb3N0KG9iaikge1xuICB2YXIgc3RyID0ge30udG9TdHJpbmcuY2FsbChvYmopO1xuXG4gIHN3aXRjaCAoc3RyKSB7XG4gICAgY2FzZSAnW29iamVjdCBGaWxlXSc6XG4gICAgY2FzZSAnW29iamVjdCBCbG9iXSc6XG4gICAgY2FzZSAnW29iamVjdCBGb3JtRGF0YV0nOlxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vKipcbiAqIERldGVybWluZSBYSFIuXG4gKi9cblxuZnVuY3Rpb24gZ2V0WEhSKCkge1xuICBpZiAocm9vdC5YTUxIdHRwUmVxdWVzdFxuICAgICYmICgnZmlsZTonICE9IHJvb3QubG9jYXRpb24ucHJvdG9jb2wgfHwgIXJvb3QuQWN0aXZlWE9iamVjdCkpIHtcbiAgICByZXR1cm4gbmV3IFhNTEh0dHBSZXF1ZXN0O1xuICB9IGVsc2Uge1xuICAgIHRyeSB7IHJldHVybiBuZXcgQWN0aXZlWE9iamVjdCgnTWljcm9zb2Z0LlhNTEhUVFAnKTsgfSBjYXRjaChlKSB7fVxuICAgIHRyeSB7IHJldHVybiBuZXcgQWN0aXZlWE9iamVjdCgnTXN4bWwyLlhNTEhUVFAuNi4wJyk7IH0gY2F0Y2goZSkge31cbiAgICB0cnkgeyByZXR1cm4gbmV3IEFjdGl2ZVhPYmplY3QoJ01zeG1sMi5YTUxIVFRQLjMuMCcpOyB9IGNhdGNoKGUpIHt9XG4gICAgdHJ5IHsgcmV0dXJuIG5ldyBBY3RpdmVYT2JqZWN0KCdNc3htbDIuWE1MSFRUUCcpOyB9IGNhdGNoKGUpIHt9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSwgYWRkZWQgdG8gc3VwcG9ydCBJRS5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc1xuICogQHJldHVybiB7U3RyaW5nfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxudmFyIHRyaW0gPSAnJy50cmltXG4gID8gZnVuY3Rpb24ocykgeyByZXR1cm4gcy50cmltKCk7IH1cbiAgOiBmdW5jdGlvbihzKSB7IHJldHVybiBzLnJlcGxhY2UoLyheXFxzKnxcXHMqJCkvZywgJycpOyB9O1xuXG4vKipcbiAqIENoZWNrIGlmIGBvYmpgIGlzIGFuIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gaXNPYmplY3Qob2JqKSB7XG4gIHJldHVybiBvYmogPT09IE9iamVjdChvYmopO1xufVxuXG4vKipcbiAqIFNlcmlhbGl6ZSB0aGUgZ2l2ZW4gYG9iamAuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9ialxuICogQHJldHVybiB7U3RyaW5nfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gc2VyaWFsaXplKG9iaikge1xuICBpZiAoIWlzT2JqZWN0KG9iaikpIHJldHVybiBvYmo7XG4gIHZhciBwYWlycyA9IFtdO1xuICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgaWYgKG51bGwgIT0gb2JqW2tleV0pIHtcbiAgICAgIHBhaXJzLnB1c2goZW5jb2RlVVJJQ29tcG9uZW50KGtleSlcbiAgICAgICAgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQob2JqW2tleV0pKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHBhaXJzLmpvaW4oJyYnKTtcbn1cblxuLyoqXG4gKiBFeHBvc2Ugc2VyaWFsaXphdGlvbiBtZXRob2QuXG4gKi9cblxuIHJlcXVlc3Quc2VyaWFsaXplT2JqZWN0ID0gc2VyaWFsaXplO1xuXG4gLyoqXG4gICogUGFyc2UgdGhlIGdpdmVuIHgtd3d3LWZvcm0tdXJsZW5jb2RlZCBgc3RyYC5cbiAgKlxuICAqIEBwYXJhbSB7U3RyaW5nfSBzdHJcbiAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICogQGFwaSBwcml2YXRlXG4gICovXG5cbmZ1bmN0aW9uIHBhcnNlU3RyaW5nKHN0cikge1xuICB2YXIgb2JqID0ge307XG4gIHZhciBwYWlycyA9IHN0ci5zcGxpdCgnJicpO1xuICB2YXIgcGFydHM7XG4gIHZhciBwYWlyO1xuXG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBwYWlycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICAgIHBhaXIgPSBwYWlyc1tpXTtcbiAgICBwYXJ0cyA9IHBhaXIuc3BsaXQoJz0nKTtcbiAgICBvYmpbZGVjb2RlVVJJQ29tcG9uZW50KHBhcnRzWzBdKV0gPSBkZWNvZGVVUklDb21wb25lbnQocGFydHNbMV0pO1xuICB9XG5cbiAgcmV0dXJuIG9iajtcbn1cblxuLyoqXG4gKiBFeHBvc2UgcGFyc2VyLlxuICovXG5cbnJlcXVlc3QucGFyc2VTdHJpbmcgPSBwYXJzZVN0cmluZztcblxuLyoqXG4gKiBEZWZhdWx0IE1JTUUgdHlwZSBtYXAuXG4gKlxuICogICAgIHN1cGVyYWdlbnQudHlwZXMueG1sID0gJ2FwcGxpY2F0aW9uL3htbCc7XG4gKlxuICovXG5cbnJlcXVlc3QudHlwZXMgPSB7XG4gIGh0bWw6ICd0ZXh0L2h0bWwnLFxuICBqc29uOiAnYXBwbGljYXRpb24vanNvbicsXG4gIHhtbDogJ2FwcGxpY2F0aW9uL3htbCcsXG4gIHVybGVuY29kZWQ6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAnZm9ybSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAnZm9ybS1kYXRhJzogJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCdcbn07XG5cbi8qKlxuICogRGVmYXVsdCBzZXJpYWxpemF0aW9uIG1hcC5cbiAqXG4gKiAgICAgc3VwZXJhZ2VudC5zZXJpYWxpemVbJ2FwcGxpY2F0aW9uL3htbCddID0gZnVuY3Rpb24ob2JqKXtcbiAqICAgICAgIHJldHVybiAnZ2VuZXJhdGVkIHhtbCBoZXJlJztcbiAqICAgICB9O1xuICpcbiAqL1xuXG4gcmVxdWVzdC5zZXJpYWxpemUgPSB7XG4gICAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJzogc2VyaWFsaXplLFxuICAgJ2FwcGxpY2F0aW9uL2pzb24nOiBKU09OLnN0cmluZ2lmeVxuIH07XG5cbiAvKipcbiAgKiBEZWZhdWx0IHBhcnNlcnMuXG4gICpcbiAgKiAgICAgc3VwZXJhZ2VudC5wYXJzZVsnYXBwbGljYXRpb24veG1sJ10gPSBmdW5jdGlvbihzdHIpe1xuICAqICAgICAgIHJldHVybiB7IG9iamVjdCBwYXJzZWQgZnJvbSBzdHIgfTtcbiAgKiAgICAgfTtcbiAgKlxuICAqL1xuXG5yZXF1ZXN0LnBhcnNlID0ge1xuICAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJzogcGFyc2VTdHJpbmcsXG4gICdhcHBsaWNhdGlvbi9qc29uJzogSlNPTi5wYXJzZVxufTtcblxuLyoqXG4gKiBQYXJzZSB0aGUgZ2l2ZW4gaGVhZGVyIGBzdHJgIGludG9cbiAqIGFuIG9iamVjdCBjb250YWluaW5nIHRoZSBtYXBwZWQgZmllbGRzLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge09iamVjdH1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIHBhcnNlSGVhZGVyKHN0cikge1xuICB2YXIgbGluZXMgPSBzdHIuc3BsaXQoL1xccj9cXG4vKTtcbiAgdmFyIGZpZWxkcyA9IHt9O1xuICB2YXIgaW5kZXg7XG4gIHZhciBsaW5lO1xuICB2YXIgZmllbGQ7XG4gIHZhciB2YWw7XG5cbiAgbGluZXMucG9wKCk7IC8vIHRyYWlsaW5nIENSTEZcblxuICBmb3IgKHZhciBpID0gMCwgbGVuID0gbGluZXMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcbiAgICBsaW5lID0gbGluZXNbaV07XG4gICAgaW5kZXggPSBsaW5lLmluZGV4T2YoJzonKTtcbiAgICBmaWVsZCA9IGxpbmUuc2xpY2UoMCwgaW5kZXgpLnRvTG93ZXJDYXNlKCk7XG4gICAgdmFsID0gdHJpbShsaW5lLnNsaWNlKGluZGV4ICsgMSkpO1xuICAgIGZpZWxkc1tmaWVsZF0gPSB2YWw7XG4gIH1cblxuICByZXR1cm4gZmllbGRzO1xufVxuXG4vKipcbiAqIFJldHVybiB0aGUgbWltZSB0eXBlIGZvciB0aGUgZ2l2ZW4gYHN0cmAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHN0clxuICogQHJldHVybiB7U3RyaW5nfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gdHlwZShzdHIpe1xuICByZXR1cm4gc3RyLnNwbGl0KC8gKjsgKi8pLnNoaWZ0KCk7XG59O1xuXG4vKipcbiAqIFJldHVybiBoZWFkZXIgZmllbGQgcGFyYW1ldGVycy5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyXG4gKiBAcmV0dXJuIHtPYmplY3R9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBwYXJhbXMoc3RyKXtcbiAgcmV0dXJuIHJlZHVjZShzdHIuc3BsaXQoLyAqOyAqLyksIGZ1bmN0aW9uKG9iaiwgc3RyKXtcbiAgICB2YXIgcGFydHMgPSBzdHIuc3BsaXQoLyAqPSAqLylcbiAgICAgICwga2V5ID0gcGFydHMuc2hpZnQoKVxuICAgICAgLCB2YWwgPSBwYXJ0cy5zaGlmdCgpO1xuXG4gICAgaWYgKGtleSAmJiB2YWwpIG9ialtrZXldID0gdmFsO1xuICAgIHJldHVybiBvYmo7XG4gIH0sIHt9KTtcbn07XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBhIG5ldyBgUmVzcG9uc2VgIHdpdGggdGhlIGdpdmVuIGB4aHJgLlxuICpcbiAqICAtIHNldCBmbGFncyAoLm9rLCAuZXJyb3IsIGV0YylcbiAqICAtIHBhcnNlIGhlYWRlclxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICBBbGlhc2luZyBgc3VwZXJhZ2VudGAgYXMgYHJlcXVlc3RgIGlzIG5pY2U6XG4gKlxuICogICAgICByZXF1ZXN0ID0gc3VwZXJhZ2VudDtcbiAqXG4gKiAgV2UgY2FuIHVzZSB0aGUgcHJvbWlzZS1saWtlIEFQSSwgb3IgcGFzcyBjYWxsYmFja3M6XG4gKlxuICogICAgICByZXF1ZXN0LmdldCgnLycpLmVuZChmdW5jdGlvbihyZXMpe30pO1xuICogICAgICByZXF1ZXN0LmdldCgnLycsIGZ1bmN0aW9uKHJlcyl7fSk7XG4gKlxuICogIFNlbmRpbmcgZGF0YSBjYW4gYmUgY2hhaW5lZDpcbiAqXG4gKiAgICAgIHJlcXVlc3RcbiAqICAgICAgICAucG9zdCgnL3VzZXInKVxuICogICAgICAgIC5zZW5kKHsgbmFtZTogJ3RqJyB9KVxuICogICAgICAgIC5lbmQoZnVuY3Rpb24ocmVzKXt9KTtcbiAqXG4gKiAgT3IgcGFzc2VkIHRvIGAuc2VuZCgpYDpcbiAqXG4gKiAgICAgIHJlcXVlc3RcbiAqICAgICAgICAucG9zdCgnL3VzZXInKVxuICogICAgICAgIC5zZW5kKHsgbmFtZTogJ3RqJyB9LCBmdW5jdGlvbihyZXMpe30pO1xuICpcbiAqICBPciBwYXNzZWQgdG8gYC5wb3N0KClgOlxuICpcbiAqICAgICAgcmVxdWVzdFxuICogICAgICAgIC5wb3N0KCcvdXNlcicsIHsgbmFtZTogJ3RqJyB9KVxuICogICAgICAgIC5lbmQoZnVuY3Rpb24ocmVzKXt9KTtcbiAqXG4gKiBPciBmdXJ0aGVyIHJlZHVjZWQgdG8gYSBzaW5nbGUgY2FsbCBmb3Igc2ltcGxlIGNhc2VzOlxuICpcbiAqICAgICAgcmVxdWVzdFxuICogICAgICAgIC5wb3N0KCcvdXNlcicsIHsgbmFtZTogJ3RqJyB9LCBmdW5jdGlvbihyZXMpe30pO1xuICpcbiAqIEBwYXJhbSB7WE1MSFRUUFJlcXVlc3R9IHhoclxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIFJlc3BvbnNlKHJlcSwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgdGhpcy5yZXEgPSByZXE7XG4gIHRoaXMueGhyID0gdGhpcy5yZXEueGhyO1xuICB0aGlzLnRleHQgPSB0aGlzLnJlcS5tZXRob2QgIT0nSEVBRCcgXG4gICAgID8gdGhpcy54aHIucmVzcG9uc2VUZXh0IFxuICAgICA6IG51bGw7XG4gIHRoaXMuc2V0U3RhdHVzUHJvcGVydGllcyh0aGlzLnhoci5zdGF0dXMpO1xuICB0aGlzLmhlYWRlciA9IHRoaXMuaGVhZGVycyA9IHBhcnNlSGVhZGVyKHRoaXMueGhyLmdldEFsbFJlc3BvbnNlSGVhZGVycygpKTtcbiAgLy8gZ2V0QWxsUmVzcG9uc2VIZWFkZXJzIHNvbWV0aW1lcyBmYWxzZWx5IHJldHVybnMgXCJcIiBmb3IgQ09SUyByZXF1ZXN0cywgYnV0XG4gIC8vIGdldFJlc3BvbnNlSGVhZGVyIHN0aWxsIHdvcmtzLiBzbyB3ZSBnZXQgY29udGVudC10eXBlIGV2ZW4gaWYgZ2V0dGluZ1xuICAvLyBvdGhlciBoZWFkZXJzIGZhaWxzLlxuICB0aGlzLmhlYWRlclsnY29udGVudC10eXBlJ10gPSB0aGlzLnhoci5nZXRSZXNwb25zZUhlYWRlcignY29udGVudC10eXBlJyk7XG4gIHRoaXMuc2V0SGVhZGVyUHJvcGVydGllcyh0aGlzLmhlYWRlcik7XG4gIHRoaXMuYm9keSA9IHRoaXMucmVxLm1ldGhvZCAhPSAnSEVBRCdcbiAgICA/IHRoaXMucGFyc2VCb2R5KHRoaXMudGV4dClcbiAgICA6IG51bGw7XG59XG5cbi8qKlxuICogR2V0IGNhc2UtaW5zZW5zaXRpdmUgYGZpZWxkYCB2YWx1ZS5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZmllbGRcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVzcG9uc2UucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uKGZpZWxkKXtcbiAgcmV0dXJuIHRoaXMuaGVhZGVyW2ZpZWxkLnRvTG93ZXJDYXNlKCldO1xufTtcblxuLyoqXG4gKiBTZXQgaGVhZGVyIHJlbGF0ZWQgcHJvcGVydGllczpcbiAqXG4gKiAgIC0gYC50eXBlYCB0aGUgY29udGVudCB0eXBlIHdpdGhvdXQgcGFyYW1zXG4gKlxuICogQSByZXNwb25zZSBvZiBcIkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOFwiXG4gKiB3aWxsIHByb3ZpZGUgeW91IHdpdGggYSBgLnR5cGVgIG9mIFwidGV4dC9wbGFpblwiLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBoZWFkZXJcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cblJlc3BvbnNlLnByb3RvdHlwZS5zZXRIZWFkZXJQcm9wZXJ0aWVzID0gZnVuY3Rpb24oaGVhZGVyKXtcbiAgLy8gY29udGVudC10eXBlXG4gIHZhciBjdCA9IHRoaXMuaGVhZGVyWydjb250ZW50LXR5cGUnXSB8fCAnJztcbiAgdGhpcy50eXBlID0gdHlwZShjdCk7XG5cbiAgLy8gcGFyYW1zXG4gIHZhciBvYmogPSBwYXJhbXMoY3QpO1xuICBmb3IgKHZhciBrZXkgaW4gb2JqKSB0aGlzW2tleV0gPSBvYmpba2V5XTtcbn07XG5cbi8qKlxuICogUGFyc2UgdGhlIGdpdmVuIGJvZHkgYHN0cmAuXG4gKlxuICogVXNlZCBmb3IgYXV0by1wYXJzaW5nIG9mIGJvZGllcy4gUGFyc2Vyc1xuICogYXJlIGRlZmluZWQgb24gdGhlIGBzdXBlcmFnZW50LnBhcnNlYCBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHN0clxuICogQHJldHVybiB7TWl4ZWR9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5SZXNwb25zZS5wcm90b3R5cGUucGFyc2VCb2R5ID0gZnVuY3Rpb24oc3RyKXtcbiAgdmFyIHBhcnNlID0gcmVxdWVzdC5wYXJzZVt0aGlzLnR5cGVdO1xuICByZXR1cm4gcGFyc2UgJiYgc3RyICYmIHN0ci5sZW5ndGhcbiAgICA/IHBhcnNlKHN0cilcbiAgICA6IG51bGw7XG59O1xuXG4vKipcbiAqIFNldCBmbGFncyBzdWNoIGFzIGAub2tgIGJhc2VkIG9uIGBzdGF0dXNgLlxuICpcbiAqIEZvciBleGFtcGxlIGEgMnh4IHJlc3BvbnNlIHdpbGwgZ2l2ZSB5b3UgYSBgLm9rYCBvZiBfX3RydWVfX1xuICogd2hlcmVhcyA1eHggd2lsbCBiZSBfX2ZhbHNlX18gYW5kIGAuZXJyb3JgIHdpbGwgYmUgX190cnVlX18uIFRoZVxuICogYC5jbGllbnRFcnJvcmAgYW5kIGAuc2VydmVyRXJyb3JgIGFyZSBhbHNvIGF2YWlsYWJsZSB0byBiZSBtb3JlXG4gKiBzcGVjaWZpYywgYW5kIGAuc3RhdHVzVHlwZWAgaXMgdGhlIGNsYXNzIG9mIGVycm9yIHJhbmdpbmcgZnJvbSAxLi41XG4gKiBzb21ldGltZXMgdXNlZnVsIGZvciBtYXBwaW5nIHJlc3BvbmQgY29sb3JzIGV0Yy5cbiAqXG4gKiBcInN1Z2FyXCIgcHJvcGVydGllcyBhcmUgYWxzbyBkZWZpbmVkIGZvciBjb21tb24gY2FzZXMuIEN1cnJlbnRseSBwcm92aWRpbmc6XG4gKlxuICogICAtIC5ub0NvbnRlbnRcbiAqICAgLSAuYmFkUmVxdWVzdFxuICogICAtIC51bmF1dGhvcml6ZWRcbiAqICAgLSAubm90QWNjZXB0YWJsZVxuICogICAtIC5ub3RGb3VuZFxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdGF0dXNcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cblJlc3BvbnNlLnByb3RvdHlwZS5zZXRTdGF0dXNQcm9wZXJ0aWVzID0gZnVuY3Rpb24oc3RhdHVzKXtcbiAgdmFyIHR5cGUgPSBzdGF0dXMgLyAxMDAgfCAwO1xuXG4gIC8vIHN0YXR1cyAvIGNsYXNzXG4gIHRoaXMuc3RhdHVzID0gc3RhdHVzO1xuICB0aGlzLnN0YXR1c1R5cGUgPSB0eXBlO1xuXG4gIC8vIGJhc2ljc1xuICB0aGlzLmluZm8gPSAxID09IHR5cGU7XG4gIHRoaXMub2sgPSAyID09IHR5cGU7XG4gIHRoaXMuY2xpZW50RXJyb3IgPSA0ID09IHR5cGU7XG4gIHRoaXMuc2VydmVyRXJyb3IgPSA1ID09IHR5cGU7XG4gIHRoaXMuZXJyb3IgPSAoNCA9PSB0eXBlIHx8IDUgPT0gdHlwZSlcbiAgICA/IHRoaXMudG9FcnJvcigpXG4gICAgOiBmYWxzZTtcblxuICAvLyBzdWdhclxuICB0aGlzLmFjY2VwdGVkID0gMjAyID09IHN0YXR1cztcbiAgdGhpcy5ub0NvbnRlbnQgPSAyMDQgPT0gc3RhdHVzIHx8IDEyMjMgPT0gc3RhdHVzO1xuICB0aGlzLmJhZFJlcXVlc3QgPSA0MDAgPT0gc3RhdHVzO1xuICB0aGlzLnVuYXV0aG9yaXplZCA9IDQwMSA9PSBzdGF0dXM7XG4gIHRoaXMubm90QWNjZXB0YWJsZSA9IDQwNiA9PSBzdGF0dXM7XG4gIHRoaXMubm90Rm91bmQgPSA0MDQgPT0gc3RhdHVzO1xuICB0aGlzLmZvcmJpZGRlbiA9IDQwMyA9PSBzdGF0dXM7XG59O1xuXG4vKipcbiAqIFJldHVybiBhbiBgRXJyb3JgIHJlcHJlc2VudGF0aXZlIG9mIHRoaXMgcmVzcG9uc2UuXG4gKlxuICogQHJldHVybiB7RXJyb3J9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlc3BvbnNlLnByb3RvdHlwZS50b0Vycm9yID0gZnVuY3Rpb24oKXtcbiAgdmFyIHJlcSA9IHRoaXMucmVxO1xuICB2YXIgbWV0aG9kID0gcmVxLm1ldGhvZDtcbiAgdmFyIHVybCA9IHJlcS51cmw7XG5cbiAgdmFyIG1zZyA9ICdjYW5ub3QgJyArIG1ldGhvZCArICcgJyArIHVybCArICcgKCcgKyB0aGlzLnN0YXR1cyArICcpJztcbiAgdmFyIGVyciA9IG5ldyBFcnJvcihtc2cpO1xuICBlcnIuc3RhdHVzID0gdGhpcy5zdGF0dXM7XG4gIGVyci5tZXRob2QgPSBtZXRob2Q7XG4gIGVyci51cmwgPSB1cmw7XG5cbiAgcmV0dXJuIGVycjtcbn07XG5cbi8qKlxuICogRXhwb3NlIGBSZXNwb25zZWAuXG4gKi9cblxucmVxdWVzdC5SZXNwb25zZSA9IFJlc3BvbnNlO1xuXG4vKipcbiAqIEluaXRpYWxpemUgYSBuZXcgYFJlcXVlc3RgIHdpdGggdGhlIGdpdmVuIGBtZXRob2RgIGFuZCBgdXJsYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kXG4gKiBAcGFyYW0ge1N0cmluZ30gdXJsXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIFJlcXVlc3QobWV0aG9kLCB1cmwpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICBFbWl0dGVyLmNhbGwodGhpcyk7XG4gIHRoaXMuX3F1ZXJ5ID0gdGhpcy5fcXVlcnkgfHwgW107XG4gIHRoaXMubWV0aG9kID0gbWV0aG9kO1xuICB0aGlzLnVybCA9IHVybDtcbiAgdGhpcy5oZWFkZXIgPSB7fTtcbiAgdGhpcy5faGVhZGVyID0ge307XG4gIHRoaXMub24oJ2VuZCcsIGZ1bmN0aW9uKCl7XG4gICAgdmFyIGVyciA9IG51bGw7XG4gICAgdmFyIHJlcyA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgcmVzID0gbmV3IFJlc3BvbnNlKHNlbGYpOyBcbiAgICB9IGNhdGNoKGUpIHtcbiAgICAgIGVyciA9IG5ldyBFcnJvcignUGFyc2VyIGlzIHVuYWJsZSB0byBwYXJzZSB0aGUgcmVzcG9uc2UnKTtcbiAgICAgIGVyci5wYXJzZSA9IHRydWU7XG4gICAgICBlcnIub3JpZ2luYWwgPSBlO1xuICAgIH1cblxuICAgIHNlbGYuY2FsbGJhY2soZXJyLCByZXMpO1xuICB9KTtcbn1cblxuLyoqXG4gKiBNaXhpbiBgRW1pdHRlcmAuXG4gKi9cblxuRW1pdHRlcihSZXF1ZXN0LnByb3RvdHlwZSk7XG5cbi8qKlxuICogQWxsb3cgZm9yIGV4dGVuc2lvblxuICovXG5cblJlcXVlc3QucHJvdG90eXBlLnVzZSA9IGZ1bmN0aW9uKGZuKSB7XG4gIGZuKHRoaXMpO1xuICByZXR1cm4gdGhpcztcbn1cblxuLyoqXG4gKiBTZXQgdGltZW91dCB0byBgbXNgLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBtc1xuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLnRpbWVvdXQgPSBmdW5jdGlvbihtcyl7XG4gIHRoaXMuX3RpbWVvdXQgPSBtcztcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIENsZWFyIHByZXZpb3VzIHRpbWVvdXQuXG4gKlxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLmNsZWFyVGltZW91dCA9IGZ1bmN0aW9uKCl7XG4gIHRoaXMuX3RpbWVvdXQgPSAwO1xuICBjbGVhclRpbWVvdXQodGhpcy5fdGltZXIpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogQWJvcnQgdGhlIHJlcXVlc3QsIGFuZCBjbGVhciBwb3RlbnRpYWwgdGltZW91dC5cbiAqXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS5hYm9ydCA9IGZ1bmN0aW9uKCl7XG4gIGlmICh0aGlzLmFib3J0ZWQpIHJldHVybjtcbiAgdGhpcy5hYm9ydGVkID0gdHJ1ZTtcbiAgdGhpcy54aHIuYWJvcnQoKTtcbiAgdGhpcy5jbGVhclRpbWVvdXQoKTtcbiAgdGhpcy5lbWl0KCdhYm9ydCcpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2V0IGhlYWRlciBgZmllbGRgIHRvIGB2YWxgLCBvciBtdWx0aXBsZSBmaWVsZHMgd2l0aCBvbmUgb2JqZWN0LlxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgICAgcmVxLmdldCgnLycpXG4gKiAgICAgICAgLnNldCgnQWNjZXB0JywgJ2FwcGxpY2F0aW9uL2pzb24nKVxuICogICAgICAgIC5zZXQoJ1gtQVBJLUtleScsICdmb29iYXInKVxuICogICAgICAgIC5lbmQoY2FsbGJhY2spO1xuICpcbiAqICAgICAgcmVxLmdldCgnLycpXG4gKiAgICAgICAgLnNldCh7IEFjY2VwdDogJ2FwcGxpY2F0aW9uL2pzb24nLCAnWC1BUEktS2V5JzogJ2Zvb2JhcicgfSlcbiAqICAgICAgICAuZW5kKGNhbGxiYWNrKTtcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R9IGZpZWxkXG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24oZmllbGQsIHZhbCl7XG4gIGlmIChpc09iamVjdChmaWVsZCkpIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gZmllbGQpIHtcbiAgICAgIHRoaXMuc2V0KGtleSwgZmllbGRba2V5XSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIHRoaXMuX2hlYWRlcltmaWVsZC50b0xvd2VyQ2FzZSgpXSA9IHZhbDtcbiAgdGhpcy5oZWFkZXJbZmllbGRdID0gdmFsO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogUmVtb3ZlIGhlYWRlciBgZmllbGRgLlxuICpcbiAqIEV4YW1wbGU6XG4gKlxuICogICAgICByZXEuZ2V0KCcvJylcbiAqICAgICAgICAudW5zZXQoJ1VzZXItQWdlbnQnKVxuICogICAgICAgIC5lbmQoY2FsbGJhY2spO1xuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBmaWVsZFxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLnVuc2V0ID0gZnVuY3Rpb24oZmllbGQpe1xuICBkZWxldGUgdGhpcy5faGVhZGVyW2ZpZWxkLnRvTG93ZXJDYXNlKCldO1xuICBkZWxldGUgdGhpcy5oZWFkZXJbZmllbGRdO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogR2V0IGNhc2UtaW5zZW5zaXRpdmUgaGVhZGVyIGBmaWVsZGAgdmFsdWUuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGZpZWxkXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS5nZXRIZWFkZXIgPSBmdW5jdGlvbihmaWVsZCl7XG4gIHJldHVybiB0aGlzLl9oZWFkZXJbZmllbGQudG9Mb3dlckNhc2UoKV07XG59O1xuXG4vKipcbiAqIFNldCBDb250ZW50LVR5cGUgdG8gYHR5cGVgLCBtYXBwaW5nIHZhbHVlcyBmcm9tIGByZXF1ZXN0LnR5cGVzYC5cbiAqXG4gKiBFeGFtcGxlczpcbiAqXG4gKiAgICAgIHN1cGVyYWdlbnQudHlwZXMueG1sID0gJ2FwcGxpY2F0aW9uL3htbCc7XG4gKlxuICogICAgICByZXF1ZXN0LnBvc3QoJy8nKVxuICogICAgICAgIC50eXBlKCd4bWwnKVxuICogICAgICAgIC5zZW5kKHhtbHN0cmluZylcbiAqICAgICAgICAuZW5kKGNhbGxiYWNrKTtcbiAqXG4gKiAgICAgIHJlcXVlc3QucG9zdCgnLycpXG4gKiAgICAgICAgLnR5cGUoJ2FwcGxpY2F0aW9uL3htbCcpXG4gKiAgICAgICAgLnNlbmQoeG1sc3RyaW5nKVxuICogICAgICAgIC5lbmQoY2FsbGJhY2spO1xuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUudHlwZSA9IGZ1bmN0aW9uKHR5cGUpe1xuICB0aGlzLnNldCgnQ29udGVudC1UeXBlJywgcmVxdWVzdC50eXBlc1t0eXBlXSB8fCB0eXBlKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCBBY2NlcHQgdG8gYHR5cGVgLCBtYXBwaW5nIHZhbHVlcyBmcm9tIGByZXF1ZXN0LnR5cGVzYC5cbiAqXG4gKiBFeGFtcGxlczpcbiAqXG4gKiAgICAgIHN1cGVyYWdlbnQudHlwZXMuanNvbiA9ICdhcHBsaWNhdGlvbi9qc29uJztcbiAqXG4gKiAgICAgIHJlcXVlc3QuZ2V0KCcvYWdlbnQnKVxuICogICAgICAgIC5hY2NlcHQoJ2pzb24nKVxuICogICAgICAgIC5lbmQoY2FsbGJhY2spO1xuICpcbiAqICAgICAgcmVxdWVzdC5nZXQoJy9hZ2VudCcpXG4gKiAgICAgICAgLmFjY2VwdCgnYXBwbGljYXRpb24vanNvbicpXG4gKiAgICAgICAgLmVuZChjYWxsYmFjayk7XG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGFjY2VwdFxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLmFjY2VwdCA9IGZ1bmN0aW9uKHR5cGUpe1xuICB0aGlzLnNldCgnQWNjZXB0JywgcmVxdWVzdC50eXBlc1t0eXBlXSB8fCB0eXBlKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCBBdXRob3JpemF0aW9uIGZpZWxkIHZhbHVlIHdpdGggYHVzZXJgIGFuZCBgcGFzc2AuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHVzZXJcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYXNzXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUuYXV0aCA9IGZ1bmN0aW9uKHVzZXIsIHBhc3Mpe1xuICB2YXIgc3RyID0gYnRvYSh1c2VyICsgJzonICsgcGFzcyk7XG4gIHRoaXMuc2V0KCdBdXRob3JpemF0aW9uJywgJ0Jhc2ljICcgKyBzdHIpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuKiBBZGQgcXVlcnktc3RyaW5nIGB2YWxgLlxuKlxuKiBFeGFtcGxlczpcbipcbiogICByZXF1ZXN0LmdldCgnL3Nob2VzJylcbiogICAgIC5xdWVyeSgnc2l6ZT0xMCcpXG4qICAgICAucXVlcnkoeyBjb2xvcjogJ2JsdWUnIH0pXG4qXG4qIEBwYXJhbSB7T2JqZWN0fFN0cmluZ30gdmFsXG4qIEByZXR1cm4ge1JlcXVlc3R9IGZvciBjaGFpbmluZ1xuKiBAYXBpIHB1YmxpY1xuKi9cblxuUmVxdWVzdC5wcm90b3R5cGUucXVlcnkgPSBmdW5jdGlvbih2YWwpe1xuICBpZiAoJ3N0cmluZycgIT0gdHlwZW9mIHZhbCkgdmFsID0gc2VyaWFsaXplKHZhbCk7XG4gIGlmICh2YWwpIHRoaXMuX3F1ZXJ5LnB1c2godmFsKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFdyaXRlIHRoZSBmaWVsZCBgbmFtZWAgYW5kIGB2YWxgIGZvciBcIm11bHRpcGFydC9mb3JtLWRhdGFcIlxuICogcmVxdWVzdCBib2RpZXMuXG4gKlxuICogYGBgIGpzXG4gKiByZXF1ZXN0LnBvc3QoJy91cGxvYWQnKVxuICogICAuZmllbGQoJ2ZvbycsICdiYXInKVxuICogICAuZW5kKGNhbGxiYWNrKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gKiBAcGFyYW0ge1N0cmluZ3xCbG9ifEZpbGV9IHZhbFxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLmZpZWxkID0gZnVuY3Rpb24obmFtZSwgdmFsKXtcbiAgaWYgKCF0aGlzLl9mb3JtRGF0YSkgdGhpcy5fZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoKTtcbiAgdGhpcy5fZm9ybURhdGEuYXBwZW5kKG5hbWUsIHZhbCk7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBRdWV1ZSB0aGUgZ2l2ZW4gYGZpbGVgIGFzIGFuIGF0dGFjaG1lbnQgdG8gdGhlIHNwZWNpZmllZCBgZmllbGRgLFxuICogd2l0aCBvcHRpb25hbCBgZmlsZW5hbWVgLlxuICpcbiAqIGBgYCBqc1xuICogcmVxdWVzdC5wb3N0KCcvdXBsb2FkJylcbiAqICAgLmF0dGFjaChuZXcgQmxvYihbJzxhIGlkPVwiYVwiPjxiIGlkPVwiYlwiPmhleSE8L2I+PC9hPiddLCB7IHR5cGU6IFwidGV4dC9odG1sXCJ9KSlcbiAqICAgLmVuZChjYWxsYmFjayk7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZmllbGRcbiAqIEBwYXJhbSB7QmxvYnxGaWxlfSBmaWxlXG4gKiBAcGFyYW0ge1N0cmluZ30gZmlsZW5hbWVcbiAqIEByZXR1cm4ge1JlcXVlc3R9IGZvciBjaGFpbmluZ1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS5hdHRhY2ggPSBmdW5jdGlvbihmaWVsZCwgZmlsZSwgZmlsZW5hbWUpe1xuICBpZiAoIXRoaXMuX2Zvcm1EYXRhKSB0aGlzLl9mb3JtRGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICB0aGlzLl9mb3JtRGF0YS5hcHBlbmQoZmllbGQsIGZpbGUsIGZpbGVuYW1lKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNlbmQgYGRhdGFgLCBkZWZhdWx0aW5nIHRoZSBgLnR5cGUoKWAgdG8gXCJqc29uXCIgd2hlblxuICogYW4gb2JqZWN0IGlzIGdpdmVuLlxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgICAgIC8vIHF1ZXJ5c3RyaW5nXG4gKiAgICAgICByZXF1ZXN0LmdldCgnL3NlYXJjaCcpXG4gKiAgICAgICAgIC5lbmQoY2FsbGJhY2spXG4gKlxuICogICAgICAgLy8gbXVsdGlwbGUgZGF0YSBcIndyaXRlc1wiXG4gKiAgICAgICByZXF1ZXN0LmdldCgnL3NlYXJjaCcpXG4gKiAgICAgICAgIC5zZW5kKHsgc2VhcmNoOiAncXVlcnknIH0pXG4gKiAgICAgICAgIC5zZW5kKHsgcmFuZ2U6ICcxLi41JyB9KVxuICogICAgICAgICAuc2VuZCh7IG9yZGVyOiAnZGVzYycgfSlcbiAqICAgICAgICAgLmVuZChjYWxsYmFjaylcbiAqXG4gKiAgICAgICAvLyBtYW51YWwganNvblxuICogICAgICAgcmVxdWVzdC5wb3N0KCcvdXNlcicpXG4gKiAgICAgICAgIC50eXBlKCdqc29uJylcbiAqICAgICAgICAgLnNlbmQoJ3tcIm5hbWVcIjpcInRqXCJ9KVxuICogICAgICAgICAuZW5kKGNhbGxiYWNrKVxuICpcbiAqICAgICAgIC8vIGF1dG8ganNvblxuICogICAgICAgcmVxdWVzdC5wb3N0KCcvdXNlcicpXG4gKiAgICAgICAgIC5zZW5kKHsgbmFtZTogJ3RqJyB9KVxuICogICAgICAgICAuZW5kKGNhbGxiYWNrKVxuICpcbiAqICAgICAgIC8vIG1hbnVhbCB4LXd3dy1mb3JtLXVybGVuY29kZWRcbiAqICAgICAgIHJlcXVlc3QucG9zdCgnL3VzZXInKVxuICogICAgICAgICAudHlwZSgnZm9ybScpXG4gKiAgICAgICAgIC5zZW5kKCduYW1lPXRqJylcbiAqICAgICAgICAgLmVuZChjYWxsYmFjaylcbiAqXG4gKiAgICAgICAvLyBhdXRvIHgtd3d3LWZvcm0tdXJsZW5jb2RlZFxuICogICAgICAgcmVxdWVzdC5wb3N0KCcvdXNlcicpXG4gKiAgICAgICAgIC50eXBlKCdmb3JtJylcbiAqICAgICAgICAgLnNlbmQoeyBuYW1lOiAndGonIH0pXG4gKiAgICAgICAgIC5lbmQoY2FsbGJhY2spXG4gKlxuICogICAgICAgLy8gZGVmYXVsdHMgdG8geC13d3ctZm9ybS11cmxlbmNvZGVkXG4gICogICAgICByZXF1ZXN0LnBvc3QoJy91c2VyJylcbiAgKiAgICAgICAgLnNlbmQoJ25hbWU9dG9iaScpXG4gICogICAgICAgIC5zZW5kKCdzcGVjaWVzPWZlcnJldCcpXG4gICogICAgICAgIC5lbmQoY2FsbGJhY2spXG4gKlxuICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fSBkYXRhXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUuc2VuZCA9IGZ1bmN0aW9uKGRhdGEpe1xuICB2YXIgb2JqID0gaXNPYmplY3QoZGF0YSk7XG4gIHZhciB0eXBlID0gdGhpcy5nZXRIZWFkZXIoJ0NvbnRlbnQtVHlwZScpO1xuXG4gIC8vIG1lcmdlXG4gIGlmIChvYmogJiYgaXNPYmplY3QodGhpcy5fZGF0YSkpIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gZGF0YSkge1xuICAgICAgdGhpcy5fZGF0YVtrZXldID0gZGF0YVtrZXldO1xuICAgIH1cbiAgfSBlbHNlIGlmICgnc3RyaW5nJyA9PSB0eXBlb2YgZGF0YSkge1xuICAgIGlmICghdHlwZSkgdGhpcy50eXBlKCdmb3JtJyk7XG4gICAgdHlwZSA9IHRoaXMuZ2V0SGVhZGVyKCdDb250ZW50LVR5cGUnKTtcbiAgICBpZiAoJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcgPT0gdHlwZSkge1xuICAgICAgdGhpcy5fZGF0YSA9IHRoaXMuX2RhdGFcbiAgICAgICAgPyB0aGlzLl9kYXRhICsgJyYnICsgZGF0YVxuICAgICAgICA6IGRhdGE7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2RhdGEgPSAodGhpcy5fZGF0YSB8fCAnJykgKyBkYXRhO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aGlzLl9kYXRhID0gZGF0YTtcbiAgfVxuXG4gIGlmICghb2JqKSByZXR1cm4gdGhpcztcbiAgaWYgKCF0eXBlKSB0aGlzLnR5cGUoJ2pzb24nKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIEludm9rZSB0aGUgY2FsbGJhY2sgd2l0aCBgZXJyYCBhbmQgYHJlc2BcbiAqIGFuZCBoYW5kbGUgYXJpdHkgY2hlY2suXG4gKlxuICogQHBhcmFtIHtFcnJvcn0gZXJyXG4gKiBAcGFyYW0ge1Jlc3BvbnNlfSByZXNcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cblJlcXVlc3QucHJvdG90eXBlLmNhbGxiYWNrID0gZnVuY3Rpb24oZXJyLCByZXMpe1xuICB2YXIgZm4gPSB0aGlzLl9jYWxsYmFjaztcbiAgdGhpcy5jbGVhclRpbWVvdXQoKTtcbiAgaWYgKDIgPT0gZm4ubGVuZ3RoKSByZXR1cm4gZm4oZXJyLCByZXMpO1xuICBpZiAoZXJyKSByZXR1cm4gdGhpcy5lbWl0KCdlcnJvcicsIGVycik7XG4gIGZuKHJlcyk7XG59O1xuXG4vKipcbiAqIEludm9rZSBjYWxsYmFjayB3aXRoIHgtZG9tYWluIGVycm9yLlxuICpcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cblJlcXVlc3QucHJvdG90eXBlLmNyb3NzRG9tYWluRXJyb3IgPSBmdW5jdGlvbigpe1xuICB2YXIgZXJyID0gbmV3IEVycm9yKCdPcmlnaW4gaXMgbm90IGFsbG93ZWQgYnkgQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJyk7XG4gIGVyci5jcm9zc0RvbWFpbiA9IHRydWU7XG4gIHRoaXMuY2FsbGJhY2soZXJyKTtcbn07XG5cbi8qKlxuICogSW52b2tlIGNhbGxiYWNrIHdpdGggdGltZW91dCBlcnJvci5cbiAqXG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS50aW1lb3V0RXJyb3IgPSBmdW5jdGlvbigpe1xuICB2YXIgdGltZW91dCA9IHRoaXMuX3RpbWVvdXQ7XG4gIHZhciBlcnIgPSBuZXcgRXJyb3IoJ3RpbWVvdXQgb2YgJyArIHRpbWVvdXQgKyAnbXMgZXhjZWVkZWQnKTtcbiAgZXJyLnRpbWVvdXQgPSB0aW1lb3V0O1xuICB0aGlzLmNhbGxiYWNrKGVycik7XG59O1xuXG4vKipcbiAqIEVuYWJsZSB0cmFuc21pc3Npb24gb2YgY29va2llcyB3aXRoIHgtZG9tYWluIHJlcXVlc3RzLlxuICpcbiAqIE5vdGUgdGhhdCBmb3IgdGhpcyB0byB3b3JrIHRoZSBvcmlnaW4gbXVzdCBub3QgYmVcbiAqIHVzaW5nIFwiQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luXCIgd2l0aCBhIHdpbGRjYXJkLFxuICogYW5kIGFsc28gbXVzdCBzZXQgXCJBY2Nlc3MtQ29udHJvbC1BbGxvdy1DcmVkZW50aWFsc1wiXG4gKiB0byBcInRydWVcIi5cbiAqXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLndpdGhDcmVkZW50aWFscyA9IGZ1bmN0aW9uKCl7XG4gIHRoaXMuX3dpdGhDcmVkZW50aWFscyA9IHRydWU7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBJbml0aWF0ZSByZXF1ZXN0LCBpbnZva2luZyBjYWxsYmFjayBgZm4ocmVzKWBcbiAqIHdpdGggYW4gaW5zdGFuY2VvZiBgUmVzcG9uc2VgLlxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUuZW5kID0gZnVuY3Rpb24oZm4pe1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciB4aHIgPSB0aGlzLnhociA9IGdldFhIUigpO1xuICB2YXIgcXVlcnkgPSB0aGlzLl9xdWVyeS5qb2luKCcmJyk7XG4gIHZhciB0aW1lb3V0ID0gdGhpcy5fdGltZW91dDtcbiAgdmFyIGRhdGEgPSB0aGlzLl9mb3JtRGF0YSB8fCB0aGlzLl9kYXRhO1xuXG4gIC8vIHN0b3JlIGNhbGxiYWNrXG4gIHRoaXMuX2NhbGxiYWNrID0gZm4gfHwgbm9vcDtcblxuICAvLyBzdGF0ZSBjaGFuZ2VcbiAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCl7XG4gICAgaWYgKDQgIT0geGhyLnJlYWR5U3RhdGUpIHJldHVybjtcbiAgICBpZiAoMCA9PSB4aHIuc3RhdHVzKSB7XG4gICAgICBpZiAoc2VsZi5hYm9ydGVkKSByZXR1cm4gc2VsZi50aW1lb3V0RXJyb3IoKTtcbiAgICAgIHJldHVybiBzZWxmLmNyb3NzRG9tYWluRXJyb3IoKTtcbiAgICB9XG4gICAgc2VsZi5lbWl0KCdlbmQnKTtcbiAgfTtcblxuICAvLyBwcm9ncmVzc1xuICBpZiAoeGhyLnVwbG9hZCkge1xuICAgIHhoci51cGxvYWQub25wcm9ncmVzcyA9IGZ1bmN0aW9uKGUpe1xuICAgICAgZS5wZXJjZW50ID0gZS5sb2FkZWQgLyBlLnRvdGFsICogMTAwO1xuICAgICAgc2VsZi5lbWl0KCdwcm9ncmVzcycsIGUpO1xuICAgIH07XG4gIH1cblxuICAvLyB0aW1lb3V0XG4gIGlmICh0aW1lb3V0ICYmICF0aGlzLl90aW1lcikge1xuICAgIHRoaXMuX3RpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgc2VsZi5hYm9ydCgpO1xuICAgIH0sIHRpbWVvdXQpO1xuICB9XG5cbiAgLy8gcXVlcnlzdHJpbmdcbiAgaWYgKHF1ZXJ5KSB7XG4gICAgcXVlcnkgPSByZXF1ZXN0LnNlcmlhbGl6ZU9iamVjdChxdWVyeSk7XG4gICAgdGhpcy51cmwgKz0gfnRoaXMudXJsLmluZGV4T2YoJz8nKVxuICAgICAgPyAnJicgKyBxdWVyeVxuICAgICAgOiAnPycgKyBxdWVyeTtcbiAgfVxuXG4gIC8vIGluaXRpYXRlIHJlcXVlc3RcbiAgeGhyLm9wZW4odGhpcy5tZXRob2QsIHRoaXMudXJsLCB0cnVlKTtcblxuICAvLyBDT1JTXG4gIGlmICh0aGlzLl93aXRoQ3JlZGVudGlhbHMpIHhoci53aXRoQ3JlZGVudGlhbHMgPSB0cnVlO1xuXG4gIC8vIGJvZHlcbiAgaWYgKCdHRVQnICE9IHRoaXMubWV0aG9kICYmICdIRUFEJyAhPSB0aGlzLm1ldGhvZCAmJiAnc3RyaW5nJyAhPSB0eXBlb2YgZGF0YSAmJiAhaXNIb3N0KGRhdGEpKSB7XG4gICAgLy8gc2VyaWFsaXplIHN0dWZmXG4gICAgdmFyIHNlcmlhbGl6ZSA9IHJlcXVlc3Quc2VyaWFsaXplW3RoaXMuZ2V0SGVhZGVyKCdDb250ZW50LVR5cGUnKV07XG4gICAgaWYgKHNlcmlhbGl6ZSkgZGF0YSA9IHNlcmlhbGl6ZShkYXRhKTtcbiAgfVxuXG4gIC8vIHNldCBoZWFkZXIgZmllbGRzXG4gIGZvciAodmFyIGZpZWxkIGluIHRoaXMuaGVhZGVyKSB7XG4gICAgaWYgKG51bGwgPT0gdGhpcy5oZWFkZXJbZmllbGRdKSBjb250aW51ZTtcbiAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihmaWVsZCwgdGhpcy5oZWFkZXJbZmllbGRdKTtcbiAgfVxuXG4gIC8vIHNlbmQgc3R1ZmZcbiAgdGhpcy5lbWl0KCdyZXF1ZXN0JywgdGhpcyk7XG4gIHhoci5zZW5kKGRhdGEpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogRXhwb3NlIGBSZXF1ZXN0YC5cbiAqL1xuXG5yZXF1ZXN0LlJlcXVlc3QgPSBSZXF1ZXN0O1xuXG4vKipcbiAqIElzc3VlIGEgcmVxdWVzdDpcbiAqXG4gKiBFeGFtcGxlczpcbiAqXG4gKiAgICByZXF1ZXN0KCdHRVQnLCAnL3VzZXJzJykuZW5kKGNhbGxiYWNrKVxuICogICAgcmVxdWVzdCgnL3VzZXJzJykuZW5kKGNhbGxiYWNrKVxuICogICAgcmVxdWVzdCgnL3VzZXJzJywgY2FsbGJhY2spXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZFxuICogQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IHVybCBvciBjYWxsYmFja1xuICogQHJldHVybiB7UmVxdWVzdH1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gcmVxdWVzdChtZXRob2QsIHVybCkge1xuICAvLyBjYWxsYmFja1xuICBpZiAoJ2Z1bmN0aW9uJyA9PSB0eXBlb2YgdXJsKSB7XG4gICAgcmV0dXJuIG5ldyBSZXF1ZXN0KCdHRVQnLCBtZXRob2QpLmVuZCh1cmwpO1xuICB9XG5cbiAgLy8gdXJsIGZpcnN0XG4gIGlmICgxID09IGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICByZXR1cm4gbmV3IFJlcXVlc3QoJ0dFVCcsIG1ldGhvZCk7XG4gIH1cblxuICByZXR1cm4gbmV3IFJlcXVlc3QobWV0aG9kLCB1cmwpO1xufVxuXG4vKipcbiAqIEdFVCBgdXJsYCB3aXRoIG9wdGlvbmFsIGNhbGxiYWNrIGBmbihyZXMpYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gdXJsXG4gKiBAcGFyYW0ge01peGVkfEZ1bmN0aW9ufSBkYXRhIG9yIGZuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICogQHJldHVybiB7UmVxdWVzdH1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxucmVxdWVzdC5nZXQgPSBmdW5jdGlvbih1cmwsIGRhdGEsIGZuKXtcbiAgdmFyIHJlcSA9IHJlcXVlc3QoJ0dFVCcsIHVybCk7XG4gIGlmICgnZnVuY3Rpb24nID09IHR5cGVvZiBkYXRhKSBmbiA9IGRhdGEsIGRhdGEgPSBudWxsO1xuICBpZiAoZGF0YSkgcmVxLnF1ZXJ5KGRhdGEpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxuLyoqXG4gKiBIRUFEIGB1cmxgIHdpdGggb3B0aW9uYWwgY2FsbGJhY2sgYGZuKHJlcylgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAqIEBwYXJhbSB7TWl4ZWR8RnVuY3Rpb259IGRhdGEgb3IgZm5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5yZXF1ZXN0LmhlYWQgPSBmdW5jdGlvbih1cmwsIGRhdGEsIGZuKXtcbiAgdmFyIHJlcSA9IHJlcXVlc3QoJ0hFQUQnLCB1cmwpO1xuICBpZiAoJ2Z1bmN0aW9uJyA9PSB0eXBlb2YgZGF0YSkgZm4gPSBkYXRhLCBkYXRhID0gbnVsbDtcbiAgaWYgKGRhdGEpIHJlcS5zZW5kKGRhdGEpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxuLyoqXG4gKiBERUxFVEUgYHVybGAgd2l0aCBvcHRpb25hbCBjYWxsYmFjayBgZm4ocmVzKWAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAqIEByZXR1cm4ge1JlcXVlc3R9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbnJlcXVlc3QuZGVsID0gZnVuY3Rpb24odXJsLCBmbil7XG4gIHZhciByZXEgPSByZXF1ZXN0KCdERUxFVEUnLCB1cmwpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxuLyoqXG4gKiBQQVRDSCBgdXJsYCB3aXRoIG9wdGlvbmFsIGBkYXRhYCBhbmQgY2FsbGJhY2sgYGZuKHJlcylgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAqIEBwYXJhbSB7TWl4ZWR9IGRhdGFcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5yZXF1ZXN0LnBhdGNoID0gZnVuY3Rpb24odXJsLCBkYXRhLCBmbil7XG4gIHZhciByZXEgPSByZXF1ZXN0KCdQQVRDSCcsIHVybCk7XG4gIGlmICgnZnVuY3Rpb24nID09IHR5cGVvZiBkYXRhKSBmbiA9IGRhdGEsIGRhdGEgPSBudWxsO1xuICBpZiAoZGF0YSkgcmVxLnNlbmQoZGF0YSk7XG4gIGlmIChmbikgcmVxLmVuZChmbik7XG4gIHJldHVybiByZXE7XG59O1xuXG4vKipcbiAqIFBPU1QgYHVybGAgd2l0aCBvcHRpb25hbCBgZGF0YWAgYW5kIGNhbGxiYWNrIGBmbihyZXMpYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gdXJsXG4gKiBAcGFyYW0ge01peGVkfSBkYXRhXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICogQHJldHVybiB7UmVxdWVzdH1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxucmVxdWVzdC5wb3N0ID0gZnVuY3Rpb24odXJsLCBkYXRhLCBmbil7XG4gIHZhciByZXEgPSByZXF1ZXN0KCdQT1NUJywgdXJsKTtcbiAgaWYgKCdmdW5jdGlvbicgPT0gdHlwZW9mIGRhdGEpIGZuID0gZGF0YSwgZGF0YSA9IG51bGw7XG4gIGlmIChkYXRhKSByZXEuc2VuZChkYXRhKTtcbiAgaWYgKGZuKSByZXEuZW5kKGZuKTtcbiAgcmV0dXJuIHJlcTtcbn07XG5cbi8qKlxuICogUFVUIGB1cmxgIHdpdGggb3B0aW9uYWwgYGRhdGFgIGFuZCBjYWxsYmFjayBgZm4ocmVzKWAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICogQHBhcmFtIHtNaXhlZHxGdW5jdGlvbn0gZGF0YSBvciBmblxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAqIEByZXR1cm4ge1JlcXVlc3R9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbnJlcXVlc3QucHV0ID0gZnVuY3Rpb24odXJsLCBkYXRhLCBmbil7XG4gIHZhciByZXEgPSByZXF1ZXN0KCdQVVQnLCB1cmwpO1xuICBpZiAoJ2Z1bmN0aW9uJyA9PSB0eXBlb2YgZGF0YSkgZm4gPSBkYXRhLCBkYXRhID0gbnVsbDtcbiAgaWYgKGRhdGEpIHJlcS5zZW5kKGRhdGEpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxuLyoqXG4gKiBFeHBvc2UgYHJlcXVlc3RgLlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWVzdDtcbiIsIlxuLyoqXG4gKiBFeHBvc2UgYEVtaXR0ZXJgLlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gRW1pdHRlcjtcblxuLyoqXG4gKiBJbml0aWFsaXplIGEgbmV3IGBFbWl0dGVyYC5cbiAqXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIEVtaXR0ZXIob2JqKSB7XG4gIGlmIChvYmopIHJldHVybiBtaXhpbihvYmopO1xufTtcblxuLyoqXG4gKiBNaXhpbiB0aGUgZW1pdHRlciBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmpcbiAqIEByZXR1cm4ge09iamVjdH1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIG1peGluKG9iaikge1xuICBmb3IgKHZhciBrZXkgaW4gRW1pdHRlci5wcm90b3R5cGUpIHtcbiAgICBvYmpba2V5XSA9IEVtaXR0ZXIucHJvdG90eXBlW2tleV07XG4gIH1cbiAgcmV0dXJuIG9iajtcbn1cblxuLyoqXG4gKiBMaXN0ZW4gb24gdGhlIGdpdmVuIGBldmVudGAgd2l0aCBgZm5gLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBldmVudFxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAqIEByZXR1cm4ge0VtaXR0ZXJ9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbkVtaXR0ZXIucHJvdG90eXBlLm9uID1cbkVtaXR0ZXIucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbihldmVudCwgZm4pe1xuICB0aGlzLl9jYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3MgfHwge307XG4gICh0aGlzLl9jYWxsYmFja3NbZXZlbnRdID0gdGhpcy5fY2FsbGJhY2tzW2V2ZW50XSB8fCBbXSlcbiAgICAucHVzaChmbik7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBBZGRzIGFuIGBldmVudGAgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBzaW5nbGVcbiAqIHRpbWUgdGhlbiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICogQHJldHVybiB7RW1pdHRlcn1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuRW1pdHRlci5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uKGV2ZW50LCBmbil7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdGhpcy5fY2FsbGJhY2tzID0gdGhpcy5fY2FsbGJhY2tzIHx8IHt9O1xuXG4gIGZ1bmN0aW9uIG9uKCkge1xuICAgIHNlbGYub2ZmKGV2ZW50LCBvbik7XG4gICAgZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIG9uLmZuID0gZm47XG4gIHRoaXMub24oZXZlbnQsIG9uKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXG4gKiByZWdpc3RlcmVkIGNhbGxiYWNrcy5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKiBAcmV0dXJuIHtFbWl0dGVyfVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5FbWl0dGVyLnByb3RvdHlwZS5vZmYgPVxuRW1pdHRlci5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPVxuRW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID1cbkVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbihldmVudCwgZm4pe1xuICB0aGlzLl9jYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3MgfHwge307XG5cbiAgLy8gYWxsXG4gIGlmICgwID09IGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICB0aGlzLl9jYWxsYmFja3MgPSB7fTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8vIHNwZWNpZmljIGV2ZW50XG4gIHZhciBjYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3NbZXZlbnRdO1xuICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XG5cbiAgLy8gcmVtb3ZlIGFsbCBoYW5kbGVyc1xuICBpZiAoMSA9PSBhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgZGVsZXRlIHRoaXMuX2NhbGxiYWNrc1tldmVudF07XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvLyByZW1vdmUgc3BlY2lmaWMgaGFuZGxlclxuICB2YXIgY2I7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY2FsbGJhY2tzLmxlbmd0aDsgaSsrKSB7XG4gICAgY2IgPSBjYWxsYmFja3NbaV07XG4gICAgaWYgKGNiID09PSBmbiB8fCBjYi5mbiA9PT0gZm4pIHtcbiAgICAgIGNhbGxiYWNrcy5zcGxpY2UoaSwgMSk7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIEVtaXQgYGV2ZW50YCB3aXRoIHRoZSBnaXZlbiBhcmdzLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBldmVudFxuICogQHBhcmFtIHtNaXhlZH0gLi4uXG4gKiBAcmV0dXJuIHtFbWl0dGVyfVxuICovXG5cbkVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbihldmVudCl7XG4gIHRoaXMuX2NhbGxiYWNrcyA9IHRoaXMuX2NhbGxiYWNrcyB8fCB7fTtcbiAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSlcbiAgICAsIGNhbGxiYWNrcyA9IHRoaXMuX2NhbGxiYWNrc1tldmVudF07XG5cbiAgaWYgKGNhbGxiYWNrcykge1xuICAgIGNhbGxiYWNrcyA9IGNhbGxiYWNrcy5zbGljZSgwKTtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gY2FsbGJhY2tzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XG4gICAgICBjYWxsYmFja3NbaV0uYXBwbHkodGhpcywgYXJncyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFJldHVybiBhcnJheSBvZiBjYWxsYmFja3MgZm9yIGBldmVudGAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50XG4gKiBAcmV0dXJuIHtBcnJheX1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuRW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJzID0gZnVuY3Rpb24oZXZlbnQpe1xuICB0aGlzLl9jYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3MgfHwge307XG4gIHJldHVybiB0aGlzLl9jYWxsYmFja3NbZXZlbnRdIHx8IFtdO1xufTtcblxuLyoqXG4gKiBDaGVjayBpZiB0aGlzIGVtaXR0ZXIgaGFzIGBldmVudGAgaGFuZGxlcnMuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50XG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5FbWl0dGVyLnByb3RvdHlwZS5oYXNMaXN0ZW5lcnMgPSBmdW5jdGlvbihldmVudCl7XG4gIHJldHVybiAhISB0aGlzLmxpc3RlbmVycyhldmVudCkubGVuZ3RoO1xufTtcbiIsIlxuLyoqXG4gKiBSZWR1Y2UgYGFycmAgd2l0aCBgZm5gLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IGFyclxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAqIEBwYXJhbSB7TWl4ZWR9IGluaXRpYWxcbiAqXG4gKiBUT0RPOiBjb21iYXRpYmxlIGVycm9yIGhhbmRsaW5nP1xuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oYXJyLCBmbiwgaW5pdGlhbCl7ICBcbiAgdmFyIGlkeCA9IDA7XG4gIHZhciBsZW4gPSBhcnIubGVuZ3RoO1xuICB2YXIgY3VyciA9IGFyZ3VtZW50cy5sZW5ndGggPT0gM1xuICAgID8gaW5pdGlhbFxuICAgIDogYXJyW2lkeCsrXTtcblxuICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgY3VyciA9IGZuLmNhbGwobnVsbCwgY3VyciwgYXJyW2lkeF0sICsraWR4LCBhcnIpO1xuICB9XG4gIFxuICByZXR1cm4gY3Vycjtcbn07Il19