UNPKG

webdriverio-automation

Version:

WebdriverIO-Automation android ios project

548 lines (536 loc) 61.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); require("source-map-support/register"); var _capabilities = require("../../lib/basedriver/capabilities"); var _chai = _interopRequireDefault(require("chai")); var _chaiAsPromised = _interopRequireDefault(require("chai-as-promised")); var _lodash = _interopRequireDefault(require("lodash")); var _desiredCaps = require("../../lib/basedriver/desired-caps"); _chai.default.use(_chaiAsPromised.default); const should = _chai.default.should(); describe('caps', function () { describe('#validateCaps', function () { it('returns invalid argument error if "capability" is not a JSON object (1)', function () { for (let arg of [undefined, null, 1, true, 'string']) { (function () { (0, _capabilities.validateCaps)(arg); }).should.throw(/must be a JSON object/); } }); it('returns result {} by default if caps is empty object and no constraints provided (2)', function () { (0, _capabilities.validateCaps)({}).should.deep.equal({}); }); describe('throws errors if constraints are not met', function () { it('returns invalid argument error if "present" constraint not met on property', function () { (() => (0, _capabilities.validateCaps)({}, { foo: { presence: true } })).should.throw(/'foo' can't be blank/); }); it('returns the capability that was passed in if "skipPresenceConstraint" is false', function () { (0, _capabilities.validateCaps)({}, { foo: { presence: true } }, { skipPresenceConstraint: true }).should.deep.equal({}); }); it('returns invalid argument error if "isString" constraint not met on property', function () { (() => (0, _capabilities.validateCaps)({ foo: 1 }, { foo: { isString: true } })).should.throw(/'foo' must be of type string/); }); it('returns invalid argument error if "isNumber" constraint not met on property', function () { (() => (0, _capabilities.validateCaps)({ foo: 'bar' }, { foo: { isNumber: true } })).should.throw(/'foo' must be of type number/); }); it('returns invalid argument error if "isBoolean" constraint not met on property', function () { (() => (0, _capabilities.validateCaps)({ foo: 'bar' }, { foo: { isBoolean: true } })).should.throw(/'foo' must be of type boolean/); }); it('returns invalid argument error if "inclusion" constraint not met on property', function () { (() => (0, _capabilities.validateCaps)({ foo: '3' }, { foo: { inclusionCaseInsensitive: ['1', '2'] } })).should.throw(/'foo' 3 not part of 1,2/); }); it('returns invalid argument error if "inclusionCaseInsensitive" constraint not met on property', function () { (() => (0, _capabilities.validateCaps)({ foo: 'a' }, { foo: { inclusion: ['A', 'B', 'C'] } })).should.throw(/'foo' a is not included in the list/); }); }); it('should not throw errors if constraints are met', function () { let caps = { number: 1, string: 'string', present: 'present', extra: 'extra' }; let constraints = { number: { isNumber: true }, string: { isString: true }, present: { presence: true }, notPresent: { presence: false } }; (0, _capabilities.validateCaps)(caps, constraints).should.deep.equal(caps); }); }); describe('#mergeCaps', function () { it('returns a result that is {} by default (1)', function () { (0, _capabilities.mergeCaps)().should.deep.equal({}); }); it('returns a result that matches primary by default (2, 3)', function () { (0, _capabilities.mergeCaps)({ hello: 'world' }).should.deep.equal({ hello: 'world' }); }); it('returns invalid argument error if primary and secondary have matching properties (4)', function () { (() => (0, _capabilities.mergeCaps)({ hello: 'world' }, { hello: 'whirl' })).should.throw(/property 'hello' should not exist on both primary [\w\W]* and secondary [\w\W]*/); }); it('returns a result with keys from primary and secondary together', function () { let primary = { a: 'a', b: 'b' }; let secondary = { c: 'c', d: 'd' }; (0, _capabilities.mergeCaps)(primary, secondary).should.deep.equal({ a: 'a', b: 'b', c: 'c', d: 'd' }); }); }); describe('#parseCaps', function () { let caps; beforeEach(function () { caps = {}; }); it('should return invalid argument if no caps object provided', function () { (() => (0, _capabilities.parseCaps)()).should.throw(/must be a JSON object/); }); it('sets "requiredCaps" to property named "alwaysMatch" (2)', function () { caps.alwaysMatch = { hello: 'world' }; (0, _capabilities.parseCaps)(caps).requiredCaps.should.deep.equal(caps.alwaysMatch); }); it('sets "requiredCaps" to empty JSON object if "alwaysMatch" is not an object (2.1)', function () { (0, _capabilities.parseCaps)(caps).requiredCaps.should.deep.equal({}); }); it('returns invalid argument error if "requiredCaps" don\'t match "constraints" (2.2)', function () { caps.alwaysMatch = { foo: 1 }; (() => (0, _capabilities.parseCaps)(caps, { foo: { isString: true } })).should.throw(/'foo' must be of type string/); }); it('sets "allFirstMatchCaps" to property named "firstMatch" (3)', function () { (0, _capabilities.parseCaps)({}, [{}]).allFirstMatchCaps.should.deep.equal([{}]); }); it('sets "allFirstMatchCaps" to [{}] if "firstMatch" is undefined (3.1)', function () { (0, _capabilities.parseCaps)({}).allFirstMatchCaps.should.deep.equal([{}]); }); it('returns invalid argument error if "firstMatch" is not an array and is not undefined (3.2)', function () { for (let arg of [null, 1, true, 'string']) { caps.firstMatch = arg; (function () { (0, _capabilities.parseCaps)(caps); }).should.throw(/must be a JSON array or undefined/); } }); it('has "validatedFirstMatchCaps" property that is empty by default if no valid firstMatch caps were found (4)', function () { (0, _capabilities.parseCaps)(caps, { foo: { presence: true } }).validatedFirstMatchCaps.should.deep.equal([]); }); describe('returns a "validatedFirstMatchCaps" array (5)', function () { it('that equals "firstMatch" if firstMatch is one empty object and there are no constraints', function () { caps.firstMatch = [{}]; (0, _capabilities.parseCaps)(caps).validatedFirstMatchCaps.should.deep.equal(caps.firstMatch); }); it('returns "null" matchedCaps if nothing matches', function () { caps.firstMatch = [{}]; should.equal((0, _capabilities.parseCaps)(caps, { foo: { presence: true } }).matchedCaps, null); }); it(`should return capabilities if presence constraint is matched in at least one of the 'firstMatch' capabilities objects`, function () { caps.alwaysMatch = { foo: 'bar' }; caps.firstMatch = [{ hello: 'world' }, { goodbye: 'world' }]; (0, _capabilities.parseCaps)(caps, { goodbye: { presence: true } }).matchedCaps.should.deep.equal({ foo: 'bar', goodbye: 'world' }); }); it(`throws invalid argument if presence constraint is not met on any capabilities`, function () { caps.alwaysMatch = { foo: 'bar' }; caps.firstMatch = [{ hello: 'world' }, { goodbye: 'world' }]; should.equal((0, _capabilities.parseCaps)(caps, { someAttribute: { presence: true } }).matchedCaps, null); }); it('that equals firstMatch if firstMatch contains two objects that pass the provided constraints', function () { caps.alwaysMatch = { foo: 'bar' }; caps.firstMatch = [{ foo: 'bar1' }, { foo: 'bar2' }]; let constraints = { foo: { presence: true, isString: true } }; (0, _capabilities.parseCaps)(caps, constraints).validatedFirstMatchCaps.should.deep.equal(caps.firstMatch); }); it('returns invalid argument error if the firstMatch[2] is not an object', function () { caps.alwaysMatch = 'Not an object and not undefined'; caps.firstMatch = [{ foo: 'bar' }, 'foo']; (() => (0, _capabilities.parseCaps)(caps, {})).should.throw(/must be a JSON object/); }); }); describe('returns a matchedCaps object (6)', function () { beforeEach(function () { caps.alwaysMatch = { hello: 'world' }; }); it('which is same as alwaysMatch if firstMatch array is not provided', function () { (0, _capabilities.parseCaps)(caps).matchedCaps.should.deep.equal({ hello: 'world' }); }); it('merges caps together', function () { caps.firstMatch = [{ foo: 'bar' }]; (0, _capabilities.parseCaps)(caps).matchedCaps.should.deep.equal({ hello: 'world', foo: 'bar' }); }); it('with merged caps', function () { caps.firstMatch = [{ hello: 'bar', foo: 'foo' }, { foo: 'bar' }]; (0, _capabilities.parseCaps)(caps).matchedCaps.should.deep.equal({ hello: 'world', foo: 'bar' }); }); }); }); describe('#processCaps', function () { it('should return "alwaysMatch" if "firstMatch" and "constraints" were not provided', function () { (0, _capabilities.processCapabilities)({}).should.deep.equal({}); }); it('should return merged caps', function () { (0, _capabilities.processCapabilities)({ alwaysMatch: { hello: 'world' }, firstMatch: [{ foo: 'bar' }] }).should.deep.equal({ hello: 'world', foo: 'bar' }); }); it('should strip out the "appium:" prefix for non-standard capabilities', function () { (0, _capabilities.processCapabilities)({ alwaysMatch: { 'appium:hello': 'world' }, firstMatch: [{ 'appium:foo': 'bar' }] }).should.deep.equal({ hello: 'world', foo: 'bar' }); }); it('should throw an exception if a standard capability (https://www.w3.org/TR/webdriver/#dfn-table-of-standard-capabilities) is prefixed', function () { (() => (0, _capabilities.processCapabilities)({ alwaysMatch: { 'appium:platformName': 'Whatevz' }, firstMatch: [{ 'appium:browserName': 'Anything' }] })).should.throw(/standard capabilities/); }); it('should not throw an exception if presence constraint is not met on a firstMatch capability', function () { const caps = (0, _capabilities.processCapabilities)({ alwaysMatch: { 'platformName': 'Fake', 'appium:fakeCap': 'foobar' }, firstMatch: [{ 'foo': 'bar' }] }, { platformName: { presence: true }, fakeCap: { presence: true } }); caps.platformName.should.equal('Fake'); caps.fakeCap.should.equal('foobar'); caps.foo.should.equal('bar'); }); it('should throw an exception if no matching caps were found', function () { (() => (0, _capabilities.processCapabilities)({ alwaysMatch: { 'platformName': 'Fake', 'appium:fakeCap': 'foobar' }, firstMatch: [{ 'foo': 'bar' }] }, { platformName: { presence: true }, fakeCap: { presence: true }, missingCap: { presence: true } })).should.throw(/'missingCap' can't be blank/); }); describe('validate Appium constraints', function () { let constraints = { ..._desiredCaps.desiredCapabilityConstraints }; let matchingCaps = { 'platformName': 'Fake', 'automationName': 'Fake', 'deviceName': 'Fake' }; let caps; it('should validate when alwaysMatch has the proper caps', function () { caps = { alwaysMatch: matchingCaps, firstMatch: [{}] }; (0, _capabilities.processCapabilities)(caps, constraints).should.deep.equal(matchingCaps); }); it('should validate when firstMatch[0] has the proper caps', function () { caps = { alwaysMatch: {}, firstMatch: [matchingCaps] }; (0, _capabilities.processCapabilities)(caps, constraints).should.deep.equal(matchingCaps); }); it('should validate when alwaysMatch and firstMatch[0] have the proper caps when merged together', function () { caps = { alwaysMatch: _lodash.default.omit(matchingCaps, ['deviceName']), firstMatch: [{ 'appium:deviceName': 'Fake' }] }; (0, _capabilities.processCapabilities)(caps, constraints).should.deep.equal(matchingCaps); }); it('should validate when automationName is omitted', function () { caps = { alwaysMatch: _lodash.default.omit(matchingCaps, ['automationName']) }; (0, _capabilities.processCapabilities)(caps, constraints).should.deep.equal(_lodash.default.omit(matchingCaps, 'automationName')); }); it('should pass if first element in "firstMatch" does validate and second element does not', function () { caps = { alwaysMatch: {}, firstMatch: [matchingCaps, { badCaps: 'badCaps' }] }; (0, _capabilities.processCapabilities)(caps, constraints).should.deep.equal(matchingCaps); }); it('should pass if first element in "firstMatch" does not validate and second element does', function () { caps = { alwaysMatch: {}, firstMatch: [{ badCaps: 'badCaps' }, matchingCaps] }; (0, _capabilities.processCapabilities)(caps, constraints).should.deep.equal(matchingCaps); }); it('should fail when deviceName is blank', function () { caps = { alwaysMatch: _lodash.default.omit(matchingCaps, ['deviceName']) }; (() => (0, _capabilities.processCapabilities)(caps, constraints)).should.throw(/'deviceName' can't be blank/); }); it('should fail when bad parameters are passed in more than one firstMatch capability', function () { caps = { alwaysMatch: {}, firstMatch: [{ bad: 'params' }, { more: 'bad-params' }] }; (() => (0, _capabilities.processCapabilities)(caps, constraints)).should.throw(/Could not find matching capabilities/); }); }); }); describe('.findNonPrefixedCaps', function () { it('should find alwaysMatch caps with no prefix', function () { (0, _capabilities.findNonPrefixedCaps)({ alwaysMatch: { 'non-standard': 'dummy' } }).should.eql(['non-standard']); }); it('should not find a standard cap in alwaysMatch', function () { (0, _capabilities.findNonPrefixedCaps)({ alwaysMatch: { 'platformName': 'Any' } }).should.eql([]); }); it('should find firstMatch caps with no prefix', function () { (0, _capabilities.findNonPrefixedCaps)({ alwaysMatch: {}, firstMatch: [{ 'non-standard': 'dummy' }] }).should.eql(['non-standard']); }); it('should not find a standard cap in prefix', function () { (0, _capabilities.findNonPrefixedCaps)({ alwaysMatch: {}, firstMatch: [{ 'platformName': 'Any' }] }).should.eql([]); }); it('should find firstMatch caps in second item of firstMatch array', function () { (0, _capabilities.findNonPrefixedCaps)({ alwaysMatch: {}, firstMatch: [{}, { 'non-standard': 'dummy' }] }).should.eql(['non-standard']); }); it('should remove duplicates from alwaysMatch and firstMatch', function () { (0, _capabilities.findNonPrefixedCaps)({ alwaysMatch: { 'non-standard': 'something' }, firstMatch: [{ 'non-standard': 'dummy' }] }).should.eql(['non-standard']); }); it('should remove duplicates from firstMatch', function () { (0, _capabilities.findNonPrefixedCaps)({ firstMatch: [{ 'non-standard': 'dummy' }, { 'non-standard': 'dummy 2' }] }).should.eql(['non-standard']); }); it('should remove duplicates and keep standard capabilities', function () { const alwaysMatch = { platformName: 'Fake', nonStandardOne: 'non-standard', nonStandardTwo: 'non-standard' }; const firstMatch = [{ nonStandardThree: 'non-standard', nonStandardFour: 'non-standard', browserName: 'FakeBrowser' }, { nonStandardThree: 'non-standard', nonStandardFour: 'non-standard', nonStandardFive: 'non-standard', browserVersion: 'whateva' }]; (0, _capabilities.findNonPrefixedCaps)({ alwaysMatch, firstMatch }).should.eql(['nonStandardOne', 'nonStandardTwo', 'nonStandardThree', 'nonStandardFour', 'nonStandardFive']); }); }); });require('source-map-support').install(); //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvYmFzZWRyaXZlci9jYXBhYmlsaXRpZXMtc3BlY3MuanMiXSwibmFtZXMiOlsiY2hhaSIsInVzZSIsImNoYWlBc1Byb21pc2VkIiwic2hvdWxkIiwiZGVzY3JpYmUiLCJpdCIsImFyZyIsInVuZGVmaW5lZCIsInRocm93IiwiZGVlcCIsImVxdWFsIiwiZm9vIiwicHJlc2VuY2UiLCJza2lwUHJlc2VuY2VDb25zdHJhaW50IiwiaXNTdHJpbmciLCJpc051bWJlciIsImlzQm9vbGVhbiIsImluY2x1c2lvbkNhc2VJbnNlbnNpdGl2ZSIsImluY2x1c2lvbiIsImNhcHMiLCJudW1iZXIiLCJzdHJpbmciLCJwcmVzZW50IiwiZXh0cmEiLCJjb25zdHJhaW50cyIsIm5vdFByZXNlbnQiLCJoZWxsbyIsInByaW1hcnkiLCJhIiwiYiIsInNlY29uZGFyeSIsImMiLCJkIiwiYmVmb3JlRWFjaCIsImFsd2F5c01hdGNoIiwicmVxdWlyZWRDYXBzIiwiYWxsRmlyc3RNYXRjaENhcHMiLCJmaXJzdE1hdGNoIiwidmFsaWRhdGVkRmlyc3RNYXRjaENhcHMiLCJtYXRjaGVkQ2FwcyIsImdvb2RieWUiLCJzb21lQXR0cmlidXRlIiwicGxhdGZvcm1OYW1lIiwiZmFrZUNhcCIsIm1pc3NpbmdDYXAiLCJkZXNpcmVkQ2FwYWJpbGl0eUNvbnN0cmFpbnRzIiwibWF0Y2hpbmdDYXBzIiwiXyIsIm9taXQiLCJiYWRDYXBzIiwiYmFkIiwibW9yZSIsImVxbCIsIm5vblN0YW5kYXJkT25lIiwibm9uU3RhbmRhcmRUd28iLCJub25TdGFuZGFyZFRocmVlIiwibm9uU3RhbmRhcmRGb3VyIiwiYnJvd3Nlck5hbWUiLCJub25TdGFuZGFyZEZpdmUiLCJicm93c2VyVmVyc2lvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBRUFBLGNBQUtDLEdBQUwsQ0FBU0MsdUJBQVQ7O0FBQ0EsTUFBTUMsTUFBTSxHQUFHSCxjQUFLRyxNQUFMLEVBQWY7O0FBRUFDLFFBQVEsQ0FBQyxNQUFELEVBQVMsWUFBWTtBQUczQkEsRUFBQUEsUUFBUSxDQUFDLGVBQUQsRUFBa0IsWUFBWTtBQUNwQ0MsSUFBQUEsRUFBRSxDQUFDLHlFQUFELEVBQTRFLFlBQVk7QUFDeEYsV0FBSyxJQUFJQyxHQUFULElBQWdCLENBQUNDLFNBQUQsRUFBWSxJQUFaLEVBQWtCLENBQWxCLEVBQXFCLElBQXJCLEVBQTJCLFFBQTNCLENBQWhCLEVBQXNEO0FBQ3BELFNBQUMsWUFBWTtBQUFFLDBDQUFhRCxHQUFiO0FBQW9CLFNBQW5DLEVBQXFDSCxNQUFyQyxDQUE0Q0ssS0FBNUMsQ0FBa0QsdUJBQWxEO0FBQ0Q7QUFDRixLQUpDLENBQUY7QUFNQUgsSUFBQUEsRUFBRSxDQUFDLHNGQUFELEVBQXlGLFlBQVk7QUFDckcsc0NBQWEsRUFBYixFQUFpQkYsTUFBakIsQ0FBd0JNLElBQXhCLENBQTZCQyxLQUE3QixDQUFtQyxFQUFuQztBQUNELEtBRkMsQ0FBRjtBQUlBTixJQUFBQSxRQUFRLENBQUMsMENBQUQsRUFBNkMsWUFBWTtBQUMvREMsTUFBQUEsRUFBRSxDQUFDLDRFQUFELEVBQStFLFlBQVk7QUFDM0YsU0FBQyxNQUFNLGdDQUFhLEVBQWIsRUFBaUI7QUFBQ00sVUFBQUEsR0FBRyxFQUFFO0FBQUNDLFlBQUFBLFFBQVEsRUFBRTtBQUFYO0FBQU4sU0FBakIsQ0FBUCxFQUFrRFQsTUFBbEQsQ0FBeURLLEtBQXpELENBQStELHNCQUEvRDtBQUNELE9BRkMsQ0FBRjtBQUlBSCxNQUFBQSxFQUFFLENBQUMsZ0ZBQUQsRUFBbUYsWUFBWTtBQUMvRix3Q0FBYSxFQUFiLEVBQWlCO0FBQUNNLFVBQUFBLEdBQUcsRUFBRTtBQUFDQyxZQUFBQSxRQUFRLEVBQUU7QUFBWDtBQUFOLFNBQWpCLEVBQTBDO0FBQUNDLFVBQUFBLHNCQUFzQixFQUFFO0FBQXpCLFNBQTFDLEVBQTBFVixNQUExRSxDQUFpRk0sSUFBakYsQ0FBc0ZDLEtBQXRGLENBQTRGLEVBQTVGO0FBQ0QsT0FGQyxDQUFGO0FBSUFMLE1BQUFBLEVBQUUsQ0FBQyw2RUFBRCxFQUFnRixZQUFZO0FBQzVGLFNBQUMsTUFBTSxnQ0FBYTtBQUFDTSxVQUFBQSxHQUFHLEVBQUU7QUFBTixTQUFiLEVBQXVCO0FBQUNBLFVBQUFBLEdBQUcsRUFBRTtBQUFDRyxZQUFBQSxRQUFRLEVBQUU7QUFBWDtBQUFOLFNBQXZCLENBQVAsRUFBd0RYLE1BQXhELENBQStESyxLQUEvRCxDQUFxRSw4QkFBckU7QUFDRCxPQUZDLENBQUY7QUFJQUgsTUFBQUEsRUFBRSxDQUFDLDZFQUFELEVBQWdGLFlBQVk7QUFDNUYsU0FBQyxNQUFNLGdDQUFhO0FBQUNNLFVBQUFBLEdBQUcsRUFBRTtBQUFOLFNBQWIsRUFBMkI7QUFBQ0EsVUFBQUEsR0FBRyxFQUFFO0FBQUNJLFlBQUFBLFFBQVEsRUFBRTtBQUFYO0FBQU4sU0FBM0IsQ0FBUCxFQUE0RFosTUFBNUQsQ0FBbUVLLEtBQW5FLENBQXlFLDhCQUF6RTtBQUNELE9BRkMsQ0FBRjtBQUlBSCxNQUFBQSxFQUFFLENBQUMsOEVBQUQsRUFBaUYsWUFBWTtBQUM3RixTQUFDLE1BQU0sZ0NBQWE7QUFBQ00sVUFBQUEsR0FBRyxFQUFFO0FBQU4sU0FBYixFQUEyQjtBQUFDQSxVQUFBQSxHQUFHLEVBQUU7QUFBQ0ssWUFBQUEsU0FBUyxFQUFFO0FBQVo7QUFBTixTQUEzQixDQUFQLEVBQTZEYixNQUE3RCxDQUFvRUssS0FBcEUsQ0FBMEUsK0JBQTFFO0FBQ0QsT0FGQyxDQUFGO0FBSUFILE1BQUFBLEVBQUUsQ0FBQyw4RUFBRCxFQUFpRixZQUFZO0FBQzdGLFNBQUMsTUFBTSxnQ0FBYTtBQUFDTSxVQUFBQSxHQUFHLEVBQUU7QUFBTixTQUFiLEVBQXlCO0FBQUNBLFVBQUFBLEdBQUcsRUFBRTtBQUFDTSxZQUFBQSx3QkFBd0IsRUFBRSxDQUFDLEdBQUQsRUFBTSxHQUFOO0FBQTNCO0FBQU4sU0FBekIsQ0FBUCxFQUFnRmQsTUFBaEYsQ0FBdUZLLEtBQXZGLENBQTZGLHlCQUE3RjtBQUNELE9BRkMsQ0FBRjtBQUlBSCxNQUFBQSxFQUFFLENBQUMsNkZBQUQsRUFBZ0csWUFBWTtBQUM1RyxTQUFDLE1BQU0sZ0NBQWE7QUFBQ00sVUFBQUEsR0FBRyxFQUFFO0FBQU4sU0FBYixFQUF5QjtBQUFDQSxVQUFBQSxHQUFHLEVBQUU7QUFBQ08sWUFBQUEsU0FBUyxFQUFFLENBQUMsR0FBRCxFQUFNLEdBQU4sRUFBVyxHQUFYO0FBQVo7QUFBTixTQUF6QixDQUFQLEVBQXNFZixNQUF0RSxDQUE2RUssS0FBN0UsQ0FBbUYscUNBQW5GO0FBQ0QsT0FGQyxDQUFGO0FBR0QsS0E1Qk8sQ0FBUjtBQThCQUgsSUFBQUEsRUFBRSxDQUFDLGdEQUFELEVBQW1ELFlBQVk7QUFDL0QsVUFBSWMsSUFBSSxHQUFHO0FBQ1RDLFFBQUFBLE1BQU0sRUFBRSxDQURDO0FBRVRDLFFBQUFBLE1BQU0sRUFBRSxRQUZDO0FBR1RDLFFBQUFBLE9BQU8sRUFBRSxTQUhBO0FBSVRDLFFBQUFBLEtBQUssRUFBRTtBQUpFLE9BQVg7QUFPQSxVQUFJQyxXQUFXLEdBQUc7QUFDaEJKLFFBQUFBLE1BQU0sRUFBRTtBQUFDTCxVQUFBQSxRQUFRLEVBQUU7QUFBWCxTQURRO0FBRWhCTSxRQUFBQSxNQUFNLEVBQUU7QUFBQ1AsVUFBQUEsUUFBUSxFQUFFO0FBQVgsU0FGUTtBQUdoQlEsUUFBQUEsT0FBTyxFQUFFO0FBQUNWLFVBQUFBLFFBQVEsRUFBRTtBQUFYLFNBSE87QUFJaEJhLFFBQUFBLFVBQVUsRUFBRTtBQUFDYixVQUFBQSxRQUFRLEVBQUU7QUFBWDtBQUpJLE9BQWxCO0FBT0Esc0NBQWFPLElBQWIsRUFBbUJLLFdBQW5CLEVBQWdDckIsTUFBaEMsQ0FBdUNNLElBQXZDLENBQTRDQyxLQUE1QyxDQUFrRFMsSUFBbEQ7QUFDRCxLQWhCQyxDQUFGO0FBaUJELEdBMURPLENBQVI7QUE2REFmLEVBQUFBLFFBQVEsQ0FBQyxZQUFELEVBQWUsWUFBWTtBQUNqQ0MsSUFBQUEsRUFBRSxDQUFDLDRDQUFELEVBQStDLFlBQVk7QUFDM0QscUNBQVlGLE1BQVosQ0FBbUJNLElBQW5CLENBQXdCQyxLQUF4QixDQUE4QixFQUE5QjtBQUNELEtBRkMsQ0FBRjtBQUlBTCxJQUFBQSxFQUFFLENBQUMseURBQUQsRUFBNEQsWUFBWTtBQUN4RSxtQ0FBVTtBQUFDcUIsUUFBQUEsS0FBSyxFQUFFO0FBQVIsT0FBVixFQUE0QnZCLE1BQTVCLENBQW1DTSxJQUFuQyxDQUF3Q0MsS0FBeEMsQ0FBOEM7QUFBQ2dCLFFBQUFBLEtBQUssRUFBRTtBQUFSLE9BQTlDO0FBQ0QsS0FGQyxDQUFGO0FBSUFyQixJQUFBQSxFQUFFLENBQUMsc0ZBQUQsRUFBeUYsWUFBWTtBQUNyRyxPQUFDLE1BQU0sNkJBQVU7QUFBQ3FCLFFBQUFBLEtBQUssRUFBRTtBQUFSLE9BQVYsRUFBNEI7QUFBQ0EsUUFBQUEsS0FBSyxFQUFFO0FBQVIsT0FBNUIsQ0FBUCxFQUFzRHZCLE1BQXRELENBQTZESyxLQUE3RCxDQUFtRSxpRkFBbkU7QUFDRCxLQUZDLENBQUY7QUFJQUgsSUFBQUEsRUFBRSxDQUFDLGdFQUFELEVBQW1FLFlBQVk7QUFDL0UsVUFBSXNCLE9BQU8sR0FBRztBQUNaQyxRQUFBQSxDQUFDLEVBQUUsR0FEUztBQUVaQyxRQUFBQSxDQUFDLEVBQUU7QUFGUyxPQUFkO0FBSUEsVUFBSUMsU0FBUyxHQUFHO0FBQ2RDLFFBQUFBLENBQUMsRUFBRSxHQURXO0FBRWRDLFFBQUFBLENBQUMsRUFBRTtBQUZXLE9BQWhCO0FBSUEsbUNBQVVMLE9BQVYsRUFBbUJHLFNBQW5CLEVBQThCM0IsTUFBOUIsQ0FBcUNNLElBQXJDLENBQTBDQyxLQUExQyxDQUFnRDtBQUM5Q2tCLFFBQUFBLENBQUMsRUFBRSxHQUQyQztBQUN0Q0MsUUFBQUEsQ0FBQyxFQUFFLEdBRG1DO0FBQzlCRSxRQUFBQSxDQUFDLEVBQUUsR0FEMkI7QUFDdEJDLFFBQUFBLENBQUMsRUFBRTtBQURtQixPQUFoRDtBQUdELEtBWkMsQ0FBRjtBQWFELEdBMUJPLENBQVI7QUE2QkE1QixFQUFBQSxRQUFRLENBQUMsWUFBRCxFQUFlLFlBQVk7QUFDakMsUUFBSWUsSUFBSjtBQUVBYyxJQUFBQSxVQUFVLENBQUMsWUFBWTtBQUNyQmQsTUFBQUEsSUFBSSxHQUFHLEVBQVA7QUFDRCxLQUZTLENBQVY7QUFJQWQsSUFBQUEsRUFBRSxDQUFDLDJEQUFELEVBQThELFlBQVk7QUFDMUUsT0FBQyxNQUFNLDhCQUFQLEVBQW9CRixNQUFwQixDQUEyQkssS0FBM0IsQ0FBaUMsdUJBQWpDO0FBQ0QsS0FGQyxDQUFGO0FBSUFILElBQUFBLEVBQUUsQ0FBQyx5REFBRCxFQUE0RCxZQUFZO0FBQ3hFYyxNQUFBQSxJQUFJLENBQUNlLFdBQUwsR0FBbUI7QUFBQ1IsUUFBQUEsS0FBSyxFQUFFO0FBQVIsT0FBbkI7QUFDQSxtQ0FBVVAsSUFBVixFQUFnQmdCLFlBQWhCLENBQTZCaEMsTUFBN0IsQ0FBb0NNLElBQXBDLENBQXlDQyxLQUF6QyxDQUErQ1MsSUFBSSxDQUFDZSxXQUFwRDtBQUNELEtBSEMsQ0FBRjtBQUtBN0IsSUFBQUEsRUFBRSxDQUFDLGtGQUFELEVBQXFGLFlBQVk7QUFDakcsbUNBQVVjLElBQVYsRUFBZ0JnQixZQUFoQixDQUE2QmhDLE1BQTdCLENBQW9DTSxJQUFwQyxDQUF5Q0MsS0FBekMsQ0FBK0MsRUFBL0M7QUFDRCxLQUZDLENBQUY7QUFJQUwsSUFBQUEsRUFBRSxDQUFDLG1GQUFELEVBQXNGLFlBQVk7QUFDbEdjLE1BQUFBLElBQUksQ0FBQ2UsV0FBTCxHQUFtQjtBQUFDdkIsUUFBQUEsR0FBRyxFQUFFO0FBQU4sT0FBbkI7QUFDQSxPQUFDLE1BQU0sNkJBQVVRLElBQVYsRUFBZ0I7QUFBQ1IsUUFBQUEsR0FBRyxFQUFFO0FBQUNHLFVBQUFBLFFBQVEsRUFBRTtBQUFYO0FBQU4sT0FBaEIsQ0FBUCxFQUFpRFgsTUFBakQsQ0FBd0RLLEtBQXhELENBQThELDhCQUE5RDtBQUNELEtBSEMsQ0FBRjtBQUtBSCxJQUFBQSxFQUFFLENBQUMsNkRBQUQsRUFBZ0UsWUFBWTtBQUM1RSxtQ0FBVSxFQUFWLEVBQWMsQ0FBQyxFQUFELENBQWQsRUFBb0IrQixpQkFBcEIsQ0FBc0NqQyxNQUF0QyxDQUE2Q00sSUFBN0MsQ0FBa0RDLEtBQWxELENBQXdELENBQUMsRUFBRCxDQUF4RDtBQUNELEtBRkMsQ0FBRjtBQUlBTCxJQUFBQSxFQUFFLENBQUMscUVBQUQsRUFBd0UsWUFBWTtBQUNwRixtQ0FBVSxFQUFWLEVBQWMrQixpQkFBZCxDQUFnQ2pDLE1BQWhDLENBQXVDTSxJQUF2QyxDQUE0Q0MsS0FBNUMsQ0FBa0QsQ0FBQyxFQUFELENBQWxEO0FBQ0QsS0FGQyxDQUFGO0FBSUFMLElBQUFBLEVBQUUsQ0FBQywyRkFBRCxFQUE4RixZQUFZO0FBQzFHLFdBQUssSUFBSUMsR0FBVCxJQUFnQixDQUFDLElBQUQsRUFBTyxDQUFQLEVBQVUsSUFBVixFQUFnQixRQUFoQixDQUFoQixFQUEyQztBQUN6Q2EsUUFBQUEsSUFBSSxDQUFDa0IsVUFBTCxHQUFrQi9CLEdBQWxCO0FBQ0EsU0FBQyxZQUFZO0FBQUUsdUNBQVVhLElBQVY7QUFBa0IsU0FBakMsRUFBbUNoQixNQUFuQyxDQUEwQ0ssS0FBMUMsQ0FBZ0QsbUNBQWhEO0FBQ0Q7QUFDRixLQUxDLENBQUY7QUFPQUgsSUFBQUEsRUFBRSxDQUFDLDRHQUFELEVBQStHLFlBQVk7QUFDM0gsbUNBQVVjLElBQVYsRUFBZ0I7QUFBQ1IsUUFBQUEsR0FBRyxFQUFFO0FBQUNDLFVBQUFBLFFBQVEsRUFBRTtBQUFYO0FBQU4sT0FBaEIsRUFBeUMwQix1QkFBekMsQ0FBaUVuQyxNQUFqRSxDQUF3RU0sSUFBeEUsQ0FBNkVDLEtBQTdFLENBQW1GLEVBQW5GO0FBQ0QsS0FGQyxDQUFGO0FBSUFOLElBQUFBLFFBQVEsQ0FBQywrQ0FBRCxFQUFrRCxZQUFZO0FBQ3BFQyxNQUFBQSxFQUFFLENBQUMseUZBQUQsRUFBNEYsWUFBWTtBQUN4R2MsUUFBQUEsSUFBSSxDQUFDa0IsVUFBTCxHQUFrQixDQUFDLEVBQUQsQ0FBbEI7QUFDQSxxQ0FBVWxCLElBQVYsRUFBZ0JtQix1QkFBaEIsQ0FBd0NuQyxNQUF4QyxDQUErQ00sSUFBL0MsQ0FBb0RDLEtBQXBELENBQTBEUyxJQUFJLENBQUNrQixVQUEvRDtBQUNELE9BSEMsQ0FBRjtBQUtBaEMsTUFBQUEsRUFBRSxDQUFDLCtDQUFELEVBQWtELFlBQVk7QUFDOURjLFFBQUFBLElBQUksQ0FBQ2tCLFVBQUwsR0FBa0IsQ0FBQyxFQUFELENBQWxCO0FBQ0FsQyxRQUFBQSxNQUFNLENBQUNPLEtBQVAsQ0FBYSw2QkFBVVMsSUFBVixFQUFnQjtBQUFDUixVQUFBQSxHQUFHLEVBQUU7QUFBQ0MsWUFBQUEsUUFBUSxFQUFFO0FBQVg7QUFBTixTQUFoQixFQUF5QzJCLFdBQXRELEVBQW1FLElBQW5FO0FBQ0QsT0FIQyxDQUFGO0FBS0FsQyxNQUFBQSxFQUFFLENBQUUsdUhBQUYsRUFBMEgsWUFBWTtBQUN0SWMsUUFBQUEsSUFBSSxDQUFDZSxXQUFMLEdBQW1CO0FBQ2pCdkIsVUFBQUEsR0FBRyxFQUFFO0FBRFksU0FBbkI7QUFHQVEsUUFBQUEsSUFBSSxDQUFDa0IsVUFBTCxHQUFrQixDQUFDO0FBQ2pCWCxVQUFBQSxLQUFLLEVBQUU7QUFEVSxTQUFELEVBRWY7QUFDRGMsVUFBQUEsT0FBTyxFQUFFO0FBRFIsU0FGZSxDQUFsQjtBQUtBLHFDQUFVckIsSUFBVixFQUFnQjtBQUFDcUIsVUFBQUEsT0FBTyxFQUFFO0FBQUM1QixZQUFBQSxRQUFRLEVBQUU7QUFBWDtBQUFWLFNBQWhCLEVBQTZDMkIsV0FBN0MsQ0FBeURwQyxNQUF6RCxDQUFnRU0sSUFBaEUsQ0FBcUVDLEtBQXJFLENBQTJFO0FBQ3pFQyxVQUFBQSxHQUFHLEVBQUUsS0FEb0U7QUFFekU2QixVQUFBQSxPQUFPLEVBQUU7QUFGZ0UsU0FBM0U7QUFJRCxPQWJDLENBQUY7QUFlQW5DLE1BQUFBLEVBQUUsQ0FBRSwrRUFBRixFQUFrRixZQUFZO0FBQzlGYyxRQUFBQSxJQUFJLENBQUNlLFdBQUwsR0FBbUI7QUFDakJ2QixVQUFBQSxHQUFHLEVBQUU7QUFEWSxTQUFuQjtBQUdBUSxRQUFBQSxJQUFJLENBQUNrQixVQUFMLEdBQWtCLENBQUM7QUFDakJYLFVBQUFBLEtBQUssRUFBRTtBQURVLFNBQUQsRUFFZjtBQUNEYyxVQUFBQSxPQUFPLEVBQUU7QUFEUixTQUZlLENBQWxCO0FBS0FyQyxRQUFBQSxNQUFNLENBQUNPLEtBQVAsQ0FBYSw2QkFBVVMsSUFBVixFQUFnQjtBQUFDc0IsVUFBQUEsYUFBYSxFQUFFO0FBQUM3QixZQUFBQSxRQUFRLEVBQUU7QUFBWDtBQUFoQixTQUFoQixFQUFtRDJCLFdBQWhFLEVBQTZFLElBQTdFO0FBQ0QsT0FWQyxDQUFGO0FBWUFsQyxNQUFBQSxFQUFFLENBQUMsOEZBQUQsRUFBaUcsWUFBWTtBQUM3R2MsUUFBQUEsSUFBSSxDQUFDZSxXQUFMLEdBQW1CO0FBQ2pCdkIsVUFBQUEsR0FBRyxFQUFFO0FBRFksU0FBbkI7QUFHQVEsUUFBQUEsSUFBSSxDQUFDa0IsVUFBTCxHQUFrQixDQUNoQjtBQUFDMUIsVUFBQUEsR0FBRyxFQUFFO0FBQU4sU0FEZ0IsRUFFaEI7QUFBQ0EsVUFBQUEsR0FBRyxFQUFFO0FBQU4sU0FGZ0IsQ0FBbEI7QUFLQSxZQUFJYSxXQUFXLEdBQUc7QUFDaEJiLFVBQUFBLEdBQUcsRUFBRTtBQUNIQyxZQUFBQSxRQUFRLEVBQUUsSUFEUDtBQUVIRSxZQUFBQSxRQUFRLEVBQUU7QUFGUDtBQURXLFNBQWxCO0FBT0EscUNBQVVLLElBQVYsRUFBZ0JLLFdBQWhCLEVBQTZCYyx1QkFBN0IsQ0FBcURuQyxNQUFyRCxDQUE0RE0sSUFBNUQsQ0FBaUVDLEtBQWpFLENBQXVFUyxJQUFJLENBQUNrQixVQUE1RTtBQUNELE9BakJDLENBQUY7QUFtQkFoQyxNQUFBQSxFQUFFLENBQUMsc0VBQUQsRUFBeUUsWUFBWTtBQUNyRmMsUUFBQUEsSUFBSSxDQUFDZSxXQUFMLEdBQW1CLGlDQUFuQjtBQUNBZixRQUFBQSxJQUFJLENBQUNrQixVQUFMLEdBQWtCLENBQUM7QUFBQzFCLFVBQUFBLEdBQUcsRUFBRTtBQUFOLFNBQUQsRUFBZSxLQUFmLENBQWxCO0FBQ0EsU0FBQyxNQUFNLDZCQUFVUSxJQUFWLEVBQWdCLEVBQWhCLENBQVAsRUFBNEJoQixNQUE1QixDQUFtQ0ssS0FBbkMsQ0FBeUMsdUJBQXpDO0FBQ0QsT0FKQyxDQUFGO0FBS0QsS0E5RE8sQ0FBUjtBQWdFQUosSUFBQUEsUUFBUSxDQUFDLGtDQUFELEVBQXFDLFlBQVk7QUFDdkQ2QixNQUFBQSxVQUFVLENBQUMsWUFBWTtBQUNyQmQsUUFBQUEsSUFBSSxDQUFDZSxXQUFMLEdBQW1CO0FBQUNSLFVBQUFBLEtBQUssRUFBRTtBQUFSLFNBQW5CO0FBQ0QsT0FGUyxDQUFWO0FBSUFyQixNQUFBQSxFQUFFLENBQUMsa0VBQUQsRUFBcUUsWUFBWTtBQUNqRixxQ0FBVWMsSUFBVixFQUFnQm9CLFdBQWhCLENBQTRCcEMsTUFBNUIsQ0FBbUNNLElBQW5DLENBQXdDQyxLQUF4QyxDQUE4QztBQUFDZ0IsVUFBQUEsS0FBSyxFQUFFO0FBQVIsU0FBOUM7QUFDRCxPQUZDLENBQUY7QUFJQXJCLE1BQUFBLEVBQUUsQ0FBQyxzQkFBRCxFQUF5QixZQUFZO0FBQ3JDYyxRQUFBQSxJQUFJLENBQUNrQixVQUFMLEdBQWtCLENBQUM7QUFBQzFCLFVBQUFBLEdBQUcsRUFBRTtBQUFOLFNBQUQsQ0FBbEI7QUFDQSxxQ0FBVVEsSUFBVixFQUFnQm9CLFdBQWhCLENBQTRCcEMsTUFBNUIsQ0FBbUNNLElBQW5DLENBQXdDQyxLQUF4QyxDQUE4QztBQUFDZ0IsVUFBQUEsS0FBSyxFQUFFLE9BQVI7QUFBaUJmLFVBQUFBLEdBQUcsRUFBRTtBQUF0QixTQUE5QztBQUNELE9BSEMsQ0FBRjtBQUtBTixNQUFBQSxFQUFFLENBQUMsa0JBQUQsRUFBcUIsWUFBWTtBQUNqQ2MsUUFBQUEsSUFBSSxDQUFDa0IsVUFBTCxHQUFrQixDQUFDO0FBQUNYLFVBQUFBLEtBQUssRUFBRSxLQUFSO0FBQWVmLFVBQUFBLEdBQUcsRUFBRTtBQUFwQixTQUFELEVBQTZCO0FBQUNBLFVBQUFBLEdBQUcsRUFBRTtBQUFOLFNBQTdCLENBQWxCO0FBQ0EscUNBQVVRLElBQVYsRUFBZ0JvQixXQUFoQixDQUE0QnBDLE1BQTVCLENBQW1DTSxJQUFuQyxDQUF3Q0MsS0FBeEMsQ0FBOEM7QUFBQ2dCLFVBQUFBLEtBQUssRUFBRSxPQUFSO0FBQWlCZixVQUFBQSxHQUFHLEVBQUU7QUFBdEIsU0FBOUM7QUFDRCxPQUhDLENBQUY7QUFJRCxLQWxCTyxDQUFSO0FBbUJELEdBL0hPLENBQVI7QUFpSUFQLEVBQUFBLFFBQVEsQ0FBQyxjQUFELEVBQWlCLFlBQVk7QUFDbkNDLElBQUFBLEVBQUUsQ0FBQyxpRkFBRCxFQUFvRixZQUFZO0FBQ2hHLDZDQUFvQixFQUFwQixFQUF3QkYsTUFBeEIsQ0FBK0JNLElBQS9CLENBQW9DQyxLQUFwQyxDQUEwQyxFQUExQztBQUNELEtBRkMsQ0FBRjtBQUlBTCxJQUFBQSxFQUFFLENBQUMsMkJBQUQsRUFBOEIsWUFBWTtBQUMxQyw2Q0FBb0I7QUFDbEI2QixRQUFBQSxXQUFXLEVBQUU7QUFBQ1IsVUFBQUEsS0FBSyxFQUFFO0FBQVIsU0FESztBQUVsQlcsUUFBQUEsVUFBVSxFQUFFLENBQUM7QUFBQzFCLFVBQUFBLEdBQUcsRUFBRTtBQUFOLFNBQUQ7QUFGTSxPQUFwQixFQUdHUixNQUhILENBR1VNLElBSFYsQ0FHZUMsS0FIZixDQUdxQjtBQUFDZ0IsUUFBQUEsS0FBSyxFQUFFLE9BQVI7QUFBaUJmLFFBQUFBLEdBQUcsRUFBRTtBQUF0QixPQUhyQjtBQUlELEtBTEMsQ0FBRjtBQU9BTixJQUFBQSxFQUFFLENBQUMscUVBQUQsRUFBd0UsWUFBWTtBQUNwRiw2Q0FBb0I7QUFDbEI2QixRQUFBQSxXQUFXLEVBQUU7QUFBQywwQkFBZ0I7QUFBakIsU0FESztBQUVsQkcsUUFBQUEsVUFBVSxFQUFFLENBQUM7QUFBQyx3QkFBYztBQUFmLFNBQUQ7QUFGTSxPQUFwQixFQUdHbEMsTUFISCxDQUdVTSxJQUhWLENBR2VDLEtBSGYsQ0FHcUI7QUFBQ2dCLFFBQUFBLEtBQUssRUFBRSxPQUFSO0FBQWlCZixRQUFBQSxHQUFHLEVBQUU7QUFBdEIsT0FIckI7QUFJRCxLQUxDLENBQUY7QUFPQU4sSUFBQUEsRUFBRSxDQUFDLHNJQUFELEVBQXlJLFlBQVk7QUFDckosT0FBQyxNQUFNLHVDQUFvQjtBQUN6QjZCLFFBQUFBLFdBQVcsRUFBRTtBQUFDLGlDQUF1QjtBQUF4QixTQURZO0FBRXpCRyxRQUFBQSxVQUFVLEVBQUUsQ0FBQztBQUFDLGdDQUFzQjtBQUF2QixTQUFEO0FBRmEsT0FBcEIsQ0FBUCxFQUdJbEMsTUFISixDQUdXSyxLQUhYLENBR2lCLHVCQUhqQjtBQUlELEtBTEMsQ0FBRjtBQU9BSCxJQUFBQSxFQUFFLENBQUMsNEZBQUQsRUFBK0YsWUFBWTtBQUMzRyxZQUFNYyxJQUFJLEdBQUcsdUNBQW9CO0FBQy9CZSxRQUFBQSxXQUFXLEVBQUU7QUFBQywwQkFBZ0IsTUFBakI7QUFBeUIsNEJBQWtCO0FBQTNDLFNBRGtCO0FBRS9CRyxRQUFBQSxVQUFVLEVBQUUsQ0FBQztBQUFDLGlCQUFPO0FBQVIsU0FBRDtBQUZtQixPQUFwQixFQUdWO0FBQ0RLLFFBQUFBLFlBQVksRUFBRTtBQUNaOUIsVUFBQUEsUUFBUSxFQUFFO0FBREUsU0FEYjtBQUlEK0IsUUFBQUEsT0FBTyxFQUFFO0FBQ1AvQixVQUFBQSxRQUFRLEVBQUU7QUFESDtBQUpSLE9BSFUsQ0FBYjtBQVlBTyxNQUFBQSxJQUFJLENBQUN1QixZQUFMLENBQWtCdkMsTUFBbEIsQ0FBeUJPLEtBQXpCLENBQStCLE1BQS9CO0FBQ0FTLE1BQUFBLElBQUksQ0FBQ3dCLE9BQUwsQ0FBYXhDLE1BQWIsQ0FBb0JPLEtBQXBCLENBQTBCLFFBQTFCO0FBQ0FTLE1BQUFBLElBQUksQ0FBQ1IsR0FBTCxDQUFTUixNQUFULENBQWdCTyxLQUFoQixDQUFzQixLQUF0QjtBQUNELEtBaEJDLENBQUY7QUFrQkFMLElBQUFBLEVBQUUsQ0FBQywwREFBRCxFQUE2RCxZQUFZO0FBQ3pFLE9BQUMsTUFBTSx1Q0FBb0I7QUFDekI2QixRQUFBQSxXQUFXLEVBQUU7QUFBQywwQkFBZ0IsTUFBakI7QUFBeUIsNEJBQWtCO0FBQTNDLFNBRFk7QUFFekJHLFFBQUFBLFVBQVUsRUFBRSxDQUFDO0FBQUMsaUJBQU87QUFBUixTQUFEO0FBRmEsT0FBcEIsRUFHSjtBQUNESyxRQUFBQSxZQUFZLEVBQUU7QUFDWjlCLFVBQUFBLFFBQVEsRUFBRTtBQURFLFNBRGI7QUFJRCtCLFFBQUFBLE9BQU8sRUFBRTtBQUNQL0IsVUFBQUEsUUFBUSxFQUFFO0FBREgsU0FKUjtBQU9EZ0MsUUFBQUEsVUFBVSxFQUFFO0FBQ1ZoQyxVQUFBQSxRQUFRLEVBQUU7QUFEQTtBQVBYLE9BSEksQ0FBUCxFQWFJVCxNQWJKLENBYVdLLEtBYlgsQ0FhaUIsNkJBYmpCO0FBY0QsS0FmQyxDQUFGO0FBaUJBSixJQUFBQSxRQUFRLENBQUMsNkJBQUQsRUFBZ0MsWUFBWTtBQUNsRCxVQUFJb0IsV0FBVyxHQUFHLEVBQUMsR0FBR3FCO0FBQUosT0FBbEI7QUFFQSxVQUFJQyxZQUFZLEdBQUc7QUFBQyx3QkFBZ0IsTUFBakI7QUFBeUIsMEJBQWtCLE1BQTNDO0FBQW1ELHNCQUFjO0FBQWpFLE9BQW5CO0FBQ0EsVUFBSTNCLElBQUo7QUFFQWQsTUFBQUEsRUFBRSxDQUFDLHNEQUFELEVBQXlELFlBQVk7QUFDckVjLFFBQUFBLElBQUksR0FBRztBQUNMZSxVQUFBQSxXQUFXLEVBQUVZLFlBRFI7QUFFTFQsVUFBQUEsVUFBVSxFQUFFLENBQUMsRUFBRDtBQUZQLFNBQVA7QUFJQSwrQ0FBb0JsQixJQUFwQixFQUEwQkssV0FBMUIsRUFBdUNyQixNQUF2QyxDQUE4Q00sSUFBOUMsQ0FBbURDLEtBQW5ELENBQXlEb0MsWUFBekQ7QUFDRCxPQU5DLENBQUY7QUFTQXpDLE1BQUFBLEVBQUUsQ0FBQyx3REFBRCxFQUEyRCxZQUFZO0FBQ3ZFYyxRQUFBQSxJQUFJLEdBQUc7QUFDTGUsVUFBQUEsV0FBVyxFQUFFLEVBRFI7QUFFTEcsVUFBQUEsVUFBVSxFQUFFLENBQUNTLFlBQUQ7QUFGUCxTQUFQO0FBSUEsK0NBQW9CM0IsSUFBcEIsRUFBMEJLLFdBQTFCLEVBQXVDckIsTUFBdkMsQ0FBOENNLElBQTlDLENBQW1EQyxLQUFuRCxDQUF5RG9DLFlBQXpEO0FBQ0QsT0FOQyxDQUFGO0FBUUF6QyxNQUFBQSxFQUFFLENBQUMsOEZBQUQsRUFBaUcsWUFBWTtBQUM3R2MsUUFBQUEsSUFBSSxHQUFHO0FBQ0xlLFVBQUFBLFdBQVcsRUFBRWEsZ0JBQUVDLElBQUYsQ0FBT0YsWUFBUCxFQUFxQixDQUFDLFlBQUQsQ0FBckIsQ0FEUjtBQUVMVCxVQUFBQSxVQUFVLEVBQUUsQ0FBQztBQUFDLGlDQUFxQjtBQUF0QixXQUFEO0FBRlAsU0FBUDtBQUlBLCtDQUFvQmxCLElBQXBCLEVBQTBCSyxXQUExQixFQUF1Q3JCLE1BQXZDLENBQThDTSxJQUE5QyxDQUFtREMsS0FBbkQsQ0FBeURvQyxZQUF6RDtBQUNELE9BTkMsQ0FBRjtBQVFBekMsTUFBQUEsRUFBRSxDQUFDLGdEQUFELEVBQW1ELFlBQVk7QUFDL0RjLFFBQUFBLElBQUksR0FBRztBQUNMZSxVQUFBQSxXQUFXLEVBQUVhLGdCQUFFQyxJQUFGLENBQU9GLFlBQVAsRUFBcUIsQ0FBQyxnQkFBRCxDQUFyQjtBQURSLFNBQVA7QUFHQSwrQ0FBb0IzQixJQUFwQixFQUEwQkssV0FBMUIsRUFBdUNyQixNQUF2QyxDQUE4Q00sSUFBOUMsQ0FBbURDLEtBQW5ELENBQXlEcUMsZ0JBQUVDLElBQUYsQ0FBT0YsWUFBUCxFQUFxQixnQkFBckIsQ0FBekQ7QUFDRCxPQUxDLENBQUY7QUFPQXpDLE1BQUFBLEVBQUUsQ0FBQyx3RkFBRCxFQUEyRixZQUFZO0FBQ3ZHYyxRQUFBQSxJQUFJLEdBQUc7QUFDTGUsVUFBQUEsV0FBVyxFQUFFLEVBRFI7QUFFTEcsVUFBQUEsVUFBVSxFQUFFLENBQ1ZTLFlBRFUsRUFFVjtBQUFDRyxZQUFBQSxPQUFPLEVBQUU7QUFBVixXQUZVO0FBRlAsU0FBUDtBQU9BLCtDQUFvQjlCLElBQXBCLEVBQTBCSyxXQUExQixFQUF1Q3JCLE1BQXZDLENBQThDTSxJQUE5QyxDQUFtREMsS0FBbkQsQ0FBeURvQyxZQUF6RDtBQUNELE9BVEMsQ0FBRjtBQVdBekMsTUFBQUEsRUFBRSxDQUFDLHdGQUFELEVBQTJGLFlBQVk7QUFDdkdjLFFBQUFBLElBQUksR0FBRztBQUNMZSxVQUFBQSxXQUFXLEVBQUUsRUFEUjtBQUVMRyxVQUFBQSxVQUFVLEVBQUUsQ0FDVjtBQUFDWSxZQUFBQSxPQUFPLEVBQUU7QUFBVixXQURVLEVBRVZILFlBRlU7QUFGUCxTQUFQO0FBT0EsK0NBQW9CM0IsSUFBcEIsRUFBMEJLLFdBQTFCLEVBQXVDckIsTUFBdkMsQ0FBOENNLElBQTlDLENBQW1EQyxLQUFuRCxDQUF5RG9DLFlBQXpEO0FBQ0QsT0FUQyxDQUFGO0FBV0F6QyxNQUFBQSxFQUFFLENBQUMsc0NBQUQsRUFBeUMsWUFBWTtBQUNyRGMsUUFBQUEsSUFBSSxHQUFHO0FBQ0xlLFVBQUFBLFdBQVcsRUFBRWEsZ0JBQUVDLElBQUYsQ0FBT0YsWUFBUCxFQUFxQixDQUFDLFlBQUQsQ0FBckI7QUFEUixTQUFQO0FBR0EsU0FBQyxNQUFNLHVDQUFvQjNCLElBQXBCLEVBQTBCSyxXQUExQixDQUFQLEVBQStDckIsTUFBL0MsQ0FBc0RLLEtBQXRELENBQTRELDZCQUE1RDtBQUNELE9BTEMsQ0FBRjtBQU9BSCxNQUFBQSxFQUFFLENBQUMsbUZBQUQsRUFBc0YsWUFBWTtBQUNsR2MsUUFBQUEsSUFBSSxHQUFHO0FBQ0xlLFVBQUFBLFdBQVcsRUFBRSxFQURSO0FBRUxHLFVBQUFBLFVBQVUsRUFBRSxDQUFDO0FBQ1hhLFlBQUFBLEdBQUcsRUFBRTtBQURNLFdBQUQsRUFFVDtBQUNEQyxZQUFBQSxJQUFJLEVBQUU7QUFETCxXQUZTO0FBRlAsU0FBUDtBQVFBLFNBQUMsTUFBTSx1Q0FBb0JoQyxJQUFwQixFQUEwQkssV0FBMUIsQ0FBUCxFQUErQ3JCLE1BQS9DLENBQXNESyxLQUF0RCxDQUE0RCxzQ0FBNUQ7QUFDRCxPQVZDLENBQUY7QUFXRCxLQTlFTyxDQUFSO0FBK0VELEdBNUlPLENBQVI7QUE2SUFKLEVBQUFBLFFBQVEsQ0FBQyxzQkFBRCxFQUF5QixZQUFZO0FBQzNDQyxJQUFBQSxFQUFFLENBQUMsNkNBQUQsRUFBZ0QsWUFBWTtBQUM1RCw2Q0FBb0I7QUFBQzZCLFFBQUFBLFdBQVcsRUFBRTtBQUNoQywwQkFBZ0I7QUFEZ0I7QUFBZCxPQUFwQixFQUVJL0IsTUFGSixDQUVXaUQsR0FGWCxDQUVlLENBQUMsY0FBRCxDQUZmO0FBR0QsS0FKQyxDQUFGO0FBS0EvQyxJQUFBQSxFQUFFLENBQUMsK0NBQUQsRUFBa0QsWUFBWTtBQUM5RCw2Q0FBb0I7QUFBQzZCLFFBQUFBLFdBQVcsRUFBRTtBQUNoQywwQkFBZ0I7QUFEZ0I7QUFBZCxPQUFwQixFQUVJL0IsTUFGSixDQUVXaUQsR0FGWCxDQUVlLEVBRmY7QUFHRCxLQUpDLENBQUY7QUFLQS9DLElBQUFBLEVBQUUsQ0FBQyw0Q0FBRCxFQUErQyxZQUFZO0FBQzNELDZDQUFvQjtBQUFDNkIsUUFBQUEsV0FBVyxFQUFFLEVBQWQ7QUFBa0JHLFFBQUFBLFVBQVUsRUFBRSxDQUFDO0FBQ2pELDBCQUFnQjtBQURpQyxTQUFEO0FBQTlCLE9BQXBCLEVBRUtsQyxNQUZMLENBRVlpRCxHQUZaLENBRWdCLENBQUMsY0FBRCxDQUZoQjtBQUdELEtBSkMsQ0FBRjtBQUtBL0MsSUFBQUEsRUFBRSxDQUFDLDBDQUFELEVBQTZDLFlBQVk7QUFDekQsNkNBQW9CO0FBQUM2QixRQUFBQSxXQUFXLEVBQUUsRUFBZDtBQUFrQkcsUUFBQUEsVUFBVSxFQUFFLENBQUM7QUFDakQsMEJBQWdCO0FBRGlDLFNBQUQ7QUFBOUIsT0FBcEIsRUFFS2xDLE1BRkwsQ0FFWWlELEdBRlosQ0FFZ0IsRUFGaEI7QUFHRCxLQUpDLENBQUY7QUFLQS9DLElBQUFBLEVBQUUsQ0FBQyxnRUFBRCxFQUFtRSxZQUFZO0FBQy9FLDZDQUFvQjtBQUFDNkIsUUFBQUEsV0FBVyxFQUFFLEVBQWQ7QUFBa0JHLFFBQUFBLFVBQVUsRUFBRSxDQUFDLEVBQUQsRUFBSztBQUNyRCwwQkFBZ0I7QUFEcUMsU0FBTDtBQUE5QixPQUFwQixFQUVLbEMsTUFGTCxDQUVZaUQsR0FGWixDQUVnQixDQUFDLGNBQUQsQ0FGaEI7QUFHRCxLQUpDLENBQUY7QUFLQS9DLElBQUFBLEVBQUUsQ0FBQywwREFBRCxFQUE2RCxZQUFZO0FBQ3pFLDZDQUFvQjtBQUFDNkIsUUFBQUEsV0FBVyxFQUFFO0FBQ2hDLDBCQUFnQjtBQURnQixTQUFkO0FBRWpCRyxRQUFBQSxVQUFVLEVBQUUsQ0FBQztBQUNkLDBCQUFnQjtBQURGLFNBQUQ7QUFGSyxPQUFwQixFQUlLbEMsTUFKTCxDQUlZaUQsR0FKWixDQUlnQixDQUFDLGNBQUQsQ0FKaEI7QUFLRCxLQU5DLENBQUY7QUFPQS9DLElBQUFBLEVBQUUsQ0FBQywwQ0FBRCxFQUE2QyxZQUFZO0FBQ3pELDZDQUFvQjtBQUFDZ0MsUUFBQUEsVUFBVSxFQUFFLENBQUM7QUFDaEMsMEJBQWdCO0FBRGdCLFNBQUQsRUFFOUI7QUFDRCwwQkFBZ0I7QUFEZixTQUY4QjtBQUFiLE9BQXBCLEVBSUtsQyxNQUpMLENBSVlpRCxHQUpaLENBSWdCLENBQUMsY0FBRCxDQUpoQjtBQUtELEtBTkMsQ0FBRjtBQU9BL0MsSUFBQUEsRUFBRSxDQUFDLHlEQUFELEVBQTRELFlBQVk7QUFDeEUsWUFBTTZCLFdBQVcsR0FBRztBQUNsQlEsUUFBQUEsWUFBWSxFQUFFLE1BREk7QUFFbEJXLFFBQUFBLGNBQWMsRUFBRSxjQUZFO0FBR2xCQyxRQUFBQSxjQUFjLEVBQUU7QUFIRSxPQUFwQjtBQUtBLFlBQU1qQixVQUFVLEdBQUcsQ0FDakI7QUFBQ2tCLFFBQUFBLGdCQUFnQixFQUFFLGNBQW5CO0FBQW1DQyxRQUFBQSxlQUFlLEVBQUUsY0FBcEQ7QUFBb0VDLFFBQUFBLFdBQVcsRUFBRTtBQUFqRixPQURpQixFQUVqQjtBQUFDRixRQUFBQSxnQkFBZ0IsRUFBRSxjQUFuQjtBQUFtQ0MsUUFBQUEsZUFBZSxFQUFFLGNBQXBEO0FBQW9FRSxRQUFBQSxlQUFlLEVBQUUsY0FBckY7QUFBcUdDLFFBQUFBLGNBQWMsRUFBRTtBQUFySCxPQUZpQixDQUFuQjtBQUlBLDZDQUFvQjtBQUFDekIsUUFBQUEsV0FBRDtBQUFjRyxRQUFBQTtBQUFkLE9BQXBCLEVBQStDbEMsTUFBL0MsQ0FBc0RpRCxHQUF0RCxDQUEwRCxDQUFDLGdCQUFELEVBQW1CLGdCQUFuQixFQUFxQyxrQkFBckMsRUFBeUQsaUJBQXpELEVBQTRFLGlCQUE1RSxDQUExRDtBQUNELEtBWEMsQ0FBRjtBQVlELEdBcERPLENBQVI7QUFxREQsQ0FoYU8sQ0FBUiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHBhcnNlQ2FwcywgdmFsaWRhdGVDYXBzLCBtZXJnZUNhcHMsIHByb2Nlc3NDYXBhYmlsaXRpZXMsIGZpbmROb25QcmVmaXhlZENhcHMgfSBmcm9tICcuLi8uLi9saWIvYmFzZWRyaXZlci9jYXBhYmlsaXRpZXMnO1xuaW1wb3J0IGNoYWkgZnJvbSAnY2hhaSc7XG5pbXBvcnQgY2hhaUFzUHJvbWlzZWQgZnJvbSAnY2hhaS1hcy1wcm9taXNlZCc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgZGVzaXJlZENhcGFiaWxpdHlDb25zdHJhaW50cyB9IGZyb20gJy4uLy4uL2xpYi9iYXNlZHJpdmVyL2Rlc2lyZWQtY2Fwcyc7XG5cbmNoYWkudXNlKGNoYWlBc1Byb21pc2VkKTtcbmNvbnN0IHNob3VsZCA9IGNoYWkuc2hvdWxkKCk7XG5cbmRlc2NyaWJlKCdjYXBzJywgZnVuY3Rpb24gKCkge1xuXG4gIC8vIFRlc3RzIGJhc2VkIG9uOiBodHRwczovL3d3dy53My5vcmcvVFIvd2ViZHJpdmVyLyNkZm4tdmFsaWRhdGUtY2Fwc1xuICBkZXNjcmliZSgnI3ZhbGlkYXRlQ2FwcycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgncmV0dXJucyBpbnZhbGlkIGFyZ3VtZW50IGVycm9yIGlmIFwiY2FwYWJpbGl0eVwiIGlzIG5vdCBhIEpTT04gb2JqZWN0ICgxKScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZvciAobGV0IGFyZyBvZiBbdW5kZWZpbmVkLCBudWxsLCAxLCB0cnVlLCAnc3RyaW5nJ10pIHtcbiAgICAgICAgKGZ1bmN0aW9uICgpIHsgdmFsaWRhdGVDYXBzKGFyZyk7IH0pLnNob3VsZC50aHJvdygvbXVzdCBiZSBhIEpTT04gb2JqZWN0Lyk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgncmV0dXJucyByZXN1bHQge30gYnkgZGVmYXVsdCBpZiBjYXBzIGlzIGVtcHR5IG9iamVjdCBhbmQgbm8gY29uc3RyYWludHMgcHJvdmlkZWQgKDIpJywgZnVuY3Rpb24gKCkge1xuICAgICAgdmFsaWRhdGVDYXBzKHt9KS5zaG91bGQuZGVlcC5lcXVhbCh7fSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgndGhyb3dzIGVycm9ycyBpZiBjb25zdHJhaW50cyBhcmUgbm90IG1ldCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGl0KCdyZXR1cm5zIGludmFsaWQgYXJndW1lbnQgZXJyb3IgaWYgXCJwcmVzZW50XCIgY29uc3RyYWludCBub3QgbWV0IG9uIHByb3BlcnR5JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAoKCkgPT4gdmFsaWRhdGVDYXBzKHt9LCB7Zm9vOiB7cHJlc2VuY2U6IHRydWV9fSkpLnNob3VsZC50aHJvdygvJ2ZvbycgY2FuJ3QgYmUgYmxhbmsvKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgncmV0dXJucyB0aGUgY2FwYWJpbGl0eSB0aGF0IHdhcyBwYXNzZWQgaW4gaWYgXCJza2lwUHJlc2VuY2VDb25zdHJhaW50XCIgaXMgZmFsc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhbGlkYXRlQ2Fwcyh7fSwge2Zvbzoge3ByZXNlbmNlOiB0cnVlfX0sIHtza2lwUHJlc2VuY2VDb25zdHJhaW50OiB0cnVlfSkuc2hvdWxkLmRlZXAuZXF1YWwoe30pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdyZXR1cm5zIGludmFsaWQgYXJndW1lbnQgZXJyb3IgaWYgXCJpc1N0cmluZ1wiIGNvbnN0cmFpbnQgbm90IG1ldCBvbiBwcm9wZXJ0eScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgKCgpID0+IHZhbGlkYXRlQ2Fwcyh7Zm9vOiAxfSwge2Zvbzoge2lzU3RyaW5nOiB0cnVlfX0pKS5zaG91bGQudGhyb3coLydmb28nIG11c3QgYmUgb2YgdHlwZSBzdHJpbmcvKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgncmV0dXJucyBpbnZhbGlkIGFyZ3VtZW50IGVycm9yIGlmIFwiaXNOdW1iZXJcIiBjb25zdHJhaW50IG5vdCBtZXQgb24gcHJvcGVydHknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICgoKSA9PiB2YWxpZGF0ZUNhcHMoe2ZvbzogJ2Jhcid9LCB7Zm9vOiB7aXNOdW1iZXI6IHRydWV9fSkpLnNob3VsZC50aHJvdygvJ2ZvbycgbXVzdCBiZSBvZiB0eXBlIG51bWJlci8pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdyZXR1cm5zIGludmFsaWQgYXJndW1lbnQgZXJyb3IgaWYgXCJpc0Jvb2xlYW5cIiBjb25zdHJhaW50IG5vdCBtZXQgb24gcHJvcGVydHknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICgoKSA9PiB2YWxpZGF0ZUNhcHMoe2ZvbzogJ2Jhcid9LCB7Zm9vOiB7aXNCb29sZWFuOiB0cnVlfX0pKS5zaG91bGQudGhyb3coLydmb28nIG11c3QgYmUgb2YgdHlwZSBib29sZWFuLyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3JldHVybnMgaW52YWxpZCBhcmd1bWVudCBlcnJvciBpZiBcImluY2x1c2lvblwiIGNvbnN0cmFpbnQgbm90IG1ldCBvbiBwcm9wZXJ0eScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgKCgpID0+IHZhbGlkYXRlQ2Fwcyh7Zm9vOiAnMyd9LCB7Zm9vOiB7aW5jbHVzaW9uQ2FzZUluc2Vuc2l0aXZlOiBbJzEnLCAnMiddfX0pKS5zaG91bGQudGhyb3coLydmb28nIDMgbm90IHBhcnQgb2YgMSwyLyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3JldHVybnMgaW52YWxpZCBhcmd1bWVudCBlcnJvciBpZiBcImluY2x1c2lvbkNhc2VJbnNlbnNpdGl2ZVwiIGNvbnN0cmFpbnQgbm90IG1ldCBvbiBwcm9wZXJ0eScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgKCgpID0+IHZhbGlkYXRlQ2Fwcyh7Zm9vOiAnYSd9LCB7Zm9vOiB7aW5jbHVzaW9uOiBbJ0EnLCAnQicsICdDJ119fSkpLnNob3VsZC50aHJvdygvJ2ZvbycgYSBpcyBub3QgaW5jbHVkZWQgaW4gdGhlIGxpc3QvKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBub3QgdGhyb3cgZXJyb3JzIGlmIGNvbnN0cmFpbnRzIGFyZSBtZXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgY2FwcyA9IHtcbiAgICAgICAgbnVtYmVyOiAxLFxuICAgICAgICBzdHJpbmc6ICdzdHJpbmcnLFxuICAgICAgICBwcmVzZW50OiAncHJlc2VudCcsXG4gICAgICAgIGV4dHJhOiAnZXh0cmEnLFxuICAgICAgfTtcblxuICAgICAgbGV0IGNvbnN0cmFpbnRzID0ge1xuICAgICAgICBudW1iZXI6IHtpc051bWJlcjogdHJ1ZX0sXG4gICAgICAgIHN0cmluZzoge2lzU3RyaW5nOiB0cnVlfSxcbiAgICAgICAgcHJlc2VudDoge3ByZXNlbmNlOiB0cnVlfSxcbiAgICAgICAgbm90UHJlc2VudDoge3ByZXNlbmNlOiBmYWxzZX0sXG4gICAgICB9O1xuXG4gICAgICB2YWxpZGF0ZUNhcHMoY2FwcywgY29uc3RyYWludHMpLnNob3VsZC5kZWVwLmVxdWFsKGNhcHMpO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyBUZXN0cyBiYXNlZCBvbjogaHR0cHM6Ly93d3cudzMub3JnL1RSL3dlYmRyaXZlci8jZGZuLW1lcmdpbmctY2Fwc1xuICBkZXNjcmliZSgnI21lcmdlQ2FwcycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgncmV0dXJucyBhIHJlc3VsdCB0aGF0IGlzIHt9IGJ5IGRlZmF1bHQgKDEpJywgZnVuY3Rpb24gKCkge1xuICAgICAgbWVyZ2VDYXBzKCkuc2hvdWxkLmRlZXAuZXF1YWwoe30pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JldHVybnMgYSByZXN1bHQgdGhhdCBtYXRjaGVzIHByaW1hcnkgYnkgZGVmYXVsdCAoMiwgMyknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBtZXJnZUNhcHMoe2hlbGxvOiAnd29ybGQnfSkuc2hvdWxkLmRlZXAuZXF1YWwoe2hlbGxvOiAnd29ybGQnfSk7XG4gICAgfSk7XG5cbiAgICBpdCgncmV0dXJucyBpbnZhbGlkIGFyZ3VtZW50IGVycm9yIGlmIHByaW1hcnkgYW5kIHNlY29uZGFyeSBoYXZlIG1hdGNoaW5nIHByb3BlcnRpZXMgKDQpJywgZnVuY3Rpb24gKCkge1xuICAgICAgKCgpID0+IG1lcmdlQ2Fwcyh7aGVsbG86ICd3b3JsZCd9LCB7aGVsbG86ICd3aGlybCd9KSkuc2hvdWxkLnRocm93KC9wcm9wZXJ0eSAnaGVsbG8nIHNob3VsZCBub3QgZXhpc3Qgb24gYm90aCBwcmltYXJ5IFtcXHdcXFddKiBhbmQgc2Vjb25kYXJ5IFtcXHdcXFddKi8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JldHVybnMgYSByZXN1bHQgd2l0aCBrZXlzIGZyb20gcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHRvZ2V0aGVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IHByaW1hcnkgPSB7XG4gICAgICAgIGE6ICdhJyxcbiAgICAgICAgYjogJ2InLFxuICAgICAgfTtcbiAgICAgIGxldCBzZWNvbmRhcnkgPSB7XG4gICAgICAgIGM6ICdjJyxcbiAgICAgICAgZDogJ2QnLFxuICAgICAgfTtcbiAgICAgIG1lcmdlQ2FwcyhwcmltYXJ5LCBzZWNvbmRhcnkpLnNob3VsZC5kZWVwLmVxdWFsKHtcbiAgICAgICAgYTogJ2EnLCBiOiAnYicsIGM6ICdjJywgZDogJ2QnLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIFRlc3RzIGJhc2VkIG9uOiBodHRwczovL3d3dy53My5vcmcvVFIvd2ViZHJpdmVyLyNwcm9jZXNzaW5nLWNhcHNcbiAgZGVzY3JpYmUoJyNwYXJzZUNhcHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGNhcHM7XG5cbiAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhcHMgPSB7fTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGludmFsaWQgYXJndW1lbnQgaWYgbm8gY2FwcyBvYmplY3QgcHJvdmlkZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAoKCkgPT4gcGFyc2VDYXBzKCkpLnNob3VsZC50aHJvdygvbXVzdCBiZSBhIEpTT04gb2JqZWN0Lyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2V0cyBcInJlcXVpcmVkQ2Fwc1wiIHRvIHByb3BlcnR5IG5hbWVkIFwiYWx3YXlzTWF0Y2hcIiAoMiknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjYXBzLmFsd2F5c01hdGNoID0ge2hlbGxvOiAnd29ybGQnfTtcbiAgICAgIHBhcnNlQ2FwcyhjYXBzKS5yZXF1aXJlZENhcHMuc2hvdWxkLmRlZXAuZXF1YWwoY2Fwcy5hbHdheXNNYXRjaCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2V0cyBcInJlcXVpcmVkQ2Fwc1wiIHRvIGVtcHR5IEpTT04gb2JqZWN0IGlmIFwiYWx3YXlzTWF0Y2hcIiBpcyBub3QgYW4gb2JqZWN0ICgyLjEpJywgZnVuY3Rpb24gKCkge1xuICAgICAgcGFyc2VDYXBzKGNhcHMpLnJlcXVpcmVkQ2Fwcy5zaG91bGQuZGVlcC5lcXVhbCh7fSk7XG4gICAgfSk7XG5cbiAgICBpdCgncmV0dXJucyBpbnZhbGlkIGFyZ3VtZW50IGVycm9yIGlmIFwicmVxdWlyZWRDYXBzXCIgZG9uXFwndCBtYXRjaCBcImNvbnN0cmFpbnRzXCIgKDIuMiknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjYXBzLmFsd2F5c01hdGNoID0ge2ZvbzogMX07XG4gICAgICAoKCkgPT4gcGFyc2VDYXBzKGNhcHMsIHtmb286IHtpc1N0cmluZzogdHJ1ZX19KSkuc2hvdWxkLnRocm93KC8nZm9vJyBtdXN0IGJlIG9mIHR5cGUgc3RyaW5nLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2V0cyBcImFsbEZpcnN0TWF0Y2hDYXBzXCIgdG8gcHJvcGVydHkgbmFtZWQgXCJmaXJzdE1hdGNoXCIgKDMpJywgZnVuY3Rpb24gKCkge1xuICAgICAgcGFyc2VDYXBzKHt9LCBbe31dKS5hbGxGaXJzdE1hdGNoQ2Fwcy5zaG91bGQuZGVlcC5lcXVhbChbe31dKTtcbiAgICB9KTtcblxuICAgIGl0KCdzZXRzIFwiYWxsRmlyc3RNYXRjaENhcHNcIiB0byBbe31dIGlmIFwiZmlyc3RNYXRjaFwiIGlzIHVuZGVmaW5lZCAoMy4xKScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHBhcnNlQ2Fwcyh7fSkuYWxsRmlyc3RNYXRjaENhcHMuc2hvdWxkLmRlZXAuZXF1YWwoW3t9XSk7XG4gICAgfSk7XG5cbiAgICBpdCgncmV0dXJucyBpbnZhbGlkIGFyZ3VtZW50IGVycm9yIGlmIFwiZmlyc3RNYXRjaFwiIGlzIG5vdCBhbiBhcnJheSBhbmQgaXMgbm90IHVuZGVmaW5lZCAoMy4yKScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZvciAobGV0IGFyZyBvZiBbbnVsbCwgMSwgdHJ1ZSwgJ3N0cmluZyddKSB7XG4gICAgICAgIGNhcHMuZmlyc3RNYXRjaCA9IGFyZztcbiAgICAgICAgKGZ1bmN0aW9uICgpIHsgcGFyc2VDYXBzKGNhcHMpOyB9KS5zaG91bGQudGhyb3coL211c3QgYmUgYSBKU09OIGFycmF5IG9yIHVuZGVmaW5lZC8pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ2hhcyBcInZhbGlkYXRlZEZpcnN0TWF0Y2hDYXBzXCIgcHJvcGVydHkgdGhhdCBpcyBlbXB0eSBieSBkZWZhdWx0IGlmIG5vIHZhbGlkIGZpcnN0TWF0Y2ggY2FwcyB3ZXJlIGZvdW5kICg0KScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHBhcnNlQ2FwcyhjYXBzLCB7Zm9vOiB7cHJlc2VuY2U6IHRydWV9fSkudmFsaWRhdGVkRmlyc3RNYXRjaENhcHMuc2hvdWxkLmRlZXAuZXF1YWwoW10pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3JldHVybnMgYSBcInZhbGlkYXRlZEZpcnN0TWF0Y2hDYXBzXCIgYXJyYXkgKDUpJywgZnVuY3Rpb24gKCkge1xuICAgICAgaXQoJ3RoYXQgZXF1YWxzIFwiZmlyc3RNYXRjaFwiIGlmIGZpcnN0TWF0Y2ggaXMgb25lIGVtcHR5IG9iamVjdCBhbmQgdGhlcmUgYXJlIG5vIGNvbnN0cmFpbnRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBjYXBzLmZpcnN0TWF0Y2ggPSBbe31dO1xuICAgICAgICBwYXJzZUNhcHMoY2FwcykudmFsaWRhdGVkRmlyc3RNYXRjaENhcHMuc2hvdWxkLmRlZXAuZXF1YWwoY2Fwcy5maXJzdE1hdGNoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgncmV0dXJucyBcIm51bGxcIiBtYXRjaGVkQ2FwcyBpZiBub3RoaW5nIG1hdGNoZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhcHMuZmlyc3RNYXRjaCA9IFt7fV07XG4gICAgICAgIHNob3VsZC5lcXVhbChwYXJzZUNhcHMoY2Fwcywge2Zvbzoge3ByZXNlbmNlOiB0cnVlfX0pLm1hdGNoZWRDYXBzLCBudWxsKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdChgc2hvdWxkIHJldHVybiBjYXBhYmlsaXRpZXMgaWYgcHJlc2VuY2UgY29uc3RyYWludCBpcyBtYXRjaGVkIGluIGF0IGxlYXN0IG9uZSBvZiB0aGUgJ2ZpcnN0TWF0Y2gnIGNhcGFiaWxpdGllcyBvYmplY3RzYCwgZnVuY3Rpb24gKCkge1xuICAgICAgICBjYXBzLmFsd2F5c01hdGNoID0ge1xuICAgICAgICAgIGZvbzogJ2JhcicsXG4gICAgICAgIH07XG4gICAgICAgIGNhcHMuZmlyc3RNYXRjaCA9IFt7XG4gICAgICAgICAgaGVsbG86ICd3b3JsZCcsXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBnb29kYnllOiAnd29ybGQnLFxuICAgICAgICB9XTtcbiAgICAgICAgcGFyc2VDYXBzKGNhcHMsIHtnb29kYnllOiB7cHJlc2VuY2U6IHRydWV9fSkubWF0Y2hlZENhcHMuc2hvdWxkLmRlZXAuZXF1YWwoe1xuICAgICAgICAgIGZvbzogJ2JhcicsXG4gICAgICAgICAgZ29vZGJ5ZTogJ3dvcmxkJyxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoYHRocm93cyBpbnZhbGlkIGFyZ3VtZW50IGlmIHByZXNlbmNlIGNvbnN0cmFpbnQgaXMgbm90IG1ldCBvbiBhbnkgY2FwYWJpbGl0aWVzYCwgZnVuY3Rpb24gKCkge1xuICAgICAgICBjYXBzLmFsd2F5c01hdGNoID0ge1xuICAgICAgICAgIGZvbzogJ2JhcicsXG4gICAgICAgIH07XG4gICAgICAgIGNhcHMuZmlyc3RNYXRjaCA9IFt7XG4gICAgICAgICAgaGVsbG86ICd3b3JsZCcsXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBnb29kYnllOiAnd29ybGQnLFxuICAgICAgICB9XTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKHBhcnNlQ2FwcyhjYXBzLCB7c29tZUF0dHJpYnV0ZToge3ByZXNlbmNlOiB0cnVlfX0pLm1hdGNoZWRDYXBzLCBudWxsKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgndGhhdCBlcXVhbHMgZmlyc3RNYXRjaCBpZiBmaXJzdE1hdGNoIGNvbnRhaW5zIHR3byBvYmplY3RzIHRoYXQgcGFzcyB0aGUgcHJvdmlkZWQgY29uc3RyYWludHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhcHMuYWx3YXlzTWF0Y2ggPSB7XG4gICAgICAgICAgZm9vOiAnYmFyJ1xuICAgICAgICB9O1xuICAgICAgICBjYXBzLmZpcnN0TWF0Y2ggPSBbXG4gICAgICAgICAge2ZvbzogJ2JhcjEnfSxcbiAgICAgICAgICB7Zm9vOiAnYmFyMid9LFxuICAgICAgICBdO1xuXG4gICAgICAgIGxldCBjb25zdHJhaW50cyA9IHtcbiAgICAgICAgICBmb286IHtcbiAgICAgICAgICAgIHByZXNlbmNlOiB0cnVlLFxuICAgICAgICAgICAgaXNTdHJpbmc6IHRydWUsXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHBhcnNlQ2FwcyhjYXBzLCBjb25zdHJhaW50cykudmFsaWRhdGVkRmlyc3RNYXRjaENhcHMuc2hvdWxkLmRlZXAuZXF1YWwoY2Fwcy5maXJzdE1hdGNoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgncmV0dXJucyBpbnZhbGlkIGFyZ3VtZW50IGVycm9yIGlmIHRoZSBmaXJzdE1hdGNoWzJdIGlzIG5vdCBhbiBvYmplY3QnLCBmdW5