/ cloudformation-templates / node_modules / aws-cdk / test / api / deploy-stack.test.js
deploy-stack.test.js
  1  "use strict";
  2  Object.defineProperty(exports, "__esModule", { value: true });
  3  const api_1 = require("../../lib/api");
  4  const util_1 = require("../util");
  5  const mock_sdk_1 = require("../util/mock-sdk");
  6  const FAKE_STACK = util_1.testStack({
  7      stackName: 'withouterrors',
  8  });
  9  const FAKE_STACK_WITH_PARAMETERS = util_1.testStack({
 10      stackName: 'withparameters',
 11      template: {
 12          Parameters: {
 13              HasValue: { Type: 'String' },
 14              HasDefault: { Type: 'String', Default: 'TheDefault' },
 15              OtherParameter: { Type: 'String' },
 16          },
 17      },
 18  });
 19  const FAKE_STACK_TERMINATION_PROTECTION = util_1.testStack({
 20      stackName: 'termination-protection',
 21      template: util_1.DEFAULT_FAKE_TEMPLATE,
 22      terminationProtection: true,
 23  });
 24  let sdk;
 25  let sdkProvider;
 26  let cfnMocks;
 27  beforeEach(() => {
 28      sdkProvider = new mock_sdk_1.MockSdkProvider();
 29      sdk = new mock_sdk_1.MockSdk();
 30      cfnMocks = {
 31          describeStackEvents: jest.fn().mockReturnValue({}),
 32          describeStacks: jest.fn()
 33              // First call, no stacks exist
 34              .mockImplementationOnce(() => ({ Stacks: [] }))
 35              // Second call, stack has been created
 36              .mockImplementationOnce(() => ({
 37              Stacks: [
 38                  {
 39                      StackStatus: 'CREATE_COMPLETE',
 40                      StackStatusReason: 'It is magic',
 41                      EnableTerminationProtection: false,
 42                  },
 43              ],
 44          })),
 45          createChangeSet: jest.fn((_o) => ({})),
 46          deleteChangeSet: jest.fn((_o) => ({})),
 47          describeChangeSet: jest.fn((_o) => ({
 48              Status: 'CREATE_COMPLETE',
 49              Changes: [],
 50          })),
 51          executeChangeSet: jest.fn((_o) => ({})),
 52          deleteStack: jest.fn((_o) => ({})),
 53          getTemplate: jest.fn((_o) => ({ TemplateBody: JSON.stringify(util_1.DEFAULT_FAKE_TEMPLATE) })),
 54          updateTerminationProtection: jest.fn((_o) => ({ StackId: 'stack-id' })),
 55      };
 56      sdk.stubCloudFormation(cfnMocks);
 57  });
 58  function standardDeployStackArguments() {
 59      return {
 60          stack: FAKE_STACK,
 61          sdk,
 62          sdkProvider,
 63          resolvedEnvironment: mock_sdk_1.mockResolvedEnvironment(),
 64          toolkitInfo: api_1.ToolkitInfo.bootstraplessDeploymentsOnly(sdk),
 65      };
 66  }
 67  test('do deploy executable change set with 0 changes', async () => {
 68      // WHEN
 69      const ret = await api_1.deployStack({
 70          ...standardDeployStackArguments(),
 71      });
 72      // THEN
 73      expect(ret.noOp).toBeFalsy();
 74      expect(cfnMocks.executeChangeSet).toHaveBeenCalled();
 75  });
 76  test('correctly passes CFN parameters, ignoring ones with empty values', async () => {
 77      // WHEN
 78      await api_1.deployStack({
 79          ...standardDeployStackArguments(),
 80          parameters: {
 81              A: 'A-value',
 82              B: 'B=value',
 83              C: undefined,
 84              D: '',
 85          },
 86      });
 87      // THEN
 88      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
 89          Parameters: [
 90              { ParameterKey: 'A', ParameterValue: 'A-value' },
 91              { ParameterKey: 'B', ParameterValue: 'B=value' },
 92          ],
 93      }));
 94  });
 95  test('reuse previous parameters if requested', async () => {
 96      // GIVEN
 97      givenStackExists({
 98          Parameters: [
 99              { ParameterKey: 'HasValue', ParameterValue: 'TheValue' },
100              { ParameterKey: 'HasDefault', ParameterValue: 'TheOldValue' },
101          ],
102      });
103      // WHEN
104      await api_1.deployStack({
105          ...standardDeployStackArguments(),
106          stack: FAKE_STACK_WITH_PARAMETERS,
107          parameters: {
108              OtherParameter: 'SomeValue',
109          },
110          usePreviousParameters: true,
111      });
112      // THEN
113      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
114          Parameters: [
115              { ParameterKey: 'HasValue', UsePreviousValue: true },
116              { ParameterKey: 'HasDefault', UsePreviousValue: true },
117              { ParameterKey: 'OtherParameter', ParameterValue: 'SomeValue' },
118          ],
119      }));
120  });
121  test('do not reuse previous parameters if not requested', async () => {
122      // GIVEN
123      givenStackExists({
124          Parameters: [
125              { ParameterKey: 'HasValue', ParameterValue: 'TheValue' },
126              { ParameterKey: 'HasDefault', ParameterValue: 'TheOldValue' },
127          ],
128      });
129      // WHEN
130      await api_1.deployStack({
131          ...standardDeployStackArguments(),
132          stack: FAKE_STACK_WITH_PARAMETERS,
133          parameters: {
134              HasValue: 'SomeValue',
135              OtherParameter: 'SomeValue',
136          },
137      });
138      // THEN
139      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
140          Parameters: [
141              { ParameterKey: 'HasValue', ParameterValue: 'SomeValue' },
142              { ParameterKey: 'OtherParameter', ParameterValue: 'SomeValue' },
143          ],
144      }));
145  });
146  test('throw exception if not enough parameters supplied', async () => {
147      // GIVEN
148      givenStackExists({
149          Parameters: [
150              { ParameterKey: 'HasValue', ParameterValue: 'TheValue' },
151              { ParameterKey: 'HasDefault', ParameterValue: 'TheOldValue' },
152          ],
153      });
154      // WHEN
155      await expect(api_1.deployStack({
156          ...standardDeployStackArguments(),
157          stack: FAKE_STACK_WITH_PARAMETERS,
158          parameters: {
159              OtherParameter: 'SomeValue',
160          },
161      })).rejects.toThrow(/CloudFormation Parameters are missing a value/);
162  });
163  test('deploy is skipped if template did not change', async () => {
164      // GIVEN
165      givenStackExists();
166      // WHEN
167      await api_1.deployStack({
168          ...standardDeployStackArguments(),
169      });
170      // THEN
171      expect(cfnMocks.executeChangeSet).not.toBeCalled();
172  });
173  test('deploy is skipped if parameters are the same', async () => {
174      // GIVEN
175      givenTemplateIs(FAKE_STACK_WITH_PARAMETERS.template);
176      givenStackExists({
177          Parameters: [
178              { ParameterKey: 'HasValue', ParameterValue: 'HasValue' },
179              { ParameterKey: 'HasDefault', ParameterValue: 'HasDefault' },
180              { ParameterKey: 'OtherParameter', ParameterValue: 'OtherParameter' },
181          ],
182      });
183      // WHEN
184      await api_1.deployStack({
185          ...standardDeployStackArguments(),
186          stack: FAKE_STACK_WITH_PARAMETERS,
187          parameters: {},
188          usePreviousParameters: true,
189      });
190      // THEN
191      expect(cfnMocks.createChangeSet).not.toHaveBeenCalled();
192  });
193  test('deploy is not skipped if parameters are different', async () => {
194      // GIVEN
195      givenTemplateIs(FAKE_STACK_WITH_PARAMETERS.template);
196      givenStackExists({
197          Parameters: [
198              { ParameterKey: 'HasValue', ParameterValue: 'HasValue' },
199              { ParameterKey: 'HasDefault', ParameterValue: 'HasDefault' },
200              { ParameterKey: 'OtherParameter', ParameterValue: 'OtherParameter' },
201          ],
202      });
203      // WHEN
204      await api_1.deployStack({
205          ...standardDeployStackArguments(),
206          stack: FAKE_STACK_WITH_PARAMETERS,
207          parameters: {
208              HasValue: 'NewValue',
209          },
210          usePreviousParameters: true,
211      });
212      // THEN
213      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
214          Parameters: [
215              { ParameterKey: 'HasValue', ParameterValue: 'NewValue' },
216              { ParameterKey: 'HasDefault', UsePreviousValue: true },
217              { ParameterKey: 'OtherParameter', UsePreviousValue: true },
218          ],
219      }));
220  });
221  test('if existing stack failed to create, it is deleted and recreated', async () => {
222      // GIVEN
223      givenStackExists({ StackStatus: 'ROLLBACK_COMPLETE' }, // This is for the initial check
224      { StackStatus: 'DELETE_COMPLETE' }, // Poll the successful deletion
225      { StackStatus: 'CREATE_COMPLETE' });
226      givenTemplateIs({
227          DifferentThan: 'TheDefault',
228      });
229      // WHEN
230      await api_1.deployStack({
231          ...standardDeployStackArguments(),
232      });
233      // THEN
234      expect(cfnMocks.deleteStack).toHaveBeenCalled();
235      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
236          ChangeSetType: 'CREATE',
237      }));
238  });
239  test('if existing stack failed to create, it is deleted and recreated even if the template did not change', async () => {
240      // GIVEN
241      givenStackExists({ StackStatus: 'ROLLBACK_COMPLETE' }, // This is for the initial check
242      { StackStatus: 'DELETE_COMPLETE' }, // Poll the successful deletion
243      { StackStatus: 'CREATE_COMPLETE' });
244      // WHEN
245      await api_1.deployStack({
246          ...standardDeployStackArguments(),
247      });
248      // THEN
249      expect(cfnMocks.deleteStack).toHaveBeenCalled();
250      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
251          ChangeSetType: 'CREATE',
252      }));
253  });
254  test('deploy not skipped if template did not change and --force is applied', async () => {
255      // GIVEN
256      givenStackExists();
257      // WHEN
258      await api_1.deployStack({
259          ...standardDeployStackArguments(),
260          force: true,
261      });
262      // THEN
263      expect(cfnMocks.executeChangeSet).toHaveBeenCalled();
264  });
265  test('deploy is skipped if template and tags did not change', async () => {
266      // GIVEN
267      givenStackExists({
268          Tags: [
269              { Key: 'Key1', Value: 'Value1' },
270              { Key: 'Key2', Value: 'Value2' },
271          ],
272      });
273      // WHEN
274      await api_1.deployStack({
275          ...standardDeployStackArguments(),
276          tags: [
277              { Key: 'Key1', Value: 'Value1' },
278              { Key: 'Key2', Value: 'Value2' },
279          ],
280      });
281      // THEN
282      expect(cfnMocks.createChangeSet).not.toBeCalled();
283      expect(cfnMocks.executeChangeSet).not.toBeCalled();
284      expect(cfnMocks.describeStacks).toHaveBeenCalledWith({ StackName: 'withouterrors' });
285      expect(cfnMocks.getTemplate).toHaveBeenCalledWith({ StackName: 'withouterrors', TemplateStage: 'Original' });
286  });
287  test('deploy not skipped if template did not change but tags changed', async () => {
288      // GIVEN
289      givenStackExists({
290          Tags: [
291              { Key: 'Key', Value: 'Value' },
292          ],
293      });
294      // WHEN
295      await api_1.deployStack({
296          stack: FAKE_STACK,
297          sdk,
298          sdkProvider,
299          resolvedEnvironment: mock_sdk_1.mockResolvedEnvironment(),
300          tags: [
301              {
302                  Key: 'Key',
303                  Value: 'NewValue',
304              },
305          ],
306          toolkitInfo: api_1.ToolkitInfo.bootstraplessDeploymentsOnly(sdk),
307      });
308      // THEN
309      expect(cfnMocks.createChangeSet).toHaveBeenCalled();
310      expect(cfnMocks.executeChangeSet).toHaveBeenCalled();
311      expect(cfnMocks.describeChangeSet).toHaveBeenCalled();
312      expect(cfnMocks.describeStacks).toHaveBeenCalledWith({ StackName: 'withouterrors' });
313      expect(cfnMocks.getTemplate).toHaveBeenCalledWith({ StackName: 'withouterrors', TemplateStage: 'Original' });
314  });
315  test('deployStack reports no change if describeChangeSet returns specific error', async () => {
316      var _a;
317      (_a = cfnMocks.describeChangeSet) === null || _a === void 0 ? void 0 : _a.mockImplementation(() => ({
318          Status: 'FAILED',
319          StatusReason: 'No updates are to be performed.',
320      }));
321      // WHEN
322      const deployResult = await api_1.deployStack({
323          ...standardDeployStackArguments(),
324      });
325      // THEN
326      expect(deployResult.noOp).toEqual(true);
327  });
328  test('deploy not skipped if template did not change but one tag removed', async () => {
329      // GIVEN
330      givenStackExists({
331          Tags: [
332              { Key: 'Key1', Value: 'Value1' },
333              { Key: 'Key2', Value: 'Value2' },
334          ],
335      });
336      // WHEN
337      await api_1.deployStack({
338          ...standardDeployStackArguments(),
339          tags: [
340              { Key: 'Key1', Value: 'Value1' },
341          ],
342      });
343      // THEN
344      expect(cfnMocks.createChangeSet).toHaveBeenCalled();
345      expect(cfnMocks.executeChangeSet).toHaveBeenCalled();
346      expect(cfnMocks.describeChangeSet).toHaveBeenCalled();
347      expect(cfnMocks.describeStacks).toHaveBeenCalledWith({ StackName: 'withouterrors' });
348      expect(cfnMocks.getTemplate).toHaveBeenCalledWith({ StackName: 'withouterrors', TemplateStage: 'Original' });
349  });
350  test('deploy is not skipped if stack is in a _FAILED state', async () => {
351      // GIVEN
352      givenStackExists({
353          StackStatus: 'DELETE_FAILED',
354      });
355      // WHEN
356      await api_1.deployStack({
357          ...standardDeployStackArguments(),
358          usePreviousParameters: true,
359      }).catch(() => { });
360      // THEN
361      expect(cfnMocks.createChangeSet).toHaveBeenCalled();
362  });
363  test('existing stack in UPDATE_ROLLBACK_COMPLETE state can be updated', async () => {
364      // GIVEN
365      givenStackExists({ StackStatus: 'UPDATE_ROLLBACK_COMPLETE' }, // This is for the initial check
366      { StackStatus: 'UPDATE_COMPLETE' });
367      givenTemplateIs({ changed: 123 });
368      // WHEN
369      await api_1.deployStack({
370          ...standardDeployStackArguments(),
371      });
372      // THEN
373      expect(cfnMocks.deleteStack).not.toHaveBeenCalled();
374      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
375          ChangeSetType: 'UPDATE',
376      }));
377  });
378  test('deploy not skipped if template changed', async () => {
379      // GIVEN
380      givenStackExists();
381      givenTemplateIs({ changed: 123 });
382      // WHEN
383      await api_1.deployStack({
384          ...standardDeployStackArguments(),
385      });
386      // THEN
387      expect(cfnMocks.executeChangeSet).toHaveBeenCalled();
388  });
389  test('not executed and no error if --no-execute is given', async () => {
390      // WHEN
391      await api_1.deployStack({
392          ...standardDeployStackArguments(),
393          execute: false,
394      });
395      // THEN
396      expect(cfnMocks.executeChangeSet).not.toHaveBeenCalled();
397  });
398  test('empty change set is deleted if --execute is given', async () => {
399      var _a;
400      (_a = cfnMocks.describeChangeSet) === null || _a === void 0 ? void 0 : _a.mockImplementation(() => ({
401          Status: 'FAILED',
402          StatusReason: 'No updates are to be performed.',
403      }));
404      // GIVEN
405      givenStackExists();
406      // WHEN
407      await api_1.deployStack({
408          ...standardDeployStackArguments(),
409          execute: true,
410          force: true,
411      });
412      // THEN
413      expect(cfnMocks.createChangeSet).toHaveBeenCalled();
414      expect(cfnMocks.executeChangeSet).not.toHaveBeenCalled();
415      //the first deletion is for any existing cdk change sets, the second is for the deleting the new empty change set
416      expect(cfnMocks.deleteChangeSet).toHaveBeenCalledTimes(2);
417  });
418  test('empty change set is not deleted if --no-execute is given', async () => {
419      var _a;
420      (_a = cfnMocks.describeChangeSet) === null || _a === void 0 ? void 0 : _a.mockImplementation(() => ({
421          Status: 'FAILED',
422          StatusReason: 'No updates are to be performed.',
423      }));
424      // GIVEN
425      givenStackExists();
426      // WHEN
427      await api_1.deployStack({
428          ...standardDeployStackArguments(),
429          execute: false,
430      });
431      // THEN
432      expect(cfnMocks.createChangeSet).toHaveBeenCalled();
433      expect(cfnMocks.executeChangeSet).not.toHaveBeenCalled();
434      //the first deletion is for any existing cdk change sets
435      expect(cfnMocks.deleteChangeSet).toHaveBeenCalledTimes(1);
436  });
437  test('use S3 url for stack deployment if present in Stack Artifact', async () => {
438      // WHEN
439      await api_1.deployStack({
440          ...standardDeployStackArguments(),
441          stack: util_1.testStack({
442              stackName: 'withouterrors',
443              properties: {
444                  stackTemplateAssetObjectUrl: 'https://use-me-use-me/',
445              },
446          }),
447      });
448      // THEN
449      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
450          TemplateURL: 'https://use-me-use-me/',
451      }));
452      expect(cfnMocks.executeChangeSet).toHaveBeenCalled();
453  });
454  test('use REST API S3 url with substituted placeholders if manifest url starts with s3://', async () => {
455      // WHEN
456      await api_1.deployStack({
457          ...standardDeployStackArguments(),
458          stack: util_1.testStack({
459              stackName: 'withouterrors',
460              properties: {
461                  stackTemplateAssetObjectUrl: 's3://use-me-use-me-${AWS::AccountId}/object',
462              },
463          }),
464      });
465      // THEN
466      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
467          TemplateURL: 'https://s3.bermuda-triangle-1337.amazonaws.com/use-me-use-me-123456789/object',
468      }));
469      expect(cfnMocks.executeChangeSet).toHaveBeenCalled();
470  });
471  test('changeset is created when stack exists in REVIEW_IN_PROGRESS status', async () => {
472      // GIVEN
473      givenStackExists({
474          StackStatus: 'REVIEW_IN_PROGRESS',
475          Tags: [
476              { Key: 'Key1', Value: 'Value1' },
477              { Key: 'Key2', Value: 'Value2' },
478          ],
479      });
480      // WHEN
481      await api_1.deployStack({
482          ...standardDeployStackArguments(),
483          execute: false,
484      });
485      // THEN
486      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
487          ChangeSetType: 'CREATE',
488          StackName: 'withouterrors',
489      }));
490      expect(cfnMocks.executeChangeSet).not.toHaveBeenCalled();
491  });
492  test('changeset is updated when stack exists in CREATE_COMPLETE status', async () => {
493      // GIVEN
494      givenStackExists({
495          Tags: [
496              { Key: 'Key1', Value: 'Value1' },
497              { Key: 'Key2', Value: 'Value2' },
498          ],
499      });
500      // WHEN
501      await api_1.deployStack({
502          ...standardDeployStackArguments(),
503          execute: false,
504      });
505      // THEN
506      expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({
507          ChangeSetType: 'UPDATE',
508          StackName: 'withouterrors',
509      }));
510      expect(cfnMocks.executeChangeSet).not.toHaveBeenCalled();
511  });
512  test('deploy with termination protection enabled', async () => {
513      // WHEN
514      await api_1.deployStack({
515          ...standardDeployStackArguments(),
516          stack: FAKE_STACK_TERMINATION_PROTECTION,
517      });
518      // THEN
519      expect(cfnMocks.updateTerminationProtection).toHaveBeenCalledWith(expect.objectContaining({
520          EnableTerminationProtection: true,
521      }));
522  });
523  test('updateTerminationProtection not called when termination protection is undefined', async () => {
524      // WHEN
525      await api_1.deployStack({
526          ...standardDeployStackArguments(),
527      });
528      // THEN
529      expect(cfnMocks.updateTerminationProtection).not.toHaveBeenCalled();
530  });
531  test('updateTerminationProtection called when termination protection is undefined and stack has termination protection', async () => {
532      // GIVEN
533      givenStackExists({
534          EnableTerminationProtection: true,
535      });
536      // WHEN
537      await api_1.deployStack({
538          ...standardDeployStackArguments(),
539      });
540      // THEN
541      expect(cfnMocks.updateTerminationProtection).toHaveBeenCalledWith(expect.objectContaining({
542          EnableTerminationProtection: false,
543      }));
544  });
545  describe('disable rollback', () => {
546      test('by default, we do not disable rollback (and also do not pass the flag)', async () => {
547          // WHEN
548          await api_1.deployStack({
549              ...standardDeployStackArguments(),
550          });
551          // THEN
552          expect(cfnMocks.executeChangeSet).toHaveBeenCalledTimes(1);
553          expect(cfnMocks.executeChangeSet).not.toHaveBeenCalledWith(expect.objectContaining({
554              DisableRollback: expect.anything(),
555          }));
556      });
557      test('rollback can be disabled by setting rollback: false', async () => {
558          // WHEN
559          await api_1.deployStack({
560              ...standardDeployStackArguments(),
561              rollback: false,
562          });
563          // THEN
564          expect(cfnMocks.executeChangeSet).toHaveBeenCalledWith(expect.objectContaining({
565              DisableRollback: true,
566          }));
567      });
568  });
569  /**
570   * Set up the mocks so that it looks like the stack exists to start with
571   *
572   * The last element of this array will be continuously repeated.
573   */
574  function givenStackExists(...overrides) {
575      cfnMocks.describeStacks.mockReset();
576      if (overrides.length === 0) {
577          overrides = [{}];
578      }
579      const baseResponse = {
580          StackName: 'mock-stack-name',
581          StackId: 'mock-stack-id',
582          CreationTime: new Date(),
583          StackStatus: 'CREATE_COMPLETE',
584          EnableTerminationProtection: false,
585      };
586      for (const override of overrides.slice(0, overrides.length - 1)) {
587          cfnMocks.describeStacks.mockImplementationOnce(() => ({
588              Stacks: [{ ...baseResponse, ...override }],
589          }));
590      }
591      cfnMocks.describeStacks.mockImplementation(() => ({
592          Stacks: [{ ...baseResponse, ...overrides[overrides.length - 1] }],
593      }));
594  }
595  function givenTemplateIs(template) {
596      cfnMocks.getTemplate.mockReset();
597      cfnMocks.getTemplate.mockReturnValue({
598          TemplateBody: JSON.stringify(template),
599      });
600  }
601  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95LXN0YWNrLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJkZXBsb3ktc3RhY2sudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHVDQUF5RDtBQUN6RCxrQ0FBMkQ7QUFDM0QsK0NBQXdIO0FBRXhILE1BQU0sVUFBVSxHQUFHLGdCQUFTLENBQUM7SUFDM0IsU0FBUyxFQUFFLGVBQWU7Q0FDM0IsQ0FBQyxDQUFDO0FBRUgsTUFBTSwwQkFBMEIsR0FBRyxnQkFBUyxDQUFDO0lBQzNDLFNBQVMsRUFBRSxnQkFBZ0I7SUFDM0IsUUFBUSxFQUFFO1FBQ1IsVUFBVSxFQUFFO1lBQ1YsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtZQUM1QixVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUU7WUFDckQsY0FBYyxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtTQUNuQztLQUNGO0NBQ0YsQ0FBQyxDQUFDO0FBRUgsTUFBTSxpQ0FBaUMsR0FBRyxnQkFBUyxDQUFDO0lBQ2xELFNBQVMsRUFBRSx3QkFBd0I7SUFDbkMsUUFBUSxFQUFFLDRCQUFxQjtJQUMvQixxQkFBcUIsRUFBRSxJQUFJO0NBQzVCLENBQUMsQ0FBQztBQUVILElBQUksR0FBWSxDQUFDO0FBQ2pCLElBQUksV0FBNEIsQ0FBQztBQUNqQyxJQUFJLFFBQStELENBQUM7QUFDcEUsVUFBVSxDQUFDLEdBQUcsRUFBRTtJQUNkLFdBQVcsR0FBRyxJQUFJLDBCQUFlLEVBQUUsQ0FBQztJQUNwQyxHQUFHLEdBQUcsSUFBSSxrQkFBTyxFQUFFLENBQUM7SUFFcEIsUUFBUSxHQUFHO1FBQ1QsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7UUFDbEQsY0FBYyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDdkIsOEJBQThCO2FBQzdCLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMvQyxzQ0FBc0M7YUFDckMsc0JBQXNCLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUM3QixNQUFNLEVBQUU7Z0JBQ047b0JBQ0UsV0FBVyxFQUFFLGlCQUFpQjtvQkFDOUIsaUJBQWlCLEVBQUUsYUFBYTtvQkFDaEMsMkJBQTJCLEVBQUUsS0FBSztpQkFDbkM7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUNMLGVBQWUsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3RDLGVBQWUsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3RDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDbEMsTUFBTSxFQUFFLGlCQUFpQjtZQUN6QixPQUFPLEVBQUUsRUFBRTtTQUNaLENBQUMsQ0FBQztRQUNILGdCQUFnQixFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdkMsV0FBVyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbEMsV0FBVyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxZQUFZLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyw0QkFBcUIsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN2RiwyQkFBMkIsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7S0FDeEUsQ0FBQztJQUNGLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxRQUFlLENBQUMsQ0FBQztBQUUxQyxDQUFDLENBQUMsQ0FBQztBQUVILFNBQVMsNEJBQTRCO0lBQ25DLE9BQU87UUFDTCxLQUFLLEVBQUUsVUFBVTtRQUNqQixHQUFHO1FBQ0gsV0FBVztRQUNYLG1CQUFtQixFQUFFLGtDQUF1QixFQUFFO1FBQzlDLFdBQVcsRUFBRSxpQkFBVyxDQUFDLDRCQUE0QixDQUFDLEdBQUcsQ0FBQztLQUMzRCxDQUFDO0FBQ0osQ0FBQztBQUVELElBQUksQ0FBQyxnREFBZ0QsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNoRSxPQUFPO0lBQ1AsTUFBTSxHQUFHLEdBQUcsTUFBTSxpQkFBVyxDQUFDO1FBQzVCLEdBQUcsNEJBQTRCLEVBQUU7S0FDbEMsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDN0IsTUFBTSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUM7QUFDdkQsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsa0VBQWtFLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDbEYsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO1FBQ2pDLFVBQVUsRUFBRTtZQUNWLENBQUMsRUFBRSxTQUFTO1lBQ1osQ0FBQyxFQUFFLFNBQVM7WUFDWixDQUFDLEVBQUUsU0FBUztZQUNaLENBQUMsRUFBRSxFQUFFO1NBQ047S0FDRixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUM7UUFDNUUsVUFBVSxFQUFFO1lBQ1YsRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUU7WUFDaEQsRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUU7U0FDakQ7S0FDRixDQUFDLENBQUMsQ0FBQztBQUNOLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLHdDQUF3QyxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3hELFFBQVE7SUFDUixnQkFBZ0IsQ0FBQztRQUNmLFVBQVUsRUFBRTtZQUNWLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsVUFBVSxFQUFFO1lBQ3hELEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFO1NBQzlEO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO1FBQ2pDLEtBQUssRUFBRSwwQkFBMEI7UUFDakMsVUFBVSxFQUFFO1lBQ1YsY0FBYyxFQUFFLFdBQVc7U0FDNUI7UUFDRCxxQkFBcUIsRUFBRSxJQUFJO0tBQzVCLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztRQUM1RSxVQUFVLEVBQUU7WUFDVixFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFO1lBQ3BELEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxnQkFBZ0IsRUFBRSxJQUFJLEVBQUU7WUFDdEQsRUFBRSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLFdBQVcsRUFBRTtTQUNoRTtLQUNGLENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsbURBQW1ELEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDbkUsUUFBUTtJQUNSLGdCQUFnQixDQUFDO1FBQ2YsVUFBVSxFQUFFO1lBQ1YsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxVQUFVLEVBQUU7WUFDeEQsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUU7U0FDOUQ7S0FDRixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxpQkFBVyxDQUFDO1FBQ2hCLEdBQUcsNEJBQTRCLEVBQUU7UUFDakMsS0FBSyxFQUFFLDBCQUEwQjtRQUNqQyxVQUFVLEVBQUU7WUFDVixRQUFRLEVBQUUsV0FBVztZQUNyQixjQUFjLEVBQUUsV0FBVztTQUM1QjtLQUNGLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztRQUM1RSxVQUFVLEVBQUU7WUFDVixFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsY0FBYyxFQUFFLFdBQVcsRUFBRTtZQUN6RCxFQUFFLFlBQVksRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFO1NBQ2hFO0tBQ0YsQ0FBQyxDQUFDLENBQUM7QUFDTixDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxtREFBbUQsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNuRSxRQUFRO0lBQ1IsZ0JBQWdCLENBQUM7UUFDZixVQUFVLEVBQUU7WUFDVixFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsY0FBYyxFQUFFLFVBQVUsRUFBRTtZQUN4RCxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRTtTQUM5RDtLQUNGLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLE1BQU0sQ0FBQyxpQkFBVyxDQUFDO1FBQ3ZCLEdBQUcsNEJBQTRCLEVBQUU7UUFDakMsS0FBSyxFQUFFLDBCQUEwQjtRQUNqQyxVQUFVLEVBQUU7WUFDVixjQUFjLEVBQUUsV0FBVztTQUM1QjtLQUNGLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsK0NBQStDLENBQUMsQ0FBQztBQUN2RSxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyw4Q0FBOEMsRUFBRSxLQUFLLElBQUksRUFBRTtJQUM5RCxRQUFRO0lBQ1IsZ0JBQWdCLEVBQUUsQ0FBQztJQUVuQixPQUFPO0lBQ1AsTUFBTSxpQkFBVyxDQUFDO1FBQ2hCLEdBQUcsNEJBQTRCLEVBQUU7S0FDbEMsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFLENBQUM7QUFDckQsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsOENBQThDLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDOUQsUUFBUTtJQUNSLGVBQWUsQ0FBQywwQkFBMEIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNyRCxnQkFBZ0IsQ0FBQztRQUNmLFVBQVUsRUFBRTtZQUNWLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsVUFBVSxFQUFFO1lBQ3hELEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsWUFBWSxFQUFFO1lBQzVELEVBQUUsWUFBWSxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRTtTQUNyRTtLQUNGLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLGlCQUFXLENBQUM7UUFDaEIsR0FBRyw0QkFBNEIsRUFBRTtRQUNqQyxLQUFLLEVBQUUsMEJBQTBCO1FBQ2pDLFVBQVUsRUFBRSxFQUFFO1FBQ2QscUJBQXFCLEVBQUUsSUFBSTtLQUM1QixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztBQUMxRCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxtREFBbUQsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNuRSxRQUFRO0lBQ1IsZUFBZSxDQUFDLDBCQUEwQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3JELGdCQUFnQixDQUFDO1FBQ2YsVUFBVSxFQUFFO1lBQ1YsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxVQUFVLEVBQUU7WUFDeEQsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUU7WUFDNUQsRUFBRSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFO1NBQ3JFO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO1FBQ2pDLEtBQUssRUFBRSwwQkFBMEI7UUFDakMsVUFBVSxFQUFFO1lBQ1YsUUFBUSxFQUFFLFVBQVU7U0FDckI7UUFDRCxxQkFBcUIsRUFBRSxJQUFJO0tBQzVCLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztRQUM1RSxVQUFVLEVBQUU7WUFDVixFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsY0FBYyxFQUFFLFVBQVUsRUFBRTtZQUN4RCxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFO1lBQ3RELEVBQUUsWUFBWSxFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLElBQUksRUFBRTtTQUMzRDtLQUNGLENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsaUVBQWlFLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDakYsUUFBUTtJQUNSLGdCQUFnQixDQUNkLEVBQUUsV0FBVyxFQUFFLG1CQUFtQixFQUFFLEVBQUUsZ0NBQWdDO0lBQ3RFLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFFLEVBQUUsK0JBQStCO0lBQ25FLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFFLENBQ25DLENBQUM7SUFDRixlQUFlLENBQUM7UUFDZCxhQUFhLEVBQUUsWUFBWTtLQUM1QixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxpQkFBVyxDQUFDO1FBQ2hCLEdBQUcsNEJBQTRCLEVBQUU7S0FDbEMsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUNoRCxNQUFNLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztRQUM1RSxhQUFhLEVBQUUsUUFBUTtLQUN4QixDQUFDLENBQUMsQ0FBQztBQUNOLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLHFHQUFxRyxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3JILFFBQVE7SUFDUixnQkFBZ0IsQ0FDZCxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBRSxFQUFFLGdDQUFnQztJQUN0RSxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLCtCQUErQjtJQUNuRSxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxDQUNuQyxDQUFDO0lBRUYsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO0tBQ2xDLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDaEQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUM7UUFDNUUsYUFBYSxFQUFFLFFBQVE7S0FDeEIsQ0FBQyxDQUFDLENBQUM7QUFDTixDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxzRUFBc0UsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN0RixRQUFRO0lBQ1IsZ0JBQWdCLEVBQUUsQ0FBQztJQUVuQixPQUFPO0lBQ1AsTUFBTSxpQkFBVyxDQUFDO1FBQ2hCLEdBQUcsNEJBQTRCLEVBQUU7UUFDakMsS0FBSyxFQUFFLElBQUk7S0FDWixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUM7QUFDdkQsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsdURBQXVELEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDdkUsUUFBUTtJQUNSLGdCQUFnQixDQUFDO1FBQ2YsSUFBSSxFQUFFO1lBQ0osRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7WUFDaEMsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7U0FDakM7S0FDRixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxpQkFBVyxDQUFDO1FBQ2hCLEdBQUcsNEJBQTRCLEVBQUU7UUFDakMsSUFBSSxFQUFFO1lBQ0osRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7WUFDaEMsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7U0FDakM7S0FDRixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDbEQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNuRCxNQUFNLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxDQUFDLENBQUM7SUFDckYsTUFBTSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7QUFDL0csQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsZ0VBQWdFLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDaEYsUUFBUTtJQUNSLGdCQUFnQixDQUFDO1FBQ2YsSUFBSSxFQUFFO1lBQ0osRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUU7U0FDL0I7S0FDRixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxpQkFBVyxDQUFDO1FBQ2hCLEtBQUssRUFBRSxVQUFVO1FBQ2pCLEdBQUc7UUFDSCxXQUFXO1FBQ1gsbUJBQW1CLEVBQUUsa0NBQXVCLEVBQUU7UUFDOUMsSUFBSSxFQUFFO1lBQ0o7Z0JBQ0UsR0FBRyxFQUFFLEtBQUs7Z0JBQ1YsS0FBSyxFQUFFLFVBQVU7YUFDbEI7U0FDRjtRQUNELFdBQVcsRUFBRSxpQkFBVyxDQUFDLDRCQUE0QixDQUFDLEdBQUcsQ0FBQztLQUMzRCxDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBQ3BELE1BQU0sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBQ3JELE1BQU0sQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBQ3RELE1BQU0sQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLENBQUMsb0JBQW9CLENBQUMsRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLENBQUMsQ0FBQztJQUNyRixNQUFNLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztBQUMvRyxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQywyRUFBMkUsRUFBRSxLQUFLLElBQUksRUFBRTs7SUFDM0YsTUFBQSxRQUFRLENBQUMsaUJBQWlCLDBDQUFFLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDcEQsTUFBTSxFQUFFLFFBQVE7UUFDaEIsWUFBWSxFQUFFLGlDQUFpQztLQUNoRCxDQUFDLEVBQUU7SUFFSixPQUFPO0lBQ1AsTUFBTSxZQUFZLEdBQUcsTUFBTSxpQkFBVyxDQUFDO1FBQ3JDLEdBQUcsNEJBQTRCLEVBQUU7S0FDbEMsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzFDLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLG1FQUFtRSxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ25GLFFBQVE7SUFDUixnQkFBZ0IsQ0FBQztRQUNmLElBQUksRUFBRTtZQUNKLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO1lBQ2hDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO1NBQ2pDO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO1FBQ2pDLElBQUksRUFBRTtZQUNKLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO1NBQ2pDO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUNwRCxNQUFNLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUNyRCxNQUFNLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUN0RCxNQUFNLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxDQUFDLENBQUM7SUFDckYsTUFBTSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7QUFDL0csQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsc0RBQXNELEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDdEUsUUFBUTtJQUNSLGdCQUFnQixDQUFDO1FBQ2YsV0FBVyxFQUFFLGVBQWU7S0FDN0IsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO1FBQ2pDLHFCQUFxQixFQUFFLElBQUk7S0FDNUIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUMsQ0FBQztJQUVuQixPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0FBQ3RELENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLGlFQUFpRSxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ2pGLFFBQVE7SUFDUixnQkFBZ0IsQ0FDZCxFQUFFLFdBQVcsRUFBRSwwQkFBMEIsRUFBRSxFQUFFLGdDQUFnQztJQUM3RSxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxDQUNuQyxDQUFDO0lBQ0YsZUFBZSxDQUFDLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFFbEMsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO0tBQ2xDLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBQ3BELE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1FBQzVFLGFBQWEsRUFBRSxRQUFRO0tBQ3hCLENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsd0NBQXdDLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDeEQsUUFBUTtJQUNSLGdCQUFnQixFQUFFLENBQUM7SUFDbkIsZUFBZSxDQUFDLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFFbEMsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO0tBQ2xDLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztBQUN2RCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxvREFBb0QsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNwRSxPQUFPO0lBQ1AsTUFBTSxpQkFBVyxDQUFDO1FBQ2hCLEdBQUcsNEJBQTRCLEVBQUU7UUFDakMsT0FBTyxFQUFFLEtBQUs7S0FDZixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0FBQzNELENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLG1EQUFtRCxFQUFFLEtBQUssSUFBSSxFQUFFOztJQUNuRSxNQUFBLFFBQVEsQ0FBQyxpQkFBaUIsMENBQUUsa0JBQWtCLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNwRCxNQUFNLEVBQUUsUUFBUTtRQUNoQixZQUFZLEVBQUUsaUNBQWlDO0tBQ2hELENBQUMsRUFBRTtJQUVKLFFBQVE7SUFDUixnQkFBZ0IsRUFBRSxDQUFDO0lBRW5CLE9BQU87SUFDUCxNQUFNLGlCQUFXLENBQUM7UUFDaEIsR0FBRyw0QkFBNEIsRUFBRTtRQUNqQyxPQUFPLEVBQUUsSUFBSTtRQUNiLEtBQUssRUFBRSxJQUFJO0tBQ1osQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUNwRCxNQUFNLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFFekQsaUhBQWlIO0lBQ2pILE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDNUQsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsMERBQTBELEVBQUUsS0FBSyxJQUFJLEVBQUU7O0lBQzFFLE1BQUEsUUFBUSxDQUFDLGlCQUFpQiwwQ0FBRSxrQkFBa0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQ3BELE1BQU0sRUFBRSxRQUFRO1FBQ2hCLFlBQVksRUFBRSxpQ0FBaUM7S0FDaEQsQ0FBQyxFQUFFO0lBRUosUUFBUTtJQUNSLGdCQUFnQixFQUFFLENBQUM7SUFFbkIsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO1FBQ2pDLE9BQU8sRUFBRSxLQUFLO0tBQ2YsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUNwRCxNQUFNLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFFekQsd0RBQXdEO0lBQ3hELE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDNUQsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsOERBQThELEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDOUUsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO1FBQ2pDLEtBQUssRUFBRSxnQkFBUyxDQUFDO1lBQ2YsU0FBUyxFQUFFLGVBQWU7WUFDMUIsVUFBVSxFQUFFO2dCQUNWLDJCQUEyQixFQUFFLHdCQUF3QjthQUN0RDtTQUNGLENBQUM7S0FDSCxDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUM7UUFDNUUsV0FBVyxFQUFFLHdCQUF3QjtLQUN0QyxDQUFDLENBQUMsQ0FBQztJQUNKLE1BQU0sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0FBQ3ZELENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLHFGQUFxRixFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3JHLE9BQU87SUFDUCxNQUFNLGlCQUFXLENBQUM7UUFDaEIsR0FBRyw0QkFBNEIsRUFBRTtRQUNqQyxLQUFLLEVBQUUsZ0JBQVMsQ0FBQztZQUNmLFNBQVMsRUFBRSxlQUFlO1lBQzFCLFVBQVUsRUFBRTtnQkFDViwyQkFBMkIsRUFBRSw2Q0FBNkM7YUFDM0U7U0FDRixDQUFDO0tBQ0gsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1FBQzVFLFdBQVcsRUFBRSwrRUFBK0U7S0FDN0YsQ0FBQyxDQUFDLENBQUM7SUFDSixNQUFNLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztBQUN2RCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxxRUFBcUUsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNyRixRQUFRO0lBQ1IsZ0JBQWdCLENBQUM7UUFDZixXQUFXLEVBQUUsb0JBQW9CO1FBQ2pDLElBQUksRUFBRTtZQUNKLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO1lBQ2hDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO1NBQ2pDO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO1FBQ2pDLE9BQU8sRUFBRSxLQUFLO0tBQ2YsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMsb0JBQW9CLENBQ25ELE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztRQUN0QixhQUFhLEVBQUUsUUFBUTtRQUN2QixTQUFTLEVBQUUsZUFBZTtLQUMzQixDQUFDLENBQ0gsQ0FBQztJQUNGLE1BQU0sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztBQUMzRCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxrRUFBa0UsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNsRixRQUFRO0lBQ1IsZ0JBQWdCLENBQUM7UUFDZixJQUFJLEVBQUU7WUFDSixFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRTtZQUNoQyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRTtTQUNqQztLQUNGLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLGlCQUFXLENBQUM7UUFDaEIsR0FBRyw0QkFBNEIsRUFBRTtRQUNqQyxPQUFPLEVBQUUsS0FBSztLQUNmLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLG9CQUFvQixDQUNuRCxNQUFNLENBQUMsZ0JBQWdCLENBQUM7UUFDdEIsYUFBYSxFQUFFLFFBQVE7UUFDdkIsU0FBUyxFQUFFLGVBQWU7S0FDM0IsQ0FBQyxDQUNILENBQUM7SUFDRixNQUFNLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUM7QUFDM0QsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsNENBQTRDLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDNUQsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO1FBQ2pDLEtBQUssRUFBRSxpQ0FBaUM7S0FDekMsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxRQUFRLENBQUMsMkJBQTJCLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUM7UUFDeEYsMkJBQTJCLEVBQUUsSUFBSTtLQUNsQyxDQUFDLENBQUMsQ0FBQztBQUNOLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLGlGQUFpRixFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ2pHLE9BQU87SUFDUCxNQUFNLGlCQUFXLENBQUM7UUFDaEIsR0FBRyw0QkFBNEIsRUFBRTtLQUNsQyxDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0FBQ3RFLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLGtIQUFrSCxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ2xJLFFBQVE7SUFDUixnQkFBZ0IsQ0FBQztRQUNmLDJCQUEyQixFQUFFLElBQUk7S0FDbEMsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0saUJBQVcsQ0FBQztRQUNoQixHQUFHLDRCQUE0QixFQUFFO0tBQ2xDLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLENBQUMsUUFBUSxDQUFDLDJCQUEyQixDQUFDLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1FBQ3hGLDJCQUEyQixFQUFFLEtBQUs7S0FDbkMsQ0FBQyxDQUFDLENBQUM7QUFDTixDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLEVBQUU7SUFDaEMsSUFBSSxDQUFDLHdFQUF3RSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3hGLE9BQU87UUFDUCxNQUFNLGlCQUFXLENBQUM7WUFDaEIsR0FBRyw0QkFBNEIsRUFBRTtTQUNsQyxDQUFDLENBQUM7UUFFSCxPQUFPO1FBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNELE1BQU0sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1lBQ2pGLGVBQWUsRUFBRSxNQUFNLENBQUMsUUFBUSxFQUFFO1NBQ25DLENBQUMsQ0FBQyxDQUFDO0lBQ04sQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMscURBQXFELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDckUsT0FBTztRQUNQLE1BQU0saUJBQVcsQ0FBQztZQUNoQixHQUFHLDRCQUE0QixFQUFFO1lBQ2pDLFFBQVEsRUFBRSxLQUFLO1NBQ2hCLENBQUMsQ0FBQztRQUVILE9BQU87UUFDUCxNQUFNLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1lBQzdFLGVBQWUsRUFBRSxJQUFJO1NBQ3RCLENBQUMsQ0FBQyxDQUFDO0lBQ04sQ0FBQyxDQUFDLENBQUM7QUFFTCxDQUFDLENBQUMsQ0FBQztBQUVIOzs7O0dBSUc7QUFDSCxTQUFTLGdCQUFnQixDQUFDLEdBQUcsU0FBbUQ7SUFDOUUsUUFBUSxDQUFDLGNBQWUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUVyQyxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQzFCLFNBQVMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0tBQ2xCO0lBRUQsTUFBTSxZQUFZLEdBQUc7UUFDbkIsU0FBUyxFQUFFLGlCQUFpQjtRQUM1QixPQUFPLEVBQUUsZUFBZTtRQUN4QixZQUFZLEVBQUUsSUFBSSxJQUFJLEVBQUU7UUFDeEIsV0FBVyxFQUFFLGlCQUFpQjtRQUM5QiwyQkFBMkIsRUFBRSxLQUFLO0tBQ25DLENBQUM7SUFFRixLQUFLLE1BQU0sUUFBUSxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEVBQUU7UUFDL0QsUUFBUSxDQUFDLGNBQWUsQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ3JELE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRyxZQUFZLEVBQUUsR0FBRyxRQUFRLEVBQUUsQ0FBQztTQUMzQyxDQUFDLENBQUMsQ0FBQztLQUNMO0lBQ0QsUUFBUSxDQUFDLGNBQWUsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQ2pELE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRyxZQUFZLEVBQUUsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQ2xFLENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLFFBQWE7SUFDcEMsUUFBUSxDQUFDLFdBQVksQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUNsQyxRQUFRLENBQUMsV0FBWSxDQUFDLGVBQWUsQ0FBQztRQUNwQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUM7S0FDdkMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGRlcGxveVN0YWNrLCBUb29sa2l0SW5mbyB9IGZyb20gJy4uLy4uL2xpYi9hcGknO1xuaW1wb3J0IHsgREVGQVVMVF9GQUtFX1RFTVBMQVRFLCB0ZXN0U3RhY2sgfSBmcm9tICcuLi91dGlsJztcbmltcG9ydCB7IE1vY2tlZE9iamVjdCwgbW9ja1Jlc29sdmVkRW52aXJvbm1lbnQsIE1vY2tTZGssIE1vY2tTZGtQcm92aWRlciwgU3luY0hhbmRsZXJTdWJzZXRPZiB9IGZyb20gJy4uL3V0aWwvbW9jay1zZGsnO1xuXG5jb25zdCBGQUtFX1NUQUNLID0gdGVzdFN0YWNrKHtcbiAgc3RhY2tOYW1lOiAnd2l0aG91dGVycm9ycycsXG59KTtcblxuY29uc3QgRkFLRV9TVEFDS19XSVRIX1BBUkFNRVRFUlMgPSB0ZXN0U3RhY2soe1xuICBzdGFja05hbWU6ICd3aXRocGFyYW1ldGVycycsXG4gIHRlbXBsYXRlOiB7XG4gICAgUGFyYW1ldGVyczoge1xuICAgICAgSGFzVmFsdWU6IHsgVHlwZTogJ1N0cmluZycgfSxcbiAgICAgIEhhc0RlZmF1bHQ6IHsgVHlwZTogJ1N0cmluZycsIERlZmF1bHQ6ICdUaGVEZWZhdWx0JyB9LFxuICAgICAgT3RoZXJQYXJhbWV0ZXI6IHsgVHlwZTogJ1N0cmluZycgfSxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IEZBS0VfU1RBQ0tfVEVSTUlOQVRJT05fUFJPVEVDVElPTiA9IHRlc3RTdGFjayh7XG4gIHN0YWNrTmFtZTogJ3Rlcm1pbmF0aW9uLXByb3RlY3Rpb24nLFxuICB0ZW1wbGF0ZTogREVGQVVMVF9GQUtFX1RFTVBMQVRFLFxuICB0ZXJtaW5hdGlvblByb3RlY3Rpb246IHRydWUsXG59KTtcblxubGV0IHNkazogTW9ja1NkaztcbmxldCBzZGtQcm92aWRlcjogTW9ja1Nka1Byb3ZpZGVyO1xubGV0IGNmbk1vY2tzOiBNb2NrZWRPYmplY3Q8U3luY0hhbmRsZXJTdWJzZXRPZjxBV1MuQ2xvdWRGb3JtYXRpb24+PjtcbmJlZm9yZUVhY2goKCkgPT4ge1xuICBzZGtQcm92aWRlciA9IG5ldyBNb2NrU2RrUHJvdmlkZXIoKTtcbiAgc2RrID0gbmV3IE1vY2tTZGsoKTtcblxuICBjZm5Nb2NrcyA9IHtcbiAgICBkZXNjcmliZVN0YWNrRXZlbnRzOiBqZXN0LmZuKCkubW9ja1JldHVyblZhbHVlKHt9KSxcbiAgICBkZXNjcmliZVN0YWNrczogamVzdC5mbigpXG4gICAgICAvLyBGaXJzdCBjYWxsLCBubyBzdGFja3MgZXhpc3RcbiAgICAgIC5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCgpID0+ICh7IFN0YWNrczogW10gfSkpXG4gICAgICAvLyBTZWNvbmQgY2FsbCwgc3RhY2sgaGFzIGJlZW4gY3JlYXRlZFxuICAgICAgLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoKCkgPT4gKHtcbiAgICAgICAgU3RhY2tzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgU3RhY2tTdGF0dXM6ICdDUkVBVEVfQ09NUExFVEUnLFxuICAgICAgICAgICAgU3RhY2tTdGF0dXNSZWFzb246ICdJdCBpcyBtYWdpYycsXG4gICAgICAgICAgICBFbmFibGVUZXJtaW5hdGlvblByb3RlY3Rpb246IGZhbHNlLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KSksXG4gICAgY3JlYXRlQ2hhbmdlU2V0OiBqZXN0LmZuKChfbykgPT4gKHt9KSksXG4gICAgZGVsZXRlQ2hhbmdlU2V0OiBqZXN0LmZuKChfbykgPT4gKHt9KSksXG4gICAgZGVzY3JpYmVDaGFuZ2VTZXQ6IGplc3QuZm4oKF9vKSA9PiAoe1xuICAgICAgU3RhdHVzOiAnQ1JFQVRFX0NPTVBMRVRFJyxcbiAgICAgIENoYW5nZXM6IFtdLFxuICAgIH0pKSxcbiAgICBleGVjdXRlQ2hhbmdlU2V0OiBqZXN0LmZuKChfbykgPT4gKHt9KSksXG4gICAgZGVsZXRlU3RhY2s6IGplc3QuZm4oKF9vKSA9PiAoe30pKSxcbiAgICBnZXRUZW1wbGF0ZTogamVzdC5mbigoX28pID0+ICh7IFRlbXBsYXRlQm9keTogSlNPTi5zdHJpbmdpZnkoREVGQVVMVF9GQUtFX1RFTVBMQVRFKSB9KSksXG4gICAgdXBkYXRlVGVybWluYXRpb25Qcm90ZWN0aW9uOiBqZXN0LmZuKChfbykgPT4gKHsgU3RhY2tJZDogJ3N0YWNrLWlkJyB9KSksXG4gIH07XG4gIHNkay5zdHViQ2xvdWRGb3JtYXRpb24oY2ZuTW9ja3MgYXMgYW55KTtcblxufSk7XG5cbmZ1bmN0aW9uIHN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSB7XG4gIHJldHVybiB7XG4gICAgc3RhY2s6IEZBS0VfU1RBQ0ssXG4gICAgc2RrLFxuICAgIHNka1Byb3ZpZGVyLFxuICAgIHJlc29sdmVkRW52aXJvbm1lbnQ6IG1vY2tSZXNvbHZlZEVudmlyb25tZW50KCksXG4gICAgdG9vbGtpdEluZm86IFRvb2xraXRJbmZvLmJvb3RzdHJhcGxlc3NEZXBsb3ltZW50c09ubHkoc2RrKSxcbiAgfTtcbn1cblxudGVzdCgnZG8gZGVwbG95IGV4ZWN1dGFibGUgY2hhbmdlIHNldCB3aXRoIDAgY2hhbmdlcycsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBjb25zdCByZXQgPSBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChyZXQubm9PcCkudG9CZUZhbHN5KCk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG59KTtcblxudGVzdCgnY29ycmVjdGx5IHBhc3NlcyBDRk4gcGFyYW1ldGVycywgaWdub3Jpbmcgb25lcyB3aXRoIGVtcHR5IHZhbHVlcycsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgIEE6ICdBLXZhbHVlJyxcbiAgICAgIEI6ICdCPXZhbHVlJyxcbiAgICAgIEM6IHVuZGVmaW5lZCxcbiAgICAgIEQ6ICcnLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmNyZWF0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgIFBhcmFtZXRlcnM6IFtcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnQScsIFBhcmFtZXRlclZhbHVlOiAnQS12YWx1ZScgfSxcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnQicsIFBhcmFtZXRlclZhbHVlOiAnQj12YWx1ZScgfSxcbiAgICBdLFxuICB9KSk7XG59KTtcblxudGVzdCgncmV1c2UgcHJldmlvdXMgcGFyYW1ldGVycyBpZiByZXF1ZXN0ZWQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFBhcmFtZXRlcnM6IFtcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnSGFzVmFsdWUnLCBQYXJhbWV0ZXJWYWx1ZTogJ1RoZVZhbHVlJyB9LFxuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNEZWZhdWx0JywgUGFyYW1ldGVyVmFsdWU6ICdUaGVPbGRWYWx1ZScgfSxcbiAgICBdLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gICAgc3RhY2s6IEZBS0VfU1RBQ0tfV0lUSF9QQVJBTUVURVJTLFxuICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgIE90aGVyUGFyYW1ldGVyOiAnU29tZVZhbHVlJyxcbiAgICB9LFxuICAgIHVzZVByZXZpb3VzUGFyYW1ldGVyczogdHJ1ZSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuY3JlYXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7XG4gICAgUGFyYW1ldGVyczogW1xuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNWYWx1ZScsIFVzZVByZXZpb3VzVmFsdWU6IHRydWUgfSxcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnSGFzRGVmYXVsdCcsIFVzZVByZXZpb3VzVmFsdWU6IHRydWUgfSxcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnT3RoZXJQYXJhbWV0ZXInLCBQYXJhbWV0ZXJWYWx1ZTogJ1NvbWVWYWx1ZScgfSxcbiAgICBdLFxuICB9KSk7XG59KTtcblxudGVzdCgnZG8gbm90IHJldXNlIHByZXZpb3VzIHBhcmFtZXRlcnMgaWYgbm90IHJlcXVlc3RlZCcsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cyh7XG4gICAgUGFyYW1ldGVyczogW1xuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNWYWx1ZScsIFBhcmFtZXRlclZhbHVlOiAnVGhlVmFsdWUnIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ0hhc0RlZmF1bHQnLCBQYXJhbWV0ZXJWYWx1ZTogJ1RoZU9sZFZhbHVlJyB9LFxuICAgIF0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICBzdGFjazogRkFLRV9TVEFDS19XSVRIX1BBUkFNRVRFUlMsXG4gICAgcGFyYW1ldGVyczoge1xuICAgICAgSGFzVmFsdWU6ICdTb21lVmFsdWUnLFxuICAgICAgT3RoZXJQYXJhbWV0ZXI6ICdTb21lVmFsdWUnLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmNyZWF0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgIFBhcmFtZXRlcnM6IFtcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnSGFzVmFsdWUnLCBQYXJhbWV0ZXJWYWx1ZTogJ1NvbWVWYWx1ZScgfSxcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnT3RoZXJQYXJhbWV0ZXInLCBQYXJhbWV0ZXJWYWx1ZTogJ1NvbWVWYWx1ZScgfSxcbiAgICBdLFxuICB9KSk7XG59KTtcblxudGVzdCgndGhyb3cgZXhjZXB0aW9uIGlmIG5vdCBlbm91Z2ggcGFyYW1ldGVycyBzdXBwbGllZCcsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cyh7XG4gICAgUGFyYW1ldGVyczogW1xuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNWYWx1ZScsIFBhcmFtZXRlclZhbHVlOiAnVGhlVmFsdWUnIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ0hhc0RlZmF1bHQnLCBQYXJhbWV0ZXJWYWx1ZTogJ1RoZU9sZFZhbHVlJyB9LFxuICAgIF0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZXhwZWN0KGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gICAgc3RhY2s6IEZBS0VfU1RBQ0tfV0lUSF9QQVJBTUVURVJTLFxuICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgIE90aGVyUGFyYW1ldGVyOiAnU29tZVZhbHVlJyxcbiAgICB9LFxuICB9KSkucmVqZWN0cy50b1Rocm93KC9DbG91ZEZvcm1hdGlvbiBQYXJhbWV0ZXJzIGFyZSBtaXNzaW5nIGEgdmFsdWUvKTtcbn0pO1xuXG50ZXN0KCdkZXBsb3kgaXMgc2tpcHBlZCBpZiB0ZW1wbGF0ZSBkaWQgbm90IGNoYW5nZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cygpO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuZXhlY3V0ZUNoYW5nZVNldCkubm90LnRvQmVDYWxsZWQoKTtcbn0pO1xuXG50ZXN0KCdkZXBsb3kgaXMgc2tpcHBlZCBpZiBwYXJhbWV0ZXJzIGFyZSB0aGUgc2FtZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5UZW1wbGF0ZUlzKEZBS0VfU1RBQ0tfV0lUSF9QQVJBTUVURVJTLnRlbXBsYXRlKTtcbiAgZ2l2ZW5TdGFja0V4aXN0cyh7XG4gICAgUGFyYW1ldGVyczogW1xuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNWYWx1ZScsIFBhcmFtZXRlclZhbHVlOiAnSGFzVmFsdWUnIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ0hhc0RlZmF1bHQnLCBQYXJhbWV0ZXJWYWx1ZTogJ0hhc0RlZmF1bHQnIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ090aGVyUGFyYW1ldGVyJywgUGFyYW1ldGVyVmFsdWU6ICdPdGhlclBhcmFtZXRlcicgfSxcbiAgICBdLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gICAgc3RhY2s6IEZBS0VfU1RBQ0tfV0lUSF9QQVJBTUVURVJTLFxuICAgIHBhcmFtZXRlcnM6IHt9LFxuICAgIHVzZVByZXZpb3VzUGFyYW1ldGVyczogdHJ1ZSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuY3JlYXRlQ2hhbmdlU2V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2RlcGxveSBpcyBub3Qgc2tpcHBlZCBpZiBwYXJhbWV0ZXJzIGFyZSBkaWZmZXJlbnQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuVGVtcGxhdGVJcyhGQUtFX1NUQUNLX1dJVEhfUEFSQU1FVEVSUy50ZW1wbGF0ZSk7XG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFBhcmFtZXRlcnM6IFtcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnSGFzVmFsdWUnLCBQYXJhbWV0ZXJWYWx1ZTogJ0hhc1ZhbHVlJyB9LFxuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNEZWZhdWx0JywgUGFyYW1ldGVyVmFsdWU6ICdIYXNEZWZhdWx0JyB9LFxuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdPdGhlclBhcmFtZXRlcicsIFBhcmFtZXRlclZhbHVlOiAnT3RoZXJQYXJhbWV0ZXInIH0sXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIHN0YWNrOiBGQUtFX1NUQUNLX1dJVEhfUEFSQU1FVEVSUyxcbiAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICBIYXNWYWx1ZTogJ05ld1ZhbHVlJyxcbiAgICB9LFxuICAgIHVzZVByZXZpb3VzUGFyYW1ldGVyczogdHJ1ZSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuY3JlYXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7XG4gICAgUGFyYW1ldGVyczogW1xuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNWYWx1ZScsIFBhcmFtZXRlclZhbHVlOiAnTmV3VmFsdWUnIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ0hhc0RlZmF1bHQnLCBVc2VQcmV2aW91c1ZhbHVlOiB0cnVlIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ090aGVyUGFyYW1ldGVyJywgVXNlUHJldmlvdXNWYWx1ZTogdHJ1ZSB9LFxuICAgIF0sXG4gIH0pKTtcbn0pO1xuXG50ZXN0KCdpZiBleGlzdGluZyBzdGFjayBmYWlsZWQgdG8gY3JlYXRlLCBpdCBpcyBkZWxldGVkIGFuZCByZWNyZWF0ZWQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoXG4gICAgeyBTdGFja1N0YXR1czogJ1JPTExCQUNLX0NPTVBMRVRFJyB9LCAvLyBUaGlzIGlzIGZvciB0aGUgaW5pdGlhbCBjaGVja1xuICAgIHsgU3RhY2tTdGF0dXM6ICdERUxFVEVfQ09NUExFVEUnIH0sIC8vIFBvbGwgdGhlIHN1Y2Nlc3NmdWwgZGVsZXRpb25cbiAgICB7IFN0YWNrU3RhdHVzOiAnQ1JFQVRFX0NPTVBMRVRFJyB9LCAvLyBQb2xsIHRoZSByZWNyZWF0aW9uXG4gICk7XG4gIGdpdmVuVGVtcGxhdGVJcyh7XG4gICAgRGlmZmVyZW50VGhhbjogJ1RoZURlZmF1bHQnLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmRlbGV0ZVN0YWNrKS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICBDaGFuZ2VTZXRUeXBlOiAnQ1JFQVRFJyxcbiAgfSkpO1xufSk7XG5cbnRlc3QoJ2lmIGV4aXN0aW5nIHN0YWNrIGZhaWxlZCB0byBjcmVhdGUsIGl0IGlzIGRlbGV0ZWQgYW5kIHJlY3JlYXRlZCBldmVuIGlmIHRoZSB0ZW1wbGF0ZSBkaWQgbm90IGNoYW5nZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cyhcbiAgICB7IFN0YWNrU3RhdHVzOiAnUk9MTEJBQ0tfQ09NUExFVEUnIH0sIC8vIFRoaXMgaXMgZm9yIHRoZSBpbml0aWFsIGNoZWNrXG4gICAgeyBTdGFja1N0YXR1czogJ0RFTEVURV9DT01QTEVURScgfSwgLy8gUG9sbCB0aGUgc3VjY2Vzc2Z1bCBkZWxldGlvblxuICAgIHsgU3RhY2tTdGF0dXM6ICdDUkVBVEVfQ09NUExFVEUnIH0sIC8vIFBvbGwgdGhlIHJlY3JlYXRpb25cbiAgKTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmRlbGV0ZVN0YWNrKS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICBDaGFuZ2VTZXRUeXBlOiAnQ1JFQVRFJyxcbiAgfSkpO1xufSk7XG5cbnRlc3QoJ2RlcGxveSBub3Qgc2tpcHBlZCBpZiB0ZW1wbGF0ZSBkaWQgbm90IGNoYW5nZSBhbmQgLS1mb3JjZSBpcyBhcHBsaWVkJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBnaXZlblN0YWNrRXhpc3RzKCk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIGZvcmNlOiB0cnVlLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG59KTtcblxudGVzdCgnZGVwbG95IGlzIHNraXBwZWQgaWYgdGVtcGxhdGUgYW5kIHRhZ3MgZGlkIG5vdCBjaGFuZ2UnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFRhZ3M6IFtcbiAgICAgIHsgS2V5OiAnS2V5MScsIFZhbHVlOiAnVmFsdWUxJyB9LFxuICAgICAgeyBLZXk6ICdLZXkyJywgVmFsdWU6ICdWYWx1ZTInIH0sXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIHRhZ3M6IFtcbiAgICAgIHsgS2V5OiAnS2V5MScsIFZhbHVlOiAnVmFsdWUxJyB9LFxuICAgICAgeyBLZXk6ICdLZXkyJywgVmFsdWU6ICdWYWx1ZTInIH0sXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuY3JlYXRlQ2hhbmdlU2V0KS5ub3QudG9CZUNhbGxlZCgpO1xuICBleHBlY3QoY2ZuTW9ja3MuZXhlY3V0ZUNoYW5nZVNldCkubm90LnRvQmVDYWxsZWQoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmRlc2NyaWJlU3RhY2tzKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7IFN0YWNrTmFtZTogJ3dpdGhvdXRlcnJvcnMnIH0pO1xuICBleHBlY3QoY2ZuTW9ja3MuZ2V0VGVtcGxhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHsgU3RhY2tOYW1lOiAnd2l0aG91dGVycm9ycycsIFRlbXBsYXRlU3RhZ2U6ICdPcmlnaW5hbCcgfSk7XG59KTtcblxudGVzdCgnZGVwbG95IG5vdCBza2lwcGVkIGlmIHRlbXBsYXRlIGRpZCBub3QgY2hhbmdlIGJ1dCB0YWdzIGNoYW5nZWQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFRhZ3M6IFtcbiAgICAgIHsgS2V5OiAnS2V5JywgVmFsdWU6ICdWYWx1ZScgfSxcbiAgICBdLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICBzdGFjazogRkFLRV9TVEFDSyxcbiAgICBzZGssXG4gICAgc2RrUHJvdmlkZXIsXG4gICAgcmVzb2x2ZWRFbnZpcm9ubWVudDogbW9ja1Jlc29sdmVkRW52aXJvbm1lbnQoKSxcbiAgICB0YWdzOiBbXG4gICAgICB7XG4gICAgICAgIEtleTogJ0tleScsXG4gICAgICAgIFZhbHVlOiAnTmV3VmFsdWUnLFxuICAgICAgfSxcbiAgICBdLFxuICAgIHRvb2xraXRJbmZvOiBUb29sa2l0SW5mby5ib290c3RyYXBsZXNzRGVwbG95bWVudHNPbmx5KHNkayksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmNyZWF0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICBleHBlY3QoY2ZuTW9ja3MuZXhlY3V0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICBleHBlY3QoY2ZuTW9ja3MuZGVzY3JpYmVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmRlc2NyaWJlU3RhY2tzKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7IFN0YWNrTmFtZTogJ3dpdGhvdXRlcnJvcnMnIH0pO1xuICBleHBlY3QoY2ZuTW9ja3MuZ2V0VGVtcGxhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHsgU3RhY2tOYW1lOiAnd2l0aG91dGVycm9ycycsIFRlbXBsYXRlU3RhZ2U6ICdPcmlnaW5hbCcgfSk7XG59KTtcblxudGVzdCgnZGVwbG95U3RhY2sgcmVwb3J0cyBubyBjaGFuZ2UgaWYgZGVzY3JpYmVDaGFuZ2VTZXQgcmV0dXJucyBzcGVjaWZpYyBlcnJvcicsIGFzeW5jICgpID0+IHtcbiAgY2ZuTW9ja3MuZGVzY3JpYmVDaGFuZ2VTZXQ/Lm1vY2tJbXBsZW1lbnRhdGlvbigoKSA9PiAoe1xuICAgIFN0YXR1czogJ0ZBSUxFRCcsXG4gICAgU3RhdHVzUmVhc29uOiAnTm8gdXBkYXRlcyBhcmUgdG8gYmUgcGVyZm9ybWVkLicsXG4gIH0pKTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IGRlcGxveVJlc3VsdCA9IGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGRlcGxveVJlc3VsdC5ub09wKS50b0VxdWFsKHRydWUpO1xufSk7XG5cbnRlc3QoJ2RlcGxveSBub3Qgc2tpcHBlZCBpZiB0ZW1wbGF0ZSBkaWQgbm90IGNoYW5nZSBidXQgb25lIHRhZyByZW1vdmVkJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBnaXZlblN0YWNrRXhpc3RzKHtcbiAgICBUYWdzOiBbXG4gICAgICB7IEtleTogJ0tleTEnLCBWYWx1ZTogJ1ZhbHVlMScgfSxcbiAgICAgIHsgS2V5OiAnS2V5MicsIFZhbHVlOiAnVmFsdWUyJyB9LFxuICAgIF0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICB0YWdzOiBbXG4gICAgICB7IEtleTogJ0tleTEnLCBWYWx1ZTogJ1ZhbHVlMScgfSxcbiAgICBdLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmV4ZWN1dGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmRlc2NyaWJlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5kZXNjcmliZVN0YWNrcykudG9IYXZlQmVlbkNhbGxlZFdpdGgoeyBTdGFja05hbWU6ICd3aXRob3V0ZXJyb3JzJyB9KTtcbiAgZXhwZWN0KGNmbk1vY2tzLmdldFRlbXBsYXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7IFN0YWNrTmFtZTogJ3dpdGhvdXRlcnJvcnMnLCBUZW1wbGF0ZVN0YWdlOiAnT3JpZ2luYWwnIH0pO1xufSk7XG5cbnRlc3QoJ2RlcGxveSBpcyBub3Qgc2tpcHBlZCBpZiBzdGFjayBpcyBpbiBhIF9GQUlMRUQgc3RhdGUnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFN0YWNrU3RhdHVzOiAnREVMRVRFX0ZBSUxFRCcsXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICB1c2VQcmV2aW91c1BhcmFtZXRlcnM6IHRydWUsXG4gIH0pLmNhdGNoKCgpID0+IHt9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbn0pO1xuXG50ZXN0KCdleGlzdGluZyBzdGFjayBpbiBVUERBVEVfUk9MTEJBQ0tfQ09NUExFVEUgc3RhdGUgY2FuIGJlIHVwZGF0ZWQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoXG4gICAgeyBTdGFja1N0YXR1czogJ1VQREFURV9ST0xMQkFDS19DT01QTEVURScgfSwgLy8gVGhpcyBpcyBmb3IgdGhlIGluaXRpYWwgY2hlY2tcbiAgICB7IFN0YWNrU3RhdHVzOiAnVVBEQVRFX0NPTVBMRVRFJyB9LCAvLyBQb2xsIHRoZSB1cGRhdGVcbiAgKTtcbiAgZ2l2ZW5UZW1wbGF0ZUlzKHsgY2hhbmdlZDogMTIzIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuZGVsZXRlU3RhY2spLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICBDaGFuZ2VTZXRUeXBlOiAnVVBEQVRFJyxcbiAgfSkpO1xufSk7XG5cbnRlc3QoJ2RlcGxveSBub3Qgc2tpcHBlZCBpZiB0ZW1wbGF0ZSBjaGFuZ2VkJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBnaXZlblN0YWNrRXhpc3RzKCk7XG4gIGdpdmVuVGVtcGxhdGVJcyh7IGNoYW5nZWQ6IDEyMyB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmV4ZWN1dGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbn0pO1xuXG50ZXN0KCdub3QgZXhlY3V0ZWQgYW5kIG5vIGVycm9yIGlmIC0tbm8tZXhlY3V0ZSBpcyBnaXZlbicsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIGV4ZWN1dGU6IGZhbHNlLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2VtcHR5IGNoYW5nZSBzZXQgaXMgZGVsZXRlZCBpZiAtLWV4ZWN1dGUgaXMgZ2l2ZW4nLCBhc3luYyAoKSA9PiB7XG4gIGNmbk1vY2tzLmRlc2NyaWJlQ2hhbmdlU2V0Py5tb2NrSW1wbGVtZW50YXRpb24oKCkgPT4gKHtcbiAgICBTdGF0dXM6ICdGQUlMRUQnLFxuICAgIFN0YXR1c1JlYXNvbjogJ05vIHVwZGF0ZXMgYXJlIHRvIGJlIHBlcmZvcm1lZC4nLFxuICB9KSk7XG5cbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cygpO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICBleGVjdXRlOiB0cnVlLFxuICAgIGZvcmNlOiB0cnVlLCAvLyBOZWNlc3NhcnkgdG8gYnlwYXNzIFwic2tpcCBkZXBsb3lcIlxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmV4ZWN1dGVDaGFuZ2VTZXQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG5cbiAgLy90aGUgZmlyc3QgZGVsZXRpb24gaXMgZm9yIGFueSBleGlzdGluZyBjZGsgY2hhbmdlIHNldHMsIHRoZSBzZWNvbmQgaXMgZm9yIHRoZSBkZWxldGluZyB0aGUgbmV3IGVtcHR5IGNoYW5nZSBzZXRcbiAgZXhwZWN0KGNmbk1vY2tzLmRlbGV0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDIpO1xufSk7XG5cbnRlc3QoJ2VtcHR5IGNoYW5nZSBzZXQgaXMgbm90IGRlbGV0ZWQgaWYgLS1uby1leGVjdXRlIGlzIGdpdmVuJywgYXN5bmMgKCkgPT4ge1xuICBjZm5Nb2Nrcy5kZXNjcmliZUNoYW5nZVNldD8ubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+ICh7XG4gICAgU3RhdHVzOiAnRkFJTEVEJyxcbiAgICBTdGF0dXNSZWFzb246ICdObyB1cGRhdGVzIGFyZSB0byBiZSBwZXJmb3JtZWQuJyxcbiAgfSkpO1xuXG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoKTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gICAgZXhlY3V0ZTogZmFsc2UsXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmNyZWF0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICBleHBlY3QoY2ZuTW9ja3MuZXhlY3V0ZUNoYW5nZVNldCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcblxuICAvL3RoZSBmaXJzdCBkZWxldGlvbiBpcyBmb3IgYW55IGV4aXN0aW5nIGNkayBjaGFuZ2Ugc2V0c1xuICBleHBlY3QoY2ZuTW9ja3MuZGVsZXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkVGltZXMoMSk7XG59KTtcblxudGVzdCgndXNlIFMzIHVybCBmb3Igc3RhY2sgZGVwbG95bWVudCBpZiBwcmVzZW50IGluIFN0YWNrIEFydGlmYWN0JywgYXN5bmMgKCkgPT4ge1xuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gICAgc3RhY2s6IHRlc3RTdGFjayh7XG4gICAgICBzdGFja05hbWU6ICd3aXRob3V0ZXJyb3JzJyxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgc3RhY2tUZW1wbGF0ZUFzc2V0T2JqZWN0VXJsOiAnaHR0cHM6Ly91c2UtbWUtdXNlLW1lLycsXG4gICAgICB9LFxuICAgIH0pLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICBUZW1wbGF0ZVVSTDogJ2h0dHBzOi8vdXNlLW1lLXVzZS1tZS8nLFxuICB9KSk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG59KTtcblxudGVzdCgndXNlIFJFU1QgQVBJIFMzIHVybCB3aXRoIHN1YnN0aXR1dGVkIHBsYWNlaG9sZGVycyBpZiBtYW5pZmVzdCB1cmwgc3RhcnRzIHdpdGggczM6Ly8nLCBhc3luYyAoKSA9PiB7XG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICBzdGFjazogdGVzdFN0YWNrKHtcbiAgICAgIHN0YWNrTmFtZTogJ3dpdGhvdXRlcnJvcnMnLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBzdGFja1RlbXBsYXRlQXNzZXRPYmplY3RVcmw6ICdzMzovL3VzZS1tZS11c2UtbWUtJHtBV1M6OkFjY291bnRJZH0vb2JqZWN0JyxcbiAgICAgIH0sXG4gICAgfSksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmNyZWF0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgIFRlbXBsYXRlVVJMOiAnaHR0cHM6Ly9zMy5iZXJtdWRhLXRyaWFuZ2xlLTEzMzcuYW1hem9uYXdzLmNvbS91c2UtbWUtdXNlLW1lLTEyMzQ1Njc4OS9vYmplY3QnLFxuICB9KSk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG59KTtcblxudGVzdCgnY2hhbmdlc2V0IGlzIGNyZWF0ZWQgd2hlbiBzdGFjayBleGlzdHMgaW4gUkVWSUVXX0lOX1BST0dSRVNTIHN0YXR1cycsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cyh7XG4gICAgU3RhY2tTdGF0dXM6ICdSRVZJRVdfSU5fUFJPR1JFU1MnLFxuICAgIFRhZ3M6IFtcbiAgICAgIHsgS2V5OiAnS2V5MScsIFZhbHVlOiAnVmFsdWUxJyB9LFxuICAgICAgeyBLZXk6ICdLZXkyJywgVmFsdWU6ICdWYWx1ZTInIH0sXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIGV4ZWN1dGU6IGZhbHNlLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICAgIENoYW5nZVNldFR5cGU6ICdDUkVBVEUnLFxuICAgICAgU3RhY2tOYW1lOiAnd2l0aG91dGVycm9ycycsXG4gICAgfSksXG4gICk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2NoYW5nZXNldCBpcyB1cGRhdGVkIHdoZW4gc3RhY2sgZXhpc3RzIGluIENSRUFURV9DT01QTEVURSBzdGF0dXMnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFRhZ3M6IFtcbiAgICAgIHsgS2V5OiAnS2V5MScsIFZhbHVlOiAnVmFsdWUxJyB9LFxuICAgICAgeyBLZXk6ICdLZXkyJywgVmFsdWU6ICdWYWx1ZTInIH0sXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIGV4ZWN1dGU6IGZhbHNlLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICAgIENoYW5nZVNldFR5cGU6ICdVUERBVEUnLFxuICAgICAgU3RhY2tOYW1lOiAnd2l0aG91dGVycm9ycycsXG4gICAgfSksXG4gICk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2RlcGxveSB3aXRoIHRlcm1pbmF0aW9uIHByb3RlY3Rpb24gZW5hYmxlZCcsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIHN0YWNrOiBGQUtFX1NUQUNLX1RFUk1JTkFUSU9OX1BST1RFQ1RJT04sXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLnVwZGF0ZVRlcm1pbmF0aW9uUHJvdGVjdGlvbikudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgIEVuYWJsZVRlcm1pbmF0aW9uUHJvdGVjdGlvbjogdHJ1ZSxcbiAgfSkpO1xufSk7XG5cbnRlc3QoJ3VwZGF0ZVRlcm1pbmF0aW9uUHJvdGVjdGlvbiBub3QgY2FsbGVkIHdoZW4gdGVybWluYXRpb24gcHJvdGVjdGlvbiBpcyB1bmRlZmluZWQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MudXBkYXRlVGVybWluYXRpb25Qcm90ZWN0aW9uKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ3VwZGF0ZVRlcm1pbmF0aW9uUHJvdGVjdGlvbiBjYWxsZWQgd2hlbiB0ZXJtaW5hdGlvbiBwcm90ZWN0aW9uIGlzIHVuZGVmaW5lZCBhbmQgc3RhY2sgaGFzIHRlcm1pbmF0aW9uIHByb3RlY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIEVuYWJsZVRlcm1pbmF0aW9uUHJvdGVjdGlvbjogdHJ1ZSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy51cGRhdGVUZXJtaW5hdGlvblByb3RlY3Rpb24pLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICBFbmFibGVUZXJtaW5hdGlvblByb3RlY3Rpb246IGZhbHNlLFxuICB9KSk7XG59KTtcblxuZGVzY3JpYmUoJ2Rpc2FibGUgcm9sbGJhY2snLCAoKSA9PiB7XG4gIHRlc3QoJ2J5IGRlZmF1bHQsIHdlIGRvIG5vdCBkaXNhYmxlIHJvbGxiYWNrIChhbmQgYWxzbyBkbyBub3QgcGFzcyB0aGUgZmxhZyknLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gV0hFTlxuICAgIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICB9KTtcblxuICAgIC8vIFRIRU5cbiAgICBleHBlY3QoY2ZuTW9ja3MuZXhlY3V0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDEpO1xuICAgIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgICAgRGlzYWJsZVJvbGxiYWNrOiBleHBlY3QuYW55dGhpbmcoKSxcbiAgICB9KSk7XG4gIH0pO1xuXG4gIHRlc3QoJ3JvbGxiYWNrIGNhbiBiZSBkaXNhYmxlZCBieSBzZXR0aW5nIHJvbGxiYWNrOiBmYWxzZScsIGFzeW5jICgpID0+IHtcbiAgICAvLyBXSEVOXG4gICAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgICAgcm9sbGJhY2s6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgLy8gVEhFTlxuICAgIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7XG4gICAgICBEaXNhYmxlUm9sbGJhY2s6IHRydWUsXG4gICAgfSkpO1xuICB9KTtcblxufSk7XG5cbi8qKlxuICogU2V0IHVwIHRoZSBtb2NrcyBzbyB0aGF0IGl0IGxvb2tzIGxpa2UgdGhlIHN0YWNrIGV4aXN0cyB0byBzdGFydCB3aXRoXG4gKlxuICogVGhlIGxhc3QgZWxlbWVudCBvZiB0aGlzIGFycmF5IHdpbGwgYmUgY29udGludW91c2x5IHJlcGVhdGVkLlxuICovXG5mdW5jdGlvbiBnaXZlblN0YWNrRXhpc3RzKC4uLm92ZXJyaWRlczogQXJyYXk8UGFydGlhbDxBV1MuQ2xvdWRGb3JtYXRpb24uU3RhY2s+Pikge1xuICBjZm5Nb2Nrcy5kZXNjcmliZVN0YWNrcyEubW9ja1Jlc2V0KCk7XG5cbiAgaWYgKG92ZXJyaWRlcy5sZW5ndGggPT09IDApIHtcbiAgICBvdmVycmlkZXMgPSBbe31dO1xuICB9XG5cbiAgY29uc3QgYmFzZVJlc3BvbnNlID0ge1xuICAgIFN0YWNrTmFtZTogJ21vY2stc3RhY2stbmFtZScsXG4gICAgU3RhY2tJZDogJ21vY2stc3RhY2staWQnLFxuICAgIENyZWF0aW9uVGltZTogbmV3IERhdGUoKSxcbiAgICBTdGFja1N0YXR1czogJ0NSRUFURV9DT01QTEVURScsXG4gICAgRW5hYmxlVGVybWluYXRpb25Qcm90ZWN0aW9uOiBmYWxzZSxcbiAgfTtcblxuICBmb3IgKGNvbnN0IG92ZXJyaWRlIG9mIG92ZXJyaWRlcy5zbGljZSgwLCBvdmVycmlkZXMubGVuZ3RoIC0gMSkpIHtcbiAgICBjZm5Nb2Nrcy5kZXNjcmliZVN0YWNrcyEubW9ja0ltcGxlbWVudGF0aW9uT25jZSgoKSA9PiAoe1xuICAgICAgU3RhY2tzOiBbeyAuLi5iYXNlUmVzcG9uc2UsIC4uLm92ZXJyaWRlIH1dLFxuICAgIH0pKTtcbiAgfVxuICBjZm5Nb2Nrcy5kZXNjcmliZVN0YWNrcyEubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+ICh7XG4gICAgU3RhY2tzOiBbeyAuLi5iYXNlUmVzcG9uc2UsIC4uLm92ZXJyaWRlc1tvdmVycmlkZXMubGVuZ3RoIC0gMV0gfV0sXG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZ2l2ZW5UZW1wbGF0ZUlzKHRlbXBsYXRlOiBhbnkpIHtcbiAgY2ZuTW9ja3MuZ2V0VGVtcGxhdGUhLm1vY2tSZXNldCgpO1xuICBjZm5Nb2Nrcy5nZXRUZW1wbGF0ZSEubW9ja1JldHVyblZhbHVlKHtcbiAgICBUZW1wbGF0ZUJvZHk6IEpTT04uc3RyaW5naWZ5KHRlbXBsYXRlKSxcbiAgfSk7XG59Il19